From a20bc41d54837a0b99ae61b25b349d00c535ced0 Mon Sep 17 00:00:00 2001 From: Andrew McCreight Date: Fri, 6 Sep 2013 16:15:10 -0700 Subject: [PATCH 01/30] Bug 913130, part 1 - Modify nsCycleCollector::Collect to allow it to be used at shutdown. r=smaug --- xpcom/base/nsCycleCollector.cpp | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/xpcom/base/nsCycleCollector.cpp b/xpcom/base/nsCycleCollector.cpp index c0b4bc0bd289..2f42146391e9 100644 --- a/xpcom/base/nsCycleCollector.cpp +++ b/xpcom/base/nsCycleCollector.cpp @@ -967,7 +967,8 @@ private: void ShutdownCollect(nsICycleCollectorListener *aListener); public: - void Collect(ccType aCCType, + bool Collect(ccType aCCType, + nsTArray *aWhiteNodes, nsCycleCollectorResults *aResults, nsICycleCollectorListener *aListener); @@ -2682,25 +2683,24 @@ nsCycleCollector::ShutdownCollect(nsICycleCollectorListener *aListener) CleanupAfterCollection(); } -void +bool nsCycleCollector::Collect(ccType aCCType, + nsTArray *aWhiteNodes, nsCycleCollectorResults *aResults, nsICycleCollectorListener *aListener) { CheckThreadSafety(); - // On a WantAllTraces CC, force a synchronous global GC to prevent - // hijinks from ForgetSkippable and compartmental GCs. - bool wantAllTraces = false; - if (aListener) { - aListener->GetWantAllTraces(&wantAllTraces); + bool forceGC = (aCCType == ShutdownCC); + if (!forceGC && aListener) { + // On a WantAllTraces CC, force a synchronous global GC to prevent + // hijinks from ForgetSkippable and compartmental GCs. + aListener->GetWantAllTraces(&forceGC); } + FixGrayBits(forceGC); - FixGrayBits(wantAllTraces); - - nsAutoTArray whiteNodes; - if (!PrepareForCollection(aResults, &whiteNodes)) { - return; + if (!PrepareForCollection(aResults, aWhiteNodes)) { + return false; } FreeSnowWhite(true); @@ -2710,8 +2710,9 @@ nsCycleCollector::Collect(ccType aCCType, } BeginCollection(aCCType, aListener); - FinishCollection(aListener); + bool collectedAny = FinishCollection(aListener); CleanupAfterCollection(); + return collectedAny; } // Don't merge too many times in a row, and do at least a minimum @@ -3184,7 +3185,9 @@ nsCycleCollector_collect(bool aManuallyTriggered, listener = new nsCycleCollectorLogger(); } - data->mCollector->Collect(aManuallyTriggered ? ManualCC : ScheduledCC, aResults, listener); + nsAutoTArray whiteNodes; + data->mCollector->Collect(aManuallyTriggered ? ManualCC : ScheduledCC, + &whiteNodes, aResults, listener); } void From 8cfa8b27b28322c29103a04bfef05d616b18fc4d Mon Sep 17 00:00:00 2001 From: Andrew McCreight Date: Fri, 6 Sep 2013 16:16:45 -0700 Subject: [PATCH 02/30] Bug 913130, part 2 - Give Collect and ShutdownCollect more consistent ordering. r=smaug --- xpcom/base/nsCycleCollector.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/xpcom/base/nsCycleCollector.cpp b/xpcom/base/nsCycleCollector.cpp index 2f42146391e9..632d881cf93e 100644 --- a/xpcom/base/nsCycleCollector.cpp +++ b/xpcom/base/nsCycleCollector.cpp @@ -2671,9 +2671,12 @@ nsCycleCollector::ShutdownCollect(nsICycleCollectorListener *aListener) // Synchronous cycle collection. Always force a JS GC beforehand. FixGrayBits(true); + + FreeSnowWhite(true); + if (aListener && NS_FAILED(aListener->Begin())) aListener = nullptr; - FreeSnowWhite(true); + BeginCollection(ShutdownCC, aListener); if (!FinishCollection(aListener)) { break; @@ -2691,6 +2694,10 @@ nsCycleCollector::Collect(ccType aCCType, { CheckThreadSafety(); + if (!PrepareForCollection(aResults, aWhiteNodes)) { + return false; + } + bool forceGC = (aCCType == ShutdownCC); if (!forceGC && aListener) { // On a WantAllTraces CC, force a synchronous global GC to prevent @@ -2699,10 +2706,6 @@ nsCycleCollector::Collect(ccType aCCType, } FixGrayBits(forceGC); - if (!PrepareForCollection(aResults, aWhiteNodes)) { - return false; - } - FreeSnowWhite(true); if (aListener && NS_FAILED(aListener->Begin())) { From 916cfd2ccd4a713df9d0f8fb3a5d667abd176685 Mon Sep 17 00:00:00 2001 From: Andrew McCreight Date: Fri, 6 Sep 2013 16:17:03 -0700 Subject: [PATCH 03/30] Bug 913130, part 3 - Run {PrepareFor,CleanupAfter} every iteration of ShutdownCollect. r=smaug --- xpcom/base/nsCycleCollector.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/xpcom/base/nsCycleCollector.cpp b/xpcom/base/nsCycleCollector.cpp index 632d881cf93e..0e89bd4143c6 100644 --- a/xpcom/base/nsCycleCollector.cpp +++ b/xpcom/base/nsCycleCollector.cpp @@ -2663,12 +2663,12 @@ nsCycleCollector::ShutdownCollect(nsICycleCollectorListener *aListener) { nsAutoTArray whiteNodes; - if (!PrepareForCollection(nullptr, &whiteNodes)) - return; - for (uint32_t i = 0; i < DEFAULT_SHUTDOWN_COLLECTIONS; ++i) { NS_ASSERTION(i < NORMAL_SHUTDOWN_COLLECTIONS, "Extra shutdown CC"); + if (!PrepareForCollection(nullptr, &whiteNodes)) + return; + // Synchronous cycle collection. Always force a JS GC beforehand. FixGrayBits(true); @@ -2678,12 +2678,12 @@ nsCycleCollector::ShutdownCollect(nsICycleCollectorListener *aListener) aListener = nullptr; BeginCollection(ShutdownCC, aListener); - if (!FinishCollection(aListener)) { + bool collectedAny = FinishCollection(aListener); + CleanupAfterCollection(); + if (!collectedAny) { break; } } - - CleanupAfterCollection(); } bool From 0e792ce8b7eae9c46d4cf3b2bd121e368a2ed094 Mon Sep 17 00:00:00 2001 From: Andrew McCreight Date: Fri, 6 Sep 2013 16:17:53 -0700 Subject: [PATCH 04/30] Bug 913130, part 4 - Replace body of ShutdownCollect loop with Collect. r=smaug --- xpcom/base/nsCycleCollector.cpp | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/xpcom/base/nsCycleCollector.cpp b/xpcom/base/nsCycleCollector.cpp index 0e89bd4143c6..91012304dc23 100644 --- a/xpcom/base/nsCycleCollector.cpp +++ b/xpcom/base/nsCycleCollector.cpp @@ -2665,22 +2665,7 @@ nsCycleCollector::ShutdownCollect(nsICycleCollectorListener *aListener) for (uint32_t i = 0; i < DEFAULT_SHUTDOWN_COLLECTIONS; ++i) { NS_ASSERTION(i < NORMAL_SHUTDOWN_COLLECTIONS, "Extra shutdown CC"); - - if (!PrepareForCollection(nullptr, &whiteNodes)) - return; - - // Synchronous cycle collection. Always force a JS GC beforehand. - FixGrayBits(true); - - FreeSnowWhite(true); - - if (aListener && NS_FAILED(aListener->Begin())) - aListener = nullptr; - - BeginCollection(ShutdownCC, aListener); - bool collectedAny = FinishCollection(aListener); - CleanupAfterCollection(); - if (!collectedAny) { + if (!Collect(ShutdownCC, &whiteNodes, nullptr, aListener)) { break; } } From 383e668837e18958c39796acc679bf25e492b4fc Mon Sep 17 00:00:00 2001 From: Monica Chew Date: Fri, 6 Sep 2013 17:12:33 -0700 Subject: [PATCH 05/30] Bug 904607: Add protocol parser for -digest256 lists (r=gcp). --- netwerk/base/public/nsIURIClassifier.idl | 2 +- toolkit/components/url-classifier/ChunkSet.h | 7 +- .../components/url-classifier/Classifier.cpp | 15 +- toolkit/components/url-classifier/Entries.h | 56 +++++-- .../components/url-classifier/HashStore.cpp | 18 ++- toolkit/components/url-classifier/HashStore.h | 32 +++- .../components/url-classifier/LookupCache.cpp | 2 +- .../url-classifier/ProtocolParser.cpp | 101 ++++++++++-- .../url-classifier/ProtocolParser.h | 16 +- .../url-classifier/content/listmanager.js | 1 + .../nsIUrlClassifierDBService.idl | 4 +- .../nsIUrlClassifierHashCompleter.idl | 8 +- .../nsIUrlClassifierStreamUpdater.idl | 1 + .../nsUrlClassifierDBService.cpp | 10 +- .../url-classifier/nsUrlClassifierDBService.h | 3 +- .../nsUrlClassifierStreamUpdater.cpp | 12 +- .../nsUrlClassifierStreamUpdater.h | 3 + .../tests/unit/data/digest1.chunk | Bin 0 -> 939 bytes .../tests/unit/data/digest2.chunk | 2 + .../tests/unit/test_digest256.js | 144 ++++++++++++++++++ .../url-classifier/tests/unit/xpcshell.ini | 1 + 21 files changed, 379 insertions(+), 59 deletions(-) create mode 100644 toolkit/components/url-classifier/tests/unit/data/digest1.chunk create mode 100644 toolkit/components/url-classifier/tests/unit/data/digest2.chunk create mode 100644 toolkit/components/url-classifier/tests/unit/test_digest256.js diff --git a/netwerk/base/public/nsIURIClassifier.idl b/netwerk/base/public/nsIURIClassifier.idl index 577424c826ce..3d23a95d4a18 100644 --- a/netwerk/base/public/nsIURIClassifier.idl +++ b/netwerk/base/public/nsIURIClassifier.idl @@ -34,7 +34,7 @@ interface nsIURIClassifierCallback : nsISupports interface nsIURIClassifier : nsISupports { /** - * Classify a Principal using it's URI, appId and InBrowserElement state. + * Classify a Principal using its URI. * * @param aPrincipal * The principal that should be checked by the URI classifier. diff --git a/toolkit/components/url-classifier/ChunkSet.h b/toolkit/components/url-classifier/ChunkSet.h index 86164d329739..a39574c32022 100644 --- a/toolkit/components/url-classifier/ChunkSet.h +++ b/toolkit/components/url-classifier/ChunkSet.h @@ -15,9 +15,10 @@ namespace mozilla { namespace safebrowsing { /** - * Store the chunks as an array of uint32_t. - * XXX: We should optimize this further to compress the - * many consecutive numbers. + * Store the chunk numbers as an array of uint32_t. We need chunk numbers in + * order to ask for incremental updates from the server. + * XXX: We should optimize this further to compress the many consecutive + * numbers. */ class ChunkSet { public: diff --git a/toolkit/components/url-classifier/Classifier.cpp b/toolkit/components/url-classifier/Classifier.cpp index d4daa366aa25..e1fcb1a62d25 100644 --- a/toolkit/components/url-classifier/Classifier.cpp +++ b/toolkit/components/url-classifier/Classifier.cpp @@ -199,7 +199,9 @@ Classifier::Check(const nsACString& aSpec, LookupResultArray& aResults) { Telemetry::AutoTimer timer; - // Get the set of fragments to look up. + // Get the set of fragments based on the url. This is necessary because we + // only look up at most 5 URLs per aSpec, even if aSpec has more than 5 + // components. nsTArray fragments; nsresult rv = LookupCache::GetLookupFragments(aSpec, &fragments); NS_ENSURE_SUCCESS(rv, rv); @@ -226,15 +228,16 @@ Classifier::Check(const nsACString& aSpec, LookupResultArray& aResults) Completion hostKey; rv = LookupCache::GetKey(fragments[i], &hostKey, mCryptoHash); if (NS_FAILED(rv)) { - // Local host on the network + // Local host on the network. continue; } #if DEBUG && defined(PR_LOGGING) if (LOG_ENABLED()) { nsAutoCString checking; - lookupHash.ToString(checking); - LOG(("Checking %s (%X)", checking.get(), lookupHash.ToUint32())); + lookupHash.ToHexString(checking); + LOG(("Checking fragment %s, hash %s (%X)", fragments[i].get(), + checking.get(), lookupHash.ToUint32())); } #endif for (uint32_t i = 0; i < cacheArray.Length(); i++) { @@ -542,8 +545,7 @@ nsresult Classifier::ApplyTableUpdates(nsTArray* aUpdates, const nsACString& aTable) { - LOG(("Classifier::ApplyTableUpdates(%s)", - PromiseFlatCString(aTable).get())); + LOG(("Classifier::ApplyTableUpdates(%s)", PromiseFlatCString(aTable).get())); nsAutoPtr store(new HashStore(aTable, mStoreDirectory)); @@ -567,6 +569,7 @@ Classifier::ApplyTableUpdates(nsTArray* aUpdates, } if (!validupdates) { + // This can happen if the update was only valid for one table. return NS_OK; } diff --git a/toolkit/components/url-classifier/Entries.h b/toolkit/components/url-classifier/Entries.h index 3a03a28db543..efc390557eea 100644 --- a/toolkit/components/url-classifier/Entries.h +++ b/toolkit/components/url-classifier/Entries.h @@ -3,6 +3,10 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +// This header file defines the storage types of the actual safebrowsing +// chunk data, which may be either 32-bit hashes or complete 256-bit hashes. +// Chunk numbers are represented in ChunkSet.h. + #ifndef SBEntries_h__ #define SBEntries_h__ @@ -21,6 +25,7 @@ namespace safebrowsing { #define PREFIX_SIZE 4 #define COMPLETE_SIZE 32 +// This is the struct that contains 4-byte hash prefixes. template struct SafebrowsingHash { @@ -82,6 +87,19 @@ struct SafebrowsingHash PL_Base64Encode((char*)buf, sHashSize, aStr.BeginWriting()); aStr.BeginWriting()[len] = '\0'; } + + void ToHexString(nsACString& aStr) const { + static const char* const lut = "0123456789ABCDEF"; + // 32 bytes is the longest hash + size_t len = 32; + + aStr.SetCapacity(2 * len); + for (size_t i = 0; i < len; ++i) { + const char c = static_cast(buf[i]); + aStr.Append(lut[(c >> 4) & 0x0F]); + aStr.Append(lut[c & 15]); + } + } #endif uint32_t ToUint32() const { return *((uint32_t*)buf); @@ -105,6 +123,7 @@ public: } } }; +// Use this for 4-byte hashes typedef SafebrowsingHash Prefix; typedef nsTArray PrefixArray; @@ -114,15 +133,19 @@ public: return memcmp(a, b, COMPLETE_SIZE); } }; +// Use this for 32-byte hashes typedef SafebrowsingHash Completion; typedef nsTArray CompletionArray; struct AddPrefix { + // The truncated hash. Prefix prefix; + // The chunk number to which it belongs. uint32_t addChunk; AddPrefix() : addChunk(0) {} + // Returns the chunk number. uint32_t Chunk() const { return addChunk; } const Prefix &PrefixHash() const { return prefix; } @@ -137,21 +160,20 @@ struct AddPrefix { }; struct AddComplete { - union { - Prefix prefix; - Completion complete; - } hash; + Completion complete; uint32_t addChunk; AddComplete() : addChunk(0) {} uint32_t Chunk() const { return addChunk; } - const Prefix &PrefixHash() const { return hash.prefix; } - const Completion &CompleteHash() const { return hash.complete; } + // The 4-byte prefix of the sha256 hash. + uint32_t ToUint32() const { return complete.ToUint32(); } + // The 32-byte sha256 hash. + const Completion &CompleteHash() const { return complete; } template int Compare(const T& other) const { - int cmp = hash.complete.Compare(other.CompleteHash()); + int cmp = complete.Compare(other.CompleteHash()); if (cmp != 0) { return cmp; } @@ -160,8 +182,11 @@ struct AddComplete { }; struct SubPrefix { + // The hash to subtract. Prefix prefix; + // The chunk number of the add chunk to which the hash belonged. uint32_t addChunk; + // The chunk number of this sub chunk. uint32_t subChunk; SubPrefix(): addChunk(0), subChunk(0) {} @@ -171,6 +196,7 @@ struct SubPrefix { const Prefix &PrefixHash() const { return prefix; } template + // Returns 0 if and only if the chunks are the same in every way. int Compare(const T& aOther) const { int cmp = prefix.Compare(aOther.PrefixHash()); if (cmp != 0) @@ -182,7 +208,9 @@ struct SubPrefix { template int CompareAlt(const T& aOther) const { - int cmp = prefix.Compare(aOther.PrefixHash()); + Prefix other; + other.FromUint32(aOther.ToUint32()); + int cmp = prefix.Compare(other); if (cmp != 0) return cmp; return addChunk - aOther.addChunk; @@ -190,10 +218,7 @@ struct SubPrefix { }; struct SubComplete { - union { - Prefix prefix; - Completion complete; - } hash; + Completion complete; uint32_t addChunk; uint32_t subChunk; @@ -201,11 +226,12 @@ struct SubComplete { uint32_t Chunk() const { return subChunk; } uint32_t AddChunk() const { return addChunk; } - const Prefix &PrefixHash() const { return hash.prefix; } - const Completion &CompleteHash() const { return hash.complete; } + const Completion &CompleteHash() const { return complete; } + // The 4-byte prefix of the sha256 hash. + uint32_t ToUint32() const { return complete.ToUint32(); } int Compare(const SubComplete& aOther) const { - int cmp = hash.complete.Compare(aOther.hash.complete); + int cmp = complete.Compare(aOther.complete); if (cmp != 0) return cmp; if (addChunk != aOther.addChunk) diff --git a/toolkit/components/url-classifier/HashStore.cpp b/toolkit/components/url-classifier/HashStore.cpp index b44001717c1b..03b1753a7dcc 100644 --- a/toolkit/components/url-classifier/HashStore.cpp +++ b/toolkit/components/url-classifier/HashStore.cpp @@ -146,7 +146,7 @@ TableUpdate::NewAddComplete(uint32_t aAddChunk, const Completion& aHash) { AddComplete *add = mAddCompletes.AppendElement(); add->addChunk = aAddChunk; - add->hash.complete = aHash; + add->complete = aHash; } void @@ -154,7 +154,7 @@ TableUpdate::NewSubComplete(uint32_t aAddChunk, const Completion& aHash, uint32_ { SubComplete *sub = mSubCompletes.AppendElement(); sub->addChunk = aAddChunk; - sub->hash.complete = aHash; + sub->complete = aHash; sub->subChunk = aSubChunk; } @@ -323,6 +323,8 @@ HashStore::CalculateChecksum(nsAutoCString& aChecksum, // Size of MD5 hash in bytes const uint32_t CHECKSUM_SIZE = 16; + // MD5 is not a secure hash function, but since this is a filesystem integrity + // check, this usage is ok. rv = hash->Init(nsICryptoHash::MD5); NS_ENSURE_SUCCESS(rv, rv); @@ -362,9 +364,7 @@ HashStore::UpdateHeader() nsresult HashStore::ReadChunkNumbers() { - if (!mInputStream) { - return NS_OK; - } + NS_ENSURE_STATE(mInputStream); nsCOMPtr seekable = do_QueryInterface(mInputStream); nsresult rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, @@ -385,6 +385,8 @@ nsresult HashStore::ReadHashes() { if (!mInputStream) { + // BeginUpdate has been called but Open hasn't initialized mInputStream, + // because the existing HashStore is empty. return NS_OK; } @@ -819,14 +821,14 @@ HashStore::WriteFile() rv = out->Write(reinterpret_cast(&mHeader), sizeof(mHeader), &written); NS_ENSURE_SUCCESS(rv, rv); - // Write chunk numbers... + // Write chunk numbers. rv = mAddChunks.Write(out); NS_ENSURE_SUCCESS(rv, rv); rv = mSubChunks.Write(out); NS_ENSURE_SUCCESS(rv, rv); - // Write hashes.. + // Write hashes. rv = WriteAddPrefixes(out); NS_ENSURE_SUCCESS(rv, rv); @@ -1002,7 +1004,7 @@ HashStore::ProcessSubs() // Remove any remaining subbed prefixes from both addprefixes // and addcompletes. - KnockoutSubs(&mSubPrefixes, &mAddPrefixes); + KnockoutSubs(&mSubPrefixes, &mAddPrefixes); KnockoutSubs(&mSubCompletes, &mAddCompletes); // Remove any remaining subprefixes referring to addchunks that diff --git a/toolkit/components/url-classifier/HashStore.h b/toolkit/components/url-classifier/HashStore.h index fc49d77809e4..ede320bb9ef2 100644 --- a/toolkit/components/url-classifier/HashStore.h +++ b/toolkit/components/url-classifier/HashStore.h @@ -17,6 +17,9 @@ namespace mozilla { namespace safebrowsing { +// A table update is built from a single update chunk from the server. As the +// protocol parser processes each chunk, it constructs a table update with the +// new hashes. class TableUpdate { public: TableUpdate(const nsACString& aTable) @@ -34,6 +37,8 @@ public: mSubCompletes.Length() == 0; } + // Throughout, uint32_t aChunk refers only to the chunk number. Chunk data is + // stored in the Prefix structures. void NewAddChunk(uint32_t aChunk) { mAddChunks.Set(aChunk); } void NewSubChunk(uint32_t aChunk) { mSubChunks.Set(aChunk); } @@ -42,6 +47,7 @@ public: void NewAddPrefix(uint32_t aAddChunk, const Prefix& aPrefix); void NewSubPrefix(uint32_t aAddChunk, const Prefix& aPrefix, uint32_t aSubChunk); + void NewAddComplete(uint32_t aChunk, const Completion& aCompletion); void NewSubComplete(uint32_t aAddChunk, const Completion& aCompletion, uint32_t aSubChunk); @@ -51,9 +57,11 @@ public: ChunkSet& AddChunks() { return mAddChunks; } ChunkSet& SubChunks() { return mSubChunks; } + // Expirations for chunks. ChunkSet& AddExpirations() { return mAddExpirations; } ChunkSet& SubExpirations() { return mSubExpirations; } + // Hashes associated with this chunk. AddPrefixArray& AddPrefixes() { return mAddPrefixes; } SubPrefixArray& SubPrefixes() { return mSubPrefixes; } AddCompleteArray& AddCompletes() { return mAddCompletes; } @@ -64,16 +72,22 @@ private: // Update not from the remote server (no freshness) bool mLocalUpdate; + // The list of chunk numbers that we have for each of the type of chunks. ChunkSet mAddChunks; ChunkSet mSubChunks; ChunkSet mAddExpirations; ChunkSet mSubExpirations; + + // 4-byte sha256 prefixes. AddPrefixArray mAddPrefixes; SubPrefixArray mSubPrefixes; + + // 32-byte hashes. AddCompleteArray mAddCompletes; SubCompleteArray mSubCompletes; }; +// There is one hash store per table. class HashStore { public: HashStore(const nsACString& aTableName, nsIFile* aStoreFile); @@ -82,6 +96,11 @@ public: const nsCString& TableName() const { return mTableName; } nsresult Open(); + // Add Prefixes are stored partly in the PrefixSet (contains the + // Prefix data organized for fast lookup/low RAM usage) and partly in the + // HashStore (Add Chunk numbers - only used for updates, slow retrieval). + // AugmentAdds function joins the separate datasets into one complete + // prefixes+chunknumbers dataset. nsresult AugmentAdds(const nsTArray& aPrefixes); ChunkSet& AddChunks() { return mAddChunks; } @@ -126,6 +145,7 @@ private: nsresult ReadChunkNumbers(); nsresult ReadHashes(); + nsresult ReadAddPrefixes(); nsresult ReadSubPrefixes(); @@ -134,6 +154,8 @@ private: nsresult ProcessSubs(); + // This is used for checking that the database is correct and for figuring out + // the number of chunks, etc. to read from disk on restart. struct Header { uint32_t magic; uint32_t version; @@ -147,6 +169,8 @@ private: Header mHeader; + // The name of the table (must end in -shavar or -digest256, or evidently + // -simple for unittesting. nsCString mTableName; nsCOMPtr mStoreDirectory; @@ -154,19 +178,23 @@ private: nsCOMPtr mInputStream; + // Chunk numbers, stored as uint32_t arrays. ChunkSet mAddChunks; ChunkSet mSubChunks; ChunkSet mAddExpirations; ChunkSet mSubExpirations; + // Chunk data for shavar tables. See Entries.h for format. AddPrefixArray mAddPrefixes; - AddCompleteArray mAddCompletes; SubPrefixArray mSubPrefixes; + + // See bug 806422 for background. We must be able to distinguish between + // updates from the completion server and updates from the regular server. + AddCompleteArray mAddCompletes; SubCompleteArray mSubCompletes; }; } } - #endif diff --git a/toolkit/components/url-classifier/LookupCache.cpp b/toolkit/components/url-classifier/LookupCache.cpp index 2033d4252134..d3a9058b654e 100644 --- a/toolkit/components/url-classifier/LookupCache.cpp +++ b/toolkit/components/url-classifier/LookupCache.cpp @@ -515,7 +515,7 @@ LookupCache::GetLookupFragments(const nsACString& aSpec, key.Assign(hosts[hostIndex]); key.Append('/'); key.Append(paths[pathIndex]); - LOG(("Chking %s", key.get())); + LOG(("Checking fragment %s", key.get())); aFragments->AppendElement(key); } diff --git a/toolkit/components/url-classifier/ProtocolParser.cpp b/toolkit/components/url-classifier/ProtocolParser.cpp index 542c302ab735..1eea49f46f08 100644 --- a/toolkit/components/url-classifier/ProtocolParser.cpp +++ b/toolkit/components/url-classifier/ProtocolParser.cpp @@ -222,6 +222,7 @@ ProtocolParser::ProcessControl(bool* aDone) rv = ProcessMAC(line); NS_ENSURE_SUCCESS(rv, rv); } else if (StringBeginsWith(line, NS_LITERAL_CSTRING("i:"))) { + // Set the table name from the table header line. SetCurrentTable(Substring(line, 2)); } else if (StringBeginsWith(line, NS_LITERAL_CSTRING("n:"))) { if (PR_sscanf(line.get(), "n:%d", &mUpdateWait) != 1) { @@ -330,12 +331,30 @@ ProtocolParser::ProcessChunkControl(const nsCString& aLine) return NS_ERROR_FAILURE; } - mChunkState.type = (command == 'a') ? CHUNK_ADD : CHUNK_SUB; - - if (mChunkState.type == CHUNK_ADD) { - mTableUpdate->NewAddChunk(mChunkState.num); - } else { - mTableUpdate->NewSubChunk(mChunkState.num); + if (StringEndsWith(mTableUpdate->TableName(), + NS_LITERAL_CSTRING("-shavar")) || + StringEndsWith(mTableUpdate->TableName(), + NS_LITERAL_CSTRING("-simple"))) { + // Accommodate test tables ending in -simple for now. + mChunkState.type = (command == 'a') ? CHUNK_ADD : CHUNK_SUB; + } else if (StringEndsWith(mTableUpdate->TableName(), + NS_LITERAL_CSTRING("-digest256"))) { + LOG(("Processing digest256 data")); + mChunkState.type = (command == 'a') ? CHUNK_ADD_DIGEST : CHUNK_SUB_DIGEST; + } + switch (mChunkState.type) { + case CHUNK_ADD: + mTableUpdate->NewAddChunk(mChunkState.num); + break; + case CHUNK_SUB: + mTableUpdate->NewSubChunk(mChunkState.num); + break; + case CHUNK_ADD_DIGEST: + mTableUpdate->NewAddChunk(mChunkState.num); + break; + case CHUNK_SUB_DIGEST: + mTableUpdate->NewSubChunk(mChunkState.num); + break; } return NS_OK; @@ -406,11 +425,15 @@ ProtocolParser::ProcessChunk(bool* aDone) mState = PROTOCOL_STATE_CONTROL; //LOG(("Handling a %d-byte chunk", chunk.Length())); - if (StringEndsWith(mTableUpdate->TableName(), NS_LITERAL_CSTRING("-shavar"))) { + if (StringEndsWith(mTableUpdate->TableName(), + NS_LITERAL_CSTRING("-shavar"))) { return ProcessShaChunk(chunk); - } else { - return ProcessPlaintextChunk(chunk); } + if (StringEndsWith(mTableUpdate->TableName(), + NS_LITERAL_CSTRING("-digest256"))) { + return ProcessDigestChunk(chunk); + } + return ProcessPlaintextChunk(chunk); } /** @@ -507,6 +530,61 @@ ProtocolParser::ProcessShaChunk(const nsACString& aChunk) return NS_OK; } +nsresult +ProtocolParser::ProcessDigestChunk(const nsACString& aChunk) +{ + if (mChunkState.type == CHUNK_ADD_DIGEST) { + return ProcessDigestAdd(aChunk); + } + if (mChunkState.type == CHUNK_SUB_DIGEST) { + return ProcessDigestSub(aChunk); + } + return NS_ERROR_UNEXPECTED; +} + +nsresult +ProtocolParser::ProcessDigestAdd(const nsACString& aChunk) +{ + // The ABNF format for add chunks is (HASH)+, where HASH is 32 bytes. + MOZ_ASSERT(aChunk.Length() % 32 == 0, + "Chunk length in bytes must be divisible by 4"); + uint32_t start = 0; + while (start < aChunk.Length()) { + Completion hash; + hash.Assign(Substring(aChunk, start, COMPLETE_SIZE)); + start += COMPLETE_SIZE; + mTableUpdate->NewAddComplete(mChunkState.num, hash); + } + return NS_OK; +} + +nsresult +ProtocolParser::ProcessDigestSub(const nsACString& aChunk) +{ + // The ABNF format for sub chunks is (ADDCHUNKNUM HASH)+, where ADDCHUNKNUM + // is a 4 byte chunk number, and HASH is 32 bytes. + MOZ_ASSERT(aChunk.Length() % 36 == 0, + "Chunk length in bytes must be divisible by 36"); + uint32_t start = 0; + while (start < aChunk.Length()) { + // Read ADDCHUNKNUM + const nsCSubstring& addChunkStr = Substring(aChunk, start, 4); + start += 4; + + uint32_t addChunk; + memcpy(&addChunk, addChunkStr.BeginReading(), 4); + addChunk = PR_ntohl(addChunk); + + // Read the hash + Completion hash; + hash.Assign(Substring(aChunk, start, COMPLETE_SIZE)); + start += COMPLETE_SIZE; + + mTableUpdate->NewSubComplete(addChunk, hash, mChunkState.num); + } + return NS_OK; +} + nsresult ProtocolParser::ProcessHostAdd(const Prefix& aDomain, uint8_t aNumEntries, const nsACString& aChunk, uint32_t* aStart) @@ -590,6 +668,7 @@ ProtocolParser::ProcessHostAddComplete(uint8_t aNumEntries, if (aNumEntries == 0) { // this is totally comprehensible. + // My sarcasm detector is going off! NS_WARNING("Expected > 0 entries for a 32-byte hash add."); return NS_OK; } @@ -684,5 +763,5 @@ ProtocolParser::GetTableUpdate(const nsACString& aTable) return update; } -} -} +} // namespace safebrowsing +} // namespace mozilla diff --git a/toolkit/components/url-classifier/ProtocolParser.h b/toolkit/components/url-classifier/ProtocolParser.h index dd4d6f3b11e5..8b18b8f5e422 100644 --- a/toolkit/components/url-classifier/ProtocolParser.h +++ b/toolkit/components/url-classifier/ProtocolParser.h @@ -59,6 +59,7 @@ private: nsresult ProcessForward(const nsCString& aLine); nsresult AddForward(const nsACString& aUrl, const nsACString& aMac); nsresult ProcessChunk(bool* done); + // Remove this, it's only used for testing nsresult ProcessPlaintextChunk(const nsACString& aChunk); nsresult ProcessShaChunk(const nsACString& aChunk); nsresult ProcessHostAdd(const Prefix& aDomain, uint8_t aNumEntries, @@ -69,6 +70,12 @@ private: uint32_t *aStart); nsresult ProcessHostSubComplete(uint8_t numEntries, const nsACString& aChunk, uint32_t* start); + // Digest chunks are very similar to shavar chunks, except digest chunks + // always contain the full hash, so there is no need for chunk data to + // contain prefix sizes. + nsresult ProcessDigestChunk(const nsACString& aChunk); + nsresult ProcessDigestAdd(const nsACString& aChunk); + nsresult ProcessDigestSub(const nsACString& aChunk); bool NextLine(nsACString& aLine); void CleanupUpdates(); @@ -80,8 +87,13 @@ private: ParserState mState; enum ChunkType { + // Types for shavar tables. CHUNK_ADD, - CHUNK_SUB + CHUNK_SUB, + // Types for digest256 tables. digest256 tables differ in format from + // shavar tables since they only contain complete hashes. + CHUNK_ADD_DIGEST, + CHUNK_SUB_DIGEST }; struct ChunkState { @@ -106,7 +118,9 @@ private: bool mRekeyRequested; nsTArray mForwards; + // Keep track of updates to apply before passing them to the DBServiceWorkers. nsTArray mTableUpdates; + // Updates to apply to the current table being parsed. TableUpdate *mTableUpdate; }; diff --git a/toolkit/components/url-classifier/content/listmanager.js b/toolkit/components/url-classifier/content/listmanager.js index 5849fe6cd353..5063d1a7b7e2 100644 --- a/toolkit/components/url-classifier/content/listmanager.js +++ b/toolkit/components/url-classifier/content/listmanager.js @@ -3,6 +3,7 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. +// This is the only implementation of nsIUrlListManager. // A class that manages lists, namely white and black lists for // phishing or malware protection. The ListManager knows how to fetch, // update, and store lists. diff --git a/toolkit/components/url-classifier/nsIUrlClassifierDBService.idl b/toolkit/components/url-classifier/nsIUrlClassifierDBService.idl index b95b366bc054..7ca5063bade1 100644 --- a/toolkit/components/url-classifier/nsIUrlClassifierDBService.idl +++ b/toolkit/components/url-classifier/nsIUrlClassifierDBService.idl @@ -79,9 +79,9 @@ interface nsIUrlClassifierUpdateObserver : nsISupports { interface nsIUrlClassifierDBService : nsISupports { /** - * Looks up a key in the database. + * Looks up a URI in the database. * - * @param key: The principal containing the information to search. + * @param principal: The principal containing the URI to search. * @param c: The callback will be called with a comma-separated list * of tables to which the key belongs. */ diff --git a/toolkit/components/url-classifier/nsIUrlClassifierHashCompleter.idl b/toolkit/components/url-classifier/nsIUrlClassifierHashCompleter.idl index 0ebcb04a199a..d1712a77962e 100644 --- a/toolkit/components/url-classifier/nsIUrlClassifierHashCompleter.idl +++ b/toolkit/components/url-classifier/nsIUrlClassifierHashCompleter.idl @@ -43,9 +43,11 @@ interface nsIUrlClassifierHashCompleterCallback : nsISupports /** * Clients updating the url-classifier database have the option of sending * partial (32-bit) hashes of URL fragments to be blacklisted. If the - * url-classifier encounters one of these truncated hashes, it will ask - * an nsIUrlClassifierCompleter instance to asynchronously provide the - * complete hash, along with some associated metadata. + * url-classifier encounters one of these truncated hashes, it will ask an + * nsIUrlClassifierCompleter instance to asynchronously provide the complete + * hash, along with some associated metadata. + * This is only ever used for testing and should absolutely be deleted (I + * think). */ [scriptable, uuid(ade9b72b-3562-44f5-aba6-e63246be53ae)] interface nsIUrlClassifierHashCompleter : nsISupports diff --git a/toolkit/components/url-classifier/nsIUrlClassifierStreamUpdater.idl b/toolkit/components/url-classifier/nsIUrlClassifierStreamUpdater.idl index bded3e8adf23..833d42fd1867 100644 --- a/toolkit/components/url-classifier/nsIUrlClassifierStreamUpdater.idl +++ b/toolkit/components/url-classifier/nsIUrlClassifierStreamUpdater.idl @@ -23,6 +23,7 @@ interface nsIUrlClassifierStreamUpdater : nsISupports * Try to download updates from updateUrl. Only one instance of this * runs at a time, so we return false if another instance is already * running. + * This is used in nsIUrlListManager as well as in testing. * @param aRequestTables Comma-separated list of tables included in this * update. * @param aRequestBody The body for the request. diff --git a/toolkit/components/url-classifier/nsUrlClassifierDBService.cpp b/toolkit/components/url-classifier/nsUrlClassifierDBService.cpp index 071358730411..fbda1291ff16 100644 --- a/toolkit/components/url-classifier/nsUrlClassifierDBService.cpp +++ b/toolkit/components/url-classifier/nsUrlClassifierDBService.cpp @@ -155,6 +155,7 @@ private: nsCOMPtr mCryptoHash; nsAutoPtr mClassifier; + // The class that actually parses the update chunks. nsAutoPtr mProtocolParser; // Directory where to store the SB databases. @@ -458,6 +459,7 @@ nsUrlClassifierDBServiceWorker::BeginUpdate(nsIUrlClassifierUpdateObserver *obse return NS_OK; } +// Called from the stream updater. NS_IMETHODIMP nsUrlClassifierDBServiceWorker::BeginStream(const nsACString &table, const nsACString &serverMAC) @@ -539,6 +541,7 @@ nsUrlClassifierDBServiceWorker::UpdateStream(const nsACString& chunk) HandlePendingLookups(); + // Feed the chunk to the parser. return mProtocolParser->AppendStream(chunk); } @@ -719,9 +722,9 @@ nsUrlClassifierDBServiceWorker::CacheCompletions(CacheResultArray *results) if (activeTable) { TableUpdate * tu = pParse->GetTableUpdate(resultsPtr->ElementAt(i).table); LOG(("CacheCompletion Addchunk %d hash %X", resultsPtr->ElementAt(i).entry.addChunk, - resultsPtr->ElementAt(i).entry.hash.prefix)); + resultsPtr->ElementAt(i).entry.ToUint32())); tu->NewAddComplete(resultsPtr->ElementAt(i).entry.addChunk, - resultsPtr->ElementAt(i).entry.hash.complete); + resultsPtr->ElementAt(i).entry.complete); tu->NewAddChunk(resultsPtr->ElementAt(i).entry.addChunk); tu->SetLocalUpdate(); updates.AppendElement(tu); @@ -919,7 +922,7 @@ nsUrlClassifierLookupCallback::Completion(const nsACString& completeHash, if (verified) { CacheResult result; result.entry.addChunk = chunkId; - result.entry.hash.complete = hash; + result.entry.complete = hash; result.table = tableName; // OK if this fails, we just won't cache the item. @@ -1300,6 +1303,7 @@ nsUrlClassifierDBService::LookupURI(nsIPrincipal* aPrincipal, rv = mWorker->QueueLookup(key, proxyCallback); NS_ENSURE_SUCCESS(rv, rv); + // This seems to just call HandlePendingLookups. return mWorkerProxy->Lookup(nullptr, nullptr); } diff --git a/toolkit/components/url-classifier/nsUrlClassifierDBService.h b/toolkit/components/url-classifier/nsUrlClassifierDBService.h index bd4be97bdebc..f3f6a63cda42 100644 --- a/toolkit/components/url-classifier/nsUrlClassifierDBService.h +++ b/toolkit/components/url-classifier/nsUrlClassifierDBService.h @@ -70,7 +70,8 @@ private: // Disallow copy constructor nsUrlClassifierDBService(nsUrlClassifierDBService&); - nsresult LookupURI(nsIPrincipal* aPrincipal, nsIUrlClassifierCallback* c, + nsresult LookupURI(nsIPrincipal* aPrincipal, + nsIUrlClassifierCallback* c, bool forceCheck, bool *didCheck); // Close db connection and join the background thread if it exists. diff --git a/toolkit/components/url-classifier/nsUrlClassifierStreamUpdater.cpp b/toolkit/components/url-classifier/nsUrlClassifierStreamUpdater.cpp index 9711caa236fe..69c520ed8007 100644 --- a/toolkit/components/url-classifier/nsUrlClassifierStreamUpdater.cpp +++ b/toolkit/components/url-classifier/nsUrlClassifierStreamUpdater.cpp @@ -27,6 +27,8 @@ static const PRLogModuleInfo *gUrlClassifierStreamUpdaterLog = nullptr; #endif +// This class does absolutely nothing, except pass requests onto the DBService. + /////////////////////////////////////////////////////////////////////////////// // nsIUrlClassiferStreamUpdater implementation // Handles creating/running the stream listener @@ -107,6 +109,7 @@ nsUrlClassifierStreamUpdater::FetchUpdate(nsIURI *aUpdateUrl, mBeganStream = false; + // If aRequestBody is empty, construct it for the test. if (!aRequestBody.IsEmpty()) { rv = AddRequestBody(aRequestBody); NS_ENSURE_SUCCESS(rv, rv); @@ -114,6 +117,7 @@ nsUrlClassifierStreamUpdater::FetchUpdate(nsIURI *aUpdateUrl, // Set the appropriate content type for file/data URIs, for unit testing // purposes. + // This is only used for testing and should be deleted. bool match; if ((NS_SUCCEEDED(aUpdateUrl->SchemeIs("file", &match)) && match) || (NS_SUCCEEDED(aUpdateUrl->SchemeIs("data", &match)) && match)) { @@ -214,8 +218,9 @@ nsUrlClassifierStreamUpdater::DownloadUpdates( mUpdateUrl->GetAsciiSpec(urlSpec); LOG(("FetchUpdate: %s", urlSpec.get())); - //LOG(("requestBody: %s", aRequestBody.get())); + //LOG(("requestBody: %s", aRequestBody.Data())); + LOG(("Calling into FetchUpdate")); return FetchUpdate(mUpdateUrl, aRequestBody, EmptyCString(), EmptyCString()); } @@ -238,6 +243,9 @@ nsUrlClassifierStreamUpdater::UpdateUrlRequested(const nsACString &aUrl, StringBeginsWith(aUrl, NS_LITERAL_CSTRING("file:"))) { update->mUrl = aUrl; } else { + // This must be fixed when bug 783047 is fixed. However, for unittesting + // update urls to localhost should use http, not https (otherwise the + // connection will fail silently, since there will be no cert available). update->mUrl = NS_LITERAL_CSTRING("http://") + aUrl; } update->mTable = aTable; @@ -418,6 +426,7 @@ nsUrlClassifierStreamUpdater::OnStartRequest(nsIRequest *request, uint32_t requestStatus; rv = httpChannel->GetResponseStatus(&requestStatus); + LOG(("HTTP request returned failure code: %d.", requestStatus)); NS_ENSURE_SUCCESS(rv, rv); strStatus.AppendInt(requestStatus); @@ -462,7 +471,6 @@ nsUrlClassifierStreamUpdater::OnDataAvailable(nsIRequest *request, NS_ENSURE_SUCCESS(rv, rv); //LOG(("Chunk (%d): %s\n\n", chunk.Length(), chunk.get())); - rv = mDBService->UpdateStream(chunk); NS_ENSURE_SUCCESS(rv, rv); diff --git a/toolkit/components/url-classifier/nsUrlClassifierStreamUpdater.h b/toolkit/components/url-classifier/nsUrlClassifierStreamUpdater.h index 18e1c188ff53..9951650f0578 100644 --- a/toolkit/components/url-classifier/nsUrlClassifierStreamUpdater.h +++ b/toolkit/components/url-classifier/nsUrlClassifierStreamUpdater.h @@ -52,15 +52,18 @@ private: nsresult AddRequestBody(const nsACString &aRequestBody); + // Fetches an update for a single table. nsresult FetchUpdate(nsIURI *aURI, const nsACString &aRequestBody, const nsACString &aTable, const nsACString &aServerMAC); + // Dumb wrapper so we don't have to create URIs. nsresult FetchUpdate(const nsACString &aURI, const nsACString &aRequestBody, const nsACString &aTable, const nsACString &aServerMAC); + // Fetches the next table, from mPendingUpdates. nsresult FetchNext(); bool mIsUpdating; diff --git a/toolkit/components/url-classifier/tests/unit/data/digest1.chunk b/toolkit/components/url-classifier/tests/unit/data/digest1.chunk new file mode 100644 index 0000000000000000000000000000000000000000..3850373c19efeca42b55542bd7f9385fbd74e696 GIT binary patch literal 939 zcmXT6GO{uTA~P-q1_u7Uj0LkA?S9YMZN9CyWtu;SY-!RTr{|nW8Zr(Sim$2dDz-8P ztF{CymlW?mtNG%1oZ9p|vJrbO%%4;|_t28?2KU5DOPNIt-i{}MMoRfc90(RUI{R$I z(*CP^`%h?0if<{EIx+V{xu*czM!xDukeW~)x2s#8%3R+3|Lggl1ray4>&oirt83(j zSWVrX{2(j?q$XkW)J2z%XUB6bcPY`H{mygV?T+GzrHkdoHaYCO!MLv#s75kx(ykr0 z$}FdtR+tBba=+ba_LtpFL;0V$dv#jGtHR|4Aafc$HV8ibkuk;MX}C!2bymN&LnTj@ z%N&Ao*gYFeCwFRs%<0ooXU&@&#PA{8^38LZsnaTd#%_KZ%AlsWrzy`W(AyBCW=6PG zUA4~)=6Ro^<4i5wn3ha@A9S$wRO&3XKH)F_nE!$7TK4YD_2nDGw>IgY3tztZlIYg- z-B$#@>)ed46`ms<`KJ%0=6lo^`@>p!;{06IH}33w3)}`(wTfrP}o#jy?mj z>t_nn!WDgd4_|A>1|NU4<<`ySb7}`!Ce40Xz4S?YT(owvl?fsemA8I5vVYZw)%)JF zY@b^FuJtZM|Cua%m)F~7KNFpEWyMm?Vk=XGYB`f{;frQmZC%!V;|#+=q51KP67rT8 zFTd8o!TNPyz@bvXVkDFTztmwa2Zey%YjIxUF@d& z%RZGiTMDGTzBoT}|0(b1TPFKV^lZOd$uJG5hWpjjP13Jp1bij-2X=0eFJHDLW`@oZ zk2;wNJbRC*?Y-t$Y-Nt{i0EO-FaK0IH6yCoBdzy*EZX;AmA%92`uDCU7G%#^eQM^- zVk-+^Fd1+aTUkPBLj#a@b0d()q_;g5G=5)|I<;ZKofSQ+vv2PI@jZC`2KSnMvZ5y^ zA632#QuBHPOZ1bpgUeiPJeie>1h3ep1iTdfvY^w{@`3<+(zUW;D?>wsi*%#reqU~3 z%AjI#P~Y%>WOUok`>#$#FWY;-==kZk&mCTg0hJ?VKHb|3i!1xL^_}t#aS>L|4D3sq UJze$jpVPNBw>931K3}a304z+4egFUf literal 0 HcmV?d00001 diff --git a/toolkit/components/url-classifier/tests/unit/data/digest2.chunk b/toolkit/components/url-classifier/tests/unit/data/digest2.chunk new file mode 100644 index 000000000000..738c96f6ba17 --- /dev/null +++ b/toolkit/components/url-classifier/tests/unit/data/digest2.chunk @@ -0,0 +1,2 @@ +a:5:32:32 +“Ê_Há^˜aÍ7ÂÙ]´=#ÌnmåÃøún‹æo—ÌQ‰ \ No newline at end of file diff --git a/toolkit/components/url-classifier/tests/unit/test_digest256.js b/toolkit/components/url-classifier/tests/unit/test_digest256.js new file mode 100644 index 000000000000..b348a15dd614 --- /dev/null +++ b/toolkit/components/url-classifier/tests/unit/test_digest256.js @@ -0,0 +1,144 @@ +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); + +XPCOMUtils.defineLazyModuleGetter(this, "NetUtil", + "resource://gre/modules/NetUtil.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "Promise", + "resource://gre/modules/Promise.jsm"); +// Global test server for serving safebrowsing updates. +let gHttpServ = null; +// Global nsIUrlClassifierDBService +let gDbService = Cc["@mozilla.org/url-classifier/dbservice;1"] + .getService(Ci.nsIUrlClassifierDBService); +// Security manager for creating nsIPrincipals from URIs +let gSecMan = Cc["@mozilla.org/scriptsecuritymanager;1"] + .getService(Ci.nsIScriptSecurityManager); + +// A map of tables to arrays of update redirect urls. +let gTables = {}; + +// Construct an update from a file. +function readFileToString(aFilename) { + let f = do_get_file(aFilename); + let stream = Cc["@mozilla.org/network/file-input-stream;1"] + .createInstance(Ci.nsIFileInputStream); + stream.init(f, -1, 0, 0); + let buf = NetUtil.readInputStreamToString(stream, stream.available()); + return buf; +} + +// Registers a table for which to serve update chunks. Returns a promise that +// resolves when that chunk has been downloaded. +function registerTableUpdate(aTable, aFilename) { + let deferred = Promise.defer(); + // If we haven't been given an update for this table yet, add it to the map + if (!(aTable in gTables)) { + gTables[aTable] = []; + } + + // The number of chunks associated with this table. + let numChunks = gTables[aTable].length + 1; + let redirectPath = "/" + aTable + "-" + numChunks; + let redirectUrl = "localhost:4444" + redirectPath; + + // Store redirect url for that table so we can return it later when we + // process an update request. + gTables[aTable].push(redirectUrl); + + gHttpServ.registerPathHandler(redirectPath, function(request, response) { + do_print("Mock safebrowsing server handling request for " + redirectPath); + let contents = readFileToString(aFilename); + response.setHeader("Content-Type", + "application/vnd.google.safebrowsing-update", false); + response.setStatusLine(request.httpVersion, 200, "OK"); + response.bodyOutputStream.write(contents, contents.length); + deferred.resolve(contents); + }); + return deferred.promise; +} + +// Construct a response with redirect urls. +function processUpdateRequest() { + let response = "n:1000\n"; + for (let table in gTables) { + response += "i:" + table + "\n"; + for (let i = 0; i < gTables[table].length; ++i) { + response += "u:" + gTables[table][i] + "\n"; + } + } + do_print("Returning update response: " + response); + return response; +} + +// Set up our test server to handle update requests. +function run_test() { + gHttpServ = new HttpServer(); + gHttpServ.registerDirectory("/", do_get_cwd()); + + gHttpServ.registerPathHandler("/downloads", function(request, response) { + let buf = NetUtil.readInputStreamToString(request.bodyInputStream, + request.bodyInputStream.available()); + let blob = processUpdateRequest(); + response.setHeader("Content-Type", + "application/vnd.google.safebrowsing-update", false); + response.setStatusLine(request.httpVersion, 200, "OK"); + response.bodyOutputStream.write(blob, blob.length); + }); + + gHttpServ.start(4444); + run_next_test(); +} + +function createURI(s) { + let service = Cc["@mozilla.org/network/io-service;1"] + .getService(Ci.nsIIOService); + return service.newURI(s, null, null); +} + +// Just throw if we ever get an update or download error. +function handleError(aEvent) { + do_throw("We didn't download or update correctly: " + aEvent); +} + +add_test(function test_update() { + let streamUpdater = Cc["@mozilla.org/url-classifier/streamupdater;1"] + .getService(Ci.nsIUrlClassifierStreamUpdater); + streamUpdater.updateUrl = "http://localhost:4444/downloads"; + + // Load up some update chunks for the safebrowsing server to serve. + registerTableUpdate("goog-downloadwhite-digest256", "data/digest1.chunk"); + registerTableUpdate("goog-downloadwhite-digest256", "data/digest2.chunk"); + + // Download some updates, and don't continue until the downloads are done. + function updateSuccess(aEvent) { + // Timeout of n:1000 is constructed in processUpdateRequest above and + // passed back in the callback in nsIUrlClassifierStreamUpdater on success. + do_check_eq("1000", aEvent); + do_print("All data processed"); + run_next_test(); + } + streamUpdater.downloadUpdates( + "goog-downloadwhite-digest256", + "goog-downloadwhite-digest256;\n", "", + updateSuccess, handleError, handleError); +}); + +add_test(function test_url_not_whitelisted() { + let uri = createURI("http://example.com"); + let principal = gSecMan.getNoAppCodebasePrincipal(uri); + gDbService.lookup(principal, function handleEvent(aEvent) { + // This URI is not on any lists. + do_check_eq("", aEvent); + run_next_test(); + }); +}); + +add_test(function test_url_whitelisted() { + // Hash of "whitelisted.com/" (canonicalized URL) is: + // 93CA5F48E15E9861CD37C2D95DB43D23CC6E6DE5C3F8FA6E8BE66F97CC518907 + let uri = createURI("http://whitelisted.com"); + let principal = gSecMan.getNoAppCodebasePrincipal(uri); + gDbService.lookup(principal, function handleEvent(aEvent) { + do_check_eq("goog-downloadwhite-digest256", aEvent); + run_next_test(); + }); +}); diff --git a/toolkit/components/url-classifier/tests/unit/xpcshell.ini b/toolkit/components/url-classifier/tests/unit/xpcshell.ini index ac5c3a8907b9..3aa869bee02c 100644 --- a/toolkit/components/url-classifier/tests/unit/xpcshell.ini +++ b/toolkit/components/url-classifier/tests/unit/xpcshell.ini @@ -11,3 +11,4 @@ skip-if = os == "mac" || os == "linux" [test_partial.js] [test_prefixset.js] [test_streamupdater.js] +[test_digest256.js] From 9c551bd436cb743e40b48d26f8bf09661d0b553c Mon Sep 17 00:00:00 2001 From: Jeff Gilbert Date: Fri, 6 Sep 2013 17:24:36 -0700 Subject: [PATCH 06/30] Bug 883478 - Update ANGLE to pull from 13-08-02. r=upstream,bjacob,bas --- gfx/angle/AUTHORS | 1 - gfx/angle/CONTRIBUTORS | 150 +- gfx/angle/Makefile.in | 1 + gfx/angle/README.chromium | 10 + gfx/angle/README.mozilla | 59 +- gfx/angle/angle-build-case-sensitive.patch | 22 + gfx/angle/angle-build-d3dcompiler-list.patch | 43 +- .../angle-build-dedupe-debug-cpp-h.patch | 18 +- .../angle-build-dedupe-uniform-cpp-h.patch | 93 + gfx/angle/angle-build-ttype.patch | 52 + gfx/angle/angle-cross-compilation.patch | 50 - gfx/angle/angle-default-clamp-strat.patch | 2 +- gfx/angle/angle-line-loop-overflow.patch | 26 - gfx/angle/angle-long-ident-hash.patch | 137 + gfx/angle/angle-long-ident-spooky-hash.patch | 743 --- gfx/angle/angle-tex-pool-default.patch | 24 + gfx/angle/build/common.gypi | 4 + gfx/angle/codereview.settings | 4 - .../extensions/EGL_ANGLE_direct3d_display.txt | 68 + gfx/angle/include/EGL/eglext.h | 6 + gfx/angle/include/GLES2/gl2ext.h | 46 + gfx/angle/include/GLSLANG/ShaderLang.h | 42 +- gfx/angle/moz.build | 16 +- gfx/angle/src/ANGLE.sln | 66 - gfx/angle/src/build_angle.gypi | 111 +- gfx/angle/src/common/RefCountObject.cpp | 1 + gfx/angle/src/common/angleutils.h | 30 + gfx/angle/src/common/debug.cpp | 4 - gfx/angle/src/common/debug.h | 7 + gfx/angle/src/common/system.h | 4 - gfx/angle/src/common/version.h | 4 +- .../src/compiler/64bit-lexer-safety.patch | 177 + gfx/angle/src/compiler/BaseTypes.h | 8 +- gfx/angle/src/compiler/CodeGenHLSL.cpp | 10 +- gfx/angle/src/compiler/Common.h | 42 +- gfx/angle/src/compiler/Compiler.cpp | 159 +- gfx/angle/src/compiler/CompilerUniform.cpp | 21 + gfx/angle/src/compiler/CompilerUniform.h | 35 + gfx/angle/src/compiler/ConstantUnion.h | 2 +- gfx/angle/src/compiler/DetectCallDepth.cpp | 185 + .../{DetectRecursion.h => DetectCallDepth.h} | 32 +- gfx/angle/src/compiler/DetectRecursion.cpp | 125 - gfx/angle/src/compiler/Diagnostics.cpp | 2 +- gfx/angle/src/compiler/InfoSink.cpp | 25 +- gfx/angle/src/compiler/InfoSink.h | 8 +- gfx/angle/src/compiler/Initialize.cpp | 735 ++- gfx/angle/src/compiler/Initialize.h | 16 +- gfx/angle/src/compiler/InitializeDll.cpp | 89 +- gfx/angle/src/compiler/InitializeDll.h | 5 +- gfx/angle/src/compiler/InitializeGlobals.h | 2 - .../src/compiler/InitializeParseContext.cpp | 78 +- .../src/compiler/InitializeParseContext.h | 15 +- gfx/angle/src/compiler/Intermediate.cpp | 147 +- .../src/compiler/MapLongVariableNames.cpp | 9 +- gfx/angle/src/compiler/OutputGLSL.cpp | 14 + gfx/angle/src/compiler/OutputGLSL.h | 1 + gfx/angle/src/compiler/OutputGLSLBase.cpp | 81 +- gfx/angle/src/compiler/OutputGLSLBase.h | 3 + gfx/angle/src/compiler/OutputHLSL.cpp | 1661 ++++--- gfx/angle/src/compiler/OutputHLSL.h | 48 +- gfx/angle/src/compiler/ParseHelper.cpp | 343 +- gfx/angle/src/compiler/ParseHelper.h | 91 +- gfx/angle/src/compiler/PoolAlloc.cpp | 70 +- gfx/angle/src/compiler/PoolAlloc.h | 10 +- gfx/angle/src/compiler/ShHandle.h | 14 +- gfx/angle/src/compiler/ShaderLang.cpp | 42 +- gfx/angle/src/compiler/SymbolTable.cpp | 211 +- gfx/angle/src/compiler/SymbolTable.h | 85 +- gfx/angle/src/compiler/TranslatorHLSL.cpp | 9 +- gfx/angle/src/compiler/TranslatorHLSL.h | 11 +- gfx/angle/src/compiler/Types.h | 275 +- .../src/compiler/ValidateLimitations.cpp | 2 +- gfx/angle/src/compiler/VariableInfo.cpp | 13 +- gfx/angle/src/compiler/generate_parser.sh | 1 + gfx/angle/src/compiler/glslang.l | 264 +- gfx/angle/src/compiler/glslang.y | 937 ++-- gfx/angle/src/compiler/glslang_lex.cpp | 987 ++-- gfx/angle/src/compiler/glslang_tab.cpp | 3546 ++++++------- gfx/angle/src/compiler/glslang_tab.h | 148 +- gfx/angle/src/compiler/intermOut.cpp | 17 +- gfx/angle/src/compiler/intermediate.h | 37 +- gfx/angle/src/compiler/localintermediate.h | 45 +- gfx/angle/src/compiler/parseConst.cpp | 42 +- .../preprocessor/64bit-tokenizer-safety.patch | 159 + .../preprocessor/ExpressionParser.cpp | 607 +-- .../src/compiler/preprocessor/Tokenizer.cpp | 169 +- .../src/compiler/preprocessor/Tokenizer.l | 6 +- .../compiler/preprocessor/generate_parser.sh | 1 + .../preprocessor/preprocessor.vcxproj | 339 +- .../preprocessor/preprocessor.vcxproj.filters | 29 +- gfx/angle/src/compiler/spooky.cpp | 348 -- gfx/angle/src/compiler/spooky.h | 293 -- .../timing/RestrictVertexShaderTiming.cpp | 6 +- .../src/compiler/translator_common.vcxproj | 284 -- .../translator_common.vcxproj.filters | 268 - .../src/compiler/translator_hlsl.vcxproj | 172 - .../compiler/translator_hlsl.vcxproj.filters | 50 - gfx/angle/src/libEGL/Config.cpp | 117 +- gfx/angle/src/libEGL/Config.h | 15 +- gfx/angle/src/libEGL/Display.cpp | 946 +--- gfx/angle/src/libEGL/Display.h | 114 +- gfx/angle/src/libEGL/Makefile.in | 25 +- gfx/angle/src/libEGL/Surface.cpp | 465 +- gfx/angle/src/libEGL/Surface.h | 36 +- gfx/angle/src/libEGL/libEGL.cpp | 273 +- gfx/angle/src/libEGL/libEGL.vcxproj | 262 - gfx/angle/src/libEGL/libEGL.vcxproj.filters | 70 - gfx/angle/src/libEGL/main.cpp | 3 +- gfx/angle/src/libEGL/main.h | 3 +- gfx/angle/src/libEGL/moz.build | 14 +- gfx/angle/src/libGLESv2/BinaryStream.h | 3 - gfx/angle/src/libGLESv2/Buffer.cpp | 79 +- gfx/angle/src/libGLESv2/Buffer.h | 47 +- gfx/angle/src/libGLESv2/Context.cpp | 2725 +++------- gfx/angle/src/libGLESv2/Context.h | 246 +- gfx/angle/src/libGLESv2/D3DConstantTable.cpp | 231 - gfx/angle/src/libGLESv2/D3DConstantTable.h | 117 - gfx/angle/src/libGLESv2/Fence.cpp | 104 +- gfx/angle/src/libGLESv2/Fence.h | 18 +- gfx/angle/src/libGLESv2/Float16ToFloat32.cpp | 4407 +++++++++-------- gfx/angle/src/libGLESv2/Framebuffer.cpp | 384 +- gfx/angle/src/libGLESv2/Framebuffer.h | 70 +- gfx/angle/src/libGLESv2/HandleAllocator.cpp | 1 + gfx/angle/src/libGLESv2/IndexDataManager.cpp | 474 -- gfx/angle/src/libGLESv2/IndexDataManager.h | 149 - gfx/angle/src/libGLESv2/Makefile.in | 23 +- gfx/angle/src/libGLESv2/Program.cpp | 27 +- gfx/angle/src/libGLESv2/Program.h | 15 +- gfx/angle/src/libGLESv2/ProgramBinary.cpp | 1920 ++++--- gfx/angle/src/libGLESv2/ProgramBinary.h | 145 +- gfx/angle/src/libGLESv2/Query.cpp | 98 +- gfx/angle/src/libGLESv2/Query.h | 17 +- gfx/angle/src/libGLESv2/Renderbuffer.cpp | 230 +- gfx/angle/src/libGLESv2/Renderbuffer.h | 64 +- gfx/angle/src/libGLESv2/ResourceManager.cpp | 18 +- gfx/angle/src/libGLESv2/ResourceManager.h | 24 +- gfx/angle/src/libGLESv2/Shader.cpp | 73 +- gfx/angle/src/libGLESv2/Shader.h | 28 +- gfx/angle/src/libGLESv2/Texture.cpp | 2235 ++------- gfx/angle/src/libGLESv2/Texture.h | 241 +- gfx/angle/src/libGLESv2/Uniform.cpp | 43 + gfx/angle/src/libGLESv2/Uniform.h | 48 + gfx/angle/src/libGLESv2/VertexDataManager.cpp | 783 --- gfx/angle/src/libGLESv2/VertexDataManager.h | 169 - gfx/angle/src/libGLESv2/angletypes.h | 129 + gfx/angle/src/libGLESv2/constants.h | 34 + gfx/angle/src/libGLESv2/libGLESv2.cpp | 1392 +++--- gfx/angle/src/libGLESv2/libGLESv2.def | 3 + gfx/angle/src/libGLESv2/libGLESv2.vcxproj | 303 -- .../src/libGLESv2/libGLESv2.vcxproj.filters | 184 - gfx/angle/src/libGLESv2/main.cpp | 35 +- gfx/angle/src/libGLESv2/main.h | 42 +- gfx/angle/src/libGLESv2/mathutil.h | 19 +- gfx/angle/src/libGLESv2/moz.build | 202 +- gfx/angle/src/libGLESv2/precompiled.cpp | 9 + gfx/angle/src/libGLESv2/precompiled.h | 42 + .../src/libGLESv2/{ => renderer}/Blit.cpp | 163 +- gfx/angle/src/libGLESv2/{ => renderer}/Blit.h | 28 +- .../src/libGLESv2/renderer/BufferStorage.cpp | 40 + .../src/libGLESv2/renderer/BufferStorage.h | 44 + .../libGLESv2/renderer/BufferStorage11.cpp | 358 ++ .../src/libGLESv2/renderer/BufferStorage11.h | 56 + .../src/libGLESv2/renderer/BufferStorage9.cpp | 78 + .../src/libGLESv2/renderer/BufferStorage9.h | 42 + gfx/angle/src/libGLESv2/renderer/Fence11.cpp | 134 + gfx/angle/src/libGLESv2/renderer/Fence11.h | 39 + gfx/angle/src/libGLESv2/renderer/Fence9.cpp | 135 + gfx/angle/src/libGLESv2/renderer/Fence9.h | 39 + gfx/angle/src/libGLESv2/renderer/FenceImpl.h | 45 + gfx/angle/src/libGLESv2/renderer/Image.cpp | 548 ++ gfx/angle/src/libGLESv2/renderer/Image.h | 131 + gfx/angle/src/libGLESv2/renderer/Image11.cpp | 457 ++ gfx/angle/src/libGLESv2/renderer/Image11.h | 76 + gfx/angle/src/libGLESv2/renderer/Image9.cpp | 732 +++ gfx/angle/src/libGLESv2/renderer/Image9.h | 79 + .../ImageSSE2.cpp} | 18 +- .../src/libGLESv2/renderer/IndexBuffer.cpp | 197 + .../src/libGLESv2/renderer/IndexBuffer.h | 111 + .../src/libGLESv2/renderer/IndexBuffer11.cpp | 183 + .../src/libGLESv2/renderer/IndexBuffer11.h | 53 + .../src/libGLESv2/renderer/IndexBuffer9.cpp | 207 + .../src/libGLESv2/renderer/IndexBuffer9.h | 53 + .../libGLESv2/renderer/IndexDataManager.cpp | 333 ++ .../src/libGLESv2/renderer/IndexDataManager.h | 66 + .../libGLESv2/renderer/IndexRangeCache.cpp | 97 + .../src/libGLESv2/renderer/IndexRangeCache.h | 58 + .../libGLESv2/renderer/InputLayoutCache.cpp | 202 + .../src/libGLESv2/renderer/InputLayoutCache.h | 80 + gfx/angle/src/libGLESv2/renderer/Query11.cpp | 122 + gfx/angle/src/libGLESv2/renderer/Query11.h | 40 + gfx/angle/src/libGLESv2/renderer/Query9.cpp | 125 + gfx/angle/src/libGLESv2/renderer/Query9.h | 40 + gfx/angle/src/libGLESv2/renderer/QueryImpl.h | 42 + .../libGLESv2/renderer/RenderStateCache.cpp | 406 ++ .../src/libGLESv2/renderer/RenderStateCache.h | 101 + .../src/libGLESv2/renderer/RenderTarget.h | 56 + .../src/libGLESv2/renderer/RenderTarget11.cpp | 355 ++ .../src/libGLESv2/renderer/RenderTarget11.h | 51 + .../src/libGLESv2/renderer/RenderTarget9.cpp | 113 + .../src/libGLESv2/renderer/RenderTarget9.h | 40 + gfx/angle/src/libGLESv2/renderer/Renderer.cpp | 227 + gfx/angle/src/libGLESv2/renderer/Renderer.h | 244 + .../src/libGLESv2/renderer/Renderer11.cpp | 3535 +++++++++++++ gfx/angle/src/libGLESv2/renderer/Renderer11.h | 358 ++ .../src/libGLESv2/renderer/Renderer9.cpp | 3222 ++++++++++++ gfx/angle/src/libGLESv2/renderer/Renderer9.h | 349 ++ .../renderer}/ShaderCache.h | 20 +- .../src/libGLESv2/renderer/ShaderExecutable.h | 51 + .../libGLESv2/renderer/ShaderExecutable11.cpp | 109 + .../libGLESv2/renderer/ShaderExecutable11.h | 47 + .../libGLESv2/renderer/ShaderExecutable9.cpp | 60 + .../libGLESv2/renderer/ShaderExecutable9.h | 39 + gfx/angle/src/libGLESv2/renderer/SwapChain.h | 44 + .../src/libGLESv2/renderer/SwapChain11.cpp | 767 +++ .../src/libGLESv2/renderer/SwapChain11.h | 78 + .../src/libGLESv2/renderer/SwapChain9.cpp | 434 ++ gfx/angle/src/libGLESv2/renderer/SwapChain9.h | 55 + .../src/libGLESv2/renderer/TextureStorage.cpp | 122 + .../src/libGLESv2/renderer/TextureStorage.h | 110 + .../libGLESv2/renderer/TextureStorage11.cpp | 667 +++ .../src/libGLESv2/renderer/TextureStorage11.h | 120 + .../libGLESv2/renderer/TextureStorage9.cpp | 328 ++ .../src/libGLESv2/renderer/TextureStorage9.h | 109 + .../src/libGLESv2/renderer/VertexBuffer.cpp | 292 ++ .../src/libGLESv2/renderer/VertexBuffer.h | 139 + .../src/libGLESv2/renderer/VertexBuffer11.cpp | 440 ++ .../src/libGLESv2/renderer/VertexBuffer11.h | 74 + .../src/libGLESv2/renderer/VertexBuffer9.cpp | 530 ++ .../src/libGLESv2/renderer/VertexBuffer9.h | 91 + .../libGLESv2/renderer/VertexDataManager.cpp | 276 ++ .../libGLESv2/renderer/VertexDataManager.h | 65 + .../renderer/VertexDeclarationCache.cpp | 217 + .../renderer/VertexDeclarationCache.h | 58 + .../src/libGLESv2/renderer/generatemip.h | 203 + .../libGLESv2/renderer/renderer11_utils.cpp | 688 +++ .../src/libGLESv2/renderer/renderer11_utils.h | 95 + .../libGLESv2/renderer/renderer9_utils.cpp | 500 ++ .../src/libGLESv2/renderer/renderer9_utils.h | 74 + .../libGLESv2/{ => renderer}/shaders/Blit.ps | 0 .../libGLESv2/{ => renderer}/shaders/Blit.vs | 0 .../libGLESv2/renderer/shaders/Clear11.hlsl | 38 + .../renderer/shaders/Passthrough11.hlsl | 29 + .../renderer/shaders/compiled/clear11vs.h | 133 + .../shaders/compiled/clearmultiple11ps.h | 199 + .../shaders/compiled/clearsingle11ps.h | 113 + .../shaders/compiled}/componentmaskps.h | 162 +- .../shaders/compiled}/flipyvs.h | 138 +- .../shaders/compiled}/luminanceps.h | 160 +- .../shaders/compiled/passthrough11vs.h | 137 + .../shaders/compiled/passthroughlum11ps.h | 155 + .../compiled/passthroughlumalpha11ps.h | 151 + .../shaders/compiled}/passthroughps.h | 126 +- .../shaders/compiled/passthroughrgb11ps.h | 155 + .../shaders/compiled/passthroughrgba11ps.h | 144 + .../shaders/compiled}/standardvs.h | 138 +- .../renderer/shaders/generate_shaders.bat | 24 + .../{ => renderer}/vertexconversion.h | 7 +- .../libGLESv2/shaders/generate_shaders.bat | 14 - gfx/angle/src/libGLESv2/utilities.cpp | 698 +-- gfx/angle/src/libGLESv2/utilities.h | 76 +- gfx/angle/src/third_party/murmurhash/LICENSE | 2 + .../third_party/murmurhash/MurmurHash3.cpp | 334 ++ .../src/third_party/murmurhash/MurmurHash3.h | 37 + 263 files changed, 36872 insertions(+), 23011 deletions(-) create mode 100644 gfx/angle/README.chromium create mode 100644 gfx/angle/angle-build-case-sensitive.patch create mode 100644 gfx/angle/angle-build-dedupe-uniform-cpp-h.patch create mode 100644 gfx/angle/angle-build-ttype.patch delete mode 100644 gfx/angle/angle-cross-compilation.patch delete mode 100644 gfx/angle/angle-line-loop-overflow.patch create mode 100644 gfx/angle/angle-long-ident-hash.patch delete mode 100644 gfx/angle/angle-long-ident-spooky-hash.patch create mode 100644 gfx/angle/angle-tex-pool-default.patch delete mode 100644 gfx/angle/codereview.settings create mode 100644 gfx/angle/extensions/EGL_ANGLE_direct3d_display.txt delete mode 100644 gfx/angle/src/ANGLE.sln create mode 100644 gfx/angle/src/compiler/64bit-lexer-safety.patch create mode 100644 gfx/angle/src/compiler/CompilerUniform.cpp create mode 100644 gfx/angle/src/compiler/CompilerUniform.h create mode 100644 gfx/angle/src/compiler/DetectCallDepth.cpp rename gfx/angle/src/compiler/{DetectRecursion.h => DetectCallDepth.h} (59%) delete mode 100644 gfx/angle/src/compiler/DetectRecursion.cpp create mode 100644 gfx/angle/src/compiler/preprocessor/64bit-tokenizer-safety.patch delete mode 100644 gfx/angle/src/compiler/spooky.cpp delete mode 100644 gfx/angle/src/compiler/spooky.h delete mode 100644 gfx/angle/src/compiler/translator_common.vcxproj delete mode 100644 gfx/angle/src/compiler/translator_common.vcxproj.filters delete mode 100644 gfx/angle/src/compiler/translator_hlsl.vcxproj delete mode 100644 gfx/angle/src/compiler/translator_hlsl.vcxproj.filters delete mode 100644 gfx/angle/src/libEGL/libEGL.vcxproj delete mode 100644 gfx/angle/src/libEGL/libEGL.vcxproj.filters delete mode 100644 gfx/angle/src/libGLESv2/D3DConstantTable.cpp delete mode 100644 gfx/angle/src/libGLESv2/D3DConstantTable.h delete mode 100644 gfx/angle/src/libGLESv2/IndexDataManager.cpp delete mode 100644 gfx/angle/src/libGLESv2/IndexDataManager.h create mode 100644 gfx/angle/src/libGLESv2/Uniform.cpp create mode 100644 gfx/angle/src/libGLESv2/Uniform.h delete mode 100644 gfx/angle/src/libGLESv2/VertexDataManager.cpp delete mode 100644 gfx/angle/src/libGLESv2/VertexDataManager.h create mode 100644 gfx/angle/src/libGLESv2/angletypes.h create mode 100644 gfx/angle/src/libGLESv2/constants.h delete mode 100644 gfx/angle/src/libGLESv2/libGLESv2.vcxproj delete mode 100644 gfx/angle/src/libGLESv2/libGLESv2.vcxproj.filters create mode 100644 gfx/angle/src/libGLESv2/precompiled.cpp create mode 100644 gfx/angle/src/libGLESv2/precompiled.h rename gfx/angle/src/libGLESv2/{ => renderer}/Blit.cpp (70%) rename gfx/angle/src/libGLESv2/{ => renderer}/Blit.h (80%) create mode 100644 gfx/angle/src/libGLESv2/renderer/BufferStorage.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/BufferStorage.h create mode 100644 gfx/angle/src/libGLESv2/renderer/BufferStorage11.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/BufferStorage11.h create mode 100644 gfx/angle/src/libGLESv2/renderer/BufferStorage9.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/BufferStorage9.h create mode 100644 gfx/angle/src/libGLESv2/renderer/Fence11.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/Fence11.h create mode 100644 gfx/angle/src/libGLESv2/renderer/Fence9.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/Fence9.h create mode 100644 gfx/angle/src/libGLESv2/renderer/FenceImpl.h create mode 100644 gfx/angle/src/libGLESv2/renderer/Image.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/Image.h create mode 100644 gfx/angle/src/libGLESv2/renderer/Image11.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/Image11.h create mode 100644 gfx/angle/src/libGLESv2/renderer/Image9.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/Image9.h rename gfx/angle/src/libGLESv2/{TextureSSE2.cpp => renderer/ImageSSE2.cpp} (85%) create mode 100644 gfx/angle/src/libGLESv2/renderer/IndexBuffer.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/IndexBuffer.h create mode 100644 gfx/angle/src/libGLESv2/renderer/IndexBuffer11.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/IndexBuffer11.h create mode 100644 gfx/angle/src/libGLESv2/renderer/IndexBuffer9.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/IndexBuffer9.h create mode 100644 gfx/angle/src/libGLESv2/renderer/IndexDataManager.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/IndexDataManager.h create mode 100644 gfx/angle/src/libGLESv2/renderer/IndexRangeCache.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/IndexRangeCache.h create mode 100644 gfx/angle/src/libGLESv2/renderer/InputLayoutCache.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/InputLayoutCache.h create mode 100644 gfx/angle/src/libGLESv2/renderer/Query11.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/Query11.h create mode 100644 gfx/angle/src/libGLESv2/renderer/Query9.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/Query9.h create mode 100644 gfx/angle/src/libGLESv2/renderer/QueryImpl.h create mode 100644 gfx/angle/src/libGLESv2/renderer/RenderStateCache.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/RenderStateCache.h create mode 100644 gfx/angle/src/libGLESv2/renderer/RenderTarget.h create mode 100644 gfx/angle/src/libGLESv2/renderer/RenderTarget11.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/RenderTarget11.h create mode 100644 gfx/angle/src/libGLESv2/renderer/RenderTarget9.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/RenderTarget9.h create mode 100644 gfx/angle/src/libGLESv2/renderer/Renderer.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/Renderer.h create mode 100644 gfx/angle/src/libGLESv2/renderer/Renderer11.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/Renderer11.h create mode 100644 gfx/angle/src/libGLESv2/renderer/Renderer9.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/Renderer9.h rename gfx/angle/src/{libEGL => libGLESv2/renderer}/ShaderCache.h (88%) create mode 100644 gfx/angle/src/libGLESv2/renderer/ShaderExecutable.h create mode 100644 gfx/angle/src/libGLESv2/renderer/ShaderExecutable11.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/ShaderExecutable11.h create mode 100644 gfx/angle/src/libGLESv2/renderer/ShaderExecutable9.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/ShaderExecutable9.h create mode 100644 gfx/angle/src/libGLESv2/renderer/SwapChain.h create mode 100644 gfx/angle/src/libGLESv2/renderer/SwapChain11.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/SwapChain11.h create mode 100644 gfx/angle/src/libGLESv2/renderer/SwapChain9.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/SwapChain9.h create mode 100644 gfx/angle/src/libGLESv2/renderer/TextureStorage.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/TextureStorage.h create mode 100644 gfx/angle/src/libGLESv2/renderer/TextureStorage11.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/TextureStorage11.h create mode 100644 gfx/angle/src/libGLESv2/renderer/TextureStorage9.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/TextureStorage9.h create mode 100644 gfx/angle/src/libGLESv2/renderer/VertexBuffer.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/VertexBuffer.h create mode 100644 gfx/angle/src/libGLESv2/renderer/VertexBuffer11.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/VertexBuffer11.h create mode 100644 gfx/angle/src/libGLESv2/renderer/VertexBuffer9.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/VertexBuffer9.h create mode 100644 gfx/angle/src/libGLESv2/renderer/VertexDataManager.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/VertexDataManager.h create mode 100644 gfx/angle/src/libGLESv2/renderer/VertexDeclarationCache.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/VertexDeclarationCache.h create mode 100644 gfx/angle/src/libGLESv2/renderer/generatemip.h create mode 100644 gfx/angle/src/libGLESv2/renderer/renderer11_utils.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/renderer11_utils.h create mode 100644 gfx/angle/src/libGLESv2/renderer/renderer9_utils.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/renderer9_utils.h rename gfx/angle/src/libGLESv2/{ => renderer}/shaders/Blit.ps (100%) rename gfx/angle/src/libGLESv2/{ => renderer}/shaders/Blit.vs (100%) create mode 100644 gfx/angle/src/libGLESv2/renderer/shaders/Clear11.hlsl create mode 100644 gfx/angle/src/libGLESv2/renderer/shaders/Passthrough11.hlsl create mode 100644 gfx/angle/src/libGLESv2/renderer/shaders/compiled/clear11vs.h create mode 100644 gfx/angle/src/libGLESv2/renderer/shaders/compiled/clearmultiple11ps.h create mode 100644 gfx/angle/src/libGLESv2/renderer/shaders/compiled/clearsingle11ps.h rename gfx/angle/src/libGLESv2/{shaders => renderer/shaders/compiled}/componentmaskps.h (93%) rename gfx/angle/src/libGLESv2/{shaders => renderer/shaders/compiled}/flipyvs.h (93%) rename gfx/angle/src/libGLESv2/{shaders => renderer/shaders/compiled}/luminanceps.h (93%) create mode 100644 gfx/angle/src/libGLESv2/renderer/shaders/compiled/passthrough11vs.h create mode 100644 gfx/angle/src/libGLESv2/renderer/shaders/compiled/passthroughlum11ps.h create mode 100644 gfx/angle/src/libGLESv2/renderer/shaders/compiled/passthroughlumalpha11ps.h rename gfx/angle/src/libGLESv2/{shaders => renderer/shaders/compiled}/passthroughps.h (91%) create mode 100644 gfx/angle/src/libGLESv2/renderer/shaders/compiled/passthroughrgb11ps.h create mode 100644 gfx/angle/src/libGLESv2/renderer/shaders/compiled/passthroughrgba11ps.h rename gfx/angle/src/libGLESv2/{shaders => renderer/shaders/compiled}/standardvs.h (92%) create mode 100644 gfx/angle/src/libGLESv2/renderer/shaders/generate_shaders.bat rename gfx/angle/src/libGLESv2/{ => renderer}/vertexconversion.h (98%) delete mode 100644 gfx/angle/src/libGLESv2/shaders/generate_shaders.bat create mode 100644 gfx/angle/src/third_party/murmurhash/LICENSE create mode 100644 gfx/angle/src/third_party/murmurhash/MurmurHash3.cpp create mode 100644 gfx/angle/src/third_party/murmurhash/MurmurHash3.h diff --git a/gfx/angle/AUTHORS b/gfx/angle/AUTHORS index 2eea0c7292a5..a2ce91575aee 100644 --- a/gfx/angle/AUTHORS +++ b/gfx/angle/AUTHORS @@ -30,4 +30,3 @@ Boying Lu Aitor Moreno Yuri O'Donnell Josh Soref -Evan Wallace diff --git a/gfx/angle/CONTRIBUTORS b/gfx/angle/CONTRIBUTORS index 1d571e076df8..00ebe7cfbfa1 100644 --- a/gfx/angle/CONTRIBUTORS +++ b/gfx/angle/CONTRIBUTORS @@ -1,74 +1,76 @@ -# This is the official list of people who can contribute -# (and who have contributed) code to the ANGLE project -# repository. -# The AUTHORS file lists the copyright holders; this file -# lists people. For example, Google employees are listed here -# but not in AUTHORS, because Google holds the copyright. -# - -TransGaming Inc. - Nicolas Capens - Daniel Koch - Andrew Lewycky - Gavriel State - Shannon Woods - -Google Inc. - Brent Austin - Michael Bai - John Bauman - Peter Beverloo - Steve Block - Rachel Blum - Eric Boren - Henry Bridge - Nat Duca - Peter Kasting - Vangelis Kokkevis - Zhenyao Mo - Daniel Nicoara - Alastair Patrick - Alok Priyadarshi - Kenneth Russell - Brian Salomon - Gregg Tavares - Jeff Timanus - Ben Vanik - Adrienne Walker - thestig@chromium.org - Justin Schuh - -Adobe Systems Inc. - Alexandru Chiculita - Steve Minns - Max Vujovic - -Autodesk, Inc. - Ranger Harke - -Cloud Party, Inc. - Conor Dickinson - -Intel Corporation - Jin Yang - Andy Chen - Josh Triplett - -Klarälvdalens Datakonsult AB - Milian Wolff - -Mozilla Corp. - Ehsan Akhgari - Jeff Gilbert - Mike Hommey - Benoit Jacob - Makoto Kato - Vladimir Vukicevic - -Turbulenz - Michael Braithwaite - -Ulrik Persson (ddefrostt) -Mark Banner (standard8mbp) -David Kilzer - +# This is the official list of people who can contribute +# (and who have contributed) code to the ANGLE project +# repository. +# The AUTHORS file lists the copyright holders; this file +# lists people. For example, Google employees are listed here +# but not in AUTHORS, because Google holds the copyright. +# + +TransGaming Inc. + Nicolas Capens + Daniel Koch + Geoff Lang + Andrew Lewycky + Jamie Madill + Gavriel State + Shannon Woods + +Google Inc. + Brent Austin + Michael Bai + John Bauman + Peter Beverloo + Steve Block + Rachel Blum + Eric Boren + Henry Bridge + Nat Duca + Peter Kasting + Vangelis Kokkevis + Zhenyao Mo + Daniel Nicoara + Alastair Patrick + Alok Priyadarshi + Kenneth Russell + Brian Salomon + Gregg Tavares + Jeff Timanus + Ben Vanik + Adrienne Walker + thestig@chromium.org + Justin Schuh + +Adobe Systems Inc. + Alexandru Chiculita + Steve Minns + Max Vujovic + +Autodesk, Inc. + Ranger Harke + +Cloud Party, Inc. + Conor Dickinson + +Intel Corporation + Jin Yang + Andy Chen + Josh Triplett + +Klarälvdalens Datakonsult AB + Milian Wolff + +Mozilla Corp. + Ehsan Akhgari + Jeff Gilbert + Mike Hommey + Benoit Jacob + Makoto Kato + Vladimir Vukicevic + +Turbulenz + Michael Braithwaite + +Ulrik Persson (ddefrostt) +Mark Banner (standard8mbp) +David Kilzer + diff --git a/gfx/angle/Makefile.in b/gfx/angle/Makefile.in index 02097a9ee897..a533d0dfcc95 100644 --- a/gfx/angle/Makefile.in +++ b/gfx/angle/Makefile.in @@ -27,6 +27,7 @@ VPATH += $(srcdir)/src/compiler VPATH += $(srcdir)/src/compiler/depgraph VPATH += $(srcdir)/src/compiler/timing VPATH += $(srcdir)/src/third_party/compiler +VPATH += $(srcdir)/src/third_party/murmurhash # Target: 'translator_glsl' # Requires: 'translator_common' diff --git a/gfx/angle/README.chromium b/gfx/angle/README.chromium new file mode 100644 index 000000000000..b141fb53074a --- /dev/null +++ b/gfx/angle/README.chromium @@ -0,0 +1,10 @@ +Name: ANGLE +URL: https://code.google.com/p/angleproject/ +Version: 2422 +License: BSD +License File: LICENSE + +Description: +ANGLE is a conformant implementation of the OpenGL ES 2.0 +specification that is hardwareâ€accelerated via Direct3D. + diff --git a/gfx/angle/README.mozilla b/gfx/angle/README.mozilla index 109b53986bc7..9befb6bcfbd7 100644 --- a/gfx/angle/README.mozilla +++ b/gfx/angle/README.mozilla @@ -1,64 +1,77 @@ This is the ANGLE project, from http://code.google.com/p/angleproject/ -Current revision: r2042 - +Current revision: f3fc6571dca9832876e09c63b0958d413737757b +Date of revision: 2013-08-02 == Applied local patches == In this order: angle-build-stdcall-alias.patch: Fix an issue GCC has with linking to undecorated stdcalls. - + angle-build-dedupe-debug-cpp-h.patch: Rename: "src/compiler/debug.{cpp,h}" To: "src/compiler/compiler_debug.{cpp,h}" Repair includes accordingly. - + angle-build-d3dcompiler-list.patch: Move `ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES` define from make files to - Display.cpp, where it's used. - + Renderer.cpp, where it's used. + angle-build-khrplatform-h-path.patch: Fix include path for khrplatform.h. - - angle-long-ident-spooky-hash.patch: - Use Spooky Hash for long identifier hashing. See bug 676071. - + + angle-build-case-sensitive.patch + Fixes cross compilation on case sensitive OSes. + + angle-build-dedupe-uniform-cpp-h.patch: + Rename: "src/compiler/Uniform.{cpp,h}" + To: "src/compiler/CompilerUniform.{cpp,h}" + Repair includes accordingly. + + angle-build-ttype.patch: + Remove bit-field markings for TType, since GCC4.7 emits a default + copy constructor which fails to compile. + + angle-long-ident-hash.patch: + Use MurmurHash3 for long identifier hashing. See bug 676071, where we used + Spooky Hash, before ANGLE came with MurmurHash3. + angle-faceforward-emu.patch: Adds emulation for faceforward(float,float,float), which is needed to prevent crashing on Mac+Intel. See bug 771406. - + angle-default-clamp-strat.patch: Fixes TCompiler::Init to treat `resources.ArrayIndexClampingStrategy` as a request for the default strategy. - angle-cross-compilation.patch - Fixes cross compilation on case sensitive OSes. + angle-tex-pool-default.patch: + Don't use D3DPOOL_MANAGED on D3D9. Just use D3DPOOL_DEFAULT. - angle-line-loop-overflow.patch - Fixes a forgotten overflow check on drawing line loop - ANGLE bug : http://code.google.com/p/angleproject/issues/detail?id=444 - ANGLE revision : 07dda9519cf4 - -In addition to these patches, the Makefile.in files are ours, they're not present in -upsteam ANGLE. Therefore, changes made to the Makefile.in files should not be stored -in the local .patch files. +In addition to these patches, the Makefile.in and moz.build build files are ours, +they're not present in upsteam ANGLE. Therefore, changes made to the build files +should not be stored in the local .patch files. == How to do a clean-slate upgrade == 1. Backup our moz-specific files: README.mozilla Makefile.in + moz.build *.patch src/libEGL/Makefile.in + src/libEGL/moz.build src/libGLESv2/Makefile.in + src/libGLESv2/moz.build 2. $ rm -rf gfx/angle 3. Copy the folder containing the angle rev you want onto gfx/angle. - $ svn export -r /gfx/angle + $ svn export -r /gfx/angle + Or: + $ git checkout-index --prefix /gfx/angle/ -a 4. Fold our moz-specific files into this new angle folder. (Makefiles, README) -4a. Remove the unused directories. (test/, samples/, etc) +4a. Remove the unused files. (test/, samples/, msvc files) 5. Clear out the "Applied Local Patches" section above, since we're going to repopulate it. diff --git a/gfx/angle/angle-build-case-sensitive.patch b/gfx/angle/angle-build-case-sensitive.patch new file mode 100644 index 000000000000..a78c67c4ba93 --- /dev/null +++ b/gfx/angle/angle-build-case-sensitive.patch @@ -0,0 +1,22 @@ +From: Jeff Gilbert +* * * +Bug 840577 - Fix ANGLE cross compilation on case sensitive OSes, relanded + +diff --git a/gfx/angle/src/libGLESv2/precompiled.h b/gfx/angle/src/libGLESv2/precompiled.h +--- a/gfx/angle/src/libGLESv2/precompiled.h ++++ b/gfx/angle/src/libGLESv2/precompiled.h +@@ -30,13 +30,13 @@ + #include + #include + #include + #include + + #include + #include + #include +-#include ++#include + + #ifdef _MSC_VER + #include + #endif diff --git a/gfx/angle/angle-build-d3dcompiler-list.patch b/gfx/angle/angle-build-d3dcompiler-list.patch index 83c20be4700b..14d02d0a8e03 100644 --- a/gfx/angle/angle-build-d3dcompiler-list.patch +++ b/gfx/angle/angle-build-d3dcompiler-list.patch @@ -1,16 +1,16 @@ From: Jeff Gilbert -diff --git a/gfx/angle/src/libEGL/Display.cpp b/gfx/angle/src/libEGL/Display.cpp ---- a/gfx/angle/src/libEGL/Display.cpp -+++ b/gfx/angle/src/libEGL/Display.cpp -@@ -26,16 +26,22 @@ - // The "Debug This Pixel..." feature in PIX often fails when using the - // D3D9Ex interfaces. In order to get debug pixel to work on a Vista/Win 7 - // machine, define "ANGLE_ENABLE_D3D9EX=0" in your project file. - #if !defined(ANGLE_ENABLE_D3D9EX) - // Enables use of the IDirect3D9Ex interface, when available - #define ANGLE_ENABLE_D3D9EX 1 - #endif // !defined(ANGLE_ENABLE_D3D9EX) +diff --git a/gfx/angle/src/libGLESv2/renderer/Renderer.cpp b/gfx/angle/src/libGLESv2/renderer/Renderer.cpp +--- a/gfx/angle/src/libGLESv2/renderer/Renderer.cpp ++++ b/gfx/angle/src/libGLESv2/renderer/Renderer.cpp +@@ -15,16 +15,23 @@ + #include "libGLESv2/renderer/Renderer11.h" + #include "libGLESv2/utilities.h" + + #if !defined(ANGLE_ENABLE_D3D11) + // Enables use of the Direct3D 11 API for a default display, when available + #define ANGLE_ENABLE_D3D11 0 + #endif +#define ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES \ + { \ @@ -18,11 +18,24 @@ diff --git a/gfx/angle/src/libEGL/Display.cpp b/gfx/angle/src/libEGL/Display.cpp + TEXT("d3dcompiler_43.dll") \ + } + - namespace egl ++ + namespace rx { - namespace + + Renderer::Renderer(egl::Display *display) : mDisplay(display) { - typedef std::map DisplayMap; - DisplayMap displays; + mD3dCompilerModule = NULL; + mD3DCompileFunc = NULL; + } +@@ -212,9 +219,9 @@ rx::Renderer *glCreateRenderer(egl::Disp + return NULL; } + void glDestroyRenderer(rx::Renderer *renderer) + { + delete renderer; + } + +-} +\ No newline at end of file ++} diff --git a/gfx/angle/angle-build-dedupe-debug-cpp-h.patch b/gfx/angle/angle-build-dedupe-debug-cpp-h.patch index 439694a10d8f..1cb4719fede1 100644 --- a/gfx/angle/angle-build-dedupe-debug-cpp-h.patch +++ b/gfx/angle/angle-build-dedupe-debug-cpp-h.patch @@ -69,7 +69,7 @@ diff --git a/gfx/angle/src/compiler/OutputHLSL.cpp b/gfx/angle/src/compiler/Outp --- a/gfx/angle/src/compiler/OutputHLSL.cpp +++ b/gfx/angle/src/compiler/OutputHLSL.cpp @@ -2,17 +2,17 @@ - // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. + // Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -90,25 +90,25 @@ diff --git a/gfx/angle/src/compiler/OutputHLSL.cpp b/gfx/angle/src/compiler/Outp diff --git a/gfx/angle/src/compiler/Types.h b/gfx/angle/src/compiler/Types.h --- a/gfx/angle/src/compiler/Types.h +++ b/gfx/angle/src/compiler/Types.h -@@ -4,17 +4,17 @@ - // found in the LICENSE file. - // +@@ -6,17 +6,17 @@ #ifndef _TYPES_INCLUDED #define _TYPES_INCLUDED + #include "common/angleutils.h" + #include "compiler/BaseTypes.h" #include "compiler/Common.h" -#include "compiler/debug.h" +#include "compiler/compiler_debug.h" - class TType; struct TPublicType; + class TType; - // - // Need to have association of line numbers to types in a list for building structs. - // - struct TTypeLine { + class TField + { + public: + POOL_ALLOCATOR_NEW_DELETE(); diff --git a/gfx/angle/src/compiler/debug.cpp b/gfx/angle/src/compiler/compiler_debug.cpp rename from gfx/angle/src/compiler/debug.cpp rename to gfx/angle/src/compiler/compiler_debug.cpp diff --git a/gfx/angle/angle-build-dedupe-uniform-cpp-h.patch b/gfx/angle/angle-build-dedupe-uniform-cpp-h.patch new file mode 100644 index 000000000000..672ab9fe37a0 --- /dev/null +++ b/gfx/angle/angle-build-dedupe-uniform-cpp-h.patch @@ -0,0 +1,93 @@ +From: Jeff Gilbert + +diff --git a/gfx/angle/src/compiler/Uniform.cpp b/gfx/angle/src/compiler/CompilerUniform.cpp +rename from gfx/angle/src/compiler/Uniform.cpp +rename to gfx/angle/src/compiler/CompilerUniform.cpp +--- a/gfx/angle/src/compiler/Uniform.cpp ++++ b/gfx/angle/src/compiler/CompilerUniform.cpp +@@ -1,15 +1,15 @@ + // + // Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. + // Use of this source code is governed by a BSD-style license that can be + // found in the LICENSE file. + // + +-#include "compiler/Uniform.h" ++#include "CompilerUniform.h" + + namespace sh + { + + Uniform::Uniform(GLenum type, GLenum precision, const char *name, int arraySize, int registerIndex) + { + this->type = type; + this->precision = precision; +diff --git a/gfx/angle/src/compiler/Uniform.h b/gfx/angle/src/compiler/CompilerUniform.h +rename from gfx/angle/src/compiler/Uniform.h +rename to gfx/angle/src/compiler/CompilerUniform.h +diff --git a/gfx/angle/src/compiler/OutputHLSL.h b/gfx/angle/src/compiler/OutputHLSL.h +--- a/gfx/angle/src/compiler/OutputHLSL.h ++++ b/gfx/angle/src/compiler/OutputHLSL.h +@@ -11,17 +11,17 @@ + #include + #include + + #define GL_APICALL + #include + + #include "compiler/intermediate.h" + #include "compiler/ParseHelper.h" +-#include "compiler/Uniform.h" ++#include "compiler/CompilerUniform.h" + + namespace sh + { + class UnfoldShortCircuit; + + class OutputHLSL : public TIntermTraverser + { + public: +diff --git a/gfx/angle/src/compiler/TranslatorHLSL.h b/gfx/angle/src/compiler/TranslatorHLSL.h +--- a/gfx/angle/src/compiler/TranslatorHLSL.h ++++ b/gfx/angle/src/compiler/TranslatorHLSL.h +@@ -3,17 +3,17 @@ + // Use of this source code is governed by a BSD-style license that can be + // found in the LICENSE file. + // + + #ifndef COMPILER_TRANSLATORHLSL_H_ + #define COMPILER_TRANSLATORHLSL_H_ + + #include "compiler/ShHandle.h" +-#include "compiler/Uniform.h" ++#include "compiler/CompilerUniform.h" + + class TranslatorHLSL : public TCompiler { + public: + TranslatorHLSL(ShShaderType type, ShShaderSpec spec, ShShaderOutput output); + + virtual TranslatorHLSL *getAsTranslatorHLSL() { return this; } + const sh::ActiveUniforms &getUniforms() { return mActiveUniforms; } + +diff --git a/gfx/angle/src/libGLESv2/Shader.h b/gfx/angle/src/libGLESv2/Shader.h +--- a/gfx/angle/src/libGLESv2/Shader.h ++++ b/gfx/angle/src/libGLESv2/Shader.h +@@ -13,17 +13,17 @@ + #define LIBGLESV2_SHADER_H_ + + #define GL_APICALL + #include + #include + #include + #include + +-#include "compiler/Uniform.h" ++#include "compiler/CompilerUniform.h" + #include "common/angleutils.h" + + namespace rx + { + class Renderer; + } + + namespace gl diff --git a/gfx/angle/angle-build-ttype.patch b/gfx/angle/angle-build-ttype.patch new file mode 100644 index 000000000000..3e54cbed95bd --- /dev/null +++ b/gfx/angle/angle-build-ttype.patch @@ -0,0 +1,52 @@ +From: Jeff Gilbert + +diff --git a/gfx/angle/src/compiler/Types.h b/gfx/angle/src/compiler/Types.h +--- a/gfx/angle/src/compiler/Types.h ++++ b/gfx/angle/src/compiler/Types.h +@@ -90,17 +90,17 @@ private: + // + // Base class for things that have a type. + // + class TType + { + public: + POOL_ALLOCATOR_NEW_DELETE(); + TType() {} +- TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, int s = 1, bool m = false, bool a = false) : ++ TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, char s = 1, bool m = false, bool a = false) : + type(t), precision(p), qualifier(q), size(s), matrix(m), array(a), arraySize(0), structure(0) + { + } + explicit TType(const TPublicType &p); + TType(TStructure* userDef, TPrecision p = EbpUndefined) : + type(EbtStruct), precision(p), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0), structure(userDef) + { + } +@@ -229,22 +229,22 @@ public: + + bool isStructureContainingArrays() const { + return structure ? structure->containsArrays() : false; + } + + private: + TString buildMangledName() const; + +- TBasicType type : 6; ++ TBasicType type; + TPrecision precision; +- TQualifier qualifier : 7; +- int size : 8; // size of vector or matrix, not size of array +- unsigned int matrix : 1; +- unsigned int array : 1; ++ TQualifier qualifier; ++ char size; // size of vector or matrix, not size of array ++ bool matrix; ++ bool array; + int arraySize; + + TStructure* structure; // 0 unless this is a struct + + mutable TString mangled; + }; + + // diff --git a/gfx/angle/angle-cross-compilation.patch b/gfx/angle/angle-cross-compilation.patch deleted file mode 100644 index bcd6d44d7680..000000000000 --- a/gfx/angle/angle-cross-compilation.patch +++ /dev/null @@ -1,50 +0,0 @@ -From: Jacek Caban -Bug 840577 - Fix ANGLE cross compilation on case sensitive OSes, relanded - - -diff --git a/gfx/angle/src/common/system.h b/gfx/angle/src/common/system.h -index f071a05..74f659b 100644 ---- a/gfx/angle/src/common/system.h -+++ b/gfx/angle/src/common/system.h -@@ -10,17 +10,17 @@ - #define COMMON_SYSTEM_H - - #if !defined(WIN32_LEAN_AND_MEAN) - #define WIN32_LEAN_AND_MEAN - #endif - - #include - #include --#include -+#include - #include - #include - - #if defined(min) - #undef min - #endif - - #if defined(max) -diff --git a/gfx/angle/src/libEGL/Display.h b/gfx/angle/src/libEGL/Display.h -index 5859cf2..a1a7870 100644 ---- a/gfx/angle/src/libEGL/Display.h -+++ b/gfx/angle/src/libEGL/Display.h -@@ -8,17 +8,17 @@ - // display on which graphics are drawn. Implements EGLDisplay. - // [EGL 1.4] section 2.1.2 page 3. - - #ifndef LIBEGL_DISPLAY_H_ - #define LIBEGL_DISPLAY_H_ - - #include "common/system.h" - #include --#include -+#include - - #include - #include - - #include "libGLESv2/Context.h" - - #include "libEGL/Config.h" - #include "libEGL/ShaderCache.h" diff --git a/gfx/angle/angle-default-clamp-strat.patch b/gfx/angle/angle-default-clamp-strat.patch index bb9e52647c32..e30273f33bf9 100644 --- a/gfx/angle/angle-default-clamp-strat.patch +++ b/gfx/angle/angle-default-clamp-strat.patch @@ -3,7 +3,7 @@ From: Jeff Gilbert diff --git a/gfx/angle/src/compiler/Compiler.cpp b/gfx/angle/src/compiler/Compiler.cpp --- a/gfx/angle/src/compiler/Compiler.cpp +++ b/gfx/angle/src/compiler/Compiler.cpp -@@ -124,18 +124,21 @@ bool TCompiler::Init(const ShBuiltInReso +@@ -130,18 +130,21 @@ bool TCompiler::Init(const ShBuiltInReso TScopedPoolAllocator scopedAlloc(&allocator, false); // Generate built-in symbol table. diff --git a/gfx/angle/angle-line-loop-overflow.patch b/gfx/angle/angle-line-loop-overflow.patch deleted file mode 100644 index c4402a95f5d4..000000000000 --- a/gfx/angle/angle-line-loop-overflow.patch +++ /dev/null @@ -1,26 +0,0 @@ -# HG changeset patch -# Parent 308e3cf5ba75fdf8ed3bdd3dc766410b708b98ef - -diff --git a/gfx/angle/src/libGLESv2/IndexDataManager.cpp b/gfx/angle/src/libGLESv2/IndexDataManager.cpp ---- a/gfx/angle/src/libGLESv2/IndexDataManager.cpp -+++ b/gfx/angle/src/libGLESv2/IndexDataManager.cpp -@@ -375,17 +375,18 @@ void StreamingIndexBuffer::reserveSpace( - - if (FAILED(result)) - { - ERR("Out of memory allocating a vertex buffer of size %lu.", mBufferSize); - } - - mWritePosition = 0; - } -- else if (mWritePosition + requiredSpace > mBufferSize) // Recycle -+ else if (mWritePosition + requiredSpace > mBufferSize || -+ mWritePosition + requiredSpace < mWritePosition) // Recycle - { - void *dummy; - mIndexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD); - mIndexBuffer->Unlock(); - - mWritePosition = 0; - } - } diff --git a/gfx/angle/angle-long-ident-hash.patch b/gfx/angle/angle-long-ident-hash.patch new file mode 100644 index 000000000000..e089a586a8ab --- /dev/null +++ b/gfx/angle/angle-long-ident-hash.patch @@ -0,0 +1,137 @@ +From: Jeff Gilbert + +diff --git a/gfx/angle/Makefile.in b/gfx/angle/Makefile.in +--- a/gfx/angle/Makefile.in ++++ b/gfx/angle/Makefile.in +@@ -32,16 +32,17 @@ LOCAL_INCLUDES += \ + -I$(srcdir)/src + + DEFINES += -DCOMPILER_IMPLEMENTATION + + VPATH += $(srcdir)/src/compiler + VPATH += $(srcdir)/src/compiler/depgraph + VPATH += $(srcdir)/src/compiler/timing + VPATH += $(srcdir)/src/third_party/compiler ++VPATH += $(srcdir)/src/third_party/murmurhash + + # Target: 'translator_glsl' + # Requires: 'translator_common' + # src/compiler: + ifdef MOZ_ANGLE_RENDERER + + libs:: + ifdef MOZ_D3DCOMPILER_CAB +diff --git a/gfx/angle/moz.build b/gfx/angle/moz.build +--- a/gfx/angle/moz.build ++++ b/gfx/angle/moz.build +@@ -83,16 +83,21 @@ CPP_SOURCES += [ + 'RestrictVertexShaderTiming.cpp', + ] + + # src/third_party/compiler: + CPP_SOURCES += [ + 'ArrayBoundsClamper.cpp', + ] + ++# src/third_party/murmurhash: ++CPP_SOURCES += [ ++ 'MurmurHash3.cpp', ++] ++ + if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': + CPP_SOURCES += [ + 'ossource_win.cpp', + ] + else: + CPP_SOURCES += [ + 'ossource_posix.cpp', + ] +diff --git a/gfx/angle/src/compiler/MapLongVariableNames.cpp b/gfx/angle/src/compiler/MapLongVariableNames.cpp +--- a/gfx/angle/src/compiler/MapLongVariableNames.cpp ++++ b/gfx/angle/src/compiler/MapLongVariableNames.cpp +@@ -1,29 +1,39 @@ + // + // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. + // Use of this source code is governed by a BSD-style license that can be + // found in the LICENSE file. + // + + #include "compiler/MapLongVariableNames.h" + ++#include "third_party/murmurhash/MurmurHash3.h" ++ + namespace { + + TString mapLongName(size_t id, const TString& name, bool isGlobal) + { + ASSERT(name.size() > MAX_SHORTENED_IDENTIFIER_SIZE); + TStringStream stream; +- stream << "webgl_"; +- if (isGlobal) +- stream << "g"; +- stream << id; +- if (name[0] != '_') +- stream << "_"; +- stream << name.substr(0, MAX_SHORTENED_IDENTIFIER_SIZE - stream.str().size()); ++ ++ uint64_t hash[2] = {0, 0}; ++ MurmurHash3_x64_128(name.data(), name.length(), 0, hash); ++ ++ // We want to avoid producing a string with a double underscore, ++ // which would be an illegal GLSL identifier. We can assume that the ++ // original identifier doesn't have a double underscore, otherwise ++ // it's illegal anyway. ++ stream << (name[0] == '_' ? "webgl" : "webgl_") ++ << name.substr(0, 9) ++ << (name[8] == '_' ? "" : "_") ++ << std::hex ++ << hash[0]; ++ ASSERT(stream.str().length() <= MAX_SHORTENED_IDENTIFIER_SIZE); ++ ASSERT(stream.str().length() >= MAX_SHORTENED_IDENTIFIER_SIZE - 2); + return stream.str(); + } + + LongNameMap* gLongNameMapInstance = NULL; + + } // anonymous namespace + + LongNameMap::LongNameMap() +diff --git a/gfx/angle/src/libGLESv2/moz.build b/gfx/angle/src/libGLESv2/moz.build +--- a/gfx/angle/src/libGLESv2/moz.build ++++ b/gfx/angle/src/libGLESv2/moz.build +@@ -71,16 +71,21 @@ CPP_SOURCES += [ + 'RestrictVertexShaderTiming.cpp', + ] + + # src/third_party/compiler: + CPP_SOURCES += [ + 'ArrayBoundsClamper.cpp', + ] + ++# src/third_party/murmurhash: ++CPP_SOURCES += [ ++ 'MurmurHash3.cpp', ++] ++ + if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': + CPP_SOURCES += [ + 'ossource_win.cpp', + ] + else: + CPP_SOURCES += [ + 'ossource_posix.cpp', + ] +@@ -165,13 +170,8 @@ CPP_SOURCES += [ + 'TextureStorage11.cpp', + 'TextureStorage9.cpp', + 'VertexBuffer.cpp', + 'VertexBuffer9.cpp', + 'VertexBuffer11.cpp', + 'VertexDataManager.cpp', + 'VertexDeclarationCache.cpp', + ] +- +-# src/third_party/murmurhash: +-CPP_SOURCES += [ +- 'MurmurHash3.cpp', +-] diff --git a/gfx/angle/angle-long-ident-spooky-hash.patch b/gfx/angle/angle-long-ident-spooky-hash.patch deleted file mode 100644 index eba2f8fd8519..000000000000 --- a/gfx/angle/angle-long-ident-spooky-hash.patch +++ /dev/null @@ -1,743 +0,0 @@ -# HG changeset patch -# Parent 262218204644915abb2add8aa52195c24035c293 - -diff --git a/gfx/angle/Makefile.in b/gfx/angle/Makefile.in ---- a/gfx/angle/Makefile.in -+++ b/gfx/angle/Makefile.in -@@ -84,16 +84,17 @@ CPPSRCS += \ - intermOut.cpp \ - IntermTraverse.cpp \ - MapLongVariableNames.cpp \ - parseConst.cpp \ - ParseHelper.cpp \ - PoolAlloc.cpp \ - QualifierAlive.cpp \ - RemoveTree.cpp \ -+ spooky.cpp \ - SymbolTable.cpp \ - util.cpp \ - ValidateLimitations.cpp \ - VariableInfo.cpp \ - VariablePacker.cpp \ - $(NULL) - - VPATH += $(srcdir)/src/compiler/depgraph -diff --git a/gfx/angle/src/compiler/MapLongVariableNames.cpp b/gfx/angle/src/compiler/MapLongVariableNames.cpp ---- a/gfx/angle/src/compiler/MapLongVariableNames.cpp -+++ b/gfx/angle/src/compiler/MapLongVariableNames.cpp -@@ -1,29 +1,36 @@ - // - // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. - // Use of this source code is governed by a BSD-style license that can be - // found in the LICENSE file. - // - - #include "compiler/MapLongVariableNames.h" -+#include "spooky.h" - - namespace { - - TString mapLongName(size_t id, const TString& name, bool isGlobal) - { - ASSERT(name.size() > MAX_SHORTENED_IDENTIFIER_SIZE); - TStringStream stream; -- stream << "webgl_"; -- if (isGlobal) -- stream << "g"; -- stream << id; -- if (name[0] != '_') -- stream << "_"; -- stream << name.substr(0, MAX_SHORTENED_IDENTIFIER_SIZE - stream.str().size()); -+ uint64 hash = SpookyHash::Hash64(name.data(), name.length(), 0); -+ -+ // We want to avoid producing a string with a double underscore, -+ // which would be an illegal GLSL identifier. We can assume that the -+ // original identifier doesn't have a double underscore, otherwise -+ // it's illegal anyway. -+ stream << (name[0] == '_' ? "webgl" : "webgl_") -+ << name.substr(0, 9) -+ << (name[8] == '_' ? "" : "_") -+ << std::hex -+ << hash; -+ ASSERT(stream.str().length() <= MAX_SHORTENED_IDENTIFIER_SIZE); -+ ASSERT(stream.str().length() >= MAX_SHORTENED_IDENTIFIER_SIZE - 2); - return stream.str(); - } - - LongNameMap* gLongNameMapInstance = NULL; - - } // anonymous namespace - - LongNameMap::LongNameMap() -diff --git a/gfx/angle/src/compiler/spooky.cpp b/gfx/angle/src/compiler/spooky.cpp -new file mode 100644 ---- /dev/null -+++ b/gfx/angle/src/compiler/spooky.cpp -@@ -0,0 +1,348 @@ -+// Spooky Hash -+// A 128-bit noncryptographic hash, for checksums and table lookup -+// By Bob Jenkins. Public domain. -+// Oct 31 2010: published framework, disclaimer ShortHash isn't right -+// Nov 7 2010: disabled ShortHash -+// Oct 31 2011: replace End, ShortMix, ShortEnd, enable ShortHash again -+ -+#include -+#include -+#include "spooky.h" -+ -+#define ALLOW_UNALIGNED_READS 1 -+ -+// -+// short hash ... it could be used on any message, -+// but it's used by Spooky just for short messages. -+// -+void SpookyHash::Short( -+ const void *message, -+ size_t length, -+ uint64 *hash1, -+ uint64 *hash2) -+{ -+ uint64 buf[sc_numVars]; -+ union -+ { -+ const uint8 *p8; -+ uint32 *p32; -+ uint64 *p64; -+ size_t i; -+ } u; -+ -+ u.p8 = (const uint8 *)message; -+ -+ if (!ALLOW_UNALIGNED_READS && (u.i & 0x7)) -+ { -+ memcpy(buf, message, length); -+ u.p64 = buf; -+ } -+ -+ size_t remainder = length%32; -+ uint64 a=*hash1; -+ uint64 b=*hash2; -+ uint64 c=sc_const; -+ uint64 d=sc_const; -+ -+ if (length > 15) -+ { -+ const uint64 *end = u.p64 + (length/32)*4; -+ -+ // handle all complete sets of 32 bytes -+ for (; u.p64 < end; u.p64 += 4) -+ { -+ c += u.p64[0]; -+ d += u.p64[1]; -+ ShortMix(a,b,c,d); -+ a += u.p64[2]; -+ b += u.p64[3]; -+ } -+ -+ //Handle the case of 16+ remaining bytes. -+ if (remainder >= 16) -+ { -+ c += u.p64[0]; -+ d += u.p64[1]; -+ ShortMix(a,b,c,d); -+ u.p64 += 2; -+ remainder -= 16; -+ } -+ } -+ -+ // Handle the last 0..15 bytes, and its length -+ d = ((uint64)length) << 56; -+ switch (remainder) -+ { -+ case 15: -+ d += ((uint64)u.p8[14]) << 48; -+ case 14: -+ d += ((uint64)u.p8[13]) << 40; -+ case 13: -+ d += ((uint64)u.p8[12]) << 32; -+ case 12: -+ d += u.p32[2]; -+ c += u.p64[0]; -+ break; -+ case 11: -+ d += ((uint64)u.p8[10]) << 16; -+ case 10: -+ d += ((uint64)u.p8[9]) << 8; -+ case 9: -+ d += (uint64)u.p8[8]; -+ case 8: -+ c += u.p64[0]; -+ break; -+ case 7: -+ c += ((uint64)u.p8[6]) << 48; -+ case 6: -+ c += ((uint64)u.p8[5]) << 40; -+ case 5: -+ c += ((uint64)u.p8[4]) << 32; -+ case 4: -+ c += u.p32[0]; -+ break; -+ case 3: -+ c += ((uint64)u.p8[2]) << 16; -+ case 2: -+ c += ((uint64)u.p8[1]) << 8; -+ case 1: -+ c += (uint64)u.p8[0]; -+ break; -+ case 0: -+ c += sc_const; -+ d += sc_const; -+ } -+ ShortEnd(a,b,c,d); -+ *hash1 = a; -+ *hash2 = b; -+} -+ -+ -+ -+ -+// do the whole hash in one call -+void SpookyHash::Hash128( -+ const void *message, -+ size_t length, -+ uint64 *hash1, -+ uint64 *hash2) -+{ -+ if (length < sc_bufSize) -+ { -+ Short(message, length, hash1, hash2); -+ return; -+ } -+ -+ uint64 h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11; -+ uint64 buf[sc_numVars]; -+ uint64 *end; -+ union -+ { -+ const uint8 *p8; -+ uint64 *p64; -+ size_t i; -+ } u; -+ size_t remainder; -+ -+ h0=h3=h6=h9 = *hash1; -+ h1=h4=h7=h10 = *hash2; -+ h2=h5=h8=h11 = sc_const; -+ -+ u.p8 = (const uint8 *)message; -+ end = u.p64 + (length/sc_blockSize)*sc_numVars; -+ -+ // handle all whole sc_blockSize blocks of bytes -+ if (ALLOW_UNALIGNED_READS || ((u.i & 0x7) == 0)) -+ { -+ while (u.p64 < end) -+ { -+ Mix(u.p64, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); -+ u.p64 += sc_numVars; -+ } -+ } -+ else -+ { -+ while (u.p64 < end) -+ { -+ memcpy(buf, u.p64, sc_blockSize); -+ Mix(buf, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); -+ u.p64 += sc_numVars; -+ } -+ } -+ -+ // handle the last partial block of sc_blockSize bytes -+ remainder = (length - ((const uint8 *)end-(const uint8 *)message)); -+ memcpy(buf, end, remainder); -+ memset(((uint8 *)buf)+remainder, 0, sc_blockSize-remainder); -+ ((uint8 *)buf)[sc_blockSize-1] = remainder; -+ Mix(buf, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); -+ -+ // do some final mixing -+ End(h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); -+ *hash1 = h0; -+ *hash2 = h1; -+} -+ -+ -+ -+// init spooky state -+void SpookyHash::Init(uint64 seed1, uint64 seed2) -+{ -+ m_length = 0; -+ m_remainder = 0; -+ m_state[0] = seed1; -+ m_state[1] = seed2; -+} -+ -+ -+// add a message fragment to the state -+void SpookyHash::Update(const void *message, size_t length) -+{ -+ uint64 h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11; -+ size_t newLength = length + m_remainder; -+ uint8 remainder; -+ union -+ { -+ const uint8 *p8; -+ uint64 *p64; -+ size_t i; -+ } u; -+ const uint64 *end; -+ -+ // Is this message fragment too short? If it is, stuff it away. -+ if (newLength < sc_bufSize) -+ { -+ memcpy(&((uint8 *)m_data)[m_remainder], message, length); -+ m_length = length + m_length; -+ m_remainder = (uint8)newLength; -+ return; -+ } -+ -+ // init the variables -+ if (m_length < sc_bufSize) -+ { -+ h0=h3=h6=h9 = m_state[0]; -+ h1=h4=h7=h10 = m_state[1]; -+ h2=h5=h8=h11 = sc_const; -+ } -+ else -+ { -+ h0 = m_state[0]; -+ h1 = m_state[1]; -+ h2 = m_state[2]; -+ h3 = m_state[3]; -+ h4 = m_state[4]; -+ h5 = m_state[5]; -+ h6 = m_state[6]; -+ h7 = m_state[7]; -+ h8 = m_state[8]; -+ h9 = m_state[9]; -+ h10 = m_state[10]; -+ h11 = m_state[11]; -+ } -+ m_length = length + m_length; -+ -+ // if we've got anything stuffed away, use it now -+ if (m_remainder) -+ { -+ uint8 prefix = sc_bufSize-m_remainder; -+ memcpy(&(((uint8 *)m_data)[m_remainder]), message, prefix); -+ u.p64 = m_data; -+ Mix(u.p64, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); -+ Mix(&u.p64[sc_numVars], h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); -+ u.p8 = ((const uint8 *)message) + prefix; -+ length -= prefix; -+ } -+ else -+ { -+ u.p8 = (const uint8 *)message; -+ } -+ -+ // handle all whole blocks of sc_blockSize bytes -+ end = u.p64 + (length/sc_blockSize)*sc_numVars; -+ remainder = (uint8)(length-((const uint8 *)end-u.p8)); -+ if (ALLOW_UNALIGNED_READS || (u.i & 0x7) == 0) -+ { -+ while (u.p64 < end) -+ { -+ Mix(u.p64, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); -+ u.p64 += sc_numVars; -+ } -+ } -+ else -+ { -+ while (u.p64 < end) -+ { -+ memcpy(m_data, u.p8, sc_blockSize); -+ Mix(m_data, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); -+ u.p64 += sc_numVars; -+ } -+ } -+ -+ // stuff away the last few bytes -+ m_remainder = remainder; -+ memcpy(m_data, end, remainder); -+ -+ // stuff away the variables -+ m_state[0] = h0; -+ m_state[1] = h1; -+ m_state[2] = h2; -+ m_state[3] = h3; -+ m_state[4] = h4; -+ m_state[5] = h5; -+ m_state[6] = h6; -+ m_state[7] = h7; -+ m_state[8] = h8; -+ m_state[9] = h9; -+ m_state[10] = h10; -+ m_state[11] = h11; -+} -+ -+ -+// report the hash for the concatenation of all message fragments so far -+void SpookyHash::Final(uint64 *hash1, uint64 *hash2) -+{ -+ // init the variables -+ if (m_length < sc_bufSize) -+ { -+ Short( m_data, m_length, hash1, hash2); -+ return; -+ } -+ -+ const uint64 *data = (const uint64 *)m_data; -+ uint8 remainder = m_remainder; -+ -+ uint64 h0 = m_state[0]; -+ uint64 h1 = m_state[1]; -+ uint64 h2 = m_state[2]; -+ uint64 h3 = m_state[3]; -+ uint64 h4 = m_state[4]; -+ uint64 h5 = m_state[5]; -+ uint64 h6 = m_state[6]; -+ uint64 h7 = m_state[7]; -+ uint64 h8 = m_state[8]; -+ uint64 h9 = m_state[9]; -+ uint64 h10 = m_state[10]; -+ uint64 h11 = m_state[11]; -+ -+ if (remainder >= sc_blockSize) -+ { -+ // m_data can contain two blocks; handle any whole first block -+ Mix(data, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); -+ data += sc_numVars; -+ remainder -= sc_blockSize; -+ } -+ -+ // mix in the last partial block, and the length mod sc_blockSize -+ memset(&((uint8 *)data)[remainder], 0, (sc_blockSize-remainder)); -+ -+ ((uint8 *)data)[sc_blockSize-1] = remainder; -+ Mix(data, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); -+ -+ // do some final mixing -+ End(h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); -+ -+ *hash1 = h0; -+ *hash2 = h1; -+} -+ -diff --git a/gfx/angle/src/compiler/spooky.h b/gfx/angle/src/compiler/spooky.h -new file mode 100644 ---- /dev/null -+++ b/gfx/angle/src/compiler/spooky.h -@@ -0,0 +1,293 @@ -+// -+// SpookyHash: a 128-bit noncryptographic hash function -+// By Bob Jenkins, public domain -+// Oct 31 2010: alpha, framework + SpookyHash::Mix appears right -+// Oct 31 2011: alpha again, Mix only good to 2^^69 but rest appears right -+// Dec 31 2011: beta, improved Mix, tested it for 2-bit deltas -+// Feb 2 2012: production, same bits as beta -+// Feb 5 2012: adjusted definitions of uint* to be more portable -+// -+// Up to 4 bytes/cycle for long messages. Reasonably fast for short messages. -+// All 1 or 2 bit deltas achieve avalanche within 1% bias per output bit. -+// -+// This was developed for and tested on 64-bit x86-compatible processors. -+// It assumes the processor is little-endian. There is a macro -+// controlling whether unaligned reads are allowed (by default they are). -+// This should be an equally good hash on big-endian machines, but it will -+// compute different results on them than on little-endian machines. -+// -+// Google's CityHash has similar specs to SpookyHash, and CityHash is faster -+// on some platforms. MD4 and MD5 also have similar specs, but they are orders -+// of magnitude slower. CRCs are two or more times slower, but unlike -+// SpookyHash, they have nice math for combining the CRCs of pieces to form -+// the CRCs of wholes. There are also cryptographic hashes, but those are even -+// slower than MD5. -+// -+ -+#include -+ -+#ifdef _MSC_VER -+# define INLINE __forceinline -+ typedef unsigned __int64 uint64; -+ typedef unsigned __int32 uint32; -+ typedef unsigned __int16 uint16; -+ typedef unsigned __int8 uint8; -+#else -+# include -+# define INLINE inline -+ typedef uint64_t uint64; -+ typedef uint32_t uint32; -+ typedef uint16_t uint16; -+ typedef uint8_t uint8; -+#endif -+ -+ -+class SpookyHash -+{ -+public: -+ // -+ // SpookyHash: hash a single message in one call, produce 128-bit output -+ // -+ static void Hash128( -+ const void *message, // message to hash -+ size_t length, // length of message in bytes -+ uint64 *hash1, // in/out: in seed 1, out hash value 1 -+ uint64 *hash2); // in/out: in seed 2, out hash value 2 -+ -+ // -+ // Hash64: hash a single message in one call, return 64-bit output -+ // -+ static uint64 Hash64( -+ const void *message, // message to hash -+ size_t length, // length of message in bytes -+ uint64 seed) // seed -+ { -+ uint64 hash1 = seed; -+ Hash128(message, length, &hash1, &seed); -+ return hash1; -+ } -+ -+ // -+ // Hash32: hash a single message in one call, produce 32-bit output -+ // -+ static uint32 Hash32( -+ const void *message, // message to hash -+ size_t length, // length of message in bytes -+ uint32 seed) // seed -+ { -+ uint64 hash1 = seed, hash2 = seed; -+ Hash128(message, length, &hash1, &hash2); -+ return (uint32)hash1; -+ } -+ -+ // -+ // Init: initialize the context of a SpookyHash -+ // -+ void Init( -+ uint64 seed1, // any 64-bit value will do, including 0 -+ uint64 seed2); // different seeds produce independent hashes -+ -+ // -+ // Update: add a piece of a message to a SpookyHash state -+ // -+ void Update( -+ const void *message, // message fragment -+ size_t length); // length of message fragment in bytes -+ -+ -+ // -+ // Final: compute the hash for the current SpookyHash state -+ // -+ // This does not modify the state; you can keep updating it afterward -+ // -+ // The result is the same as if SpookyHash() had been called with -+ // all the pieces concatenated into one message. -+ // -+ void Final( -+ uint64 *hash1, // out only: first 64 bits of hash value. -+ uint64 *hash2); // out only: second 64 bits of hash value. -+ -+ // -+ // left rotate a 64-bit value by k bytes -+ // -+ static INLINE uint64 Rot64(uint64 x, int k) -+ { -+ return (x << k) | (x >> (64 - k)); -+ } -+ -+ // -+ // This is used if the input is 96 bytes long or longer. -+ // -+ // The internal state is fully overwritten every 96 bytes. -+ // Every input bit appears to cause at least 128 bits of entropy -+ // before 96 other bytes are combined, when run forward or backward -+ // For every input bit, -+ // Two inputs differing in just that input bit -+ // Where "differ" means xor or subtraction -+ // And the base value is random -+ // When run forward or backwards one Mix -+ // I tried 3 pairs of each; they all differed by at least 212 bits. -+ // -+ static INLINE void Mix( -+ const uint64 *data, -+ uint64 &s0, uint64 &s1, uint64 &s2, uint64 &s3, -+ uint64 &s4, uint64 &s5, uint64 &s6, uint64 &s7, -+ uint64 &s8, uint64 &s9, uint64 &s10,uint64 &s11) -+ { -+ s0 += data[0]; s2 ^= s10; s11 ^= s0; s0 = Rot64(s0,11); s11 += s1; -+ s1 += data[1]; s3 ^= s11; s0 ^= s1; s1 = Rot64(s1,32); s0 += s2; -+ s2 += data[2]; s4 ^= s0; s1 ^= s2; s2 = Rot64(s2,43); s1 += s3; -+ s3 += data[3]; s5 ^= s1; s2 ^= s3; s3 = Rot64(s3,31); s2 += s4; -+ s4 += data[4]; s6 ^= s2; s3 ^= s4; s4 = Rot64(s4,17); s3 += s5; -+ s5 += data[5]; s7 ^= s3; s4 ^= s5; s5 = Rot64(s5,28); s4 += s6; -+ s6 += data[6]; s8 ^= s4; s5 ^= s6; s6 = Rot64(s6,39); s5 += s7; -+ s7 += data[7]; s9 ^= s5; s6 ^= s7; s7 = Rot64(s7,57); s6 += s8; -+ s8 += data[8]; s10 ^= s6; s7 ^= s8; s8 = Rot64(s8,55); s7 += s9; -+ s9 += data[9]; s11 ^= s7; s8 ^= s9; s9 = Rot64(s9,54); s8 += s10; -+ s10 += data[10]; s0 ^= s8; s9 ^= s10; s10 = Rot64(s10,22); s9 += s11; -+ s11 += data[11]; s1 ^= s9; s10 ^= s11; s11 = Rot64(s11,46); s10 += s0; -+ } -+ -+ // -+ // Mix all 12 inputs together so that h0, h1 are a hash of them all. -+ // -+ // For two inputs differing in just the input bits -+ // Where "differ" means xor or subtraction -+ // And the base value is random, or a counting value starting at that bit -+ // The final result will have each bit of h0, h1 flip -+ // For every input bit, -+ // with probability 50 +- .3% -+ // For every pair of input bits, -+ // with probability 50 +- 3% -+ // -+ // This does not rely on the last Mix() call having already mixed some. -+ // Two iterations was almost good enough for a 64-bit result, but a -+ // 128-bit result is reported, so End() does three iterations. -+ // -+ static INLINE void EndPartial( -+ uint64 &h0, uint64 &h1, uint64 &h2, uint64 &h3, -+ uint64 &h4, uint64 &h5, uint64 &h6, uint64 &h7, -+ uint64 &h8, uint64 &h9, uint64 &h10,uint64 &h11) -+ { -+ h11+= h1; h2 ^= h11; h1 = Rot64(h1,44); -+ h0 += h2; h3 ^= h0; h2 = Rot64(h2,15); -+ h1 += h3; h4 ^= h1; h3 = Rot64(h3,34); -+ h2 += h4; h5 ^= h2; h4 = Rot64(h4,21); -+ h3 += h5; h6 ^= h3; h5 = Rot64(h5,38); -+ h4 += h6; h7 ^= h4; h6 = Rot64(h6,33); -+ h5 += h7; h8 ^= h5; h7 = Rot64(h7,10); -+ h6 += h8; h9 ^= h6; h8 = Rot64(h8,13); -+ h7 += h9; h10^= h7; h9 = Rot64(h9,38); -+ h8 += h10; h11^= h8; h10= Rot64(h10,53); -+ h9 += h11; h0 ^= h9; h11= Rot64(h11,42); -+ h10+= h0; h1 ^= h10; h0 = Rot64(h0,54); -+ } -+ -+ static INLINE void End( -+ uint64 &h0, uint64 &h1, uint64 &h2, uint64 &h3, -+ uint64 &h4, uint64 &h5, uint64 &h6, uint64 &h7, -+ uint64 &h8, uint64 &h9, uint64 &h10,uint64 &h11) -+ { -+ EndPartial(h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); -+ EndPartial(h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); -+ EndPartial(h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); -+ } -+ -+ // -+ // The goal is for each bit of the input to expand into 128 bits of -+ // apparent entropy before it is fully overwritten. -+ // n trials both set and cleared at least m bits of h0 h1 h2 h3 -+ // n: 2 m: 29 -+ // n: 3 m: 46 -+ // n: 4 m: 57 -+ // n: 5 m: 107 -+ // n: 6 m: 146 -+ // n: 7 m: 152 -+ // when run forwards or backwards -+ // for all 1-bit and 2-bit diffs -+ // with diffs defined by either xor or subtraction -+ // with a base of all zeros plus a counter, or plus another bit, or random -+ // -+ static INLINE void ShortMix(uint64 &h0, uint64 &h1, uint64 &h2, uint64 &h3) -+ { -+ h2 = Rot64(h2,50); h2 += h3; h0 ^= h2; -+ h3 = Rot64(h3,52); h3 += h0; h1 ^= h3; -+ h0 = Rot64(h0,30); h0 += h1; h2 ^= h0; -+ h1 = Rot64(h1,41); h1 += h2; h3 ^= h1; -+ h2 = Rot64(h2,54); h2 += h3; h0 ^= h2; -+ h3 = Rot64(h3,48); h3 += h0; h1 ^= h3; -+ h0 = Rot64(h0,38); h0 += h1; h2 ^= h0; -+ h1 = Rot64(h1,37); h1 += h2; h3 ^= h1; -+ h2 = Rot64(h2,62); h2 += h3; h0 ^= h2; -+ h3 = Rot64(h3,34); h3 += h0; h1 ^= h3; -+ h0 = Rot64(h0,5); h0 += h1; h2 ^= h0; -+ h1 = Rot64(h1,36); h1 += h2; h3 ^= h1; -+ } -+ -+ // -+ // Mix all 4 inputs together so that h0, h1 are a hash of them all. -+ // -+ // For two inputs differing in just the input bits -+ // Where "differ" means xor or subtraction -+ // And the base value is random, or a counting value starting at that bit -+ // The final result will have each bit of h0, h1 flip -+ // For every input bit, -+ // with probability 50 +- .3% (it is probably better than that) -+ // For every pair of input bits, -+ // with probability 50 +- .75% (the worst case is approximately that) -+ // -+ static INLINE void ShortEnd(uint64 &h0, uint64 &h1, uint64 &h2, uint64 &h3) -+ { -+ h3 ^= h2; h2 = Rot64(h2,15); h3 += h2; -+ h0 ^= h3; h3 = Rot64(h3,52); h0 += h3; -+ h1 ^= h0; h0 = Rot64(h0,26); h1 += h0; -+ h2 ^= h1; h1 = Rot64(h1,51); h2 += h1; -+ h3 ^= h2; h2 = Rot64(h2,28); h3 += h2; -+ h0 ^= h3; h3 = Rot64(h3,9); h0 += h3; -+ h1 ^= h0; h0 = Rot64(h0,47); h1 += h0; -+ h2 ^= h1; h1 = Rot64(h1,54); h2 += h1; -+ h3 ^= h2; h2 = Rot64(h2,32); h3 += h2; -+ h0 ^= h3; h3 = Rot64(h3,25); h0 += h3; -+ h1 ^= h0; h0 = Rot64(h0,63); h1 += h0; -+ } -+ -+private: -+ -+ // -+ // Short is used for messages under 192 bytes in length -+ // Short has a low startup cost, the normal mode is good for long -+ // keys, the cost crossover is at about 192 bytes. The two modes were -+ // held to the same quality bar. -+ // -+ static void Short( -+ const void *message, -+ size_t length, -+ uint64 *hash1, -+ uint64 *hash2); -+ -+ // number of uint64's in internal state -+ static const size_t sc_numVars = 12; -+ -+ // size of the internal state -+ static const size_t sc_blockSize = sc_numVars*8; -+ -+ // size of buffer of unhashed data, in bytes -+ static const size_t sc_bufSize = 2*sc_blockSize; -+ -+ // -+ // sc_const: a constant which: -+ // * is not zero -+ // * is odd -+ // * is a not-very-regular mix of 1's and 0's -+ // * does not need any other special mathematical properties -+ // -+ static const uint64 sc_const = 0xdeadbeefdeadbeefLL; -+ -+ uint64 m_data[2*sc_numVars]; // unhashed data, for partial messages -+ uint64 m_state[sc_numVars]; // internal state of the hash -+ size_t m_length; // total length of the input so far -+ uint8 m_remainder; // length of unhashed data stashed in m_data -+}; -+ -+ -+ -diff --git a/gfx/angle/src/libGLESv2/Makefile.in b/gfx/angle/src/libGLESv2/Makefile.in ---- a/gfx/angle/src/libGLESv2/Makefile.in -+++ b/gfx/angle/src/libGLESv2/Makefile.in -@@ -91,16 +91,17 @@ CPPSRCS += \ - intermOut.cpp \ - IntermTraverse.cpp \ - MapLongVariableNames.cpp \ - parseConst.cpp \ - ParseHelper.cpp \ - PoolAlloc.cpp \ - QualifierAlive.cpp \ - RemoveTree.cpp \ -+ spooky.cpp \ - SymbolTable.cpp \ - util.cpp \ - ValidateLimitations.cpp \ - VariableInfo.cpp \ - VariablePacker.cpp \ - $(NULL) - - VPATH += $(srcdir)/../compiler/depgraph diff --git a/gfx/angle/angle-tex-pool-default.patch b/gfx/angle/angle-tex-pool-default.patch new file mode 100644 index 000000000000..0ecfa0a225ab --- /dev/null +++ b/gfx/angle/angle-tex-pool-default.patch @@ -0,0 +1,24 @@ +From: Jeff Gilbert + +diff --git a/gfx/angle/src/libGLESv2/renderer/Renderer9.cpp b/gfx/angle/src/libGLESv2/renderer/Renderer9.cpp +--- a/gfx/angle/src/libGLESv2/renderer/Renderer9.cpp ++++ b/gfx/angle/src/libGLESv2/renderer/Renderer9.cpp +@@ -3128,17 +3128,17 @@ D3DPOOL Renderer9::getTexturePool(DWORD + if (mD3d9Ex != NULL) + { + return D3DPOOL_DEFAULT; + } + else + { + if (!(usage & (D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_RENDERTARGET))) + { +- return D3DPOOL_MANAGED; ++ return D3DPOOL_DEFAULT; + } + } + + return D3DPOOL_DEFAULT; + } + + bool Renderer9::copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged) + { diff --git a/gfx/angle/build/common.gypi b/gfx/angle/build/common.gypi index 3ae185ed0da9..fc9f295154bc 100644 --- a/gfx/angle/build/common.gypi +++ b/gfx/angle/build/common.gypi @@ -110,6 +110,10 @@ 'LinkIncremental': '2', }, }, + 'xcode_settings': { + 'COPY_PHASE_STRIP': 'NO', + 'GCC_OPTIMIZATION_LEVEL': '0', + }, }, # Debug 'Release': { 'inherit_from': ['Common'], diff --git a/gfx/angle/codereview.settings b/gfx/angle/codereview.settings deleted file mode 100644 index de224f3462f1..000000000000 --- a/gfx/angle/codereview.settings +++ /dev/null @@ -1,4 +0,0 @@ -# This file is used by gcl to get repository specific information. -CODE_REVIEW_SERVER: codereview.appspot.com -CC_LIST: angleproject-review@googlegroups.com -VIEW_VC: http://code.google.com/p/angleproject/source/detail?r= diff --git a/gfx/angle/extensions/EGL_ANGLE_direct3d_display.txt b/gfx/angle/extensions/EGL_ANGLE_direct3d_display.txt new file mode 100644 index 000000000000..267ca9ce9d90 --- /dev/null +++ b/gfx/angle/extensions/EGL_ANGLE_direct3d_display.txt @@ -0,0 +1,68 @@ +Name + + ANGLE_direct3d_display + +Name Strings + + EGL_ANGLE_direct3d_display + +Contributors + + Nicolas Capens + Shannon Woods + +Contacts + + Shannon Woods, Google Inc. (shannonwoods 'at' chromium.org) + +Status + + In progress + +Version + + Version 1, May 15, 2013 + +Number + + EGL Extension #?? + +Dependencies + + This extension is written against the wording of the EGL 1.4 + Specification. + +Overview + + This extension allows for specifying the behavior of the renderer backing the display. + +New Types + + None + +New Procedures and Functions + + None + +New Tokens + + EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE (EGLNativeDisplayType)-2 + EGL_D3D11_ONLY_DISPLAY_ANGLE (EGLNativeDisplayType)-3 + +Additions to Chapter 3 of the EGL 1.4 Specification (EGL Functions and Errors) + + Add before the last sentence of the first paragraph of section 3.2, + "Initialization": + + "If is EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE, the display returned + will be backed by a Direct3D 11 renderer if one is available, or by a + Direct3D 9 renderer otherwise. If is EGL_D3D11_ONLY_DISPLAY_ANGLE, + the display returned will be backed by a Direct3D 11 renderer if one is + available, or will return NULL otherwise." + +Issues + +Revision History + + Version 1, 2013/05/15 - First draft. + diff --git a/gfx/angle/include/EGL/eglext.h b/gfx/angle/include/EGL/eglext.h index b670840d12e4..c06d4c085050 100644 --- a/gfx/angle/include/EGL/eglext.h +++ b/gfx/angle/include/EGL/eglext.h @@ -306,6 +306,12 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACEPOINTERANGLEPROC) (EGLDisplay #define EGL_SOFTWARE_DISPLAY_ANGLE ((EGLNativeDisplayType)-1) #endif +#ifndef EGL_ANGLE_direct3d_display +#define EGL_ANGLE_direct3d_display 1 +#define EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ((EGLNativeDisplayType)-2) +#define EGL_D3D11_ONLY_DISPLAY_ANGLE ((EGLNativeDisplayType)-3) +#endif + #ifndef EGL_ANGLE_surface_d3d_texture_2d_share_handle #define EGL_ANGLE_surface_d3d_texture_2d_share_handle 1 #define EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE 0x3200 diff --git a/gfx/angle/include/GLES2/gl2ext.h b/gfx/angle/include/GLES2/gl2ext.h index e297fbfe87ae..bad50f9ccbb3 100644 --- a/gfx/angle/include/GLES2/gl2ext.h +++ b/gfx/angle/include/GLES2/gl2ext.h @@ -556,6 +556,44 @@ typedef void* GLeglImageOES; #define GL_COLOR_ATTACHMENT15_NV 0x8CEF #endif +/* GL_EXT_draw_buffers */ +#ifndef GL_EXT_draw_buffers +#define GL_MAX_DRAW_BUFFERS_EXT 0x8824 +#define GL_DRAW_BUFFER0_EXT 0x8825 +#define GL_DRAW_BUFFER1_EXT 0x8826 +#define GL_DRAW_BUFFER2_EXT 0x8827 +#define GL_DRAW_BUFFER3_EXT 0x8828 +#define GL_DRAW_BUFFER4_EXT 0x8829 +#define GL_DRAW_BUFFER5_EXT 0x882A +#define GL_DRAW_BUFFER6_EXT 0x882B +#define GL_DRAW_BUFFER7_EXT 0x882C +#define GL_DRAW_BUFFER8_EXT 0x882D +#define GL_DRAW_BUFFER9_EXT 0x882E +#define GL_DRAW_BUFFER10_EXT 0x882F +#define GL_DRAW_BUFFER11_EXT 0x8830 +#define GL_DRAW_BUFFER12_EXT 0x8831 +#define GL_DRAW_BUFFER13_EXT 0x8832 +#define GL_DRAW_BUFFER14_EXT 0x8833 +#define GL_DRAW_BUFFER15_EXT 0x8834 +#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0 +#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1 +#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2 +#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3 +#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4 +#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5 +#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6 +#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7 +#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8 +#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9 +#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA +#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB +#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC +#define GL_COLOR_ATTACHMENT13_EXT 0x8CED +#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE +#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF +#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF +#endif + /* GL_NV_fbo_color_attachments */ #ifndef GL_NV_fbo_color_attachments #define GL_MAX_COLOR_ATTACHMENTS_NV 0x8CDF @@ -1331,6 +1369,14 @@ GL_APICALL void GL_APIENTRY glDrawBuffersNV (GLsizei n, const GLenum *bufs); typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSNVPROC) (GLsizei n, const GLenum *bufs); #endif +#ifndef GL_EXT_draw_buffers +#define GL_EXT_draw_buffers 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glDrawBuffersEXT (GLsizei n, const GLenum *bufs); +#endif +typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSEXTPROC) (GLsizei n, const GLenum *bufs); +#endif + /* GL_NV_fbo_color_attachments */ #ifndef GL_NV_fbo_color_attachments #define GL_NV_fbo_color_attachments 1 diff --git a/gfx/angle/include/GLSLANG/ShaderLang.h b/gfx/angle/include/GLSLANG/ShaderLang.h index 103db293a68b..21e4e9dc7bcf 100644 --- a/gfx/angle/include/GLSLANG/ShaderLang.h +++ b/gfx/angle/include/GLSLANG/ShaderLang.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -78,9 +78,11 @@ typedef enum { } ShShaderSpec; typedef enum { - SH_ESSL_OUTPUT = 0x8B45, - SH_GLSL_OUTPUT = 0x8B46, - SH_HLSL_OUTPUT = 0x8B47 + SH_ESSL_OUTPUT = 0x8B45, + SH_GLSL_OUTPUT = 0x8B46, + SH_HLSL_OUTPUT = 0x8B47, + SH_HLSL9_OUTPUT = 0x8B47, + SH_HLSL11_OUTPUT = 0x8B48 } ShShaderOutput; typedef enum { @@ -116,7 +118,8 @@ typedef enum { SH_MAPPED_NAME_MAX_LENGTH = 0x6000, SH_NAME_MAX_LENGTH = 0x6001, SH_HASHED_NAME_MAX_LENGTH = 0x6002, - SH_HASHED_NAMES_COUNT = 0x6003 + SH_HASHED_NAMES_COUNT = 0x6003, + SH_ACTIVE_UNIFORMS_ARRAY = 0x6004 } ShShaderInfo; // Compile options. @@ -159,7 +162,13 @@ typedef enum { // vec234, or mat234 type. The ShArrayIndexClampingStrategy enum, // specified in the ShBuiltInResources when constructing the // compiler, selects the strategy for the clamping implementation. - SH_CLAMP_INDIRECT_ARRAY_BOUNDS = 0x1000 + SH_CLAMP_INDIRECT_ARRAY_BOUNDS = 0x1000, + + // This flag limits the complexity of an expression. + SH_LIMIT_EXPRESSION_COMPLEXITY = 0x2000, + + // This flag limits the depth of the call stack. + SH_LIMIT_CALL_STACK_DEPTH = 0x4000, } ShCompileOptions; // Defines alternate strategies for implementing array index clamping. @@ -209,6 +218,7 @@ typedef struct int OES_EGL_image_external; int ARB_texture_rectangle; int EXT_draw_buffers; + int EXT_frag_depth; // Set to 1 if highp precision is supported in the fragment language. // Default is 0. @@ -222,6 +232,12 @@ typedef struct // Selects a strategy to use when implementing array index clamping. // Default is SH_CLAMP_WITH_CLAMP_INTRINSIC. ShArrayIndexClampingStrategy ArrayIndexClampingStrategy; + + // The maximum complexity an expression can be. + int MaxExpressionComplexity; + + // The maximum depth a call stack can be. + int MaxCallStackDepth; } ShBuiltInResources; // @@ -248,7 +264,7 @@ typedef void* ShHandle; // spec: Specifies the language spec the compiler must conform to - // SH_GLES2_SPEC or SH_WEBGL_SPEC. // output: Specifies the output code type - SH_ESSL_OUTPUT, SH_GLSL_OUTPUT, -// or SH_HLSL_OUTPUT. +// SH_HLSL9_OUTPUT or SH_HLSL11_OUTPUT. // resources: Specifies the built-in resources. COMPILER_EXPORT ShHandle ShConstructCompiler( ShShaderType type, @@ -411,6 +427,18 @@ COMPILER_EXPORT void ShGetNameHashingEntry(const ShHandle handle, char* name, char* hashedName); +// Returns a parameter from a compiled shader. +// Parameters: +// handle: Specifies the compiler +// pname: Specifies the parameter to query. +// The following parameters are defined: +// SH_ACTIVE_UNIFORMS_ARRAY: an STL vector of active uniforms. Valid only for +// HLSL output. +// params: Requested parameter +COMPILER_EXPORT void ShGetInfoPointer(const ShHandle handle, + ShShaderInfo pname, + void** params); + #ifdef __cplusplus } #endif diff --git a/gfx/angle/moz.build b/gfx/angle/moz.build index ab2b1f9b83f6..bfaed8cf88f5 100644 --- a/gfx/angle/moz.build +++ b/gfx/angle/moz.build @@ -34,12 +34,15 @@ CPP_SOURCES += [ 'Tokenizer.cpp', ] + +# Target: 'translator_common' +# Requires: 'preprocessor' # src/compiler: CPP_SOURCES += [ 'BuiltInFunctionEmulator.cpp', 'Compiler.cpp', 'compiler_debug.cpp', - 'DetectRecursion.cpp', + 'DetectCallDepth.cpp', 'Diagnostics.cpp', 'DirectiveHandler.cpp', 'ForLoopUnroll.cpp', @@ -58,8 +61,8 @@ CPP_SOURCES += [ 'PoolAlloc.cpp', 'QualifierAlive.cpp', 'RemoveTree.cpp', - 'spooky.cpp', 'SymbolTable.cpp', + 'CompilerUniform.cpp', 'util.cpp', 'ValidateLimitations.cpp', 'VariableInfo.cpp', @@ -85,6 +88,11 @@ CPP_SOURCES += [ 'ArrayBoundsClamper.cpp', ] +# src/third_party/murmurhash: +CPP_SOURCES += [ + 'MurmurHash3.cpp', +] + if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': CPP_SOURCES += [ 'ossource_win.cpp', @@ -94,6 +102,7 @@ else: 'ossource_posix.cpp', ] + # Target: 'translator_glsl' # Requires: 'translator_common' # src/compiler: @@ -109,8 +118,5 @@ CPP_SOURCES += [ ] LIBRARY_NAME = 'angle' - LIBXUL_LIBRARY = True - MSVC_ENABLE_PGO = True - diff --git a/gfx/angle/src/ANGLE.sln b/gfx/angle/src/ANGLE.sln deleted file mode 100644 index 81c1382fc088..000000000000 --- a/gfx/angle/src/ANGLE.sln +++ /dev/null @@ -1,66 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual C++ Express 2010 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libEGL", "libEGL\libEGL.vcxproj", "{E746FCA9-64C3-433E-85E8-9A5A67AB7ED6}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libGLESv2", "libGLESv2\libGLESv2.vcxproj", "{B5871A7A-968C-42E3-A33B-981E6F448E78}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "translator_hlsl", "compiler\translator_hlsl.vcxproj", "{5620F0E4-6C43-49BC-A178-B804E1A0C3A7}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "translator_common", "compiler\translator_common.vcxproj", "{5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "preprocessor", "compiler\preprocessor\preprocessor.vcxproj", "{FBE32DF3-0FB0-4F2F-A424-2C21BD7BC325}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {E746FCA9-64C3-433E-85E8-9A5A67AB7ED6}.Debug|Win32.ActiveCfg = Debug|Win32 - {E746FCA9-64C3-433E-85E8-9A5A67AB7ED6}.Debug|Win32.Build.0 = Debug|Win32 - {E746FCA9-64C3-433E-85E8-9A5A67AB7ED6}.Debug|x64.ActiveCfg = Debug|x64 - {E746FCA9-64C3-433E-85E8-9A5A67AB7ED6}.Debug|x64.Build.0 = Debug|x64 - {E746FCA9-64C3-433E-85E8-9A5A67AB7ED6}.Release|Win32.ActiveCfg = Release|Win32 - {E746FCA9-64C3-433E-85E8-9A5A67AB7ED6}.Release|Win32.Build.0 = Release|Win32 - {E746FCA9-64C3-433E-85E8-9A5A67AB7ED6}.Release|x64.ActiveCfg = Release|x64 - {E746FCA9-64C3-433E-85E8-9A5A67AB7ED6}.Release|x64.Build.0 = Release|x64 - {B5871A7A-968C-42E3-A33B-981E6F448E78}.Debug|Win32.ActiveCfg = Debug|Win32 - {B5871A7A-968C-42E3-A33B-981E6F448E78}.Debug|Win32.Build.0 = Debug|Win32 - {B5871A7A-968C-42E3-A33B-981E6F448E78}.Debug|x64.ActiveCfg = Debug|x64 - {B5871A7A-968C-42E3-A33B-981E6F448E78}.Debug|x64.Build.0 = Debug|x64 - {B5871A7A-968C-42E3-A33B-981E6F448E78}.Release|Win32.ActiveCfg = Release|Win32 - {B5871A7A-968C-42E3-A33B-981E6F448E78}.Release|Win32.Build.0 = Release|Win32 - {B5871A7A-968C-42E3-A33B-981E6F448E78}.Release|x64.ActiveCfg = Release|x64 - {B5871A7A-968C-42E3-A33B-981E6F448E78}.Release|x64.Build.0 = Release|x64 - {5620F0E4-6C43-49BC-A178-B804E1A0C3A7}.Debug|Win32.ActiveCfg = Debug|Win32 - {5620F0E4-6C43-49BC-A178-B804E1A0C3A7}.Debug|Win32.Build.0 = Debug|Win32 - {5620F0E4-6C43-49BC-A178-B804E1A0C3A7}.Debug|x64.ActiveCfg = Debug|x64 - {5620F0E4-6C43-49BC-A178-B804E1A0C3A7}.Debug|x64.Build.0 = Debug|x64 - {5620F0E4-6C43-49BC-A178-B804E1A0C3A7}.Release|Win32.ActiveCfg = Release|Win32 - {5620F0E4-6C43-49BC-A178-B804E1A0C3A7}.Release|Win32.Build.0 = Release|Win32 - {5620F0E4-6C43-49BC-A178-B804E1A0C3A7}.Release|x64.ActiveCfg = Release|x64 - {5620F0E4-6C43-49BC-A178-B804E1A0C3A7}.Release|x64.Build.0 = Release|x64 - {5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}.Debug|Win32.ActiveCfg = Debug|Win32 - {5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}.Debug|Win32.Build.0 = Debug|Win32 - {5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}.Debug|x64.ActiveCfg = Debug|x64 - {5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}.Debug|x64.Build.0 = Debug|x64 - {5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}.Release|Win32.ActiveCfg = Release|Win32 - {5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}.Release|Win32.Build.0 = Release|Win32 - {5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}.Release|x64.ActiveCfg = Release|x64 - {5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}.Release|x64.Build.0 = Release|x64 - {FBE32DF3-0FB0-4F2F-A424-2C21BD7BC325}.Debug|Win32.ActiveCfg = Debug|Win32 - {FBE32DF3-0FB0-4F2F-A424-2C21BD7BC325}.Debug|Win32.Build.0 = Debug|Win32 - {FBE32DF3-0FB0-4F2F-A424-2C21BD7BC325}.Debug|x64.ActiveCfg = Debug|x64 - {FBE32DF3-0FB0-4F2F-A424-2C21BD7BC325}.Debug|x64.Build.0 = Debug|x64 - {FBE32DF3-0FB0-4F2F-A424-2C21BD7BC325}.Release|Win32.ActiveCfg = Release|Win32 - {FBE32DF3-0FB0-4F2F-A424-2C21BD7BC325}.Release|Win32.Build.0 = Release|Win32 - {FBE32DF3-0FB0-4F2F-A424-2C21BD7BC325}.Release|x64.ActiveCfg = Release|x64 - {FBE32DF3-0FB0-4F2F-A424-2C21BD7BC325}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/gfx/angle/src/build_angle.gypi b/gfx/angle/src/build_angle.gypi index 7b664d36dd3d..c91cce1b34aa 100644 --- a/gfx/angle/src/build_angle.gypi +++ b/gfx/angle/src/build_angle.gypi @@ -72,8 +72,8 @@ 'compiler/ConstantUnion.h', 'compiler/debug.cpp', 'compiler/debug.h', - 'compiler/DetectRecursion.cpp', - 'compiler/DetectRecursion.h', + 'compiler/DetectCallDepth.cpp', + 'compiler/DetectCallDepth.h', 'compiler/Diagnostics.h', 'compiler/Diagnostics.cpp', 'compiler/DirectiveHandler.h', @@ -118,6 +118,8 @@ 'compiler/SymbolTable.cpp', 'compiler/SymbolTable.h', 'compiler/Types.h', + 'compiler/Uniform.cpp', + 'compiler/Uniform.h', 'compiler/util.cpp', 'compiler/util.h', 'compiler/ValidateLimitations.cpp', @@ -221,28 +223,26 @@ 'include_dirs': [ '.', '../include', + 'libGLESv2', ], 'sources': [ + 'third_party/murmurhash/MurmurHash3.h', + 'third_party/murmurhash/MurmurHash3.cpp', 'common/angleutils.h', 'common/debug.cpp', 'common/debug.h', 'common/RefCountObject.cpp', 'common/RefCountObject.h', 'common/version.h', - 'libGLESv2/IndexDataManager.cpp', - 'libGLESv2/IndexDataManager.h', - 'libGLESv2/vertexconversion.h', - 'libGLESv2/VertexDataManager.cpp', - 'libGLESv2/VertexDataManager.h', + 'libGLESv2/precompiled.h', + 'libGLESv2/precompiled.cpp', 'libGLESv2/BinaryStream.h', - 'libGLESv2/Blit.cpp', - 'libGLESv2/Blit.h', 'libGLESv2/Buffer.cpp', 'libGLESv2/Buffer.h', + 'libGLESv2/constants.h', 'libGLESv2/Context.cpp', 'libGLESv2/Context.h', - 'libGLESv2/D3DConstantTable.cpp', - 'libGLESv2/D3DConstantTable.h', + 'libGLESv2/angletypes.h', 'libGLESv2/Fence.cpp', 'libGLESv2/Fence.h', 'libGLESv2/Float16ToFloat32.cpp', @@ -264,13 +264,97 @@ 'libGLESv2/Query.cpp', 'libGLESv2/Renderbuffer.cpp', 'libGLESv2/Renderbuffer.h', + 'libGLESv2/renderer/Blit.cpp', + 'libGLESv2/renderer/Blit.h', + 'libGLESv2/renderer/BufferStorage.h', + 'libGLESv2/renderer/BufferStorage.cpp', + 'libGLESv2/renderer/BufferStorage9.cpp', + 'libGLESv2/renderer/BufferStorage9.h', + 'libGLESv2/renderer/BufferStorage11.cpp', + 'libGLESv2/renderer/BufferStorage11.h', + 'libGLESv2/renderer/FenceImpl.h', + 'libGLESv2/renderer/Fence9.cpp', + 'libGLESv2/renderer/Fence9.h', + 'libGLESv2/renderer/Fence11.cpp', + 'libGLESv2/renderer/Fence11.h', + 'libGLESv2/renderer/generatemip.h', + 'libGLESv2/renderer/Image.cpp', + 'libGLESv2/renderer/Image.h', + 'libGLESv2/renderer/Image11.cpp', + 'libGLESv2/renderer/Image11.h', + 'libGLESv2/renderer/Image9.cpp', + 'libGLESv2/renderer/Image9.h', + 'libGLESv2/renderer/ImageSSE2.cpp', + 'libGLESv2/renderer/IndexBuffer.cpp', + 'libGLESv2/renderer/IndexBuffer.h', + 'libGLESv2/renderer/IndexBuffer9.cpp', + 'libGLESv2/renderer/IndexBuffer9.h', + 'libGLESv2/renderer/IndexBuffer11.cpp', + 'libGLESv2/renderer/IndexBuffer11.h', + 'libGLESv2/renderer/IndexDataManager.cpp', + 'libGLESv2/renderer/IndexDataManager.h', + 'libGLESv2/renderer/IndexRangeCache.cpp', + 'libGLESv2/renderer/IndexRangeCache.h', + 'libGLESv2/renderer/InputLayoutCache.cpp', + 'libGLESv2/renderer/InputLayoutCache.h', + 'libGLESv2/renderer/QueryImpl.h', + 'libGLESv2/renderer/Query9.cpp', + 'libGLESv2/renderer/Query9.h', + 'libGLESv2/renderer/Query11.cpp', + 'libGLESv2/renderer/Query11.h', + 'libGLESv2/renderer/Renderer.cpp', + 'libGLESv2/renderer/Renderer.h', + 'libGLESv2/renderer/Renderer11.cpp', + 'libGLESv2/renderer/Renderer11.h', + 'libGLESv2/renderer/renderer11_utils.cpp', + 'libGLESv2/renderer/renderer11_utils.h', + 'libGLESv2/renderer/Renderer9.cpp', + 'libGLESv2/renderer/Renderer9.h', + 'libGLESv2/renderer/renderer9_utils.cpp', + 'libGLESv2/renderer/renderer9_utils.h', + 'libGLESv2/renderer/RenderStateCache.cpp', + 'libGLESv2/renderer/RenderStateCache.h', + 'libGLESv2/renderer/RenderTarget.h', + 'libGLESv2/renderer/RenderTarget11.h', + 'libGLESv2/renderer/RenderTarget11.cpp', + 'libGLESv2/renderer/RenderTarget9.h', + 'libGLESv2/renderer/RenderTarget9.cpp', + 'libGLESv2/renderer/ShaderCache.h', + 'libGLESv2/renderer/ShaderExecutable.h', + 'libGLESv2/renderer/ShaderExecutable9.cpp', + 'libGLESv2/renderer/ShaderExecutable9.h', + 'libGLESv2/renderer/ShaderExecutable11.cpp', + 'libGLESv2/renderer/ShaderExecutable11.h', + 'libGLESv2/renderer/SwapChain.h', + 'libGLESv2/renderer/SwapChain9.cpp', + 'libGLESv2/renderer/SwapChain9.h', + 'libGLESv2/renderer/SwapChain11.cpp', + 'libGLESv2/renderer/SwapChain11.h', + 'libGLESv2/renderer/TextureStorage.cpp', + 'libGLESv2/renderer/TextureStorage.h', + 'libGLESv2/renderer/TextureStorage11.cpp', + 'libGLESv2/renderer/TextureStorage11.h', + 'libGLESv2/renderer/TextureStorage9.cpp', + 'libGLESv2/renderer/TextureStorage9.h', + 'libGLESv2/renderer/VertexBuffer.cpp', + 'libGLESv2/renderer/VertexBuffer.h', + 'libGLESv2/renderer/VertexBuffer9.cpp', + 'libGLESv2/renderer/VertexBuffer9.h', + 'libGLESv2/renderer/VertexBuffer11.cpp', + 'libGLESv2/renderer/VertexBuffer11.h', + 'libGLESv2/renderer/vertexconversion.h', + 'libGLESv2/renderer/VertexDataManager.cpp', + 'libGLESv2/renderer/VertexDataManager.h', + 'libGLESv2/renderer/VertexDeclarationCache.cpp', + 'libGLESv2/renderer/VertexDeclarationCache.h', 'libGLESv2/ResourceManager.cpp', 'libGLESv2/ResourceManager.h', 'libGLESv2/Shader.cpp', 'libGLESv2/Shader.h', 'libGLESv2/Texture.cpp', - 'libGLESv2/TextureSSE2.cpp', 'libGLESv2/Texture.h', + 'libGLESv2/Uniform.cpp', + 'libGLESv2/Uniform.h', 'libGLESv2/utilities.cpp', 'libGLESv2/utilities.h', ], @@ -280,6 +364,7 @@ 'VCLinkerTool': { 'AdditionalDependencies': [ 'd3d9.lib', + 'dxguid.lib', ], } }, @@ -291,6 +376,7 @@ 'include_dirs': [ '.', '../include', + 'libGLESv2', ], 'sources': [ 'common/angleutils.h', @@ -317,7 +403,6 @@ 'VCLinkerTool': { 'AdditionalDependencies': [ 'd3d9.lib', - 'dxguid.lib', ], } }, diff --git a/gfx/angle/src/common/RefCountObject.cpp b/gfx/angle/src/common/RefCountObject.cpp index c1ef90cdccc2..0364adf2cd55 100644 --- a/gfx/angle/src/common/RefCountObject.cpp +++ b/gfx/angle/src/common/RefCountObject.cpp @@ -1,3 +1,4 @@ +#include "precompiled.h" // // Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be diff --git a/gfx/angle/src/common/angleutils.h b/gfx/angle/src/common/angleutils.h index ff9730c4da7a..9761567fb274 100644 --- a/gfx/angle/src/common/angleutils.h +++ b/gfx/angle/src/common/angleutils.h @@ -9,12 +9,39 @@ #ifndef COMMON_ANGLEUTILS_H_ #define COMMON_ANGLEUTILS_H_ +#include + // A macro to disallow the copy constructor and operator= functions // This must be used in the private: declarations for a class #define DISALLOW_COPY_AND_ASSIGN(TypeName) \ TypeName(const TypeName&); \ void operator=(const TypeName&) +template +inline unsigned int ArraySize(T(&)[N]) +{ + return N; +} + +template +void SafeRelease(T (&resourceBlock)[N]) +{ + for (unsigned int i = 0; i < N; i++) + { + SafeRelease(resourceBlock[i]); + } +} + +template +void SafeRelease(T& resource) +{ + if (resource) + { + resource->Release(); + resource = NULL; + } +} + #if defined(_MSC_VER) #define snprintf _snprintf #endif @@ -23,4 +50,7 @@ #define VENDOR_ID_INTEL 0x8086 #define VENDOR_ID_NVIDIA 0x10DE +#define GL_BGRA4_ANGLEX 0x6ABC +#define GL_BGR5_A1_ANGLEX 0x6ABD + #endif // COMMON_ANGLEUTILS_H_ diff --git a/gfx/angle/src/common/debug.cpp b/gfx/angle/src/common/debug.cpp index 59399607d560..23337405ed16 100644 --- a/gfx/angle/src/common/debug.cpp +++ b/gfx/angle/src/common/debug.cpp @@ -7,10 +7,6 @@ // debug.cpp: Debugging utilities. #include "common/debug.h" - -#include -#include - #include "common/system.h" #include diff --git a/gfx/angle/src/common/debug.h b/gfx/angle/src/common/debug.h index 5f8f60fe6111..23ee26d23baa 100644 --- a/gfx/angle/src/common/debug.h +++ b/gfx/angle/src/common/debug.h @@ -99,6 +99,13 @@ namespace gl #define UNREACHABLE() ERR("\t! Unreachable reached: %s(%d)\n", __FUNCTION__, __LINE__) #endif +// A macro that determines whether an object has a given runtime type. +#if !defined(NDEBUG) && (!defined(_MSC_VER) || defined(_CPPRTTI)) +#define HAS_DYNAMIC_TYPE(type, obj) (dynamic_cast(obj) != NULL) +#else +#define HAS_DYNAMIC_TYPE(type, obj) true +#endif + // A macro functioning as a compile-time assert to validate constant conditions #define META_ASSERT(condition) typedef int COMPILE_TIME_ASSERT_##__LINE__[static_cast(condition)?1:-1] diff --git a/gfx/angle/src/common/system.h b/gfx/angle/src/common/system.h index 74f659bb60fc..5eb140bccd2e 100644 --- a/gfx/angle/src/common/system.h +++ b/gfx/angle/src/common/system.h @@ -14,10 +14,6 @@ #endif #include -#include -#include -#include -#include #if defined(min) #undef min diff --git a/gfx/angle/src/common/version.h b/gfx/angle/src/common/version.h index 62bb1da7ae04..0353fb48d5dc 100644 --- a/gfx/angle/src/common/version.h +++ b/gfx/angle/src/common/version.h @@ -1,7 +1,7 @@ #define MAJOR_VERSION 1 -#define MINOR_VERSION 0 +#define MINOR_VERSION 2 #define BUILD_VERSION 0 -#define BUILD_REVISION 2040 +#define BUILD_REVISION 2431 #define STRINGIFY(x) #x #define MACRO_STRINGIFY(x) STRINGIFY(x) diff --git a/gfx/angle/src/compiler/64bit-lexer-safety.patch b/gfx/angle/src/compiler/64bit-lexer-safety.patch new file mode 100644 index 000000000000..7af91f576534 --- /dev/null +++ b/gfx/angle/src/compiler/64bit-lexer-safety.patch @@ -0,0 +1,177 @@ +--- a/src/compiler/glslang_lex.cpp ++++ b/src/compiler/glslang_lex.cpp +@@ -68,6 +68,7 @@ typedef int16_t flex_int16_t; + typedef uint16_t flex_uint16_t; + typedef int32_t flex_int32_t; + typedef uint32_t flex_uint32_t; ++typedef uint64_t flex_uint64_t; + #else + typedef signed char flex_int8_t; + typedef short int flex_int16_t; +@@ -191,6 +192,11 @@ typedef void* yyscan_t; + typedef struct yy_buffer_state *YY_BUFFER_STATE; + #endif + ++#ifndef YY_TYPEDEF_YY_SIZE_T ++#define YY_TYPEDEF_YY_SIZE_T ++typedef size_t yy_size_t; ++#endif ++ + #define EOB_ACT_CONTINUE_SCAN 0 + #define EOB_ACT_END_OF_FILE 1 + #define EOB_ACT_LAST_MATCH 2 +@@ -204,7 +210,7 @@ typedef struct yy_buffer_state *YY_BUFFER_STATE; + */ + #define YY_LESS_LINENO(n) \ + do { \ +- int yyl;\ ++ yy_size_t yyl;\ + for ( yyl = n; yyl < yyleng; ++yyl )\ + if ( yytext[yyl] == '\n' )\ + --yylineno;\ +@@ -226,11 +232,6 @@ typedef struct yy_buffer_state *YY_BUFFER_STATE; + + #define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner ) + +-#ifndef YY_TYPEDEF_YY_SIZE_T +-#define YY_TYPEDEF_YY_SIZE_T +-typedef size_t yy_size_t; +-#endif +- + #ifndef YY_STRUCT_YY_BUFFER_STATE + #define YY_STRUCT_YY_BUFFER_STATE + struct yy_buffer_state +@@ -248,7 +249,7 @@ struct yy_buffer_state + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ +- int yy_n_chars; ++ yy_size_t yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to +@@ -327,7 +328,7 @@ static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner ); + + YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner ); + YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner ); +-YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner ); ++YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,yy_size_t len ,yyscan_t yyscanner ); + + void *yyalloc (yy_size_t ,yyscan_t yyscanner ); + void *yyrealloc (void *,yy_size_t ,yyscan_t yyscanner ); +@@ -378,7 +379,7 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner ); + */ + #define YY_DO_BEFORE_ACTION \ + yyg->yytext_ptr = yy_bp; \ +- yyleng = (size_t) (yy_cp - yy_bp); \ ++ yyleng = (yy_size_t) (yy_cp - yy_bp); \ + yyg->yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yyg->yy_c_buf_p = yy_cp; +@@ -1035,8 +1036,8 @@ struct yyguts_t + size_t yy_buffer_stack_max; /**< capacity of stack. */ + YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */ + char yy_hold_char; +- int yy_n_chars; +- int yyleng_r; ++ yy_size_t yy_n_chars; ++ yy_size_t yyleng_r; + char *yy_c_buf_p; + int yy_init; + int yy_start; +@@ -1089,7 +1090,7 @@ FILE *yyget_out (yyscan_t yyscanner ); + + void yyset_out (FILE * out_str ,yyscan_t yyscanner ); + +-int yyget_leng (yyscan_t yyscanner ); ++yy_size_t yyget_leng (yyscan_t yyscanner ); + + char *yyget_text (yyscan_t yyscanner ); + +@@ -1158,7 +1159,7 @@ static int input (yyscan_t yyscanner ); + if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ + { \ + int c = '*'; \ +- int n; \ ++ yy_size_t n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ +@@ -1317,7 +1318,7 @@ yy_find_action: + + if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] ) + { +- int yyl; ++ yy_size_t yyl; + for ( yyl = 0; yyl < yyleng; ++yyl ) + if ( yytext[yyl] == '\n' ) + +@@ -2203,7 +2204,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) + + else + { +- int num_to_read = ++ yy_size_t num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) +@@ -2217,7 +2218,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) + + if ( b->yy_is_our_buffer ) + { +- int new_size = b->yy_buf_size * 2; ++ yy_size_t new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; +@@ -2248,7 +2249,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), +- yyg->yy_n_chars, (size_t) num_to_read ); ++ yyg->yy_n_chars, num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } +@@ -2373,7 +2374,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) + + else + { /* need more input */ +- int offset = yyg->yy_c_buf_p - yyg->yytext_ptr; ++ yy_size_t offset = yyg->yy_c_buf_p - yyg->yytext_ptr; + ++yyg->yy_c_buf_p; + + switch ( yy_get_next_buffer( yyscanner ) ) +@@ -2660,7 +2661,7 @@ void yypop_buffer_state (yyscan_t yyscanner) + */ + static void yyensure_buffer_stack (yyscan_t yyscanner) + { +- int num_to_alloc; ++ yy_size_t num_to_alloc; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if (!yyg->yy_buffer_stack) { +@@ -2758,12 +2759,11 @@ YY_BUFFER_STATE yy_scan_string (yyconst char * yystr , yyscan_t yyscanner) + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + */ +-YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len , yyscan_t yyscanner) ++YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len , yyscan_t yyscanner) + { + YY_BUFFER_STATE b; + char *buf; +- yy_size_t n; +- int i; ++ yy_size_t n, i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = _yybytes_len + 2; +@@ -2913,7 +2913,7 @@ FILE *yyget_out (yyscan_t yyscanner) + /** Get the length of the current token. + * @param yyscanner The scanner object. + */ +-int yyget_leng (yyscan_t yyscanner) ++yy_size_t yyget_leng (yyscan_t yyscanner) + { + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyleng; diff --git a/gfx/angle/src/compiler/BaseTypes.h b/gfx/angle/src/compiler/BaseTypes.h index af4c7e3ed9d3..1631f4f779fa 100644 --- a/gfx/angle/src/compiler/BaseTypes.h +++ b/gfx/angle/src/compiler/BaseTypes.h @@ -90,10 +90,6 @@ enum TQualifier EvqInvariantVaryingOut, // vertex shaders only read/write EvqUniform, // Readonly, vertex and fragment - // pack/unpack input and output - EvqInput, - EvqOutput, - // parameters EvqIn, EvqOut, @@ -112,6 +108,7 @@ enum TQualifier // built-ins written by fragment shader EvqFragColor, EvqFragData, + EvqFragDepth, // end of list EvqLast @@ -137,14 +134,13 @@ inline const char* getQualifierString(TQualifier q) case EvqIn: return "in"; break; case EvqOut: return "out"; break; case EvqInOut: return "inout"; break; - case EvqInput: return "input"; break; - case EvqOutput: return "output"; break; case EvqPosition: return "Position"; break; case EvqPointSize: return "PointSize"; break; case EvqFragCoord: return "FragCoord"; break; case EvqFrontFacing: return "FrontFacing"; break; case EvqFragColor: return "FragColor"; break; case EvqFragData: return "FragData"; break; + case EvqFragDepth: return "FragDepth"; break; default: return "unknown qualifier"; } } diff --git a/gfx/angle/src/compiler/CodeGenHLSL.cpp b/gfx/angle/src/compiler/CodeGenHLSL.cpp index f46ff66d40fb..637ccc5e37be 100644 --- a/gfx/angle/src/compiler/CodeGenHLSL.cpp +++ b/gfx/angle/src/compiler/CodeGenHLSL.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -14,9 +14,11 @@ TCompiler* ConstructCompiler( ShShaderType type, ShShaderSpec spec, ShShaderOutput output) { - switch (output) { - case SH_HLSL_OUTPUT: - return new TranslatorHLSL(type, spec); + switch (output) + { + case SH_HLSL9_OUTPUT: + case SH_HLSL11_OUTPUT: + return new TranslatorHLSL(type, spec, output); default: return NULL; } diff --git a/gfx/angle/src/compiler/Common.h b/gfx/angle/src/compiler/Common.h index 27a559829089..46f9440fff1b 100644 --- a/gfx/angle/src/compiler/Common.h +++ b/gfx/angle/src/compiler/Common.h @@ -14,36 +14,24 @@ #include "compiler/PoolAlloc.h" -// We need two pieces of information to report errors/warnings - string and -// line number. We encode these into a single int so that it can be easily -// incremented/decremented by lexer. The right SOURCE_LOC_LINE_SIZE bits store -// line number while the rest store the string number. Since the shaders are -// usually small, we should not run out of memory. SOURCE_LOC_LINE_SIZE -// can be increased to alleviate this issue. -typedef int TSourceLoc; -const unsigned int SOURCE_LOC_LINE_SIZE = 16; // in bits. -const unsigned int SOURCE_LOC_LINE_MASK = (1 << SOURCE_LOC_LINE_SIZE) - 1; - -inline TSourceLoc EncodeSourceLoc(int string, int line) { - return (string << SOURCE_LOC_LINE_SIZE) | (line & SOURCE_LOC_LINE_MASK); -} - -inline void DecodeSourceLoc(TSourceLoc loc, int* string, int* line) { - if (string) *string = loc >> SOURCE_LOC_LINE_SIZE; - if (line) *line = loc & SOURCE_LOC_LINE_MASK; -} +struct TSourceLoc { + int first_file; + int first_line; + int last_file; + int last_line; +}; // // Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme. // -#define POOL_ALLOCATOR_NEW_DELETE(A) \ - void* operator new(size_t s) { return (A).allocate(s); } \ - void* operator new(size_t, void *_Where) { return (_Where); } \ - void operator delete(void*) { } \ - void operator delete(void *, void *) { } \ - void* operator new[](size_t s) { return (A).allocate(s); } \ - void* operator new[](size_t, void *_Where) { return (_Where); } \ - void operator delete[](void*) { } \ +#define POOL_ALLOCATOR_NEW_DELETE() \ + void* operator new(size_t s) { return GetGlobalPoolAllocator()->allocate(s); } \ + void* operator new(size_t, void *_Where) { return (_Where); } \ + void operator delete(void*) { } \ + void operator delete(void *, void *) { } \ + void* operator new[](size_t s) { return GetGlobalPoolAllocator()->allocate(s); } \ + void* operator new[](size_t, void *_Where) { return (_Where); } \ + void operator delete[](void*) { } \ void operator delete[](void *, void *) { } // @@ -54,7 +42,7 @@ typedef std::basic_string , TStringAllocator> TStri typedef std::basic_ostringstream, TStringAllocator> TStringStream; inline TString* NewPoolTString(const char* s) { - void* memory = GlobalPoolAllocator.allocate(sizeof(TString)); + void* memory = GetGlobalPoolAllocator()->allocate(sizeof(TString)); return new(memory) TString(s); } diff --git a/gfx/angle/src/compiler/Compiler.cpp b/gfx/angle/src/compiler/Compiler.cpp index 5b6136a318df..606b875cfb9f 100644 --- a/gfx/angle/src/compiler/Compiler.cpp +++ b/gfx/angle/src/compiler/Compiler.cpp @@ -1,11 +1,11 @@ // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // #include "compiler/BuiltInFunctionEmulator.h" -#include "compiler/DetectRecursion.h" +#include "compiler/DetectCallDepth.h" #include "compiler/ForLoopUnroll.h" #include "compiler/Initialize.h" #include "compiler/InitializeParseContext.h" @@ -27,51 +27,6 @@ bool isWebGLBasedSpec(ShShaderSpec spec) } namespace { -bool InitializeSymbolTable( - const TBuiltInStrings& builtInStrings, - ShShaderType type, ShShaderSpec spec, const ShBuiltInResources& resources, - TInfoSink& infoSink, TSymbolTable& symbolTable) -{ - TIntermediate intermediate(infoSink); - TExtensionBehavior extBehavior; - InitExtensionBehavior(resources, extBehavior); - // The builtins deliberately don't specify precisions for the function - // arguments and return types. For that reason we don't try to check them. - TParseContext parseContext(symbolTable, extBehavior, intermediate, type, spec, 0, false, NULL, infoSink); - parseContext.fragmentPrecisionHigh = resources.FragmentPrecisionHigh == 1; - - GlobalParseContext = &parseContext; - - assert(symbolTable.isEmpty()); - // - // Parse the built-ins. This should only happen once per - // language symbol table. - // - // Push the symbol table to give it an initial scope. This - // push should not have a corresponding pop, so that built-ins - // are preserved, and the test for an empty table fails. - // - symbolTable.push(); - - for (TBuiltInStrings::const_iterator i = builtInStrings.begin(); i != builtInStrings.end(); ++i) - { - const char* builtInShaders = i->c_str(); - int builtInLengths = static_cast(i->size()); - if (builtInLengths <= 0) - continue; - - if (PaParseStrings(1, &builtInShaders, &builtInLengths, &parseContext) != 0) - { - infoSink.info.message(EPrefixInternalError, "Unable to parse built-ins"); - return false; - } - } - - IdentifyBuiltIns(type, spec, resources, symbolTable); - - return true; -} - class TScopedPoolAllocator { public: TScopedPoolAllocator(TPoolAllocator* allocator, bool pushPop) @@ -103,6 +58,9 @@ TShHandleBase::~TShHandleBase() { TCompiler::TCompiler(ShShaderType type, ShShaderSpec spec) : shaderType(type), shaderSpec(spec), + maxUniformVectors(0), + maxExpressionComplexity(0), + maxCallStackDepth(0), fragmentPrecisionHigh(false), clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC), builtInFunctionEmulator(type) @@ -121,6 +79,8 @@ bool TCompiler::Init(const ShBuiltInResources& resources) maxUniformVectors = (shaderType == SH_VERTEX_SHADER) ? resources.MaxVertexUniformVectors : resources.MaxFragmentUniformVectors; + maxExpressionComplexity = resources.MaxExpressionComplexity; + maxCallStackDepth = resources.MaxCallStackDepth; TScopedPoolAllocator scopedAlloc(&allocator, false); // Generate built-in symbol table. @@ -168,13 +128,15 @@ bool TCompiler::compile(const char* const shaderStrings[], shaderType, shaderSpec, compileOptions, true, sourcePath, infoSink); parseContext.fragmentPrecisionHigh = fragmentPrecisionHigh; - GlobalParseContext = &parseContext; + SetGlobalParseContext(&parseContext); // We preserve symbols at the built-in level from compile-to-compile. // Start pushing the user-defined symbols at global level. symbolTable.push(); - if (!symbolTable.atGlobalLevel()) - infoSink.info.message(EPrefixInternalError, "Wrong symbol table level"); + if (!symbolTable.atGlobalLevel()) { + infoSink.info.prefix(EPrefixInternalError); + infoSink.info << "Wrong symbol table level"; + } // Parse shader. bool success = @@ -185,7 +147,7 @@ bool TCompiler::compile(const char* const shaderStrings[], success = intermediate.postProcess(root); if (success) - success = detectRecursion(root); + success = detectCallDepth(root, infoSink, (compileOptions & SH_LIMIT_CALL_STACK_DEPTH) != 0); if (success && (compileOptions & SH_VALIDATE_LOOP_INDEXING)) success = validateLimitations(root); @@ -208,6 +170,10 @@ bool TCompiler::compile(const char* const shaderStrings[], if (success && (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS)) arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root); + // Disallow expressions deemed too complex. + if (success && (compileOptions & SH_LIMIT_EXPRESSION_COMPLEXITY)) + success = limitExpressionComplexity(root); + // Call mapLongVariableNames() before collectAttribsUniforms() so in // collectAttribsUniforms() we already have the mapped symbol names and // we could composite mapped and original variable names. @@ -220,7 +186,8 @@ bool TCompiler::compile(const char* const shaderStrings[], if (compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS) { success = enforcePackingRestrictions(); if (!success) { - infoSink.info.message(EPrefixError, "too many uniforms"); + infoSink.info.prefix(EPrefixError); + infoSink.info << "too many uniforms"; } } } @@ -242,13 +209,42 @@ bool TCompiler::compile(const char* const shaderStrings[], return success; } -bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources& resources) +bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources) { - TBuiltIns builtIns; + compileResources = resources; - builtIns.initialize(shaderType, shaderSpec, resources); - return InitializeSymbolTable(builtIns.getBuiltInStrings(), - shaderType, shaderSpec, resources, infoSink, symbolTable); + assert(symbolTable.isEmpty()); + symbolTable.push(); + + TPublicType integer; + integer.type = EbtInt; + integer.size = 1; + integer.matrix = false; + integer.array = false; + + TPublicType floatingPoint; + floatingPoint.type = EbtFloat; + floatingPoint.size = 1; + floatingPoint.matrix = false; + floatingPoint.array = false; + + switch(shaderType) + { + case SH_FRAGMENT_SHADER: + symbolTable.setDefaultPrecision(integer, EbpMedium); + break; + case SH_VERTEX_SHADER: + symbolTable.setDefaultPrecision(integer, EbpHigh); + symbolTable.setDefaultPrecision(floatingPoint, EbpHigh); + break; + default: assert(false && "Language not supported"); + } + + InsertBuiltInFunctions(shaderType, shaderSpec, resources, symbolTable); + + IdentifyBuiltIns(shaderType, shaderSpec, resources, symbolTable); + + return true; } void TCompiler::clearResults() @@ -266,18 +262,24 @@ void TCompiler::clearResults() nameMap.clear(); } -bool TCompiler::detectRecursion(TIntermNode* root) +bool TCompiler::detectCallDepth(TIntermNode* root, TInfoSink& infoSink, bool limitCallStackDepth) { - DetectRecursion detect; + DetectCallDepth detect(infoSink, limitCallStackDepth, maxCallStackDepth); root->traverse(&detect); - switch (detect.detectRecursion()) { - case DetectRecursion::kErrorNone: + switch (detect.detectCallDepth()) { + case DetectCallDepth::kErrorNone: return true; - case DetectRecursion::kErrorMissingMain: - infoSink.info.message(EPrefixError, "Missing main()"); + case DetectCallDepth::kErrorMissingMain: + infoSink.info.prefix(EPrefixError); + infoSink.info << "Missing main()"; return false; - case DetectRecursion::kErrorRecursion: - infoSink.info.message(EPrefixError, "Function recursion detected"); + case DetectCallDepth::kErrorRecursion: + infoSink.info.prefix(EPrefixError); + infoSink.info << "Function recursion detected"; + return false; + case DetectCallDepth::kErrorMaxDepthExceeded: + infoSink.info.prefix(EPrefixError); + infoSink.info << "Function call stack too deep"; return false; default: UNREACHABLE(); @@ -323,6 +325,28 @@ bool TCompiler::enforceTimingRestrictions(TIntermNode* root, bool outputGraph) } } +bool TCompiler::limitExpressionComplexity(TIntermNode* root) +{ + TIntermTraverser traverser; + root->traverse(&traverser); + TDependencyGraph graph(root); + + for (TFunctionCallVector::const_iterator iter = graph.beginUserDefinedFunctionCalls(); + iter != graph.endUserDefinedFunctionCalls(); + ++iter) + { + TGraphFunctionCall* samplerSymbol = *iter; + TDependencyGraphTraverser graphTraverser; + samplerSymbol->traverse(&graphTraverser); + } + + if (traverser.getMaxDepth() > maxExpressionComplexity) { + infoSink.info << "Expression too complex."; + return false; + } + return true; +} + bool TCompiler::enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph) { RestrictFragmentShaderTiming restrictor(infoSink.info); @@ -366,6 +390,11 @@ const TExtensionBehavior& TCompiler::getExtensionBehavior() const return extensionBehavior; } +const ShBuiltInResources& TCompiler::getResources() const +{ + return compileResources; +} + const ArrayBoundsClamper& TCompiler::getArrayBoundsClamper() const { return arrayBoundsClamper; diff --git a/gfx/angle/src/compiler/CompilerUniform.cpp b/gfx/angle/src/compiler/CompilerUniform.cpp new file mode 100644 index 000000000000..e3c234685829 --- /dev/null +++ b/gfx/angle/src/compiler/CompilerUniform.cpp @@ -0,0 +1,21 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "CompilerUniform.h" + +namespace sh +{ + +Uniform::Uniform(GLenum type, GLenum precision, const char *name, int arraySize, int registerIndex) +{ + this->type = type; + this->precision = precision; + this->name = name; + this->arraySize = arraySize; + this->registerIndex = registerIndex; +} + +} diff --git a/gfx/angle/src/compiler/CompilerUniform.h b/gfx/angle/src/compiler/CompilerUniform.h new file mode 100644 index 000000000000..2ffd51eeaf28 --- /dev/null +++ b/gfx/angle/src/compiler/CompilerUniform.h @@ -0,0 +1,35 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_UNIFORM_H_ +#define COMPILER_UNIFORM_H_ + +#include +#include + +#define GL_APICALL +#include + +namespace sh +{ + +struct Uniform +{ + Uniform(GLenum type, GLenum precision, const char *name, int arraySize, int registerIndex); + + GLenum type; + GLenum precision; + std::string name; + unsigned int arraySize; + + int registerIndex; +}; + +typedef std::vector ActiveUniforms; + +} + +#endif // COMPILER_UNIFORM_H_ diff --git a/gfx/angle/src/compiler/ConstantUnion.h b/gfx/angle/src/compiler/ConstantUnion.h index 32af4d38b0b5..b1e37885f901 100644 --- a/gfx/angle/src/compiler/ConstantUnion.h +++ b/gfx/angle/src/compiler/ConstantUnion.h @@ -11,13 +11,13 @@ class ConstantUnion { public: + POOL_ALLOCATOR_NEW_DELETE(); ConstantUnion() { iConst = 0; type = EbtVoid; } - POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) void setIConst(int i) {iConst = i; type = EbtInt; } void setFConst(float f) {fConst = f; type = EbtFloat; } void setBConst(bool b) {bConst = b; type = EbtBool; } diff --git a/gfx/angle/src/compiler/DetectCallDepth.cpp b/gfx/angle/src/compiler/DetectCallDepth.cpp new file mode 100644 index 000000000000..60df52c7151a --- /dev/null +++ b/gfx/angle/src/compiler/DetectCallDepth.cpp @@ -0,0 +1,185 @@ +// +// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/DetectCallDepth.h" +#include "compiler/InfoSink.h" + +DetectCallDepth::FunctionNode::FunctionNode(const TString& fname) + : name(fname), + visit(PreVisit) +{ +} + +const TString& DetectCallDepth::FunctionNode::getName() const +{ + return name; +} + +void DetectCallDepth::FunctionNode::addCallee( + DetectCallDepth::FunctionNode* callee) +{ + for (size_t i = 0; i < callees.size(); ++i) { + if (callees[i] == callee) + return; + } + callees.push_back(callee); +} + +int DetectCallDepth::FunctionNode::detectCallDepth(DetectCallDepth* detectCallDepth, int depth) +{ + ASSERT(visit == PreVisit); + ASSERT(detectCallDepth); + + int maxDepth = depth; + visit = InVisit; + for (size_t i = 0; i < callees.size(); ++i) { + switch (callees[i]->visit) { + case InVisit: + // cycle detected, i.e., recursion detected. + return kInfiniteCallDepth; + case PostVisit: + break; + case PreVisit: { + // Check before we recurse so we don't go too depth + if (detectCallDepth->checkExceedsMaxDepth(depth)) + return depth; + int callDepth = callees[i]->detectCallDepth(detectCallDepth, depth + 1); + // Check after we recurse so we can exit immediately and provide info. + if (detectCallDepth->checkExceedsMaxDepth(callDepth)) { + detectCallDepth->getInfoSink().info << "<-" << callees[i]->getName(); + return callDepth; + } + maxDepth = std::max(callDepth, maxDepth); + break; + } + default: + UNREACHABLE(); + break; + } + } + visit = PostVisit; + return maxDepth; +} + +void DetectCallDepth::FunctionNode::reset() +{ + visit = PreVisit; +} + +DetectCallDepth::DetectCallDepth(TInfoSink& infoSink, bool limitCallStackDepth, int maxCallStackDepth) + : TIntermTraverser(true, false, true, false), + currentFunction(NULL), + infoSink(infoSink), + maxDepth(limitCallStackDepth ? maxCallStackDepth : FunctionNode::kInfiniteCallDepth) +{ +} + +DetectCallDepth::~DetectCallDepth() +{ + for (size_t i = 0; i < functions.size(); ++i) + delete functions[i]; +} + +bool DetectCallDepth::visitAggregate(Visit visit, TIntermAggregate* node) +{ + switch (node->getOp()) + { + case EOpPrototype: + // Function declaration. + // Don't add FunctionNode here because node->getName() is the + // unmangled function name. + break; + case EOpFunction: { + // Function definition. + if (visit == PreVisit) { + currentFunction = findFunctionByName(node->getName()); + if (currentFunction == NULL) { + currentFunction = new FunctionNode(node->getName()); + functions.push_back(currentFunction); + } + } else if (visit == PostVisit) { + currentFunction = NULL; + } + break; + } + case EOpFunctionCall: { + // Function call. + if (visit == PreVisit) { + FunctionNode* func = findFunctionByName(node->getName()); + if (func == NULL) { + func = new FunctionNode(node->getName()); + functions.push_back(func); + } + if (currentFunction) + currentFunction->addCallee(func); + } + break; + } + default: + break; + } + return true; +} + +bool DetectCallDepth::checkExceedsMaxDepth(int depth) +{ + return depth >= maxDepth; +} + +void DetectCallDepth::resetFunctionNodes() +{ + for (size_t i = 0; i < functions.size(); ++i) { + functions[i]->reset(); + } +} + +DetectCallDepth::ErrorCode DetectCallDepth::detectCallDepthForFunction(FunctionNode* func) +{ + currentFunction = NULL; + resetFunctionNodes(); + + int maxCallDepth = func->detectCallDepth(this, 1); + + if (maxCallDepth == FunctionNode::kInfiniteCallDepth) + return kErrorRecursion; + + if (maxCallDepth >= maxDepth) + return kErrorMaxDepthExceeded; + + return kErrorNone; +} + +DetectCallDepth::ErrorCode DetectCallDepth::detectCallDepth() +{ + if (maxDepth != FunctionNode::kInfiniteCallDepth) { + // Check all functions because the driver may fail on them + // TODO: Before detectingRecursion, strip unused functions. + for (size_t i = 0; i < functions.size(); ++i) { + ErrorCode error = detectCallDepthForFunction(functions[i]); + if (error != kErrorNone) + return error; + } + } else { + FunctionNode* main = findFunctionByName("main("); + if (main == NULL) + return kErrorMissingMain; + + return detectCallDepthForFunction(main); + } + + return kErrorNone; +} + +DetectCallDepth::FunctionNode* DetectCallDepth::findFunctionByName( + const TString& name) +{ + for (size_t i = 0; i < functions.size(); ++i) { + if (functions[i]->getName() == name) + return functions[i]; + } + return NULL; +} + diff --git a/gfx/angle/src/compiler/DetectRecursion.h b/gfx/angle/src/compiler/DetectCallDepth.h similarity index 59% rename from gfx/angle/src/compiler/DetectRecursion.h rename to gfx/angle/src/compiler/DetectCallDepth.h index bbac79dc9ce6..89e85f88f6ea 100644 --- a/gfx/angle/src/compiler/DetectRecursion.h +++ b/gfx/angle/src/compiler/DetectCallDepth.h @@ -9,28 +9,36 @@ #include "GLSLANG/ShaderLang.h" +#include #include "compiler/intermediate.h" #include "compiler/VariableInfo.h" +class TInfoSink; + // Traverses intermediate tree to detect function recursion. -class DetectRecursion : public TIntermTraverser { +class DetectCallDepth : public TIntermTraverser { public: enum ErrorCode { kErrorMissingMain, kErrorRecursion, + kErrorMaxDepthExceeded, kErrorNone }; - DetectRecursion(); - ~DetectRecursion(); + DetectCallDepth(TInfoSink& infoSync, bool limitCallStackDepth, int maxCallStackDepth); + ~DetectCallDepth(); virtual bool visitAggregate(Visit, TIntermAggregate*); - ErrorCode detectRecursion(); + bool checkExceedsMaxDepth(int depth); + + ErrorCode detectCallDepth(); private: class FunctionNode { public: + static const int kInfiniteCallDepth = INT_MAX; + FunctionNode(const TString& fname); const TString& getName() const; @@ -38,8 +46,11 @@ private: // If a function is already in the callee list, this becomes a no-op. void addCallee(FunctionNode* callee); - // Return true if recursive function calls are detected. - bool detectRecursion(); + // Returns kInifinityCallDepth if recursive function calls are detected. + int detectCallDepth(DetectCallDepth* detectCallDepth, int depth); + + // Reset state. + void reset(); private: // mangled function name is unique. @@ -51,10 +62,19 @@ private: Visit visit; }; + ErrorCode detectCallDepthForFunction(FunctionNode* func); FunctionNode* findFunctionByName(const TString& name); + void resetFunctionNodes(); + + TInfoSink& getInfoSink() { return infoSink; } TVector functions; FunctionNode* currentFunction; + TInfoSink& infoSink; + int maxDepth; + + DetectCallDepth(const DetectCallDepth&); + void operator=(const DetectCallDepth&); }; #endif // COMPILER_DETECT_RECURSION_H_ diff --git a/gfx/angle/src/compiler/DetectRecursion.cpp b/gfx/angle/src/compiler/DetectRecursion.cpp deleted file mode 100644 index c09780dd92d5..000000000000 --- a/gfx/angle/src/compiler/DetectRecursion.cpp +++ /dev/null @@ -1,125 +0,0 @@ -// -// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/DetectRecursion.h" - -DetectRecursion::FunctionNode::FunctionNode(const TString& fname) - : name(fname), - visit(PreVisit) -{ -} - -const TString& DetectRecursion::FunctionNode::getName() const -{ - return name; -} - -void DetectRecursion::FunctionNode::addCallee( - DetectRecursion::FunctionNode* callee) -{ - for (size_t i = 0; i < callees.size(); ++i) { - if (callees[i] == callee) - return; - } - callees.push_back(callee); -} - -bool DetectRecursion::FunctionNode::detectRecursion() -{ - ASSERT(visit == PreVisit); - visit = InVisit; - for (size_t i = 0; i < callees.size(); ++i) { - switch (callees[i]->visit) { - case InVisit: - // cycle detected, i.e., recursion detected. - return true; - case PostVisit: - break; - case PreVisit: { - bool recursion = callees[i]->detectRecursion(); - if (recursion) - return true; - break; - } - default: - UNREACHABLE(); - break; - } - } - visit = PostVisit; - return false; -} - -DetectRecursion::DetectRecursion() - : currentFunction(NULL) -{ -} - -DetectRecursion::~DetectRecursion() -{ - for (size_t i = 0; i < functions.size(); ++i) - delete functions[i]; -} - -bool DetectRecursion::visitAggregate(Visit visit, TIntermAggregate* node) -{ - switch (node->getOp()) - { - case EOpPrototype: - // Function declaration. - // Don't add FunctionNode here because node->getName() is the - // unmangled function name. - break; - case EOpFunction: { - // Function definition. - if (visit == PreVisit) { - currentFunction = findFunctionByName(node->getName()); - if (currentFunction == NULL) { - currentFunction = new FunctionNode(node->getName()); - functions.push_back(currentFunction); - } - } - break; - } - case EOpFunctionCall: { - // Function call. - if (visit == PreVisit) { - ASSERT(currentFunction != NULL); - FunctionNode* func = findFunctionByName(node->getName()); - if (func == NULL) { - func = new FunctionNode(node->getName()); - functions.push_back(func); - } - currentFunction->addCallee(func); - } - break; - } - default: - break; - } - return true; -} - -DetectRecursion::ErrorCode DetectRecursion::detectRecursion() -{ - FunctionNode* main = findFunctionByName("main("); - if (main == NULL) - return kErrorMissingMain; - if (main->detectRecursion()) - return kErrorRecursion; - return kErrorNone; -} - -DetectRecursion::FunctionNode* DetectRecursion::findFunctionByName( - const TString& name) -{ - for (size_t i = 0; i < functions.size(); ++i) { - if (functions[i]->getName() == name) - return functions[i]; - } - return NULL; -} - diff --git a/gfx/angle/src/compiler/Diagnostics.cpp b/gfx/angle/src/compiler/Diagnostics.cpp index 5bfd2199e816..7396a0a23f72 100644 --- a/gfx/angle/src/compiler/Diagnostics.cpp +++ b/gfx/angle/src/compiler/Diagnostics.cpp @@ -46,7 +46,7 @@ void TDiagnostics::writeInfo(Severity severity, TInfoSinkBase& sink = mInfoSink.info; /* VC++ format: file(linenum) : error #: 'token' : extrainfo */ sink.prefix(prefix); - sink.location(EncodeSourceLoc(loc.file, loc.line)); + sink.location(loc.file, loc.line); sink << "'" << token << "' : " << reason << " " << extra << "\n"; } diff --git a/gfx/angle/src/compiler/InfoSink.cpp b/gfx/angle/src/compiler/InfoSink.cpp index ba32f781f548..d20a6c0175ac 100644 --- a/gfx/angle/src/compiler/InfoSink.cpp +++ b/gfx/angle/src/compiler/InfoSink.cpp @@ -6,8 +6,8 @@ #include "compiler/InfoSink.h" -void TInfoSinkBase::prefix(TPrefixType message) { - switch(message) { +void TInfoSinkBase::prefix(TPrefixType p) { + switch(p) { case EPrefixNone: break; case EPrefixWarning: @@ -31,29 +31,24 @@ void TInfoSinkBase::prefix(TPrefixType message) { } } -void TInfoSinkBase::location(TSourceLoc loc) { - int string = 0, line = 0; - DecodeSourceLoc(loc, &string, &line); - +void TInfoSinkBase::location(int file, int line) { TPersistStringStream stream; if (line) - stream << string << ":" << line; + stream << file << ":" << line; else - stream << string << ":? "; + stream << file << ":? "; stream << ": "; sink.append(stream.str()); } -void TInfoSinkBase::message(TPrefixType message, const char* s) { - prefix(message); - sink.append(s); - sink.append("\n"); +void TInfoSinkBase::location(const TSourceLoc& loc) { + location(loc.first_file, loc.first_line); } -void TInfoSinkBase::message(TPrefixType message, const char* s, TSourceLoc loc) { - prefix(message); +void TInfoSinkBase::message(TPrefixType p, const TSourceLoc& loc, const char* m) { + prefix(p); location(loc); - sink.append(s); + sink.append(m); sink.append("\n"); } diff --git a/gfx/angle/src/compiler/InfoSink.h b/gfx/angle/src/compiler/InfoSink.h index e2224e918d04..688883814225 100644 --- a/gfx/angle/src/compiler/InfoSink.h +++ b/gfx/angle/src/compiler/InfoSink.h @@ -96,10 +96,10 @@ public: const TPersistString& str() const { return sink; } const char* c_str() const { return sink.c_str(); } - void prefix(TPrefixType message); - void location(TSourceLoc loc); - void message(TPrefixType message, const char* s); - void message(TPrefixType message, const char* s, TSourceLoc loc); + void prefix(TPrefixType p); + void location(int file, int line); + void location(const TSourceLoc& loc); + void message(TPrefixType p, const TSourceLoc& loc, const char* m); private: TPersistString sink; diff --git a/gfx/angle/src/compiler/Initialize.cpp b/gfx/angle/src/compiler/Initialize.cpp index 97b46f898e8f..2cdbe17aa6d5 100644 --- a/gfx/angle/src/compiler/Initialize.cpp +++ b/gfx/angle/src/compiler/Initialize.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -14,513 +14,413 @@ #include "compiler/intermediate.h" -//============================================================================ -// -// Prototypes for built-in functions seen by both vertex and fragment shaders. -// -//============================================================================ -static TString BuiltInFunctionsCommon(const ShBuiltInResources& resources) +void InsertBuiltInFunctions(ShShaderType type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &symbolTable) { - TString s; + TType *float1 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 1); + TType *float2 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 2); + TType *float3 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 3); + TType *float4 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 4); + + TType *int2 = new TType(EbtInt, EbpUndefined, EvqGlobal, 2); + TType *int3 = new TType(EbtInt, EbpUndefined, EvqGlobal, 3); + TType *int4 = new TType(EbtInt, EbpUndefined, EvqGlobal, 4); // // Angle and Trigonometric Functions. // - s.append(TString("float radians(float degrees);")); - s.append(TString("vec2 radians(vec2 degrees);")); - s.append(TString("vec3 radians(vec3 degrees);")); - s.append(TString("vec4 radians(vec4 degrees);")); + symbolTable.insertBuiltIn(float1, "radians", float1); + symbolTable.insertBuiltIn(float2, "radians", float2); + symbolTable.insertBuiltIn(float3, "radians", float3); + symbolTable.insertBuiltIn(float4, "radians", float4); - s.append(TString("float degrees(float radians);")); - s.append(TString("vec2 degrees(vec2 radians);")); - s.append(TString("vec3 degrees(vec3 radians);")); - s.append(TString("vec4 degrees(vec4 radians);")); + symbolTable.insertBuiltIn(float1, "degrees", float1); + symbolTable.insertBuiltIn(float2, "degrees", float2); + symbolTable.insertBuiltIn(float3, "degrees", float3); + symbolTable.insertBuiltIn(float4, "degrees", float4); - s.append(TString("float sin(float angle);")); - s.append(TString("vec2 sin(vec2 angle);")); - s.append(TString("vec3 sin(vec3 angle);")); - s.append(TString("vec4 sin(vec4 angle);")); + symbolTable.insertBuiltIn(float1, "sin", float1); + symbolTable.insertBuiltIn(float2, "sin", float2); + symbolTable.insertBuiltIn(float3, "sin", float3); + symbolTable.insertBuiltIn(float4, "sin", float4); - s.append(TString("float cos(float angle);")); - s.append(TString("vec2 cos(vec2 angle);")); - s.append(TString("vec3 cos(vec3 angle);")); - s.append(TString("vec4 cos(vec4 angle);")); + symbolTable.insertBuiltIn(float1, "cos", float1); + symbolTable.insertBuiltIn(float2, "cos", float2); + symbolTable.insertBuiltIn(float3, "cos", float3); + symbolTable.insertBuiltIn(float4, "cos", float4); - s.append(TString("float tan(float angle);")); - s.append(TString("vec2 tan(vec2 angle);")); - s.append(TString("vec3 tan(vec3 angle);")); - s.append(TString("vec4 tan(vec4 angle);")); + symbolTable.insertBuiltIn(float1, "tan", float1); + symbolTable.insertBuiltIn(float2, "tan", float2); + symbolTable.insertBuiltIn(float3, "tan", float3); + symbolTable.insertBuiltIn(float4, "tan", float4); - s.append(TString("float asin(float x);")); - s.append(TString("vec2 asin(vec2 x);")); - s.append(TString("vec3 asin(vec3 x);")); - s.append(TString("vec4 asin(vec4 x);")); + symbolTable.insertBuiltIn(float1, "asin", float1); + symbolTable.insertBuiltIn(float2, "asin", float2); + symbolTable.insertBuiltIn(float3, "asin", float3); + symbolTable.insertBuiltIn(float4, "asin", float4); - s.append(TString("float acos(float x);")); - s.append(TString("vec2 acos(vec2 x);")); - s.append(TString("vec3 acos(vec3 x);")); - s.append(TString("vec4 acos(vec4 x);")); + symbolTable.insertBuiltIn(float1, "acos", float1); + symbolTable.insertBuiltIn(float2, "acos", float2); + symbolTable.insertBuiltIn(float3, "acos", float3); + symbolTable.insertBuiltIn(float4, "acos", float4); - s.append(TString("float atan(float y, float x);")); - s.append(TString("vec2 atan(vec2 y, vec2 x);")); - s.append(TString("vec3 atan(vec3 y, vec3 x);")); - s.append(TString("vec4 atan(vec4 y, vec4 x);")); + symbolTable.insertBuiltIn(float1, "atan", float1, float1); + symbolTable.insertBuiltIn(float2, "atan", float2, float2); + symbolTable.insertBuiltIn(float3, "atan", float3, float3); + symbolTable.insertBuiltIn(float4, "atan", float4, float4); - s.append(TString("float atan(float y_over_x);")); - s.append(TString("vec2 atan(vec2 y_over_x);")); - s.append(TString("vec3 atan(vec3 y_over_x);")); - s.append(TString("vec4 atan(vec4 y_over_x);")); + symbolTable.insertBuiltIn(float1, "atan", float1); + symbolTable.insertBuiltIn(float2, "atan", float2); + symbolTable.insertBuiltIn(float3, "atan", float3); + symbolTable.insertBuiltIn(float4, "atan", float4); // // Exponential Functions. // - s.append(TString("float pow(float x, float y);")); - s.append(TString("vec2 pow(vec2 x, vec2 y);")); - s.append(TString("vec3 pow(vec3 x, vec3 y);")); - s.append(TString("vec4 pow(vec4 x, vec4 y);")); + symbolTable.insertBuiltIn(float1, "pow", float1, float1); + symbolTable.insertBuiltIn(float2, "pow", float2, float2); + symbolTable.insertBuiltIn(float3, "pow", float3, float3); + symbolTable.insertBuiltIn(float4, "pow", float4, float4); - s.append(TString("float exp(float x);")); - s.append(TString("vec2 exp(vec2 x);")); - s.append(TString("vec3 exp(vec3 x);")); - s.append(TString("vec4 exp(vec4 x);")); + symbolTable.insertBuiltIn(float1, "exp", float1); + symbolTable.insertBuiltIn(float2, "exp", float2); + symbolTable.insertBuiltIn(float3, "exp", float3); + symbolTable.insertBuiltIn(float4, "exp", float4); - s.append(TString("float log(float x);")); - s.append(TString("vec2 log(vec2 x);")); - s.append(TString("vec3 log(vec3 x);")); - s.append(TString("vec4 log(vec4 x);")); + symbolTable.insertBuiltIn(float1, "log", float1); + symbolTable.insertBuiltIn(float2, "log", float2); + symbolTable.insertBuiltIn(float3, "log", float3); + symbolTable.insertBuiltIn(float4, "log", float4); - s.append(TString("float exp2(float x);")); - s.append(TString("vec2 exp2(vec2 x);")); - s.append(TString("vec3 exp2(vec3 x);")); - s.append(TString("vec4 exp2(vec4 x);")); + symbolTable.insertBuiltIn(float1, "exp2", float1); + symbolTable.insertBuiltIn(float2, "exp2", float2); + symbolTable.insertBuiltIn(float3, "exp2", float3); + symbolTable.insertBuiltIn(float4, "exp2", float4); - s.append(TString("float log2(float x);")); - s.append(TString("vec2 log2(vec2 x);")); - s.append(TString("vec3 log2(vec3 x);")); - s.append(TString("vec4 log2(vec4 x);")); + symbolTable.insertBuiltIn(float1, "log2", float1); + symbolTable.insertBuiltIn(float2, "log2", float2); + symbolTable.insertBuiltIn(float3, "log2", float3); + symbolTable.insertBuiltIn(float4, "log2", float4); - s.append(TString("float sqrt(float x);")); - s.append(TString("vec2 sqrt(vec2 x);")); - s.append(TString("vec3 sqrt(vec3 x);")); - s.append(TString("vec4 sqrt(vec4 x);")); + symbolTable.insertBuiltIn(float1, "sqrt", float1); + symbolTable.insertBuiltIn(float2, "sqrt", float2); + symbolTable.insertBuiltIn(float3, "sqrt", float3); + symbolTable.insertBuiltIn(float4, "sqrt", float4); - s.append(TString("float inversesqrt(float x);")); - s.append(TString("vec2 inversesqrt(vec2 x);")); - s.append(TString("vec3 inversesqrt(vec3 x);")); - s.append(TString("vec4 inversesqrt(vec4 x);")); + symbolTable.insertBuiltIn(float1, "inversesqrt", float1); + symbolTable.insertBuiltIn(float2, "inversesqrt", float2); + symbolTable.insertBuiltIn(float3, "inversesqrt", float3); + symbolTable.insertBuiltIn(float4, "inversesqrt", float4); // // Common Functions. // - s.append(TString("float abs(float x);")); - s.append(TString("vec2 abs(vec2 x);")); - s.append(TString("vec3 abs(vec3 x);")); - s.append(TString("vec4 abs(vec4 x);")); + symbolTable.insertBuiltIn(float1, "abs", float1); + symbolTable.insertBuiltIn(float2, "abs", float2); + symbolTable.insertBuiltIn(float3, "abs", float3); + symbolTable.insertBuiltIn(float4, "abs", float4); - s.append(TString("float sign(float x);")); - s.append(TString("vec2 sign(vec2 x);")); - s.append(TString("vec3 sign(vec3 x);")); - s.append(TString("vec4 sign(vec4 x);")); + symbolTable.insertBuiltIn(float1, "sign", float1); + symbolTable.insertBuiltIn(float2, "sign", float2); + symbolTable.insertBuiltIn(float3, "sign", float3); + symbolTable.insertBuiltIn(float4, "sign", float4); - s.append(TString("float floor(float x);")); - s.append(TString("vec2 floor(vec2 x);")); - s.append(TString("vec3 floor(vec3 x);")); - s.append(TString("vec4 floor(vec4 x);")); + symbolTable.insertBuiltIn(float1, "floor", float1); + symbolTable.insertBuiltIn(float2, "floor", float2); + symbolTable.insertBuiltIn(float3, "floor", float3); + symbolTable.insertBuiltIn(float4, "floor", float4); - s.append(TString("float ceil(float x);")); - s.append(TString("vec2 ceil(vec2 x);")); - s.append(TString("vec3 ceil(vec3 x);")); - s.append(TString("vec4 ceil(vec4 x);")); + symbolTable.insertBuiltIn(float1, "ceil", float1); + symbolTable.insertBuiltIn(float2, "ceil", float2); + symbolTable.insertBuiltIn(float3, "ceil", float3); + symbolTable.insertBuiltIn(float4, "ceil", float4); - s.append(TString("float fract(float x);")); - s.append(TString("vec2 fract(vec2 x);")); - s.append(TString("vec3 fract(vec3 x);")); - s.append(TString("vec4 fract(vec4 x);")); + symbolTable.insertBuiltIn(float1, "fract", float1); + symbolTable.insertBuiltIn(float2, "fract", float2); + symbolTable.insertBuiltIn(float3, "fract", float3); + symbolTable.insertBuiltIn(float4, "fract", float4); - s.append(TString("float mod(float x, float y);")); - s.append(TString("vec2 mod(vec2 x, float y);")); - s.append(TString("vec3 mod(vec3 x, float y);")); - s.append(TString("vec4 mod(vec4 x, float y);")); - s.append(TString("vec2 mod(vec2 x, vec2 y);")); - s.append(TString("vec3 mod(vec3 x, vec3 y);")); - s.append(TString("vec4 mod(vec4 x, vec4 y);")); + symbolTable.insertBuiltIn(float1, "mod", float1, float1); + symbolTable.insertBuiltIn(float2, "mod", float2, float1); + symbolTable.insertBuiltIn(float3, "mod", float3, float1); + symbolTable.insertBuiltIn(float4, "mod", float4, float1); + symbolTable.insertBuiltIn(float2, "mod", float2, float2); + symbolTable.insertBuiltIn(float3, "mod", float3, float3); + symbolTable.insertBuiltIn(float4, "mod", float4, float4); - s.append(TString("float min(float x, float y);")); - s.append(TString("vec2 min(vec2 x, float y);")); - s.append(TString("vec3 min(vec3 x, float y);")); - s.append(TString("vec4 min(vec4 x, float y);")); - s.append(TString("vec2 min(vec2 x, vec2 y);")); - s.append(TString("vec3 min(vec3 x, vec3 y);")); - s.append(TString("vec4 min(vec4 x, vec4 y);")); + symbolTable.insertBuiltIn(float1, "min", float1, float1); + symbolTable.insertBuiltIn(float2, "min", float2, float1); + symbolTable.insertBuiltIn(float3, "min", float3, float1); + symbolTable.insertBuiltIn(float4, "min", float4, float1); + symbolTable.insertBuiltIn(float2, "min", float2, float2); + symbolTable.insertBuiltIn(float3, "min", float3, float3); + symbolTable.insertBuiltIn(float4, "min", float4, float4); - s.append(TString("float max(float x, float y);")); - s.append(TString("vec2 max(vec2 x, float y);")); - s.append(TString("vec3 max(vec3 x, float y);")); - s.append(TString("vec4 max(vec4 x, float y);")); - s.append(TString("vec2 max(vec2 x, vec2 y);")); - s.append(TString("vec3 max(vec3 x, vec3 y);")); - s.append(TString("vec4 max(vec4 x, vec4 y);")); + symbolTable.insertBuiltIn(float1, "max", float1, float1); + symbolTable.insertBuiltIn(float2, "max", float2, float1); + symbolTable.insertBuiltIn(float3, "max", float3, float1); + symbolTable.insertBuiltIn(float4, "max", float4, float1); + symbolTable.insertBuiltIn(float2, "max", float2, float2); + symbolTable.insertBuiltIn(float3, "max", float3, float3); + symbolTable.insertBuiltIn(float4, "max", float4, float4); - s.append(TString("float clamp(float x, float minVal, float maxVal);")); - s.append(TString("vec2 clamp(vec2 x, float minVal, float maxVal);")); - s.append(TString("vec3 clamp(vec3 x, float minVal, float maxVal);")); - s.append(TString("vec4 clamp(vec4 x, float minVal, float maxVal);")); - s.append(TString("vec2 clamp(vec2 x, vec2 minVal, vec2 maxVal);")); - s.append(TString("vec3 clamp(vec3 x, vec3 minVal, vec3 maxVal);")); - s.append(TString("vec4 clamp(vec4 x, vec4 minVal, vec4 maxVal);")); + symbolTable.insertBuiltIn(float1, "clamp", float1, float1, float1); + symbolTable.insertBuiltIn(float2, "clamp", float2, float1, float1); + symbolTable.insertBuiltIn(float3, "clamp", float3, float1, float1); + symbolTable.insertBuiltIn(float4, "clamp", float4, float1, float1); + symbolTable.insertBuiltIn(float2, "clamp", float2, float2, float2); + symbolTable.insertBuiltIn(float3, "clamp", float3, float3, float3); + symbolTable.insertBuiltIn(float4, "clamp", float4, float4, float4); - s.append(TString("float mix(float x, float y, float a);")); - s.append(TString("vec2 mix(vec2 x, vec2 y, float a);")); - s.append(TString("vec3 mix(vec3 x, vec3 y, float a);")); - s.append(TString("vec4 mix(vec4 x, vec4 y, float a);")); - s.append(TString("vec2 mix(vec2 x, vec2 y, vec2 a);")); - s.append(TString("vec3 mix(vec3 x, vec3 y, vec3 a);")); - s.append(TString("vec4 mix(vec4 x, vec4 y, vec4 a);")); + symbolTable.insertBuiltIn(float1, "mix", float1, float1, float1); + symbolTable.insertBuiltIn(float2, "mix", float2, float2, float1); + symbolTable.insertBuiltIn(float3, "mix", float3, float3, float1); + symbolTable.insertBuiltIn(float4, "mix", float4, float4, float1); + symbolTable.insertBuiltIn(float2, "mix", float2, float2, float2); + symbolTable.insertBuiltIn(float3, "mix", float3, float3, float3); + symbolTable.insertBuiltIn(float4, "mix", float4, float4, float4); - s.append(TString("float step(float edge, float x);")); - s.append(TString("vec2 step(vec2 edge, vec2 x);")); - s.append(TString("vec3 step(vec3 edge, vec3 x);")); - s.append(TString("vec4 step(vec4 edge, vec4 x);")); - s.append(TString("vec2 step(float edge, vec2 x);")); - s.append(TString("vec3 step(float edge, vec3 x);")); - s.append(TString("vec4 step(float edge, vec4 x);")); + symbolTable.insertBuiltIn(float1, "step", float1, float1); + symbolTable.insertBuiltIn(float2, "step", float2, float2); + symbolTable.insertBuiltIn(float3, "step", float3, float3); + symbolTable.insertBuiltIn(float4, "step", float4, float4); + symbolTable.insertBuiltIn(float2, "step", float1, float2); + symbolTable.insertBuiltIn(float3, "step", float1, float3); + symbolTable.insertBuiltIn(float4, "step", float1, float4); - s.append(TString("float smoothstep(float edge0, float edge1, float x);")); - s.append(TString("vec2 smoothstep(vec2 edge0, vec2 edge1, vec2 x);")); - s.append(TString("vec3 smoothstep(vec3 edge0, vec3 edge1, vec3 x);")); - s.append(TString("vec4 smoothstep(vec4 edge0, vec4 edge1, vec4 x);")); - s.append(TString("vec2 smoothstep(float edge0, float edge1, vec2 x);")); - s.append(TString("vec3 smoothstep(float edge0, float edge1, vec3 x);")); - s.append(TString("vec4 smoothstep(float edge0, float edge1, vec4 x);")); + symbolTable.insertBuiltIn(float1, "smoothstep", float1, float1, float1); + symbolTable.insertBuiltIn(float2, "smoothstep", float2, float2, float2); + symbolTable.insertBuiltIn(float3, "smoothstep", float3, float3, float3); + symbolTable.insertBuiltIn(float4, "smoothstep", float4, float4, float4); + symbolTable.insertBuiltIn(float2, "smoothstep", float1, float1, float2); + symbolTable.insertBuiltIn(float3, "smoothstep", float1, float1, float3); + symbolTable.insertBuiltIn(float4, "smoothstep", float1, float1, float4); // // Geometric Functions. // - s.append(TString("float length(float x);")); - s.append(TString("float length(vec2 x);")); - s.append(TString("float length(vec3 x);")); - s.append(TString("float length(vec4 x);")); + symbolTable.insertBuiltIn(float1, "length", float1); + symbolTable.insertBuiltIn(float1, "length", float2); + symbolTable.insertBuiltIn(float1, "length", float3); + symbolTable.insertBuiltIn(float1, "length", float4); - s.append(TString("float distance(float p0, float p1);")); - s.append(TString("float distance(vec2 p0, vec2 p1);")); - s.append(TString("float distance(vec3 p0, vec3 p1);")); - s.append(TString("float distance(vec4 p0, vec4 p1);")); + symbolTable.insertBuiltIn(float1, "distance", float1, float1); + symbolTable.insertBuiltIn(float1, "distance", float2, float2); + symbolTable.insertBuiltIn(float1, "distance", float3, float3); + symbolTable.insertBuiltIn(float1, "distance", float4, float4); - s.append(TString("float dot(float x, float y);")); - s.append(TString("float dot(vec2 x, vec2 y);")); - s.append(TString("float dot(vec3 x, vec3 y);")); - s.append(TString("float dot(vec4 x, vec4 y);")); + symbolTable.insertBuiltIn(float1, "dot", float1, float1); + symbolTable.insertBuiltIn(float1, "dot", float2, float2); + symbolTable.insertBuiltIn(float1, "dot", float3, float3); + symbolTable.insertBuiltIn(float1, "dot", float4, float4); - s.append(TString("vec3 cross(vec3 x, vec3 y);")); - s.append(TString("float normalize(float x);")); - s.append(TString("vec2 normalize(vec2 x);")); - s.append(TString("vec3 normalize(vec3 x);")); - s.append(TString("vec4 normalize(vec4 x);")); + symbolTable.insertBuiltIn(float3, "cross", float3, float3); + symbolTable.insertBuiltIn(float1, "normalize", float1); + symbolTable.insertBuiltIn(float2, "normalize", float2); + symbolTable.insertBuiltIn(float3, "normalize", float3); + symbolTable.insertBuiltIn(float4, "normalize", float4); - s.append(TString("float faceforward(float N, float I, float Nref);")); - s.append(TString("vec2 faceforward(vec2 N, vec2 I, vec2 Nref);")); - s.append(TString("vec3 faceforward(vec3 N, vec3 I, vec3 Nref);")); - s.append(TString("vec4 faceforward(vec4 N, vec4 I, vec4 Nref);")); + symbolTable.insertBuiltIn(float1, "faceforward", float1, float1, float1); + symbolTable.insertBuiltIn(float2, "faceforward", float2, float2, float2); + symbolTable.insertBuiltIn(float3, "faceforward", float3, float3, float3); + symbolTable.insertBuiltIn(float4, "faceforward", float4, float4, float4); - s.append(TString("float reflect(float I, float N);")); - s.append(TString("vec2 reflect(vec2 I, vec2 N);")); - s.append(TString("vec3 reflect(vec3 I, vec3 N);")); - s.append(TString("vec4 reflect(vec4 I, vec4 N);")); + symbolTable.insertBuiltIn(float1, "reflect", float1, float1); + symbolTable.insertBuiltIn(float2, "reflect", float2, float2); + symbolTable.insertBuiltIn(float3, "reflect", float3, float3); + symbolTable.insertBuiltIn(float4, "reflect", float4, float4); - s.append(TString("float refract(float I, float N, float eta);")); - s.append(TString("vec2 refract(vec2 I, vec2 N, float eta);")); - s.append(TString("vec3 refract(vec3 I, vec3 N, float eta);")); - s.append(TString("vec4 refract(vec4 I, vec4 N, float eta);")); + symbolTable.insertBuiltIn(float1, "refract", float1, float1, float1); + symbolTable.insertBuiltIn(float2, "refract", float2, float2, float1); + symbolTable.insertBuiltIn(float3, "refract", float3, float3, float1); + symbolTable.insertBuiltIn(float4, "refract", float4, float4, float1); + + TType *mat2 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 2, true); + TType *mat3 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 3, true); + TType *mat4 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 4, true); // // Matrix Functions. // - s.append(TString("mat2 matrixCompMult(mat2 x, mat2 y);")); - s.append(TString("mat3 matrixCompMult(mat3 x, mat3 y);")); - s.append(TString("mat4 matrixCompMult(mat4 x, mat4 y);")); + symbolTable.insertBuiltIn(mat2, "matrixCompMult", mat2, mat2); + symbolTable.insertBuiltIn(mat3, "matrixCompMult", mat3, mat3); + symbolTable.insertBuiltIn(mat4, "matrixCompMult", mat4, mat4); + + TType *bool1 = new TType(EbtBool, EbpUndefined, EvqGlobal, 1); + TType *bool2 = new TType(EbtBool, EbpUndefined, EvqGlobal, 2); + TType *bool3 = new TType(EbtBool, EbpUndefined, EvqGlobal, 3); + TType *bool4 = new TType(EbtBool, EbpUndefined, EvqGlobal, 4); // // Vector relational functions. // - s.append(TString("bvec2 lessThan(vec2 x, vec2 y);")); - s.append(TString("bvec3 lessThan(vec3 x, vec3 y);")); - s.append(TString("bvec4 lessThan(vec4 x, vec4 y);")); + symbolTable.insertBuiltIn(bool2, "lessThan", float2, float2); + symbolTable.insertBuiltIn(bool3, "lessThan", float3, float3); + symbolTable.insertBuiltIn(bool4, "lessThan", float4, float4); - s.append(TString("bvec2 lessThan(ivec2 x, ivec2 y);")); - s.append(TString("bvec3 lessThan(ivec3 x, ivec3 y);")); - s.append(TString("bvec4 lessThan(ivec4 x, ivec4 y);")); + symbolTable.insertBuiltIn(bool2, "lessThan", int2, int2); + symbolTable.insertBuiltIn(bool3, "lessThan", int3, int3); + symbolTable.insertBuiltIn(bool4, "lessThan", int4, int4); - s.append(TString("bvec2 lessThanEqual(vec2 x, vec2 y);")); - s.append(TString("bvec3 lessThanEqual(vec3 x, vec3 y);")); - s.append(TString("bvec4 lessThanEqual(vec4 x, vec4 y);")); + symbolTable.insertBuiltIn(bool2, "lessThanEqual", float2, float2); + symbolTable.insertBuiltIn(bool3, "lessThanEqual", float3, float3); + symbolTable.insertBuiltIn(bool4, "lessThanEqual", float4, float4); - s.append(TString("bvec2 lessThanEqual(ivec2 x, ivec2 y);")); - s.append(TString("bvec3 lessThanEqual(ivec3 x, ivec3 y);")); - s.append(TString("bvec4 lessThanEqual(ivec4 x, ivec4 y);")); + symbolTable.insertBuiltIn(bool2, "lessThanEqual", int2, int2); + symbolTable.insertBuiltIn(bool3, "lessThanEqual", int3, int3); + symbolTable.insertBuiltIn(bool4, "lessThanEqual", int4, int4); - s.append(TString("bvec2 greaterThan(vec2 x, vec2 y);")); - s.append(TString("bvec3 greaterThan(vec3 x, vec3 y);")); - s.append(TString("bvec4 greaterThan(vec4 x, vec4 y);")); + symbolTable.insertBuiltIn(bool2, "greaterThan", float2, float2); + symbolTable.insertBuiltIn(bool3, "greaterThan", float3, float3); + symbolTable.insertBuiltIn(bool4, "greaterThan", float4, float4); - s.append(TString("bvec2 greaterThan(ivec2 x, ivec2 y);")); - s.append(TString("bvec3 greaterThan(ivec3 x, ivec3 y);")); - s.append(TString("bvec4 greaterThan(ivec4 x, ivec4 y);")); + symbolTable.insertBuiltIn(bool2, "greaterThan", int2, int2); + symbolTable.insertBuiltIn(bool3, "greaterThan", int3, int3); + symbolTable.insertBuiltIn(bool4, "greaterThan", int4, int4); - s.append(TString("bvec2 greaterThanEqual(vec2 x, vec2 y);")); - s.append(TString("bvec3 greaterThanEqual(vec3 x, vec3 y);")); - s.append(TString("bvec4 greaterThanEqual(vec4 x, vec4 y);")); + symbolTable.insertBuiltIn(bool2, "greaterThanEqual", float2, float2); + symbolTable.insertBuiltIn(bool3, "greaterThanEqual", float3, float3); + symbolTable.insertBuiltIn(bool4, "greaterThanEqual", float4, float4); - s.append(TString("bvec2 greaterThanEqual(ivec2 x, ivec2 y);")); - s.append(TString("bvec3 greaterThanEqual(ivec3 x, ivec3 y);")); - s.append(TString("bvec4 greaterThanEqual(ivec4 x, ivec4 y);")); + symbolTable.insertBuiltIn(bool2, "greaterThanEqual", int2, int2); + symbolTable.insertBuiltIn(bool3, "greaterThanEqual", int3, int3); + symbolTable.insertBuiltIn(bool4, "greaterThanEqual", int4, int4); - s.append(TString("bvec2 equal(vec2 x, vec2 y);")); - s.append(TString("bvec3 equal(vec3 x, vec3 y);")); - s.append(TString("bvec4 equal(vec4 x, vec4 y);")); + symbolTable.insertBuiltIn(bool2, "equal", float2, float2); + symbolTable.insertBuiltIn(bool3, "equal", float3, float3); + symbolTable.insertBuiltIn(bool4, "equal", float4, float4); - s.append(TString("bvec2 equal(ivec2 x, ivec2 y);")); - s.append(TString("bvec3 equal(ivec3 x, ivec3 y);")); - s.append(TString("bvec4 equal(ivec4 x, ivec4 y);")); + symbolTable.insertBuiltIn(bool2, "equal", int2, int2); + symbolTable.insertBuiltIn(bool3, "equal", int3, int3); + symbolTable.insertBuiltIn(bool4, "equal", int4, int4); - s.append(TString("bvec2 equal(bvec2 x, bvec2 y);")); - s.append(TString("bvec3 equal(bvec3 x, bvec3 y);")); - s.append(TString("bvec4 equal(bvec4 x, bvec4 y);")); + symbolTable.insertBuiltIn(bool2, "equal", bool2, bool2); + symbolTable.insertBuiltIn(bool3, "equal", bool3, bool3); + symbolTable.insertBuiltIn(bool4, "equal", bool4, bool4); - s.append(TString("bvec2 notEqual(vec2 x, vec2 y);")); - s.append(TString("bvec3 notEqual(vec3 x, vec3 y);")); - s.append(TString("bvec4 notEqual(vec4 x, vec4 y);")); + symbolTable.insertBuiltIn(bool2, "notEqual", float2, float2); + symbolTable.insertBuiltIn(bool3, "notEqual", float3, float3); + symbolTable.insertBuiltIn(bool4, "notEqual", float4, float4); - s.append(TString("bvec2 notEqual(ivec2 x, ivec2 y);")); - s.append(TString("bvec3 notEqual(ivec3 x, ivec3 y);")); - s.append(TString("bvec4 notEqual(ivec4 x, ivec4 y);")); + symbolTable.insertBuiltIn(bool2, "notEqual", int2, int2); + symbolTable.insertBuiltIn(bool3, "notEqual", int3, int3); + symbolTable.insertBuiltIn(bool4, "notEqual", int4, int4); - s.append(TString("bvec2 notEqual(bvec2 x, bvec2 y);")); - s.append(TString("bvec3 notEqual(bvec3 x, bvec3 y);")); - s.append(TString("bvec4 notEqual(bvec4 x, bvec4 y);")); + symbolTable.insertBuiltIn(bool2, "notEqual", bool2, bool2); + symbolTable.insertBuiltIn(bool3, "notEqual", bool3, bool3); + symbolTable.insertBuiltIn(bool4, "notEqual", bool4, bool4); - s.append(TString("bool any(bvec2 x);")); - s.append(TString("bool any(bvec3 x);")); - s.append(TString("bool any(bvec4 x);")); + symbolTable.insertBuiltIn(bool1, "any", bool2); + symbolTable.insertBuiltIn(bool1, "any", bool3); + symbolTable.insertBuiltIn(bool1, "any", bool4); - s.append(TString("bool all(bvec2 x);")); - s.append(TString("bool all(bvec3 x);")); - s.append(TString("bool all(bvec4 x);")); + symbolTable.insertBuiltIn(bool1, "all", bool2); + symbolTable.insertBuiltIn(bool1, "all", bool3); + symbolTable.insertBuiltIn(bool1, "all", bool4); - s.append(TString("bvec2 not(bvec2 x);")); - s.append(TString("bvec3 not(bvec3 x);")); - s.append(TString("bvec4 not(bvec4 x);")); + symbolTable.insertBuiltIn(bool2, "not", bool2); + symbolTable.insertBuiltIn(bool3, "not", bool3); + symbolTable.insertBuiltIn(bool4, "not", bool4); + + TType *sampler2D = new TType(EbtSampler2D, EbpUndefined, EvqGlobal, 1); + TType *samplerCube = new TType(EbtSamplerCube, EbpUndefined, EvqGlobal, 1); // - // Texture Functions. + // Texture Functions for GLSL ES 1.0 // - s.append(TString("vec4 texture2D(sampler2D sampler, vec2 coord);")); - s.append(TString("vec4 texture2DProj(sampler2D sampler, vec3 coord);")); - s.append(TString("vec4 texture2DProj(sampler2D sampler, vec4 coord);")); - s.append(TString("vec4 textureCube(samplerCube sampler, vec3 coord);")); + symbolTable.insertBuiltIn(float4, "texture2D", sampler2D, float2); + symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float3); + symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float4); + symbolTable.insertBuiltIn(float4, "textureCube", samplerCube, float3); - if (resources.OES_EGL_image_external) { - s.append(TString("vec4 texture2D(samplerExternalOES sampler, vec2 coord);")); - s.append(TString("vec4 texture2DProj(samplerExternalOES sampler, vec3 coord);")); - s.append(TString("vec4 texture2DProj(samplerExternalOES sampler, vec4 coord);")); + if (resources.OES_EGL_image_external) + { + TType *samplerExternalOES = new TType(EbtSamplerExternalOES, EbpUndefined, EvqGlobal, 1); + + symbolTable.insertBuiltIn(float4, "texture2D", samplerExternalOES, float2); + symbolTable.insertBuiltIn(float4, "texture2DProj", samplerExternalOES, float3); + symbolTable.insertBuiltIn(float4, "texture2DProj", samplerExternalOES, float4); } - if (resources.ARB_texture_rectangle) { - s.append(TString("vec4 texture2DRect(sampler2DRect sampler, vec2 coord);")); - s.append(TString("vec4 texture2DRectProj(sampler2DRect sampler, vec3 coord);")); - s.append(TString("vec4 texture2DRectProj(sampler2DRect sampler, vec4 coord);")); + if (resources.ARB_texture_rectangle) + { + TType *sampler2DRect = new TType(EbtSampler2DRect, EbpUndefined, EvqGlobal, 1); + + symbolTable.insertBuiltIn(float4, "texture2DRect", sampler2DRect, float2); + symbolTable.insertBuiltIn(float4, "texture2DRectProj", sampler2DRect, float3); + symbolTable.insertBuiltIn(float4, "texture2DRectProj", sampler2DRect, float4); } - // - // Noise functions. - // - //s.append(TString("float noise1(float x);")); - //s.append(TString("float noise1(vec2 x);")); - //s.append(TString("float noise1(vec3 x);")); - //s.append(TString("float noise1(vec4 x);")); + if (type == SH_FRAGMENT_SHADER) + { + symbolTable.insertBuiltIn(float4, "texture2D", sampler2D, float2, float1); + symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float3, float1); + symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float4, float1); + symbolTable.insertBuiltIn(float4, "textureCube", samplerCube, float3, float1); - //s.append(TString("vec2 noise2(float x);")); - //s.append(TString("vec2 noise2(vec2 x);")); - //s.append(TString("vec2 noise2(vec3 x);")); - //s.append(TString("vec2 noise2(vec4 x);")); + if (resources.OES_standard_derivatives) + { + symbolTable.insertBuiltIn(float1, "dFdx", float1); + symbolTable.insertBuiltIn(float2, "dFdx", float2); + symbolTable.insertBuiltIn(float3, "dFdx", float3); + symbolTable.insertBuiltIn(float4, "dFdx", float4); + + symbolTable.insertBuiltIn(float1, "dFdy", float1); + symbolTable.insertBuiltIn(float2, "dFdy", float2); + symbolTable.insertBuiltIn(float3, "dFdy", float3); + symbolTable.insertBuiltIn(float4, "dFdy", float4); - //s.append(TString("vec3 noise3(float x);")); - //s.append(TString("vec3 noise3(vec2 x);")); - //s.append(TString("vec3 noise3(vec3 x);")); - //s.append(TString("vec3 noise3(vec4 x);")); - - //s.append(TString("vec4 noise4(float x);")); - //s.append(TString("vec4 noise4(vec2 x);")); - //s.append(TString("vec4 noise4(vec3 x);")); - //s.append(TString("vec4 noise4(vec4 x);")); - - return s; -} - -//============================================================================ -// -// Prototypes for built-in functions seen by vertex shaders only. -// -//============================================================================ -static TString BuiltInFunctionsVertex(const ShBuiltInResources& resources) -{ - TString s; - - // - // Geometric Functions. - // - //s.append(TString("vec4 ftransform();")); - - // - // Texture Functions. - // - s.append(TString("vec4 texture2DLod(sampler2D sampler, vec2 coord, float lod);")); - s.append(TString("vec4 texture2DProjLod(sampler2D sampler, vec3 coord, float lod);")); - s.append(TString("vec4 texture2DProjLod(sampler2D sampler, vec4 coord, float lod);")); - s.append(TString("vec4 textureCubeLod(samplerCube sampler, vec3 coord, float lod);")); - - return s; -} - -//============================================================================ -// -// Prototypes for built-in functions seen by fragment shaders only. -// -//============================================================================ -static TString BuiltInFunctionsFragment(const ShBuiltInResources& resources) -{ - TString s; - - // - // Texture Functions. - // - s.append(TString("vec4 texture2D(sampler2D sampler, vec2 coord, float bias);")); - s.append(TString("vec4 texture2DProj(sampler2D sampler, vec3 coord, float bias);")); - s.append(TString("vec4 texture2DProj(sampler2D sampler, vec4 coord, float bias);")); - s.append(TString("vec4 textureCube(samplerCube sampler, vec3 coord, float bias);")); - - if (resources.OES_standard_derivatives) { - s.append(TString("float dFdx(float p);")); - s.append(TString("vec2 dFdx(vec2 p);")); - s.append(TString("vec3 dFdx(vec3 p);")); - s.append(TString("vec4 dFdx(vec4 p);")); - - s.append(TString("float dFdy(float p);")); - s.append(TString("vec2 dFdy(vec2 p);")); - s.append(TString("vec3 dFdy(vec3 p);")); - s.append(TString("vec4 dFdy(vec4 p);")); - - s.append(TString("float fwidth(float p);")); - s.append(TString("vec2 fwidth(vec2 p);")); - s.append(TString("vec3 fwidth(vec3 p);")); - s.append(TString("vec4 fwidth(vec4 p);")); + symbolTable.insertBuiltIn(float1, "fwidth", float1); + symbolTable.insertBuiltIn(float2, "fwidth", float2); + symbolTable.insertBuiltIn(float3, "fwidth", float3); + symbolTable.insertBuiltIn(float4, "fwidth", float4); + } } - return s; -} - -//============================================================================ -// -// Standard uniforms. -// -//============================================================================ -static TString StandardUniforms() -{ - TString s; + if(type == SH_VERTEX_SHADER) + { + symbolTable.insertBuiltIn(float4, "texture2DLod", sampler2D, float2, float1); + symbolTable.insertBuiltIn(float4, "texture2DProjLod", sampler2D, float3, float1); + symbolTable.insertBuiltIn(float4, "texture2DProjLod", sampler2D, float4, float1); + symbolTable.insertBuiltIn(float4, "textureCubeLod", samplerCube, float3, float1); + } // // Depth range in window coordinates // - s.append(TString("struct gl_DepthRangeParameters {")); - s.append(TString(" highp float near;")); // n - s.append(TString(" highp float far;")); // f - s.append(TString(" highp float diff;")); // f - n - s.append(TString("};")); - s.append(TString("uniform gl_DepthRangeParameters gl_DepthRange;")); + TFieldList *fields = NewPoolTFieldList(); + TField *near = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("near")); + TField *far = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("far")); + TField *diff = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("diff")); + fields->push_back(near); + fields->push_back(far); + fields->push_back(diff); + TStructure *depthRangeStruct = new TStructure(NewPoolTString("gl_DepthRangeParameters"), fields); + TVariable *depthRangeParameters = new TVariable(&depthRangeStruct->name(), depthRangeStruct, true); + symbolTable.insert(*depthRangeParameters); + TVariable *depthRange = new TVariable(NewPoolTString("gl_DepthRange"), TType(depthRangeStruct)); + depthRange->setQualifier(EvqUniform); + symbolTable.insert(*depthRange); - return s; -} - -//============================================================================ -// -// Default precision for vertex shaders. -// -//============================================================================ -static TString DefaultPrecisionVertex() -{ - TString s; - - s.append(TString("precision highp int;")); - s.append(TString("precision highp float;")); - - return s; -} - -//============================================================================ -// -// Default precision for fragment shaders. -// -//============================================================================ -static TString DefaultPrecisionFragment() -{ - TString s; - - s.append(TString("precision mediump int;")); - // No default precision for float in fragment shaders - - return s; -} - -//============================================================================ -// -// Implementation dependent built-in constants. -// -//============================================================================ -static TString BuiltInConstants(ShShaderSpec spec, const ShBuiltInResources &resources) -{ - TStringStream s; - - s << "const int gl_MaxVertexAttribs = " << resources.MaxVertexAttribs << ";"; - s << "const int gl_MaxVertexUniformVectors = " << resources.MaxVertexUniformVectors << ";"; - - s << "const int gl_MaxVaryingVectors = " << resources.MaxVaryingVectors << ";"; - s << "const int gl_MaxVertexTextureImageUnits = " << resources.MaxVertexTextureImageUnits << ";"; - s << "const int gl_MaxCombinedTextureImageUnits = " << resources.MaxCombinedTextureImageUnits << ";"; - s << "const int gl_MaxTextureImageUnits = " << resources.MaxTextureImageUnits << ";"; - s << "const int gl_MaxFragmentUniformVectors = " << resources.MaxFragmentUniformVectors << ";"; + // + // Implementation dependent built-in constants. + // + symbolTable.insertConstInt("gl_MaxVertexAttribs", resources.MaxVertexAttribs); + symbolTable.insertConstInt("gl_MaxVertexUniformVectors", resources.MaxVertexUniformVectors); + symbolTable.insertConstInt("gl_MaxVaryingVectors", resources.MaxVaryingVectors); + symbolTable.insertConstInt("gl_MaxVertexTextureImageUnits", resources.MaxVertexTextureImageUnits); + symbolTable.insertConstInt("gl_MaxCombinedTextureImageUnits", resources.MaxCombinedTextureImageUnits); + symbolTable.insertConstInt("gl_MaxTextureImageUnits", resources.MaxTextureImageUnits); + symbolTable.insertConstInt("gl_MaxFragmentUniformVectors", resources.MaxFragmentUniformVectors); if (spec != SH_CSS_SHADERS_SPEC) - s << "const int gl_MaxDrawBuffers = " << resources.MaxDrawBuffers << ";"; - - return s.str(); -} - -void TBuiltIns::initialize(ShShaderType type, ShShaderSpec spec, - const ShBuiltInResources& resources) -{ - switch (type) { - case SH_FRAGMENT_SHADER: - builtInStrings.push_back(DefaultPrecisionFragment()); - builtInStrings.push_back(BuiltInFunctionsCommon(resources)); - builtInStrings.push_back(BuiltInFunctionsFragment(resources)); - builtInStrings.push_back(StandardUniforms()); - break; - - case SH_VERTEX_SHADER: - builtInStrings.push_back(DefaultPrecisionVertex()); - builtInStrings.push_back(BuiltInFunctionsCommon(resources)); - builtInStrings.push_back(BuiltInFunctionsVertex(resources)); - builtInStrings.push_back(StandardUniforms()); - break; - - default: assert(false && "Language not supported"); + { + symbolTable.insertConstInt("gl_MaxDrawBuffers", resources.MaxDrawBuffers); } - - builtInStrings.push_back(BuiltInConstants(spec, resources)); } void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec, - const ShBuiltInResources& resources, - TSymbolTable& symbolTable) + const ShBuiltInResources &resources, + TSymbolTable &symbolTable) { // // First, insert some special built-in variables that are not in @@ -539,6 +439,10 @@ void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec, if (spec != SH_CSS_SHADERS_SPEC) { symbolTable.insert(*new TVariable(NewPoolTString("gl_FragColor"), TType(EbtFloat, EbpMedium, EvqFragColor, 4))); symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData[gl_MaxDrawBuffers]"), TType(EbtFloat, EbpMedium, EvqFragData, 4))); + if (resources.EXT_frag_depth) { + symbolTable.insert(*new TVariable(NewPoolTString("gl_FragDepthEXT"), TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium, EvqFragDepth, 1))); + symbolTable.relateToExtension("gl_FragDepthEXT", "GL_EXT_frag_depth"); + } } else { symbolTable.insert(*new TVariable(NewPoolTString("css_MixColor"), TType(EbtFloat, EbpMedium, EvqGlobal, 4))); symbolTable.insert(*new TVariable(NewPoolTString("css_ColorMatrix"), TType(EbtFloat, EbpMedium, EvqGlobal, 4, true))); @@ -560,8 +464,6 @@ void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec, // expected to be resolved through a library of functions, versus as // operations. // - symbolTable.relateToOperator("not", EOpVectorLogicalNot); - symbolTable.relateToOperator("matrixCompMult", EOpMul); symbolTable.relateToOperator("equal", EOpVectorEqual); @@ -612,6 +514,7 @@ void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec, symbolTable.relateToOperator("any", EOpAny); symbolTable.relateToOperator("all", EOpAll); + symbolTable.relateToOperator("not", EOpVectorLogicalNot); // Map language-specific operators. switch(type) { @@ -656,4 +559,6 @@ void InitExtensionBehavior(const ShBuiltInResources& resources, extBehavior["GL_ARB_texture_rectangle"] = EBhUndefined; if (resources.EXT_draw_buffers) extBehavior["GL_EXT_draw_buffers"] = EBhUndefined; + if (resources.EXT_frag_depth) + extBehavior["GL_EXT_frag_depth"] = EBhUndefined; } diff --git a/gfx/angle/src/compiler/Initialize.h b/gfx/angle/src/compiler/Initialize.h index 8b0adc6b4c23..4aa13466acad 100644 --- a/gfx/angle/src/compiler/Initialize.h +++ b/gfx/angle/src/compiler/Initialize.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -11,19 +11,7 @@ #include "compiler/ShHandle.h" #include "compiler/SymbolTable.h" -typedef TVector TBuiltInStrings; - -class TBuiltIns { -public: - POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) - - void initialize(ShShaderType type, ShShaderSpec spec, - const ShBuiltInResources& resources); - const TBuiltInStrings& getBuiltInStrings() { return builtInStrings; } - -protected: - TBuiltInStrings builtInStrings; -}; +void InsertBuiltInFunctions(ShShaderType type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &table); void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec, const ShBuiltInResources& resources, diff --git a/gfx/angle/src/compiler/InitializeDll.cpp b/gfx/angle/src/compiler/InitializeDll.cpp index 8763cfeea8d7..6c7f27fced17 100644 --- a/gfx/angle/src/compiler/InitializeDll.cpp +++ b/gfx/angle/src/compiler/InitializeDll.cpp @@ -10,25 +10,8 @@ #include "compiler/InitializeParseContext.h" #include "compiler/osinclude.h" -OS_TLSIndex ThreadInitializeIndex = OS_INVALID_TLS_INDEX; - bool InitProcess() { - if (ThreadInitializeIndex != OS_INVALID_TLS_INDEX) { - // - // Function is re-entrant. - // - return true; - } - - ThreadInitializeIndex = OS_AllocTLSIndex(); - - if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) { - assert(0 && "InitProcess(): Failed to allocate TLS area for init flag"); - return false; - } - - if (!InitializePoolIndex()) { assert(0 && "InitProcess(): Failed to initalize global pool"); return false; @@ -39,77 +22,11 @@ bool InitProcess() return false; } - return InitThread(); -} - -bool DetachProcess() -{ - bool success = true; - - if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) - return true; - - success = DetachThread(); - - if (!FreeParseContextIndex()) - success = false; - - FreePoolIndex(); - - OS_FreeTLSIndex(ThreadInitializeIndex); - ThreadInitializeIndex = OS_INVALID_TLS_INDEX; - - return success; -} - -bool InitThread() -{ - // - // This function is re-entrant - // - if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) { - assert(0 && "InitThread(): Process hasn't been initalised."); - return false; - } - - if (OS_GetTLSValue(ThreadInitializeIndex) != 0) - return true; - - InitializeGlobalPools(); - - if (!InitializeGlobalParseContext()) - return false; - - if (!OS_SetTLSValue(ThreadInitializeIndex, (void *)1)) { - assert(0 && "InitThread(): Unable to set init flag."); - return false; - } - return true; } -bool DetachThread() +void DetachProcess() { - bool success = true; - - if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) - return true; - - // - // Function is re-entrant and this thread may not have been initalised. - // - if (OS_GetTLSValue(ThreadInitializeIndex) != 0) { - if (!OS_SetTLSValue(ThreadInitializeIndex, (void *)0)) { - assert(0 && "DetachThread(): Unable to clear init flag."); - success = false; - } - - if (!FreeParseContext()) - success = false; - - FreeGlobalPools(); - } - - return success; + FreeParseContextIndex(); + FreePoolIndex(); } - diff --git a/gfx/angle/src/compiler/InitializeDll.h b/gfx/angle/src/compiler/InitializeDll.h index 857238eeae19..43070cc3ff78 100644 --- a/gfx/angle/src/compiler/InitializeDll.h +++ b/gfx/angle/src/compiler/InitializeDll.h @@ -7,10 +7,7 @@ #define __INITIALIZEDLL_H bool InitProcess(); -bool DetachProcess(); - -bool InitThread(); -bool DetachThread(); +void DetachProcess(); #endif // __INITIALIZEDLL_H diff --git a/gfx/angle/src/compiler/InitializeGlobals.h b/gfx/angle/src/compiler/InitializeGlobals.h index 842a45281dd6..071594142471 100644 --- a/gfx/angle/src/compiler/InitializeGlobals.h +++ b/gfx/angle/src/compiler/InitializeGlobals.h @@ -7,8 +7,6 @@ #ifndef __INITIALIZE_GLOBALS_INCLUDED_ #define __INITIALIZE_GLOBALS_INCLUDED_ -void InitializeGlobalPools(); -void FreeGlobalPools(); bool InitializePoolIndex(); void FreePoolIndex(); diff --git a/gfx/angle/src/compiler/InitializeParseContext.cpp b/gfx/angle/src/compiler/InitializeParseContext.cpp index 1f40cf58006a..dfab027330de 100644 --- a/gfx/angle/src/compiler/InitializeParseContext.cpp +++ b/gfx/angle/src/compiler/InitializeParseContext.cpp @@ -12,85 +12,29 @@ OS_TLSIndex GlobalParseContextIndex = OS_INVALID_TLS_INDEX; bool InitializeParseContextIndex() { - if (GlobalParseContextIndex != OS_INVALID_TLS_INDEX) { - assert(0 && "InitializeParseContextIndex(): Parse Context already initalized"); - return false; - } + assert(GlobalParseContextIndex == OS_INVALID_TLS_INDEX); - // - // Allocate a TLS index. - // GlobalParseContextIndex = OS_AllocTLSIndex(); - - if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) { - assert(0 && "InitializeParseContextIndex(): Parse Context already initalized"); - return false; - } - - return true; + return GlobalParseContextIndex != OS_INVALID_TLS_INDEX; } -bool FreeParseContextIndex() +void FreeParseContextIndex() { - OS_TLSIndex tlsiIndex = GlobalParseContextIndex; - - if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) { - assert(0 && "FreeParseContextIndex(): Parse Context index not initalized"); - return false; - } + assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX); + OS_FreeTLSIndex(GlobalParseContextIndex); GlobalParseContextIndex = OS_INVALID_TLS_INDEX; - - return OS_FreeTLSIndex(tlsiIndex); } -bool InitializeGlobalParseContext() +void SetGlobalParseContext(TParseContext* context) { - if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) { - assert(0 && "InitializeGlobalParseContext(): Parse Context index not initalized"); - return false; - } - - TThreadParseContext *lpParseContext = static_cast(OS_GetTLSValue(GlobalParseContextIndex)); - if (lpParseContext != 0) { - assert(0 && "InitializeParseContextIndex(): Parse Context already initalized"); - return false; - } - - TThreadParseContext *lpThreadData = new TThreadParseContext(); - if (lpThreadData == 0) { - assert(0 && "InitializeGlobalParseContext(): Unable to create thread parse context"); - return false; - } - - lpThreadData->lpGlobalParseContext = 0; - OS_SetTLSValue(GlobalParseContextIndex, lpThreadData); - - return true; + assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX); + OS_SetTLSValue(GlobalParseContextIndex, context); } -bool FreeParseContext() +TParseContext* GetGlobalParseContext() { - if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) { - assert(0 && "FreeParseContext(): Parse Context index not initalized"); - return false; - } - - TThreadParseContext *lpParseContext = static_cast(OS_GetTLSValue(GlobalParseContextIndex)); - if (lpParseContext) - delete lpParseContext; - - return true; -} - -TParseContextPointer& GetGlobalParseContext() -{ - // - // Minimal error checking for speed - // - - TThreadParseContext *lpParseContext = static_cast(OS_GetTLSValue(GlobalParseContextIndex)); - - return lpParseContext->lpGlobalParseContext; + assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX); + return static_cast(OS_GetTLSValue(GlobalParseContextIndex)); } diff --git a/gfx/angle/src/compiler/InitializeParseContext.h b/gfx/angle/src/compiler/InitializeParseContext.h index aa53b735d44d..bffbab87d072 100644 --- a/gfx/angle/src/compiler/InitializeParseContext.h +++ b/gfx/angle/src/compiler/InitializeParseContext.h @@ -8,19 +8,10 @@ #define __INITIALIZE_PARSE_CONTEXT_INCLUDED_ bool InitializeParseContextIndex(); -bool FreeParseContextIndex(); - -bool InitializeGlobalParseContext(); -bool FreeParseContext(); +void FreeParseContextIndex(); struct TParseContext; -typedef TParseContext* TParseContextPointer; -extern TParseContextPointer& GetGlobalParseContext(); -#define GlobalParseContext GetGlobalParseContext() - -typedef struct TThreadParseContextRec -{ - TParseContext *lpGlobalParseContext; -} TThreadParseContext; +extern void SetGlobalParseContext(TParseContext* context); +extern TParseContext* GetGlobalParseContext(); #endif // __INITIALIZE_PARSE_CONTEXT_INCLUDED_ diff --git a/gfx/angle/src/compiler/Intermediate.cpp b/gfx/angle/src/compiler/Intermediate.cpp index edf279ef675d..3b6622185d20 100644 --- a/gfx/angle/src/compiler/Intermediate.cpp +++ b/gfx/angle/src/compiler/Intermediate.cpp @@ -131,7 +131,7 @@ const char* getOperatorString(TOperator op) { // // Returns the added node. // -TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, TSourceLoc line) +TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, const TSourceLoc& line) { TIntermSymbol* node = new TIntermSymbol(id, name, type); node->setLine(line); @@ -144,7 +144,7 @@ TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType // // Returns the added node. // -TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line, TSymbolTable& symbolTable) +TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line, TSymbolTable& symbolTable) { switch (op) { case EOpEqual: @@ -200,8 +200,6 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn // one and promote it to the right type. // TIntermBinary* node = new TIntermBinary(op); - if (line == 0) - line = right->getLine(); node->setLine(line); node->setLeft(left); @@ -230,15 +228,13 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn // // Returns the added node. // -TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line) +TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line) { // // Like adding binary math, except the conversion can only go // from right to left. // TIntermBinary* node = new TIntermBinary(op); - if (line == 0) - line = left->getLine(); node->setLine(line); TIntermTyped* child = addConversion(op, left->getType(), right); @@ -260,11 +256,9 @@ TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TInterm // Returns the added node. // The caller should set the type of the returned node. // -TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc line) +TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc& line) { TIntermBinary* node = new TIntermBinary(op); - if (line == 0) - line = index->getLine(); node->setLine(line); node->setLeft(base); node->setRight(index); @@ -279,13 +273,13 @@ TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermT // // Returns the added node. // -TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, TSourceLoc line, TSymbolTable& symbolTable) +TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, const TSourceLoc& line, TSymbolTable& symbolTable) { TIntermUnary* node; TIntermTyped* child = childNode->getAsTyped(); if (child == 0) { - infoSink.info.message(EPrefixInternalError, "Bad type in AddUnaryMath", line); + infoSink.info.message(EPrefixInternalError, line, "Bad type in AddUnaryMath"); return 0; } @@ -348,8 +342,6 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, // Make a new node for the operator. // node = new TIntermUnary(op); - if (line == 0) - line = child->getLine(); node->setLine(line); node->setOperand(child); @@ -376,7 +368,7 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, // Returns an aggregate node, which could be the one passed in if // it was already an aggregate but no operator was set. // -TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, TSourceLoc line) +TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, const TSourceLoc& line) { TIntermAggregate* aggNode; @@ -391,8 +383,6 @@ TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperat // aggNode = new TIntermAggregate(); aggNode->getSequence().push_back(node); - if (line == 0) - line = node->getLine(); } } else aggNode = new TIntermAggregate(); @@ -401,8 +391,7 @@ TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperat // Set the operator. // aggNode->setOp(op); - if (line != 0) - aggNode->setLine(line); + aggNode->setLine(line); return aggNode; } @@ -491,7 +480,7 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt case EbtInt: newOp = EOpConvIntToFloat; break; case EbtBool: newOp = EOpConvBoolToFloat; break; default: - infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine()); + infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node"); return 0; } break; @@ -500,7 +489,7 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt case EbtInt: newOp = EOpConvIntToBool; break; case EbtFloat: newOp = EOpConvFloatToBool; break; default: - infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine()); + infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node"); return 0; } break; @@ -509,12 +498,12 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt case EbtBool: newOp = EOpConvBoolToInt; break; case EbtFloat: newOp = EOpConvFloatToInt; break; default: - infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine()); + infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node"); return 0; } break; default: - infoSink.info.message(EPrefixInternalError, "Bad promotion type", node->getLine()); + infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion type"); return 0; } @@ -534,7 +523,7 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt // Returns the resulting aggregate, unless 0 was passed in for // both existing nodes. // -TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, TSourceLoc line) +TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc& line) { if (left == 0 && right == 0) return 0; @@ -551,8 +540,7 @@ TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* r if (right) aggNode->getSequence().push_back(right); - if (line != 0) - aggNode->setLine(line); + aggNode->setLine(line); return aggNode; } @@ -562,18 +550,14 @@ TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* r // // Returns an aggregate, unless 0 was passed in for the existing node. // -TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, TSourceLoc line) +TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, const TSourceLoc& line) { if (node == 0) return 0; TIntermAggregate* aggNode = new TIntermAggregate; aggNode->getSequence().push_back(node); - - if (line != 0) - aggNode->setLine(line); - else - aggNode->setLine(node->getLine()); + aggNode->setLine(line); return aggNode; } @@ -585,7 +569,7 @@ TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, TSourceLoc lin // // Returns the selection node created. // -TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, TSourceLoc line) +TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, const TSourceLoc& line) { // // For compile time constant selections, prune the code and @@ -606,7 +590,7 @@ TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nod } -TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, TSourceLoc line) +TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line) { if (left->getType().getQualifier() == EvqConst && right->getType().getQualifier() == EvqConst) { return right; @@ -626,7 +610,7 @@ TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, T // // Returns the selection node created, or 0 if one could not be. // -TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, TSourceLoc line) +TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc& line) { // // Get compatible types. @@ -669,7 +653,7 @@ TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* true // Returns the constant union node created. // -TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, TSourceLoc line) +TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, const TSourceLoc& line) { TIntermConstantUnion* node = new TIntermConstantUnion(unionArrayPointer, t); node->setLine(line); @@ -677,7 +661,7 @@ TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayP return node; } -TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, TSourceLoc line) +TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, const TSourceLoc& line) { TIntermAggregate* node = new TIntermAggregate(EOpSequence); @@ -700,7 +684,7 @@ TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, TSourceLoc line) // // Create loop nodes. // -TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTyped* cond, TIntermTyped* expr, TIntermNode* body, TSourceLoc line) +TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTyped* cond, TIntermTyped* expr, TIntermNode* body, const TSourceLoc& line) { TIntermNode* node = new TIntermLoop(type, init, cond, expr, body); node->setLine(line); @@ -711,12 +695,12 @@ TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTy // // Add branches. // -TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TSourceLoc line) +TIntermBranch* TIntermediate::addBranch(TOperator branchOp, const TSourceLoc& line) { return addBranch(branchOp, 0, line); } -TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, TSourceLoc line) +TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, const TSourceLoc& line) { TIntermBranch* node = new TIntermBranch(branchOp, expression); node->setLine(line); @@ -861,7 +845,7 @@ bool TIntermBinary::promote(TInfoSink& infoSink) { // This function only handles scalars, vectors, and matrices. if (left->isArray() || right->isArray()) { - infoSink.info.message(EPrefixInternalError, "Invalid operation for arrays", getLine()); + infoSink.info.message(EPrefixInternalError, getLine(), "Invalid operation for arrays"); return false; } @@ -966,7 +950,7 @@ bool TIntermBinary::promote(TInfoSink& infoSink) setType(TType(basicType, higherPrecision, EvqTemporary, size, false)); } } else { - infoSink.info.message(EPrefixInternalError, "Missing elses", getLine()); + infoSink.info.message(EPrefixInternalError, getLine(), "Missing elses"); return false; } break; @@ -995,7 +979,7 @@ bool TIntermBinary::promote(TInfoSink& infoSink) setType(TType(basicType, higherPrecision, EvqTemporary, size, false)); } } else { - infoSink.info.message(EPrefixInternalError, "Missing elses", getLine()); + infoSink.info.message(EPrefixInternalError, getLine(), "Missing elses"); return false; } break; @@ -1035,23 +1019,22 @@ bool TIntermBinary::promote(TInfoSink& infoSink) bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray) { - const TTypeList* fields = leftNodeType.getStruct(); + const TFieldList& fields = leftNodeType.getStruct()->fields(); - size_t structSize = fields->size(); - int index = 0; + size_t structSize = fields.size(); + size_t index = 0; for (size_t j = 0; j < structSize; j++) { - int size = (*fields)[j].type->getObjectSize(); - for (int i = 0; i < size; i++) { - if ((*fields)[j].type->getBasicType() == EbtStruct) { - if (!CompareStructure(*(*fields)[j].type, &rightUnionArray[index], &leftUnionArray[index])) + size_t size = fields[j]->type()->getObjectSize(); + for (size_t i = 0; i < size; i++) { + if (fields[j]->type()->getBasicType() == EbtStruct) { + if (!CompareStructure(*(fields[j]->type()), &rightUnionArray[index], &leftUnionArray[index])) return false; } else { if (leftUnionArray[index] != rightUnionArray[index]) return false; index++; } - } } return true; @@ -1063,10 +1046,10 @@ bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, TType typeWithoutArrayness = leftNodeType; typeWithoutArrayness.clearArrayness(); - int arraySize = leftNodeType.getArraySize(); + size_t arraySize = leftNodeType.getArraySize(); - for (int i = 0; i < arraySize; ++i) { - int offset = typeWithoutArrayness.getObjectSize() * i; + for (size_t i = 0; i < arraySize; ++i) { + size_t offset = typeWithoutArrayness.getObjectSize() * i; if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset])) return false; } @@ -1086,7 +1069,7 @@ bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink) { ConstantUnion *unionArray = getUnionArrayPointer(); - int objectSize = getType().getObjectSize(); + size_t objectSize = getType().getObjectSize(); if (constantNode) { // binary operations TIntermConstantUnion *node = constantNode->getAsConstantUnion(); @@ -1096,13 +1079,13 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod // for a case like float f = 1.2 + vec4(2,3,4,5); if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) { rightUnionArray = new ConstantUnion[objectSize]; - for (int i = 0; i < objectSize; ++i) + for (size_t i = 0; i < objectSize; ++i) rightUnionArray[i] = *node->getUnionArrayPointer(); returnType = getType(); } else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) { // for a case like float f = vec4(2,3,4,5) + 1.2; unionArray = new ConstantUnion[constantNode->getType().getObjectSize()]; - for (int i = 0; i < constantNode->getType().getObjectSize(); ++i) + for (size_t i = 0; i < constantNode->getType().getObjectSize(); ++i) unionArray[i] = *getUnionArrayPointer(); returnType = node->getType(); objectSize = constantNode->getType().getObjectSize(); @@ -1116,14 +1099,14 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod case EOpAdd: tempConstArray = new ConstantUnion[objectSize]; {// support MSVC++6.0 - for (int i = 0; i < objectSize; i++) + for (size_t i = 0; i < objectSize; i++) tempConstArray[i] = unionArray[i] + rightUnionArray[i]; } break; case EOpSub: tempConstArray = new ConstantUnion[objectSize]; {// support MSVC++6.0 - for (int i = 0; i < objectSize; i++) + for (size_t i = 0; i < objectSize; i++) tempConstArray[i] = unionArray[i] - rightUnionArray[i]; } break; @@ -1133,13 +1116,13 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod case EOpMatrixTimesScalar: tempConstArray = new ConstantUnion[objectSize]; {// support MSVC++6.0 - for (int i = 0; i < objectSize; i++) + for (size_t i = 0; i < objectSize; i++) tempConstArray[i] = unionArray[i] * rightUnionArray[i]; } break; case EOpMatrixTimesMatrix: if (getType().getBasicType() != EbtFloat || node->getBasicType() != EbtFloat) { - infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine()); + infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for matrix multiply"); return 0; } {// support MSVC++6.0 @@ -1158,11 +1141,11 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod case EOpDiv: tempConstArray = new ConstantUnion[objectSize]; {// support MSVC++6.0 - for (int i = 0; i < objectSize; i++) { + for (size_t i = 0; i < objectSize; i++) { switch (getType().getBasicType()) { case EbtFloat: if (rightUnionArray[i] == 0.0f) { - infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine()); + infoSink.info.message(EPrefixWarning, getLine(), "Divide by zero error during constant folding"); tempConstArray[i].setFConst(unionArray[i].getFConst() < 0 ? -FLT_MAX : FLT_MAX); } else tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst()); @@ -1170,13 +1153,13 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod case EbtInt: if (rightUnionArray[i] == 0) { - infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine()); + infoSink.info.message(EPrefixWarning, getLine(), "Divide by zero error during constant folding"); tempConstArray[i].setIConst(INT_MAX); } else tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst()); break; default: - infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"/\"", getLine()); + infoSink.info.message(EPrefixInternalError, getLine(), "Constant folding cannot be done for \"/\""); return 0; } } @@ -1185,7 +1168,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod case EOpMatrixTimesVector: if (node->getBasicType() != EbtFloat) { - infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix times vector", getLine()); + infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for matrix times vector"); return 0; } tempConstArray = new ConstantUnion[getNominalSize()]; @@ -1206,7 +1189,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod case EOpVectorTimesMatrix: if (getType().getBasicType() != EbtFloat) { - infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for vector times matrix", getLine()); + infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for vector times matrix"); return 0; } @@ -1224,7 +1207,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently tempConstArray = new ConstantUnion[objectSize]; {// support MSVC++6.0 - for (int i = 0; i < objectSize; i++) + for (size_t i = 0; i < objectSize; i++) tempConstArray[i] = unionArray[i] && rightUnionArray[i]; } break; @@ -1232,7 +1215,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod case EOpLogicalOr: // this code is written for possible future use, will not get executed currently tempConstArray = new ConstantUnion[objectSize]; {// support MSVC++6.0 - for (int i = 0; i < objectSize; i++) + for (size_t i = 0; i < objectSize; i++) tempConstArray[i] = unionArray[i] || rightUnionArray[i]; } break; @@ -1240,7 +1223,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod case EOpLogicalXor: tempConstArray = new ConstantUnion[objectSize]; {// support MSVC++6.0 - for (int i = 0; i < objectSize; i++) + for (size_t i = 0; i < objectSize; i++) switch (getType().getBasicType()) { case EbtBool: tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); break; default: assert(false && "Default missing"); @@ -1286,7 +1269,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod if (!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray)) boolNodeFlag = true; } else { - for (int i = 0; i < objectSize; i++) { + for (size_t i = 0; i < objectSize; i++) { if (unionArray[i] != rightUnionArray[i]) { boolNodeFlag = true; break; // break out of for loop @@ -1312,7 +1295,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod if (CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray)) boolNodeFlag = true; } else { - for (int i = 0; i < objectSize; i++) { + for (size_t i = 0; i < objectSize; i++) { if (unionArray[i] == rightUnionArray[i]) { boolNodeFlag = true; break; // break out of for loop @@ -1334,7 +1317,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod return tempNode; default: - infoSink.info.message(EPrefixInternalError, "Invalid operator for constant folding", getLine()); + infoSink.info.message(EPrefixInternalError, getLine(), "Invalid operator for constant folding"); return 0; } tempNode = new TIntermConstantUnion(tempConstArray, returnType); @@ -1347,14 +1330,14 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod // TIntermConstantUnion *newNode = 0; ConstantUnion* tempConstArray = new ConstantUnion[objectSize]; - for (int i = 0; i < objectSize; i++) { + for (size_t i = 0; i < objectSize; i++) { switch(op) { case EOpNegative: switch (getType().getBasicType()) { case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break; case EbtInt: tempConstArray[i].setIConst(-unionArray[i].getIConst()); break; default: - infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine()); + infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); return 0; } break; @@ -1362,7 +1345,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod switch (getType().getBasicType()) { case EbtBool: tempConstArray[i].setBConst(!unionArray[i].getBConst()); break; default: - infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine()); + infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); return 0; } break; @@ -1378,11 +1361,11 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node) { - int size = node->getType().getObjectSize(); + size_t size = node->getType().getObjectSize(); ConstantUnion *leftUnionArray = new ConstantUnion[size]; - for (int i=0; i < size; i++) { + for (size_t i = 0; i < size; i++) { switch (promoteTo) { case EbtFloat: @@ -1397,7 +1380,7 @@ TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermC leftUnionArray[i].setFConst(static_cast(node->getFConst(i))); break; default: - infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine()); + infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote"); return 0; } break; @@ -1413,7 +1396,7 @@ TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermC leftUnionArray[i].setIConst(static_cast(node->getFConst(i))); break; default: - infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine()); + infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote"); return 0; } break; @@ -1429,13 +1412,13 @@ TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermC leftUnionArray[i].setBConst(node->getFConst(i) != 0.0f); break; default: - infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine()); + infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote"); return 0; } break; default: - infoSink.info.message(EPrefixInternalError, "Incorrect data type found", node->getLine()); + infoSink.info.message(EPrefixInternalError, node->getLine(), "Incorrect data type found"); return 0; } diff --git a/gfx/angle/src/compiler/MapLongVariableNames.cpp b/gfx/angle/src/compiler/MapLongVariableNames.cpp index b48c147d7f4d..2f89cbebac36 100644 --- a/gfx/angle/src/compiler/MapLongVariableNames.cpp +++ b/gfx/angle/src/compiler/MapLongVariableNames.cpp @@ -5,7 +5,8 @@ // #include "compiler/MapLongVariableNames.h" -#include "spooky.h" + +#include "third_party/murmurhash/MurmurHash3.h" namespace { @@ -13,7 +14,9 @@ TString mapLongName(size_t id, const TString& name, bool isGlobal) { ASSERT(name.size() > MAX_SHORTENED_IDENTIFIER_SIZE); TStringStream stream; - uint64 hash = SpookyHash::Hash64(name.data(), name.length(), 0); + + uint64_t hash[2] = {0, 0}; + MurmurHash3_x64_128(name.data(), name.length(), 0, hash); // We want to avoid producing a string with a double underscore, // which would be an illegal GLSL identifier. We can assume that the @@ -23,7 +26,7 @@ TString mapLongName(size_t id, const TString& name, bool isGlobal) << name.substr(0, 9) << (name[8] == '_' ? "" : "_") << std::hex - << hash; + << hash[0]; ASSERT(stream.str().length() <= MAX_SHORTENED_IDENTIFIER_SIZE); ASSERT(stream.str().length() >= MAX_SHORTENED_IDENTIFIER_SIZE - 2); return stream.str(); diff --git a/gfx/angle/src/compiler/OutputGLSL.cpp b/gfx/angle/src/compiler/OutputGLSL.cpp index 206f403408b1..10a451c0d76e 100644 --- a/gfx/angle/src/compiler/OutputGLSL.cpp +++ b/gfx/angle/src/compiler/OutputGLSL.cpp @@ -19,3 +19,17 @@ bool TOutputGLSL::writeVariablePrecision(TPrecision) { return false; } + +void TOutputGLSL::visitSymbol(TIntermSymbol* node) +{ + TInfoSinkBase& out = objSink(); + + if (node->getSymbol() == "gl_FragDepthEXT") + { + out << "gl_FragDepth"; + } + else + { + TOutputGLSLBase::visitSymbol(node); + } +} diff --git a/gfx/angle/src/compiler/OutputGLSL.h b/gfx/angle/src/compiler/OutputGLSL.h index 199b6f3e46cf..fa68ac81030e 100644 --- a/gfx/angle/src/compiler/OutputGLSL.h +++ b/gfx/angle/src/compiler/OutputGLSL.h @@ -20,6 +20,7 @@ public: protected: virtual bool writeVariablePrecision(TPrecision); + virtual void visitSymbol(TIntermSymbol* node); }; #endif // CROSSCOMPILERGLSL_OUTPUTGLSL_H_ diff --git a/gfx/angle/src/compiler/OutputGLSLBase.cpp b/gfx/angle/src/compiler/OutputGLSLBase.cpp index 861c51a55a06..82995fc31245 100644 --- a/gfx/angle/src/compiler/OutputGLSLBase.cpp +++ b/gfx/angle/src/compiler/OutputGLSLBase.cpp @@ -79,25 +79,9 @@ void TOutputGLSLBase::writeVariableType(const TType& type) if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal)) out << type.getQualifierString() << " "; // Declare the struct if we have not done so already. - if ((type.getBasicType() == EbtStruct) && - (mDeclaredStructs.find(type.getTypeName()) == mDeclaredStructs.end())) + if ((type.getBasicType() == EbtStruct) && !structDeclared(type.getStruct())) { - out << "struct " << hashName(type.getTypeName()) << "{\n"; - const TTypeList* structure = type.getStruct(); - ASSERT(structure != NULL); - for (size_t i = 0; i < structure->size(); ++i) - { - const TType* fieldType = (*structure)[i].type; - ASSERT(fieldType != NULL); - if (writeVariablePrecision(fieldType->getPrecision())) - out << " "; - out << getTypeName(*fieldType) << " " << hashName(fieldType->getFieldName()); - if (fieldType->isArray()) - out << arrayBrackets(*fieldType); - out << ";\n"; - } - out << "}"; - mDeclaredStructs.insert(type.getTypeName()); + declareStruct(type.getStruct()); } else { @@ -138,24 +122,25 @@ const ConstantUnion* TOutputGLSLBase::writeConstantUnion(const TType& type, if (type.getBasicType() == EbtStruct) { - out << hashName(type.getTypeName()) << "("; - const TTypeList* structure = type.getStruct(); - ASSERT(structure != NULL); - for (size_t i = 0; i < structure->size(); ++i) + const TStructure* structure = type.getStruct(); + out << hashName(structure->name()) << "("; + + const TFieldList& fields = structure->fields(); + for (size_t i = 0; i < fields.size(); ++i) { - const TType* fieldType = (*structure)[i].type; + const TType* fieldType = fields[i]->type(); ASSERT(fieldType != NULL); pConstUnion = writeConstantUnion(*fieldType, pConstUnion); - if (i != structure->size() - 1) out << ", "; + if (i != fields.size() - 1) out << ", "; } out << ")"; } else { - int size = type.getObjectSize(); + size_t size = type.getObjectSize(); bool writeType = size > 1; if (writeType) out << getTypeName(type) << "("; - for (int i = 0; i < size; ++i, ++pConstUnion) + for (size_t i = 0; i < size; ++i, ++pConstUnion) { switch (pConstUnion->getType()) { @@ -260,12 +245,18 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary* node) case EOpIndexDirectStruct: if (visit == InVisit) { + // Here we are writing out "foo.bar", where "foo" is struct + // and "bar" is field. In AST, it is represented as a binary + // node, where left child represents "foo" and right child "bar". + // The node itself represents ".". The struct field "bar" is + // actually stored as an index into TStructure::fields. out << "."; - // TODO(alokp): ASSERT - TString fieldName = node->getType().getFieldName(); + const TStructure* structure = node->getLeft()->getType().getStruct(); + const TIntermConstantUnion* index = node->getRight()->getAsConstantUnion(); + const TField* field = structure->fields()[index->getIConst(0)]; - const TType& structType = node->getLeft()->getType(); - if (!mSymbolTable.findBuiltIn(structType.getTypeName())) + TString fieldName = field->name(); + if (!mSymbolTable.findBuiltIn(structure->name())) fieldName = hashName(fieldName); out << fieldName; @@ -596,7 +587,7 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node) { const TType& type = node->getType(); ASSERT(type.getBasicType() == EbtStruct); - out << hashName(type.getTypeName()) << "("; + out << hashName(type.getStruct()->name()) << "("; } else if (visit == InVisit) { @@ -765,7 +756,7 @@ TString TOutputGLSLBase::getTypeName(const TType& type) else { if (type.getBasicType() == EbtStruct) - out << hashName(type.getTypeName()); + out << hashName(type.getStruct()->name()); else out << type.getBasicString(); } @@ -798,3 +789,29 @@ TString TOutputGLSLBase::hashFunctionName(const TString& mangled_name) return name; return hashName(name); } + +bool TOutputGLSLBase::structDeclared(const TStructure* structure) const +{ + return mDeclaredStructs.find(structure->name()) != mDeclaredStructs.end(); +} + +void TOutputGLSLBase::declareStruct(const TStructure* structure) +{ + TInfoSinkBase& out = objSink(); + + out << "struct " << hashName(structure->name()) << "{\n"; + const TFieldList& fields = structure->fields(); + for (size_t i = 0; i < fields.size(); ++i) + { + const TField* field = fields[i]; + if (writeVariablePrecision(field->type()->getPrecision())) + out << " "; + out << getTypeName(*field->type()) << " " << hashName(field->name()); + if (field->type()->isArray()) + out << arrayBrackets(*field->type()); + out << ";\n"; + } + out << "}"; + + mDeclaredStructs.insert(structure->name()); +} diff --git a/gfx/angle/src/compiler/OutputGLSLBase.h b/gfx/angle/src/compiler/OutputGLSLBase.h index c9f72d5631bd..df4ad68c2c89 100644 --- a/gfx/angle/src/compiler/OutputGLSLBase.h +++ b/gfx/angle/src/compiler/OutputGLSLBase.h @@ -52,6 +52,9 @@ protected: TString hashFunctionName(const TString& mangled_name); private: + bool structDeclared(const TStructure* structure) const; + void declareStruct(const TStructure* structure); + TInfoSinkBase& mObjSink; bool mDeclaringVariables; diff --git a/gfx/angle/src/compiler/OutputHLSL.cpp b/gfx/angle/src/compiler/OutputHLSL.cpp index b8b0751d5f1a..2735f943f1f3 100644 --- a/gfx/angle/src/compiler/OutputHLSL.cpp +++ b/gfx/angle/src/compiler/OutputHLSL.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -27,7 +27,8 @@ TString str(int i) return buffer; } -OutputHLSL::OutputHLSL(TParseContext &context) : TIntermTraverser(true, true, true), mContext(context) +OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resources, ShShaderOutput outputType) + : TIntermTraverser(true, true, true), mContext(context), mOutputType(outputType) { mUnfoldShortCircuit = new UnfoldShortCircuit(context, this); mInsideFunction = false; @@ -47,11 +48,14 @@ OutputHLSL::OutputHLSL(TParseContext &context) : TIntermTraverser(true, true, tr mUsesTexture2DProjLod0_bias = false; mUsesTextureCubeLod0 = false; mUsesTextureCubeLod0_bias = false; + mUsesFragColor = false; + mUsesFragData = false; mUsesDepthRange = false; mUsesFragCoord = false; mUsesPointCoord = false; mUsesFrontFacing = false; mUsesPointSize = false; + mUsesFragDepth = false; mUsesXor = false; mUsesMod1 = false; mUsesMod2v = false; @@ -64,23 +68,13 @@ OutputHLSL::OutputHLSL(TParseContext &context) : TIntermTraverser(true, true, tr mUsesFaceforward2 = false; mUsesFaceforward3 = false; mUsesFaceforward4 = false; - mUsesEqualMat2 = false; - mUsesEqualMat3 = false; - mUsesEqualMat4 = false; - mUsesEqualVec2 = false; - mUsesEqualVec3 = false; - mUsesEqualVec4 = false; - mUsesEqualIVec2 = false; - mUsesEqualIVec3 = false; - mUsesEqualIVec4 = false; - mUsesEqualBVec2 = false; - mUsesEqualBVec3 = false; - mUsesEqualBVec4 = false; mUsesAtan2_1 = false; mUsesAtan2_2 = false; mUsesAtan2_3 = false; mUsesAtan2_4 = false; + mNumRenderTargets = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1; + mScopeDepth = 0; mUniqueIndex = 0; @@ -90,6 +84,24 @@ OutputHLSL::OutputHLSL(TParseContext &context) : TIntermTraverser(true, true, tr mInsideDiscontinuousLoop = false; mExcessiveLoopIndex = NULL; + + if (mOutputType == SH_HLSL9_OUTPUT) + { + if (mContext.shaderType == SH_FRAGMENT_SHADER) + { + mUniformRegister = 3; // Reserve registers for dx_DepthRange, dx_ViewCoords and dx_DepthFront + } + else + { + mUniformRegister = 2; // Reserve registers for dx_DepthRange and dx_ViewAdjust + } + } + else + { + mUniformRegister = 0; + } + + mSamplerRegister = 0; } OutputHLSL::~OutputHLSL() @@ -113,6 +125,11 @@ TInfoSinkBase &OutputHLSL::getBodyStream() return mBody; } +const ActiveUniforms &OutputHLSL::getUniforms() +{ + return mActiveUniforms; +} + int OutputHLSL::vectorSize(const TType &type) const { int elementSize = type.isMatrix() ? type.getNominalSize() : 1; @@ -136,58 +153,76 @@ void OutputHLSL::header() out << *constructor; } + TString uniforms; + TString varyings; + TString attributes; + + for (ReferencedSymbols::const_iterator uniform = mReferencedUniforms.begin(); uniform != mReferencedUniforms.end(); uniform++) + { + const TType &type = uniform->second->getType(); + const TString &name = uniform->second->getSymbol(); + + if (mOutputType == SH_HLSL11_OUTPUT && IsSampler(type.getBasicType())) // Also declare the texture + { + int index = samplerRegister(mReferencedUniforms[name]); + + uniforms += "uniform SamplerState sampler_" + decorateUniform(name, type) + arrayString(type) + + " : register(s" + str(index) + ");\n"; + + uniforms += "uniform " + textureString(type) + " texture_" + decorateUniform(name, type) + arrayString(type) + + " : register(t" + str(index) + ");\n"; + } + else + { + uniforms += "uniform " + typeString(type) + " " + decorateUniform(name, type) + arrayString(type) + + " : register(" + registerString(mReferencedUniforms[name]) + ");\n"; + } + } + + for (ReferencedSymbols::const_iterator varying = mReferencedVaryings.begin(); varying != mReferencedVaryings.end(); varying++) + { + const TType &type = varying->second->getType(); + const TString &name = varying->second->getSymbol(); + + // Program linking depends on this exact format + varyings += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n"; + } + + for (ReferencedSymbols::const_iterator attribute = mReferencedAttributes.begin(); attribute != mReferencedAttributes.end(); attribute++) + { + const TType &type = attribute->second->getType(); + const TString &name = attribute->second->getSymbol(); + + attributes += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n"; + } + if (shaderType == SH_FRAGMENT_SHADER) { - TString uniforms; - TString varyings; + TExtensionBehavior::const_iterator iter = mContext.extensionBehavior().find("GL_EXT_draw_buffers"); + const bool usingMRTExtension = (iter != mContext.extensionBehavior().end() && (iter->second == EBhEnable || iter->second == EBhRequire)); - TSymbolTableLevel *symbols = mContext.symbolTable.getGlobalLevel(); - int semanticIndex = 0; - - for (TSymbolTableLevel::const_iterator namedSymbol = symbols->begin(); namedSymbol != symbols->end(); namedSymbol++) - { - const TSymbol *symbol = (*namedSymbol).second; - const TString &name = symbol->getName(); - - if (symbol->isVariable()) - { - const TVariable *variable = static_cast(symbol); - const TType &type = variable->getType(); - TQualifier qualifier = type.getQualifier(); - - if (qualifier == EvqUniform) - { - if (mReferencedUniforms.find(name.c_str()) != mReferencedUniforms.end()) - { - uniforms += "uniform " + typeString(type) + " " + decorateUniform(name, type) + arrayString(type) + ";\n"; - } - } - else if (qualifier == EvqVaryingIn || qualifier == EvqInvariantVaryingIn) - { - if (mReferencedVaryings.find(name.c_str()) != mReferencedVaryings.end()) - { - // Program linking depends on this exact format - varyings += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n"; - - semanticIndex += type.isArray() ? type.getArraySize() : 1; - } - } - else if (qualifier == EvqGlobal || qualifier == EvqTemporary) - { - // Globals are declared and intialized as an aggregate node - } - else if (qualifier == EvqConst) - { - // Constants are repeated as literals where used - } - else UNREACHABLE(); - } - } + const unsigned int numColorValues = usingMRTExtension ? mNumRenderTargets : 1; out << "// Varyings\n"; out << varyings; out << "\n" - "static float4 gl_Color[1] = {float4(0, 0, 0, 0)};\n"; + "static float4 gl_Color[" << numColorValues << "] =\n" + "{\n"; + for (unsigned int i = 0; i < numColorValues; i++) + { + out << " float4(0, 0, 0, 0)"; + if (i + 1 != numColorValues) + { + out << ","; + } + out << "\n"; + } + out << "};\n"; + + if (mUsesFragDepth) + { + out << "static float gl_Depth = 0.0;\n"; + } if (mUsesFragCoord) { @@ -206,205 +241,379 @@ void OutputHLSL::header() out << "\n"; - if (mUsesFragCoord) + if (mUsesDepthRange) { - out << "uniform float4 dx_Coord;\n" - "uniform float2 dx_Depth;\n"; + out << "struct gl_DepthRangeParameters\n" + "{\n" + " float near;\n" + " float far;\n" + " float diff;\n" + "};\n" + "\n"; } - if (mUsesFrontFacing) + if (mOutputType == SH_HLSL11_OUTPUT) { - out << "uniform bool dx_PointsOrLines;\n" - "uniform bool dx_FrontCCW;\n"; + out << "cbuffer DriverConstants : register(b1)\n" + "{\n"; + + if (mUsesDepthRange) + { + out << " float3 dx_DepthRange : packoffset(c0);\n"; + } + + if (mUsesFragCoord) + { + out << " float4 dx_ViewCoords : packoffset(c1);\n"; + } + + if (mUsesFragCoord || mUsesFrontFacing) + { + out << " float3 dx_DepthFront : packoffset(c2);\n"; + } + + out << "};\n"; + } + else + { + if (mUsesDepthRange) + { + out << "uniform float3 dx_DepthRange : register(c0);"; + } + + if (mUsesFragCoord) + { + out << "uniform float4 dx_ViewCoords : register(c1);\n"; + } + + if (mUsesFragCoord || mUsesFrontFacing) + { + out << "uniform float3 dx_DepthFront : register(c2);\n"; + } + } + + out << "\n"; + + if (mUsesDepthRange) + { + out << "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, dx_DepthRange.y, dx_DepthRange.z};\n" + "\n"; } - out << "\n"; out << uniforms; out << "\n"; if (mUsesTexture2D) { - out << "float4 gl_texture2D(sampler2D s, float2 t)\n" - "{\n" - " return tex2D(s, t);\n" - "}\n" - "\n"; + if (mOutputType == SH_HLSL9_OUTPUT) + { + out << "float4 gl_texture2D(sampler2D s, float2 t)\n" + "{\n" + " return tex2D(s, t);\n" + "}\n" + "\n"; + } + else if (mOutputType == SH_HLSL11_OUTPUT) + { + out << "float4 gl_texture2D(Texture2D t, SamplerState s, float2 uv)\n" + "{\n" + " return t.Sample(s, uv);\n" + "}\n" + "\n"; + } + else UNREACHABLE(); } if (mUsesTexture2D_bias) { - out << "float4 gl_texture2D(sampler2D s, float2 t, float bias)\n" - "{\n" - " return tex2Dbias(s, float4(t.x, t.y, 0, bias));\n" - "}\n" - "\n"; + if (mOutputType == SH_HLSL9_OUTPUT) + { + out << "float4 gl_texture2D(sampler2D s, float2 t, float bias)\n" + "{\n" + " return tex2Dbias(s, float4(t.x, t.y, 0, bias));\n" + "}\n" + "\n"; + } + else if (mOutputType == SH_HLSL11_OUTPUT) + { + out << "float4 gl_texture2D(Texture2D t, SamplerState s, float2 uv, float bias)\n" + "{\n" + " return t.SampleBias(s, uv, bias);\n" + "}\n" + "\n"; + } + else UNREACHABLE(); } if (mUsesTexture2DProj) { - out << "float4 gl_texture2DProj(sampler2D s, float3 t)\n" - "{\n" - " return tex2Dproj(s, float4(t.x, t.y, 0, t.z));\n" - "}\n" - "\n" - "float4 gl_texture2DProj(sampler2D s, float4 t)\n" - "{\n" - " return tex2Dproj(s, t);\n" - "}\n" - "\n"; + if (mOutputType == SH_HLSL9_OUTPUT) + { + out << "float4 gl_texture2DProj(sampler2D s, float3 t)\n" + "{\n" + " return tex2Dproj(s, float4(t.x, t.y, 0, t.z));\n" + "}\n" + "\n" + "float4 gl_texture2DProj(sampler2D s, float4 t)\n" + "{\n" + " return tex2Dproj(s, t);\n" + "}\n" + "\n"; + } + else if (mOutputType == SH_HLSL11_OUTPUT) + { + out << "float4 gl_texture2DProj(Texture2D t, SamplerState s, float3 uvw)\n" + "{\n" + " return t.Sample(s, float2(uvw.x / uvw.z, uvw.y / uvw.z));\n" + "}\n" + "\n" + "float4 gl_texture2DProj(Texture2D t, SamplerState s, float4 uvw)\n" + "{\n" + " return t.Sample(s, float2(uvw.x / uvw.w, uvw.y / uvw.w));\n" + "}\n" + "\n"; + } + else UNREACHABLE(); } if (mUsesTexture2DProj_bias) { - out << "float4 gl_texture2DProj(sampler2D s, float3 t, float bias)\n" - "{\n" - " return tex2Dbias(s, float4(t.x / t.z, t.y / t.z, 0, bias));\n" - "}\n" - "\n" - "float4 gl_texture2DProj(sampler2D s, float4 t, float bias)\n" - "{\n" - " return tex2Dbias(s, float4(t.x / t.w, t.y / t.w, 0, bias));\n" - "}\n" - "\n"; + if (mOutputType == SH_HLSL9_OUTPUT) + { + out << "float4 gl_texture2DProj(sampler2D s, float3 t, float bias)\n" + "{\n" + " return tex2Dbias(s, float4(t.x / t.z, t.y / t.z, 0, bias));\n" + "}\n" + "\n" + "float4 gl_texture2DProj(sampler2D s, float4 t, float bias)\n" + "{\n" + " return tex2Dbias(s, float4(t.x / t.w, t.y / t.w, 0, bias));\n" + "}\n" + "\n"; + } + else if (mOutputType == SH_HLSL11_OUTPUT) + { + out << "float4 gl_texture2DProj(Texture2D t, SamplerState s, float3 uvw, float bias)\n" + "{\n" + " return t.SampleBias(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), bias);\n" + "}\n" + "\n" + "float4 gl_texture2DProj(Texture2D t, SamplerState s, float4 uvw, float bias)\n" + "{\n" + " return t.SampleBias(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), bias);\n" + "}\n" + "\n"; + } + else UNREACHABLE(); } if (mUsesTextureCube) { - out << "float4 gl_textureCube(samplerCUBE s, float3 t)\n" - "{\n" - " return texCUBE(s, t);\n" - "}\n" - "\n"; + if (mOutputType == SH_HLSL9_OUTPUT) + { + out << "float4 gl_textureCube(samplerCUBE s, float3 t)\n" + "{\n" + " return texCUBE(s, t);\n" + "}\n" + "\n"; + } + else if (mOutputType == SH_HLSL11_OUTPUT) + { + out << "float4 gl_textureCube(TextureCube t, SamplerState s, float3 uvw)\n" + "{\n" + " return t.Sample(s, uvw);\n" + "}\n" + "\n"; + } + else UNREACHABLE(); } if (mUsesTextureCube_bias) { - out << "float4 gl_textureCube(samplerCUBE s, float3 t, float bias)\n" - "{\n" - " return texCUBEbias(s, float4(t.x, t.y, t.z, bias));\n" - "}\n" - "\n"; + if (mOutputType == SH_HLSL9_OUTPUT) + { + out << "float4 gl_textureCube(samplerCUBE s, float3 t, float bias)\n" + "{\n" + " return texCUBEbias(s, float4(t.x, t.y, t.z, bias));\n" + "}\n" + "\n"; + } + else if (mOutputType == SH_HLSL11_OUTPUT) + { + out << "float4 gl_textureCube(TextureCube t, SamplerState s, float3 uvw, float bias)\n" + "{\n" + " return t.SampleBias(s, uvw, bias);\n" + "}\n" + "\n"; + } + else UNREACHABLE(); } // These *Lod0 intrinsics are not available in GL fragment shaders. // They are used to sample using discontinuous texture coordinates. if (mUsesTexture2DLod0) { - out << "float4 gl_texture2DLod0(sampler2D s, float2 t)\n" - "{\n" - " return tex2Dlod(s, float4(t.x, t.y, 0, 0));\n" - "}\n" - "\n"; + if (mOutputType == SH_HLSL9_OUTPUT) + { + out << "float4 gl_texture2DLod0(sampler2D s, float2 t)\n" + "{\n" + " return tex2Dlod(s, float4(t.x, t.y, 0, 0));\n" + "}\n" + "\n"; + } + else if (mOutputType == SH_HLSL11_OUTPUT) + { + out << "float4 gl_texture2DLod0(Texture2D t, SamplerState s, float2 uv)\n" + "{\n" + " return t.SampleLevel(s, uv, 0);\n" + "}\n" + "\n"; + } + else UNREACHABLE(); } if (mUsesTexture2DLod0_bias) { - out << "float4 gl_texture2DLod0(sampler2D s, float2 t, float bias)\n" - "{\n" - " return tex2Dlod(s, float4(t.x, t.y, 0, 0));\n" - "}\n" - "\n"; + if (mOutputType == SH_HLSL9_OUTPUT) + { + out << "float4 gl_texture2DLod0(sampler2D s, float2 t, float bias)\n" + "{\n" + " return tex2Dlod(s, float4(t.x, t.y, 0, 0));\n" + "}\n" + "\n"; + } + else if (mOutputType == SH_HLSL11_OUTPUT) + { + out << "float4 gl_texture2DLod0(Texture2D t, SamplerState s, float2 uv, float bias)\n" + "{\n" + " return t.SampleLevel(s, uv, 0);\n" + "}\n" + "\n"; + } + else UNREACHABLE(); } if (mUsesTexture2DProjLod0) { - out << "float4 gl_texture2DProjLod0(sampler2D s, float3 t)\n" - "{\n" - " return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, 0));\n" - "}\n" - "\n" - "float4 gl_texture2DProjLod(sampler2D s, float4 t)\n" - "{\n" - " return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, 0));\n" - "}\n" - "\n"; + if (mOutputType == SH_HLSL9_OUTPUT) + { + out << "float4 gl_texture2DProjLod0(sampler2D s, float3 t)\n" + "{\n" + " return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, 0));\n" + "}\n" + "\n" + "float4 gl_texture2DProjLod(sampler2D s, float4 t)\n" + "{\n" + " return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, 0));\n" + "}\n" + "\n"; + } + else if (mOutputType == SH_HLSL11_OUTPUT) + { + out << "float4 gl_texture2DProjLod0(Texture2D t, SamplerState s, float3 uvw)\n" + "{\n" + " return t.SampleLevel(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), 0);\n" + "}\n" + "\n" + "float4 gl_texture2DProjLod0(Texture2D t, SamplerState s, float4 uvw)\n" + "{\n" + " return t.SampleLevel(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), 0);\n" + "}\n" + "\n"; + } + else UNREACHABLE(); } if (mUsesTexture2DProjLod0_bias) { - out << "float4 gl_texture2DProjLod0_bias(sampler2D s, float3 t, float bias)\n" - "{\n" - " return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, 0));\n" - "}\n" - "\n" - "float4 gl_texture2DProjLod_bias(sampler2D s, float4 t, float bias)\n" - "{\n" - " return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, 0));\n" - "}\n" - "\n"; + if (mOutputType == SH_HLSL9_OUTPUT) + { + out << "float4 gl_texture2DProjLod0_bias(sampler2D s, float3 t, float bias)\n" + "{\n" + " return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, 0));\n" + "}\n" + "\n" + "float4 gl_texture2DProjLod_bias(sampler2D s, float4 t, float bias)\n" + "{\n" + " return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, 0));\n" + "}\n" + "\n"; + } + else if (mOutputType == SH_HLSL11_OUTPUT) + { + out << "float4 gl_texture2DProjLod_bias(Texture2D t, SamplerState s, float3 uvw, float bias)\n" + "{\n" + " return t.SampleLevel(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), 0);\n" + "}\n" + "\n" + "float4 gl_texture2DProjLod_bias(Texture2D t, SamplerState s, float4 uvw, float bias)\n" + "{\n" + " return t.SampleLevel(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), 0);\n" + "}\n" + "\n"; + } + else UNREACHABLE(); } if (mUsesTextureCubeLod0) { - out << "float4 gl_textureCubeLod0(samplerCUBE s, float3 t)\n" - "{\n" - " return texCUBElod(s, float4(t.x, t.y, t.z, 0));\n" - "}\n" - "\n"; + if (mOutputType == SH_HLSL9_OUTPUT) + { + out << "float4 gl_textureCubeLod0(samplerCUBE s, float3 t)\n" + "{\n" + " return texCUBElod(s, float4(t.x, t.y, t.z, 0));\n" + "}\n" + "\n"; + } + else if (mOutputType == SH_HLSL11_OUTPUT) + { + out << "float4 gl_textureCubeLod0(TextureCube t, SamplerState s, float3 uvw)\n" + "{\n" + " return t.SampleLevel(s, uvw, 0);\n" + "}\n" + "\n"; + } + else UNREACHABLE(); } if (mUsesTextureCubeLod0_bias) { - out << "float4 gl_textureCubeLod0(samplerCUBE s, float3 t, float bias)\n" - "{\n" - " return texCUBElod(s, float4(t.x, t.y, t.z, 0));\n" - "}\n" - "\n"; + if (mOutputType == SH_HLSL9_OUTPUT) + { + out << "float4 gl_textureCubeLod0(samplerCUBE s, float3 t, float bias)\n" + "{\n" + " return texCUBElod(s, float4(t.x, t.y, t.z, 0));\n" + "}\n" + "\n"; + } + else if (mOutputType == SH_HLSL11_OUTPUT) + { + out << "float4 gl_textureCubeLod0(TextureCube t, SamplerState s, float3 uvw, float bias)\n" + "{\n" + " return t.SampleLevel(s, uvw, 0);\n" + "}\n" + "\n"; + } + else UNREACHABLE(); + } + + if (usingMRTExtension && mNumRenderTargets > 1) + { + out << "#define GL_USES_MRT\n"; + } + + if (mUsesFragColor) + { + out << "#define GL_USES_FRAG_COLOR\n"; + } + + if (mUsesFragData) + { + out << "#define GL_USES_FRAG_DATA\n"; } } else // Vertex shader { - TString uniforms; - TString attributes; - TString varyings; - - TSymbolTableLevel *symbols = mContext.symbolTable.getGlobalLevel(); - - for (TSymbolTableLevel::const_iterator namedSymbol = symbols->begin(); namedSymbol != symbols->end(); namedSymbol++) - { - const TSymbol *symbol = (*namedSymbol).second; - const TString &name = symbol->getName(); - - if (symbol->isVariable()) - { - const TVariable *variable = static_cast(symbol); - const TType &type = variable->getType(); - TQualifier qualifier = type.getQualifier(); - - if (qualifier == EvqUniform) - { - if (mReferencedUniforms.find(name.c_str()) != mReferencedUniforms.end()) - { - uniforms += "uniform " + typeString(type) + " " + decorateUniform(name, type) + arrayString(type) + ";\n"; - } - } - else if (qualifier == EvqAttribute) - { - if (mReferencedAttributes.find(name.c_str()) != mReferencedAttributes.end()) - { - attributes += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n"; - } - } - else if (qualifier == EvqVaryingOut || qualifier == EvqInvariantVaryingOut) - { - if (mReferencedVaryings.find(name.c_str()) != mReferencedVaryings.end()) - { - // Program linking depends on this exact format - varyings += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n"; - } - } - else if (qualifier == EvqGlobal || qualifier == EvqTemporary) - { - // Globals are declared and intialized as an aggregate node - } - else if (qualifier == EvqConst) - { - // Constants are repeated as literals where used - } - else UNREACHABLE(); - } - } - out << "// Attributes\n"; out << attributes; out << "\n" @@ -418,74 +627,194 @@ void OutputHLSL::header() out << "\n" "// Varyings\n"; out << varyings; - out << "\n" - "uniform float2 dx_HalfPixelSize;\n" - "\n"; - out << uniforms; + out << "\n"; + + if (mUsesDepthRange) + { + out << "struct gl_DepthRangeParameters\n" + "{\n" + " float near;\n" + " float far;\n" + " float diff;\n" + "};\n" + "\n"; + } + + if (mOutputType == SH_HLSL11_OUTPUT) + { + if (mUsesDepthRange) + { + out << "cbuffer DriverConstants : register(b1)\n" + "{\n" + " float3 dx_DepthRange : packoffset(c0);\n" + "};\n" + "\n"; + } + } + else + { + if (mUsesDepthRange) + { + out << "uniform float3 dx_DepthRange : register(c0);\n"; + } + + out << "uniform float4 dx_ViewAdjust : register(c1);\n" + "\n"; + } + + if (mUsesDepthRange) + { + out << "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, dx_DepthRange.y, dx_DepthRange.z};\n" + "\n"; + } + + out << uniforms; out << "\n"; if (mUsesTexture2D) { - out << "float4 gl_texture2D(sampler2D s, float2 t)\n" - "{\n" - " return tex2Dlod(s, float4(t.x, t.y, 0, 0));\n" - "}\n" - "\n"; + if (mOutputType == SH_HLSL9_OUTPUT) + { + out << "float4 gl_texture2D(sampler2D s, float2 t)\n" + "{\n" + " return tex2Dlod(s, float4(t.x, t.y, 0, 0));\n" + "}\n" + "\n"; + } + else if (mOutputType == SH_HLSL11_OUTPUT) + { + out << "float4 gl_texture2D(Texture2D t, SamplerState s, float2 uv)\n" + "{\n" + " return t.SampleLevel(s, uv, 0);\n" + "}\n" + "\n"; + } + else UNREACHABLE(); } if (mUsesTexture2DLod) { - out << "float4 gl_texture2DLod(sampler2D s, float2 t, float lod)\n" - "{\n" - " return tex2Dlod(s, float4(t.x, t.y, 0, lod));\n" - "}\n" - "\n"; + if (mOutputType == SH_HLSL9_OUTPUT) + { + out << "float4 gl_texture2DLod(sampler2D s, float2 t, float lod)\n" + "{\n" + " return tex2Dlod(s, float4(t.x, t.y, 0, lod));\n" + "}\n" + "\n"; + } + else if (mOutputType == SH_HLSL11_OUTPUT) + { + out << "float4 gl_texture2DLod(Texture2D t, SamplerState s, float2 uv, float lod)\n" + "{\n" + " return t.SampleLevel(s, uv, lod);\n" + "}\n" + "\n"; + } + else UNREACHABLE(); } if (mUsesTexture2DProj) { - out << "float4 gl_texture2DProj(sampler2D s, float3 t)\n" - "{\n" - " return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, 0));\n" - "}\n" - "\n" - "float4 gl_texture2DProj(sampler2D s, float4 t)\n" - "{\n" - " return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, 0));\n" - "}\n" - "\n"; + if (mOutputType == SH_HLSL9_OUTPUT) + { + out << "float4 gl_texture2DProj(sampler2D s, float3 t)\n" + "{\n" + " return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, 0));\n" + "}\n" + "\n" + "float4 gl_texture2DProj(sampler2D s, float4 t)\n" + "{\n" + " return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, 0));\n" + "}\n" + "\n"; + } + else if (mOutputType == SH_HLSL11_OUTPUT) + { + out << "float4 gl_texture2DProj(Texture2D t, SamplerState s, float3 uvw)\n" + "{\n" + " return t.SampleLevel(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), 0);\n" + "}\n" + "\n" + "float4 gl_texture2DProj(Texture2D t, SamplerState s, float4 uvw)\n" + "{\n" + " return t.SampleLevel(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), 0);\n" + "}\n" + "\n"; + } + else UNREACHABLE(); } if (mUsesTexture2DProjLod) { - out << "float4 gl_texture2DProjLod(sampler2D s, float3 t, float lod)\n" - "{\n" - " return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, lod));\n" - "}\n" - "\n" - "float4 gl_texture2DProjLod(sampler2D s, float4 t, float lod)\n" - "{\n" - " return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, lod));\n" - "}\n" - "\n"; + if (mOutputType == SH_HLSL9_OUTPUT) + { + out << "float4 gl_texture2DProjLod(sampler2D s, float3 t, float lod)\n" + "{\n" + " return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, lod));\n" + "}\n" + "\n" + "float4 gl_texture2DProjLod(sampler2D s, float4 t, float lod)\n" + "{\n" + " return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, lod));\n" + "}\n" + "\n"; + } + else if (mOutputType == SH_HLSL11_OUTPUT) + { + out << "float4 gl_texture2DProj(Texture2D t, SamplerState s, float3 uvw, float lod)\n" + "{\n" + " return t.SampleLevel(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), lod);\n" + "}\n" + "\n" + "float4 gl_texture2DProj(Texture2D t, SamplerState s, float4 uvw)\n" + "{\n" + " return t.SampleLevel(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), lod);\n" + "}\n" + "\n"; + } + else UNREACHABLE(); } if (mUsesTextureCube) { - out << "float4 gl_textureCube(samplerCUBE s, float3 t)\n" - "{\n" - " return texCUBElod(s, float4(t.x, t.y, t.z, 0));\n" - "}\n" - "\n"; + if (mOutputType == SH_HLSL9_OUTPUT) + { + out << "float4 gl_textureCube(samplerCUBE s, float3 t)\n" + "{\n" + " return texCUBElod(s, float4(t.x, t.y, t.z, 0));\n" + "}\n" + "\n"; + } + else if (mOutputType == SH_HLSL11_OUTPUT) + { + out << "float4 gl_textureCube(TextureCube t, SamplerState s, float3 uvw)\n" + "{\n" + " return t.SampleLevel(s, uvw, 0);\n" + "}\n" + "\n"; + } + else UNREACHABLE(); } if (mUsesTextureCubeLod) { - out << "float4 gl_textureCubeLod(samplerCUBE s, float3 t, float lod)\n" - "{\n" - " return texCUBElod(s, float4(t.x, t.y, t.z, lod));\n" - "}\n" - "\n"; + if (mOutputType == SH_HLSL9_OUTPUT) + { + out << "float4 gl_textureCubeLod(samplerCUBE s, float3 t, float lod)\n" + "{\n" + " return texCUBElod(s, float4(t.x, t.y, t.z, lod));\n" + "}\n" + "\n"; + } + else if (mOutputType == SH_HLSL11_OUTPUT) + { + out << "float4 gl_textureCubeLod(TextureCube t, SamplerState s, float3 uvw, float lod)\n" + "{\n" + " return t.SampleLevel(s, uvw, lod);\n" + "}\n" + "\n"; + } + else UNREACHABLE(); } } @@ -509,18 +838,14 @@ void OutputHLSL::header() out << "#define GL_USES_POINT_SIZE\n"; } + if (mUsesFragDepth) + { + out << "#define GL_USES_FRAG_DEPTH\n"; + } + if (mUsesDepthRange) { - out << "struct gl_DepthRangeParameters\n" - "{\n" - " float near;\n" - " float far;\n" - " float diff;\n" - "};\n" - "\n" - "uniform float3 dx_DepthRange;" - "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, dx_DepthRange.y, dx_DepthRange.z};\n" - "\n"; + out << "#define GL_USES_DEPTH_RANGE\n"; } if (mUsesXor) @@ -659,108 +984,6 @@ void OutputHLSL::header() "\n"; } - if (mUsesEqualMat2) - { - out << "bool equal(float2x2 m, float2x2 n)\n" - "{\n" - " return m[0][0] == n[0][0] && m[0][1] == n[0][1] &&\n" - " m[1][0] == n[1][0] && m[1][1] == n[1][1];\n" - "}\n"; - } - - if (mUsesEqualMat3) - { - out << "bool equal(float3x3 m, float3x3 n)\n" - "{\n" - " return m[0][0] == n[0][0] && m[0][1] == n[0][1] && m[0][2] == n[0][2] &&\n" - " m[1][0] == n[1][0] && m[1][1] == n[1][1] && m[1][2] == n[1][2] &&\n" - " m[2][0] == n[2][0] && m[2][1] == n[2][1] && m[2][2] == n[2][2];\n" - "}\n"; - } - - if (mUsesEqualMat4) - { - out << "bool equal(float4x4 m, float4x4 n)\n" - "{\n" - " return m[0][0] == n[0][0] && m[0][1] == n[0][1] && m[0][2] == n[0][2] && m[0][3] == n[0][3] &&\n" - " m[1][0] == n[1][0] && m[1][1] == n[1][1] && m[1][2] == n[1][2] && m[1][3] == n[1][3] &&\n" - " m[2][0] == n[2][0] && m[2][1] == n[2][1] && m[2][2] == n[2][2] && m[2][3] == n[2][3] &&\n" - " m[3][0] == n[3][0] && m[3][1] == n[3][1] && m[3][2] == n[3][2] && m[3][3] == n[3][3];\n" - "}\n"; - } - - if (mUsesEqualVec2) - { - out << "bool equal(float2 v, float2 u)\n" - "{\n" - " return v.x == u.x && v.y == u.y;\n" - "}\n"; - } - - if (mUsesEqualVec3) - { - out << "bool equal(float3 v, float3 u)\n" - "{\n" - " return v.x == u.x && v.y == u.y && v.z == u.z;\n" - "}\n"; - } - - if (mUsesEqualVec4) - { - out << "bool equal(float4 v, float4 u)\n" - "{\n" - " return v.x == u.x && v.y == u.y && v.z == u.z && v.w == u.w;\n" - "}\n"; - } - - if (mUsesEqualIVec2) - { - out << "bool equal(int2 v, int2 u)\n" - "{\n" - " return v.x == u.x && v.y == u.y;\n" - "}\n"; - } - - if (mUsesEqualIVec3) - { - out << "bool equal(int3 v, int3 u)\n" - "{\n" - " return v.x == u.x && v.y == u.y && v.z == u.z;\n" - "}\n"; - } - - if (mUsesEqualIVec4) - { - out << "bool equal(int4 v, int4 u)\n" - "{\n" - " return v.x == u.x && v.y == u.y && v.z == u.z && v.w == u.w;\n" - "}\n"; - } - - if (mUsesEqualBVec2) - { - out << "bool equal(bool2 v, bool2 u)\n" - "{\n" - " return v.x == u.x && v.y == u.y;\n" - "}\n"; - } - - if (mUsesEqualBVec3) - { - out << "bool equal(bool3 v, bool3 u)\n" - "{\n" - " return v.x == u.x && v.y == u.y && v.z == u.z;\n" - "}\n"; - } - - if (mUsesEqualBVec4) - { - out << "bool equal(bool4 v, bool4 u)\n" - "{\n" - " return v.x == u.x && v.y == u.y && v.z == u.z && v.w == u.w;\n" - "}\n"; - } - if (mUsesAtan2_1) { out << "float atanyx(float y, float x)\n" @@ -813,10 +1036,12 @@ void OutputHLSL::visitSymbol(TIntermSymbol *node) if (name == "gl_FragColor") { out << "gl_Color[0]"; + mUsesFragColor = true; } else if (name == "gl_FragData") { out << "gl_Color"; + mUsesFragData = true; } else if (name == "gl_DepthRange") { @@ -843,23 +1068,28 @@ void OutputHLSL::visitSymbol(TIntermSymbol *node) mUsesPointSize = true; out << name; } + else if (name == "gl_FragDepthEXT") + { + mUsesFragDepth = true; + out << "gl_Depth"; + } else { TQualifier qualifier = node->getQualifier(); if (qualifier == EvqUniform) { - mReferencedUniforms.insert(name.c_str()); + mReferencedUniforms[name] = node; out << decorateUniform(name, node->getType()); } else if (qualifier == EvqAttribute) { - mReferencedAttributes.insert(name.c_str()); + mReferencedAttributes[name] = node; out << decorate(name); } else if (qualifier == EvqVaryingOut || qualifier == EvqInvariantVaryingOut || qualifier == EvqVaryingIn || qualifier == EvqInvariantVaryingIn) { - mReferencedVaryings.insert(name.c_str()); + mReferencedVaryings[name] = node; out << decorate(name); } else @@ -952,7 +1182,10 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) case EOpIndexDirectStruct: if (visit == InVisit) { - out << "." + decorateField(node->getType().getFieldName(), node->getLeft()->getType()); + const TStructure* structure = node->getLeft()->getType().getStruct(); + const TIntermConstantUnion* index = node->getRight()->getAsConstantUnion(); + const TField* field = structure->fields()[index->getIConst(0)]; + out << "." + decorateField(field->name(), node->getLeft()->getType()); return false; } @@ -1021,18 +1254,18 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) out << "!("; } - const TTypeList *fields = node->getLeft()->getType().getStruct(); + const TFieldList &fields = node->getLeft()->getType().getStruct()->fields(); - for (size_t i = 0; i < fields->size(); i++) + for (size_t i = 0; i < fields.size(); i++) { - const TType *fieldType = (*fields)[i].type; + const TField *field = fields[i]; node->getLeft()->traverse(this); - out << "." + decorateField(fieldType->getFieldName(), node->getLeft()->getType()) + " == "; + out << "." + decorateField(field->name(), node->getLeft()->getType()) + " == "; node->getRight()->traverse(this); - out << "." + decorateField(fieldType->getFieldName(), node->getLeft()->getType()); + out << "." + decorateField(field->name(), node->getLeft()->getType()); - if (i < fields->size() - 1) + if (i < fields.size() - 1) { out << " && "; } @@ -1044,59 +1277,15 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) } else { - if (node->getLeft()->isMatrix()) - { - switch (node->getLeft()->getNominalSize()) - { - case 2: mUsesEqualMat2 = true; break; - case 3: mUsesEqualMat3 = true; break; - case 4: mUsesEqualMat4 = true; break; - default: UNREACHABLE(); - } - } - else if (node->getLeft()->isVector()) - { - switch (node->getLeft()->getBasicType()) - { - case EbtFloat: - switch (node->getLeft()->getNominalSize()) - { - case 2: mUsesEqualVec2 = true; break; - case 3: mUsesEqualVec3 = true; break; - case 4: mUsesEqualVec4 = true; break; - default: UNREACHABLE(); - } - break; - case EbtInt: - switch (node->getLeft()->getNominalSize()) - { - case 2: mUsesEqualIVec2 = true; break; - case 3: mUsesEqualIVec3 = true; break; - case 4: mUsesEqualIVec4 = true; break; - default: UNREACHABLE(); - } - break; - case EbtBool: - switch (node->getLeft()->getNominalSize()) - { - case 2: mUsesEqualBVec2 = true; break; - case 3: mUsesEqualBVec3 = true; break; - case 4: mUsesEqualBVec4 = true; break; - default: UNREACHABLE(); - } - break; - default: UNREACHABLE(); - } - } - else UNREACHABLE(); + ASSERT(node->getLeft()->isMatrix() || node->getLeft()->isVector()); if (node->getOp() == EOpEqual) { - outputTriplet(visit, "equal(", ", ", ")"); + outputTriplet(visit, "all(", " == ", ")"); } else { - outputTriplet(visit, "!equal(", ", ", ")"); + outputTriplet(visit, "!all(", " == ", ")"); } } break; @@ -1238,7 +1427,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) { if (mInsideFunction) { - outputLineDirective(node->getLine()); + outputLineDirective(node->getLine().first_line); out << "{\n"; mScopeDepth++; @@ -1255,7 +1444,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) for (TIntermSequence::iterator sit = node->getSequence().begin(); sit != node->getSequence().end(); sit++) { - outputLineDirective((*sit)->getLine()); + outputLineDirective((*sit)->getLine().first_line); traverseStatements(*sit); @@ -1264,7 +1453,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) if (mInsideFunction) { - outputLineDirective(node->getEndLine()); + outputLineDirective(node->getLine().last_line); out << "}\n"; mScopeDepth--; @@ -1277,13 +1466,12 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) { TIntermSequence &sequence = node->getSequence(); TIntermTyped *variable = sequence[0]->getAsTyped(); - bool visit = true; if (variable && (variable->getQualifier() == EvqTemporary || variable->getQualifier() == EvqGlobal)) { if (variable->getType().getStruct()) { - addConstructor(variable->getType(), scopedStruct(variable->getType().getTypeName()), NULL); + addConstructor(variable->getType(), scopedStruct(variable->getType().getStruct()->name()), NULL); } if (!variable->getAsSymbolNode() || variable->getAsSymbolNode()->getSymbol() != "") // Variable declaration @@ -1310,19 +1498,11 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) (*sit)->traverse(this); } - if (visit && this->inVisit) + if (*sit != sequence.back()) { - if (*sit != sequence.back()) - { - visit = this->visitAggregate(InVisit, node); - } + out << ", "; } } - - if (visit && this->postVisit) - { - this->visitAggregate(PostVisit, node); - } } else if (variable->getAsSymbolNode() && variable->getAsSymbolNode()->getSymbol() == "") // Type (struct) declaration { @@ -1330,7 +1510,24 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) } else UNREACHABLE(); } - + else if (variable && (variable->getQualifier() == EvqVaryingOut || variable->getQualifier() == EvqInvariantVaryingOut)) + { + for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++) + { + TIntermSymbol *symbol = (*sit)->getAsSymbolNode(); + + if (symbol) + { + // Vertex (output) varyings which are declared but not written to should still be declared to allow successful linking + mReferencedVaryings[symbol->getSymbol()] = symbol; + } + else + { + (*sit)->traverse(this); + } + } + } + return false; } else if (visit == InVisit) @@ -1401,7 +1598,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) { if (symbol->getType().getStruct()) { - addConstructor(symbol->getType(), scopedStruct(symbol->getType().getTypeName()), NULL); + addConstructor(symbol->getType(), scopedStruct(symbol->getType().getStruct()->name()), NULL); } out << argumentString(symbol); @@ -1441,151 +1638,163 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) break; case EOpFunctionCall: { - if (visit == PreVisit) + TString name = TFunction::unmangleName(node->getName()); + bool lod0 = mInsideDiscontinuousLoop || mOutputLod0Function; + + if (node->isUserDefined()) { - TString name = TFunction::unmangleName(node->getName()); - bool lod0 = mInsideDiscontinuousLoop || mOutputLod0Function; - - if (node->isUserDefined()) - { - out << decorate(name) << (lod0 ? "Lod0(" : "("); - } - else - { - if (name == "texture2D") - { - if (!lod0) - { - if (node->getSequence().size() == 2) - { - mUsesTexture2D = true; - } - else if (node->getSequence().size() == 3) - { - mUsesTexture2D_bias = true; - } - else UNREACHABLE(); - - out << "gl_texture2D("; - } - else - { - if (node->getSequence().size() == 2) - { - mUsesTexture2DLod0 = true; - } - else if (node->getSequence().size() == 3) - { - mUsesTexture2DLod0_bias = true; - } - else UNREACHABLE(); - - out << "gl_texture2DLod0("; - } - } - else if (name == "texture2DProj") - { - if (!lod0) - { - if (node->getSequence().size() == 2) - { - mUsesTexture2DProj = true; - } - else if (node->getSequence().size() == 3) - { - mUsesTexture2DProj_bias = true; - } - else UNREACHABLE(); - - out << "gl_texture2DProj("; - } - else - { - if (node->getSequence().size() == 2) - { - mUsesTexture2DProjLod0 = true; - } - else if (node->getSequence().size() == 3) - { - mUsesTexture2DProjLod0_bias = true; - } - else UNREACHABLE(); - - out << "gl_texture2DProjLod0("; - } - } - else if (name == "textureCube") - { - if (!lod0) - { - if (node->getSequence().size() == 2) - { - mUsesTextureCube = true; - } - else if (node->getSequence().size() == 3) - { - mUsesTextureCube_bias = true; - } - else UNREACHABLE(); - - out << "gl_textureCube("; - } - else - { - if (node->getSequence().size() == 2) - { - mUsesTextureCubeLod0 = true; - } - else if (node->getSequence().size() == 3) - { - mUsesTextureCubeLod0_bias = true; - } - else UNREACHABLE(); - - out << "gl_textureCubeLod0("; - } - } - else if (name == "texture2DLod") - { - if (node->getSequence().size() == 3) - { - mUsesTexture2DLod = true; - } - else UNREACHABLE(); - - out << "gl_texture2DLod("; - } - else if (name == "texture2DProjLod") - { - if (node->getSequence().size() == 3) - { - mUsesTexture2DProjLod = true; - } - else UNREACHABLE(); - - out << "gl_texture2DProjLod("; - } - else if (name == "textureCubeLod") - { - if (node->getSequence().size() == 3) - { - mUsesTextureCubeLod = true; - } - else UNREACHABLE(); - - out << "gl_textureCubeLod("; - } - else UNREACHABLE(); - } - } - else if (visit == InVisit) - { - out << ", "; + out << decorate(name) << (lod0 ? "Lod0(" : "("); } else { - out << ")"; + if (name == "texture2D") + { + if (!lod0) + { + if (node->getSequence().size() == 2) + { + mUsesTexture2D = true; + } + else if (node->getSequence().size() == 3) + { + mUsesTexture2D_bias = true; + } + else UNREACHABLE(); + + out << "gl_texture2D("; + } + else + { + if (node->getSequence().size() == 2) + { + mUsesTexture2DLod0 = true; + } + else if (node->getSequence().size() == 3) + { + mUsesTexture2DLod0_bias = true; + } + else UNREACHABLE(); + + out << "gl_texture2DLod0("; + } + } + else if (name == "texture2DProj") + { + if (!lod0) + { + if (node->getSequence().size() == 2) + { + mUsesTexture2DProj = true; + } + else if (node->getSequence().size() == 3) + { + mUsesTexture2DProj_bias = true; + } + else UNREACHABLE(); + + out << "gl_texture2DProj("; + } + else + { + if (node->getSequence().size() == 2) + { + mUsesTexture2DProjLod0 = true; + } + else if (node->getSequence().size() == 3) + { + mUsesTexture2DProjLod0_bias = true; + } + else UNREACHABLE(); + + out << "gl_texture2DProjLod0("; + } + } + else if (name == "textureCube") + { + if (!lod0) + { + if (node->getSequence().size() == 2) + { + mUsesTextureCube = true; + } + else if (node->getSequence().size() == 3) + { + mUsesTextureCube_bias = true; + } + else UNREACHABLE(); + + out << "gl_textureCube("; + } + else + { + if (node->getSequence().size() == 2) + { + mUsesTextureCubeLod0 = true; + } + else if (node->getSequence().size() == 3) + { + mUsesTextureCubeLod0_bias = true; + } + else UNREACHABLE(); + + out << "gl_textureCubeLod0("; + } + } + else if (name == "texture2DLod") + { + if (node->getSequence().size() == 3) + { + mUsesTexture2DLod = true; + } + else UNREACHABLE(); + + out << "gl_texture2DLod("; + } + else if (name == "texture2DProjLod") + { + if (node->getSequence().size() == 3) + { + mUsesTexture2DProjLod = true; + } + else UNREACHABLE(); + + out << "gl_texture2DProjLod("; + } + else if (name == "textureCubeLod") + { + if (node->getSequence().size() == 3) + { + mUsesTextureCubeLod = true; + } + else UNREACHABLE(); + + out << "gl_textureCubeLod("; + } + else UNREACHABLE(); } + + TIntermSequence &arguments = node->getSequence(); + + for (TIntermSequence::iterator arg = arguments.begin(); arg != arguments.end(); arg++) + { + if (mOutputType == SH_HLSL11_OUTPUT && IsSampler((*arg)->getAsTyped()->getBasicType())) + { + out << "texture_"; + (*arg)->traverse(this); + out << ", sampler_"; + } + + (*arg)->traverse(this); + + if (arg < arguments.end() - 1) + { + out << ", "; + } + } + + out << ")"; + + return false; } break; case EOpParameters: outputTriplet(visit, "(", ", ", ")\n{\n"); break; @@ -1650,8 +1859,8 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) outputTriplet(visit, "mat4(", ", ", ")"); break; case EOpConstructStruct: - addConstructor(node->getType(), scopedStruct(node->getType().getTypeName()), &node->getSequence()); - outputTriplet(visit, structLookup(node->getType().getTypeName()) + "_ctor(", ", ", ")"); + addConstructor(node->getType(), scopedStruct(node->getType().getStruct()->name()), &node->getSequence()); + outputTriplet(visit, structLookup(node->getType().getStruct()->name()) + "_ctor(", ", ", ")"); break; case EOpLessThan: outputTriplet(visit, "(", " < ", ")"); break; case EOpGreaterThan: outputTriplet(visit, "(", " > ", ")"); break; @@ -1741,7 +1950,7 @@ bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node) out << ")\n"; - outputLineDirective(node->getLine()); + outputLineDirective(node->getLine().first_line); out << "{\n"; if (node->getTrueBlock()) @@ -1749,20 +1958,20 @@ bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node) traverseStatements(node->getTrueBlock()); } - outputLineDirective(node->getLine()); + outputLineDirective(node->getLine().first_line); out << ";\n}\n"; if (node->getFalseBlock()) { out << "else\n"; - outputLineDirective(node->getFalseBlock()->getLine()); + outputLineDirective(node->getFalseBlock()->getLine().first_line); out << "{\n"; - outputLineDirective(node->getFalseBlock()->getLine()); + outputLineDirective(node->getFalseBlock()->getLine().first_line); traverseStatements(node->getFalseBlock()); - outputLineDirective(node->getFalseBlock()->getLine()); + outputLineDirective(node->getFalseBlock()->getLine().first_line); out << ";\n}\n"; } } @@ -1784,9 +1993,12 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node) mInsideDiscontinuousLoop = containsLoopDiscontinuity(node); } - if (handleExcessiveLoop(node)) + if (mOutputType == SH_HLSL9_OUTPUT) { - return false; + if (handleExcessiveLoop(node)) + { + return false; + } } TInfoSinkBase &out = mBody; @@ -1795,7 +2007,7 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node) { out << "{do\n"; - outputLineDirective(node->getLine()); + outputLineDirective(node->getLine().first_line); out << "{\n"; } else @@ -1823,7 +2035,7 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node) out << ")\n"; - outputLineDirective(node->getLine()); + outputLineDirective(node->getLine().first_line); out << "{\n"; } @@ -1832,12 +2044,12 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node) traverseStatements(node->getBody()); } - outputLineDirective(node->getLine()); + outputLineDirective(node->getLine().first_line); out << ";}\n"; if (node->getType() == ELoopDoWhile) { - outputLineDirective(node->getCondition()->getLine()); + outputLineDirective(node->getCondition()->getLine().first_line); out << "while(\n"; node->getCondition()->traverse(this); @@ -2109,7 +2321,7 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node) out << increment; out << ")\n"; - outputLineDirective(node->getLine()); + outputLineDirective(node->getLine().first_line); out << "{\n"; if (node->getBody()) @@ -2117,7 +2329,7 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node) node->getBody()->traverse(this); } - outputLineDirective(node->getLine()); + outputLineDirective(node->getLine().first_line); out << ";}\n"; if (!firstLoopFragment) @@ -2192,6 +2404,12 @@ TString OutputHLSL::argumentString(const TIntermSymbol *symbol) name = decorate(name); } + if (mOutputType == SH_HLSL11_OUTPUT && IsSampler(type.getBasicType())) + { + return qualifierString(qualifier) + " " + textureString(type) + " texture_" + name + arrayString(type) + ", " + + qualifierString(qualifier) + " SamplerState sampler_" + name + arrayString(type); + } + return qualifierString(qualifier) + " " + typeString(type) + " " + name + arrayString(type); } @@ -2213,22 +2431,23 @@ TString OutputHLSL::typeString(const TType &type) { if (type.getBasicType() == EbtStruct) { - if (type.getTypeName() != "") + const TString& typeName = type.getStruct()->name(); + if (typeName != "") { - return structLookup(type.getTypeName()); + return structLookup(typeName); } else // Nameless structure, define in place { - const TTypeList &fields = *type.getStruct(); + const TFieldList &fields = type.getStruct()->fields(); TString string = "struct\n" "{\n"; for (unsigned int i = 0; i < fields.size(); i++) { - const TType &field = *fields[i].type; + const TField *field = fields[i]; - string += " " + typeString(field) + " " + decorate(field.getFieldName()) + arrayString(field) + ";\n"; + string += " " + typeString(*field->type()) + " " + decorate(field->name()) + arrayString(*field->type()) + ";\n"; } string += "} "; @@ -2286,10 +2505,28 @@ TString OutputHLSL::typeString(const TType &type) } } - UNIMPLEMENTED(); // FIXME + UNREACHABLE(); return ""; } +TString OutputHLSL::textureString(const TType &type) +{ + switch (type.getBasicType()) + { + case EbtSampler2D: + return "Texture2D"; + case EbtSamplerCube: + return "TextureCube"; + case EbtSamplerExternalOES: + return "Texture2D"; + default: + break; + } + + UNREACHABLE(); + return ""; +} + TString OutputHLSL::arrayString(const TType &type) { if (!type.isArray()) @@ -2304,11 +2541,12 @@ TString OutputHLSL::initializer(const TType &type) { TString string; - for (int component = 0; component < type.getObjectSize(); component++) + size_t size = type.getObjectSize(); + for (size_t component = 0; component < size; component++) { string += "0"; - if (component < type.getObjectSize() - 1) + if (component + 1 < size) { string += ", "; } @@ -2347,13 +2585,13 @@ void OutputHLSL::addConstructor(const TType &type, const TString &name, const TI structure += "struct " + decorate(name) + "\n" "{\n"; - const TTypeList &fields = *type.getStruct(); + const TFieldList &fields = type.getStruct()->fields(); for (unsigned int i = 0; i < fields.size(); i++) { - const TType &field = *fields[i].type; + const TField *field = fields[i]; - structure += " " + typeString(field) + " " + decorateField(field.getFieldName(), type) + arrayString(field) + ";\n"; + structure += " " + typeString(*field->type()) + " " + decorateField(field->name(), type) + arrayString(*field->type()) + ";\n"; } structure += "};\n"; @@ -2365,7 +2603,7 @@ void OutputHLSL::addConstructor(const TType &type, const TString &name, const TI for (unsigned int i = 0; i < fields.size(); i++) { - ctorParameters.push_back(*fields[i].type); + ctorParameters.push_back(*fields[i]->type()); } } else if (parameters) @@ -2458,27 +2696,30 @@ void OutputHLSL::addConstructor(const TType &type, const TString &name, const TI } else { - int remainingComponents = ctorType.getObjectSize(); - int parameterIndex = 0; + size_t remainingComponents = ctorType.getObjectSize(); + size_t parameterIndex = 0; while (remainingComponents > 0) { const TType ¶meter = ctorParameters[parameterIndex]; - bool moreParameters = parameterIndex < (int)ctorParameters.size() - 1; + const size_t parameterSize = parameter.getObjectSize(); + bool moreParameters = parameterIndex + 1 < ctorParameters.size(); constructor += "x" + str(parameterIndex); if (parameter.isScalar()) { - remainingComponents -= parameter.getObjectSize(); + ASSERT(parameterSize <= remainingComponents); + remainingComponents -= parameterSize; } else if (parameter.isVector()) { - if (remainingComponents == parameter.getObjectSize() || moreParameters) + if (remainingComponents == parameterSize || moreParameters) { - remainingComponents -= parameter.getObjectSize(); + ASSERT(parameterSize <= remainingComponents); + remainingComponents -= parameterSize; } - else if (remainingComponents < parameter.getNominalSize()) + else if (remainingComponents < static_cast(parameter.getNominalSize())) { switch (remainingComponents) { @@ -2495,9 +2736,10 @@ void OutputHLSL::addConstructor(const TType &type, const TString &name, const TI } else if (parameter.isMatrix() || parameter.getStruct()) { - ASSERT(remainingComponents == parameter.getObjectSize() || moreParameters); + ASSERT(remainingComponents == parameterSize || moreParameters); + ASSERT(parameterSize <= remainingComponents); - remainingComponents -= parameter.getObjectSize(); + remainingComponents -= parameterSize; } else UNREACHABLE(); @@ -2534,17 +2776,17 @@ const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const Con if (type.getBasicType() == EbtStruct) { - out << structLookup(type.getTypeName()) + "_ctor("; + out << structLookup(type.getStruct()->name()) + "_ctor("; - const TTypeList *structure = type.getStruct(); + const TFieldList &fields = type.getStruct()->fields(); - for (size_t i = 0; i < structure->size(); i++) + for (size_t i = 0; i < fields.size(); i++) { - const TType *fieldType = (*structure)[i].type; + const TType *fieldType = fields[i]->type(); constUnion = writeConstantUnion(*fieldType, constUnion); - if (i != structure->size() - 1) + if (i != fields.size() - 1) { out << ", "; } @@ -2554,7 +2796,7 @@ const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const Con } else { - int size = type.getObjectSize(); + size_t size = type.getObjectSize(); bool writeType = size > 1; if (writeType) @@ -2562,7 +2804,7 @@ const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const Con out << typeString(type) << "("; } - for (int i = 0; i < size; i++, constUnion++) + for (size_t i = 0; i < size; i++, constUnion++) { switch (constUnion->getType()) { @@ -2641,11 +2883,7 @@ TString OutputHLSL::decorate(const TString &string) TString OutputHLSL::decorateUniform(const TString &string, const TType &type) { - if (type.isArray()) - { - return "ar_" + string; // Allows identifying arrays of size 1 - } - else if (type.getBasicType() == EbtSamplerExternalOES) + if (type.getBasicType() == EbtSamplerExternalOES) { return "ex_" + string; } @@ -2655,11 +2893,202 @@ TString OutputHLSL::decorateUniform(const TString &string, const TType &type) TString OutputHLSL::decorateField(const TString &string, const TType &structure) { - if (structure.getTypeName().compare(0, 3, "gl_") != 0) + if (structure.getStruct()->name().compare(0, 3, "gl_") != 0) { return decorate(string); } return string; } + +TString OutputHLSL::registerString(TIntermSymbol *operand) +{ + ASSERT(operand->getQualifier() == EvqUniform); + + if (IsSampler(operand->getBasicType())) + { + return "s" + str(samplerRegister(operand)); + } + + return "c" + str(uniformRegister(operand)); +} + +int OutputHLSL::samplerRegister(TIntermSymbol *sampler) +{ + const TType &type = sampler->getType(); + ASSERT(IsSampler(type.getBasicType())); + + int index = mSamplerRegister; + mSamplerRegister += sampler->totalRegisterCount(); + + declareUniform(type, sampler->getSymbol(), index); + + return index; +} + +int OutputHLSL::uniformRegister(TIntermSymbol *uniform) +{ + const TType &type = uniform->getType(); + ASSERT(!IsSampler(type.getBasicType())); + + int index = mUniformRegister; + mUniformRegister += uniform->totalRegisterCount(); + + declareUniform(type, uniform->getSymbol(), index); + + return index; +} + +void OutputHLSL::declareUniform(const TType &type, const TString &name, int index) +{ + TStructure *structure = type.getStruct(); + + if (!structure) + { + mActiveUniforms.push_back(Uniform(glVariableType(type), glVariablePrecision(type), name.c_str(), type.getArraySize(), index)); + } + else + { + const TFieldList &fields = structure->fields(); + + if (type.isArray()) + { + int elementIndex = index; + + for (int i = 0; i < type.getArraySize(); i++) + { + for (size_t j = 0; j < fields.size(); j++) + { + const TType &fieldType = *fields[j]->type(); + const TString uniformName = name + "[" + str(i) + "]." + fields[j]->name(); + declareUniform(fieldType, uniformName, elementIndex); + elementIndex += fieldType.totalRegisterCount(); + } + } + } + else + { + int fieldIndex = index; + + for (size_t i = 0; i < fields.size(); i++) + { + const TType &fieldType = *fields[i]->type(); + const TString uniformName = name + "." + fields[i]->name(); + declareUniform(fieldType, uniformName, fieldIndex); + fieldIndex += fieldType.totalRegisterCount(); + } + } + } +} + +GLenum OutputHLSL::glVariableType(const TType &type) +{ + if (type.getBasicType() == EbtFloat) + { + if (type.isScalar()) + { + return GL_FLOAT; + } + else if (type.isVector()) + { + switch(type.getNominalSize()) + { + case 2: return GL_FLOAT_VEC2; + case 3: return GL_FLOAT_VEC3; + case 4: return GL_FLOAT_VEC4; + default: UNREACHABLE(); + } + } + else if (type.isMatrix()) + { + switch(type.getNominalSize()) + { + case 2: return GL_FLOAT_MAT2; + case 3: return GL_FLOAT_MAT3; + case 4: return GL_FLOAT_MAT4; + default: UNREACHABLE(); + } + } + else UNREACHABLE(); + } + else if (type.getBasicType() == EbtInt) + { + if (type.isScalar()) + { + return GL_INT; + } + else if (type.isVector()) + { + switch(type.getNominalSize()) + { + case 2: return GL_INT_VEC2; + case 3: return GL_INT_VEC3; + case 4: return GL_INT_VEC4; + default: UNREACHABLE(); + } + } + else UNREACHABLE(); + } + else if (type.getBasicType() == EbtBool) + { + if (type.isScalar()) + { + return GL_BOOL; + } + else if (type.isVector()) + { + switch(type.getNominalSize()) + { + case 2: return GL_BOOL_VEC2; + case 3: return GL_BOOL_VEC3; + case 4: return GL_BOOL_VEC4; + default: UNREACHABLE(); + } + } + else UNREACHABLE(); + } + else if (type.getBasicType() == EbtSampler2D) + { + return GL_SAMPLER_2D; + } + else if (type.getBasicType() == EbtSamplerCube) + { + return GL_SAMPLER_CUBE; + } + else UNREACHABLE(); + + return GL_NONE; +} + +GLenum OutputHLSL::glVariablePrecision(const TType &type) +{ + if (type.getBasicType() == EbtFloat) + { + switch (type.getPrecision()) + { + case EbpHigh: return GL_HIGH_FLOAT; + case EbpMedium: return GL_MEDIUM_FLOAT; + case EbpLow: return GL_LOW_FLOAT; + case EbpUndefined: + // Should be defined as the default precision by the parser + default: UNREACHABLE(); + } + } + else if (type.getBasicType() == EbtInt) + { + switch (type.getPrecision()) + { + case EbpHigh: return GL_HIGH_INT; + case EbpMedium: return GL_MEDIUM_INT; + case EbpLow: return GL_LOW_INT; + case EbpUndefined: + // Should be defined as the default precision by the parser + default: UNREACHABLE(); + } + } + + // Other types (boolean, sampler) don't have a precision + return GL_NONE; +} + } diff --git a/gfx/angle/src/compiler/OutputHLSL.h b/gfx/angle/src/compiler/OutputHLSL.h index dc843fb36605..c593822b5993 100644 --- a/gfx/angle/src/compiler/OutputHLSL.h +++ b/gfx/angle/src/compiler/OutputHLSL.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -9,9 +9,14 @@ #include #include +#include + +#define GL_APICALL +#include #include "compiler/intermediate.h" #include "compiler/ParseHelper.h" +#include "compiler/CompilerUniform.h" namespace sh { @@ -20,14 +25,16 @@ class UnfoldShortCircuit; class OutputHLSL : public TIntermTraverser { public: - explicit OutputHLSL(TParseContext &context); + OutputHLSL(TParseContext &context, const ShBuiltInResources& resources, ShShaderOutput outputType); ~OutputHLSL(); void output(); TInfoSinkBase &getBodyStream(); + const ActiveUniforms &getUniforms(); TString typeString(const TType &type); + TString textureString(const TType &type); static TString qualifierString(TQualifier qualifier); static TString arrayString(const TType &type); static TString initializer(const TType &type); @@ -64,6 +71,7 @@ class OutputHLSL : public TIntermTraverser TString structLookup(const TString &typeName); TParseContext &mContext; + const ShShaderOutput mOutputType; UnfoldShortCircuit *mUnfoldShortCircuit; bool mInsideFunction; @@ -72,9 +80,10 @@ class OutputHLSL : public TIntermTraverser TInfoSinkBase mBody; TInfoSinkBase mFooter; - std::set mReferencedUniforms; - std::set mReferencedAttributes; - std::set mReferencedVaryings; + typedef std::map ReferencedSymbols; + ReferencedSymbols mReferencedUniforms; + ReferencedSymbols mReferencedAttributes; + ReferencedSymbols mReferencedVaryings; // Parameters determining what goes in the header output bool mUsesTexture2D; @@ -92,11 +101,14 @@ class OutputHLSL : public TIntermTraverser bool mUsesTexture2DProjLod0_bias; bool mUsesTextureCubeLod0; bool mUsesTextureCubeLod0_bias; + bool mUsesFragColor; + bool mUsesFragData; bool mUsesDepthRange; bool mUsesFragCoord; bool mUsesPointCoord; bool mUsesFrontFacing; bool mUsesPointSize; + bool mUsesFragDepth; bool mUsesXor; bool mUsesMod1; bool mUsesMod2v; @@ -109,23 +121,13 @@ class OutputHLSL : public TIntermTraverser bool mUsesFaceforward2; bool mUsesFaceforward3; bool mUsesFaceforward4; - bool mUsesEqualMat2; - bool mUsesEqualMat3; - bool mUsesEqualMat4; - bool mUsesEqualVec2; - bool mUsesEqualVec3; - bool mUsesEqualVec4; - bool mUsesEqualIVec2; - bool mUsesEqualIVec3; - bool mUsesEqualIVec4; - bool mUsesEqualBVec2; - bool mUsesEqualBVec3; - bool mUsesEqualBVec4; bool mUsesAtan2_1; bool mUsesAtan2_2; bool mUsesAtan2_3; bool mUsesAtan2_4; + int mNumRenderTargets; + typedef std::set Constructors; Constructors mConstructors; @@ -146,6 +148,18 @@ class OutputHLSL : public TIntermTraverser bool mInsideDiscontinuousLoop; TIntermSymbol *mExcessiveLoopIndex; + + int mUniformRegister; + int mSamplerRegister; + + TString registerString(TIntermSymbol *operand); + int samplerRegister(TIntermSymbol *sampler); + int uniformRegister(TIntermSymbol *uniform); + void declareUniform(const TType &type, const TString &name, int index); + static GLenum glVariableType(const TType &type); + static GLenum glVariablePrecision(const TType &type); + + ActiveUniforms mActiveUniforms; }; } diff --git a/gfx/angle/src/compiler/ParseHelper.cpp b/gfx/angle/src/compiler/ParseHelper.cpp index 441ff35e006f..a4787a1cb59b 100644 --- a/gfx/angle/src/compiler/ParseHelper.cpp +++ b/gfx/angle/src/compiler/ParseHelper.cpp @@ -22,7 +22,7 @@ // Look at a '.' field selector string and change it into offsets // for a vector. // -bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TVectorFields& fields, int line) +bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TVectorFields& fields, const TSourceLoc& line) { fields.num = (int) compString.size(); if (fields.num > 4) { @@ -115,7 +115,7 @@ bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TV // Look at a '.' field selector string and change it into offsets // for a matrix. // -bool TParseContext::parseMatrixFields(const TString& compString, int matSize, TMatrixFields& fields, int line) +bool TParseContext::parseMatrixFields(const TString& compString, int matSize, TMatrixFields& fields, const TSourceLoc& line) { fields.wholeRow = false; fields.wholeCol = false; @@ -175,22 +175,24 @@ void TParseContext::recover() // // Used by flex/bison to output all syntax and parsing errors. // -void TParseContext::error(TSourceLoc loc, +void TParseContext::error(const TSourceLoc& loc, const char* reason, const char* token, const char* extraInfo) { pp::SourceLocation srcLoc; - DecodeSourceLoc(loc, &srcLoc.file, &srcLoc.line); + srcLoc.file = loc.first_file; + srcLoc.line = loc.first_line; diagnostics.writeInfo(pp::Diagnostics::ERROR, srcLoc, reason, token, extraInfo); } -void TParseContext::warning(TSourceLoc loc, +void TParseContext::warning(const TSourceLoc& loc, const char* reason, const char* token, const char* extraInfo) { pp::SourceLocation srcLoc; - DecodeSourceLoc(loc, &srcLoc.file, &srcLoc.line); + srcLoc.file = loc.first_file; + srcLoc.line = loc.first_line; diagnostics.writeInfo(pp::Diagnostics::WARNING, srcLoc, reason, token, extraInfo); } @@ -203,7 +205,7 @@ void TParseContext::trace(const char* str) // // Same error message for all places assignments don't work. // -void TParseContext::assignError(int line, const char* op, TString left, TString right) +void TParseContext::assignError(const TSourceLoc& line, const char* op, TString left, TString right) { std::stringstream extraInfoStream; extraInfoStream << "cannot convert from '" << right << "' to '" << left << "'"; @@ -214,7 +216,7 @@ void TParseContext::assignError(int line, const char* op, TString left, TString // // Same error message for all places unary operations don't work. // -void TParseContext::unaryOpError(int line, const char* op, TString operand) +void TParseContext::unaryOpError(const TSourceLoc& line, const char* op, TString operand) { std::stringstream extraInfoStream; extraInfoStream << "no operation '" << op << "' exists that takes an operand of type " << operand @@ -226,7 +228,7 @@ void TParseContext::unaryOpError(int line, const char* op, TString operand) // // Same error message for all binary operations don't work. // -void TParseContext::binaryOpError(int line, const char* op, TString left, TString right) +void TParseContext::binaryOpError(const TSourceLoc& line, const char* op, TString left, TString right) { std::stringstream extraInfoStream; extraInfoStream << "no operation '" << op << "' exists that takes a left-hand operand of type '" << left @@ -235,7 +237,7 @@ void TParseContext::binaryOpError(int line, const char* op, TString left, TStrin error(line, " wrong operand types ", op, extraInfo.c_str()); } -bool TParseContext::precisionErrorCheck(int line, TPrecision precision, TBasicType type){ +bool TParseContext::precisionErrorCheck(const TSourceLoc& line, TPrecision precision, TBasicType type){ if (!checksPrecisionErrors) return false; switch( type ){ @@ -263,7 +265,7 @@ bool TParseContext::precisionErrorCheck(int line, TPrecision precision, TBasicTy // // Returns true if the was an error. // -bool TParseContext::lValueErrorCheck(int line, const char* op, TIntermTyped* node) +bool TParseContext::lValueErrorCheck(const TSourceLoc& line, const char* op, TIntermTyped* node) { TIntermSymbol* symNode = node->getAsSymbolNode(); TIntermBinary* binaryNode = node->getAsBinaryNode(); @@ -317,7 +319,6 @@ bool TParseContext::lValueErrorCheck(int line, const char* op, TIntermTyped* nod case EvqAttribute: message = "can't modify an attribute"; break; case EvqUniform: message = "can't modify a uniform"; break; case EvqVaryingIn: message = "can't modify a varying"; break; - case EvqInput: message = "can't modify an input"; break; case EvqFragCoord: message = "can't modify gl_FragCoord"; break; case EvqFrontFacing: message = "can't modify gl_FrontFacing"; break; case EvqPointCoord: message = "can't modify gl_PointCoord"; break; @@ -409,7 +410,7 @@ bool TParseContext::integerErrorCheck(TIntermTyped* node, const char* token) // // Returns true if the was an error. // -bool TParseContext::globalErrorCheck(int line, bool global, const char* token) +bool TParseContext::globalErrorCheck(const TSourceLoc& line, bool global, const char* token) { if (global) return false; @@ -428,7 +429,7 @@ bool TParseContext::globalErrorCheck(int line, bool global, const char* token) // // Returns true if there was an error. // -bool TParseContext::reservedErrorCheck(int line, const TString& identifier) +bool TParseContext::reservedErrorCheck(const TSourceLoc& line, const TString& identifier) { static const char* reservedErrMsg = "reserved built-in name"; if (!symbolTable.atBuiltInLevel()) { @@ -466,7 +467,7 @@ bool TParseContext::reservedErrorCheck(int line, const TString& identifier) // // Returns true if there was an error in construction. // -bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction& function, TOperator op, TType* type) +bool TParseContext::constructorErrorCheck(const TSourceLoc& line, TIntermNode* node, TFunction& function, TOperator op, TType* type) { *type = function.getReturnType(); @@ -487,7 +488,7 @@ bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction // again, there is an extra argument, so 'overfull' will become true. // - int size = 0; + size_t size = 0; bool constType = true; bool full = false; bool overFull = false; @@ -534,7 +535,7 @@ bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction return true; } - if (op == EOpConstructStruct && !type->isArray() && int(type->getStruct()->size()) != function.getParamCount()) { + if (op == EOpConstructStruct && !type->isArray() && int(type->getStruct()->fields().size()) != function.getParamCount()) { error(line, "Number of constructor parameters does not match the number of structure fields", "constructor"); return true; } @@ -568,7 +569,7 @@ bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction // // returns true in case of an error // -bool TParseContext::voidErrorCheck(int line, const TString& identifier, const TPublicType& pubType) +bool TParseContext::voidErrorCheck(const TSourceLoc& line, const TString& identifier, const TPublicType& pubType) { if (pubType.type == EbtVoid) { error(line, "illegal use of type 'void'", identifier.c_str()); @@ -582,7 +583,7 @@ bool TParseContext::voidErrorCheck(int line, const TString& identifier, const TP // // returns true in case of an error // -bool TParseContext::boolErrorCheck(int line, const TIntermTyped* type) +bool TParseContext::boolErrorCheck(const TSourceLoc& line, const TIntermTyped* type) { if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector()) { error(line, "boolean expression expected", ""); @@ -596,7 +597,7 @@ bool TParseContext::boolErrorCheck(int line, const TIntermTyped* type) // // returns true in case of an error // -bool TParseContext::boolErrorCheck(int line, const TPublicType& pType) +bool TParseContext::boolErrorCheck(const TSourceLoc& line, const TPublicType& pType) { if (pType.type != EbtBool || pType.array || pType.matrix || (pType.size > 1)) { error(line, "boolean expression expected", ""); @@ -606,7 +607,7 @@ bool TParseContext::boolErrorCheck(int line, const TPublicType& pType) return false; } -bool TParseContext::samplerErrorCheck(int line, const TPublicType& pType, const char* reason) +bool TParseContext::samplerErrorCheck(const TSourceLoc& line, const TPublicType& pType, const char* reason) { if (pType.type == EbtStruct) { if (containsSampler(*pType.userDef)) { @@ -625,7 +626,7 @@ bool TParseContext::samplerErrorCheck(int line, const TPublicType& pType, const return false; } -bool TParseContext::structQualifierErrorCheck(int line, const TPublicType& pType) +bool TParseContext::structQualifierErrorCheck(const TSourceLoc& line, const TPublicType& pType) { if ((pType.qualifier == EvqVaryingIn || pType.qualifier == EvqVaryingOut || pType.qualifier == EvqAttribute) && pType.type == EbtStruct) { @@ -640,7 +641,7 @@ bool TParseContext::structQualifierErrorCheck(int line, const TPublicType& pType return false; } -bool TParseContext::parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type) +bool TParseContext::parameterSamplerErrorCheck(const TSourceLoc& line, TQualifier qualifier, const TType& type) { if ((qualifier == EvqOut || qualifier == EvqInOut) && type.getBasicType() != EbtStruct && IsSampler(type.getBasicType())) { @@ -657,9 +658,9 @@ bool TParseContext::containsSampler(TType& type) return true; if (type.getBasicType() == EbtStruct) { - TTypeList& structure = *type.getStruct(); - for (unsigned int i = 0; i < structure.size(); ++i) { - if (containsSampler(*structure[i].type)) + const TFieldList& fields = type.getStruct()->fields(); + for (unsigned int i = 0; i < fields.size(); ++i) { + if (containsSampler(*fields[i]->type())) return true; } } @@ -672,7 +673,7 @@ bool TParseContext::containsSampler(TType& type) // // Returns true if there was an error. // -bool TParseContext::arraySizeErrorCheck(int line, TIntermTyped* expr, int& size) +bool TParseContext::arraySizeErrorCheck(const TSourceLoc& line, TIntermTyped* expr, int& size) { TIntermConstantUnion* constant = expr->getAsConstantUnion(); if (constant == 0 || constant->getBasicType() != EbtInt) { @@ -696,7 +697,7 @@ bool TParseContext::arraySizeErrorCheck(int line, TIntermTyped* expr, int& size) // // Returns true if there is an error. // -bool TParseContext::arrayQualifierErrorCheck(int line, TPublicType type) +bool TParseContext::arrayQualifierErrorCheck(const TSourceLoc& line, TPublicType type) { if ((type.qualifier == EvqAttribute) || (type.qualifier == EvqConst)) { error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str()); @@ -711,7 +712,7 @@ bool TParseContext::arrayQualifierErrorCheck(int line, TPublicType type) // // Returns true if there is an error. // -bool TParseContext::arrayTypeErrorCheck(int line, TPublicType type) +bool TParseContext::arrayTypeErrorCheck(const TSourceLoc& line, TPublicType type) { // // Can the type be an array? @@ -732,7 +733,7 @@ bool TParseContext::arrayTypeErrorCheck(int line, TPublicType type) // // Returns true if there was an error. // -bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType type, TVariable*& variable) +bool TParseContext::arrayErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType type, TVariable*& variable) { // // Don't check for reserved word use until after we know it's not in the symbol table, @@ -777,16 +778,6 @@ bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType t return true; } - TType* t = variable->getArrayInformationType(); - while (t != 0) { - if (t->getMaxArraySize() > type.arraySize) { - error(line, "higher index value already used for the array", identifier.c_str()); - return true; - } - t->setArraySize(type.arraySize); - t = t->getArrayInformationType(); - } - if (type.arraySize) variable->getType().setArraySize(type.arraySize); } @@ -797,56 +788,12 @@ bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType t return false; } -bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size, bool updateFlag, TSourceLoc line) -{ - bool builtIn = false; - TSymbol* symbol = symbolTable.find(node->getSymbol(), &builtIn); - if (symbol == 0) { - error(line, " undeclared identifier", node->getSymbol().c_str()); - return true; - } - TVariable* variable = static_cast(symbol); - - type->setArrayInformationType(variable->getArrayInformationType()); - variable->updateArrayInformationType(type); - - // special casing to test index value of gl_FragData. If the accessed index is >= gl_MaxDrawBuffers - // its an error - if (node->getSymbol() == "gl_FragData") { - TSymbol* fragData = symbolTable.find("gl_MaxDrawBuffers", &builtIn); - ASSERT(fragData); - - int fragDataValue = static_cast(fragData)->getConstPointer()[0].getIConst(); - if (fragDataValue <= size) { - error(line, "", "[", "gl_FragData can only have a max array size of up to gl_MaxDrawBuffers"); - return true; - } - } - - // we dont want to update the maxArraySize when this flag is not set, we just want to include this - // node type in the chain of node types so that its updated when a higher maxArraySize comes in. - if (!updateFlag) - return false; - - size++; - variable->getType().setMaxArraySize(size); - type->setMaxArraySize(size); - TType* tt = type; - - while(tt->getArrayInformationType() != 0) { - tt = tt->getArrayInformationType(); - tt->setMaxArraySize(size); - } - - return false; -} - // // Enforce non-initializer type/qualifier rules. // // Returns true if there was an error. // -bool TParseContext::nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type, bool array) +bool TParseContext::nonInitConstErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, bool array) { if (type.qualifier == EvqConst) { @@ -878,7 +825,7 @@ bool TParseContext::nonInitConstErrorCheck(int line, TString& identifier, TPubli // // Returns true if there was an error. // -bool TParseContext::nonInitErrorCheck(int line, TString& identifier, TPublicType& type, TVariable*& variable) +bool TParseContext::nonInitErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, TVariable*& variable) { if (reservedErrorCheck(line, identifier)) recover(); @@ -898,7 +845,7 @@ bool TParseContext::nonInitErrorCheck(int line, TString& identifier, TPublicType return false; } -bool TParseContext::paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type) +bool TParseContext::paramErrorCheck(const TSourceLoc& line, TQualifier qualifier, TQualifier paramQualifier, TType* type) { if (qualifier != EvqConst && qualifier != EvqTemporary) { error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier)); @@ -917,7 +864,7 @@ bool TParseContext::paramErrorCheck(int line, TQualifier qualifier, TQualifier p return false; } -bool TParseContext::extensionErrorCheck(int line, const TString& extension) +bool TParseContext::extensionErrorCheck(const TSourceLoc& line, const TString& extension) { const TExtensionBehavior& extBehavior = extensionBehavior(); TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str()); @@ -945,18 +892,17 @@ bool TParseContext::supportsExtension(const char* extension) return (iter != extbehavior.end()); } -void TParseContext::handleExtensionDirective(int line, const char* extName, const char* behavior) +bool TParseContext::isExtensionEnabled(const char* extension) const { - pp::SourceLocation loc; - DecodeSourceLoc(line, &loc.file, &loc.line); - directiveHandler.handleExtension(loc, extName, behavior); -} + const TExtensionBehavior& extbehavior = extensionBehavior(); + TExtensionBehavior::const_iterator iter = extbehavior.find(extension); -void TParseContext::handlePragmaDirective(int line, const char* name, const char* value) -{ - pp::SourceLocation loc; - DecodeSourceLoc(line, &loc.file, &loc.line); - directiveHandler.handlePragma(loc, name, value); + if (iter == extbehavior.end()) + { + return false; + } + + return (iter->second == EBhEnable || iter->second == EBhRequire); } ///////////////////////////////////////////////////////////////////////////////// @@ -970,12 +916,13 @@ void TParseContext::handlePragmaDirective(int line, const char* name, const char // // Return the function symbol if found, otherwise 0. // -const TFunction* TParseContext::findFunction(int line, TFunction* call, bool *builtIn) +const TFunction* TParseContext::findFunction(const TSourceLoc& line, TFunction* call, bool *builtIn) { // First find by unmangled name to check whether the function name has been // hidden by a variable name or struct typename. + // If a function is found, check for one with a matching argument list. const TSymbol* symbol = symbolTable.find(call->getName(), builtIn); - if (symbol == 0) { + if (symbol == 0 || symbol->isFunction()) { symbol = symbolTable.find(call->getMangledName(), builtIn); } @@ -996,7 +943,7 @@ const TFunction* TParseContext::findFunction(int line, TFunction* call, bool *bu // Initializers show up in several places in the grammar. Have one set of // code to handle them here. // -bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType, +bool TParseContext::executeInitializer(const TSourceLoc& line, TString& identifier, TPublicType& pType, TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable) { TType type = TType(pType); @@ -1048,13 +995,7 @@ bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPu return true; } if (initializer->getAsConstantUnion()) { - ConstantUnion* unionArray = variable->getConstPointer(); - - if (type.getObjectSize() == 1 && type.getBasicType() != EbtStruct) { - *unionArray = (initializer->getAsConstantUnion()->getUnionArrayPointer())[0]; - } else { - variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer()); - } + variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer()); } else if (initializer->getAsSymbolNode()) { const TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getSymbol()); const TVariable* tVar = static_cast(symbol); @@ -1108,16 +1049,16 @@ bool TParseContext::areAllChildConst(TIntermAggregate* aggrNode) // // Returns 0 for an error or the constructed node (aggregate or typed) for no error. // -TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type, TOperator op, TFunction* fnCall, TSourceLoc line) +TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type, TOperator op, TFunction* fnCall, const TSourceLoc& line) { if (node == 0) return 0; TIntermAggregate* aggrNode = node->getAsAggregate(); - TTypeList::const_iterator memberTypes; + TFieldList::const_iterator memberFields; if (op == EOpConstructStruct) - memberTypes = type->getStruct()->begin(); + memberFields = type->getStruct()->fields().begin(); TType elementType = *type; if (type->isArray()) @@ -1139,7 +1080,7 @@ TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type if (type->isArray()) newNode = constructStruct(node, &elementType, 1, node->getLine(), false); else if (op == EOpConstructStruct) - newNode = constructStruct(node, (*memberTypes).type, 1, node->getLine(), false); + newNode = constructStruct(node, (*memberFields)->type(), 1, node->getLine(), false); else newNode = constructBuiltIn(type, op, node, node->getLine(), false); @@ -1170,7 +1111,7 @@ TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type if (type->isArray()) newNode = constructStruct(*p, &elementType, paramCount+1, node->getLine(), true); else if (op == EOpConstructStruct) - newNode = constructStruct(*p, (memberTypes[paramCount]).type, paramCount+1, node->getLine(), true); + newNode = constructStruct(*p, memberFields[paramCount]->type(), paramCount+1, node->getLine(), true); else newNode = constructBuiltIn(type, op, *p, node->getLine(), true); @@ -1216,7 +1157,7 @@ TIntermTyped* TParseContext::foldConstConstructor(TIntermAggregate* aggrNode, co // // Returns 0 for an error or the constructed node. // -TIntermTyped* TParseContext::constructBuiltIn(const TType* type, TOperator op, TIntermNode* node, TSourceLoc line, bool subset) +TIntermTyped* TParseContext::constructBuiltIn(const TType* type, TOperator op, TIntermNode* node, const TSourceLoc& line, bool subset) { TIntermTyped* newNode; TOperator basicOp; @@ -1278,7 +1219,7 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType* type, TOperator op, T // // Returns 0 for an error or the input node itself if the expected and the given parameter types match. // -TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int paramCount, TSourceLoc line, bool subset) +TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int paramCount, const TSourceLoc& line, bool subset) { if (*type == node->getAsTyped()->getType()) { if (subset) @@ -1305,7 +1246,7 @@ TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int // node or it could be the intermediate tree representation of accessing fields in a constant structure or column of // a constant matrix. // -TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, TSourceLoc line) +TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, const TSourceLoc& line) { TIntermTyped* typedNode; TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); @@ -1327,7 +1268,7 @@ TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTy ConstantUnion* constArray = new ConstantUnion[fields.num]; for (int i = 0; i < fields.num; i++) { - if (fields.offsets[i] >= node->getType().getObjectSize()) { + if (fields.offsets[i] >= node->getType().getNominalSize()) { std::stringstream extraInfoStream; extraInfoStream << "vector field selection out of range '" << fields.offsets[i] << "'"; std::string extraInfo = extraInfoStream.str(); @@ -1349,7 +1290,7 @@ TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTy // to the function could either be a symbol node (m[0] where m is a constant matrix)that represents a // constant matrix or it could be the tree representation of the constant matrix (s.m1[0] where s is a constant structure) // -TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, TSourceLoc line) +TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, const TSourceLoc& line) { TIntermTyped* typedNode; TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); @@ -1384,7 +1325,7 @@ TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, T // to the function could either be a symbol node (a[0] where a is a constant array)that represents a // constant array or it could be the tree representation of the constant array (s.a1[0] where s is a constant structure) // -TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TSourceLoc line) +TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, const TSourceLoc& line) { TIntermTyped* typedNode; TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); @@ -1400,9 +1341,8 @@ TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TS index = 0; } - int arrayElementSize = arrayElementType.getObjectSize(); - if (tempConstantNode) { + size_t arrayElementSize = arrayElementType.getObjectSize(); ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer(); typedNode = intermediate.addConstantUnion(&unionArray[arrayElementSize * index], tempConstantNode->getType(), line); } else { @@ -1421,22 +1361,21 @@ TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TS // If there is an embedded/nested struct, it appropriately calls addConstStructNested or addConstStructFromAggr // function and returns the parse-tree with the values of the embedded/nested struct. // -TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* node, TSourceLoc line) +TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* node, const TSourceLoc& line) { - const TTypeList* fields = node->getType().getStruct(); - TIntermTyped *typedNode; - int instanceSize = 0; - unsigned int index = 0; - TIntermConstantUnion *tempConstantNode = node->getAsConstantUnion(); + const TFieldList& fields = node->getType().getStruct()->fields(); - for ( index = 0; index < fields->size(); ++index) { - if ((*fields)[index].type->getFieldName() == identifier) { + size_t instanceSize = 0; + for (size_t index = 0; index < fields.size(); ++index) { + if (fields[index]->name() == identifier) { break; } else { - instanceSize += (*fields)[index].type->getObjectSize(); + instanceSize += fields[index]->type()->getObjectSize(); } } + TIntermTyped* typedNode = 0; + TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); if (tempConstantNode) { ConstantUnion* constArray = tempConstantNode->getUnionArrayPointer(); @@ -1451,7 +1390,7 @@ TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* n return typedNode; } -bool TParseContext::enterStructDeclaration(int line, const TString& identifier) +bool TParseContext::enterStructDeclaration(const TSourceLoc& line, const TString& identifier) { ++structNestingLevel; @@ -1477,21 +1416,21 @@ const int kWebGLMaxStructNesting = 4; } // namespace -bool TParseContext::structNestingErrorCheck(TSourceLoc line, const TType& fieldType) +bool TParseContext::structNestingErrorCheck(const TSourceLoc& line, const TField& field) { if (!isWebGLBasedSpec(shaderSpec)) { return false; } - if (fieldType.getBasicType() != EbtStruct) { + if (field.type()->getBasicType() != EbtStruct) { return false; } // We're already inside a structure definition at this point, so add // one to the field's struct nesting. - if (1 + fieldType.getDeepestStructNesting() > kWebGLMaxStructNesting) { + if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting) { std::stringstream extraInfoStream; - extraInfoStream << "Reference of struct type " << fieldType.getTypeName() + extraInfoStream << "Reference of struct type " << field.name() << " exceeds maximum struct nesting of " << kWebGLMaxStructNesting; std::string extraInfo = extraInfoStream.str(); error(line, "", "", extraInfo.c_str()); @@ -1501,6 +1440,140 @@ bool TParseContext::structNestingErrorCheck(TSourceLoc line, const TType& fieldT return false; } +// +// Parse an array index expression +// +TIntermTyped* TParseContext::addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc& location, TIntermTyped *indexExpression) +{ + TIntermTyped *indexedExpression = NULL; + + if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector()) + { + if (baseExpression->getAsSymbolNode()) + { + error(location, " left of '[' is not of type array, matrix, or vector ", baseExpression->getAsSymbolNode()->getSymbol().c_str()); + } + else + { + error(location, " left of '[' is not of type array, matrix, or vector ", "expression"); + } + recover(); + } + + if (indexExpression->getQualifier() == EvqConst) + { + int index = indexExpression->getAsConstantUnion()->getIConst(0); + if (index < 0) + { + std::stringstream infoStream; + infoStream << index; + std::string info = infoStream.str(); + error(location, "negative index", info.c_str()); + recover(); + index = 0; + } + if (baseExpression->getType().getQualifier() == EvqConst) + { + if (baseExpression->isArray()) + { + // constant folding for arrays + indexedExpression = addConstArrayNode(index, baseExpression, location); + } + else if (baseExpression->isVector()) + { + // constant folding for vectors + TVectorFields fields; + fields.num = 1; + fields.offsets[0] = index; // need to do it this way because v.xy sends fields integer array + indexedExpression = addConstVectorNode(fields, baseExpression, location); + } + else if (baseExpression->isMatrix()) + { + // constant folding for matrices + indexedExpression = addConstMatrixNode(index, baseExpression, location); + } + } + else + { + if (baseExpression->isArray()) + { + if (index >= baseExpression->getType().getArraySize()) + { + std::stringstream extraInfoStream; + extraInfoStream << "array index out of range '" << index << "'"; + std::string extraInfo = extraInfoStream.str(); + error(location, "", "[", extraInfo.c_str()); + recover(); + index = baseExpression->getType().getArraySize() - 1; + } + else if (baseExpression->getQualifier() == EvqFragData && index > 0 && !isExtensionEnabled("GL_EXT_draw_buffers")) + { + error(location, "", "[", "array indexes for gl_FragData must be zero when GL_EXT_draw_buffers is disabled"); + recover(); + index = 0; + } + } + else if ((baseExpression->isVector() || baseExpression->isMatrix()) && baseExpression->getType().getNominalSize() <= index) + { + std::stringstream extraInfoStream; + extraInfoStream << "field selection out of range '" << index << "'"; + std::string extraInfo = extraInfoStream.str(); + error(location, "", "[", extraInfo.c_str()); + recover(); + index = baseExpression->getType().getNominalSize() - 1; + } + + indexExpression->getAsConstantUnion()->getUnionArrayPointer()->setIConst(index); + indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location); + } + } + else + { + indexedExpression = intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location); + } + + if (indexedExpression == 0) + { + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setFConst(0.0f); + indexedExpression = intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), location); + } + else if (baseExpression->isArray()) + { + const TType &baseType = baseExpression->getType(); + if (baseType.getStruct()) + { + TType copyOfType(baseType.getStruct()); + indexedExpression->setType(copyOfType); + } + else + { + indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqTemporary, baseExpression->getNominalSize(), baseExpression->isMatrix())); + } + + if (baseExpression->getType().getQualifier() == EvqConst) + { + indexedExpression->getTypePointer()->setQualifier(EvqConst); + } + } + else if (baseExpression->isMatrix()) + { + TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary; + indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier, baseExpression->getNominalSize())); + } + else if (baseExpression->isVector()) + { + TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary; + indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier)); + } + else + { + indexedExpression->setType(baseExpression->getType()); + } + + return indexedExpression; +} + // // Parse an array of strings using yyparse. // diff --git a/gfx/angle/src/compiler/ParseHelper.h b/gfx/angle/src/compiler/ParseHelper.h index 26a3ea130802..c2b3c3f7ec89 100644 --- a/gfx/angle/src/compiler/ParseHelper.h +++ b/gfx/angle/src/compiler/ParseHelper.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -33,10 +33,8 @@ struct TParseContext { compileOptions(options), sourcePath(sourcePath), treeRoot(0), - lexAfterType(false), loopNestingLevel(0), structNestingLevel(0), - inTypeParen(false), currentFunctionType(NULL), functionReturnsValue(false), checksPrecisionErrors(checksPrecErrors), @@ -51,16 +49,13 @@ struct TParseContext { int compileOptions; const char* sourcePath; // Path of source file or NULL. TIntermNode* treeRoot; // root of parse tree being created - bool lexAfterType; // true if we've recognized a type, so can only be looking for an identifier int loopNestingLevel; // 0 if outside all loops int structNestingLevel; // incremented while parsing a struct declaration - bool inTypeParen; // true if in parentheses, looking only for an identifier const TType* currentFunctionType; // the return type of the function that's currently being parsed bool functionReturnsValue; // true if a non-void function has a return bool checksPrecisionErrors; // true if an error will be generated when a variable is declared without precision, explicit or implicit. bool fragmentPrecisionHigh; // true if highp precision is supported in the fragment language. TString HashErrMsg; - bool AfterEOF; TDiagnostics diagnostics; TDirectiveHandler directiveHandler; pp::Preprocessor preprocessor; @@ -68,71 +63,69 @@ struct TParseContext { int numErrors() const { return diagnostics.numErrors(); } TInfoSink& infoSink() { return diagnostics.infoSink(); } - void error(TSourceLoc loc, const char *reason, const char* token, + void error(const TSourceLoc& loc, const char *reason, const char* token, const char* extraInfo=""); - void warning(TSourceLoc loc, const char* reason, const char* token, + void warning(const TSourceLoc& loc, const char* reason, const char* token, const char* extraInfo=""); void trace(const char* str); void recover(); - bool parseVectorFields(const TString&, int vecSize, TVectorFields&, int line); - bool parseMatrixFields(const TString&, int matSize, TMatrixFields&, int line); + bool parseVectorFields(const TString&, int vecSize, TVectorFields&, const TSourceLoc& line); + bool parseMatrixFields(const TString&, int matSize, TMatrixFields&, const TSourceLoc& line); - bool reservedErrorCheck(int line, const TString& identifier); - void assignError(int line, const char* op, TString left, TString right); - void unaryOpError(int line, const char* op, TString operand); - void binaryOpError(int line, const char* op, TString left, TString right); - bool precisionErrorCheck(int line, TPrecision precision, TBasicType type); - bool lValueErrorCheck(int line, const char* op, TIntermTyped*); + bool reservedErrorCheck(const TSourceLoc& line, const TString& identifier); + void assignError(const TSourceLoc& line, const char* op, TString left, TString right); + void unaryOpError(const TSourceLoc& line, const char* op, TString operand); + void binaryOpError(const TSourceLoc& line, const char* op, TString left, TString right); + bool precisionErrorCheck(const TSourceLoc& line, TPrecision precision, TBasicType type); + bool lValueErrorCheck(const TSourceLoc& line, const char* op, TIntermTyped*); bool constErrorCheck(TIntermTyped* node); bool integerErrorCheck(TIntermTyped* node, const char* token); - bool globalErrorCheck(int line, bool global, const char* token); - bool constructorErrorCheck(int line, TIntermNode*, TFunction&, TOperator, TType*); - bool arraySizeErrorCheck(int line, TIntermTyped* expr, int& size); - bool arrayQualifierErrorCheck(int line, TPublicType type); - bool arrayTypeErrorCheck(int line, TPublicType type); - bool arrayErrorCheck(int line, TString& identifier, TPublicType type, TVariable*& variable); - bool voidErrorCheck(int, const TString&, const TPublicType&); - bool boolErrorCheck(int, const TIntermTyped*); - bool boolErrorCheck(int, const TPublicType&); - bool samplerErrorCheck(int line, const TPublicType& pType, const char* reason); - bool structQualifierErrorCheck(int line, const TPublicType& pType); - bool parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type); - bool nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type, bool array); - bool nonInitErrorCheck(int line, TString& identifier, TPublicType& type, TVariable*& variable); - bool paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type); - bool extensionErrorCheck(int line, const TString&); - - const TExtensionBehavior& extensionBehavior() const { return directiveHandler.extensionBehavior(); } - bool supportsExtension(const char* extension); - void handleExtensionDirective(int line, const char* extName, const char* behavior); + bool globalErrorCheck(const TSourceLoc& line, bool global, const char* token); + bool constructorErrorCheck(const TSourceLoc& line, TIntermNode*, TFunction&, TOperator, TType*); + bool arraySizeErrorCheck(const TSourceLoc& line, TIntermTyped* expr, int& size); + bool arrayQualifierErrorCheck(const TSourceLoc& line, TPublicType type); + bool arrayTypeErrorCheck(const TSourceLoc& line, TPublicType type); + bool arrayErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType type, TVariable*& variable); + bool voidErrorCheck(const TSourceLoc&, const TString&, const TPublicType&); + bool boolErrorCheck(const TSourceLoc&, const TIntermTyped*); + bool boolErrorCheck(const TSourceLoc&, const TPublicType&); + bool samplerErrorCheck(const TSourceLoc& line, const TPublicType& pType, const char* reason); + bool structQualifierErrorCheck(const TSourceLoc& line, const TPublicType& pType); + bool parameterSamplerErrorCheck(const TSourceLoc& line, TQualifier qualifier, const TType& type); + bool nonInitConstErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, bool array); + bool nonInitErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, TVariable*& variable); + bool paramErrorCheck(const TSourceLoc& line, TQualifier qualifier, TQualifier paramQualifier, TType* type); + bool extensionErrorCheck(const TSourceLoc& line, const TString&); const TPragma& pragma() const { return directiveHandler.pragma(); } - void handlePragmaDirective(int line, const char* name, const char* value); + const TExtensionBehavior& extensionBehavior() const { return directiveHandler.extensionBehavior(); } + bool supportsExtension(const char* extension); + bool isExtensionEnabled(const char* extension) const; bool containsSampler(TType& type); bool areAllChildConst(TIntermAggregate* aggrNode); - const TFunction* findFunction(int line, TFunction* pfnCall, bool *builtIn = 0); - bool executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType, + const TFunction* findFunction(const TSourceLoc& line, TFunction* pfnCall, bool *builtIn = 0); + bool executeInitializer(const TSourceLoc& line, TString& identifier, TPublicType& pType, TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable = 0); - bool arraySetMaxSize(TIntermSymbol*, TType*, int, bool, TSourceLoc); - TIntermTyped* addConstructor(TIntermNode*, const TType*, TOperator, TFunction*, TSourceLoc); + TIntermTyped* addConstructor(TIntermNode*, const TType*, TOperator, TFunction*, const TSourceLoc&); TIntermTyped* foldConstConstructor(TIntermAggregate* aggrNode, const TType& type); - TIntermTyped* constructStruct(TIntermNode*, TType*, int, TSourceLoc, bool subset); - TIntermTyped* constructBuiltIn(const TType*, TOperator, TIntermNode*, TSourceLoc, bool subset); - TIntermTyped* addConstVectorNode(TVectorFields&, TIntermTyped*, TSourceLoc); - TIntermTyped* addConstMatrixNode(int , TIntermTyped*, TSourceLoc); - TIntermTyped* addConstArrayNode(int index, TIntermTyped* node, TSourceLoc line); - TIntermTyped* addConstStruct(TString& , TIntermTyped*, TSourceLoc); + TIntermTyped* constructStruct(TIntermNode*, TType*, int, const TSourceLoc&, bool subset); + TIntermTyped* constructBuiltIn(const TType*, TOperator, TIntermNode*, const TSourceLoc&, bool subset); + TIntermTyped* addConstVectorNode(TVectorFields&, TIntermTyped*, const TSourceLoc&); + TIntermTyped* addConstMatrixNode(int , TIntermTyped*, const TSourceLoc&); + TIntermTyped* addConstArrayNode(int index, TIntermTyped* node, const TSourceLoc& line); + TIntermTyped* addConstStruct(TString& , TIntermTyped*, const TSourceLoc&); + TIntermTyped* addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc& location, TIntermTyped *indexExpression); // Performs an error check for embedded struct declarations. // Returns true if an error was raised due to the declaration of // this struct. - bool enterStructDeclaration(TSourceLoc line, const TString& identifier); + bool enterStructDeclaration(const TSourceLoc& line, const TString& identifier); void exitStructDeclaration(); - bool structNestingErrorCheck(TSourceLoc line, const TType& fieldType); + bool structNestingErrorCheck(const TSourceLoc& line, const TField& field); }; int PaParseStrings(size_t count, const char* const string[], const int length[], diff --git a/gfx/angle/src/compiler/PoolAlloc.cpp b/gfx/angle/src/compiler/PoolAlloc.cpp index 9ef4f59f5cfb..eb993567b353 100644 --- a/gfx/angle/src/compiler/PoolAlloc.cpp +++ b/gfx/angle/src/compiler/PoolAlloc.cpp @@ -17,55 +17,32 @@ OS_TLSIndex PoolIndex = OS_INVALID_TLS_INDEX; -void InitializeGlobalPools() -{ - TThreadGlobalPools* globalPools= static_cast(OS_GetTLSValue(PoolIndex)); - if (globalPools) - return; - - TThreadGlobalPools* threadData = new TThreadGlobalPools(); - threadData->globalPoolAllocator = 0; - - OS_SetTLSValue(PoolIndex, threadData); -} - -void FreeGlobalPools() -{ - // Release the allocated memory for this thread. - TThreadGlobalPools* globalPools= static_cast(OS_GetTLSValue(PoolIndex)); - if (!globalPools) - return; - - delete globalPools; -} - bool InitializePoolIndex() { - // Allocate a TLS index. - if ((PoolIndex = OS_AllocTLSIndex()) == OS_INVALID_TLS_INDEX) - return false; + assert(PoolIndex == OS_INVALID_TLS_INDEX); - return true; + PoolIndex = OS_AllocTLSIndex(); + return PoolIndex != OS_INVALID_TLS_INDEX; } void FreePoolIndex() { - // Release the TLS index. + assert(PoolIndex != OS_INVALID_TLS_INDEX); + OS_FreeTLSIndex(PoolIndex); + PoolIndex = OS_INVALID_TLS_INDEX; } -TPoolAllocator& GetGlobalPoolAllocator() +TPoolAllocator* GetGlobalPoolAllocator() { - TThreadGlobalPools* threadData = static_cast(OS_GetTLSValue(PoolIndex)); - - return *threadData->globalPoolAllocator; + assert(PoolIndex != OS_INVALID_TLS_INDEX); + return static_cast(OS_GetTLSValue(PoolIndex)); } void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator) { - TThreadGlobalPools* threadData = static_cast(OS_GetTLSValue(PoolIndex)); - - threadData->globalPoolAllocator = poolAllocator; + assert(PoolIndex != OS_INVALID_TLS_INDEX); + OS_SetTLSValue(PoolIndex, poolAllocator); } // @@ -228,24 +205,27 @@ void TPoolAllocator::popAll() void* TPoolAllocator::allocate(size_t numBytes) { - // If we are using guard blocks, all allocations are bracketed by - // them: [guardblock][allocation][guardblock]. numBytes is how - // much memory the caller asked for. allocationSize is the total - // size including guard blocks. In release build, - // guardBlockSize=0 and this all gets optimized away. - size_t allocationSize = TAllocation::allocationSize(numBytes); - // // Just keep some interesting statistics. // ++numCalls; totalBytes += numBytes; + // If we are using guard blocks, all allocations are bracketed by + // them: [guardblock][allocation][guardblock]. numBytes is how + // much memory the caller asked for. allocationSize is the total + // size including guard blocks. In release build, + // guardBlockSize=0 and this all gets optimized away. + size_t allocationSize = TAllocation::allocationSize(numBytes); + // Detect integer overflow. + if (allocationSize < numBytes) + return 0; + // // Do the allocation, most likely case first, for efficiency. // This step could be moved to be inline sometime. // - if (currentPageOffset + allocationSize <= pageSize) { + if (allocationSize <= pageSize - currentPageOffset) { // // Safe to allocate from currentPageOffset. // @@ -256,12 +236,16 @@ void* TPoolAllocator::allocate(size_t numBytes) return initializeAllocation(inUseList, memory, numBytes); } - if (allocationSize + headerSkip > pageSize) { + if (allocationSize > pageSize - headerSkip) { // // Do a multi-page allocation. Don't mix these with the others. // The OS is efficient and allocating and free-ing multiple pages. // size_t numBytesToAlloc = allocationSize + headerSkip; + // Detect integer overflow. + if (numBytesToAlloc < allocationSize) + return 0; + tHeader* memory = reinterpret_cast(::new char[numBytesToAlloc]); if (memory == 0) return 0; diff --git a/gfx/angle/src/compiler/PoolAlloc.h b/gfx/angle/src/compiler/PoolAlloc.h index a8a59c69acd9..edd249c4d3a3 100644 --- a/gfx/angle/src/compiler/PoolAlloc.h +++ b/gfx/angle/src/compiler/PoolAlloc.h @@ -219,14 +219,8 @@ private: // different times. But a simple use is to have a global pop // with everyone using the same global allocator. // -extern TPoolAllocator& GetGlobalPoolAllocator(); +extern TPoolAllocator* GetGlobalPoolAllocator(); extern void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator); -#define GlobalPoolAllocator GetGlobalPoolAllocator() - -struct TThreadGlobalPools -{ - TPoolAllocator* globalPoolAllocator; -}; // // This STL compatible allocator is intended to be used as the allocator @@ -253,7 +247,7 @@ public: pointer address(reference x) const { return &x; } const_pointer address(const_reference x) const { return &x; } - pool_allocator() : allocator(&GlobalPoolAllocator) { } + pool_allocator() : allocator(GetGlobalPoolAllocator()) { } pool_allocator(TPoolAllocator& a) : allocator(&a) { } pool_allocator(const pool_allocator& p) : allocator(p.allocator) { } diff --git a/gfx/angle/src/compiler/ShHandle.h b/gfx/angle/src/compiler/ShHandle.h index daecd869c2e2..eaf6f687d098 100644 --- a/gfx/angle/src/compiler/ShHandle.h +++ b/gfx/angle/src/compiler/ShHandle.h @@ -27,6 +27,7 @@ class LongNameMap; class TCompiler; class TDependencyGraph; +class TranslatorHLSL; // // Helper function to identify specs that are based on the WebGL spec, @@ -42,6 +43,7 @@ public: TShHandleBase(); virtual ~TShHandleBase(); virtual TCompiler* getAsCompiler() { return 0; } + virtual TranslatorHLSL* getAsTranslatorHLSL() { return 0; } protected: // Memory allocator. Allocates and tracks memory required by the compiler. @@ -81,8 +83,8 @@ protected: bool InitBuiltInSymbolTable(const ShBuiltInResources& resources); // Clears the results from the previous compilation. void clearResults(); - // Return true if function recursion is detected. - bool detectRecursion(TIntermNode* root); + // Return true if function recursion is detected or call depth exceeded. + bool detectCallDepth(TIntermNode* root, TInfoSink& infoSink, bool limitCallStackDepth); // Rewrites a shader's intermediate tree according to the CSS Shaders spec. void rewriteCSSShader(TIntermNode* root); // Returns true if the given shader does not exceed the minimum @@ -104,8 +106,12 @@ protected: // Returns true if the shader does not use sampler dependent values to affect control // flow or in operations whose time can depend on the input values. bool enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph); + // Return true if the maximum expression complexity below the limit. + bool limitExpressionComplexity(TIntermNode* root); // Get built-in extensions with default behavior. const TExtensionBehavior& getExtensionBehavior() const; + // Get the resources set by InitBuiltInSymbolTable + const ShBuiltInResources& getResources() const; const ArrayBoundsClamper& getArrayBoundsClamper() const; ShArrayIndexClampingStrategy getArrayIndexClampingStrategy() const; @@ -116,6 +122,10 @@ private: ShShaderSpec shaderSpec; int maxUniformVectors; + int maxExpressionComplexity; + int maxCallStackDepth; + + ShBuiltInResources compileResources; // Built-in symbol table for the given language, spec, and resources. // It is preserved from compile-to-compile. diff --git a/gfx/angle/src/compiler/ShaderLang.cpp b/gfx/angle/src/compiler/ShaderLang.cpp index dcf8b9694771..147894e06d5e 100644 --- a/gfx/angle/src/compiler/ShaderLang.cpp +++ b/gfx/angle/src/compiler/ShaderLang.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -14,6 +14,7 @@ #include "compiler/InitializeDll.h" #include "compiler/preprocessor/length_limits.h" #include "compiler/ShHandle.h" +#include "compiler/TranslatorHLSL.h" // // This is the platform independent interface between an OGL driver @@ -84,15 +85,13 @@ static void getVariableInfo(ShShaderInfo varType, } // -// Driver must call this first, once, before doing any other -// compiler operations. +// Driver must call this first, once, before doing any other compiler operations. +// Subsequent calls to this function are no-op. // int ShInitialize() { - if (!InitProcess()) - return 0; - - return 1; + static const bool kInitialized = InitProcess(); + return kInitialized ? 1 : 0; } // @@ -100,9 +99,7 @@ int ShInitialize() // int ShFinalize() { - if (!DetachProcess()) - return 0; - + DetachProcess(); return 1; } @@ -126,6 +123,7 @@ void ShInitBuiltInResources(ShBuiltInResources* resources) resources->OES_EGL_image_external = 0; resources->ARB_texture_rectangle = 0; resources->EXT_draw_buffers = 0; + resources->EXT_frag_depth = 0; // Disable highp precision in fragment shader by default. resources->FragmentPrecisionHigh = 0; @@ -143,9 +141,6 @@ ShHandle ShConstructCompiler(ShShaderType type, ShShaderSpec spec, ShShaderOutput output, const ShBuiltInResources* resources) { - if (!InitThread()) - return 0; - TShHandleBase* base = static_cast(ConstructCompiler(type, spec, output)); TCompiler* compiler = base->getAsCompiler(); if (compiler == 0) @@ -184,9 +179,6 @@ int ShCompile( size_t numStrings, int compileOptions) { - if (!InitThread()) - return 0; - if (handle == 0) return 0; @@ -351,3 +343,21 @@ void ShGetNameHashingEntry(const ShHandle handle, // To be on the safe side in case the source is longer than expected. hashedName[len - 1] = '\0'; } + +void ShGetInfoPointer(const ShHandle handle, ShShaderInfo pname, void** params) +{ + if (!handle || !params) + return; + + TShHandleBase* base = static_cast(handle); + TranslatorHLSL* translator = base->getAsTranslatorHLSL(); + if (!translator) return; + + switch(pname) + { + case SH_ACTIVE_UNIFORMS_ARRAY: + *params = (void*)&translator->getUniforms(); + break; + default: UNREACHABLE(); + } +} diff --git a/gfx/angle/src/compiler/SymbolTable.cpp b/gfx/angle/src/compiler/SymbolTable.cpp index 847c1e40858d..51180aff663d 100644 --- a/gfx/angle/src/compiler/SymbolTable.cpp +++ b/gfx/angle/src/compiler/SymbolTable.cpp @@ -17,48 +17,34 @@ #include #include - -#include "common/angleutils.h" +#include TType::TType(const TPublicType &p) : - type(p.type), precision(p.precision), qualifier(p.qualifier), size(p.size), matrix(p.matrix), array(p.array), arraySize(p.arraySize), - maxArraySize(0), arrayInformationType(0), structure(0), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0), typeName(0) + type(p.type), precision(p.precision), qualifier(p.qualifier), size(p.size), matrix(p.matrix), array(p.array), arraySize(p.arraySize), structure(0) { - if (p.userDef) { + if (p.userDef) structure = p.userDef->getStruct(); - typeName = NewPoolTString(p.userDef->getTypeName().c_str()); - computeDeepestStructNesting(); - } } // // Recursively generate mangled names. // -void TType::buildMangledName(TString& mangledName) +TString TType::buildMangledName() const { + TString mangledName; if (isMatrix()) mangledName += 'm'; else if (isVector()) mangledName += 'v'; switch (type) { - case EbtFloat: mangledName += 'f'; break; - case EbtInt: mangledName += 'i'; break; - case EbtBool: mangledName += 'b'; break; - case EbtSampler2D: mangledName += "s2"; break; - case EbtSamplerCube: mangledName += "sC"; break; - case EbtStruct: - mangledName += "struct-"; - if (typeName) - mangledName += *typeName; - {// support MSVC++6.0 - for (unsigned int i = 0; i < structure->size(); ++i) { - mangledName += '-'; - (*structure)[i].type->buildMangledName(mangledName); - } - } - default: - break; + case EbtFloat: mangledName += 'f'; break; + case EbtInt: mangledName += 'i'; break; + case EbtBool: mangledName += 'b'; break; + case EbtSampler2D: mangledName += "s2"; break; + case EbtSamplerCube: mangledName += "sC"; break; + case EbtStruct: mangledName += structure->mangledName(); break; + default: break; } mangledName += static_cast('0' + getNominalSize()); @@ -69,55 +55,74 @@ void TType::buildMangledName(TString& mangledName) mangledName += buf; mangledName += ']'; } + return mangledName; } -int TType::getStructSize() const +size_t TType::getObjectSize() const { - if (!getStruct()) { - assert(false && "Not a struct"); - return 0; + size_t totalSize = 0; + + if (getBasicType() == EbtStruct) + totalSize = structure->objectSize(); + else if (matrix) + totalSize = size * size; + else + totalSize = size; + + if (isArray()) { + size_t arraySize = getArraySize(); + if (arraySize > INT_MAX / totalSize) + totalSize = INT_MAX; + else + totalSize *= arraySize; } - if (structureSize == 0) - for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); tl++) - structureSize += ((*tl).type)->getObjectSize(); - - return structureSize; + return totalSize; } -void TType::computeDeepestStructNesting() +bool TStructure::containsArrays() const { - if (!getStruct()) { - return; - } - - int maxNesting = 0; - for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); ++tl) { - maxNesting = std::max(maxNesting, ((*tl).type)->getDeepestStructNesting()); - } - - deepestStructNesting = 1 + maxNesting; -} - -bool TType::isStructureContainingArrays() const -{ - if (!structure) - { - return false; - } - - for (TTypeList::const_iterator member = structure->begin(); member != structure->end(); member++) - { - if (member->type->isArray() || - member->type->isStructureContainingArrays()) - { + for (size_t i = 0; i < mFields->size(); ++i) { + const TType* fieldType = (*mFields)[i]->type(); + if (fieldType->isArray() || fieldType->isStructureContainingArrays()) return true; - } } - return false; } +TString TStructure::buildMangledName() const +{ + TString mangledName("struct-"); + mangledName += *mName; + for (size_t i = 0; i < mFields->size(); ++i) { + mangledName += '-'; + mangledName += (*mFields)[i]->type()->getMangledName(); + } + return mangledName; +} + +size_t TStructure::calculateObjectSize() const +{ + size_t size = 0; + for (size_t i = 0; i < mFields->size(); ++i) { + size_t fieldSize = (*mFields)[i]->type()->getObjectSize(); + if (fieldSize > INT_MAX - size) + size = INT_MAX; + else + size += fieldSize; + } + return size; +} + +int TStructure::calculateDeepestNesting() const +{ + int maxNesting = 0; + for (size_t i = 0; i < mFields->size(); ++i) { + maxNesting = std::max(maxNesting, (*mFields)[i]->type()->getDeepestStructNesting()); + } + return 1 + maxNesting; +} + // // Dump functions. // @@ -196,84 +201,8 @@ void TSymbolTableLevel::relateToOperator(const char* name, TOperator op) void TSymbolTableLevel::relateToExtension(const char* name, const TString& ext) { for (tLevel::iterator it = level.begin(); it != level.end(); ++it) { - if (it->second->isFunction()) { - TFunction* function = static_cast(it->second); - if (function->getName() == name) - function->relateToExtension(ext); - } - } -} - -TSymbol::TSymbol(const TSymbol& copyOf) -{ - name = NewPoolTString(copyOf.name->c_str()); - uniqueId = copyOf.uniqueId; -} - -TVariable::TVariable(const TVariable& copyOf, TStructureMap& remapper) : TSymbol(copyOf) -{ - type.copyType(copyOf.type, remapper); - userType = copyOf.userType; - // for builtIn symbol table level, unionArray and arrayInformation pointers should be NULL - assert(copyOf.arrayInformationType == 0); - arrayInformationType = 0; - - if (copyOf.unionArray) { - assert(!copyOf.type.getStruct()); - assert(copyOf.type.getObjectSize() == 1); - unionArray = new ConstantUnion[1]; - unionArray[0] = copyOf.unionArray[0]; - } else - unionArray = 0; -} - -TVariable* TVariable::clone(TStructureMap& remapper) -{ - TVariable *variable = new TVariable(*this, remapper); - - return variable; -} - -TFunction::TFunction(const TFunction& copyOf, TStructureMap& remapper) : TSymbol(copyOf) -{ - for (unsigned int i = 0; i < copyOf.parameters.size(); ++i) { - TParameter param; - parameters.push_back(param); - parameters.back().copyParam(copyOf.parameters[i], remapper); - } - - returnType.copyType(copyOf.returnType, remapper); - mangledName = copyOf.mangledName; - op = copyOf.op; - defined = copyOf.defined; -} - -TFunction* TFunction::clone(TStructureMap& remapper) -{ - TFunction *function = new TFunction(*this, remapper); - - return function; -} - -TSymbolTableLevel* TSymbolTableLevel::clone(TStructureMap& remapper) -{ - TSymbolTableLevel *symTableLevel = new TSymbolTableLevel(); - tLevel::iterator iter; - for (iter = level.begin(); iter != level.end(); ++iter) { - symTableLevel->insert(*iter->second->clone(remapper)); - } - - return symTableLevel; -} - -void TSymbolTable::copyTable(const TSymbolTable& copyOf) -{ - TStructureMap remapper; - uniqueId = copyOf.uniqueId; - for (unsigned int i = 0; i < copyOf.table.size(); ++i) { - table.push_back(copyOf.table[i]->clone(remapper)); - } - for( unsigned int i = 0; i < copyOf.precisionStack.size(); i++) { - precisionStack.push_back( copyOf.precisionStack[i] ); + TSymbol* symbol = it->second; + if (symbol->getName() == name) + symbol->relateToExtension(ext); } } diff --git a/gfx/angle/src/compiler/SymbolTable.h b/gfx/angle/src/compiler/SymbolTable.h index d27aa332b74f..f9a7948a3bc2 100644 --- a/gfx/angle/src/compiler/SymbolTable.h +++ b/gfx/angle/src/compiler/SymbolTable.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -32,6 +32,7 @@ #include +#include "common/angleutils.h" #include "compiler/InfoSink.h" #include "compiler/intermediate.h" @@ -40,22 +41,26 @@ // class TSymbol { public: - POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) + POOL_ALLOCATOR_NEW_DELETE(); TSymbol(const TString *n) : name(n) { } virtual ~TSymbol() { /* don't delete name, it's from the pool */ } + const TString& getName() const { return *name; } virtual const TString& getMangledName() const { return getName(); } virtual bool isFunction() const { return false; } virtual bool isVariable() const { return false; } void setUniqueId(int id) { uniqueId = id; } int getUniqueId() const { return uniqueId; } - virtual void dump(TInfoSink &infoSink) const = 0; - TSymbol(const TSymbol&); - virtual TSymbol* clone(TStructureMap& remapper) = 0; + virtual void dump(TInfoSink &infoSink) const = 0; + void relateToExtension(const TString& ext) { extension = ext; } + const TString& getExtension() const { return extension; } + +private: + DISALLOW_COPY_AND_ASSIGN(TSymbol); -protected: const TString *name; unsigned int uniqueId; // For real comparing during code generation + TString extension; }; // @@ -70,15 +75,13 @@ protected: // class TVariable : public TSymbol { public: - TVariable(const TString *name, const TType& t, bool uT = false ) : TSymbol(name), type(t), userType(uT), unionArray(0), arrayInformationType(0) { } + TVariable(const TString *name, const TType& t, bool uT = false ) : TSymbol(name), type(t), userType(uT), unionArray(0) { } virtual ~TVariable() { } virtual bool isVariable() const { return true; } TType& getType() { return type; } const TType& getType() const { return type; } bool isUserType() const { return userType; } void setQualifier(TQualifier qualifier) { type.setQualifier(qualifier); } - void updateArrayInformationType(TType *t) { arrayInformationType = t; } - TType* getArrayInformationType() { return arrayInformationType; } virtual void dump(TInfoSink &infoSink) const; @@ -100,16 +103,15 @@ public: delete[] unionArray; unionArray = constArray; } - TVariable(const TVariable&, TStructureMap& remapper); // copy constructor - virtual TVariable* clone(TStructureMap& remapper); -protected: +private: + DISALLOW_COPY_AND_ASSIGN(TVariable); + TType type; bool userType; // we are assuming that Pool Allocator will free the memory allocated to unionArray // when this object is destroyed ConstantUnion *unionArray; - TType *arrayInformationType; // this is used for updating maxArraySize in all the references to a given symbol }; // @@ -119,11 +121,6 @@ protected: struct TParameter { TString *name; TType* type; - void copyParam(const TParameter& param, TStructureMap& remapper) - { - name = NewPoolTString(param.name->c_str()); - type = param.type->clone(remapper); - } }; // @@ -163,9 +160,6 @@ public: void relateToOperator(TOperator o) { op = o; } TOperator getBuiltInOp() const { return op; } - void relateToExtension(const TString& ext) { extension = ext; } - const TString& getExtension() const { return extension; } - void setDefined() { defined = true; } bool isDefined() { return defined; } @@ -173,16 +167,15 @@ public: const TParameter& getParam(size_t i) const { return parameters[i]; } virtual void dump(TInfoSink &infoSink) const; - TFunction(const TFunction&, TStructureMap& remapper); - virtual TFunction* clone(TStructureMap& remapper); -protected: +private: + DISALLOW_COPY_AND_ASSIGN(TFunction); + typedef TVector TParamList; TParamList parameters; TType returnType; TString mangledName; TOperator op; - TString extension; bool defined; }; @@ -194,21 +187,26 @@ public: typedef const tLevel::value_type tLevelPair; typedef std::pair tInsertResult; - POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) + POOL_ALLOCATOR_NEW_DELETE(); TSymbolTableLevel() { } ~TSymbolTableLevel(); - bool insert(TSymbol& symbol) + bool insert(const TString &name, TSymbol &symbol) { // // returning true means symbol was added to the table // tInsertResult result; - result = level.insert(tLevelPair(symbol.getMangledName(), &symbol)); + result = level.insert(tLevelPair(name, &symbol)); return result.second; } + bool insert(TSymbol &symbol) + { + return insert(symbol.getMangledName(), symbol); + } + TSymbol* find(const TString& name) const { tLevel::const_iterator it = level.find(name); @@ -231,7 +229,6 @@ public: void relateToOperator(const char* name, TOperator op); void relateToExtension(const char* name, const TString& ext); void dump(TInfoSink &infoSink) const; - TSymbolTableLevel* clone(TStructureMap& remapper); protected: tLevel level; @@ -282,6 +279,35 @@ public: return table[currentLevel()]->insert(symbol); } + bool insertConstInt(const char *name, int value) + { + TVariable *constant = new TVariable(NewPoolTString(name), TType(EbtInt, EbpUndefined, EvqConst, 1)); + constant->getConstPointer()->setIConst(value); + return insert(*constant); + } + + bool insertBuiltIn(TType *rvalue, const char *name, TType *ptype1, TType *ptype2 = 0, TType *ptype3 = 0) + { + TFunction *function = new TFunction(NewPoolTString(name), *rvalue); + + TParameter param1 = {NULL, ptype1}; + function->addParameter(param1); + + if(ptype2) + { + TParameter param2 = {NULL, ptype2}; + function->addParameter(param2); + } + + if(ptype3) + { + TParameter param3 = {NULL, ptype3}; + function->addParameter(param3); + } + + return insert(*function); + } + TSymbol* find(const TString& name, bool* builtIn = 0, bool *sameScope = 0) { int level = currentLevel(); @@ -321,7 +347,6 @@ public: } int getMaxSymbolId() { return uniqueId; } void dump(TInfoSink &infoSink) const; - void copyTable(const TSymbolTable& copyOf); bool setDefaultPrecision( const TPublicType& type, TPrecision prec ){ if (IsSampler(type.type)) diff --git a/gfx/angle/src/compiler/TranslatorHLSL.cpp b/gfx/angle/src/compiler/TranslatorHLSL.cpp index f41decd48c59..37408a07c496 100644 --- a/gfx/angle/src/compiler/TranslatorHLSL.cpp +++ b/gfx/angle/src/compiler/TranslatorHLSL.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -9,15 +9,16 @@ #include "compiler/InitializeParseContext.h" #include "compiler/OutputHLSL.h" -TranslatorHLSL::TranslatorHLSL(ShShaderType type, ShShaderSpec spec) - : TCompiler(type, spec) +TranslatorHLSL::TranslatorHLSL(ShShaderType type, ShShaderSpec spec, ShShaderOutput output) + : TCompiler(type, spec), mOutputType(output) { } void TranslatorHLSL::translate(TIntermNode *root) { TParseContext& parseContext = *GetGlobalParseContext(); - sh::OutputHLSL outputHLSL(parseContext); + sh::OutputHLSL outputHLSL(parseContext, getResources(), mOutputType); outputHLSL.output(); + mActiveUniforms = outputHLSL.getUniforms(); } diff --git a/gfx/angle/src/compiler/TranslatorHLSL.h b/gfx/angle/src/compiler/TranslatorHLSL.h index c3f672ba9198..9bac66ae92a4 100644 --- a/gfx/angle/src/compiler/TranslatorHLSL.h +++ b/gfx/angle/src/compiler/TranslatorHLSL.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -8,13 +8,20 @@ #define COMPILER_TRANSLATORHLSL_H_ #include "compiler/ShHandle.h" +#include "compiler/CompilerUniform.h" class TranslatorHLSL : public TCompiler { public: - TranslatorHLSL(ShShaderType type, ShShaderSpec spec); + TranslatorHLSL(ShShaderType type, ShShaderSpec spec, ShShaderOutput output); + + virtual TranslatorHLSL *getAsTranslatorHLSL() { return this; } + const sh::ActiveUniforms &getUniforms() { return mActiveUniforms; } protected: virtual void translate(TIntermNode* root); + + sh::ActiveUniforms mActiveUniforms; + ShShaderOutput mOutputType; }; #endif // COMPILER_TRANSLATORHLSL_H_ diff --git a/gfx/angle/src/compiler/Types.h b/gfx/angle/src/compiler/Types.h index fec7adbce6bd..39b93d8c370d 100644 --- a/gfx/angle/src/compiler/Types.h +++ b/gfx/angle/src/compiler/Types.h @@ -7,30 +7,85 @@ #ifndef _TYPES_INCLUDED #define _TYPES_INCLUDED +#include "common/angleutils.h" + #include "compiler/BaseTypes.h" #include "compiler/Common.h" #include "compiler/compiler_debug.h" -class TType; struct TPublicType; +class TType; -// -// Need to have association of line numbers to types in a list for building structs. -// -struct TTypeLine { - TType* type; - int line; -}; -typedef TVector TTypeList; - -inline TTypeList* NewPoolTTypeList() +class TField { - void* memory = GlobalPoolAllocator.allocate(sizeof(TTypeList)); - return new(memory) TTypeList; +public: + POOL_ALLOCATOR_NEW_DELETE(); + TField(TType* type, TString* name) : mType(type), mName(name) {} + + // TODO(alokp): We should only return const type. + // Fix it by tweaking grammar. + TType* type() { return mType; } + const TType* type() const { return mType; } + + const TString& name() const { return *mName; } + +private: + DISALLOW_COPY_AND_ASSIGN(TField); + TType* mType; + TString* mName; +}; + +typedef TVector TFieldList; +inline TFieldList* NewPoolTFieldList() +{ + void* memory = GetGlobalPoolAllocator()->allocate(sizeof(TFieldList)); + return new(memory) TFieldList; } -typedef TMap TStructureMap; -typedef TMap::iterator TStructureMapIterator; +class TStructure +{ +public: + POOL_ALLOCATOR_NEW_DELETE(); + TStructure(TString* name, TFieldList* fields) + : mName(name), + mFields(fields), + mObjectSize(0), + mDeepestNesting(0) { + } + + const TString& name() const { return *mName; } + const TFieldList& fields() const { return *mFields; } + + const TString& mangledName() const { + if (mMangledName.empty()) + mMangledName = buildMangledName(); + return mMangledName; + } + size_t objectSize() const { + if (mObjectSize == 0) + mObjectSize = calculateObjectSize(); + return mObjectSize; + }; + int deepestNesting() const { + if (mDeepestNesting == 0) + mDeepestNesting = calculateDeepestNesting(); + return mDeepestNesting; + } + bool containsArrays() const; + +private: + DISALLOW_COPY_AND_ASSIGN(TStructure); + TString buildMangledName() const; + size_t calculateObjectSize() const; + int calculateDeepestNesting() const; + + TString* mName; + TFieldList* mFields; + + mutable TString mMangledName; + mutable size_t mObjectSize; + mutable int mDeepestNesting; +}; // // Base class for things that have a type. @@ -38,72 +93,16 @@ typedef TMap::iterator TStructureMapIterator; class TType { public: - POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) + POOL_ALLOCATOR_NEW_DELETE(); TType() {} - TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, int s = 1, bool m = false, bool a = false) : - type(t), precision(p), qualifier(q), size(s), matrix(m), array(a), arraySize(0), - maxArraySize(0), arrayInformationType(0), structure(0), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0), typeName(0) + TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, char s = 1, bool m = false, bool a = false) : + type(t), precision(p), qualifier(q), size(s), matrix(m), array(a), arraySize(0), structure(0) { } explicit TType(const TPublicType &p); - TType(TTypeList* userDef, const TString& n, TPrecision p = EbpUndefined) : - type(EbtStruct), precision(p), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0), - maxArraySize(0), arrayInformationType(0), structure(userDef), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0) + TType(TStructure* userDef, TPrecision p = EbpUndefined) : + type(EbtStruct), precision(p), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0), structure(userDef) { - typeName = NewPoolTString(n.c_str()); - } - - void copyType(const TType& copyOf, TStructureMap& remapper) - { - type = copyOf.type; - precision = copyOf.precision; - qualifier = copyOf.qualifier; - size = copyOf.size; - matrix = copyOf.matrix; - array = copyOf.array; - arraySize = copyOf.arraySize; - - TStructureMapIterator iter; - if (copyOf.structure) { - if ((iter = remapper.find(structure)) == remapper.end()) { - // create the new structure here - structure = NewPoolTTypeList(); - for (unsigned int i = 0; i < copyOf.structure->size(); ++i) { - TTypeLine typeLine; - typeLine.line = (*copyOf.structure)[i].line; - typeLine.type = (*copyOf.structure)[i].type->clone(remapper); - structure->push_back(typeLine); - } - } else { - structure = iter->second; - } - } else - structure = 0; - - fieldName = 0; - if (copyOf.fieldName) - fieldName = NewPoolTString(copyOf.fieldName->c_str()); - typeName = 0; - if (copyOf.typeName) - typeName = NewPoolTString(copyOf.typeName->c_str()); - - mangled = 0; - if (copyOf.mangled) - mangled = NewPoolTString(copyOf.mangled->c_str()); - - structureSize = copyOf.structureSize; - maxArraySize = copyOf.maxArraySize; - deepestStructNesting = copyOf.deepestStructNesting; - assert(copyOf.arrayInformationType == 0); - arrayInformationType = 0; // arrayInformationType should not be set for builtIn symbol table level - } - - TType* clone(TStructureMap& remapper) - { - TType *newType = new TType(); - newType->copyType(*this, remapper); - - return newType; } TBasicType getBasicType() const { return type; } @@ -119,21 +118,42 @@ public: int getNominalSize() const { return size; } void setNominalSize(int s) { size = s; } // Full size of single instance of type - int getObjectSize() const + size_t getObjectSize() const; + + int elementRegisterCount() const { - int totalSize; + if (structure) + { + const TFieldList &fields = getStruct()->fields(); + int registerCount = 0; - if (getBasicType() == EbtStruct) - totalSize = getStructSize(); - else if (matrix) - totalSize = size * size; + for (size_t i = 0; i < fields.size(); i++) + { + registerCount += fields[i]->type()->totalRegisterCount(); + } + + return registerCount; + } + else if (isMatrix()) + { + return getNominalSize(); + } else - totalSize = size; + { + return 1; + } + } - if (isArray()) - totalSize *= std::max(getArraySize(), getMaxArraySize()); - - return totalSize; + int totalRegisterCount() const + { + if (array) + { + return arraySize * elementRegisterCount(); + } + else + { + return elementRegisterCount(); + } } bool isMatrix() const { return matrix ? true : false; } @@ -142,47 +162,20 @@ public: bool isArray() const { return array ? true : false; } int getArraySize() const { return arraySize; } void setArraySize(int s) { array = true; arraySize = s; } - int getMaxArraySize () const { return maxArraySize; } - void setMaxArraySize (int s) { maxArraySize = s; } - void clearArrayness() { array = false; arraySize = 0; maxArraySize = 0; } - void setArrayInformationType(TType* t) { arrayInformationType = t; } - TType* getArrayInformationType() const { return arrayInformationType; } + void clearArrayness() { array = false; arraySize = 0; } bool isVector() const { return size > 1 && !matrix; } bool isScalar() const { return size == 1 && !matrix && !structure; } - TTypeList* getStruct() const { return structure; } - void setStruct(TTypeList* s) { structure = s; computeDeepestStructNesting(); } + TStructure* getStruct() const { return structure; } + void setStruct(TStructure* s) { structure = s; } - const TString& getTypeName() const - { - assert(typeName); - return *typeName; - } - void setTypeName(const TString& n) - { - typeName = NewPoolTString(n.c_str()); - } - - bool isField() const { return fieldName != 0; } - const TString& getFieldName() const - { - assert(fieldName); - return *fieldName; - } - void setFieldName(const TString& n) - { - fieldName = NewPoolTString(n.c_str()); - } - - TString& getMangledName() { - if (!mangled) { - mangled = NewPoolTString(""); - buildMangledName(*mangled); - *mangled += ';' ; + const TString& getMangledName() const { + if (mangled.empty()) { + mangled = buildMangledName(); + mangled += ';'; } - - return *mangled; + return mangled; } bool sameElementType(const TType& right) const { @@ -230,32 +223,28 @@ public: // For type "nesting2", this method would return 2 -- the number // of structures through which indirection must occur to reach the // deepest field (nesting2.field1.position). - int getDeepestStructNesting() const { return deepestStructNesting; } + int getDeepestStructNesting() const { + return structure ? structure->deepestNesting() : 0; + } - bool isStructureContainingArrays() const; + bool isStructureContainingArrays() const { + return structure ? structure->containsArrays() : false; + } -protected: - void buildMangledName(TString&); - int getStructSize() const; - void computeDeepestStructNesting(); +private: + TString buildMangledName() const; - TBasicType type : 6; + TBasicType type; TPrecision precision; - TQualifier qualifier : 7; - int size : 8; // size of vector or matrix, not size of array - unsigned int matrix : 1; - unsigned int array : 1; + TQualifier qualifier; + char size; // size of vector or matrix, not size of array + bool matrix; + bool array; int arraySize; - int maxArraySize; - TType* arrayInformationType; - TTypeList* structure; // 0 unless this is a struct - mutable int structureSize; - int deepestStructNesting; + TStructure* structure; // 0 unless this is a struct - TString *fieldName; // for structure field names - TString *mangled; - TString *typeName; // for structure field type name + mutable TString mangled; }; // @@ -277,9 +266,9 @@ struct TPublicType bool array; int arraySize; TType* userDef; - int line; + TSourceLoc line; - void setBasic(TBasicType bt, TQualifier q, int ln = 0) + void setBasic(TBasicType bt, TQualifier q, const TSourceLoc& ln) { type = bt; qualifier = q; diff --git a/gfx/angle/src/compiler/ValidateLimitations.cpp b/gfx/angle/src/compiler/ValidateLimitations.cpp index a5562d09a439..736ceeaefc64 100644 --- a/gfx/angle/src/compiler/ValidateLimitations.cpp +++ b/gfx/angle/src/compiler/ValidateLimitations.cpp @@ -435,7 +435,7 @@ bool ValidateLimitations::validateFunctionCall(TIntermAggregate* node) return true; bool valid = true; - TSymbolTable& symbolTable = GlobalParseContext->symbolTable; + TSymbolTable& symbolTable = GetGlobalParseContext()->symbolTable; TSymbol* symbol = symbolTable.find(node->getName()); ASSERT(symbol && symbol->isFunction()); TFunction* function = static_cast(symbol); diff --git a/gfx/angle/src/compiler/VariableInfo.cpp b/gfx/angle/src/compiler/VariableInfo.cpp index eb6bea9b0fb6..84db807a801a 100644 --- a/gfx/angle/src/compiler/VariableInfo.cpp +++ b/gfx/angle/src/compiler/VariableInfo.cpp @@ -131,12 +131,13 @@ void getUserDefinedVariableInfo(const TType& type, { ASSERT(type.getBasicType() == EbtStruct); - const TTypeList* structure = type.getStruct(); - for (size_t i = 0; i < structure->size(); ++i) { - const TType* fieldType = (*structure)[i].type; - getVariableInfo(*fieldType, - name + "." + fieldType->getFieldName(), - mappedName + "." + TIntermTraverser::hash(fieldType->getFieldName(), hashFunction), + const TFieldList& fields = type.getStruct()->fields(); + for (size_t i = 0; i < fields.size(); ++i) { + const TType& fieldType = *(fields[i]->type()); + const TString& fieldName = fields[i]->name(); + getVariableInfo(fieldType, + name + "." + fieldName, + mappedName + "." + TIntermTraverser::hash(fieldName, hashFunction), infoList, hashFunction); } diff --git a/gfx/angle/src/compiler/generate_parser.sh b/gfx/angle/src/compiler/generate_parser.sh index e4721915e3cf..e4d88b2e84cd 100755 --- a/gfx/angle/src/compiler/generate_parser.sh +++ b/gfx/angle/src/compiler/generate_parser.sh @@ -25,3 +25,4 @@ script_dir=$(dirname $0) # Generate Parser run_flex glslang run_bison glslang +patch --silent --forward < 64bit-lexer-safety.patch diff --git a/gfx/angle/src/compiler/glslang.l b/gfx/angle/src/compiler/glslang.l index 140a9aeb2d82..404987508f1c 100644 --- a/gfx/angle/src/compiler/glslang.l +++ b/gfx/angle/src/compiler/glslang.l @@ -47,7 +47,10 @@ WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp). #pragma warning(disable : 4102) #endif -#define YY_USER_ACTION yylval->lex.line = yylineno; +#define YY_USER_ACTION \ + yylloc->first_file = yylloc->last_file = yycolumn; \ + yylloc->first_line = yylloc->last_line = yylineno; + #define YY_INPUT(buf, result, max_size) \ result = string_input(buf, max_size, yyscanner); @@ -57,10 +60,8 @@ static int reserved_word(yyscan_t yyscanner); %} %option noyywrap nounput never-interactive -%option yylineno reentrant bison-bridge -%option stack +%option yylineno reentrant bison-bridge bison-locations %option extra-type="TParseContext*" -%x COMMENT FIELDS D [0-9] L [a-zA-Z_] @@ -70,73 +71,60 @@ O [0-7] %% -%{ - TParseContext* context = yyextra; -%} +"invariant" { return INVARIANT; } +"highp" { return HIGH_PRECISION; } +"mediump" { return MEDIUM_PRECISION; } +"lowp" { return LOW_PRECISION; } +"precision" { return PRECISION; } - /* Single-line comments */ -"//"[^\n]* ; +"attribute" { return ATTRIBUTE; } +"const" { return CONST_QUAL; } +"uniform" { return UNIFORM; } +"varying" { return VARYING; } - /* Multi-line comments */ -"/*" { yy_push_state(COMMENT, yyscanner); } -. | -\n ; -"*/" { yy_pop_state(yyscanner); } +"break" { return BREAK; } +"continue" { return CONTINUE; } +"do" { return DO; } +"for" { return FOR; } +"while" { return WHILE; } -"invariant" { return(INVARIANT); } -"highp" { return(HIGH_PRECISION); } -"mediump" { return(MEDIUM_PRECISION); } -"lowp" { return(LOW_PRECISION); } -"precision" { return(PRECISION); } +"if" { return IF; } +"else" { return ELSE; } -"attribute" { return(ATTRIBUTE); } -"const" { return(CONST_QUAL); } -"uniform" { return(UNIFORM); } -"varying" { return(VARYING); } +"in" { return IN_QUAL; } +"out" { return OUT_QUAL; } +"inout" { return INOUT_QUAL; } -"break" { return(BREAK); } -"continue" { return(CONTINUE); } -"do" { return(DO); } -"for" { return(FOR); } -"while" { return(WHILE); } +"float" { return FLOAT_TYPE; } +"int" { return INT_TYPE; } +"void" { return VOID_TYPE; } +"bool" { return BOOL_TYPE; } +"true" { yylval->lex.b = true; return BOOLCONSTANT; } +"false" { yylval->lex.b = false; return BOOLCONSTANT; } -"if" { return(IF); } -"else" { return(ELSE); } +"discard" { return DISCARD; } +"return" { return RETURN; } -"in" { return(IN_QUAL); } -"out" { return(OUT_QUAL); } -"inout" { return(INOUT_QUAL); } +"mat2" { return MATRIX2; } +"mat3" { return MATRIX3; } +"mat4" { return MATRIX4; } -"float" { context->lexAfterType = true; return(FLOAT_TYPE); } -"int" { context->lexAfterType = true; return(INT_TYPE); } -"void" { context->lexAfterType = true; return(VOID_TYPE); } -"bool" { context->lexAfterType = true; return(BOOL_TYPE); } -"true" { yylval->lex.b = true; return(BOOLCONSTANT); } -"false" { yylval->lex.b = false; return(BOOLCONSTANT); } +"vec2" { return VEC2; } +"vec3" { return VEC3; } +"vec4" { return VEC4; } +"ivec2" { return IVEC2; } +"ivec3" { return IVEC3; } +"ivec4" { return IVEC4; } +"bvec2" { return BVEC2; } +"bvec3" { return BVEC3; } +"bvec4" { return BVEC4; } -"discard" { return(DISCARD); } -"return" { return(RETURN); } +"sampler2D" { return SAMPLER2D; } +"samplerCube" { return SAMPLERCUBE; } +"samplerExternalOES" { return SAMPLER_EXTERNAL_OES; } +"sampler2DRect" { return SAMPLER2DRECT; } -"mat2" { context->lexAfterType = true; return(MATRIX2); } -"mat3" { context->lexAfterType = true; return(MATRIX3); } -"mat4" { context->lexAfterType = true; return(MATRIX4); } - -"vec2" { context->lexAfterType = true; return (VEC2); } -"vec3" { context->lexAfterType = true; return (VEC3); } -"vec4" { context->lexAfterType = true; return (VEC4); } -"ivec2" { context->lexAfterType = true; return (IVEC2); } -"ivec3" { context->lexAfterType = true; return (IVEC3); } -"ivec4" { context->lexAfterType = true; return (IVEC4); } -"bvec2" { context->lexAfterType = true; return (BVEC2); } -"bvec3" { context->lexAfterType = true; return (BVEC3); } -"bvec4" { context->lexAfterType = true; return (BVEC4); } - -"sampler2D" { context->lexAfterType = true; return SAMPLER2D; } -"samplerCube" { context->lexAfterType = true; return SAMPLERCUBE; } -"samplerExternalOES" { context->lexAfterType = true; return SAMPLER_EXTERNAL_OES; } -"sampler2DRect" { context->lexAfterType = true; return SAMPLER2DRECT; } - -"struct" { context->lexAfterType = true; return(STRUCT); } +"struct" { return STRUCT; } "asm" { return reserved_word(yyscanner); } @@ -183,13 +171,11 @@ O [0-7] "fvec3" { return reserved_word(yyscanner); } "fvec4" { return reserved_word(yyscanner); } -"sampler1D" { return reserved_word(yyscanner); } -"sampler3D" { return reserved_word(yyscanner); } - -"sampler1DShadow" { return reserved_word(yyscanner); } -"sampler2DShadow" { return reserved_word(yyscanner); } - -"sampler3DRect" { return reserved_word(yyscanner); } +"sampler1D" { return reserved_word(yyscanner); } +"sampler3D" { return reserved_word(yyscanner); } +"sampler1DShadow" { return reserved_word(yyscanner); } +"sampler2DShadow" { return reserved_word(yyscanner); } +"sampler3DRect" { return reserved_word(yyscanner); } "sampler2DRectShadow" { return reserved_word(yyscanner); } "sizeof" { return reserved_word(yyscanner); } @@ -203,72 +189,64 @@ O [0-7] return check_type(yyscanner); } -0[xX]{H}+ { yylval->lex.i = static_cast(strtol(yytext, 0, 0)); return(INTCONSTANT); } -0{O}+ { yylval->lex.i = static_cast(strtol(yytext, 0, 0)); return(INTCONSTANT); } -0{D}+ { context->error(yylineno, "Invalid Octal number.", yytext); context->recover(); return 0;} -{D}+ { yylval->lex.i = static_cast(strtol(yytext, 0, 0)); return(INTCONSTANT); } +0[xX]{H}+ { yylval->lex.i = static_cast(strtol(yytext, 0, 0)); return INTCONSTANT; } +0{O}+ { yylval->lex.i = static_cast(strtol(yytext, 0, 0)); return INTCONSTANT; } +{D}+ { yylval->lex.i = static_cast(strtol(yytext, 0, 0)); return INTCONSTANT; } -{D}+{E} { yylval->lex.f = static_cast(atof_dot(yytext)); return(FLOATCONSTANT); } -{D}+"."{D}*({E})? { yylval->lex.f = static_cast(atof_dot(yytext)); return(FLOATCONSTANT); } -"."{D}+({E})? { yylval->lex.f = static_cast(atof_dot(yytext)); return(FLOATCONSTANT); } +{D}+{E} { yylval->lex.f = static_cast(atof_dot(yytext)); return FLOATCONSTANT; } +{D}+"."{D}*({E})? { yylval->lex.f = static_cast(atof_dot(yytext)); return FLOATCONSTANT; } +"."{D}+({E})? { yylval->lex.f = static_cast(atof_dot(yytext)); return FLOATCONSTANT; } -"+=" { return(ADD_ASSIGN); } -"-=" { return(SUB_ASSIGN); } -"*=" { return(MUL_ASSIGN); } -"/=" { return(DIV_ASSIGN); } -"%=" { return(MOD_ASSIGN); } -"<<=" { return(LEFT_ASSIGN); } -">>=" { return(RIGHT_ASSIGN); } -"&=" { return(AND_ASSIGN); } -"^=" { return(XOR_ASSIGN); } -"|=" { return(OR_ASSIGN); } +"+=" { return ADD_ASSIGN; } +"-=" { return SUB_ASSIGN; } +"*=" { return MUL_ASSIGN; } +"/=" { return DIV_ASSIGN; } +"%=" { return MOD_ASSIGN; } +"<<=" { return LEFT_ASSIGN; } +">>=" { return RIGHT_ASSIGN; } +"&=" { return AND_ASSIGN; } +"^=" { return XOR_ASSIGN; } +"|=" { return OR_ASSIGN; } -"++" { return(INC_OP); } -"--" { return(DEC_OP); } -"&&" { return(AND_OP); } -"||" { return(OR_OP); } -"^^" { return(XOR_OP); } -"<=" { return(LE_OP); } -">=" { return(GE_OP); } -"==" { return(EQ_OP); } -"!=" { return(NE_OP); } -"<<" { return(LEFT_OP); } -">>" { return(RIGHT_OP); } -";" { context->lexAfterType = false; return(SEMICOLON); } -("{"|"<%") { context->lexAfterType = false; return(LEFT_BRACE); } -("}"|"%>") { return(RIGHT_BRACE); } -"," { if (context->inTypeParen) context->lexAfterType = false; return(COMMA); } -":" { return(COLON); } -"=" { context->lexAfterType = false; return(EQUAL); } -"(" { context->lexAfterType = false; context->inTypeParen = true; return(LEFT_PAREN); } -")" { context->inTypeParen = false; return(RIGHT_PAREN); } -("["|"<:") { return(LEFT_BRACKET); } -("]"|":>") { return(RIGHT_BRACKET); } -"." { BEGIN(FIELDS); return(DOT); } -"!" { return(BANG); } -"-" { return(DASH); } -"~" { return(TILDE); } -"+" { return(PLUS); } -"*" { return(STAR); } -"/" { return(SLASH); } -"%" { return(PERCENT); } -"<" { return(LEFT_ANGLE); } -">" { return(RIGHT_ANGLE); } -"|" { return(VERTICAL_BAR); } -"^" { return(CARET); } -"&" { return(AMPERSAND); } -"?" { return(QUESTION); } +"++" { return INC_OP; } +"--" { return DEC_OP; } +"&&" { return AND_OP; } +"||" { return OR_OP; } +"^^" { return XOR_OP; } +"<=" { return LE_OP; } +">=" { return GE_OP; } +"==" { return EQ_OP; } +"!=" { return NE_OP; } +"<<" { return LEFT_OP; } +">>" { return RIGHT_OP; } +";" { return SEMICOLON; } +("{"|"<%") { return LEFT_BRACE; } +("}"|"%>") { return RIGHT_BRACE; } +"," { return COMMA; } +":" { return COLON; } +"=" { return EQUAL; } +"(" { return LEFT_PAREN; } +")" { return RIGHT_PAREN; } +("["|"<:") { return LEFT_BRACKET; } +("]"|":>") { return RIGHT_BRACKET; } +"." { return DOT; } +"!" { return BANG; } +"-" { return DASH; } +"~" { return TILDE; } +"+" { return PLUS; } +"*" { return STAR; } +"/" { return SLASH; } +"%" { return PERCENT; } +"<" { return LEFT_ANGLE; } +">" { return RIGHT_ANGLE; } +"|" { return VERTICAL_BAR; } +"^" { return CARET; } +"&" { return AMPERSAND; } +"?" { return QUESTION; } -{L}({L}|{D})* { - BEGIN(INITIAL); - yylval->lex.string = NewPoolTString(yytext); - return FIELD_SELECTION; -} -[ \t\v\f\r] {} - -[ \t\v\n\f\r] { } -<*><> { context->AfterEOF = true; yyterminate(); } -<*>. { context->warning(yylineno, "Unknown char", yytext, ""); return 0; } +[ \t\v\n\f\r] { } +<> { yyterminate(); } +. { assert(false); return 0; } %% @@ -278,7 +256,8 @@ yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner) { yy_size_t len = token.type == pp::Token::LAST ? 0 : token.text.size(); if (len < max_size) memcpy(buf, token.text.c_str(), len); - yyset_lineno(EncodeSourceLoc(token.location.file, token.location.line), yyscanner); + yyset_column(token.location.file, yyscanner); + yyset_lineno(token.location.line, yyscanner); if (len >= max_size) YY_FATAL_ERROR("Input buffer overflow"); @@ -292,12 +271,10 @@ int check_type(yyscan_t yyscanner) { int token = IDENTIFIER; TSymbol* symbol = yyextra->symbolTable.find(yytext); - if (yyextra->lexAfterType == false && symbol && symbol->isVariable()) { + if (symbol && symbol->isVariable()) { TVariable* variable = static_cast(symbol); - if (variable->isUserType()) { - yyextra->lexAfterType = true; + if (variable->isUserType()) token = TYPE_NAME; - } } yylval->lex.symbol = symbol; return token; @@ -306,22 +283,11 @@ int check_type(yyscan_t yyscanner) { int reserved_word(yyscan_t yyscanner) { struct yyguts_t* yyg = (struct yyguts_t*) yyscanner; - yyextra->error(yylineno, "Illegal use of reserved word", yytext, ""); + yyextra->error(*yylloc, "Illegal use of reserved word", yytext, ""); yyextra->recover(); return 0; } -void yyerror(TParseContext* context, const char* reason) { - struct yyguts_t* yyg = (struct yyguts_t*) context->scanner; - - if (context->AfterEOF) { - context->error(yylineno, reason, "unexpected EOF"); - } else { - context->error(yylineno, reason, yytext); - } - context->recover(); -} - int glslang_initialize(TParseContext* context) { yyscan_t scanner = NULL; if (yylex_init_extra(context, &scanner)) @@ -344,8 +310,8 @@ int glslang_finalize(TParseContext* context) { int glslang_scan(size_t count, const char* const string[], const int length[], TParseContext* context) { yyrestart(NULL, context->scanner); - yyset_lineno(EncodeSourceLoc(0, 1), context->scanner); - context->AfterEOF = false; + yyset_column(0, context->scanner); + yyset_lineno(1, context->scanner); // Initialize preprocessor. if (!context->preprocessor.init(count, string, length)) diff --git a/gfx/angle/src/compiler/glslang.y b/gfx/angle/src/compiler/glslang.y index 8dbcee32ef71..0e8c3c3bc7bb 100644 --- a/gfx/angle/src/compiler/glslang.y +++ b/gfx/angle/src/compiler/glslang.y @@ -39,7 +39,6 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h). #include "GLSLANG/ShaderLang.h" #define YYENABLE_NLS 0 -#define YYLTYPE_IS_TRIVIAL 1 #define YYLEX_PARAM context->scanner %} @@ -47,10 +46,15 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h). %expect 1 /* One shift reduce conflict because of if | else */ %pure-parser %parse-param {TParseContext* context} +%locations + +%code requires { +#define YYLTYPE TSourceLoc +#define YYLTYPE_IS_DECLARED 1 +} %union { struct { - TSourceLoc line; union { TString *string; float f; @@ -60,7 +64,6 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h). TSymbol* symbol; } lex; struct { - TSourceLoc line; TOperator op; union { TIntermNode* intermNode; @@ -74,23 +77,31 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h). TQualifier qualifier; TFunction* function; TParameter param; - TTypeLine typeLine; - TTypeList* typeList; + TField* field; + TFieldList* fieldList; }; } interm; } %{ -extern int yylex(YYSTYPE* yylval_param, void* yyscanner); -extern void yyerror(TParseContext* context, const char* reason); +extern int yylex(YYSTYPE* yylval, YYLTYPE* yylloc, void* yyscanner); +static void yyerror(YYLTYPE* yylloc, TParseContext* context, const char* reason); -#define FRAG_VERT_ONLY(S, L) { \ - if (context->shaderType != SH_FRAGMENT_SHADER && \ - context->shaderType != SH_VERTEX_SHADER) { \ - context->error(L, " supported in vertex/fragment shaders only ", S); \ - context->recover(); \ - } \ -} +#define YYLLOC_DEFAULT(Current, Rhs, N) \ + do { \ + if (YYID(N)) { \ + (Current).first_file = YYRHSLOC(Rhs, 1).first_file; \ + (Current).first_line = YYRHSLOC(Rhs, 1).first_line; \ + (Current).last_file = YYRHSLOC(Rhs, N).last_file; \ + (Current).last_line = YYRHSLOC(Rhs, N).last_line; \ + } \ + else { \ + (Current).first_file = YYRHSLOC(Rhs, 0).last_file; \ + (Current).first_line = YYRHSLOC(Rhs, 0).last_line; \ + (Current).last_file = YYRHSLOC(Rhs, 0).last_file; \ + (Current).last_line = YYRHSLOC(Rhs, 0).last_line; \ + } \ + } while (0) #define VERTEX_ONLY(S, L) { \ if (context->shaderType != SH_VERTEX_SHADER) { \ @@ -116,7 +127,6 @@ extern void yyerror(TParseContext* context, const char* reason); %token SAMPLER2D SAMPLERCUBE SAMPLER_EXTERNAL_OES SAMPLER2DRECT %token IDENTIFIER TYPE_NAME FLOATCONSTANT INTCONSTANT BOOLCONSTANT -%token FIELD_SELECTION %token LEFT_OP RIGHT_OP %token INC_OP DEC_OP LE_OP GE_OP EQ_OP NE_OP %token AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN @@ -127,6 +137,7 @@ extern void yyerror(TParseContext* context, const char* reason); %token COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT %token LEFT_ANGLE RIGHT_ANGLE VERTICAL_BAR CARET AMPERSAND QUESTION +%type identifier %type assignment_operator unary_operator %type variable_identifier primary_expression postfix_expression %type expression integer_expression assignment_expression @@ -154,8 +165,8 @@ extern void yyerror(TParseContext* context, const char* reason); %type type_qualifier fully_specified_type type_specifier %type type_specifier_no_prec type_specifier_nonarray %type struct_specifier -%type struct_declarator -%type struct_declarator_list struct_declaration struct_declaration_list +%type struct_declarator +%type struct_declarator_list struct_declaration struct_declaration_list %type function_header function_declarator function_identifier %type function_header_with_parameters function_call_header %type function_call_header_with_parameters function_call_header_no_parameters function_call_generic function_prototype @@ -164,13 +175,17 @@ extern void yyerror(TParseContext* context, const char* reason); %start translation_unit %% +identifier + : IDENTIFIER + | TYPE_NAME + variable_identifier : IDENTIFIER { // The symbol table search was done in the lexical phase const TSymbol* symbol = $1.symbol; const TVariable* variable; if (symbol == 0) { - context->error($1.line, "undeclared identifier", $1.string->c_str()); + context->error(@1, "undeclared identifier", $1.string->c_str()); context->recover(); TType type(EbtFloat, EbpUndefined); TVariable* fakeVariable = new TVariable($1.string, type); @@ -179,10 +194,17 @@ variable_identifier } else { // This identifier can only be a variable type symbol if (! symbol->isVariable()) { - context->error($1.line, "variable expected", $1.string->c_str()); + context->error(@1, "variable expected", $1.string->c_str()); context->recover(); } + variable = static_cast(symbol); + + if (context->symbolTable.findBuiltIn(variable->getName()) && + !variable->getExtension().empty() && + context->extensionErrorCheck(@1, variable->getExtension())) { + context->recover(); + } } // don't delete $1.string, it's used by error recovery, and the pool @@ -191,11 +213,12 @@ variable_identifier if (variable->getType().getQualifier() == EvqConst ) { ConstantUnion* constArray = variable->getConstPointer(); TType t(variable->getType()); - $$ = context->intermediate.addConstantUnion(constArray, t, $1.line); + $$ = context->intermediate.addConstantUnion(constArray, t, @1); } else $$ = context->intermediate.addSymbol(variable->getUniqueId(), - variable->getName(), - variable->getType(), $1.line); + variable->getName(), + variable->getType(), + @1); } ; @@ -209,22 +232,22 @@ primary_expression // check for overflow for constants // if (abs($1.i) >= (1 << 16)) { - context->error($1.line, " integer constant overflow", ""); + context->error(@1, " integer constant overflow", ""); context->recover(); } ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setIConst($1.i); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $1.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), @1); } | FLOATCONSTANT { ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setFConst($1.f); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), $1.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), @1); } | BOOLCONSTANT { ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst($1.b); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $1.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @1); } | LEFT_PAREN expression RIGHT_PAREN { $$ = $2; @@ -236,103 +259,27 @@ postfix_expression $$ = $1; } | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET { - if (!$1->isArray() && !$1->isMatrix() && !$1->isVector()) { - if ($1->getAsSymbolNode()) - context->error($2.line, " left of '[' is not of type array, matrix, or vector ", $1->getAsSymbolNode()->getSymbol().c_str()); - else - context->error($2.line, " left of '[' is not of type array, matrix, or vector ", "expression"); - context->recover(); - } - if ($1->getType().getQualifier() == EvqConst && $3->getQualifier() == EvqConst) { - if ($1->isArray()) { // constant folding for arrays - $$ = context->addConstArrayNode($3->getAsConstantUnion()->getIConst(0), $1, $2.line); - } else if ($1->isVector()) { // constant folding for vectors - TVectorFields fields; - fields.num = 1; - fields.offsets[0] = $3->getAsConstantUnion()->getIConst(0); // need to do it this way because v.xy sends fields integer array - $$ = context->addConstVectorNode(fields, $1, $2.line); - } else if ($1->isMatrix()) { // constant folding for matrices - $$ = context->addConstMatrixNode($3->getAsConstantUnion()->getIConst(0), $1, $2.line); - } - } else { - if ($3->getQualifier() == EvqConst) { - if (($1->isVector() || $1->isMatrix()) && $1->getType().getNominalSize() <= $3->getAsConstantUnion()->getIConst(0) && !$1->isArray() ) { - std::stringstream extraInfoStream; - extraInfoStream << "field selection out of range '" << $3->getAsConstantUnion()->getIConst(0) << "'"; - std::string extraInfo = extraInfoStream.str(); - context->error($2.line, "", "[", extraInfo.c_str()); - context->recover(); - } else { - if ($1->isArray()) { - if ($1->getType().getArraySize() == 0) { - if ($1->getType().getMaxArraySize() <= $3->getAsConstantUnion()->getIConst(0)) { - if (context->arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), $3->getAsConstantUnion()->getIConst(0), true, $2.line)) - context->recover(); - } else { - if (context->arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), 0, false, $2.line)) - context->recover(); - } - } else if ( $3->getAsConstantUnion()->getIConst(0) >= $1->getType().getArraySize()) { - std::stringstream extraInfoStream; - extraInfoStream << "array index out of range '" << $3->getAsConstantUnion()->getIConst(0) << "'"; - std::string extraInfo = extraInfoStream.str(); - context->error($2.line, "", "[", extraInfo.c_str()); - context->recover(); - } - } - $$ = context->intermediate.addIndex(EOpIndexDirect, $1, $3, $2.line); - } - } else { - if ($1->isArray() && $1->getType().getArraySize() == 0) { - context->error($2.line, "", "[", "array must be redeclared with a size before being indexed with a variable"); - context->recover(); - } - - $$ = context->intermediate.addIndex(EOpIndexIndirect, $1, $3, $2.line); - } - } - if ($$ == 0) { - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setFConst(0.0f); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), $2.line); - } else if ($1->isArray()) { - if ($1->getType().getStruct()) - $$->setType(TType($1->getType().getStruct(), $1->getType().getTypeName())); - else - $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, $1->getNominalSize(), $1->isMatrix())); - - if ($1->getType().getQualifier() == EvqConst) - $$->getTypePointer()->setQualifier(EvqConst); - } else if ($1->isMatrix() && $1->getType().getQualifier() == EvqConst) - $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConst, $1->getNominalSize())); - else if ($1->isMatrix()) - $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, $1->getNominalSize())); - else if ($1->isVector() && $1->getType().getQualifier() == EvqConst) - $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConst)); - else if ($1->isVector()) - $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary)); - else - $$->setType($1->getType()); + $$ = context->addIndexExpression($1, @2, $3); } | function_call { $$ = $1; } - | postfix_expression DOT FIELD_SELECTION { + | postfix_expression DOT identifier { if ($1->isArray()) { - context->error($3.line, "cannot apply dot operator to an array", "."); + context->error(@3, "cannot apply dot operator to an array", "."); context->recover(); } if ($1->isVector()) { TVectorFields fields; - if (! context->parseVectorFields(*$3.string, $1->getNominalSize(), fields, $3.line)) { + if (! context->parseVectorFields(*$3.string, $1->getNominalSize(), fields, @3)) { fields.num = 1; fields.offsets[0] = 0; context->recover(); } if ($1->getType().getQualifier() == EvqConst) { // constant folding for vector fields - $$ = context->addConstVectorNode(fields, $1, $3.line); + $$ = context->addConstVectorNode(fields, $1, @3); if ($$ == 0) { context->recover(); $$ = $1; @@ -341,13 +288,13 @@ postfix_expression $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConst, (int) (*$3.string).size())); } else { TString vectorString = *$3.string; - TIntermTyped* index = context->intermediate.addSwizzle(fields, $3.line); - $$ = context->intermediate.addIndex(EOpVectorSwizzle, $1, index, $2.line); + TIntermTyped* index = context->intermediate.addSwizzle(fields, @3); + $$ = context->intermediate.addIndex(EOpVectorSwizzle, $1, index, @2); $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, (int) vectorString.size())); } } else if ($1->isMatrix()) { TMatrixFields fields; - if (! context->parseMatrixFields(*$3.string, $1->getNominalSize(), fields, $3.line)) { + if (! context->parseMatrixFields(*$3.string, $1->getNominalSize(), fields, @3)) { fields.wholeRow = false; fields.wholeCol = false; fields.row = 0; @@ -356,84 +303,78 @@ postfix_expression } if (fields.wholeRow || fields.wholeCol) { - context->error($2.line, " non-scalar fields not implemented yet", "."); + context->error(@2, " non-scalar fields not implemented yet", "."); context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setIConst(0); - TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $3.line); - $$ = context->intermediate.addIndex(EOpIndexDirect, $1, index, $2.line); + TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), @3); + $$ = context->intermediate.addIndex(EOpIndexDirect, $1, index, @2); $$->setType(TType($1->getBasicType(), $1->getPrecision(),EvqTemporary, $1->getNominalSize())); } else { ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setIConst(fields.col * $1->getNominalSize() + fields.row); - TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $3.line); - $$ = context->intermediate.addIndex(EOpIndexDirect, $1, index, $2.line); + TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), @3); + $$ = context->intermediate.addIndex(EOpIndexDirect, $1, index, @2); $$->setType(TType($1->getBasicType(), $1->getPrecision())); } } else if ($1->getBasicType() == EbtStruct) { bool fieldFound = false; - const TTypeList* fields = $1->getType().getStruct(); - if (fields == 0) { - context->error($2.line, "structure has no fields", "Internal Error"); - context->recover(); - $$ = $1; - } else { - unsigned int i; - for (i = 0; i < fields->size(); ++i) { - if ((*fields)[i].type->getFieldName() == *$3.string) { - fieldFound = true; - break; - } - } - if (fieldFound) { - if ($1->getType().getQualifier() == EvqConst) { - $$ = context->addConstStruct(*$3.string, $1, $2.line); - if ($$ == 0) { - context->recover(); - $$ = $1; - } - else { - $$->setType(*(*fields)[i].type); - // change the qualifier of the return type, not of the structure field - // as the structure definition is shared between various structures. - $$->getTypePointer()->setQualifier(EvqConst); - } - } else { - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setIConst(i); - TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, *(*fields)[i].type, $3.line); - $$ = context->intermediate.addIndex(EOpIndexDirectStruct, $1, index, $2.line); - $$->setType(*(*fields)[i].type); - } - } else { - context->error($2.line, " no such field in structure", $3.string->c_str()); - context->recover(); - $$ = $1; + const TFieldList& fields = $1->getType().getStruct()->fields(); + unsigned int i; + for (i = 0; i < fields.size(); ++i) { + if (fields[i]->name() == *$3.string) { + fieldFound = true; + break; } } + if (fieldFound) { + if ($1->getType().getQualifier() == EvqConst) { + $$ = context->addConstStruct(*$3.string, $1, @2); + if ($$ == 0) { + context->recover(); + $$ = $1; + } + else { + $$->setType(*fields[i]->type()); + // change the qualifier of the return type, not of the structure field + // as the structure definition is shared between various structures. + $$->getTypePointer()->setQualifier(EvqConst); + } + } else { + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setIConst(i); + TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, *fields[i]->type(), @3); + $$ = context->intermediate.addIndex(EOpIndexDirectStruct, $1, index, @2); + $$->setType(*fields[i]->type()); + } + } else { + context->error(@2, " no such field in structure", $3.string->c_str()); + context->recover(); + $$ = $1; + } } else { - context->error($2.line, " field selection requires structure, vector, or matrix on left hand side", $3.string->c_str()); + context->error(@2, " field selection requires structure, vector, or matrix on left hand side", $3.string->c_str()); context->recover(); $$ = $1; } // don't delete $3.string, it's from the pool } | postfix_expression INC_OP { - if (context->lValueErrorCheck($2.line, "++", $1)) + if (context->lValueErrorCheck(@2, "++", $1)) context->recover(); - $$ = context->intermediate.addUnaryMath(EOpPostIncrement, $1, $2.line, context->symbolTable); + $$ = context->intermediate.addUnaryMath(EOpPostIncrement, $1, @2, context->symbolTable); if ($$ == 0) { - context->unaryOpError($2.line, "++", $1->getCompleteString()); + context->unaryOpError(@2, "++", $1->getCompleteString()); context->recover(); $$ = $1; } } | postfix_expression DEC_OP { - if (context->lValueErrorCheck($2.line, "--", $1)) + if (context->lValueErrorCheck(@2, "--", $1)) context->recover(); - $$ = context->intermediate.addUnaryMath(EOpPostDecrement, $1, $2.line, context->symbolTable); + $$ = context->intermediate.addUnaryMath(EOpPostDecrement, $1, @2, context->symbolTable); if ($$ == 0) { - context->unaryOpError($2.line, "--", $1->getCompleteString()); + context->unaryOpError(@2, "--", $1->getCompleteString()); context->recover(); $$ = $1; } @@ -461,18 +402,18 @@ function_call // Their parameters will be verified algorithmically. // TType type(EbtVoid, EbpUndefined); // use this to get the type back - if (context->constructorErrorCheck($1.line, $1.intermNode, *fnCall, op, &type)) { + if (context->constructorErrorCheck(@1, $1.intermNode, *fnCall, op, &type)) { $$ = 0; } else { // // It's a constructor, of type 'type'. // - $$ = context->addConstructor($1.intermNode, &type, op, fnCall, $1.line); + $$ = context->addConstructor($1.intermNode, &type, op, fnCall, @1); } if ($$ == 0) { context->recover(); - $$ = context->intermediate.setAggregateOperator(0, op, $1.line); + $$ = context->intermediate.setAggregateOperator(0, op, @1); } $$->setType(type); } else { @@ -481,13 +422,13 @@ function_call // const TFunction* fnCandidate; bool builtIn; - fnCandidate = context->findFunction($1.line, fnCall, &builtIn); + fnCandidate = context->findFunction(@1, fnCall, &builtIn); if (fnCandidate) { // // A declared function. // if (builtIn && !fnCandidate->getExtension().empty() && - context->extensionErrorCheck($1.line, fnCandidate->getExtension())) { + context->extensionErrorCheck(@1, fnCandidate->getExtension())) { context->recover(); } op = fnCandidate->getBuiltInOp(); @@ -499,7 +440,7 @@ function_call // // Treat it like a built-in unary operator. // - $$ = context->intermediate.addUnaryMath(op, $1.intermNode, 0, context->symbolTable); + $$ = context->intermediate.addUnaryMath(op, $1.intermNode, @1, context->symbolTable); if ($$ == 0) { std::stringstream extraInfoStream; extraInfoStream << "built in unary operator function. Type: " << static_cast($1.intermNode)->getCompleteString(); @@ -508,12 +449,12 @@ function_call YYERROR; } } else { - $$ = context->intermediate.setAggregateOperator($1.intermAggregate, op, $1.line); + $$ = context->intermediate.setAggregateOperator($1.intermAggregate, op, @1); } } else { // This is a real function call - $$ = context->intermediate.setAggregateOperator($1.intermAggregate, EOpFunctionCall, $1.line); + $$ = context->intermediate.setAggregateOperator($1.intermAggregate, EOpFunctionCall, @1); $$->setType(fnCandidate->getReturnType()); // this is how we know whether the given function is a builtIn function or a user defined function @@ -540,7 +481,7 @@ function_call // Put on a dummy node for error recovery ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setFConst(0.0f); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), $1.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), @1); context->recover(); } } @@ -553,7 +494,7 @@ function_call_or_method $$ = $1; } | postfix_expression DOT function_call_generic { - context->error($3.line, "methods are not supported", ""); + context->error(@3, "methods are not supported", ""); context->recover(); $$ = $3; } @@ -562,11 +503,9 @@ function_call_or_method function_call_generic : function_call_header_with_parameters RIGHT_PAREN { $$ = $1; - $$.line = $2.line; } | function_call_header_no_parameters RIGHT_PAREN { $$ = $1; - $$.line = $2.line; } ; @@ -592,7 +531,7 @@ function_call_header_with_parameters TParameter param = { 0, new TType($3->getType()) }; $1.function->addParameter(param); $$.function = $1.function; - $$.intermNode = context->intermediate.growAggregate($1.intermNode, $3, $2.line); + $$.intermNode = context->intermediate.growAggregate($1.intermNode, $3, @2); } ; @@ -617,39 +556,39 @@ function_identifier case EbtFloat: if ($1.matrix) { switch($1.size) { - case 2: op = EOpConstructMat2; break; - case 3: op = EOpConstructMat3; break; - case 4: op = EOpConstructMat4; break; + case 2: op = EOpConstructMat2; break; + case 3: op = EOpConstructMat3; break; + case 4: op = EOpConstructMat4; break; } } else { switch($1.size) { - case 1: op = EOpConstructFloat; break; - case 2: op = EOpConstructVec2; break; - case 3: op = EOpConstructVec3; break; - case 4: op = EOpConstructVec4; break; + case 1: op = EOpConstructFloat; break; + case 2: op = EOpConstructVec2; break; + case 3: op = EOpConstructVec3; break; + case 4: op = EOpConstructVec4; break; } } break; case EbtInt: switch($1.size) { - case 1: op = EOpConstructInt; break; - case 2: FRAG_VERT_ONLY("ivec2", $1.line); op = EOpConstructIVec2; break; - case 3: FRAG_VERT_ONLY("ivec3", $1.line); op = EOpConstructIVec3; break; - case 4: FRAG_VERT_ONLY("ivec4", $1.line); op = EOpConstructIVec4; break; + case 1: op = EOpConstructInt; break; + case 2: op = EOpConstructIVec2; break; + case 3: op = EOpConstructIVec3; break; + case 4: op = EOpConstructIVec4; break; } break; case EbtBool: switch($1.size) { - case 1: op = EOpConstructBool; break; - case 2: FRAG_VERT_ONLY("bvec2", $1.line); op = EOpConstructBVec2; break; - case 3: FRAG_VERT_ONLY("bvec3", $1.line); op = EOpConstructBVec3; break; - case 4: FRAG_VERT_ONLY("bvec4", $1.line); op = EOpConstructBVec4; break; + case 1: op = EOpConstructBool; break; + case 2: op = EOpConstructBVec2; break; + case 3: op = EOpConstructBVec3; break; + case 4: op = EOpConstructBVec4; break; } break; default: break; } if (op == EOpNull) { - context->error($1.line, "cannot construct this type", getBasicString($1.type)); + context->error(@1, "cannot construct this type", getBasicString($1.type)); context->recover(); $1.type = EbtFloat; op = EOpConstructFloat; @@ -661,14 +600,7 @@ function_identifier $$ = function; } | IDENTIFIER { - if (context->reservedErrorCheck($1.line, *$1.string)) - context->recover(); - TType type(EbtVoid, EbpUndefined); - TFunction *function = new TFunction($1.string, type); - $$ = function; - } - | FIELD_SELECTION { - if (context->reservedErrorCheck($1.line, *$1.string)) + if (context->reservedErrorCheck(@1, *$1.string)) context->recover(); TType type(EbtVoid, EbpUndefined); TFunction *function = new TFunction($1.string, type); @@ -681,28 +613,28 @@ unary_expression $$ = $1; } | INC_OP unary_expression { - if (context->lValueErrorCheck($1.line, "++", $2)) + if (context->lValueErrorCheck(@1, "++", $2)) context->recover(); - $$ = context->intermediate.addUnaryMath(EOpPreIncrement, $2, $1.line, context->symbolTable); + $$ = context->intermediate.addUnaryMath(EOpPreIncrement, $2, @1, context->symbolTable); if ($$ == 0) { - context->unaryOpError($1.line, "++", $2->getCompleteString()); + context->unaryOpError(@1, "++", $2->getCompleteString()); context->recover(); $$ = $2; } } | DEC_OP unary_expression { - if (context->lValueErrorCheck($1.line, "--", $2)) + if (context->lValueErrorCheck(@1, "--", $2)) context->recover(); - $$ = context->intermediate.addUnaryMath(EOpPreDecrement, $2, $1.line, context->symbolTable); + $$ = context->intermediate.addUnaryMath(EOpPreDecrement, $2, @1, context->symbolTable); if ($$ == 0) { - context->unaryOpError($1.line, "--", $2->getCompleteString()); + context->unaryOpError(@1, "--", $2->getCompleteString()); context->recover(); $$ = $2; } } | unary_operator unary_expression { if ($1.op != EOpNull) { - $$ = context->intermediate.addUnaryMath($1.op, $2, $1.line, context->symbolTable); + $$ = context->intermediate.addUnaryMath($1.op, $2, @1, context->symbolTable); if ($$ == 0) { const char* errorOp = ""; switch($1.op) { @@ -710,7 +642,7 @@ unary_expression case EOpLogicalNot: errorOp = "!"; break; default: break; } - context->unaryOpError($1.line, errorOp, $2->getCompleteString()); + context->unaryOpError(@1, errorOp, $2->getCompleteString()); context->recover(); $$ = $2; } @@ -721,28 +653,26 @@ unary_expression // Grammar Note: No traditional style type casts. unary_operator - : PLUS { $$.line = $1.line; $$.op = EOpNull; } - | DASH { $$.line = $1.line; $$.op = EOpNegative; } - | BANG { $$.line = $1.line; $$.op = EOpLogicalNot; } + : PLUS { $$.op = EOpNull; } + | DASH { $$.op = EOpNegative; } + | BANG { $$.op = EOpLogicalNot; } ; // Grammar Note: No '*' or '&' unary ops. Pointers are not supported. multiplicative_expression : unary_expression { $$ = $1; } | multiplicative_expression STAR unary_expression { - FRAG_VERT_ONLY("*", $2.line); - $$ = context->intermediate.addBinaryMath(EOpMul, $1, $3, $2.line, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpMul, $1, $3, @2, context->symbolTable); if ($$ == 0) { - context->binaryOpError($2.line, "*", $1->getCompleteString(), $3->getCompleteString()); + context->binaryOpError(@2, "*", $1->getCompleteString(), $3->getCompleteString()); context->recover(); $$ = $1; } } | multiplicative_expression SLASH unary_expression { - FRAG_VERT_ONLY("/", $2.line); - $$ = context->intermediate.addBinaryMath(EOpDiv, $1, $3, $2.line, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpDiv, $1, $3, @2, context->symbolTable); if ($$ == 0) { - context->binaryOpError($2.line, "/", $1->getCompleteString(), $3->getCompleteString()); + context->binaryOpError(@2, "/", $1->getCompleteString(), $3->getCompleteString()); context->recover(); $$ = $1; } @@ -752,17 +682,17 @@ multiplicative_expression additive_expression : multiplicative_expression { $$ = $1; } | additive_expression PLUS multiplicative_expression { - $$ = context->intermediate.addBinaryMath(EOpAdd, $1, $3, $2.line, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpAdd, $1, $3, @2, context->symbolTable); if ($$ == 0) { - context->binaryOpError($2.line, "+", $1->getCompleteString(), $3->getCompleteString()); + context->binaryOpError(@2, "+", $1->getCompleteString(), $3->getCompleteString()); context->recover(); $$ = $1; } } | additive_expression DASH multiplicative_expression { - $$ = context->intermediate.addBinaryMath(EOpSub, $1, $3, $2.line, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpSub, $1, $3, @2, context->symbolTable); if ($$ == 0) { - context->binaryOpError($2.line, "-", $1->getCompleteString(), $3->getCompleteString()); + context->binaryOpError(@2, "-", $1->getCompleteString(), $3->getCompleteString()); context->recover(); $$ = $1; } @@ -776,43 +706,43 @@ shift_expression relational_expression : shift_expression { $$ = $1; } | relational_expression LEFT_ANGLE shift_expression { - $$ = context->intermediate.addBinaryMath(EOpLessThan, $1, $3, $2.line, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpLessThan, $1, $3, @2, context->symbolTable); if ($$ == 0) { - context->binaryOpError($2.line, "<", $1->getCompleteString(), $3->getCompleteString()); + context->binaryOpError(@2, "<", $1->getCompleteString(), $3->getCompleteString()); context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); } } | relational_expression RIGHT_ANGLE shift_expression { - $$ = context->intermediate.addBinaryMath(EOpGreaterThan, $1, $3, $2.line, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpGreaterThan, $1, $3, @2, context->symbolTable); if ($$ == 0) { - context->binaryOpError($2.line, ">", $1->getCompleteString(), $3->getCompleteString()); + context->binaryOpError(@2, ">", $1->getCompleteString(), $3->getCompleteString()); context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); } } | relational_expression LE_OP shift_expression { - $$ = context->intermediate.addBinaryMath(EOpLessThanEqual, $1, $3, $2.line, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpLessThanEqual, $1, $3, @2, context->symbolTable); if ($$ == 0) { - context->binaryOpError($2.line, "<=", $1->getCompleteString(), $3->getCompleteString()); + context->binaryOpError(@2, "<=", $1->getCompleteString(), $3->getCompleteString()); context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); } } | relational_expression GE_OP shift_expression { - $$ = context->intermediate.addBinaryMath(EOpGreaterThanEqual, $1, $3, $2.line, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpGreaterThanEqual, $1, $3, @2, context->symbolTable); if ($$ == 0) { - context->binaryOpError($2.line, ">=", $1->getCompleteString(), $3->getCompleteString()); + context->binaryOpError(@2, ">=", $1->getCompleteString(), $3->getCompleteString()); context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); } } ; @@ -820,23 +750,23 @@ relational_expression equality_expression : relational_expression { $$ = $1; } | equality_expression EQ_OP relational_expression { - $$ = context->intermediate.addBinaryMath(EOpEqual, $1, $3, $2.line, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpEqual, $1, $3, @2, context->symbolTable); if ($$ == 0) { - context->binaryOpError($2.line, "==", $1->getCompleteString(), $3->getCompleteString()); + context->binaryOpError(@2, "==", $1->getCompleteString(), $3->getCompleteString()); context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); } } | equality_expression NE_OP relational_expression { - $$ = context->intermediate.addBinaryMath(EOpNotEqual, $1, $3, $2.line, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpNotEqual, $1, $3, @2, context->symbolTable); if ($$ == 0) { - context->binaryOpError($2.line, "!=", $1->getCompleteString(), $3->getCompleteString()); + context->binaryOpError(@2, "!=", $1->getCompleteString(), $3->getCompleteString()); context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); } } ; @@ -856,13 +786,13 @@ inclusive_or_expression logical_and_expression : inclusive_or_expression { $$ = $1; } | logical_and_expression AND_OP inclusive_or_expression { - $$ = context->intermediate.addBinaryMath(EOpLogicalAnd, $1, $3, $2.line, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpLogicalAnd, $1, $3, @2, context->symbolTable); if ($$ == 0) { - context->binaryOpError($2.line, "&&", $1->getCompleteString(), $3->getCompleteString()); + context->binaryOpError(@2, "&&", $1->getCompleteString(), $3->getCompleteString()); context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); } } ; @@ -870,13 +800,13 @@ logical_and_expression logical_xor_expression : logical_and_expression { $$ = $1; } | logical_xor_expression XOR_OP logical_and_expression { - $$ = context->intermediate.addBinaryMath(EOpLogicalXor, $1, $3, $2.line, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpLogicalXor, $1, $3, @2, context->symbolTable); if ($$ == 0) { - context->binaryOpError($2.line, "^^", $1->getCompleteString(), $3->getCompleteString()); + context->binaryOpError(@2, "^^", $1->getCompleteString(), $3->getCompleteString()); context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); } } ; @@ -884,13 +814,13 @@ logical_xor_expression logical_or_expression : logical_xor_expression { $$ = $1; } | logical_or_expression OR_OP logical_xor_expression { - $$ = context->intermediate.addBinaryMath(EOpLogicalOr, $1, $3, $2.line, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpLogicalOr, $1, $3, @2, context->symbolTable); if ($$ == 0) { - context->binaryOpError($2.line, "||", $1->getCompleteString(), $3->getCompleteString()); + context->binaryOpError(@2, "||", $1->getCompleteString(), $3->getCompleteString()); context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); } } ; @@ -898,15 +828,15 @@ logical_or_expression conditional_expression : logical_or_expression { $$ = $1; } | logical_or_expression QUESTION expression COLON assignment_expression { - if (context->boolErrorCheck($2.line, $1)) + if (context->boolErrorCheck(@2, $1)) context->recover(); - $$ = context->intermediate.addSelection($1, $3, $5, $2.line); + $$ = context->intermediate.addSelection($1, $3, $5, @2); if ($3->getType() != $5->getType()) $$ = 0; if ($$ == 0) { - context->binaryOpError($2.line, ":", $3->getCompleteString(), $5->getCompleteString()); + context->binaryOpError(@2, ":", $3->getCompleteString(), $5->getCompleteString()); context->recover(); $$ = $5; } @@ -916,11 +846,11 @@ conditional_expression assignment_expression : conditional_expression { $$ = $1; } | unary_expression assignment_operator assignment_expression { - if (context->lValueErrorCheck($2.line, "assign", $1)) + if (context->lValueErrorCheck(@2, "assign", $1)) context->recover(); - $$ = context->intermediate.addAssign($2.op, $1, $3, $2.line); + $$ = context->intermediate.addAssign($2.op, $1, $3, @2); if ($$ == 0) { - context->assignError($2.line, "assign", $1->getCompleteString(), $3->getCompleteString()); + context->assignError(@2, "assign", $1->getCompleteString(), $3->getCompleteString()); context->recover(); $$ = $1; } @@ -928,11 +858,11 @@ assignment_expression ; assignment_operator - : EQUAL { $$.line = $1.line; $$.op = EOpAssign; } - | MUL_ASSIGN { FRAG_VERT_ONLY("*=", $1.line); $$.line = $1.line; $$.op = EOpMulAssign; } - | DIV_ASSIGN { FRAG_VERT_ONLY("/=", $1.line); $$.line = $1.line; $$.op = EOpDivAssign; } - | ADD_ASSIGN { $$.line = $1.line; $$.op = EOpAddAssign; } - | SUB_ASSIGN { $$.line = $1.line; $$.op = EOpSubAssign; } + : EQUAL { $$.op = EOpAssign; } + | MUL_ASSIGN { $$.op = EOpMulAssign; } + | DIV_ASSIGN { $$.op = EOpDivAssign; } + | ADD_ASSIGN { $$.op = EOpAddAssign; } + | SUB_ASSIGN { $$.op = EOpSubAssign; } ; expression @@ -940,9 +870,9 @@ expression $$ = $1; } | expression COMMA assignment_expression { - $$ = context->intermediate.addComma($1, $3, $2.line); + $$ = context->intermediate.addComma($1, $3, @2); if ($$ == 0) { - context->binaryOpError($2.line, ",", $1->getCompleteString(), $3->getCompleteString()); + context->binaryOpError(@2, ",", $1->getCompleteString(), $3->getCompleteString()); context->recover(); $$ = $3; } @@ -970,13 +900,13 @@ declaration const TParameter ¶m = function.getParam(i); if (param.name != 0) { - TVariable *variable = new TVariable(param.name, *param.type); + TVariable variable(param.name, *param.type); - prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), $1.line), $1.line); + prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(variable.getUniqueId(), variable.getName(), variable.getType(), @1), @1); } else { - prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(0, "", *param.type, $1.line), $1.line); + prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(0, "", *param.type, @1), @1); } } @@ -992,11 +922,11 @@ declaration } | PRECISION precision_qualifier type_specifier_no_prec SEMICOLON { if (($2 == EbpHigh) && (context->shaderType == SH_FRAGMENT_SHADER) && !context->fragmentPrecisionHigh) { - context->error($1.line, "precision is not supported in fragment shader", "highp"); + context->error(@1, "precision is not supported in fragment shader", "highp"); context->recover(); } if (!context->symbolTable.setDefaultPrecision( $3, $2 )) { - context->error($1.line, "illegal type argument for default precision qualifier", getBasicString($3.type)); + context->error(@1, "illegal type argument for default precision qualifier", getBasicString($3.type)); context->recover(); } $$ = 0; @@ -1016,24 +946,41 @@ function_prototype TFunction* prevDec = static_cast(context->symbolTable.find($1->getMangledName())); if (prevDec) { if (prevDec->getReturnType() != $1->getReturnType()) { - context->error($2.line, "overloaded functions must have the same return type", $1->getReturnType().getBasicString()); + context->error(@2, "overloaded functions must have the same return type", $1->getReturnType().getBasicString()); context->recover(); } for (size_t i = 0; i < prevDec->getParamCount(); ++i) { if (prevDec->getParam(i).type->getQualifier() != $1->getParam(i).type->getQualifier()) { - context->error($2.line, "overloaded functions must have the same parameter qualifiers", $1->getParam(i).type->getQualifierString()); + context->error(@2, "overloaded functions must have the same parameter qualifiers", $1->getParam(i).type->getQualifierString()); context->recover(); } } } + // + // Check for previously declared variables using the same name. + // + TSymbol *prevSym = context->symbolTable.find($1->getName()); + if (prevSym) + { + if (!prevSym->isFunction()) + { + context->error(@2, "redefinition", $1->getName().c_str(), "function"); + context->recover(); + } + } + else + { + // Insert the unmangled name to detect potential future redefinition as a variable. + context->symbolTable.getOuterLevel()->insert($1->getName(), *$1); + } + // // If this is a redeclaration, it could also be a definition, // in which case, we want to use the variable names from this one, and not the one that's // being redeclared. So, pass back up this declaration, not the one in the symbol table. // $$.function = $1; - $$.line = $2.line; // We're at the inner scope level of the function's arguments and body statement. // Add the function prototype to the surrounding scope instead. @@ -1069,7 +1016,7 @@ function_header_with_parameters // // This parameter > first is void // - context->error($2.line, "cannot be an argument type except for '(void)'", "void"); + context->error(@2, "cannot be an argument type except for '(void)'", "void"); context->recover(); delete $3.param.type; } else { @@ -1083,11 +1030,11 @@ function_header_with_parameters function_header : fully_specified_type IDENTIFIER LEFT_PAREN { if ($1.qualifier != EvqGlobal && $1.qualifier != EvqTemporary) { - context->error($2.line, "no qualifiers allowed for function return", getQualifierString($1.qualifier)); + context->error(@2, "no qualifiers allowed for function return", getQualifierString($1.qualifier)); context->recover(); } // make sure a sampler is not involved as well... - if (context->structQualifierErrorCheck($2.line, $1)) + if (context->structQualifierErrorCheck(@2, $1)) context->recover(); // Add the function as a prototype after parsing it (we do not support recursion) @@ -1102,33 +1049,31 @@ function_header parameter_declarator // Type + name - : type_specifier IDENTIFIER { + : type_specifier identifier { if ($1.type == EbtVoid) { - context->error($2.line, "illegal use of type 'void'", $2.string->c_str()); + context->error(@2, "illegal use of type 'void'", $2.string->c_str()); context->recover(); } - if (context->reservedErrorCheck($2.line, *$2.string)) + if (context->reservedErrorCheck(@2, *$2.string)) context->recover(); TParameter param = {$2.string, new TType($1)}; - $$.line = $2.line; $$.param = param; } - | type_specifier IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET { + | type_specifier identifier LEFT_BRACKET constant_expression RIGHT_BRACKET { // Check that we can make an array out of this type - if (context->arrayTypeErrorCheck($3.line, $1)) + if (context->arrayTypeErrorCheck(@3, $1)) context->recover(); - if (context->reservedErrorCheck($2.line, *$2.string)) + if (context->reservedErrorCheck(@2, *$2.string)) context->recover(); int size; - if (context->arraySizeErrorCheck($3.line, $4, size)) + if (context->arraySizeErrorCheck(@3, $4, size)) context->recover(); $1.setArray(true, size); TType* type = new TType($1); TParameter param = { $2.string, type }; - $$.line = $2.line; $$.param = param; } ; @@ -1144,14 +1089,14 @@ parameter_declaration // : type_qualifier parameter_qualifier parameter_declarator { $$ = $3; - if (context->paramErrorCheck($3.line, $1.qualifier, $2, $$.param.type)) + if (context->paramErrorCheck(@3, $1.qualifier, $2, $$.param.type)) context->recover(); } | parameter_qualifier parameter_declarator { $$ = $2; - if (context->parameterSamplerErrorCheck($2.line, $1, *$2.param.type)) + if (context->parameterSamplerErrorCheck(@2, $1, *$2.param.type)) context->recover(); - if (context->paramErrorCheck($2.line, EvqTemporary, $1, $$.param.type)) + if (context->paramErrorCheck(@2, EvqTemporary, $1, $$.param.type)) context->recover(); } // @@ -1159,14 +1104,14 @@ parameter_declaration // | type_qualifier parameter_qualifier parameter_type_specifier { $$ = $3; - if (context->paramErrorCheck($3.line, $1.qualifier, $2, $$.param.type)) + if (context->paramErrorCheck(@3, $1.qualifier, $2, $$.param.type)) context->recover(); } | parameter_qualifier parameter_type_specifier { $$ = $2; - if (context->parameterSamplerErrorCheck($2.line, $1, *$2.param.type)) + if (context->parameterSamplerErrorCheck(@2, $1, *$2.param.type)) context->recover(); - if (context->paramErrorCheck($2.line, EvqTemporary, $1, $$.param.type)) + if (context->paramErrorCheck(@2, EvqTemporary, $1, $$.param.type)) context->recover(); } ; @@ -1197,83 +1142,83 @@ init_declarator_list : single_declaration { $$ = $1; } - | init_declarator_list COMMA IDENTIFIER { + | init_declarator_list COMMA identifier { if ($1.type.type == EbtInvariant && !$3.symbol) { - context->error($3.line, "undeclared identifier declared as invariant", $3.string->c_str()); + context->error(@3, "undeclared identifier declared as invariant", $3.string->c_str()); context->recover(); } - TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$3.string, TType($1.type), $3.line); - $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, symbol, $3.line); + TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$3.string, TType($1.type), @3); + $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, symbol, @3); - if (context->structQualifierErrorCheck($3.line, $$.type)) + if (context->structQualifierErrorCheck(@3, $$.type)) context->recover(); - if (context->nonInitConstErrorCheck($3.line, *$3.string, $$.type, false)) + if (context->nonInitConstErrorCheck(@3, *$3.string, $$.type, false)) context->recover(); TVariable* variable = 0; - if (context->nonInitErrorCheck($3.line, *$3.string, $$.type, variable)) + if (context->nonInitErrorCheck(@3, *$3.string, $$.type, variable)) context->recover(); if (symbol && variable) symbol->setId(variable->getUniqueId()); } - | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET RIGHT_BRACKET { - if (context->structQualifierErrorCheck($3.line, $1.type)) + | init_declarator_list COMMA identifier LEFT_BRACKET RIGHT_BRACKET { + if (context->structQualifierErrorCheck(@3, $1.type)) context->recover(); - if (context->nonInitConstErrorCheck($3.line, *$3.string, $1.type, true)) + if (context->nonInitConstErrorCheck(@3, *$3.string, $1.type, true)) context->recover(); $$ = $1; - if (context->arrayTypeErrorCheck($4.line, $1.type) || context->arrayQualifierErrorCheck($4.line, $1.type)) + if (context->arrayTypeErrorCheck(@4, $1.type) || context->arrayQualifierErrorCheck(@4, $1.type)) context->recover(); else { $1.type.setArray(true); TVariable* variable; - if (context->arrayErrorCheck($4.line, *$3.string, $1.type, variable)) + if (context->arrayErrorCheck(@4, *$3.string, $1.type, variable)) context->recover(); } } - | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET { - if (context->structQualifierErrorCheck($3.line, $1.type)) + | init_declarator_list COMMA identifier LEFT_BRACKET constant_expression RIGHT_BRACKET { + if (context->structQualifierErrorCheck(@3, $1.type)) context->recover(); - if (context->nonInitConstErrorCheck($3.line, *$3.string, $1.type, true)) + if (context->nonInitConstErrorCheck(@3, *$3.string, $1.type, true)) context->recover(); $$ = $1; - if (context->arrayTypeErrorCheck($4.line, $1.type) || context->arrayQualifierErrorCheck($4.line, $1.type)) + if (context->arrayTypeErrorCheck(@4, $1.type) || context->arrayQualifierErrorCheck(@4, $1.type)) context->recover(); else { int size; - if (context->arraySizeErrorCheck($4.line, $5, size)) + if (context->arraySizeErrorCheck(@4, $5, size)) context->recover(); $1.type.setArray(true, size); TVariable* variable = 0; - if (context->arrayErrorCheck($4.line, *$3.string, $1.type, variable)) + if (context->arrayErrorCheck(@4, *$3.string, $1.type, variable)) context->recover(); TType type = TType($1.type); type.setArraySize(size); - $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, context->intermediate.addSymbol(variable ? variable->getUniqueId() : 0, *$3.string, type, $3.line), $3.line); + $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, context->intermediate.addSymbol(variable ? variable->getUniqueId() : 0, *$3.string, type, @3), @3); } } - | init_declarator_list COMMA IDENTIFIER EQUAL initializer { - if (context->structQualifierErrorCheck($3.line, $1.type)) + | init_declarator_list COMMA identifier EQUAL initializer { + if (context->structQualifierErrorCheck(@3, $1.type)) context->recover(); $$ = $1; TIntermNode* intermNode; - if (!context->executeInitializer($3.line, *$3.string, $1.type, $5, intermNode)) { + if (!context->executeInitializer(@3, *$3.string, $1.type, $5, intermNode)) { // // build the intermediate representation // if (intermNode) - $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, intermNode, $4.line); + $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, intermNode, @4); else $$.intermAggregate = $1.intermAggregate; } else { @@ -1286,79 +1231,79 @@ init_declarator_list single_declaration : fully_specified_type { $$.type = $1; - $$.intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, "", TType($1), $1.line), $1.line); + $$.intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, "", TType($1), @1), @1); } - | fully_specified_type IDENTIFIER { - TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), $2.line); - $$.intermAggregate = context->intermediate.makeAggregate(symbol, $2.line); + | fully_specified_type identifier { + TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), @2); + $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2); - if (context->structQualifierErrorCheck($2.line, $$.type)) + if (context->structQualifierErrorCheck(@2, $$.type)) context->recover(); - if (context->nonInitConstErrorCheck($2.line, *$2.string, $$.type, false)) + if (context->nonInitConstErrorCheck(@2, *$2.string, $$.type, false)) context->recover(); $$.type = $1; TVariable* variable = 0; - if (context->nonInitErrorCheck($2.line, *$2.string, $$.type, variable)) + if (context->nonInitErrorCheck(@2, *$2.string, $$.type, variable)) context->recover(); if (variable && symbol) symbol->setId(variable->getUniqueId()); } - | fully_specified_type IDENTIFIER LEFT_BRACKET RIGHT_BRACKET { - context->error($2.line, "unsized array declarations not supported", $2.string->c_str()); + | fully_specified_type identifier LEFT_BRACKET RIGHT_BRACKET { + context->error(@2, "unsized array declarations not supported", $2.string->c_str()); context->recover(); - TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), $2.line); - $$.intermAggregate = context->intermediate.makeAggregate(symbol, $2.line); + TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), @2); + $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2); $$.type = $1; } - | fully_specified_type IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET { + | fully_specified_type identifier LEFT_BRACKET constant_expression RIGHT_BRACKET { TType type = TType($1); int size; - if (context->arraySizeErrorCheck($2.line, $4, size)) + if (context->arraySizeErrorCheck(@2, $4, size)) context->recover(); type.setArraySize(size); - TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, type, $2.line); - $$.intermAggregate = context->intermediate.makeAggregate(symbol, $2.line); + TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, type, @2); + $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2); - if (context->structQualifierErrorCheck($2.line, $1)) + if (context->structQualifierErrorCheck(@2, $1)) context->recover(); - if (context->nonInitConstErrorCheck($2.line, *$2.string, $1, true)) + if (context->nonInitConstErrorCheck(@2, *$2.string, $1, true)) context->recover(); $$.type = $1; - if (context->arrayTypeErrorCheck($3.line, $1) || context->arrayQualifierErrorCheck($3.line, $1)) + if (context->arrayTypeErrorCheck(@3, $1) || context->arrayQualifierErrorCheck(@3, $1)) context->recover(); else { int size; - if (context->arraySizeErrorCheck($3.line, $4, size)) + if (context->arraySizeErrorCheck(@3, $4, size)) context->recover(); $1.setArray(true, size); TVariable* variable = 0; - if (context->arrayErrorCheck($3.line, *$2.string, $1, variable)) + if (context->arrayErrorCheck(@3, *$2.string, $1, variable)) context->recover(); if (variable && symbol) symbol->setId(variable->getUniqueId()); } } - | fully_specified_type IDENTIFIER EQUAL initializer { - if (context->structQualifierErrorCheck($2.line, $1)) + | fully_specified_type identifier EQUAL initializer { + if (context->structQualifierErrorCheck(@2, $1)) context->recover(); $$.type = $1; TIntermNode* intermNode; - if (!context->executeInitializer($2.line, *$2.string, $1, $4, intermNode)) { + if (!context->executeInitializer(@2, *$2.string, $1, $4, intermNode)) { // // Build intermediate representation // if(intermNode) - $$.intermAggregate = context->intermediate.makeAggregate(intermNode, $3.line); + $$.intermAggregate = context->intermediate.makeAggregate(intermNode, @3); else $$.intermAggregate = 0; } else { @@ -1367,118 +1312,50 @@ single_declaration } } | INVARIANT IDENTIFIER { - VERTEX_ONLY("invariant declaration", $1.line); - if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "invariant varying")) + VERTEX_ONLY("invariant declaration", @1); + if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "invariant varying")) context->recover(); - $$.type.setBasic(EbtInvariant, EvqInvariantVaryingOut, $2.line); + $$.type.setBasic(EbtInvariant, EvqInvariantVaryingOut, @2); if (!$2.symbol) { - context->error($2.line, "undeclared identifier declared as invariant", $2.string->c_str()); + context->error(@2, "undeclared identifier declared as invariant", $2.string->c_str()); context->recover(); $$.intermAggregate = 0; } else { - TIntermSymbol *symbol = context->intermediate.addSymbol(0, *$2.string, TType($$.type), $2.line); - $$.intermAggregate = context->intermediate.makeAggregate(symbol, $2.line); + TIntermSymbol *symbol = context->intermediate.addSymbol(0, *$2.string, TType($$.type), @2); + $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2); } } - -// -// Place holder for the pack/unpack languages. -// -// | buffer_specifier { -// $$.intermAggregate = 0; -// } ; -// Grammar Note: No 'enum', or 'typedef'. - -// -// Place holder for the pack/unpack languages. -// -//%type buffer_declaration -//%type buffer_specifier input_or_output buffer_declaration_list -//buffer_specifier -// : input_or_output LEFT_BRACE buffer_declaration_list RIGHT_BRACE { -// } -// ; -// -//input_or_output -// : INPUT { -// if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "input")) -// context->recover(); -// UNPACK_ONLY("input", $1.line); -// $$.qualifier = EvqInput; -// } -// | OUTPUT { -// if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "output")) -// context->recover(); -// PACK_ONLY("output", $1.line); -// $$.qualifier = EvqOutput; -// } -// ; - -// -// Place holder for the pack/unpack languages. -// -//buffer_declaration_list -// : buffer_declaration { -// } -// | buffer_declaration_list buffer_declaration { -// } -// ; - -// -// Input/output semantics: -// float must be 16 or 32 bits -// float alignment restrictions? -// check for only one input and only one output -// sum of bitfields has to be multiple of 32 -// - -// -// Place holder for the pack/unpack languages. -// -//buffer_declaration -// : type_specifier IDENTIFIER COLON constant_expression SEMICOLON { -// if (context->reservedErrorCheck($2.line, *$2.string, context)) -// context->recover(); -// $$.variable = new TVariable($2.string, $1); -// if (! context->symbolTable.insert(*$$.variable)) { -// context->error($2.line, "redefinition", $$.variable->getName().c_str()); -// context->recover(); -// // don't have to delete $$.variable, the pool pop will take care of it -// } -// } -// ; - fully_specified_type : type_specifier { $$ = $1; if ($1.array) { - context->error($1.line, "not supported", "first-class array"); + context->error(@1, "not supported", "first-class array"); context->recover(); $1.setArray(false); } } | type_qualifier type_specifier { if ($2.array) { - context->error($2.line, "not supported", "first-class array"); + context->error(@2, "not supported", "first-class array"); context->recover(); $2.setArray(false); } if ($1.qualifier == EvqAttribute && ($2.type == EbtBool || $2.type == EbtInt)) { - context->error($2.line, "cannot be bool or int", getQualifierString($1.qualifier)); + context->error(@2, "cannot be bool or int", getQualifierString($1.qualifier)); context->recover(); } if (($1.qualifier == EvqVaryingIn || $1.qualifier == EvqVaryingOut) && ($2.type == EbtBool || $2.type == EbtInt)) { - context->error($2.line, "cannot be bool or int", getQualifierString($1.qualifier)); + context->error(@2, "cannot be bool or int", getQualifierString($1.qualifier)); context->recover(); } $$ = $2; @@ -1488,34 +1365,34 @@ fully_specified_type type_qualifier : CONST_QUAL { - $$.setBasic(EbtVoid, EvqConst, $1.line); + $$.setBasic(EbtVoid, EvqConst, @1); } | ATTRIBUTE { - VERTEX_ONLY("attribute", $1.line); - if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "attribute")) + VERTEX_ONLY("attribute", @1); + if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "attribute")) context->recover(); - $$.setBasic(EbtVoid, EvqAttribute, $1.line); + $$.setBasic(EbtVoid, EvqAttribute, @1); } | VARYING { - if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "varying")) + if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "varying")) context->recover(); if (context->shaderType == SH_VERTEX_SHADER) - $$.setBasic(EbtVoid, EvqVaryingOut, $1.line); + $$.setBasic(EbtVoid, EvqVaryingOut, @1); else - $$.setBasic(EbtVoid, EvqVaryingIn, $1.line); + $$.setBasic(EbtVoid, EvqVaryingIn, @1); } | INVARIANT VARYING { - if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "invariant varying")) + if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "invariant varying")) context->recover(); if (context->shaderType == SH_VERTEX_SHADER) - $$.setBasic(EbtVoid, EvqInvariantVaryingOut, $1.line); + $$.setBasic(EbtVoid, EvqInvariantVaryingOut, @1); else - $$.setBasic(EbtVoid, EvqInvariantVaryingIn, $1.line); + $$.setBasic(EbtVoid, EvqInvariantVaryingIn, @1); } | UNIFORM { - if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "uniform")) + if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "uniform")) context->recover(); - $$.setBasic(EbtVoid, EvqUniform, $1.line); + $$.setBasic(EbtVoid, EvqUniform, @1); } ; @@ -1525,7 +1402,7 @@ type_specifier if ($$.precision == EbpUndefined) { $$.precision = context->symbolTable.getDefaultPrecision($1.type); - if (context->precisionErrorCheck($1.line, $$.precision, $1.type)) { + if (context->precisionErrorCheck(@1, $$.precision, $1.type)) { context->recover(); } } @@ -1555,11 +1432,11 @@ type_specifier_no_prec | type_specifier_nonarray LEFT_BRACKET constant_expression RIGHT_BRACKET { $$ = $1; - if (context->arrayTypeErrorCheck($2.line, $1)) + if (context->arrayTypeErrorCheck(@2, $1)) context->recover(); else { int size; - if (context->arraySizeErrorCheck($2.line, $3, size)) + if (context->arraySizeErrorCheck(@2, $3, size)) context->recover(); $$.setArray(true, size); } @@ -1569,118 +1446,105 @@ type_specifier_no_prec type_specifier_nonarray : VOID_TYPE { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtVoid, qual, $1.line); + $$.setBasic(EbtVoid, qual, @1); } | FLOAT_TYPE { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtFloat, qual, $1.line); + $$.setBasic(EbtFloat, qual, @1); } | INT_TYPE { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtInt, qual, $1.line); + $$.setBasic(EbtInt, qual, @1); } | BOOL_TYPE { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtBool, qual, $1.line); + $$.setBasic(EbtBool, qual, @1); } -// | UNSIGNED INT_TYPE { -// PACK_UNPACK_ONLY("unsigned", $1.line); -// TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; -// $$.setBasic(EbtInt, qual, $1.line); -// } | VEC2 { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtFloat, qual, $1.line); + $$.setBasic(EbtFloat, qual, @1); $$.setAggregate(2); } | VEC3 { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtFloat, qual, $1.line); + $$.setBasic(EbtFloat, qual, @1); $$.setAggregate(3); } | VEC4 { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtFloat, qual, $1.line); + $$.setBasic(EbtFloat, qual, @1); $$.setAggregate(4); } | BVEC2 { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtBool, qual, $1.line); + $$.setBasic(EbtBool, qual, @1); $$.setAggregate(2); } | BVEC3 { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtBool, qual, $1.line); + $$.setBasic(EbtBool, qual, @1); $$.setAggregate(3); } | BVEC4 { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtBool, qual, $1.line); + $$.setBasic(EbtBool, qual, @1); $$.setAggregate(4); } | IVEC2 { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtInt, qual, $1.line); + $$.setBasic(EbtInt, qual, @1); $$.setAggregate(2); } | IVEC3 { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtInt, qual, $1.line); + $$.setBasic(EbtInt, qual, @1); $$.setAggregate(3); } | IVEC4 { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtInt, qual, $1.line); + $$.setBasic(EbtInt, qual, @1); $$.setAggregate(4); } | MATRIX2 { - FRAG_VERT_ONLY("mat2", $1.line); TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtFloat, qual, $1.line); + $$.setBasic(EbtFloat, qual, @1); $$.setAggregate(2, true); } | MATRIX3 { - FRAG_VERT_ONLY("mat3", $1.line); TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtFloat, qual, $1.line); + $$.setBasic(EbtFloat, qual, @1); $$.setAggregate(3, true); } | MATRIX4 { - FRAG_VERT_ONLY("mat4", $1.line); TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtFloat, qual, $1.line); + $$.setBasic(EbtFloat, qual, @1); $$.setAggregate(4, true); } | SAMPLER2D { - FRAG_VERT_ONLY("sampler2D", $1.line); TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtSampler2D, qual, $1.line); + $$.setBasic(EbtSampler2D, qual, @1); } | SAMPLERCUBE { - FRAG_VERT_ONLY("samplerCube", $1.line); TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtSamplerCube, qual, $1.line); + $$.setBasic(EbtSamplerCube, qual, @1); } | SAMPLER_EXTERNAL_OES { if (!context->supportsExtension("GL_OES_EGL_image_external")) { - context->error($1.line, "unsupported type", "samplerExternalOES"); + context->error(@1, "unsupported type", "samplerExternalOES"); context->recover(); } - FRAG_VERT_ONLY("samplerExternalOES", $1.line); TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtSamplerExternalOES, qual, $1.line); + $$.setBasic(EbtSamplerExternalOES, qual, @1); } | SAMPLER2DRECT { if (!context->supportsExtension("GL_ARB_texture_rectangle")) { - context->error($1.line, "unsupported type", "sampler2DRect"); + context->error(@1, "unsupported type", "sampler2DRect"); context->recover(); } - FRAG_VERT_ONLY("sampler2DRect", $1.line); TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtSampler2DRect, qual, $1.line); + $$.setBasic(EbtSampler2DRect, qual, @1); } | struct_specifier { - FRAG_VERT_ONLY("struct", $1.line); $$ = $1; $$.qualifier = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; } @@ -1691,29 +1555,29 @@ type_specifier_nonarray // TType& structure = static_cast($1.symbol)->getType(); TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtStruct, qual, $1.line); + $$.setBasic(EbtStruct, qual, @1); $$.userDef = &structure; } ; struct_specifier - : STRUCT IDENTIFIER LEFT_BRACE { if (context->enterStructDeclaration($2.line, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE { - if (context->reservedErrorCheck($2.line, *$2.string)) + : STRUCT identifier LEFT_BRACE { if (context->enterStructDeclaration(@2, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE { + if (context->reservedErrorCheck(@2, *$2.string)) context->recover(); - TType* structure = new TType($5, *$2.string); + TType* structure = new TType(new TStructure($2.string, $5)); TVariable* userTypeDef = new TVariable($2.string, *structure, true); if (! context->symbolTable.insert(*userTypeDef)) { - context->error($2.line, "redefinition", $2.string->c_str(), "struct"); + context->error(@2, "redefinition", $2.string->c_str(), "struct"); context->recover(); } - $$.setBasic(EbtStruct, EvqTemporary, $1.line); + $$.setBasic(EbtStruct, EvqTemporary, @1); $$.userDef = structure; context->exitStructDeclaration(); } - | STRUCT LEFT_BRACE { if (context->enterStructDeclaration($2.line, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE { - TType* structure = new TType($4, TString("")); - $$.setBasic(EbtStruct, EvqTemporary, $1.line); + | STRUCT LEFT_BRACE { if (context->enterStructDeclaration(@2, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE { + TType* structure = new TType(new TStructure(NewPoolTString(""), $4)); + $$.setBasic(EbtStruct, EvqTemporary, @1); $$.userDef = structure; context->exitStructDeclaration(); } @@ -1725,14 +1589,15 @@ struct_declaration_list } | struct_declaration_list struct_declaration { $$ = $1; - for (unsigned int i = 0; i < $2->size(); ++i) { - for (unsigned int j = 0; j < $$->size(); ++j) { - if ((*$$)[j].type->getFieldName() == (*$2)[i].type->getFieldName()) { - context->error((*$2)[i].line, "duplicate field name in structure:", "struct", (*$2)[i].type->getFieldName().c_str()); + for (size_t i = 0; i < $2->size(); ++i) { + TField* field = (*$2)[i]; + for (size_t j = 0; j < $$->size(); ++j) { + if ((*$$)[j]->name() == field->name()) { + context->error(@2, "duplicate field name in structure:", "struct", field->name().c_str()); context->recover(); } } - $$->push_back((*$2)[i]); + $$->push_back(field); } } ; @@ -1741,14 +1606,14 @@ struct_declaration : type_specifier struct_declarator_list SEMICOLON { $$ = $2; - if (context->voidErrorCheck($1.line, (*$2)[0].type->getFieldName(), $1)) { + if (context->voidErrorCheck(@1, (*$2)[0]->name(), $1)) { context->recover(); } for (unsigned int i = 0; i < $$->size(); ++i) { // // Careful not to replace already known aspects of type, like array-ness // - TType* type = (*$$)[i].type; + TType* type = (*$$)[i]->type(); type->setBasicType($1.type); type->setNominalSize($1.size); type->setMatrix($1.matrix); @@ -1756,26 +1621,23 @@ struct_declaration // don't allow arrays of arrays if (type->isArray()) { - if (context->arrayTypeErrorCheck($1.line, $1)) + if (context->arrayTypeErrorCheck(@1, $1)) context->recover(); } if ($1.array) type->setArraySize($1.arraySize); - if ($1.userDef) { + if ($1.userDef) type->setStruct($1.userDef->getStruct()); - type->setTypeName($1.userDef->getTypeName()); - } - if (context->structNestingErrorCheck($1.line, *type)) { + if (context->structNestingErrorCheck(@1, *(*$$)[i])) context->recover(); - } } } ; struct_declarator_list : struct_declarator { - $$ = NewPoolTTypeList(); + $$ = NewPoolTFieldList(); $$->push_back($1); } | struct_declarator_list COMMA struct_declarator { @@ -1784,26 +1646,24 @@ struct_declarator_list ; struct_declarator - : IDENTIFIER { - if (context->reservedErrorCheck($1.line, *$1.string)) + : identifier { + if (context->reservedErrorCheck(@1, *$1.string)) context->recover(); - $$.type = new TType(EbtVoid, EbpUndefined); - $$.line = $1.line; - $$.type->setFieldName(*$1.string); + TType* type = new TType(EbtVoid, EbpUndefined); + $$ = new TField(type, $1.string); } - | IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET { - if (context->reservedErrorCheck($1.line, *$1.string)) + | identifier LEFT_BRACKET constant_expression RIGHT_BRACKET { + if (context->reservedErrorCheck(@1, *$1.string)) context->recover(); - $$.type = new TType(EbtVoid, EbpUndefined); - $$.line = $1.line; - $$.type->setFieldName(*$1.string); - - int size; - if (context->arraySizeErrorCheck($2.line, $3, size)) + TType* type = new TType(EbtVoid, EbpUndefined); + int size = 0; + if (context->arraySizeErrorCheck(@3, $3, size)) context->recover(); - $$.type->setArraySize(size); + type->setArraySize(size); + + $$ = new TField(type, $1.string); } ; @@ -1835,7 +1695,7 @@ compound_statement | LEFT_BRACE { context->symbolTable.push(); } statement_list { context->symbolTable.pop(); } RIGHT_BRACE { if ($3 != 0) { $3->setOp(EOpSequence); - $3->setEndLine($5.line); + $3->setLine(@$); } $$ = $3; } @@ -1859,7 +1719,7 @@ compound_statement_no_new_scope | LEFT_BRACE statement_list RIGHT_BRACE { if ($2) { $2->setOp(EOpSequence); - $2->setEndLine($3.line); + $2->setLine(@$); } $$ = $2; } @@ -1867,10 +1727,10 @@ compound_statement_no_new_scope statement_list : statement { - $$ = context->intermediate.makeAggregate($1, 0); + $$ = context->intermediate.makeAggregate($1, @$); } | statement_list statement { - $$ = context->intermediate.growAggregate($1, $2, 0); + $$ = context->intermediate.growAggregate($1, $2, @$); } ; @@ -1881,9 +1741,9 @@ expression_statement selection_statement : IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement { - if (context->boolErrorCheck($1.line, $3)) + if (context->boolErrorCheck(@1, $3)) context->recover(); - $$ = context->intermediate.addSelection($3, $5, $1.line); + $$ = context->intermediate.addSelection($3, $5, @1); } ; @@ -1907,14 +1767,14 @@ condition if (context->boolErrorCheck($1->getLine(), $1)) context->recover(); } - | fully_specified_type IDENTIFIER EQUAL initializer { + | fully_specified_type identifier EQUAL initializer { TIntermNode* intermNode; - if (context->structQualifierErrorCheck($2.line, $1)) + if (context->structQualifierErrorCheck(@2, $1)) context->recover(); - if (context->boolErrorCheck($2.line, $1)) + if (context->boolErrorCheck(@2, $1)) context->recover(); - if (!context->executeInitializer($2.line, *$2.string, $1, $4, intermNode)) + if (!context->executeInitializer(@2, *$2.string, $1, $4, intermNode)) $$ = $4; else { context->recover(); @@ -1926,19 +1786,19 @@ condition iteration_statement : WHILE LEFT_PAREN { context->symbolTable.push(); ++context->loopNestingLevel; } condition RIGHT_PAREN statement_no_new_scope { context->symbolTable.pop(); - $$ = context->intermediate.addLoop(ELoopWhile, 0, $4, 0, $6, $1.line); + $$ = context->intermediate.addLoop(ELoopWhile, 0, $4, 0, $6, @1); --context->loopNestingLevel; } | DO { ++context->loopNestingLevel; } statement_with_scope WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON { - if (context->boolErrorCheck($8.line, $6)) + if (context->boolErrorCheck(@8, $6)) context->recover(); - $$ = context->intermediate.addLoop(ELoopDoWhile, 0, $6, 0, $3, $4.line); + $$ = context->intermediate.addLoop(ELoopDoWhile, 0, $6, 0, $3, @4); --context->loopNestingLevel; } | FOR LEFT_PAREN { context->symbolTable.push(); ++context->loopNestingLevel; } for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope { context->symbolTable.pop(); - $$ = context->intermediate.addLoop(ELoopFor, $4, reinterpret_cast($5.node1), reinterpret_cast($5.node2), $7, $1.line); + $$ = context->intermediate.addLoop(ELoopFor, $4, reinterpret_cast($5.node1), reinterpret_cast($5.node2), $7, @1); --context->loopNestingLevel; } ; @@ -1975,39 +1835,39 @@ for_rest_statement jump_statement : CONTINUE SEMICOLON { if (context->loopNestingLevel <= 0) { - context->error($1.line, "continue statement only allowed in loops", ""); + context->error(@1, "continue statement only allowed in loops", ""); context->recover(); } - $$ = context->intermediate.addBranch(EOpContinue, $1.line); + $$ = context->intermediate.addBranch(EOpContinue, @1); } | BREAK SEMICOLON { if (context->loopNestingLevel <= 0) { - context->error($1.line, "break statement only allowed in loops", ""); + context->error(@1, "break statement only allowed in loops", ""); context->recover(); } - $$ = context->intermediate.addBranch(EOpBreak, $1.line); + $$ = context->intermediate.addBranch(EOpBreak, @1); } | RETURN SEMICOLON { - $$ = context->intermediate.addBranch(EOpReturn, $1.line); + $$ = context->intermediate.addBranch(EOpReturn, @1); if (context->currentFunctionType->getBasicType() != EbtVoid) { - context->error($1.line, "non-void function must return a value", "return"); + context->error(@1, "non-void function must return a value", "return"); context->recover(); } } | RETURN expression SEMICOLON { - $$ = context->intermediate.addBranch(EOpReturn, $2, $1.line); + $$ = context->intermediate.addBranch(EOpReturn, $2, @1); context->functionReturnsValue = true; if (context->currentFunctionType->getBasicType() == EbtVoid) { - context->error($1.line, "void function cannot return a value", "return"); + context->error(@1, "void function cannot return a value", "return"); context->recover(); } else if (*(context->currentFunctionType) != $2->getType()) { - context->error($1.line, "function return is not matching type:", "return"); + context->error(@1, "function return is not matching type:", "return"); context->recover(); } } | DISCARD SEMICOLON { - FRAG_ONLY("discard", $1.line); - $$ = context->intermediate.addBranch(EOpKill, $1.line); + FRAG_ONLY("discard", @1); + $$ = context->intermediate.addBranch(EOpKill, @1); } ; @@ -2019,7 +1879,7 @@ translation_unit context->treeRoot = $$; } | translation_unit external_declaration { - $$ = context->intermediate.growAggregate($1, $2, 0); + $$ = context->intermediate.growAggregate($1, $2, @$); context->treeRoot = $$; } ; @@ -2041,7 +1901,7 @@ function_definition if (builtIn) { - context->error($1.line, "built-in functions cannot be redefined", function->getName().c_str()); + context->error(@1, "built-in functions cannot be redefined", function->getName().c_str()); context->recover(); } @@ -2055,7 +1915,7 @@ function_definition // // Then this function already has a body. // - context->error($1.line, "function already has a body", function->getName().c_str()); + context->error(@1, "function already has a body", function->getName().c_str()); context->recover(); } prevDec->setDefined(); @@ -2065,11 +1925,11 @@ function_definition // if (function->getName() == "main") { if (function->getParamCount() > 0) { - context->error($1.line, "function cannot take any parameter(s)", function->getName().c_str()); + context->error(@1, "function cannot take any parameter(s)", function->getName().c_str()); context->recover(); } if (function->getReturnType().getBasicType() != EbtVoid) { - context->error($1.line, "", function->getReturnType().getBasicString(), "main function cannot return a value"); + context->error(@1, "", function->getReturnType().getBasicString(), "main function cannot return a value"); context->recover(); } } @@ -2097,7 +1957,7 @@ function_definition // Insert the parameters with name in the symbol table. // if (! context->symbolTable.insert(*variable)) { - context->error($1.line, "redefinition", variable->getName().c_str()); + context->error(@1, "redefinition", variable->getName().c_str()); context->recover(); delete variable; } @@ -2108,14 +1968,15 @@ function_definition paramNodes = context->intermediate.growAggregate( paramNodes, context->intermediate.addSymbol(variable->getUniqueId(), - variable->getName(), - variable->getType(), $1.line), - $1.line); + variable->getName(), + variable->getType(), + @1), + @1); } else { - paramNodes = context->intermediate.growAggregate(paramNodes, context->intermediate.addSymbol(0, "", *param.type, $1.line), $1.line); + paramNodes = context->intermediate.growAggregate(paramNodes, context->intermediate.addSymbol(0, "", *param.type, @1), @1); } } - context->intermediate.setAggregateOperator(paramNodes, EOpParameters, $1.line); + context->intermediate.setAggregateOperator(paramNodes, EOpParameters, @1); $1.intermAggregate = paramNodes; context->loopNestingLevel = 0; } @@ -2123,12 +1984,12 @@ function_definition //?? Check that all paths return a value if return type != void ? // May be best done as post process phase on intermediate code if (context->currentFunctionType->getBasicType() != EbtVoid && ! context->functionReturnsValue) { - context->error($1.line, "function does not return a value:", "", $1.function->getName().c_str()); + context->error(@1, "function does not return a value:", "", $1.function->getName().c_str()); context->recover(); } - $$ = context->intermediate.growAggregate($1.intermAggregate, $3, 0); - context->intermediate.setAggregateOperator($$, EOpFunction, $1.line); + $$ = context->intermediate.growAggregate($1.intermAggregate, $3, @$); + context->intermediate.setAggregateOperator($$, EOpFunction, @1); $$->getAsAggregate()->setName($1.function->getMangledName().c_str()); $$->getAsAggregate()->setType($1.function->getReturnType()); @@ -2137,15 +1998,17 @@ function_definition $$->getAsAggregate()->setOptimize(context->pragma().optimize); $$->getAsAggregate()->setDebug(context->pragma().debug); - if ($3 && $3->getAsAggregate()) - $$->getAsAggregate()->setEndLine($3->getAsAggregate()->getEndLine()); - context->symbolTable.pop(); } ; %% +void yyerror(YYLTYPE* yylloc, TParseContext* context, const char* reason) { + context->error(*yylloc, reason, ""); + context->recover(); +} + int glslang_parse(TParseContext* context) { return yyparse(context); } diff --git a/gfx/angle/src/compiler/glslang_lex.cpp b/gfx/angle/src/compiler/glslang_lex.cpp index a60dad51ebe8..9f95521f23b9 100644 --- a/gfx/angle/src/compiler/glslang_lex.cpp +++ b/gfx/angle/src/compiler/glslang_lex.cpp @@ -384,8 +384,8 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner ); *yy_cp = '\0'; \ yyg->yy_c_buf_p = yy_cp; -#define YY_NUM_RULES 155 -#define YY_END_OF_BUFFER 156 +#define YY_NUM_RULES 147 +#define YY_END_OF_BUFFER 148 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info @@ -393,58 +393,57 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static yyconst flex_int16_t yy_accept[459] = +static yyconst flex_int16_t yy_accept[443] = { 0, - 0, 0, 0, 0, 0, 0, 156, 154, 153, 153, - 138, 144, 149, 133, 134, 142, 141, 130, 139, 137, - 143, 102, 102, 131, 127, 145, 132, 146, 150, 98, - 135, 136, 148, 98, 98, 98, 98, 98, 98, 98, - 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 98, 98, 98, 128, 147, 129, 140, 3, 4, 3, - 152, 155, 151, 124, 110, 129, 118, 113, 108, 116, - 106, 117, 107, 105, 2, 1, 109, 104, 100, 101, - 0, 0, 102, 136, 128, 135, 125, 121, 123, 122, - 126, 98, 114, 120, 98, 98, 98, 98, 98, 98, + 0, 0, 148, 146, 145, 145, 132, 138, 143, 127, + 128, 136, 135, 124, 133, 131, 137, 96, 96, 125, + 121, 139, 126, 140, 144, 93, 129, 130, 142, 93, + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, + 93, 93, 93, 93, 93, 93, 93, 93, 93, 122, + 141, 123, 134, 118, 104, 123, 112, 107, 102, 110, + 100, 111, 101, 99, 103, 98, 95, 96, 0, 0, + 130, 122, 129, 119, 115, 117, 116, 120, 93, 108, + 114, 93, 93, 93, 93, 93, 93, 93, 93, 93, + 93, 12, 93, 93, 93, 93, 93, 93, 93, 93, - 98, 98, 98, 98, 17, 98, 98, 98, 98, 98, - 98, 98, 98, 98, 98, 98, 98, 98, 20, 22, - 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 98, 98, 98, 98, 98, 98, 98, 115, 119, 5, - 151, 0, 1, 104, 0, 0, 103, 99, 111, 112, - 50, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 98, 98, 98, 98, 98, 98, 98, 98, 98, 18, - 98, 98, 98, 98, 98, 98, 98, 98, 26, 98, - 98, 98, 98, 98, 98, 98, 98, 23, 98, 98, + 93, 93, 93, 93, 93, 15, 17, 93, 93, 93, + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, + 93, 93, 93, 93, 109, 113, 0, 98, 0, 0, + 97, 94, 105, 106, 45, 93, 93, 93, 93, 93, + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, + 93, 93, 93, 13, 93, 93, 93, 93, 93, 93, + 93, 93, 21, 93, 93, 93, 93, 93, 93, 93, + 93, 18, 93, 93, 93, 93, 93, 93, 93, 93, + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, - 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 98, 0, 105, 0, 104, 98, 28, 98, 98, 95, - 98, 98, 98, 98, 98, 98, 98, 21, 53, 98, - 98, 98, 69, 98, 98, 58, 73, 98, 98, 98, - 98, 98, 98, 98, 98, 70, 9, 33, 34, 35, - 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 98, 98, 98, 98, 98, 98, 56, 29, 98, 98, - 98, 98, 98, 98, 36, 37, 38, 27, 98, 98, - 98, 15, 42, 43, 44, 51, 12, 98, 98, 98, + 93, 93, 93, 93, 93, 0, 99, 0, 98, 93, + 23, 93, 93, 90, 93, 93, 93, 93, 93, 93, + 93, 16, 48, 93, 93, 93, 64, 93, 93, 53, + 68, 93, 93, 93, 93, 93, 93, 93, 93, 65, + 4, 28, 29, 30, 93, 93, 93, 93, 93, 93, + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, + 51, 24, 93, 93, 93, 93, 93, 93, 31, 32, + 33, 22, 93, 93, 93, 10, 37, 38, 39, 46, + 7, 93, 93, 93, 93, 77, 78, 79, 93, 25, + 69, 20, 80, 81, 82, 2, 74, 75, 76, 93, - 98, 82, 83, 84, 98, 30, 74, 25, 85, 86, - 87, 7, 79, 80, 81, 98, 24, 77, 98, 98, - 39, 40, 41, 98, 98, 98, 98, 98, 98, 98, - 98, 98, 71, 98, 98, 98, 98, 98, 98, 98, - 98, 52, 98, 97, 98, 98, 19, 98, 98, 98, - 98, 72, 66, 61, 98, 98, 98, 98, 98, 78, - 57, 98, 64, 32, 98, 94, 65, 49, 76, 59, - 98, 98, 98, 98, 98, 98, 98, 98, 60, 31, - 98, 98, 98, 8, 98, 98, 98, 98, 98, 54, - 13, 98, 14, 98, 98, 16, 67, 98, 98, 98, + 19, 72, 93, 93, 34, 35, 36, 93, 93, 93, + 93, 93, 93, 93, 93, 93, 66, 93, 93, 93, + 93, 93, 93, 93, 93, 47, 93, 92, 93, 93, + 14, 93, 93, 93, 93, 67, 61, 56, 93, 93, + 93, 93, 93, 73, 52, 93, 59, 27, 93, 89, + 60, 44, 71, 54, 93, 93, 93, 93, 93, 93, + 93, 93, 55, 26, 93, 93, 93, 3, 93, 93, + 93, 93, 93, 49, 8, 93, 9, 93, 93, 11, + 62, 93, 93, 93, 57, 93, 93, 93, 93, 93, + 93, 50, 70, 58, 6, 63, 1, 91, 5, 83, - 62, 98, 98, 98, 98, 98, 98, 55, 75, 63, - 11, 68, 6, 96, 10, 88, 45, 89, 98, 98, - 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 46, 98, 98, 98, 98, 98, 98, 98, 48, 98, - 92, 98, 98, 98, 98, 98, 90, 98, 91, 98, - 98, 98, 98, 98, 98, 47, 93, 0 + 40, 84, 93, 93, 93, 93, 93, 93, 93, 93, + 93, 93, 93, 93, 41, 93, 93, 93, 93, 93, + 93, 93, 43, 93, 87, 93, 93, 93, 93, 93, + 85, 93, 86, 93, 93, 93, 93, 93, 93, 42, + 88, 0 } ; static yyconst flex_int32_t yy_ec[256] = @@ -481,212 +480,198 @@ static yyconst flex_int32_t yy_ec[256] = static yyconst flex_int32_t yy_meta[68] = { 0, - 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, - 3, 1, 1, 1, 1, 1, 1, 3, 3, 3, - 3, 4, 4, 4, 4, 4, 1, 1, 1, 3, - 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 1, 1, 1, 1 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, + 2, 1, 1, 1, 1, 1, 1, 2, 2, 2, + 2, 3, 3, 3, 3, 3, 1, 1, 1, 2, + 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 1, 1, 1, 1 } ; -static yyconst flex_int16_t yy_base[464] = +static yyconst flex_int16_t yy_base[445] = { 0, - 0, 0, 65, 66, 75, 0, 680, 681, 681, 681, - 654, 45, 137, 681, 681, 653, 134, 681, 133, 131, - 146, 159, 168, 651, 681, 186, 651, 47, 681, 0, - 681, 681, 128, 100, 110, 152, 156, 146, 166, 622, - 173, 109, 621, 126, 177, 615, 178, 628, 187, 184, - 141, 197, 624, 681, 157, 681, 681, 681, 681, 656, - 681, 681, 0, 681, 681, 681, 681, 681, 681, 681, - 681, 681, 681, 236, 681, 0, 681, 243, 273, 282, - 304, 0, 314, 681, 681, 681, 644, 681, 681, 681, - 643, 0, 681, 681, 616, 609, 612, 620, 619, 606, + 0, 0, 587, 588, 588, 588, 561, 43, 64, 588, + 588, 560, 61, 588, 60, 58, 559, 77, 86, 557, + 588, 104, 557, 55, 588, 0, 588, 588, 75, 26, + 57, 82, 83, 73, 93, 528, 97, 95, 527, 44, + 71, 521, 104, 534, 110, 116, 35, 111, 530, 588, + 114, 588, 588, 588, 588, 588, 588, 588, 588, 588, + 588, 588, 588, 165, 588, 172, 202, 211, 233, 0, + 588, 588, 588, 551, 588, 588, 588, 550, 0, 588, + 588, 523, 516, 519, 527, 526, 513, 528, 515, 521, + 509, 506, 519, 506, 503, 503, 509, 497, 108, 502, - 621, 608, 614, 602, 599, 612, 599, 596, 596, 602, - 590, 189, 595, 605, 591, 597, 600, 601, 0, 216, - 600, 188, 586, 599, 590, 592, 582, 596, 593, 595, - 578, 583, 580, 569, 183, 577, 582, 578, 580, 569, - 572, 220, 577, 569, 581, 176, 574, 681, 681, 681, - 0, 331, 0, 344, 361, 290, 374, 0, 681, 681, - 0, 566, 570, 579, 576, 560, 560, 215, 575, 572, - 572, 570, 567, 559, 565, 552, 563, 549, 565, 0, - 562, 550, 557, 554, 558, 551, 540, 539, 552, 555, - 552, 547, 538, 260, 543, 546, 537, 534, 538, 544, + 512, 498, 504, 507, 508, 0, 145, 507, 113, 493, + 506, 497, 499, 489, 503, 500, 502, 485, 490, 487, + 476, 157, 484, 489, 485, 487, 476, 479, 118, 484, + 476, 488, 70, 481, 588, 588, 246, 253, 270, 219, + 283, 0, 588, 588, 0, 473, 477, 486, 483, 467, + 467, 119, 482, 479, 479, 477, 474, 466, 472, 459, + 470, 456, 472, 0, 469, 457, 464, 461, 465, 458, + 447, 446, 459, 462, 459, 454, 445, 188, 450, 453, + 444, 441, 445, 451, 442, 433, 436, 434, 444, 430, + 428, 441, 427, 429, 426, 437, 436, 124, 431, 426, - 535, 526, 529, 527, 537, 523, 521, 534, 520, 522, - 519, 530, 529, 283, 524, 519, 508, 264, 526, 528, - 517, 381, 388, 395, 402, 518, 0, 516, 320, 0, - 508, 506, 514, 503, 520, 509, 336, 0, 0, 503, - 513, 513, 0, 498, 349, 0, 0, 500, 366, 501, - 495, 494, 495, 494, 407, 0, 0, 0, 0, 0, - 490, 491, 496, 487, 500, 495, 494, 486, 490, 482, - 485, 489, 494, 480, 492, 483, 0, 0, 489, 478, - 478, 483, 482, 479, 0, 0, 0, 0, 469, 481, - 483, 0, 0, 0, 0, 0, 0, 471, 472, 466, + 415, 258, 433, 435, 424, 290, 297, 304, 311, 425, + 0, 423, 275, 0, 415, 413, 421, 410, 427, 416, + 316, 0, 0, 410, 420, 420, 0, 405, 319, 0, + 0, 407, 322, 408, 402, 401, 402, 401, 325, 0, + 0, 0, 0, 0, 397, 398, 403, 394, 407, 402, + 401, 393, 397, 389, 392, 396, 401, 387, 399, 390, + 0, 0, 396, 385, 385, 390, 389, 386, 0, 0, + 0, 0, 376, 388, 390, 0, 0, 0, 0, 0, + 0, 378, 379, 373, 383, 0, 0, 0, 374, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 381, - 476, 0, 0, 0, 467, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 474, 0, 0, 472, 468, - 0, 0, 0, 464, 460, 465, 455, 468, 454, 467, - 456, 463, 0, 461, 463, 447, 449, 455, 461, 456, - 444, 0, 446, 0, 445, 448, 0, 437, 436, 436, - 449, 0, 451, 0, 450, 449, 434, 447, 434, 0, - 0, 437, 0, 0, 429, 0, 0, 0, 0, 0, - 426, 437, 430, 436, 433, 428, 420, 432, 0, 0, - 425, 432, 421, 0, 430, 427, 417, 411, 425, 0, - 0, 425, 0, 423, 422, 0, 0, 421, 407, 419, + 0, 0, 379, 375, 0, 0, 0, 371, 367, 372, + 362, 375, 361, 374, 363, 370, 0, 368, 370, 354, + 356, 362, 368, 363, 351, 0, 353, 0, 352, 355, + 0, 344, 343, 343, 356, 0, 358, 0, 357, 356, + 341, 354, 341, 0, 0, 344, 0, 0, 336, 0, + 0, 0, 0, 0, 333, 344, 337, 343, 340, 335, + 327, 339, 0, 0, 332, 339, 328, 0, 337, 334, + 324, 329, 332, 0, 0, 332, 0, 330, 329, 0, + 0, 328, 314, 326, 0, 317, 338, 337, 336, 307, + 303, 0, 0, 0, 0, 0, 0, 0, 0, 328, - 0, 410, 431, 430, 429, 400, 396, 0, 0, 0, - 0, 0, 0, 0, 0, 421, 250, 421, 411, 384, - 392, 394, 390, 392, 391, 390, 393, 390, 391, 388, - 0, 332, 343, 317, 329, 313, 317, 304, 321, 291, - 0, 302, 280, 271, 255, 262, 0, 256, 0, 232, - 206, 212, 148, 159, 113, 0, 0, 681, 442, 444, - 446, 450, 161 + 166, 325, 316, 299, 308, 310, 306, 308, 307, 306, + 309, 306, 256, 253, 0, 228, 238, 222, 235, 203, + 207, 204, 212, 191, 0, 201, 165, 167, 153, 161, + 0, 170, 0, 175, 151, 141, 100, 114, 59, 0, + 0, 588, 359, 113 } ; -static yyconst flex_int16_t yy_def[464] = +static yyconst flex_int16_t yy_def[445] = { 0, - 458, 1, 459, 459, 458, 5, 458, 458, 458, 458, - 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, - 458, 458, 458, 458, 458, 458, 458, 458, 458, 460, - 458, 458, 458, 460, 460, 460, 460, 460, 460, 460, - 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, - 460, 460, 460, 458, 458, 458, 458, 458, 458, 458, - 458, 458, 461, 458, 458, 458, 458, 458, 458, 458, - 458, 458, 458, 458, 458, 462, 458, 458, 458, 458, - 458, 463, 458, 458, 458, 458, 458, 458, 458, 458, - 458, 460, 458, 458, 460, 460, 460, 460, 460, 460, + 442, 1, 442, 442, 442, 442, 442, 442, 442, 442, + 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, + 442, 442, 442, 442, 442, 443, 442, 442, 442, 443, + 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, + 443, 443, 443, 443, 443, 443, 443, 443, 443, 442, + 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, + 442, 442, 442, 442, 442, 442, 442, 442, 442, 444, + 442, 442, 442, 442, 442, 442, 442, 442, 443, 442, + 442, 443, 443, 443, 443, 443, 443, 443, 443, 443, + 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, - 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, - 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, - 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, - 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, - 460, 460, 460, 460, 460, 460, 460, 458, 458, 458, - 461, 458, 462, 458, 458, 458, 458, 463, 458, 458, - 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, - 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, - 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, - 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, + 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, + 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, + 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, + 443, 443, 443, 443, 442, 442, 442, 442, 442, 442, + 442, 444, 442, 442, 443, 443, 443, 443, 443, 443, + 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, + 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, + 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, + 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, + 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, - 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, - 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, - 460, 458, 458, 458, 458, 460, 460, 460, 460, 460, - 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, - 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, - 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, - 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, - 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, - 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, - 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, + 443, 443, 443, 443, 443, 442, 442, 442, 442, 443, + 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, + 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, + 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, + 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, + 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, + 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, + 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, + 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, + 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, - 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, - 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, - 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, - 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, - 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, - 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, - 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, - 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, - 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, - 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, + 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, + 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, + 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, + 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, + 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, + 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, + 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, + 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, + 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, + 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, - 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, - 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, - 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, - 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, - 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, - 460, 460, 460, 460, 460, 460, 460, 0, 458, 458, - 458, 458, 458 + 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, + 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, + 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, + 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, + 443, 0, 442, 442 } ; -static yyconst flex_int16_t yy_nxt[749] = +static yyconst flex_int16_t yy_nxt[656] = { 0, - 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 23, 23, 23, 23, 23, - 23, 24, 25, 26, 27, 28, 29, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 41, 42, 30, 43, - 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - 30, 30, 30, 54, 55, 56, 57, 59, 59, 65, - 66, 90, 91, 60, 60, 8, 61, 62, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 19, 19, 19, 19, + 19, 20, 21, 22, 23, 24, 25, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 26, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 26, 26, 26, 50, 51, 52, 53, 55, 56, 57, + 60, 62, 64, 64, 64, 64, 64, 64, 64, 77, + 78, 82, 83, 110, 63, 61, 129, 111, 58, 66, + 130, 67, 67, 67, 67, 67, 67, 68, 66, 80, - 8, 8, 63, 63, 63, 63, 63, 63, 63, 63, - 63, 8, 8, 8, 63, 63, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, 8, 8, - 8, 8, 67, 70, 72, 74, 74, 74, 74, 74, - 74, 74, 93, 119, 75, 95, 96, 73, 71, 76, - 120, 68, 97, 158, 98, 123, 94, 121, 99, 124, - 77, 78, 457, 79, 79, 79, 79, 79, 79, 80, - 78, 148, 83, 83, 83, 83, 83, 83, 83, 81, - 85, 100, 142, 456, 82, 107, 143, 108, 81, 103, + 68, 68, 68, 68, 68, 68, 68, 69, 72, 84, + 112, 85, 70, 81, 142, 86, 69, 203, 441, 204, + 69, 87, 94, 113, 95, 73, 90, 74, 75, 69, + 91, 88, 97, 96, 89, 92, 103, 70, 135, 106, + 98, 93, 99, 115, 104, 100, 107, 162, 440, 119, + 131, 101, 439, 108, 132, 105, 120, 121, 116, 125, + 163, 117, 126, 133, 176, 198, 122, 123, 264, 124, + 127, 438, 177, 199, 216, 217, 265, 128, 136, 64, + 64, 64, 64, 64, 64, 64, 138, 138, 138, 138, + 138, 138, 138, 437, 170, 137, 190, 171, 172, 406, - 455, 101, 81, 104, 102, 110, 109, 86, 105, 87, - 88, 81, 116, 111, 106, 112, 125, 128, 113, 82, - 117, 149, 206, 219, 114, 220, 132, 138, 178, 126, - 139, 118, 129, 133, 134, 130, 144, 207, 140, 192, - 145, 179, 454, 135, 136, 141, 137, 193, 453, 146, - 74, 74, 74, 74, 74, 74, 74, 154, 154, 154, - 154, 154, 154, 154, 452, 186, 152, 214, 187, 188, - 232, 233, 189, 155, 190, 215, 258, 259, 260, 152, - 285, 286, 287, 422, 423, 78, 155, 79, 79, 79, - 79, 79, 79, 80, 78, 451, 80, 80, 80, 80, + 407, 173, 139, 174, 242, 243, 244, 436, 137, 435, + 434, 191, 433, 432, 66, 139, 67, 67, 67, 67, + 67, 67, 68, 66, 431, 68, 68, 68, 68, 68, + 68, 68, 69, 141, 141, 141, 141, 141, 141, 141, + 430, 69, 140, 429, 140, 69, 428, 141, 141, 141, + 141, 141, 141, 141, 69, 206, 427, 206, 426, 425, + 207, 207, 207, 207, 207, 207, 207, 138, 138, 138, + 138, 138, 138, 138, 269, 270, 271, 424, 423, 208, + 422, 208, 421, 139, 209, 209, 209, 209, 209, 209, + 209, 277, 278, 279, 420, 419, 139, 141, 141, 141, - 80, 80, 80, 81, 157, 157, 157, 157, 157, 157, - 157, 450, 81, 156, 449, 156, 81, 448, 157, 157, - 157, 157, 157, 157, 157, 81, 78, 280, 83, 83, - 83, 83, 83, 83, 83, 281, 293, 294, 295, 447, - 222, 446, 222, 445, 81, 223, 223, 223, 223, 223, - 223, 223, 302, 303, 304, 444, 443, 81, 154, 154, - 154, 154, 154, 154, 154, 309, 310, 311, 442, 441, - 224, 440, 224, 439, 155, 225, 225, 225, 225, 225, - 225, 225, 313, 314, 315, 438, 437, 155, 157, 157, - 157, 157, 157, 157, 157, 223, 223, 223, 223, 223, + 141, 141, 141, 141, 207, 207, 207, 207, 207, 207, + 207, 207, 207, 207, 207, 207, 207, 207, 209, 209, + 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, + 209, 209, 286, 287, 288, 293, 294, 295, 297, 298, + 299, 305, 306, 307, 387, 388, 389, 418, 417, 416, + 415, 414, 413, 412, 411, 410, 409, 390, 408, 391, + 79, 79, 405, 404, 403, 402, 401, 400, 399, 398, + 397, 396, 395, 394, 393, 392, 386, 385, 384, 383, + 382, 381, 380, 379, 378, 377, 376, 375, 374, 373, + 372, 371, 370, 369, 368, 367, 366, 365, 364, 363, - 223, 223, 223, 223, 223, 223, 223, 223, 223, 225, - 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, - 225, 225, 225, 321, 322, 323, 403, 404, 405, 436, - 435, 434, 433, 432, 431, 430, 429, 428, 427, 406, - 426, 407, 58, 58, 58, 58, 92, 92, 151, 151, - 153, 425, 153, 153, 424, 421, 420, 419, 418, 417, - 416, 415, 414, 413, 412, 411, 410, 409, 408, 402, - 401, 400, 399, 398, 397, 396, 395, 394, 393, 392, - 391, 390, 389, 388, 387, 386, 385, 384, 383, 382, - 381, 380, 379, 378, 377, 376, 375, 374, 373, 372, + 362, 361, 360, 359, 358, 357, 356, 355, 354, 353, + 352, 351, 350, 349, 348, 347, 346, 345, 344, 343, + 342, 341, 340, 339, 338, 337, 336, 335, 334, 333, + 332, 331, 330, 329, 328, 327, 326, 325, 324, 323, + 322, 321, 320, 319, 318, 317, 316, 315, 314, 313, + 312, 311, 310, 309, 308, 304, 303, 302, 301, 300, + 296, 292, 291, 290, 289, 285, 284, 283, 282, 281, + 280, 276, 275, 274, 273, 272, 268, 267, 266, 263, + 262, 261, 260, 259, 258, 257, 256, 255, 254, 253, + 252, 251, 250, 249, 248, 247, 246, 245, 241, 240, - 371, 370, 369, 368, 367, 366, 365, 364, 363, 362, - 361, 360, 359, 358, 357, 356, 355, 354, 353, 352, - 351, 350, 349, 348, 347, 346, 345, 344, 343, 342, - 341, 340, 339, 338, 337, 336, 335, 334, 333, 332, - 331, 330, 329, 328, 327, 326, 325, 324, 320, 319, - 318, 317, 316, 312, 308, 307, 306, 305, 301, 300, - 299, 298, 297, 296, 292, 291, 290, 289, 288, 284, - 283, 282, 279, 278, 277, 276, 275, 274, 273, 272, - 271, 270, 269, 268, 267, 266, 265, 264, 263, 262, - 261, 257, 256, 255, 254, 253, 252, 251, 250, 249, + 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, + 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, + 219, 218, 215, 214, 213, 212, 211, 210, 205, 202, + 201, 200, 197, 196, 195, 194, 193, 192, 189, 188, + 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, + 175, 169, 168, 167, 166, 165, 164, 161, 160, 159, + 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, + 148, 147, 146, 145, 144, 143, 134, 118, 114, 109, + 102, 76, 71, 65, 59, 54, 442, 3, 442, 442, + 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, - 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, - 238, 237, 236, 235, 234, 231, 230, 229, 228, 227, - 226, 221, 218, 217, 216, 213, 212, 211, 210, 209, - 208, 205, 204, 203, 202, 201, 200, 199, 198, 197, - 196, 195, 194, 191, 185, 184, 183, 182, 181, 180, - 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, - 167, 166, 165, 164, 163, 162, 161, 160, 159, 150, - 147, 131, 127, 122, 115, 89, 84, 69, 64, 458, - 7, 458, 458, 458, 458, 458, 458, 458, 458, 458, - 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, - - 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, - 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, - 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, - 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, - 458, 458, 458, 458, 458, 458, 458, 458 + 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, + 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, + 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, + 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, + 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, + 442, 442, 442, 442, 442 } ; -static yyconst flex_int16_t yy_chk[749] = +static yyconst flex_int16_t yy_chk[656] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -694,95 +679,85 @@ static yyconst flex_int16_t yy_chk[749] = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 3, 4, 12, - 12, 28, 28, 3, 4, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 1, 1, 1, 1, 1, 1, 1, 8, 8, 9, + 13, 15, 16, 16, 16, 16, 16, 16, 16, 24, + 24, 30, 30, 40, 15, 13, 47, 40, 9, 18, + 47, 18, 18, 18, 18, 18, 18, 18, 19, 29, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 13, 17, 19, 20, 20, 20, 20, 20, - 20, 20, 33, 42, 21, 34, 34, 19, 17, 21, - 42, 13, 35, 463, 35, 44, 33, 42, 35, 44, - 21, 22, 455, 22, 22, 22, 22, 22, 22, 22, - 23, 55, 23, 23, 23, 23, 23, 23, 23, 22, - 26, 36, 51, 454, 22, 38, 51, 38, 23, 37, + 19, 19, 19, 19, 19, 19, 19, 18, 22, 31, + 41, 31, 18, 29, 444, 31, 19, 133, 439, 133, + 18, 32, 34, 41, 34, 22, 33, 22, 22, 19, + 33, 32, 35, 34, 32, 33, 37, 18, 51, 38, + 35, 33, 35, 43, 37, 35, 38, 99, 438, 45, + 48, 35, 437, 38, 48, 37, 45, 45, 43, 46, + 99, 43, 46, 48, 109, 129, 45, 45, 198, 45, + 46, 436, 109, 129, 152, 152, 198, 46, 51, 64, + 64, 64, 64, 64, 64, 64, 66, 66, 66, 66, + 66, 66, 66, 435, 107, 64, 122, 107, 107, 401, - 453, 36, 22, 37, 36, 39, 38, 26, 37, 26, - 26, 23, 41, 39, 37, 39, 45, 47, 39, 22, - 41, 55, 135, 146, 39, 146, 49, 50, 112, 45, - 50, 41, 47, 49, 49, 47, 52, 135, 50, 122, - 52, 112, 452, 49, 49, 50, 49, 122, 451, 52, - 74, 74, 74, 74, 74, 74, 74, 78, 78, 78, - 78, 78, 78, 78, 450, 120, 74, 142, 120, 120, - 168, 168, 120, 78, 120, 142, 194, 194, 194, 74, - 218, 218, 218, 417, 417, 79, 78, 79, 79, 79, - 79, 79, 79, 79, 80, 448, 80, 80, 80, 80, + 401, 107, 66, 107, 178, 178, 178, 434, 64, 432, + 430, 122, 429, 428, 67, 66, 67, 67, 67, 67, + 67, 67, 67, 68, 427, 68, 68, 68, 68, 68, + 68, 68, 67, 140, 140, 140, 140, 140, 140, 140, + 426, 68, 69, 424, 69, 67, 423, 69, 69, 69, + 69, 69, 69, 69, 68, 137, 422, 137, 421, 420, + 137, 137, 137, 137, 137, 137, 137, 138, 138, 138, + 138, 138, 138, 138, 202, 202, 202, 419, 418, 139, + 417, 139, 416, 138, 139, 139, 139, 139, 139, 139, + 139, 213, 213, 213, 414, 413, 138, 141, 141, 141, - 80, 80, 80, 79, 156, 156, 156, 156, 156, 156, - 156, 446, 80, 81, 445, 81, 79, 444, 81, 81, - 81, 81, 81, 81, 81, 80, 83, 214, 83, 83, - 83, 83, 83, 83, 83, 214, 229, 229, 229, 443, - 152, 442, 152, 440, 83, 152, 152, 152, 152, 152, - 152, 152, 237, 237, 237, 439, 438, 83, 154, 154, - 154, 154, 154, 154, 154, 245, 245, 245, 437, 436, - 155, 435, 155, 434, 154, 155, 155, 155, 155, 155, - 155, 155, 249, 249, 249, 433, 432, 154, 157, 157, - 157, 157, 157, 157, 157, 222, 222, 222, 222, 222, + 141, 141, 141, 141, 206, 206, 206, 206, 206, 206, + 206, 207, 207, 207, 207, 207, 207, 207, 208, 208, + 208, 208, 208, 208, 208, 209, 209, 209, 209, 209, + 209, 209, 221, 221, 221, 229, 229, 229, 233, 233, + 233, 239, 239, 239, 372, 372, 372, 412, 411, 410, + 409, 408, 407, 406, 405, 404, 403, 372, 402, 372, + 443, 443, 400, 391, 390, 389, 388, 387, 386, 384, + 383, 382, 379, 378, 376, 373, 371, 370, 369, 367, + 366, 365, 362, 361, 360, 359, 358, 357, 356, 355, + 349, 346, 343, 342, 341, 340, 339, 337, 335, 334, - 222, 222, 223, 223, 223, 223, 223, 223, 223, 224, - 224, 224, 224, 224, 224, 224, 225, 225, 225, 225, - 225, 225, 225, 255, 255, 255, 388, 388, 388, 430, - 429, 428, 427, 426, 425, 424, 423, 422, 421, 388, - 420, 388, 459, 459, 459, 459, 460, 460, 461, 461, - 462, 419, 462, 462, 418, 416, 407, 406, 405, 404, - 403, 402, 400, 399, 398, 395, 394, 392, 389, 387, - 386, 385, 383, 382, 381, 378, 377, 376, 375, 374, - 373, 372, 371, 365, 362, 359, 358, 357, 356, 355, - 353, 351, 350, 349, 348, 346, 345, 343, 341, 340, + 333, 332, 330, 329, 327, 325, 324, 323, 322, 321, + 320, 319, 318, 316, 315, 314, 313, 312, 311, 310, + 309, 308, 304, 303, 300, 289, 285, 284, 283, 282, + 275, 274, 273, 268, 267, 266, 265, 264, 263, 260, + 259, 258, 257, 256, 255, 254, 253, 252, 251, 250, + 249, 248, 247, 246, 245, 238, 237, 236, 235, 234, + 232, 228, 226, 225, 224, 220, 219, 218, 217, 216, + 215, 212, 210, 205, 204, 203, 201, 200, 199, 197, + 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, + 186, 185, 184, 183, 182, 181, 180, 179, 177, 176, - 339, 338, 337, 336, 335, 334, 332, 331, 330, 329, - 328, 327, 326, 325, 324, 320, 319, 316, 305, 301, - 300, 299, 298, 291, 290, 289, 284, 283, 282, 281, - 280, 279, 276, 275, 274, 273, 272, 271, 270, 269, - 268, 267, 266, 265, 264, 263, 262, 261, 254, 253, - 252, 251, 250, 248, 244, 242, 241, 240, 236, 235, - 234, 233, 232, 231, 228, 226, 221, 220, 219, 217, - 216, 215, 213, 212, 211, 210, 209, 208, 207, 206, - 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, - 195, 193, 192, 191, 190, 189, 188, 187, 186, 185, + 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, + 165, 163, 162, 161, 160, 159, 158, 157, 156, 155, + 154, 153, 151, 150, 149, 148, 147, 146, 134, 132, + 131, 130, 128, 127, 126, 125, 124, 123, 121, 120, + 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, + 108, 105, 104, 103, 102, 101, 100, 98, 97, 96, + 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, + 85, 84, 83, 82, 78, 74, 49, 44, 42, 39, + 36, 23, 20, 17, 12, 7, 3, 442, 442, 442, + 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, - 184, 183, 182, 181, 179, 178, 177, 176, 175, 174, - 173, 172, 171, 170, 169, 167, 166, 165, 164, 163, - 162, 147, 145, 144, 143, 141, 140, 139, 138, 137, - 136, 134, 133, 132, 131, 130, 129, 128, 127, 126, - 125, 124, 123, 121, 118, 117, 116, 115, 114, 113, - 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, - 101, 100, 99, 98, 97, 96, 95, 91, 87, 60, - 53, 48, 46, 43, 40, 27, 24, 16, 11, 7, - 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, - 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, - - 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, - 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, - 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, - 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, - 458, 458, 458, 458, 458, 458, 458, 458 + 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, + 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, + 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, + 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, + 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, + 442, 442, 442, 442, 442 } ; /* Table of booleans, true if rule could match eol. */ -static yyconst flex_int32_t yy_rule_can_match_eol[156] = +static yyconst flex_int32_t yy_rule_can_match_eol[148] = { 0, -0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, }; + 0, 0, 0, 0, 0, 1, 0, 0, }; /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. @@ -817,7 +792,10 @@ WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp). #pragma warning(disable : 4102) #endif -#define YY_USER_ACTION yylval->lex.line = yylineno; +#define YY_USER_ACTION \ + yylloc->first_file = yylloc->last_file = yycolumn; \ + yylloc->first_line = yylloc->last_line = yylineno; + #define YY_INPUT(buf, result, max_size) \ result = string_input(buf, max_size, yyscanner); @@ -826,8 +804,6 @@ static int check_type(yyscan_t yyscanner); static int reserved_word(yyscan_t yyscanner); #define INITIAL 0 -#define COMMENT 1 -#define FIELDS 2 #define YY_EXTRA_TYPE TParseContext* @@ -865,6 +841,8 @@ struct yyguts_t YYSTYPE * yylval_r; + YYLTYPE * yylloc_r; + }; /* end struct yyguts_t */ static int yy_init_globals (yyscan_t yyscanner ); @@ -873,6 +851,8 @@ static int yy_init_globals (yyscan_t yyscanner ); * from bison output in section 1.*/ # define yylval yyg->yylval_r + # define yylloc yyg->yylloc_r + int yylex_init (yyscan_t* scanner); int yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner); @@ -910,6 +890,10 @@ YYSTYPE * yyget_lval (yyscan_t yyscanner ); void yyset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner ); + YYLTYPE *yyget_lloc (yyscan_t yyscanner ); + + void yyset_lloc (YYLTYPE * yylloc_param ,yyscan_t yyscanner ); + /* Macros after this point can all be overridden by user definitions in * section 1. */ @@ -940,12 +924,6 @@ static int input (yyscan_t yyscanner ); #endif - static void yy_push_state (int new_state ,yyscan_t yyscanner); - - static void yy_pop_state (yyscan_t yyscanner ); - - static int yy_top_state (yyscan_t yyscanner ); - /* Amount of stuff to slurp up with each read. */ #ifndef YY_READ_BUF_SIZE #define YY_READ_BUF_SIZE 8192 @@ -1022,10 +1000,10 @@ static int input (yyscan_t yyscanner ); #define YY_DECL_IS_OURS 1 extern int yylex \ - (YYSTYPE * yylval_param ,yyscan_t yyscanner); + (YYSTYPE * yylval_param,YYLTYPE * yylloc_param ,yyscan_t yyscanner); #define YY_DECL int yylex \ - (YYSTYPE * yylval_param , yyscan_t yyscanner) + (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner) #endif /* !YY_DECL */ /* Code executed at the beginning of each rule, after yytext and yyleng @@ -1052,12 +1030,10 @@ YY_DECL register int yy_act; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - TParseContext* context = yyextra; - - /* Single-line comments */ - yylval = yylval_param; + yylloc = yylloc_param; + if ( !yyg->yy_init ) { yyg->yy_init = 1; @@ -1109,13 +1085,13 @@ yy_match: while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 459 ) + if ( yy_current_state >= 443 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } - while ( yy_current_state != 458 ); + while ( yy_current_state != 442 ); yy_cp = yyg->yy_last_accepting_cpos; yy_current_state = yyg->yy_last_accepting_state; @@ -1149,198 +1125,199 @@ do_action: /* This label is used only to access EOF actions. */ case 1: YY_RULE_SETUP -; +{ return INVARIANT; } YY_BREAK -/* Multi-line comments */ case 2: YY_RULE_SETUP -{ yy_push_state(COMMENT, yyscanner); } +{ return HIGH_PRECISION; } YY_BREAK case 3: -case 4: -/* rule 4 can match eol */ YY_RULE_SETUP -; +{ return MEDIUM_PRECISION; } + YY_BREAK +case 4: +YY_RULE_SETUP +{ return LOW_PRECISION; } YY_BREAK case 5: YY_RULE_SETUP -{ yy_pop_state(yyscanner); } +{ return PRECISION; } YY_BREAK case 6: YY_RULE_SETUP -{ return(INVARIANT); } +{ return ATTRIBUTE; } YY_BREAK case 7: YY_RULE_SETUP -{ return(HIGH_PRECISION); } +{ return CONST_QUAL; } YY_BREAK case 8: YY_RULE_SETUP -{ return(MEDIUM_PRECISION); } +{ return UNIFORM; } YY_BREAK case 9: YY_RULE_SETUP -{ return(LOW_PRECISION); } +{ return VARYING; } YY_BREAK case 10: YY_RULE_SETUP -{ return(PRECISION); } +{ return BREAK; } YY_BREAK case 11: YY_RULE_SETUP -{ return(ATTRIBUTE); } +{ return CONTINUE; } YY_BREAK case 12: YY_RULE_SETUP -{ return(CONST_QUAL); } +{ return DO; } YY_BREAK case 13: YY_RULE_SETUP -{ return(UNIFORM); } +{ return FOR; } YY_BREAK case 14: YY_RULE_SETUP -{ return(VARYING); } +{ return WHILE; } YY_BREAK case 15: YY_RULE_SETUP -{ return(BREAK); } +{ return IF; } YY_BREAK case 16: YY_RULE_SETUP -{ return(CONTINUE); } +{ return ELSE; } YY_BREAK case 17: YY_RULE_SETUP -{ return(DO); } +{ return IN_QUAL; } YY_BREAK case 18: YY_RULE_SETUP -{ return(FOR); } +{ return OUT_QUAL; } YY_BREAK case 19: YY_RULE_SETUP -{ return(WHILE); } +{ return INOUT_QUAL; } YY_BREAK case 20: YY_RULE_SETUP -{ return(IF); } +{ return FLOAT_TYPE; } YY_BREAK case 21: YY_RULE_SETUP -{ return(ELSE); } +{ return INT_TYPE; } YY_BREAK case 22: YY_RULE_SETUP -{ return(IN_QUAL); } +{ return VOID_TYPE; } YY_BREAK case 23: YY_RULE_SETUP -{ return(OUT_QUAL); } +{ return BOOL_TYPE; } YY_BREAK case 24: YY_RULE_SETUP -{ return(INOUT_QUAL); } +{ yylval->lex.b = true; return BOOLCONSTANT; } YY_BREAK case 25: YY_RULE_SETUP -{ context->lexAfterType = true; return(FLOAT_TYPE); } +{ yylval->lex.b = false; return BOOLCONSTANT; } YY_BREAK case 26: YY_RULE_SETUP -{ context->lexAfterType = true; return(INT_TYPE); } +{ return DISCARD; } YY_BREAK case 27: YY_RULE_SETUP -{ context->lexAfterType = true; return(VOID_TYPE); } +{ return RETURN; } YY_BREAK case 28: YY_RULE_SETUP -{ context->lexAfterType = true; return(BOOL_TYPE); } +{ return MATRIX2; } YY_BREAK case 29: YY_RULE_SETUP -{ yylval->lex.b = true; return(BOOLCONSTANT); } +{ return MATRIX3; } YY_BREAK case 30: YY_RULE_SETUP -{ yylval->lex.b = false; return(BOOLCONSTANT); } +{ return MATRIX4; } YY_BREAK case 31: YY_RULE_SETUP -{ return(DISCARD); } +{ return VEC2; } YY_BREAK case 32: YY_RULE_SETUP -{ return(RETURN); } +{ return VEC3; } YY_BREAK case 33: YY_RULE_SETUP -{ context->lexAfterType = true; return(MATRIX2); } +{ return VEC4; } YY_BREAK case 34: YY_RULE_SETUP -{ context->lexAfterType = true; return(MATRIX3); } +{ return IVEC2; } YY_BREAK case 35: YY_RULE_SETUP -{ context->lexAfterType = true; return(MATRIX4); } +{ return IVEC3; } YY_BREAK case 36: YY_RULE_SETUP -{ context->lexAfterType = true; return (VEC2); } +{ return IVEC4; } YY_BREAK case 37: YY_RULE_SETUP -{ context->lexAfterType = true; return (VEC3); } +{ return BVEC2; } YY_BREAK case 38: YY_RULE_SETUP -{ context->lexAfterType = true; return (VEC4); } +{ return BVEC3; } YY_BREAK case 39: YY_RULE_SETUP -{ context->lexAfterType = true; return (IVEC2); } +{ return BVEC4; } YY_BREAK case 40: YY_RULE_SETUP -{ context->lexAfterType = true; return (IVEC3); } +{ return SAMPLER2D; } YY_BREAK case 41: YY_RULE_SETUP -{ context->lexAfterType = true; return (IVEC4); } +{ return SAMPLERCUBE; } YY_BREAK case 42: YY_RULE_SETUP -{ context->lexAfterType = true; return (BVEC2); } +{ return SAMPLER_EXTERNAL_OES; } YY_BREAK case 43: YY_RULE_SETUP -{ context->lexAfterType = true; return (BVEC3); } +{ return SAMPLER2DRECT; } YY_BREAK case 44: YY_RULE_SETUP -{ context->lexAfterType = true; return (BVEC4); } +{ return STRUCT; } YY_BREAK case 45: YY_RULE_SETUP -{ context->lexAfterType = true; return SAMPLER2D; } +{ return reserved_word(yyscanner); } YY_BREAK case 46: YY_RULE_SETUP -{ context->lexAfterType = true; return SAMPLERCUBE; } +{ return reserved_word(yyscanner); } YY_BREAK case 47: YY_RULE_SETUP -{ context->lexAfterType = true; return SAMPLER_EXTERNAL_OES; } +{ return reserved_word(yyscanner); } YY_BREAK case 48: YY_RULE_SETUP -{ context->lexAfterType = true; return SAMPLER2DRECT; } +{ return reserved_word(yyscanner); } YY_BREAK case 49: YY_RULE_SETUP -{ context->lexAfterType = true; return(STRUCT); } +{ return reserved_word(yyscanner); } YY_BREAK case 50: YY_RULE_SETUP @@ -1516,267 +1493,229 @@ YY_RULE_SETUP YY_BREAK case 93: YY_RULE_SETUP -{ return reserved_word(yyscanner); } - YY_BREAK -case 94: -YY_RULE_SETUP -{ return reserved_word(yyscanner); } - YY_BREAK -case 95: -YY_RULE_SETUP -{ return reserved_word(yyscanner); } - YY_BREAK -case 96: -YY_RULE_SETUP -{ return reserved_word(yyscanner); } - YY_BREAK -case 97: -YY_RULE_SETUP -{ return reserved_word(yyscanner); } - YY_BREAK -case 98: -YY_RULE_SETUP { yylval->lex.string = NewPoolTString(yytext); return check_type(yyscanner); } YY_BREAK +case 94: +YY_RULE_SETUP +{ yylval->lex.i = static_cast(strtol(yytext, 0, 0)); return INTCONSTANT; } + YY_BREAK +case 95: +YY_RULE_SETUP +{ yylval->lex.i = static_cast(strtol(yytext, 0, 0)); return INTCONSTANT; } + YY_BREAK +case 96: +YY_RULE_SETUP +{ yylval->lex.i = static_cast(strtol(yytext, 0, 0)); return INTCONSTANT; } + YY_BREAK +case 97: +YY_RULE_SETUP +{ yylval->lex.f = static_cast(atof_dot(yytext)); return FLOATCONSTANT; } + YY_BREAK +case 98: +YY_RULE_SETUP +{ yylval->lex.f = static_cast(atof_dot(yytext)); return FLOATCONSTANT; } + YY_BREAK case 99: YY_RULE_SETUP -{ yylval->lex.i = static_cast(strtol(yytext, 0, 0)); return(INTCONSTANT); } +{ yylval->lex.f = static_cast(atof_dot(yytext)); return FLOATCONSTANT; } YY_BREAK case 100: YY_RULE_SETUP -{ yylval->lex.i = static_cast(strtol(yytext, 0, 0)); return(INTCONSTANT); } +{ return ADD_ASSIGN; } YY_BREAK case 101: YY_RULE_SETUP -{ context->error(yylineno, "Invalid Octal number.", yytext); context->recover(); return 0;} +{ return SUB_ASSIGN; } YY_BREAK case 102: YY_RULE_SETUP -{ yylval->lex.i = static_cast(strtol(yytext, 0, 0)); return(INTCONSTANT); } +{ return MUL_ASSIGN; } YY_BREAK case 103: YY_RULE_SETUP -{ yylval->lex.f = static_cast(atof_dot(yytext)); return(FLOATCONSTANT); } +{ return DIV_ASSIGN; } YY_BREAK case 104: YY_RULE_SETUP -{ yylval->lex.f = static_cast(atof_dot(yytext)); return(FLOATCONSTANT); } +{ return MOD_ASSIGN; } YY_BREAK case 105: YY_RULE_SETUP -{ yylval->lex.f = static_cast(atof_dot(yytext)); return(FLOATCONSTANT); } +{ return LEFT_ASSIGN; } YY_BREAK case 106: YY_RULE_SETUP -{ return(ADD_ASSIGN); } +{ return RIGHT_ASSIGN; } YY_BREAK case 107: YY_RULE_SETUP -{ return(SUB_ASSIGN); } +{ return AND_ASSIGN; } YY_BREAK case 108: YY_RULE_SETUP -{ return(MUL_ASSIGN); } +{ return XOR_ASSIGN; } YY_BREAK case 109: YY_RULE_SETUP -{ return(DIV_ASSIGN); } +{ return OR_ASSIGN; } YY_BREAK case 110: YY_RULE_SETUP -{ return(MOD_ASSIGN); } +{ return INC_OP; } YY_BREAK case 111: YY_RULE_SETUP -{ return(LEFT_ASSIGN); } +{ return DEC_OP; } YY_BREAK case 112: YY_RULE_SETUP -{ return(RIGHT_ASSIGN); } +{ return AND_OP; } YY_BREAK case 113: YY_RULE_SETUP -{ return(AND_ASSIGN); } +{ return OR_OP; } YY_BREAK case 114: YY_RULE_SETUP -{ return(XOR_ASSIGN); } +{ return XOR_OP; } YY_BREAK case 115: YY_RULE_SETUP -{ return(OR_ASSIGN); } +{ return LE_OP; } YY_BREAK case 116: YY_RULE_SETUP -{ return(INC_OP); } +{ return GE_OP; } YY_BREAK case 117: YY_RULE_SETUP -{ return(DEC_OP); } +{ return EQ_OP; } YY_BREAK case 118: YY_RULE_SETUP -{ return(AND_OP); } +{ return NE_OP; } YY_BREAK case 119: YY_RULE_SETUP -{ return(OR_OP); } +{ return LEFT_OP; } YY_BREAK case 120: YY_RULE_SETUP -{ return(XOR_OP); } +{ return RIGHT_OP; } YY_BREAK case 121: YY_RULE_SETUP -{ return(LE_OP); } +{ return SEMICOLON; } YY_BREAK case 122: YY_RULE_SETUP -{ return(GE_OP); } +{ return LEFT_BRACE; } YY_BREAK case 123: YY_RULE_SETUP -{ return(EQ_OP); } +{ return RIGHT_BRACE; } YY_BREAK case 124: YY_RULE_SETUP -{ return(NE_OP); } +{ return COMMA; } YY_BREAK case 125: YY_RULE_SETUP -{ return(LEFT_OP); } +{ return COLON; } YY_BREAK case 126: YY_RULE_SETUP -{ return(RIGHT_OP); } +{ return EQUAL; } YY_BREAK case 127: YY_RULE_SETUP -{ context->lexAfterType = false; return(SEMICOLON); } +{ return LEFT_PAREN; } YY_BREAK case 128: YY_RULE_SETUP -{ context->lexAfterType = false; return(LEFT_BRACE); } +{ return RIGHT_PAREN; } YY_BREAK case 129: YY_RULE_SETUP -{ return(RIGHT_BRACE); } +{ return LEFT_BRACKET; } YY_BREAK case 130: YY_RULE_SETUP -{ if (context->inTypeParen) context->lexAfterType = false; return(COMMA); } +{ return RIGHT_BRACKET; } YY_BREAK case 131: YY_RULE_SETUP -{ return(COLON); } +{ return DOT; } YY_BREAK case 132: YY_RULE_SETUP -{ context->lexAfterType = false; return(EQUAL); } +{ return BANG; } YY_BREAK case 133: YY_RULE_SETUP -{ context->lexAfterType = false; context->inTypeParen = true; return(LEFT_PAREN); } +{ return DASH; } YY_BREAK case 134: YY_RULE_SETUP -{ context->inTypeParen = false; return(RIGHT_PAREN); } +{ return TILDE; } YY_BREAK case 135: YY_RULE_SETUP -{ return(LEFT_BRACKET); } +{ return PLUS; } YY_BREAK case 136: YY_RULE_SETUP -{ return(RIGHT_BRACKET); } +{ return STAR; } YY_BREAK case 137: YY_RULE_SETUP -{ BEGIN(FIELDS); return(DOT); } +{ return SLASH; } YY_BREAK case 138: YY_RULE_SETUP -{ return(BANG); } +{ return PERCENT; } YY_BREAK case 139: YY_RULE_SETUP -{ return(DASH); } +{ return LEFT_ANGLE; } YY_BREAK case 140: YY_RULE_SETUP -{ return(TILDE); } +{ return RIGHT_ANGLE; } YY_BREAK case 141: YY_RULE_SETUP -{ return(PLUS); } +{ return VERTICAL_BAR; } YY_BREAK case 142: YY_RULE_SETUP -{ return(STAR); } +{ return CARET; } YY_BREAK case 143: YY_RULE_SETUP -{ return(SLASH); } +{ return AMPERSAND; } YY_BREAK case 144: YY_RULE_SETUP -{ return(PERCENT); } +{ return QUESTION; } YY_BREAK case 145: +/* rule 145 can match eol */ YY_RULE_SETUP -{ return(LEFT_ANGLE); } +{ } + YY_BREAK +case YY_STATE_EOF(INITIAL): +{ yyterminate(); } YY_BREAK case 146: YY_RULE_SETUP -{ return(RIGHT_ANGLE); } +{ assert(false); return 0; } YY_BREAK case 147: YY_RULE_SETUP -{ return(VERTICAL_BAR); } - YY_BREAK -case 148: -YY_RULE_SETUP -{ return(CARET); } - YY_BREAK -case 149: -YY_RULE_SETUP -{ return(AMPERSAND); } - YY_BREAK -case 150: -YY_RULE_SETUP -{ return(QUESTION); } - YY_BREAK -case 151: -YY_RULE_SETUP -{ - BEGIN(INITIAL); - yylval->lex.string = NewPoolTString(yytext); - return FIELD_SELECTION; -} - YY_BREAK -case 152: -YY_RULE_SETUP -{} - YY_BREAK -case 153: -/* rule 153 can match eol */ -YY_RULE_SETUP -{ } - YY_BREAK -case YY_STATE_EOF(INITIAL): -case YY_STATE_EOF(COMMENT): -case YY_STATE_EOF(FIELDS): -{ context->AfterEOF = true; yyterminate(); } - YY_BREAK -case 154: -YY_RULE_SETUP -{ context->warning(yylineno, "Unknown char", yytext, ""); return 0; } - YY_BREAK -case 155: -YY_RULE_SETUP ECHO; YY_BREAK @@ -2071,7 +2010,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 459 ) + if ( yy_current_state >= 443 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; @@ -2100,11 +2039,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 459 ) + if ( yy_current_state >= 443 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - yy_is_jam = (yy_current_state == 458); + yy_is_jam = (yy_current_state == 442); return yy_is_jam ? 0 : yy_current_state; } @@ -2158,7 +2097,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) case EOB_ACT_END_OF_FILE: { if ( yywrap(yyscanner ) ) - return 0; + return EOF; if ( ! yyg->yy_did_buffer_switch_on_eof ) YY_NEW_FILE; @@ -2548,46 +2487,6 @@ YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len return b; } - static void yy_push_state (int new_state , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - if ( yyg->yy_start_stack_ptr >= yyg->yy_start_stack_depth ) - { - yy_size_t new_size; - - yyg->yy_start_stack_depth += YY_START_STACK_INCR; - new_size = yyg->yy_start_stack_depth * sizeof( int ); - - if ( ! yyg->yy_start_stack ) - yyg->yy_start_stack = (int *) yyalloc(new_size ,yyscanner ); - - else - yyg->yy_start_stack = (int *) yyrealloc((void *) yyg->yy_start_stack,new_size ,yyscanner ); - - if ( ! yyg->yy_start_stack ) - YY_FATAL_ERROR( "out of memory expanding start-condition stack" ); - } - - yyg->yy_start_stack[yyg->yy_start_stack_ptr++] = YY_START; - - BEGIN(new_state); -} - - static void yy_pop_state (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - if ( --yyg->yy_start_stack_ptr < 0 ) - YY_FATAL_ERROR( "start-condition stack underflow" ); - - BEGIN(yyg->yy_start_stack[yyg->yy_start_stack_ptr]); -} - - static int yy_top_state (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - return yyg->yy_start_stack[yyg->yy_start_stack_ptr - 1]; -} - #ifndef YY_EXIT_FAILURE #define YY_EXIT_FAILURE 2 #endif @@ -2773,6 +2672,18 @@ void yyset_lval (YYSTYPE * yylval_param , yyscan_t yyscanner) yylval = yylval_param; } +YYLTYPE *yyget_lloc (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yylloc; +} + +void yyset_lloc (YYLTYPE * yylloc_param , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yylloc = yylloc_param; +} + /* User-visible API */ /* yylex_init is special because it creates the scanner itself, so it is @@ -2954,7 +2865,8 @@ yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner) { yy_size_t len = token.type == pp::Token::LAST ? 0 : token.text.size(); if (len < max_size) memcpy(buf, token.text.c_str(), len); - yyset_lineno(EncodeSourceLoc(token.location.file, token.location.line),yyscanner); + yyset_column(token.location.file,yyscanner); + yyset_lineno(token.location.line,yyscanner); if (len >= max_size) YY_FATAL_ERROR("Input buffer overflow"); @@ -2968,12 +2880,10 @@ int check_type(yyscan_t yyscanner) { int token = IDENTIFIER; TSymbol* symbol = yyextra->symbolTable.find(yytext); - if (yyextra->lexAfterType == false && symbol && symbol->isVariable()) { + if (symbol && symbol->isVariable()) { TVariable* variable = static_cast(symbol); - if (variable->isUserType()) { - yyextra->lexAfterType = true; + if (variable->isUserType()) token = TYPE_NAME; - } } yylval->lex.symbol = symbol; return token; @@ -2982,22 +2892,11 @@ int check_type(yyscan_t yyscanner) { int reserved_word(yyscan_t yyscanner) { struct yyguts_t* yyg = (struct yyguts_t*) yyscanner; - yyextra->error(yylineno, "Illegal use of reserved word", yytext, ""); + yyextra->error(*yylloc, "Illegal use of reserved word", yytext, ""); yyextra->recover(); return 0; } -void yyerror(TParseContext* context, const char* reason) { - struct yyguts_t* yyg = (struct yyguts_t*) context->scanner; - - if (context->AfterEOF) { - context->error(yylineno, reason, "unexpected EOF"); - } else { - context->error(yylineno, reason, yytext); - } - context->recover(); -} - int glslang_initialize(TParseContext* context) { yyscan_t scanner = NULL; if (yylex_init_extra(context,&scanner)) @@ -3020,8 +2919,8 @@ int glslang_finalize(TParseContext* context) { int glslang_scan(size_t count, const char* const string[], const int length[], TParseContext* context) { yyrestart(NULL,context->scanner); - yyset_lineno(EncodeSourceLoc(0, 1),context->scanner); - context->AfterEOF = false; + yyset_column(0,context->scanner); + yyset_lineno(1,context->scanner); // Initialize preprocessor. if (!context->preprocessor.init(count, string, length)) diff --git a/gfx/angle/src/compiler/glslang_tab.cpp b/gfx/angle/src/compiler/glslang_tab.cpp index 2231728cbff3..7afd4ca89146 100644 --- a/gfx/angle/src/compiler/glslang_tab.cpp +++ b/gfx/angle/src/compiler/glslang_tab.cpp @@ -1,9 +1,8 @@ -/* A Bison parser, made by GNU Bison 2.4.2. */ +/* A Bison parser, made by GNU Bison 2.7. */ -/* Skeleton implementation for Bison's Yacc-like parsers in C +/* Bison implementation for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2006, 2009-2010 Free Software - Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -45,7 +44,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "2.4.2" +#define YYBISON_VERSION "2.7" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -59,8 +58,6 @@ /* Pull parsers. */ #define YYPULL 1 -/* Using locations. */ -#define YYLSP_NEEDED 0 @@ -92,16 +89,18 @@ #include "GLSLANG/ShaderLang.h" #define YYENABLE_NLS 0 -#define YYLTYPE_IS_TRIVIAL 1 #define YYLEX_PARAM context->scanner -/* Enabling traces. */ -#ifndef YYDEBUG -# define YYDEBUG 0 -#endif +# ifndef YY_NULL +# if defined __cplusplus && 201103L <= __cplusplus +# define YY_NULL nullptr +# else +# define YY_NULL 0 +# endif +# endif /* Enabling verbose error messages. */ #ifdef YYERROR_VERBOSE @@ -111,10 +110,24 @@ # define YYERROR_VERBOSE 0 #endif -/* Enabling the token table. */ -#ifndef YYTOKEN_TABLE -# define YYTOKEN_TABLE 0 +/* In a future release of Bison, this section will be replaced + by #include "glslang_tab.h". */ +#ifndef YY_YY_GLSLANG_TAB_H_INCLUDED +# define YY_YY_GLSLANG_TAB_H_INCLUDED +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 #endif +#if YYDEBUG +extern int yydebug; +#endif +/* "%code requires" blocks. */ + + +#define YYLTYPE TSourceLoc +#define YYLTYPE_IS_DECLARED 1 + + /* Tokens. */ @@ -170,64 +183,61 @@ FLOATCONSTANT = 302, INTCONSTANT = 303, BOOLCONSTANT = 304, - FIELD_SELECTION = 305, - LEFT_OP = 306, - RIGHT_OP = 307, - INC_OP = 308, - DEC_OP = 309, - LE_OP = 310, - GE_OP = 311, - EQ_OP = 312, - NE_OP = 313, - AND_OP = 314, - OR_OP = 315, - XOR_OP = 316, - MUL_ASSIGN = 317, - DIV_ASSIGN = 318, - ADD_ASSIGN = 319, - MOD_ASSIGN = 320, - LEFT_ASSIGN = 321, - RIGHT_ASSIGN = 322, - AND_ASSIGN = 323, - XOR_ASSIGN = 324, - OR_ASSIGN = 325, - SUB_ASSIGN = 326, - LEFT_PAREN = 327, - RIGHT_PAREN = 328, - LEFT_BRACKET = 329, - RIGHT_BRACKET = 330, - LEFT_BRACE = 331, - RIGHT_BRACE = 332, - DOT = 333, - COMMA = 334, - COLON = 335, - EQUAL = 336, - SEMICOLON = 337, - BANG = 338, - DASH = 339, - TILDE = 340, - PLUS = 341, - STAR = 342, - SLASH = 343, - PERCENT = 344, - LEFT_ANGLE = 345, - RIGHT_ANGLE = 346, - VERTICAL_BAR = 347, - CARET = 348, - AMPERSAND = 349, - QUESTION = 350 + LEFT_OP = 305, + RIGHT_OP = 306, + INC_OP = 307, + DEC_OP = 308, + LE_OP = 309, + GE_OP = 310, + EQ_OP = 311, + NE_OP = 312, + AND_OP = 313, + OR_OP = 314, + XOR_OP = 315, + MUL_ASSIGN = 316, + DIV_ASSIGN = 317, + ADD_ASSIGN = 318, + MOD_ASSIGN = 319, + LEFT_ASSIGN = 320, + RIGHT_ASSIGN = 321, + AND_ASSIGN = 322, + XOR_ASSIGN = 323, + OR_ASSIGN = 324, + SUB_ASSIGN = 325, + LEFT_PAREN = 326, + RIGHT_PAREN = 327, + LEFT_BRACKET = 328, + RIGHT_BRACKET = 329, + LEFT_BRACE = 330, + RIGHT_BRACE = 331, + DOT = 332, + COMMA = 333, + COLON = 334, + EQUAL = 335, + SEMICOLON = 336, + BANG = 337, + DASH = 338, + TILDE = 339, + PLUS = 340, + STAR = 341, + SLASH = 342, + PERCENT = 343, + LEFT_ANGLE = 344, + RIGHT_ANGLE = 345, + VERTICAL_BAR = 346, + CARET = 347, + AMPERSAND = 348, + QUESTION = 349 }; #endif - #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE { struct { - TSourceLoc line; union { TString *string; float f; @@ -237,7 +247,6 @@ typedef union YYSTYPE TSymbol* symbol; } lex; struct { - TSourceLoc line; TOperator op; union { TIntermNode* intermNode; @@ -251,8 +260,8 @@ typedef union YYSTYPE TQualifier qualifier; TFunction* function; TParameter param; - TTypeLine typeLine; - TTypeList* typeList; + TField* field; + TFieldList* fieldList; }; } interm; @@ -264,20 +273,57 @@ typedef union YYSTYPE # define YYSTYPE_IS_DECLARED 1 #endif +#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED +typedef struct YYLTYPE +{ + int first_line; + int first_column; + int last_line; + int last_column; +} YYLTYPE; +# define yyltype YYLTYPE /* obsolescent; will be withdrawn */ +# define YYLTYPE_IS_DECLARED 1 +# define YYLTYPE_IS_TRIVIAL 1 +#endif + + +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int yyparse (void *YYPARSE_PARAM); +#else +int yyparse (); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int yyparse (TParseContext* context); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ + +#endif /* !YY_YY_GLSLANG_TAB_H_INCLUDED */ /* Copy the second part of user declarations. */ -extern int yylex(YYSTYPE* yylval_param, void* yyscanner); -extern void yyerror(TParseContext* context, const char* reason); +extern int yylex(YYSTYPE* yylval, YYLTYPE* yylloc, void* yyscanner); +static void yyerror(YYLTYPE* yylloc, TParseContext* context, const char* reason); -#define FRAG_VERT_ONLY(S, L) { \ - if (context->shaderType != SH_FRAGMENT_SHADER && \ - context->shaderType != SH_VERTEX_SHADER) { \ - context->error(L, " supported in vertex/fragment shaders only ", S); \ - context->recover(); \ - } \ -} +#define YYLLOC_DEFAULT(Current, Rhs, N) \ + do { \ + if (YYID(N)) { \ + (Current).first_file = YYRHSLOC(Rhs, 1).first_file; \ + (Current).first_line = YYRHSLOC(Rhs, 1).first_line; \ + (Current).last_file = YYRHSLOC(Rhs, N).last_file; \ + (Current).last_line = YYRHSLOC(Rhs, N).last_line; \ + } \ + else { \ + (Current).first_file = YYRHSLOC(Rhs, 0).last_file; \ + (Current).first_line = YYRHSLOC(Rhs, 0).last_line; \ + (Current).last_file = YYRHSLOC(Rhs, 0).last_file; \ + (Current).last_line = YYRHSLOC(Rhs, 0).last_line; \ + } \ + } while (0) #define VERTEX_ONLY(S, L) { \ if (context->shaderType != SH_VERTEX_SHADER) { \ @@ -346,24 +392,24 @@ typedef short int yytype_int16; # if defined YYENABLE_NLS && YYENABLE_NLS # if ENABLE_NLS # include /* INFRINGES ON USER NAME SPACE */ -# define YY_(msgid) dgettext ("bison-runtime", msgid) +# define YY_(Msgid) dgettext ("bison-runtime", Msgid) # endif # endif # ifndef YY_ -# define YY_(msgid) msgid +# define YY_(Msgid) Msgid # endif #endif /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ -# define YYUSE(e) ((void) (e)) +# define YYUSE(E) ((void) (E)) #else -# define YYUSE(e) /* empty */ +# define YYUSE(E) /* empty */ #endif /* Identity function, used to suppress warnings about constant conditions. */ #ifndef lint -# define YYID(n) (n) +# define YYID(N) (N) #else #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) @@ -396,11 +442,12 @@ YYID (yyi) # define alloca _alloca # else # define YYSTACK_ALLOC alloca -# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ +# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ -# ifndef _STDLIB_H -# define _STDLIB_H 1 + /* Use EXIT_SUCCESS as a witness for stdlib.h. */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 # endif # endif # endif @@ -423,24 +470,24 @@ YYID (yyi) # ifndef YYSTACK_ALLOC_MAXIMUM # define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM # endif -# if (defined __cplusplus && ! defined _STDLIB_H \ +# if (defined __cplusplus && ! defined EXIT_SUCCESS \ && ! ((defined YYMALLOC || defined malloc) \ && (defined YYFREE || defined free))) # include /* INFRINGES ON USER NAME SPACE */ -# ifndef _STDLIB_H -# define _STDLIB_H 1 +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 # endif # endif # ifndef YYMALLOC # define YYMALLOC malloc -# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ +# if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef YYFREE # define YYFREE free -# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ +# if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif @@ -451,13 +498,15 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */ #if (! defined yyoverflow \ && (! defined __cplusplus \ - || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \ + && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) /* A type that is properly aligned for any stack member. */ union yyalloc { yytype_int16 yyss_alloc; YYSTYPE yyvs_alloc; + YYLTYPE yyls_alloc; }; /* The size of the maximum gap between one aligned stack and the next. */ @@ -466,26 +515,10 @@ union yyalloc /* The size of an array large to enough to hold all stacks, each with N elements. */ # define YYSTACK_BYTES(N) \ - ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ - + YYSTACK_GAP_MAXIMUM) + ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \ + + 2 * YYSTACK_GAP_MAXIMUM) -/* Copy COUNT objects from FROM to TO. The source and destination do - not overlap. */ -# ifndef YYCOPY -# if defined __GNUC__ && 1 < __GNUC__ -# define YYCOPY(To, From, Count) \ - __builtin_memcpy (To, From, (Count) * sizeof (*(From))) -# else -# define YYCOPY(To, From, Count) \ - do \ - { \ - YYSIZE_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (To)[yyi] = (From)[yyi]; \ - } \ - while (YYID (0)) -# endif -# endif +# define YYCOPY_NEEDED 1 /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of @@ -505,23 +538,43 @@ union yyalloc #endif +#if defined YYCOPY_NEEDED && YYCOPY_NEEDED +/* Copy COUNT objects from SRC to DST. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(Dst, Src, Count) \ + __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) +# else +# define YYCOPY(Dst, Src, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (Dst)[yyi] = (Src)[yyi]; \ + } \ + while (YYID (0)) +# endif +# endif +#endif /* !YYCOPY_NEEDED */ + /* YYFINAL -- State number of the termination state. */ -#define YYFINAL 71 +#define YYFINAL 74 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 1416 +#define YYLAST 1490 /* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 96 +#define YYNTOKENS 95 /* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 83 +#define YYNNTS 84 /* YYNRULES -- Number of rules. */ -#define YYNRULES 201 +#define YYNRULES 202 /* YYNRULES -- Number of states. */ -#define YYNSTATES 304 +#define YYNSTATES 307 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 -#define YYMAXUTOK 350 +#define YYMAXUTOK 349 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) @@ -563,8 +616,7 @@ static const yytype_uint8 yytranslate[] = 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, - 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, - 95 + 85, 86, 87, 88, 89, 90, 91, 92, 93, 94 }; #if YYDEBUG @@ -572,119 +624,120 @@ static const yytype_uint8 yytranslate[] = YYRHS. */ static const yytype_uint16 yyprhs[] = { - 0, 0, 3, 5, 7, 9, 11, 13, 17, 19, - 24, 26, 30, 33, 36, 38, 40, 42, 46, 49, - 52, 55, 57, 60, 64, 67, 69, 71, 73, 75, - 78, 81, 84, 86, 88, 90, 92, 96, 100, 102, - 106, 110, 112, 114, 118, 122, 126, 130, 132, 136, - 140, 142, 144, 146, 148, 152, 154, 158, 160, 164, - 166, 172, 174, 178, 180, 182, 184, 186, 188, 190, - 194, 196, 199, 202, 207, 210, 212, 214, 217, 221, - 225, 228, 234, 238, 241, 245, 248, 249, 251, 253, - 255, 257, 259, 263, 269, 276, 282, 284, 287, 292, - 298, 303, 306, 308, 311, 313, 315, 317, 320, 322, - 324, 327, 329, 331, 333, 335, 340, 342, 344, 346, + 0, 0, 3, 5, 7, 9, 11, 13, 15, 17, + 21, 23, 28, 30, 34, 37, 40, 42, 44, 46, + 50, 53, 56, 59, 61, 64, 68, 71, 73, 75, + 77, 80, 83, 86, 88, 90, 92, 94, 98, 102, + 104, 108, 112, 114, 116, 120, 124, 128, 132, 134, + 138, 142, 144, 146, 148, 150, 154, 156, 160, 162, + 166, 168, 174, 176, 180, 182, 184, 186, 188, 190, + 192, 196, 198, 201, 204, 209, 212, 214, 216, 219, + 223, 227, 230, 236, 240, 243, 247, 250, 251, 253, + 255, 257, 259, 261, 265, 271, 278, 284, 286, 289, + 294, 300, 305, 308, 310, 313, 315, 317, 319, 322, + 324, 326, 329, 331, 333, 335, 337, 342, 344, 346, 348, 350, 352, 354, 356, 358, 360, 362, 364, 366, - 368, 370, 372, 374, 376, 378, 380, 382, 384, 385, - 392, 393, 399, 401, 404, 408, 410, 414, 416, 421, - 423, 425, 427, 429, 431, 433, 435, 437, 439, 442, - 443, 444, 450, 452, 454, 455, 458, 459, 462, 465, - 469, 471, 474, 476, 479, 485, 489, 491, 493, 498, - 499, 506, 507, 516, 517, 525, 527, 529, 531, 532, - 535, 539, 542, 545, 548, 552, 555, 557, 560, 562, - 564, 565 + 368, 370, 372, 374, 376, 378, 380, 382, 384, 386, + 387, 394, 395, 401, 403, 406, 410, 412, 416, 418, + 423, 425, 427, 429, 431, 433, 435, 437, 439, 441, + 444, 445, 446, 452, 454, 456, 457, 460, 461, 464, + 467, 471, 473, 476, 478, 481, 487, 491, 493, 495, + 500, 501, 508, 509, 518, 519, 527, 529, 531, 533, + 534, 537, 541, 544, 547, 550, 554, 557, 559, 562, + 564, 566, 567 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int16 yyrhs[] = { - 175, 0, -1, 45, -1, 97, -1, 48, -1, 47, - -1, 49, -1, 72, 124, 73, -1, 98, -1, 99, - 74, 100, 75, -1, 101, -1, 99, 78, 50, -1, - 99, 53, -1, 99, 54, -1, 124, -1, 102, -1, - 103, -1, 99, 78, 103, -1, 105, 73, -1, 104, - 73, -1, 106, 39, -1, 106, -1, 106, 122, -1, - 105, 79, 122, -1, 107, 72, -1, 142, -1, 45, - -1, 50, -1, 99, -1, 53, 108, -1, 54, 108, - -1, 109, 108, -1, 86, -1, 84, -1, 83, -1, - 108, -1, 110, 87, 108, -1, 110, 88, 108, -1, - 110, -1, 111, 86, 110, -1, 111, 84, 110, -1, - 111, -1, 112, -1, 113, 90, 112, -1, 113, 91, - 112, -1, 113, 55, 112, -1, 113, 56, 112, -1, - 113, -1, 114, 57, 113, -1, 114, 58, 113, -1, - 114, -1, 115, -1, 116, -1, 117, -1, 118, 59, - 117, -1, 118, -1, 119, 61, 118, -1, 119, -1, - 120, 60, 119, -1, 120, -1, 120, 95, 124, 80, - 122, -1, 121, -1, 108, 123, 122, -1, 81, -1, - 62, -1, 63, -1, 64, -1, 71, -1, 122, -1, - 124, 79, 122, -1, 121, -1, 127, 82, -1, 135, - 82, -1, 7, 140, 141, 82, -1, 128, 73, -1, - 130, -1, 129, -1, 130, 132, -1, 129, 79, 132, - -1, 137, 45, 72, -1, 139, 45, -1, 139, 45, - 74, 125, 75, -1, 138, 133, 131, -1, 133, 131, - -1, 138, 133, 134, -1, 133, 134, -1, -1, 33, - -1, 34, -1, 35, -1, 139, -1, 136, -1, 135, - 79, 45, -1, 135, 79, 45, 74, 75, -1, 135, - 79, 45, 74, 125, 75, -1, 135, 79, 45, 81, - 150, -1, 137, -1, 137, 45, -1, 137, 45, 74, - 75, -1, 137, 45, 74, 125, 75, -1, 137, 45, - 81, 150, -1, 3, 45, -1, 139, -1, 138, 139, - -1, 9, -1, 8, -1, 37, -1, 3, 37, -1, - 36, -1, 141, -1, 140, 141, -1, 4, -1, 5, - -1, 6, -1, 142, -1, 142, 74, 125, 75, -1, - 39, -1, 11, -1, 12, -1, 10, -1, 27, -1, - 28, -1, 29, -1, 21, -1, 22, -1, 23, -1, - 24, -1, 25, -1, 26, -1, 30, -1, 31, -1, - 32, -1, 41, -1, 42, -1, 43, -1, 44, -1, - 143, -1, 46, -1, -1, 38, 45, 76, 144, 146, - 77, -1, -1, 38, 76, 145, 146, 77, -1, 147, - -1, 146, 147, -1, 139, 148, 82, -1, 149, -1, - 148, 79, 149, -1, 45, -1, 45, 74, 125, 75, - -1, 122, -1, 126, -1, 154, -1, 153, -1, 151, - -1, 163, -1, 164, -1, 167, -1, 174, -1, 76, - 77, -1, -1, -1, 76, 155, 162, 156, 77, -1, - 161, -1, 153, -1, -1, 159, 161, -1, -1, 160, - 153, -1, 76, 77, -1, 76, 162, 77, -1, 152, - -1, 162, 152, -1, 82, -1, 124, 82, -1, 18, - 72, 124, 73, 165, -1, 158, 16, 158, -1, 158, - -1, 124, -1, 137, 45, 81, 150, -1, -1, 40, - 72, 168, 166, 73, 157, -1, -1, 15, 169, 158, - 40, 72, 124, 73, 82, -1, -1, 17, 72, 170, - 171, 173, 73, 157, -1, 163, -1, 151, -1, 166, - -1, -1, 172, 82, -1, 172, 82, 124, -1, 14, - 82, -1, 13, 82, -1, 20, 82, -1, 20, 124, - 82, -1, 19, 82, -1, 176, -1, 175, 176, -1, - 177, -1, 126, -1, -1, 127, 178, 161, -1 + 175, 0, -1, 45, -1, 46, -1, 45, -1, 97, + -1, 48, -1, 47, -1, 49, -1, 71, 124, 72, + -1, 98, -1, 99, 73, 100, 74, -1, 101, -1, + 99, 77, 96, -1, 99, 52, -1, 99, 53, -1, + 124, -1, 102, -1, 103, -1, 99, 77, 103, -1, + 105, 72, -1, 104, 72, -1, 106, 39, -1, 106, + -1, 106, 122, -1, 105, 78, 122, -1, 107, 71, + -1, 142, -1, 45, -1, 99, -1, 52, 108, -1, + 53, 108, -1, 109, 108, -1, 85, -1, 83, -1, + 82, -1, 108, -1, 110, 86, 108, -1, 110, 87, + 108, -1, 110, -1, 111, 85, 110, -1, 111, 83, + 110, -1, 111, -1, 112, -1, 113, 89, 112, -1, + 113, 90, 112, -1, 113, 54, 112, -1, 113, 55, + 112, -1, 113, -1, 114, 56, 113, -1, 114, 57, + 113, -1, 114, -1, 115, -1, 116, -1, 117, -1, + 118, 58, 117, -1, 118, -1, 119, 60, 118, -1, + 119, -1, 120, 59, 119, -1, 120, -1, 120, 94, + 124, 79, 122, -1, 121, -1, 108, 123, 122, -1, + 80, -1, 61, -1, 62, -1, 63, -1, 70, -1, + 122, -1, 124, 78, 122, -1, 121, -1, 127, 81, + -1, 135, 81, -1, 7, 140, 141, 81, -1, 128, + 72, -1, 130, -1, 129, -1, 130, 132, -1, 129, + 78, 132, -1, 137, 45, 71, -1, 139, 96, -1, + 139, 96, 73, 125, 74, -1, 138, 133, 131, -1, + 133, 131, -1, 138, 133, 134, -1, 133, 134, -1, + -1, 33, -1, 34, -1, 35, -1, 139, -1, 136, + -1, 135, 78, 96, -1, 135, 78, 96, 73, 74, + -1, 135, 78, 96, 73, 125, 74, -1, 135, 78, + 96, 80, 150, -1, 137, -1, 137, 96, -1, 137, + 96, 73, 74, -1, 137, 96, 73, 125, 74, -1, + 137, 96, 80, 150, -1, 3, 45, -1, 139, -1, + 138, 139, -1, 9, -1, 8, -1, 37, -1, 3, + 37, -1, 36, -1, 141, -1, 140, 141, -1, 4, + -1, 5, -1, 6, -1, 142, -1, 142, 73, 125, + 74, -1, 39, -1, 11, -1, 12, -1, 10, -1, + 27, -1, 28, -1, 29, -1, 21, -1, 22, -1, + 23, -1, 24, -1, 25, -1, 26, -1, 30, -1, + 31, -1, 32, -1, 41, -1, 42, -1, 43, -1, + 44, -1, 143, -1, 46, -1, -1, 38, 96, 75, + 144, 146, 76, -1, -1, 38, 75, 145, 146, 76, + -1, 147, -1, 146, 147, -1, 139, 148, 81, -1, + 149, -1, 148, 78, 149, -1, 96, -1, 96, 73, + 125, 74, -1, 122, -1, 126, -1, 154, -1, 153, + -1, 151, -1, 163, -1, 164, -1, 167, -1, 174, + -1, 75, 76, -1, -1, -1, 75, 155, 162, 156, + 76, -1, 161, -1, 153, -1, -1, 159, 161, -1, + -1, 160, 153, -1, 75, 76, -1, 75, 162, 76, + -1, 152, -1, 162, 152, -1, 81, -1, 124, 81, + -1, 18, 71, 124, 72, 165, -1, 158, 16, 158, + -1, 158, -1, 124, -1, 137, 96, 80, 150, -1, + -1, 40, 71, 168, 166, 72, 157, -1, -1, 15, + 169, 158, 40, 71, 124, 72, 81, -1, -1, 17, + 71, 170, 171, 173, 72, 157, -1, 163, -1, 151, + -1, 166, -1, -1, 172, 81, -1, 172, 81, 124, + -1, 14, 81, -1, 13, 81, -1, 20, 81, -1, + 20, 124, 81, -1, 19, 81, -1, 176, -1, 175, + 176, -1, 177, -1, 126, -1, -1, 127, 178, 161, + -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { - 0, 168, 168, 203, 206, 219, 224, 229, 235, 238, - 317, 320, 421, 431, 444, 452, 552, 555, 563, 567, - 574, 578, 585, 591, 600, 608, 663, 670, 680, 683, - 693, 703, 724, 725, 726, 731, 732, 741, 753, 754, - 762, 773, 777, 778, 788, 798, 808, 821, 822, 832, - 845, 849, 853, 857, 858, 871, 872, 885, 886, 899, - 900, 917, 918, 931, 932, 933, 934, 935, 939, 942, - 953, 961, 988, 993, 1007, 1045, 1048, 1055, 1063, 1084, - 1105, 1116, 1145, 1150, 1160, 1165, 1175, 1178, 1181, 1184, - 1190, 1197, 1200, 1222, 1240, 1264, 1287, 1291, 1309, 1317, - 1349, 1369, 1458, 1467, 1490, 1493, 1499, 1507, 1515, 1523, - 1533, 1540, 1543, 1546, 1552, 1555, 1570, 1574, 1578, 1582, - 1591, 1596, 1601, 1606, 1611, 1616, 1621, 1626, 1631, 1636, - 1642, 1648, 1654, 1659, 1664, 1673, 1682, 1687, 1700, 1700, - 1714, 1714, 1723, 1726, 1741, 1777, 1781, 1787, 1795, 1811, - 1815, 1819, 1820, 1826, 1827, 1828, 1829, 1830, 1834, 1835, - 1835, 1835, 1845, 1846, 1850, 1850, 1851, 1851, 1856, 1859, - 1869, 1872, 1878, 1879, 1883, 1891, 1895, 1905, 1910, 1927, - 1927, 1932, 1932, 1939, 1939, 1947, 1950, 1956, 1959, 1965, - 1969, 1976, 1983, 1990, 1997, 2008, 2017, 2021, 2028, 2031, - 2037, 2037 + 0, 179, 179, 180, 183, 226, 229, 242, 247, 252, + 258, 261, 264, 267, 362, 372, 385, 393, 493, 496, + 504, 507, 513, 517, 524, 530, 539, 547, 602, 612, + 615, 625, 635, 656, 657, 658, 663, 664, 672, 683, + 684, 692, 703, 707, 708, 718, 728, 738, 751, 752, + 762, 775, 779, 783, 787, 788, 801, 802, 815, 816, + 829, 830, 847, 848, 861, 862, 863, 864, 865, 869, + 872, 883, 891, 918, 923, 937, 992, 995, 1002, 1010, + 1031, 1052, 1062, 1090, 1095, 1105, 1110, 1120, 1123, 1126, + 1129, 1135, 1142, 1145, 1167, 1185, 1209, 1232, 1236, 1254, + 1262, 1294, 1314, 1335, 1344, 1367, 1370, 1376, 1384, 1392, + 1400, 1410, 1417, 1420, 1423, 1429, 1432, 1447, 1451, 1455, + 1459, 1463, 1468, 1473, 1478, 1483, 1488, 1493, 1498, 1503, + 1508, 1513, 1518, 1523, 1527, 1531, 1539, 1547, 1551, 1564, + 1564, 1578, 1578, 1587, 1590, 1606, 1639, 1643, 1649, 1656, + 1671, 1675, 1679, 1680, 1686, 1687, 1688, 1689, 1690, 1694, + 1695, 1695, 1695, 1705, 1706, 1710, 1710, 1711, 1711, 1716, + 1719, 1729, 1732, 1738, 1739, 1743, 1751, 1755, 1765, 1770, + 1787, 1787, 1792, 1792, 1799, 1799, 1807, 1810, 1816, 1819, + 1825, 1829, 1836, 1843, 1850, 1857, 1868, 1877, 1881, 1888, + 1891, 1897, 1897 }; #endif -#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE +#if YYDEBUG || YYERROR_VERBOSE || 0 /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = @@ -697,15 +750,15 @@ static const char *const yytname[] = "MATRIX3", "MATRIX4", "IN_QUAL", "OUT_QUAL", "INOUT_QUAL", "UNIFORM", "VARYING", "STRUCT", "VOID_TYPE", "WHILE", "SAMPLER2D", "SAMPLERCUBE", "SAMPLER_EXTERNAL_OES", "SAMPLER2DRECT", "IDENTIFIER", "TYPE_NAME", - "FLOATCONSTANT", "INTCONSTANT", "BOOLCONSTANT", "FIELD_SELECTION", - "LEFT_OP", "RIGHT_OP", "INC_OP", "DEC_OP", "LE_OP", "GE_OP", "EQ_OP", - "NE_OP", "AND_OP", "OR_OP", "XOR_OP", "MUL_ASSIGN", "DIV_ASSIGN", - "ADD_ASSIGN", "MOD_ASSIGN", "LEFT_ASSIGN", "RIGHT_ASSIGN", "AND_ASSIGN", - "XOR_ASSIGN", "OR_ASSIGN", "SUB_ASSIGN", "LEFT_PAREN", "RIGHT_PAREN", - "LEFT_BRACKET", "RIGHT_BRACKET", "LEFT_BRACE", "RIGHT_BRACE", "DOT", - "COMMA", "COLON", "EQUAL", "SEMICOLON", "BANG", "DASH", "TILDE", "PLUS", - "STAR", "SLASH", "PERCENT", "LEFT_ANGLE", "RIGHT_ANGLE", "VERTICAL_BAR", - "CARET", "AMPERSAND", "QUESTION", "$accept", "variable_identifier", + "FLOATCONSTANT", "INTCONSTANT", "BOOLCONSTANT", "LEFT_OP", "RIGHT_OP", + "INC_OP", "DEC_OP", "LE_OP", "GE_OP", "EQ_OP", "NE_OP", "AND_OP", + "OR_OP", "XOR_OP", "MUL_ASSIGN", "DIV_ASSIGN", "ADD_ASSIGN", + "MOD_ASSIGN", "LEFT_ASSIGN", "RIGHT_ASSIGN", "AND_ASSIGN", "XOR_ASSIGN", + "OR_ASSIGN", "SUB_ASSIGN", "LEFT_PAREN", "RIGHT_PAREN", "LEFT_BRACKET", + "RIGHT_BRACKET", "LEFT_BRACE", "RIGHT_BRACE", "DOT", "COMMA", "COLON", + "EQUAL", "SEMICOLON", "BANG", "DASH", "TILDE", "PLUS", "STAR", "SLASH", + "PERCENT", "LEFT_ANGLE", "RIGHT_ANGLE", "VERTICAL_BAR", "CARET", + "AMPERSAND", "QUESTION", "$accept", "identifier", "variable_identifier", "primary_expression", "postfix_expression", "integer_expression", "function_call", "function_call_or_method", "function_call_generic", "function_call_header_no_parameters", @@ -733,7 +786,7 @@ static const char *const yytname[] = "selection_rest_statement", "condition", "iteration_statement", "$@7", "$@8", "$@9", "for_init_statement", "conditionopt", "for_rest_statement", "jump_statement", "translation_unit", "external_declaration", - "function_definition", "$@10", 0 + "function_definition", "$@10", YY_NULL }; #endif @@ -751,461 +804,482 @@ static const yytype_uint16 yytoknum[] = 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, - 345, 346, 347, 348, 349, 350 + 345, 346, 347, 348, 349 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { - 0, 96, 97, 98, 98, 98, 98, 98, 99, 99, - 99, 99, 99, 99, 100, 101, 102, 102, 103, 103, - 104, 104, 105, 105, 106, 107, 107, 107, 108, 108, - 108, 108, 109, 109, 109, 110, 110, 110, 111, 111, - 111, 112, 113, 113, 113, 113, 113, 114, 114, 114, - 115, 116, 117, 118, 118, 119, 119, 120, 120, 121, - 121, 122, 122, 123, 123, 123, 123, 123, 124, 124, - 125, 126, 126, 126, 127, 128, 128, 129, 129, 130, - 131, 131, 132, 132, 132, 132, 133, 133, 133, 133, - 134, 135, 135, 135, 135, 135, 136, 136, 136, 136, - 136, 136, 137, 137, 138, 138, 138, 138, 138, 139, - 139, 140, 140, 140, 141, 141, 142, 142, 142, 142, + 0, 95, 96, 96, 97, 98, 98, 98, 98, 98, + 99, 99, 99, 99, 99, 99, 100, 101, 102, 102, + 103, 103, 104, 104, 105, 105, 106, 107, 107, 108, + 108, 108, 108, 109, 109, 109, 110, 110, 110, 111, + 111, 111, 112, 113, 113, 113, 113, 113, 114, 114, + 114, 115, 116, 117, 118, 118, 119, 119, 120, 120, + 121, 121, 122, 122, 123, 123, 123, 123, 123, 124, + 124, 125, 126, 126, 126, 127, 128, 128, 129, 129, + 130, 131, 131, 132, 132, 132, 132, 133, 133, 133, + 133, 134, 135, 135, 135, 135, 135, 136, 136, 136, + 136, 136, 136, 137, 137, 138, 138, 138, 138, 138, + 139, 139, 140, 140, 140, 141, 141, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, - 142, 142, 142, 142, 142, 142, 142, 142, 144, 143, - 145, 143, 146, 146, 147, 148, 148, 149, 149, 150, - 151, 152, 152, 153, 153, 153, 153, 153, 154, 155, - 156, 154, 157, 157, 159, 158, 160, 158, 161, 161, - 162, 162, 163, 163, 164, 165, 165, 166, 166, 168, - 167, 169, 167, 170, 167, 171, 171, 172, 172, 173, - 173, 174, 174, 174, 174, 174, 175, 175, 176, 176, - 178, 177 + 142, 142, 142, 142, 142, 142, 142, 142, 142, 144, + 143, 145, 143, 146, 146, 147, 148, 148, 149, 149, + 150, 151, 152, 152, 153, 153, 153, 153, 153, 154, + 155, 156, 154, 157, 157, 159, 158, 160, 158, 161, + 161, 162, 162, 163, 163, 164, 165, 165, 166, 166, + 168, 167, 169, 167, 170, 167, 171, 171, 172, 172, + 173, 173, 174, 174, 174, 174, 174, 175, 175, 176, + 176, 178, 177 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ static const yytype_uint8 yyr2[] = { - 0, 2, 1, 1, 1, 1, 1, 3, 1, 4, - 1, 3, 2, 2, 1, 1, 1, 3, 2, 2, - 2, 1, 2, 3, 2, 1, 1, 1, 1, 2, - 2, 2, 1, 1, 1, 1, 3, 3, 1, 3, - 3, 1, 1, 3, 3, 3, 3, 1, 3, 3, - 1, 1, 1, 1, 3, 1, 3, 1, 3, 1, - 5, 1, 3, 1, 1, 1, 1, 1, 1, 3, - 1, 2, 2, 4, 2, 1, 1, 2, 3, 3, - 2, 5, 3, 2, 3, 2, 0, 1, 1, 1, - 1, 1, 3, 5, 6, 5, 1, 2, 4, 5, - 4, 2, 1, 2, 1, 1, 1, 2, 1, 1, - 2, 1, 1, 1, 1, 4, 1, 1, 1, 1, + 0, 2, 1, 1, 1, 1, 1, 1, 1, 3, + 1, 4, 1, 3, 2, 2, 1, 1, 1, 3, + 2, 2, 2, 1, 2, 3, 2, 1, 1, 1, + 2, 2, 2, 1, 1, 1, 1, 3, 3, 1, + 3, 3, 1, 1, 3, 3, 3, 3, 1, 3, + 3, 1, 1, 1, 1, 3, 1, 3, 1, 3, + 1, 5, 1, 3, 1, 1, 1, 1, 1, 1, + 3, 1, 2, 2, 4, 2, 1, 1, 2, 3, + 3, 2, 5, 3, 2, 3, 2, 0, 1, 1, + 1, 1, 1, 3, 5, 6, 5, 1, 2, 4, + 5, 4, 2, 1, 2, 1, 1, 1, 2, 1, + 1, 2, 1, 1, 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 0, 6, - 0, 5, 1, 2, 3, 1, 3, 1, 4, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, - 0, 5, 1, 1, 0, 2, 0, 2, 2, 3, - 1, 2, 1, 2, 5, 3, 1, 1, 4, 0, - 6, 0, 8, 0, 7, 1, 1, 1, 0, 2, - 3, 2, 2, 2, 3, 2, 1, 2, 1, 1, - 0, 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 6, 0, 5, 1, 2, 3, 1, 3, 1, 4, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, + 0, 0, 5, 1, 1, 0, 2, 0, 2, 2, + 3, 1, 2, 1, 2, 5, 3, 1, 1, 4, + 0, 6, 0, 8, 0, 7, 1, 1, 1, 0, + 2, 3, 2, 2, 2, 3, 2, 1, 2, 1, + 1, 0, 3 }; -/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state - STATE-NUM when YYTABLE doesn't specify something else to do. Zero +/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM. + Performed when YYTABLE doesn't specify something else to do. Zero means the default is an error. */ static const yytype_uint8 yydefact[] = { - 0, 0, 111, 112, 113, 0, 105, 104, 119, 117, - 118, 123, 124, 125, 126, 127, 128, 120, 121, 122, - 129, 130, 131, 108, 106, 0, 116, 132, 133, 134, - 135, 137, 199, 200, 0, 76, 86, 0, 91, 96, - 0, 102, 0, 109, 114, 136, 0, 196, 198, 107, - 101, 0, 0, 140, 71, 0, 74, 86, 0, 87, - 88, 89, 77, 0, 86, 0, 72, 97, 103, 110, - 0, 1, 197, 0, 138, 0, 0, 201, 78, 83, - 85, 90, 0, 92, 79, 0, 0, 2, 5, 4, - 6, 27, 0, 0, 0, 34, 33, 32, 3, 8, - 28, 10, 15, 16, 0, 0, 21, 0, 35, 0, - 38, 41, 42, 47, 50, 51, 52, 53, 55, 57, - 59, 70, 0, 25, 73, 0, 0, 0, 142, 0, - 0, 181, 0, 0, 0, 0, 0, 159, 168, 172, - 35, 61, 68, 0, 150, 0, 114, 153, 170, 152, - 151, 0, 154, 155, 156, 157, 80, 82, 84, 0, - 0, 98, 0, 149, 100, 29, 30, 0, 12, 13, - 0, 0, 19, 18, 0, 20, 22, 24, 31, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 115, 0, 147, 0, 145, 141, 143, - 192, 191, 166, 183, 0, 195, 193, 0, 179, 158, - 0, 64, 65, 66, 67, 63, 0, 0, 173, 169, - 171, 0, 93, 0, 95, 99, 7, 0, 14, 26, - 11, 17, 23, 36, 37, 40, 39, 45, 46, 43, - 44, 48, 49, 54, 56, 58, 0, 139, 0, 0, - 144, 0, 0, 0, 0, 0, 194, 0, 160, 62, - 69, 0, 94, 9, 0, 0, 146, 0, 165, 167, - 186, 185, 188, 166, 177, 0, 0, 0, 81, 60, - 148, 0, 187, 0, 0, 176, 174, 0, 0, 161, - 0, 189, 0, 166, 0, 163, 180, 162, 0, 190, - 184, 175, 178, 182 + 0, 0, 112, 113, 114, 0, 106, 105, 120, 118, + 119, 124, 125, 126, 127, 128, 129, 121, 122, 123, + 130, 131, 132, 109, 107, 0, 117, 133, 134, 135, + 136, 138, 200, 201, 0, 77, 87, 0, 92, 97, + 0, 103, 0, 110, 115, 137, 0, 197, 199, 108, + 102, 0, 2, 3, 141, 0, 72, 0, 75, 87, + 0, 88, 89, 90, 78, 0, 87, 0, 73, 2, + 98, 104, 111, 0, 1, 198, 0, 0, 139, 0, + 202, 79, 84, 86, 91, 0, 93, 80, 0, 0, + 4, 7, 6, 8, 0, 0, 0, 35, 34, 33, + 5, 10, 29, 12, 17, 18, 0, 0, 23, 0, + 36, 0, 39, 42, 43, 48, 51, 52, 53, 54, + 56, 58, 60, 71, 0, 27, 74, 0, 0, 143, + 0, 0, 0, 182, 0, 0, 0, 0, 0, 160, + 169, 173, 36, 62, 69, 0, 151, 0, 115, 154, + 171, 153, 152, 0, 155, 156, 157, 158, 81, 83, + 85, 0, 0, 99, 0, 150, 101, 30, 31, 0, + 14, 15, 0, 0, 21, 20, 0, 22, 24, 26, + 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 116, 148, 0, 146, 142, + 144, 0, 193, 192, 167, 184, 0, 196, 194, 0, + 180, 159, 0, 65, 66, 67, 68, 64, 0, 0, + 174, 170, 172, 0, 94, 0, 96, 100, 9, 0, + 16, 2, 3, 13, 19, 25, 37, 38, 41, 40, + 46, 47, 44, 45, 49, 50, 55, 57, 59, 0, + 0, 0, 145, 140, 0, 0, 0, 0, 0, 195, + 0, 161, 63, 70, 0, 95, 11, 0, 0, 147, + 0, 166, 168, 187, 186, 189, 167, 178, 0, 0, + 0, 82, 61, 149, 0, 188, 0, 0, 177, 175, + 0, 0, 162, 0, 190, 0, 167, 0, 164, 181, + 163, 0, 191, 185, 176, 179, 183 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { - -1, 98, 99, 100, 227, 101, 102, 103, 104, 105, - 106, 107, 140, 109, 110, 111, 112, 113, 114, 115, - 116, 117, 118, 119, 120, 141, 142, 216, 143, 122, - 144, 145, 34, 35, 36, 79, 62, 63, 80, 37, - 38, 39, 40, 41, 42, 43, 123, 45, 125, 75, - 127, 128, 196, 197, 164, 147, 148, 149, 150, 210, - 277, 296, 251, 252, 253, 297, 151, 152, 153, 286, - 276, 154, 257, 202, 254, 272, 283, 284, 155, 46, - 47, 48, 55 + -1, 196, 100, 101, 102, 229, 103, 104, 105, 106, + 107, 108, 109, 142, 111, 112, 113, 114, 115, 116, + 117, 118, 119, 120, 121, 122, 143, 144, 218, 145, + 124, 146, 147, 34, 35, 36, 82, 64, 65, 83, + 37, 38, 39, 40, 41, 42, 43, 125, 45, 130, + 77, 128, 129, 197, 198, 166, 149, 150, 151, 152, + 212, 280, 299, 254, 255, 256, 300, 153, 154, 155, + 289, 279, 156, 260, 204, 257, 275, 286, 287, 157, + 46, 47, 48, 57 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ -#define YYPACT_NINF -266 +#define YYPACT_NINF -261 static const yytype_int16 yypact[] = { - 1253, -20, -266, -266, -266, 148, -266, -266, -266, -266, - -266, -266, -266, -266, -266, -266, -266, -266, -266, -266, - -266, -266, -266, -266, -266, -39, -266, -266, -266, -266, - -266, -266, -266, -18, -2, 6, 21, -61, -266, 51, - 1296, -266, 1370, -266, 25, -266, 1209, -266, -266, -266, - -266, 1370, 42, -266, -266, 50, -266, 71, 95, -266, - -266, -266, -266, 1296, 123, 105, -266, 9, -266, -266, - 974, -266, -266, 81, -266, 1296, 290, -266, -266, -266, - -266, 125, 1296, -13, -266, 776, 974, 99, -266, -266, - -266, -266, 974, 974, 974, -266, -266, -266, -266, -266, - 35, -266, -266, -266, 100, -6, 1040, 104, -266, 974, - 36, -64, -266, -21, 102, -266, -266, -266, 113, 117, - -51, -266, 108, -266, -266, 1296, 129, 1109, -266, 97, - 103, -266, 112, 114, 106, 842, 115, 116, -266, -266, - 39, -266, -266, -43, -266, -18, 47, -266, -266, -266, - -266, 374, -266, -266, -266, -266, 118, -266, -266, 908, - 974, -266, 120, -266, -266, -266, -266, 19, -266, -266, - 974, 1333, -266, -266, 974, 119, -266, -266, -266, 974, - 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, - 974, 974, 974, -266, 1152, 122, -29, -266, -266, -266, - -266, -266, 121, -266, 974, -266, -266, 5, -266, -266, - 458, -266, -266, -266, -266, -266, 974, 974, -266, -266, - -266, 974, -266, 137, -266, -266, -266, 138, 111, -266, - 142, -266, -266, -266, -266, 36, 36, -266, -266, -266, - -266, -21, -21, -266, 113, 117, 82, -266, 974, 129, - -266, 175, 50, 626, 710, 38, -266, 197, 458, -266, - -266, 141, -266, -266, 974, 155, -266, 145, -266, -266, - -266, -266, 197, 121, 111, 186, 159, 160, -266, -266, - -266, 974, -266, 166, 176, 236, -266, 174, 542, -266, - 43, 974, 542, 121, 974, -266, -266, -266, 177, 111, - -266, -266, -266, -266 + 1327, -20, -261, -261, -261, 113, -261, -261, -261, -261, + -261, -261, -261, -261, -261, -261, -261, -261, -261, -261, + -261, -261, -261, -261, -261, -19, -261, -261, -261, -261, + -261, -261, -261, -61, -40, -28, 75, -7, -261, 24, + 1370, -261, 1444, -261, -11, -261, 1283, -261, -261, -261, + -261, 1444, -261, -261, -261, 6, -261, 54, -261, 88, + 62, -261, -261, -261, -261, 1370, 59, 91, -261, 36, + -50, -261, -261, 1051, -261, -261, 63, 1370, -261, 293, + -261, -261, -261, -261, 91, 1370, -12, -261, 856, 1051, + 77, -261, -261, -261, 1051, 1051, 1051, -261, -261, -261, + -261, -261, -14, -261, -261, -261, 84, -44, 1116, 95, + -261, 1051, 53, 3, -261, -36, 89, -261, -261, -261, + 104, 107, -45, -261, 96, -261, -261, 91, 1184, -261, + 1370, 92, 93, -261, 98, 101, 94, 921, 105, 102, + -261, -261, 72, -261, -261, 9, -261, -61, 42, -261, + -261, -261, -261, 376, -261, -261, -261, -261, 106, -261, + -261, 986, 1051, -261, 103, -261, -261, -261, -261, -41, + -261, -261, 1051, 1407, -261, -261, 1051, 110, -261, -261, + -261, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, + 1051, 1051, 1051, 1051, 1051, -261, 109, 23, -261, -261, + -261, 1227, -261, -261, 111, -261, 1051, -261, -261, 25, + -261, -261, 459, -261, -261, -261, -261, -261, 1051, 1051, + -261, -261, -261, 1051, -261, 114, -261, -261, -261, 115, + 112, 77, 116, -261, -261, -261, -261, -261, 53, 53, + -261, -261, -261, -261, -36, -36, -261, 104, 107, 76, + 1051, 91, -261, -261, 145, 54, 625, 708, -6, -261, + 791, 459, -261, -261, 117, -261, -261, 1051, 120, -261, + 124, -261, -261, -261, -261, 791, 111, 112, 91, 125, + 122, -261, -261, -261, 1051, -261, 118, 128, 180, -261, + 126, 542, -261, -5, 1051, 542, 111, 1051, -261, -261, + -261, 123, 112, -261, -261, -261, -261 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int16 yypgoto[] = { - -266, -266, -266, -266, -266, -266, -266, 85, -266, -266, - -266, -266, -44, -266, -15, -266, -55, -19, -266, -266, - -266, 72, 70, 73, -266, -66, -83, -266, -92, -73, - 13, 14, -266, -266, -266, 180, 206, 201, 184, -266, - -266, -241, -25, -30, 262, -4, 0, -266, -266, -266, - 143, -122, -266, 22, -145, 16, -144, -226, -266, -266, - -266, -17, -265, -266, -266, -54, 63, 20, -266, -266, - 4, -266, -266, -266, -266, -266, -266, -266, -266, -266, - 231, -266, -266 + -261, -24, -261, -261, -261, -261, -261, -261, 34, -261, + -261, -261, -261, 32, -261, -33, -261, -27, -26, -261, + -261, -261, 14, 16, 18, -261, -66, -87, -261, -92, + -85, 11, 12, -261, -261, -261, 141, 150, 161, 143, + -261, -261, -231, 5, -30, 224, -18, 0, -261, -261, + -261, 100, -119, -261, -17, -156, -25, -145, -243, -261, + -261, -261, -64, -260, -261, -261, -52, 21, -22, -261, + -261, -39, -261, -261, -261, -261, -261, -261, -261, -261, + -261, 191, -261, -261 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which - number is the opposite. If zero, do what YYDEFACT says. - If YYTABLE_NINF, syntax error. */ -#define YYTABLE_NINF -165 + number is the opposite. If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF -166 static const yytype_int16 yytable[] = { - 44, 77, 167, 163, 121, 199, 52, 220, 285, 191, - 68, 64, 162, 32, 33, 224, 275, 49, 65, 121, - 181, 66, 182, 176, 58, 50, 108, 269, 301, 6, - 7, 275, 64, 81, 183, 184, 217, 53, 69, 218, - 44, 108, 44, 207, 192, 126, 44, 73, 165, 166, - 249, 44, 81, 250, 59, 60, 61, 23, 24, 32, - 33, 159, 295, 44, 54, 178, 295, 173, 160, 185, - 186, 56, 199, 174, 58, 44, 146, 163, 228, 6, - 7, 84, 44, 85, 217, 57, 223, 256, 168, 169, - 86, 232, 226, 121, -75, 126, 67, 126, 217, 70, - 246, 211, 212, 213, 59, 60, 61, 23, 24, 170, - 214, 273, 255, 171, 220, 108, 298, 217, 74, -25, - 215, 70, 217, 179, 180, 44, 76, 44, 237, 238, - 239, 240, 49, 259, 260, 233, 234, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 261, 302, - 83, 146, 2, 3, 4, 121, 59, 60, 61, 187, - 188, 217, 264, 124, 126, 274, 235, 236, 241, 242, - 156, -26, 189, 172, 195, 265, 177, 108, 190, 200, - 274, 279, 121, 193, 203, 201, 204, 208, 205, 290, - 217, -116, 221, 209, 44, 225, 248, -164, 268, 299, - 58, 2, 3, 4, 108, 6, 7, 8, 9, 10, - 146, 163, 262, 263, -27, 267, 278, 281, 11, 12, - 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, - 280, 287, 288, 23, 24, 25, 26, 289, 27, 28, - 29, 30, 87, 31, 88, 89, 90, 91, 291, 292, - 92, 93, 293, 146, 146, 294, 231, 146, 146, 303, - 244, 243, 157, 78, 245, 82, 158, 51, 194, 94, - 270, 266, 146, 258, 271, 300, 282, 72, 0, 0, - 95, 96, 0, 97, 0, 0, 0, 0, 146, 0, - 0, 0, 146, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 129, 130, 131, 0, 132, 133, 134, - 135, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 0, 0, 0, 23, 24, 25, 26, - 136, 27, 28, 29, 30, 87, 31, 88, 89, 90, - 91, 0, 0, 92, 93, 0, 0, 0, 0, 0, + 44, 55, 165, 164, 169, 80, 226, 123, 222, 200, + 71, 32, 33, 272, 193, 70, 288, 49, 185, 186, + 56, 178, 123, 88, 72, 50, 52, 53, 175, 278, + 89, 228, 58, 76, 176, 84, 304, 219, 170, 171, + 44, 66, 44, 86, 278, 209, 44, 127, 298, 194, + 59, 44, 298, 187, 188, 84, 54, 32, 33, 172, + 158, 161, 73, 173, 66, 44, 276, 301, 162, 69, + 53, 67, 219, 219, 68, 165, 225, 44, 60, 148, + 230, 78, 200, 6, 7, 44, 183, 219, 184, 235, + 220, 60, 61, 62, 63, 123, 6, 7, 127, 49, + 127, 251, 249, 219, 252, 110, 259, 87, 61, 62, + 63, 23, 24, -27, 258, 73, 222, 2, 3, 4, + 110, 61, 62, 63, 23, 24, 167, 168, 44, 79, + 44, 262, 263, 213, 214, 215, 52, 53, 264, 181, + 182, 305, 216, 180, 126, 189, 190, -76, -28, 233, + 238, 239, 217, 148, 219, 267, 174, 123, 240, 241, + 242, 243, 191, 244, 245, 268, 179, 192, 277, 205, + 195, 127, 206, 202, 203, 207, 210, 227, 211, 223, + 282, -117, 250, 277, 123, 270, -165, -138, 265, 266, + 219, 281, 293, 110, 283, 284, 296, 291, 292, 294, + 295, 44, 302, 271, 306, 246, 297, 234, 247, 81, + 165, 248, 148, 236, 237, 110, 110, 110, 110, 110, + 110, 110, 110, 110, 110, 110, 159, 85, 160, 51, + 201, 303, 273, 261, 269, 274, 285, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 94, 0, 0, 0, 137, 138, 0, 0, - 0, 0, 139, 95, 96, 0, 97, 1, 2, 3, - 4, 5, 6, 7, 8, 9, 10, 129, 130, 131, - 0, 132, 133, 134, 135, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 0, 0, 0, - 23, 24, 25, 26, 136, 27, 28, 29, 30, 87, - 31, 88, 89, 90, 91, 0, 0, 92, 93, 0, + 0, 0, 0, 0, 290, 110, 148, 148, 0, 0, + 148, 148, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 148, 0, 0, 0, 0, + 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, + 0, 148, 0, 0, 0, 148, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 131, 132, 133, 0, + 134, 135, 136, 137, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 0, 0, 0, 23, + 24, 25, 26, 138, 27, 28, 29, 30, 90, 31, + 91, 92, 93, 0, 0, 94, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 94, 0, 0, 0, - 137, 219, 0, 0, 0, 0, 139, 95, 96, 0, - 97, 1, 2, 3, 4, 5, 6, 7, 8, 9, - 10, 129, 130, 131, 0, 132, 133, 134, 135, 11, - 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, - 22, 0, 0, 0, 23, 24, 25, 26, 136, 27, - 28, 29, 30, 87, 31, 88, 89, 90, 91, 0, - 0, 92, 93, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 94, 0, 0, 0, 137, 0, 0, 0, 0, 0, - 139, 95, 96, 0, 97, 1, 2, 3, 4, 5, - 6, 7, 8, 9, 10, 129, 130, 131, 0, 132, - 133, 134, 135, 11, 12, 13, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 0, 0, 0, 23, 24, - 25, 26, 136, 27, 28, 29, 30, 87, 31, 88, - 89, 90, 91, 0, 0, 92, 93, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 94, 0, 0, 0, 76, 0, - 0, 0, 0, 0, 139, 95, 96, 0, 97, 1, - 2, 3, 4, 5, 6, 7, 8, 9, 10, 129, - 130, 131, 0, 132, 133, 134, 135, 11, 12, 13, + 0, 0, 0, 0, 96, 0, 0, 0, 139, 140, + 0, 0, 0, 0, 141, 97, 98, 0, 99, 1, + 2, 3, 4, 5, 6, 7, 8, 9, 10, 131, + 132, 133, 0, 134, 135, 136, 137, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 0, - 0, 0, 23, 24, 25, 26, 136, 27, 28, 29, - 30, 87, 31, 88, 89, 90, 91, 0, 0, 92, - 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 94, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 139, 95, - 96, 0, 97, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 0, 0, 0, 0, 0, 0, 0, - 0, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 0, 0, 0, 23, 24, 25, 26, - 0, 27, 28, 29, 30, 87, 31, 88, 89, 90, - 91, 0, 0, 92, 93, 0, 0, 0, 0, 0, + 0, 0, 23, 24, 25, 26, 138, 27, 28, 29, + 30, 90, 31, 91, 92, 93, 0, 0, 94, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 94, 0, 0, 0, 8, 9, 10, 0, - 0, 0, 139, 95, 96, 0, 97, 11, 12, 13, + 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, + 0, 139, 221, 0, 0, 0, 0, 141, 97, 98, + 0, 99, 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 131, 132, 133, 0, 134, 135, 136, 137, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 0, 0, 0, 23, 24, 25, 26, 138, + 27, 28, 29, 30, 90, 31, 91, 92, 93, 0, + 0, 94, 95, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 96, 0, 0, 0, 139, 0, 0, 0, 0, 0, + 141, 97, 98, 0, 99, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 10, 131, 132, 133, 0, 134, + 135, 136, 137, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 0, 0, 0, 23, 24, + 25, 26, 138, 27, 28, 29, 30, 90, 31, 91, + 92, 93, 0, 0, 94, 95, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 96, 0, 0, 0, 79, 0, 0, + 0, 0, 0, 141, 97, 98, 0, 99, 1, 2, + 3, 4, 5, 6, 7, 8, 9, 10, 131, 132, + 133, 0, 134, 135, 136, 137, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 0, 0, + 0, 23, 24, 25, 26, 138, 27, 28, 29, 30, + 90, 31, 91, 92, 93, 0, 0, 94, 95, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 141, 97, 98, 0, + 99, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 0, 0, 0, 0, 0, 0, 0, 0, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 0, 0, 0, 23, 24, 25, 26, 0, 27, + 28, 29, 30, 90, 31, 91, 92, 93, 0, 0, + 94, 95, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, + 97, 98, 0, 99, 60, 2, 3, 4, 0, 6, + 7, 8, 9, 10, 0, 0, 0, 0, 0, 0, + 0, 0, 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 0, 0, 0, 23, 24, 25, + 26, 0, 27, 28, 29, 30, 90, 31, 91, 92, + 93, 0, 0, 94, 95, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 96, 0, 0, 0, 8, 9, 10, 0, + 0, 0, 0, 97, 98, 0, 99, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 0, 0, 0, 0, 0, 25, 26, 0, 27, 28, 29, - 30, 87, 31, 88, 89, 90, 91, 0, 0, 92, - 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 94, 0, - 0, 161, 8, 9, 10, 0, 0, 0, 0, 95, - 96, 0, 97, 11, 12, 13, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 0, 0, 0, 0, 0, - 25, 26, 0, 27, 28, 29, 30, 87, 31, 88, - 89, 90, 91, 0, 0, 92, 93, 0, 0, 0, + 30, 90, 31, 91, 92, 93, 0, 0, 94, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 94, 0, 0, 0, 8, 9, - 10, 0, 0, 0, 206, 95, 96, 0, 97, 11, - 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, - 22, 0, 0, 0, 0, 0, 25, 26, 0, 27, - 28, 29, 30, 87, 31, 88, 89, 90, 91, 0, - 0, 92, 93, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, + 163, 8, 9, 10, 0, 0, 0, 0, 97, 98, + 0, 99, 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 0, 0, 0, 0, 0, 25, + 26, 0, 27, 28, 29, 30, 90, 31, 91, 92, + 93, 0, 0, 94, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 94, 0, 0, 222, 8, 9, 10, 0, 0, 0, - 0, 95, 96, 0, 97, 11, 12, 13, 14, 15, + 0, 0, 96, 0, 0, 0, 8, 9, 10, 0, + 0, 0, 208, 97, 98, 0, 99, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 0, + 0, 0, 0, 0, 25, 26, 0, 27, 28, 29, + 30, 90, 31, 91, 92, 93, 0, 0, 94, 95, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, + 224, 8, 9, 10, 0, 0, 0, 0, 97, 98, + 0, 99, 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 0, 0, 0, 0, 0, 25, + 26, 0, 27, 28, 29, 30, 90, 31, 91, 92, + 93, 0, 0, 94, 95, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 96, 0, 0, 0, 8, 9, 10, 0, + 0, 0, 0, 97, 98, 0, 99, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 0, + 0, 0, 0, 0, 25, 177, 0, 27, 28, 29, + 30, 90, 31, 91, 92, 93, 0, 0, 94, 95, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 96, 2, 3, + 4, 0, 0, 0, 8, 9, 10, 0, 97, 98, + 0, 99, 0, 0, 0, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 0, 0, 0, - 0, 0, 25, 26, 0, 27, 28, 29, 30, 87, - 31, 88, 89, 90, 91, 0, 0, 92, 93, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 94, 0, 0, 0, - 8, 9, 10, 0, 0, 0, 0, 95, 96, 0, - 97, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 0, 0, 0, 0, 0, 25, 175, - 0, 27, 28, 29, 30, 87, 31, 88, 89, 90, - 91, 0, 0, 92, 93, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 94, 2, 3, 4, 0, 0, 0, 8, - 9, 10, 0, 95, 96, 0, 97, 0, 0, 0, - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 0, 0, 0, 0, 0, 25, 26, 0, - 27, 28, 29, 30, 0, 31, 2, 3, 4, 0, - 0, 0, 8, 9, 10, 0, 0, 0, 0, 0, - 0, 0, 0, 11, 12, 13, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 0, 198, 0, 0, 0, - 25, 26, 0, 27, 28, 29, 30, 0, 31, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, - 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, - 9, 10, 0, 0, 0, 0, 0, 0, 0, 247, - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 0, 0, 0, 23, 24, 25, 26, 0, - 27, 28, 29, 30, 0, 31, 1, 2, 3, 4, + 0, 0, 25, 26, 0, 27, 28, 29, 30, 0, + 31, 2, 3, 4, 0, 0, 0, 8, 9, 10, + 0, 0, 0, 0, 0, 0, 0, 0, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 199, 0, 0, 0, 0, 25, 26, 0, 27, 28, + 29, 30, 0, 31, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 74, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0, 0, - 0, 0, 0, 0, 11, 12, 13, 14, 15, 16, + 0, 0, 0, 253, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 0, 0, 0, 23, 24, 25, 26, 0, 27, 28, 29, 30, 0, 31, - 2, 3, 4, 0, 0, 0, 8, 9, 10, 0, - 0, 0, 0, 0, 0, 0, 0, 11, 12, 13, - 14, 15, 16, 17, 18, 19, 20, 21, 22, 0, - 0, 0, 0, 0, 25, 26, 0, 27, 28, 29, - 30, 0, 31, 8, 9, 10, 0, 0, 0, 0, - 0, 0, 0, 0, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 0, 0, 0, 0, - 0, 25, 26, 0, 27, 28, 29, 30, 229, 31, - 8, 9, 10, 230, 0, 0, 0, 0, 0, 0, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 0, 0, 0, 0, 0, 0, 0, 0, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 0, 0, 0, 23, 24, 25, 26, 0, 27, 28, + 29, 30, 0, 31, 2, 3, 4, 0, 0, 0, + 8, 9, 10, 0, 0, 0, 0, 0, 0, 0, 0, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 0, 0, 0, 0, 0, 25, 26, - 0, 27, 28, 29, 30, 0, 31 + 0, 27, 28, 29, 30, 0, 31, 8, 9, 10, + 0, 0, 0, 0, 0, 0, 0, 0, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 0, 0, 0, 0, 0, 25, 26, 0, 27, 28, + 29, 30, 231, 232, 8, 9, 10, 0, 0, 0, + 0, 0, 0, 0, 0, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 0, 0, 0, + 0, 0, 25, 26, 0, 27, 28, 29, 30, 0, + 31 }; +#define yypact_value_is_default(Yystate) \ + (!!((Yystate) == (-261))) + +#define yytable_value_is_error(Yytable_value) \ + YYID (0) + static const yytype_int16 yycheck[] = { - 0, 55, 94, 86, 70, 127, 45, 151, 273, 60, - 40, 36, 85, 0, 0, 160, 257, 37, 79, 85, - 84, 82, 86, 106, 3, 45, 70, 253, 293, 8, - 9, 272, 57, 63, 55, 56, 79, 76, 42, 82, - 40, 85, 42, 135, 95, 75, 46, 51, 92, 93, - 79, 51, 82, 82, 33, 34, 35, 36, 37, 46, - 46, 74, 288, 63, 82, 109, 292, 73, 81, 90, - 91, 73, 194, 79, 3, 75, 76, 160, 170, 8, - 9, 72, 82, 74, 79, 79, 159, 82, 53, 54, - 81, 174, 73, 159, 73, 125, 45, 127, 79, 74, - 192, 62, 63, 64, 33, 34, 35, 36, 37, 74, - 71, 73, 204, 78, 258, 159, 73, 79, 76, 72, - 81, 74, 79, 87, 88, 125, 76, 127, 183, 184, - 185, 186, 37, 216, 217, 179, 180, 181, 182, 183, - 184, 185, 186, 187, 188, 189, 190, 191, 221, 294, - 45, 151, 4, 5, 6, 221, 33, 34, 35, 57, - 58, 79, 80, 82, 194, 257, 181, 182, 187, 188, - 45, 72, 59, 73, 45, 248, 72, 221, 61, 82, - 272, 264, 248, 75, 72, 82, 72, 72, 82, 281, - 79, 72, 74, 77, 194, 75, 74, 76, 252, 291, - 3, 4, 5, 6, 248, 8, 9, 10, 11, 12, - 210, 294, 75, 75, 72, 40, 75, 72, 21, 22, - 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, - 75, 45, 73, 36, 37, 38, 39, 77, 41, 42, - 43, 44, 45, 46, 47, 48, 49, 50, 82, 73, - 53, 54, 16, 253, 254, 81, 171, 257, 258, 82, - 190, 189, 82, 57, 191, 64, 82, 5, 125, 72, - 254, 249, 272, 210, 254, 292, 272, 46, -1, -1, - 83, 84, -1, 86, -1, -1, -1, -1, 288, -1, - -1, -1, 292, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, -1, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31, 32, -1, -1, -1, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, - 50, -1, -1, 53, 54, -1, -1, -1, -1, -1, + 0, 25, 89, 88, 96, 57, 162, 73, 153, 128, + 40, 0, 0, 256, 59, 39, 276, 37, 54, 55, + 81, 108, 88, 73, 42, 45, 45, 46, 72, 260, + 80, 72, 72, 51, 78, 65, 296, 78, 52, 53, + 40, 36, 42, 67, 275, 137, 46, 77, 291, 94, + 78, 51, 295, 89, 90, 85, 75, 46, 46, 73, + 84, 73, 73, 77, 59, 65, 72, 72, 80, 45, + 46, 78, 78, 78, 81, 162, 161, 77, 3, 79, + 172, 75, 201, 8, 9, 85, 83, 78, 85, 176, + 81, 3, 33, 34, 35, 161, 8, 9, 128, 37, + 130, 78, 194, 78, 81, 73, 81, 71, 33, 34, + 35, 36, 37, 71, 206, 73, 261, 4, 5, 6, + 88, 33, 34, 35, 36, 37, 94, 95, 128, 75, + 130, 218, 219, 61, 62, 63, 45, 46, 223, 86, + 87, 297, 70, 111, 81, 56, 57, 72, 71, 173, + 183, 184, 80, 153, 78, 79, 72, 223, 185, 186, + 187, 188, 58, 189, 190, 250, 71, 60, 260, 71, + 74, 201, 71, 81, 81, 81, 71, 74, 76, 73, + 267, 71, 73, 275, 250, 40, 75, 71, 74, 74, + 78, 74, 284, 161, 74, 71, 16, 72, 76, 81, + 72, 201, 294, 255, 81, 191, 80, 173, 192, 59, + 297, 193, 212, 181, 182, 183, 184, 185, 186, 187, + 188, 189, 190, 191, 192, 193, 85, 66, 85, 5, + 130, 295, 257, 212, 251, 257, 275, 46, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 72, -1, -1, -1, 76, 77, -1, -1, - -1, -1, 82, 83, 84, -1, 86, 3, 4, 5, - 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - -1, 17, 18, 19, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, -1, -1, -1, - 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, - 46, 47, 48, 49, 50, -1, -1, 53, 54, -1, + -1, -1, -1, -1, 278, 223, 256, 257, -1, -1, + 260, 261, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 275, -1, -1, -1, -1, + -1, -1, 250, -1, -1, -1, -1, -1, -1, -1, + -1, 291, -1, -1, -1, 295, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, -1, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, -1, -1, -1, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, + 47, 48, 49, -1, -1, 52, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 72, -1, -1, -1, - 76, 77, -1, -1, -1, -1, 82, 83, 84, -1, - 86, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, -1, 17, 18, 19, 20, 21, - 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, -1, -1, -1, 36, 37, 38, 39, 40, 41, - 42, 43, 44, 45, 46, 47, 48, 49, 50, -1, - -1, 53, 54, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 72, -1, -1, -1, 76, -1, -1, -1, -1, -1, - 82, 83, 84, -1, 86, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, -1, 17, - 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, -1, -1, -1, 36, 37, - 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, -1, -1, 53, 54, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 72, -1, -1, -1, 76, -1, - -1, -1, -1, -1, 82, 83, 84, -1, 86, 3, + -1, -1, -1, -1, 71, -1, -1, -1, 75, 76, + -1, -1, -1, -1, 81, 82, 83, -1, 85, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, -1, -1, -1, 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 49, 50, -1, -1, 53, - 54, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 72, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 82, 83, - 84, -1, 86, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, -1, -1, -1, -1, -1, -1, -1, - -1, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31, 32, -1, -1, -1, 36, 37, 38, 39, - -1, 41, 42, 43, 44, 45, 46, 47, 48, 49, - 50, -1, -1, 53, 54, -1, -1, -1, -1, -1, + 44, 45, 46, 47, 48, 49, -1, -1, 52, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 72, -1, -1, -1, 10, 11, 12, -1, - -1, -1, 82, 83, 84, -1, 86, 21, 22, 23, + -1, -1, -1, -1, -1, -1, -1, 71, -1, -1, + -1, 75, 76, -1, -1, -1, -1, 81, 82, 83, + -1, 85, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, -1, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, -1, -1, -1, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, -1, + -1, 52, 53, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 71, -1, -1, -1, 75, -1, -1, -1, -1, -1, + 81, 82, 83, -1, 85, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, -1, 17, + 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 31, 32, -1, -1, -1, 36, 37, + 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, -1, -1, 52, 53, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 71, -1, -1, -1, 75, -1, -1, + -1, -1, -1, 81, 82, 83, -1, 85, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, -1, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, -1, -1, + -1, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, -1, -1, 52, 53, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 71, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 81, 82, 83, -1, + 85, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, -1, -1, -1, -1, -1, -1, -1, -1, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, -1, -1, -1, 36, 37, 38, 39, -1, 41, + 42, 43, 44, 45, 46, 47, 48, 49, -1, -1, + 52, 53, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 71, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 81, + 82, 83, -1, 85, 3, 4, 5, 6, -1, 8, + 9, 10, 11, 12, -1, -1, -1, -1, -1, -1, + -1, -1, 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 32, -1, -1, -1, 36, 37, 38, + 39, -1, 41, 42, 43, 44, 45, 46, 47, 48, + 49, -1, -1, 52, 53, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 71, -1, -1, -1, 10, 11, 12, -1, + -1, -1, -1, 82, 83, -1, 85, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, -1, -1, -1, -1, -1, 38, 39, -1, 41, 42, 43, - 44, 45, 46, 47, 48, 49, 50, -1, -1, 53, - 54, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 72, -1, - -1, 75, 10, 11, 12, -1, -1, -1, -1, 83, - 84, -1, 86, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, -1, -1, -1, -1, -1, - 38, 39, -1, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, -1, -1, 53, 54, -1, -1, -1, + 44, 45, 46, 47, 48, 49, -1, -1, 52, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 72, -1, -1, -1, 10, 11, - 12, -1, -1, -1, 82, 83, 84, -1, 86, 21, - 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, -1, -1, -1, -1, -1, 38, 39, -1, 41, - 42, 43, 44, 45, 46, 47, 48, 49, 50, -1, - -1, 53, 54, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 71, -1, -1, + 74, 10, 11, 12, -1, -1, -1, -1, 82, 83, + -1, 85, 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 32, -1, -1, -1, -1, -1, 38, + 39, -1, 41, 42, 43, 44, 45, 46, 47, 48, + 49, -1, -1, 52, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 72, -1, -1, 75, 10, 11, 12, -1, -1, -1, - -1, 83, 84, -1, 86, 21, 22, 23, 24, 25, + -1, -1, 71, -1, -1, -1, 10, 11, 12, -1, + -1, -1, 81, 82, 83, -1, 85, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, -1, + -1, -1, -1, -1, 38, 39, -1, 41, 42, 43, + 44, 45, 46, 47, 48, 49, -1, -1, 52, 53, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 71, -1, -1, + 74, 10, 11, 12, -1, -1, -1, -1, 82, 83, + -1, 85, 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 32, -1, -1, -1, -1, -1, 38, + 39, -1, 41, 42, 43, 44, 45, 46, 47, 48, + 49, -1, -1, 52, 53, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 71, -1, -1, -1, 10, 11, 12, -1, + -1, -1, -1, 82, 83, -1, 85, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, -1, + -1, -1, -1, -1, 38, 39, -1, 41, 42, 43, + 44, 45, 46, 47, 48, 49, -1, -1, 52, 53, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 71, 4, 5, + 6, -1, -1, -1, 10, 11, 12, -1, 82, 83, + -1, 85, -1, -1, -1, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, -1, -1, -1, - -1, -1, 38, 39, -1, 41, 42, 43, 44, 45, - 46, 47, 48, 49, 50, -1, -1, 53, 54, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 72, -1, -1, -1, - 10, 11, 12, -1, -1, -1, -1, 83, 84, -1, - 86, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31, 32, -1, -1, -1, -1, -1, 38, 39, - -1, 41, 42, 43, 44, 45, 46, 47, 48, 49, - 50, -1, -1, 53, 54, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 72, 4, 5, 6, -1, -1, -1, 10, - 11, 12, -1, 83, 84, -1, 86, -1, -1, -1, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32, -1, -1, -1, -1, -1, 38, 39, -1, - 41, 42, 43, 44, -1, 46, 4, 5, 6, -1, - -1, -1, 10, 11, 12, -1, -1, -1, -1, -1, - -1, -1, -1, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, -1, 77, -1, -1, -1, - 38, 39, -1, 41, 42, 43, 44, -1, 46, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, - -1, -1, 3, 4, 5, 6, 7, 8, 9, 10, - 11, 12, -1, -1, -1, -1, -1, -1, -1, 77, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32, -1, -1, -1, 36, 37, 38, 39, -1, - 41, 42, 43, 44, -1, 46, 3, 4, 5, 6, + -1, -1, 38, 39, -1, 41, 42, 43, 44, -1, + 46, 4, 5, 6, -1, -1, -1, 10, 11, 12, + -1, -1, -1, -1, -1, -1, -1, -1, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 76, -1, -1, -1, -1, 38, 39, -1, 41, 42, + 43, 44, -1, 46, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 0, -1, -1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, -1, -1, -1, -1, - -1, -1, -1, -1, 21, 22, 23, 24, 25, 26, + -1, -1, -1, 76, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, -1, -1, -1, 36, 37, 38, 39, -1, 41, 42, 43, 44, -1, 46, - 4, 5, 6, -1, -1, -1, 10, 11, 12, -1, - -1, -1, -1, -1, -1, -1, -1, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, 32, -1, - -1, -1, -1, -1, 38, 39, -1, 41, 42, 43, - 44, -1, 46, 10, 11, 12, -1, -1, -1, -1, - -1, -1, -1, -1, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, -1, -1, -1, -1, - -1, 38, 39, -1, 41, 42, 43, 44, 45, 46, - 10, 11, 12, 50, -1, -1, -1, -1, -1, -1, + 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + -1, -1, -1, -1, -1, -1, -1, -1, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + -1, -1, -1, 36, 37, 38, 39, -1, 41, 42, + 43, 44, -1, 46, 4, 5, 6, -1, -1, -1, + 10, 11, 12, -1, -1, -1, -1, -1, -1, -1, -1, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, -1, -1, -1, -1, -1, 38, 39, - -1, 41, 42, 43, 44, -1, 46 + -1, 41, 42, 43, 44, -1, 46, 10, 11, 12, + -1, -1, -1, -1, -1, -1, -1, -1, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + -1, -1, -1, -1, -1, 38, 39, -1, 41, 42, + 43, 44, 45, 46, 10, 11, 12, -1, -1, -1, + -1, -1, -1, -1, -1, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, -1, -1, -1, + -1, -1, 38, 39, -1, 41, 42, 43, 44, -1, + 46 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing @@ -1217,32 +1291,32 @@ static const yytype_uint8 yystos[] = 30, 31, 32, 36, 37, 38, 39, 41, 42, 43, 44, 46, 126, 127, 128, 129, 130, 135, 136, 137, 138, 139, 140, 141, 142, 143, 175, 176, 177, 37, - 45, 140, 45, 76, 82, 178, 73, 79, 3, 33, - 34, 35, 132, 133, 138, 79, 82, 45, 139, 141, - 74, 0, 176, 141, 76, 145, 76, 161, 132, 131, - 134, 139, 133, 45, 72, 74, 81, 45, 47, 48, - 49, 50, 53, 54, 72, 83, 84, 86, 97, 98, - 99, 101, 102, 103, 104, 105, 106, 107, 108, 109, - 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, - 120, 121, 125, 142, 82, 144, 139, 146, 147, 13, - 14, 15, 17, 18, 19, 20, 40, 76, 77, 82, - 108, 121, 122, 124, 126, 127, 142, 151, 152, 153, - 154, 162, 163, 164, 167, 174, 45, 131, 134, 74, - 81, 75, 125, 122, 150, 108, 108, 124, 53, 54, - 74, 78, 73, 73, 79, 39, 122, 72, 108, 87, - 88, 84, 86, 55, 56, 90, 91, 57, 58, 59, - 61, 60, 95, 75, 146, 45, 148, 149, 77, 147, - 82, 82, 169, 72, 72, 82, 82, 124, 72, 77, - 155, 62, 63, 64, 71, 81, 123, 79, 82, 77, - 152, 74, 75, 125, 150, 75, 73, 100, 124, 45, - 50, 103, 122, 108, 108, 110, 110, 112, 112, 112, - 112, 113, 113, 117, 118, 119, 124, 77, 74, 79, - 82, 158, 159, 160, 170, 124, 82, 168, 162, 122, - 122, 125, 75, 75, 80, 125, 149, 40, 161, 153, - 151, 163, 171, 73, 124, 137, 166, 156, 75, 122, - 75, 72, 166, 172, 173, 158, 165, 45, 73, 77, - 124, 82, 73, 16, 81, 153, 157, 161, 73, 124, - 157, 158, 150, 82 + 45, 140, 45, 46, 75, 96, 81, 178, 72, 78, + 3, 33, 34, 35, 132, 133, 138, 78, 81, 45, + 96, 139, 141, 73, 0, 176, 141, 145, 75, 75, + 161, 132, 131, 134, 139, 133, 96, 71, 73, 80, + 45, 47, 48, 49, 52, 53, 71, 82, 83, 85, + 97, 98, 99, 101, 102, 103, 104, 105, 106, 107, + 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, + 118, 119, 120, 121, 125, 142, 81, 139, 146, 147, + 144, 13, 14, 15, 17, 18, 19, 20, 40, 75, + 76, 81, 108, 121, 122, 124, 126, 127, 142, 151, + 152, 153, 154, 162, 163, 164, 167, 174, 96, 131, + 134, 73, 80, 74, 125, 122, 150, 108, 108, 124, + 52, 53, 73, 77, 72, 72, 78, 39, 122, 71, + 108, 86, 87, 83, 85, 54, 55, 89, 90, 56, + 57, 58, 60, 59, 94, 74, 96, 148, 149, 76, + 147, 146, 81, 81, 169, 71, 71, 81, 81, 124, + 71, 76, 155, 61, 62, 63, 70, 80, 123, 78, + 81, 76, 152, 73, 74, 125, 150, 74, 72, 100, + 124, 45, 46, 96, 103, 122, 108, 108, 110, 110, + 112, 112, 112, 112, 113, 113, 117, 118, 119, 124, + 73, 78, 81, 76, 158, 159, 160, 170, 124, 81, + 168, 162, 122, 122, 125, 74, 74, 79, 125, 149, + 40, 161, 153, 151, 163, 171, 72, 124, 137, 166, + 156, 74, 122, 74, 71, 166, 172, 173, 158, 165, + 96, 72, 76, 124, 81, 72, 16, 80, 153, 157, + 161, 72, 124, 157, 158, 150, 81 }; #define yyerrok (yyerrstatus = 0) @@ -1272,24 +1346,24 @@ static const yytype_uint8 yystos[] = #define YYRECOVERING() (!!yyerrstatus) -#define YYBACKUP(Token, Value) \ -do \ - if (yychar == YYEMPTY && yylen == 1) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - yytoken = YYTRANSLATE (yychar); \ - YYPOPSTACK (1); \ - goto yybackup; \ - } \ - else \ - { \ - yyerror (context, YY_("syntax error: cannot back up")); \ +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + YYPOPSTACK (yylen); \ + yystate = *yyssp; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (&yylloc, context, YY_("syntax error: cannot back up")); \ YYERROR; \ } \ while (YYID (0)) - +/* Error token number */ #define YYTERROR 1 #define YYERRCODE 256 @@ -1298,27 +1372,28 @@ while (YYID (0)) If N is 0, then set CURRENT to the empty location which ends the previous symbol: RHS[0] (always defined). */ -#define YYRHSLOC(Rhs, K) ((Rhs)[K]) #ifndef YYLLOC_DEFAULT -# define YYLLOC_DEFAULT(Current, Rhs, N) \ - do \ - if (YYID (N)) \ - { \ - (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ - (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ - (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ - (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ - } \ - else \ - { \ - (Current).first_line = (Current).last_line = \ - YYRHSLOC (Rhs, 0).last_line; \ - (Current).first_column = (Current).last_column = \ - YYRHSLOC (Rhs, 0).last_column; \ - } \ +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (YYID (N)) \ + { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC (Rhs, 0).last_column; \ + } \ while (YYID (0)) #endif +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) + /* YY_LOCATION_PRINT -- Print the location on the stream. This macro was not mandated originally: define only if we know @@ -1326,10 +1401,46 @@ while (YYID (0)) #ifndef YY_LOCATION_PRINT # if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL -# define YY_LOCATION_PRINT(File, Loc) \ - fprintf (File, "%d.%d-%d.%d", \ - (Loc).first_line, (Loc).first_column, \ - (Loc).last_line, (Loc).last_column) + +/* Print *YYLOCP on YYO. Private, do not rely on its existence. */ + +__attribute__((__unused__)) +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static unsigned +yy_location_print_ (FILE *yyo, YYLTYPE const * const yylocp) +#else +static unsigned +yy_location_print_ (yyo, yylocp) + FILE *yyo; + YYLTYPE const * const yylocp; +#endif +{ + unsigned res = 0; + int end_col = 0 != yylocp->last_column ? yylocp->last_column - 1 : 0; + if (0 <= yylocp->first_line) + { + res += fprintf (yyo, "%d", yylocp->first_line); + if (0 <= yylocp->first_column) + res += fprintf (yyo, ".%d", yylocp->first_column); + } + if (0 <= yylocp->last_line) + { + if (yylocp->first_line < yylocp->last_line) + { + res += fprintf (yyo, "-%d", yylocp->last_line); + if (0 <= end_col) + res += fprintf (yyo, ".%d", end_col); + } + else if (0 <= end_col && yylocp->first_column < end_col) + res += fprintf (yyo, "-%d", end_col); + } + return res; + } + +# define YY_LOCATION_PRINT(File, Loc) \ + yy_location_print_ (File, &(Loc)) + # else # define YY_LOCATION_PRINT(File, Loc) ((void) 0) # endif @@ -1337,11 +1448,10 @@ while (YYID (0)) /* YYLEX -- calling `yylex' with the right arguments. */ - #ifdef YYLEX_PARAM -# define YYLEX yylex (&yylval, YYLEX_PARAM) +# define YYLEX yylex (&yylval, &yylloc, YYLEX_PARAM) #else -# define YYLEX yylex (&yylval) +# define YYLEX yylex (&yylval, &yylloc) #endif /* Enable debugging if requested. */ @@ -1364,7 +1474,7 @@ do { \ { \ YYFPRINTF (stderr, "%s ", Title); \ yy_symbol_print (stderr, \ - Type, Value, context); \ + Type, Value, Location, context); \ YYFPRINTF (stderr, "\n"); \ } \ } while (YYID (0)) @@ -1378,18 +1488,22 @@ do { \ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void -yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, TParseContext* context) +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, TParseContext* context) #else static void -yy_symbol_value_print (yyoutput, yytype, yyvaluep, context) +yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, context) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; + YYLTYPE const * const yylocationp; TParseContext* context; #endif { + FILE *yyo = yyoutput; + YYUSE (yyo); if (!yyvaluep) return; + YYUSE (yylocationp); YYUSE (context); # ifdef YYPRINT if (yytype < YYNTOKENS) @@ -1400,7 +1514,7 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep, context) switch (yytype) { default: - break; + break; } } @@ -1412,13 +1526,14 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep, context) #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void -yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, TParseContext* context) +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, TParseContext* context) #else static void -yy_symbol_print (yyoutput, yytype, yyvaluep, context) +yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp, context) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; + YYLTYPE const * const yylocationp; TParseContext* context; #endif { @@ -1427,7 +1542,9 @@ yy_symbol_print (yyoutput, yytype, yyvaluep, context) else YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); - yy_symbol_value_print (yyoutput, yytype, yyvaluep, context); + YY_LOCATION_PRINT (yyoutput, *yylocationp); + YYFPRINTF (yyoutput, ": "); + yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, context); YYFPRINTF (yyoutput, ")"); } @@ -1470,11 +1587,12 @@ do { \ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void -yy_reduce_print (YYSTYPE *yyvsp, int yyrule, TParseContext* context) +yy_reduce_print (YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule, TParseContext* context) #else static void -yy_reduce_print (yyvsp, yyrule, context) +yy_reduce_print (yyvsp, yylsp, yyrule, context) YYSTYPE *yyvsp; + YYLTYPE *yylsp; int yyrule; TParseContext* context; #endif @@ -1490,7 +1608,7 @@ yy_reduce_print (yyvsp, yyrule, context) YYFPRINTF (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], &(yyvsp[(yyi + 1) - (yynrhs)]) - , context); + , &(yylsp[(yyi + 1) - (yynrhs)]) , context); YYFPRINTF (stderr, "\n"); } } @@ -1498,7 +1616,7 @@ yy_reduce_print (yyvsp, yyrule, context) # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug) \ - yy_reduce_print (yyvsp, Rule, context); \ + yy_reduce_print (yyvsp, yylsp, Rule, context); \ } while (YYID (0)) /* Nonzero means print parse trace. It is left uninitialized so that @@ -1528,7 +1646,6 @@ int yydebug; # define YYMAXDEPTH 10000 #endif - #if YYERROR_VERBOSE @@ -1631,115 +1748,145 @@ yytnamerr (char *yyres, const char *yystr) } # endif -/* Copy into YYRESULT an error message about the unexpected token - YYCHAR while in state YYSTATE. Return the number of bytes copied, - including the terminating null byte. If YYRESULT is null, do not - copy anything; just return the number of bytes that would be - copied. As a special case, return 0 if an ordinary "syntax error" - message will do. Return YYSIZE_MAXIMUM if overflow occurs during - size calculation. */ -static YYSIZE_T -yysyntax_error (char *yyresult, int yystate, int yychar) +/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message + about the unexpected token YYTOKEN for the state stack whose top is + YYSSP. + + Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is + not large enough to hold the message. In that case, also set + *YYMSG_ALLOC to the required number of bytes. Return 2 if the + required number of bytes is too large to store. */ +static int +yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, + yytype_int16 *yyssp, int yytoken) { - int yyn = yypact[yystate]; + YYSIZE_T yysize0 = yytnamerr (YY_NULL, yytname[yytoken]); + YYSIZE_T yysize = yysize0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + /* Internationalized format string. */ + const char *yyformat = YY_NULL; + /* Arguments of yyformat. */ + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + /* Number of reported tokens (one for the "unexpected", one per + "expected"). */ + int yycount = 0; - if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) - return 0; - else + /* There are many possibilities here to consider: + - Assume YYFAIL is not used. It's too flawed to consider. See + + for details. YYERROR is fine as it does not invoke this + function. + - If this state is a consistent state with a default action, then + the only way this function was invoked is if the default action + is an error action. In that case, don't check for expected + tokens because there are none. + - The only way there can be no lookahead present (in yychar) is if + this state is a consistent state with a default action. Thus, + detecting the absence of a lookahead is sufficient to determine + that there is no unexpected or expected token to report. In that + case, just report a simple "syntax error". + - Don't assume there isn't a lookahead just because this state is a + consistent state with a default action. There might have been a + previous inconsistent state, consistent state with a non-default + action, or user semantic action that manipulated yychar. + - Of course, the expected token list depends on states to have + correct lookahead information, and it depends on the parser not + to perform extra reductions after fetching a lookahead from the + scanner and before detecting a syntax error. Thus, state merging + (from LALR or IELR) and default reductions corrupt the expected + token list. However, the list is correct for canonical LR with + one exception: it will still contain any token that will not be + accepted due to an error action in a later state. + */ + if (yytoken != YYEMPTY) { - int yytype = YYTRANSLATE (yychar); - YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); - YYSIZE_T yysize = yysize0; - YYSIZE_T yysize1; - int yysize_overflow = 0; - enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; - char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; - int yyx; + int yyn = yypact[*yyssp]; + yyarg[yycount++] = yytname[yytoken]; + if (!yypact_value_is_default (yyn)) + { + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. In other words, skip the first -YYN actions for + this state because they are default actions. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yyx; -# if 0 - /* This is so xgettext sees the translatable formats that are - constructed on the fly. */ - YY_("syntax error, unexpected %s"); - YY_("syntax error, unexpected %s, expecting %s"); - YY_("syntax error, unexpected %s, expecting %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); -# endif - char *yyfmt; - char const *yyf; - static char const yyunexpected[] = "syntax error, unexpected %s"; - static char const yyexpecting[] = ", expecting %s"; - static char const yyor[] = " or %s"; - char yyformat[sizeof yyunexpected - + sizeof yyexpecting - 1 - + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) - * (sizeof yyor - 1))]; - char const *yyprefix = yyexpecting; - - /* Start YYX at -YYN if negative to avoid negative indexes in - YYCHECK. */ - int yyxbegin = yyn < 0 ? -yyn : 0; - - /* Stay within bounds of both yycheck and yytname. */ - int yychecklim = YYLAST - yyn + 1; - int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; - int yycount = 1; - - yyarg[0] = yytname[yytype]; - yyfmt = yystpcpy (yyformat, yyunexpected); - - for (yyx = yyxbegin; yyx < yyxend; ++yyx) - if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) - { - if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) - { - yycount = 1; - yysize = yysize0; - yyformat[sizeof yyunexpected - 1] = '\0'; - break; - } - yyarg[yycount++] = yytname[yyx]; - yysize1 = yysize + yytnamerr (0, yytname[yyx]); - yysize_overflow |= (yysize1 < yysize); - yysize = yysize1; - yyfmt = yystpcpy (yyfmt, yyprefix); - yyprefix = yyor; - } - - yyf = YY_(yyformat); - yysize1 = yysize + yystrlen (yyf); - yysize_overflow |= (yysize1 < yysize); - yysize = yysize1; - - if (yysize_overflow) - return YYSIZE_MAXIMUM; - - if (yyresult) - { - /* Avoid sprintf, as that infringes on the user's name space. - Don't have undefined behavior even if the translation - produced a string with the wrong number of "%s"s. */ - char *yyp = yyresult; - int yyi = 0; - while ((*yyp = *yyf) != '\0') - { - if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) - { - yyp += yytnamerr (yyp, yyarg[yyi++]); - yyf += 2; - } - else - { - yyp++; - yyf++; - } - } - } - return yysize; + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR + && !yytable_value_is_error (yytable[yyx + yyn])) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + break; + } + yyarg[yycount++] = yytname[yyx]; + { + YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULL, yytname[yyx]); + if (! (yysize <= yysize1 + && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } + } + } } + + switch (yycount) + { +# define YYCASE_(N, S) \ + case N: \ + yyformat = S; \ + break + YYCASE_(0, YY_("syntax error")); + YYCASE_(1, YY_("syntax error, unexpected %s")); + YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); + YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); + YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); + YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); +# undef YYCASE_ + } + + { + YYSIZE_T yysize1 = yysize + yystrlen (yyformat); + if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } + + if (*yymsg_alloc < yysize) + { + *yymsg_alloc = 2 * yysize; + if (! (yysize <= *yymsg_alloc + && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) + *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; + return 1; + } + + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + { + char *yyp = *yymsg; + int yyi = 0; + while ((*yyp = *yyformat) != '\0') + if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyformat += 2; + } + else + { + yyp++; + yyformat++; + } + } + return 0; } #endif /* YYERROR_VERBOSE */ - /*-----------------------------------------------. | Release the memory associated to this symbol. | @@ -1749,17 +1896,19 @@ yysyntax_error (char *yyresult, int yystate, int yychar) #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void -yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, TParseContext* context) +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp, TParseContext* context) #else static void -yydestruct (yymsg, yytype, yyvaluep, context) +yydestruct (yymsg, yytype, yyvaluep, yylocationp, context) const char *yymsg; int yytype; YYSTYPE *yyvaluep; + YYLTYPE *yylocationp; TParseContext* context; #endif { YYUSE (yyvaluep); + YYUSE (yylocationp); YYUSE (context); if (!yymsg) @@ -1770,32 +1919,16 @@ yydestruct (yymsg, yytype, yyvaluep, context) { default: - break; + break; } } -/* Prevent warnings from -Wmissing-prototypes. */ -#ifdef YYPARSE_PARAM -#if defined __STDC__ || defined __cplusplus -int yyparse (void *YYPARSE_PARAM); -#else -int yyparse (); -#endif -#else /* ! YYPARSE_PARAM */ -#if defined __STDC__ || defined __cplusplus -int yyparse (TParseContext* context); -#else -int yyparse (); -#endif -#endif /* ! YYPARSE_PARAM */ - - -/*-------------------------. -| yyparse or yypush_parse. | -`-------------------------*/ +/*----------. +| yyparse. | +`----------*/ #ifdef YYPARSE_PARAM #if (defined __STDC__ || defined __C99__FUNC__ \ @@ -1822,8 +1955,40 @@ yyparse (context) /* The lookahead symbol. */ int yychar; + +#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ +/* Suppress an incorrect diagnostic about yylval being uninitialized. */ +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\ + _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ + _Pragma ("GCC diagnostic pop") +#else +/* Default value used for initialization, for pacifying older GCCs + or non-GCC compilers. */ +static YYSTYPE yyval_default; +# define YY_INITIAL_VALUE(Value) = Value +#endif +static YYLTYPE yyloc_default +# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL + = { 1, 1, 1, 1 } +# endif +; +#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_END +#endif +#ifndef YY_INITIAL_VALUE +# define YY_INITIAL_VALUE(Value) /* Nothing. */ +#endif + /* The semantic value of the lookahead symbol. */ -YYSTYPE yylval; +YYSTYPE yylval YY_INITIAL_VALUE(yyval_default); + +/* Location data for the lookahead symbol. */ +YYLTYPE yylloc = yyloc_default; + /* Number of syntax errors so far. */ int yynerrs; @@ -1835,8 +2000,9 @@ YYSTYPE yylval; /* The stacks and their tools: `yyss': related to states. `yyvs': related to semantic values. + `yyls': related to locations. - Refer to the stacks thru separate pointers, to allow yyoverflow + Refer to the stacks through separate pointers, to allow yyoverflow to reallocate them elsewhere. */ /* The state stack. */ @@ -1849,15 +2015,24 @@ YYSTYPE yylval; YYSTYPE *yyvs; YYSTYPE *yyvsp; + /* The location stack. */ + YYLTYPE yylsa[YYINITDEPTH]; + YYLTYPE *yyls; + YYLTYPE *yylsp; + + /* The locations where the error started and ended. */ + YYLTYPE yyerror_range[3]; + YYSIZE_T yystacksize; int yyn; int yyresult; /* Lookahead token as an internal (translated) token number. */ - int yytoken; + int yytoken = 0; /* The variables used to return semantic value and location from the action routines. */ YYSTYPE yyval; + YYLTYPE yyloc; #if YYERROR_VERBOSE /* Buffer for error messages, and its allocated size. */ @@ -1866,15 +2041,15 @@ YYSTYPE yylval; YYSIZE_T yymsg_alloc = sizeof yymsgbuf; #endif -#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N), yylsp -= (N)) /* The number of symbols on the RHS of the reduced rule. Keep to zero when no symbol should be popped. */ int yylen = 0; - yytoken = 0; - yyss = yyssa; - yyvs = yyvsa; + yyssp = yyss = yyssa; + yyvsp = yyvs = yyvsa; + yylsp = yyls = yylsa; yystacksize = YYINITDEPTH; YYDPRINTF ((stderr, "Starting parse\n")); @@ -1883,14 +2058,7 @@ YYSTYPE yylval; yyerrstatus = 0; yynerrs = 0; yychar = YYEMPTY; /* Cause a token to be read. */ - - /* Initialize stack pointers. - Waste one element of value and location stack - so that they stay on the same level as the state stack. - The wasted elements are never initialized. */ - yyssp = yyss; - yyvsp = yyvs; - + yylsp[0] = yylloc; goto yysetstate; /*------------------------------------------------------------. @@ -1916,6 +2084,7 @@ YYSTYPE yylval; memory. */ YYSTYPE *yyvs1 = yyvs; yytype_int16 *yyss1 = yyss; + YYLTYPE *yyls1 = yyls; /* Each stack pointer address is followed by the size of the data in use in that stack, in bytes. This used to be a @@ -1924,8 +2093,10 @@ YYSTYPE yylval; yyoverflow (YY_("memory exhausted"), &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), + &yyls1, yysize * sizeof (*yylsp), &yystacksize); + yyls = yyls1; yyss = yyss1; yyvs = yyvs1; } @@ -1948,6 +2119,7 @@ YYSTYPE yylval; goto yyexhaustedlab; YYSTACK_RELOCATE (yyss_alloc, yyss); YYSTACK_RELOCATE (yyvs_alloc, yyvs); + YYSTACK_RELOCATE (yyls_alloc, yyls); # undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); @@ -1957,6 +2129,7 @@ YYSTYPE yylval; yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; + yylsp = yyls + yysize - 1; YYDPRINTF ((stderr, "Stack size increased to %lu\n", (unsigned long int) yystacksize)); @@ -1982,7 +2155,7 @@ yybackup: /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; - if (yyn == YYPACT_NINF) + if (yypact_value_is_default (yyn)) goto yydefault; /* Not known => get a lookahead token if don't already have one. */ @@ -2013,8 +2186,8 @@ yybackup: yyn = yytable[yyn]; if (yyn <= 0) { - if (yyn == 0 || yyn == YYTABLE_NINF) - goto yyerrlab; + if (yytable_value_is_error (yyn)) + goto yyerrlab; yyn = -yyn; goto yyreduce; } @@ -2031,8 +2204,10 @@ yybackup: yychar = YYEMPTY; yystate = yyn; + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; - + YY_IGNORE_MAYBE_UNINITIALIZED_END + *++yylsp = yylloc; goto yynewstate; @@ -2063,18 +2238,19 @@ yyreduce: GCC warning that YYVAL may be used uninitialized. */ yyval = yyvsp[1-yylen]; - + /* Default location. */ + YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen); YY_REDUCE_PRINT (yyn); switch (yyn) { - case 2: + case 4: { // The symbol table search was done in the lexical phase const TSymbol* symbol = (yyvsp[(1) - (1)].lex).symbol; const TVariable* variable; if (symbol == 0) { - context->error((yyvsp[(1) - (1)].lex).line, "undeclared identifier", (yyvsp[(1) - (1)].lex).string->c_str()); + context->error((yylsp[(1) - (1)]), "undeclared identifier", (yyvsp[(1) - (1)].lex).string->c_str()); context->recover(); TType type(EbtFloat, EbpUndefined); TVariable* fakeVariable = new TVariable((yyvsp[(1) - (1)].lex).string, type); @@ -2083,10 +2259,17 @@ yyreduce: } else { // This identifier can only be a variable type symbol if (! symbol->isVariable()) { - context->error((yyvsp[(1) - (1)].lex).line, "variable expected", (yyvsp[(1) - (1)].lex).string->c_str()); + context->error((yylsp[(1) - (1)]), "variable expected", (yyvsp[(1) - (1)].lex).string->c_str()); context->recover(); } + variable = static_cast(symbol); + + if (context->symbolTable.findBuiltIn(variable->getName()) && + !variable->getExtension().empty() && + context->extensionErrorCheck((yylsp[(1) - (1)]), variable->getExtension())) { + context->recover(); + } } // don't delete $1.string, it's used by error recovery, and the pool @@ -2095,22 +2278,23 @@ yyreduce: if (variable->getType().getQualifier() == EvqConst ) { ConstantUnion* constArray = variable->getConstPointer(); TType t(variable->getType()); - (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(constArray, t, (yyvsp[(1) - (1)].lex).line); + (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(constArray, t, (yylsp[(1) - (1)])); } else (yyval.interm.intermTypedNode) = context->intermediate.addSymbol(variable->getUniqueId(), - variable->getName(), - variable->getType(), (yyvsp[(1) - (1)].lex).line); + variable->getName(), + variable->getType(), + (yylsp[(1) - (1)])); } break; - case 3: + case 5: { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); } break; - case 4: + case 6: { // @@ -2118,127 +2302,37 @@ yyreduce: // check for overflow for constants // if (abs((yyvsp[(1) - (1)].lex).i) >= (1 << 16)) { - context->error((yyvsp[(1) - (1)].lex).line, " integer constant overflow", ""); + context->error((yylsp[(1) - (1)]), " integer constant overflow", ""); context->recover(); } ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setIConst((yyvsp[(1) - (1)].lex).i); - (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), (yyvsp[(1) - (1)].lex).line); - } - break; - - case 5: - - { - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setFConst((yyvsp[(1) - (1)].lex).f); - (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), (yyvsp[(1) - (1)].lex).line); - } - break; - - case 6: - - { - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setBConst((yyvsp[(1) - (1)].lex).b); - (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yyvsp[(1) - (1)].lex).line); + (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), (yylsp[(1) - (1)])); } break; case 7: { - (yyval.interm.intermTypedNode) = (yyvsp[(2) - (3)].interm.intermTypedNode); + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setFConst((yyvsp[(1) - (1)].lex).f); + (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), (yylsp[(1) - (1)])); } break; case 8: { - (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setBConst((yyvsp[(1) - (1)].lex).b); + (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yylsp[(1) - (1)])); } break; case 9: { - if (!(yyvsp[(1) - (4)].interm.intermTypedNode)->isArray() && !(yyvsp[(1) - (4)].interm.intermTypedNode)->isMatrix() && !(yyvsp[(1) - (4)].interm.intermTypedNode)->isVector()) { - if ((yyvsp[(1) - (4)].interm.intermTypedNode)->getAsSymbolNode()) - context->error((yyvsp[(2) - (4)].lex).line, " left of '[' is not of type array, matrix, or vector ", (yyvsp[(1) - (4)].interm.intermTypedNode)->getAsSymbolNode()->getSymbol().c_str()); - else - context->error((yyvsp[(2) - (4)].lex).line, " left of '[' is not of type array, matrix, or vector ", "expression"); - context->recover(); - } - if ((yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getQualifier() == EvqConst && (yyvsp[(3) - (4)].interm.intermTypedNode)->getQualifier() == EvqConst) { - if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isArray()) { // constant folding for arrays - (yyval.interm.intermTypedNode) = context->addConstArrayNode((yyvsp[(3) - (4)].interm.intermTypedNode)->getAsConstantUnion()->getIConst(0), (yyvsp[(1) - (4)].interm.intermTypedNode), (yyvsp[(2) - (4)].lex).line); - } else if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isVector()) { // constant folding for vectors - TVectorFields fields; - fields.num = 1; - fields.offsets[0] = (yyvsp[(3) - (4)].interm.intermTypedNode)->getAsConstantUnion()->getIConst(0); // need to do it this way because v.xy sends fields integer array - (yyval.interm.intermTypedNode) = context->addConstVectorNode(fields, (yyvsp[(1) - (4)].interm.intermTypedNode), (yyvsp[(2) - (4)].lex).line); - } else if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isMatrix()) { // constant folding for matrices - (yyval.interm.intermTypedNode) = context->addConstMatrixNode((yyvsp[(3) - (4)].interm.intermTypedNode)->getAsConstantUnion()->getIConst(0), (yyvsp[(1) - (4)].interm.intermTypedNode), (yyvsp[(2) - (4)].lex).line); - } - } else { - if ((yyvsp[(3) - (4)].interm.intermTypedNode)->getQualifier() == EvqConst) { - if (((yyvsp[(1) - (4)].interm.intermTypedNode)->isVector() || (yyvsp[(1) - (4)].interm.intermTypedNode)->isMatrix()) && (yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getNominalSize() <= (yyvsp[(3) - (4)].interm.intermTypedNode)->getAsConstantUnion()->getIConst(0) && !(yyvsp[(1) - (4)].interm.intermTypedNode)->isArray() ) { - std::stringstream extraInfoStream; - extraInfoStream << "field selection out of range '" << (yyvsp[(3) - (4)].interm.intermTypedNode)->getAsConstantUnion()->getIConst(0) << "'"; - std::string extraInfo = extraInfoStream.str(); - context->error((yyvsp[(2) - (4)].lex).line, "", "[", extraInfo.c_str()); - context->recover(); - } else { - if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isArray()) { - if ((yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getArraySize() == 0) { - if ((yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getMaxArraySize() <= (yyvsp[(3) - (4)].interm.intermTypedNode)->getAsConstantUnion()->getIConst(0)) { - if (context->arraySetMaxSize((yyvsp[(1) - (4)].interm.intermTypedNode)->getAsSymbolNode(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getTypePointer(), (yyvsp[(3) - (4)].interm.intermTypedNode)->getAsConstantUnion()->getIConst(0), true, (yyvsp[(2) - (4)].lex).line)) - context->recover(); - } else { - if (context->arraySetMaxSize((yyvsp[(1) - (4)].interm.intermTypedNode)->getAsSymbolNode(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getTypePointer(), 0, false, (yyvsp[(2) - (4)].lex).line)) - context->recover(); - } - } else if ( (yyvsp[(3) - (4)].interm.intermTypedNode)->getAsConstantUnion()->getIConst(0) >= (yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getArraySize()) { - std::stringstream extraInfoStream; - extraInfoStream << "array index out of range '" << (yyvsp[(3) - (4)].interm.intermTypedNode)->getAsConstantUnion()->getIConst(0) << "'"; - std::string extraInfo = extraInfoStream.str(); - context->error((yyvsp[(2) - (4)].lex).line, "", "[", extraInfo.c_str()); - context->recover(); - } - } - (yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpIndexDirect, (yyvsp[(1) - (4)].interm.intermTypedNode), (yyvsp[(3) - (4)].interm.intermTypedNode), (yyvsp[(2) - (4)].lex).line); - } - } else { - if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isArray() && (yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getArraySize() == 0) { - context->error((yyvsp[(2) - (4)].lex).line, "", "[", "array must be redeclared with a size before being indexed with a variable"); - context->recover(); - } - - (yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpIndexIndirect, (yyvsp[(1) - (4)].interm.intermTypedNode), (yyvsp[(3) - (4)].interm.intermTypedNode), (yyvsp[(2) - (4)].lex).line); - } - } - if ((yyval.interm.intermTypedNode) == 0) { - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setFConst(0.0f); - (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), (yyvsp[(2) - (4)].lex).line); - } else if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isArray()) { - if ((yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getStruct()) - (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getStruct(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getTypeName())); - else - (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (4)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getPrecision(), EvqTemporary, (yyvsp[(1) - (4)].interm.intermTypedNode)->getNominalSize(), (yyvsp[(1) - (4)].interm.intermTypedNode)->isMatrix())); - - if ((yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getQualifier() == EvqConst) - (yyval.interm.intermTypedNode)->getTypePointer()->setQualifier(EvqConst); - } else if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isMatrix() && (yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getQualifier() == EvqConst) - (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (4)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getPrecision(), EvqConst, (yyvsp[(1) - (4)].interm.intermTypedNode)->getNominalSize())); - else if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isMatrix()) - (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (4)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getPrecision(), EvqTemporary, (yyvsp[(1) - (4)].interm.intermTypedNode)->getNominalSize())); - else if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isVector() && (yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getQualifier() == EvqConst) - (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (4)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getPrecision(), EvqConst)); - else if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isVector()) - (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (4)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getPrecision(), EvqTemporary)); - else - (yyval.interm.intermTypedNode)->setType((yyvsp[(1) - (4)].interm.intermTypedNode)->getType()); + (yyval.interm.intermTypedNode) = (yyvsp[(2) - (3)].interm.intermTypedNode); } break; @@ -2251,22 +2345,36 @@ yyreduce: case 11: + { + (yyval.interm.intermTypedNode) = context->addIndexExpression((yyvsp[(1) - (4)].interm.intermTypedNode), (yylsp[(2) - (4)]), (yyvsp[(3) - (4)].interm.intermTypedNode)); + } + break; + + case 12: + + { + (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); + } + break; + + case 13: + { if ((yyvsp[(1) - (3)].interm.intermTypedNode)->isArray()) { - context->error((yyvsp[(3) - (3)].lex).line, "cannot apply dot operator to an array", "."); + context->error((yylsp[(3) - (3)]), "cannot apply dot operator to an array", "."); context->recover(); } if ((yyvsp[(1) - (3)].interm.intermTypedNode)->isVector()) { TVectorFields fields; - if (! context->parseVectorFields(*(yyvsp[(3) - (3)].lex).string, (yyvsp[(1) - (3)].interm.intermTypedNode)->getNominalSize(), fields, (yyvsp[(3) - (3)].lex).line)) { + if (! context->parseVectorFields(*(yyvsp[(3) - (3)].lex).string, (yyvsp[(1) - (3)].interm.intermTypedNode)->getNominalSize(), fields, (yylsp[(3) - (3)]))) { fields.num = 1; fields.offsets[0] = 0; context->recover(); } if ((yyvsp[(1) - (3)].interm.intermTypedNode)->getType().getQualifier() == EvqConst) { // constant folding for vector fields - (yyval.interm.intermTypedNode) = context->addConstVectorNode(fields, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].lex).line); + (yyval.interm.intermTypedNode) = context->addConstVectorNode(fields, (yyvsp[(1) - (3)].interm.intermTypedNode), (yylsp[(3) - (3)])); if ((yyval.interm.intermTypedNode) == 0) { context->recover(); (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode); @@ -2275,13 +2383,13 @@ yyreduce: (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (3)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (3)].interm.intermTypedNode)->getPrecision(), EvqConst, (int) (*(yyvsp[(3) - (3)].lex).string).size())); } else { TString vectorString = *(yyvsp[(3) - (3)].lex).string; - TIntermTyped* index = context->intermediate.addSwizzle(fields, (yyvsp[(3) - (3)].lex).line); - (yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpVectorSwizzle, (yyvsp[(1) - (3)].interm.intermTypedNode), index, (yyvsp[(2) - (3)].lex).line); + TIntermTyped* index = context->intermediate.addSwizzle(fields, (yylsp[(3) - (3)])); + (yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpVectorSwizzle, (yyvsp[(1) - (3)].interm.intermTypedNode), index, (yylsp[(2) - (3)])); (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (3)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (3)].interm.intermTypedNode)->getPrecision(), EvqTemporary, (int) vectorString.size())); } } else if ((yyvsp[(1) - (3)].interm.intermTypedNode)->isMatrix()) { TMatrixFields fields; - if (! context->parseMatrixFields(*(yyvsp[(3) - (3)].lex).string, (yyvsp[(1) - (3)].interm.intermTypedNode)->getNominalSize(), fields, (yyvsp[(3) - (3)].lex).line)) { + if (! context->parseMatrixFields(*(yyvsp[(3) - (3)].lex).string, (yyvsp[(1) - (3)].interm.intermTypedNode)->getNominalSize(), fields, (yylsp[(3) - (3)]))) { fields.wholeRow = false; fields.wholeCol = false; fields.row = 0; @@ -2290,63 +2398,57 @@ yyreduce: } if (fields.wholeRow || fields.wholeCol) { - context->error((yyvsp[(2) - (3)].lex).line, " non-scalar fields not implemented yet", "."); + context->error((yylsp[(2) - (3)]), " non-scalar fields not implemented yet", "."); context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setIConst(0); - TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), (yyvsp[(3) - (3)].lex).line); - (yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpIndexDirect, (yyvsp[(1) - (3)].interm.intermTypedNode), index, (yyvsp[(2) - (3)].lex).line); + TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), (yylsp[(3) - (3)])); + (yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpIndexDirect, (yyvsp[(1) - (3)].interm.intermTypedNode), index, (yylsp[(2) - (3)])); (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (3)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (3)].interm.intermTypedNode)->getPrecision(),EvqTemporary, (yyvsp[(1) - (3)].interm.intermTypedNode)->getNominalSize())); } else { ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setIConst(fields.col * (yyvsp[(1) - (3)].interm.intermTypedNode)->getNominalSize() + fields.row); - TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), (yyvsp[(3) - (3)].lex).line); - (yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpIndexDirect, (yyvsp[(1) - (3)].interm.intermTypedNode), index, (yyvsp[(2) - (3)].lex).line); + TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), (yylsp[(3) - (3)])); + (yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpIndexDirect, (yyvsp[(1) - (3)].interm.intermTypedNode), index, (yylsp[(2) - (3)])); (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (3)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (3)].interm.intermTypedNode)->getPrecision())); } } else if ((yyvsp[(1) - (3)].interm.intermTypedNode)->getBasicType() == EbtStruct) { bool fieldFound = false; - const TTypeList* fields = (yyvsp[(1) - (3)].interm.intermTypedNode)->getType().getStruct(); - if (fields == 0) { - context->error((yyvsp[(2) - (3)].lex).line, "structure has no fields", "Internal Error"); - context->recover(); - (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode); - } else { - unsigned int i; - for (i = 0; i < fields->size(); ++i) { - if ((*fields)[i].type->getFieldName() == *(yyvsp[(3) - (3)].lex).string) { - fieldFound = true; - break; - } - } - if (fieldFound) { - if ((yyvsp[(1) - (3)].interm.intermTypedNode)->getType().getQualifier() == EvqConst) { - (yyval.interm.intermTypedNode) = context->addConstStruct(*(yyvsp[(3) - (3)].lex).string, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line); - if ((yyval.interm.intermTypedNode) == 0) { - context->recover(); - (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode); - } - else { - (yyval.interm.intermTypedNode)->setType(*(*fields)[i].type); - // change the qualifier of the return type, not of the structure field - // as the structure definition is shared between various structures. - (yyval.interm.intermTypedNode)->getTypePointer()->setQualifier(EvqConst); - } - } else { - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setIConst(i); - TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, *(*fields)[i].type, (yyvsp[(3) - (3)].lex).line); - (yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpIndexDirectStruct, (yyvsp[(1) - (3)].interm.intermTypedNode), index, (yyvsp[(2) - (3)].lex).line); - (yyval.interm.intermTypedNode)->setType(*(*fields)[i].type); - } - } else { - context->error((yyvsp[(2) - (3)].lex).line, " no such field in structure", (yyvsp[(3) - (3)].lex).string->c_str()); - context->recover(); - (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode); + const TFieldList& fields = (yyvsp[(1) - (3)].interm.intermTypedNode)->getType().getStruct()->fields(); + unsigned int i; + for (i = 0; i < fields.size(); ++i) { + if (fields[i]->name() == *(yyvsp[(3) - (3)].lex).string) { + fieldFound = true; + break; } } + if (fieldFound) { + if ((yyvsp[(1) - (3)].interm.intermTypedNode)->getType().getQualifier() == EvqConst) { + (yyval.interm.intermTypedNode) = context->addConstStruct(*(yyvsp[(3) - (3)].lex).string, (yyvsp[(1) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)])); + if ((yyval.interm.intermTypedNode) == 0) { + context->recover(); + (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode); + } + else { + (yyval.interm.intermTypedNode)->setType(*fields[i]->type()); + // change the qualifier of the return type, not of the structure field + // as the structure definition is shared between various structures. + (yyval.interm.intermTypedNode)->getTypePointer()->setQualifier(EvqConst); + } + } else { + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setIConst(i); + TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, *fields[i]->type(), (yylsp[(3) - (3)])); + (yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpIndexDirectStruct, (yyvsp[(1) - (3)].interm.intermTypedNode), index, (yylsp[(2) - (3)])); + (yyval.interm.intermTypedNode)->setType(*fields[i]->type()); + } + } else { + context->error((yylsp[(2) - (3)]), " no such field in structure", (yyvsp[(3) - (3)].lex).string->c_str()); + context->recover(); + (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode); + } } else { - context->error((yyvsp[(2) - (3)].lex).line, " field selection requires structure, vector, or matrix on left hand side", (yyvsp[(3) - (3)].lex).string->c_str()); + context->error((yylsp[(2) - (3)]), " field selection requires structure, vector, or matrix on left hand side", (yyvsp[(3) - (3)].lex).string->c_str()); context->recover(); (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode); } @@ -2354,36 +2456,36 @@ yyreduce: } break; - case 12: - - { - if (context->lValueErrorCheck((yyvsp[(2) - (2)].lex).line, "++", (yyvsp[(1) - (2)].interm.intermTypedNode))) - context->recover(); - (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath(EOpPostIncrement, (yyvsp[(1) - (2)].interm.intermTypedNode), (yyvsp[(2) - (2)].lex).line, context->symbolTable); - if ((yyval.interm.intermTypedNode) == 0) { - context->unaryOpError((yyvsp[(2) - (2)].lex).line, "++", (yyvsp[(1) - (2)].interm.intermTypedNode)->getCompleteString()); - context->recover(); - (yyval.interm.intermTypedNode) = (yyvsp[(1) - (2)].interm.intermTypedNode); - } - } - break; - - case 13: - - { - if (context->lValueErrorCheck((yyvsp[(2) - (2)].lex).line, "--", (yyvsp[(1) - (2)].interm.intermTypedNode))) - context->recover(); - (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath(EOpPostDecrement, (yyvsp[(1) - (2)].interm.intermTypedNode), (yyvsp[(2) - (2)].lex).line, context->symbolTable); - if ((yyval.interm.intermTypedNode) == 0) { - context->unaryOpError((yyvsp[(2) - (2)].lex).line, "--", (yyvsp[(1) - (2)].interm.intermTypedNode)->getCompleteString()); - context->recover(); - (yyval.interm.intermTypedNode) = (yyvsp[(1) - (2)].interm.intermTypedNode); - } - } - break; - case 14: + { + if (context->lValueErrorCheck((yylsp[(2) - (2)]), "++", (yyvsp[(1) - (2)].interm.intermTypedNode))) + context->recover(); + (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath(EOpPostIncrement, (yyvsp[(1) - (2)].interm.intermTypedNode), (yylsp[(2) - (2)]), context->symbolTable); + if ((yyval.interm.intermTypedNode) == 0) { + context->unaryOpError((yylsp[(2) - (2)]), "++", (yyvsp[(1) - (2)].interm.intermTypedNode)->getCompleteString()); + context->recover(); + (yyval.interm.intermTypedNode) = (yyvsp[(1) - (2)].interm.intermTypedNode); + } + } + break; + + case 15: + + { + if (context->lValueErrorCheck((yylsp[(2) - (2)]), "--", (yyvsp[(1) - (2)].interm.intermTypedNode))) + context->recover(); + (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath(EOpPostDecrement, (yyvsp[(1) - (2)].interm.intermTypedNode), (yylsp[(2) - (2)]), context->symbolTable); + if ((yyval.interm.intermTypedNode) == 0) { + context->unaryOpError((yylsp[(2) - (2)]), "--", (yyvsp[(1) - (2)].interm.intermTypedNode)->getCompleteString()); + context->recover(); + (yyval.interm.intermTypedNode) = (yyvsp[(1) - (2)].interm.intermTypedNode); + } + } + break; + + case 16: + { if (context->integerErrorCheck((yyvsp[(1) - (1)].interm.intermTypedNode), "[]")) context->recover(); @@ -2391,7 +2493,7 @@ yyreduce: } break; - case 15: + case 17: { TFunction* fnCall = (yyvsp[(1) - (1)].interm).function; @@ -2405,18 +2507,18 @@ yyreduce: // Their parameters will be verified algorithmically. // TType type(EbtVoid, EbpUndefined); // use this to get the type back - if (context->constructorErrorCheck((yyvsp[(1) - (1)].interm).line, (yyvsp[(1) - (1)].interm).intermNode, *fnCall, op, &type)) { + if (context->constructorErrorCheck((yylsp[(1) - (1)]), (yyvsp[(1) - (1)].interm).intermNode, *fnCall, op, &type)) { (yyval.interm.intermTypedNode) = 0; } else { // // It's a constructor, of type 'type'. // - (yyval.interm.intermTypedNode) = context->addConstructor((yyvsp[(1) - (1)].interm).intermNode, &type, op, fnCall, (yyvsp[(1) - (1)].interm).line); + (yyval.interm.intermTypedNode) = context->addConstructor((yyvsp[(1) - (1)].interm).intermNode, &type, op, fnCall, (yylsp[(1) - (1)])); } if ((yyval.interm.intermTypedNode) == 0) { context->recover(); - (yyval.interm.intermTypedNode) = context->intermediate.setAggregateOperator(0, op, (yyvsp[(1) - (1)].interm).line); + (yyval.interm.intermTypedNode) = context->intermediate.setAggregateOperator(0, op, (yylsp[(1) - (1)])); } (yyval.interm.intermTypedNode)->setType(type); } else { @@ -2425,13 +2527,13 @@ yyreduce: // const TFunction* fnCandidate; bool builtIn; - fnCandidate = context->findFunction((yyvsp[(1) - (1)].interm).line, fnCall, &builtIn); + fnCandidate = context->findFunction((yylsp[(1) - (1)]), fnCall, &builtIn); if (fnCandidate) { // // A declared function. // if (builtIn && !fnCandidate->getExtension().empty() && - context->extensionErrorCheck((yyvsp[(1) - (1)].interm).line, fnCandidate->getExtension())) { + context->extensionErrorCheck((yylsp[(1) - (1)]), fnCandidate->getExtension())) { context->recover(); } op = fnCandidate->getBuiltInOp(); @@ -2443,7 +2545,7 @@ yyreduce: // // Treat it like a built-in unary operator. // - (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath(op, (yyvsp[(1) - (1)].interm).intermNode, 0, context->symbolTable); + (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath(op, (yyvsp[(1) - (1)].interm).intermNode, (yylsp[(1) - (1)]), context->symbolTable); if ((yyval.interm.intermTypedNode) == 0) { std::stringstream extraInfoStream; extraInfoStream << "built in unary operator function. Type: " << static_cast((yyvsp[(1) - (1)].interm).intermNode)->getCompleteString(); @@ -2452,12 +2554,12 @@ yyreduce: YYERROR; } } else { - (yyval.interm.intermTypedNode) = context->intermediate.setAggregateOperator((yyvsp[(1) - (1)].interm).intermAggregate, op, (yyvsp[(1) - (1)].interm).line); + (yyval.interm.intermTypedNode) = context->intermediate.setAggregateOperator((yyvsp[(1) - (1)].interm).intermAggregate, op, (yylsp[(1) - (1)])); } } else { // This is a real function call - (yyval.interm.intermTypedNode) = context->intermediate.setAggregateOperator((yyvsp[(1) - (1)].interm).intermAggregate, EOpFunctionCall, (yyvsp[(1) - (1)].interm).line); + (yyval.interm.intermTypedNode) = context->intermediate.setAggregateOperator((yyvsp[(1) - (1)].interm).intermAggregate, EOpFunctionCall, (yylsp[(1) - (1)])); (yyval.interm.intermTypedNode)->setType(fnCandidate->getReturnType()); // this is how we know whether the given function is a builtIn function or a user defined function @@ -2484,7 +2586,7 @@ yyreduce: // Put on a dummy node for error recovery ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setFConst(0.0f); - (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), (yyvsp[(1) - (1)].interm).line); + (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), (yylsp[(1) - (1)])); context->recover(); } } @@ -2492,47 +2594,45 @@ yyreduce: } break; - case 16: + case 18: { (yyval.interm) = (yyvsp[(1) - (1)].interm); } break; - case 17: + case 19: { - context->error((yyvsp[(3) - (3)].interm).line, "methods are not supported", ""); + context->error((yylsp[(3) - (3)]), "methods are not supported", ""); context->recover(); (yyval.interm) = (yyvsp[(3) - (3)].interm); } break; - case 18: - - { - (yyval.interm) = (yyvsp[(1) - (2)].interm); - (yyval.interm).line = (yyvsp[(2) - (2)].lex).line; - } - break; - - case 19: - - { - (yyval.interm) = (yyvsp[(1) - (2)].interm); - (yyval.interm).line = (yyvsp[(2) - (2)].lex).line; - } - break; - case 20: + { + (yyval.interm) = (yyvsp[(1) - (2)].interm); + } + break; + + case 21: + + { + (yyval.interm) = (yyvsp[(1) - (2)].interm); + } + break; + + case 22: + { (yyval.interm).function = (yyvsp[(1) - (2)].interm.function); (yyval.interm).intermNode = 0; } break; - case 21: + case 23: { (yyval.interm).function = (yyvsp[(1) - (1)].interm.function); @@ -2540,7 +2640,7 @@ yyreduce: } break; - case 22: + case 24: { TParameter param = { 0, new TType((yyvsp[(2) - (2)].interm.intermTypedNode)->getType()) }; @@ -2550,24 +2650,24 @@ yyreduce: } break; - case 23: + case 25: { TParameter param = { 0, new TType((yyvsp[(3) - (3)].interm.intermTypedNode)->getType()) }; (yyvsp[(1) - (3)].interm).function->addParameter(param); (yyval.interm).function = (yyvsp[(1) - (3)].interm).function; - (yyval.interm).intermNode = context->intermediate.growAggregate((yyvsp[(1) - (3)].interm).intermNode, (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line); + (yyval.interm).intermNode = context->intermediate.growAggregate((yyvsp[(1) - (3)].interm).intermNode, (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)])); } break; - case 24: + case 26: { (yyval.interm.function) = (yyvsp[(1) - (2)].interm.function); } break; - case 25: + case 27: { // @@ -2581,39 +2681,39 @@ yyreduce: case EbtFloat: if ((yyvsp[(1) - (1)].interm.type).matrix) { switch((yyvsp[(1) - (1)].interm.type).size) { - case 2: op = EOpConstructMat2; break; - case 3: op = EOpConstructMat3; break; - case 4: op = EOpConstructMat4; break; + case 2: op = EOpConstructMat2; break; + case 3: op = EOpConstructMat3; break; + case 4: op = EOpConstructMat4; break; } } else { switch((yyvsp[(1) - (1)].interm.type).size) { - case 1: op = EOpConstructFloat; break; - case 2: op = EOpConstructVec2; break; - case 3: op = EOpConstructVec3; break; - case 4: op = EOpConstructVec4; break; + case 1: op = EOpConstructFloat; break; + case 2: op = EOpConstructVec2; break; + case 3: op = EOpConstructVec3; break; + case 4: op = EOpConstructVec4; break; } } break; case EbtInt: switch((yyvsp[(1) - (1)].interm.type).size) { - case 1: op = EOpConstructInt; break; - case 2: FRAG_VERT_ONLY("ivec2", (yyvsp[(1) - (1)].interm.type).line); op = EOpConstructIVec2; break; - case 3: FRAG_VERT_ONLY("ivec3", (yyvsp[(1) - (1)].interm.type).line); op = EOpConstructIVec3; break; - case 4: FRAG_VERT_ONLY("ivec4", (yyvsp[(1) - (1)].interm.type).line); op = EOpConstructIVec4; break; + case 1: op = EOpConstructInt; break; + case 2: op = EOpConstructIVec2; break; + case 3: op = EOpConstructIVec3; break; + case 4: op = EOpConstructIVec4; break; } break; case EbtBool: switch((yyvsp[(1) - (1)].interm.type).size) { - case 1: op = EOpConstructBool; break; - case 2: FRAG_VERT_ONLY("bvec2", (yyvsp[(1) - (1)].interm.type).line); op = EOpConstructBVec2; break; - case 3: FRAG_VERT_ONLY("bvec3", (yyvsp[(1) - (1)].interm.type).line); op = EOpConstructBVec3; break; - case 4: FRAG_VERT_ONLY("bvec4", (yyvsp[(1) - (1)].interm.type).line); op = EOpConstructBVec4; break; + case 1: op = EOpConstructBool; break; + case 2: op = EOpConstructBVec2; break; + case 3: op = EOpConstructBVec3; break; + case 4: op = EOpConstructBVec4; break; } break; default: break; } if (op == EOpNull) { - context->error((yyvsp[(1) - (1)].interm.type).line, "cannot construct this type", getBasicString((yyvsp[(1) - (1)].interm.type).type)); + context->error((yylsp[(1) - (1)]), "cannot construct this type", getBasicString((yyvsp[(1) - (1)].interm.type).type)); context->recover(); (yyvsp[(1) - (1)].interm.type).type = EbtFloat; op = EOpConstructFloat; @@ -2626,57 +2726,32 @@ yyreduce: } break; - case 26: - - { - if (context->reservedErrorCheck((yyvsp[(1) - (1)].lex).line, *(yyvsp[(1) - (1)].lex).string)) - context->recover(); - TType type(EbtVoid, EbpUndefined); - TFunction *function = new TFunction((yyvsp[(1) - (1)].lex).string, type); - (yyval.interm.function) = function; - } - break; - - case 27: - - { - if (context->reservedErrorCheck((yyvsp[(1) - (1)].lex).line, *(yyvsp[(1) - (1)].lex).string)) - context->recover(); - TType type(EbtVoid, EbpUndefined); - TFunction *function = new TFunction((yyvsp[(1) - (1)].lex).string, type); - (yyval.interm.function) = function; - } - break; - case 28: { - (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); + if (context->reservedErrorCheck((yylsp[(1) - (1)]), *(yyvsp[(1) - (1)].lex).string)) + context->recover(); + TType type(EbtVoid, EbpUndefined); + TFunction *function = new TFunction((yyvsp[(1) - (1)].lex).string, type); + (yyval.interm.function) = function; } break; case 29: { - if (context->lValueErrorCheck((yyvsp[(1) - (2)].lex).line, "++", (yyvsp[(2) - (2)].interm.intermTypedNode))) - context->recover(); - (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath(EOpPreIncrement, (yyvsp[(2) - (2)].interm.intermTypedNode), (yyvsp[(1) - (2)].lex).line, context->symbolTable); - if ((yyval.interm.intermTypedNode) == 0) { - context->unaryOpError((yyvsp[(1) - (2)].lex).line, "++", (yyvsp[(2) - (2)].interm.intermTypedNode)->getCompleteString()); - context->recover(); - (yyval.interm.intermTypedNode) = (yyvsp[(2) - (2)].interm.intermTypedNode); - } + (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); } break; case 30: { - if (context->lValueErrorCheck((yyvsp[(1) - (2)].lex).line, "--", (yyvsp[(2) - (2)].interm.intermTypedNode))) + if (context->lValueErrorCheck((yylsp[(1) - (2)]), "++", (yyvsp[(2) - (2)].interm.intermTypedNode))) context->recover(); - (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath(EOpPreDecrement, (yyvsp[(2) - (2)].interm.intermTypedNode), (yyvsp[(1) - (2)].lex).line, context->symbolTable); + (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath(EOpPreIncrement, (yyvsp[(2) - (2)].interm.intermTypedNode), (yylsp[(1) - (2)]), context->symbolTable); if ((yyval.interm.intermTypedNode) == 0) { - context->unaryOpError((yyvsp[(1) - (2)].lex).line, "--", (yyvsp[(2) - (2)].interm.intermTypedNode)->getCompleteString()); + context->unaryOpError((yylsp[(1) - (2)]), "++", (yyvsp[(2) - (2)].interm.intermTypedNode)->getCompleteString()); context->recover(); (yyval.interm.intermTypedNode) = (yyvsp[(2) - (2)].interm.intermTypedNode); } @@ -2685,9 +2760,23 @@ yyreduce: case 31: + { + if (context->lValueErrorCheck((yylsp[(1) - (2)]), "--", (yyvsp[(2) - (2)].interm.intermTypedNode))) + context->recover(); + (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath(EOpPreDecrement, (yyvsp[(2) - (2)].interm.intermTypedNode), (yylsp[(1) - (2)]), context->symbolTable); + if ((yyval.interm.intermTypedNode) == 0) { + context->unaryOpError((yylsp[(1) - (2)]), "--", (yyvsp[(2) - (2)].interm.intermTypedNode)->getCompleteString()); + context->recover(); + (yyval.interm.intermTypedNode) = (yyvsp[(2) - (2)].interm.intermTypedNode); + } + } + break; + + case 32: + { if ((yyvsp[(1) - (2)].interm).op != EOpNull) { - (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath((yyvsp[(1) - (2)].interm).op, (yyvsp[(2) - (2)].interm.intermTypedNode), (yyvsp[(1) - (2)].interm).line, context->symbolTable); + (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath((yyvsp[(1) - (2)].interm).op, (yyvsp[(2) - (2)].interm.intermTypedNode), (yylsp[(1) - (2)]), context->symbolTable); if ((yyval.interm.intermTypedNode) == 0) { const char* errorOp = ""; switch((yyvsp[(1) - (2)].interm).op) { @@ -2695,7 +2784,7 @@ yyreduce: case EOpLogicalNot: errorOp = "!"; break; default: break; } - context->unaryOpError((yyvsp[(1) - (2)].interm).line, errorOp, (yyvsp[(2) - (2)].interm.intermTypedNode)->getCompleteString()); + context->unaryOpError((yylsp[(1) - (2)]), errorOp, (yyvsp[(2) - (2)].interm.intermTypedNode)->getCompleteString()); context->recover(); (yyval.interm.intermTypedNode) = (yyvsp[(2) - (2)].interm.intermTypedNode); } @@ -2704,46 +2793,32 @@ yyreduce: } break; - case 32: - - { (yyval.interm).line = (yyvsp[(1) - (1)].lex).line; (yyval.interm).op = EOpNull; } - break; - case 33: - { (yyval.interm).line = (yyvsp[(1) - (1)].lex).line; (yyval.interm).op = EOpNegative; } + { (yyval.interm).op = EOpNull; } break; case 34: - { (yyval.interm).line = (yyvsp[(1) - (1)].lex).line; (yyval.interm).op = EOpLogicalNot; } + { (yyval.interm).op = EOpNegative; } break; case 35: - { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); } + { (yyval.interm).op = EOpLogicalNot; } break; case 36: - { - FRAG_VERT_ONLY("*", (yyvsp[(2) - (3)].lex).line); - (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpMul, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable); - if ((yyval.interm.intermTypedNode) == 0) { - context->binaryOpError((yyvsp[(2) - (3)].lex).line, "*", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); - context->recover(); - (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode); - } - } + { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); } break; case 37: { - FRAG_VERT_ONLY("/", (yyvsp[(2) - (3)].lex).line); - (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpDiv, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable); + (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpMul, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]), context->symbolTable); if ((yyval.interm.intermTypedNode) == 0) { - context->binaryOpError((yyvsp[(2) - (3)].lex).line, "/", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); + context->binaryOpError((yylsp[(2) - (3)]), "*", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); context->recover(); (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode); } @@ -2752,27 +2827,27 @@ yyreduce: case 38: - { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); } - break; - - case 39: - { - (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpAdd, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable); + (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpDiv, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]), context->symbolTable); if ((yyval.interm.intermTypedNode) == 0) { - context->binaryOpError((yyvsp[(2) - (3)].lex).line, "+", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); + context->binaryOpError((yylsp[(2) - (3)]), "/", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); context->recover(); (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode); } } break; + case 39: + + { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); } + break; + case 40: { - (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpSub, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable); + (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpAdd, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]), context->symbolTable); if ((yyval.interm.intermTypedNode) == 0) { - context->binaryOpError((yyvsp[(2) - (3)].lex).line, "-", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); + context->binaryOpError((yylsp[(2) - (3)]), "+", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); context->recover(); (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode); } @@ -2781,7 +2856,14 @@ yyreduce: case 41: - { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); } + { + (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpSub, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]), context->symbolTable); + if ((yyval.interm.intermTypedNode) == 0) { + context->binaryOpError((yylsp[(2) - (3)]), "-", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); + context->recover(); + (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode); + } + } break; case 42: @@ -2791,28 +2873,19 @@ yyreduce: case 43: - { - (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpLessThan, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable); - if ((yyval.interm.intermTypedNode) == 0) { - context->binaryOpError((yyvsp[(2) - (3)].lex).line, "<", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); - context->recover(); - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setBConst(false); - (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yyvsp[(2) - (3)].lex).line); - } - } + { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); } break; case 44: { - (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpGreaterThan, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable); + (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpLessThan, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]), context->symbolTable); if ((yyval.interm.intermTypedNode) == 0) { - context->binaryOpError((yyvsp[(2) - (3)].lex).line, ">", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); + context->binaryOpError((yylsp[(2) - (3)]), "<", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst(false); - (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yyvsp[(2) - (3)].lex).line); + (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yylsp[(2) - (3)])); } } break; @@ -2820,13 +2893,13 @@ yyreduce: case 45: { - (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpLessThanEqual, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable); + (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpGreaterThan, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]), context->symbolTable); if ((yyval.interm.intermTypedNode) == 0) { - context->binaryOpError((yyvsp[(2) - (3)].lex).line, "<=", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); + context->binaryOpError((yylsp[(2) - (3)]), ">", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst(false); - (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yyvsp[(2) - (3)].lex).line); + (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yylsp[(2) - (3)])); } } break; @@ -2834,53 +2907,62 @@ yyreduce: case 46: { - (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpGreaterThanEqual, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable); + (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpLessThanEqual, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]), context->symbolTable); if ((yyval.interm.intermTypedNode) == 0) { - context->binaryOpError((yyvsp[(2) - (3)].lex).line, ">=", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); + context->binaryOpError((yylsp[(2) - (3)]), "<=", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst(false); - (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yyvsp[(2) - (3)].lex).line); + (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yylsp[(2) - (3)])); } } break; case 47: - { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); } + { + (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpGreaterThanEqual, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]), context->symbolTable); + if ((yyval.interm.intermTypedNode) == 0) { + context->binaryOpError((yylsp[(2) - (3)]), ">=", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); + context->recover(); + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setBConst(false); + (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yylsp[(2) - (3)])); + } + } break; case 48: - { - (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpEqual, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable); - if ((yyval.interm.intermTypedNode) == 0) { - context->binaryOpError((yyvsp[(2) - (3)].lex).line, "==", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); - context->recover(); - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setBConst(false); - (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yyvsp[(2) - (3)].lex).line); - } - } + { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); } break; case 49: { - (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpNotEqual, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable); + (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpEqual, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]), context->symbolTable); if ((yyval.interm.intermTypedNode) == 0) { - context->binaryOpError((yyvsp[(2) - (3)].lex).line, "!=", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); + context->binaryOpError((yylsp[(2) - (3)]), "==", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst(false); - (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yyvsp[(2) - (3)].lex).line); + (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yylsp[(2) - (3)])); } } break; case 50: - { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); } + { + (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpNotEqual, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]), context->symbolTable); + if ((yyval.interm.intermTypedNode) == 0) { + context->binaryOpError((yylsp[(2) - (3)]), "!=", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); + context->recover(); + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setBConst(false); + (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yylsp[(2) - (3)])); + } + } break; case 51: @@ -2900,143 +2982,148 @@ yyreduce: case 54: - { - (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpLogicalAnd, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable); - if ((yyval.interm.intermTypedNode) == 0) { - context->binaryOpError((yyvsp[(2) - (3)].lex).line, "&&", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); - context->recover(); - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setBConst(false); - (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yyvsp[(2) - (3)].lex).line); - } - } + { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); } break; case 55: - { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); } + { + (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpLogicalAnd, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]), context->symbolTable); + if ((yyval.interm.intermTypedNode) == 0) { + context->binaryOpError((yylsp[(2) - (3)]), "&&", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); + context->recover(); + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setBConst(false); + (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yylsp[(2) - (3)])); + } + } break; case 56: - { - (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpLogicalXor, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable); - if ((yyval.interm.intermTypedNode) == 0) { - context->binaryOpError((yyvsp[(2) - (3)].lex).line, "^^", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); - context->recover(); - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setBConst(false); - (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yyvsp[(2) - (3)].lex).line); - } - } + { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); } break; case 57: - { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); } - break; - - case 58: - { - (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpLogicalOr, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable); + (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpLogicalXor, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]), context->symbolTable); if ((yyval.interm.intermTypedNode) == 0) { - context->binaryOpError((yyvsp[(2) - (3)].lex).line, "||", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); + context->binaryOpError((yylsp[(2) - (3)]), "^^", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst(false); - (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yyvsp[(2) - (3)].lex).line); + (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yylsp[(2) - (3)])); } } break; - case 59: + case 58: { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); } break; - case 60: + case 59: { - if (context->boolErrorCheck((yyvsp[(2) - (5)].lex).line, (yyvsp[(1) - (5)].interm.intermTypedNode))) + (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpLogicalOr, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]), context->symbolTable); + if ((yyval.interm.intermTypedNode) == 0) { + context->binaryOpError((yylsp[(2) - (3)]), "||", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); + context->recover(); + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setBConst(false); + (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yylsp[(2) - (3)])); + } + } + break; + + case 60: + + { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); } + break; + + case 61: + + { + if (context->boolErrorCheck((yylsp[(2) - (5)]), (yyvsp[(1) - (5)].interm.intermTypedNode))) context->recover(); - (yyval.interm.intermTypedNode) = context->intermediate.addSelection((yyvsp[(1) - (5)].interm.intermTypedNode), (yyvsp[(3) - (5)].interm.intermTypedNode), (yyvsp[(5) - (5)].interm.intermTypedNode), (yyvsp[(2) - (5)].lex).line); + (yyval.interm.intermTypedNode) = context->intermediate.addSelection((yyvsp[(1) - (5)].interm.intermTypedNode), (yyvsp[(3) - (5)].interm.intermTypedNode), (yyvsp[(5) - (5)].interm.intermTypedNode), (yylsp[(2) - (5)])); if ((yyvsp[(3) - (5)].interm.intermTypedNode)->getType() != (yyvsp[(5) - (5)].interm.intermTypedNode)->getType()) (yyval.interm.intermTypedNode) = 0; if ((yyval.interm.intermTypedNode) == 0) { - context->binaryOpError((yyvsp[(2) - (5)].lex).line, ":", (yyvsp[(3) - (5)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(5) - (5)].interm.intermTypedNode)->getCompleteString()); + context->binaryOpError((yylsp[(2) - (5)]), ":", (yyvsp[(3) - (5)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(5) - (5)].interm.intermTypedNode)->getCompleteString()); context->recover(); (yyval.interm.intermTypedNode) = (yyvsp[(5) - (5)].interm.intermTypedNode); } } break; - case 61: + case 62: { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); } break; - case 62: + case 63: { - if (context->lValueErrorCheck((yyvsp[(2) - (3)].interm).line, "assign", (yyvsp[(1) - (3)].interm.intermTypedNode))) + if (context->lValueErrorCheck((yylsp[(2) - (3)]), "assign", (yyvsp[(1) - (3)].interm.intermTypedNode))) context->recover(); - (yyval.interm.intermTypedNode) = context->intermediate.addAssign((yyvsp[(2) - (3)].interm).op, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].interm).line); + (yyval.interm.intermTypedNode) = context->intermediate.addAssign((yyvsp[(2) - (3)].interm).op, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)])); if ((yyval.interm.intermTypedNode) == 0) { - context->assignError((yyvsp[(2) - (3)].interm).line, "assign", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); + context->assignError((yylsp[(2) - (3)]), "assign", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); context->recover(); (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode); } } break; - case 63: - - { (yyval.interm).line = (yyvsp[(1) - (1)].lex).line; (yyval.interm).op = EOpAssign; } - break; - case 64: - { FRAG_VERT_ONLY("*=", (yyvsp[(1) - (1)].lex).line); (yyval.interm).line = (yyvsp[(1) - (1)].lex).line; (yyval.interm).op = EOpMulAssign; } + { (yyval.interm).op = EOpAssign; } break; case 65: - { FRAG_VERT_ONLY("/=", (yyvsp[(1) - (1)].lex).line); (yyval.interm).line = (yyvsp[(1) - (1)].lex).line; (yyval.interm).op = EOpDivAssign; } + { (yyval.interm).op = EOpMulAssign; } break; case 66: - { (yyval.interm).line = (yyvsp[(1) - (1)].lex).line; (yyval.interm).op = EOpAddAssign; } + { (yyval.interm).op = EOpDivAssign; } break; case 67: - { (yyval.interm).line = (yyvsp[(1) - (1)].lex).line; (yyval.interm).op = EOpSubAssign; } + { (yyval.interm).op = EOpAddAssign; } break; case 68: + { (yyval.interm).op = EOpSubAssign; } + break; + + case 69: + { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); } break; - case 69: + case 70: { - (yyval.interm.intermTypedNode) = context->intermediate.addComma((yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line); + (yyval.interm.intermTypedNode) = context->intermediate.addComma((yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)])); if ((yyval.interm.intermTypedNode) == 0) { - context->binaryOpError((yyvsp[(2) - (3)].lex).line, ",", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); + context->binaryOpError((yylsp[(2) - (3)]), ",", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); context->recover(); (yyval.interm.intermTypedNode) = (yyvsp[(3) - (3)].interm.intermTypedNode); } } break; - case 70: + case 71: { if (context->constErrorCheck((yyvsp[(1) - (1)].interm.intermTypedNode))) @@ -3045,7 +3132,7 @@ yyreduce: } break; - case 71: + case 72: { TFunction &function = *((yyvsp[(1) - (2)].interm).function); @@ -3059,13 +3146,13 @@ yyreduce: const TParameter ¶m = function.getParam(i); if (param.name != 0) { - TVariable *variable = new TVariable(param.name, *param.type); + TVariable variable(param.name, *param.type); - prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), (yyvsp[(1) - (2)].interm).line), (yyvsp[(1) - (2)].interm).line); + prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(variable.getUniqueId(), variable.getName(), variable.getType(), (yylsp[(1) - (2)])), (yylsp[(1) - (2)])); } else { - prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(0, "", *param.type, (yyvsp[(1) - (2)].interm).line), (yyvsp[(1) - (2)].interm).line); + prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(0, "", *param.type, (yylsp[(1) - (2)])), (yylsp[(1) - (2)])); } } @@ -3076,7 +3163,7 @@ yyreduce: } break; - case 72: + case 73: { if ((yyvsp[(1) - (2)].interm).intermAggregate) @@ -3085,22 +3172,22 @@ yyreduce: } break; - case 73: + case 74: { if (((yyvsp[(2) - (4)].interm.precision) == EbpHigh) && (context->shaderType == SH_FRAGMENT_SHADER) && !context->fragmentPrecisionHigh) { - context->error((yyvsp[(1) - (4)].lex).line, "precision is not supported in fragment shader", "highp"); + context->error((yylsp[(1) - (4)]), "precision is not supported in fragment shader", "highp"); context->recover(); } if (!context->symbolTable.setDefaultPrecision( (yyvsp[(3) - (4)].interm.type), (yyvsp[(2) - (4)].interm.precision) )) { - context->error((yyvsp[(1) - (4)].lex).line, "illegal type argument for default precision qualifier", getBasicString((yyvsp[(3) - (4)].interm.type).type)); + context->error((yylsp[(1) - (4)]), "illegal type argument for default precision qualifier", getBasicString((yyvsp[(3) - (4)].interm.type).type)); context->recover(); } (yyval.interm.intermNode) = 0; } break; - case 74: + case 75: { // @@ -3114,24 +3201,41 @@ yyreduce: TFunction* prevDec = static_cast(context->symbolTable.find((yyvsp[(1) - (2)].interm.function)->getMangledName())); if (prevDec) { if (prevDec->getReturnType() != (yyvsp[(1) - (2)].interm.function)->getReturnType()) { - context->error((yyvsp[(2) - (2)].lex).line, "overloaded functions must have the same return type", (yyvsp[(1) - (2)].interm.function)->getReturnType().getBasicString()); + context->error((yylsp[(2) - (2)]), "overloaded functions must have the same return type", (yyvsp[(1) - (2)].interm.function)->getReturnType().getBasicString()); context->recover(); } for (size_t i = 0; i < prevDec->getParamCount(); ++i) { if (prevDec->getParam(i).type->getQualifier() != (yyvsp[(1) - (2)].interm.function)->getParam(i).type->getQualifier()) { - context->error((yyvsp[(2) - (2)].lex).line, "overloaded functions must have the same parameter qualifiers", (yyvsp[(1) - (2)].interm.function)->getParam(i).type->getQualifierString()); + context->error((yylsp[(2) - (2)]), "overloaded functions must have the same parameter qualifiers", (yyvsp[(1) - (2)].interm.function)->getParam(i).type->getQualifierString()); context->recover(); } } } + // + // Check for previously declared variables using the same name. + // + TSymbol *prevSym = context->symbolTable.find((yyvsp[(1) - (2)].interm.function)->getName()); + if (prevSym) + { + if (!prevSym->isFunction()) + { + context->error((yylsp[(2) - (2)]), "redefinition", (yyvsp[(1) - (2)].interm.function)->getName().c_str(), "function"); + context->recover(); + } + } + else + { + // Insert the unmangled name to detect potential future redefinition as a variable. + context->symbolTable.getOuterLevel()->insert((yyvsp[(1) - (2)].interm.function)->getName(), *(yyvsp[(1) - (2)].interm.function)); + } + // // If this is a redeclaration, it could also be a definition, // in which case, we want to use the variable names from this one, and not the one that's // being redeclared. So, pass back up this declaration, not the one in the symbol table. // (yyval.interm).function = (yyvsp[(1) - (2)].interm.function); - (yyval.interm).line = (yyvsp[(2) - (2)].lex).line; // We're at the inner scope level of the function's arguments and body statement. // Add the function prototype to the surrounding scope instead. @@ -3139,13 +3243,6 @@ yyreduce: } break; - case 75: - - { - (yyval.interm.function) = (yyvsp[(1) - (1)].interm.function); - } - break; - case 76: { @@ -3155,6 +3252,13 @@ yyreduce: case 77: + { + (yyval.interm.function) = (yyvsp[(1) - (1)].interm.function); + } + break; + + case 78: + { // Add the parameter (yyval.interm.function) = (yyvsp[(1) - (2)].interm.function); @@ -3165,7 +3269,7 @@ yyreduce: } break; - case 78: + case 79: { // @@ -3176,7 +3280,7 @@ yyreduce: // // This parameter > first is void // - context->error((yyvsp[(2) - (3)].lex).line, "cannot be an argument type except for '(void)'", "void"); + context->error((yylsp[(2) - (3)]), "cannot be an argument type except for '(void)'", "void"); context->recover(); delete (yyvsp[(3) - (3)].interm).param.type; } else { @@ -3187,15 +3291,15 @@ yyreduce: } break; - case 79: + case 80: { if ((yyvsp[(1) - (3)].interm.type).qualifier != EvqGlobal && (yyvsp[(1) - (3)].interm.type).qualifier != EvqTemporary) { - context->error((yyvsp[(2) - (3)].lex).line, "no qualifiers allowed for function return", getQualifierString((yyvsp[(1) - (3)].interm.type).qualifier)); + context->error((yylsp[(2) - (3)]), "no qualifiers allowed for function return", getQualifierString((yyvsp[(1) - (3)].interm.type).qualifier)); context->recover(); } // make sure a sampler is not involved as well... - if (context->structQualifierErrorCheck((yyvsp[(2) - (3)].lex).line, (yyvsp[(1) - (3)].interm.type))) + if (context->structQualifierErrorCheck((yylsp[(2) - (3)]), (yyvsp[(1) - (3)].interm.type))) context->recover(); // Add the function as a prototype after parsing it (we do not support recursion) @@ -3208,39 +3312,16 @@ yyreduce: } break; - case 80: - - { - if ((yyvsp[(1) - (2)].interm.type).type == EbtVoid) { - context->error((yyvsp[(2) - (2)].lex).line, "illegal use of type 'void'", (yyvsp[(2) - (2)].lex).string->c_str()); - context->recover(); - } - if (context->reservedErrorCheck((yyvsp[(2) - (2)].lex).line, *(yyvsp[(2) - (2)].lex).string)) - context->recover(); - TParameter param = {(yyvsp[(2) - (2)].lex).string, new TType((yyvsp[(1) - (2)].interm.type))}; - (yyval.interm).line = (yyvsp[(2) - (2)].lex).line; - (yyval.interm).param = param; - } - break; - case 81: { - // Check that we can make an array out of this type - if (context->arrayTypeErrorCheck((yyvsp[(3) - (5)].lex).line, (yyvsp[(1) - (5)].interm.type))) + if ((yyvsp[(1) - (2)].interm.type).type == EbtVoid) { + context->error((yylsp[(2) - (2)]), "illegal use of type 'void'", (yyvsp[(2) - (2)].lex).string->c_str()); context->recover(); - - if (context->reservedErrorCheck((yyvsp[(2) - (5)].lex).line, *(yyvsp[(2) - (5)].lex).string)) + } + if (context->reservedErrorCheck((yylsp[(2) - (2)]), *(yyvsp[(2) - (2)].lex).string)) context->recover(); - - int size; - if (context->arraySizeErrorCheck((yyvsp[(3) - (5)].lex).line, (yyvsp[(4) - (5)].interm.intermTypedNode), size)) - context->recover(); - (yyvsp[(1) - (5)].interm.type).setArray(true, size); - - TType* type = new TType((yyvsp[(1) - (5)].interm.type)); - TParameter param = { (yyvsp[(2) - (5)].lex).string, type }; - (yyval.interm).line = (yyvsp[(2) - (5)].lex).line; + TParameter param = {(yyvsp[(2) - (2)].lex).string, new TType((yyvsp[(1) - (2)].interm.type))}; (yyval.interm).param = param; } break; @@ -3248,19 +3329,29 @@ yyreduce: case 82: { - (yyval.interm) = (yyvsp[(3) - (3)].interm); - if (context->paramErrorCheck((yyvsp[(3) - (3)].interm).line, (yyvsp[(1) - (3)].interm.type).qualifier, (yyvsp[(2) - (3)].interm.qualifier), (yyval.interm).param.type)) + // Check that we can make an array out of this type + if (context->arrayTypeErrorCheck((yylsp[(3) - (5)]), (yyvsp[(1) - (5)].interm.type))) context->recover(); + + if (context->reservedErrorCheck((yylsp[(2) - (5)]), *(yyvsp[(2) - (5)].lex).string)) + context->recover(); + + int size; + if (context->arraySizeErrorCheck((yylsp[(3) - (5)]), (yyvsp[(4) - (5)].interm.intermTypedNode), size)) + context->recover(); + (yyvsp[(1) - (5)].interm.type).setArray(true, size); + + TType* type = new TType((yyvsp[(1) - (5)].interm.type)); + TParameter param = { (yyvsp[(2) - (5)].lex).string, type }; + (yyval.interm).param = param; } break; case 83: { - (yyval.interm) = (yyvsp[(2) - (2)].interm); - if (context->parameterSamplerErrorCheck((yyvsp[(2) - (2)].interm).line, (yyvsp[(1) - (2)].interm.qualifier), *(yyvsp[(2) - (2)].interm).param.type)) - context->recover(); - if (context->paramErrorCheck((yyvsp[(2) - (2)].interm).line, EvqTemporary, (yyvsp[(1) - (2)].interm.qualifier), (yyval.interm).param.type)) + (yyval.interm) = (yyvsp[(3) - (3)].interm); + if (context->paramErrorCheck((yylsp[(3) - (3)]), (yyvsp[(1) - (3)].interm.type).qualifier, (yyvsp[(2) - (3)].interm.qualifier), (yyval.interm).param.type)) context->recover(); } break; @@ -3268,8 +3359,10 @@ yyreduce: case 84: { - (yyval.interm) = (yyvsp[(3) - (3)].interm); - if (context->paramErrorCheck((yyvsp[(3) - (3)].interm).line, (yyvsp[(1) - (3)].interm.type).qualifier, (yyvsp[(2) - (3)].interm.qualifier), (yyval.interm).param.type)) + (yyval.interm) = (yyvsp[(2) - (2)].interm); + if (context->parameterSamplerErrorCheck((yylsp[(2) - (2)]), (yyvsp[(1) - (2)].interm.qualifier), *(yyvsp[(2) - (2)].interm).param.type)) + context->recover(); + if (context->paramErrorCheck((yylsp[(2) - (2)]), EvqTemporary, (yyvsp[(1) - (2)].interm.qualifier), (yyval.interm).param.type)) context->recover(); } break; @@ -3277,10 +3370,8 @@ yyreduce: case 85: { - (yyval.interm) = (yyvsp[(2) - (2)].interm); - if (context->parameterSamplerErrorCheck((yyvsp[(2) - (2)].interm).line, (yyvsp[(1) - (2)].interm.qualifier), *(yyvsp[(2) - (2)].interm).param.type)) - context->recover(); - if (context->paramErrorCheck((yyvsp[(2) - (2)].interm).line, EvqTemporary, (yyvsp[(1) - (2)].interm.qualifier), (yyval.interm).param.type)) + (yyval.interm) = (yyvsp[(3) - (3)].interm); + if (context->paramErrorCheck((yylsp[(3) - (3)]), (yyvsp[(1) - (3)].interm.type).qualifier, (yyvsp[(2) - (3)].interm.qualifier), (yyval.interm).param.type)) context->recover(); } break; @@ -3288,7 +3379,11 @@ yyreduce: case 86: { - (yyval.interm.qualifier) = EvqIn; + (yyval.interm) = (yyvsp[(2) - (2)].interm); + if (context->parameterSamplerErrorCheck((yylsp[(2) - (2)]), (yyvsp[(1) - (2)].interm.qualifier), *(yyvsp[(2) - (2)].interm).param.type)) + context->recover(); + if (context->paramErrorCheck((yylsp[(2) - (2)]), EvqTemporary, (yyvsp[(1) - (2)].interm.qualifier), (yyval.interm).param.type)) + context->recover(); } break; @@ -3302,123 +3397,130 @@ yyreduce: case 88: { - (yyval.interm.qualifier) = EvqOut; + (yyval.interm.qualifier) = EvqIn; } break; case 89: { - (yyval.interm.qualifier) = EvqInOut; + (yyval.interm.qualifier) = EvqOut; } break; case 90: + { + (yyval.interm.qualifier) = EvqInOut; + } + break; + + case 91: + { TParameter param = { 0, new TType((yyvsp[(1) - (1)].interm.type)) }; (yyval.interm).param = param; } break; - case 91: + case 92: { (yyval.interm) = (yyvsp[(1) - (1)].interm); } break; - case 92: + case 93: { if ((yyvsp[(1) - (3)].interm).type.type == EbtInvariant && !(yyvsp[(3) - (3)].lex).symbol) { - context->error((yyvsp[(3) - (3)].lex).line, "undeclared identifier declared as invariant", (yyvsp[(3) - (3)].lex).string->c_str()); + context->error((yylsp[(3) - (3)]), "undeclared identifier declared as invariant", (yyvsp[(3) - (3)].lex).string->c_str()); context->recover(); } - TIntermSymbol* symbol = context->intermediate.addSymbol(0, *(yyvsp[(3) - (3)].lex).string, TType((yyvsp[(1) - (3)].interm).type), (yyvsp[(3) - (3)].lex).line); - (yyval.interm).intermAggregate = context->intermediate.growAggregate((yyvsp[(1) - (3)].interm).intermNode, symbol, (yyvsp[(3) - (3)].lex).line); + TIntermSymbol* symbol = context->intermediate.addSymbol(0, *(yyvsp[(3) - (3)].lex).string, TType((yyvsp[(1) - (3)].interm).type), (yylsp[(3) - (3)])); + (yyval.interm).intermAggregate = context->intermediate.growAggregate((yyvsp[(1) - (3)].interm).intermNode, symbol, (yylsp[(3) - (3)])); - if (context->structQualifierErrorCheck((yyvsp[(3) - (3)].lex).line, (yyval.interm).type)) + if (context->structQualifierErrorCheck((yylsp[(3) - (3)]), (yyval.interm).type)) context->recover(); - if (context->nonInitConstErrorCheck((yyvsp[(3) - (3)].lex).line, *(yyvsp[(3) - (3)].lex).string, (yyval.interm).type, false)) + if (context->nonInitConstErrorCheck((yylsp[(3) - (3)]), *(yyvsp[(3) - (3)].lex).string, (yyval.interm).type, false)) context->recover(); TVariable* variable = 0; - if (context->nonInitErrorCheck((yyvsp[(3) - (3)].lex).line, *(yyvsp[(3) - (3)].lex).string, (yyval.interm).type, variable)) + if (context->nonInitErrorCheck((yylsp[(3) - (3)]), *(yyvsp[(3) - (3)].lex).string, (yyval.interm).type, variable)) context->recover(); if (symbol && variable) symbol->setId(variable->getUniqueId()); } break; - case 93: + case 94: { - if (context->structQualifierErrorCheck((yyvsp[(3) - (5)].lex).line, (yyvsp[(1) - (5)].interm).type)) + if (context->structQualifierErrorCheck((yylsp[(3) - (5)]), (yyvsp[(1) - (5)].interm).type)) context->recover(); - if (context->nonInitConstErrorCheck((yyvsp[(3) - (5)].lex).line, *(yyvsp[(3) - (5)].lex).string, (yyvsp[(1) - (5)].interm).type, true)) + if (context->nonInitConstErrorCheck((yylsp[(3) - (5)]), *(yyvsp[(3) - (5)].lex).string, (yyvsp[(1) - (5)].interm).type, true)) context->recover(); (yyval.interm) = (yyvsp[(1) - (5)].interm); - if (context->arrayTypeErrorCheck((yyvsp[(4) - (5)].lex).line, (yyvsp[(1) - (5)].interm).type) || context->arrayQualifierErrorCheck((yyvsp[(4) - (5)].lex).line, (yyvsp[(1) - (5)].interm).type)) + if (context->arrayTypeErrorCheck((yylsp[(4) - (5)]), (yyvsp[(1) - (5)].interm).type) || context->arrayQualifierErrorCheck((yylsp[(4) - (5)]), (yyvsp[(1) - (5)].interm).type)) context->recover(); else { (yyvsp[(1) - (5)].interm).type.setArray(true); TVariable* variable; - if (context->arrayErrorCheck((yyvsp[(4) - (5)].lex).line, *(yyvsp[(3) - (5)].lex).string, (yyvsp[(1) - (5)].interm).type, variable)) + if (context->arrayErrorCheck((yylsp[(4) - (5)]), *(yyvsp[(3) - (5)].lex).string, (yyvsp[(1) - (5)].interm).type, variable)) context->recover(); } } break; - case 94: - - { - if (context->structQualifierErrorCheck((yyvsp[(3) - (6)].lex).line, (yyvsp[(1) - (6)].interm).type)) - context->recover(); - - if (context->nonInitConstErrorCheck((yyvsp[(3) - (6)].lex).line, *(yyvsp[(3) - (6)].lex).string, (yyvsp[(1) - (6)].interm).type, true)) - context->recover(); - - (yyval.interm) = (yyvsp[(1) - (6)].interm); - - if (context->arrayTypeErrorCheck((yyvsp[(4) - (6)].lex).line, (yyvsp[(1) - (6)].interm).type) || context->arrayQualifierErrorCheck((yyvsp[(4) - (6)].lex).line, (yyvsp[(1) - (6)].interm).type)) - context->recover(); - else { - int size; - if (context->arraySizeErrorCheck((yyvsp[(4) - (6)].lex).line, (yyvsp[(5) - (6)].interm.intermTypedNode), size)) - context->recover(); - (yyvsp[(1) - (6)].interm).type.setArray(true, size); - TVariable* variable = 0; - if (context->arrayErrorCheck((yyvsp[(4) - (6)].lex).line, *(yyvsp[(3) - (6)].lex).string, (yyvsp[(1) - (6)].interm).type, variable)) - context->recover(); - TType type = TType((yyvsp[(1) - (6)].interm).type); - type.setArraySize(size); - (yyval.interm).intermAggregate = context->intermediate.growAggregate((yyvsp[(1) - (6)].interm).intermNode, context->intermediate.addSymbol(variable ? variable->getUniqueId() : 0, *(yyvsp[(3) - (6)].lex).string, type, (yyvsp[(3) - (6)].lex).line), (yyvsp[(3) - (6)].lex).line); - } - } - break; - case 95: { - if (context->structQualifierErrorCheck((yyvsp[(3) - (5)].lex).line, (yyvsp[(1) - (5)].interm).type)) + if (context->structQualifierErrorCheck((yylsp[(3) - (6)]), (yyvsp[(1) - (6)].interm).type)) + context->recover(); + + if (context->nonInitConstErrorCheck((yylsp[(3) - (6)]), *(yyvsp[(3) - (6)].lex).string, (yyvsp[(1) - (6)].interm).type, true)) + context->recover(); + + (yyval.interm) = (yyvsp[(1) - (6)].interm); + + if (context->arrayTypeErrorCheck((yylsp[(4) - (6)]), (yyvsp[(1) - (6)].interm).type) || context->arrayQualifierErrorCheck((yylsp[(4) - (6)]), (yyvsp[(1) - (6)].interm).type)) + context->recover(); + else { + int size; + if (context->arraySizeErrorCheck((yylsp[(4) - (6)]), (yyvsp[(5) - (6)].interm.intermTypedNode), size)) + context->recover(); + (yyvsp[(1) - (6)].interm).type.setArray(true, size); + TVariable* variable = 0; + if (context->arrayErrorCheck((yylsp[(4) - (6)]), *(yyvsp[(3) - (6)].lex).string, (yyvsp[(1) - (6)].interm).type, variable)) + context->recover(); + TType type = TType((yyvsp[(1) - (6)].interm).type); + type.setArraySize(size); + (yyval.interm).intermAggregate = context->intermediate.growAggregate((yyvsp[(1) - (6)].interm).intermNode, context->intermediate.addSymbol(variable ? variable->getUniqueId() : 0, *(yyvsp[(3) - (6)].lex).string, type, (yylsp[(3) - (6)])), (yylsp[(3) - (6)])); + } + } + break; + + case 96: + + { + if (context->structQualifierErrorCheck((yylsp[(3) - (5)]), (yyvsp[(1) - (5)].interm).type)) context->recover(); (yyval.interm) = (yyvsp[(1) - (5)].interm); TIntermNode* intermNode; - if (!context->executeInitializer((yyvsp[(3) - (5)].lex).line, *(yyvsp[(3) - (5)].lex).string, (yyvsp[(1) - (5)].interm).type, (yyvsp[(5) - (5)].interm.intermTypedNode), intermNode)) { + if (!context->executeInitializer((yylsp[(3) - (5)]), *(yyvsp[(3) - (5)].lex).string, (yyvsp[(1) - (5)].interm).type, (yyvsp[(5) - (5)].interm.intermTypedNode), intermNode)) { // // build the intermediate representation // if (intermNode) - (yyval.interm).intermAggregate = context->intermediate.growAggregate((yyvsp[(1) - (5)].interm).intermNode, intermNode, (yyvsp[(4) - (5)].lex).line); + (yyval.interm).intermAggregate = context->intermediate.growAggregate((yyvsp[(1) - (5)].interm).intermNode, intermNode, (yylsp[(4) - (5)])); else (yyval.interm).intermAggregate = (yyvsp[(1) - (5)].interm).intermAggregate; } else { @@ -3428,77 +3530,77 @@ yyreduce: } break; - case 96: - - { - (yyval.interm).type = (yyvsp[(1) - (1)].interm.type); - (yyval.interm).intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, "", TType((yyvsp[(1) - (1)].interm.type)), (yyvsp[(1) - (1)].interm.type).line), (yyvsp[(1) - (1)].interm.type).line); - } - break; - case 97: { - TIntermSymbol* symbol = context->intermediate.addSymbol(0, *(yyvsp[(2) - (2)].lex).string, TType((yyvsp[(1) - (2)].interm.type)), (yyvsp[(2) - (2)].lex).line); - (yyval.interm).intermAggregate = context->intermediate.makeAggregate(symbol, (yyvsp[(2) - (2)].lex).line); - - if (context->structQualifierErrorCheck((yyvsp[(2) - (2)].lex).line, (yyval.interm).type)) - context->recover(); - - if (context->nonInitConstErrorCheck((yyvsp[(2) - (2)].lex).line, *(yyvsp[(2) - (2)].lex).string, (yyval.interm).type, false)) - context->recover(); - - (yyval.interm).type = (yyvsp[(1) - (2)].interm.type); - - TVariable* variable = 0; - if (context->nonInitErrorCheck((yyvsp[(2) - (2)].lex).line, *(yyvsp[(2) - (2)].lex).string, (yyval.interm).type, variable)) - context->recover(); - if (variable && symbol) - symbol->setId(variable->getUniqueId()); + (yyval.interm).type = (yyvsp[(1) - (1)].interm.type); + (yyval.interm).intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, "", TType((yyvsp[(1) - (1)].interm.type)), (yylsp[(1) - (1)])), (yylsp[(1) - (1)])); } break; case 98: { - context->error((yyvsp[(2) - (4)].lex).line, "unsized array declarations not supported", (yyvsp[(2) - (4)].lex).string->c_str()); - context->recover(); + TIntermSymbol* symbol = context->intermediate.addSymbol(0, *(yyvsp[(2) - (2)].lex).string, TType((yyvsp[(1) - (2)].interm.type)), (yylsp[(2) - (2)])); + (yyval.interm).intermAggregate = context->intermediate.makeAggregate(symbol, (yylsp[(2) - (2)])); + + if (context->structQualifierErrorCheck((yylsp[(2) - (2)]), (yyval.interm).type)) + context->recover(); - TIntermSymbol* symbol = context->intermediate.addSymbol(0, *(yyvsp[(2) - (4)].lex).string, TType((yyvsp[(1) - (4)].interm.type)), (yyvsp[(2) - (4)].lex).line); - (yyval.interm).intermAggregate = context->intermediate.makeAggregate(symbol, (yyvsp[(2) - (4)].lex).line); - (yyval.interm).type = (yyvsp[(1) - (4)].interm.type); + if (context->nonInitConstErrorCheck((yylsp[(2) - (2)]), *(yyvsp[(2) - (2)].lex).string, (yyval.interm).type, false)) + context->recover(); + + (yyval.interm).type = (yyvsp[(1) - (2)].interm.type); + + TVariable* variable = 0; + if (context->nonInitErrorCheck((yylsp[(2) - (2)]), *(yyvsp[(2) - (2)].lex).string, (yyval.interm).type, variable)) + context->recover(); + if (variable && symbol) + symbol->setId(variable->getUniqueId()); } break; case 99: + { + context->error((yylsp[(2) - (4)]), "unsized array declarations not supported", (yyvsp[(2) - (4)].lex).string->c_str()); + context->recover(); + + TIntermSymbol* symbol = context->intermediate.addSymbol(0, *(yyvsp[(2) - (4)].lex).string, TType((yyvsp[(1) - (4)].interm.type)), (yylsp[(2) - (4)])); + (yyval.interm).intermAggregate = context->intermediate.makeAggregate(symbol, (yylsp[(2) - (4)])); + (yyval.interm).type = (yyvsp[(1) - (4)].interm.type); + } + break; + + case 100: + { TType type = TType((yyvsp[(1) - (5)].interm.type)); int size; - if (context->arraySizeErrorCheck((yyvsp[(2) - (5)].lex).line, (yyvsp[(4) - (5)].interm.intermTypedNode), size)) + if (context->arraySizeErrorCheck((yylsp[(2) - (5)]), (yyvsp[(4) - (5)].interm.intermTypedNode), size)) context->recover(); type.setArraySize(size); - TIntermSymbol* symbol = context->intermediate.addSymbol(0, *(yyvsp[(2) - (5)].lex).string, type, (yyvsp[(2) - (5)].lex).line); - (yyval.interm).intermAggregate = context->intermediate.makeAggregate(symbol, (yyvsp[(2) - (5)].lex).line); + TIntermSymbol* symbol = context->intermediate.addSymbol(0, *(yyvsp[(2) - (5)].lex).string, type, (yylsp[(2) - (5)])); + (yyval.interm).intermAggregate = context->intermediate.makeAggregate(symbol, (yylsp[(2) - (5)])); - if (context->structQualifierErrorCheck((yyvsp[(2) - (5)].lex).line, (yyvsp[(1) - (5)].interm.type))) + if (context->structQualifierErrorCheck((yylsp[(2) - (5)]), (yyvsp[(1) - (5)].interm.type))) context->recover(); - if (context->nonInitConstErrorCheck((yyvsp[(2) - (5)].lex).line, *(yyvsp[(2) - (5)].lex).string, (yyvsp[(1) - (5)].interm.type), true)) + if (context->nonInitConstErrorCheck((yylsp[(2) - (5)]), *(yyvsp[(2) - (5)].lex).string, (yyvsp[(1) - (5)].interm.type), true)) context->recover(); (yyval.interm).type = (yyvsp[(1) - (5)].interm.type); - if (context->arrayTypeErrorCheck((yyvsp[(3) - (5)].lex).line, (yyvsp[(1) - (5)].interm.type)) || context->arrayQualifierErrorCheck((yyvsp[(3) - (5)].lex).line, (yyvsp[(1) - (5)].interm.type))) + if (context->arrayTypeErrorCheck((yylsp[(3) - (5)]), (yyvsp[(1) - (5)].interm.type)) || context->arrayQualifierErrorCheck((yylsp[(3) - (5)]), (yyvsp[(1) - (5)].interm.type))) context->recover(); else { int size; - if (context->arraySizeErrorCheck((yyvsp[(3) - (5)].lex).line, (yyvsp[(4) - (5)].interm.intermTypedNode), size)) + if (context->arraySizeErrorCheck((yylsp[(3) - (5)]), (yyvsp[(4) - (5)].interm.intermTypedNode), size)) context->recover(); (yyvsp[(1) - (5)].interm.type).setArray(true, size); TVariable* variable = 0; - if (context->arrayErrorCheck((yyvsp[(3) - (5)].lex).line, *(yyvsp[(2) - (5)].lex).string, (yyvsp[(1) - (5)].interm.type), variable)) + if (context->arrayErrorCheck((yylsp[(3) - (5)]), *(yyvsp[(2) - (5)].lex).string, (yyvsp[(1) - (5)].interm.type), variable)) context->recover(); if (variable && symbol) symbol->setId(variable->getUniqueId()); @@ -3506,21 +3608,21 @@ yyreduce: } break; - case 100: + case 101: { - if (context->structQualifierErrorCheck((yyvsp[(2) - (4)].lex).line, (yyvsp[(1) - (4)].interm.type))) + if (context->structQualifierErrorCheck((yylsp[(2) - (4)]), (yyvsp[(1) - (4)].interm.type))) context->recover(); (yyval.interm).type = (yyvsp[(1) - (4)].interm.type); TIntermNode* intermNode; - if (!context->executeInitializer((yyvsp[(2) - (4)].lex).line, *(yyvsp[(2) - (4)].lex).string, (yyvsp[(1) - (4)].interm.type), (yyvsp[(4) - (4)].interm.intermTypedNode), intermNode)) { + if (!context->executeInitializer((yylsp[(2) - (4)]), *(yyvsp[(2) - (4)].lex).string, (yyvsp[(1) - (4)].interm.type), (yyvsp[(4) - (4)].interm.intermTypedNode), intermNode)) { // // Build intermediate representation // if(intermNode) - (yyval.interm).intermAggregate = context->intermediate.makeAggregate(intermNode, (yyvsp[(3) - (4)].lex).line); + (yyval.interm).intermAggregate = context->intermediate.makeAggregate(intermNode, (yylsp[(3) - (4)])); else (yyval.interm).intermAggregate = 0; } else { @@ -3530,58 +3632,58 @@ yyreduce: } break; - case 101: + case 102: { - VERTEX_ONLY("invariant declaration", (yyvsp[(1) - (2)].lex).line); - if (context->globalErrorCheck((yyvsp[(1) - (2)].lex).line, context->symbolTable.atGlobalLevel(), "invariant varying")) + VERTEX_ONLY("invariant declaration", (yylsp[(1) - (2)])); + if (context->globalErrorCheck((yylsp[(1) - (2)]), context->symbolTable.atGlobalLevel(), "invariant varying")) context->recover(); - (yyval.interm).type.setBasic(EbtInvariant, EvqInvariantVaryingOut, (yyvsp[(2) - (2)].lex).line); + (yyval.interm).type.setBasic(EbtInvariant, EvqInvariantVaryingOut, (yylsp[(2) - (2)])); if (!(yyvsp[(2) - (2)].lex).symbol) { - context->error((yyvsp[(2) - (2)].lex).line, "undeclared identifier declared as invariant", (yyvsp[(2) - (2)].lex).string->c_str()); + context->error((yylsp[(2) - (2)]), "undeclared identifier declared as invariant", (yyvsp[(2) - (2)].lex).string->c_str()); context->recover(); (yyval.interm).intermAggregate = 0; } else { - TIntermSymbol *symbol = context->intermediate.addSymbol(0, *(yyvsp[(2) - (2)].lex).string, TType((yyval.interm).type), (yyvsp[(2) - (2)].lex).line); - (yyval.interm).intermAggregate = context->intermediate.makeAggregate(symbol, (yyvsp[(2) - (2)].lex).line); - } - } - break; - - case 102: - - { - (yyval.interm.type) = (yyvsp[(1) - (1)].interm.type); - - if ((yyvsp[(1) - (1)].interm.type).array) { - context->error((yyvsp[(1) - (1)].interm.type).line, "not supported", "first-class array"); - context->recover(); - (yyvsp[(1) - (1)].interm.type).setArray(false); + TIntermSymbol *symbol = context->intermediate.addSymbol(0, *(yyvsp[(2) - (2)].lex).string, TType((yyval.interm).type), (yylsp[(2) - (2)])); + (yyval.interm).intermAggregate = context->intermediate.makeAggregate(symbol, (yylsp[(2) - (2)])); } } break; case 103: + { + (yyval.interm.type) = (yyvsp[(1) - (1)].interm.type); + + if ((yyvsp[(1) - (1)].interm.type).array) { + context->error((yylsp[(1) - (1)]), "not supported", "first-class array"); + context->recover(); + (yyvsp[(1) - (1)].interm.type).setArray(false); + } + } + break; + + case 104: + { if ((yyvsp[(2) - (2)].interm.type).array) { - context->error((yyvsp[(2) - (2)].interm.type).line, "not supported", "first-class array"); + context->error((yylsp[(2) - (2)]), "not supported", "first-class array"); context->recover(); (yyvsp[(2) - (2)].interm.type).setArray(false); } if ((yyvsp[(1) - (2)].interm.type).qualifier == EvqAttribute && ((yyvsp[(2) - (2)].interm.type).type == EbtBool || (yyvsp[(2) - (2)].interm.type).type == EbtInt)) { - context->error((yyvsp[(2) - (2)].interm.type).line, "cannot be bool or int", getQualifierString((yyvsp[(1) - (2)].interm.type).qualifier)); + context->error((yylsp[(2) - (2)]), "cannot be bool or int", getQualifierString((yyvsp[(1) - (2)].interm.type).qualifier)); context->recover(); } if (((yyvsp[(1) - (2)].interm.type).qualifier == EvqVaryingIn || (yyvsp[(1) - (2)].interm.type).qualifier == EvqVaryingOut) && ((yyvsp[(2) - (2)].interm.type).type == EbtBool || (yyvsp[(2) - (2)].interm.type).type == EbtInt)) { - context->error((yyvsp[(2) - (2)].interm.type).line, "cannot be bool or int", getQualifierString((yyvsp[(1) - (2)].interm.type).qualifier)); + context->error((yylsp[(2) - (2)]), "cannot be bool or int", getQualifierString((yyvsp[(1) - (2)].interm.type).qualifier)); context->recover(); } (yyval.interm.type) = (yyvsp[(2) - (2)].interm.type); @@ -3589,71 +3691,71 @@ yyreduce: } break; - case 104: - - { - (yyval.interm.type).setBasic(EbtVoid, EvqConst, (yyvsp[(1) - (1)].lex).line); - } - break; - case 105: { - VERTEX_ONLY("attribute", (yyvsp[(1) - (1)].lex).line); - if (context->globalErrorCheck((yyvsp[(1) - (1)].lex).line, context->symbolTable.atGlobalLevel(), "attribute")) - context->recover(); - (yyval.interm.type).setBasic(EbtVoid, EvqAttribute, (yyvsp[(1) - (1)].lex).line); + (yyval.interm.type).setBasic(EbtVoid, EvqConst, (yylsp[(1) - (1)])); } break; case 106: { - if (context->globalErrorCheck((yyvsp[(1) - (1)].lex).line, context->symbolTable.atGlobalLevel(), "varying")) + VERTEX_ONLY("attribute", (yylsp[(1) - (1)])); + if (context->globalErrorCheck((yylsp[(1) - (1)]), context->symbolTable.atGlobalLevel(), "attribute")) context->recover(); - if (context->shaderType == SH_VERTEX_SHADER) - (yyval.interm.type).setBasic(EbtVoid, EvqVaryingOut, (yyvsp[(1) - (1)].lex).line); - else - (yyval.interm.type).setBasic(EbtVoid, EvqVaryingIn, (yyvsp[(1) - (1)].lex).line); + (yyval.interm.type).setBasic(EbtVoid, EvqAttribute, (yylsp[(1) - (1)])); } break; case 107: { - if (context->globalErrorCheck((yyvsp[(1) - (2)].lex).line, context->symbolTable.atGlobalLevel(), "invariant varying")) + if (context->globalErrorCheck((yylsp[(1) - (1)]), context->symbolTable.atGlobalLevel(), "varying")) context->recover(); if (context->shaderType == SH_VERTEX_SHADER) - (yyval.interm.type).setBasic(EbtVoid, EvqInvariantVaryingOut, (yyvsp[(1) - (2)].lex).line); + (yyval.interm.type).setBasic(EbtVoid, EvqVaryingOut, (yylsp[(1) - (1)])); else - (yyval.interm.type).setBasic(EbtVoid, EvqInvariantVaryingIn, (yyvsp[(1) - (2)].lex).line); + (yyval.interm.type).setBasic(EbtVoid, EvqVaryingIn, (yylsp[(1) - (1)])); } break; case 108: { - if (context->globalErrorCheck((yyvsp[(1) - (1)].lex).line, context->symbolTable.atGlobalLevel(), "uniform")) + if (context->globalErrorCheck((yylsp[(1) - (2)]), context->symbolTable.atGlobalLevel(), "invariant varying")) context->recover(); - (yyval.interm.type).setBasic(EbtVoid, EvqUniform, (yyvsp[(1) - (1)].lex).line); + if (context->shaderType == SH_VERTEX_SHADER) + (yyval.interm.type).setBasic(EbtVoid, EvqInvariantVaryingOut, (yylsp[(1) - (2)])); + else + (yyval.interm.type).setBasic(EbtVoid, EvqInvariantVaryingIn, (yylsp[(1) - (2)])); } break; case 109: + { + if (context->globalErrorCheck((yylsp[(1) - (1)]), context->symbolTable.atGlobalLevel(), "uniform")) + context->recover(); + (yyval.interm.type).setBasic(EbtVoid, EvqUniform, (yylsp[(1) - (1)])); + } + break; + + case 110: + { (yyval.interm.type) = (yyvsp[(1) - (1)].interm.type); if ((yyval.interm.type).precision == EbpUndefined) { (yyval.interm.type).precision = context->symbolTable.getDefaultPrecision((yyvsp[(1) - (1)].interm.type).type); - if (context->precisionErrorCheck((yyvsp[(1) - (1)].interm.type).line, (yyval.interm.type).precision, (yyvsp[(1) - (1)].interm.type).type)) { + if (context->precisionErrorCheck((yylsp[(1) - (1)]), (yyval.interm.type).precision, (yyvsp[(1) - (1)].interm.type).type)) { context->recover(); } } } break; - case 110: + case 111: { (yyval.interm.type) = (yyvsp[(2) - (2)].interm.type); @@ -3661,63 +3763,55 @@ yyreduce: } break; - case 111: + case 112: { (yyval.interm.precision) = EbpHigh; } break; - case 112: + case 113: { (yyval.interm.precision) = EbpMedium; } break; - case 113: + case 114: { (yyval.interm.precision) = EbpLow; } break; - case 114: + case 115: { (yyval.interm.type) = (yyvsp[(1) - (1)].interm.type); } break; - case 115: + case 116: { (yyval.interm.type) = (yyvsp[(1) - (4)].interm.type); - if (context->arrayTypeErrorCheck((yyvsp[(2) - (4)].lex).line, (yyvsp[(1) - (4)].interm.type))) + if (context->arrayTypeErrorCheck((yylsp[(2) - (4)]), (yyvsp[(1) - (4)].interm.type))) context->recover(); else { int size; - if (context->arraySizeErrorCheck((yyvsp[(2) - (4)].lex).line, (yyvsp[(3) - (4)].interm.intermTypedNode), size)) + if (context->arraySizeErrorCheck((yylsp[(2) - (4)]), (yyvsp[(3) - (4)].interm.intermTypedNode), size)) context->recover(); (yyval.interm.type).setArray(true, size); } } break; - case 116: - - { - TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - (yyval.interm.type).setBasic(EbtVoid, qual, (yyvsp[(1) - (1)].lex).line); - } - break; - case 117: { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - (yyval.interm.type).setBasic(EbtFloat, qual, (yyvsp[(1) - (1)].lex).line); + (yyval.interm.type).setBasic(EbtVoid, qual, (yylsp[(1) - (1)])); } break; @@ -3725,7 +3819,7 @@ yyreduce: { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - (yyval.interm.type).setBasic(EbtInt, qual, (yyvsp[(1) - (1)].lex).line); + (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[(1) - (1)])); } break; @@ -3733,7 +3827,7 @@ yyreduce: { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - (yyval.interm.type).setBasic(EbtBool, qual, (yyvsp[(1) - (1)].lex).line); + (yyval.interm.type).setBasic(EbtInt, qual, (yylsp[(1) - (1)])); } break; @@ -3741,8 +3835,7 @@ yyreduce: { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - (yyval.interm.type).setBasic(EbtFloat, qual, (yyvsp[(1) - (1)].lex).line); - (yyval.interm.type).setAggregate(2); + (yyval.interm.type).setBasic(EbtBool, qual, (yylsp[(1) - (1)])); } break; @@ -3750,8 +3843,8 @@ yyreduce: { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - (yyval.interm.type).setBasic(EbtFloat, qual, (yyvsp[(1) - (1)].lex).line); - (yyval.interm.type).setAggregate(3); + (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[(1) - (1)])); + (yyval.interm.type).setAggregate(2); } break; @@ -3759,8 +3852,8 @@ yyreduce: { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - (yyval.interm.type).setBasic(EbtFloat, qual, (yyvsp[(1) - (1)].lex).line); - (yyval.interm.type).setAggregate(4); + (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[(1) - (1)])); + (yyval.interm.type).setAggregate(3); } break; @@ -3768,8 +3861,8 @@ yyreduce: { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - (yyval.interm.type).setBasic(EbtBool, qual, (yyvsp[(1) - (1)].lex).line); - (yyval.interm.type).setAggregate(2); + (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[(1) - (1)])); + (yyval.interm.type).setAggregate(4); } break; @@ -3777,8 +3870,8 @@ yyreduce: { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - (yyval.interm.type).setBasic(EbtBool, qual, (yyvsp[(1) - (1)].lex).line); - (yyval.interm.type).setAggregate(3); + (yyval.interm.type).setBasic(EbtBool, qual, (yylsp[(1) - (1)])); + (yyval.interm.type).setAggregate(2); } break; @@ -3786,8 +3879,8 @@ yyreduce: { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - (yyval.interm.type).setBasic(EbtBool, qual, (yyvsp[(1) - (1)].lex).line); - (yyval.interm.type).setAggregate(4); + (yyval.interm.type).setBasic(EbtBool, qual, (yylsp[(1) - (1)])); + (yyval.interm.type).setAggregate(3); } break; @@ -3795,8 +3888,8 @@ yyreduce: { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - (yyval.interm.type).setBasic(EbtInt, qual, (yyvsp[(1) - (1)].lex).line); - (yyval.interm.type).setAggregate(2); + (yyval.interm.type).setBasic(EbtBool, qual, (yylsp[(1) - (1)])); + (yyval.interm.type).setAggregate(4); } break; @@ -3804,8 +3897,8 @@ yyreduce: { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - (yyval.interm.type).setBasic(EbtInt, qual, (yyvsp[(1) - (1)].lex).line); - (yyval.interm.type).setAggregate(3); + (yyval.interm.type).setBasic(EbtInt, qual, (yylsp[(1) - (1)])); + (yyval.interm.type).setAggregate(2); } break; @@ -3813,95 +3906,96 @@ yyreduce: { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - (yyval.interm.type).setBasic(EbtInt, qual, (yyvsp[(1) - (1)].lex).line); - (yyval.interm.type).setAggregate(4); + (yyval.interm.type).setBasic(EbtInt, qual, (yylsp[(1) - (1)])); + (yyval.interm.type).setAggregate(3); } break; case 129: { - FRAG_VERT_ONLY("mat2", (yyvsp[(1) - (1)].lex).line); TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - (yyval.interm.type).setBasic(EbtFloat, qual, (yyvsp[(1) - (1)].lex).line); - (yyval.interm.type).setAggregate(2, true); + (yyval.interm.type).setBasic(EbtInt, qual, (yylsp[(1) - (1)])); + (yyval.interm.type).setAggregate(4); } break; case 130: { - FRAG_VERT_ONLY("mat3", (yyvsp[(1) - (1)].lex).line); TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - (yyval.interm.type).setBasic(EbtFloat, qual, (yyvsp[(1) - (1)].lex).line); - (yyval.interm.type).setAggregate(3, true); + (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[(1) - (1)])); + (yyval.interm.type).setAggregate(2, true); } break; case 131: { - FRAG_VERT_ONLY("mat4", (yyvsp[(1) - (1)].lex).line); TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - (yyval.interm.type).setBasic(EbtFloat, qual, (yyvsp[(1) - (1)].lex).line); - (yyval.interm.type).setAggregate(4, true); + (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[(1) - (1)])); + (yyval.interm.type).setAggregate(3, true); } break; case 132: { - FRAG_VERT_ONLY("sampler2D", (yyvsp[(1) - (1)].lex).line); TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - (yyval.interm.type).setBasic(EbtSampler2D, qual, (yyvsp[(1) - (1)].lex).line); + (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[(1) - (1)])); + (yyval.interm.type).setAggregate(4, true); } break; case 133: { - FRAG_VERT_ONLY("samplerCube", (yyvsp[(1) - (1)].lex).line); TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - (yyval.interm.type).setBasic(EbtSamplerCube, qual, (yyvsp[(1) - (1)].lex).line); + (yyval.interm.type).setBasic(EbtSampler2D, qual, (yylsp[(1) - (1)])); } break; case 134: { - if (!context->supportsExtension("GL_OES_EGL_image_external")) { - context->error((yyvsp[(1) - (1)].lex).line, "unsupported type", "samplerExternalOES"); - context->recover(); - } - FRAG_VERT_ONLY("samplerExternalOES", (yyvsp[(1) - (1)].lex).line); TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - (yyval.interm.type).setBasic(EbtSamplerExternalOES, qual, (yyvsp[(1) - (1)].lex).line); + (yyval.interm.type).setBasic(EbtSamplerCube, qual, (yylsp[(1) - (1)])); } break; case 135: { - if (!context->supportsExtension("GL_ARB_texture_rectangle")) { - context->error((yyvsp[(1) - (1)].lex).line, "unsupported type", "sampler2DRect"); + if (!context->supportsExtension("GL_OES_EGL_image_external")) { + context->error((yylsp[(1) - (1)]), "unsupported type", "samplerExternalOES"); context->recover(); } - FRAG_VERT_ONLY("sampler2DRect", (yyvsp[(1) - (1)].lex).line); TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - (yyval.interm.type).setBasic(EbtSampler2DRect, qual, (yyvsp[(1) - (1)].lex).line); + (yyval.interm.type).setBasic(EbtSamplerExternalOES, qual, (yylsp[(1) - (1)])); } break; case 136: { - FRAG_VERT_ONLY("struct", (yyvsp[(1) - (1)].interm.type).line); + if (!context->supportsExtension("GL_ARB_texture_rectangle")) { + context->error((yylsp[(1) - (1)]), "unsupported type", "sampler2DRect"); + context->recover(); + } + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtSampler2DRect, qual, (yylsp[(1) - (1)])); + } + break; + + case 137: + + { (yyval.interm.type) = (yyvsp[(1) - (1)].interm.type); (yyval.interm.type).qualifier = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; } break; - case 137: + case 138: { // @@ -3910,105 +4004,69 @@ yyreduce: // TType& structure = static_cast((yyvsp[(1) - (1)].lex).symbol)->getType(); TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - (yyval.interm.type).setBasic(EbtStruct, qual, (yyvsp[(1) - (1)].lex).line); + (yyval.interm.type).setBasic(EbtStruct, qual, (yylsp[(1) - (1)])); (yyval.interm.type).userDef = &structure; } break; - case 138: - - { if (context->enterStructDeclaration((yyvsp[(2) - (3)].lex).line, *(yyvsp[(2) - (3)].lex).string)) context->recover(); } - break; - case 139: - { - if (context->reservedErrorCheck((yyvsp[(2) - (6)].lex).line, *(yyvsp[(2) - (6)].lex).string)) - context->recover(); - - TType* structure = new TType((yyvsp[(5) - (6)].interm.typeList), *(yyvsp[(2) - (6)].lex).string); - TVariable* userTypeDef = new TVariable((yyvsp[(2) - (6)].lex).string, *structure, true); - if (! context->symbolTable.insert(*userTypeDef)) { - context->error((yyvsp[(2) - (6)].lex).line, "redefinition", (yyvsp[(2) - (6)].lex).string->c_str(), "struct"); - context->recover(); - } - (yyval.interm.type).setBasic(EbtStruct, EvqTemporary, (yyvsp[(1) - (6)].lex).line); - (yyval.interm.type).userDef = structure; - context->exitStructDeclaration(); - } + { if (context->enterStructDeclaration((yylsp[(2) - (3)]), *(yyvsp[(2) - (3)].lex).string)) context->recover(); } break; case 140: - { if (context->enterStructDeclaration((yyvsp[(2) - (2)].lex).line, *(yyvsp[(2) - (2)].lex).string)) context->recover(); } + { + if (context->reservedErrorCheck((yylsp[(2) - (6)]), *(yyvsp[(2) - (6)].lex).string)) + context->recover(); + + TType* structure = new TType(new TStructure((yyvsp[(2) - (6)].lex).string, (yyvsp[(5) - (6)].interm.fieldList))); + TVariable* userTypeDef = new TVariable((yyvsp[(2) - (6)].lex).string, *structure, true); + if (! context->symbolTable.insert(*userTypeDef)) { + context->error((yylsp[(2) - (6)]), "redefinition", (yyvsp[(2) - (6)].lex).string->c_str(), "struct"); + context->recover(); + } + (yyval.interm.type).setBasic(EbtStruct, EvqTemporary, (yylsp[(1) - (6)])); + (yyval.interm.type).userDef = structure; + context->exitStructDeclaration(); + } break; case 141: - { - TType* structure = new TType((yyvsp[(4) - (5)].interm.typeList), TString("")); - (yyval.interm.type).setBasic(EbtStruct, EvqTemporary, (yyvsp[(1) - (5)].lex).line); - (yyval.interm.type).userDef = structure; - context->exitStructDeclaration(); - } + { if (context->enterStructDeclaration((yylsp[(2) - (2)]), *(yyvsp[(2) - (2)].lex).string)) context->recover(); } break; case 142: { - (yyval.interm.typeList) = (yyvsp[(1) - (1)].interm.typeList); + TType* structure = new TType(new TStructure(NewPoolTString(""), (yyvsp[(4) - (5)].interm.fieldList))); + (yyval.interm.type).setBasic(EbtStruct, EvqTemporary, (yylsp[(1) - (5)])); + (yyval.interm.type).userDef = structure; + context->exitStructDeclaration(); } break; case 143: { - (yyval.interm.typeList) = (yyvsp[(1) - (2)].interm.typeList); - for (unsigned int i = 0; i < (yyvsp[(2) - (2)].interm.typeList)->size(); ++i) { - for (unsigned int j = 0; j < (yyval.interm.typeList)->size(); ++j) { - if ((*(yyval.interm.typeList))[j].type->getFieldName() == (*(yyvsp[(2) - (2)].interm.typeList))[i].type->getFieldName()) { - context->error((*(yyvsp[(2) - (2)].interm.typeList))[i].line, "duplicate field name in structure:", "struct", (*(yyvsp[(2) - (2)].interm.typeList))[i].type->getFieldName().c_str()); - context->recover(); - } - } - (yyval.interm.typeList)->push_back((*(yyvsp[(2) - (2)].interm.typeList))[i]); - } + (yyval.interm.fieldList) = (yyvsp[(1) - (1)].interm.fieldList); } break; case 144: { - (yyval.interm.typeList) = (yyvsp[(2) - (3)].interm.typeList); - - if (context->voidErrorCheck((yyvsp[(1) - (3)].interm.type).line, (*(yyvsp[(2) - (3)].interm.typeList))[0].type->getFieldName(), (yyvsp[(1) - (3)].interm.type))) { - context->recover(); - } - for (unsigned int i = 0; i < (yyval.interm.typeList)->size(); ++i) { - // - // Careful not to replace already known aspects of type, like array-ness - // - TType* type = (*(yyval.interm.typeList))[i].type; - type->setBasicType((yyvsp[(1) - (3)].interm.type).type); - type->setNominalSize((yyvsp[(1) - (3)].interm.type).size); - type->setMatrix((yyvsp[(1) - (3)].interm.type).matrix); - type->setPrecision((yyvsp[(1) - (3)].interm.type).precision); - - // don't allow arrays of arrays - if (type->isArray()) { - if (context->arrayTypeErrorCheck((yyvsp[(1) - (3)].interm.type).line, (yyvsp[(1) - (3)].interm.type))) + (yyval.interm.fieldList) = (yyvsp[(1) - (2)].interm.fieldList); + for (size_t i = 0; i < (yyvsp[(2) - (2)].interm.fieldList)->size(); ++i) { + TField* field = (*(yyvsp[(2) - (2)].interm.fieldList))[i]; + for (size_t j = 0; j < (yyval.interm.fieldList)->size(); ++j) { + if ((*(yyval.interm.fieldList))[j]->name() == field->name()) { + context->error((yylsp[(2) - (2)]), "duplicate field name in structure:", "struct", field->name().c_str()); context->recover(); + } } - if ((yyvsp[(1) - (3)].interm.type).array) - type->setArraySize((yyvsp[(1) - (3)].interm.type).arraySize); - if ((yyvsp[(1) - (3)].interm.type).userDef) { - type->setStruct((yyvsp[(1) - (3)].interm.type).userDef->getStruct()); - type->setTypeName((yyvsp[(1) - (3)].interm.type).userDef->getTypeName()); - } - - if (context->structNestingErrorCheck((yyvsp[(1) - (3)].interm.type).line, *type)) { - context->recover(); - } + (yyval.interm.fieldList)->push_back(field); } } break; @@ -4016,65 +4074,92 @@ yyreduce: case 145: { - (yyval.interm.typeList) = NewPoolTTypeList(); - (yyval.interm.typeList)->push_back((yyvsp[(1) - (1)].interm.typeLine)); + (yyval.interm.fieldList) = (yyvsp[(2) - (3)].interm.fieldList); + + if (context->voidErrorCheck((yylsp[(1) - (3)]), (*(yyvsp[(2) - (3)].interm.fieldList))[0]->name(), (yyvsp[(1) - (3)].interm.type))) { + context->recover(); + } + for (unsigned int i = 0; i < (yyval.interm.fieldList)->size(); ++i) { + // + // Careful not to replace already known aspects of type, like array-ness + // + TType* type = (*(yyval.interm.fieldList))[i]->type(); + type->setBasicType((yyvsp[(1) - (3)].interm.type).type); + type->setNominalSize((yyvsp[(1) - (3)].interm.type).size); + type->setMatrix((yyvsp[(1) - (3)].interm.type).matrix); + type->setPrecision((yyvsp[(1) - (3)].interm.type).precision); + + // don't allow arrays of arrays + if (type->isArray()) { + if (context->arrayTypeErrorCheck((yylsp[(1) - (3)]), (yyvsp[(1) - (3)].interm.type))) + context->recover(); + } + if ((yyvsp[(1) - (3)].interm.type).array) + type->setArraySize((yyvsp[(1) - (3)].interm.type).arraySize); + if ((yyvsp[(1) - (3)].interm.type).userDef) + type->setStruct((yyvsp[(1) - (3)].interm.type).userDef->getStruct()); + + if (context->structNestingErrorCheck((yylsp[(1) - (3)]), *(*(yyval.interm.fieldList))[i])) + context->recover(); + } } break; case 146: { - (yyval.interm.typeList)->push_back((yyvsp[(3) - (3)].interm.typeLine)); + (yyval.interm.fieldList) = NewPoolTFieldList(); + (yyval.interm.fieldList)->push_back((yyvsp[(1) - (1)].interm.field)); } break; case 147: { - if (context->reservedErrorCheck((yyvsp[(1) - (1)].lex).line, *(yyvsp[(1) - (1)].lex).string)) - context->recover(); - - (yyval.interm.typeLine).type = new TType(EbtVoid, EbpUndefined); - (yyval.interm.typeLine).line = (yyvsp[(1) - (1)].lex).line; - (yyval.interm.typeLine).type->setFieldName(*(yyvsp[(1) - (1)].lex).string); + (yyval.interm.fieldList)->push_back((yyvsp[(3) - (3)].interm.field)); } break; case 148: { - if (context->reservedErrorCheck((yyvsp[(1) - (4)].lex).line, *(yyvsp[(1) - (4)].lex).string)) + if (context->reservedErrorCheck((yylsp[(1) - (1)]), *(yyvsp[(1) - (1)].lex).string)) context->recover(); - (yyval.interm.typeLine).type = new TType(EbtVoid, EbpUndefined); - (yyval.interm.typeLine).line = (yyvsp[(1) - (4)].lex).line; - (yyval.interm.typeLine).type->setFieldName(*(yyvsp[(1) - (4)].lex).string); - - int size; - if (context->arraySizeErrorCheck((yyvsp[(2) - (4)].lex).line, (yyvsp[(3) - (4)].interm.intermTypedNode), size)) - context->recover(); - (yyval.interm.typeLine).type->setArraySize(size); + TType* type = new TType(EbtVoid, EbpUndefined); + (yyval.interm.field) = new TField(type, (yyvsp[(1) - (1)].lex).string); } break; case 149: - { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); } + { + if (context->reservedErrorCheck((yylsp[(1) - (4)]), *(yyvsp[(1) - (4)].lex).string)) + context->recover(); + + TType* type = new TType(EbtVoid, EbpUndefined); + int size = 0; + if (context->arraySizeErrorCheck((yylsp[(3) - (4)]), (yyvsp[(3) - (4)].interm.intermTypedNode), size)) + context->recover(); + type->setArraySize(size); + + (yyval.interm.field) = new TField(type, (yyvsp[(1) - (4)].lex).string); + } break; case 150: - { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); } + { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); } break; case 151: - { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermAggregate); } + { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); } break; case 152: - { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); } + { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermAggregate); } break; case 153: @@ -4104,33 +4189,33 @@ yyreduce: case 158: - { (yyval.interm.intermAggregate) = 0; } + { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); } break; case 159: - { context->symbolTable.push(); } + { (yyval.interm.intermAggregate) = 0; } break; case 160: - { context->symbolTable.pop(); } + { context->symbolTable.push(); } break; case 161: - { - if ((yyvsp[(3) - (5)].interm.intermAggregate) != 0) { - (yyvsp[(3) - (5)].interm.intermAggregate)->setOp(EOpSequence); - (yyvsp[(3) - (5)].interm.intermAggregate)->setEndLine((yyvsp[(5) - (5)].lex).line); - } - (yyval.interm.intermAggregate) = (yyvsp[(3) - (5)].interm.intermAggregate); - } + { context->symbolTable.pop(); } break; case 162: - { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); } + { + if ((yyvsp[(3) - (5)].interm.intermAggregate) != 0) { + (yyvsp[(3) - (5)].interm.intermAggregate)->setOp(EOpSequence); + (yyvsp[(3) - (5)].interm.intermAggregate)->setLine((yyloc)); + } + (yyval.interm.intermAggregate) = (yyvsp[(3) - (5)].interm.intermAggregate); + } break; case 163: @@ -4140,84 +4225,89 @@ yyreduce: case 164: - { context->symbolTable.push(); } + { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); } break; case 165: - { context->symbolTable.pop(); (yyval.interm.intermNode) = (yyvsp[(2) - (2)].interm.intermNode); } + { context->symbolTable.push(); } break; case 166: - { context->symbolTable.push(); } + { context->symbolTable.pop(); (yyval.interm.intermNode) = (yyvsp[(2) - (2)].interm.intermNode); } break; case 167: - { context->symbolTable.pop(); (yyval.interm.intermNode) = (yyvsp[(2) - (2)].interm.intermNode); } + { context->symbolTable.push(); } break; case 168: + { context->symbolTable.pop(); (yyval.interm.intermNode) = (yyvsp[(2) - (2)].interm.intermNode); } + break; + + case 169: + { (yyval.interm.intermNode) = 0; } break; - case 169: + case 170: { if ((yyvsp[(2) - (3)].interm.intermAggregate)) { (yyvsp[(2) - (3)].interm.intermAggregate)->setOp(EOpSequence); - (yyvsp[(2) - (3)].interm.intermAggregate)->setEndLine((yyvsp[(3) - (3)].lex).line); + (yyvsp[(2) - (3)].interm.intermAggregate)->setLine((yyloc)); } (yyval.interm.intermNode) = (yyvsp[(2) - (3)].interm.intermAggregate); } break; - case 170: - - { - (yyval.interm.intermAggregate) = context->intermediate.makeAggregate((yyvsp[(1) - (1)].interm.intermNode), 0); - } - break; - case 171: { - (yyval.interm.intermAggregate) = context->intermediate.growAggregate((yyvsp[(1) - (2)].interm.intermAggregate), (yyvsp[(2) - (2)].interm.intermNode), 0); + (yyval.interm.intermAggregate) = context->intermediate.makeAggregate((yyvsp[(1) - (1)].interm.intermNode), (yyloc)); } break; case 172: - { (yyval.interm.intermNode) = 0; } + { + (yyval.interm.intermAggregate) = context->intermediate.growAggregate((yyvsp[(1) - (2)].interm.intermAggregate), (yyvsp[(2) - (2)].interm.intermNode), (yyloc)); + } break; case 173: - { (yyval.interm.intermNode) = static_cast((yyvsp[(1) - (2)].interm.intermTypedNode)); } + { (yyval.interm.intermNode) = 0; } break; case 174: - { - if (context->boolErrorCheck((yyvsp[(1) - (5)].lex).line, (yyvsp[(3) - (5)].interm.intermTypedNode))) - context->recover(); - (yyval.interm.intermNode) = context->intermediate.addSelection((yyvsp[(3) - (5)].interm.intermTypedNode), (yyvsp[(5) - (5)].interm.nodePair), (yyvsp[(1) - (5)].lex).line); - } + { (yyval.interm.intermNode) = static_cast((yyvsp[(1) - (2)].interm.intermTypedNode)); } break; case 175: + { + if (context->boolErrorCheck((yylsp[(1) - (5)]), (yyvsp[(3) - (5)].interm.intermTypedNode))) + context->recover(); + (yyval.interm.intermNode) = context->intermediate.addSelection((yyvsp[(3) - (5)].interm.intermTypedNode), (yyvsp[(5) - (5)].interm.nodePair), (yylsp[(1) - (5)])); + } + break; + + case 176: + { (yyval.interm.nodePair).node1 = (yyvsp[(1) - (3)].interm.intermNode); (yyval.interm.nodePair).node2 = (yyvsp[(3) - (3)].interm.intermNode); } break; - case 176: + case 177: { (yyval.interm.nodePair).node1 = (yyvsp[(1) - (1)].interm.intermNode); @@ -4225,7 +4315,7 @@ yyreduce: } break; - case 177: + case 178: { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); @@ -4234,16 +4324,16 @@ yyreduce: } break; - case 178: + case 179: { TIntermNode* intermNode; - if (context->structQualifierErrorCheck((yyvsp[(2) - (4)].lex).line, (yyvsp[(1) - (4)].interm.type))) + if (context->structQualifierErrorCheck((yylsp[(2) - (4)]), (yyvsp[(1) - (4)].interm.type))) context->recover(); - if (context->boolErrorCheck((yyvsp[(2) - (4)].lex).line, (yyvsp[(1) - (4)].interm.type))) + if (context->boolErrorCheck((yylsp[(2) - (4)]), (yyvsp[(1) - (4)].interm.type))) context->recover(); - if (!context->executeInitializer((yyvsp[(2) - (4)].lex).line, *(yyvsp[(2) - (4)].lex).string, (yyvsp[(1) - (4)].interm.type), (yyvsp[(4) - (4)].interm.intermTypedNode), intermNode)) + if (!context->executeInitializer((yylsp[(2) - (4)]), *(yyvsp[(2) - (4)].lex).string, (yyvsp[(1) - (4)].interm.type), (yyvsp[(4) - (4)].interm.intermTypedNode), intermNode)) (yyval.interm.intermTypedNode) = (yyvsp[(4) - (4)].interm.intermTypedNode); else { context->recover(); @@ -4252,54 +4342,47 @@ yyreduce: } break; - case 179: - - { context->symbolTable.push(); ++context->loopNestingLevel; } - break; - case 180: - { - context->symbolTable.pop(); - (yyval.interm.intermNode) = context->intermediate.addLoop(ELoopWhile, 0, (yyvsp[(4) - (6)].interm.intermTypedNode), 0, (yyvsp[(6) - (6)].interm.intermNode), (yyvsp[(1) - (6)].lex).line); - --context->loopNestingLevel; - } + { context->symbolTable.push(); ++context->loopNestingLevel; } break; case 181: - { ++context->loopNestingLevel; } + { + context->symbolTable.pop(); + (yyval.interm.intermNode) = context->intermediate.addLoop(ELoopWhile, 0, (yyvsp[(4) - (6)].interm.intermTypedNode), 0, (yyvsp[(6) - (6)].interm.intermNode), (yylsp[(1) - (6)])); + --context->loopNestingLevel; + } break; case 182: - { - if (context->boolErrorCheck((yyvsp[(8) - (8)].lex).line, (yyvsp[(6) - (8)].interm.intermTypedNode))) - context->recover(); - - (yyval.interm.intermNode) = context->intermediate.addLoop(ELoopDoWhile, 0, (yyvsp[(6) - (8)].interm.intermTypedNode), 0, (yyvsp[(3) - (8)].interm.intermNode), (yyvsp[(4) - (8)].lex).line); - --context->loopNestingLevel; - } + { ++context->loopNestingLevel; } break; case 183: - { context->symbolTable.push(); ++context->loopNestingLevel; } + { + if (context->boolErrorCheck((yylsp[(8) - (8)]), (yyvsp[(6) - (8)].interm.intermTypedNode))) + context->recover(); + + (yyval.interm.intermNode) = context->intermediate.addLoop(ELoopDoWhile, 0, (yyvsp[(6) - (8)].interm.intermTypedNode), 0, (yyvsp[(3) - (8)].interm.intermNode), (yylsp[(4) - (8)])); + --context->loopNestingLevel; + } break; case 184: - { - context->symbolTable.pop(); - (yyval.interm.intermNode) = context->intermediate.addLoop(ELoopFor, (yyvsp[(4) - (7)].interm.intermNode), reinterpret_cast((yyvsp[(5) - (7)].interm.nodePair).node1), reinterpret_cast((yyvsp[(5) - (7)].interm.nodePair).node2), (yyvsp[(7) - (7)].interm.intermNode), (yyvsp[(1) - (7)].lex).line); - --context->loopNestingLevel; - } + { context->symbolTable.push(); ++context->loopNestingLevel; } break; case 185: { - (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); + context->symbolTable.pop(); + (yyval.interm.intermNode) = context->intermediate.addLoop(ELoopFor, (yyvsp[(4) - (7)].interm.intermNode), reinterpret_cast((yyvsp[(5) - (7)].interm.nodePair).node1), reinterpret_cast((yyvsp[(5) - (7)].interm.nodePair).node2), (yyvsp[(7) - (7)].interm.intermNode), (yylsp[(1) - (7)])); + --context->loopNestingLevel; } break; @@ -4313,26 +4396,33 @@ yyreduce: case 187: { - (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); + (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); } break; case 188: { - (yyval.interm.intermTypedNode) = 0; + (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); } break; case 189: + { + (yyval.interm.intermTypedNode) = 0; + } + break; + + case 190: + { (yyval.interm.nodePair).node1 = (yyvsp[(1) - (2)].interm.intermTypedNode); (yyval.interm.nodePair).node2 = 0; } break; - case 190: + case 191: { (yyval.interm.nodePair).node1 = (yyvsp[(1) - (3)].interm.intermTypedNode); @@ -4340,49 +4430,34 @@ yyreduce: } break; - case 191: - - { - if (context->loopNestingLevel <= 0) { - context->error((yyvsp[(1) - (2)].lex).line, "continue statement only allowed in loops", ""); - context->recover(); - } - (yyval.interm.intermNode) = context->intermediate.addBranch(EOpContinue, (yyvsp[(1) - (2)].lex).line); - } - break; - case 192: { if (context->loopNestingLevel <= 0) { - context->error((yyvsp[(1) - (2)].lex).line, "break statement only allowed in loops", ""); + context->error((yylsp[(1) - (2)]), "continue statement only allowed in loops", ""); context->recover(); } - (yyval.interm.intermNode) = context->intermediate.addBranch(EOpBreak, (yyvsp[(1) - (2)].lex).line); + (yyval.interm.intermNode) = context->intermediate.addBranch(EOpContinue, (yylsp[(1) - (2)])); } break; case 193: { - (yyval.interm.intermNode) = context->intermediate.addBranch(EOpReturn, (yyvsp[(1) - (2)].lex).line); - if (context->currentFunctionType->getBasicType() != EbtVoid) { - context->error((yyvsp[(1) - (2)].lex).line, "non-void function must return a value", "return"); + if (context->loopNestingLevel <= 0) { + context->error((yylsp[(1) - (2)]), "break statement only allowed in loops", ""); context->recover(); } + (yyval.interm.intermNode) = context->intermediate.addBranch(EOpBreak, (yylsp[(1) - (2)])); } break; case 194: { - (yyval.interm.intermNode) = context->intermediate.addBranch(EOpReturn, (yyvsp[(2) - (3)].interm.intermTypedNode), (yyvsp[(1) - (3)].lex).line); - context->functionReturnsValue = true; - if (context->currentFunctionType->getBasicType() == EbtVoid) { - context->error((yyvsp[(1) - (3)].lex).line, "void function cannot return a value", "return"); - context->recover(); - } else if (*(context->currentFunctionType) != (yyvsp[(2) - (3)].interm.intermTypedNode)->getType()) { - context->error((yyvsp[(1) - (3)].lex).line, "function return is not matching type:", "return"); + (yyval.interm.intermNode) = context->intermediate.addBranch(EOpReturn, (yylsp[(1) - (2)])); + if (context->currentFunctionType->getBasicType() != EbtVoid) { + context->error((yylsp[(1) - (2)]), "non-void function must return a value", "return"); context->recover(); } } @@ -4391,23 +4466,30 @@ yyreduce: case 195: { - FRAG_ONLY("discard", (yyvsp[(1) - (2)].lex).line); - (yyval.interm.intermNode) = context->intermediate.addBranch(EOpKill, (yyvsp[(1) - (2)].lex).line); + (yyval.interm.intermNode) = context->intermediate.addBranch(EOpReturn, (yyvsp[(2) - (3)].interm.intermTypedNode), (yylsp[(1) - (3)])); + context->functionReturnsValue = true; + if (context->currentFunctionType->getBasicType() == EbtVoid) { + context->error((yylsp[(1) - (3)]), "void function cannot return a value", "return"); + context->recover(); + } else if (*(context->currentFunctionType) != (yyvsp[(2) - (3)].interm.intermTypedNode)->getType()) { + context->error((yylsp[(1) - (3)]), "function return is not matching type:", "return"); + context->recover(); + } } break; case 196: { - (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); - context->treeRoot = (yyval.interm.intermNode); + FRAG_ONLY("discard", (yylsp[(1) - (2)])); + (yyval.interm.intermNode) = context->intermediate.addBranch(EOpKill, (yylsp[(1) - (2)])); } break; case 197: { - (yyval.interm.intermNode) = context->intermediate.growAggregate((yyvsp[(1) - (2)].interm.intermNode), (yyvsp[(2) - (2)].interm.intermNode), 0); + (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); context->treeRoot = (yyval.interm.intermNode); } break; @@ -4415,7 +4497,8 @@ yyreduce: case 198: { - (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); + (yyval.interm.intermNode) = context->intermediate.growAggregate((yyvsp[(1) - (2)].interm.intermNode), (yyvsp[(2) - (2)].interm.intermNode), (yyloc)); + context->treeRoot = (yyval.interm.intermNode); } break; @@ -4428,6 +4511,13 @@ yyreduce: case 200: + { + (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); + } + break; + + case 201: + { TFunction* function = (yyvsp[(1) - (1)].interm).function; @@ -4435,7 +4525,7 @@ yyreduce: if (builtIn) { - context->error((yyvsp[(1) - (1)].interm).line, "built-in functions cannot be redefined", function->getName().c_str()); + context->error((yylsp[(1) - (1)]), "built-in functions cannot be redefined", function->getName().c_str()); context->recover(); } @@ -4449,7 +4539,7 @@ yyreduce: // // Then this function already has a body. // - context->error((yyvsp[(1) - (1)].interm).line, "function already has a body", function->getName().c_str()); + context->error((yylsp[(1) - (1)]), "function already has a body", function->getName().c_str()); context->recover(); } prevDec->setDefined(); @@ -4459,11 +4549,11 @@ yyreduce: // if (function->getName() == "main") { if (function->getParamCount() > 0) { - context->error((yyvsp[(1) - (1)].interm).line, "function cannot take any parameter(s)", function->getName().c_str()); + context->error((yylsp[(1) - (1)]), "function cannot take any parameter(s)", function->getName().c_str()); context->recover(); } if (function->getReturnType().getBasicType() != EbtVoid) { - context->error((yyvsp[(1) - (1)].interm).line, "", function->getReturnType().getBasicString(), "main function cannot return a value"); + context->error((yylsp[(1) - (1)]), "", function->getReturnType().getBasicString(), "main function cannot return a value"); context->recover(); } } @@ -4491,7 +4581,7 @@ yyreduce: // Insert the parameters with name in the symbol table. // if (! context->symbolTable.insert(*variable)) { - context->error((yyvsp[(1) - (1)].interm).line, "redefinition", variable->getName().c_str()); + context->error((yylsp[(1) - (1)]), "redefinition", variable->getName().c_str()); context->recover(); delete variable; } @@ -4502,31 +4592,32 @@ yyreduce: paramNodes = context->intermediate.growAggregate( paramNodes, context->intermediate.addSymbol(variable->getUniqueId(), - variable->getName(), - variable->getType(), (yyvsp[(1) - (1)].interm).line), - (yyvsp[(1) - (1)].interm).line); + variable->getName(), + variable->getType(), + (yylsp[(1) - (1)])), + (yylsp[(1) - (1)])); } else { - paramNodes = context->intermediate.growAggregate(paramNodes, context->intermediate.addSymbol(0, "", *param.type, (yyvsp[(1) - (1)].interm).line), (yyvsp[(1) - (1)].interm).line); + paramNodes = context->intermediate.growAggregate(paramNodes, context->intermediate.addSymbol(0, "", *param.type, (yylsp[(1) - (1)])), (yylsp[(1) - (1)])); } } - context->intermediate.setAggregateOperator(paramNodes, EOpParameters, (yyvsp[(1) - (1)].interm).line); + context->intermediate.setAggregateOperator(paramNodes, EOpParameters, (yylsp[(1) - (1)])); (yyvsp[(1) - (1)].interm).intermAggregate = paramNodes; context->loopNestingLevel = 0; } break; - case 201: + case 202: { //?? Check that all paths return a value if return type != void ? // May be best done as post process phase on intermediate code if (context->currentFunctionType->getBasicType() != EbtVoid && ! context->functionReturnsValue) { - context->error((yyvsp[(1) - (3)].interm).line, "function does not return a value:", "", (yyvsp[(1) - (3)].interm).function->getName().c_str()); + context->error((yylsp[(1) - (3)]), "function does not return a value:", "", (yyvsp[(1) - (3)].interm).function->getName().c_str()); context->recover(); } - (yyval.interm.intermNode) = context->intermediate.growAggregate((yyvsp[(1) - (3)].interm).intermAggregate, (yyvsp[(3) - (3)].interm.intermNode), 0); - context->intermediate.setAggregateOperator((yyval.interm.intermNode), EOpFunction, (yyvsp[(1) - (3)].interm).line); + (yyval.interm.intermNode) = context->intermediate.growAggregate((yyvsp[(1) - (3)].interm).intermAggregate, (yyvsp[(3) - (3)].interm.intermNode), (yyloc)); + context->intermediate.setAggregateOperator((yyval.interm.intermNode), EOpFunction, (yylsp[(1) - (3)])); (yyval.interm.intermNode)->getAsAggregate()->setName((yyvsp[(1) - (3)].interm).function->getMangledName().c_str()); (yyval.interm.intermNode)->getAsAggregate()->setType((yyvsp[(1) - (3)].interm).function->getReturnType()); @@ -4535,9 +4626,6 @@ yyreduce: (yyval.interm.intermNode)->getAsAggregate()->setOptimize(context->pragma().optimize); (yyval.interm.intermNode)->getAsAggregate()->setDebug(context->pragma().debug); - if ((yyvsp[(3) - (3)].interm.intermNode) && (yyvsp[(3) - (3)].interm.intermNode)->getAsAggregate()) - (yyval.interm.intermNode)->getAsAggregate()->setEndLine((yyvsp[(3) - (3)].interm.intermNode)->getAsAggregate()->getEndLine()); - context->symbolTable.pop(); } break; @@ -4546,6 +4634,17 @@ yyreduce: default: break; } + /* User semantic actions sometimes alter yychar, and that requires + that yytoken be updated with the new translation. We take the + approach of translating immediately before every use of yytoken. + One alternative is translating here after every semantic action, + but that translation would be missed if the semantic action invokes + YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or + if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an + incorrect destructor might then be invoked immediately. In the + case of YYERROR or YYBACKUP, subsequent parser actions might lead + to an incorrect destructor call or verbose syntax error message + before the lookahead is translated. */ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); YYPOPSTACK (yylen); @@ -4553,6 +4652,7 @@ yyreduce: YY_STACK_PRINT (yyss, yyssp); *++yyvsp = yyval; + *++yylsp = yyloc; /* Now `shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule @@ -4573,48 +4673,51 @@ yyreduce: | yyerrlab -- here on detecting error | `------------------------------------*/ yyerrlab: + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); + /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { ++yynerrs; #if ! YYERROR_VERBOSE - yyerror (context, YY_("syntax error")); + yyerror (&yylloc, context, YY_("syntax error")); #else +# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ + yyssp, yytoken) { - YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); - if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) - { - YYSIZE_T yyalloc = 2 * yysize; - if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) - yyalloc = YYSTACK_ALLOC_MAXIMUM; - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); - yymsg = (char *) YYSTACK_ALLOC (yyalloc); - if (yymsg) - yymsg_alloc = yyalloc; - else - { - yymsg = yymsgbuf; - yymsg_alloc = sizeof yymsgbuf; - } - } - - if (0 < yysize && yysize <= yymsg_alloc) - { - (void) yysyntax_error (yymsg, yystate, yychar); - yyerror (context, yymsg); - } - else - { - yyerror (context, YY_("syntax error")); - if (yysize != 0) - goto yyexhaustedlab; - } + char const *yymsgp = YY_("syntax error"); + int yysyntax_error_status; + yysyntax_error_status = YYSYNTAX_ERROR; + if (yysyntax_error_status == 0) + yymsgp = yymsg; + else if (yysyntax_error_status == 1) + { + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); + if (!yymsg) + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + yysyntax_error_status = 2; + } + else + { + yysyntax_error_status = YYSYNTAX_ERROR; + yymsgp = yymsg; + } + } + yyerror (&yylloc, context, yymsgp); + if (yysyntax_error_status == 2) + goto yyexhaustedlab; } +# undef YYSYNTAX_ERROR #endif } - + yyerror_range[1] = yylloc; if (yyerrstatus == 3) { @@ -4630,7 +4733,7 @@ yyerrlab: else { yydestruct ("Error: discarding", - yytoken, &yylval, context); + yytoken, &yylval, &yylloc, context); yychar = YYEMPTY; } } @@ -4651,6 +4754,7 @@ yyerrorlab: if (/*CONSTCOND*/ 0) goto yyerrorlab; + yyerror_range[1] = yylsp[1-yylen]; /* Do not reclaim the symbols of the rule which action triggered this YYERROR. */ YYPOPSTACK (yylen); @@ -4669,7 +4773,7 @@ yyerrlab1: for (;;) { yyn = yypact[yystate]; - if (yyn != YYPACT_NINF) + if (!yypact_value_is_default (yyn)) { yyn += YYTERROR; if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) @@ -4684,16 +4788,23 @@ yyerrlab1: if (yyssp == yyss) YYABORT; - + yyerror_range[1] = *yylsp; yydestruct ("Error: popping", - yystos[yystate], yyvsp, context); + yystos[yystate], yyvsp, yylsp, context); YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); } + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END + yyerror_range[2] = yylloc; + /* Using YYLLOC is tempting, but would change the location of + the lookahead. YYLOC is available though. */ + YYLLOC_DEFAULT (yyloc, yyerror_range, 2); + *++yylsp = yyloc; /* Shift the error token. */ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); @@ -4716,20 +4827,25 @@ yyabortlab: yyresult = 1; goto yyreturn; -#if !defined(yyoverflow) || YYERROR_VERBOSE +#if !defined yyoverflow || YYERROR_VERBOSE /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ yyexhaustedlab: - yyerror (context, YY_("memory exhausted")); + yyerror (&yylloc, context, YY_("memory exhausted")); yyresult = 2; /* Fall through. */ #endif yyreturn: if (yychar != YYEMPTY) - yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval, context); + { + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = YYTRANSLATE (yychar); + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval, &yylloc, context); + } /* Do not reclaim the symbols of the rule which action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); @@ -4737,7 +4853,7 @@ yyreturn: while (yyssp != yyss) { yydestruct ("Cleanup: popping", - yystos[*yyssp], yyvsp, context); + yystos[*yyssp], yyvsp, yylsp, context); YYPOPSTACK (1); } #ifndef yyoverflow @@ -4756,7 +4872,11 @@ yyreturn: +void yyerror(YYLTYPE* yylloc, TParseContext* context, const char* reason) { + context->error(*yylloc, reason, ""); + context->recover(); +} + int glslang_parse(TParseContext* context) { return yyparse(context); } - diff --git a/gfx/angle/src/compiler/glslang_tab.h b/gfx/angle/src/compiler/glslang_tab.h index 3e461eeaffff..2f0f110641a7 100644 --- a/gfx/angle/src/compiler/glslang_tab.h +++ b/gfx/angle/src/compiler/glslang_tab.h @@ -1,9 +1,8 @@ -/* A Bison parser, made by GNU Bison 2.4.2. */ +/* A Bison parser, made by GNU Bison 2.7. */ -/* Skeleton interface for Bison's Yacc-like parsers in C +/* Bison interface for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2006, 2009-2010 Free Software - Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -31,6 +30,23 @@ This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ +#ifndef YY_YY_GLSLANG_TAB_H_INCLUDED +# define YY_YY_GLSLANG_TAB_H_INCLUDED +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif +#if YYDEBUG +extern int yydebug; +#endif +/* "%code requires" blocks. */ + + +#define YYLTYPE TSourceLoc +#define YYLTYPE_IS_DECLARED 1 + + + /* Tokens. */ #ifndef YYTOKENTYPE @@ -85,64 +101,61 @@ FLOATCONSTANT = 302, INTCONSTANT = 303, BOOLCONSTANT = 304, - FIELD_SELECTION = 305, - LEFT_OP = 306, - RIGHT_OP = 307, - INC_OP = 308, - DEC_OP = 309, - LE_OP = 310, - GE_OP = 311, - EQ_OP = 312, - NE_OP = 313, - AND_OP = 314, - OR_OP = 315, - XOR_OP = 316, - MUL_ASSIGN = 317, - DIV_ASSIGN = 318, - ADD_ASSIGN = 319, - MOD_ASSIGN = 320, - LEFT_ASSIGN = 321, - RIGHT_ASSIGN = 322, - AND_ASSIGN = 323, - XOR_ASSIGN = 324, - OR_ASSIGN = 325, - SUB_ASSIGN = 326, - LEFT_PAREN = 327, - RIGHT_PAREN = 328, - LEFT_BRACKET = 329, - RIGHT_BRACKET = 330, - LEFT_BRACE = 331, - RIGHT_BRACE = 332, - DOT = 333, - COMMA = 334, - COLON = 335, - EQUAL = 336, - SEMICOLON = 337, - BANG = 338, - DASH = 339, - TILDE = 340, - PLUS = 341, - STAR = 342, - SLASH = 343, - PERCENT = 344, - LEFT_ANGLE = 345, - RIGHT_ANGLE = 346, - VERTICAL_BAR = 347, - CARET = 348, - AMPERSAND = 349, - QUESTION = 350 + LEFT_OP = 305, + RIGHT_OP = 306, + INC_OP = 307, + DEC_OP = 308, + LE_OP = 309, + GE_OP = 310, + EQ_OP = 311, + NE_OP = 312, + AND_OP = 313, + OR_OP = 314, + XOR_OP = 315, + MUL_ASSIGN = 316, + DIV_ASSIGN = 317, + ADD_ASSIGN = 318, + MOD_ASSIGN = 319, + LEFT_ASSIGN = 320, + RIGHT_ASSIGN = 321, + AND_ASSIGN = 322, + XOR_ASSIGN = 323, + OR_ASSIGN = 324, + SUB_ASSIGN = 325, + LEFT_PAREN = 326, + RIGHT_PAREN = 327, + LEFT_BRACKET = 328, + RIGHT_BRACKET = 329, + LEFT_BRACE = 330, + RIGHT_BRACE = 331, + DOT = 332, + COMMA = 333, + COLON = 334, + EQUAL = 335, + SEMICOLON = 336, + BANG = 337, + DASH = 338, + TILDE = 339, + PLUS = 340, + STAR = 341, + SLASH = 342, + PERCENT = 343, + LEFT_ANGLE = 344, + RIGHT_ANGLE = 345, + VERTICAL_BAR = 346, + CARET = 347, + AMPERSAND = 348, + QUESTION = 349 }; #endif - #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE { struct { - TSourceLoc line; union { TString *string; float f; @@ -152,7 +165,6 @@ typedef union YYSTYPE TSymbol* symbol; } lex; struct { - TSourceLoc line; TOperator op; union { TIntermNode* intermNode; @@ -166,8 +178,8 @@ typedef union YYSTYPE TQualifier qualifier; TFunction* function; TParameter param; - TTypeLine typeLine; - TTypeList* typeList; + TField* field; + TFieldList* fieldList; }; } interm; @@ -179,6 +191,32 @@ typedef union YYSTYPE # define YYSTYPE_IS_DECLARED 1 #endif +#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED +typedef struct YYLTYPE +{ + int first_line; + int first_column; + int last_line; + int last_column; +} YYLTYPE; +# define yyltype YYLTYPE /* obsolescent; will be withdrawn */ +# define YYLTYPE_IS_DECLARED 1 +# define YYLTYPE_IS_TRIVIAL 1 +#endif +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int yyparse (void *YYPARSE_PARAM); +#else +int yyparse (); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int yyparse (TParseContext* context); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ +#endif /* !YY_YY_GLSLANG_TAB_H_INCLUDED */ diff --git a/gfx/angle/src/compiler/intermOut.cpp b/gfx/angle/src/compiler/intermOut.cpp index f48a049c633d..13aa96af6d62 100644 --- a/gfx/angle/src/compiler/intermOut.cpp +++ b/gfx/angle/src/compiler/intermOut.cpp @@ -189,7 +189,9 @@ bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary* node) case EOpAny: out << "any"; break; case EOpAll: out << "all"; break; - default: out.message(EPrefixError, "Bad unary op"); + default: + out.prefix(EPrefixError); + out << "Bad unary op"; } out << " (" << node->getCompleteString() << ")"; @@ -204,7 +206,8 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate* node) TInfoSinkBase& out = sink; if (node->getOp() == EOpNull) { - out.message(EPrefixError, "node is still EOpNull!"); + out.prefix(EPrefixError); + out << "node is still EOpNull!"; return true; } @@ -263,7 +266,9 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate* node) case EOpDeclaration: out << "Declaration: "; break; - default: out.message(EPrefixError, "Bad aggregation op"); + default: + out.prefix(EPrefixError); + out << "Bad aggregation op"; } if (node->getOp() != EOpSequence && node->getOp() != EOpParameters) @@ -311,9 +316,9 @@ void TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node) { TInfoSinkBase& out = sink; - int size = node->getType().getObjectSize(); + size_t size = node->getType().getObjectSize(); - for (int i = 0; i < size; i++) { + for (size_t i = 0; i < size; i++) { OutputTreeText(out, node, depth); switch (node->getUnionArrayPointer()[i].getType()) { case EbtBool: @@ -334,7 +339,7 @@ void TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node) out << " (const int)\n"; break; default: - out.message(EPrefixInternalError, "Unknown constant", node->getLine()); + out.message(EPrefixInternalError, node->getLine(), "Unknown constant"); break; } } diff --git a/gfx/angle/src/compiler/intermediate.h b/gfx/angle/src/compiler/intermediate.h index be60e0ec7032..738621fe700b 100644 --- a/gfx/angle/src/compiler/intermediate.h +++ b/gfx/angle/src/compiler/intermediate.h @@ -18,6 +18,7 @@ #include "GLSLANG/ShaderLang.h" +#include #include "compiler/Common.h" #include "compiler/Types.h" #include "compiler/ConstantUnion.h" @@ -204,12 +205,17 @@ class TInfoSink; // class TIntermNode { public: - POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) + POOL_ALLOCATOR_NEW_DELETE(); + TIntermNode() { + // TODO: Move this to TSourceLoc constructor + // after getting rid of TPublicType. + line.first_file = line.last_file = 0; + line.first_line = line.last_line = 0; + } + virtual ~TIntermNode() { } - TIntermNode() : line(0) {} - - TSourceLoc getLine() const { return line; } - void setLine(TSourceLoc l) { line = l; } + const TSourceLoc& getLine() const { return line; } + void setLine(const TSourceLoc& l) { line = l; } virtual void traverse(TIntermTraverser*) = 0; virtual TIntermTyped* getAsTyped() { return 0; } @@ -220,7 +226,6 @@ public: virtual TIntermSelection* getAsSelectionNode() { return 0; } virtual TIntermSymbol* getAsSymbolNode() { return 0; } virtual TIntermLoop* getAsLoopNode() { return 0; } - virtual ~TIntermNode() { } protected: TSourceLoc line; @@ -259,6 +264,10 @@ public: const char* getQualifierString() const { return type.getQualifierString(); } TString getCompleteString() const { return type.getCompleteString(); } + int totalRegisterCount() const { return type.totalRegisterCount(); } + int elementRegisterCount() const { return type.elementRegisterCount(); } + int getArraySize() const { return type.getArraySize(); } + protected: TType type; }; @@ -450,7 +459,7 @@ typedef TVector TQualifierList; // class TIntermAggregate : public TIntermOperator { public: - TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), endLine(0), useEmulatedFunction(false) { } + TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), useEmulatedFunction(false) { } TIntermAggregate(TOperator o) : TIntermOperator(o), useEmulatedFunction(false) { } ~TIntermAggregate() { } @@ -470,9 +479,6 @@ public: void setDebug(bool d) { debug = d; } bool getDebug() { return debug; } - void setEndLine(TSourceLoc line) { endLine = line; } - TSourceLoc getEndLine() const { return endLine; } - void setUseEmulatedFunction() { useEmulatedFunction = true; } bool getUseEmulatedFunction() { return useEmulatedFunction; } @@ -485,7 +491,6 @@ protected: bool optimize; bool debug; - TSourceLoc endLine; // If set to true, replace the built-in function call with an emulated one // to work around driver bugs. @@ -534,14 +539,14 @@ enum Visit class TIntermTraverser { public: - POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) - + POOL_ALLOCATOR_NEW_DELETE(); TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) : preVisit(preVisit), inVisit(inVisit), postVisit(postVisit), rightToLeft(rightToLeft), - depth(0) {} + depth(0), + maxDepth(0) {} virtual ~TIntermTraverser() {}; virtual void visitSymbol(TIntermSymbol*) {} @@ -553,7 +558,8 @@ public: virtual bool visitLoop(Visit visit, TIntermLoop*) {return true;} virtual bool visitBranch(Visit visit, TIntermBranch*) {return true;} - void incrementDepth() {depth++;} + int getMaxDepth() const {return maxDepth;} + void incrementDepth() {depth++; maxDepth = std::max(maxDepth, depth); } void decrementDepth() {depth--;} // Return the original name if hash function pointer is NULL; @@ -567,6 +573,7 @@ public: protected: int depth; + int maxDepth; }; #endif // __INTERMEDIATE_H diff --git a/gfx/angle/src/compiler/localintermediate.h b/gfx/angle/src/compiler/localintermediate.h index 56890bd56999..ccbc40178acf 100644 --- a/gfx/angle/src/compiler/localintermediate.h +++ b/gfx/angle/src/compiler/localintermediate.h @@ -22,37 +22,36 @@ struct TVectorFields { class TInfoSink; class TIntermediate { public: - POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) - + POOL_ALLOCATOR_NEW_DELETE(); TIntermediate(TInfoSink& i) : infoSink(i) { } - TIntermSymbol* addSymbol(int Id, const TString&, const TType&, TSourceLoc); + + TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TSourceLoc&); TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*); - TIntermTyped* addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc, TSymbolTable&); - TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc); - TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc); - TIntermTyped* addUnaryMath(TOperator op, TIntermNode* child, TSourceLoc, TSymbolTable&); - TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, TSourceLoc); - TIntermAggregate* makeAggregate(TIntermNode* node, TSourceLoc); - TIntermAggregate* setAggregateOperator(TIntermNode*, TOperator, TSourceLoc); - TIntermNode* addSelection(TIntermTyped* cond, TIntermNodePair code, TSourceLoc); - TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, TSourceLoc); - TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, TSourceLoc); - TIntermConstantUnion* addConstantUnion(ConstantUnion*, const TType&, TSourceLoc); + TIntermTyped* addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&, TSymbolTable&); + TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&); + TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc&); + TIntermTyped* addUnaryMath(TOperator op, TIntermNode* child, const TSourceLoc&, TSymbolTable&); + TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc&); + TIntermAggregate* makeAggregate(TIntermNode* node, const TSourceLoc&); + TIntermAggregate* setAggregateOperator(TIntermNode*, TOperator, const TSourceLoc&); + TIntermNode* addSelection(TIntermTyped* cond, TIntermNodePair code, const TSourceLoc&); + TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc&); + TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc&); + TIntermConstantUnion* addConstantUnion(ConstantUnion*, const TType&, const TSourceLoc&); TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) ; - bool parseConstTree(TSourceLoc, TIntermNode*, ConstantUnion*, TOperator, TSymbolTable&, TType, bool singleConstantParam = false); - TIntermNode* addLoop(TLoopType, TIntermNode*, TIntermTyped*, TIntermTyped*, TIntermNode*, TSourceLoc); - TIntermBranch* addBranch(TOperator, TSourceLoc); - TIntermBranch* addBranch(TOperator, TIntermTyped*, TSourceLoc); - TIntermTyped* addSwizzle(TVectorFields&, TSourceLoc); + bool parseConstTree(const TSourceLoc&, TIntermNode*, ConstantUnion*, TOperator, TSymbolTable&, TType, bool singleConstantParam = false); + TIntermNode* addLoop(TLoopType, TIntermNode*, TIntermTyped*, TIntermTyped*, TIntermNode*, const TSourceLoc&); + TIntermBranch* addBranch(TOperator, const TSourceLoc&); + TIntermBranch* addBranch(TOperator, TIntermTyped*, const TSourceLoc&); + TIntermTyped* addSwizzle(TVectorFields&, const TSourceLoc&); bool postProcess(TIntermNode*); - void remove(TIntermNode*); + void remove(TIntermNode*); void outputTree(TIntermNode*); - -protected: - TInfoSink& infoSink; private: void operator=(TIntermediate&); // prevent assignments + + TInfoSink& infoSink; }; #endif // _LOCAL_INTERMEDIATE_INCLUDED_ diff --git a/gfx/angle/src/compiler/parseConst.cpp b/gfx/angle/src/compiler/parseConst.cpp index 421d31f586b3..1cc5db8d770b 100644 --- a/gfx/angle/src/compiler/parseConst.cpp +++ b/gfx/angle/src/compiler/parseConst.cpp @@ -38,16 +38,16 @@ protected: bool visitLoop(Visit visit, TIntermLoop*); bool visitBranch(Visit visit, TIntermBranch*); - int index; + size_t index; ConstantUnion *unionArray; TType type; TOperator constructorType; bool singleConstantParam; TInfoSink& infoSink; TSymbolTable& symbolTable; - int size; // size of the constructor ( 4 for vec4) + size_t size; // size of the constructor ( 4 for vec4) bool isMatrix; - int matrixSize; // dimension of the matrix (nominal size and not the instance size) + size_t matrixSize; // dimension of the matrix (nominal size and not the instance size) }; // @@ -61,7 +61,7 @@ protected: void TConstTraverser::visitSymbol(TIntermSymbol* node) { - infoSink.info.message(EPrefixInternalError, "Symbol Node found in constant constructor", node->getLine()); + infoSink.info.message(EPrefixInternalError, node->getLine(), "Symbol Node found in constant constructor"); return; } @@ -74,12 +74,12 @@ bool TConstTraverser::visitBinary(Visit visit, TIntermBinary* node) TString buf; buf.append("'constructor' : assigning non-constant to "); buf.append(type.getCompleteString()); - infoSink.info.message(EPrefixError, buf.c_str(), node->getLine()); + infoSink.info.message(EPrefixError, node->getLine(), buf.c_str()); error = true; return false; } - infoSink.info.message(EPrefixInternalError, "Binary Node found in constant constructor", node->getLine()); + infoSink.info.message(EPrefixInternalError, node->getLine(), "Binary Node found in constant constructor"); return false; } @@ -89,7 +89,7 @@ bool TConstTraverser::visitUnary(Visit visit, TIntermUnary* node) TString buf; buf.append("'constructor' : assigning non-constant to "); buf.append(type.getCompleteString()); - infoSink.info.message(EPrefixError, buf.c_str(), node->getLine()); + infoSink.info.message(EPrefixError, node->getLine(), buf.c_str()); error = true; return false; } @@ -100,7 +100,7 @@ bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate* node) TString buf; buf.append("'constructor' : assigning non-constant to "); buf.append(type.getCompleteString()); - infoSink.info.message(EPrefixError, buf.c_str(), node->getLine()); + infoSink.info.message(EPrefixError, node->getLine(), buf.c_str()); error = true; return false; } @@ -144,7 +144,7 @@ bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate* node) bool TConstTraverser::visitSelection(Visit visit, TIntermSelection* node) { - infoSink.info.message(EPrefixInternalError, "Selection Node found in constant constructor", node->getLine()); + infoSink.info.message(EPrefixInternalError, node->getLine(), "Selection Node found in constant constructor"); error = true; return false; } @@ -159,16 +159,16 @@ void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node) } ConstantUnion* leftUnionArray = unionArray; - int instanceSize = type.getObjectSize(); + size_t instanceSize = type.getObjectSize(); if (index >= instanceSize) return; if (!singleConstantParam) { - int size = node->getType().getObjectSize(); + size_t size = node->getType().getObjectSize(); ConstantUnion *rightUnionArray = node->getUnionArrayPointer(); - for (int i=0; i < size; i++) { + for (size_t i = 0; i < size; i++) { if (index >= instanceSize) return; leftUnionArray[index] = rightUnionArray[i]; @@ -176,11 +176,11 @@ void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node) (index)++; } } else { - int totalSize = index + size; + size_t totalSize = index + size; ConstantUnion *rightUnionArray = node->getUnionArrayPointer(); if (!isMatrix) { - int count = 0; - for (int i = index; i < totalSize; i++) { + size_t count = 0; + for (size_t i = index; i < totalSize; i++) { if (i >= instanceSize) return; @@ -192,9 +192,9 @@ void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node) count++; } } else { // for matrix constructors - int count = 0; - int element = index; - for (int i = index; i < totalSize; i++) { + size_t count = 0; + size_t element = index; + for (size_t i = index; i < totalSize; i++) { if (i >= instanceSize) return; if (element - i == 0 || (i - element) % (matrixSize + 1) == 0 ) @@ -213,14 +213,14 @@ void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node) bool TConstTraverser::visitLoop(Visit visit, TIntermLoop* node) { - infoSink.info.message(EPrefixInternalError, "Loop Node found in constant constructor", node->getLine()); + infoSink.info.message(EPrefixInternalError, node->getLine(), "Loop Node found in constant constructor"); error = true; return false; } bool TConstTraverser::visitBranch(Visit visit, TIntermBranch* node) { - infoSink.info.message(EPrefixInternalError, "Branch Node found in constant constructor", node->getLine()); + infoSink.info.message(EPrefixInternalError, node->getLine(), "Branch Node found in constant constructor"); error = true; return false; } @@ -230,7 +230,7 @@ bool TConstTraverser::visitBranch(Visit visit, TIntermBranch* node) // Individual functions can be initialized to 0 to skip processing of that // type of node. It's children will still be processed. // -bool TIntermediate::parseConstTree(TSourceLoc line, TIntermNode* root, ConstantUnion* unionArray, TOperator constructorType, TSymbolTable& symbolTable, TType t, bool singleConstantParam) +bool TIntermediate::parseConstTree(const TSourceLoc& line, TIntermNode* root, ConstantUnion* unionArray, TOperator constructorType, TSymbolTable& symbolTable, TType t, bool singleConstantParam) { if (root == 0) return false; diff --git a/gfx/angle/src/compiler/preprocessor/64bit-tokenizer-safety.patch b/gfx/angle/src/compiler/preprocessor/64bit-tokenizer-safety.patch new file mode 100644 index 000000000000..7cb061601ed7 --- /dev/null +++ b/gfx/angle/src/compiler/preprocessor/64bit-tokenizer-safety.patch @@ -0,0 +1,159 @@ +--- a/src/compiler/preprocessor/Tokenizer.cpp ++++ b/src/compiler/preprocessor/Tokenizer.cpp +@@ -56,6 +56,7 @@ typedef int16_t flex_int16_t; + typedef uint16_t flex_uint16_t; + typedef int32_t flex_int32_t; + typedef uint32_t flex_uint32_t; ++typedef uint64_t flex_uint64_t; + #else + typedef signed char flex_int8_t; + typedef short int flex_int16_t; +@@ -179,6 +180,11 @@ typedef void* yyscan_t; + typedef struct yy_buffer_state *YY_BUFFER_STATE; + #endif + ++#ifndef YY_TYPEDEF_YY_SIZE_T ++#define YY_TYPEDEF_YY_SIZE_T ++typedef size_t yy_size_t; ++#endif ++ + #define EOB_ACT_CONTINUE_SCAN 0 + #define EOB_ACT_END_OF_FILE 1 + #define EOB_ACT_LAST_MATCH 2 +@@ -201,11 +207,6 @@ typedef struct yy_buffer_state *YY_BUFFER_STATE; + + #define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner ) + +-#ifndef YY_TYPEDEF_YY_SIZE_T +-#define YY_TYPEDEF_YY_SIZE_T +-typedef size_t yy_size_t; +-#endif +- + #ifndef YY_STRUCT_YY_BUFFER_STATE + #define YY_STRUCT_YY_BUFFER_STATE + struct yy_buffer_state +@@ -223,7 +224,7 @@ struct yy_buffer_state + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ +- int yy_n_chars; ++ yy_size_t yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to +@@ -302,7 +303,7 @@ static void pp_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner ); + + YY_BUFFER_STATE pp_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner ); + YY_BUFFER_STATE pp_scan_string (yyconst char *yy_str ,yyscan_t yyscanner ); +-YY_BUFFER_STATE pp_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner ); ++YY_BUFFER_STATE pp_scan_bytes (yyconst char *bytes,yy_size_t len ,yyscan_t yyscanner ); + + void *ppalloc (yy_size_t ,yyscan_t yyscanner ); + void *pprealloc (void *,yy_size_t ,yyscan_t yyscanner ); +@@ -353,7 +354,7 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner ); + */ + #define YY_DO_BEFORE_ACTION \ + yyg->yytext_ptr = yy_bp; \ +- yyleng = (size_t) (yy_cp - yy_bp); \ ++ yyleng = (yy_size_t) (yy_cp - yy_bp); \ + yyg->yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yyg->yy_c_buf_p = yy_cp; +@@ -579,8 +580,8 @@ struct yyguts_t + size_t yy_buffer_stack_max; /**< capacity of stack. */ + YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */ + char yy_hold_char; +- int yy_n_chars; +- int yyleng_r; ++ yy_size_t yy_n_chars; ++ yy_size_t yyleng_r; + char *yy_c_buf_p; + int yy_init; + int yy_start; +@@ -637,7 +638,7 @@ FILE *ppget_out (yyscan_t yyscanner ); + + void ppset_out (FILE * out_str ,yyscan_t yyscanner ); + +-int ppget_leng (yyscan_t yyscanner ); ++yy_size_t ppget_leng (yyscan_t yyscanner ); + + char *ppget_text (yyscan_t yyscanner ); + +@@ -704,7 +705,7 @@ static int input (yyscan_t yyscanner ); + if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ + { \ + int c = '*'; \ +- int n; \ ++ yy_size_t n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ +@@ -1338,7 +1339,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) + + else + { +- int num_to_read = ++ yy_size_t num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) +@@ -1352,7 +1353,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) + + if ( b->yy_is_our_buffer ) + { +- int new_size = b->yy_buf_size * 2; ++ yy_size_t new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; +@@ -1383,7 +1384,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), +- yyg->yy_n_chars, (size_t) num_to_read ); ++ yyg->yy_n_chars, num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } +@@ -1508,7 +1509,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) + + else + { /* need more input */ +- int offset = yyg->yy_c_buf_p - yyg->yytext_ptr; ++ yy_size_t offset = yyg->yy_c_buf_p - yyg->yytext_ptr; + ++yyg->yy_c_buf_p; + + switch ( yy_get_next_buffer( yyscanner ) ) +@@ -1788,7 +1789,7 @@ void pppop_buffer_state (yyscan_t yyscanner) + */ + static void ppensure_buffer_stack (yyscan_t yyscanner) + { +- int num_to_alloc; ++ yy_size_t num_to_alloc; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if (!yyg->yy_buffer_stack) { +@@ -1886,12 +1887,11 @@ YY_BUFFER_STATE pp_scan_string (yyconst char * yystr , yyscan_t yyscanner) + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + */ +-YY_BUFFER_STATE pp_scan_bytes (yyconst char * yybytes, int _yybytes_len , yyscan_t yyscanner) ++YY_BUFFER_STATE pp_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len , yyscan_t yyscanner) + { + YY_BUFFER_STATE b; + char *buf; +- yy_size_t n; +- int i; ++ yy_size_t n, i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = _yybytes_len + 2; +@@ -2001,7 +2001,7 @@ FILE *ppget_out (yyscan_t yyscanner) + /** Get the length of the current token. + * @param yyscanner The scanner object. + */ +-int ppget_leng (yyscan_t yyscanner) ++yy_size_t ppget_leng (yyscan_t yyscanner) + { + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyleng; diff --git a/gfx/angle/src/compiler/preprocessor/ExpressionParser.cpp b/gfx/angle/src/compiler/preprocessor/ExpressionParser.cpp index 4c4225dcd13c..67966e95de62 100644 --- a/gfx/angle/src/compiler/preprocessor/ExpressionParser.cpp +++ b/gfx/angle/src/compiler/preprocessor/ExpressionParser.cpp @@ -1,9 +1,8 @@ -/* A Bison parser, made by GNU Bison 2.4.2. */ +/* A Bison parser, made by GNU Bison 2.7. */ -/* Skeleton implementation for Bison's Yacc-like parsers in C +/* Bison implementation for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2006, 2009-2010 Free Software - Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -45,7 +44,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "2.4.2" +#define YYBISON_VERSION "2.7" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -59,8 +58,6 @@ /* Pull parsers. */ #define YYPULL 1 -/* Using locations. */ -#define YYLSP_NEEDED 0 /* Substitute the variable and function names. */ #define yyparse ppparse @@ -71,7 +68,6 @@ #define yydebug ppdebug #define yynerrs ppnerrs - /* Copy the first part of user declarations. */ @@ -130,10 +126,13 @@ static void yyerror(Context* context, const char* reason); -/* Enabling traces. */ -#ifndef YYDEBUG -# define YYDEBUG 0 -#endif +# ifndef YY_NULL +# if defined __cplusplus && 201103L <= __cplusplus +# define YY_NULL nullptr +# else +# define YY_NULL 0 +# endif +# endif /* Enabling verbose error messages. */ #ifdef YYERROR_VERBOSE @@ -143,11 +142,14 @@ static void yyerror(Context* context, const char* reason); # define YYERROR_VERBOSE 0 #endif -/* Enabling the token table. */ -#ifndef YYTOKEN_TABLE -# define YYTOKEN_TABLE 0 -#endif +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif +#if YYDEBUG +extern int ppdebug; +#endif /* Tokens. */ #ifndef YYTOKENTYPE @@ -169,7 +171,6 @@ static void yyerror(Context* context, const char* reason); #endif - #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef int YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 @@ -178,6 +179,22 @@ typedef int YYSTYPE; #endif +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int ppparse (void *YYPARSE_PARAM); +#else +int ppparse (); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int ppparse (Context *context); +#else +int ppparse (); +#endif +#endif /* ! YYPARSE_PARAM */ + + + /* Copy the second part of user declarations. */ @@ -233,24 +250,24 @@ typedef short int yytype_int16; # if defined YYENABLE_NLS && YYENABLE_NLS # if ENABLE_NLS # include /* INFRINGES ON USER NAME SPACE */ -# define YY_(msgid) dgettext ("bison-runtime", msgid) +# define YY_(Msgid) dgettext ("bison-runtime", Msgid) # endif # endif # ifndef YY_ -# define YY_(msgid) msgid +# define YY_(Msgid) Msgid # endif #endif /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ -# define YYUSE(e) ((void) (e)) +# define YYUSE(E) ((void) (E)) #else -# define YYUSE(e) /* empty */ +# define YYUSE(E) /* empty */ #endif /* Identity function, used to suppress warnings about constant conditions. */ #ifndef lint -# define YYID(n) (n) +# define YYID(N) (N) #else #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) @@ -283,11 +300,12 @@ YYID (yyi) # define alloca _alloca # else # define YYSTACK_ALLOC alloca -# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ +# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ -# ifndef _STDLIB_H -# define _STDLIB_H 1 + /* Use EXIT_SUCCESS as a witness for stdlib.h. */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 # endif # endif # endif @@ -310,24 +328,24 @@ YYID (yyi) # ifndef YYSTACK_ALLOC_MAXIMUM # define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM # endif -# if (defined __cplusplus && ! defined _STDLIB_H \ +# if (defined __cplusplus && ! defined EXIT_SUCCESS \ && ! ((defined YYMALLOC || defined malloc) \ && (defined YYFREE || defined free))) # include /* INFRINGES ON USER NAME SPACE */ -# ifndef _STDLIB_H -# define _STDLIB_H 1 +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 # endif # endif # ifndef YYMALLOC # define YYMALLOC malloc -# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ +# if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef YYFREE # define YYFREE free -# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ +# if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif @@ -356,23 +374,7 @@ union yyalloc ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + YYSTACK_GAP_MAXIMUM) -/* Copy COUNT objects from FROM to TO. The source and destination do - not overlap. */ -# ifndef YYCOPY -# if defined __GNUC__ && 1 < __GNUC__ -# define YYCOPY(To, From, Count) \ - __builtin_memcpy (To, From, (Count) * sizeof (*(From))) -# else -# define YYCOPY(To, From, Count) \ - do \ - { \ - YYSIZE_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (To)[yyi] = (From)[yyi]; \ - } \ - while (YYID (0)) -# endif -# endif +# define YYCOPY_NEEDED 1 /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of @@ -392,6 +394,26 @@ union yyalloc #endif +#if defined YYCOPY_NEEDED && YYCOPY_NEEDED +/* Copy COUNT objects from SRC to DST. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(Dst, Src, Count) \ + __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) +# else +# define YYCOPY(Dst, Src, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (Dst)[yyi] = (Src)[yyi]; \ + } \ + while (YYID (0)) +# endif +# endif +#endif /* !YYCOPY_NEEDED */ + /* YYFINAL -- State number of the termination state. */ #define YYFINAL 14 /* YYLAST -- Last index in YYTABLE. */ @@ -473,13 +495,13 @@ static const yytype_int8 yyrhs[] = /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint8 yyrline[] = { - 0, 90, 90, 97, 98, 101, 104, 107, 110, 113, - 116, 119, 122, 125, 128, 131, 134, 137, 140, 143, - 156, 169, 172, 175, 178, 181, 184 + 0, 91, 91, 98, 99, 102, 105, 108, 111, 114, + 117, 120, 123, 126, 129, 132, 135, 138, 141, 144, + 157, 170, 173, 176, 179, 182, 185 }; #endif -#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE +#if YYDEBUG || YYERROR_VERBOSE || 0 /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = @@ -488,7 +510,7 @@ static const char *const yytname[] = "TOK_OP_AND", "'|'", "'^'", "'&'", "TOK_OP_NE", "TOK_OP_EQ", "'<'", "'>'", "TOK_OP_GE", "TOK_OP_LE", "TOK_OP_RIGHT", "TOK_OP_LEFT", "'+'", "'-'", "'*'", "'/'", "'%'", "TOK_UNARY", "'!'", "'~'", "'('", "')'", - "$accept", "input", "expression", 0 + "$accept", "input", "expression", YY_NULL }; #endif @@ -519,8 +541,8 @@ static const yytype_uint8 yyr2[] = 3, 3, 2, 2, 2, 2, 3 }; -/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state - STATE-NUM when YYTABLE doesn't specify something else to do. Zero +/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM. + Performed when YYTABLE doesn't specify something else to do. Zero means the default is an error. */ static const yytype_uint8 yydefact[] = { @@ -559,8 +581,7 @@ static const yytype_int8 yypgoto[] = /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which - number is the opposite. If zero, do what YYDEFACT says. - If YYTABLE_NINF, syntax error. */ + number is the opposite. If YYTABLE_NINF, syntax error. */ #define YYTABLE_NINF -1 static const yytype_uint8 yytable[] = { @@ -584,6 +605,12 @@ static const yytype_uint8 yytable[] = 27, 28, 29, 30, 31, 32 }; +#define yypact_value_is_default(Yystate) \ + (!!((Yystate) == (-11))) + +#define yytable_value_is_error(Yytable_value) \ + YYID (0) + static const yytype_int8 yycheck[] = { 2, 3, 4, 5, 6, 15, 16, 17, 18, 19, @@ -645,72 +672,35 @@ static const yytype_uint8 yystos[] = #define YYRECOVERING() (!!yyerrstatus) -#define YYBACKUP(Token, Value) \ -do \ - if (yychar == YYEMPTY && yylen == 1) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - yytoken = YYTRANSLATE (yychar); \ - YYPOPSTACK (1); \ - goto yybackup; \ - } \ - else \ - { \ +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + YYPOPSTACK (yylen); \ + yystate = *yyssp; \ + goto yybackup; \ + } \ + else \ + { \ yyerror (context, YY_("syntax error: cannot back up")); \ YYERROR; \ } \ while (YYID (0)) - +/* Error token number */ #define YYTERROR 1 #define YYERRCODE 256 -/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. - If N is 0, then set CURRENT to the empty location which ends - the previous symbol: RHS[0] (always defined). */ - -#define YYRHSLOC(Rhs, K) ((Rhs)[K]) -#ifndef YYLLOC_DEFAULT -# define YYLLOC_DEFAULT(Current, Rhs, N) \ - do \ - if (YYID (N)) \ - { \ - (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ - (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ - (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ - (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ - } \ - else \ - { \ - (Current).first_line = (Current).last_line = \ - YYRHSLOC (Rhs, 0).last_line; \ - (Current).first_column = (Current).last_column = \ - YYRHSLOC (Rhs, 0).last_column; \ - } \ - while (YYID (0)) -#endif - - -/* YY_LOCATION_PRINT -- Print the location on the stream. - This macro was not mandated originally: define only if we know - we won't break user code: when these are the locations we know. */ - +/* This macro is provided for backward compatibility. */ #ifndef YY_LOCATION_PRINT -# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL -# define YY_LOCATION_PRINT(File, Loc) \ - fprintf (File, "%d.%d-%d.%d", \ - (Loc).first_line, (Loc).first_column, \ - (Loc).last_line, (Loc).last_column) -# else -# define YY_LOCATION_PRINT(File, Loc) ((void) 0) -# endif +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) #endif /* YYLEX -- calling `yylex' with the right arguments. */ - #ifdef YYLEX_PARAM # define YYLEX yylex (&yylval, YYLEX_PARAM) #else @@ -761,6 +751,8 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep, context) Context *context; #endif { + FILE *yyo = yyoutput; + YYUSE (yyo); if (!yyvaluep) return; YYUSE (context); @@ -773,7 +765,7 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep, context) switch (yytype) { default: - break; + break; } } @@ -901,7 +893,6 @@ int yydebug; # define YYMAXDEPTH 10000 #endif - #if YYERROR_VERBOSE @@ -1004,115 +995,145 @@ yytnamerr (char *yyres, const char *yystr) } # endif -/* Copy into YYRESULT an error message about the unexpected token - YYCHAR while in state YYSTATE. Return the number of bytes copied, - including the terminating null byte. If YYRESULT is null, do not - copy anything; just return the number of bytes that would be - copied. As a special case, return 0 if an ordinary "syntax error" - message will do. Return YYSIZE_MAXIMUM if overflow occurs during - size calculation. */ -static YYSIZE_T -yysyntax_error (char *yyresult, int yystate, int yychar) +/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message + about the unexpected token YYTOKEN for the state stack whose top is + YYSSP. + + Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is + not large enough to hold the message. In that case, also set + *YYMSG_ALLOC to the required number of bytes. Return 2 if the + required number of bytes is too large to store. */ +static int +yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, + yytype_int16 *yyssp, int yytoken) { - int yyn = yypact[yystate]; + YYSIZE_T yysize0 = yytnamerr (YY_NULL, yytname[yytoken]); + YYSIZE_T yysize = yysize0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + /* Internationalized format string. */ + const char *yyformat = YY_NULL; + /* Arguments of yyformat. */ + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + /* Number of reported tokens (one for the "unexpected", one per + "expected"). */ + int yycount = 0; - if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) - return 0; - else + /* There are many possibilities here to consider: + - Assume YYFAIL is not used. It's too flawed to consider. See + + for details. YYERROR is fine as it does not invoke this + function. + - If this state is a consistent state with a default action, then + the only way this function was invoked is if the default action + is an error action. In that case, don't check for expected + tokens because there are none. + - The only way there can be no lookahead present (in yychar) is if + this state is a consistent state with a default action. Thus, + detecting the absence of a lookahead is sufficient to determine + that there is no unexpected or expected token to report. In that + case, just report a simple "syntax error". + - Don't assume there isn't a lookahead just because this state is a + consistent state with a default action. There might have been a + previous inconsistent state, consistent state with a non-default + action, or user semantic action that manipulated yychar. + - Of course, the expected token list depends on states to have + correct lookahead information, and it depends on the parser not + to perform extra reductions after fetching a lookahead from the + scanner and before detecting a syntax error. Thus, state merging + (from LALR or IELR) and default reductions corrupt the expected + token list. However, the list is correct for canonical LR with + one exception: it will still contain any token that will not be + accepted due to an error action in a later state. + */ + if (yytoken != YYEMPTY) { - int yytype = YYTRANSLATE (yychar); - YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); - YYSIZE_T yysize = yysize0; - YYSIZE_T yysize1; - int yysize_overflow = 0; - enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; - char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; - int yyx; + int yyn = yypact[*yyssp]; + yyarg[yycount++] = yytname[yytoken]; + if (!yypact_value_is_default (yyn)) + { + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. In other words, skip the first -YYN actions for + this state because they are default actions. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yyx; -# if 0 - /* This is so xgettext sees the translatable formats that are - constructed on the fly. */ - YY_("syntax error, unexpected %s"); - YY_("syntax error, unexpected %s, expecting %s"); - YY_("syntax error, unexpected %s, expecting %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); -# endif - char *yyfmt; - char const *yyf; - static char const yyunexpected[] = "syntax error, unexpected %s"; - static char const yyexpecting[] = ", expecting %s"; - static char const yyor[] = " or %s"; - char yyformat[sizeof yyunexpected - + sizeof yyexpecting - 1 - + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) - * (sizeof yyor - 1))]; - char const *yyprefix = yyexpecting; - - /* Start YYX at -YYN if negative to avoid negative indexes in - YYCHECK. */ - int yyxbegin = yyn < 0 ? -yyn : 0; - - /* Stay within bounds of both yycheck and yytname. */ - int yychecklim = YYLAST - yyn + 1; - int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; - int yycount = 1; - - yyarg[0] = yytname[yytype]; - yyfmt = yystpcpy (yyformat, yyunexpected); - - for (yyx = yyxbegin; yyx < yyxend; ++yyx) - if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) - { - if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) - { - yycount = 1; - yysize = yysize0; - yyformat[sizeof yyunexpected - 1] = '\0'; - break; - } - yyarg[yycount++] = yytname[yyx]; - yysize1 = yysize + yytnamerr (0, yytname[yyx]); - yysize_overflow |= (yysize1 < yysize); - yysize = yysize1; - yyfmt = yystpcpy (yyfmt, yyprefix); - yyprefix = yyor; - } - - yyf = YY_(yyformat); - yysize1 = yysize + yystrlen (yyf); - yysize_overflow |= (yysize1 < yysize); - yysize = yysize1; - - if (yysize_overflow) - return YYSIZE_MAXIMUM; - - if (yyresult) - { - /* Avoid sprintf, as that infringes on the user's name space. - Don't have undefined behavior even if the translation - produced a string with the wrong number of "%s"s. */ - char *yyp = yyresult; - int yyi = 0; - while ((*yyp = *yyf) != '\0') - { - if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) - { - yyp += yytnamerr (yyp, yyarg[yyi++]); - yyf += 2; - } - else - { - yyp++; - yyf++; - } - } - } - return yysize; + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR + && !yytable_value_is_error (yytable[yyx + yyn])) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + break; + } + yyarg[yycount++] = yytname[yyx]; + { + YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULL, yytname[yyx]); + if (! (yysize <= yysize1 + && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } + } + } } + + switch (yycount) + { +# define YYCASE_(N, S) \ + case N: \ + yyformat = S; \ + break + YYCASE_(0, YY_("syntax error")); + YYCASE_(1, YY_("syntax error, unexpected %s")); + YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); + YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); + YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); + YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); +# undef YYCASE_ + } + + { + YYSIZE_T yysize1 = yysize + yystrlen (yyformat); + if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } + + if (*yymsg_alloc < yysize) + { + *yymsg_alloc = 2 * yysize; + if (! (yysize <= *yymsg_alloc + && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) + *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; + return 1; + } + + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + { + char *yyp = *yymsg; + int yyi = 0; + while ((*yyp = *yyformat) != '\0') + if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyformat += 2; + } + else + { + yyp++; + yyformat++; + } + } + return 0; } #endif /* YYERROR_VERBOSE */ - /*-----------------------------------------------. | Release the memory associated to this symbol. | @@ -1143,32 +1164,16 @@ yydestruct (yymsg, yytype, yyvaluep, context) { default: - break; + break; } } -/* Prevent warnings from -Wmissing-prototypes. */ -#ifdef YYPARSE_PARAM -#if defined __STDC__ || defined __cplusplus -int yyparse (void *YYPARSE_PARAM); -#else -int yyparse (); -#endif -#else /* ! YYPARSE_PARAM */ -#if defined __STDC__ || defined __cplusplus -int yyparse (Context *context); -#else -int yyparse (); -#endif -#endif /* ! YYPARSE_PARAM */ - - -/*-------------------------. -| yyparse or yypush_parse. | -`-------------------------*/ +/*----------. +| yyparse. | +`----------*/ #ifdef YYPARSE_PARAM #if (defined __STDC__ || defined __C99__FUNC__ \ @@ -1195,8 +1200,31 @@ yyparse (context) /* The lookahead symbol. */ int yychar; + +#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ +/* Suppress an incorrect diagnostic about yylval being uninitialized. */ +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\ + _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ + _Pragma ("GCC diagnostic pop") +#else +/* Default value used for initialization, for pacifying older GCCs + or non-GCC compilers. */ +static YYSTYPE yyval_default; +# define YY_INITIAL_VALUE(Value) = Value +#endif +#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_END +#endif +#ifndef YY_INITIAL_VALUE +# define YY_INITIAL_VALUE(Value) /* Nothing. */ +#endif + /* The semantic value of the lookahead symbol. */ -YYSTYPE yylval; +YYSTYPE yylval YY_INITIAL_VALUE(yyval_default); /* Number of syntax errors so far. */ int yynerrs; @@ -1209,7 +1237,7 @@ YYSTYPE yylval; `yyss': related to states. `yyvs': related to semantic values. - Refer to the stacks thru separate pointers, to allow yyoverflow + Refer to the stacks through separate pointers, to allow yyoverflow to reallocate them elsewhere. */ /* The state stack. */ @@ -1227,7 +1255,7 @@ YYSTYPE yylval; int yyn; int yyresult; /* Lookahead token as an internal (translated) token number. */ - int yytoken; + int yytoken = 0; /* The variables used to return semantic value and location from the action routines. */ YYSTYPE yyval; @@ -1245,9 +1273,8 @@ YYSTYPE yylval; Keep to zero when no symbol should be popped. */ int yylen = 0; - yytoken = 0; - yyss = yyssa; - yyvs = yyvsa; + yyssp = yyss = yyssa; + yyvsp = yyvs = yyvsa; yystacksize = YYINITDEPTH; YYDPRINTF ((stderr, "Starting parse\n")); @@ -1256,14 +1283,6 @@ YYSTYPE yylval; yyerrstatus = 0; yynerrs = 0; yychar = YYEMPTY; /* Cause a token to be read. */ - - /* Initialize stack pointers. - Waste one element of value and location stack - so that they stay on the same level as the state stack. - The wasted elements are never initialized. */ - yyssp = yyss; - yyvsp = yyvs; - goto yysetstate; /*------------------------------------------------------------. @@ -1355,7 +1374,7 @@ yybackup: /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; - if (yyn == YYPACT_NINF) + if (yypact_value_is_default (yyn)) goto yydefault; /* Not known => get a lookahead token if don't already have one. */ @@ -1386,8 +1405,8 @@ yybackup: yyn = yytable[yyn]; if (yyn <= 0) { - if (yyn == 0 || yyn == YYTABLE_NINF) - goto yyerrlab; + if (yytable_value_is_error (yyn)) + goto yyerrlab; yyn = -yyn; goto yyreduce; } @@ -1404,7 +1423,9 @@ yybackup: yychar = YYEMPTY; yystate = yyn; + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END goto yynewstate; @@ -1633,6 +1654,17 @@ yyreduce: default: break; } + /* User semantic actions sometimes alter yychar, and that requires + that yytoken be updated with the new translation. We take the + approach of translating immediately before every use of yytoken. + One alternative is translating here after every semantic action, + but that translation would be missed if the semantic action invokes + YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or + if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an + incorrect destructor might then be invoked immediately. In the + case of YYERROR or YYBACKUP, subsequent parser actions might lead + to an incorrect destructor call or verbose syntax error message + before the lookahead is translated. */ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); YYPOPSTACK (yylen); @@ -1660,6 +1692,10 @@ yyreduce: | yyerrlab -- here on detecting error | `------------------------------------*/ yyerrlab: + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); + /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { @@ -1667,37 +1703,36 @@ yyerrlab: #if ! YYERROR_VERBOSE yyerror (context, YY_("syntax error")); #else +# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ + yyssp, yytoken) { - YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); - if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) - { - YYSIZE_T yyalloc = 2 * yysize; - if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) - yyalloc = YYSTACK_ALLOC_MAXIMUM; - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); - yymsg = (char *) YYSTACK_ALLOC (yyalloc); - if (yymsg) - yymsg_alloc = yyalloc; - else - { - yymsg = yymsgbuf; - yymsg_alloc = sizeof yymsgbuf; - } - } - - if (0 < yysize && yysize <= yymsg_alloc) - { - (void) yysyntax_error (yymsg, yystate, yychar); - yyerror (context, yymsg); - } - else - { - yyerror (context, YY_("syntax error")); - if (yysize != 0) - goto yyexhaustedlab; - } + char const *yymsgp = YY_("syntax error"); + int yysyntax_error_status; + yysyntax_error_status = YYSYNTAX_ERROR; + if (yysyntax_error_status == 0) + yymsgp = yymsg; + else if (yysyntax_error_status == 1) + { + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); + if (!yymsg) + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + yysyntax_error_status = 2; + } + else + { + yysyntax_error_status = YYSYNTAX_ERROR; + yymsgp = yymsg; + } + } + yyerror (context, yymsgp); + if (yysyntax_error_status == 2) + goto yyexhaustedlab; } +# undef YYSYNTAX_ERROR #endif } @@ -1756,7 +1791,7 @@ yyerrlab1: for (;;) { yyn = yypact[yystate]; - if (yyn != YYPACT_NINF) + if (!yypact_value_is_default (yyn)) { yyn += YYTERROR; if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) @@ -1779,7 +1814,9 @@ yyerrlab1: YY_STACK_PRINT (yyss, yyssp); } + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END /* Shift the error token. */ @@ -1803,7 +1840,7 @@ yyabortlab: yyresult = 1; goto yyreturn; -#if !defined(yyoverflow) || YYERROR_VERBOSE +#if !defined yyoverflow || YYERROR_VERBOSE /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ @@ -1815,8 +1852,13 @@ yyexhaustedlab: yyreturn: if (yychar != YYEMPTY) - yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval, context); + { + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = YYTRANSLATE (yychar); + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval, context); + } /* Do not reclaim the symbols of the rule which action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); @@ -1937,4 +1979,3 @@ bool ExpressionParser::parse(Token* token, int* result) } } // namespace pp - diff --git a/gfx/angle/src/compiler/preprocessor/Tokenizer.cpp b/gfx/angle/src/compiler/preprocessor/Tokenizer.cpp index 66e0f3cc890f..6f426780c0cf 100644 --- a/gfx/angle/src/compiler/preprocessor/Tokenizer.cpp +++ b/gfx/angle/src/compiler/preprocessor/Tokenizer.cpp @@ -1,6 +1,6 @@ #line 16 "./Tokenizer.l" // -// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2011-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -359,8 +359,8 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner ); *yy_cp = '\0'; \ yyg->yy_c_buf_p = yy_cp; -#define YY_NUM_RULES 37 -#define YY_END_OF_BUFFER 38 +#define YY_NUM_RULES 38 +#define YY_END_OF_BUFFER 39 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info @@ -368,17 +368,17 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static yyconst flex_int16_t yy_accept[84] = +static yyconst flex_int16_t yy_accept[87] = { 0, - 0, 0, 0, 0, 38, 36, 34, 35, 35, 33, + 0, 0, 0, 0, 39, 37, 34, 35, 35, 33, 7, 33, 33, 33, 33, 33, 33, 33, 33, 9, - 9, 33, 33, 33, 8, 33, 33, 3, 5, 5, - 4, 34, 35, 19, 27, 20, 30, 25, 12, 23, - 13, 24, 10, 2, 1, 26, 10, 9, 11, 11, - 11, 11, 9, 14, 16, 18, 17, 15, 8, 31, - 21, 32, 22, 3, 5, 6, 11, 10, 11, 1, - 10, 11, 0, 10, 9, 28, 29, 0, 10, 10, - 10, 10, 0 + 9, 33, 33, 33, 8, 37, 33, 33, 3, 5, + 5, 4, 34, 35, 19, 27, 20, 30, 25, 12, + 23, 13, 24, 10, 2, 1, 26, 10, 9, 11, + 11, 11, 11, 9, 14, 16, 18, 17, 15, 8, + 36, 36, 31, 21, 32, 22, 3, 5, 6, 11, + 10, 11, 1, 10, 11, 0, 10, 9, 28, 29, + 0, 10, 10, 10, 10, 0 } ; static yyconst flex_int32_t yy_ec[256] = @@ -392,11 +392,11 @@ static yyconst flex_int32_t yy_ec[256] = 19, 20, 9, 1, 21, 21, 21, 21, 22, 21, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 23, 23, - 9, 1, 9, 25, 23, 1, 21, 21, 21, 21, + 9, 25, 9, 26, 23, 1, 21, 21, 21, 21, 22, 21, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, - 23, 23, 9, 26, 9, 9, 1, 1, 1, 1, + 23, 23, 9, 27, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -413,85 +413,89 @@ static yyconst flex_int32_t yy_ec[256] = 1, 1, 1, 1, 1 } ; -static yyconst flex_int32_t yy_meta[27] = +static yyconst flex_int32_t yy_meta[28] = { 0, 1, 1, 2, 2, 1, 1, 1, 1, 1, 3, 1, 1, 4, 1, 5, 5, 5, 1, 1, 1, - 5, 5, 5, 5, 1, 1 + 5, 5, 5, 5, 1, 1, 1 } ; -static yyconst flex_int16_t yy_base[89] = +static yyconst flex_int16_t yy_base[92] = { 0, - 0, 0, 24, 26, 158, 159, 150, 159, 145, 128, - 159, 112, 23, 159, 111, 21, 25, 30, 29, 36, - 46, 36, 100, 45, 0, 16, 47, 0, 159, 84, - 65, 73, 159, 159, 159, 159, 159, 159, 159, 159, - 159, 159, 61, 159, 0, 159, 73, 32, 56, 83, - 95, 68, 0, 31, 159, 159, 159, 19, 0, 159, - 159, 159, 159, 0, 159, 159, 98, 0, 110, 0, - 0, 117, 52, 90, 80, 159, 159, 101, 97, 112, - 120, 123, 159, 140, 28, 145, 150, 152 + 0, 0, 25, 27, 162, 163, 159, 163, 152, 132, + 163, 131, 24, 163, 116, 22, 26, 31, 30, 37, + 40, 44, 115, 46, 0, 64, 50, 15, 0, 163, + 124, 91, 88, 163, 163, 163, 163, 163, 163, 163, + 163, 163, 163, 64, 163, 0, 163, 76, 54, 58, + 79, 91, 91, 0, 56, 163, 163, 163, 32, 0, + 163, 36, 163, 163, 163, 163, 0, 163, 163, 94, + 0, 106, 0, 0, 113, 55, 72, 113, 163, 163, + 116, 101, 108, 123, 126, 163, 143, 31, 148, 153, + 155 + } ; -static yyconst flex_int16_t yy_def[89] = +static yyconst flex_int16_t yy_def[92] = { 0, - 83, 1, 84, 84, 83, 83, 83, 83, 83, 83, - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - 20, 83, 83, 83, 85, 83, 83, 86, 83, 83, - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - 83, 83, 83, 83, 87, 83, 83, 20, 20, 47, - 50, 88, 21, 83, 83, 83, 83, 83, 85, 83, - 83, 83, 83, 86, 83, 83, 43, 43, 67, 87, - 47, 50, 83, 51, 88, 83, 83, 83, 69, 72, - 83, 83, 0, 83, 83, 83, 83, 83 + 86, 1, 87, 87, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 20, 86, 86, 86, 88, 86, 86, 86, 89, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 90, 86, 86, 20, 20, + 48, 51, 91, 21, 86, 86, 86, 86, 86, 88, + 86, 86, 86, 86, 86, 86, 89, 86, 86, 44, + 44, 70, 90, 48, 51, 86, 52, 91, 86, 86, + 86, 72, 75, 86, 86, 0, 86, 86, 86, 86, + 86 + } ; -static yyconst flex_int16_t yy_nxt[186] = +static yyconst flex_int16_t yy_nxt[191] = { 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 21, 22, 23, 24, - 25, 25, 25, 25, 26, 27, 29, 30, 29, 30, - 36, 39, 59, 31, 60, 31, 41, 77, 44, 40, - 61, 37, 45, 42, 43, 43, 43, 46, 47, 76, - 48, 48, 49, 54, 55, 50, 50, 51, 50, 52, - 53, 53, 53, 57, 58, 62, 81, 81, 81, 50, - 49, 49, 63, 67, 32, 68, 68, 68, 66, 50, - 50, 67, 69, 67, 67, 50, 65, 71, 71, 71, - 50, 50, 50, 50, 72, 50, 50, 50, 50, 50, + 25, 25, 25, 25, 26, 27, 28, 30, 31, 30, + 31, 37, 40, 65, 32, 60, 32, 42, 61, 45, + 41, 66, 38, 46, 43, 44, 44, 44, 47, 48, + 80, 49, 49, 50, 54, 54, 54, 51, 52, 51, + 53, 55, 56, 51, 58, 59, 61, 62, 63, 84, + 84, 84, 50, 50, 79, 64, 70, 51, 71, 71, + 71, 51, 86, 86, 70, 72, 70, 70, 51, 33, + 74, 74, 74, 51, 51, 51, 51, 75, 51, 51, - 83, 83, 50, 50, 50, 73, 73, 83, 83, 74, - 74, 74, 67, 67, 67, 82, 82, 82, 56, 67, - 78, 78, 83, 83, 79, 79, 79, 78, 78, 38, - 35, 80, 80, 80, 81, 81, 81, 82, 82, 82, - 28, 28, 28, 28, 28, 64, 34, 33, 64, 64, - 70, 32, 70, 70, 70, 75, 75, 83, 5, 83, - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - 83, 83, 83, 83, 83 + 51, 76, 76, 51, 69, 77, 77, 77, 70, 70, + 70, 86, 86, 51, 51, 70, 81, 81, 86, 86, + 82, 82, 82, 81, 81, 51, 68, 83, 83, 83, + 85, 85, 85, 57, 39, 51, 51, 84, 84, 84, + 85, 85, 85, 29, 29, 29, 29, 29, 67, 36, + 35, 67, 67, 73, 34, 73, 73, 73, 78, 78, + 33, 86, 5, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86 } ; -static yyconst flex_int16_t yy_chk[186] = +static yyconst flex_int16_t yy_chk[191] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 3, 3, 4, 4, - 13, 16, 85, 3, 26, 4, 17, 58, 19, 16, - 26, 13, 19, 17, 18, 18, 18, 19, 20, 54, - 20, 20, 20, 22, 22, 48, 20, 20, 20, 20, - 21, 21, 21, 24, 24, 27, 73, 73, 73, 21, - 49, 49, 27, 43, 32, 43, 43, 43, 31, 49, - 52, 43, 43, 43, 43, 47, 30, 47, 47, 47, - 52, 52, 75, 47, 47, 47, 47, 50, 50, 50, + 1, 1, 1, 1, 1, 1, 1, 3, 3, 4, + 4, 13, 16, 28, 3, 88, 4, 17, 62, 19, + 16, 28, 13, 19, 17, 18, 18, 18, 19, 20, + 59, 20, 20, 20, 21, 21, 21, 20, 20, 20, + 20, 22, 22, 21, 24, 24, 26, 26, 27, 76, + 76, 76, 50, 50, 55, 27, 44, 49, 44, 44, + 44, 50, 77, 77, 44, 44, 44, 44, 48, 33, + 48, 48, 48, 51, 51, 51, 48, 48, 48, 48, - 74, 74, 75, 75, 50, 51, 51, 79, 79, 51, - 51, 51, 67, 67, 67, 78, 78, 78, 23, 67, - 69, 69, 80, 80, 69, 69, 69, 72, 72, 15, - 12, 72, 72, 72, 81, 81, 81, 82, 82, 82, - 84, 84, 84, 84, 84, 86, 10, 9, 86, 86, - 87, 7, 87, 87, 87, 88, 88, 5, 83, 83, - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - 83, 83, 83, 83, 83 + 51, 52, 52, 53, 32, 52, 52, 52, 70, 70, + 70, 82, 82, 53, 53, 70, 72, 72, 83, 83, + 72, 72, 72, 75, 75, 78, 31, 75, 75, 75, + 81, 81, 81, 23, 15, 78, 78, 84, 84, 84, + 85, 85, 85, 87, 87, 87, 87, 87, 89, 12, + 10, 89, 89, 90, 9, 90, 90, 90, 91, 91, + 7, 5, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86 } ; /* The intent behind this definition is that it'll catch @@ -503,7 +507,7 @@ static yyconst flex_int16_t yy_chk[186] = #define YY_RESTORE_YY_MORE_OFFSET /* // -// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -843,13 +847,13 @@ yy_match: while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 84 ) + if ( yy_current_state >= 87 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } - while ( yy_current_state != 83 ); + while ( yy_current_state != 86 ); yy_cp = yyg->yy_last_accepting_cpos; yy_current_state = yyg->yy_last_accepting_state; @@ -1106,6 +1110,11 @@ YY_RULE_SETUP } YY_BREAK case 36: +/* rule 36 can match eol */ +YY_RULE_SETUP +{ ++yylineno; } + YY_BREAK +case 37: YY_RULE_SETUP { yylval->assign(1, yytext[0]); @@ -1141,7 +1150,7 @@ case YY_STATE_EOF(COMMENT): yyterminate(); } YY_BREAK -case 37: +case 38: YY_RULE_SETUP ECHO; YY_BREAK @@ -1437,7 +1446,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 84 ) + if ( yy_current_state >= 87 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; @@ -1466,11 +1475,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 84 ) + if ( yy_current_state >= 87 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - yy_is_jam = (yy_current_state == 83); + yy_is_jam = (yy_current_state == 86); return yy_is_jam ? 0 : yy_current_state; } @@ -1524,7 +1533,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) case EOB_ACT_END_OF_FILE: { if ( ppwrap(yyscanner ) ) - return 0; + return EOF; if ( ! yyg->yy_did_buffer_switch_on_eof ) YY_NEW_FILE; diff --git a/gfx/angle/src/compiler/preprocessor/Tokenizer.l b/gfx/angle/src/compiler/preprocessor/Tokenizer.l index cdefd204e4b5..fc81d84f373f 100644 --- a/gfx/angle/src/compiler/preprocessor/Tokenizer.l +++ b/gfx/angle/src/compiler/preprocessor/Tokenizer.l @@ -1,6 +1,6 @@ /* // -// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -14,7 +14,7 @@ IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh. %top{ // -// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2011-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -229,6 +229,8 @@ FRACTIONAL_CONSTANT ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".") return '\n'; } +\\{NEWLINE} { ++yylineno; } + . { yylval->assign(1, yytext[0]); return pp::Token::PP_OTHER; diff --git a/gfx/angle/src/compiler/preprocessor/generate_parser.sh b/gfx/angle/src/compiler/preprocessor/generate_parser.sh index e9c70b13b535..03285872204c 100644 --- a/gfx/angle/src/compiler/preprocessor/generate_parser.sh +++ b/gfx/angle/src/compiler/preprocessor/generate_parser.sh @@ -24,3 +24,4 @@ script_dir=$(dirname $0) # Generate preprocessor run_flex Tokenizer.l Tokenizer.cpp run_bison ExpressionParser.y ExpressionParser.cpp +patch --silent --forward < 64bit-tokenizer-safety.patch diff --git a/gfx/angle/src/compiler/preprocessor/preprocessor.vcxproj b/gfx/angle/src/compiler/preprocessor/preprocessor.vcxproj index c3d5d6c071a2..ca8530b5074a 100644 --- a/gfx/angle/src/compiler/preprocessor/preprocessor.vcxproj +++ b/gfx/angle/src/compiler/preprocessor/preprocessor.vcxproj @@ -1,169 +1,172 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {FBE32DF3-0FB0-4F2F-A424-2C21BD7BC325} - preprocessor - Win32Proj - - - - StaticLibrary - Unicode - true - - - StaticLibrary - Unicode - - - StaticLibrary - Unicode - true - - - StaticLibrary - Unicode - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.40219.1 - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - $(SolutionDir)$(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - $(SolutionDir)$(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ - - - - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - - - Level4 - true - EditAndContinue - 4100;4127;4189;4239;4244;4245;4512;4702;4267;%(DisableSpecificWarnings) - - - - - X64 - - - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - - - Level4 - true - ProgramDatabase - 4100;4127;4189;4239;4244;4245;4512;4702;4718;4267;%(DisableSpecificWarnings) - - - - - MaxSpeed - AnySuitable - WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;_SECURE_SCL=0;%(PreprocessorDefinitions) - MultiThreaded - - - Level4 - true - ProgramDatabase - 4100;4127;4189;4239;4244;4245;4512;4702;4718;4267;%(DisableSpecificWarnings) - - - - - X64 - - - MaxSpeed - AnySuitable - WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;_SECURE_SCL=0;%(PreprocessorDefinitions) - MultiThreaded - - - Level4 - true - ProgramDatabase - 4100;4127;4189;4239;4244;4245;4512;4702;4718;4267;%(DisableSpecificWarnings) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {FBE32DF3-0FB0-4F2F-A424-2C21BD7BC325} + preprocessor + Win32Proj + + + + StaticLibrary + Unicode + true + + + StaticLibrary + Unicode + + + StaticLibrary + Unicode + true + + + StaticLibrary + Unicode + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.40219.1 + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + + + + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + + + Level4 + true + EditAndContinue + 4100;4127;4189;4239;4244;4245;4512;4702;4267;%(DisableSpecificWarnings) + + + + + X64 + + + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + + + Level4 + true + ProgramDatabase + 4100;4127;4189;4239;4244;4245;4512;4702;4718;4267;%(DisableSpecificWarnings) + + + + + MaxSpeed + AnySuitable + WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;_SECURE_SCL=0;%(PreprocessorDefinitions) + MultiThreaded + + + Level4 + true + ProgramDatabase + 4100;4127;4189;4239;4244;4245;4512;4702;4718;4267;%(DisableSpecificWarnings) + + + + + X64 + + + MaxSpeed + AnySuitable + WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;_SECURE_SCL=0;%(PreprocessorDefinitions) + MultiThreaded + + + Level4 + true + ProgramDatabase + 4100;4127;4189;4239;4244;4245;4512;4702;4718;4267;%(DisableSpecificWarnings) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/gfx/angle/src/compiler/preprocessor/preprocessor.vcxproj.filters b/gfx/angle/src/compiler/preprocessor/preprocessor.vcxproj.filters index 2df91e2f749f..4ac202f4002a 100644 --- a/gfx/angle/src/compiler/preprocessor/preprocessor.vcxproj.filters +++ b/gfx/angle/src/compiler/preprocessor/preprocessor.vcxproj.filters @@ -11,12 +11,6 @@ - - Source Files - - - Source Files - Source Files @@ -44,14 +38,14 @@ Source Files + + Source Files + + + Source Files + - - Header Files - - - Header Files - Header Files @@ -91,5 +85,16 @@ Header Files + + Header Files + + + Header Files + + + + + Source Files + \ No newline at end of file diff --git a/gfx/angle/src/compiler/spooky.cpp b/gfx/angle/src/compiler/spooky.cpp deleted file mode 100644 index f6d78f276f5a..000000000000 --- a/gfx/angle/src/compiler/spooky.cpp +++ /dev/null @@ -1,348 +0,0 @@ -// Spooky Hash -// A 128-bit noncryptographic hash, for checksums and table lookup -// By Bob Jenkins. Public domain. -// Oct 31 2010: published framework, disclaimer ShortHash isn't right -// Nov 7 2010: disabled ShortHash -// Oct 31 2011: replace End, ShortMix, ShortEnd, enable ShortHash again - -#include -#include -#include "spooky.h" - -#define ALLOW_UNALIGNED_READS 1 - -// -// short hash ... it could be used on any message, -// but it's used by Spooky just for short messages. -// -void SpookyHash::Short( - const void *message, - size_t length, - uint64 *hash1, - uint64 *hash2) -{ - uint64 buf[sc_numVars]; - union - { - const uint8 *p8; - uint32 *p32; - uint64 *p64; - size_t i; - } u; - - u.p8 = (const uint8 *)message; - - if (!ALLOW_UNALIGNED_READS && (u.i & 0x7)) - { - memcpy(buf, message, length); - u.p64 = buf; - } - - size_t remainder = length%32; - uint64 a=*hash1; - uint64 b=*hash2; - uint64 c=sc_const; - uint64 d=sc_const; - - if (length > 15) - { - const uint64 *end = u.p64 + (length/32)*4; - - // handle all complete sets of 32 bytes - for (; u.p64 < end; u.p64 += 4) - { - c += u.p64[0]; - d += u.p64[1]; - ShortMix(a,b,c,d); - a += u.p64[2]; - b += u.p64[3]; - } - - //Handle the case of 16+ remaining bytes. - if (remainder >= 16) - { - c += u.p64[0]; - d += u.p64[1]; - ShortMix(a,b,c,d); - u.p64 += 2; - remainder -= 16; - } - } - - // Handle the last 0..15 bytes, and its length - d = ((uint64)length) << 56; - switch (remainder) - { - case 15: - d += ((uint64)u.p8[14]) << 48; - case 14: - d += ((uint64)u.p8[13]) << 40; - case 13: - d += ((uint64)u.p8[12]) << 32; - case 12: - d += u.p32[2]; - c += u.p64[0]; - break; - case 11: - d += ((uint64)u.p8[10]) << 16; - case 10: - d += ((uint64)u.p8[9]) << 8; - case 9: - d += (uint64)u.p8[8]; - case 8: - c += u.p64[0]; - break; - case 7: - c += ((uint64)u.p8[6]) << 48; - case 6: - c += ((uint64)u.p8[5]) << 40; - case 5: - c += ((uint64)u.p8[4]) << 32; - case 4: - c += u.p32[0]; - break; - case 3: - c += ((uint64)u.p8[2]) << 16; - case 2: - c += ((uint64)u.p8[1]) << 8; - case 1: - c += (uint64)u.p8[0]; - break; - case 0: - c += sc_const; - d += sc_const; - } - ShortEnd(a,b,c,d); - *hash1 = a; - *hash2 = b; -} - - - - -// do the whole hash in one call -void SpookyHash::Hash128( - const void *message, - size_t length, - uint64 *hash1, - uint64 *hash2) -{ - if (length < sc_bufSize) - { - Short(message, length, hash1, hash2); - return; - } - - uint64 h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11; - uint64 buf[sc_numVars]; - uint64 *end; - union - { - const uint8 *p8; - uint64 *p64; - size_t i; - } u; - size_t remainder; - - h0=h3=h6=h9 = *hash1; - h1=h4=h7=h10 = *hash2; - h2=h5=h8=h11 = sc_const; - - u.p8 = (const uint8 *)message; - end = u.p64 + (length/sc_blockSize)*sc_numVars; - - // handle all whole sc_blockSize blocks of bytes - if (ALLOW_UNALIGNED_READS || ((u.i & 0x7) == 0)) - { - while (u.p64 < end) - { - Mix(u.p64, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); - u.p64 += sc_numVars; - } - } - else - { - while (u.p64 < end) - { - memcpy(buf, u.p64, sc_blockSize); - Mix(buf, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); - u.p64 += sc_numVars; - } - } - - // handle the last partial block of sc_blockSize bytes - remainder = (length - ((const uint8 *)end-(const uint8 *)message)); - memcpy(buf, end, remainder); - memset(((uint8 *)buf)+remainder, 0, sc_blockSize-remainder); - ((uint8 *)buf)[sc_blockSize-1] = remainder; - Mix(buf, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); - - // do some final mixing - End(h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); - *hash1 = h0; - *hash2 = h1; -} - - - -// init spooky state -void SpookyHash::Init(uint64 seed1, uint64 seed2) -{ - m_length = 0; - m_remainder = 0; - m_state[0] = seed1; - m_state[1] = seed2; -} - - -// add a message fragment to the state -void SpookyHash::Update(const void *message, size_t length) -{ - uint64 h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11; - size_t newLength = length + m_remainder; - uint8 remainder; - union - { - const uint8 *p8; - uint64 *p64; - size_t i; - } u; - const uint64 *end; - - // Is this message fragment too short? If it is, stuff it away. - if (newLength < sc_bufSize) - { - memcpy(&((uint8 *)m_data)[m_remainder], message, length); - m_length = length + m_length; - m_remainder = (uint8)newLength; - return; - } - - // init the variables - if (m_length < sc_bufSize) - { - h0=h3=h6=h9 = m_state[0]; - h1=h4=h7=h10 = m_state[1]; - h2=h5=h8=h11 = sc_const; - } - else - { - h0 = m_state[0]; - h1 = m_state[1]; - h2 = m_state[2]; - h3 = m_state[3]; - h4 = m_state[4]; - h5 = m_state[5]; - h6 = m_state[6]; - h7 = m_state[7]; - h8 = m_state[8]; - h9 = m_state[9]; - h10 = m_state[10]; - h11 = m_state[11]; - } - m_length = length + m_length; - - // if we've got anything stuffed away, use it now - if (m_remainder) - { - uint8 prefix = sc_bufSize-m_remainder; - memcpy(&(((uint8 *)m_data)[m_remainder]), message, prefix); - u.p64 = m_data; - Mix(u.p64, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); - Mix(&u.p64[sc_numVars], h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); - u.p8 = ((const uint8 *)message) + prefix; - length -= prefix; - } - else - { - u.p8 = (const uint8 *)message; - } - - // handle all whole blocks of sc_blockSize bytes - end = u.p64 + (length/sc_blockSize)*sc_numVars; - remainder = (uint8)(length-((const uint8 *)end-u.p8)); - if (ALLOW_UNALIGNED_READS || (u.i & 0x7) == 0) - { - while (u.p64 < end) - { - Mix(u.p64, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); - u.p64 += sc_numVars; - } - } - else - { - while (u.p64 < end) - { - memcpy(m_data, u.p8, sc_blockSize); - Mix(m_data, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); - u.p64 += sc_numVars; - } - } - - // stuff away the last few bytes - m_remainder = remainder; - memcpy(m_data, end, remainder); - - // stuff away the variables - m_state[0] = h0; - m_state[1] = h1; - m_state[2] = h2; - m_state[3] = h3; - m_state[4] = h4; - m_state[5] = h5; - m_state[6] = h6; - m_state[7] = h7; - m_state[8] = h8; - m_state[9] = h9; - m_state[10] = h10; - m_state[11] = h11; -} - - -// report the hash for the concatenation of all message fragments so far -void SpookyHash::Final(uint64 *hash1, uint64 *hash2) -{ - // init the variables - if (m_length < sc_bufSize) - { - Short( m_data, m_length, hash1, hash2); - return; - } - - const uint64 *data = (const uint64 *)m_data; - uint8 remainder = m_remainder; - - uint64 h0 = m_state[0]; - uint64 h1 = m_state[1]; - uint64 h2 = m_state[2]; - uint64 h3 = m_state[3]; - uint64 h4 = m_state[4]; - uint64 h5 = m_state[5]; - uint64 h6 = m_state[6]; - uint64 h7 = m_state[7]; - uint64 h8 = m_state[8]; - uint64 h9 = m_state[9]; - uint64 h10 = m_state[10]; - uint64 h11 = m_state[11]; - - if (remainder >= sc_blockSize) - { - // m_data can contain two blocks; handle any whole first block - Mix(data, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); - data += sc_numVars; - remainder -= sc_blockSize; - } - - // mix in the last partial block, and the length mod sc_blockSize - memset(&((uint8 *)data)[remainder], 0, (sc_blockSize-remainder)); - - ((uint8 *)data)[sc_blockSize-1] = remainder; - Mix(data, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); - - // do some final mixing - End(h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); - - *hash1 = h0; - *hash2 = h1; -} - diff --git a/gfx/angle/src/compiler/spooky.h b/gfx/angle/src/compiler/spooky.h deleted file mode 100644 index cafd52e47d92..000000000000 --- a/gfx/angle/src/compiler/spooky.h +++ /dev/null @@ -1,293 +0,0 @@ -// -// SpookyHash: a 128-bit noncryptographic hash function -// By Bob Jenkins, public domain -// Oct 31 2010: alpha, framework + SpookyHash::Mix appears right -// Oct 31 2011: alpha again, Mix only good to 2^^69 but rest appears right -// Dec 31 2011: beta, improved Mix, tested it for 2-bit deltas -// Feb 2 2012: production, same bits as beta -// Feb 5 2012: adjusted definitions of uint* to be more portable -// -// Up to 4 bytes/cycle for long messages. Reasonably fast for short messages. -// All 1 or 2 bit deltas achieve avalanche within 1% bias per output bit. -// -// This was developed for and tested on 64-bit x86-compatible processors. -// It assumes the processor is little-endian. There is a macro -// controlling whether unaligned reads are allowed (by default they are). -// This should be an equally good hash on big-endian machines, but it will -// compute different results on them than on little-endian machines. -// -// Google's CityHash has similar specs to SpookyHash, and CityHash is faster -// on some platforms. MD4 and MD5 also have similar specs, but they are orders -// of magnitude slower. CRCs are two or more times slower, but unlike -// SpookyHash, they have nice math for combining the CRCs of pieces to form -// the CRCs of wholes. There are also cryptographic hashes, but those are even -// slower than MD5. -// - -#include - -#ifdef _MSC_VER -# define INLINE __forceinline - typedef unsigned __int64 uint64; - typedef unsigned __int32 uint32; - typedef unsigned __int16 uint16; - typedef unsigned __int8 uint8; -#else -# include -# define INLINE inline - typedef uint64_t uint64; - typedef uint32_t uint32; - typedef uint16_t uint16; - typedef uint8_t uint8; -#endif - - -class SpookyHash -{ -public: - // - // SpookyHash: hash a single message in one call, produce 128-bit output - // - static void Hash128( - const void *message, // message to hash - size_t length, // length of message in bytes - uint64 *hash1, // in/out: in seed 1, out hash value 1 - uint64 *hash2); // in/out: in seed 2, out hash value 2 - - // - // Hash64: hash a single message in one call, return 64-bit output - // - static uint64 Hash64( - const void *message, // message to hash - size_t length, // length of message in bytes - uint64 seed) // seed - { - uint64 hash1 = seed; - Hash128(message, length, &hash1, &seed); - return hash1; - } - - // - // Hash32: hash a single message in one call, produce 32-bit output - // - static uint32 Hash32( - const void *message, // message to hash - size_t length, // length of message in bytes - uint32 seed) // seed - { - uint64 hash1 = seed, hash2 = seed; - Hash128(message, length, &hash1, &hash2); - return (uint32)hash1; - } - - // - // Init: initialize the context of a SpookyHash - // - void Init( - uint64 seed1, // any 64-bit value will do, including 0 - uint64 seed2); // different seeds produce independent hashes - - // - // Update: add a piece of a message to a SpookyHash state - // - void Update( - const void *message, // message fragment - size_t length); // length of message fragment in bytes - - - // - // Final: compute the hash for the current SpookyHash state - // - // This does not modify the state; you can keep updating it afterward - // - // The result is the same as if SpookyHash() had been called with - // all the pieces concatenated into one message. - // - void Final( - uint64 *hash1, // out only: first 64 bits of hash value. - uint64 *hash2); // out only: second 64 bits of hash value. - - // - // left rotate a 64-bit value by k bytes - // - static INLINE uint64 Rot64(uint64 x, int k) - { - return (x << k) | (x >> (64 - k)); - } - - // - // This is used if the input is 96 bytes long or longer. - // - // The internal state is fully overwritten every 96 bytes. - // Every input bit appears to cause at least 128 bits of entropy - // before 96 other bytes are combined, when run forward or backward - // For every input bit, - // Two inputs differing in just that input bit - // Where "differ" means xor or subtraction - // And the base value is random - // When run forward or backwards one Mix - // I tried 3 pairs of each; they all differed by at least 212 bits. - // - static INLINE void Mix( - const uint64 *data, - uint64 &s0, uint64 &s1, uint64 &s2, uint64 &s3, - uint64 &s4, uint64 &s5, uint64 &s6, uint64 &s7, - uint64 &s8, uint64 &s9, uint64 &s10,uint64 &s11) - { - s0 += data[0]; s2 ^= s10; s11 ^= s0; s0 = Rot64(s0,11); s11 += s1; - s1 += data[1]; s3 ^= s11; s0 ^= s1; s1 = Rot64(s1,32); s0 += s2; - s2 += data[2]; s4 ^= s0; s1 ^= s2; s2 = Rot64(s2,43); s1 += s3; - s3 += data[3]; s5 ^= s1; s2 ^= s3; s3 = Rot64(s3,31); s2 += s4; - s4 += data[4]; s6 ^= s2; s3 ^= s4; s4 = Rot64(s4,17); s3 += s5; - s5 += data[5]; s7 ^= s3; s4 ^= s5; s5 = Rot64(s5,28); s4 += s6; - s6 += data[6]; s8 ^= s4; s5 ^= s6; s6 = Rot64(s6,39); s5 += s7; - s7 += data[7]; s9 ^= s5; s6 ^= s7; s7 = Rot64(s7,57); s6 += s8; - s8 += data[8]; s10 ^= s6; s7 ^= s8; s8 = Rot64(s8,55); s7 += s9; - s9 += data[9]; s11 ^= s7; s8 ^= s9; s9 = Rot64(s9,54); s8 += s10; - s10 += data[10]; s0 ^= s8; s9 ^= s10; s10 = Rot64(s10,22); s9 += s11; - s11 += data[11]; s1 ^= s9; s10 ^= s11; s11 = Rot64(s11,46); s10 += s0; - } - - // - // Mix all 12 inputs together so that h0, h1 are a hash of them all. - // - // For two inputs differing in just the input bits - // Where "differ" means xor or subtraction - // And the base value is random, or a counting value starting at that bit - // The final result will have each bit of h0, h1 flip - // For every input bit, - // with probability 50 +- .3% - // For every pair of input bits, - // with probability 50 +- 3% - // - // This does not rely on the last Mix() call having already mixed some. - // Two iterations was almost good enough for a 64-bit result, but a - // 128-bit result is reported, so End() does three iterations. - // - static INLINE void EndPartial( - uint64 &h0, uint64 &h1, uint64 &h2, uint64 &h3, - uint64 &h4, uint64 &h5, uint64 &h6, uint64 &h7, - uint64 &h8, uint64 &h9, uint64 &h10,uint64 &h11) - { - h11+= h1; h2 ^= h11; h1 = Rot64(h1,44); - h0 += h2; h3 ^= h0; h2 = Rot64(h2,15); - h1 += h3; h4 ^= h1; h3 = Rot64(h3,34); - h2 += h4; h5 ^= h2; h4 = Rot64(h4,21); - h3 += h5; h6 ^= h3; h5 = Rot64(h5,38); - h4 += h6; h7 ^= h4; h6 = Rot64(h6,33); - h5 += h7; h8 ^= h5; h7 = Rot64(h7,10); - h6 += h8; h9 ^= h6; h8 = Rot64(h8,13); - h7 += h9; h10^= h7; h9 = Rot64(h9,38); - h8 += h10; h11^= h8; h10= Rot64(h10,53); - h9 += h11; h0 ^= h9; h11= Rot64(h11,42); - h10+= h0; h1 ^= h10; h0 = Rot64(h0,54); - } - - static INLINE void End( - uint64 &h0, uint64 &h1, uint64 &h2, uint64 &h3, - uint64 &h4, uint64 &h5, uint64 &h6, uint64 &h7, - uint64 &h8, uint64 &h9, uint64 &h10,uint64 &h11) - { - EndPartial(h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); - EndPartial(h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); - EndPartial(h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); - } - - // - // The goal is for each bit of the input to expand into 128 bits of - // apparent entropy before it is fully overwritten. - // n trials both set and cleared at least m bits of h0 h1 h2 h3 - // n: 2 m: 29 - // n: 3 m: 46 - // n: 4 m: 57 - // n: 5 m: 107 - // n: 6 m: 146 - // n: 7 m: 152 - // when run forwards or backwards - // for all 1-bit and 2-bit diffs - // with diffs defined by either xor or subtraction - // with a base of all zeros plus a counter, or plus another bit, or random - // - static INLINE void ShortMix(uint64 &h0, uint64 &h1, uint64 &h2, uint64 &h3) - { - h2 = Rot64(h2,50); h2 += h3; h0 ^= h2; - h3 = Rot64(h3,52); h3 += h0; h1 ^= h3; - h0 = Rot64(h0,30); h0 += h1; h2 ^= h0; - h1 = Rot64(h1,41); h1 += h2; h3 ^= h1; - h2 = Rot64(h2,54); h2 += h3; h0 ^= h2; - h3 = Rot64(h3,48); h3 += h0; h1 ^= h3; - h0 = Rot64(h0,38); h0 += h1; h2 ^= h0; - h1 = Rot64(h1,37); h1 += h2; h3 ^= h1; - h2 = Rot64(h2,62); h2 += h3; h0 ^= h2; - h3 = Rot64(h3,34); h3 += h0; h1 ^= h3; - h0 = Rot64(h0,5); h0 += h1; h2 ^= h0; - h1 = Rot64(h1,36); h1 += h2; h3 ^= h1; - } - - // - // Mix all 4 inputs together so that h0, h1 are a hash of them all. - // - // For two inputs differing in just the input bits - // Where "differ" means xor or subtraction - // And the base value is random, or a counting value starting at that bit - // The final result will have each bit of h0, h1 flip - // For every input bit, - // with probability 50 +- .3% (it is probably better than that) - // For every pair of input bits, - // with probability 50 +- .75% (the worst case is approximately that) - // - static INLINE void ShortEnd(uint64 &h0, uint64 &h1, uint64 &h2, uint64 &h3) - { - h3 ^= h2; h2 = Rot64(h2,15); h3 += h2; - h0 ^= h3; h3 = Rot64(h3,52); h0 += h3; - h1 ^= h0; h0 = Rot64(h0,26); h1 += h0; - h2 ^= h1; h1 = Rot64(h1,51); h2 += h1; - h3 ^= h2; h2 = Rot64(h2,28); h3 += h2; - h0 ^= h3; h3 = Rot64(h3,9); h0 += h3; - h1 ^= h0; h0 = Rot64(h0,47); h1 += h0; - h2 ^= h1; h1 = Rot64(h1,54); h2 += h1; - h3 ^= h2; h2 = Rot64(h2,32); h3 += h2; - h0 ^= h3; h3 = Rot64(h3,25); h0 += h3; - h1 ^= h0; h0 = Rot64(h0,63); h1 += h0; - } - -private: - - // - // Short is used for messages under 192 bytes in length - // Short has a low startup cost, the normal mode is good for long - // keys, the cost crossover is at about 192 bytes. The two modes were - // held to the same quality bar. - // - static void Short( - const void *message, - size_t length, - uint64 *hash1, - uint64 *hash2); - - // number of uint64's in internal state - static const size_t sc_numVars = 12; - - // size of the internal state - static const size_t sc_blockSize = sc_numVars*8; - - // size of buffer of unhashed data, in bytes - static const size_t sc_bufSize = 2*sc_blockSize; - - // - // sc_const: a constant which: - // * is not zero - // * is odd - // * is a not-very-regular mix of 1's and 0's - // * does not need any other special mathematical properties - // - static const uint64 sc_const = 0xdeadbeefdeadbeefLL; - - uint64 m_data[2*sc_numVars]; // unhashed data, for partial messages - uint64 m_state[sc_numVars]; // internal state of the hash - size_t m_length; // total length of the input so far - uint8 m_remainder; // length of unhashed data stashed in m_data -}; - - - diff --git a/gfx/angle/src/compiler/timing/RestrictVertexShaderTiming.cpp b/gfx/angle/src/compiler/timing/RestrictVertexShaderTiming.cpp index 524c6cf53a69..355eb62d650b 100644 --- a/gfx/angle/src/compiler/timing/RestrictVertexShaderTiming.cpp +++ b/gfx/angle/src/compiler/timing/RestrictVertexShaderTiming.cpp @@ -10,8 +10,8 @@ void RestrictVertexShaderTiming::visitSymbol(TIntermSymbol* node) { if (IsSampler(node->getBasicType())) { ++mNumErrors; - mSink.prefix(EPrefixError); - mSink.location(node->getLine()); - mSink << "Samplers are not permitted in vertex shaders.\n"; + mSink.message(EPrefixError, + node->getLine(), + "Samplers are not permitted in vertex shaders"); } } diff --git a/gfx/angle/src/compiler/translator_common.vcxproj b/gfx/angle/src/compiler/translator_common.vcxproj deleted file mode 100644 index 749a6c71fd5e..000000000000 --- a/gfx/angle/src/compiler/translator_common.vcxproj +++ /dev/null @@ -1,284 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD} - compiler - Win32Proj - - - - StaticLibrary - NotSet - true - - - StaticLibrary - NotSet - - - StaticLibrary - NotSet - true - - - StaticLibrary - NotSet - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.40219.1 - $(SolutionDir)$(Configuration)\ - $(Configuration)\common\ - $(SolutionDir)$(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ - $(SolutionDir)$(Configuration)\ - $(Configuration)\common\ - $(SolutionDir)$(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ - - - - Disabled - $(ProjectDir);$(ProjectDir)../;$(ProjectDir)../../include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - - - Level4 - true - EditAndContinue - 4100;4127;4189;4239;4244;4245;4512;4702;4718;%(DisableSpecificWarnings) - - - - - X64 - - - Disabled - $(ProjectDir);$(ProjectDir)../;$(ProjectDir)../../include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - - - Level4 - true - ProgramDatabase - 4100;4127;4189;4239;4244;4245;4267;4512;4702;4718;%(DisableSpecificWarnings) - - - - - MaxSpeed - AnySuitable - $(ProjectDir);$(ProjectDir)../;$(ProjectDir)../../include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;_SECURE_SCL=0;%(PreprocessorDefinitions) - MultiThreaded - - - Level4 - true - ProgramDatabase - 4100;4127;4189;4239;4244;4245;4512;4702;4718;%(DisableSpecificWarnings) - - - - - X64 - - - MaxSpeed - AnySuitable - $(ProjectDir);$(ProjectDir)../;$(ProjectDir)../../include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;_SECURE_SCL=0;%(PreprocessorDefinitions) - MultiThreaded - - - Level4 - true - ProgramDatabase - 4100;4127;4189;4239;4244;4245;4267;4512;4702;4718;%(DisableSpecificWarnings) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %(AdditionalInputs) - %(Outputs) - - - - - %(AdditionalInputs) - %(Outputs) - - - - - %(AdditionalInputs) - %(Outputs) - - - - - %(AdditionalInputs) - %(Outputs) - - - - - - - %(Outputs) - - - - - %(Outputs) - - - - - %(Outputs) - - - - - %(Outputs) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {fbe32df3-0fb0-4f2f-a424-2c21bd7bc325} - false - true - false - true - true - - - - - - diff --git a/gfx/angle/src/compiler/translator_common.vcxproj.filters b/gfx/angle/src/compiler/translator_common.vcxproj.filters deleted file mode 100644 index 2de92438c869..000000000000 --- a/gfx/angle/src/compiler/translator_common.vcxproj.filters +++ /dev/null @@ -1,268 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {eb8da157-b29c-43c3-880d-54679e176dc5} - - - {b5410d3a-c3c8-4ae6-843a-b000d652632e} - - - {a9847611-dcd5-4c89-8262-a22b96c7c98d} - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {094f7115-35d3-4c63-870c-ab5f393dc2c2} - - - {5f5742e9-15e1-43b4-b1e7-0c118be14e04} - - - {c4007e35-3c11-44d6-95f7-bb81db528068} - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files\generated - - - Source Files\generated - - - Source Files\depgraph - - - Source Files\depgraph - - - Source Files\depgraph - - - Source Files\depgraph - - - Source Files\timing - - - Source Files\timing - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files\generated - - - Header Files\timing - - - Header Files\timing - - - Header Files\depgraph - - - Header Files\depgraph - - - Header Files\depgraph - - - Header Files - - - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/gfx/angle/src/compiler/translator_hlsl.vcxproj b/gfx/angle/src/compiler/translator_hlsl.vcxproj deleted file mode 100644 index 4ebc11c43a19..000000000000 --- a/gfx/angle/src/compiler/translator_hlsl.vcxproj +++ /dev/null @@ -1,172 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {5620F0E4-6C43-49BC-A178-B804E1A0C3A7} - CrossCompilerHLSL - Win32Proj - - - - StaticLibrary - Unicode - true - - - StaticLibrary - Unicode - - - StaticLibrary - Unicode - true - - - StaticLibrary - Unicode - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.40219.1 - $(SolutionDir)$(Configuration)\ - $(Configuration)\hlsl\ - $(SolutionDir)$(Configuration)\ - $(Configuration)\hlsl\ - $(SolutionDir)$(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ - $(SolutionDir)$(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ - - - - Disabled - $(ProjectDir)../;$(ProjectDir)../../include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;NOMINMAX;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - - - Level4 - true - EditAndContinue - 4100;4127;4189;4239;4244;4245;4512;4702;%(DisableSpecificWarnings) - - - - - MaxSpeed - AnySuitable - true - $(ProjectDir)../;$(ProjectDir)../../include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_SECURE_SCL=0;%(PreprocessorDefinitions) - MultiThreaded - true - - - Level4 - true - ProgramDatabase - 4100;4127;4189;4239;4244;4245;4512;4702;%(DisableSpecificWarnings) - - - - - X64 - - - Disabled - $(ProjectDir)../;$(ProjectDir)../../include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;NOMINMAX;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - - - Level4 - 4100;4127;4189;4239;4244;4245;4512;4702;%(DisableSpecificWarnings) - ProgramDatabase - true - - - - - X64 - - - MaxSpeed - AnySuitable - true - $(ProjectDir)../;$(ProjectDir)../../include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_SECURE_SCL=0;%(PreprocessorDefinitions) - MultiThreaded - true - - - Level4 - 4100;4127;4189;4239;4244;4245;4512;4702;%(DisableSpecificWarnings) - ProgramDatabase - true - - - - - - - - - - - - - - - - - - - - {5b3a6db8-1e7e-40d7-92b9-da8aae619fad} - false - true - false - true - true - - - - - - \ No newline at end of file diff --git a/gfx/angle/src/compiler/translator_hlsl.vcxproj.filters b/gfx/angle/src/compiler/translator_hlsl.vcxproj.filters deleted file mode 100644 index beee069eb39d..000000000000 --- a/gfx/angle/src/compiler/translator_hlsl.vcxproj.filters +++ /dev/null @@ -1,50 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - \ No newline at end of file diff --git a/gfx/angle/src/libEGL/Config.cpp b/gfx/angle/src/libEGL/Config.cpp index 89bc8d89f423..5488cb6f4f12 100644 --- a/gfx/angle/src/libEGL/Config.cpp +++ b/gfx/angle/src/libEGL/Config.cpp @@ -13,76 +13,30 @@ #include #include +#include +#include + #include "common/debug.h" using namespace std; namespace egl { -Config::Config(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight) - : mDisplayMode(displayMode), mRenderTargetFormat(renderTargetFormat), mDepthStencilFormat(depthStencilFormat), mMultiSample(multiSample) -{ - set(displayMode, minInterval, maxInterval, renderTargetFormat, depthStencilFormat, multiSample, texWidth, texHeight); -} - -void Config::setDefaults() -{ - mBufferSize = 0; - mRedSize = 0; - mGreenSize = 0; - mBlueSize = 0; - mLuminanceSize = 0; - mAlphaSize = 0; - mAlphaMaskSize = 0; - mBindToTextureRGB = EGL_DONT_CARE; - mBindToTextureRGBA = EGL_DONT_CARE; - mColorBufferType = EGL_RGB_BUFFER; - mConfigCaveat = EGL_DONT_CARE; - mConfigID = EGL_DONT_CARE; - mConformant = 0; - mDepthSize = 0; - mLevel = 0; - mMatchNativePixmap = EGL_NONE; - mMaxPBufferWidth = 0; - mMaxPBufferHeight = 0; - mMaxPBufferPixels = 0; - mMaxSwapInterval = EGL_DONT_CARE; - mMinSwapInterval = EGL_DONT_CARE; - mNativeRenderable = EGL_DONT_CARE; - mNativeVisualID = 0; - mNativeVisualType = EGL_DONT_CARE; - mRenderableType = EGL_OPENGL_ES_BIT; - mSampleBuffers = 0; - mSamples = 0; - mStencilSize = 0; - mSurfaceType = EGL_WINDOW_BIT; - mTransparentType = EGL_NONE; - mTransparentRedValue = EGL_DONT_CARE; - mTransparentGreenValue = EGL_DONT_CARE; - mTransparentBlueValue = EGL_DONT_CARE; -} - -void Config::set(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight) +Config::Config(rx::ConfigDesc desc, EGLint minInterval, EGLint maxInterval, EGLint texWidth, EGLint texHeight) + : mRenderTargetFormat(desc.renderTargetFormat), mDepthStencilFormat(desc.depthStencilFormat), mMultiSample(desc.multiSample) { mBindToTextureRGB = EGL_FALSE; mBindToTextureRGBA = EGL_FALSE; - switch (renderTargetFormat) + switch (desc.renderTargetFormat) { - case D3DFMT_A1R5G5B5: + case GL_RGB5_A1: mBufferSize = 16; mRedSize = 5; mGreenSize = 5; mBlueSize = 5; mAlphaSize = 1; break; - case D3DFMT_A2R10G10B10: - mBufferSize = 32; - mRedSize = 10; - mGreenSize = 10; - mBlueSize = 10; - mAlphaSize = 2; - break; - case D3DFMT_A8R8G8B8: + case GL_RGBA8_OES: mBufferSize = 32; mRedSize = 8; mGreenSize = 8; @@ -90,14 +44,14 @@ void Config::set(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInter mAlphaSize = 8; mBindToTextureRGBA = true; break; - case D3DFMT_R5G6B5: + case GL_RGB565: mBufferSize = 16; mRedSize = 5; mGreenSize = 6; mBlueSize = 5; mAlphaSize = 0; break; - case D3DFMT_X8R8G8B8: + case GL_RGB8_OES: mBufferSize = 32; mRedSize = 8; mGreenSize = 8; @@ -105,6 +59,14 @@ void Config::set(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInter mAlphaSize = 0; mBindToTextureRGB = true; break; + case GL_BGRA8_EXT: + mBufferSize = 32; + mRedSize = 8; + mGreenSize = 8; + mBlueSize = 8; + mAlphaSize = 8; + mBindToTextureRGBA = true; + break; default: UNREACHABLE(); // Other formats should not be valid } @@ -112,52 +74,32 @@ void Config::set(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInter mLuminanceSize = 0; mAlphaMaskSize = 0; mColorBufferType = EGL_RGB_BUFFER; - mConfigCaveat = (displayMode.Format == renderTargetFormat) ? EGL_NONE : EGL_SLOW_CONFIG; + mConfigCaveat = (desc.fastConfig) ? EGL_NONE : EGL_SLOW_CONFIG; mConfigID = 0; mConformant = EGL_OPENGL_ES2_BIT; - switch (depthStencilFormat) + switch (desc.depthStencilFormat) { - case D3DFMT_UNKNOWN: + case GL_NONE: mDepthSize = 0; mStencilSize = 0; break; -// case D3DFMT_D16_LOCKABLE: -// mDepthSize = 16; -// mStencilSize = 0; -// break; - case D3DFMT_D32: + case GL_DEPTH_COMPONENT32_OES: mDepthSize = 32; mStencilSize = 0; break; - case D3DFMT_D15S1: - mDepthSize = 15; - mStencilSize = 1; - break; - case D3DFMT_D24S8: + case GL_DEPTH24_STENCIL8_OES: mDepthSize = 24; mStencilSize = 8; break; - case D3DFMT_D24X8: + case GL_DEPTH_COMPONENT24_OES: mDepthSize = 24; mStencilSize = 0; break; - case D3DFMT_D24X4S4: - mDepthSize = 24; - mStencilSize = 4; - break; - case D3DFMT_D16: + case GL_DEPTH_COMPONENT16: mDepthSize = 16; mStencilSize = 0; break; -// case D3DFMT_D32F_LOCKABLE: -// mDepthSize = 32; -// mStencilSize = 0; -// break; -// case D3DFMT_D24FS8: -// mDepthSize = 24; -// mStencilSize = 8; -// break; default: UNREACHABLE(); } @@ -173,8 +115,8 @@ void Config::set(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInter mNativeVisualID = 0; mNativeVisualType = 0; mRenderableType = EGL_OPENGL_ES2_BIT; - mSampleBuffers = multiSample ? 1 : 0; - mSamples = multiSample; + mSampleBuffers = desc.multiSample ? 1 : 0; + mSamples = desc.multiSample; mSurfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT; mTransparentType = EGL_NONE; mTransparentRedValue = 0; @@ -288,10 +230,9 @@ ConfigSet::ConfigSet() { } -void ConfigSet::add(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight) +void ConfigSet::add(rx::ConfigDesc desc, EGLint minSwapInterval, EGLint maxSwapInterval, EGLint texWidth, EGLint texHeight) { - Config config(displayMode, minSwapInterval, maxSwapInterval, renderTargetFormat, depthStencilFormat, multiSample, texWidth, texHeight); - + Config config(desc, minSwapInterval, maxSwapInterval, texWidth, texHeight); mSet.insert(config); } diff --git a/gfx/angle/src/libEGL/Config.h b/gfx/angle/src/libEGL/Config.h index 95626ed1ad23..680337b7009f 100644 --- a/gfx/angle/src/libEGL/Config.h +++ b/gfx/angle/src/libEGL/Config.h @@ -13,10 +13,10 @@ #define EGLAPI #include -#include #include +#include "libGLESv2/renderer/Renderer.h" #include "common/angleutils.h" namespace egl @@ -26,16 +26,13 @@ class Display; class Config { public: - Config(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight); + Config(rx::ConfigDesc desc, EGLint minSwapInterval, EGLint maxSwapInterval, EGLint texWidth, EGLint texHeight); - void setDefaults(); - void set(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight); EGLConfig getHandle() const; - const D3DDISPLAYMODE mDisplayMode; - const D3DFORMAT mRenderTargetFormat; - const D3DFORMAT mDepthStencilFormat; - const EGLint mMultiSample; + const GLenum mRenderTargetFormat; + const GLenum mDepthStencilFormat; + const GLint mMultiSample; EGLint mBufferSize; // Depth of the color buffer EGLint mRedSize; // Bits of Red in the color buffer @@ -99,7 +96,7 @@ class ConfigSet public: ConfigSet(); - void add(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight); + void add(rx::ConfigDesc desc, EGLint minSwapInterval, EGLint maxSwapInterval, EGLint texWidth, EGLint texHeight); size_t size() const; bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig); const egl::Config *get(EGLConfig configHandle); diff --git a/gfx/angle/src/libEGL/Display.cpp b/gfx/angle/src/libEGL/Display.cpp index 9292cb140bce..8f2af7946437 100644 --- a/gfx/angle/src/libEGL/Display.cpp +++ b/gfx/angle/src/libEGL/Display.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -16,26 +16,12 @@ #include "common/debug.h" #include "libGLESv2/mathutil.h" -#include "libGLESv2/utilities.h" +#include "libGLESv2/main.h" +#include "libGLESv2/Context.h" +#include "libGLESv2/renderer/SwapChain.h" #include "libEGL/main.h" - -// Can also be enabled by defining FORCE_REF_RAST in the project's predefined macros -#define REF_RAST 0 - -// The "Debug This Pixel..." feature in PIX often fails when using the -// D3D9Ex interfaces. In order to get debug pixel to work on a Vista/Win 7 -// machine, define "ANGLE_ENABLE_D3D9EX=0" in your project file. -#if !defined(ANGLE_ENABLE_D3D9EX) -// Enables use of the IDirect3D9Ex interface, when available -#define ANGLE_ENABLE_D3D9EX 1 -#endif // !defined(ANGLE_ENABLE_D3D9EX) - -#define ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES \ - { \ - TEXT("d3dcompiler_46.dll"), \ - TEXT("d3dcompiler_43.dll") \ - } +#include "libEGL/Surface.h" namespace egl { @@ -51,52 +37,19 @@ egl::Display *Display::getDisplay(EGLNativeDisplayType displayId) { return displays[displayId]; } + + // FIXME: Check if displayId is a valid display device context - egl::Display *display = NULL; - - if (displayId == EGL_DEFAULT_DISPLAY) - { - display = new egl::Display(displayId, (HDC)NULL, false); - } - else if (displayId == EGL_SOFTWARE_DISPLAY_ANGLE) - { - display = new egl::Display(displayId, (HDC)NULL, true); - } - else - { - // FIXME: Check if displayId is a valid display device context - - display = new egl::Display(displayId, (HDC)displayId, false); - } + egl::Display *display = new egl::Display(displayId, (HDC)displayId); displays[displayId] = display; return display; } -Display::Display(EGLNativeDisplayType displayId, HDC deviceContext, bool software) : mDc(deviceContext) +Display::Display(EGLNativeDisplayType displayId, HDC deviceContext) : mDc(deviceContext) { - mD3d9Module = NULL; - mD3dCompilerModule = NULL; - - mD3d9 = NULL; - mD3d9Ex = NULL; - mDevice = NULL; - mDeviceEx = NULL; - mDeviceWindow = NULL; - - mAdapter = D3DADAPTER_DEFAULT; - - #if REF_RAST == 1 || defined(FORCE_REF_RAST) - mDeviceType = D3DDEVTYPE_REF; - #else - mDeviceType = D3DDEVTYPE_HAL; - #endif - - mMinSwapInterval = 1; - mMaxSwapInterval = 1; - mSoftwareDevice = software; mDisplayId = displayId; - mDeviceLost = false; + mRenderer = NULL; } Display::~Display() @@ -107,7 +60,7 @@ Display::~Display() if (thisDisplay != displays.end()) { - displays.erase(thisDisplay); + displays.erase(thisDisplay); } } @@ -118,222 +71,49 @@ bool Display::initialize() return true; } - if (mSoftwareDevice) - { - mD3d9Module = GetModuleHandle(TEXT("swiftshader_d3d9.dll")); - } - else - { - mD3d9Module = GetModuleHandle(TEXT("d3d9.dll")); - } - if (mD3d9Module == NULL) + mRenderer = glCreateRenderer(this, mDc, mDisplayId); + + if (!mRenderer) { terminate(); - return false; + return error(EGL_NOT_INITIALIZED, false); } - typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**); - Direct3DCreate9ExFunc Direct3DCreate9ExPtr = reinterpret_cast(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex")); + EGLint minSwapInterval = mRenderer->getMinSwapInterval(); + EGLint maxSwapInterval = mRenderer->getMaxSwapInterval(); + EGLint maxTextureWidth = mRenderer->getMaxTextureWidth(); + EGLint maxTextureHeight = mRenderer->getMaxTextureHeight(); - #if defined(ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES) - // Find a D3DCompiler module that had already been loaded based on a predefined list of versions. - static TCHAR* d3dCompilerNames[] = ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES; - - for (int i = 0; i < sizeof(d3dCompilerNames) / sizeof(*d3dCompilerNames); ++i) - { - if (GetModuleHandleEx(0, d3dCompilerNames[i], &mD3dCompilerModule)) - { - break; - } - } - #else - // Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was built with. - mD3dCompilerModule = LoadLibrary(D3DCOMPILER_DLL); - #endif // ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES - - if (!mD3dCompilerModule) - { - terminate(); - return false; - } - - mD3DCompileFunc = reinterpret_cast(GetProcAddress(mD3dCompilerModule, "D3DCompile")); - ASSERT(mD3DCompileFunc); + rx::ConfigDesc *descList; + int numConfigs = mRenderer->generateConfigs(&descList); + ConfigSet configSet; - // Use Direct3D9Ex if available. Among other things, this version is less - // inclined to report a lost context, for example when the user switches - // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available. - if (ANGLE_ENABLE_D3D9EX && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex))) + for (int i = 0; i < numConfigs; ++i) + configSet.add(descList[i], minSwapInterval, maxSwapInterval, + maxTextureWidth, maxTextureHeight); + + // Give the sorted configs a unique ID and store them internally + EGLint index = 1; + for (ConfigSet::Iterator config = configSet.mSet.begin(); config != configSet.mSet.end(); config++) { - ASSERT(mD3d9Ex); - mD3d9Ex->QueryInterface(IID_IDirect3D9, reinterpret_cast(&mD3d9)); - ASSERT(mD3d9); - } - else - { - mD3d9 = Direct3DCreate9(D3D_SDK_VERSION); + Config configuration = *config; + configuration.mConfigID = index; + index++; + + mConfigSet.mSet.insert(configuration); } - if (mD3d9) - { - if (mDc != NULL) - { - // UNIMPLEMENTED(); // FIXME: Determine which adapter index the device context corresponds to - } - - HRESULT result; - - // Give up on getting device caps after about one second. - for (int i = 0; i < 10; ++i) - { - result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps); - - if (SUCCEEDED(result)) - { - break; - } - else if (result == D3DERR_NOTAVAILABLE) - { - Sleep(100); // Give the driver some time to initialize/recover - } - else if (FAILED(result)) // D3DERR_OUTOFVIDEOMEMORY, E_OUTOFMEMORY, D3DERR_INVALIDDEVICE, or another error we can't recover from - { - terminate(); - return error(EGL_BAD_ALLOC, false); - } - } - - if (mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(2, 0)) - { - terminate(); - return error(EGL_NOT_INITIALIZED, false); - } - - // When DirectX9 is running with an older DirectX8 driver, a StretchRect from a regular texture to a render target texture is not supported. - // This is required by Texture2D::convertToRenderTarget. - if ((mDeviceCaps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES) == 0) - { - terminate(); - return error(EGL_NOT_INITIALIZED, false); - } - - mMinSwapInterval = 4; - mMaxSwapInterval = 0; - - if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) {mMinSwapInterval = std::min(mMinSwapInterval, 0); mMaxSwapInterval = std::max(mMaxSwapInterval, 0);} - if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE) {mMinSwapInterval = std::min(mMinSwapInterval, 1); mMaxSwapInterval = std::max(mMaxSwapInterval, 1);} - if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_TWO) {mMinSwapInterval = std::min(mMinSwapInterval, 2); mMaxSwapInterval = std::max(mMaxSwapInterval, 2);} - if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_THREE) {mMinSwapInterval = std::min(mMinSwapInterval, 3); mMaxSwapInterval = std::max(mMaxSwapInterval, 3);} - if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_FOUR) {mMinSwapInterval = std::min(mMinSwapInterval, 4); mMaxSwapInterval = std::max(mMaxSwapInterval, 4);} - - mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier); - - // ATI cards on XP have problems with non-power-of-two textures. - mSupportsNonPower2Textures = !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) && - !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) && - !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) && - !(getComparableOSVersion() < versionWindowsVista && mAdapterIdentifier.VendorId == VENDOR_ID_AMD); - - const D3DFORMAT renderTargetFormats[] = - { - D3DFMT_A1R5G5B5, - // D3DFMT_A2R10G10B10, // The color_ramp conformance test uses ReadPixels with UNSIGNED_BYTE causing it to think that rendering skipped a colour value. - D3DFMT_A8R8G8B8, - D3DFMT_R5G6B5, - // D3DFMT_X1R5G5B5, // Has no compatible OpenGL ES renderbuffer format - D3DFMT_X8R8G8B8 - }; - - const D3DFORMAT depthStencilFormats[] = - { - D3DFMT_UNKNOWN, - // D3DFMT_D16_LOCKABLE, - D3DFMT_D32, - // D3DFMT_D15S1, - D3DFMT_D24S8, - D3DFMT_D24X8, - // D3DFMT_D24X4S4, - D3DFMT_D16, - // D3DFMT_D32F_LOCKABLE, - // D3DFMT_D24FS8 - }; - - D3DDISPLAYMODE currentDisplayMode; - mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); - - ConfigSet configSet; - - for (unsigned int formatIndex = 0; formatIndex < sizeof(renderTargetFormats) / sizeof(D3DFORMAT); formatIndex++) - { - D3DFORMAT renderTargetFormat = renderTargetFormats[formatIndex]; - - HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, renderTargetFormat); - - if (SUCCEEDED(result)) - { - for (unsigned int depthStencilIndex = 0; depthStencilIndex < sizeof(depthStencilFormats) / sizeof(D3DFORMAT); depthStencilIndex++) - { - D3DFORMAT depthStencilFormat = depthStencilFormats[depthStencilIndex]; - HRESULT result = D3D_OK; - - if(depthStencilFormat != D3DFMT_UNKNOWN) - { - result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, depthStencilFormat); - } - - if (SUCCEEDED(result)) - { - if(depthStencilFormat != D3DFMT_UNKNOWN) - { - result = mD3d9->CheckDepthStencilMatch(mAdapter, mDeviceType, currentDisplayMode.Format, renderTargetFormat, depthStencilFormat); - } - - if (SUCCEEDED(result)) - { - // FIXME: enumerate multi-sampling - - configSet.add(currentDisplayMode, mMinSwapInterval, mMaxSwapInterval, renderTargetFormat, depthStencilFormat, 0, - mDeviceCaps.MaxTextureWidth, mDeviceCaps.MaxTextureHeight); - } - } - } - } - } - - // Give the sorted configs a unique ID and store them internally - EGLint index = 1; - for (ConfigSet::Iterator config = configSet.mSet.begin(); config != configSet.mSet.end(); config++) - { - Config configuration = *config; - configuration.mConfigID = index; - index++; - - mConfigSet.mSet.insert(configuration); - } - } + mRenderer->deleteConfigs(descList); + descList = NULL; if (!isInitialized()) { terminate(); - return false; } initExtensionString(); - - static const TCHAR windowName[] = TEXT("AngleHiddenWindow"); - static const TCHAR className[] = TEXT("STATIC"); - - mDeviceWindow = CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL); - - if (!createDevice()) - { - terminate(); - return false; - } - - mVertexShaderCache.initialize(mDevice); - mPixelShaderCache.initialize(mDevice); + initVendorString(); return true; } @@ -350,85 +130,8 @@ void Display::terminate() destroyContext(*mContextSet.begin()); } - while (!mEventQueryPool.empty()) - { - mEventQueryPool.back()->Release(); - mEventQueryPool.pop_back(); - } - - mVertexShaderCache.clear(); - mPixelShaderCache.clear(); - - if (mDevice) - { - // If the device is lost, reset it first to prevent leaving the driver in an unstable state - if (testDeviceLost()) - { - resetDevice(); - } - - mDevice->Release(); - mDevice = NULL; - } - - if (mDeviceEx) - { - mDeviceEx->Release(); - mDeviceEx = NULL; - } - - if (mD3d9) - { - mD3d9->Release(); - mD3d9 = NULL; - } - - if (mDeviceWindow) - { - DestroyWindow(mDeviceWindow); - mDeviceWindow = NULL; - } - - if (mD3d9Ex) - { - mD3d9Ex->Release(); - mD3d9Ex = NULL; - } - - if (mD3d9Module) - { - mD3d9Module = NULL; - } - - if (mD3dCompilerModule) - { - FreeLibrary(mD3dCompilerModule); - mD3dCompilerModule = NULL; - } -} - -void Display::startScene() -{ - if (!mSceneStarted) - { - long result = mDevice->BeginScene(); - if (SUCCEEDED(result)) { - // This is defensive checking against the device being - // lost at unexpected times. - mSceneStarted = true; - } - } -} - -void Display::endScene() -{ - if (mSceneStarted) - { - // EndScene can fail if the device was lost, for example due - // to a TDR during a draw call. - mDevice->EndScene(); - mSceneStarted = false; - } + glDestroyRenderer(mRenderer); + mRenderer = NULL; } bool Display::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig) @@ -481,111 +184,7 @@ bool Display::getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value) return true; } -bool Display::createDevice() -{ - if (!isInitialized()) - { - return error(EGL_NOT_INITIALIZED, false); - } - D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters(); - DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES; - HRESULT result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice); - - if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DEVICELOST) - { - return error(EGL_BAD_ALLOC, false); - } - - if (FAILED(result)) - { - result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_NOTAVAILABLE || result == D3DERR_DEVICELOST); - return error(EGL_BAD_ALLOC, false); - } - } - - if (mD3d9Ex) - { - result = mDevice->QueryInterface(IID_IDirect3DDevice9Ex, (void**) &mDeviceEx); - ASSERT(SUCCEEDED(result)); - } - - initializeDevice(); - - return true; -} - -// do any one-time device initialization -// NOTE: this is also needed after a device lost/reset -// to reset the scene status and ensure the default states are reset. -void Display::initializeDevice() -{ - // Permanent non-default states - mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE); - mDevice->SetRenderState(D3DRS_LASTPIXEL, FALSE); - - if (mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0)) - { - mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, (DWORD&)mDeviceCaps.MaxPointSize); - } - else - { - mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, 0x3F800000); // 1.0f - } - - mSceneStarted = false; -} - -bool Display::resetDevice() -{ - D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters(); - - HRESULT result = D3D_OK; - bool lost = testDeviceLost(); - int attempts = 3; - - while (lost && attempts > 0) - { - if (mDeviceEx) - { - Sleep(500); // Give the graphics driver some CPU time - result = mDeviceEx->ResetEx(&presentParameters, NULL); - } - else - { - result = mDevice->TestCooperativeLevel(); - - while (result == D3DERR_DEVICELOST) - { - Sleep(100); // Give the graphics driver some CPU time - result = mDevice->TestCooperativeLevel(); - } - - if (result == D3DERR_DEVICENOTRESET) - { - result = mDevice->Reset(&presentParameters); - } - } - - lost = testDeviceLost(); - attempts --; - } - - if (FAILED(result)) - { - ERR("Reset/ResetEx failed multiple times: 0x%08X", result); - return error(EGL_BAD_ALLOC, false); - } - - // reset device defaults - initializeDevice(); - - return true; -} EGLSurface Display::createWindowSurface(HWND window, EGLConfig config, const EGLint *attribList) { @@ -629,7 +228,7 @@ EGLSurface Display::createWindowSurface(HWND window, EGLConfig config, const EGL return error(EGL_BAD_ALLOC, EGL_NO_SURFACE); } - if (testDeviceLost()) + if (mRenderer->testDeviceLost(false)) { if (!restoreLostDevice()) return EGL_NO_SURFACE; @@ -720,7 +319,7 @@ EGLSurface Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle, return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); } - if (textureFormat != EGL_NO_TEXTURE && !getNonPower2TextureSupport() && (!gl::isPow2(width) || !gl::isPow2(height))) + if (textureFormat != EGL_NO_TEXTURE && !mRenderer->getNonPower2TextureSupport() && (!gl::isPow2(width) || !gl::isPow2(height))) { return error(EGL_BAD_MATCH, EGL_NO_SURFACE); } @@ -742,7 +341,7 @@ EGLSurface Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle, return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); } - if (testDeviceLost()) + if (mRenderer->testDeviceLost(false)) { if (!restoreLostDevice()) return EGL_NO_SURFACE; @@ -763,24 +362,18 @@ EGLSurface Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle, EGLContext Display::createContext(EGLConfig configHandle, const gl::Context *shareContext, bool notifyResets, bool robustAccess) { - if (!mDevice) + if (!mRenderer) { - if (!createDevice()) - { - return NULL; - } + return NULL; } - else if (testDeviceLost()) // Lost device + else if (mRenderer->testDeviceLost(false)) // Lost device { if (!restoreLostDevice()) return NULL; } - const egl::Config *config = mConfigSet.get(configHandle); - - gl::Context *context = glCreateContext(config, shareContext, notifyResets, robustAccess); + gl::Context *context = glCreateContext(shareContext, mRenderer, notifyResets, robustAccess); mContextSet.insert(context); - mDeviceLost = false; return context; } @@ -799,18 +392,9 @@ bool Display::restoreLostDevice() (*surface)->release(); } - while (!mEventQueryPool.empty()) + if (!mRenderer->resetDevice()) { - mEventQueryPool.back()->Release(); - mEventQueryPool.pop_back(); - } - - mVertexShaderCache.clear(); - mPixelShaderCache.clear(); - - if (!resetDevice()) - { - return false; + return error(EGL_BAD_ALLOC, false); } // Restore any surfaces that may have been lost @@ -841,18 +425,20 @@ void Display::notifyDeviceLost() { (*context)->markContextLost(); } - mDeviceLost = true; - error(EGL_CONTEXT_LOST); + egl::error(EGL_CONTEXT_LOST); } -bool Display::isDeviceLost() +void Display::recreateSwapChains() { - return mDeviceLost; + for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++) + { + (*surface)->getSwapChain()->recreate(); + } } bool Display::isInitialized() const { - return mD3d9 != NULL && mConfigSet.size() > 0; + return mRenderer != NULL && mConfigSet.size() > 0; } bool Display::isValidConfig(EGLConfig config) @@ -883,354 +469,10 @@ bool Display::hasExistingWindowSurface(HWND window) return false; } -EGLint Display::getMinSwapInterval() -{ - return mMinSwapInterval; -} - -EGLint Display::getMaxSwapInterval() -{ - return mMaxSwapInterval; -} - -IDirect3DDevice9 *Display::getDevice() -{ - if (!mDevice) - { - if (!createDevice()) - { - return NULL; - } - } - - return mDevice; -} - -D3DCAPS9 Display::getDeviceCaps() -{ - return mDeviceCaps; -} - -D3DADAPTER_IDENTIFIER9 *Display::getAdapterIdentifier() -{ - return &mAdapterIdentifier; -} - -bool Display::testDeviceLost() -{ - bool isLost = false; - - if (mDeviceEx) - { - isLost = FAILED(mDeviceEx->CheckDeviceState(NULL)); - } - else if (mDevice) - { - isLost = FAILED(mDevice->TestCooperativeLevel()); - } - - return isLost; -} - -bool Display::testDeviceResettable() -{ - HRESULT status = D3D_OK; - - if (mDeviceEx) - { - status = mDeviceEx->CheckDeviceState(NULL); - } - else if (mDevice) - { - status = mDevice->TestCooperativeLevel(); - } - - switch (status) - { - case D3DERR_DEVICENOTRESET: - case D3DERR_DEVICEHUNG: - return true; - default: - return false; - } -} - -void Display::sync(bool block) -{ - HRESULT result; - - IDirect3DQuery9* query = allocateEventQuery(); - if (!query) - { - return; - } - - result = query->Issue(D3DISSUE_END); - ASSERT(SUCCEEDED(result)); - - do - { - result = query->GetData(NULL, 0, D3DGETDATA_FLUSH); - - if(block && result == S_FALSE) - { - // Keep polling, but allow other threads to do something useful first - Sleep(0); - // explicitly check for device loss - // some drivers seem to return S_FALSE even if the device is lost - // instead of D3DERR_DEVICELOST like they should - if (testDeviceLost()) - { - result = D3DERR_DEVICELOST; - } - } - } - while(block && result == S_FALSE); - - freeEventQuery(query); - - if (isDeviceLostError(result)) - { - notifyDeviceLost(); - } -} - -IDirect3DQuery9* Display::allocateEventQuery() -{ - IDirect3DQuery9 *query = NULL; - - if (mEventQueryPool.empty()) - { - HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &query); - ASSERT(SUCCEEDED(result)); - } - else - { - query = mEventQueryPool.back(); - mEventQueryPool.pop_back(); - } - - return query; -} - -void Display::freeEventQuery(IDirect3DQuery9* query) -{ - if (mEventQueryPool.size() > 1000) - { - query->Release(); - } - else - { - mEventQueryPool.push_back(query); - } -} - -void Display::getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray) -{ - for (int multiSampleIndex = 0; multiSampleIndex <= D3DMULTISAMPLE_16_SAMPLES; multiSampleIndex++) - { - HRESULT result = mD3d9->CheckDeviceMultiSampleType(mAdapter, mDeviceType, format, - TRUE, (D3DMULTISAMPLE_TYPE)multiSampleIndex, NULL); - - multiSampleArray[multiSampleIndex] = SUCCEEDED(result); - } -} - -bool Display::getDXT1TextureSupport() -{ - D3DDISPLAYMODE currentDisplayMode; - mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); - - return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT1)); -} - -bool Display::getDXT3TextureSupport() -{ - D3DDISPLAYMODE currentDisplayMode; - mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); - - return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT3)); -} - -bool Display::getDXT5TextureSupport() -{ - D3DDISPLAYMODE currentDisplayMode; - mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); - - return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT5)); -} - -// we use INTZ for depth textures in Direct3D9 -// we also want NULL texture support to ensure the we can make depth-only FBOs -// see http://aras-p.info/texts/D3D9GPUHacks.html -bool Display::getDepthTextureSupport() const -{ - D3DDISPLAYMODE currentDisplayMode; - mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); - - bool intz = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, - D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, D3DFMT_INTZ)); - bool null = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, - D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL)); - - return intz && null; -} - -bool Display::getFloat32TextureSupport(bool *filtering, bool *renderable) -{ - D3DDISPLAYMODE currentDisplayMode; - mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); - - *filtering = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER, - D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) && - SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER, - D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F)); - - *renderable = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, - D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F))&& - SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, - D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F)); - - if (!*filtering && !*renderable) - { - return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, - D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) && - SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, - D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F)); - } - else - { - return true; - } -} - -bool Display::getFloat16TextureSupport(bool *filtering, bool *renderable) -{ - D3DDISPLAYMODE currentDisplayMode; - mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); - - *filtering = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER, - D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) && - SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER, - D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F)); - - *renderable = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, - D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) && - SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, - D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F)); - - if (!*filtering && !*renderable) - { - return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, - D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) && - SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, - D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F)); - } - else - { - return true; - } -} - -bool Display::getLuminanceTextureSupport() -{ - D3DDISPLAYMODE currentDisplayMode; - mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); - - return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_L8)); -} - -bool Display::getLuminanceAlphaTextureSupport() -{ - D3DDISPLAYMODE currentDisplayMode; - mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); - - return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_A8L8)); -} - -float Display::getTextureFilterAnisotropySupport() const -{ - // Must support a minimum of 2:1 anisotropy for max anisotropy to be considered supported, per the spec - if ((mDeviceCaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) && (mDeviceCaps.MaxAnisotropy >= 2)) - { - return static_cast(mDeviceCaps.MaxAnisotropy); - } - return 1.0f; -} - -D3DPOOL Display::getBufferPool(DWORD usage) const -{ - if (mD3d9Ex != NULL) - { - return D3DPOOL_DEFAULT; - } - else - { - if (!(usage & D3DUSAGE_DYNAMIC)) - { - return D3DPOOL_MANAGED; - } - } - - return D3DPOOL_DEFAULT; -} - -D3DPOOL Display::getTexturePool(DWORD usage) const -{ - if (mD3d9Ex != NULL) - { - return D3DPOOL_DEFAULT; - } - else - { - if (!(usage & (D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_RENDERTARGET))) - { - return D3DPOOL_MANAGED; - } - } - - return D3DPOOL_DEFAULT; -} - -bool Display::getEventQuerySupport() -{ - IDirect3DQuery9 *query = allocateEventQuery(); - if (query) - { - freeEventQuery(query); - return true; - } - else - { - return false; - } -} - -D3DPRESENT_PARAMETERS Display::getDefaultPresentParameters() -{ - D3DPRESENT_PARAMETERS presentParameters = {0}; - - // The default swap chain is never actually used. Surface will create a new swap chain with the proper parameters. - presentParameters.AutoDepthStencilFormat = D3DFMT_UNKNOWN; - presentParameters.BackBufferCount = 1; - presentParameters.BackBufferFormat = D3DFMT_UNKNOWN; - presentParameters.BackBufferWidth = 1; - presentParameters.BackBufferHeight = 1; - presentParameters.EnableAutoDepthStencil = FALSE; - presentParameters.Flags = 0; - presentParameters.hDeviceWindow = mDeviceWindow; - presentParameters.MultiSampleQuality = 0; - presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE; - presentParameters.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; - presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD; - presentParameters.Windowed = TRUE; - - return presentParameters; -} - void Display::initExtensionString() { HMODULE swiftShader = GetModuleHandle(TEXT("swiftshader_d3d9.dll")); + bool shareHandleSupported = mRenderer->getShareHandleSupport(); mExtensionString = ""; @@ -1238,7 +480,7 @@ void Display::initExtensionString() mExtensionString += "EGL_EXT_create_context_robustness "; // ANGLE-specific extensions - if (shareHandleSupported()) + if (shareHandleSupported) { mExtensionString += "EGL_ANGLE_d3d_share_handle_client_buffer "; } @@ -1250,12 +492,15 @@ void Display::initExtensionString() mExtensionString += "EGL_ANGLE_software_display "; } - if (shareHandleSupported()) + if (shareHandleSupported) { mExtensionString += "EGL_ANGLE_surface_d3d_texture_2d_share_handle "; } - mExtensionString += "EGL_NV_post_sub_buffer"; + if (mRenderer->getPostSubBufferSupport()) + { + mExtensionString += "EGL_NV_post_sub_buffer"; + } std::string::size_type end = mExtensionString.find_last_not_of(' '); if (end != std::string::npos) @@ -1269,73 +514,24 @@ const char *Display::getExtensionString() const return mExtensionString.c_str(); } -bool Display::shareHandleSupported() const +void Display::initVendorString() { - // PIX doesn't seem to support using share handles, so disable them. - return isD3d9ExDevice() && !gl::perfActive(); -} + mVendorString = "Google Inc."; -IDirect3DVertexShader9 *Display::createVertexShader(const DWORD *function, size_t length) -{ - return mVertexShaderCache.create(function, length); -} + LUID adapterLuid = {0}; -HRESULT Display::compileShaderSource(const char* hlsl, const char* sourceName, const char* profile, DWORD flags, ID3DBlob** binary, ID3DBlob** errorMessage) -{ - return mD3DCompileFunc(hlsl, strlen(hlsl), sourceName, NULL, NULL, "main", profile, flags, 0, binary, errorMessage); -} - -IDirect3DPixelShader9 *Display::createPixelShader(const DWORD *function, size_t length) -{ - return mPixelShaderCache.create(function, length); -} - -// Only Direct3D 10 ready devices support all the necessary vertex texture formats. -// We test this using D3D9 by checking support for the R16F format. -bool Display::getVertexTextureSupport() const -{ - if (!isInitialized() || mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(3, 0)) + if (mRenderer && mRenderer->getLUID(&adapterLuid)) { - return false; - } + char adapterLuidString[64]; + sprintf_s(adapterLuidString, sizeof(adapterLuidString), " (adapter LUID: %08x%08x)", adapterLuid.HighPart, adapterLuid.LowPart); - D3DDISPLAYMODE currentDisplayMode; - mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); - - HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F); - - return SUCCEEDED(result); -} - -bool Display::getNonPower2TextureSupport() const -{ - return mSupportsNonPower2Textures; -} - -bool Display::getOcclusionQuerySupport() const -{ - if (!isInitialized()) - { - return false; - } - - IDirect3DQuery9 *query = NULL; - HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, &query); - - if (SUCCEEDED(result) && query) - { - query->Release(); - return true; - } - else - { - return false; + mVendorString += adapterLuidString; } } -bool Display::getInstancingSupport() const +const char *Display::getVendorString() const { - return mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0); + return mVendorString.c_str(); } } diff --git a/gfx/angle/src/libEGL/Display.h b/gfx/angle/src/libEGL/Display.h index a1a78708dca1..58c3940331b3 100644 --- a/gfx/angle/src/libEGL/Display.h +++ b/gfx/angle/src/libEGL/Display.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -12,33 +12,21 @@ #define LIBEGL_DISPLAY_H_ #include "common/system.h" -#include -#include #include #include -#include "libGLESv2/Context.h" - #include "libEGL/Config.h" -#include "libEGL/ShaderCache.h" -#include "libEGL/Surface.h" -const int versionWindowsVista = MAKEWORD(0x00, 0x06); -const int versionWindows7 = MAKEWORD(0x01, 0x06); - -// Return the version of the operating system in a format suitable for ordering -// comparison. -inline int getComparableOSVersion() +namespace gl { - DWORD version = GetVersion(); - int majorVersion = LOBYTE(LOWORD(version)); - int minorVersion = HIBYTE(LOWORD(version)); - return MAKEWORD(minorVersion, majorVersion); +class Context; } namespace egl { +class Surface; + class Display { public: @@ -47,9 +35,6 @@ class Display bool initialize(); void terminate(); - virtual void startScene(); - virtual void endScene(); - static egl::Display *getDisplay(EGLNativeDisplayType displayId); bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig); @@ -68,83 +53,26 @@ class Display bool isValidSurface(egl::Surface *surface); bool hasExistingWindowSurface(HWND window); - EGLint getMinSwapInterval(); - EGLint getMaxSwapInterval(); - - virtual IDirect3DDevice9 *getDevice(); - virtual D3DCAPS9 getDeviceCaps(); - virtual D3DADAPTER_IDENTIFIER9 *getAdapterIdentifier(); - virtual bool testDeviceLost(); - virtual bool testDeviceResettable(); - virtual void sync(bool block); - virtual IDirect3DQuery9* allocateEventQuery(); - virtual void freeEventQuery(IDirect3DQuery9* query); - virtual void getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray); - virtual bool getDXT1TextureSupport(); - virtual bool getDXT3TextureSupport(); - virtual bool getDXT5TextureSupport(); - virtual bool getEventQuerySupport(); - virtual bool getFloat32TextureSupport(bool *filtering, bool *renderable); - virtual bool getFloat16TextureSupport(bool *filtering, bool *renderable); - virtual bool getLuminanceTextureSupport(); - virtual bool getLuminanceAlphaTextureSupport(); - virtual bool getVertexTextureSupport() const; - virtual bool getNonPower2TextureSupport() const; - virtual bool getDepthTextureSupport() const; - virtual bool getOcclusionQuerySupport() const; - virtual bool getInstancingSupport() const; - virtual float getTextureFilterAnisotropySupport() const; - virtual D3DPOOL getBufferPool(DWORD usage) const; - virtual D3DPOOL getTexturePool(DWORD usage) const; + rx::Renderer *getRenderer() { return mRenderer; }; + // exported methods must be virtual virtual void notifyDeviceLost(); - bool isDeviceLost(); + virtual void recreateSwapChains(); - bool isD3d9ExDevice() const { return mD3d9Ex != NULL; } const char *getExtensionString() const; - bool shareHandleSupported() const; - - virtual IDirect3DVertexShader9 *createVertexShader(const DWORD *function, size_t length); - virtual IDirect3DPixelShader9 *createPixelShader(const DWORD *function, size_t length); - - virtual HRESULT compileShaderSource(const char* hlsl, const char* sourceName, const char* profile, DWORD flags, ID3DBlob** binary, ID3DBlob** errorMessage); + const char *getVendorString() const; private: DISALLOW_COPY_AND_ASSIGN(Display); - Display(EGLNativeDisplayType displayId, HDC deviceContext, bool software); - - D3DPRESENT_PARAMETERS getDefaultPresentParameters(); + Display(EGLNativeDisplayType displayId, HDC deviceContext); bool restoreLostDevice(); EGLNativeDisplayType mDisplayId; const HDC mDc; - HMODULE mD3d9Module; - - UINT mAdapter; - D3DDEVTYPE mDeviceType; - IDirect3D9 *mD3d9; // Always valid after successful initialization. - IDirect3D9Ex *mD3d9Ex; // Might be null if D3D9Ex is not supported. - IDirect3DDevice9 *mDevice; - IDirect3DDevice9Ex *mDeviceEx; // Might be null if D3D9Ex is not supported. - - // A pool of event queries that are currently unused. - std::vector mEventQueryPool; - - VertexShaderCache mVertexShaderCache; - PixelShaderCache mPixelShaderCache; - - D3DCAPS9 mDeviceCaps; - D3DADAPTER_IDENTIFIER9 mAdapterIdentifier; - HWND mDeviceWindow; - - bool mSceneStarted; - EGLint mMaxSwapInterval; - EGLint mMinSwapInterval; bool mSoftwareDevice; - bool mSupportsNonPower2Textures; typedef std::set SurfaceSet; SurfaceSet mSurfaceSet; @@ -153,29 +81,13 @@ class Display typedef std::set ContextSet; ContextSet mContextSet; - bool mDeviceLost; - bool createDevice(); - void initializeDevice(); - bool resetDevice(); + rx::Renderer *mRenderer; void initExtensionString(); + void initVendorString(); std::string mExtensionString; - - typedef HRESULT (WINAPI *D3DCompileFunc)(LPCVOID pSrcData, - SIZE_T SrcDataSize, - LPCSTR pSourceName, - CONST D3D_SHADER_MACRO* pDefines, - ID3DInclude* pInclude, - LPCSTR pEntrypoint, - LPCSTR pTarget, - UINT Flags1, - UINT Flags2, - ID3DBlob** ppCode, - ID3DBlob** ppErrorMsgs); - - HMODULE mD3dCompilerModule; - D3DCompileFunc mD3DCompileFunc; + std::string mVendorString; }; } diff --git a/gfx/angle/src/libEGL/Makefile.in b/gfx/angle/src/libEGL/Makefile.in index 3570212c9a55..dfaba3d70866 100644 --- a/gfx/angle/src/libEGL/Makefile.in +++ b/gfx/angle/src/libEGL/Makefile.in @@ -19,16 +19,16 @@ endif OS_COMPILE_CFLAGS = $(OS_CPPFLAGS) OS_COMPILE_CXXFLAGS = $(OS_CPPFLAGS) -DEFINES += -DANGLE_BUILD -DNOMINMAX -DLIBEGL_EXPORTS -D_CRT_SECURE_NO_DEPRECATE - -DEFINES += -DANGLE_DISABLE_TRACE -DEFINES += -DANGLE_COMPILE_OPTIMIZATION_LEVEL=D3DCOMPILE_OPTIMIZATION_LEVEL1 +DEFINES += -DLIBEGL_EXPORTS +DEFINES += -DANGLE_BUILD -DNOMINMAX -D_CRT_SECURE_NO_DEPRECATE ifndef MOZ_DEBUG DEFINES += -D_SECURE_SCL=0 endif # Below is a transcription of the EGL target from build_angle.gypi. +DEFINES += -DANGLE_DISABLE_TRACE +DEFINES += -DANGLE_COMPILE_OPTIMIZATION_LEVEL=D3DCOMPILE_OPTIMIZATION_LEVEL1 # Target: 'libEGL' # Links with: 'libGLESv2' @@ -36,30 +36,29 @@ LOCAL_INCLUDES = \ -I$(srcdir)/../../include \ -I$(srcdir)/../../include/KHR \ -I$(srcdir)/.. \ - -I"$(MOZ_DIRECTX_SDK_PATH)/include" + -I$(srcdir)/../libGLESv2 +# -I"$(MOZ_DIRECTX_SDK_PATH)/include" -VPATH += $(srcdir)/../common # src/common: -VPATH += $(srcdir)/../libEGL +VPATH += $(srcdir)/../common # src/libEGL: +VPATH += $(srcdir)/../libEGL DEFFILE = $(srcdir)/libEGL.def RCFILE = $(srcdir)/libEGL.rc include $(topsrcdir)/config/rules.mk -OS_LIBS += $(call EXPAND_LIBNAME,dwmapi) +#OS_LIBS += $(call EXPAND_LIBNAME,dwmapi) ifdef GNU_CC OS_CXXFLAGS := $(filter-out -fno-exceptions,$(OS_CXXFLAGS)) -fexceptions -OS_LIBS += -ld3d9 -ldxguid -llibGLESv2 +OS_LIBS += -ld3d9 -llibGLESv2 else EXTRA_DSO_LDOPTS = "$(MOZ_DIRECTX_SDK_PATH)/lib/$(MOZ_DIRECTX_SDK_CPU_SUFFIX)/d3d9.lib" \ - "$(MOZ_DIRECTX_SDK_PATH)/lib/$(MOZ_DIRECTX_SDK_CPU_SUFFIX)/dxguid.lib" \ - "$(DIST)/lib/libGLESv2.lib" \ - delayimp.lib \ - /delayload:dwmapi.dll + "$(DIST)/lib/libGLESv2.lib" \ + delayimp.lib endif diff --git a/gfx/angle/src/libEGL/Surface.cpp b/gfx/angle/src/libEGL/Surface.cpp index 861ca8c4be3f..539c4c623d82 100644 --- a/gfx/angle/src/libEGL/Surface.cpp +++ b/gfx/angle/src/libEGL/Surface.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -14,6 +14,8 @@ #include "common/debug.h" #include "libGLESv2/Texture.h" +#include "libGLESv2/renderer/SwapChain.h" +#include "libGLESv2/main.h" #include "libEGL/main.h" #include "libEGL/Display.h" @@ -24,11 +26,8 @@ namespace egl Surface::Surface(Display *display, const Config *config, HWND window, EGLint postSubBufferSupported) : mDisplay(display), mConfig(config), mWindow(window), mPostSubBufferSupported(postSubBufferSupported) { + mRenderer = mDisplay->getRenderer(); mSwapChain = NULL; - mBackBuffer = NULL; - mDepthStencil = NULL; - mRenderTarget = NULL; - mOffscreenTexture = NULL; mShareHandle = NULL; mTexture = NULL; mTextureFormat = EGL_NO_TEXTURE; @@ -38,6 +37,8 @@ Surface::Surface(Display *display, const Config *config, HWND window, EGLint pos mRenderBuffer = EGL_BACK_BUFFER; mSwapBehavior = EGL_BUFFER_PRESERVED; mSwapInterval = -1; + mWidth = -1; + mHeight = -1; setSwapInterval(1); subclassWindow(); @@ -46,11 +47,8 @@ Surface::Surface(Display *display, const Config *config, HWND window, EGLint pos Surface::Surface(Display *display, const Config *config, HANDLE shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureType) : mDisplay(display), mWindow(NULL), mConfig(config), mShareHandle(shareHandle), mWidth(width), mHeight(height), mPostSubBufferSupported(EGL_FALSE) { + mRenderer = mDisplay->getRenderer(); mSwapChain = NULL; - mBackBuffer = NULL; - mDepthStencil = NULL; - mRenderTarget = NULL; - mOffscreenTexture = NULL; mWindowSubclassed = false; mTexture = NULL; mTextureFormat = textureFormat; @@ -71,8 +69,6 @@ Surface::~Surface() bool Surface::initialize() { - ASSERT(!mSwapChain && !mOffscreenTexture && !mDepthStencil); - if (!resetSwapChain()) return false; @@ -81,278 +77,107 @@ bool Surface::initialize() void Surface::release() { - if (mSwapChain) - { - mSwapChain->Release(); - mSwapChain = NULL; - } - - if (mBackBuffer) - { - mBackBuffer->Release(); - mBackBuffer = NULL; - } - - if (mDepthStencil) - { - mDepthStencil->Release(); - mDepthStencil = NULL; - } - - if (mRenderTarget) - { - mRenderTarget->Release(); - mRenderTarget = NULL; - } - - if (mOffscreenTexture) - { - mOffscreenTexture->Release(); - mOffscreenTexture = NULL; - } + delete mSwapChain; + mSwapChain = NULL; if (mTexture) { mTexture->releaseTexImage(); mTexture = NULL; } - - mShareHandle = NULL; } bool Surface::resetSwapChain() { - if (!mWindow) - { - return resetSwapChain(mWidth, mHeight); - } + ASSERT(!mSwapChain); - RECT windowRect; - if (!GetClientRect(getWindowHandle(), &windowRect)) - { - ASSERT(false); - - ERR("Could not retrieve the window dimensions"); - return false; - } - - return resetSwapChain(windowRect.right - windowRect.left, windowRect.bottom - windowRect.top); -} - -bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight) -{ - IDirect3DDevice9 *device = mDisplay->getDevice(); - - if (device == NULL) - { - return false; - } - - // Evict all non-render target textures to system memory and release all resources - // before reallocating them to free up as much video memory as possible. - device->EvictManagedResources(); - - HRESULT result; - - // Release specific resources to free up memory for the new render target, while the - // old render target still exists for the purpose of preserving its contents. - if (mSwapChain) - { - mSwapChain->Release(); - mSwapChain = NULL; - } - - if (mBackBuffer) - { - mBackBuffer->Release(); - mBackBuffer = NULL; - } - - if (mOffscreenTexture) - { - mOffscreenTexture->Release(); - mOffscreenTexture = NULL; - } - - if (mDepthStencil) - { - mDepthStencil->Release(); - mDepthStencil = NULL; - } - - mShareHandle = NULL; - HANDLE *pShareHandle = NULL; - if (!mWindow && mDisplay->shareHandleSupported()) - { - pShareHandle = &mShareHandle; - } - - result = device->CreateTexture(backbufferWidth, backbufferHeight, 1, D3DUSAGE_RENDERTARGET, - mConfig->mRenderTargetFormat, D3DPOOL_DEFAULT, &mOffscreenTexture, pShareHandle); - if (FAILED(result)) - { - ERR("Could not create offscreen texture: %08lX", result); - release(); - - if(isDeviceLostError(result)) - { - mDisplay->notifyDeviceLost(); - return false; - } - else - { - return error(EGL_BAD_ALLOC, false); - } - } - - IDirect3DSurface9 *oldRenderTarget = mRenderTarget; - - result = mOffscreenTexture->GetSurfaceLevel(0, &mRenderTarget); - ASSERT(SUCCEEDED(result)); - - if (oldRenderTarget) - { - RECT rect = - { - 0, 0, - mWidth, mHeight - }; - - if (rect.right > static_cast(backbufferWidth)) - { - rect.right = backbufferWidth; - } - - if (rect.bottom > static_cast(backbufferHeight)) - { - rect.bottom = backbufferHeight; - } - - mDisplay->endScene(); - - result = device->StretchRect(oldRenderTarget, &rect, mRenderTarget, &rect, D3DTEXF_NONE); - ASSERT(SUCCEEDED(result)); - - oldRenderTarget->Release(); - } + int width; + int height; if (mWindow) { - D3DPRESENT_PARAMETERS presentParameters = {0}; - presentParameters.AutoDepthStencilFormat = mConfig->mDepthStencilFormat; - presentParameters.BackBufferCount = 1; - presentParameters.BackBufferFormat = mConfig->mRenderTargetFormat; - presentParameters.EnableAutoDepthStencil = FALSE; - presentParameters.Flags = 0; - presentParameters.hDeviceWindow = getWindowHandle(); - presentParameters.MultiSampleQuality = 0; // FIXME: Unimplemented - presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE; // FIXME: Unimplemented - presentParameters.PresentationInterval = mPresentInterval; - presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD; - presentParameters.Windowed = TRUE; - presentParameters.BackBufferWidth = backbufferWidth; - presentParameters.BackBufferHeight = backbufferHeight; - - // http://crbug.com/140239 - // http://crbug.com/143434 - // - // Some AMD/Intel switchable systems / drivers appear to round swap chain surfaces to a multiple of 64 pixels in width - // when using the integrated Intel. This rounds the width up rather than down. - // - // Some non-switchable AMD GPUs / drivers do not respect the source rectangle to Present. Therefore, when the vendor ID - // is not Intel, the back buffer width must be exactly the same width as the window or horizontal scaling will occur. - D3DADAPTER_IDENTIFIER9* adapterIdentifier = mDisplay->getAdapterIdentifier(); - if (adapterIdentifier->VendorId == VENDOR_ID_INTEL) + RECT windowRect; + if (!GetClientRect(getWindowHandle(), &windowRect)) { - presentParameters.BackBufferWidth = (presentParameters.BackBufferWidth + 63) / 64 * 64; + ASSERT(false); + + ERR("Could not retrieve the window dimensions"); + return error(EGL_BAD_SURFACE, false); } - result = device->CreateAdditionalSwapChain(&presentParameters, &mSwapChain); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL || result == D3DERR_DEVICELOST); - - ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result); - release(); - - if(isDeviceLostError(result)) - { - mDisplay->notifyDeviceLost(); - return false; - } - else - { - return error(EGL_BAD_ALLOC, false); - } - } - - result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer); - ASSERT(SUCCEEDED(result)); - InvalidateRect(mWindow, NULL, FALSE); + width = windowRect.right - windowRect.left; + height = windowRect.bottom - windowRect.top; + } + else + { + // non-window surface - size is determined at creation + width = mWidth; + height = mHeight; } - if (mConfig->mDepthStencilFormat != D3DFMT_UNKNOWN) + mSwapChain = mRenderer->createSwapChain(mWindow, mShareHandle, + mConfig->mRenderTargetFormat, + mConfig->mDepthStencilFormat); + if (!mSwapChain) { - result = device->CreateDepthStencilSurface(backbufferWidth, backbufferHeight, mConfig->mDepthStencilFormat, D3DMULTISAMPLE_NONE, - 0, FALSE, &mDepthStencil, NULL); + return error(EGL_BAD_ALLOC, false); + } - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL); + if (!resetSwapChain(width, height)) + { + delete mSwapChain; + mSwapChain = NULL; + return false; + } - ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result); - release(); + return true; +} - if(isDeviceLostError(result)) - { - mDisplay->notifyDeviceLost(); - return false; - } - else - { - return error(EGL_BAD_ALLOC, false); - } - } +bool Surface::resizeSwapChain(int backbufferWidth, int backbufferHeight) +{ + ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0); + ASSERT(mSwapChain); + + EGLint status = mSwapChain->resize(backbufferWidth, backbufferHeight); + + if (status == EGL_CONTEXT_LOST) + { + mDisplay->notifyDeviceLost(); + return false; + } + else if (status != EGL_SUCCESS) + { + return error(status, false); } mWidth = backbufferWidth; mHeight = backbufferHeight; - mPresentIntervalDirty = false; return true; } -void Surface::recreateAdditionalSwapChain() +bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight) { - if (!mSwapChain) + ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0); + ASSERT(mSwapChain); + + EGLint status = mSwapChain->reset(backbufferWidth, backbufferHeight, mSwapInterval); + + if (status == EGL_CONTEXT_LOST) { - return; + mRenderer->notifyDeviceLost(); + return false; + } + else if (status != EGL_SUCCESS) + { + return error(status, false); } - IDirect3DDevice9 *device = mDisplay->getDevice(); - if (device == NULL) - { - return; - } + mWidth = backbufferWidth; + mHeight = backbufferHeight; + mSwapIntervalDirty = false; - D3DPRESENT_PARAMETERS presentParameters; - HRESULT result = mSwapChain->GetPresentParameters(&presentParameters); - ASSERT(SUCCEEDED(result)); - - IDirect3DSwapChain9* newSwapChain = NULL; - result = device->CreateAdditionalSwapChain(&presentParameters, &newSwapChain); - if (FAILED(result)) - { - return; - } - - mSwapChain->Release(); - mSwapChain = newSwapChain; - - mBackBuffer->Release(); - result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer); - ASSERT(SUCCEEDED(result)); + return true; } bool Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) @@ -377,86 +202,18 @@ bool Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) return true; } - IDirect3DDevice9 *device = mDisplay->getDevice(); + EGLint status = mSwapChain->swapRect(x, y, width, height); - // Disable all pipeline operations - device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); - device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); - device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); - device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); - device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); - device->SetRenderState(D3DRS_STENCILENABLE, FALSE); - device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); - device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED); - device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE); - device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); - device->SetPixelShader(NULL); - device->SetVertexShader(NULL); - - device->SetRenderTarget(0, mBackBuffer); - device->SetDepthStencilSurface(NULL); - - device->SetTexture(0, mOffscreenTexture); - device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); - device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); - device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); - device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); - device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); - device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); - device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1); - - D3DVIEWPORT9 viewport = {0, 0, mWidth, mHeight, 0.0f, 1.0f}; - device->SetViewport(&viewport); - - float x1 = x - 0.5f; - float y1 = (mHeight - y - height) - 0.5f; - float x2 = (x + width) - 0.5f; - float y2 = (mHeight - y) - 0.5f; - - float u1 = x / float(mWidth); - float v1 = y / float(mHeight); - float u2 = (x + width) / float(mWidth); - float v2 = (y + height) / float(mHeight); - - float quad[4][6] = {{x1, y1, 0.0f, 1.0f, u1, v2}, - {x2, y1, 0.0f, 1.0f, u2, v2}, - {x2, y2, 0.0f, 1.0f, u2, v1}, - {x1, y2, 0.0f, 1.0f, u1, v1}}; // x, y, z, rhw, u, v - - mDisplay->startScene(); - device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, 6 * sizeof(float)); - mDisplay->endScene(); - - device->SetTexture(0, NULL); - - RECT rect = + if (status == EGL_CONTEXT_LOST) { - x, mHeight - y - height, - x + width, mHeight - y - }; - - HRESULT result = mSwapChain->Present(&rect, &rect, NULL, NULL, 0); - - gl::Context *context = static_cast(glGetCurrentContext()); - if (context) - { - context->markAllStateDirty(); - } - - if (isDeviceLostError(result)) - { - mDisplay->notifyDeviceLost(); + mRenderer->notifyDeviceLost(); return false; } - - if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DRIVERINTERNALERROR) + else if (status != EGL_SUCCESS) { - return error(EGL_BAD_ALLOC, false); + return error(status, false); } - ASSERT(SUCCEEDED(result)); - checkForOutOfDateSwapChain(); return true; @@ -552,9 +309,17 @@ bool Surface::checkForOutOfDateSwapChain() int clientHeight = client.bottom - client.top; bool sizeDirty = clientWidth != getWidth() || clientHeight != getHeight(); - if (sizeDirty || mPresentIntervalDirty) + if (mSwapIntervalDirty) { resetSwapChain(clientWidth, clientHeight); + } + else if (sizeDirty) + { + resizeSwapChain(clientWidth, clientHeight); + } + + if (mSwapIntervalDirty || sizeDirty) + { if (static_cast(getCurrentDrawSurface()) == this) { glMakeCurrent(glGetCurrentContext(), static_cast(getCurrentDisplay()), this); @@ -562,24 +327,10 @@ bool Surface::checkForOutOfDateSwapChain() return true; } + return false; } -DWORD Surface::convertInterval(EGLint interval) -{ - switch(interval) - { - case 0: return D3DPRESENT_INTERVAL_IMMEDIATE; - case 1: return D3DPRESENT_INTERVAL_ONE; - case 2: return D3DPRESENT_INTERVAL_TWO; - case 3: return D3DPRESENT_INTERVAL_THREE; - case 4: return D3DPRESENT_INTERVAL_FOUR; - default: UNREACHABLE(); - } - - return D3DPRESENT_INTERVAL_DEFAULT; -} - bool Surface::swap() { return swapRect(0, 0, mWidth, mHeight); @@ -611,38 +362,9 @@ EGLint Surface::isPostSubBufferSupported() const return mPostSubBufferSupported; } -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *Surface::getRenderTarget() +rx::SwapChain *Surface::getSwapChain() const { - if (mRenderTarget) - { - mRenderTarget->AddRef(); - } - - return mRenderTarget; -} - -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *Surface::getDepthStencil() -{ - if (mDepthStencil) - { - mDepthStencil->AddRef(); - } - - return mDepthStencil; -} - -IDirect3DTexture9 *Surface::getOffscreenTexture() -{ - if (mOffscreenTexture) - { - mOffscreenTexture->AddRef(); - } - - return mOffscreenTexture; + return mSwapChain; } void Surface::setSwapInterval(EGLint interval) @@ -653,11 +375,10 @@ void Surface::setSwapInterval(EGLint interval) } mSwapInterval = interval; - mSwapInterval = std::max(mSwapInterval, mDisplay->getMinSwapInterval()); - mSwapInterval = std::min(mSwapInterval, mDisplay->getMaxSwapInterval()); + mSwapInterval = std::max(mSwapInterval, mRenderer->getMinSwapInterval()); + mSwapInterval = std::min(mSwapInterval, mRenderer->getMaxSwapInterval()); - mPresentInterval = convertInterval(mSwapInterval); - mPresentIntervalDirty = true; + mSwapIntervalDirty = true; } EGLenum Surface::getTextureFormat() const @@ -680,7 +401,7 @@ gl::Texture2D *Surface::getBoundTexture() const return mTexture; } -D3DFORMAT Surface::getFormat() const +EGLenum Surface::getFormat() const { return mConfig->mRenderTargetFormat; } diff --git a/gfx/angle/src/libEGL/Surface.h b/gfx/angle/src/libEGL/Surface.h index 0318460372d0..938b800cdde7 100644 --- a/gfx/angle/src/libEGL/Surface.h +++ b/gfx/angle/src/libEGL/Surface.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -8,12 +8,11 @@ // such as the client area of a window, including any back buffers. // Implements EGLSurface and related functionality. [EGL 1.4] section 2.2 page 3. -#ifndef INCLUDE_SURFACE_H_ -#define INCLUDE_SURFACE_H_ +#ifndef LIBEGL_SURFACE_H_ +#define LIBEGL_SURFACE_H_ #define EGLAPI #include -#include #include "common/angleutils.h" @@ -21,6 +20,11 @@ namespace gl { class Texture2D; } +namespace rx +{ +class Renderer; +class SwapChain; +} namespace egl { @@ -48,41 +52,32 @@ class Surface virtual EGLint isPostSubBufferSupported() const; - virtual IDirect3DSurface9 *getRenderTarget(); - virtual IDirect3DSurface9 *getDepthStencil(); - virtual IDirect3DTexture9 *getOffscreenTexture(); - - HANDLE getShareHandle() { return mShareHandle; } + virtual rx::SwapChain *getSwapChain() const; void setSwapInterval(EGLint interval); bool checkForOutOfDateSwapChain(); // Returns true if swapchain changed due to resize or interval update virtual EGLenum getTextureFormat() const; virtual EGLenum getTextureTarget() const; - virtual D3DFORMAT getFormat() const; + virtual EGLenum getFormat() const; virtual void setBoundTexture(gl::Texture2D *texture); virtual gl::Texture2D *getBoundTexture() const; - void recreateAdditionalSwapChain(); - private: DISALLOW_COPY_AND_ASSIGN(Surface); Display *const mDisplay; - IDirect3DSwapChain9 *mSwapChain; - IDirect3DSurface9 *mBackBuffer; - IDirect3DSurface9 *mDepthStencil; - IDirect3DSurface9* mRenderTarget; - IDirect3DTexture9* mOffscreenTexture; + rx::Renderer *mRenderer; HANDLE mShareHandle; + rx::SwapChain *mSwapChain; void subclassWindow(); void unsubclassWindow(); + bool resizeSwapChain(int backbufferWidth, int backbufferHeight); bool resetSwapChain(int backbufferWidth, int backbufferHeight); bool swapRect(EGLint x, EGLint y, EGLint width, EGLint height); - static DWORD convertInterval(EGLint interval); const HWND mWindow; // Window that the surface is created for. bool mWindowSubclassed; // Indicates whether we successfully subclassed mWindow for WM_RESIZE hooking @@ -105,10 +100,9 @@ private: EGLint mSwapInterval; EGLint mPostSubBufferSupported; - DWORD mPresentInterval; - bool mPresentIntervalDirty; + bool mSwapIntervalDirty; gl::Texture2D *mTexture; }; } -#endif // INCLUDE_SURFACE_H_ +#endif // LIBEGL_SURFACE_H_ diff --git a/gfx/angle/src/libEGL/libEGL.cpp b/gfx/angle/src/libEGL/libEGL.cpp index 25df1c8c245a..6e10c3926d44 100644 --- a/gfx/angle/src/libEGL/libEGL.cpp +++ b/gfx/angle/src/libEGL/libEGL.cpp @@ -12,21 +12,23 @@ #include "common/version.h" #include "libGLESv2/Context.h" #include "libGLESv2/Texture.h" +#include "libGLESv2/main.h" +#include "libGLESv2/renderer/SwapChain.h" #include "libEGL/main.h" #include "libEGL/Display.h" - +#include "libEGL/Surface.h" bool validateDisplay(egl::Display *display) { if (display == EGL_NO_DISPLAY) { - return error(EGL_BAD_DISPLAY, false); + return egl::error(EGL_BAD_DISPLAY, false); } if (!display->isInitialized()) { - return error(EGL_NOT_INITIALIZED, false); + return egl::error(EGL_NOT_INITIALIZED, false); } return true; @@ -41,7 +43,7 @@ bool validateConfig(egl::Display *display, EGLConfig config) if (!display->isValidConfig(config)) { - return error(EGL_BAD_CONFIG, false); + return egl::error(EGL_BAD_CONFIG, false); } return true; @@ -56,7 +58,7 @@ bool validateContext(egl::Display *display, gl::Context *context) if (!display->isValidContext(context)) { - return error(EGL_BAD_CONTEXT, false); + return egl::error(EGL_BAD_CONTEXT, false); } return true; @@ -71,7 +73,7 @@ bool validateSurface(egl::Display *display, egl::Surface *surface) if (!display->isValidSurface(surface)) { - return error(EGL_BAD_SURFACE, false); + return egl::error(EGL_BAD_SURFACE, false); } return true; @@ -103,7 +105,7 @@ EGLDisplay __stdcall eglGetDisplay(EGLNativeDisplayType display_id) } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_NO_DISPLAY); + return egl::error(EGL_BAD_ALLOC, EGL_NO_DISPLAY); } } @@ -116,24 +118,24 @@ EGLBoolean __stdcall eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) { if (dpy == EGL_NO_DISPLAY) { - return error(EGL_BAD_DISPLAY, EGL_FALSE); + return egl::error(EGL_BAD_DISPLAY, EGL_FALSE); } egl::Display *display = static_cast(dpy); if (!display->initialize()) { - return error(EGL_NOT_INITIALIZED, EGL_FALSE); + return egl::error(EGL_NOT_INITIALIZED, EGL_FALSE); } if (major) *major = 1; if (minor) *minor = 4; - return success(EGL_TRUE); + return egl::success(EGL_TRUE); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -145,18 +147,18 @@ EGLBoolean __stdcall eglTerminate(EGLDisplay dpy) { if (dpy == EGL_NO_DISPLAY) { - return error(EGL_BAD_DISPLAY, EGL_FALSE); + return egl::error(EGL_BAD_DISPLAY, EGL_FALSE); } egl::Display *display = static_cast(dpy); display->terminate(); - return success(EGL_TRUE); + return egl::success(EGL_TRUE); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -176,20 +178,20 @@ const char *__stdcall eglQueryString(EGLDisplay dpy, EGLint name) switch (name) { case EGL_CLIENT_APIS: - return success("OpenGL_ES"); + return egl::success("OpenGL_ES"); case EGL_EXTENSIONS: - return display->getExtensionString(); + return egl::success(display->getExtensionString()); case EGL_VENDOR: - return success("Google Inc."); + return egl::success(display->getVendorString()); case EGL_VERSION: - return success("1.4 (ANGLE " VERSION_STRING ")"); + return egl::success("1.4 (ANGLE " VERSION_STRING ")"); } - return error(EGL_BAD_PARAMETER, (const char*)NULL); + return egl::error(EGL_BAD_PARAMETER, (const char*)NULL); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, (const char*)NULL); + return egl::error(EGL_BAD_ALLOC, (const char*)NULL); } } @@ -210,21 +212,21 @@ EGLBoolean __stdcall eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint co if (!num_config) { - return error(EGL_BAD_PARAMETER, EGL_FALSE); + return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); } const EGLint attribList[] = {EGL_NONE}; if (!display->getConfigs(configs, attribList, config_size, num_config)) { - return error(EGL_BAD_ATTRIBUTE, EGL_FALSE); + return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE); } - return success(EGL_TRUE); + return egl::success(EGL_TRUE); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -245,7 +247,7 @@ EGLBoolean __stdcall eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, if (!num_config) { - return error(EGL_BAD_PARAMETER, EGL_FALSE); + return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); } const EGLint attribList[] = {EGL_NONE}; @@ -257,11 +259,11 @@ EGLBoolean __stdcall eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, display->getConfigs(configs, attrib_list, config_size, num_config); - return success(EGL_TRUE); + return egl::success(EGL_TRUE); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -281,14 +283,14 @@ EGLBoolean __stdcall eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint if (!display->getConfigAttrib(config, attribute, value)) { - return error(EGL_BAD_ATTRIBUTE, EGL_FALSE); + return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE); } - return success(EGL_TRUE); + return egl::success(EGL_TRUE); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -310,14 +312,14 @@ EGLSurface __stdcall eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EG if (!IsWindow(window)) { - return error(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); + return egl::error(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); } return display->createWindowSurface(window, config, attrib_list); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_NO_SURFACE); + return egl::error(EGL_BAD_ALLOC, EGL_NO_SURFACE); } } @@ -339,7 +341,7 @@ EGLSurface __stdcall eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, c } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_NO_SURFACE); + return egl::error(EGL_BAD_ALLOC, EGL_NO_SURFACE); } } @@ -359,11 +361,11 @@ EGLSurface __stdcall eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EG UNIMPLEMENTED(); // FIXME - return success(EGL_NO_SURFACE); + return egl::success(EGL_NO_SURFACE); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_NO_SURFACE); + return egl::error(EGL_BAD_ALLOC, EGL_NO_SURFACE); } } @@ -383,16 +385,16 @@ EGLBoolean __stdcall eglDestroySurface(EGLDisplay dpy, EGLSurface surface) if (surface == EGL_NO_SURFACE) { - return error(EGL_BAD_SURFACE, EGL_FALSE); + return egl::error(EGL_BAD_SURFACE, EGL_FALSE); } display->destroySurface((egl::Surface*)surface); - return success(EGL_TRUE); + return egl::success(EGL_TRUE); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -413,7 +415,7 @@ EGLBoolean __stdcall eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint if (surface == EGL_NO_SURFACE) { - return error(EGL_BAD_SURFACE, EGL_FALSE); + return egl::error(EGL_BAD_SURFACE, EGL_FALSE); } switch (attribute) @@ -470,14 +472,14 @@ EGLBoolean __stdcall eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint *value = eglSurface->isPostSubBufferSupported(); break; default: - return error(EGL_BAD_ATTRIBUTE, EGL_FALSE); + return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE); } - return success(EGL_TRUE); + return egl::success(EGL_TRUE); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -498,23 +500,26 @@ EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surf if (surface == EGL_NO_SURFACE) { - return error(EGL_BAD_SURFACE, EGL_FALSE); + return egl::error(EGL_BAD_SURFACE, EGL_FALSE); } switch (attribute) { case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE: - *value = (void*) eglSurface->getShareHandle(); + { + rx::SwapChain *swapchain = eglSurface->getSwapChain(); + *value = (void*) (swapchain ? swapchain->getShareHandle() : NULL); + } break; default: - return error(EGL_BAD_ATTRIBUTE, EGL_FALSE); + return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE); } - return success(EGL_TRUE); + return egl::success(EGL_TRUE); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -528,20 +533,20 @@ EGLBoolean __stdcall eglBindAPI(EGLenum api) { case EGL_OPENGL_API: case EGL_OPENVG_API: - return error(EGL_BAD_PARAMETER, EGL_FALSE); // Not supported by this implementation + return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); // Not supported by this implementation case EGL_OPENGL_ES_API: break; default: - return error(EGL_BAD_PARAMETER, EGL_FALSE); + return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); } egl::setCurrentAPI(api); - return success(EGL_TRUE); + return egl::success(EGL_TRUE); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -553,11 +558,11 @@ EGLenum __stdcall eglQueryAPI(void) { EGLenum API = egl::getCurrentAPI(); - return success(API); + return egl::success(API); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -569,11 +574,11 @@ EGLBoolean __stdcall eglWaitClient(void) { UNIMPLEMENTED(); // FIXME - return success(0); + return egl::success(0); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -585,11 +590,11 @@ EGLBoolean __stdcall eglReleaseThread(void) { eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE); - return success(EGL_TRUE); + return egl::success(EGL_TRUE); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -610,14 +615,14 @@ EGLSurface __stdcall eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum bu if (buftype != EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE || !buffer) { - return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE); + return egl::error(EGL_BAD_PARAMETER, EGL_NO_SURFACE); } return display->createOffscreenSurface(config, (HANDLE)buffer, attrib_list); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_NO_SURFACE); + return egl::error(EGL_BAD_ALLOC, EGL_NO_SURFACE); } } @@ -638,11 +643,11 @@ EGLBoolean __stdcall eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint UNIMPLEMENTED(); // FIXME - return success(EGL_TRUE); + return egl::success(EGL_TRUE); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -662,34 +667,34 @@ EGLBoolean __stdcall eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint if (buffer != EGL_BACK_BUFFER) { - return error(EGL_BAD_PARAMETER, EGL_FALSE); + return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); } if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle()) { - return error(EGL_BAD_SURFACE, EGL_FALSE); + return egl::error(EGL_BAD_SURFACE, EGL_FALSE); } if (eglSurface->getBoundTexture()) { - return error(EGL_BAD_ACCESS, EGL_FALSE); + return egl::error(EGL_BAD_ACCESS, EGL_FALSE); } if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE) { - return error(EGL_BAD_MATCH, EGL_FALSE); + return egl::error(EGL_BAD_MATCH, EGL_FALSE); } if (!glBindTexImage(eglSurface)) { - return error(EGL_BAD_MATCH, EGL_FALSE); + return egl::error(EGL_BAD_MATCH, EGL_FALSE); } - return success(EGL_TRUE); + return egl::success(EGL_TRUE); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -709,17 +714,17 @@ EGLBoolean __stdcall eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLi if (buffer != EGL_BACK_BUFFER) { - return error(EGL_BAD_PARAMETER, EGL_FALSE); + return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); } if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle()) { - return error(EGL_BAD_SURFACE, EGL_FALSE); + return egl::error(EGL_BAD_SURFACE, EGL_FALSE); } if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE) { - return error(EGL_BAD_MATCH, EGL_FALSE); + return egl::error(EGL_BAD_MATCH, EGL_FALSE); } gl::Texture2D *texture = eglSurface->getBoundTexture(); @@ -729,11 +734,11 @@ EGLBoolean __stdcall eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLi texture->releaseTexImage(); } - return success(EGL_TRUE); + return egl::success(EGL_TRUE); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -754,16 +759,16 @@ EGLBoolean __stdcall eglSwapInterval(EGLDisplay dpy, EGLint interval) if (draw_surface == NULL) { - return error(EGL_BAD_SURFACE, EGL_FALSE); + return egl::error(EGL_BAD_SURFACE, EGL_FALSE); } draw_surface->setSwapInterval(interval); - return success(EGL_TRUE); + return egl::success(EGL_TRUE); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -791,32 +796,32 @@ EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLConte case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT: if (attribute[1] == EGL_TRUE) { - return error(EGL_BAD_CONFIG, EGL_NO_CONTEXT); // Unimplemented + return egl::error(EGL_BAD_CONFIG, EGL_NO_CONTEXT); // Unimplemented // robust_access = true; } else if (attribute[1] != EGL_FALSE) - return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); + return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); break; case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT: if (attribute[1] == EGL_LOSE_CONTEXT_ON_RESET_EXT) reset_notification = true; else if (attribute[1] != EGL_NO_RESET_NOTIFICATION_EXT) - return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); + return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); break; default: - return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); + return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); } } } if (client_version != 2) { - return error(EGL_BAD_CONFIG, EGL_NO_CONTEXT); + return egl::error(EGL_BAD_CONFIG, EGL_NO_CONTEXT); } if (share_context && static_cast(share_context)->isResetNotificationEnabled() != reset_notification) { - return error(EGL_BAD_MATCH, EGL_NO_CONTEXT); + return egl::error(EGL_BAD_MATCH, EGL_NO_CONTEXT); } egl::Display *display = static_cast(dpy); @@ -829,13 +834,13 @@ EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLConte EGLContext context = display->createContext(config, static_cast(share_context), reset_notification, robust_access); if (context) - return success(context); + return egl::success(context); else - return error(EGL_CONTEXT_LOST, EGL_NO_CONTEXT); + return egl::error(EGL_CONTEXT_LOST, EGL_NO_CONTEXT); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_NO_CONTEXT); + return egl::error(EGL_BAD_ALLOC, EGL_NO_CONTEXT); } } @@ -855,16 +860,16 @@ EGLBoolean __stdcall eglDestroyContext(EGLDisplay dpy, EGLContext ctx) if (ctx == EGL_NO_CONTEXT) { - return error(EGL_BAD_CONTEXT, EGL_FALSE); + return egl::error(EGL_BAD_CONTEXT, EGL_FALSE); } display->destroyContext(context); - return success(EGL_TRUE); + return egl::success(EGL_TRUE); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -877,24 +882,26 @@ EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface { egl::Display *display = static_cast(dpy); gl::Context *context = static_cast(ctx); - IDirect3DDevice9 *device = display->getDevice(); - - if (!device || display->testDeviceLost()) - { - display->notifyDeviceLost(); - return EGL_FALSE; - } - - if (display->isDeviceLost()) - { - return error(EGL_CONTEXT_LOST, EGL_FALSE); - } if (ctx != EGL_NO_CONTEXT && !validateContext(display, context)) { return EGL_FALSE; } + if (dpy != EGL_NO_DISPLAY) + { + rx::Renderer *renderer = display->getRenderer(); + if (renderer->testDeviceLost(true)) + { + return EGL_FALSE; + } + + if (renderer->isDeviceLost()) + { + return egl::error(EGL_CONTEXT_LOST, EGL_FALSE); + } + } + if ((draw != EGL_NO_SURFACE && !validateSurface(display, static_cast(draw))) || (read != EGL_NO_SURFACE && !validateSurface(display, static_cast(read)))) { @@ -912,11 +919,11 @@ EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface glMakeCurrent(context, display, static_cast(draw)); - return success(EGL_TRUE); + return egl::success(EGL_TRUE); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -928,11 +935,11 @@ EGLContext __stdcall eglGetCurrentContext(void) { EGLContext context = glGetCurrentContext(); - return success(context); + return egl::success(context); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_NO_CONTEXT); + return egl::error(EGL_BAD_ALLOC, EGL_NO_CONTEXT); } } @@ -945,21 +952,21 @@ EGLSurface __stdcall eglGetCurrentSurface(EGLint readdraw) if (readdraw == EGL_READ) { EGLSurface read = egl::getCurrentReadSurface(); - return success(read); + return egl::success(read); } else if (readdraw == EGL_DRAW) { EGLSurface draw = egl::getCurrentDrawSurface(); - return success(draw); + return egl::success(draw); } else { - return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE); + return egl::error(EGL_BAD_PARAMETER, EGL_NO_SURFACE); } } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_NO_SURFACE); + return egl::error(EGL_BAD_ALLOC, EGL_NO_SURFACE); } } @@ -971,11 +978,11 @@ EGLDisplay __stdcall eglGetCurrentDisplay(void) { EGLDisplay dpy = egl::getCurrentDisplay(); - return success(dpy); + return egl::success(dpy); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_NO_DISPLAY); + return egl::error(EGL_BAD_ALLOC, EGL_NO_DISPLAY); } } @@ -996,11 +1003,11 @@ EGLBoolean __stdcall eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attr UNIMPLEMENTED(); // FIXME - return success(0); + return egl::success(0); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -1012,11 +1019,11 @@ EGLBoolean __stdcall eglWaitGL(void) { UNIMPLEMENTED(); // FIXME - return success(0); + return egl::success(0); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -1028,11 +1035,11 @@ EGLBoolean __stdcall eglWaitNative(EGLint engine) { UNIMPLEMENTED(); // FIXME - return success(0); + return egl::success(0); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -1050,24 +1057,24 @@ EGLBoolean __stdcall eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) return EGL_FALSE; } - if (display->isDeviceLost()) + if (display->getRenderer()->isDeviceLost()) { - return error(EGL_CONTEXT_LOST, EGL_FALSE); + return egl::error(EGL_CONTEXT_LOST, EGL_FALSE); } if (surface == EGL_NO_SURFACE) { - return error(EGL_BAD_SURFACE, EGL_FALSE); + return egl::error(EGL_BAD_SURFACE, EGL_FALSE); } if (eglSurface->swap()) { - return success(EGL_TRUE); + return egl::success(EGL_TRUE); } } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } return EGL_FALSE; @@ -1087,18 +1094,18 @@ EGLBoolean __stdcall eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativ return EGL_FALSE; } - if (display->isDeviceLost()) + if (display->getRenderer()->isDeviceLost()) { - return error(EGL_CONTEXT_LOST, EGL_FALSE); + return egl::error(EGL_CONTEXT_LOST, EGL_FALSE); } UNIMPLEMENTED(); // FIXME - return success(0); + return egl::success(0); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -1110,7 +1117,7 @@ EGLBoolean __stdcall eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLi { if (x < 0 || y < 0 || width < 0 || height < 0) { - return error(EGL_BAD_PARAMETER, EGL_FALSE); + return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); } egl::Display *display = static_cast(dpy); @@ -1121,24 +1128,24 @@ EGLBoolean __stdcall eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLi return EGL_FALSE; } - if (display->isDeviceLost()) + if (display->getRenderer()->isDeviceLost()) { - return error(EGL_CONTEXT_LOST, EGL_FALSE); + return egl::error(EGL_CONTEXT_LOST, EGL_FALSE); } if (surface == EGL_NO_SURFACE) { - return error(EGL_BAD_SURFACE, EGL_FALSE); + return egl::error(EGL_BAD_SURFACE, EGL_FALSE); } if (eglSurface->postSubBuffer(x, y, width, height)) { - return success(EGL_TRUE); + return egl::success(EGL_TRUE); } } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } return EGL_FALSE; @@ -1163,7 +1170,7 @@ __eglMustCastToProperFunctionPointerType __stdcall eglGetProcAddress(const char {"", NULL}, }; - for (int ext = 0; ext < sizeof(eglExtensions) / sizeof(Extension); ext++) + for (unsigned int ext = 0; ext < ArraySize(eglExtensions); ext++) { if (strcmp(procname, eglExtensions[ext].name) == 0) { @@ -1175,7 +1182,7 @@ __eglMustCastToProperFunctionPointerType __stdcall eglGetProcAddress(const char } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, (__eglMustCastToProperFunctionPointerType)NULL); + return egl::error(EGL_BAD_ALLOC, (__eglMustCastToProperFunctionPointerType)NULL); } } } diff --git a/gfx/angle/src/libEGL/libEGL.vcxproj b/gfx/angle/src/libEGL/libEGL.vcxproj deleted file mode 100644 index c49cadbcd9f2..000000000000 --- a/gfx/angle/src/libEGL/libEGL.vcxproj +++ /dev/null @@ -1,262 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {E746FCA9-64C3-433E-85E8-9A5A67AB7ED6} - libEGL - Win32Proj - - - - DynamicLibrary - Unicode - true - - - DynamicLibrary - Unicode - - - DynamicLibrary - Unicode - true - - - DynamicLibrary - Unicode - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.40219.1 - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - true - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - false - $(SolutionDir)$(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ - true - $(SolutionDir)$(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ - false - $(LibraryPath) - $(LibraryPath) - $(LibraryPath) - $(LibraryPath) - - - - Disabled - $(ProjectDir)/..; $(ProjectDir)/../../include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBEGL_EXPORTS;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - - - Level4 - true - EditAndContinue - 4100;4127;4189;4239;4244;4245;4512;4702;%(DisableSpecificWarnings) - - - d3d9.lib;dxguid.lib;%(AdditionalDependencies) - libEGL.def - %(DelayLoadDLLs) - true - Windows - false - - - MachineX86 - - - %40echo on -mkdir "$(ProjectDir)..\..\lib\$(Configuration)\" -copy "$(OutDir)libEGL.dll" "$(ProjectDir)..\..\lib\$(Configuration)\" -copy "$(OutDir)libEGL.lib" "$(ProjectDir)..\..\lib\$(Configuration)\" -%40echo off - - - - - - MaxSpeed - AnySuitable - $(ProjectDir)/..; $(ProjectDir)/../../include;%(AdditionalIncludeDirectories) - ANGLE_DISABLE_TRACE;WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBEGL_EXPORTS;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;_SECURE_SCL=0;%(PreprocessorDefinitions) - MultiThreaded - - - Level4 - true - ProgramDatabase - 4100;4127;4189;4239;4244;4245;4512;4702;%(DisableSpecificWarnings) - - - d3d9.lib;dxguid.lib;%(AdditionalDependencies) - libEGL.def - %(DelayLoadDLLs) - true - Windows - true - true - false - - - MachineX86 - - - %40echo on -mkdir "$(ProjectDir)..\..\lib\$(Configuration)\" -copy "$(OutDir)libEGL.dll" "$(ProjectDir)..\..\lib\$(Configuration)\" -copy "$(OutDir)libEGL.lib" "$(ProjectDir)..\..\lib\$(Configuration)\" -%40echo off - - - - - - X64 - - - Disabled - $(ProjectDir)/..; $(ProjectDir)/../../include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBEGL_EXPORTS;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - - - Level4 - 4100;4127;4189;4239;4244;4245;4512;4702;%(DisableSpecificWarnings) - ProgramDatabase - true - - - d3d9.lib;dxguid.lib;%(AdditionalDependencies) - libEGL.def - %(DelayLoadDLLs) - true - Windows - false - - - MachineX64 - - - %40echo on -mkdir "$(ProjectDir)..\..\lib\$(Configuration)\" -copy "$(OutDir)libEGL.dll" "$(ProjectDir)..\..\lib\$(Configuration)\" -copy "$(OutDir)libEGL.lib" "$(ProjectDir)..\..\lib\$(Configuration)\" -%40echo off - - - - - - X64 - - - MaxSpeed - AnySuitable - $(ProjectDir)/..; $(ProjectDir)/../../include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBEGL_EXPORTS;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;_SECURE_SCL=0;%(PreprocessorDefinitions) - MultiThreaded - - - Level4 - 4100;4127;4189;4239;4244;4245;4512;4702;%(DisableSpecificWarnings) - ProgramDatabase - true - - - d3d9.lib;dxguid.lib;%(AdditionalDependencies) - libEGL.def - %(DelayLoadDLLs) - true - Windows - true - true - false - - - MachineX64 - - - %40echo on -mkdir "$(ProjectDir)..\..\lib\$(Configuration)\" -copy "$(OutDir)libEGL.dll" "$(ProjectDir)..\..\lib\$(Configuration)\" -copy "$(OutDir)libEGL.lib" "$(ProjectDir)..\..\lib\$(Configuration)\" -%40echo off - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {b5871a7a-968c-42e3-a33b-981e6f448e78} - false - - - - - - \ No newline at end of file diff --git a/gfx/angle/src/libEGL/libEGL.vcxproj.filters b/gfx/angle/src/libEGL/libEGL.vcxproj.filters deleted file mode 100644 index 9139e499c5e7..000000000000 --- a/gfx/angle/src/libEGL/libEGL.vcxproj.filters +++ /dev/null @@ -1,70 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - - - - \ No newline at end of file diff --git a/gfx/angle/src/libEGL/main.cpp b/gfx/angle/src/libEGL/main.cpp index dc24c4fb04e3..424ec3fcd1d9 100644 --- a/gfx/angle/src/libEGL/main.cpp +++ b/gfx/angle/src/libEGL/main.cpp @@ -157,9 +157,10 @@ EGLSurface getCurrentReadSurface() return current->readSurface; } -} void error(EGLint errorCode) { egl::setCurrentError(errorCode); } + +} diff --git a/gfx/angle/src/libEGL/main.h b/gfx/angle/src/libEGL/main.h index d09d9e6bc3ad..77da8f0f8e73 100644 --- a/gfx/angle/src/libEGL/main.h +++ b/gfx/angle/src/libEGL/main.h @@ -38,7 +38,6 @@ EGLSurface getCurrentDrawSurface(); void setCurrentReadSurface(EGLSurface surface); EGLSurface getCurrentReadSurface(); -} void error(EGLint errorCode); @@ -58,4 +57,6 @@ const T &success(const T &returnValue) return returnValue; } +} + #endif // LIBEGL_MAIN_H_ diff --git a/gfx/angle/src/libEGL/moz.build b/gfx/angle/src/libEGL/moz.build index c5e75df03754..81eff9d4371a 100644 --- a/gfx/angle/src/libEGL/moz.build +++ b/gfx/angle/src/libEGL/moz.build @@ -6,15 +6,21 @@ MODULE = 'libegl' +# Target: 'libEGL' +# Requires: 'libGLESv2' +# src/common: +CPP_SOURCES += [ + 'debug.cpp', + 'RefCountObject.cpp', +] + +# src/libEGL CPP_SOURCES += [ 'Config.cpp', 'Display.cpp', - 'RefCountObject.cpp', - 'Surface.cpp', - 'debug.cpp', 'libEGL.cpp', 'main.cpp', + 'Surface.cpp', ] LIBRARY_NAME = 'libEGL' - diff --git a/gfx/angle/src/libGLESv2/BinaryStream.h b/gfx/angle/src/libGLESv2/BinaryStream.h index 5f7213b8dadf..21c2f86ce820 100644 --- a/gfx/angle/src/libGLESv2/BinaryStream.h +++ b/gfx/angle/src/libGLESv2/BinaryStream.h @@ -9,9 +9,6 @@ #ifndef LIBGLESV2_BINARYSTREAM_H_ #define LIBGLESV2_BINARYSTREAM_H_ -#include -#include - #include "common/angleutils.h" namespace gl diff --git a/gfx/angle/src/libGLESv2/Buffer.cpp b/gfx/angle/src/libGLESv2/Buffer.cpp index dd12e3c0773b..a64fbad4fa1c 100644 --- a/gfx/angle/src/libGLESv2/Buffer.cpp +++ b/gfx/angle/src/libGLESv2/Buffer.cpp @@ -1,5 +1,6 @@ +#include "precompiled.h" // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -10,19 +11,20 @@ #include "libGLESv2/Buffer.h" -#include "libGLESv2/main.h" -#include "libGLESv2/VertexDataManager.h" -#include "libGLESv2/IndexDataManager.h" +#include "libGLESv2/renderer/VertexBuffer.h" +#include "libGLESv2/renderer/IndexBuffer.h" +#include "libGLESv2/renderer/BufferStorage.h" +#include "libGLESv2/renderer/Renderer.h" namespace gl { -Buffer::Buffer(GLuint id) : RefCountObject(id) +Buffer::Buffer(rx::Renderer *renderer, GLuint id) : RefCountObject(id) { - mContents = NULL; - mSize = 0; + mRenderer = renderer; mUsage = GL_DYNAMIC_DRAW; + mBufferStorage = renderer->createBufferStorage(); mStaticVertexBuffer = NULL; mStaticIndexBuffer = NULL; mUnmodifiedDataUse = 0; @@ -30,47 +32,34 @@ Buffer::Buffer(GLuint id) : RefCountObject(id) Buffer::~Buffer() { - delete[] mContents; + delete mBufferStorage; delete mStaticVertexBuffer; delete mStaticIndexBuffer; } void Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage) { - if (size == 0) - { - delete[] mContents; - mContents = NULL; - } - else if (size != mSize) - { - delete[] mContents; - mContents = new GLubyte[size]; - memset(mContents, 0, size); - } + mBufferStorage->clear(); + mIndexRangeCache.clear(); + mBufferStorage->setData(data, size, 0); - if (data != NULL && size > 0) - { - memcpy(mContents, data, size); - } - - mSize = size; mUsage = usage; invalidateStaticData(); if (usage == GL_STATIC_DRAW) { - mStaticVertexBuffer = new StaticVertexBuffer(getDevice()); - mStaticIndexBuffer = new StaticIndexBuffer(getDevice()); + mStaticVertexBuffer = new rx::StaticVertexBufferInterface(mRenderer); + mStaticIndexBuffer = new rx::StaticIndexBufferInterface(mRenderer); } } void Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset) { - memcpy(mContents + offset, data, size); - - if ((mStaticVertexBuffer && mStaticVertexBuffer->size() != 0) || (mStaticIndexBuffer && mStaticIndexBuffer->size() != 0)) + mBufferStorage->setData(data, size, offset); + mIndexRangeCache.invalidateRange(offset, size); + + if ((mStaticVertexBuffer && mStaticVertexBuffer->getBufferSize() != 0) || (mStaticIndexBuffer && mStaticIndexBuffer->getBufferSize() != 0)) { invalidateStaticData(); } @@ -78,12 +67,27 @@ void Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset) mUnmodifiedDataUse = 0; } -StaticVertexBuffer *Buffer::getStaticVertexBuffer() +rx::BufferStorage *Buffer::getStorage() const +{ + return mBufferStorage; +} + +unsigned int Buffer::size() +{ + return mBufferStorage->getSize(); +} + +GLenum Buffer::usage() const +{ + return mUsage; +} + +rx::StaticVertexBufferInterface *Buffer::getStaticVertexBuffer() { return mStaticVertexBuffer; } -StaticIndexBuffer *Buffer::getStaticIndexBuffer() +rx::StaticIndexBufferInterface *Buffer::getStaticIndexBuffer() { return mStaticIndexBuffer; } @@ -106,12 +110,17 @@ void Buffer::promoteStaticUsage(int dataSize) { mUnmodifiedDataUse += dataSize; - if (mUnmodifiedDataUse > 3 * mSize) + if (mUnmodifiedDataUse > 3 * mBufferStorage->getSize()) { - mStaticVertexBuffer = new StaticVertexBuffer(getDevice()); - mStaticIndexBuffer = new StaticIndexBuffer(getDevice()); + mStaticVertexBuffer = new rx::StaticVertexBufferInterface(mRenderer); + mStaticIndexBuffer = new rx::StaticIndexBufferInterface(mRenderer); } } } +rx::IndexRangeCache *Buffer::getIndexRangeCache() +{ + return &mIndexRangeCache; +} + } diff --git a/gfx/angle/src/libGLESv2/Buffer.h b/gfx/angle/src/libGLESv2/Buffer.h index 7019c4e160b2..3f9fe8f8a337 100644 --- a/gfx/angle/src/libGLESv2/Buffer.h +++ b/gfx/angle/src/libGLESv2/Buffer.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -11,49 +11,56 @@ #ifndef LIBGLESV2_BUFFER_H_ #define LIBGLESV2_BUFFER_H_ -#include -#include - -#define GL_APICALL -#include - #include "common/angleutils.h" #include "common/RefCountObject.h" +#include "libGLESv2/renderer/IndexRangeCache.h" + +namespace rx +{ +class Renderer; +class BufferStorage; +class StaticIndexBufferInterface; +class StaticVertexBufferInterface; +}; namespace gl { -class StaticVertexBuffer; -class StaticIndexBuffer; class Buffer : public RefCountObject { public: - explicit Buffer(GLuint id); + Buffer(rx::Renderer *renderer, GLuint id); virtual ~Buffer(); void bufferData(const void *data, GLsizeiptr size, GLenum usage); void bufferSubData(const void *data, GLsizeiptr size, GLintptr offset); - void *data() { return mContents; } - size_t size() const { return mSize; } - GLenum usage() const { return mUsage; } + GLenum usage() const; - StaticVertexBuffer *getStaticVertexBuffer(); - StaticIndexBuffer *getStaticIndexBuffer(); + rx::BufferStorage *getStorage() const; + unsigned int size(); + + rx::StaticVertexBufferInterface *getStaticVertexBuffer(); + rx::StaticIndexBufferInterface *getStaticIndexBuffer(); void invalidateStaticData(); void promoteStaticUsage(int dataSize); + rx::IndexRangeCache *getIndexRangeCache(); + private: DISALLOW_COPY_AND_ASSIGN(Buffer); - GLubyte *mContents; - GLsizeiptr mSize; + rx::Renderer *mRenderer; GLenum mUsage; - StaticVertexBuffer *mStaticVertexBuffer; - StaticIndexBuffer *mStaticIndexBuffer; - GLsizeiptr mUnmodifiedDataUse; + rx::BufferStorage *mBufferStorage; + + rx::IndexRangeCache mIndexRangeCache; + + rx::StaticVertexBufferInterface *mStaticVertexBuffer; + rx::StaticIndexBufferInterface *mStaticIndexBuffer; + unsigned int mUnmodifiedDataUse; }; } diff --git a/gfx/angle/src/libGLESv2/Context.cpp b/gfx/angle/src/libGLESv2/Context.cpp index e150aeec72a7..e084db1ab40b 100644 --- a/gfx/angle/src/libGLESv2/Context.cpp +++ b/gfx/angle/src/libGLESv2/Context.cpp @@ -1,5 +1,6 @@ +#include "precompiled.h" // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -9,27 +10,22 @@ #include "libGLESv2/Context.h" -#include -#include - -#include "libEGL/Display.h" - #include "libGLESv2/main.h" -#include "libGLESv2/mathutil.h" #include "libGLESv2/utilities.h" -#include "libGLESv2/Blit.h" -#include "libGLESv2/ResourceManager.h" #include "libGLESv2/Buffer.h" #include "libGLESv2/Fence.h" #include "libGLESv2/Framebuffer.h" +#include "libGLESv2/Renderbuffer.h" #include "libGLESv2/Program.h" #include "libGLESv2/ProgramBinary.h" #include "libGLESv2/Query.h" -#include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/Shader.h" #include "libGLESv2/Texture.h" -#include "libGLESv2/VertexDataManager.h" -#include "libGLESv2/IndexDataManager.h" +#include "libGLESv2/ResourceManager.h" +#include "libGLESv2/renderer/IndexDataManager.h" +#include "libGLESv2/renderer/RenderTarget.h" +#include "libGLESv2/renderer/Renderer.h" + +#include "libEGL/Surface.h" #undef near #undef far @@ -46,13 +42,10 @@ static const char* makeStaticString(const std::string& str) return strings.insert(str).first->c_str(); } -Context::Context(const egl::Config *config, const gl::Context *shareContext, bool notifyResets, bool robustAccess) : mConfig(config) +Context::Context(const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess) : mRenderer(renderer) { ASSERT(robustAccess == false); // Unimplemented - mDisplay = NULL; - mDevice = NULL; - mFenceHandleAllocator.setBaseHandle(0); setClearColor(0.0f, 0.0f, 0.0f, 0.0f); @@ -60,68 +53,74 @@ Context::Context(const egl::Config *config, const gl::Context *shareContext, boo mState.depthClearValue = 1.0f; mState.stencilClearValue = 0; - mState.cullFace = false; - mState.cullMode = GL_BACK; - mState.frontFace = GL_CCW; - mState.depthTest = false; - mState.depthFunc = GL_LESS; - mState.blend = false; - mState.sourceBlendRGB = GL_ONE; - mState.sourceBlendAlpha = GL_ONE; - mState.destBlendRGB = GL_ZERO; - mState.destBlendAlpha = GL_ZERO; - mState.blendEquationRGB = GL_FUNC_ADD; - mState.blendEquationAlpha = GL_FUNC_ADD; + mState.rasterizer.cullFace = false; + mState.rasterizer.cullMode = GL_BACK; + mState.rasterizer.frontFace = GL_CCW; + mState.rasterizer.polygonOffsetFill = false; + mState.rasterizer.polygonOffsetFactor = 0.0f; + mState.rasterizer.polygonOffsetUnits = 0.0f; + mState.rasterizer.pointDrawMode = false; + mState.rasterizer.multiSample = false; + mState.scissorTest = false; + mState.scissor.x = 0; + mState.scissor.y = 0; + mState.scissor.width = 0; + mState.scissor.height = 0; + + mState.blend.blend = false; + mState.blend.sourceBlendRGB = GL_ONE; + mState.blend.sourceBlendAlpha = GL_ONE; + mState.blend.destBlendRGB = GL_ZERO; + mState.blend.destBlendAlpha = GL_ZERO; + mState.blend.blendEquationRGB = GL_FUNC_ADD; + mState.blend.blendEquationAlpha = GL_FUNC_ADD; + mState.blend.sampleAlphaToCoverage = false; + mState.blend.dither = true; + mState.blendColor.red = 0; mState.blendColor.green = 0; mState.blendColor.blue = 0; mState.blendColor.alpha = 0; - mState.stencilTest = false; - mState.stencilFunc = GL_ALWAYS; + + mState.depthStencil.depthTest = false; + mState.depthStencil.depthFunc = GL_LESS; + mState.depthStencil.depthMask = true; + mState.depthStencil.stencilTest = false; + mState.depthStencil.stencilFunc = GL_ALWAYS; + mState.depthStencil.stencilMask = -1; + mState.depthStencil.stencilWritemask = -1; + mState.depthStencil.stencilBackFunc = GL_ALWAYS; + mState.depthStencil.stencilBackMask = - 1; + mState.depthStencil.stencilBackWritemask = -1; + mState.depthStencil.stencilFail = GL_KEEP; + mState.depthStencil.stencilPassDepthFail = GL_KEEP; + mState.depthStencil.stencilPassDepthPass = GL_KEEP; + mState.depthStencil.stencilBackFail = GL_KEEP; + mState.depthStencil.stencilBackPassDepthFail = GL_KEEP; + mState.depthStencil.stencilBackPassDepthPass = GL_KEEP; + mState.stencilRef = 0; - mState.stencilMask = -1; - mState.stencilWritemask = -1; - mState.stencilBackFunc = GL_ALWAYS; mState.stencilBackRef = 0; - mState.stencilBackMask = - 1; - mState.stencilBackWritemask = -1; - mState.stencilFail = GL_KEEP; - mState.stencilPassDepthFail = GL_KEEP; - mState.stencilPassDepthPass = GL_KEEP; - mState.stencilBackFail = GL_KEEP; - mState.stencilBackPassDepthFail = GL_KEEP; - mState.stencilBackPassDepthPass = GL_KEEP; - mState.polygonOffsetFill = false; - mState.polygonOffsetFactor = 0.0f; - mState.polygonOffsetUnits = 0.0f; - mState.sampleAlphaToCoverage = false; + mState.sampleCoverage = false; mState.sampleCoverageValue = 1.0f; mState.sampleCoverageInvert = false; - mState.scissorTest = false; - mState.dither = true; mState.generateMipmapHint = GL_DONT_CARE; mState.fragmentShaderDerivativeHint = GL_DONT_CARE; mState.lineWidth = 1.0f; - mState.viewportX = 0; - mState.viewportY = 0; - mState.viewportWidth = config->mDisplayMode.Width; - mState.viewportHeight = config->mDisplayMode.Height; + mState.viewport.x = 0; + mState.viewport.y = 0; + mState.viewport.width = 0; + mState.viewport.height = 0; mState.zNear = 0.0f; mState.zFar = 1.0f; - mState.scissorX = 0; - mState.scissorY = 0; - mState.scissorWidth = config->mDisplayMode.Width; - mState.scissorHeight = config->mDisplayMode.Height; - - mState.colorMaskRed = true; - mState.colorMaskGreen = true; - mState.colorMaskBlue = true; - mState.colorMaskAlpha = true; - mState.depthMask = true; + mState.blend.colorMaskRed = true; + mState.blend.colorMaskGreen = true; + mState.blend.colorMaskBlue = true; + mState.blend.colorMaskAlpha = true; if (shareContext != NULL) { @@ -130,7 +129,7 @@ Context::Context(const egl::Config *config, const gl::Context *shareContext, boo } else { - mResourceManager = new ResourceManager(); + mResourceManager = new ResourceManager(mRenderer); } // [OpenGL ES 2.0.24] section 3.7 page 83: @@ -139,8 +138,8 @@ Context::Context(const egl::Config *config, const gl::Context *shareContext, boo // In order that access to these initial textures not be lost, they are treated as texture // objects all of whose names are 0. - mTexture2DZero.set(new Texture2D(0)); - mTextureCubeMapZero.set(new TextureCubeMap(0)); + mTexture2DZero.set(new Texture2D(mRenderer, 0)); + mTextureCubeMapZero.set(new TextureCubeMap(mRenderer, 0)); mState.activeSampler = 0; bindArrayBuffer(0); @@ -161,11 +160,6 @@ Context::Context(const egl::Config *config, const gl::Context *shareContext, boo mExtensionString = NULL; mRendererString = NULL; - mVertexDataManager = NULL; - mIndexDataManager = NULL; - mBlit = NULL; - mLineLoopIB = NULL; - mInvalidEnum = false; mInvalidValue = false; mInvalidOperation = false; @@ -178,15 +172,13 @@ Context::Context(const egl::Config *config, const gl::Context *shareContext, boo mResetStrategy = (notifyResets ? GL_LOSE_CONTEXT_ON_RESET_EXT : GL_NO_RESET_NOTIFICATION_EXT); mRobustAccess = robustAccess; + mSupportsBGRATextures = false; mSupportsDXT1Textures = false; mSupportsDXT3Textures = false; mSupportsDXT5Textures = false; mSupportsEventQueries = false; mSupportsOcclusionQueries = false; mNumCompressedTextureFormats = 0; - mMaxSupportedSamples = 0; - mMaskedClearSavedState = NULL; - markAllStateDirty(); } Context::~Context() @@ -217,15 +209,9 @@ Context::~Context() deleteQuery(mQueryMap.begin()->first); } - while (!mMultiSampleSupport.empty()) - { - delete [] mMultiSampleSupport.begin()->second; - mMultiSampleSupport.erase(mMultiSampleSupport.begin()); - } - for (int type = 0; type < TEXTURE_TYPE_COUNT; type++) { - for (int sampler = 0; sampler < MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF; sampler++) + for (int sampler = 0; sampler < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS; sampler++) { mState.samplerTexture[type][sampler].set(NULL); } @@ -253,86 +239,42 @@ Context::~Context() mTexture2DZero.set(NULL); mTextureCubeMapZero.set(NULL); - delete mVertexDataManager; - delete mIndexDataManager; - delete mBlit; - delete mLineLoopIB; - - if (mMaskedClearSavedState) - { - mMaskedClearSavedState->Release(); - } - mResourceManager->release(); } -void Context::makeCurrent(egl::Display *display, egl::Surface *surface) +void Context::makeCurrent(egl::Surface *surface) { - mDisplay = display; - mDevice = mDisplay->getDevice(); - if (!mHasBeenCurrent) { - mDeviceCaps = mDisplay->getDeviceCaps(); + mMajorShaderModel = mRenderer->getMajorShaderModel(); + mMaximumPointSize = mRenderer->getMaxPointSize(); + mSupportsVertexTexture = mRenderer->getVertexTextureSupport(); + mSupportsNonPower2Texture = mRenderer->getNonPower2TextureSupport(); + mSupportsInstancing = mRenderer->getInstancingSupport(); - mVertexDataManager = new VertexDataManager(this, mDevice); - mIndexDataManager = new IndexDataManager(this, mDevice); - mBlit = new Blit(this); - - mSupportsShaderModel3 = mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0); - mMaximumPointSize = mDeviceCaps.MaxPointSize; - mSupportsVertexTexture = mDisplay->getVertexTextureSupport(); - mSupportsNonPower2Texture = mDisplay->getNonPower2TextureSupport(); - mSupportsInstancing = mDisplay->getInstancingSupport(); - - mMaxTextureDimension = std::min(std::min((int)mDeviceCaps.MaxTextureWidth, (int)mDeviceCaps.MaxTextureHeight), + mMaxViewportDimension = mRenderer->getMaxViewportDimension(); + mMaxTextureDimension = std::min(std::min(mRenderer->getMaxTextureWidth(), mRenderer->getMaxTextureHeight()), (int)gl::IMPLEMENTATION_MAX_TEXTURE_SIZE); mMaxCubeTextureDimension = std::min(mMaxTextureDimension, (int)gl::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE); mMaxRenderbufferDimension = mMaxTextureDimension; mMaxTextureLevel = log2(mMaxTextureDimension) + 1; - mMaxTextureAnisotropy = mDisplay->getTextureFilterAnisotropySupport(); + mMaxTextureAnisotropy = mRenderer->getTextureMaxAnisotropy(); TRACE("MaxTextureDimension=%d, MaxCubeTextureDimension=%d, MaxRenderbufferDimension=%d, MaxTextureLevel=%d, MaxTextureAnisotropy=%f", mMaxTextureDimension, mMaxCubeTextureDimension, mMaxRenderbufferDimension, mMaxTextureLevel, mMaxTextureAnisotropy); - const D3DFORMAT renderBufferFormats[] = - { - D3DFMT_A8R8G8B8, - D3DFMT_X8R8G8B8, - D3DFMT_R5G6B5, - D3DFMT_D24S8 - }; - - int max = 0; - for (unsigned int i = 0; i < sizeof(renderBufferFormats) / sizeof(D3DFORMAT); ++i) - { - bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1]; - mDisplay->getMultiSampleSupport(renderBufferFormats[i], multisampleArray); - mMultiSampleSupport[renderBufferFormats[i]] = multisampleArray; - - for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j) - { - if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max) - { - max = j; - } - } - } - - mMaxSupportedSamples = max; - - mSupportsEventQueries = mDisplay->getEventQuerySupport(); - mSupportsOcclusionQueries = mDisplay->getOcclusionQuerySupport(); - mSupportsDXT1Textures = mDisplay->getDXT1TextureSupport(); - mSupportsDXT3Textures = mDisplay->getDXT3TextureSupport(); - mSupportsDXT5Textures = mDisplay->getDXT5TextureSupport(); - mSupportsFloat32Textures = mDisplay->getFloat32TextureSupport(&mSupportsFloat32LinearFilter, &mSupportsFloat32RenderableTextures); - mSupportsFloat16Textures = mDisplay->getFloat16TextureSupport(&mSupportsFloat16LinearFilter, &mSupportsFloat16RenderableTextures); - mSupportsLuminanceTextures = mDisplay->getLuminanceTextureSupport(); - mSupportsLuminanceAlphaTextures = mDisplay->getLuminanceAlphaTextureSupport(); - mSupportsDepthTextures = mDisplay->getDepthTextureSupport(); - mSupportsTextureFilterAnisotropy = mMaxTextureAnisotropy >= 2.0f; - mSupportsDerivativeInstructions = (mDeviceCaps.PS20Caps.Caps & D3DPS20CAPS_GRADIENTINSTRUCTIONS) != 0; - mSupports32bitIndices = mDeviceCaps.MaxVertexIndex >= (1 << 16); + mSupportsEventQueries = mRenderer->getEventQuerySupport(); + mSupportsOcclusionQueries = mRenderer->getOcclusionQuerySupport(); + mSupportsBGRATextures = mRenderer->getBGRATextureSupport(); + mSupportsDXT1Textures = mRenderer->getDXT1TextureSupport(); + mSupportsDXT3Textures = mRenderer->getDXT3TextureSupport(); + mSupportsDXT5Textures = mRenderer->getDXT5TextureSupport(); + mSupportsFloat32Textures = mRenderer->getFloat32TextureSupport(&mSupportsFloat32LinearFilter, &mSupportsFloat32RenderableTextures); + mSupportsFloat16Textures = mRenderer->getFloat16TextureSupport(&mSupportsFloat16LinearFilter, &mSupportsFloat16RenderableTextures); + mSupportsLuminanceTextures = mRenderer->getLuminanceTextureSupport(); + mSupportsLuminanceAlphaTextures = mRenderer->getLuminanceAlphaTextureSupport(); + mSupportsDepthTextures = mRenderer->getDepthTextureSupport(); + mSupportsTextureFilterAnisotropy = mRenderer->getTextureFilterAnisotropySupport(); + mSupports32bitIndices = mRenderer->get32BitIndexSupport(); mNumCompressedTextureFormats = 0; if (supportsDXT1Textures()) @@ -351,85 +293,30 @@ void Context::makeCurrent(egl::Display *display, egl::Surface *surface) initExtensionString(); initRendererString(); - mState.viewportX = 0; - mState.viewportY = 0; - mState.viewportWidth = surface->getWidth(); - mState.viewportHeight = surface->getHeight(); + mState.viewport.x = 0; + mState.viewport.y = 0; + mState.viewport.width = surface->getWidth(); + mState.viewport.height = surface->getHeight(); - mState.scissorX = 0; - mState.scissorY = 0; - mState.scissorWidth = surface->getWidth(); - mState.scissorHeight = surface->getHeight(); + mState.scissor.x = 0; + mState.scissor.y = 0; + mState.scissor.width = surface->getWidth(); + mState.scissor.height = surface->getHeight(); mHasBeenCurrent = true; } - // Wrap the existing Direct3D 9 resources into GL objects and assign them to the '0' names - IDirect3DSurface9 *defaultRenderTarget = surface->getRenderTarget(); - IDirect3DSurface9 *depthStencil = surface->getDepthStencil(); + // Wrap the existing swapchain resources into GL objects and assign them to the '0' names + rx::SwapChain *swapchain = surface->getSwapChain(); - Colorbuffer *colorbufferZero = new Colorbuffer(defaultRenderTarget); - DepthStencilbuffer *depthStencilbufferZero = new DepthStencilbuffer(depthStencil); - Framebuffer *framebufferZero = new DefaultFramebuffer(colorbufferZero, depthStencilbufferZero); + Colorbuffer *colorbufferZero = new Colorbuffer(mRenderer, swapchain); + DepthStencilbuffer *depthStencilbufferZero = new DepthStencilbuffer(mRenderer, swapchain); + Framebuffer *framebufferZero = new DefaultFramebuffer(mRenderer, colorbufferZero, depthStencilbufferZero); setFramebufferZero(framebufferZero); - - if (defaultRenderTarget) - { - defaultRenderTarget->Release(); - } - - if (depthStencil) - { - depthStencil->Release(); - } - - markAllStateDirty(); -} - -// This function will set all of the state-related dirty flags, so that all state is set during next pre-draw. -void Context::markAllStateDirty() -{ - for (int t = 0; t < MAX_TEXTURE_IMAGE_UNITS; t++) - { - mAppliedTextureSerialPS[t] = 0; - } - - for (int t = 0; t < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; t++) - { - mAppliedTextureSerialVS[t] = 0; - } - - mAppliedProgramBinarySerial = 0; - mAppliedRenderTargetSerial = 0; - mAppliedDepthbufferSerial = 0; - mAppliedStencilbufferSerial = 0; - mAppliedIBSerial = 0; - mDepthStencilInitialized = false; - mViewportInitialized = false; - mRenderTargetDescInitialized = false; - - mVertexDeclarationCache.markStateDirty(); - - mClearStateDirty = true; - mCullStateDirty = true; - mDepthStateDirty = true; - mMaskStateDirty = true; - mBlendStateDirty = true; - mStencilStateDirty = true; - mPolygonOffsetStateDirty = true; - mScissorStateDirty = true; - mSampleStateDirty = true; - mDitherStateDirty = true; - mFrontFaceDirty = true; - mDxUniformsDirty = true; -} - -void Context::markDxUniformsDirty() -{ - mDxUniformsDirty = true; } +// NOTE: this function should not assume that this context is current! void Context::markContextLost() { if (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT) @@ -462,57 +349,37 @@ void Context::setClearStencil(int stencil) void Context::setCullFace(bool enabled) { - if (mState.cullFace != enabled) - { - mState.cullFace = enabled; - mCullStateDirty = true; - } + mState.rasterizer.cullFace = enabled; } bool Context::isCullFaceEnabled() const { - return mState.cullFace; + return mState.rasterizer.cullFace; } void Context::setCullMode(GLenum mode) { - if (mState.cullMode != mode) - { - mState.cullMode = mode; - mCullStateDirty = true; - } + mState.rasterizer.cullMode = mode; } void Context::setFrontFace(GLenum front) { - if (mState.frontFace != front) - { - mState.frontFace = front; - mFrontFaceDirty = true; - } + mState.rasterizer.frontFace = front; } void Context::setDepthTest(bool enabled) { - if (mState.depthTest != enabled) - { - mState.depthTest = enabled; - mDepthStateDirty = true; - } + mState.depthStencil.depthTest = enabled; } bool Context::isDepthTestEnabled() const { - return mState.depthTest; + return mState.depthStencil.depthTest; } void Context::setDepthFunc(GLenum depthFunc) { - if (mState.depthFunc != depthFunc) - { - mState.depthFunc = depthFunc; - mDepthStateDirty = true; - } + mState.depthStencil.depthFunc = depthFunc; } void Context::setDepthRange(float zNear, float zFar) @@ -523,190 +390,114 @@ void Context::setDepthRange(float zNear, float zFar) void Context::setBlend(bool enabled) { - if (mState.blend != enabled) - { - mState.blend = enabled; - mBlendStateDirty = true; - } + mState.blend.blend = enabled; } bool Context::isBlendEnabled() const { - return mState.blend; + return mState.blend.blend; } void Context::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha) { - if (mState.sourceBlendRGB != sourceRGB || - mState.sourceBlendAlpha != sourceAlpha || - mState.destBlendRGB != destRGB || - mState.destBlendAlpha != destAlpha) - { - mState.sourceBlendRGB = sourceRGB; - mState.destBlendRGB = destRGB; - mState.sourceBlendAlpha = sourceAlpha; - mState.destBlendAlpha = destAlpha; - mBlendStateDirty = true; - } + mState.blend.sourceBlendRGB = sourceRGB; + mState.blend.destBlendRGB = destRGB; + mState.blend.sourceBlendAlpha = sourceAlpha; + mState.blend.destBlendAlpha = destAlpha; } void Context::setBlendColor(float red, float green, float blue, float alpha) { - if (mState.blendColor.red != red || - mState.blendColor.green != green || - mState.blendColor.blue != blue || - mState.blendColor.alpha != alpha) - { - mState.blendColor.red = red; - mState.blendColor.green = green; - mState.blendColor.blue = blue; - mState.blendColor.alpha = alpha; - mBlendStateDirty = true; - } + mState.blendColor.red = red; + mState.blendColor.green = green; + mState.blendColor.blue = blue; + mState.blendColor.alpha = alpha; } void Context::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation) { - if (mState.blendEquationRGB != rgbEquation || - mState.blendEquationAlpha != alphaEquation) - { - mState.blendEquationRGB = rgbEquation; - mState.blendEquationAlpha = alphaEquation; - mBlendStateDirty = true; - } + mState.blend.blendEquationRGB = rgbEquation; + mState.blend.blendEquationAlpha = alphaEquation; } void Context::setStencilTest(bool enabled) { - if (mState.stencilTest != enabled) - { - mState.stencilTest = enabled; - mStencilStateDirty = true; - } + mState.depthStencil.stencilTest = enabled; } bool Context::isStencilTestEnabled() const { - return mState.stencilTest; + return mState.depthStencil.stencilTest; } void Context::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask) { - if (mState.stencilFunc != stencilFunc || - mState.stencilRef != stencilRef || - mState.stencilMask != stencilMask) - { - mState.stencilFunc = stencilFunc; - mState.stencilRef = (stencilRef > 0) ? stencilRef : 0; - mState.stencilMask = stencilMask; - mStencilStateDirty = true; - } + mState.depthStencil.stencilFunc = stencilFunc; + mState.stencilRef = (stencilRef > 0) ? stencilRef : 0; + mState.depthStencil.stencilMask = stencilMask; } void Context::setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask) { - if (mState.stencilBackFunc != stencilBackFunc || - mState.stencilBackRef != stencilBackRef || - mState.stencilBackMask != stencilBackMask) - { - mState.stencilBackFunc = stencilBackFunc; - mState.stencilBackRef = (stencilBackRef > 0) ? stencilBackRef : 0; - mState.stencilBackMask = stencilBackMask; - mStencilStateDirty = true; - } + mState.depthStencil.stencilBackFunc = stencilBackFunc; + mState.stencilBackRef = (stencilBackRef > 0) ? stencilBackRef : 0; + mState.depthStencil.stencilBackMask = stencilBackMask; } void Context::setStencilWritemask(GLuint stencilWritemask) { - if (mState.stencilWritemask != stencilWritemask) - { - mState.stencilWritemask = stencilWritemask; - mStencilStateDirty = true; - } + mState.depthStencil.stencilWritemask = stencilWritemask; } void Context::setStencilBackWritemask(GLuint stencilBackWritemask) { - if (mState.stencilBackWritemask != stencilBackWritemask) - { - mState.stencilBackWritemask = stencilBackWritemask; - mStencilStateDirty = true; - } + mState.depthStencil.stencilBackWritemask = stencilBackWritemask; } void Context::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass) { - if (mState.stencilFail != stencilFail || - mState.stencilPassDepthFail != stencilPassDepthFail || - mState.stencilPassDepthPass != stencilPassDepthPass) - { - mState.stencilFail = stencilFail; - mState.stencilPassDepthFail = stencilPassDepthFail; - mState.stencilPassDepthPass = stencilPassDepthPass; - mStencilStateDirty = true; - } + mState.depthStencil.stencilFail = stencilFail; + mState.depthStencil.stencilPassDepthFail = stencilPassDepthFail; + mState.depthStencil.stencilPassDepthPass = stencilPassDepthPass; } void Context::setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass) { - if (mState.stencilBackFail != stencilBackFail || - mState.stencilBackPassDepthFail != stencilBackPassDepthFail || - mState.stencilBackPassDepthPass != stencilBackPassDepthPass) - { - mState.stencilBackFail = stencilBackFail; - mState.stencilBackPassDepthFail = stencilBackPassDepthFail; - mState.stencilBackPassDepthPass = stencilBackPassDepthPass; - mStencilStateDirty = true; - } + mState.depthStencil.stencilBackFail = stencilBackFail; + mState.depthStencil.stencilBackPassDepthFail = stencilBackPassDepthFail; + mState.depthStencil.stencilBackPassDepthPass = stencilBackPassDepthPass; } void Context::setPolygonOffsetFill(bool enabled) { - if (mState.polygonOffsetFill != enabled) - { - mState.polygonOffsetFill = enabled; - mPolygonOffsetStateDirty = true; - } + mState.rasterizer.polygonOffsetFill = enabled; } bool Context::isPolygonOffsetFillEnabled() const { - return mState.polygonOffsetFill; - + return mState.rasterizer.polygonOffsetFill; } void Context::setPolygonOffsetParams(GLfloat factor, GLfloat units) { - if (mState.polygonOffsetFactor != factor || - mState.polygonOffsetUnits != units) - { - mState.polygonOffsetFactor = factor; - mState.polygonOffsetUnits = units; - mPolygonOffsetStateDirty = true; - } + // An application can pass NaN values here, so handle this gracefully + mState.rasterizer.polygonOffsetFactor = factor != factor ? 0.0f : factor; + mState.rasterizer.polygonOffsetUnits = units != units ? 0.0f : units; } void Context::setSampleAlphaToCoverage(bool enabled) { - if (mState.sampleAlphaToCoverage != enabled) - { - mState.sampleAlphaToCoverage = enabled; - mSampleStateDirty = true; - } + mState.blend.sampleAlphaToCoverage = enabled; } bool Context::isSampleAlphaToCoverageEnabled() const { - return mState.sampleAlphaToCoverage; + return mState.blend.sampleAlphaToCoverage; } void Context::setSampleCoverage(bool enabled) { - if (mState.sampleCoverage != enabled) - { - mState.sampleCoverage = enabled; - mSampleStateDirty = true; - } + mState.sampleCoverage = enabled; } bool Context::isSampleCoverageEnabled() const @@ -716,22 +507,13 @@ bool Context::isSampleCoverageEnabled() const void Context::setSampleCoverageParams(GLclampf value, bool invert) { - if (mState.sampleCoverageValue != value || - mState.sampleCoverageInvert != invert) - { - mState.sampleCoverageValue = value; - mState.sampleCoverageInvert = invert; - mSampleStateDirty = true; - } + mState.sampleCoverageValue = value; + mState.sampleCoverageInvert = invert; } void Context::setScissorTest(bool enabled) { - if (mState.scissorTest != enabled) - { - mState.scissorTest = enabled; - mScissorStateDirty = true; - } + mState.scissorTest = enabled; } bool Context::isScissorTestEnabled() const @@ -741,16 +523,12 @@ bool Context::isScissorTestEnabled() const void Context::setDither(bool enabled) { - if (mState.dither != enabled) - { - mState.dither = enabled; - mDitherStateDirty = true; - } + mState.blend.dither = enabled; } bool Context::isDitherEnabled() const { - return mState.dither; + return mState.blend.dither; } void Context::setLineWidth(GLfloat width) @@ -773,45 +551,31 @@ void Context::setFragmentShaderDerivativeHint(GLenum hint) void Context::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height) { - mState.viewportX = x; - mState.viewportY = y; - mState.viewportWidth = width; - mState.viewportHeight = height; + mState.viewport.x = x; + mState.viewport.y = y; + mState.viewport.width = width; + mState.viewport.height = height; } void Context::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height) { - if (mState.scissorX != x || mState.scissorY != y || - mState.scissorWidth != width || mState.scissorHeight != height) - { - mState.scissorX = x; - mState.scissorY = y; - mState.scissorWidth = width; - mState.scissorHeight = height; - mScissorStateDirty = true; - } + mState.scissor.x = x; + mState.scissor.y = y; + mState.scissor.width = width; + mState.scissor.height = height; } void Context::setColorMask(bool red, bool green, bool blue, bool alpha) { - if (mState.colorMaskRed != red || mState.colorMaskGreen != green || - mState.colorMaskBlue != blue || mState.colorMaskAlpha != alpha) - { - mState.colorMaskRed = red; - mState.colorMaskGreen = green; - mState.colorMaskBlue = blue; - mState.colorMaskAlpha = alpha; - mMaskStateDirty = true; - } + mState.blend.colorMaskRed = red; + mState.blend.colorMaskGreen = green; + mState.blend.colorMaskBlue = blue; + mState.blend.colorMaskAlpha = alpha; } void Context::setDepthMask(bool mask) { - if (mState.depthMask != mask) - { - mState.depthMask = mask; - mMaskStateDirty = true; - } + mState.depthStencil.depthMask = mask; } void Context::setActiveSampler(unsigned int active) @@ -891,11 +655,6 @@ const void *Context::getVertexAttribPointer(unsigned int attribNum) const return mState.vertexAttribute[attribNum].mPointer; } -const VertexAttributeArray &Context::getVertexAttributes() -{ - return mState.vertexAttribute; -} - void Context::setPackAlignment(GLint alignment) { mState.packAlignment = alignment; @@ -965,7 +724,7 @@ GLuint Context::createFence() { GLuint handle = mFenceHandleAllocator.allocate(); - mFenceMap[handle] = new Fence(mDisplay); + mFenceMap[handle] = new Fence(mRenderer); return handle; } @@ -1127,7 +886,7 @@ void Context::bindReadFramebuffer(GLuint framebuffer) { if (!getFramebuffer(framebuffer)) { - mFramebufferMap[framebuffer] = new Framebuffer(); + mFramebufferMap[framebuffer] = new Framebuffer(mRenderer); } mState.readFramebuffer = framebuffer; @@ -1137,7 +896,7 @@ void Context::bindDrawFramebuffer(GLuint framebuffer) { if (!getFramebuffer(framebuffer)) { - mFramebufferMap[framebuffer] = new Framebuffer(); + mFramebufferMap[framebuffer] = new Framebuffer(mRenderer); } mState.drawFramebuffer = framebuffer; @@ -1162,7 +921,6 @@ void Context::useProgram(GLuint program) Program *newProgram = mResourceManager->getProgram(program); Program *oldProgram = mResourceManager->getProgram(priorProgram); mCurrentProgramBinary.set(NULL); - mDxUniformsDirty = true; if (newProgram) { @@ -1188,7 +946,6 @@ void Context::linkProgram(GLuint program) if (linked && program == mState.currentProgram) { mCurrentProgramBinary.set(programObject->getProgramBinary()); - mDxUniformsDirty = true; } } @@ -1203,7 +960,6 @@ void Context::setProgramBinary(GLuint program, const void *binary, GLint length) if (loaded && program == mState.currentProgram) { mCurrentProgramBinary.set(programObject->getProgramBinary()); - mDxUniformsDirty = true; } } @@ -1229,7 +985,7 @@ void Context::beginQuery(GLenum target, GLuint query) { if (mState.activeQuery[i].get() != NULL) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } @@ -1252,13 +1008,13 @@ void Context::beginQuery(GLenum target, GLuint query) // check that name was obtained with glGenQueries if (!queryObject) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } // check for type mismatch if (queryObject->getType() != target) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } // set query as active for specified target @@ -1289,7 +1045,7 @@ void Context::endQuery(GLenum target) if (queryObject == NULL) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } queryObject->end(); @@ -1307,8 +1063,31 @@ void Context::setFramebufferZero(Framebuffer *buffer) } } -void Context::setRenderbufferStorage(RenderbufferStorage *renderbuffer) +void Context::setRenderbufferStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples) { + RenderbufferStorage *renderbuffer = NULL; + switch (internalformat) + { + case GL_DEPTH_COMPONENT16: + renderbuffer = new gl::Depthbuffer(mRenderer, width, height, samples); + break; + case GL_RGBA4: + case GL_RGB5_A1: + case GL_RGB565: + case GL_RGB8_OES: + case GL_RGBA8_OES: + renderbuffer = new gl::Colorbuffer(mRenderer,width, height, internalformat, samples); + break; + case GL_STENCIL_INDEX8: + renderbuffer = new gl::Stencilbuffer(mRenderer, width, height, samples); + break; + case GL_DEPTH24_STENCIL8_OES: + renderbuffer = new gl::DepthStencilbuffer(mRenderer, width, height, samples); + break; + default: + UNREACHABLE(); return; + } + Renderbuffer *renderbufferObject = mState.renderbuffer.get(); renderbufferObject->setStorage(renderbuffer); } @@ -1353,7 +1132,7 @@ Query *Context::getQuery(unsigned int handle, bool create, GLenum type) { if (!query->second && create) { - query->second = new Query(handle, type); + query->second = new Query(mRenderer, type, handle); query->second->addRef(); } return query->second; @@ -1406,25 +1185,25 @@ bool Context::getBooleanv(GLenum pname, GLboolean *params) { switch (pname) { - case GL_SHADER_COMPILER: *params = GL_TRUE; break; - case GL_SAMPLE_COVERAGE_INVERT: *params = mState.sampleCoverageInvert; break; - case GL_DEPTH_WRITEMASK: *params = mState.depthMask; break; + case GL_SHADER_COMPILER: *params = GL_TRUE; break; + case GL_SAMPLE_COVERAGE_INVERT: *params = mState.sampleCoverageInvert; break; + case GL_DEPTH_WRITEMASK: *params = mState.depthStencil.depthMask; break; case GL_COLOR_WRITEMASK: - params[0] = mState.colorMaskRed; - params[1] = mState.colorMaskGreen; - params[2] = mState.colorMaskBlue; - params[3] = mState.colorMaskAlpha; + params[0] = mState.blend.colorMaskRed; + params[1] = mState.blend.colorMaskGreen; + params[2] = mState.blend.colorMaskBlue; + params[3] = mState.blend.colorMaskAlpha; break; - case GL_CULL_FACE: *params = mState.cullFace; break; - case GL_POLYGON_OFFSET_FILL: *params = mState.polygonOffsetFill; break; - case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mState.sampleAlphaToCoverage; break; - case GL_SAMPLE_COVERAGE: *params = mState.sampleCoverage; break; - case GL_SCISSOR_TEST: *params = mState.scissorTest; break; - case GL_STENCIL_TEST: *params = mState.stencilTest; break; - case GL_DEPTH_TEST: *params = mState.depthTest; break; - case GL_BLEND: *params = mState.blend; break; - case GL_DITHER: *params = mState.dither; break; - case GL_CONTEXT_ROBUST_ACCESS_EXT: *params = mRobustAccess ? GL_TRUE : GL_FALSE; break; + case GL_CULL_FACE: *params = mState.rasterizer.cullFace; break; + case GL_POLYGON_OFFSET_FILL: *params = mState.rasterizer.polygonOffsetFill; break; + case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mState.blend.sampleAlphaToCoverage; break; + case GL_SAMPLE_COVERAGE: *params = mState.sampleCoverage; break; + case GL_SCISSOR_TEST: *params = mState.scissorTest; break; + case GL_STENCIL_TEST: *params = mState.depthStencil.stencilTest; break; + case GL_DEPTH_TEST: *params = mState.depthStencil.depthTest; break; + case GL_BLEND: *params = mState.blend.blend; break; + case GL_DITHER: *params = mState.blend.dither; break; + case GL_CONTEXT_ROBUST_ACCESS_EXT: *params = mRobustAccess ? GL_TRUE : GL_FALSE; break; default: return false; } @@ -1440,11 +1219,11 @@ bool Context::getFloatv(GLenum pname, GLfloat *params) // case, this should make no difference to the calling application. switch (pname) { - case GL_LINE_WIDTH: *params = mState.lineWidth; break; - case GL_SAMPLE_COVERAGE_VALUE: *params = mState.sampleCoverageValue; break; - case GL_DEPTH_CLEAR_VALUE: *params = mState.depthClearValue; break; - case GL_POLYGON_OFFSET_FACTOR: *params = mState.polygonOffsetFactor; break; - case GL_POLYGON_OFFSET_UNITS: *params = mState.polygonOffsetUnits; break; + case GL_LINE_WIDTH: *params = mState.lineWidth; break; + case GL_SAMPLE_COVERAGE_VALUE: *params = mState.sampleCoverageValue; break; + case GL_DEPTH_CLEAR_VALUE: *params = mState.depthClearValue; break; + case GL_POLYGON_OFFSET_FACTOR: *params = mState.rasterizer.polygonOffsetFactor; break; + case GL_POLYGON_OFFSET_UNITS: *params = mState.rasterizer.polygonOffsetUnits; break; case GL_ALIASED_LINE_WIDTH_RANGE: params[0] = gl::ALIASED_LINE_WIDTH_RANGE_MIN; params[1] = gl::ALIASED_LINE_WIDTH_RANGE_MAX; @@ -1485,6 +1264,22 @@ bool Context::getFloatv(GLenum pname, GLfloat *params) bool Context::getIntegerv(GLenum pname, GLint *params) { + if (pname >= GL_DRAW_BUFFER0_EXT && pname <= GL_DRAW_BUFFER15_EXT) + { + unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0_EXT); + + if (colorAttachment >= mRenderer->getMaxRenderTargets()) + { + // return true to stop further operation in the parent call + return gl::error(GL_INVALID_OPERATION, true); + } + + Framebuffer *framebuffer = getDrawFramebuffer(); + + *params = framebuffer->getDrawBufferState(colorAttachment); + return true; + } + // Please note: DEPTH_CLEAR_VALUE is not included in our internal getIntegerv implementation // because it is stored as a float, despite the fact that the GL ES 2.0 spec names // GetIntegerv as its native query function. As it would require conversion in any @@ -1493,13 +1288,15 @@ bool Context::getIntegerv(GLenum pname, GLint *params) switch (pname) { case GL_MAX_VERTEX_ATTRIBS: *params = gl::MAX_VERTEX_ATTRIBS; break; - case GL_MAX_VERTEX_UNIFORM_VECTORS: *params = gl::MAX_VERTEX_UNIFORM_VECTORS; break; - case GL_MAX_VARYING_VECTORS: *params = getMaximumVaryingVectors(); break; - case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = getMaximumCombinedTextureImageUnits(); break; - case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = getMaximumVertexTextureImageUnits(); break; + case GL_MAX_VERTEX_UNIFORM_VECTORS: *params = mRenderer->getMaxVertexUniformVectors(); break; + case GL_MAX_VARYING_VECTORS: *params = mRenderer->getMaxVaryingVectors(); break; + case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = mRenderer->getMaxCombinedTextureImageUnits(); break; + case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = mRenderer->getMaxVertexTextureImageUnits(); break; case GL_MAX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_TEXTURE_IMAGE_UNITS; break; - case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = getMaximumFragmentUniformVectors(); break; + case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = mRenderer->getMaxFragmentUniformVectors(); break; case GL_MAX_RENDERBUFFER_SIZE: *params = getMaximumRenderbufferDimension(); break; + case GL_MAX_COLOR_ATTACHMENTS_EXT: *params = mRenderer->getMaxRenderTargets(); break; + case GL_MAX_DRAW_BUFFERS_EXT: *params = mRenderer->getMaxRenderTargets(); break; case GL_NUM_SHADER_BINARY_FORMATS: *params = 0; break; case GL_SHADER_BINARY_FORMATS: /* no shader binary formats are supported */ break; case GL_ARRAY_BUFFER_BINDING: *params = mState.arrayBuffer.id(); break; @@ -1515,27 +1312,27 @@ bool Context::getIntegerv(GLenum pname, GLint *params) case GL_GENERATE_MIPMAP_HINT: *params = mState.generateMipmapHint; break; case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: *params = mState.fragmentShaderDerivativeHint; break; case GL_ACTIVE_TEXTURE: *params = (mState.activeSampler + GL_TEXTURE0); break; - case GL_STENCIL_FUNC: *params = mState.stencilFunc; break; - case GL_STENCIL_REF: *params = mState.stencilRef; break; - case GL_STENCIL_VALUE_MASK: *params = mState.stencilMask; break; - case GL_STENCIL_BACK_FUNC: *params = mState.stencilBackFunc; break; - case GL_STENCIL_BACK_REF: *params = mState.stencilBackRef; break; - case GL_STENCIL_BACK_VALUE_MASK: *params = mState.stencilBackMask; break; - case GL_STENCIL_FAIL: *params = mState.stencilFail; break; - case GL_STENCIL_PASS_DEPTH_FAIL: *params = mState.stencilPassDepthFail; break; - case GL_STENCIL_PASS_DEPTH_PASS: *params = mState.stencilPassDepthPass; break; - case GL_STENCIL_BACK_FAIL: *params = mState.stencilBackFail; break; - case GL_STENCIL_BACK_PASS_DEPTH_FAIL: *params = mState.stencilBackPassDepthFail; break; - case GL_STENCIL_BACK_PASS_DEPTH_PASS: *params = mState.stencilBackPassDepthPass; break; - case GL_DEPTH_FUNC: *params = mState.depthFunc; break; - case GL_BLEND_SRC_RGB: *params = mState.sourceBlendRGB; break; - case GL_BLEND_SRC_ALPHA: *params = mState.sourceBlendAlpha; break; - case GL_BLEND_DST_RGB: *params = mState.destBlendRGB; break; - case GL_BLEND_DST_ALPHA: *params = mState.destBlendAlpha; break; - case GL_BLEND_EQUATION_RGB: *params = mState.blendEquationRGB; break; - case GL_BLEND_EQUATION_ALPHA: *params = mState.blendEquationAlpha; break; - case GL_STENCIL_WRITEMASK: *params = mState.stencilWritemask; break; - case GL_STENCIL_BACK_WRITEMASK: *params = mState.stencilBackWritemask; break; + case GL_STENCIL_FUNC: *params = mState.depthStencil.stencilFunc; break; + case GL_STENCIL_REF: *params = mState.stencilRef; break; + case GL_STENCIL_VALUE_MASK: *params = mState.depthStencil.stencilMask; break; + case GL_STENCIL_BACK_FUNC: *params = mState.depthStencil.stencilBackFunc; break; + case GL_STENCIL_BACK_REF: *params = mState.stencilBackRef; break; + case GL_STENCIL_BACK_VALUE_MASK: *params = mState.depthStencil.stencilBackMask; break; + case GL_STENCIL_FAIL: *params = mState.depthStencil.stencilFail; break; + case GL_STENCIL_PASS_DEPTH_FAIL: *params = mState.depthStencil.stencilPassDepthFail; break; + case GL_STENCIL_PASS_DEPTH_PASS: *params = mState.depthStencil.stencilPassDepthPass; break; + case GL_STENCIL_BACK_FAIL: *params = mState.depthStencil.stencilBackFail; break; + case GL_STENCIL_BACK_PASS_DEPTH_FAIL: *params = mState.depthStencil.stencilBackPassDepthFail; break; + case GL_STENCIL_BACK_PASS_DEPTH_PASS: *params = mState.depthStencil.stencilBackPassDepthPass; break; + case GL_DEPTH_FUNC: *params = mState.depthStencil.depthFunc; break; + case GL_BLEND_SRC_RGB: *params = mState.blend.sourceBlendRGB; break; + case GL_BLEND_SRC_ALPHA: *params = mState.blend.sourceBlendAlpha; break; + case GL_BLEND_DST_RGB: *params = mState.blend.destBlendRGB; break; + case GL_BLEND_DST_ALPHA: *params = mState.blend.destBlendAlpha; break; + case GL_BLEND_EQUATION_RGB: *params = mState.blend.blendEquationRGB; break; + case GL_BLEND_EQUATION_ALPHA: *params = mState.blend.blendEquationAlpha; break; + case GL_STENCIL_WRITEMASK: *params = mState.depthStencil.stencilWritemask; break; + case GL_STENCIL_BACK_WRITEMASK: *params = mState.depthStencil.stencilBackWritemask; break; case GL_STENCIL_CLEAR_VALUE: *params = mState.stencilClearValue; break; case GL_SUBPIXEL_BITS: *params = 4; break; case GL_MAX_TEXTURE_SIZE: *params = getMaximumTextureDimension(); break; @@ -1601,9 +1398,8 @@ bool Context::getIntegerv(GLenum pname, GLint *params) break; case GL_MAX_VIEWPORT_DIMS: { - int maxDimension = std::max(getMaximumRenderbufferDimension(), getMaximumTextureDimension()); - params[0] = maxDimension; - params[1] = maxDimension; + params[0] = mMaxViewportDimension; + params[1] = mMaxViewportDimension; } break; case GL_COMPRESSED_TEXTURE_FORMATS: @@ -1624,35 +1420,35 @@ bool Context::getIntegerv(GLenum pname, GLint *params) } break; case GL_VIEWPORT: - params[0] = mState.viewportX; - params[1] = mState.viewportY; - params[2] = mState.viewportWidth; - params[3] = mState.viewportHeight; + params[0] = mState.viewport.x; + params[1] = mState.viewport.y; + params[2] = mState.viewport.width; + params[3] = mState.viewport.height; break; case GL_SCISSOR_BOX: - params[0] = mState.scissorX; - params[1] = mState.scissorY; - params[2] = mState.scissorWidth; - params[3] = mState.scissorHeight; + params[0] = mState.scissor.x; + params[1] = mState.scissor.y; + params[2] = mState.scissor.width; + params[3] = mState.scissor.height; break; - case GL_CULL_FACE_MODE: *params = mState.cullMode; break; - case GL_FRONT_FACE: *params = mState.frontFace; break; + case GL_CULL_FACE_MODE: *params = mState.rasterizer.cullMode; break; + case GL_FRONT_FACE: *params = mState.rasterizer.frontFace; break; case GL_RED_BITS: case GL_GREEN_BITS: case GL_BLUE_BITS: case GL_ALPHA_BITS: { gl::Framebuffer *framebuffer = getDrawFramebuffer(); - gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(); + gl::Renderbuffer *colorbuffer = framebuffer->getFirstColorbuffer(); if (colorbuffer) { switch (pname) { - case GL_RED_BITS: *params = colorbuffer->getRedSize(); break; - case GL_GREEN_BITS: *params = colorbuffer->getGreenSize(); break; - case GL_BLUE_BITS: *params = colorbuffer->getBlueSize(); break; - case GL_ALPHA_BITS: *params = colorbuffer->getAlphaSize(); break; + case GL_RED_BITS: *params = colorbuffer->getRedSize(); break; + case GL_GREEN_BITS: *params = colorbuffer->getGreenSize(); break; + case GL_BLUE_BITS: *params = colorbuffer->getBlueSize(); break; + case GL_ALPHA_BITS: *params = colorbuffer->getAlphaSize(); break; } } else @@ -1693,9 +1489,9 @@ bool Context::getIntegerv(GLenum pname, GLint *params) break; case GL_TEXTURE_BINDING_2D: { - if (mState.activeSampler > getMaximumCombinedTextureImageUnits() - 1) + if (mState.activeSampler > mRenderer->getMaxCombinedTextureImageUnits() - 1) { - error(GL_INVALID_OPERATION); + gl::error(GL_INVALID_OPERATION); return false; } @@ -1704,9 +1500,9 @@ bool Context::getIntegerv(GLenum pname, GLint *params) break; case GL_TEXTURE_BINDING_CUBE_MAP: { - if (mState.activeSampler > getMaximumCombinedTextureImageUnits() - 1) + if (mState.activeSampler > mRenderer->getMaxCombinedTextureImageUnits() - 1) { - error(GL_INVALID_OPERATION); + gl::error(GL_INVALID_OPERATION); return false; } @@ -1731,6 +1527,13 @@ bool Context::getIntegerv(GLenum pname, GLint *params) bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams) { + if (pname >= GL_DRAW_BUFFER0_EXT && pname <= GL_DRAW_BUFFER15_EXT) + { + *type = GL_INT; + *numParams = 1; + return true; + } + // Please note: the query type returned for DEPTH_CLEAR_VALUE in this implementation // is FLOAT rather than INT, as would be suggested by the GL ES 2.0 spec. This is due // to the fact that it is stored internally as a float, and so would require conversion @@ -1760,6 +1563,8 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu case GL_MAX_TEXTURE_IMAGE_UNITS: case GL_MAX_FRAGMENT_UNIFORM_VECTORS: case GL_MAX_RENDERBUFFER_SIZE: + case GL_MAX_COLOR_ATTACHMENTS_EXT: + case GL_MAX_DRAW_BUFFERS_EXT: case GL_NUM_SHADER_BINARY_FORMATS: case GL_NUM_COMPRESSED_TEXTURE_FORMATS: case GL_ARRAY_BUFFER_BINDING: @@ -1911,186 +1716,25 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu } // Applies the render target surface, depth stencil surface, viewport rectangle and -// scissor rectangle to the Direct3D 9 device -bool Context::applyRenderTarget(bool ignoreViewport) +// scissor rectangle to the renderer +bool Context::applyRenderTarget(GLenum drawMode, bool ignoreViewport) { Framebuffer *framebufferObject = getDrawFramebuffer(); if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE) { - return error(GL_INVALID_FRAMEBUFFER_OPERATION, false); + return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION, false); } - // if there is no color attachment we must synthesize a NULL colorattachment - // to keep the D3D runtime happy. This should only be possible if depth texturing. - Renderbuffer *renderbufferObject = NULL; - if (framebufferObject->getColorbufferType() != GL_NONE) + mRenderer->applyRenderTarget(framebufferObject); + + if (!mRenderer->setViewport(mState.viewport, mState.zNear, mState.zFar, drawMode, mState.rasterizer.frontFace, + ignoreViewport)) { - renderbufferObject = framebufferObject->getColorbuffer(); - } - else - { - renderbufferObject = framebufferObject->getNullColorbuffer(); - } - if (!renderbufferObject) - { - ERR("unable to locate renderbuffer for FBO."); return false; } - bool renderTargetChanged = false; - unsigned int renderTargetSerial = renderbufferObject->getSerial(); - if (renderTargetSerial != mAppliedRenderTargetSerial) - { - IDirect3DSurface9 *renderTarget = renderbufferObject->getRenderTarget(); - if (!renderTarget) - { - ERR("render target pointer unexpectedly null."); - return false; // Context must be lost - } - mDevice->SetRenderTarget(0, renderTarget); - mAppliedRenderTargetSerial = renderTargetSerial; - mScissorStateDirty = true; // Scissor area must be clamped to render target's size-- this is different for different render targets. - renderTargetChanged = true; - renderTarget->Release(); - } - - IDirect3DSurface9 *depthStencil = NULL; - unsigned int depthbufferSerial = 0; - unsigned int stencilbufferSerial = 0; - if (framebufferObject->getDepthbufferType() != GL_NONE) - { - Renderbuffer *depthbuffer = framebufferObject->getDepthbuffer(); - depthStencil = depthbuffer->getDepthStencil(); - if (!depthStencil) - { - ERR("Depth stencil pointer unexpectedly null."); - return false; - } - - depthbufferSerial = depthbuffer->getSerial(); - } - else if (framebufferObject->getStencilbufferType() != GL_NONE) - { - Renderbuffer *stencilbuffer = framebufferObject->getStencilbuffer(); - depthStencil = stencilbuffer->getDepthStencil(); - if (!depthStencil) - { - ERR("Depth stencil pointer unexpectedly null."); - return false; - } - - stencilbufferSerial = stencilbuffer->getSerial(); - } - - if (depthbufferSerial != mAppliedDepthbufferSerial || - stencilbufferSerial != mAppliedStencilbufferSerial || - !mDepthStencilInitialized) - { - mDevice->SetDepthStencilSurface(depthStencil); - mAppliedDepthbufferSerial = depthbufferSerial; - mAppliedStencilbufferSerial = stencilbufferSerial; - mDepthStencilInitialized = true; - } - - if (depthStencil) - { - depthStencil->Release(); - } - - if (!mRenderTargetDescInitialized || renderTargetChanged) - { - IDirect3DSurface9 *renderTarget = renderbufferObject->getRenderTarget(); - if (!renderTarget) - { - return false; // Context must be lost - } - renderTarget->GetDesc(&mRenderTargetDesc); - mRenderTargetDescInitialized = true; - renderTarget->Release(); - } - - D3DVIEWPORT9 viewport; - - float zNear = clamp01(mState.zNear); - float zFar = clamp01(mState.zFar); - - if (ignoreViewport) - { - viewport.X = 0; - viewport.Y = 0; - viewport.Width = mRenderTargetDesc.Width; - viewport.Height = mRenderTargetDesc.Height; - viewport.MinZ = 0.0f; - viewport.MaxZ = 1.0f; - } - else - { - viewport.X = clamp(mState.viewportX, 0L, static_cast(mRenderTargetDesc.Width)); - viewport.Y = clamp(mState.viewportY, 0L, static_cast(mRenderTargetDesc.Height)); - viewport.Width = clamp(mState.viewportWidth, 0L, static_cast(mRenderTargetDesc.Width) - static_cast(viewport.X)); - viewport.Height = clamp(mState.viewportHeight, 0L, static_cast(mRenderTargetDesc.Height) - static_cast(viewport.Y)); - viewport.MinZ = zNear; - viewport.MaxZ = zFar; - } - - if (viewport.Width <= 0 || viewport.Height <= 0) - { - return false; // Nothing to render - } - - if (renderTargetChanged || !mViewportInitialized || memcmp(&viewport, &mSetViewport, sizeof mSetViewport) != 0) - { - mDevice->SetViewport(&viewport); - mSetViewport = viewport; - mViewportInitialized = true; - mDxUniformsDirty = true; - } - - if (mScissorStateDirty) - { - if (mState.scissorTest) - { - RECT rect; - rect.left = clamp(mState.scissorX, 0L, static_cast(mRenderTargetDesc.Width)); - rect.top = clamp(mState.scissorY, 0L, static_cast(mRenderTargetDesc.Height)); - rect.right = clamp(mState.scissorX + mState.scissorWidth, 0L, static_cast(mRenderTargetDesc.Width)); - rect.bottom = clamp(mState.scissorY + mState.scissorHeight, 0L, static_cast(mRenderTargetDesc.Height)); - mDevice->SetScissorRect(&rect); - mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); - } - else - { - mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); - } - - mScissorStateDirty = false; - } - - if (mState.currentProgram && mDxUniformsDirty) - { - ProgramBinary *programBinary = getCurrentProgramBinary(); - - GLint halfPixelSize = programBinary->getDxHalfPixelSizeLocation(); - GLfloat xy[2] = {1.0f / viewport.Width, -1.0f / viewport.Height}; - programBinary->setUniform2fv(halfPixelSize, 1, xy); - - // These values are used for computing gl_FragCoord in Program::linkVaryings(). - GLint coord = programBinary->getDxCoordLocation(); - GLfloat whxy[4] = {mState.viewportWidth / 2.0f, mState.viewportHeight / 2.0f, - (float)mState.viewportX + mState.viewportWidth / 2.0f, - (float)mState.viewportY + mState.viewportHeight / 2.0f}; - programBinary->setUniform4fv(coord, 1, whxy); - - GLint depth = programBinary->getDxDepthLocation(); - GLfloat dz[2] = {(zFar - zNear) / 2.0f, (zNear + zFar) / 2.0f}; - programBinary->setUniform2fv(depth, 1, dz); - - GLint depthRange = programBinary->getDxDepthRangeLocation(); - GLfloat nearFarDiff[3] = {zNear, zFar, zFar - zNear}; - programBinary->setUniform3fv(depthRange, 1, nearFarDiff); - mDxUniformsDirty = false; - } + mRenderer->setScissorRectangle(mState.scissor, mState.scissorTest); return true; } @@ -2098,290 +1742,46 @@ bool Context::applyRenderTarget(bool ignoreViewport) // Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D 9 device void Context::applyState(GLenum drawMode) { - ProgramBinary *programBinary = getCurrentProgramBinary(); - Framebuffer *framebufferObject = getDrawFramebuffer(); + int samples = framebufferObject->getSamples(); - GLint frontCCW = programBinary->getDxFrontCCWLocation(); - GLint ccw = (mState.frontFace == GL_CCW); - programBinary->setUniform1iv(frontCCW, 1, &ccw); + mState.rasterizer.pointDrawMode = (drawMode == GL_POINTS); + mState.rasterizer.multiSample = (samples != 0); + mRenderer->setRasterizerState(mState.rasterizer); - GLint pointsOrLines = programBinary->getDxPointsOrLinesLocation(); - GLint alwaysFront = !isTriangleMode(drawMode); - programBinary->setUniform1iv(pointsOrLines, 1, &alwaysFront); - - D3DADAPTER_IDENTIFIER9 *identifier = mDisplay->getAdapterIdentifier(); - bool zeroColorMaskAllowed = identifier->VendorId != 0x1002; - // Apparently some ATI cards have a bug where a draw with a zero color - // write mask can cause later draws to have incorrect results. Instead, - // set a nonzero color write mask but modify the blend state so that no - // drawing is done. - // http://code.google.com/p/angleproject/issues/detail?id=169 - - if (mCullStateDirty || mFrontFaceDirty) + unsigned int mask = 0; + if (mState.sampleCoverage) { - if (mState.cullFace) + if (mState.sampleCoverageValue != 0) { - mDevice->SetRenderState(D3DRS_CULLMODE, es2dx::ConvertCullMode(mState.cullMode, mState.frontFace)); - } - else - { - mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); - } + + float threshold = 0.5f; - mCullStateDirty = false; - } - - if (mDepthStateDirty) - { - if (mState.depthTest) - { - mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); - mDevice->SetRenderState(D3DRS_ZFUNC, es2dx::ConvertComparison(mState.depthFunc)); - } - else - { - mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); - } - - mDepthStateDirty = false; - } - - if (!zeroColorMaskAllowed && (mMaskStateDirty || mBlendStateDirty)) - { - mBlendStateDirty = true; - mMaskStateDirty = true; - } - - if (mBlendStateDirty) - { - if (mState.blend) - { - mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); - - if (mState.sourceBlendRGB != GL_CONSTANT_ALPHA && mState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA && - mState.destBlendRGB != GL_CONSTANT_ALPHA && mState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA) + for (int i = 0; i < samples; ++i) { - mDevice->SetRenderState(D3DRS_BLENDFACTOR, es2dx::ConvertColor(mState.blendColor)); - } - else - { - mDevice->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(unorm<8>(mState.blendColor.alpha), - unorm<8>(mState.blendColor.alpha), - unorm<8>(mState.blendColor.alpha), - unorm<8>(mState.blendColor.alpha))); - } + mask <<= 1; - mDevice->SetRenderState(D3DRS_SRCBLEND, es2dx::ConvertBlendFunc(mState.sourceBlendRGB)); - mDevice->SetRenderState(D3DRS_DESTBLEND, es2dx::ConvertBlendFunc(mState.destBlendRGB)); - mDevice->SetRenderState(D3DRS_BLENDOP, es2dx::ConvertBlendOp(mState.blendEquationRGB)); - - if (mState.sourceBlendRGB != mState.sourceBlendAlpha || - mState.destBlendRGB != mState.destBlendAlpha || - mState.blendEquationRGB != mState.blendEquationAlpha) - { - mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); - - mDevice->SetRenderState(D3DRS_SRCBLENDALPHA, es2dx::ConvertBlendFunc(mState.sourceBlendAlpha)); - mDevice->SetRenderState(D3DRS_DESTBLENDALPHA, es2dx::ConvertBlendFunc(mState.destBlendAlpha)); - mDevice->SetRenderState(D3DRS_BLENDOPALPHA, es2dx::ConvertBlendOp(mState.blendEquationAlpha)); - } - else - { - mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE); - } - } - else - { - mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); - } - - mBlendStateDirty = false; - } - - if (mStencilStateDirty || mFrontFaceDirty) - { - if (mState.stencilTest && framebufferObject->hasStencil()) - { - mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE); - mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE); - - // FIXME: Unsupported by D3D9 - const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF; - const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK; - const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK; - if (mState.stencilWritemask != mState.stencilBackWritemask || - mState.stencilRef != mState.stencilBackRef || - mState.stencilMask != mState.stencilBackMask) - { - ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL."); - return error(GL_INVALID_OPERATION); - } - - // get the maximum size of the stencil ref - gl::Renderbuffer *stencilbuffer = framebufferObject->getStencilbuffer(); - GLuint maxStencil = (1 << stencilbuffer->getStencilSize()) - 1; - - mDevice->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilWritemask); - mDevice->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, - es2dx::ConvertComparison(mState.stencilFunc)); - - mDevice->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, (mState.stencilRef < (GLint)maxStencil) ? mState.stencilRef : maxStencil); - mDevice->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilMask); - - mDevice->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, - es2dx::ConvertStencilOp(mState.stencilFail)); - mDevice->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, - es2dx::ConvertStencilOp(mState.stencilPassDepthFail)); - mDevice->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, - es2dx::ConvertStencilOp(mState.stencilPassDepthPass)); - - mDevice->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilBackWritemask); - mDevice->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, - es2dx::ConvertComparison(mState.stencilBackFunc)); - - mDevice->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, (mState.stencilBackRef < (GLint)maxStencil) ? mState.stencilBackRef : maxStencil); - mDevice->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilBackMask); - - mDevice->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, - es2dx::ConvertStencilOp(mState.stencilBackFail)); - mDevice->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, - es2dx::ConvertStencilOp(mState.stencilBackPassDepthFail)); - mDevice->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, - es2dx::ConvertStencilOp(mState.stencilBackPassDepthPass)); - } - else - { - mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); - } - - mStencilStateDirty = false; - mFrontFaceDirty = false; - } - - if (mMaskStateDirty) - { - int colorMask = es2dx::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen, - mState.colorMaskBlue, mState.colorMaskAlpha); - if (colorMask == 0 && !zeroColorMaskAllowed) - { - // Enable green channel, but set blending so nothing will be drawn. - mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_GREEN); - mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); - - mDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO); - mDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); - mDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); - } - else - { - mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, colorMask); - } - mDevice->SetRenderState(D3DRS_ZWRITEENABLE, mState.depthMask ? TRUE : FALSE); - - mMaskStateDirty = false; - } - - if (mPolygonOffsetStateDirty) - { - if (mState.polygonOffsetFill) - { - gl::Renderbuffer *depthbuffer = framebufferObject->getDepthbuffer(); - if (depthbuffer) - { - mDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *((DWORD*)&mState.polygonOffsetFactor)); - float depthBias = ldexp(mState.polygonOffsetUnits, -(int)(depthbuffer->getDepthSize())); - mDevice->SetRenderState(D3DRS_DEPTHBIAS, *((DWORD*)&depthBias)); - } - } - else - { - mDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0); - mDevice->SetRenderState(D3DRS_DEPTHBIAS, 0); - } - - mPolygonOffsetStateDirty = false; - } - - if (mSampleStateDirty) - { - if (mState.sampleAlphaToCoverage) - { - FIXME("Sample alpha to coverage is unimplemented."); - } - - mDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE); - if (mState.sampleCoverage) - { - unsigned int mask = 0; - if (mState.sampleCoverageValue != 0) - { - float threshold = 0.5f; - - for (int i = 0; i < framebufferObject->getSamples(); ++i) + if ((i + 1) * mState.sampleCoverageValue >= threshold) { - mask <<= 1; - - if ((i + 1) * mState.sampleCoverageValue >= threshold) - { - threshold += 1.0f; - mask |= 1; - } + threshold += 1.0f; + mask |= 1; } } - - if (mState.sampleCoverageInvert) - { - mask = ~mask; - } - - mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, mask); } - else + + if (mState.sampleCoverageInvert) { - mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF); - } - - mSampleStateDirty = false; - } - - if (mDitherStateDirty) - { - mDevice->SetRenderState(D3DRS_DITHERENABLE, mState.dither ? TRUE : FALSE); - - mDitherStateDirty = false; - } -} - -GLenum Context::applyVertexBuffer(GLint first, GLsizei count, GLsizei instances, GLsizei *repeatDraw) -{ - TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS]; - - GLenum err = mVertexDataManager->prepareVertexData(first, count, attributes, instances); - if (err != GL_NO_ERROR) - { - return err; - } - - ProgramBinary *programBinary = getCurrentProgramBinary(); - return mVertexDeclarationCache.applyDeclaration(mDevice, attributes, programBinary, instances, repeatDraw); -} - -// Applies the indices and element array bindings to the Direct3D 9 device -GLenum Context::applyIndexBuffer(const GLvoid *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) -{ - GLenum err = mIndexDataManager->prepareIndexData(type, count, mState.elementArrayBuffer.get(), indices, indexInfo); - - if (err == GL_NO_ERROR) - { - if (indexInfo->serial != mAppliedIBSerial) - { - mDevice->SetIndices(indexInfo->indexBuffer); - mAppliedIBSerial = indexInfo->serial; + mask = ~mask; } } + else + { + mask = 0xFFFFFFFF; + } + mRenderer->setBlendState(mState.blend, mState.blendColor, mask); - return err; + mRenderer->setDepthStencilState(mState.depthStencil, mState.stencilRef, mState.stencilBackRef, + mState.rasterizer.frontFace == GL_CCW); } // Applies the shaders and shader constants to the Direct3D 9 device @@ -2389,17 +1789,8 @@ void Context::applyShaders() { ProgramBinary *programBinary = getCurrentProgramBinary(); - if (programBinary->getSerial() != mAppliedProgramBinarySerial) - { - IDirect3DVertexShader9 *vertexShader = programBinary->getVertexShader(); - IDirect3DPixelShader9 *pixelShader = programBinary->getPixelShader(); - - mDevice->SetPixelShader(pixelShader); - mDevice->SetVertexShader(vertexShader); - programBinary->dirtyAllUniforms(); - mAppliedProgramBinarySerial = programBinary->getSerial(); - } - + mRenderer->applyShaders(programBinary); + programBinary->applyUniforms(); } @@ -2421,84 +1812,43 @@ void Context::applyTextures(SamplerType type) { ProgramBinary *programBinary = getCurrentProgramBinary(); - int samplerCount = (type == SAMPLER_PIXEL) ? MAX_TEXTURE_IMAGE_UNITS : MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; // Range of Direct3D 9 samplers of given sampler type - unsigned int *appliedTextureSerial = (type == SAMPLER_PIXEL) ? mAppliedTextureSerialPS : mAppliedTextureSerialVS; - int d3dSamplerOffset = (type == SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0; + // Range of Direct3D samplers of given sampler type + int samplerCount = (type == SAMPLER_PIXEL) ? MAX_TEXTURE_IMAGE_UNITS : mRenderer->getMaxVertexTextureImageUnits(); int samplerRange = programBinary->getUsedSamplerRange(type); for (int samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++) { int textureUnit = programBinary->getSamplerMapping(type, samplerIndex); // OpenGL texture image unit index - int d3dSampler = samplerIndex + d3dSamplerOffset; if (textureUnit != -1) { TextureType textureType = programBinary->getSamplerTextureType(type, samplerIndex); - Texture *texture = getSamplerTexture(textureUnit, textureType); - unsigned int texSerial = texture->getTextureSerial(); - if (appliedTextureSerial[samplerIndex] != texSerial || texture->hasDirtyParameters() || texture->hasDirtyImages()) + if (texture->isSamplerComplete()) { - IDirect3DBaseTexture9 *d3dTexture = texture->getTexture(); + SamplerState samplerState; + texture->getSamplerState(&samplerState); + mRenderer->setSamplerState(type, samplerIndex, samplerState); - if (d3dTexture) - { - if (appliedTextureSerial[samplerIndex] != texSerial || texture->hasDirtyParameters()) - { - GLenum wrapS = texture->getWrapS(); - GLenum wrapT = texture->getWrapT(); - GLenum minFilter = texture->getMinFilter(); - GLenum magFilter = texture->getMagFilter(); - float maxAnisotropy = texture->getMaxAnisotropy(); + mRenderer->setTexture(type, samplerIndex, texture); - mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSU, es2dx::ConvertTextureWrap(wrapS)); - mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSV, es2dx::ConvertTextureWrap(wrapT)); - - mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAGFILTER, es2dx::ConvertMagFilter(magFilter, maxAnisotropy)); - D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter; - es2dx::ConvertMinFilter(minFilter, &d3dMinFilter, &d3dMipFilter, maxAnisotropy); - mDevice->SetSamplerState(d3dSampler, D3DSAMP_MINFILTER, d3dMinFilter); - mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter); - mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXMIPLEVEL, texture->getLodOffset()); - - if (supportsTextureFilterAnisotropy()) - { - mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXANISOTROPY, (DWORD)maxAnisotropy); - } - } - - if (appliedTextureSerial[samplerIndex] != texSerial || texture->hasDirtyImages()) - { - mDevice->SetTexture(d3dSampler, d3dTexture); - } - } - else - { - mDevice->SetTexture(d3dSampler, getIncompleteTexture(textureType)->getTexture()); - } - - appliedTextureSerial[samplerIndex] = texSerial; texture->resetDirty(); } + else + { + mRenderer->setTexture(type, samplerIndex, getIncompleteTexture(textureType)); + } } else { - if (appliedTextureSerial[samplerIndex] != 0) - { - mDevice->SetTexture(d3dSampler, NULL); - appliedTextureSerial[samplerIndex] = 0; - } + mRenderer->setTexture(type, samplerIndex, NULL); } } for (int samplerIndex = samplerRange; samplerIndex < samplerCount; samplerIndex++) { - if (appliedTextureSerial[samplerIndex] != 0) - { - mDevice->SetTexture(samplerIndex + d3dSamplerOffset, NULL); - appliedTextureSerial[samplerIndex] = 0; - } + mRenderer->setTexture(type, samplerIndex, NULL); } } @@ -2509,354 +1859,26 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) { - return error(GL_INVALID_FRAMEBUFFER_OPERATION); + return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION); } if (getReadFramebufferHandle() != 0 && framebuffer->getSamples() != 0) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } - GLsizei outputPitch = ComputePitch(width, ConvertSizedInternalFormat(format, type), mState.packAlignment); + GLsizei outputPitch = ComputePitch(width, ConvertSizedInternalFormat(format, type), getPackAlignment()); // sized query sanity check if (bufSize) { int requiredSize = outputPitch * height; if (requiredSize > *bufSize) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } - IDirect3DSurface9 *renderTarget = framebuffer->getRenderTarget(); - if (!renderTarget) - { - return; // Context must be lost, return silently - } - - D3DSURFACE_DESC desc; - renderTarget->GetDesc(&desc); - - if (desc.MultiSampleType != D3DMULTISAMPLE_NONE) - { - UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target - renderTarget->Release(); - return error(GL_OUT_OF_MEMORY); - } - - HRESULT result; - IDirect3DSurface9 *systemSurface = NULL; - bool directToPixels = !getPackReverseRowOrder() && getPackAlignment() <= 4 && mDisplay->isD3d9ExDevice() && - x == 0 && y == 0 && UINT(width) == desc.Width && UINT(height) == desc.Height && - desc.Format == D3DFMT_A8R8G8B8 && format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE; - if (directToPixels) - { - // Use the pixels ptr as a shared handle to write directly into client's memory - result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, - D3DPOOL_SYSTEMMEM, &systemSurface, &pixels); - if (FAILED(result)) - { - // Try again without the shared handle - directToPixels = false; - } - } - - if (!directToPixels) - { - result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, - D3DPOOL_SYSTEMMEM, &systemSurface, NULL); - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - renderTarget->Release(); - return error(GL_OUT_OF_MEMORY); - } - } - - result = mDevice->GetRenderTargetData(renderTarget, systemSurface); - renderTarget->Release(); - renderTarget = NULL; - - if (FAILED(result)) - { - systemSurface->Release(); - - // It turns out that D3D will sometimes produce more error - // codes than those documented. - if (checkDeviceLost(result)) - return error(GL_OUT_OF_MEMORY); - else - { - UNREACHABLE(); - return; - } - - } - - if (directToPixels) - { - systemSurface->Release(); - return; - } - - RECT rect; - rect.left = clamp(x, 0L, static_cast(desc.Width)); - rect.top = clamp(y, 0L, static_cast(desc.Height)); - rect.right = clamp(x + width, 0L, static_cast(desc.Width)); - rect.bottom = clamp(y + height, 0L, static_cast(desc.Height)); - - D3DLOCKED_RECT lock; - result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY); - - if (FAILED(result)) - { - UNREACHABLE(); - systemSurface->Release(); - - return; // No sensible error to generate - } - - unsigned char *dest = (unsigned char*)pixels; - unsigned short *dest16 = (unsigned short*)pixels; - - unsigned char *source; - int inputPitch; - if (getPackReverseRowOrder()) - { - source = ((unsigned char*)lock.pBits) + lock.Pitch * (rect.bottom - rect.top - 1); - inputPitch = -lock.Pitch; - } - else - { - source = (unsigned char*)lock.pBits; - inputPitch = lock.Pitch; - } - - unsigned int fastPixelSize = 0; - - if (desc.Format == D3DFMT_A8R8G8B8 && - format == GL_BGRA_EXT && - type == GL_UNSIGNED_BYTE) - { - fastPixelSize = 4; - } - else if ((desc.Format == D3DFMT_A4R4G4B4 && - format == GL_BGRA_EXT && - type == GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT) || - (desc.Format == D3DFMT_A1R5G5B5 && - format == GL_BGRA_EXT && - type == GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT)) - { - fastPixelSize = 2; - } - else if (desc.Format == D3DFMT_A16B16G16R16F && - format == GL_RGBA && - type == GL_HALF_FLOAT_OES) - { - fastPixelSize = 8; - } - else if (desc.Format == D3DFMT_A32B32G32R32F && - format == GL_RGBA && - type == GL_FLOAT) - { - fastPixelSize = 16; - } - - for (int j = 0; j < rect.bottom - rect.top; j++) - { - if (fastPixelSize != 0) - { - // Fast path for formats which require no translation: - // D3DFMT_A8R8G8B8 to BGRA/UNSIGNED_BYTE - // D3DFMT_A4R4G4B4 to BGRA/UNSIGNED_SHORT_4_4_4_4_REV_EXT - // D3DFMT_A1R5G5B5 to BGRA/UNSIGNED_SHORT_1_5_5_5_REV_EXT - // D3DFMT_A16B16G16R16F to RGBA/HALF_FLOAT_OES - // D3DFMT_A32B32G32R32F to RGBA/FLOAT - // - // Note that buffers with no alpha go through the slow path below. - memcpy(dest + j * outputPitch, - source + j * inputPitch, - (rect.right - rect.left) * fastPixelSize); - continue; - } - else if (desc.Format == D3DFMT_A8R8G8B8 && - format == GL_RGBA && - type == GL_UNSIGNED_BYTE) - { - // Fast path for swapping red with blue - for (int i = 0; i < rect.right - rect.left; i++) - { - unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch); - *(unsigned int*)(dest + 4 * i + j * outputPitch) = - (argb & 0xFF00FF00) | // Keep alpha and green - (argb & 0x00FF0000) >> 16 | // Move red to blue - (argb & 0x000000FF) << 16; // Move blue to red - } - continue; - } - - for (int i = 0; i < rect.right - rect.left; i++) - { - float r; - float g; - float b; - float a; - - switch (desc.Format) - { - case D3DFMT_R5G6B5: - { - unsigned short rgb = *(unsigned short*)(source + 2 * i + j * inputPitch); - - a = 1.0f; - b = (rgb & 0x001F) * (1.0f / 0x001F); - g = (rgb & 0x07E0) * (1.0f / 0x07E0); - r = (rgb & 0xF800) * (1.0f / 0xF800); - } - break; - case D3DFMT_A1R5G5B5: - { - unsigned short argb = *(unsigned short*)(source + 2 * i + j * inputPitch); - - a = (argb & 0x8000) ? 1.0f : 0.0f; - b = (argb & 0x001F) * (1.0f / 0x001F); - g = (argb & 0x03E0) * (1.0f / 0x03E0); - r = (argb & 0x7C00) * (1.0f / 0x7C00); - } - break; - case D3DFMT_A8R8G8B8: - { - unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch); - - a = (argb & 0xFF000000) * (1.0f / 0xFF000000); - b = (argb & 0x000000FF) * (1.0f / 0x000000FF); - g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00); - r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000); - } - break; - case D3DFMT_X8R8G8B8: - { - unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * inputPitch); - - a = 1.0f; - b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF); - g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00); - r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000); - } - break; - case D3DFMT_A2R10G10B10: - { - unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch); - - a = (argb & 0xC0000000) * (1.0f / 0xC0000000); - b = (argb & 0x000003FF) * (1.0f / 0x000003FF); - g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00); - r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000); - } - break; - case D3DFMT_A32B32G32R32F: - { - // float formats in D3D are stored rgba, rather than the other way round - r = *((float*)(source + 16 * i + j * inputPitch) + 0); - g = *((float*)(source + 16 * i + j * inputPitch) + 1); - b = *((float*)(source + 16 * i + j * inputPitch) + 2); - a = *((float*)(source + 16 * i + j * inputPitch) + 3); - } - break; - case D3DFMT_A16B16G16R16F: - { - // float formats in D3D are stored rgba, rather than the other way round - r = float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 0)); - g = float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 1)); - b = float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 2)); - a = float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 3)); - } - break; - default: - UNIMPLEMENTED(); // FIXME - UNREACHABLE(); - return; - } - - switch (format) - { - case GL_RGBA: - switch (type) - { - case GL_UNSIGNED_BYTE: - dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f); - dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f); - dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f); - dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f); - break; - default: UNREACHABLE(); - } - break; - case GL_BGRA_EXT: - switch (type) - { - case GL_UNSIGNED_BYTE: - dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * b + 0.5f); - dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f); - dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * r + 0.5f); - dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f); - break; - case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT: - // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section - // this type is packed as follows: - // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - // -------------------------------------------------------------------------------- - // | 4th | 3rd | 2nd | 1st component | - // -------------------------------------------------------------------------------- - // in the case of BGRA_EXT, B is the first component, G the second, and so forth. - dest16[i + j * outputPitch / sizeof(unsigned short)] = - ((unsigned short)(15 * a + 0.5f) << 12)| - ((unsigned short)(15 * r + 0.5f) << 8) | - ((unsigned short)(15 * g + 0.5f) << 4) | - ((unsigned short)(15 * b + 0.5f) << 0); - break; - case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT: - // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section - // this type is packed as follows: - // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - // -------------------------------------------------------------------------------- - // | 4th | 3rd | 2nd | 1st component | - // -------------------------------------------------------------------------------- - // in the case of BGRA_EXT, B is the first component, G the second, and so forth. - dest16[i + j * outputPitch / sizeof(unsigned short)] = - ((unsigned short)( a + 0.5f) << 15) | - ((unsigned short)(31 * r + 0.5f) << 10) | - ((unsigned short)(31 * g + 0.5f) << 5) | - ((unsigned short)(31 * b + 0.5f) << 0); - break; - default: UNREACHABLE(); - } - break; - case GL_RGB: - switch (type) - { - case GL_UNSIGNED_SHORT_5_6_5: - dest16[i + j * outputPitch / sizeof(unsigned short)] = - ((unsigned short)(31 * b + 0.5f) << 0) | - ((unsigned short)(63 * g + 0.5f) << 5) | - ((unsigned short)(31 * r + 0.5f) << 11); - break; - case GL_UNSIGNED_BYTE: - dest[3 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f); - dest[3 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f); - dest[3 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f); - break; - default: UNREACHABLE(); - } - break; - default: UNREACHABLE(); - } - } - } - - systemSurface->UnlockRect(); - - systemSurface->Release(); + mRenderer->readPixels(framebuffer, x, y, width, height, format, type, outputPitch, getPackReverseRowOrder(), getPackAlignment(), pixels); } void Context::clear(GLbitfield mask) @@ -2865,300 +1887,112 @@ void Context::clear(GLbitfield mask) if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE) { - return error(GL_INVALID_FRAMEBUFFER_OPERATION); + return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION); } DWORD flags = 0; + GLbitfield finalMask = 0; if (mask & GL_COLOR_BUFFER_BIT) { mask &= ~GL_COLOR_BUFFER_BIT; - if (framebufferObject->getColorbufferType() != GL_NONE) + if (framebufferObject->hasEnabledColorAttachment()) { - flags |= D3DCLEAR_TARGET; + finalMask |= GL_COLOR_BUFFER_BIT; } } if (mask & GL_DEPTH_BUFFER_BIT) { mask &= ~GL_DEPTH_BUFFER_BIT; - if (mState.depthMask && framebufferObject->getDepthbufferType() != GL_NONE) + if (mState.depthStencil.depthMask && framebufferObject->getDepthbufferType() != GL_NONE) { - flags |= D3DCLEAR_ZBUFFER; + finalMask |= GL_DEPTH_BUFFER_BIT; } } - GLuint stencilUnmasked = 0x0; - if (mask & GL_STENCIL_BUFFER_BIT) { mask &= ~GL_STENCIL_BUFFER_BIT; if (framebufferObject->getStencilbufferType() != GL_NONE) { - IDirect3DSurface9 *depthStencil = framebufferObject->getStencilbuffer()->getDepthStencil(); + rx::RenderTarget *depthStencil = framebufferObject->getStencilbuffer()->getDepthStencil(); if (!depthStencil) { ERR("Depth stencil pointer unexpectedly null."); return; } - - D3DSURFACE_DESC desc; - depthStencil->GetDesc(&desc); - depthStencil->Release(); - unsigned int stencilSize = dx2es::GetStencilSize(desc.Format); - stencilUnmasked = (0x1 << stencilSize) - 1; - - if (stencilUnmasked != 0x0) + if (GetStencilSize(depthStencil->getActualFormat()) > 0) { - flags |= D3DCLEAR_STENCIL; + finalMask |= GL_STENCIL_BUFFER_BIT; } } } if (mask != 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } - if (!applyRenderTarget(true)) // Clips the clear to the scissor rectangle but not the viewport + if (!applyRenderTarget(GL_TRIANGLES, true)) // Clips the clear to the scissor rectangle but not the viewport { return; } - D3DCOLOR color = D3DCOLOR_ARGB(unorm<8>(mState.colorClearValue.alpha), - unorm<8>(mState.colorClearValue.red), - unorm<8>(mState.colorClearValue.green), - unorm<8>(mState.colorClearValue.blue)); - float depth = clamp01(mState.depthClearValue); - int stencil = mState.stencilClearValue & 0x000000FF; + ClearParameters clearParams; + clearParams.mask = finalMask; + clearParams.colorClearValue = mState.colorClearValue; + clearParams.colorMaskRed = mState.blend.colorMaskRed; + clearParams.colorMaskGreen = mState.blend.colorMaskGreen; + clearParams.colorMaskBlue = mState.blend.colorMaskBlue; + clearParams.colorMaskAlpha = mState.blend.colorMaskAlpha; + clearParams.depthClearValue = mState.depthClearValue; + clearParams.stencilClearValue = mState.stencilClearValue; + clearParams.stencilWriteMask = mState.depthStencil.stencilWritemask; - bool alphaUnmasked = (dx2es::GetAlphaSize(mRenderTargetDesc.Format) == 0) || mState.colorMaskAlpha; - - const bool needMaskedStencilClear = (flags & D3DCLEAR_STENCIL) && - (mState.stencilWritemask & stencilUnmasked) != stencilUnmasked; - const bool needMaskedColorClear = (flags & D3DCLEAR_TARGET) && - !(mState.colorMaskRed && mState.colorMaskGreen && - mState.colorMaskBlue && alphaUnmasked); - - if (needMaskedColorClear || needMaskedStencilClear) - { - // State which is altered in all paths from this point to the clear call is saved. - // State which is altered in only some paths will be flagged dirty in the case that - // that path is taken. - HRESULT hr; - if (mMaskedClearSavedState == NULL) - { - hr = mDevice->BeginStateBlock(); - ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); - - mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); - mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS); - mDevice->SetRenderState(D3DRS_ZENABLE, FALSE); - mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); - mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); - mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); - mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); - mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); - mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0); - mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); - mDevice->SetPixelShader(NULL); - mDevice->SetVertexShader(NULL); - mDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE); - mDevice->SetStreamSource(0, NULL, 0, 0); - mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); - mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); - mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR); - mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); - mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR); - mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color); - mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF); - - for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - mDevice->SetStreamSourceFreq(i, 1); - } - - hr = mDevice->EndStateBlock(&mMaskedClearSavedState); - ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); - } - - ASSERT(mMaskedClearSavedState != NULL); - - if (mMaskedClearSavedState != NULL) - { - hr = mMaskedClearSavedState->Capture(); - ASSERT(SUCCEEDED(hr)); - } - - mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); - mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS); - mDevice->SetRenderState(D3DRS_ZENABLE, FALSE); - mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); - mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); - mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); - mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); - mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); - - if (flags & D3DCLEAR_TARGET) - { - mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, es2dx::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen, mState.colorMaskBlue, mState.colorMaskAlpha)); - } - else - { - mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0); - } - - if (stencilUnmasked != 0x0 && (flags & D3DCLEAR_STENCIL)) - { - mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE); - mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE); - mDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS); - mDevice->SetRenderState(D3DRS_STENCILREF, stencil); - mDevice->SetRenderState(D3DRS_STENCILWRITEMASK, mState.stencilWritemask); - mDevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE); - mDevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE); - mDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE); - mStencilStateDirty = true; - } - else - { - mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); - } - - mDevice->SetPixelShader(NULL); - mDevice->SetVertexShader(NULL); - mDevice->SetFVF(D3DFVF_XYZRHW); - mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); - mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); - mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR); - mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); - mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR); - mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color); - mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF); - - for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - mDevice->SetStreamSourceFreq(i, 1); - } - - float quad[4][4]; // A quadrilateral covering the target, aligned to match the edges - quad[0][0] = -0.5f; - quad[0][1] = mRenderTargetDesc.Height - 0.5f; - quad[0][2] = 0.0f; - quad[0][3] = 1.0f; - - quad[1][0] = mRenderTargetDesc.Width - 0.5f; - quad[1][1] = mRenderTargetDesc.Height - 0.5f; - quad[1][2] = 0.0f; - quad[1][3] = 1.0f; - - quad[2][0] = -0.5f; - quad[2][1] = -0.5f; - quad[2][2] = 0.0f; - quad[2][3] = 1.0f; - - quad[3][0] = mRenderTargetDesc.Width - 0.5f; - quad[3][1] = -0.5f; - quad[3][2] = 0.0f; - quad[3][3] = 1.0f; - - mDisplay->startScene(); - mDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float[4])); - - if (flags & D3DCLEAR_ZBUFFER) - { - mDevice->SetRenderState(D3DRS_ZENABLE, TRUE); - mDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE); - mDevice->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil); - } - - if (mMaskedClearSavedState != NULL) - { - mMaskedClearSavedState->Apply(); - } - } - else if (flags) - { - mDevice->Clear(0, NULL, flags, color, depth, stencil); - } + mRenderer->clear(clearParams, framebufferObject); } void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances) { if (!mState.currentProgram) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } - D3DPRIMITIVETYPE primitiveType; - int primitiveCount; - - if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount)) - return error(GL_INVALID_ENUM); - - if (primitiveCount <= 0) + if (!mRenderer->applyPrimitiveType(mode, count)) { return; } - if (!applyRenderTarget(false)) + if (!applyRenderTarget(mode, false)) { return; } applyState(mode); - GLsizei repeatDraw = 1; - GLenum err = applyVertexBuffer(first, count, instances, &repeatDraw); + ProgramBinary *programBinary = getCurrentProgramBinary(); + + GLenum err = mRenderer->applyVertexBuffer(programBinary, mState.vertexAttribute, first, count, instances); if (err != GL_NO_ERROR) { - return error(err); + return gl::error(err); } applyShaders(); applyTextures(); - if (!getCurrentProgramBinary()->validateSamplers(NULL)) + if (!programBinary->validateSamplers(NULL)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (!skipDraw(mode)) { - mDisplay->startScene(); - - if (mode == GL_LINE_LOOP) - { - drawLineLoop(count, GL_NONE, NULL, 0); - } - else if (instances > 0) - { - StaticIndexBuffer *countingIB = mIndexDataManager->getCountingIndices(count); - if (countingIB) - { - if (mAppliedIBSerial != countingIB->getSerial()) - { - mDevice->SetIndices(countingIB->getBuffer()); - mAppliedIBSerial = countingIB->getSerial(); - } - - for (int i = 0; i < repeatDraw; i++) - { - mDevice->DrawIndexedPrimitive(primitiveType, 0, 0, count, 0, primitiveCount); - } - } - else - { - ERR("Could not create a counting index buffer for glDrawArraysInstanced."); - return error(GL_OUT_OF_MEMORY); - } - } - else // Regular case - { - mDevice->DrawPrimitive(primitiveType, 0, primitiveCount); - } + mRenderer->drawArrays(mode, count, instances); } } @@ -3166,222 +2000,60 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid { if (!mState.currentProgram) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (!indices && !mState.elementArrayBuffer) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } - - D3DPRIMITIVETYPE primitiveType; - int primitiveCount; - - if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount)) - return error(GL_INVALID_ENUM); - - if (primitiveCount <= 0) + + if (!mRenderer->applyPrimitiveType(mode, count)) { return; } - if (!applyRenderTarget(false)) + if (!applyRenderTarget(mode, false)) { return; } applyState(mode); - TranslatedIndexData indexInfo; - GLenum err = applyIndexBuffer(indices, count, mode, type, &indexInfo); + rx::TranslatedIndexData indexInfo; + GLenum err = mRenderer->applyIndexBuffer(indices, mState.elementArrayBuffer.get(), count, mode, type, &indexInfo); if (err != GL_NO_ERROR) { - return error(err); + return gl::error(err); } + ProgramBinary *programBinary = getCurrentProgramBinary(); + GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1; - GLsizei repeatDraw = 1; - err = applyVertexBuffer(indexInfo.minIndex, vertexCount, instances, &repeatDraw); + err = mRenderer->applyVertexBuffer(programBinary, mState.vertexAttribute, indexInfo.minIndex, vertexCount, instances); if (err != GL_NO_ERROR) { - return error(err); + return gl::error(err); } applyShaders(); applyTextures(); - if (!getCurrentProgramBinary()->validateSamplers(NULL)) + if (!programBinary->validateSamplers(NULL)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (!skipDraw(mode)) { - mDisplay->startScene(); - - if (mode == GL_LINE_LOOP) - { - drawLineLoop(count, type, indices, indexInfo.minIndex); - } - else - { - for (int i = 0; i < repeatDraw; i++) - { - mDevice->DrawIndexedPrimitive(primitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, vertexCount, indexInfo.startIndex, primitiveCount); - } - } + mRenderer->drawElements(mode, count, type, indices, mState.elementArrayBuffer.get(), indexInfo, instances); } } // Implements glFlush when block is false, glFinish when block is true void Context::sync(bool block) { - mDisplay->sync(block); -} - -void Context::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex) -{ - // Get the raw indices for an indexed draw - if (type != GL_NONE && mState.elementArrayBuffer.get()) - { - Buffer *indexBuffer = mState.elementArrayBuffer.get(); - intptr_t offset = reinterpret_cast(indices); - indices = static_cast(indexBuffer->data()) + offset; - } - - UINT startIndex = 0; - bool succeeded = false; - - if (supports32bitIndices()) - { - const int spaceNeeded = (count + 1) * sizeof(unsigned int); - - if (!mLineLoopIB) - { - mLineLoopIB = new StreamingIndexBuffer(mDevice, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX32); - } - - if (mLineLoopIB) - { - mLineLoopIB->reserveSpace(spaceNeeded, GL_UNSIGNED_INT); - - UINT offset = 0; - unsigned int *data = static_cast(mLineLoopIB->map(spaceNeeded, &offset)); - startIndex = offset / 4; - - if (data) - { - switch (type) - { - case GL_NONE: // Non-indexed draw - for (int i = 0; i < count; i++) - { - data[i] = i; - } - data[count] = 0; - break; - case GL_UNSIGNED_BYTE: - for (int i = 0; i < count; i++) - { - data[i] = static_cast(indices)[i]; - } - data[count] = static_cast(indices)[0]; - break; - case GL_UNSIGNED_SHORT: - for (int i = 0; i < count; i++) - { - data[i] = static_cast(indices)[i]; - } - data[count] = static_cast(indices)[0]; - break; - case GL_UNSIGNED_INT: - for (int i = 0; i < count; i++) - { - data[i] = static_cast(indices)[i]; - } - data[count] = static_cast(indices)[0]; - break; - default: UNREACHABLE(); - } - - mLineLoopIB->unmap(); - succeeded = true; - } - } - } - else - { - const int spaceNeeded = (count + 1) * sizeof(unsigned short); - - if (!mLineLoopIB) - { - mLineLoopIB = new StreamingIndexBuffer(mDevice, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX16); - } - - if (mLineLoopIB) - { - mLineLoopIB->reserveSpace(spaceNeeded, GL_UNSIGNED_SHORT); - - UINT offset = 0; - unsigned short *data = static_cast(mLineLoopIB->map(spaceNeeded, &offset)); - startIndex = offset / 2; - - if (data) - { - switch (type) - { - case GL_NONE: // Non-indexed draw - for (int i = 0; i < count; i++) - { - data[i] = i; - } - data[count] = 0; - break; - case GL_UNSIGNED_BYTE: - for (int i = 0; i < count; i++) - { - data[i] = static_cast(indices)[i]; - } - data[count] = static_cast(indices)[0]; - break; - case GL_UNSIGNED_SHORT: - for (int i = 0; i < count; i++) - { - data[i] = static_cast(indices)[i]; - } - data[count] = static_cast(indices)[0]; - break; - case GL_UNSIGNED_INT: - for (int i = 0; i < count; i++) - { - data[i] = static_cast(indices)[i]; - } - data[count] = static_cast(indices)[0]; - break; - default: UNREACHABLE(); - } - - mLineLoopIB->unmap(); - succeeded = true; - } - } - } - - if (succeeded) - { - if (mAppliedIBSerial != mLineLoopIB->getSerial()) - { - mDevice->SetIndices(mLineLoopIB->getBuffer()); - mAppliedIBSerial = mLineLoopIB->getSerial(); - } - - mDevice->DrawIndexedPrimitive(D3DPT_LINESTRIP, -minIndex, minIndex, count, startIndex, count); - } - else - { - ERR("Could not create a looping index buffer for GL_LINE_LOOP."); - return error(GL_OUT_OF_MEMORY); - } + mRenderer->sync(block); } void Context::recordInvalidEnum() @@ -3453,21 +2125,20 @@ GLenum Context::getError() GLenum Context::getResetStatus() { - if (mResetStatus == GL_NO_ERROR) + if (mResetStatus == GL_NO_ERROR && !mContextLost) { - bool lost = mDisplay->testDeviceLost(); - - if (lost) - { - mDisplay->notifyDeviceLost(); // Sets mResetStatus - } + // mResetStatus will be set by the markContextLost callback + // in the case a notification is sent + mRenderer->testDeviceLost(true); } GLenum status = mResetStatus; if (mResetStatus != GL_NO_ERROR) { - if (mDisplay->testDeviceResettable()) + ASSERT(mContextLost); + + if (mRenderer->testDeviceResettable()) { mResetStatus = GL_NO_ERROR; } @@ -3481,63 +2152,29 @@ bool Context::isResetNotificationEnabled() return (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT); } -bool Context::supportsShaderModel3() const +int Context::getMajorShaderModel() const { - return mSupportsShaderModel3; + return mMajorShaderModel; } float Context::getMaximumPointSize() const { - return mSupportsShaderModel3 ? mMaximumPointSize : ALIASED_POINT_SIZE_RANGE_MAX_SM2; -} - -int Context::getMaximumVaryingVectors() const -{ - return mSupportsShaderModel3 ? MAX_VARYING_VECTORS_SM3 : MAX_VARYING_VECTORS_SM2; -} - -unsigned int Context::getMaximumVertexTextureImageUnits() const -{ - return mSupportsVertexTexture ? MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF : 0; + return mMaximumPointSize; } unsigned int Context::getMaximumCombinedTextureImageUnits() const { - return MAX_TEXTURE_IMAGE_UNITS + getMaximumVertexTextureImageUnits(); -} - -int Context::getMaximumFragmentUniformVectors() const -{ - return mSupportsShaderModel3 ? MAX_FRAGMENT_UNIFORM_VECTORS_SM3 : MAX_FRAGMENT_UNIFORM_VECTORS_SM2; + return mRenderer->getMaxCombinedTextureImageUnits(); } int Context::getMaxSupportedSamples() const { - return mMaxSupportedSamples; + return mRenderer->getMaxSupportedSamples(); } -int Context::getNearestSupportedSamples(D3DFORMAT format, int requested) const +unsigned int Context::getMaximumRenderTargets() const { - if (requested == 0) - { - return requested; - } - - std::map::const_iterator itr = mMultiSampleSupport.find(format); - if (itr == mMultiSampleSupport.end()) - { - return -1; - } - - for (int i = requested; i <= D3DMULTISAMPLE_16_SAMPLES; ++i) - { - if (itr->second[i] && i != D3DMULTISAMPLE_NONMASKABLE) - { - return i; - } - } - - return -1; + return mRenderer->getMaxRenderTargets(); } bool Context::supportsEventQueries() const @@ -3550,6 +2187,11 @@ bool Context::supportsOcclusionQueries() const return mSupportsOcclusionQueries; } +bool Context::supportsBGRATextures() const +{ + return mSupportsBGRATextures; +} + bool Context::supportsDXT1Textures() const { return mSupportsDXT1Textures; @@ -3650,11 +2292,6 @@ bool Context::supportsTextureFilterAnisotropy() const return mSupportsTextureFilterAnisotropy; } -bool Context::supportsDerivativeInstructions() const -{ - return mSupportsDerivativeInstructions; -} - float Context::getTextureMaxAnisotropy() const { return mMaxTextureAnisotropy; @@ -3665,20 +2302,17 @@ bool Context::getCurrentReadFormatType(GLenum *format, GLenum *type) Framebuffer *framebuffer = getReadFramebuffer(); if (!framebuffer || framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) { - return error(GL_INVALID_OPERATION, false); + return gl::error(GL_INVALID_OPERATION, false); } - Renderbuffer *renderbuffer = framebuffer->getColorbuffer(); + Renderbuffer *renderbuffer = framebuffer->getReadColorbuffer(); if (!renderbuffer) { - return error(GL_INVALID_OPERATION, false); + return gl::error(GL_INVALID_OPERATION, false); } - if(!dx2es::ConvertReadBufferFormat(renderbuffer->getD3DFormat(), format, type)) - { - ASSERT(false); - return false; - } + *format = gl::ExtractFormat(renderbuffer->getActualFormat()); + *type = gl::ExtractType(renderbuffer->getActualFormat()); return true; } @@ -3716,7 +2350,7 @@ void Context::detachTexture(GLuint texture) for (int type = 0; type < TEXTURE_TYPE_COUNT; type++) { - for (int sampler = 0; sampler < MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF; sampler++) + for (int sampler = 0; sampler < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS; sampler++) { if (mState.samplerTexture[type][sampler].id() == texture) { @@ -3807,7 +2441,7 @@ Texture *Context::getIncompleteTexture(TextureType type) case TEXTURE_2D: { - Texture2D *incomplete2d = new Texture2D(Texture::INCOMPLETE_TEXTURE_ID); + Texture2D *incomplete2d = new Texture2D(mRenderer, Texture::INCOMPLETE_TEXTURE_ID); incomplete2d->setImage(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color); t = incomplete2d; } @@ -3815,7 +2449,7 @@ Texture *Context::getIncompleteTexture(TextureType type) case TEXTURE_CUBE: { - TextureCubeMap *incompleteCube = new TextureCubeMap(Texture::INCOMPLETE_TEXTURE_ID); + TextureCubeMap *incompleteCube = new TextureCubeMap(mRenderer, Texture::INCOMPLETE_TEXTURE_ID); incompleteCube->setImagePosX(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color); incompleteCube->setImageNegX(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color); @@ -3851,9 +2485,9 @@ bool Context::skipDraw(GLenum drawMode) return true; } } - else if (isTriangleMode(drawMode)) + else if (IsTriangleMode(drawMode)) { - if (mState.cullFace && mState.cullMode == GL_FRONT_AND_BACK) + if (mState.rasterizer.cullFace && mState.rasterizer.cullMode == GL_FRONT_AND_BACK) { return true; } @@ -3862,25 +2496,6 @@ bool Context::skipDraw(GLenum drawMode) return false; } -bool Context::isTriangleMode(GLenum drawMode) -{ - switch (drawMode) - { - case GL_TRIANGLES: - case GL_TRIANGLE_FAN: - case GL_TRIANGLE_STRIP: - return true; - case GL_POINTS: - case GL_LINES: - case GL_LINE_LOOP: - case GL_LINE_STRIP: - return false; - default: UNREACHABLE(); - } - - return false; -} - void Context::setVertexAttrib(GLuint index, const GLfloat *values) { ASSERT(index < gl::MAX_VERTEX_ATTRIBS); @@ -3889,8 +2504,6 @@ void Context::setVertexAttrib(GLuint index, const GLfloat *values) mState.vertexAttribute[index].mCurrentValue[1] = values[1]; mState.vertexAttribute[index].mCurrentValue[2] = values[2]; mState.vertexAttribute[index].mCurrentValue[3] = values[3]; - - mVertexDataManager->dirtyCurrentValue(index); } void Context::setVertexAttribDivisor(GLuint index, GLuint divisor) @@ -3917,7 +2530,7 @@ void Context::initExtensionString() extensionString += "GL_OES_packed_depth_stencil "; extensionString += "GL_OES_get_program_binary "; extensionString += "GL_OES_rgb8_rgba8 "; - if (supportsDerivativeInstructions()) + if (mRenderer->getDerivativeInstructionSupport()) { extensionString += "GL_OES_standard_derivatives "; } @@ -3963,8 +2576,18 @@ void Context::initExtensionString() extensionString += "GL_EXT_texture_filter_anisotropic "; } - extensionString += "GL_EXT_texture_format_BGRA8888 "; + if (supportsBGRATextures()) + { + extensionString += "GL_EXT_texture_format_BGRA8888 "; + } + + if (mRenderer->getMaxRenderTargets() > 1) + { + extensionString += "GL_EXT_draw_buffers "; + } + extensionString += "GL_EXT_texture_storage "; + extensionString += "GL_EXT_frag_depth "; // ANGLE-specific extensions if (supportsDepthTextures()) @@ -4019,24 +2642,10 @@ const char *Context::getExtensionString() const void Context::initRendererString() { - D3DADAPTER_IDENTIFIER9 *identifier = mDisplay->getAdapterIdentifier(); - std::ostringstream rendererString; rendererString << "ANGLE ("; - - rendererString << identifier->Description; - - if (mDisplay->isD3d9ExDevice()) - { - rendererString << " Direct3D9Ex"; - } - else - { - rendererString << " Direct3D9"; - } - - rendererString << " vs_" << D3DSHADER_VERSION_MAJOR(mDeviceCaps.VertexShaderVersion) << "_" << D3DSHADER_VERSION_MINOR(mDeviceCaps.VertexShaderVersion); - rendererString << " ps_" << D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion) << "_" << D3DSHADER_VERSION_MINOR(mDeviceCaps.PixelShaderVersion) << ")"; + rendererString << mRenderer->getRendererDescription(); + rendererString << ")"; mRendererString = makeStaticString(rendererString.str()); } @@ -4056,179 +2665,216 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1 if (!readFramebuffer || readFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE || !drawFramebuffer || drawFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) { - return error(GL_INVALID_FRAMEBUFFER_OPERATION); + return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION); } if (drawFramebuffer->getSamples() != 0) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } - int readBufferWidth = readFramebuffer->getColorbuffer()->getWidth(); - int readBufferHeight = readFramebuffer->getColorbuffer()->getHeight(); - int drawBufferWidth = drawFramebuffer->getColorbuffer()->getWidth(); - int drawBufferHeight = drawFramebuffer->getColorbuffer()->getHeight(); + Renderbuffer *readColorBuffer = readFramebuffer->getReadColorbuffer(); + Renderbuffer *drawColorBuffer = drawFramebuffer->getFirstColorbuffer(); - RECT sourceRect; - RECT destRect; + if (drawColorBuffer == NULL) + { + ERR("Draw buffers formats don't match, which is not supported in this implementation of BlitFramebufferANGLE"); + return gl::error(GL_INVALID_OPERATION); + } + + int readBufferWidth = readColorBuffer->getWidth(); + int readBufferHeight = readColorBuffer->getHeight(); + int drawBufferWidth = drawColorBuffer->getWidth(); + int drawBufferHeight = drawColorBuffer->getHeight(); + + Rectangle sourceRect; + Rectangle destRect; if (srcX0 < srcX1) { - sourceRect.left = srcX0; - sourceRect.right = srcX1; - destRect.left = dstX0; - destRect.right = dstX1; + sourceRect.x = srcX0; + destRect.x = dstX0; + sourceRect.width = srcX1 - srcX0; + destRect.width = dstX1 - dstX0; } else { - sourceRect.left = srcX1; - destRect.left = dstX1; - sourceRect.right = srcX0; - destRect.right = dstX0; + sourceRect.x = srcX1; + destRect.x = dstX1; + sourceRect.width = srcX0 - srcX1; + destRect.width = dstX0 - dstX1; } if (srcY0 < srcY1) { - sourceRect.bottom = srcY1; - destRect.bottom = dstY1; - sourceRect.top = srcY0; - destRect.top = dstY0; + sourceRect.height = srcY1 - srcY0; + destRect.height = dstY1 - dstY0; + sourceRect.y = srcY0; + destRect.y = dstY0; } else { - sourceRect.bottom = srcY0; - destRect.bottom = dstY0; - sourceRect.top = srcY1; - destRect.top = dstY1; + sourceRect.height = srcY0 - srcY1; + destRect.height = dstY0 - srcY1; + sourceRect.y = srcY1; + destRect.y = dstY1; } - RECT sourceScissoredRect = sourceRect; - RECT destScissoredRect = destRect; + Rectangle sourceScissoredRect = sourceRect; + Rectangle destScissoredRect = destRect; if (mState.scissorTest) { - // Only write to parts of the destination framebuffer which pass the scissor test - // Please note: the destRect is now in D3D-style coordinates, so the *top* of the - // rect will be checked against scissorY, rather than the bottom. - if (destRect.left < mState.scissorX) + // Only write to parts of the destination framebuffer which pass the scissor test. + if (destRect.x < mState.scissor.x) { - int xDiff = mState.scissorX - destRect.left; - destScissoredRect.left = mState.scissorX; - sourceScissoredRect.left += xDiff; + int xDiff = mState.scissor.x - destRect.x; + destScissoredRect.x = mState.scissor.x; + destScissoredRect.width -= xDiff; + sourceScissoredRect.x += xDiff; + sourceScissoredRect.width -= xDiff; + } - if (destRect.right > mState.scissorX + mState.scissorWidth) + if (destRect.x + destRect.width > mState.scissor.x + mState.scissor.width) { - int xDiff = destRect.right - (mState.scissorX + mState.scissorWidth); - destScissoredRect.right = mState.scissorX + mState.scissorWidth; - sourceScissoredRect.right -= xDiff; + int xDiff = (destRect.x + destRect.width) - (mState.scissor.x + mState.scissor.width); + destScissoredRect.width -= xDiff; + sourceScissoredRect.width -= xDiff; } - if (destRect.top < mState.scissorY) + if (destRect.y < mState.scissor.y) { - int yDiff = mState.scissorY - destRect.top; - destScissoredRect.top = mState.scissorY; - sourceScissoredRect.top += yDiff; + int yDiff = mState.scissor.y - destRect.y; + destScissoredRect.y = mState.scissor.y; + destScissoredRect.height -= yDiff; + sourceScissoredRect.y += yDiff; + sourceScissoredRect.height -= yDiff; } - if (destRect.bottom > mState.scissorY + mState.scissorHeight) + if (destRect.y + destRect.height > mState.scissor.y + mState.scissor.height) { - int yDiff = destRect.bottom - (mState.scissorY + mState.scissorHeight); - destScissoredRect.bottom = mState.scissorY + mState.scissorHeight; - sourceScissoredRect.bottom -= yDiff; + int yDiff = (destRect.y + destRect.height) - (mState.scissor.y + mState.scissor.height); + destScissoredRect.height -= yDiff; + sourceScissoredRect.height -= yDiff; } } bool blitRenderTarget = false; bool blitDepthStencil = false; - RECT sourceTrimmedRect = sourceScissoredRect; - RECT destTrimmedRect = destScissoredRect; + Rectangle sourceTrimmedRect = sourceScissoredRect; + Rectangle destTrimmedRect = destScissoredRect; // The source & destination rectangles also may need to be trimmed if they fall out of the bounds of // the actual draw and read surfaces. - if (sourceTrimmedRect.left < 0) + if (sourceTrimmedRect.x < 0) { - int xDiff = 0 - sourceTrimmedRect.left; - sourceTrimmedRect.left = 0; - destTrimmedRect.left += xDiff; + int xDiff = 0 - sourceTrimmedRect.x; + sourceTrimmedRect.x = 0; + sourceTrimmedRect.width -= xDiff; + destTrimmedRect.x += xDiff; + destTrimmedRect.width -= xDiff; } - if (sourceTrimmedRect.right > readBufferWidth) + if (sourceTrimmedRect.x + sourceTrimmedRect.width > readBufferWidth) { - int xDiff = sourceTrimmedRect.right - readBufferWidth; - sourceTrimmedRect.right = readBufferWidth; - destTrimmedRect.right -= xDiff; + int xDiff = (sourceTrimmedRect.x + sourceTrimmedRect.width) - readBufferWidth; + sourceTrimmedRect.width -= xDiff; + destTrimmedRect.width -= xDiff; } - if (sourceTrimmedRect.top < 0) + if (sourceTrimmedRect.y < 0) { - int yDiff = 0 - sourceTrimmedRect.top; - sourceTrimmedRect.top = 0; - destTrimmedRect.top += yDiff; + int yDiff = 0 - sourceTrimmedRect.y; + sourceTrimmedRect.y = 0; + sourceTrimmedRect.height -= yDiff; + destTrimmedRect.y += yDiff; + destTrimmedRect.height -= yDiff; } - if (sourceTrimmedRect.bottom > readBufferHeight) + if (sourceTrimmedRect.y + sourceTrimmedRect.height > readBufferHeight) { - int yDiff = sourceTrimmedRect.bottom - readBufferHeight; - sourceTrimmedRect.bottom = readBufferHeight; - destTrimmedRect.bottom -= yDiff; + int yDiff = (sourceTrimmedRect.y + sourceTrimmedRect.height) - readBufferHeight; + sourceTrimmedRect.height -= yDiff; + destTrimmedRect.height -= yDiff; } - if (destTrimmedRect.left < 0) + if (destTrimmedRect.x < 0) { - int xDiff = 0 - destTrimmedRect.left; - destTrimmedRect.left = 0; - sourceTrimmedRect.left += xDiff; + int xDiff = 0 - destTrimmedRect.x; + destTrimmedRect.x = 0; + destTrimmedRect.width -= xDiff; + sourceTrimmedRect.x += xDiff; + sourceTrimmedRect.width -= xDiff; } - if (destTrimmedRect.right > drawBufferWidth) + if (destTrimmedRect.x + destTrimmedRect.width > drawBufferWidth) { - int xDiff = destTrimmedRect.right - drawBufferWidth; - destTrimmedRect.right = drawBufferWidth; - sourceTrimmedRect.right -= xDiff; + int xDiff = (destTrimmedRect.x + destTrimmedRect.width) - drawBufferWidth; + destTrimmedRect.width -= xDiff; + sourceTrimmedRect.width -= xDiff; } - if (destTrimmedRect.top < 0) + if (destTrimmedRect.y < 0) { - int yDiff = 0 - destTrimmedRect.top; - destTrimmedRect.top = 0; - sourceTrimmedRect.top += yDiff; + int yDiff = 0 - destTrimmedRect.y; + destTrimmedRect.y = 0; + destTrimmedRect.height -= yDiff; + sourceTrimmedRect.y += yDiff; + sourceTrimmedRect.height -= yDiff; } - if (destTrimmedRect.bottom > drawBufferHeight) + if (destTrimmedRect.y + destTrimmedRect.height > drawBufferHeight) { - int yDiff = destTrimmedRect.bottom - drawBufferHeight; - destTrimmedRect.bottom = drawBufferHeight; - sourceTrimmedRect.bottom -= yDiff; + int yDiff = (destTrimmedRect.y + destTrimmedRect.height) - drawBufferHeight; + destTrimmedRect.height -= yDiff; + sourceTrimmedRect.height -= yDiff; } bool partialBufferCopy = false; - if (sourceTrimmedRect.bottom - sourceTrimmedRect.top < readBufferHeight || - sourceTrimmedRect.right - sourceTrimmedRect.left < readBufferWidth || - destTrimmedRect.bottom - destTrimmedRect.top < drawBufferHeight || - destTrimmedRect.right - destTrimmedRect.left < drawBufferWidth || - sourceTrimmedRect.top != 0 || destTrimmedRect.top != 0 || sourceTrimmedRect.left != 0 || destTrimmedRect.left != 0) + if (sourceTrimmedRect.height < readBufferHeight || + sourceTrimmedRect.width < readBufferWidth || + destTrimmedRect.height < drawBufferHeight || + destTrimmedRect.width < drawBufferWidth || + sourceTrimmedRect.y != 0 || destTrimmedRect.y != 0 || sourceTrimmedRect.x != 0 || destTrimmedRect.x != 0) { partialBufferCopy = true; } if (mask & GL_COLOR_BUFFER_BIT) { - const bool validReadType = readFramebuffer->getColorbufferType() == GL_TEXTURE_2D || - readFramebuffer->getColorbufferType() == GL_RENDERBUFFER; - const bool validDrawType = drawFramebuffer->getColorbufferType() == GL_TEXTURE_2D || - drawFramebuffer->getColorbufferType() == GL_RENDERBUFFER; - if (!validReadType || !validDrawType || - readFramebuffer->getColorbuffer()->getD3DFormat() != drawFramebuffer->getColorbuffer()->getD3DFormat()) + const GLenum readColorbufferType = readFramebuffer->getReadColorbufferType(); + const bool validReadType = (readColorbufferType == GL_TEXTURE_2D) || (readColorbufferType == GL_RENDERBUFFER); + bool validDrawType = true; + bool validDrawFormat = true; + + for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) + { + if (drawFramebuffer->isEnabledColorAttachment(colorAttachment)) + { + if (drawFramebuffer->getColorbufferType(colorAttachment) != GL_TEXTURE_2D && + drawFramebuffer->getColorbufferType(colorAttachment) != GL_RENDERBUFFER) + { + validDrawType = false; + } + + if (drawFramebuffer->getColorbuffer(colorAttachment)->getActualFormat() != readColorBuffer->getActualFormat()) + { + validDrawFormat = false; + } + } + } + + if (!validReadType || !validDrawType || !validDrawFormat) { ERR("Color buffer format conversion in BlitFramebufferANGLE not supported by this implementation"); - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (partialBufferCopy && readFramebuffer->getSamples() != 0) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } blitRenderTarget = true; @@ -4248,9 +2894,9 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1 if (readFramebuffer->getDepthbuffer() && drawFramebuffer->getDepthbuffer()) { if (readFramebuffer->getDepthbufferType() != drawFramebuffer->getDepthbufferType() || - readFramebuffer->getDepthbuffer()->getD3DFormat() != drawFramebuffer->getDepthbuffer()->getD3DFormat()) + readFramebuffer->getDepthbuffer()->getActualFormat() != drawFramebuffer->getDepthbuffer()->getActualFormat()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } blitDepthStencil = true; @@ -4264,9 +2910,9 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1 if (readFramebuffer->getStencilbuffer() && drawFramebuffer->getStencilbuffer()) { if (readFramebuffer->getStencilbufferType() != drawFramebuffer->getStencilbufferType() || - readFramebuffer->getStencilbuffer()->getD3DFormat() != drawFramebuffer->getStencilbuffer()->getD3DFormat()) + readFramebuffer->getStencilbuffer()->getActualFormat() != drawFramebuffer->getStencilbuffer()->getActualFormat()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } blitDepthStencil = true; @@ -4278,255 +2924,29 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1 if (partialBufferCopy) { ERR("Only whole-buffer depth and stencil blits are supported by this implementation."); - return error(GL_INVALID_OPERATION); // only whole-buffer copies are permitted + return gl::error(GL_INVALID_OPERATION); // only whole-buffer copies are permitted } if ((drawDSBuffer && drawDSBuffer->getSamples() != 0) || (readDSBuffer && readDSBuffer->getSamples() != 0)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } if (blitRenderTarget || blitDepthStencil) { - mDisplay->endScene(); - - if (blitRenderTarget) - { - IDirect3DSurface9* readRenderTarget = readFramebuffer->getRenderTarget(); - IDirect3DSurface9* drawRenderTarget = drawFramebuffer->getRenderTarget(); - - HRESULT result = mDevice->StretchRect(readRenderTarget, &sourceTrimmedRect, - drawRenderTarget, &destTrimmedRect, D3DTEXF_NONE); - - readRenderTarget->Release(); - drawRenderTarget->Release(); - - if (FAILED(result)) - { - ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result); - return; - } - } - - if (blitDepthStencil) - { - IDirect3DSurface9* readDepthStencil = readFramebuffer->getDepthStencil(); - IDirect3DSurface9* drawDepthStencil = drawFramebuffer->getDepthStencil(); - - HRESULT result = mDevice->StretchRect(readDepthStencil, NULL, drawDepthStencil, NULL, D3DTEXF_NONE); - - readDepthStencil->Release(); - drawDepthStencil->Release(); - - if (FAILED(result)) - { - ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result); - return; - } - } + mRenderer->blitRect(readFramebuffer, sourceTrimmedRect, drawFramebuffer, destTrimmedRect, blitRenderTarget, blitDepthStencil); } } -VertexDeclarationCache::VertexDeclarationCache() : mMaxLru(0) -{ - for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++) - { - mVertexDeclCache[i].vertexDeclaration = NULL; - mVertexDeclCache[i].lruCount = 0; - } -} - -VertexDeclarationCache::~VertexDeclarationCache() -{ - for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++) - { - if (mVertexDeclCache[i].vertexDeclaration) - { - mVertexDeclCache[i].vertexDeclaration->Release(); - } - } -} - -GLenum VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], ProgramBinary *programBinary, GLsizei instances, GLsizei *repeatDraw) -{ - *repeatDraw = 1; - - int indexedAttribute = MAX_VERTEX_ATTRIBS; - int instancedAttribute = MAX_VERTEX_ATTRIBS; - - if (instances > 0) - { - // Find an indexed attribute to be mapped to D3D stream 0 - for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - if (attributes[i].active) - { - if (indexedAttribute == MAX_VERTEX_ATTRIBS) - { - if (attributes[i].divisor == 0) - { - indexedAttribute = i; - } - } - else if (instancedAttribute == MAX_VERTEX_ATTRIBS) - { - if (attributes[i].divisor != 0) - { - instancedAttribute = i; - } - } - else break; // Found both an indexed and instanced attribute - } - } - - if (indexedAttribute == MAX_VERTEX_ATTRIBS) - { - return GL_INVALID_OPERATION; - } - } - - D3DVERTEXELEMENT9 elements[MAX_VERTEX_ATTRIBS + 1]; - D3DVERTEXELEMENT9 *element = &elements[0]; - - for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - if (attributes[i].active) - { - int stream = i; - - if (instances > 0) - { - // Due to a bug on ATI cards we can't enable instancing when none of the attributes are instanced. - if (instancedAttribute == MAX_VERTEX_ATTRIBS) - { - *repeatDraw = instances; - } - else - { - if (i == indexedAttribute) - { - stream = 0; - } - else if (i == 0) - { - stream = indexedAttribute; - } - - UINT frequency = 1; - - if (attributes[i].divisor == 0) - { - frequency = D3DSTREAMSOURCE_INDEXEDDATA | instances; - } - else - { - frequency = D3DSTREAMSOURCE_INSTANCEDATA | attributes[i].divisor; - } - - device->SetStreamSourceFreq(stream, frequency); - mInstancingEnabled = true; - } - } - - if (mAppliedVBs[stream].serial != attributes[i].serial || - mAppliedVBs[stream].stride != attributes[i].stride || - mAppliedVBs[stream].offset != attributes[i].offset) - { - device->SetStreamSource(stream, attributes[i].vertexBuffer, attributes[i].offset, attributes[i].stride); - mAppliedVBs[stream].serial = attributes[i].serial; - mAppliedVBs[stream].stride = attributes[i].stride; - mAppliedVBs[stream].offset = attributes[i].offset; - } - - element->Stream = stream; - element->Offset = 0; - element->Type = attributes[i].type; - element->Method = D3DDECLMETHOD_DEFAULT; - element->Usage = D3DDECLUSAGE_TEXCOORD; - element->UsageIndex = programBinary->getSemanticIndex(i); - element++; - } - } - - if (instances == 0 || instancedAttribute == MAX_VERTEX_ATTRIBS) - { - if (mInstancingEnabled) - { - for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - device->SetStreamSourceFreq(i, 1); - } - - mInstancingEnabled = false; - } - } - - static const D3DVERTEXELEMENT9 end = D3DDECL_END(); - *(element++) = end; - - for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++) - { - VertexDeclCacheEntry *entry = &mVertexDeclCache[i]; - if (memcmp(entry->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9)) == 0 && entry->vertexDeclaration) - { - entry->lruCount = ++mMaxLru; - if(entry->vertexDeclaration != mLastSetVDecl) - { - device->SetVertexDeclaration(entry->vertexDeclaration); - mLastSetVDecl = entry->vertexDeclaration; - } - - return GL_NO_ERROR; - } - } - - VertexDeclCacheEntry *lastCache = mVertexDeclCache; - - for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++) - { - if (mVertexDeclCache[i].lruCount < lastCache->lruCount) - { - lastCache = &mVertexDeclCache[i]; - } - } - - if (lastCache->vertexDeclaration != NULL) - { - lastCache->vertexDeclaration->Release(); - lastCache->vertexDeclaration = NULL; - // mLastSetVDecl is set to the replacement, so we don't have to worry - // about it. - } - - memcpy(lastCache->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9)); - device->CreateVertexDeclaration(elements, &lastCache->vertexDeclaration); - device->SetVertexDeclaration(lastCache->vertexDeclaration); - mLastSetVDecl = lastCache->vertexDeclaration; - lastCache->lruCount = ++mMaxLru; - - return GL_NO_ERROR; -} - -void VertexDeclarationCache::markStateDirty() -{ - for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - mAppliedVBs[i].serial = 0; - } - - mLastSetVDecl = NULL; - mInstancingEnabled = true; // Forces it to be disabled when not used -} - } extern "C" { -gl::Context *glCreateContext(const egl::Config *config, const gl::Context *shareContext, bool notifyResets, bool robustAccess) +gl::Context *glCreateContext(const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess) { - return new gl::Context(config, shareContext, notifyResets, robustAccess); + return new gl::Context(shareContext, renderer, notifyResets, robustAccess); } void glDestroyContext(gl::Context *context) @@ -4548,4 +2968,5 @@ gl::Context *glGetCurrentContext() { return gl::getContext(); } + } diff --git a/gfx/angle/src/libGLESv2/Context.h b/gfx/angle/src/libGLESv2/Context.h index 8c45bf30a637..9c222be24d7f 100644 --- a/gfx/angle/src/libGLESv2/Context.h +++ b/gfx/angle/src/libGLESv2/Context.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -15,7 +15,6 @@ #include #define EGLAPI #include -#include #include #include @@ -27,22 +26,23 @@ #include "common/angleutils.h" #include "common/RefCountObject.h" -#include "libGLESv2/ResourceManager.h" #include "libGLESv2/HandleAllocator.h" +#include "libGLESv2/angletypes.h" +#include "libGLESv2/Constants.h" + +namespace rx +{ +class Renderer; +} namespace egl { class Display; class Surface; -class Config; } namespace gl { -struct TranslatedAttribute; -struct TranslatedIndexData; - -class Buffer; class Shader; class Program; class ProgramBinary; @@ -54,35 +54,12 @@ class Renderbuffer; class RenderbufferStorage; class Colorbuffer; class Depthbuffer; -class StreamingIndexBuffer; class Stencilbuffer; class DepthStencilbuffer; -class VertexDataManager; -class IndexDataManager; -class Blit; class Fence; class Query; - -enum -{ - D3D9_MAX_FLOAT_CONSTANTS = 256, - D3D9_MAX_BOOL_CONSTANTS = 16, - D3D9_MAX_INT_CONSTANTS = 16, - - MAX_VERTEX_ATTRIBS = 16, - MAX_VERTEX_UNIFORM_VECTORS = D3D9_MAX_FLOAT_CONSTANTS - 2, // Reserve space for dx_HalfPixelSize and dx_DepthRange. - MAX_VARYING_VECTORS_SM2 = 8, - MAX_VARYING_VECTORS_SM3 = 10, - MAX_TEXTURE_IMAGE_UNITS = 16, - MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF = 4, // For devices supporting vertex texture fetch - MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF = MAX_TEXTURE_IMAGE_UNITS + MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF, - MAX_FRAGMENT_UNIFORM_VECTORS_SM2 = 32 - 3, // Reserve space for dx_Coord, dx_Depth, and dx_DepthRange. dx_PointOrLines and dx_FrontCCW use separate bool registers. - MAX_FRAGMENT_UNIFORM_VECTORS_SM3 = 224 - 3, - MAX_DRAW_BUFFERS = 1, - - GL_BGRA4_ANGLEX = 0x6ABC, - GL_BGR5_A1_ANGLEX = 0x6ABD -}; +class ResourceManager; +class Buffer; enum QueryType { @@ -92,19 +69,6 @@ enum QueryType QUERY_TYPE_COUNT }; -const float ALIASED_LINE_WIDTH_RANGE_MIN = 1.0f; -const float ALIASED_LINE_WIDTH_RANGE_MAX = 1.0f; -const float ALIASED_POINT_SIZE_RANGE_MIN = 1.0f; -const float ALIASED_POINT_SIZE_RANGE_MAX_SM2 = 1.0f; - -struct Color -{ - float red; - float green; - float blue; - float alpha; -}; - // Helper structure describing a single vertex attribute class VertexAttribute { @@ -155,8 +119,6 @@ class VertexAttribute unsigned int mDivisor; }; -typedef VertexAttribute VertexAttributeArray[MAX_VERTEX_ATTRIBS]; - // Helper structure to store all raw state struct State { @@ -164,67 +126,29 @@ struct State GLclampf depthClearValue; int stencilClearValue; - bool cullFace; - GLenum cullMode; - GLenum frontFace; - bool depthTest; - GLenum depthFunc; - bool blend; - GLenum sourceBlendRGB; - GLenum destBlendRGB; - GLenum sourceBlendAlpha; - GLenum destBlendAlpha; - GLenum blendEquationRGB; - GLenum blendEquationAlpha; + RasterizerState rasterizer; + bool scissorTest; + Rectangle scissor; + + BlendState blend; Color blendColor; - bool stencilTest; - GLenum stencilFunc; - GLint stencilRef; - GLuint stencilMask; - GLenum stencilFail; - GLenum stencilPassDepthFail; - GLenum stencilPassDepthPass; - GLuint stencilWritemask; - GLenum stencilBackFunc; - GLint stencilBackRef; - GLuint stencilBackMask; - GLenum stencilBackFail; - GLenum stencilBackPassDepthFail; - GLenum stencilBackPassDepthPass; - GLuint stencilBackWritemask; - bool polygonOffsetFill; - GLfloat polygonOffsetFactor; - GLfloat polygonOffsetUnits; - bool sampleAlphaToCoverage; bool sampleCoverage; GLclampf sampleCoverageValue; bool sampleCoverageInvert; - bool scissorTest; - bool dither; + + DepthStencilState depthStencil; + GLint stencilRef; + GLint stencilBackRef; GLfloat lineWidth; GLenum generateMipmapHint; GLenum fragmentShaderDerivativeHint; - GLint viewportX; - GLint viewportY; - GLsizei viewportWidth; - GLsizei viewportHeight; + Rectangle viewport; float zNear; float zFar; - GLint scissorX; - GLint scissorY; - GLsizei scissorWidth; - GLsizei scissorHeight; - - bool colorMaskRed; - bool colorMaskGreen; - bool colorMaskBlue; - bool colorMaskAlpha; - bool depthMask; - unsigned int activeSampler; // Active texture unit selector - GL_TEXTURE0 BindingPointer arrayBuffer; BindingPointer elementArrayBuffer; @@ -234,7 +158,7 @@ struct State GLuint currentProgram; VertexAttribute vertexAttribute[MAX_VERTEX_ATTRIBS]; - BindingPointer samplerTexture[TEXTURE_TYPE_COUNT][MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF]; + BindingPointer samplerTexture[TEXTURE_TYPE_COUNT][IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS]; BindingPointer activeQuery[QUERY_TYPE_COUNT]; GLint unpackAlignment; @@ -242,52 +166,14 @@ struct State bool packReverseRowOrder; }; -// Helper class to construct and cache vertex declarations -class VertexDeclarationCache -{ - public: - VertexDeclarationCache(); - ~VertexDeclarationCache(); - - GLenum applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], ProgramBinary *programBinary, GLsizei instances, GLsizei *repeatDraw); - - void markStateDirty(); - - private: - UINT mMaxLru; - - enum { NUM_VERTEX_DECL_CACHE_ENTRIES = 32 }; - - struct VBData - { - unsigned int serial; - unsigned int stride; - unsigned int offset; - }; - - VBData mAppliedVBs[MAX_VERTEX_ATTRIBS]; - IDirect3DVertexDeclaration9 *mLastSetVDecl; - bool mInstancingEnabled; - - struct VertexDeclCacheEntry - { - D3DVERTEXELEMENT9 cachedElements[MAX_VERTEX_ATTRIBS + 1]; - UINT lruCount; - IDirect3DVertexDeclaration9 *vertexDeclaration; - } mVertexDeclCache[NUM_VERTEX_DECL_CACHE_ENTRIES]; -}; - class Context { public: - Context(const egl::Config *config, const gl::Context *shareContext, bool notifyResets, bool robustAccess); + Context(const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess); ~Context(); - void makeCurrent(egl::Display *display, egl::Surface *surface); - - virtual void markAllStateDirty(); - void markDxUniformsDirty(); + void makeCurrent(egl::Surface *surface); virtual void markContextLost(); bool isContextLost(); @@ -377,8 +263,6 @@ class Context bool normalized, GLsizei stride, const void *pointer); const void *getVertexAttribPointer(unsigned int attribNum) const; - const VertexAttributeArray &getVertexAttributes(); - void setUnpackAlignment(GLint alignment); GLint getUnpackAlignment() const; @@ -430,7 +314,7 @@ class Context void setFramebufferZero(Framebuffer *framebuffer); - void setRenderbufferStorage(RenderbufferStorage *renderbuffer); + void setRenderbufferStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples); void setVertexAttrib(GLuint index, const GLfloat *values); void setVertexAttribDivisor(GLuint index, GLuint divisor); @@ -465,8 +349,6 @@ class Context void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instances); void sync(bool block); // flush/finish - void drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex); - void recordInvalidEnum(); void recordInvalidValue(); void recordInvalidOperation(); @@ -477,22 +359,20 @@ class Context GLenum getResetStatus(); virtual bool isResetNotificationEnabled(); - bool supportsShaderModel3() const; + int getMajorShaderModel() const; float getMaximumPointSize() const; - int getMaximumVaryingVectors() const; - unsigned int getMaximumVertexTextureImageUnits() const; unsigned int getMaximumCombinedTextureImageUnits() const; - int getMaximumFragmentUniformVectors() const; int getMaximumRenderbufferDimension() const; int getMaximumTextureDimension() const; int getMaximumCubeTextureDimension() const; int getMaximumTextureLevel() const; + unsigned int getMaximumRenderTargets() const; GLsizei getMaxSupportedSamples() const; - int getNearestSupportedSamples(D3DFORMAT format, int requested) const; const char *getExtensionString() const; const char *getRendererString() const; bool supportsEventQueries() const; bool supportsOcclusionQueries() const; + bool supportsBGRATextures() const; bool supportsDXT1Textures() const; bool supportsDXT3Textures() const; bool supportsDXT5Textures() const; @@ -509,7 +389,6 @@ class Context bool supportsNonPower2Texture() const; bool supportsInstancing() const; bool supportsTextureFilterAnisotropy() const; - bool supportsDerivativeInstructions() const; bool getCurrentReadFormatType(GLenum *format, GLenum *type); @@ -519,17 +398,11 @@ class Context GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask); - Blit *getBlitter() { return mBlit; } - - const D3DCAPS9 &getDeviceCaps() { return mDeviceCaps; } - private: DISALLOW_COPY_AND_ASSIGN(Context); - bool applyRenderTarget(bool ignoreViewport); + bool applyRenderTarget(GLenum drawMode, bool ignoreViewport); void applyState(GLenum drawMode); - GLenum applyVertexBuffer(GLint first, GLsizei count, GLsizei instances, GLsizei *repeatDraw); - GLenum applyIndexBuffer(const GLvoid *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo); void applyShaders(); void applyTextures(); void applyTextures(SamplerType type); @@ -542,14 +415,11 @@ class Context Texture *getIncompleteTexture(TextureType type); bool skipDraw(GLenum drawMode); - bool isTriangleMode(GLenum drawMode); void initExtensionString(); void initRendererString(); - const egl::Config *const mConfig; - egl::Display *mDisplay; - IDirect3DDevice9 *mDevice; + rx::Renderer *const mRenderer; State mState; @@ -578,13 +448,6 @@ class Context const char *mExtensionString; const char *mRendererString; - - VertexDataManager *mVertexDataManager; - IndexDataManager *mIndexDataManager; - - Blit *mBlit; - - StreamingIndexBuffer *mLineLoopIB; BindingPointer mIncompleteTextures[TEXTURE_TYPE_COUNT]; @@ -602,36 +465,23 @@ class Context GLenum mResetStrategy; bool mRobustAccess; - unsigned int mAppliedTextureSerialPS[MAX_TEXTURE_IMAGE_UNITS]; - unsigned int mAppliedTextureSerialVS[MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF]; - unsigned int mAppliedProgramBinarySerial; - unsigned int mAppliedRenderTargetSerial; - unsigned int mAppliedDepthbufferSerial; - unsigned int mAppliedStencilbufferSerial; - unsigned int mAppliedIBSerial; - bool mDepthStencilInitialized; - bool mViewportInitialized; - D3DVIEWPORT9 mSetViewport; - bool mRenderTargetDescInitialized; - D3DSURFACE_DESC mRenderTargetDesc; - bool mDxUniformsDirty; BindingPointer mCurrentProgramBinary; Framebuffer *mBoundDrawFramebuffer; - bool mSupportsShaderModel3; + int mMajorShaderModel; float mMaximumPointSize; bool mSupportsVertexTexture; bool mSupportsNonPower2Texture; bool mSupportsInstancing; + int mMaxViewportDimension; int mMaxRenderbufferDimension; int mMaxTextureDimension; int mMaxCubeTextureDimension; int mMaxTextureLevel; float mMaxTextureAnisotropy; - std::map mMultiSampleSupport; - GLsizei mMaxSupportedSamples; bool mSupportsEventQueries; bool mSupportsOcclusionQueries; + bool mSupportsBGRATextures; bool mSupportsDXT1Textures; bool mSupportsDXT3Textures; bool mSupportsDXT5Textures; @@ -646,42 +496,10 @@ class Context bool mSupportsDepthTextures; bool mSupports32bitIndices; bool mSupportsTextureFilterAnisotropy; - bool mSupportsDerivativeInstructions; int mNumCompressedTextureFormats; - // state caching flags - bool mClearStateDirty; - bool mCullStateDirty; - bool mDepthStateDirty; - bool mMaskStateDirty; - bool mPixelPackingStateDirty; - bool mBlendStateDirty; - bool mStencilStateDirty; - bool mPolygonOffsetStateDirty; - bool mScissorStateDirty; - bool mSampleStateDirty; - bool mFrontFaceDirty; - bool mDitherStateDirty; - - IDirect3DStateBlock9 *mMaskedClearSavedState; - - D3DCAPS9 mDeviceCaps; - ResourceManager *mResourceManager; - - VertexDeclarationCache mVertexDeclarationCache; }; } -extern "C" -{ -// Exported functions for use by EGL -gl::Context *glCreateContext(const egl::Config *config, const gl::Context *shareContext, bool notifyResets, bool robustAccess); -void glDestroyContext(gl::Context *context); -void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface); -gl::Context *glGetCurrentContext(); -__eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char *procname); -bool __stdcall glBindTexImage(egl::Surface *surface); -} - #endif // INCLUDE_CONTEXT_H_ diff --git a/gfx/angle/src/libGLESv2/D3DConstantTable.cpp b/gfx/angle/src/libGLESv2/D3DConstantTable.cpp deleted file mode 100644 index 145a56857837..000000000000 --- a/gfx/angle/src/libGLESv2/D3DConstantTable.cpp +++ /dev/null @@ -1,231 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// D3DConstantTable.cpp: Implements the D3DConstantTable class which parses -// information about constants from the CTAB comment in a D3D shader blob. -// Restructures the constant table as a hierarchy of constants in the same -// way as D3DX. - -#include "libGLESv2/D3DConstantTable.h" - -#include "common/system.h" -#include -#include -#include - -#include "libGLESv2/BinaryStream.h" - -const static int SHADER_VERSION_MASK = D3DVS_VERSION(0, 0); -const static int FOURCC_CTAB = MAKEFOURCC('C','T','A','B'); - -namespace gl -{ -// These structs and constants correspond to the format of the constant table in a shader binary. -// They match the corresponding structures in d3dx9shader.h. -namespace ctab -{ -struct ConstantTable -{ - DWORD size; - DWORD creator; - DWORD version; - DWORD constants; - DWORD constantInfos; - DWORD flags; - DWORD target; -}; - -struct ConstantInfo -{ - DWORD name; - WORD registerSet; - WORD registerIndex; - WORD registerCount; - WORD reserved; - DWORD typeInfo; - DWORD defaultValue; -}; - -struct TypeInfo -{ - WORD typeClass; - WORD type; - WORD rows; - WORD columns; - WORD elements; - WORD structMembers; - DWORD structMemberInfos; -}; - -struct StructMemberInfo -{ - DWORD name; - DWORD typeInfo; -}; -} - -D3DConstant::D3DConstant(const char *base, const ctab::ConstantInfo *constantInfo) -{ - const ctab::TypeInfo *typeInfo = reinterpret_cast(base + constantInfo->typeInfo); - - name = base + constantInfo->name; - registerSet = static_cast(constantInfo->registerSet); - registerIndex = constantInfo->registerIndex; - registerCount = constantInfo->registerCount; - typeClass = static_cast(typeInfo->typeClass); - type = static_cast(typeInfo->type); - rows = typeInfo->rows; - columns = typeInfo->columns; - elements = typeInfo->elements; - - if (typeClass == CLASS_STRUCT) - { - addStructMembers(base, registerSet, registerIndex, registerIndex + registerCount, typeInfo); - } -} - -D3DConstant::D3DConstant(const char *base, RegisterSet registerSet, unsigned registerIndex, unsigned maxRegister, const ctab::StructMemberInfo *memberInfo) - : registerSet(registerSet), registerIndex(registerIndex) -{ - const ctab::TypeInfo *typeInfo = reinterpret_cast(base + memberInfo->typeInfo); - - name = base + memberInfo->name; - registerCount = std::min(static_cast(maxRegister - registerIndex), typeInfo->rows * typeInfo->elements); - typeClass = static_cast(typeInfo->typeClass); - type = static_cast(typeInfo->type); - rows = typeInfo->rows; - columns = typeInfo->columns; - elements = typeInfo->elements; - - if (typeClass == CLASS_STRUCT) - { - registerCount = addStructMembers(base, registerSet, registerIndex, maxRegister, typeInfo); - } -} - -D3DConstant::~D3DConstant() -{ - for (size_t j = 0; j < structMembers.size(); ++j) - { - for (size_t i = 0; i < structMembers[j].size(); ++i) - { - delete structMembers[j][i]; - } - } -} - -unsigned D3DConstant::addStructMembers(const char *base, RegisterSet registerSet, unsigned registerIndex, unsigned maxRegister, const ctab::TypeInfo *typeInfo) -{ - const ctab::StructMemberInfo *memberInfos = reinterpret_cast( - base + typeInfo->structMemberInfos); - - unsigned memberIndex = registerIndex; - - structMembers.resize(elements); - - for (unsigned j = 0; j < elements; ++j) - { - structMembers[j].resize(typeInfo->structMembers); - - for (unsigned i = 0; i < typeInfo->structMembers; ++i) - { - const ctab::TypeInfo *memberTypeInfo = reinterpret_cast( - base + memberInfos[i].typeInfo); - - D3DConstant *member = new D3DConstant(base, registerSet, memberIndex, maxRegister, memberInfos + i); - memberIndex += member->registerCount; - - structMembers[j][i] = member; - } - } - - return memberIndex - registerIndex; -} - -D3DConstantTable::D3DConstantTable(void *blob, size_t size) : mError(false) -{ - BinaryInputStream stream(blob, size); - - int version; - stream.read(&version); - if ((version & SHADER_VERSION_MASK) != SHADER_VERSION_MASK) - { - mError = true; - return; - } - - const ctab::ConstantTable* constantTable = NULL; - - while (!stream.error()) - { - int token; - stream.read(&token); - - if ((token & D3DSI_OPCODE_MASK) == D3DSIO_COMMENT) - { - size_t length = ((token & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT) * sizeof(DWORD); - - int fourcc; - stream.read(&fourcc); - if (fourcc == FOURCC_CTAB) - { - constantTable = reinterpret_cast(static_cast(blob) + stream.offset()); - break; - } - - stream.skip(length - sizeof(fourcc)); - } - else if (token == D3DSIO_END) - { - break; - } - } - - mError = !constantTable || stream.error(); - if (mError) - { - return; - } - - const char *base = reinterpret_cast(constantTable); - - mConstants.resize(constantTable->constants); - const ctab::ConstantInfo *constantInfos = - reinterpret_cast(base + constantTable->constantInfos); - for (size_t i = 0; i < constantTable->constants; ++i) - { - mConstants[i] = new D3DConstant(base, constantInfos + i); - } -} - -D3DConstantTable::~D3DConstantTable() -{ - for (size_t i = 0; i < mConstants.size(); ++i) - { - delete mConstants[i]; - } -} - -const D3DConstant *D3DConstantTable::getConstant(unsigned index) const -{ - return mConstants[index]; -} - -const D3DConstant *D3DConstantTable::getConstantByName(const char *name) const -{ - for (size_t i = 0; i < mConstants.size(); ++i) - { - const D3DConstant *constant = getConstant(i); - if (constant->name == name) - { - return constant; - } - } - - return NULL; -} - -} diff --git a/gfx/angle/src/libGLESv2/D3DConstantTable.h b/gfx/angle/src/libGLESv2/D3DConstantTable.h deleted file mode 100644 index b376911cf818..000000000000 --- a/gfx/angle/src/libGLESv2/D3DConstantTable.h +++ /dev/null @@ -1,117 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// D3DConstantTable.h: Implements the D3DConstantTable class which parses -// information about constants from the CTAB comment in a D3D shader blob. -// Restructures the constant table as a hierarchy of constants in the same -// way as D3DX. - -#ifndef LIBGLESV2_D3DCONSTANTTABLE_H_ -#define LIBGLESV2_D3DCONSTANTTABLE_H_ - -#include -#include - -#include "common/angleutils.h" - -namespace gl -{ - -namespace ctab -{ -struct ConstantTable; -struct ConstantInfo; -struct TypeInfo; -struct StructMemberInfo; -} - -struct D3DConstant -{ - // These enums match those in d3dx9shader.h. - enum Class - { - CLASS_SCALAR, - CLASS_VECTOR, - CLASS_MATRIX_ROWS, - CLASS_MATRIX_COLUMNS, - CLASS_OBJECT, - CLASS_STRUCT, - }; - - enum RegisterSet - { - RS_BOOL, - RS_INT4, - RS_FLOAT4, - RS_SAMPLER, - }; - - enum Type - { - PT_VOID, - PT_BOOL, - PT_INT, - PT_FLOAT, - PT_STRING, - PT_TEXTURE, - PT_TEXTURE1D, - PT_TEXTURE2D, - PT_TEXTURE3D, - PT_TEXTURECUBE, - PT_SAMPLER, - PT_SAMPLER1D, - PT_SAMPLER2D, - PT_SAMPLER3D, - PT_SAMPLERCUBE, - PT_PIXELSHADER, - PT_VERTEXSHADER, - PT_PIXELFRAGMENT, - PT_VERTEXFRAGMENT, - PT_UNSUPPORTED, - }; - - D3DConstant(const char *base, const ctab::ConstantInfo *constantInfo); - ~D3DConstant(); - - std::string name; - RegisterSet registerSet; - unsigned registerIndex; - unsigned registerCount; - Class typeClass; - Type type; - unsigned rows; - unsigned columns; - unsigned elements; - - // Array of structure members. - std::vector > structMembers; - - private: - D3DConstant(const char *base, RegisterSet registerSet, unsigned registerIndex, unsigned maxRegister, const ctab::StructMemberInfo *memberInfo); - unsigned addStructMembers(const char *base, RegisterSet registerSet, unsigned registerIndex, unsigned maxRegister, const ctab::TypeInfo *typeInfo); -}; - -class D3DConstantTable -{ - public: - D3DConstantTable(void *blob, size_t size); - ~D3DConstantTable(); - - bool error() const { return mError; } - - unsigned constants() const { return mConstants.size(); } - const D3DConstant *getConstant(unsigned index) const; - const D3DConstant *getConstantByName(const char *name) const; - - private: - DISALLOW_COPY_AND_ASSIGN(D3DConstantTable); - std::vector mConstants; - bool mError; -}; - -} - -#endif // LIBGLESV2_D3DCONSTANTTABLE_H_ diff --git a/gfx/angle/src/libGLESv2/Fence.cpp b/gfx/angle/src/libGLESv2/Fence.cpp index 14d1239abf2b..e4218bbeec2a 100644 --- a/gfx/angle/src/libGLESv2/Fence.cpp +++ b/gfx/angle/src/libGLESv2/Fence.cpp @@ -1,5 +1,6 @@ +#include "precompiled.h" // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -7,126 +8,45 @@ // Fence.cpp: Implements the gl::Fence class, which supports the GL_NV_fence extension. #include "libGLESv2/Fence.h" - -#include "libGLESv2/main.h" +#include "libGLESv2/renderer/FenceImpl.h" +#include "libGLESv2/renderer/Renderer.h" namespace gl { -Fence::Fence(egl::Display* display) +Fence::Fence(rx::Renderer *renderer) { - mDisplay = display; - mQuery = NULL; - mCondition = GL_NONE; - mStatus = GL_FALSE; + mFence = renderer->createFence(); } Fence::~Fence() { - if (mQuery != NULL) - { - mDisplay->freeEventQuery(mQuery); - } + delete mFence; } GLboolean Fence::isFence() { - // GL_NV_fence spec: - // A name returned by GenFencesNV, but not yet set via SetFenceNV, is not the name of an existing fence. - return mQuery != NULL; + return mFence->isFence(); } void Fence::setFence(GLenum condition) { - if (!mQuery) - { - mQuery = mDisplay->allocateEventQuery(); - if (!mQuery) - { - return error(GL_OUT_OF_MEMORY); - } - } - - HRESULT result = mQuery->Issue(D3DISSUE_END); - ASSERT(SUCCEEDED(result)); - - mCondition = condition; - mStatus = GL_FALSE; + mFence->setFence(condition); } GLboolean Fence::testFence() { - if (mQuery == NULL) - { - return error(GL_INVALID_OPERATION, GL_TRUE); - } - - HRESULT result = mQuery->GetData(NULL, 0, D3DGETDATA_FLUSH); - - if (checkDeviceLost(result)) - { - return error(GL_OUT_OF_MEMORY, GL_TRUE); - } - - ASSERT(result == S_OK || result == S_FALSE); - mStatus = result == S_OK; - return mStatus; + return mFence->testFence(); } void Fence::finishFence() { - if (mQuery == NULL) - { - return error(GL_INVALID_OPERATION); - } - - while (!testFence()) - { - Sleep(0); - } + mFence->finishFence(); } void Fence::getFenceiv(GLenum pname, GLint *params) { - if (mQuery == NULL) - { - return error(GL_INVALID_OPERATION); - } - - switch (pname) - { - case GL_FENCE_STATUS_NV: - { - // GL_NV_fence spec: - // Once the status of a fence has been finished (via FinishFenceNV) or tested and the returned status is TRUE (via either TestFenceNV - // or GetFenceivNV querying the FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence. - if (mStatus) - { - params[0] = GL_TRUE; - return; - } - - HRESULT result = mQuery->GetData(NULL, 0, 0); - - if (checkDeviceLost(result)) - { - params[0] = GL_TRUE; - return error(GL_OUT_OF_MEMORY); - } - - ASSERT(result == S_OK || result == S_FALSE); - mStatus = result == S_OK; - params[0] = mStatus; - - break; - } - case GL_FENCE_CONDITION_NV: - params[0] = mCondition; - break; - default: - return error(GL_INVALID_ENUM); - break; - } + mFence->getFenceiv(pname, params); } } diff --git a/gfx/angle/src/libGLESv2/Fence.h b/gfx/angle/src/libGLESv2/Fence.h index 9626cb0ff0e0..1cedebb112d9 100644 --- a/gfx/angle/src/libGLESv2/Fence.h +++ b/gfx/angle/src/libGLESv2/Fence.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -9,15 +9,12 @@ #ifndef LIBGLESV2_FENCE_H_ #define LIBGLESV2_FENCE_H_ -#define GL_APICALL -#include -#include - #include "common/angleutils.h" -namespace egl +namespace rx { -class Display; +class Renderer; +class FenceImpl; } namespace gl @@ -26,7 +23,7 @@ namespace gl class Fence { public: - explicit Fence(egl::Display* display); + explicit Fence(rx::Renderer *renderer); virtual ~Fence(); GLboolean isFence(); @@ -38,10 +35,7 @@ class Fence private: DISALLOW_COPY_AND_ASSIGN(Fence); - egl::Display* mDisplay; - IDirect3DQuery9* mQuery; - GLenum mCondition; - GLboolean mStatus; + rx::FenceImpl *mFence; }; } diff --git a/gfx/angle/src/libGLESv2/Float16ToFloat32.cpp b/gfx/angle/src/libGLESv2/Float16ToFloat32.cpp index da3687ddd113..b90d2f6023c5 100644 --- a/gfx/angle/src/libGLESv2/Float16ToFloat32.cpp +++ b/gfx/angle/src/libGLESv2/Float16ToFloat32.cpp @@ -1,2203 +1,2204 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// This file is automatically generated. - -namespace gl -{ - -const static unsigned g_mantissa[2048] = { - 0x00000000, - 0x33800000, - 0x34000000, - 0x34400000, - 0x34800000, - 0x34a00000, - 0x34c00000, - 0x34e00000, - 0x35000000, - 0x35100000, - 0x35200000, - 0x35300000, - 0x35400000, - 0x35500000, - 0x35600000, - 0x35700000, - 0x35800000, - 0x35880000, - 0x35900000, - 0x35980000, - 0x35a00000, - 0x35a80000, - 0x35b00000, - 0x35b80000, - 0x35c00000, - 0x35c80000, - 0x35d00000, - 0x35d80000, - 0x35e00000, - 0x35e80000, - 0x35f00000, - 0x35f80000, - 0x36000000, - 0x36040000, - 0x36080000, - 0x360c0000, - 0x36100000, - 0x36140000, - 0x36180000, - 0x361c0000, - 0x36200000, - 0x36240000, - 0x36280000, - 0x362c0000, - 0x36300000, - 0x36340000, - 0x36380000, - 0x363c0000, - 0x36400000, - 0x36440000, - 0x36480000, - 0x364c0000, - 0x36500000, - 0x36540000, - 0x36580000, - 0x365c0000, - 0x36600000, - 0x36640000, - 0x36680000, - 0x366c0000, - 0x36700000, - 0x36740000, - 0x36780000, - 0x367c0000, - 0x36800000, - 0x36820000, - 0x36840000, - 0x36860000, - 0x36880000, - 0x368a0000, - 0x368c0000, - 0x368e0000, - 0x36900000, - 0x36920000, - 0x36940000, - 0x36960000, - 0x36980000, - 0x369a0000, - 0x369c0000, - 0x369e0000, - 0x36a00000, - 0x36a20000, - 0x36a40000, - 0x36a60000, - 0x36a80000, - 0x36aa0000, - 0x36ac0000, - 0x36ae0000, - 0x36b00000, - 0x36b20000, - 0x36b40000, - 0x36b60000, - 0x36b80000, - 0x36ba0000, - 0x36bc0000, - 0x36be0000, - 0x36c00000, - 0x36c20000, - 0x36c40000, - 0x36c60000, - 0x36c80000, - 0x36ca0000, - 0x36cc0000, - 0x36ce0000, - 0x36d00000, - 0x36d20000, - 0x36d40000, - 0x36d60000, - 0x36d80000, - 0x36da0000, - 0x36dc0000, - 0x36de0000, - 0x36e00000, - 0x36e20000, - 0x36e40000, - 0x36e60000, - 0x36e80000, - 0x36ea0000, - 0x36ec0000, - 0x36ee0000, - 0x36f00000, - 0x36f20000, - 0x36f40000, - 0x36f60000, - 0x36f80000, - 0x36fa0000, - 0x36fc0000, - 0x36fe0000, - 0x37000000, - 0x37010000, - 0x37020000, - 0x37030000, - 0x37040000, - 0x37050000, - 0x37060000, - 0x37070000, - 0x37080000, - 0x37090000, - 0x370a0000, - 0x370b0000, - 0x370c0000, - 0x370d0000, - 0x370e0000, - 0x370f0000, - 0x37100000, - 0x37110000, - 0x37120000, - 0x37130000, - 0x37140000, - 0x37150000, - 0x37160000, - 0x37170000, - 0x37180000, - 0x37190000, - 0x371a0000, - 0x371b0000, - 0x371c0000, - 0x371d0000, - 0x371e0000, - 0x371f0000, - 0x37200000, - 0x37210000, - 0x37220000, - 0x37230000, - 0x37240000, - 0x37250000, - 0x37260000, - 0x37270000, - 0x37280000, - 0x37290000, - 0x372a0000, - 0x372b0000, - 0x372c0000, - 0x372d0000, - 0x372e0000, - 0x372f0000, - 0x37300000, - 0x37310000, - 0x37320000, - 0x37330000, - 0x37340000, - 0x37350000, - 0x37360000, - 0x37370000, - 0x37380000, - 0x37390000, - 0x373a0000, - 0x373b0000, - 0x373c0000, - 0x373d0000, - 0x373e0000, - 0x373f0000, - 0x37400000, - 0x37410000, - 0x37420000, - 0x37430000, - 0x37440000, - 0x37450000, - 0x37460000, - 0x37470000, - 0x37480000, - 0x37490000, - 0x374a0000, - 0x374b0000, - 0x374c0000, - 0x374d0000, - 0x374e0000, - 0x374f0000, - 0x37500000, - 0x37510000, - 0x37520000, - 0x37530000, - 0x37540000, - 0x37550000, - 0x37560000, - 0x37570000, - 0x37580000, - 0x37590000, - 0x375a0000, - 0x375b0000, - 0x375c0000, - 0x375d0000, - 0x375e0000, - 0x375f0000, - 0x37600000, - 0x37610000, - 0x37620000, - 0x37630000, - 0x37640000, - 0x37650000, - 0x37660000, - 0x37670000, - 0x37680000, - 0x37690000, - 0x376a0000, - 0x376b0000, - 0x376c0000, - 0x376d0000, - 0x376e0000, - 0x376f0000, - 0x37700000, - 0x37710000, - 0x37720000, - 0x37730000, - 0x37740000, - 0x37750000, - 0x37760000, - 0x37770000, - 0x37780000, - 0x37790000, - 0x377a0000, - 0x377b0000, - 0x377c0000, - 0x377d0000, - 0x377e0000, - 0x377f0000, - 0x37800000, - 0x37808000, - 0x37810000, - 0x37818000, - 0x37820000, - 0x37828000, - 0x37830000, - 0x37838000, - 0x37840000, - 0x37848000, - 0x37850000, - 0x37858000, - 0x37860000, - 0x37868000, - 0x37870000, - 0x37878000, - 0x37880000, - 0x37888000, - 0x37890000, - 0x37898000, - 0x378a0000, - 0x378a8000, - 0x378b0000, - 0x378b8000, - 0x378c0000, - 0x378c8000, - 0x378d0000, - 0x378d8000, - 0x378e0000, - 0x378e8000, - 0x378f0000, - 0x378f8000, - 0x37900000, - 0x37908000, - 0x37910000, - 0x37918000, - 0x37920000, - 0x37928000, - 0x37930000, - 0x37938000, - 0x37940000, - 0x37948000, - 0x37950000, - 0x37958000, - 0x37960000, - 0x37968000, - 0x37970000, - 0x37978000, - 0x37980000, - 0x37988000, - 0x37990000, - 0x37998000, - 0x379a0000, - 0x379a8000, - 0x379b0000, - 0x379b8000, - 0x379c0000, - 0x379c8000, - 0x379d0000, - 0x379d8000, - 0x379e0000, - 0x379e8000, - 0x379f0000, - 0x379f8000, - 0x37a00000, - 0x37a08000, - 0x37a10000, - 0x37a18000, - 0x37a20000, - 0x37a28000, - 0x37a30000, - 0x37a38000, - 0x37a40000, - 0x37a48000, - 0x37a50000, - 0x37a58000, - 0x37a60000, - 0x37a68000, - 0x37a70000, - 0x37a78000, - 0x37a80000, - 0x37a88000, - 0x37a90000, - 0x37a98000, - 0x37aa0000, - 0x37aa8000, - 0x37ab0000, - 0x37ab8000, - 0x37ac0000, - 0x37ac8000, - 0x37ad0000, - 0x37ad8000, - 0x37ae0000, - 0x37ae8000, - 0x37af0000, - 0x37af8000, - 0x37b00000, - 0x37b08000, - 0x37b10000, - 0x37b18000, - 0x37b20000, - 0x37b28000, - 0x37b30000, - 0x37b38000, - 0x37b40000, - 0x37b48000, - 0x37b50000, - 0x37b58000, - 0x37b60000, - 0x37b68000, - 0x37b70000, - 0x37b78000, - 0x37b80000, - 0x37b88000, - 0x37b90000, - 0x37b98000, - 0x37ba0000, - 0x37ba8000, - 0x37bb0000, - 0x37bb8000, - 0x37bc0000, - 0x37bc8000, - 0x37bd0000, - 0x37bd8000, - 0x37be0000, - 0x37be8000, - 0x37bf0000, - 0x37bf8000, - 0x37c00000, - 0x37c08000, - 0x37c10000, - 0x37c18000, - 0x37c20000, - 0x37c28000, - 0x37c30000, - 0x37c38000, - 0x37c40000, - 0x37c48000, - 0x37c50000, - 0x37c58000, - 0x37c60000, - 0x37c68000, - 0x37c70000, - 0x37c78000, - 0x37c80000, - 0x37c88000, - 0x37c90000, - 0x37c98000, - 0x37ca0000, - 0x37ca8000, - 0x37cb0000, - 0x37cb8000, - 0x37cc0000, - 0x37cc8000, - 0x37cd0000, - 0x37cd8000, - 0x37ce0000, - 0x37ce8000, - 0x37cf0000, - 0x37cf8000, - 0x37d00000, - 0x37d08000, - 0x37d10000, - 0x37d18000, - 0x37d20000, - 0x37d28000, - 0x37d30000, - 0x37d38000, - 0x37d40000, - 0x37d48000, - 0x37d50000, - 0x37d58000, - 0x37d60000, - 0x37d68000, - 0x37d70000, - 0x37d78000, - 0x37d80000, - 0x37d88000, - 0x37d90000, - 0x37d98000, - 0x37da0000, - 0x37da8000, - 0x37db0000, - 0x37db8000, - 0x37dc0000, - 0x37dc8000, - 0x37dd0000, - 0x37dd8000, - 0x37de0000, - 0x37de8000, - 0x37df0000, - 0x37df8000, - 0x37e00000, - 0x37e08000, - 0x37e10000, - 0x37e18000, - 0x37e20000, - 0x37e28000, - 0x37e30000, - 0x37e38000, - 0x37e40000, - 0x37e48000, - 0x37e50000, - 0x37e58000, - 0x37e60000, - 0x37e68000, - 0x37e70000, - 0x37e78000, - 0x37e80000, - 0x37e88000, - 0x37e90000, - 0x37e98000, - 0x37ea0000, - 0x37ea8000, - 0x37eb0000, - 0x37eb8000, - 0x37ec0000, - 0x37ec8000, - 0x37ed0000, - 0x37ed8000, - 0x37ee0000, - 0x37ee8000, - 0x37ef0000, - 0x37ef8000, - 0x37f00000, - 0x37f08000, - 0x37f10000, - 0x37f18000, - 0x37f20000, - 0x37f28000, - 0x37f30000, - 0x37f38000, - 0x37f40000, - 0x37f48000, - 0x37f50000, - 0x37f58000, - 0x37f60000, - 0x37f68000, - 0x37f70000, - 0x37f78000, - 0x37f80000, - 0x37f88000, - 0x37f90000, - 0x37f98000, - 0x37fa0000, - 0x37fa8000, - 0x37fb0000, - 0x37fb8000, - 0x37fc0000, - 0x37fc8000, - 0x37fd0000, - 0x37fd8000, - 0x37fe0000, - 0x37fe8000, - 0x37ff0000, - 0x37ff8000, - 0x38000000, - 0x38004000, - 0x38008000, - 0x3800c000, - 0x38010000, - 0x38014000, - 0x38018000, - 0x3801c000, - 0x38020000, - 0x38024000, - 0x38028000, - 0x3802c000, - 0x38030000, - 0x38034000, - 0x38038000, - 0x3803c000, - 0x38040000, - 0x38044000, - 0x38048000, - 0x3804c000, - 0x38050000, - 0x38054000, - 0x38058000, - 0x3805c000, - 0x38060000, - 0x38064000, - 0x38068000, - 0x3806c000, - 0x38070000, - 0x38074000, - 0x38078000, - 0x3807c000, - 0x38080000, - 0x38084000, - 0x38088000, - 0x3808c000, - 0x38090000, - 0x38094000, - 0x38098000, - 0x3809c000, - 0x380a0000, - 0x380a4000, - 0x380a8000, - 0x380ac000, - 0x380b0000, - 0x380b4000, - 0x380b8000, - 0x380bc000, - 0x380c0000, - 0x380c4000, - 0x380c8000, - 0x380cc000, - 0x380d0000, - 0x380d4000, - 0x380d8000, - 0x380dc000, - 0x380e0000, - 0x380e4000, - 0x380e8000, - 0x380ec000, - 0x380f0000, - 0x380f4000, - 0x380f8000, - 0x380fc000, - 0x38100000, - 0x38104000, - 0x38108000, - 0x3810c000, - 0x38110000, - 0x38114000, - 0x38118000, - 0x3811c000, - 0x38120000, - 0x38124000, - 0x38128000, - 0x3812c000, - 0x38130000, - 0x38134000, - 0x38138000, - 0x3813c000, - 0x38140000, - 0x38144000, - 0x38148000, - 0x3814c000, - 0x38150000, - 0x38154000, - 0x38158000, - 0x3815c000, - 0x38160000, - 0x38164000, - 0x38168000, - 0x3816c000, - 0x38170000, - 0x38174000, - 0x38178000, - 0x3817c000, - 0x38180000, - 0x38184000, - 0x38188000, - 0x3818c000, - 0x38190000, - 0x38194000, - 0x38198000, - 0x3819c000, - 0x381a0000, - 0x381a4000, - 0x381a8000, - 0x381ac000, - 0x381b0000, - 0x381b4000, - 0x381b8000, - 0x381bc000, - 0x381c0000, - 0x381c4000, - 0x381c8000, - 0x381cc000, - 0x381d0000, - 0x381d4000, - 0x381d8000, - 0x381dc000, - 0x381e0000, - 0x381e4000, - 0x381e8000, - 0x381ec000, - 0x381f0000, - 0x381f4000, - 0x381f8000, - 0x381fc000, - 0x38200000, - 0x38204000, - 0x38208000, - 0x3820c000, - 0x38210000, - 0x38214000, - 0x38218000, - 0x3821c000, - 0x38220000, - 0x38224000, - 0x38228000, - 0x3822c000, - 0x38230000, - 0x38234000, - 0x38238000, - 0x3823c000, - 0x38240000, - 0x38244000, - 0x38248000, - 0x3824c000, - 0x38250000, - 0x38254000, - 0x38258000, - 0x3825c000, - 0x38260000, - 0x38264000, - 0x38268000, - 0x3826c000, - 0x38270000, - 0x38274000, - 0x38278000, - 0x3827c000, - 0x38280000, - 0x38284000, - 0x38288000, - 0x3828c000, - 0x38290000, - 0x38294000, - 0x38298000, - 0x3829c000, - 0x382a0000, - 0x382a4000, - 0x382a8000, - 0x382ac000, - 0x382b0000, - 0x382b4000, - 0x382b8000, - 0x382bc000, - 0x382c0000, - 0x382c4000, - 0x382c8000, - 0x382cc000, - 0x382d0000, - 0x382d4000, - 0x382d8000, - 0x382dc000, - 0x382e0000, - 0x382e4000, - 0x382e8000, - 0x382ec000, - 0x382f0000, - 0x382f4000, - 0x382f8000, - 0x382fc000, - 0x38300000, - 0x38304000, - 0x38308000, - 0x3830c000, - 0x38310000, - 0x38314000, - 0x38318000, - 0x3831c000, - 0x38320000, - 0x38324000, - 0x38328000, - 0x3832c000, - 0x38330000, - 0x38334000, - 0x38338000, - 0x3833c000, - 0x38340000, - 0x38344000, - 0x38348000, - 0x3834c000, - 0x38350000, - 0x38354000, - 0x38358000, - 0x3835c000, - 0x38360000, - 0x38364000, - 0x38368000, - 0x3836c000, - 0x38370000, - 0x38374000, - 0x38378000, - 0x3837c000, - 0x38380000, - 0x38384000, - 0x38388000, - 0x3838c000, - 0x38390000, - 0x38394000, - 0x38398000, - 0x3839c000, - 0x383a0000, - 0x383a4000, - 0x383a8000, - 0x383ac000, - 0x383b0000, - 0x383b4000, - 0x383b8000, - 0x383bc000, - 0x383c0000, - 0x383c4000, - 0x383c8000, - 0x383cc000, - 0x383d0000, - 0x383d4000, - 0x383d8000, - 0x383dc000, - 0x383e0000, - 0x383e4000, - 0x383e8000, - 0x383ec000, - 0x383f0000, - 0x383f4000, - 0x383f8000, - 0x383fc000, - 0x38400000, - 0x38404000, - 0x38408000, - 0x3840c000, - 0x38410000, - 0x38414000, - 0x38418000, - 0x3841c000, - 0x38420000, - 0x38424000, - 0x38428000, - 0x3842c000, - 0x38430000, - 0x38434000, - 0x38438000, - 0x3843c000, - 0x38440000, - 0x38444000, - 0x38448000, - 0x3844c000, - 0x38450000, - 0x38454000, - 0x38458000, - 0x3845c000, - 0x38460000, - 0x38464000, - 0x38468000, - 0x3846c000, - 0x38470000, - 0x38474000, - 0x38478000, - 0x3847c000, - 0x38480000, - 0x38484000, - 0x38488000, - 0x3848c000, - 0x38490000, - 0x38494000, - 0x38498000, - 0x3849c000, - 0x384a0000, - 0x384a4000, - 0x384a8000, - 0x384ac000, - 0x384b0000, - 0x384b4000, - 0x384b8000, - 0x384bc000, - 0x384c0000, - 0x384c4000, - 0x384c8000, - 0x384cc000, - 0x384d0000, - 0x384d4000, - 0x384d8000, - 0x384dc000, - 0x384e0000, - 0x384e4000, - 0x384e8000, - 0x384ec000, - 0x384f0000, - 0x384f4000, - 0x384f8000, - 0x384fc000, - 0x38500000, - 0x38504000, - 0x38508000, - 0x3850c000, - 0x38510000, - 0x38514000, - 0x38518000, - 0x3851c000, - 0x38520000, - 0x38524000, - 0x38528000, - 0x3852c000, - 0x38530000, - 0x38534000, - 0x38538000, - 0x3853c000, - 0x38540000, - 0x38544000, - 0x38548000, - 0x3854c000, - 0x38550000, - 0x38554000, - 0x38558000, - 0x3855c000, - 0x38560000, - 0x38564000, - 0x38568000, - 0x3856c000, - 0x38570000, - 0x38574000, - 0x38578000, - 0x3857c000, - 0x38580000, - 0x38584000, - 0x38588000, - 0x3858c000, - 0x38590000, - 0x38594000, - 0x38598000, - 0x3859c000, - 0x385a0000, - 0x385a4000, - 0x385a8000, - 0x385ac000, - 0x385b0000, - 0x385b4000, - 0x385b8000, - 0x385bc000, - 0x385c0000, - 0x385c4000, - 0x385c8000, - 0x385cc000, - 0x385d0000, - 0x385d4000, - 0x385d8000, - 0x385dc000, - 0x385e0000, - 0x385e4000, - 0x385e8000, - 0x385ec000, - 0x385f0000, - 0x385f4000, - 0x385f8000, - 0x385fc000, - 0x38600000, - 0x38604000, - 0x38608000, - 0x3860c000, - 0x38610000, - 0x38614000, - 0x38618000, - 0x3861c000, - 0x38620000, - 0x38624000, - 0x38628000, - 0x3862c000, - 0x38630000, - 0x38634000, - 0x38638000, - 0x3863c000, - 0x38640000, - 0x38644000, - 0x38648000, - 0x3864c000, - 0x38650000, - 0x38654000, - 0x38658000, - 0x3865c000, - 0x38660000, - 0x38664000, - 0x38668000, - 0x3866c000, - 0x38670000, - 0x38674000, - 0x38678000, - 0x3867c000, - 0x38680000, - 0x38684000, - 0x38688000, - 0x3868c000, - 0x38690000, - 0x38694000, - 0x38698000, - 0x3869c000, - 0x386a0000, - 0x386a4000, - 0x386a8000, - 0x386ac000, - 0x386b0000, - 0x386b4000, - 0x386b8000, - 0x386bc000, - 0x386c0000, - 0x386c4000, - 0x386c8000, - 0x386cc000, - 0x386d0000, - 0x386d4000, - 0x386d8000, - 0x386dc000, - 0x386e0000, - 0x386e4000, - 0x386e8000, - 0x386ec000, - 0x386f0000, - 0x386f4000, - 0x386f8000, - 0x386fc000, - 0x38700000, - 0x38704000, - 0x38708000, - 0x3870c000, - 0x38710000, - 0x38714000, - 0x38718000, - 0x3871c000, - 0x38720000, - 0x38724000, - 0x38728000, - 0x3872c000, - 0x38730000, - 0x38734000, - 0x38738000, - 0x3873c000, - 0x38740000, - 0x38744000, - 0x38748000, - 0x3874c000, - 0x38750000, - 0x38754000, - 0x38758000, - 0x3875c000, - 0x38760000, - 0x38764000, - 0x38768000, - 0x3876c000, - 0x38770000, - 0x38774000, - 0x38778000, - 0x3877c000, - 0x38780000, - 0x38784000, - 0x38788000, - 0x3878c000, - 0x38790000, - 0x38794000, - 0x38798000, - 0x3879c000, - 0x387a0000, - 0x387a4000, - 0x387a8000, - 0x387ac000, - 0x387b0000, - 0x387b4000, - 0x387b8000, - 0x387bc000, - 0x387c0000, - 0x387c4000, - 0x387c8000, - 0x387cc000, - 0x387d0000, - 0x387d4000, - 0x387d8000, - 0x387dc000, - 0x387e0000, - 0x387e4000, - 0x387e8000, - 0x387ec000, - 0x387f0000, - 0x387f4000, - 0x387f8000, - 0x387fc000, - 0x38000000, - 0x38002000, - 0x38004000, - 0x38006000, - 0x38008000, - 0x3800a000, - 0x3800c000, - 0x3800e000, - 0x38010000, - 0x38012000, - 0x38014000, - 0x38016000, - 0x38018000, - 0x3801a000, - 0x3801c000, - 0x3801e000, - 0x38020000, - 0x38022000, - 0x38024000, - 0x38026000, - 0x38028000, - 0x3802a000, - 0x3802c000, - 0x3802e000, - 0x38030000, - 0x38032000, - 0x38034000, - 0x38036000, - 0x38038000, - 0x3803a000, - 0x3803c000, - 0x3803e000, - 0x38040000, - 0x38042000, - 0x38044000, - 0x38046000, - 0x38048000, - 0x3804a000, - 0x3804c000, - 0x3804e000, - 0x38050000, - 0x38052000, - 0x38054000, - 0x38056000, - 0x38058000, - 0x3805a000, - 0x3805c000, - 0x3805e000, - 0x38060000, - 0x38062000, - 0x38064000, - 0x38066000, - 0x38068000, - 0x3806a000, - 0x3806c000, - 0x3806e000, - 0x38070000, - 0x38072000, - 0x38074000, - 0x38076000, - 0x38078000, - 0x3807a000, - 0x3807c000, - 0x3807e000, - 0x38080000, - 0x38082000, - 0x38084000, - 0x38086000, - 0x38088000, - 0x3808a000, - 0x3808c000, - 0x3808e000, - 0x38090000, - 0x38092000, - 0x38094000, - 0x38096000, - 0x38098000, - 0x3809a000, - 0x3809c000, - 0x3809e000, - 0x380a0000, - 0x380a2000, - 0x380a4000, - 0x380a6000, - 0x380a8000, - 0x380aa000, - 0x380ac000, - 0x380ae000, - 0x380b0000, - 0x380b2000, - 0x380b4000, - 0x380b6000, - 0x380b8000, - 0x380ba000, - 0x380bc000, - 0x380be000, - 0x380c0000, - 0x380c2000, - 0x380c4000, - 0x380c6000, - 0x380c8000, - 0x380ca000, - 0x380cc000, - 0x380ce000, - 0x380d0000, - 0x380d2000, - 0x380d4000, - 0x380d6000, - 0x380d8000, - 0x380da000, - 0x380dc000, - 0x380de000, - 0x380e0000, - 0x380e2000, - 0x380e4000, - 0x380e6000, - 0x380e8000, - 0x380ea000, - 0x380ec000, - 0x380ee000, - 0x380f0000, - 0x380f2000, - 0x380f4000, - 0x380f6000, - 0x380f8000, - 0x380fa000, - 0x380fc000, - 0x380fe000, - 0x38100000, - 0x38102000, - 0x38104000, - 0x38106000, - 0x38108000, - 0x3810a000, - 0x3810c000, - 0x3810e000, - 0x38110000, - 0x38112000, - 0x38114000, - 0x38116000, - 0x38118000, - 0x3811a000, - 0x3811c000, - 0x3811e000, - 0x38120000, - 0x38122000, - 0x38124000, - 0x38126000, - 0x38128000, - 0x3812a000, - 0x3812c000, - 0x3812e000, - 0x38130000, - 0x38132000, - 0x38134000, - 0x38136000, - 0x38138000, - 0x3813a000, - 0x3813c000, - 0x3813e000, - 0x38140000, - 0x38142000, - 0x38144000, - 0x38146000, - 0x38148000, - 0x3814a000, - 0x3814c000, - 0x3814e000, - 0x38150000, - 0x38152000, - 0x38154000, - 0x38156000, - 0x38158000, - 0x3815a000, - 0x3815c000, - 0x3815e000, - 0x38160000, - 0x38162000, - 0x38164000, - 0x38166000, - 0x38168000, - 0x3816a000, - 0x3816c000, - 0x3816e000, - 0x38170000, - 0x38172000, - 0x38174000, - 0x38176000, - 0x38178000, - 0x3817a000, - 0x3817c000, - 0x3817e000, - 0x38180000, - 0x38182000, - 0x38184000, - 0x38186000, - 0x38188000, - 0x3818a000, - 0x3818c000, - 0x3818e000, - 0x38190000, - 0x38192000, - 0x38194000, - 0x38196000, - 0x38198000, - 0x3819a000, - 0x3819c000, - 0x3819e000, - 0x381a0000, - 0x381a2000, - 0x381a4000, - 0x381a6000, - 0x381a8000, - 0x381aa000, - 0x381ac000, - 0x381ae000, - 0x381b0000, - 0x381b2000, - 0x381b4000, - 0x381b6000, - 0x381b8000, - 0x381ba000, - 0x381bc000, - 0x381be000, - 0x381c0000, - 0x381c2000, - 0x381c4000, - 0x381c6000, - 0x381c8000, - 0x381ca000, - 0x381cc000, - 0x381ce000, - 0x381d0000, - 0x381d2000, - 0x381d4000, - 0x381d6000, - 0x381d8000, - 0x381da000, - 0x381dc000, - 0x381de000, - 0x381e0000, - 0x381e2000, - 0x381e4000, - 0x381e6000, - 0x381e8000, - 0x381ea000, - 0x381ec000, - 0x381ee000, - 0x381f0000, - 0x381f2000, - 0x381f4000, - 0x381f6000, - 0x381f8000, - 0x381fa000, - 0x381fc000, - 0x381fe000, - 0x38200000, - 0x38202000, - 0x38204000, - 0x38206000, - 0x38208000, - 0x3820a000, - 0x3820c000, - 0x3820e000, - 0x38210000, - 0x38212000, - 0x38214000, - 0x38216000, - 0x38218000, - 0x3821a000, - 0x3821c000, - 0x3821e000, - 0x38220000, - 0x38222000, - 0x38224000, - 0x38226000, - 0x38228000, - 0x3822a000, - 0x3822c000, - 0x3822e000, - 0x38230000, - 0x38232000, - 0x38234000, - 0x38236000, - 0x38238000, - 0x3823a000, - 0x3823c000, - 0x3823e000, - 0x38240000, - 0x38242000, - 0x38244000, - 0x38246000, - 0x38248000, - 0x3824a000, - 0x3824c000, - 0x3824e000, - 0x38250000, - 0x38252000, - 0x38254000, - 0x38256000, - 0x38258000, - 0x3825a000, - 0x3825c000, - 0x3825e000, - 0x38260000, - 0x38262000, - 0x38264000, - 0x38266000, - 0x38268000, - 0x3826a000, - 0x3826c000, - 0x3826e000, - 0x38270000, - 0x38272000, - 0x38274000, - 0x38276000, - 0x38278000, - 0x3827a000, - 0x3827c000, - 0x3827e000, - 0x38280000, - 0x38282000, - 0x38284000, - 0x38286000, - 0x38288000, - 0x3828a000, - 0x3828c000, - 0x3828e000, - 0x38290000, - 0x38292000, - 0x38294000, - 0x38296000, - 0x38298000, - 0x3829a000, - 0x3829c000, - 0x3829e000, - 0x382a0000, - 0x382a2000, - 0x382a4000, - 0x382a6000, - 0x382a8000, - 0x382aa000, - 0x382ac000, - 0x382ae000, - 0x382b0000, - 0x382b2000, - 0x382b4000, - 0x382b6000, - 0x382b8000, - 0x382ba000, - 0x382bc000, - 0x382be000, - 0x382c0000, - 0x382c2000, - 0x382c4000, - 0x382c6000, - 0x382c8000, - 0x382ca000, - 0x382cc000, - 0x382ce000, - 0x382d0000, - 0x382d2000, - 0x382d4000, - 0x382d6000, - 0x382d8000, - 0x382da000, - 0x382dc000, - 0x382de000, - 0x382e0000, - 0x382e2000, - 0x382e4000, - 0x382e6000, - 0x382e8000, - 0x382ea000, - 0x382ec000, - 0x382ee000, - 0x382f0000, - 0x382f2000, - 0x382f4000, - 0x382f6000, - 0x382f8000, - 0x382fa000, - 0x382fc000, - 0x382fe000, - 0x38300000, - 0x38302000, - 0x38304000, - 0x38306000, - 0x38308000, - 0x3830a000, - 0x3830c000, - 0x3830e000, - 0x38310000, - 0x38312000, - 0x38314000, - 0x38316000, - 0x38318000, - 0x3831a000, - 0x3831c000, - 0x3831e000, - 0x38320000, - 0x38322000, - 0x38324000, - 0x38326000, - 0x38328000, - 0x3832a000, - 0x3832c000, - 0x3832e000, - 0x38330000, - 0x38332000, - 0x38334000, - 0x38336000, - 0x38338000, - 0x3833a000, - 0x3833c000, - 0x3833e000, - 0x38340000, - 0x38342000, - 0x38344000, - 0x38346000, - 0x38348000, - 0x3834a000, - 0x3834c000, - 0x3834e000, - 0x38350000, - 0x38352000, - 0x38354000, - 0x38356000, - 0x38358000, - 0x3835a000, - 0x3835c000, - 0x3835e000, - 0x38360000, - 0x38362000, - 0x38364000, - 0x38366000, - 0x38368000, - 0x3836a000, - 0x3836c000, - 0x3836e000, - 0x38370000, - 0x38372000, - 0x38374000, - 0x38376000, - 0x38378000, - 0x3837a000, - 0x3837c000, - 0x3837e000, - 0x38380000, - 0x38382000, - 0x38384000, - 0x38386000, - 0x38388000, - 0x3838a000, - 0x3838c000, - 0x3838e000, - 0x38390000, - 0x38392000, - 0x38394000, - 0x38396000, - 0x38398000, - 0x3839a000, - 0x3839c000, - 0x3839e000, - 0x383a0000, - 0x383a2000, - 0x383a4000, - 0x383a6000, - 0x383a8000, - 0x383aa000, - 0x383ac000, - 0x383ae000, - 0x383b0000, - 0x383b2000, - 0x383b4000, - 0x383b6000, - 0x383b8000, - 0x383ba000, - 0x383bc000, - 0x383be000, - 0x383c0000, - 0x383c2000, - 0x383c4000, - 0x383c6000, - 0x383c8000, - 0x383ca000, - 0x383cc000, - 0x383ce000, - 0x383d0000, - 0x383d2000, - 0x383d4000, - 0x383d6000, - 0x383d8000, - 0x383da000, - 0x383dc000, - 0x383de000, - 0x383e0000, - 0x383e2000, - 0x383e4000, - 0x383e6000, - 0x383e8000, - 0x383ea000, - 0x383ec000, - 0x383ee000, - 0x383f0000, - 0x383f2000, - 0x383f4000, - 0x383f6000, - 0x383f8000, - 0x383fa000, - 0x383fc000, - 0x383fe000, - 0x38400000, - 0x38402000, - 0x38404000, - 0x38406000, - 0x38408000, - 0x3840a000, - 0x3840c000, - 0x3840e000, - 0x38410000, - 0x38412000, - 0x38414000, - 0x38416000, - 0x38418000, - 0x3841a000, - 0x3841c000, - 0x3841e000, - 0x38420000, - 0x38422000, - 0x38424000, - 0x38426000, - 0x38428000, - 0x3842a000, - 0x3842c000, - 0x3842e000, - 0x38430000, - 0x38432000, - 0x38434000, - 0x38436000, - 0x38438000, - 0x3843a000, - 0x3843c000, - 0x3843e000, - 0x38440000, - 0x38442000, - 0x38444000, - 0x38446000, - 0x38448000, - 0x3844a000, - 0x3844c000, - 0x3844e000, - 0x38450000, - 0x38452000, - 0x38454000, - 0x38456000, - 0x38458000, - 0x3845a000, - 0x3845c000, - 0x3845e000, - 0x38460000, - 0x38462000, - 0x38464000, - 0x38466000, - 0x38468000, - 0x3846a000, - 0x3846c000, - 0x3846e000, - 0x38470000, - 0x38472000, - 0x38474000, - 0x38476000, - 0x38478000, - 0x3847a000, - 0x3847c000, - 0x3847e000, - 0x38480000, - 0x38482000, - 0x38484000, - 0x38486000, - 0x38488000, - 0x3848a000, - 0x3848c000, - 0x3848e000, - 0x38490000, - 0x38492000, - 0x38494000, - 0x38496000, - 0x38498000, - 0x3849a000, - 0x3849c000, - 0x3849e000, - 0x384a0000, - 0x384a2000, - 0x384a4000, - 0x384a6000, - 0x384a8000, - 0x384aa000, - 0x384ac000, - 0x384ae000, - 0x384b0000, - 0x384b2000, - 0x384b4000, - 0x384b6000, - 0x384b8000, - 0x384ba000, - 0x384bc000, - 0x384be000, - 0x384c0000, - 0x384c2000, - 0x384c4000, - 0x384c6000, - 0x384c8000, - 0x384ca000, - 0x384cc000, - 0x384ce000, - 0x384d0000, - 0x384d2000, - 0x384d4000, - 0x384d6000, - 0x384d8000, - 0x384da000, - 0x384dc000, - 0x384de000, - 0x384e0000, - 0x384e2000, - 0x384e4000, - 0x384e6000, - 0x384e8000, - 0x384ea000, - 0x384ec000, - 0x384ee000, - 0x384f0000, - 0x384f2000, - 0x384f4000, - 0x384f6000, - 0x384f8000, - 0x384fa000, - 0x384fc000, - 0x384fe000, - 0x38500000, - 0x38502000, - 0x38504000, - 0x38506000, - 0x38508000, - 0x3850a000, - 0x3850c000, - 0x3850e000, - 0x38510000, - 0x38512000, - 0x38514000, - 0x38516000, - 0x38518000, - 0x3851a000, - 0x3851c000, - 0x3851e000, - 0x38520000, - 0x38522000, - 0x38524000, - 0x38526000, - 0x38528000, - 0x3852a000, - 0x3852c000, - 0x3852e000, - 0x38530000, - 0x38532000, - 0x38534000, - 0x38536000, - 0x38538000, - 0x3853a000, - 0x3853c000, - 0x3853e000, - 0x38540000, - 0x38542000, - 0x38544000, - 0x38546000, - 0x38548000, - 0x3854a000, - 0x3854c000, - 0x3854e000, - 0x38550000, - 0x38552000, - 0x38554000, - 0x38556000, - 0x38558000, - 0x3855a000, - 0x3855c000, - 0x3855e000, - 0x38560000, - 0x38562000, - 0x38564000, - 0x38566000, - 0x38568000, - 0x3856a000, - 0x3856c000, - 0x3856e000, - 0x38570000, - 0x38572000, - 0x38574000, - 0x38576000, - 0x38578000, - 0x3857a000, - 0x3857c000, - 0x3857e000, - 0x38580000, - 0x38582000, - 0x38584000, - 0x38586000, - 0x38588000, - 0x3858a000, - 0x3858c000, - 0x3858e000, - 0x38590000, - 0x38592000, - 0x38594000, - 0x38596000, - 0x38598000, - 0x3859a000, - 0x3859c000, - 0x3859e000, - 0x385a0000, - 0x385a2000, - 0x385a4000, - 0x385a6000, - 0x385a8000, - 0x385aa000, - 0x385ac000, - 0x385ae000, - 0x385b0000, - 0x385b2000, - 0x385b4000, - 0x385b6000, - 0x385b8000, - 0x385ba000, - 0x385bc000, - 0x385be000, - 0x385c0000, - 0x385c2000, - 0x385c4000, - 0x385c6000, - 0x385c8000, - 0x385ca000, - 0x385cc000, - 0x385ce000, - 0x385d0000, - 0x385d2000, - 0x385d4000, - 0x385d6000, - 0x385d8000, - 0x385da000, - 0x385dc000, - 0x385de000, - 0x385e0000, - 0x385e2000, - 0x385e4000, - 0x385e6000, - 0x385e8000, - 0x385ea000, - 0x385ec000, - 0x385ee000, - 0x385f0000, - 0x385f2000, - 0x385f4000, - 0x385f6000, - 0x385f8000, - 0x385fa000, - 0x385fc000, - 0x385fe000, - 0x38600000, - 0x38602000, - 0x38604000, - 0x38606000, - 0x38608000, - 0x3860a000, - 0x3860c000, - 0x3860e000, - 0x38610000, - 0x38612000, - 0x38614000, - 0x38616000, - 0x38618000, - 0x3861a000, - 0x3861c000, - 0x3861e000, - 0x38620000, - 0x38622000, - 0x38624000, - 0x38626000, - 0x38628000, - 0x3862a000, - 0x3862c000, - 0x3862e000, - 0x38630000, - 0x38632000, - 0x38634000, - 0x38636000, - 0x38638000, - 0x3863a000, - 0x3863c000, - 0x3863e000, - 0x38640000, - 0x38642000, - 0x38644000, - 0x38646000, - 0x38648000, - 0x3864a000, - 0x3864c000, - 0x3864e000, - 0x38650000, - 0x38652000, - 0x38654000, - 0x38656000, - 0x38658000, - 0x3865a000, - 0x3865c000, - 0x3865e000, - 0x38660000, - 0x38662000, - 0x38664000, - 0x38666000, - 0x38668000, - 0x3866a000, - 0x3866c000, - 0x3866e000, - 0x38670000, - 0x38672000, - 0x38674000, - 0x38676000, - 0x38678000, - 0x3867a000, - 0x3867c000, - 0x3867e000, - 0x38680000, - 0x38682000, - 0x38684000, - 0x38686000, - 0x38688000, - 0x3868a000, - 0x3868c000, - 0x3868e000, - 0x38690000, - 0x38692000, - 0x38694000, - 0x38696000, - 0x38698000, - 0x3869a000, - 0x3869c000, - 0x3869e000, - 0x386a0000, - 0x386a2000, - 0x386a4000, - 0x386a6000, - 0x386a8000, - 0x386aa000, - 0x386ac000, - 0x386ae000, - 0x386b0000, - 0x386b2000, - 0x386b4000, - 0x386b6000, - 0x386b8000, - 0x386ba000, - 0x386bc000, - 0x386be000, - 0x386c0000, - 0x386c2000, - 0x386c4000, - 0x386c6000, - 0x386c8000, - 0x386ca000, - 0x386cc000, - 0x386ce000, - 0x386d0000, - 0x386d2000, - 0x386d4000, - 0x386d6000, - 0x386d8000, - 0x386da000, - 0x386dc000, - 0x386de000, - 0x386e0000, - 0x386e2000, - 0x386e4000, - 0x386e6000, - 0x386e8000, - 0x386ea000, - 0x386ec000, - 0x386ee000, - 0x386f0000, - 0x386f2000, - 0x386f4000, - 0x386f6000, - 0x386f8000, - 0x386fa000, - 0x386fc000, - 0x386fe000, - 0x38700000, - 0x38702000, - 0x38704000, - 0x38706000, - 0x38708000, - 0x3870a000, - 0x3870c000, - 0x3870e000, - 0x38710000, - 0x38712000, - 0x38714000, - 0x38716000, - 0x38718000, - 0x3871a000, - 0x3871c000, - 0x3871e000, - 0x38720000, - 0x38722000, - 0x38724000, - 0x38726000, - 0x38728000, - 0x3872a000, - 0x3872c000, - 0x3872e000, - 0x38730000, - 0x38732000, - 0x38734000, - 0x38736000, - 0x38738000, - 0x3873a000, - 0x3873c000, - 0x3873e000, - 0x38740000, - 0x38742000, - 0x38744000, - 0x38746000, - 0x38748000, - 0x3874a000, - 0x3874c000, - 0x3874e000, - 0x38750000, - 0x38752000, - 0x38754000, - 0x38756000, - 0x38758000, - 0x3875a000, - 0x3875c000, - 0x3875e000, - 0x38760000, - 0x38762000, - 0x38764000, - 0x38766000, - 0x38768000, - 0x3876a000, - 0x3876c000, - 0x3876e000, - 0x38770000, - 0x38772000, - 0x38774000, - 0x38776000, - 0x38778000, - 0x3877a000, - 0x3877c000, - 0x3877e000, - 0x38780000, - 0x38782000, - 0x38784000, - 0x38786000, - 0x38788000, - 0x3878a000, - 0x3878c000, - 0x3878e000, - 0x38790000, - 0x38792000, - 0x38794000, - 0x38796000, - 0x38798000, - 0x3879a000, - 0x3879c000, - 0x3879e000, - 0x387a0000, - 0x387a2000, - 0x387a4000, - 0x387a6000, - 0x387a8000, - 0x387aa000, - 0x387ac000, - 0x387ae000, - 0x387b0000, - 0x387b2000, - 0x387b4000, - 0x387b6000, - 0x387b8000, - 0x387ba000, - 0x387bc000, - 0x387be000, - 0x387c0000, - 0x387c2000, - 0x387c4000, - 0x387c6000, - 0x387c8000, - 0x387ca000, - 0x387cc000, - 0x387ce000, - 0x387d0000, - 0x387d2000, - 0x387d4000, - 0x387d6000, - 0x387d8000, - 0x387da000, - 0x387dc000, - 0x387de000, - 0x387e0000, - 0x387e2000, - 0x387e4000, - 0x387e6000, - 0x387e8000, - 0x387ea000, - 0x387ec000, - 0x387ee000, - 0x387f0000, - 0x387f2000, - 0x387f4000, - 0x387f6000, - 0x387f8000, - 0x387fa000, - 0x387fc000, - 0x387fe000, -}; - -const static unsigned g_exponent[64] = { - 0x00000000, - 0x00800000, - 0x01000000, - 0x01800000, - 0x02000000, - 0x02800000, - 0x03000000, - 0x03800000, - 0x04000000, - 0x04800000, - 0x05000000, - 0x05800000, - 0x06000000, - 0x06800000, - 0x07000000, - 0x07800000, - 0x08000000, - 0x08800000, - 0x09000000, - 0x09800000, - 0x0a000000, - 0x0a800000, - 0x0b000000, - 0x0b800000, - 0x0c000000, - 0x0c800000, - 0x0d000000, - 0x0d800000, - 0x0e000000, - 0x0e800000, - 0x0f000000, - 0x47800000, - 0x80000000, - 0x80800000, - 0x81000000, - 0x81800000, - 0x82000000, - 0x82800000, - 0x83000000, - 0x83800000, - 0x84000000, - 0x84800000, - 0x85000000, - 0x85800000, - 0x86000000, - 0x86800000, - 0x87000000, - 0x87800000, - 0x88000000, - 0x88800000, - 0x89000000, - 0x89800000, - 0x8a000000, - 0x8a800000, - 0x8b000000, - 0x8b800000, - 0x8c000000, - 0x8c800000, - 0x8d000000, - 0x8d800000, - 0x8e000000, - 0x8e800000, - 0x8f000000, - 0xc7800000, -}; - -const static unsigned g_offset[64] = { - 0x00000000, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000000, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, -}; - -float float16ToFloat32(unsigned short h) -{ - unsigned i32 = g_mantissa[g_offset[h >> 10] + (h & 0x3ff)] + g_exponent[h >> 10]; - return *(float*) &i32; -} -} - +#include "precompiled.h" +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// This file is automatically generated. + +namespace gl +{ + +const static unsigned g_mantissa[2048] = { + 0x00000000, + 0x33800000, + 0x34000000, + 0x34400000, + 0x34800000, + 0x34a00000, + 0x34c00000, + 0x34e00000, + 0x35000000, + 0x35100000, + 0x35200000, + 0x35300000, + 0x35400000, + 0x35500000, + 0x35600000, + 0x35700000, + 0x35800000, + 0x35880000, + 0x35900000, + 0x35980000, + 0x35a00000, + 0x35a80000, + 0x35b00000, + 0x35b80000, + 0x35c00000, + 0x35c80000, + 0x35d00000, + 0x35d80000, + 0x35e00000, + 0x35e80000, + 0x35f00000, + 0x35f80000, + 0x36000000, + 0x36040000, + 0x36080000, + 0x360c0000, + 0x36100000, + 0x36140000, + 0x36180000, + 0x361c0000, + 0x36200000, + 0x36240000, + 0x36280000, + 0x362c0000, + 0x36300000, + 0x36340000, + 0x36380000, + 0x363c0000, + 0x36400000, + 0x36440000, + 0x36480000, + 0x364c0000, + 0x36500000, + 0x36540000, + 0x36580000, + 0x365c0000, + 0x36600000, + 0x36640000, + 0x36680000, + 0x366c0000, + 0x36700000, + 0x36740000, + 0x36780000, + 0x367c0000, + 0x36800000, + 0x36820000, + 0x36840000, + 0x36860000, + 0x36880000, + 0x368a0000, + 0x368c0000, + 0x368e0000, + 0x36900000, + 0x36920000, + 0x36940000, + 0x36960000, + 0x36980000, + 0x369a0000, + 0x369c0000, + 0x369e0000, + 0x36a00000, + 0x36a20000, + 0x36a40000, + 0x36a60000, + 0x36a80000, + 0x36aa0000, + 0x36ac0000, + 0x36ae0000, + 0x36b00000, + 0x36b20000, + 0x36b40000, + 0x36b60000, + 0x36b80000, + 0x36ba0000, + 0x36bc0000, + 0x36be0000, + 0x36c00000, + 0x36c20000, + 0x36c40000, + 0x36c60000, + 0x36c80000, + 0x36ca0000, + 0x36cc0000, + 0x36ce0000, + 0x36d00000, + 0x36d20000, + 0x36d40000, + 0x36d60000, + 0x36d80000, + 0x36da0000, + 0x36dc0000, + 0x36de0000, + 0x36e00000, + 0x36e20000, + 0x36e40000, + 0x36e60000, + 0x36e80000, + 0x36ea0000, + 0x36ec0000, + 0x36ee0000, + 0x36f00000, + 0x36f20000, + 0x36f40000, + 0x36f60000, + 0x36f80000, + 0x36fa0000, + 0x36fc0000, + 0x36fe0000, + 0x37000000, + 0x37010000, + 0x37020000, + 0x37030000, + 0x37040000, + 0x37050000, + 0x37060000, + 0x37070000, + 0x37080000, + 0x37090000, + 0x370a0000, + 0x370b0000, + 0x370c0000, + 0x370d0000, + 0x370e0000, + 0x370f0000, + 0x37100000, + 0x37110000, + 0x37120000, + 0x37130000, + 0x37140000, + 0x37150000, + 0x37160000, + 0x37170000, + 0x37180000, + 0x37190000, + 0x371a0000, + 0x371b0000, + 0x371c0000, + 0x371d0000, + 0x371e0000, + 0x371f0000, + 0x37200000, + 0x37210000, + 0x37220000, + 0x37230000, + 0x37240000, + 0x37250000, + 0x37260000, + 0x37270000, + 0x37280000, + 0x37290000, + 0x372a0000, + 0x372b0000, + 0x372c0000, + 0x372d0000, + 0x372e0000, + 0x372f0000, + 0x37300000, + 0x37310000, + 0x37320000, + 0x37330000, + 0x37340000, + 0x37350000, + 0x37360000, + 0x37370000, + 0x37380000, + 0x37390000, + 0x373a0000, + 0x373b0000, + 0x373c0000, + 0x373d0000, + 0x373e0000, + 0x373f0000, + 0x37400000, + 0x37410000, + 0x37420000, + 0x37430000, + 0x37440000, + 0x37450000, + 0x37460000, + 0x37470000, + 0x37480000, + 0x37490000, + 0x374a0000, + 0x374b0000, + 0x374c0000, + 0x374d0000, + 0x374e0000, + 0x374f0000, + 0x37500000, + 0x37510000, + 0x37520000, + 0x37530000, + 0x37540000, + 0x37550000, + 0x37560000, + 0x37570000, + 0x37580000, + 0x37590000, + 0x375a0000, + 0x375b0000, + 0x375c0000, + 0x375d0000, + 0x375e0000, + 0x375f0000, + 0x37600000, + 0x37610000, + 0x37620000, + 0x37630000, + 0x37640000, + 0x37650000, + 0x37660000, + 0x37670000, + 0x37680000, + 0x37690000, + 0x376a0000, + 0x376b0000, + 0x376c0000, + 0x376d0000, + 0x376e0000, + 0x376f0000, + 0x37700000, + 0x37710000, + 0x37720000, + 0x37730000, + 0x37740000, + 0x37750000, + 0x37760000, + 0x37770000, + 0x37780000, + 0x37790000, + 0x377a0000, + 0x377b0000, + 0x377c0000, + 0x377d0000, + 0x377e0000, + 0x377f0000, + 0x37800000, + 0x37808000, + 0x37810000, + 0x37818000, + 0x37820000, + 0x37828000, + 0x37830000, + 0x37838000, + 0x37840000, + 0x37848000, + 0x37850000, + 0x37858000, + 0x37860000, + 0x37868000, + 0x37870000, + 0x37878000, + 0x37880000, + 0x37888000, + 0x37890000, + 0x37898000, + 0x378a0000, + 0x378a8000, + 0x378b0000, + 0x378b8000, + 0x378c0000, + 0x378c8000, + 0x378d0000, + 0x378d8000, + 0x378e0000, + 0x378e8000, + 0x378f0000, + 0x378f8000, + 0x37900000, + 0x37908000, + 0x37910000, + 0x37918000, + 0x37920000, + 0x37928000, + 0x37930000, + 0x37938000, + 0x37940000, + 0x37948000, + 0x37950000, + 0x37958000, + 0x37960000, + 0x37968000, + 0x37970000, + 0x37978000, + 0x37980000, + 0x37988000, + 0x37990000, + 0x37998000, + 0x379a0000, + 0x379a8000, + 0x379b0000, + 0x379b8000, + 0x379c0000, + 0x379c8000, + 0x379d0000, + 0x379d8000, + 0x379e0000, + 0x379e8000, + 0x379f0000, + 0x379f8000, + 0x37a00000, + 0x37a08000, + 0x37a10000, + 0x37a18000, + 0x37a20000, + 0x37a28000, + 0x37a30000, + 0x37a38000, + 0x37a40000, + 0x37a48000, + 0x37a50000, + 0x37a58000, + 0x37a60000, + 0x37a68000, + 0x37a70000, + 0x37a78000, + 0x37a80000, + 0x37a88000, + 0x37a90000, + 0x37a98000, + 0x37aa0000, + 0x37aa8000, + 0x37ab0000, + 0x37ab8000, + 0x37ac0000, + 0x37ac8000, + 0x37ad0000, + 0x37ad8000, + 0x37ae0000, + 0x37ae8000, + 0x37af0000, + 0x37af8000, + 0x37b00000, + 0x37b08000, + 0x37b10000, + 0x37b18000, + 0x37b20000, + 0x37b28000, + 0x37b30000, + 0x37b38000, + 0x37b40000, + 0x37b48000, + 0x37b50000, + 0x37b58000, + 0x37b60000, + 0x37b68000, + 0x37b70000, + 0x37b78000, + 0x37b80000, + 0x37b88000, + 0x37b90000, + 0x37b98000, + 0x37ba0000, + 0x37ba8000, + 0x37bb0000, + 0x37bb8000, + 0x37bc0000, + 0x37bc8000, + 0x37bd0000, + 0x37bd8000, + 0x37be0000, + 0x37be8000, + 0x37bf0000, + 0x37bf8000, + 0x37c00000, + 0x37c08000, + 0x37c10000, + 0x37c18000, + 0x37c20000, + 0x37c28000, + 0x37c30000, + 0x37c38000, + 0x37c40000, + 0x37c48000, + 0x37c50000, + 0x37c58000, + 0x37c60000, + 0x37c68000, + 0x37c70000, + 0x37c78000, + 0x37c80000, + 0x37c88000, + 0x37c90000, + 0x37c98000, + 0x37ca0000, + 0x37ca8000, + 0x37cb0000, + 0x37cb8000, + 0x37cc0000, + 0x37cc8000, + 0x37cd0000, + 0x37cd8000, + 0x37ce0000, + 0x37ce8000, + 0x37cf0000, + 0x37cf8000, + 0x37d00000, + 0x37d08000, + 0x37d10000, + 0x37d18000, + 0x37d20000, + 0x37d28000, + 0x37d30000, + 0x37d38000, + 0x37d40000, + 0x37d48000, + 0x37d50000, + 0x37d58000, + 0x37d60000, + 0x37d68000, + 0x37d70000, + 0x37d78000, + 0x37d80000, + 0x37d88000, + 0x37d90000, + 0x37d98000, + 0x37da0000, + 0x37da8000, + 0x37db0000, + 0x37db8000, + 0x37dc0000, + 0x37dc8000, + 0x37dd0000, + 0x37dd8000, + 0x37de0000, + 0x37de8000, + 0x37df0000, + 0x37df8000, + 0x37e00000, + 0x37e08000, + 0x37e10000, + 0x37e18000, + 0x37e20000, + 0x37e28000, + 0x37e30000, + 0x37e38000, + 0x37e40000, + 0x37e48000, + 0x37e50000, + 0x37e58000, + 0x37e60000, + 0x37e68000, + 0x37e70000, + 0x37e78000, + 0x37e80000, + 0x37e88000, + 0x37e90000, + 0x37e98000, + 0x37ea0000, + 0x37ea8000, + 0x37eb0000, + 0x37eb8000, + 0x37ec0000, + 0x37ec8000, + 0x37ed0000, + 0x37ed8000, + 0x37ee0000, + 0x37ee8000, + 0x37ef0000, + 0x37ef8000, + 0x37f00000, + 0x37f08000, + 0x37f10000, + 0x37f18000, + 0x37f20000, + 0x37f28000, + 0x37f30000, + 0x37f38000, + 0x37f40000, + 0x37f48000, + 0x37f50000, + 0x37f58000, + 0x37f60000, + 0x37f68000, + 0x37f70000, + 0x37f78000, + 0x37f80000, + 0x37f88000, + 0x37f90000, + 0x37f98000, + 0x37fa0000, + 0x37fa8000, + 0x37fb0000, + 0x37fb8000, + 0x37fc0000, + 0x37fc8000, + 0x37fd0000, + 0x37fd8000, + 0x37fe0000, + 0x37fe8000, + 0x37ff0000, + 0x37ff8000, + 0x38000000, + 0x38004000, + 0x38008000, + 0x3800c000, + 0x38010000, + 0x38014000, + 0x38018000, + 0x3801c000, + 0x38020000, + 0x38024000, + 0x38028000, + 0x3802c000, + 0x38030000, + 0x38034000, + 0x38038000, + 0x3803c000, + 0x38040000, + 0x38044000, + 0x38048000, + 0x3804c000, + 0x38050000, + 0x38054000, + 0x38058000, + 0x3805c000, + 0x38060000, + 0x38064000, + 0x38068000, + 0x3806c000, + 0x38070000, + 0x38074000, + 0x38078000, + 0x3807c000, + 0x38080000, + 0x38084000, + 0x38088000, + 0x3808c000, + 0x38090000, + 0x38094000, + 0x38098000, + 0x3809c000, + 0x380a0000, + 0x380a4000, + 0x380a8000, + 0x380ac000, + 0x380b0000, + 0x380b4000, + 0x380b8000, + 0x380bc000, + 0x380c0000, + 0x380c4000, + 0x380c8000, + 0x380cc000, + 0x380d0000, + 0x380d4000, + 0x380d8000, + 0x380dc000, + 0x380e0000, + 0x380e4000, + 0x380e8000, + 0x380ec000, + 0x380f0000, + 0x380f4000, + 0x380f8000, + 0x380fc000, + 0x38100000, + 0x38104000, + 0x38108000, + 0x3810c000, + 0x38110000, + 0x38114000, + 0x38118000, + 0x3811c000, + 0x38120000, + 0x38124000, + 0x38128000, + 0x3812c000, + 0x38130000, + 0x38134000, + 0x38138000, + 0x3813c000, + 0x38140000, + 0x38144000, + 0x38148000, + 0x3814c000, + 0x38150000, + 0x38154000, + 0x38158000, + 0x3815c000, + 0x38160000, + 0x38164000, + 0x38168000, + 0x3816c000, + 0x38170000, + 0x38174000, + 0x38178000, + 0x3817c000, + 0x38180000, + 0x38184000, + 0x38188000, + 0x3818c000, + 0x38190000, + 0x38194000, + 0x38198000, + 0x3819c000, + 0x381a0000, + 0x381a4000, + 0x381a8000, + 0x381ac000, + 0x381b0000, + 0x381b4000, + 0x381b8000, + 0x381bc000, + 0x381c0000, + 0x381c4000, + 0x381c8000, + 0x381cc000, + 0x381d0000, + 0x381d4000, + 0x381d8000, + 0x381dc000, + 0x381e0000, + 0x381e4000, + 0x381e8000, + 0x381ec000, + 0x381f0000, + 0x381f4000, + 0x381f8000, + 0x381fc000, + 0x38200000, + 0x38204000, + 0x38208000, + 0x3820c000, + 0x38210000, + 0x38214000, + 0x38218000, + 0x3821c000, + 0x38220000, + 0x38224000, + 0x38228000, + 0x3822c000, + 0x38230000, + 0x38234000, + 0x38238000, + 0x3823c000, + 0x38240000, + 0x38244000, + 0x38248000, + 0x3824c000, + 0x38250000, + 0x38254000, + 0x38258000, + 0x3825c000, + 0x38260000, + 0x38264000, + 0x38268000, + 0x3826c000, + 0x38270000, + 0x38274000, + 0x38278000, + 0x3827c000, + 0x38280000, + 0x38284000, + 0x38288000, + 0x3828c000, + 0x38290000, + 0x38294000, + 0x38298000, + 0x3829c000, + 0x382a0000, + 0x382a4000, + 0x382a8000, + 0x382ac000, + 0x382b0000, + 0x382b4000, + 0x382b8000, + 0x382bc000, + 0x382c0000, + 0x382c4000, + 0x382c8000, + 0x382cc000, + 0x382d0000, + 0x382d4000, + 0x382d8000, + 0x382dc000, + 0x382e0000, + 0x382e4000, + 0x382e8000, + 0x382ec000, + 0x382f0000, + 0x382f4000, + 0x382f8000, + 0x382fc000, + 0x38300000, + 0x38304000, + 0x38308000, + 0x3830c000, + 0x38310000, + 0x38314000, + 0x38318000, + 0x3831c000, + 0x38320000, + 0x38324000, + 0x38328000, + 0x3832c000, + 0x38330000, + 0x38334000, + 0x38338000, + 0x3833c000, + 0x38340000, + 0x38344000, + 0x38348000, + 0x3834c000, + 0x38350000, + 0x38354000, + 0x38358000, + 0x3835c000, + 0x38360000, + 0x38364000, + 0x38368000, + 0x3836c000, + 0x38370000, + 0x38374000, + 0x38378000, + 0x3837c000, + 0x38380000, + 0x38384000, + 0x38388000, + 0x3838c000, + 0x38390000, + 0x38394000, + 0x38398000, + 0x3839c000, + 0x383a0000, + 0x383a4000, + 0x383a8000, + 0x383ac000, + 0x383b0000, + 0x383b4000, + 0x383b8000, + 0x383bc000, + 0x383c0000, + 0x383c4000, + 0x383c8000, + 0x383cc000, + 0x383d0000, + 0x383d4000, + 0x383d8000, + 0x383dc000, + 0x383e0000, + 0x383e4000, + 0x383e8000, + 0x383ec000, + 0x383f0000, + 0x383f4000, + 0x383f8000, + 0x383fc000, + 0x38400000, + 0x38404000, + 0x38408000, + 0x3840c000, + 0x38410000, + 0x38414000, + 0x38418000, + 0x3841c000, + 0x38420000, + 0x38424000, + 0x38428000, + 0x3842c000, + 0x38430000, + 0x38434000, + 0x38438000, + 0x3843c000, + 0x38440000, + 0x38444000, + 0x38448000, + 0x3844c000, + 0x38450000, + 0x38454000, + 0x38458000, + 0x3845c000, + 0x38460000, + 0x38464000, + 0x38468000, + 0x3846c000, + 0x38470000, + 0x38474000, + 0x38478000, + 0x3847c000, + 0x38480000, + 0x38484000, + 0x38488000, + 0x3848c000, + 0x38490000, + 0x38494000, + 0x38498000, + 0x3849c000, + 0x384a0000, + 0x384a4000, + 0x384a8000, + 0x384ac000, + 0x384b0000, + 0x384b4000, + 0x384b8000, + 0x384bc000, + 0x384c0000, + 0x384c4000, + 0x384c8000, + 0x384cc000, + 0x384d0000, + 0x384d4000, + 0x384d8000, + 0x384dc000, + 0x384e0000, + 0x384e4000, + 0x384e8000, + 0x384ec000, + 0x384f0000, + 0x384f4000, + 0x384f8000, + 0x384fc000, + 0x38500000, + 0x38504000, + 0x38508000, + 0x3850c000, + 0x38510000, + 0x38514000, + 0x38518000, + 0x3851c000, + 0x38520000, + 0x38524000, + 0x38528000, + 0x3852c000, + 0x38530000, + 0x38534000, + 0x38538000, + 0x3853c000, + 0x38540000, + 0x38544000, + 0x38548000, + 0x3854c000, + 0x38550000, + 0x38554000, + 0x38558000, + 0x3855c000, + 0x38560000, + 0x38564000, + 0x38568000, + 0x3856c000, + 0x38570000, + 0x38574000, + 0x38578000, + 0x3857c000, + 0x38580000, + 0x38584000, + 0x38588000, + 0x3858c000, + 0x38590000, + 0x38594000, + 0x38598000, + 0x3859c000, + 0x385a0000, + 0x385a4000, + 0x385a8000, + 0x385ac000, + 0x385b0000, + 0x385b4000, + 0x385b8000, + 0x385bc000, + 0x385c0000, + 0x385c4000, + 0x385c8000, + 0x385cc000, + 0x385d0000, + 0x385d4000, + 0x385d8000, + 0x385dc000, + 0x385e0000, + 0x385e4000, + 0x385e8000, + 0x385ec000, + 0x385f0000, + 0x385f4000, + 0x385f8000, + 0x385fc000, + 0x38600000, + 0x38604000, + 0x38608000, + 0x3860c000, + 0x38610000, + 0x38614000, + 0x38618000, + 0x3861c000, + 0x38620000, + 0x38624000, + 0x38628000, + 0x3862c000, + 0x38630000, + 0x38634000, + 0x38638000, + 0x3863c000, + 0x38640000, + 0x38644000, + 0x38648000, + 0x3864c000, + 0x38650000, + 0x38654000, + 0x38658000, + 0x3865c000, + 0x38660000, + 0x38664000, + 0x38668000, + 0x3866c000, + 0x38670000, + 0x38674000, + 0x38678000, + 0x3867c000, + 0x38680000, + 0x38684000, + 0x38688000, + 0x3868c000, + 0x38690000, + 0x38694000, + 0x38698000, + 0x3869c000, + 0x386a0000, + 0x386a4000, + 0x386a8000, + 0x386ac000, + 0x386b0000, + 0x386b4000, + 0x386b8000, + 0x386bc000, + 0x386c0000, + 0x386c4000, + 0x386c8000, + 0x386cc000, + 0x386d0000, + 0x386d4000, + 0x386d8000, + 0x386dc000, + 0x386e0000, + 0x386e4000, + 0x386e8000, + 0x386ec000, + 0x386f0000, + 0x386f4000, + 0x386f8000, + 0x386fc000, + 0x38700000, + 0x38704000, + 0x38708000, + 0x3870c000, + 0x38710000, + 0x38714000, + 0x38718000, + 0x3871c000, + 0x38720000, + 0x38724000, + 0x38728000, + 0x3872c000, + 0x38730000, + 0x38734000, + 0x38738000, + 0x3873c000, + 0x38740000, + 0x38744000, + 0x38748000, + 0x3874c000, + 0x38750000, + 0x38754000, + 0x38758000, + 0x3875c000, + 0x38760000, + 0x38764000, + 0x38768000, + 0x3876c000, + 0x38770000, + 0x38774000, + 0x38778000, + 0x3877c000, + 0x38780000, + 0x38784000, + 0x38788000, + 0x3878c000, + 0x38790000, + 0x38794000, + 0x38798000, + 0x3879c000, + 0x387a0000, + 0x387a4000, + 0x387a8000, + 0x387ac000, + 0x387b0000, + 0x387b4000, + 0x387b8000, + 0x387bc000, + 0x387c0000, + 0x387c4000, + 0x387c8000, + 0x387cc000, + 0x387d0000, + 0x387d4000, + 0x387d8000, + 0x387dc000, + 0x387e0000, + 0x387e4000, + 0x387e8000, + 0x387ec000, + 0x387f0000, + 0x387f4000, + 0x387f8000, + 0x387fc000, + 0x38000000, + 0x38002000, + 0x38004000, + 0x38006000, + 0x38008000, + 0x3800a000, + 0x3800c000, + 0x3800e000, + 0x38010000, + 0x38012000, + 0x38014000, + 0x38016000, + 0x38018000, + 0x3801a000, + 0x3801c000, + 0x3801e000, + 0x38020000, + 0x38022000, + 0x38024000, + 0x38026000, + 0x38028000, + 0x3802a000, + 0x3802c000, + 0x3802e000, + 0x38030000, + 0x38032000, + 0x38034000, + 0x38036000, + 0x38038000, + 0x3803a000, + 0x3803c000, + 0x3803e000, + 0x38040000, + 0x38042000, + 0x38044000, + 0x38046000, + 0x38048000, + 0x3804a000, + 0x3804c000, + 0x3804e000, + 0x38050000, + 0x38052000, + 0x38054000, + 0x38056000, + 0x38058000, + 0x3805a000, + 0x3805c000, + 0x3805e000, + 0x38060000, + 0x38062000, + 0x38064000, + 0x38066000, + 0x38068000, + 0x3806a000, + 0x3806c000, + 0x3806e000, + 0x38070000, + 0x38072000, + 0x38074000, + 0x38076000, + 0x38078000, + 0x3807a000, + 0x3807c000, + 0x3807e000, + 0x38080000, + 0x38082000, + 0x38084000, + 0x38086000, + 0x38088000, + 0x3808a000, + 0x3808c000, + 0x3808e000, + 0x38090000, + 0x38092000, + 0x38094000, + 0x38096000, + 0x38098000, + 0x3809a000, + 0x3809c000, + 0x3809e000, + 0x380a0000, + 0x380a2000, + 0x380a4000, + 0x380a6000, + 0x380a8000, + 0x380aa000, + 0x380ac000, + 0x380ae000, + 0x380b0000, + 0x380b2000, + 0x380b4000, + 0x380b6000, + 0x380b8000, + 0x380ba000, + 0x380bc000, + 0x380be000, + 0x380c0000, + 0x380c2000, + 0x380c4000, + 0x380c6000, + 0x380c8000, + 0x380ca000, + 0x380cc000, + 0x380ce000, + 0x380d0000, + 0x380d2000, + 0x380d4000, + 0x380d6000, + 0x380d8000, + 0x380da000, + 0x380dc000, + 0x380de000, + 0x380e0000, + 0x380e2000, + 0x380e4000, + 0x380e6000, + 0x380e8000, + 0x380ea000, + 0x380ec000, + 0x380ee000, + 0x380f0000, + 0x380f2000, + 0x380f4000, + 0x380f6000, + 0x380f8000, + 0x380fa000, + 0x380fc000, + 0x380fe000, + 0x38100000, + 0x38102000, + 0x38104000, + 0x38106000, + 0x38108000, + 0x3810a000, + 0x3810c000, + 0x3810e000, + 0x38110000, + 0x38112000, + 0x38114000, + 0x38116000, + 0x38118000, + 0x3811a000, + 0x3811c000, + 0x3811e000, + 0x38120000, + 0x38122000, + 0x38124000, + 0x38126000, + 0x38128000, + 0x3812a000, + 0x3812c000, + 0x3812e000, + 0x38130000, + 0x38132000, + 0x38134000, + 0x38136000, + 0x38138000, + 0x3813a000, + 0x3813c000, + 0x3813e000, + 0x38140000, + 0x38142000, + 0x38144000, + 0x38146000, + 0x38148000, + 0x3814a000, + 0x3814c000, + 0x3814e000, + 0x38150000, + 0x38152000, + 0x38154000, + 0x38156000, + 0x38158000, + 0x3815a000, + 0x3815c000, + 0x3815e000, + 0x38160000, + 0x38162000, + 0x38164000, + 0x38166000, + 0x38168000, + 0x3816a000, + 0x3816c000, + 0x3816e000, + 0x38170000, + 0x38172000, + 0x38174000, + 0x38176000, + 0x38178000, + 0x3817a000, + 0x3817c000, + 0x3817e000, + 0x38180000, + 0x38182000, + 0x38184000, + 0x38186000, + 0x38188000, + 0x3818a000, + 0x3818c000, + 0x3818e000, + 0x38190000, + 0x38192000, + 0x38194000, + 0x38196000, + 0x38198000, + 0x3819a000, + 0x3819c000, + 0x3819e000, + 0x381a0000, + 0x381a2000, + 0x381a4000, + 0x381a6000, + 0x381a8000, + 0x381aa000, + 0x381ac000, + 0x381ae000, + 0x381b0000, + 0x381b2000, + 0x381b4000, + 0x381b6000, + 0x381b8000, + 0x381ba000, + 0x381bc000, + 0x381be000, + 0x381c0000, + 0x381c2000, + 0x381c4000, + 0x381c6000, + 0x381c8000, + 0x381ca000, + 0x381cc000, + 0x381ce000, + 0x381d0000, + 0x381d2000, + 0x381d4000, + 0x381d6000, + 0x381d8000, + 0x381da000, + 0x381dc000, + 0x381de000, + 0x381e0000, + 0x381e2000, + 0x381e4000, + 0x381e6000, + 0x381e8000, + 0x381ea000, + 0x381ec000, + 0x381ee000, + 0x381f0000, + 0x381f2000, + 0x381f4000, + 0x381f6000, + 0x381f8000, + 0x381fa000, + 0x381fc000, + 0x381fe000, + 0x38200000, + 0x38202000, + 0x38204000, + 0x38206000, + 0x38208000, + 0x3820a000, + 0x3820c000, + 0x3820e000, + 0x38210000, + 0x38212000, + 0x38214000, + 0x38216000, + 0x38218000, + 0x3821a000, + 0x3821c000, + 0x3821e000, + 0x38220000, + 0x38222000, + 0x38224000, + 0x38226000, + 0x38228000, + 0x3822a000, + 0x3822c000, + 0x3822e000, + 0x38230000, + 0x38232000, + 0x38234000, + 0x38236000, + 0x38238000, + 0x3823a000, + 0x3823c000, + 0x3823e000, + 0x38240000, + 0x38242000, + 0x38244000, + 0x38246000, + 0x38248000, + 0x3824a000, + 0x3824c000, + 0x3824e000, + 0x38250000, + 0x38252000, + 0x38254000, + 0x38256000, + 0x38258000, + 0x3825a000, + 0x3825c000, + 0x3825e000, + 0x38260000, + 0x38262000, + 0x38264000, + 0x38266000, + 0x38268000, + 0x3826a000, + 0x3826c000, + 0x3826e000, + 0x38270000, + 0x38272000, + 0x38274000, + 0x38276000, + 0x38278000, + 0x3827a000, + 0x3827c000, + 0x3827e000, + 0x38280000, + 0x38282000, + 0x38284000, + 0x38286000, + 0x38288000, + 0x3828a000, + 0x3828c000, + 0x3828e000, + 0x38290000, + 0x38292000, + 0x38294000, + 0x38296000, + 0x38298000, + 0x3829a000, + 0x3829c000, + 0x3829e000, + 0x382a0000, + 0x382a2000, + 0x382a4000, + 0x382a6000, + 0x382a8000, + 0x382aa000, + 0x382ac000, + 0x382ae000, + 0x382b0000, + 0x382b2000, + 0x382b4000, + 0x382b6000, + 0x382b8000, + 0x382ba000, + 0x382bc000, + 0x382be000, + 0x382c0000, + 0x382c2000, + 0x382c4000, + 0x382c6000, + 0x382c8000, + 0x382ca000, + 0x382cc000, + 0x382ce000, + 0x382d0000, + 0x382d2000, + 0x382d4000, + 0x382d6000, + 0x382d8000, + 0x382da000, + 0x382dc000, + 0x382de000, + 0x382e0000, + 0x382e2000, + 0x382e4000, + 0x382e6000, + 0x382e8000, + 0x382ea000, + 0x382ec000, + 0x382ee000, + 0x382f0000, + 0x382f2000, + 0x382f4000, + 0x382f6000, + 0x382f8000, + 0x382fa000, + 0x382fc000, + 0x382fe000, + 0x38300000, + 0x38302000, + 0x38304000, + 0x38306000, + 0x38308000, + 0x3830a000, + 0x3830c000, + 0x3830e000, + 0x38310000, + 0x38312000, + 0x38314000, + 0x38316000, + 0x38318000, + 0x3831a000, + 0x3831c000, + 0x3831e000, + 0x38320000, + 0x38322000, + 0x38324000, + 0x38326000, + 0x38328000, + 0x3832a000, + 0x3832c000, + 0x3832e000, + 0x38330000, + 0x38332000, + 0x38334000, + 0x38336000, + 0x38338000, + 0x3833a000, + 0x3833c000, + 0x3833e000, + 0x38340000, + 0x38342000, + 0x38344000, + 0x38346000, + 0x38348000, + 0x3834a000, + 0x3834c000, + 0x3834e000, + 0x38350000, + 0x38352000, + 0x38354000, + 0x38356000, + 0x38358000, + 0x3835a000, + 0x3835c000, + 0x3835e000, + 0x38360000, + 0x38362000, + 0x38364000, + 0x38366000, + 0x38368000, + 0x3836a000, + 0x3836c000, + 0x3836e000, + 0x38370000, + 0x38372000, + 0x38374000, + 0x38376000, + 0x38378000, + 0x3837a000, + 0x3837c000, + 0x3837e000, + 0x38380000, + 0x38382000, + 0x38384000, + 0x38386000, + 0x38388000, + 0x3838a000, + 0x3838c000, + 0x3838e000, + 0x38390000, + 0x38392000, + 0x38394000, + 0x38396000, + 0x38398000, + 0x3839a000, + 0x3839c000, + 0x3839e000, + 0x383a0000, + 0x383a2000, + 0x383a4000, + 0x383a6000, + 0x383a8000, + 0x383aa000, + 0x383ac000, + 0x383ae000, + 0x383b0000, + 0x383b2000, + 0x383b4000, + 0x383b6000, + 0x383b8000, + 0x383ba000, + 0x383bc000, + 0x383be000, + 0x383c0000, + 0x383c2000, + 0x383c4000, + 0x383c6000, + 0x383c8000, + 0x383ca000, + 0x383cc000, + 0x383ce000, + 0x383d0000, + 0x383d2000, + 0x383d4000, + 0x383d6000, + 0x383d8000, + 0x383da000, + 0x383dc000, + 0x383de000, + 0x383e0000, + 0x383e2000, + 0x383e4000, + 0x383e6000, + 0x383e8000, + 0x383ea000, + 0x383ec000, + 0x383ee000, + 0x383f0000, + 0x383f2000, + 0x383f4000, + 0x383f6000, + 0x383f8000, + 0x383fa000, + 0x383fc000, + 0x383fe000, + 0x38400000, + 0x38402000, + 0x38404000, + 0x38406000, + 0x38408000, + 0x3840a000, + 0x3840c000, + 0x3840e000, + 0x38410000, + 0x38412000, + 0x38414000, + 0x38416000, + 0x38418000, + 0x3841a000, + 0x3841c000, + 0x3841e000, + 0x38420000, + 0x38422000, + 0x38424000, + 0x38426000, + 0x38428000, + 0x3842a000, + 0x3842c000, + 0x3842e000, + 0x38430000, + 0x38432000, + 0x38434000, + 0x38436000, + 0x38438000, + 0x3843a000, + 0x3843c000, + 0x3843e000, + 0x38440000, + 0x38442000, + 0x38444000, + 0x38446000, + 0x38448000, + 0x3844a000, + 0x3844c000, + 0x3844e000, + 0x38450000, + 0x38452000, + 0x38454000, + 0x38456000, + 0x38458000, + 0x3845a000, + 0x3845c000, + 0x3845e000, + 0x38460000, + 0x38462000, + 0x38464000, + 0x38466000, + 0x38468000, + 0x3846a000, + 0x3846c000, + 0x3846e000, + 0x38470000, + 0x38472000, + 0x38474000, + 0x38476000, + 0x38478000, + 0x3847a000, + 0x3847c000, + 0x3847e000, + 0x38480000, + 0x38482000, + 0x38484000, + 0x38486000, + 0x38488000, + 0x3848a000, + 0x3848c000, + 0x3848e000, + 0x38490000, + 0x38492000, + 0x38494000, + 0x38496000, + 0x38498000, + 0x3849a000, + 0x3849c000, + 0x3849e000, + 0x384a0000, + 0x384a2000, + 0x384a4000, + 0x384a6000, + 0x384a8000, + 0x384aa000, + 0x384ac000, + 0x384ae000, + 0x384b0000, + 0x384b2000, + 0x384b4000, + 0x384b6000, + 0x384b8000, + 0x384ba000, + 0x384bc000, + 0x384be000, + 0x384c0000, + 0x384c2000, + 0x384c4000, + 0x384c6000, + 0x384c8000, + 0x384ca000, + 0x384cc000, + 0x384ce000, + 0x384d0000, + 0x384d2000, + 0x384d4000, + 0x384d6000, + 0x384d8000, + 0x384da000, + 0x384dc000, + 0x384de000, + 0x384e0000, + 0x384e2000, + 0x384e4000, + 0x384e6000, + 0x384e8000, + 0x384ea000, + 0x384ec000, + 0x384ee000, + 0x384f0000, + 0x384f2000, + 0x384f4000, + 0x384f6000, + 0x384f8000, + 0x384fa000, + 0x384fc000, + 0x384fe000, + 0x38500000, + 0x38502000, + 0x38504000, + 0x38506000, + 0x38508000, + 0x3850a000, + 0x3850c000, + 0x3850e000, + 0x38510000, + 0x38512000, + 0x38514000, + 0x38516000, + 0x38518000, + 0x3851a000, + 0x3851c000, + 0x3851e000, + 0x38520000, + 0x38522000, + 0x38524000, + 0x38526000, + 0x38528000, + 0x3852a000, + 0x3852c000, + 0x3852e000, + 0x38530000, + 0x38532000, + 0x38534000, + 0x38536000, + 0x38538000, + 0x3853a000, + 0x3853c000, + 0x3853e000, + 0x38540000, + 0x38542000, + 0x38544000, + 0x38546000, + 0x38548000, + 0x3854a000, + 0x3854c000, + 0x3854e000, + 0x38550000, + 0x38552000, + 0x38554000, + 0x38556000, + 0x38558000, + 0x3855a000, + 0x3855c000, + 0x3855e000, + 0x38560000, + 0x38562000, + 0x38564000, + 0x38566000, + 0x38568000, + 0x3856a000, + 0x3856c000, + 0x3856e000, + 0x38570000, + 0x38572000, + 0x38574000, + 0x38576000, + 0x38578000, + 0x3857a000, + 0x3857c000, + 0x3857e000, + 0x38580000, + 0x38582000, + 0x38584000, + 0x38586000, + 0x38588000, + 0x3858a000, + 0x3858c000, + 0x3858e000, + 0x38590000, + 0x38592000, + 0x38594000, + 0x38596000, + 0x38598000, + 0x3859a000, + 0x3859c000, + 0x3859e000, + 0x385a0000, + 0x385a2000, + 0x385a4000, + 0x385a6000, + 0x385a8000, + 0x385aa000, + 0x385ac000, + 0x385ae000, + 0x385b0000, + 0x385b2000, + 0x385b4000, + 0x385b6000, + 0x385b8000, + 0x385ba000, + 0x385bc000, + 0x385be000, + 0x385c0000, + 0x385c2000, + 0x385c4000, + 0x385c6000, + 0x385c8000, + 0x385ca000, + 0x385cc000, + 0x385ce000, + 0x385d0000, + 0x385d2000, + 0x385d4000, + 0x385d6000, + 0x385d8000, + 0x385da000, + 0x385dc000, + 0x385de000, + 0x385e0000, + 0x385e2000, + 0x385e4000, + 0x385e6000, + 0x385e8000, + 0x385ea000, + 0x385ec000, + 0x385ee000, + 0x385f0000, + 0x385f2000, + 0x385f4000, + 0x385f6000, + 0x385f8000, + 0x385fa000, + 0x385fc000, + 0x385fe000, + 0x38600000, + 0x38602000, + 0x38604000, + 0x38606000, + 0x38608000, + 0x3860a000, + 0x3860c000, + 0x3860e000, + 0x38610000, + 0x38612000, + 0x38614000, + 0x38616000, + 0x38618000, + 0x3861a000, + 0x3861c000, + 0x3861e000, + 0x38620000, + 0x38622000, + 0x38624000, + 0x38626000, + 0x38628000, + 0x3862a000, + 0x3862c000, + 0x3862e000, + 0x38630000, + 0x38632000, + 0x38634000, + 0x38636000, + 0x38638000, + 0x3863a000, + 0x3863c000, + 0x3863e000, + 0x38640000, + 0x38642000, + 0x38644000, + 0x38646000, + 0x38648000, + 0x3864a000, + 0x3864c000, + 0x3864e000, + 0x38650000, + 0x38652000, + 0x38654000, + 0x38656000, + 0x38658000, + 0x3865a000, + 0x3865c000, + 0x3865e000, + 0x38660000, + 0x38662000, + 0x38664000, + 0x38666000, + 0x38668000, + 0x3866a000, + 0x3866c000, + 0x3866e000, + 0x38670000, + 0x38672000, + 0x38674000, + 0x38676000, + 0x38678000, + 0x3867a000, + 0x3867c000, + 0x3867e000, + 0x38680000, + 0x38682000, + 0x38684000, + 0x38686000, + 0x38688000, + 0x3868a000, + 0x3868c000, + 0x3868e000, + 0x38690000, + 0x38692000, + 0x38694000, + 0x38696000, + 0x38698000, + 0x3869a000, + 0x3869c000, + 0x3869e000, + 0x386a0000, + 0x386a2000, + 0x386a4000, + 0x386a6000, + 0x386a8000, + 0x386aa000, + 0x386ac000, + 0x386ae000, + 0x386b0000, + 0x386b2000, + 0x386b4000, + 0x386b6000, + 0x386b8000, + 0x386ba000, + 0x386bc000, + 0x386be000, + 0x386c0000, + 0x386c2000, + 0x386c4000, + 0x386c6000, + 0x386c8000, + 0x386ca000, + 0x386cc000, + 0x386ce000, + 0x386d0000, + 0x386d2000, + 0x386d4000, + 0x386d6000, + 0x386d8000, + 0x386da000, + 0x386dc000, + 0x386de000, + 0x386e0000, + 0x386e2000, + 0x386e4000, + 0x386e6000, + 0x386e8000, + 0x386ea000, + 0x386ec000, + 0x386ee000, + 0x386f0000, + 0x386f2000, + 0x386f4000, + 0x386f6000, + 0x386f8000, + 0x386fa000, + 0x386fc000, + 0x386fe000, + 0x38700000, + 0x38702000, + 0x38704000, + 0x38706000, + 0x38708000, + 0x3870a000, + 0x3870c000, + 0x3870e000, + 0x38710000, + 0x38712000, + 0x38714000, + 0x38716000, + 0x38718000, + 0x3871a000, + 0x3871c000, + 0x3871e000, + 0x38720000, + 0x38722000, + 0x38724000, + 0x38726000, + 0x38728000, + 0x3872a000, + 0x3872c000, + 0x3872e000, + 0x38730000, + 0x38732000, + 0x38734000, + 0x38736000, + 0x38738000, + 0x3873a000, + 0x3873c000, + 0x3873e000, + 0x38740000, + 0x38742000, + 0x38744000, + 0x38746000, + 0x38748000, + 0x3874a000, + 0x3874c000, + 0x3874e000, + 0x38750000, + 0x38752000, + 0x38754000, + 0x38756000, + 0x38758000, + 0x3875a000, + 0x3875c000, + 0x3875e000, + 0x38760000, + 0x38762000, + 0x38764000, + 0x38766000, + 0x38768000, + 0x3876a000, + 0x3876c000, + 0x3876e000, + 0x38770000, + 0x38772000, + 0x38774000, + 0x38776000, + 0x38778000, + 0x3877a000, + 0x3877c000, + 0x3877e000, + 0x38780000, + 0x38782000, + 0x38784000, + 0x38786000, + 0x38788000, + 0x3878a000, + 0x3878c000, + 0x3878e000, + 0x38790000, + 0x38792000, + 0x38794000, + 0x38796000, + 0x38798000, + 0x3879a000, + 0x3879c000, + 0x3879e000, + 0x387a0000, + 0x387a2000, + 0x387a4000, + 0x387a6000, + 0x387a8000, + 0x387aa000, + 0x387ac000, + 0x387ae000, + 0x387b0000, + 0x387b2000, + 0x387b4000, + 0x387b6000, + 0x387b8000, + 0x387ba000, + 0x387bc000, + 0x387be000, + 0x387c0000, + 0x387c2000, + 0x387c4000, + 0x387c6000, + 0x387c8000, + 0x387ca000, + 0x387cc000, + 0x387ce000, + 0x387d0000, + 0x387d2000, + 0x387d4000, + 0x387d6000, + 0x387d8000, + 0x387da000, + 0x387dc000, + 0x387de000, + 0x387e0000, + 0x387e2000, + 0x387e4000, + 0x387e6000, + 0x387e8000, + 0x387ea000, + 0x387ec000, + 0x387ee000, + 0x387f0000, + 0x387f2000, + 0x387f4000, + 0x387f6000, + 0x387f8000, + 0x387fa000, + 0x387fc000, + 0x387fe000, +}; + +const static unsigned g_exponent[64] = { + 0x00000000, + 0x00800000, + 0x01000000, + 0x01800000, + 0x02000000, + 0x02800000, + 0x03000000, + 0x03800000, + 0x04000000, + 0x04800000, + 0x05000000, + 0x05800000, + 0x06000000, + 0x06800000, + 0x07000000, + 0x07800000, + 0x08000000, + 0x08800000, + 0x09000000, + 0x09800000, + 0x0a000000, + 0x0a800000, + 0x0b000000, + 0x0b800000, + 0x0c000000, + 0x0c800000, + 0x0d000000, + 0x0d800000, + 0x0e000000, + 0x0e800000, + 0x0f000000, + 0x47800000, + 0x80000000, + 0x80800000, + 0x81000000, + 0x81800000, + 0x82000000, + 0x82800000, + 0x83000000, + 0x83800000, + 0x84000000, + 0x84800000, + 0x85000000, + 0x85800000, + 0x86000000, + 0x86800000, + 0x87000000, + 0x87800000, + 0x88000000, + 0x88800000, + 0x89000000, + 0x89800000, + 0x8a000000, + 0x8a800000, + 0x8b000000, + 0x8b800000, + 0x8c000000, + 0x8c800000, + 0x8d000000, + 0x8d800000, + 0x8e000000, + 0x8e800000, + 0x8f000000, + 0xc7800000, +}; + +const static unsigned g_offset[64] = { + 0x00000000, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000000, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, +}; + +float float16ToFloat32(unsigned short h) +{ + unsigned i32 = g_mantissa[g_offset[h >> 10] + (h & 0x3ff)] + g_exponent[h >> 10]; + return *(float*) &i32; +} +} + diff --git a/gfx/angle/src/libGLESv2/Framebuffer.cpp b/gfx/angle/src/libGLESv2/Framebuffer.cpp index 77d79c0be22b..b0abba0ac441 100644 --- a/gfx/angle/src/libGLESv2/Framebuffer.cpp +++ b/gfx/angle/src/libGLESv2/Framebuffer.cpp @@ -1,5 +1,6 @@ +#include "precompiled.h" // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -10,26 +11,38 @@ #include "libGLESv2/Framebuffer.h" #include "libGLESv2/main.h" -#include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/Texture.h" #include "libGLESv2/utilities.h" +#include "libGLESv2/Texture.h" +#include "libGLESv2/Context.h" +#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/Renderbuffer.h" namespace gl { -Framebuffer::Framebuffer() +Framebuffer::Framebuffer(rx::Renderer *renderer) + : mRenderer(renderer) { - mColorbufferType = GL_NONE; + for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) + { + mColorbufferTypes[colorAttachment] = GL_NONE; + mDrawBufferStates[colorAttachment] = GL_NONE; + } + mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT; + mReadBufferState = GL_COLOR_ATTACHMENT0_EXT; + mDepthbufferType = GL_NONE; mStencilbufferType = GL_NONE; } Framebuffer::~Framebuffer() { - mColorbufferPointer.set(NULL); + for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) + { + mColorbufferPointers[colorAttachment].set(NULL); + } mDepthbufferPointer.set(NULL); mStencilbufferPointer.set(NULL); - mNullColorbufferPointer.set(NULL); } Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle) const @@ -57,10 +70,11 @@ Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle) const return buffer; } -void Framebuffer::setColorbuffer(GLenum type, GLuint colorbuffer) +void Framebuffer::setColorbuffer(unsigned int colorAttachment, GLenum type, GLuint colorbuffer) { - mColorbufferType = (colorbuffer != 0) ? type : GL_NONE; - mColorbufferPointer.set(lookupRenderbuffer(type, colorbuffer)); + ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); + mColorbufferTypes[colorAttachment] = (colorbuffer != 0) ? type : GL_NONE; + mColorbufferPointers[colorAttachment].set(lookupRenderbuffer(type, colorbuffer)); } void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer) @@ -77,10 +91,13 @@ void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer) void Framebuffer::detachTexture(GLuint texture) { - if (mColorbufferPointer.id() == texture && IsInternalTextureTarget(mColorbufferType)) + for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) { - mColorbufferType = GL_NONE; - mColorbufferPointer.set(NULL); + if (mColorbufferPointers[colorAttachment].id() == texture && IsInternalTextureTarget(mColorbufferTypes[colorAttachment])) + { + mColorbufferTypes[colorAttachment] = GL_NONE; + mColorbufferPointers[colorAttachment].set(NULL); + } } if (mDepthbufferPointer.id() == texture && IsInternalTextureTarget(mDepthbufferType)) @@ -98,10 +115,13 @@ void Framebuffer::detachTexture(GLuint texture) void Framebuffer::detachRenderbuffer(GLuint renderbuffer) { - if (mColorbufferPointer.id() == renderbuffer && mColorbufferType == GL_RENDERBUFFER) + for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) { - mColorbufferType = GL_NONE; - mColorbufferPointer.set(NULL); + if (mColorbufferPointers[colorAttachment].id() == renderbuffer && mColorbufferTypes[colorAttachment] == GL_RENDERBUFFER) + { + mColorbufferTypes[colorAttachment] = GL_NONE; + mColorbufferPointers[colorAttachment].set(NULL); + } } if (mDepthbufferPointer.id() == renderbuffer && mDepthbufferType == GL_RENDERBUFFER) @@ -117,9 +137,11 @@ void Framebuffer::detachRenderbuffer(GLuint renderbuffer) } } -unsigned int Framebuffer::getRenderTargetSerial() +unsigned int Framebuffer::getRenderTargetSerial(unsigned int colorAttachment) const { - Renderbuffer *colorbuffer = mColorbufferPointer.get(); + ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); + + Renderbuffer *colorbuffer = mColorbufferPointers[colorAttachment].get(); if (colorbuffer) { @@ -129,40 +151,7 @@ unsigned int Framebuffer::getRenderTargetSerial() return 0; } -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *Framebuffer::getRenderTarget() -{ - Renderbuffer *colorbuffer = mColorbufferPointer.get(); - - if (colorbuffer) - { - return colorbuffer->getRenderTarget(); - } - - return NULL; -} - -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *Framebuffer::getDepthStencil() -{ - Renderbuffer *depthstencilbuffer = mDepthbufferPointer.get(); - - if (!depthstencilbuffer) - { - depthstencilbuffer = mStencilbufferPointer.get(); - } - - if (depthstencilbuffer) - { - return depthstencilbuffer->getDepthStencil(); - } - - return NULL; -} - -unsigned int Framebuffer::getDepthbufferSerial() +unsigned int Framebuffer::getDepthbufferSerial() const { Renderbuffer *depthbuffer = mDepthbufferPointer.get(); @@ -174,7 +163,7 @@ unsigned int Framebuffer::getDepthbufferSerial() return 0; } -unsigned int Framebuffer::getStencilbufferSerial() +unsigned int Framebuffer::getStencilbufferSerial() const { Renderbuffer *stencilbuffer = mStencilbufferPointer.get(); @@ -186,80 +175,124 @@ unsigned int Framebuffer::getStencilbufferSerial() return 0; } -Renderbuffer *Framebuffer::getColorbuffer() +Renderbuffer *Framebuffer::getColorbuffer(unsigned int colorAttachment) const { - return mColorbufferPointer.get(); + ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); + return mColorbufferPointers[colorAttachment].get(); } -Renderbuffer *Framebuffer::getDepthbuffer() +Renderbuffer *Framebuffer::getDepthbuffer() const { return mDepthbufferPointer.get(); } -Renderbuffer *Framebuffer::getStencilbuffer() +Renderbuffer *Framebuffer::getStencilbuffer() const { return mStencilbufferPointer.get(); } -Renderbuffer *Framebuffer::getNullColorbuffer() +Renderbuffer *Framebuffer::getDepthOrStencilbuffer() const { - Renderbuffer *nullbuffer = mNullColorbufferPointer.get(); - Renderbuffer *depthbuffer = getDepthbuffer(); - - if (!depthbuffer) + Renderbuffer *depthstencilbuffer = mDepthbufferPointer.get(); + + if (!depthstencilbuffer) { - ERR("Unexpected null depthbuffer for depth-only FBO."); - return NULL; + depthstencilbuffer = mStencilbufferPointer.get(); } - GLsizei width = depthbuffer->getWidth(); - GLsizei height = depthbuffer->getHeight(); + return depthstencilbuffer; +} - if (!nullbuffer || - width != nullbuffer->getWidth() || height != nullbuffer->getHeight()) +Renderbuffer *Framebuffer::getReadColorbuffer() const +{ + // Will require more logic if glReadBuffers is supported + return mColorbufferPointers[0].get(); +} + +GLenum Framebuffer::getReadColorbufferType() const +{ + // Will require more logic if glReadBuffers is supported + return mColorbufferTypes[0]; +} + +Renderbuffer *Framebuffer::getFirstColorbuffer() const +{ + for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) { - nullbuffer = new Renderbuffer(0, new Colorbuffer(width, height, GL_NONE, 0)); - mNullColorbufferPointer.set(nullbuffer); + if (mColorbufferTypes[colorAttachment] != GL_NONE) + { + return mColorbufferPointers[colorAttachment].get(); + } } - return nullbuffer; + return NULL; } -GLenum Framebuffer::getColorbufferType() +GLenum Framebuffer::getColorbufferType(unsigned int colorAttachment) const { - return mColorbufferType; + ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); + return mColorbufferTypes[colorAttachment]; } -GLenum Framebuffer::getDepthbufferType() +GLenum Framebuffer::getDepthbufferType() const { return mDepthbufferType; } -GLenum Framebuffer::getStencilbufferType() +GLenum Framebuffer::getStencilbufferType() const { return mStencilbufferType; } -GLuint Framebuffer::getColorbufferHandle() +GLuint Framebuffer::getColorbufferHandle(unsigned int colorAttachment) const { - return mColorbufferPointer.id(); + ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); + return mColorbufferPointers[colorAttachment].id(); } -GLuint Framebuffer::getDepthbufferHandle() +GLuint Framebuffer::getDepthbufferHandle() const { return mDepthbufferPointer.id(); } -GLuint Framebuffer::getStencilbufferHandle() +GLuint Framebuffer::getStencilbufferHandle() const { return mStencilbufferPointer.id(); } -bool Framebuffer::hasStencil() +GLenum Framebuffer::getDrawBufferState(unsigned int colorAttachment) const +{ + return mDrawBufferStates[colorAttachment]; +} + +void Framebuffer::setDrawBufferState(unsigned int colorAttachment, GLenum drawBuffer) +{ + mDrawBufferStates[colorAttachment] = drawBuffer; +} + +bool Framebuffer::isEnabledColorAttachment(unsigned int colorAttachment) const +{ + return (mColorbufferTypes[colorAttachment] != GL_NONE && mDrawBufferStates[colorAttachment] != GL_NONE); +} + +bool Framebuffer::hasEnabledColorAttachment() const +{ + for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) + { + if (isEnabledColorAttachment(colorAttachment)) + { + return true; + } + } + + return false; +} + +bool Framebuffer::hasStencil() const { if (mStencilbufferType != GL_NONE) { - Renderbuffer *stencilbufferObject = getStencilbuffer(); + const Renderbuffer *stencilbufferObject = getStencilbuffer(); if (stencilbufferObject) { @@ -270,73 +303,125 @@ bool Framebuffer::hasStencil() return false; } -GLenum Framebuffer::completeness() +bool Framebuffer::usingExtendedDrawBuffers() const +{ + for (unsigned int colorAttachment = 1; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) + { + if (isEnabledColorAttachment(colorAttachment)) + { + return true; + } + } + + return false; +} + +GLenum Framebuffer::completeness() const { - gl::Context *context = gl::getContext(); int width = 0; int height = 0; + int colorbufferSize = 0; int samples = -1; bool missingAttachment = true; - if (mColorbufferType != GL_NONE) + for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) { - Renderbuffer *colorbuffer = getColorbuffer(); - - if (!colorbuffer) + if (mColorbufferTypes[colorAttachment] != GL_NONE) { - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - } + const Renderbuffer *colorbuffer = getColorbuffer(colorAttachment); - if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0) - { - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - } - - if (mColorbufferType == GL_RENDERBUFFER) - { - if (!gl::IsColorRenderable(colorbuffer->getInternalFormat())) + if (!colorbuffer) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } - } - else if (IsInternalTextureTarget(mColorbufferType)) - { - GLint internalformat = colorbuffer->getInternalFormat(); - GLenum format = gl::ExtractFormat(internalformat); - if (IsCompressed(format) || - format == GL_ALPHA || - format == GL_LUMINANCE || - format == GL_LUMINANCE_ALPHA) - { - return GL_FRAMEBUFFER_UNSUPPORTED; - } - - if ((gl::IsFloat32Format(internalformat) && !context->supportsFloat32RenderableTextures()) || - (gl::IsFloat16Format(internalformat) && !context->supportsFloat16RenderableTextures())) - { - return GL_FRAMEBUFFER_UNSUPPORTED; - } - - if (gl::IsDepthTexture(internalformat) || gl::IsStencilTexture(internalformat)) + if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } - } - else - { - UNREACHABLE(); - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - } - width = colorbuffer->getWidth(); - height = colorbuffer->getHeight(); - samples = colorbuffer->getSamples(); - missingAttachment = false; + if (mColorbufferTypes[colorAttachment] == GL_RENDERBUFFER) + { + if (!gl::IsColorRenderable(colorbuffer->getInternalFormat())) + { + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + } + } + else if (IsInternalTextureTarget(mColorbufferTypes[colorAttachment])) + { + GLint internalformat = colorbuffer->getInternalFormat(); + GLenum format = gl::ExtractFormat(internalformat); + + if (IsCompressed(format) || + format == GL_ALPHA || + format == GL_LUMINANCE || + format == GL_LUMINANCE_ALPHA) + { + return GL_FRAMEBUFFER_UNSUPPORTED; + } + + bool filtering, renderable; + + if ((gl::IsFloat32Format(internalformat) && !mRenderer->getFloat32TextureSupport(&filtering, &renderable)) || + (gl::IsFloat16Format(internalformat) && !mRenderer->getFloat16TextureSupport(&filtering, &renderable))) + { + return GL_FRAMEBUFFER_UNSUPPORTED; + } + + if (gl::IsDepthTexture(internalformat) || gl::IsStencilTexture(internalformat)) + { + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + } + } + else + { + UNREACHABLE(); + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + } + + if (!missingAttachment) + { + // all color attachments must have the same width and height + if (colorbuffer->getWidth() != width || colorbuffer->getHeight() != height) + { + return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; + } + + // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that + // all color attachments have the same number of samples for the FBO to be complete. + if (colorbuffer->getSamples() != samples) + { + return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT; + } + + // all color attachments attachments must have the same number of bitplanes + if (gl::ComputePixelSize(colorbuffer->getInternalFormat()) != colorbufferSize) + { + return GL_FRAMEBUFFER_UNSUPPORTED; + } + + // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness + for (unsigned int previousColorAttachment = 0; previousColorAttachment < colorAttachment; previousColorAttachment++) + { + if (mColorbufferPointers[colorAttachment].get() == mColorbufferPointers[previousColorAttachment].get()) + { + return GL_FRAMEBUFFER_UNSUPPORTED; + } + } + } + else + { + width = colorbuffer->getWidth(); + height = colorbuffer->getHeight(); + samples = colorbuffer->getSamples(); + colorbufferSize = gl::ComputePixelSize(colorbuffer->getInternalFormat()); + missingAttachment = false; + } + } } - Renderbuffer *depthbuffer = NULL; - Renderbuffer *stencilbuffer = NULL; + const Renderbuffer *depthbuffer = NULL; + const Renderbuffer *stencilbuffer = NULL; if (mDepthbufferType != GL_NONE) { @@ -364,7 +449,7 @@ GLenum Framebuffer::completeness() GLint internalformat = depthbuffer->getInternalFormat(); // depth texture attachments require OES/ANGLE_depth_texture - if (!context->supportsDepthTextures()) + if (!mRenderer->getDepthTextureSupport()) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } @@ -424,7 +509,7 @@ GLenum Framebuffer::completeness() // texture stencil attachments come along as part // of OES_packed_depth_stencil + OES/ANGLE_depth_texture - if (!context->supportsDepthTextures()) + if (!mRenderer->getDepthTextureSupport()) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } @@ -473,36 +558,45 @@ GLenum Framebuffer::completeness() return GL_FRAMEBUFFER_COMPLETE; } -DefaultFramebuffer::DefaultFramebuffer(Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil) +DefaultFramebuffer::DefaultFramebuffer(rx::Renderer *renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil) + : Framebuffer(renderer) { - mColorbufferPointer.set(new Renderbuffer(0, colorbuffer)); + mColorbufferPointers[0].set(new Renderbuffer(mRenderer, 0, colorbuffer)); - Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(0, depthStencil); + Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(mRenderer, 0, depthStencil); mDepthbufferPointer.set(depthStencilRenderbuffer); mStencilbufferPointer.set(depthStencilRenderbuffer); - mColorbufferType = GL_RENDERBUFFER; + mColorbufferTypes[0] = GL_RENDERBUFFER; mDepthbufferType = (depthStencilRenderbuffer->getDepthSize() != 0) ? GL_RENDERBUFFER : GL_NONE; mStencilbufferType = (depthStencilRenderbuffer->getStencilSize() != 0) ? GL_RENDERBUFFER : GL_NONE; + + mDrawBufferStates[0] = GL_BACK; + mReadBufferState = GL_BACK; } -int Framebuffer::getSamples() +int Framebuffer::getSamples() const { if (completeness() == GL_FRAMEBUFFER_COMPLETE) { - return getColorbuffer()->getSamples(); - } - else - { - return 0; + // for a complete framebuffer, all attachments must have the same sample count + // in this case return the first nonzero sample size + for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) + { + if (mColorbufferTypes[colorAttachment] != GL_NONE) + { + return getColorbuffer(colorAttachment)->getSamples(); + } + } } + + return 0; } -GLenum DefaultFramebuffer::completeness() +GLenum DefaultFramebuffer::completeness() const { - // The default framebuffer should always be complete - ASSERT(Framebuffer::completeness() == GL_FRAMEBUFFER_COMPLETE); - + // The default framebuffer *must* always be complete, though it may not be + // subject to the same rules as application FBOs. ie, it could have 0x0 size. return GL_FRAMEBUFFER_COMPLETE; } diff --git a/gfx/angle/src/libGLESv2/Framebuffer.h b/gfx/angle/src/libGLESv2/Framebuffer.h index 14d9c2a74c06..b54e008dd825 100644 --- a/gfx/angle/src/libGLESv2/Framebuffer.h +++ b/gfx/angle/src/libGLESv2/Framebuffer.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -10,12 +10,14 @@ #ifndef LIBGLESV2_FRAMEBUFFER_H_ #define LIBGLESV2_FRAMEBUFFER_H_ -#define GL_APICALL -#include -#include - #include "common/angleutils.h" #include "common/RefCountObject.h" +#include "constants.h" + +namespace rx +{ +class Renderer; +} namespace gl { @@ -28,45 +30,53 @@ class DepthStencilbuffer; class Framebuffer { public: - Framebuffer(); + explicit Framebuffer(rx::Renderer *renderer); virtual ~Framebuffer(); - void setColorbuffer(GLenum type, GLuint colorbuffer); + void setColorbuffer(unsigned int colorAttachment, GLenum type, GLuint colorbuffer); void setDepthbuffer(GLenum type, GLuint depthbuffer); void setStencilbuffer(GLenum type, GLuint stencilbuffer); void detachTexture(GLuint texture); void detachRenderbuffer(GLuint renderbuffer); - IDirect3DSurface9 *getRenderTarget(); - IDirect3DSurface9 *getDepthStencil(); + unsigned int getRenderTargetSerial(unsigned int colorAttachment) const; + unsigned int getDepthbufferSerial() const; + unsigned int getStencilbufferSerial() const; - unsigned int getRenderTargetSerial(); - unsigned int getDepthbufferSerial(); - unsigned int getStencilbufferSerial(); + Renderbuffer *getColorbuffer(unsigned int colorAttachment) const; + Renderbuffer *getDepthbuffer() const; + Renderbuffer *getStencilbuffer() const; + Renderbuffer *getDepthOrStencilbuffer() const; + Renderbuffer *getReadColorbuffer() const; + GLenum getReadColorbufferType() const; + Renderbuffer *getFirstColorbuffer() const; - Renderbuffer *getColorbuffer(); - Renderbuffer *getDepthbuffer(); - Renderbuffer *getStencilbuffer(); - Renderbuffer *getNullColorbuffer(); + GLenum getColorbufferType(unsigned int colorAttachment) const; + GLenum getDepthbufferType() const; + GLenum getStencilbufferType() const; - GLenum getColorbufferType(); - GLenum getDepthbufferType(); - GLenum getStencilbufferType(); + GLuint getColorbufferHandle(unsigned int colorAttachment) const; + GLuint getDepthbufferHandle() const; + GLuint getStencilbufferHandle() const; - GLuint getColorbufferHandle(); - GLuint getDepthbufferHandle(); - GLuint getStencilbufferHandle(); + GLenum getDrawBufferState(unsigned int colorAttachment) const; + void setDrawBufferState(unsigned int colorAttachment, GLenum drawBuffer); - bool hasStencil(); - int getSamples(); + bool isEnabledColorAttachment(unsigned int colorAttachment) const; + bool hasEnabledColorAttachment() const; + bool hasStencil() const; + int getSamples() const; + bool usingExtendedDrawBuffers() const; - virtual GLenum completeness(); + virtual GLenum completeness() const; protected: - GLenum mColorbufferType; - BindingPointer mColorbufferPointer; + GLenum mColorbufferTypes[IMPLEMENTATION_MAX_DRAW_BUFFERS]; + BindingPointer mColorbufferPointers[IMPLEMENTATION_MAX_DRAW_BUFFERS]; + GLenum mDrawBufferStates[IMPLEMENTATION_MAX_DRAW_BUFFERS]; + GLenum mReadBufferState; GLenum mDepthbufferType; BindingPointer mDepthbufferPointer; @@ -74,7 +84,7 @@ class Framebuffer GLenum mStencilbufferType; BindingPointer mStencilbufferPointer; - BindingPointer mNullColorbufferPointer; + rx::Renderer *mRenderer; private: DISALLOW_COPY_AND_ASSIGN(Framebuffer); @@ -85,9 +95,9 @@ class Framebuffer class DefaultFramebuffer : public Framebuffer { public: - DefaultFramebuffer(Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil); + DefaultFramebuffer(rx::Renderer *Renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil); - virtual GLenum completeness(); + virtual GLenum completeness() const; private: DISALLOW_COPY_AND_ASSIGN(DefaultFramebuffer); diff --git a/gfx/angle/src/libGLESv2/HandleAllocator.cpp b/gfx/angle/src/libGLESv2/HandleAllocator.cpp index c498f8a17809..37da99aa1828 100644 --- a/gfx/angle/src/libGLESv2/HandleAllocator.cpp +++ b/gfx/angle/src/libGLESv2/HandleAllocator.cpp @@ -1,3 +1,4 @@ +#include "precompiled.h" // // Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be diff --git a/gfx/angle/src/libGLESv2/IndexDataManager.cpp b/gfx/angle/src/libGLESv2/IndexDataManager.cpp deleted file mode 100644 index 18374dc80c73..000000000000 --- a/gfx/angle/src/libGLESv2/IndexDataManager.cpp +++ /dev/null @@ -1,474 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// IndexDataManager.cpp: Defines the IndexDataManager, a class that -// runs the Buffer translation process for index buffers. - -#include "libGLESv2/IndexDataManager.h" - -#include "common/debug.h" - -#include "libGLESv2/Buffer.h" -#include "libGLESv2/mathutil.h" -#include "libGLESv2/main.h" - -namespace gl -{ -unsigned int IndexBuffer::mCurrentSerial = 1; - -IndexDataManager::IndexDataManager(Context *context, IDirect3DDevice9 *device) : mDevice(device) -{ - mStreamingBufferShort = new StreamingIndexBuffer(mDevice, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX16); - - if (context->supports32bitIndices()) - { - mStreamingBufferInt = new StreamingIndexBuffer(mDevice, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX32); - - if (!mStreamingBufferInt) - { - // Don't leave it in a half-initialized state - delete mStreamingBufferShort; - mStreamingBufferShort = NULL; - } - } - else - { - mStreamingBufferInt = NULL; - } - - if (!mStreamingBufferShort) - { - ERR("Failed to allocate the streaming index buffer(s)."); - } - - mCountingBuffer = NULL; -} - -IndexDataManager::~IndexDataManager() -{ - delete mStreamingBufferShort; - delete mStreamingBufferInt; - delete mCountingBuffer; -} - -void convertIndices(GLenum type, const void *input, GLsizei count, void *output) -{ - if (type == GL_UNSIGNED_BYTE) - { - const GLubyte *in = static_cast(input); - GLushort *out = static_cast(output); - - for (GLsizei i = 0; i < count; i++) - { - out[i] = in[i]; - } - } - else if (type == GL_UNSIGNED_INT) - { - memcpy(output, input, count * sizeof(GLuint)); - } - else if (type == GL_UNSIGNED_SHORT) - { - memcpy(output, input, count * sizeof(GLushort)); - } - else UNREACHABLE(); -} - -template -void computeRange(const IndexType *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex) -{ - *minIndex = indices[0]; - *maxIndex = indices[0]; - - for (GLsizei i = 0; i < count; i++) - { - if (*minIndex > indices[i]) *minIndex = indices[i]; - if (*maxIndex < indices[i]) *maxIndex = indices[i]; - } -} - -void computeRange(GLenum type, const GLvoid *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex) -{ - if (type == GL_UNSIGNED_BYTE) - { - computeRange(static_cast(indices), count, minIndex, maxIndex); - } - else if (type == GL_UNSIGNED_INT) - { - computeRange(static_cast(indices), count, minIndex, maxIndex); - } - else if (type == GL_UNSIGNED_SHORT) - { - computeRange(static_cast(indices), count, minIndex, maxIndex); - } - else UNREACHABLE(); -} - -GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, Buffer *buffer, const GLvoid *indices, TranslatedIndexData *translated) -{ - if (!mStreamingBufferShort) - { - return GL_OUT_OF_MEMORY; - } - - D3DFORMAT format = (type == GL_UNSIGNED_INT) ? D3DFMT_INDEX32 : D3DFMT_INDEX16; - intptr_t offset = reinterpret_cast(indices); - bool alignedOffset = false; - - if (buffer != NULL) - { - switch (type) - { - case GL_UNSIGNED_BYTE: alignedOffset = (offset % sizeof(GLubyte) == 0); break; - case GL_UNSIGNED_SHORT: alignedOffset = (offset % sizeof(GLushort) == 0); break; - case GL_UNSIGNED_INT: alignedOffset = (offset % sizeof(GLuint) == 0); break; - default: UNREACHABLE(); alignedOffset = false; - } - - if (typeSize(type) * count + offset > static_cast(buffer->size())) - { - return GL_INVALID_OPERATION; - } - - indices = static_cast(buffer->data()) + offset; - } - - StreamingIndexBuffer *streamingBuffer = (type == GL_UNSIGNED_INT) ? mStreamingBufferInt : mStreamingBufferShort; - - StaticIndexBuffer *staticBuffer = buffer ? buffer->getStaticIndexBuffer() : NULL; - IndexBuffer *indexBuffer = streamingBuffer; - UINT streamOffset = 0; - - if (staticBuffer && staticBuffer->lookupType(type) && alignedOffset) - { - indexBuffer = staticBuffer; - streamOffset = staticBuffer->lookupRange(offset, count, &translated->minIndex, &translated->maxIndex); - - if (streamOffset == -1) - { - streamOffset = (offset / typeSize(type)) * indexSize(format); - computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex); - staticBuffer->addRange(offset, count, translated->minIndex, translated->maxIndex, streamOffset); - } - } - else - { - int convertCount = count; - - if (staticBuffer) - { - if (staticBuffer->size() == 0 && alignedOffset) - { - indexBuffer = staticBuffer; - convertCount = buffer->size() / typeSize(type); - } - else - { - buffer->invalidateStaticData(); - staticBuffer = NULL; - } - } - - void *output = NULL; - - if (indexBuffer) - { - indexBuffer->reserveSpace(convertCount * indexSize(format), type); - output = indexBuffer->map(indexSize(format) * convertCount, &streamOffset); - } - - if (output == NULL) - { - ERR("Failed to map index buffer."); - return GL_OUT_OF_MEMORY; - } - - convertIndices(type, staticBuffer ? buffer->data() : indices, convertCount, output); - indexBuffer->unmap(); - - computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex); - - if (staticBuffer) - { - streamOffset = (offset / typeSize(type)) * indexSize(format); - staticBuffer->addRange(offset, count, translated->minIndex, translated->maxIndex, streamOffset); - } - } - - translated->indexBuffer = indexBuffer->getBuffer(); - translated->serial = indexBuffer->getSerial(); - translated->startIndex = streamOffset / indexSize(format); - - if (buffer) - { - buffer->promoteStaticUsage(count * typeSize(type)); - } - - return GL_NO_ERROR; -} - -std::size_t IndexDataManager::indexSize(D3DFORMAT format) const -{ - return (format == D3DFMT_INDEX32) ? sizeof(unsigned int) : sizeof(unsigned short); -} - -std::size_t IndexDataManager::typeSize(GLenum type) const -{ - switch (type) - { - case GL_UNSIGNED_INT: return sizeof(GLuint); - case GL_UNSIGNED_SHORT: return sizeof(GLushort); - case GL_UNSIGNED_BYTE: return sizeof(GLubyte); - default: UNREACHABLE(); return sizeof(GLushort); - } -} - -StaticIndexBuffer *IndexDataManager::getCountingIndices(GLsizei count) -{ - if (count <= 65536) // 16-bit indices - { - const unsigned int spaceNeeded = count * sizeof(unsigned short); - - if (!mCountingBuffer || mCountingBuffer->size() < spaceNeeded) - { - delete mCountingBuffer; - mCountingBuffer = new StaticIndexBuffer(mDevice); - mCountingBuffer->reserveSpace(spaceNeeded, GL_UNSIGNED_SHORT); - - UINT offset; - unsigned short *data = static_cast(mCountingBuffer->map(spaceNeeded, &offset)); - - if (data) - { - for(int i = 0; i < count; i++) - { - data[i] = i; - } - - mCountingBuffer->unmap(); - } - } - } - else if (mStreamingBufferInt) // 32-bit indices supported - { - const unsigned int spaceNeeded = count * sizeof(unsigned int); - - if (!mCountingBuffer || mCountingBuffer->size() < spaceNeeded) - { - delete mCountingBuffer; - mCountingBuffer = new StaticIndexBuffer(mDevice); - mCountingBuffer->reserveSpace(spaceNeeded, GL_UNSIGNED_INT); - - UINT offset; - unsigned int *data = static_cast(mCountingBuffer->map(spaceNeeded, &offset)); - - if (data) - { - for(int i = 0; i < count; i++) - { - data[i] = i; - } - - mCountingBuffer->unmap(); - } - } - } - else return NULL; - - return mCountingBuffer; -} - -IndexBuffer::IndexBuffer(IDirect3DDevice9 *device, UINT size, D3DFORMAT format) : mDevice(device), mBufferSize(size), mIndexBuffer(NULL) -{ - if (size > 0) - { - D3DPOOL pool = getDisplay()->getBufferPool(D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY); - HRESULT result = device->CreateIndexBuffer(size, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, format, pool, &mIndexBuffer, NULL); - mSerial = issueSerial(); - - if (FAILED(result)) - { - ERR("Out of memory allocating an index buffer of size %lu.", size); - } - } -} - -IndexBuffer::~IndexBuffer() -{ - if (mIndexBuffer) - { - mIndexBuffer->Release(); - } -} - -IDirect3DIndexBuffer9 *IndexBuffer::getBuffer() const -{ - return mIndexBuffer; -} - -unsigned int IndexBuffer::getSerial() const -{ - return mSerial; -} - -unsigned int IndexBuffer::issueSerial() -{ - return mCurrentSerial++; -} - -void IndexBuffer::unmap() -{ - if (mIndexBuffer) - { - mIndexBuffer->Unlock(); - } -} - -StreamingIndexBuffer::StreamingIndexBuffer(IDirect3DDevice9 *device, UINT initialSize, D3DFORMAT format) : IndexBuffer(device, initialSize, format) -{ - mWritePosition = 0; -} - -StreamingIndexBuffer::~StreamingIndexBuffer() -{ -} - -void *StreamingIndexBuffer::map(UINT requiredSpace, UINT *offset) -{ - void *mapPtr = NULL; - - if (mIndexBuffer) - { - HRESULT result = mIndexBuffer->Lock(mWritePosition, requiredSpace, &mapPtr, D3DLOCK_NOOVERWRITE); - - if (FAILED(result)) - { - ERR(" Lock failed with error 0x%08x", result); - return NULL; - } - - *offset = mWritePosition; - mWritePosition += requiredSpace; - } - - return mapPtr; -} - -void StreamingIndexBuffer::reserveSpace(UINT requiredSpace, GLenum type) -{ - if (requiredSpace > mBufferSize) - { - if (mIndexBuffer) - { - mIndexBuffer->Release(); - mIndexBuffer = NULL; - } - - mBufferSize = std::max(requiredSpace, 2 * mBufferSize); - - D3DPOOL pool = getDisplay()->getBufferPool(D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY); - HRESULT result = mDevice->CreateIndexBuffer(mBufferSize, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, type == GL_UNSIGNED_INT ? D3DFMT_INDEX32 : D3DFMT_INDEX16, pool, &mIndexBuffer, NULL); - mSerial = issueSerial(); - - if (FAILED(result)) - { - ERR("Out of memory allocating a vertex buffer of size %lu.", mBufferSize); - } - - mWritePosition = 0; - } - else if (mWritePosition + requiredSpace > mBufferSize || - mWritePosition + requiredSpace < mWritePosition) // Recycle - { - void *dummy; - mIndexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD); - mIndexBuffer->Unlock(); - - mWritePosition = 0; - } -} - -StaticIndexBuffer::StaticIndexBuffer(IDirect3DDevice9 *device) : IndexBuffer(device, 0, D3DFMT_UNKNOWN) -{ - mCacheType = GL_NONE; -} - -StaticIndexBuffer::~StaticIndexBuffer() -{ -} - -void *StaticIndexBuffer::map(UINT requiredSpace, UINT *offset) -{ - void *mapPtr = NULL; - - if (mIndexBuffer) - { - HRESULT result = mIndexBuffer->Lock(0, requiredSpace, &mapPtr, 0); - - if (FAILED(result)) - { - ERR(" Lock failed with error 0x%08x", result); - return NULL; - } - - *offset = 0; - } - - return mapPtr; -} - -void StaticIndexBuffer::reserveSpace(UINT requiredSpace, GLenum type) -{ - if (!mIndexBuffer && mBufferSize == 0) - { - D3DPOOL pool = getDisplay()->getBufferPool(D3DUSAGE_WRITEONLY); - HRESULT result = mDevice->CreateIndexBuffer(requiredSpace, D3DUSAGE_WRITEONLY, type == GL_UNSIGNED_INT ? D3DFMT_INDEX32 : D3DFMT_INDEX16, pool, &mIndexBuffer, NULL); - mSerial = issueSerial(); - - if (FAILED(result)) - { - ERR("Out of memory allocating a vertex buffer of size %lu.", mBufferSize); - } - - mBufferSize = requiredSpace; - mCacheType = type; - } - else if (mIndexBuffer && mBufferSize >= requiredSpace && mCacheType == type) - { - // Already allocated - } - else UNREACHABLE(); // Static index buffers can't be resized -} - -bool StaticIndexBuffer::lookupType(GLenum type) -{ - return mCacheType == type; -} - -UINT StaticIndexBuffer::lookupRange(intptr_t offset, GLsizei count, UINT *minIndex, UINT *maxIndex) -{ - IndexRange range = {offset, count}; - - std::map::iterator res = mCache.find(range); - - if (res == mCache.end()) - { - return -1; - } - - *minIndex = res->second.minIndex; - *maxIndex = res->second.maxIndex; - return res->second.streamOffset; -} - -void StaticIndexBuffer::addRange(intptr_t offset, GLsizei count, UINT minIndex, UINT maxIndex, UINT streamOffset) -{ - IndexRange indexRange = {offset, count}; - IndexResult indexResult = {minIndex, maxIndex, streamOffset}; - mCache[indexRange] = indexResult; -} - -} diff --git a/gfx/angle/src/libGLESv2/IndexDataManager.h b/gfx/angle/src/libGLESv2/IndexDataManager.h deleted file mode 100644 index c1d4168315f8..000000000000 --- a/gfx/angle/src/libGLESv2/IndexDataManager.h +++ /dev/null @@ -1,149 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// IndexDataManager.h: Defines the IndexDataManager, a class that -// runs the Buffer translation process for index buffers. - -#ifndef LIBGLESV2_INDEXDATAMANAGER_H_ -#define LIBGLESV2_INDEXDATAMANAGER_H_ - -#include -#include - -#define GL_APICALL -#include - -#include "libGLESv2/Context.h" - -namespace -{ - enum { INITIAL_INDEX_BUFFER_SIZE = 4096 * sizeof(GLuint) }; -} - -namespace gl -{ - -struct TranslatedIndexData -{ - UINT minIndex; - UINT maxIndex; - UINT startIndex; - - IDirect3DIndexBuffer9 *indexBuffer; - unsigned int serial; -}; - -class IndexBuffer -{ - public: - IndexBuffer(IDirect3DDevice9 *device, UINT size, D3DFORMAT format); - virtual ~IndexBuffer(); - - UINT size() const { return mBufferSize; } - virtual void *map(UINT requiredSpace, UINT *offset) = 0; - void unmap(); - virtual void reserveSpace(UINT requiredSpace, GLenum type) = 0; - - IDirect3DIndexBuffer9 *getBuffer() const; - unsigned int getSerial() const; - - protected: - IDirect3DDevice9 *const mDevice; - - IDirect3DIndexBuffer9 *mIndexBuffer; - UINT mBufferSize; - - unsigned int mSerial; - static unsigned int issueSerial(); - static unsigned int mCurrentSerial; - - private: - DISALLOW_COPY_AND_ASSIGN(IndexBuffer); -}; - -class StreamingIndexBuffer : public IndexBuffer -{ - public: - StreamingIndexBuffer(IDirect3DDevice9 *device, UINT initialSize, D3DFORMAT format); - ~StreamingIndexBuffer(); - - virtual void *map(UINT requiredSpace, UINT *offset); - virtual void reserveSpace(UINT requiredSpace, GLenum type); - - private: - UINT mWritePosition; -}; - -class StaticIndexBuffer : public IndexBuffer -{ - public: - explicit StaticIndexBuffer(IDirect3DDevice9 *device); - ~StaticIndexBuffer(); - - virtual void *map(UINT requiredSpace, UINT *offset); - virtual void reserveSpace(UINT requiredSpace, GLenum type); - - bool lookupType(GLenum type); - UINT lookupRange(intptr_t offset, GLsizei count, UINT *minIndex, UINT *maxIndex); // Returns the offset into the index buffer, or -1 if not found - void addRange(intptr_t offset, GLsizei count, UINT minIndex, UINT maxIndex, UINT streamOffset); - - private: - GLenum mCacheType; - - struct IndexRange - { - intptr_t offset; - GLsizei count; - - bool operator<(const IndexRange& rhs) const - { - if (offset != rhs.offset) - { - return offset < rhs.offset; - } - if (count != rhs.count) - { - return count < rhs.count; - } - return false; - } - }; - - struct IndexResult - { - UINT minIndex; - UINT maxIndex; - UINT streamOffset; - }; - - std::map mCache; -}; - -class IndexDataManager -{ - public: - IndexDataManager(Context *context, IDirect3DDevice9 *evice); - virtual ~IndexDataManager(); - - GLenum prepareIndexData(GLenum type, GLsizei count, Buffer *arrayElementBuffer, const GLvoid *indices, TranslatedIndexData *translated); - StaticIndexBuffer *getCountingIndices(GLsizei count); - - private: - DISALLOW_COPY_AND_ASSIGN(IndexDataManager); - - std::size_t typeSize(GLenum type) const; - std::size_t indexSize(D3DFORMAT format) const; - - IDirect3DDevice9 *const mDevice; - - StreamingIndexBuffer *mStreamingBufferShort; - StreamingIndexBuffer *mStreamingBufferInt; - StaticIndexBuffer *mCountingBuffer; -}; - -} - -#endif // LIBGLESV2_INDEXDATAMANAGER_H_ diff --git a/gfx/angle/src/libGLESv2/Makefile.in b/gfx/angle/src/libGLESv2/Makefile.in index d7bba7508d97..7b9ddd4c667e 100644 --- a/gfx/angle/src/libGLESv2/Makefile.in +++ b/gfx/angle/src/libGLESv2/Makefile.in @@ -1,4 +1,3 @@ -# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -20,7 +19,8 @@ endif OS_COMPILE_CFLAGS = $(OS_CPPFLAGS) OS_COMPILE_CXXFLAGS = $(OS_CPPFLAGS) -DEFINES += -DANGLE_BUILD -DNOMINMAX -DLIBGLESV2_EXPORTS -D_CRT_SECURE_NO_DEPRECATE +DEFINES += -DLIBGLESV2_EXPORTS +DEFINES += -DANGLE_BUILD -DNOMINMAX -D_CRT_SECURE_NO_DEPRECATE ifndef MOZ_DEBUG DEFINES += -D_SECURE_SCL=0 @@ -28,7 +28,6 @@ endif # The below is a rough translation of build_angle.gypi, # copied from src/Makefile.in. - DEFINES += -DANGLE_DISABLE_TRACE DEFINES += -DANGLE_COMPILE_OPTIMIZATION_LEVEL=D3DCOMPILE_OPTIMIZATION_LEVEL1 @@ -45,22 +44,16 @@ LOCAL_INCLUDES += \ DEFINES += -DCOMPILER_IMPLEMENTATION +VPATH += $(srcdir)/renderer +VPATH += $(srcdir)/.. VPATH += $(srcdir)/../compiler VPATH += $(srcdir)/../compiler/depgraph VPATH += $(srcdir)/../compiler/timing VPATH += $(srcdir)/../third_party/compiler +VPATH += $(srcdir)/../third_party/murmurhash # Above should match the relevant targets from angle/Makefile.in. -# Below is a transcription of more targets from build_angle.gypi. - -# Target: 'translator_hlsl' -# Requires: 'translator_common' - -# Target: 'libGLESv2' -# Requires: 'translator_hlsl' -LOCAL_INCLUDES += -I"$(MOZ_DIRECTX_SDK_PATH)/include" - VPATH += $(srcdir)/../common # src/common: DEFFILE = $(srcdir)/libGLESv2.def @@ -75,10 +68,12 @@ ifdef GNU_CC TextureSSE2.$(OBJ_SUFFIX): CXXFLAGS+=-msse2 OS_CXXFLAGS := $(filter-out -fno-exceptions,$(OS_CXXFLAGS)) -fexceptions -OS_LIBS += -ld3d9 +OS_LIBS += -ld3d9 -ldxguid else -EXTRA_DSO_LDOPTS = "$(MOZ_DIRECTX_SDK_PATH)/lib/$(MOZ_DIRECTX_SDK_CPU_SUFFIX)/d3d9.lib" +EXTRA_DSO_LDOPTS = "$(MOZ_DIRECTX_SDK_PATH)/lib/$(MOZ_DIRECTX_SDK_CPU_SUFFIX)/d3d9.lib" \ + "$(MOZ_DIRECTX_SDK_PATH)/lib/$(MOZ_DIRECTX_SDK_CPU_SUFFIX)/dxguid.lib" \ + delayimp.lib endif diff --git a/gfx/angle/src/libGLESv2/Program.cpp b/gfx/angle/src/libGLESv2/Program.cpp index 5f53a1f5817f..c38aa5a61aa3 100644 --- a/gfx/angle/src/libGLESv2/Program.cpp +++ b/gfx/angle/src/libGLESv2/Program.cpp @@ -1,5 +1,6 @@ +#include "precompiled.h" // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -9,14 +10,7 @@ #include "libGLESv2/Program.h" #include "libGLESv2/ProgramBinary.h" - -#include "common/debug.h" - -#include "libGLESv2/main.h" -#include "libGLESv2/Shader.h" -#include "libGLESv2/utilities.h" - -#include +#include "libGLESv2/ResourceManager.h" namespace gl { @@ -91,7 +85,7 @@ void InfoLog::appendSanitized(const char *message) } while (found != std::string::npos); - append("%s\n", msg.c_str()); + append("%s", msg.c_str()); } void InfoLog::append(const char *format, ...) @@ -112,15 +106,17 @@ void InfoLog::append(const char *format, ...) if (!mInfoLog) { - mInfoLog = new char[infoLength + 1]; + mInfoLog = new char[infoLength + 2]; strcpy(mInfoLog, info); + strcpy(mInfoLog + infoLength, "\n"); } else { size_t logLength = strlen(mInfoLog); - char *newLog = new char[logLength + infoLength + 1]; + char *newLog = new char[logLength + infoLength + 2]; strcpy(newLog, mInfoLog); strcpy(newLog + logLength, info); + strcpy(newLog + logLength + infoLength, "\n"); delete[] mInfoLog; mInfoLog = newLog; @@ -136,7 +132,7 @@ void InfoLog::reset() } } -Program::Program(ResourceManager *manager, GLuint handle) : mResourceManager(manager), mHandle(handle) +Program::Program(rx::Renderer *renderer, ResourceManager *manager, GLuint handle) : mResourceManager(manager), mHandle(handle) { mFragmentShader = NULL; mVertexShader = NULL; @@ -144,6 +140,7 @@ Program::Program(ResourceManager *manager, GLuint handle) : mResourceManager(man mDeleteStatus = false; mLinked = false; mRefCount = 0; + mRenderer = renderer; } Program::~Program() @@ -247,7 +244,7 @@ bool Program::link() mInfoLog.reset(); - mProgramBinary.set(new ProgramBinary()); + mProgramBinary.set(new ProgramBinary(mRenderer)); mLinked = mProgramBinary->link(mInfoLog, mAttributeBindings, mFragmentShader, mVertexShader); return mLinked; @@ -304,7 +301,7 @@ bool Program::setProgramBinary(const void *binary, GLsizei length) mInfoLog.reset(); - mProgramBinary.set(new ProgramBinary()); + mProgramBinary.set(new ProgramBinary(mRenderer)); mLinked = mProgramBinary->load(mInfoLog, binary, length); if (!mLinked) { diff --git a/gfx/angle/src/libGLESv2/Program.h b/gfx/angle/src/libGLESv2/Program.h index 1c4716bfe83b..a9db83403d9f 100644 --- a/gfx/angle/src/libGLESv2/Program.h +++ b/gfx/angle/src/libGLESv2/Program.h @@ -13,14 +13,22 @@ #include #include -#include "libGLESv2/Shader.h" -#include "libGLESv2/Context.h" +#include "common/angleutils.h" +#include "common/RefCountObject.h" +#include "libGLESv2/Constants.h" + +namespace rx +{ +class Renderer; +} namespace gl { class ResourceManager; class FragmentShader; class VertexShader; +class ProgramBinary; +class Shader; extern const char * const g_fakepath; @@ -57,7 +65,7 @@ class InfoLog class Program { public: - Program(ResourceManager *manager, GLuint handle); + Program(rx::Renderer *renderer, ResourceManager *manager, GLuint handle); ~Program(); @@ -112,6 +120,7 @@ class Program unsigned int mRefCount; ResourceManager *mResourceManager; + rx::Renderer *mRenderer; const GLuint mHandle; InfoLog mInfoLog; diff --git a/gfx/angle/src/libGLESv2/ProgramBinary.cpp b/gfx/angle/src/libGLESv2/ProgramBinary.cpp index 2c57c62399b0..135facd89a04 100644 --- a/gfx/angle/src/libGLESv2/ProgramBinary.cpp +++ b/gfx/angle/src/libGLESv2/ProgramBinary.cpp @@ -1,5 +1,6 @@ +#include "precompiled.h" // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -8,21 +9,21 @@ // and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28. #include "libGLESv2/BinaryStream.h" -#include "libGLESv2/Program.h" #include "libGLESv2/ProgramBinary.h" +#include "libGLESv2/renderer/ShaderExecutable.h" #include "common/debug.h" #include "common/version.h" +#include "utilities.h" #include "libGLESv2/main.h" #include "libGLESv2/Shader.h" -#include "libGLESv2/utilities.h" +#include "libGLESv2/Program.h" +#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/renderer/VertexDataManager.h" -#include - -#if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL) -#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3 -#endif +#undef near +#undef far namespace gl { @@ -33,43 +34,18 @@ std::string str(int i) return buffer; } -Uniform::Uniform(GLenum type, const std::string &_name, unsigned int arraySize) - : type(type), _name(_name), name(ProgramBinary::undecorateUniform(_name)), arraySize(arraySize) -{ - int bytes = UniformInternalSize(type) * arraySize; - data = new unsigned char[bytes]; - memset(data, 0, bytes); - dirty = true; -} - -Uniform::~Uniform() -{ - delete[] data; -} - -bool Uniform::isArray() -{ - size_t dot = _name.find_last_of('.'); - if (dot == std::string::npos) dot = -1; - - return _name.compare(dot + 1, dot + 4, "ar_") == 0; -} - -UniformLocation::UniformLocation(const std::string &_name, unsigned int element, unsigned int index) - : name(ProgramBinary::undecorateUniform(_name)), element(element), index(index) +UniformLocation::UniformLocation(const std::string &name, unsigned int element, unsigned int index) + : name(name), element(element), index(index) { } unsigned int ProgramBinary::mCurrentSerial = 1; -ProgramBinary::ProgramBinary() : RefCountObject(0), mSerial(issueSerial()) +ProgramBinary::ProgramBinary(rx::Renderer *renderer) : mRenderer(renderer), RefCountObject(0), mSerial(issueSerial()) { - mDevice = getDevice(); - mPixelExecutable = NULL; mVertexExecutable = NULL; - mConstantTablePS = NULL; - mConstantTableVS = NULL; + mGeometryExecutable = NULL; mValidated = false; @@ -83,36 +59,26 @@ ProgramBinary::ProgramBinary() : RefCountObject(0), mSerial(issueSerial()) mSamplersPS[index].active = false; } - for (int index = 0; index < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; index++) + for (int index = 0; index < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; index++) { mSamplersVS[index].active = false; } mUsedVertexSamplerRange = 0; mUsedPixelSamplerRange = 0; - - mDxDepthRangeLocation = -1; - mDxDepthLocation = -1; - mDxCoordLocation = -1; - mDxHalfPixelSizeLocation = -1; - mDxFrontCCWLocation = -1; - mDxPointsOrLinesLocation = -1; + mUsesPointSize = false; } ProgramBinary::~ProgramBinary() { - if (mPixelExecutable) - { - mPixelExecutable->Release(); - } + delete mPixelExecutable; + mPixelExecutable = NULL; - if (mVertexExecutable) - { - mVertexExecutable->Release(); - } + delete mVertexExecutable; + mVertexExecutable = NULL; - delete mConstantTablePS; - delete mConstantTableVS; + delete mGeometryExecutable; + mGeometryExecutable = NULL; while (!mUniforms.empty()) { @@ -131,16 +97,21 @@ unsigned int ProgramBinary::issueSerial() return mCurrentSerial++; } -IDirect3DPixelShader9 *ProgramBinary::getPixelShader() +rx::ShaderExecutable *ProgramBinary::getPixelExecutable() { return mPixelExecutable; } -IDirect3DVertexShader9 *ProgramBinary::getVertexShader() +rx::ShaderExecutable *ProgramBinary::getVertexExecutable() { return mVertexExecutable; } +rx::ShaderExecutable *ProgramBinary::getGeometryExecutable() +{ + return mGeometryExecutable; +} + GLuint ProgramBinary::getAttributeLocation(const char *name) { if (name) @@ -184,6 +155,16 @@ bool ProgramBinary::usesPointSize() const return mUsesPointSize; } +bool ProgramBinary::usesPointSpriteEmulation() const +{ + return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4; +} + +bool ProgramBinary::usesGeometryShader() const +{ + return usesPointSpriteEmulation(); +} + // Returns the index of the texture image unit (0-19) corresponding to a Direct3D 9 sampler // index (0-15 for the pixel shader and 0-3 for the vertex shader). GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerIndex) @@ -211,7 +192,7 @@ GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerInd default: UNREACHABLE(); } - if (logicalTextureUnit >= 0 && logicalTextureUnit < (GLint)getContext()->getMaximumCombinedTextureImageUnits()) + if (logicalTextureUnit >= 0 && logicalTextureUnit < (GLint)mRenderer->getMaxCombinedTextureImageUnits()) { return logicalTextureUnit; } @@ -275,15 +256,15 @@ bool ProgramBinary::setUniform1fv(GLint location, GLsizei count, const GLfloat* Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; targetUniform->dirty = true; + int elementCount = targetUniform->elementCount(); + + if (elementCount == 1 && count > 1) + return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION + + count = std::min(elementCount - (int)mUniformIndex[location].element, count); + if (targetUniform->type == GL_FLOAT) { - int arraySize = targetUniform->arraySize; - - if (arraySize == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION - - count = std::min(arraySize - (int)mUniformIndex[location].element, count); - GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4; for (int i = 0; i < count; i++) @@ -298,24 +279,16 @@ bool ProgramBinary::setUniform1fv(GLint location, GLsizei count, const GLfloat* } else if (targetUniform->type == GL_BOOL) { - int arraySize = targetUniform->arraySize; + GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - if (arraySize == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION - - count = std::min(arraySize - (int)mUniformIndex[location].element, count); - GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element; - - for (int i = 0; i < count; ++i) + for (int i = 0; i < count; i++) { - if (v[i] == 0.0f) - { - boolParams[i] = GL_FALSE; - } - else - { - boolParams[i] = GL_TRUE; - } + boolParams[0] = (v[0] == 0.0f) ? GL_FALSE : GL_TRUE; + boolParams[1] = GL_FALSE; + boolParams[2] = GL_FALSE; + boolParams[3] = GL_FALSE; + boolParams += 4; + v += 1; } } else @@ -336,15 +309,15 @@ bool ProgramBinary::setUniform2fv(GLint location, GLsizei count, const GLfloat * Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; targetUniform->dirty = true; + int elementCount = targetUniform->elementCount(); + + if (elementCount == 1 && count > 1) + return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION + + count = std::min(elementCount - (int)mUniformIndex[location].element, count); + if (targetUniform->type == GL_FLOAT_VEC2) { - int arraySize = targetUniform->arraySize; - - if (arraySize == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION - - count = std::min(arraySize - (int)mUniformIndex[location].element, count); - GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4; for (int i = 0; i < count; i++) @@ -359,25 +332,16 @@ bool ProgramBinary::setUniform2fv(GLint location, GLsizei count, const GLfloat * } else if (targetUniform->type == GL_BOOL_VEC2) { - int arraySize = targetUniform->arraySize; + GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - if (arraySize == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION - - count = std::min(arraySize - (int)mUniformIndex[location].element, count); - - GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * 2; - - for (int i = 0; i < count * 2; ++i) + for (int i = 0; i < count; i++) { - if (v[i] == 0.0f) - { - boolParams[i] = GL_FALSE; - } - else - { - boolParams[i] = GL_TRUE; - } + boolParams[0] = (v[0] == 0.0f) ? GL_FALSE : GL_TRUE; + boolParams[1] = (v[1] == 0.0f) ? GL_FALSE : GL_TRUE; + boolParams[2] = GL_FALSE; + boolParams[3] = GL_FALSE; + boolParams += 4; + v += 2; } } else @@ -398,15 +362,15 @@ bool ProgramBinary::setUniform3fv(GLint location, GLsizei count, const GLfloat * Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; targetUniform->dirty = true; + int elementCount = targetUniform->elementCount(); + + if (elementCount == 1 && count > 1) + return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION + + count = std::min(elementCount - (int)mUniformIndex[location].element, count); + if (targetUniform->type == GL_FLOAT_VEC3) { - int arraySize = targetUniform->arraySize; - - if (arraySize == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION - - count = std::min(arraySize - (int)mUniformIndex[location].element, count); - GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4; for (int i = 0; i < count; i++) @@ -421,24 +385,16 @@ bool ProgramBinary::setUniform3fv(GLint location, GLsizei count, const GLfloat * } else if (targetUniform->type == GL_BOOL_VEC3) { - int arraySize = targetUniform->arraySize; + GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - if (arraySize == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION - - count = std::min(arraySize - (int)mUniformIndex[location].element, count); - GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * 3; - - for (int i = 0; i < count * 3; ++i) + for (int i = 0; i < count; i++) { - if (v[i] == 0.0f) - { - boolParams[i] = GL_FALSE; - } - else - { - boolParams[i] = GL_TRUE; - } + boolParams[0] = (v[0] == 0.0f) ? GL_FALSE : GL_TRUE; + boolParams[1] = (v[1] == 0.0f) ? GL_FALSE : GL_TRUE; + boolParams[2] = (v[2] == 0.0f) ? GL_FALSE : GL_TRUE; + boolParams[3] = GL_FALSE; + boolParams += 4; + v += 3; } } else @@ -459,38 +415,39 @@ bool ProgramBinary::setUniform4fv(GLint location, GLsizei count, const GLfloat * Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; targetUniform->dirty = true; + int elementCount = targetUniform->elementCount(); + + if (elementCount == 1 && count > 1) + return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION + + count = std::min(elementCount - (int)mUniformIndex[location].element, count); + if (targetUniform->type == GL_FLOAT_VEC4) { - int arraySize = targetUniform->arraySize; + GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4; - if (arraySize == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION - - count = std::min(arraySize - (int)mUniformIndex[location].element, count); - - memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 4, - v, 4 * sizeof(GLfloat) * count); + for (int i = 0; i < count; i++) + { + target[0] = v[0]; + target[1] = v[1]; + target[2] = v[2]; + target[3] = v[3]; + target += 4; + v += 4; + } } else if (targetUniform->type == GL_BOOL_VEC4) { - int arraySize = targetUniform->arraySize; + GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - if (arraySize == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION - - count = std::min(arraySize - (int)mUniformIndex[location].element, count); - GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * 4; - - for (int i = 0; i < count * 4; ++i) + for (int i = 0; i < count; i++) { - if (v[i] == 0.0f) - { - boolParams[i] = GL_FALSE; - } - else - { - boolParams[i] = GL_TRUE; - } + boolParams[0] = (v[0] == 0.0f) ? GL_FALSE : GL_TRUE; + boolParams[1] = (v[1] == 0.0f) ? GL_FALSE : GL_TRUE; + boolParams[2] = (v[2] == 0.0f) ? GL_FALSE : GL_TRUE; + boolParams[3] = (v[3] == 0.0f) ? GL_FALSE : GL_TRUE; + boolParams += 4; + v += 4; } } else @@ -547,14 +504,14 @@ bool ProgramBinary::setUniformMatrix2fv(GLint location, GLsizei count, const GLf return false; } - int arraySize = targetUniform->arraySize; + int elementCount = targetUniform->elementCount(); - if (arraySize == 1 && count > 1) + if (elementCount == 1 && count > 1) return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION - count = std::min(arraySize - (int)mUniformIndex[location].element, count); - + count = std::min(elementCount - (int)mUniformIndex[location].element, count); GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 8; + for (int i = 0; i < count; i++) { transposeMatrix(target, value); @@ -580,14 +537,14 @@ bool ProgramBinary::setUniformMatrix3fv(GLint location, GLsizei count, const GLf return false; } - int arraySize = targetUniform->arraySize; + int elementCount = targetUniform->elementCount(); - if (arraySize == 1 && count > 1) + if (elementCount == 1 && count > 1) return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION - count = std::min(arraySize - (int)mUniformIndex[location].element, count); - + count = std::min(elementCount - (int)mUniformIndex[location].element, count); GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 12; + for (int i = 0; i < count; i++) { transposeMatrix(target, value); @@ -614,14 +571,14 @@ bool ProgramBinary::setUniformMatrix4fv(GLint location, GLsizei count, const GLf return false; } - int arraySize = targetUniform->arraySize; + int elementCount = targetUniform->elementCount(); - if (arraySize == 1 && count > 1) + if (elementCount == 1 && count > 1) return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION - count = std::min(arraySize - (int)mUniformIndex[location].element, count); - + count = std::min(elementCount - (int)mUniformIndex[location].element, count); GLfloat *target = (GLfloat*)(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 16); + for (int i = 0; i < count; i++) { transposeMatrix(target, value); @@ -642,40 +599,41 @@ bool ProgramBinary::setUniform1iv(GLint location, GLsizei count, const GLint *v) Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; targetUniform->dirty = true; + int elementCount = targetUniform->elementCount(); + + if (elementCount == 1 && count > 1) + return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION + + count = std::min(elementCount - (int)mUniformIndex[location].element, count); + if (targetUniform->type == GL_INT || targetUniform->type == GL_SAMPLER_2D || targetUniform->type == GL_SAMPLER_CUBE) { - int arraySize = targetUniform->arraySize; + GLint *target = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - if (arraySize == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION - - count = std::min(arraySize - (int)mUniformIndex[location].element, count); - - memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLint), - v, sizeof(GLint) * count); + for (int i = 0; i < count; i++) + { + target[0] = v[0]; + target[1] = 0; + target[2] = 0; + target[3] = 0; + target += 4; + v += 1; + } } else if (targetUniform->type == GL_BOOL) { - int arraySize = targetUniform->arraySize; + GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - if (arraySize == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION - - count = std::min(arraySize - (int)mUniformIndex[location].element, count); - GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element; - - for (int i = 0; i < count; ++i) + for (int i = 0; i < count; i++) { - if (v[i] == 0) - { - boolParams[i] = GL_FALSE; - } - else - { - boolParams[i] = GL_TRUE; - } + boolParams[0] = (v[0] == 0) ? GL_FALSE : GL_TRUE; + boolParams[1] = GL_FALSE; + boolParams[2] = GL_FALSE; + boolParams[3] = GL_FALSE; + boolParams += 4; + v += 1; } } else @@ -696,38 +654,39 @@ bool ProgramBinary::setUniform2iv(GLint location, GLsizei count, const GLint *v) Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; targetUniform->dirty = true; + int elementCount = targetUniform->elementCount(); + + if (elementCount == 1 && count > 1) + return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION + + count = std::min(elementCount - (int)mUniformIndex[location].element, count); + if (targetUniform->type == GL_INT_VEC2) { - int arraySize = targetUniform->arraySize; + GLint *target = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - if (arraySize == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION - - count = std::min(arraySize - (int)mUniformIndex[location].element, count); - - memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLint) * 2, - v, 2 * sizeof(GLint) * count); + for (int i = 0; i < count; i++) + { + target[0] = v[0]; + target[1] = v[1]; + target[2] = 0; + target[3] = 0; + target += 4; + v += 2; + } } else if (targetUniform->type == GL_BOOL_VEC2) { - int arraySize = targetUniform->arraySize; + GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - if (arraySize == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION - - count = std::min(arraySize - (int)mUniformIndex[location].element, count); - GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * 2; - - for (int i = 0; i < count * 2; ++i) + for (int i = 0; i < count; i++) { - if (v[i] == 0) - { - boolParams[i] = GL_FALSE; - } - else - { - boolParams[i] = GL_TRUE; - } + boolParams[0] = (v[0] == 0) ? GL_FALSE : GL_TRUE; + boolParams[1] = (v[1] == 0) ? GL_FALSE : GL_TRUE; + boolParams[2] = GL_FALSE; + boolParams[3] = GL_FALSE; + boolParams += 4; + v += 2; } } else @@ -748,38 +707,39 @@ bool ProgramBinary::setUniform3iv(GLint location, GLsizei count, const GLint *v) Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; targetUniform->dirty = true; + int elementCount = targetUniform->elementCount(); + + if (elementCount == 1 && count > 1) + return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION + + count = std::min(elementCount - (int)mUniformIndex[location].element, count); + if (targetUniform->type == GL_INT_VEC3) { - int arraySize = targetUniform->arraySize; + GLint *target = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - if (arraySize == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION - - count = std::min(arraySize - (int)mUniformIndex[location].element, count); - - memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLint) * 3, - v, 3 * sizeof(GLint) * count); + for (int i = 0; i < count; i++) + { + target[0] = v[0]; + target[1] = v[1]; + target[2] = v[2]; + target[3] = 0; + target += 4; + v += 3; + } } else if (targetUniform->type == GL_BOOL_VEC3) { - int arraySize = targetUniform->arraySize; + GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - if (arraySize == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION - - count = std::min(arraySize - (int)mUniformIndex[location].element, count); - GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * 3; - - for (int i = 0; i < count * 3; ++i) + for (int i = 0; i < count; i++) { - if (v[i] == 0) - { - boolParams[i] = GL_FALSE; - } - else - { - boolParams[i] = GL_TRUE; - } + boolParams[0] = (v[0] == 0) ? GL_FALSE : GL_TRUE; + boolParams[1] = (v[1] == 0) ? GL_FALSE : GL_TRUE; + boolParams[2] = (v[2] == 0) ? GL_FALSE : GL_TRUE; + boolParams[3] = GL_FALSE; + boolParams += 4; + v += 3; } } else @@ -800,38 +760,39 @@ bool ProgramBinary::setUniform4iv(GLint location, GLsizei count, const GLint *v) Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; targetUniform->dirty = true; + int elementCount = targetUniform->elementCount(); + + if (elementCount == 1 && count > 1) + return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION + + count = std::min(elementCount - (int)mUniformIndex[location].element, count); + if (targetUniform->type == GL_INT_VEC4) { - int arraySize = targetUniform->arraySize; + GLint *target = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - if (arraySize == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION - - count = std::min(arraySize - (int)mUniformIndex[location].element, count); - - memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLint) * 4, - v, 4 * sizeof(GLint) * count); + for (int i = 0; i < count; i++) + { + target[0] = v[0]; + target[1] = v[1]; + target[2] = v[2]; + target[3] = v[3]; + target += 4; + v += 4; + } } else if (targetUniform->type == GL_BOOL_VEC4) { - int arraySize = targetUniform->arraySize; + GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - if (arraySize == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION - - count = std::min(arraySize - (int)mUniformIndex[location].element, count); - GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * 4; - - for (int i = 0; i < count * 4; ++i) + for (int i = 0; i < count; i++) { - if (v[i] == 0) - { - boolParams[i] = GL_FALSE; - } - else - { - boolParams[i] = GL_TRUE; - } + boolParams[0] = (v[0] == 0) ? GL_FALSE : GL_TRUE; + boolParams[1] = (v[1] == 0) ? GL_FALSE : GL_TRUE; + boolParams[2] = (v[2] == 0) ? GL_FALSE : GL_TRUE; + boolParams[3] = (v[3] == 0) ? GL_FALSE : GL_TRUE; + boolParams += 4; + v += 4; } } else @@ -874,30 +835,29 @@ bool ProgramBinary::getUniformfv(GLint location, GLsizei *bufSize, GLfloat *para break; default: { - unsigned int count = UniformExternalComponentCount(targetUniform->type); - unsigned int internalCount = UniformInternalComponentCount(targetUniform->type); + unsigned int size = UniformComponentCount(targetUniform->type); switch (UniformComponentType(targetUniform->type)) { case GL_BOOL: { - GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * internalCount; + GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - for (unsigned int i = 0; i < count; ++i) + for (unsigned int i = 0; i < size; i++) { params[i] = (boolParams[i] == GL_FALSE) ? 0.0f : 1.0f; } } break; case GL_FLOAT: - memcpy(params, targetUniform->data + mUniformIndex[location].element * internalCount * sizeof(GLfloat), - count * sizeof(GLfloat)); + memcpy(params, targetUniform->data + mUniformIndex[location].element * 4 * sizeof(GLfloat), + size * sizeof(GLfloat)); break; case GL_INT: { - GLint *intParams = (GLint*)targetUniform->data + mUniformIndex[location].element * internalCount; + GLint *intParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - for (unsigned int i = 0; i < count; ++i) + for (unsigned int i = 0; i < size; i++) { params[i] = (float)intParams[i]; } @@ -933,50 +893,43 @@ bool ProgramBinary::getUniformiv(GLint location, GLsizei *bufSize, GLint *params switch (targetUniform->type) { case GL_FLOAT_MAT2: - { - transposeMatrix(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 8); - } + transposeMatrix(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 8); break; case GL_FLOAT_MAT3: - { - transposeMatrix(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 12); - } + transposeMatrix(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 12); break; case GL_FLOAT_MAT4: - { - transposeMatrix(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 16); - } + transposeMatrix(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 16); break; default: { - unsigned int count = UniformExternalComponentCount(targetUniform->type); - unsigned int internalCount = UniformInternalComponentCount(targetUniform->type); + unsigned int size = VariableColumnCount(targetUniform->type); switch (UniformComponentType(targetUniform->type)) { case GL_BOOL: { - GLboolean *boolParams = targetUniform->data + mUniformIndex[location].element * internalCount; + GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - for (unsigned int i = 0; i < count; ++i) + for (unsigned int i = 0; i < size; i++) { - params[i] = (GLint)boolParams[i]; + params[i] = boolParams[i]; } } break; case GL_FLOAT: { - GLfloat *floatParams = (GLfloat*)targetUniform->data + mUniformIndex[location].element * internalCount; + GLfloat *floatParams = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4; - for (unsigned int i = 0; i < count; ++i) + for (unsigned int i = 0; i < size; i++) { params[i] = (GLint)floatParams[i]; } } break; case GL_INT: - memcpy(params, targetUniform->data + mUniformIndex[location].element * internalCount * sizeof(GLint), - count * sizeof(GLint)); + memcpy(params, targetUniform->data + mUniformIndex[location].element * 4 * sizeof(GLint), + size * sizeof(GLint)); break; default: UNREACHABLE(); } @@ -995,152 +948,67 @@ void ProgramBinary::dirtyAllUniforms() } } -// Applies all the uniforms set for this program object to the Direct3D 9 device +// Applies all the uniforms set for this program object to the renderer void ProgramBinary::applyUniforms() { - for (std::vector::iterator ub = mUniforms.begin(), ue = mUniforms.end(); ub != ue; ++ub) { + // Retrieve sampler uniform values + for (std::vector::iterator ub = mUniforms.begin(), ue = mUniforms.end(); ub != ue; ++ub) + { Uniform *targetUniform = *ub; if (targetUniform->dirty) { - int arraySize = targetUniform->arraySize; - GLfloat *f = (GLfloat*)targetUniform->data; - GLint *i = (GLint*)targetUniform->data; - GLboolean *b = (GLboolean*)targetUniform->data; - - switch (targetUniform->type) + if (targetUniform->type == GL_SAMPLER_2D || + targetUniform->type == GL_SAMPLER_CUBE) { - case GL_BOOL: applyUniformnbv(targetUniform, arraySize, 1, b); break; - case GL_BOOL_VEC2: applyUniformnbv(targetUniform, arraySize, 2, b); break; - case GL_BOOL_VEC3: applyUniformnbv(targetUniform, arraySize, 3, b); break; - case GL_BOOL_VEC4: applyUniformnbv(targetUniform, arraySize, 4, b); break; - case GL_FLOAT: - case GL_FLOAT_VEC2: - case GL_FLOAT_VEC3: - case GL_FLOAT_VEC4: - case GL_FLOAT_MAT2: - case GL_FLOAT_MAT3: - case GL_FLOAT_MAT4: applyUniformnfv(targetUniform, f); break; - case GL_SAMPLER_2D: - case GL_SAMPLER_CUBE: - case GL_INT: applyUniform1iv(targetUniform, arraySize, i); break; - case GL_INT_VEC2: applyUniform2iv(targetUniform, arraySize, i); break; - case GL_INT_VEC3: applyUniform3iv(targetUniform, arraySize, i); break; - case GL_INT_VEC4: applyUniform4iv(targetUniform, arraySize, i); break; - default: - UNREACHABLE(); - } + int count = targetUniform->elementCount(); + GLint (*v)[4] = (GLint(*)[4])targetUniform->data; - targetUniform->dirty = false; - } - } -} + if (targetUniform->psRegisterIndex >= 0) + { + unsigned int firstIndex = targetUniform->psRegisterIndex; -// Compiles the HLSL code of the attached shaders into executable binaries -ID3D10Blob *ProgramBinary::compileToBinary(InfoLog &infoLog, const char *hlsl, const char *profile, D3DConstantTable **constantTable) -{ - if (!hlsl) - { - return NULL; - } + for (int i = 0; i < count; i++) + { + unsigned int samplerIndex = firstIndex + i; - HRESULT result = S_OK; - UINT flags = 0; - std::string sourceText; - if (perfActive()) - { - flags |= D3DCOMPILE_DEBUG; -#ifdef NDEBUG - flags |= ANGLE_COMPILE_OPTIMIZATION_LEVEL; -#else - flags |= D3DCOMPILE_SKIP_OPTIMIZATION; -#endif + if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS) + { + ASSERT(mSamplersPS[samplerIndex].active); + mSamplersPS[samplerIndex].logicalTextureUnit = v[i][0]; + } + } + } - std::string sourcePath = getTempPath(); - sourceText = std::string("#line 2 \"") + sourcePath + std::string("\"\n\n") + std::string(hlsl); - writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size()); - } - else - { - flags |= ANGLE_COMPILE_OPTIMIZATION_LEVEL; - sourceText = hlsl; - } + if (targetUniform->vsRegisterIndex >= 0) + { + unsigned int firstIndex = targetUniform->vsRegisterIndex; - // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders when it would otherwise pass with alternative options. - // Try the default flags first and if compilation fails, try some alternatives. - const static UINT extraFlags[] = - { - 0, - D3DCOMPILE_AVOID_FLOW_CONTROL, - D3DCOMPILE_PREFER_FLOW_CONTROL - }; + for (int i = 0; i < count; i++) + { + unsigned int samplerIndex = firstIndex + i; - const static char * const extraFlagNames[] = - { - "default", - "avoid flow control", - "prefer flow control" - }; - - for (int i = 0; i < sizeof(extraFlags) / sizeof(UINT); ++i) - { - ID3D10Blob *errorMessage = NULL; - ID3D10Blob *binary = NULL; - result = getDisplay()->compileShaderSource(hlsl, g_fakepath, profile, flags | extraFlags[i], &binary, &errorMessage); - if (errorMessage) - { - const char *message = (const char*)errorMessage->GetBufferPointer(); - - infoLog.appendSanitized(message); - TRACE("\n%s", hlsl); - TRACE("\n%s", message); - - errorMessage->Release(); - errorMessage = NULL; - } - - if (SUCCEEDED(result)) - { - D3DConstantTable *table = new D3DConstantTable(binary->GetBufferPointer(), binary->GetBufferSize()); - if (table->error()) - { - delete table; - binary->Release(); - return NULL; - } - - *constantTable = table; - - return binary; - } - else - { - if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY) - { - return error(GL_OUT_OF_MEMORY, (ID3D10Blob*) NULL); - } - - infoLog.append("Warning: D3D shader compilation failed with "); - infoLog.append(extraFlagNames[i]); - infoLog.append(" flags."); - if (i + 1 < sizeof(extraFlagNames) / sizeof(char*)) - { - infoLog.append(" Retrying with "); - infoLog.append(extraFlagNames[i + 1]); - infoLog.append(".\n"); + if (samplerIndex < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS) + { + ASSERT(mSamplersVS[samplerIndex].active); + mSamplersVS[samplerIndex].logicalTextureUnit = v[i][0]; + } + } + } } } } - return NULL; + mRenderer->applyUniforms(this, &mUniforms); } // Packs varyings into generic varying registers, using the algorithm from [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111 // Returns the number of used varying registers, or -1 if unsuccesful int ProgramBinary::packVaryings(InfoLog &infoLog, const Varying *packing[][4], FragmentShader *fragmentShader) { - Context *context = getContext(); - const int maxVaryingVectors = context->getMaximumVaryingVectors(); + const int maxVaryingVectors = mRenderer->getMaxVaryingVectors(); + + fragmentShader->resetVaryingsRegisterAssignment(); for (VaryingList::iterator varying = fragmentShader->mVaryings.begin(); varying != fragmentShader->mVaryings.end(); varying++) { @@ -1285,47 +1153,43 @@ int ProgramBinary::packVaryings(InfoLog &infoLog, const Varying *packing[][4], F return registers; } -bool ProgramBinary::linkVaryings(InfoLog &infoLog, std::string& pixelHLSL, std::string& vertexHLSL, FragmentShader *fragmentShader, VertexShader *vertexShader) +bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const Varying *packing[][4], + std::string& pixelHLSL, std::string& vertexHLSL, + FragmentShader *fragmentShader, VertexShader *vertexShader) { if (pixelHLSL.empty() || vertexHLSL.empty()) { return false; } - // Reset the varying register assignments - for (VaryingList::iterator fragVar = fragmentShader->mVaryings.begin(); fragVar != fragmentShader->mVaryings.end(); fragVar++) - { - fragVar->reg = -1; - fragVar->col = -1; - } - - for (VaryingList::iterator vtxVar = vertexShader->mVaryings.begin(); vtxVar != vertexShader->mVaryings.end(); vtxVar++) - { - vtxVar->reg = -1; - vtxVar->col = -1; - } - - // Map the varyings to the register file - const Varying *packing[MAX_VARYING_VECTORS_SM3][4] = {NULL}; - int registers = packVaryings(infoLog, packing, fragmentShader); - - if (registers < 0) + bool usesMRT = fragmentShader->mUsesMultipleRenderTargets; + bool usesFragColor = fragmentShader->mUsesFragColor; + bool usesFragData = fragmentShader->mUsesFragData; + if (usesFragColor && usesFragData) { + infoLog.append("Cannot use both gl_FragColor and gl_FragData in the same fragment shader."); return false; } // Write the HLSL input/output declarations - Context *context = getContext(); - const bool sm3 = context->supportsShaderModel3(); - const int maxVaryingVectors = context->getMaximumVaryingVectors(); + const int shaderModel = mRenderer->getMajorShaderModel(); + const int maxVaryingVectors = mRenderer->getMaxVaryingVectors(); - if (registers == maxVaryingVectors && fragmentShader->mUsesFragCoord) + const int registersNeeded = registers + (fragmentShader->mUsesFragCoord ? 1 : 0) + (fragmentShader->mUsesPointCoord ? 1 : 0); + + // The output color is broadcast to all enabled draw buffers when writing to gl_FragColor + const bool broadcast = fragmentShader->mUsesFragColor; + const unsigned int numRenderTargets = (broadcast || usesMRT ? mRenderer->getMaxRenderTargets() : 1); + + if (registersNeeded > maxVaryingVectors) { - infoLog.append("No varying registers left to support gl_FragCoord"); + infoLog.append("No varying registers left to support gl_FragCoord/gl_PointCoord"); return false; } + vertexShader->resetVaryingsRegisterAssignment(); + for (VaryingList::iterator input = fragmentShader->mVaryings.begin(); input != fragmentShader->mVaryings.end(); input++) { bool matched = false; @@ -1358,10 +1222,37 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, std::string& pixelHLSL, std:: } mUsesPointSize = vertexShader->mUsesPointSize; - std::string varyingSemantic = (mUsesPointSize && sm3) ? "COLOR" : "TEXCOORD"; + std::string varyingSemantic = (mUsesPointSize && shaderModel == 3) ? "COLOR" : "TEXCOORD"; + std::string targetSemantic = (shaderModel >= 4) ? "SV_Target" : "COLOR"; + std::string positionSemantic = (shaderModel >= 4) ? "SV_Position" : "POSITION"; + std::string depthSemantic = (shaderModel >= 4) ? "SV_Depth" : "DEPTH"; + + // special varyings that use reserved registers + int reservedRegisterIndex = registers; + std::string fragCoordSemantic; + std::string pointCoordSemantic; + + if (fragmentShader->mUsesFragCoord) + { + fragCoordSemantic = varyingSemantic + str(reservedRegisterIndex++); + } + + if (fragmentShader->mUsesPointCoord) + { + // Shader model 3 uses a special TEXCOORD semantic for point sprite texcoords. + // In DX11 we compute this in the GS. + if (shaderModel == 3) + { + pointCoordSemantic = "TEXCOORD0"; + } + else if (shaderModel >= 4) + { + pointCoordSemantic = varyingSemantic + str(reservedRegisterIndex++); + } + } vertexHLSL += "struct VS_INPUT\n" - "{\n"; + "{\n"; int semanticIndex = 0; for (AttributeArray::iterator attribute = vertexShader->mAttributes.begin(); attribute != vertexShader->mAttributes.end(); attribute++) @@ -1384,10 +1275,14 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, std::string& pixelHLSL, std:: } vertexHLSL += "};\n" - "\n" - "struct VS_OUTPUT\n" - "{\n" - " float4 gl_Position : POSITION;\n"; + "\n" + "struct VS_OUTPUT\n" + "{\n"; + + if (shaderModel < 4) + { + vertexHLSL += " float4 gl_Position : " + positionSemantic + ";\n"; + } for (int r = 0; r < registers; r++) { @@ -1398,18 +1293,23 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, std::string& pixelHLSL, std:: if (fragmentShader->mUsesFragCoord) { - vertexHLSL += " float4 gl_FragCoord : " + varyingSemantic + str(registers) + ";\n"; + vertexHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + ";\n"; } - if (vertexShader->mUsesPointSize && sm3) + if (vertexShader->mUsesPointSize && shaderModel >= 3) { vertexHLSL += " float gl_PointSize : PSIZE;\n"; } + if (shaderModel >= 4) + { + vertexHLSL += " float4 gl_Position : " + positionSemantic + ";\n"; + } + vertexHLSL += "};\n" - "\n" - "VS_OUTPUT main(VS_INPUT input)\n" - "{\n"; + "\n" + "VS_OUTPUT main(VS_INPUT input)\n" + "{\n"; for (AttributeArray::iterator attribute = vertexShader->mAttributes.begin(); attribute != vertexShader->mAttributes.end(); attribute++) { @@ -1423,16 +1323,30 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, std::string& pixelHLSL, std:: vertexHLSL += "(input." + decorateAttribute(attribute->name) + ");\n"; } - vertexHLSL += "\n" - " gl_main();\n" - "\n" - " VS_OUTPUT output;\n" - " output.gl_Position.x = gl_Position.x - dx_HalfPixelSize.x * gl_Position.w;\n" - " output.gl_Position.y = -(gl_Position.y + dx_HalfPixelSize.y * gl_Position.w);\n" - " output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n" - " output.gl_Position.w = gl_Position.w;\n"; + if (shaderModel >= 4) + { + vertexHLSL += "\n" + " gl_main();\n" + "\n" + " VS_OUTPUT output;\n" + " output.gl_Position.x = gl_Position.x;\n" + " output.gl_Position.y = -gl_Position.y;\n" + " output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n" + " output.gl_Position.w = gl_Position.w;\n"; + } + else + { + vertexHLSL += "\n" + " gl_main();\n" + "\n" + " VS_OUTPUT output;\n" + " output.gl_Position.x = gl_Position.x * dx_ViewAdjust.z + dx_ViewAdjust.x * gl_Position.w;\n" + " output.gl_Position.y = -(gl_Position.y * dx_ViewAdjust.w + dx_ViewAdjust.y * gl_Position.w);\n" + " output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n" + " output.gl_Position.w = gl_Position.w;\n"; + } - if (vertexShader->mUsesPointSize && sm3) + if (vertexShader->mUsesPointSize && shaderModel >= 3) { vertexHLSL += " output.gl_PointSize = gl_PointSize;\n"; } @@ -1504,11 +1418,11 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, std::string& pixelHLSL, std:: } vertexHLSL += "\n" - " return output;\n" - "}\n"; + " return output;\n" + "}\n"; pixelHLSL += "struct PS_INPUT\n" - "{\n"; + "{\n"; for (VaryingList::iterator varying = fragmentShader->mVaryings.begin(); varying != fragmentShader->mVaryings.end(); varying++) { @@ -1520,7 +1434,7 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, std::string& pixelHLSL, std:: for (int j = 0; j < rows; j++) { std::string n = str(varying->reg + i * rows + j); - pixelHLSL += " float4 v" + n + " : " + varyingSemantic + n + ";\n"; + pixelHLSL += " float" + str(VariableColumnCount(varying->type)) + " v" + n + " : " + varyingSemantic + n + ";\n"; } } } @@ -1529,53 +1443,96 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, std::string& pixelHLSL, std:: if (fragmentShader->mUsesFragCoord) { - pixelHLSL += " float4 gl_FragCoord : " + varyingSemantic + str(registers) + ";\n"; - if (sm3) { + pixelHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + ";\n"; + } + + if (fragmentShader->mUsesPointCoord && shaderModel >= 3) + { + pixelHLSL += " float2 gl_PointCoord : " + pointCoordSemantic + ";\n"; + } + + // Must consume the PSIZE element if the geometry shader is not active + // We won't know if we use a GS until we draw + if (vertexShader->mUsesPointSize && shaderModel >= 4) + { + pixelHLSL += " float gl_PointSize : PSIZE;\n"; + } + + if (fragmentShader->mUsesFragCoord) + { + if (shaderModel >= 4) + { + pixelHLSL += " float4 dx_VPos : SV_Position;\n"; + } + else if (shaderModel >= 3) + { pixelHLSL += " float2 dx_VPos : VPOS;\n"; } } - if (fragmentShader->mUsesPointCoord && sm3) + pixelHLSL += "};\n" + "\n" + "struct PS_OUTPUT\n" + "{\n"; + + for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++) { - pixelHLSL += " float2 gl_PointCoord : TEXCOORD0;\n"; + pixelHLSL += " float4 gl_Color" + str(renderTargetIndex) + " : " + targetSemantic + str(renderTargetIndex) + ";\n"; } - if (fragmentShader->mUsesFrontFacing) + if (fragmentShader->mUsesFragDepth) { - pixelHLSL += " float vFace : VFACE;\n"; + pixelHLSL += " float gl_Depth : " + depthSemantic + ";\n"; } pixelHLSL += "};\n" - "\n" - "struct PS_OUTPUT\n" - "{\n" - " float4 gl_Color[1] : COLOR;\n" - "};\n" - "\n" - "PS_OUTPUT main(PS_INPUT input)\n" - "{\n"; + "\n"; + + if (fragmentShader->mUsesFrontFacing) + { + if (shaderModel >= 4) + { + pixelHLSL += "PS_OUTPUT main(PS_INPUT input, bool isFrontFace : SV_IsFrontFace)\n" + "{\n"; + } + else + { + pixelHLSL += "PS_OUTPUT main(PS_INPUT input, float vFace : VFACE)\n" + "{\n"; + } + } + else + { + pixelHLSL += "PS_OUTPUT main(PS_INPUT input)\n" + "{\n"; + } if (fragmentShader->mUsesFragCoord) { pixelHLSL += " float rhw = 1.0 / input.gl_FragCoord.w;\n"; - if (sm3) + if (shaderModel >= 4) + { + pixelHLSL += " gl_FragCoord.x = input.dx_VPos.x;\n" + " gl_FragCoord.y = input.dx_VPos.y;\n"; + } + else if (shaderModel >= 3) { pixelHLSL += " gl_FragCoord.x = input.dx_VPos.x + 0.5;\n" - " gl_FragCoord.y = input.dx_VPos.y + 0.5;\n"; + " gl_FragCoord.y = input.dx_VPos.y + 0.5;\n"; } else { - // dx_Coord contains the viewport width/2, height/2, center.x and center.y. See Context::applyRenderTarget() - pixelHLSL += " gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * dx_Coord.x + dx_Coord.z;\n" - " gl_FragCoord.y = (input.gl_FragCoord.y * rhw) * dx_Coord.y + dx_Coord.w;\n"; + // dx_ViewCoords contains the viewport width/2, height/2, center.x and center.y. See Renderer::setViewport() + pixelHLSL += " gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * dx_ViewCoords.x + dx_ViewCoords.z;\n" + " gl_FragCoord.y = (input.gl_FragCoord.y * rhw) * dx_ViewCoords.y + dx_ViewCoords.w;\n"; } - pixelHLSL += " gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * dx_Depth.x + dx_Depth.y;\n" - " gl_FragCoord.w = rhw;\n"; + pixelHLSL += " gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * dx_DepthFront.x + dx_DepthFront.y;\n" + " gl_FragCoord.w = rhw;\n"; } - if (fragmentShader->mUsesPointCoord && sm3) + if (fragmentShader->mUsesPointCoord && shaderModel >= 3) { pixelHLSL += " gl_PointCoord.x = input.gl_PointCoord.x;\n"; pixelHLSL += " gl_PointCoord.y = 1.0 - input.gl_PointCoord.y;\n"; @@ -1583,7 +1540,14 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, std::string& pixelHLSL, std:: if (fragmentShader->mUsesFrontFacing) { - pixelHLSL += " gl_FrontFacing = dx_PointsOrLines || (dx_FrontCCW ? (input.vFace >= 0.0) : (input.vFace <= 0.0));\n"; + if (shaderModel <= 3) + { + pixelHLSL += " gl_FrontFacing = (vFace * dx_DepthFront.z >= 0.0);\n"; + } + else + { + pixelHLSL += " gl_FrontFacing = isFrontFace;\n"; + } } for (VaryingList::iterator varying = fragmentShader->mVaryings.begin(); varying != fragmentShader->mVaryings.end(); varying++) @@ -1623,13 +1587,25 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, std::string& pixelHLSL, std:: } pixelHLSL += "\n" - " gl_main();\n" - "\n" - " PS_OUTPUT output;\n" - " output.gl_Color[0] = gl_Color[0];\n" - "\n" - " return output;\n" - "}\n"; + " gl_main();\n" + "\n" + " PS_OUTPUT output;\n"; + + for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++) + { + unsigned int sourceColorIndex = broadcast ? 0 : renderTargetIndex; + + pixelHLSL += " output.gl_Color" + str(renderTargetIndex) + " = gl_Color[" + str(sourceColorIndex) + "];\n"; + } + + if (fragmentShader->mUsesFragDepth) + { + pixelHLSL += " output.gl_Depth = gl_Depth;\n"; + } + + pixelHLSL += "\n" + " return output;\n" + "}\n"; return true; } @@ -1654,6 +1630,14 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) return false; } + int compileFlags = 0; + stream.read(&compileFlags); + if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL) + { + infoLog.append("Mismatched compilation flags."); + return false; + } + for (int i = 0; i < MAX_VERTEX_ATTRIBS; ++i) { stream.read(&mLinkedAttribute[i].type); @@ -1673,7 +1657,7 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) mSamplersPS[i].textureType = (TextureType) textureType; } - for (unsigned int i = 0; i < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; ++i) + for (unsigned int i = 0; i < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; ++i) { stream.read(&mSamplersVS[i].active); stream.read(&mSamplersVS[i].logicalTextureUnit); @@ -1699,24 +1683,20 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) for (unsigned int i = 0; i < size; ++i) { GLenum type; - std::string _name; + GLenum precision; + std::string name; unsigned int arraySize; stream.read(&type); - stream.read(&_name); + stream.read(&precision); + stream.read(&name); stream.read(&arraySize); - mUniforms[i] = new Uniform(type, _name, arraySize); + mUniforms[i] = new Uniform(type, precision, name, arraySize); - stream.read(&mUniforms[i]->ps.float4Index); - stream.read(&mUniforms[i]->ps.samplerIndex); - stream.read(&mUniforms[i]->ps.boolIndex); - stream.read(&mUniforms[i]->ps.registerCount); - - stream.read(&mUniforms[i]->vs.float4Index); - stream.read(&mUniforms[i]->vs.samplerIndex); - stream.read(&mUniforms[i]->vs.boolIndex); - stream.read(&mUniforms[i]->vs.registerCount); + stream.read(&mUniforms[i]->psRegisterIndex); + stream.read(&mUniforms[i]->vsRegisterIndex); + stream.read(&mUniforms[i]->registerCount); } stream.read(&size); @@ -1734,26 +1714,22 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) stream.read(&mUniformIndex[i].index); } - stream.read(&mDxDepthRangeLocation); - stream.read(&mDxDepthLocation); - stream.read(&mDxCoordLocation); - stream.read(&mDxHalfPixelSizeLocation); - stream.read(&mDxFrontCCWLocation); - stream.read(&mDxPointsOrLinesLocation); - unsigned int pixelShaderSize; stream.read(&pixelShaderSize); unsigned int vertexShaderSize; stream.read(&vertexShaderSize); + unsigned int geometryShaderSize; + stream.read(&geometryShaderSize); + const char *ptr = (const char*) binary + stream.offset(); - const D3DCAPS9 *binaryIdentifier = (const D3DCAPS9*) ptr; + const GUID *binaryIdentifier = (const GUID *) ptr; ptr += sizeof(GUID); - D3DADAPTER_IDENTIFIER9 *currentIdentifier = getDisplay()->getAdapterIdentifier(); - if (memcmp(¤tIdentifier->DeviceIdentifier, binaryIdentifier, sizeof(GUID)) != 0) + GUID identifier = mRenderer->getAdapterIdentifier(); + if (memcmp(&identifier, binaryIdentifier, sizeof(GUID)) != 0) { infoLog.append("Invalid program binary."); return false; @@ -1765,22 +1741,46 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) const char *vertexShaderFunction = ptr; ptr += vertexShaderSize; - mPixelExecutable = getDisplay()->createPixelShader(reinterpret_cast(pixelShaderFunction), pixelShaderSize); + const char *geometryShaderFunction = geometryShaderSize > 0 ? ptr : NULL; + ptr += geometryShaderSize; + + mPixelExecutable = mRenderer->loadExecutable(reinterpret_cast(pixelShaderFunction), + pixelShaderSize, rx::SHADER_PIXEL); if (!mPixelExecutable) { infoLog.append("Could not create pixel shader."); return false; } - mVertexExecutable = getDisplay()->createVertexShader(reinterpret_cast(vertexShaderFunction), vertexShaderSize); + mVertexExecutable = mRenderer->loadExecutable(reinterpret_cast(vertexShaderFunction), + vertexShaderSize, rx::SHADER_VERTEX); if (!mVertexExecutable) { infoLog.append("Could not create vertex shader."); - mPixelExecutable->Release(); + delete mPixelExecutable; mPixelExecutable = NULL; return false; } + if (geometryShaderFunction != NULL && geometryShaderSize > 0) + { + mGeometryExecutable = mRenderer->loadExecutable(reinterpret_cast(geometryShaderFunction), + geometryShaderSize, rx::SHADER_GEOMETRY); + if (!mGeometryExecutable) + { + infoLog.append("Could not create geometry shader."); + delete mPixelExecutable; + mPixelExecutable = NULL; + delete mVertexExecutable; + mVertexExecutable = NULL; + return false; + } + } + else + { + mGeometryExecutable = NULL; + } + return true; } @@ -1790,6 +1790,7 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) stream.write(GL_PROGRAM_BINARY_ANGLE); stream.write(VERSION_DWORD); + stream.write(ANGLE_COMPILE_OPTIMIZATION_LEVEL); for (unsigned int i = 0; i < MAX_VERTEX_ATTRIBS; ++i) { @@ -1805,7 +1806,7 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) stream.write((int) mSamplersPS[i].textureType); } - for (unsigned int i = 0; i < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; ++i) + for (unsigned int i = 0; i < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; ++i) { stream.write(mSamplersVS[i].active); stream.write(mSamplersVS[i].logicalTextureUnit); @@ -1820,18 +1821,13 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) for (unsigned int i = 0; i < mUniforms.size(); ++i) { stream.write(mUniforms[i]->type); - stream.write(mUniforms[i]->_name); + stream.write(mUniforms[i]->precision); + stream.write(mUniforms[i]->name); stream.write(mUniforms[i]->arraySize); - stream.write(mUniforms[i]->ps.float4Index); - stream.write(mUniforms[i]->ps.samplerIndex); - stream.write(mUniforms[i]->ps.boolIndex); - stream.write(mUniforms[i]->ps.registerCount); - - stream.write(mUniforms[i]->vs.float4Index); - stream.write(mUniforms[i]->vs.samplerIndex); - stream.write(mUniforms[i]->vs.boolIndex); - stream.write(mUniforms[i]->vs.registerCount); + stream.write(mUniforms[i]->psRegisterIndex); + stream.write(mUniforms[i]->vsRegisterIndex); + stream.write(mUniforms[i]->registerCount); } stream.write(mUniformIndex.size()); @@ -1842,29 +1838,21 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) stream.write(mUniformIndex[i].index); } - stream.write(mDxDepthRangeLocation); - stream.write(mDxDepthLocation); - stream.write(mDxCoordLocation); - stream.write(mDxHalfPixelSizeLocation); - stream.write(mDxFrontCCWLocation); - stream.write(mDxPointsOrLinesLocation); - - UINT pixelShaderSize; - HRESULT result = mPixelExecutable->GetFunction(NULL, &pixelShaderSize); - ASSERT(SUCCEEDED(result)); + UINT pixelShaderSize = mPixelExecutable->getLength(); stream.write(pixelShaderSize); - UINT vertexShaderSize; - result = mVertexExecutable->GetFunction(NULL, &vertexShaderSize); - ASSERT(SUCCEEDED(result)); + UINT vertexShaderSize = mVertexExecutable->getLength(); stream.write(vertexShaderSize); - D3DADAPTER_IDENTIFIER9 *identifier = getDisplay()->getAdapterIdentifier(); + UINT geometryShaderSize = (mGeometryExecutable != NULL) ? mGeometryExecutable->getLength() : 0; + stream.write(geometryShaderSize); + + GUID identifier = mRenderer->getAdapterIdentifier(); GLsizei streamLength = stream.length(); const void *streamData = stream.data(); - GLsizei totalLength = streamLength + sizeof(GUID) + pixelShaderSize + vertexShaderSize; + GLsizei totalLength = streamLength + sizeof(GUID) + pixelShaderSize + vertexShaderSize + geometryShaderSize; if (totalLength > bufSize) { if (length) @@ -1882,17 +1870,21 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) memcpy(ptr, streamData, streamLength); ptr += streamLength; - memcpy(ptr, &identifier->DeviceIdentifier, sizeof(GUID)); + memcpy(ptr, &identifier, sizeof(GUID)); ptr += sizeof(GUID); - result = mPixelExecutable->GetFunction(ptr, &pixelShaderSize); - ASSERT(SUCCEEDED(result)); + memcpy(ptr, mPixelExecutable->getFunction(), pixelShaderSize); ptr += pixelShaderSize; - result = mVertexExecutable->GetFunction(ptr, &vertexShaderSize); - ASSERT(SUCCEEDED(result)); + memcpy(ptr, mVertexExecutable->getFunction(), vertexShaderSize); ptr += vertexShaderSize; + if (mGeometryExecutable != NULL && geometryShaderSize > 0) + { + memcpy(ptr, mGeometryExecutable->getFunction(), geometryShaderSize); + ptr += geometryShaderSize; + } + ASSERT(ptr - totalLength == binary); } @@ -1932,69 +1924,66 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin std::string pixelHLSL = fragmentShader->getHLSL(); std::string vertexHLSL = vertexShader->getHLSL(); - if (!linkVaryings(infoLog, pixelHLSL, vertexHLSL, fragmentShader, vertexShader)) + // Map the varyings to the register file + const Varying *packing[IMPLEMENTATION_MAX_VARYING_VECTORS][4] = {NULL}; + int registers = packVaryings(infoLog, packing, fragmentShader); + + if (registers < 0) { return false; } - Context *context = getContext(); - const char *vertexProfile = context->supportsShaderModel3() ? "vs_3_0" : "vs_2_0"; - const char *pixelProfile = context->supportsShaderModel3() ? "ps_3_0" : "ps_2_0"; - - ID3D10Blob *vertexBinary = compileToBinary(infoLog, vertexHLSL.c_str(), vertexProfile, &mConstantTableVS); - ID3D10Blob *pixelBinary = compileToBinary(infoLog, pixelHLSL.c_str(), pixelProfile, &mConstantTablePS); - - if (vertexBinary && pixelBinary) + if (!linkVaryings(infoLog, registers, packing, pixelHLSL, vertexHLSL, fragmentShader, vertexShader)) { - mVertexExecutable = getDisplay()->createVertexShader((DWORD*)vertexBinary->GetBufferPointer(), vertexBinary->GetBufferSize()); - if (!mVertexExecutable) - { - return error(GL_OUT_OF_MEMORY, false); - } - - mPixelExecutable = getDisplay()->createPixelShader((DWORD*)pixelBinary->GetBufferPointer(), pixelBinary->GetBufferSize()); - if (!mPixelExecutable) - { - mVertexExecutable->Release(); - mVertexExecutable = NULL; - return error(GL_OUT_OF_MEMORY, false); - } - - vertexBinary->Release(); - pixelBinary->Release(); - vertexBinary = NULL; - pixelBinary = NULL; - - if (!linkAttributes(infoLog, attributeBindings, fragmentShader, vertexShader)) - { - return false; - } - - if (!linkUniforms(infoLog, GL_FRAGMENT_SHADER, mConstantTablePS)) - { - return false; - } - - if (!linkUniforms(infoLog, GL_VERTEX_SHADER, mConstantTableVS)) - { - return false; - } - - // these uniforms are searched as already-decorated because gl_ and dx_ - // are reserved prefixes, and do not receive additional decoration - mDxDepthRangeLocation = getUniformLocation("dx_DepthRange"); - mDxDepthLocation = getUniformLocation("dx_Depth"); - mDxCoordLocation = getUniformLocation("dx_Coord"); - mDxHalfPixelSizeLocation = getUniformLocation("dx_HalfPixelSize"); - mDxFrontCCWLocation = getUniformLocation("dx_FrontCCW"); - mDxPointsOrLinesLocation = getUniformLocation("dx_PointsOrLines"); - - context->markDxUniformsDirty(); - - return true; + return false; } - return false; + bool success = true; + + if (!linkAttributes(infoLog, attributeBindings, fragmentShader, vertexShader)) + { + success = false; + } + + if (!linkUniforms(infoLog, vertexShader->getUniforms(), fragmentShader->getUniforms())) + { + success = false; + } + + // special case for gl_DepthRange, the only built-in uniform (also a struct) + if (vertexShader->mUsesDepthRange || fragmentShader->mUsesDepthRange) + { + mUniforms.push_back(new Uniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.near", 0)); + mUniforms.push_back(new Uniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.far", 0)); + mUniforms.push_back(new Uniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.diff", 0)); + } + + if (success) + { + mVertexExecutable = mRenderer->compileToExecutable(infoLog, vertexHLSL.c_str(), rx::SHADER_VERTEX); + mPixelExecutable = mRenderer->compileToExecutable(infoLog, pixelHLSL.c_str(), rx::SHADER_PIXEL); + + if (usesGeometryShader()) + { + std::string geometryHLSL = generateGeometryShaderHLSL(registers, packing, fragmentShader, vertexShader); + mGeometryExecutable = mRenderer->compileToExecutable(infoLog, geometryHLSL.c_str(), rx::SHADER_GEOMETRY); + } + + if (!mVertexExecutable || !mPixelExecutable || (usesGeometryShader() && !mGeometryExecutable)) + { + infoLog.append("Failed to create D3D shaders."); + success = false; + + delete mVertexExecutable; + mVertexExecutable = NULL; + delete mPixelExecutable; + mPixelExecutable = NULL; + delete mGeometryExecutable; + mGeometryExecutable = NULL; + } + } + + return success; } // Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices @@ -2067,13 +2056,19 @@ bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &at return true; } -bool ProgramBinary::linkUniforms(InfoLog &infoLog, GLenum shader, D3DConstantTable *constantTable) +bool ProgramBinary::linkUniforms(InfoLog &infoLog, const sh::ActiveUniforms &vertexUniforms, const sh::ActiveUniforms &fragmentUniforms) { - for (unsigned int constantIndex = 0; constantIndex < constantTable->constants(); constantIndex++) + for (sh::ActiveUniforms::const_iterator uniform = vertexUniforms.begin(); uniform != vertexUniforms.end(); uniform++) { - const D3DConstant *constant = constantTable->getConstant(constantIndex); + if (!defineUniform(GL_VERTEX_SHADER, *uniform, infoLog)) + { + return false; + } + } - if (!defineUniform(infoLog, shader, constant)) + for (sh::ActiveUniforms::const_iterator uniform = fragmentUniforms.begin(); uniform != fragmentUniforms.end(); uniform++) + { + if (!defineUniform(GL_FRAGMENT_SHADER, *uniform, infoLog)) { return false; } @@ -2082,25 +2077,36 @@ bool ProgramBinary::linkUniforms(InfoLog &infoLog, GLenum shader, D3DConstantTab return true; } -// Adds the description of a constant found in the binary shader to the list of uniforms -// Returns true if succesful (uniform not already defined) -bool ProgramBinary::defineUniform(InfoLog &infoLog, GLenum shader, const D3DConstant *constant, std::string name) +bool ProgramBinary::defineUniform(GLenum shader, const sh::Uniform &constant, InfoLog &infoLog) { - if (constant->registerSet == D3DConstant::RS_SAMPLER) + if (constant.type == GL_SAMPLER_2D || + constant.type == GL_SAMPLER_CUBE) { - for (unsigned int i = 0; i < constant->registerCount; i++) + unsigned int samplerIndex = constant.registerIndex; + + do { - const D3DConstant *psConstant = mConstantTablePS->getConstantByName(constant->name.c_str()); - const D3DConstant *vsConstant = mConstantTableVS->getConstantByName(constant->name.c_str()); - - if (psConstant) + if (shader == GL_VERTEX_SHADER) + { + if (samplerIndex < mRenderer->getMaxVertexTextureImageUnits()) + { + mSamplersVS[samplerIndex].active = true; + mSamplersVS[samplerIndex].textureType = (constant.type == GL_SAMPLER_CUBE) ? TEXTURE_CUBE : TEXTURE_2D; + mSamplersVS[samplerIndex].logicalTextureUnit = 0; + mUsedVertexSamplerRange = std::max(samplerIndex + 1, mUsedVertexSamplerRange); + } + else + { + infoLog.append("Vertex shader sampler count exceeds the maximum vertex texture units (%d).", mRenderer->getMaxVertexTextureImageUnits()); + return false; + } + } + else if (shader == GL_FRAGMENT_SHADER) { - unsigned int samplerIndex = psConstant->registerIndex + i; - if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS) { mSamplersPS[samplerIndex].active = true; - mSamplersPS[samplerIndex].textureType = (constant->type == D3DConstant::PT_SAMPLERCUBE) ? TEXTURE_CUBE : TEXTURE_2D; + mSamplersPS[samplerIndex].textureType = (constant.type == GL_SAMPLER_CUBE) ? TEXTURE_CUBE : TEXTURE_2D; mSamplersPS[samplerIndex].logicalTextureUnit = 0; mUsedPixelSamplerRange = std::max(samplerIndex + 1, mUsedPixelSamplerRange); } @@ -2110,170 +2116,221 @@ bool ProgramBinary::defineUniform(InfoLog &infoLog, GLenum shader, const D3DCons return false; } } - - if (vsConstant) - { - unsigned int samplerIndex = vsConstant->registerIndex + i; + else UNREACHABLE(); - if (samplerIndex < getContext()->getMaximumVertexTextureImageUnits()) - { - mSamplersVS[samplerIndex].active = true; - mSamplersVS[samplerIndex].textureType = (constant->type == D3DConstant::PT_SAMPLERCUBE) ? TEXTURE_CUBE : TEXTURE_2D; - mSamplersVS[samplerIndex].logicalTextureUnit = 0; - mUsedVertexSamplerRange = std::max(samplerIndex + 1, mUsedVertexSamplerRange); - } - else - { - infoLog.append("Vertex shader sampler count exceeds MAX_VERTEX_TEXTURE_IMAGE_UNITS (%d).", getContext()->getMaximumVertexTextureImageUnits()); - return false; - } - } + samplerIndex++; } + while (samplerIndex < constant.registerIndex + constant.arraySize); } - switch(constant->typeClass) + Uniform *uniform = NULL; + GLint location = getUniformLocation(constant.name); + + if (location >= 0) // Previously defined, type and precision must match { - case D3DConstant::CLASS_STRUCT: - { - for (unsigned int arrayIndex = 0; arrayIndex < constant->elements; arrayIndex++) - { - for (unsigned int field = 0; field < constant->structMembers[arrayIndex].size(); field++) - { - const D3DConstant *fieldConstant = constant->structMembers[arrayIndex][field]; - - std::string structIndex = (constant->elements > 1) ? ("[" + str(arrayIndex) + "]") : ""; - - if (!defineUniform(infoLog, shader, fieldConstant, name + constant->name + structIndex + ".")) - { - return false; - } - } - } - - return true; - } - case D3DConstant::CLASS_SCALAR: - case D3DConstant::CLASS_VECTOR: - case D3DConstant::CLASS_MATRIX_COLUMNS: - case D3DConstant::CLASS_OBJECT: - return defineUniform(shader, constant, name + constant->name); - default: - UNREACHABLE(); - return false; - } -} - -bool ProgramBinary::defineUniform(GLenum shader, const D3DConstant *constant, const std::string &_name) -{ - Uniform *uniform = createUniform(constant, _name); - - if(!uniform) - { - return false; - } - - // Check if already defined - GLint location = getUniformLocation(uniform->name); - GLenum type = uniform->type; - - if (location >= 0) - { - delete uniform; uniform = mUniforms[mUniformIndex[location].index]; + + if (uniform->type != constant.type) + { + infoLog.append("Types for uniform %s do not match between the vertex and fragment shader", uniform->name.c_str()); + return false; + } + + if (uniform->precision != constant.precision) + { + infoLog.append("Precisions for uniform %s do not match between the vertex and fragment shader", uniform->name.c_str()); + return false; + } + } + else + { + uniform = new Uniform(constant.type, constant.precision, constant.name, constant.arraySize); } - if (shader == GL_FRAGMENT_SHADER) uniform->ps.set(constant); - if (shader == GL_VERTEX_SHADER) uniform->vs.set(constant); + if (!uniform) + { + return false; + } + + if (shader == GL_FRAGMENT_SHADER) + { + uniform->psRegisterIndex = constant.registerIndex; + } + else if (shader == GL_VERTEX_SHADER) + { + uniform->vsRegisterIndex = constant.registerIndex; + } + else UNREACHABLE(); if (location >= 0) { - return uniform->type == type; + return uniform->type == constant.type; } mUniforms.push_back(uniform); unsigned int uniformIndex = mUniforms.size() - 1; - for (unsigned int i = 0; i < uniform->arraySize; ++i) + for (unsigned int i = 0; i < uniform->elementCount(); i++) { - mUniformIndex.push_back(UniformLocation(_name, i, uniformIndex)); + mUniformIndex.push_back(UniformLocation(constant.name, i, uniformIndex)); } - return true; -} - -Uniform *ProgramBinary::createUniform(const D3DConstant *constant, const std::string &_name) -{ - if (constant->rows == 1) // Vectors and scalars + if (shader == GL_VERTEX_SHADER) { - switch (constant->type) + if (constant.registerIndex + uniform->registerCount > mRenderer->getReservedVertexUniformVectors() + mRenderer->getMaxVertexUniformVectors()) { - case D3DConstant::PT_SAMPLER2D: - switch (constant->columns) - { - case 1: return new Uniform(GL_SAMPLER_2D, _name, constant->elements); - default: UNREACHABLE(); - } - break; - case D3DConstant::PT_SAMPLERCUBE: - switch (constant->columns) - { - case 1: return new Uniform(GL_SAMPLER_CUBE, _name, constant->elements); - default: UNREACHABLE(); - } - break; - case D3DConstant::PT_BOOL: - switch (constant->columns) - { - case 1: return new Uniform(GL_BOOL, _name, constant->elements); - case 2: return new Uniform(GL_BOOL_VEC2, _name, constant->elements); - case 3: return new Uniform(GL_BOOL_VEC3, _name, constant->elements); - case 4: return new Uniform(GL_BOOL_VEC4, _name, constant->elements); - default: UNREACHABLE(); - } - break; - case D3DConstant::PT_INT: - switch (constant->columns) - { - case 1: return new Uniform(GL_INT, _name, constant->elements); - case 2: return new Uniform(GL_INT_VEC2, _name, constant->elements); - case 3: return new Uniform(GL_INT_VEC3, _name, constant->elements); - case 4: return new Uniform(GL_INT_VEC4, _name, constant->elements); - default: UNREACHABLE(); - } - break; - case D3DConstant::PT_FLOAT: - switch (constant->columns) - { - case 1: return new Uniform(GL_FLOAT, _name, constant->elements); - case 2: return new Uniform(GL_FLOAT_VEC2, _name, constant->elements); - case 3: return new Uniform(GL_FLOAT_VEC3, _name, constant->elements); - case 4: return new Uniform(GL_FLOAT_VEC4, _name, constant->elements); - default: UNREACHABLE(); - } - break; - default: - UNREACHABLE(); + infoLog.append("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%u)", mRenderer->getMaxVertexUniformVectors()); + return false; } } - else if (constant->rows == constant->columns) // Square matrices + else if (shader == GL_FRAGMENT_SHADER) { - switch (constant->type) + if (constant.registerIndex + uniform->registerCount > mRenderer->getReservedFragmentUniformVectors() + mRenderer->getMaxFragmentUniformVectors()) { - case D3DConstant::PT_FLOAT: - switch (constant->rows) - { - case 2: return new Uniform(GL_FLOAT_MAT2, _name, constant->elements); - case 3: return new Uniform(GL_FLOAT_MAT3, _name, constant->elements); - case 4: return new Uniform(GL_FLOAT_MAT4, _name, constant->elements); - default: UNREACHABLE(); - } - break; - default: UNREACHABLE(); + infoLog.append("Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS (%u)", mRenderer->getMaxFragmentUniformVectors()); + return false; } } else UNREACHABLE(); - return 0; + return true; +} + +std::string ProgramBinary::generateGeometryShaderHLSL(int registers, const Varying *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const +{ + // for now we only handle point sprite emulation + ASSERT(usesPointSpriteEmulation()); + return generatePointSpriteHLSL(registers, packing, fragmentShader, vertexShader); +} + +std::string ProgramBinary::generatePointSpriteHLSL(int registers, const Varying *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const +{ + ASSERT(registers >= 0); + ASSERT(vertexShader->mUsesPointSize); + ASSERT(mRenderer->getMajorShaderModel() >= 4); + + std::string geomHLSL; + + std::string varyingSemantic = "TEXCOORD"; + + std::string fragCoordSemantic; + std::string pointCoordSemantic; + + int reservedRegisterIndex = registers; + + if (fragmentShader->mUsesFragCoord) + { + fragCoordSemantic = varyingSemantic + str(reservedRegisterIndex++); + } + + if (fragmentShader->mUsesPointCoord) + { + pointCoordSemantic = varyingSemantic + str(reservedRegisterIndex++); + } + + geomHLSL += "uniform float4 dx_ViewCoords : register(c1);\n" + "\n" + "struct GS_INPUT\n" + "{\n"; + + for (int r = 0; r < registers; r++) + { + int registerSize = packing[r][3] ? 4 : (packing[r][2] ? 3 : (packing[r][1] ? 2 : 1)); + + geomHLSL += " float" + str(registerSize) + " v" + str(r) + " : " + varyingSemantic + str(r) + ";\n"; + } + + if (fragmentShader->mUsesFragCoord) + { + geomHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + ";\n"; + } + + geomHLSL += " float gl_PointSize : PSIZE;\n" + " float4 gl_Position : SV_Position;\n" + "};\n" + "\n" + "struct GS_OUTPUT\n" + "{\n"; + + for (int r = 0; r < registers; r++) + { + int registerSize = packing[r][3] ? 4 : (packing[r][2] ? 3 : (packing[r][1] ? 2 : 1)); + + geomHLSL += " float" + str(registerSize) + " v" + str(r) + " : " + varyingSemantic + str(r) + ";\n"; + } + + if (fragmentShader->mUsesFragCoord) + { + geomHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + ";\n"; + } + + if (fragmentShader->mUsesPointCoord) + { + geomHLSL += " float2 gl_PointCoord : " + pointCoordSemantic + ";\n"; + } + + geomHLSL += " float gl_PointSize : PSIZE;\n" + " float4 gl_Position : SV_Position;\n" + "};\n" + "\n" + "static float2 pointSpriteCorners[] = \n" + "{\n" + " float2( 0.5f, -0.5f),\n" + " float2( 0.5f, 0.5f),\n" + " float2(-0.5f, -0.5f),\n" + " float2(-0.5f, 0.5f)\n" + "};\n" + "\n" + "static float2 pointSpriteTexcoords[] = \n" + "{\n" + " float2(1.0f, 1.0f),\n" + " float2(1.0f, 0.0f),\n" + " float2(0.0f, 1.0f),\n" + " float2(0.0f, 0.0f)\n" + "};\n" + "\n" + "static float minPointSize = " + str(ALIASED_POINT_SIZE_RANGE_MIN) + ".0f;\n" + "static float maxPointSize = " + str(mRenderer->getMaxPointSize()) + ".0f;\n" + "\n" + "[maxvertexcount(4)]\n" + "void main(point GS_INPUT input[1], inout TriangleStream outStream)\n" + "{\n" + " GS_OUTPUT output = (GS_OUTPUT)0;\n" + " output.gl_PointSize = input[0].gl_PointSize;\n"; + + for (int r = 0; r < registers; r++) + { + geomHLSL += " output.v" + str(r) + " = input[0].v" + str(r) + ";\n"; + } + + if (fragmentShader->mUsesFragCoord) + { + geomHLSL += " output.gl_FragCoord = input[0].gl_FragCoord;\n"; + } + + geomHLSL += " \n" + " float gl_PointSize = clamp(input[0].gl_PointSize, minPointSize, maxPointSize);\n" + " float4 gl_Position = input[0].gl_Position;\n" + " float2 viewportScale = float2(1.0f / dx_ViewCoords.x, 1.0f / dx_ViewCoords.y) * gl_Position.w;\n"; + + for (int corner = 0; corner < 4; corner++) + { + geomHLSL += " \n" + " output.gl_Position = gl_Position + float4(pointSpriteCorners[" + str(corner) + "] * viewportScale * gl_PointSize, 0.0f, 0.0f);\n"; + + if (fragmentShader->mUsesPointCoord) + { + geomHLSL += " output.gl_PointCoord = pointSpriteTexcoords[" + str(corner) + "];\n"; + } + + geomHLSL += " outStream.Append(output);\n"; + } + + geomHLSL += " \n" + " outStream.RestartStrip();\n" + "}\n"; + + return geomHLSL; } // This method needs to match OutputHLSL::decorate @@ -2287,235 +2344,12 @@ std::string ProgramBinary::decorateAttribute(const std::string &name) return name; } -std::string ProgramBinary::undecorateUniform(const std::string &_name) -{ - std::string name = _name; - - // Remove any structure field decoration - size_t pos = 0; - while ((pos = name.find("._", pos)) != std::string::npos) - { - name.replace(pos, 2, "."); - } - - // Remove the leading decoration - if (name[0] == '_') - { - return name.substr(1); - } - else if (name.compare(0, 3, "ar_") == 0) - { - return name.substr(3); - } - - return name; -} - -void ProgramBinary::applyUniformnbv(Uniform *targetUniform, GLsizei count, int width, const GLboolean *v) -{ - float vector[D3D9_MAX_FLOAT_CONSTANTS * 4]; - BOOL boolVector[D3D9_MAX_BOOL_CONSTANTS]; - - if (targetUniform->ps.float4Index >= 0 || targetUniform->vs.float4Index >= 0) - { - ASSERT(count <= D3D9_MAX_FLOAT_CONSTANTS); - for (int i = 0; i < count; i++) - { - for (int j = 0; j < 4; j++) - { - if (j < width) - { - vector[i * 4 + j] = (v[i * width + j] == GL_FALSE) ? 0.0f : 1.0f; - } - else - { - vector[i * 4 + j] = 0.0f; - } - } - } - } - - if (targetUniform->ps.boolIndex >= 0 || targetUniform->vs.boolIndex >= 0) - { - int psCount = targetUniform->ps.boolIndex >= 0 ? targetUniform->ps.registerCount : 0; - int vsCount = targetUniform->vs.boolIndex >= 0 ? targetUniform->vs.registerCount : 0; - int copyCount = std::min(count * width, std::max(psCount, vsCount)); - ASSERT(copyCount <= D3D9_MAX_BOOL_CONSTANTS); - for (int i = 0; i < copyCount; i++) - { - boolVector[i] = v[i] != GL_FALSE; - } - } - - if (targetUniform->ps.float4Index >= 0) - { - mDevice->SetPixelShaderConstantF(targetUniform->ps.float4Index, vector, targetUniform->ps.registerCount); - } - - if (targetUniform->ps.boolIndex >= 0) - { - mDevice->SetPixelShaderConstantB(targetUniform->ps.boolIndex, boolVector, targetUniform->ps.registerCount); - } - - if (targetUniform->vs.float4Index >= 0) - { - mDevice->SetVertexShaderConstantF(targetUniform->vs.float4Index, vector, targetUniform->vs.registerCount); - } - - if (targetUniform->vs.boolIndex >= 0) - { - mDevice->SetVertexShaderConstantB(targetUniform->vs.boolIndex, boolVector, targetUniform->vs.registerCount); - } -} - -bool ProgramBinary::applyUniformnfv(Uniform *targetUniform, const GLfloat *v) -{ - if (targetUniform->ps.registerCount) - { - mDevice->SetPixelShaderConstantF(targetUniform->ps.float4Index, v, targetUniform->ps.registerCount); - } - - if (targetUniform->vs.registerCount) - { - mDevice->SetVertexShaderConstantF(targetUniform->vs.float4Index, v, targetUniform->vs.registerCount); - } - - return true; -} - -bool ProgramBinary::applyUniform1iv(Uniform *targetUniform, GLsizei count, const GLint *v) -{ - ASSERT(count <= D3D9_MAX_FLOAT_CONSTANTS); - Vector4 vector[D3D9_MAX_FLOAT_CONSTANTS]; - - for (int i = 0; i < count; i++) - { - vector[i] = Vector4((float)v[i], 0, 0, 0); - } - - if (targetUniform->ps.registerCount) - { - if (targetUniform->ps.samplerIndex >= 0) - { - unsigned int firstIndex = targetUniform->ps.samplerIndex; - - for (int i = 0; i < count; i++) - { - unsigned int samplerIndex = firstIndex + i; - - if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS) - { - ASSERT(mSamplersPS[samplerIndex].active); - mSamplersPS[samplerIndex].logicalTextureUnit = v[i]; - } - } - } - else - { - ASSERT(targetUniform->ps.float4Index >= 0); - mDevice->SetPixelShaderConstantF(targetUniform->ps.float4Index, (const float*)vector, targetUniform->ps.registerCount); - } - } - - if (targetUniform->vs.registerCount) - { - if (targetUniform->vs.samplerIndex >= 0) - { - unsigned int firstIndex = targetUniform->vs.samplerIndex; - - for (int i = 0; i < count; i++) - { - unsigned int samplerIndex = firstIndex + i; - - if (samplerIndex < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF) - { - ASSERT(mSamplersVS[samplerIndex].active); - mSamplersVS[samplerIndex].logicalTextureUnit = v[i]; - } - } - } - else - { - ASSERT(targetUniform->vs.float4Index >= 0); - mDevice->SetVertexShaderConstantF(targetUniform->vs.float4Index, (const float *)vector, targetUniform->vs.registerCount); - } - } - - return true; -} - -bool ProgramBinary::applyUniform2iv(Uniform *targetUniform, GLsizei count, const GLint *v) -{ - ASSERT(count <= D3D9_MAX_FLOAT_CONSTANTS); - Vector4 vector[D3D9_MAX_FLOAT_CONSTANTS]; - - for (int i = 0; i < count; i++) - { - vector[i] = Vector4((float)v[0], (float)v[1], 0, 0); - - v += 2; - } - - applyUniformniv(targetUniform, count, vector); - - return true; -} - -bool ProgramBinary::applyUniform3iv(Uniform *targetUniform, GLsizei count, const GLint *v) -{ - ASSERT(count <= D3D9_MAX_FLOAT_CONSTANTS); - Vector4 vector[D3D9_MAX_FLOAT_CONSTANTS]; - - for (int i = 0; i < count; i++) - { - vector[i] = Vector4((float)v[0], (float)v[1], (float)v[2], 0); - - v += 3; - } - - applyUniformniv(targetUniform, count, vector); - - return true; -} - -bool ProgramBinary::applyUniform4iv(Uniform *targetUniform, GLsizei count, const GLint *v) -{ - ASSERT(count <= D3D9_MAX_FLOAT_CONSTANTS); - Vector4 vector[D3D9_MAX_FLOAT_CONSTANTS]; - - for (int i = 0; i < count; i++) - { - vector[i] = Vector4((float)v[0], (float)v[1], (float)v[2], (float)v[3]); - - v += 4; - } - - applyUniformniv(targetUniform, count, vector); - - return true; -} - -void ProgramBinary::applyUniformniv(Uniform *targetUniform, GLsizei count, const Vector4 *vector) -{ - if (targetUniform->ps.registerCount) - { - ASSERT(targetUniform->ps.float4Index >= 0); - mDevice->SetPixelShaderConstantF(targetUniform->ps.float4Index, (const float *)vector, targetUniform->ps.registerCount); - } - - if (targetUniform->vs.registerCount) - { - ASSERT(targetUniform->vs.float4Index >= 0); - mDevice->SetVertexShaderConstantF(targetUniform->vs.float4Index, (const float *)vector, targetUniform->vs.registerCount); - } -} - bool ProgramBinary::isValidated() const { return mValidated; } -void ProgramBinary::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) +void ProgramBinary::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const { // Skip over inactive attributes unsigned int activeAttribute = 0; @@ -2553,7 +2387,7 @@ void ProgramBinary::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *l *type = mLinkedAttribute[attribute].type; } -GLint ProgramBinary::getActiveAttributeCount() +GLint ProgramBinary::getActiveAttributeCount() const { int count = 0; @@ -2568,7 +2402,7 @@ GLint ProgramBinary::getActiveAttributeCount() return count; } -GLint ProgramBinary::getActiveAttributeMaxLength() +GLint ProgramBinary::getActiveAttributeMaxLength() const { int maxLength = 0; @@ -2583,33 +2417,15 @@ GLint ProgramBinary::getActiveAttributeMaxLength() return maxLength; } -void ProgramBinary::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) +void ProgramBinary::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const { - // Skip over internal uniforms - unsigned int activeUniform = 0; - unsigned int uniform; - for (uniform = 0; uniform < mUniforms.size(); uniform++) - { - if (mUniforms[uniform]->name.compare(0, 3, "dx_") == 0) - { - continue; - } - - if (activeUniform == index) - { - break; - } - - activeUniform++; - } - - ASSERT(uniform < mUniforms.size()); // index must be smaller than getActiveUniformCount() + ASSERT(index < mUniforms.size()); // index must be smaller than getActiveUniformCount() if (bufsize > 0) { - std::string string = mUniforms[uniform]->name; + std::string string = mUniforms[index]->name; - if (mUniforms[uniform]->isArray()) + if (mUniforms[index]->isArray()) { string += "[0]"; } @@ -2623,35 +2439,24 @@ void ProgramBinary::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *len } } - *size = mUniforms[uniform]->arraySize; + *size = mUniforms[index]->elementCount(); - *type = mUniforms[uniform]->type; + *type = mUniforms[index]->type; } -GLint ProgramBinary::getActiveUniformCount() +GLint ProgramBinary::getActiveUniformCount() const { - int count = 0; - - unsigned int numUniforms = mUniforms.size(); - for (unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++) - { - if (mUniforms[uniformIndex]->name.compare(0, 3, "dx_") != 0) - { - count++; - } - } - - return count; + return mUniforms.size(); } -GLint ProgramBinary::getActiveUniformMaxLength() +GLint ProgramBinary::getActiveUniformMaxLength() const { int maxLength = 0; unsigned int numUniforms = mUniforms.size(); for (unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++) { - if (!mUniforms[uniformIndex]->name.empty() && mUniforms[uniformIndex]->name.compare(0, 3, "dx_") != 0) + if (!mUniforms[uniformIndex]->name.empty()) { int length = (int)(mUniforms[uniformIndex]->name.length() + 1); if (mUniforms[uniformIndex]->isArray()) @@ -2684,10 +2489,10 @@ bool ProgramBinary::validateSamplers(InfoLog *infoLog) // texture image unit, and this is the current program, then ValidateProgram will fail, and // DrawArrays and DrawElements will issue the INVALID_OPERATION error. - const unsigned int maxCombinedTextureImageUnits = getContext()->getMaximumCombinedTextureImageUnits(); - TextureType textureUnitType[MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF]; + const unsigned int maxCombinedTextureImageUnits = mRenderer->getMaxCombinedTextureImageUnits(); + TextureType textureUnitType[IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS]; - for (unsigned int i = 0; i < MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF; ++i) + for (unsigned int i = 0; i < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS; ++i) { textureUnitType[i] = TEXTURE_UNKNOWN; } @@ -2702,7 +2507,7 @@ bool ProgramBinary::validateSamplers(InfoLog *infoLog) { if (infoLog) { - infoLog->append("Sampler uniform (%d) exceeds MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits); + infoLog->append("Sampler uniform (%d) exceeds IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits); } return false; @@ -2737,7 +2542,7 @@ bool ProgramBinary::validateSamplers(InfoLog *infoLog) { if (infoLog) { - infoLog->append("Sampler uniform (%d) exceeds MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits); + infoLog->append("Sampler uniform (%d) exceeds IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits); } return false; @@ -2765,38 +2570,51 @@ bool ProgramBinary::validateSamplers(InfoLog *infoLog) return true; } -GLint ProgramBinary::getDxDepthRangeLocation() const -{ - return mDxDepthRangeLocation; -} - -GLint ProgramBinary::getDxDepthLocation() const -{ - return mDxDepthLocation; -} - -GLint ProgramBinary::getDxCoordLocation() const -{ - return mDxCoordLocation; -} - -GLint ProgramBinary::getDxHalfPixelSizeLocation() const -{ - return mDxHalfPixelSizeLocation; -} - -GLint ProgramBinary::getDxFrontCCWLocation() const -{ - return mDxFrontCCWLocation; -} - -GLint ProgramBinary::getDxPointsOrLinesLocation() const -{ - return mDxPointsOrLinesLocation; -} - ProgramBinary::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureType(TEXTURE_2D) { } +struct AttributeSorter +{ + AttributeSorter(const int (&semanticIndices)[MAX_VERTEX_ATTRIBS]) + : originalIndices(semanticIndices) + { + for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) + { + indices[i] = i; + } + + std::sort(&indices[0], &indices[MAX_VERTEX_ATTRIBS], *this); + } + + bool operator()(int a, int b) + { + return originalIndices[a] == -1 ? false : originalIndices[a] < originalIndices[b]; + } + + int indices[MAX_VERTEX_ATTRIBS]; + const int (&originalIndices)[MAX_VERTEX_ATTRIBS]; +}; + +void ProgramBinary::sortAttributesByLayout(rx::TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS], int sortedSemanticIndices[MAX_VERTEX_ATTRIBS]) const +{ + AttributeSorter sorter(mSemanticIndex); + + int oldIndices[MAX_VERTEX_ATTRIBS]; + rx::TranslatedAttribute oldTranslatedAttributes[MAX_VERTEX_ATTRIBS]; + + for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) + { + oldIndices[i] = mSemanticIndex[i]; + oldTranslatedAttributes[i] = attributes[i]; + } + + for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) + { + int oldIndex = sorter.indices[i]; + sortedSemanticIndices[i] = oldIndices[oldIndex]; + attributes[i] = oldTranslatedAttributes[oldIndex]; + } +} + } diff --git a/gfx/angle/src/libGLESv2/ProgramBinary.h b/gfx/angle/src/libGLESv2/ProgramBinary.h index 9ffe70b6177c..2386c0bd6f4e 100644 --- a/gfx/angle/src/libGLESv2/ProgramBinary.h +++ b/gfx/angle/src/libGLESv2/ProgramBinary.h @@ -14,71 +14,30 @@ #include #include -#include #include #include -#include "libGLESv2/Context.h" -#include "libGLESv2/D3DConstantTable.h" +#include "common/RefCountObject.h" +#include "angletypes.h" #include "libGLESv2/mathutil.h" +#include "libGLESv2/Uniform.h" #include "libGLESv2/Shader.h" +#include "libGLESv2/Constants.h" + +namespace rx +{ +class ShaderExecutable; +class Renderer; +struct TranslatedAttribute; +} namespace gl { class FragmentShader; class VertexShader; - -// Helper struct representing a single shader uniform -struct Uniform -{ - Uniform(GLenum type, const std::string &_name, unsigned int arraySize); - - ~Uniform(); - - bool isArray(); - - const GLenum type; - const std::string _name; // Decorated name - const std::string name; // Undecorated name - const unsigned int arraySize; - - unsigned char *data; - bool dirty; - - struct RegisterInfo - { - RegisterInfo() - { - float4Index = -1; - samplerIndex = -1; - boolIndex = -1; - registerCount = 0; - } - - void set(const D3DConstant *constant) - { - switch(constant->registerSet) - { - case D3DConstant::RS_BOOL: boolIndex = constant->registerIndex; break; - case D3DConstant::RS_FLOAT4: float4Index = constant->registerIndex; break; - case D3DConstant::RS_SAMPLER: samplerIndex = constant->registerIndex; break; - default: UNREACHABLE(); - } - - ASSERT(registerCount == 0 || registerCount == (int)constant->registerCount); - registerCount = constant->registerCount; - } - - int float4Index; - int samplerIndex; - int boolIndex; - - int registerCount; - }; - - RegisterInfo ps; - RegisterInfo vs; -}; +class InfoLog; +class AttributeBindings; +struct Varying; // Struct used for correlating uniforms/elements of uniform arrays to handles struct UniformLocation @@ -87,7 +46,7 @@ struct UniformLocation { } - UniformLocation(const std::string &_name, unsigned int element, unsigned int index); + UniformLocation(const std::string &name, unsigned int element, unsigned int index); std::string name; unsigned int element; @@ -98,11 +57,12 @@ struct UniformLocation class ProgramBinary : public RefCountObject { public: - ProgramBinary(); + explicit ProgramBinary(rx::Renderer *renderer); ~ProgramBinary(); - IDirect3DPixelShader9 *getPixelShader(); - IDirect3DVertexShader9 *getVertexShader(); + rx::ShaderExecutable *getPixelExecutable(); + rx::ShaderExecutable *getVertexExecutable(); + rx::ShaderExecutable *getGeometryExecutable(); GLuint getAttributeLocation(const char *name); int getSemanticIndex(int attributeIndex); @@ -111,6 +71,8 @@ class ProgramBinary : public RefCountObject TextureType getSamplerTextureType(SamplerType type, unsigned int samplerIndex); GLint getUsedSamplerRange(SamplerType type); bool usesPointSize() const; + bool usesPointSpriteEmulation() const; + bool usesGeometryShader() const; GLint getUniformLocation(std::string name); bool setUniform1fv(GLint location, GLsizei count, const GLfloat *v); @@ -128,13 +90,6 @@ class ProgramBinary : public RefCountObject bool getUniformfv(GLint location, GLsizei *bufSize, GLfloat *params); bool getUniformiv(GLint location, GLsizei *bufSize, GLint *params); - GLint getDxDepthRangeLocation() const; - GLint getDxDepthLocation() const; - GLint getDxCoordLocation() const; - GLint getDxHalfPixelSizeLocation() const; - GLint getDxFrontCCWLocation() const; - GLint getDxPointsOrLinesLocation() const; - void dirtyAllUniforms(); void applyUniforms(); @@ -145,13 +100,13 @@ class ProgramBinary : public RefCountObject bool link(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader); void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders); - void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); - GLint getActiveAttributeCount(); - GLint getActiveAttributeMaxLength(); + void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const; + GLint getActiveAttributeCount() const; + GLint getActiveAttributeMaxLength() const; - void getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); - GLint getActiveUniformCount(); - GLint getActiveUniformMaxLength(); + void getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const; + GLint getActiveUniformCount() const; + GLint getActiveUniformMaxLength() const; void validate(InfoLog &infoLog); bool validateSamplers(InfoLog *infoLog); @@ -159,39 +114,31 @@ class ProgramBinary : public RefCountObject unsigned int getSerial() const; + void sortAttributesByLayout(rx::TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS], int sortedSemanticIndices[MAX_VERTEX_ATTRIBS]) const; + static std::string decorateAttribute(const std::string &name); // Prepend an underscore - static std::string undecorateUniform(const std::string &_name); // Remove leading underscore private: DISALLOW_COPY_AND_ASSIGN(ProgramBinary); - ID3D10Blob *compileToBinary(InfoLog &infoLog, const char *hlsl, const char *profile, D3DConstantTable **constantTable); - int packVaryings(InfoLog &infoLog, const Varying *packing[][4], FragmentShader *fragmentShader); - bool linkVaryings(InfoLog &infoLog, std::string& pixelHLSL, std::string& vertexHLSL, FragmentShader *fragmentShader, VertexShader *vertexShader); + bool linkVaryings(InfoLog &infoLog, int registers, const Varying *packing[][4], + std::string& pixelHLSL, std::string& vertexHLSL, + FragmentShader *fragmentShader, VertexShader *vertexShader); bool linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader); - bool linkUniforms(InfoLog &infoLog, GLenum shader, D3DConstantTable *constantTable); - bool defineUniform(InfoLog &infoLog, GLenum shader, const D3DConstant *constant, std::string name = ""); - bool defineUniform(GLenum shader, const D3DConstant *constant, const std::string &name); - Uniform *createUniform( const D3DConstant *constant, const std::string &name); - bool applyUniformnfv(Uniform *targetUniform, const GLfloat *v); - bool applyUniform1iv(Uniform *targetUniform, GLsizei count, const GLint *v); - bool applyUniform2iv(Uniform *targetUniform, GLsizei count, const GLint *v); - bool applyUniform3iv(Uniform *targetUniform, GLsizei count, const GLint *v); - bool applyUniform4iv(Uniform *targetUniform, GLsizei count, const GLint *v); - void applyUniformniv(Uniform *targetUniform, GLsizei count, const Vector4 *vector); - void applyUniformnbv(Uniform *targetUniform, GLsizei count, int width, const GLboolean *v); + bool linkUniforms(InfoLog &infoLog, const sh::ActiveUniforms &vertexUniforms, const sh::ActiveUniforms &fragmentUniforms); + bool defineUniform(GLenum shader, const sh::Uniform &constant, InfoLog &infoLog); + + std::string generateGeometryShaderHLSL(int registers, const Varying *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const; + std::string generatePointSpriteHLSL(int registers, const Varying *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const; - IDirect3DDevice9 *mDevice; + rx::Renderer *const mRenderer; - IDirect3DPixelShader9 *mPixelExecutable; - IDirect3DVertexShader9 *mVertexExecutable; - - // These are only used during linking. - D3DConstantTable *mConstantTablePS; - D3DConstantTable *mConstantTableVS; + rx::ShaderExecutable *mPixelExecutable; + rx::ShaderExecutable *mVertexExecutable; + rx::ShaderExecutable *mGeometryExecutable; Attribute mLinkedAttribute[MAX_VERTEX_ATTRIBS]; int mSemanticIndex[MAX_VERTEX_ATTRIBS]; @@ -206,23 +153,15 @@ class ProgramBinary : public RefCountObject }; Sampler mSamplersPS[MAX_TEXTURE_IMAGE_UNITS]; - Sampler mSamplersVS[MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF]; + Sampler mSamplersVS[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; GLuint mUsedVertexSamplerRange; GLuint mUsedPixelSamplerRange; bool mUsesPointSize; - typedef std::vector UniformArray; UniformArray mUniforms; typedef std::vector UniformIndex; UniformIndex mUniformIndex; - GLint mDxDepthRangeLocation; - GLint mDxDepthLocation; - GLint mDxCoordLocation; - GLint mDxHalfPixelSizeLocation; - GLint mDxFrontCCWLocation; - GLint mDxPointsOrLinesLocation; - bool mValidated; const unsigned int mSerial; diff --git a/gfx/angle/src/libGLESv2/Query.cpp b/gfx/angle/src/libGLESv2/Query.cpp index 10edda5c576f..bd987954f1fe 100644 --- a/gfx/angle/src/libGLESv2/Query.cpp +++ b/gfx/angle/src/libGLESv2/Query.cpp @@ -1,3 +1,4 @@ +#include "precompiled.h" // // Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -7,122 +8,45 @@ // Query.cpp: Implements the gl::Query class #include "libGLESv2/Query.h" - -#include "libGLESv2/main.h" +#include "libGLESv2/renderer/QueryImpl.h" +#include "libGLESv2/renderer/Renderer.h" namespace gl { -Query::Query(GLuint id, GLenum type) : RefCountObject(id) +Query::Query(rx::Renderer *renderer, GLenum type, GLuint id) : RefCountObject(id) { - mQuery = NULL; - mStatus = GL_FALSE; - mResult = GL_FALSE; - mType = type; + mQuery = renderer->createQuery(type); } Query::~Query() { - if (mQuery != NULL) - { - mQuery->Release(); - mQuery = NULL; - } + delete mQuery; } void Query::begin() { - if (mQuery == NULL) - { - if (FAILED(getDevice()->CreateQuery(D3DQUERYTYPE_OCCLUSION, &mQuery))) - { - return error(GL_OUT_OF_MEMORY); - } - } - - HRESULT result = mQuery->Issue(D3DISSUE_BEGIN); - ASSERT(SUCCEEDED(result)); + mQuery->begin(); } void Query::end() { - if (mQuery == NULL) - { - return error(GL_INVALID_OPERATION); - } - - HRESULT result = mQuery->Issue(D3DISSUE_END); - ASSERT(SUCCEEDED(result)); - - mStatus = GL_FALSE; - mResult = GL_FALSE; + mQuery->end(); } GLuint Query::getResult() { - if (mQuery != NULL) - { - while (!testQuery()) - { - Sleep(0); - // explicitly check for device loss - // some drivers seem to return S_FALSE even if the device is lost - // instead of D3DERR_DEVICELOST like they should - if (gl::getDisplay()->testDeviceLost()) - { - gl::getDisplay()->notifyDeviceLost(); - return error(GL_OUT_OF_MEMORY, 0); - } - } - } - - return (GLuint)mResult; + return mQuery->getResult(); } GLboolean Query::isResultAvailable() { - if (mQuery != NULL) - { - testQuery(); - } - - return mStatus; + return mQuery->isResultAvailable(); } GLenum Query::getType() const { - return mType; + return mQuery->getType(); } -GLboolean Query::testQuery() -{ - if (mQuery != NULL && mStatus != GL_TRUE) - { - DWORD numPixels = 0; - - HRESULT hres = mQuery->GetData(&numPixels, sizeof(DWORD), D3DGETDATA_FLUSH); - if (hres == S_OK) - { - mStatus = GL_TRUE; - - switch (mType) - { - case GL_ANY_SAMPLES_PASSED_EXT: - case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: - mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE; - break; - default: - ASSERT(false); - } - } - else if (checkDeviceLost(hres)) - { - return error(GL_OUT_OF_MEMORY, GL_TRUE); - } - - return mStatus; - } - - return GL_TRUE; // prevent blocking when query is null -} } diff --git a/gfx/angle/src/libGLESv2/Query.h b/gfx/angle/src/libGLESv2/Query.h index 79357a0583e4..e9b95b729b61 100644 --- a/gfx/angle/src/libGLESv2/Query.h +++ b/gfx/angle/src/libGLESv2/Query.h @@ -11,22 +11,28 @@ #define GL_APICALL #include -#include #include "common/angleutils.h" #include "common/RefCountObject.h" +namespace rx +{ +class Renderer; +class QueryImpl; +} + namespace gl { class Query : public RefCountObject { public: - Query(GLuint id, GLenum type); + Query(rx::Renderer *renderer, GLenum type, GLuint id); virtual ~Query(); void begin(); void end(); + GLuint getResult(); GLboolean isResultAvailable(); @@ -35,12 +41,7 @@ class Query : public RefCountObject private: DISALLOW_COPY_AND_ASSIGN(Query); - GLboolean testQuery(); - - IDirect3DQuery9* mQuery; - GLenum mType; - GLboolean mStatus; - GLint mResult; + rx::QueryImpl *mQuery; }; } diff --git a/gfx/angle/src/libGLESv2/Renderbuffer.cpp b/gfx/angle/src/libGLESv2/Renderbuffer.cpp index 4b911e812096..127513741c2f 100644 --- a/gfx/angle/src/libGLESv2/Renderbuffer.cpp +++ b/gfx/angle/src/libGLESv2/Renderbuffer.cpp @@ -1,5 +1,6 @@ +#include "precompiled.h" // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -9,9 +10,10 @@ // objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108. #include "libGLESv2/Renderbuffer.h" +#include "libGLESv2/renderer/RenderTarget.h" -#include "libGLESv2/main.h" #include "libGLESv2/Texture.h" +#include "libGLESv2/renderer/Renderer.h" #include "libGLESv2/utilities.h" namespace gl @@ -35,32 +37,32 @@ void RenderbufferInterface::releaseProxy(const Renderbuffer *proxy) GLuint RenderbufferInterface::getRedSize() const { - return dx2es::GetRedSize(getD3DFormat()); + return gl::GetRedSize(getActualFormat()); } GLuint RenderbufferInterface::getGreenSize() const { - return dx2es::GetGreenSize(getD3DFormat()); + return gl::GetGreenSize(getActualFormat()); } GLuint RenderbufferInterface::getBlueSize() const { - return dx2es::GetBlueSize(getD3DFormat()); + return gl::GetBlueSize(getActualFormat()); } GLuint RenderbufferInterface::getAlphaSize() const { - return dx2es::GetAlphaSize(getD3DFormat()); + return gl::GetAlphaSize(getActualFormat()); } GLuint RenderbufferInterface::getDepthSize() const { - return dx2es::GetDepthSize(getD3DFormat()); + return gl::GetDepthSize(getActualFormat()); } GLuint RenderbufferInterface::getStencilSize() const { - return dx2es::GetStencilSize(getD3DFormat()); + return gl::GetStencilSize(getActualFormat()); } ///// RenderbufferTexture2D Implementation //////// @@ -87,16 +89,12 @@ void RenderbufferTexture2D::releaseProxy(const Renderbuffer *proxy) mTexture2D->releaseProxy(proxy); } -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *RenderbufferTexture2D::getRenderTarget() +rx::RenderTarget *RenderbufferTexture2D::getRenderTarget() { return mTexture2D->getRenderTarget(mTarget); } -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *RenderbufferTexture2D::getDepthStencil() +rx::RenderTarget *RenderbufferTexture2D::getDepthStencil() { return mTexture2D->getDepthStencil(mTarget); } @@ -116,9 +114,9 @@ GLenum RenderbufferTexture2D::getInternalFormat() const return mTexture2D->getInternalFormat(0); } -D3DFORMAT RenderbufferTexture2D::getD3DFormat() const +GLenum RenderbufferTexture2D::getActualFormat() const { - return mTexture2D->getD3DFormat(0); + return mTexture2D->getActualFormat(0); } GLsizei RenderbufferTexture2D::getSamples() const @@ -155,16 +153,12 @@ void RenderbufferTextureCubeMap::releaseProxy(const Renderbuffer *proxy) mTextureCubeMap->releaseProxy(proxy); } -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *RenderbufferTextureCubeMap::getRenderTarget() +rx::RenderTarget *RenderbufferTextureCubeMap::getRenderTarget() { return mTextureCubeMap->getRenderTarget(mTarget); } -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *RenderbufferTextureCubeMap::getDepthStencil() +rx::RenderTarget *RenderbufferTextureCubeMap::getDepthStencil() { return NULL; } @@ -184,9 +178,9 @@ GLenum RenderbufferTextureCubeMap::getInternalFormat() const return mTextureCubeMap->getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0); } -D3DFORMAT RenderbufferTextureCubeMap::getD3DFormat() const +GLenum RenderbufferTextureCubeMap::getActualFormat() const { - return mTextureCubeMap->getD3DFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0); + return mTextureCubeMap->getActualFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0); } GLsizei RenderbufferTextureCubeMap::getSamples() const @@ -201,7 +195,7 @@ unsigned int RenderbufferTextureCubeMap::getSerial() const ////// Renderbuffer Implementation ////// -Renderbuffer::Renderbuffer(GLuint id, RenderbufferInterface *instance) : RefCountObject(id) +Renderbuffer::Renderbuffer(rx::Renderer *renderer, GLuint id, RenderbufferInterface *instance) : RefCountObject(id) { ASSERT(instance != NULL); mInstance = instance; @@ -228,16 +222,12 @@ void Renderbuffer::release() const RefCountObject::release(); } -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *Renderbuffer::getRenderTarget() +rx::RenderTarget *Renderbuffer::getRenderTarget() { return mInstance->getRenderTarget(); } -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *Renderbuffer::getDepthStencil() +rx::RenderTarget *Renderbuffer::getDepthStencil() { return mInstance->getDepthStencil(); } @@ -257,9 +247,9 @@ GLenum Renderbuffer::getInternalFormat() const return mInstance->getInternalFormat(); } -D3DFORMAT Renderbuffer::getD3DFormat() const +GLenum Renderbuffer::getActualFormat() const { - return mInstance->getD3DFormat(); + return mInstance->getActualFormat(); } GLuint Renderbuffer::getRedSize() const @@ -315,7 +305,7 @@ RenderbufferStorage::RenderbufferStorage() : mSerial(issueSerial()) mWidth = 0; mHeight = 0; mInternalFormat = GL_RGBA4; - mD3DFormat = D3DFMT_A8R8G8B8; + mActualFormat = GL_RGBA8_OES; mSamples = 0; } @@ -323,16 +313,12 @@ RenderbufferStorage::~RenderbufferStorage() { } -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *RenderbufferStorage::getRenderTarget() +rx::RenderTarget *RenderbufferStorage::getRenderTarget() { return NULL; } -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *RenderbufferStorage::getDepthStencil() +rx::RenderTarget *RenderbufferStorage::getDepthStencil() { return NULL; } @@ -352,9 +338,9 @@ GLenum RenderbufferStorage::getInternalFormat() const return mInternalFormat; } -D3DFORMAT RenderbufferStorage::getD3DFormat() const +GLenum RenderbufferStorage::getActualFormat() const { - return mD3DFormat; + return mActualFormat; } GLsizei RenderbufferStorage::getSamples() const @@ -379,164 +365,96 @@ unsigned int RenderbufferStorage::issueCubeSerials() return firstSerial; } -Colorbuffer::Colorbuffer(IDirect3DSurface9 *renderTarget) : mRenderTarget(renderTarget) +Colorbuffer::Colorbuffer(rx::Renderer *renderer, rx::SwapChain *swapChain) { - if (renderTarget) + mRenderTarget = renderer->createRenderTarget(swapChain, false); + + if (mRenderTarget) { - renderTarget->AddRef(); - - D3DSURFACE_DESC description; - renderTarget->GetDesc(&description); - - mWidth = description.Width; - mHeight = description.Height; - mInternalFormat = dx2es::ConvertBackBufferFormat(description.Format); - mD3DFormat = description.Format; - mSamples = dx2es::GetSamplesFromMultisampleType(description.MultiSampleType); + mWidth = mRenderTarget->getWidth(); + mHeight = mRenderTarget->getHeight(); + mInternalFormat = mRenderTarget->getInternalFormat(); + mActualFormat = mRenderTarget->getActualFormat(); + mSamples = mRenderTarget->getSamples(); } } -Colorbuffer::Colorbuffer(int width, int height, GLenum format, GLsizei samples) : mRenderTarget(NULL) +Colorbuffer::Colorbuffer(rx::Renderer *renderer, int width, int height, GLenum format, GLsizei samples) : mRenderTarget(NULL) { - IDirect3DDevice9 *device = getDevice(); + mRenderTarget = renderer->createRenderTarget(width, height, format, samples, false); - D3DFORMAT requestedFormat = es2dx::ConvertRenderbufferFormat(format); - int supportedSamples = getContext()->getNearestSupportedSamples(requestedFormat, samples); - - if (supportedSamples == -1) + if (mRenderTarget) { - error(GL_OUT_OF_MEMORY); - - return; + mWidth = width; + mHeight = height; + mInternalFormat = format; + mActualFormat = mRenderTarget->getActualFormat(); + mSamples = mRenderTarget->getSamples(); } - - if (width > 0 && height > 0) - { - HRESULT result = device->CreateRenderTarget(width, height, requestedFormat, - es2dx::GetMultisampleTypeFromSamples(supportedSamples), 0, FALSE, &mRenderTarget, NULL); - - if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY) - { - error(GL_OUT_OF_MEMORY); - - return; - } - - ASSERT(SUCCEEDED(result)); - } - - mWidth = width; - mHeight = height; - mInternalFormat = format; - mD3DFormat = requestedFormat; - mSamples = supportedSamples; } Colorbuffer::~Colorbuffer() { if (mRenderTarget) { - mRenderTarget->Release(); + delete mRenderTarget; } } -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *Colorbuffer::getRenderTarget() +rx::RenderTarget *Colorbuffer::getRenderTarget() { if (mRenderTarget) { - mRenderTarget->AddRef(); + return mRenderTarget; } - return mRenderTarget; + return NULL; } -DepthStencilbuffer::DepthStencilbuffer(IDirect3DSurface9 *depthStencil) : mDepthStencil(depthStencil) +DepthStencilbuffer::DepthStencilbuffer(rx::Renderer *renderer, rx::SwapChain *swapChain) { - if (depthStencil) + mDepthStencil = renderer->createRenderTarget(swapChain, true); + if (mDepthStencil) { - depthStencil->AddRef(); - - D3DSURFACE_DESC description; - depthStencil->GetDesc(&description); - - mWidth = description.Width; - mHeight = description.Height; - mInternalFormat = dx2es::ConvertDepthStencilFormat(description.Format); - mSamples = dx2es::GetSamplesFromMultisampleType(description.MultiSampleType); - mD3DFormat = description.Format; + mWidth = mDepthStencil->getWidth(); + mHeight = mDepthStencil->getHeight(); + mInternalFormat = mDepthStencil->getInternalFormat(); + mSamples = mDepthStencil->getSamples(); + mActualFormat = mDepthStencil->getActualFormat(); } } -DepthStencilbuffer::DepthStencilbuffer(int width, int height, GLsizei samples) +DepthStencilbuffer::DepthStencilbuffer(rx::Renderer *renderer, int width, int height, GLsizei samples) { - IDirect3DDevice9 *device = getDevice(); - mDepthStencil = NULL; - - int supportedSamples = getContext()->getNearestSupportedSamples(D3DFMT_D24S8, samples); + mDepthStencil = renderer->createRenderTarget(width, height, GL_DEPTH24_STENCIL8_OES, samples, true); - if (supportedSamples == -1) - { - error(GL_OUT_OF_MEMORY); - - return; - } - - if (width > 0 && height > 0) - { - HRESULT result = device->CreateDepthStencilSurface(width, height, D3DFMT_D24S8, es2dx::GetMultisampleTypeFromSamples(supportedSamples), - 0, FALSE, &mDepthStencil, 0); - - if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY) - { - error(GL_OUT_OF_MEMORY); - - return; - } - - ASSERT(SUCCEEDED(result)); - } - - mWidth = width; - mHeight = height; + mWidth = mDepthStencil->getWidth(); + mHeight = mDepthStencil->getHeight(); mInternalFormat = GL_DEPTH24_STENCIL8_OES; - mD3DFormat = D3DFMT_D24S8; - mSamples = supportedSamples; + mActualFormat = mDepthStencil->getActualFormat(); + mSamples = mDepthStencil->getSamples(); } DepthStencilbuffer::~DepthStencilbuffer() { if (mDepthStencil) { - mDepthStencil->Release(); + delete mDepthStencil; } } -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *DepthStencilbuffer::getDepthStencil() +rx::RenderTarget *DepthStencilbuffer::getDepthStencil() { if (mDepthStencil) { - mDepthStencil->AddRef(); + return mDepthStencil; } - return mDepthStencil; + return NULL; } -Depthbuffer::Depthbuffer(IDirect3DSurface9 *depthStencil) : DepthStencilbuffer(depthStencil) -{ - if (depthStencil) - { - mInternalFormat = GL_DEPTH_COMPONENT16; // If the renderbuffer parameters are queried, the calling function - // will expect one of the valid renderbuffer formats for use in - // glRenderbufferStorage - } -} - -Depthbuffer::Depthbuffer(int width, int height, GLsizei samples) : DepthStencilbuffer(width, height, samples) +Depthbuffer::Depthbuffer(rx::Renderer *renderer, int width, int height, GLsizei samples) : DepthStencilbuffer(renderer, width, height, samples) { if (mDepthStencil) { @@ -550,17 +468,7 @@ Depthbuffer::~Depthbuffer() { } -Stencilbuffer::Stencilbuffer(IDirect3DSurface9 *depthStencil) : DepthStencilbuffer(depthStencil) -{ - if (depthStencil) - { - mInternalFormat = GL_STENCIL_INDEX8; // If the renderbuffer parameters are queried, the calling function - // will expect one of the valid renderbuffer formats for use in - // glRenderbufferStorage - } -} - -Stencilbuffer::Stencilbuffer(int width, int height, GLsizei samples) : DepthStencilbuffer(width, height, samples) +Stencilbuffer::Stencilbuffer(rx::Renderer *renderer, int width, int height, GLsizei samples) : DepthStencilbuffer(renderer, width, height, samples) { if (mDepthStencil) { diff --git a/gfx/angle/src/libGLESv2/Renderbuffer.h b/gfx/angle/src/libGLESv2/Renderbuffer.h index e6d5ddb875a2..eca2f3a780ad 100644 --- a/gfx/angle/src/libGLESv2/Renderbuffer.h +++ b/gfx/angle/src/libGLESv2/Renderbuffer.h @@ -14,11 +14,17 @@ #define GL_APICALL #include -#include #include "common/angleutils.h" #include "common/RefCountObject.h" +namespace rx +{ +class Renderer; +class SwapChain; +class RenderTarget; +} + namespace gl { class Texture2D; @@ -37,13 +43,13 @@ class RenderbufferInterface virtual void addProxyRef(const Renderbuffer *proxy); virtual void releaseProxy(const Renderbuffer *proxy); - virtual IDirect3DSurface9 *getRenderTarget() = 0; - virtual IDirect3DSurface9 *getDepthStencil() = 0; + virtual rx::RenderTarget *getRenderTarget() = 0; + virtual rx::RenderTarget *getDepthStencil() = 0; virtual GLsizei getWidth() const = 0; virtual GLsizei getHeight() const = 0; virtual GLenum getInternalFormat() const = 0; - virtual D3DFORMAT getD3DFormat() const = 0; + virtual GLenum getActualFormat() const = 0; virtual GLsizei getSamples() const = 0; GLuint getRedSize() const; @@ -69,13 +75,13 @@ class RenderbufferTexture2D : public RenderbufferInterface void addProxyRef(const Renderbuffer *proxy); void releaseProxy(const Renderbuffer *proxy); - IDirect3DSurface9 *getRenderTarget(); - IDirect3DSurface9 *getDepthStencil(); + rx::RenderTarget *getRenderTarget(); + rx::RenderTarget *getDepthStencil(); virtual GLsizei getWidth() const; virtual GLsizei getHeight() const; virtual GLenum getInternalFormat() const; - virtual D3DFORMAT getD3DFormat() const; + virtual GLenum getActualFormat() const; virtual GLsizei getSamples() const; virtual unsigned int getSerial() const; @@ -97,13 +103,13 @@ class RenderbufferTextureCubeMap : public RenderbufferInterface void addProxyRef(const Renderbuffer *proxy); void releaseProxy(const Renderbuffer *proxy); - IDirect3DSurface9 *getRenderTarget(); - IDirect3DSurface9 *getDepthStencil(); + rx::RenderTarget *getRenderTarget(); + rx::RenderTarget *getDepthStencil(); virtual GLsizei getWidth() const; virtual GLsizei getHeight() const; virtual GLenum getInternalFormat() const; - virtual D3DFORMAT getD3DFormat() const; + virtual GLenum getActualFormat() const; virtual GLsizei getSamples() const; virtual unsigned int getSerial() const; @@ -125,13 +131,13 @@ class RenderbufferStorage : public RenderbufferInterface virtual ~RenderbufferStorage() = 0; - virtual IDirect3DSurface9 *getRenderTarget(); - virtual IDirect3DSurface9 *getDepthStencil(); + virtual rx::RenderTarget *getRenderTarget(); + virtual rx::RenderTarget *getDepthStencil(); virtual GLsizei getWidth() const; virtual GLsizei getHeight() const; virtual GLenum getInternalFormat() const; - virtual D3DFORMAT getD3DFormat() const; + virtual GLenum getActualFormat() const; virtual GLsizei getSamples() const; virtual unsigned int getSerial() const; @@ -143,7 +149,7 @@ class RenderbufferStorage : public RenderbufferInterface GLsizei mWidth; GLsizei mHeight; GLenum mInternalFormat; - D3DFORMAT mD3DFormat; + GLenum mActualFormat; GLsizei mSamples; private: @@ -160,7 +166,7 @@ class RenderbufferStorage : public RenderbufferInterface class Renderbuffer : public RefCountObject { public: - Renderbuffer(GLuint id, RenderbufferInterface *storage); + Renderbuffer(rx::Renderer *renderer, GLuint id, RenderbufferInterface *storage); virtual ~Renderbuffer(); @@ -171,13 +177,13 @@ class Renderbuffer : public RefCountObject void addRef() const; void release() const; - IDirect3DSurface9 *getRenderTarget(); - IDirect3DSurface9 *getDepthStencil(); + rx::RenderTarget *getRenderTarget(); + rx::RenderTarget *getDepthStencil(); GLsizei getWidth() const; GLsizei getHeight() const; GLenum getInternalFormat() const; - D3DFORMAT getD3DFormat() const; + GLenum getActualFormat() const; GLuint getRedSize() const; GLuint getGreenSize() const; GLuint getBlueSize() const; @@ -199,31 +205,31 @@ class Renderbuffer : public RefCountObject class Colorbuffer : public RenderbufferStorage { public: - explicit Colorbuffer(IDirect3DSurface9 *renderTarget); - Colorbuffer(GLsizei width, GLsizei height, GLenum format, GLsizei samples); + Colorbuffer(rx::Renderer *renderer, rx::SwapChain *swapChain); + Colorbuffer(rx::Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples); virtual ~Colorbuffer(); - virtual IDirect3DSurface9 *getRenderTarget(); + virtual rx::RenderTarget *getRenderTarget(); private: DISALLOW_COPY_AND_ASSIGN(Colorbuffer); - IDirect3DSurface9 *mRenderTarget; + rx::RenderTarget *mRenderTarget; }; class DepthStencilbuffer : public RenderbufferStorage { public: - explicit DepthStencilbuffer(IDirect3DSurface9 *depthStencil); - DepthStencilbuffer(GLsizei width, GLsizei height, GLsizei samples); + DepthStencilbuffer(rx::Renderer *renderer, rx::SwapChain *swapChain); + DepthStencilbuffer(rx::Renderer *renderer, GLsizei width, GLsizei height, GLsizei samples); ~DepthStencilbuffer(); - virtual IDirect3DSurface9 *getDepthStencil(); + virtual rx::RenderTarget *getDepthStencil(); protected: - IDirect3DSurface9 *mDepthStencil; + rx::RenderTarget *mDepthStencil; private: DISALLOW_COPY_AND_ASSIGN(DepthStencilbuffer); @@ -232,8 +238,7 @@ class DepthStencilbuffer : public RenderbufferStorage class Depthbuffer : public DepthStencilbuffer { public: - explicit Depthbuffer(IDirect3DSurface9 *depthStencil); - Depthbuffer(GLsizei width, GLsizei height, GLsizei samples); + Depthbuffer(rx::Renderer *renderer, GLsizei width, GLsizei height, GLsizei samples); virtual ~Depthbuffer(); @@ -244,8 +249,7 @@ class Depthbuffer : public DepthStencilbuffer class Stencilbuffer : public DepthStencilbuffer { public: - explicit Stencilbuffer(IDirect3DSurface9 *depthStencil); - Stencilbuffer(GLsizei width, GLsizei height, GLsizei samples); + Stencilbuffer(rx::Renderer *renderer, GLsizei width, GLsizei height, GLsizei samples); virtual ~Stencilbuffer(); diff --git a/gfx/angle/src/libGLESv2/ResourceManager.cpp b/gfx/angle/src/libGLESv2/ResourceManager.cpp index 4b97e9c113be..58dd44fd9559 100644 --- a/gfx/angle/src/libGLESv2/ResourceManager.cpp +++ b/gfx/angle/src/libGLESv2/ResourceManager.cpp @@ -1,3 +1,4 @@ +#include "precompiled.h" // // Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -17,9 +18,10 @@ namespace gl { -ResourceManager::ResourceManager() +ResourceManager::ResourceManager(rx::Renderer *renderer) { mRefCount = 1; + mRenderer = renderer; } ResourceManager::~ResourceManager() @@ -80,11 +82,11 @@ GLuint ResourceManager::createShader(GLenum type) if (type == GL_VERTEX_SHADER) { - mShaderMap[handle] = new VertexShader(this, handle); + mShaderMap[handle] = new VertexShader(this, mRenderer, handle); } else if (type == GL_FRAGMENT_SHADER) { - mShaderMap[handle] = new FragmentShader(this, handle); + mShaderMap[handle] = new FragmentShader(this, mRenderer, handle); } else UNREACHABLE(); @@ -96,7 +98,7 @@ GLuint ResourceManager::createProgram() { GLuint handle = mProgramShaderHandleAllocator.allocate(); - mProgramMap[handle] = new Program(this, handle); + mProgramMap[handle] = new Program(mRenderer, this, handle); return handle; } @@ -276,7 +278,7 @@ void ResourceManager::checkBufferAllocation(unsigned int buffer) { if (buffer != 0 && !getBuffer(buffer)) { - Buffer *bufferObject = new Buffer(buffer); + Buffer *bufferObject = new Buffer(mRenderer, buffer); mBufferMap[buffer] = bufferObject; bufferObject->addRef(); } @@ -290,11 +292,11 @@ void ResourceManager::checkTextureAllocation(GLuint texture, TextureType type) if (type == TEXTURE_2D) { - textureObject = new Texture2D(texture); + textureObject = new Texture2D(mRenderer, texture); } else if (type == TEXTURE_CUBE) { - textureObject = new TextureCubeMap(texture); + textureObject = new TextureCubeMap(mRenderer, texture); } else { @@ -311,7 +313,7 @@ void ResourceManager::checkRenderbufferAllocation(GLuint renderbuffer) { if (renderbuffer != 0 && !getRenderbuffer(renderbuffer)) { - Renderbuffer *renderbufferObject = new Renderbuffer(renderbuffer, new Colorbuffer(0, 0, GL_RGBA4, 0)); + Renderbuffer *renderbufferObject = new Renderbuffer(mRenderer, renderbuffer, new Colorbuffer(mRenderer, 0, 0, GL_RGBA4, 0)); mRenderbufferMap[renderbuffer] = renderbufferObject; renderbufferObject->addRef(); } diff --git a/gfx/angle/src/libGLESv2/ResourceManager.h b/gfx/angle/src/libGLESv2/ResourceManager.h index ae4f1b04a52b..e99c77c35d25 100644 --- a/gfx/angle/src/libGLESv2/ResourceManager.h +++ b/gfx/angle/src/libGLESv2/ResourceManager.h @@ -20,8 +20,14 @@ #endif #include "common/angleutils.h" +#include "libGLESv2/angletypes.h" #include "libGLESv2/HandleAllocator.h" +namespace rx +{ +class Renderer; +} + namespace gl { class Buffer; @@ -30,25 +36,10 @@ class Program; class Texture; class Renderbuffer; -enum TextureType -{ - TEXTURE_2D, - TEXTURE_CUBE, - - TEXTURE_TYPE_COUNT, - TEXTURE_UNKNOWN -}; - -enum SamplerType -{ - SAMPLER_PIXEL, - SAMPLER_VERTEX -}; - class ResourceManager { public: - ResourceManager(); + explicit ResourceManager(rx::Renderer *renderer); ~ResourceManager(); void addRef(); @@ -82,6 +73,7 @@ class ResourceManager DISALLOW_COPY_AND_ASSIGN(ResourceManager); std::size_t mRefCount; + rx::Renderer *mRenderer; #ifndef HASH_MAP # ifdef _MSC_VER diff --git a/gfx/angle/src/libGLESv2/Shader.cpp b/gfx/angle/src/libGLESv2/Shader.cpp index e3e02d5e11bb..7dfdd0ba3a76 100644 --- a/gfx/angle/src/libGLESv2/Shader.cpp +++ b/gfx/angle/src/libGLESv2/Shader.cpp @@ -1,5 +1,6 @@ +#include "precompiled.h" // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -10,18 +11,19 @@ #include "libGLESv2/Shader.h" -#include - #include "GLSLANG/ShaderLang.h" -#include "libGLESv2/main.h" #include "libGLESv2/utilities.h" +#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/Constants.h" +#include "libGLESv2/ResourceManager.h" namespace gl { void *Shader::mFragmentCompiler = NULL; void *Shader::mVertexCompiler = NULL; -Shader::Shader(ResourceManager *manager, GLuint handle) : mHandle(handle), mResourceManager(manager) +Shader::Shader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle) + : mHandle(handle), mRenderer(renderer), mResourceManager(manager) { mSource = NULL; mHlsl = NULL; @@ -174,6 +176,11 @@ void Shader::getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer) getSourceImpl(mHlsl, bufSize, length, buffer); } +const sh::ActiveUniforms &Shader::getUniforms() +{ + return mActiveUniforms; +} + bool Shader::isCompiled() { return mHlsl != NULL; @@ -223,24 +230,27 @@ void Shader::initializeCompiler() if (result) { + ShShaderOutput hlslVersion = (mRenderer->getMajorShaderModel() >= 4) ? SH_HLSL11_OUTPUT : SH_HLSL9_OUTPUT; + ShBuiltInResources resources; ShInitBuiltInResources(&resources); - Context *context = getContext(); resources.MaxVertexAttribs = MAX_VERTEX_ATTRIBS; - resources.MaxVertexUniformVectors = MAX_VERTEX_UNIFORM_VECTORS; - resources.MaxVaryingVectors = context->getMaximumVaryingVectors(); - resources.MaxVertexTextureImageUnits = context->getMaximumVertexTextureImageUnits(); - resources.MaxCombinedTextureImageUnits = context->getMaximumCombinedTextureImageUnits(); + resources.MaxVertexUniformVectors = mRenderer->getMaxVertexUniformVectors(); + resources.MaxVaryingVectors = mRenderer->getMaxVaryingVectors(); + resources.MaxVertexTextureImageUnits = mRenderer->getMaxVertexTextureImageUnits(); + resources.MaxCombinedTextureImageUnits = mRenderer->getMaxCombinedTextureImageUnits(); resources.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS; - resources.MaxFragmentUniformVectors = context->getMaximumFragmentUniformVectors(); - resources.MaxDrawBuffers = MAX_DRAW_BUFFERS; - resources.OES_standard_derivatives = context->supportsDerivativeInstructions() ? 1 : 0; - // resources.OES_EGL_image_external = getDisplay()->isD3d9ExDevice() ? 1 : 0; // TODO: commented out until the extension is actually supported. + resources.MaxFragmentUniformVectors = mRenderer->getMaxFragmentUniformVectors(); + resources.MaxDrawBuffers = mRenderer->getMaxRenderTargets(); + resources.OES_standard_derivatives = mRenderer->getDerivativeInstructionSupport(); + resources.EXT_draw_buffers = mRenderer->getMaxRenderTargets() > 1; + // resources.OES_EGL_image_external = mRenderer->getShareHandleSupport() ? 1 : 0; // TODO: commented out until the extension is actually supported. resources.FragmentPrecisionHigh = 1; // Shader Model 2+ always supports FP24 (s16e7) which corresponds to highp + resources.EXT_frag_depth = 1; // Shader Model 2+ always supports explicit depth output - mFragmentCompiler = ShConstructCompiler(SH_FRAGMENT_SHADER, SH_GLES2_SPEC, SH_HLSL_OUTPUT, &resources); - mVertexCompiler = ShConstructCompiler(SH_VERTEX_SHADER, SH_GLES2_SPEC, SH_HLSL_OUTPUT, &resources); + mFragmentCompiler = ShConstructCompiler(SH_FRAGMENT_SHADER, SH_GLES2_SPEC, hlslVersion, &resources); + mVertexCompiler = ShConstructCompiler(SH_VERTEX_SHADER, SH_GLES2_SPEC, hlslVersion, &resources); } } } @@ -288,10 +298,24 @@ void Shader::parseVaryings() input = strstr(input, ";") + 2; } + mUsesMultipleRenderTargets = strstr(mHlsl, "GL_USES_MRT") != NULL; + mUsesFragColor = strstr(mHlsl, "GL_USES_FRAG_COLOR") != NULL; + mUsesFragData = strstr(mHlsl, "GL_USES_FRAG_DATA") != NULL; mUsesFragCoord = strstr(mHlsl, "GL_USES_FRAG_COORD") != NULL; mUsesFrontFacing = strstr(mHlsl, "GL_USES_FRONT_FACING") != NULL; mUsesPointSize = strstr(mHlsl, "GL_USES_POINT_SIZE") != NULL; mUsesPointCoord = strstr(mHlsl, "GL_USES_POINT_COORD") != NULL; + mUsesDepthRange = strstr(mHlsl, "GL_USES_DEPTH_RANGE") != NULL; + mUsesFragDepth = strstr(mHlsl, "GL_USES_FRAG_DEPTH") != NULL; + } +} + +void Shader::resetVaryingsRegisterAssignment() +{ + for (VaryingList::iterator var = mVaryings.begin(); var != mVaryings.end(); var++) + { + var->reg = -1; + var->col = -1; } } @@ -307,10 +331,17 @@ void Shader::uncompile() // set by parseVaryings mVaryings.clear(); + mUsesMultipleRenderTargets = false; + mUsesFragColor = false; + mUsesFragData = false; mUsesFragCoord = false; mUsesFrontFacing = false; mUsesPointSize = false; mUsesPointCoord = false; + mUsesDepthRange = false; + mUsesFragDepth = false; + + mActiveUniforms.clear(); } void Shader::compileToHLSL(void *compiler) @@ -356,6 +387,10 @@ void Shader::compileToHLSL(void *compiler) ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &objCodeLen); mHlsl = new char[objCodeLen]; ShGetObjectCode(compiler, mHlsl); + + void *activeUniforms; + ShGetInfoPointer(compiler, SH_ACTIVE_UNIFORMS_ARRAY, &activeUniforms); + mActiveUniforms = *(sh::ActiveUniforms*)activeUniforms; } else { @@ -486,7 +521,8 @@ bool Shader::compareVarying(const Varying &x, const Varying &y) return false; } -VertexShader::VertexShader(ResourceManager *manager, GLuint handle) : Shader(manager, handle) +VertexShader::VertexShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle) + : Shader(manager, renderer, handle) { } @@ -561,7 +597,8 @@ void VertexShader::parseAttributes() } } -FragmentShader::FragmentShader(ResourceManager *manager, GLuint handle) : Shader(manager, handle) +FragmentShader::FragmentShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle) + : Shader(manager, renderer, handle) { } diff --git a/gfx/angle/src/libGLESv2/Shader.h b/gfx/angle/src/libGLESv2/Shader.h index b73fc288a117..4a9a27ed5033 100644 --- a/gfx/angle/src/libGLESv2/Shader.h +++ b/gfx/angle/src/libGLESv2/Shader.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -18,10 +18,18 @@ #include #include -#include "libGLESv2/ResourceManager.h" +#include "compiler/CompilerUniform.h" +#include "common/angleutils.h" + +namespace rx +{ +class Renderer; +} namespace gl { +class ResourceManager; + struct Varying { Varying(GLenum type, const std::string &name, int size, bool array) @@ -45,7 +53,7 @@ class Shader friend class ProgramBinary; public: - Shader(ResourceManager *manager, GLuint handle); + Shader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle); virtual ~Shader(); @@ -60,6 +68,7 @@ class Shader void getSource(GLsizei bufSize, GLsizei *length, char *buffer); int getTranslatedSourceLength() const; void getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer); + const sh::ActiveUniforms &getUniforms(); virtual void compile() = 0; virtual void uncompile(); @@ -76,6 +85,7 @@ class Shader protected: void parseVaryings(); + void resetVaryingsRegisterAssignment(); void compileToHLSL(void *compiler); @@ -84,12 +94,19 @@ class Shader static GLenum parseType(const std::string &type); static bool compareVarying(const Varying &x, const Varying &y); + const rx::Renderer *const mRenderer; + VaryingList mVaryings; + bool mUsesMultipleRenderTargets; + bool mUsesFragColor; + bool mUsesFragData; bool mUsesFragCoord; bool mUsesFrontFacing; bool mUsesPointSize; bool mUsesPointCoord; + bool mUsesDepthRange; + bool mUsesFragDepth; static void *mFragmentCompiler; static void *mVertexCompiler; @@ -106,6 +123,7 @@ class Shader char *mSource; char *mHlsl; char *mInfoLog; + sh::ActiveUniforms mActiveUniforms; ResourceManager *mResourceManager; }; @@ -131,7 +149,7 @@ class VertexShader : public Shader friend class ProgramBinary; public: - VertexShader(ResourceManager *manager, GLuint handle); + VertexShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle); ~VertexShader(); @@ -151,7 +169,7 @@ class VertexShader : public Shader class FragmentShader : public Shader { public: - FragmentShader(ResourceManager *manager, GLuint handle); + FragmentShader(ResourceManager *manager,const rx::Renderer *renderer, GLuint handle); ~FragmentShader(); diff --git a/gfx/angle/src/libGLESv2/Texture.cpp b/gfx/angle/src/libGLESv2/Texture.cpp index e3e8941d69ca..ae83037845f2 100644 --- a/gfx/angle/src/libGLESv2/Texture.cpp +++ b/gfx/angle/src/libGLESv2/Texture.cpp @@ -1,5 +1,6 @@ +#include "precompiled.h" // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -10,1316 +11,30 @@ #include "libGLESv2/Texture.h" -#include - -#include "common/debug.h" - -#include "libEGL/Display.h" - #include "libGLESv2/main.h" #include "libGLESv2/mathutil.h" #include "libGLESv2/utilities.h" -#include "libGLESv2/Blit.h" -#include "libGLESv2/Framebuffer.h" +#include "libGLESv2/renderer/Blit.h" +#include "libGLESv2/Renderbuffer.h" +#include "libGLESv2/renderer/Image.h" +#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/renderer/TextureStorage.h" +#include "libEGL/Surface.h" namespace gl { -unsigned int TextureStorage::mCurrentTextureSerial = 1; -static D3DFORMAT ConvertTextureInternalFormat(GLint internalformat) +Texture::Texture(rx::Renderer *renderer, GLuint id) : RefCountObject(id) { - switch (internalformat) - { - case GL_DEPTH_COMPONENT16: - case GL_DEPTH_COMPONENT32_OES: - case GL_DEPTH24_STENCIL8_OES: - return D3DFMT_INTZ; - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - return D3DFMT_DXT1; - case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: - return D3DFMT_DXT3; - case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: - return D3DFMT_DXT5; - case GL_RGBA32F_EXT: - case GL_RGB32F_EXT: - case GL_ALPHA32F_EXT: - case GL_LUMINANCE32F_EXT: - case GL_LUMINANCE_ALPHA32F_EXT: - return D3DFMT_A32B32G32R32F; - case GL_RGBA16F_EXT: - case GL_RGB16F_EXT: - case GL_ALPHA16F_EXT: - case GL_LUMINANCE16F_EXT: - case GL_LUMINANCE_ALPHA16F_EXT: - return D3DFMT_A16B16G16R16F; - case GL_LUMINANCE8_EXT: - if (getContext()->supportsLuminanceTextures()) - { - return D3DFMT_L8; - } - break; - case GL_LUMINANCE8_ALPHA8_EXT: - if (getContext()->supportsLuminanceAlphaTextures()) - { - return D3DFMT_A8L8; - } - break; - case GL_RGB8_OES: - case GL_RGB565: - return D3DFMT_X8R8G8B8; - } - - return D3DFMT_A8R8G8B8; -} - -static bool IsTextureFormatRenderable(D3DFORMAT format) -{ - if (format == D3DFMT_INTZ) - { - return true; - } - switch(format) - { - case D3DFMT_L8: - case D3DFMT_A8L8: - case D3DFMT_DXT1: - case D3DFMT_DXT3: - case D3DFMT_DXT5: - return false; - case D3DFMT_A8R8G8B8: - case D3DFMT_X8R8G8B8: - case D3DFMT_A16B16G16R16F: - case D3DFMT_A32B32G32R32F: - return true; - default: - UNREACHABLE(); - } - - return false; -} - -static inline DWORD GetTextureUsage(D3DFORMAT d3dfmt, GLenum glusage, bool forceRenderable) -{ - DWORD d3dusage = 0; - - if (d3dfmt == D3DFMT_INTZ) - { - d3dusage |= D3DUSAGE_DEPTHSTENCIL; - } - else if(forceRenderable || (IsTextureFormatRenderable(d3dfmt) && (glusage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE))) - { - d3dusage |= D3DUSAGE_RENDERTARGET; - } - return d3dusage; -} - -static void MakeValidSize(bool isImage, bool isCompressed, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset) -{ - int upsampleCount = 0; - - if (isCompressed) - { - // Don't expand the size of full textures that are at least 4x4 - // already. - if (isImage || *requestWidth < 4 || *requestHeight < 4) - { - while (*requestWidth % 4 != 0 || *requestHeight % 4 != 0) - { - *requestWidth <<= 1; - *requestHeight <<= 1; - upsampleCount++; - } - } - } - *levelOffset = upsampleCount; -} - -static void CopyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source) -{ - D3DLOCKED_RECT sourceLock = {0}; - D3DLOCKED_RECT destLock = {0}; - - source->LockRect(&sourceLock, NULL, 0); - dest->LockRect(&destLock, NULL, 0); - - if (sourceLock.pBits && destLock.pBits) - { - D3DSURFACE_DESC desc; - source->GetDesc(&desc); - - int rows = dx::IsCompressedFormat(desc.Format) ? desc.Height / 4 : desc.Height; - int bytes = dx::ComputeRowSize(desc.Format, desc.Width); - ASSERT(bytes <= sourceLock.Pitch && bytes <= destLock.Pitch); - - for(int i = 0; i < rows; i++) - { - memcpy((char*)destLock.pBits + destLock.Pitch * i, (char*)sourceLock.pBits + sourceLock.Pitch * i, bytes); - } - - source->UnlockRect(); - dest->UnlockRect(); - } - else UNREACHABLE(); -} - -Image::Image() -{ - mWidth = 0; - mHeight = 0; - mInternalFormat = GL_NONE; - - mSurface = NULL; - - mDirty = false; - - mD3DPool = D3DPOOL_SYSTEMMEM; - mD3DFormat = D3DFMT_UNKNOWN; -} - -Image::~Image() -{ - if (mSurface) - { - mSurface->Release(); - } -} - -bool Image::redefine(GLint internalformat, GLsizei width, GLsizei height, bool forceRelease) -{ - if (mWidth != width || - mHeight != height || - mInternalFormat != internalformat || - forceRelease) - { - mWidth = width; - mHeight = height; - mInternalFormat = internalformat; - // compute the d3d format that will be used - mD3DFormat = ConvertTextureInternalFormat(internalformat); - - if (mSurface) - { - mSurface->Release(); - mSurface = NULL; - } - - return true; - } - - return false; -} - -void Image::createSurface() -{ - if(mSurface) - { - return; - } - - IDirect3DTexture9 *newTexture = NULL; - IDirect3DSurface9 *newSurface = NULL; - const D3DPOOL poolToUse = D3DPOOL_SYSTEMMEM; - const D3DFORMAT d3dFormat = getD3DFormat(); - ASSERT(d3dFormat != D3DFMT_INTZ); // We should never get here for depth textures - - if (mWidth != 0 && mHeight != 0) - { - int levelToFetch = 0; - GLsizei requestWidth = mWidth; - GLsizei requestHeight = mHeight; - MakeValidSize(true, IsCompressed(mInternalFormat), &requestWidth, &requestHeight, &levelToFetch); - - HRESULT result = getDevice()->CreateTexture(requestWidth, requestHeight, levelToFetch + 1, 0, d3dFormat, - poolToUse, &newTexture, NULL); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - ERR("Creating image surface failed."); - return error(GL_OUT_OF_MEMORY); - } - - newTexture->GetSurfaceLevel(levelToFetch, &newSurface); - newTexture->Release(); - } - - mSurface = newSurface; - mDirty = false; - mD3DPool = poolToUse; -} - -HRESULT Image::lock(D3DLOCKED_RECT *lockedRect, const RECT *rect) -{ - createSurface(); - - HRESULT result = D3DERR_INVALIDCALL; - - if (mSurface) - { - result = mSurface->LockRect(lockedRect, rect, 0); - ASSERT(SUCCEEDED(result)); - - mDirty = true; - } - - return result; -} - -void Image::unlock() -{ - if (mSurface) - { - HRESULT result = mSurface->UnlockRect(); - ASSERT(SUCCEEDED(result)); - } -} - -bool Image::isRenderableFormat() const -{ - return IsTextureFormatRenderable(getD3DFormat()); -} - -D3DFORMAT Image::getD3DFormat() const -{ - // this should only happen if the image hasn't been redefined first - // which would be a bug by the caller - ASSERT(mD3DFormat != D3DFMT_UNKNOWN); - - return mD3DFormat; -} - -IDirect3DSurface9 *Image::getSurface() -{ - createSurface(); - - return mSurface; -} - -void Image::setManagedSurface(IDirect3DSurface9 *surface) -{ - D3DSURFACE_DESC desc; - surface->GetDesc(&desc); - ASSERT(desc.Pool == D3DPOOL_MANAGED); - - if ((GLsizei)desc.Width == mWidth && (GLsizei)desc.Height == mHeight) - { - if (mSurface) - { - CopyLockableSurfaces(surface, mSurface); - mSurface->Release(); - } - - mSurface = surface; - mD3DPool = desc.Pool; - } -} - -void Image::updateSurface(IDirect3DSurface9 *destSurface, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) -{ - IDirect3DSurface9 *sourceSurface = getSurface(); - - if (sourceSurface && sourceSurface != destSurface) - { - RECT rect; - rect.left = xoffset; - rect.top = yoffset; - rect.right = xoffset + width; - rect.bottom = yoffset + height; - - POINT point = {rect.left, rect.top}; - - if (mD3DPool == D3DPOOL_MANAGED) - { - D3DSURFACE_DESC desc; - sourceSurface->GetDesc(&desc); - - IDirect3DSurface9 *surf = 0; - HRESULT result = getDevice()->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL); - - if (SUCCEEDED(result)) - { - CopyLockableSurfaces(surf, sourceSurface); - result = getDevice()->UpdateSurface(surf, &rect, destSurface, &point); - ASSERT(SUCCEEDED(result)); - surf->Release(); - } - } - else - { - // UpdateSurface: source must be SYSTEMMEM, dest must be DEFAULT pools - HRESULT result = getDevice()->UpdateSurface(sourceSurface, &rect, destSurface, &point); - ASSERT(SUCCEEDED(result)); - } - } -} - -// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input -// into the target pixel rectangle. -void Image::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - GLint unpackAlignment, const void *input) -{ - RECT lockRect = - { - xoffset, yoffset, - xoffset + width, yoffset + height - }; - - D3DLOCKED_RECT locked; - HRESULT result = lock(&locked, &lockRect); - if (FAILED(result)) - { - return; - } - - - GLsizei inputPitch = ComputePitch(width, mInternalFormat, unpackAlignment); - - switch (mInternalFormat) - { - case GL_ALPHA8_EXT: - if (supportsSSE2()) - { - loadAlphaDataSSE2(width, height, inputPitch, input, locked.Pitch, locked.pBits); - } - else - { - loadAlphaData(width, height, inputPitch, input, locked.Pitch, locked.pBits); - } - break; - case GL_LUMINANCE8_EXT: - loadLuminanceData(width, height, inputPitch, input, locked.Pitch, locked.pBits, getD3DFormat() == D3DFMT_L8); - break; - case GL_ALPHA32F_EXT: - loadAlphaFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_LUMINANCE32F_EXT: - loadLuminanceFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_ALPHA16F_EXT: - loadAlphaHalfFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_LUMINANCE16F_EXT: - loadLuminanceHalfFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_LUMINANCE8_ALPHA8_EXT: - loadLuminanceAlphaData(width, height, inputPitch, input, locked.Pitch, locked.pBits, getD3DFormat() == D3DFMT_A8L8); - break; - case GL_LUMINANCE_ALPHA32F_EXT: - loadLuminanceAlphaFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_LUMINANCE_ALPHA16F_EXT: - loadLuminanceAlphaHalfFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_RGB8_OES: - loadRGBUByteData(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_RGB565: - loadRGB565Data(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_RGBA8_OES: - if (supportsSSE2()) - { - loadRGBAUByteDataSSE2(width, height, inputPitch, input, locked.Pitch, locked.pBits); - } - else - { - loadRGBAUByteData(width, height, inputPitch, input, locked.Pitch, locked.pBits); - } - break; - case GL_RGBA4: - loadRGBA4444Data(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_RGB5_A1: - loadRGBA5551Data(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_BGRA8_EXT: - loadBGRAData(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - // float textures are converted to RGBA, not BGRA, as they're stored that way in D3D - case GL_RGB32F_EXT: - loadRGBFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_RGB16F_EXT: - loadRGBHalfFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_RGBA32F_EXT: - loadRGBAFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_RGBA16F_EXT: - loadRGBAHalfFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - default: UNREACHABLE(); - } - - unlock(); -} - -void Image::loadAlphaData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const -{ - const unsigned char *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = static_cast(input) + y * inputPitch; - dest = static_cast(output) + y * outputPitch; - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = 0; - dest[4 * x + 1] = 0; - dest[4 * x + 2] = 0; - dest[4 * x + 3] = source[x]; - } - } -} - -void Image::loadAlphaFloatData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const -{ - const float *source = NULL; - float *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = reinterpret_cast(static_cast(output) + y * outputPitch); - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = 0; - dest[4 * x + 1] = 0; - dest[4 * x + 2] = 0; - dest[4 * x + 3] = source[x]; - } - } -} - -void Image::loadAlphaHalfFloatData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const -{ - const unsigned short *source = NULL; - unsigned short *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = reinterpret_cast(static_cast(output) + y * outputPitch); - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = 0; - dest[4 * x + 1] = 0; - dest[4 * x + 2] = 0; - dest[4 * x + 3] = source[x]; - } - } -} - -void Image::loadLuminanceData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output, bool native) const -{ - const unsigned char *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = static_cast(input) + y * inputPitch; - dest = static_cast(output) + y * outputPitch; - - if (!native) // BGRA8 destination format - { - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = source[x]; - dest[4 * x + 1] = source[x]; - dest[4 * x + 2] = source[x]; - dest[4 * x + 3] = 0xFF; - } - } - else // L8 destination format - { - memcpy(dest, source, width); - } - } -} - -void Image::loadLuminanceFloatData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const -{ - const float *source = NULL; - float *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = reinterpret_cast(static_cast(output) + y * outputPitch); - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = source[x]; - dest[4 * x + 1] = source[x]; - dest[4 * x + 2] = source[x]; - dest[4 * x + 3] = 1.0f; - } - } -} - -void Image::loadLuminanceHalfFloatData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const -{ - const unsigned short *source = NULL; - unsigned short *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = reinterpret_cast(static_cast(output) + y * outputPitch); - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = source[x]; - dest[4 * x + 1] = source[x]; - dest[4 * x + 2] = source[x]; - dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1 - } - } -} - -void Image::loadLuminanceAlphaData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output, bool native) const -{ - const unsigned char *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = static_cast(input) + y * inputPitch; - dest = static_cast(output) + y * outputPitch; - - if (!native) // BGRA8 destination format - { - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = source[2*x+0]; - dest[4 * x + 1] = source[2*x+0]; - dest[4 * x + 2] = source[2*x+0]; - dest[4 * x + 3] = source[2*x+1]; - } - } - else - { - memcpy(dest, source, width * 2); - } - } -} - -void Image::loadLuminanceAlphaFloatData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const -{ - const float *source = NULL; - float *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = reinterpret_cast(static_cast(output) + y * outputPitch); - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = source[2*x+0]; - dest[4 * x + 1] = source[2*x+0]; - dest[4 * x + 2] = source[2*x+0]; - dest[4 * x + 3] = source[2*x+1]; - } - } -} - -void Image::loadLuminanceAlphaHalfFloatData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const -{ - const unsigned short *source = NULL; - unsigned short *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = reinterpret_cast(static_cast(output) + y * outputPitch); - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = source[2*x+0]; - dest[4 * x + 1] = source[2*x+0]; - dest[4 * x + 2] = source[2*x+0]; - dest[4 * x + 3] = source[2*x+1]; - } - } -} - -void Image::loadRGBUByteData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const -{ - const unsigned char *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = static_cast(input) + y * inputPitch; - dest = static_cast(output) + y * outputPitch; - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = source[x * 3 + 2]; - dest[4 * x + 1] = source[x * 3 + 1]; - dest[4 * x + 2] = source[x * 3 + 0]; - dest[4 * x + 3] = 0xFF; - } - } -} - -void Image::loadRGB565Data(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const -{ - const unsigned short *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = static_cast(output) + y * outputPitch; - for (int x = 0; x < width; x++) - { - unsigned short rgba = source[x]; - dest[4 * x + 0] = ((rgba & 0x001F) << 3) | ((rgba & 0x001F) >> 2); - dest[4 * x + 1] = ((rgba & 0x07E0) >> 3) | ((rgba & 0x07E0) >> 9); - dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13); - dest[4 * x + 3] = 0xFF; - } - } -} - -void Image::loadRGBFloatData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const -{ - const float *source = NULL; - float *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = reinterpret_cast(static_cast(output) + y * outputPitch); - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = source[x * 3 + 0]; - dest[4 * x + 1] = source[x * 3 + 1]; - dest[4 * x + 2] = source[x * 3 + 2]; - dest[4 * x + 3] = 1.0f; - } - } -} - -void Image::loadRGBHalfFloatData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const -{ - const unsigned short *source = NULL; - unsigned short *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = reinterpret_cast(static_cast(output) + y * outputPitch); - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = source[x * 3 + 0]; - dest[4 * x + 1] = source[x * 3 + 1]; - dest[4 * x + 2] = source[x * 3 + 2]; - dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1 - } - } -} - -void Image::loadRGBAUByteData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const -{ - const unsigned int *source = NULL; - unsigned int *dest = NULL; - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = reinterpret_cast(static_cast(output) + y * outputPitch); - - for (int x = 0; x < width; x++) - { - unsigned int rgba = source[x]; - dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00); - } - } -} - -void Image::loadRGBA4444Data(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const -{ - const unsigned short *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = static_cast(output) + y * outputPitch; - for (int x = 0; x < width; x++) - { - unsigned short rgba = source[x]; - dest[4 * x + 0] = ((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4); - dest[4 * x + 1] = ((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8); - dest[4 * x + 2] = ((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12); - dest[4 * x + 3] = ((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0); - } - } -} - -void Image::loadRGBA5551Data(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const -{ - const unsigned short *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = static_cast(output) + y * outputPitch; - for (int x = 0; x < width; x++) - { - unsigned short rgba = source[x]; - dest[4 * x + 0] = ((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3); - dest[4 * x + 1] = ((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8); - dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13); - dest[4 * x + 3] = (rgba & 0x0001) ? 0xFF : 0; - } - } -} - -void Image::loadRGBAFloatData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const -{ - const float *source = NULL; - float *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = reinterpret_cast(static_cast(output) + y * outputPitch); - memcpy(dest, source, width * 16); - } -} - -void Image::loadRGBAHalfFloatData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const -{ - const unsigned char *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = static_cast(input) + y * inputPitch; - dest = static_cast(output) + y * outputPitch; - memcpy(dest, source, width * 8); - } -} - -void Image::loadBGRAData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const -{ - const unsigned char *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = static_cast(input) + y * inputPitch; - dest = static_cast(output) + y * outputPitch; - memcpy(dest, source, width*4); - } -} - -void Image::loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - const void *input) { - ASSERT(xoffset % 4 == 0); - ASSERT(yoffset % 4 == 0); - - RECT lockRect = { - xoffset, yoffset, - xoffset + width, yoffset + height - }; - - D3DLOCKED_RECT locked; - HRESULT result = lock(&locked, &lockRect); - if (FAILED(result)) - { - return; - } - - GLsizei inputSize = ComputeCompressedSize(width, height, mInternalFormat); - GLsizei inputPitch = ComputeCompressedPitch(width, mInternalFormat); - int rows = inputSize / inputPitch; - for (int i = 0; i < rows; ++i) - { - memcpy((void*)((BYTE*)locked.pBits + i * locked.Pitch), (void*)((BYTE*)input + i * inputPitch), inputPitch); - } - - unlock(); -} - -// This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats and incomplete textures -void Image::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, IDirect3DSurface9 *renderTarget) -{ - IDirect3DDevice9 *device = getDevice(); - IDirect3DSurface9 *renderTargetData = NULL; - D3DSURFACE_DESC description; - renderTarget->GetDesc(&description); - - HRESULT result = device->CreateOffscreenPlainSurface(description.Width, description.Height, description.Format, D3DPOOL_SYSTEMMEM, &renderTargetData, NULL); - - if (FAILED(result)) - { - ERR("Could not create matching destination surface."); - return error(GL_OUT_OF_MEMORY); - } - - result = device->GetRenderTargetData(renderTarget, renderTargetData); - - if (FAILED(result)) - { - ERR("GetRenderTargetData unexpectedly failed."); - renderTargetData->Release(); - return error(GL_OUT_OF_MEMORY); - } - - RECT sourceRect = {x, y, x + width, y + height}; - RECT destRect = {xoffset, yoffset, xoffset + width, yoffset + height}; - - D3DLOCKED_RECT sourceLock = {0}; - result = renderTargetData->LockRect(&sourceLock, &sourceRect, 0); - - if (FAILED(result)) - { - ERR("Failed to lock the source surface (rectangle might be invalid)."); - renderTargetData->Release(); - return error(GL_OUT_OF_MEMORY); - } - - D3DLOCKED_RECT destLock = {0}; - result = lock(&destLock, &destRect); - - if (FAILED(result)) - { - ERR("Failed to lock the destination surface (rectangle might be invalid)."); - renderTargetData->UnlockRect(); - renderTargetData->Release(); - return error(GL_OUT_OF_MEMORY); - } - - if (destLock.pBits && sourceLock.pBits) - { - unsigned char *source = (unsigned char*)sourceLock.pBits; - unsigned char *dest = (unsigned char*)destLock.pBits; - - switch (description.Format) - { - case D3DFMT_X8R8G8B8: - case D3DFMT_A8R8G8B8: - switch(getD3DFormat()) - { - case D3DFMT_X8R8G8B8: - case D3DFMT_A8R8G8B8: - for(int y = 0; y < height; y++) - { - memcpy(dest, source, 4 * width); - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - case D3DFMT_L8: - for(int y = 0; y < height; y++) - { - for(int x = 0; x < width; x++) - { - dest[x] = source[x * 4 + 2]; - } - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - case D3DFMT_A8L8: - for(int y = 0; y < height; y++) - { - for(int x = 0; x < width; x++) - { - dest[x * 2 + 0] = source[x * 4 + 2]; - dest[x * 2 + 1] = source[x * 4 + 3]; - } - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - default: - UNREACHABLE(); - } - break; - case D3DFMT_R5G6B5: - switch(getD3DFormat()) - { - case D3DFMT_X8R8G8B8: - for(int y = 0; y < height; y++) - { - for(int x = 0; x < width; x++) - { - unsigned short rgb = ((unsigned short*)source)[x]; - unsigned char red = (rgb & 0xF800) >> 8; - unsigned char green = (rgb & 0x07E0) >> 3; - unsigned char blue = (rgb & 0x001F) << 3; - dest[x + 0] = blue | (blue >> 5); - dest[x + 1] = green | (green >> 6); - dest[x + 2] = red | (red >> 5); - dest[x + 3] = 0xFF; - } - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - case D3DFMT_L8: - for(int y = 0; y < height; y++) - { - for(int x = 0; x < width; x++) - { - unsigned char red = source[x * 2 + 1] & 0xF8; - dest[x] = red | (red >> 5); - } - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - default: - UNREACHABLE(); - } - break; - case D3DFMT_A1R5G5B5: - switch(getD3DFormat()) - { - case D3DFMT_X8R8G8B8: - for(int y = 0; y < height; y++) - { - for(int x = 0; x < width; x++) - { - unsigned short argb = ((unsigned short*)source)[x]; - unsigned char red = (argb & 0x7C00) >> 7; - unsigned char green = (argb & 0x03E0) >> 2; - unsigned char blue = (argb & 0x001F) << 3; - dest[x + 0] = blue | (blue >> 5); - dest[x + 1] = green | (green >> 5); - dest[x + 2] = red | (red >> 5); - dest[x + 3] = 0xFF; - } - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - case D3DFMT_A8R8G8B8: - for(int y = 0; y < height; y++) - { - for(int x = 0; x < width; x++) - { - unsigned short argb = ((unsigned short*)source)[x]; - unsigned char red = (argb & 0x7C00) >> 7; - unsigned char green = (argb & 0x03E0) >> 2; - unsigned char blue = (argb & 0x001F) << 3; - unsigned char alpha = (signed short)argb >> 15; - dest[x + 0] = blue | (blue >> 5); - dest[x + 1] = green | (green >> 5); - dest[x + 2] = red | (red >> 5); - dest[x + 3] = alpha; - } - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - case D3DFMT_L8: - for(int y = 0; y < height; y++) - { - for(int x = 0; x < width; x++) - { - unsigned char red = source[x * 2 + 1] & 0x7C; - dest[x] = (red << 1) | (red >> 4); - } - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - case D3DFMT_A8L8: - for(int y = 0; y < height; y++) - { - for(int x = 0; x < width; x++) - { - unsigned char red = source[x * 2 + 1] & 0x7C; - dest[x * 2 + 0] = (red << 1) | (red >> 4); - dest[x * 2 + 1] = (signed char)source[x * 2 + 1] >> 7; - } - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - default: - UNREACHABLE(); - } - break; - default: - UNREACHABLE(); - } - } - - unlock(); - renderTargetData->UnlockRect(); - - renderTargetData->Release(); - - mDirty = true; -} - -namespace -{ -struct L8 -{ - unsigned char L; - - static void average(L8 *dst, const L8 *src1, const L8 *src2) - { - dst->L = ((src1->L ^ src2->L) >> 1) + (src1->L & src2->L); - } -}; - -struct A8L8 -{ - unsigned char L; - unsigned char A; - - static void average(A8L8 *dst, const A8L8 *src1, const A8L8 *src2) - { - *(unsigned short*)dst = (((*(unsigned short*)src1 ^ *(unsigned short*)src2) & 0xFEFE) >> 1) + (*(unsigned short*)src1 & *(unsigned short*)src2); - } -}; - -struct A8R8G8B8 -{ - unsigned char B; - unsigned char G; - unsigned char R; - unsigned char A; - - static void average(A8R8G8B8 *dst, const A8R8G8B8 *src1, const A8R8G8B8 *src2) - { - *(unsigned int*)dst = (((*(unsigned int*)src1 ^ *(unsigned int*)src2) & 0xFEFEFEFE) >> 1) + (*(unsigned int*)src1 & *(unsigned int*)src2); - } -}; - -struct A16B16G16R16F -{ - unsigned short R; - unsigned short G; - unsigned short B; - unsigned short A; - - static void average(A16B16G16R16F *dst, const A16B16G16R16F *src1, const A16B16G16R16F *src2) - { - dst->R = float32ToFloat16((float16ToFloat32(src1->R) + float16ToFloat32(src2->R)) * 0.5f); - dst->G = float32ToFloat16((float16ToFloat32(src1->G) + float16ToFloat32(src2->G)) * 0.5f); - dst->B = float32ToFloat16((float16ToFloat32(src1->B) + float16ToFloat32(src2->B)) * 0.5f); - dst->A = float32ToFloat16((float16ToFloat32(src1->A) + float16ToFloat32(src2->A)) * 0.5f); - } -}; - -struct A32B32G32R32F -{ - float R; - float G; - float B; - float A; - - static void average(A32B32G32R32F *dst, const A32B32G32R32F *src1, const A32B32G32R32F *src2) - { - dst->R = (src1->R + src2->R) * 0.5f; - dst->G = (src1->G + src2->G) * 0.5f; - dst->B = (src1->B + src2->B) * 0.5f; - dst->A = (src1->A + src2->A) * 0.5f; - } -}; - -template -void GenerateMip(unsigned int sourceWidth, unsigned int sourceHeight, - const unsigned char *sourceData, int sourcePitch, - unsigned char *destData, int destPitch) -{ - unsigned int mipWidth = std::max(1U, sourceWidth >> 1); - unsigned int mipHeight = std::max(1U, sourceHeight >> 1); - - if (sourceHeight == 1) - { - ASSERT(sourceWidth != 1); - - const T *src = (const T*)sourceData; - T *dst = (T*)destData; - - for (unsigned int x = 0; x < mipWidth; x++) - { - T::average(&dst[x], &src[x * 2], &src[x * 2 + 1]); - } - } - else if (sourceWidth == 1) - { - ASSERT(sourceHeight != 1); - - for (unsigned int y = 0; y < mipHeight; y++) - { - const T *src0 = (const T*)(sourceData + y * 2 * sourcePitch); - const T *src1 = (const T*)(sourceData + y * 2 * sourcePitch + sourcePitch); - T *dst = (T*)(destData + y * destPitch); - - T::average(dst, src0, src1); - } - } - else - { - for (unsigned int y = 0; y < mipHeight; y++) - { - const T *src0 = (const T*)(sourceData + y * 2 * sourcePitch); - const T *src1 = (const T*)(sourceData + y * 2 * sourcePitch + sourcePitch); - T *dst = (T*)(destData + y * destPitch); - - for (unsigned int x = 0; x < mipWidth; x++) - { - T tmp0; - T tmp1; - - T::average(&tmp0, &src0[x * 2], &src0[x * 2 + 1]); - T::average(&tmp1, &src1[x * 2], &src1[x * 2 + 1]); - T::average(&dst[x], &tmp0, &tmp1); - } - } - } -} - -void GenerateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface) -{ - D3DSURFACE_DESC destDesc; - HRESULT result = destSurface->GetDesc(&destDesc); - ASSERT(SUCCEEDED(result)); - - D3DSURFACE_DESC sourceDesc; - result = sourceSurface->GetDesc(&sourceDesc); - ASSERT(SUCCEEDED(result)); - - ASSERT(sourceDesc.Format == destDesc.Format); - ASSERT(sourceDesc.Width == 1 || sourceDesc.Width / 2 == destDesc.Width); - ASSERT(sourceDesc.Height == 1 || sourceDesc.Height / 2 == destDesc.Height); - - D3DLOCKED_RECT sourceLocked = {0}; - result = sourceSurface->LockRect(&sourceLocked, NULL, D3DLOCK_READONLY); - ASSERT(SUCCEEDED(result)); - - D3DLOCKED_RECT destLocked = {0}; - result = destSurface->LockRect(&destLocked, NULL, 0); - ASSERT(SUCCEEDED(result)); - - const unsigned char *sourceData = reinterpret_cast(sourceLocked.pBits); - unsigned char *destData = reinterpret_cast(destLocked.pBits); - - if (sourceData && destData) - { - switch (sourceDesc.Format) - { - case D3DFMT_L8: - GenerateMip(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch); - break; - case D3DFMT_A8L8: - GenerateMip(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch); - break; - case D3DFMT_A8R8G8B8: - case D3DFMT_X8R8G8B8: - GenerateMip(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch); - break; - case D3DFMT_A16B16G16R16F: - GenerateMip(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch); - break; - case D3DFMT_A32B32G32R32F: - GenerateMip(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch); - break; - default: - UNREACHABLE(); - break; - } - - destSurface->UnlockRect(); - sourceSurface->UnlockRect(); - } -} -} - -TextureStorage::TextureStorage(DWORD usage) - : mLodOffset(0), - mD3DUsage(usage), - mD3DPool(getDisplay()->getTexturePool(usage)), - mTextureSerial(issueTextureSerial()) -{ -} - -TextureStorage::~TextureStorage() -{ -} - -bool TextureStorage::isRenderTarget() const -{ - return (mD3DUsage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL)) != 0; -} - -bool TextureStorage::isManaged() const -{ - return (mD3DPool == D3DPOOL_MANAGED); -} - -D3DPOOL TextureStorage::getPool() const -{ - return mD3DPool; -} - -DWORD TextureStorage::getUsage() const -{ - return mD3DUsage; -} - -unsigned int TextureStorage::getTextureSerial() const -{ - return mTextureSerial; -} - -unsigned int TextureStorage::issueTextureSerial() -{ - return mCurrentTextureSerial++; -} - -int TextureStorage::getLodOffset() const -{ - return mLodOffset; -} - -Texture::Texture(GLuint id) : RefCountObject(id) -{ - mMinFilter = GL_NEAREST_MIPMAP_LINEAR; - mMagFilter = GL_LINEAR; - mWrapS = GL_REPEAT; - mWrapT = GL_REPEAT; - mDirtyParameters = true; + mRenderer = renderer; + + mSamplerState.minFilter = GL_NEAREST_MIPMAP_LINEAR; + mSamplerState.magFilter = GL_LINEAR; + mSamplerState.wrapS = GL_REPEAT; + mSamplerState.wrapT = GL_REPEAT; + mSamplerState.maxAnisotropy = 1.0f; + mSamplerState.lodOffset = 0; mUsage = GL_NONE; - mMaxAnisotropy = 1.0f; mDirtyImages = true; @@ -1341,14 +56,8 @@ bool Texture::setMinFilter(GLenum filter) case GL_LINEAR_MIPMAP_NEAREST: case GL_NEAREST_MIPMAP_LINEAR: case GL_LINEAR_MIPMAP_LINEAR: - { - if (mMinFilter != filter) - { - mMinFilter = filter; - mDirtyParameters = true; - } - return true; - } + mSamplerState.minFilter = filter; + return true; default: return false; } @@ -1361,14 +70,8 @@ bool Texture::setMagFilter(GLenum filter) { case GL_NEAREST: case GL_LINEAR: - { - if (mMagFilter != filter) - { - mMagFilter = filter; - mDirtyParameters = true; - } - return true; - } + mSamplerState.magFilter = filter; + return true; default: return false; } @@ -1382,14 +85,8 @@ bool Texture::setWrapS(GLenum wrap) case GL_REPEAT: case GL_CLAMP_TO_EDGE: case GL_MIRRORED_REPEAT: - { - if (mWrapS != wrap) - { - mWrapS = wrap; - mDirtyParameters = true; - } - return true; - } + mSamplerState.wrapS = wrap; + return true; default: return false; } @@ -1403,14 +100,8 @@ bool Texture::setWrapT(GLenum wrap) case GL_REPEAT: case GL_CLAMP_TO_EDGE: case GL_MIRRORED_REPEAT: - { - if (mWrapT != wrap) - { - mWrapT = wrap; - mDirtyParameters = true; - } - return true; - } + mSamplerState.wrapT = wrap; + return true; default: return false; } @@ -1424,11 +115,9 @@ bool Texture::setMaxAnisotropy(float textureMaxAnisotropy, float contextMaxAniso { return false; } - if (mMaxAnisotropy != textureMaxAnisotropy) - { - mMaxAnisotropy = textureMaxAnisotropy; - mDirtyParameters = true; - } + + mSamplerState.maxAnisotropy = textureMaxAnisotropy; + return true; } @@ -1448,27 +137,39 @@ bool Texture::setUsage(GLenum usage) GLenum Texture::getMinFilter() const { - return mMinFilter; + return mSamplerState.minFilter; } GLenum Texture::getMagFilter() const { - return mMagFilter; + return mSamplerState.magFilter; } GLenum Texture::getWrapS() const { - return mWrapS; + return mSamplerState.wrapS; } GLenum Texture::getWrapT() const { - return mWrapT; + return mSamplerState.wrapT; } float Texture::getMaxAnisotropy() const { - return mMaxAnisotropy; + return mSamplerState.maxAnisotropy; +} + +int Texture::getLodOffset() +{ + rx::TextureStorageInterface *texture = getStorage(false); + return texture ? texture->getLodOffset() : 0; +} + +void Texture::getSamplerState(SamplerState *sampler) +{ + *sampler = mSamplerState; + sampler->lodOffset = getLodOffset(); } GLenum Texture::getUsage() const @@ -1478,7 +179,7 @@ GLenum Texture::getUsage() const bool Texture::isMipmapFiltered() const { - switch (mMinFilter) + switch (mSamplerState.minFilter) { case GL_NEAREST: case GL_LINEAR: @@ -1493,7 +194,7 @@ bool Texture::isMipmapFiltered() const } } -void Texture::setImage(GLint unpackAlignment, const void *pixels, Image *image) +void Texture::setImage(GLint unpackAlignment, const void *pixels, rx::Image *image) { if (pixels != NULL) { @@ -1502,7 +203,7 @@ void Texture::setImage(GLint unpackAlignment, const void *pixels, Image *image) } } -void Texture::setCompressedImage(GLsizei imageSize, const void *pixels, Image *image) +void Texture::setCompressedImage(GLsizei imageSize, const void *pixels, rx::Image *image) { if (pixels != NULL) { @@ -1511,7 +212,7 @@ void Texture::setCompressedImage(GLsizei imageSize, const void *pixels, Image *i } } -bool Texture::subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *image) +bool Texture::subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, rx::Image *image) { if (pixels != NULL) { @@ -1522,7 +223,7 @@ bool Texture::subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei heig return true; } -bool Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *image) +bool Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, rx::Image *image) { if (pixels != NULL) { @@ -1533,27 +234,17 @@ bool Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GL return true; } -IDirect3DBaseTexture9 *Texture::getTexture() +rx::TextureStorageInterface *Texture::getNativeTexture() { - if (!isSamplerComplete()) - { - return NULL; - } - // ensure the underlying texture is created - if (getStorage(false) == NULL) + + rx::TextureStorageInterface *storage = getStorage(false); + if (storage) { - return NULL; + updateTexture(); } - updateTexture(); - - return getBaseTexture(); -} - -bool Texture::hasDirtyParameters() const -{ - return mDirtyParameters; + return storage; } bool Texture::hasDirtyImages() const @@ -1563,19 +254,18 @@ bool Texture::hasDirtyImages() const void Texture::resetDirty() { - mDirtyParameters = false; mDirtyImages = false; } unsigned int Texture::getTextureSerial() { - TextureStorage *texture = getStorage(false); + rx::TextureStorageInterface *texture = getStorage(false); return texture ? texture->getTextureSerial() : 0; } unsigned int Texture::getRenderTargetSerial(GLenum target) { - TextureStorage *texture = getStorage(true); + rx::TextureStorageInterface *texture = getStorage(true); return texture ? texture->getRenderTargetSerial(target) : 0; } @@ -1584,15 +274,9 @@ bool Texture::isImmutable() const return mImmutable; } -int Texture::getLodOffset() -{ - TextureStorage *texture = getStorage(false); - return texture ? texture->getLodOffset() : 0; -} - GLint Texture::creationLevels(GLsizei width, GLsizei height) const { - if ((isPow2(width) && isPow2(height)) || getContext()->supportsNonPower2Texture()) + if ((isPow2(width) && isPow2(height)) || mRenderer->getNonPower2TextureSupport()) { return 0; // Maximum number of levels } @@ -1608,127 +292,17 @@ GLint Texture::creationLevels(GLsizei size) const return creationLevels(size, size); } -int Texture::levelCount() -{ - return getBaseTexture() ? getBaseTexture()->GetLevelCount() - getLodOffset() : 0; -} - -Blit *Texture::getBlitter() -{ - Context *context = getContext(); - return context->getBlitter(); -} - -bool Texture::copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged) -{ - if (source && dest) - { - HRESULT result = D3DERR_OUTOFVIDEOMEMORY; - - if (fromManaged) - { - D3DSURFACE_DESC desc; - source->GetDesc(&desc); - - IDirect3DSurface9 *surf = 0; - result = getDevice()->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL); - - if (SUCCEEDED(result)) - { - CopyLockableSurfaces(surf, source); - result = getDevice()->UpdateSurface(surf, NULL, dest, NULL); - surf->Release(); - } - } - else - { - egl::Display *display = getDisplay(); - IDirect3DDevice9 *device = display->getDevice(); - - display->endScene(); - result = device->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE); - } - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - return false; - } - } - - return true; -} - -TextureStorage2D::TextureStorage2D(IDirect3DTexture9 *surfaceTexture) : TextureStorage(D3DUSAGE_RENDERTARGET), mRenderTargetSerial(RenderbufferStorage::issueSerial()) -{ - mTexture = surfaceTexture; -} - -TextureStorage2D::TextureStorage2D(int levels, D3DFORMAT format, DWORD usage, int width, int height) - : TextureStorage(usage), mRenderTargetSerial(RenderbufferStorage::issueSerial()) -{ - mTexture = NULL; - // if the width or height is not positive this should be treated as an incomplete texture - // we handle that here by skipping the d3d texture creation - if (width > 0 && height > 0) - { - IDirect3DDevice9 *device = getDevice(); - MakeValidSize(false, dx::IsCompressedFormat(format), &width, &height, &mLodOffset); - HRESULT result = device->CreateTexture(width, height, levels ? levels + mLodOffset : 0, getUsage(), format, getPool(), &mTexture, NULL); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - error(GL_OUT_OF_MEMORY); - } - } -} - -TextureStorage2D::~TextureStorage2D() -{ - if (mTexture) - { - mTexture->Release(); - } -} - -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *TextureStorage2D::getSurfaceLevel(int level, bool dirty) -{ - IDirect3DSurface9 *surface = NULL; - - if (mTexture) - { - HRESULT result = mTexture->GetSurfaceLevel(level + mLodOffset, &surface); - ASSERT(SUCCEEDED(result)); - - // With managed textures the driver needs to be informed of updates to the lower mipmap levels - if (level != 0 && isManaged() && dirty) - { - mTexture->AddDirtyRect(NULL); - } - } - - return surface; -} - -IDirect3DBaseTexture9 *TextureStorage2D::getBaseTexture() const -{ - return mTexture; -} - -unsigned int TextureStorage2D::getRenderTargetSerial(GLenum target) const -{ - return mRenderTargetSerial; -} - -Texture2D::Texture2D(GLuint id) : Texture(id) +Texture2D::Texture2D(rx::Renderer *renderer, GLuint id) : Texture(renderer, id) { mTexStorage = NULL; mSurface = NULL; mColorbufferProxy = NULL; mProxyRefs = 0; + + for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i) + { + mImageArray[i] = renderer->createImage(); + } } Texture2D::~Texture2D() @@ -1743,6 +317,11 @@ Texture2D::~Texture2D() mSurface->setBoundTexture(NULL); mSurface = NULL; } + + for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i) + { + delete mImageArray[i]; + } } // We need to maintain a count of references to renderbuffers acting as @@ -1770,7 +349,7 @@ GLenum Texture2D::getTarget() const GLsizei Texture2D::getWidth(GLint level) const { if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mImageArray[level].getWidth(); + return mImageArray[level]->getWidth(); else return 0; } @@ -1778,7 +357,7 @@ GLsizei Texture2D::getWidth(GLint level) const GLsizei Texture2D::getHeight(GLint level) const { if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mImageArray[level].getHeight(); + return mImageArray[level]->getHeight(); else return 0; } @@ -1786,15 +365,15 @@ GLsizei Texture2D::getHeight(GLint level) const GLenum Texture2D::getInternalFormat(GLint level) const { if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mImageArray[level].getInternalFormat(); + return mImageArray[level]->getInternalFormat(); else return GL_NONE; } -D3DFORMAT Texture2D::getD3DFormat(GLint level) const +GLenum Texture2D::getActualFormat(GLint level) const { if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mImageArray[level].getD3DFormat(); + return mImageArray[level]->getActualFormat(); else return D3DFMT_UNKNOWN; } @@ -1803,18 +382,31 @@ void Texture2D::redefineImage(GLint level, GLint internalformat, GLsizei width, { releaseTexImage(); - bool redefined = mImageArray[level].redefine(internalformat, width, height, false); + // If there currently is a corresponding storage texture image, it has these parameters + const int storageWidth = std::max(1, mImageArray[0]->getWidth() >> level); + const int storageHeight = std::max(1, mImageArray[0]->getHeight() >> level); + const int storageFormat = mImageArray[0]->getInternalFormat(); - if (mTexStorage && redefined) + mImageArray[level]->redefine(mRenderer, internalformat, width, height, false); + + if (mTexStorage) { - for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + const int storageLevels = mTexStorage->levelCount(); + + if ((level >= storageLevels && storageLevels != 0) || + width != storageWidth || + height != storageHeight || + internalformat != storageFormat) // Discard mismatched storage { - mImageArray[i].markDirty(); - } + for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + mImageArray[i]->markDirty(); + } - delete mTexStorage; - mTexStorage = NULL; - mDirtyImages = true; + delete mTexStorage; + mTexStorage = NULL; + mDirtyImages = true; + } } } @@ -1823,32 +415,19 @@ void Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum form GLint internalformat = ConvertSizedInternalFormat(format, type); redefineImage(level, internalformat, width, height); - Texture::setImage(unpackAlignment, pixels, &mImageArray[level]); + Texture::setImage(unpackAlignment, pixels, mImageArray[level]); } void Texture2D::bindTexImage(egl::Surface *surface) { releaseTexImage(); - GLint internalformat; + GLint internalformat = surface->getFormat(); - switch(surface->getFormat()) - { - case D3DFMT_A8R8G8B8: - internalformat = GL_RGBA8_OES; - break; - case D3DFMT_X8R8G8B8: - internalformat = GL_RGB8_OES; - break; - default: - UNIMPLEMENTED(); - return; - } - - mImageArray[0].redefine(internalformat, surface->getWidth(), surface->getHeight(), true); + mImageArray[0]->redefine(mRenderer, internalformat, surface->getWidth(), surface->getHeight(), true); delete mTexStorage; - mTexStorage = new TextureStorage2D(surface->getOffscreenTexture()); + mTexStorage = new rx::TextureStorageInterface2D(mRenderer, surface->getSwapChain()); mDirtyImages = true; mSurface = surface; @@ -1870,7 +449,7 @@ void Texture2D::releaseTexImage() for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) { - mImageArray[i].redefine(GL_RGBA8_OES, 0, 0, true); + mImageArray[i]->redefine(mRenderer, GL_NONE, 0, 0, true); } } } @@ -1880,23 +459,16 @@ void Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GL // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly redefineImage(level, format, width, height); - Texture::setCompressedImage(imageSize, pixels, &mImageArray[level]); + Texture::setCompressedImage(imageSize, pixels, mImageArray[level]); } void Texture2D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) { - ASSERT(mImageArray[level].getSurface() != NULL); - if (level < levelCount()) { - IDirect3DSurface9 *destLevel = mTexStorage->getSurfaceLevel(level, true); - - if (destLevel) + rx::Image *image = mImageArray[level]; + if (image->updateSurface(mTexStorage, level, xoffset, yoffset, width, height)) { - Image *image = &mImageArray[level]; - image->updateSurface(destLevel, xoffset, yoffset, width, height); - - destLevel->Release(); image->markClean(); } } @@ -1904,7 +476,7 @@ void Texture2D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei wi void Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels) { - if (Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, &mImageArray[level])) + if (Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, mImageArray[level])) { commitRect(level, xoffset, yoffset, width, height); } @@ -1912,7 +484,7 @@ void Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei widt void Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels) { - if (Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, &mImageArray[level])) + if (Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, mImageArray[level])) { commitRect(level, xoffset, yoffset, width, height); } @@ -1920,20 +492,12 @@ void Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GL void Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) { - IDirect3DSurface9 *renderTarget = source->getRenderTarget(); - - if (!renderTarget) - { - ERR("Failed to retrieve the render target."); - return error(GL_OUT_OF_MEMORY); - } - GLint internalformat = ConvertSizedInternalFormat(format, GL_UNSIGNED_BYTE); redefineImage(level, internalformat, width, height); - - if (!mImageArray[level].isRenderableFormat()) + + if (!mImageArray[level]->isRenderableFormat()) { - mImageArray[level].copy(0, 0, x, y, width, height, renderTarget); + mImageArray[level]->copy(0, 0, x, y, width, height, source); mDirtyImages = true; } else @@ -1943,47 +507,31 @@ void Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei convertToRenderTarget(); } - mImageArray[level].markClean(); + mImageArray[level]->markClean(); if (width != 0 && height != 0 && level < levelCount()) { - RECT sourceRect; - sourceRect.left = x; - sourceRect.right = x + width; - sourceRect.top = y; - sourceRect.bottom = y + height; - - IDirect3DSurface9 *dest = mTexStorage->getSurfaceLevel(level, true); + gl::Rectangle sourceRect; + sourceRect.x = x; + sourceRect.width = width; + sourceRect.y = y; + sourceRect.height = height; - if (dest) - { - getBlitter()->copy(renderTarget, sourceRect, format, 0, 0, dest); - dest->Release(); - } + mRenderer->copyImage(source, sourceRect, format, 0, 0, mTexStorage, level); } } - - renderTarget->Release(); } void Texture2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) { - if (xoffset + width > mImageArray[level].getWidth() || yoffset + height > mImageArray[level].getHeight()) + if (xoffset + width > mImageArray[level]->getWidth() || yoffset + height > mImageArray[level]->getHeight()) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } - IDirect3DSurface9 *renderTarget = source->getRenderTarget(); - - if (!renderTarget) + if (!mImageArray[level]->isRenderableFormat() || (!mTexStorage && !isSamplerComplete())) { - ERR("Failed to retrieve the render target."); - return error(GL_OUT_OF_MEMORY); - } - - if (!mImageArray[level].isRenderableFormat() || (!mTexStorage && !isSamplerComplete())) - { - mImageArray[level].copy(xoffset, yoffset, x, y, width, height, renderTarget); + mImageArray[level]->copy(xoffset, yoffset, x, y, width, height, source); mDirtyImages = true; } else @@ -1997,46 +545,35 @@ void Texture2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yo if (level < levelCount()) { - RECT sourceRect; - sourceRect.left = x; - sourceRect.right = x + width; - sourceRect.top = y; - sourceRect.bottom = y + height; + gl::Rectangle sourceRect; + sourceRect.x = x; + sourceRect.width = width; + sourceRect.y = y; + sourceRect.height = height; - IDirect3DSurface9 *dest = mTexStorage->getSurfaceLevel(level, true); - - if (dest) - { - getBlitter()->copy(renderTarget, sourceRect, - gl::ExtractFormat(mImageArray[0].getInternalFormat()), - xoffset, yoffset, dest); - dest->Release(); - } + mRenderer->copyImage(source, sourceRect, + gl::ExtractFormat(mImageArray[0]->getInternalFormat()), + xoffset, yoffset, mTexStorage, level); } } - - renderTarget->Release(); } void Texture2D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) { - D3DFORMAT d3dfmt = ConvertTextureInternalFormat(internalformat); - DWORD d3dusage = GetTextureUsage(d3dfmt, mUsage, false); - delete mTexStorage; - mTexStorage = new TextureStorage2D(levels, d3dfmt, d3dusage, width, height); + mTexStorage = new rx::TextureStorageInterface2D(mRenderer, levels, internalformat, mUsage, false, width, height); mImmutable = true; for (int level = 0; level < levels; level++) { - mImageArray[level].redefine(internalformat, width, height, true); + mImageArray[level]->redefine(mRenderer, internalformat, width, height, true); width = std::max(1, width >> 1); height = std::max(1, height >> 1); } for (int level = levels; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) { - mImageArray[level].redefine(GL_NONE, 0, 0, true); + mImageArray[level]->redefine(mRenderer, GL_NONE, 0, 0, true); } if (mTexStorage->isManaged()) @@ -2045,8 +582,7 @@ void Texture2D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GL for (int level = 0; level < levels; level++) { - IDirect3DSurface9 *surface = mTexStorage->getSurfaceLevel(level, false); - mImageArray[level].setManagedSurface(surface); + mImageArray[level]->setManagedSurface(mTexStorage, level); } } } @@ -2054,8 +590,8 @@ void Texture2D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GL // Tests for 2D texture sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 85. bool Texture2D::isSamplerComplete() const { - GLsizei width = mImageArray[0].getWidth(); - GLsizei height = mImageArray[0].getHeight(); + GLsizei width = mImageArray[0]->getWidth(); + GLsizei height = mImageArray[0]->getHeight(); if (width <= 0 || height <= 0) { @@ -2063,22 +599,24 @@ bool Texture2D::isSamplerComplete() const } bool mipmapping = isMipmapFiltered(); + bool filtering, renderable; - if ((IsFloat32Format(getInternalFormat(0)) && !getContext()->supportsFloat32LinearFilter()) || - (IsFloat16Format(getInternalFormat(0)) && !getContext()->supportsFloat16LinearFilter())) + if ((IsFloat32Format(getInternalFormat(0)) && !mRenderer->getFloat32TextureSupport(&filtering, &renderable)) || + (IsFloat16Format(getInternalFormat(0)) && !mRenderer->getFloat16TextureSupport(&filtering, &renderable))) { - if (mMagFilter != GL_NEAREST || (mMinFilter != GL_NEAREST && mMinFilter != GL_NEAREST_MIPMAP_NEAREST)) + if (mSamplerState.magFilter != GL_NEAREST || + (mSamplerState.minFilter != GL_NEAREST && mSamplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST)) { return false; } } - bool npotSupport = getContext()->supportsNonPower2Texture(); + bool npotSupport = mRenderer->getNonPower2TextureSupport(); if (!npotSupport) { - if ((getWrapS() != GL_CLAMP_TO_EDGE && !isPow2(width)) || - (getWrapT() != GL_CLAMP_TO_EDGE && !isPow2(height))) + if ((mSamplerState.wrapS != GL_CLAMP_TO_EDGE && !isPow2(width)) || + (mSamplerState.wrapT != GL_CLAMP_TO_EDGE && !isPow2(height))) { return false; } @@ -2111,8 +649,8 @@ bool Texture2D::isMipmapComplete() const return true; } - GLsizei width = mImageArray[0].getWidth(); - GLsizei height = mImageArray[0].getHeight(); + GLsizei width = mImageArray[0]->getWidth(); + GLsizei height = mImageArray[0]->getHeight(); if (width <= 0 || height <= 0) { @@ -2123,17 +661,17 @@ bool Texture2D::isMipmapComplete() const for (int level = 1; level <= q; level++) { - if (mImageArray[level].getInternalFormat() != mImageArray[0].getInternalFormat()) + if (mImageArray[level]->getInternalFormat() != mImageArray[0]->getInternalFormat()) { return false; } - if (mImageArray[level].getWidth() != std::max(1, width >> level)) + if (mImageArray[level]->getWidth() != std::max(1, width >> level)) { return false; } - if (mImageArray[level].getHeight() != std::max(1, height >> level)) + if (mImageArray[level]->getHeight() != std::max(1, height >> level)) { return false; } @@ -2152,26 +690,20 @@ bool Texture2D::isDepth(GLint level) const return IsDepthTexture(getInternalFormat(level)); } -IDirect3DBaseTexture9 *Texture2D::getBaseTexture() const -{ - return mTexStorage ? mTexStorage->getBaseTexture() : NULL; -} - -// Constructs a Direct3D 9 texture resource from the texture images +// Constructs a native texture resource from the texture images void Texture2D::createTexture() { - GLsizei width = mImageArray[0].getWidth(); - GLsizei height = mImageArray[0].getHeight(); + GLsizei width = mImageArray[0]->getWidth(); + GLsizei height = mImageArray[0]->getHeight(); if (!(width > 0 && height > 0)) - return; // do not attempt to create d3d textures for nonexistant data + return; // do not attempt to create native textures for nonexistant data GLint levels = creationLevels(width, height); - D3DFORMAT d3dfmt = mImageArray[0].getD3DFormat(); - DWORD d3dusage = GetTextureUsage(d3dfmt, mUsage, false); + GLenum internalformat = mImageArray[0]->getInternalFormat(); delete mTexStorage; - mTexStorage = new TextureStorage2D(levels, d3dfmt, d3dusage, width, height); + mTexStorage = new rx::TextureStorageInterface2D(mRenderer, levels, internalformat, mUsage, false, width, height); if (mTexStorage->isManaged()) { @@ -2179,8 +711,7 @@ void Texture2D::createTexture() for (int level = 0; level < levels; level++) { - IDirect3DSurface9 *surface = mTexStorage->getSurfaceLevel(level, false); - mImageArray[level].setManagedSurface(surface); + mImageArray[level]->setManagedSurface(mTexStorage, level); } } @@ -2195,47 +726,34 @@ void Texture2D::updateTexture() for (int level = 0; level < levels; level++) { - Image *image = &mImageArray[level]; + rx::Image *image = mImageArray[level]; if (image->isDirty()) { - commitRect(level, 0, 0, mImageArray[level].getWidth(), mImageArray[level].getHeight()); + commitRect(level, 0, 0, mImageArray[level]->getWidth(), mImageArray[level]->getHeight()); } } } void Texture2D::convertToRenderTarget() { - TextureStorage2D *newTexStorage = NULL; + rx::TextureStorageInterface2D *newTexStorage = NULL; - if (mImageArray[0].getWidth() != 0 && mImageArray[0].getHeight() != 0) + if (mImageArray[0]->getWidth() != 0 && mImageArray[0]->getHeight() != 0) { - GLsizei width = mImageArray[0].getWidth(); - GLsizei height = mImageArray[0].getHeight(); - GLint levels = creationLevels(width, height); - D3DFORMAT d3dfmt = mImageArray[0].getD3DFormat(); - DWORD d3dusage = GetTextureUsage(d3dfmt, GL_FRAMEBUFFER_ATTACHMENT_ANGLE, true); + GLsizei width = mImageArray[0]->getWidth(); + GLsizei height = mImageArray[0]->getHeight(); + GLint levels = mTexStorage != NULL ? mTexStorage->levelCount() : creationLevels(width, height); + GLenum internalformat = mImageArray[0]->getInternalFormat(); - newTexStorage = new TextureStorage2D(levels, d3dfmt, d3dusage, width, height); + newTexStorage = new rx::TextureStorageInterface2D(mRenderer, levels, internalformat, GL_FRAMEBUFFER_ATTACHMENT_ANGLE, true, width, height); if (mTexStorage != NULL) { - int levels = levelCount(); - for (int i = 0; i < levels; i++) - { - IDirect3DSurface9 *source = mTexStorage->getSurfaceLevel(i, false); - IDirect3DSurface9 *dest = newTexStorage->getSurfaceLevel(i, true); - - if (!copyToRenderTarget(dest, source, mTexStorage->isManaged())) - { - delete newTexStorage; - if (source) source->Release(); - if (dest) dest->Release(); - return error(GL_OUT_OF_MEMORY); - } - - if (source) source->Release(); - if (dest) dest->Release(); + if (!mRenderer->copyToRenderTarget(newTexStorage, mTexStorage)) + { + delete newTexStorage; + return gl::error(GL_OUT_OF_MEMORY); } } } @@ -2248,53 +766,37 @@ void Texture2D::convertToRenderTarget() void Texture2D::generateMipmaps() { - if (!getContext()->supportsNonPower2Texture()) + if (!mRenderer->getNonPower2TextureSupport()) { - if (!isPow2(mImageArray[0].getWidth()) || !isPow2(mImageArray[0].getHeight())) + if (!isPow2(mImageArray[0]->getWidth()) || !isPow2(mImageArray[0]->getHeight())) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } // Purge array levels 1 through q and reset them to represent the generated mipmap levels. - unsigned int q = log2(std::max(mImageArray[0].getWidth(), mImageArray[0].getHeight())); + unsigned int q = log2(std::max(mImageArray[0]->getWidth(), mImageArray[0]->getHeight())); for (unsigned int i = 1; i <= q; i++) { - redefineImage(i, mImageArray[0].getInternalFormat(), - std::max(mImageArray[0].getWidth() >> i, 1), - std::max(mImageArray[0].getHeight() >> i, 1)); + redefineImage(i, mImageArray[0]->getInternalFormat(), + std::max(mImageArray[0]->getWidth() >> i, 1), + std::max(mImageArray[0]->getHeight() >> i, 1)); } if (mTexStorage && mTexStorage->isRenderTarget()) { for (unsigned int i = 1; i <= q; i++) { - IDirect3DSurface9 *upper = mTexStorage->getSurfaceLevel(i - 1, false); - IDirect3DSurface9 *lower = mTexStorage->getSurfaceLevel(i, true); + mTexStorage->generateMipmap(i); - if (upper != NULL && lower != NULL) - { - getBlitter()->boxFilter(upper, lower); - } - - if (upper != NULL) upper->Release(); - if (lower != NULL) lower->Release(); - - mImageArray[i].markClean(); + mImageArray[i]->markClean(); } } else { for (unsigned int i = 1; i <= q; i++) { - if (mImageArray[i].getSurface() == NULL) - { - return error(GL_OUT_OF_MEMORY); - } - - GenerateMip(mImageArray[i].getSurface(), mImageArray[i - 1].getSurface()); - - mImageArray[i].markDirty(); + mRenderer->generateMipmap(mImageArray[i], mImageArray[i - 1]); } } } @@ -2303,20 +805,18 @@ Renderbuffer *Texture2D::getRenderbuffer(GLenum target) { if (target != GL_TEXTURE_2D) { - return error(GL_INVALID_OPERATION, (Renderbuffer *)NULL); + return gl::error(GL_INVALID_OPERATION, (Renderbuffer *)NULL); } if (mColorbufferProxy == NULL) { - mColorbufferProxy = new Renderbuffer(id(), new RenderbufferTexture2D(this, target)); + mColorbufferProxy = new Renderbuffer(mRenderer, id(), new RenderbufferTexture2D(this, target)); } return mColorbufferProxy; } -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *Texture2D::getRenderTarget(GLenum target) +rx::RenderTarget *Texture2D::getRenderTarget(GLenum target) { ASSERT(target == GL_TEXTURE_2D); @@ -2333,12 +833,11 @@ IDirect3DSurface9 *Texture2D::getRenderTarget(GLenum target) { return NULL; } - return mTexStorage->getSurfaceLevel(0, false); + + return mTexStorage->getRenderTarget(); } -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *Texture2D::getDepthStencil(GLenum target) +rx::RenderTarget *Texture2D::getDepthStencil(GLenum target) { ASSERT(target == GL_TEXTURE_2D); @@ -2355,10 +854,15 @@ IDirect3DSurface9 *Texture2D::getDepthStencil(GLenum target) { return NULL; } - return mTexStorage->getSurfaceLevel(0, false); + return mTexStorage->getRenderTarget(); } -TextureStorage *Texture2D::getStorage(bool renderTarget) +int Texture2D::levelCount() +{ + return mTexStorage ? mTexStorage->levelCount() : 0; +} + +rx::TextureStorageInterface *Texture2D::getStorage(bool renderTarget) { if (!mTexStorage || (renderTarget && !mTexStorage->isRenderTarget())) { @@ -2375,74 +879,18 @@ TextureStorage *Texture2D::getStorage(bool renderTarget) return mTexStorage; } -TextureStorageCubeMap::TextureStorageCubeMap(int levels, D3DFORMAT format, DWORD usage, int size) - : TextureStorage(usage), mFirstRenderTargetSerial(RenderbufferStorage::issueCubeSerials()) -{ - mTexture = NULL; - // if the size is not positive this should be treated as an incomplete texture - // we handle that here by skipping the d3d texture creation - if (size > 0) - { - IDirect3DDevice9 *device = getDevice(); - int height = size; - MakeValidSize(false, dx::IsCompressedFormat(format), &size, &height, &mLodOffset); - HRESULT result = device->CreateCubeTexture(size, levels ? levels + mLodOffset : 0, getUsage(), format, getPool(), &mTexture, NULL); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - error(GL_OUT_OF_MEMORY); - } - } -} - -TextureStorageCubeMap::~TextureStorageCubeMap() -{ - if (mTexture) - { - mTexture->Release(); - } -} - -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *TextureStorageCubeMap::getCubeMapSurface(GLenum faceTarget, int level, bool dirty) -{ - IDirect3DSurface9 *surface = NULL; - - if (mTexture) - { - D3DCUBEMAP_FACES face = es2dx::ConvertCubeFace(faceTarget); - HRESULT result = mTexture->GetCubeMapSurface(face, level + mLodOffset, &surface); - ASSERT(SUCCEEDED(result)); - - // With managed textures the driver needs to be informed of updates to the lower mipmap levels - if (level != 0 && isManaged() && dirty) - { - mTexture->AddDirtyRect(face, NULL); - } - } - - return surface; -} - -IDirect3DBaseTexture9 *TextureStorageCubeMap::getBaseTexture() const -{ - return mTexture; -} - -unsigned int TextureStorageCubeMap::getRenderTargetSerial(GLenum target) const -{ - return mFirstRenderTargetSerial + TextureCubeMap::faceIndex(target); -} - -TextureCubeMap::TextureCubeMap(GLuint id) : Texture(id) +TextureCubeMap::TextureCubeMap(rx::Renderer *renderer, GLuint id) : Texture(renderer, id) { mTexStorage = NULL; for (int i = 0; i < 6; i++) { mFaceProxies[i] = NULL; mFaceProxyRefs[i] = 0; + + for (int j = 0; j < IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++j) + { + mImageArray[i][j] = renderer->createImage(); + } } } @@ -2451,6 +899,11 @@ TextureCubeMap::~TextureCubeMap() for (int i = 0; i < 6; i++) { mFaceProxies[i] = NULL; + + for (int j = 0; j < IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++j) + { + delete mImageArray[i][j]; + } } delete mTexStorage; @@ -2494,7 +947,7 @@ GLenum TextureCubeMap::getTarget() const GLsizei TextureCubeMap::getWidth(GLenum target, GLint level) const { if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mImageArray[faceIndex(target)][level].getWidth(); + return mImageArray[faceIndex(target)][level]->getWidth(); else return 0; } @@ -2502,7 +955,7 @@ GLsizei TextureCubeMap::getWidth(GLenum target, GLint level) const GLsizei TextureCubeMap::getHeight(GLenum target, GLint level) const { if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mImageArray[faceIndex(target)][level].getHeight(); + return mImageArray[faceIndex(target)][level]->getHeight(); else return 0; } @@ -2510,15 +963,15 @@ GLsizei TextureCubeMap::getHeight(GLenum target, GLint level) const GLenum TextureCubeMap::getInternalFormat(GLenum target, GLint level) const { if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mImageArray[faceIndex(target)][level].getInternalFormat(); + return mImageArray[faceIndex(target)][level]->getInternalFormat(); else return GL_NONE; } -D3DFORMAT TextureCubeMap::getD3DFormat(GLenum target, GLint level) const +GLenum TextureCubeMap::getActualFormat(GLenum target, GLint level) const { if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mImageArray[faceIndex(target)][level].getD3DFormat(); + return mImageArray[faceIndex(target)][level]->getActualFormat(); else return D3DFMT_UNKNOWN; } @@ -2558,32 +1011,22 @@ void TextureCubeMap::setCompressedImage(GLenum face, GLint level, GLenum format, // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly redefineImage(faceIndex(face), level, format, width, height); - Texture::setCompressedImage(imageSize, pixels, &mImageArray[faceIndex(face)][level]); + Texture::setCompressedImage(imageSize, pixels, mImageArray[faceIndex(face)][level]); } void TextureCubeMap::commitRect(int face, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) { - ASSERT(mImageArray[face][level].getSurface() != NULL); - if (level < levelCount()) { - IDirect3DSurface9 *destLevel = mTexStorage->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, true); - ASSERT(destLevel != NULL); - - if (destLevel != NULL) - { - Image *image = &mImageArray[face][level]; - image->updateSurface(destLevel, xoffset, yoffset, width, height); - - destLevel->Release(); + rx::Image *image = mImageArray[face][level]; + if (image->updateSurface(mTexStorage, face, level, xoffset, yoffset, width, height)) image->markClean(); - } } } void TextureCubeMap::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels) { - if (Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, &mImageArray[faceIndex(target)][level])) + if (Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, mImageArray[faceIndex(target)][level])) { commitRect(faceIndex(target), level, xoffset, yoffset, width, height); } @@ -2591,7 +1034,7 @@ void TextureCubeMap::subImage(GLenum target, GLint level, GLint xoffset, GLint y void TextureCubeMap::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels) { - if (Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, &mImageArray[faceIndex(target)][level])) + if (Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, mImageArray[faceIndex(target)][level])) { commitRect(faceIndex(target), level, xoffset, yoffset, width, height); } @@ -2600,22 +1043,24 @@ void TextureCubeMap::subImageCompressed(GLenum target, GLint level, GLint xoffse // Tests for cube map sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 86. bool TextureCubeMap::isSamplerComplete() const { - int size = mImageArray[0][0].getWidth(); + int size = mImageArray[0][0]->getWidth(); bool mipmapping = isMipmapFiltered(); + bool filtering, renderable; - if ((gl::ExtractType(getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0)) == GL_FLOAT && !getContext()->supportsFloat32LinearFilter()) || - (gl::ExtractType(getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0) == GL_HALF_FLOAT_OES) && !getContext()->supportsFloat16LinearFilter())) + if ((gl::ExtractType(getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0)) == GL_FLOAT && !mRenderer->getFloat32TextureSupport(&filtering, &renderable)) || + (gl::ExtractType(getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0) == GL_HALF_FLOAT_OES) && !mRenderer->getFloat16TextureSupport(&filtering, &renderable))) { - if (mMagFilter != GL_NEAREST || (mMinFilter != GL_NEAREST && mMinFilter != GL_NEAREST_MIPMAP_NEAREST)) + if (mSamplerState.magFilter != GL_NEAREST || + (mSamplerState.minFilter != GL_NEAREST && mSamplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST)) { return false; } } - if (!isPow2(size) && !getContext()->supportsNonPower2Texture()) + if (!isPow2(size) && !mRenderer->getNonPower2TextureSupport()) { - if (getWrapS() != GL_CLAMP_TO_EDGE || getWrapT() != GL_CLAMP_TO_EDGE || mipmapping) + if (mSamplerState.wrapS != GL_CLAMP_TO_EDGE || mSamplerState.wrapT != GL_CLAMP_TO_EDGE || mipmapping) { return false; } @@ -2642,16 +1087,16 @@ bool TextureCubeMap::isSamplerComplete() const // Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81. bool TextureCubeMap::isCubeComplete() const { - if (mImageArray[0][0].getWidth() <= 0 || mImageArray[0][0].getHeight() != mImageArray[0][0].getWidth()) + if (mImageArray[0][0]->getWidth() <= 0 || mImageArray[0][0]->getHeight() != mImageArray[0][0]->getWidth()) { return false; } for (unsigned int face = 1; face < 6; face++) { - if (mImageArray[face][0].getWidth() != mImageArray[0][0].getWidth() || - mImageArray[face][0].getWidth() != mImageArray[0][0].getHeight() || - mImageArray[face][0].getInternalFormat() != mImageArray[0][0].getInternalFormat()) + if (mImageArray[face][0]->getWidth() != mImageArray[0][0]->getWidth() || + mImageArray[face][0]->getWidth() != mImageArray[0][0]->getHeight() || + mImageArray[face][0]->getInternalFormat() != mImageArray[0][0]->getInternalFormat()) { return false; } @@ -2672,7 +1117,7 @@ bool TextureCubeMap::isMipmapCubeComplete() const return false; } - GLsizei size = mImageArray[0][0].getWidth(); + GLsizei size = mImageArray[0][0]->getWidth(); int q = log2(size); @@ -2680,12 +1125,12 @@ bool TextureCubeMap::isMipmapCubeComplete() const { for (int level = 1; level <= q; level++) { - if (mImageArray[face][level].getInternalFormat() != mImageArray[0][0].getInternalFormat()) + if (mImageArray[face][level]->getInternalFormat() != mImageArray[0][0]->getInternalFormat()) { return false; } - if (mImageArray[face][level].getWidth() != std::max(1, size >> level)) + if (mImageArray[face][level]->getWidth() != std::max(1, size >> level)) { return false; } @@ -2700,25 +1145,19 @@ bool TextureCubeMap::isCompressed(GLenum target, GLint level) const return IsCompressed(getInternalFormat(target, level)); } -IDirect3DBaseTexture9 *TextureCubeMap::getBaseTexture() const -{ - return mTexStorage ? mTexStorage->getBaseTexture() : NULL; -} - -// Constructs a Direct3D 9 texture resource from the texture images, or returns an existing one +// Constructs a native texture resource from the texture images, or returns an existing one void TextureCubeMap::createTexture() { - GLsizei size = mImageArray[0][0].getWidth(); + GLsizei size = mImageArray[0][0]->getWidth(); if (!(size > 0)) - return; // do not attempt to create d3d textures for nonexistant data + return; // do not attempt to create native textures for nonexistant data GLint levels = creationLevels(size); - D3DFORMAT d3dfmt = mImageArray[0][0].getD3DFormat(); - DWORD d3dusage = GetTextureUsage(d3dfmt, mUsage, false); + GLenum internalformat = mImageArray[0][0]->getInternalFormat(); delete mTexStorage; - mTexStorage = new TextureStorageCubeMap(levels, d3dfmt, d3dusage, size); + mTexStorage = new rx::TextureStorageInterfaceCube(mRenderer, levels, internalformat, mUsage, false, size); if (mTexStorage->isManaged()) { @@ -2728,8 +1167,7 @@ void TextureCubeMap::createTexture() { for (int level = 0; level < levels; level++) { - IDirect3DSurface9 *surface = mTexStorage->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, false); - mImageArray[face][level].setManagedSurface(surface); + mImageArray[face][level]->setManagedSurface(mTexStorage, face, level); } } } @@ -2747,7 +1185,7 @@ void TextureCubeMap::updateTexture() for (int level = 0; level < levels; level++) { - Image *image = &mImageArray[face][level]; + rx::Image *image = mImageArray[face][level]; if (image->isDirty()) { @@ -2759,38 +1197,22 @@ void TextureCubeMap::updateTexture() void TextureCubeMap::convertToRenderTarget() { - TextureStorageCubeMap *newTexStorage = NULL; + rx::TextureStorageInterfaceCube *newTexStorage = NULL; - if (mImageArray[0][0].getWidth() != 0) + if (mImageArray[0][0]->getWidth() != 0) { - GLsizei size = mImageArray[0][0].getWidth(); - GLint levels = creationLevels(size); - D3DFORMAT d3dfmt = mImageArray[0][0].getD3DFormat(); - DWORD d3dusage = GetTextureUsage(d3dfmt, GL_FRAMEBUFFER_ATTACHMENT_ANGLE, true); + GLsizei size = mImageArray[0][0]->getWidth(); + GLint levels = mTexStorage != NULL ? mTexStorage->levelCount() : creationLevels(size); + GLenum internalformat = mImageArray[0][0]->getInternalFormat(); - newTexStorage = new TextureStorageCubeMap(levels, d3dfmt, d3dusage, size); + newTexStorage = new rx::TextureStorageInterfaceCube(mRenderer, levels, internalformat, GL_FRAMEBUFFER_ATTACHMENT_ANGLE, true, size); if (mTexStorage != NULL) { - int levels = levelCount(); - for (int f = 0; f < 6; f++) + if (!mRenderer->copyToRenderTarget(newTexStorage, mTexStorage)) { - for (int i = 0; i < levels; i++) - { - IDirect3DSurface9 *source = mTexStorage->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, false); - IDirect3DSurface9 *dest = newTexStorage->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, true); - - if (!copyToRenderTarget(dest, source, mTexStorage->isManaged())) - { - delete newTexStorage; - if (source) source->Release(); - if (dest) dest->Release(); - return error(GL_OUT_OF_MEMORY); - } - - if (source) source->Release(); - if (dest) dest->Release(); - } + delete newTexStorage; + return gl::error(GL_OUT_OF_MEMORY); } } } @@ -2806,7 +1228,7 @@ void TextureCubeMap::setImage(int faceIndex, GLint level, GLsizei width, GLsizei GLint internalformat = ConvertSizedInternalFormat(format, type); redefineImage(faceIndex, level, internalformat, width, height); - Texture::setImage(unpackAlignment, pixels, &mImageArray[faceIndex][level]); + Texture::setImage(unpackAlignment, pixels, mImageArray[faceIndex][level]); } unsigned int TextureCubeMap::faceIndex(GLenum face) @@ -2822,42 +1244,47 @@ unsigned int TextureCubeMap::faceIndex(GLenum face) void TextureCubeMap::redefineImage(int face, GLint level, GLint internalformat, GLsizei width, GLsizei height) { - bool redefined = mImageArray[face][level].redefine(internalformat, width, height, false); + // If there currently is a corresponding storage texture image, it has these parameters + const int storageWidth = std::max(1, mImageArray[0][0]->getWidth() >> level); + const int storageHeight = std::max(1, mImageArray[0][0]->getHeight() >> level); + const int storageFormat = mImageArray[0][0]->getInternalFormat(); - if (mTexStorage && redefined) + mImageArray[face][level]->redefine(mRenderer, internalformat, width, height, false); + + if (mTexStorage) { - for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + const int storageLevels = mTexStorage->levelCount(); + + if ((level >= storageLevels && storageLevels != 0) || + width != storageWidth || + height != storageHeight || + internalformat != storageFormat) // Discard mismatched storage { - for (int f = 0; f < 6; f++) + for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) { - mImageArray[f][i].markDirty(); + for (int f = 0; f < 6; f++) + { + mImageArray[f][i]->markDirty(); + } } + + delete mTexStorage; + mTexStorage = NULL; + + mDirtyImages = true; } - - delete mTexStorage; - mTexStorage = NULL; - - mDirtyImages = true; } } void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) { - IDirect3DSurface9 *renderTarget = source->getRenderTarget(); - - if (!renderTarget) - { - ERR("Failed to retrieve the render target."); - return error(GL_OUT_OF_MEMORY); - } - unsigned int faceindex = faceIndex(target); GLint internalformat = gl::ConvertSizedInternalFormat(format, GL_UNSIGNED_BYTE); redefineImage(faceindex, level, internalformat, width, height); - if (!mImageArray[faceindex][level].isRenderableFormat()) + if (!mImageArray[faceindex][level]->isRenderableFormat()) { - mImageArray[faceindex][level].copy(0, 0, x, y, width, height, renderTarget); + mImageArray[faceindex][level]->copy(0, 0, x, y, width, height, source); mDirtyImages = true; } else @@ -2867,53 +1294,37 @@ void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint convertToRenderTarget(); } - mImageArray[faceindex][level].markClean(); + mImageArray[faceindex][level]->markClean(); ASSERT(width == height); if (width > 0 && level < levelCount()) { - RECT sourceRect; - sourceRect.left = x; - sourceRect.right = x + width; - sourceRect.top = y; - sourceRect.bottom = y + height; + gl::Rectangle sourceRect; + sourceRect.x = x; + sourceRect.width = width; + sourceRect.y = y; + sourceRect.height = height; - IDirect3DSurface9 *dest = mTexStorage->getCubeMapSurface(target, level, true); - - if (dest) - { - getBlitter()->copy(renderTarget, sourceRect, format, 0, 0, dest); - dest->Release(); - } + mRenderer->copyImage(source, sourceRect, format, 0, 0, mTexStorage, target, level); } } - - renderTarget->Release(); } void TextureCubeMap::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) { - GLsizei size = mImageArray[faceIndex(target)][level].getWidth(); + GLsizei size = mImageArray[faceIndex(target)][level]->getWidth(); if (xoffset + width > size || yoffset + height > size) { - return error(GL_INVALID_VALUE); - } - - IDirect3DSurface9 *renderTarget = source->getRenderTarget(); - - if (!renderTarget) - { - ERR("Failed to retrieve the render target."); - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_INVALID_VALUE); } unsigned int faceindex = faceIndex(target); - if (!mImageArray[faceindex][level].isRenderableFormat() || (!mTexStorage && !isSamplerComplete())) + if (!mImageArray[faceindex][level]->isRenderableFormat() || (!mTexStorage && !isSamplerComplete())) { - mImageArray[faceindex][level].copy(0, 0, x, y, width, height, renderTarget); + mImageArray[faceindex][level]->copy(0, 0, x, y, width, height, source); mDirtyImages = true; } else @@ -2927,39 +1338,29 @@ void TextureCubeMap::copySubImage(GLenum target, GLint level, GLint xoffset, GLi if (level < levelCount()) { - RECT sourceRect; - sourceRect.left = x; - sourceRect.right = x + width; - sourceRect.top = y; - sourceRect.bottom = y + height; + gl::Rectangle sourceRect; + sourceRect.x = x; + sourceRect.width = width; + sourceRect.y = y; + sourceRect.height = height; - IDirect3DSurface9 *dest = mTexStorage->getCubeMapSurface(target, level, true); - - if (dest) - { - getBlitter()->copy(renderTarget, sourceRect, gl::ExtractFormat(mImageArray[0][0].getInternalFormat()), xoffset, yoffset, dest); - dest->Release(); - } + mRenderer->copyImage(source, sourceRect, gl::ExtractFormat(mImageArray[0][0]->getInternalFormat()), + xoffset, yoffset, mTexStorage, target, level); } } - - renderTarget->Release(); } void TextureCubeMap::storage(GLsizei levels, GLenum internalformat, GLsizei size) { - D3DFORMAT d3dfmt = ConvertTextureInternalFormat(internalformat); - DWORD d3dusage = GetTextureUsage(d3dfmt, mUsage, false); - delete mTexStorage; - mTexStorage = new TextureStorageCubeMap(levels, d3dfmt, d3dusage, size); + mTexStorage = new rx::TextureStorageInterfaceCube(mRenderer, levels, internalformat, mUsage, false, size); mImmutable = true; for (int level = 0; level < levels; level++) { for (int face = 0; face < 6; face++) { - mImageArray[face][level].redefine(internalformat, size, size, true); + mImageArray[face][level]->redefine(mRenderer, internalformat, size, size, true); size = std::max(1, size >> 1); } } @@ -2968,7 +1369,7 @@ void TextureCubeMap::storage(GLsizei levels, GLenum internalformat, GLsizei size { for (int face = 0; face < 6; face++) { - mImageArray[face][level].redefine(GL_NONE, 0, 0, true); + mImageArray[face][level]->redefine(mRenderer, GL_NONE, 0, 0, true); } } @@ -2980,8 +1381,7 @@ void TextureCubeMap::storage(GLsizei levels, GLenum internalformat, GLsizei size { for (int level = 0; level < levels; level++) { - IDirect3DSurface9 *surface = mTexStorage->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, false); - mImageArray[face][level].setManagedSurface(surface); + mImageArray[face][level]->setManagedSurface(mTexStorage, face, level); } } } @@ -2991,26 +1391,26 @@ void TextureCubeMap::generateMipmaps() { if (!isCubeComplete()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } - if (!getContext()->supportsNonPower2Texture()) + if (!mRenderer->getNonPower2TextureSupport()) { - if (!isPow2(mImageArray[0][0].getWidth())) + if (!isPow2(mImageArray[0][0]->getWidth())) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } // Purge array levels 1 through q and reset them to represent the generated mipmap levels. - unsigned int q = log2(mImageArray[0][0].getWidth()); + unsigned int q = log2(mImageArray[0][0]->getWidth()); for (unsigned int f = 0; f < 6; f++) { for (unsigned int i = 1; i <= q; i++) { - redefineImage(f, i, mImageArray[f][0].getInternalFormat(), - std::max(mImageArray[f][0].getWidth() >> i, 1), - std::max(mImageArray[f][0].getWidth() >> i, 1)); + redefineImage(f, i, mImageArray[f][0]->getInternalFormat(), + std::max(mImageArray[f][0]->getWidth() >> i, 1), + std::max(mImageArray[f][0]->getWidth() >> i, 1)); } } @@ -3020,18 +1420,9 @@ void TextureCubeMap::generateMipmaps() { for (unsigned int i = 1; i <= q; i++) { - IDirect3DSurface9 *upper = mTexStorage->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i - 1, false); - IDirect3DSurface9 *lower = mTexStorage->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, true); + mTexStorage->generateMipmap(f, i); - if (upper != NULL && lower != NULL) - { - getBlitter()->boxFilter(upper, lower); - } - - if (upper != NULL) upper->Release(); - if (lower != NULL) lower->Release(); - - mImageArray[f][i].markClean(); + mImageArray[f][i]->markClean(); } } } @@ -3041,14 +1432,7 @@ void TextureCubeMap::generateMipmaps() { for (unsigned int i = 1; i <= q; i++) { - if (mImageArray[f][i].getSurface() == NULL) - { - return error(GL_OUT_OF_MEMORY); - } - - GenerateMip(mImageArray[f][i].getSurface(), mImageArray[f][i - 1].getSurface()); - - mImageArray[f][i].markDirty(); + mRenderer->generateMipmap(mImageArray[f][i], mImageArray[f][i - 1]); } } } @@ -3058,22 +1442,20 @@ Renderbuffer *TextureCubeMap::getRenderbuffer(GLenum target) { if (!IsCubemapTextureTarget(target)) { - return error(GL_INVALID_OPERATION, (Renderbuffer *)NULL); + return gl::error(GL_INVALID_OPERATION, (Renderbuffer *)NULL); } unsigned int face = faceIndex(target); if (mFaceProxies[face] == NULL) { - mFaceProxies[face] = new Renderbuffer(id(), new RenderbufferTextureCubeMap(this, target)); + mFaceProxies[face] = new Renderbuffer(mRenderer, id(), new RenderbufferTextureCubeMap(this, target)); } return mFaceProxies[face]; } -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *TextureCubeMap::getRenderTarget(GLenum target) +rx::RenderTarget *TextureCubeMap::getRenderTarget(GLenum target) { ASSERT(IsCubemapTextureTarget(target)); @@ -3085,10 +1467,15 @@ IDirect3DSurface9 *TextureCubeMap::getRenderTarget(GLenum target) updateTexture(); - return mTexStorage->getCubeMapSurface(target, 0, false); + return mTexStorage->getRenderTarget(target); } -TextureStorage *TextureCubeMap::getStorage(bool renderTarget) +int TextureCubeMap::levelCount() +{ + return mTexStorage ? mTexStorage->levelCount() - getLodOffset() : 0; +} + +rx::TextureStorageInterface *TextureCubeMap::getStorage(bool renderTarget) { if (!mTexStorage || (renderTarget && !mTexStorage->isRenderTarget())) { diff --git a/gfx/angle/src/libGLESv2/Texture.h b/gfx/angle/src/libGLESv2/Texture.h index deb2d050a5a9..4f5fab28d01d 100644 --- a/gfx/angle/src/libGLESv2/Texture.h +++ b/gfx/angle/src/libGLESv2/Texture.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -15,22 +15,30 @@ #define GL_APICALL #include -#include #include "common/debug.h" #include "common/RefCountObject.h" -#include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/utilities.h" +#include "libGLESv2/angletypes.h" namespace egl { class Surface; } +namespace rx +{ +class Renderer; +class TextureStorageInterface; +class TextureStorageInterface2D; +class TextureStorageInterfaceCube; +class RenderTarget; +class Image; +} + namespace gl { -class Blit; class Framebuffer; +class Renderbuffer; enum { @@ -43,132 +51,10 @@ enum IMPLEMENTATION_MAX_TEXTURE_LEVELS = 15 // 1+log2 of MAX_TEXTURE_SIZE }; -class Image -{ - public: - Image(); - ~Image(); - - bool redefine(GLint internalformat, GLsizei width, GLsizei height, bool forceRelease); - void markDirty() {mDirty = true;} - void markClean() {mDirty = false;} - - bool isRenderableFormat() const; - D3DFORMAT getD3DFormat() const; - - GLsizei getWidth() const {return mWidth;} - GLsizei getHeight() const {return mHeight;} - GLenum getInternalFormat() const {return mInternalFormat;} - bool isDirty() const {return mSurface && mDirty;} - IDirect3DSurface9 *getSurface(); - - void setManagedSurface(IDirect3DSurface9 *surface); - void updateSurface(IDirect3DSurface9 *dest, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); - - void loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - GLint unpackAlignment, const void *input); - - void loadAlphaData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const; - void loadAlphaDataSSE2(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const; - void loadAlphaFloatData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const; - void loadAlphaHalfFloatData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const; - void loadLuminanceData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output, bool native) const; - void loadLuminanceFloatData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const; - void loadLuminanceHalfFloatData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const; - void loadLuminanceAlphaData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output, bool native) const; - void loadLuminanceAlphaFloatData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const; - void loadLuminanceAlphaHalfFloatData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const; - void loadRGBUByteData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const; - void loadRGB565Data(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const; - void loadRGBFloatData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const; - void loadRGBHalfFloatData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const; - void loadRGBAUByteDataSSE2(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const; - void loadRGBAUByteData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const; - void loadRGBA4444Data(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const; - void loadRGBA5551Data(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const; - void loadRGBAFloatData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const; - void loadRGBAHalfFloatData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const; - void loadBGRAData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const; - void loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - const void *input); - - void copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, IDirect3DSurface9 *renderTarget); - - private: - DISALLOW_COPY_AND_ASSIGN(Image); - - void createSurface(); - - HRESULT lock(D3DLOCKED_RECT *lockedRect, const RECT *rect); - void unlock(); - - GLsizei mWidth; - GLsizei mHeight; - GLint mInternalFormat; - - bool mDirty; - - D3DPOOL mD3DPool; // can only be D3DPOOL_SYSTEMMEM or D3DPOOL_MANAGED since it needs to be lockable. - D3DFORMAT mD3DFormat; - - IDirect3DSurface9 *mSurface; -}; - -class TextureStorage -{ - public: - explicit TextureStorage(DWORD usage); - - virtual ~TextureStorage(); - - bool isRenderTarget() const; - bool isManaged() const; - D3DPOOL getPool() const; - DWORD getUsage() const; - unsigned int getTextureSerial() const; - virtual unsigned int getRenderTargetSerial(GLenum target) const = 0; - int getLodOffset() const; - - protected: - int mLodOffset; - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorage); - - const DWORD mD3DUsage; - const D3DPOOL mD3DPool; - - const unsigned int mTextureSerial; - static unsigned int issueTextureSerial(); - - static unsigned int mCurrentTextureSerial; -}; - class Texture : public RefCountObject { public: - explicit Texture(GLuint id); + Texture(rx::Renderer *renderer, GLuint id); virtual ~Texture(); @@ -189,12 +75,14 @@ class Texture : public RefCountObject GLenum getWrapS() const; GLenum getWrapT() const; float getMaxAnisotropy() const; + int getLodOffset(); + void getSamplerState(SamplerState *sampler); GLenum getUsage() const; bool isMipmapFiltered() const; virtual bool isSamplerComplete() const = 0; - IDirect3DBaseTexture9 *getTexture(); + rx::TextureStorageInterface *getNativeTexture(); virtual Renderbuffer *getRenderbuffer(GLenum target) = 0; virtual void generateMipmaps() = 0; @@ -207,36 +95,28 @@ class Texture : public RefCountObject unsigned int getRenderTargetSerial(GLenum target); bool isImmutable() const; - int getLodOffset(); static const GLuint INCOMPLETE_TEXTURE_ID = static_cast(-1); // Every texture takes an id at creation time. The value is arbitrary because it is never registered with the resource manager. protected: - void setImage(GLint unpackAlignment, const void *pixels, Image *image); - bool subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *image); - void setCompressedImage(GLsizei imageSize, const void *pixels, Image *image); - bool subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *image); + void setImage(GLint unpackAlignment, const void *pixels, rx::Image *image); + bool subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, rx::Image *image); + void setCompressedImage(GLsizei imageSize, const void *pixels, rx::Image *image); + bool subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, rx::Image *image); GLint creationLevels(GLsizei width, GLsizei height) const; GLint creationLevels(GLsizei size) const; - virtual IDirect3DBaseTexture9 *getBaseTexture() const = 0; virtual void createTexture() = 0; virtual void updateTexture() = 0; virtual void convertToRenderTarget() = 0; - virtual IDirect3DSurface9 *getRenderTarget(GLenum target) = 0; + virtual rx::RenderTarget *getRenderTarget(GLenum target) = 0; - int levelCount(); + virtual int levelCount() = 0; - static Blit *getBlitter(); - static bool copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged); + rx::Renderer *mRenderer; - GLenum mMinFilter; - GLenum mMagFilter; - GLenum mWrapS; - GLenum mWrapT; - float mMaxAnisotropy; - bool mDirtyParameters; + SamplerState mSamplerState; GLenum mUsage; bool mDirtyImages; @@ -246,33 +126,13 @@ class Texture : public RefCountObject private: DISALLOW_COPY_AND_ASSIGN(Texture); - virtual TextureStorage *getStorage(bool renderTarget) = 0; -}; - -class TextureStorage2D : public TextureStorage -{ - public: - explicit TextureStorage2D(IDirect3DTexture9 *surfaceTexture); - TextureStorage2D(int levels, D3DFORMAT format, DWORD usage, int width, int height); - - virtual ~TextureStorage2D(); - - IDirect3DSurface9 *getSurfaceLevel(int level, bool dirty); - IDirect3DBaseTexture9 *getBaseTexture() const; - - virtual unsigned int getRenderTargetSerial(GLenum target) const; - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorage2D); - - IDirect3DTexture9 *mTexture; - const unsigned int mRenderTargetSerial; + virtual rx::TextureStorageInterface *getStorage(bool renderTarget) = 0; }; class Texture2D : public Texture { public: - explicit Texture2D(GLuint id); + Texture2D(rx::Renderer *renderer, GLuint id); ~Texture2D(); @@ -284,7 +144,7 @@ class Texture2D : public Texture GLsizei getWidth(GLint level) const; GLsizei getHeight(GLint level) const; GLenum getInternalFormat(GLint level) const; - D3DFORMAT getD3DFormat(GLint level) const; + GLenum getActualFormat(GLint level) const; bool isCompressed(GLint level) const; bool isDepth(GLint level) const; @@ -306,26 +166,26 @@ class Texture2D : public Texture protected: friend class RenderbufferTexture2D; - virtual IDirect3DSurface9 *getRenderTarget(GLenum target); - virtual IDirect3DSurface9 *getDepthStencil(GLenum target); + virtual rx::RenderTarget *getRenderTarget(GLenum target); + virtual rx::RenderTarget *getDepthStencil(GLenum target); + virtual int levelCount(); private: DISALLOW_COPY_AND_ASSIGN(Texture2D); - virtual IDirect3DBaseTexture9 *getBaseTexture() const; virtual void createTexture(); virtual void updateTexture(); virtual void convertToRenderTarget(); - virtual TextureStorage *getStorage(bool renderTarget); + virtual rx::TextureStorageInterface *getStorage(bool renderTarget); bool isMipmapComplete() const; void redefineImage(GLint level, GLint internalformat, GLsizei width, GLsizei height); void commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); - Image mImageArray[IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + rx::Image *mImageArray[IMPLEMENTATION_MAX_TEXTURE_LEVELS]; - TextureStorage2D *mTexStorage; + rx::TextureStorageInterface2D *mTexStorage; egl::Surface *mSurface; // A specific internal reference count is kept for colorbuffer proxy references, @@ -337,29 +197,10 @@ class Texture2D : public Texture unsigned int mProxyRefs; }; -class TextureStorageCubeMap : public TextureStorage -{ - public: - TextureStorageCubeMap(int levels, D3DFORMAT format, DWORD usage, int size); - - virtual ~TextureStorageCubeMap(); - - IDirect3DSurface9 *getCubeMapSurface(GLenum faceTarget, int level, bool dirty); - IDirect3DBaseTexture9 *getBaseTexture() const; - - virtual unsigned int getRenderTargetSerial(GLenum target) const; - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorageCubeMap); - - IDirect3DCubeTexture9 *mTexture; - const unsigned int mFirstRenderTargetSerial; -}; - class TextureCubeMap : public Texture { public: - explicit TextureCubeMap(GLuint id); + TextureCubeMap(rx::Renderer *renderer, GLuint id); ~TextureCubeMap(); @@ -371,7 +212,7 @@ class TextureCubeMap : public Texture GLsizei getWidth(GLenum target, GLint level) const; GLsizei getHeight(GLenum target, GLint level) const; GLenum getInternalFormat(GLenum target, GLint level) const; - D3DFORMAT getD3DFormat(GLenum target, GLint level) const; + GLenum getActualFormat(GLenum target, GLint level) const; bool isCompressed(GLenum target, GLint level) const; void setImagePosX(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels); @@ -399,16 +240,16 @@ class TextureCubeMap : public Texture protected: friend class RenderbufferTextureCubeMap; - virtual IDirect3DSurface9 *getRenderTarget(GLenum target); + virtual rx::RenderTarget *getRenderTarget(GLenum target); + virtual int levelCount(); private: DISALLOW_COPY_AND_ASSIGN(TextureCubeMap); - virtual IDirect3DBaseTexture9 *getBaseTexture() const; virtual void createTexture(); virtual void updateTexture(); virtual void convertToRenderTarget(); - virtual TextureStorage *getStorage(bool renderTarget); + virtual rx::TextureStorageInterface *getStorage(bool renderTarget); bool isCubeComplete() const; bool isMipmapCubeComplete() const; @@ -417,9 +258,9 @@ class TextureCubeMap : public Texture void commitRect(int faceIndex, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); void redefineImage(int faceIndex, GLint level, GLint internalformat, GLsizei width, GLsizei height); - Image mImageArray[6][IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + rx::Image *mImageArray[6][IMPLEMENTATION_MAX_TEXTURE_LEVELS]; - TextureStorageCubeMap *mTexStorage; + rx::TextureStorageInterfaceCube *mTexStorage; // A specific internal reference count is kept for colorbuffer proxy references, // because, as the renderbuffer acting as proxy will maintain a binding pointer diff --git a/gfx/angle/src/libGLESv2/Uniform.cpp b/gfx/angle/src/libGLESv2/Uniform.cpp new file mode 100644 index 000000000000..0fe3b8c963c4 --- /dev/null +++ b/gfx/angle/src/libGLESv2/Uniform.cpp @@ -0,0 +1,43 @@ +#include "precompiled.h" +// +// Copyright (c) 2010-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "libGLESv2/Uniform.h" + +#include "libGLESv2/utilities.h" + +namespace gl +{ + +Uniform::Uniform(GLenum type, GLenum precision, const std::string &name, unsigned int arraySize) + : type(type), precision(precision), name(name), arraySize(arraySize) +{ + int bytes = gl::UniformInternalSize(type) * elementCount(); + data = new unsigned char[bytes]; + memset(data, 0, bytes); + dirty = true; + + psRegisterIndex = -1; + vsRegisterIndex = -1; + registerCount = VariableRowCount(type) * elementCount(); +} + +Uniform::~Uniform() +{ + delete[] data; +} + +bool Uniform::isArray() const +{ + return arraySize > 0; +} + +unsigned int Uniform::elementCount() const +{ + return arraySize > 0 ? arraySize : 1; +} + +} diff --git a/gfx/angle/src/libGLESv2/Uniform.h b/gfx/angle/src/libGLESv2/Uniform.h new file mode 100644 index 000000000000..64414acbd8f6 --- /dev/null +++ b/gfx/angle/src/libGLESv2/Uniform.h @@ -0,0 +1,48 @@ +// +// Copyright (c) 2010-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef LIBGLESV2_UNIFORM_H_ +#define LIBGLESV2_UNIFORM_H_ + +#include +#include + +#define GL_APICALL +#include + +#include "common/debug.h" + +namespace gl +{ + +// Helper struct representing a single shader uniform +struct Uniform +{ + Uniform(GLenum type, GLenum precision, const std::string &name, unsigned int arraySize); + + ~Uniform(); + + bool isArray() const; + unsigned int elementCount() const; + + const GLenum type; + const GLenum precision; + const std::string name; + const unsigned int arraySize; + + unsigned char *data; + bool dirty; + + int psRegisterIndex; + int vsRegisterIndex; + unsigned int registerCount; +}; + +typedef std::vector UniformArray; + +} + +#endif // LIBGLESV2_UNIFORM_H_ diff --git a/gfx/angle/src/libGLESv2/VertexDataManager.cpp b/gfx/angle/src/libGLESv2/VertexDataManager.cpp deleted file mode 100644 index 32c40182d3db..000000000000 --- a/gfx/angle/src/libGLESv2/VertexDataManager.cpp +++ /dev/null @@ -1,783 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// VertexDataManager.h: Defines the VertexDataManager, a class that -// runs the Buffer translation process. - -#include "libGLESv2/VertexDataManager.h" - -#include "common/debug.h" - -#include "libGLESv2/Buffer.h" -#include "libGLESv2/Program.h" -#include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/main.h" - -#include "libGLESv2/vertexconversion.h" -#include "libGLESv2/IndexDataManager.h" - -namespace -{ - enum { INITIAL_STREAM_BUFFER_SIZE = 1024*1024 }; - // This has to be at least 4k or else it fails on ATI cards. - enum { CONSTANT_VERTEX_BUFFER_SIZE = 4096 }; -} - -namespace gl -{ -unsigned int VertexBuffer::mCurrentSerial = 1; - -int elementsInBuffer(const VertexAttribute &attribute, int size) -{ - int stride = attribute.stride(); - return (size - attribute.mOffset % stride + (stride - attribute.typeSize())) / stride; -} - -VertexDataManager::VertexDataManager(Context *context, IDirect3DDevice9 *device) : mContext(context), mDevice(device) -{ - for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - mDirtyCurrentValue[i] = true; - mCurrentValueBuffer[i] = NULL; - mCurrentValueOffsets[i] = 0; - } - - const D3DCAPS9 &caps = context->getDeviceCaps(); - checkVertexCaps(caps.DeclTypes); - - mStreamingBuffer = new StreamingVertexBuffer(mDevice, INITIAL_STREAM_BUFFER_SIZE); - - if (!mStreamingBuffer) - { - ERR("Failed to allocate the streaming vertex buffer."); - } -} - -VertexDataManager::~VertexDataManager() -{ - delete mStreamingBuffer; - - for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - delete mCurrentValueBuffer[i]; - } -} - -std::size_t VertexDataManager::writeAttributeData(ArrayVertexBuffer *vertexBuffer, GLint start, GLsizei count, const VertexAttribute &attribute, GLsizei instances) -{ - Buffer *buffer = attribute.mBoundBuffer.get(); - - int inputStride = attribute.stride(); - int elementSize = attribute.typeSize(); - const FormatConverter &converter = formatConverter(attribute); - std::size_t streamOffset = 0; - - void *output = NULL; - - if (vertexBuffer) - { - output = vertexBuffer->map(attribute, spaceRequired(attribute, count, instances), &streamOffset); - } - - if (output == NULL) - { - ERR("Failed to map vertex buffer."); - return -1; - } - - const char *input = NULL; - - if (buffer) - { - int offset = attribute.mOffset; - - input = static_cast(buffer->data()) + offset; - } - else - { - input = static_cast(attribute.mPointer); - } - - if (instances == 0 || attribute.mDivisor == 0) - { - input += inputStride * start; - } - - if (converter.identity && inputStride == elementSize) - { - memcpy(output, input, count * inputStride); - } - else - { - converter.convertArray(input, inputStride, count, output); - } - - vertexBuffer->unmap(); - - return streamOffset; -} - -GLenum VertexDataManager::prepareVertexData(GLint start, GLsizei count, TranslatedAttribute *translated, GLsizei instances) -{ - if (!mStreamingBuffer) - { - return GL_OUT_OF_MEMORY; - } - - const VertexAttributeArray &attribs = mContext->getVertexAttributes(); - ProgramBinary *programBinary = mContext->getCurrentProgramBinary(); - - for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) - { - translated[attributeIndex].active = (programBinary->getSemanticIndex(attributeIndex) != -1); - } - - // Determine the required storage size per used buffer, and invalidate static buffers that don't contain matching attributes - for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - if (translated[i].active && attribs[i].mArrayEnabled) - { - Buffer *buffer = attribs[i].mBoundBuffer.get(); - StaticVertexBuffer *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL; - - if (staticBuffer) - { - if (staticBuffer->size() == 0) - { - int totalCount = elementsInBuffer(attribs[i], buffer->size()); - staticBuffer->addRequiredSpace(spaceRequired(attribs[i], totalCount, 0)); - } - else if (staticBuffer->lookupAttribute(attribs[i]) == -1) - { - // This static buffer doesn't have matching attributes, so fall back to using the streaming buffer - // Add the space of all previous attributes belonging to the invalidated static buffer to the streaming buffer - for (int previous = 0; previous < i; previous++) - { - if (translated[previous].active && attribs[previous].mArrayEnabled) - { - Buffer *previousBuffer = attribs[previous].mBoundBuffer.get(); - StaticVertexBuffer *previousStaticBuffer = previousBuffer ? previousBuffer->getStaticVertexBuffer() : NULL; - - if (staticBuffer == previousStaticBuffer) - { - mStreamingBuffer->addRequiredSpace(spaceRequired(attribs[previous], count, instances)); - } - } - } - - mStreamingBuffer->addRequiredSpace(spaceRequired(attribs[i], count, instances)); - - buffer->invalidateStaticData(); - } - } - else - { - mStreamingBuffer->addRequiredSpace(spaceRequired(attribs[i], count, instances)); - } - } - } - - // Reserve the required space per used buffer - for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - if (translated[i].active && attribs[i].mArrayEnabled) - { - Buffer *buffer = attribs[i].mBoundBuffer.get(); - ArrayVertexBuffer *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL; - ArrayVertexBuffer *vertexBuffer = staticBuffer ? staticBuffer : mStreamingBuffer; - - if (vertexBuffer) - { - vertexBuffer->reserveRequiredSpace(); - } - } - } - - // Perform the vertex data translations - for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - if (translated[i].active) - { - if (attribs[i].mArrayEnabled) - { - Buffer *buffer = attribs[i].mBoundBuffer.get(); - - if (!buffer && attribs[i].mPointer == NULL) - { - // This is an application error that would normally result in a crash, but we catch it and return an error - ERR("An enabled vertex array has no buffer and no pointer."); - return GL_INVALID_OPERATION; - } - - const FormatConverter &converter = formatConverter(attribs[i]); - - StaticVertexBuffer *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL; - ArrayVertexBuffer *vertexBuffer = staticBuffer ? staticBuffer : static_cast(mStreamingBuffer); - - std::size_t streamOffset = -1; - - if (staticBuffer) - { - streamOffset = staticBuffer->lookupAttribute(attribs[i]); - - if (streamOffset == -1) - { - // Convert the entire buffer - int totalCount = elementsInBuffer(attribs[i], buffer->size()); - int startIndex = attribs[i].mOffset / attribs[i].stride(); - - streamOffset = writeAttributeData(staticBuffer, -startIndex, totalCount, attribs[i], 0); - } - - if (streamOffset != -1) - { - streamOffset += (attribs[i].mOffset / attribs[i].stride()) * converter.outputElementSize; - - if (instances == 0 || attribs[i].mDivisor == 0) - { - streamOffset += start * converter.outputElementSize; - } - } - } - else - { - streamOffset = writeAttributeData(mStreamingBuffer, start, count, attribs[i], instances); - } - - if (streamOffset == -1) - { - return GL_OUT_OF_MEMORY; - } - - translated[i].vertexBuffer = vertexBuffer->getBuffer(); - translated[i].serial = vertexBuffer->getSerial(); - translated[i].divisor = attribs[i].mDivisor; - - translated[i].type = converter.d3dDeclType; - translated[i].stride = converter.outputElementSize; - translated[i].offset = streamOffset; - } - else - { - if (!mCurrentValueBuffer[i]) - { - mCurrentValueBuffer[i] = new StreamingVertexBuffer(mDevice, CONSTANT_VERTEX_BUFFER_SIZE); - } - - StreamingVertexBuffer *buffer = mCurrentValueBuffer[i]; - - if (mDirtyCurrentValue[i]) - { - const int requiredSpace = 4 * sizeof(float); - buffer->addRequiredSpace(requiredSpace); - buffer->reserveRequiredSpace(); - float *data = static_cast(buffer->map(VertexAttribute(), requiredSpace, &mCurrentValueOffsets[i])); - if (data) - { - data[0] = attribs[i].mCurrentValue[0]; - data[1] = attribs[i].mCurrentValue[1]; - data[2] = attribs[i].mCurrentValue[2]; - data[3] = attribs[i].mCurrentValue[3]; - buffer->unmap(); - mDirtyCurrentValue[i] = false; - } - } - - translated[i].vertexBuffer = mCurrentValueBuffer[i]->getBuffer(); - translated[i].serial = mCurrentValueBuffer[i]->getSerial(); - translated[i].divisor = 0; - - translated[i].type = D3DDECLTYPE_FLOAT4; - translated[i].stride = 0; - translated[i].offset = mCurrentValueOffsets[i]; - } - } - } - - for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - if (translated[i].active && attribs[i].mArrayEnabled) - { - Buffer *buffer = attribs[i].mBoundBuffer.get(); - - if (buffer) - { - buffer->promoteStaticUsage(count * attribs[i].typeSize()); - } - } - } - - return GL_NO_ERROR; -} - -std::size_t VertexDataManager::spaceRequired(const VertexAttribute &attrib, std::size_t count, GLsizei instances) const -{ - size_t elementSize = formatConverter(attrib).outputElementSize; - - if (instances == 0 || attrib.mDivisor == 0) - { - return elementSize * count; - } - else - { - return elementSize * ((instances + attrib.mDivisor - 1) / attrib.mDivisor); - } -} - -// Mapping from OpenGL-ES vertex attrib type to D3D decl type: -// -// BYTE SHORT (Cast) -// BYTE-norm FLOAT (Normalize) (can't be exactly represented as SHORT-norm) -// UNSIGNED_BYTE UBYTE4 (Identity) or SHORT (Cast) -// UNSIGNED_BYTE-norm UBYTE4N (Identity) or FLOAT (Normalize) -// SHORT SHORT (Identity) -// SHORT-norm SHORT-norm (Identity) or FLOAT (Normalize) -// UNSIGNED_SHORT FLOAT (Cast) -// UNSIGNED_SHORT-norm USHORT-norm (Identity) or FLOAT (Normalize) -// FIXED (not in WebGL) FLOAT (FixedToFloat) -// FLOAT FLOAT (Identity) - -// GLToCType maps from GL type (as GLenum) to the C typedef. -template struct GLToCType { }; - -template <> struct GLToCType { typedef GLbyte type; }; -template <> struct GLToCType { typedef GLubyte type; }; -template <> struct GLToCType { typedef GLshort type; }; -template <> struct GLToCType { typedef GLushort type; }; -template <> struct GLToCType { typedef GLuint type; }; -template <> struct GLToCType { typedef GLfloat type; }; - -// This differs from D3DDECLTYPE in that it is unsized. (Size expansion is applied last.) -enum D3DVertexType -{ - D3DVT_FLOAT, - D3DVT_SHORT, - D3DVT_SHORT_NORM, - D3DVT_UBYTE, - D3DVT_UBYTE_NORM, - D3DVT_USHORT_NORM -}; - -// D3DToCType maps from D3D vertex type (as enum D3DVertexType) to the corresponding C type. -template struct D3DToCType { }; - -template <> struct D3DToCType { typedef float type; }; -template <> struct D3DToCType { typedef short type; }; -template <> struct D3DToCType { typedef short type; }; -template <> struct D3DToCType { typedef unsigned char type; }; -template <> struct D3DToCType { typedef unsigned char type; }; -template <> struct D3DToCType { typedef unsigned short type; }; - -// Encode the type/size combinations that D3D permits. For each type/size it expands to a widener that will provide the appropriate final size. -template -struct WidenRule -{ -}; - -template struct WidenRule : gl::NoWiden { }; -template struct WidenRule : gl::WidenToEven { }; -template struct WidenRule : gl::WidenToEven { }; -template struct WidenRule : gl::WidenToFour { }; -template struct WidenRule : gl::WidenToFour { }; -template struct WidenRule : gl::WidenToEven { }; - -// VertexTypeFlags encodes the D3DCAPS9::DeclType flag and vertex declaration flag for each D3D vertex type & size combination. -template -struct VertexTypeFlags -{ -}; - -template -struct VertexTypeFlagsHelper -{ - enum { capflag = _capflag }; - enum { declflag = _declflag }; -}; - -template <> struct VertexTypeFlags : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT1> { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT2> { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT3> { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT4> { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT2> { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT4> { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper { }; - - -// VertexTypeMapping maps GL type & normalized flag to preferred and fallback D3D vertex types (as D3DVertexType enums). -template -struct VertexTypeMapping -{ -}; - -template -struct VertexTypeMappingBase -{ - enum { preferred = Preferred }; - enum { fallback = Fallback }; -}; - -template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Cast -template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Normalize -template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Identity, Cast -template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Identity, Normalize -template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Identity -template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Cast, Normalize -template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Cast -template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Cast, Normalize -template struct VertexTypeMapping : VertexTypeMappingBase { }; // FixedToFloat -template struct VertexTypeMapping : VertexTypeMappingBase { }; // Identity - - -// Given a GL type & norm flag and a D3D type, ConversionRule provides the type conversion rule (Cast, Normalize, Identity, FixedToFloat). -// The conversion rules themselves are defined in vertexconversion.h. - -// Almost all cases are covered by Cast (including those that are actually Identity since Cast knows it's an identity mapping). -template -struct ConversionRule : gl::Cast::type, typename D3DToCType::type> -{ -}; - -// All conversions from normalized types to float use the Normalize operator. -template struct ConversionRule : gl::Normalize::type> { }; - -// Use a full specialisation for this so that it preferentially matches ahead of the generic normalize-to-float rules. -template <> struct ConversionRule : gl::FixedToFloat { }; -template <> struct ConversionRule : gl::FixedToFloat { }; - -// A 2-stage construction is used for DefaultVertexValues because float must use SimpleDefaultValues (i.e. 0/1) -// whether it is normalized or not. -template -struct DefaultVertexValuesStage2 -{ -}; - -template struct DefaultVertexValuesStage2 : gl::NormalizedDefaultValues { }; -template struct DefaultVertexValuesStage2 : gl::SimpleDefaultValues { }; - -// Work out the default value rule for a D3D type (expressed as the C type) and -template -struct DefaultVertexValues : DefaultVertexValuesStage2 -{ -}; - -template struct DefaultVertexValues : gl::SimpleDefaultValues { }; - -// Policy rules for use with Converter, to choose whether to use the preferred or fallback conversion. -// The fallback conversion produces an output that all D3D9 devices must support. -template struct UsePreferred { enum { type = T::preferred }; }; -template struct UseFallback { enum { type = T::fallback }; }; - -// Converter ties it all together. Given an OpenGL type/norm/size and choice of preferred/fallback conversion, -// it provides all the members of the appropriate VertexDataConverter, the D3DCAPS9::DeclTypes flag in cap flag -// and the D3DDECLTYPE member needed for the vertex declaration in declflag. -template class PreferenceRule> -struct Converter - : gl::VertexDataConverter::type, - WidenRule >::type, size>, - ConversionRule >::type>, - DefaultVertexValues >::type>::type, normalized > > -{ -private: - enum { d3dtype = PreferenceRule< VertexTypeMapping >::type }; - enum { d3dsize = WidenRule::finalWidth }; - -public: - enum { capflag = VertexTypeFlags::capflag }; - enum { declflag = VertexTypeFlags::declflag }; -}; - -// Initialise a TranslationInfo -#define TRANSLATION(type, norm, size, preferred) \ - { \ - Converter::identity, \ - Converter::finalSize, \ - Converter::convertArray, \ - static_cast(Converter::declflag) \ - } - -#define TRANSLATION_FOR_TYPE_NORM_SIZE(type, norm, size) \ - { \ - Converter::capflag, \ - TRANSLATION(type, norm, size, UsePreferred), \ - TRANSLATION(type, norm, size, UseFallback) \ - } - -#define TRANSLATIONS_FOR_TYPE(type) \ - { \ - { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \ - { TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 4) }, \ - } - -#define TRANSLATIONS_FOR_TYPE_NO_NORM(type) \ - { \ - { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \ - { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \ - } - -const VertexDataManager::TranslationDescription VertexDataManager::mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4] = // [GL types as enumerated by typeIndex()][normalized][size-1] -{ - TRANSLATIONS_FOR_TYPE(GL_BYTE), - TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_BYTE), - TRANSLATIONS_FOR_TYPE(GL_SHORT), - TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_SHORT), - TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FIXED), - TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FLOAT) -}; - -void VertexDataManager::checkVertexCaps(DWORD declTypes) -{ - for (unsigned int i = 0; i < NUM_GL_VERTEX_ATTRIB_TYPES; i++) - { - for (unsigned int j = 0; j < 2; j++) - { - for (unsigned int k = 0; k < 4; k++) - { - if (mPossibleTranslations[i][j][k].capsFlag == 0 || (declTypes & mPossibleTranslations[i][j][k].capsFlag) != 0) - { - mAttributeTypes[i][j][k] = mPossibleTranslations[i][j][k].preferredConversion; - } - else - { - mAttributeTypes[i][j][k] = mPossibleTranslations[i][j][k].fallbackConversion; - } - } - } - } -} - -// This is used to index mAttributeTypes and mPossibleTranslations. -unsigned int VertexDataManager::typeIndex(GLenum type) const -{ - switch (type) - { - case GL_BYTE: return 0; - case GL_UNSIGNED_BYTE: return 1; - case GL_SHORT: return 2; - case GL_UNSIGNED_SHORT: return 3; - case GL_FIXED: return 4; - case GL_FLOAT: return 5; - - default: UNREACHABLE(); return 5; - } -} - -VertexBuffer::VertexBuffer(IDirect3DDevice9 *device, std::size_t size, DWORD usageFlags) : mDevice(device), mVertexBuffer(NULL) -{ - if (size > 0) - { - D3DPOOL pool = getDisplay()->getBufferPool(usageFlags); - HRESULT result = device->CreateVertexBuffer(size, usageFlags, 0, pool, &mVertexBuffer, NULL); - mSerial = issueSerial(); - - if (FAILED(result)) - { - ERR("Out of memory allocating a vertex buffer of size %lu.", size); - } - } -} - -VertexBuffer::~VertexBuffer() -{ - if (mVertexBuffer) - { - mVertexBuffer->Release(); - } -} - -void VertexBuffer::unmap() -{ - if (mVertexBuffer) - { - mVertexBuffer->Unlock(); - } -} - -IDirect3DVertexBuffer9 *VertexBuffer::getBuffer() const -{ - return mVertexBuffer; -} - -unsigned int VertexBuffer::getSerial() const -{ - return mSerial; -} - -unsigned int VertexBuffer::issueSerial() -{ - return mCurrentSerial++; -} - -ArrayVertexBuffer::ArrayVertexBuffer(IDirect3DDevice9 *device, std::size_t size, DWORD usageFlags) : VertexBuffer(device, size, usageFlags) -{ - mBufferSize = size; - mWritePosition = 0; - mRequiredSpace = 0; -} - -ArrayVertexBuffer::~ArrayVertexBuffer() -{ -} - -void ArrayVertexBuffer::addRequiredSpace(UINT requiredSpace) -{ - mRequiredSpace += requiredSpace; -} - -StreamingVertexBuffer::StreamingVertexBuffer(IDirect3DDevice9 *device, std::size_t initialSize) : ArrayVertexBuffer(device, initialSize, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY) -{ -} - -StreamingVertexBuffer::~StreamingVertexBuffer() -{ -} - -void *StreamingVertexBuffer::map(const VertexAttribute &attribute, std::size_t requiredSpace, std::size_t *offset) -{ - void *mapPtr = NULL; - - if (mVertexBuffer) - { - HRESULT result = mVertexBuffer->Lock(mWritePosition, requiredSpace, &mapPtr, D3DLOCK_NOOVERWRITE); - - if (FAILED(result)) - { - ERR("Lock failed with error 0x%08x", result); - return NULL; - } - - *offset = mWritePosition; - mWritePosition += requiredSpace; - } - - return mapPtr; -} - -void StreamingVertexBuffer::reserveRequiredSpace() -{ - if (mRequiredSpace > mBufferSize) - { - if (mVertexBuffer) - { - mVertexBuffer->Release(); - mVertexBuffer = NULL; - } - - mBufferSize = std::max(mRequiredSpace, 3 * mBufferSize / 2); // 1.5 x mBufferSize is arbitrary and should be checked to see we don't have too many reallocations. - - D3DPOOL pool = getDisplay()->getBufferPool(D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY); - HRESULT result = mDevice->CreateVertexBuffer(mBufferSize, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, pool, &mVertexBuffer, NULL); - mSerial = issueSerial(); - - if (FAILED(result)) - { - ERR("Out of memory allocating a vertex buffer of size %lu.", mBufferSize); - } - - mWritePosition = 0; - } - else if (mWritePosition + mRequiredSpace > mBufferSize) // Recycle - { - if (mVertexBuffer) - { - void *dummy; - mVertexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD); - mVertexBuffer->Unlock(); - } - - mWritePosition = 0; - } - - mRequiredSpace = 0; -} - -StaticVertexBuffer::StaticVertexBuffer(IDirect3DDevice9 *device) : ArrayVertexBuffer(device, 0, D3DUSAGE_WRITEONLY) -{ -} - -StaticVertexBuffer::~StaticVertexBuffer() -{ -} - -void *StaticVertexBuffer::map(const VertexAttribute &attribute, std::size_t requiredSpace, std::size_t *streamOffset) -{ - void *mapPtr = NULL; - - if (mVertexBuffer) - { - HRESULT result = mVertexBuffer->Lock(mWritePosition, requiredSpace, &mapPtr, 0); - - if (FAILED(result)) - { - ERR("Lock failed with error 0x%08x", result); - return NULL; - } - - int attributeOffset = attribute.mOffset % attribute.stride(); - VertexElement element = {attribute.mType, attribute.mSize, attribute.stride(), attribute.mNormalized, attributeOffset, mWritePosition}; - mCache.push_back(element); - - *streamOffset = mWritePosition; - mWritePosition += requiredSpace; - } - - return mapPtr; -} - -void StaticVertexBuffer::reserveRequiredSpace() -{ - if (!mVertexBuffer && mBufferSize == 0) - { - D3DPOOL pool = getDisplay()->getBufferPool(D3DUSAGE_WRITEONLY); - HRESULT result = mDevice->CreateVertexBuffer(mRequiredSpace, D3DUSAGE_WRITEONLY, 0, pool, &mVertexBuffer, NULL); - mSerial = issueSerial(); - - if (FAILED(result)) - { - ERR("Out of memory allocating a vertex buffer of size %lu.", mRequiredSpace); - } - - mBufferSize = mRequiredSpace; - } - else if (mVertexBuffer && mBufferSize >= mRequiredSpace) - { - // Already allocated - } - else UNREACHABLE(); // Static vertex buffers can't be resized - - mRequiredSpace = 0; -} - -std::size_t StaticVertexBuffer::lookupAttribute(const VertexAttribute &attribute) -{ - for (unsigned int element = 0; element < mCache.size(); element++) - { - if (mCache[element].type == attribute.mType && - mCache[element].size == attribute.mSize && - mCache[element].stride == attribute.stride() && - mCache[element].normalized == attribute.mNormalized) - { - if (mCache[element].attributeOffset == attribute.mOffset % attribute.stride()) - { - return mCache[element].streamOffset; - } - } - } - - return -1; -} - -const VertexDataManager::FormatConverter &VertexDataManager::formatConverter(const VertexAttribute &attribute) const -{ - return mAttributeTypes[typeIndex(attribute.mType)][attribute.mNormalized][attribute.mSize - 1]; -} -} diff --git a/gfx/angle/src/libGLESv2/VertexDataManager.h b/gfx/angle/src/libGLESv2/VertexDataManager.h deleted file mode 100644 index 857591ac2930..000000000000 --- a/gfx/angle/src/libGLESv2/VertexDataManager.h +++ /dev/null @@ -1,169 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// VertexDataManager.h: Defines the VertexDataManager, a class that -// runs the Buffer translation process. - -#ifndef LIBGLESV2_VERTEXDATAMANAGER_H_ -#define LIBGLESV2_VERTEXDATAMANAGER_H_ - -#include -#include - -#define GL_APICALL -#include - -#include "libGLESv2/Context.h" - -namespace gl -{ - -struct TranslatedAttribute -{ - bool active; - - D3DDECLTYPE type; - UINT offset; - UINT stride; // 0 means not to advance the read pointer at all - - IDirect3DVertexBuffer9 *vertexBuffer; - unsigned int serial; - unsigned int divisor; -}; - -class VertexBuffer -{ - public: - VertexBuffer(IDirect3DDevice9 *device, std::size_t size, DWORD usageFlags); - virtual ~VertexBuffer(); - - void unmap(); - - IDirect3DVertexBuffer9 *getBuffer() const; - unsigned int getSerial() const; - - protected: - IDirect3DDevice9 *const mDevice; - IDirect3DVertexBuffer9 *mVertexBuffer; - - unsigned int mSerial; - static unsigned int issueSerial(); - static unsigned int mCurrentSerial; - - private: - DISALLOW_COPY_AND_ASSIGN(VertexBuffer); -}; - -class ArrayVertexBuffer : public VertexBuffer -{ - public: - ArrayVertexBuffer(IDirect3DDevice9 *device, std::size_t size, DWORD usageFlags); - ~ArrayVertexBuffer(); - - std::size_t size() const { return mBufferSize; } - virtual void *map(const VertexAttribute &attribute, std::size_t requiredSpace, std::size_t *streamOffset) = 0; - virtual void reserveRequiredSpace() = 0; - void addRequiredSpace(UINT requiredSpace); - - protected: - std::size_t mBufferSize; - std::size_t mWritePosition; - std::size_t mRequiredSpace; -}; - -class StreamingVertexBuffer : public ArrayVertexBuffer -{ - public: - StreamingVertexBuffer(IDirect3DDevice9 *device, std::size_t initialSize); - ~StreamingVertexBuffer(); - - void *map(const VertexAttribute &attribute, std::size_t requiredSpace, std::size_t *streamOffset); - void reserveRequiredSpace(); -}; - -class StaticVertexBuffer : public ArrayVertexBuffer -{ - public: - explicit StaticVertexBuffer(IDirect3DDevice9 *device); - ~StaticVertexBuffer(); - - void *map(const VertexAttribute &attribute, std::size_t requiredSpace, std::size_t *streamOffset); - void reserveRequiredSpace(); - - std::size_t lookupAttribute(const VertexAttribute &attribute); // Returns the offset into the vertex buffer, or -1 if not found - - private: - struct VertexElement - { - GLenum type; - GLint size; - GLsizei stride; - bool normalized; - int attributeOffset; - - std::size_t streamOffset; - }; - - std::vector mCache; -}; - -class VertexDataManager -{ - public: - VertexDataManager(Context *context, IDirect3DDevice9 *backend); - virtual ~VertexDataManager(); - - void dirtyCurrentValue(int index) { mDirtyCurrentValue[index] = true; } - - GLenum prepareVertexData(GLint start, GLsizei count, TranslatedAttribute *outAttribs, GLsizei instances); - - private: - DISALLOW_COPY_AND_ASSIGN(VertexDataManager); - - std::size_t spaceRequired(const VertexAttribute &attrib, std::size_t count, GLsizei instances) const; - std::size_t writeAttributeData(ArrayVertexBuffer *vertexBuffer, GLint start, GLsizei count, const VertexAttribute &attribute, GLsizei instances); - - Context *const mContext; - IDirect3DDevice9 *const mDevice; - - StreamingVertexBuffer *mStreamingBuffer; - - bool mDirtyCurrentValue[MAX_VERTEX_ATTRIBS]; - StreamingVertexBuffer *mCurrentValueBuffer[MAX_VERTEX_ATTRIBS]; - std::size_t mCurrentValueOffsets[MAX_VERTEX_ATTRIBS]; - - // Attribute format conversion - struct FormatConverter - { - bool identity; - std::size_t outputElementSize; - void (*convertArray)(const void *in, std::size_t stride, std::size_t n, void *out); - D3DDECLTYPE d3dDeclType; - }; - - enum { NUM_GL_VERTEX_ATTRIB_TYPES = 6 }; - - FormatConverter mAttributeTypes[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; // [GL types as enumerated by typeIndex()][normalized][size - 1] - - struct TranslationDescription - { - DWORD capsFlag; - FormatConverter preferredConversion; - FormatConverter fallbackConversion; - }; - - // This table is used to generate mAttributeTypes. - static const TranslationDescription mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; // [GL types as enumerated by typeIndex()][normalized][size - 1] - - void checkVertexCaps(DWORD declTypes); - - unsigned int typeIndex(GLenum type) const; - const FormatConverter &formatConverter(const VertexAttribute &attribute) const; -}; - -} - -#endif // LIBGLESV2_VERTEXDATAMANAGER_H_ diff --git a/gfx/angle/src/libGLESv2/angletypes.h b/gfx/angle/src/libGLESv2/angletypes.h new file mode 100644 index 000000000000..b2f0cad26592 --- /dev/null +++ b/gfx/angle/src/libGLESv2/angletypes.h @@ -0,0 +1,129 @@ +// +// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// angletypes.h : Defines a variety of structures and enum types that are used throughout libGLESv2 + +#ifndef LIBGLESV2_ANGLETYPES_H_ +#define LIBGLESV2_ANGLETYPES_H_ + +namespace gl +{ + +enum TextureType +{ + TEXTURE_2D, + TEXTURE_CUBE, + + TEXTURE_TYPE_COUNT, + TEXTURE_UNKNOWN +}; + +enum SamplerType +{ + SAMPLER_PIXEL, + SAMPLER_VERTEX +}; + +struct Color +{ + float red; + float green; + float blue; + float alpha; +}; + +struct Rectangle +{ + int x; + int y; + int width; + int height; +}; + +struct RasterizerState +{ + bool cullFace; + GLenum cullMode; + GLenum frontFace; + + bool polygonOffsetFill; + GLfloat polygonOffsetFactor; + GLfloat polygonOffsetUnits; + + bool pointDrawMode; + bool multiSample; +}; + +struct BlendState +{ + bool blend; + GLenum sourceBlendRGB; + GLenum destBlendRGB; + GLenum sourceBlendAlpha; + GLenum destBlendAlpha; + GLenum blendEquationRGB; + GLenum blendEquationAlpha; + + bool colorMaskRed; + bool colorMaskGreen; + bool colorMaskBlue; + bool colorMaskAlpha; + + bool sampleAlphaToCoverage; + + bool dither; +}; + +struct DepthStencilState +{ + bool depthTest; + GLenum depthFunc; + bool depthMask; + + bool stencilTest; + GLenum stencilFunc; + GLuint stencilMask; + GLenum stencilFail; + GLenum stencilPassDepthFail; + GLenum stencilPassDepthPass; + GLuint stencilWritemask; + GLenum stencilBackFunc; + GLuint stencilBackMask; + GLenum stencilBackFail; + GLenum stencilBackPassDepthFail; + GLenum stencilBackPassDepthPass; + GLuint stencilBackWritemask; +}; + +struct SamplerState +{ + GLenum minFilter; + GLenum magFilter; + GLenum wrapS; + GLenum wrapT; + float maxAnisotropy; + int lodOffset; +}; + +struct ClearParameters +{ + GLbitfield mask; + + Color colorClearValue; + bool colorMaskRed; + bool colorMaskGreen; + bool colorMaskBlue; + bool colorMaskAlpha; + + float depthClearValue; + + GLint stencilClearValue; + GLuint stencilWriteMask; +}; + +} + +#endif // LIBGLESV2_ANGLETYPES_H_ diff --git a/gfx/angle/src/libGLESv2/constants.h b/gfx/angle/src/libGLESv2/constants.h new file mode 100644 index 000000000000..9f24d66a7dc7 --- /dev/null +++ b/gfx/angle/src/libGLESv2/constants.h @@ -0,0 +1,34 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Contants.h: Defines some implementation specific and gl constants + +#ifndef LIBGLESV2_CONSTANTS_H_ +#define LIBGLESV2_CONSTANTS_H_ + +namespace gl +{ + +enum +{ + MAX_VERTEX_ATTRIBS = 16, + MAX_TEXTURE_IMAGE_UNITS = 16, + + // Implementation upper limits, real maximums depend on the hardware + IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS = 16, + IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS = MAX_TEXTURE_IMAGE_UNITS + IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS, + + IMPLEMENTATION_MAX_VARYING_VECTORS = 32, + IMPLEMENTATION_MAX_DRAW_BUFFERS = 8 +}; + +const float ALIASED_LINE_WIDTH_RANGE_MIN = 1.0f; +const float ALIASED_LINE_WIDTH_RANGE_MAX = 1.0f; +const float ALIASED_POINT_SIZE_RANGE_MIN = 1.0f; + +} + +#endif // LIBGLESV2_CONSTANTS_H_ diff --git a/gfx/angle/src/libGLESv2/libGLESv2.cpp b/gfx/angle/src/libGLESv2/libGLESv2.cpp index 16d9c1775d73..1e7cf9d0cfae 100644 --- a/gfx/angle/src/libGLESv2/libGLESv2.cpp +++ b/gfx/angle/src/libGLESv2/libGLESv2.cpp @@ -1,3 +1,4 @@ +#include "precompiled.h" // // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -6,29 +7,19 @@ // libGLESv2.cpp: Implements the exported OpenGL ES 2.0 functions. -#define GL_APICALL -#include -#include - -#include -#include - -#include "common/debug.h" #include "common/version.h" #include "libGLESv2/main.h" -#include "libGLESv2/mathutil.h" #include "libGLESv2/utilities.h" #include "libGLESv2/Buffer.h" -#include "libGLESv2/Context.h" #include "libGLESv2/Fence.h" #include "libGLESv2/Framebuffer.h" +#include "libGLESv2/Renderbuffer.h" #include "libGLESv2/Program.h" #include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/Shader.h" #include "libGLESv2/Texture.h" #include "libGLESv2/Query.h" +#include "libGLESv2/Context.h" bool validImageSize(GLint level, GLsizei width, GLsizei height) { @@ -71,7 +62,7 @@ bool checkTextureFormatType(GLenum format, GLenum type) case GL_DEPTH_STENCIL_OES: break; default: - return error(GL_INVALID_ENUM, false); + return gl::error(GL_INVALID_ENUM, false); } // invalid -> sets INVALID_ENUM @@ -89,7 +80,7 @@ bool checkTextureFormatType(GLenum format, GLenum type) case GL_LUMINANCE_ALPHA: return true; default: - return error(GL_INVALID_OPERATION, false); + return gl::error(GL_INVALID_OPERATION, false); } case GL_FLOAT: @@ -103,7 +94,7 @@ bool checkTextureFormatType(GLenum format, GLenum type) case GL_LUMINANCE_ALPHA: return true; default: - return error(GL_INVALID_OPERATION, false); + return gl::error(GL_INVALID_OPERATION, false); } case GL_UNSIGNED_SHORT_4_4_4_4: @@ -113,7 +104,7 @@ bool checkTextureFormatType(GLenum format, GLenum type) case GL_RGBA: return true; default: - return error(GL_INVALID_OPERATION, false); + return gl::error(GL_INVALID_OPERATION, false); } case GL_UNSIGNED_SHORT_5_6_5: @@ -122,7 +113,7 @@ bool checkTextureFormatType(GLenum format, GLenum type) case GL_RGB: return true; default: - return error(GL_INVALID_OPERATION, false); + return gl::error(GL_INVALID_OPERATION, false); } case GL_UNSIGNED_SHORT: @@ -132,7 +123,7 @@ bool checkTextureFormatType(GLenum format, GLenum type) case GL_DEPTH_COMPONENT: return true; default: - return error(GL_INVALID_OPERATION, false); + return gl::error(GL_INVALID_OPERATION, false); } case GL_UNSIGNED_INT_24_8_OES: @@ -141,11 +132,11 @@ bool checkTextureFormatType(GLenum format, GLenum type) case GL_DEPTH_STENCIL_OES: return true; default: - return error(GL_INVALID_OPERATION, false); + return gl::error(GL_INVALID_OPERATION, false); } default: - return error(GL_INVALID_ENUM, false); + return gl::error(GL_INVALID_ENUM, false); } } @@ -155,12 +146,12 @@ bool validateSubImageParams2D(bool compressed, GLsizei width, GLsizei height, { if (!texture) { - return error(GL_INVALID_OPERATION, false); + return gl::error(GL_INVALID_OPERATION, false); } if (compressed != texture->isCompressed(level)) { - return error(GL_INVALID_OPERATION, false); + return gl::error(GL_INVALID_OPERATION, false); } if (format != GL_NONE) @@ -168,7 +159,7 @@ bool validateSubImageParams2D(bool compressed, GLsizei width, GLsizei height, GLenum internalformat = gl::ConvertSizedInternalFormat(format, type); if (internalformat != texture->getInternalFormat(level)) { - return error(GL_INVALID_OPERATION, false); + return gl::error(GL_INVALID_OPERATION, false); } } @@ -177,14 +168,14 @@ bool validateSubImageParams2D(bool compressed, GLsizei width, GLsizei height, if ((width % 4 != 0 && width != texture->getWidth(0)) || (height % 4 != 0 && height != texture->getHeight(0))) { - return error(GL_INVALID_OPERATION, false); + return gl::error(GL_INVALID_OPERATION, false); } } if (xoffset + width > texture->getWidth(level) || yoffset + height > texture->getHeight(level)) { - return error(GL_INVALID_VALUE, false); + return gl::error(GL_INVALID_VALUE, false); } return true; @@ -196,12 +187,12 @@ bool validateSubImageParamsCube(bool compressed, GLsizei width, GLsizei height, { if (!texture) { - return error(GL_INVALID_OPERATION, false); + return gl::error(GL_INVALID_OPERATION, false); } if (compressed != texture->isCompressed(target, level)) { - return error(GL_INVALID_OPERATION, false); + return gl::error(GL_INVALID_OPERATION, false); } if (format != GL_NONE) @@ -209,7 +200,7 @@ bool validateSubImageParamsCube(bool compressed, GLsizei width, GLsizei height, GLenum internalformat = gl::ConvertSizedInternalFormat(format, type); if (internalformat != texture->getInternalFormat(target, level)) { - return error(GL_INVALID_OPERATION, false); + return gl::error(GL_INVALID_OPERATION, false); } } @@ -218,14 +209,14 @@ bool validateSubImageParamsCube(bool compressed, GLsizei width, GLsizei height, if ((width % 4 != 0 && width != texture->getWidth(target, 0)) || (height % 4 != 0 && height != texture->getHeight(target, 0))) { - return error(GL_INVALID_OPERATION, false); + return gl::error(GL_INVALID_OPERATION, false); } } if (xoffset + width > texture->getWidth(target, level) || yoffset + height > texture->getHeight(target, level)) { - return error(GL_INVALID_VALUE, false); + return gl::error(GL_INVALID_VALUE, false); } return true; @@ -277,7 +268,7 @@ void __stdcall glActiveTexture(GLenum texture) { if (texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + context->getMaximumCombinedTextureImageUnits() - 1) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } context->setActiveSampler(texture - GL_TEXTURE0); @@ -285,7 +276,7 @@ void __stdcall glActiveTexture(GLenum texture) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -306,11 +297,11 @@ void __stdcall glAttachShader(GLuint program, GLuint shader) { if (context->getShader(program)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } else { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } } @@ -318,23 +309,23 @@ void __stdcall glAttachShader(GLuint program, GLuint shader) { if (context->getProgram(shader)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } else { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } } if (!programObject->attachShader(shaderObject)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -350,12 +341,12 @@ void __stdcall glBeginQueryEXT(GLenum target, GLuint id) case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if (id == 0) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } gl::Context *context = gl::getNonLostContext(); @@ -367,7 +358,7 @@ void __stdcall glBeginQueryEXT(GLenum target, GLuint id) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -379,7 +370,7 @@ void __stdcall glBindAttribLocation(GLuint program, GLuint index, const GLchar* { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -392,17 +383,17 @@ void __stdcall glBindAttribLocation(GLuint program, GLuint index, const GLchar* { if (context->getShader(program)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } else { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } } if (strncmp(name, "gl_", 3) == 0) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } programObject->bindAttributeLocation(index, name); @@ -410,7 +401,7 @@ void __stdcall glBindAttribLocation(GLuint program, GLuint index, const GLchar* } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -433,13 +424,13 @@ void __stdcall glBindBuffer(GLenum target, GLuint buffer) context->bindElementArrayBuffer(buffer); return; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -451,7 +442,7 @@ void __stdcall glBindFramebuffer(GLenum target, GLuint framebuffer) { if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } gl::Context *context = gl::getNonLostContext(); @@ -471,7 +462,7 @@ void __stdcall glBindFramebuffer(GLenum target, GLuint framebuffer) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -483,7 +474,7 @@ void __stdcall glBindRenderbuffer(GLenum target, GLuint renderbuffer) { if (target != GL_RENDERBUFFER) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } gl::Context *context = gl::getNonLostContext(); @@ -495,7 +486,7 @@ void __stdcall glBindRenderbuffer(GLenum target, GLuint renderbuffer) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -513,7 +504,7 @@ void __stdcall glBindTexture(GLenum target, GLuint texture) if (textureObject && textureObject->getTarget() != target && texture != 0) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } switch (target) @@ -525,13 +516,13 @@ void __stdcall glBindTexture(GLenum target, GLuint texture) context->bindTextureCubeMap(texture); return; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -551,7 +542,7 @@ void __stdcall glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclamp } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -573,7 +564,7 @@ void __stdcall glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) case GL_FUNC_REVERSE_SUBTRACT: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } switch (modeAlpha) @@ -583,7 +574,7 @@ void __stdcall glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) case GL_FUNC_REVERSE_SUBTRACT: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } gl::Context *context = gl::getNonLostContext(); @@ -595,7 +586,7 @@ void __stdcall glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -630,7 +621,7 @@ void __stdcall glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha case GL_SRC_ALPHA_SATURATE: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } switch (dstRGB) @@ -651,7 +642,7 @@ void __stdcall glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha case GL_ONE_MINUS_CONSTANT_ALPHA: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } switch (srcAlpha) @@ -673,7 +664,7 @@ void __stdcall glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha case GL_SRC_ALPHA_SATURATE: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } switch (dstAlpha) @@ -694,7 +685,7 @@ void __stdcall glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha case GL_ONE_MINUS_CONSTANT_ALPHA: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } bool constantColorUsed = (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR || @@ -706,7 +697,7 @@ void __stdcall glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha if (constantColorUsed && constantAlphaUsed) { ERR("Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR invalid under WebGL"); - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } gl::Context *context = gl::getNonLostContext(); @@ -718,7 +709,7 @@ void __stdcall glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -731,7 +722,7 @@ void __stdcall glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, { if (size < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } switch (usage) @@ -741,7 +732,7 @@ void __stdcall glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, case GL_DYNAMIC_DRAW: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } gl::Context *context = gl::getNonLostContext(); @@ -759,12 +750,12 @@ void __stdcall glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, buffer = context->getElementArrayBuffer(); break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if (!buffer) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } buffer->bufferData(data, size, usage); @@ -772,7 +763,7 @@ void __stdcall glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -785,7 +776,7 @@ void __stdcall glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, { if (size < 0 || offset < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (data == NULL) @@ -808,17 +799,17 @@ void __stdcall glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, buffer = context->getElementArrayBuffer(); break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if (!buffer) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if ((size_t)size + offset > buffer->size()) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } buffer->bufferSubData(data, size, offset); @@ -826,7 +817,7 @@ void __stdcall glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -838,7 +829,7 @@ GLenum __stdcall glCheckFramebufferStatus(GLenum target) { if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE) { - return error(GL_INVALID_ENUM, 0); + return gl::error(GL_INVALID_ENUM, 0); } gl::Context *context = gl::getNonLostContext(); @@ -860,7 +851,7 @@ GLenum __stdcall glCheckFramebufferStatus(GLenum target) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY, 0); + return gl::error(GL_OUT_OF_MEMORY, 0); } return 0; @@ -881,7 +872,7 @@ void __stdcall glClear(GLbitfield mask) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -901,7 +892,7 @@ void __stdcall glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclamp } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -920,7 +911,7 @@ void __stdcall glClearDepthf(GLclampf depth) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -939,7 +930,7 @@ void __stdcall glClearStencil(GLint s) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -959,7 +950,7 @@ void __stdcall glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboo } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -979,11 +970,11 @@ void __stdcall glCompileShader(GLuint shader) { if (context->getProgram(shader)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } else { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } } @@ -992,7 +983,7 @@ void __stdcall glCompileShader(GLuint shader) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -1007,7 +998,7 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna { if (!validImageSize(level, width, height) || border != 0 || imageSize < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } switch (internalformat) @@ -1018,12 +1009,22 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if (border != 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_OPERATION); + } + + if (width != 1 && width != 2 && width % 4 != 0) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (height != 1 && height != 2 && height % 4 != 0) + { + return gl::error(GL_INVALID_OPERATION); } gl::Context *context = gl::getNonLostContext(); @@ -1032,7 +1033,7 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna { if (level > context->getMaximumTextureLevel()) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } switch (target) @@ -1041,7 +1042,7 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna if (width > (context->getMaximumTextureDimension() >> level) || height > (context->getMaximumTextureDimension() >> level)) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } break; case GL_TEXTURE_CUBE_MAP_POSITIVE_X: @@ -1052,17 +1053,17 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: if (width != height) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (width > (context->getMaximumCubeTextureDimension() >> level) || height > (context->getMaximumCubeTextureDimension() >> level)) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } switch (internalformat) { @@ -1070,19 +1071,19 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: if (!context->supportsDXT1Textures()) { - return error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed + return gl::error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed } break; case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: if (!context->supportsDXT3Textures()) { - return error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed + return gl::error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed } break; case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: if (!context->supportsDXT5Textures()) { - return error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed + return gl::error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed } break; default: UNREACHABLE(); @@ -1090,7 +1091,7 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna if (imageSize != gl::ComputeCompressedSize(width, height, internalformat)) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (target == GL_TEXTURE_2D) @@ -1099,12 +1100,12 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna if (!texture) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (texture->isImmutable()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } texture->setCompressedImage(level, internalformat, width, height, imageSize, data); @@ -1115,12 +1116,12 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna if (!texture) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (texture->isImmutable()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } switch (target) @@ -1141,7 +1142,7 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -1157,12 +1158,12 @@ void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffs { if (!gl::IsInternalTextureTarget(target)) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if (xoffset < 0 || yoffset < 0 || !validImageSize(level, width, height) || imageSize < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } switch (format) @@ -1173,7 +1174,7 @@ void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffs case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if (width == 0 || height == 0 || data == NULL) @@ -1187,7 +1188,7 @@ void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffs { if (level > context->getMaximumTextureLevel()) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } switch (format) { @@ -1195,19 +1196,19 @@ void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffs case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: if (!context->supportsDXT1Textures()) { - return error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed + return gl::error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed } break; case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: if (!context->supportsDXT3Textures()) { - return error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed + return gl::error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed } break; case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: if (!context->supportsDXT5Textures()) { - return error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed + return gl::error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed } break; default: UNREACHABLE(); @@ -1215,12 +1216,12 @@ void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffs if (imageSize != gl::ComputeCompressedSize(width, height, format)) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (xoffset % 4 != 0 || yoffset % 4 != 0) { - return error(GL_INVALID_OPERATION); // we wait to check the offsets until this point, because the multiple-of-four restriction + return gl::error(GL_INVALID_OPERATION); // we wait to check the offsets until this point, because the multiple-of-four restriction // does not exist unless DXT textures are supported. } @@ -1248,7 +1249,7 @@ void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffs } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -1262,12 +1263,12 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma { if (!validImageSize(level, width, height)) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (border != 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -1276,7 +1277,7 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma { if (level > context->getMaximumTextureLevel()) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } switch (target) @@ -1285,7 +1286,7 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma if (width > (context->getMaximumTextureDimension() >> level) || height > (context->getMaximumTextureDimension() >> level)) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } break; case GL_TEXTURE_CUBE_MAP_POSITIVE_X: @@ -1296,32 +1297,32 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: if (width != height) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (width > (context->getMaximumCubeTextureDimension() >> level) || height > (context->getMaximumCubeTextureDimension() >> level)) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } gl::Framebuffer *framebuffer = context->getReadFramebuffer(); if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) { - return error(GL_INVALID_FRAMEBUFFER_OPERATION); + return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION); } - if (context->getReadFramebufferHandle() != 0 && framebuffer->getColorbuffer()->getSamples() != 0) + if (context->getReadFramebufferHandle() != 0 && framebuffer->getSamples() != 0) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } - gl::Renderbuffer *source = framebuffer->getColorbuffer(); + gl::Renderbuffer *source = framebuffer->getReadColorbuffer(); GLenum colorbufferFormat = source->getInternalFormat(); // [OpenGL ES 2.0.24] table 3.9 @@ -1331,9 +1332,10 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 && + colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } break; case GL_LUMINANCE: @@ -1342,49 +1344,51 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 && + colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } break; case GL_LUMINANCE_ALPHA: case GL_RGBA: if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 && + colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } break; case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: if (context->supportsDXT1Textures()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } else { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: if (context->supportsDXT3Textures()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } else { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: if (context->supportsDXT5Textures()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } else { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_DEPTH_COMPONENT: @@ -1394,14 +1398,14 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma case GL_DEPTH24_STENCIL8_OES: if (context->supportsDepthTextures()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } else { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if (target == GL_TEXTURE_2D) @@ -1410,12 +1414,12 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma if (!texture) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (texture->isImmutable()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } texture->copyImage(level, internalformat, x, y, width, height, framebuffer); @@ -1426,12 +1430,12 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma if (!texture) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (texture->isImmutable()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } texture->copyImage(target, level, internalformat, x, y, width, height, framebuffer); @@ -1441,7 +1445,7 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -1455,17 +1459,17 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL { if (!gl::IsInternalTextureTarget(target)) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if (level < 0 || xoffset < 0 || yoffset < 0 || width < 0 || height < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (std::numeric_limits::max() - xoffset < width || std::numeric_limits::max() - yoffset < height) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (width == 0 || height == 0) @@ -1479,22 +1483,22 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL { if (level > context->getMaximumTextureLevel()) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Framebuffer *framebuffer = context->getReadFramebuffer(); if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) { - return error(GL_INVALID_FRAMEBUFFER_OPERATION); + return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION); } - if (context->getReadFramebufferHandle() != 0 && framebuffer->getColorbuffer()->getSamples() != 0) + if (context->getReadFramebufferHandle() != 0 && framebuffer->getSamples() != 0) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } - gl::Renderbuffer *source = framebuffer->getColorbuffer(); + gl::Renderbuffer *source = framebuffer->getReadColorbuffer(); GLenum colorbufferFormat = source->getInternalFormat(); gl::Texture *texture = NULL; GLenum textureFormat = GL_RGBA; @@ -1532,7 +1536,7 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } break; case GL_LUMINANCE: @@ -1543,7 +1547,7 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } break; case GL_LUMINANCE_ALPHA: @@ -1552,19 +1556,19 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } break; case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); case GL_DEPTH_COMPONENT: case GL_DEPTH_STENCIL_OES: - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); default: - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } texture->copySubImage(target, level, xoffset, yoffset, x, y, width, height, framebuffer); @@ -1573,7 +1577,7 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -1592,7 +1596,7 @@ GLuint __stdcall glCreateProgram(void) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY, 0); + return gl::error(GL_OUT_OF_MEMORY, 0); } return 0; @@ -1614,13 +1618,13 @@ GLuint __stdcall glCreateShader(GLenum type) case GL_VERTEX_SHADER: return context->createShader(type); default: - return error(GL_INVALID_ENUM, 0); + return gl::error(GL_INVALID_ENUM, 0); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY, 0); + return gl::error(GL_OUT_OF_MEMORY, 0); } return 0; @@ -1647,12 +1651,12 @@ void __stdcall glCullFace(GLenum mode) } break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -1664,7 +1668,7 @@ void __stdcall glDeleteBuffers(GLsizei n, const GLuint* buffers) { if (n < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -1679,7 +1683,7 @@ void __stdcall glDeleteBuffers(GLsizei n, const GLuint* buffers) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -1691,7 +1695,7 @@ void __stdcall glDeleteFencesNV(GLsizei n, const GLuint* fences) { if (n < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -1706,7 +1710,7 @@ void __stdcall glDeleteFencesNV(GLsizei n, const GLuint* fences) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -1718,7 +1722,7 @@ void __stdcall glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers) { if (n < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -1736,7 +1740,7 @@ void __stdcall glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -1759,11 +1763,11 @@ void __stdcall glDeleteProgram(GLuint program) { if(context->getShader(program)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } else { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } } @@ -1772,7 +1776,7 @@ void __stdcall glDeleteProgram(GLuint program) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -1784,7 +1788,7 @@ void __stdcall glDeleteQueriesEXT(GLsizei n, const GLuint *ids) { if (n < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -1799,7 +1803,7 @@ void __stdcall glDeleteQueriesEXT(GLsizei n, const GLuint *ids) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -1811,7 +1815,7 @@ void __stdcall glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) { if (n < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -1826,7 +1830,7 @@ void __stdcall glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -1849,11 +1853,11 @@ void __stdcall glDeleteShader(GLuint shader) { if(context->getProgram(shader)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } else { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } } @@ -1862,7 +1866,7 @@ void __stdcall glDeleteShader(GLuint shader) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -1874,7 +1878,7 @@ void __stdcall glDeleteTextures(GLsizei n, const GLuint* textures) { if (n < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -1892,7 +1896,7 @@ void __stdcall glDeleteTextures(GLsizei n, const GLuint* textures) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -1914,7 +1918,7 @@ void __stdcall glDepthFunc(GLenum func) case GL_NOTEQUAL: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } gl::Context *context = gl::getNonLostContext(); @@ -1926,7 +1930,7 @@ void __stdcall glDepthFunc(GLenum func) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -1945,7 +1949,7 @@ void __stdcall glDepthMask(GLboolean flag) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -1964,7 +1968,7 @@ void __stdcall glDepthRangef(GLclampf zNear, GLclampf zFar) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -1988,11 +1992,11 @@ void __stdcall glDetachShader(GLuint program, GLuint shader) shaderByProgramHandle = context->getShader(program); if (!shaderByProgramHandle) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } else { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } @@ -2001,23 +2005,23 @@ void __stdcall glDetachShader(GLuint program, GLuint shader) gl::Program *programByShaderHandle = context->getProgram(shader); if (!programByShaderHandle) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } else { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } if (!programObject->detachShader(shaderObject)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2043,13 +2047,13 @@ void __stdcall glDisable(GLenum cap) case GL_BLEND: context->setBlend(false); break; case GL_DITHER: context->setDither(false); break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2061,7 +2065,7 @@ void __stdcall glDisableVertexAttribArray(GLuint index) { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -2073,7 +2077,7 @@ void __stdcall glDisableVertexAttribArray(GLuint index) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2085,7 +2089,7 @@ void __stdcall glDrawArrays(GLenum mode, GLint first, GLsizei count) { if (count < 0 || first < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -2097,7 +2101,7 @@ void __stdcall glDrawArrays(GLenum mode, GLint first, GLsizei count) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2109,7 +2113,7 @@ void __stdcall glDrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei coun { if (count < 0 || first < 0 || primcount < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (primcount > 0) @@ -2124,7 +2128,7 @@ void __stdcall glDrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei coun } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2137,7 +2141,7 @@ void __stdcall glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLv { if (count < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -2152,11 +2156,11 @@ void __stdcall glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLv case GL_UNSIGNED_INT: if (!context->supports32bitIndices()) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } context->drawElements(mode, count, type, indices, 0); @@ -2164,7 +2168,7 @@ void __stdcall glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLv } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2177,7 +2181,7 @@ void __stdcall glDrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum t { if (count < 0 || primcount < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (primcount > 0) @@ -2194,11 +2198,11 @@ void __stdcall glDrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum t case GL_UNSIGNED_INT: if (!context->supports32bitIndices()) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } context->drawElements(mode, count, type, indices, primcount); @@ -2207,7 +2211,7 @@ void __stdcall glDrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum t } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2233,13 +2237,13 @@ void __stdcall glEnable(GLenum cap) case GL_BLEND: context->setBlend(true); break; case GL_DITHER: context->setDither(true); break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2251,7 +2255,7 @@ void __stdcall glEnableVertexAttribArray(GLuint index) { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -2263,7 +2267,7 @@ void __stdcall glEnableVertexAttribArray(GLuint index) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2279,7 +2283,7 @@ void __stdcall glEndQueryEXT(GLenum target) case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } gl::Context *context = gl::getNonLostContext(); @@ -2291,7 +2295,7 @@ void __stdcall glEndQueryEXT(GLenum target) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2309,7 +2313,7 @@ void __stdcall glFinishFenceNV(GLuint fence) if (fenceObject == NULL) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } fenceObject->finishFence(); @@ -2317,7 +2321,7 @@ void __stdcall glFinishFenceNV(GLuint fence) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2336,7 +2340,7 @@ void __stdcall glFinish(void) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2355,7 +2359,7 @@ void __stdcall glFlush(void) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2369,7 +2373,7 @@ void __stdcall glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenu if ((target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE) || (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0)) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } gl::Context *context = gl::getNonLostContext(); @@ -2391,28 +2395,39 @@ void __stdcall glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenu if (!framebuffer || (framebufferHandle == 0 && renderbuffer != 0)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } - switch (attachment) + if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) { - case GL_COLOR_ATTACHMENT0: - framebuffer->setColorbuffer(GL_RENDERBUFFER, renderbuffer); - break; - case GL_DEPTH_ATTACHMENT: - framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer); - break; - case GL_STENCIL_ATTACHMENT: - framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer); - break; - default: - return error(GL_INVALID_ENUM); + const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT); + + if (colorAttachment >= context->getMaximumRenderTargets()) + { + return gl::error(GL_INVALID_VALUE); + } + + framebuffer->setColorbuffer(colorAttachment, GL_RENDERBUFFER, renderbuffer); + } + else + { + switch (attachment) + { + case GL_DEPTH_ATTACHMENT: + framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer); + break; + case GL_STENCIL_ATTACHMENT: + framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer); + break; + default: + return gl::error(GL_INVALID_ENUM); + } } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2425,23 +2440,34 @@ void __stdcall glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum t { if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE) { - return error(GL_INVALID_ENUM); - } - - switch (attachment) - { - case GL_COLOR_ATTACHMENT0: - case GL_DEPTH_ATTACHMENT: - case GL_STENCIL_ATTACHMENT: - break; - default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } gl::Context *context = gl::getNonLostContext(); if (context) { + if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) + { + const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT); + + if (colorAttachment >= context->getMaximumRenderTargets()) + { + return gl::error(GL_INVALID_VALUE); + } + } + else + { + switch (attachment) + { + case GL_DEPTH_ATTACHMENT: + case GL_STENCIL_ATTACHMENT: + break; + default: + return gl::error(GL_INVALID_ENUM); + } + } + if (texture == 0) { textarget = GL_NONE; @@ -2452,7 +2478,7 @@ void __stdcall glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum t if (tex == NULL) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } switch (textarget) @@ -2461,12 +2487,12 @@ void __stdcall glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum t { if (tex->getTarget() != GL_TEXTURE_2D) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } gl::Texture2D *tex2d = static_cast(tex); if (tex2d->isCompressed(0)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } break; } @@ -2480,23 +2506,23 @@ void __stdcall glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum t { if (tex->getTarget() != GL_TEXTURE_CUBE_MAP) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } gl::TextureCubeMap *texcube = static_cast(tex); if (texcube->isCompressed(textarget, level)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } break; } default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if (level != 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } } @@ -2515,20 +2541,33 @@ void __stdcall glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum t if (framebufferHandle == 0 || !framebuffer) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } - switch (attachment) + if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) { - case GL_COLOR_ATTACHMENT0: framebuffer->setColorbuffer(textarget, texture); break; - case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture); break; - case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture); break; + const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT); + + if (colorAttachment >= context->getMaximumRenderTargets()) + { + return gl::error(GL_INVALID_VALUE); + } + + framebuffer->setColorbuffer(colorAttachment, textarget, texture); + } + else + { + switch (attachment) + { + case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture); break; + case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture); break; + } } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2552,12 +2591,12 @@ void __stdcall glFrontFace(GLenum mode) } break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2569,7 +2608,7 @@ void __stdcall glGenBuffers(GLsizei n, GLuint* buffers) { if (n < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -2584,7 +2623,7 @@ void __stdcall glGenBuffers(GLsizei n, GLuint* buffers) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2606,11 +2645,11 @@ void __stdcall glGenerateMipmap(GLenum target) if (tex2d->isCompressed(0)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (tex2d->isDepth(0)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } tex2d->generateMipmaps(); @@ -2623,7 +2662,7 @@ void __stdcall glGenerateMipmap(GLenum target) if (texcube->isCompressed(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } texcube->generateMipmaps(); @@ -2631,13 +2670,13 @@ void __stdcall glGenerateMipmap(GLenum target) } default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2649,7 +2688,7 @@ void __stdcall glGenFencesNV(GLsizei n, GLuint* fences) { if (n < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -2664,7 +2703,7 @@ void __stdcall glGenFencesNV(GLsizei n, GLuint* fences) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2676,7 +2715,7 @@ void __stdcall glGenFramebuffers(GLsizei n, GLuint* framebuffers) { if (n < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -2691,7 +2730,7 @@ void __stdcall glGenFramebuffers(GLsizei n, GLuint* framebuffers) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2703,7 +2742,7 @@ void __stdcall glGenQueriesEXT(GLsizei n, GLuint* ids) { if (n < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -2718,7 +2757,7 @@ void __stdcall glGenQueriesEXT(GLsizei n, GLuint* ids) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2730,7 +2769,7 @@ void __stdcall glGenRenderbuffers(GLsizei n, GLuint* renderbuffers) { if (n < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -2745,7 +2784,7 @@ void __stdcall glGenRenderbuffers(GLsizei n, GLuint* renderbuffers) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2757,7 +2796,7 @@ void __stdcall glGenTextures(GLsizei n, GLuint* textures) { if (n < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -2772,7 +2811,7 @@ void __stdcall glGenTextures(GLsizei n, GLuint* textures) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2786,7 +2825,7 @@ void __stdcall glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, { if (bufsize < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -2799,17 +2838,17 @@ void __stdcall glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, { if (context->getShader(program)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } else { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } } if (index >= (GLuint)programObject->getActiveAttributeCount()) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } programObject->getActiveAttribute(index, bufsize, length, size, type, name); @@ -2817,7 +2856,7 @@ void __stdcall glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2831,7 +2870,7 @@ void __stdcall glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, { if (bufsize < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -2844,17 +2883,17 @@ void __stdcall glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, { if (context->getShader(program)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } else { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } } if (index >= (GLuint)programObject->getActiveUniformCount()) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } programObject->getActiveUniform(index, bufsize, length, size, type, name); @@ -2862,7 +2901,7 @@ void __stdcall glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2875,7 +2914,7 @@ void __stdcall glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* c { if (maxcount < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -2888,11 +2927,11 @@ void __stdcall glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* c { if (context->getShader(program)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } else { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } } @@ -2901,7 +2940,7 @@ void __stdcall glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* c } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2922,18 +2961,18 @@ int __stdcall glGetAttribLocation(GLuint program, const GLchar* name) { if (context->getShader(program)) { - return error(GL_INVALID_OPERATION, -1); + return gl::error(GL_INVALID_OPERATION, -1); } else { - return error(GL_INVALID_VALUE, -1); + return gl::error(GL_INVALID_VALUE, -1); } } gl::ProgramBinary *programBinary = programObject->getProgramBinary(); if (!programObject->isLinked() || !programBinary) { - return error(GL_INVALID_OPERATION, -1); + return gl::error(GL_INVALID_OPERATION, -1); } return programBinary->getAttributeLocation(name); @@ -2941,7 +2980,7 @@ int __stdcall glGetAttribLocation(GLuint program, const GLchar* name) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY, -1); + return gl::error(GL_OUT_OF_MEMORY, -1); } return -1; @@ -2962,7 +3001,7 @@ void __stdcall glGetBooleanv(GLenum pname, GLboolean* params) GLenum nativeType; unsigned int numParams = 0; if (!context->getQueryParameterInfo(pname, &nativeType, &numParams)) - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); if (numParams == 0) return; // it is known that the pname is valid, but there are no parameters to return @@ -3006,7 +3045,7 @@ void __stdcall glGetBooleanv(GLenum pname, GLboolean* params) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -3030,13 +3069,13 @@ void __stdcall glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params case GL_ELEMENT_ARRAY_BUFFER: buffer = context->getElementArrayBuffer(); break; - default: return error(GL_INVALID_ENUM); + default: return gl::error(GL_INVALID_ENUM); } if (!buffer) { // A null buffer means that "0" is bound to the requested buffer target - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } switch (pname) @@ -3047,13 +3086,13 @@ void __stdcall glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params case GL_BUFFER_SIZE: *params = buffer->size(); break; - default: return error(GL_INVALID_ENUM); + default: return gl::error(GL_INVALID_ENUM); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -3086,7 +3125,7 @@ void __stdcall glGetFenceivNV(GLuint fence, GLenum pname, GLint *params) if (fenceObject == NULL) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } fenceObject->getFenceiv(pname, params); @@ -3094,7 +3133,7 @@ void __stdcall glGetFenceivNV(GLuint fence, GLenum pname, GLint *params) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -3113,7 +3152,7 @@ void __stdcall glGetFloatv(GLenum pname, GLfloat* params) GLenum nativeType; unsigned int numParams = 0; if (!context->getQueryParameterInfo(pname, &nativeType, &numParams)) - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); if (numParams == 0) return; // it is known that the pname is valid, but that there are no parameters to return. @@ -3154,7 +3193,7 @@ void __stdcall glGetFloatv(GLenum pname, GLfloat* params) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -3171,7 +3210,7 @@ void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attac { if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } gl::Framebuffer *framebuffer = NULL; @@ -3179,7 +3218,7 @@ void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attac { if(context->getReadFramebufferHandle() == 0) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } framebuffer = context->getReadFramebuffer(); @@ -3188,7 +3227,7 @@ void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attac { if (context->getDrawFramebufferHandle() == 0) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } framebuffer = context->getDrawFramebuffer(); @@ -3196,21 +3235,33 @@ void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attac GLenum attachmentType; GLuint attachmentHandle; - switch (attachment) + + if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) { - case GL_COLOR_ATTACHMENT0: - attachmentType = framebuffer->getColorbufferType(); - attachmentHandle = framebuffer->getColorbufferHandle(); - break; - case GL_DEPTH_ATTACHMENT: - attachmentType = framebuffer->getDepthbufferType(); - attachmentHandle = framebuffer->getDepthbufferHandle(); - break; - case GL_STENCIL_ATTACHMENT: - attachmentType = framebuffer->getStencilbufferType(); - attachmentHandle = framebuffer->getStencilbufferHandle(); - break; - default: return error(GL_INVALID_ENUM); + const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT); + + if (colorAttachment >= context->getMaximumRenderTargets()) + { + return gl::error(GL_INVALID_ENUM); + } + + attachmentType = framebuffer->getColorbufferType(colorAttachment); + attachmentHandle = framebuffer->getColorbufferHandle(colorAttachment); + } + else + { + switch (attachment) + { + case GL_DEPTH_ATTACHMENT: + attachmentType = framebuffer->getDepthbufferType(); + attachmentHandle = framebuffer->getDepthbufferHandle(); + break; + case GL_STENCIL_ATTACHMENT: + attachmentType = framebuffer->getStencilbufferType(); + attachmentHandle = framebuffer->getStencilbufferHandle(); + break; + default: return gl::error(GL_INVALID_ENUM); + } } GLenum attachmentObjectType; // Type category @@ -3240,7 +3291,7 @@ void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attac } else { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: @@ -3250,7 +3301,7 @@ void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attac } else { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: @@ -3267,17 +3318,17 @@ void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attac } else { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -3317,7 +3368,7 @@ void __stdcall glGetIntegerv(GLenum pname, GLint* params) GLenum nativeType; unsigned int numParams = 0; if (!context->getQueryParameterInfo(pname, &nativeType, &numParams)) - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); if (numParams == 0) return; // it is known that pname is valid, but there are no parameters to return @@ -3363,7 +3414,7 @@ void __stdcall glGetIntegerv(GLenum pname, GLint* params) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -3381,7 +3432,7 @@ void __stdcall glGetProgramiv(GLuint program, GLenum pname, GLint* params) if (!programObject) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } switch (pname) @@ -3417,13 +3468,13 @@ void __stdcall glGetProgramiv(GLuint program, GLenum pname, GLint* params) *params = programObject->getProgramBinaryLength(); return; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -3436,7 +3487,7 @@ void __stdcall glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* len { if (bufsize < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -3447,7 +3498,7 @@ void __stdcall glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* len if (!programObject) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } programObject->getInfoLog(bufsize, length, infolog); @@ -3455,7 +3506,7 @@ void __stdcall glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* len } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -3470,7 +3521,7 @@ void __stdcall glGetQueryivEXT(GLenum target, GLenum pname, GLint *params) case GL_CURRENT_QUERY_EXT: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } gl::Context *context = gl::getNonLostContext(); @@ -3482,7 +3533,7 @@ void __stdcall glGetQueryivEXT(GLenum target, GLenum pname, GLint *params) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -3498,7 +3549,7 @@ void __stdcall glGetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params) case GL_QUERY_RESULT_AVAILABLE_EXT: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } gl::Context *context = gl::getNonLostContext(); @@ -3508,12 +3559,12 @@ void __stdcall glGetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params) if (!queryObject) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (context->getActiveQuery(queryObject->getType()) == id) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } switch(pname) @@ -3531,7 +3582,7 @@ void __stdcall glGetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -3547,12 +3598,12 @@ void __stdcall glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* { if (target != GL_RENDERBUFFER) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if (context->getRenderbufferHandle() == 0) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } gl::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getRenderbufferHandle()); @@ -3575,17 +3626,17 @@ void __stdcall glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* } else { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -3603,7 +3654,7 @@ void __stdcall glGetShaderiv(GLuint shader, GLenum pname, GLint* params) if (!shaderObject) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } switch (pname) @@ -3627,13 +3678,13 @@ void __stdcall glGetShaderiv(GLuint shader, GLenum pname, GLint* params) *params = shaderObject->getTranslatedSourceLength(); return; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -3646,7 +3697,7 @@ void __stdcall glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* lengt { if (bufsize < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -3657,7 +3708,7 @@ void __stdcall glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* lengt if (!shaderObject) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } shaderObject->getInfoLog(bufsize, length, infolog); @@ -3665,7 +3716,7 @@ void __stdcall glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* lengt } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -3682,7 +3733,7 @@ void __stdcall glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontyp case GL_FRAGMENT_SHADER: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } switch (precisiontype) @@ -3705,12 +3756,12 @@ void __stdcall glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontyp *precision = 0; break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -3723,7 +3774,7 @@ void __stdcall glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length { if (bufsize < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -3734,7 +3785,7 @@ void __stdcall glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length if (!shaderObject) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } shaderObject->getSource(bufsize, length, source); @@ -3742,7 +3793,7 @@ void __stdcall glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -3755,7 +3806,7 @@ void __stdcall glGetTranslatedShaderSourceANGLE(GLuint shader, GLsizei bufsize, { if (bufsize < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -3766,7 +3817,7 @@ void __stdcall glGetTranslatedShaderSourceANGLE(GLuint shader, GLsizei bufsize, if (!shaderObject) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } shaderObject->getTranslatedSource(bufsize, length, source); @@ -3774,7 +3825,7 @@ void __stdcall glGetTranslatedShaderSourceANGLE(GLuint shader, GLsizei bufsize, } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -3799,12 +3850,12 @@ const GLubyte* __stdcall glGetString(GLenum name) case GL_EXTENSIONS: return (GLubyte*)((context != NULL) ? context->getExtensionString() : ""); default: - return error(GL_INVALID_ENUM, (GLubyte*)NULL); + return gl::error(GL_INVALID_ENUM, (GLubyte*)NULL); } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY, (GLubyte*)NULL); + return gl::error(GL_OUT_OF_MEMORY, (GLubyte*)NULL); } } @@ -3829,7 +3880,7 @@ void __stdcall glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params) texture = context->getTextureCubeMap(); break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } switch (pname) @@ -3855,18 +3906,18 @@ void __stdcall glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params) case GL_TEXTURE_MAX_ANISOTROPY_EXT: if (!context->supportsTextureFilterAnisotropy()) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } *params = (GLfloat)texture->getMaxAnisotropy(); break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -3891,7 +3942,7 @@ void __stdcall glGetTexParameteriv(GLenum target, GLenum pname, GLint* params) texture = context->getTextureCubeMap(); break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } switch (pname) @@ -3917,18 +3968,18 @@ void __stdcall glGetTexParameteriv(GLenum target, GLenum pname, GLint* params) case GL_TEXTURE_MAX_ANISOTROPY_EXT: if (!context->supportsTextureFilterAnisotropy()) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } *params = (GLint)texture->getMaxAnisotropy(); break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -3941,7 +3992,7 @@ void __stdcall glGetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSiz { if (bufSize < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -3950,31 +4001,31 @@ void __stdcall glGetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSiz { if (program == 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Program *programObject = context->getProgram(program); if (!programObject || !programObject->isLinked()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } gl::ProgramBinary *programBinary = programObject->getProgramBinary(); if (!programBinary) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (!programBinary->getUniformfv(location, &bufSize, params)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -3990,31 +4041,31 @@ void __stdcall glGetUniformfv(GLuint program, GLint location, GLfloat* params) { if (program == 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Program *programObject = context->getProgram(program); if (!programObject || !programObject->isLinked()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } gl::ProgramBinary *programBinary = programObject->getProgramBinary(); if (!programBinary) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (!programBinary->getUniformfv(location, NULL, params)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -4027,7 +4078,7 @@ void __stdcall glGetnUniformivEXT(GLuint program, GLint location, GLsizei bufSiz { if (bufSize < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -4036,31 +4087,31 @@ void __stdcall glGetnUniformivEXT(GLuint program, GLint location, GLsizei bufSiz { if (program == 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Program *programObject = context->getProgram(program); if (!programObject || !programObject->isLinked()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } gl::ProgramBinary *programBinary = programObject->getProgramBinary(); if (!programBinary) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (!programBinary->getUniformiv(location, &bufSize, params)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -4076,31 +4127,31 @@ void __stdcall glGetUniformiv(GLuint program, GLint location, GLint* params) { if (program == 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Program *programObject = context->getProgram(program); if (!programObject || !programObject->isLinked()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } gl::ProgramBinary *programBinary = programObject->getProgramBinary(); if (!programBinary) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (!programBinary->getUniformiv(location, NULL, params)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -4125,18 +4176,18 @@ int __stdcall glGetUniformLocation(GLuint program, const GLchar* name) { if (context->getShader(program)) { - return error(GL_INVALID_OPERATION, -1); + return gl::error(GL_INVALID_OPERATION, -1); } else { - return error(GL_INVALID_VALUE, -1); + return gl::error(GL_INVALID_VALUE, -1); } } gl::ProgramBinary *programBinary = programObject->getProgramBinary(); if (!programObject->isLinked() || !programBinary) { - return error(GL_INVALID_OPERATION, -1); + return gl::error(GL_INVALID_OPERATION, -1); } return programBinary->getUniformLocation(name); @@ -4144,7 +4195,7 @@ int __stdcall glGetUniformLocation(GLuint program, const GLchar* name) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY, -1); + return gl::error(GL_OUT_OF_MEMORY, -1); } return -1; @@ -4162,7 +4213,7 @@ void __stdcall glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params) { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } const gl::VertexAttribute &attribState = context->getVertexAttribState(index); @@ -4196,13 +4247,13 @@ void __stdcall glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params) case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE: *params = (GLfloat)attribState.mDivisor; break; - default: return error(GL_INVALID_ENUM); + default: return gl::error(GL_INVALID_ENUM); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -4218,7 +4269,7 @@ void __stdcall glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params) { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } const gl::VertexAttribute &attribState = context->getVertexAttribState(index); @@ -4253,13 +4304,13 @@ void __stdcall glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params) case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE: *params = (GLint)attribState.mDivisor; break; - default: return error(GL_INVALID_ENUM); + default: return gl::error(GL_INVALID_ENUM); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -4275,12 +4326,12 @@ void __stdcall glGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** po { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } *pointer = const_cast(context->getVertexAttribPointer(index)); @@ -4288,7 +4339,7 @@ void __stdcall glGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** po } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -4305,7 +4356,7 @@ void __stdcall glHint(GLenum target, GLenum mode) case GL_DONT_CARE: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } gl::Context *context = gl::getNonLostContext(); @@ -4318,12 +4369,12 @@ void __stdcall glHint(GLenum target, GLenum mode) if (context) context->setFragmentShaderDerivativeHint(mode); break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -4347,7 +4398,7 @@ GLboolean __stdcall glIsBuffer(GLuint buffer) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY, GL_FALSE); + return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); } return GL_FALSE; @@ -4375,13 +4426,13 @@ GLboolean __stdcall glIsEnabled(GLenum cap) case GL_BLEND: return context->isBlendEnabled(); case GL_DITHER: return context->isDitherEnabled(); default: - return error(GL_INVALID_ENUM, false); + return gl::error(GL_INVALID_ENUM, false); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY, false); + return gl::error(GL_OUT_OF_MEMORY, false); } return false; @@ -4409,7 +4460,7 @@ GLboolean __stdcall glIsFenceNV(GLuint fence) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY, GL_FALSE); + return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); } return GL_FALSE; @@ -4435,7 +4486,7 @@ GLboolean __stdcall glIsFramebuffer(GLuint framebuffer) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY, GL_FALSE); + return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); } return GL_FALSE; @@ -4461,7 +4512,7 @@ GLboolean __stdcall glIsProgram(GLuint program) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY, GL_FALSE); + return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); } return GL_FALSE; @@ -4492,7 +4543,7 @@ GLboolean __stdcall glIsQueryEXT(GLuint id) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY, GL_FALSE); + return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); } return GL_FALSE; @@ -4518,7 +4569,7 @@ GLboolean __stdcall glIsRenderbuffer(GLuint renderbuffer) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY, GL_FALSE); + return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); } return GL_FALSE; @@ -4544,7 +4595,7 @@ GLboolean __stdcall glIsShader(GLuint shader) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY, GL_FALSE); + return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); } return GL_FALSE; @@ -4570,7 +4621,7 @@ GLboolean __stdcall glIsTexture(GLuint texture) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY, GL_FALSE); + return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); } return GL_FALSE; @@ -4584,7 +4635,7 @@ void __stdcall glLineWidth(GLfloat width) { if (width <= 0.0f) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -4596,7 +4647,7 @@ void __stdcall glLineWidth(GLfloat width) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -4616,11 +4667,11 @@ void __stdcall glLinkProgram(GLuint program) { if (context->getShader(program)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } else { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } } @@ -4629,7 +4680,7 @@ void __stdcall glLinkProgram(GLuint program) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -4648,7 +4699,7 @@ void __stdcall glPixelStorei(GLenum pname, GLint param) case GL_UNPACK_ALIGNMENT: if (param != 1 && param != 2 && param != 4 && param != 8) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } context->setUnpackAlignment(param); @@ -4657,7 +4708,7 @@ void __stdcall glPixelStorei(GLenum pname, GLint param) case GL_PACK_ALIGNMENT: if (param != 1 && param != 2 && param != 4 && param != 8) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } context->setPackAlignment(param); @@ -4668,13 +4719,13 @@ void __stdcall glPixelStorei(GLenum pname, GLint param) break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -4693,7 +4744,7 @@ void __stdcall glPolygonOffset(GLfloat factor, GLfloat units) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -4709,7 +4760,7 @@ void __stdcall glReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height, { if (width < 0 || height < 0 || bufSize < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -4726,7 +4777,7 @@ void __stdcall glReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height, if (!(currentFormat == format && currentType == type) && !validReadFormatType(format, type)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } context->readPixels(x, y, width, height, format, type, &bufSize, data); @@ -4734,7 +4785,7 @@ void __stdcall glReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height, } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -4749,7 +4800,7 @@ void __stdcall glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, { if (width < 0 || height < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -4766,7 +4817,7 @@ void __stdcall glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, if (!(currentFormat == format && currentType == type) && !validReadFormatType(format, type)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } context->readPixels(x, y, width, height, format, type, NULL, pixels); @@ -4774,7 +4825,7 @@ void __stdcall glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -4788,7 +4839,7 @@ void __stdcall glReleaseShaderCompiler(void) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -4804,17 +4855,17 @@ void __stdcall glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samp case GL_RENDERBUFFER: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if (!gl::IsColorRenderable(internalformat) && !gl::IsDepthRenderable(internalformat) && !gl::IsStencilRenderable(internalformat)) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if (width < 0 || height < 0 || samples < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -4825,41 +4876,35 @@ void __stdcall glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samp height > context->getMaximumRenderbufferDimension() || samples > context->getMaxSupportedSamples()) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } GLuint handle = context->getRenderbufferHandle(); if (handle == 0) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } switch (internalformat) { case GL_DEPTH_COMPONENT16: - context->setRenderbufferStorage(new gl::Depthbuffer(width, height, samples)); - break; case GL_RGBA4: case GL_RGB5_A1: case GL_RGB565: case GL_RGB8_OES: case GL_RGBA8_OES: - context->setRenderbufferStorage(new gl::Colorbuffer(width, height, internalformat, samples)); - break; case GL_STENCIL_INDEX8: - context->setRenderbufferStorage(new gl::Stencilbuffer(width, height, samples)); - break; case GL_DEPTH24_STENCIL8_OES: - context->setRenderbufferStorage(new gl::DepthStencilbuffer(width, height, samples)); + context->setRenderbufferStorage(width, height, internalformat, samples); break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -4883,7 +4928,7 @@ void __stdcall glSampleCoverage(GLclampf value, GLboolean invert) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -4895,7 +4940,7 @@ void __stdcall glSetFenceNV(GLuint fence, GLenum condition) { if (condition != GL_ALL_COMPLETED_NV) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } gl::Context *context = gl::getNonLostContext(); @@ -4906,7 +4951,7 @@ void __stdcall glSetFenceNV(GLuint fence, GLenum condition) if (fenceObject == NULL) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } fenceObject->setFence(condition); @@ -4914,7 +4959,7 @@ void __stdcall glSetFenceNV(GLuint fence, GLenum condition) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -4926,7 +4971,7 @@ void __stdcall glScissor(GLint x, GLint y, GLsizei width, GLsizei height) { if (width < 0 || height < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context* context = gl::getNonLostContext(); @@ -4938,7 +4983,7 @@ void __stdcall glScissor(GLint x, GLint y, GLsizei width, GLsizei height) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -4951,11 +4996,11 @@ void __stdcall glShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryfor try { // No binary shader formats are supported. - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -4968,7 +5013,7 @@ void __stdcall glShaderSource(GLuint shader, GLsizei count, const GLchar** strin { if (count < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -4981,11 +5026,11 @@ void __stdcall glShaderSource(GLuint shader, GLsizei count, const GLchar** strin { if (context->getProgram(shader)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } else { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } } @@ -4994,7 +5039,7 @@ void __stdcall glShaderSource(GLuint shader, GLsizei count, const GLchar** strin } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -5016,7 +5061,7 @@ void __stdcall glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint case GL_FRONT_AND_BACK: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } switch (func) @@ -5031,7 +5076,7 @@ void __stdcall glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint case GL_NOTEQUAL: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } gl::Context *context = gl::getNonLostContext(); @@ -5051,7 +5096,7 @@ void __stdcall glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -5073,7 +5118,7 @@ void __stdcall glStencilMaskSeparate(GLenum face, GLuint mask) case GL_FRONT_AND_BACK: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } gl::Context *context = gl::getNonLostContext(); @@ -5093,7 +5138,7 @@ void __stdcall glStencilMaskSeparate(GLenum face, GLuint mask) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -5116,7 +5161,7 @@ void __stdcall glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenu case GL_FRONT_AND_BACK: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } switch (fail) @@ -5131,7 +5176,7 @@ void __stdcall glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenu case GL_DECR_WRAP: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } switch (zfail) @@ -5146,7 +5191,7 @@ void __stdcall glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenu case GL_DECR_WRAP: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } switch (zpass) @@ -5161,7 +5206,7 @@ void __stdcall glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenu case GL_DECR_WRAP: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } gl::Context *context = gl::getNonLostContext(); @@ -5181,7 +5226,7 @@ void __stdcall glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenu } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -5199,7 +5244,7 @@ GLboolean __stdcall glTestFenceNV(GLuint fence) if (fenceObject == NULL) { - return error(GL_INVALID_OPERATION, GL_TRUE); + return gl::error(GL_INVALID_OPERATION, GL_TRUE); } return fenceObject->testFence(); @@ -5207,7 +5252,7 @@ GLboolean __stdcall glTestFenceNV(GLuint fence) } catch(std::bad_alloc&) { - error(GL_OUT_OF_MEMORY); + gl::error(GL_OUT_OF_MEMORY); } return GL_TRUE; @@ -5224,12 +5269,12 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL { if (!validImageSize(level, width, height)) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (internalformat != GLint(format)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } // validate by itself (used as secondary key below) @@ -5246,7 +5291,7 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL case GL_FLOAT: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } // validate + combinations @@ -5264,7 +5309,7 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL case GL_HALF_FLOAT_OES: break; default: - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } break; case GL_RGB: @@ -5276,7 +5321,7 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL case GL_HALF_FLOAT_OES: break; default: - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } break; case GL_RGBA: @@ -5289,7 +5334,7 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL case GL_HALF_FLOAT_OES: break; default: - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } break; case GL_BGRA_EXT: @@ -5298,7 +5343,7 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL case GL_UNSIGNED_BYTE: break; default: - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } break; case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are handled below @@ -5313,7 +5358,7 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL case GL_UNSIGNED_INT: break; default: - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } break; case GL_DEPTH_STENCIL_OES: @@ -5322,16 +5367,16 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL case GL_UNSIGNED_INT_24_8_OES: break; default: - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if (border != 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -5340,7 +5385,7 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL { if (level > context->getMaximumTextureLevel()) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } switch (target) @@ -5349,7 +5394,7 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL if (width > (context->getMaximumTextureDimension() >> level) || height > (context->getMaximumTextureDimension() >> level)) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } break; case GL_TEXTURE_CUBE_MAP_POSITIVE_X: @@ -5360,17 +5405,17 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: if (width != height) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (width > (context->getMaximumCubeTextureDimension() >> level) || height > (context->getMaximumCubeTextureDimension() >> level)) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } switch (format) { @@ -5378,48 +5423,48 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: if (context->supportsDXT1Textures()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } else { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: if (context->supportsDXT3Textures()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } else { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: if (context->supportsDXT5Textures()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } else { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_DEPTH_COMPONENT: case GL_DEPTH_STENCIL_OES: if (!context->supportsDepthTextures()) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (target != GL_TEXTURE_2D) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } // OES_depth_texture supports loading depth data and multiple levels, // but ANGLE_depth_texture does not if (pixels != NULL || level != 0) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } break; default: @@ -5430,14 +5475,14 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL { if (!context->supportsFloat32Textures()) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } else if (type == GL_HALF_FLOAT_OES) { if (!context->supportsFloat16Textures()) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } @@ -5447,12 +5492,12 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL if (!texture) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (texture->isImmutable()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } texture->setImage(level, width, height, format, type, context->getUnpackAlignment(), pixels); @@ -5463,12 +5508,12 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL if (!texture) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (texture->isImmutable()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } switch (target) @@ -5498,7 +5543,7 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -5523,7 +5568,7 @@ void __stdcall glTexParameterf(GLenum target, GLenum pname, GLfloat param) texture = context->getTextureCubeMap(); break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } switch (pname) @@ -5531,51 +5576,51 @@ void __stdcall glTexParameterf(GLenum target, GLenum pname, GLfloat param) case GL_TEXTURE_WRAP_S: if (!texture->setWrapS((GLenum)param)) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_TEXTURE_WRAP_T: if (!texture->setWrapT((GLenum)param)) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_TEXTURE_MIN_FILTER: if (!texture->setMinFilter((GLenum)param)) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_TEXTURE_MAG_FILTER: if (!texture->setMagFilter((GLenum)param)) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_TEXTURE_USAGE_ANGLE: if (!texture->setUsage((GLenum)param)) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_TEXTURE_MAX_ANISOTROPY_EXT: if (!context->supportsTextureFilterAnisotropy()) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if (!texture->setMaxAnisotropy((float)param, context->getTextureMaxAnisotropy())) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -5605,7 +5650,7 @@ void __stdcall glTexParameteri(GLenum target, GLenum pname, GLint param) texture = context->getTextureCubeMap(); break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } switch (pname) @@ -5613,51 +5658,51 @@ void __stdcall glTexParameteri(GLenum target, GLenum pname, GLint param) case GL_TEXTURE_WRAP_S: if (!texture->setWrapS((GLenum)param)) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_TEXTURE_WRAP_T: if (!texture->setWrapT((GLenum)param)) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_TEXTURE_MIN_FILTER: if (!texture->setMinFilter((GLenum)param)) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_TEXTURE_MAG_FILTER: if (!texture->setMagFilter((GLenum)param)) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_TEXTURE_USAGE_ANGLE: if (!texture->setUsage((GLenum)param)) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_TEXTURE_MAX_ANISOTROPY_EXT: if (!context->supportsTextureFilterAnisotropy()) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if (!texture->setMaxAnisotropy((float)param, context->getTextureMaxAnisotropy())) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -5675,22 +5720,22 @@ void __stdcall glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalf { if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if (width < 1 || height < 1 || levels < 1) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (target == GL_TEXTURE_CUBE_MAP && width != height) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } GLenum format = gl::ExtractFormat(internalformat); @@ -5698,7 +5743,7 @@ void __stdcall glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalf if (format == GL_NONE || type == GL_NONE) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } gl::Context *context = gl::getNonLostContext(); @@ -5711,25 +5756,25 @@ void __stdcall glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalf if (width > context->getMaximumTextureDimension() || height > context->getMaximumTextureDimension()) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } break; case GL_TEXTURE_CUBE_MAP: if (width > context->getMaximumCubeTextureDimension() || height > context->getMaximumCubeTextureDimension()) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if (levels != 1 && !context->supportsNonPower2Texture()) { if (!gl::isPow2(width) || !gl::isPow2(height)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } @@ -5739,19 +5784,19 @@ void __stdcall glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalf case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: if (!context->supportsDXT1Textures()) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: if (!context->supportsDXT3Textures()) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: if (!context->supportsDXT5Textures()) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_RGBA32F_EXT: @@ -5761,7 +5806,7 @@ void __stdcall glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalf case GL_LUMINANCE_ALPHA32F_EXT: if (!context->supportsFloat32Textures()) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_RGBA16F_EXT: @@ -5771,7 +5816,7 @@ void __stdcall glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalf case GL_LUMINANCE_ALPHA16F_EXT: if (!context->supportsFloat16Textures()) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_DEPTH_COMPONENT16: @@ -5779,16 +5824,16 @@ void __stdcall glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalf case GL_DEPTH24_STENCIL8_OES: if (!context->supportsDepthTextures()) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if (target != GL_TEXTURE_2D) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } // ANGLE_depth_texture only supports 1-level textures if (levels != 1) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } break; default: @@ -5801,12 +5846,12 @@ void __stdcall glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalf if (!texture || texture->id() == 0) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (texture->isImmutable()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } texture->storage(levels, internalformat, width, height); @@ -5817,12 +5862,12 @@ void __stdcall glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalf if (!texture || texture->id() == 0) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (texture->isImmutable()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } texture->storage(levels, internalformat, width); @@ -5832,7 +5877,7 @@ void __stdcall glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalf } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -5848,17 +5893,17 @@ void __stdcall glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint { if (!gl::IsInternalTextureTarget(target)) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if (level < 0 || xoffset < 0 || yoffset < 0 || width < 0 || height < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (std::numeric_limits::max() - xoffset < width || std::numeric_limits::max() - yoffset < height) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (!checkTextureFormatType(format, type)) @@ -5872,35 +5917,35 @@ void __stdcall glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint { if (level > context->getMaximumTextureLevel()) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (format == GL_FLOAT) { if (!context->supportsFloat32Textures()) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } else if (format == GL_HALF_FLOAT_OES) { if (!context->supportsFloat16Textures()) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } else if (gl::IsDepthTexture(format)) { if (!context->supportsDepthTextures()) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if (target != GL_TEXTURE_2D) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } // OES_depth_texture supports loading depth data, but ANGLE_depth_texture does not - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (width == 0 || height == 0 || pixels == NULL) @@ -5932,7 +5977,7 @@ void __stdcall glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -5949,7 +5994,7 @@ void __stdcall glUniform1fv(GLint location, GLsizei count, const GLfloat* v) { if (count < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (location == -1) @@ -5964,18 +6009,18 @@ void __stdcall glUniform1fv(GLint location, GLsizei count, const GLfloat* v) gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); if (!programBinary) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (!programBinary->setUniform1fv(location, count, v)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -5992,7 +6037,7 @@ void __stdcall glUniform1iv(GLint location, GLsizei count, const GLint* v) { if (count < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (location == -1) @@ -6007,18 +6052,18 @@ void __stdcall glUniform1iv(GLint location, GLsizei count, const GLint* v) gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); if (!programBinary) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (!programBinary->setUniform1iv(location, count, v)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6037,7 +6082,7 @@ void __stdcall glUniform2fv(GLint location, GLsizei count, const GLfloat* v) { if (count < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (location == -1) @@ -6052,18 +6097,18 @@ void __stdcall glUniform2fv(GLint location, GLsizei count, const GLfloat* v) gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); if (!programBinary) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (!programBinary->setUniform2fv(location, count, v)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6082,7 +6127,7 @@ void __stdcall glUniform2iv(GLint location, GLsizei count, const GLint* v) { if (count < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (location == -1) @@ -6097,18 +6142,18 @@ void __stdcall glUniform2iv(GLint location, GLsizei count, const GLint* v) gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); if (!programBinary) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (!programBinary->setUniform2iv(location, count, v)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6127,7 +6172,7 @@ void __stdcall glUniform3fv(GLint location, GLsizei count, const GLfloat* v) { if (count < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (location == -1) @@ -6142,18 +6187,18 @@ void __stdcall glUniform3fv(GLint location, GLsizei count, const GLfloat* v) gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); if (!programBinary) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (!programBinary->setUniform3fv(location, count, v)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6172,7 +6217,7 @@ void __stdcall glUniform3iv(GLint location, GLsizei count, const GLint* v) { if (count < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (location == -1) @@ -6187,18 +6232,18 @@ void __stdcall glUniform3iv(GLint location, GLsizei count, const GLint* v) gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); if (!programBinary) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (!programBinary->setUniform3iv(location, count, v)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6217,7 +6262,7 @@ void __stdcall glUniform4fv(GLint location, GLsizei count, const GLfloat* v) { if (count < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (location == -1) @@ -6232,18 +6277,18 @@ void __stdcall glUniform4fv(GLint location, GLsizei count, const GLfloat* v) gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); if (!programBinary) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (!programBinary->setUniform4fv(location, count, v)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6262,7 +6307,7 @@ void __stdcall glUniform4iv(GLint location, GLsizei count, const GLint* v) { if (count < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (location == -1) @@ -6277,18 +6322,18 @@ void __stdcall glUniform4iv(GLint location, GLsizei count, const GLint* v) gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); if (!programBinary) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (!programBinary->setUniform4iv(location, count, v)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6301,7 +6346,7 @@ void __stdcall glUniformMatrix2fv(GLint location, GLsizei count, GLboolean trans { if (count < 0 || transpose != GL_FALSE) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (location == -1) @@ -6316,18 +6361,18 @@ void __stdcall glUniformMatrix2fv(GLint location, GLsizei count, GLboolean trans gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); if (!programBinary) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (!programBinary->setUniformMatrix2fv(location, count, value)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6340,7 +6385,7 @@ void __stdcall glUniformMatrix3fv(GLint location, GLsizei count, GLboolean trans { if (count < 0 || transpose != GL_FALSE) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (location == -1) @@ -6355,18 +6400,18 @@ void __stdcall glUniformMatrix3fv(GLint location, GLsizei count, GLboolean trans gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); if (!programBinary) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (!programBinary->setUniformMatrix3fv(location, count, value)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6379,7 +6424,7 @@ void __stdcall glUniformMatrix4fv(GLint location, GLsizei count, GLboolean trans { if (count < 0 || transpose != GL_FALSE) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (location == -1) @@ -6394,18 +6439,18 @@ void __stdcall glUniformMatrix4fv(GLint location, GLsizei count, GLboolean trans gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); if (!programBinary) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (!programBinary->setUniformMatrix4fv(location, count, value)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6425,17 +6470,17 @@ void __stdcall glUseProgram(GLuint program) { if (context->getShader(program)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } else { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } } if (program != 0 && !programObject->isLinked()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } context->useProgram(program); @@ -6443,7 +6488,7 @@ void __stdcall glUseProgram(GLuint program) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6463,11 +6508,11 @@ void __stdcall glValidateProgram(GLuint program) { if (context->getShader(program)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } else { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } } @@ -6476,7 +6521,7 @@ void __stdcall glValidateProgram(GLuint program) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6488,7 +6533,7 @@ void __stdcall glVertexAttrib1f(GLuint index, GLfloat x) { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -6501,7 +6546,7 @@ void __stdcall glVertexAttrib1f(GLuint index, GLfloat x) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6513,7 +6558,7 @@ void __stdcall glVertexAttrib1fv(GLuint index, const GLfloat* values) { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -6526,7 +6571,7 @@ void __stdcall glVertexAttrib1fv(GLuint index, const GLfloat* values) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6538,7 +6583,7 @@ void __stdcall glVertexAttrib2f(GLuint index, GLfloat x, GLfloat y) { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -6551,7 +6596,7 @@ void __stdcall glVertexAttrib2f(GLuint index, GLfloat x, GLfloat y) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6563,7 +6608,7 @@ void __stdcall glVertexAttrib2fv(GLuint index, const GLfloat* values) { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -6576,7 +6621,7 @@ void __stdcall glVertexAttrib2fv(GLuint index, const GLfloat* values) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6588,7 +6633,7 @@ void __stdcall glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z) { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -6601,7 +6646,7 @@ void __stdcall glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6613,7 +6658,7 @@ void __stdcall glVertexAttrib3fv(GLuint index, const GLfloat* values) { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -6626,7 +6671,7 @@ void __stdcall glVertexAttrib3fv(GLuint index, const GLfloat* values) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6638,7 +6683,7 @@ void __stdcall glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, G { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -6651,7 +6696,7 @@ void __stdcall glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, G } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6663,7 +6708,7 @@ void __stdcall glVertexAttrib4fv(GLuint index, const GLfloat* values) { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -6675,7 +6720,7 @@ void __stdcall glVertexAttrib4fv(GLuint index, const GLfloat* values) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6687,7 +6732,7 @@ void __stdcall glVertexAttribDivisorANGLE(GLuint index, GLuint divisor) { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -6699,7 +6744,7 @@ void __stdcall glVertexAttribDivisorANGLE(GLuint index, GLuint divisor) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6713,12 +6758,12 @@ void __stdcall glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLbo { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (size < 1 || size > 4) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } switch (type) @@ -6731,12 +6776,12 @@ void __stdcall glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLbo case GL_FLOAT: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if (stride < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -6748,7 +6793,7 @@ void __stdcall glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLbo } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6760,7 +6805,7 @@ void __stdcall glViewport(GLint x, GLint y, GLsizei width, GLsizei height) { if (width < 0 || height < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -6772,7 +6817,7 @@ void __stdcall glViewport(GLint x, GLint y, GLsizei width, GLsizei height) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6791,18 +6836,18 @@ void __stdcall glBlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLi case GL_NEAREST: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0) { ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation"); - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } gl::Context *context = gl::getNonLostContext(); @@ -6812,7 +6857,7 @@ void __stdcall glBlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLi if (context->getReadFramebufferHandle() == context->getDrawFramebufferHandle()) { ERR("Blits with the same source and destination framebuffer are not supported by this implementation."); - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask); @@ -6820,7 +6865,7 @@ void __stdcall glBlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLi } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6838,7 +6883,7 @@ void __stdcall glTexImage3DOES(GLenum target, GLint level, GLenum internalformat } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6858,19 +6903,19 @@ void __stdcall glGetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *l if (!programObject || !programObject->isLinked()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } gl::ProgramBinary *programBinary = programObject->getProgramBinary(); if (!programBinary) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (!programBinary->save(binary, bufSize, length)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } *binaryFormat = GL_PROGRAM_BINARY_ANGLE; @@ -6878,7 +6923,7 @@ void __stdcall glGetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *l } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6896,14 +6941,14 @@ void __stdcall glProgramBinaryOES(GLuint program, GLenum binaryFormat, { if (binaryFormat != GL_PROGRAM_BINARY_ANGLE) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } gl::Program *programObject = context->getProgram(program); if (!programObject) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } context->setProgramBinary(program, binary, length); @@ -6911,7 +6956,65 @@ void __stdcall glProgramBinaryOES(GLuint program, GLenum binaryFormat, } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); + } +} + +void __stdcall glDrawBuffersEXT(GLsizei n, const GLenum *bufs) +{ + EVENT("(GLenum n = %d, bufs = 0x%0.8p)", n, bufs); + + try + { + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (n < 0 || (unsigned int)n > context->getMaximumRenderTargets()) + { + return gl::error(GL_INVALID_VALUE); + } + + if (context->getDrawFramebufferHandle() == 0) + { + if (n != 1) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (bufs[0] != GL_NONE && bufs[0] != GL_BACK) + { + return gl::error(GL_INVALID_OPERATION); + } + } + else + { + for (int colorAttachment = 0; colorAttachment < n; colorAttachment++) + { + const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment; + if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment) + { + return gl::error(GL_INVALID_OPERATION); + } + } + } + + gl::Framebuffer *framebuffer = context->getDrawFramebuffer(); + + for (int colorAttachment = 0; colorAttachment < n; colorAttachment++) + { + framebuffer->setDrawBufferState(colorAttachment, bufs[colorAttachment]); + } + + for (int colorAttachment = n; colorAttachment < (int)context->getMaximumRenderTargets(); colorAttachment++) + { + framebuffer->setDrawBufferState(colorAttachment, GL_NONE); + } + } + } + catch (std::bad_alloc&) + { + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6948,13 +7051,14 @@ __eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char * {"glEndQueryEXT", (__eglMustCastToProperFunctionPointerType)glEndQueryEXT}, {"glGetQueryivEXT", (__eglMustCastToProperFunctionPointerType)glGetQueryivEXT}, {"glGetQueryObjectuivEXT", (__eglMustCastToProperFunctionPointerType)glGetQueryObjectuivEXT}, + {"glDrawBuffersEXT", (__eglMustCastToProperFunctionPointerType)glDrawBuffersEXT}, {"glVertexAttribDivisorANGLE", (__eglMustCastToProperFunctionPointerType)glVertexAttribDivisorANGLE}, {"glDrawArraysInstancedANGLE", (__eglMustCastToProperFunctionPointerType)glDrawArraysInstancedANGLE}, {"glDrawElementsInstancedANGLE", (__eglMustCastToProperFunctionPointerType)glDrawElementsInstancedANGLE}, {"glGetProgramBinaryOES", (__eglMustCastToProperFunctionPointerType)glGetProgramBinaryOES}, {"glProgramBinaryOES", (__eglMustCastToProperFunctionPointerType)glProgramBinaryOES}, }; - for (int ext = 0; ext < sizeof(glExtensions) / sizeof(Extension); ext++) + for (unsigned int ext = 0; ext < ArraySize(glExtensions); ext++) { if (strcmp(procname, glExtensions[ext].name) == 0) { @@ -6993,7 +7097,7 @@ bool __stdcall glBindTexImage(egl::Surface *surface) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY, false); + return gl::error(GL_OUT_OF_MEMORY, false); } return true; diff --git a/gfx/angle/src/libGLESv2/libGLESv2.def b/gfx/angle/src/libGLESv2/libGLESv2.def index 30a32c9254a0..591d78cd34f0 100644 --- a/gfx/angle/src/libGLESv2/libGLESv2.def +++ b/gfx/angle/src/libGLESv2/libGLESv2.def @@ -172,6 +172,7 @@ EXPORTS glDrawElementsInstancedANGLE @174 glProgramBinaryOES @175 glGetProgramBinaryOES @176 + glDrawBuffersEXT @179 ; EGL dependencies glCreateContext @144 NONAME @@ -185,3 +186,5 @@ EXPORTS ; so we explicitly add aliases for APIs used by EGL. glGetProcAddress@4=glGetProcAddress glBindTexImage@4=glBindTexImage + glCreateRenderer @177 NONAME + glDestroyRenderer @178 NONAME \ No newline at end of file diff --git a/gfx/angle/src/libGLESv2/libGLESv2.vcxproj b/gfx/angle/src/libGLESv2/libGLESv2.vcxproj deleted file mode 100644 index 8352d2215ff0..000000000000 --- a/gfx/angle/src/libGLESv2/libGLESv2.vcxproj +++ /dev/null @@ -1,303 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {B5871A7A-968C-42E3-A33B-981E6F448E78} - libGLESv2 - Win32Proj - - - - DynamicLibrary - Unicode - true - - - DynamicLibrary - Unicode - - - DynamicLibrary - Unicode - true - - - DynamicLibrary - Unicode - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.40219.1 - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - true - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - false - $(SolutionDir)$(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ - true - $(SolutionDir)$(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ - false - $(IncludePath) - $(LibraryPath) - $(IncludePath) - $(LibraryPath) - $(IncludePath) - $(IncludePath) - $(LibraryPath) - $(LibraryPath) - - - - Disabled - $(ProjectDir)/..; $(ProjectDir)/../../include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBGLESV2_EXPORTS;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - - - Level4 - true - EditAndContinue - 4100;4127;4189;4239;4244;4245;4512;4702;%(DisableSpecificWarnings) - - - d3d9.lib;%(AdditionalDependencies) - libGLESv2.def - true - Windows - false - - - MachineX86 - - - %40echo on -mkdir "$(ProjectDir)..\..\lib\$(Configuration)\" -copy "$(OutDir)libGLESv2.dll" "$(ProjectDir)..\..\lib\$(Configuration)\" -copy "$(OutDir)libGLESv2.lib" "$(ProjectDir)..\..\lib\$(Configuration)\" -%40echo off - - - - - - MaxSpeed - AnySuitable - $(ProjectDir)/..; $(ProjectDir)/../../include;%(AdditionalIncludeDirectories) - ANGLE_DISABLE_TRACE;WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBGLESV2_EXPORTS;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;_SECURE_SCL=0;%(PreprocessorDefinitions) - MultiThreaded - - - Level4 - true - ProgramDatabase - 4100;4127;4189;4239;4244;4245;4512;4702;4718;%(DisableSpecificWarnings) - - - d3d9.lib;%(AdditionalDependencies) - false - libGLESv2.def - true - Windows - true - true - false - - - MachineX86 - - - %40echo on -mkdir "$(ProjectDir)..\..\lib\$(Configuration)\" -copy "$(OutDir)libGLESv2.dll" "$(ProjectDir)..\..\lib\$(Configuration)\" -copy "$(OutDir)libGLESv2.lib" "$(ProjectDir)..\..\lib\$(Configuration)\" -%40echo off - - - - - - X64 - - - Disabled - $(ProjectDir)/..; $(ProjectDir)/../../include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBGLESV2_EXPORTS;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - - - Level4 - 4100;4127;4189;4239;4244;4245;4512;4702;4718;%(DisableSpecificWarnings) - ProgramDatabase - true - - - d3d9.lib;%(AdditionalDependencies) - libGLESv2.def - true - Windows - false - - - MachineX64 - - - %40echo on -mkdir "$(ProjectDir)..\..\lib\$(Configuration)\" -copy "$(OutDir)libGLESv2.dll" "$(ProjectDir)..\..\lib\$(Configuration)\" -copy "$(OutDir)libGLESv2.lib" "$(ProjectDir)..\..\lib\$(Configuration)\" -%40echo off - - - - - - X64 - - - MaxSpeed - AnySuitable - $(ProjectDir)/..; $(ProjectDir)/../../include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBGLESV2_EXPORTS;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;_SECURE_SCL=0;%(PreprocessorDefinitions) - MultiThreaded - - - Level4 - 4100;4127;4189;4239;4244;4245;4512;4702;4718;%(DisableSpecificWarnings) - ProgramDatabase - true - - - d3d9.lib;%(AdditionalDependencies) - false - libGLESv2.def - true - Windows - true - true - false - - - MachineX64 - - - %40echo on -mkdir "$(ProjectDir)..\..\lib\$(Configuration)\" -copy "$(OutDir)libGLESv2.dll" "$(ProjectDir)..\..\lib\$(Configuration)\" -copy "$(OutDir)libGLESv2.lib" "$(ProjectDir)..\..\lib\$(Configuration)\" -%40echo off - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {5620f0e4-6c43-49bc-a178-b804e1a0c3a7} - false - true - false - true - true - - - - - - \ No newline at end of file diff --git a/gfx/angle/src/libGLESv2/libGLESv2.vcxproj.filters b/gfx/angle/src/libGLESv2/libGLESv2.vcxproj.filters deleted file mode 100644 index dafea3b162eb..000000000000 --- a/gfx/angle/src/libGLESv2/libGLESv2.vcxproj.filters +++ /dev/null @@ -1,184 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - - - - \ No newline at end of file diff --git a/gfx/angle/src/libGLESv2/main.cpp b/gfx/angle/src/libGLESv2/main.cpp index 6e678c2616ca..6d7a241340f9 100644 --- a/gfx/angle/src/libGLESv2/main.cpp +++ b/gfx/angle/src/libGLESv2/main.cpp @@ -1,3 +1,4 @@ +#include "precompiled.h" // // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -7,12 +8,8 @@ // main.cpp: DLL entry point and management of thread-local data. #include "libGLESv2/main.h" -#include "libGLESv2/utilities.h" -#include "common/debug.h" -#include "libEGL/Surface.h" - -#include "libGLESv2/Framebuffer.h" +#include "libGLESv2/Context.h" static DWORD currentTLS = TLS_OUT_OF_INDEXES; @@ -83,7 +80,7 @@ void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface) if (context && display && surface) { - context->makeCurrent(display, surface); + context->makeCurrent(surface); } } @@ -102,7 +99,7 @@ Context *getNonLostContext() { if (context->isContextLost()) { - error(GL_OUT_OF_MEMORY); + gl::error(GL_OUT_OF_MEMORY); return NULL; } else @@ -120,27 +117,6 @@ egl::Display *getDisplay() return current->display; } -IDirect3DDevice9 *getDevice() -{ - egl::Display *display = getDisplay(); - - return display->getDevice(); -} - -bool checkDeviceLost(HRESULT errorCode) -{ - egl::Display *display = NULL; - - if (isDeviceLostError(errorCode)) - { - display = gl::getDisplay(); - display->notifyDeviceLost(); - return true; - } - return false; -} -} - // Records an error code void error(GLenum errorCode) { @@ -174,3 +150,6 @@ void error(GLenum errorCode) } } } + +} + diff --git a/gfx/angle/src/libGLESv2/main.h b/gfx/angle/src/libGLESv2/main.h index 504848aa6587..196afaeab67e 100644 --- a/gfx/angle/src/libGLESv2/main.h +++ b/gfx/angle/src/libGLESv2/main.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -9,17 +9,19 @@ #ifndef LIBGLESV2_MAIN_H_ #define LIBGLESV2_MAIN_H_ -#define GL_APICALL -#include -#include - #include "common/debug.h" -#include "libEGL/Display.h" +#include "common/system.h" -#include "libGLESv2/Context.h" +namespace egl +{ +class Display; +class Surface; +} namespace gl { +class Context; + struct Current { Context *context; @@ -32,11 +34,6 @@ Context *getContext(); Context *getNonLostContext(); egl::Display *getDisplay(); -IDirect3DDevice9 *getDevice(); - -bool checkDeviceLost(HRESULT errorCode); -} - void error(GLenum errorCode); template @@ -47,4 +44,25 @@ const T &error(GLenum errorCode, const T &returnValue) return returnValue; } +} + +namespace rx +{ +class Renderer; +} + +extern "C" +{ +// Exported functions for use by EGL +gl::Context *glCreateContext(const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess); +void glDestroyContext(gl::Context *context); +void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface); +gl::Context *glGetCurrentContext(); +rx::Renderer *glCreateRenderer(egl::Display *display, HDC hDc, EGLNativeDisplayType displayId); +void glDestroyRenderer(rx::Renderer *renderer); + +__eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char *procname); +bool __stdcall glBindTexImage(egl::Surface *surface); +} + #endif // LIBGLESV2_MAIN_H_ diff --git a/gfx/angle/src/libGLESv2/mathutil.h b/gfx/angle/src/libGLESv2/mathutil.h index abeee909024c..bb48b94eaf71 100644 --- a/gfx/angle/src/libGLESv2/mathutil.h +++ b/gfx/angle/src/libGLESv2/mathutil.h @@ -10,9 +10,9 @@ #define LIBGLESV2_MATHUTIL_H_ #include -#include #include "common/system.h" +#include "common/debug.h" namespace gl { @@ -55,7 +55,8 @@ inline unsigned int ceilPow2(unsigned int x) template inline T clamp(T x, MIN min, MAX max) { - return x < min ? min : (x > max ? max : x); + // Since NaNs fail all comparison tests, a NaN value will default to min + return x > min ? (x > max ? max : x) : min; } inline float clamp01(float x) @@ -143,4 +144,18 @@ float float16ToFloat32(unsigned short h); } +namespace rx +{ + +struct Range +{ + Range() {} + Range(int lo, int hi) : start(lo), end(hi) { ASSERT(lo <= hi); } + + int start; + int end; +}; + +} + #endif // LIBGLESV2_MATHUTIL_H_ diff --git a/gfx/angle/src/libGLESv2/moz.build b/gfx/angle/src/libGLESv2/moz.build index 96b10e458e17..c26405eebc80 100644 --- a/gfx/angle/src/libGLESv2/moz.build +++ b/gfx/angle/src/libGLESv2/moz.build @@ -6,93 +6,175 @@ MODULE = 'libglesv2' +# Target: 'preprocessor' +# src/compiler/preprocessor: CPP_SOURCES += [ - 'ArrayBoundsClamper.cpp', - 'Blit.cpp', - 'Buffer.cpp', - 'BuiltInFunctionEmulator.cpp', - 'CodeGenHLSL.cpp', - 'Compiler.cpp', - 'Context.cpp', - 'D3DConstantTable.cpp', - 'DependencyGraph.cpp', - 'DependencyGraphBuilder.cpp', - 'DependencyGraphOutput.cpp', - 'DependencyGraphTraverse.cpp', - 'DetectDiscontinuity.cpp', - 'DetectRecursion.cpp', - 'Diagnostics.cpp', 'DiagnosticsBase.cpp', - 'DirectiveHandler.cpp', 'DirectiveHandlerBase.cpp', 'DirectiveParser.cpp', 'ExpressionParser.cpp', - 'Fence.cpp', - 'Float16ToFloat32.cpp', + 'Input.cpp', + 'Lexer.cpp', + 'Macro.cpp', + 'MacroExpander.cpp', + 'Preprocessor.cpp', + 'Token.cpp', + 'Tokenizer.cpp', +] + + +# Target: 'translator_common' +# Requires: 'preprocessor' +# src/compiler: +CPP_SOURCES += [ + 'BuiltInFunctionEmulator.cpp', + 'Compiler.cpp', + 'compiler_debug.cpp', + 'DetectCallDepth.cpp', + 'Diagnostics.cpp', + 'DirectiveHandler.cpp', 'ForLoopUnroll.cpp', - 'Framebuffer.cpp', - 'HandleAllocator.cpp', - 'IndexDataManager.cpp', + 'glslang_lex.cpp', + 'glslang_tab.cpp', 'InfoSink.cpp', 'Initialize.cpp', 'InitializeDll.cpp', 'InitializeParseContext.cpp', - 'Input.cpp', - 'IntermTraverse.cpp', 'Intermediate.cpp', - 'Lexer.cpp', - 'Macro.cpp', - 'MacroExpander.cpp', + 'intermOut.cpp', + 'IntermTraverse.cpp', 'MapLongVariableNames.cpp', - 'OutputHLSL.cpp', + 'parseConst.cpp', 'ParseHelper.cpp', 'PoolAlloc.cpp', - 'Preprocessor.cpp', - 'Program.cpp', - 'ProgramBinary.cpp', 'QualifierAlive.cpp', - 'Query.cpp', - 'RefCountObject.cpp', 'RemoveTree.cpp', - 'Renderbuffer.cpp', - 'ResourceManager.cpp', - 'RestrictFragmentShaderTiming.cpp', - 'RestrictVertexShaderTiming.cpp', - 'SearchSymbol.cpp', - 'Shader.cpp', - 'ShaderLang.cpp', 'SymbolTable.cpp', - 'Texture.cpp', - 'TextureSSE2.cpp', - 'Token.cpp', - 'Tokenizer.cpp', - 'TranslatorHLSL.cpp', - 'UnfoldShortCircuit.cpp', + 'CompilerUniform.cpp', + 'util.cpp', 'ValidateLimitations.cpp', 'VariableInfo.cpp', 'VariablePacker.cpp', - 'VertexDataManager.cpp', - 'compiler_debug.cpp', - 'debug.cpp', - 'glslang_lex.cpp', - 'glslang_tab.cpp', - 'intermOut.cpp', - 'libGLESv2.cpp', - 'main.cpp', - 'parseConst.cpp', - 'spooky.cpp', - 'util.cpp', - 'utilities.cpp', +] + +# src/compiler/depgraph: +CPP_SOURCES += [ + 'DependencyGraph.cpp', + 'DependencyGraphBuilder.cpp', + 'DependencyGraphOutput.cpp', + 'DependencyGraphTraverse.cpp', +] + +# src/compiler/timing: +CPP_SOURCES += [ + 'RestrictFragmentShaderTiming.cpp', + 'RestrictVertexShaderTiming.cpp', +] + +# src/third_party/compiler: +CPP_SOURCES += [ + 'ArrayBoundsClamper.cpp', +] + +# src/third_party/murmurhash: +CPP_SOURCES += [ + 'MurmurHash3.cpp', ] if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': CPP_SOURCES += [ - 'ossource_win.cpp' + 'ossource_win.cpp', ] else: CPP_SOURCES += [ - 'ossource_posix.cpp' + 'ossource_posix.cpp', ] -LIBRARY_NAME = 'libGLESv2' +# Target: 'translator_hlsl' +# Requires: 'translator_common' +# src/compiler: +CPP_SOURCES += [ + 'ShaderLang.cpp', + 'DetectDiscontinuity.cpp', + 'CodeGenHLSL.cpp', + 'OutputHLSL.cpp', + 'TranslatorHLSL.cpp', + 'UnfoldShortCircuit.cpp', + 'SearchSymbol.cpp', +] + + +# Target: 'libGLESv2' +# Requires: 'translator_hlsl' +# src/common: +CPP_SOURCES += [ + 'debug.cpp', + 'RefCountObject.cpp', +] + +# src/libGLESv2: +CPP_SOURCES += [ + 'precompiled.cpp', + 'Buffer.cpp', + 'Context.cpp', + 'Fence.cpp', + 'Float16ToFloat32.cpp', + 'Framebuffer.cpp', + 'HandleAllocator.cpp', + 'libGLESv2.cpp', + 'main.cpp', + 'Program.cpp', + 'ProgramBinary.cpp', + 'Query.cpp', + 'Renderbuffer.cpp', + 'ResourceManager.cpp', + 'Shader.cpp', + 'Texture.cpp', + 'Uniform.cpp', + 'utilities.cpp', +] + +# src/libGLESv2/renderer: +CPP_SOURCES += [ + 'Blit.cpp', + 'BufferStorage.cpp', + 'BufferStorage9.cpp', + 'BufferStorage11.cpp', + 'Fence9.cpp', + 'Fence11.cpp', + 'Image.cpp', + 'Image11.cpp', + 'Image9.cpp', + 'ImageSSE2.cpp', + 'IndexBuffer.cpp', + 'IndexBuffer9.cpp', + 'IndexBuffer11.cpp', + 'IndexDataManager.cpp', + 'IndexRangeCache.cpp', + 'InputLayoutCache.cpp', + 'Query9.cpp', + 'Query11.cpp', + 'Renderer.cpp', + 'Renderer11.cpp', + 'renderer11_utils.cpp', + 'Renderer9.cpp', + 'renderer9_utils.cpp', + 'RenderStateCache.cpp', + 'RenderTarget11.cpp', + 'RenderTarget9.cpp', + 'ShaderExecutable9.cpp', + 'ShaderExecutable11.cpp', + 'SwapChain9.cpp', + 'SwapChain11.cpp', + 'TextureStorage.cpp', + 'TextureStorage11.cpp', + 'TextureStorage9.cpp', + 'VertexBuffer.cpp', + 'VertexBuffer9.cpp', + 'VertexBuffer11.cpp', + 'VertexDataManager.cpp', + 'VertexDeclarationCache.cpp', +] + +LIBRARY_NAME = 'libGLESv2' diff --git a/gfx/angle/src/libGLESv2/precompiled.cpp b/gfx/angle/src/libGLESv2/precompiled.cpp new file mode 100644 index 000000000000..2621cd6ce3e2 --- /dev/null +++ b/gfx/angle/src/libGLESv2/precompiled.cpp @@ -0,0 +1,9 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// precompiled.cpp: Precompiled header source file for libGLESv2. + +#include "precompiled.h" diff --git a/gfx/angle/src/libGLESv2/precompiled.h b/gfx/angle/src/libGLESv2/precompiled.h new file mode 100644 index 000000000000..f62e71b35f68 --- /dev/null +++ b/gfx/angle/src/libGLESv2/precompiled.h @@ -0,0 +1,42 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// precompiled.h: Precompiled header file for libGLESv2. + +#define GL_APICALL +#include +#include + +#define EGLAPI +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // for std::min and std::max +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifdef _MSC_VER +#include +#endif diff --git a/gfx/angle/src/libGLESv2/Blit.cpp b/gfx/angle/src/libGLESv2/renderer/Blit.cpp similarity index 70% rename from gfx/angle/src/libGLESv2/Blit.cpp rename to gfx/angle/src/libGLESv2/renderer/Blit.cpp index 70071964ca4a..2a3ce39c6324 100644 --- a/gfx/angle/src/libGLESv2/Blit.cpp +++ b/gfx/angle/src/libGLESv2/renderer/Blit.cpp @@ -1,3 +1,4 @@ +#include "precompiled.h" // // Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -6,20 +7,23 @@ // Blit.cpp: Surface copy utility class. -#include "libGLESv2/Blit.h" - -#include "common/debug.h" +#include "libGLESv2/renderer/Blit.h" #include "libGLESv2/main.h" -#include "libGLESv2/utilities.h" +#include "libGLESv2/renderer/renderer9_utils.h" +#include "libGLESv2/renderer/TextureStorage9.h" +#include "libGLESv2/renderer/RenderTarget9.h" +#include "libGLESv2/renderer/Renderer9.h" +#include "libGLESv2/Framebuffer.h" +#include "libGLESv2/Renderbuffer.h" namespace { -#include "libGLESv2/shaders/standardvs.h" -#include "libGLESv2/shaders/flipyvs.h" -#include "libGLESv2/shaders/passthroughps.h" -#include "libGLESv2/shaders/luminanceps.h" -#include "libGLESv2/shaders/componentmaskps.h" +#include "libGLESv2/renderer/shaders/compiled/standardvs.h" +#include "libGLESv2/renderer/shaders/compiled/flipyvs.h" +#include "libGLESv2/renderer/shaders/compiled/passthroughps.h" +#include "libGLESv2/renderer/shaders/compiled/luminanceps.h" +#include "libGLESv2/renderer/shaders/compiled/componentmaskps.h" const BYTE* const g_shaderCode[] = { @@ -40,10 +44,10 @@ const size_t g_shaderSize[] = }; } -namespace gl +namespace rx { -Blit::Blit(Context *context) - : mContext(context), mQuadVertexBuffer(NULL), mQuadVertexDeclaration(NULL), mSavedStateBlock(NULL), mSavedRenderTarget(NULL), mSavedDepthStencil(NULL) +Blit::Blit(rx::Renderer9 *renderer) + : mRenderer(renderer), mQuadVertexBuffer(NULL), mQuadVertexDeclaration(NULL), mSavedStateBlock(NULL), mSavedRenderTarget(NULL), mSavedDepthStencil(NULL) { initGeometry(); memset(mCompiledShaders, 0, sizeof(mCompiledShaders)); @@ -74,14 +78,14 @@ void Blit::initGeometry() 1, 1 }; - IDirect3DDevice9 *device = getDevice(); + IDirect3DDevice9 *device = mRenderer->getDevice(); HRESULT result = device->CreateVertexBuffer(sizeof(quad), D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &mQuadVertexBuffer, NULL); if (FAILED(result)) { ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } void *lockPtr = NULL; @@ -90,7 +94,7 @@ void Blit::initGeometry() if (FAILED(result) || lockPtr == NULL) { ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } memcpy(lockPtr, quad, sizeof(quad)); @@ -107,17 +111,16 @@ void Blit::initGeometry() if (FAILED(result)) { ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } template bool Blit::setShader(ShaderId source, const char *profile, - D3DShaderType *(egl::Display::*createShader)(const DWORD *, size_t length), + D3DShaderType *(rx::Renderer9::*createShader)(const DWORD *, size_t length), HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*)) { - egl::Display *display = getDisplay(); - IDirect3DDevice9 *device = display->getDevice(); + IDirect3DDevice9 *device = mRenderer->getDevice(); D3DShaderType *shader; @@ -130,7 +133,7 @@ bool Blit::setShader(ShaderId source, const char *profile, const BYTE* shaderCode = g_shaderCode[source]; size_t shaderSize = g_shaderSize[source]; - shader = (display->*createShader)(reinterpret_cast(shaderCode), shaderSize); + shader = (mRenderer->*createShader)(reinterpret_cast(shaderCode), shaderSize); if (!shader) { ERR("Failed to create shader for blit operation"); @@ -153,12 +156,12 @@ bool Blit::setShader(ShaderId source, const char *profile, bool Blit::setVertexShader(ShaderId shader) { - return setShader(shader, "vs_2_0", &egl::Display::createVertexShader, &IDirect3DDevice9::SetVertexShader); + return setShader(shader, "vs_2_0", &rx::Renderer9::createVertexShader, &IDirect3DDevice9::SetVertexShader); } bool Blit::setPixelShader(ShaderId shader) { - return setShader(shader, "ps_2_0", &egl::Display::createPixelShader, &IDirect3DDevice9::SetPixelShader); + return setShader(shader, "ps_2_0", &rx::Renderer9::createPixelShader, &IDirect3DDevice9::SetPixelShader); } RECT Blit::getSurfaceRect(IDirect3DSurface9 *surface) const @@ -183,7 +186,7 @@ bool Blit::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest) return false; } - IDirect3DDevice9 *device = getDevice(); + IDirect3DDevice9 *device = mRenderer->getDevice(); saveState(); @@ -208,9 +211,86 @@ bool Blit::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest) return true; } +bool Blit::copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level) +{ + RenderTarget9 *renderTarget = NULL; + IDirect3DSurface9 *source = NULL; + gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(0); + + if (colorbuffer) + { + renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget()); + } + + if (renderTarget) + { + source = renderTarget->getSurface(); + } + + if (!source) + { + ERR("Failed to retrieve the render target."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage->getStorageInstance()); + IDirect3DSurface9 *destSurface = storage9->getSurfaceLevel(level, true); + bool result = false; + + if (destSurface) + { + result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface); + destSurface->Release(); + } + + source->Release(); + return result; +} + +bool Blit::copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level) +{ + RenderTarget9 *renderTarget = NULL; + IDirect3DSurface9 *source = NULL; + gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(0); + + if (colorbuffer) + { + renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget()); + } + + if (renderTarget) + { + source = renderTarget->getSurface(); + } + + if (!source) + { + ERR("Failed to retrieve the render target."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage->getStorageInstance()); + IDirect3DSurface9 *destSurface = storage9->getCubeMapSurface(target, level, true); + bool result = false; + + if (destSurface) + { + result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface); + destSurface->Release(); + } + + source->Release(); + return result; +} + bool Blit::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest) { - IDirect3DDevice9 *device = getDevice(); + if (!dest) + { + return false; + } + + IDirect3DDevice9 *device = mRenderer->getDevice(); D3DSURFACE_DESC sourceDesc; D3DSURFACE_DESC destDesc; @@ -218,7 +298,7 @@ bool Blit::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFo dest->GetDesc(&destDesc); if (sourceDesc.Format == destDesc.Format && destDesc.Usage & D3DUSAGE_RENDERTARGET && - dx2es::IsFormatChannelEquivalent(destDesc.Format, destFormat)) // Can use StretchRect + d3d9_gl::IsFormatChannelEquivalent(destDesc.Format, destFormat)) // Can use StretchRect { RECT destRect = {xoffset, yoffset, xoffset + (sourceRect.right - sourceRect.left), yoffset + (sourceRect.bottom - sourceRect.top)}; HRESULT result = device->StretchRect(source, &sourceRect, dest, &destRect, D3DTEXF_POINT); @@ -226,14 +306,13 @@ bool Blit::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFo if (FAILED(result)) { ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - return error(GL_OUT_OF_MEMORY, false); + return gl::error(GL_OUT_OF_MEMORY, false); } } else { return formatConvert(source, sourceRect, destFormat, xoffset, yoffset, dest); } - return true; } @@ -245,7 +324,7 @@ bool Blit::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLen return false; } - IDirect3DDevice9 *device = getDevice(); + IDirect3DDevice9 *device = mRenderer->getDevice(); saveState(); @@ -325,7 +404,7 @@ bool Blit::setFormatConvertShaders(GLenum destFormat) break; } - getDevice()->SetPixelShaderConstantF(0, psConst0, 1); + mRenderer->getDevice()->SetPixelShaderConstantF(0, psConst0, 1); return true; } @@ -337,8 +416,7 @@ IDirect3DTexture9 *Blit::copySurfaceToTexture(IDirect3DSurface9 *surface, const return NULL; } - egl::Display *display = getDisplay(); - IDirect3DDevice9 *device = getDevice(); + IDirect3DDevice9 *device = mRenderer->getDevice(); D3DSURFACE_DESC sourceDesc; surface->GetDesc(&sourceDesc); @@ -350,7 +428,7 @@ IDirect3DTexture9 *Blit::copySurfaceToTexture(IDirect3DSurface9 *surface, const if (FAILED(result)) { ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - return error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL); + return gl::error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL); } IDirect3DSurface9 *textureSurface; @@ -360,10 +438,10 @@ IDirect3DTexture9 *Blit::copySurfaceToTexture(IDirect3DSurface9 *surface, const { ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); texture->Release(); - return error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL); + return gl::error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL); } - display->endScene(); + mRenderer->endScene(); result = device->StretchRect(surface, &sourceRect, textureSurface, NULL, D3DTEXF_NONE); textureSurface->Release(); @@ -372,7 +450,7 @@ IDirect3DTexture9 *Blit::copySurfaceToTexture(IDirect3DSurface9 *surface, const { ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); texture->Release(); - return error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL); + return gl::error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL); } return texture; @@ -380,7 +458,7 @@ IDirect3DTexture9 *Blit::copySurfaceToTexture(IDirect3DSurface9 *surface, const void Blit::setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset) { - IDirect3DDevice9 *device = getDevice(); + IDirect3DDevice9 *device = mRenderer->getDevice(); D3DVIEWPORT9 vp; vp.X = xoffset; @@ -397,7 +475,7 @@ void Blit::setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset) void Blit::setCommonBlitState() { - IDirect3DDevice9 *device = getDevice(); + IDirect3DDevice9 *device = mRenderer->getDevice(); device->SetDepthStencilSurface(NULL); @@ -419,7 +497,7 @@ void Blit::setCommonBlitState() RECT scissorRect = {0}; // Scissoring is disabled for flipping, but we need this to capture and restore the old rectangle device->SetScissorRect(&scissorRect); - for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++) + for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) { device->SetStreamSourceFreq(i, 1); } @@ -427,19 +505,18 @@ void Blit::setCommonBlitState() void Blit::render() { - egl::Display *display = getDisplay(); - IDirect3DDevice9 *device = getDevice(); + IDirect3DDevice9 *device = mRenderer->getDevice(); HRESULT hr = device->SetStreamSource(0, mQuadVertexBuffer, 0, 2 * sizeof(float)); hr = device->SetVertexDeclaration(mQuadVertexDeclaration); - display->startScene(); + mRenderer->startScene(); hr = device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); } void Blit::saveState() { - IDirect3DDevice9 *device = getDevice(); + IDirect3DDevice9 *device = mRenderer->getDevice(); HRESULT hr; @@ -491,7 +568,7 @@ void Blit::saveState() void Blit::restoreState() { - IDirect3DDevice9 *device = getDevice(); + IDirect3DDevice9 *device = mRenderer->getDevice(); device->SetDepthStencilSurface(mSavedDepthStencil); if (mSavedDepthStencil != NULL) diff --git a/gfx/angle/src/libGLESv2/Blit.h b/gfx/angle/src/libGLESv2/renderer/Blit.h similarity index 80% rename from gfx/angle/src/libGLESv2/Blit.h rename to gfx/angle/src/libGLESv2/renderer/Blit.h index a9bb4956eb7f..3718028e662d 100644 --- a/gfx/angle/src/libGLESv2/Blit.h +++ b/gfx/angle/src/libGLESv2/renderer/Blit.h @@ -9,30 +9,29 @@ #ifndef LIBGLESV2_BLIT_H_ #define LIBGLESV2_BLIT_H_ -#include - -#define GL_APICALL -#include - -#include - #include "common/angleutils.h" -#include "libEGL/Display.h" - namespace gl { -class Context; +class Framebuffer; +} + +namespace rx +{ +class Renderer9; +class TextureStorageInterface2D; +class TextureStorageInterfaceCube; class Blit { public: - explicit Blit(Context *context); + explicit Blit(Renderer9 *renderer); ~Blit(); // Copy from source surface to dest surface. // sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left) - bool copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest); + bool copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level); + bool copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level); // Copy from source surface to dest surface. // sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left) @@ -44,7 +43,7 @@ class Blit bool boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest); private: - Context *mContext; + rx::Renderer9 *mRenderer; IDirect3DVertexBuffer9 *mQuadVertexBuffer; IDirect3DVertexDeclaration9 *mQuadVertexDeclaration; @@ -53,6 +52,7 @@ class Blit bool setFormatConvertShaders(GLenum destFormat); + bool copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest); IDirect3DTexture9 *copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect); void setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset); void setCommonBlitState(); @@ -74,7 +74,7 @@ class Blit template bool setShader(ShaderId source, const char *profile, - D3DShaderType *(egl::Display::*createShader)(const DWORD *, size_t length), + D3DShaderType *(Renderer9::*createShader)(const DWORD *, size_t length), HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*)); bool setVertexShader(ShaderId shader); diff --git a/gfx/angle/src/libGLESv2/renderer/BufferStorage.cpp b/gfx/angle/src/libGLESv2/renderer/BufferStorage.cpp new file mode 100644 index 000000000000..a49b7bab8427 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/BufferStorage.cpp @@ -0,0 +1,40 @@ +#include "precompiled.h" +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// BufferStorage.cpp Defines the abstract BufferStorage class. + +#include "libGLESv2/renderer/BufferStorage.h" + +namespace rx +{ + +unsigned int BufferStorage::mNextSerial = 1; + +BufferStorage::BufferStorage() +{ + updateSerial(); +} + +BufferStorage::~BufferStorage() +{ +} + +unsigned int BufferStorage::getSerial() const +{ + return mSerial; +} + +void BufferStorage::updateSerial() +{ + mSerial = mNextSerial++; +} + +void BufferStorage::markBufferUsage() +{ +} + +} diff --git a/gfx/angle/src/libGLESv2/renderer/BufferStorage.h b/gfx/angle/src/libGLESv2/renderer/BufferStorage.h new file mode 100644 index 000000000000..ace1a11bae00 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/BufferStorage.h @@ -0,0 +1,44 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// BufferStorage.h Defines the abstract BufferStorage class. + +#ifndef LIBGLESV2_RENDERER_BUFFERSTORAGE_H_ +#define LIBGLESV2_RENDERER_BUFFERSTORAGE_H_ + +#include "common/angleutils.h" + +namespace rx +{ + +class BufferStorage +{ + public: + BufferStorage(); + virtual ~BufferStorage(); + + // The data returned is only guaranteed valid until next non-const method. + virtual void *getData() = 0; + virtual void setData(const void* data, unsigned int size, unsigned int offset) = 0; + virtual void clear() = 0; + virtual unsigned int getSize() const = 0; + virtual bool supportsDirectBinding() const = 0; + virtual void markBufferUsage(); + unsigned int getSerial() const; + + protected: + void updateSerial(); + + private: + DISALLOW_COPY_AND_ASSIGN(BufferStorage); + + unsigned int mSerial; + static unsigned int mNextSerial; +}; + +} + +#endif // LIBGLESV2_RENDERER_BUFFERSTORAGE_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/BufferStorage11.cpp b/gfx/angle/src/libGLESv2/renderer/BufferStorage11.cpp new file mode 100644 index 000000000000..3647d8a89855 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/BufferStorage11.cpp @@ -0,0 +1,358 @@ +#include "precompiled.h" +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// BufferStorage11.cpp Defines the BufferStorage11 class. + +#include "libGLESv2/renderer/BufferStorage11.h" +#include "libGLESv2/main.h" +#include "libGLESv2/renderer/Renderer11.h" + +namespace rx +{ + +BufferStorage11::BufferStorage11(Renderer11 *renderer) +{ + mRenderer = renderer; + + mStagingBuffer = NULL; + mStagingBufferSize = 0; + + mBuffer = NULL; + mBufferSize = 0; + + mSize = 0; + + mResolvedData = NULL; + mResolvedDataSize = 0; + mResolvedDataValid = false; + + mReadUsageCount = 0; + mWriteUsageCount = 0; +} + +BufferStorage11::~BufferStorage11() +{ + if (mStagingBuffer) + { + mStagingBuffer->Release(); + mStagingBuffer = NULL; + } + + if (mBuffer) + { + mBuffer->Release(); + mBuffer = NULL; + } + + if (mResolvedData) + { + free(mResolvedData); + mResolvedData = NULL; + } +} + +BufferStorage11 *BufferStorage11::makeBufferStorage11(BufferStorage *bufferStorage) +{ + ASSERT(HAS_DYNAMIC_TYPE(BufferStorage11*, bufferStorage)); + return static_cast(bufferStorage); +} + +void *BufferStorage11::getData() +{ + if (!mResolvedDataValid) + { + ID3D11Device *device = mRenderer->getDevice(); + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + HRESULT result; + + if (!mStagingBuffer || mStagingBufferSize < mBufferSize) + { + if (mStagingBuffer) + { + mStagingBuffer->Release(); + mStagingBuffer = NULL; + mStagingBufferSize = 0; + } + + D3D11_BUFFER_DESC bufferDesc; + bufferDesc.ByteWidth = mSize; + bufferDesc.Usage = D3D11_USAGE_STAGING; + bufferDesc.BindFlags = 0; + bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + bufferDesc.MiscFlags = 0; + bufferDesc.StructureByteStride = 0; + + result = device->CreateBuffer(&bufferDesc, NULL, &mStagingBuffer); + if (FAILED(result)) + { + return gl::error(GL_OUT_OF_MEMORY, (void*)NULL); + } + + mStagingBufferSize = bufferDesc.ByteWidth; + } + + if (!mResolvedData || mResolvedDataSize < mBufferSize) + { + free(mResolvedData); + mResolvedData = malloc(mSize); + mResolvedDataSize = mSize; + } + + D3D11_BOX srcBox; + srcBox.left = 0; + srcBox.right = mSize; + srcBox.top = 0; + srcBox.bottom = 1; + srcBox.front = 0; + srcBox.back = 1; + + context->CopySubresourceRegion(mStagingBuffer, 0, 0, 0, 0, mBuffer, 0, &srcBox); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + result = context->Map(mStagingBuffer, 0, D3D11_MAP_READ, 0, &mappedResource); + if (FAILED(result)) + { + return gl::error(GL_OUT_OF_MEMORY, (void*)NULL); + } + + memcpy(mResolvedData, mappedResource.pData, mSize); + + context->Unmap(mStagingBuffer, 0); + + mResolvedDataValid = true; + } + + mReadUsageCount = 0; + + return mResolvedData; +} + +void BufferStorage11::setData(const void* data, unsigned int size, unsigned int offset) +{ + ID3D11Device *device = mRenderer->getDevice(); + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + HRESULT result; + + unsigned int requiredBufferSize = size + offset; + unsigned int requiredStagingSize = size; + bool directInitialization = offset == 0 && (!mBuffer || mBufferSize < size + offset); + + if (!directInitialization) + { + if (!mStagingBuffer || mStagingBufferSize < requiredStagingSize) + { + if (mStagingBuffer) + { + mStagingBuffer->Release(); + mStagingBuffer = NULL; + mStagingBufferSize = 0; + } + + D3D11_BUFFER_DESC bufferDesc; + bufferDesc.ByteWidth = size; + bufferDesc.Usage = D3D11_USAGE_STAGING; + bufferDesc.BindFlags = 0; + bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + bufferDesc.MiscFlags = 0; + bufferDesc.StructureByteStride = 0; + + if (data) + { + D3D11_SUBRESOURCE_DATA initialData; + initialData.pSysMem = data; + initialData.SysMemPitch = size; + initialData.SysMemSlicePitch = 0; + + result = device->CreateBuffer(&bufferDesc, &initialData, &mStagingBuffer); + } + else + { + result = device->CreateBuffer(&bufferDesc, NULL, &mStagingBuffer); + } + + if (FAILED(result)) + { + return gl::error(GL_OUT_OF_MEMORY); + } + + mStagingBufferSize = size; + } + else if (data) + { + D3D11_MAPPED_SUBRESOURCE mappedResource; + result = context->Map(mStagingBuffer, 0, D3D11_MAP_WRITE, 0, &mappedResource); + if (FAILED(result)) + { + return gl::error(GL_OUT_OF_MEMORY); + } + + memcpy(mappedResource.pData, data, size); + + context->Unmap(mStagingBuffer, 0); + } + } + + if (!mBuffer || mBufferSize < size + offset) + { + D3D11_BUFFER_DESC bufferDesc; + bufferDesc.ByteWidth = requiredBufferSize; + bufferDesc.Usage = D3D11_USAGE_DEFAULT; + bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER | D3D11_BIND_INDEX_BUFFER; + bufferDesc.CPUAccessFlags = 0; + bufferDesc.MiscFlags = 0; + bufferDesc.StructureByteStride = 0; + + if (directInitialization) + { + // Since the data will fill the entire buffer (being larger than the initial size and having + // no offset), the buffer can be initialized with the data so no staging buffer is required + + // No longer need the old buffer + if (mBuffer) + { + mBuffer->Release(); + mBuffer = NULL; + mBufferSize = 0; + } + + if (data) + { + D3D11_SUBRESOURCE_DATA initialData; + initialData.pSysMem = data; + initialData.SysMemPitch = size; + initialData.SysMemSlicePitch = 0; + + result = device->CreateBuffer(&bufferDesc, &initialData, &mBuffer); + } + else + { + result = device->CreateBuffer(&bufferDesc, NULL, &mBuffer); + } + + if (FAILED(result)) + { + return gl::error(GL_OUT_OF_MEMORY); + } + } + else if (mBuffer && offset > 0) + { + // If offset is greater than zero and the buffer is non-null, need to preserve the data from + // the old buffer up to offset + ID3D11Buffer *newBuffer = NULL; + + result = device->CreateBuffer(&bufferDesc, NULL, &newBuffer); + if (FAILED(result)) + { + return gl::error(GL_OUT_OF_MEMORY); + } + + D3D11_BOX srcBox; + srcBox.left = 0; + srcBox.right = std::min(offset, mBufferSize); + srcBox.top = 0; + srcBox.bottom = 1; + srcBox.front = 0; + srcBox.back = 1; + + context->CopySubresourceRegion(newBuffer, 0, 0, 0, 0, mBuffer, 0, &srcBox); + + mBuffer->Release(); + mBuffer = newBuffer; + } + else + { + // Simple case, nothing needs to be copied from the old buffer to the new one, just create + // a new buffer + + // No longer need the old buffer + if (mBuffer) + { + mBuffer->Release(); + mBuffer = NULL; + mBufferSize = 0; + } + + // Create a new buffer for data storage + result = device->CreateBuffer(&bufferDesc, NULL, &mBuffer); + if (FAILED(result)) + { + return gl::error(GL_OUT_OF_MEMORY); + } + } + + updateSerial(); + mBufferSize = bufferDesc.ByteWidth; + } + + if (!directInitialization) + { + ASSERT(mStagingBuffer && mStagingBufferSize >= requiredStagingSize); + + // Data is already put into the staging buffer, copy it over to the data buffer + D3D11_BOX srcBox; + srcBox.left = 0; + srcBox.right = size; + srcBox.top = 0; + srcBox.bottom = 1; + srcBox.front = 0; + srcBox.back = 1; + + context->CopySubresourceRegion(mBuffer, 0, offset, 0, 0, mStagingBuffer, 0, &srcBox); + } + + mSize = std::max(mSize, offset + size); + + mWriteUsageCount = 0; + + mResolvedDataValid = false; +} + +void BufferStorage11::clear() +{ + mResolvedDataValid = false; + mSize = 0; +} + +unsigned int BufferStorage11::getSize() const +{ + return mSize; +} + +bool BufferStorage11::supportsDirectBinding() const +{ + return true; +} + +void BufferStorage11::markBufferUsage() +{ + mReadUsageCount++; + mWriteUsageCount++; + + static const unsigned int usageLimit = 5; + + if (mReadUsageCount > usageLimit && mResolvedData) + { + free(mResolvedData); + mResolvedData = NULL; + mResolvedDataSize = 0; + mResolvedDataValid = false; + } + + if (mReadUsageCount > usageLimit && mWriteUsageCount > usageLimit && mStagingBuffer) + { + mStagingBuffer->Release(); + mStagingBuffer = NULL; + mStagingBufferSize = 0; + } +} + +ID3D11Buffer *BufferStorage11::getBuffer() const +{ + return mBuffer; +} + +} diff --git a/gfx/angle/src/libGLESv2/renderer/BufferStorage11.h b/gfx/angle/src/libGLESv2/renderer/BufferStorage11.h new file mode 100644 index 000000000000..b62348b0c936 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/BufferStorage11.h @@ -0,0 +1,56 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// BufferStorage11.h Defines the BufferStorage11 class. + +#ifndef LIBGLESV2_RENDERER_BUFFERSTORAGE11_H_ +#define LIBGLESV2_RENDERER_BUFFERSTORAGE11_H_ + +#include "libGLESv2/renderer/BufferStorage.h" + +namespace rx +{ +class Renderer11; + +class BufferStorage11 : public BufferStorage +{ + public: + explicit BufferStorage11(Renderer11 *renderer); + virtual ~BufferStorage11(); + + static BufferStorage11 *makeBufferStorage11(BufferStorage *bufferStorage); + + virtual void *getData(); + virtual void setData(const void* data, unsigned int size, unsigned int offset); + virtual void clear(); + virtual unsigned int getSize() const; + virtual bool supportsDirectBinding() const; + virtual void markBufferUsage(); + + ID3D11Buffer *getBuffer() const; + + private: + Renderer11 *mRenderer; + + ID3D11Buffer *mStagingBuffer; + unsigned int mStagingBufferSize; + + ID3D11Buffer *mBuffer; + unsigned int mBufferSize; + + unsigned int mSize; + + void *mResolvedData; + unsigned int mResolvedDataSize; + bool mResolvedDataValid; + + unsigned int mReadUsageCount; + unsigned int mWriteUsageCount; +}; + +} + +#endif // LIBGLESV2_RENDERER_BUFFERSTORAGE11_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/BufferStorage9.cpp b/gfx/angle/src/libGLESv2/renderer/BufferStorage9.cpp new file mode 100644 index 000000000000..e69e7a8921e3 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/BufferStorage9.cpp @@ -0,0 +1,78 @@ +#include "precompiled.h" +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// BufferStorage9.cpp Defines the BufferStorage9 class. + +#include "libGLESv2/renderer/BufferStorage9.h" +#include "common/debug.h" + +namespace rx +{ + +BufferStorage9::BufferStorage9() +{ + mMemory = NULL; + mAllocatedSize = 0; + mSize = 0; +} + +BufferStorage9::~BufferStorage9() +{ + delete[] mMemory; +} + +BufferStorage9 *BufferStorage9::makeBufferStorage9(BufferStorage *bufferStorage) +{ + ASSERT(HAS_DYNAMIC_TYPE(BufferStorage9*, bufferStorage)); + return static_cast(bufferStorage); +} + +void *BufferStorage9::getData() +{ + return mMemory; +} + +void BufferStorage9::setData(const void* data, unsigned int size, unsigned int offset) +{ + if (!mMemory || offset + size > mAllocatedSize) + { + unsigned int newAllocatedSize = offset + size; + void *newMemory = new char[newAllocatedSize]; + + if (offset > 0 && mMemory && mAllocatedSize > 0) + { + memcpy(newMemory, mMemory, std::min(offset, mAllocatedSize)); + } + + delete[] mMemory; + mMemory = newMemory; + mAllocatedSize = newAllocatedSize; + } + + mSize = std::max(mSize, offset + size); + if (data) + { + memcpy(reinterpret_cast(mMemory) + offset, data, size); + } +} + +void BufferStorage9::clear() +{ + mSize = 0; +} + +unsigned int BufferStorage9::getSize() const +{ + return mSize; +} + +bool BufferStorage9::supportsDirectBinding() const +{ + return false; +} + +} diff --git a/gfx/angle/src/libGLESv2/renderer/BufferStorage9.h b/gfx/angle/src/libGLESv2/renderer/BufferStorage9.h new file mode 100644 index 000000000000..3e803969bc35 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/BufferStorage9.h @@ -0,0 +1,42 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// BufferStorage9.h Defines the BufferStorage9 class. + +#ifndef LIBGLESV2_RENDERER_BUFFERSTORAGE9_H_ +#define LIBGLESV2_RENDERER_BUFFERSTORAGE9_H_ + +#include "libGLESv2/renderer/BufferStorage.h" + +namespace rx +{ + +class BufferStorage9 : public BufferStorage +{ + public: + BufferStorage9(); + virtual ~BufferStorage9(); + + static BufferStorage9 *makeBufferStorage9(BufferStorage *bufferStorage); + + virtual void *getData(); + virtual void setData(const void* data, unsigned int size, unsigned int offset); + virtual void clear(); + virtual unsigned int getSize() const; + virtual bool supportsDirectBinding() const; + + private: + DISALLOW_COPY_AND_ASSIGN(BufferStorage9); + + void *mMemory; + unsigned int mAllocatedSize; + + unsigned int mSize; +}; + +} + +#endif // LIBGLESV2_RENDERER_BUFFERSTORAGE9_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/Fence11.cpp b/gfx/angle/src/libGLESv2/renderer/Fence11.cpp new file mode 100644 index 000000000000..9d11c9a0fc82 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/Fence11.cpp @@ -0,0 +1,134 @@ +#include "precompiled.h" +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Fence11.cpp: Defines the rx::Fence11 class which implements rx::FenceImpl. + +#include "libGLESv2/renderer/Fence11.h" +#include "libGLESv2/main.h" +#include "libGLESv2/renderer/Renderer11.h" + +namespace rx +{ + +Fence11::Fence11(rx::Renderer11 *renderer) +{ + mRenderer = renderer; + mQuery = NULL; +} + +Fence11::~Fence11() +{ + if (mQuery) + { + mQuery->Release(); + mQuery = NULL; + } +} + +GLboolean Fence11::isFence() +{ + // GL_NV_fence spec: + // A name returned by GenFencesNV, but not yet set via SetFenceNV, is not the name of an existing fence. + return mQuery != NULL; +} + +void Fence11::setFence(GLenum condition) +{ + if (!mQuery) + { + D3D11_QUERY_DESC queryDesc; + queryDesc.Query = D3D11_QUERY_EVENT; + queryDesc.MiscFlags = 0; + + if (FAILED(mRenderer->getDevice()->CreateQuery(&queryDesc, &mQuery))) + { + return gl::error(GL_OUT_OF_MEMORY); + } + } + + mRenderer->getDeviceContext()->End(mQuery); + + setCondition(condition); + setStatus(GL_FALSE); +} + +GLboolean Fence11::testFence() +{ + if (mQuery == NULL) + { + return gl::error(GL_INVALID_OPERATION, GL_TRUE); + } + + HRESULT result = mRenderer->getDeviceContext()->GetData(mQuery, NULL, 0, 0); + + if (mRenderer->isDeviceLost()) + { + return gl::error(GL_OUT_OF_MEMORY, GL_TRUE); + } + + ASSERT(result == S_OK || result == S_FALSE); + setStatus(result == S_OK); + return getStatus(); +} + +void Fence11::finishFence() +{ + if (mQuery == NULL) + { + return gl::error(GL_INVALID_OPERATION); + } + + while (!testFence()) + { + Sleep(0); + } +} + +void Fence11::getFenceiv(GLenum pname, GLint *params) +{ + if (mQuery == NULL) + { + return gl::error(GL_INVALID_OPERATION); + } + + switch (pname) + { + case GL_FENCE_STATUS_NV: + { + // GL_NV_fence spec: + // Once the status of a fence has been finished (via FinishFenceNV) or tested and the returned status is TRUE (via either TestFenceNV + // or GetFenceivNV querying the FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence. + if (getStatus()) + { + params[0] = GL_TRUE; + return; + } + + HRESULT result = mRenderer->getDeviceContext()->GetData(mQuery, NULL, 0, D3D11_ASYNC_GETDATA_DONOTFLUSH); + + if (mRenderer->isDeviceLost()) + { + params[0] = GL_TRUE; + return gl::error(GL_OUT_OF_MEMORY); + } + + ASSERT(result == S_OK || result == S_FALSE); + setStatus(result == S_OK); + params[0] = getStatus(); + + break; + } + case GL_FENCE_CONDITION_NV: + params[0] = getCondition(); + break; + default: + return gl::error(GL_INVALID_ENUM); + break; + } +} + +} diff --git a/gfx/angle/src/libGLESv2/renderer/Fence11.h b/gfx/angle/src/libGLESv2/renderer/Fence11.h new file mode 100644 index 000000000000..a5398bca1490 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/Fence11.h @@ -0,0 +1,39 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Fence11.h: Defines the rx::Fence11 class which implements rx::FenceImpl. + +#ifndef LIBGLESV2_RENDERER_Fence11_H_ +#define LIBGLESV2_RENDERER_Fence11_H_ + +#include "libGLESv2/renderer/FenceImpl.h" + +namespace rx +{ +class Renderer11; + +class Fence11 : public FenceImpl +{ + public: + explicit Fence11(rx::Renderer11 *renderer); + virtual ~Fence11(); + + GLboolean isFence(); + void setFence(GLenum condition); + GLboolean testFence(); + void finishFence(); + void getFenceiv(GLenum pname, GLint *params); + + private: + DISALLOW_COPY_AND_ASSIGN(Fence11); + + rx::Renderer11 *mRenderer; + ID3D11Query *mQuery; +}; + +} + +#endif // LIBGLESV2_RENDERER_FENCE11_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/Fence9.cpp b/gfx/angle/src/libGLESv2/renderer/Fence9.cpp new file mode 100644 index 000000000000..86064d7e52ba --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/Fence9.cpp @@ -0,0 +1,135 @@ +#include "precompiled.h" +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Fence9.cpp: Defines the rx::Fence9 class. + +#include "libGLESv2/renderer/Fence9.h" +#include "libGLESv2/main.h" +#include "libGLESv2/renderer/renderer9_utils.h" +#include "libGLESv2/renderer/Renderer9.h" + +namespace rx +{ + +Fence9::Fence9(rx::Renderer9 *renderer) +{ + mRenderer = renderer; + mQuery = NULL; +} + +Fence9::~Fence9() +{ + if (mQuery) + { + mRenderer->freeEventQuery(mQuery); + mQuery = NULL; + } +} + +GLboolean Fence9::isFence() +{ + // GL_NV_fence spec: + // A name returned by GenFencesNV, but not yet set via SetFenceNV, is not the name of an existing fence. + return mQuery != NULL; +} + +void Fence9::setFence(GLenum condition) +{ + if (!mQuery) + { + mQuery = mRenderer->allocateEventQuery(); + if (!mQuery) + { + return gl::error(GL_OUT_OF_MEMORY); + } + } + + HRESULT result = mQuery->Issue(D3DISSUE_END); + ASSERT(SUCCEEDED(result)); + + setCondition(condition); + setStatus(GL_FALSE); +} + +GLboolean Fence9::testFence() +{ + if (mQuery == NULL) + { + return gl::error(GL_INVALID_OPERATION, GL_TRUE); + } + + HRESULT result = mQuery->GetData(NULL, 0, D3DGETDATA_FLUSH); + + if (d3d9::isDeviceLostError(result)) + { + mRenderer->notifyDeviceLost(); + return gl::error(GL_OUT_OF_MEMORY, GL_TRUE); + } + + ASSERT(result == S_OK || result == S_FALSE); + setStatus(result == S_OK); + return getStatus(); +} + +void Fence9::finishFence() +{ + if (mQuery == NULL) + { + return gl::error(GL_INVALID_OPERATION); + } + + while (!testFence()) + { + Sleep(0); + } +} + +void Fence9::getFenceiv(GLenum pname, GLint *params) +{ + if (mQuery == NULL) + { + return gl::error(GL_INVALID_OPERATION); + } + + switch (pname) + { + case GL_FENCE_STATUS_NV: + { + // GL_NV_fence spec: + // Once the status of a fence has been finished (via FinishFenceNV) or tested and the returned status is TRUE (via either TestFenceNV + // or GetFenceivNV querying the FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence. + if (getStatus()) + { + params[0] = GL_TRUE; + return; + } + + HRESULT result = mQuery->GetData(NULL, 0, 0); + + if (d3d9::isDeviceLostError(result)) + { + params[0] = GL_TRUE; + mRenderer->notifyDeviceLost(); + return gl::error(GL_OUT_OF_MEMORY); + } + + ASSERT(result == S_OK || result == S_FALSE); + setStatus(result == S_OK); + params[0] = getStatus(); + + break; + } + case GL_FENCE_CONDITION_NV: + params[0] = getCondition(); + break; + default: + return gl::error(GL_INVALID_ENUM); + break; + } +} + +} diff --git a/gfx/angle/src/libGLESv2/renderer/Fence9.h b/gfx/angle/src/libGLESv2/renderer/Fence9.h new file mode 100644 index 000000000000..9f17641e519a --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/Fence9.h @@ -0,0 +1,39 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Fence9.h: Defines the rx::Fence9 class which implements rx::FenceImpl. + +#ifndef LIBGLESV2_RENDERER_FENCE9_H_ +#define LIBGLESV2_RENDERER_FENCE9_H_ + +#include "libGLESv2/renderer/FenceImpl.h" + +namespace rx +{ +class Renderer9; + +class Fence9 : public FenceImpl +{ + public: + explicit Fence9(rx::Renderer9 *renderer); + virtual ~Fence9(); + + GLboolean isFence(); + void setFence(GLenum condition); + GLboolean testFence(); + void finishFence(); + void getFenceiv(GLenum pname, GLint *params); + + private: + DISALLOW_COPY_AND_ASSIGN(Fence9); + + rx::Renderer9 *mRenderer; + IDirect3DQuery9 *mQuery; +}; + +} + +#endif // LIBGLESV2_RENDERER_FENCE9_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/FenceImpl.h b/gfx/angle/src/libGLESv2/renderer/FenceImpl.h new file mode 100644 index 000000000000..d7f2102a2e96 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/FenceImpl.h @@ -0,0 +1,45 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// FenceImpl.h: Defines the rx::FenceImpl class. + +#ifndef LIBGLESV2_RENDERER_FENCEIMPL_H_ +#define LIBGLESV2_RENDERER_FENCEIMPL_H_ + +#include "common/angleutils.h" + +namespace rx +{ + +class FenceImpl +{ + public: + FenceImpl() : mStatus(GL_FALSE), mCondition(GL_NONE) { }; + virtual ~FenceImpl() { }; + + virtual GLboolean isFence() = 0; + virtual void setFence(GLenum condition) = 0; + virtual GLboolean testFence() = 0; + virtual void finishFence() = 0; + virtual void getFenceiv(GLenum pname, GLint *params) = 0; + + protected: + void setStatus(GLboolean status) { mStatus = status; } + GLboolean getStatus() const { return mStatus; } + + void setCondition(GLuint condition) { mCondition = condition; } + GLuint getCondition() const { return mCondition; } + + private: + DISALLOW_COPY_AND_ASSIGN(FenceImpl); + + GLboolean mStatus; + GLenum mCondition; +}; + +} + +#endif // LIBGLESV2_RENDERER_FENCEIMPL_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/Image.cpp b/gfx/angle/src/libGLESv2/renderer/Image.cpp new file mode 100644 index 000000000000..57239ef74ffd --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/Image.cpp @@ -0,0 +1,548 @@ +#include "precompiled.h" +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Image.h: Implements the rx::Image class, an abstract base class for the +// renderer-specific classes which will define the interface to the underlying +// surfaces or resources. + +#include "libGLESv2/renderer/Image.h" + +namespace rx +{ + +Image::Image() +{ + mWidth = 0; + mHeight = 0; + mInternalFormat = GL_NONE; + mActualFormat = GL_NONE; +} + +void Image::loadAlphaDataToBGRA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const unsigned char *source = NULL; + unsigned char *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = static_cast(input) + y * inputPitch; + dest = static_cast(output) + y * outputPitch; + for (int x = 0; x < width; x++) + { + dest[4 * x + 0] = 0; + dest[4 * x + 1] = 0; + dest[4 * x + 2] = 0; + dest[4 * x + 3] = source[x]; + } + } +} + +void Image::loadAlphaDataToNative(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const unsigned char *source = NULL; + unsigned char *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = static_cast(input) + y * inputPitch; + dest = static_cast(output) + y * outputPitch; + memcpy(dest, source, width); + } +} + +void Image::loadAlphaFloatDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const float *source = NULL; + float *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast(static_cast(input) + y * inputPitch); + dest = reinterpret_cast(static_cast(output) + y * outputPitch); + for (int x = 0; x < width; x++) + { + dest[4 * x + 0] = 0; + dest[4 * x + 1] = 0; + dest[4 * x + 2] = 0; + dest[4 * x + 3] = source[x]; + } + } +} + +void Image::loadAlphaHalfFloatDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const unsigned short *source = NULL; + unsigned short *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast(static_cast(input) + y * inputPitch); + dest = reinterpret_cast(static_cast(output) + y * outputPitch); + for (int x = 0; x < width; x++) + { + dest[4 * x + 0] = 0; + dest[4 * x + 1] = 0; + dest[4 * x + 2] = 0; + dest[4 * x + 3] = source[x]; + } + } +} + +void Image::loadLuminanceDataToNativeOrBGRA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output, bool native) +{ + const unsigned char *source = NULL; + unsigned char *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = static_cast(input) + y * inputPitch; + dest = static_cast(output) + y * outputPitch; + + if (!native) // BGRA8 destination format + { + for (int x = 0; x < width; x++) + { + dest[4 * x + 0] = source[x]; + dest[4 * x + 1] = source[x]; + dest[4 * x + 2] = source[x]; + dest[4 * x + 3] = 0xFF; + } + } + else // L8 destination format + { + memcpy(dest, source, width); + } + } +} + +void Image::loadLuminanceFloatDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const float *source = NULL; + float *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast(static_cast(input) + y * inputPitch); + dest = reinterpret_cast(static_cast(output) + y * outputPitch); + for (int x = 0; x < width; x++) + { + dest[4 * x + 0] = source[x]; + dest[4 * x + 1] = source[x]; + dest[4 * x + 2] = source[x]; + dest[4 * x + 3] = 1.0f; + } + } +} + +void Image::loadLuminanceFloatDataToRGB(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const float *source = NULL; + float *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast(static_cast(input) + y * inputPitch); + dest = reinterpret_cast(static_cast(output) + y * outputPitch); + for (int x = 0; x < width; x++) + { + dest[3 * x + 0] = source[x]; + dest[3 * x + 1] = source[x]; + dest[3 * x + 2] = source[x]; + } + } +} + +void Image::loadLuminanceHalfFloatDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const unsigned short *source = NULL; + unsigned short *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast(static_cast(input) + y * inputPitch); + dest = reinterpret_cast(static_cast(output) + y * outputPitch); + for (int x = 0; x < width; x++) + { + dest[4 * x + 0] = source[x]; + dest[4 * x + 1] = source[x]; + dest[4 * x + 2] = source[x]; + dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1 + } + } +} + +void Image::loadLuminanceAlphaDataToNativeOrBGRA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output, bool native) +{ + const unsigned char *source = NULL; + unsigned char *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = static_cast(input) + y * inputPitch; + dest = static_cast(output) + y * outputPitch; + + if (!native) // BGRA8 destination format + { + for (int x = 0; x < width; x++) + { + dest[4 * x + 0] = source[2*x+0]; + dest[4 * x + 1] = source[2*x+0]; + dest[4 * x + 2] = source[2*x+0]; + dest[4 * x + 3] = source[2*x+1]; + } + } + else + { + memcpy(dest, source, width * 2); + } + } +} + +void Image::loadLuminanceAlphaFloatDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const float *source = NULL; + float *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast(static_cast(input) + y * inputPitch); + dest = reinterpret_cast(static_cast(output) + y * outputPitch); + for (int x = 0; x < width; x++) + { + dest[4 * x + 0] = source[2*x+0]; + dest[4 * x + 1] = source[2*x+0]; + dest[4 * x + 2] = source[2*x+0]; + dest[4 * x + 3] = source[2*x+1]; + } + } +} + +void Image::loadLuminanceAlphaHalfFloatDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const unsigned short *source = NULL; + unsigned short *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast(static_cast(input) + y * inputPitch); + dest = reinterpret_cast(static_cast(output) + y * outputPitch); + for (int x = 0; x < width; x++) + { + dest[4 * x + 0] = source[2*x+0]; + dest[4 * x + 1] = source[2*x+0]; + dest[4 * x + 2] = source[2*x+0]; + dest[4 * x + 3] = source[2*x+1]; + } + } +} + +void Image::loadRGBUByteDataToBGRX(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const unsigned char *source = NULL; + unsigned char *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = static_cast(input) + y * inputPitch; + dest = static_cast(output) + y * outputPitch; + for (int x = 0; x < width; x++) + { + dest[4 * x + 0] = source[x * 3 + 2]; + dest[4 * x + 1] = source[x * 3 + 1]; + dest[4 * x + 2] = source[x * 3 + 0]; + dest[4 * x + 3] = 0xFF; + } + } +} + +void Image::loadRGBUByteDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const unsigned char *source = NULL; + unsigned char *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = static_cast(input) + y * inputPitch; + dest = static_cast(output) + y * outputPitch; + for (int x = 0; x < width; x++) + { + dest[4 * x + 0] = source[x * 3 + 0]; + dest[4 * x + 1] = source[x * 3 + 1]; + dest[4 * x + 2] = source[x * 3 + 2]; + dest[4 * x + 3] = 0xFF; + } + } +} + +void Image::loadRGB565DataToBGRA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const unsigned short *source = NULL; + unsigned char *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast(static_cast(input) + y * inputPitch); + dest = static_cast(output) + y * outputPitch; + for (int x = 0; x < width; x++) + { + unsigned short rgba = source[x]; + dest[4 * x + 0] = ((rgba & 0x001F) << 3) | ((rgba & 0x001F) >> 2); + dest[4 * x + 1] = ((rgba & 0x07E0) >> 3) | ((rgba & 0x07E0) >> 9); + dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13); + dest[4 * x + 3] = 0xFF; + } + } +} + +void Image::loadRGB565DataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const unsigned short *source = NULL; + unsigned char *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast(static_cast(input) + y * inputPitch); + dest = static_cast(output) + y * outputPitch; + for (int x = 0; x < width; x++) + { + unsigned short rgba = source[x]; + dest[4 * x + 0] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13); + dest[4 * x + 1] = ((rgba & 0x07E0) >> 3) | ((rgba & 0x07E0) >> 9); + dest[4 * x + 2] = ((rgba & 0x001F) << 3) | ((rgba & 0x001F) >> 2); + dest[4 * x + 3] = 0xFF; + } + } +} + +void Image::loadRGBFloatDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const float *source = NULL; + float *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast(static_cast(input) + y * inputPitch); + dest = reinterpret_cast(static_cast(output) + y * outputPitch); + for (int x = 0; x < width; x++) + { + dest[4 * x + 0] = source[x * 3 + 0]; + dest[4 * x + 1] = source[x * 3 + 1]; + dest[4 * x + 2] = source[x * 3 + 2]; + dest[4 * x + 3] = 1.0f; + } + } +} + +void Image::loadRGBFloatDataToNative(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const float *source = NULL; + float *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast(static_cast(input) + y * inputPitch); + dest = reinterpret_cast(static_cast(output) + y * outputPitch); + memcpy(dest, source, width * 12); + } +} + +void Image::loadRGBHalfFloatDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const unsigned short *source = NULL; + unsigned short *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast(static_cast(input) + y * inputPitch); + dest = reinterpret_cast(static_cast(output) + y * outputPitch); + for (int x = 0; x < width; x++) + { + dest[4 * x + 0] = source[x * 3 + 0]; + dest[4 * x + 1] = source[x * 3 + 1]; + dest[4 * x + 2] = source[x * 3 + 2]; + dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1 + } + } +} + +void Image::loadRGBAUByteDataToBGRA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const unsigned int *source = NULL; + unsigned int *dest = NULL; + for (int y = 0; y < height; y++) + { + source = reinterpret_cast(static_cast(input) + y * inputPitch); + dest = reinterpret_cast(static_cast(output) + y * outputPitch); + + for (int x = 0; x < width; x++) + { + unsigned int rgba = source[x]; + dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00); + } + } +} + +void Image::loadRGBAUByteDataToNative(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const unsigned int *source = NULL; + unsigned int *dest = NULL; + for (int y = 0; y < height; y++) + { + source = reinterpret_cast(static_cast(input) + y * inputPitch); + dest = reinterpret_cast(static_cast(output) + y * outputPitch); + + memcpy(dest, source, width * 4); + } +} + +void Image::loadRGBA4444DataToBGRA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const unsigned short *source = NULL; + unsigned char *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast(static_cast(input) + y * inputPitch); + dest = static_cast(output) + y * outputPitch; + for (int x = 0; x < width; x++) + { + unsigned short rgba = source[x]; + dest[4 * x + 0] = ((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4); + dest[4 * x + 1] = ((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8); + dest[4 * x + 2] = ((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12); + dest[4 * x + 3] = ((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0); + } + } +} + +void Image::loadRGBA4444DataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const unsigned short *source = NULL; + unsigned char *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast(static_cast(input) + y * inputPitch); + dest = static_cast(output) + y * outputPitch; + for (int x = 0; x < width; x++) + { + unsigned short rgba = source[x]; + dest[4 * x + 0] = ((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12); + dest[4 * x + 1] = ((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8); + dest[4 * x + 2] = ((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4); + dest[4 * x + 3] = ((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0); + } + } +} + +void Image::loadRGBA5551DataToBGRA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const unsigned short *source = NULL; + unsigned char *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast(static_cast(input) + y * inputPitch); + dest = static_cast(output) + y * outputPitch; + for (int x = 0; x < width; x++) + { + unsigned short rgba = source[x]; + dest[4 * x + 0] = ((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3); + dest[4 * x + 1] = ((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8); + dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13); + dest[4 * x + 3] = (rgba & 0x0001) ? 0xFF : 0; + } + } +} + +void Image::loadRGBA5551DataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const unsigned short *source = NULL; + unsigned char *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast(static_cast(input) + y * inputPitch); + dest = static_cast(output) + y * outputPitch; + for (int x = 0; x < width; x++) + { + unsigned short rgba = source[x]; + dest[4 * x + 0] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13); + dest[4 * x + 1] = ((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8); + dest[4 * x + 2] = ((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3); + dest[4 * x + 3] = (rgba & 0x0001) ? 0xFF : 0; + } + } +} + +void Image::loadRGBAFloatDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const float *source = NULL; + float *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast(static_cast(input) + y * inputPitch); + dest = reinterpret_cast(static_cast(output) + y * outputPitch); + memcpy(dest, source, width * 16); + } +} + +void Image::loadRGBAHalfFloatDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const unsigned char *source = NULL; + unsigned char *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = static_cast(input) + y * inputPitch; + dest = static_cast(output) + y * outputPitch; + memcpy(dest, source, width * 8); + } +} + +void Image::loadBGRADataToBGRA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const unsigned char *source = NULL; + unsigned char *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = static_cast(input) + y * inputPitch; + dest = static_cast(output) + y * outputPitch; + memcpy(dest, source, width*4); + } +} + +} diff --git a/gfx/angle/src/libGLESv2/renderer/Image.h b/gfx/angle/src/libGLESv2/renderer/Image.h new file mode 100644 index 000000000000..454e83e21e63 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/Image.h @@ -0,0 +1,131 @@ +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Image.h: Defines the rx::Image class, an abstract base class for the +// renderer-specific classes which will define the interface to the underlying +// surfaces or resources. + +#ifndef LIBGLESV2_RENDERER_IMAGE_H_ +#define LIBGLESV2_RENDERER_IMAGE_H_ + +#include "common/debug.h" + +namespace gl +{ +class Framebuffer; +} + +namespace rx +{ +class Renderer; +class TextureStorageInterface2D; +class TextureStorageInterfaceCube; + +class Image +{ + public: + Image(); + virtual ~Image() {}; + + GLsizei getWidth() const { return mWidth; } + GLsizei getHeight() const { return mHeight; } + GLenum getInternalFormat() const { return mInternalFormat; } + GLenum getActualFormat() const { return mActualFormat; } + + void markDirty() {mDirty = true;} + void markClean() {mDirty = false;} + virtual bool isDirty() const = 0; + + virtual void setManagedSurface(TextureStorageInterface2D *storage, int level) {}; + virtual void setManagedSurface(TextureStorageInterfaceCube *storage, int face, int level) {}; + virtual bool updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) = 0; + virtual bool updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) = 0; + + virtual bool redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease) = 0; + + virtual bool isRenderableFormat() const = 0; + + virtual void loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + GLint unpackAlignment, const void *input) = 0; + virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + const void *input) = 0; + + virtual void copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0; + + static void loadAlphaDataToBGRA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadAlphaDataToNative(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadAlphaDataToBGRASSE2(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadAlphaFloatDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadAlphaHalfFloatDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadLuminanceDataToNativeOrBGRA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output, bool native); + static void loadLuminanceFloatDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadLuminanceFloatDataToRGB(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadLuminanceHalfFloatDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadLuminanceAlphaDataToNativeOrBGRA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output, bool native); + static void loadLuminanceAlphaFloatDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadLuminanceAlphaHalfFloatDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadRGBUByteDataToBGRX(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadRGBUByteDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadRGB565DataToBGRA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadRGB565DataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadRGBFloatDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadRGBFloatDataToNative(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadRGBHalfFloatDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadRGBAUByteDataToBGRASSE2(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadRGBAUByteDataToBGRA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadRGBAUByteDataToNative(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadRGBA4444DataToBGRA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadRGBA4444DataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadRGBA5551DataToBGRA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadRGBA5551DataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadRGBAFloatDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadRGBAHalfFloatDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadBGRADataToBGRA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + + protected: + GLsizei mWidth; + GLsizei mHeight; + GLint mInternalFormat; + GLenum mActualFormat; + + bool mDirty; + + private: + DISALLOW_COPY_AND_ASSIGN(Image); +}; + +} + +#endif // LIBGLESV2_RENDERER_IMAGE_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/Image11.cpp b/gfx/angle/src/libGLESv2/renderer/Image11.cpp new file mode 100644 index 000000000000..a46ad7566110 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/Image11.cpp @@ -0,0 +1,457 @@ +#include "precompiled.h" +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Image11.h: Implements the rx::Image11 class, which acts as the interface to +// the actual underlying resources of a Texture + +#include "libGLESv2/renderer/Renderer11.h" +#include "libGLESv2/renderer/Image11.h" +#include "libGLESv2/renderer/TextureStorage11.h" +#include "libGLESv2/Framebuffer.h" +#include "libGLESv2/Renderbuffer.h" + +#include "libGLESv2/main.h" +#include "libGLESv2/utilities.h" +#include "libGLESv2/renderer/renderer11_utils.h" +#include "libGLESv2/renderer/generatemip.h" + +namespace rx +{ + +Image11::Image11() +{ + mStagingTexture = NULL; + mRenderer = NULL; + mDXGIFormat = DXGI_FORMAT_UNKNOWN; +} + +Image11::~Image11() +{ + if (mStagingTexture) + { + mStagingTexture->Release(); + } +} + +Image11 *Image11::makeImage11(Image *img) +{ + ASSERT(HAS_DYNAMIC_TYPE(rx::Image11*, img)); + return static_cast(img); +} + +void Image11::generateMipmap(Image11 *dest, Image11 *src) +{ + ASSERT(src->getDXGIFormat() == dest->getDXGIFormat()); + ASSERT(src->getWidth() == 1 || src->getWidth() / 2 == dest->getWidth()); + ASSERT(src->getHeight() == 1 || src->getHeight() / 2 == dest->getHeight()); + + D3D11_MAPPED_SUBRESOURCE destMapped, srcMapped; + dest->map(&destMapped); + src->map(&srcMapped); + + const unsigned char *sourceData = reinterpret_cast(srcMapped.pData); + unsigned char *destData = reinterpret_cast(destMapped.pData); + + if (sourceData && destData) + { + switch (src->getDXGIFormat()) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_B8G8R8A8_UNORM: + GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); + break; + case DXGI_FORMAT_A8_UNORM: + GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); + break; + case DXGI_FORMAT_R8_UNORM: + GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); + break; + case DXGI_FORMAT_R32G32B32A32_FLOAT: + GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); + break; + case DXGI_FORMAT_R32G32B32_FLOAT: + GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); + break; + case DXGI_FORMAT_R16G16B16A16_FLOAT: + GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); + break; + case DXGI_FORMAT_R8G8_UNORM: + GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); + break; + case DXGI_FORMAT_R16_FLOAT: + GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); + break; + case DXGI_FORMAT_R16G16_FLOAT: + GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); + break; + case DXGI_FORMAT_R32_FLOAT: + GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); + break; + case DXGI_FORMAT_R32G32_FLOAT: + GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); + break; + default: + UNREACHABLE(); + break; + } + + dest->unmap(); + src->unmap(); + } + + dest->markDirty(); +} + +bool Image11::isDirty() const +{ + return (mStagingTexture && mDirty); +} + +bool Image11::updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +{ + TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage->getStorageInstance()); + return storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, 0, xoffset, yoffset, width, height); +} + +bool Image11::updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +{ + TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage->getStorageInstance()); + return storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, face, xoffset, yoffset, width, height); +} + +bool Image11::redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease) +{ + if (mWidth != width || + mHeight != height || + mInternalFormat != internalformat || + forceRelease) + { + mRenderer = Renderer11::makeRenderer11(renderer); + + mWidth = width; + mHeight = height; + mInternalFormat = internalformat; + // compute the d3d format that will be used + mDXGIFormat = gl_d3d11::ConvertTextureFormat(internalformat); + mActualFormat = d3d11_gl::ConvertTextureInternalFormat(mDXGIFormat); + + if (mStagingTexture) + { + mStagingTexture->Release(); + mStagingTexture = NULL; + } + + return true; + } + + return false; +} + +bool Image11::isRenderableFormat() const +{ + return TextureStorage11::IsTextureFormatRenderable(mDXGIFormat); +} + +DXGI_FORMAT Image11::getDXGIFormat() const +{ + // this should only happen if the image hasn't been redefined first + // which would be a bug by the caller + ASSERT(mDXGIFormat != DXGI_FORMAT_UNKNOWN); + + return mDXGIFormat; +} + +// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input +// into the target pixel rectangle. +void Image11::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + GLint unpackAlignment, const void *input) +{ + D3D11_MAPPED_SUBRESOURCE mappedImage; + HRESULT result = map(&mappedImage); + if (FAILED(result)) + { + ERR("Could not map image for loading."); + return; + } + + GLsizei inputPitch = gl::ComputePitch(width, mInternalFormat, unpackAlignment); + size_t pixelSize = d3d11::ComputePixelSizeBits(mDXGIFormat) / 8; + void* offsetMappedData = (void*)((BYTE *)mappedImage.pData + (yoffset * mappedImage.RowPitch + xoffset * pixelSize)); + + switch (mInternalFormat) + { + case GL_ALPHA8_EXT: + loadAlphaDataToNative(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); + break; + case GL_LUMINANCE8_EXT: + loadLuminanceDataToNativeOrBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData, false); + break; + case GL_ALPHA32F_EXT: + loadAlphaFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); + break; + case GL_LUMINANCE32F_EXT: + loadLuminanceFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); + break; + case GL_ALPHA16F_EXT: + loadAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); + break; + case GL_LUMINANCE16F_EXT: + loadLuminanceHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); + break; + case GL_LUMINANCE8_ALPHA8_EXT: + loadLuminanceAlphaDataToNativeOrBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData, false); + break; + case GL_LUMINANCE_ALPHA32F_EXT: + loadLuminanceAlphaFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); + break; + case GL_LUMINANCE_ALPHA16F_EXT: + loadLuminanceAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); + break; + case GL_RGB8_OES: + loadRGBUByteDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); + break; + case GL_RGB565: + loadRGB565DataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); + break; + case GL_RGBA8_OES: + loadRGBAUByteDataToNative(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); + break; + case GL_RGBA4: + loadRGBA4444DataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); + break; + case GL_RGB5_A1: + loadRGBA5551DataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); + break; + case GL_BGRA8_EXT: + loadBGRADataToBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); + break; + case GL_RGB32F_EXT: + loadRGBFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); + break; + case GL_RGB16F_EXT: + loadRGBHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); + break; + case GL_RGBA32F_EXT: + loadRGBAFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); + break; + case GL_RGBA16F_EXT: + loadRGBAHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); + break; + default: UNREACHABLE(); + } + + unmap(); +} + +void Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + const void *input) +{ + ASSERT(xoffset % 4 == 0); + ASSERT(yoffset % 4 == 0); + + D3D11_MAPPED_SUBRESOURCE mappedImage; + HRESULT result = map(&mappedImage); + if (FAILED(result)) + { + ERR("Could not map image for loading."); + return; + } + + // Size computation assumes a 4x4 block compressed texture format + size_t blockSize = d3d11::ComputeBlockSizeBits(mDXGIFormat) / 8; + void* offsetMappedData = (void*)((BYTE *)mappedImage.pData + ((yoffset / 4) * mappedImage.RowPitch + (xoffset / 4) * blockSize)); + + GLsizei inputSize = gl::ComputeCompressedSize(width, height, mInternalFormat); + GLsizei inputPitch = gl::ComputeCompressedPitch(width, mInternalFormat); + int rows = inputSize / inputPitch; + for (int i = 0; i < rows; ++i) + { + memcpy((void*)((BYTE*)offsetMappedData + i * mappedImage.RowPitch), (void*)((BYTE*)input + i * inputPitch), inputPitch); + } + + unmap(); +} + +void Image11::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) +{ + gl::Renderbuffer *colorbuffer = source->getReadColorbuffer(); + + if (colorbuffer && colorbuffer->getActualFormat() == (GLuint)mActualFormat) + { + // No conversion needed-- use copyback fastpath + ID3D11Texture2D *colorBufferTexture = NULL; + unsigned int subresourceIndex = 0; + + if (mRenderer->getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture)) + { + D3D11_TEXTURE2D_DESC textureDesc; + colorBufferTexture->GetDesc(&textureDesc); + + ID3D11Device *device = mRenderer->getDevice(); + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + ID3D11Texture2D* srcTex = NULL; + if (textureDesc.SampleDesc.Count > 1) + { + D3D11_TEXTURE2D_DESC resolveDesc; + resolveDesc.Width = textureDesc.Width; + resolveDesc.Height = textureDesc.Height; + resolveDesc.MipLevels = 1; + resolveDesc.ArraySize = 1; + resolveDesc.Format = textureDesc.Format; + resolveDesc.SampleDesc.Count = 1; + resolveDesc.SampleDesc.Quality = 0; + resolveDesc.Usage = D3D11_USAGE_DEFAULT; + resolveDesc.BindFlags = 0; + resolveDesc.CPUAccessFlags = 0; + resolveDesc.MiscFlags = 0; + + HRESULT result = device->CreateTexture2D(&resolveDesc, NULL, &srcTex); + if (FAILED(result)) + { + ERR("Failed to create resolve texture for Image11::copy, HRESULT: 0x%X.", result); + return; + } + + deviceContext->ResolveSubresource(srcTex, 0, colorBufferTexture, subresourceIndex, textureDesc.Format); + subresourceIndex = 0; + } + else + { + srcTex = colorBufferTexture; + srcTex->AddRef(); + } + + D3D11_BOX srcBox; + srcBox.left = x; + srcBox.right = x + width; + srcBox.top = y; + srcBox.bottom = y + height; + srcBox.front = 0; + srcBox.back = 1; + + deviceContext->CopySubresourceRegion(mStagingTexture, 0, xoffset, yoffset, 0, srcTex, subresourceIndex, &srcBox); + + srcTex->Release(); + colorBufferTexture->Release(); + } + } + else + { + // This format requires conversion, so we must copy the texture to staging and manually convert via readPixels + D3D11_MAPPED_SUBRESOURCE mappedImage; + HRESULT result = map(&mappedImage); + + // determine the offset coordinate into the destination buffer + GLsizei rowOffset = gl::ComputePixelSize(mActualFormat) * xoffset; + void *dataOffset = static_cast(mappedImage.pData) + mappedImage.RowPitch * yoffset + rowOffset; + + mRenderer->readPixels(source, x, y, width, height, gl::ExtractFormat(mInternalFormat), + gl::ExtractType(mInternalFormat), mappedImage.RowPitch, false, 4, dataOffset); + + unmap(); + } +} + +ID3D11Texture2D *Image11::getStagingTexture() +{ + createStagingTexture(); + + return mStagingTexture; +} + +unsigned int Image11::getStagingSubresource() +{ + createStagingTexture(); + + return mStagingSubresource; +} + +void Image11::createStagingTexture() +{ + if (mStagingTexture) + { + return; + } + + ID3D11Texture2D *newTexture = NULL; + int lodOffset = 1; + const DXGI_FORMAT dxgiFormat = getDXGIFormat(); + ASSERT(!d3d11::IsDepthStencilFormat(dxgiFormat)); // We should never get here for depth textures + + if (mWidth != 0 && mHeight != 0) + { + GLsizei width = mWidth; + GLsizei height = mHeight; + + // adjust size if needed for compressed textures + gl::MakeValidSize(false, d3d11::IsCompressed(dxgiFormat), &width, &height, &lodOffset); + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE2D_DESC desc; + desc.Width = width; + desc.Height = height; + desc.MipLevels = lodOffset + 1; + desc.ArraySize = 1; + desc.Format = dxgiFormat; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_STAGING; + desc.BindFlags = 0; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + + HRESULT result = device->CreateTexture2D(&desc, NULL, &newTexture); + + if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + ERR("Creating image failed."); + return gl::error(GL_OUT_OF_MEMORY); + } + } + + mStagingTexture = newTexture; + mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1); + mDirty = false; +} + +HRESULT Image11::map(D3D11_MAPPED_SUBRESOURCE *map) +{ + createStagingTexture(); + + HRESULT result = E_FAIL; + + if (mStagingTexture) + { + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + result = deviceContext->Map(mStagingTexture, mStagingSubresource, D3D11_MAP_WRITE, 0, map); + + // this can fail if the device is removed (from TDR) + if (d3d11::isDeviceLostError(result)) + { + mRenderer->notifyDeviceLost(); + } + else if (SUCCEEDED(result)) + { + mDirty = true; + } + } + + return result; +} + +void Image11::unmap() +{ + if (mStagingTexture) + { + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + deviceContext->Unmap(mStagingTexture, mStagingSubresource); + } +} + +} diff --git a/gfx/angle/src/libGLESv2/renderer/Image11.h b/gfx/angle/src/libGLESv2/renderer/Image11.h new file mode 100644 index 000000000000..4d5f1c178033 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/Image11.h @@ -0,0 +1,76 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Image11.h: Defines the rx::Image11 class, which acts as the interface to +// the actual underlying resources of a Texture + +#ifndef LIBGLESV2_RENDERER_IMAGE11_H_ +#define LIBGLESV2_RENDERER_IMAGE11_H_ + +#include "libGLESv2/renderer/Image.h" + +#include "common/debug.h" + +namespace gl +{ +class Framebuffer; +} + +namespace rx +{ +class Renderer; +class Renderer11; +class TextureStorageInterface2D; +class TextureStorageInterfaceCube; + +class Image11 : public Image +{ + public: + Image11(); + virtual ~Image11(); + + static Image11 *makeImage11(Image *img); + + static void generateMipmap(Image11 *dest, Image11 *src); + + virtual bool isDirty() const; + + virtual bool updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); + virtual bool updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); + + virtual bool redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease); + + virtual bool isRenderableFormat() const; + DXGI_FORMAT getDXGIFormat() const; + + virtual void loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + GLint unpackAlignment, const void *input); + virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + const void *input); + + virtual void copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); + + protected: + HRESULT map(D3D11_MAPPED_SUBRESOURCE *map); + void unmap(); + + private: + DISALLOW_COPY_AND_ASSIGN(Image11); + + ID3D11Texture2D *getStagingTexture(); + unsigned int getStagingSubresource(); + void createStagingTexture(); + + Renderer11 *mRenderer; + + DXGI_FORMAT mDXGIFormat; + ID3D11Texture2D *mStagingTexture; + unsigned int mStagingSubresource; +}; + +} + +#endif // LIBGLESV2_RENDERER_IMAGE11_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/Image9.cpp b/gfx/angle/src/libGLESv2/renderer/Image9.cpp new file mode 100644 index 000000000000..b3dcc59b6bd9 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/Image9.cpp @@ -0,0 +1,732 @@ +#include "precompiled.h" +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Image9.cpp: Implements the rx::Image9 class, which acts as the interface to +// the actual underlying surfaces of a Texture. + +#include "libGLESv2/renderer/Image9.h" + +#include "libGLESv2/main.h" +#include "libGLESv2/Framebuffer.h" +#include "libGLESv2/Renderbuffer.h" +#include "libGLESv2/renderer/Renderer9.h" +#include "libGLESv2/renderer/RenderTarget9.h" +#include "libGLESv2/renderer/TextureStorage9.h" + +#include "libGLESv2/renderer/renderer9_utils.h" +#include "libGLESv2/renderer/generatemip.h" + +namespace rx +{ + +Image9::Image9() +{ + mSurface = NULL; + mRenderer = NULL; + + mD3DPool = D3DPOOL_SYSTEMMEM; + mD3DFormat = D3DFMT_UNKNOWN; +} + +Image9::~Image9() +{ + if (mSurface) + { + mSurface->Release(); + } +} + +void Image9::generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface) +{ + D3DSURFACE_DESC destDesc; + HRESULT result = destSurface->GetDesc(&destDesc); + ASSERT(SUCCEEDED(result)); + + D3DSURFACE_DESC sourceDesc; + result = sourceSurface->GetDesc(&sourceDesc); + ASSERT(SUCCEEDED(result)); + + ASSERT(sourceDesc.Format == destDesc.Format); + ASSERT(sourceDesc.Width == 1 || sourceDesc.Width / 2 == destDesc.Width); + ASSERT(sourceDesc.Height == 1 || sourceDesc.Height / 2 == destDesc.Height); + + D3DLOCKED_RECT sourceLocked = {0}; + result = sourceSurface->LockRect(&sourceLocked, NULL, D3DLOCK_READONLY); + ASSERT(SUCCEEDED(result)); + + D3DLOCKED_RECT destLocked = {0}; + result = destSurface->LockRect(&destLocked, NULL, 0); + ASSERT(SUCCEEDED(result)); + + const unsigned char *sourceData = reinterpret_cast(sourceLocked.pBits); + unsigned char *destData = reinterpret_cast(destLocked.pBits); + + if (sourceData && destData) + { + switch (sourceDesc.Format) + { + case D3DFMT_L8: + GenerateMip(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch); + break; + case D3DFMT_A8L8: + GenerateMip(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch); + break; + case D3DFMT_A8R8G8B8: + case D3DFMT_X8R8G8B8: + GenerateMip(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch); + break; + case D3DFMT_A16B16G16R16F: + GenerateMip(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch); + break; + case D3DFMT_A32B32G32R32F: + GenerateMip(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch); + break; + default: + UNREACHABLE(); + break; + } + + destSurface->UnlockRect(); + sourceSurface->UnlockRect(); + } +} + +Image9 *Image9::makeImage9(Image *img) +{ + ASSERT(HAS_DYNAMIC_TYPE(rx::Image9*, img)); + return static_cast(img); +} + +void Image9::generateMipmap(Image9 *dest, Image9 *source) +{ + IDirect3DSurface9 *sourceSurface = source->getSurface(); + if (sourceSurface == NULL) + return gl::error(GL_OUT_OF_MEMORY); + + IDirect3DSurface9 *destSurface = dest->getSurface(); + generateMip(destSurface, sourceSurface); + + dest->markDirty(); +} + +void Image9::copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source) +{ + D3DLOCKED_RECT sourceLock = {0}; + D3DLOCKED_RECT destLock = {0}; + + source->LockRect(&sourceLock, NULL, 0); + dest->LockRect(&destLock, NULL, 0); + + if (sourceLock.pBits && destLock.pBits) + { + D3DSURFACE_DESC desc; + source->GetDesc(&desc); + + int rows = d3d9::IsCompressedFormat(desc.Format) ? desc.Height / 4 : desc.Height; + int bytes = d3d9::ComputeRowSize(desc.Format, desc.Width); + ASSERT(bytes <= sourceLock.Pitch && bytes <= destLock.Pitch); + + for(int i = 0; i < rows; i++) + { + memcpy((char*)destLock.pBits + destLock.Pitch * i, (char*)sourceLock.pBits + sourceLock.Pitch * i, bytes); + } + + source->UnlockRect(); + dest->UnlockRect(); + } + else UNREACHABLE(); +} + +bool Image9::redefine(rx::Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease) +{ + if (mWidth != width || + mHeight != height || + mInternalFormat != internalformat || + forceRelease) + { + mRenderer = Renderer9::makeRenderer9(renderer); + + mWidth = width; + mHeight = height; + mInternalFormat = internalformat; + // compute the d3d format that will be used + mD3DFormat = mRenderer->ConvertTextureInternalFormat(internalformat); + mActualFormat = d3d9_gl::GetEquivalentFormat(mD3DFormat); + + if (mSurface) + { + mSurface->Release(); + mSurface = NULL; + } + + return true; + } + + return false; +} + +void Image9::createSurface() +{ + if(mSurface) + { + return; + } + + IDirect3DTexture9 *newTexture = NULL; + IDirect3DSurface9 *newSurface = NULL; + const D3DPOOL poolToUse = D3DPOOL_SYSTEMMEM; + const D3DFORMAT d3dFormat = getD3DFormat(); + ASSERT(d3dFormat != D3DFMT_INTZ); // We should never get here for depth textures + + if (mWidth != 0 && mHeight != 0) + { + int levelToFetch = 0; + GLsizei requestWidth = mWidth; + GLsizei requestHeight = mHeight; + gl::MakeValidSize(true, gl::IsCompressed(mInternalFormat), &requestWidth, &requestHeight, &levelToFetch); + + IDirect3DDevice9 *device = mRenderer->getDevice(); + + HRESULT result = device->CreateTexture(requestWidth, requestHeight, levelToFetch + 1, 0, d3dFormat, + poolToUse, &newTexture, NULL); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + ERR("Creating image surface failed."); + return gl::error(GL_OUT_OF_MEMORY); + } + + newTexture->GetSurfaceLevel(levelToFetch, &newSurface); + newTexture->Release(); + } + + mSurface = newSurface; + mDirty = false; + mD3DPool = poolToUse; +} + +HRESULT Image9::lock(D3DLOCKED_RECT *lockedRect, const RECT *rect) +{ + createSurface(); + + HRESULT result = D3DERR_INVALIDCALL; + + if (mSurface) + { + result = mSurface->LockRect(lockedRect, rect, 0); + ASSERT(SUCCEEDED(result)); + + mDirty = true; + } + + return result; +} + +void Image9::unlock() +{ + if (mSurface) + { + HRESULT result = mSurface->UnlockRect(); + ASSERT(SUCCEEDED(result)); + } +} + +bool Image9::isRenderableFormat() const +{ + return TextureStorage9::IsTextureFormatRenderable(getD3DFormat()); +} + +D3DFORMAT Image9::getD3DFormat() const +{ + // this should only happen if the image hasn't been redefined first + // which would be a bug by the caller + ASSERT(mD3DFormat != D3DFMT_UNKNOWN); + + return mD3DFormat; +} + +IDirect3DSurface9 *Image9::getSurface() +{ + createSurface(); + + return mSurface; +} + +void Image9::setManagedSurface(TextureStorageInterface2D *storage, int level) +{ + TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage->getStorageInstance()); + setManagedSurface(storage9->getSurfaceLevel(level, false)); +} + +void Image9::setManagedSurface(TextureStorageInterfaceCube *storage, int face, int level) +{ + TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage->getStorageInstance()); + setManagedSurface(storage9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, false)); +} + +void Image9::setManagedSurface(IDirect3DSurface9 *surface) +{ + D3DSURFACE_DESC desc; + surface->GetDesc(&desc); + ASSERT(desc.Pool == D3DPOOL_MANAGED); + + if ((GLsizei)desc.Width == mWidth && (GLsizei)desc.Height == mHeight) + { + if (mSurface) + { + copyLockableSurfaces(surface, mSurface); + mSurface->Release(); + } + + mSurface = surface; + mD3DPool = desc.Pool; + } +} + +bool Image9::updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +{ + ASSERT(getSurface() != NULL); + TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage->getStorageInstance()); + return updateSurface(storage9->getSurfaceLevel(level, true), xoffset, yoffset, width, height); +} + +bool Image9::updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +{ + ASSERT(getSurface() != NULL); + TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage->getStorageInstance()); + return updateSurface(storage9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, true), xoffset, yoffset, width, height); +} + +bool Image9::updateSurface(IDirect3DSurface9 *destSurface, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +{ + if (!destSurface) + return false; + + IDirect3DSurface9 *sourceSurface = getSurface(); + + if (sourceSurface && sourceSurface != destSurface) + { + RECT rect; + rect.left = xoffset; + rect.top = yoffset; + rect.right = xoffset + width; + rect.bottom = yoffset + height; + + POINT point = {rect.left, rect.top}; + + IDirect3DDevice9 *device = mRenderer->getDevice(); + + if (mD3DPool == D3DPOOL_MANAGED) + { + D3DSURFACE_DESC desc; + sourceSurface->GetDesc(&desc); + + IDirect3DSurface9 *surf = 0; + HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL); + + if (SUCCEEDED(result)) + { + copyLockableSurfaces(surf, sourceSurface); + result = device->UpdateSurface(surf, &rect, destSurface, &point); + ASSERT(SUCCEEDED(result)); + surf->Release(); + } + } + else + { + // UpdateSurface: source must be SYSTEMMEM, dest must be DEFAULT pools + HRESULT result = device->UpdateSurface(sourceSurface, &rect, destSurface, &point); + ASSERT(SUCCEEDED(result)); + } + } + + destSurface->Release(); + return true; +} + +// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input +// into the target pixel rectangle. +void Image9::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + GLint unpackAlignment, const void *input) +{ + RECT lockRect = + { + xoffset, yoffset, + xoffset + width, yoffset + height + }; + + D3DLOCKED_RECT locked; + HRESULT result = lock(&locked, &lockRect); + if (FAILED(result)) + { + return; + } + + + GLsizei inputPitch = gl::ComputePitch(width, mInternalFormat, unpackAlignment); + + switch (mInternalFormat) + { + case GL_ALPHA8_EXT: + if (gl::supportsSSE2()) + { + loadAlphaDataToBGRASSE2(width, height, inputPitch, input, locked.Pitch, locked.pBits); + } + else + { + loadAlphaDataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits); + } + break; + case GL_LUMINANCE8_EXT: + loadLuminanceDataToNativeOrBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits, getD3DFormat() == D3DFMT_L8); + break; + case GL_ALPHA32F_EXT: + loadAlphaFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); + break; + case GL_LUMINANCE32F_EXT: + loadLuminanceFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); + break; + case GL_ALPHA16F_EXT: + loadAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); + break; + case GL_LUMINANCE16F_EXT: + loadLuminanceHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); + break; + case GL_LUMINANCE8_ALPHA8_EXT: + loadLuminanceAlphaDataToNativeOrBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits, getD3DFormat() == D3DFMT_A8L8); + break; + case GL_LUMINANCE_ALPHA32F_EXT: + loadLuminanceAlphaFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); + break; + case GL_LUMINANCE_ALPHA16F_EXT: + loadLuminanceAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); + break; + case GL_RGB8_OES: + loadRGBUByteDataToBGRX(width, height, inputPitch, input, locked.Pitch, locked.pBits); + break; + case GL_RGB565: + loadRGB565DataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits); + break; + case GL_RGBA8_OES: + if (gl::supportsSSE2()) + { + loadRGBAUByteDataToBGRASSE2(width, height, inputPitch, input, locked.Pitch, locked.pBits); + } + else + { + loadRGBAUByteDataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits); + } + break; + case GL_RGBA4: + loadRGBA4444DataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits); + break; + case GL_RGB5_A1: + loadRGBA5551DataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits); + break; + case GL_BGRA8_EXT: + loadBGRADataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits); + break; + // float textures are converted to RGBA, not BGRA, as they're stored that way in D3D + case GL_RGB32F_EXT: + loadRGBFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); + break; + case GL_RGB16F_EXT: + loadRGBHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); + break; + case GL_RGBA32F_EXT: + loadRGBAFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); + break; + case GL_RGBA16F_EXT: + loadRGBAHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); + break; + default: UNREACHABLE(); + } + + unlock(); +} + +void Image9::loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + const void *input) +{ + ASSERT(xoffset % 4 == 0); + ASSERT(yoffset % 4 == 0); + + RECT lockRect = { + xoffset, yoffset, + xoffset + width, yoffset + height + }; + + D3DLOCKED_RECT locked; + HRESULT result = lock(&locked, &lockRect); + if (FAILED(result)) + { + return; + } + + GLsizei inputSize = gl::ComputeCompressedSize(width, height, mInternalFormat); + GLsizei inputPitch = gl::ComputeCompressedPitch(width, mInternalFormat); + int rows = inputSize / inputPitch; + for (int i = 0; i < rows; ++i) + { + memcpy((void*)((BYTE*)locked.pBits + i * locked.Pitch), (void*)((BYTE*)input + i * inputPitch), inputPitch); + } + + unlock(); +} + +// This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats and incomplete textures +void Image9::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) +{ + RenderTarget9 *renderTarget = NULL; + IDirect3DSurface9 *surface = NULL; + gl::Renderbuffer *colorbuffer = source->getColorbuffer(0); + + if (colorbuffer) + { + renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget()); + } + + if (renderTarget) + { + surface = renderTarget->getSurface(); + } + + if (!surface) + { + ERR("Failed to retrieve the render target."); + return gl::error(GL_OUT_OF_MEMORY); + } + + IDirect3DDevice9 *device = mRenderer->getDevice(); + + IDirect3DSurface9 *renderTargetData = NULL; + D3DSURFACE_DESC description; + surface->GetDesc(&description); + + HRESULT result = device->CreateOffscreenPlainSurface(description.Width, description.Height, description.Format, D3DPOOL_SYSTEMMEM, &renderTargetData, NULL); + + if (FAILED(result)) + { + ERR("Could not create matching destination surface."); + surface->Release(); + return gl::error(GL_OUT_OF_MEMORY); + } + + result = device->GetRenderTargetData(surface, renderTargetData); + + if (FAILED(result)) + { + ERR("GetRenderTargetData unexpectedly failed."); + renderTargetData->Release(); + surface->Release(); + return gl::error(GL_OUT_OF_MEMORY); + } + + RECT sourceRect = {x, y, x + width, y + height}; + RECT destRect = {xoffset, yoffset, xoffset + width, yoffset + height}; + + D3DLOCKED_RECT sourceLock = {0}; + result = renderTargetData->LockRect(&sourceLock, &sourceRect, 0); + + if (FAILED(result)) + { + ERR("Failed to lock the source surface (rectangle might be invalid)."); + renderTargetData->Release(); + surface->Release(); + return gl::error(GL_OUT_OF_MEMORY); + } + + D3DLOCKED_RECT destLock = {0}; + result = lock(&destLock, &destRect); + + if (FAILED(result)) + { + ERR("Failed to lock the destination surface (rectangle might be invalid)."); + renderTargetData->UnlockRect(); + renderTargetData->Release(); + surface->Release(); + return gl::error(GL_OUT_OF_MEMORY); + } + + if (destLock.pBits && sourceLock.pBits) + { + unsigned char *source = (unsigned char*)sourceLock.pBits; + unsigned char *dest = (unsigned char*)destLock.pBits; + + switch (description.Format) + { + case D3DFMT_X8R8G8B8: + case D3DFMT_A8R8G8B8: + switch(getD3DFormat()) + { + case D3DFMT_X8R8G8B8: + case D3DFMT_A8R8G8B8: + for(int y = 0; y < height; y++) + { + memcpy(dest, source, 4 * width); + + source += sourceLock.Pitch; + dest += destLock.Pitch; + } + break; + case D3DFMT_L8: + for(int y = 0; y < height; y++) + { + for(int x = 0; x < width; x++) + { + dest[x] = source[x * 4 + 2]; + } + + source += sourceLock.Pitch; + dest += destLock.Pitch; + } + break; + case D3DFMT_A8L8: + for(int y = 0; y < height; y++) + { + for(int x = 0; x < width; x++) + { + dest[x * 2 + 0] = source[x * 4 + 2]; + dest[x * 2 + 1] = source[x * 4 + 3]; + } + + source += sourceLock.Pitch; + dest += destLock.Pitch; + } + break; + default: + UNREACHABLE(); + } + break; + case D3DFMT_R5G6B5: + switch(getD3DFormat()) + { + case D3DFMT_X8R8G8B8: + for(int y = 0; y < height; y++) + { + for(int x = 0; x < width; x++) + { + unsigned short rgb = ((unsigned short*)source)[x]; + unsigned char red = (rgb & 0xF800) >> 8; + unsigned char green = (rgb & 0x07E0) >> 3; + unsigned char blue = (rgb & 0x001F) << 3; + dest[x + 0] = blue | (blue >> 5); + dest[x + 1] = green | (green >> 6); + dest[x + 2] = red | (red >> 5); + dest[x + 3] = 0xFF; + } + + source += sourceLock.Pitch; + dest += destLock.Pitch; + } + break; + case D3DFMT_L8: + for(int y = 0; y < height; y++) + { + for(int x = 0; x < width; x++) + { + unsigned char red = source[x * 2 + 1] & 0xF8; + dest[x] = red | (red >> 5); + } + + source += sourceLock.Pitch; + dest += destLock.Pitch; + } + break; + default: + UNREACHABLE(); + } + break; + case D3DFMT_A1R5G5B5: + switch(getD3DFormat()) + { + case D3DFMT_X8R8G8B8: + for(int y = 0; y < height; y++) + { + for(int x = 0; x < width; x++) + { + unsigned short argb = ((unsigned short*)source)[x]; + unsigned char red = (argb & 0x7C00) >> 7; + unsigned char green = (argb & 0x03E0) >> 2; + unsigned char blue = (argb & 0x001F) << 3; + dest[x + 0] = blue | (blue >> 5); + dest[x + 1] = green | (green >> 5); + dest[x + 2] = red | (red >> 5); + dest[x + 3] = 0xFF; + } + + source += sourceLock.Pitch; + dest += destLock.Pitch; + } + break; + case D3DFMT_A8R8G8B8: + for(int y = 0; y < height; y++) + { + for(int x = 0; x < width; x++) + { + unsigned short argb = ((unsigned short*)source)[x]; + unsigned char red = (argb & 0x7C00) >> 7; + unsigned char green = (argb & 0x03E0) >> 2; + unsigned char blue = (argb & 0x001F) << 3; + unsigned char alpha = (signed short)argb >> 15; + dest[x + 0] = blue | (blue >> 5); + dest[x + 1] = green | (green >> 5); + dest[x + 2] = red | (red >> 5); + dest[x + 3] = alpha; + } + + source += sourceLock.Pitch; + dest += destLock.Pitch; + } + break; + case D3DFMT_L8: + for(int y = 0; y < height; y++) + { + for(int x = 0; x < width; x++) + { + unsigned char red = source[x * 2 + 1] & 0x7C; + dest[x] = (red << 1) | (red >> 4); + } + + source += sourceLock.Pitch; + dest += destLock.Pitch; + } + break; + case D3DFMT_A8L8: + for(int y = 0; y < height; y++) + { + for(int x = 0; x < width; x++) + { + unsigned char red = source[x * 2 + 1] & 0x7C; + dest[x * 2 + 0] = (red << 1) | (red >> 4); + dest[x * 2 + 1] = (signed char)source[x * 2 + 1] >> 7; + } + + source += sourceLock.Pitch; + dest += destLock.Pitch; + } + break; + default: + UNREACHABLE(); + } + break; + default: + UNREACHABLE(); + } + } + + unlock(); + renderTargetData->UnlockRect(); + + renderTargetData->Release(); + surface->Release(); + + mDirty = true; +} + +} \ No newline at end of file diff --git a/gfx/angle/src/libGLESv2/renderer/Image9.h b/gfx/angle/src/libGLESv2/renderer/Image9.h new file mode 100644 index 000000000000..2fbbca31243d --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/Image9.h @@ -0,0 +1,79 @@ +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Image9.h: Defines the rx::Image9 class, which acts as the interface to +// the actual underlying surfaces of a Texture. + +#ifndef LIBGLESV2_RENDERER_IMAGE9_H_ +#define LIBGLESV2_RENDERER_IMAGE9_H_ + +#include "libGLESv2/renderer/Image.h" +#include "common/debug.h" + +namespace gl +{ +class Framebuffer; +} + +namespace rx +{ +class Renderer; +class Renderer9; +class TextureStorageInterface2D; +class TextureStorageInterfaceCube; + +class Image9 : public Image +{ + public: + Image9(); + ~Image9(); + + static Image9 *makeImage9(Image *img); + + static void generateMipmap(Image9 *dest, Image9 *source); + static void generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface); + static void copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source); + + virtual bool redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease); + + virtual bool isRenderableFormat() const; + D3DFORMAT getD3DFormat() const; + + virtual bool isDirty() const {return mSurface && mDirty;} + IDirect3DSurface9 *getSurface(); + + virtual void setManagedSurface(TextureStorageInterface2D *storage, int level); + virtual void setManagedSurface(TextureStorageInterfaceCube *storage, int face, int level); + virtual bool updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); + virtual bool updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); + + virtual void loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + GLint unpackAlignment, const void *input); + virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + const void *input); + + virtual void copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); + + private: + DISALLOW_COPY_AND_ASSIGN(Image9); + + void createSurface(); + void setManagedSurface(IDirect3DSurface9 *surface); + bool updateSurface(IDirect3DSurface9 *dest, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); + + HRESULT lock(D3DLOCKED_RECT *lockedRect, const RECT *rect); + void unlock(); + + Renderer9 *mRenderer; + + D3DPOOL mD3DPool; // can only be D3DPOOL_SYSTEMMEM or D3DPOOL_MANAGED since it needs to be lockable. + D3DFORMAT mD3DFormat; + + IDirect3DSurface9 *mSurface; +}; +} + +#endif // LIBGLESV2_RENDERER_IMAGE9_H_ diff --git a/gfx/angle/src/libGLESv2/TextureSSE2.cpp b/gfx/angle/src/libGLESv2/renderer/ImageSSE2.cpp similarity index 85% rename from gfx/angle/src/libGLESv2/TextureSSE2.cpp rename to gfx/angle/src/libGLESv2/renderer/ImageSSE2.cpp index 48ea6643bca2..b2a90ca9611a 100644 --- a/gfx/angle/src/libGLESv2/TextureSSE2.cpp +++ b/gfx/angle/src/libGLESv2/renderer/ImageSSE2.cpp @@ -1,22 +1,22 @@ +#include "precompiled.h" // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// TextureSSE2.cpp: Implements SSE2-based functions of gl::Image class. It's +// ImageSSE2.cpp: Implements SSE2-based functions of rx::Image class. It's // in a separated file for GCC, which can enable SSE usage only per-file, // not for code blocks that use SSE2 explicitly. #include "libGLESv2/Texture.h" +#include "libGLESv2/renderer/Image.h" -#include - -namespace gl +namespace rx { -void Image::loadRGBAUByteDataSSE2(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const +void Image::loadRGBAUByteDataToBGRASSE2(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) { const unsigned int *source = NULL; unsigned int *dest = NULL; @@ -57,8 +57,8 @@ void Image::loadRGBAUByteDataSSE2(GLsizei width, GLsizei height, } } -void Image::loadAlphaDataSSE2(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const +void Image::loadAlphaDataToBGRASSE2(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) { const unsigned char *source = NULL; unsigned int *dest = NULL; diff --git a/gfx/angle/src/libGLESv2/renderer/IndexBuffer.cpp b/gfx/angle/src/libGLESv2/renderer/IndexBuffer.cpp new file mode 100644 index 000000000000..37dbd3e19529 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/IndexBuffer.cpp @@ -0,0 +1,197 @@ +#include "precompiled.h" +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// IndexBuffer.cpp: Defines the abstract IndexBuffer class and IndexBufferInterface +// class with derivations, classes that perform graphics API agnostic index buffer operations. + +#include "libGLESv2/renderer/IndexBuffer.h" +#include "libGLESv2/renderer/Renderer.h" + +namespace rx +{ + +unsigned int IndexBuffer::mNextSerial = 1; + +IndexBuffer::IndexBuffer() +{ + updateSerial(); +} + +IndexBuffer::~IndexBuffer() +{ +} + +unsigned int IndexBuffer::getSerial() const +{ + return mSerial; +} + +void IndexBuffer::updateSerial() +{ + mSerial = mNextSerial++; +} + + +IndexBufferInterface::IndexBufferInterface(Renderer *renderer, bool dynamic) : mRenderer(renderer) +{ + mIndexBuffer = renderer->createIndexBuffer(); + + mDynamic = dynamic; + mWritePosition = 0; +} + +IndexBufferInterface::~IndexBufferInterface() +{ + if (mIndexBuffer) + { + delete mIndexBuffer; + } +} + +GLenum IndexBufferInterface::getIndexType() const +{ + return mIndexBuffer->getIndexType(); +} + +unsigned int IndexBufferInterface::getBufferSize() const +{ + return mIndexBuffer->getBufferSize(); +} + +unsigned int IndexBufferInterface::getSerial() const +{ + return mIndexBuffer->getSerial(); +} + +bool IndexBufferInterface::mapBuffer(unsigned int size, void** outMappedMemory, unsigned int *streamOffset) +{ + // Protect against integer overflow + if (mWritePosition + size < mWritePosition) + { + return false; + } + + if (!mIndexBuffer->mapBuffer(mWritePosition, size, outMappedMemory)) + { + if (outMappedMemory) + { + *outMappedMemory = NULL; + } + return false; + } + + if (streamOffset) + { + *streamOffset = mWritePosition; + } + + mWritePosition += size; + return true; +} + +bool IndexBufferInterface::unmapBuffer() +{ + return mIndexBuffer->unmapBuffer(); +} + +IndexBuffer * IndexBufferInterface::getIndexBuffer() const +{ + return mIndexBuffer; +} + +unsigned int IndexBufferInterface::getWritePosition() const +{ + return mWritePosition; +} + +void IndexBufferInterface::setWritePosition(unsigned int writePosition) +{ + mWritePosition = writePosition; +} + +bool IndexBufferInterface::discard() +{ + return mIndexBuffer->discard(); +} + +bool IndexBufferInterface::setBufferSize(unsigned int bufferSize, GLenum indexType) +{ + if (mIndexBuffer->getBufferSize() == 0) + { + return mIndexBuffer->initialize(bufferSize, indexType, mDynamic); + } + else + { + return mIndexBuffer->setSize(bufferSize, indexType); + } +} + +StreamingIndexBufferInterface::StreamingIndexBufferInterface(Renderer *renderer) : IndexBufferInterface(renderer, true) +{ +} + +StreamingIndexBufferInterface::~StreamingIndexBufferInterface() +{ +} + +bool StreamingIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum indexType) +{ + bool result = true; + unsigned int curBufferSize = getBufferSize(); + unsigned int writePos = getWritePosition(); + if (size > curBufferSize) + { + result = setBufferSize(std::max(size, 2 * curBufferSize), indexType); + setWritePosition(0); + } + else if (writePos + size > curBufferSize || writePos + size < writePos) + { + if (!discard()) + { + return false; + } + setWritePosition(0); + } + + return result; +} + + +StaticIndexBufferInterface::StaticIndexBufferInterface(Renderer *renderer) : IndexBufferInterface(renderer, false) +{ +} + +StaticIndexBufferInterface::~StaticIndexBufferInterface() +{ +} + +bool StaticIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum indexType) +{ + unsigned int curSize = getBufferSize(); + if (curSize == 0) + { + return setBufferSize(size, indexType); + } + else if (curSize >= size && indexType == getIndexType()) + { + return true; + } + else + { + ERR("Static index buffers can't be resized"); + UNREACHABLE(); + return false; + } +} + +IndexRangeCache *StaticIndexBufferInterface::getIndexRangeCache() +{ + return &mIndexRangeCache; +} + +} + diff --git a/gfx/angle/src/libGLESv2/renderer/IndexBuffer.h b/gfx/angle/src/libGLESv2/renderer/IndexBuffer.h new file mode 100644 index 000000000000..6fb885a1cd64 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/IndexBuffer.h @@ -0,0 +1,111 @@ +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// IndexBuffer.h: Defines the abstract IndexBuffer class and IndexBufferInterface +// class with derivations, classes that perform graphics API agnostic index buffer operations. + +#ifndef LIBGLESV2_RENDERER_INDEXBUFFER_H_ +#define LIBGLESV2_RENDERER_INDEXBUFFER_H_ + +#include "common/angleutils.h" +#include "libGLESv2/renderer/IndexRangeCache.h" + +namespace rx +{ +class Renderer; + +class IndexBuffer +{ + public: + IndexBuffer(); + virtual ~IndexBuffer(); + + virtual bool initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) = 0; + + virtual bool mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory) = 0; + virtual bool unmapBuffer() = 0; + + virtual bool discard() = 0; + + virtual GLenum getIndexType() const = 0; + virtual unsigned int getBufferSize() const = 0; + virtual bool setSize(unsigned int bufferSize, GLenum indexType) = 0; + + unsigned int getSerial() const; + + protected: + void updateSerial(); + + private: + DISALLOW_COPY_AND_ASSIGN(IndexBuffer); + + unsigned int mSerial; + static unsigned int mNextSerial; +}; + +class IndexBufferInterface +{ + public: + IndexBufferInterface(Renderer *renderer, bool dynamic); + virtual ~IndexBufferInterface(); + + virtual bool reserveBufferSpace(unsigned int size, GLenum indexType) = 0; + + GLenum getIndexType() const; + unsigned int getBufferSize() const; + + unsigned int getSerial() const; + + bool mapBuffer(unsigned int size, void** outMappedMemory, unsigned int *streamOffset); + bool unmapBuffer(); + + IndexBuffer *getIndexBuffer() const; + + protected: + unsigned int getWritePosition() const; + void setWritePosition(unsigned int writePosition); + + bool discard(); + + bool setBufferSize(unsigned int bufferSize, GLenum indexType); + + private: + DISALLOW_COPY_AND_ASSIGN(IndexBufferInterface); + + rx::Renderer *const mRenderer; + + IndexBuffer* mIndexBuffer; + + unsigned int mWritePosition; + bool mDynamic; +}; + +class StreamingIndexBufferInterface : public IndexBufferInterface +{ + public: + StreamingIndexBufferInterface(Renderer *renderer); + ~StreamingIndexBufferInterface(); + + virtual bool reserveBufferSpace(unsigned int size, GLenum indexType); +}; + +class StaticIndexBufferInterface : public IndexBufferInterface +{ + public: + explicit StaticIndexBufferInterface(Renderer *renderer); + ~StaticIndexBufferInterface(); + + virtual bool reserveBufferSpace(unsigned int size, GLenum indexType); + + IndexRangeCache *getIndexRangeCache(); + + private: + IndexRangeCache mIndexRangeCache; +}; + +} + +#endif // LIBGLESV2_RENDERER_INDEXBUFFER_H_ \ No newline at end of file diff --git a/gfx/angle/src/libGLESv2/renderer/IndexBuffer11.cpp b/gfx/angle/src/libGLESv2/renderer/IndexBuffer11.cpp new file mode 100644 index 000000000000..66604c455824 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/IndexBuffer11.cpp @@ -0,0 +1,183 @@ +#include "precompiled.h" +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// IndexBuffer11.cpp: Defines the D3D11 IndexBuffer implementation. + +#include "libGLESv2/renderer/IndexBuffer11.h" +#include "libGLESv2/renderer/Renderer11.h" + +namespace rx +{ + +IndexBuffer11::IndexBuffer11(Renderer11 *const renderer) : mRenderer(renderer) +{ + mBuffer = NULL; + mBufferSize = 0; + mDynamicUsage = false; +} + +IndexBuffer11::~IndexBuffer11() +{ + if (mBuffer) + { + mBuffer->Release(); + mBuffer = NULL; + } +} + +bool IndexBuffer11::initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) +{ + if (mBuffer) + { + mBuffer->Release(); + mBuffer = NULL; + } + + updateSerial(); + + if (bufferSize > 0) + { + ID3D11Device* dxDevice = mRenderer->getDevice(); + + D3D11_BUFFER_DESC bufferDesc; + bufferDesc.ByteWidth = bufferSize; + bufferDesc.Usage = D3D11_USAGE_DYNAMIC; + bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; + bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + bufferDesc.MiscFlags = 0; + bufferDesc.StructureByteStride = 0; + + HRESULT result = dxDevice->CreateBuffer(&bufferDesc, NULL, &mBuffer); + if (FAILED(result)) + { + return false; + } + } + + mBufferSize = bufferSize; + mIndexType = indexType; + mDynamicUsage = dynamic; + + return true; +} + +IndexBuffer11 *IndexBuffer11::makeIndexBuffer11(IndexBuffer *indexBuffer) +{ + ASSERT(HAS_DYNAMIC_TYPE(IndexBuffer11*, indexBuffer)); + return static_cast(indexBuffer); +} + +bool IndexBuffer11::mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory) +{ + if (mBuffer) + { + // Check for integer overflows and out-out-bounds map requests + if (offset + size < offset || offset + size > mBufferSize) + { + ERR("Index buffer map range is not inside the buffer."); + return false; + } + + ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource); + if (FAILED(result)) + { + ERR("Index buffer map failed with error 0x%08x", result); + return false; + } + + *outMappedMemory = reinterpret_cast(mappedResource.pData) + offset; + return true; + } + else + { + ERR("Index buffer not initialized."); + return false; + } +} + +bool IndexBuffer11::unmapBuffer() +{ + if (mBuffer) + { + ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); + dxContext->Unmap(mBuffer, 0); + return true; + } + else + { + ERR("Index buffer not initialized."); + return false; + } +} + +GLenum IndexBuffer11::getIndexType() const +{ + return mIndexType; +} + +unsigned int IndexBuffer11::getBufferSize() const +{ + return mBufferSize; +} + +bool IndexBuffer11::setSize(unsigned int bufferSize, GLenum indexType) +{ + if (bufferSize > mBufferSize || indexType != mIndexType) + { + return initialize(bufferSize, indexType, mDynamicUsage); + } + else + { + return true; + } +} + +bool IndexBuffer11::discard() +{ + if (mBuffer) + { + ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + ERR("Index buffer map failed with error 0x%08x", result); + return false; + } + + dxContext->Unmap(mBuffer, 0); + + return true; + } + else + { + ERR("Index buffer not initialized."); + return false; + } +} + +DXGI_FORMAT IndexBuffer11::getIndexFormat() const +{ + switch (mIndexType) + { + case GL_UNSIGNED_BYTE: return DXGI_FORMAT_R16_UINT; + case GL_UNSIGNED_SHORT: return DXGI_FORMAT_R16_UINT; + case GL_UNSIGNED_INT: return DXGI_FORMAT_R32_UINT; + default: UNREACHABLE(); return DXGI_FORMAT_UNKNOWN; + } +} + +ID3D11Buffer *IndexBuffer11::getBuffer() const +{ + return mBuffer; +} + +} \ No newline at end of file diff --git a/gfx/angle/src/libGLESv2/renderer/IndexBuffer11.h b/gfx/angle/src/libGLESv2/renderer/IndexBuffer11.h new file mode 100644 index 000000000000..39a61946ad6e --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/IndexBuffer11.h @@ -0,0 +1,53 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// IndexBuffer11.h: Defines the D3D11 IndexBuffer implementation. + +#ifndef LIBGLESV2_RENDERER_INDEXBUFFER11_H_ +#define LIBGLESV2_RENDERER_INDEXBUFFER11_H_ + +#include "libGLESv2/renderer/IndexBuffer.h" + +namespace rx +{ +class Renderer11; + +class IndexBuffer11 : public IndexBuffer +{ + public: + explicit IndexBuffer11(Renderer11 *const renderer); + virtual ~IndexBuffer11(); + + virtual bool initialize(unsigned int bufferSize, GLenum indexType, bool dynamic); + + static IndexBuffer11 *makeIndexBuffer11(IndexBuffer *indexBuffer); + + virtual bool mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory); + virtual bool unmapBuffer(); + + virtual GLenum getIndexType() const; + virtual unsigned int getBufferSize() const; + virtual bool setSize(unsigned int bufferSize, GLenum indexType); + + virtual bool discard(); + + DXGI_FORMAT getIndexFormat() const; + ID3D11Buffer *getBuffer() const; + + private: + DISALLOW_COPY_AND_ASSIGN(IndexBuffer11); + + rx::Renderer11 *const mRenderer; + + ID3D11Buffer *mBuffer; + unsigned int mBufferSize; + GLenum mIndexType; + bool mDynamicUsage; +}; + +} + +#endif // LIBGLESV2_RENDERER_INDEXBUFFER11_H_ \ No newline at end of file diff --git a/gfx/angle/src/libGLESv2/renderer/IndexBuffer9.cpp b/gfx/angle/src/libGLESv2/renderer/IndexBuffer9.cpp new file mode 100644 index 000000000000..c6d83c5dca7a --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/IndexBuffer9.cpp @@ -0,0 +1,207 @@ +#include "precompiled.h" +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Indexffer9.cpp: Defines the D3D9 IndexBuffer implementation. + +#include "libGLESv2/renderer/IndexBuffer9.h" +#include "libGLESv2/renderer/Renderer9.h" + +namespace rx +{ + +IndexBuffer9::IndexBuffer9(Renderer9 *const renderer) : mRenderer(renderer) +{ + mIndexBuffer = NULL; + mBufferSize = 0; + mIndexType = 0; + mDynamic = false; +} + +IndexBuffer9::~IndexBuffer9() +{ + if (mIndexBuffer) + { + mIndexBuffer->Release(); + mIndexBuffer = NULL; + } +} + +bool IndexBuffer9::initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) +{ + if (mIndexBuffer) + { + mIndexBuffer->Release(); + mIndexBuffer = NULL; + } + + updateSerial(); + + if (bufferSize > 0) + { + D3DFORMAT format; + if (indexType == GL_UNSIGNED_SHORT || indexType == GL_UNSIGNED_BYTE) + { + format = D3DFMT_INDEX16; + } + else if (indexType == GL_UNSIGNED_INT) + { + if (mRenderer->get32BitIndexSupport()) + { + format = D3DFMT_INDEX32; + } + else + { + ERR("Attempted to create a 32-bit index buffer but renderer does not support 32-bit indices."); + return false; + } + } + else + { + ERR("Invalid index type %u.", indexType); + return false; + } + + DWORD usageFlags = D3DUSAGE_WRITEONLY; + if (dynamic) + { + usageFlags |= D3DUSAGE_DYNAMIC; + } + + HRESULT result = mRenderer->createIndexBuffer(bufferSize, usageFlags, format, &mIndexBuffer); + if (FAILED(result)) + { + ERR("Failed to create an index buffer of size %u, result: 0x%08x.", mBufferSize, result); + return false; + } + } + + mBufferSize = bufferSize; + mIndexType = indexType; + mDynamic = dynamic; + + return true; +} + +IndexBuffer9 *IndexBuffer9::makeIndexBuffer9(IndexBuffer *indexBuffer) +{ + ASSERT(HAS_DYNAMIC_TYPE(IndexBuffer9*, indexBuffer)); + return static_cast(indexBuffer); +} + +bool IndexBuffer9::mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory) +{ + if (mIndexBuffer) + { + DWORD lockFlags = mDynamic ? D3DLOCK_NOOVERWRITE : 0; + + void *mapPtr = NULL; + HRESULT result = mIndexBuffer->Lock(offset, size, &mapPtr, lockFlags); + if (FAILED(result)) + { + ERR("Index buffer lock failed with error 0x%08x", result); + return false; + } + + *outMappedMemory = mapPtr; + return true; + } + else + { + ERR("Index buffer not initialized."); + return false; + } +} + +bool IndexBuffer9::unmapBuffer() +{ + if (mIndexBuffer) + { + HRESULT result = mIndexBuffer->Unlock(); + if (FAILED(result)) + { + ERR("Index buffer unlock failed with error 0x%08x", result); + return false; + } + + return true; + } + else + { + ERR("Index buffer not initialized."); + return false; + } +} + +GLenum IndexBuffer9::getIndexType() const +{ + return mIndexType; +} + +unsigned int IndexBuffer9::getBufferSize() const +{ + return mBufferSize; +} + +bool IndexBuffer9::setSize(unsigned int bufferSize, GLenum indexType) +{ + if (bufferSize > mBufferSize || indexType != mIndexType) + { + return initialize(bufferSize, indexType, mDynamic); + } + else + { + return true; + } +} + +bool IndexBuffer9::discard() +{ + if (mIndexBuffer) + { + void *dummy; + HRESULT result; + + result = mIndexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD); + if (FAILED(result)) + { + ERR("Discard lock failed with error 0x%08x", result); + return false; + } + + result = mIndexBuffer->Unlock(); + if (FAILED(result)) + { + ERR("Discard unlock failed with error 0x%08x", result); + return false; + } + + return true; + } + else + { + ERR("Index buffer not initialized."); + return false; + } +} + +D3DFORMAT IndexBuffer9::getIndexFormat() const +{ + switch (mIndexType) + { + case GL_UNSIGNED_BYTE: return D3DFMT_INDEX16; + case GL_UNSIGNED_SHORT: return D3DFMT_INDEX16; + case GL_UNSIGNED_INT: return D3DFMT_INDEX32; + default: UNREACHABLE(); return D3DFMT_UNKNOWN; + } +} + +IDirect3DIndexBuffer9 * IndexBuffer9::getBuffer() const +{ + return mIndexBuffer; +} + +} \ No newline at end of file diff --git a/gfx/angle/src/libGLESv2/renderer/IndexBuffer9.h b/gfx/angle/src/libGLESv2/renderer/IndexBuffer9.h new file mode 100644 index 000000000000..680186753245 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/IndexBuffer9.h @@ -0,0 +1,53 @@ +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Indexffer9.h: Defines the D3D9 IndexBuffer implementation. + +#ifndef LIBGLESV2_RENDERER_INDEXBUFFER9_H_ +#define LIBGLESV2_RENDERER_INDEXBUFFER9_H_ + +#include "libGLESv2/renderer/IndexBuffer.h" + +namespace rx +{ +class Renderer9; + +class IndexBuffer9 : public IndexBuffer +{ + public: + explicit IndexBuffer9(Renderer9 *const renderer); + virtual ~IndexBuffer9(); + + virtual bool initialize(unsigned int bufferSize, GLenum indexType, bool dynamic); + + static IndexBuffer9 *makeIndexBuffer9(IndexBuffer *indexBuffer); + + virtual bool mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory); + virtual bool unmapBuffer(); + + virtual GLenum getIndexType() const; + virtual unsigned int getBufferSize() const; + virtual bool setSize(unsigned int bufferSize, GLenum indexType); + + virtual bool discard(); + + D3DFORMAT getIndexFormat() const; + IDirect3DIndexBuffer9 *getBuffer() const; + + private: + DISALLOW_COPY_AND_ASSIGN(IndexBuffer9); + + rx::Renderer9 *const mRenderer; + + IDirect3DIndexBuffer9 *mIndexBuffer; + unsigned int mBufferSize; + GLenum mIndexType; + bool mDynamic; +}; + +} + +#endif // LIBGLESV2_RENDERER_INDEXBUFFER9_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/IndexDataManager.cpp b/gfx/angle/src/libGLESv2/renderer/IndexDataManager.cpp new file mode 100644 index 000000000000..2eab550cb547 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/IndexDataManager.cpp @@ -0,0 +1,333 @@ +#include "precompiled.h" +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// IndexDataManager.cpp: Defines the IndexDataManager, a class that +// runs the Buffer translation process for index buffers. + +#include "libGLESv2/renderer/IndexDataManager.h" +#include "libGLESv2/renderer/BufferStorage.h" + +#include "libGLESv2/Buffer.h" +#include "libGLESv2/main.h" +#include "libGLESv2/utilities.h" +#include "libGLESv2/renderer/IndexBuffer.h" + +namespace rx +{ + +IndexDataManager::IndexDataManager(Renderer *renderer) : mRenderer(renderer) +{ + mStreamingBufferShort = new StreamingIndexBufferInterface(mRenderer); + if (!mStreamingBufferShort->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT)) + { + delete mStreamingBufferShort; + mStreamingBufferShort = NULL; + } + + mStreamingBufferInt = new StreamingIndexBufferInterface(mRenderer); + if (!mStreamingBufferInt->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT)) + { + delete mStreamingBufferInt; + mStreamingBufferInt = NULL; + } + + if (!mStreamingBufferShort) + { + // Make sure both buffers are deleted. + delete mStreamingBufferInt; + mStreamingBufferInt = NULL; + + ERR("Failed to allocate the streaming index buffer(s)."); + } + + mCountingBuffer = NULL; +} + +IndexDataManager::~IndexDataManager() +{ + delete mStreamingBufferShort; + delete mStreamingBufferInt; + delete mCountingBuffer; +} + +static void convertIndices(GLenum type, const void *input, GLsizei count, void *output) +{ + if (type == GL_UNSIGNED_BYTE) + { + const GLubyte *in = static_cast(input); + GLushort *out = static_cast(output); + + for (GLsizei i = 0; i < count; i++) + { + out[i] = in[i]; + } + } + else if (type == GL_UNSIGNED_INT) + { + memcpy(output, input, count * sizeof(GLuint)); + } + else if (type == GL_UNSIGNED_SHORT) + { + memcpy(output, input, count * sizeof(GLushort)); + } + else UNREACHABLE(); +} + +template +static void computeRange(const IndexType *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex) +{ + *minIndex = indices[0]; + *maxIndex = indices[0]; + + for (GLsizei i = 0; i < count; i++) + { + if (*minIndex > indices[i]) *minIndex = indices[i]; + if (*maxIndex < indices[i]) *maxIndex = indices[i]; + } +} + +static void computeRange(GLenum type, const GLvoid *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex) +{ + if (type == GL_UNSIGNED_BYTE) + { + computeRange(static_cast(indices), count, minIndex, maxIndex); + } + else if (type == GL_UNSIGNED_INT) + { + computeRange(static_cast(indices), count, minIndex, maxIndex); + } + else if (type == GL_UNSIGNED_SHORT) + { + computeRange(static_cast(indices), count, minIndex, maxIndex); + } + else UNREACHABLE(); +} + +GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer *buffer, const GLvoid *indices, TranslatedIndexData *translated) +{ + if (!mStreamingBufferShort) + { + return GL_OUT_OF_MEMORY; + } + + GLenum destinationIndexType = (type == GL_UNSIGNED_INT) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT; + intptr_t offset = reinterpret_cast(indices); + bool alignedOffset = false; + + BufferStorage *storage = NULL; + + if (buffer != NULL) + { + storage = buffer->getStorage(); + + switch (type) + { + case GL_UNSIGNED_BYTE: alignedOffset = (offset % sizeof(GLubyte) == 0); break; + case GL_UNSIGNED_SHORT: alignedOffset = (offset % sizeof(GLushort) == 0); break; + case GL_UNSIGNED_INT: alignedOffset = (offset % sizeof(GLuint) == 0); break; + default: UNREACHABLE(); alignedOffset = false; + } + + unsigned int typeSize = gl::ComputeTypeSize(type); + + // check for integer overflows and underflows + if (static_cast(offset) > (std::numeric_limits::max() / typeSize) || + static_cast(count) > ((std::numeric_limits::max() / typeSize) - offset)) + { + return GL_OUT_OF_MEMORY; + } + + if (typeSize * static_cast(count) + offset > storage->getSize()) + { + return GL_INVALID_OPERATION; + } + + indices = static_cast(storage->getData()) + offset; + } + + StreamingIndexBufferInterface *streamingBuffer = (type == GL_UNSIGNED_INT) ? mStreamingBufferInt : mStreamingBufferShort; + + StaticIndexBufferInterface *staticBuffer = buffer ? buffer->getStaticIndexBuffer() : NULL; + IndexBufferInterface *indexBuffer = streamingBuffer; + bool directStorage = alignedOffset && storage && storage->supportsDirectBinding() && + destinationIndexType == type; + unsigned int streamOffset = 0; + + if (directStorage) + { + indexBuffer = streamingBuffer; + streamOffset = offset; + storage->markBufferUsage(); + + if (!buffer->getIndexRangeCache()->findRange(type, offset, count, &translated->minIndex, + &translated->maxIndex, NULL)) + { + computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex); + buffer->getIndexRangeCache()->addRange(type, offset, count, translated->minIndex, + translated->maxIndex, offset); + } + } + else if (staticBuffer && staticBuffer->getBufferSize() != 0 && staticBuffer->getIndexType() == type && alignedOffset) + { + indexBuffer = staticBuffer; + if (!staticBuffer->getIndexRangeCache()->findRange(type, offset, count, &translated->minIndex, + &translated->maxIndex, &streamOffset)) + { + streamOffset = (offset / gl::ComputeTypeSize(type)) * gl::ComputeTypeSize(destinationIndexType); + computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex); + staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->minIndex, + translated->maxIndex, streamOffset); + } + } + else + { + unsigned int convertCount = count; + + if (staticBuffer) + { + if (staticBuffer->getBufferSize() == 0 && alignedOffset) + { + indexBuffer = staticBuffer; + convertCount = storage->getSize() / gl::ComputeTypeSize(type); + } + else + { + buffer->invalidateStaticData(); + staticBuffer = NULL; + } + } + + if (!indexBuffer) + { + ERR("No valid index buffer."); + return GL_INVALID_OPERATION; + } + + unsigned int indexTypeSize = gl::ComputeTypeSize(destinationIndexType); + if (convertCount > std::numeric_limits::max() / indexTypeSize) + { + ERR("Reserving %u indicies of %u bytes each exceeds the maximum buffer size.", convertCount, indexTypeSize); + return GL_OUT_OF_MEMORY; + } + + unsigned int bufferSizeRequired = convertCount * indexTypeSize; + if (!indexBuffer->reserveBufferSpace(bufferSizeRequired, type)) + { + ERR("Failed to reserve %u bytes in an index buffer.", bufferSizeRequired); + return GL_OUT_OF_MEMORY; + } + + void* output = NULL; + if (!indexBuffer->mapBuffer(bufferSizeRequired, &output, &streamOffset)) + { + ERR("Failed to map index buffer."); + return GL_OUT_OF_MEMORY; + } + + convertIndices(type, staticBuffer ? storage->getData() : indices, convertCount, output); + + if (!indexBuffer->unmapBuffer()) + { + ERR("Failed to unmap index buffer."); + return GL_OUT_OF_MEMORY; + } + + computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex); + + if (staticBuffer) + { + streamOffset = (offset / gl::ComputeTypeSize(type)) * gl::ComputeTypeSize(destinationIndexType); + staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->minIndex, + translated->maxIndex, streamOffset); + } + } + + translated->storage = directStorage ? storage : NULL; + translated->indexBuffer = indexBuffer->getIndexBuffer(); + translated->serial = directStorage ? storage->getSerial() : indexBuffer->getSerial(); + translated->startIndex = streamOffset / gl::ComputeTypeSize(destinationIndexType); + translated->startOffset = streamOffset; + + if (buffer) + { + buffer->promoteStaticUsage(count * gl::ComputeTypeSize(type)); + } + + return GL_NO_ERROR; +} + +StaticIndexBufferInterface *IndexDataManager::getCountingIndices(GLsizei count) +{ + if (count <= 65536) // 16-bit indices + { + const unsigned int spaceNeeded = count * sizeof(unsigned short); + + if (!mCountingBuffer || mCountingBuffer->getBufferSize() < spaceNeeded) + { + delete mCountingBuffer; + mCountingBuffer = new StaticIndexBufferInterface(mRenderer); + mCountingBuffer->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT); + + void* mappedMemory = NULL; + if (!mCountingBuffer->mapBuffer(spaceNeeded, &mappedMemory, NULL)) + { + ERR("Failed to map counting buffer."); + return NULL; + } + + unsigned short *data = reinterpret_cast(mappedMemory); + for(int i = 0; i < count; i++) + { + data[i] = i; + } + + if (!mCountingBuffer->unmapBuffer()) + { + ERR("Failed to unmap counting buffer."); + return NULL; + } + } + } + else if (mStreamingBufferInt) // 32-bit indices supported + { + const unsigned int spaceNeeded = count * sizeof(unsigned int); + + if (!mCountingBuffer || mCountingBuffer->getBufferSize() < spaceNeeded) + { + delete mCountingBuffer; + mCountingBuffer = new StaticIndexBufferInterface(mRenderer); + mCountingBuffer->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT); + + void* mappedMemory = NULL; + if (!mCountingBuffer->mapBuffer(spaceNeeded, &mappedMemory, NULL)) + { + ERR("Failed to map counting buffer."); + return NULL; + } + + unsigned int *data = reinterpret_cast(mappedMemory); + for(int i = 0; i < count; i++) + { + data[i] = i; + } + + if (!mCountingBuffer->unmapBuffer()) + { + ERR("Failed to unmap counting buffer."); + return NULL; + } + } + } + else + { + return NULL; + } + + return mCountingBuffer; +} + +} diff --git a/gfx/angle/src/libGLESv2/renderer/IndexDataManager.h b/gfx/angle/src/libGLESv2/renderer/IndexDataManager.h new file mode 100644 index 000000000000..0e77c81d1bba --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/IndexDataManager.h @@ -0,0 +1,66 @@ +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// IndexDataManager.h: Defines the IndexDataManager, a class that +// runs the Buffer translation process for index buffers. + +#ifndef LIBGLESV2_INDEXDATAMANAGER_H_ +#define LIBGLESV2_INDEXDATAMANAGER_H_ + +#include "common/angleutils.h" + +namespace +{ + enum { INITIAL_INDEX_BUFFER_SIZE = 4096 * sizeof(GLuint) }; +} + +namespace gl +{ +class Buffer; +} + +namespace rx +{ +class StaticIndexBufferInterface; +class StreamingIndexBufferInterface; +class IndexBuffer; +class BufferStorage; +class Renderer; + +struct TranslatedIndexData +{ + unsigned int minIndex; + unsigned int maxIndex; + unsigned int startIndex; + unsigned int startOffset; // In bytes + + IndexBuffer *indexBuffer; + BufferStorage *storage; + unsigned int serial; +}; + +class IndexDataManager +{ + public: + explicit IndexDataManager(Renderer *renderer); + virtual ~IndexDataManager(); + + GLenum prepareIndexData(GLenum type, GLsizei count, gl::Buffer *arrayElementBuffer, const GLvoid *indices, TranslatedIndexData *translated); + StaticIndexBufferInterface *getCountingIndices(GLsizei count); + + private: + DISALLOW_COPY_AND_ASSIGN(IndexDataManager); + + Renderer *const mRenderer; + + StreamingIndexBufferInterface *mStreamingBufferShort; + StreamingIndexBufferInterface *mStreamingBufferInt; + StaticIndexBufferInterface *mCountingBuffer; +}; + +} + +#endif // LIBGLESV2_INDEXDATAMANAGER_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/IndexRangeCache.cpp b/gfx/angle/src/libGLESv2/renderer/IndexRangeCache.cpp new file mode 100644 index 000000000000..7630934afde7 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/IndexRangeCache.cpp @@ -0,0 +1,97 @@ +#include "precompiled.h" +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// IndexRangeCache.cpp: Defines the rx::IndexRangeCache class which stores information about +// ranges of indices. + +#include "libGLESv2/renderer/IndexRangeCache.h" +#include "common/debug.h" +#include "libGLESv2/utilities.h" +#include + +namespace rx +{ + +void IndexRangeCache::addRange(GLenum type, intptr_t offset, GLsizei count, unsigned int minIdx, unsigned int maxIdx, + unsigned int streamOffset) +{ + mIndexRangeCache[IndexRange(type, offset, count)] = IndexBounds(minIdx, maxIdx, streamOffset); +} + +void IndexRangeCache::invalidateRange(unsigned int offset, unsigned int size) +{ + unsigned int invalidateStart = offset; + unsigned int invalidateEnd = offset + size; + + IndexRangeMap::iterator i = mIndexRangeCache.begin(); + while (i != mIndexRangeCache.end()) + { + unsigned int rangeStart = i->second.streamOffset; + unsigned int rangeEnd = i->second.streamOffset + (gl::ComputeTypeSize(i->first.type) * i->first.count); + + if (invalidateEnd < rangeStart || invalidateStart > rangeEnd) + { + ++i; + } + else + { + i = mIndexRangeCache.erase(i); + } + } +} + +bool IndexRangeCache::findRange(GLenum type, intptr_t offset, GLsizei count, unsigned int *outMinIndex, + unsigned int *outMaxIndex, unsigned int *outStreamOffset) const +{ + IndexRangeMap::const_iterator i = mIndexRangeCache.find(IndexRange(type, offset, count)); + if (i != mIndexRangeCache.end()) + { + if (outMinIndex) *outMinIndex = i->second.minIndex; + if (outMaxIndex) *outMaxIndex = i->second.maxIndex; + if (outStreamOffset) *outStreamOffset = i->second.streamOffset; + return true; + } + else + { + if (outMinIndex) *outMinIndex = 0; + if (outMaxIndex) *outMaxIndex = 0; + if (outStreamOffset) *outStreamOffset = 0; + return false; + } +} + +void IndexRangeCache::clear() +{ + mIndexRangeCache.clear(); +} + +IndexRangeCache::IndexRange::IndexRange() + : type(GL_NONE), offset(0), count(0) +{ +} + +IndexRangeCache::IndexRange::IndexRange(GLenum typ, intptr_t off, GLsizei c) + : type(typ), offset(off), count(c) +{ +} + +bool IndexRangeCache::IndexRange::operator<(const IndexRange& rhs) const +{ + return std::make_tuple(type, offset, count) < std::make_tuple(rhs.type, rhs.offset, rhs.count); +} + +IndexRangeCache::IndexBounds::IndexBounds() + : minIndex(0), maxIndex(0), streamOffset(0) +{ +} + +IndexRangeCache::IndexBounds::IndexBounds(unsigned int minIdx, unsigned int maxIdx, unsigned int offset) + : minIndex(minIdx), maxIndex(maxIdx), streamOffset(offset) +{ +} + +} diff --git a/gfx/angle/src/libGLESv2/renderer/IndexRangeCache.h b/gfx/angle/src/libGLESv2/renderer/IndexRangeCache.h new file mode 100644 index 000000000000..5a5ade10b58e --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/IndexRangeCache.h @@ -0,0 +1,58 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// IndexRangeCache.h: Defines the rx::IndexRangeCache class which stores information about +// ranges of indices. + +#ifndef LIBGLESV2_RENDERER_INDEXRANGECACHE_H_ +#define LIBGLESV2_RENDERER_INDEXRANGECACHE_H_ + +#include "common/angleutils.h" + +namespace rx +{ + +class IndexRangeCache +{ + public: + void addRange(GLenum type, intptr_t offset, GLsizei count, unsigned int minIdx, unsigned int maxIdx, + unsigned int streamOffset); + bool findRange(GLenum type, intptr_t offset, GLsizei count, unsigned int *outMinIndex, + unsigned int *outMaxIndex, unsigned int *outStreamOffset) const; + + void invalidateRange(unsigned int offset, unsigned int size); + void clear(); + + private: + struct IndexRange + { + GLenum type; + intptr_t offset; + GLsizei count; + + IndexRange(); + IndexRange(GLenum type, intptr_t offset, GLsizei count); + + bool operator<(const IndexRange& rhs) const; + }; + + struct IndexBounds + { + unsigned int minIndex; + unsigned int maxIndex; + unsigned int streamOffset; + + IndexBounds(); + IndexBounds(unsigned int minIdx, unsigned int maxIdx, unsigned int offset); + }; + + typedef std::map IndexRangeMap; + IndexRangeMap mIndexRangeCache; +}; + +} + +#endif LIBGLESV2_RENDERER_INDEXRANGECACHE_H diff --git a/gfx/angle/src/libGLESv2/renderer/InputLayoutCache.cpp b/gfx/angle/src/libGLESv2/renderer/InputLayoutCache.cpp new file mode 100644 index 000000000000..fcc6f7ce612e --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/InputLayoutCache.cpp @@ -0,0 +1,202 @@ +#include "precompiled.h" +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// InputLayoutCache.cpp: Defines InputLayoutCache, a class that builds and caches +// D3D11 input layouts. + +#include "libGLESv2/renderer/InputLayoutCache.h" +#include "libGLESv2/renderer/VertexBuffer11.h" +#include "libGLESv2/renderer/BufferStorage11.h" +#include "libGLESv2/renderer/ShaderExecutable11.h" +#include "libGLESv2/ProgramBinary.h" +#include "libGLESv2/Context.h" +#include "libGLESv2/renderer/VertexDataManager.h" + +#include "third_party/murmurhash/MurmurHash3.h" + +namespace rx +{ + +const unsigned int InputLayoutCache::kMaxInputLayouts = 1024; + +InputLayoutCache::InputLayoutCache() : mInputLayoutMap(kMaxInputLayouts, hashInputLayout, compareInputLayouts) +{ + mCounter = 0; + mDevice = NULL; + mDeviceContext = NULL; + mCurrentIL = NULL; + for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + mCurrentBuffers[i] = -1; + mCurrentVertexStrides[i] = -1; + mCurrentVertexOffsets[i] = -1; + } +} + +InputLayoutCache::~InputLayoutCache() +{ + clear(); +} + +void InputLayoutCache::initialize(ID3D11Device *device, ID3D11DeviceContext *context) +{ + clear(); + mDevice = device; + mDeviceContext = context; +} + +void InputLayoutCache::clear() +{ + for (InputLayoutMap::iterator i = mInputLayoutMap.begin(); i != mInputLayoutMap.end(); i++) + { + i->second.inputLayout->Release(); + } + mInputLayoutMap.clear(); + markDirty(); +} + +void InputLayoutCache::markDirty() +{ + mCurrentIL = NULL; + for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + mCurrentBuffers[i] = -1; + mCurrentVertexStrides[i] = -1; + mCurrentVertexOffsets[i] = -1; + } +} + +GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS], + gl::ProgramBinary *programBinary) +{ + int sortedSemanticIndices[gl::MAX_VERTEX_ATTRIBS]; + programBinary->sortAttributesByLayout(attributes, sortedSemanticIndices); + + if (!mDevice || !mDeviceContext) + { + ERR("InputLayoutCache is not initialized."); + return GL_INVALID_OPERATION; + } + + InputLayoutKey ilKey = { 0 }; + + ID3D11Buffer *vertexBuffers[gl::MAX_VERTEX_ATTRIBS] = { NULL }; + unsigned int vertexBufferSerials[gl::MAX_VERTEX_ATTRIBS] = { 0 }; + UINT vertexStrides[gl::MAX_VERTEX_ATTRIBS] = { 0 }; + UINT vertexOffsets[gl::MAX_VERTEX_ATTRIBS] = { 0 }; + + static const char* semanticName = "TEXCOORD"; + + for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + if (attributes[i].active) + { + VertexBuffer11 *vertexBuffer = VertexBuffer11::makeVertexBuffer11(attributes[i].vertexBuffer); + BufferStorage11 *bufferStorage = attributes[i].storage ? BufferStorage11::makeBufferStorage11(attributes[i].storage) : NULL; + + D3D11_INPUT_CLASSIFICATION inputClass = attributes[i].divisor > 0 ? D3D11_INPUT_PER_INSTANCE_DATA : D3D11_INPUT_PER_VERTEX_DATA; + + // Record the type of the associated vertex shader vector in our key + // This will prevent mismatched vertex shaders from using the same input layout + GLint attributeSize; + programBinary->getActiveAttribute(ilKey.elementCount, 0, NULL, &attributeSize, &ilKey.glslElementType[ilKey.elementCount], NULL); + + ilKey.elements[ilKey.elementCount].SemanticName = semanticName; + ilKey.elements[ilKey.elementCount].SemanticIndex = sortedSemanticIndices[i]; + ilKey.elements[ilKey.elementCount].Format = attributes[i].attribute->mArrayEnabled ? vertexBuffer->getDXGIFormat(*attributes[i].attribute) : DXGI_FORMAT_R32G32B32A32_FLOAT; + ilKey.elements[ilKey.elementCount].InputSlot = i; + ilKey.elements[ilKey.elementCount].AlignedByteOffset = 0; + ilKey.elements[ilKey.elementCount].InputSlotClass = inputClass; + ilKey.elements[ilKey.elementCount].InstanceDataStepRate = attributes[i].divisor; + ilKey.elementCount++; + + vertexBuffers[i] = bufferStorage ? bufferStorage->getBuffer() : vertexBuffer->getBuffer(); + vertexBufferSerials[i] = bufferStorage ? bufferStorage->getSerial() : vertexBuffer->getSerial(); + vertexStrides[i] = attributes[i].stride; + vertexOffsets[i] = attributes[i].offset; + } + } + + ID3D11InputLayout *inputLayout = NULL; + + InputLayoutMap::iterator i = mInputLayoutMap.find(ilKey); + if (i != mInputLayoutMap.end()) + { + inputLayout = i->second.inputLayout; + i->second.lastUsedTime = mCounter++; + } + else + { + ShaderExecutable11 *shader = ShaderExecutable11::makeShaderExecutable11(programBinary->getVertexExecutable()); + + HRESULT result = mDevice->CreateInputLayout(ilKey.elements, ilKey.elementCount, shader->getFunction(), shader->getLength(), &inputLayout); + if (FAILED(result)) + { + ERR("Failed to crate input layout, result: 0x%08x", result); + return GL_INVALID_OPERATION; + } + + if (mInputLayoutMap.size() >= kMaxInputLayouts) + { + TRACE("Overflowed the limit of %u input layouts, removing the least recently used " + "to make room.", kMaxInputLayouts); + + InputLayoutMap::iterator leastRecentlyUsed = mInputLayoutMap.begin(); + for (InputLayoutMap::iterator i = mInputLayoutMap.begin(); i != mInputLayoutMap.end(); i++) + { + if (i->second.lastUsedTime < leastRecentlyUsed->second.lastUsedTime) + { + leastRecentlyUsed = i; + } + } + leastRecentlyUsed->second.inputLayout->Release(); + mInputLayoutMap.erase(leastRecentlyUsed); + } + + InputLayoutCounterPair inputCounterPair; + inputCounterPair.inputLayout = inputLayout; + inputCounterPair.lastUsedTime = mCounter++; + + mInputLayoutMap.insert(std::make_pair(ilKey, inputCounterPair)); + } + + if (inputLayout != mCurrentIL) + { + mDeviceContext->IASetInputLayout(inputLayout); + mCurrentIL = inputLayout; + } + + for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + if (vertexBufferSerials[i] != mCurrentBuffers[i] || vertexStrides[i] != mCurrentVertexStrides[i] || + vertexOffsets[i] != mCurrentVertexOffsets[i]) + { + mDeviceContext->IASetVertexBuffers(i, 1, &vertexBuffers[i], &vertexStrides[i], &vertexOffsets[i]); + mCurrentBuffers[i] = vertexBufferSerials[i]; + mCurrentVertexStrides[i] = vertexStrides[i]; + mCurrentVertexOffsets[i] = vertexOffsets[i]; + } + } + + return GL_NO_ERROR; +} + +std::size_t InputLayoutCache::hashInputLayout(const InputLayoutKey &inputLayout) +{ + static const unsigned int seed = 0xDEADBEEF; + + std::size_t hash = 0; + MurmurHash3_x86_32(&inputLayout, sizeof(InputLayoutKey), seed, &hash); + return hash; +} + +bool InputLayoutCache::compareInputLayouts(const InputLayoutKey &a, const InputLayoutKey &b) +{ + return memcmp(&a, &b, sizeof(InputLayoutKey)) == 0; +} + +} diff --git a/gfx/angle/src/libGLESv2/renderer/InputLayoutCache.h b/gfx/angle/src/libGLESv2/renderer/InputLayoutCache.h new file mode 100644 index 000000000000..797853def110 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/InputLayoutCache.h @@ -0,0 +1,80 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// InputLayoutCache.h: Defines InputLayoutCache, a class that builds and caches +// D3D11 input layouts. + +#ifndef LIBGLESV2_RENDERER_INPUTLAYOUTCACHE_H_ +#define LIBGLESV2_RENDERER_INPUTLAYOUTCACHE_H_ + +#include "libGLESv2/Constants.h" +#include "common/angleutils.h" + +namespace gl +{ +class ProgramBinary; +} + +namespace rx +{ +struct TranslatedAttribute; + +class InputLayoutCache +{ + public: + InputLayoutCache(); + virtual ~InputLayoutCache(); + + void initialize(ID3D11Device *device, ID3D11DeviceContext *context); + void clear(); + void markDirty(); + + GLenum applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS], + gl::ProgramBinary *programBinary); + + private: + DISALLOW_COPY_AND_ASSIGN(InputLayoutCache); + + struct InputLayoutKey + { + unsigned int elementCount; + D3D11_INPUT_ELEMENT_DESC elements[gl::MAX_VERTEX_ATTRIBS]; + GLenum glslElementType[gl::MAX_VERTEX_ATTRIBS]; + }; + + struct InputLayoutCounterPair + { + ID3D11InputLayout *inputLayout; + unsigned long long lastUsedTime; + }; + + ID3D11InputLayout *mCurrentIL; + unsigned int mCurrentBuffers[gl::MAX_VERTEX_ATTRIBS]; + UINT mCurrentVertexStrides[gl::MAX_VERTEX_ATTRIBS]; + UINT mCurrentVertexOffsets[gl::MAX_VERTEX_ATTRIBS]; + + static std::size_t hashInputLayout(const InputLayoutKey &inputLayout); + static bool compareInputLayouts(const InputLayoutKey &a, const InputLayoutKey &b); + + typedef std::size_t (*InputLayoutHashFunction)(const InputLayoutKey &); + typedef bool (*InputLayoutEqualityFunction)(const InputLayoutKey &, const InputLayoutKey &); + typedef std::unordered_map InputLayoutMap; + InputLayoutMap mInputLayoutMap; + + static const unsigned int kMaxInputLayouts; + + unsigned long long mCounter; + + ID3D11Device *mDevice; + ID3D11DeviceContext *mDeviceContext; +}; + +} + +#endif // LIBGLESV2_RENDERER_INPUTLAYOUTCACHE_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/Query11.cpp b/gfx/angle/src/libGLESv2/renderer/Query11.cpp new file mode 100644 index 000000000000..13210fc92913 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/Query11.cpp @@ -0,0 +1,122 @@ +#include "precompiled.h" +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Query11.cpp: Defines the rx::Query11 class which implements rx::QueryImpl. + +#include "libGLESv2/renderer/Query11.h" +#include "libGLESv2/renderer/Renderer11.h" +#include "libGLESv2/main.h" + +namespace rx +{ + +Query11::Query11(rx::Renderer11 *renderer, GLenum type) : QueryImpl(type) +{ + mRenderer = renderer; + mQuery = NULL; +} + +Query11::~Query11() +{ + if (mQuery) + { + mQuery->Release(); + mQuery = NULL; + } +} + +void Query11::begin() +{ + if (mQuery == NULL) + { + D3D11_QUERY_DESC queryDesc; + queryDesc.Query = D3D11_QUERY_OCCLUSION; + queryDesc.MiscFlags = 0; + + if (FAILED(mRenderer->getDevice()->CreateQuery(&queryDesc, &mQuery))) + { + return gl::error(GL_OUT_OF_MEMORY); + } + } + + mRenderer->getDeviceContext()->Begin(mQuery); +} + +void Query11::end() +{ + if (mQuery == NULL) + { + return gl::error(GL_INVALID_OPERATION); + } + + mRenderer->getDeviceContext()->End(mQuery); + + mStatus = GL_FALSE; + mResult = GL_FALSE; +} + +GLuint Query11::getResult() +{ + if (mQuery != NULL) + { + while (!testQuery()) + { + Sleep(0); + // explicitly check for device loss, some drivers seem to return S_FALSE + // if the device is lost + if (mRenderer->testDeviceLost(true)) + { + return gl::error(GL_OUT_OF_MEMORY, 0); + } + } + } + + return mResult; +} + +GLboolean Query11::isResultAvailable() +{ + if (mQuery != NULL) + { + testQuery(); + } + + return mStatus; +} + +GLboolean Query11::testQuery() +{ + if (mQuery != NULL && mStatus != GL_TRUE) + { + UINT64 numPixels = 0; + HRESULT result = mRenderer->getDeviceContext()->GetData(mQuery, &numPixels, sizeof(UINT64), 0); + if (result == S_OK) + { + mStatus = GL_TRUE; + + switch (getType()) + { + case GL_ANY_SAMPLES_PASSED_EXT: + case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: + mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE; + break; + default: + UNREACHABLE(); + } + } + else if (mRenderer->testDeviceLost(true)) + { + return gl::error(GL_OUT_OF_MEMORY, GL_TRUE); + } + + return mStatus; + } + + return GL_TRUE; // prevent blocking when query is null +} + +} diff --git a/gfx/angle/src/libGLESv2/renderer/Query11.h b/gfx/angle/src/libGLESv2/renderer/Query11.h new file mode 100644 index 000000000000..0a03de77ca32 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/Query11.h @@ -0,0 +1,40 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Query11.h: Defines the rx::Query11 class which implements rx::QueryImpl. + +#ifndef LIBGLESV2_RENDERER_QUERY11_H_ +#define LIBGLESV2_RENDERER_QUERY11_H_ + +#include "libGLESv2/renderer/QueryImpl.h" + +namespace rx +{ +class Renderer11; + +class Query11 : public QueryImpl +{ + public: + Query11(rx::Renderer11 *renderer, GLenum type); + virtual ~Query11(); + + void begin(); + void end(); + GLuint getResult(); + GLboolean isResultAvailable(); + + private: + DISALLOW_COPY_AND_ASSIGN(Query11); + + GLboolean testQuery(); + + rx::Renderer11 *mRenderer; + ID3D11Query *mQuery; +}; + +} + +#endif // LIBGLESV2_RENDERER_QUERY11_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/Query9.cpp b/gfx/angle/src/libGLESv2/renderer/Query9.cpp new file mode 100644 index 000000000000..ef694267dd1e --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/Query9.cpp @@ -0,0 +1,125 @@ +#include "precompiled.h" +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Query9.cpp: Defines the rx::Query9 class which implements rx::QueryImpl. + + +#include "libGLESv2/renderer/Query9.h" +#include "libGLESv2/main.h" +#include "libGLESv2/renderer/renderer9_utils.h" +#include "libGLESv2/renderer/Renderer9.h" + +namespace rx +{ + +Query9::Query9(rx::Renderer9 *renderer, GLenum type) : QueryImpl(type) +{ + mRenderer = renderer; + mQuery = NULL; +} + +Query9::~Query9() +{ + if (mQuery) + { + mQuery->Release(); + mQuery = NULL; + } +} + +void Query9::begin() +{ + if (mQuery == NULL) + { + if (FAILED(mRenderer->getDevice()->CreateQuery(D3DQUERYTYPE_OCCLUSION, &mQuery))) + { + return gl::error(GL_OUT_OF_MEMORY); + } + } + + HRESULT result = mQuery->Issue(D3DISSUE_BEGIN); + ASSERT(SUCCEEDED(result)); +} + +void Query9::end() +{ + if (mQuery == NULL) + { + return gl::error(GL_INVALID_OPERATION); + } + + HRESULT result = mQuery->Issue(D3DISSUE_END); + ASSERT(SUCCEEDED(result)); + + mStatus = GL_FALSE; + mResult = GL_FALSE; +} + +GLuint Query9::getResult() +{ + if (mQuery != NULL) + { + while (!testQuery()) + { + Sleep(0); + // explicitly check for device loss + // some drivers seem to return S_FALSE even if the device is lost + // instead of D3DERR_DEVICELOST like they should + if (mRenderer->testDeviceLost(true)) + { + return gl::error(GL_OUT_OF_MEMORY, 0); + } + } + } + + return mResult; +} + +GLboolean Query9::isResultAvailable() +{ + if (mQuery != NULL) + { + testQuery(); + } + + return mStatus; +} + +GLboolean Query9::testQuery() +{ + if (mQuery != NULL && mStatus != GL_TRUE) + { + DWORD numPixels = 0; + + HRESULT hres = mQuery->GetData(&numPixels, sizeof(DWORD), D3DGETDATA_FLUSH); + if (hres == S_OK) + { + mStatus = GL_TRUE; + + switch (getType()) + { + case GL_ANY_SAMPLES_PASSED_EXT: + case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: + mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE; + break; + default: + ASSERT(false); + } + } + else if (d3d9::isDeviceLostError(hres)) + { + mRenderer->notifyDeviceLost(); + return gl::error(GL_OUT_OF_MEMORY, GL_TRUE); + } + + return mStatus; + } + + return GL_TRUE; // prevent blocking when query is null +} + +} diff --git a/gfx/angle/src/libGLESv2/renderer/Query9.h b/gfx/angle/src/libGLESv2/renderer/Query9.h new file mode 100644 index 000000000000..47eef89336ef --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/Query9.h @@ -0,0 +1,40 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Query9.h: Defines the rx::Query9 class which implements rx::QueryImpl. + +#ifndef LIBGLESV2_RENDERER_QUERY9_H_ +#define LIBGLESV2_RENDERER_QUERY9_H_ + +#include "libGLESv2/renderer/QueryImpl.h" + +namespace rx +{ +class Renderer9; + +class Query9 : public QueryImpl +{ + public: + Query9(rx::Renderer9 *renderer, GLenum type); + virtual ~Query9(); + + void begin(); + void end(); + GLuint getResult(); + GLboolean isResultAvailable(); + + private: + DISALLOW_COPY_AND_ASSIGN(Query9); + + GLboolean testQuery(); + + rx::Renderer9 *mRenderer; + IDirect3DQuery9 *mQuery; +}; + +} + +#endif // LIBGLESV2_RENDERER_QUERY9_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/QueryImpl.h b/gfx/angle/src/libGLESv2/renderer/QueryImpl.h new file mode 100644 index 000000000000..a874047b0c26 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/QueryImpl.h @@ -0,0 +1,42 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// QueryImpl.h: Defines the abstract rx::QueryImpl class. + +#ifndef LIBGLESV2_RENDERER_QUERYIMPL_H_ +#define LIBGLESV2_RENDERER_QUERYIMPL_H_ + +#include "common/angleutils.h" + +namespace rx +{ + +class QueryImpl +{ + public: + explicit QueryImpl(GLenum type) : mType(type), mStatus(GL_FALSE), mResult(0) { } + virtual ~QueryImpl() { } + + virtual void begin() = 0; + virtual void end() = 0; + virtual GLuint getResult() = 0; + virtual GLboolean isResultAvailable() = 0; + + GLenum getType() const { return mType; } + + protected: + GLuint mResult; + GLboolean mStatus; + + private: + DISALLOW_COPY_AND_ASSIGN(QueryImpl); + + GLenum mType; +}; + +} + +#endif // LIBGLESV2_RENDERER_QUERYIMPL_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/RenderStateCache.cpp b/gfx/angle/src/libGLESv2/renderer/RenderStateCache.cpp new file mode 100644 index 000000000000..b3111af72be0 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/RenderStateCache.cpp @@ -0,0 +1,406 @@ +#include "precompiled.h" +// +// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// RenderStateCache.cpp: Defines rx::RenderStateCache, a cache of Direct3D render +// state objects. + +#include "libGLESv2/renderer/RenderStateCache.h" +#include "libGLESv2/renderer/renderer11_utils.h" + +#include "common/debug.h" +#include "third_party/murmurhash/MurmurHash3.h" + +namespace rx +{ + +// MSDN's documentation of ID3D11Device::CreateBlendState, ID3D11Device::CreateRasterizerState, +// ID3D11Device::CreateDepthStencilState and ID3D11Device::CreateSamplerState claims the maximum +// number of unique states of each type an application can create is 4096 +const unsigned int RenderStateCache::kMaxBlendStates = 4096; +const unsigned int RenderStateCache::kMaxRasterizerStates = 4096; +const unsigned int RenderStateCache::kMaxDepthStencilStates = 4096; +const unsigned int RenderStateCache::kMaxSamplerStates = 4096; + +RenderStateCache::RenderStateCache() : mDevice(NULL), mCounter(0), + mBlendStateCache(kMaxBlendStates, hashBlendState, compareBlendStates), + mRasterizerStateCache(kMaxRasterizerStates, hashRasterizerState, compareRasterizerStates), + mDepthStencilStateCache(kMaxDepthStencilStates, hashDepthStencilState, compareDepthStencilStates), + mSamplerStateCache(kMaxSamplerStates, hashSamplerState, compareSamplerStates) +{ +} + +RenderStateCache::~RenderStateCache() +{ + clear(); +} + +void RenderStateCache::initialize(ID3D11Device *device) +{ + clear(); + mDevice = device; +} + +void RenderStateCache::clear() +{ + for (BlendStateMap::iterator i = mBlendStateCache.begin(); i != mBlendStateCache.end(); i++) + { + i->second.first->Release(); + } + mBlendStateCache.clear(); + + for (RasterizerStateMap::iterator i = mRasterizerStateCache.begin(); i != mRasterizerStateCache.end(); i++) + { + i->second.first->Release(); + } + mRasterizerStateCache.clear(); + + for (DepthStencilStateMap::iterator i = mDepthStencilStateCache.begin(); i != mDepthStencilStateCache.end(); i++) + { + i->second.first->Release(); + } + mDepthStencilStateCache.clear(); + + for (SamplerStateMap::iterator i = mSamplerStateCache.begin(); i != mSamplerStateCache.end(); i++) + { + i->second.first->Release(); + } + mSamplerStateCache.clear(); +} + +std::size_t RenderStateCache::hashBlendState(const gl::BlendState &blendState) +{ + static const unsigned int seed = 0xABCDEF98; + + std::size_t hash = 0; + MurmurHash3_x86_32(&blendState, sizeof(gl::BlendState), seed, &hash); + return hash; +} + +bool RenderStateCache::compareBlendStates(const gl::BlendState &a, const gl::BlendState &b) +{ + return memcmp(&a, &b, sizeof(gl::BlendState)) == 0; +} + +ID3D11BlendState *RenderStateCache::getBlendState(const gl::BlendState &blendState) +{ + if (!mDevice) + { + ERR("RenderStateCache is not initialized."); + return NULL; + } + + BlendStateMap::iterator i = mBlendStateCache.find(blendState); + if (i != mBlendStateCache.end()) + { + BlendStateCounterPair &state = i->second; + state.second = mCounter++; + return state.first; + } + else + { + if (mBlendStateCache.size() >= kMaxBlendStates) + { + TRACE("Overflowed the limit of %u blend states, removing the least recently used " + "to make room.", kMaxBlendStates); + + BlendStateMap::iterator leastRecentlyUsed = mBlendStateCache.begin(); + for (BlendStateMap::iterator i = mBlendStateCache.begin(); i != mBlendStateCache.end(); i++) + { + if (i->second.second < leastRecentlyUsed->second.second) + { + leastRecentlyUsed = i; + } + } + leastRecentlyUsed->second.first->Release(); + mBlendStateCache.erase(leastRecentlyUsed); + } + + // Create a new blend state and insert it into the cache + D3D11_BLEND_DESC blendDesc = { 0 }; + blendDesc.AlphaToCoverageEnable = blendState.sampleAlphaToCoverage; + blendDesc.IndependentBlendEnable = FALSE; + + for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) + { + D3D11_RENDER_TARGET_BLEND_DESC &rtBlend = blendDesc.RenderTarget[i]; + + rtBlend.BlendEnable = blendState.blend; + if (blendState.blend) + { + rtBlend.SrcBlend = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendRGB, false); + rtBlend.DestBlend = gl_d3d11::ConvertBlendFunc(blendState.destBlendRGB, false); + rtBlend.BlendOp = gl_d3d11::ConvertBlendOp(blendState.blendEquationRGB); + + rtBlend.SrcBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendAlpha, true); + rtBlend.DestBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.destBlendAlpha, true); + rtBlend.BlendOpAlpha = gl_d3d11::ConvertBlendOp(blendState.blendEquationAlpha); + } + + rtBlend.RenderTargetWriteMask = gl_d3d11::ConvertColorMask(blendState.colorMaskRed, + blendState.colorMaskGreen, + blendState.colorMaskBlue, + blendState.colorMaskAlpha); + } + + ID3D11BlendState *dx11BlendState = NULL; + HRESULT result = mDevice->CreateBlendState(&blendDesc, &dx11BlendState); + if (FAILED(result) || !dx11BlendState) + { + ERR("Unable to create a ID3D11BlendState, HRESULT: 0x%X.", result); + return NULL; + } + + mBlendStateCache.insert(std::make_pair(blendState, std::make_pair(dx11BlendState, mCounter++))); + + return dx11BlendState; + } +} + +std::size_t RenderStateCache::hashRasterizerState(const RasterizerStateKey &rasterState) +{ + static const unsigned int seed = 0xABCDEF98; + + std::size_t hash = 0; + MurmurHash3_x86_32(&rasterState, sizeof(RasterizerStateKey), seed, &hash); + return hash; +} + +bool RenderStateCache::compareRasterizerStates(const RasterizerStateKey &a, const RasterizerStateKey &b) +{ + return memcmp(&a, &b, sizeof(RasterizerStateKey)) == 0; +} + +ID3D11RasterizerState *RenderStateCache::getRasterizerState(const gl::RasterizerState &rasterState, + bool scissorEnabled, unsigned int depthSize) +{ + if (!mDevice) + { + ERR("RenderStateCache is not initialized."); + return NULL; + } + + RasterizerStateKey key; + key.rasterizerState = rasterState; + key.scissorEnabled = scissorEnabled; + key.depthSize = depthSize; + + RasterizerStateMap::iterator i = mRasterizerStateCache.find(key); + if (i != mRasterizerStateCache.end()) + { + RasterizerStateCounterPair &state = i->second; + state.second = mCounter++; + return state.first; + } + else + { + if (mRasterizerStateCache.size() >= kMaxRasterizerStates) + { + TRACE("Overflowed the limit of %u rasterizer states, removing the least recently used " + "to make room.", kMaxRasterizerStates); + + RasterizerStateMap::iterator leastRecentlyUsed = mRasterizerStateCache.begin(); + for (RasterizerStateMap::iterator i = mRasterizerStateCache.begin(); i != mRasterizerStateCache.end(); i++) + { + if (i->second.second < leastRecentlyUsed->second.second) + { + leastRecentlyUsed = i; + } + } + leastRecentlyUsed->second.first->Release(); + mRasterizerStateCache.erase(leastRecentlyUsed); + } + + D3D11_CULL_MODE cullMode = gl_d3d11::ConvertCullMode(rasterState.cullFace, rasterState.cullMode); + + // Disable culling if drawing points + if (rasterState.pointDrawMode) + { + cullMode = D3D11_CULL_NONE; + } + + D3D11_RASTERIZER_DESC rasterDesc; + rasterDesc.FillMode = D3D11_FILL_SOLID; + rasterDesc.CullMode = cullMode; + rasterDesc.FrontCounterClockwise = (rasterState.frontFace == GL_CCW) ? FALSE: TRUE; + rasterDesc.DepthBias = ldexp(rasterState.polygonOffsetUnits, -static_cast(depthSize)); + rasterDesc.DepthBiasClamp = 0.0f; // MSDN documentation of DepthBiasClamp implies a value of zero will preform no clamping, must be tested though. + rasterDesc.SlopeScaledDepthBias = rasterState.polygonOffsetFactor; + rasterDesc.DepthClipEnable = TRUE; + rasterDesc.ScissorEnable = scissorEnabled ? TRUE : FALSE; + rasterDesc.MultisampleEnable = rasterState.multiSample; + rasterDesc.AntialiasedLineEnable = FALSE; + + ID3D11RasterizerState *dx11RasterizerState = NULL; + HRESULT result = mDevice->CreateRasterizerState(&rasterDesc, &dx11RasterizerState); + if (FAILED(result) || !dx11RasterizerState) + { + ERR("Unable to create a ID3D11RasterizerState, HRESULT: 0x%X.", result); + return NULL; + } + + mRasterizerStateCache.insert(std::make_pair(key, std::make_pair(dx11RasterizerState, mCounter++))); + + return dx11RasterizerState; + } +} + +std::size_t RenderStateCache::hashDepthStencilState(const gl::DepthStencilState &dsState) +{ + static const unsigned int seed = 0xABCDEF98; + + std::size_t hash = 0; + MurmurHash3_x86_32(&dsState, sizeof(gl::DepthStencilState), seed, &hash); + return hash; +} + +bool RenderStateCache::compareDepthStencilStates(const gl::DepthStencilState &a, const gl::DepthStencilState &b) +{ + return memcmp(&a, &b, sizeof(gl::DepthStencilState)) == 0; +} + +ID3D11DepthStencilState *RenderStateCache::getDepthStencilState(const gl::DepthStencilState &dsState) +{ + if (!mDevice) + { + ERR("RenderStateCache is not initialized."); + return NULL; + } + + DepthStencilStateMap::iterator i = mDepthStencilStateCache.find(dsState); + if (i != mDepthStencilStateCache.end()) + { + DepthStencilStateCounterPair &state = i->second; + state.second = mCounter++; + return state.first; + } + else + { + if (mDepthStencilStateCache.size() >= kMaxDepthStencilStates) + { + TRACE("Overflowed the limit of %u depth stencil states, removing the least recently used " + "to make room.", kMaxDepthStencilStates); + + DepthStencilStateMap::iterator leastRecentlyUsed = mDepthStencilStateCache.begin(); + for (DepthStencilStateMap::iterator i = mDepthStencilStateCache.begin(); i != mDepthStencilStateCache.end(); i++) + { + if (i->second.second < leastRecentlyUsed->second.second) + { + leastRecentlyUsed = i; + } + } + leastRecentlyUsed->second.first->Release(); + mDepthStencilStateCache.erase(leastRecentlyUsed); + } + + D3D11_DEPTH_STENCIL_DESC dsDesc = { 0 }; + dsDesc.DepthEnable = dsState.depthTest ? TRUE : FALSE; + dsDesc.DepthWriteMask = gl_d3d11::ConvertDepthMask(dsState.depthMask); + dsDesc.DepthFunc = gl_d3d11::ConvertComparison(dsState.depthFunc); + dsDesc.StencilEnable = dsState.stencilTest ? TRUE : FALSE; + dsDesc.StencilReadMask = gl_d3d11::ConvertStencilMask(dsState.stencilMask); + dsDesc.StencilWriteMask = gl_d3d11::ConvertStencilMask(dsState.stencilWritemask); + dsDesc.FrontFace.StencilFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilFail); + dsDesc.FrontFace.StencilDepthFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilPassDepthFail); + dsDesc.FrontFace.StencilPassOp = gl_d3d11::ConvertStencilOp(dsState.stencilPassDepthPass); + dsDesc.FrontFace.StencilFunc = gl_d3d11::ConvertComparison(dsState.stencilFunc); + dsDesc.BackFace.StencilFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilBackFail); + dsDesc.BackFace.StencilDepthFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilBackPassDepthFail); + dsDesc.BackFace.StencilPassOp = gl_d3d11::ConvertStencilOp(dsState.stencilBackPassDepthPass); + dsDesc.BackFace.StencilFunc = gl_d3d11::ConvertComparison(dsState.stencilBackFunc); + + ID3D11DepthStencilState *dx11DepthStencilState = NULL; + HRESULT result = mDevice->CreateDepthStencilState(&dsDesc, &dx11DepthStencilState); + if (FAILED(result) || !dx11DepthStencilState) + { + ERR("Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result); + return NULL; + } + + mDepthStencilStateCache.insert(std::make_pair(dsState, std::make_pair(dx11DepthStencilState, mCounter++))); + + return dx11DepthStencilState; + } +} + +std::size_t RenderStateCache::hashSamplerState(const gl::SamplerState &samplerState) +{ + static const unsigned int seed = 0xABCDEF98; + + std::size_t hash = 0; + MurmurHash3_x86_32(&samplerState, sizeof(gl::SamplerState), seed, &hash); + return hash; +} + +bool RenderStateCache::compareSamplerStates(const gl::SamplerState &a, const gl::SamplerState &b) +{ + return memcmp(&a, &b, sizeof(gl::SamplerState)) == 0; +} + +ID3D11SamplerState *RenderStateCache::getSamplerState(const gl::SamplerState &samplerState) +{ + if (!mDevice) + { + ERR("RenderStateCache is not initialized."); + return NULL; + } + + SamplerStateMap::iterator i = mSamplerStateCache.find(samplerState); + if (i != mSamplerStateCache.end()) + { + SamplerStateCounterPair &state = i->second; + state.second = mCounter++; + return state.first; + } + else + { + if (mSamplerStateCache.size() >= kMaxSamplerStates) + { + TRACE("Overflowed the limit of %u sampler states, removing the least recently used " + "to make room.", kMaxSamplerStates); + + SamplerStateMap::iterator leastRecentlyUsed = mSamplerStateCache.begin(); + for (SamplerStateMap::iterator i = mSamplerStateCache.begin(); i != mSamplerStateCache.end(); i++) + { + if (i->second.second < leastRecentlyUsed->second.second) + { + leastRecentlyUsed = i; + } + } + leastRecentlyUsed->second.first->Release(); + mSamplerStateCache.erase(leastRecentlyUsed); + } + + D3D11_SAMPLER_DESC samplerDesc; + samplerDesc.Filter = gl_d3d11::ConvertFilter(samplerState.minFilter, samplerState.magFilter, samplerState.maxAnisotropy); + samplerDesc.AddressU = gl_d3d11::ConvertTextureWrap(samplerState.wrapS); + samplerDesc.AddressV = gl_d3d11::ConvertTextureWrap(samplerState.wrapT); + samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; + samplerDesc.MipLODBias = static_cast(samplerState.lodOffset); + samplerDesc.MaxAnisotropy = samplerState.maxAnisotropy; + samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; + samplerDesc.BorderColor[0] = 0.0f; + samplerDesc.BorderColor[1] = 0.0f; + samplerDesc.BorderColor[2] = 0.0f; + samplerDesc.BorderColor[3] = 0.0f; + samplerDesc.MinLOD = gl_d3d11::ConvertMinLOD(samplerState.minFilter, samplerState.lodOffset); + samplerDesc.MaxLOD = gl_d3d11::ConvertMaxLOD(samplerState.minFilter, samplerState.lodOffset); + + ID3D11SamplerState *dx11SamplerState = NULL; + HRESULT result = mDevice->CreateSamplerState(&samplerDesc, &dx11SamplerState); + if (FAILED(result) || !dx11SamplerState) + { + ERR("Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result); + return NULL; + } + + mSamplerStateCache.insert(std::make_pair(samplerState, std::make_pair(dx11SamplerState, mCounter++))); + + return dx11SamplerState; + } +} + +} \ No newline at end of file diff --git a/gfx/angle/src/libGLESv2/renderer/RenderStateCache.h b/gfx/angle/src/libGLESv2/renderer/RenderStateCache.h new file mode 100644 index 000000000000..f8b5111de48f --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/RenderStateCache.h @@ -0,0 +1,101 @@ +// +// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// RenderStateCache.h: Defines rx::RenderStateCache, a cache of Direct3D render +// state objects. + +#ifndef LIBGLESV2_RENDERER_RENDERSTATECACHE_H_ +#define LIBGLESV2_RENDERER_RENDERSTATECACHE_H_ + +#include "libGLESv2/angletypes.h" +#include "common/angleutils.h" + +namespace rx +{ + +class RenderStateCache +{ + public: + RenderStateCache(); + virtual ~RenderStateCache(); + + void initialize(ID3D11Device *device); + void clear(); + + // Increments refcount on the returned blend state, Release() must be called. + ID3D11BlendState *getBlendState(const gl::BlendState &blendState); + ID3D11RasterizerState *getRasterizerState(const gl::RasterizerState &rasterState, + bool scissorEnabled, unsigned int depthSize); + ID3D11DepthStencilState *getDepthStencilState(const gl::DepthStencilState &dsState); + ID3D11SamplerState *getSamplerState(const gl::SamplerState &samplerState); + + private: + DISALLOW_COPY_AND_ASSIGN(RenderStateCache); + + unsigned long long mCounter; + + // Blend state cache + static std::size_t hashBlendState(const gl::BlendState &blendState); + static bool compareBlendStates(const gl::BlendState &a, const gl::BlendState &b); + static const unsigned int kMaxBlendStates; + + typedef std::size_t (*BlendStateHashFunction)(const gl::BlendState &); + typedef bool (*BlendStateEqualityFunction)(const gl::BlendState &, const gl::BlendState &); + typedef std::pair BlendStateCounterPair; + typedef std::unordered_map BlendStateMap; + BlendStateMap mBlendStateCache; + + // Rasterizer state cache + struct RasterizerStateKey + { + gl::RasterizerState rasterizerState; + bool scissorEnabled; + unsigned int depthSize; + }; + static std::size_t hashRasterizerState(const RasterizerStateKey &rasterState); + static bool compareRasterizerStates(const RasterizerStateKey &a, const RasterizerStateKey &b); + static const unsigned int kMaxRasterizerStates; + + typedef std::size_t (*RasterizerStateHashFunction)(const RasterizerStateKey &); + typedef bool (*RasterizerStateEqualityFunction)(const RasterizerStateKey &, const RasterizerStateKey &); + typedef std::pair RasterizerStateCounterPair; + typedef std::unordered_map RasterizerStateMap; + RasterizerStateMap mRasterizerStateCache; + + // Depth stencil state cache + static std::size_t hashDepthStencilState(const gl::DepthStencilState &dsState); + static bool compareDepthStencilStates(const gl::DepthStencilState &a, const gl::DepthStencilState &b); + static const unsigned int kMaxDepthStencilStates; + + typedef std::size_t (*DepthStencilStateHashFunction)(const gl::DepthStencilState &); + typedef bool (*DepthStencilStateEqualityFunction)(const gl::DepthStencilState &, const gl::DepthStencilState &); + typedef std::pair DepthStencilStateCounterPair; + typedef std::unordered_map DepthStencilStateMap; + DepthStencilStateMap mDepthStencilStateCache; + + // Sample state cache + static std::size_t hashSamplerState(const gl::SamplerState &samplerState); + static bool compareSamplerStates(const gl::SamplerState &a, const gl::SamplerState &b); + static const unsigned int kMaxSamplerStates; + + typedef std::size_t (*SamplerStateHashFunction)(const gl::SamplerState &); + typedef bool (*SamplerStateEqualityFunction)(const gl::SamplerState &, const gl::SamplerState &); + typedef std::pair SamplerStateCounterPair; + typedef std::unordered_map SamplerStateMap; + SamplerStateMap mSamplerStateCache; + + ID3D11Device *mDevice; +}; + +} + +#endif // LIBGLESV2_RENDERER_RENDERSTATECACHE_H_ \ No newline at end of file diff --git a/gfx/angle/src/libGLESv2/renderer/RenderTarget.h b/gfx/angle/src/libGLESv2/renderer/RenderTarget.h new file mode 100644 index 000000000000..80de39f4f766 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/RenderTarget.h @@ -0,0 +1,56 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// RenderTarget.h: Defines an abstract wrapper class to manage IDirect3DSurface9 +// and ID3D11View objects belonging to renderbuffers. + +#ifndef LIBGLESV2_RENDERER_RENDERTARGET_H_ +#define LIBGLESV2_RENDERER_RENDERTARGET_H_ + +#include "common/angleutils.h" + +namespace rx +{ +class RenderTarget +{ + public: + RenderTarget() + { + mWidth = 0; + mHeight = 0; + mInternalFormat = GL_NONE; + mActualFormat = GL_NONE; + mSamples = 0; + } + + virtual ~RenderTarget() {}; + + GLsizei getWidth() { return mWidth; } + GLsizei getHeight() { return mHeight; } + GLenum getInternalFormat() { return mInternalFormat; } + GLenum getActualFormat() { return mActualFormat; } + GLsizei getSamples() { return mSamples; } + + struct Desc { + GLsizei width; + GLsizei height; + GLenum format; + }; + + protected: + GLsizei mWidth; + GLsizei mHeight; + GLenum mInternalFormat; + GLenum mActualFormat; + GLsizei mSamples; + + private: + DISALLOW_COPY_AND_ASSIGN(RenderTarget); +}; + +} + +#endif // LIBGLESV2_RENDERTARGET_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/RenderTarget11.cpp b/gfx/angle/src/libGLESv2/renderer/RenderTarget11.cpp new file mode 100644 index 000000000000..2667cc6fa781 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/RenderTarget11.cpp @@ -0,0 +1,355 @@ +#include "precompiled.h" +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// RenderTarget11.cpp: Implements a DX11-specific wrapper for ID3D11View pointers +// retained by Renderbuffers. + +#include "libGLESv2/renderer/RenderTarget11.h" +#include "libGLESv2/renderer/Renderer11.h" + +#include "libGLESv2/renderer/renderer11_utils.h" +#include "libGLESv2/main.h" + +namespace rx +{ + +static unsigned int getRTVSubresourceIndex(ID3D11Texture2D *texture, ID3D11RenderTargetView *view) +{ + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + view->GetDesc(&rtvDesc); + + D3D11_TEXTURE2D_DESC texDesc; + texture->GetDesc(&texDesc); + + unsigned int mipSlice = 0; + unsigned int arraySlice = 0; + unsigned int mipLevels = texDesc.MipLevels; + + switch (rtvDesc.ViewDimension) + { + case D3D11_RTV_DIMENSION_TEXTURE1D: + mipSlice = rtvDesc.Texture1D.MipSlice; + arraySlice = 0; + break; + + case D3D11_RTV_DIMENSION_TEXTURE1DARRAY: + mipSlice = rtvDesc.Texture1DArray.MipSlice; + arraySlice = rtvDesc.Texture1DArray.FirstArraySlice; + break; + + case D3D11_RTV_DIMENSION_TEXTURE2D: + mipSlice = rtvDesc.Texture2D.MipSlice; + arraySlice = 0; + break; + + case D3D11_RTV_DIMENSION_TEXTURE2DARRAY: + mipSlice = rtvDesc.Texture2DArray.MipSlice; + arraySlice = rtvDesc.Texture2DArray.FirstArraySlice; + break; + + case D3D11_RTV_DIMENSION_TEXTURE2DMS: + mipSlice = 0; + arraySlice = 0; + break; + + case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY: + mipSlice = 0; + arraySlice = rtvDesc.Texture2DMSArray.FirstArraySlice; + break; + + case D3D11_RTV_DIMENSION_TEXTURE3D: + mipSlice = rtvDesc.Texture3D.MipSlice; + arraySlice = 0; + break; + + case D3D11_RTV_DIMENSION_UNKNOWN: + case D3D11_RTV_DIMENSION_BUFFER: + UNIMPLEMENTED(); + break; + + default: + UNREACHABLE(); + break; + } + + return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels); +} + +static unsigned int getDSVSubresourceIndex(ID3D11Texture2D *texture, ID3D11DepthStencilView *view) +{ + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; + view->GetDesc(&dsvDesc); + + D3D11_TEXTURE2D_DESC texDesc; + texture->GetDesc(&texDesc); + + unsigned int mipSlice = 0; + unsigned int arraySlice = 0; + unsigned int mipLevels = texDesc.MipLevels; + + switch (dsvDesc.ViewDimension) + { + case D3D11_DSV_DIMENSION_TEXTURE1D: + mipSlice = dsvDesc.Texture1D.MipSlice; + arraySlice = 0; + break; + + case D3D11_DSV_DIMENSION_TEXTURE1DARRAY: + mipSlice = dsvDesc.Texture1DArray.MipSlice; + arraySlice = dsvDesc.Texture1DArray.FirstArraySlice; + break; + + case D3D11_DSV_DIMENSION_TEXTURE2D: + mipSlice = dsvDesc.Texture2D.MipSlice; + arraySlice = 0; + break; + + case D3D11_DSV_DIMENSION_TEXTURE2DARRAY: + mipSlice = dsvDesc.Texture2DArray.MipSlice; + arraySlice = dsvDesc.Texture2DArray.FirstArraySlice; + break; + + case D3D11_DSV_DIMENSION_TEXTURE2DMS: + mipSlice = 0; + arraySlice = 0; + break; + + case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY: + mipSlice = 0; + arraySlice = dsvDesc.Texture2DMSArray.FirstArraySlice; + break; + + case D3D11_RTV_DIMENSION_UNKNOWN: + UNIMPLEMENTED(); + break; + + default: + UNREACHABLE(); + break; + } + + return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels); +} + +RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11RenderTargetView *rtv, ID3D11Texture2D *tex, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height) +{ + mRenderer = Renderer11::makeRenderer11(renderer); + mTexture = tex; + mRenderTarget = rtv; + mDepthStencil = NULL; + mShaderResource = srv; + mSubresourceIndex = 0; + + if (mRenderTarget && mTexture) + { + D3D11_RENDER_TARGET_VIEW_DESC desc; + mRenderTarget->GetDesc(&desc); + + D3D11_TEXTURE2D_DESC texDesc; + mTexture->GetDesc(&texDesc); + + mSubresourceIndex = getRTVSubresourceIndex(mTexture, mRenderTarget); + mWidth = width; + mHeight = height; + mSamples = (texDesc.SampleDesc.Count > 1) ? texDesc.SampleDesc.Count : 0; + + mInternalFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format); + mActualFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format); + } +} + +RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11DepthStencilView *dsv, ID3D11Texture2D *tex, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height) +{ + mRenderer = Renderer11::makeRenderer11(renderer); + mTexture = tex; + mRenderTarget = NULL; + mDepthStencil = dsv; + mShaderResource = srv; + mSubresourceIndex = 0; + + if (mDepthStencil && mTexture) + { + D3D11_DEPTH_STENCIL_VIEW_DESC desc; + mDepthStencil->GetDesc(&desc); + + D3D11_TEXTURE2D_DESC texDesc; + mTexture->GetDesc(&texDesc); + + mSubresourceIndex = getDSVSubresourceIndex(mTexture, mDepthStencil); + mWidth = width; + mHeight = height; + mSamples = (texDesc.SampleDesc.Count > 1) ? texDesc.SampleDesc.Count : 0; + + mInternalFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format); + mActualFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format); + } +} + +RenderTarget11::RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples, bool depth) +{ + mRenderer = Renderer11::makeRenderer11(renderer); + mTexture = NULL; + mRenderTarget = NULL; + mDepthStencil = NULL; + mShaderResource = NULL; + + DXGI_FORMAT requestedFormat = gl_d3d11::ConvertRenderbufferFormat(format); + + int supportedSamples = mRenderer->getNearestSupportedSamples(requestedFormat, samples); + if (supportedSamples < 0) + { + gl::error(GL_OUT_OF_MEMORY); + return; + } + + if (width > 0 && height > 0) + { + // Create texture resource + D3D11_TEXTURE2D_DESC desc; + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = requestedFormat; + desc.SampleDesc.Count = (supportedSamples == 0) ? 1 : supportedSamples; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + desc.BindFlags = (depth ? D3D11_BIND_DEPTH_STENCIL : (D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE)); + + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture); + + if (result == E_OUTOFMEMORY) + { + gl::error(GL_OUT_OF_MEMORY); + return; + } + ASSERT(SUCCEEDED(result)); + + if (depth) + { + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; + dsvDesc.Format = requestedFormat; + dsvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_DSV_DIMENSION_TEXTURE2D : D3D11_DSV_DIMENSION_TEXTURE2DMS; + dsvDesc.Texture2D.MipSlice = 0; + dsvDesc.Flags = 0; + result = device->CreateDepthStencilView(mTexture, &dsvDesc, &mDepthStencil); + + if (result == E_OUTOFMEMORY) + { + mTexture->Release(); + mTexture = NULL; + gl::error(GL_OUT_OF_MEMORY); + } + ASSERT(SUCCEEDED(result)); + } + else + { + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = requestedFormat; + rtvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_RTV_DIMENSION_TEXTURE2D : D3D11_RTV_DIMENSION_TEXTURE2DMS; + rtvDesc.Texture2D.MipSlice = 0; + result = device->CreateRenderTargetView(mTexture, &rtvDesc, &mRenderTarget); + + if (result == E_OUTOFMEMORY) + { + mTexture->Release(); + mTexture = NULL; + gl::error(GL_OUT_OF_MEMORY); + return; + } + ASSERT(SUCCEEDED(result)); + + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = requestedFormat; + srvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_SRV_DIMENSION_TEXTURE2D : D3D11_SRV_DIMENSION_TEXTURE2DMS; + srvDesc.Texture2D.MostDetailedMip = 0; + srvDesc.Texture2D.MipLevels = 1; + result = device->CreateShaderResourceView(mTexture, &srvDesc, &mShaderResource); + + if (result == E_OUTOFMEMORY) + { + mTexture->Release(); + mTexture = NULL; + mRenderTarget->Release(); + mRenderTarget = NULL; + gl::error(GL_OUT_OF_MEMORY); + return; + } + ASSERT(SUCCEEDED(result)); + } + } + + mWidth = width; + mHeight = height; + mInternalFormat = format; + mSamples = supportedSamples; + mActualFormat = d3d11_gl::ConvertTextureInternalFormat(requestedFormat); + mSubresourceIndex = D3D11CalcSubresource(0, 0, 1); +} + +RenderTarget11::~RenderTarget11() +{ + if (mTexture) + { + mTexture->Release(); + mTexture = NULL; + } + + if (mRenderTarget) + { + mRenderTarget->Release(); + mRenderTarget = NULL; + } + + if (mDepthStencil) + { + mDepthStencil->Release(); + mDepthStencil = NULL; + } + + if (mShaderResource) + { + mShaderResource->Release(); + mShaderResource = NULL; + } +} + +RenderTarget11 *RenderTarget11::makeRenderTarget11(RenderTarget *target) +{ + ASSERT(HAS_DYNAMIC_TYPE(rx::RenderTarget11*, target)); + return static_cast(target); +} + +ID3D11Texture2D *RenderTarget11::getTexture() const +{ + return mTexture; +} + +ID3D11RenderTargetView *RenderTarget11::getRenderTargetView() const +{ + return mRenderTarget; +} + +ID3D11DepthStencilView *RenderTarget11::getDepthStencilView() const +{ + return mDepthStencil; +} + +ID3D11ShaderResourceView *RenderTarget11::getShaderResourceView() const +{ + return mShaderResource; +} + +unsigned int RenderTarget11::getSubresourceIndex() const +{ + return mSubresourceIndex; +} + +} diff --git a/gfx/angle/src/libGLESv2/renderer/RenderTarget11.h b/gfx/angle/src/libGLESv2/renderer/RenderTarget11.h new file mode 100644 index 000000000000..97827f263970 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/RenderTarget11.h @@ -0,0 +1,51 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// RenderTarget11.h: Defines a DX11-specific wrapper for ID3D11View pointers +// retained by Renderbuffers. + +#ifndef LIBGLESV2_RENDERER_RENDERTARGET11_H_ +#define LIBGLESV2_RENDERER_RENDERTARGET11_H_ + +#include "libGLESv2/renderer/RenderTarget.h" + +namespace rx +{ +class Renderer; +class Renderer11; + +class RenderTarget11 : public RenderTarget +{ + public: + RenderTarget11(Renderer *renderer, ID3D11RenderTargetView *rtv, ID3D11Texture2D *tex, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height); + RenderTarget11(Renderer *renderer, ID3D11DepthStencilView *dsv, ID3D11Texture2D *tex, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height); + RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples, bool depth); + virtual ~RenderTarget11(); + + static RenderTarget11 *makeRenderTarget11(RenderTarget *renderTarget); + + ID3D11Texture2D *getTexture() const; + ID3D11RenderTargetView *getRenderTargetView() const; + ID3D11DepthStencilView *getDepthStencilView() const; + ID3D11ShaderResourceView *getShaderResourceView() const; + + unsigned int getSubresourceIndex() const; + + private: + DISALLOW_COPY_AND_ASSIGN(RenderTarget11); + + unsigned int mSubresourceIndex; + ID3D11Texture2D *mTexture; + ID3D11RenderTargetView *mRenderTarget; + ID3D11DepthStencilView *mDepthStencil; + ID3D11ShaderResourceView *mShaderResource; + + Renderer11 *mRenderer; +}; + +} + +#endif LIBGLESV2_RENDERER_RENDERTARGET11_H_ \ No newline at end of file diff --git a/gfx/angle/src/libGLESv2/renderer/RenderTarget9.cpp b/gfx/angle/src/libGLESv2/renderer/RenderTarget9.cpp new file mode 100644 index 000000000000..a84c7090599c --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/RenderTarget9.cpp @@ -0,0 +1,113 @@ +#include "precompiled.h" +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// RenderTarget9.cpp: Implements a D3D9-specific wrapper for IDirect3DSurface9 +// pointers retained by renderbuffers. + +#include "libGLESv2/renderer/RenderTarget9.h" +#include "libGLESv2/renderer/Renderer9.h" + +#include "libGLESv2/renderer/renderer9_utils.h" +#include "libGLESv2/main.h" + +namespace rx +{ + +RenderTarget9::RenderTarget9(Renderer *renderer, IDirect3DSurface9 *surface) +{ + mRenderer = Renderer9::makeRenderer9(renderer); + mRenderTarget = surface; + + if (mRenderTarget) + { + D3DSURFACE_DESC description; + mRenderTarget->GetDesc(&description); + + mWidth = description.Width; + mHeight = description.Height; + + mInternalFormat = d3d9_gl::GetEquivalentFormat(description.Format); + mActualFormat = d3d9_gl::GetEquivalentFormat(description.Format); + mSamples = d3d9_gl::GetSamplesFromMultisampleType(description.MultiSampleType); + } +} + +RenderTarget9::RenderTarget9(Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples) +{ + mRenderer = Renderer9::makeRenderer9(renderer); + mRenderTarget = NULL; + + D3DFORMAT requestedFormat = gl_d3d9::ConvertRenderbufferFormat(format); + int supportedSamples = mRenderer->getNearestSupportedSamples(requestedFormat, samples); + + if (supportedSamples == -1) + { + gl::error(GL_OUT_OF_MEMORY); + + return; + } + + HRESULT result = D3DERR_INVALIDCALL; + + if (width > 0 && height > 0) + { + if (requestedFormat == D3DFMT_D24S8) + { + result = mRenderer->getDevice()->CreateDepthStencilSurface(width, height, requestedFormat, + gl_d3d9::GetMultisampleTypeFromSamples(supportedSamples), + 0, FALSE, &mRenderTarget, NULL); + } + else + { + result = mRenderer->getDevice()->CreateRenderTarget(width, height, requestedFormat, + gl_d3d9::GetMultisampleTypeFromSamples(supportedSamples), + 0, FALSE, &mRenderTarget, NULL); + } + + if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY) + { + gl::error(GL_OUT_OF_MEMORY); + + return; + } + + ASSERT(SUCCEEDED(result)); + } + + mWidth = width; + mHeight = height; + mInternalFormat = format; + mSamples = supportedSamples; + mActualFormat = d3d9_gl::GetEquivalentFormat(requestedFormat); +} + +RenderTarget9::~RenderTarget9() +{ + if (mRenderTarget) + { + mRenderTarget->Release(); + } +} + +RenderTarget9 *RenderTarget9::makeRenderTarget9(RenderTarget *target) +{ + ASSERT(HAS_DYNAMIC_TYPE(rx::RenderTarget9*, target)); + return static_cast(target); +} + +IDirect3DSurface9 *RenderTarget9::getSurface() +{ + // Caller is responsible for releasing the returned surface reference. + if (mRenderTarget) + { + mRenderTarget->AddRef(); + } + + return mRenderTarget; +} + +} \ No newline at end of file diff --git a/gfx/angle/src/libGLESv2/renderer/RenderTarget9.h b/gfx/angle/src/libGLESv2/renderer/RenderTarget9.h new file mode 100644 index 000000000000..faf8ad1c6d2d --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/RenderTarget9.h @@ -0,0 +1,40 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// RenderTarget9.h: Defines a D3D9-specific wrapper for IDirect3DSurface9 pointers +// retained by Renderbuffers. + +#ifndef LIBGLESV2_RENDERER_RENDERTARGET9_H_ +#define LIBGLESV2_RENDERER_RENDERTARGET9_H_ + +#include "libGLESv2/renderer/RenderTarget.h" + +namespace rx +{ +class Renderer; +class Renderer9; + +class RenderTarget9 : public RenderTarget +{ + public: + RenderTarget9(Renderer *renderer, IDirect3DSurface9 *surface); + RenderTarget9(Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples); + virtual ~RenderTarget9(); + + static RenderTarget9 *makeRenderTarget9(RenderTarget *renderTarget); + IDirect3DSurface9 *getSurface(); + + private: + DISALLOW_COPY_AND_ASSIGN(RenderTarget9); + + IDirect3DSurface9 *mRenderTarget; + + Renderer9 *mRenderer; +}; + +} + +#endif // LIBGLESV2_RENDERER_RENDERTARGET9_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/Renderer.cpp b/gfx/angle/src/libGLESv2/renderer/Renderer.cpp new file mode 100644 index 000000000000..32074ea64e59 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/Renderer.cpp @@ -0,0 +1,227 @@ +#include "precompiled.h" +// +// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Renderer.cpp: Implements EGL dependencies for creating and destroying Renderer instances. + +#include +#include "libGLESv2/main.h" +#include "libGLESv2/Program.h" +#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/renderer/Renderer9.h" +#include "libGLESv2/renderer/Renderer11.h" +#include "libGLESv2/utilities.h" + +#if !defined(ANGLE_ENABLE_D3D11) +// Enables use of the Direct3D 11 API for a default display, when available +#define ANGLE_ENABLE_D3D11 0 +#endif + +#define ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES \ + { \ + TEXT("d3dcompiler_46.dll"), \ + TEXT("d3dcompiler_43.dll") \ + } + + +namespace rx +{ + +Renderer::Renderer(egl::Display *display) : mDisplay(display) +{ + mD3dCompilerModule = NULL; + mD3DCompileFunc = NULL; +} + +Renderer::~Renderer() +{ + if (mD3dCompilerModule) + { + FreeLibrary(mD3dCompilerModule); + mD3dCompilerModule = NULL; + } +} + +bool Renderer::initializeCompiler() +{ +#if defined(ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES) + // Find a D3DCompiler module that had already been loaded based on a predefined list of versions. + static TCHAR* d3dCompilerNames[] = ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES; + + for (size_t i = 0; i < ArraySize(d3dCompilerNames); ++i) + { + if (GetModuleHandleEx(0, d3dCompilerNames[i], &mD3dCompilerModule)) + { + break; + } + } +#else + // Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was built with. + mD3dCompilerModule = LoadLibrary(D3DCOMPILER_DLL); +#endif // ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES + + if (!mD3dCompilerModule) + { + ERR("No D3D compiler module found - aborting!\n"); + return false; + } + + mD3DCompileFunc = reinterpret_cast(GetProcAddress(mD3dCompilerModule, "D3DCompile")); + ASSERT(mD3DCompileFunc); + + return mD3DCompileFunc != NULL; +} + +// Compiles HLSL code into executable binaries +ShaderBlob *Renderer::compileToBinary(gl::InfoLog &infoLog, const char *hlsl, const char *profile, UINT optimizationFlags, bool alternateFlags) +{ + if (!hlsl) + { + return NULL; + } + + HRESULT result = S_OK; + UINT flags = 0; + std::string sourceText; + if (gl::perfActive()) + { + flags |= D3DCOMPILE_DEBUG; + +#ifdef NDEBUG + flags |= optimizationFlags; +#else + flags |= D3DCOMPILE_SKIP_OPTIMIZATION; +#endif + + std::string sourcePath = getTempPath(); + sourceText = std::string("#line 2 \"") + sourcePath + std::string("\"\n\n") + std::string(hlsl); + writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size()); + } + else + { + flags |= optimizationFlags; + sourceText = hlsl; + } + + // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders when it would otherwise pass with alternative options. + // Try the default flags first and if compilation fails, try some alternatives. + const static UINT extraFlags[] = + { + 0, + D3DCOMPILE_AVOID_FLOW_CONTROL, + D3DCOMPILE_PREFER_FLOW_CONTROL + }; + + const static char * const extraFlagNames[] = + { + "default", + "avoid flow control", + "prefer flow control" + }; + + int attempts = alternateFlags ? ArraySize(extraFlags) : 1; + pD3DCompile compileFunc = reinterpret_cast(mD3DCompileFunc); + for (int i = 0; i < attempts; ++i) + { + ID3DBlob *errorMessage = NULL; + ID3DBlob *binary = NULL; + + result = compileFunc(hlsl, strlen(hlsl), gl::g_fakepath, NULL, NULL, + "main", profile, flags | extraFlags[i], 0, &binary, &errorMessage); + if (errorMessage) + { + const char *message = (const char*)errorMessage->GetBufferPointer(); + + infoLog.appendSanitized(message); + TRACE("\n%s", hlsl); + TRACE("\n%s", message); + + errorMessage->Release(); + errorMessage = NULL; + } + + if (SUCCEEDED(result)) + { + return (ShaderBlob*)binary; + } + else + { + if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY) + { + return gl::error(GL_OUT_OF_MEMORY, (ShaderBlob*) NULL); + } + + infoLog.append("Warning: D3D shader compilation failed with "); + infoLog.append(extraFlagNames[i]); + infoLog.append(" flags."); + if (i + 1 < attempts) + { + infoLog.append(" Retrying with "); + infoLog.append(extraFlagNames[i + 1]); + infoLog.append(".\n"); + } + } + } + + return NULL; +} + +} + +extern "C" +{ + +rx::Renderer *glCreateRenderer(egl::Display *display, HDC hDc, EGLNativeDisplayType displayId) +{ + rx::Renderer *renderer = NULL; + EGLint status = EGL_BAD_ALLOC; + + if (ANGLE_ENABLE_D3D11 || + displayId == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE || + displayId == EGL_D3D11_ONLY_DISPLAY_ANGLE) + { + renderer = new rx::Renderer11(display, hDc); + + if (renderer) + { + status = renderer->initialize(); + } + + if (status == EGL_SUCCESS) + { + return renderer; + } + else if (displayId == EGL_D3D11_ONLY_DISPLAY_ANGLE) + { + return NULL; + } + + // Failed to create a D3D11 renderer, try creating a D3D9 renderer + delete renderer; + } + + bool softwareDevice = (displayId == EGL_SOFTWARE_DISPLAY_ANGLE); + renderer = new rx::Renderer9(display, hDc, softwareDevice); + + if (renderer) + { + status = renderer->initialize(); + } + + if (status == EGL_SUCCESS) + { + return renderer; + } + + return NULL; +} + +void glDestroyRenderer(rx::Renderer *renderer) +{ + delete renderer; +} + +} diff --git a/gfx/angle/src/libGLESv2/renderer/Renderer.h b/gfx/angle/src/libGLESv2/renderer/Renderer.h new file mode 100644 index 000000000000..04e877ba9e7c --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/Renderer.h @@ -0,0 +1,244 @@ +// +// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Renderer.h: Defines a back-end specific class that hides the details of the +// implementation-specific renderer. + +#ifndef LIBGLESV2_RENDERER_RENDERER_H_ +#define LIBGLESV2_RENDERER_RENDERER_H_ + +#include "libGLESv2/Uniform.h" +#include "libGLESv2/angletypes.h" + +#if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL) +#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3 +#endif + +const int versionWindowsVista = MAKEWORD(0x00, 0x06); +const int versionWindows7 = MAKEWORD(0x01, 0x06); + +// Return the version of the operating system in a format suitable for ordering +// comparison. +inline int getComparableOSVersion() +{ + DWORD version = GetVersion(); + int majorVersion = LOBYTE(LOWORD(version)); + int minorVersion = HIBYTE(LOWORD(version)); + return MAKEWORD(minorVersion, majorVersion); +} + +namespace egl +{ +class Display; +} + +namespace gl +{ +class InfoLog; +class ProgramBinary; +class VertexAttribute; +class Buffer; +class Texture; +class Framebuffer; +} + +namespace rx +{ +class TextureStorageInterface2D; +class TextureStorageInterfaceCube; +class VertexBuffer; +class IndexBuffer; +class QueryImpl; +class FenceImpl; +class BufferStorage; +class Blit; +struct TranslatedIndexData; +class ShaderExecutable; +class SwapChain; +class RenderTarget; +class Image; +class TextureStorage; + +typedef void * ShaderBlob; +typedef void (*pCompileFunc)(); + +struct ConfigDesc +{ + GLenum renderTargetFormat; + GLenum depthStencilFormat; + GLint multiSample; + bool fastConfig; +}; + +struct dx_VertexConstants +{ + float depthRange[4]; + float viewAdjust[4]; +}; + +struct dx_PixelConstants +{ + float depthRange[4]; + float viewCoords[4]; + float depthFront[4]; +}; + +enum ShaderType +{ + SHADER_VERTEX, + SHADER_PIXEL, + SHADER_GEOMETRY +}; + +class Renderer +{ + public: + explicit Renderer(egl::Display *display); + virtual ~Renderer(); + + virtual EGLint initialize() = 0; + virtual bool resetDevice() = 0; + + virtual int generateConfigs(ConfigDesc **configDescList) = 0; + virtual void deleteConfigs(ConfigDesc *configDescList) = 0; + + virtual void sync(bool block) = 0; + + virtual SwapChain *createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) = 0; + + virtual void setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler) = 0; + virtual void setTexture(gl::SamplerType type, int index, gl::Texture *texture) = 0; + + virtual void setRasterizerState(const gl::RasterizerState &rasterState) = 0; + virtual void setBlendState(const gl::BlendState &blendState, const gl::Color &blendColor, + unsigned int sampleMask) = 0; + virtual void setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, + int stencilBackRef, bool frontFaceCCW) = 0; + + virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled) = 0; + virtual bool setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, + bool ignoreViewport) = 0; + + virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer) = 0; + virtual void applyShaders(gl::ProgramBinary *programBinary) = 0; + virtual void applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray) = 0; + virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount) = 0; + virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances) = 0; + virtual GLenum applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) = 0; + + virtual void drawArrays(GLenum mode, GLsizei count, GLsizei instances) = 0; + virtual void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances) = 0; + + virtual void clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) = 0; + + virtual void markAllStateDirty() = 0; + + // lost device + virtual void notifyDeviceLost() = 0; + virtual bool isDeviceLost() = 0; + virtual bool testDeviceLost(bool notify) = 0; + virtual bool testDeviceResettable() = 0; + + // Renderer capabilities + virtual DWORD getAdapterVendor() const = 0; + virtual std::string getRendererDescription() const = 0; + virtual GUID getAdapterIdentifier() const = 0; + + virtual bool getBGRATextureSupport() const = 0; + virtual bool getDXT1TextureSupport() = 0; + virtual bool getDXT3TextureSupport() = 0; + virtual bool getDXT5TextureSupport() = 0; + virtual bool getEventQuerySupport() = 0; + virtual bool getFloat32TextureSupport(bool *filtering, bool *renderable) = 0; + virtual bool getFloat16TextureSupport(bool *filtering, bool *renderable) = 0; + virtual bool getLuminanceTextureSupport() = 0; + virtual bool getLuminanceAlphaTextureSupport() = 0; + bool getVertexTextureSupport() const { return getMaxVertexTextureImageUnits() > 0; } + virtual unsigned int getMaxVertexTextureImageUnits() const = 0; + virtual unsigned int getMaxCombinedTextureImageUnits() const = 0; + virtual unsigned int getReservedVertexUniformVectors() const = 0; + virtual unsigned int getReservedFragmentUniformVectors() const = 0; + virtual unsigned int getMaxVertexUniformVectors() const = 0; + virtual unsigned int getMaxFragmentUniformVectors() const = 0; + virtual unsigned int getMaxVaryingVectors() const = 0; + virtual bool getNonPower2TextureSupport() const = 0; + virtual bool getDepthTextureSupport() const = 0; + virtual bool getOcclusionQuerySupport() const = 0; + virtual bool getInstancingSupport() const = 0; + virtual bool getTextureFilterAnisotropySupport() const = 0; + virtual float getTextureMaxAnisotropy() const = 0; + virtual bool getShareHandleSupport() const = 0; + virtual bool getDerivativeInstructionSupport() const = 0; + virtual bool getPostSubBufferSupport() const = 0; + + virtual int getMajorShaderModel() const = 0; + virtual float getMaxPointSize() const = 0; + virtual int getMaxViewportDimension() const = 0; + virtual int getMaxTextureWidth() const = 0; + virtual int getMaxTextureHeight() const = 0; + virtual bool get32BitIndexSupport() const = 0; + virtual int getMinSwapInterval() const = 0; + virtual int getMaxSwapInterval() const = 0; + + virtual GLsizei getMaxSupportedSamples() const = 0; + + virtual unsigned int getMaxRenderTargets() const = 0; + + // Pixel operations + virtual bool copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source) = 0; + virtual bool copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source) = 0; + + virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level) = 0; + virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level) = 0; + + virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, + bool blitRenderTarget, bool blitDepthStencil) = 0; + virtual void readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, + GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels) = 0; + + // RenderTarget creation + virtual RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth) = 0; + virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth) = 0; + + // Shader operations + virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type) = 0; + virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type) = 0; + + // Image operations + virtual Image *createImage() = 0; + virtual void generateMipmap(Image *dest, Image *source) = 0; + virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain) = 0; + virtual TextureStorage *createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height) = 0; + virtual TextureStorage *createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size) = 0; + + // Buffer creation + virtual VertexBuffer *createVertexBuffer() = 0; + virtual IndexBuffer *createIndexBuffer() = 0; + virtual BufferStorage *createBufferStorage() = 0; + + // Query and Fence creation + virtual QueryImpl *createQuery(GLenum type) = 0; + virtual FenceImpl *createFence() = 0; + + virtual bool getLUID(LUID *adapterLuid) const = 0; + + protected: + bool initializeCompiler(); + ShaderBlob *compileToBinary(gl::InfoLog &infoLog, const char *hlsl, const char *profile, UINT optimizationFlags, bool alternateFlags); + + egl::Display *mDisplay; + + private: + DISALLOW_COPY_AND_ASSIGN(Renderer); + + HMODULE mD3dCompilerModule; + pCompileFunc mD3DCompileFunc; +}; + +} +#endif // LIBGLESV2_RENDERER_RENDERER_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/Renderer11.cpp b/gfx/angle/src/libGLESv2/renderer/Renderer11.cpp new file mode 100644 index 000000000000..774cd714f2fa --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/Renderer11.cpp @@ -0,0 +1,3535 @@ +#include "precompiled.h" +// +// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Renderer11.cpp: Implements a back-end specific class for the D3D11 renderer. + +#include "libGLESv2/main.h" +#include "libGLESv2/utilities.h" +#include "libGLESv2/Buffer.h" +#include "libGLESv2/ProgramBinary.h" +#include "libGLESv2/Framebuffer.h" +#include "libGLESv2/RenderBuffer.h" +#include "libGLESv2/renderer/Renderer11.h" +#include "libGLESv2/renderer/RenderTarget11.h" +#include "libGLESv2/renderer/renderer11_utils.h" +#include "libGLESv2/renderer/ShaderExecutable11.h" +#include "libGLESv2/renderer/SwapChain11.h" +#include "libGLESv2/renderer/Image11.h" +#include "libGLESv2/renderer/VertexBuffer11.h" +#include "libGLESv2/renderer/IndexBuffer11.h" +#include "libGLESv2/renderer/BufferStorage11.h" +#include "libGLESv2/renderer/VertexDataManager.h" +#include "libGLESv2/renderer/IndexDataManager.h" +#include "libGLESv2/renderer/TextureStorage11.h" +#include "libGLESv2/renderer/Query11.h" +#include "libGLESv2/renderer/Fence11.h" + +#include "libGLESv2/renderer/shaders/compiled/passthrough11vs.h" +#include "libGLESv2/renderer/shaders/compiled/passthroughrgba11ps.h" +#include "libGLESv2/renderer/shaders/compiled/passthroughrgb11ps.h" +#include "libGLESv2/renderer/shaders/compiled/passthroughlum11ps.h" +#include "libGLESv2/renderer/shaders/compiled/passthroughlumalpha11ps.h" + +#include "libGLESv2/renderer/shaders/compiled/clear11vs.h" +#include "libGLESv2/renderer/shaders/compiled/clearsingle11ps.h" +#include "libGLESv2/renderer/shaders/compiled/clearmultiple11ps.h" + +#include "libEGL/Display.h" + +#ifdef _DEBUG +// this flag enables suppressing some spurious warnings that pop up in certain WebGL samples +// and conformance tests. to enable all warnings, remove this define. +#define ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS 1 +#endif + +namespace rx +{ +static const DXGI_FORMAT RenderTargetFormats[] = + { + DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM + }; + +static const DXGI_FORMAT DepthStencilFormats[] = + { + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_D24_UNORM_S8_UINT, + DXGI_FORMAT_D16_UNORM + }; + +enum +{ + MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 = 16 +}; + +Renderer11::Renderer11(egl::Display *display, HDC hDc) : Renderer(display), mDc(hDc) +{ + mVertexDataManager = NULL; + mIndexDataManager = NULL; + + mLineLoopIB = NULL; + mTriangleFanIB = NULL; + + mCopyResourcesInitialized = false; + mCopyVB = NULL; + mCopySampler = NULL; + mCopyIL = NULL; + mCopyVS = NULL; + mCopyRGBAPS = NULL; + mCopyRGBPS = NULL; + mCopyLumPS = NULL; + mCopyLumAlphaPS = NULL; + + mClearResourcesInitialized = false; + mClearVB = NULL; + mClearIL = NULL; + mClearVS = NULL; + mClearSinglePS = NULL; + mClearMultiplePS = NULL; + mClearScissorRS = NULL; + mClearNoScissorRS = NULL; + + mSyncQuery = NULL; + + mD3d11Module = NULL; + mDxgiModule = NULL; + + mDeviceLost = false; + + mMaxSupportedSamples = 0; + + mDevice = NULL; + mDeviceContext = NULL; + mDxgiAdapter = NULL; + mDxgiFactory = NULL; + + mDriverConstantBufferVS = NULL; + mDriverConstantBufferPS = NULL; + + mBGRATextureSupport = false; + + mIsGeometryShaderActive = false; +} + +Renderer11::~Renderer11() +{ + release(); +} + +Renderer11 *Renderer11::makeRenderer11(Renderer *renderer) +{ + ASSERT(HAS_DYNAMIC_TYPE(rx::Renderer11*, renderer)); + return static_cast(renderer); +} + +#ifndef __d3d11_1_h__ +#define D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET ((D3D11_MESSAGE_ID)3146081) +#endif + +EGLint Renderer11::initialize() +{ + if (!initializeCompiler()) + { + return EGL_NOT_INITIALIZED; + } + + mDxgiModule = LoadLibrary(TEXT("dxgi.dll")); + mD3d11Module = LoadLibrary(TEXT("d3d11.dll")); + + if (mD3d11Module == NULL || mDxgiModule == NULL) + { + ERR("Could not load D3D11 or DXGI library - aborting!\n"); + return EGL_NOT_INITIALIZED; + } + + // create the D3D11 device + ASSERT(mDevice == NULL); + PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice"); + + if (D3D11CreateDevice == NULL) + { + ERR("Could not retrieve D3D11CreateDevice address - aborting!\n"); + return EGL_NOT_INITIALIZED; + } + + D3D_FEATURE_LEVEL featureLevels[] = + { + D3D_FEATURE_LEVEL_11_0, + D3D_FEATURE_LEVEL_10_1, + D3D_FEATURE_LEVEL_10_0, + }; + + HRESULT result = S_OK; + +#ifdef _DEBUG + result = D3D11CreateDevice(NULL, + D3D_DRIVER_TYPE_HARDWARE, + NULL, + D3D11_CREATE_DEVICE_DEBUG, + featureLevels, + ArraySize(featureLevels), + D3D11_SDK_VERSION, + &mDevice, + &mFeatureLevel, + &mDeviceContext); + + if (!mDevice || FAILED(result)) + { + ERR("Failed creating Debug D3D11 device - falling back to release runtime.\n"); + } + + if (!mDevice || FAILED(result)) +#endif + { + result = D3D11CreateDevice(NULL, + D3D_DRIVER_TYPE_HARDWARE, + NULL, + 0, + featureLevels, + ArraySize(featureLevels), + D3D11_SDK_VERSION, + &mDevice, + &mFeatureLevel, + &mDeviceContext); + + if (!mDevice || FAILED(result)) + { + ERR("Could not create D3D11 device - aborting!\n"); + return EGL_NOT_INITIALIZED; // Cleanup done by destructor through glDestroyRenderer + } + } + + IDXGIDevice *dxgiDevice = NULL; + result = mDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice); + + if (FAILED(result)) + { + ERR("Could not query DXGI device - aborting!\n"); + return EGL_NOT_INITIALIZED; + } + + result = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&mDxgiAdapter); + + if (FAILED(result)) + { + ERR("Could not retrieve DXGI adapter - aborting!\n"); + return EGL_NOT_INITIALIZED; + } + + dxgiDevice->Release(); + + mDxgiAdapter->GetDesc(&mAdapterDescription); + memset(mDescription, 0, sizeof(mDescription)); + wcstombs(mDescription, mAdapterDescription.Description, sizeof(mDescription) - 1); + + result = mDxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&mDxgiFactory); + + if (!mDxgiFactory || FAILED(result)) + { + ERR("Could not create DXGI factory - aborting!\n"); + return EGL_NOT_INITIALIZED; + } + + // Disable some spurious D3D11 debug warnings to prevent them from flooding the output log +#if defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG) + ID3D11InfoQueue *infoQueue; + result = mDevice->QueryInterface(__uuidof(ID3D11InfoQueue), (void **)&infoQueue); + + if (SUCCEEDED(result)) + { + D3D11_MESSAGE_ID hideMessages[] = + { + D3D11_MESSAGE_ID_DEVICE_OMSETRENDERTARGETS_HAZARD, + D3D11_MESSAGE_ID_DEVICE_PSSETSHADERRESOURCES_HAZARD, + D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET + }; + + D3D11_INFO_QUEUE_FILTER filter = {0}; + filter.DenyList.NumIDs = ArraySize(hideMessages); + filter.DenyList.pIDList = hideMessages; + + infoQueue->AddStorageFilterEntries(&filter); + + infoQueue->Release(); + } +#endif + + unsigned int maxSupportedSamples = 0; + unsigned int rtFormatCount = ArraySize(RenderTargetFormats); + unsigned int dsFormatCount = ArraySize(DepthStencilFormats); + for (unsigned int i = 0; i < rtFormatCount + dsFormatCount; ++i) + { + DXGI_FORMAT format = (i < rtFormatCount) ? RenderTargetFormats[i] : DepthStencilFormats[i - rtFormatCount]; + if (format != DXGI_FORMAT_UNKNOWN) + { + UINT formatSupport; + result = mDevice->CheckFormatSupport(format, &formatSupport); + if (SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET)) + { + MultisampleSupportInfo supportInfo; + + for (unsigned int j = 1; j <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; j++) + { + result = mDevice->CheckMultisampleQualityLevels(format, j, &supportInfo.qualityLevels[j - 1]); + if (SUCCEEDED(result) && supportInfo.qualityLevels[j - 1] > 0) + { + maxSupportedSamples = std::max(j, maxSupportedSamples); + } + else + { + supportInfo.qualityLevels[j - 1] = 0; + } + } + + mMultisampleSupportMap.insert(std::make_pair(format, supportInfo)); + } + } + } + mMaxSupportedSamples = maxSupportedSamples; + + initializeDevice(); + + // BGRA texture support is optional in feature levels 10 and 10_1 + UINT formatSupport; + result = mDevice->CheckFormatSupport(DXGI_FORMAT_B8G8R8A8_UNORM, &formatSupport); + if (FAILED(result)) + { + ERR("Error checking BGRA format support: 0x%08X", result); + } + else + { + const int flags = (D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_RENDER_TARGET); + mBGRATextureSupport = (formatSupport & flags) == flags; + } + + // Check floating point texture support + static const unsigned int requiredTextureFlags = D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_TEXTURECUBE; + static const unsigned int requiredRenderableFlags = D3D11_FORMAT_SUPPORT_RENDER_TARGET; + static const unsigned int requiredFilterFlags = D3D11_FORMAT_SUPPORT_SHADER_SAMPLE; + + DXGI_FORMAT float16Formats[] = + { + DXGI_FORMAT_R16_FLOAT, + DXGI_FORMAT_R16G16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + }; + + DXGI_FORMAT float32Formats[] = + { + DXGI_FORMAT_R32_FLOAT, + DXGI_FORMAT_R32G32_FLOAT, + DXGI_FORMAT_R32G32B32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + }; + + mFloat16TextureSupport = true; + mFloat16FilterSupport = true; + mFloat16RenderSupport = true; + for (unsigned int i = 0; i < ArraySize(float16Formats); i++) + { + if (SUCCEEDED(mDevice->CheckFormatSupport(float16Formats[i], &formatSupport))) + { + mFloat16TextureSupport = mFloat16TextureSupport && (formatSupport & requiredTextureFlags) == requiredTextureFlags; + mFloat16FilterSupport = mFloat16FilterSupport && (formatSupport & requiredFilterFlags) == requiredFilterFlags; + mFloat16RenderSupport = mFloat16RenderSupport && (formatSupport & requiredRenderableFlags) == requiredRenderableFlags; + } + else + { + mFloat16TextureSupport = false; + mFloat16RenderSupport = false; + mFloat16FilterSupport = false; + } + } + + mFloat32TextureSupport = true; + mFloat32FilterSupport = true; + mFloat32RenderSupport = true; + for (unsigned int i = 0; i < ArraySize(float32Formats); i++) + { + if (SUCCEEDED(mDevice->CheckFormatSupport(float32Formats[i], &formatSupport))) + { + mFloat32TextureSupport = mFloat32TextureSupport && (formatSupport & requiredTextureFlags) == requiredTextureFlags; + mFloat32FilterSupport = mFloat32FilterSupport && (formatSupport & requiredFilterFlags) == requiredFilterFlags; + mFloat32RenderSupport = mFloat32RenderSupport && (formatSupport & requiredRenderableFlags) == requiredRenderableFlags; + } + else + { + mFloat32TextureSupport = false; + mFloat32FilterSupport = false; + mFloat32RenderSupport = false; + } + } + + // Check compressed texture support + const unsigned int requiredCompressedTextureFlags = D3D11_FORMAT_SUPPORT_TEXTURE2D; + + if (SUCCEEDED(mDevice->CheckFormatSupport(DXGI_FORMAT_BC1_UNORM, &formatSupport))) + { + mDXT1TextureSupport = (formatSupport & requiredCompressedTextureFlags) == requiredCompressedTextureFlags; + } + else + { + mDXT1TextureSupport = false; + } + + if (SUCCEEDED(mDevice->CheckFormatSupport(DXGI_FORMAT_BC3_UNORM, &formatSupport))) + { + mDXT3TextureSupport = (formatSupport & requiredCompressedTextureFlags) == requiredCompressedTextureFlags; + } + else + { + mDXT3TextureSupport = false; + } + + if (SUCCEEDED(mDevice->CheckFormatSupport(DXGI_FORMAT_BC5_UNORM, &formatSupport))) + { + mDXT5TextureSupport = (formatSupport & requiredCompressedTextureFlags) == requiredCompressedTextureFlags; + } + else + { + mDXT5TextureSupport = false; + } + + // Check depth texture support + DXGI_FORMAT depthTextureFormats[] = + { + DXGI_FORMAT_D16_UNORM, + DXGI_FORMAT_D24_UNORM_S8_UINT, + }; + + static const unsigned int requiredDepthTextureFlags = D3D11_FORMAT_SUPPORT_DEPTH_STENCIL | + D3D11_FORMAT_SUPPORT_TEXTURE2D; + + mDepthTextureSupport = true; + for (unsigned int i = 0; i < ArraySize(depthTextureFormats); i++) + { + if (SUCCEEDED(mDevice->CheckFormatSupport(depthTextureFormats[i], &formatSupport))) + { + mDepthTextureSupport = mDepthTextureSupport && ((formatSupport & requiredDepthTextureFlags) == requiredDepthTextureFlags); + } + else + { + mDepthTextureSupport = false; + } + } + + return EGL_SUCCESS; +} + +// do any one-time device initialization +// NOTE: this is also needed after a device lost/reset +// to reset the scene status and ensure the default states are reset. +void Renderer11::initializeDevice() +{ + mStateCache.initialize(mDevice); + mInputLayoutCache.initialize(mDevice, mDeviceContext); + + ASSERT(!mVertexDataManager && !mIndexDataManager); + mVertexDataManager = new VertexDataManager(this); + mIndexDataManager = new IndexDataManager(this); + + markAllStateDirty(); +} + +int Renderer11::generateConfigs(ConfigDesc **configDescList) +{ + unsigned int numRenderFormats = ArraySize(RenderTargetFormats); + unsigned int numDepthFormats = ArraySize(DepthStencilFormats); + (*configDescList) = new ConfigDesc[numRenderFormats * numDepthFormats]; + int numConfigs = 0; + + for (unsigned int formatIndex = 0; formatIndex < numRenderFormats; formatIndex++) + { + for (unsigned int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++) + { + DXGI_FORMAT renderTargetFormat = RenderTargetFormats[formatIndex]; + + UINT formatSupport = 0; + HRESULT result = mDevice->CheckFormatSupport(renderTargetFormat, &formatSupport); + + if (SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_RENDER_TARGET)) + { + DXGI_FORMAT depthStencilFormat = DepthStencilFormats[depthStencilIndex]; + + bool depthStencilFormatOK = true; + + if (depthStencilFormat != DXGI_FORMAT_UNKNOWN) + { + UINT formatSupport = 0; + result = mDevice->CheckFormatSupport(depthStencilFormat, &formatSupport); + depthStencilFormatOK = SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_DEPTH_STENCIL); + } + + if (depthStencilFormatOK) + { + ConfigDesc newConfig; + newConfig.renderTargetFormat = d3d11_gl::ConvertBackBufferFormat(renderTargetFormat); + newConfig.depthStencilFormat = d3d11_gl::ConvertDepthStencilFormat(depthStencilFormat); + newConfig.multiSample = 0; // FIXME: enumerate multi-sampling + newConfig.fastConfig = true; // Assume all DX11 format conversions to be fast + + (*configDescList)[numConfigs++] = newConfig; + } + } + } + } + + return numConfigs; +} + +void Renderer11::deleteConfigs(ConfigDesc *configDescList) +{ + delete [] (configDescList); +} + +void Renderer11::sync(bool block) +{ + if (block) + { + HRESULT result; + + if (!mSyncQuery) + { + D3D11_QUERY_DESC queryDesc; + queryDesc.Query = D3D11_QUERY_EVENT; + queryDesc.MiscFlags = 0; + + result = mDevice->CreateQuery(&queryDesc, &mSyncQuery); + ASSERT(SUCCEEDED(result)); + } + + mDeviceContext->End(mSyncQuery); + mDeviceContext->Flush(); + + do + { + result = mDeviceContext->GetData(mSyncQuery, NULL, 0, D3D11_ASYNC_GETDATA_DONOTFLUSH); + + // Keep polling, but allow other threads to do something useful first + Sleep(0); + + if (testDeviceLost(true)) + { + return; + } + } + while (result == S_FALSE); + } + else + { + mDeviceContext->Flush(); + } +} + +SwapChain *Renderer11::createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) +{ + return new rx::SwapChain11(this, window, shareHandle, backBufferFormat, depthBufferFormat); +} + +void Renderer11::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState) +{ + if (type == gl::SAMPLER_PIXEL) + { + if (index < 0 || index >= gl::MAX_TEXTURE_IMAGE_UNITS) + { + ERR("Pixel shader sampler index %i is not valid.", index); + return; + } + + if (mForceSetPixelSamplerStates[index] || memcmp(&samplerState, &mCurPixelSamplerStates[index], sizeof(gl::SamplerState)) != 0) + { + ID3D11SamplerState *dxSamplerState = mStateCache.getSamplerState(samplerState); + + if (!dxSamplerState) + { + ERR("NULL sampler state returned by RenderStateCache::getSamplerState, setting the default" + "sampler state for pixel shaders at slot %i.", index); + } + + mDeviceContext->PSSetSamplers(index, 1, &dxSamplerState); + + mCurPixelSamplerStates[index] = samplerState; + } + + mForceSetPixelSamplerStates[index] = false; + } + else if (type == gl::SAMPLER_VERTEX) + { + if (index < 0 || index >= (int)getMaxVertexTextureImageUnits()) + { + ERR("Vertex shader sampler index %i is not valid.", index); + return; + } + + if (mForceSetVertexSamplerStates[index] || memcmp(&samplerState, &mCurVertexSamplerStates[index], sizeof(gl::SamplerState)) != 0) + { + ID3D11SamplerState *dxSamplerState = mStateCache.getSamplerState(samplerState); + + if (!dxSamplerState) + { + ERR("NULL sampler state returned by RenderStateCache::getSamplerState, setting the default" + "sampler state for vertex shaders at slot %i.", index); + } + + mDeviceContext->VSSetSamplers(index, 1, &dxSamplerState); + + mCurVertexSamplerStates[index] = samplerState; + } + + mForceSetVertexSamplerStates[index] = false; + } + else UNREACHABLE(); +} + +void Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *texture) +{ + ID3D11ShaderResourceView *textureSRV = NULL; + unsigned int serial = 0; + bool forceSetTexture = false; + + if (texture) + { + TextureStorageInterface *texStorage = texture->getNativeTexture(); + if (texStorage) + { + TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage->getStorageInstance()); + textureSRV = storage11->getSRV(); + } + + // If we get NULL back from getSRV here, something went wrong in the texture class and we're unexpectedly + // missing the shader resource view + ASSERT(textureSRV != NULL); + + serial = texture->getTextureSerial(); + forceSetTexture = texture->hasDirtyImages(); + } + + if (type == gl::SAMPLER_PIXEL) + { + if (index < 0 || index >= gl::MAX_TEXTURE_IMAGE_UNITS) + { + ERR("Pixel shader sampler index %i is not valid.", index); + return; + } + + if (forceSetTexture || mCurPixelTextureSerials[index] != serial) + { + mDeviceContext->PSSetShaderResources(index, 1, &textureSRV); + } + + mCurPixelTextureSerials[index] = serial; + } + else if (type == gl::SAMPLER_VERTEX) + { + if (index < 0 || index >= (int)getMaxVertexTextureImageUnits()) + { + ERR("Vertex shader sampler index %i is not valid.", index); + return; + } + + if (forceSetTexture || mCurVertexTextureSerials[index] != serial) + { + mDeviceContext->VSSetShaderResources(index, 1, &textureSRV); + } + + mCurVertexTextureSerials[index] = serial; + } + else UNREACHABLE(); +} + +void Renderer11::setRasterizerState(const gl::RasterizerState &rasterState) +{ + if (mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0) + { + ID3D11RasterizerState *dxRasterState = mStateCache.getRasterizerState(rasterState, mScissorEnabled, + mCurDepthSize); + if (!dxRasterState) + { + ERR("NULL rasterizer state returned by RenderStateCache::getRasterizerState, setting the default" + "rasterizer state."); + } + + mDeviceContext->RSSetState(dxRasterState); + + mCurRasterState = rasterState; + } + + mForceSetRasterState = false; +} + +void Renderer11::setBlendState(const gl::BlendState &blendState, const gl::Color &blendColor, + unsigned int sampleMask) +{ + if (mForceSetBlendState || + memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0 || + memcmp(&blendColor, &mCurBlendColor, sizeof(gl::Color)) != 0 || + sampleMask != mCurSampleMask) + { + ID3D11BlendState *dxBlendState = mStateCache.getBlendState(blendState); + if (!dxBlendState) + { + ERR("NULL blend state returned by RenderStateCache::getBlendState, setting the default " + "blend state."); + } + + float blendColors[4] = {0.0f}; + if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA && blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA && + blendState.destBlendRGB != GL_CONSTANT_ALPHA && blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA) + { + blendColors[0] = blendColor.red; + blendColors[1] = blendColor.green; + blendColors[2] = blendColor.blue; + blendColors[3] = blendColor.alpha; + } + else + { + blendColors[0] = blendColor.alpha; + blendColors[1] = blendColor.alpha; + blendColors[2] = blendColor.alpha; + blendColors[3] = blendColor.alpha; + } + + mDeviceContext->OMSetBlendState(dxBlendState, blendColors, sampleMask); + + mCurBlendState = blendState; + mCurBlendColor = blendColor; + mCurSampleMask = sampleMask; + } + + mForceSetBlendState = false; +} + +void Renderer11::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, + int stencilBackRef, bool frontFaceCCW) +{ + if (mForceSetDepthStencilState || + memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0 || + stencilRef != mCurStencilRef || stencilBackRef != mCurStencilBackRef) + { + if (depthStencilState.stencilWritemask != depthStencilState.stencilBackWritemask || + stencilRef != stencilBackRef || + depthStencilState.stencilMask != depthStencilState.stencilBackMask) + { + ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are " + "invalid under WebGL."); + return gl::error(GL_INVALID_OPERATION); + } + + ID3D11DepthStencilState *dxDepthStencilState = mStateCache.getDepthStencilState(depthStencilState); + if (!dxDepthStencilState) + { + ERR("NULL depth stencil state returned by RenderStateCache::getDepthStencilState, " + "setting the default depth stencil state."); + } + + mDeviceContext->OMSetDepthStencilState(dxDepthStencilState, static_cast(stencilRef)); + + mCurDepthStencilState = depthStencilState; + mCurStencilRef = stencilRef; + mCurStencilBackRef = stencilBackRef; + } + + mForceSetDepthStencilState = false; +} + +void Renderer11::setScissorRectangle(const gl::Rectangle &scissor, bool enabled) +{ + if (mForceSetScissor || memcmp(&scissor, &mCurScissor, sizeof(gl::Rectangle)) != 0 || + enabled != mScissorEnabled) + { + if (enabled) + { + D3D11_RECT rect; + rect.left = std::max(0, scissor.x); + rect.top = std::max(0, scissor.y); + rect.right = scissor.x + std::max(0, scissor.width); + rect.bottom = scissor.y + std::max(0, scissor.height); + + mDeviceContext->RSSetScissorRects(1, &rect); + } + + if (enabled != mScissorEnabled) + { + mForceSetRasterState = true; + } + + mCurScissor = scissor; + mScissorEnabled = enabled; + } + + mForceSetScissor = false; +} + +bool Renderer11::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, + bool ignoreViewport) +{ + gl::Rectangle actualViewport = viewport; + float actualZNear = gl::clamp01(zNear); + float actualZFar = gl::clamp01(zFar); + if (ignoreViewport) + { + actualViewport.x = 0; + actualViewport.y = 0; + actualViewport.width = mRenderTargetDesc.width; + actualViewport.height = mRenderTargetDesc.height; + actualZNear = 0.0f; + actualZFar = 1.0f; + } + + // Get D3D viewport bounds, which depends on the feature level + const Range& viewportBounds = getViewportBounds(); + + // Clamp width and height first to the gl maximum, then clamp further if we extend past the D3D maximum bounds + D3D11_VIEWPORT dxViewport; + dxViewport.TopLeftX = gl::clamp(actualViewport.x, viewportBounds.start, viewportBounds.end); + dxViewport.TopLeftY = gl::clamp(actualViewport.y, viewportBounds.start, viewportBounds.end); + dxViewport.Width = gl::clamp(actualViewport.width, 0, getMaxViewportDimension()); + dxViewport.Height = gl::clamp(actualViewport.height, 0, getMaxViewportDimension()); + dxViewport.Width = std::min((int)dxViewport.Width, viewportBounds.end - static_cast(dxViewport.TopLeftX)); + dxViewport.Height = std::min((int)dxViewport.Height, viewportBounds.end - static_cast(dxViewport.TopLeftY)); + dxViewport.MinDepth = actualZNear; + dxViewport.MaxDepth = actualZFar; + + if (dxViewport.Width <= 0 || dxViewport.Height <= 0) + { + return false; // Nothing to render + } + + bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 || + actualZNear != mCurNear || actualZFar != mCurFar; + + if (viewportChanged) + { + mDeviceContext->RSSetViewports(1, &dxViewport); + + mCurViewport = actualViewport; + mCurNear = actualZNear; + mCurFar = actualZFar; + + mPixelConstants.viewCoords[0] = actualViewport.width * 0.5f; + mPixelConstants.viewCoords[1] = actualViewport.height * 0.5f; + mPixelConstants.viewCoords[2] = actualViewport.x + (actualViewport.width * 0.5f); + mPixelConstants.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f); + + mPixelConstants.depthFront[0] = (actualZFar - actualZNear) * 0.5f; + mPixelConstants.depthFront[1] = (actualZNear + actualZFar) * 0.5f; + + mVertexConstants.depthRange[0] = actualZNear; + mVertexConstants.depthRange[1] = actualZFar; + mVertexConstants.depthRange[2] = actualZFar - actualZNear; + + mPixelConstants.depthRange[0] = actualZNear; + mPixelConstants.depthRange[1] = actualZFar; + mPixelConstants.depthRange[2] = actualZFar - actualZNear; + } + + mForceSetViewport = false; + return true; +} + +bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count) +{ + D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; + + GLsizei minCount = 0; + + switch (mode) + { + case GL_POINTS: primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST; minCount = 1; break; + case GL_LINES: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINELIST; minCount = 2; break; + case GL_LINE_LOOP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; minCount = 2; break; + case GL_LINE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; minCount = 2; break; + case GL_TRIANGLES: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; minCount = 3; break; + case GL_TRIANGLE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; minCount = 3; break; + // emulate fans via rewriting index buffer + case GL_TRIANGLE_FAN: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; minCount = 3; break; + default: + return gl::error(GL_INVALID_ENUM, false); + } + + if (primitiveTopology != mCurrentPrimitiveTopology) + { + mDeviceContext->IASetPrimitiveTopology(primitiveTopology); + mCurrentPrimitiveTopology = primitiveTopology; + } + + return count >= minCount; +} + +bool Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer) +{ + // Get the color render buffer and serial + // Also extract the render target dimensions and view + unsigned int renderTargetWidth = 0; + unsigned int renderTargetHeight = 0; + GLenum renderTargetFormat = 0; + unsigned int renderTargetSerials[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {0}; + ID3D11RenderTargetView* framebufferRTVs[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL}; + bool missingColorRenderTarget = true; + + for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) + { + const GLenum drawBufferState = framebuffer->getDrawBufferState(colorAttachment); + + if (framebuffer->getColorbufferType(colorAttachment) != GL_NONE && drawBufferState != GL_NONE) + { + // the draw buffer must be either "none", "back" for the default buffer or the same index as this color (in order) + ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + colorAttachment)); + + gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(colorAttachment); + + if (!colorbuffer) + { + ERR("render target pointer unexpectedly null."); + return false; + } + + // check for zero-sized default framebuffer, which is a special case. + // in this case we do not wish to modify any state and just silently return false. + // this will not report any gl error but will cause the calling method to return. + if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0) + { + return false; + } + + renderTargetSerials[colorAttachment] = colorbuffer->getSerial(); + + // Extract the render target dimensions and view + RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget()); + if (!renderTarget) + { + ERR("render target pointer unexpectedly null."); + return false; + } + + framebufferRTVs[colorAttachment] = renderTarget->getRenderTargetView(); + if (!framebufferRTVs[colorAttachment]) + { + ERR("render target view pointer unexpectedly null."); + return false; + } + + if (missingColorRenderTarget) + { + renderTargetWidth = colorbuffer->getWidth(); + renderTargetHeight = colorbuffer->getHeight(); + renderTargetFormat = colorbuffer->getActualFormat(); + missingColorRenderTarget = false; + } + } + } + + // Get the depth stencil render buffer and serials + gl::Renderbuffer *depthStencil = NULL; + unsigned int depthbufferSerial = 0; + unsigned int stencilbufferSerial = 0; + if (framebuffer->getDepthbufferType() != GL_NONE) + { + depthStencil = framebuffer->getDepthbuffer(); + if (!depthStencil) + { + ERR("Depth stencil pointer unexpectedly null."); + SafeRelease(framebufferRTVs); + return false; + } + + depthbufferSerial = depthStencil->getSerial(); + } + else if (framebuffer->getStencilbufferType() != GL_NONE) + { + depthStencil = framebuffer->getStencilbuffer(); + if (!depthStencil) + { + ERR("Depth stencil pointer unexpectedly null."); + SafeRelease(framebufferRTVs); + return false; + } + + stencilbufferSerial = depthStencil->getSerial(); + } + + // Extract the depth stencil sizes and view + unsigned int depthSize = 0; + unsigned int stencilSize = 0; + ID3D11DepthStencilView* framebufferDSV = NULL; + if (depthStencil) + { + RenderTarget11 *depthStencilRenderTarget = RenderTarget11::makeRenderTarget11(depthStencil->getDepthStencil()); + if (!depthStencilRenderTarget) + { + ERR("render target pointer unexpectedly null."); + SafeRelease(framebufferRTVs); + return false; + } + + framebufferDSV = depthStencilRenderTarget->getDepthStencilView(); + if (!framebufferDSV) + { + ERR("depth stencil view pointer unexpectedly null."); + SafeRelease(framebufferRTVs); + return false; + } + + // If there is no render buffer, the width, height and format values come from + // the depth stencil + if (missingColorRenderTarget) + { + renderTargetWidth = depthStencil->getWidth(); + renderTargetHeight = depthStencil->getHeight(); + renderTargetFormat = depthStencil->getActualFormat(); + } + + depthSize = depthStencil->getDepthSize(); + stencilSize = depthStencil->getStencilSize(); + } + + // Apply the render target and depth stencil + if (!mRenderTargetDescInitialized || !mDepthStencilInitialized || + memcmp(renderTargetSerials, mAppliedRenderTargetSerials, sizeof(renderTargetSerials)) != 0 || + depthbufferSerial != mAppliedDepthbufferSerial || + stencilbufferSerial != mAppliedStencilbufferSerial) + { + mDeviceContext->OMSetRenderTargets(getMaxRenderTargets(), framebufferRTVs, framebufferDSV); + + mRenderTargetDesc.width = renderTargetWidth; + mRenderTargetDesc.height = renderTargetHeight; + mRenderTargetDesc.format = renderTargetFormat; + mForceSetViewport = true; + mForceSetScissor = true; + + if (!mDepthStencilInitialized || depthSize != mCurDepthSize) + { + mCurDepthSize = depthSize; + mForceSetRasterState = true; + } + + mCurStencilSize = stencilSize; + + for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++) + { + mAppliedRenderTargetSerials[rtIndex] = renderTargetSerials[rtIndex]; + } + mAppliedDepthbufferSerial = depthbufferSerial; + mAppliedStencilbufferSerial = stencilbufferSerial; + mRenderTargetDescInitialized = true; + mDepthStencilInitialized = true; + } + + return true; +} + +GLenum Renderer11::applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances) +{ + TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS]; + GLenum err = mVertexDataManager->prepareVertexData(vertexAttributes, programBinary, first, count, attributes, instances); + if (err != GL_NO_ERROR) + { + return err; + } + + return mInputLayoutCache.applyVertexBuffers(attributes, programBinary); +} + +GLenum Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) +{ + GLenum err = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo); + + if (err == GL_NO_ERROR) + { + if (indexInfo->storage) + { + if (indexInfo->serial != mAppliedStorageIBSerial || indexInfo->startOffset != mAppliedIBOffset) + { + BufferStorage11 *storage = BufferStorage11::makeBufferStorage11(indexInfo->storage); + IndexBuffer11* indexBuffer = IndexBuffer11::makeIndexBuffer11(indexInfo->indexBuffer); + + mDeviceContext->IASetIndexBuffer(storage->getBuffer(), indexBuffer->getIndexFormat(), indexInfo->startOffset); + + mAppliedIBSerial = 0; + mAppliedStorageIBSerial = storage->getSerial(); + mAppliedIBOffset = indexInfo->startOffset; + } + } + else if (indexInfo->serial != mAppliedIBSerial || indexInfo->startOffset != mAppliedIBOffset) + { + IndexBuffer11* indexBuffer = IndexBuffer11::makeIndexBuffer11(indexInfo->indexBuffer); + + mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexInfo->startOffset); + + mAppliedIBSerial = indexInfo->serial; + mAppliedStorageIBSerial = 0; + mAppliedIBOffset = indexInfo->startOffset; + } + } + + return err; +} + +void Renderer11::drawArrays(GLenum mode, GLsizei count, GLsizei instances) +{ + if (mode == GL_LINE_LOOP) + { + drawLineLoop(count, GL_NONE, NULL, 0, NULL); + } + else if (mode == GL_TRIANGLE_FAN) + { + drawTriangleFan(count, GL_NONE, NULL, 0, NULL, instances); + } + else if (instances > 0) + { + mDeviceContext->DrawInstanced(count, instances, 0, 0); + } + else + { + mDeviceContext->Draw(count, 0); + } +} + +void Renderer11::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances) +{ + if (mode == GL_LINE_LOOP) + { + drawLineLoop(count, type, indices, indexInfo.minIndex, elementArrayBuffer); + } + else if (mode == GL_TRIANGLE_FAN) + { + drawTriangleFan(count, type, indices, indexInfo.minIndex, elementArrayBuffer, instances); + } + else if (instances > 0) + { + mDeviceContext->DrawIndexedInstanced(count, instances, 0, -static_cast(indexInfo.minIndex), 0); + } + else + { + mDeviceContext->DrawIndexed(count, 0, -static_cast(indexInfo.minIndex)); + } +} + +void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer) +{ + // Get the raw indices for an indexed draw + if (type != GL_NONE && elementArrayBuffer) + { + gl::Buffer *indexBuffer = elementArrayBuffer; + BufferStorage *storage = indexBuffer->getStorage(); + intptr_t offset = reinterpret_cast(indices); + indices = static_cast(storage->getData()) + offset; + } + + if (!mLineLoopIB) + { + mLineLoopIB = new StreamingIndexBufferInterface(this); + if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT)) + { + delete mLineLoopIB; + mLineLoopIB = NULL; + + ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP."); + return gl::error(GL_OUT_OF_MEMORY); + } + } + + // Checked by Renderer11::applyPrimitiveType + ASSERT(count >= 0); + + if (static_cast(count) + 1 > (std::numeric_limits::max() / sizeof(unsigned int))) + { + ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required."); + return gl::error(GL_OUT_OF_MEMORY); + } + + const unsigned int spaceNeeded = (static_cast(count) + 1) * sizeof(unsigned int); + if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT)) + { + ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP."); + return gl::error(GL_OUT_OF_MEMORY); + } + + void* mappedMemory = NULL; + unsigned int offset; + if (!mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset)) + { + ERR("Could not map index buffer for GL_LINE_LOOP."); + return gl::error(GL_OUT_OF_MEMORY); + } + + unsigned int *data = reinterpret_cast(mappedMemory); + unsigned int indexBufferOffset = offset; + + switch (type) + { + case GL_NONE: // Non-indexed draw + for (int i = 0; i < count; i++) + { + data[i] = i; + } + data[count] = 0; + break; + case GL_UNSIGNED_BYTE: + for (int i = 0; i < count; i++) + { + data[i] = static_cast(indices)[i]; + } + data[count] = static_cast(indices)[0]; + break; + case GL_UNSIGNED_SHORT: + for (int i = 0; i < count; i++) + { + data[i] = static_cast(indices)[i]; + } + data[count] = static_cast(indices)[0]; + break; + case GL_UNSIGNED_INT: + for (int i = 0; i < count; i++) + { + data[i] = static_cast(indices)[i]; + } + data[count] = static_cast(indices)[0]; + break; + default: UNREACHABLE(); + } + + if (!mLineLoopIB->unmapBuffer()) + { + ERR("Could not unmap index buffer for GL_LINE_LOOP."); + return gl::error(GL_OUT_OF_MEMORY); + } + + if (mAppliedIBSerial != mLineLoopIB->getSerial() || mAppliedIBOffset != indexBufferOffset) + { + IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mLineLoopIB->getIndexBuffer()); + + mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexBufferOffset); + mAppliedIBSerial = mLineLoopIB->getSerial(); + mAppliedStorageIBSerial = 0; + mAppliedIBOffset = indexBufferOffset; + } + + mDeviceContext->DrawIndexed(count + 1, 0, -minIndex); +} + +void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances) +{ + // Get the raw indices for an indexed draw + if (type != GL_NONE && elementArrayBuffer) + { + gl::Buffer *indexBuffer = elementArrayBuffer; + BufferStorage *storage = indexBuffer->getStorage(); + intptr_t offset = reinterpret_cast(indices); + indices = static_cast(storage->getData()) + offset; + } + + if (!mTriangleFanIB) + { + mTriangleFanIB = new StreamingIndexBufferInterface(this); + if (!mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT)) + { + delete mTriangleFanIB; + mTriangleFanIB = NULL; + + ERR("Could not create a scratch index buffer for GL_TRIANGLE_FAN."); + return gl::error(GL_OUT_OF_MEMORY); + } + } + + // Checked by Renderer11::applyPrimitiveType + ASSERT(count >= 3); + + const unsigned int numTris = count - 2; + + if (numTris > (std::numeric_limits::max() / (sizeof(unsigned int) * 3))) + { + ERR("Could not create a scratch index buffer for GL_TRIANGLE_FAN, too many indices required."); + return gl::error(GL_OUT_OF_MEMORY); + } + + const unsigned int spaceNeeded = (numTris * 3) * sizeof(unsigned int); + if (!mTriangleFanIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT)) + { + ERR("Could not reserve enough space in scratch index buffer for GL_TRIANGLE_FAN."); + return gl::error(GL_OUT_OF_MEMORY); + } + + void* mappedMemory = NULL; + unsigned int offset; + if (!mTriangleFanIB->mapBuffer(spaceNeeded, &mappedMemory, &offset)) + { + ERR("Could not map scratch index buffer for GL_TRIANGLE_FAN."); + return gl::error(GL_OUT_OF_MEMORY); + } + + unsigned int *data = reinterpret_cast(mappedMemory); + unsigned int indexBufferOffset = offset; + + switch (type) + { + case GL_NONE: // Non-indexed draw + for (unsigned int i = 0; i < numTris; i++) + { + data[i*3 + 0] = 0; + data[i*3 + 1] = i + 1; + data[i*3 + 2] = i + 2; + } + break; + case GL_UNSIGNED_BYTE: + for (unsigned int i = 0; i < numTris; i++) + { + data[i*3 + 0] = static_cast(indices)[0]; + data[i*3 + 1] = static_cast(indices)[i + 1]; + data[i*3 + 2] = static_cast(indices)[i + 2]; + } + break; + case GL_UNSIGNED_SHORT: + for (unsigned int i = 0; i < numTris; i++) + { + data[i*3 + 0] = static_cast(indices)[0]; + data[i*3 + 1] = static_cast(indices)[i + 1]; + data[i*3 + 2] = static_cast(indices)[i + 2]; + } + break; + case GL_UNSIGNED_INT: + for (unsigned int i = 0; i < numTris; i++) + { + data[i*3 + 0] = static_cast(indices)[0]; + data[i*3 + 1] = static_cast(indices)[i + 1]; + data[i*3 + 2] = static_cast(indices)[i + 2]; + } + break; + default: UNREACHABLE(); + } + + if (!mTriangleFanIB->unmapBuffer()) + { + ERR("Could not unmap scratch index buffer for GL_TRIANGLE_FAN."); + return gl::error(GL_OUT_OF_MEMORY); + } + + if (mAppliedIBSerial != mTriangleFanIB->getSerial() || mAppliedIBOffset != indexBufferOffset) + { + IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mTriangleFanIB->getIndexBuffer()); + + mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexBufferOffset); + mAppliedIBSerial = mTriangleFanIB->getSerial(); + mAppliedStorageIBSerial = 0; + mAppliedIBOffset = indexBufferOffset; + } + + if (instances > 0) + { + mDeviceContext->DrawIndexedInstanced(numTris * 3, instances, 0, -minIndex, 0); + } + else + { + mDeviceContext->DrawIndexed(numTris * 3, 0, -minIndex); + } +} + +void Renderer11::applyShaders(gl::ProgramBinary *programBinary) +{ + unsigned int programBinarySerial = programBinary->getSerial(); + const bool updateProgramState = (programBinarySerial != mAppliedProgramBinarySerial); + + if (updateProgramState) + { + ShaderExecutable *vertexExe = programBinary->getVertexExecutable(); + ShaderExecutable *pixelExe = programBinary->getPixelExecutable(); + + ID3D11VertexShader *vertexShader = NULL; + if (vertexExe) vertexShader = ShaderExecutable11::makeShaderExecutable11(vertexExe)->getVertexShader(); + + ID3D11PixelShader *pixelShader = NULL; + if (pixelExe) pixelShader = ShaderExecutable11::makeShaderExecutable11(pixelExe)->getPixelShader(); + + mDeviceContext->PSSetShader(pixelShader, NULL, 0); + mDeviceContext->VSSetShader(vertexShader, NULL, 0); + + programBinary->dirtyAllUniforms(); + + mAppliedProgramBinarySerial = programBinarySerial; + } + + // Only use the geometry shader currently for point sprite drawing + const bool usesGeometryShader = (programBinary->usesGeometryShader() && mCurRasterState.pointDrawMode); + + if (updateProgramState || usesGeometryShader != mIsGeometryShaderActive) + { + if (usesGeometryShader) + { + ShaderExecutable *geometryExe = programBinary->getGeometryExecutable(); + ID3D11GeometryShader *geometryShader = ShaderExecutable11::makeShaderExecutable11(geometryExe)->getGeometryShader(); + mDeviceContext->GSSetShader(geometryShader, NULL, 0); + } + else + { + mDeviceContext->GSSetShader(NULL, NULL, 0); + } + + mIsGeometryShaderActive = usesGeometryShader; + } +} + +void Renderer11::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray) +{ + ShaderExecutable11 *vertexExecutable = ShaderExecutable11::makeShaderExecutable11(programBinary->getVertexExecutable()); + ShaderExecutable11 *pixelExecutable = ShaderExecutable11::makeShaderExecutable11(programBinary->getPixelExecutable()); + + unsigned int totalRegisterCountVS = 0; + unsigned int totalRegisterCountPS = 0; + + bool vertexUniformsDirty = false; + bool pixelUniformsDirty = false; + + for (gl::UniformArray::const_iterator uniform_iterator = uniformArray->begin(); uniform_iterator != uniformArray->end(); uniform_iterator++) + { + const gl::Uniform *uniform = *uniform_iterator; + + if (uniform->vsRegisterIndex >= 0) + { + totalRegisterCountVS += uniform->registerCount; + vertexUniformsDirty = vertexUniformsDirty || uniform->dirty; + } + + if (uniform->psRegisterIndex >= 0) + { + totalRegisterCountPS += uniform->registerCount; + pixelUniformsDirty = pixelUniformsDirty || uniform->dirty; + } + } + + ID3D11Buffer *vertexConstantBuffer = vertexExecutable->getConstantBuffer(mDevice, totalRegisterCountVS); + ID3D11Buffer *pixelConstantBuffer = pixelExecutable->getConstantBuffer(mDevice, totalRegisterCountPS); + + float (*mapVS)[4] = NULL; + float (*mapPS)[4] = NULL; + + if (totalRegisterCountVS > 0 && vertexUniformsDirty) + { + D3D11_MAPPED_SUBRESOURCE map = {0}; + HRESULT result = mDeviceContext->Map(vertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); + ASSERT(SUCCEEDED(result)); + mapVS = (float(*)[4])map.pData; + } + + if (totalRegisterCountPS > 0 && pixelUniformsDirty) + { + D3D11_MAPPED_SUBRESOURCE map = {0}; + HRESULT result = mDeviceContext->Map(pixelConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); + ASSERT(SUCCEEDED(result)); + mapPS = (float(*)[4])map.pData; + } + + for (gl::UniformArray::iterator uniform_iterator = uniformArray->begin(); uniform_iterator != uniformArray->end(); uniform_iterator++) + { + gl::Uniform *uniform = *uniform_iterator; + + if (uniform->type != GL_SAMPLER_2D && uniform->type != GL_SAMPLER_CUBE) + { + if (uniform->vsRegisterIndex >= 0 && mapVS) + { + memcpy(mapVS + uniform->vsRegisterIndex, uniform->data, uniform->registerCount * sizeof(float[4])); + } + + if (uniform->psRegisterIndex >= 0 && mapPS) + { + memcpy(mapPS + uniform->psRegisterIndex, uniform->data, uniform->registerCount * sizeof(float[4])); + } + } + + uniform->dirty = false; + } + + if (mapVS) + { + mDeviceContext->Unmap(vertexConstantBuffer, 0); + } + + if (mapPS) + { + mDeviceContext->Unmap(pixelConstantBuffer, 0); + } + + if (mCurrentVertexConstantBuffer != vertexConstantBuffer) + { + mDeviceContext->VSSetConstantBuffers(0, 1, &vertexConstantBuffer); + mCurrentVertexConstantBuffer = vertexConstantBuffer; + } + + if (mCurrentPixelConstantBuffer != pixelConstantBuffer) + { + mDeviceContext->PSSetConstantBuffers(0, 1, &pixelConstantBuffer); + mCurrentPixelConstantBuffer = pixelConstantBuffer; + } + + // Driver uniforms + if (!mDriverConstantBufferVS) + { + D3D11_BUFFER_DESC constantBufferDescription = {0}; + constantBufferDescription.ByteWidth = sizeof(dx_VertexConstants); + constantBufferDescription.Usage = D3D11_USAGE_DEFAULT; + constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + constantBufferDescription.CPUAccessFlags = 0; + constantBufferDescription.MiscFlags = 0; + constantBufferDescription.StructureByteStride = 0; + + HRESULT result = mDevice->CreateBuffer(&constantBufferDescription, NULL, &mDriverConstantBufferVS); + ASSERT(SUCCEEDED(result)); + + mDeviceContext->VSSetConstantBuffers(1, 1, &mDriverConstantBufferVS); + } + + if (!mDriverConstantBufferPS) + { + D3D11_BUFFER_DESC constantBufferDescription = {0}; + constantBufferDescription.ByteWidth = sizeof(dx_PixelConstants); + constantBufferDescription.Usage = D3D11_USAGE_DEFAULT; + constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + constantBufferDescription.CPUAccessFlags = 0; + constantBufferDescription.MiscFlags = 0; + constantBufferDescription.StructureByteStride = 0; + + HRESULT result = mDevice->CreateBuffer(&constantBufferDescription, NULL, &mDriverConstantBufferPS); + ASSERT(SUCCEEDED(result)); + + mDeviceContext->PSSetConstantBuffers(1, 1, &mDriverConstantBufferPS); + } + + if (memcmp(&mVertexConstants, &mAppliedVertexConstants, sizeof(dx_VertexConstants)) != 0) + { + mDeviceContext->UpdateSubresource(mDriverConstantBufferVS, 0, NULL, &mVertexConstants, 16, 0); + memcpy(&mAppliedVertexConstants, &mVertexConstants, sizeof(dx_VertexConstants)); + } + + if (memcmp(&mPixelConstants, &mAppliedPixelConstants, sizeof(dx_PixelConstants)) != 0) + { + mDeviceContext->UpdateSubresource(mDriverConstantBufferPS, 0, NULL, &mPixelConstants, 16, 0); + memcpy(&mAppliedPixelConstants, &mPixelConstants, sizeof(dx_PixelConstants)); + } + + // needed for the point sprite geometry shader + if (mCurrentGeometryConstantBuffer != mDriverConstantBufferPS) + { + mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS); + mCurrentGeometryConstantBuffer = mDriverConstantBufferPS; + } +} + +void Renderer11::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) +{ + bool alphaUnmasked = (gl::GetAlphaSize(mRenderTargetDesc.format) == 0) || clearParams.colorMaskAlpha; + bool needMaskedColorClear = (clearParams.mask & GL_COLOR_BUFFER_BIT) && + !(clearParams.colorMaskRed && clearParams.colorMaskGreen && + clearParams.colorMaskBlue && alphaUnmasked); + + unsigned int stencilUnmasked = 0x0; + if (frameBuffer->hasStencil()) + { + unsigned int stencilSize = gl::GetStencilSize(frameBuffer->getStencilbuffer()->getActualFormat()); + stencilUnmasked = (0x1 << stencilSize) - 1; + } + bool needMaskedStencilClear = (clearParams.mask & GL_STENCIL_BUFFER_BIT) && + (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked; + + bool needScissoredClear = mScissorEnabled && (mCurScissor.x > 0 || mCurScissor.y > 0 || + mCurScissor.x + mCurScissor.width < mRenderTargetDesc.width || + mCurScissor.y + mCurScissor.height < mRenderTargetDesc.height); + + if (needMaskedColorClear || needMaskedStencilClear || needScissoredClear) + { + maskedClear(clearParams, frameBuffer->usingExtendedDrawBuffers()); + } + else + { + if (clearParams.mask & GL_COLOR_BUFFER_BIT) + { + for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) + { + if (frameBuffer->isEnabledColorAttachment(colorAttachment)) + { + gl::Renderbuffer *renderbufferObject = frameBuffer->getColorbuffer(colorAttachment); + if (renderbufferObject) + { + RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(renderbufferObject->getRenderTarget()); + if (!renderTarget) + { + ERR("render target pointer unexpectedly null."); + return; + } + + ID3D11RenderTargetView *framebufferRTV = renderTarget->getRenderTargetView(); + if (!framebufferRTV) + { + ERR("render target view pointer unexpectedly null."); + return; + } + + const float clearValues[4] = { clearParams.colorClearValue.red, + clearParams.colorClearValue.green, + clearParams.colorClearValue.blue, + clearParams.colorClearValue.alpha }; + mDeviceContext->ClearRenderTargetView(framebufferRTV, clearValues); + } + } + } + } + if (clearParams.mask & GL_DEPTH_BUFFER_BIT || clearParams.mask & GL_STENCIL_BUFFER_BIT) + { + gl::Renderbuffer *renderbufferObject = frameBuffer->getDepthOrStencilbuffer(); + if (renderbufferObject) + { + RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(renderbufferObject->getDepthStencil()); + if (!renderTarget) + { + ERR("render target pointer unexpectedly null."); + return; + } + + ID3D11DepthStencilView *framebufferDSV = renderTarget->getDepthStencilView(); + if (!framebufferDSV) + { + ERR("depth stencil view pointer unexpectedly null."); + return; + } + + UINT clearFlags = 0; + if (clearParams.mask & GL_DEPTH_BUFFER_BIT) + { + clearFlags |= D3D11_CLEAR_DEPTH; + } + if (clearParams.mask & GL_STENCIL_BUFFER_BIT) + { + clearFlags |= D3D11_CLEAR_STENCIL; + } + + float depthClear = gl::clamp01(clearParams.depthClearValue); + UINT8 stencilClear = clearParams.stencilClearValue & 0x000000FF; + + mDeviceContext->ClearDepthStencilView(framebufferDSV, clearFlags, depthClear, stencilClear); + } + } + } +} + +void Renderer11::maskedClear(const gl::ClearParameters &clearParams, bool usingExtendedDrawBuffers) +{ + HRESULT result; + + if (!mClearResourcesInitialized) + { + ASSERT(!mClearVB && !mClearVS && !mClearSinglePS && !mClearMultiplePS && !mClearScissorRS && !mClearNoScissorRS); + + D3D11_BUFFER_DESC vbDesc; + vbDesc.ByteWidth = sizeof(d3d11::PositionDepthColorVertex) * 4; + vbDesc.Usage = D3D11_USAGE_DYNAMIC; + vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + vbDesc.MiscFlags = 0; + vbDesc.StructureByteStride = 0; + + result = mDevice->CreateBuffer(&vbDesc, NULL, &mClearVB); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mClearVB, "Renderer11 masked clear vertex buffer"); + + D3D11_INPUT_ELEMENT_DESC quadLayout[] = + { + { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }; + + result = mDevice->CreateInputLayout(quadLayout, 2, g_VS_Clear, sizeof(g_VS_Clear), &mClearIL); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mClearIL, "Renderer11 masked clear input layout"); + + result = mDevice->CreateVertexShader(g_VS_Clear, sizeof(g_VS_Clear), NULL, &mClearVS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mClearVS, "Renderer11 masked clear vertex shader"); + + result = mDevice->CreatePixelShader(g_PS_ClearSingle, sizeof(g_PS_ClearSingle), NULL, &mClearSinglePS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mClearSinglePS, "Renderer11 masked clear pixel shader (1 RT)"); + + result = mDevice->CreatePixelShader(g_PS_ClearMultiple, sizeof(g_PS_ClearMultiple), NULL, &mClearMultiplePS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mClearMultiplePS, "Renderer11 masked clear pixel shader (MRT)"); + + D3D11_RASTERIZER_DESC rsScissorDesc; + rsScissorDesc.FillMode = D3D11_FILL_SOLID; + rsScissorDesc.CullMode = D3D11_CULL_NONE; + rsScissorDesc.FrontCounterClockwise = FALSE; + rsScissorDesc.DepthBias = 0; + rsScissorDesc.DepthBiasClamp = 0.0f; + rsScissorDesc.SlopeScaledDepthBias = 0.0f; + rsScissorDesc.DepthClipEnable = FALSE; + rsScissorDesc.ScissorEnable = TRUE; + rsScissorDesc.MultisampleEnable = FALSE; + rsScissorDesc.AntialiasedLineEnable = FALSE; + + result = mDevice->CreateRasterizerState(&rsScissorDesc, &mClearScissorRS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mClearScissorRS, "Renderer11 masked clear scissor rasterizer state"); + + D3D11_RASTERIZER_DESC rsNoScissorDesc; + rsNoScissorDesc.FillMode = D3D11_FILL_SOLID; + rsNoScissorDesc.CullMode = D3D11_CULL_NONE; + rsNoScissorDesc.FrontCounterClockwise = FALSE; + rsNoScissorDesc.DepthBias = 0; + rsNoScissorDesc.DepthBiasClamp = 0.0f; + rsNoScissorDesc.SlopeScaledDepthBias = 0.0f; + rsNoScissorDesc.DepthClipEnable = FALSE; + rsNoScissorDesc.ScissorEnable = FALSE; + rsNoScissorDesc.MultisampleEnable = FALSE; + rsNoScissorDesc.AntialiasedLineEnable = FALSE; + + result = mDevice->CreateRasterizerState(&rsNoScissorDesc, &mClearNoScissorRS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mClearNoScissorRS, "Renderer11 masked clear no scissor rasterizer state"); + + mClearResourcesInitialized = true; + } + + // Prepare the depth stencil state to write depth values if the depth should be cleared + // and stencil values if the stencil should be cleared + gl::DepthStencilState glDSState; + glDSState.depthTest = (clearParams.mask & GL_DEPTH_BUFFER_BIT) != 0; + glDSState.depthFunc = GL_ALWAYS; + glDSState.depthMask = (clearParams.mask & GL_DEPTH_BUFFER_BIT) != 0; + glDSState.stencilTest = (clearParams.mask & GL_STENCIL_BUFFER_BIT) != 0; + glDSState.stencilFunc = GL_ALWAYS; + glDSState.stencilMask = 0; + glDSState.stencilFail = GL_REPLACE; + glDSState.stencilPassDepthFail = GL_REPLACE; + glDSState.stencilPassDepthPass = GL_REPLACE; + glDSState.stencilWritemask = clearParams.stencilWriteMask; + glDSState.stencilBackFunc = GL_ALWAYS; + glDSState.stencilBackMask = 0; + glDSState.stencilBackFail = GL_REPLACE; + glDSState.stencilBackPassDepthFail = GL_REPLACE; + glDSState.stencilBackPassDepthPass = GL_REPLACE; + glDSState.stencilBackWritemask = clearParams.stencilWriteMask; + + int stencilClear = clearParams.stencilClearValue & 0x000000FF; + + ID3D11DepthStencilState *dsState = mStateCache.getDepthStencilState(glDSState); + + // Prepare the blend state to use a write mask if the color buffer should be cleared + gl::BlendState glBlendState; + glBlendState.blend = false; + glBlendState.sourceBlendRGB = GL_ONE; + glBlendState.destBlendRGB = GL_ZERO; + glBlendState.sourceBlendAlpha = GL_ONE; + glBlendState.destBlendAlpha = GL_ZERO; + glBlendState.blendEquationRGB = GL_FUNC_ADD; + glBlendState.blendEquationAlpha = GL_FUNC_ADD; + glBlendState.colorMaskRed = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskRed : false; + glBlendState.colorMaskGreen = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskGreen : false; + glBlendState.colorMaskBlue = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskBlue : false; + glBlendState.colorMaskAlpha = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskAlpha : false; + glBlendState.sampleAlphaToCoverage = false; + glBlendState.dither = false; + + static const float blendFactors[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; + static const UINT sampleMask = 0xFFFFFFFF; + + ID3D11BlendState *blendState = mStateCache.getBlendState(glBlendState); + + // Set the vertices + D3D11_MAPPED_SUBRESOURCE mappedResource; + result = mDeviceContext->Map(mClearVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + ERR("Failed to map masked clear vertex buffer, HRESULT: 0x%X.", result); + return; + } + + d3d11::PositionDepthColorVertex *vertices = reinterpret_cast(mappedResource.pData); + + float depthClear = gl::clamp01(clearParams.depthClearValue); + d3d11::SetPositionDepthColorVertex(&vertices[0], -1.0f, 1.0f, depthClear, clearParams.colorClearValue); + d3d11::SetPositionDepthColorVertex(&vertices[1], -1.0f, -1.0f, depthClear, clearParams.colorClearValue); + d3d11::SetPositionDepthColorVertex(&vertices[2], 1.0f, 1.0f, depthClear, clearParams.colorClearValue); + d3d11::SetPositionDepthColorVertex(&vertices[3], 1.0f, -1.0f, depthClear, clearParams.colorClearValue); + + mDeviceContext->Unmap(mClearVB, 0); + + // Apply state + mDeviceContext->OMSetBlendState(blendState, blendFactors, sampleMask); + mDeviceContext->OMSetDepthStencilState(dsState, stencilClear); + mDeviceContext->RSSetState(mScissorEnabled ? mClearScissorRS : mClearNoScissorRS); + + // Apply shaders + ID3D11PixelShader *pixelShader = usingExtendedDrawBuffers ? mClearMultiplePS : mClearSinglePS; + + mDeviceContext->IASetInputLayout(mClearIL); + mDeviceContext->VSSetShader(mClearVS, NULL, 0); + mDeviceContext->PSSetShader(pixelShader, NULL, 0); + mDeviceContext->GSSetShader(NULL, NULL, 0); + + // Apply vertex buffer + static UINT stride = sizeof(d3d11::PositionDepthColorVertex); + static UINT startIdx = 0; + mDeviceContext->IASetVertexBuffers(0, 1, &mClearVB, &stride, &startIdx); + mDeviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + + // Draw the clear quad + mDeviceContext->Draw(4, 0); + + // Clean up + markAllStateDirty(); +} + +void Renderer11::markAllStateDirty() +{ + for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++) + { + mAppliedRenderTargetSerials[rtIndex] = 0; + } + mAppliedDepthbufferSerial = 0; + mAppliedStencilbufferSerial = 0; + mDepthStencilInitialized = false; + mRenderTargetDescInitialized = false; + + for (int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; i++) + { + mForceSetVertexSamplerStates[i] = true; + mCurVertexTextureSerials[i] = 0; + } + for (int i = 0; i < gl::MAX_TEXTURE_IMAGE_UNITS; i++) + { + mForceSetPixelSamplerStates[i] = true; + mCurPixelTextureSerials[i] = 0; + } + + mForceSetBlendState = true; + mForceSetRasterState = true; + mForceSetDepthStencilState = true; + mForceSetScissor = true; + mForceSetViewport = true; + + mAppliedIBSerial = 0; + mAppliedStorageIBSerial = 0; + mAppliedIBOffset = 0; + + mAppliedProgramBinarySerial = 0; + memset(&mAppliedVertexConstants, 0, sizeof(dx_VertexConstants)); + memset(&mAppliedPixelConstants, 0, sizeof(dx_PixelConstants)); + + mInputLayoutCache.markDirty(); + + mCurrentVertexConstantBuffer = NULL; + mCurrentPixelConstantBuffer = NULL; + mCurrentGeometryConstantBuffer = NULL; + + mCurrentPrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; +} + +void Renderer11::releaseDeviceResources() +{ + mStateCache.clear(); + mInputLayoutCache.clear(); + + delete mVertexDataManager; + mVertexDataManager = NULL; + + delete mIndexDataManager; + mIndexDataManager = NULL; + + delete mLineLoopIB; + mLineLoopIB = NULL; + + delete mTriangleFanIB; + mTriangleFanIB = NULL; + + SafeRelease(mCopyVB); + SafeRelease(mCopySampler); + SafeRelease(mCopyIL); + SafeRelease(mCopyIL); + SafeRelease(mCopyVS); + SafeRelease(mCopyRGBAPS); + SafeRelease(mCopyRGBPS); + SafeRelease(mCopyLumPS); + SafeRelease(mCopyLumAlphaPS); + + mCopyResourcesInitialized = false; + + SafeRelease(mClearVB); + SafeRelease(mClearIL); + SafeRelease(mClearVS); + SafeRelease(mClearSinglePS); + SafeRelease(mClearMultiplePS); + SafeRelease(mClearScissorRS); + SafeRelease(mClearNoScissorRS); + + mClearResourcesInitialized = false; + + SafeRelease(mDriverConstantBufferVS); + SafeRelease(mDriverConstantBufferPS); + SafeRelease(mSyncQuery); +} + +void Renderer11::notifyDeviceLost() +{ + mDeviceLost = true; + mDisplay->notifyDeviceLost(); +} + +bool Renderer11::isDeviceLost() +{ + return mDeviceLost; +} + +// set notify to true to broadcast a message to all contexts of the device loss +bool Renderer11::testDeviceLost(bool notify) +{ + bool isLost = false; + + // GetRemovedReason is used to test if the device is removed + HRESULT result = mDevice->GetDeviceRemovedReason(); + isLost = d3d11::isDeviceLostError(result); + + if (isLost) + { + // Log error if this is a new device lost event + if (mDeviceLost == false) + { + ERR("The D3D11 device was removed: 0x%08X", result); + } + + // ensure we note the device loss -- + // we'll probably get this done again by notifyDeviceLost + // but best to remember it! + // Note that we don't want to clear the device loss status here + // -- this needs to be done by resetDevice + mDeviceLost = true; + if (notify) + { + notifyDeviceLost(); + } + } + + return isLost; +} + +bool Renderer11::testDeviceResettable() +{ + // determine if the device is resettable by creating a dummy device + PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice"); + + if (D3D11CreateDevice == NULL) + { + return false; + } + + D3D_FEATURE_LEVEL featureLevels[] = + { + D3D_FEATURE_LEVEL_11_0, + D3D_FEATURE_LEVEL_10_1, + D3D_FEATURE_LEVEL_10_0, + }; + + ID3D11Device* dummyDevice; + D3D_FEATURE_LEVEL dummyFeatureLevel; + ID3D11DeviceContext* dummyContext; + + HRESULT result = D3D11CreateDevice(NULL, + D3D_DRIVER_TYPE_HARDWARE, + NULL, + #if defined(_DEBUG) + D3D11_CREATE_DEVICE_DEBUG, + #else + 0, + #endif + featureLevels, + ArraySize(featureLevels), + D3D11_SDK_VERSION, + &dummyDevice, + &dummyFeatureLevel, + &dummyContext); + + if (!mDevice || FAILED(result)) + { + return false; + } + + dummyContext->Release(); + dummyDevice->Release(); + + return true; +} + +void Renderer11::release() +{ + releaseDeviceResources(); + + if (mDxgiFactory) + { + mDxgiFactory->Release(); + mDxgiFactory = NULL; + } + + if (mDxgiAdapter) + { + mDxgiAdapter->Release(); + mDxgiAdapter = NULL; + } + + if (mDeviceContext) + { + mDeviceContext->ClearState(); + mDeviceContext->Flush(); + mDeviceContext->Release(); + mDeviceContext = NULL; + } + + if (mDevice) + { + mDevice->Release(); + mDevice = NULL; + } + + if (mD3d11Module) + { + FreeLibrary(mD3d11Module); + mD3d11Module = NULL; + } + + if (mDxgiModule) + { + FreeLibrary(mDxgiModule); + mDxgiModule = NULL; + } +} + +bool Renderer11::resetDevice() +{ + // recreate everything + release(); + EGLint result = initialize(); + + if (result != EGL_SUCCESS) + { + ERR("Could not reinitialize D3D11 device: %08X", result); + return false; + } + + mDeviceLost = false; + + return true; +} + +DWORD Renderer11::getAdapterVendor() const +{ + return mAdapterDescription.VendorId; +} + +std::string Renderer11::getRendererDescription() const +{ + std::ostringstream rendererString; + + rendererString << mDescription; + rendererString << " Direct3D11"; + + rendererString << " vs_" << getMajorShaderModel() << "_" << getMinorShaderModel(); + rendererString << " ps_" << getMajorShaderModel() << "_" << getMinorShaderModel(); + + return rendererString.str(); +} + +GUID Renderer11::getAdapterIdentifier() const +{ + // Use the adapter LUID as our adapter ID + // This number is local to a machine is only guaranteed to be unique between restarts + META_ASSERT(sizeof(LUID) <= sizeof(GUID)); + GUID adapterId = {0}; + memcpy(&adapterId, &mAdapterDescription.AdapterLuid, sizeof(LUID)); + return adapterId; +} + +bool Renderer11::getBGRATextureSupport() const +{ + return mBGRATextureSupport; +} + +bool Renderer11::getDXT1TextureSupport() +{ + return mDXT1TextureSupport; +} + +bool Renderer11::getDXT3TextureSupport() +{ + return mDXT3TextureSupport; +} + +bool Renderer11::getDXT5TextureSupport() +{ + return mDXT5TextureSupport; +} + +bool Renderer11::getDepthTextureSupport() const +{ + return mDepthTextureSupport; +} + +bool Renderer11::getFloat32TextureSupport(bool *filtering, bool *renderable) +{ + *renderable = mFloat32RenderSupport; + *filtering = mFloat32FilterSupport; + return mFloat32TextureSupport; +} + +bool Renderer11::getFloat16TextureSupport(bool *filtering, bool *renderable) +{ + *renderable = mFloat16RenderSupport; + *filtering = mFloat16FilterSupport; + return mFloat16TextureSupport; +} + +bool Renderer11::getLuminanceTextureSupport() +{ + return false; +} + +bool Renderer11::getLuminanceAlphaTextureSupport() +{ + return false; +} + +bool Renderer11::getTextureFilterAnisotropySupport() const +{ + return true; +} + +float Renderer11::getTextureMaxAnisotropy() const +{ + switch (mFeatureLevel) + { + case D3D_FEATURE_LEVEL_11_0: + return D3D11_MAX_MAXANISOTROPY; + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return D3D10_MAX_MAXANISOTROPY; + default: UNREACHABLE(); + return 0; + } +} + +bool Renderer11::getEventQuerySupport() +{ + return true; +} + +Range Renderer11::getViewportBounds() const +{ + switch (mFeatureLevel) + { + case D3D_FEATURE_LEVEL_11_0: + return Range(D3D11_VIEWPORT_BOUNDS_MIN, D3D11_VIEWPORT_BOUNDS_MAX); + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return Range(D3D10_VIEWPORT_BOUNDS_MIN, D3D10_VIEWPORT_BOUNDS_MAX); + default: UNREACHABLE(); + return Range(0, 0); + } +} + +unsigned int Renderer11::getMaxVertexTextureImageUnits() const +{ + META_ASSERT(MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 <= gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS); + switch (mFeatureLevel) + { + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return MAX_TEXTURE_IMAGE_UNITS_VTF_SM4; + default: UNREACHABLE(); + return 0; + } +} + +unsigned int Renderer11::getMaxCombinedTextureImageUnits() const +{ + return gl::MAX_TEXTURE_IMAGE_UNITS + getMaxVertexTextureImageUnits(); +} + +unsigned int Renderer11::getReservedVertexUniformVectors() const +{ + return 0; // Driver uniforms are stored in a separate constant buffer +} + +unsigned int Renderer11::getReservedFragmentUniformVectors() const +{ + return 0; // Driver uniforms are stored in a separate constant buffer +} + +unsigned int Renderer11::getMaxVertexUniformVectors() const +{ + META_ASSERT(MAX_VERTEX_UNIFORM_VECTORS_D3D11 <= D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT); + ASSERT(mFeatureLevel >= D3D_FEATURE_LEVEL_10_0); + return MAX_VERTEX_UNIFORM_VECTORS_D3D11; +} + +unsigned int Renderer11::getMaxFragmentUniformVectors() const +{ + META_ASSERT(MAX_FRAGMENT_UNIFORM_VECTORS_D3D11 <= D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT); + ASSERT(mFeatureLevel >= D3D_FEATURE_LEVEL_10_0); + return MAX_FRAGMENT_UNIFORM_VECTORS_D3D11; +} + +unsigned int Renderer11::getMaxVaryingVectors() const +{ + META_ASSERT(gl::IMPLEMENTATION_MAX_VARYING_VECTORS == D3D11_VS_OUTPUT_REGISTER_COUNT); + switch (mFeatureLevel) + { + case D3D_FEATURE_LEVEL_11_0: + return D3D11_VS_OUTPUT_REGISTER_COUNT; + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return D3D10_VS_OUTPUT_REGISTER_COUNT; + default: UNREACHABLE(); + return 0; + } +} + +bool Renderer11::getNonPower2TextureSupport() const +{ + switch (mFeatureLevel) + { + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return true; + default: UNREACHABLE(); + return false; + } +} + +bool Renderer11::getOcclusionQuerySupport() const +{ + switch (mFeatureLevel) + { + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return true; + default: UNREACHABLE(); + return false; + } +} + +bool Renderer11::getInstancingSupport() const +{ + switch (mFeatureLevel) + { + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return true; + default: UNREACHABLE(); + return false; + } +} + +bool Renderer11::getShareHandleSupport() const +{ + // We only currently support share handles with BGRA surfaces, because + // chrome needs BGRA. Once chrome fixes this, we should always support them. + // PIX doesn't seem to support using share handles, so disable them. + return getBGRATextureSupport() && !gl::perfActive(); +} + +bool Renderer11::getDerivativeInstructionSupport() const +{ + switch (mFeatureLevel) + { + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return true; + default: UNREACHABLE(); + return false; + } +} + +bool Renderer11::getPostSubBufferSupport() const +{ + // D3D11 does not support present with dirty rectangles until D3D11.1 and DXGI 1.2. + return false; +} + +int Renderer11::getMajorShaderModel() const +{ + switch (mFeatureLevel) + { + case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MAJOR_VERSION; // 5 + case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MAJOR_VERSION; // 4 + case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MAJOR_VERSION; // 4 + default: UNREACHABLE(); return 0; + } +} + +int Renderer11::getMinorShaderModel() const +{ + switch (mFeatureLevel) + { + case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MINOR_VERSION; // 0 + case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MINOR_VERSION; // 1 + case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MINOR_VERSION; // 0 + default: UNREACHABLE(); return 0; + } +} + +float Renderer11::getMaxPointSize() const +{ + // choose a reasonable maximum. we enforce this in the shader. + // (nb: on a Radeon 2600xt, DX9 reports a 256 max point size) + return 1024.0f; +} + +int Renderer11::getMaxViewportDimension() const +{ + // Maximum viewport size must be at least as large as the largest render buffer (or larger). + // In our case return the maximum texture size, which is the maximum render buffer size. + META_ASSERT(D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION * 2 - 1 <= D3D11_VIEWPORT_BOUNDS_MAX); + META_ASSERT(D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION * 2 - 1 <= D3D10_VIEWPORT_BOUNDS_MAX); + + switch (mFeatureLevel) + { + case D3D_FEATURE_LEVEL_11_0: + return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384 + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192 + default: UNREACHABLE(); + return 0; + } +} + +int Renderer11::getMaxTextureWidth() const +{ + switch (mFeatureLevel) + { + case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384 + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192 + default: UNREACHABLE(); return 0; + } +} + +int Renderer11::getMaxTextureHeight() const +{ + switch (mFeatureLevel) + { + case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384 + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192 + default: UNREACHABLE(); return 0; + } +} + +bool Renderer11::get32BitIndexSupport() const +{ + switch (mFeatureLevel) + { + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP >= 32; // true + default: UNREACHABLE(); return false; + } +} + +int Renderer11::getMinSwapInterval() const +{ + return 0; +} + +int Renderer11::getMaxSwapInterval() const +{ + return 4; +} + +int Renderer11::getMaxSupportedSamples() const +{ + return mMaxSupportedSamples; +} + +int Renderer11::getNearestSupportedSamples(DXGI_FORMAT format, unsigned int requested) const +{ + if (requested == 0) + { + return 0; + } + + MultisampleSupportMap::const_iterator iter = mMultisampleSupportMap.find(format); + if (iter != mMultisampleSupportMap.end()) + { + const MultisampleSupportInfo& info = iter->second; + for (unsigned int i = requested - 1; i < D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; i++) + { + if (info.qualityLevels[i] > 0) + { + return i + 1; + } + } + } + + return -1; +} + +unsigned int Renderer11::getMaxRenderTargets() const +{ + META_ASSERT(D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS); + META_ASSERT(D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS); + + switch (mFeatureLevel) + { + case D3D_FEATURE_LEVEL_11_0: + return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; // 8 + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT; // 8 + default: + UNREACHABLE(); + return 1; + } +} + +bool Renderer11::copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source) +{ + if (source && dest) + { + TextureStorage11_2D *source11 = TextureStorage11_2D::makeTextureStorage11_2D(source->getStorageInstance()); + TextureStorage11_2D *dest11 = TextureStorage11_2D::makeTextureStorage11_2D(dest->getStorageInstance()); + + mDeviceContext->CopyResource(dest11->getBaseTexture(), source11->getBaseTexture()); + return true; + } + + return false; +} + +bool Renderer11::copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source) +{ + if (source && dest) + { + TextureStorage11_Cube *source11 = TextureStorage11_Cube::makeTextureStorage11_Cube(source->getStorageInstance()); + TextureStorage11_Cube *dest11 = TextureStorage11_Cube::makeTextureStorage11_Cube(dest->getStorageInstance()); + + mDeviceContext->CopyResource(dest11->getBaseTexture(), source11->getBaseTexture()); + return true; + } + + return false; +} + +bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level) +{ + gl::Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer(); + if (!colorbuffer) + { + ERR("Failed to retrieve the color buffer from the frame buffer."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget()); + if (!sourceRenderTarget) + { + ERR("Failed to retrieve the render target from the frame buffer."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); + if (!source) + { + ERR("Failed to retrieve the render target view from the render target."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage->getStorageInstance()); + if (!storage11) + { + ERR("Failed to retrieve the texture storage from the destination."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(level)); + if (!destRenderTarget) + { + ERR("Failed to retrieve the render target from the destination storage."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView(); + if (!dest) + { + ERR("Failed to retrieve the render target view from the destination render target."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + gl::Rectangle destRect; + destRect.x = xoffset; + destRect.y = yoffset; + destRect.width = sourceRect.width; + destRect.height = sourceRect.height; + + bool ret = copyTexture(source, sourceRect, sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), + dest, destRect, destRenderTarget->getWidth(), destRenderTarget->getHeight(), destFormat); + + return ret; +} + +bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level) +{ + gl::Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer(); + if (!colorbuffer) + { + ERR("Failed to retrieve the color buffer from the frame buffer."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget()); + if (!sourceRenderTarget) + { + ERR("Failed to retrieve the render target from the frame buffer."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); + if (!source) + { + ERR("Failed to retrieve the render target view from the render target."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage->getStorageInstance()); + if (!storage11) + { + ERR("Failed to retrieve the texture storage from the destination."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(target, level)); + if (!destRenderTarget) + { + ERR("Failed to retrieve the render target from the destination storage."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView(); + if (!dest) + { + ERR("Failed to retrieve the render target view from the destination render target."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + gl::Rectangle destRect; + destRect.x = xoffset; + destRect.y = yoffset; + destRect.width = sourceRect.width; + destRect.height = sourceRect.height; + + bool ret = copyTexture(source, sourceRect, sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), + dest, destRect, destRenderTarget->getWidth(), destRenderTarget->getHeight(), destFormat); + + return ret; +} + +bool Renderer11::copyTexture(ID3D11ShaderResourceView *source, const gl::Rectangle &sourceArea, unsigned int sourceWidth, unsigned int sourceHeight, + ID3D11RenderTargetView *dest, const gl::Rectangle &destArea, unsigned int destWidth, unsigned int destHeight, GLenum destFormat) +{ + HRESULT result; + + if (!mCopyResourcesInitialized) + { + ASSERT(!mCopyVB && !mCopySampler && !mCopyIL && !mCopyVS && !mCopyRGBAPS && !mCopyRGBPS && !mCopyLumPS && !mCopyLumAlphaPS); + + D3D11_BUFFER_DESC vbDesc; + vbDesc.ByteWidth = sizeof(d3d11::PositionTexCoordVertex) * 4; + vbDesc.Usage = D3D11_USAGE_DYNAMIC; + vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + vbDesc.MiscFlags = 0; + vbDesc.StructureByteStride = 0; + + result = mDevice->CreateBuffer(&vbDesc, NULL, &mCopyVB); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mCopyVB, "Renderer11 copy texture vertex buffer"); + + D3D11_SAMPLER_DESC samplerDesc; + samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; + samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; + samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; + samplerDesc.MipLODBias = 0.0f; + samplerDesc.MaxAnisotropy = 0; + samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; + samplerDesc.BorderColor[0] = 0.0f; + samplerDesc.BorderColor[1] = 0.0f; + samplerDesc.BorderColor[2] = 0.0f; + samplerDesc.BorderColor[3] = 0.0f; + samplerDesc.MinLOD = 0.0f; + samplerDesc.MaxLOD = 0.0f; + + result = mDevice->CreateSamplerState(&samplerDesc, &mCopySampler); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mCopySampler, "Renderer11 copy sampler"); + + D3D11_INPUT_ELEMENT_DESC quadLayout[] = + { + { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }; + + result = mDevice->CreateInputLayout(quadLayout, 2, g_VS_Passthrough, sizeof(g_VS_Passthrough), &mCopyIL); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mCopyIL, "Renderer11 copy texture input layout"); + + result = mDevice->CreateVertexShader(g_VS_Passthrough, sizeof(g_VS_Passthrough), NULL, &mCopyVS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mCopyVS, "Renderer11 copy texture vertex shader"); + + result = mDevice->CreatePixelShader(g_PS_PassthroughRGBA, sizeof(g_PS_PassthroughRGBA), NULL, &mCopyRGBAPS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mCopyRGBAPS, "Renderer11 copy texture RGBA pixel shader"); + + result = mDevice->CreatePixelShader(g_PS_PassthroughRGB, sizeof(g_PS_PassthroughRGB), NULL, &mCopyRGBPS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mCopyRGBPS, "Renderer11 copy texture RGB pixel shader"); + + result = mDevice->CreatePixelShader(g_PS_PassthroughLum, sizeof(g_PS_PassthroughLum), NULL, &mCopyLumPS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mCopyLumPS, "Renderer11 copy texture luminance pixel shader"); + + result = mDevice->CreatePixelShader(g_PS_PassthroughLumAlpha, sizeof(g_PS_PassthroughLumAlpha), NULL, &mCopyLumAlphaPS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mCopyLumAlphaPS, "Renderer11 copy texture luminance alpha pixel shader"); + + mCopyResourcesInitialized = true; + } + + // Verify the source and destination area sizes + if (sourceArea.x < 0 || sourceArea.x + sourceArea.width > static_cast(sourceWidth) || + sourceArea.y < 0 || sourceArea.y + sourceArea.height > static_cast(sourceHeight) || + destArea.x < 0 || destArea.x + destArea.width > static_cast(destWidth) || + destArea.y < 0 || destArea.y + destArea.height > static_cast(destHeight)) + { + return gl::error(GL_INVALID_VALUE, false); + } + + // Set vertices + D3D11_MAPPED_SUBRESOURCE mappedResource; + result = mDeviceContext->Map(mCopyVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + ERR("Failed to map vertex buffer for texture copy, HRESULT: 0x%X.", result); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + d3d11::PositionTexCoordVertex *vertices = static_cast(mappedResource.pData); + + // Create a quad in homogeneous coordinates + float x1 = (destArea.x / float(destWidth)) * 2.0f - 1.0f; + float y1 = ((destHeight - destArea.y - destArea.height) / float(destHeight)) * 2.0f - 1.0f; + float x2 = ((destArea.x + destArea.width) / float(destWidth)) * 2.0f - 1.0f; + float y2 = ((destHeight - destArea.y) / float(destHeight)) * 2.0f - 1.0f; + + float u1 = sourceArea.x / float(sourceWidth); + float v1 = sourceArea.y / float(sourceHeight); + float u2 = (sourceArea.x + sourceArea.width) / float(sourceWidth); + float v2 = (sourceArea.y + sourceArea.height) / float(sourceHeight); + + d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v2); + d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v1); + d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v2); + d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v1); + + mDeviceContext->Unmap(mCopyVB, 0); + + static UINT stride = sizeof(d3d11::PositionTexCoordVertex); + static UINT startIdx = 0; + mDeviceContext->IASetVertexBuffers(0, 1, &mCopyVB, &stride, &startIdx); + + // Apply state + mDeviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF); + mDeviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF); + mDeviceContext->RSSetState(NULL); + + // Apply shaders + mDeviceContext->IASetInputLayout(mCopyIL); + mDeviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + mDeviceContext->VSSetShader(mCopyVS, NULL, 0); + + ID3D11PixelShader *ps = NULL; + switch(destFormat) + { + case GL_RGBA: ps = mCopyRGBAPS; break; + case GL_RGB: ps = mCopyRGBPS; break; + case GL_ALPHA: ps = mCopyRGBAPS; break; + case GL_BGRA_EXT: ps = mCopyRGBAPS; break; + case GL_LUMINANCE: ps = mCopyLumPS; break; + case GL_LUMINANCE_ALPHA: ps = mCopyLumAlphaPS; break; + default: UNREACHABLE(); ps = NULL; break; + } + + mDeviceContext->PSSetShader(ps, NULL, 0); + mDeviceContext->GSSetShader(NULL, NULL, 0); + + // Unset the currently bound shader resource to avoid conflicts + static ID3D11ShaderResourceView *const nullSRV = NULL; + mDeviceContext->PSSetShaderResources(0, 1, &nullSRV); + + // Apply render target + setOneTimeRenderTarget(dest); + + // Set the viewport + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; + viewport.Width = destWidth; + viewport.Height = destHeight; + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + mDeviceContext->RSSetViewports(1, &viewport); + + // Apply textures + mDeviceContext->PSSetShaderResources(0, 1, &source); + mDeviceContext->PSSetSamplers(0, 1, &mCopySampler); + + // Draw the quad + mDeviceContext->Draw(4, 0); + + // Unbind textures and render targets and vertex buffer + mDeviceContext->PSSetShaderResources(0, 1, &nullSRV); + + unapplyRenderTargets(); + + UINT zero = 0; + ID3D11Buffer *const nullBuffer = NULL; + mDeviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero); + + markAllStateDirty(); + + return true; +} + +void Renderer11::unapplyRenderTargets() +{ + setOneTimeRenderTarget(NULL); +} + +void Renderer11::setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView) +{ + ID3D11RenderTargetView *rtvArray[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL}; + + rtvArray[0] = renderTargetView; + + mDeviceContext->OMSetRenderTargets(getMaxRenderTargets(), rtvArray, NULL); + + // Do not preserve the serial for this one-time-use render target + for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++) + { + mAppliedRenderTargetSerials[rtIndex] = 0; + } +} + +RenderTarget *Renderer11::createRenderTarget(SwapChain *swapChain, bool depth) +{ + SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain); + RenderTarget11 *renderTarget = NULL; + + if (depth) + { + // Note: depth stencil may be NULL for 0 sized surfaces + renderTarget = new RenderTarget11(this, swapChain11->getDepthStencil(), + swapChain11->getDepthStencilTexture(), NULL, + swapChain11->getWidth(), swapChain11->getHeight()); + } + else + { + // Note: render target may be NULL for 0 sized surfaces + renderTarget = new RenderTarget11(this, swapChain11->getRenderTarget(), + swapChain11->getOffscreenTexture(), + swapChain11->getRenderTargetShaderResource(), + swapChain11->getWidth(), swapChain11->getHeight()); + } + return renderTarget; +} + +RenderTarget *Renderer11::createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth) +{ + RenderTarget11 *renderTarget = new RenderTarget11(this, width, height, format, samples, depth); + return renderTarget; +} + +ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length, rx::ShaderType type) +{ + ShaderExecutable11 *executable = NULL; + + switch (type) + { + case rx::SHADER_VERTEX: + { + ID3D11VertexShader *vshader = NULL; + HRESULT result = mDevice->CreateVertexShader(function, length, NULL, &vshader); + ASSERT(SUCCEEDED(result)); + + if (vshader) + { + executable = new ShaderExecutable11(function, length, vshader); + } + } + break; + case rx::SHADER_PIXEL: + { + ID3D11PixelShader *pshader = NULL; + HRESULT result = mDevice->CreatePixelShader(function, length, NULL, &pshader); + ASSERT(SUCCEEDED(result)); + + if (pshader) + { + executable = new ShaderExecutable11(function, length, pshader); + } + } + break; + case rx::SHADER_GEOMETRY: + { + ID3D11GeometryShader *gshader = NULL; + HRESULT result = mDevice->CreateGeometryShader(function, length, NULL, &gshader); + ASSERT(SUCCEEDED(result)); + + if (gshader) + { + executable = new ShaderExecutable11(function, length, gshader); + } + } + break; + default: + UNREACHABLE(); + break; + } + + return executable; +} + +ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type) +{ + const char *profile = NULL; + + switch (type) + { + case rx::SHADER_VERTEX: + profile = "vs_4_0"; + break; + case rx::SHADER_PIXEL: + profile = "ps_4_0"; + break; + case rx::SHADER_GEOMETRY: + profile = "gs_4_0"; + break; + default: + UNREACHABLE(); + return NULL; + } + + ID3DBlob *binary = (ID3DBlob*)compileToBinary(infoLog, shaderHLSL, profile, D3DCOMPILE_OPTIMIZATION_LEVEL0, false); + if (!binary) + return NULL; + + ShaderExecutable *executable = loadExecutable((DWORD *)binary->GetBufferPointer(), binary->GetBufferSize(), type); + binary->Release(); + + return executable; +} + +VertexBuffer *Renderer11::createVertexBuffer() +{ + return new VertexBuffer11(this); +} + +IndexBuffer *Renderer11::createIndexBuffer() +{ + return new IndexBuffer11(this); +} + +BufferStorage *Renderer11::createBufferStorage() +{ + return new BufferStorage11(this); +} + +QueryImpl *Renderer11::createQuery(GLenum type) +{ + return new Query11(this, type); +} + +FenceImpl *Renderer11::createFence() +{ + return new Fence11(this); +} + +bool Renderer11::getRenderTargetResource(gl::Renderbuffer *colorbuffer, unsigned int *subresourceIndex, ID3D11Texture2D **resource) +{ + ASSERT(colorbuffer != NULL); + + RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget()); + if (renderTarget) + { + *subresourceIndex = renderTarget->getSubresourceIndex(); + + ID3D11RenderTargetView *colorBufferRTV = renderTarget->getRenderTargetView(); + if (colorBufferRTV) + { + ID3D11Resource *textureResource = NULL; + colorBufferRTV->GetResource(&textureResource); + + if (textureResource) + { + HRESULT result = textureResource->QueryInterface(IID_ID3D11Texture2D, (void**)resource); + textureResource->Release(); + + if (SUCCEEDED(result)) + { + return true; + } + else + { + ERR("Failed to extract the ID3D11Texture2D from the render target resource, " + "HRESULT: 0x%X.", result); + } + } + } + } + + return false; +} + +bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, + bool blitRenderTarget, bool blitDepthStencil) +{ + if (blitRenderTarget) + { + gl::Renderbuffer *readBuffer = readTarget->getReadColorbuffer(); + + if (!readBuffer) + { + ERR("Failed to retrieve the read buffer from the read framebuffer."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + RenderTarget *readRenderTarget = readBuffer->getRenderTarget(); + + for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) + { + if (drawTarget->isEnabledColorAttachment(colorAttachment)) + { + gl::Renderbuffer *drawBuffer = drawTarget->getColorbuffer(colorAttachment); + + if (!drawBuffer) + { + ERR("Failed to retrieve the draw buffer from the draw framebuffer."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + RenderTarget *drawRenderTarget = drawBuffer->getRenderTarget(); + + if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, false)) + { + return false; + } + } + } + } + + if (blitDepthStencil) + { + gl::Renderbuffer *readBuffer = readTarget->getDepthOrStencilbuffer(); + gl::Renderbuffer *drawBuffer = drawTarget->getDepthOrStencilbuffer(); + + if (!readBuffer) + { + ERR("Failed to retrieve the read depth-stencil buffer from the read framebuffer."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + if (!drawBuffer) + { + ERR("Failed to retrieve the draw depth-stencil buffer from the draw framebuffer."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + RenderTarget *readRenderTarget = readBuffer->getDepthStencil(); + RenderTarget *drawRenderTarget = drawBuffer->getDepthStencil(); + + if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, true)) + { + return false; + } + } + + return true; +} + +void Renderer11::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, + GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels) +{ + ID3D11Texture2D *colorBufferTexture = NULL; + unsigned int subresourceIndex = 0; + + gl::Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer(); + + if (colorbuffer && getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture)) + { + gl::Rectangle area; + area.x = x; + area.y = y; + area.width = width; + area.height = height; + + readTextureData(colorBufferTexture, subresourceIndex, area, format, type, outputPitch, + packReverseRowOrder, packAlignment, pixels); + + colorBufferTexture->Release(); + colorBufferTexture = NULL; + } +} + +Image *Renderer11::createImage() +{ + return new Image11(); +} + +void Renderer11::generateMipmap(Image *dest, Image *src) +{ + Image11 *dest11 = Image11::makeImage11(dest); + Image11 *src11 = Image11::makeImage11(src); + Image11::generateMipmap(dest11, src11); +} + +TextureStorage *Renderer11::createTextureStorage2D(SwapChain *swapChain) +{ + SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain); + return new TextureStorage11_2D(this, swapChain11); +} + +TextureStorage *Renderer11::createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height) +{ + return new TextureStorage11_2D(this, levels, internalformat, usage, forceRenderable, width, height); +} + +TextureStorage *Renderer11::createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size) +{ + return new TextureStorage11_Cube(this, levels, internalformat, usage, forceRenderable, size); +} + +static inline unsigned int getFastPixelCopySize(DXGI_FORMAT sourceFormat, GLenum destFormat, GLenum destType) +{ + if (sourceFormat == DXGI_FORMAT_A8_UNORM && + destFormat == GL_ALPHA && + destType == GL_UNSIGNED_BYTE) + { + return 1; + } + else if (sourceFormat == DXGI_FORMAT_R8G8B8A8_UNORM && + destFormat == GL_RGBA && + destType == GL_UNSIGNED_BYTE) + { + return 4; + } + else if (sourceFormat == DXGI_FORMAT_B8G8R8A8_UNORM && + destFormat == GL_BGRA_EXT && + destType == GL_UNSIGNED_BYTE) + { + return 4; + } + else if (sourceFormat == DXGI_FORMAT_R16G16B16A16_FLOAT && + destFormat == GL_RGBA && + destType == GL_HALF_FLOAT_OES) + { + return 8; + } + else if (sourceFormat == DXGI_FORMAT_R32G32B32_FLOAT && + destFormat == GL_RGB && + destType == GL_FLOAT) + { + return 12; + } + else if (sourceFormat == DXGI_FORMAT_R32G32B32A32_FLOAT && + destFormat == GL_RGBA && + destType == GL_FLOAT) + { + return 16; + } + else + { + return 0; + } +} + +static inline void readPixelColor(const unsigned char *data, DXGI_FORMAT format, unsigned int x, + unsigned int y, int inputPitch, gl::Color *outColor) +{ + switch (format) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: + { + unsigned int rgba = *reinterpret_cast(data + 4 * x + y * inputPitch); + outColor->red = (rgba & 0x000000FF) * (1.0f / 0x000000FF); + outColor->green = (rgba & 0x0000FF00) * (1.0f / 0x0000FF00); + outColor->blue = (rgba & 0x00FF0000) * (1.0f / 0x00FF0000); + outColor->alpha = (rgba & 0xFF000000) * (1.0f / 0xFF000000); + } + break; + + case DXGI_FORMAT_A8_UNORM: + { + outColor->red = 0.0f; + outColor->green = 0.0f; + outColor->blue = 0.0f; + outColor->alpha = *(data + x + y * inputPitch) / 255.0f; + } + break; + + case DXGI_FORMAT_R32G32B32A32_FLOAT: + { + outColor->red = *(reinterpret_cast(data + 16 * x + y * inputPitch) + 0); + outColor->green = *(reinterpret_cast(data + 16 * x + y * inputPitch) + 1); + outColor->blue = *(reinterpret_cast(data + 16 * x + y * inputPitch) + 2); + outColor->alpha = *(reinterpret_cast(data + 16 * x + y * inputPitch) + 3); + } + break; + + case DXGI_FORMAT_R32G32B32_FLOAT: + { + outColor->red = *(reinterpret_cast(data + 12 * x + y * inputPitch) + 0); + outColor->green = *(reinterpret_cast(data + 12 * x + y * inputPitch) + 1); + outColor->blue = *(reinterpret_cast(data + 12 * x + y * inputPitch) + 2); + outColor->alpha = 1.0f; + } + break; + + case DXGI_FORMAT_R16G16B16A16_FLOAT: + { + outColor->red = gl::float16ToFloat32(*(reinterpret_cast(data + 8 * x + y * inputPitch) + 0)); + outColor->green = gl::float16ToFloat32(*(reinterpret_cast(data + 8 * x + y * inputPitch) + 1)); + outColor->blue = gl::float16ToFloat32(*(reinterpret_cast(data + 8 * x + y * inputPitch) + 2)); + outColor->alpha = gl::float16ToFloat32(*(reinterpret_cast(data + 8 * x + y * inputPitch) + 3)); + } + break; + + case DXGI_FORMAT_B8G8R8A8_UNORM: + { + unsigned int bgra = *reinterpret_cast(data + 4 * x + y * inputPitch); + outColor->red = (bgra & 0x00FF0000) * (1.0f / 0x00FF0000); + outColor->blue = (bgra & 0x000000FF) * (1.0f / 0x000000FF); + outColor->green = (bgra & 0x0000FF00) * (1.0f / 0x0000FF00); + outColor->alpha = (bgra & 0xFF000000) * (1.0f / 0xFF000000); + } + break; + + case DXGI_FORMAT_R8_UNORM: + { + outColor->red = *(data + x + y * inputPitch) / 255.0f; + outColor->green = 0.0f; + outColor->blue = 0.0f; + outColor->alpha = 1.0f; + } + break; + + case DXGI_FORMAT_R8G8_UNORM: + { + unsigned short rg = *reinterpret_cast(data + 2 * x + y * inputPitch); + + outColor->red = (rg & 0xFF00) * (1.0f / 0xFF00); + outColor->green = (rg & 0x00FF) * (1.0f / 0x00FF); + outColor->blue = 0.0f; + outColor->alpha = 1.0f; + } + break; + + case DXGI_FORMAT_R16_FLOAT: + { + outColor->red = gl::float16ToFloat32(*reinterpret_cast(data + 2 * x + y * inputPitch)); + outColor->green = 0.0f; + outColor->blue = 0.0f; + outColor->alpha = 1.0f; + } + break; + + case DXGI_FORMAT_R16G16_FLOAT: + { + outColor->red = gl::float16ToFloat32(*(reinterpret_cast(data + 4 * x + y * inputPitch) + 0)); + outColor->green = gl::float16ToFloat32(*(reinterpret_cast(data + 4 * x + y * inputPitch) + 1)); + outColor->blue = 0.0f; + outColor->alpha = 1.0f; + } + break; + + default: + ERR("ReadPixelColor not implemented for DXGI format %u.", format); + UNIMPLEMENTED(); + break; + } +} + +static inline void writePixelColor(const gl::Color &color, GLenum format, GLenum type, unsigned int x, + unsigned int y, int outputPitch, void *outData) +{ + unsigned char* byteData = reinterpret_cast(outData); + unsigned short* shortData = reinterpret_cast(outData); + + switch (format) + { + case GL_RGBA: + switch (type) + { + case GL_UNSIGNED_BYTE: + byteData[4 * x + y * outputPitch + 0] = static_cast(255 * color.red + 0.5f); + byteData[4 * x + y * outputPitch + 1] = static_cast(255 * color.green + 0.5f); + byteData[4 * x + y * outputPitch + 2] = static_cast(255 * color.blue + 0.5f); + byteData[4 * x + y * outputPitch + 3] = static_cast(255 * color.alpha + 0.5f); + break; + + default: + ERR("WritePixelColor not implemented for format GL_RGBA and type 0x%X.", type); + UNIMPLEMENTED(); + break; + } + break; + + case GL_BGRA_EXT: + switch (type) + { + case GL_UNSIGNED_BYTE: + byteData[4 * x + y * outputPitch + 0] = static_cast(255 * color.blue + 0.5f); + byteData[4 * x + y * outputPitch + 1] = static_cast(255 * color.green + 0.5f); + byteData[4 * x + y * outputPitch + 2] = static_cast(255 * color.red + 0.5f); + byteData[4 * x + y * outputPitch + 3] = static_cast(255 * color.alpha + 0.5f); + break; + + case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT: + // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section + // this type is packed as follows: + // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + // -------------------------------------------------------------------------------- + // | 4th | 3rd | 2nd | 1st component | + // -------------------------------------------------------------------------------- + // in the case of BGRA_EXT, B is the first component, G the second, and so forth. + shortData[x + y * outputPitch / sizeof(unsigned short)] = + (static_cast(15 * color.alpha + 0.5f) << 12) | + (static_cast(15 * color.red + 0.5f) << 8) | + (static_cast(15 * color.green + 0.5f) << 4) | + (static_cast(15 * color.blue + 0.5f) << 0); + break; + + case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT: + // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section + // this type is packed as follows: + // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + // -------------------------------------------------------------------------------- + // | 4th | 3rd | 2nd | 1st component | + // -------------------------------------------------------------------------------- + // in the case of BGRA_EXT, B is the first component, G the second, and so forth. + shortData[x + y * outputPitch / sizeof(unsigned short)] = + (static_cast( color.alpha + 0.5f) << 15) | + (static_cast(31 * color.red + 0.5f) << 10) | + (static_cast(31 * color.green + 0.5f) << 5) | + (static_cast(31 * color.blue + 0.5f) << 0); + break; + + default: + ERR("WritePixelColor not implemented for format GL_BGRA_EXT and type 0x%X.", type); + UNIMPLEMENTED(); + break; + } + break; + + case GL_RGB: + switch (type) + { + case GL_UNSIGNED_SHORT_5_6_5: + shortData[x + y * outputPitch / sizeof(unsigned short)] = + (static_cast(31 * color.blue + 0.5f) << 0) | + (static_cast(63 * color.green + 0.5f) << 5) | + (static_cast(31 * color.red + 0.5f) << 11); + break; + + case GL_UNSIGNED_BYTE: + byteData[3 * x + y * outputPitch + 0] = static_cast(255 * color.red + 0.5f); + byteData[3 * x + y * outputPitch + 1] = static_cast(255 * color.green + 0.5f); + byteData[3 * x + y * outputPitch + 2] = static_cast(255 * color.blue + 0.5f); + break; + + default: + ERR("WritePixelColor not implemented for format GL_RGB and type 0x%X.", type); + UNIMPLEMENTED(); + break; + } + break; + + default: + ERR("WritePixelColor not implemented for format 0x%X.", format); + UNIMPLEMENTED(); + break; + } +} + +void Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area, + GLenum format, GLenum type, GLsizei outputPitch, bool packReverseRowOrder, + GLint packAlignment, void *pixels) +{ + D3D11_TEXTURE2D_DESC textureDesc; + texture->GetDesc(&textureDesc); + + D3D11_TEXTURE2D_DESC stagingDesc; + stagingDesc.Width = area.width; + stagingDesc.Height = area.height; + stagingDesc.MipLevels = 1; + stagingDesc.ArraySize = 1; + stagingDesc.Format = textureDesc.Format; + stagingDesc.SampleDesc.Count = 1; + stagingDesc.SampleDesc.Quality = 0; + stagingDesc.Usage = D3D11_USAGE_STAGING; + stagingDesc.BindFlags = 0; + stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + stagingDesc.MiscFlags = 0; + + ID3D11Texture2D* stagingTex = NULL; + HRESULT result = mDevice->CreateTexture2D(&stagingDesc, NULL, &stagingTex); + if (FAILED(result)) + { + ERR("Failed to create staging texture for readPixels, HRESULT: 0x%X.", result); + return; + } + + ID3D11Texture2D* srcTex = NULL; + if (textureDesc.SampleDesc.Count > 1) + { + D3D11_TEXTURE2D_DESC resolveDesc; + resolveDesc.Width = textureDesc.Width; + resolveDesc.Height = textureDesc.Height; + resolveDesc.MipLevels = 1; + resolveDesc.ArraySize = 1; + resolveDesc.Format = textureDesc.Format; + resolveDesc.SampleDesc.Count = 1; + resolveDesc.SampleDesc.Quality = 0; + resolveDesc.Usage = D3D11_USAGE_DEFAULT; + resolveDesc.BindFlags = 0; + resolveDesc.CPUAccessFlags = 0; + resolveDesc.MiscFlags = 0; + + result = mDevice->CreateTexture2D(&resolveDesc, NULL, &srcTex); + if (FAILED(result)) + { + ERR("Failed to create resolve texture for readPixels, HRESULT: 0x%X.", result); + stagingTex->Release(); + return; + } + + mDeviceContext->ResolveSubresource(srcTex, 0, texture, subResource, textureDesc.Format); + subResource = 0; + } + else + { + srcTex = texture; + srcTex->AddRef(); + } + + D3D11_BOX srcBox; + srcBox.left = area.x; + srcBox.right = area.x + area.width; + srcBox.top = area.y; + srcBox.bottom = area.y + area.height; + srcBox.front = 0; + srcBox.back = 1; + + mDeviceContext->CopySubresourceRegion(stagingTex, 0, 0, 0, 0, srcTex, subResource, &srcBox); + + srcTex->Release(); + srcTex = NULL; + + D3D11_MAPPED_SUBRESOURCE mapping; + mDeviceContext->Map(stagingTex, 0, D3D11_MAP_READ, 0, &mapping); + + unsigned char *source; + int inputPitch; + if (packReverseRowOrder) + { + source = static_cast(mapping.pData) + mapping.RowPitch * (area.height - 1); + inputPitch = -static_cast(mapping.RowPitch); + } + else + { + source = static_cast(mapping.pData); + inputPitch = static_cast(mapping.RowPitch); + } + + unsigned int fastPixelSize = getFastPixelCopySize(textureDesc.Format, format, type); + if (fastPixelSize != 0) + { + unsigned char *dest = static_cast(pixels); + for (int j = 0; j < area.height; j++) + { + memcpy(dest + j * outputPitch, source + j * inputPitch, area.width * fastPixelSize); + } + } + else if (textureDesc.Format == DXGI_FORMAT_B8G8R8A8_UNORM && + format == GL_RGBA && + type == GL_UNSIGNED_BYTE) + { + // Fast path for swapping red with blue + unsigned char *dest = static_cast(pixels); + + for (int j = 0; j < area.height; j++) + { + for (int i = 0; i < area.width; i++) + { + unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch); + *(unsigned int*)(dest + 4 * i + j * outputPitch) = + (argb & 0xFF00FF00) | // Keep alpha and green + (argb & 0x00FF0000) >> 16 | // Move red to blue + (argb & 0x000000FF) << 16; // Move blue to red + } + } + } + else + { + gl::Color pixelColor; + for (int j = 0; j < area.height; j++) + { + for (int i = 0; i < area.width; i++) + { + readPixelColor(source, textureDesc.Format, i, j, inputPitch, &pixelColor); + writePixelColor(pixelColor, format, type, i, j, outputPitch, pixels); + } + } + } + + mDeviceContext->Unmap(stagingTex, 0); + + stagingTex->Release(); + stagingTex = NULL; +} + +bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget, + RenderTarget *drawRenderTarget, bool wholeBufferCopy) +{ + ASSERT(readRect.width == drawRect.width && readRect.height == drawRect.height); + + RenderTarget11 *drawRenderTarget11 = RenderTarget11::makeRenderTarget11(drawRenderTarget); + if (!drawRenderTarget) + { + ERR("Failed to retrieve the draw render target from the draw framebuffer."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + ID3D11Texture2D *drawTexture = drawRenderTarget11->getTexture(); + unsigned int drawSubresource = drawRenderTarget11->getSubresourceIndex(); + + RenderTarget11 *readRenderTarget11 = RenderTarget11::makeRenderTarget11(readRenderTarget); + if (!readRenderTarget) + { + ERR("Failed to retrieve the read render target from the read framebuffer."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + ID3D11Texture2D *readTexture = NULL; + unsigned int readSubresource = 0; + if (readRenderTarget->getSamples() > 0) + { + readTexture = resolveMultisampledTexture(readRenderTarget11->getTexture(), readRenderTarget11->getSubresourceIndex()); + readSubresource = 0; + } + else + { + readTexture = readRenderTarget11->getTexture(); + readTexture->AddRef(); + readSubresource = readRenderTarget11->getSubresourceIndex(); + } + + if (!readTexture) + { + ERR("Failed to retrieve the read render target view from the read render target."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + D3D11_BOX readBox; + readBox.left = readRect.x; + readBox.right = readRect.x + readRect.width; + readBox.top = readRect.y; + readBox.bottom = readRect.y + readRect.height; + readBox.front = 0; + readBox.back = 1; + + // D3D11 needs depth-stencil CopySubresourceRegions to have a NULL pSrcBox + // We also require complete framebuffer copies for depth-stencil blit. + D3D11_BOX *pSrcBox = wholeBufferCopy ? NULL : &readBox; + + mDeviceContext->CopySubresourceRegion(drawTexture, drawSubresource, drawRect.x, drawRect.y, 0, + readTexture, readSubresource, pSrcBox); + + SafeRelease(readTexture); + + return true; +} + +ID3D11Texture2D *Renderer11::resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource) +{ + D3D11_TEXTURE2D_DESC textureDesc; + source->GetDesc(&textureDesc); + + if (textureDesc.SampleDesc.Count > 1) + { + D3D11_TEXTURE2D_DESC resolveDesc; + resolveDesc.Width = textureDesc.Width; + resolveDesc.Height = textureDesc.Height; + resolveDesc.MipLevels = 1; + resolveDesc.ArraySize = 1; + resolveDesc.Format = textureDesc.Format; + resolveDesc.SampleDesc.Count = 1; + resolveDesc.SampleDesc.Quality = 0; + resolveDesc.Usage = textureDesc.Usage; + resolveDesc.BindFlags = textureDesc.BindFlags; + resolveDesc.CPUAccessFlags = 0; + resolveDesc.MiscFlags = 0; + + ID3D11Texture2D *resolveTexture = NULL; + HRESULT result = mDevice->CreateTexture2D(&resolveDesc, NULL, &resolveTexture); + if (FAILED(result)) + { + ERR("Failed to create a multisample resolve texture, HRESULT: 0x%X.", result); + return NULL; + } + + mDeviceContext->ResolveSubresource(resolveTexture, 0, source, subresource, textureDesc.Format); + return resolveTexture; + } + else + { + source->AddRef(); + return source; + } +} + +bool Renderer11::getLUID(LUID *adapterLuid) const +{ + adapterLuid->HighPart = 0; + adapterLuid->LowPart = 0; + + if (!mDxgiAdapter) + { + return false; + } + + DXGI_ADAPTER_DESC adapterDesc; + if (FAILED(mDxgiAdapter->GetDesc(&adapterDesc))) + { + return false; + } + + *adapterLuid = adapterDesc.AdapterLuid; + return true; +} + +} diff --git a/gfx/angle/src/libGLESv2/renderer/Renderer11.h b/gfx/angle/src/libGLESv2/renderer/Renderer11.h new file mode 100644 index 000000000000..f024855f97cc --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/Renderer11.h @@ -0,0 +1,358 @@ +// +// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Renderer11.h: Defines a back-end specific class for the D3D11 renderer. + +#ifndef LIBGLESV2_RENDERER_RENDERER11_H_ +#define LIBGLESV2_RENDERER_RENDERER11_H_ + +#include "common/angleutils.h" +#include "libGLESv2/angletypes.h" +#include "libGLESv2/mathutil.h" + +#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/renderer/RenderStateCache.h" +#include "libGLESv2/renderer/InputLayoutCache.h" +#include "libGLESv2/renderer/RenderTarget.h" + +namespace gl +{ +class Renderbuffer; +} + +namespace rx +{ + +class VertexDataManager; +class IndexDataManager; +class StreamingIndexBufferInterface; + +enum +{ + MAX_VERTEX_UNIFORM_VECTORS_D3D11 = 1024, + MAX_FRAGMENT_UNIFORM_VECTORS_D3D11 = 1024 +}; + +class Renderer11 : public Renderer +{ + public: + Renderer11(egl::Display *display, HDC hDc); + virtual ~Renderer11(); + + static Renderer11 *makeRenderer11(Renderer *renderer); + + virtual EGLint initialize(); + virtual bool resetDevice(); + + virtual int generateConfigs(ConfigDesc **configDescList); + virtual void deleteConfigs(ConfigDesc *configDescList); + + virtual void sync(bool block); + + virtual SwapChain *createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat); + + virtual void setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler); + virtual void setTexture(gl::SamplerType type, int index, gl::Texture *texture); + + virtual void setRasterizerState(const gl::RasterizerState &rasterState); + virtual void setBlendState(const gl::BlendState &blendState, const gl::Color &blendColor, + unsigned int sampleMask); + virtual void setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, + int stencilBackRef, bool frontFaceCCW); + + virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled); + virtual bool setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, + bool ignoreViewport); + + virtual bool applyPrimitiveType(GLenum mode, GLsizei count); + virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer); + virtual void applyShaders(gl::ProgramBinary *programBinary); + virtual void applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray); + virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances); + virtual GLenum applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo); + + virtual void drawArrays(GLenum mode, GLsizei count, GLsizei instances); + virtual void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances); + + virtual void clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer); + + virtual void markAllStateDirty(); + + // lost device + void notifyDeviceLost(); + virtual bool isDeviceLost(); + virtual bool testDeviceLost(bool notify); + virtual bool testDeviceResettable(); + + // Renderer capabilities + virtual DWORD getAdapterVendor() const; + virtual std::string getRendererDescription() const; + virtual GUID getAdapterIdentifier() const; + + virtual bool getBGRATextureSupport() const; + virtual bool getDXT1TextureSupport(); + virtual bool getDXT3TextureSupport(); + virtual bool getDXT5TextureSupport(); + virtual bool getEventQuerySupport(); + virtual bool getFloat32TextureSupport(bool *filtering, bool *renderable); + virtual bool getFloat16TextureSupport(bool *filtering, bool *renderable); + virtual bool getLuminanceTextureSupport(); + virtual bool getLuminanceAlphaTextureSupport(); + virtual unsigned int getMaxVertexTextureImageUnits() const; + virtual unsigned int getMaxCombinedTextureImageUnits() const; + virtual unsigned int getReservedVertexUniformVectors() const; + virtual unsigned int getReservedFragmentUniformVectors() const; + virtual unsigned int getMaxVertexUniformVectors() const; + virtual unsigned int getMaxFragmentUniformVectors() const; + virtual unsigned int getMaxVaryingVectors() const; + virtual bool getNonPower2TextureSupport() const; + virtual bool getDepthTextureSupport() const; + virtual bool getOcclusionQuerySupport() const; + virtual bool getInstancingSupport() const; + virtual bool getTextureFilterAnisotropySupport() const; + virtual float getTextureMaxAnisotropy() const; + virtual bool getShareHandleSupport() const; + virtual bool getDerivativeInstructionSupport() const; + virtual bool getPostSubBufferSupport() const; + + virtual int getMajorShaderModel() const; + virtual float getMaxPointSize() const; + virtual int getMaxViewportDimension() const; + virtual int getMaxTextureWidth() const; + virtual int getMaxTextureHeight() const; + virtual bool get32BitIndexSupport() const; + virtual int getMinSwapInterval() const; + virtual int getMaxSwapInterval() const; + + virtual GLsizei getMaxSupportedSamples() const; + int getNearestSupportedSamples(DXGI_FORMAT format, unsigned int requested) const; + + virtual unsigned int getMaxRenderTargets() const; + + // Pixel operations + virtual bool copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source); + virtual bool copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source); + + virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level); + virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level); + + bool copyTexture(ID3D11ShaderResourceView *source, const gl::Rectangle &sourceArea, unsigned int sourceWidth, unsigned int sourceHeight, + ID3D11RenderTargetView *dest, const gl::Rectangle &destArea, unsigned int destWidth, unsigned int destHeight, GLenum destFormat); + + virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, + bool blitRenderTarget, bool blitDepthStencil); + virtual void readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, + GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels); + + // RenderTarget creation + virtual RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth); + virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth); + + // Shader operations + virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type); + virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type); + + // Image operations + virtual Image *createImage(); + virtual void generateMipmap(Image *dest, Image *source); + virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain); + virtual TextureStorage *createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height); + virtual TextureStorage *createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size); + + // Buffer creation + virtual VertexBuffer *createVertexBuffer(); + virtual IndexBuffer *createIndexBuffer(); + virtual BufferStorage *createBufferStorage(); + + // Query and Fence creation + virtual QueryImpl *createQuery(GLenum type); + virtual FenceImpl *createFence(); + + // D3D11-renderer specific methods + ID3D11Device *getDevice() { return mDevice; } + ID3D11DeviceContext *getDeviceContext() { return mDeviceContext; }; + IDXGIFactory *getDxgiFactory() { return mDxgiFactory; }; + + bool getRenderTargetResource(gl::Renderbuffer *colorbuffer, unsigned int *subresourceIndex, ID3D11Texture2D **resource); + void unapplyRenderTargets(); + void setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView); + + virtual bool getLUID(LUID *adapterLuid) const; + + private: + DISALLOW_COPY_AND_ASSIGN(Renderer11); + + void drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer); + void drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances); + + void readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area, + GLenum format, GLenum type, GLsizei outputPitch, bool packReverseRowOrder, + GLint packAlignment, void *pixels); + + void maskedClear(const gl::ClearParameters &clearParams, bool usingExtendedDrawBuffers); + rx::Range getViewportBounds() const; + + bool blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget, + RenderTarget *drawRenderTarget, bool wholeBufferCopy); + ID3D11Texture2D *resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource); + + HMODULE mD3d11Module; + HMODULE mDxgiModule; + HDC mDc; + + bool mDeviceLost; + + void initializeDevice(); + void releaseDeviceResources(); + int getMinorShaderModel() const; + void release(); + + RenderStateCache mStateCache; + + // Support flags + bool mFloat16TextureSupport; + bool mFloat16FilterSupport; + bool mFloat16RenderSupport; + + bool mFloat32TextureSupport; + bool mFloat32FilterSupport; + bool mFloat32RenderSupport; + + bool mDXT1TextureSupport; + bool mDXT3TextureSupport; + bool mDXT5TextureSupport; + + bool mDepthTextureSupport; + + // Multisample format support + struct MultisampleSupportInfo + { + unsigned int qualityLevels[D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT]; + }; + + typedef std::unordered_map MultisampleSupportMap; + MultisampleSupportMap mMultisampleSupportMap; + + unsigned int mMaxSupportedSamples; + + // current render target states + unsigned int mAppliedRenderTargetSerials[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS]; + unsigned int mAppliedDepthbufferSerial; + unsigned int mAppliedStencilbufferSerial; + bool mDepthStencilInitialized; + bool mRenderTargetDescInitialized; + rx::RenderTarget::Desc mRenderTargetDesc; + unsigned int mCurDepthSize; + unsigned int mCurStencilSize; + + // Currently applied sampler states + bool mForceSetVertexSamplerStates[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; + gl::SamplerState mCurVertexSamplerStates[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; + + bool mForceSetPixelSamplerStates[gl::MAX_TEXTURE_IMAGE_UNITS]; + gl::SamplerState mCurPixelSamplerStates[gl::MAX_TEXTURE_IMAGE_UNITS]; + + // Currently applied textures + unsigned int mCurVertexTextureSerials[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; + unsigned int mCurPixelTextureSerials[gl::MAX_TEXTURE_IMAGE_UNITS]; + + // Currently applied blend state + bool mForceSetBlendState; + gl::BlendState mCurBlendState; + gl::Color mCurBlendColor; + unsigned int mCurSampleMask; + + // Currently applied rasterizer state + bool mForceSetRasterState; + gl::RasterizerState mCurRasterState; + + // Currently applied depth stencil state + bool mForceSetDepthStencilState; + gl::DepthStencilState mCurDepthStencilState; + int mCurStencilRef; + int mCurStencilBackRef; + + // Currently applied scissor rectangle + bool mForceSetScissor; + bool mScissorEnabled; + gl::Rectangle mCurScissor; + + // Currently applied viewport + bool mForceSetViewport; + gl::Rectangle mCurViewport; + float mCurNear; + float mCurFar; + + // Currently applied primitive topology + D3D11_PRIMITIVE_TOPOLOGY mCurrentPrimitiveTopology; + + unsigned int mAppliedIBSerial; + unsigned int mAppliedStorageIBSerial; + unsigned int mAppliedIBOffset; + + unsigned int mAppliedProgramBinarySerial; + bool mIsGeometryShaderActive; + + dx_VertexConstants mVertexConstants; + dx_VertexConstants mAppliedVertexConstants; + ID3D11Buffer *mDriverConstantBufferVS; + ID3D11Buffer *mCurrentVertexConstantBuffer; + + dx_PixelConstants mPixelConstants; + dx_PixelConstants mAppliedPixelConstants; + ID3D11Buffer *mDriverConstantBufferPS; + ID3D11Buffer *mCurrentPixelConstantBuffer; + + ID3D11Buffer *mCurrentGeometryConstantBuffer; + + // Vertex, index and input layouts + VertexDataManager *mVertexDataManager; + IndexDataManager *mIndexDataManager; + InputLayoutCache mInputLayoutCache; + + StreamingIndexBufferInterface *mLineLoopIB; + StreamingIndexBufferInterface *mTriangleFanIB; + + // Texture copy resources + bool mCopyResourcesInitialized; + ID3D11Buffer *mCopyVB; + ID3D11SamplerState *mCopySampler; + ID3D11InputLayout *mCopyIL; + ID3D11VertexShader *mCopyVS; + ID3D11PixelShader *mCopyRGBAPS; + ID3D11PixelShader *mCopyRGBPS; + ID3D11PixelShader *mCopyLumPS; + ID3D11PixelShader *mCopyLumAlphaPS; + + // Masked clear resources + bool mClearResourcesInitialized; + ID3D11Buffer *mClearVB; + ID3D11InputLayout *mClearIL; + ID3D11VertexShader *mClearVS; + ID3D11PixelShader *mClearSinglePS; + ID3D11PixelShader *mClearMultiplePS; + ID3D11RasterizerState *mClearScissorRS; + ID3D11RasterizerState *mClearNoScissorRS; + + // Sync query + ID3D11Query *mSyncQuery; + + ID3D11Device *mDevice; + D3D_FEATURE_LEVEL mFeatureLevel; + ID3D11DeviceContext *mDeviceContext; + IDXGIAdapter *mDxgiAdapter; + DXGI_ADAPTER_DESC mAdapterDescription; + char mDescription[128]; + IDXGIFactory *mDxgiFactory; + + // Cached device caps + bool mBGRATextureSupport; +}; + +} +#endif // LIBGLESV2_RENDERER_RENDERER11_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/Renderer9.cpp b/gfx/angle/src/libGLESv2/renderer/Renderer9.cpp new file mode 100644 index 000000000000..a2bf303554e2 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/Renderer9.cpp @@ -0,0 +1,3222 @@ +#include "precompiled.h" +// +// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Renderer9.cpp: Implements a back-end specific class for the D3D9 renderer. + +#include "libGLESv2/main.h" +#include "libGLESv2/Buffer.h" +#include "libGLESv2/Texture.h" +#include "libGLESv2/Framebuffer.h" +#include "libGLESv2/Renderbuffer.h" +#include "libGLESv2/ProgramBinary.h" +#include "libGLESv2/renderer/IndexDataManager.h" +#include "libGLESv2/renderer/Renderer9.h" +#include "libGLESv2/renderer/renderer9_utils.h" +#include "libGLESv2/renderer/ShaderExecutable9.h" +#include "libGLESv2/renderer/SwapChain9.h" +#include "libGLESv2/renderer/TextureStorage9.h" +#include "libGLESv2/renderer/Image9.h" +#include "libGLESv2/renderer/Blit.h" +#include "libGLESv2/renderer/RenderTarget9.h" +#include "libGLESv2/renderer/VertexBuffer9.h" +#include "libGLESv2/renderer/IndexBuffer9.h" +#include "libGLESv2/renderer/BufferStorage9.h" +#include "libGLESv2/renderer/Query9.h" +#include "libGLESv2/renderer/Fence9.h" + +#include "libEGL/Display.h" + +// Can also be enabled by defining FORCE_REF_RAST in the project's predefined macros +#define REF_RAST 0 + +// The "Debug This Pixel..." feature in PIX often fails when using the +// D3D9Ex interfaces. In order to get debug pixel to work on a Vista/Win 7 +// machine, define "ANGLE_ENABLE_D3D9EX=0" in your project file. +#if !defined(ANGLE_ENABLE_D3D9EX) +// Enables use of the IDirect3D9Ex interface, when available +#define ANGLE_ENABLE_D3D9EX 1 +#endif // !defined(ANGLE_ENABLE_D3D9EX) + +namespace rx +{ +static const D3DFORMAT RenderTargetFormats[] = + { + D3DFMT_A1R5G5B5, + // D3DFMT_A2R10G10B10, // The color_ramp conformance test uses ReadPixels with UNSIGNED_BYTE causing it to think that rendering skipped a colour value. + D3DFMT_A8R8G8B8, + D3DFMT_R5G6B5, + // D3DFMT_X1R5G5B5, // Has no compatible OpenGL ES renderbuffer format + D3DFMT_X8R8G8B8 + }; + +static const D3DFORMAT DepthStencilFormats[] = + { + D3DFMT_UNKNOWN, + // D3DFMT_D16_LOCKABLE, + D3DFMT_D32, + // D3DFMT_D15S1, + D3DFMT_D24S8, + D3DFMT_D24X8, + // D3DFMT_D24X4S4, + D3DFMT_D16, + // D3DFMT_D32F_LOCKABLE, + // D3DFMT_D24FS8 + }; + +enum +{ + MAX_VERTEX_CONSTANT_VECTORS_D3D9 = 256, + MAX_PIXEL_CONSTANT_VECTORS_SM2 = 32, + MAX_PIXEL_CONSTANT_VECTORS_SM3 = 224, + MAX_VARYING_VECTORS_SM2 = 8, + MAX_VARYING_VECTORS_SM3 = 10, + + MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 = 4 +}; + +Renderer9::Renderer9(egl::Display *display, HDC hDc, bool softwareDevice) : Renderer(display), mDc(hDc), mSoftwareDevice(softwareDevice) +{ + mD3d9Module = NULL; + + mD3d9 = NULL; + mD3d9Ex = NULL; + mDevice = NULL; + mDeviceEx = NULL; + mDeviceWindow = NULL; + mBlit = NULL; + + mAdapter = D3DADAPTER_DEFAULT; + + #if REF_RAST == 1 || defined(FORCE_REF_RAST) + mDeviceType = D3DDEVTYPE_REF; + #else + mDeviceType = D3DDEVTYPE_HAL; + #endif + + mDeviceLost = false; + + mMaxSupportedSamples = 0; + + mMaskedClearSavedState = NULL; + + mVertexDataManager = NULL; + mIndexDataManager = NULL; + mLineLoopIB = NULL; + + mMaxNullColorbufferLRU = 0; + for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++) + { + mNullColorbufferCache[i].lruCount = 0; + mNullColorbufferCache[i].width = 0; + mNullColorbufferCache[i].height = 0; + mNullColorbufferCache[i].buffer = NULL; + } +} + +Renderer9::~Renderer9() +{ + releaseDeviceResources(); + + if (mDevice) + { + // If the device is lost, reset it first to prevent leaving the driver in an unstable state + if (testDeviceLost(false)) + { + resetDevice(); + } + + mDevice->Release(); + mDevice = NULL; + } + + if (mDeviceEx) + { + mDeviceEx->Release(); + mDeviceEx = NULL; + } + + if (mD3d9) + { + mD3d9->Release(); + mD3d9 = NULL; + } + + if (mDeviceWindow) + { + DestroyWindow(mDeviceWindow); + mDeviceWindow = NULL; + } + + if (mD3d9Ex) + { + mD3d9Ex->Release(); + mD3d9Ex = NULL; + } + + if (mD3d9Module) + { + mD3d9Module = NULL; + } + + while (!mMultiSampleSupport.empty()) + { + delete [] mMultiSampleSupport.begin()->second; + mMultiSampleSupport.erase(mMultiSampleSupport.begin()); + } +} + +Renderer9 *Renderer9::makeRenderer9(Renderer *renderer) +{ + ASSERT(HAS_DYNAMIC_TYPE(rx::Renderer9*, renderer)); + return static_cast(renderer); +} + +EGLint Renderer9::initialize() +{ + if (!initializeCompiler()) + { + return EGL_NOT_INITIALIZED; + } + + if (mSoftwareDevice) + { + mD3d9Module = GetModuleHandle(TEXT("swiftshader_d3d9.dll")); + } + else + { + mD3d9Module = GetModuleHandle(TEXT("d3d9.dll")); + } + + if (mD3d9Module == NULL) + { + ERR("No D3D9 module found - aborting!\n"); + return EGL_NOT_INITIALIZED; + } + + typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**); + Direct3DCreate9ExFunc Direct3DCreate9ExPtr = reinterpret_cast(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex")); + + // Use Direct3D9Ex if available. Among other things, this version is less + // inclined to report a lost context, for example when the user switches + // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available. + if (ANGLE_ENABLE_D3D9EX && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex))) + { + ASSERT(mD3d9Ex); + mD3d9Ex->QueryInterface(IID_IDirect3D9, reinterpret_cast(&mD3d9)); + ASSERT(mD3d9); + } + else + { + mD3d9 = Direct3DCreate9(D3D_SDK_VERSION); + } + + if (!mD3d9) + { + ERR("Could not create D3D9 device - aborting!\n"); + return EGL_NOT_INITIALIZED; + } + + if (mDc != NULL) + { + // UNIMPLEMENTED(); // FIXME: Determine which adapter index the device context corresponds to + } + + HRESULT result; + + // Give up on getting device caps after about one second. + for (int i = 0; i < 10; ++i) + { + result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps); + if (SUCCEEDED(result)) + { + break; + } + else if (result == D3DERR_NOTAVAILABLE) + { + Sleep(100); // Give the driver some time to initialize/recover + } + else if (FAILED(result)) // D3DERR_OUTOFVIDEOMEMORY, E_OUTOFMEMORY, D3DERR_INVALIDDEVICE, or another error we can't recover from + { + ERR("failed to get device caps (0x%x)\n", result); + return EGL_NOT_INITIALIZED; + } + } + + if (mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(2, 0)) + { + ERR("Renderer does not support PS 2.0. aborting!\n"); + return EGL_NOT_INITIALIZED; + } + + // When DirectX9 is running with an older DirectX8 driver, a StretchRect from a regular texture to a render target texture is not supported. + // This is required by Texture2D::convertToRenderTarget. + if ((mDeviceCaps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES) == 0) + { + ERR("Renderer does not support stretctrect from textures!\n"); + return EGL_NOT_INITIALIZED; + } + + mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier); + + // ATI cards on XP have problems with non-power-of-two textures. + mSupportsNonPower2Textures = !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) && + !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) && + !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) && + !(getComparableOSVersion() < versionWindowsVista && mAdapterIdentifier.VendorId == VENDOR_ID_AMD); + + // Must support a minimum of 2:1 anisotropy for max anisotropy to be considered supported, per the spec + mSupportsTextureFilterAnisotropy = ((mDeviceCaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) && (mDeviceCaps.MaxAnisotropy >= 2)); + + mMinSwapInterval = 4; + mMaxSwapInterval = 0; + + if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) + { + mMinSwapInterval = std::min(mMinSwapInterval, 0); + mMaxSwapInterval = std::max(mMaxSwapInterval, 0); + } + if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE) + { + mMinSwapInterval = std::min(mMinSwapInterval, 1); + mMaxSwapInterval = std::max(mMaxSwapInterval, 1); + } + if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_TWO) + { + mMinSwapInterval = std::min(mMinSwapInterval, 2); + mMaxSwapInterval = std::max(mMaxSwapInterval, 2); + } + if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_THREE) + { + mMinSwapInterval = std::min(mMinSwapInterval, 3); + mMaxSwapInterval = std::max(mMaxSwapInterval, 3); + } + if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_FOUR) + { + mMinSwapInterval = std::min(mMinSwapInterval, 4); + mMaxSwapInterval = std::max(mMaxSwapInterval, 4); + } + + int max = 0; + for (unsigned int i = 0; i < ArraySize(RenderTargetFormats); ++i) + { + bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1]; + getMultiSampleSupport(RenderTargetFormats[i], multisampleArray); + mMultiSampleSupport[RenderTargetFormats[i]] = multisampleArray; + + for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j) + { + if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max) + { + max = j; + } + } + } + + for (unsigned int i = 0; i < ArraySize(DepthStencilFormats); ++i) + { + if (DepthStencilFormats[i] == D3DFMT_UNKNOWN) + continue; + + bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1]; + getMultiSampleSupport(DepthStencilFormats[i], multisampleArray); + mMultiSampleSupport[DepthStencilFormats[i]] = multisampleArray; + + for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j) + { + if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max) + { + max = j; + } + } + } + + mMaxSupportedSamples = max; + + static const TCHAR windowName[] = TEXT("AngleHiddenWindow"); + static const TCHAR className[] = TEXT("STATIC"); + + mDeviceWindow = CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL); + + D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters(); + DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES; + + result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice); + if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DEVICELOST) + { + return EGL_BAD_ALLOC; + } + + if (FAILED(result)) + { + result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_NOTAVAILABLE || result == D3DERR_DEVICELOST); + return EGL_BAD_ALLOC; + } + } + + if (mD3d9Ex) + { + result = mDevice->QueryInterface(IID_IDirect3DDevice9Ex, (void**) &mDeviceEx); + ASSERT(SUCCEEDED(result)); + } + + mVertexShaderCache.initialize(mDevice); + mPixelShaderCache.initialize(mDevice); + + // Check occlusion query support + IDirect3DQuery9 *occlusionQuery = NULL; + if (SUCCEEDED(mDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery)) && occlusionQuery) + { + occlusionQuery->Release(); + mOcclusionQuerySupport = true; + } + else + { + mOcclusionQuerySupport = false; + } + + // Check event query support + IDirect3DQuery9 *eventQuery = NULL; + if (SUCCEEDED(mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery)) && eventQuery) + { + eventQuery->Release(); + mEventQuerySupport = true; + } + else + { + mEventQuerySupport = false; + } + + D3DDISPLAYMODE currentDisplayMode; + mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); + + // Check vertex texture support + // Only Direct3D 10 ready devices support all the necessary vertex texture formats. + // We test this using D3D9 by checking support for the R16F format. + mVertexTextureSupport = mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0) && + SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, + D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F)); + + // Check depth texture support + // we use INTZ for depth textures in Direct3D9 + // we also want NULL texture support to ensure the we can make depth-only FBOs + // see http://aras-p.info/texts/D3D9GPUHacks.html + mDepthTextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, + D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, D3DFMT_INTZ)) && + SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, + D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL)); + + // Check 32 bit floating point texture support + mFloat32FilterSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER, + D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) && + SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER, + D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F)); + + mFloat32RenderSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, + D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) && + SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, + D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F)); + + if (!mFloat32FilterSupport && !mFloat32RenderSupport) + { + mFloat32TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, + D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) && + SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, + D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F)); + } + else + { + mFloat32TextureSupport = true; + } + + // Check 16 bit floating point texture support + mFloat16FilterSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER, + D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) && + SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER, + D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F)); + + mFloat16RenderSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, + D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) && + SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, + D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F)); + + if (!mFloat16FilterSupport && !mFloat16RenderSupport) + { + mFloat16TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, + D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) && + SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, + D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F)); + } + else + { + mFloat16TextureSupport = true; + } + + // Check DXT texture support + mDXT1TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT1)); + mDXT3TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT3)); + mDXT5TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT5)); + + // Check luminance[alpha] texture support + mLuminanceTextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_L8)); + mLuminanceAlphaTextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_A8L8)); + + initializeDevice(); + + return EGL_SUCCESS; +} + +// do any one-time device initialization +// NOTE: this is also needed after a device lost/reset +// to reset the scene status and ensure the default states are reset. +void Renderer9::initializeDevice() +{ + // Permanent non-default states + mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE); + mDevice->SetRenderState(D3DRS_LASTPIXEL, FALSE); + + if (mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0)) + { + mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, (DWORD&)mDeviceCaps.MaxPointSize); + } + else + { + mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, 0x3F800000); // 1.0f + } + + markAllStateDirty(); + + mSceneStarted = false; + + ASSERT(!mBlit && !mVertexDataManager && !mIndexDataManager); + mBlit = new Blit(this); + mVertexDataManager = new rx::VertexDataManager(this); + mIndexDataManager = new rx::IndexDataManager(this); +} + +D3DPRESENT_PARAMETERS Renderer9::getDefaultPresentParameters() +{ + D3DPRESENT_PARAMETERS presentParameters = {0}; + + // The default swap chain is never actually used. Surface will create a new swap chain with the proper parameters. + presentParameters.AutoDepthStencilFormat = D3DFMT_UNKNOWN; + presentParameters.BackBufferCount = 1; + presentParameters.BackBufferFormat = D3DFMT_UNKNOWN; + presentParameters.BackBufferWidth = 1; + presentParameters.BackBufferHeight = 1; + presentParameters.EnableAutoDepthStencil = FALSE; + presentParameters.Flags = 0; + presentParameters.hDeviceWindow = mDeviceWindow; + presentParameters.MultiSampleQuality = 0; + presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE; + presentParameters.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; + presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD; + presentParameters.Windowed = TRUE; + + return presentParameters; +} + +int Renderer9::generateConfigs(ConfigDesc **configDescList) +{ + D3DDISPLAYMODE currentDisplayMode; + mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); + + unsigned int numRenderFormats = ArraySize(RenderTargetFormats); + unsigned int numDepthFormats = ArraySize(DepthStencilFormats); + (*configDescList) = new ConfigDesc[numRenderFormats * numDepthFormats]; + int numConfigs = 0; + + for (unsigned int formatIndex = 0; formatIndex < numRenderFormats; formatIndex++) + { + D3DFORMAT renderTargetFormat = RenderTargetFormats[formatIndex]; + + HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, renderTargetFormat); + + if (SUCCEEDED(result)) + { + for (unsigned int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++) + { + D3DFORMAT depthStencilFormat = DepthStencilFormats[depthStencilIndex]; + HRESULT result = D3D_OK; + + if(depthStencilFormat != D3DFMT_UNKNOWN) + { + result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, depthStencilFormat); + } + + if (SUCCEEDED(result)) + { + if(depthStencilFormat != D3DFMT_UNKNOWN) + { + result = mD3d9->CheckDepthStencilMatch(mAdapter, mDeviceType, currentDisplayMode.Format, renderTargetFormat, depthStencilFormat); + } + + if (SUCCEEDED(result)) + { + ConfigDesc newConfig; + newConfig.renderTargetFormat = d3d9_gl::ConvertBackBufferFormat(renderTargetFormat); + newConfig.depthStencilFormat = d3d9_gl::ConvertDepthStencilFormat(depthStencilFormat); + newConfig.multiSample = 0; // FIXME: enumerate multi-sampling + newConfig.fastConfig = (currentDisplayMode.Format == renderTargetFormat); + + (*configDescList)[numConfigs++] = newConfig; + } + } + } + } + } + + return numConfigs; +} + +void Renderer9::deleteConfigs(ConfigDesc *configDescList) +{ + delete [] (configDescList); +} + +void Renderer9::startScene() +{ + if (!mSceneStarted) + { + long result = mDevice->BeginScene(); + if (SUCCEEDED(result)) { + // This is defensive checking against the device being + // lost at unexpected times. + mSceneStarted = true; + } + } +} + +void Renderer9::endScene() +{ + if (mSceneStarted) + { + // EndScene can fail if the device was lost, for example due + // to a TDR during a draw call. + mDevice->EndScene(); + mSceneStarted = false; + } +} + +void Renderer9::sync(bool block) +{ + HRESULT result; + + IDirect3DQuery9* query = allocateEventQuery(); + if (!query) + { + return; + } + + result = query->Issue(D3DISSUE_END); + ASSERT(SUCCEEDED(result)); + + do + { + result = query->GetData(NULL, 0, D3DGETDATA_FLUSH); + + if(block && result == S_FALSE) + { + // Keep polling, but allow other threads to do something useful first + Sleep(0); + // explicitly check for device loss + // some drivers seem to return S_FALSE even if the device is lost + // instead of D3DERR_DEVICELOST like they should + if (testDeviceLost(false)) + { + result = D3DERR_DEVICELOST; + } + } + } + while(block && result == S_FALSE); + + freeEventQuery(query); + + if (d3d9::isDeviceLostError(result)) + { + notifyDeviceLost(); + } +} + +SwapChain *Renderer9::createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) +{ + return new rx::SwapChain9(this, window, shareHandle, backBufferFormat, depthBufferFormat); +} + +IDirect3DQuery9* Renderer9::allocateEventQuery() +{ + IDirect3DQuery9 *query = NULL; + + if (mEventQueryPool.empty()) + { + HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &query); + ASSERT(SUCCEEDED(result)); + } + else + { + query = mEventQueryPool.back(); + mEventQueryPool.pop_back(); + } + + return query; +} + +void Renderer9::freeEventQuery(IDirect3DQuery9* query) +{ + if (mEventQueryPool.size() > 1000) + { + query->Release(); + } + else + { + mEventQueryPool.push_back(query); + } +} + +IDirect3DVertexShader9 *Renderer9::createVertexShader(const DWORD *function, size_t length) +{ + return mVertexShaderCache.create(function, length); +} + +IDirect3DPixelShader9 *Renderer9::createPixelShader(const DWORD *function, size_t length) +{ + return mPixelShaderCache.create(function, length); +} + +HRESULT Renderer9::createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer) +{ + D3DPOOL Pool = getBufferPool(Usage); + return mDevice->CreateVertexBuffer(Length, Usage, 0, Pool, ppVertexBuffer, NULL); +} + +VertexBuffer *Renderer9::createVertexBuffer() +{ + return new VertexBuffer9(this); +} + +HRESULT Renderer9::createIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, IDirect3DIndexBuffer9 **ppIndexBuffer) +{ + D3DPOOL Pool = getBufferPool(Usage); + return mDevice->CreateIndexBuffer(Length, Usage, Format, Pool, ppIndexBuffer, NULL); +} + +IndexBuffer *Renderer9::createIndexBuffer() +{ + return new IndexBuffer9(this); +} + +BufferStorage *Renderer9::createBufferStorage() +{ + return new BufferStorage9(); +} + +QueryImpl *Renderer9::createQuery(GLenum type) +{ + return new Query9(this, type); +} + +FenceImpl *Renderer9::createFence() +{ + return new Fence9(this); +} + +void Renderer9::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState) +{ + bool *forceSetSamplers = (type == gl::SAMPLER_PIXEL) ? mForceSetPixelSamplerStates : mForceSetVertexSamplerStates; + gl::SamplerState *appliedSamplers = (type == gl::SAMPLER_PIXEL) ? mCurPixelSamplerStates: mCurVertexSamplerStates; + + if (forceSetSamplers[index] || memcmp(&samplerState, &appliedSamplers[index], sizeof(gl::SamplerState)) != 0) + { + int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0; + int d3dSampler = index + d3dSamplerOffset; + + mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSU, gl_d3d9::ConvertTextureWrap(samplerState.wrapS)); + mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSV, gl_d3d9::ConvertTextureWrap(samplerState.wrapT)); + + mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAGFILTER, gl_d3d9::ConvertMagFilter(samplerState.magFilter, samplerState.maxAnisotropy)); + D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter; + gl_d3d9::ConvertMinFilter(samplerState.minFilter, &d3dMinFilter, &d3dMipFilter, samplerState.maxAnisotropy); + mDevice->SetSamplerState(d3dSampler, D3DSAMP_MINFILTER, d3dMinFilter); + mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter); + mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXMIPLEVEL, samplerState.lodOffset); + if (mSupportsTextureFilterAnisotropy) + { + mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXANISOTROPY, (DWORD)samplerState.maxAnisotropy); + } + } + + forceSetSamplers[index] = false; + appliedSamplers[index] = samplerState; +} + +void Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *texture) +{ + int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0; + int d3dSampler = index + d3dSamplerOffset; + IDirect3DBaseTexture9 *d3dTexture = NULL; + unsigned int serial = 0; + bool forceSetTexture = false; + + unsigned int *appliedSerials = (type == gl::SAMPLER_PIXEL) ? mCurPixelTextureSerials : mCurVertexTextureSerials; + + if (texture) + { + TextureStorageInterface *texStorage = texture->getNativeTexture(); + if (texStorage) + { + TextureStorage9 *storage9 = TextureStorage9::makeTextureStorage9(texStorage->getStorageInstance()); + d3dTexture = storage9->getBaseTexture(); + } + // If we get NULL back from getBaseTexture here, something went wrong + // in the texture class and we're unexpectedly missing the d3d texture + ASSERT(d3dTexture != NULL); + + serial = texture->getTextureSerial(); + forceSetTexture = texture->hasDirtyImages(); + } + + if (forceSetTexture || appliedSerials[index] != serial) + { + mDevice->SetTexture(d3dSampler, d3dTexture); + } + + appliedSerials[index] = serial; +} + +void Renderer9::setRasterizerState(const gl::RasterizerState &rasterState) +{ + bool rasterStateChanged = mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0; + + if (rasterStateChanged) + { + // Set the cull mode + if (rasterState.cullFace) + { + mDevice->SetRenderState(D3DRS_CULLMODE, gl_d3d9::ConvertCullMode(rasterState.cullMode, rasterState.frontFace)); + } + else + { + mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + } + + if (rasterState.polygonOffsetFill) + { + if (mCurDepthSize > 0) + { + mDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *(DWORD*)&rasterState.polygonOffsetFactor); + + float depthBias = ldexp(rasterState.polygonOffsetUnits, -static_cast(mCurDepthSize)); + mDevice->SetRenderState(D3DRS_DEPTHBIAS, *(DWORD*)&depthBias); + } + } + else + { + mDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0); + mDevice->SetRenderState(D3DRS_DEPTHBIAS, 0); + } + + mCurRasterState = rasterState; + } + + mForceSetRasterState = false; +} + +void Renderer9::setBlendState(const gl::BlendState &blendState, const gl::Color &blendColor, unsigned int sampleMask) +{ + bool blendStateChanged = mForceSetBlendState || memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0; + bool blendColorChanged = mForceSetBlendState || memcmp(&blendColor, &mCurBlendColor, sizeof(gl::Color)) != 0; + bool sampleMaskChanged = mForceSetBlendState || sampleMask != mCurSampleMask; + + if (blendStateChanged || blendColorChanged) + { + if (blendState.blend) + { + mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + + if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA && blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA && + blendState.destBlendRGB != GL_CONSTANT_ALPHA && blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA) + { + mDevice->SetRenderState(D3DRS_BLENDFACTOR, gl_d3d9::ConvertColor(blendColor)); + } + else + { + mDevice->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(gl::unorm<8>(blendColor.alpha), + gl::unorm<8>(blendColor.alpha), + gl::unorm<8>(blendColor.alpha), + gl::unorm<8>(blendColor.alpha))); + } + + mDevice->SetRenderState(D3DRS_SRCBLEND, gl_d3d9::ConvertBlendFunc(blendState.sourceBlendRGB)); + mDevice->SetRenderState(D3DRS_DESTBLEND, gl_d3d9::ConvertBlendFunc(blendState.destBlendRGB)); + mDevice->SetRenderState(D3DRS_BLENDOP, gl_d3d9::ConvertBlendOp(blendState.blendEquationRGB)); + + if (blendState.sourceBlendRGB != blendState.sourceBlendAlpha || + blendState.destBlendRGB != blendState.destBlendAlpha || + blendState.blendEquationRGB != blendState.blendEquationAlpha) + { + mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); + + mDevice->SetRenderState(D3DRS_SRCBLENDALPHA, gl_d3d9::ConvertBlendFunc(blendState.sourceBlendAlpha)); + mDevice->SetRenderState(D3DRS_DESTBLENDALPHA, gl_d3d9::ConvertBlendFunc(blendState.destBlendAlpha)); + mDevice->SetRenderState(D3DRS_BLENDOPALPHA, gl_d3d9::ConvertBlendOp(blendState.blendEquationAlpha)); + } + else + { + mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE); + } + } + else + { + mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + } + + if (blendState.sampleAlphaToCoverage) + { + FIXME("Sample alpha to coverage is unimplemented."); + } + + // Set the color mask + bool zeroColorMaskAllowed = getAdapterVendor() != VENDOR_ID_AMD; + // Apparently some ATI cards have a bug where a draw with a zero color + // write mask can cause later draws to have incorrect results. Instead, + // set a nonzero color write mask but modify the blend state so that no + // drawing is done. + // http://code.google.com/p/angleproject/issues/detail?id=169 + + DWORD colorMask = gl_d3d9::ConvertColorMask(blendState.colorMaskRed, blendState.colorMaskGreen, + blendState.colorMaskBlue, blendState.colorMaskAlpha); + if (colorMask == 0 && !zeroColorMaskAllowed) + { + // Enable green channel, but set blending so nothing will be drawn. + mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_GREEN); + mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + + mDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO); + mDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); + mDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); + } + else + { + mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, colorMask); + } + + mDevice->SetRenderState(D3DRS_DITHERENABLE, blendState.dither ? TRUE : FALSE); + + mCurBlendState = blendState; + mCurBlendColor = blendColor; + } + + if (sampleMaskChanged) + { + // Set the multisample mask + mDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE); + mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, static_cast(sampleMask)); + + mCurSampleMask = sampleMask; + } + + mForceSetBlendState = false; +} + +void Renderer9::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, + int stencilBackRef, bool frontFaceCCW) +{ + bool depthStencilStateChanged = mForceSetDepthStencilState || + memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0; + bool stencilRefChanged = mForceSetDepthStencilState || stencilRef != mCurStencilRef || + stencilBackRef != mCurStencilBackRef; + bool frontFaceCCWChanged = mForceSetDepthStencilState || frontFaceCCW != mCurFrontFaceCCW; + + if (depthStencilStateChanged) + { + if (depthStencilState.depthTest) + { + mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); + mDevice->SetRenderState(D3DRS_ZFUNC, gl_d3d9::ConvertComparison(depthStencilState.depthFunc)); + } + else + { + mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); + } + + mCurDepthStencilState = depthStencilState; + } + + if (depthStencilStateChanged || stencilRefChanged || frontFaceCCWChanged) + { + if (depthStencilState.stencilTest && mCurStencilSize > 0) + { + mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE); + mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE); + + // FIXME: Unsupported by D3D9 + const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF; + const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK; + const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK; + if (depthStencilState.stencilWritemask != depthStencilState.stencilBackWritemask || + stencilRef != stencilBackRef || + depthStencilState.stencilMask != depthStencilState.stencilBackMask) + { + ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL."); + return gl::error(GL_INVALID_OPERATION); + } + + // get the maximum size of the stencil ref + unsigned int maxStencil = (1 << mCurStencilSize) - 1; + + mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, + depthStencilState.stencilWritemask); + mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, + gl_d3d9::ConvertComparison(depthStencilState.stencilFunc)); + + mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, + (stencilRef < (int)maxStencil) ? stencilRef : maxStencil); + mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, + depthStencilState.stencilMask); + + mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, + gl_d3d9::ConvertStencilOp(depthStencilState.stencilFail)); + mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, + gl_d3d9::ConvertStencilOp(depthStencilState.stencilPassDepthFail)); + mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, + gl_d3d9::ConvertStencilOp(depthStencilState.stencilPassDepthPass)); + + mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, + depthStencilState.stencilBackWritemask); + mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, + gl_d3d9::ConvertComparison(depthStencilState.stencilBackFunc)); + + mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, + (stencilBackRef < (int)maxStencil) ? stencilBackRef : maxStencil); + mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, + depthStencilState.stencilBackMask); + + mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, + gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackFail)); + mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, + gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackPassDepthFail)); + mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, + gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackPassDepthPass)); + } + else + { + mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); + } + + mDevice->SetRenderState(D3DRS_ZWRITEENABLE, depthStencilState.depthMask ? TRUE : FALSE); + + mCurStencilRef = stencilRef; + mCurStencilBackRef = stencilBackRef; + mCurFrontFaceCCW = frontFaceCCW; + } + + mForceSetDepthStencilState = false; +} + +void Renderer9::setScissorRectangle(const gl::Rectangle &scissor, bool enabled) +{ + bool scissorChanged = mForceSetScissor || + memcmp(&scissor, &mCurScissor, sizeof(gl::Rectangle)) != 0 || + enabled != mScissorEnabled; + + if (scissorChanged) + { + if (enabled) + { + RECT rect; + rect.left = gl::clamp(scissor.x, 0, static_cast(mRenderTargetDesc.width)); + rect.top = gl::clamp(scissor.y, 0, static_cast(mRenderTargetDesc.height)); + rect.right = gl::clamp(scissor.x + scissor.width, 0, static_cast(mRenderTargetDesc.width)); + rect.bottom = gl::clamp(scissor.y + scissor.height, 0, static_cast(mRenderTargetDesc.height)); + mDevice->SetScissorRect(&rect); + } + + mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, enabled ? TRUE : FALSE); + + mScissorEnabled = enabled; + mCurScissor = scissor; + } + + mForceSetScissor = false; +} + +bool Renderer9::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, + bool ignoreViewport) +{ + gl::Rectangle actualViewport = viewport; + float actualZNear = gl::clamp01(zNear); + float actualZFar = gl::clamp01(zFar); + if (ignoreViewport) + { + actualViewport.x = 0; + actualViewport.y = 0; + actualViewport.width = mRenderTargetDesc.width; + actualViewport.height = mRenderTargetDesc.height; + actualZNear = 0.0f; + actualZFar = 1.0f; + } + + D3DVIEWPORT9 dxViewport; + dxViewport.X = gl::clamp(actualViewport.x, 0, static_cast(mRenderTargetDesc.width)); + dxViewport.Y = gl::clamp(actualViewport.y, 0, static_cast(mRenderTargetDesc.height)); + dxViewport.Width = gl::clamp(actualViewport.width, 0, static_cast(mRenderTargetDesc.width) - static_cast(dxViewport.X)); + dxViewport.Height = gl::clamp(actualViewport.height, 0, static_cast(mRenderTargetDesc.height) - static_cast(dxViewport.Y)); + dxViewport.MinZ = actualZNear; + dxViewport.MaxZ = actualZFar; + + if (dxViewport.Width <= 0 || dxViewport.Height <= 0) + { + return false; // Nothing to render + } + + bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 || + actualZNear != mCurNear || actualZFar != mCurFar; + if (viewportChanged) + { + mDevice->SetViewport(&dxViewport); + + mCurViewport = actualViewport; + mCurNear = actualZNear; + mCurFar = actualZFar; + + dx_VertexConstants vc = {0}; + dx_PixelConstants pc = {0}; + + vc.viewAdjust[0] = (float)((actualViewport.width - (int)dxViewport.Width) + 2 * (actualViewport.x - (int)dxViewport.X) - 1) / dxViewport.Width; + vc.viewAdjust[1] = (float)((actualViewport.height - (int)dxViewport.Height) + 2 * (actualViewport.y - (int)dxViewport.Y) - 1) / dxViewport.Height; + vc.viewAdjust[2] = (float)actualViewport.width / dxViewport.Width; + vc.viewAdjust[3] = (float)actualViewport.height / dxViewport.Height; + + pc.viewCoords[0] = actualViewport.width * 0.5f; + pc.viewCoords[1] = actualViewport.height * 0.5f; + pc.viewCoords[2] = actualViewport.x + (actualViewport.width * 0.5f); + pc.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f); + + pc.depthFront[0] = (actualZFar - actualZNear) * 0.5f; + pc.depthFront[1] = (actualZNear + actualZFar) * 0.5f; + pc.depthFront[2] = !gl::IsTriangleMode(drawMode) ? 0.0f : (frontFace == GL_CCW ? 1.0f : -1.0f);; + + vc.depthRange[0] = actualZNear; + vc.depthRange[1] = actualZFar; + vc.depthRange[2] = actualZFar - actualZNear; + + pc.depthRange[0] = actualZNear; + pc.depthRange[1] = actualZFar; + pc.depthRange[2] = actualZFar - actualZNear; + + if (memcmp(&vc, &mVertexConstants, sizeof(dx_VertexConstants)) != 0) + { + mVertexConstants = vc; + mDxUniformsDirty = true; + } + + if (memcmp(&pc, &mPixelConstants, sizeof(dx_PixelConstants)) != 0) + { + mPixelConstants = pc; + mDxUniformsDirty = true; + } + } + + mForceSetViewport = false; + return true; +} + +bool Renderer9::applyPrimitiveType(GLenum mode, GLsizei count) +{ + switch (mode) + { + case GL_POINTS: + mPrimitiveType = D3DPT_POINTLIST; + mPrimitiveCount = count; + break; + case GL_LINES: + mPrimitiveType = D3DPT_LINELIST; + mPrimitiveCount = count / 2; + break; + case GL_LINE_LOOP: + mPrimitiveType = D3DPT_LINESTRIP; + mPrimitiveCount = count - 1; // D3D doesn't support line loops, so we draw the last line separately + break; + case GL_LINE_STRIP: + mPrimitiveType = D3DPT_LINESTRIP; + mPrimitiveCount = count - 1; + break; + case GL_TRIANGLES: + mPrimitiveType = D3DPT_TRIANGLELIST; + mPrimitiveCount = count / 3; + break; + case GL_TRIANGLE_STRIP: + mPrimitiveType = D3DPT_TRIANGLESTRIP; + mPrimitiveCount = count - 2; + break; + case GL_TRIANGLE_FAN: + mPrimitiveType = D3DPT_TRIANGLEFAN; + mPrimitiveCount = count - 2; + break; + default: + return gl::error(GL_INVALID_ENUM, false); + } + + return mPrimitiveCount > 0; +} + + +gl::Renderbuffer *Renderer9::getNullColorbuffer(gl::Renderbuffer *depthbuffer) +{ + if (!depthbuffer) + { + ERR("Unexpected null depthbuffer for depth-only FBO."); + return NULL; + } + + GLsizei width = depthbuffer->getWidth(); + GLsizei height = depthbuffer->getHeight(); + + // search cached nullcolorbuffers + for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++) + { + if (mNullColorbufferCache[i].buffer != NULL && + mNullColorbufferCache[i].width == width && + mNullColorbufferCache[i].height == height) + { + mNullColorbufferCache[i].lruCount = ++mMaxNullColorbufferLRU; + return mNullColorbufferCache[i].buffer; + } + } + + gl::Renderbuffer *nullbuffer = new gl::Renderbuffer(this, 0, new gl::Colorbuffer(this, width, height, GL_NONE, 0)); + + // add nullbuffer to the cache + NullColorbufferCacheEntry *oldest = &mNullColorbufferCache[0]; + for (int i = 1; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++) + { + if (mNullColorbufferCache[i].lruCount < oldest->lruCount) + { + oldest = &mNullColorbufferCache[i]; + } + } + + delete oldest->buffer; + oldest->buffer = nullbuffer; + oldest->lruCount = ++mMaxNullColorbufferLRU; + oldest->width = width; + oldest->height = height; + + return nullbuffer; +} + +bool Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer) +{ + // if there is no color attachment we must synthesize a NULL colorattachment + // to keep the D3D runtime happy. This should only be possible if depth texturing. + gl::Renderbuffer *renderbufferObject = NULL; + if (framebuffer->getColorbufferType(0) != GL_NONE) + { + renderbufferObject = framebuffer->getColorbuffer(0); + } + else + { + renderbufferObject = getNullColorbuffer(framebuffer->getDepthbuffer()); + } + if (!renderbufferObject) + { + ERR("unable to locate renderbuffer for FBO."); + return false; + } + + bool renderTargetChanged = false; + unsigned int renderTargetSerial = renderbufferObject->getSerial(); + if (renderTargetSerial != mAppliedRenderTargetSerial) + { + // Apply the render target on the device + IDirect3DSurface9 *renderTargetSurface = NULL; + + RenderTarget *renderTarget = renderbufferObject->getRenderTarget(); + if (renderTarget) + { + renderTargetSurface = RenderTarget9::makeRenderTarget9(renderTarget)->getSurface(); + } + + if (!renderTargetSurface) + { + ERR("render target pointer unexpectedly null."); + return false; // Context must be lost + } + + mDevice->SetRenderTarget(0, renderTargetSurface); + renderTargetSurface->Release(); + + mAppliedRenderTargetSerial = renderTargetSerial; + renderTargetChanged = true; + } + + gl::Renderbuffer *depthStencil = NULL; + unsigned int depthbufferSerial = 0; + unsigned int stencilbufferSerial = 0; + if (framebuffer->getDepthbufferType() != GL_NONE) + { + depthStencil = framebuffer->getDepthbuffer(); + if (!depthStencil) + { + ERR("Depth stencil pointer unexpectedly null."); + return false; + } + + depthbufferSerial = depthStencil->getSerial(); + } + else if (framebuffer->getStencilbufferType() != GL_NONE) + { + depthStencil = framebuffer->getStencilbuffer(); + if (!depthStencil) + { + ERR("Depth stencil pointer unexpectedly null."); + return false; + } + + stencilbufferSerial = depthStencil->getSerial(); + } + + if (depthbufferSerial != mAppliedDepthbufferSerial || + stencilbufferSerial != mAppliedStencilbufferSerial || + !mDepthStencilInitialized) + { + unsigned int depthSize = 0; + unsigned int stencilSize = 0; + + // Apply the depth stencil on the device + if (depthStencil) + { + IDirect3DSurface9 *depthStencilSurface = NULL; + RenderTarget *depthStencilRenderTarget = depthStencil->getDepthStencil(); + + if (depthStencilRenderTarget) + { + depthStencilSurface = RenderTarget9::makeRenderTarget9(depthStencilRenderTarget)->getSurface(); + } + + if (!depthStencilSurface) + { + ERR("depth stencil pointer unexpectedly null."); + return false; // Context must be lost + } + + mDevice->SetDepthStencilSurface(depthStencilSurface); + depthStencilSurface->Release(); + + depthSize = depthStencil->getDepthSize(); + stencilSize = depthStencil->getStencilSize(); + } + else + { + mDevice->SetDepthStencilSurface(NULL); + } + + if (!mDepthStencilInitialized || depthSize != mCurDepthSize) + { + mCurDepthSize = depthSize; + mForceSetRasterState = true; + } + + if (!mDepthStencilInitialized || stencilSize != mCurStencilSize) + { + mCurStencilSize = stencilSize; + mForceSetDepthStencilState = true; + } + + mAppliedDepthbufferSerial = depthbufferSerial; + mAppliedStencilbufferSerial = stencilbufferSerial; + mDepthStencilInitialized = true; + } + + if (renderTargetChanged || !mRenderTargetDescInitialized) + { + mForceSetScissor = true; + mForceSetViewport = true; + + mRenderTargetDesc.width = renderbufferObject->getWidth(); + mRenderTargetDesc.height = renderbufferObject->getHeight(); + mRenderTargetDesc.format = renderbufferObject->getActualFormat(); + mRenderTargetDescInitialized = true; + } + + return true; +} + +GLenum Renderer9::applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances) +{ + TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS]; + GLenum err = mVertexDataManager->prepareVertexData(vertexAttributes, programBinary, first, count, attributes, instances); + if (err != GL_NO_ERROR) + { + return err; + } + + return mVertexDeclarationCache.applyDeclaration(mDevice, attributes, programBinary, instances, &mRepeatDraw); +} + +// Applies the indices and element array bindings to the Direct3D 9 device +GLenum Renderer9::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) +{ + GLenum err = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo); + + if (err == GL_NO_ERROR) + { + // Directly binding the storage buffer is not supported for d3d9 + ASSERT(indexInfo->storage == NULL); + + if (indexInfo->serial != mAppliedIBSerial) + { + IndexBuffer9* indexBuffer = IndexBuffer9::makeIndexBuffer9(indexInfo->indexBuffer); + + mDevice->SetIndices(indexBuffer->getBuffer()); + mAppliedIBSerial = indexInfo->serial; + } + } + + return err; +} + +void Renderer9::drawArrays(GLenum mode, GLsizei count, GLsizei instances) +{ + startScene(); + + if (mode == GL_LINE_LOOP) + { + drawLineLoop(count, GL_NONE, NULL, 0, NULL); + } + else if (instances > 0) + { + StaticIndexBufferInterface *countingIB = mIndexDataManager->getCountingIndices(count); + if (countingIB) + { + if (mAppliedIBSerial != countingIB->getSerial()) + { + IndexBuffer9 *indexBuffer = IndexBuffer9::makeIndexBuffer9(countingIB->getIndexBuffer()); + + mDevice->SetIndices(indexBuffer->getBuffer()); + mAppliedIBSerial = countingIB->getSerial(); + } + + for (int i = 0; i < mRepeatDraw; i++) + { + mDevice->DrawIndexedPrimitive(mPrimitiveType, 0, 0, count, 0, mPrimitiveCount); + } + } + else + { + ERR("Could not create a counting index buffer for glDrawArraysInstanced."); + return gl::error(GL_OUT_OF_MEMORY); + } + } + else // Regular case + { + mDevice->DrawPrimitive(mPrimitiveType, 0, mPrimitiveCount); + } +} + +void Renderer9::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei /*instances*/) +{ + startScene(); + + if (mode == GL_POINTS) + { + drawIndexedPoints(count, type, indices, elementArrayBuffer); + } + else if (mode == GL_LINE_LOOP) + { + drawLineLoop(count, type, indices, indexInfo.minIndex, elementArrayBuffer); + } + else + { + for (int i = 0; i < mRepeatDraw; i++) + { + GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1; + mDevice->DrawIndexedPrimitive(mPrimitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, vertexCount, indexInfo.startIndex, mPrimitiveCount); + } + } +} + +void Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer) +{ + // Get the raw indices for an indexed draw + if (type != GL_NONE && elementArrayBuffer) + { + gl::Buffer *indexBuffer = elementArrayBuffer; + BufferStorage *storage = indexBuffer->getStorage(); + intptr_t offset = reinterpret_cast(indices); + indices = static_cast(storage->getData()) + offset; + } + + unsigned int startIndex = 0; + + if (get32BitIndexSupport()) + { + if (!mLineLoopIB) + { + mLineLoopIB = new StreamingIndexBufferInterface(this); + if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT)) + { + delete mLineLoopIB; + mLineLoopIB = NULL; + + ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP."); + return gl::error(GL_OUT_OF_MEMORY); + } + } + + if (static_cast(count) + 1 > (std::numeric_limits::max() / sizeof(unsigned int))) + { + ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required."); + return gl::error(GL_OUT_OF_MEMORY); + } + + // Checked by Renderer9::applyPrimitiveType + ASSERT(count >= 0); + + const unsigned int spaceNeeded = (static_cast(count) + 1) * sizeof(unsigned int); + if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT)) + { + ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP."); + return gl::error(GL_OUT_OF_MEMORY); + } + + void* mappedMemory = NULL; + unsigned int offset = 0; + if (!mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset)) + { + ERR("Could not map index buffer for GL_LINE_LOOP."); + return gl::error(GL_OUT_OF_MEMORY); + } + + startIndex = static_cast(offset) / 4; + unsigned int *data = reinterpret_cast(mappedMemory); + + switch (type) + { + case GL_NONE: // Non-indexed draw + for (int i = 0; i < count; i++) + { + data[i] = i; + } + data[count] = 0; + break; + case GL_UNSIGNED_BYTE: + for (int i = 0; i < count; i++) + { + data[i] = static_cast(indices)[i]; + } + data[count] = static_cast(indices)[0]; + break; + case GL_UNSIGNED_SHORT: + for (int i = 0; i < count; i++) + { + data[i] = static_cast(indices)[i]; + } + data[count] = static_cast(indices)[0]; + break; + case GL_UNSIGNED_INT: + for (int i = 0; i < count; i++) + { + data[i] = static_cast(indices)[i]; + } + data[count] = static_cast(indices)[0]; + break; + default: UNREACHABLE(); + } + + if (!mLineLoopIB->unmapBuffer()) + { + ERR("Could not unmap index buffer for GL_LINE_LOOP."); + return gl::error(GL_OUT_OF_MEMORY); + } + } + else + { + if (!mLineLoopIB) + { + mLineLoopIB = new StreamingIndexBufferInterface(this); + if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT)) + { + delete mLineLoopIB; + mLineLoopIB = NULL; + + ERR("Could not create a 16-bit looping index buffer for GL_LINE_LOOP."); + return gl::error(GL_OUT_OF_MEMORY); + } + } + + // Checked by Renderer9::applyPrimitiveType + ASSERT(count >= 0); + + if (static_cast(count) + 1 > (std::numeric_limits::max() / sizeof(unsigned short))) + { + ERR("Could not create a 16-bit looping index buffer for GL_LINE_LOOP, too many indices required."); + return gl::error(GL_OUT_OF_MEMORY); + } + + const unsigned int spaceNeeded = (static_cast(count) + 1) * sizeof(unsigned short); + if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT)) + { + ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP."); + return gl::error(GL_OUT_OF_MEMORY); + } + + void* mappedMemory = NULL; + unsigned int offset; + if (mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset)) + { + ERR("Could not map index buffer for GL_LINE_LOOP."); + return gl::error(GL_OUT_OF_MEMORY); + } + + startIndex = static_cast(offset) / 2; + unsigned short *data = reinterpret_cast(mappedMemory); + + switch (type) + { + case GL_NONE: // Non-indexed draw + for (int i = 0; i < count; i++) + { + data[i] = i; + } + data[count] = 0; + break; + case GL_UNSIGNED_BYTE: + for (int i = 0; i < count; i++) + { + data[i] = static_cast(indices)[i]; + } + data[count] = static_cast(indices)[0]; + break; + case GL_UNSIGNED_SHORT: + for (int i = 0; i < count; i++) + { + data[i] = static_cast(indices)[i]; + } + data[count] = static_cast(indices)[0]; + break; + case GL_UNSIGNED_INT: + for (int i = 0; i < count; i++) + { + data[i] = static_cast(indices)[i]; + } + data[count] = static_cast(indices)[0]; + break; + default: UNREACHABLE(); + } + + if (!mLineLoopIB->unmapBuffer()) + { + ERR("Could not unmap index buffer for GL_LINE_LOOP."); + return gl::error(GL_OUT_OF_MEMORY); + } + } + + if (mAppliedIBSerial != mLineLoopIB->getSerial()) + { + IndexBuffer9 *indexBuffer = IndexBuffer9::makeIndexBuffer9(mLineLoopIB->getIndexBuffer()); + + mDevice->SetIndices(indexBuffer->getBuffer()); + mAppliedIBSerial = mLineLoopIB->getSerial(); + } + + mDevice->DrawIndexedPrimitive(D3DPT_LINESTRIP, -minIndex, minIndex, count, startIndex, count); +} + +template +static void drawPoints(IDirect3DDevice9* device, GLsizei count, const GLvoid *indices) +{ + for (int i = 0; i < count; i++) + { + unsigned int indexValue = static_cast(static_cast(indices)[i]); + device->DrawPrimitive(D3DPT_POINTLIST, indexValue, 1); + } +} + +void Renderer9::drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer) +{ + // Drawing index point lists is unsupported in d3d9, fall back to a regular DrawPrimitive call + // for each individual point. This call is not expected to happen often. + + if (elementArrayBuffer) + { + BufferStorage *storage = elementArrayBuffer->getStorage(); + intptr_t offset = reinterpret_cast(indices); + indices = static_cast(storage->getData()) + offset; + } + + switch (type) + { + case GL_UNSIGNED_BYTE: drawPoints(mDevice, count, indices); break; + case GL_UNSIGNED_SHORT: drawPoints(mDevice, count, indices); break; + case GL_UNSIGNED_INT: drawPoints(mDevice, count, indices); break; + default: UNREACHABLE(); + } +} + +void Renderer9::applyShaders(gl::ProgramBinary *programBinary) +{ + unsigned int programBinarySerial = programBinary->getSerial(); + if (programBinarySerial != mAppliedProgramBinarySerial) + { + ShaderExecutable *vertexExe = programBinary->getVertexExecutable(); + ShaderExecutable *pixelExe = programBinary->getPixelExecutable(); + + IDirect3DVertexShader9 *vertexShader = NULL; + if (vertexExe) vertexShader = ShaderExecutable9::makeShaderExecutable9(vertexExe)->getVertexShader(); + + IDirect3DPixelShader9 *pixelShader = NULL; + if (pixelExe) pixelShader = ShaderExecutable9::makeShaderExecutable9(pixelExe)->getPixelShader(); + + mDevice->SetPixelShader(pixelShader); + mDevice->SetVertexShader(vertexShader); + programBinary->dirtyAllUniforms(); + mDxUniformsDirty = true; + + mAppliedProgramBinarySerial = programBinarySerial; + } +} + +void Renderer9::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray) +{ + for (std::vector::const_iterator ub = uniformArray->begin(), ue = uniformArray->end(); ub != ue; ++ub) + { + gl::Uniform *targetUniform = *ub; + + if (targetUniform->dirty) + { + GLfloat *f = (GLfloat*)targetUniform->data; + GLint *i = (GLint*)targetUniform->data; + + switch (targetUniform->type) + { + case GL_SAMPLER_2D: + case GL_SAMPLER_CUBE: + break; + case GL_BOOL: + case GL_BOOL_VEC2: + case GL_BOOL_VEC3: + case GL_BOOL_VEC4: + applyUniformnbv(targetUniform, i); + break; + case GL_FLOAT: + case GL_FLOAT_VEC2: + case GL_FLOAT_VEC3: + case GL_FLOAT_VEC4: + case GL_FLOAT_MAT2: + case GL_FLOAT_MAT3: + case GL_FLOAT_MAT4: + applyUniformnfv(targetUniform, f); + break; + case GL_INT: + case GL_INT_VEC2: + case GL_INT_VEC3: + case GL_INT_VEC4: + applyUniformniv(targetUniform, i); + break; + default: + UNREACHABLE(); + } + + targetUniform->dirty = false; + } + } + + // Driver uniforms + if (mDxUniformsDirty) + { + mDevice->SetVertexShaderConstantF(0, (float*)&mVertexConstants, sizeof(dx_VertexConstants) / sizeof(float[4])); + mDevice->SetPixelShaderConstantF(0, (float*)&mPixelConstants, sizeof(dx_PixelConstants) / sizeof(float[4])); + mDxUniformsDirty = false; + } +} + +void Renderer9::applyUniformnfv(gl::Uniform *targetUniform, const GLfloat *v) +{ + if (targetUniform->psRegisterIndex >= 0) + { + mDevice->SetPixelShaderConstantF(targetUniform->psRegisterIndex, v, targetUniform->registerCount); + } + + if (targetUniform->vsRegisterIndex >= 0) + { + mDevice->SetVertexShaderConstantF(targetUniform->vsRegisterIndex, v, targetUniform->registerCount); + } +} + +void Renderer9::applyUniformniv(gl::Uniform *targetUniform, const GLint *v) +{ + ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9); + GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4]; + + for (unsigned int i = 0; i < targetUniform->registerCount; i++) + { + vector[i][0] = (GLfloat)v[4 * i + 0]; + vector[i][1] = (GLfloat)v[4 * i + 1]; + vector[i][2] = (GLfloat)v[4 * i + 2]; + vector[i][3] = (GLfloat)v[4 * i + 3]; + } + + applyUniformnfv(targetUniform, (GLfloat*)vector); +} + +void Renderer9::applyUniformnbv(gl::Uniform *targetUniform, const GLint *v) +{ + ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9); + GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4]; + + for (unsigned int i = 0; i < targetUniform->registerCount; i++) + { + vector[i][0] = (v[4 * i + 0] == GL_FALSE) ? 0.0f : 1.0f; + vector[i][1] = (v[4 * i + 1] == GL_FALSE) ? 0.0f : 1.0f; + vector[i][2] = (v[4 * i + 2] == GL_FALSE) ? 0.0f : 1.0f; + vector[i][3] = (v[4 * i + 3] == GL_FALSE) ? 0.0f : 1.0f; + } + + applyUniformnfv(targetUniform, (GLfloat*)vector); +} + +void Renderer9::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) +{ + D3DCOLOR color = D3DCOLOR_ARGB(gl::unorm<8>(clearParams.colorClearValue.alpha), + gl::unorm<8>(clearParams.colorClearValue.red), + gl::unorm<8>(clearParams.colorClearValue.green), + gl::unorm<8>(clearParams.colorClearValue.blue)); + float depth = gl::clamp01(clearParams.depthClearValue); + int stencil = clearParams.stencilClearValue & 0x000000FF; + + unsigned int stencilUnmasked = 0x0; + if ((clearParams.mask & GL_STENCIL_BUFFER_BIT) && frameBuffer->hasStencil()) + { + unsigned int stencilSize = gl::GetStencilSize(frameBuffer->getStencilbuffer()->getActualFormat()); + stencilUnmasked = (0x1 << stencilSize) - 1; + } + + bool alphaUnmasked = (gl::GetAlphaSize(mRenderTargetDesc.format) == 0) || clearParams.colorMaskAlpha; + + const bool needMaskedStencilClear = (clearParams.mask & GL_STENCIL_BUFFER_BIT) && + (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked; + const bool needMaskedColorClear = (clearParams.mask & GL_COLOR_BUFFER_BIT) && + !(clearParams.colorMaskRed && clearParams.colorMaskGreen && + clearParams.colorMaskBlue && alphaUnmasked); + + if (needMaskedColorClear || needMaskedStencilClear) + { + // State which is altered in all paths from this point to the clear call is saved. + // State which is altered in only some paths will be flagged dirty in the case that + // that path is taken. + HRESULT hr; + if (mMaskedClearSavedState == NULL) + { + hr = mDevice->BeginStateBlock(); + ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); + + mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); + mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS); + mDevice->SetRenderState(D3DRS_ZENABLE, FALSE); + mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); + mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); + mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); + mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0); + mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); + mDevice->SetPixelShader(NULL); + mDevice->SetVertexShader(NULL); + mDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE); + mDevice->SetStreamSource(0, NULL, 0, 0); + mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); + mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR); + mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR); + mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color); + mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF); + + for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + mDevice->SetStreamSourceFreq(i, 1); + } + + hr = mDevice->EndStateBlock(&mMaskedClearSavedState); + ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); + } + + ASSERT(mMaskedClearSavedState != NULL); + + if (mMaskedClearSavedState != NULL) + { + hr = mMaskedClearSavedState->Capture(); + ASSERT(SUCCEEDED(hr)); + } + + mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); + mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS); + mDevice->SetRenderState(D3DRS_ZENABLE, FALSE); + mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); + mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); + mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); + + if (clearParams.mask & GL_COLOR_BUFFER_BIT) + { + mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, + gl_d3d9::ConvertColorMask(clearParams.colorMaskRed, + clearParams.colorMaskGreen, + clearParams.colorMaskBlue, + clearParams.colorMaskAlpha)); + } + else + { + mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0); + } + + if (stencilUnmasked != 0x0 && (clearParams.mask & GL_STENCIL_BUFFER_BIT)) + { + mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE); + mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE); + mDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS); + mDevice->SetRenderState(D3DRS_STENCILREF, stencil); + mDevice->SetRenderState(D3DRS_STENCILWRITEMASK, clearParams.stencilWriteMask); + mDevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE); + mDevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE); + mDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE); + } + else + { + mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); + } + + mDevice->SetPixelShader(NULL); + mDevice->SetVertexShader(NULL); + mDevice->SetFVF(D3DFVF_XYZRHW); + mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); + mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR); + mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR); + mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color); + mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF); + + for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + mDevice->SetStreamSourceFreq(i, 1); + } + + float quad[4][4]; // A quadrilateral covering the target, aligned to match the edges + quad[0][0] = -0.5f; + quad[0][1] = mRenderTargetDesc.height - 0.5f; + quad[0][2] = 0.0f; + quad[0][3] = 1.0f; + + quad[1][0] = mRenderTargetDesc.width - 0.5f; + quad[1][1] = mRenderTargetDesc.height - 0.5f; + quad[1][2] = 0.0f; + quad[1][3] = 1.0f; + + quad[2][0] = -0.5f; + quad[2][1] = -0.5f; + quad[2][2] = 0.0f; + quad[2][3] = 1.0f; + + quad[3][0] = mRenderTargetDesc.width - 0.5f; + quad[3][1] = -0.5f; + quad[3][2] = 0.0f; + quad[3][3] = 1.0f; + + startScene(); + mDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float[4])); + + if (clearParams.mask & GL_DEPTH_BUFFER_BIT) + { + mDevice->SetRenderState(D3DRS_ZENABLE, TRUE); + mDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE); + mDevice->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil); + } + + if (mMaskedClearSavedState != NULL) + { + mMaskedClearSavedState->Apply(); + } + } + else if (clearParams.mask) + { + DWORD dxClearFlags = 0; + if (clearParams.mask & GL_COLOR_BUFFER_BIT) + { + dxClearFlags |= D3DCLEAR_TARGET; + } + if (clearParams.mask & GL_DEPTH_BUFFER_BIT) + { + dxClearFlags |= D3DCLEAR_ZBUFFER; + } + if (clearParams.mask & GL_STENCIL_BUFFER_BIT) + { + dxClearFlags |= D3DCLEAR_STENCIL; + } + + mDevice->Clear(0, NULL, dxClearFlags, color, depth, stencil); + } +} + +void Renderer9::markAllStateDirty() +{ + mAppliedRenderTargetSerial = 0; + mAppliedDepthbufferSerial = 0; + mAppliedStencilbufferSerial = 0; + mDepthStencilInitialized = false; + mRenderTargetDescInitialized = false; + + mForceSetDepthStencilState = true; + mForceSetRasterState = true; + mForceSetScissor = true; + mForceSetViewport = true; + mForceSetBlendState = true; + + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; i++) + { + mForceSetVertexSamplerStates[i] = true; + mCurVertexTextureSerials[i] = 0; + } + for (unsigned int i = 0; i < gl::MAX_TEXTURE_IMAGE_UNITS; i++) + { + mForceSetPixelSamplerStates[i] = true; + mCurPixelTextureSerials[i] = 0; + } + + mAppliedIBSerial = 0; + mAppliedProgramBinarySerial = 0; + mDxUniformsDirty = true; + + mVertexDeclarationCache.markStateDirty(); +} + +void Renderer9::releaseDeviceResources() +{ + while (!mEventQueryPool.empty()) + { + mEventQueryPool.back()->Release(); + mEventQueryPool.pop_back(); + } + + if (mMaskedClearSavedState) + { + mMaskedClearSavedState->Release(); + mMaskedClearSavedState = NULL; + } + + mVertexShaderCache.clear(); + mPixelShaderCache.clear(); + + delete mBlit; + mBlit = NULL; + + delete mVertexDataManager; + mVertexDataManager = NULL; + + delete mIndexDataManager; + mIndexDataManager = NULL; + + delete mLineLoopIB; + mLineLoopIB = NULL; + + for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++) + { + delete mNullColorbufferCache[i].buffer; + mNullColorbufferCache[i].buffer = NULL; + } + +} + + +void Renderer9::notifyDeviceLost() +{ + mDeviceLost = true; + mDisplay->notifyDeviceLost(); +} + +bool Renderer9::isDeviceLost() +{ + return mDeviceLost; +} + +// set notify to true to broadcast a message to all contexts of the device loss +bool Renderer9::testDeviceLost(bool notify) +{ + HRESULT status = S_OK; + + if (mDeviceEx) + { + status = mDeviceEx->CheckDeviceState(NULL); + } + else if (mDevice) + { + status = mDevice->TestCooperativeLevel(); + } + else + { + // No device yet, so no reset required + } + + bool isLost = FAILED(status) || d3d9::isDeviceLostError(status); + + if (isLost) + { + // ensure we note the device loss -- + // we'll probably get this done again by notifyDeviceLost + // but best to remember it! + // Note that we don't want to clear the device loss status here + // -- this needs to be done by resetDevice + mDeviceLost = true; + if (notify) + { + notifyDeviceLost(); + } + } + + return isLost; +} + +bool Renderer9::testDeviceResettable() +{ + HRESULT status = D3D_OK; + + if (mDeviceEx) + { + status = mDeviceEx->CheckDeviceState(NULL); + } + else if (mDevice) + { + status = mDevice->TestCooperativeLevel(); + } + + // On D3D9Ex, DEVICELOST represents a hung device that needs to be restarted + // DEVICEREMOVED indicates the device has been stopped and must be recreated + switch (status) + { + case D3DERR_DEVICENOTRESET: + case D3DERR_DEVICEHUNG: + return true; + case D3DERR_DEVICELOST: + return (mDeviceEx != NULL); + case D3DERR_DEVICEREMOVED: + UNIMPLEMENTED(); + return false; + default: + return false; + } +} + +bool Renderer9::resetDevice() +{ + releaseDeviceResources(); + + D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters(); + + HRESULT result = D3D_OK; + bool lost = testDeviceLost(false); + int attempts = 3; + + while (lost && attempts > 0) + { + if (mDeviceEx) + { + Sleep(500); // Give the graphics driver some CPU time + result = mDeviceEx->ResetEx(&presentParameters, NULL); + } + else + { + result = mDevice->TestCooperativeLevel(); + while (result == D3DERR_DEVICELOST) + { + Sleep(100); // Give the graphics driver some CPU time + result = mDevice->TestCooperativeLevel(); + } + + if (result == D3DERR_DEVICENOTRESET) + { + result = mDevice->Reset(&presentParameters); + } + } + + lost = testDeviceLost(false); + attempts --; + } + + if (FAILED(result)) + { + ERR("Reset/ResetEx failed multiple times: 0x%08X", result); + return false; + } + + // reset device defaults + initializeDevice(); + mDeviceLost = false; + + return true; +} + +DWORD Renderer9::getAdapterVendor() const +{ + return mAdapterIdentifier.VendorId; +} + +std::string Renderer9::getRendererDescription() const +{ + std::ostringstream rendererString; + + rendererString << mAdapterIdentifier.Description; + if (getShareHandleSupport()) + { + rendererString << " Direct3D9Ex"; + } + else + { + rendererString << " Direct3D9"; + } + + rendererString << " vs_" << D3DSHADER_VERSION_MAJOR(mDeviceCaps.VertexShaderVersion) << "_" << D3DSHADER_VERSION_MINOR(mDeviceCaps.VertexShaderVersion); + rendererString << " ps_" << D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion) << "_" << D3DSHADER_VERSION_MINOR(mDeviceCaps.PixelShaderVersion); + + return rendererString.str(); +} + +GUID Renderer9::getAdapterIdentifier() const +{ + return mAdapterIdentifier.DeviceIdentifier; +} + +void Renderer9::getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray) +{ + for (int multiSampleIndex = 0; multiSampleIndex <= D3DMULTISAMPLE_16_SAMPLES; multiSampleIndex++) + { + HRESULT result = mD3d9->CheckDeviceMultiSampleType(mAdapter, mDeviceType, format, + TRUE, (D3DMULTISAMPLE_TYPE)multiSampleIndex, NULL); + + multiSampleArray[multiSampleIndex] = SUCCEEDED(result); + } +} + +bool Renderer9::getBGRATextureSupport() const +{ + // DirectX 9 always supports BGRA + return true; +} + +bool Renderer9::getDXT1TextureSupport() +{ + return mDXT1TextureSupport; +} + +bool Renderer9::getDXT3TextureSupport() +{ + return mDXT3TextureSupport; +} + +bool Renderer9::getDXT5TextureSupport() +{ + return mDXT5TextureSupport; +} + +bool Renderer9::getDepthTextureSupport() const +{ + return mDepthTextureSupport; +} + +bool Renderer9::getFloat32TextureSupport(bool *filtering, bool *renderable) +{ + *filtering = mFloat32FilterSupport; + *renderable = mFloat32RenderSupport; + return mFloat32TextureSupport; +} + +bool Renderer9::getFloat16TextureSupport(bool *filtering, bool *renderable) +{ + *filtering = mFloat16FilterSupport; + *renderable = mFloat16RenderSupport; + return mFloat16TextureSupport; +} + +bool Renderer9::getLuminanceTextureSupport() +{ + return mLuminanceTextureSupport; +} + +bool Renderer9::getLuminanceAlphaTextureSupport() +{ + return mLuminanceAlphaTextureSupport; +} + +bool Renderer9::getTextureFilterAnisotropySupport() const +{ + return mSupportsTextureFilterAnisotropy; +} + +float Renderer9::getTextureMaxAnisotropy() const +{ + if (mSupportsTextureFilterAnisotropy) + { + return static_cast(mDeviceCaps.MaxAnisotropy); + } + return 1.0f; +} + +bool Renderer9::getEventQuerySupport() +{ + return mEventQuerySupport; +} + +unsigned int Renderer9::getMaxVertexTextureImageUnits() const +{ + META_ASSERT(MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 <= gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS); + return mVertexTextureSupport ? MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 : 0; +} + +unsigned int Renderer9::getMaxCombinedTextureImageUnits() const +{ + return gl::MAX_TEXTURE_IMAGE_UNITS + getMaxVertexTextureImageUnits(); +} + +unsigned int Renderer9::getReservedVertexUniformVectors() const +{ + return 2; // dx_ViewAdjust and dx_DepthRange. +} + +unsigned int Renderer9::getReservedFragmentUniformVectors() const +{ + return 3; // dx_ViewCoords, dx_DepthFront and dx_DepthRange. +} + +unsigned int Renderer9::getMaxVertexUniformVectors() const +{ + return MAX_VERTEX_CONSTANT_VECTORS_D3D9 - getReservedVertexUniformVectors(); +} + +unsigned int Renderer9::getMaxFragmentUniformVectors() const +{ + const int maxPixelConstantVectors = (getMajorShaderModel() >= 3) ? MAX_PIXEL_CONSTANT_VECTORS_SM3 : MAX_PIXEL_CONSTANT_VECTORS_SM2; + + return maxPixelConstantVectors - getReservedFragmentUniformVectors(); +} + +unsigned int Renderer9::getMaxVaryingVectors() const +{ + return (getMajorShaderModel() >= 3) ? MAX_VARYING_VECTORS_SM3 : MAX_VARYING_VECTORS_SM2; +} + +bool Renderer9::getNonPower2TextureSupport() const +{ + return mSupportsNonPower2Textures; +} + +bool Renderer9::getOcclusionQuerySupport() const +{ + return mOcclusionQuerySupport; +} + +bool Renderer9::getInstancingSupport() const +{ + return mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0); +} + +bool Renderer9::getShareHandleSupport() const +{ + // PIX doesn't seem to support using share handles, so disable them. + return (mD3d9Ex != NULL) && !gl::perfActive(); +} + +bool Renderer9::getDerivativeInstructionSupport() const +{ + return (mDeviceCaps.PS20Caps.Caps & D3DPS20CAPS_GRADIENTINSTRUCTIONS) != 0; +} + +bool Renderer9::getPostSubBufferSupport() const +{ + return true; +} + +int Renderer9::getMajorShaderModel() const +{ + return D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion); +} + +float Renderer9::getMaxPointSize() const +{ + // Point size clamped at 1.0f for SM2 + return getMajorShaderModel() == 3 ? mDeviceCaps.MaxPointSize : 1.0f; +} + +int Renderer9::getMaxViewportDimension() const +{ + int maxTextureDimension = std::min(std::min(getMaxTextureWidth(), getMaxTextureHeight()), + (int)gl::IMPLEMENTATION_MAX_TEXTURE_SIZE); + return maxTextureDimension; +} + +int Renderer9::getMaxTextureWidth() const +{ + return (int)mDeviceCaps.MaxTextureWidth; +} + +int Renderer9::getMaxTextureHeight() const +{ + return (int)mDeviceCaps.MaxTextureHeight; +} + +bool Renderer9::get32BitIndexSupport() const +{ + return mDeviceCaps.MaxVertexIndex >= (1 << 16); +} + +DWORD Renderer9::getCapsDeclTypes() const +{ + return mDeviceCaps.DeclTypes; +} + +int Renderer9::getMinSwapInterval() const +{ + return mMinSwapInterval; +} + +int Renderer9::getMaxSwapInterval() const +{ + return mMaxSwapInterval; +} + +int Renderer9::getMaxSupportedSamples() const +{ + return mMaxSupportedSamples; +} + +int Renderer9::getNearestSupportedSamples(D3DFORMAT format, int requested) const +{ + if (requested == 0) + { + return requested; + } + + std::map::const_iterator itr = mMultiSampleSupport.find(format); + if (itr == mMultiSampleSupport.end()) + { + if (format == D3DFMT_UNKNOWN) + return 0; + return -1; + } + + for (int i = requested; i <= D3DMULTISAMPLE_16_SAMPLES; ++i) + { + if (itr->second[i] && i != D3DMULTISAMPLE_NONMASKABLE) + { + return i; + } + } + + return -1; +} + +unsigned int Renderer9::getMaxRenderTargets() const +{ + // we do not support MRT in d3d9 + return 1; +} + +D3DFORMAT Renderer9::ConvertTextureInternalFormat(GLint internalformat) +{ + switch (internalformat) + { + case GL_DEPTH_COMPONENT16: + case GL_DEPTH_COMPONENT32_OES: + case GL_DEPTH24_STENCIL8_OES: + return D3DFMT_INTZ; + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + return D3DFMT_DXT1; + case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: + return D3DFMT_DXT3; + case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: + return D3DFMT_DXT5; + case GL_RGBA32F_EXT: + case GL_RGB32F_EXT: + case GL_ALPHA32F_EXT: + case GL_LUMINANCE32F_EXT: + case GL_LUMINANCE_ALPHA32F_EXT: + return D3DFMT_A32B32G32R32F; + case GL_RGBA16F_EXT: + case GL_RGB16F_EXT: + case GL_ALPHA16F_EXT: + case GL_LUMINANCE16F_EXT: + case GL_LUMINANCE_ALPHA16F_EXT: + return D3DFMT_A16B16G16R16F; + case GL_LUMINANCE8_EXT: + if (getLuminanceTextureSupport()) + { + return D3DFMT_L8; + } + break; + case GL_LUMINANCE8_ALPHA8_EXT: + if (getLuminanceAlphaTextureSupport()) + { + return D3DFMT_A8L8; + } + break; + case GL_RGB8_OES: + case GL_RGB565: + return D3DFMT_X8R8G8B8; + } + + return D3DFMT_A8R8G8B8; +} + +bool Renderer9::copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source) +{ + bool result = false; + + if (source && dest) + { + TextureStorage9_2D *source9 = TextureStorage9_2D::makeTextureStorage9_2D(source->getStorageInstance()); + TextureStorage9_2D *dest9 = TextureStorage9_2D::makeTextureStorage9_2D(dest->getStorageInstance()); + + int levels = source9->levelCount(); + for (int i = 0; i < levels; ++i) + { + IDirect3DSurface9 *srcSurf = source9->getSurfaceLevel(i, false); + IDirect3DSurface9 *dstSurf = dest9->getSurfaceLevel(i, false); + + result = copyToRenderTarget(dstSurf, srcSurf, source9->isManaged()); + + if (srcSurf) srcSurf->Release(); + if (dstSurf) dstSurf->Release(); + + if (!result) + return false; + } + } + + return result; +} + +bool Renderer9::copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source) +{ + bool result = false; + + if (source && dest) + { + TextureStorage9_Cube *source9 = TextureStorage9_Cube::makeTextureStorage9_Cube(source->getStorageInstance()); + TextureStorage9_Cube *dest9 = TextureStorage9_Cube::makeTextureStorage9_Cube(dest->getStorageInstance()); + int levels = source9->levelCount(); + for (int f = 0; f < 6; f++) + { + for (int i = 0; i < levels; i++) + { + IDirect3DSurface9 *srcSurf = source9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, false); + IDirect3DSurface9 *dstSurf = dest9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, true); + + result = copyToRenderTarget(dstSurf, srcSurf, source9->isManaged()); + + if (srcSurf) srcSurf->Release(); + if (dstSurf) dstSurf->Release(); + + if (!result) + return false; + } + } + } + + return result; +} + +D3DPOOL Renderer9::getBufferPool(DWORD usage) const +{ + if (mD3d9Ex != NULL) + { + return D3DPOOL_DEFAULT; + } + else + { + if (!(usage & D3DUSAGE_DYNAMIC)) + { + return D3DPOOL_MANAGED; + } + } + + return D3DPOOL_DEFAULT; +} + +bool Renderer9::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level) +{ + RECT rect; + rect.left = sourceRect.x; + rect.top = sourceRect.y; + rect.right = sourceRect.x + sourceRect.width; + rect.bottom = sourceRect.y + sourceRect.height; + + return mBlit->copy(framebuffer, rect, destFormat, xoffset, yoffset, storage, level); +} + +bool Renderer9::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level) +{ + RECT rect; + rect.left = sourceRect.x; + rect.top = sourceRect.y; + rect.right = sourceRect.x + sourceRect.width; + rect.bottom = sourceRect.y + sourceRect.height; + + return mBlit->copy(framebuffer, rect, destFormat, xoffset, yoffset, storage, target, level); +} + +bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle &readRect, gl::Framebuffer *drawFramebuffer, const gl::Rectangle &drawRect, + bool blitRenderTarget, bool blitDepthStencil) +{ + endScene(); + + if (blitRenderTarget) + { + gl::Renderbuffer *readBuffer = readFramebuffer->getColorbuffer(0); + gl::Renderbuffer *drawBuffer = drawFramebuffer->getColorbuffer(0); + RenderTarget9 *readRenderTarget = NULL; + RenderTarget9 *drawRenderTarget = NULL; + IDirect3DSurface9* readSurface = NULL; + IDirect3DSurface9* drawSurface = NULL; + + if (readBuffer) + { + readRenderTarget = RenderTarget9::makeRenderTarget9(readBuffer->getRenderTarget()); + } + if (drawBuffer) + { + drawRenderTarget = RenderTarget9::makeRenderTarget9(drawBuffer->getRenderTarget()); + } + + if (readRenderTarget) + { + readSurface = readRenderTarget->getSurface(); + } + if (drawRenderTarget) + { + drawSurface = drawRenderTarget->getSurface(); + } + + if (!readSurface || !drawSurface) + { + ERR("Failed to retrieve the render target."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + RECT srcRect; + srcRect.left = readRect.x; + srcRect.right = readRect.x + readRect.width; + srcRect.top = readRect.y; + srcRect.bottom = readRect.y + readRect.height; + + RECT dstRect; + dstRect.left = drawRect.x; + dstRect.right = drawRect.x + drawRect.width; + dstRect.top = drawRect.y; + dstRect.bottom = drawRect.y + drawRect.height; + + HRESULT result = mDevice->StretchRect(readSurface, &srcRect, drawSurface, &dstRect, D3DTEXF_NONE); + + readSurface->Release(); + drawSurface->Release(); + + if (FAILED(result)) + { + ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result); + return false; + } + } + + if (blitDepthStencil) + { + gl::Renderbuffer *readBuffer = readFramebuffer->getDepthOrStencilbuffer(); + gl::Renderbuffer *drawBuffer = drawFramebuffer->getDepthOrStencilbuffer(); + RenderTarget9 *readDepthStencil = NULL; + RenderTarget9 *drawDepthStencil = NULL; + IDirect3DSurface9* readSurface = NULL; + IDirect3DSurface9* drawSurface = NULL; + + if (readBuffer) + { + readDepthStencil = RenderTarget9::makeRenderTarget9(readBuffer->getDepthStencil()); + } + if (drawBuffer) + { + drawDepthStencil = RenderTarget9::makeRenderTarget9(drawBuffer->getDepthStencil()); + } + + if (readDepthStencil) + { + readSurface = readDepthStencil->getSurface(); + } + if (drawDepthStencil) + { + drawSurface = drawDepthStencil->getSurface(); + } + + if (!readSurface || !drawSurface) + { + ERR("Failed to retrieve the render target."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + HRESULT result = mDevice->StretchRect(readSurface, NULL, drawSurface, NULL, D3DTEXF_NONE); + + readSurface->Release(); + drawSurface->Release(); + + if (FAILED(result)) + { + ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result); + return false; + } + } + + return true; +} + +void Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, + GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels) +{ + RenderTarget9 *renderTarget = NULL; + IDirect3DSurface9 *surface = NULL; + gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(0); + + if (colorbuffer) + { + renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget()); + } + + if (renderTarget) + { + surface = renderTarget->getSurface(); + } + + if (!surface) + { + // context must be lost + return; + } + + D3DSURFACE_DESC desc; + surface->GetDesc(&desc); + + if (desc.MultiSampleType != D3DMULTISAMPLE_NONE) + { + UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target + surface->Release(); + return gl::error(GL_OUT_OF_MEMORY); + } + + HRESULT result; + IDirect3DSurface9 *systemSurface = NULL; + bool directToPixels = !packReverseRowOrder && packAlignment <= 4 && getShareHandleSupport() && + x == 0 && y == 0 && UINT(width) == desc.Width && UINT(height) == desc.Height && + desc.Format == D3DFMT_A8R8G8B8 && format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE; + if (directToPixels) + { + // Use the pixels ptr as a shared handle to write directly into client's memory + result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, + D3DPOOL_SYSTEMMEM, &systemSurface, &pixels); + if (FAILED(result)) + { + // Try again without the shared handle + directToPixels = false; + } + } + + if (!directToPixels) + { + result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, + D3DPOOL_SYSTEMMEM, &systemSurface, NULL); + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + surface->Release(); + return gl::error(GL_OUT_OF_MEMORY); + } + } + + result = mDevice->GetRenderTargetData(surface, systemSurface); + surface->Release(); + surface = NULL; + + if (FAILED(result)) + { + systemSurface->Release(); + + // It turns out that D3D will sometimes produce more error + // codes than those documented. + if (d3d9::isDeviceLostError(result)) + { + notifyDeviceLost(); + return gl::error(GL_OUT_OF_MEMORY); + } + else + { + UNREACHABLE(); + return; + } + + } + + if (directToPixels) + { + systemSurface->Release(); + return; + } + + RECT rect; + rect.left = gl::clamp(x, 0L, static_cast(desc.Width)); + rect.top = gl::clamp(y, 0L, static_cast(desc.Height)); + rect.right = gl::clamp(x + width, 0L, static_cast(desc.Width)); + rect.bottom = gl::clamp(y + height, 0L, static_cast(desc.Height)); + + D3DLOCKED_RECT lock; + result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY); + + if (FAILED(result)) + { + UNREACHABLE(); + systemSurface->Release(); + + return; // No sensible error to generate + } + + unsigned char *dest = (unsigned char*)pixels; + unsigned short *dest16 = (unsigned short*)pixels; + + unsigned char *source; + int inputPitch; + if (packReverseRowOrder) + { + source = ((unsigned char*)lock.pBits) + lock.Pitch * (rect.bottom - rect.top - 1); + inputPitch = -lock.Pitch; + } + else + { + source = (unsigned char*)lock.pBits; + inputPitch = lock.Pitch; + } + + unsigned int fastPixelSize = 0; + + if (desc.Format == D3DFMT_A8R8G8B8 && + format == GL_BGRA_EXT && + type == GL_UNSIGNED_BYTE) + { + fastPixelSize = 4; + } + else if ((desc.Format == D3DFMT_A4R4G4B4 && + format == GL_BGRA_EXT && + type == GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT) || + (desc.Format == D3DFMT_A1R5G5B5 && + format == GL_BGRA_EXT && + type == GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT)) + { + fastPixelSize = 2; + } + else if (desc.Format == D3DFMT_A16B16G16R16F && + format == GL_RGBA && + type == GL_HALF_FLOAT_OES) + { + fastPixelSize = 8; + } + else if (desc.Format == D3DFMT_A32B32G32R32F && + format == GL_RGBA && + type == GL_FLOAT) + { + fastPixelSize = 16; + } + + for (int j = 0; j < rect.bottom - rect.top; j++) + { + if (fastPixelSize != 0) + { + // Fast path for formats which require no translation: + // D3DFMT_A8R8G8B8 to BGRA/UNSIGNED_BYTE + // D3DFMT_A4R4G4B4 to BGRA/UNSIGNED_SHORT_4_4_4_4_REV_EXT + // D3DFMT_A1R5G5B5 to BGRA/UNSIGNED_SHORT_1_5_5_5_REV_EXT + // D3DFMT_A16B16G16R16F to RGBA/HALF_FLOAT_OES + // D3DFMT_A32B32G32R32F to RGBA/FLOAT + // + // Note that buffers with no alpha go through the slow path below. + memcpy(dest + j * outputPitch, + source + j * inputPitch, + (rect.right - rect.left) * fastPixelSize); + continue; + } + else if (desc.Format == D3DFMT_A8R8G8B8 && + format == GL_RGBA && + type == GL_UNSIGNED_BYTE) + { + // Fast path for swapping red with blue + for (int i = 0; i < rect.right - rect.left; i++) + { + unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch); + *(unsigned int*)(dest + 4 * i + j * outputPitch) = + (argb & 0xFF00FF00) | // Keep alpha and green + (argb & 0x00FF0000) >> 16 | // Move red to blue + (argb & 0x000000FF) << 16; // Move blue to red + } + continue; + } + + for (int i = 0; i < rect.right - rect.left; i++) + { + float r; + float g; + float b; + float a; + + switch (desc.Format) + { + case D3DFMT_R5G6B5: + { + unsigned short rgb = *(unsigned short*)(source + 2 * i + j * inputPitch); + + a = 1.0f; + b = (rgb & 0x001F) * (1.0f / 0x001F); + g = (rgb & 0x07E0) * (1.0f / 0x07E0); + r = (rgb & 0xF800) * (1.0f / 0xF800); + } + break; + case D3DFMT_A1R5G5B5: + { + unsigned short argb = *(unsigned short*)(source + 2 * i + j * inputPitch); + + a = (argb & 0x8000) ? 1.0f : 0.0f; + b = (argb & 0x001F) * (1.0f / 0x001F); + g = (argb & 0x03E0) * (1.0f / 0x03E0); + r = (argb & 0x7C00) * (1.0f / 0x7C00); + } + break; + case D3DFMT_A8R8G8B8: + { + unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch); + + a = (argb & 0xFF000000) * (1.0f / 0xFF000000); + b = (argb & 0x000000FF) * (1.0f / 0x000000FF); + g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00); + r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000); + } + break; + case D3DFMT_X8R8G8B8: + { + unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * inputPitch); + + a = 1.0f; + b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF); + g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00); + r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000); + } + break; + case D3DFMT_A2R10G10B10: + { + unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch); + + a = (argb & 0xC0000000) * (1.0f / 0xC0000000); + b = (argb & 0x000003FF) * (1.0f / 0x000003FF); + g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00); + r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000); + } + break; + case D3DFMT_A32B32G32R32F: + { + // float formats in D3D are stored rgba, rather than the other way round + r = *((float*)(source + 16 * i + j * inputPitch) + 0); + g = *((float*)(source + 16 * i + j * inputPitch) + 1); + b = *((float*)(source + 16 * i + j * inputPitch) + 2); + a = *((float*)(source + 16 * i + j * inputPitch) + 3); + } + break; + case D3DFMT_A16B16G16R16F: + { + // float formats in D3D are stored rgba, rather than the other way round + r = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 0)); + g = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 1)); + b = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 2)); + a = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 3)); + } + break; + default: + UNIMPLEMENTED(); // FIXME + UNREACHABLE(); + return; + } + + switch (format) + { + case GL_RGBA: + switch (type) + { + case GL_UNSIGNED_BYTE: + dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f); + dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f); + dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f); + dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f); + break; + default: UNREACHABLE(); + } + break; + case GL_BGRA_EXT: + switch (type) + { + case GL_UNSIGNED_BYTE: + dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * b + 0.5f); + dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f); + dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * r + 0.5f); + dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f); + break; + case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT: + // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section + // this type is packed as follows: + // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + // -------------------------------------------------------------------------------- + // | 4th | 3rd | 2nd | 1st component | + // -------------------------------------------------------------------------------- + // in the case of BGRA_EXT, B is the first component, G the second, and so forth. + dest16[i + j * outputPitch / sizeof(unsigned short)] = + ((unsigned short)(15 * a + 0.5f) << 12)| + ((unsigned short)(15 * r + 0.5f) << 8) | + ((unsigned short)(15 * g + 0.5f) << 4) | + ((unsigned short)(15 * b + 0.5f) << 0); + break; + case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT: + // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section + // this type is packed as follows: + // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + // -------------------------------------------------------------------------------- + // | 4th | 3rd | 2nd | 1st component | + // -------------------------------------------------------------------------------- + // in the case of BGRA_EXT, B is the first component, G the second, and so forth. + dest16[i + j * outputPitch / sizeof(unsigned short)] = + ((unsigned short)( a + 0.5f) << 15) | + ((unsigned short)(31 * r + 0.5f) << 10) | + ((unsigned short)(31 * g + 0.5f) << 5) | + ((unsigned short)(31 * b + 0.5f) << 0); + break; + default: UNREACHABLE(); + } + break; + case GL_RGB: + switch (type) + { + case GL_UNSIGNED_SHORT_5_6_5: + dest16[i + j * outputPitch / sizeof(unsigned short)] = + ((unsigned short)(31 * b + 0.5f) << 0) | + ((unsigned short)(63 * g + 0.5f) << 5) | + ((unsigned short)(31 * r + 0.5f) << 11); + break; + case GL_UNSIGNED_BYTE: + dest[3 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f); + dest[3 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f); + dest[3 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f); + break; + default: UNREACHABLE(); + } + break; + default: UNREACHABLE(); + } + } + } + + systemSurface->UnlockRect(); + + systemSurface->Release(); +} + +RenderTarget *Renderer9::createRenderTarget(SwapChain *swapChain, bool depth) +{ + SwapChain9 *swapChain9 = SwapChain9::makeSwapChain9(swapChain); + IDirect3DSurface9 *surface = NULL; + if (depth) + { + surface = swapChain9->getDepthStencil(); + } + else + { + surface = swapChain9->getRenderTarget(); + } + + RenderTarget9 *renderTarget = new RenderTarget9(this, surface); + + return renderTarget; +} + +RenderTarget *Renderer9::createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth) +{ + RenderTarget9 *renderTarget = new RenderTarget9(this, width, height, format, samples); + return renderTarget; +} + +ShaderExecutable *Renderer9::loadExecutable(const void *function, size_t length, rx::ShaderType type) +{ + ShaderExecutable9 *executable = NULL; + + switch (type) + { + case rx::SHADER_VERTEX: + { + IDirect3DVertexShader9 *vshader = createVertexShader((DWORD*)function, length); + if (vshader) + { + executable = new ShaderExecutable9(function, length, vshader); + } + } + break; + case rx::SHADER_PIXEL: + { + IDirect3DPixelShader9 *pshader = createPixelShader((DWORD*)function, length); + if (pshader) + { + executable = new ShaderExecutable9(function, length, pshader); + } + } + break; + default: + UNREACHABLE(); + break; + } + + return executable; +} + +ShaderExecutable *Renderer9::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type) +{ + const char *profile = NULL; + + switch (type) + { + case rx::SHADER_VERTEX: + profile = getMajorShaderModel() >= 3 ? "vs_3_0" : "vs_2_0"; + break; + case rx::SHADER_PIXEL: + profile = getMajorShaderModel() >= 3 ? "ps_3_0" : "ps_2_0"; + break; + default: + UNREACHABLE(); + return NULL; + } + + ID3DBlob *binary = (ID3DBlob*)compileToBinary(infoLog, shaderHLSL, profile, ANGLE_COMPILE_OPTIMIZATION_LEVEL, true); + if (!binary) + return NULL; + + ShaderExecutable *executable = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type); + binary->Release(); + + return executable; +} + +bool Renderer9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest) +{ + return mBlit->boxFilter(source, dest); +} + +D3DPOOL Renderer9::getTexturePool(DWORD usage) const +{ + if (mD3d9Ex != NULL) + { + return D3DPOOL_DEFAULT; + } + else + { + if (!(usage & (D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_RENDERTARGET))) + { + return D3DPOOL_DEFAULT; + } + } + + return D3DPOOL_DEFAULT; +} + +bool Renderer9::copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged) +{ + if (source && dest) + { + HRESULT result = D3DERR_OUTOFVIDEOMEMORY; + + if (fromManaged) + { + D3DSURFACE_DESC desc; + source->GetDesc(&desc); + + IDirect3DSurface9 *surf = 0; + result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL); + + if (SUCCEEDED(result)) + { + Image9::copyLockableSurfaces(surf, source); + result = mDevice->UpdateSurface(surf, NULL, dest, NULL); + surf->Release(); + } + } + else + { + endScene(); + result = mDevice->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE); + } + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return false; + } + } + + return true; +} + +Image *Renderer9::createImage() +{ + return new Image9(); +} + +void Renderer9::generateMipmap(Image *dest, Image *src) +{ + Image9 *src9 = Image9::makeImage9(src); + Image9 *dst9 = Image9::makeImage9(dest); + Image9::generateMipmap(dst9, src9); +} + +TextureStorage *Renderer9::createTextureStorage2D(SwapChain *swapChain) +{ + SwapChain9 *swapChain9 = SwapChain9::makeSwapChain9(swapChain); + return new TextureStorage9_2D(this, swapChain9); +} + +TextureStorage *Renderer9::createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height) +{ + return new TextureStorage9_2D(this, levels, internalformat, usage, forceRenderable, width, height); +} + +TextureStorage *Renderer9::createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size) +{ + return new TextureStorage9_Cube(this, levels, internalformat, usage, forceRenderable, size); +} + +bool Renderer9::getLUID(LUID *adapterLuid) const +{ + adapterLuid->HighPart = 0; + adapterLuid->LowPart = 0; + + if (mD3d9Ex) + { + mD3d9Ex->GetAdapterLUID(mAdapter, adapterLuid); + return true; + } + + return false; +} + +} diff --git a/gfx/angle/src/libGLESv2/renderer/Renderer9.h b/gfx/angle/src/libGLESv2/renderer/Renderer9.h new file mode 100644 index 000000000000..2873e6114611 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/Renderer9.h @@ -0,0 +1,349 @@ +// +// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Renderer9.h: Defines a back-end specific class for the D3D9 renderer. + +#ifndef LIBGLESV2_RENDERER_RENDERER9_H_ +#define LIBGLESV2_RENDERER_RENDERER9_H_ + +#include "common/angleutils.h" +#include "libGLESv2/mathutil.h" +#include "libGLESv2/renderer/ShaderCache.h" +#include "libGLESv2/renderer/VertexDeclarationCache.h" +#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/renderer/RenderTarget.h" + +namespace gl +{ +class Renderbuffer; +} + +namespace rx +{ +class VertexDataManager; +class IndexDataManager; +class StreamingIndexBufferInterface; +struct TranslatedAttribute; + +class Renderer9 : public Renderer +{ + public: + Renderer9(egl::Display *display, HDC hDc, bool softwareDevice); + virtual ~Renderer9(); + + static Renderer9 *makeRenderer9(Renderer *renderer); + + virtual EGLint initialize(); + virtual bool resetDevice(); + + virtual int generateConfigs(ConfigDesc **configDescList); + virtual void deleteConfigs(ConfigDesc *configDescList); + + void startScene(); + void endScene(); + + virtual void sync(bool block); + + virtual SwapChain *createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat); + + IDirect3DQuery9* allocateEventQuery(); + void freeEventQuery(IDirect3DQuery9* query); + + // resource creation + IDirect3DVertexShader9 *createVertexShader(const DWORD *function, size_t length); + IDirect3DPixelShader9 *createPixelShader(const DWORD *function, size_t length); + HRESULT createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer); + HRESULT createIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, IDirect3DIndexBuffer9 **ppIndexBuffer); +#if 0 + void *createTexture2D(); + void *createTextureCube(); + void *createQuery(); + void *createIndexBuffer(); + void *createVertexbuffer(); + + // state setup + void applyShaders(); + void applyConstants(); +#endif + virtual void setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler); + virtual void setTexture(gl::SamplerType type, int index, gl::Texture *texture); + + virtual void setRasterizerState(const gl::RasterizerState &rasterState); + virtual void setBlendState(const gl::BlendState &blendState, const gl::Color &blendColor, + unsigned int sampleMask); + virtual void setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, + int stencilBackRef, bool frontFaceCCW); + + virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled); + virtual bool setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, + bool ignoreViewport); + + virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer); + virtual void applyShaders(gl::ProgramBinary *programBinary); + virtual void applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray); + virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount); + virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances); + virtual GLenum applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo); + + virtual void drawArrays(GLenum mode, GLsizei count, GLsizei instances); + virtual void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances); + + virtual void clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer); + + virtual void markAllStateDirty(); + + // lost device + void notifyDeviceLost(); + virtual bool isDeviceLost(); + virtual bool testDeviceLost(bool notify); + virtual bool testDeviceResettable(); + + // Renderer capabilities + IDirect3DDevice9 *getDevice() { return mDevice; } + virtual DWORD getAdapterVendor() const; + virtual std::string getRendererDescription() const; + virtual GUID getAdapterIdentifier() const; + + virtual bool getBGRATextureSupport() const; + virtual bool getDXT1TextureSupport(); + virtual bool getDXT3TextureSupport(); + virtual bool getDXT5TextureSupport(); + virtual bool getEventQuerySupport(); + virtual bool getFloat32TextureSupport(bool *filtering, bool *renderable); + virtual bool getFloat16TextureSupport(bool *filtering, bool *renderable); + virtual bool getLuminanceTextureSupport(); + virtual bool getLuminanceAlphaTextureSupport(); + virtual unsigned int getMaxVertexTextureImageUnits() const; + virtual unsigned int getMaxCombinedTextureImageUnits() const; + virtual unsigned int getReservedVertexUniformVectors() const; + virtual unsigned int getReservedFragmentUniformVectors() const; + virtual unsigned int getMaxVertexUniformVectors() const; + virtual unsigned int getMaxFragmentUniformVectors() const; + virtual unsigned int getMaxVaryingVectors() const; + virtual bool getNonPower2TextureSupport() const; + virtual bool getDepthTextureSupport() const; + virtual bool getOcclusionQuerySupport() const; + virtual bool getInstancingSupport() const; + virtual bool getTextureFilterAnisotropySupport() const; + virtual float getTextureMaxAnisotropy() const; + virtual bool getShareHandleSupport() const; + virtual bool getDerivativeInstructionSupport() const; + virtual bool getPostSubBufferSupport() const; + + virtual int getMajorShaderModel() const; + virtual float getMaxPointSize() const; + virtual int getMaxViewportDimension() const; + virtual int getMaxTextureWidth() const; + virtual int getMaxTextureHeight() const; + virtual bool get32BitIndexSupport() const; + DWORD getCapsDeclTypes() const; + virtual int getMinSwapInterval() const; + virtual int getMaxSwapInterval() const; + + virtual GLsizei getMaxSupportedSamples() const; + int getNearestSupportedSamples(D3DFORMAT format, int requested) const; + + virtual unsigned int getMaxRenderTargets() const; + + D3DFORMAT ConvertTextureInternalFormat(GLint internalformat); + + // Pixel operations + virtual bool copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source); + virtual bool copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source); + + virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level); + virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level); + + virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, + bool blitRenderTarget, bool blitDepthStencil); + virtual void readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, + GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels); + + // RenderTarget creation + virtual RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth); + virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth); + + // Shader operations + virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type); + virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type); + + // Image operations + virtual Image *createImage(); + virtual void generateMipmap(Image *dest, Image *source); + virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain); + virtual TextureStorage *createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height); + virtual TextureStorage *createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size); + + // Buffer creation + virtual VertexBuffer *createVertexBuffer(); + virtual IndexBuffer *createIndexBuffer(); + virtual BufferStorage *createBufferStorage(); + + // Query and Fence creation + virtual QueryImpl *createQuery(GLenum type); + virtual FenceImpl *createFence(); + + // D3D9-renderer specific methods + bool boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest); + + D3DPOOL getTexturePool(DWORD usage) const; + + virtual bool getLUID(LUID *adapterLuid) const; + + private: + DISALLOW_COPY_AND_ASSIGN(Renderer9); + + void applyUniformnfv(gl::Uniform *targetUniform, const GLfloat *v); + void applyUniformniv(gl::Uniform *targetUniform, const GLint *v); + void applyUniformnbv(gl::Uniform *targetUniform, const GLint *v); + + void drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer); + void drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer); + + void getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray); + bool copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged); + gl::Renderbuffer *getNullColorbuffer(gl::Renderbuffer *depthbuffer); + + D3DPOOL getBufferPool(DWORD usage) const; + + HMODULE mD3d9Module; + HDC mDc; + + void initializeDevice(); + D3DPRESENT_PARAMETERS getDefaultPresentParameters(); + void releaseDeviceResources(); + + UINT mAdapter; + D3DDEVTYPE mDeviceType; + bool mSoftwareDevice; // FIXME: Deprecate + IDirect3D9 *mD3d9; // Always valid after successful initialization. + IDirect3D9Ex *mD3d9Ex; // Might be null if D3D9Ex is not supported. + IDirect3DDevice9 *mDevice; + IDirect3DDevice9Ex *mDeviceEx; // Might be null if D3D9Ex is not supported. + + Blit *mBlit; + + HWND mDeviceWindow; + + bool mDeviceLost; + D3DCAPS9 mDeviceCaps; + D3DADAPTER_IDENTIFIER9 mAdapterIdentifier; + + D3DPRIMITIVETYPE mPrimitiveType; + int mPrimitiveCount; + GLsizei mRepeatDraw; + + bool mSceneStarted; + bool mSupportsNonPower2Textures; + bool mSupportsTextureFilterAnisotropy; + int mMinSwapInterval; + int mMaxSwapInterval; + + bool mOcclusionQuerySupport; + bool mEventQuerySupport; + bool mVertexTextureSupport; + + bool mDepthTextureSupport; + + bool mFloat32TextureSupport; + bool mFloat32FilterSupport; + bool mFloat32RenderSupport; + + bool mFloat16TextureSupport; + bool mFloat16FilterSupport; + bool mFloat16RenderSupport; + + bool mDXT1TextureSupport; + bool mDXT3TextureSupport; + bool mDXT5TextureSupport; + + bool mLuminanceTextureSupport; + bool mLuminanceAlphaTextureSupport; + + std::map mMultiSampleSupport; + GLsizei mMaxSupportedSamples; + + // current render target states + unsigned int mAppliedRenderTargetSerial; + unsigned int mAppliedDepthbufferSerial; + unsigned int mAppliedStencilbufferSerial; + bool mDepthStencilInitialized; + bool mRenderTargetDescInitialized; + rx::RenderTarget::Desc mRenderTargetDesc; + unsigned int mCurStencilSize; + unsigned int mCurDepthSize; + + IDirect3DStateBlock9 *mMaskedClearSavedState; + + // previously set render states + bool mForceSetDepthStencilState; + gl::DepthStencilState mCurDepthStencilState; + int mCurStencilRef; + int mCurStencilBackRef; + bool mCurFrontFaceCCW; + + bool mForceSetRasterState; + gl::RasterizerState mCurRasterState; + + bool mForceSetScissor; + gl::Rectangle mCurScissor; + bool mScissorEnabled; + + bool mForceSetViewport; + gl::Rectangle mCurViewport; + float mCurNear; + float mCurFar; + + bool mForceSetBlendState; + gl::BlendState mCurBlendState; + gl::Color mCurBlendColor; + GLuint mCurSampleMask; + + // Currently applied sampler states + bool mForceSetVertexSamplerStates[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; + gl::SamplerState mCurVertexSamplerStates[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; + + bool mForceSetPixelSamplerStates[gl::MAX_TEXTURE_IMAGE_UNITS]; + gl::SamplerState mCurPixelSamplerStates[gl::MAX_TEXTURE_IMAGE_UNITS]; + + // Currently applied textures + unsigned int mCurVertexTextureSerials[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; + unsigned int mCurPixelTextureSerials[gl::MAX_TEXTURE_IMAGE_UNITS]; + + unsigned int mAppliedIBSerial; + unsigned int mAppliedProgramBinarySerial; + + rx::dx_VertexConstants mVertexConstants; + rx::dx_PixelConstants mPixelConstants; + bool mDxUniformsDirty; + + // A pool of event queries that are currently unused. + std::vector mEventQueryPool; + VertexShaderCache mVertexShaderCache; + PixelShaderCache mPixelShaderCache; + + VertexDataManager *mVertexDataManager; + VertexDeclarationCache mVertexDeclarationCache; + + IndexDataManager *mIndexDataManager; + StreamingIndexBufferInterface *mLineLoopIB; + + enum { NUM_NULL_COLORBUFFER_CACHE_ENTRIES = 12 }; + struct NullColorbufferCacheEntry + { + UINT lruCount; + int width; + int height; + gl::Renderbuffer *buffer; + } mNullColorbufferCache[NUM_NULL_COLORBUFFER_CACHE_ENTRIES]; + UINT mMaxNullColorbufferLRU; + +}; + +} +#endif // LIBGLESV2_RENDERER_RENDERER9_H_ diff --git a/gfx/angle/src/libEGL/ShaderCache.h b/gfx/angle/src/libGLESv2/renderer/ShaderCache.h similarity index 88% rename from gfx/angle/src/libEGL/ShaderCache.h rename to gfx/angle/src/libGLESv2/renderer/ShaderCache.h index cfe523ba09fd..4391ac271a36 100644 --- a/gfx/angle/src/libEGL/ShaderCache.h +++ b/gfx/angle/src/libGLESv2/renderer/ShaderCache.h @@ -4,21 +4,15 @@ // found in the LICENSE file. // -// Display.h: Defines egl::ShaderCache, a cache of Direct3D shader objects +// ShaderCache: Defines rx::ShaderCache, a cache of Direct3D shader objects // keyed by their byte code. -#ifndef LIBEGL_SHADER_CACHE_H_ -#define LIBEGL_SHADER_CACHE_H_ +#ifndef LIBGLESV2_RENDERER_SHADER_CACHE_H_ +#define LIBGLESV2_RENDERER_SHADER_CACHE_H_ -#include +#include "common/debug.h" -#ifdef _MSC_VER -#include -#else -#include -#endif - -namespace egl +namespace rx { template class ShaderCache @@ -48,7 +42,7 @@ class ShaderCache it->second->AddRef(); return it->second; } - + ShaderObject *shader; HRESULT result = createShader(function, &shader); if (FAILED(result)) @@ -113,4 +107,4 @@ typedef ShaderCache PixelShaderCache; } -#endif // LIBEGL_SHADER_CACHE_H_ +#endif // LIBGLESV2_RENDERER_SHADER_CACHE_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/ShaderExecutable.h b/gfx/angle/src/libGLESv2/renderer/ShaderExecutable.h new file mode 100644 index 000000000000..293e340845e5 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/ShaderExecutable.h @@ -0,0 +1,51 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// ShaderExecutable.h: Defines a renderer-agnostic class to contain shader +// executable implementation details. + +#ifndef LIBGLESV2_RENDERER_SHADEREXECUTABLE_H_ +#define LIBGLESV2_RENDERER_SHADEREXECUTABLE_H_ + +#include "common/angleutils.h" + +namespace rx +{ + +class ShaderExecutable +{ + public: + ShaderExecutable(const void *function, size_t length) : mLength(length) + { + mFunction = new char[length]; + memcpy(mFunction, function, length); + } + + virtual ~ShaderExecutable() + { + delete[] mFunction; + } + + void *getFunction() const + { + return mFunction; + } + + size_t getLength() const + { + return mLength; + } + + private: + DISALLOW_COPY_AND_ASSIGN(ShaderExecutable); + + void *mFunction; + const size_t mLength; +}; + +} + +#endif // LIBGLESV2_RENDERER_SHADEREXECUTABLE9_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/ShaderExecutable11.cpp b/gfx/angle/src/libGLESv2/renderer/ShaderExecutable11.cpp new file mode 100644 index 000000000000..e1eb56033483 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/ShaderExecutable11.cpp @@ -0,0 +1,109 @@ +#include "precompiled.h" +// +// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// ShaderExecutable11.cpp: Implements a D3D11-specific class to contain shader +// executable implementation details. + +#include "libGLESv2/renderer/ShaderExecutable11.h" + +#include "common/debug.h" + +namespace rx +{ + +ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11PixelShader *executable) + : ShaderExecutable(function, length) +{ + mPixelExecutable = executable; + mVertexExecutable = NULL; + mGeometryExecutable = NULL; + + mConstantBuffer = NULL; +} + +ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable) + : ShaderExecutable(function, length) +{ + mVertexExecutable = executable; + mPixelExecutable = NULL; + mGeometryExecutable = NULL; + + mConstantBuffer = NULL; +} + +ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11GeometryShader *executable) + : ShaderExecutable(function, length) +{ + mGeometryExecutable = executable; + mVertexExecutable = NULL; + mPixelExecutable = NULL; + + mConstantBuffer = NULL; +} + +ShaderExecutable11::~ShaderExecutable11() +{ + if (mVertexExecutable) + { + mVertexExecutable->Release(); + } + if (mPixelExecutable) + { + mPixelExecutable->Release(); + } + if (mGeometryExecutable) + { + mGeometryExecutable->Release(); + } + + if (mConstantBuffer) + { + mConstantBuffer->Release(); + } +} + +ShaderExecutable11 *ShaderExecutable11::makeShaderExecutable11(ShaderExecutable *executable) +{ + ASSERT(HAS_DYNAMIC_TYPE(ShaderExecutable11*, executable)); + return static_cast(executable); +} + +ID3D11VertexShader *ShaderExecutable11::getVertexShader() const +{ + return mVertexExecutable; +} + +ID3D11PixelShader *ShaderExecutable11::getPixelShader() const +{ + return mPixelExecutable; +} + +ID3D11GeometryShader *ShaderExecutable11::getGeometryShader() const +{ + return mGeometryExecutable; +} + +ID3D11Buffer *ShaderExecutable11::getConstantBuffer(ID3D11Device *device, unsigned int registerCount) +{ + if (!mConstantBuffer && registerCount > 0) + { + D3D11_BUFFER_DESC constantBufferDescription = {0}; + constantBufferDescription.ByteWidth = registerCount * sizeof(float[4]); + constantBufferDescription.Usage = D3D11_USAGE_DYNAMIC; + constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + constantBufferDescription.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + constantBufferDescription.MiscFlags = 0; + constantBufferDescription.StructureByteStride = 0; + + HRESULT result = device->CreateBuffer(&constantBufferDescription, NULL, &mConstantBuffer); + ASSERT(SUCCEEDED(result)); + } + + return mConstantBuffer; +} + +} \ No newline at end of file diff --git a/gfx/angle/src/libGLESv2/renderer/ShaderExecutable11.h b/gfx/angle/src/libGLESv2/renderer/ShaderExecutable11.h new file mode 100644 index 000000000000..c6ec1cf7d2cd --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/ShaderExecutable11.h @@ -0,0 +1,47 @@ +// +// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// ShaderExecutable11.h: Defines a D3D11-specific class to contain shader +// executable implementation details. + +#ifndef LIBGLESV2_RENDERER_SHADEREXECUTABLE11_H_ +#define LIBGLESV2_RENDERER_SHADEREXECUTABLE11_H_ + +#include "libGLESv2/renderer/ShaderExecutable.h" + +namespace rx +{ + +class ShaderExecutable11 : public ShaderExecutable +{ + public: + ShaderExecutable11(const void *function, size_t length, ID3D11PixelShader *executable); + ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable); + ShaderExecutable11(const void *function, size_t length, ID3D11GeometryShader *executable); + + virtual ~ShaderExecutable11(); + + static ShaderExecutable11 *makeShaderExecutable11(ShaderExecutable *executable); + + ID3D11PixelShader *getPixelShader() const; + ID3D11VertexShader *getVertexShader() const; + ID3D11GeometryShader *getGeometryShader() const; + + ID3D11Buffer *getConstantBuffer(ID3D11Device *device, unsigned int registerCount); + + private: + DISALLOW_COPY_AND_ASSIGN(ShaderExecutable11); + + ID3D11PixelShader *mPixelExecutable; + ID3D11VertexShader *mVertexExecutable; + ID3D11GeometryShader *mGeometryExecutable; + + ID3D11Buffer *mConstantBuffer; +}; + +} + +#endif // LIBGLESV2_RENDERER_SHADEREXECUTABLE11_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/ShaderExecutable9.cpp b/gfx/angle/src/libGLESv2/renderer/ShaderExecutable9.cpp new file mode 100644 index 000000000000..98868a3fbf38 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/ShaderExecutable9.cpp @@ -0,0 +1,60 @@ +#include "precompiled.h" +// +// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// ShaderExecutable9.cpp: Implements a D3D9-specific class to contain shader +// executable implementation details. + +#include "libGLESv2/renderer/ShaderExecutable9.h" + +#include "common/debug.h" + +namespace rx +{ + +ShaderExecutable9::ShaderExecutable9(const void *function, size_t length, IDirect3DPixelShader9 *executable) + : ShaderExecutable(function, length) +{ + mPixelExecutable = executable; + mVertexExecutable = NULL; +} + +ShaderExecutable9::ShaderExecutable9(const void *function, size_t length, IDirect3DVertexShader9 *executable) + : ShaderExecutable(function, length) +{ + mVertexExecutable = executable; + mPixelExecutable = NULL; +} + +ShaderExecutable9::~ShaderExecutable9() +{ + if (mVertexExecutable) + { + mVertexExecutable->Release(); + } + if (mPixelExecutable) + { + mPixelExecutable->Release(); + } +} + +ShaderExecutable9 *ShaderExecutable9::makeShaderExecutable9(ShaderExecutable *executable) +{ + ASSERT(HAS_DYNAMIC_TYPE(ShaderExecutable9*, executable)); + return static_cast(executable); +} + +IDirect3DVertexShader9 *ShaderExecutable9::getVertexShader() const +{ + return mVertexExecutable; +} + +IDirect3DPixelShader9 *ShaderExecutable9::getPixelShader() const +{ + return mPixelExecutable; +} + +} \ No newline at end of file diff --git a/gfx/angle/src/libGLESv2/renderer/ShaderExecutable9.h b/gfx/angle/src/libGLESv2/renderer/ShaderExecutable9.h new file mode 100644 index 000000000000..fa1e6c2844a9 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/ShaderExecutable9.h @@ -0,0 +1,39 @@ +// +// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// ShaderExecutable9.h: Defines a D3D9-specific class to contain shader +// executable implementation details. + +#ifndef LIBGLESV2_RENDERER_SHADEREXECUTABLE9_H_ +#define LIBGLESV2_RENDERER_SHADEREXECUTABLE9_H_ + +#include "libGLESv2/renderer/ShaderExecutable.h" + +namespace rx +{ + +class ShaderExecutable9 : public ShaderExecutable +{ + public: + ShaderExecutable9(const void *function, size_t length, IDirect3DPixelShader9 *executable); + ShaderExecutable9(const void *function, size_t length, IDirect3DVertexShader9 *executable); + virtual ~ShaderExecutable9(); + + static ShaderExecutable9 *makeShaderExecutable9(ShaderExecutable *executable); + + IDirect3DPixelShader9 *getPixelShader() const; + IDirect3DVertexShader9 *getVertexShader() const; + + private: + DISALLOW_COPY_AND_ASSIGN(ShaderExecutable9); + + IDirect3DPixelShader9 *mPixelExecutable; + IDirect3DVertexShader9 *mVertexExecutable; +}; + +} + +#endif // LIBGLESV2_RENDERER_SHADEREXECUTABLE9_H_ \ No newline at end of file diff --git a/gfx/angle/src/libGLESv2/renderer/SwapChain.h b/gfx/angle/src/libGLESv2/renderer/SwapChain.h new file mode 100644 index 000000000000..14c0515fc860 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/SwapChain.h @@ -0,0 +1,44 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// SwapChain.h: Defines a back-end specific class that hides the details of the +// implementation-specific swapchain. + +#ifndef LIBGLESV2_RENDERER_SWAPCHAIN_H_ +#define LIBGLESV2_RENDERER_SWAPCHAIN_H_ + +#include "common/angleutils.h" + +namespace rx +{ + +class SwapChain +{ + public: + SwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) + : mWindow(window), mShareHandle(shareHandle), mBackBufferFormat(backBufferFormat), mDepthBufferFormat(depthBufferFormat) + { + } + + virtual ~SwapChain() {}; + + virtual EGLint resize(EGLint backbufferWidth, EGLint backbufferSize) = 0; + virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval) = 0; + virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height) = 0; + virtual void recreate() = 0; + + virtual HANDLE getShareHandle() {return mShareHandle;}; + + protected: + const HWND mWindow; // Window that the surface is created for. + const GLenum mBackBufferFormat; + const GLenum mDepthBufferFormat; + + HANDLE mShareHandle; +}; + +} +#endif // LIBGLESV2_RENDERER_SWAPCHAIN_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/SwapChain11.cpp b/gfx/angle/src/libGLESv2/renderer/SwapChain11.cpp new file mode 100644 index 000000000000..87422be727fb --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/SwapChain11.cpp @@ -0,0 +1,767 @@ +#include "precompiled.h" +// +// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// SwapChain11.cpp: Implements a back-end specific class for the D3D11 swap chain. + +#include "libGLESv2/renderer/SwapChain11.h" + +#include "libGLESv2/renderer/renderer11_utils.h" +#include "libGLESv2/renderer/Renderer11.h" +#include "libGLESv2/renderer/shaders/compiled/passthrough11vs.h" +#include "libGLESv2/renderer/shaders/compiled/passthroughrgba11ps.h" + +namespace rx +{ + +SwapChain11::SwapChain11(Renderer11 *renderer, HWND window, HANDLE shareHandle, + GLenum backBufferFormat, GLenum depthBufferFormat) + : mRenderer(renderer), SwapChain(window, shareHandle, backBufferFormat, depthBufferFormat) +{ + mSwapChain = NULL; + mBackBufferTexture = NULL; + mBackBufferRTView = NULL; + mOffscreenTexture = NULL; + mOffscreenRTView = NULL; + mOffscreenSRView = NULL; + mDepthStencilTexture = NULL; + mDepthStencilDSView = NULL; + mQuadVB = NULL; + mPassThroughSampler = NULL; + mPassThroughIL = NULL; + mPassThroughVS = NULL; + mPassThroughPS = NULL; + mWidth = -1; + mHeight = -1; + mSwapInterval = 0; + mAppCreatedShareHandle = mShareHandle != NULL; + mPassThroughResourcesInit = false; +} + +SwapChain11::~SwapChain11() +{ + release(); +} + +void SwapChain11::release() +{ + if (mSwapChain) + { + mSwapChain->Release(); + mSwapChain = NULL; + } + + if (mBackBufferTexture) + { + mBackBufferTexture->Release(); + mBackBufferTexture = NULL; + } + + if (mBackBufferRTView) + { + mBackBufferRTView->Release(); + mBackBufferRTView = NULL; + } + + if (mOffscreenTexture) + { + mOffscreenTexture->Release(); + mOffscreenTexture = NULL; + } + + if (mOffscreenRTView) + { + mOffscreenRTView->Release(); + mOffscreenRTView = NULL; + } + + if (mOffscreenSRView) + { + mOffscreenSRView->Release(); + mOffscreenSRView = NULL; + } + + if (mDepthStencilTexture) + { + mDepthStencilTexture->Release(); + mDepthStencilTexture = NULL; + } + + if (mDepthStencilDSView) + { + mDepthStencilDSView->Release(); + mDepthStencilDSView = NULL; + } + + if (mQuadVB) + { + mQuadVB->Release(); + mQuadVB = NULL; + } + + if (mPassThroughSampler) + { + mPassThroughSampler->Release(); + mPassThroughSampler = NULL; + } + + if (mPassThroughIL) + { + mPassThroughIL->Release(); + mPassThroughIL = NULL; + } + + if (mPassThroughVS) + { + mPassThroughVS->Release(); + mPassThroughVS = NULL; + } + + if (mPassThroughPS) + { + mPassThroughPS->Release(); + mPassThroughPS = NULL; + } + + if (!mAppCreatedShareHandle) + { + mShareHandle = NULL; + } +} + +void SwapChain11::releaseOffscreenTexture() +{ + if (mOffscreenTexture) + { + mOffscreenTexture->Release(); + mOffscreenTexture = NULL; + } + + if (mOffscreenRTView) + { + mOffscreenRTView->Release(); + mOffscreenRTView = NULL; + } + + if (mOffscreenSRView) + { + mOffscreenSRView->Release(); + mOffscreenSRView = NULL; + } + + if (mDepthStencilTexture) + { + mDepthStencilTexture->Release(); + mDepthStencilTexture = NULL; + } + + if (mDepthStencilDSView) + { + mDepthStencilDSView->Release(); + mDepthStencilDSView = NULL; + } +} + +EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHeight) +{ + ID3D11Device *device = mRenderer->getDevice(); + + ASSERT(device != NULL); + + // D3D11 does not allow zero size textures + ASSERT(backbufferWidth >= 1); + ASSERT(backbufferHeight >= 1); + + // Preserve the render target content + ID3D11Texture2D *previousOffscreenTexture = mOffscreenTexture; + if (previousOffscreenTexture) + { + previousOffscreenTexture->AddRef(); + } + const int previousWidth = mWidth; + const int previousHeight = mHeight; + + releaseOffscreenTexture(); + + // If the app passed in a share handle, open the resource + // See EGL_ANGLE_d3d_share_handle_client_buffer + if (mAppCreatedShareHandle) + { + ID3D11Resource *tempResource11; + HRESULT result = device->OpenSharedResource(mShareHandle, __uuidof(ID3D11Resource), (void**)&tempResource11); + + if (FAILED(result)) + { + ERR("Failed to open the swap chain pbuffer share handle: %08lX", result); + release(); + return EGL_BAD_PARAMETER; + } + + result = tempResource11->QueryInterface(__uuidof(ID3D11Texture2D), (void**)&mOffscreenTexture); + tempResource11->Release(); + + if (FAILED(result)) + { + ERR("Failed to query texture2d interface in pbuffer share handle: %08lX", result); + release(); + return EGL_BAD_PARAMETER; + } + + // Validate offscreen texture parameters + D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; + mOffscreenTexture->GetDesc(&offscreenTextureDesc); + + if (offscreenTextureDesc.Width != (UINT)backbufferWidth + || offscreenTextureDesc.Height != (UINT)backbufferHeight + || offscreenTextureDesc.Format != gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat) + || offscreenTextureDesc.MipLevels != 1 + || offscreenTextureDesc.ArraySize != 1) + { + ERR("Invalid texture parameters in the shared offscreen texture pbuffer"); + release(); + return EGL_BAD_PARAMETER; + } + } + else + { + const bool useSharedResource = !mWindow && mRenderer->getShareHandleSupport(); + + D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; + offscreenTextureDesc.Width = backbufferWidth; + offscreenTextureDesc.Height = backbufferHeight; + offscreenTextureDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat); + offscreenTextureDesc.MipLevels = 1; + offscreenTextureDesc.ArraySize = 1; + offscreenTextureDesc.SampleDesc.Count = 1; + offscreenTextureDesc.SampleDesc.Quality = 0; + offscreenTextureDesc.Usage = D3D11_USAGE_DEFAULT; + offscreenTextureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; + offscreenTextureDesc.CPUAccessFlags = 0; + offscreenTextureDesc.MiscFlags = useSharedResource ? D3D11_RESOURCE_MISC_SHARED : 0; + + HRESULT result = device->CreateTexture2D(&offscreenTextureDesc, NULL, &mOffscreenTexture); + + if (FAILED(result)) + { + ERR("Could not create offscreen texture: %08lX", result); + release(); + + if (d3d11::isDeviceLostError(result)) + { + return EGL_CONTEXT_LOST; + } + else + { + return EGL_BAD_ALLOC; + } + } + + d3d11::SetDebugName(mOffscreenTexture, "Offscreen texture"); + + // EGL_ANGLE_surface_d3d_texture_2d_share_handle requires that we store a share handle for the client + if (useSharedResource) + { + IDXGIResource *offscreenTextureResource = NULL; + result = mOffscreenTexture->QueryInterface(__uuidof(IDXGIResource), (void**)&offscreenTextureResource); + + // Fall back to no share handle on failure + if (FAILED(result)) + { + ERR("Could not query offscreen texture resource: %08lX", result); + } + else + { + result = offscreenTextureResource->GetSharedHandle(&mShareHandle); + + if (FAILED(result)) + { + mShareHandle = NULL; + ERR("Could not get offscreen texture shared handle: %08lX", result); + } + } + } + } + + HRESULT result = device->CreateRenderTargetView(mOffscreenTexture, NULL, &mOffscreenRTView); + + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mOffscreenRTView, "Offscreen render target"); + + result = device->CreateShaderResourceView(mOffscreenTexture, NULL, &mOffscreenSRView); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mOffscreenSRView, "Offscreen shader resource"); + + if (mDepthBufferFormat != GL_NONE) + { + D3D11_TEXTURE2D_DESC depthStencilDesc = {0}; + depthStencilDesc.Width = backbufferWidth; + depthStencilDesc.Height = backbufferHeight; + depthStencilDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mDepthBufferFormat); + depthStencilDesc.MipLevels = 1; + depthStencilDesc.ArraySize = 1; + depthStencilDesc.SampleDesc.Count = 1; + depthStencilDesc.SampleDesc.Quality = 0; + depthStencilDesc.Usage = D3D11_USAGE_DEFAULT; + depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; + depthStencilDesc.CPUAccessFlags = 0; + depthStencilDesc.MiscFlags = 0; + + result = device->CreateTexture2D(&depthStencilDesc, NULL, &mDepthStencilTexture); + if (FAILED(result)) + { + ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result); + release(); + + if (d3d11::isDeviceLostError(result)) + { + return EGL_CONTEXT_LOST; + } + else + { + return EGL_BAD_ALLOC; + } + } + d3d11::SetDebugName(mDepthStencilTexture, "Depth stencil texture"); + + result = device->CreateDepthStencilView(mDepthStencilTexture, NULL, &mDepthStencilDSView); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mDepthStencilDSView, "Depth stencil view"); + } + + mWidth = backbufferWidth; + mHeight = backbufferHeight; + + if (previousOffscreenTexture != NULL) + { + D3D11_BOX sourceBox = {0}; + sourceBox.left = 0; + sourceBox.right = std::min(previousWidth, mWidth); + sourceBox.top = std::max(previousHeight - mHeight, 0); + sourceBox.bottom = previousHeight; + sourceBox.front = 0; + sourceBox.back = 1; + + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + const int yoffset = std::max(mHeight - previousHeight, 0); + deviceContext->CopySubresourceRegion(mOffscreenTexture, 0, 0, yoffset, 0, previousOffscreenTexture, 0, &sourceBox); + + previousOffscreenTexture->Release(); + + if (mSwapChain) + { + swapRect(0, 0, mWidth, mHeight); + } + } + + return EGL_SUCCESS; +} + +EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) +{ + ID3D11Device *device = mRenderer->getDevice(); + + if (device == NULL) + { + return EGL_BAD_ACCESS; + } + + // Can only call resize if we have already created our swap buffer and resources + ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView); + + if (mBackBufferTexture) + { + mBackBufferTexture->Release(); + mBackBufferTexture = NULL; + } + + if (mBackBufferRTView) + { + mBackBufferRTView->Release(); + mBackBufferRTView = NULL; + } + + // Resize swap chain + DXGI_FORMAT backbufferDXGIFormat = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat); + HRESULT result = mSwapChain->ResizeBuffers(2, backbufferWidth, backbufferHeight, backbufferDXGIFormat, 0); + + if (FAILED(result)) + { + ERR("Error resizing swap chain buffers: 0x%08X", result); + release(); + + if (d3d11::isDeviceLostError(result)) + { + return EGL_CONTEXT_LOST; + } + else + { + return EGL_BAD_ALLOC; + } + } + + result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture); + ASSERT(SUCCEEDED(result)); + if (SUCCEEDED(result)) + { + d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture"); + } + + result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView); + ASSERT(SUCCEEDED(result)); + if (SUCCEEDED(result)) + { + d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target"); + } + + return resetOffscreenTexture(backbufferWidth, backbufferHeight); +} + +EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval) +{ + ID3D11Device *device = mRenderer->getDevice(); + + if (device == NULL) + { + return EGL_BAD_ACCESS; + } + + // Release specific resources to free up memory for the new render target, while the + // old render target still exists for the purpose of preserving its contents. + if (mSwapChain) + { + mSwapChain->Release(); + mSwapChain = NULL; + } + + if (mBackBufferTexture) + { + mBackBufferTexture->Release(); + mBackBufferTexture = NULL; + } + + if (mBackBufferRTView) + { + mBackBufferRTView->Release(); + mBackBufferRTView = NULL; + } + + mSwapInterval = static_cast(swapInterval); + if (mSwapInterval > 4) + { + // IDXGISwapChain::Present documentation states that valid sync intervals are in the [0,4] range + return EGL_BAD_PARAMETER; + } + + // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains + if (backbufferWidth < 1 || backbufferHeight < 1) + { + releaseOffscreenTexture(); + return EGL_SUCCESS; + } + + if (mWindow) + { + // We cannot create a swap chain for an HWND that is owned by a different process + DWORD currentProcessId = GetCurrentProcessId(); + DWORD wndProcessId; + GetWindowThreadProcessId(mWindow, &wndProcessId); + + if (currentProcessId != wndProcessId) + { + ERR("Could not create swap chain, window owned by different process"); + release(); + return EGL_BAD_NATIVE_WINDOW; + } + + IDXGIFactory *factory = mRenderer->getDxgiFactory(); + + DXGI_SWAP_CHAIN_DESC swapChainDesc = {0}; + swapChainDesc.BufferCount = 2; + swapChainDesc.BufferDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat); + swapChainDesc.BufferDesc.Width = backbufferWidth; + swapChainDesc.BufferDesc.Height = backbufferHeight; + swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; + swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; + swapChainDesc.BufferDesc.RefreshRate.Numerator = 0; + swapChainDesc.BufferDesc.RefreshRate.Denominator = 1; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.Flags = 0; + swapChainDesc.OutputWindow = mWindow; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Windowed = TRUE; + + HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, &mSwapChain); + + if (FAILED(result)) + { + ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result); + release(); + + if (d3d11::isDeviceLostError(result)) + { + return EGL_CONTEXT_LOST; + } + else + { + return EGL_BAD_ALLOC; + } + } + + result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture"); + + result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target"); + } + + // If we are resizing the swap chain, we don't wish to recreate all the static resources + if (!mPassThroughResourcesInit) + { + mPassThroughResourcesInit = true; + initPassThroughResources(); + } + + return resetOffscreenTexture(backbufferWidth, backbufferHeight); +} + +void SwapChain11::initPassThroughResources() +{ + ID3D11Device *device = mRenderer->getDevice(); + + ASSERT(device != NULL); + + // Make sure our resources are all not allocated, when we create + ASSERT(mQuadVB == NULL && mPassThroughSampler == NULL); + ASSERT(mPassThroughIL == NULL && mPassThroughVS == NULL && mPassThroughPS == NULL); + + D3D11_BUFFER_DESC vbDesc; + vbDesc.ByteWidth = sizeof(d3d11::PositionTexCoordVertex) * 4; + vbDesc.Usage = D3D11_USAGE_DYNAMIC; + vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + vbDesc.MiscFlags = 0; + vbDesc.StructureByteStride = 0; + + HRESULT result = device->CreateBuffer(&vbDesc, NULL, &mQuadVB); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mQuadVB, "Swap chain quad vertex buffer"); + + D3D11_SAMPLER_DESC samplerDesc; + samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; + samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; + samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; + samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; + samplerDesc.MipLODBias = 0.0f; + samplerDesc.MaxAnisotropy = 0; + samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; + samplerDesc.BorderColor[0] = 0.0f; + samplerDesc.BorderColor[1] = 0.0f; + samplerDesc.BorderColor[2] = 0.0f; + samplerDesc.BorderColor[3] = 0.0f; + samplerDesc.MinLOD = 0; + samplerDesc.MaxLOD = D3D11_FLOAT32_MAX; + + result = device->CreateSamplerState(&samplerDesc, &mPassThroughSampler); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mPassThroughSampler, "Swap chain pass through sampler"); + + D3D11_INPUT_ELEMENT_DESC quadLayout[] = + { + { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }; + + result = device->CreateInputLayout(quadLayout, 2, g_VS_Passthrough, sizeof(g_VS_Passthrough), &mPassThroughIL); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mPassThroughIL, "Swap chain pass through layout"); + + result = device->CreateVertexShader(g_VS_Passthrough, sizeof(g_VS_Passthrough), NULL, &mPassThroughVS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mPassThroughVS, "Swap chain pass through vertex shader"); + + result = device->CreatePixelShader(g_PS_PassthroughRGBA, sizeof(g_PS_PassthroughRGBA), NULL, &mPassThroughPS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mPassThroughPS, "Swap chain pass through pixel shader"); +} + +// parameters should be validated/clamped by caller +EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) +{ + if (!mSwapChain) + { + return EGL_SUCCESS; + } + + ID3D11Device *device = mRenderer->getDevice(); + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + // Set vertices + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT result = deviceContext->Map(mQuadVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + return EGL_BAD_ACCESS; + } + + d3d11::PositionTexCoordVertex *vertices = static_cast(mappedResource.pData); + + // Create a quad in homogeneous coordinates + float x1 = (x / float(mWidth)) * 2.0f - 1.0f; + float y1 = (y / float(mHeight)) * 2.0f - 1.0f; + float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f; + float y2 = ((y + height) / float(mHeight)) * 2.0f - 1.0f; + + float u1 = x / float(mWidth); + float v1 = y / float(mHeight); + float u2 = (x + width) / float(mWidth); + float v2 = (y + height) / float(mHeight); + + d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v1); + d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2); + d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1); + d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v2); + + deviceContext->Unmap(mQuadVB, 0); + + static UINT stride = sizeof(d3d11::PositionTexCoordVertex); + static UINT startIdx = 0; + deviceContext->IASetVertexBuffers(0, 1, &mQuadVB, &stride, &startIdx); + + // Apply state + deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF); + + static const float blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; + deviceContext->OMSetBlendState(NULL, blendFactor, 0xFFFFFFF); + + deviceContext->RSSetState(NULL); + + // Apply shaders + deviceContext->IASetInputLayout(mPassThroughIL); + deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + deviceContext->VSSetShader(mPassThroughVS, NULL, 0); + deviceContext->PSSetShader(mPassThroughPS, NULL, 0); + deviceContext->GSSetShader(NULL, NULL, 0); + + // Apply render targets + mRenderer->setOneTimeRenderTarget(mBackBufferRTView); + + // Set the viewport + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; + viewport.Width = mWidth; + viewport.Height = mHeight; + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + deviceContext->RSSetViewports(1, &viewport); + + // Apply textures + deviceContext->PSSetShaderResources(0, 1, &mOffscreenSRView); + deviceContext->PSSetSamplers(0, 1, &mPassThroughSampler); + + // Draw + deviceContext->Draw(4, 0); + result = mSwapChain->Present(mSwapInterval, 0); + + if (result == DXGI_ERROR_DEVICE_REMOVED) + { + HRESULT removedReason = device->GetDeviceRemovedReason(); + ERR("Present failed: the D3D11 device was removed: 0x%08X", removedReason); + return EGL_CONTEXT_LOST; + } + else if (result == DXGI_ERROR_DEVICE_RESET) + { + ERR("Present failed: the D3D11 device was reset from a bad command."); + return EGL_CONTEXT_LOST; + } + else if (FAILED(result)) + { + ERR("Present failed with error code 0x%08X", result); + } + + // Unbind + static ID3D11ShaderResourceView *const nullSRV = NULL; + deviceContext->PSSetShaderResources(0, 1, &nullSRV); + + mRenderer->unapplyRenderTargets(); + mRenderer->markAllStateDirty(); + + return EGL_SUCCESS; +} + +// Increments refcount on texture. +// caller must Release() the returned texture +ID3D11Texture2D *SwapChain11::getOffscreenTexture() +{ + if (mOffscreenTexture) + { + mOffscreenTexture->AddRef(); + } + + return mOffscreenTexture; +} + +// Increments refcount on view. +// caller must Release() the returned view +ID3D11RenderTargetView *SwapChain11::getRenderTarget() +{ + if (mOffscreenRTView) + { + mOffscreenRTView->AddRef(); + } + + return mOffscreenRTView; +} + +// Increments refcount on view. +// caller must Release() the returned view +ID3D11ShaderResourceView *SwapChain11::getRenderTargetShaderResource() +{ + if (mOffscreenSRView) + { + mOffscreenSRView->AddRef(); + } + + return mOffscreenSRView; +} + +// Increments refcount on view. +// caller must Release() the returned view +ID3D11DepthStencilView *SwapChain11::getDepthStencil() +{ + if (mDepthStencilDSView) + { + mDepthStencilDSView->AddRef(); + } + + return mDepthStencilDSView; +} + +ID3D11Texture2D *SwapChain11::getDepthStencilTexture() +{ + if (mDepthStencilTexture) + { + mDepthStencilTexture->AddRef(); + } + + return mDepthStencilTexture; +} + +SwapChain11 *SwapChain11::makeSwapChain11(SwapChain *swapChain) +{ + ASSERT(HAS_DYNAMIC_TYPE(rx::SwapChain11*, swapChain)); + return static_cast(swapChain); +} + +void SwapChain11::recreate() +{ + // possibly should use this method instead of reset +} + +} diff --git a/gfx/angle/src/libGLESv2/renderer/SwapChain11.h b/gfx/angle/src/libGLESv2/renderer/SwapChain11.h new file mode 100644 index 000000000000..800104602e35 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/SwapChain11.h @@ -0,0 +1,78 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// SwapChain11.h: Defines a back-end specific class for the D3D11 swap chain. + +#ifndef LIBGLESV2_RENDERER_SWAPCHAIN11_H_ +#define LIBGLESV2_RENDERER_SWAPCHAIN11_H_ + +#include "common/angleutils.h" +#include "libGLESv2/renderer/SwapChain.h" + +namespace rx +{ +class Renderer11; + +class SwapChain11 : public SwapChain +{ + public: + SwapChain11(Renderer11 *renderer, HWND window, HANDLE shareHandle, + GLenum backBufferFormat, GLenum depthBufferFormat); + virtual ~SwapChain11(); + + EGLint resize(EGLint backbufferWidth, EGLint backbufferHeight); + virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval); + virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height); + virtual void recreate(); + + virtual ID3D11Texture2D *getOffscreenTexture(); + virtual ID3D11RenderTargetView *getRenderTarget(); + virtual ID3D11ShaderResourceView *getRenderTargetShaderResource(); + + virtual ID3D11Texture2D *getDepthStencilTexture(); + virtual ID3D11DepthStencilView *getDepthStencil(); + + EGLint getWidth() const { return mWidth; } + EGLint getHeight() const { return mHeight; } + + static SwapChain11 *makeSwapChain11(SwapChain *swapChain); + + private: + DISALLOW_COPY_AND_ASSIGN(SwapChain11); + + void release(); + void initPassThroughResources(); + void releaseOffscreenTexture(); + EGLint resetOffscreenTexture(int backbufferWidth, int backbufferHeight); + + Renderer11 *mRenderer; + EGLint mHeight; + EGLint mWidth; + bool mAppCreatedShareHandle; + unsigned int mSwapInterval; + bool mPassThroughResourcesInit; + + IDXGISwapChain *mSwapChain; + + ID3D11Texture2D *mBackBufferTexture; + ID3D11RenderTargetView *mBackBufferRTView; + + ID3D11Texture2D *mOffscreenTexture; + ID3D11RenderTargetView *mOffscreenRTView; + ID3D11ShaderResourceView *mOffscreenSRView; + + ID3D11Texture2D *mDepthStencilTexture; + ID3D11DepthStencilView *mDepthStencilDSView; + + ID3D11Buffer *mQuadVB; + ID3D11SamplerState *mPassThroughSampler; + ID3D11InputLayout *mPassThroughIL; + ID3D11VertexShader *mPassThroughVS; + ID3D11PixelShader *mPassThroughPS; +}; + +} +#endif // LIBGLESV2_RENDERER_SWAPCHAIN11_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/SwapChain9.cpp b/gfx/angle/src/libGLESv2/renderer/SwapChain9.cpp new file mode 100644 index 000000000000..0324d0199be1 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/SwapChain9.cpp @@ -0,0 +1,434 @@ +#include "precompiled.h" +// +// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// SwapChain9.cpp: Implements a back-end specific class for the D3D9 swap chain. + +#include "libGLESv2/renderer/SwapChain9.h" +#include "libGLESv2/renderer/renderer9_utils.h" +#include "libGLESv2/renderer/Renderer9.h" + +namespace rx +{ + +SwapChain9::SwapChain9(Renderer9 *renderer, HWND window, HANDLE shareHandle, + GLenum backBufferFormat, GLenum depthBufferFormat) + : mRenderer(renderer), SwapChain(window, shareHandle, backBufferFormat, depthBufferFormat) +{ + mSwapChain = NULL; + mBackBuffer = NULL; + mDepthStencil = NULL; + mRenderTarget = NULL; + mOffscreenTexture = NULL; + mWidth = -1; + mHeight = -1; + mSwapInterval = -1; +} + +SwapChain9::~SwapChain9() +{ + release(); +} + +void SwapChain9::release() +{ + if (mSwapChain) + { + mSwapChain->Release(); + mSwapChain = NULL; + } + + if (mBackBuffer) + { + mBackBuffer->Release(); + mBackBuffer = NULL; + } + + if (mDepthStencil) + { + mDepthStencil->Release(); + mDepthStencil = NULL; + } + + if (mRenderTarget) + { + mRenderTarget->Release(); + mRenderTarget = NULL; + } + + if (mOffscreenTexture) + { + mOffscreenTexture->Release(); + mOffscreenTexture = NULL; + } + + if (mWindow) + mShareHandle = NULL; +} + +static DWORD convertInterval(EGLint interval) +{ + switch(interval) + { + case 0: return D3DPRESENT_INTERVAL_IMMEDIATE; + case 1: return D3DPRESENT_INTERVAL_ONE; + case 2: return D3DPRESENT_INTERVAL_TWO; + case 3: return D3DPRESENT_INTERVAL_THREE; + case 4: return D3DPRESENT_INTERVAL_FOUR; + default: UNREACHABLE(); + } + + return D3DPRESENT_INTERVAL_DEFAULT; +} + +EGLint SwapChain9::resize(int backbufferWidth, int backbufferHeight) +{ + // D3D9 does not support resizing swap chains without recreating them + return reset(backbufferWidth, backbufferHeight, mSwapInterval); +} + +EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval) +{ + IDirect3DDevice9 *device = mRenderer->getDevice(); + + if (device == NULL) + { + return EGL_BAD_ACCESS; + } + + // Evict all non-render target textures to system memory and release all resources + // before reallocating them to free up as much video memory as possible. + device->EvictManagedResources(); + + HRESULT result; + + // Release specific resources to free up memory for the new render target, while the + // old render target still exists for the purpose of preserving its contents. + if (mSwapChain) + { + mSwapChain->Release(); + mSwapChain = NULL; + } + + if (mBackBuffer) + { + mBackBuffer->Release(); + mBackBuffer = NULL; + } + + if (mOffscreenTexture) + { + mOffscreenTexture->Release(); + mOffscreenTexture = NULL; + } + + if (mDepthStencil) + { + mDepthStencil->Release(); + mDepthStencil = NULL; + } + + HANDLE *pShareHandle = NULL; + if (!mWindow && mRenderer->getShareHandleSupport()) + { + pShareHandle = &mShareHandle; + } + + result = device->CreateTexture(backbufferWidth, backbufferHeight, 1, D3DUSAGE_RENDERTARGET, + gl_d3d9::ConvertRenderbufferFormat(mBackBufferFormat), D3DPOOL_DEFAULT, + &mOffscreenTexture, pShareHandle); + if (FAILED(result)) + { + ERR("Could not create offscreen texture: %08lX", result); + release(); + + if (d3d9::isDeviceLostError(result)) + { + return EGL_CONTEXT_LOST; + } + else + { + return EGL_BAD_ALLOC; + } + } + + IDirect3DSurface9 *oldRenderTarget = mRenderTarget; + + result = mOffscreenTexture->GetSurfaceLevel(0, &mRenderTarget); + ASSERT(SUCCEEDED(result)); + + if (oldRenderTarget) + { + RECT rect = + { + 0, 0, + mWidth, mHeight + }; + + if (rect.right > static_cast(backbufferWidth)) + { + rect.right = backbufferWidth; + } + + if (rect.bottom > static_cast(backbufferHeight)) + { + rect.bottom = backbufferHeight; + } + + mRenderer->endScene(); + + result = device->StretchRect(oldRenderTarget, &rect, mRenderTarget, &rect, D3DTEXF_NONE); + ASSERT(SUCCEEDED(result)); + + oldRenderTarget->Release(); + } + + if (mWindow) + { + D3DPRESENT_PARAMETERS presentParameters = {0}; + presentParameters.AutoDepthStencilFormat = gl_d3d9::ConvertRenderbufferFormat(mDepthBufferFormat); + presentParameters.BackBufferCount = 1; + presentParameters.BackBufferFormat = gl_d3d9::ConvertRenderbufferFormat(mBackBufferFormat); + presentParameters.EnableAutoDepthStencil = FALSE; + presentParameters.Flags = 0; + presentParameters.hDeviceWindow = mWindow; + presentParameters.MultiSampleQuality = 0; // FIXME: Unimplemented + presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE; // FIXME: Unimplemented + presentParameters.PresentationInterval = convertInterval(swapInterval); + presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD; + presentParameters.Windowed = TRUE; + presentParameters.BackBufferWidth = backbufferWidth; + presentParameters.BackBufferHeight = backbufferHeight; + + // http://crbug.com/140239 + // http://crbug.com/143434 + // + // Some AMD/Intel switchable systems / drivers appear to round swap chain surfaces to a multiple of 64 pixels in width + // when using the integrated Intel. This rounds the width up rather than down. + // + // Some non-switchable AMD GPUs / drivers do not respect the source rectangle to Present. Therefore, when the vendor ID + // is not Intel, the back buffer width must be exactly the same width as the window or horizontal scaling will occur. + if (mRenderer->getAdapterVendor() == VENDOR_ID_INTEL) + { + presentParameters.BackBufferWidth = (presentParameters.BackBufferWidth + 63) / 64 * 64; + } + + result = device->CreateAdditionalSwapChain(&presentParameters, &mSwapChain); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL || result == D3DERR_DEVICELOST); + + ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result); + release(); + + if (d3d9::isDeviceLostError(result)) + { + return EGL_CONTEXT_LOST; + } + else + { + return EGL_BAD_ALLOC; + } + } + + result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer); + ASSERT(SUCCEEDED(result)); + InvalidateRect(mWindow, NULL, FALSE); + } + + if (mDepthBufferFormat != GL_NONE) + { + result = device->CreateDepthStencilSurface(backbufferWidth, backbufferHeight, + gl_d3d9::ConvertRenderbufferFormat(mDepthBufferFormat), + D3DMULTISAMPLE_NONE, 0, FALSE, &mDepthStencil, NULL); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL); + + ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result); + release(); + + if (d3d9::isDeviceLostError(result)) + { + return EGL_CONTEXT_LOST; + } + else + { + return EGL_BAD_ALLOC; + } + } + } + + mWidth = backbufferWidth; + mHeight = backbufferHeight; + mSwapInterval = swapInterval; + + return EGL_SUCCESS; +} + +// parameters should be validated/clamped by caller +EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) +{ + if (!mSwapChain) + { + return EGL_SUCCESS; + } + + IDirect3DDevice9 *device = mRenderer->getDevice(); + + // Disable all pipeline operations + device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); + device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); + device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); + device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + device->SetRenderState(D3DRS_STENCILENABLE, FALSE); + device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); + device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED); + device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE); + device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); + device->SetPixelShader(NULL); + device->SetVertexShader(NULL); + + device->SetRenderTarget(0, mBackBuffer); + device->SetDepthStencilSurface(NULL); + + device->SetTexture(0, mOffscreenTexture); + device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); + device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); + device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); + device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); + device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); + device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1); + + D3DVIEWPORT9 viewport = {0, 0, mWidth, mHeight, 0.0f, 1.0f}; + device->SetViewport(&viewport); + + float x1 = x - 0.5f; + float y1 = (mHeight - y - height) - 0.5f; + float x2 = (x + width) - 0.5f; + float y2 = (mHeight - y) - 0.5f; + + float u1 = x / float(mWidth); + float v1 = y / float(mHeight); + float u2 = (x + width) / float(mWidth); + float v2 = (y + height) / float(mHeight); + + float quad[4][6] = {{x1, y1, 0.0f, 1.0f, u1, v2}, + {x2, y1, 0.0f, 1.0f, u2, v2}, + {x2, y2, 0.0f, 1.0f, u2, v1}, + {x1, y2, 0.0f, 1.0f, u1, v1}}; // x, y, z, rhw, u, v + + mRenderer->startScene(); + device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, 6 * sizeof(float)); + mRenderer->endScene(); + + device->SetTexture(0, NULL); + + RECT rect = + { + x, mHeight - y - height, + x + width, mHeight - y + }; + + HRESULT result = mSwapChain->Present(&rect, &rect, NULL, NULL, 0); + + mRenderer->markAllStateDirty(); + + if (d3d9::isDeviceLostError(result)) + { + return EGL_CONTEXT_LOST; + } + + if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DRIVERINTERNALERROR) + { + return EGL_BAD_ALLOC; + } + + ASSERT(SUCCEEDED(result)); + + return EGL_SUCCESS; +} + +// Increments refcount on surface. +// caller must Release() the returned surface +IDirect3DSurface9 *SwapChain9::getRenderTarget() +{ + if (mRenderTarget) + { + mRenderTarget->AddRef(); + } + + return mRenderTarget; +} + +// Increments refcount on surface. +// caller must Release() the returned surface +IDirect3DSurface9 *SwapChain9::getDepthStencil() +{ + if (mDepthStencil) + { + mDepthStencil->AddRef(); + } + + return mDepthStencil; +} + +// Increments refcount on texture. +// caller must Release() the returned texture +IDirect3DTexture9 *SwapChain9::getOffscreenTexture() +{ + if (mOffscreenTexture) + { + mOffscreenTexture->AddRef(); + } + + return mOffscreenTexture; +} + +SwapChain9 *SwapChain9::makeSwapChain9(SwapChain *swapChain) +{ + ASSERT(HAS_DYNAMIC_TYPE(rx::SwapChain9*, swapChain)); + return static_cast(swapChain); +} + +void SwapChain9::recreate() +{ + if (!mSwapChain) + { + return; + } + + IDirect3DDevice9 *device = mRenderer->getDevice(); + if (device == NULL) + { + return; + } + + D3DPRESENT_PARAMETERS presentParameters; + HRESULT result = mSwapChain->GetPresentParameters(&presentParameters); + ASSERT(SUCCEEDED(result)); + + IDirect3DSwapChain9* newSwapChain = NULL; + result = device->CreateAdditionalSwapChain(&presentParameters, &newSwapChain); + if (FAILED(result)) + { + return; + } + + mSwapChain->Release(); + mSwapChain = newSwapChain; + + mBackBuffer->Release(); + result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer); + ASSERT(SUCCEEDED(result)); +} + +} diff --git a/gfx/angle/src/libGLESv2/renderer/SwapChain9.h b/gfx/angle/src/libGLESv2/renderer/SwapChain9.h new file mode 100644 index 000000000000..16a62bd86f6a --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/SwapChain9.h @@ -0,0 +1,55 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// SwapChain9.h: Defines a back-end specific class for the D3D9 swap chain. + +#ifndef LIBGLESV2_RENDERER_SWAPCHAIN9_H_ +#define LIBGLESV2_RENDERER_SWAPCHAIN9_H_ + +#include "common/angleutils.h" +#include "libGLESv2/renderer/SwapChain.h" + +namespace rx +{ +class Renderer9; + +class SwapChain9 : public SwapChain +{ + public: + SwapChain9(Renderer9 *renderer, HWND window, HANDLE shareHandle, + GLenum backBufferFormat, GLenum depthBufferFormat); + virtual ~SwapChain9(); + + EGLint resize(EGLint backbufferWidth, EGLint backbufferHeight); + virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval); + virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height); + virtual void recreate(); + + virtual IDirect3DSurface9 *getRenderTarget(); + virtual IDirect3DSurface9 *getDepthStencil(); + virtual IDirect3DTexture9 *getOffscreenTexture(); + + static SwapChain9 *makeSwapChain9(SwapChain *swapChain); + + private: + DISALLOW_COPY_AND_ASSIGN(SwapChain9); + + void release(); + + Renderer9 *mRenderer; + EGLint mHeight; + EGLint mWidth; + EGLint mSwapInterval; + + IDirect3DSwapChain9 *mSwapChain; + IDirect3DSurface9 *mBackBuffer; + IDirect3DSurface9 *mRenderTarget; + IDirect3DSurface9 *mDepthStencil; + IDirect3DTexture9* mOffscreenTexture; +}; + +} +#endif // LIBGLESV2_RENDERER_SWAPCHAIN9_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/TextureStorage.cpp b/gfx/angle/src/libGLESv2/renderer/TextureStorage.cpp new file mode 100644 index 000000000000..00b316f1cc5d --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/TextureStorage.cpp @@ -0,0 +1,122 @@ +#include "precompiled.h" +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// TextureStorage.cpp: Implements the abstract rx::TextureStorageInterface class and its concrete derived +// classes TextureStorageInterface2D and TextureStorageInterfaceCube, which act as the interface to the +// GPU-side texture. + +#include "libGLESv2/renderer/TextureStorage.h" +#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/Renderbuffer.h" +#include "libGLESv2/Texture.h" + +#include "common/debug.h" + +namespace rx +{ +unsigned int TextureStorageInterface::mCurrentTextureSerial = 1; + +TextureStorageInterface::TextureStorageInterface() + : mTextureSerial(issueTextureSerial()), + mInstance(NULL) +{ +} + +TextureStorageInterface::~TextureStorageInterface() +{ + delete mInstance; +} + +bool TextureStorageInterface::isRenderTarget() const +{ + return mInstance->isRenderTarget(); +} + + +bool TextureStorageInterface::isManaged() const +{ + return mInstance->isManaged(); +} + +unsigned int TextureStorageInterface::getTextureSerial() const +{ + return mTextureSerial; +} + +unsigned int TextureStorageInterface::issueTextureSerial() +{ + return mCurrentTextureSerial++; +} + +int TextureStorageInterface::getLodOffset() const +{ + return mInstance->getLodOffset(); +} + + +int TextureStorageInterface::levelCount() +{ + return mInstance->levelCount(); +} + +TextureStorageInterface2D::TextureStorageInterface2D(Renderer *renderer, SwapChain *swapchain) + : mRenderTargetSerial(gl::RenderbufferStorage::issueSerial()) +{ + mInstance = renderer->createTextureStorage2D(swapchain); +} + +TextureStorageInterface2D::TextureStorageInterface2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height) + : mRenderTargetSerial(gl::RenderbufferStorage::issueSerial()) +{ + mInstance = renderer->createTextureStorage2D(levels, internalformat, usage, forceRenderable, width, height); +} + +TextureStorageInterface2D::~TextureStorageInterface2D() +{ +} + +RenderTarget *TextureStorageInterface2D::getRenderTarget() const +{ + return mInstance->getRenderTarget(); +} + +void TextureStorageInterface2D::generateMipmap(int level) +{ + mInstance->generateMipmap(level); +} + +unsigned int TextureStorageInterface2D::getRenderTargetSerial(GLenum target) const +{ + return mRenderTargetSerial; +} + +TextureStorageInterfaceCube::TextureStorageInterfaceCube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size) + : mFirstRenderTargetSerial(gl::RenderbufferStorage::issueCubeSerials()) +{ + mInstance = renderer->createTextureStorageCube(levels, internalformat, usage, forceRenderable, size); +} + +TextureStorageInterfaceCube::~TextureStorageInterfaceCube() +{ +} + +RenderTarget *TextureStorageInterfaceCube::getRenderTarget(GLenum faceTarget) const +{ + return mInstance->getRenderTarget(faceTarget); +} + +void TextureStorageInterfaceCube::generateMipmap(int face, int level) +{ + mInstance->generateMipmap(face, level); +} + +unsigned int TextureStorageInterfaceCube::getRenderTargetSerial(GLenum target) const +{ + return mFirstRenderTargetSerial + gl::TextureCubeMap::faceIndex(target); +} + +} \ No newline at end of file diff --git a/gfx/angle/src/libGLESv2/renderer/TextureStorage.h b/gfx/angle/src/libGLESv2/renderer/TextureStorage.h new file mode 100644 index 000000000000..edddb75f3fc0 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/TextureStorage.h @@ -0,0 +1,110 @@ +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// TextureStorage.h: Defines the abstract rx::TextureStorageInterface class and its concrete derived +// classes TextureStorageInterface2D and TextureStorageInterfaceCube, which act as the interface to the +// GPU-side texture. + +#ifndef LIBGLESV2_RENDERER_TEXTURESTORAGE_H_ +#define LIBGLESV2_RENDERER_TEXTURESTORAGE_H_ + +#include "common/debug.h" + +namespace rx +{ +class Renderer; +class SwapChain; +class RenderTarget; +class Blit; + +class TextureStorage +{ + public: + TextureStorage() {}; + virtual ~TextureStorage() {}; + + virtual int getLodOffset() const = 0; + virtual bool isRenderTarget() const = 0; + virtual bool isManaged() const = 0; + virtual int levelCount() = 0; + + virtual RenderTarget *getRenderTarget() = 0; + virtual RenderTarget *getRenderTarget(GLenum faceTarget) = 0; + virtual void generateMipmap(int level) = 0; + virtual void generateMipmap(int face, int level) = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(TextureStorage); + +}; + +class TextureStorageInterface +{ + public: + TextureStorageInterface(); + virtual ~TextureStorageInterface(); + + TextureStorage *getStorageInstance() { return mInstance; } + + unsigned int getTextureSerial() const; + virtual unsigned int getRenderTargetSerial(GLenum target) const = 0; + + virtual int getLodOffset() const; + virtual bool isRenderTarget() const; + virtual bool isManaged() const; + virtual int levelCount(); + + protected: + TextureStorage *mInstance; + + private: + DISALLOW_COPY_AND_ASSIGN(TextureStorageInterface); + + const unsigned int mTextureSerial; + static unsigned int issueTextureSerial(); + + static unsigned int mCurrentTextureSerial; +}; + +class TextureStorageInterface2D : public TextureStorageInterface +{ + public: + TextureStorageInterface2D(Renderer *renderer, SwapChain *swapchain); + TextureStorageInterface2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height); + virtual ~TextureStorageInterface2D(); + + void generateMipmap(int level); + RenderTarget *getRenderTarget() const; + + virtual unsigned int getRenderTargetSerial(GLenum target) const; + + private: + DISALLOW_COPY_AND_ASSIGN(TextureStorageInterface2D); + + const unsigned int mRenderTargetSerial; +}; + +class TextureStorageInterfaceCube : public TextureStorageInterface +{ + public: + TextureStorageInterfaceCube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size); + virtual ~TextureStorageInterfaceCube(); + + void generateMipmap(int face, int level); + RenderTarget *getRenderTarget(GLenum faceTarget) const; + + virtual unsigned int getRenderTargetSerial(GLenum target) const; + + private: + DISALLOW_COPY_AND_ASSIGN(TextureStorageInterfaceCube); + + const unsigned int mFirstRenderTargetSerial; +}; + +} + +#endif // LIBGLESV2_RENDERER_TEXTURESTORAGE_H_ + diff --git a/gfx/angle/src/libGLESv2/renderer/TextureStorage11.cpp b/gfx/angle/src/libGLESv2/renderer/TextureStorage11.cpp new file mode 100644 index 000000000000..408b48ebab7a --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/TextureStorage11.cpp @@ -0,0 +1,667 @@ +#include "precompiled.h" +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// TextureStorage11.cpp: Implements the abstract rx::TextureStorage11 class and its concrete derived +// classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 texture. + +#include "libGLESv2/renderer/TextureStorage11.h" + +#include "libGLESv2/renderer/Renderer11.h" +#include "libGLESv2/renderer/RenderTarget11.h" +#include "libGLESv2/renderer/SwapChain11.h" +#include "libGLESv2/renderer/renderer11_utils.h" + +#include "libGLESv2/utilities.h" +#include "libGLESv2/main.h" + +namespace rx +{ + +TextureStorage11::TextureStorage11(Renderer *renderer, UINT bindFlags) + : mBindFlags(bindFlags), + mLodOffset(0), + mMipLevels(0), + mTexture(NULL), + mTextureFormat(DXGI_FORMAT_UNKNOWN), + mShaderResourceFormat(DXGI_FORMAT_UNKNOWN), + mRenderTargetFormat(DXGI_FORMAT_UNKNOWN), + mDepthStencilFormat(DXGI_FORMAT_UNKNOWN), + mSRV(NULL), + mTextureWidth(0), + mTextureHeight(0) +{ + mRenderer = Renderer11::makeRenderer11(renderer); +} + +TextureStorage11::~TextureStorage11() +{ +} + +TextureStorage11 *TextureStorage11::makeTextureStorage11(TextureStorage *storage) +{ + ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11*, storage)); + return static_cast(storage); +} + +DWORD TextureStorage11::GetTextureBindFlags(DXGI_FORMAT format, GLenum glusage, bool forceRenderable) +{ + UINT bindFlags = D3D11_BIND_SHADER_RESOURCE; + + if (d3d11::IsDepthStencilFormat(format)) + { + bindFlags |= D3D11_BIND_DEPTH_STENCIL; + } + else if(forceRenderable || (TextureStorage11::IsTextureFormatRenderable(format) && (glusage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE))) + { + bindFlags |= D3D11_BIND_RENDER_TARGET; + } + return bindFlags; +} + +bool TextureStorage11::IsTextureFormatRenderable(DXGI_FORMAT format) +{ + switch(format) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_A8_UNORM: + case DXGI_FORMAT_R32G32B32A32_FLOAT: + case DXGI_FORMAT_R16G16B16A16_FLOAT: + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_R8_UNORM: + case DXGI_FORMAT_R8G8_UNORM: + case DXGI_FORMAT_R16_FLOAT: + case DXGI_FORMAT_R16G16_FLOAT: + return true; + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_R32G32B32_FLOAT: // not renderable on all devices + return false; + default: + UNREACHABLE(); + return false; + } +} + +UINT TextureStorage11::getBindFlags() const +{ + return mBindFlags; +} + +ID3D11Texture2D *TextureStorage11::getBaseTexture() const +{ + return mTexture; +} + +int TextureStorage11::getLodOffset() const +{ + return mLodOffset; +} + +bool TextureStorage11::isRenderTarget() const +{ + return (mBindFlags & (D3D11_BIND_RENDER_TARGET | D3D11_BIND_DEPTH_STENCIL)) != 0; +} + +bool TextureStorage11::isManaged() const +{ + return false; +} + +int TextureStorage11::levelCount() +{ + int levels = 0; + if (getBaseTexture()) + { + levels = mMipLevels - getLodOffset(); + } + return levels; +} + +UINT TextureStorage11::getSubresourceIndex(int level, int faceIndex) +{ + UINT index = 0; + if (getBaseTexture()) + { + index = D3D11CalcSubresource(level, faceIndex, mMipLevels); + } + return index; +} + +bool TextureStorage11::updateSubresourceLevel(ID3D11Texture2D *srcTexture, unsigned int sourceSubresource, + int level, int face, GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height) +{ + if (srcTexture) + { + // Round up the width and height to the nearest multiple of dimension alignment + unsigned int dimensionAlignment = d3d11::GetTextureFormatDimensionAlignment(mTextureFormat); + width = width + dimensionAlignment - 1 - (width - 1) % dimensionAlignment; + height = height + dimensionAlignment - 1 - (height - 1) % dimensionAlignment; + + D3D11_BOX srcBox; + srcBox.left = xoffset; + srcBox.top = yoffset; + srcBox.right = xoffset + width; + srcBox.bottom = yoffset + height; + srcBox.front = 0; + srcBox.back = 1; + + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + ASSERT(getBaseTexture()); + context->CopySubresourceRegion(getBaseTexture(), getSubresourceIndex(level + mLodOffset, face), + xoffset, yoffset, 0, srcTexture, sourceSubresource, &srcBox); + return true; + } + + return false; +} + +void TextureStorage11::generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest) +{ + if (source && dest) + { + ID3D11ShaderResourceView *sourceSRV = source->getShaderResourceView(); + ID3D11RenderTargetView *destRTV = dest->getRenderTargetView(); + + if (sourceSRV && destRTV) + { + gl::Rectangle sourceArea; + sourceArea.x = 0; + sourceArea.y = 0; + sourceArea.width = source->getWidth(); + sourceArea.height = source->getHeight(); + + gl::Rectangle destArea; + destArea.x = 0; + destArea.y = 0; + destArea.width = dest->getWidth(); + destArea.height = dest->getHeight(); + + mRenderer->copyTexture(sourceSRV, sourceArea, source->getWidth(), source->getHeight(), + destRTV, destArea, dest->getWidth(), dest->getHeight(), + GL_RGBA); + } + } +} + +TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain) + : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE) +{ + mTexture = swapchain->getOffscreenTexture(); + mSRV = swapchain->getRenderTargetShaderResource(); + + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + mRenderTarget[i] = NULL; + } + + D3D11_TEXTURE2D_DESC texDesc; + mTexture->GetDesc(&texDesc); + mMipLevels = texDesc.MipLevels; + mTextureFormat = texDesc.Format; + mTextureWidth = texDesc.Width; + mTextureHeight = texDesc.Height; + + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + mSRV->GetDesc(&srvDesc); + mShaderResourceFormat = srvDesc.Format; + + ID3D11RenderTargetView* offscreenRTV = swapchain->getRenderTarget(); + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + offscreenRTV->GetDesc(&rtvDesc); + mRenderTargetFormat = rtvDesc.Format; + offscreenRTV->Release(); + + mDepthStencilFormat = DXGI_FORMAT_UNKNOWN; +} + +TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height) + : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat), usage, forceRenderable)) +{ + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + mRenderTarget[i] = NULL; + } + + DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat); + if (d3d11::IsDepthStencilFormat(convertedFormat)) + { + mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat); + mShaderResourceFormat = d3d11::GetDepthShaderResourceFormat(convertedFormat); + mDepthStencilFormat = convertedFormat; + mRenderTargetFormat = DXGI_FORMAT_UNKNOWN; + } + else + { + mTextureFormat = convertedFormat; + mShaderResourceFormat = convertedFormat; + mDepthStencilFormat = DXGI_FORMAT_UNKNOWN; + mRenderTargetFormat = convertedFormat; + } + + // if the width or height is not positive this should be treated as an incomplete texture + // we handle that here by skipping the d3d texture creation + if (width > 0 && height > 0) + { + // adjust size if needed for compressed textures + gl::MakeValidSize(false, gl::IsCompressed(internalformat), &width, &height, &mLodOffset); + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE2D_DESC desc; + desc.Width = width; // Compressed texture size constraints? + desc.Height = height; + desc.MipLevels = (levels > 0) ? levels + mLodOffset : 0; + desc.ArraySize = 1; + desc.Format = mTextureFormat; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = getBindFlags(); + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture); + + // this can happen from windows TDR + if (d3d11::isDeviceLostError(result)) + { + mRenderer->notifyDeviceLost(); + gl::error(GL_OUT_OF_MEMORY); + } + else if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + ERR("Creating image failed."); + gl::error(GL_OUT_OF_MEMORY); + } + else + { + mTexture->GetDesc(&desc); + mMipLevels = desc.MipLevels; + mTextureWidth = desc.Width; + mTextureHeight = desc.Height; + } + } +} + +TextureStorage11_2D::~TextureStorage11_2D() +{ + if (mTexture) + { + mTexture->Release(); + mTexture = NULL; + } + + if (mSRV) + { + mSRV->Release(); + mSRV = NULL; + } + + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + delete mRenderTarget[i]; + mRenderTarget[i] = NULL; + } +} + +TextureStorage11_2D *TextureStorage11_2D::makeTextureStorage11_2D(TextureStorage *storage) +{ + ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2D*, storage)); + return static_cast(storage); +} + +RenderTarget *TextureStorage11_2D::getRenderTarget(int level) +{ + if (level >= 0 && level < static_cast(mMipLevels)) + { + if (!mRenderTarget[level]) + { + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result; + + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = mShaderResourceFormat; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + srvDesc.Texture2D.MostDetailedMip = level; + srvDesc.Texture2D.MipLevels = 1; + + ID3D11ShaderResourceView *srv; + result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv); + + if (result == E_OUTOFMEMORY) + { + return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); + } + ASSERT(SUCCEEDED(result)); + + if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) + { + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + rtvDesc.Texture2D.MipSlice = level; + + ID3D11RenderTargetView *rtv; + result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv); + + if (result == E_OUTOFMEMORY) + { + srv->Release(); + return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); + } + ASSERT(SUCCEEDED(result)); + + // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11 + // also needs to keep a reference to the texture. + mTexture->AddRef(); + + mRenderTarget[level] = new RenderTarget11(mRenderer, rtv, mTexture, srv, + std::max(mTextureWidth >> level, 1U), + std::max(mTextureHeight >> level, 1U)); + } + else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN) + { + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; + dsvDesc.Format = mDepthStencilFormat; + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; + dsvDesc.Texture2D.MipSlice = level; + dsvDesc.Flags = 0; + + ID3D11DepthStencilView *dsv; + result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv); + + if (result == E_OUTOFMEMORY) + { + srv->Release(); + return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); + } + ASSERT(SUCCEEDED(result)); + + // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11 + // also needs to keep a reference to the texture. + mTexture->AddRef(); + + mRenderTarget[level] = new RenderTarget11(mRenderer, dsv, mTexture, srv, + std::max(mTextureWidth >> level, 1U), + std::max(mTextureHeight >> level, 1U)); + } + else + { + UNREACHABLE(); + } + } + + return mRenderTarget[level]; + } + else + { + return NULL; + } +} + +ID3D11ShaderResourceView *TextureStorage11_2D::getSRV() +{ + if (!mSRV) + { + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = mShaderResourceFormat; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + srvDesc.Texture2D.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels); + srvDesc.Texture2D.MostDetailedMip = 0; + + HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV); + + if (result == E_OUTOFMEMORY) + { + return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); + } + ASSERT(SUCCEEDED(result)); + } + + return mSRV; +} + +void TextureStorage11_2D::generateMipmap(int level) +{ + RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(level - 1)); + RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(level)); + + generateMipmapLayer(source, dest); +} + +TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size) + : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat), usage, forceRenderable)) +{ + for (unsigned int i = 0; i < 6; i++) + { + for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++) + { + mRenderTarget[i][j] = NULL; + } + } + + DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat); + if (d3d11::IsDepthStencilFormat(convertedFormat)) + { + mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat); + mShaderResourceFormat = d3d11::GetDepthShaderResourceFormat(convertedFormat); + mDepthStencilFormat = convertedFormat; + mRenderTargetFormat = DXGI_FORMAT_UNKNOWN; + } + else + { + mTextureFormat = convertedFormat; + mShaderResourceFormat = convertedFormat; + mDepthStencilFormat = DXGI_FORMAT_UNKNOWN; + mRenderTargetFormat = convertedFormat; + } + + // if the size is not positive this should be treated as an incomplete texture + // we handle that here by skipping the d3d texture creation + if (size > 0) + { + // adjust size if needed for compressed textures + int height = size; + gl::MakeValidSize(false, gl::IsCompressed(internalformat), &size, &height, &mLodOffset); + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE2D_DESC desc; + desc.Width = size; + desc.Height = size; + desc.MipLevels = (levels > 0) ? levels + mLodOffset : 0; + desc.ArraySize = 6; + desc.Format = mTextureFormat; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = getBindFlags(); + desc.CPUAccessFlags = 0; + desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE; + + HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture); + + if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + ERR("Creating image failed."); + gl::error(GL_OUT_OF_MEMORY); + } + else + { + mTexture->GetDesc(&desc); + mMipLevels = desc.MipLevels; + mTextureWidth = desc.Width; + mTextureHeight = desc.Height; + } + } +} + +TextureStorage11_Cube::~TextureStorage11_Cube() +{ + if (mTexture) + { + mTexture->Release(); + mTexture = NULL; + } + + if (mSRV) + { + mSRV->Release(); + mSRV = NULL; + } + + for (unsigned int i = 0; i < 6; i++) + { + for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++) + { + delete mRenderTarget[i][j]; + mRenderTarget[i][j] = NULL; + } + } +} + +TextureStorage11_Cube *TextureStorage11_Cube::makeTextureStorage11_Cube(TextureStorage *storage) +{ + ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_Cube*, storage)); + return static_cast(storage); +} + +RenderTarget *TextureStorage11_Cube::getRenderTarget(GLenum faceTarget, int level) +{ + unsigned int faceIdx = gl::TextureCubeMap::faceIndex(faceTarget); + if (level >= 0 && level < static_cast(mMipLevels)) + { + if (!mRenderTarget[faceIdx][level]) + { + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result; + + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = mShaderResourceFormat; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; + srvDesc.Texture2DArray.MostDetailedMip = level; + srvDesc.Texture2DArray.MipLevels = 1; + srvDesc.Texture2DArray.FirstArraySlice = faceIdx; + srvDesc.Texture2DArray.ArraySize = 1; + + ID3D11ShaderResourceView *srv; + result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv); + + if (result == E_OUTOFMEMORY) + { + return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); + } + ASSERT(SUCCEEDED(result)); + + if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) + { + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; + rtvDesc.Texture2DArray.MipSlice = level; + rtvDesc.Texture2DArray.FirstArraySlice = faceIdx; + rtvDesc.Texture2DArray.ArraySize = 1; + + ID3D11RenderTargetView *rtv; + result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv); + + if (result == E_OUTOFMEMORY) + { + srv->Release(); + return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); + } + ASSERT(SUCCEEDED(result)); + + // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11 + // also needs to keep a reference to the texture. + mTexture->AddRef(); + + mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, rtv, mTexture, srv, + std::max(mTextureWidth >> level, 1U), + std::max(mTextureHeight >> level, 1U)); + } + else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN) + { + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; + dsvDesc.Format = mRenderTargetFormat; + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY; + dsvDesc.Texture2DArray.MipSlice = level; + dsvDesc.Texture2DArray.FirstArraySlice = faceIdx; + dsvDesc.Texture2DArray.ArraySize = 1; + + ID3D11DepthStencilView *dsv; + result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv); + + if (result == E_OUTOFMEMORY) + { + srv->Release(); + return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); + } + ASSERT(SUCCEEDED(result)); + + // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11 + // also needs to keep a reference to the texture. + mTexture->AddRef(); + + mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, dsv, mTexture, srv, + std::max(mTextureWidth >> level, 1U), + std::max(mTextureHeight >> level, 1U)); + } + else + { + UNREACHABLE(); + } + } + + return mRenderTarget[faceIdx][level]; + } + else + { + return NULL; + } +} + +ID3D11ShaderResourceView *TextureStorage11_Cube::getSRV() +{ + if (!mSRV) + { + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = mShaderResourceFormat; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; + srvDesc.TextureCube.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels); + srvDesc.TextureCube.MostDetailedMip = 0; + + HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV); + + if (result == E_OUTOFMEMORY) + { + return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); + } + ASSERT(SUCCEEDED(result)); + } + + return mSRV; +} + +void TextureStorage11_Cube::generateMipmap(int face, int level) +{ + RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level - 1)); + RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level)); + + generateMipmapLayer(source, dest); +} + +} diff --git a/gfx/angle/src/libGLESv2/renderer/TextureStorage11.h b/gfx/angle/src/libGLESv2/renderer/TextureStorage11.h new file mode 100644 index 000000000000..3c5ded05b889 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/TextureStorage11.h @@ -0,0 +1,120 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// TextureStorage11.h: Defines the abstract rx::TextureStorage11 class and its concrete derived +// classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 texture. + +#ifndef LIBGLESV2_RENDERER_TEXTURESTORAGE11_H_ +#define LIBGLESV2_RENDERER_TEXTURESTORAGE11_H_ + +#include "libGLESv2/Texture.h" +#include "libGLESv2/renderer/TextureStorage.h" + +namespace rx +{ +class RenderTarget; +class RenderTarget11; +class Renderer; +class Renderer11; +class SwapChain11; + +class TextureStorage11 : public TextureStorage +{ + public: + TextureStorage11(Renderer *renderer, UINT bindFlags); + virtual ~TextureStorage11(); + + static TextureStorage11 *makeTextureStorage11(TextureStorage *storage); + + static DWORD GetTextureBindFlags(DXGI_FORMAT d3dfmt, GLenum glusage, bool forceRenderable); + static bool IsTextureFormatRenderable(DXGI_FORMAT format); + + UINT getBindFlags() const; + + virtual ID3D11Texture2D *getBaseTexture() const; + virtual ID3D11ShaderResourceView *getSRV() = 0; + virtual RenderTarget *getRenderTarget() { return getRenderTarget(0); } + virtual RenderTarget *getRenderTarget(int level) { return NULL; } + virtual RenderTarget *getRenderTarget(GLenum faceTarget) { return getRenderTarget(faceTarget, 0); } + virtual RenderTarget *getRenderTarget(GLenum faceTarget, int level) { return NULL; } + + virtual void generateMipmap(int level) {}; + virtual void generateMipmap(int face, int level) {}; + + virtual int getLodOffset() const; + virtual bool isRenderTarget() const; + virtual bool isManaged() const; + virtual int levelCount(); + UINT getSubresourceIndex(int level, int faceTarget); + + bool updateSubresourceLevel(ID3D11Texture2D *texture, unsigned int sourceSubresource, int level, + int faceTarget, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); + + protected: + void generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest); + + Renderer11 *mRenderer; + int mLodOffset; + unsigned int mMipLevels; + + ID3D11Texture2D *mTexture; + DXGI_FORMAT mTextureFormat; + DXGI_FORMAT mShaderResourceFormat; + DXGI_FORMAT mRenderTargetFormat; + DXGI_FORMAT mDepthStencilFormat; + unsigned int mTextureWidth; + unsigned int mTextureHeight; + + ID3D11ShaderResourceView *mSRV; + + private: + DISALLOW_COPY_AND_ASSIGN(TextureStorage11); + + const UINT mBindFlags; +}; + +class TextureStorage11_2D : public TextureStorage11 +{ + public: + TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain); + TextureStorage11_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height); + virtual ~TextureStorage11_2D(); + + static TextureStorage11_2D *makeTextureStorage11_2D(TextureStorage *storage); + + virtual ID3D11ShaderResourceView *getSRV(); + virtual RenderTarget *getRenderTarget(int level); + + virtual void generateMipmap(int level); + + private: + DISALLOW_COPY_AND_ASSIGN(TextureStorage11_2D); + + RenderTarget11 *mRenderTarget[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; +}; + +class TextureStorage11_Cube : public TextureStorage11 +{ + public: + TextureStorage11_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size); + virtual ~TextureStorage11_Cube(); + + static TextureStorage11_Cube *makeTextureStorage11_Cube(TextureStorage *storage); + + virtual ID3D11ShaderResourceView *getSRV(); + virtual RenderTarget *getRenderTarget(GLenum faceTarget, int level); + + virtual void generateMipmap(int face, int level); + + private: + DISALLOW_COPY_AND_ASSIGN(TextureStorage11_Cube); + + RenderTarget11 *mRenderTarget[6][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; +}; + +} + +#endif // LIBGLESV2_RENDERER_TEXTURESTORAGE11_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/TextureStorage9.cpp b/gfx/angle/src/libGLESv2/renderer/TextureStorage9.cpp new file mode 100644 index 000000000000..8aa74a7cba1b --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/TextureStorage9.cpp @@ -0,0 +1,328 @@ +#include "precompiled.h" +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// TextureStorage9.cpp: Implements the abstract rx::TextureStorage9 class and its concrete derived +// classes TextureStorage9_2D and TextureStorage9_Cube, which act as the interface to the +// D3D9 texture. + +#include "libGLESv2/main.h" +#include "libGLESv2/renderer/Renderer9.h" +#include "libGLESv2/renderer/TextureStorage9.h" +#include "libGLESv2/renderer/SwapChain9.h" +#include "libGLESv2/renderer/RenderTarget9.h" +#include "libGLESv2/renderer/renderer9_utils.h" +#include "libGLESv2/Texture.h" + +namespace rx +{ +TextureStorage9::TextureStorage9(Renderer *renderer, DWORD usage) + : mLodOffset(0), + mRenderer(Renderer9::makeRenderer9(renderer)), + mD3DUsage(usage), + mD3DPool(mRenderer->getTexturePool(usage)) +{ +} + +TextureStorage9::~TextureStorage9() +{ +} + +TextureStorage9 *TextureStorage9::makeTextureStorage9(TextureStorage *storage) +{ + ASSERT(HAS_DYNAMIC_TYPE(TextureStorage9*, storage)); + return static_cast(storage); +} + +DWORD TextureStorage9::GetTextureUsage(D3DFORMAT d3dfmt, GLenum glusage, bool forceRenderable) +{ + DWORD d3dusage = 0; + + if (d3dfmt == D3DFMT_INTZ) + { + d3dusage |= D3DUSAGE_DEPTHSTENCIL; + } + else if(forceRenderable || (TextureStorage9::IsTextureFormatRenderable(d3dfmt) && (glusage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE))) + { + d3dusage |= D3DUSAGE_RENDERTARGET; + } + return d3dusage; +} + +bool TextureStorage9::IsTextureFormatRenderable(D3DFORMAT format) +{ + if (format == D3DFMT_INTZ) + { + return true; + } + switch(format) + { + case D3DFMT_L8: + case D3DFMT_A8L8: + case D3DFMT_DXT1: + case D3DFMT_DXT3: + case D3DFMT_DXT5: + return false; + case D3DFMT_A8R8G8B8: + case D3DFMT_X8R8G8B8: + case D3DFMT_A16B16G16R16F: + case D3DFMT_A32B32G32R32F: + return true; + default: + UNREACHABLE(); + } + + return false; +} + +bool TextureStorage9::isRenderTarget() const +{ + return (mD3DUsage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL)) != 0; +} + +bool TextureStorage9::isManaged() const +{ + return (mD3DPool == D3DPOOL_MANAGED); +} + +D3DPOOL TextureStorage9::getPool() const +{ + return mD3DPool; +} + +DWORD TextureStorage9::getUsage() const +{ + return mD3DUsage; +} + +int TextureStorage9::getLodOffset() const +{ + return mLodOffset; +} + +int TextureStorage9::levelCount() +{ + return getBaseTexture() ? getBaseTexture()->GetLevelCount() - getLodOffset() : 0; +} + +TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, SwapChain9 *swapchain) : TextureStorage9(renderer, D3DUSAGE_RENDERTARGET) +{ + IDirect3DTexture9 *surfaceTexture = swapchain->getOffscreenTexture(); + mTexture = surfaceTexture; + mRenderTarget = NULL; + + initializeRenderTarget(); +} + +TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height) + : TextureStorage9(renderer, GetTextureUsage(Renderer9::makeRenderer9(renderer)->ConvertTextureInternalFormat(internalformat), usage, forceRenderable)) +{ + mTexture = NULL; + mRenderTarget = NULL; + // if the width or height is not positive this should be treated as an incomplete texture + // we handle that here by skipping the d3d texture creation + if (width > 0 && height > 0) + { + IDirect3DDevice9 *device = mRenderer->getDevice(); + gl::MakeValidSize(false, gl::IsCompressed(internalformat), &width, &height, &mLodOffset); + HRESULT result = device->CreateTexture(width, height, levels ? levels + mLodOffset : 0, getUsage(), + mRenderer->ConvertTextureInternalFormat(internalformat), getPool(), &mTexture, NULL); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + gl::error(GL_OUT_OF_MEMORY); + } + } + + initializeRenderTarget(); +} + +TextureStorage9_2D::~TextureStorage9_2D() +{ + if (mTexture) + { + mTexture->Release(); + } + + delete mRenderTarget; +} + +TextureStorage9_2D *TextureStorage9_2D::makeTextureStorage9_2D(TextureStorage *storage) +{ + ASSERT(HAS_DYNAMIC_TYPE(TextureStorage9_2D*, storage)); + return static_cast(storage); +} + +// Increments refcount on surface. +// caller must Release() the returned surface +IDirect3DSurface9 *TextureStorage9_2D::getSurfaceLevel(int level, bool dirty) +{ + IDirect3DSurface9 *surface = NULL; + + if (mTexture) + { + HRESULT result = mTexture->GetSurfaceLevel(level + mLodOffset, &surface); + ASSERT(SUCCEEDED(result)); + + // With managed textures the driver needs to be informed of updates to the lower mipmap levels + if (level + mLodOffset != 0 && isManaged() && dirty) + { + mTexture->AddDirtyRect(NULL); + } + } + + return surface; +} + +RenderTarget *TextureStorage9_2D::getRenderTarget() +{ + return mRenderTarget; +} + +void TextureStorage9_2D::generateMipmap(int level) +{ + IDirect3DSurface9 *upper = getSurfaceLevel(level - 1, false); + IDirect3DSurface9 *lower = getSurfaceLevel(level, true); + + if (upper != NULL && lower != NULL) + { + mRenderer->boxFilter(upper, lower); + } + + if (upper != NULL) upper->Release(); + if (lower != NULL) lower->Release(); +} + +IDirect3DBaseTexture9 *TextureStorage9_2D::getBaseTexture() const +{ + return mTexture; +} + +void TextureStorage9_2D::initializeRenderTarget() +{ + ASSERT(mRenderTarget == NULL); + + if (mTexture != NULL && isRenderTarget()) + { + IDirect3DSurface9 *surface = getSurfaceLevel(0, false); + + mRenderTarget = new RenderTarget9(mRenderer, surface); + } +} + +TextureStorage9_Cube::TextureStorage9_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size) + : TextureStorage9(renderer, GetTextureUsage(Renderer9::makeRenderer9(renderer)->ConvertTextureInternalFormat(internalformat), usage, forceRenderable)) +{ + mTexture = NULL; + for (int i = 0; i < 6; ++i) + { + mRenderTarget[i] = NULL; + } + + // if the size is not positive this should be treated as an incomplete texture + // we handle that here by skipping the d3d texture creation + if (size > 0) + { + IDirect3DDevice9 *device = mRenderer->getDevice(); + int height = size; + gl::MakeValidSize(false, gl::IsCompressed(internalformat), &size, &height, &mLodOffset); + HRESULT result = device->CreateCubeTexture(size, levels ? levels + mLodOffset : 0, getUsage(), + mRenderer->ConvertTextureInternalFormat(internalformat), getPool(), &mTexture, NULL); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + gl::error(GL_OUT_OF_MEMORY); + } + } + + initializeRenderTarget(); +} + +TextureStorage9_Cube::~TextureStorage9_Cube() +{ + if (mTexture) + { + mTexture->Release(); + } + + for (int i = 0; i < 6; ++i) + { + delete mRenderTarget[i]; + } +} + +TextureStorage9_Cube *TextureStorage9_Cube::makeTextureStorage9_Cube(TextureStorage *storage) +{ + ASSERT(HAS_DYNAMIC_TYPE(TextureStorage9_Cube*, storage)); + return static_cast(storage); +} + +// Increments refcount on surface. +// caller must Release() the returned surface +IDirect3DSurface9 *TextureStorage9_Cube::getCubeMapSurface(GLenum faceTarget, int level, bool dirty) +{ + IDirect3DSurface9 *surface = NULL; + + if (mTexture) + { + D3DCUBEMAP_FACES face = gl_d3d9::ConvertCubeFace(faceTarget); + HRESULT result = mTexture->GetCubeMapSurface(face, level + mLodOffset, &surface); + ASSERT(SUCCEEDED(result)); + + // With managed textures the driver needs to be informed of updates to the lower mipmap levels + if (level != 0 && isManaged() && dirty) + { + mTexture->AddDirtyRect(face, NULL); + } + } + + return surface; +} + +RenderTarget *TextureStorage9_Cube::getRenderTarget(GLenum faceTarget) +{ + return mRenderTarget[gl::TextureCubeMap::faceIndex(faceTarget)]; +} + +void TextureStorage9_Cube::generateMipmap(int face, int level) +{ + IDirect3DSurface9 *upper = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level - 1, false); + IDirect3DSurface9 *lower = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, true); + + if (upper != NULL && lower != NULL) + { + mRenderer->boxFilter(upper, lower); + } + + if (upper != NULL) upper->Release(); + if (lower != NULL) lower->Release(); +} + +IDirect3DBaseTexture9 *TextureStorage9_Cube::getBaseTexture() const +{ + return mTexture; +} + +void TextureStorage9_Cube::initializeRenderTarget() +{ + if (mTexture != NULL && isRenderTarget()) + { + IDirect3DSurface9 *surface = NULL; + + for (int i = 0; i < 6; ++i) + { + ASSERT(mRenderTarget[i] == NULL); + + surface = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, false); + + mRenderTarget[i] = new RenderTarget9(mRenderer, surface); + } + } +} + +} \ No newline at end of file diff --git a/gfx/angle/src/libGLESv2/renderer/TextureStorage9.h b/gfx/angle/src/libGLESv2/renderer/TextureStorage9.h new file mode 100644 index 000000000000..86f551a1315d --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/TextureStorage9.h @@ -0,0 +1,109 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// TextureStorage9.h: Defines the abstract rx::TextureStorage9 class and its concrete derived +// classes TextureStorage9_2D and TextureStorage9_Cube, which act as the interface to the +// D3D9 texture. + +#ifndef LIBGLESV2_RENDERER_TEXTURESTORAGE9_H_ +#define LIBGLESV2_RENDERER_TEXTURESTORAGE9_H_ + +#include "libGLESv2/renderer/TextureStorage.h" +#include "common/debug.h" + +namespace rx +{ +class Renderer9; +class SwapChain9; +class RenderTarget; +class RenderTarget9; +class Blit; + +class TextureStorage9 : public TextureStorage +{ + public: + TextureStorage9(Renderer *renderer, DWORD usage); + virtual ~TextureStorage9(); + + static TextureStorage9 *makeTextureStorage9(TextureStorage *storage); + + static DWORD GetTextureUsage(D3DFORMAT d3dfmt, GLenum glusage, bool forceRenderable); + static bool IsTextureFormatRenderable(D3DFORMAT format); + + D3DPOOL getPool() const; + DWORD getUsage() const; + + virtual IDirect3DBaseTexture9 *getBaseTexture() const = 0; + virtual RenderTarget *getRenderTarget() { return NULL; } + virtual RenderTarget *getRenderTarget(GLenum faceTarget) { return NULL; } + virtual void generateMipmap(int level) {}; + virtual void generateMipmap(int face, int level) {}; + + virtual int getLodOffset() const; + virtual bool isRenderTarget() const; + virtual bool isManaged() const; + virtual int levelCount(); + + protected: + int mLodOffset; + Renderer9 *mRenderer; + + private: + DISALLOW_COPY_AND_ASSIGN(TextureStorage9); + + const DWORD mD3DUsage; + const D3DPOOL mD3DPool; +}; + +class TextureStorage9_2D : public TextureStorage9 +{ + public: + TextureStorage9_2D(Renderer *renderer, SwapChain9 *swapchain); + TextureStorage9_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height); + virtual ~TextureStorage9_2D(); + + static TextureStorage9_2D *makeTextureStorage9_2D(TextureStorage *storage); + + IDirect3DSurface9 *getSurfaceLevel(int level, bool dirty); + virtual RenderTarget *getRenderTarget(); + virtual IDirect3DBaseTexture9 *getBaseTexture() const; + virtual void generateMipmap(int level); + + private: + DISALLOW_COPY_AND_ASSIGN(TextureStorage9_2D); + + void initializeRenderTarget(); + + IDirect3DTexture9 *mTexture; + RenderTarget9 *mRenderTarget; +}; + +class TextureStorage9_Cube : public TextureStorage9 +{ + public: + TextureStorage9_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size); + virtual ~TextureStorage9_Cube(); + + static TextureStorage9_Cube *makeTextureStorage9_Cube(TextureStorage *storage); + + IDirect3DSurface9 *getCubeMapSurface(GLenum faceTarget, int level, bool dirty); + virtual RenderTarget *getRenderTarget(GLenum faceTarget); + virtual IDirect3DBaseTexture9 *getBaseTexture() const; + virtual void generateMipmap(int face, int level); + + private: + DISALLOW_COPY_AND_ASSIGN(TextureStorage9_Cube); + + void initializeRenderTarget(); + + IDirect3DCubeTexture9 *mTexture; + RenderTarget9 *mRenderTarget[6]; +}; + +} + +#endif // LIBGLESV2_RENDERER_TEXTURESTORAGE9_H_ + diff --git a/gfx/angle/src/libGLESv2/renderer/VertexBuffer.cpp b/gfx/angle/src/libGLESv2/renderer/VertexBuffer.cpp new file mode 100644 index 000000000000..a073d95033f3 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/VertexBuffer.cpp @@ -0,0 +1,292 @@ +#include "precompiled.h" +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// VertexBuffer.cpp: Defines the abstract VertexBuffer class and VertexBufferInterface +// class with derivations, classes that perform graphics API agnostic vertex buffer operations. + +#include "libGLESv2/renderer/VertexBuffer.h" +#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/Context.h" + +namespace rx +{ + +unsigned int VertexBuffer::mNextSerial = 1; + +VertexBuffer::VertexBuffer() +{ + updateSerial(); +} + +VertexBuffer::~VertexBuffer() +{ +} + +void VertexBuffer::updateSerial() +{ + mSerial = mNextSerial++; +} + +unsigned int VertexBuffer::getSerial() const +{ + return mSerial; +} + +VertexBufferInterface::VertexBufferInterface(rx::Renderer *renderer, bool dynamic) : mRenderer(renderer) +{ + mDynamic = dynamic; + mWritePosition = 0; + mReservedSpace = 0; + + mVertexBuffer = renderer->createVertexBuffer(); +} + +VertexBufferInterface::~VertexBufferInterface() +{ + delete mVertexBuffer; +} + +unsigned int VertexBufferInterface::getSerial() const +{ + return mVertexBuffer->getSerial(); +} + +unsigned int VertexBufferInterface::getBufferSize() const +{ + return mVertexBuffer->getBufferSize(); +} + +bool VertexBufferInterface::setBufferSize(unsigned int size) +{ + if (mVertexBuffer->getBufferSize() == 0) + { + return mVertexBuffer->initialize(size, mDynamic); + } + else + { + return mVertexBuffer->setBufferSize(size); + } +} + +unsigned int VertexBufferInterface::getWritePosition() const +{ + return mWritePosition; +} + +void VertexBufferInterface::setWritePosition(unsigned int writePosition) +{ + mWritePosition = writePosition; +} + +bool VertexBufferInterface::discard() +{ + return mVertexBuffer->discard(); +} + +bool VertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances, + unsigned int *outStreamOffset) +{ + unsigned int spaceRequired; + if (!mVertexBuffer->getSpaceRequired(attrib, count, instances, &spaceRequired)) + { + return false; + } + + if (mWritePosition + spaceRequired < mWritePosition) + { + return false; + } + + if (!reserveSpace(mReservedSpace)) + { + return false; + } + mReservedSpace = 0; + + if (!mVertexBuffer->storeVertexAttributes(attrib, start, count, instances, mWritePosition)) + { + return false; + } + + if (outStreamOffset) + { + *outStreamOffset = mWritePosition; + } + + mWritePosition += spaceRequired; + + return true; +} + +bool VertexBufferInterface::storeRawData(const void* data, unsigned int size, unsigned int *outStreamOffset) +{ + if (mWritePosition + size < mWritePosition) + { + return false; + } + + if (!reserveSpace(mReservedSpace)) + { + return false; + } + mReservedSpace = 0; + + if (!mVertexBuffer->storeRawData(data, size, mWritePosition)) + { + return false; + } + + if (outStreamOffset) + { + *outStreamOffset = mWritePosition; + } + + mWritePosition += size; + + return true; +} + +bool VertexBufferInterface::reserveVertexSpace(const gl::VertexAttribute &attribute, GLsizei count, GLsizei instances) +{ + unsigned int requiredSpace; + if (!mVertexBuffer->getSpaceRequired(attribute, count, instances, &requiredSpace)) + { + return false; + } + + // Protect against integer overflow + if (mReservedSpace + requiredSpace < mReservedSpace) + { + return false; + } + + mReservedSpace += requiredSpace; + return true; +} + +bool VertexBufferInterface::reserveRawDataSpace(unsigned int size) +{ + // Protect against integer overflow + if (mReservedSpace + size < mReservedSpace) + { + return false; + } + + mReservedSpace += size; + return true; +} + +VertexBuffer* VertexBufferInterface::getVertexBuffer() const +{ + return mVertexBuffer; +} + + +StreamingVertexBufferInterface::StreamingVertexBufferInterface(rx::Renderer *renderer, std::size_t initialSize) : VertexBufferInterface(renderer, true) +{ + setBufferSize(initialSize); +} + +StreamingVertexBufferInterface::~StreamingVertexBufferInterface() +{ +} + +bool StreamingVertexBufferInterface::reserveSpace(unsigned int size) +{ + bool result = true; + unsigned int curBufferSize = getBufferSize(); + if (size > curBufferSize) + { + result = setBufferSize(std::max(size, 3 * curBufferSize / 2)); + setWritePosition(0); + } + else if (getWritePosition() + size > curBufferSize) + { + if (!discard()) + { + return false; + } + setWritePosition(0); + } + + return result; +} + +StaticVertexBufferInterface::StaticVertexBufferInterface(rx::Renderer *renderer) : VertexBufferInterface(renderer, false) +{ +} + +StaticVertexBufferInterface::~StaticVertexBufferInterface() +{ +} + +bool StaticVertexBufferInterface::lookupAttribute(const gl::VertexAttribute &attribute, unsigned int *outStreamOffset) +{ + for (unsigned int element = 0; element < mCache.size(); element++) + { + if (mCache[element].type == attribute.mType && + mCache[element].size == attribute.mSize && + mCache[element].stride == attribute.stride() && + mCache[element].normalized == attribute.mNormalized) + { + if (mCache[element].attributeOffset == attribute.mOffset % attribute.stride()) + { + if (outStreamOffset) + { + *outStreamOffset = mCache[element].streamOffset; + } + return true; + } + } + } + + return false; +} + +bool StaticVertexBufferInterface::reserveSpace(unsigned int size) +{ + unsigned int curSize = getBufferSize(); + if (curSize == 0) + { + setBufferSize(size); + return true; + } + else if (curSize >= size) + { + return true; + } + else + { + UNREACHABLE(); // Static vertex buffers can't be resized + return false; + } +} + +bool StaticVertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances, + unsigned int *outStreamOffset) +{ + unsigned int streamOffset; + if (VertexBufferInterface::storeVertexAttributes(attrib, start, count, instances, &streamOffset)) + { + int attributeOffset = attrib.mOffset % attrib.stride(); + VertexElement element = { attrib.mType, attrib.mSize, attrib.stride(), attrib.mNormalized, attributeOffset, streamOffset }; + mCache.push_back(element); + + if (outStreamOffset) + { + *outStreamOffset = streamOffset; + } + + return true; + } + else + { + return false; + } +} + +} diff --git a/gfx/angle/src/libGLESv2/renderer/VertexBuffer.h b/gfx/angle/src/libGLESv2/renderer/VertexBuffer.h new file mode 100644 index 000000000000..cbafdd20f60c --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/VertexBuffer.h @@ -0,0 +1,139 @@ +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// VertexBuffer.h: Defines the abstract VertexBuffer class and VertexBufferInterface +// class with derivations, classes that perform graphics API agnostic vertex buffer operations. + +#ifndef LIBGLESV2_RENDERER_VERTEXBUFFER_H_ +#define LIBGLESV2_RENDERER_VERTEXBUFFER_H_ + +#include "common/angleutils.h" + +namespace gl +{ +class VertexAttribute; +} + +namespace rx +{ +class Renderer; + +class VertexBuffer +{ + public: + VertexBuffer(); + virtual ~VertexBuffer(); + + virtual bool initialize(unsigned int size, bool dynamicUsage) = 0; + + virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, + GLsizei instances, unsigned int offset) = 0; + virtual bool storeRawData(const void* data, unsigned int size, unsigned int offset) = 0; + + virtual bool getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, + unsigned int *outSpaceRequired) const = 0; + + virtual bool requiresConversion(const gl::VertexAttribute &attrib) const = 0; + + virtual unsigned int getBufferSize() const = 0; + virtual bool setBufferSize(unsigned int size) = 0; + virtual bool discard() = 0; + + unsigned int getSerial() const; + + protected: + void updateSerial(); + + private: + DISALLOW_COPY_AND_ASSIGN(VertexBuffer); + + unsigned int mSerial; + static unsigned int mNextSerial; +}; + +class VertexBufferInterface +{ + public: + VertexBufferInterface(rx::Renderer *renderer, bool dynamic); + virtual ~VertexBufferInterface(); + + bool reserveVertexSpace(const gl::VertexAttribute &attribute, GLsizei count, GLsizei instances); + bool reserveRawDataSpace(unsigned int size); + + unsigned int getBufferSize() const; + + unsigned int getSerial() const; + + virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances, + unsigned int *outStreamOffset); + virtual bool storeRawData(const void* data, unsigned int size, unsigned int *outStreamOffset); + + VertexBuffer* getVertexBuffer() const; + + protected: + virtual bool reserveSpace(unsigned int size) = 0; + + unsigned int getWritePosition() const; + void setWritePosition(unsigned int writePosition); + + bool discard(); + + bool setBufferSize(unsigned int size); + + private: + DISALLOW_COPY_AND_ASSIGN(VertexBufferInterface); + + rx::Renderer *const mRenderer; + + VertexBuffer* mVertexBuffer; + + unsigned int mWritePosition; + unsigned int mReservedSpace; + bool mDynamic; +}; + +class StreamingVertexBufferInterface : public VertexBufferInterface +{ + public: + StreamingVertexBufferInterface(rx::Renderer *renderer, std::size_t initialSize); + ~StreamingVertexBufferInterface(); + + protected: + bool reserveSpace(unsigned int size); +}; + +class StaticVertexBufferInterface : public VertexBufferInterface +{ + public: + explicit StaticVertexBufferInterface(rx::Renderer *renderer); + ~StaticVertexBufferInterface(); + + bool storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances, + unsigned int *outStreamOffset); + + bool lookupAttribute(const gl::VertexAttribute &attribute, unsigned int* outStreamOffset); + + protected: + bool reserveSpace(unsigned int size); + + private: + struct VertexElement + { + GLenum type; + GLint size; + GLsizei stride; + bool normalized; + int attributeOffset; + + unsigned int streamOffset; + }; + + std::vector mCache; +}; + +} + +#endif // LIBGLESV2_RENDERER_VERTEXBUFFER_H_ \ No newline at end of file diff --git a/gfx/angle/src/libGLESv2/renderer/VertexBuffer11.cpp b/gfx/angle/src/libGLESv2/renderer/VertexBuffer11.cpp new file mode 100644 index 000000000000..521da80c3d7e --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/VertexBuffer11.cpp @@ -0,0 +1,440 @@ +#include "precompiled.h" +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// VertexBuffer11.cpp: Defines the D3D11 VertexBuffer implementation. + +#include "libGLESv2/renderer/VertexBuffer11.h" +#include "libGLESv2/renderer/BufferStorage.h" + +#include "libGLESv2/Buffer.h" +#include "libGLESv2/renderer/Renderer11.h" +#include "libGLESv2/Context.h" + +namespace rx +{ + +VertexBuffer11::VertexBuffer11(rx::Renderer11 *const renderer) : mRenderer(renderer) +{ + mBuffer = NULL; + mBufferSize = 0; + mDynamicUsage = false; +} + +VertexBuffer11::~VertexBuffer11() +{ + if (mBuffer) + { + mBuffer->Release(); + mBuffer = NULL; + } +} + +bool VertexBuffer11::initialize(unsigned int size, bool dynamicUsage) +{ + if (mBuffer) + { + mBuffer->Release(); + mBuffer = NULL; + } + + updateSerial(); + + if (size > 0) + { + ID3D11Device* dxDevice = mRenderer->getDevice(); + + D3D11_BUFFER_DESC bufferDesc; + bufferDesc.ByteWidth = size; + bufferDesc.Usage = D3D11_USAGE_DYNAMIC; + bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + bufferDesc.MiscFlags = 0; + bufferDesc.StructureByteStride = 0; + + HRESULT result = dxDevice->CreateBuffer(&bufferDesc, NULL, &mBuffer); + if (FAILED(result)) + { + return false; + } + } + + mBufferSize = size; + mDynamicUsage = dynamicUsage; + return true; +} + +VertexBuffer11 *VertexBuffer11::makeVertexBuffer11(VertexBuffer *vetexBuffer) +{ + ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer11*, vetexBuffer)); + return static_cast(vetexBuffer); +} + +bool VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, + GLsizei instances, unsigned int offset) +{ + if (mBuffer) + { + gl::Buffer *buffer = attrib.mBoundBuffer.get(); + + int inputStride = attrib.stride(); + const VertexConverter &converter = getVertexConversion(attrib); + + ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource); + if (FAILED(result)) + { + ERR("Vertex buffer map failed with error 0x%08x", result); + return false; + } + + char* output = reinterpret_cast(mappedResource.pData) + offset; + + const char *input = NULL; + if (buffer) + { + BufferStorage *storage = buffer->getStorage(); + input = static_cast(storage->getData()) + static_cast(attrib.mOffset); + } + else + { + input = static_cast(attrib.mPointer); + } + + if (instances == 0 || attrib.mDivisor == 0) + { + input += inputStride * start; + } + + converter.conversionFunc(input, inputStride, count, output); + + dxContext->Unmap(mBuffer, 0); + + return true; + } + else + { + ERR("Vertex buffer not initialized."); + return false; + } +} + +bool VertexBuffer11::storeRawData(const void* data, unsigned int size, unsigned int offset) +{ + if (mBuffer) + { + ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource); + if (FAILED(result)) + { + ERR("Vertex buffer map failed with error 0x%08x", result); + return false; + } + + char* bufferData = static_cast(mappedResource.pData); + memcpy(bufferData + offset, data, size); + + dxContext->Unmap(mBuffer, 0); + + return true; + } + else + { + ERR("Vertex buffer not initialized."); + return false; + } +} + +bool VertexBuffer11::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, + GLsizei instances, unsigned int *outSpaceRequired) const +{ + unsigned int elementSize = getVertexConversion(attrib).outputElementSize; + + unsigned int elementCount = 0; + if (instances == 0 || attrib.mDivisor == 0) + { + elementCount = count; + } + else + { + if (static_cast(instances) < std::numeric_limits::max() - (attrib.mDivisor - 1)) + { + // Round up + elementCount = (static_cast(instances) + (attrib.mDivisor - 1)) / attrib.mDivisor; + } + else + { + elementCount = instances / attrib.mDivisor; + } + } + + if (elementSize <= std::numeric_limits::max() / elementCount) + { + if (outSpaceRequired) + { + *outSpaceRequired = elementSize * elementCount; + } + return true; + } + else + { + return false; + } +} + +bool VertexBuffer11::requiresConversion(const gl::VertexAttribute &attrib) const +{ + return !getVertexConversion(attrib).identity; +} + +unsigned int VertexBuffer11::getBufferSize() const +{ + return mBufferSize; +} + +bool VertexBuffer11::setBufferSize(unsigned int size) +{ + if (size > mBufferSize) + { + return initialize(size, mDynamicUsage); + } + else + { + return true; + } +} + +bool VertexBuffer11::discard() +{ + if (mBuffer) + { + ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + ERR("Vertex buffer map failed with error 0x%08x", result); + return false; + } + + dxContext->Unmap(mBuffer, 0); + + return true; + } + else + { + ERR("Vertex buffer not initialized."); + return false; + } +} + +unsigned int VertexBuffer11::getVertexSize(const gl::VertexAttribute &attrib) const +{ + return getVertexConversion(attrib).outputElementSize; +} + +DXGI_FORMAT VertexBuffer11::getDXGIFormat(const gl::VertexAttribute &attrib) const +{ + return getVertexConversion(attrib).dxgiFormat; +} + +ID3D11Buffer *VertexBuffer11::getBuffer() const +{ + return mBuffer; +} + +template +static void copyVertexData(const void *input, unsigned int stride, unsigned int count, void *output) +{ + unsigned int attribSize = sizeof(T) * componentCount; + + if (attribSize == stride && !widen) + { + memcpy(output, input, count * attribSize); + } + else + { + unsigned int outputStride = widen ? 4 : componentCount; + T defaultVal = normalized ? std::numeric_limits::max() : T(1); + + for (unsigned int i = 0; i < count; i++) + { + const T *offsetInput = reinterpret_cast(reinterpret_cast(input) + i * stride); + T *offsetOutput = reinterpret_cast(output) + i * outputStride; + + for (unsigned int j = 0; j < componentCount; j++) + { + offsetOutput[j] = offsetInput[j]; + } + + if (widen) + { + offsetOutput[3] = defaultVal; + } + } + } +} + +template +static void copyFixedVertexData(const void* input, unsigned int stride, unsigned int count, void* output) +{ + static const float divisor = 1.0f / (1 << 16); + + for (unsigned int i = 0; i < count; i++) + { + const GLfixed* offsetInput = reinterpret_cast(reinterpret_cast(input) + stride * i); + float* offsetOutput = reinterpret_cast(output) + i * componentCount; + + for (unsigned int j = 0; j < componentCount; j++) + { + offsetOutput[j] = static_cast(offsetInput[j]) * divisor; + } + } +} + +template +static void copyToFloatVertexData(const void* input, unsigned int stride, unsigned int count, void* output) +{ + typedef std::numeric_limits NL; + + for (unsigned int i = 0; i < count; i++) + { + const T *offsetInput = reinterpret_cast(reinterpret_cast(input) + stride * i); + float *offsetOutput = reinterpret_cast(output) + i * componentCount; + + for (unsigned int j = 0; j < componentCount; j++) + { + if (normalized) + { + if (NL::is_signed) + { + const float divisor = 1.0f / (2 * static_cast(NL::max()) + 1); + offsetOutput[j] = (2 * static_cast(offsetInput[j]) + 1) * divisor; + } + else + { + offsetOutput[j] = static_cast(offsetInput[j]) / NL::max(); + } + } + else + { + offsetOutput[j] = static_cast(offsetInput[j]); + } + } + } +} + +const VertexBuffer11::VertexConverter VertexBuffer11::mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4] = +{ + { // GL_BYTE + { // unnormalized + { ©ToFloatVertexData, false, DXGI_FORMAT_R32_FLOAT, 4 }, + { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32_FLOAT, 8 }, + { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 }, + { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 }, + }, + { // normalized + { ©VertexData, true, DXGI_FORMAT_R8_SNORM, 1 }, + { ©VertexData, true, DXGI_FORMAT_R8G8_SNORM, 2 }, + { ©VertexData, false, DXGI_FORMAT_R8G8B8A8_SNORM, 4 }, + { ©VertexData, true, DXGI_FORMAT_R8G8B8A8_SNORM, 4 }, + }, + }, + { // GL_UNSIGNED_BYTE + { // unnormalized + { ©ToFloatVertexData, false, DXGI_FORMAT_R32_FLOAT, 4 }, + { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32_FLOAT, 8 }, + { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 }, + { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 }, + }, + { // normalized + { ©VertexData, true, DXGI_FORMAT_R8_UNORM, 1 }, + { ©VertexData, true, DXGI_FORMAT_R8G8_UNORM, 2 }, + { ©VertexData, false, DXGI_FORMAT_R8G8B8A8_UNORM, 4 }, + { ©VertexData, true, DXGI_FORMAT_R8G8B8A8_UNORM, 4 }, + }, + }, + { // GL_SHORT + { // unnormalized + { ©ToFloatVertexData, false, DXGI_FORMAT_R32_FLOAT, 4 }, + { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32_FLOAT, 8 }, + { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 }, + { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 }, + }, + { // normalized + { ©VertexData, true, DXGI_FORMAT_R16_SNORM, 2 }, + { ©VertexData, true, DXGI_FORMAT_R16G16_SNORM, 4 }, + { ©VertexData, false, DXGI_FORMAT_R16G16B16A16_SNORM, 8 }, + { ©VertexData, true, DXGI_FORMAT_R16G16B16A16_SNORM, 8 }, + }, + }, + { // GL_UNSIGNED_SHORT + { // unnormalized + { ©ToFloatVertexData, false, DXGI_FORMAT_R32_FLOAT, 4 }, + { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32_FLOAT, 8 }, + { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 }, + { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 }, + }, + { // normalized + { ©VertexData, true, DXGI_FORMAT_R16_UNORM, 2 }, + { ©VertexData, true, DXGI_FORMAT_R16G16_UNORM, 4 }, + { ©VertexData, false, DXGI_FORMAT_R16G16B16A16_UNORM, 8 }, + { ©VertexData, true, DXGI_FORMAT_R16G16B16A16_UNORM, 8 }, + }, + }, + { // GL_FIXED + { // unnormalized + { ©FixedVertexData<1>, false, DXGI_FORMAT_R32_FLOAT, 4 }, + { ©FixedVertexData<2>, false, DXGI_FORMAT_R32G32_FLOAT, 8 }, + { ©FixedVertexData<3>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 }, + { ©FixedVertexData<4>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 }, + }, + { // normalized + { ©FixedVertexData<1>, false, DXGI_FORMAT_R32_FLOAT, 4 }, + { ©FixedVertexData<2>, false, DXGI_FORMAT_R32G32_FLOAT, 8 }, + { ©FixedVertexData<3>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 }, + { ©FixedVertexData<4>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 }, + }, + }, + { // GL_FLOAT + { // unnormalized + { ©VertexData, true, DXGI_FORMAT_R32_FLOAT, 4 }, + { ©VertexData, true, DXGI_FORMAT_R32G32_FLOAT, 8 }, + { ©VertexData, true, DXGI_FORMAT_R32G32B32_FLOAT, 12 }, + { ©VertexData, true, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 }, + }, + { // normalized + { ©VertexData, true, DXGI_FORMAT_R32_FLOAT, 4 }, + { ©VertexData, true, DXGI_FORMAT_R32G32_FLOAT, 8 }, + { ©VertexData, true, DXGI_FORMAT_R32G32B32_FLOAT, 12 }, + { ©VertexData, true, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 }, + }, + }, +}; + +const VertexBuffer11::VertexConverter &VertexBuffer11::getVertexConversion(const gl::VertexAttribute &attribute) +{ + unsigned int typeIndex = 0; + switch (attribute.mType) + { + case GL_BYTE: typeIndex = 0; break; + case GL_UNSIGNED_BYTE: typeIndex = 1; break; + case GL_SHORT: typeIndex = 2; break; + case GL_UNSIGNED_SHORT: typeIndex = 3; break; + case GL_FIXED: typeIndex = 4; break; + case GL_FLOAT: typeIndex = 5; break; + default: UNREACHABLE(); break; + } + + return mPossibleTranslations[typeIndex][attribute.mNormalized ? 1 : 0][attribute.mSize - 1]; +} + +} diff --git a/gfx/angle/src/libGLESv2/renderer/VertexBuffer11.h b/gfx/angle/src/libGLESv2/renderer/VertexBuffer11.h new file mode 100644 index 000000000000..eceb426e82d4 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/VertexBuffer11.h @@ -0,0 +1,74 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// VertexBuffer11.h: Defines the D3D11 VertexBuffer implementation. + +#ifndef LIBGLESV2_RENDERER_VERTEXBUFFER11_H_ +#define LIBGLESV2_RENDERER_VERTEXBUFFER11_H_ + +#include "libGLESv2/renderer/VertexBuffer.h" + +namespace rx +{ +class Renderer11; + +class VertexBuffer11 : public VertexBuffer +{ + public: + explicit VertexBuffer11(rx::Renderer11 *const renderer); + virtual ~VertexBuffer11(); + + virtual bool initialize(unsigned int size, bool dynamicUsage); + + static VertexBuffer11 *makeVertexBuffer11(VertexBuffer *vetexBuffer); + + virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances, + unsigned int offset); + virtual bool storeRawData(const void* data, unsigned int size, unsigned int offset); + + virtual bool getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, + unsigned int *outSpaceRequired) const; + + virtual bool requiresConversion(const gl::VertexAttribute &attrib) const; + + virtual unsigned int getBufferSize() const; + virtual bool setBufferSize(unsigned int size); + virtual bool discard(); + + unsigned int getVertexSize(const gl::VertexAttribute &attrib) const; + DXGI_FORMAT getDXGIFormat(const gl::VertexAttribute &attrib) const; + + ID3D11Buffer *getBuffer() const; + + private: + DISALLOW_COPY_AND_ASSIGN(VertexBuffer11); + + rx::Renderer11 *const mRenderer; + + ID3D11Buffer *mBuffer; + unsigned int mBufferSize; + bool mDynamicUsage; + + typedef void (*VertexConversionFunction)(const void *, unsigned int, unsigned int, void *); + struct VertexConverter + { + VertexConversionFunction conversionFunc; + bool identity; + DXGI_FORMAT dxgiFormat; + unsigned int outputElementSize; + }; + + enum { NUM_GL_VERTEX_ATTRIB_TYPES = 6 }; + + // This table is used to generate mAttributeTypes. + static const VertexConverter mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; // [GL types as enumerated by typeIndex()][normalized][size - 1] + + static const VertexConverter &getVertexConversion(const gl::VertexAttribute &attribute); +}; + +} + +#endif // LIBGLESV2_RENDERER_VERTEXBUFFER11_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/VertexBuffer9.cpp b/gfx/angle/src/libGLESv2/renderer/VertexBuffer9.cpp new file mode 100644 index 000000000000..534be2584e6d --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/VertexBuffer9.cpp @@ -0,0 +1,530 @@ +#include "precompiled.h" +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// VertexBuffer9.cpp: Defines the D3D9 VertexBuffer implementation. + +#include "libGLESv2/renderer/VertexBuffer9.h" +#include "libGLESv2/renderer/vertexconversion.h" +#include "libGLESv2/renderer/BufferStorage.h" +#include "libGLESv2/Context.h" +#include "libGLESv2/renderer/Renderer9.h" + +#include "libGLESv2/Buffer.h" + +namespace rx +{ + +bool VertexBuffer9::mTranslationsInitialized = false; +VertexBuffer9::FormatConverter VertexBuffer9::mFormatConverters[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; + +VertexBuffer9::VertexBuffer9(rx::Renderer9 *const renderer) : mRenderer(renderer) +{ + mVertexBuffer = NULL; + mBufferSize = 0; + mDynamicUsage = false; + + if (!mTranslationsInitialized) + { + initializeTranslations(renderer->getCapsDeclTypes()); + mTranslationsInitialized = true; + } +} + +VertexBuffer9::~VertexBuffer9() +{ + if (mVertexBuffer) + { + mVertexBuffer->Release(); + mVertexBuffer = NULL; + } +} + +bool VertexBuffer9::initialize(unsigned int size, bool dynamicUsage) +{ + if (mVertexBuffer) + { + mVertexBuffer->Release(); + mVertexBuffer = NULL; + } + + updateSerial(); + + if (size > 0) + { + DWORD flags = D3DUSAGE_WRITEONLY; + if (dynamicUsage) + { + flags |= D3DUSAGE_DYNAMIC; + } + + HRESULT result = mRenderer->createVertexBuffer(size, flags, &mVertexBuffer); + + if (FAILED(result)) + { + ERR("Out of memory allocating a vertex buffer of size %lu.", size); + return false; + } + } + + mBufferSize = size; + mDynamicUsage = dynamicUsage; + return true; +} + +VertexBuffer9 *VertexBuffer9::makeVertexBuffer9(VertexBuffer *vertexBuffer) +{ + ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer9*, vertexBuffer)); + return static_cast(vertexBuffer); +} + +bool VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, + GLsizei instances, unsigned int offset) +{ + if (mVertexBuffer) + { + gl::Buffer *buffer = attrib.mBoundBuffer.get(); + + int inputStride = attrib.stride(); + int elementSize = attrib.typeSize(); + const FormatConverter &converter = formatConverter(attrib); + + DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0; + + void *mapPtr = NULL; + + unsigned int mapSize; + if (!spaceRequired(attrib, count, instances, &mapSize)) + { + return false; + } + + HRESULT result = mVertexBuffer->Lock(offset, mapSize, &mapPtr, lockFlags); + + if (FAILED(result)) + { + ERR("Lock failed with error 0x%08x", result); + return false; + } + + const char *input = NULL; + if (buffer) + { + BufferStorage *storage = buffer->getStorage(); + input = static_cast(storage->getData()) + static_cast(attrib.mOffset); + } + else + { + input = static_cast(attrib.mPointer); + } + + if (instances == 0 || attrib.mDivisor == 0) + { + input += inputStride * start; + } + + if (converter.identity && inputStride == elementSize) + { + memcpy(mapPtr, input, count * inputStride); + } + else + { + converter.convertArray(input, inputStride, count, mapPtr); + } + + mVertexBuffer->Unlock(); + + return true; + } + else + { + ERR("Vertex buffer not initialized."); + return false; + } +} + +bool VertexBuffer9::storeRawData(const void* data, unsigned int size, unsigned int offset) +{ + if (mVertexBuffer) + { + DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0; + + void *mapPtr = NULL; + HRESULT result = mVertexBuffer->Lock(offset, size, &mapPtr, lockFlags); + + if (FAILED(result)) + { + ERR("Lock failed with error 0x%08x", result); + return false; + } + + memcpy(mapPtr, data, size); + + mVertexBuffer->Unlock(); + + return true; + } + else + { + ERR("Vertex buffer not initialized."); + return false; + } +} + +bool VertexBuffer9::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, + unsigned int *outSpaceRequired) const +{ + return spaceRequired(attrib, count, instances, outSpaceRequired); +} + +bool VertexBuffer9::requiresConversion(const gl::VertexAttribute &attrib) const +{ + return formatConverter(attrib).identity; +} + +unsigned int VertexBuffer9::getVertexSize(const gl::VertexAttribute &attrib) const +{ + unsigned int spaceRequired; + return getSpaceRequired(attrib, 1, 0, &spaceRequired) ? spaceRequired : 0; +} + +D3DDECLTYPE VertexBuffer9::getDeclType(const gl::VertexAttribute &attrib) const +{ + return formatConverter(attrib).d3dDeclType; +} + +unsigned int VertexBuffer9::getBufferSize() const +{ + return mBufferSize; +} + +bool VertexBuffer9::setBufferSize(unsigned int size) +{ + if (size > mBufferSize) + { + return initialize(size, mDynamicUsage); + } + else + { + return true; + } +} + +bool VertexBuffer9::discard() +{ + if (mVertexBuffer) + { + void *dummy; + HRESULT result; + + result = mVertexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD); + if (FAILED(result)) + { + ERR("Discard lock failed with error 0x%08x", result); + return false; + } + + result = mVertexBuffer->Unlock(); + if (FAILED(result)) + { + ERR("Discard unlock failed with error 0x%08x", result); + return false; + } + + return true; + } + else + { + ERR("Vertex buffer not initialized."); + return false; + } +} + +IDirect3DVertexBuffer9 * VertexBuffer9::getBuffer() const +{ + return mVertexBuffer; +} + +// Mapping from OpenGL-ES vertex attrib type to D3D decl type: +// +// BYTE SHORT (Cast) +// BYTE-norm FLOAT (Normalize) (can't be exactly represented as SHORT-norm) +// UNSIGNED_BYTE UBYTE4 (Identity) or SHORT (Cast) +// UNSIGNED_BYTE-norm UBYTE4N (Identity) or FLOAT (Normalize) +// SHORT SHORT (Identity) +// SHORT-norm SHORT-norm (Identity) or FLOAT (Normalize) +// UNSIGNED_SHORT FLOAT (Cast) +// UNSIGNED_SHORT-norm USHORT-norm (Identity) or FLOAT (Normalize) +// FIXED (not in WebGL) FLOAT (FixedToFloat) +// FLOAT FLOAT (Identity) + +// GLToCType maps from GL type (as GLenum) to the C typedef. +template struct GLToCType { }; + +template <> struct GLToCType { typedef GLbyte type; }; +template <> struct GLToCType { typedef GLubyte type; }; +template <> struct GLToCType { typedef GLshort type; }; +template <> struct GLToCType { typedef GLushort type; }; +template <> struct GLToCType { typedef GLuint type; }; +template <> struct GLToCType { typedef GLfloat type; }; + +// This differs from D3DDECLTYPE in that it is unsized. (Size expansion is applied last.) +enum D3DVertexType +{ + D3DVT_FLOAT, + D3DVT_SHORT, + D3DVT_SHORT_NORM, + D3DVT_UBYTE, + D3DVT_UBYTE_NORM, + D3DVT_USHORT_NORM +}; + +// D3DToCType maps from D3D vertex type (as enum D3DVertexType) to the corresponding C type. +template struct D3DToCType { }; + +template <> struct D3DToCType { typedef float type; }; +template <> struct D3DToCType { typedef short type; }; +template <> struct D3DToCType { typedef short type; }; +template <> struct D3DToCType { typedef unsigned char type; }; +template <> struct D3DToCType { typedef unsigned char type; }; +template <> struct D3DToCType { typedef unsigned short type; }; + +// Encode the type/size combinations that D3D permits. For each type/size it expands to a widener that will provide the appropriate final size. +template struct WidenRule { }; + +template struct WidenRule : NoWiden { }; +template struct WidenRule : WidenToEven { }; +template struct WidenRule : WidenToEven { }; +template struct WidenRule : WidenToFour { }; +template struct WidenRule : WidenToFour { }; +template struct WidenRule : WidenToEven { }; + +// VertexTypeFlags encodes the D3DCAPS9::DeclType flag and vertex declaration flag for each D3D vertex type & size combination. +template struct VertexTypeFlags { }; + +template +struct VertexTypeFlagsHelper +{ + enum { capflag = _capflag }; + enum { declflag = _declflag }; +}; + +template <> struct VertexTypeFlags : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT1> { }; +template <> struct VertexTypeFlags : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT2> { }; +template <> struct VertexTypeFlags : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT3> { }; +template <> struct VertexTypeFlags : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT4> { }; +template <> struct VertexTypeFlags : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT2> { }; +template <> struct VertexTypeFlags : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT4> { }; +template <> struct VertexTypeFlags : VertexTypeFlagsHelper { }; +template <> struct VertexTypeFlags : VertexTypeFlagsHelper { }; +template <> struct VertexTypeFlags : VertexTypeFlagsHelper { }; +template <> struct VertexTypeFlags : VertexTypeFlagsHelper { }; +template <> struct VertexTypeFlags : VertexTypeFlagsHelper { }; +template <> struct VertexTypeFlags : VertexTypeFlagsHelper { }; + + +// VertexTypeMapping maps GL type & normalized flag to preferred and fallback D3D vertex types (as D3DVertexType enums). +template struct VertexTypeMapping { }; + +template +struct VertexTypeMappingBase +{ + enum { preferred = Preferred }; + enum { fallback = Fallback }; +}; + +template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Cast +template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Normalize +template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Identity, Cast +template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Identity, Normalize +template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Identity +template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Cast, Normalize +template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Cast +template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Cast, Normalize +template struct VertexTypeMapping : VertexTypeMappingBase { }; // FixedToFloat +template struct VertexTypeMapping : VertexTypeMappingBase { }; // Identity + + +// Given a GL type & norm flag and a D3D type, ConversionRule provides the type conversion rule (Cast, Normalize, Identity, FixedToFloat). +// The conversion rules themselves are defined in vertexconversion.h. + +// Almost all cases are covered by Cast (including those that are actually Identity since Cast knows it's an identity mapping). +template +struct ConversionRule : Cast::type, typename D3DToCType::type> { }; + +// All conversions from normalized types to float use the Normalize operator. +template struct ConversionRule : Normalize::type> { }; + +// Use a full specialization for this so that it preferentially matches ahead of the generic normalize-to-float rules. +template <> struct ConversionRule : FixedToFloat { }; +template <> struct ConversionRule : FixedToFloat { }; + +// A 2-stage construction is used for DefaultVertexValues because float must use SimpleDefaultValues (i.e. 0/1) +// whether it is normalized or not. +template struct DefaultVertexValuesStage2 { }; + +template struct DefaultVertexValuesStage2 : NormalizedDefaultValues { }; +template struct DefaultVertexValuesStage2 : SimpleDefaultValues { }; + +// Work out the default value rule for a D3D type (expressed as the C type) and +template struct DefaultVertexValues : DefaultVertexValuesStage2 { }; +template struct DefaultVertexValues : SimpleDefaultValues { }; + +// Policy rules for use with Converter, to choose whether to use the preferred or fallback conversion. +// The fallback conversion produces an output that all D3D9 devices must support. +template struct UsePreferred { enum { type = T::preferred }; }; +template struct UseFallback { enum { type = T::fallback }; }; + +// Converter ties it all together. Given an OpenGL type/norm/size and choice of preferred/fallback conversion, +// it provides all the members of the appropriate VertexDataConverter, the D3DCAPS9::DeclTypes flag in cap flag +// and the D3DDECLTYPE member needed for the vertex declaration in declflag. +template class PreferenceRule> +struct Converter + : VertexDataConverter::type, + WidenRule >::type, size>, + ConversionRule >::type>, + DefaultVertexValues >::type>::type, normalized > > +{ +private: + enum { d3dtype = PreferenceRule< VertexTypeMapping >::type }; + enum { d3dsize = WidenRule::finalWidth }; + +public: + enum { capflag = VertexTypeFlags::capflag }; + enum { declflag = VertexTypeFlags::declflag }; +}; + +// Initialize a TranslationInfo +#define TRANSLATION(type, norm, size, preferred) \ + { \ + Converter::identity, \ + Converter::finalSize, \ + Converter::convertArray, \ + static_cast(Converter::declflag) \ + } + +#define TRANSLATION_FOR_TYPE_NORM_SIZE(type, norm, size) \ + { \ + Converter::capflag, \ + TRANSLATION(type, norm, size, UsePreferred), \ + TRANSLATION(type, norm, size, UseFallback) \ + } + +#define TRANSLATIONS_FOR_TYPE(type) \ + { \ + { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \ + { TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 4) }, \ + } + +#define TRANSLATIONS_FOR_TYPE_NO_NORM(type) \ + { \ + { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \ + { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \ + } + +const VertexBuffer9::TranslationDescription VertexBuffer9::mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4] = // [GL types as enumerated by typeIndex()][normalized][size-1] +{ + TRANSLATIONS_FOR_TYPE(GL_BYTE), + TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_BYTE), + TRANSLATIONS_FOR_TYPE(GL_SHORT), + TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_SHORT), + TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FIXED), + TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FLOAT) +}; + +void VertexBuffer9::initializeTranslations(DWORD declTypes) +{ + for (unsigned int i = 0; i < NUM_GL_VERTEX_ATTRIB_TYPES; i++) + { + for (unsigned int j = 0; j < 2; j++) + { + for (unsigned int k = 0; k < 4; k++) + { + if (mPossibleTranslations[i][j][k].capsFlag == 0 || (declTypes & mPossibleTranslations[i][j][k].capsFlag) != 0) + { + mFormatConverters[i][j][k] = mPossibleTranslations[i][j][k].preferredConversion; + } + else + { + mFormatConverters[i][j][k] = mPossibleTranslations[i][j][k].fallbackConversion; + } + } + } + } +} + +unsigned int VertexBuffer9::typeIndex(GLenum type) +{ + switch (type) + { + case GL_BYTE: return 0; + case GL_UNSIGNED_BYTE: return 1; + case GL_SHORT: return 2; + case GL_UNSIGNED_SHORT: return 3; + case GL_FIXED: return 4; + case GL_FLOAT: return 5; + + default: UNREACHABLE(); return 5; + } +} + +const VertexBuffer9::FormatConverter &VertexBuffer9::formatConverter(const gl::VertexAttribute &attribute) +{ + return mFormatConverters[typeIndex(attribute.mType)][attribute.mNormalized][attribute.mSize - 1]; +} + +bool VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances, + unsigned int *outSpaceRequired) +{ + unsigned int elementSize = formatConverter(attrib).outputElementSize; + + if (instances == 0 || attrib.mDivisor == 0) + { + unsigned int elementCount = 0; + if (instances == 0 || attrib.mDivisor == 0) + { + elementCount = count; + } + else + { + if (static_cast(instances) < std::numeric_limits::max() - (attrib.mDivisor - 1)) + { + // Round up + elementCount = (static_cast(instances) + (attrib.mDivisor - 1)) / attrib.mDivisor; + } + else + { + elementCount = static_cast(instances) / attrib.mDivisor; + } + } + + if (elementSize <= std::numeric_limits::max() / elementCount) + { + if (outSpaceRequired) + { + *outSpaceRequired = elementSize * elementCount; + } + return true; + } + else + { + return false; + } + } + else + { + const unsigned int elementSize = 4; + if (outSpaceRequired) + { + *outSpaceRequired = elementSize * 4; + } + return true; + } +} + +} diff --git a/gfx/angle/src/libGLESv2/renderer/VertexBuffer9.h b/gfx/angle/src/libGLESv2/renderer/VertexBuffer9.h new file mode 100644 index 000000000000..2f88117bda25 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/VertexBuffer9.h @@ -0,0 +1,91 @@ +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// VertexBuffer9.h: Defines the D3D9 VertexBuffer implementation. + +#ifndef LIBGLESV2_RENDERER_VERTEXBUFFER9_H_ +#define LIBGLESV2_RENDERER_VERTEXBUFFER9_H_ + +#include "libGLESv2/renderer/VertexBuffer.h" + +namespace rx +{ +class Renderer9; + +class VertexBuffer9 : public VertexBuffer +{ + public: + explicit VertexBuffer9(rx::Renderer9 *const renderer); + virtual ~VertexBuffer9(); + + virtual bool initialize(unsigned int size, bool dynamicUsage); + + static VertexBuffer9 *makeVertexBuffer9(VertexBuffer *vertexBuffer); + + virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances, + unsigned int offset); + virtual bool storeRawData(const void* data, unsigned int size, unsigned int offset); + + virtual bool getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, unsigned int *outSpaceRequired) const; + + virtual bool requiresConversion(const gl::VertexAttribute &attrib) const; + + unsigned int getVertexSize(const gl::VertexAttribute &attrib) const; + D3DDECLTYPE getDeclType(const gl::VertexAttribute &attrib) const; + + virtual unsigned int getBufferSize() const; + virtual bool setBufferSize(unsigned int size); + virtual bool discard(); + + IDirect3DVertexBuffer9 *getBuffer() const; + + private: + DISALLOW_COPY_AND_ASSIGN(VertexBuffer9); + + rx::Renderer9 *const mRenderer; + + IDirect3DVertexBuffer9 *mVertexBuffer; + unsigned int mBufferSize; + bool mDynamicUsage; + + // Attribute format conversion + enum { NUM_GL_VERTEX_ATTRIB_TYPES = 6 }; + + struct FormatConverter + { + bool identity; + std::size_t outputElementSize; + void (*convertArray)(const void *in, std::size_t stride, std::size_t n, void *out); + D3DDECLTYPE d3dDeclType; + }; + + static bool mTranslationsInitialized; + static void initializeTranslations(DWORD declTypes); + + // [GL types as enumerated by typeIndex()][normalized][size - 1] + static FormatConverter mFormatConverters[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; + + struct TranslationDescription + { + DWORD capsFlag; + FormatConverter preferredConversion; + FormatConverter fallbackConversion; + }; + + // This table is used to generate mFormatConverters. + // [GL types as enumerated by typeIndex()][normalized][size - 1] + static const TranslationDescription mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; + + static unsigned int typeIndex(GLenum type); + static const FormatConverter &formatConverter(const gl::VertexAttribute &attribute); + + static bool spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances, + unsigned int *outSpaceRequired); +}; + +} + +#endif // LIBGLESV2_RENDERER_VERTEXBUFFER9_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/VertexDataManager.cpp b/gfx/angle/src/libGLESv2/renderer/VertexDataManager.cpp new file mode 100644 index 000000000000..879046346f72 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/VertexDataManager.cpp @@ -0,0 +1,276 @@ +#include "precompiled.h" +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// VertexDataManager.h: Defines the VertexDataManager, a class that +// runs the Buffer translation process. + +#include "libGLESv2/renderer/VertexDataManager.h" +#include "libGLESv2/renderer/BufferStorage.h" + +#include "libGLESv2/Buffer.h" +#include "libGLESv2/ProgramBinary.h" +#include "libGLESv2/Context.h" +#include "libGLESv2/renderer/VertexBuffer.h" + +namespace +{ + enum { INITIAL_STREAM_BUFFER_SIZE = 1024*1024 }; + // This has to be at least 4k or else it fails on ATI cards. + enum { CONSTANT_VERTEX_BUFFER_SIZE = 4096 }; +} + +namespace rx +{ + +static int elementsInBuffer(const gl::VertexAttribute &attribute, unsigned int size) +{ + // Size cannot be larger than a GLsizei + if (size > static_cast(std::numeric_limits::max())) + { + size = static_cast(std::numeric_limits::max()); + } + + GLsizei stride = attribute.stride(); + return (size - attribute.mOffset % stride + (stride - attribute.typeSize())) / stride; +} + +VertexDataManager::VertexDataManager(Renderer *renderer) : mRenderer(renderer) +{ + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + mCurrentValue[i][0] = std::numeric_limits::quiet_NaN(); + mCurrentValue[i][1] = std::numeric_limits::quiet_NaN(); + mCurrentValue[i][2] = std::numeric_limits::quiet_NaN(); + mCurrentValue[i][3] = std::numeric_limits::quiet_NaN(); + mCurrentValueBuffer[i] = NULL; + mCurrentValueOffsets[i] = 0; + } + + mStreamingBuffer = new StreamingVertexBufferInterface(renderer, INITIAL_STREAM_BUFFER_SIZE); + + if (!mStreamingBuffer) + { + ERR("Failed to allocate the streaming vertex buffer."); + } +} + +VertexDataManager::~VertexDataManager() +{ + delete mStreamingBuffer; + + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + delete mCurrentValueBuffer[i]; + } +} + +static bool directStoragePossible(VertexBufferInterface* vb, const gl::VertexAttribute& attrib) +{ + gl::Buffer *buffer = attrib.mBoundBuffer.get(); + BufferStorage *storage = buffer ? buffer->getStorage() : NULL; + + const bool isAligned = (attrib.stride() % 4 == 0) && (attrib.mOffset % 4 == 0); + + return storage && storage->supportsDirectBinding() && !vb->getVertexBuffer()->requiresConversion(attrib) && isAligned; +} + +GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], gl::ProgramBinary *programBinary, GLint start, GLsizei count, TranslatedAttribute *translated, GLsizei instances) +{ + if (!mStreamingBuffer) + { + return GL_OUT_OF_MEMORY; + } + + for (int attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++) + { + translated[attributeIndex].active = (programBinary->getSemanticIndex(attributeIndex) != -1); + } + + // Invalidate static buffers that don't contain matching attributes + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + if (translated[i].active && attribs[i].mArrayEnabled) + { + gl::Buffer *buffer = attribs[i].mBoundBuffer.get(); + StaticVertexBufferInterface *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL; + + if (staticBuffer && staticBuffer->getBufferSize() > 0 && !staticBuffer->lookupAttribute(attribs[i], NULL) && + !directStoragePossible(staticBuffer, attribs[i])) + { + buffer->invalidateStaticData(); + } + } + } + + // Reserve the required space in the buffers + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + if (translated[i].active && attribs[i].mArrayEnabled) + { + gl::Buffer *buffer = attribs[i].mBoundBuffer.get(); + StaticVertexBufferInterface *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL; + VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast(mStreamingBuffer); + + if (!directStoragePossible(vertexBuffer, attribs[i])) + { + if (staticBuffer) + { + if (staticBuffer->getBufferSize() == 0) + { + int totalCount = elementsInBuffer(attribs[i], buffer->size()); + if (!staticBuffer->reserveVertexSpace(attribs[i], totalCount, 0)) + { + return GL_OUT_OF_MEMORY; + } + } + } + else + { + if (!mStreamingBuffer->reserveVertexSpace(attribs[i], count, instances)) + { + return GL_OUT_OF_MEMORY; + } + } + } + } + } + + // Perform the vertex data translations + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + if (translated[i].active) + { + if (attribs[i].mArrayEnabled) + { + gl::Buffer *buffer = attribs[i].mBoundBuffer.get(); + + if (!buffer && attribs[i].mPointer == NULL) + { + // This is an application error that would normally result in a crash, but we catch it and return an error + ERR("An enabled vertex array has no buffer and no pointer."); + return GL_INVALID_OPERATION; + } + + StaticVertexBufferInterface *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL; + VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast(mStreamingBuffer); + + BufferStorage *storage = buffer ? buffer->getStorage() : NULL; + bool directStorage = directStoragePossible(vertexBuffer, attribs[i]); + + unsigned int streamOffset = 0; + unsigned int outputElementSize = 0; + + if (directStorage) + { + outputElementSize = attribs[i].stride(); + streamOffset = attribs[i].mOffset + outputElementSize * start; + storage->markBufferUsage(); + } + else if (staticBuffer) + { + if (!staticBuffer->getVertexBuffer()->getSpaceRequired(attribs[i], 1, 0, &outputElementSize)) + { + return GL_OUT_OF_MEMORY; + } + + if (!staticBuffer->lookupAttribute(attribs[i], &streamOffset)) + { + // Convert the entire buffer + int totalCount = elementsInBuffer(attribs[i], storage->getSize()); + int startIndex = attribs[i].mOffset / attribs[i].stride(); + + if (!staticBuffer->storeVertexAttributes(attribs[i], -startIndex, totalCount, 0, &streamOffset)) + { + return GL_OUT_OF_MEMORY; + } + } + + unsigned int firstElementOffset = (attribs[i].mOffset / attribs[i].stride()) * outputElementSize; + unsigned int startOffset = (instances == 0 || attribs[i].mDivisor == 0) ? start * outputElementSize : 0; + if (streamOffset + firstElementOffset + startOffset < streamOffset) + { + return GL_OUT_OF_MEMORY; + } + + streamOffset += firstElementOffset + startOffset; + } + else + { + if (!mStreamingBuffer->getVertexBuffer()->getSpaceRequired(attribs[i], 1, 0, &outputElementSize) || + !mStreamingBuffer->storeVertexAttributes(attribs[i], start, count, instances, &streamOffset)) + { + return GL_OUT_OF_MEMORY; + } + } + + translated[i].storage = directStorage ? storage : NULL; + translated[i].vertexBuffer = vertexBuffer->getVertexBuffer(); + translated[i].serial = directStorage ? storage->getSerial() : vertexBuffer->getSerial(); + translated[i].divisor = attribs[i].mDivisor; + + translated[i].attribute = &attribs[i]; + translated[i].stride = outputElementSize; + translated[i].offset = streamOffset; + } + else + { + if (!mCurrentValueBuffer[i]) + { + mCurrentValueBuffer[i] = new StreamingVertexBufferInterface(mRenderer, CONSTANT_VERTEX_BUFFER_SIZE); + } + + StreamingVertexBufferInterface *buffer = mCurrentValueBuffer[i]; + + if (mCurrentValue[i][0] != attribs[i].mCurrentValue[0] || + mCurrentValue[i][1] != attribs[i].mCurrentValue[1] || + mCurrentValue[i][2] != attribs[i].mCurrentValue[2] || + mCurrentValue[i][3] != attribs[i].mCurrentValue[3]) + { + unsigned int requiredSpace = sizeof(float) * 4; + if (!buffer->reserveRawDataSpace(requiredSpace)) + { + return GL_OUT_OF_MEMORY; + } + + unsigned int streamOffset; + if (!buffer->storeRawData(attribs[i].mCurrentValue, requiredSpace, &streamOffset)) + { + return GL_OUT_OF_MEMORY; + } + + mCurrentValueOffsets[i] = streamOffset; + } + + translated[i].storage = NULL; + translated[i].vertexBuffer = mCurrentValueBuffer[i]->getVertexBuffer(); + translated[i].serial = mCurrentValueBuffer[i]->getSerial(); + translated[i].divisor = 0; + + translated[i].attribute = &attribs[i]; + translated[i].stride = 0; + translated[i].offset = mCurrentValueOffsets[i]; + } + } + } + + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + if (translated[i].active && attribs[i].mArrayEnabled) + { + gl::Buffer *buffer = attribs[i].mBoundBuffer.get(); + + if (buffer) + { + buffer->promoteStaticUsage(count * attribs[i].typeSize()); + } + } + } + + return GL_NO_ERROR; +} + +} diff --git a/gfx/angle/src/libGLESv2/renderer/VertexDataManager.h b/gfx/angle/src/libGLESv2/renderer/VertexDataManager.h new file mode 100644 index 000000000000..1a8786552a5e --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/VertexDataManager.h @@ -0,0 +1,65 @@ +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// VertexDataManager.h: Defines the VertexDataManager, a class that +// runs the Buffer translation process. + +#ifndef LIBGLESV2_RENDERER_VERTEXDATAMANAGER_H_ +#define LIBGLESV2_RENDERER_VERTEXDATAMANAGER_H_ + +#include "libGLESv2/Constants.h" +#include "common/angleutils.h" + +namespace gl +{ +class VertexAttribute; +class ProgramBinary; +} + +namespace rx +{ +class BufferStorage; +class StreamingVertexBufferInterface; +class VertexBuffer; +class Renderer; + +struct TranslatedAttribute +{ + bool active; + + const gl::VertexAttribute *attribute; + unsigned int offset; + unsigned int stride; // 0 means not to advance the read pointer at all + + VertexBuffer *vertexBuffer; + BufferStorage *storage; + unsigned int serial; + unsigned int divisor; +}; + +class VertexDataManager +{ + public: + VertexDataManager(rx::Renderer *renderer); + virtual ~VertexDataManager(); + + GLenum prepareVertexData(const gl::VertexAttribute attribs[], gl::ProgramBinary *programBinary, GLint start, GLsizei count, TranslatedAttribute *outAttribs, GLsizei instances); + + private: + DISALLOW_COPY_AND_ASSIGN(VertexDataManager); + + rx::Renderer *const mRenderer; + + StreamingVertexBufferInterface *mStreamingBuffer; + + float mCurrentValue[gl::MAX_VERTEX_ATTRIBS][4]; + StreamingVertexBufferInterface *mCurrentValueBuffer[gl::MAX_VERTEX_ATTRIBS]; + std::size_t mCurrentValueOffsets[gl::MAX_VERTEX_ATTRIBS]; +}; + +} + +#endif // LIBGLESV2_RENDERER_VERTEXDATAMANAGER_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/VertexDeclarationCache.cpp b/gfx/angle/src/libGLESv2/renderer/VertexDeclarationCache.cpp new file mode 100644 index 000000000000..9b83a6476ebc --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/VertexDeclarationCache.cpp @@ -0,0 +1,217 @@ +#include "precompiled.h" +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// VertexDeclarationCache.cpp: Implements a helper class to construct and cache vertex declarations. + +#include "libGLESv2/ProgramBinary.h" +#include "libGLESv2/Context.h" +#include "libGLESv2/renderer/VertexBuffer9.h" +#include "libGLESv2/renderer/VertexDeclarationCache.h" + +namespace rx +{ + +VertexDeclarationCache::VertexDeclarationCache() : mMaxLru(0) +{ + for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++) + { + mVertexDeclCache[i].vertexDeclaration = NULL; + mVertexDeclCache[i].lruCount = 0; + } + + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + mAppliedVBs[i].serial = 0; + } + + mLastSetVDecl = NULL; + mInstancingEnabled = true; +} + +VertexDeclarationCache::~VertexDeclarationCache() +{ + for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++) + { + if (mVertexDeclCache[i].vertexDeclaration) + { + mVertexDeclCache[i].vertexDeclaration->Release(); + } + } +} + +GLenum VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], gl::ProgramBinary *programBinary, GLsizei instances, GLsizei *repeatDraw) +{ + *repeatDraw = 1; + + int indexedAttribute = gl::MAX_VERTEX_ATTRIBS; + int instancedAttribute = gl::MAX_VERTEX_ATTRIBS; + + if (instances > 0) + { + // Find an indexed attribute to be mapped to D3D stream 0 + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + if (attributes[i].active) + { + if (indexedAttribute == gl::MAX_VERTEX_ATTRIBS && attributes[i].divisor == 0) + { + indexedAttribute = i; + } + else if (instancedAttribute == gl::MAX_VERTEX_ATTRIBS && attributes[i].divisor != 0) + { + instancedAttribute = i; + } + if (indexedAttribute != gl::MAX_VERTEX_ATTRIBS && instancedAttribute != gl::MAX_VERTEX_ATTRIBS) + break; // Found both an indexed and instanced attribute + } + } + + if (indexedAttribute == gl::MAX_VERTEX_ATTRIBS) + { + return GL_INVALID_OPERATION; + } + } + + D3DVERTEXELEMENT9 elements[gl::MAX_VERTEX_ATTRIBS + 1]; + D3DVERTEXELEMENT9 *element = &elements[0]; + + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + if (attributes[i].active) + { + // Directly binding the storage buffer is not supported for d3d9 + ASSERT(attributes[i].storage == NULL); + + int stream = i; + + if (instances > 0) + { + // Due to a bug on ATI cards we can't enable instancing when none of the attributes are instanced. + if (instancedAttribute == gl::MAX_VERTEX_ATTRIBS) + { + *repeatDraw = instances; + } + else + { + if (i == indexedAttribute) + { + stream = 0; + } + else if (i == 0) + { + stream = indexedAttribute; + } + + UINT frequency = 1; + + if (attributes[i].divisor == 0) + { + frequency = D3DSTREAMSOURCE_INDEXEDDATA | instances; + } + else + { + frequency = D3DSTREAMSOURCE_INSTANCEDATA | attributes[i].divisor; + } + + device->SetStreamSourceFreq(stream, frequency); + mInstancingEnabled = true; + } + } + + VertexBuffer9 *vertexBuffer = VertexBuffer9::makeVertexBuffer9(attributes[i].vertexBuffer); + + if (mAppliedVBs[stream].serial != attributes[i].serial || + mAppliedVBs[stream].stride != attributes[i].stride || + mAppliedVBs[stream].offset != attributes[i].offset) + { + device->SetStreamSource(stream, vertexBuffer->getBuffer(), attributes[i].offset, attributes[i].stride); + mAppliedVBs[stream].serial = attributes[i].serial; + mAppliedVBs[stream].stride = attributes[i].stride; + mAppliedVBs[stream].offset = attributes[i].offset; + } + + element->Stream = stream; + element->Offset = 0; + element->Type = attributes[i].attribute->mArrayEnabled ? vertexBuffer->getDeclType(*attributes[i].attribute) : D3DDECLTYPE_FLOAT4; + element->Method = D3DDECLMETHOD_DEFAULT; + element->Usage = D3DDECLUSAGE_TEXCOORD; + element->UsageIndex = programBinary->getSemanticIndex(i); + element++; + } + } + + if (instances == 0 || instancedAttribute == gl::MAX_VERTEX_ATTRIBS) + { + if (mInstancingEnabled) + { + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + device->SetStreamSourceFreq(i, 1); + } + + mInstancingEnabled = false; + } + } + + static const D3DVERTEXELEMENT9 end = D3DDECL_END(); + *(element++) = end; + + for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++) + { + VertexDeclCacheEntry *entry = &mVertexDeclCache[i]; + if (memcmp(entry->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9)) == 0 && entry->vertexDeclaration) + { + entry->lruCount = ++mMaxLru; + if(entry->vertexDeclaration != mLastSetVDecl) + { + device->SetVertexDeclaration(entry->vertexDeclaration); + mLastSetVDecl = entry->vertexDeclaration; + } + + return GL_NO_ERROR; + } + } + + VertexDeclCacheEntry *lastCache = mVertexDeclCache; + + for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++) + { + if (mVertexDeclCache[i].lruCount < lastCache->lruCount) + { + lastCache = &mVertexDeclCache[i]; + } + } + + if (lastCache->vertexDeclaration != NULL) + { + lastCache->vertexDeclaration->Release(); + lastCache->vertexDeclaration = NULL; + // mLastSetVDecl is set to the replacement, so we don't have to worry + // about it. + } + + memcpy(lastCache->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9)); + device->CreateVertexDeclaration(elements, &lastCache->vertexDeclaration); + device->SetVertexDeclaration(lastCache->vertexDeclaration); + mLastSetVDecl = lastCache->vertexDeclaration; + lastCache->lruCount = ++mMaxLru; + + return GL_NO_ERROR; +} + +void VertexDeclarationCache::markStateDirty() +{ + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + mAppliedVBs[i].serial = 0; + } + + mLastSetVDecl = NULL; + mInstancingEnabled = true; // Forces it to be disabled when not used +} + +} diff --git a/gfx/angle/src/libGLESv2/renderer/VertexDeclarationCache.h b/gfx/angle/src/libGLESv2/renderer/VertexDeclarationCache.h new file mode 100644 index 000000000000..3fc024a9bab4 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/VertexDeclarationCache.h @@ -0,0 +1,58 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// VertexDeclarationCache.h: Defines a helper class to construct and cache vertex declarations. + +#ifndef LIBGLESV2_RENDERER_VERTEXDECLARATIONCACHE_H_ +#define LIBGLESV2_RENDERER_VERTEXDECLARATIONCACHE_H_ + +#include "libGLESv2/renderer/VertexDataManager.h" + +namespace gl +{ +class VertexDataManager; +} + +namespace rx +{ + +class VertexDeclarationCache +{ + public: + VertexDeclarationCache(); + ~VertexDeclarationCache(); + + GLenum applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], gl::ProgramBinary *programBinary, GLsizei instances, GLsizei *repeatDraw); + + void markStateDirty(); + + private: + UINT mMaxLru; + + enum { NUM_VERTEX_DECL_CACHE_ENTRIES = 32 }; + + struct VBData + { + unsigned int serial; + unsigned int stride; + unsigned int offset; + }; + + VBData mAppliedVBs[gl::MAX_VERTEX_ATTRIBS]; + IDirect3DVertexDeclaration9 *mLastSetVDecl; + bool mInstancingEnabled; + + struct VertexDeclCacheEntry + { + D3DVERTEXELEMENT9 cachedElements[gl::MAX_VERTEX_ATTRIBS + 1]; + UINT lruCount; + IDirect3DVertexDeclaration9 *vertexDeclaration; + } mVertexDeclCache[NUM_VERTEX_DECL_CACHE_ENTRIES]; +}; + +} + +#endif // LIBGLESV2_RENDERER_VERTEXDECLARATIONCACHE_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/generatemip.h b/gfx/angle/src/libGLESv2/renderer/generatemip.h new file mode 100644 index 000000000000..8e1973605b8b --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/generatemip.h @@ -0,0 +1,203 @@ +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// generatemip.h: Defines the GenerateMip function, templated on the format +// type of the image for which mip levels are being generated. + +#ifndef LIBGLESV2_RENDERER_GENERATEMIP_H_ +#define LIBGLESV2_RENDERER_GENERATEMIP_H_ + +#include "libGLESv2/mathutil.h" + +namespace rx +{ +struct L8 +{ + unsigned char L; + + static void average(L8 *dst, const L8 *src1, const L8 *src2) + { + dst->L = ((src1->L ^ src2->L) >> 1) + (src1->L & src2->L); + } +}; + +typedef L8 R8; // R8 type is functionally equivalent for mip purposes +typedef L8 A8; // A8 type is functionally equivalent for mip purposes + +struct A8L8 +{ + unsigned char L; + unsigned char A; + + static void average(A8L8 *dst, const A8L8 *src1, const A8L8 *src2) + { + *(unsigned short*)dst = (((*(unsigned short*)src1 ^ *(unsigned short*)src2) & 0xFEFE) >> 1) + (*(unsigned short*)src1 & *(unsigned short*)src2); + } +}; + +typedef A8L8 R8G8; // R8G8 type is functionally equivalent for mip purposes + +struct A8R8G8B8 +{ + unsigned char B; + unsigned char G; + unsigned char R; + unsigned char A; + + static void average(A8R8G8B8 *dst, const A8R8G8B8 *src1, const A8R8G8B8 *src2) + { + *(unsigned int*)dst = (((*(unsigned int*)src1 ^ *(unsigned int*)src2) & 0xFEFEFEFE) >> 1) + (*(unsigned int*)src1 & *(unsigned int*)src2); + } +}; + +typedef A8R8G8B8 R8G8B8A8; // R8G8B8A8 type is functionally equivalent for mip purposes + +struct A16B16G16R16F +{ + unsigned short R; + unsigned short G; + unsigned short B; + unsigned short A; + + static void average(A16B16G16R16F *dst, const A16B16G16R16F *src1, const A16B16G16R16F *src2) + { + dst->R = gl::float32ToFloat16((gl::float16ToFloat32(src1->R) + gl::float16ToFloat32(src2->R)) * 0.5f); + dst->G = gl::float32ToFloat16((gl::float16ToFloat32(src1->G) + gl::float16ToFloat32(src2->G)) * 0.5f); + dst->B = gl::float32ToFloat16((gl::float16ToFloat32(src1->B) + gl::float16ToFloat32(src2->B)) * 0.5f); + dst->A = gl::float32ToFloat16((gl::float16ToFloat32(src1->A) + gl::float16ToFloat32(src2->A)) * 0.5f); + } +}; + +struct R16F +{ + unsigned short R; + + static void average(R16F *dst, const R16F *src1, const R16F *src2) + { + dst->R = gl::float32ToFloat16((gl::float16ToFloat32(src1->R) + gl::float16ToFloat32(src2->R)) * 0.5f); + } +}; + +struct R16G16F +{ + unsigned short R; + unsigned short G; + + static void average(R16G16F *dst, const R16G16F *src1, const R16G16F *src2) + { + dst->R = gl::float32ToFloat16((gl::float16ToFloat32(src1->R) + gl::float16ToFloat32(src2->R)) * 0.5f); + dst->G = gl::float32ToFloat16((gl::float16ToFloat32(src1->G) + gl::float16ToFloat32(src2->G)) * 0.5f); + } +}; + +struct A32B32G32R32F +{ + float R; + float G; + float B; + float A; + + static void average(A32B32G32R32F *dst, const A32B32G32R32F *src1, const A32B32G32R32F *src2) + { + dst->R = (src1->R + src2->R) * 0.5f; + dst->G = (src1->G + src2->G) * 0.5f; + dst->B = (src1->B + src2->B) * 0.5f; + dst->A = (src1->A + src2->A) * 0.5f; + } +}; + +struct R32F +{ + float R; + + static void average(R32F *dst, const R32F *src1, const R32F *src2) + { + dst->R = (src1->R + src2->R) * 0.5f; + } +}; + +struct R32G32F +{ + float R; + float G; + + static void average(R32G32F *dst, const R32G32F *src1, const R32G32F *src2) + { + dst->R = (src1->R + src2->R) * 0.5f; + dst->G = (src1->G + src2->G) * 0.5f; + } +}; + +struct R32G32B32F +{ + float R; + float G; + float B; + + static void average(R32G32B32F *dst, const R32G32B32F *src1, const R32G32B32F *src2) + { + dst->R = (src1->R + src2->R) * 0.5f; + dst->G = (src1->G + src2->G) * 0.5f; + dst->B = (src1->B + src2->B) * 0.5f; + } +}; + +template +static void GenerateMip(unsigned int sourceWidth, unsigned int sourceHeight, + const unsigned char *sourceData, int sourcePitch, + unsigned char *destData, int destPitch) +{ + unsigned int mipWidth = std::max(1U, sourceWidth >> 1); + unsigned int mipHeight = std::max(1U, sourceHeight >> 1); + + if (sourceHeight == 1) + { + ASSERT(sourceWidth != 1); + + const T *src = (const T*)sourceData; + T *dst = (T*)destData; + + for (unsigned int x = 0; x < mipWidth; x++) + { + T::average(&dst[x], &src[x * 2], &src[x * 2 + 1]); + } + } + else if (sourceWidth == 1) + { + ASSERT(sourceHeight != 1); + + for (unsigned int y = 0; y < mipHeight; y++) + { + const T *src0 = (const T*)(sourceData + y * 2 * sourcePitch); + const T *src1 = (const T*)(sourceData + y * 2 * sourcePitch + sourcePitch); + T *dst = (T*)(destData + y * destPitch); + + T::average(dst, src0, src1); + } + } + else + { + for (unsigned int y = 0; y < mipHeight; y++) + { + const T *src0 = (const T*)(sourceData + y * 2 * sourcePitch); + const T *src1 = (const T*)(sourceData + y * 2 * sourcePitch + sourcePitch); + T *dst = (T*)(destData + y * destPitch); + + for (unsigned int x = 0; x < mipWidth; x++) + { + T tmp0; + T tmp1; + + T::average(&tmp0, &src0[x * 2], &src0[x * 2 + 1]); + T::average(&tmp1, &src1[x * 2], &src1[x * 2 + 1]); + T::average(&dst[x], &tmp0, &tmp1); + } + } + } +} +} + +#endif // LIBGLESV2_RENDERER_GENERATEMIP_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/renderer11_utils.cpp b/gfx/angle/src/libGLESv2/renderer/renderer11_utils.cpp new file mode 100644 index 000000000000..13800da258ce --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/renderer11_utils.cpp @@ -0,0 +1,688 @@ +#include "precompiled.h" +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// renderer11_utils.cpp: Conversion functions and other utility routines +// specific to the D3D11 renderer. + +#include "libGLESv2/renderer/renderer11_utils.h" + +#include "common/debug.h" + +namespace gl_d3d11 +{ + +D3D11_BLEND ConvertBlendFunc(GLenum glBlend, bool isAlpha) +{ + D3D11_BLEND d3dBlend = D3D11_BLEND_ZERO; + + switch (glBlend) + { + case GL_ZERO: d3dBlend = D3D11_BLEND_ZERO; break; + case GL_ONE: d3dBlend = D3D11_BLEND_ONE; break; + case GL_SRC_COLOR: d3dBlend = (isAlpha ? D3D11_BLEND_SRC_ALPHA : D3D11_BLEND_SRC_COLOR); break; + case GL_ONE_MINUS_SRC_COLOR: d3dBlend = (isAlpha ? D3D11_BLEND_INV_SRC_ALPHA : D3D11_BLEND_INV_SRC_COLOR); break; + case GL_DST_COLOR: d3dBlend = (isAlpha ? D3D11_BLEND_DEST_ALPHA : D3D11_BLEND_DEST_COLOR); break; + case GL_ONE_MINUS_DST_COLOR: d3dBlend = (isAlpha ? D3D11_BLEND_INV_DEST_ALPHA : D3D11_BLEND_INV_DEST_COLOR); break; + case GL_SRC_ALPHA: d3dBlend = D3D11_BLEND_SRC_ALPHA; break; + case GL_ONE_MINUS_SRC_ALPHA: d3dBlend = D3D11_BLEND_INV_SRC_ALPHA; break; + case GL_DST_ALPHA: d3dBlend = D3D11_BLEND_DEST_ALPHA; break; + case GL_ONE_MINUS_DST_ALPHA: d3dBlend = D3D11_BLEND_INV_DEST_ALPHA; break; + case GL_CONSTANT_COLOR: d3dBlend = D3D11_BLEND_BLEND_FACTOR; break; + case GL_ONE_MINUS_CONSTANT_COLOR: d3dBlend = D3D11_BLEND_INV_BLEND_FACTOR; break; + case GL_CONSTANT_ALPHA: d3dBlend = D3D11_BLEND_BLEND_FACTOR; break; + case GL_ONE_MINUS_CONSTANT_ALPHA: d3dBlend = D3D11_BLEND_INV_BLEND_FACTOR; break; + case GL_SRC_ALPHA_SATURATE: d3dBlend = D3D11_BLEND_SRC_ALPHA_SAT; break; + default: UNREACHABLE(); + } + + return d3dBlend; +} + +D3D11_BLEND_OP ConvertBlendOp(GLenum glBlendOp) +{ + D3D11_BLEND_OP d3dBlendOp = D3D11_BLEND_OP_ADD; + + switch (glBlendOp) + { + case GL_FUNC_ADD: d3dBlendOp = D3D11_BLEND_OP_ADD; break; + case GL_FUNC_SUBTRACT: d3dBlendOp = D3D11_BLEND_OP_SUBTRACT; break; + case GL_FUNC_REVERSE_SUBTRACT: d3dBlendOp = D3D11_BLEND_OP_REV_SUBTRACT; break; + default: UNREACHABLE(); + } + + return d3dBlendOp; +} + +UINT8 ConvertColorMask(bool red, bool green, bool blue, bool alpha) +{ + UINT8 mask = 0; + if (red) + { + mask |= D3D11_COLOR_WRITE_ENABLE_RED; + } + if (green) + { + mask |= D3D11_COLOR_WRITE_ENABLE_GREEN; + } + if (blue) + { + mask |= D3D11_COLOR_WRITE_ENABLE_BLUE; + } + if (alpha) + { + mask |= D3D11_COLOR_WRITE_ENABLE_ALPHA; + } + return mask; +} + +D3D11_CULL_MODE ConvertCullMode(bool cullEnabled, GLenum cullMode) +{ + D3D11_CULL_MODE cull = D3D11_CULL_NONE; + + if (cullEnabled) + { + switch (cullMode) + { + case GL_FRONT: cull = D3D11_CULL_FRONT; break; + case GL_BACK: cull = D3D11_CULL_BACK; break; + case GL_FRONT_AND_BACK: cull = D3D11_CULL_NONE; break; + default: UNREACHABLE(); + } + } + else + { + cull = D3D11_CULL_NONE; + } + + return cull; +} + +D3D11_COMPARISON_FUNC ConvertComparison(GLenum comparison) +{ + D3D11_COMPARISON_FUNC d3dComp = D3D11_COMPARISON_NEVER; + switch (comparison) + { + case GL_NEVER: d3dComp = D3D11_COMPARISON_NEVER; break; + case GL_ALWAYS: d3dComp = D3D11_COMPARISON_ALWAYS; break; + case GL_LESS: d3dComp = D3D11_COMPARISON_LESS; break; + case GL_LEQUAL: d3dComp = D3D11_COMPARISON_LESS_EQUAL; break; + case GL_EQUAL: d3dComp = D3D11_COMPARISON_EQUAL; break; + case GL_GREATER: d3dComp = D3D11_COMPARISON_GREATER; break; + case GL_GEQUAL: d3dComp = D3D11_COMPARISON_GREATER_EQUAL; break; + case GL_NOTEQUAL: d3dComp = D3D11_COMPARISON_NOT_EQUAL; break; + default: UNREACHABLE(); + } + + return d3dComp; +} + +D3D11_DEPTH_WRITE_MASK ConvertDepthMask(bool depthWriteEnabled) +{ + return depthWriteEnabled ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO; +} + +UINT8 ConvertStencilMask(GLuint stencilmask) +{ + return static_cast(stencilmask); +} + +D3D11_STENCIL_OP ConvertStencilOp(GLenum stencilOp) +{ + D3D11_STENCIL_OP d3dStencilOp = D3D11_STENCIL_OP_KEEP; + + switch (stencilOp) + { + case GL_ZERO: d3dStencilOp = D3D11_STENCIL_OP_ZERO; break; + case GL_KEEP: d3dStencilOp = D3D11_STENCIL_OP_KEEP; break; + case GL_REPLACE: d3dStencilOp = D3D11_STENCIL_OP_REPLACE; break; + case GL_INCR: d3dStencilOp = D3D11_STENCIL_OP_INCR_SAT; break; + case GL_DECR: d3dStencilOp = D3D11_STENCIL_OP_DECR_SAT; break; + case GL_INVERT: d3dStencilOp = D3D11_STENCIL_OP_INVERT; break; + case GL_INCR_WRAP: d3dStencilOp = D3D11_STENCIL_OP_INCR; break; + case GL_DECR_WRAP: d3dStencilOp = D3D11_STENCIL_OP_DECR; break; + default: UNREACHABLE(); + } + + return d3dStencilOp; +} + +D3D11_FILTER ConvertFilter(GLenum minFilter, GLenum magFilter, float maxAnisotropy) +{ + if (maxAnisotropy > 1.0f) + { + return D3D11_ENCODE_ANISOTROPIC_FILTER(false); + } + else + { + D3D11_FILTER_TYPE dxMin = D3D11_FILTER_TYPE_POINT; + D3D11_FILTER_TYPE dxMip = D3D11_FILTER_TYPE_POINT; + switch (minFilter) + { + case GL_NEAREST: dxMin = D3D11_FILTER_TYPE_POINT; dxMip = D3D11_FILTER_TYPE_POINT; break; + case GL_LINEAR: dxMin = D3D11_FILTER_TYPE_LINEAR; dxMip = D3D11_FILTER_TYPE_POINT; break; + case GL_NEAREST_MIPMAP_NEAREST: dxMin = D3D11_FILTER_TYPE_POINT; dxMip = D3D11_FILTER_TYPE_POINT; break; + case GL_LINEAR_MIPMAP_NEAREST: dxMin = D3D11_FILTER_TYPE_LINEAR; dxMip = D3D11_FILTER_TYPE_POINT; break; + case GL_NEAREST_MIPMAP_LINEAR: dxMin = D3D11_FILTER_TYPE_POINT; dxMip = D3D11_FILTER_TYPE_LINEAR; break; + case GL_LINEAR_MIPMAP_LINEAR: dxMin = D3D11_FILTER_TYPE_LINEAR; dxMip = D3D11_FILTER_TYPE_LINEAR; break; + default: UNREACHABLE(); + } + + D3D11_FILTER_TYPE dxMag = D3D11_FILTER_TYPE_POINT; + switch (magFilter) + { + case GL_NEAREST: dxMag = D3D11_FILTER_TYPE_POINT; break; + case GL_LINEAR: dxMag = D3D11_FILTER_TYPE_LINEAR; break; + default: UNREACHABLE(); + } + + return D3D11_ENCODE_BASIC_FILTER(dxMin, dxMag, dxMip, false); + } +} + +D3D11_TEXTURE_ADDRESS_MODE ConvertTextureWrap(GLenum wrap) +{ + switch (wrap) + { + case GL_REPEAT: return D3D11_TEXTURE_ADDRESS_WRAP; + case GL_CLAMP_TO_EDGE: return D3D11_TEXTURE_ADDRESS_CLAMP; + case GL_MIRRORED_REPEAT: return D3D11_TEXTURE_ADDRESS_MIRROR; + default: UNREACHABLE(); + } + + return D3D11_TEXTURE_ADDRESS_WRAP; +} + +FLOAT ConvertMinLOD(GLenum minFilter, unsigned int lodOffset) +{ + return (minFilter == GL_NEAREST || minFilter == GL_LINEAR) ? static_cast(lodOffset) : -FLT_MAX; +} + +FLOAT ConvertMaxLOD(GLenum minFilter, unsigned int lodOffset) +{ + return (minFilter == GL_NEAREST || minFilter == GL_LINEAR) ? static_cast(lodOffset) : FLT_MAX; +} + +} + +namespace d3d11_gl +{ + +GLenum ConvertBackBufferFormat(DXGI_FORMAT format) +{ + switch (format) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: return GL_RGBA8_OES; + case DXGI_FORMAT_B8G8R8A8_UNORM: return GL_BGRA8_EXT; + default: + UNREACHABLE(); + } + + return GL_RGBA8_OES; +} + +GLenum ConvertDepthStencilFormat(DXGI_FORMAT format) +{ + switch (format) + { + case DXGI_FORMAT_UNKNOWN: return GL_NONE; + case DXGI_FORMAT_D16_UNORM: return GL_DEPTH_COMPONENT16; + case DXGI_FORMAT_D24_UNORM_S8_UINT: return GL_DEPTH24_STENCIL8_OES; + default: + UNREACHABLE(); + } + + return GL_DEPTH24_STENCIL8_OES; +} + +GLenum ConvertRenderbufferFormat(DXGI_FORMAT format) +{ + switch (format) + { + case DXGI_FORMAT_B8G8R8A8_UNORM: + return GL_BGRA8_EXT; + case DXGI_FORMAT_R8G8B8A8_UNORM: + return GL_RGBA8_OES; + case DXGI_FORMAT_D16_UNORM: + return GL_DEPTH_COMPONENT16; + case DXGI_FORMAT_D24_UNORM_S8_UINT: + return GL_DEPTH24_STENCIL8_OES; + default: + UNREACHABLE(); + } + + return GL_RGBA8_OES; +} + +GLenum ConvertTextureInternalFormat(DXGI_FORMAT format) +{ + switch (format) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: + return GL_RGBA8_OES; + case DXGI_FORMAT_A8_UNORM: + return GL_ALPHA8_EXT; + case DXGI_FORMAT_BC1_UNORM: + return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; + case DXGI_FORMAT_BC2_UNORM: + return GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE; + case DXGI_FORMAT_BC3_UNORM: + return GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE; + case DXGI_FORMAT_R32G32B32A32_FLOAT: + return GL_RGBA32F_EXT; + case DXGI_FORMAT_R32G32B32_FLOAT: + return GL_RGB32F_EXT; + case DXGI_FORMAT_R16G16B16A16_FLOAT: + return GL_RGBA16F_EXT; + case DXGI_FORMAT_B8G8R8A8_UNORM: + return GL_BGRA8_EXT; + case DXGI_FORMAT_R8_UNORM: + return GL_R8_EXT; + case DXGI_FORMAT_R8G8_UNORM: + return GL_RG8_EXT; + case DXGI_FORMAT_R16_FLOAT: + return GL_R16F_EXT; + case DXGI_FORMAT_R16G16_FLOAT: + return GL_RG16F_EXT; + case DXGI_FORMAT_D16_UNORM: + return GL_DEPTH_COMPONENT16; + case DXGI_FORMAT_D24_UNORM_S8_UINT: + return GL_DEPTH24_STENCIL8_OES; + case DXGI_FORMAT_UNKNOWN: + return GL_NONE; + default: + UNREACHABLE(); + } + + return GL_RGBA8_OES; +} + +} + +namespace gl_d3d11 +{ + +DXGI_FORMAT ConvertRenderbufferFormat(GLenum format) +{ + switch (format) + { + case GL_RGBA4: + case GL_RGB5_A1: + case GL_RGBA8_OES: + case GL_RGB565: + case GL_RGB8_OES: + return DXGI_FORMAT_R8G8B8A8_UNORM; + case GL_BGRA8_EXT: + return DXGI_FORMAT_B8G8R8A8_UNORM; + case GL_DEPTH_COMPONENT16: + return DXGI_FORMAT_D16_UNORM; + case GL_STENCIL_INDEX8: + case GL_DEPTH24_STENCIL8_OES: + return DXGI_FORMAT_D24_UNORM_S8_UINT; + default: + UNREACHABLE(); + } + + return DXGI_FORMAT_R8G8B8A8_UNORM; +} + +DXGI_FORMAT ConvertTextureFormat(GLenum internalformat) +{ + switch (internalformat) + { + case GL_RGB565: + case GL_RGBA4: + case GL_RGB5_A1: + case GL_RGB8_OES: + case GL_RGBA8_OES: + case GL_LUMINANCE8_EXT: + case GL_LUMINANCE8_ALPHA8_EXT: + return DXGI_FORMAT_R8G8B8A8_UNORM; + case GL_ALPHA8_EXT: + return DXGI_FORMAT_A8_UNORM; + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + return DXGI_FORMAT_BC1_UNORM; + case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: + return DXGI_FORMAT_BC2_UNORM; + case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: + return DXGI_FORMAT_BC3_UNORM; + case GL_RGBA32F_EXT: + case GL_ALPHA32F_EXT: + case GL_LUMINANCE_ALPHA32F_EXT: + return DXGI_FORMAT_R32G32B32A32_FLOAT; + case GL_RGB32F_EXT: + case GL_LUMINANCE32F_EXT: + return DXGI_FORMAT_R32G32B32A32_FLOAT; + case GL_RGBA16F_EXT: + case GL_ALPHA16F_EXT: + case GL_LUMINANCE_ALPHA16F_EXT: + case GL_RGB16F_EXT: + case GL_LUMINANCE16F_EXT: + return DXGI_FORMAT_R16G16B16A16_FLOAT; + case GL_BGRA8_EXT: + return DXGI_FORMAT_B8G8R8A8_UNORM; + case GL_R8_EXT: + return DXGI_FORMAT_R8_UNORM; + case GL_RG8_EXT: + return DXGI_FORMAT_R8G8_UNORM; + case GL_R16F_EXT: + return DXGI_FORMAT_R16_FLOAT; + case GL_RG16F_EXT: + return DXGI_FORMAT_R16G16_FLOAT; + case GL_DEPTH_COMPONENT16: + return DXGI_FORMAT_D16_UNORM; + case GL_DEPTH_COMPONENT32_OES: + case GL_DEPTH24_STENCIL8_OES: + return DXGI_FORMAT_D24_UNORM_S8_UINT; + case GL_NONE: + return DXGI_FORMAT_UNKNOWN; + default: + UNREACHABLE(); + } + + return DXGI_FORMAT_R8G8B8A8_UNORM; +} + +} + +namespace d3d11 +{ + +void SetPositionTexCoordVertex(PositionTexCoordVertex* vertex, float x, float y, float u, float v) +{ + vertex->x = x; + vertex->y = y; + vertex->u = u; + vertex->v = v; +} + +void SetPositionDepthColorVertex(PositionDepthColorVertex* vertex, float x, float y, float z, + const gl::Color &color) +{ + vertex->x = x; + vertex->y = y; + vertex->z = z; + vertex->r = color.red; + vertex->g = color.green; + vertex->b = color.blue; + vertex->a = color.alpha; +} + +size_t ComputePixelSizeBits(DXGI_FORMAT format) +{ + switch (format) + { + case DXGI_FORMAT_R1_UNORM: + return 1; + + case DXGI_FORMAT_A8_UNORM: + case DXGI_FORMAT_R8_SINT: + case DXGI_FORMAT_R8_SNORM: + case DXGI_FORMAT_R8_TYPELESS: + case DXGI_FORMAT_R8_UINT: + case DXGI_FORMAT_R8_UNORM: + return 8; + + case DXGI_FORMAT_B5G5R5A1_UNORM: + case DXGI_FORMAT_B5G6R5_UNORM: + case DXGI_FORMAT_D16_UNORM: + case DXGI_FORMAT_R16_FLOAT: + case DXGI_FORMAT_R16_SINT: + case DXGI_FORMAT_R16_SNORM: + case DXGI_FORMAT_R16_TYPELESS: + case DXGI_FORMAT_R16_UINT: + case DXGI_FORMAT_R16_UNORM: + case DXGI_FORMAT_R8G8_SINT: + case DXGI_FORMAT_R8G8_SNORM: + case DXGI_FORMAT_R8G8_TYPELESS: + case DXGI_FORMAT_R8G8_UINT: + case DXGI_FORMAT_R8G8_UNORM: + return 16; + + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + case DXGI_FORMAT_B8G8R8X8_UNORM: + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + case DXGI_FORMAT_D24_UNORM_S8_UINT: + case DXGI_FORMAT_D32_FLOAT: + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + case DXGI_FORMAT_G8R8_G8B8_UNORM: + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + case DXGI_FORMAT_R10G10B10A2_UINT: + case DXGI_FORMAT_R10G10B10A2_UNORM: + case DXGI_FORMAT_R11G11B10_FLOAT: + case DXGI_FORMAT_R16G16_FLOAT: + case DXGI_FORMAT_R16G16_SINT: + case DXGI_FORMAT_R16G16_SNORM: + case DXGI_FORMAT_R16G16_TYPELESS: + case DXGI_FORMAT_R16G16_UINT: + case DXGI_FORMAT_R16G16_UNORM: + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + case DXGI_FORMAT_R24G8_TYPELESS: + case DXGI_FORMAT_R32_FLOAT: + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + case DXGI_FORMAT_R32_SINT: + case DXGI_FORMAT_R32_TYPELESS: + case DXGI_FORMAT_R32_UINT: + case DXGI_FORMAT_R8G8_B8G8_UNORM: + case DXGI_FORMAT_R8G8B8A8_SINT: + case DXGI_FORMAT_R8G8B8A8_SNORM: + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + case DXGI_FORMAT_R8G8B8A8_UINT: + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + return 32; + + case DXGI_FORMAT_R16G16B16A16_FLOAT: + case DXGI_FORMAT_R16G16B16A16_SINT: + case DXGI_FORMAT_R16G16B16A16_SNORM: + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + case DXGI_FORMAT_R16G16B16A16_UINT: + case DXGI_FORMAT_R16G16B16A16_UNORM: + case DXGI_FORMAT_R32G32_FLOAT: + case DXGI_FORMAT_R32G32_SINT: + case DXGI_FORMAT_R32G32_TYPELESS: + case DXGI_FORMAT_R32G32_UINT: + case DXGI_FORMAT_R32G8X24_TYPELESS: + return 64; + + case DXGI_FORMAT_R32G32B32_FLOAT: + case DXGI_FORMAT_R32G32B32_SINT: + case DXGI_FORMAT_R32G32B32_TYPELESS: + case DXGI_FORMAT_R32G32B32_UINT: + return 96; + + case DXGI_FORMAT_R32G32B32A32_FLOAT: + case DXGI_FORMAT_R32G32B32A32_SINT: + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + case DXGI_FORMAT_R32G32B32A32_UINT: + return 128; + + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT_BC4_SNORM: + case DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT_BC4_UNORM: + return 4; + + case DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT_BC5_SNORM: + case DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT_BC6H_SF16: + case DXGI_FORMAT_BC6H_TYPELESS: + case DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT_BC7_TYPELESS: + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: + return 8; + + default: + return 0; + } +} + +size_t ComputeBlockSizeBits(DXGI_FORMAT format) +{ + switch (format) + { + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT_BC4_SNORM: + case DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT_BC5_SNORM: + case DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT_BC6H_SF16: + case DXGI_FORMAT_BC6H_TYPELESS: + case DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT_BC7_TYPELESS: + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: + return ComputePixelSizeBits(format) * 16; + default: + UNREACHABLE(); + return 0; + } +} + +bool IsCompressed(DXGI_FORMAT format) +{ + switch (format) + { + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT_BC4_SNORM: + case DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT_BC5_SNORM: + case DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT_BC6H_SF16: + case DXGI_FORMAT_BC6H_TYPELESS: + case DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT_BC7_TYPELESS: + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: + return true; + case DXGI_FORMAT_UNKNOWN: + UNREACHABLE(); + return false; + default: + return false; + } +} + +unsigned int GetTextureFormatDimensionAlignment(DXGI_FORMAT format) +{ + switch (format) + { + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT_BC4_SNORM: + case DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT_BC5_SNORM: + case DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT_BC6H_SF16: + case DXGI_FORMAT_BC6H_TYPELESS: + case DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT_BC7_TYPELESS: + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: + return 4; + case DXGI_FORMAT_UNKNOWN: + UNREACHABLE(); + return 1; + default: + return 1; + } +} + +bool IsDepthStencilFormat(DXGI_FORMAT format) +{ + switch (format) + { + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + case DXGI_FORMAT_D32_FLOAT: + case DXGI_FORMAT_D24_UNORM_S8_UINT: + case DXGI_FORMAT_D16_UNORM: + return true; + default: + return false; + } +} + +DXGI_FORMAT GetDepthTextureFormat(DXGI_FORMAT format) +{ + switch (format) + { + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: return DXGI_FORMAT_R32G8X24_TYPELESS; + case DXGI_FORMAT_D32_FLOAT: return DXGI_FORMAT_R32_TYPELESS; + case DXGI_FORMAT_D24_UNORM_S8_UINT: return DXGI_FORMAT_R24G8_TYPELESS; + case DXGI_FORMAT_D16_UNORM: return DXGI_FORMAT_R16_TYPELESS; + default: UNREACHABLE(); return DXGI_FORMAT_UNKNOWN; + } +} + +DXGI_FORMAT GetDepthShaderResourceFormat(DXGI_FORMAT format) +{ + switch (format) + { + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS; + case DXGI_FORMAT_D32_FLOAT: return DXGI_FORMAT_R32_UINT; + case DXGI_FORMAT_D24_UNORM_S8_UINT: return DXGI_FORMAT_R24_UNORM_X8_TYPELESS; + case DXGI_FORMAT_D16_UNORM: return DXGI_FORMAT_R16_UNORM; + default: UNREACHABLE(); return DXGI_FORMAT_UNKNOWN; + } +} + +HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name) +{ +#if defined(_DEBUG) + return resource->SetPrivateData(WKPDID_D3DDebugObjectName, strlen(name), name); +#else + return S_OK; +#endif +} + +} diff --git a/gfx/angle/src/libGLESv2/renderer/renderer11_utils.h b/gfx/angle/src/libGLESv2/renderer/renderer11_utils.h new file mode 100644 index 000000000000..1bc48c1a135a --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/renderer11_utils.h @@ -0,0 +1,95 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// renderer11_utils.h: Conversion functions and other utility routines +// specific to the D3D11 renderer. + +#ifndef LIBGLESV2_RENDERER_RENDERER11_UTILS_H +#define LIBGLESV2_RENDERER_RENDERER11_UTILS_H + +#include "libGLESv2/angletypes.h" + +namespace gl_d3d11 +{ + +D3D11_BLEND ConvertBlendFunc(GLenum glBlend, bool isAlpha); +D3D11_BLEND_OP ConvertBlendOp(GLenum glBlendOp); +UINT8 ConvertColorMask(bool maskRed, bool maskGreen, bool maskBlue, bool maskAlpha); + +D3D11_CULL_MODE ConvertCullMode(bool cullEnabled, GLenum cullMode); + +D3D11_COMPARISON_FUNC ConvertComparison(GLenum comparison); +D3D11_DEPTH_WRITE_MASK ConvertDepthMask(bool depthWriteEnabled); +UINT8 ConvertStencilMask(GLuint stencilmask); +D3D11_STENCIL_OP ConvertStencilOp(GLenum stencilOp); + +D3D11_FILTER ConvertFilter(GLenum minFilter, GLenum magFilter, float maxAnisotropy); +D3D11_TEXTURE_ADDRESS_MODE ConvertTextureWrap(GLenum wrap); +FLOAT ConvertMinLOD(GLenum minFilter, unsigned int lodOffset); +FLOAT ConvertMaxLOD(GLenum minFilter, unsigned int lodOffset); + +DXGI_FORMAT ConvertRenderbufferFormat(GLenum format); +DXGI_FORMAT ConvertTextureFormat(GLenum format); +} + +namespace d3d11_gl +{ + +GLenum ConvertBackBufferFormat(DXGI_FORMAT format); +GLenum ConvertDepthStencilFormat(DXGI_FORMAT format); +GLenum ConvertRenderbufferFormat(DXGI_FORMAT format); +GLenum ConvertTextureInternalFormat(DXGI_FORMAT format); + +} + +namespace d3d11 +{ + +struct PositionTexCoordVertex +{ + float x, y; + float u, v; +}; +void SetPositionTexCoordVertex(PositionTexCoordVertex* vertex, float x, float y, float u, float v); + +struct PositionDepthColorVertex +{ + float x, y, z; + float r, g, b, a; +}; +void SetPositionDepthColorVertex(PositionDepthColorVertex* vertex, float x, float y, float z, + const gl::Color &color); + +size_t ComputePixelSizeBits(DXGI_FORMAT format); +size_t ComputeBlockSizeBits(DXGI_FORMAT format); + +bool IsCompressed(DXGI_FORMAT format); +unsigned int GetTextureFormatDimensionAlignment(DXGI_FORMAT format); + +bool IsDepthStencilFormat(DXGI_FORMAT format); +DXGI_FORMAT GetDepthTextureFormat(DXGI_FORMAT format); +DXGI_FORMAT GetDepthShaderResourceFormat(DXGI_FORMAT format); + +HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name); + +inline bool isDeviceLostError(HRESULT errorCode) +{ + switch (errorCode) + { + case DXGI_ERROR_DEVICE_HUNG: + case DXGI_ERROR_DEVICE_REMOVED: + case DXGI_ERROR_DEVICE_RESET: + case DXGI_ERROR_DRIVER_INTERNAL_ERROR: + case DXGI_ERROR_NOT_CURRENTLY_AVAILABLE: + return true; + default: + return false; + } +} + +} + +#endif // LIBGLESV2_RENDERER_RENDERER11_UTILS_H diff --git a/gfx/angle/src/libGLESv2/renderer/renderer9_utils.cpp b/gfx/angle/src/libGLESv2/renderer/renderer9_utils.cpp new file mode 100644 index 000000000000..da75d465e3cf --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/renderer9_utils.cpp @@ -0,0 +1,500 @@ +#include "precompiled.h" +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// renderer9_utils.cpp: Conversion functions and other utility routines +// specific to the D3D9 renderer. + +#include "libGLESv2/renderer/renderer9_utils.h" +#include "libGLESv2/mathutil.h" +#include "libGLESv2/Context.h" + +#include "common/debug.h" + +namespace gl_d3d9 +{ + +D3DCMPFUNC ConvertComparison(GLenum comparison) +{ + D3DCMPFUNC d3dComp = D3DCMP_ALWAYS; + switch (comparison) + { + case GL_NEVER: d3dComp = D3DCMP_NEVER; break; + case GL_ALWAYS: d3dComp = D3DCMP_ALWAYS; break; + case GL_LESS: d3dComp = D3DCMP_LESS; break; + case GL_LEQUAL: d3dComp = D3DCMP_LESSEQUAL; break; + case GL_EQUAL: d3dComp = D3DCMP_EQUAL; break; + case GL_GREATER: d3dComp = D3DCMP_GREATER; break; + case GL_GEQUAL: d3dComp = D3DCMP_GREATEREQUAL; break; + case GL_NOTEQUAL: d3dComp = D3DCMP_NOTEQUAL; break; + default: UNREACHABLE(); + } + + return d3dComp; +} + +D3DCOLOR ConvertColor(gl::Color color) +{ + return D3DCOLOR_RGBA(gl::unorm<8>(color.red), + gl::unorm<8>(color.green), + gl::unorm<8>(color.blue), + gl::unorm<8>(color.alpha)); +} + +D3DBLEND ConvertBlendFunc(GLenum blend) +{ + D3DBLEND d3dBlend = D3DBLEND_ZERO; + + switch (blend) + { + case GL_ZERO: d3dBlend = D3DBLEND_ZERO; break; + case GL_ONE: d3dBlend = D3DBLEND_ONE; break; + case GL_SRC_COLOR: d3dBlend = D3DBLEND_SRCCOLOR; break; + case GL_ONE_MINUS_SRC_COLOR: d3dBlend = D3DBLEND_INVSRCCOLOR; break; + case GL_DST_COLOR: d3dBlend = D3DBLEND_DESTCOLOR; break; + case GL_ONE_MINUS_DST_COLOR: d3dBlend = D3DBLEND_INVDESTCOLOR; break; + case GL_SRC_ALPHA: d3dBlend = D3DBLEND_SRCALPHA; break; + case GL_ONE_MINUS_SRC_ALPHA: d3dBlend = D3DBLEND_INVSRCALPHA; break; + case GL_DST_ALPHA: d3dBlend = D3DBLEND_DESTALPHA; break; + case GL_ONE_MINUS_DST_ALPHA: d3dBlend = D3DBLEND_INVDESTALPHA; break; + case GL_CONSTANT_COLOR: d3dBlend = D3DBLEND_BLENDFACTOR; break; + case GL_ONE_MINUS_CONSTANT_COLOR: d3dBlend = D3DBLEND_INVBLENDFACTOR; break; + case GL_CONSTANT_ALPHA: d3dBlend = D3DBLEND_BLENDFACTOR; break; + case GL_ONE_MINUS_CONSTANT_ALPHA: d3dBlend = D3DBLEND_INVBLENDFACTOR; break; + case GL_SRC_ALPHA_SATURATE: d3dBlend = D3DBLEND_SRCALPHASAT; break; + default: UNREACHABLE(); + } + + return d3dBlend; +} + +D3DBLENDOP ConvertBlendOp(GLenum blendOp) +{ + D3DBLENDOP d3dBlendOp = D3DBLENDOP_ADD; + + switch (blendOp) + { + case GL_FUNC_ADD: d3dBlendOp = D3DBLENDOP_ADD; break; + case GL_FUNC_SUBTRACT: d3dBlendOp = D3DBLENDOP_SUBTRACT; break; + case GL_FUNC_REVERSE_SUBTRACT: d3dBlendOp = D3DBLENDOP_REVSUBTRACT; break; + default: UNREACHABLE(); + } + + return d3dBlendOp; +} + +D3DSTENCILOP ConvertStencilOp(GLenum stencilOp) +{ + D3DSTENCILOP d3dStencilOp = D3DSTENCILOP_KEEP; + + switch (stencilOp) + { + case GL_ZERO: d3dStencilOp = D3DSTENCILOP_ZERO; break; + case GL_KEEP: d3dStencilOp = D3DSTENCILOP_KEEP; break; + case GL_REPLACE: d3dStencilOp = D3DSTENCILOP_REPLACE; break; + case GL_INCR: d3dStencilOp = D3DSTENCILOP_INCRSAT; break; + case GL_DECR: d3dStencilOp = D3DSTENCILOP_DECRSAT; break; + case GL_INVERT: d3dStencilOp = D3DSTENCILOP_INVERT; break; + case GL_INCR_WRAP: d3dStencilOp = D3DSTENCILOP_INCR; break; + case GL_DECR_WRAP: d3dStencilOp = D3DSTENCILOP_DECR; break; + default: UNREACHABLE(); + } + + return d3dStencilOp; +} + +D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap) +{ + D3DTEXTUREADDRESS d3dWrap = D3DTADDRESS_WRAP; + + switch (wrap) + { + case GL_REPEAT: d3dWrap = D3DTADDRESS_WRAP; break; + case GL_CLAMP_TO_EDGE: d3dWrap = D3DTADDRESS_CLAMP; break; + case GL_MIRRORED_REPEAT: d3dWrap = D3DTADDRESS_MIRROR; break; + default: UNREACHABLE(); + } + + return d3dWrap; +} + +D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace) +{ + D3DCULL cull = D3DCULL_CCW; + switch (cullFace) + { + case GL_FRONT: + cull = (frontFace == GL_CCW ? D3DCULL_CW : D3DCULL_CCW); + break; + case GL_BACK: + cull = (frontFace == GL_CCW ? D3DCULL_CCW : D3DCULL_CW); + break; + case GL_FRONT_AND_BACK: + cull = D3DCULL_NONE; // culling will be handled during draw + break; + default: UNREACHABLE(); + } + + return cull; +} + +D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace) +{ + D3DCUBEMAP_FACES face = D3DCUBEMAP_FACE_POSITIVE_X; + + switch (cubeFace) + { + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + face = D3DCUBEMAP_FACE_POSITIVE_X; + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + face = D3DCUBEMAP_FACE_NEGATIVE_X; + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + face = D3DCUBEMAP_FACE_POSITIVE_Y; + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + face = D3DCUBEMAP_FACE_NEGATIVE_Y; + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + face = D3DCUBEMAP_FACE_POSITIVE_Z; + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + face = D3DCUBEMAP_FACE_NEGATIVE_Z; + break; + default: UNREACHABLE(); + } + + return face; +} + +DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha) +{ + return (red ? D3DCOLORWRITEENABLE_RED : 0) | + (green ? D3DCOLORWRITEENABLE_GREEN : 0) | + (blue ? D3DCOLORWRITEENABLE_BLUE : 0) | + (alpha ? D3DCOLORWRITEENABLE_ALPHA : 0); +} + +D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter, float maxAnisotropy) +{ + if (maxAnisotropy > 1.0f) + { + return D3DTEXF_ANISOTROPIC; + } + + D3DTEXTUREFILTERTYPE d3dMagFilter = D3DTEXF_POINT; + switch (magFilter) + { + case GL_NEAREST: d3dMagFilter = D3DTEXF_POINT; break; + case GL_LINEAR: d3dMagFilter = D3DTEXF_LINEAR; break; + default: UNREACHABLE(); + } + + return d3dMagFilter; +} + +void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter, float maxAnisotropy) +{ + switch (minFilter) + { + case GL_NEAREST: + *d3dMinFilter = D3DTEXF_POINT; + *d3dMipFilter = D3DTEXF_NONE; + break; + case GL_LINEAR: + *d3dMinFilter = D3DTEXF_LINEAR; + *d3dMipFilter = D3DTEXF_NONE; + break; + case GL_NEAREST_MIPMAP_NEAREST: + *d3dMinFilter = D3DTEXF_POINT; + *d3dMipFilter = D3DTEXF_POINT; + break; + case GL_LINEAR_MIPMAP_NEAREST: + *d3dMinFilter = D3DTEXF_LINEAR; + *d3dMipFilter = D3DTEXF_POINT; + break; + case GL_NEAREST_MIPMAP_LINEAR: + *d3dMinFilter = D3DTEXF_POINT; + *d3dMipFilter = D3DTEXF_LINEAR; + break; + case GL_LINEAR_MIPMAP_LINEAR: + *d3dMinFilter = D3DTEXF_LINEAR; + *d3dMipFilter = D3DTEXF_LINEAR; + break; + default: + *d3dMinFilter = D3DTEXF_POINT; + *d3dMipFilter = D3DTEXF_NONE; + UNREACHABLE(); + } + + if (maxAnisotropy > 1.0f) + { + *d3dMinFilter = D3DTEXF_ANISOTROPIC; + } +} + +D3DFORMAT ConvertRenderbufferFormat(GLenum format) +{ + switch (format) + { + case GL_NONE: return D3DFMT_NULL; + case GL_RGBA4: + case GL_RGB5_A1: + case GL_RGBA8_OES: return D3DFMT_A8R8G8B8; + case GL_RGB565: return D3DFMT_R5G6B5; + case GL_RGB8_OES: return D3DFMT_X8R8G8B8; + case GL_DEPTH_COMPONENT16: + case GL_STENCIL_INDEX8: + case GL_DEPTH24_STENCIL8_OES: return D3DFMT_D24S8; + default: UNREACHABLE(); return D3DFMT_A8R8G8B8; + } +} + +D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples) +{ + if (samples <= 1) + return D3DMULTISAMPLE_NONE; + else + return (D3DMULTISAMPLE_TYPE)samples; +} + +} + +namespace d3d9_gl +{ + +unsigned int GetStencilSize(D3DFORMAT stencilFormat) +{ + if (stencilFormat == D3DFMT_INTZ) + { + return 8; + } + switch(stencilFormat) + { + case D3DFMT_D24FS8: + case D3DFMT_D24S8: + return 8; + case D3DFMT_D24X4S4: + return 4; + case D3DFMT_D15S1: + return 1; + case D3DFMT_D16_LOCKABLE: + case D3DFMT_D32: + case D3DFMT_D24X8: + case D3DFMT_D32F_LOCKABLE: + case D3DFMT_D16: + return 0; + //case D3DFMT_D32_LOCKABLE: return 0; // DirectX 9Ex only + //case D3DFMT_S8_LOCKABLE: return 8; // DirectX 9Ex only + default: + return 0; + } +} + +unsigned int GetAlphaSize(D3DFORMAT colorFormat) +{ + switch (colorFormat) + { + case D3DFMT_A16B16G16R16F: + return 16; + case D3DFMT_A32B32G32R32F: + return 32; + case D3DFMT_A2R10G10B10: + return 2; + case D3DFMT_A8R8G8B8: + return 8; + case D3DFMT_A1R5G5B5: + return 1; + case D3DFMT_X8R8G8B8: + case D3DFMT_R5G6B5: + return 0; + default: + return 0; + } +} + +GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type) +{ + if (type == D3DMULTISAMPLE_NONMASKABLE) + return 0; + else + return type; +} + +bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format) +{ + switch (d3dformat) + { + case D3DFMT_L8: + return (format == GL_LUMINANCE); + case D3DFMT_A8L8: + return (format == GL_LUMINANCE_ALPHA); + case D3DFMT_DXT1: + return (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT || format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT); + case D3DFMT_DXT3: + return (format == GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE); + case D3DFMT_DXT5: + return (format == GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE); + case D3DFMT_A8R8G8B8: + case D3DFMT_A16B16G16R16F: + case D3DFMT_A32B32G32R32F: + return (format == GL_RGBA || format == GL_BGRA_EXT); + case D3DFMT_X8R8G8B8: + return (format == GL_RGB); + default: + if (d3dformat == D3DFMT_INTZ && gl::IsDepthTexture(format)) + return true; + return false; + } +} + +GLenum ConvertBackBufferFormat(D3DFORMAT format) +{ + switch (format) + { + case D3DFMT_A4R4G4B4: return GL_RGBA4; + case D3DFMT_A8R8G8B8: return GL_RGBA8_OES; + case D3DFMT_A1R5G5B5: return GL_RGB5_A1; + case D3DFMT_R5G6B5: return GL_RGB565; + case D3DFMT_X8R8G8B8: return GL_RGB8_OES; + default: + UNREACHABLE(); + } + + return GL_RGBA4; +} + +GLenum ConvertDepthStencilFormat(D3DFORMAT format) +{ + if (format == D3DFMT_INTZ) + { + return GL_DEPTH24_STENCIL8_OES; + } + switch (format) + { + case D3DFMT_D16: + case D3DFMT_D24X8: + return GL_DEPTH_COMPONENT16; + case D3DFMT_D24S8: + return GL_DEPTH24_STENCIL8_OES; + case D3DFMT_UNKNOWN: + return GL_NONE; + default: + UNREACHABLE(); + } + + return GL_DEPTH24_STENCIL8_OES; +} + +GLenum ConvertRenderTargetFormat(D3DFORMAT format) +{ + if (format == D3DFMT_INTZ) + { + return GL_DEPTH24_STENCIL8_OES; + } + + switch (format) + { + case D3DFMT_A4R4G4B4: return GL_RGBA4; + case D3DFMT_A8R8G8B8: return GL_RGBA8_OES; + case D3DFMT_A1R5G5B5: return GL_RGB5_A1; + case D3DFMT_R5G6B5: return GL_RGB565; + case D3DFMT_X8R8G8B8: return GL_RGB8_OES; + case D3DFMT_D16: + case D3DFMT_D24X8: + return GL_DEPTH_COMPONENT16; + case D3DFMT_D24S8: + return GL_DEPTH24_STENCIL8_OES; + case D3DFMT_UNKNOWN: + return GL_NONE; + default: + UNREACHABLE(); + } + + return GL_RGBA4; +} + +GLenum GetEquivalentFormat(D3DFORMAT format) +{ + if (format == D3DFMT_INTZ) + return GL_DEPTH24_STENCIL8_OES; + if (format == D3DFMT_NULL) + return GL_NONE; + + switch (format) + { + case D3DFMT_A4R4G4B4: return GL_RGBA4; + case D3DFMT_A8R8G8B8: return GL_RGBA8_OES; + case D3DFMT_A1R5G5B5: return GL_RGB5_A1; + case D3DFMT_R5G6B5: return GL_RGB565; + case D3DFMT_X8R8G8B8: return GL_RGB8_OES; + case D3DFMT_D16: return GL_DEPTH_COMPONENT16; + case D3DFMT_D24S8: return GL_DEPTH24_STENCIL8_OES; + case D3DFMT_UNKNOWN: return GL_NONE; + case D3DFMT_DXT1: return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; + case D3DFMT_DXT3: return GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE; + case D3DFMT_DXT5: return GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE; + case D3DFMT_A32B32G32R32F: return GL_RGBA32F_EXT; + case D3DFMT_A16B16G16R16F: return GL_RGBA16F_EXT; + case D3DFMT_L8: return GL_LUMINANCE8_EXT; + case D3DFMT_A8L8: return GL_LUMINANCE8_ALPHA8_EXT; + default: UNREACHABLE(); + return GL_NONE; + } +} + +} + +namespace d3d9 +{ + +bool IsCompressedFormat(D3DFORMAT surfaceFormat) +{ + switch(surfaceFormat) + { + case D3DFMT_DXT1: + case D3DFMT_DXT2: + case D3DFMT_DXT3: + case D3DFMT_DXT4: + case D3DFMT_DXT5: + return true; + default: + return false; + } +} + +size_t ComputeRowSize(D3DFORMAT format, unsigned int width) +{ + if (format == D3DFMT_INTZ) + { + return 4 * width; + } + switch (format) + { + case D3DFMT_L8: + return 1 * width; + case D3DFMT_A8L8: + return 2 * width; + case D3DFMT_X8R8G8B8: + case D3DFMT_A8R8G8B8: + return 4 * width; + case D3DFMT_A16B16G16R16F: + return 8 * width; + case D3DFMT_A32B32G32R32F: + return 16 * width; + case D3DFMT_DXT1: + return 8 * ((width + 3) / 4); + case D3DFMT_DXT3: + case D3DFMT_DXT5: + return 16 * ((width + 3) / 4); + default: + UNREACHABLE(); + return 0; + } +} + +} diff --git a/gfx/angle/src/libGLESv2/renderer/renderer9_utils.h b/gfx/angle/src/libGLESv2/renderer/renderer9_utils.h new file mode 100644 index 000000000000..bf6cdf1ea656 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/renderer9_utils.h @@ -0,0 +1,74 @@ +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// renderer9_utils.h: Conversion functions and other utility routines +// specific to the D3D9 renderer + +#ifndef LIBGLESV2_RENDERER_RENDERER9_UTILS_H +#define LIBGLESV2_RENDERER_RENDERER9_UTILS_H + +#include "libGLESv2/utilities.h" + +const D3DFORMAT D3DFMT_INTZ = ((D3DFORMAT)(MAKEFOURCC('I','N','T','Z'))); +const D3DFORMAT D3DFMT_NULL = ((D3DFORMAT)(MAKEFOURCC('N','U','L','L'))); + +namespace gl_d3d9 +{ + +D3DCMPFUNC ConvertComparison(GLenum comparison); +D3DCOLOR ConvertColor(gl::Color color); +D3DBLEND ConvertBlendFunc(GLenum blend); +D3DBLENDOP ConvertBlendOp(GLenum blendOp); +D3DSTENCILOP ConvertStencilOp(GLenum stencilOp); +D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap); +D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace); +D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace); +DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha); +D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter, float maxAnisotropy); +void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter, float maxAnisotropy); +D3DFORMAT ConvertRenderbufferFormat(GLenum format); +D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples); + +} + +namespace d3d9_gl +{ + +GLuint GetAlphaSize(D3DFORMAT colorFormat); +GLuint GetStencilSize(D3DFORMAT stencilFormat); + +GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type); + +bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format); +GLenum ConvertBackBufferFormat(D3DFORMAT format); +GLenum ConvertDepthStencilFormat(D3DFORMAT format); +GLenum ConvertRenderTargetFormat(D3DFORMAT format); +GLenum GetEquivalentFormat(D3DFORMAT format); + +} + +namespace d3d9 +{ +bool IsCompressedFormat(D3DFORMAT format); +size_t ComputeRowSize(D3DFORMAT format, unsigned int width); + +inline bool isDeviceLostError(HRESULT errorCode) +{ + switch (errorCode) + { + case D3DERR_DRIVERINTERNALERROR: + case D3DERR_DEVICELOST: + case D3DERR_DEVICEHUNG: + case D3DERR_DEVICEREMOVED: + return true; + default: + return false; + } +} + +} + +#endif // LIBGLESV2_RENDERER_RENDERER9_UTILS_H diff --git a/gfx/angle/src/libGLESv2/shaders/Blit.ps b/gfx/angle/src/libGLESv2/renderer/shaders/Blit.ps similarity index 100% rename from gfx/angle/src/libGLESv2/shaders/Blit.ps rename to gfx/angle/src/libGLESv2/renderer/shaders/Blit.ps diff --git a/gfx/angle/src/libGLESv2/shaders/Blit.vs b/gfx/angle/src/libGLESv2/renderer/shaders/Blit.vs similarity index 100% rename from gfx/angle/src/libGLESv2/shaders/Blit.vs rename to gfx/angle/src/libGLESv2/renderer/shaders/Blit.vs diff --git a/gfx/angle/src/libGLESv2/renderer/shaders/Clear11.hlsl b/gfx/angle/src/libGLESv2/renderer/shaders/Clear11.hlsl new file mode 100644 index 000000000000..042ac699b66a --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/shaders/Clear11.hlsl @@ -0,0 +1,38 @@ +void VS_Clear( in float3 inPosition : POSITION, in float4 inColor : COLOR, + out float4 outPosition : SV_POSITION, out float4 outColor : COLOR) +{ + outPosition = float4(inPosition, 1.0f); + outColor = inColor; +} + +// Assume we are in SM4+, which has 8 color outputs +struct PS_OutputMultiple +{ + float4 color0 : SV_TARGET0; + float4 color1 : SV_TARGET1; + float4 color2 : SV_TARGET2; + float4 color3 : SV_TARGET3; + float4 color4 : SV_TARGET4; + float4 color5 : SV_TARGET5; + float4 color6 : SV_TARGET6; + float4 color7 : SV_TARGET7; +}; + +PS_OutputMultiple PS_ClearMultiple(in float4 inPosition : SV_POSITION, in float4 inColor : COLOR) +{ + PS_OutputMultiple outColor; + outColor.color0 = inColor; + outColor.color1 = inColor; + outColor.color2 = inColor; + outColor.color3 = inColor; + outColor.color4 = inColor; + outColor.color5 = inColor; + outColor.color6 = inColor; + outColor.color7 = inColor; + return outColor; +} + +float4 PS_ClearSingle(in float4 inPosition : SV_Position, in float4 inColor : COLOR) : SV_Target0 +{ + return inColor; +} diff --git a/gfx/angle/src/libGLESv2/renderer/shaders/Passthrough11.hlsl b/gfx/angle/src/libGLESv2/renderer/shaders/Passthrough11.hlsl new file mode 100644 index 000000000000..43b7801efc1f --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/shaders/Passthrough11.hlsl @@ -0,0 +1,29 @@ +Texture2D Texture : register(t0); +SamplerState Sampler : register(s0); + +void VS_Passthrough( in float2 inPosition : POSITION, in float2 inTexCoord : TEXCOORD0, + out float4 outPosition : SV_POSITION, out float2 outTexCoord : TEXCOORD0) +{ + outPosition = float4(inPosition, 0.0f, 1.0f); + outTexCoord = inTexCoord; +} + +float4 PS_PassthroughRGBA(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return Texture.Sample(Sampler, inTexCoord).rgba; +} + +float4 PS_PassthroughRGB(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return float4(Texture.Sample(Sampler, inTexCoord).rgb, 1.0f); +} + +float4 PS_PassthroughLum(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return float4(Texture.Sample(Sampler, inTexCoord).rrr, 1.0f); +} + +float4 PS_PassthroughLumAlpha(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return Texture.Sample(Sampler, inTexCoord).rrra; +} diff --git a/gfx/angle/src/libGLESv2/renderer/shaders/compiled/clear11vs.h b/gfx/angle/src/libGLESv2/renderer/shaders/compiled/clear11vs.h new file mode 100644 index 000000000000..9f9c7017971d --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/shaders/compiled/clear11vs.h @@ -0,0 +1,133 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111 +// +// +// fxc /E VS_Clear /T vs_4_0 /Fh compiled/clear11vs.h Clear11.hlsl +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------ ------ +// POSITION 0 xyz 0 NONE float xyz +// COLOR 0 xyzw 1 NONE float xyzw +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------ ------ +// SV_POSITION 0 xyzw 0 POS float xyzw +// COLOR 0 xyzw 1 NONE float xyzw +// +vs_4_0 +dcl_input v0.xyz +dcl_input v1.xyzw +dcl_output_siv o0.xyzw, position +dcl_output o1.xyzw +mov o0.xyz, v0.xyzx +mov o0.w, l(1.000000) +mov o1.xyzw, v1.xyzw +ret +// Approximately 4 instruction slots used +#endif + +const BYTE g_VS_Clear[] = +{ + 68, 88, 66, 67, 109, 138, + 105, 83, 86, 190, 83, 125, + 72, 102, 194, 136, 46, 69, + 17, 121, 1, 0, 0, 0, + 48, 2, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 140, 0, 0, 0, 220, 0, + 0, 0, 48, 1, 0, 0, + 180, 1, 0, 0, 82, 68, + 69, 70, 80, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 28, 0, 0, 0, 0, 4, + 254, 255, 0, 1, 0, 0, + 28, 0, 0, 0, 77, 105, + 99, 114, 111, 115, 111, 102, + 116, 32, 40, 82, 41, 32, + 72, 76, 83, 76, 32, 83, + 104, 97, 100, 101, 114, 32, + 67, 111, 109, 112, 105, 108, + 101, 114, 32, 57, 46, 50, + 57, 46, 57, 53, 50, 46, + 51, 49, 49, 49, 0, 171, + 171, 171, 73, 83, 71, 78, + 72, 0, 0, 0, 2, 0, + 0, 0, 8, 0, 0, 0, + 56, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 7, 7, 0, 0, + 65, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 15, 15, 0, 0, + 80, 79, 83, 73, 84, 73, + 79, 78, 0, 67, 79, 76, + 79, 82, 0, 171, 79, 83, + 71, 78, 76, 0, 0, 0, + 2, 0, 0, 0, 8, 0, + 0, 0, 56, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 68, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 15, 0, + 0, 0, 83, 86, 95, 80, + 79, 83, 73, 84, 73, 79, + 78, 0, 67, 79, 76, 79, + 82, 0, 171, 171, 83, 72, + 68, 82, 124, 0, 0, 0, + 64, 0, 1, 0, 31, 0, + 0, 0, 95, 0, 0, 3, + 114, 16, 16, 0, 0, 0, + 0, 0, 95, 0, 0, 3, + 242, 16, 16, 0, 1, 0, + 0, 0, 103, 0, 0, 4, + 242, 32, 16, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 1, 0, 0, 0, + 54, 0, 0, 5, 114, 32, + 16, 0, 0, 0, 0, 0, + 70, 18, 16, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 130, 32, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 63, 54, 0, + 0, 5, 242, 32, 16, 0, + 1, 0, 0, 0, 70, 30, + 16, 0, 1, 0, 0, 0, + 62, 0, 0, 1, 83, 84, + 65, 84, 116, 0, 0, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; diff --git a/gfx/angle/src/libGLESv2/renderer/shaders/compiled/clearmultiple11ps.h b/gfx/angle/src/libGLESv2/renderer/shaders/compiled/clearmultiple11ps.h new file mode 100644 index 000000000000..c70eebb8b322 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/shaders/compiled/clearmultiple11ps.h @@ -0,0 +1,199 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111 +// +// +// fxc /E PS_ClearMultiple /T ps_4_0 /Fh compiled/clearmultiple11ps.h +// Clear11.hlsl +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------ ------ +// SV_POSITION 0 xyzw 0 POS float +// COLOR 0 xyzw 1 NONE float xyzw +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------ ------ +// SV_TARGET 0 xyzw 0 TARGET float xyzw +// SV_TARGET 1 xyzw 1 TARGET float xyzw +// SV_TARGET 2 xyzw 2 TARGET float xyzw +// SV_TARGET 3 xyzw 3 TARGET float xyzw +// SV_TARGET 4 xyzw 4 TARGET float xyzw +// SV_TARGET 5 xyzw 5 TARGET float xyzw +// SV_TARGET 6 xyzw 6 TARGET float xyzw +// SV_TARGET 7 xyzw 7 TARGET float xyzw +// +ps_4_0 +dcl_input_ps linear v1.xyzw +dcl_output o0.xyzw +dcl_output o1.xyzw +dcl_output o2.xyzw +dcl_output o3.xyzw +dcl_output o4.xyzw +dcl_output o5.xyzw +dcl_output o6.xyzw +dcl_output o7.xyzw +mov o0.xyzw, v1.xyzw +mov o1.xyzw, v1.xyzw +mov o2.xyzw, v1.xyzw +mov o3.xyzw, v1.xyzw +mov o4.xyzw, v1.xyzw +mov o5.xyzw, v1.xyzw +mov o6.xyzw, v1.xyzw +mov o7.xyzw, v1.xyzw +ret +// Approximately 9 instruction slots used +#endif + +const BYTE g_PS_ClearMultiple[] = +{ + 68, 88, 66, 67, 146, 246, + 236, 240, 50, 40, 87, 55, + 73, 140, 251, 200, 8, 22, + 173, 117, 1, 0, 0, 0, + 88, 3, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 140, 0, 0, 0, 224, 0, + 0, 0, 188, 1, 0, 0, + 220, 2, 0, 0, 82, 68, + 69, 70, 80, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 28, 0, 0, 0, 0, 4, + 255, 255, 0, 1, 0, 0, + 28, 0, 0, 0, 77, 105, + 99, 114, 111, 115, 111, 102, + 116, 32, 40, 82, 41, 32, + 72, 76, 83, 76, 32, 83, + 104, 97, 100, 101, 114, 32, + 67, 111, 109, 112, 105, 108, + 101, 114, 32, 57, 46, 50, + 57, 46, 57, 53, 50, 46, + 51, 49, 49, 49, 0, 171, + 171, 171, 73, 83, 71, 78, + 76, 0, 0, 0, 2, 0, + 0, 0, 8, 0, 0, 0, + 56, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 68, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 15, 15, 0, 0, + 83, 86, 95, 80, 79, 83, + 73, 84, 73, 79, 78, 0, + 67, 79, 76, 79, 82, 0, + 171, 171, 79, 83, 71, 78, + 212, 0, 0, 0, 8, 0, + 0, 0, 8, 0, 0, 0, + 200, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 200, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 15, 0, 0, 0, + 200, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 2, 0, + 0, 0, 15, 0, 0, 0, + 200, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 3, 0, + 0, 0, 15, 0, 0, 0, + 200, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 4, 0, + 0, 0, 15, 0, 0, 0, + 200, 0, 0, 0, 5, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 5, 0, + 0, 0, 15, 0, 0, 0, + 200, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 6, 0, + 0, 0, 15, 0, 0, 0, + 200, 0, 0, 0, 7, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 7, 0, + 0, 0, 15, 0, 0, 0, + 83, 86, 95, 84, 65, 82, + 71, 69, 84, 0, 171, 171, + 83, 72, 68, 82, 24, 1, + 0, 0, 64, 0, 0, 0, + 70, 0, 0, 0, 98, 16, + 0, 3, 242, 16, 16, 0, + 1, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 0, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 1, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 2, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 3, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 4, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 5, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 6, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 7, 0, 0, 0, 54, 0, + 0, 5, 242, 32, 16, 0, + 0, 0, 0, 0, 70, 30, + 16, 0, 1, 0, 0, 0, + 54, 0, 0, 5, 242, 32, + 16, 0, 1, 0, 0, 0, + 70, 30, 16, 0, 1, 0, + 0, 0, 54, 0, 0, 5, + 242, 32, 16, 0, 2, 0, + 0, 0, 70, 30, 16, 0, + 1, 0, 0, 0, 54, 0, + 0, 5, 242, 32, 16, 0, + 3, 0, 0, 0, 70, 30, + 16, 0, 1, 0, 0, 0, + 54, 0, 0, 5, 242, 32, + 16, 0, 4, 0, 0, 0, + 70, 30, 16, 0, 1, 0, + 0, 0, 54, 0, 0, 5, + 242, 32, 16, 0, 5, 0, + 0, 0, 70, 30, 16, 0, + 1, 0, 0, 0, 54, 0, + 0, 5, 242, 32, 16, 0, + 6, 0, 0, 0, 70, 30, + 16, 0, 1, 0, 0, 0, + 54, 0, 0, 5, 242, 32, + 16, 0, 7, 0, 0, 0, + 70, 30, 16, 0, 1, 0, + 0, 0, 62, 0, 0, 1, + 83, 84, 65, 84, 116, 0, + 0, 0, 9, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 9, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; diff --git a/gfx/angle/src/libGLESv2/renderer/shaders/compiled/clearsingle11ps.h b/gfx/angle/src/libGLESv2/renderer/shaders/compiled/clearsingle11ps.h new file mode 100644 index 000000000000..20395e2a70b1 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/shaders/compiled/clearsingle11ps.h @@ -0,0 +1,113 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111 +// +// +// fxc /E PS_ClearSingle /T ps_4_0 /Fh compiled/clearsingle11ps.h +// Clear11.hlsl +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------ ------ +// SV_Position 0 xyzw 0 POS float +// COLOR 0 xyzw 1 NONE float xyzw +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------ ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_4_0 +dcl_input_ps linear v1.xyzw +dcl_output o0.xyzw +mov o0.xyzw, v1.xyzw +ret +// Approximately 2 instruction slots used +#endif + +const BYTE g_PS_ClearSingle[] = +{ + 68, 88, 66, 67, 11, 49, + 220, 157, 35, 106, 175, 161, + 180, 178, 147, 150, 134, 162, + 222, 79, 1, 0, 0, 0, + 208, 1, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 140, 0, 0, 0, 224, 0, + 0, 0, 20, 1, 0, 0, + 84, 1, 0, 0, 82, 68, + 69, 70, 80, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 28, 0, 0, 0, 0, 4, + 255, 255, 0, 1, 0, 0, + 28, 0, 0, 0, 77, 105, + 99, 114, 111, 115, 111, 102, + 116, 32, 40, 82, 41, 32, + 72, 76, 83, 76, 32, 83, + 104, 97, 100, 101, 114, 32, + 67, 111, 109, 112, 105, 108, + 101, 114, 32, 57, 46, 50, + 57, 46, 57, 53, 50, 46, + 51, 49, 49, 49, 0, 171, + 171, 171, 73, 83, 71, 78, + 76, 0, 0, 0, 2, 0, + 0, 0, 8, 0, 0, 0, + 56, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 68, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 15, 15, 0, 0, + 83, 86, 95, 80, 111, 115, + 105, 116, 105, 111, 110, 0, + 67, 79, 76, 79, 82, 0, + 171, 171, 79, 83, 71, 78, + 44, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 83, 86, 95, 84, 97, 114, + 103, 101, 116, 0, 171, 171, + 83, 72, 68, 82, 56, 0, + 0, 0, 64, 0, 0, 0, + 14, 0, 0, 0, 98, 16, + 0, 3, 242, 16, 16, 0, + 1, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 242, 32, 16, 0, + 0, 0, 0, 0, 70, 30, + 16, 0, 1, 0, 0, 0, + 62, 0, 0, 1, 83, 84, + 65, 84, 116, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; diff --git a/gfx/angle/src/libGLESv2/shaders/componentmaskps.h b/gfx/angle/src/libGLESv2/renderer/shaders/compiled/componentmaskps.h similarity index 93% rename from gfx/angle/src/libGLESv2/shaders/componentmaskps.h rename to gfx/angle/src/libGLESv2/renderer/shaders/compiled/componentmaskps.h index d902f7450afd..2b8f04b4f78b 100644 --- a/gfx/angle/src/libGLESv2/shaders/componentmaskps.h +++ b/gfx/angle/src/libGLESv2/renderer/shaders/compiled/componentmaskps.h @@ -1,81 +1,81 @@ -#if 0 -// -// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111 -// -// fxc /E componentmaskps /T ps_2_0 /Fh componentmaskps.h Blit.ps -// -// -// Parameters: -// -// float4 mode; -// sampler2D tex; -// -// -// Registers: -// -// Name Reg Size -// ------------ ----- ---- -// mode c0 1 -// tex s0 1 -// - - ps_2_0 - dcl t0.xy - dcl_2d s0 - texld r0, t0, s0 - mul r1.xyz, r0, c0.x - mad r1.w, r0.w, c0.z, c0.w - mov oC0, r1 - -// approximately 4 instruction slots used (1 texture, 3 arithmetic) -#endif - -const BYTE g_ps20_componentmaskps[] = -{ - 0, 2, 255, 255, 254, 255, - 43, 0, 67, 84, 65, 66, - 28, 0, 0, 0, 119, 0, - 0, 0, 0, 2, 255, 255, - 2, 0, 0, 0, 28, 0, - 0, 0, 0, 1, 0, 0, - 112, 0, 0, 0, 68, 0, - 0, 0, 2, 0, 0, 0, - 1, 0, 0, 0, 76, 0, - 0, 0, 0, 0, 0, 0, - 92, 0, 0, 0, 3, 0, - 0, 0, 1, 0, 0, 0, - 96, 0, 0, 0, 0, 0, - 0, 0, 109, 111, 100, 101, - 0, 171, 171, 171, 1, 0, - 3, 0, 1, 0, 4, 0, - 1, 0, 0, 0, 0, 0, - 0, 0, 116, 101, 120, 0, - 4, 0, 12, 0, 1, 0, - 1, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 112, 115, - 95, 50, 95, 48, 0, 77, - 105, 99, 114, 111, 115, 111, - 102, 116, 32, 40, 82, 41, - 32, 72, 76, 83, 76, 32, - 83, 104, 97, 100, 101, 114, - 32, 67, 111, 109, 112, 105, - 108, 101, 114, 32, 57, 46, - 50, 57, 46, 57, 53, 50, - 46, 51, 49, 49, 49, 0, - 31, 0, 0, 2, 0, 0, - 0, 128, 0, 0, 3, 176, - 31, 0, 0, 2, 0, 0, - 0, 144, 0, 8, 15, 160, - 66, 0, 0, 3, 0, 0, - 15, 128, 0, 0, 228, 176, - 0, 8, 228, 160, 5, 0, - 0, 3, 1, 0, 7, 128, - 0, 0, 228, 128, 0, 0, - 0, 160, 4, 0, 0, 4, - 1, 0, 8, 128, 0, 0, - 255, 128, 0, 0, 170, 160, - 0, 0, 255, 160, 1, 0, - 0, 2, 0, 8, 15, 128, - 1, 0, 228, 128, 255, 255, - 0, 0 -}; +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111 +// +// fxc /E componentmaskps /T ps_2_0 /Fh compiled/componentmaskps.h Blit.ps +// +// +// Parameters: +// +// float4 mode; +// sampler2D tex; +// +// +// Registers: +// +// Name Reg Size +// ------------ ----- ---- +// mode c0 1 +// tex s0 1 +// + + ps_2_0 + dcl t0.xy + dcl_2d s0 + texld r0, t0, s0 + mul r1.xyz, r0, c0.x + mad r1.w, r0.w, c0.z, c0.w + mov oC0, r1 + +// approximately 4 instruction slots used (1 texture, 3 arithmetic) +#endif + +const BYTE g_ps20_componentmaskps[] = +{ + 0, 2, 255, 255, 254, 255, + 43, 0, 67, 84, 65, 66, + 28, 0, 0, 0, 119, 0, + 0, 0, 0, 2, 255, 255, + 2, 0, 0, 0, 28, 0, + 0, 0, 0, 1, 0, 0, + 112, 0, 0, 0, 68, 0, + 0, 0, 2, 0, 0, 0, + 1, 0, 0, 0, 76, 0, + 0, 0, 0, 0, 0, 0, + 92, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 96, 0, 0, 0, 0, 0, + 0, 0, 109, 111, 100, 101, + 0, 171, 171, 171, 1, 0, + 3, 0, 1, 0, 4, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 116, 101, 120, 0, + 4, 0, 12, 0, 1, 0, + 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 112, 115, + 95, 50, 95, 48, 0, 77, + 105, 99, 114, 111, 115, 111, + 102, 116, 32, 40, 82, 41, + 32, 72, 76, 83, 76, 32, + 83, 104, 97, 100, 101, 114, + 32, 67, 111, 109, 112, 105, + 108, 101, 114, 32, 57, 46, + 50, 57, 46, 57, 53, 50, + 46, 51, 49, 49, 49, 0, + 31, 0, 0, 2, 0, 0, + 0, 128, 0, 0, 3, 176, + 31, 0, 0, 2, 0, 0, + 0, 144, 0, 8, 15, 160, + 66, 0, 0, 3, 0, 0, + 15, 128, 0, 0, 228, 176, + 0, 8, 228, 160, 5, 0, + 0, 3, 1, 0, 7, 128, + 0, 0, 228, 128, 0, 0, + 0, 160, 4, 0, 0, 4, + 1, 0, 8, 128, 0, 0, + 255, 128, 0, 0, 170, 160, + 0, 0, 255, 160, 1, 0, + 0, 2, 0, 8, 15, 128, + 1, 0, 228, 128, 255, 255, + 0, 0 +}; diff --git a/gfx/angle/src/libGLESv2/shaders/flipyvs.h b/gfx/angle/src/libGLESv2/renderer/shaders/compiled/flipyvs.h similarity index 93% rename from gfx/angle/src/libGLESv2/shaders/flipyvs.h rename to gfx/angle/src/libGLESv2/renderer/shaders/compiled/flipyvs.h index b810792a954c..ef121016e951 100644 --- a/gfx/angle/src/libGLESv2/shaders/flipyvs.h +++ b/gfx/angle/src/libGLESv2/renderer/shaders/compiled/flipyvs.h @@ -1,69 +1,69 @@ -#if 0 -// -// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111 -// -// fxc /E flipyvs /T vs_2_0 /Fh flipyvs.h Blit.vs -// -// -// Parameters: -// -// float4 halfPixelSize; -// -// -// Registers: -// -// Name Reg Size -// ------------- ----- ---- -// halfPixelSize c0 1 -// - - vs_2_0 - def c1, 0.5, 1, 0, 0 - dcl_position v0 - add oPos, v0, c0 - mad oT0, v0, c1.xxyy, c1.xxzz - -// approximately 2 instruction slots used -#endif - -const BYTE g_vs20_flipyvs[] = -{ - 0, 2, 254, 255, 254, 255, - 35, 0, 67, 84, 65, 66, - 28, 0, 0, 0, 87, 0, - 0, 0, 0, 2, 254, 255, - 1, 0, 0, 0, 28, 0, - 0, 0, 0, 1, 0, 0, - 80, 0, 0, 0, 48, 0, - 0, 0, 2, 0, 0, 0, - 1, 0, 0, 0, 64, 0, - 0, 0, 0, 0, 0, 0, - 104, 97, 108, 102, 80, 105, - 120, 101, 108, 83, 105, 122, - 101, 0, 171, 171, 1, 0, - 3, 0, 1, 0, 4, 0, - 1, 0, 0, 0, 0, 0, - 0, 0, 118, 115, 95, 50, - 95, 48, 0, 77, 105, 99, - 114, 111, 115, 111, 102, 116, - 32, 40, 82, 41, 32, 72, - 76, 83, 76, 32, 83, 104, - 97, 100, 101, 114, 32, 67, - 111, 109, 112, 105, 108, 101, - 114, 32, 57, 46, 50, 57, - 46, 57, 53, 50, 46, 51, - 49, 49, 49, 0, 81, 0, - 0, 5, 1, 0, 15, 160, - 0, 0, 0, 63, 0, 0, - 128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 31, 0, - 0, 2, 0, 0, 0, 128, - 0, 0, 15, 144, 2, 0, - 0, 3, 0, 0, 15, 192, - 0, 0, 228, 144, 0, 0, - 228, 160, 4, 0, 0, 4, - 0, 0, 15, 224, 0, 0, - 228, 144, 1, 0, 80, 160, - 1, 0, 160, 160, 255, 255, - 0, 0 -}; +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111 +// +// fxc /E flipyvs /T vs_2_0 /Fh compiled/flipyvs.h Blit.vs +// +// +// Parameters: +// +// float4 halfPixelSize; +// +// +// Registers: +// +// Name Reg Size +// ------------- ----- ---- +// halfPixelSize c0 1 +// + + vs_2_0 + def c1, 0.5, 1, 0, 0 + dcl_position v0 + add oPos, v0, c0 + mad oT0, v0, c1.xxyy, c1.xxzz + +// approximately 2 instruction slots used +#endif + +const BYTE g_vs20_flipyvs[] = +{ + 0, 2, 254, 255, 254, 255, + 35, 0, 67, 84, 65, 66, + 28, 0, 0, 0, 87, 0, + 0, 0, 0, 2, 254, 255, + 1, 0, 0, 0, 28, 0, + 0, 0, 0, 1, 0, 0, + 80, 0, 0, 0, 48, 0, + 0, 0, 2, 0, 0, 0, + 1, 0, 0, 0, 64, 0, + 0, 0, 0, 0, 0, 0, + 104, 97, 108, 102, 80, 105, + 120, 101, 108, 83, 105, 122, + 101, 0, 171, 171, 1, 0, + 3, 0, 1, 0, 4, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 118, 115, 95, 50, + 95, 48, 0, 77, 105, 99, + 114, 111, 115, 111, 102, 116, + 32, 40, 82, 41, 32, 72, + 76, 83, 76, 32, 83, 104, + 97, 100, 101, 114, 32, 67, + 111, 109, 112, 105, 108, 101, + 114, 32, 57, 46, 50, 57, + 46, 57, 53, 50, 46, 51, + 49, 49, 49, 0, 81, 0, + 0, 5, 1, 0, 15, 160, + 0, 0, 0, 63, 0, 0, + 128, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 31, 0, + 0, 2, 0, 0, 0, 128, + 0, 0, 15, 144, 2, 0, + 0, 3, 0, 0, 15, 192, + 0, 0, 228, 144, 0, 0, + 228, 160, 4, 0, 0, 4, + 0, 0, 15, 224, 0, 0, + 228, 144, 1, 0, 80, 160, + 1, 0, 160, 160, 255, 255, + 0, 0 +}; diff --git a/gfx/angle/src/libGLESv2/shaders/luminanceps.h b/gfx/angle/src/libGLESv2/renderer/shaders/compiled/luminanceps.h similarity index 93% rename from gfx/angle/src/libGLESv2/shaders/luminanceps.h rename to gfx/angle/src/libGLESv2/renderer/shaders/compiled/luminanceps.h index 2d0bc9da2507..44dc749860e1 100644 --- a/gfx/angle/src/libGLESv2/shaders/luminanceps.h +++ b/gfx/angle/src/libGLESv2/renderer/shaders/compiled/luminanceps.h @@ -1,80 +1,80 @@ -#if 0 -// -// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111 -// -// fxc /E luminanceps /T ps_2_0 /Fh luminanceps.h Blit.ps -// -// -// Parameters: -// -// float4 mode; -// sampler2D tex; -// -// -// Registers: -// -// Name Reg Size -// ------------ ----- ---- -// mode c0 1 -// tex s0 1 -// - - ps_2_0 - dcl t0.xy - dcl_2d s0 - texld r0, t0, s0 - mad r1.w, r0.w, c0.x, c0.y - mov r1.xyz, r0.x - mov oC0, r1 - -// approximately 4 instruction slots used (1 texture, 3 arithmetic) -#endif - -const BYTE g_ps20_luminanceps[] = -{ - 0, 2, 255, 255, 254, 255, - 43, 0, 67, 84, 65, 66, - 28, 0, 0, 0, 119, 0, - 0, 0, 0, 2, 255, 255, - 2, 0, 0, 0, 28, 0, - 0, 0, 0, 1, 0, 0, - 112, 0, 0, 0, 68, 0, - 0, 0, 2, 0, 0, 0, - 1, 0, 0, 0, 76, 0, - 0, 0, 0, 0, 0, 0, - 92, 0, 0, 0, 3, 0, - 0, 0, 1, 0, 0, 0, - 96, 0, 0, 0, 0, 0, - 0, 0, 109, 111, 100, 101, - 0, 171, 171, 171, 1, 0, - 3, 0, 1, 0, 4, 0, - 1, 0, 0, 0, 0, 0, - 0, 0, 116, 101, 120, 0, - 4, 0, 12, 0, 1, 0, - 1, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 112, 115, - 95, 50, 95, 48, 0, 77, - 105, 99, 114, 111, 115, 111, - 102, 116, 32, 40, 82, 41, - 32, 72, 76, 83, 76, 32, - 83, 104, 97, 100, 101, 114, - 32, 67, 111, 109, 112, 105, - 108, 101, 114, 32, 57, 46, - 50, 57, 46, 57, 53, 50, - 46, 51, 49, 49, 49, 0, - 31, 0, 0, 2, 0, 0, - 0, 128, 0, 0, 3, 176, - 31, 0, 0, 2, 0, 0, - 0, 144, 0, 8, 15, 160, - 66, 0, 0, 3, 0, 0, - 15, 128, 0, 0, 228, 176, - 0, 8, 228, 160, 4, 0, - 0, 4, 1, 0, 8, 128, - 0, 0, 255, 128, 0, 0, - 0, 160, 0, 0, 85, 160, - 1, 0, 0, 2, 1, 0, - 7, 128, 0, 0, 0, 128, - 1, 0, 0, 2, 0, 8, - 15, 128, 1, 0, 228, 128, - 255, 255, 0, 0 -}; +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111 +// +// fxc /E luminanceps /T ps_2_0 /Fh compiled/luminanceps.h Blit.ps +// +// +// Parameters: +// +// float4 mode; +// sampler2D tex; +// +// +// Registers: +// +// Name Reg Size +// ------------ ----- ---- +// mode c0 1 +// tex s0 1 +// + + ps_2_0 + dcl t0.xy + dcl_2d s0 + texld r0, t0, s0 + mad r1.w, r0.w, c0.x, c0.y + mov r1.xyz, r0.x + mov oC0, r1 + +// approximately 4 instruction slots used (1 texture, 3 arithmetic) +#endif + +const BYTE g_ps20_luminanceps[] = +{ + 0, 2, 255, 255, 254, 255, + 43, 0, 67, 84, 65, 66, + 28, 0, 0, 0, 119, 0, + 0, 0, 0, 2, 255, 255, + 2, 0, 0, 0, 28, 0, + 0, 0, 0, 1, 0, 0, + 112, 0, 0, 0, 68, 0, + 0, 0, 2, 0, 0, 0, + 1, 0, 0, 0, 76, 0, + 0, 0, 0, 0, 0, 0, + 92, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 96, 0, 0, 0, 0, 0, + 0, 0, 109, 111, 100, 101, + 0, 171, 171, 171, 1, 0, + 3, 0, 1, 0, 4, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 116, 101, 120, 0, + 4, 0, 12, 0, 1, 0, + 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 112, 115, + 95, 50, 95, 48, 0, 77, + 105, 99, 114, 111, 115, 111, + 102, 116, 32, 40, 82, 41, + 32, 72, 76, 83, 76, 32, + 83, 104, 97, 100, 101, 114, + 32, 67, 111, 109, 112, 105, + 108, 101, 114, 32, 57, 46, + 50, 57, 46, 57, 53, 50, + 46, 51, 49, 49, 49, 0, + 31, 0, 0, 2, 0, 0, + 0, 128, 0, 0, 3, 176, + 31, 0, 0, 2, 0, 0, + 0, 144, 0, 8, 15, 160, + 66, 0, 0, 3, 0, 0, + 15, 128, 0, 0, 228, 176, + 0, 8, 228, 160, 4, 0, + 0, 4, 1, 0, 8, 128, + 0, 0, 255, 128, 0, 0, + 0, 160, 0, 0, 85, 160, + 1, 0, 0, 2, 1, 0, + 7, 128, 0, 0, 0, 128, + 1, 0, 0, 2, 0, 8, + 15, 128, 1, 0, 228, 128, + 255, 255, 0, 0 +}; diff --git a/gfx/angle/src/libGLESv2/renderer/shaders/compiled/passthrough11vs.h b/gfx/angle/src/libGLESv2/renderer/shaders/compiled/passthrough11vs.h new file mode 100644 index 000000000000..b12fff9bf935 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/shaders/compiled/passthrough11vs.h @@ -0,0 +1,137 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111 +// +// +// fxc /E VS_Passthrough /T vs_4_0 /Fh compiled/passthrough11vs.h +// Passthrough11.hlsl +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------ ------ +// POSITION 0 xy 0 NONE float xy +// TEXCOORD 0 xy 1 NONE float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------ ------ +// SV_POSITION 0 xyzw 0 POS float xyzw +// TEXCOORD 0 xy 1 NONE float xy +// +vs_4_0 +dcl_input v0.xy +dcl_input v1.xy +dcl_output_siv o0.xyzw, position +dcl_output o1.xy +mov o0.xy, v0.xyxx +mov o0.zw, l(0,0,0,1.000000) +mov o1.xy, v1.xyxx +ret +// Approximately 4 instruction slots used +#endif + +const BYTE g_VS_Passthrough[] = +{ + 68, 88, 66, 67, 117, 74, + 34, 79, 174, 226, 170, 74, + 110, 16, 237, 14, 67, 185, + 119, 167, 1, 0, 0, 0, + 68, 2, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 140, 0, 0, 0, 224, 0, + 0, 0, 56, 1, 0, 0, + 200, 1, 0, 0, 82, 68, + 69, 70, 80, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 28, 0, 0, 0, 0, 4, + 254, 255, 0, 1, 0, 0, + 28, 0, 0, 0, 77, 105, + 99, 114, 111, 115, 111, 102, + 116, 32, 40, 82, 41, 32, + 72, 76, 83, 76, 32, 83, + 104, 97, 100, 101, 114, 32, + 67, 111, 109, 112, 105, 108, + 101, 114, 32, 57, 46, 50, + 57, 46, 57, 53, 50, 46, + 51, 49, 49, 49, 0, 171, + 171, 171, 73, 83, 71, 78, + 76, 0, 0, 0, 2, 0, + 0, 0, 8, 0, 0, 0, + 56, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 3, 3, 0, 0, + 65, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 3, 3, 0, 0, + 80, 79, 83, 73, 84, 73, + 79, 78, 0, 84, 69, 88, + 67, 79, 79, 82, 68, 0, + 171, 171, 79, 83, 71, 78, + 80, 0, 0, 0, 2, 0, + 0, 0, 8, 0, 0, 0, + 56, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 68, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 3, 12, 0, 0, + 83, 86, 95, 80, 79, 83, + 73, 84, 73, 79, 78, 0, + 84, 69, 88, 67, 79, 79, + 82, 68, 0, 171, 171, 171, + 83, 72, 68, 82, 136, 0, + 0, 0, 64, 0, 1, 0, + 34, 0, 0, 0, 95, 0, + 0, 3, 50, 16, 16, 0, + 0, 0, 0, 0, 95, 0, + 0, 3, 50, 16, 16, 0, + 1, 0, 0, 0, 103, 0, + 0, 4, 242, 32, 16, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 101, 0, 0, 3, + 50, 32, 16, 0, 1, 0, + 0, 0, 54, 0, 0, 5, + 50, 32, 16, 0, 0, 0, + 0, 0, 70, 16, 16, 0, + 0, 0, 0, 0, 54, 0, + 0, 8, 194, 32, 16, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 128, 63, + 54, 0, 0, 5, 50, 32, + 16, 0, 1, 0, 0, 0, + 70, 16, 16, 0, 1, 0, + 0, 0, 62, 0, 0, 1, + 83, 84, 65, 84, 116, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; diff --git a/gfx/angle/src/libGLESv2/renderer/shaders/compiled/passthroughlum11ps.h b/gfx/angle/src/libGLESv2/renderer/shaders/compiled/passthroughlum11ps.h new file mode 100644 index 000000000000..0d5c8ebdaa5e --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/shaders/compiled/passthroughlum11ps.h @@ -0,0 +1,155 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111 +// +// +// fxc /E PS_PassthroughLum /T ps_4_0 /Fh compiled/passthroughlum11ps.h +// Passthrough11.hlsl +// +// +// Resource Bindings: +// +// Name Type Format Dim Slot Elements +// ------------------------------ ---------- ------- ----------- ---- -------- +// Sampler sampler NA NA 0 1 +// Texture texture float4 2d 0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------ ------ +// SV_POSITION 0 xyzw 0 POS float +// TEXCOORD 0 xy 1 NONE float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------ ------ +// SV_TARGET 0 xyzw 0 TARGET float xyzw +// +ps_4_0 +dcl_sampler s0, mode_default +dcl_resource_texture2d (float,float,float,float) t0 +dcl_input_ps linear v1.xy +dcl_output o0.xyzw +dcl_temps 1 +sample r0.xyzw, v1.xyxx, t0.xyzw, s0 +mov o0.xyz, r0.xxxx +mov o0.w, l(1.000000) +ret +// Approximately 4 instruction slots used +#endif + +const BYTE g_PS_PassthroughLum[] = +{ + 68, 88, 66, 67, 97, 41, + 37, 154, 0, 174, 137, 157, + 76, 219, 230, 26, 227, 174, + 187, 66, 1, 0, 0, 0, + 128, 2, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 220, 0, 0, 0, 52, 1, + 0, 0, 104, 1, 0, 0, + 4, 2, 0, 0, 82, 68, + 69, 70, 160, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 28, 0, 0, 0, 0, 4, + 255, 255, 0, 1, 0, 0, + 108, 0, 0, 0, 92, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 100, 0, 0, 0, 2, 0, + 0, 0, 5, 0, 0, 0, + 4, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 13, 0, + 0, 0, 83, 97, 109, 112, + 108, 101, 114, 0, 84, 101, + 120, 116, 117, 114, 101, 0, + 77, 105, 99, 114, 111, 115, + 111, 102, 116, 32, 40, 82, + 41, 32, 72, 76, 83, 76, + 32, 83, 104, 97, 100, 101, + 114, 32, 67, 111, 109, 112, + 105, 108, 101, 114, 32, 57, + 46, 50, 57, 46, 57, 53, + 50, 46, 51, 49, 49, 49, + 0, 171, 171, 171, 73, 83, + 71, 78, 80, 0, 0, 0, + 2, 0, 0, 0, 8, 0, + 0, 0, 56, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 68, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 3, 3, + 0, 0, 83, 86, 95, 80, + 79, 83, 73, 84, 73, 79, + 78, 0, 84, 69, 88, 67, + 79, 79, 82, 68, 0, 171, + 171, 171, 79, 83, 71, 78, + 44, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 83, 86, 95, 84, 65, 82, + 71, 69, 84, 0, 171, 171, + 83, 72, 68, 82, 148, 0, + 0, 0, 64, 0, 0, 0, + 37, 0, 0, 0, 90, 0, + 0, 3, 0, 96, 16, 0, + 0, 0, 0, 0, 88, 24, + 0, 4, 0, 112, 16, 0, + 0, 0, 0, 0, 85, 85, + 0, 0, 98, 16, 0, 3, + 50, 16, 16, 0, 1, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 0, 0, + 0, 0, 104, 0, 0, 2, + 1, 0, 0, 0, 69, 0, + 0, 9, 242, 0, 16, 0, + 0, 0, 0, 0, 70, 16, + 16, 0, 1, 0, 0, 0, + 70, 126, 16, 0, 0, 0, + 0, 0, 0, 96, 16, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 114, 32, 16, 0, + 0, 0, 0, 0, 6, 0, + 16, 0, 0, 0, 0, 0, + 54, 0, 0, 5, 130, 32, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 63, 62, 0, 0, 1, + 83, 84, 65, 84, 116, 0, + 0, 0, 4, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; diff --git a/gfx/angle/src/libGLESv2/renderer/shaders/compiled/passthroughlumalpha11ps.h b/gfx/angle/src/libGLESv2/renderer/shaders/compiled/passthroughlumalpha11ps.h new file mode 100644 index 000000000000..6f9c14d38598 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/shaders/compiled/passthroughlumalpha11ps.h @@ -0,0 +1,151 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111 +// +// +// fxc /E PS_PassthroughLumAlpha /T ps_4_0 /Fh +// compiled/passthroughlumalpha11ps.h Passthrough11.hlsl +// +// +// Resource Bindings: +// +// Name Type Format Dim Slot Elements +// ------------------------------ ---------- ------- ----------- ---- -------- +// Sampler sampler NA NA 0 1 +// Texture texture float4 2d 0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------ ------ +// SV_POSITION 0 xyzw 0 POS float +// TEXCOORD 0 xy 1 NONE float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------ ------ +// SV_TARGET 0 xyzw 0 TARGET float xyzw +// +ps_4_0 +dcl_sampler s0, mode_default +dcl_resource_texture2d (float,float,float,float) t0 +dcl_input_ps linear v1.xy +dcl_output o0.xyzw +dcl_temps 1 +sample r0.xyzw, v1.xyxx, t0.xyzw, s0 +mov o0.xyzw, r0.xxxw +ret +// Approximately 3 instruction slots used +#endif + +const BYTE g_PS_PassthroughLumAlpha[] = +{ + 68, 88, 66, 67, 197, 72, + 251, 236, 53, 107, 182, 146, + 196, 219, 130, 187, 140, 159, + 211, 123, 1, 0, 0, 0, + 108, 2, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 220, 0, 0, 0, 52, 1, + 0, 0, 104, 1, 0, 0, + 240, 1, 0, 0, 82, 68, + 69, 70, 160, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 28, 0, 0, 0, 0, 4, + 255, 255, 0, 1, 0, 0, + 108, 0, 0, 0, 92, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 100, 0, 0, 0, 2, 0, + 0, 0, 5, 0, 0, 0, + 4, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 13, 0, + 0, 0, 83, 97, 109, 112, + 108, 101, 114, 0, 84, 101, + 120, 116, 117, 114, 101, 0, + 77, 105, 99, 114, 111, 115, + 111, 102, 116, 32, 40, 82, + 41, 32, 72, 76, 83, 76, + 32, 83, 104, 97, 100, 101, + 114, 32, 67, 111, 109, 112, + 105, 108, 101, 114, 32, 57, + 46, 50, 57, 46, 57, 53, + 50, 46, 51, 49, 49, 49, + 0, 171, 171, 171, 73, 83, + 71, 78, 80, 0, 0, 0, + 2, 0, 0, 0, 8, 0, + 0, 0, 56, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 68, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 3, 3, + 0, 0, 83, 86, 95, 80, + 79, 83, 73, 84, 73, 79, + 78, 0, 84, 69, 88, 67, + 79, 79, 82, 68, 0, 171, + 171, 171, 79, 83, 71, 78, + 44, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 83, 86, 95, 84, 65, 82, + 71, 69, 84, 0, 171, 171, + 83, 72, 68, 82, 128, 0, + 0, 0, 64, 0, 0, 0, + 32, 0, 0, 0, 90, 0, + 0, 3, 0, 96, 16, 0, + 0, 0, 0, 0, 88, 24, + 0, 4, 0, 112, 16, 0, + 0, 0, 0, 0, 85, 85, + 0, 0, 98, 16, 0, 3, + 50, 16, 16, 0, 1, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 0, 0, + 0, 0, 104, 0, 0, 2, + 1, 0, 0, 0, 69, 0, + 0, 9, 242, 0, 16, 0, + 0, 0, 0, 0, 70, 16, + 16, 0, 1, 0, 0, 0, + 70, 126, 16, 0, 0, 0, + 0, 0, 0, 96, 16, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 242, 32, 16, 0, + 0, 0, 0, 0, 6, 12, + 16, 0, 0, 0, 0, 0, + 62, 0, 0, 1, 83, 84, + 65, 84, 116, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; diff --git a/gfx/angle/src/libGLESv2/shaders/passthroughps.h b/gfx/angle/src/libGLESv2/renderer/shaders/compiled/passthroughps.h similarity index 91% rename from gfx/angle/src/libGLESv2/shaders/passthroughps.h rename to gfx/angle/src/libGLESv2/renderer/shaders/compiled/passthroughps.h index 56b75ef9033f..f231d44023bf 100644 --- a/gfx/angle/src/libGLESv2/shaders/passthroughps.h +++ b/gfx/angle/src/libGLESv2/renderer/shaders/compiled/passthroughps.h @@ -1,63 +1,63 @@ -#if 0 -// -// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111 -// -// fxc /E passthroughps /T ps_2_0 /Fh passthroughps.h Blit.ps -// -// -// Parameters: -// -// sampler2D tex; -// -// -// Registers: -// -// Name Reg Size -// ------------ ----- ---- -// tex s0 1 -// - - ps_2_0 - dcl t0.xy - dcl_2d s0 - texld r0, t0, s0 - mov oC0, r0 - -// approximately 2 instruction slots used (1 texture, 1 arithmetic) -#endif - -const BYTE g_ps20_passthroughps[] = -{ - 0, 2, 255, 255, 254, 255, - 32, 0, 67, 84, 65, 66, - 28, 0, 0, 0, 75, 0, - 0, 0, 0, 2, 255, 255, - 1, 0, 0, 0, 28, 0, - 0, 0, 0, 1, 0, 0, - 68, 0, 0, 0, 48, 0, - 0, 0, 3, 0, 0, 0, - 1, 0, 0, 0, 52, 0, - 0, 0, 0, 0, 0, 0, - 116, 101, 120, 0, 4, 0, - 12, 0, 1, 0, 1, 0, - 1, 0, 0, 0, 0, 0, - 0, 0, 112, 115, 95, 50, - 95, 48, 0, 77, 105, 99, - 114, 111, 115, 111, 102, 116, - 32, 40, 82, 41, 32, 72, - 76, 83, 76, 32, 83, 104, - 97, 100, 101, 114, 32, 67, - 111, 109, 112, 105, 108, 101, - 114, 32, 57, 46, 50, 57, - 46, 57, 53, 50, 46, 51, - 49, 49, 49, 0, 31, 0, - 0, 2, 0, 0, 0, 128, - 0, 0, 3, 176, 31, 0, - 0, 2, 0, 0, 0, 144, - 0, 8, 15, 160, 66, 0, - 0, 3, 0, 0, 15, 128, - 0, 0, 228, 176, 0, 8, - 228, 160, 1, 0, 0, 2, - 0, 8, 15, 128, 0, 0, - 228, 128, 255, 255, 0, 0 -}; +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111 +// +// fxc /E passthroughps /T ps_2_0 /Fh compiled/passthroughps.h Blit.ps +// +// +// Parameters: +// +// sampler2D tex; +// +// +// Registers: +// +// Name Reg Size +// ------------ ----- ---- +// tex s0 1 +// + + ps_2_0 + dcl t0.xy + dcl_2d s0 + texld r0, t0, s0 + mov oC0, r0 + +// approximately 2 instruction slots used (1 texture, 1 arithmetic) +#endif + +const BYTE g_ps20_passthroughps[] = +{ + 0, 2, 255, 255, 254, 255, + 32, 0, 67, 84, 65, 66, + 28, 0, 0, 0, 75, 0, + 0, 0, 0, 2, 255, 255, + 1, 0, 0, 0, 28, 0, + 0, 0, 0, 1, 0, 0, + 68, 0, 0, 0, 48, 0, + 0, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 52, 0, + 0, 0, 0, 0, 0, 0, + 116, 101, 120, 0, 4, 0, + 12, 0, 1, 0, 1, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 112, 115, 95, 50, + 95, 48, 0, 77, 105, 99, + 114, 111, 115, 111, 102, 116, + 32, 40, 82, 41, 32, 72, + 76, 83, 76, 32, 83, 104, + 97, 100, 101, 114, 32, 67, + 111, 109, 112, 105, 108, 101, + 114, 32, 57, 46, 50, 57, + 46, 57, 53, 50, 46, 51, + 49, 49, 49, 0, 31, 0, + 0, 2, 0, 0, 0, 128, + 0, 0, 3, 176, 31, 0, + 0, 2, 0, 0, 0, 144, + 0, 8, 15, 160, 66, 0, + 0, 3, 0, 0, 15, 128, + 0, 0, 228, 176, 0, 8, + 228, 160, 1, 0, 0, 2, + 0, 8, 15, 128, 0, 0, + 228, 128, 255, 255, 0, 0 +}; diff --git a/gfx/angle/src/libGLESv2/renderer/shaders/compiled/passthroughrgb11ps.h b/gfx/angle/src/libGLESv2/renderer/shaders/compiled/passthroughrgb11ps.h new file mode 100644 index 000000000000..da9ff630adad --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/shaders/compiled/passthroughrgb11ps.h @@ -0,0 +1,155 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111 +// +// +// fxc /E PS_PassthroughRGB /T ps_4_0 /Fh compiled/passthroughrgb11ps.h +// Passthrough11.hlsl +// +// +// Resource Bindings: +// +// Name Type Format Dim Slot Elements +// ------------------------------ ---------- ------- ----------- ---- -------- +// Sampler sampler NA NA 0 1 +// Texture texture float4 2d 0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------ ------ +// SV_POSITION 0 xyzw 0 POS float +// TEXCOORD 0 xy 1 NONE float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------ ------ +// SV_TARGET 0 xyzw 0 TARGET float xyzw +// +ps_4_0 +dcl_sampler s0, mode_default +dcl_resource_texture2d (float,float,float,float) t0 +dcl_input_ps linear v1.xy +dcl_output o0.xyzw +dcl_temps 1 +sample r0.xyzw, v1.xyxx, t0.xyzw, s0 +mov o0.xyz, r0.xyzx +mov o0.w, l(1.000000) +ret +// Approximately 4 instruction slots used +#endif + +const BYTE g_PS_PassthroughRGB[] = +{ + 68, 88, 66, 67, 253, 45, + 13, 34, 125, 194, 95, 149, + 1, 95, 194, 252, 118, 228, + 178, 200, 1, 0, 0, 0, + 128, 2, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 220, 0, 0, 0, 52, 1, + 0, 0, 104, 1, 0, 0, + 4, 2, 0, 0, 82, 68, + 69, 70, 160, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 28, 0, 0, 0, 0, 4, + 255, 255, 0, 1, 0, 0, + 108, 0, 0, 0, 92, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 100, 0, 0, 0, 2, 0, + 0, 0, 5, 0, 0, 0, + 4, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 13, 0, + 0, 0, 83, 97, 109, 112, + 108, 101, 114, 0, 84, 101, + 120, 116, 117, 114, 101, 0, + 77, 105, 99, 114, 111, 115, + 111, 102, 116, 32, 40, 82, + 41, 32, 72, 76, 83, 76, + 32, 83, 104, 97, 100, 101, + 114, 32, 67, 111, 109, 112, + 105, 108, 101, 114, 32, 57, + 46, 50, 57, 46, 57, 53, + 50, 46, 51, 49, 49, 49, + 0, 171, 171, 171, 73, 83, + 71, 78, 80, 0, 0, 0, + 2, 0, 0, 0, 8, 0, + 0, 0, 56, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 68, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 3, 3, + 0, 0, 83, 86, 95, 80, + 79, 83, 73, 84, 73, 79, + 78, 0, 84, 69, 88, 67, + 79, 79, 82, 68, 0, 171, + 171, 171, 79, 83, 71, 78, + 44, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 83, 86, 95, 84, 65, 82, + 71, 69, 84, 0, 171, 171, + 83, 72, 68, 82, 148, 0, + 0, 0, 64, 0, 0, 0, + 37, 0, 0, 0, 90, 0, + 0, 3, 0, 96, 16, 0, + 0, 0, 0, 0, 88, 24, + 0, 4, 0, 112, 16, 0, + 0, 0, 0, 0, 85, 85, + 0, 0, 98, 16, 0, 3, + 50, 16, 16, 0, 1, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 0, 0, + 0, 0, 104, 0, 0, 2, + 1, 0, 0, 0, 69, 0, + 0, 9, 242, 0, 16, 0, + 0, 0, 0, 0, 70, 16, + 16, 0, 1, 0, 0, 0, + 70, 126, 16, 0, 0, 0, + 0, 0, 0, 96, 16, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 114, 32, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 54, 0, 0, 5, 130, 32, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 63, 62, 0, 0, 1, + 83, 84, 65, 84, 116, 0, + 0, 0, 4, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; diff --git a/gfx/angle/src/libGLESv2/renderer/shaders/compiled/passthroughrgba11ps.h b/gfx/angle/src/libGLESv2/renderer/shaders/compiled/passthroughrgba11ps.h new file mode 100644 index 000000000000..55f2fef57f48 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/shaders/compiled/passthroughrgba11ps.h @@ -0,0 +1,144 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111 +// +// +// fxc /E PS_PassthroughRGBA /T ps_4_0 /Fh compiled/passthroughrgba11ps.h +// Passthrough11.hlsl +// +// +// Resource Bindings: +// +// Name Type Format Dim Slot Elements +// ------------------------------ ---------- ------- ----------- ---- -------- +// Sampler sampler NA NA 0 1 +// Texture texture float4 2d 0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------ ------ +// SV_POSITION 0 xyzw 0 POS float +// TEXCOORD 0 xy 1 NONE float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------ ------ +// SV_TARGET 0 xyzw 0 TARGET float xyzw +// +ps_4_0 +dcl_sampler s0, mode_default +dcl_resource_texture2d (float,float,float,float) t0 +dcl_input_ps linear v1.xy +dcl_output o0.xyzw +sample o0.xyzw, v1.xyxx, t0.xyzw, s0 +ret +// Approximately 2 instruction slots used +#endif + +const BYTE g_PS_PassthroughRGBA[] = +{ + 68, 88, 66, 67, 152, 86, + 225, 107, 155, 83, 216, 13, + 154, 212, 144, 5, 82, 74, + 90, 98, 1, 0, 0, 0, + 80, 2, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 220, 0, 0, 0, 52, 1, + 0, 0, 104, 1, 0, 0, + 212, 1, 0, 0, 82, 68, + 69, 70, 160, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 28, 0, 0, 0, 0, 4, + 255, 255, 0, 1, 0, 0, + 108, 0, 0, 0, 92, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 100, 0, 0, 0, 2, 0, + 0, 0, 5, 0, 0, 0, + 4, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 13, 0, + 0, 0, 83, 97, 109, 112, + 108, 101, 114, 0, 84, 101, + 120, 116, 117, 114, 101, 0, + 77, 105, 99, 114, 111, 115, + 111, 102, 116, 32, 40, 82, + 41, 32, 72, 76, 83, 76, + 32, 83, 104, 97, 100, 101, + 114, 32, 67, 111, 109, 112, + 105, 108, 101, 114, 32, 57, + 46, 50, 57, 46, 57, 53, + 50, 46, 51, 49, 49, 49, + 0, 171, 171, 171, 73, 83, + 71, 78, 80, 0, 0, 0, + 2, 0, 0, 0, 8, 0, + 0, 0, 56, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 68, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 3, 3, + 0, 0, 83, 86, 95, 80, + 79, 83, 73, 84, 73, 79, + 78, 0, 84, 69, 88, 67, + 79, 79, 82, 68, 0, 171, + 171, 171, 79, 83, 71, 78, + 44, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 83, 86, 95, 84, 65, 82, + 71, 69, 84, 0, 171, 171, + 83, 72, 68, 82, 100, 0, + 0, 0, 64, 0, 0, 0, + 25, 0, 0, 0, 90, 0, + 0, 3, 0, 96, 16, 0, + 0, 0, 0, 0, 88, 24, + 0, 4, 0, 112, 16, 0, + 0, 0, 0, 0, 85, 85, + 0, 0, 98, 16, 0, 3, + 50, 16, 16, 0, 1, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 0, 0, + 0, 0, 69, 0, 0, 9, + 242, 32, 16, 0, 0, 0, + 0, 0, 70, 16, 16, 0, + 1, 0, 0, 0, 70, 126, + 16, 0, 0, 0, 0, 0, + 0, 96, 16, 0, 0, 0, + 0, 0, 62, 0, 0, 1, + 83, 84, 65, 84, 116, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; diff --git a/gfx/angle/src/libGLESv2/shaders/standardvs.h b/gfx/angle/src/libGLESv2/renderer/shaders/compiled/standardvs.h similarity index 92% rename from gfx/angle/src/libGLESv2/shaders/standardvs.h rename to gfx/angle/src/libGLESv2/renderer/shaders/compiled/standardvs.h index a667f64b2370..8ea892eb5568 100644 --- a/gfx/angle/src/libGLESv2/shaders/standardvs.h +++ b/gfx/angle/src/libGLESv2/renderer/shaders/compiled/standardvs.h @@ -1,69 +1,69 @@ -#if 0 -// -// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111 -// -// fxc /E standardvs /T vs_2_0 /Fh standardvs.h Blit.vs -// -// -// Parameters: -// -// float4 halfPixelSize; -// -// -// Registers: -// -// Name Reg Size -// ------------- ----- ---- -// halfPixelSize c0 1 -// - - vs_2_0 - def c1, 0.5, -0.5, 1, 0 - dcl_position v0 - add oPos, v0, c0 - mad oT0, v0, c1.xyzz, c1.xxww - -// approximately 2 instruction slots used -#endif - -const BYTE g_vs20_standardvs[] = -{ - 0, 2, 254, 255, 254, 255, - 35, 0, 67, 84, 65, 66, - 28, 0, 0, 0, 87, 0, - 0, 0, 0, 2, 254, 255, - 1, 0, 0, 0, 28, 0, - 0, 0, 0, 1, 0, 0, - 80, 0, 0, 0, 48, 0, - 0, 0, 2, 0, 0, 0, - 1, 0, 0, 0, 64, 0, - 0, 0, 0, 0, 0, 0, - 104, 97, 108, 102, 80, 105, - 120, 101, 108, 83, 105, 122, - 101, 0, 171, 171, 1, 0, - 3, 0, 1, 0, 4, 0, - 1, 0, 0, 0, 0, 0, - 0, 0, 118, 115, 95, 50, - 95, 48, 0, 77, 105, 99, - 114, 111, 115, 111, 102, 116, - 32, 40, 82, 41, 32, 72, - 76, 83, 76, 32, 83, 104, - 97, 100, 101, 114, 32, 67, - 111, 109, 112, 105, 108, 101, - 114, 32, 57, 46, 50, 57, - 46, 57, 53, 50, 46, 51, - 49, 49, 49, 0, 81, 0, - 0, 5, 1, 0, 15, 160, - 0, 0, 0, 63, 0, 0, - 0, 191, 0, 0, 128, 63, - 0, 0, 0, 0, 31, 0, - 0, 2, 0, 0, 0, 128, - 0, 0, 15, 144, 2, 0, - 0, 3, 0, 0, 15, 192, - 0, 0, 228, 144, 0, 0, - 228, 160, 4, 0, 0, 4, - 0, 0, 15, 224, 0, 0, - 228, 144, 1, 0, 164, 160, - 1, 0, 240, 160, 255, 255, - 0, 0 -}; +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111 +// +// fxc /E standardvs /T vs_2_0 /Fh compiled/standardvs.h Blit.vs +// +// +// Parameters: +// +// float4 halfPixelSize; +// +// +// Registers: +// +// Name Reg Size +// ------------- ----- ---- +// halfPixelSize c0 1 +// + + vs_2_0 + def c1, 0.5, -0.5, 1, 0 + dcl_position v0 + add oPos, v0, c0 + mad oT0, v0, c1.xyzz, c1.xxww + +// approximately 2 instruction slots used +#endif + +const BYTE g_vs20_standardvs[] = +{ + 0, 2, 254, 255, 254, 255, + 35, 0, 67, 84, 65, 66, + 28, 0, 0, 0, 87, 0, + 0, 0, 0, 2, 254, 255, + 1, 0, 0, 0, 28, 0, + 0, 0, 0, 1, 0, 0, + 80, 0, 0, 0, 48, 0, + 0, 0, 2, 0, 0, 0, + 1, 0, 0, 0, 64, 0, + 0, 0, 0, 0, 0, 0, + 104, 97, 108, 102, 80, 105, + 120, 101, 108, 83, 105, 122, + 101, 0, 171, 171, 1, 0, + 3, 0, 1, 0, 4, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 118, 115, 95, 50, + 95, 48, 0, 77, 105, 99, + 114, 111, 115, 111, 102, 116, + 32, 40, 82, 41, 32, 72, + 76, 83, 76, 32, 83, 104, + 97, 100, 101, 114, 32, 67, + 111, 109, 112, 105, 108, 101, + 114, 32, 57, 46, 50, 57, + 46, 57, 53, 50, 46, 51, + 49, 49, 49, 0, 81, 0, + 0, 5, 1, 0, 15, 160, + 0, 0, 0, 63, 0, 0, + 0, 191, 0, 0, 128, 63, + 0, 0, 0, 0, 31, 0, + 0, 2, 0, 0, 0, 128, + 0, 0, 15, 144, 2, 0, + 0, 3, 0, 0, 15, 192, + 0, 0, 228, 144, 0, 0, + 228, 160, 4, 0, 0, 4, + 0, 0, 15, 224, 0, 0, + 228, 144, 1, 0, 164, 160, + 1, 0, 240, 160, 255, 255, + 0, 0 +}; diff --git a/gfx/angle/src/libGLESv2/renderer/shaders/generate_shaders.bat b/gfx/angle/src/libGLESv2/renderer/shaders/generate_shaders.bat new file mode 100644 index 000000000000..04ef1368d3b4 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/shaders/generate_shaders.bat @@ -0,0 +1,24 @@ +@ECHO OFF +REM +REM Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +REM Use of this source code is governed by a BSD-style license that can be +REM found in the LICENSE file. +REM + +PATH %PATH%;%DXSDK_DIR%\Utilities\bin\x86 + +fxc /E standardvs /T vs_2_0 /Fh compiled/standardvs.h Blit.vs +fxc /E flipyvs /T vs_2_0 /Fh compiled/flipyvs.h Blit.vs +fxc /E passthroughps /T ps_2_0 /Fh compiled/passthroughps.h Blit.ps +fxc /E luminanceps /T ps_2_0 /Fh compiled/luminanceps.h Blit.ps +fxc /E componentmaskps /T ps_2_0 /Fh compiled/componentmaskps.h Blit.ps + +fxc /E VS_Passthrough /T vs_4_0 /Fh compiled/passthrough11vs.h Passthrough11.hlsl +fxc /E PS_PassthroughRGBA /T ps_4_0 /Fh compiled/passthroughrgba11ps.h Passthrough11.hlsl +fxc /E PS_PassthroughRGB /T ps_4_0 /Fh compiled/passthroughrgb11ps.h Passthrough11.hlsl +fxc /E PS_PassthroughLum /T ps_4_0 /Fh compiled/passthroughlum11ps.h Passthrough11.hlsl +fxc /E PS_PassthroughLumAlpha /T ps_4_0 /Fh compiled/passthroughlumalpha11ps.h Passthrough11.hlsl + +fxc /E VS_Clear /T vs_4_0 /Fh compiled/clear11vs.h Clear11.hlsl +fxc /E PS_ClearSingle /T ps_4_0 /Fh compiled/clearsingle11ps.h Clear11.hlsl +fxc /E PS_ClearMultiple /T ps_4_0 /Fh compiled/clearmultiple11ps.h Clear11.hlsl diff --git a/gfx/angle/src/libGLESv2/vertexconversion.h b/gfx/angle/src/libGLESv2/renderer/vertexconversion.h similarity index 98% rename from gfx/angle/src/libGLESv2/vertexconversion.h rename to gfx/angle/src/libGLESv2/renderer/vertexconversion.h index 5bb8b8995e91..590b9d48a386 100644 --- a/gfx/angle/src/libGLESv2/vertexconversion.h +++ b/gfx/angle/src/libGLESv2/renderer/vertexconversion.h @@ -10,12 +10,7 @@ #ifndef LIBGLESV2_VERTEXCONVERSION_H_ #define LIBGLESV2_VERTEXCONVERSION_H_ -#include -#include - -#include "libGLESv2/Context.h" // Defines Index - -namespace gl +namespace rx { // Conversion types: diff --git a/gfx/angle/src/libGLESv2/shaders/generate_shaders.bat b/gfx/angle/src/libGLESv2/shaders/generate_shaders.bat deleted file mode 100644 index f346fb6aff94..000000000000 --- a/gfx/angle/src/libGLESv2/shaders/generate_shaders.bat +++ /dev/null @@ -1,14 +0,0 @@ -@ECHO OFF -REM -REM Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -REM Use of this source code is governed by a BSD-style license that can be -REM found in the LICENSE file. -REM - -PATH %PATH%;%DXSDK_DIR%\Utilities\bin\x86 - -fxc /E standardvs /T vs_2_0 /Fh standardvs.h Blit.vs -fxc /E flipyvs /T vs_2_0 /Fh flipyvs.h Blit.vs -fxc /E passthroughps /T ps_2_0 /Fh passthroughps.h Blit.ps -fxc /E luminanceps /T ps_2_0 /Fh luminanceps.h Blit.ps -fxc /E componentmaskps /T ps_2_0 /Fh componentmaskps.h Blit.ps diff --git a/gfx/angle/src/libGLESv2/utilities.cpp b/gfx/angle/src/libGLESv2/utilities.cpp index cc5a7783d59b..32df49e672bd 100644 --- a/gfx/angle/src/libGLESv2/utilities.cpp +++ b/gfx/angle/src/libGLESv2/utilities.cpp @@ -1,5 +1,6 @@ +#include "precompiled.h" // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -7,20 +8,12 @@ // utilities.cpp: Conversion functions and other utility routines. #include "libGLESv2/utilities.h" - -#include -#include - -#include "common/debug.h" -#include "common/system.h" #include "libGLESv2/mathutil.h" -#include "libGLESv2/Context.h" namespace gl { -// This is how much data the application expects for a uniform -int UniformExternalComponentCount(GLenum type) +int UniformComponentCount(GLenum type) { switch (type) { @@ -54,42 +47,6 @@ int UniformExternalComponentCount(GLenum type) return 0; } -// This is how much data we actually store for a uniform -int UniformInternalComponentCount(GLenum type) -{ - switch (type) - { - case GL_BOOL: - case GL_INT: - case GL_SAMPLER_2D: - case GL_SAMPLER_CUBE: - return 1; - case GL_BOOL_VEC2: - case GL_INT_VEC2: - return 2; - case GL_INT_VEC3: - case GL_BOOL_VEC3: - return 3; - case GL_FLOAT: - case GL_FLOAT_VEC2: - case GL_FLOAT_VEC3: - case GL_BOOL_VEC4: - case GL_FLOAT_VEC4: - case GL_INT_VEC4: - return 4; - case GL_FLOAT_MAT2: - return 8; - case GL_FLOAT_MAT3: - return 12; - case GL_FLOAT_MAT4: - return 16; - default: - UNREACHABLE(); - } - - return 0; -} - GLenum UniformComponentType(GLenum type) { switch(type) @@ -136,12 +93,13 @@ size_t UniformComponentSize(GLenum type) size_t UniformInternalSize(GLenum type) { - return UniformComponentSize(UniformComponentType(type)) * UniformInternalComponentCount(type); + // Expanded to 4-element vectors + return UniformComponentSize(UniformComponentType(type)) * VariableRowCount(type) * 4; } size_t UniformExternalSize(GLenum type) { - return UniformComponentSize(UniformComponentType(type)) * UniformExternalComponentCount(type); + return UniformComponentSize(UniformComponentType(type)) * UniformComponentCount(type); } int VariableRowCount(GLenum type) @@ -162,6 +120,8 @@ int VariableRowCount(GLenum type) case GL_BOOL_VEC4: case GL_FLOAT_VEC4: case GL_INT_VEC4: + case GL_SAMPLER_2D: + case GL_SAMPLER_CUBE: return 1; case GL_FLOAT_MAT2: return 2; @@ -185,6 +145,8 @@ int VariableColumnCount(GLenum type) case GL_BOOL: case GL_FLOAT: case GL_INT: + case GL_SAMPLER_2D: + case GL_SAMPLER_CUBE: return 1; case GL_BOOL_VEC2: case GL_FLOAT_VEC2: @@ -256,6 +218,29 @@ GLsizei ComputeCompressedSize(GLsizei width, GLsizei height, GLenum internalform } } +GLsizei ComputeTypeSize(GLenum type) +{ + switch (type) + { + case GL_BYTE: return 1; + case GL_UNSIGNED_BYTE: return 1; + case GL_SHORT: return 2; + case GL_UNSIGNED_SHORT: return 2; + case GL_INT: return 4; + case GL_UNSIGNED_INT: return 4; + case GL_FLOAT: return 4; + case GL_HALF_FLOAT_OES: return 2; + case GL_UNSIGNED_SHORT_5_6_5: return 2; + case GL_UNSIGNED_SHORT_4_4_4_4: return 2; + case GL_UNSIGNED_SHORT_5_5_5_1: return 2; + case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT: return 2; + case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT: return 2; + case GL_UNSIGNED_INT_2_10_10_10_REV_EXT: return 4; + case GL_UNSIGNED_INT_24_8_OES: return 4; + default: UNREACHABLE(); return 0; + } +} + bool IsCompressed(GLenum format) { if(format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT || @@ -296,6 +281,27 @@ bool IsStencilTexture(GLenum format) return false; } +void MakeValidSize(bool isImage, bool isCompressed, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset) +{ + int upsampleCount = 0; + + if (isCompressed) + { + // Don't expand the size of full textures that are at least 4x4 + // already. + if (isImage || *requestWidth < 4 || *requestHeight < 4) + { + while (*requestWidth % 4 != 0 || *requestHeight % 4 != 0) + { + *requestWidth <<= 1; + *requestHeight <<= 1; + upsampleCount++; + } + } + } + *levelOffset = upsampleCount; +} + // Returns the size, in bytes, of a single texel in an Image int ComputePixelSize(GLint internalformat) { @@ -509,6 +515,8 @@ bool IsColorRenderable(GLenum internalformat) case GL_STENCIL_INDEX8: case GL_DEPTH24_STENCIL8_OES: return false; + case GL_BGRA8_EXT: + return true; default: UNIMPLEMENTED(); } @@ -588,597 +596,141 @@ bool IsFloat16Format(GLint internalformat) } } -} - -namespace es2dx +unsigned int GetAlphaSize(GLenum colorFormat) { - -D3DCMPFUNC ConvertComparison(GLenum comparison) -{ - D3DCMPFUNC d3dComp = D3DCMP_ALWAYS; - switch (comparison) + switch (colorFormat) { - case GL_NEVER: d3dComp = D3DCMP_NEVER; break; - case GL_ALWAYS: d3dComp = D3DCMP_ALWAYS; break; - case GL_LESS: d3dComp = D3DCMP_LESS; break; - case GL_LEQUAL: d3dComp = D3DCMP_LESSEQUAL; break; - case GL_EQUAL: d3dComp = D3DCMP_EQUAL; break; - case GL_GREATER: d3dComp = D3DCMP_GREATER; break; - case GL_GEQUAL: d3dComp = D3DCMP_GREATEREQUAL; break; - case GL_NOTEQUAL: d3dComp = D3DCMP_NOTEQUAL; break; - default: UNREACHABLE(); - } - - return d3dComp; -} - -D3DCOLOR ConvertColor(gl::Color color) -{ - return D3DCOLOR_RGBA(gl::unorm<8>(color.red), - gl::unorm<8>(color.green), - gl::unorm<8>(color.blue), - gl::unorm<8>(color.alpha)); -} - -D3DBLEND ConvertBlendFunc(GLenum blend) -{ - D3DBLEND d3dBlend = D3DBLEND_ZERO; - - switch (blend) - { - case GL_ZERO: d3dBlend = D3DBLEND_ZERO; break; - case GL_ONE: d3dBlend = D3DBLEND_ONE; break; - case GL_SRC_COLOR: d3dBlend = D3DBLEND_SRCCOLOR; break; - case GL_ONE_MINUS_SRC_COLOR: d3dBlend = D3DBLEND_INVSRCCOLOR; break; - case GL_DST_COLOR: d3dBlend = D3DBLEND_DESTCOLOR; break; - case GL_ONE_MINUS_DST_COLOR: d3dBlend = D3DBLEND_INVDESTCOLOR; break; - case GL_SRC_ALPHA: d3dBlend = D3DBLEND_SRCALPHA; break; - case GL_ONE_MINUS_SRC_ALPHA: d3dBlend = D3DBLEND_INVSRCALPHA; break; - case GL_DST_ALPHA: d3dBlend = D3DBLEND_DESTALPHA; break; - case GL_ONE_MINUS_DST_ALPHA: d3dBlend = D3DBLEND_INVDESTALPHA; break; - case GL_CONSTANT_COLOR: d3dBlend = D3DBLEND_BLENDFACTOR; break; - case GL_ONE_MINUS_CONSTANT_COLOR: d3dBlend = D3DBLEND_INVBLENDFACTOR; break; - case GL_CONSTANT_ALPHA: d3dBlend = D3DBLEND_BLENDFACTOR; break; - case GL_ONE_MINUS_CONSTANT_ALPHA: d3dBlend = D3DBLEND_INVBLENDFACTOR; break; - case GL_SRC_ALPHA_SATURATE: d3dBlend = D3DBLEND_SRCALPHASAT; break; - default: UNREACHABLE(); - } - - return d3dBlend; -} - -D3DBLENDOP ConvertBlendOp(GLenum blendOp) -{ - D3DBLENDOP d3dBlendOp = D3DBLENDOP_ADD; - - switch (blendOp) - { - case GL_FUNC_ADD: d3dBlendOp = D3DBLENDOP_ADD; break; - case GL_FUNC_SUBTRACT: d3dBlendOp = D3DBLENDOP_SUBTRACT; break; - case GL_FUNC_REVERSE_SUBTRACT: d3dBlendOp = D3DBLENDOP_REVSUBTRACT; break; - default: UNREACHABLE(); - } - - return d3dBlendOp; -} - -D3DSTENCILOP ConvertStencilOp(GLenum stencilOp) -{ - D3DSTENCILOP d3dStencilOp = D3DSTENCILOP_KEEP; - - switch (stencilOp) - { - case GL_ZERO: d3dStencilOp = D3DSTENCILOP_ZERO; break; - case GL_KEEP: d3dStencilOp = D3DSTENCILOP_KEEP; break; - case GL_REPLACE: d3dStencilOp = D3DSTENCILOP_REPLACE; break; - case GL_INCR: d3dStencilOp = D3DSTENCILOP_INCRSAT; break; - case GL_DECR: d3dStencilOp = D3DSTENCILOP_DECRSAT; break; - case GL_INVERT: d3dStencilOp = D3DSTENCILOP_INVERT; break; - case GL_INCR_WRAP: d3dStencilOp = D3DSTENCILOP_INCR; break; - case GL_DECR_WRAP: d3dStencilOp = D3DSTENCILOP_DECR; break; - default: UNREACHABLE(); - } - - return d3dStencilOp; -} - -D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap) -{ - D3DTEXTUREADDRESS d3dWrap = D3DTADDRESS_WRAP; - - switch (wrap) - { - case GL_REPEAT: d3dWrap = D3DTADDRESS_WRAP; break; - case GL_CLAMP_TO_EDGE: d3dWrap = D3DTADDRESS_CLAMP; break; - case GL_MIRRORED_REPEAT: d3dWrap = D3DTADDRESS_MIRROR; break; - default: UNREACHABLE(); - } - - return d3dWrap; -} - -D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace) -{ - D3DCULL cull = D3DCULL_CCW; - switch (cullFace) - { - case GL_FRONT: - cull = (frontFace == GL_CCW ? D3DCULL_CW : D3DCULL_CCW); - break; - case GL_BACK: - cull = (frontFace == GL_CCW ? D3DCULL_CCW : D3DCULL_CW); - break; - case GL_FRONT_AND_BACK: - cull = D3DCULL_NONE; // culling will be handled during draw - break; - default: UNREACHABLE(); - } - - return cull; -} - -D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace) -{ - D3DCUBEMAP_FACES face = D3DCUBEMAP_FACE_POSITIVE_X; - - switch (cubeFace) - { - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - face = D3DCUBEMAP_FACE_POSITIVE_X; - break; - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - face = D3DCUBEMAP_FACE_NEGATIVE_X; - break; - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - face = D3DCUBEMAP_FACE_POSITIVE_Y; - break; - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - face = D3DCUBEMAP_FACE_NEGATIVE_Y; - break; - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - face = D3DCUBEMAP_FACE_POSITIVE_Z; - break; - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - face = D3DCUBEMAP_FACE_NEGATIVE_Z; - break; - default: UNREACHABLE(); - } - - return face; -} - -DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha) -{ - return (red ? D3DCOLORWRITEENABLE_RED : 0) | - (green ? D3DCOLORWRITEENABLE_GREEN : 0) | - (blue ? D3DCOLORWRITEENABLE_BLUE : 0) | - (alpha ? D3DCOLORWRITEENABLE_ALPHA : 0); -} - -D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter, float maxAnisotropy) -{ - if (maxAnisotropy > 1.0f) - { - return D3DTEXF_ANISOTROPIC; - } - - D3DTEXTUREFILTERTYPE d3dMagFilter = D3DTEXF_POINT; - switch (magFilter) - { - case GL_NEAREST: d3dMagFilter = D3DTEXF_POINT; break; - case GL_LINEAR: d3dMagFilter = D3DTEXF_LINEAR; break; - default: UNREACHABLE(); - } - - return d3dMagFilter; -} - -void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter, float maxAnisotropy) -{ - switch (minFilter) - { - case GL_NEAREST: - *d3dMinFilter = D3DTEXF_POINT; - *d3dMipFilter = D3DTEXF_NONE; - break; - case GL_LINEAR: - *d3dMinFilter = D3DTEXF_LINEAR; - *d3dMipFilter = D3DTEXF_NONE; - break; - case GL_NEAREST_MIPMAP_NEAREST: - *d3dMinFilter = D3DTEXF_POINT; - *d3dMipFilter = D3DTEXF_POINT; - break; - case GL_LINEAR_MIPMAP_NEAREST: - *d3dMinFilter = D3DTEXF_LINEAR; - *d3dMipFilter = D3DTEXF_POINT; - break; - case GL_NEAREST_MIPMAP_LINEAR: - *d3dMinFilter = D3DTEXF_POINT; - *d3dMipFilter = D3DTEXF_LINEAR; - break; - case GL_LINEAR_MIPMAP_LINEAR: - *d3dMinFilter = D3DTEXF_LINEAR; - *d3dMipFilter = D3DTEXF_LINEAR; - break; - default: - *d3dMinFilter = D3DTEXF_POINT; - *d3dMipFilter = D3DTEXF_NONE; - UNREACHABLE(); - } - - if (maxAnisotropy > 1.0f) - { - *d3dMinFilter = D3DTEXF_ANISOTROPIC; - } -} - -bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount, - D3DPRIMITIVETYPE *d3dPrimitiveType, int *d3dPrimitiveCount) -{ - switch (primitiveType) - { - case GL_POINTS: - *d3dPrimitiveType = D3DPT_POINTLIST; - *d3dPrimitiveCount = elementCount; - break; - case GL_LINES: - *d3dPrimitiveType = D3DPT_LINELIST; - *d3dPrimitiveCount = elementCount / 2; - break; - case GL_LINE_LOOP: - *d3dPrimitiveType = D3DPT_LINESTRIP; - *d3dPrimitiveCount = elementCount - 1; // D3D doesn't support line loops, so we draw the last line separately - break; - case GL_LINE_STRIP: - *d3dPrimitiveType = D3DPT_LINESTRIP; - *d3dPrimitiveCount = elementCount - 1; - break; - case GL_TRIANGLES: - *d3dPrimitiveType = D3DPT_TRIANGLELIST; - *d3dPrimitiveCount = elementCount / 3; - break; - case GL_TRIANGLE_STRIP: - *d3dPrimitiveType = D3DPT_TRIANGLESTRIP; - *d3dPrimitiveCount = elementCount - 2; - break; - case GL_TRIANGLE_FAN: - *d3dPrimitiveType = D3DPT_TRIANGLEFAN; - *d3dPrimitiveCount = elementCount - 2; - break; - default: - return false; - } - - return true; -} - -D3DFORMAT ConvertRenderbufferFormat(GLenum format) -{ - switch (format) - { - case GL_NONE: return D3DFMT_NULL; + case GL_RGBA16F_EXT: + return 16; + case GL_RGBA32F_EXT: + return 32; case GL_RGBA4: - case GL_RGB5_A1: - case GL_RGBA8_OES: return D3DFMT_A8R8G8B8; - case GL_RGB565: return D3DFMT_R5G6B5; - case GL_RGB8_OES: return D3DFMT_X8R8G8B8; - case GL_DEPTH_COMPONENT16: - case GL_STENCIL_INDEX8: - case GL_DEPTH24_STENCIL8_OES: return D3DFMT_D24S8; - default: UNREACHABLE(); return D3DFMT_A8R8G8B8; - } -} - -D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples) -{ - if (samples <= 1) - return D3DMULTISAMPLE_NONE; - else - return (D3DMULTISAMPLE_TYPE)samples; -} - -} - -namespace dx2es -{ - -unsigned int GetStencilSize(D3DFORMAT stencilFormat) -{ - if (stencilFormat == D3DFMT_INTZ) - { - return 8; - } - switch(stencilFormat) - { - case D3DFMT_D24FS8: - case D3DFMT_D24S8: - return 8; - case D3DFMT_D24X4S4: return 4; - case D3DFMT_D15S1: - return 1; - case D3DFMT_D16_LOCKABLE: - case D3DFMT_D32: - case D3DFMT_D24X8: - case D3DFMT_D32F_LOCKABLE: - case D3DFMT_D16: - return 0; - //case D3DFMT_D32_LOCKABLE: return 0; // DirectX 9Ex only - //case D3DFMT_S8_LOCKABLE: return 8; // DirectX 9Ex only - default: - return 0; - } -} - -unsigned int GetAlphaSize(D3DFORMAT colorFormat) -{ - switch (colorFormat) - { - case D3DFMT_A16B16G16R16F: - return 16; - case D3DFMT_A32B32G32R32F: - return 32; - case D3DFMT_A2R10G10B10: - return 2; - case D3DFMT_A8R8G8B8: + case GL_RGBA8_OES: + case GL_BGRA8_EXT: return 8; - case D3DFMT_A1R5G5B5: + case GL_RGB5_A1: return 1; - case D3DFMT_X8R8G8B8: - case D3DFMT_R5G6B5: + case GL_RGB8_OES: + case GL_RGB565: + case GL_RGB32F_EXT: + case GL_RGB16F_EXT: return 0; default: return 0; } } -unsigned int GetRedSize(D3DFORMAT colorFormat) +unsigned int GetRedSize(GLenum colorFormat) { switch (colorFormat) { - case D3DFMT_A16B16G16R16F: + case GL_RGBA16F_EXT: + case GL_RGB16F_EXT: return 16; - case D3DFMT_A32B32G32R32F: + case GL_RGBA32F_EXT: + case GL_RGB32F_EXT: return 32; - case D3DFMT_A2R10G10B10: - return 10; - case D3DFMT_A8R8G8B8: - case D3DFMT_X8R8G8B8: + case GL_RGBA4: + return 4; + case GL_RGBA8_OES: + case GL_BGRA8_EXT: + case GL_RGB8_OES: return 8; - case D3DFMT_A1R5G5B5: - case D3DFMT_R5G6B5: + case GL_RGB5_A1: + case GL_RGB565: return 5; default: return 0; } } -unsigned int GetGreenSize(D3DFORMAT colorFormat) +unsigned int GetGreenSize(GLenum colorFormat) { switch (colorFormat) { - case D3DFMT_A16B16G16R16F: + case GL_RGBA16F_EXT: + case GL_RGB16F_EXT: return 16; - case D3DFMT_A32B32G32R32F: + case GL_RGBA32F_EXT: + case GL_RGB32F_EXT: return 32; - case D3DFMT_A2R10G10B10: - return 10; - case D3DFMT_A8R8G8B8: - case D3DFMT_X8R8G8B8: + case GL_RGBA4: + return 4; + case GL_RGBA8_OES: + case GL_BGRA8_EXT: + case GL_RGB8_OES: return 8; - case D3DFMT_A1R5G5B5: + case GL_RGB5_A1: return 5; - case D3DFMT_R5G6B5: + case GL_RGB565: return 6; default: return 0; } } -unsigned int GetBlueSize(D3DFORMAT colorFormat) +unsigned int GetBlueSize(GLenum colorFormat) { switch (colorFormat) { - case D3DFMT_A16B16G16R16F: + case GL_RGBA16F_EXT: + case GL_RGB16F_EXT: return 16; - case D3DFMT_A32B32G32R32F: + case GL_RGBA32F_EXT: + case GL_RGB32F_EXT: return 32; - case D3DFMT_A2R10G10B10: - return 10; - case D3DFMT_A8R8G8B8: - case D3DFMT_X8R8G8B8: + case GL_RGBA4: + return 4; + case GL_RGBA8_OES: + case GL_BGRA8_EXT: + case GL_RGB8_OES: return 8; - case D3DFMT_A1R5G5B5: - case D3DFMT_R5G6B5: + case GL_RGB5_A1: + case GL_RGB565: return 5; default: return 0; } } -unsigned int GetDepthSize(D3DFORMAT depthFormat) +unsigned int GetDepthSize(GLenum depthFormat) { - if (depthFormat == D3DFMT_INTZ) - { - return 24; - } switch (depthFormat) { - case D3DFMT_D16_LOCKABLE: return 16; - case D3DFMT_D32: return 32; - case D3DFMT_D15S1: return 15; - case D3DFMT_D24S8: return 24; - case D3DFMT_D24X8: return 24; - case D3DFMT_D24X4S4: return 24; - case D3DFMT_D16: return 16; - case D3DFMT_D32F_LOCKABLE: return 32; - case D3DFMT_D24FS8: return 24; - //case D3DFMT_D32_LOCKABLE: return 32; // D3D9Ex only - //case D3DFMT_S8_LOCKABLE: return 0; // D3D9Ex only - default: return 0; + case GL_DEPTH_COMPONENT16: return 16; + case GL_DEPTH_COMPONENT32_OES: return 32; + case GL_DEPTH24_STENCIL8_OES: return 24; + default: return 0; } } -GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type) +unsigned int GetStencilSize(GLenum stencilFormat) { - if (type == D3DMULTISAMPLE_NONMASKABLE) - return 0; - else - return type; -} - -bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format) -{ - switch (d3dformat) + switch (stencilFormat) { - case D3DFMT_L8: - return (format == GL_LUMINANCE); - case D3DFMT_A8L8: - return (format == GL_LUMINANCE_ALPHA); - case D3DFMT_DXT1: - return (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT || format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT); - case D3DFMT_DXT3: - return (format == GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE); - case D3DFMT_DXT5: - return (format == GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE); - case D3DFMT_A8R8G8B8: - case D3DFMT_A16B16G16R16F: - case D3DFMT_A32B32G32R32F: - return (format == GL_RGBA || format == GL_BGRA_EXT); - case D3DFMT_X8R8G8B8: - return (format == GL_RGB); - default: - if (d3dformat == D3DFMT_INTZ && gl::IsDepthTexture(format)) - return true; - return false; + case GL_DEPTH24_STENCIL8_OES: return 8; + default: return 0; } } -bool ConvertReadBufferFormat(D3DFORMAT d3dformat, GLenum *format, GLenum *type) +bool IsTriangleMode(GLenum drawMode) { - switch (d3dformat) + switch (drawMode) { - case D3DFMT_A8R8G8B8: - *type = GL_UNSIGNED_BYTE; - *format = GL_BGRA_EXT; - break; - case D3DFMT_X8R8G8B8: - *type = GL_UNSIGNED_BYTE; - *format = GL_RGB; - break; - case D3DFMT_R5G6B5: - *type = GL_UNSIGNED_SHORT_5_6_5; - *format = GL_RGB; - break; - case D3DFMT_A16B16G16R16F: - *type = GL_HALF_FLOAT_OES; - *format = GL_RGBA; - break; - case D3DFMT_A32B32G32R32F: - *type = GL_FLOAT; - *format = GL_RGBA; - break; - case D3DFMT_A4R4G4B4: - *type = GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT; - *format = GL_BGRA_EXT; - break; - case D3DFMT_A1R5G5B5: - *type = GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT; - *format = GL_BGRA_EXT; - break; - default: - *type = GL_NONE; - *format = GL_NONE; - return false; - } - return true; -} - -GLenum ConvertBackBufferFormat(D3DFORMAT format) -{ - switch (format) - { - case D3DFMT_A4R4G4B4: return GL_RGBA4; - case D3DFMT_A8R8G8B8: return GL_RGBA8_OES; - case D3DFMT_A1R5G5B5: return GL_RGB5_A1; - case D3DFMT_R5G6B5: return GL_RGB565; - case D3DFMT_X8R8G8B8: return GL_RGB8_OES; - default: - UNREACHABLE(); - } - - return GL_RGBA4; -} - -GLenum ConvertDepthStencilFormat(D3DFORMAT format) -{ - if (format == D3DFMT_INTZ) - { - return GL_DEPTH24_STENCIL8_OES; - } - switch (format) - { - case D3DFMT_D16: - case D3DFMT_D24X8: - return GL_DEPTH_COMPONENT16; - case D3DFMT_D24S8: - return GL_DEPTH24_STENCIL8_OES; - default: - UNREACHABLE(); - } - - return GL_DEPTH24_STENCIL8_OES; -} - -} - -namespace dx -{ - -bool IsCompressedFormat(D3DFORMAT surfaceFormat) -{ - switch(surfaceFormat) - { - case D3DFMT_DXT1: - case D3DFMT_DXT2: - case D3DFMT_DXT3: - case D3DFMT_DXT4: - case D3DFMT_DXT5: + case GL_TRIANGLES: + case GL_TRIANGLE_FAN: + case GL_TRIANGLE_STRIP: return true; - default: + case GL_POINTS: + case GL_LINES: + case GL_LINE_LOOP: + case GL_LINE_STRIP: return false; + default: UNREACHABLE(); } -} -size_t ComputeRowSize(D3DFORMAT format, unsigned int width) -{ - if (format == D3DFMT_INTZ) - { - return 4 * width; - } - switch (format) - { - case D3DFMT_L8: - return 1 * width; - case D3DFMT_A8L8: - return 2 * width; - case D3DFMT_X8R8G8B8: - case D3DFMT_A8R8G8B8: - return 4 * width; - case D3DFMT_A16B16G16R16F: - return 8 * width; - case D3DFMT_A32B32G32R32F: - return 16 * width; - case D3DFMT_DXT1: - return 8 * ((width + 3) / 4); - case D3DFMT_DXT3: - case D3DFMT_DXT5: - return 16 * ((width + 3) / 4); - default: - UNREACHABLE(); - return 0; - } + return false; } } diff --git a/gfx/angle/src/libGLESv2/utilities.h b/gfx/angle/src/libGLESv2/utilities.h index eb133de59b61..ed663ebca201 100644 --- a/gfx/angle/src/libGLESv2/utilities.h +++ b/gfx/angle/src/libGLESv2/utilities.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -12,20 +12,15 @@ #define GL_APICALL #include #include -#include #include -const D3DFORMAT D3DFMT_INTZ = ((D3DFORMAT)(MAKEFOURCC('I','N','T','Z'))); -const D3DFORMAT D3DFMT_NULL = ((D3DFORMAT)(MAKEFOURCC('N','U','L','L'))); - namespace gl { struct Color; -int UniformExternalComponentCount(GLenum type); -int UniformInternalComponentCount(GLenum type); +int UniformComponentCount(GLenum type); GLenum UniformComponentType(GLenum type); size_t UniformInternalSize(GLenum type); size_t UniformExternalSize(GLenum type); @@ -34,10 +29,12 @@ int VariableColumnCount(GLenum type); int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize); +void MakeValidSize(bool isImage, bool isCompressed, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset); int ComputePixelSize(GLint internalformat); GLsizei ComputePitch(GLsizei width, GLint internalformat, GLint alignment); GLsizei ComputeCompressedPitch(GLsizei width, GLenum format); GLsizei ComputeCompressedSize(GLsizei width, GLsizei height, GLenum format); +GLsizei ComputeTypeSize(GLenum type); bool IsCompressed(GLenum format); bool IsDepthTexture(GLenum format); bool IsStencilTexture(GLenum format); @@ -53,69 +50,18 @@ bool IsStencilRenderable(GLenum internalformat); bool IsFloat32Format(GLint internalformat); bool IsFloat16Format(GLint internalformat); -} -namespace es2dx -{ +GLuint GetAlphaSize(GLenum colorFormat); +GLuint GetRedSize(GLenum colorFormat); +GLuint GetGreenSize(GLenum colorFormat); +GLuint GetBlueSize(GLenum colorFormat); +GLuint GetDepthSize(GLenum depthFormat); +GLuint GetStencilSize(GLenum stencilFormat); +bool IsTriangleMode(GLenum drawMode); -D3DCMPFUNC ConvertComparison(GLenum comparison); -D3DCOLOR ConvertColor(gl::Color color); -D3DBLEND ConvertBlendFunc(GLenum blend); -D3DBLENDOP ConvertBlendOp(GLenum blendOp); -D3DSTENCILOP ConvertStencilOp(GLenum stencilOp); -D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap); -D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace); -D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace); -DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha); -D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter, float maxAnisotropy); -void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter, float maxAnisotropy); -bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount, - D3DPRIMITIVETYPE *d3dPrimitiveType, int *d3dPrimitiveCount); -D3DFORMAT ConvertRenderbufferFormat(GLenum format); -D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples); - -} - -namespace dx2es -{ - -GLuint GetAlphaSize(D3DFORMAT colorFormat); -GLuint GetRedSize(D3DFORMAT colorFormat); -GLuint GetGreenSize(D3DFORMAT colorFormat); -GLuint GetBlueSize(D3DFORMAT colorFormat); -GLuint GetDepthSize(D3DFORMAT depthFormat); -GLuint GetStencilSize(D3DFORMAT stencilFormat); - -GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type); - -bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format); -bool ConvertReadBufferFormat(D3DFORMAT d3dformat, GLenum *format, GLenum *type); -GLenum ConvertBackBufferFormat(D3DFORMAT format); -GLenum ConvertDepthStencilFormat(D3DFORMAT format); - -} - -namespace dx -{ -bool IsCompressedFormat(D3DFORMAT format); -size_t ComputeRowSize(D3DFORMAT format, unsigned int width); } std::string getTempPath(); void writeFile(const char* path, const void* data, size_t size); -inline bool isDeviceLostError(HRESULT errorCode) -{ - switch (errorCode) - { - case D3DERR_DRIVERINTERNALERROR: - case D3DERR_DEVICELOST: - case D3DERR_DEVICEHUNG: - case D3DERR_DEVICEREMOVED: - return true; - default: - return false; - } -} - #endif // LIBGLESV2_UTILITIES_H diff --git a/gfx/angle/src/third_party/murmurhash/LICENSE b/gfx/angle/src/third_party/murmurhash/LICENSE new file mode 100644 index 000000000000..6a385f0f078c --- /dev/null +++ b/gfx/angle/src/third_party/murmurhash/LICENSE @@ -0,0 +1,2 @@ +// MurmurHash3 was written by Austin Appleby, and is placed in the public +// domain. The author hereby disclaims copyright to this source code. \ No newline at end of file diff --git a/gfx/angle/src/third_party/murmurhash/MurmurHash3.cpp b/gfx/angle/src/third_party/murmurhash/MurmurHash3.cpp new file mode 100644 index 000000000000..94a18a598c5b --- /dev/null +++ b/gfx/angle/src/third_party/murmurhash/MurmurHash3.cpp @@ -0,0 +1,334 @@ +//----------------------------------------------------------------------------- +// MurmurHash3 was written by Austin Appleby, and is placed in the public +// domain. The author hereby disclaims copyright to this source code. + +// Note - The x86 and x64 versions do _not_ produce the same results, as the +// algorithms are optimized for their respective platforms. You can still +// compile and run any of them on any platform, but your performance with the +// non-native version will be less than optimal. + +#include "MurmurHash3.h" + +//----------------------------------------------------------------------------- +// Platform-specific functions and macros + +// Microsoft Visual Studio + +#if defined(_MSC_VER) + +#define FORCE_INLINE __forceinline + +#include + +#define ROTL32(x,y) _rotl(x,y) +#define ROTL64(x,y) _rotl64(x,y) + +#define BIG_CONSTANT(x) (x) + +// Other compilers + +#else // defined(_MSC_VER) + +#define FORCE_INLINE __attribute__((always_inline)) + +inline uint32_t rotl32 ( uint32_t x, int8_t r ) +{ + return (x << r) | (x >> (32 - r)); +} + +inline uint64_t rotl64 ( uint64_t x, int8_t r ) +{ + return (x << r) | (x >> (64 - r)); +} + +#define ROTL32(x,y) rotl32(x,y) +#define ROTL64(x,y) rotl64(x,y) + +#define BIG_CONSTANT(x) (x##LLU) + +#endif // !defined(_MSC_VER) + +//----------------------------------------------------------------------------- +// Block read - if your platform needs to do endian-swapping or can only +// handle aligned reads, do the conversion here + +FORCE_INLINE uint32_t getblock ( const uint32_t * p, int i ) +{ + return p[i]; +} + +FORCE_INLINE uint64_t getblock ( const uint64_t * p, int i ) +{ + return p[i]; +} + +//----------------------------------------------------------------------------- +// Finalization mix - force all bits of a hash block to avalanche + +FORCE_INLINE uint32_t fmix ( uint32_t h ) +{ + h ^= h >> 16; + h *= 0x85ebca6b; + h ^= h >> 13; + h *= 0xc2b2ae35; + h ^= h >> 16; + + return h; +} + +//---------- + +FORCE_INLINE uint64_t fmix ( uint64_t k ) +{ + k ^= k >> 33; + k *= BIG_CONSTANT(0xff51afd7ed558ccd); + k ^= k >> 33; + k *= BIG_CONSTANT(0xc4ceb9fe1a85ec53); + k ^= k >> 33; + + return k; +} + +//----------------------------------------------------------------------------- + +void MurmurHash3_x86_32 ( const void * key, int len, + uint32_t seed, void * out ) +{ + const uint8_t * data = (const uint8_t*)key; + const int nblocks = len / 4; + + uint32_t h1 = seed; + + const uint32_t c1 = 0xcc9e2d51; + const uint32_t c2 = 0x1b873593; + + //---------- + // body + + const uint32_t * blocks = (const uint32_t *)(data + nblocks*4); + + for(int i = -nblocks; i; i++) + { + uint32_t k1 = getblock(blocks,i); + + k1 *= c1; + k1 = ROTL32(k1,15); + k1 *= c2; + + h1 ^= k1; + h1 = ROTL32(h1,13); + h1 = h1*5+0xe6546b64; + } + + //---------- + // tail + + const uint8_t * tail = (const uint8_t*)(data + nblocks*4); + + uint32_t k1 = 0; + + switch(len & 3) + { + case 3: k1 ^= tail[2] << 16; + case 2: k1 ^= tail[1] << 8; + case 1: k1 ^= tail[0]; + k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1; + }; + + //---------- + // finalization + + h1 ^= len; + + h1 = fmix(h1); + + *(uint32_t*)out = h1; +} + +//----------------------------------------------------------------------------- + +void MurmurHash3_x86_128 ( const void * key, const int len, + uint32_t seed, void * out ) +{ + const uint8_t * data = (const uint8_t*)key; + const int nblocks = len / 16; + + uint32_t h1 = seed; + uint32_t h2 = seed; + uint32_t h3 = seed; + uint32_t h4 = seed; + + const uint32_t c1 = 0x239b961b; + const uint32_t c2 = 0xab0e9789; + const uint32_t c3 = 0x38b34ae5; + const uint32_t c4 = 0xa1e38b93; + + //---------- + // body + + const uint32_t * blocks = (const uint32_t *)(data + nblocks*16); + + for(int i = -nblocks; i; i++) + { + uint32_t k1 = getblock(blocks,i*4+0); + uint32_t k2 = getblock(blocks,i*4+1); + uint32_t k3 = getblock(blocks,i*4+2); + uint32_t k4 = getblock(blocks,i*4+3); + + k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1; + + h1 = ROTL32(h1,19); h1 += h2; h1 = h1*5+0x561ccd1b; + + k2 *= c2; k2 = ROTL32(k2,16); k2 *= c3; h2 ^= k2; + + h2 = ROTL32(h2,17); h2 += h3; h2 = h2*5+0x0bcaa747; + + k3 *= c3; k3 = ROTL32(k3,17); k3 *= c4; h3 ^= k3; + + h3 = ROTL32(h3,15); h3 += h4; h3 = h3*5+0x96cd1c35; + + k4 *= c4; k4 = ROTL32(k4,18); k4 *= c1; h4 ^= k4; + + h4 = ROTL32(h4,13); h4 += h1; h4 = h4*5+0x32ac3b17; + } + + //---------- + // tail + + const uint8_t * tail = (const uint8_t*)(data + nblocks*16); + + uint32_t k1 = 0; + uint32_t k2 = 0; + uint32_t k3 = 0; + uint32_t k4 = 0; + + switch(len & 15) + { + case 15: k4 ^= tail[14] << 16; + case 14: k4 ^= tail[13] << 8; + case 13: k4 ^= tail[12] << 0; + k4 *= c4; k4 = ROTL32(k4,18); k4 *= c1; h4 ^= k4; + + case 12: k3 ^= tail[11] << 24; + case 11: k3 ^= tail[10] << 16; + case 10: k3 ^= tail[ 9] << 8; + case 9: k3 ^= tail[ 8] << 0; + k3 *= c3; k3 = ROTL32(k3,17); k3 *= c4; h3 ^= k3; + + case 8: k2 ^= tail[ 7] << 24; + case 7: k2 ^= tail[ 6] << 16; + case 6: k2 ^= tail[ 5] << 8; + case 5: k2 ^= tail[ 4] << 0; + k2 *= c2; k2 = ROTL32(k2,16); k2 *= c3; h2 ^= k2; + + case 4: k1 ^= tail[ 3] << 24; + case 3: k1 ^= tail[ 2] << 16; + case 2: k1 ^= tail[ 1] << 8; + case 1: k1 ^= tail[ 0] << 0; + k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1; + }; + + //---------- + // finalization + + h1 ^= len; h2 ^= len; h3 ^= len; h4 ^= len; + + h1 += h2; h1 += h3; h1 += h4; + h2 += h1; h3 += h1; h4 += h1; + + h1 = fmix(h1); + h2 = fmix(h2); + h3 = fmix(h3); + h4 = fmix(h4); + + h1 += h2; h1 += h3; h1 += h4; + h2 += h1; h3 += h1; h4 += h1; + + ((uint32_t*)out)[0] = h1; + ((uint32_t*)out)[1] = h2; + ((uint32_t*)out)[2] = h3; + ((uint32_t*)out)[3] = h4; +} + +//----------------------------------------------------------------------------- + +void MurmurHash3_x64_128 ( const void * key, const int len, + const uint32_t seed, void * out ) +{ + const uint8_t * data = (const uint8_t*)key; + const int nblocks = len / 16; + + uint64_t h1 = seed; + uint64_t h2 = seed; + + const uint64_t c1 = BIG_CONSTANT(0x87c37b91114253d5); + const uint64_t c2 = BIG_CONSTANT(0x4cf5ad432745937f); + + //---------- + // body + + const uint64_t * blocks = (const uint64_t *)(data); + + for(int i = 0; i < nblocks; i++) + { + uint64_t k1 = getblock(blocks,i*2+0); + uint64_t k2 = getblock(blocks,i*2+1); + + k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1; + + h1 = ROTL64(h1,27); h1 += h2; h1 = h1*5+0x52dce729; + + k2 *= c2; k2 = ROTL64(k2,33); k2 *= c1; h2 ^= k2; + + h2 = ROTL64(h2,31); h2 += h1; h2 = h2*5+0x38495ab5; + } + + //---------- + // tail + + const uint8_t * tail = (const uint8_t*)(data + nblocks*16); + + uint64_t k1 = 0; + uint64_t k2 = 0; + + switch(len & 15) + { + case 15: k2 ^= uint64_t(tail[14]) << 48; + case 14: k2 ^= uint64_t(tail[13]) << 40; + case 13: k2 ^= uint64_t(tail[12]) << 32; + case 12: k2 ^= uint64_t(tail[11]) << 24; + case 11: k2 ^= uint64_t(tail[10]) << 16; + case 10: k2 ^= uint64_t(tail[ 9]) << 8; + case 9: k2 ^= uint64_t(tail[ 8]) << 0; + k2 *= c2; k2 = ROTL64(k2,33); k2 *= c1; h2 ^= k2; + + case 8: k1 ^= uint64_t(tail[ 7]) << 56; + case 7: k1 ^= uint64_t(tail[ 6]) << 48; + case 6: k1 ^= uint64_t(tail[ 5]) << 40; + case 5: k1 ^= uint64_t(tail[ 4]) << 32; + case 4: k1 ^= uint64_t(tail[ 3]) << 24; + case 3: k1 ^= uint64_t(tail[ 2]) << 16; + case 2: k1 ^= uint64_t(tail[ 1]) << 8; + case 1: k1 ^= uint64_t(tail[ 0]) << 0; + k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1; + }; + + //---------- + // finalization + + h1 ^= len; h2 ^= len; + + h1 += h2; + h2 += h1; + + h1 = fmix(h1); + h2 = fmix(h2); + + h1 += h2; + h2 += h1; + + ((uint64_t*)out)[0] = h1; + ((uint64_t*)out)[1] = h2; +} + +//----------------------------------------------------------------------------- diff --git a/gfx/angle/src/third_party/murmurhash/MurmurHash3.h b/gfx/angle/src/third_party/murmurhash/MurmurHash3.h new file mode 100644 index 000000000000..3c6c78cdae59 --- /dev/null +++ b/gfx/angle/src/third_party/murmurhash/MurmurHash3.h @@ -0,0 +1,37 @@ +//----------------------------------------------------------------------------- +// MurmurHash3 was written by Austin Appleby, and is placed in the public +// domain. The author hereby disclaims copyright to this source code. + +#ifndef _MURMURHASH3_H_ +#define _MURMURHASH3_H_ + +//----------------------------------------------------------------------------- +// Platform-specific functions and macros + +// Microsoft Visual Studio + +#if defined(_MSC_VER) + +typedef unsigned char uint8_t; +typedef unsigned long uint32_t; +typedef unsigned __int64 uint64_t; + +// Other compilers + +#else // defined(_MSC_VER) + +#include + +#endif // !defined(_MSC_VER) + +//----------------------------------------------------------------------------- + +void MurmurHash3_x86_32 ( const void * key, int len, uint32_t seed, void * out ); + +void MurmurHash3_x86_128 ( const void * key, int len, uint32_t seed, void * out ); + +void MurmurHash3_x64_128 ( const void * key, int len, uint32_t seed, void * out ); + +//----------------------------------------------------------------------------- + +#endif // _MURMURHASH3_H_ \ No newline at end of file From ebe730706539c74d708416ae1a0dc7404cd34509 Mon Sep 17 00:00:00 2001 From: Masatoshi Kimura Date: Sat, 7 Sep 2013 09:34:20 +0900 Subject: [PATCH 07/30] Bug 913494 - Remove enablePrivilege usage from tests for password manager. r=bholley --- .../passwordmgr/test/pwmgr_common.js | 20 ++++------ .../passwordmgr/test/test_basic_form_2.html | 1 - .../test/test_basic_form_2pw_2.html | 8 +--- .../test/test_basic_form_autocomplete.html | 16 ++------ .../test/test_basic_form_html5.html | 2 - ...test_basic_form_observer_autocomplete.html | 16 +++----- ...est_basic_form_observer_autofillForms.html | 21 +++------- .../test_basic_form_observer_foundLogins.html | 38 +++++++------------ .../test/test_basic_form_pwonly.html | 3 +- .../passwordmgr/test/test_bug_227640.html | 2 - .../passwordmgr/test/test_bug_627616.html | 2 +- .../test/test_master_password.html | 5 +-- .../test/test_master_password_cleanup.html | 5 +-- .../passwordmgr/test/test_notifications.html | 15 +++----- .../test/test_privbrowsing_perwindowpb.html | 8 ++-- .../components/passwordmgr/test/test_xhr.html | 7 +--- .../passwordmgr/test/test_zzz_finish.html | 6 +-- 17 files changed, 58 insertions(+), 117 deletions(-) diff --git a/toolkit/components/passwordmgr/test/pwmgr_common.js b/toolkit/components/passwordmgr/test/pwmgr_common.js index 5eb6659383c7..9848ce3c9271 100644 --- a/toolkit/components/passwordmgr/test/pwmgr_common.js +++ b/toolkit/components/passwordmgr/test/pwmgr_common.js @@ -109,19 +109,17 @@ function checkUnmodifiedForm(formNum) { // Mochitest gives us a sendKey(), but it's targeted to a specific element. // This basically sends an untargeted key event, to whatever's focused. function doKey(aKey, modifier) { - // Seems we need to enable this again, or sendKeyEvent() complaints. - netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); - var keyName = "DOM_VK_" + aKey.toUpperCase(); - var key = Components.interfaces.nsIDOMKeyEvent[keyName]; + var key = KeyEvent[keyName]; // undefined --> null if (!modifier) modifier = null; // Window utils for sending fake sey events. - var wutils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor). - getInterface(Components.interfaces.nsIDOMWindowUtils); + var wutils = window.QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor). + getInterface(SpecialPowers.Ci.nsIDOMWindowUtils); + wutils = SpecialPowers.wrap(wutils); if (wutils.sendKeyEvent("keydown", key, 0, modifier)) { wutils.sendKeyEvent("keypress", key, 0, modifier); @@ -131,10 +129,8 @@ function doKey(aKey, modifier) { // Init with a common login function commonInit() { - netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); - - var pwmgr = Components.classes["@mozilla.org/login-manager;1"]. - getService(Components.interfaces.nsILoginManager); + var pwmgr = SpecialPowers.Cc["@mozilla.org/login-manager;1"]. + getService(SpecialPowers.Ci.nsILoginManager); ok(pwmgr != null, "Access LoginManager"); @@ -152,8 +148,8 @@ function commonInit() { } // Add a login that's used in multiple tests - var login = Components.classes["@mozilla.org/login-manager/loginInfo;1"]. - createInstance(Components.interfaces.nsILoginInfo); + var login = SpecialPowers.Cc["@mozilla.org/login-manager/loginInfo;1"]. + createInstance(SpecialPowers.Ci.nsILoginInfo); login.init("http://mochi.test:8888", "http://mochi.test:8888", null, "testuser", "testpass", "uname", "pword"); pwmgr.addLogin(login); diff --git a/toolkit/components/passwordmgr/test/test_basic_form_2.html b/toolkit/components/passwordmgr/test/test_basic_form_2.html index f1e8bcef0348..00d5dcb95ae5 100644 --- a/toolkit/components/passwordmgr/test/test_basic_form_2.html +++ b/toolkit/components/passwordmgr/test/test_basic_form_2.html @@ -39,7 +39,6 @@ SpecialPowers.setBoolPref("signon.autofillForms", false); /** Test for Login Manager: simple form fill with autofillForms disabled **/ function startTest(){ - netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); // Ensure the form is empty at start is($_(1, "uname").value, "", "Checking for blank username"); is($_(1, "pword").value, "", "Checking for blank password"); diff --git a/toolkit/components/passwordmgr/test/test_basic_form_2pw_2.html b/toolkit/components/passwordmgr/test/test_basic_form_2pw_2.html index 54251e071ba7..d99dc517435b 100644 --- a/toolkit/components/passwordmgr/test/test_basic_form_2pw_2.html +++ b/toolkit/components/passwordmgr/test/test_basic_form_2pw_2.html @@ -100,8 +100,6 @@ function getFormSubmitButton(formNum) { // Counts the number of logins currently stored by password manager. function countLogins() { - netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); - var logins = pwmgr.getAllLogins(); return logins.length; @@ -110,12 +108,10 @@ function countLogins() { commonInit(); // Get the pwmgr service -netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); - -var Cc_pwmgr = Components.classes["@mozilla.org/login-manager;1"]; +var Cc_pwmgr = SpecialPowers.Cc["@mozilla.org/login-manager;1"]; ok(Cc_pwmgr != null, "Access Cc[@mozilla.org/login-manager;1]"); -var Ci_pwmgr = Components.interfaces.nsILoginManager; +var Ci_pwmgr = SpecialPowers.Ci.nsILoginManager; ok(Ci_pwmgr != null, "Access Ci.nsILoginManager"); var pwmgr = Cc_pwmgr.getService(Ci_pwmgr); diff --git a/toolkit/components/passwordmgr/test/test_basic_form_autocomplete.html b/toolkit/components/passwordmgr/test/test_basic_form_autocomplete.html index c4068077e2c5..0bf5737d4152 100644 --- a/toolkit/components/passwordmgr/test/test_basic_form_autocomplete.html +++ b/toolkit/components/passwordmgr/test/test_basic_form_autocomplete.html @@ -21,8 +21,8 @@ ok(pwmgr != null, "nsLoginManager service"); // Create some logins just for this form, since we'll be deleting them. var nsLoginInfo = -SpecialPowers.wrap(Components).Constructor("@mozilla.org/login-manager/loginInfo;1", - Components.interfaces.nsILoginInfo, "init"); +SpecialPowers.wrap(SpecialPowers.Components).Constructor("@mozilla.org/login-manager/loginInfo;1", + SpecialPowers.Ci.nsILoginInfo, "init"); ok(nsLoginInfo != null, "nsLoginInfo constructor"); @@ -167,7 +167,7 @@ try { var uname = $_(1, "uname"); var pword = $_(1, "pword"); -const shiftModifier = Components.interfaces.nsIDOMEvent.SHIFT_MASK; +const shiftModifier = SpecialPowers.Ci.nsIDOMEvent.SHIFT_MASK; // Restore the form to the default state. function restoreForm() { @@ -410,20 +410,12 @@ function runTest(testNum) { gNextTestWillOpenPopup = false; break; - /* The previous comments said that test 14 was special and needed to not - * have enablePrivilege, or else dispatchEvent will send a trusted event - * (we're testing to see if we ignore untrusted events, so don't want - * that). - * We should file a bug to look into this. - */ case 14: - /* // Send a fake (untrusted) event. checkACForm("", ""); uname.value = "zzzuser4"; sendFakeAutocompleteEvent(uname); checkACForm("zzzuser4", ""); - */ gNextTestWillOpenPopup = true; break; @@ -799,7 +791,7 @@ function getMenuEntries() { } function startTest() { - var Ci = Components.interfaces; + var Ci = SpecialPowers.Ci; chromeWin = SpecialPowers.wrap(window) .QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsIWebNavigation) diff --git a/toolkit/components/passwordmgr/test/test_basic_form_html5.html b/toolkit/components/passwordmgr/test/test_basic_form_html5.html index b4fb1d52b5e1..ba50cb3cf11e 100644 --- a/toolkit/components/passwordmgr/test/test_basic_form_html5.html +++ b/toolkit/components/passwordmgr/test/test_basic_form_html5.html @@ -133,8 +133,6 @@ pwmgr.addLogin(login4); (Password manager not working with input type=email) */ function startTest() { - netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); - checkForm(1, "testuser@example.com", "testpass1"); checkForm(2, "555-555-5555", "testpass2"); checkForm(3, "http://mozilla.org", "testpass3"); diff --git a/toolkit/components/passwordmgr/test/test_basic_form_observer_autocomplete.html b/toolkit/components/passwordmgr/test/test_basic_form_observer_autocomplete.html index 2325656b11f1..2e1b313f9e63 100644 --- a/toolkit/components/passwordmgr/test/test_basic_form_observer_autocomplete.html +++ b/toolkit/components/passwordmgr/test/test_basic_form_observer_autocomplete.html @@ -11,9 +11,6 @@ Login Manager test: simple form with autocomplete off and notifying observers &

@@ -73,7 +65,6 @@ os.addObserver(TestObserver, "passwordmgr-found-logins", false); /** Test for Login Manager: simple form with autofillForms disabled and notifying observers **/ function startTest(){ - netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); // Test that found-form observer is notified & got correct data is(TestObserver.receivedNotificationFoundForm, true, "Checking found-form observer was notified"); is(TestObserver.dataFoundForm, "noAutofillForms", "Checking found-form observer got correct data"); @@ -85,8 +76,8 @@ function startTest(){ // Test that found-logins observer is notified & got correct data is(TestObserver.receivedNotificationFoundLogins, true, "Checking found-logins observer was notified"); is(TestObserver.dataFoundLogins.get("didntFillReason"), "noAutofillForms", "Checking didntFillReason is noAutofillForms"); - is(TestObserver.dataFoundLogins.get("usernameField"), $_(1, "uname"), "Checking username field is correct"); - is(TestObserver.dataFoundLogins.get("passwordField"), $_(1, "pword"), "Checking password field is correct"); + is(SpecialPowers.unwrap(TestObserver.dataFoundLogins.get("usernameField")), $_(1, "uname"), "Checking username field is correct"); + is(SpecialPowers.unwrap(TestObserver.dataFoundLogins.get("passwordField")), $_(1, "pword"), "Checking password field is correct"); is(TestObserver.dataFoundLogins.get("foundLogins").constructor.name, "Array", "Checking foundLogins is array"); is(TestObserver.dataFoundLogins.get("foundLogins").length, 1, "Checking foundLogins contains one login"); ok(TestObserver.dataFoundLogins.get("selectedLogin").QueryInterface(Ci.nsILoginInfo), "Checking selectedLogin is nsILoginInfo"); @@ -97,8 +88,8 @@ function startTest(){ SpecialPowers.setBoolPref("signon.autofillForms", true); // Remove the observer - os.removeObserver(TestObserver, "passwordmgr-found-form"); - os.removeObserver(TestObserver, "passwordmgr-found-logins"); + SpecialPowers.removeObserver(TestObserver, "passwordmgr-found-form"); + SpecialPowers.removeObserver(TestObserver, "passwordmgr-found-logins"); SimpleTest.finish(); } diff --git a/toolkit/components/passwordmgr/test/test_basic_form_observer_foundLogins.html b/toolkit/components/passwordmgr/test/test_basic_form_observer_foundLogins.html index 4615b2a62626..e5ac8a4b3037 100644 --- a/toolkit/components/passwordmgr/test/test_basic_form_observer_foundLogins.html +++ b/toolkit/components/passwordmgr/test/test_basic_form_observer_foundLogins.html @@ -14,16 +14,12 @@ SimpleTest.waitForExplicitFinish(); const Cc = SpecialPowers.Cc; const Ci = SpecialPowers.Ci; -netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); -const Cu = Components.utils; - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); // Configure the login manager with two logins for one of the forms // so we can do a multiple logins test. var nsLoginInfo = - new Components.Constructor("@mozilla.org/login-manager/loginInfo;1", - Components.interfaces.nsILoginInfo); + new SpecialPowers.wrap(SpecialPowers.Components).Constructor("@mozilla.org/login-manager/loginInfo;1", + SpecialPowers.Ci.nsILoginInfo); var login1 = new nsLoginInfo(); login1.init("http://mochi.test:8888", "http://www.example.com", null, "testuser1", "testpass1", "uname", "pword"); @@ -37,9 +33,7 @@ pwmgr.addLogin(login2); var TestObserver = { results: {}, - QueryInterface : XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference]), observe : function (subject, topic, data) { - netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); if (topic == "passwordmgr-found-logins") { var formInfo = subject.QueryInterface(Ci.nsIPropertyBag2); var id = formInfo.get("passwordField").form.id; @@ -54,9 +48,7 @@ for (var formID of ["form1", "form2", "form3", "form4", "form5"]) TestObserver.results[formID] = { receivedNotification: false, data: null }; // Add the observer -var os = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); -os.addObserver(TestObserver, "passwordmgr-found-logins", false); +SpecialPowers.addObserver(TestObserver, "passwordmgr-found-logins", false);

@@ -116,13 +108,11 @@ os.addObserver(TestObserver, "passwordmgr-found-logins", false); /** Test for Login Manager: notifying observers of passwordmgr-found-logins **/ function startTest(){ - netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); - // Test notification of a form that was filled. is(TestObserver.results["form1"].receivedNotification, true, "Checking observer was notified"); is(TestObserver.results["form1"].data.get("didntFillReason"), null, "Checking didntFillReason is null"); - is(TestObserver.results["form1"].data.get("usernameField"), $_(1, "uname"), "Checking username field is correct"); - is(TestObserver.results["form1"].data.get("passwordField"), $_(1, "pword"), "Checking password field is correct"); + is(SpecialPowers.unwrap(TestObserver.results["form1"].data.get("usernameField")), $_(1, "uname"), "Checking username field is correct"); + is(SpecialPowers.unwrap(TestObserver.results["form1"].data.get("passwordField")), $_(1, "pword"), "Checking password field is correct"); is(TestObserver.results["form1"].data.get("foundLogins").constructor.name, "Array", "Checking foundLogins is array"); is(TestObserver.results["form1"].data.get("foundLogins").length, 1, "Checking foundLogins contains one login"); ok(TestObserver.results["form1"].data.get("selectedLogin").QueryInterface(Ci.nsILoginInfo), "Checking selectedLogin is nsILoginInfo"); @@ -133,8 +123,8 @@ function startTest(){ // already contained a value. is(TestObserver.results["form2"].receivedNotification, true, "Checking observer was notified"); is(TestObserver.results["form2"].data.get("didntFillReason"), "existingUsername", "Checking didntFillReason is existingUsername"); - is(TestObserver.results["form2"].data.get("usernameField"), $_(2, "uname"), "Checking username field is correct"); - is(TestObserver.results["form2"].data.get("passwordField"), $_(2, "pword"), "Checking password field is correct"); + is(SpecialPowers.unwrap(TestObserver.results["form2"].data.get("usernameField")), $_(2, "uname"), "Checking username field is correct"); + is(SpecialPowers.unwrap(TestObserver.results["form2"].data.get("passwordField")), $_(2, "pword"), "Checking password field is correct"); is(TestObserver.results["form2"].data.get("foundLogins").constructor.name, "Array", "Checking foundLogins is array"); is(TestObserver.results["form2"].data.get("foundLogins").length, 1, "Checking foundLogins contains one login"); is(TestObserver.results["form2"].data.get("selectedLogin"), null, "Checking selectedLogin is null"); @@ -143,8 +133,8 @@ function startTest(){ // already contained a value. is(TestObserver.results["form3"].receivedNotification, true, "Checking observer was notified"); is(TestObserver.results["form3"].data.get("didntFillReason"), "existingPassword", "Checking didntFillReason is existingPassword"); - is(TestObserver.results["form3"].data.get("usernameField"), $_(3, "uname"), "Checking username field is correct"); - is(TestObserver.results["form3"].data.get("passwordField"), $_(3, "pword"), "Checking password field is correct"); + is(SpecialPowers.unwrap(TestObserver.results["form3"].data.get("usernameField")), $_(3, "uname"), "Checking username field is correct"); + is(SpecialPowers.unwrap(TestObserver.results["form3"].data.get("passwordField")), $_(3, "pword"), "Checking password field is correct"); is(TestObserver.results["form3"].data.get("foundLogins").constructor.name, "Array", "Checking foundLogins is array"); is(TestObserver.results["form3"].data.get("foundLogins").length, 1, "Checking foundLogins contains one login"); is(TestObserver.results["form3"].data.get("selectedLogin"), null, "Checking selectedLogin is null"); @@ -152,8 +142,8 @@ function startTest(){ // Test notification of a form that wasn't filled because autocomplete is off. is(TestObserver.results["form4"].receivedNotification, true, "Checking observer was notified"); is(TestObserver.results["form4"].data.get("didntFillReason"), "autocompleteOff", "Checking didntFillReason is autocompleteOff"); - is(TestObserver.results["form4"].data.get("usernameField"), $_(4, "uname"), "Checking username field is correct"); - is(TestObserver.results["form4"].data.get("passwordField"), $_(4, "pword"), "Checking password field is correct"); + is(SpecialPowers.unwrap(TestObserver.results["form4"].data.get("usernameField")), $_(4, "uname"), "Checking username field is correct"); + is(SpecialPowers.unwrap(TestObserver.results["form4"].data.get("passwordField")), $_(4, "pword"), "Checking password field is correct"); is(TestObserver.results["form4"].data.get("foundLogins").constructor.name, "Array", "Checking foundLogins is array"); is(TestObserver.results["form4"].data.get("foundLogins").length, 1, "Checking foundLogins contains one login"); ok(TestObserver.results["form4"].data.get("selectedLogin").QueryInterface(Ci.nsILoginInfo), "Checking selectedLogin is nsILoginInfo"); @@ -164,8 +154,8 @@ function startTest(){ // are available for the form. is(TestObserver.results["form5"].receivedNotification, true, "Checking observer was notified"); is(TestObserver.results["form5"].data.get("didntFillReason"), "multipleLogins", "Checking didntFillReason is multipleLogins"); - is(TestObserver.results["form5"].data.get("usernameField"), $_(5, "uname"), "Checking username field is correct"); - is(TestObserver.results["form5"].data.get("passwordField"), $_(5, "pword"), "Checking password field is correct"); + is(SpecialPowers.unwrap(TestObserver.results["form5"].data.get("usernameField")), $_(5, "uname"), "Checking username field is correct"); + is(SpecialPowers.unwrap(TestObserver.results["form5"].data.get("passwordField")), $_(5, "pword"), "Checking password field is correct"); is(TestObserver.results["form5"].data.get("foundLogins").constructor.name, "Array", "Checking foundLogins is array"); is(TestObserver.results["form5"].data.get("foundLogins").length, 2, "Checking foundLogins contains two logins"); is(TestObserver.results["form5"].data.get("selectedLogin"), null, "Checking selectedLogin is null"); @@ -175,7 +165,7 @@ function startTest(){ // test_basic_form_observer_autofillForms.html. // Remove the observer - os.removeObserver(TestObserver, "passwordmgr-found-logins"); + SpecialPowers.removeObserver(TestObserver, "passwordmgr-found-logins"); // Remove the logins added for the multiple logins test. pwmgr.removeLogin(login1); diff --git a/toolkit/components/passwordmgr/test/test_basic_form_pwonly.html b/toolkit/components/passwordmgr/test/test_basic_form_pwonly.html index 8dca8685de7d..ead1b32a2a38 100644 --- a/toolkit/components/passwordmgr/test/test_basic_form_pwonly.html +++ b/toolkit/components/passwordmgr/test/test_basic_form_pwonly.html @@ -15,7 +15,7 @@ SimpleTest.waitForExplicitFinish(); var pwmgr = SpecialPowers.Cc["@mozilla.org/login-manager;1"] .getService(SpecialPowers.Ci.nsILoginManager); -var nsLoginInfo = new Components.Constructor("@mozilla.org/login-manager/loginInfo;1", Components.interfaces.nsILoginInfo); +var nsLoginInfo = new SpecialPowers.wrap(SpecialPowers.Components).Constructor("@mozilla.org/login-manager/loginInfo;1", SpecialPowers.Ci.nsILoginInfo); ok(nsLoginInfo != null, "nsLoginInfo constructor"); // pwlogin1 uses a unique formSubmitURL, to check forms where no other logins @@ -207,7 +207,6 @@ function startTest() { checkUnmodifiedForm(12); checkUnmodifiedForm(13); - netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); pwmgr.removeLogin(pwlogin2); SimpleTest.finish(); } diff --git a/toolkit/components/passwordmgr/test/test_bug_227640.html b/toolkit/components/passwordmgr/test/test_bug_227640.html index 7721823cfe19..f69c2cef6c63 100644 --- a/toolkit/components/passwordmgr/test/test_bug_227640.html +++ b/toolkit/components/passwordmgr/test/test_bug_227640.html @@ -231,8 +231,6 @@ function getFormSubmitButton(formNum) { // Counts the number of logins currently stored by password manager. function countLogins() { - netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); - var logins = pwmgr.getAllLogins(); return logins.length; diff --git a/toolkit/components/passwordmgr/test/test_bug_627616.html b/toolkit/components/passwordmgr/test/test_bug_627616.html index 258a6dcbf39f..839cc107b652 100644 --- a/toolkit/components/passwordmgr/test/test_bug_627616.html +++ b/toolkit/components/passwordmgr/test/test_bug_627616.html @@ -22,7 +22,7 @@ const interfaces = [Ci.nsIProtocolProxyCallback, Ci.nsISupports]; if (!interfaces.some( function(v) { return iid.equals(v) } )) - throw Components.results.NS_ERROR_NO_INTERFACE; + throw SpecialPowers.Cr.NS_ERROR_NO_INTERFACE; return this; }, diff --git a/toolkit/components/passwordmgr/test/test_master_password.html b/toolkit/components/passwordmgr/test/test_master_password.html index 266b4bcfa86c..cce6a377b05b 100644 --- a/toolkit/components/passwordmgr/test/test_master_password.html +++ b/toolkit/components/passwordmgr/test/test_master_password.html @@ -18,7 +18,7 @@ var pwmgr = SpecialPowers.Cc["@mozilla.org/login-manager;1"] var pwcrypt = SpecialPowers.Cc["@mozilla.org/login-manager/crypto/SDR;1"] .getService(Ci.nsILoginManagerCrypto); -var nsLoginInfo = new Components.Constructor("@mozilla.org/login-manager/loginInfo;1", Ci.nsILoginInfo); +var nsLoginInfo = new SpecialPowers.wrap(SpecialPowers.Components).Constructor("@mozilla.org/login-manager/loginInfo;1", Ci.nsILoginInfo); var exampleCom = "http://example.com/tests/toolkit/components/passwordmgr/test/"; var exampleOrg = "http://example.org/tests/toolkit/components/passwordmgr/test/"; @@ -57,7 +57,6 @@ var iframe2 = document.getElementById("iframe2"); * timer is a one-shot). */ function handleDialog(doc, testNum) { - netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); ok(true, "handleDialog running for test " + testNum); var clickOK = true; @@ -115,8 +114,6 @@ function handleDialog(doc, testNum) { function startTest1() { - netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); - ok(pwcrypt.isLoggedIn, "should be initially logged in (no MP)"); enableMasterPassword(); ok(!pwcrypt.isLoggedIn, "should be logged out after setting MP"); diff --git a/toolkit/components/passwordmgr/test/test_master_password_cleanup.html b/toolkit/components/passwordmgr/test/test_master_password_cleanup.html index 34a01699ab43..5d2276ea0367 100644 --- a/toolkit/components/passwordmgr/test/test_master_password_cleanup.html +++ b/toolkit/components/passwordmgr/test/test_master_password_cleanup.html @@ -39,9 +39,8 @@ function cleanup() { ok(true, "done."); } -netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); -const Cc = Components.classes; -const Ci = Components.interfaces; +const Cc = SpecialPowers.Cc; +const Ci = SpecialPowers.Ci; cleanup(); diff --git a/toolkit/components/passwordmgr/test/test_notifications.html b/toolkit/components/passwordmgr/test/test_notifications.html index 0a30a2d36e7d..d3c4d6081591 100644 --- a/toolkit/components/passwordmgr/test/test_notifications.html +++ b/toolkit/components/passwordmgr/test/test_notifications.html @@ -55,8 +55,6 @@ var subtests = [ var ignoreLoad = false; function handleLoad(aEvent) { - netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); - // ignore every other load event ... We get one for loading the subtest (which // we want to ignore), and another when the subtest's form submits itself // (which we want to handle, to start the next test). @@ -151,7 +149,7 @@ function checkTest() { // existing loging that was submitted for this form. var logins = pwmgr.getAllLogins(); is(logins.length, 1, "Should only have 1 login"); - ok(logins[0] instanceof Ci.nsILoginMetaInfo, "metainfo QI"); + ok(SpecialPowers.call_Instanceof(logins[0], Ci.nsILoginMetaInfo), "metainfo QI"); is(logins[0].timesUsed, 2, "check .timesUsed for existing login submission"); ok(logins[0].timeLastUsed > logins[0].timeCreated, "timeLastUsed bumped"); ok(logins[0].timeCreated == logins[0].timePasswordChanged, "timeChanged not updated"); @@ -302,7 +300,7 @@ function checkTest() { // the login being changed with this form. var logins = pwmgr.getAllLogins(); is(logins.length, 1, "Should only have 1 login"); - ok(logins[0] instanceof Ci.nsILoginMetaInfo, "metainfo QI"); + ok(SpecialPowers.call_Instanceof(logins[0], Ci.nsILoginMetaInfo), "metainfo QI"); is(logins[0].timesUsed, 2, "check .timesUsed incremented on change"); ok(logins[0].timeCreated < logins[0].timeLastUsed, "timeLastUsed bumped"); ok(logins[0].timeLastUsed == logins[0].timePasswordChanged, "timeUsed == timeChanged"); @@ -388,11 +386,8 @@ function checkTest() { // * existing login test, form has different password --> change password, no save prompt } - -netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); - -const Ci = Components.interfaces; -const Cc = Components.classes; +const Ci = SpecialPowers.Ci; +const Cc = SpecialPowers.Cc; ok(Ci != null, "Access Ci"); ok(Cc != null, "Access Cc"); @@ -408,7 +403,7 @@ ok(prefs != null, "Access prefs"); prefs = prefs.getBranch("signon."); ok(prefs != null, "Access pref branch"); -var nsLoginInfo = new Components.Constructor("@mozilla.org/login-manager/loginInfo;1", +var nsLoginInfo = new SpecialPowers.wrap(SpecialPowers.Components).Constructor("@mozilla.org/login-manager/loginInfo;1", Ci.nsILoginInfo, "init"); var login1 = new nsLoginInfo("http://mochi.test:8888", "http://mochi.test:8888", null, "notifyu1", "notifyp1", "user", "pass"); diff --git a/toolkit/components/passwordmgr/test/test_privbrowsing_perwindowpb.html b/toolkit/components/passwordmgr/test/test_privbrowsing_perwindowpb.html index 24c894da57bf..0449e153dae7 100644 --- a/toolkit/components/passwordmgr/test/test_privbrowsing_perwindowpb.html +++ b/toolkit/components/passwordmgr/test/test_privbrowsing_perwindowpb.html @@ -20,9 +20,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=248970 /** Test for Bug 248970 **/ // based on test_notifications.html -const Ci = Components.interfaces; -const Cc = Components.classes; -const Cr = Components.results; +const Ci = SpecialPowers.Ci; +const Cc = SpecialPowers.Cc; +const Cr = SpecialPowers.Cr; var testpath = "/tests/toolkit/components/passwordmgr/test/"; var prefix = "http://test2.example.com" + testpath; @@ -249,7 +249,7 @@ ok(pwmgr != null, "Access pwmgr"); var url = "http://test2.example.com"; is(pwmgr.countLogins(url, "", null), 0, "No logins should be stored for " + url); -var nsLoginInfo = new Components.Constructor("@mozilla.org/login-manager/loginInfo;1", +var nsLoginInfo = new SpecialPowers.wrap(SpecialPowers.Components).Constructor("@mozilla.org/login-manager/loginInfo;1", Ci.nsILoginInfo, "init"); var login = new nsLoginInfo(url, url, null, "notifyu1", "notifyp1", "user", "pass"); diff --git a/toolkit/components/passwordmgr/test/test_xhr.html b/toolkit/components/passwordmgr/test/test_xhr.html index 9e1a94687132..b4a68cd78389 100644 --- a/toolkit/components/passwordmgr/test/test_xhr.html +++ b/toolkit/components/passwordmgr/test/test_xhr.html @@ -19,7 +19,6 @@ Login Manager test: XHR prompt