From 5a3a792f4d700bbad7af833be26c673d499e67ad Mon Sep 17 00:00:00 2001 From: Neil Deakin Date: Fri, 19 Sep 2014 16:44:08 -0400 Subject: [PATCH 001/114] Bug 1067993, TabParent's Deactivate isn't called when window is lowered, r=smaug --- dom/base/nsFocusManager.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dom/base/nsFocusManager.cpp b/dom/base/nsFocusManager.cpp index 410354ee2c03..fae36762677b 100644 --- a/dom/base/nsFocusManager.cpp +++ b/dom/base/nsFocusManager.cpp @@ -1612,12 +1612,12 @@ nsFocusManager::Blur(nsPIDOMWindow* aWindowToClear, widget->SetFocus(false); } } + } // if the object being blurred is a remote browser, deactivate remote content - if (TabParent* remote = TabParent::GetFrom(content)) { - remote->Deactivate(); - LOGFOCUS(("Remote browser deactivated")); - } + if (TabParent* remote = TabParent::GetFrom(content)) { + remote->Deactivate(); + LOGFOCUS(("Remote browser deactivated")); } } From 70797271f3924e86a71c276d21e5deee5b845e33 Mon Sep 17 00:00:00 2001 From: Aaron Klotz Date: Fri, 19 Sep 2014 14:49:34 -0600 Subject: [PATCH 002/114] Bug 1070042: Fix --debugger parameter in reftest/crashtest; r=ted --- build/automation.py.in | 6 +++--- layout/tools/reftest/mach_commands.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/automation.py.in b/build/automation.py.in index bccf2d253ccb..f5f81b2c26ec 100644 --- a/build/automation.py.in +++ b/build/automation.py.in @@ -755,9 +755,9 @@ class Automation(object): args = [] if debuggerInfo: - args.extend(debuggerInfo["args"]) + args.extend(debuggerInfo.args) args.append(cmd) - cmd = os.path.abspath(debuggerInfo["path"]) + cmd = os.path.abspath(debuggerInfo.path) if self.IS_MAC: args.append("-foreground") @@ -850,7 +850,7 @@ class Automation(object): cmd, args = self.buildCommandLine(app, debuggerInfo, profileDir, testURL, extraArgs) startTime = datetime.now() - if debuggerInfo and debuggerInfo["interactive"]: + if debuggerInfo and debuggerInfo.interactive: # If an interactive debugger is attached, don't redirect output, # don't use timeouts, and don't capture ctrl-c. timeout = None diff --git a/layout/tools/reftest/mach_commands.py b/layout/tools/reftest/mach_commands.py index 1db29b89d8ea..d0233b467821 100644 --- a/layout/tools/reftest/mach_commands.py +++ b/layout/tools/reftest/mach_commands.py @@ -255,7 +255,7 @@ class ReftestRunner(MozbuildObject): pass_thru = False if debugger: - extra_args.append('--debugger=%s' % debugger) + extra_args.append('--debugger=\'%s\'' % debugger) pass_thru = True if debugger_args: # Use _make_shell_string (which quotes) so that we From bb7cc33cc14552d2c10edf3677ce6817a5d4805c Mon Sep 17 00:00:00 2001 From: Andrew McCreight Date: Fri, 19 Sep 2014 14:07:25 -0700 Subject: [PATCH 003/114] Bug 1067505 - Make nsCategoryManager into a strong memory reporter. r=njn The nsCategoryManager singleton lives until very late in shutdown, so the unregister always fails. It is okay to make it a strong reporter because it will always outlive the memory reporter manager anyways. --- xpcom/components/nsCategoryManager.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/xpcom/components/nsCategoryManager.cpp b/xpcom/components/nsCategoryManager.cpp index 49674f3ee5ef..0f641a236b5b 100644 --- a/xpcom/components/nsCategoryManager.cpp +++ b/xpcom/components/nsCategoryManager.cpp @@ -469,13 +469,11 @@ nsCategoryManager::nsCategoryManager() void nsCategoryManager::InitMemoryReporter() { - RegisterWeakMemoryReporter(this); + RegisterStrongMemoryReporter(this); } nsCategoryManager::~nsCategoryManager() { - UnregisterWeakMemoryReporter(this); - // the hashtable contains entries that must be deleted before the arena is // destroyed, or else you will have PRLocks undestroyed and other Really // Bad Stuff (TM) From 233163862b7137d6ec769bb44aaaf77c80c2f88d Mon Sep 17 00:00:00 2001 From: Randell Jesup Date: Fri, 19 Sep 2014 17:24:28 -0400 Subject: [PATCH 004/114] Bug 1062876: refactor window iteration code for MediaManager r=jib --- dom/media/MediaManager.cpp | 204 +++++++++++++++++++------------------ dom/media/MediaManager.h | 14 ++- 2 files changed, 116 insertions(+), 102 deletions(-) diff --git a/dom/media/MediaManager.cpp b/dom/media/MediaManager.cpp index d90ab82b6bd2..9dea58d704a3 100644 --- a/dom/media/MediaManager.cpp +++ b/dom/media/MediaManager.cpp @@ -1893,10 +1893,34 @@ MediaManager::GetBackend(uint64_t aWindowId) return mBackend; } +static void +StopSharingCallback(MediaManager *aThis, + uint64_t aWindowID, + StreamListeners *aListeners, + void *aData) +{ + if (aListeners) { + auto length = aListeners->Length(); + for (size_t i = 0; i < length; ++i) { + GetUserMediaCallbackMediaStreamListener *listener = aListeners->ElementAt(i); + + if (listener->Stream()) { // aka HasBeenActivate()ed + listener->Invalidate(); + } + listener->Remove(); + listener->StopScreenWindowSharing(); + } + aListeners->Clear(); + aThis->RemoveWindowID(aWindowID); + } +} + + void MediaManager::OnNavigation(uint64_t aWindowID) { NS_ASSERTION(NS_IsMainThread(), "OnNavigation called off main thread"); + LOG(("OnNavigation for %llu", aWindowID)); // Invalidate this window. The runnables check this value before making // a call to content. @@ -1911,24 +1935,13 @@ MediaManager::OnNavigation(uint64_t aWindowID) // This is safe since we're on main-thread, and the windowlist can only // be added to from the main-thread - StreamListeners* listeners = GetWindowListeners(aWindowID); - if (!listeners) { - return; + nsPIDOMWindow *window = static_cast + (nsGlobalWindow::GetInnerWindowWithId(aWindowID)); + if (window) { + IterateWindowListeners(window, StopSharingCallback, nullptr); + } else { + RemoveWindowID(aWindowID); } - - uint32_t length = listeners->Length(); - for (uint32_t i = 0; i < length; i++) { - nsRefPtr listener = - listeners->ElementAt(i); - if (listener->Stream()) { // aka HasBeenActivate()ed - listener->Invalidate(); - } - listener->Remove(); - } - listeners->Clear(); - - RemoveWindowID(aWindowID); - // listeners has been deleted } void @@ -2213,92 +2226,93 @@ MediaManager::GetActiveMediaCaptureWindows(nsISupportsArray **aArray) return NS_OK; } +// XXX flags might be better... +struct CaptureWindowStateData { + bool *mVideo; + bool *mAudio; + bool *mScreenShare; + bool *mWindowShare; + bool *mAppShare; +}; + +static void +CaptureWindowStateCallback(MediaManager *aThis, + uint64_t aWindowID, + StreamListeners *aListeners, + void *aData) +{ + struct CaptureWindowStateData *data = (struct CaptureWindowStateData *) aData; + + if (aListeners) { + auto length = aListeners->Length(); + for (size_t i = 0; i < length; ++i) { + GetUserMediaCallbackMediaStreamListener *listener = aListeners->ElementAt(i); + + if (listener->CapturingVideo()) { + *data->mVideo = true; + } + if (listener->CapturingAudio()) { + *data->mAudio = true; + } + if (listener->CapturingScreen()) { + *data->mScreenShare = true; + } + if (listener->CapturingWindow()) { + *data->mWindowShare = true; + } + if (listener->CapturingApplication()) { + *data->mAppShare = true; + } + } + } +} + + NS_IMETHODIMP MediaManager::MediaCaptureWindowState(nsIDOMWindow* aWindow, bool* aVideo, bool* aAudio, bool *aScreenShare, bool* aWindowShare, bool *aAppShare) { NS_ASSERTION(NS_IsMainThread(), "Only call on main thread"); + struct CaptureWindowStateData data; + data.mVideo = aVideo; + data.mAudio = aAudio; + data.mScreenShare = aScreenShare; + data.mWindowShare = aWindowShare; + data.mAppShare = aAppShare; + *aVideo = false; *aAudio = false; *aScreenShare = false; *aWindowShare = false; *aAppShare = false; - nsresult rv = MediaCaptureWindowStateInternal(aWindow, aVideo, aAudio, aScreenShare, aWindowShare, aAppShare); -#ifdef DEBUG nsCOMPtr piWin = do_QueryInterface(aWindow); + if (piWin) { + IterateWindowListeners(piWin, CaptureWindowStateCallback, &data); + } +#ifdef DEBUG LOG(("%s: window %lld capturing %s %s %s %s %s", __FUNCTION__, piWin ? piWin->WindowID() : -1, *aVideo ? "video" : "", *aAudio ? "audio" : "", *aScreenShare ? "screenshare" : "", *aWindowShare ? "windowshare" : "", *aAppShare ? "appshare" : "")); #endif - return rv; -} - -nsresult -MediaManager::MediaCaptureWindowStateInternal(nsIDOMWindow* aWindow, bool* aVideo, - bool* aAudio, bool *aScreenShare, - bool* aWindowShare, bool *aAppShare) -{ - // We need to return the union of all streams in all innerwindows that - // correspond to that outerwindow. - - // Iterate the docshell tree to find all the child windows, find - // all the listeners for each one, get the booleans, and merge the - // results. - nsCOMPtr piWin = do_QueryInterface(aWindow); - if (piWin) { - if (piWin->IsInnerWindow() || piWin->GetCurrentInnerWindow()) { - uint64_t windowID; - if (piWin->IsInnerWindow()) { - windowID = piWin->WindowID(); - } else { - windowID = piWin->GetCurrentInnerWindow()->WindowID(); - } - StreamListeners* listeners = GetActiveWindows()->Get(windowID); - if (listeners) { - uint32_t length = listeners->Length(); - for (uint32_t i = 0; i < length; ++i) { - nsRefPtr listener = - listeners->ElementAt(i); - if (listener->CapturingVideo()) { - *aVideo = true; - } - if (listener->CapturingAudio()) { - *aAudio = true; - } - if (listener->CapturingScreen()) { - *aScreenShare = true; - } - if (listener->CapturingWindow()) { - *aWindowShare = true; - } - if (listener->CapturingApplication()) { - *aAppShare = true; - } - } - } - } - - // iterate any children of *this* window (iframes, etc) - nsCOMPtr docShell = piWin->GetDocShell(); - if (docShell) { - int32_t i, count; - docShell->GetChildCount(&count); - for (i = 0; i < count; ++i) { - nsCOMPtr item; - docShell->GetChildAt(i, getter_AddRefs(item)); - nsCOMPtr win = item ? item->GetWindow() : nullptr; - - MediaCaptureWindowStateInternal(win, aVideo, aAudio, aScreenShare, aWindowShare, aAppShare); - } - } - } return NS_OK; } -// XXX abstract out the iteration over all children and provide a function pointer and data ptr +static void +StopScreensharingCallback(MediaManager *aThis, + uint64_t aWindowID, + StreamListeners *aListeners, + void *aData) +{ + if (aListeners) { + auto length = aListeners->Length(); + for (size_t i = 0; i < length; ++i) { + aListeners->ElementAt(i)->StopScreenWindowSharing(); + } + } +} void MediaManager::StopScreensharing(uint64_t aWindowID) @@ -2311,18 +2325,17 @@ MediaManager::StopScreensharing(uint64_t aWindowID) if (!window) { return; } - StopScreensharing(window); + IterateWindowListeners(window, &StopScreensharingCallback, nullptr); } +// lets us do all sorts of things to the listeners void -MediaManager::StopScreensharing(nsPIDOMWindow *aWindow) +MediaManager::IterateWindowListeners(nsPIDOMWindow *aWindow, + WindowListenerCallback aCallback, + void *aData) { - // We need to stop window/screensharing for all streams in all innerwindows that - // correspond to that outerwindow. - - // Iterate the docshell tree to find all the child windows, find - // all the listeners for each one, and tell them to stop - // window/screensharing + // Iterate the docshell tree to find all the child windows, and for each + // invoke the callback nsCOMPtr piWin = do_QueryInterface(aWindow); if (piWin) { if (piWin->IsInnerWindow() || piWin->GetCurrentInnerWindow()) { @@ -2333,12 +2346,8 @@ MediaManager::StopScreensharing(nsPIDOMWindow *aWindow) windowID = piWin->GetCurrentInnerWindow()->WindowID(); } StreamListeners* listeners = GetActiveWindows()->Get(windowID); - if (listeners) { - uint32_t length = listeners->Length(); - for (uint32_t i = 0; i < length; ++i) { - listeners->ElementAt(i)->StopScreenWindowSharing(); - } - } + // pass listeners so it can modify/delete the list + (*aCallback)(this, windowID, listeners, aData); } // iterate any children of *this* window (iframes, etc) @@ -2352,13 +2361,14 @@ MediaManager::StopScreensharing(nsPIDOMWindow *aWindow) nsCOMPtr win = item ? item->GetWindow() : nullptr; if (win) { - StopScreensharing(win); + IterateWindowListeners(win, aCallback, aData); } } } } } + void MediaManager::StopMediaStreams() { diff --git a/dom/media/MediaManager.h b/dom/media/MediaManager.h index 250c4cb53ea9..f596a72afba6 100644 --- a/dom/media/MediaManager.h +++ b/dom/media/MediaManager.h @@ -528,6 +528,12 @@ public: MediaEngineAudioSource* GetSource(); }; +// we could add MediaManager if needed +typedef void (*WindowListenerCallback)(MediaManager *aThis, + uint64_t aWindowID, + StreamListeners *aListeners, + void *aData); + class MediaManager MOZ_FINAL : public nsIMediaManagerService, public nsIObserver { @@ -600,12 +606,10 @@ private: ~MediaManager() {} - nsresult MediaCaptureWindowStateInternal(nsIDOMWindow* aWindow, bool* aVideo, - bool* aAudio, bool *aScreenShare, - bool* aWindowShare, bool *aAppShare); - void StopScreensharing(uint64_t aWindowID); - void StopScreensharing(nsPIDOMWindow *aWindow); + void IterateWindowListeners(nsPIDOMWindow *aWindow, + WindowListenerCallback aCallback, + void *aData); void StopMediaStreams(); From 9b9d1e1c9f17fa94cc3ab9989e66d132be2a77be Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Fri, 19 Sep 2014 14:53:28 -0700 Subject: [PATCH 005/114] Bug 1060200 (Part 1) - Add support for RasterImage surfaces to SurfaceCache. r=dholbert --- image/src/SurfaceCache.h | 51 ++++++++++++++++++++++++++++++--------- image/src/VectorImage.cpp | 10 +++++--- 2 files changed, 45 insertions(+), 16 deletions(-) diff --git a/image/src/SurfaceCache.h b/image/src/SurfaceCache.h index 3d7632465fd9..442583f9de3f 100644 --- a/image/src/SurfaceCache.h +++ b/image/src/SurfaceCache.h @@ -36,23 +36,14 @@ typedef Image* ImageKey; * SurfaceKey contains the information we need to look up a specific cached * surface. Together with an ImageKey, this uniquely identifies the surface. * - * XXX(seth): Right now this is specialized to the needs of VectorImage. We'll - * generalize it in bug 919071. + * Callers should construct a SurfaceKey using the appropriate helper function + * for their image type - either RasterSurfaceKey or VectorSurfaceKey. */ class SurfaceKey { typedef gfx::IntSize IntSize; -public: - SurfaceKey(const IntSize& aSize, - const Maybe& aSVGContext, - const float aAnimationTime, - const uint32_t aFlags) - : mSize(aSize) - , mSVGContext(aSVGContext) - , mAnimationTime(aAnimationTime) - , mFlags(aFlags) - { } +public: bool operator==(const SurfaceKey& aOther) const { return aOther.mSize == mSize && @@ -72,16 +63,52 @@ public: IntSize Size() const { return mSize; } private: + SurfaceKey(const IntSize& aSize, + const Maybe& aSVGContext, + const float aAnimationTime, + const uint32_t aFlags) + : mSize(aSize) + , mSVGContext(aSVGContext) + , mAnimationTime(aAnimationTime) + , mFlags(aFlags) + { } + static uint32_t HashSIC(const SVGImageContext& aSIC) { return aSIC.Hash(); } + friend SurfaceKey RasterSurfaceKey(const IntSize&, const uint32_t); + friend SurfaceKey VectorSurfaceKey(const IntSize&, + const Maybe&, + const float); + IntSize mSize; Maybe mSVGContext; float mAnimationTime; uint32_t mFlags; }; +inline SurfaceKey +RasterSurfaceKey(const gfx::IntSize& aSize, + const uint32_t aFlags) +{ + // We don't care about aAnimationTime for RasterImage because it's not + // currently possible to store anything but the first frame in the + // SurfaceCache. + return SurfaceKey(aSize, Nothing(), 0.0f, aFlags); +} + +inline SurfaceKey +VectorSurfaceKey(const gfx::IntSize& aSize, + const Maybe& aSVGContext, + const float aAnimationTime) +{ + // We don't care about aFlags for VectorImage because none of the flags we + // have right now influence VectorImage's rendering. If we add a new flag that + // *does* affect how a VectorImage renders, we'll have to change this. + return SurfaceKey(aSize, aSVGContext, aAnimationTime, 0); +} + /** * SurfaceCache is an imagelib-global service that allows caching of temporary * surfaces. Surfaces expire from the cache automatically if they go too long diff --git a/image/src/VectorImage.cpp b/image/src/VectorImage.cpp index 279e87d6d811..94c6bcf60218 100644 --- a/image/src/VectorImage.cpp +++ b/image/src/VectorImage.cpp @@ -849,8 +849,9 @@ VectorImage::Draw(gfxContext* aContext, DrawableFrameRef frameRef = SurfaceCache::Lookup(ImageKey(this), - SurfaceKey(params.size, aSVGContext, - animTime, aFlags)); + VectorSurfaceKey(params.size, + params.svgContext, + params.animationTime)); // Draw. if (frameRef) { @@ -911,8 +912,9 @@ VectorImage::CreateSurfaceAndShow(const SVGDrawingParameters& aParams) // Attempt to cache the frame. SurfaceCache::Insert(frame, ImageKey(this), - SurfaceKey(aParams.size, aParams.svgContext, - aParams.animationTime, aParams.flags)); + VectorSurfaceKey(aParams.size, + aParams.svgContext, + aParams.animationTime)); // Draw. nsRefPtr drawable = From 721363b4e59a8b85e8ae292dfc24ce7bae59412e Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Fri, 19 Sep 2014 14:53:28 -0700 Subject: [PATCH 006/114] Bug 1060200 (Part 2) - Add SurfaceCache::RemoveIfPresent so invalid entries can be freed eagerly. r=dholbert --- image/src/SurfaceCache.cpp | 24 ++++++++++++++++++++++++ image/src/SurfaceCache.h | 12 ++++++++++++ 2 files changed, 36 insertions(+) diff --git a/image/src/SurfaceCache.cpp b/image/src/SurfaceCache.cpp index b4a557a820c2..bb22016e86fe 100644 --- a/image/src/SurfaceCache.cpp +++ b/image/src/SurfaceCache.cpp @@ -339,6 +339,20 @@ public: return ref; } + void RemoveIfPresent(const ImageKey aImageKey, + const SurfaceKey& aSurfaceKey) + { + nsRefPtr cache = GetImageCache(aImageKey); + if (!cache) + return; // No cached surfaces for this image. + + nsRefPtr surface = cache->Lookup(aSurfaceKey); + if (!surface) + return; // Lookup in the per-image cache missed. + + Remove(surface); + } + bool CanHold(const Cost aCost) const { return aCost <= mMaxCost; @@ -537,6 +551,16 @@ SurfaceCache::CanHold(const IntSize& aSize) return sInstance->CanHold(cost); } +/* static */ void +SurfaceCache::RemoveIfPresent(const ImageKey aImageKey, + const SurfaceKey& aSurfaceKey) +{ + MOZ_ASSERT(sInstance, "Should be initialized"); + MOZ_ASSERT(NS_IsMainThread()); + + return sInstance->RemoveIfPresent(aImageKey, aSurfaceKey); +} + /* static */ void SurfaceCache::Discard(Image* aImageKey) { diff --git a/image/src/SurfaceCache.h b/image/src/SurfaceCache.h index 442583f9de3f..29231a97d901 100644 --- a/image/src/SurfaceCache.h +++ b/image/src/SurfaceCache.h @@ -183,6 +183,18 @@ struct SurfaceCache */ static bool CanHold(const IntSize& aSize); + /* + * Removes a surface from the cache, if it's present. + * + * Use this function to remove individual surfaces that have become invalid. + * Prefer Discard() or DiscardAll() when they're applicable, as they have much + * better performance than calling this function repeatedly. + * + * @param aImageKey Key data identifying which image the surface belongs to. + * @param aSurfaceKey Key data which uniquely identifies the requested surface. + */ + static void RemoveIfPresent(const ImageKey aImageKey, + const SurfaceKey& aSurfaceKey); /* * Evicts any cached surfaces associated with the given image from the cache. * This MUST be called, at a minimum, when the image is destroyed. If From 79a519affc18809cbccd62279e48f871f9cca6c2 Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Fri, 19 Sep 2014 14:53:29 -0700 Subject: [PATCH 007/114] Bug 1060200 (Part 3) - Handle SurfaceCache function calls after shutdown. r=dholbert --- image/src/SurfaceCache.cpp | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/image/src/SurfaceCache.cpp b/image/src/SurfaceCache.cpp index bb22016e86fe..ee90b6806a13 100644 --- a/image/src/SurfaceCache.cpp +++ b/image/src/SurfaceCache.cpp @@ -522,8 +522,10 @@ SurfaceCache::Shutdown() SurfaceCache::Lookup(const ImageKey aImageKey, const SurfaceKey& aSurfaceKey) { - MOZ_ASSERT(sInstance, "Should be initialized"); MOZ_ASSERT(NS_IsMainThread()); + if (!sInstance) { + return DrawableFrameRef(); + } return sInstance->Lookup(aImageKey, aSurfaceKey); } @@ -533,19 +535,21 @@ SurfaceCache::Insert(imgFrame* aSurface, const ImageKey aImageKey, const SurfaceKey& aSurfaceKey) { - MOZ_ASSERT(sInstance, "Should be initialized"); MOZ_ASSERT(NS_IsMainThread()); - - Cost cost = ComputeCost(aSurfaceKey.Size()); - return sInstance->Insert(aSurface, aSurfaceKey.Size(), cost, aImageKey, - aSurfaceKey); + if (sInstance) { + Cost cost = ComputeCost(aSurfaceKey.Size()); + sInstance->Insert(aSurface, aSurfaceKey.Size(), cost, aImageKey, + aSurfaceKey); + } } /* static */ bool SurfaceCache::CanHold(const IntSize& aSize) { - MOZ_ASSERT(sInstance, "Should be initialized"); MOZ_ASSERT(NS_IsMainThread()); + if (!sInstance) { + return false; + } Cost cost = ComputeCost(aSize); return sInstance->CanHold(cost); @@ -555,30 +559,28 @@ SurfaceCache::CanHold(const IntSize& aSize) SurfaceCache::RemoveIfPresent(const ImageKey aImageKey, const SurfaceKey& aSurfaceKey) { - MOZ_ASSERT(sInstance, "Should be initialized"); MOZ_ASSERT(NS_IsMainThread()); - - return sInstance->RemoveIfPresent(aImageKey, aSurfaceKey); + if (sInstance) { + sInstance->RemoveIfPresent(aImageKey, aSurfaceKey); + } } /* static */ void SurfaceCache::Discard(Image* aImageKey) { - MOZ_ASSERT(sInstance, "Should be initialized"); MOZ_ASSERT(NS_IsMainThread()); - - return sInstance->Discard(aImageKey); + if (sInstance) { + sInstance->Discard(aImageKey); + } } /* static */ void SurfaceCache::DiscardAll() { MOZ_ASSERT(NS_IsMainThread()); - if (sInstance) { sInstance->DiscardAll(); } - // nothing to discard } } // namespace image From e3b53953b56474ca0c188798364c42e9cb574b65 Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Fri, 19 Sep 2014 14:53:29 -0700 Subject: [PATCH 008/114] Bug 1060200 (Part 4) - Store HQ scaled frames in SurfaceCache and remove ScaleRequest and ScaleResult. r=tn --- image/src/RasterImage.cpp | 479 +++++++++----------- image/src/RasterImage.h | 60 +-- image/src/imgFrame.h | 1 + image/test/reftest/downscaling/reftest.list | 16 +- 4 files changed, 234 insertions(+), 322 deletions(-) diff --git a/image/src/RasterImage.cpp b/image/src/RasterImage.cpp index fe6f215df976..81b6c721d42b 100644 --- a/image/src/RasterImage.cpp +++ b/image/src/RasterImage.cpp @@ -24,6 +24,7 @@ #include "nsIThreadPool.h" #include "nsXPCOMCIDInternal.h" #include "nsIObserverService.h" +#include "SurfaceCache.h" #include "FrameAnimator.h" #include "nsPNGDecoder.h" @@ -67,6 +68,12 @@ using std::ceil; #define DECODE_FLAGS_MASK (imgIContainer::FLAG_DECODE_NO_PREMULTIPLY_ALPHA | imgIContainer::FLAG_DECODE_NO_COLORSPACE_CONVERSION) #define DECODE_FLAGS_DEFAULT 0 +static uint32_t +DecodeFlags(uint32_t aFlags) +{ + return aFlags & DECODE_FLAGS_MASK; +} + /* Accounting for compressed data */ #if defined(PR_LOGGING) static PRLogModuleInfo * @@ -184,185 +191,141 @@ DiscardingEnabled() return enabled; } -class ScaleRequest +class ScaleRunner : public nsRunnable { -public: - ScaleRequest(RasterImage* aImage, - const nsIntSize& aSize, - RawAccessFrameRef&& aSrcRef) - : weakImage(aImage) - , srcRef(Move(aSrcRef)) - , srcRect(srcRef->GetRect()) - , dstSize(aSize) - , done(false) - , stopped(false) + enum ScaleState { - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(!srcRef->GetIsPaletted()); + eNew, + eReady, + eFinish, + eFinishWithError + }; + +public: + ScaleRunner(RasterImage* aImage, + uint32_t aImageFlags, + const nsIntSize& aSize, + RawAccessFrameRef&& aSrcRef) + : mImage(aImage) + , mSrcRef(Move(aSrcRef)) + , mDstSize(aSize) + , mImageFlags(aImageFlags) + , mState(eNew) + { + MOZ_ASSERT(!mSrcRef->GetIsPaletted()); MOZ_ASSERT(aSize.width > 0 && aSize.height > 0); } - // This can only be called on the main thread. - bool AcquireResources() + bool Init() { MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(mState == eNew, "Calling Init() twice?"); - nsRefPtr image = weakImage.get(); - if (!image) { + // We'll need a destination frame. It's unconditionally ARGB32 because + // that's what the scaler outputs. + nsRefPtr tentativeDstFrame = new imgFrame(); + nsresult rv = + tentativeDstFrame->InitForDecoder(mDstSize, SurfaceFormat::B8G8R8A8); + if (NS_FAILED(rv)) { return false; } - if (!dstFrame) { - // We need to hold a lock onto the RasterImage object itself so that - // it (and its associated imgFrames) aren't marked as discardable. - if (NS_FAILED(image->LockImage())) { - return false; - } - - // We'll need a destination frame. It's unconditionally ARGB32 because - // that's what the scaler outputs. - nsRefPtr tentativeDstFrame = new imgFrame(); - nsresult rv = - tentativeDstFrame->InitForDecoder(dstSize, SurfaceFormat::B8G8R8A8); - if (NS_FAILED(rv)) { - return false; - } - - // We need a strong reference to the raw data for the destination frame. - // (We already got one for the source frame in the constructor.) - RawAccessFrameRef tentativeDstRef = tentativeDstFrame->RawAccessRef(); - if (!tentativeDstRef) { - return false; - } - - dstFrame = tentativeDstFrame.forget(); - dstRef = Move(tentativeDstRef); + // We need a strong reference to the raw data for the destination frame. + // (We already got one for the source frame in the constructor.) + RawAccessFrameRef tentativeDstRef = tentativeDstFrame->RawAccessRef(); + if (!tentativeDstRef) { + return false; } + // Everything worked, so commit to these objects and mark ourselves ready. + mDstRef = Move(tentativeDstRef); + mState = eReady; + + // Insert the new surface into the cache immediately. We need to do this so + // that we won't start multiple scaling jobs for the same size. + SurfaceCache::Insert(mDstRef.get(), ImageKey(mImage.get()), + RasterSurfaceKey(mDstSize.ToIntSize(), mImageFlags)); + return true; } - // This can only be called on the main thread. - void ReleaseResources() + NS_IMETHOD Run() MOZ_OVERRIDE { - MOZ_ASSERT(NS_IsMainThread()); - - nsRefPtr image = weakImage.get(); - if (image) { - image->UnlockImage(); - } - - if (dstFrame) { - dstFrame->SetOptimizable(); - dstFrame->SetDiscardable(); - } - - // Release everything except dstFrame, which we keep around for RasterImage - // to retrieve. - srcRef.reset(); - dstRef.reset(); - } - - // These values may only be modified on the main thread. - WeakPtr weakImage; - nsRefPtr dstFrame; - RawAccessFrameRef srcRef; - RawAccessFrameRef dstRef; - - // Below are the values that may be modified on the scaling thread. - nsIntRect srcRect; - nsIntSize dstSize; - bool done; - - // This boolean is accessed from both threads simultaneously without locking. - // That's safe because stopping a ScaleRequest is strictly an optimization; - // if we're not cache-coherent, at worst we'll do extra work. - bool stopped; -}; - -class DrawRunner : public nsRunnable -{ -public: - explicit DrawRunner(ScaleRequest* request) - : mScaleRequest(request) - {} - - NS_IMETHOD Run() - { - // Grab the weak image pointer before the request releases it. - nsRefPtr image = mScaleRequest->weakImage.get(); - - // ScaleWorker is finished with this request, so release everything that we - // don't need anymore. - mScaleRequest->ReleaseResources(); - - if (image) { - RasterImage::ScaleStatus status; - if (mScaleRequest->done) { - status = RasterImage::SCALE_DONE; - } else { - status = RasterImage::SCALE_INVALID; - } - - image->ScalingDone(mScaleRequest, status); - } - - return NS_OK; - } - -private: /* members */ - nsAutoPtr mScaleRequest; -}; - -class ScaleRunner : public nsRunnable -{ -public: - ScaleRunner(RasterImage* aImage, - const nsIntSize& aSize, - RawAccessFrameRef&& aSrcRef) - { - nsAutoPtr req(new ScaleRequest(aImage, aSize, Move(aSrcRef))); - if (!req->AcquireResources()) { - return; - } - - aImage->ScalingStart(req); - mScaleRequest = req; - } - - NS_IMETHOD Run() - { - ScaleRequest* req = mScaleRequest.get(); - - if (!req->stopped) { + if (mState == eReady) { // Collect information from the frames that we need to scale. - uint8_t* srcData = req->srcRef->GetImageData(); - uint8_t* dstData = req->dstRef->GetImageData(); - uint32_t srcStride = req->srcRef->GetImageBytesPerRow(); - uint32_t dstStride = req->dstRef->GetImageBytesPerRow(); - SurfaceFormat srcFormat = req->srcRef->GetFormat(); + uint8_t* srcData = mSrcRef->GetImageData(); + IntSize srcSize = mSrcRef->GetSize(); + uint32_t srcStride = mSrcRef->GetImageBytesPerRow(); + uint8_t* dstData = mDstRef->GetImageData(); + uint32_t dstStride = mDstRef->GetImageBytesPerRow(); + SurfaceFormat srcFormat = mSrcRef->GetFormat(); // Actually do the scaling. - req->done = - gfx::Scale(srcData, req->srcRect.width, req->srcRect.height, srcStride, - dstData, req->dstSize.width, req->dstSize.height, dstStride, + bool succeeded = + gfx::Scale(srcData, srcSize.width, srcSize.height, srcStride, + dstData, mDstSize.width, mDstSize.height, dstStride, srcFormat); - } else { - req->done = false; - } - // OK, we've got a new scaled image. Let's get the main thread to unlock and - // redraw it. - nsRefPtr runner = new DrawRunner(mScaleRequest.forget()); - NS_DispatchToMainThread(runner); + if (succeeded) { + // Mark the frame as complete and discardable. + mDstRef->ImageUpdated(mDstRef->GetRect()); + MOZ_ASSERT(mDstRef->ImageComplete(), + "Incomplete, but just updated the entire frame"); + if (DiscardingEnabled()) { + mDstRef->SetDiscardable(); + } + } + + // We need to send notifications and release our references on the main + // thread, so finish up there. + mState = succeeded ? eFinish : eFinishWithError; + NS_DispatchToMainThread(this); + } else if (mState == eFinish) { + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(mDstRef, "Should have a valid scaled frame"); + + // Notify, so observers can redraw. + nsRefPtr image = mImage.get(); + if (image) { + image->NotifyNewScaledFrame(); + } + + // We're done, so release everything. + mSrcRef.reset(); + mDstRef.reset(); + } else if (mState == eFinishWithError) { + MOZ_ASSERT(NS_IsMainThread()); + NS_WARNING("HQ scaling failed"); + + // Remove the frame from the cache since we know we don't need it. + SurfaceCache::RemoveIfPresent(ImageKey(mImage.get()), + RasterSurfaceKey(mDstSize.ToIntSize(), + mImageFlags)); + + // Release everything we're holding, too. + mSrcRef.reset(); + mDstRef.reset(); + } else { + // mState must be eNew, which is invalid in Run(). + MOZ_ASSERT(false, "Need to call Init() before dispatching"); + } return NS_OK; } - bool IsOK() const { return !!mScaleRequest; } - private: - nsAutoPtr mScaleRequest; + virtual ~ScaleRunner() + { + MOZ_ASSERT(!mSrcRef && !mDstRef, + "Should have released strong refs in Run()"); + } + + WeakPtr mImage; + RawAccessFrameRef mSrcRef; + RawAccessFrameRef mDstRef; + const nsIntSize mDstSize; + uint32_t mImageFlags; + ScaleState mState; }; /* static */ StaticRefPtr RasterImage::DecodePool::sSingleton; @@ -404,8 +367,7 @@ RasterImage::RasterImage(imgStatusTracker* aStatusTracker, mFinishing(false), mInUpdateImageContainer(false), mWantFullDecode(false), - mPendingError(false), - mScaleRequest(nullptr) + mPendingError(false) { mStatusTrackerInit = new imgStatusTrackerInit(this, aStatusTracker); @@ -453,6 +415,9 @@ RasterImage::~RasterImage() } } + // Release any HQ scaled frames from the surface cache. + SurfaceCache::Discard(this); + mAnim = nullptr; // Total statistics @@ -1069,13 +1034,7 @@ size_t RasterImage::SizeOfDecodedWithComputedFallbackIfHeap(gfxMemoryLocation aLocation, MallocSizeOf aMallocSizeOf) const { - size_t n = mFrameBlender.SizeOfDecodedWithComputedFallbackIfHeap(aLocation, aMallocSizeOf); - - if (mScaleResult.status == SCALE_DONE) { - n += mScaleResult.frame->SizeOfExcludingThisWithComputedFallbackIfHeap(aLocation, aMallocSizeOf); - } - - return n; + return mFrameBlender.SizeOfDecodedWithComputedFallbackIfHeap(aLocation, aMallocSizeOf); } size_t @@ -1942,10 +1901,6 @@ RasterImage::Discard(bool force) // Delete all the decoded frames mFrameBlender.Discard(); - // Clear our downscaled frame. - mScaleResult.status = SCALE_INVALID; - mScaleResult.frame = nullptr; - // Clear the last decoded multipart frame. mMultipartDecodedFrame = nullptr; @@ -2518,94 +2473,83 @@ RasterImage::SyncDecode() } bool -RasterImage::CanQualityScale(const gfx::Size& scale) +RasterImage::CanScale(GraphicsFilter aFilter, + const nsIntSize& aSize, + uint32_t aFlags) { - // If target size is 1:1 with original, don't scale. - if (scale.width == 1.0 && scale.height == 1.0) +#ifndef MOZ_ENABLE_SKIA + // The high-quality scaler requires Skia. + return false; +#else + // Check basic requirements: HQ downscaling is enabled, we're decoded, the + // flags allow us to do it, and a 'good' filter is being used. The flags may + // ask us not to scale because the caller isn't drawing to the window. If + // we're drawing to something else (e.g. a canvas) we usually have no way of + // updating what we've drawn, so HQ scaling is useless. + if (!gHQDownscaling || !mDecoded || + !(aFlags & imgIContainer::FLAG_HIGH_QUALITY_SCALING) || + aFilter != GraphicsFilter::FILTER_GOOD) { return false; - - // To save memory don't quality upscale images bigger than the limit. - if (scale.width > 1.0 || scale.height > 1.0) { - uint32_t scaled_size = static_cast(mSize.width * mSize.height * scale.width * scale.height); - if (scaled_size > gHQUpscalingMaxSize) - return false; } - return true; -} - -bool -RasterImage::CanScale(GraphicsFilter aFilter, gfx::Size aScale, uint32_t aFlags) -{ -// The high-quality scaler requires Skia. -#ifdef MOZ_ENABLE_SKIA // We don't use the scaler for animated or multipart images to avoid doing a // bunch of work on an image that just gets thrown away. - // We only use the scaler when drawing to the window because, if we're not - // drawing to a window (eg a canvas), updates to that image will be ignored. - if (gHQDownscaling && aFilter == GraphicsFilter::FILTER_GOOD && - !mAnim && mDecoded && !mMultipart && CanQualityScale(aScale) && - (aFlags & imgIContainer::FLAG_HIGH_QUALITY_SCALING)) { - gfxFloat factor = gHQDownscalingMinFactor / 1000.0; - - return (aScale.width < factor || aScale.height < factor); + if (mAnim || mMultipart) { + return false; } -#endif - return false; -} + // If target size is 1:1 with original, don't scale. + if (aSize == mSize) { + return false; + } -void -RasterImage::ScalingStart(ScaleRequest* request) -{ - MOZ_ASSERT(request); - mScaleResult.scaledSize = request->dstSize; - mScaleResult.status = SCALE_PENDING; - mScaleRequest = request; -} - -void -RasterImage::ScalingDone(ScaleRequest* request, ScaleStatus status) -{ - MOZ_ASSERT(status == SCALE_DONE || status == SCALE_INVALID); - MOZ_ASSERT(request); - - if (status == SCALE_DONE) { - MOZ_ASSERT(request->done); - - mScaleResult.status = SCALE_DONE; - mScaleResult.frame = request->dstFrame.forget(); - mScaleResult.scaledSize = request->dstSize; - - mScaleResult.frame->ImageUpdated(mScaleResult.frame->GetRect()); - - if (mStatusTracker) { - mStatusTracker->FrameChanged(&request->srcRect); + // To save memory, don't quality upscale images bigger than the limit. + if (aSize.width > mSize.width || aSize.height > mSize.height) { + uint32_t scaledSize = static_cast(aSize.width * aSize.height); + if (scaledSize > gHQUpscalingMaxSize) { + return false; } - } else { - mScaleResult.status = SCALE_INVALID; - mScaleResult.frame = nullptr; } - // If we were waiting for this scale to come through, forget the scale - // request. Otherwise, we still have a scale outstanding that it's possible - // for us to (want to) stop. - if (mScaleRequest == request) { - mScaleRequest = nullptr; + // There's no point in scaling if we can't store the result. + if (!SurfaceCache::CanHold(aSize.ToIntSize())) { + return false; + } + + // XXX(seth): It's not clear what this check buys us over gHQUpscalingMaxSize. + // The default value of this pref is 1000, which means that we never upscale. + // If that's all it's getting us, I'd rather we just forbid that explicitly. + gfx::Size scale(double(aSize.width) / mSize.width, + double(aSize.height) / mSize.height); + gfxFloat minFactor = gHQDownscalingMinFactor / 1000.0; + return (scale.width < minFactor || scale.height < minFactor); +#endif +} + +void +RasterImage::NotifyNewScaledFrame() +{ + if (mStatusTracker) { + // Send an invalidation so observers will repaint and can take advantage of + // the new scaled frame if possible. + // XXX(seth): Why does FrameChanged take a pointer and not a reference? + nsIntRect invalidationRect(0, 0, mSize.width, mSize.height); + mStatusTracker->FrameChanged(&invalidationRect); } } void -RasterImage::RequestScale(imgFrame* aFrame, nsIntSize aSize) +RasterImage::RequestScale(imgFrame* aFrame, + uint32_t aFlags, + const nsIntSize& aSize) { - // We can't store more than one scaled version of an image right now, so if - // there's more than one instance of this image, bail. - if (mLockCount != 1) { + // We don't scale frames which aren't fully decoded. + if (!aFrame->ImageComplete()) { return; } - // We don't scale frames which aren't fully decoded. - if (!aFrame->ImageComplete()) { + // We can't scale frames that need padding or are single pixel. + if (aFrame->NeedsPadding() || aFrame->IsSinglePixel()) { return; } @@ -2615,13 +2559,9 @@ RasterImage::RequestScale(imgFrame* aFrame, nsIntSize aSize) return; } - // If we have an outstanding request, signal it to stop (if it can). - if (mScaleRequest) { - mScaleRequest->stopped = true; - } - - nsRefPtr runner = new ScaleRunner(this, aSize, Move(frameRef)); - if (runner->IsOK()) { + nsRefPtr runner = + new ScaleRunner(this, DecodeFlags(aFlags), aSize, Move(frameRef)); + if (runner->Init()) { if (!sScaleWorkerThread) { NS_NewNamedThread("Image Scaler", getter_AddRefs(sScaleWorkerThread)); ClearOnShutdown(&sScaleWorkerThread); @@ -2640,24 +2580,20 @@ RasterImage::DrawWithPreDownscaleIfNeeded(DrawableFrameRef&& aFrameRef, uint32_t aFlags) { DrawableFrameRef frameRef; - gfx::Size scale(double(aSize.width) / mSize.width, - double(aSize.height) / mSize.height); - if (CanScale(aFilter, scale, aFlags) && !aFrameRef->IsSinglePixel()) { - // FIXME: Current implementation doesn't support pre-downscale - // mechanism for multiple sizes from same src, since we cache - // pre-downscaled frame only for the latest requested scale. - // The solution is to cache more than one scaled image frame - // for each RasterImage. - if (mScaleResult.status == SCALE_DONE && mScaleResult.scaledSize == aSize) { - frameRef = mScaleResult.frame->DrawableRef(); + if (CanScale(aFilter, aSize, aFlags)) { + frameRef = + SurfaceCache::Lookup(ImageKey(this), + RasterSurfaceKey(aSize.ToIntSize(), + DecodeFlags(aFlags))); + if (!frameRef) { + // We either didn't have a matching scaled frame or the OS threw it away. + // Request a new one so we'll be ready next time. For now, we'll fall back + // to aFrameRef below. + RequestScale(aFrameRef.get(), aFlags, aSize); } - if (!frameRef && - (mScaleResult.status != SCALE_PENDING || mScaleResult.scaledSize != aSize)) { - // We either didn't have a complete scaled frame, it didn't match, or the - // OS threw it away. Fall back to aFrame, and request a new scaled frame - // if we're not already working on the one we need. - RequestScale(aFrameRef.get(), aSize); + if (frameRef && !frameRef->ImageComplete()) { + frameRef.reset(); // We're still scaling, so we can't use this yet. } } @@ -2671,6 +2607,8 @@ RasterImage::DrawWithPreDownscaleIfNeeded(DrawableFrameRef&& aFrameRef, // adjust the drawing parameters accordingly. nsIntRect finalFrameRect = frameRef->GetRect(); if (finalFrameRect.Size() != aSize) { + gfx::Size scale(double(aSize.width) / mSize.width, + double(aSize.height) / mSize.height); aContext->Multiply(gfxMatrix::Scaling(scale.width, scale.height)); region.Scale(1.0 / scale.width, 1.0 / scale.height); } @@ -2678,9 +2616,6 @@ RasterImage::DrawWithPreDownscaleIfNeeded(DrawableFrameRef&& aFrameRef, // We can only use padding if we're using the original |aFrameRef|, unscaled. // (If so, we moved it into |frameRef|, so |aFrameRef| is empty.) Because of // this restriction, we don't scale frames that require padding. - // XXX(seth): We actually do scale such frames right now though, if a single - // frame of a non-animated image requires padding. We'll fix that in bug - // 1060200, because dependencies between bugs make it hard to fix here. nsIntMargin padding(0, 0, 0, 0); if (!aFrameRef) { padding = nsIntMargin(finalFrameRect.y, @@ -3680,22 +3615,22 @@ RasterImage::OptimalImageSizeForDest(const gfxSize& aDest, uint32_t aWhichFrame, } nsIntSize destSize(ceil(aDest.width), ceil(aDest.height)); - gfx::Size scale(double(destSize.width) / mSize.width, - double(destSize.height) / mSize.height); - if (CanScale(aFilter, scale, aFlags)) { - if (mScaleResult.scaledSize == destSize) { - if (mScaleResult.status == SCALE_DONE) { + if (CanScale(aFilter, destSize, aFlags)) { + DrawableFrameRef frameRef = + SurfaceCache::Lookup(ImageKey(this), + RasterSurfaceKey(destSize.ToIntSize(), + DecodeFlags(aFlags))); + + if (frameRef && frameRef->ImageComplete()) { return destSize; // We have an existing HQ scale for this size. - } else if (mScaleResult.status == SCALE_PENDING) { - return mSize; // We're waiting for exactly this result. - } } - - // If there's only one instance of this image on this page, ask for a scale. - DrawableFrameRef frameRef = GetFrame(GetRequestedFrameIndex(aWhichFrame)); - if (frameRef) { - RequestScale(frameRef.get(), destSize); + if (!frameRef) { + // We could HQ scale to this size, but we haven't. Request a scale now. + frameRef = GetFrame(GetRequestedFrameIndex(aWhichFrame)); + if (frameRef) { + RequestScale(frameRef.get(), aFlags, destSize); + } } } diff --git a/image/src/RasterImage.h b/image/src/RasterImage.h index f91fa9050c94..60bca02d3e1f 100644 --- a/image/src/RasterImage.h +++ b/image/src/RasterImage.h @@ -132,9 +132,9 @@ class Image; namespace image { -class ScaleRequest; class Decoder; class FrameAnimator; +class ScaleRunner; class RasterImage MOZ_FINAL : public ImageResource , public nsIProperties @@ -298,23 +298,6 @@ public: // Called from module startup. Sets up RasterImage to be used. static void Initialize(); - enum ScaleStatus - { - SCALE_INVALID, - SCALE_PENDING, - SCALE_DONE - }; - - // Call this with a new ScaleRequest to mark this RasterImage's scale result - // as waiting for the results of this request. You call to ScalingDone before - // request is destroyed! - void ScalingStart(ScaleRequest* request); - - // Call this with a finished ScaleRequest to set this RasterImage's scale - // result. Give it a ScaleStatus of SCALE_DONE if everything succeeded, and - // SCALE_INVALID otherwise. - void ScalingDone(ScaleRequest* request, ScaleStatus status); - // Decoder shutdown enum eShutdownIntent { eShutdownIntent_Done = 0, @@ -326,9 +309,6 @@ public: // Decode strategy private: - // Initiates an HQ scale for the given frame, if possible. - void RequestScale(imgFrame* aFrame, nsIntSize aScale); - already_AddRefed CurrentStatusTracker() { mDecodingMonitor.AssertCurrentThreadIn(); @@ -724,32 +704,28 @@ private: // data bool IsDecodeFinished(); TimeStamp mDrawStartTime; - inline bool CanQualityScale(const gfx::Size& scale); - inline bool CanScale(GraphicsFilter aFilter, gfx::Size aScale, uint32_t aFlags); - - struct ScaleResult - { - ScaleResult() - : status(SCALE_INVALID) - {} - - nsIntSize scaledSize; - nsRefPtr frame; - ScaleStatus status; - }; - - ScaleResult mScaleResult; - - // We hold on to a bare pointer to a ScaleRequest while it's outstanding so - // we can mark it as stopped if necessary. The ScaleWorker/DrawWorker duo - // will inform us when to let go of this pointer. - ScaleRequest* mScaleRequest; - // Initializes imgStatusTracker and resets it on RasterImage destruction. nsAutoPtr mStatusTrackerInit; nsresult ShutdownDecoder(eShutdownIntent aIntent); + + ////////////////////////////////////////////////////////////////////////////// + // Scaling. + ////////////////////////////////////////////////////////////////////////////// + + // Initiates an HQ scale for the given frame, if possible. + void RequestScale(imgFrame* aFrame, uint32_t aFlags, const nsIntSize& aSize); + + // Determines whether we can perform an HQ scale with the given parameters. + bool CanScale(GraphicsFilter aFilter, const nsIntSize& aSize, uint32_t aFlags); + + // Called by the HQ scaler when a new scaled frame is ready. + void NotifyNewScaledFrame(); + + friend class ScaleRunner; + + // Error handling. void DoError(); diff --git a/image/src/imgFrame.h b/image/src/imgFrame.h index 276b46cd189f..4c6cc57b15bc 100644 --- a/image/src/imgFrame.h +++ b/image/src/imgFrame.h @@ -85,6 +85,7 @@ public: nsIntRect GetRect() const; IntSize GetSize() const { return mSize; } + bool NeedsPadding() const { return mOffset != nsIntPoint(0, 0); } int32_t GetStride() const; SurfaceFormat GetFormat() const; bool GetNeedsBackground() const; diff --git a/image/test/reftest/downscaling/reftest.list b/image/test/reftest/downscaling/reftest.list index 13691b424e29..31e34db7d1ef 100644 --- a/image/test/reftest/downscaling/reftest.list +++ b/image/test/reftest/downscaling/reftest.list @@ -107,53 +107,53 @@ fuzzy(20,999) != downscale-2b.html?203,52,left about:blank fuzzy(20,999) != downscale-2c.html?203,52,left about:blank fuzzy(20,999) != downscale-2d.html?203,52,left about:blank fuzzy(20,999) != downscale-2e.html?203,52,left about:blank -fuzzy(20,999) fails-if(B2G) != downscale-2f.html?203,52,left about:blank +fuzzy(20,999) != downscale-2f.html?203,52,left about:blank fuzzy(20,999) != downscale-2a.html?205,53,left about:blank fuzzy(20,999) != downscale-2b.html?205,53,left about:blank fuzzy(20,999) != downscale-2c.html?205,53,left about:blank fuzzy(20,999) != downscale-2d.html?205,53,left about:blank fuzzy(20,999) != downscale-2e.html?205,53,left about:blank -fuzzy(20,999) fails-if(B2G) != downscale-2f.html?205,53,left about:blank +fuzzy(20,999) != downscale-2f.html?205,53,left about:blank fuzzy(20,999) != downscale-2a.html?203,52,right about:blank fuzzy(20,999) != downscale-2b.html?203,52,right about:blank fuzzy(20,999) != downscale-2c.html?203,52,right about:blank fuzzy(20,999) != downscale-2d.html?203,52,right about:blank fuzzy(20,999) != downscale-2e.html?203,52,right about:blank -fuzzy(20,999) fails-if(B2G) != downscale-2f.html?203,52,right about:blank +fuzzy(20,999) != downscale-2f.html?203,52,right about:blank fuzzy(20,999) != downscale-2a.html?205,53,right about:blank fuzzy(20,999) != downscale-2b.html?205,53,right about:blank fuzzy(20,999) != downscale-2c.html?205,53,right about:blank fuzzy(20,999) != downscale-2d.html?205,53,right about:blank fuzzy(20,999) != downscale-2e.html?205,53,right about:blank -fuzzy(20,999) fails-if(B2G) != downscale-2f.html?205,53,right about:blank +fuzzy(20,999) != downscale-2f.html?205,53,right about:blank fuzzy(20,999) != downscale-2a.html?203,52,top about:blank fuzzy(20,999) != downscale-2b.html?203,52,top about:blank fuzzy(20,999) != downscale-2c.html?203,52,top about:blank fuzzy(20,999) != downscale-2d.html?203,52,top about:blank fuzzy(20,999) != downscale-2e.html?203,52,top about:blank -fuzzy(20,999) fails-if(B2G) != downscale-2f.html?203,52,top about:blank +fuzzy(20,999) != downscale-2f.html?203,52,top about:blank fuzzy(20,999) != downscale-2a.html?205,53,top about:blank fuzzy(20,999) != downscale-2b.html?205,53,top about:blank fuzzy(20,999) != downscale-2c.html?205,53,top about:blank fuzzy(20,999) != downscale-2d.html?205,53,top about:blank fuzzy(20,999) != downscale-2e.html?205,53,top about:blank -fuzzy(20,999) fails-if(B2G) != downscale-2f.html?205,53,top about:blank +fuzzy(20,999) != downscale-2f.html?205,53,top about:blank fuzzy(20,999) != downscale-2a.html?203,52,bottom about:blank fuzzy(20,999) != downscale-2b.html?203,52,bottom about:blank fuzzy(20,999) != downscale-2c.html?203,52,bottom about:blank fuzzy(20,999) != downscale-2d.html?203,52,bottom about:blank fuzzy(20,999) != downscale-2e.html?203,52,bottom about:blank -fuzzy(20,999) fails-if(B2G) != downscale-2f.html?203,52,bottom about:blank +fuzzy(20,999) != downscale-2f.html?203,52,bottom about:blank fuzzy(20,999) != downscale-2a.html?205,53,bottom about:blank fuzzy(20,999) != downscale-2b.html?205,53,bottom about:blank fuzzy(20,999) != downscale-2c.html?205,53,bottom about:blank fuzzy(20,999) != downscale-2d.html?205,53,bottom about:blank fuzzy(20,999) != downscale-2e.html?205,53,bottom about:blank -fuzzy(20,999) fails-if(B2G) != downscale-2f.html?205,53,bottom about:blank +fuzzy(20,999) != downscale-2f.html?205,53,bottom about:blank From 4578b908ad4f108b816b0a32fac897d4337841ac Mon Sep 17 00:00:00 2001 From: Andrew McCreight Date: Fri, 19 Sep 2014 15:00:43 -0700 Subject: [PATCH 009/114] Bug 1069689, part 1 - .*? at the start of a search regexp isn't useful. r=jmaher --- build/automationutils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/automationutils.py b/build/automationutils.py index 7aa5c6bbbdcc..ade4daf168aa 100644 --- a/build/automationutils.py +++ b/build/automationutils.py @@ -312,10 +312,10 @@ def processLeakLog(leakLogFile, leakThreshold = 0): log.info("TEST-INFO | leakcheck | threshold set at %d bytes" % leakThreshold) (leakLogFileDir, leakFileBase) = os.path.split(leakLogFile) - fileNameRegExp = re.compile(r".*?_([a-z]*)_pid\d*$") + fileNameRegExp = re.compile(r"_([a-z]*)_pid\d*$") if leakFileBase[-4:] == ".log": leakFileBase = leakFileBase[:-4] - fileNameRegExp = re.compile(r".*?_([a-z]*)_pid\d*.log$") + fileNameRegExp = re.compile(r"_([a-z]*)_pid\d*.log$") for fileName in os.listdir(leakLogFileDir): if fileName.find(leakFileBase) != -1: From 06cb96aeec6f9d9169e45b7a67f7bbde3b84e741 Mon Sep 17 00:00:00 2001 From: Andrew McCreight Date: Fri, 19 Sep 2014 15:00:43 -0700 Subject: [PATCH 010/114] Bug 1069689, part 2 - Don't generate a regexp then throw it away. r=jmaher --- build/automationutils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build/automationutils.py b/build/automationutils.py index ade4daf168aa..3ee16afb41e1 100644 --- a/build/automationutils.py +++ b/build/automationutils.py @@ -312,10 +312,11 @@ def processLeakLog(leakLogFile, leakThreshold = 0): log.info("TEST-INFO | leakcheck | threshold set at %d bytes" % leakThreshold) (leakLogFileDir, leakFileBase) = os.path.split(leakLogFile) - fileNameRegExp = re.compile(r"_([a-z]*)_pid\d*$") if leakFileBase[-4:] == ".log": leakFileBase = leakFileBase[:-4] fileNameRegExp = re.compile(r"_([a-z]*)_pid\d*.log$") + else: + fileNameRegExp = re.compile(r"_([a-z]*)_pid\d*$") for fileName in os.listdir(leakLogFileDir): if fileName.find(leakFileBase) != -1: From 154ca8c80bae69aa1ad7fa2ddef749ac2fd8f02c Mon Sep 17 00:00:00 2001 From: Andrew McCreight Date: Fri, 19 Sep 2014 15:00:43 -0700 Subject: [PATCH 011/114] Bug 1069689, part 3 - Make 'default' the default process type. r=jmaher --- build/automationutils.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/build/automationutils.py b/build/automationutils.py index 3ee16afb41e1..b60dda3c2591 100644 --- a/build/automationutils.py +++ b/build/automationutils.py @@ -207,11 +207,7 @@ def processSingleLeakFile(leakLogFileName, processType, leakThreshold): r"(?P-?\d+)\s+(?P-?\d+)\s+" r"-?\d+\s+(?P-?\d+)") - processString = "" - if processType: - # eg 'plugin' - processString = " %s process:" % processType - + processString = " %s process:" % processType crashedOnPurpose = False totalBytesLeaked = None logAsWarning = False @@ -271,7 +267,7 @@ def processSingleLeakFile(leakLogFileName, processType, leakThreshold): # totalBytesLeaked was seen and is non-zero. if totalBytesLeaked > leakThreshold: - if processType and processType == "tab": + if processType == "tab": # For now, ignore tab process leaks. See bug 1051230. log.info("WARNING | leakcheck | ignoring leaks in tab process") prefix = "WARNING" @@ -302,6 +298,15 @@ def processLeakLog(leakLogFile, leakThreshold = 0): Use this function if you want an additional PASS/FAIL summary. It must be used with the |XPCOM_MEM_BLOAT_LOG| environment variable. + + The base of leakLogFile for a non-default process needs to end with + _proctype_pid12345.log + "proctype" is a string denoting the type of the process, which should + be the result of calling XRE_ChildProcessTypeToString(). 12345 is + a series of digits that is the pid for the process. The .log is + optional. + + All other file names are treated as being for default processes. """ if not os.path.exists(leakLogFile): @@ -321,10 +326,11 @@ def processLeakLog(leakLogFile, leakThreshold = 0): for fileName in os.listdir(leakLogFileDir): if fileName.find(leakFileBase) != -1: thisFile = os.path.join(leakLogFileDir, fileName) - processType = None m = fileNameRegExp.search(fileName) if m: processType = m.group(1) + else: + processType = "default" processSingleLeakFile(thisFile, processType, leakThreshold) def replaceBackSlashes(input): From 11c263f4f668e27dd4d42dd3055ea493078183e7 Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Fri, 19 Sep 2014 15:10:00 -0700 Subject: [PATCH 012/114] Bug 1063247: Allow implicit construction of JS::ubi::Node from JS::HandleValue. r=terrence This seems reasonable, since a ubi::Node is really just a pointer with some introspection support, so the value and the Node are pretty similar. And I don't see cases where you'd want an error. --- js/public/UbiNode.h | 2 +- js/src/vm/UbiNode.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/js/public/UbiNode.h b/js/public/UbiNode.h index a5d0cf11db36..49b787fad584 100644 --- a/js/public/UbiNode.h +++ b/js/public/UbiNode.h @@ -271,7 +271,7 @@ class Node { } // Constructors accepting SpiderMonkey's other generic-pointer-ish types. - explicit Node(JS::Value value); + Node(JS::HandleValue value); Node(JSGCTraceKind kind, void *ptr); // copy construction and copy assignment just use memcpy, since we know diff --git a/js/src/vm/UbiNode.cpp b/js/src/vm/UbiNode.cpp index 1a8056758bd4..dcef624ccaa7 100644 --- a/js/src/vm/UbiNode.cpp +++ b/js/src/vm/UbiNode.cpp @@ -60,7 +60,7 @@ Node::Node(JSGCTraceKind kind, void *ptr) } } -Node::Node(Value value) +Node::Node(HandleValue value) { if (value.isObject()) construct(&value.toObject()); From 24bff230a902a486dc3f9c6e96baff2d447d3a84 Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Fri, 19 Sep 2014 15:10:01 -0700 Subject: [PATCH 013/114] Bug 1063247: Amend JS::ubi::Node::size and its implementations to expect a mozilla::MallocSizeOf function. r=terrence Note that JS::ubi::Node::size has no callers at present, so we can change its type without changing any callers. --- js/public/UbiNode.h | 13 ++++++++++--- js/src/vm/UbiNode.cpp | 7 ++++++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/js/public/UbiNode.h b/js/public/UbiNode.h index 49b787fad584..ae5144038fc1 100644 --- a/js/public/UbiNode.h +++ b/js/public/UbiNode.h @@ -10,6 +10,7 @@ #include "mozilla/Alignment.h" #include "mozilla/Assertions.h" #include "mozilla/Attributes.h" +#include "mozilla/MemoryReporting.h" #include "mozilla/Move.h" #include "jspubtd.h" @@ -178,7 +179,9 @@ class Base { // Return the size of this node, in bytes. Include any structures that this // node owns exclusively that are not exposed as their own ubi::Nodes. - virtual size_t size() const { return 0; } + // |mallocSizeOf| should be a malloc block sizing function; see + // |mfbt/MemoryReporting.h. + virtual size_t size(mozilla::MallocSizeOf mallocSizeof) const { return 0; } // Return an EdgeRange that initially contains all the referent's outgoing // edges. The EdgeRange should be freed with 'js_delete'. (You could use @@ -321,9 +324,13 @@ class Node { JS::Value exposeToJS() const; const char16_t *typeName() const { return base()->typeName(); } - size_t size() const { return base()->size(); } JS::Zone *zone() const { return base()->zone(); } JSCompartment *compartment() const { return base()->compartment(); } + + size_t size(mozilla::MallocSizeOf mallocSizeof) const { + return base()->size(mallocSizeof); + } + EdgeRange *edges(JSContext *cx, bool wantNames = true) const { return base()->edges(cx, wantNames); } @@ -455,7 +462,7 @@ template<> struct Concrete : TracerConcreteWithCompartment { template<> class Concrete : public Base { const char16_t *typeName() const MOZ_OVERRIDE; - size_t size() const MOZ_OVERRIDE; + size_t size(mozilla::MallocSizeOf mallocSizeOf) const MOZ_OVERRIDE; EdgeRange *edges(JSContext *cx, bool wantNames) const MOZ_OVERRIDE; JS::Zone *zone() const MOZ_OVERRIDE; JSCompartment *compartment() const MOZ_OVERRIDE; diff --git a/js/src/vm/UbiNode.cpp b/js/src/vm/UbiNode.cpp index dcef624ccaa7..ea38d70409b7 100644 --- a/js/src/vm/UbiNode.cpp +++ b/js/src/vm/UbiNode.cpp @@ -37,11 +37,16 @@ using JS::ubi::TracerConcreteWithCompartment; // All operations on null ubi::Nodes crash. const char16_t *Concrete::typeName() const { MOZ_CRASH("null ubi::Node"); } -size_t Concrete::size() const { MOZ_CRASH("null ubi::Node"); } EdgeRange *Concrete::edges(JSContext *, bool) const { MOZ_CRASH("null ubi::Node"); } JS::Zone *Concrete::zone() const { MOZ_CRASH("null ubi::Node"); } JSCompartment *Concrete::compartment() const { MOZ_CRASH("null ubi::Node"); } +size_t +Concrete::size(mozilla::MallocSizeOf mallocSizeof) const +{ + MOZ_CRASH("null ubi::Node"); +} + Node::Node(JSGCTraceKind kind, void *ptr) { switch (kind) { From 04bf937110393ca02118eca0f678a0d80a9a8af1 Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Fri, 19 Sep 2014 15:10:01 -0700 Subject: [PATCH 014/114] Bug 1063247: Let embeddings tell Debugger how to find the size of a malloc'd block of memory. r=terrence --- js/public/Debug.h | 14 ++++++++++++++ js/src/builtin/TestingFunctions.cpp | 18 ++++++++++++++++++ js/src/configure.in | 5 +++-- js/src/shell/js.cpp | 29 +++++++++++++++++++++++++++++ js/src/vm/DebuggerMemory.cpp | 6 ++++++ js/src/vm/Runtime.cpp | 9 ++++++++- js/src/vm/Runtime.h | 6 ++++++ js/src/vm/UbiNode.cpp | 1 + 8 files changed, 85 insertions(+), 3 deletions(-) diff --git a/js/public/Debug.h b/js/public/Debug.h index e824706d6deb..d1fab06512db 100644 --- a/js/public/Debug.h +++ b/js/public/Debug.h @@ -11,6 +11,7 @@ #include "mozilla/Assertions.h" #include "mozilla/Attributes.h" +#include "mozilla/MemoryReporting.h" #include "mozilla/Move.h" #include "jspubtd.h" @@ -249,6 +250,19 @@ class BuilderOrigin : public Builder { JSObject *unwrap(Object &object) { return unwrapAny(object); } }; + +// Finding the size of blocks allocated with malloc +// ------------------------------------------------ +// +// Debugger.Memory wants to be able to report how many bytes items in memory are +// consuming. To do this, it needs a function that accepts a pointer to a block, +// and returns the number of bytes allocated to that block. SpiderMonkey itself +// doesn't know which function is appropriate to use, but the embedding does. + +// Tell Debuggers in |runtime| to use |mallocSizeOf| to find the size of +// malloc'd blocks. +void SetDebuggerMallocSizeOf(JSRuntime *runtime, mozilla::MallocSizeOf mallocSizeOf); + } // namespace dbg } // namespace JS diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp index 0a43b7a9c588..91ed3d1e38e1 100644 --- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -2012,6 +2012,19 @@ IsSimdAvailable(JSContext *cx, unsigned argc, Value *vp) return true; } +static bool +ByteSize(JSContext *cx, unsigned argc, Value *vp) +{ + CallArgs args = CallArgsFromVp(argc, vp); + mozilla::MallocSizeOf mallocSizeOf = cx->runtime()->debuggerMallocSizeOf; + JS::ubi::Node node = args.get(0); + if (node) + args.rval().set(NumberValue(node.size(mallocSizeOf))); + else + args.rval().setUndefined(); + return true; +} + static const JSFunctionSpecWithHelp TestingFunctions[] = { JS_FN_HELP("gc", ::GC, 0, 0, "gc([obj] | 'compartment' [, 'shrinking'])", @@ -2334,6 +2347,11 @@ static const JSFunctionSpecWithHelp TestingFunctions[] = { " options.locals - show local variables in each frame\n" " options.thisprops - show the properties of the 'this' object of each frame\n"), + JS_FN_HELP("byteSize", ByteSize, 1, 0, +"byteSize(value)", +" Return the size in bytes occupied by |value|, or |undefined| if value\n" +" is not allocated in memory.\n"), + JS_FS_HELP_END }; diff --git a/js/src/configure.in b/js/src/configure.in index 3af4a7d20a5f..75177dd749fe 100644 --- a/js/src/configure.in +++ b/js/src/configure.in @@ -1736,6 +1736,7 @@ ia64*-hpux*) LDFLAGS="$LDFLAGS -DYNAMICBASE" fi AC_DEFINE(HAVE_SNPRINTF) + AC_DEFINE(HAVE__MSIZE) AC_DEFINE(_WINDOWS) AC_DEFINE(WIN32) AC_DEFINE(XP_WIN) @@ -3912,8 +3913,8 @@ dnl ======================================================== dnl JavaScript shell dnl ======================================================== -AC_HAVE_FUNCS(setlocale) -AC_HAVE_FUNCS(localeconv) +AC_CHECK_HEADERS(malloc.h malloc/malloc.h) +AC_CHECK_FUNCS(setlocale localeconv malloc_size malloc_usable_size) AC_SUBST(MOZILLA_VERSION) diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index d6800a752728..866522a9a991 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -22,6 +22,12 @@ # include /* for isatty() */ #endif #include +#ifdef HAVE_MALLOC_H /* for malloc_usable_size on Linux, _msize on Windows */ +#include +#endif +#ifdef HAVE_MALLOC_MALLOC_H +#include /* for malloc_size on OSX */ +#endif #include #include #include @@ -57,6 +63,7 @@ #include "frontend/Parser.h" #include "jit/arm/Simulator-arm.h" #include "jit/Ion.h" +#include "js/Debug.h" #include "js/OldDebugAPI.h" #include "js/StructuredClone.h" #include "perf/jsperf.h" @@ -5848,6 +5855,26 @@ DummyPreserveWrapperCallback(JSContext *cx, JSObject *obj) return true; } +size_t +ShellMallocSizeOf(const void *constPtr) +{ + // Match the type that all the library functions we might use here expect. + void *ptr = (void *) constPtr; + + if (!ptr) + return 0; + +#if defined(HAVE_MALLOC_USABLE_SIZE) + return malloc_usable_size(ptr); +#elif defined(HAVE_MALLOC_SIZE) + return malloc_size(ptr); +#elif HAVE__MSIZE + return _msize(ptr); +#else + return 0; +#endif +} + int main(int argc, char **argv, char **envp) { @@ -6095,6 +6122,8 @@ main(int argc, char **argv, char **envp) JS_SetNativeStackQuota(rt, gMaxStackSize); + JS::dbg::SetDebuggerMallocSizeOf(rt, ShellMallocSizeOf); + if (!offThreadState.init()) return 1; diff --git a/js/src/vm/DebuggerMemory.cpp b/js/src/vm/DebuggerMemory.cpp index f6b4391cb5c6..a8af499fd8ba 100644 --- a/js/src/vm/DebuggerMemory.cpp +++ b/js/src/vm/DebuggerMemory.cpp @@ -15,6 +15,7 @@ #include "jscompartment.h" #include "gc/Marking.h" +#include "js/Debug.h" #include "js/UbiNode.h" #include "js/UbiNodeTraverse.h" #include "vm/Debugger.h" @@ -249,6 +250,11 @@ DebuggerMemory::setMaxAllocationsLogLength(JSContext *cx, unsigned argc, Value * /* Debugger.Memory.prototype.takeCensus */ +void +JS::dbg::SetDebuggerMallocSizeOf(JSRuntime *rt, mozilla::MallocSizeOf mallocSizeOf) { + rt->debuggerMallocSizeOf = mallocSizeOf; +} + namespace js { namespace dbg { diff --git a/js/src/vm/Runtime.cpp b/js/src/vm/Runtime.cpp index 92346a5c105b..d5c0fe5ab0fc 100644 --- a/js/src/vm/Runtime.cpp +++ b/js/src/vm/Runtime.cpp @@ -121,6 +121,12 @@ static const JSWrapObjectCallbacks DefaultWrapObjectCallbacks = { nullptr }; +static size_t +ReturnZeroSize(const void *p) +{ + return 0; +} + JSRuntime::JSRuntime(JSRuntime *parentRuntime) : JS::shadow::Runtime( #ifdef JSGC_GENERATIONAL @@ -223,7 +229,8 @@ JSRuntime::JSRuntime(JSRuntime *parentRuntime) enteredPolicy(nullptr), #endif largeAllocationFailureCallback(nullptr), - oomCallback(nullptr) + oomCallback(nullptr), + debuggerMallocSizeOf(ReturnZeroSize) { liveRuntimesCount++; diff --git a/js/src/vm/Runtime.h b/js/src/vm/Runtime.h index 90bb614fb4c2..62670ac4b681 100644 --- a/js/src/vm/Runtime.h +++ b/js/src/vm/Runtime.h @@ -1402,6 +1402,12 @@ struct JSRuntime : public JS::shadow::Runtime, } return (T *)onOutOfMemoryCanGC(p, newSize * sizeof(T)); } + + /* + * Debugger.Memory functions like takeCensus use this embedding-provided + * function to assess the size of malloc'd blocks of memory. + */ + mozilla::MallocSizeOf debuggerMallocSizeOf; }; namespace js { diff --git a/js/src/vm/UbiNode.cpp b/js/src/vm/UbiNode.cpp index ea38d70409b7..9b4ca683be10 100644 --- a/js/src/vm/UbiNode.cpp +++ b/js/src/vm/UbiNode.cpp @@ -27,6 +27,7 @@ #include "jsobjinlines.h" +using JS::HandleValue; using JS::Value; using JS::ubi::Concrete; using JS::ubi::Edge; From 98b09bfb3a7891b48255f6f02bd2d0c72b5d8e1b Mon Sep 17 00:00:00 2001 From: Terrence Cole Date: Fri, 19 Sep 2014 15:51:57 -0700 Subject: [PATCH 015/114] Bug 1029549 - Sanity-check TenuredHeap pointers when accessing them; r=jonco --HG-- extra : rebase_source : 3aeb0679d121e301b1b6c5aea2511dbc1a419e55 --- js/public/RootingAPI.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/js/public/RootingAPI.h b/js/public/RootingAPI.h index 20a0bdaa4300..5c46413a0792 100644 --- a/js/public/RootingAPI.h +++ b/js/public/RootingAPI.h @@ -369,7 +369,11 @@ class TenuredHeap : public js::HeapBase return (bits & flag) != 0; } - T getPtr() const { return reinterpret_cast(bits & ~flagsMask); } + T getPtr() const { + T ptr = reinterpret_cast(bits & ~flagsMask); + MOZ_ASSERT(JS::GetTenuredGCThingZone(ptr) != nullptr); + return ptr; + } uintptr_t getFlags() const { return bits & flagsMask; } operator T() const { return getPtr(); } From d428c6078c7c5bf5e0bd39e46966ac7766016302 Mon Sep 17 00:00:00 2001 From: Terrence Cole Date: Fri, 19 Sep 2014 16:53:17 -0700 Subject: [PATCH 016/114] Back out changeset b7f417116d90 (Bug 1029549) for making the tree a beautiful orange color on a CLOSED TREE --- js/public/RootingAPI.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/js/public/RootingAPI.h b/js/public/RootingAPI.h index 5c46413a0792..20a0bdaa4300 100644 --- a/js/public/RootingAPI.h +++ b/js/public/RootingAPI.h @@ -369,11 +369,7 @@ class TenuredHeap : public js::HeapBase return (bits & flag) != 0; } - T getPtr() const { - T ptr = reinterpret_cast(bits & ~flagsMask); - MOZ_ASSERT(JS::GetTenuredGCThingZone(ptr) != nullptr); - return ptr; - } + T getPtr() const { return reinterpret_cast(bits & ~flagsMask); } uintptr_t getFlags() const { return bits & flagsMask; } operator T() const { return getPtr(); } From d205486a0044feb82716783d3a6aedbda10da03d Mon Sep 17 00:00:00 2001 From: Alexander Surkov Date: Fri, 19 Sep 2014 20:02:30 -0400 Subject: [PATCH 017/114] Bug 1040735 - DOM node reinsertion under anonymous content may trigger a11y child adoption, r=bz, tbdaunde, davidb --- accessible/base/nsAccessibilityService.cpp | 39 +++++++++++++---- accessible/base/nsAccessibilityService.h | 3 +- accessible/generic/DocAccessible.cpp | 12 ------ accessible/generic/DocAccessible.h | 11 ++++- .../tests/mochitest/treeupdate/a11y.ini | 1 + .../mochitest/treeupdate/test_bug1040735.html | 42 +++++++++++++++++++ .../mochitest/treeupdate/test_optgroup.html | 5 ++- .../mochitest/treeupdate/test_select.html | 3 +- layout/base/RestyleManager.cpp | 2 +- layout/base/nsCSSFrameConstructor.cpp | 2 +- layout/xul/nsListBoxBodyFrame.cpp | 3 +- 11 files changed, 93 insertions(+), 30 deletions(-) create mode 100644 accessible/tests/mochitest/treeupdate/test_bug1040735.html diff --git a/accessible/base/nsAccessibilityService.cpp b/accessible/base/nsAccessibilityService.cpp index e36a6c5dc55e..95675ef9b816 100644 --- a/accessible/base/nsAccessibilityService.cpp +++ b/accessible/base/nsAccessibilityService.cpp @@ -34,6 +34,7 @@ #include "States.h" #include "Statistics.h" #include "TextLeafAccessibleWrap.h" +#include "TreeWalker.h" #ifdef MOZ_ACCESSIBILITY_ATK #include "AtkSocketAccessible.h" @@ -391,22 +392,44 @@ nsAccessibilityService::ContentRangeInserted(nsIPresShell* aPresShell, void nsAccessibilityService::ContentRemoved(nsIPresShell* aPresShell, - nsIContent* aContainer, - nsIContent* aChild) + nsIContent* aChildNode) { #ifdef A11Y_LOG if (logging::IsEnabled(logging::eTree)) { logging::MsgBegin("TREE", "content removed"); - logging::Node("container", aContainer); - logging::Node("content", aChild); + logging::Node("container", aChildNode->GetFlattenedTreeParent()); + logging::Node("content", aChildNode); + } +#endif + + DocAccessible* document = GetDocAccessible(aPresShell); + if (document) { + // Flatten hierarchy may be broken at this point so we cannot get a true + // container by traversing up the DOM tree. Find a parent of first accessible + // from the subtree of the given DOM node, that'll be a container. If no + // accessibles in subtree then we don't care about the change. + Accessible* child = document->GetAccessible(aChildNode); + if (!child) { + a11y::TreeWalker walker(document->GetContainerAccessible(aChildNode), + aChildNode, a11y::TreeWalker::eWalkCache); + child = walker.NextChild(); + } + + if (child) { + document->ContentRemoved(child->Parent(), aChildNode); +#ifdef A11Y_LOG + if (logging::IsEnabled(logging::eTree)) + logging::AccessibleNNode("real container", child->Parent()); +#endif + } + } + +#ifdef A11Y_LOG + if (logging::IsEnabled(logging::eTree)) { logging::MsgEnd(); logging::Stack(); } #endif - - DocAccessible* docAccessible = GetDocAccessible(aPresShell); - if (docAccessible) - docAccessible->ContentRemoved(aContainer, aChild); } void diff --git a/accessible/base/nsAccessibilityService.h b/accessible/base/nsAccessibilityService.h index a9f1d3c76fab..1ea1ab85bcb7 100644 --- a/accessible/base/nsAccessibilityService.h +++ b/accessible/base/nsAccessibilityService.h @@ -90,8 +90,7 @@ public: /** * Notification used to update the accessible tree when content is removed. */ - void ContentRemoved(nsIPresShell* aPresShell, nsIContent* aContainer, - nsIContent* aChild); + void ContentRemoved(nsIPresShell* aPresShell, nsIContent* aChild); virtual void UpdateText(nsIPresShell* aPresShell, nsIContent* aContent); diff --git a/accessible/generic/DocAccessible.cpp b/accessible/generic/DocAccessible.cpp index b67053d3c2cc..e0e594c7842c 100644 --- a/accessible/generic/DocAccessible.cpp +++ b/accessible/generic/DocAccessible.cpp @@ -1417,18 +1417,6 @@ DocAccessible::ContentInserted(nsIContent* aContainerNode, } } -void -DocAccessible::ContentRemoved(nsIContent* aContainerNode, - nsIContent* aChildNode) -{ - // Update the whole tree of this document accessible when the container is - // null (document element is removed). - Accessible* container = aContainerNode ? - GetAccessibleOrContainer(aContainerNode) : this; - - UpdateTree(container, aChildNode, false); -} - void DocAccessible::RecreateAccessible(nsIContent* aContent) { diff --git a/accessible/generic/DocAccessible.h b/accessible/generic/DocAccessible.h index 791bcb81a3c5..d21439b12e01 100644 --- a/accessible/generic/DocAccessible.h +++ b/accessible/generic/DocAccessible.h @@ -296,7 +296,16 @@ public: /** * Notify the document accessible that content was removed. */ - void ContentRemoved(nsIContent* aContainerNode, nsIContent* aChildNode); + void ContentRemoved(Accessible* aContainer, nsIContent* aChildNode) + { + // Update the whole tree of this document accessible when the container is + // null (document element is removed). + UpdateTree((aContainer ? aContainer : this), aChildNode, false); + } + void ContentRemoved(nsIContent* aContainerNode, nsIContent* aChildNode) + { + ContentRemoved(GetAccessibleOrContainer(aContainerNode), aChildNode); + } /** * Updates accessible tree when rendered text is changed. diff --git a/accessible/tests/mochitest/treeupdate/a11y.ini b/accessible/tests/mochitest/treeupdate/a11y.ini index e3852cd99895..d3f1ffac97db 100644 --- a/accessible/tests/mochitest/treeupdate/a11y.ini +++ b/accessible/tests/mochitest/treeupdate/a11y.ini @@ -5,6 +5,7 @@ [test_bug883708.xhtml] [test_bug884251.xhtml] [test_bug895082.html] +[test_bug1040735.html] [test_canvas.html] [test_colorpicker.xul] [test_contextmenu.xul] diff --git a/accessible/tests/mochitest/treeupdate/test_bug1040735.html b/accessible/tests/mochitest/treeupdate/test_bug1040735.html new file mode 100644 index 000000000000..527f23197748 --- /dev/null +++ b/accessible/tests/mochitest/treeupdate/test_bug1040735.html @@ -0,0 +1,42 @@ + + + + Adopt DOM node from anonymous subtree + + + + + + + + + + + + Bug 1040735 +

+ +
+  
+ + + + + + diff --git a/accessible/tests/mochitest/treeupdate/test_optgroup.html b/accessible/tests/mochitest/treeupdate/test_optgroup.html index a0e172c0752f..360e1bbc08f8 100644 --- a/accessible/tests/mochitest/treeupdate/test_optgroup.html +++ b/accessible/tests/mochitest/treeupdate/test_optgroup.html @@ -51,7 +51,7 @@ { COMBOBOX_OPTION: [ { TEXT_LEAF: [] } ] }, - { COMBOBOX_OPTION: [ + { COMBOBOX_OPTION: [ { TEXT_LEAF: [] } ] }, ]}, @@ -71,6 +71,7 @@ { this.selectNode = getNode(aID); this.select = getAccessible(this.selectNode); + this.selectList = this.select.firstChild; this.invoke = function removeOptGroup_invoke() { @@ -79,7 +80,7 @@ } this.eventSeq = [ - new invokerChecker(EVENT_REORDER, this.select) + new invokerChecker(EVENT_REORDER, this.selectList) ]; this.finalCheck = function removeOptGroup_finalCheck() diff --git a/accessible/tests/mochitest/treeupdate/test_select.html b/accessible/tests/mochitest/treeupdate/test_select.html index 25fb4201baaa..520b8dab20dd 100644 --- a/accessible/tests/mochitest/treeupdate/test_select.html +++ b/accessible/tests/mochitest/treeupdate/test_select.html @@ -63,6 +63,7 @@ { this.selectNode = getNode(aID); this.select = getAccessible(this.selectNode); + this.selectList = this.select.firstChild; this.invoke = function removeOptions_invoke() { @@ -71,7 +72,7 @@ } this.eventSeq = [ - new invokerChecker(EVENT_REORDER, this.select) + new invokerChecker(EVENT_REORDER, this.selectList) ]; this.finalCheck = function removeOptions_finalCheck() diff --git a/layout/base/RestyleManager.cpp b/layout/base/RestyleManager.cpp index 290bc5588c2d..8e929ad4a875 100644 --- a/layout/base/RestyleManager.cpp +++ b/layout/base/RestyleManager.cpp @@ -3409,7 +3409,7 @@ ElementRestyler::SendAccessibilityNotifications() if (accService) { nsIPresShell* presShell = mFrame->PresContext()->GetPresShell(); nsIContent* content = mFrame->GetContent(); - accService->ContentRemoved(presShell, content->GetParent(), content); + accService->ContentRemoved(presShell, content); // Process children staying shown. uint32_t visibleContentCount = mVisibleKidsOfHiddenElement.Length(); diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index 7f627a6120f5..37efd0676fde 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -7803,7 +7803,7 @@ nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer, #ifdef ACCESSIBILITY nsAccessibilityService* accService = nsIPresShell::AccService(); if (accService) { - accService->ContentRemoved(mPresShell, aContainer, aChild); + accService->ContentRemoved(mPresShell, aChild); } #endif diff --git a/layout/xul/nsListBoxBodyFrame.cpp b/layout/xul/nsListBoxBodyFrame.cpp index 39765d44ea72..071d8094bec8 100644 --- a/layout/xul/nsListBoxBodyFrame.cpp +++ b/layout/xul/nsListBoxBodyFrame.cpp @@ -1512,8 +1512,7 @@ nsListBoxBodyFrame::RemoveChildFrame(nsBoxLayoutState &aState, nsAccessibilityService* accService = nsIPresShell::AccService(); if (accService) { nsIContent* content = aFrame->GetContent(); - accService->ContentRemoved(PresContext()->PresShell(), content->GetParent(), - content); + accService->ContentRemoved(PresContext()->PresShell(), content); } #endif From 895d364e1cbb3d68dfabeeaba91f43e6a514c91c Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Fri, 19 Sep 2014 22:58:26 -0400 Subject: [PATCH 018/114] Bug 958887 part 1. Add support for doing BinaryName annotations in IDL. r=peterv --- dom/bindings/Configuration.py | 10 ++++++++++ dom/bindings/parser/WebIDL.py | 6 ++++-- dom/bindings/test/TestBindingHeader.h | 3 +++ dom/bindings/test/TestCodeGen.webidl | 4 ++++ dom/bindings/test/TestExampleGen.webidl | 4 ++++ dom/bindings/test/TestJSImplGen.webidl | 4 ++++ 6 files changed, 29 insertions(+), 2 deletions(-) diff --git a/dom/bindings/Configuration.py b/dom/bindings/Configuration.py index 18b6fece75c1..8e6f7326ecd5 100644 --- a/dom/bindings/Configuration.py +++ b/dom/bindings/Configuration.py @@ -470,6 +470,16 @@ class Descriptor(DescriptorProvider): m.getExtendedAttribute("AvailableIn") == "PrivilegedApps"): self.featureDetectibleThings.add("%s.%s" % (self.interface.identifier.name, m.identifier.name)) + for member in self.interface.members: + if not member.isAttr() and not member.isMethod(): + continue + binaryName = member.getExtendedAttribute("BinaryName") + if binaryName: + assert isinstance(binaryName, list) + assert len(binaryName) == 1 + self._binaryNames.setdefault(member.identifier.name, + binaryName[0]) + # Build the prototype chain. self.prototypeChain = [] parent = interface diff --git a/dom/bindings/parser/WebIDL.py b/dom/bindings/parser/WebIDL.py index 3dd97df0624a..20083463e1bf 100644 --- a/dom/bindings/parser/WebIDL.py +++ b/dom/bindings/parser/WebIDL.py @@ -3362,7 +3362,8 @@ class IDLAttribute(IDLInterfaceMember): identifier == "AvailableIn" or identifier == "NewObject" or identifier == "UnsafeInPrerendering" or - identifier == "CheckPermissions"): + identifier == "CheckPermissions" or + identifier == "BinaryName"): # Known attributes that we don't need to do anything with here pass else: @@ -3963,7 +3964,8 @@ class IDLMethod(IDLInterfaceMember, IDLScope): identifier == "Pref" or identifier == "Func" or identifier == "AvailableIn" or - identifier == "CheckPermissions"): + identifier == "CheckPermissions" or + identifier == "BinaryName"): # Known attributes that we don't need to do anything with here pass else: diff --git a/dom/bindings/test/TestBindingHeader.h b/dom/bindings/test/TestBindingHeader.h index c94b3f954765..3b15cfe662cc 100644 --- a/dom/bindings/test/TestBindingHeader.h +++ b/dom/bindings/test/TestBindingHeader.h @@ -689,10 +689,13 @@ public: // binaryNames tests void MethodRenamedTo(); + void OtherMethodRenamedTo(); void MethodRenamedTo(int8_t); int8_t AttributeGetterRenamedTo(); int8_t AttributeRenamedTo(); void SetAttributeRenamedTo(int8_t); + int8_t OtherAttributeRenamedTo(); + void SetOtherAttributeRenamedTo(int8_t); // Dictionary tests void PassDictionary(JSContext*, const Dict&); diff --git a/dom/bindings/test/TestCodeGen.webidl b/dom/bindings/test/TestCodeGen.webidl index cd2d77e0a07a..75073ec09c00 100644 --- a/dom/bindings/test/TestCodeGen.webidl +++ b/dom/bindings/test/TestCodeGen.webidl @@ -656,9 +656,13 @@ interface TestInterface { // binaryNames tests void methodRenamedFrom(); + [BinaryName="otherMethodRenamedTo"] + void otherMethodRenamedFrom(); void methodRenamedFrom(byte argument); readonly attribute byte attributeGetterRenamedFrom; attribute byte attributeRenamedFrom; + [BinaryName="otherAttributeRenamedTo"] + attribute byte otherAttributeRenamedFrom; void passDictionary(optional Dict x); [Cached, Pure] diff --git a/dom/bindings/test/TestExampleGen.webidl b/dom/bindings/test/TestExampleGen.webidl index 0d69652b5b0a..43f5d84a4063 100644 --- a/dom/bindings/test/TestExampleGen.webidl +++ b/dom/bindings/test/TestExampleGen.webidl @@ -520,9 +520,13 @@ interface TestExampleInterface { // binaryNames tests void methodRenamedFrom(); + [BinaryName="otherMethodRenamedTo"] + void otherMethodRenamedFrom(); void methodRenamedFrom(byte argument); readonly attribute byte attributeGetterRenamedFrom; attribute byte attributeRenamedFrom; + [BinaryName="otherAttributeRenamedTo"] + attribute byte otherAttributeRenamedFrom; void passDictionary(optional Dict x); [Cached, Pure] diff --git a/dom/bindings/test/TestJSImplGen.webidl b/dom/bindings/test/TestJSImplGen.webidl index 2c47e77d3034..a5ec61d9a3be 100644 --- a/dom/bindings/test/TestJSImplGen.webidl +++ b/dom/bindings/test/TestJSImplGen.webidl @@ -536,9 +536,13 @@ interface TestJSImplInterface { // binaryNames tests void methodRenamedFrom(); + [BinaryName="otherMethodRenamedTo"] + void otherMethodRenamedFrom(); void methodRenamedFrom(byte argument); readonly attribute byte attributeGetterRenamedFrom; attribute byte attributeRenamedFrom; + [BinaryName="otherAttributeRenamedTo"] + attribute byte otherAttributeRenamedFrom; void passDictionary(optional Dict x); [Cached, Pure] From 972f8bc0eeaaefbd12f073e0c83e9d726a369119 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Fri, 19 Sep 2014 22:58:26 -0400 Subject: [PATCH 019/114] Bug 958887 part 2. Pass the actual names of the CSS properties involved to GenerateCSS2PropertiesWebIDL.py. r=peterv --- dom/bindings/GenerateCSS2PropertiesWebIDL.py | 2 +- dom/webidl/CSS2PropertiesProps.h | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/dom/bindings/GenerateCSS2PropertiesWebIDL.py b/dom/bindings/GenerateCSS2PropertiesWebIDL.py index e1e4a3a56e34..fe6f4d375d99 100644 --- a/dom/bindings/GenerateCSS2PropertiesWebIDL.py +++ b/dom/bindings/GenerateCSS2PropertiesWebIDL.py @@ -7,7 +7,7 @@ import string propList = eval(sys.stdin.read()) props = "" -for [prop, id, flags, pref] in propList: +for [name, prop, id, flags, pref] in propList: extendedAttrs = ["Throws", "TreatNullAs=EmptyString"] # To limit the overhead of Func= annotations, we only generate them when # necessary, which is when the diff --git a/dom/webidl/CSS2PropertiesProps.h b/dom/webidl/CSS2PropertiesProps.h index 63d5f5eff876..f0dd534bcc2a 100644 --- a/dom/webidl/CSS2PropertiesProps.h +++ b/dom/webidl/CSS2PropertiesProps.h @@ -8,13 +8,13 @@ #define PROP_STRINGIFY_INTERNAL(X) #X #define PROP_STRINGIFY(X) PROP_STRINGIFY_INTERNAL(X) -#define DO_PROP(method, id, flags, pref) \ - [ #method, #id, PROP_STRINGIFY(flags), pref ], +#define DO_PROP(name, method, id, flags, pref) \ + [ #name, #method, #id, PROP_STRINGIFY(flags), pref ], #define CSS_PROP(name, id, method, flags, pref, parsevariant, kwtable, \ stylestruct, stylestructofset, animtype) \ - DO_PROP(method, id, flags, pref) + DO_PROP(name, method, id, flags, pref) #define CSS_PROP_SHORTHAND(name, id, method, flags, pref) \ - DO_PROP(method, id, flags, pref) + DO_PROP(name, method, id, flags, pref) #define CSS_PROP_PUBLIC_OR_PRIVATE(publicname_, privatename_) publicname_ #define CSS_PROP_LIST_EXCLUDE_INTERNAL @@ -26,7 +26,7 @@ #undef CSS_PROP #define CSS_PROP_ALIAS(name, id, method, pref) \ - DO_PROP(method, id, 0, pref) + DO_PROP(name, method, id, 0, pref) #include "nsCSSPropAliasList.h" From 9b823d65099e9b76c87fde1016ec8dbecc2853d8 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Fri, 19 Sep 2014 22:58:27 -0400 Subject: [PATCH 020/114] Bug 958887 part 3. Fix codegen support for IDL attribute names and methods with dashes in them. r=peterv --- dom/bindings/Codegen.py | 56 +++++++++++++++---------- dom/bindings/test/TestBindingHeader.h | 4 ++ dom/bindings/test/TestCodeGen.webidl | 3 ++ dom/bindings/test/TestExampleGen.webidl | 3 ++ dom/bindings/test/TestJSImplGen.webidl | 3 ++ 5 files changed, 47 insertions(+), 22 deletions(-) diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index be69b7904f6d..8510fb606134 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -2102,6 +2102,9 @@ def MakeClearCachedValueNativeName(member): def MakeJSImplClearCachedValueNativeName(member): return "_" + MakeClearCachedValueNativeName(member) +def IDLToCIdentifier(name): + return name.replace("-", "_") + class MethodDefiner(PropertyDefiner): """ @@ -2288,7 +2291,7 @@ class MethodDefiner(PropertyDefiner): jitinfo = "nullptr" else: selfHostedName = "nullptr" - accessor = m.get("nativeName", m["name"]) + accessor = m.get("nativeName", IDLToCIdentifier(m["name"])) if m.get("methodInfo", True): # Cast this in case the methodInfo is a # JSTypedMethodJitInfo. @@ -2380,7 +2383,7 @@ class AttrDefiner(PropertyDefiner): def getter(attr): if self.static: - accessor = 'get_' + attr.identifier.name + accessor = 'get_' + IDLToCIdentifier(attr.identifier.name) jitinfo = "nullptr" else: if attr.hasLenientThis(): @@ -2391,7 +2394,8 @@ class AttrDefiner(PropertyDefiner): accessor = "genericGetter" else: accessor = "GenericBindingGetter" - jitinfo = "&%s_getterinfo" % attr.identifier.name + jitinfo = ("&%s_getterinfo" % + IDLToCIdentifier(attr.identifier.name)) return "{ { JS_CAST_NATIVE_TO(%s, JSPropertyOp), %s } }" % \ (accessor, jitinfo) @@ -2401,7 +2405,7 @@ class AttrDefiner(PropertyDefiner): attr.getExtendedAttribute("Replaceable") is None): return "JSOP_NULLWRAPPER" if self.static: - accessor = 'set_' + attr.identifier.name + accessor = 'set_' + IDLToCIdentifier(attr.identifier.name) jitinfo = "nullptr" else: if attr.hasLenientThis(): @@ -2412,7 +2416,7 @@ class AttrDefiner(PropertyDefiner): accessor = "genericSetter" else: accessor = "GenericBindingSetter" - jitinfo = "&%s_setterinfo" % attr.identifier.name + jitinfo = "&%s_setterinfo" % IDLToCIdentifier(attr.identifier.name) return "{ { JS_CAST_NATIVE_TO(%s, JSStrictPropertyOp), %s } }" % \ (accessor, jitinfo) @@ -2555,7 +2559,7 @@ class CGJsonifyAttributesMethod(CGAbstractMethod): } } """, - name=m.identifier.name) + name=IDLToCIdentifier(m.identifier.name)) ret += 'return true;\n' return ret @@ -7308,7 +7312,7 @@ class CGAbstractStaticBindingMethod(CGAbstractStaticMethod): def MakeNativeName(name): - return name[0].upper() + name[1:] + return name[0].upper() + IDLToCIdentifier(name[1:]) class CGGenericMethod(CGAbstractBindingMethod): @@ -7394,7 +7398,7 @@ class CGSpecializedMethod(CGAbstractStaticMethod): """ def __init__(self, descriptor, method): self.method = method - name = CppKeywords.checkMethodName(method.identifier.name) + name = CppKeywords.checkMethodName(IDLToCIdentifier(method.identifier.name)) args = [Argument('JSContext*', 'cx'), Argument('JS::Handle', 'obj'), Argument('%s*' % descriptor.nativeType, 'self'), @@ -7637,7 +7641,7 @@ class CGStaticMethod(CGAbstractStaticBindingMethod): """ def __init__(self, descriptor, method): self.method = method - name = method.identifier.name + name = IDLToCIdentifier(method.identifier.name) CGAbstractStaticBindingMethod.__init__(self, descriptor, name) def generate_code(self): @@ -7695,7 +7699,7 @@ class CGSpecializedGetter(CGAbstractStaticMethod): """ def __init__(self, descriptor, attr): self.attr = attr - name = 'get_' + attr.identifier.name + name = 'get_' + IDLToCIdentifier(attr.identifier.name) args = [ Argument('JSContext*', 'cx'), Argument('JS::Handle', 'obj'), @@ -7761,7 +7765,7 @@ class CGStaticGetter(CGAbstractStaticBindingMethod): """ def __init__(self, descriptor, attr): self.attr = attr - name = 'get_' + attr.identifier.name + name = 'get_' + IDLToCIdentifier(attr.identifier.name) CGAbstractStaticBindingMethod.__init__(self, descriptor, name) def generate_code(self): @@ -7827,7 +7831,7 @@ class CGSpecializedSetter(CGAbstractStaticMethod): """ def __init__(self, descriptor, attr): self.attr = attr - name = 'set_' + attr.identifier.name + name = 'set_' + IDLToCIdentifier(attr.identifier.name) args = [Argument('JSContext*', 'cx'), Argument('JS::Handle', 'obj'), Argument('%s*' % descriptor.nativeType, 'self'), @@ -7852,7 +7856,7 @@ class CGStaticSetter(CGAbstractStaticBindingMethod): """ def __init__(self, descriptor, attr): self.attr = attr - name = 'set_' + attr.identifier.name + name = 'set_' + IDLToCIdentifier(attr.identifier.name) CGAbstractStaticBindingMethod.__init__(self, descriptor, name) def generate_code(self): @@ -8007,10 +8011,12 @@ class CGMemberJITInfo(CGThing): def define(self): if self.member.isAttr(): - getterinfo = ("%s_getterinfo" % self.member.identifier.name) + getterinfo = ("%s_getterinfo" % + IDLToCIdentifier(self.member.identifier.name)) # We need the cast here because JSJitGetterOp has a "void* self" # while we have the right type. - getter = ("(JSJitGetterOp)get_%s" % self.member.identifier.name) + getter = ("(JSJitGetterOp)get_%s" % + IDLToCIdentifier(self.member.identifier.name)) getterinfal = "infallible" in self.descriptor.getExtendedAttributes(self.member, getter=True) getterconst = (self.member.getExtendedAttribute("SameObject") or self.member.getExtendedAttribute("Constant")) @@ -8044,10 +8050,12 @@ class CGMemberJITInfo(CGThing): if (not self.member.readonly or self.member.getExtendedAttribute("PutForwards") is not None or self.member.getExtendedAttribute("Replaceable") is not None): - setterinfo = ("%s_setterinfo" % self.member.identifier.name) + setterinfo = ("%s_setterinfo" % + IDLToCIdentifier(self.member.identifier.name)) # Actually a JSJitSetterOp, but JSJitGetterOp is first in the # union. - setter = ("(JSJitGetterOp)set_%s" % self.member.identifier.name) + setter = ("(JSJitGetterOp)set_%s" % + IDLToCIdentifier(self.member.identifier.name)) # Setters are always fallible, since they have to do a typed unwrap. result += self.defineJitInfo(setterinfo, setter, "Setter", False, False, "AliasEverything", @@ -8056,8 +8064,10 @@ class CGMemberJITInfo(CGThing): None) return result if self.member.isMethod(): - methodinfo = ("%s_methodinfo" % self.member.identifier.name) - name = CppKeywords.checkMethodName(self.member.identifier.name) + methodinfo = ("%s_methodinfo" % + IDLToCIdentifier(self.member.identifier.name)) + name = CppKeywords.checkMethodName( + IDLToCIdentifier(self.member.identifier.name)) if self.member.returnsPromise(): name = CGMethodPromiseWrapper.makeName(name) # Actually a JSJitMethodOp, but JSJitGetterOp is first in the union. @@ -8271,7 +8281,9 @@ class CGStaticMethodJitinfo(CGGeneric): " JSJitInfo::AliasEverything, JSVAL_TYPE_MISSING, false, false,\n" " false, false, 0\n" "};\n" % - (method.identifier.name, method.identifier.name)) + (IDLToCIdentifier(method.identifier.name), + CppKeywords.checkMethodName( + IDLToCIdentifier(method.identifier.name)))) def getEnumValueName(value): @@ -11494,7 +11506,7 @@ class CGDictionary(CGThing): @staticmethod def makeMemberName(name): - return "m" + name[0].upper() + name[1:].replace("-", "_") + return "m" + name[0].upper() + IDLToCIdentifier(name[1:]) def getMemberType(self, memberInfo): _, conversionInfo = memberInfo @@ -11701,7 +11713,7 @@ class CGDictionary(CGThing): @staticmethod def makeIdName(name): - return name.replace("-", "_") + "_id" + return IDLToCIdentifier(name) + "_id" @staticmethod def getDictionaryDependenciesFromType(type): diff --git a/dom/bindings/test/TestBindingHeader.h b/dom/bindings/test/TestBindingHeader.h index 3b15cfe662cc..a77d1701a410 100644 --- a/dom/bindings/test/TestBindingHeader.h +++ b/dom/bindings/test/TestBindingHeader.h @@ -834,6 +834,10 @@ public: TestInterface*, const Dict&, double, const Optional&); + void SetDashed_attribute(int8_t); + int8_t Dashed_attribute(); + void Dashed_method(); + // Methods and properties imported via "implements" bool ImplementedProperty(); void SetImplementedProperty(bool); diff --git a/dom/bindings/test/TestCodeGen.webidl b/dom/bindings/test/TestCodeGen.webidl index 75073ec09c00..37575d035b93 100644 --- a/dom/bindings/test/TestCodeGen.webidl +++ b/dom/bindings/test/TestCodeGen.webidl @@ -834,6 +834,9 @@ interface TestInterface { attribute TestCallbackInterface jsonifierShouldSkipThis3; jsonifier; + attribute byte dashed-attribute; + void dashed-method(); + // If you add things here, add them to TestExampleGen and TestJSImplGen as well }; diff --git a/dom/bindings/test/TestExampleGen.webidl b/dom/bindings/test/TestExampleGen.webidl index 43f5d84a4063..72ea586dec3b 100644 --- a/dom/bindings/test/TestExampleGen.webidl +++ b/dom/bindings/test/TestExampleGen.webidl @@ -683,6 +683,9 @@ interface TestExampleInterface { attribute TestCallbackInterface jsonifierShouldSkipThis3; jsonifier; + attribute byte dashed-attribute; + void dashed-method(); + // If you add things here, add them to TestCodeGen and TestJSImplGen as well }; diff --git a/dom/bindings/test/TestJSImplGen.webidl b/dom/bindings/test/TestJSImplGen.webidl index a5ec61d9a3be..ed6017756209 100644 --- a/dom/bindings/test/TestJSImplGen.webidl +++ b/dom/bindings/test/TestJSImplGen.webidl @@ -716,6 +716,9 @@ interface TestJSImplInterface { attribute TestCallbackInterface jsonifierShouldSkipThis3; jsonifier; + attribute byte dashed-attribute; + void dashed-method(); + // If you add things here, add them to TestCodeGen as well }; From bc34b410222721735ce562f529af35ba9c779117 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Fri, 19 Sep 2014 22:58:27 -0400 Subject: [PATCH 021/114] Bug 958887 part 4. Generate property accessors on the CSS2Properties interface for the dashed-named CSS properties and float that use their actual property names. r=peterv --- dom/bindings/GenerateCSS2PropertiesWebIDL.py | 22 ++++++++++ layout/style/test/mochitest.ini | 1 + .../test/test_exposed_prop_accessors.html | 43 +++++++++++++++++++ 3 files changed, 66 insertions(+) create mode 100644 layout/style/test/test_exposed_prop_accessors.html diff --git a/dom/bindings/GenerateCSS2PropertiesWebIDL.py b/dom/bindings/GenerateCSS2PropertiesWebIDL.py index fe6f4d375d99..53c9add0ee1e 100644 --- a/dom/bindings/GenerateCSS2PropertiesWebIDL.py +++ b/dom/bindings/GenerateCSS2PropertiesWebIDL.py @@ -26,6 +26,28 @@ for [name, prop, id, flags, pref] in propList: # (e.g. on nsComputedDOMStyle). props += " [%s] attribute DOMString %s;\n" % (", ".join(extendedAttrs), prop) + # Per spec, what's actually supposed to happen here is that we're supposed + # to have properties for: + # + # 1) Each supported CSS property name, camelCased. + # 2) Each supported name that contains dashes but doesn't start with a + # dash, without any changes to the name. + # 3) cssFloat + # + # Note that "float" will cause a property called "float" to exist due to (1) + # in that list. + # + # In practice, cssFloat is the only case in which "name" doesn't contain "-" + # but also doesn't match "prop". So the stuff we did with "prop" covers (3) + # and all of (1) except "float". If we now output attributes for all the + # cases where "name" doesn't match "prop" and "name" doesn't start with "-", + # that will cover "float" and (2). + if prop != name and name[0] != "-": + extendedAttrs.append('BinaryName="%s"' % prop) + # Throw in a '_' before the attribute name, because some of these + # property names collide with IDL reserved words. + props += " [%s] attribute DOMString _%s;\n" % (", ".join(extendedAttrs), + name) idlFile = open(sys.argv[1], "r"); idlTemplate = idlFile.read(); diff --git a/layout/style/test/mochitest.ini b/layout/style/test/mochitest.ini index 6a630b498f2b..1db9bc77212f 100644 --- a/layout/style/test/mochitest.ini +++ b/layout/style/test/mochitest.ini @@ -121,6 +121,7 @@ skip-if = toolkit == 'android' #bug 536603 [test_descriptor_storage.html] [test_descriptor_syntax_errors.html] [test_dont_use_document_colors.html] +[test_exposed_prop_accessors.html] [test_extra_inherit_initial.html] [test_flexbox_align_self_auto.html] [test_flexbox_child_display_values.xhtml] diff --git a/layout/style/test/test_exposed_prop_accessors.html b/layout/style/test/test_exposed_prop_accessors.html new file mode 100644 index 000000000000..8edd2ccfeea2 --- /dev/null +++ b/layout/style/test/test_exposed_prop_accessors.html @@ -0,0 +1,43 @@ + + + + + Test for cloning of CSS property values (including 'inherit', 'initial' and 'unset') + + + + + +

+
+
+
+ + From 5b37e56161cb76ac2b95a3f9d04a2e546296c856 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Fri, 19 Sep 2014 22:58:27 -0400 Subject: [PATCH 022/114] Bug 1066826. Remove navigator.mozIsLocallyAvailable API. r=peterv --- dom/base/Navigator.cpp | 109 ------------------------------------ dom/base/Navigator.h | 2 - dom/webidl/Navigator.webidl | 6 -- 3 files changed, 117 deletions(-) diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp index 44630079d4a8..a8e7c4caf620 100644 --- a/dom/base/Navigator.cpp +++ b/dom/base/Navigator.cpp @@ -892,115 +892,6 @@ Navigator::RegisterProtocolHandler(const nsAString& aProtocol, mWindow->GetOuterWindow()); } -bool -Navigator::MozIsLocallyAvailable(const nsAString &aURI, - bool aWhenOffline, - ErrorResult& aRv) -{ - nsCOMPtr uri; - nsresult rv = NS_NewURI(getter_AddRefs(uri), aURI); - if (NS_FAILED(rv)) { - aRv.Throw(rv); - return false; - } - - // This method of checking the cache will only work for http/https urls. - bool match; - rv = uri->SchemeIs("http", &match); - if (NS_FAILED(rv)) { - aRv.Throw(rv); - return false; - } - - if (!match) { - rv = uri->SchemeIs("https", &match); - if (NS_FAILED(rv)) { - aRv.Throw(rv); - return false; - } - if (!match) { - aRv.Throw(NS_ERROR_DOM_BAD_URI); - return false; - } - } - - // Same origin check. - JSContext *cx = nsContentUtils::GetCurrentJSContext(); - if (!cx) { - aRv.Throw(NS_ERROR_FAILURE); - return false; - } - - rv = nsContentUtils::GetSecurityManager()->CheckSameOrigin(cx, uri); - if (NS_FAILED(rv)) { - aRv.Throw(rv); - return false; - } - - // These load flags cause an error to be thrown if there is no - // valid cache entry, and skip the load if there is. - // If the cache is busy, assume that it is not yet available rather - // than waiting for it to become available. - uint32_t loadFlags = nsIChannel::INHIBIT_CACHING | - nsICachingChannel::LOAD_NO_NETWORK_IO | - nsICachingChannel::LOAD_ONLY_IF_MODIFIED | - nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE_IF_BUSY; - - if (aWhenOffline) { - loadFlags |= nsICachingChannel::LOAD_CHECK_OFFLINE_CACHE | - nsICachingChannel::LOAD_ONLY_FROM_CACHE | - nsIRequest::LOAD_FROM_CACHE; - } - - if (!mWindow) { - aRv.Throw(NS_ERROR_UNEXPECTED); - return false; - } - - nsCOMPtr loadGroup; - nsCOMPtr doc = mWindow->GetDoc(); - if (doc) { - loadGroup = doc->GetDocumentLoadGroup(); - } - - nsCOMPtr channel; - rv = NS_NewChannel(getter_AddRefs(channel), uri, - nullptr, loadGroup, nullptr, loadFlags); - if (NS_FAILED(rv)) { - aRv.Throw(rv); - return false; - } - - nsCOMPtr stream; - rv = channel->Open(getter_AddRefs(stream)); - if (NS_FAILED(rv)) { - aRv.Throw(rv); - return false; - } - - stream->Close(); - - nsresult status; - rv = channel->GetStatus(&status); - if (NS_FAILED(rv)) { - aRv.Throw(rv); - return false; - } - - if (NS_FAILED(status)) { - return false; - } - - nsCOMPtr httpChannel = do_QueryInterface(channel); - bool isAvailable; - rv = httpChannel->GetRequestSucceeded(&isAvailable); - if (NS_FAILED(rv)) { - aRv.Throw(rv); - return false; - } - return isAvailable; -} - nsDOMDeviceStorage* Navigator::GetDeviceStorage(const nsAString& aType, ErrorResult& aRv) { diff --git a/dom/base/Navigator.h b/dom/base/Navigator.h index a083bf6fb510..5a8b09b58f8a 100644 --- a/dom/base/Navigator.h +++ b/dom/base/Navigator.h @@ -207,8 +207,6 @@ public: nsTArray >& aStores, ErrorResult& aRv); DesktopNotificationCenter* GetMozNotification(ErrorResult& aRv); - bool MozIsLocallyAvailable(const nsAString& aURI, bool aWhenOffline, - ErrorResult& aRv); MobileMessageManager* GetMozMobileMessage(); Telephony* GetMozTelephony(ErrorResult& aRv); network::Connection* GetConnection(ErrorResult& aRv); diff --git a/dom/webidl/Navigator.webidl b/dom/webidl/Navigator.webidl index 0a4bd21cedf2..49b3d58e23de 100644 --- a/dom/webidl/Navigator.webidl +++ b/dom/webidl/Navigator.webidl @@ -253,12 +253,6 @@ partial interface Navigator { readonly attribute DesktopNotificationCenter mozNotification; }; -// nsIDOMClientInformation -partial interface Navigator { - [Throws] - boolean mozIsLocallyAvailable(DOMString uri, boolean whenOffline); -}; - #ifdef MOZ_WEBSMS_BACKEND partial interface Navigator { [CheckPermissions="sms", Pref="dom.sms.enabled"] From bfbc3e39049e05d1f185fee1b145ab8b7cc83291 Mon Sep 17 00:00:00 2001 From: Walter Litwinczyk Date: Fri, 19 Sep 2014 16:35:54 -0700 Subject: [PATCH 023/114] Bug 1036068 - Update ANGLE to chromium/2151. r=jrmuizel --- dom/canvas/WebGLContextGL.cpp | 6 +- dom/canvas/WebGLContextValidate.cpp | 4 +- dom/canvas/WebGLProgram.cpp | 4 +- dom/canvas/WebGLShader.h | 4 +- dom/canvas/WebGLUniformInfo.h | 39 +- gfx/angle/AUTHORS | 1 + gfx/angle/BUILD.gn | 230 + gfx/angle/CONTRIBUTORS | 7 + gfx/angle/README.md | 21 + gfx/angle/README.mozilla | 15 +- gfx/angle/include/EGL/egl.h | 555 +- gfx/angle/include/EGL/eglext.h | 1157 +- gfx/angle/include/EGL/eglplatform.h | 14 +- gfx/angle/include/GLSLANG/ShaderLang.h | 143 +- gfx/angle/include/GLSLANG/ShaderVars.h | 123 + gfx/angle/include/KHR/khrplatform.h | 0 gfx/angle/include/angle_gl.h | 23 + gfx/angle/moz.build | 30 +- gfx/angle/src/angle.gypi | 114 +- gfx/angle/src/commit.h | 6 +- gfx/angle/src/commit_id.bat | 15 - gfx/angle/src/commit_id.py | 26 +- gfx/angle/src/common/RefCountObject.h | 36 +- gfx/angle/src/common/angleutils.cpp | 37 + gfx/angle/src/common/angleutils.h | 74 +- gfx/angle/src/common/blocklayout.cpp | 132 +- gfx/angle/src/common/blocklayout.h | 66 +- gfx/angle/src/common/debug.cpp | 32 +- gfx/angle/src/common/debug.h | 6 + gfx/angle/src/common/event_tracer.h | 12 +- gfx/angle/src/common/mathutil.cpp | 1 + gfx/angle/src/common/mathutil.h | 25 +- gfx/angle/src/common/platform.h | 67 + gfx/angle/src/common/shadervars.h | 162 - gfx/angle/src/common/tls.cpp | 74 + gfx/angle/src/common/tls.h | 33 + gfx/angle/src/common/utilities.cpp | 181 +- gfx/angle/src/common/utilities.h | 22 +- gfx/angle/src/compiler.gypi | 225 +- .../compiler/preprocessor/generate_parser.sh | 0 gfx/angle/src/compiler/translator/BaseTypes.h | 33 +- .../translator/BuiltInFunctionEmulator.cpp | 8 +- .../BuiltInFunctionEmulator.cpp.orig | 490 + .../translator/BuiltInFunctionEmulator.h | 4 +- gfx/angle/src/compiler/translator/CodeGen.cpp | 2 +- .../src/compiler/translator/Compiler.cpp | 94 +- .../translator/{ShHandle.h => Compiler.h} | 43 +- .../src/compiler/translator/ConstantUnion.h | 63 +- .../src/compiler/translator/DetectCallDepth.h | 2 +- .../compiler/translator/DetectDiscontinuity.h | 2 +- .../compiler/translator/FlagStd140Structs.h | 2 +- .../src/compiler/translator/ForLoopUnroll.cpp | 4 +- gfx/angle/src/compiler/translator/HashNames.h | 2 +- .../src/compiler/translator/Initialize.cpp | 57 +- .../src/compiler/translator/Initialize.h | 6 +- .../src/compiler/translator/InitializeDll.cpp | 6 +- .../translator/InitializeParseContext.cpp | 26 +- .../translator/InitializeVariables.cpp | 24 +- .../compiler/translator/InitializeVariables.h | 18 +- .../src/compiler/translator/IntermNode.cpp | 1107 ++ .../src/compiler/translator/IntermNode.h | 772 ++ .../compiler/translator/IntermTraverse.cpp | 100 +- .../src/compiler/translator/Intermediate.cpp | 1703 +-- .../src/compiler/translator/Intermediate.h | 67 + .../src/compiler/translator/LoopInfo.cpp | 4 +- gfx/angle/src/compiler/translator/LoopInfo.h | 2 +- .../src/compiler/translator/NodeSearch.h | 2 +- .../compiler/translator/OutputGLSLBase.cpp | 139 +- .../src/compiler/translator/OutputGLSLBase.h | 16 +- .../src/compiler/translator/OutputHLSL.cpp | 1706 +-- .../src/compiler/translator/OutputHLSL.h | 100 +- .../src/compiler/translator/ParseContext.cpp | 332 +- .../src/compiler/translator/ParseContext.h | 17 +- .../src/compiler/translator/PoolAlloc.cpp | 37 +- .../compiler/translator/QualifierAlive.cpp | 2 +- .../translator/RegenerateStructNames.cpp | 82 + .../translator/RegenerateStructNames.h | 40 + .../src/compiler/translator/RemoveTree.cpp | 2 +- .../src/compiler/translator/RenameFunction.h | 2 +- .../compiler/translator/RewriteElseBlocks.cpp | 92 +- .../compiler/translator/RewriteElseBlocks.h | 19 +- .../ScalarizeVecAndMatConstructorArgs.cpp | 277 + .../ScalarizeVecAndMatConstructorArgs.h | 47 + .../src/compiler/translator/SearchSymbol.h | 2 +- .../src/compiler/translator/ShaderLang.cpp | 269 +- .../src/compiler/translator/ShaderVars.cpp | 166 + .../src/compiler/translator/StructureHLSL.cpp | 490 + .../src/compiler/translator/StructureHLSL.h | 79 + .../src/compiler/translator/SymbolTable.cpp | 31 +- .../src/compiler/translator/SymbolTable.h | 54 +- .../compiler/translator/TranslatorESSL.cpp | 5 +- .../src/compiler/translator/TranslatorESSL.h | 4 +- .../compiler/translator/TranslatorGLSL.cpp | 4 +- .../src/compiler/translator/TranslatorGLSL.h | 4 +- .../compiler/translator/TranslatorHLSL.cpp | 39 +- .../src/compiler/translator/TranslatorHLSL.h | 31 +- gfx/angle/src/compiler/translator/Types.cpp | 82 +- gfx/angle/src/compiler/translator/Types.h | 37 +- .../translator/UnfoldShortCircuit.cpp | 3 +- .../compiler/translator/UnfoldShortCircuit.h | 2 +- .../translator/UnfoldShortCircuitAST.h | 2 +- .../src/compiler/translator/UniformHLSL.cpp | 278 + .../src/compiler/translator/UniformHLSL.h | 65 + .../src/compiler/translator/UtilsHLSL.cpp | 243 + gfx/angle/src/compiler/translator/UtilsHLSL.h | 37 + .../translator/ValidateLimitations.cpp | 111 +- .../compiler/translator/ValidateLimitations.h | 6 +- .../src/compiler/translator/ValidateOutputs.h | 2 +- .../src/compiler/translator/VariableInfo.cpp | 629 +- .../src/compiler/translator/VariableInfo.h | 59 +- .../compiler/translator/VariablePacker.cpp | 224 +- .../src/compiler/translator/VariablePacker.h | 14 +- .../src/compiler/translator/VersionGLSL.cpp | 116 +- .../src/compiler/translator/VersionGLSL.h | 30 +- .../translator/depgraph/DependencyGraph.h | 2 +- .../depgraph/DependencyGraphBuilder.cpp | 164 +- .../depgraph/DependencyGraphBuilder.h | 194 +- .../compiler/translator/generate_parser.sh | 0 gfx/angle/src/compiler/translator/glslang.y | 92 +- .../src/compiler/translator/glslang_tab.cpp | 144 +- .../src/compiler/translator/intermOut.cpp | 572 +- .../src/compiler/translator/intermediate.h | 693 - .../compiler/translator/localintermediate.h | 55 - gfx/angle/src/compiler/translator/osinclude.h | 66 - .../compiler/translator/ossource_posix.cpp | 64 - .../src/compiler/translator/ossource_win.cpp | 57 - .../src/compiler/translator/parseConst.cpp | 291 +- .../timing/RestrictFragmentShaderTiming.h | 2 +- .../timing/RestrictVertexShaderTiming.h | 2 +- gfx/angle/src/compiler/translator/util.cpp | 335 + gfx/angle/src/compiler/translator/util.h | 39 + gfx/angle/src/libEGL.gypi | 73 +- gfx/angle/src/libEGL/Config.cpp | 5 +- gfx/angle/src/libEGL/Config.h | 1 - gfx/angle/src/libEGL/Display.cpp | 132 +- gfx/angle/src/libEGL/Display.h | 20 +- gfx/angle/src/libEGL/Surface.h | 3 +- gfx/angle/src/libEGL/libEGL.cpp | 1334 +- gfx/angle/src/libEGL/libEGL.def | 75 +- gfx/angle/src/libEGL/main.cpp | 37 +- gfx/angle/src/libEGL/main.h | 1 - gfx/angle/src/libEGL/moz.build | 4 +- gfx/angle/src/libGLESv2.gypi | 345 +- gfx/angle/src/libGLESv2/BinaryStream.h | 4 + gfx/angle/src/libGLESv2/Buffer.cpp | 143 +- gfx/angle/src/libGLESv2/Buffer.h | 40 +- gfx/angle/src/libGLESv2/Caps.cpp | 420 + gfx/angle/src/libGLESv2/Caps.h | 273 + gfx/angle/src/libGLESv2/Context.cpp | 2515 +--- gfx/angle/src/libGLESv2/Context.h | 362 +- gfx/angle/src/libGLESv2/DynamicHLSL.h | 78 - gfx/angle/src/libGLESv2/Error.cpp | 48 + gfx/angle/src/libGLESv2/Error.h | 39 + gfx/angle/src/libGLESv2/Fence.cpp | 3 +- gfx/angle/src/libGLESv2/Float16ToFloat32.cpp | 1 - gfx/angle/src/libGLESv2/Framebuffer.cpp | 588 +- gfx/angle/src/libGLESv2/Framebuffer.h | 67 +- .../src/libGLESv2/FramebufferAttachment.cpp | 469 + .../src/libGLESv2/FramebufferAttachment.h | 240 + gfx/angle/src/libGLESv2/HandleAllocator.cpp | 1 - gfx/angle/src/libGLESv2/HandleAllocator.h | 7 +- gfx/angle/src/libGLESv2/Program.cpp | 17 +- gfx/angle/src/libGLESv2/Program.h | 24 +- gfx/angle/src/libGLESv2/ProgramBinary.cpp | 1043 +- gfx/angle/src/libGLESv2/ProgramBinary.h | 167 +- gfx/angle/src/libGLESv2/Query.cpp | 18 +- gfx/angle/src/libGLESv2/Query.h | 10 +- gfx/angle/src/libGLESv2/Renderbuffer.cpp | 587 +- gfx/angle/src/libGLESv2/Renderbuffer.h | 241 +- .../src/libGLESv2/RenderbufferProxySet.cpp | 87 - .../src/libGLESv2/RenderbufferProxySet.h | 46 - gfx/angle/src/libGLESv2/ResourceManager.cpp | 26 +- gfx/angle/src/libGLESv2/ResourceManager.h | 9 +- gfx/angle/src/libGLESv2/Sampler.cpp | 1 - gfx/angle/src/libGLESv2/Shader.cpp | 497 +- gfx/angle/src/libGLESv2/Shader.h | 125 +- gfx/angle/src/libGLESv2/State.cpp | 1437 ++ gfx/angle/src/libGLESv2/State.h | 309 + gfx/angle/src/libGLESv2/Texture.cpp | 2345 +--- gfx/angle/src/libGLESv2/Texture.h | 259 +- gfx/angle/src/libGLESv2/TransformFeedback.cpp | 10 +- gfx/angle/src/libGLESv2/TransformFeedback.h | 12 +- gfx/angle/src/libGLESv2/Uniform.cpp | 5 +- gfx/angle/src/libGLESv2/Uniform.h | 18 +- gfx/angle/src/libGLESv2/VertexArray.cpp | 57 +- gfx/angle/src/libGLESv2/VertexArray.h | 21 +- gfx/angle/src/libGLESv2/VertexAttribute.cpp | 55 + gfx/angle/src/libGLESv2/VertexAttribute.h | 123 +- gfx/angle/src/libGLESv2/angletypes.cpp | 44 +- gfx/angle/src/libGLESv2/angletypes.h | 4 +- .../libGLESv2/{Constants.h => constants.h} | 14 +- gfx/angle/src/libGLESv2/formatutils.cpp | 2086 +-- gfx/angle/src/libGLESv2/formatutils.h | 128 +- gfx/angle/src/libGLESv2/libGLESv2.cpp | 11501 +++++++--------- gfx/angle/src/libGLESv2/main.cpp | 85 +- gfx/angle/src/libGLESv2/main.h | 5 +- gfx/angle/src/libGLESv2/moz.build | 102 +- gfx/angle/src/libGLESv2/precompiled.cpp | 9 - gfx/angle/src/libGLESv2/precompiled.h | 48 - gfx/angle/src/libGLESv2/queryconversions.cpp | 1 - gfx/angle/src/libGLESv2/renderer/BufferImpl.h | 34 + .../src/libGLESv2/renderer/BufferStorage.cpp | 36 - .../src/libGLESv2/renderer/BufferStorage.h | 49 - gfx/angle/src/libGLESv2/renderer/Image.cpp | 1 - gfx/angle/src/libGLESv2/renderer/Image.h | 16 +- .../libGLESv2/renderer/IndexRangeCache.cpp | 57 +- .../src/libGLESv2/renderer/IndexRangeCache.h | 17 +- gfx/angle/src/libGLESv2/renderer/QueryImpl.h | 13 +- gfx/angle/src/libGLESv2/renderer/Renderer.cpp | 126 +- gfx/angle/src/libGLESv2/renderer/Renderer.h | 99 +- .../src/libGLESv2/renderer/ShaderExecutable.h | 25 +- gfx/angle/src/libGLESv2/renderer/ShaderImpl.h | 29 + gfx/angle/src/libGLESv2/renderer/SwapChain.h | 4 + .../src/libGLESv2/renderer/TextureImpl.h | 70 + .../renderer/TransformFeedbackImpl.h | 31 + .../src/libGLESv2/renderer/VertexArrayImpl.h | 32 + .../libGLESv2/renderer/VertexDataManager.cpp | 293 - .../src/libGLESv2/renderer/copyimage.cpp | 11 +- gfx/angle/src/libGLESv2/renderer/copyimage.h | 25 +- .../src/libGLESv2/renderer/copyimage.inl | 32 + gfx/angle/src/libGLESv2/renderer/copyvertex.h | 298 +- .../src/libGLESv2/renderer/copyvertex.inl | 288 + .../src/libGLESv2/renderer/d3d/BufferD3D.cpp | 82 + .../src/libGLESv2/renderer/d3d/BufferD3D.h | 56 + .../{ => renderer/d3d}/DynamicHLSL.cpp | 642 +- .../src/libGLESv2/renderer/d3d/DynamicHLSL.h | 106 + .../libGLESv2/renderer/d3d/HLSLCompiler.cpp | 20 +- .../src/libGLESv2/renderer/d3d/HLSLCompiler.h | 2 - .../src/libGLESv2/renderer/d3d/ImageD3D.cpp | 26 + .../src/libGLESv2/renderer/d3d/ImageD3D.h | 54 + .../renderer/{ => d3d}/IndexBuffer.cpp | 3 +- .../renderer/{ => d3d}/IndexBuffer.h | 0 .../renderer/{ => d3d}/IndexDataManager.cpp | 213 +- .../renderer/{ => d3d}/IndexDataManager.h | 13 +- .../libGLESv2/renderer/d3d/MemoryBuffer.cpp | 77 + .../src/libGLESv2/renderer/d3d/MemoryBuffer.h | 38 + .../src/libGLESv2/renderer/d3d/ShaderD3D.cpp | 473 + .../src/libGLESv2/renderer/d3d/ShaderD3D.h | 142 + .../src/libGLESv2/renderer/d3d/TextureD3D.cpp | 2220 +++ .../src/libGLESv2/renderer/d3d/TextureD3D.h | 321 + .../renderer/{ => d3d}/TextureStorage.cpp | 6 +- .../renderer/{ => d3d}/TextureStorage.h | 2 + .../renderer/d3d/TransformFeedbackD3D.cpp | 38 + .../renderer/d3d/TransformFeedbackD3D.h | 32 + .../renderer/{ => d3d}/VertexBuffer.cpp | 39 +- .../renderer/{ => d3d}/VertexBuffer.h | 15 +- .../renderer/d3d/VertexDataManager.cpp | 335 + .../renderer/{ => d3d}/VertexDataManager.h | 31 +- .../renderer/{ => d3d}/d3d11/Blit11.cpp | 116 +- .../renderer/{ => d3d}/d3d11/Blit11.h | 2 + .../d3d11/Buffer11.cpp} | 451 +- .../libGLESv2/renderer/d3d/d3d11/Buffer11.h | 114 + .../renderer/{ => d3d}/d3d11/Clear11.cpp | 140 +- .../renderer/{ => d3d}/d3d11/Clear11.h | 11 +- .../renderer/{ => d3d}/d3d11/Fence11.cpp | 5 +- .../renderer/{ => d3d}/d3d11/Fence11.h | 0 .../renderer/{ => d3d}/d3d11/Image11.cpp | 230 +- .../renderer/{ => d3d}/d3d11/Image11.h | 20 +- .../{ => d3d}/d3d11/IndexBuffer11.cpp | 5 +- .../renderer/{ => d3d}/d3d11/IndexBuffer11.h | 2 +- .../{ => d3d}/d3d11/InputLayoutCache.cpp | 21 +- .../{ => d3d}/d3d11/InputLayoutCache.h | 5 + .../{ => d3d}/d3d11/PixelTransfer11.cpp | 41 +- .../{ => d3d}/d3d11/PixelTransfer11.h | 6 + .../renderer/{ => d3d}/d3d11/Query11.cpp | 21 +- .../renderer/{ => d3d}/d3d11/Query11.h | 6 +- .../{ => d3d}/d3d11/RenderStateCache.cpp | 24 +- .../{ => d3d}/d3d11/RenderStateCache.h | 3 + .../{ => d3d}/d3d11/RenderTarget11.cpp | 77 +- .../renderer/{ => d3d}/d3d11/RenderTarget11.h | 0 .../renderer/{ => d3d}/d3d11/Renderer11.cpp | 1159 +- .../renderer/{ => d3d}/d3d11/Renderer11.h | 130 +- .../{ => d3d}/d3d11/ShaderExecutable11.cpp | 6 +- .../{ => d3d}/d3d11/ShaderExecutable11.h | 0 .../renderer/{ => d3d}/d3d11/SwapChain11.cpp | 52 +- .../renderer/{ => d3d}/d3d11/SwapChain11.h | 0 .../{ => d3d}/d3d11/TextureStorage11.cpp | 486 +- .../{ => d3d}/d3d11/TextureStorage11.h | 45 +- .../renderer/d3d/d3d11/VertexArray11.h | 42 + .../{ => d3d}/d3d11/VertexBuffer11.cpp | 55 +- .../renderer/{ => d3d}/d3d11/VertexBuffer11.h | 2 +- .../renderer/d3d/d3d11/formatutils11.cpp | 1075 ++ .../renderer/d3d/d3d11/formatutils11.h | 84 + .../renderer/d3d/d3d11/renderer11_utils.cpp | 1068 ++ .../{ => d3d}/d3d11/renderer11_utils.h | 16 +- .../d3d11/shaders/BufferToTexture11.hlsl | 0 .../{ => d3d}/d3d11/shaders/Clear11.hlsl | 0 .../d3d11/shaders/Passthrough2D11.hlsl | 0 .../d3d11/shaders/Passthrough3D11.hlsl | 0 .../{ => d3d}/d3d11/shaders/Swizzle11.hlsl | 0 .../shaders/compiled/buffertotexture11_gs.h | 0 .../compiled/buffertotexture11_ps_4f.h | 0 .../compiled/buffertotexture11_ps_4i.h | 0 .../compiled/buffertotexture11_ps_4ui.h | 0 .../shaders/compiled/buffertotexture11_vs.h | 0 .../d3d11/shaders/compiled/clearfloat11ps.h | 0 .../d3d11/shaders/compiled/clearfloat11vs.h | 0 .../d3d11/shaders/compiled/clearsint11ps.h | 0 .../d3d11/shaders/compiled/clearsint11vs.h | 0 .../d3d11/shaders/compiled/clearuint11ps.h | 0 .../d3d11/shaders/compiled/clearuint11vs.h | 0 .../shaders/compiled/passthrough2d11vs.h | 0 .../shaders/compiled/passthrough3d11gs.h | 0 .../shaders/compiled/passthrough3d11vs.h | 0 .../shaders/compiled/passthroughdepth2d11ps.h | 0 .../shaders/compiled/passthroughlum2d11ps.h | 0 .../shaders/compiled/passthroughlum3d11ps.h | 0 .../compiled/passthroughlumalpha2d11ps.h | 0 .../compiled/passthroughlumalpha3d11ps.h | 0 .../shaders/compiled/passthroughr2d11ps.h | 0 .../shaders/compiled/passthroughr2di11ps.h | 0 .../shaders/compiled/passthroughr2dui11ps.h | 0 .../shaders/compiled/passthroughr3d11ps.h | 0 .../shaders/compiled/passthroughr3di11ps.h | 0 .../shaders/compiled/passthroughr3dui11ps.h | 0 .../shaders/compiled/passthroughrg2d11ps.h | 0 .../shaders/compiled/passthroughrg2di11ps.h | 0 .../shaders/compiled/passthroughrg2dui11ps.h | 0 .../shaders/compiled/passthroughrg3d11ps.h | 0 .../shaders/compiled/passthroughrg3di11ps.h | 0 .../shaders/compiled/passthroughrg3dui11ps.h | 0 .../shaders/compiled/passthroughrgb2d11ps.h | 0 .../shaders/compiled/passthroughrgb2di11ps.h | 0 .../shaders/compiled/passthroughrgb2dui11ps.h | 0 .../shaders/compiled/passthroughrgb3d11ps.h | 0 .../shaders/compiled/passthroughrgb3di11ps.h | 0 .../shaders/compiled/passthroughrgb3dui11ps.h | 0 .../shaders/compiled/passthroughrgba2d11ps.h | 0 .../shaders/compiled/passthroughrgba2di11ps.h | 0 .../compiled/passthroughrgba2dui11ps.h | 0 .../shaders/compiled/passthroughrgba3d11ps.h | 0 .../shaders/compiled/passthroughrgba3di11ps.h | 0 .../compiled/passthroughrgba3dui11ps.h | 0 .../shaders/compiled/swizzlef2darrayps.h | 0 .../d3d11/shaders/compiled/swizzlef2dps.h | 0 .../d3d11/shaders/compiled/swizzlef3dps.h | 0 .../shaders/compiled/swizzlei2darrayps.h | 0 .../d3d11/shaders/compiled/swizzlei2dps.h | 0 .../d3d11/shaders/compiled/swizzlei3dps.h | 0 .../shaders/compiled/swizzleui2darrayps.h | 0 .../d3d11/shaders/compiled/swizzleui2dps.h | 0 .../d3d11/shaders/compiled/swizzleui3dps.h | 0 .../d3d11/shaders/generate_shaders.bat | 0 .../renderer/{ => d3d}/d3d9/Blit9.cpp | 35 +- .../libGLESv2/renderer/{ => d3d}/d3d9/Blit9.h | 2 + .../libGLESv2/renderer/d3d/d3d9/Buffer9.cpp | 115 + .../src/libGLESv2/renderer/d3d/d3d9/Buffer9.h | 52 + .../renderer/{ => d3d}/d3d9/Fence9.cpp | 7 +- .../renderer/{ => d3d}/d3d9/Fence9.h | 0 .../renderer/{ => d3d}/d3d9/Image9.cpp | 96 +- .../renderer/{ => d3d}/d3d9/Image9.h | 6 +- .../renderer/{ => d3d}/d3d9/IndexBuffer9.cpp | 9 +- .../renderer/{ => d3d}/d3d9/IndexBuffer9.h | 2 +- .../renderer/{ => d3d}/d3d9/Query9.cpp | 23 +- .../renderer/{ => d3d}/d3d9/Query9.h | 6 +- .../renderer/{ => d3d}/d3d9/RenderTarget9.cpp | 44 +- .../renderer/{ => d3d}/d3d9/RenderTarget9.h | 0 .../renderer/{ => d3d}/d3d9/Renderer9.cpp | 900 +- .../renderer/{ => d3d}/d3d9/Renderer9.h | 129 +- .../renderer/{ => d3d}/d3d9/ShaderCache.h | 4 + .../{ => d3d}/d3d9/ShaderExecutable9.cpp | 3 +- .../{ => d3d}/d3d9/ShaderExecutable9.h | 0 .../renderer/{ => d3d}/d3d9/SwapChain9.cpp | 26 +- .../renderer/{ => d3d}/d3d9/SwapChain9.h | 0 .../{ => d3d}/d3d9/TextureStorage9.cpp | 47 +- .../renderer/{ => d3d}/d3d9/TextureStorage9.h | 4 +- .../renderer/d3d/d3d9/VertexArray9.h | 43 + .../renderer/{ => d3d}/d3d9/VertexBuffer9.cpp | 65 +- .../renderer/{ => d3d}/d3d9/VertexBuffer9.h | 10 +- .../{ => d3d}/d3d9/VertexDeclarationCache.cpp | 27 +- .../{ => d3d}/d3d9/VertexDeclarationCache.h | 2 +- .../renderer/d3d/d3d9/formatutils9.cpp | 579 + .../renderer/d3d/d3d9/formatutils9.cpp.orig | 629 + .../renderer/d3d/d3d9/formatutils9.h | 74 + .../renderer/d3d/d3d9/renderer9_utils.cpp | 536 + .../renderer/{ => d3d}/d3d9/renderer9_utils.h | 21 +- .../renderer/{ => d3d}/d3d9/shaders/Blit.ps | 0 .../renderer/{ => d3d}/d3d9/shaders/Blit.vs | 0 .../d3d9/shaders/compiled/componentmaskps.h | 0 .../{ => d3d}/d3d9/shaders/compiled/flipyvs.h | 0 .../d3d9/shaders/compiled/luminanceps.h | 0 .../d3d9/shaders/compiled/passthroughps.h | 0 .../d3d9/shaders/compiled/standardvs.h | 0 .../d3d9/shaders/generate_shaders.bat | 0 .../renderer/d3d11/BufferStorage11.h | 100 - .../renderer/d3d11/formatutils11.cpp | 1665 --- .../libGLESv2/renderer/d3d11/formatutils11.h | 79 - .../renderer/d3d11/renderer11_utils.cpp | 280 - .../renderer/d3d9/BufferStorage9.cpp | 98 - .../libGLESv2/renderer/d3d9/BufferStorage9.h | 46 - .../libGLESv2/renderer/d3d9/formatutils9.cpp | 864 -- .../libGLESv2/renderer/d3d9/formatutils9.h | 77 - .../renderer/d3d9/renderer9_utils.cpp | 247 - .../src/libGLESv2/renderer/generatemip.h | 255 +- .../src/libGLESv2/renderer/generatemip.inl | 266 + .../src/libGLESv2/renderer/imageformats.h | 2 +- .../src/libGLESv2/renderer/loadimage.cpp | 1000 +- gfx/angle/src/libGLESv2/renderer/loadimage.h | 494 +- .../src/libGLESv2/renderer/loadimage.inl | 156 + .../src/libGLESv2/renderer/loadimageSSE2.cpp | 145 +- .../src/libGLESv2/renderer/vertexconversion.h | 22 +- gfx/angle/src/libGLESv2/validationES.cpp | 1161 +- gfx/angle/src/libGLESv2/validationES.h | 62 +- gfx/angle/src/libGLESv2/validationES2.cpp | 632 +- gfx/angle/src/libGLESv2/validationES2.h | 13 +- gfx/angle/src/libGLESv2/validationES3.cpp | 1147 +- gfx/angle/src/libGLESv2/validationES3.h | 21 +- .../third_party/compiler/ArrayBoundsClamper.h | 2 +- 408 files changed, 36552 insertions(+), 33939 deletions(-) create mode 100644 gfx/angle/BUILD.gn create mode 100644 gfx/angle/README.md create mode 100644 gfx/angle/include/GLSLANG/ShaderVars.h mode change 100644 => 100755 gfx/angle/include/KHR/khrplatform.h create mode 100644 gfx/angle/include/angle_gl.h delete mode 100644 gfx/angle/src/commit_id.bat create mode 100644 gfx/angle/src/common/angleutils.cpp create mode 100644 gfx/angle/src/common/platform.h delete mode 100644 gfx/angle/src/common/shadervars.h create mode 100644 gfx/angle/src/common/tls.cpp create mode 100644 gfx/angle/src/common/tls.h mode change 100644 => 100755 gfx/angle/src/compiler/preprocessor/generate_parser.sh create mode 100644 gfx/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp.orig rename gfx/angle/src/compiler/translator/{ShHandle.h => Compiler.h} (82%) create mode 100644 gfx/angle/src/compiler/translator/IntermNode.cpp create mode 100644 gfx/angle/src/compiler/translator/IntermNode.h create mode 100644 gfx/angle/src/compiler/translator/Intermediate.h create mode 100644 gfx/angle/src/compiler/translator/RegenerateStructNames.cpp create mode 100644 gfx/angle/src/compiler/translator/RegenerateStructNames.h create mode 100644 gfx/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp create mode 100644 gfx/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h create mode 100644 gfx/angle/src/compiler/translator/ShaderVars.cpp create mode 100644 gfx/angle/src/compiler/translator/StructureHLSL.cpp create mode 100644 gfx/angle/src/compiler/translator/StructureHLSL.h create mode 100644 gfx/angle/src/compiler/translator/UniformHLSL.cpp create mode 100644 gfx/angle/src/compiler/translator/UniformHLSL.h create mode 100644 gfx/angle/src/compiler/translator/UtilsHLSL.cpp create mode 100644 gfx/angle/src/compiler/translator/UtilsHLSL.h mode change 100755 => 100644 gfx/angle/src/compiler/translator/generate_parser.sh delete mode 100644 gfx/angle/src/compiler/translator/intermediate.h delete mode 100644 gfx/angle/src/compiler/translator/localintermediate.h delete mode 100644 gfx/angle/src/compiler/translator/osinclude.h delete mode 100644 gfx/angle/src/compiler/translator/ossource_posix.cpp delete mode 100644 gfx/angle/src/compiler/translator/ossource_win.cpp create mode 100644 gfx/angle/src/libGLESv2/Caps.cpp create mode 100644 gfx/angle/src/libGLESv2/Caps.h delete mode 100644 gfx/angle/src/libGLESv2/DynamicHLSL.h create mode 100644 gfx/angle/src/libGLESv2/Error.cpp create mode 100644 gfx/angle/src/libGLESv2/Error.h create mode 100644 gfx/angle/src/libGLESv2/FramebufferAttachment.cpp create mode 100644 gfx/angle/src/libGLESv2/FramebufferAttachment.h delete mode 100644 gfx/angle/src/libGLESv2/RenderbufferProxySet.cpp delete mode 100644 gfx/angle/src/libGLESv2/RenderbufferProxySet.h create mode 100644 gfx/angle/src/libGLESv2/State.cpp create mode 100644 gfx/angle/src/libGLESv2/State.h create mode 100644 gfx/angle/src/libGLESv2/VertexAttribute.cpp rename gfx/angle/src/libGLESv2/{Constants.h => constants.h} (74%) delete mode 100644 gfx/angle/src/libGLESv2/precompiled.cpp delete mode 100644 gfx/angle/src/libGLESv2/precompiled.h create mode 100644 gfx/angle/src/libGLESv2/renderer/BufferImpl.h delete mode 100644 gfx/angle/src/libGLESv2/renderer/BufferStorage.cpp delete mode 100644 gfx/angle/src/libGLESv2/renderer/BufferStorage.h create mode 100644 gfx/angle/src/libGLESv2/renderer/ShaderImpl.h create mode 100644 gfx/angle/src/libGLESv2/renderer/TextureImpl.h create mode 100644 gfx/angle/src/libGLESv2/renderer/TransformFeedbackImpl.h create mode 100644 gfx/angle/src/libGLESv2/renderer/VertexArrayImpl.h delete mode 100644 gfx/angle/src/libGLESv2/renderer/VertexDataManager.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/copyimage.inl create mode 100644 gfx/angle/src/libGLESv2/renderer/copyvertex.inl create mode 100644 gfx/angle/src/libGLESv2/renderer/d3d/BufferD3D.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/d3d/BufferD3D.h rename gfx/angle/src/libGLESv2/{ => renderer/d3d}/DynamicHLSL.cpp (63%) create mode 100644 gfx/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.h create mode 100644 gfx/angle/src/libGLESv2/renderer/d3d/ImageD3D.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/d3d/ImageD3D.h rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/IndexBuffer.cpp (98%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/IndexBuffer.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/IndexDataManager.cpp (59%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/IndexDataManager.h (87%) create mode 100644 gfx/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.h create mode 100644 gfx/angle/src/libGLESv2/renderer/d3d/ShaderD3D.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/d3d/ShaderD3D.h create mode 100644 gfx/angle/src/libGLESv2/renderer/d3d/TextureD3D.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/d3d/TextureD3D.h rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/TextureStorage.cpp (97%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/TextureStorage.h (99%) create mode 100644 gfx/angle/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.h rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/VertexBuffer.cpp (82%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/VertexBuffer.h (92%) create mode 100644 gfx/angle/src/libGLESv2/renderer/d3d/VertexDataManager.cpp rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/VertexDataManager.h (55%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/Blit11.cpp (90%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/Blit11.h (99%) rename gfx/angle/src/libGLESv2/renderer/{d3d11/BufferStorage11.cpp => d3d/d3d11/Buffer11.cpp} (62%) create mode 100644 gfx/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.h rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/Clear11.cpp (79%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/Clear11.h (91%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/Fence11.cpp (91%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/Fence11.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/Image11.cpp (57%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/Image11.h (78%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/IndexBuffer11.cpp (97%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/IndexBuffer11.h (93%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/InputLayoutCache.cpp (92%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/InputLayoutCache.h (97%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/PixelTransfer11.cpp (86%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/PixelTransfer11.h (97%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/Query11.cpp (91%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/Query11.h (92%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/RenderStateCache.cpp (96%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/RenderStateCache.h (98%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/RenderTarget11.cpp (82%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/RenderTarget11.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/Renderer11.cpp (73%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/Renderer11.h (75%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/ShaderExecutable11.cpp (96%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/ShaderExecutable11.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/SwapChain11.cpp (92%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/SwapChain11.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/TextureStorage11.cpp (73%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/TextureStorage11.h (79%) create mode 100644 gfx/angle/src/libGLESv2/renderer/d3d/d3d11/VertexArray11.h rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/VertexBuffer11.cpp (73%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/VertexBuffer11.h (96%) create mode 100644 gfx/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.h create mode 100644 gfx/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/renderer11_utils.h (90%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/BufferToTexture11.hlsl (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/Clear11.hlsl (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/Passthrough2D11.hlsl (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/Passthrough3D11.hlsl (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/Swizzle11.hlsl (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/buffertotexture11_gs.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/buffertotexture11_ps_4f.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/buffertotexture11_ps_4i.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/buffertotexture11_ps_4ui.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/buffertotexture11_vs.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/clearfloat11ps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/clearfloat11vs.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/clearsint11ps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/clearsint11vs.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/clearuint11ps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/clearuint11vs.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/passthrough2d11vs.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/passthrough3d11gs.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/passthrough3d11vs.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/passthroughdepth2d11ps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/passthroughlum2d11ps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/passthroughlum3d11ps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/passthroughlumalpha2d11ps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/passthroughlumalpha3d11ps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/passthroughr2d11ps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/passthroughr2di11ps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/passthroughr2dui11ps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/passthroughr3d11ps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/passthroughr3di11ps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/passthroughr3dui11ps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/passthroughrg2d11ps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/passthroughrg2di11ps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/passthroughrg2dui11ps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/passthroughrg3d11ps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/passthroughrg3di11ps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/passthroughrg3dui11ps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/passthroughrgb2d11ps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/passthroughrgb2di11ps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/passthroughrgb2dui11ps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/passthroughrgb3d11ps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/passthroughrgb3di11ps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/passthroughrgb3dui11ps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/passthroughrgba2d11ps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/passthroughrgba2di11ps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/passthroughrgba2dui11ps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/passthroughrgba3d11ps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/passthroughrgba3di11ps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/passthroughrgba3dui11ps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/swizzlef2darrayps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/swizzlef2dps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/swizzlef3dps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/swizzlei2darrayps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/swizzlei2dps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/swizzlei3dps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/swizzleui2darrayps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/swizzleui2dps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/compiled/swizzleui3dps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d11/shaders/generate_shaders.bat (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d9/Blit9.cpp (94%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d9/Blit9.h (99%) create mode 100644 gfx/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.h rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d9/Fence9.cpp (88%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d9/Fence9.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d9/Image9.cpp (84%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d9/Image9.h (95%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d9/IndexBuffer9.cpp (94%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d9/IndexBuffer9.h (96%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d9/Query9.cpp (88%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d9/Query9.h (92%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d9/RenderTarget9.cpp (72%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d9/RenderTarget9.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d9/Renderer9.cpp (76%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d9/Renderer9.h (74%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d9/ShaderCache.h (97%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d9/ShaderExecutable9.cpp (94%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d9/ShaderExecutable9.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d9/SwapChain9.cpp (92%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d9/SwapChain9.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d9/TextureStorage9.cpp (83%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d9/TextureStorage9.h (95%) create mode 100644 gfx/angle/src/libGLESv2/renderer/d3d/d3d9/VertexArray9.h rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d9/VertexBuffer9.cpp (70%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d9/VertexBuffer9.h (81%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d9/VertexDeclarationCache.cpp (89%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d9/VertexDeclarationCache.h (96%) create mode 100644 gfx/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.cpp.orig create mode 100644 gfx/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.h create mode 100644 gfx/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d9/renderer9_utils.h (67%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d9/shaders/Blit.ps (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d9/shaders/Blit.vs (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d9/shaders/compiled/componentmaskps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d9/shaders/compiled/flipyvs.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d9/shaders/compiled/luminanceps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d9/shaders/compiled/passthroughps.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d9/shaders/compiled/standardvs.h (100%) rename gfx/angle/src/libGLESv2/renderer/{ => d3d}/d3d9/shaders/generate_shaders.bat (100%) delete mode 100644 gfx/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.h delete mode 100644 gfx/angle/src/libGLESv2/renderer/d3d11/formatutils11.cpp delete mode 100644 gfx/angle/src/libGLESv2/renderer/d3d11/formatutils11.h delete mode 100644 gfx/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.cpp delete mode 100644 gfx/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.cpp delete mode 100644 gfx/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.h delete mode 100644 gfx/angle/src/libGLESv2/renderer/d3d9/formatutils9.cpp delete mode 100644 gfx/angle/src/libGLESv2/renderer/d3d9/formatutils9.h delete mode 100644 gfx/angle/src/libGLESv2/renderer/d3d9/renderer9_utils.cpp create mode 100644 gfx/angle/src/libGLESv2/renderer/generatemip.inl create mode 100644 gfx/angle/src/libGLESv2/renderer/loadimage.inl diff --git a/dom/canvas/WebGLContextGL.cpp b/dom/canvas/WebGLContextGL.cpp index 98d219de456f..5037f8ad3bbd 100644 --- a/dom/canvas/WebGLContextGL.cpp +++ b/dom/canvas/WebGLContextGL.cpp @@ -3131,7 +3131,7 @@ WebGLContext::CompileShader(WebGLShader *shader) } #endif - compiler = ShConstructCompiler((ShShaderType) shader->ShaderType(), + compiler = ShConstructCompiler(shader->ShaderType(), SH_WEBGL_SPEC, targetShaderSourceLanguage, &resources); @@ -3224,7 +3224,7 @@ WebGLContext::CompileShader(WebGLShader *shader) for (size_t i = 0; i < num_uniforms; i++) { size_t length; int size; - ShDataType type; + sh::GLenum type; ShPrecisionType precision; int staticUse; ShGetVariableInfo(compiler, SH_ACTIVE_UNIFORMS, (int)i, @@ -3251,7 +3251,7 @@ WebGLContext::CompileShader(WebGLShader *shader) for (size_t i = 0; i < num_attributes; i++) { size_t length; int size; - ShDataType type; + sh::GLenum type; ShPrecisionType precision; int staticUse; ShGetVariableInfo(compiler, SH_ACTIVE_ATTRIBUTES, (int)i, diff --git a/dom/canvas/WebGLContextValidate.cpp b/dom/canvas/WebGLContextValidate.cpp index 559a0595e1f0..21d53d0689d0 100644 --- a/dom/canvas/WebGLContextValidate.cpp +++ b/dom/canvas/WebGLContextValidate.cpp @@ -1443,8 +1443,8 @@ WebGLContext::ValidateUniformLocation(const char* info, WebGLUniformLocation *lo bool WebGLContext::ValidateSamplerUniformSetter(const char* info, WebGLUniformLocation *location, GLint value) { - if (location->Info().type != SH_SAMPLER_2D && - location->Info().type != SH_SAMPLER_CUBE) + if (location->Info().type != LOCAL_GL_SAMPLER_2D && + location->Info().type != LOCAL_GL_SAMPLER_CUBE) { return true; } diff --git a/dom/canvas/WebGLProgram.cpp b/dom/canvas/WebGLProgram.cpp index a945f4f93240..d94b0b273e47 100644 --- a/dom/canvas/WebGLProgram.cpp +++ b/dom/canvas/WebGLProgram.cpp @@ -126,8 +126,8 @@ WebGLProgram::UpperBoundNumSamplerUniforms() { continue; for (size_t j = 0; j < shader->mUniformInfos.Length(); ++j) { WebGLUniformInfo u = shader->mUniformInfos[j]; - if (u.type == SH_SAMPLER_2D || - u.type == SH_SAMPLER_CUBE) + if (u.type == LOCAL_GL_SAMPLER_2D || + u.type == LOCAL_GL_SAMPLER_CUBE) { numSamplerUniforms += u.arraySize; } diff --git a/dom/canvas/WebGLShader.h b/dom/canvas/WebGLShader.h index f85322159c17..048078e0eddd 100644 --- a/dom/canvas/WebGLShader.h +++ b/dom/canvas/WebGLShader.h @@ -38,7 +38,7 @@ public: size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; GLuint GLName() { return mGLName; } - GLenum ShaderType() { return mType; } + sh::GLenum ShaderType() { return mType; } void SetSource(const nsAString& src) { // XXX do some quick gzip here maybe -- getting this will be very rare @@ -85,7 +85,7 @@ protected: } GLuint mGLName; - GLenum mType; + sh::GLenum mType; nsString mSource; nsString mTranslatedSource; nsCString mTranslationLog; // The translation log should contain only ASCII characters diff --git a/dom/canvas/WebGLUniformInfo.h b/dom/canvas/WebGLUniformInfo.h index 9c341cb30ed2..5e46df934f0d 100644 --- a/dom/canvas/WebGLUniformInfo.h +++ b/dom/canvas/WebGLUniformInfo.h @@ -6,6 +6,7 @@ #ifndef WEBGLUNIFORMINFO_H_ #define WEBGLUNIFORMINFO_H_ +#include "GLDefs.h" #include "angle/ShaderLang.h" namespace mozilla { @@ -13,35 +14,35 @@ namespace mozilla { struct WebGLUniformInfo { uint32_t arraySize; bool isArray; - ShDataType type; + sh::GLenum type; - explicit WebGLUniformInfo(uint32_t s = 0, bool a = false, ShDataType t = SH_NONE) + explicit WebGLUniformInfo(uint32_t s = 0, bool a = false, sh::GLenum t = LOCAL_GL_NONE) : arraySize(s), isArray(a), type(t) {} int ElementSize() const { switch (type) { - case SH_INT: - case SH_FLOAT: - case SH_BOOL: - case SH_SAMPLER_2D: - case SH_SAMPLER_CUBE: + case LOCAL_GL_INT: + case LOCAL_GL_FLOAT: + case LOCAL_GL_BOOL: + case LOCAL_GL_SAMPLER_2D: + case LOCAL_GL_SAMPLER_CUBE: return 1; - case SH_INT_VEC2: - case SH_FLOAT_VEC2: - case SH_BOOL_VEC2: + case LOCAL_GL_INT_VEC2: + case LOCAL_GL_FLOAT_VEC2: + case LOCAL_GL_BOOL_VEC2: return 2; - case SH_INT_VEC3: - case SH_FLOAT_VEC3: - case SH_BOOL_VEC3: + case LOCAL_GL_INT_VEC3: + case LOCAL_GL_FLOAT_VEC3: + case LOCAL_GL_BOOL_VEC3: return 3; - case SH_INT_VEC4: - case SH_FLOAT_VEC4: - case SH_BOOL_VEC4: - case SH_FLOAT_MAT2: + case LOCAL_GL_INT_VEC4: + case LOCAL_GL_FLOAT_VEC4: + case LOCAL_GL_BOOL_VEC4: + case LOCAL_GL_FLOAT_MAT2: return 4; - case SH_FLOAT_MAT3: + case LOCAL_GL_FLOAT_MAT3: return 9; - case SH_FLOAT_MAT4: + case LOCAL_GL_FLOAT_MAT4: return 16; default: MOZ_ASSERT(false); // should never get here diff --git a/gfx/angle/AUTHORS b/gfx/angle/AUTHORS index 0bdb65ee9aa7..b79bb5d16143 100644 --- a/gfx/angle/AUTHORS +++ b/gfx/angle/AUTHORS @@ -20,6 +20,7 @@ Intel Corporation Mozilla Corporation Turbulenz Klarälvdalens Datakonsult AB +Microsoft Open Technologies, Inc. Jacek Caban Mark Callow diff --git a/gfx/angle/BUILD.gn b/gfx/angle/BUILD.gn new file mode 100644 index 000000000000..86339be7ad01 --- /dev/null +++ b/gfx/angle/BUILD.gn @@ -0,0 +1,230 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +if (is_win) { + # Only needed on Windows. + gles_gypi = exec_script( + "//build/gypi_to_gn.py", + [ rebase_path("src/libGLESv2.gypi") ], + "scope", + [ "src/libGLESv2.gypi" ]) + + egl_gypi = exec_script( + "//build/gypi_to_gn.py", + [ rebase_path("src/libEGL.gypi") ], + "scope", + [ "src/libEGL.gypi" ]) +} + +compiler_gypi = exec_script( + "//build/gypi_to_gn.py", + [ rebase_path("src/compiler.gypi") ], + "scope", + [ "src/compiler.gypi" ]) + +# This config is exported to dependent targets (and also applied to internal +# ones). +config("external_config") { + include_dirs = [ + "include", + ] +} + +# This config is applied to internal Angle targets (not pushed to dependents). +config("internal_config") { + include_dirs = [ + "include", + "src", + ] +} + +component("translator") { + sources = [ + "src/compiler/translator/ShaderLang.cpp", + "src/compiler/translator/ShaderVars.cpp", + ] + + defines = [ "ANGLE_TRANSLATOR_IMPLEMENTATION" ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ + ":internal_config", + "//build/config/compiler:no_chromium_code", + ] + + deps = [ + ":translator_lib", + ] + forward_dependent_configs_from = [ ":translator_lib" ] +} + +# Holds the shared includes so we only need to list them once. +source_set("includes") { + sources = [ + "include/EGL/egl.h", + "include/EGL/eglext.h", + "include/EGL/eglplatform.h", + "include/GLES2/gl2.h", + "include/GLES2/gl2ext.h", + "include/GLES2/gl2platform.h", + "include/GLES3/gl3.h", + "include/GLES3/gl3ext.h", + "include/GLES3/gl3platform.h", + "include/GLSLANG/ShaderLang.h", + "include/KHR/khrplatform.h", + ] +} + +static_library("preprocessor") { + sources = rebase_path(compiler_gypi.angle_preprocessor_sources, ".", "src") + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ + ":internal_config", + "//build/config/compiler:no_chromium_code", + ] +} + +config("translator_static_config") { + defines = [ "ANGLE_TRANSLATOR_STATIC" ] +} + +static_library("translator_lib") { + sources = rebase_path(compiler_gypi.angle_translator_lib_sources, ".", "src") + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ + ":internal_config", + ":translator_static_config", + "//build/config/compiler:no_chromium_code", + ] + direct_dependent_configs = [ ":external_config" ] + + deps = [ + ":includes", + ":preprocessor", + ] +} + +static_library("translator_static") { + sources = [ + "src/compiler/translator/ShaderLang.cpp", + "src/compiler/translator/ShaderVars.cpp", + ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ + ":internal_config", + "//build/config/compiler:no_chromium_code", + ] + direct_dependent_configs = [ ":translator_static_config" ] + + deps = [ + ":translator_lib", + ] + forward_dependent_configs_from = [ ":translator_lib" ] +} + +config("commit_id_config") { + include_dirs = [ "$root_gen_dir/angle" ] +} + +action("commit_id") { + script = "src/commit_id.py" + + output_file = "$root_gen_dir/angle/id/commit.h" + outputs = [ output_file ] + + args = [ + "gen", + rebase_path(".", root_build_dir), + rebase_path(output_file, root_build_dir), + ] + + direct_dependent_configs = [ ":commit_id_config" ] +} + +if (is_win) { + angle_enable_d3d9 = true + angle_enable_d3d11 = true + + shared_library("libGLESv2") { + sources = rebase_path(gles_gypi.angle_libglesv2_sources, ".", "src") + + defines = [ + "ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES={ " + + "\"d3dcompiler_46.dll\", \"d3dcompiler_43.dll\" }", + "GL_APICALL=", + "GL_GLEXT_PROTOTYPES=", + "EGLAPI=", + ] + libs = [] + + # Shared D3dD sources. + if (angle_enable_d3d9 || angle_enable_d3d11) { + sources += rebase_path(gles_gypi.angle_d3d_shared_sources, ".", "src") + } + + if (angle_enable_d3d9) { + sources += rebase_path(gles_gypi.angle_d3d9_sources, ".", "src") + defines += [ "ANGLE_ENABLE_D3D9" ] + libs += [ "d3d9.lib" ] + } + + if (angle_enable_d3d11) { + sources += rebase_path(gles_gypi.angle_d3d11_sources, ".", "src") + defines += [ "ANGLE_ENABLE_D3D11" ] + libs += [ "dxguid.lib" ] + } + + if (is_debug) { + defines += [ "ANGLE_ENABLE_PERF" ] + libs += [ "d3d9.lib" ] + } + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ + ":internal_config", + "//build/config/compiler:no_chromium_code", + ] + + include_dirs = [ "src/libGLESv2" ] + + deps = [ + ":commit_id", + ":includes", + ":translator", + #":copy_compiler_dll", TODO(GYP) + ] + } + + shared_library("libEGL") { + sources = rebase_path(egl_gypi.angle_libegl_sources, ".", "src") + + defines = [ + "GL_APICALL=", + "GL_GLEXT_PROTOTYPES=", + "EGLAPI=", + ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ + ":internal_config", + "//build/config/compiler:no_chromium_code", + ] + + if (is_debug) { + defines += [ "ANGLE_ENABLE_PERF" ] + } + + include_dirs = [ "src/libGLESv2" ] + libs = [ "d3d9.lib" ] + + deps = [ + ":commit_id", + ":includes", + ":libGLESv2", + ] + } +} # is_win diff --git a/gfx/angle/CONTRIBUTORS b/gfx/angle/CONTRIBUTORS index fcb6315234c0..0cae10a0f6e1 100644 --- a/gfx/angle/CONTRIBUTORS +++ b/gfx/angle/CONTRIBUTORS @@ -52,10 +52,14 @@ Autodesk, Inc. Cloud Party, Inc. Conor Dickinson +Digia Plc + Andrew Knight + Intel Corporation Jin Yang Andy Chen Josh Triplett + Sudarsana Nagineni Klarälvdalens Datakonsult AB Milian Wolff @@ -75,3 +79,6 @@ Ulrik Persson (ddefrostt) Mark Banner (standard8mbp) David Kilzer +Microsoft Open Technologies, Inc. +Cooper Partin +Austin Kinross diff --git a/gfx/angle/README.md b/gfx/angle/README.md new file mode 100644 index 000000000000..c9205dae1602 --- /dev/null +++ b/gfx/angle/README.md @@ -0,0 +1,21 @@ +#ANGLE +The goal of ANGLE is to allow Windows users to seamlessly run WebGL and other OpenGL ES content by translating OpenGL ES API calls to DirectX 9 or DirectX 11 API calls. + +ANGLE is a conformant implementation of the OpenGL ES 2.0 specification that is hardware‐accelerated via Direct3D. ANGLE v1.0.772 was certified compliant by passing the ES 2.0.3 conformance tests in October 2011. ANGLE also provides an implementation of the EGL 1.4 specification. Work on ANGLE's OpenGL ES 3.0 implementation is currently in progress, but should not be considered stable. + +ANGLE is used as the default WebGL backend for both Google Chrome and Mozilla Firefox on Windows platforms. Chrome uses ANGLE for all graphics rendering on Windows, including the accelerated Canvas2D implementation and the Native Client sandbox environment. + +Portions of the ANGLE shader compiler are used as a shader validator and translator by WebGL implementations across multiple platforms. It is used on Mac OS X, Linux, and in mobile variants of the browsers. Having one shader validator helps to ensure that a consistent set of GLSL ES shaders are accepted across browsers and platforms. The shader translator can be used to translate shaders to other shading languages, and to optionally apply shader modifications to work around bugs or quirks in the native graphics drivers. The translator targets Desktop GLSL, Direct3D HLSL, and even ESSL for native GLES2 platforms. + +##Building +For building instructions, visit the [dev setup wiki](https://code.google.com/p/angleproject/wiki/DevSetup). + +##Contributing +* Join our [Google group](https://groups.google.com/group/angleproject) to keep up to date. +* Read about ANGLE development on the [wiki](http://code.google.com/p/angleproject/w/list). +* Become a [code contributor](https://code.google.com/p/angleproject/wiki/ContributingCode). +* File bugs in the [issue tracker](http://code.google.com/p/angleproject/issues/list) (preferably with an isolated test-case). +* Read about WebGL on the [Khronos WebGL Wiki](http://khronos.org/webgl/wiki/Main_Page). +* Learn about implementation details in the [OpenGL Insights chapter on ANGLE](http://www.seas.upenn.edu/~pcozzi/OpenGLInsights/OpenGLInsights-ANGLE.pdf) and this [ANGLE presentation](https://code.google.com/p/angleproject/downloads/detail?name=ANGLE%20and%20Cross-Platform%20WebGL%20Support.pdf&can=2&q=). +* Learn about the past, present, and future of the ANGLE implementation in [this recent presentation](https://docs.google.com/presentation/d/1CucIsdGVDmdTWRUbg68IxLE5jXwCb2y1E9YVhQo0thg/pub?start=false&loop=false). +* If you use ANGLE in your own project, we'd love to hear about it! \ No newline at end of file diff --git a/gfx/angle/README.mozilla b/gfx/angle/README.mozilla index 816c8603dd60..d321c08c3b67 100644 --- a/gfx/angle/README.mozilla +++ b/gfx/angle/README.mozilla @@ -17,8 +17,11 @@ includes Mozilla-specific patches on top of upstream. git checkout mozilla 5. Rebase the mozilla branch on top of the new google master. Fix up patches along the way, - remove unneded commits. + remove unneded commits. Google seems to have "chromium/2059" branches as well, that I + assume are merges into the Chromium tree. These might be a good point to rebase on + as well, instead of google/master: git rebase -i google/master + or git rebase -i google/chromium/2081 (whatever the latest is in 'git branch -a') 6. Re-generate moz.build files: ./gyp_mozbuild @@ -33,3 +36,13 @@ includes Mozilla-specific patches on top of upstream. 9. Build. Fix things until it builds. 10. Try runs and reviews! + +11. Once reviews are done and checkin is ready, tag the equivalent git repo: + git tag -a mozilla-bug-123456 -m "ANGLE update for bug 123456" + +12. Push the new mozilla branch, along with the tags upstream: + git push --tags mozilla +mozilla + +The "mozilla" branch head will keep moving, since it will keep getting rebased. +The tags will point to the topmost commit that was used for a particular bug number, +so that we can see its history if needed. diff --git a/gfx/angle/include/EGL/egl.h b/gfx/angle/include/EGL/egl.h index b55e6c640d8d..12590a0e2032 100644 --- a/gfx/angle/include/EGL/egl.h +++ b/gfx/angle/include/EGL/egl.h @@ -1,11 +1,12 @@ -/* -*- mode: c; tab-width: 8; -*- */ -/* vi: set sw=4 ts=8: */ -/* Reference version of egl.h for EGL 1.4. - * $Revision: 9356 $ on $Date: 2009-10-21 05:52:25 -0400 (Wed, 21 Oct 2009) $ - */ +#ifndef __egl_h_ +#define __egl_h_ 1 + +#ifdef __cplusplus +extern "C" { +#endif /* -** Copyright (c) 2007-2009 The Khronos Group Inc. +** Copyright (c) 2013-2014 The Khronos Group Inc. ** ** Permission is hereby granted, free of charge, to any person obtaining a ** copy of this software and/or associated documentation files (the @@ -26,304 +27,272 @@ ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. */ +/* +** This header is generated from the Khronos OpenGL / OpenGL ES XML +** API Registry. The current version of the Registry, generator scripts +** used to make the header, and the header can be found at +** http://www.opengl.org/registry/ +** +** Khronos $Revision: 27018 $ on $Date: 2014-06-10 08:06:12 -0700 (Tue, 10 Jun 2014) $ +*/ -#ifndef __egl_h_ -#define __egl_h_ - -/* All platform-dependent types and macro boilerplate (such as EGLAPI - * and EGLAPIENTRY) should go in eglplatform.h. - */ #include -#ifdef __cplusplus -extern "C" { -#endif +/* Generated on date 20140610 */ -/* EGL Types */ -/* EGLint is defined in eglplatform.h */ +/* Generated C header for: + * API: egl + * Versions considered: .* + * Versions emitted: .* + * Default extensions included: None + * Additional extensions included: _nomatch_^ + * Extensions removed: _nomatch_^ + */ + +#ifndef EGL_VERSION_1_0 +#define EGL_VERSION_1_0 1 typedef unsigned int EGLBoolean; -typedef unsigned int EGLenum; -typedef void *EGLConfig; -typedef void *EGLContext; typedef void *EGLDisplay; +#include +#include +typedef void *EGLConfig; typedef void *EGLSurface; -typedef void *EGLClientBuffer; - -/* EGL Versioning */ -#define EGL_VERSION_1_0 1 -#define EGL_VERSION_1_1 1 -#define EGL_VERSION_1_2 1 -#define EGL_VERSION_1_3 1 -#define EGL_VERSION_1_4 1 - -/* EGL Enumerants. Bitmasks and other exceptional cases aside, most - * enums are assigned unique values starting at 0x3000. - */ - -/* EGL aliases */ -#define EGL_FALSE 0 -#define EGL_TRUE 1 - -/* Out-of-band handle values */ -#define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType)0) -#define EGL_NO_CONTEXT ((EGLContext)0) -#define EGL_NO_DISPLAY ((EGLDisplay)0) -#define EGL_NO_SURFACE ((EGLSurface)0) - -/* Out-of-band attribute value */ -#define EGL_DONT_CARE ((EGLint)-1) - -/* Errors / GetError return values */ -#define EGL_SUCCESS 0x3000 -#define EGL_NOT_INITIALIZED 0x3001 -#define EGL_BAD_ACCESS 0x3002 -#define EGL_BAD_ALLOC 0x3003 -#define EGL_BAD_ATTRIBUTE 0x3004 -#define EGL_BAD_CONFIG 0x3005 -#define EGL_BAD_CONTEXT 0x3006 -#define EGL_BAD_CURRENT_SURFACE 0x3007 -#define EGL_BAD_DISPLAY 0x3008 -#define EGL_BAD_MATCH 0x3009 -#define EGL_BAD_NATIVE_PIXMAP 0x300A -#define EGL_BAD_NATIVE_WINDOW 0x300B -#define EGL_BAD_PARAMETER 0x300C -#define EGL_BAD_SURFACE 0x300D -#define EGL_CONTEXT_LOST 0x300E /* EGL 1.1 - IMG_power_management */ - -/* Reserved 0x300F-0x301F for additional errors */ - -/* Config attributes */ -#define EGL_BUFFER_SIZE 0x3020 -#define EGL_ALPHA_SIZE 0x3021 -#define EGL_BLUE_SIZE 0x3022 -#define EGL_GREEN_SIZE 0x3023 -#define EGL_RED_SIZE 0x3024 -#define EGL_DEPTH_SIZE 0x3025 -#define EGL_STENCIL_SIZE 0x3026 -#define EGL_CONFIG_CAVEAT 0x3027 -#define EGL_CONFIG_ID 0x3028 -#define EGL_LEVEL 0x3029 -#define EGL_MAX_PBUFFER_HEIGHT 0x302A -#define EGL_MAX_PBUFFER_PIXELS 0x302B -#define EGL_MAX_PBUFFER_WIDTH 0x302C -#define EGL_NATIVE_RENDERABLE 0x302D -#define EGL_NATIVE_VISUAL_ID 0x302E -#define EGL_NATIVE_VISUAL_TYPE 0x302F -#define EGL_SAMPLES 0x3031 -#define EGL_SAMPLE_BUFFERS 0x3032 -#define EGL_SURFACE_TYPE 0x3033 -#define EGL_TRANSPARENT_TYPE 0x3034 -#define EGL_TRANSPARENT_BLUE_VALUE 0x3035 -#define EGL_TRANSPARENT_GREEN_VALUE 0x3036 -#define EGL_TRANSPARENT_RED_VALUE 0x3037 -#define EGL_NONE 0x3038 /* Attrib list terminator */ -#define EGL_BIND_TO_TEXTURE_RGB 0x3039 -#define EGL_BIND_TO_TEXTURE_RGBA 0x303A -#define EGL_MIN_SWAP_INTERVAL 0x303B -#define EGL_MAX_SWAP_INTERVAL 0x303C -#define EGL_LUMINANCE_SIZE 0x303D -#define EGL_ALPHA_MASK_SIZE 0x303E -#define EGL_COLOR_BUFFER_TYPE 0x303F -#define EGL_RENDERABLE_TYPE 0x3040 -#define EGL_MATCH_NATIVE_PIXMAP 0x3041 /* Pseudo-attribute (not queryable) */ -#define EGL_CONFORMANT 0x3042 - -/* Reserved 0x3041-0x304F for additional config attributes */ - -/* Config attribute values */ -#define EGL_SLOW_CONFIG 0x3050 /* EGL_CONFIG_CAVEAT value */ -#define EGL_NON_CONFORMANT_CONFIG 0x3051 /* EGL_CONFIG_CAVEAT value */ -#define EGL_TRANSPARENT_RGB 0x3052 /* EGL_TRANSPARENT_TYPE value */ -#define EGL_RGB_BUFFER 0x308E /* EGL_COLOR_BUFFER_TYPE value */ -#define EGL_LUMINANCE_BUFFER 0x308F /* EGL_COLOR_BUFFER_TYPE value */ - -/* More config attribute values, for EGL_TEXTURE_FORMAT */ -#define EGL_NO_TEXTURE 0x305C -#define EGL_TEXTURE_RGB 0x305D -#define EGL_TEXTURE_RGBA 0x305E -#define EGL_TEXTURE_2D 0x305F - -/* Config attribute mask bits */ -#define EGL_PBUFFER_BIT 0x0001 /* EGL_SURFACE_TYPE mask bits */ -#define EGL_PIXMAP_BIT 0x0002 /* EGL_SURFACE_TYPE mask bits */ -#define EGL_WINDOW_BIT 0x0004 /* EGL_SURFACE_TYPE mask bits */ -#define EGL_VG_COLORSPACE_LINEAR_BIT 0x0020 /* EGL_SURFACE_TYPE mask bits */ -#define EGL_VG_ALPHA_FORMAT_PRE_BIT 0x0040 /* EGL_SURFACE_TYPE mask bits */ -#define EGL_MULTISAMPLE_RESOLVE_BOX_BIT 0x0200 /* EGL_SURFACE_TYPE mask bits */ -#define EGL_SWAP_BEHAVIOR_PRESERVED_BIT 0x0400 /* EGL_SURFACE_TYPE mask bits */ - -#define EGL_OPENGL_ES_BIT 0x0001 /* EGL_RENDERABLE_TYPE mask bits */ -#define EGL_OPENVG_BIT 0x0002 /* EGL_RENDERABLE_TYPE mask bits */ -#define EGL_OPENGL_ES2_BIT 0x0004 /* EGL_RENDERABLE_TYPE mask bits */ -#define EGL_OPENGL_BIT 0x0008 /* EGL_RENDERABLE_TYPE mask bits */ - -/* QueryString targets */ -#define EGL_VENDOR 0x3053 -#define EGL_VERSION 0x3054 -#define EGL_EXTENSIONS 0x3055 -#define EGL_CLIENT_APIS 0x308D - -/* QuerySurface / SurfaceAttrib / CreatePbufferSurface targets */ -#define EGL_HEIGHT 0x3056 -#define EGL_WIDTH 0x3057 -#define EGL_LARGEST_PBUFFER 0x3058 -#define EGL_TEXTURE_FORMAT 0x3080 -#define EGL_TEXTURE_TARGET 0x3081 -#define EGL_MIPMAP_TEXTURE 0x3082 -#define EGL_MIPMAP_LEVEL 0x3083 -#define EGL_RENDER_BUFFER 0x3086 -#define EGL_VG_COLORSPACE 0x3087 -#define EGL_VG_ALPHA_FORMAT 0x3088 -#define EGL_HORIZONTAL_RESOLUTION 0x3090 -#define EGL_VERTICAL_RESOLUTION 0x3091 -#define EGL_PIXEL_ASPECT_RATIO 0x3092 -#define EGL_SWAP_BEHAVIOR 0x3093 -#define EGL_MULTISAMPLE_RESOLVE 0x3099 - -/* EGL_RENDER_BUFFER values / BindTexImage / ReleaseTexImage buffer targets */ -#define EGL_BACK_BUFFER 0x3084 -#define EGL_SINGLE_BUFFER 0x3085 - -/* OpenVG color spaces */ -#define EGL_VG_COLORSPACE_sRGB 0x3089 /* EGL_VG_COLORSPACE value */ -#define EGL_VG_COLORSPACE_LINEAR 0x308A /* EGL_VG_COLORSPACE value */ - -/* OpenVG alpha formats */ -#define EGL_VG_ALPHA_FORMAT_NONPRE 0x308B /* EGL_ALPHA_FORMAT value */ -#define EGL_VG_ALPHA_FORMAT_PRE 0x308C /* EGL_ALPHA_FORMAT value */ - -/* Constant scale factor by which fractional display resolutions & - * aspect ratio are scaled when queried as integer values. - */ -#define EGL_DISPLAY_SCALING 10000 - -/* Unknown display resolution/aspect ratio */ -#define EGL_UNKNOWN ((EGLint)-1) - -/* Back buffer swap behaviors */ -#define EGL_BUFFER_PRESERVED 0x3094 /* EGL_SWAP_BEHAVIOR value */ -#define EGL_BUFFER_DESTROYED 0x3095 /* EGL_SWAP_BEHAVIOR value */ - -/* CreatePbufferFromClientBuffer buffer types */ -#define EGL_OPENVG_IMAGE 0x3096 - -/* QueryContext targets */ -#define EGL_CONTEXT_CLIENT_TYPE 0x3097 - -/* CreateContext attributes */ -#define EGL_CONTEXT_CLIENT_VERSION 0x3098 - -/* Multisample resolution behaviors */ -#define EGL_MULTISAMPLE_RESOLVE_DEFAULT 0x309A /* EGL_MULTISAMPLE_RESOLVE value */ -#define EGL_MULTISAMPLE_RESOLVE_BOX 0x309B /* EGL_MULTISAMPLE_RESOLVE value */ - -/* BindAPI/QueryAPI targets */ -#define EGL_OPENGL_ES_API 0x30A0 -#define EGL_OPENVG_API 0x30A1 -#define EGL_OPENGL_API 0x30A2 - -/* GetCurrentSurface targets */ -#define EGL_DRAW 0x3059 -#define EGL_READ 0x305A - -/* WaitNative engines */ -#define EGL_CORE_NATIVE_ENGINE 0x305B - -/* EGL 1.2 tokens renamed for consistency in EGL 1.3 */ -#define EGL_COLORSPACE EGL_VG_COLORSPACE -#define EGL_ALPHA_FORMAT EGL_VG_ALPHA_FORMAT -#define EGL_COLORSPACE_sRGB EGL_VG_COLORSPACE_sRGB -#define EGL_COLORSPACE_LINEAR EGL_VG_COLORSPACE_LINEAR -#define EGL_ALPHA_FORMAT_NONPRE EGL_VG_ALPHA_FORMAT_NONPRE -#define EGL_ALPHA_FORMAT_PRE EGL_VG_ALPHA_FORMAT_PRE - -/* EGL extensions must request enum blocks from the Khronos - * API Registrar, who maintains the enumerant registry. Submit - * a bug in Khronos Bugzilla against task "Registry". - */ - - - -/* EGL Functions */ - -EGLAPI EGLint EGLAPIENTRY eglGetError(void); - -EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id); -EGLAPI EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor); -EGLAPI EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay dpy); - -EGLAPI const char * EGLAPIENTRY eglQueryString(EGLDisplay dpy, EGLint name); - -EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, - EGLint config_size, EGLint *num_config); -EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, - EGLConfig *configs, EGLint config_size, - EGLint *num_config); -EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, - EGLint attribute, EGLint *value); - -EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, - EGLNativeWindowType win, - const EGLint *attrib_list); -EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, - const EGLint *attrib_list); -EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, - EGLNativePixmapType pixmap, - const EGLint *attrib_list); -EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface(EGLDisplay dpy, EGLSurface surface); -EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface(EGLDisplay dpy, EGLSurface surface, - EGLint attribute, EGLint *value); - -EGLAPI EGLBoolean EGLAPIENTRY eglBindAPI(EGLenum api); -EGLAPI EGLenum EGLAPIENTRY eglQueryAPI(void); - -EGLAPI EGLBoolean EGLAPIENTRY eglWaitClient(void); - -EGLAPI EGLBoolean EGLAPIENTRY eglReleaseThread(void); - -EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferFromClientBuffer( - EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, - EGLConfig config, const EGLint *attrib_list); - -EGLAPI EGLBoolean EGLAPIENTRY eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, - EGLint attribute, EGLint value); -EGLAPI EGLBoolean EGLAPIENTRY eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer); -EGLAPI EGLBoolean EGLAPIENTRY eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer); - - -EGLAPI EGLBoolean EGLAPIENTRY eglSwapInterval(EGLDisplay dpy, EGLint interval); - - -EGLAPI EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay dpy, EGLConfig config, - EGLContext share_context, - const EGLint *attrib_list); -EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay dpy, EGLContext ctx); -EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, - EGLSurface read, EGLContext ctx); - -EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext(void); -EGLAPI EGLSurface EGLAPIENTRY eglGetCurrentSurface(EGLint readdraw); -EGLAPI EGLDisplay EGLAPIENTRY eglGetCurrentDisplay(void); -EGLAPI EGLBoolean EGLAPIENTRY eglQueryContext(EGLDisplay dpy, EGLContext ctx, - EGLint attribute, EGLint *value); - -EGLAPI EGLBoolean EGLAPIENTRY eglWaitGL(void); -EGLAPI EGLBoolean EGLAPIENTRY eglWaitNative(EGLint engine); -EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surface); -EGLAPI EGLBoolean EGLAPIENTRY eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, - EGLNativePixmapType target); - -/* This is a generic function pointer type, whose name indicates it must - * be cast to the proper type *and calling convention* before use. - */ +typedef void *EGLContext; typedef void (*__eglMustCastToProperFunctionPointerType)(void); +#define EGL_ALPHA_SIZE 0x3021 +#define EGL_BAD_ACCESS 0x3002 +#define EGL_BAD_ALLOC 0x3003 +#define EGL_BAD_ATTRIBUTE 0x3004 +#define EGL_BAD_CONFIG 0x3005 +#define EGL_BAD_CONTEXT 0x3006 +#define EGL_BAD_CURRENT_SURFACE 0x3007 +#define EGL_BAD_DISPLAY 0x3008 +#define EGL_BAD_MATCH 0x3009 +#define EGL_BAD_NATIVE_PIXMAP 0x300A +#define EGL_BAD_NATIVE_WINDOW 0x300B +#define EGL_BAD_PARAMETER 0x300C +#define EGL_BAD_SURFACE 0x300D +#define EGL_BLUE_SIZE 0x3022 +#define EGL_BUFFER_SIZE 0x3020 +#define EGL_CONFIG_CAVEAT 0x3027 +#define EGL_CONFIG_ID 0x3028 +#define EGL_CORE_NATIVE_ENGINE 0x305B +#define EGL_DEPTH_SIZE 0x3025 +#define EGL_DONT_CARE ((EGLint)-1) +#define EGL_DRAW 0x3059 +#define EGL_EXTENSIONS 0x3055 +#define EGL_FALSE 0 +#define EGL_GREEN_SIZE 0x3023 +#define EGL_HEIGHT 0x3056 +#define EGL_LARGEST_PBUFFER 0x3058 +#define EGL_LEVEL 0x3029 +#define EGL_MAX_PBUFFER_HEIGHT 0x302A +#define EGL_MAX_PBUFFER_PIXELS 0x302B +#define EGL_MAX_PBUFFER_WIDTH 0x302C +#define EGL_NATIVE_RENDERABLE 0x302D +#define EGL_NATIVE_VISUAL_ID 0x302E +#define EGL_NATIVE_VISUAL_TYPE 0x302F +#define EGL_NONE 0x3038 +#define EGL_NON_CONFORMANT_CONFIG 0x3051 +#define EGL_NOT_INITIALIZED 0x3001 +#define EGL_NO_CONTEXT ((EGLContext)0) +#define EGL_NO_DISPLAY ((EGLDisplay)0) +#define EGL_NO_SURFACE ((EGLSurface)0) +#define EGL_PBUFFER_BIT 0x0001 +#define EGL_PIXMAP_BIT 0x0002 +#define EGL_READ 0x305A +#define EGL_RED_SIZE 0x3024 +#define EGL_SAMPLES 0x3031 +#define EGL_SAMPLE_BUFFERS 0x3032 +#define EGL_SLOW_CONFIG 0x3050 +#define EGL_STENCIL_SIZE 0x3026 +#define EGL_SUCCESS 0x3000 +#define EGL_SURFACE_TYPE 0x3033 +#define EGL_TRANSPARENT_BLUE_VALUE 0x3035 +#define EGL_TRANSPARENT_GREEN_VALUE 0x3036 +#define EGL_TRANSPARENT_RED_VALUE 0x3037 +#define EGL_TRANSPARENT_RGB 0x3052 +#define EGL_TRANSPARENT_TYPE 0x3034 +#define EGL_TRUE 1 +#define EGL_VENDOR 0x3053 +#define EGL_VERSION 0x3054 +#define EGL_WIDTH 0x3057 +#define EGL_WINDOW_BIT 0x0004 +EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig (EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config); +EGLAPI EGLBoolean EGLAPIENTRY eglCopyBuffers (EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target); +EGLAPI EGLContext EGLAPIENTRY eglCreateContext (EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list); +EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferSurface (EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list); +EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurface (EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list); +EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface (EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext (EGLDisplay dpy, EGLContext ctx); +EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface (EGLDisplay dpy, EGLSurface surface); +EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib (EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value); +EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs (EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config); +EGLAPI EGLDisplay EGLAPIENTRY eglGetCurrentDisplay (void); +EGLAPI EGLSurface EGLAPIENTRY eglGetCurrentSurface (EGLint readdraw); +EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay (EGLNativeDisplayType display_id); +EGLAPI EGLint EGLAPIENTRY eglGetError (void); +EGLAPI __eglMustCastToProperFunctionPointerType EGLAPIENTRY eglGetProcAddress (const char *procname); +EGLAPI EGLBoolean EGLAPIENTRY eglInitialize (EGLDisplay dpy, EGLint *major, EGLint *minor); +EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent (EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx); +EGLAPI EGLBoolean EGLAPIENTRY eglQueryContext (EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value); +EGLAPI const char *EGLAPIENTRY eglQueryString (EGLDisplay dpy, EGLint name); +EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value); +EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers (EGLDisplay dpy, EGLSurface surface); +EGLAPI EGLBoolean EGLAPIENTRY eglTerminate (EGLDisplay dpy); +EGLAPI EGLBoolean EGLAPIENTRY eglWaitGL (void); +EGLAPI EGLBoolean EGLAPIENTRY eglWaitNative (EGLint engine); +#endif /* EGL_VERSION_1_0 */ -/* Now, define eglGetProcAddress using the generic function ptr. type */ -EGLAPI __eglMustCastToProperFunctionPointerType EGLAPIENTRY - eglGetProcAddress(const char *procname); +#ifndef EGL_VERSION_1_1 +#define EGL_VERSION_1_1 1 +#define EGL_BACK_BUFFER 0x3084 +#define EGL_BIND_TO_TEXTURE_RGB 0x3039 +#define EGL_BIND_TO_TEXTURE_RGBA 0x303A +#define EGL_CONTEXT_LOST 0x300E +#define EGL_MIN_SWAP_INTERVAL 0x303B +#define EGL_MAX_SWAP_INTERVAL 0x303C +#define EGL_MIPMAP_TEXTURE 0x3082 +#define EGL_MIPMAP_LEVEL 0x3083 +#define EGL_NO_TEXTURE 0x305C +#define EGL_TEXTURE_2D 0x305F +#define EGL_TEXTURE_FORMAT 0x3080 +#define EGL_TEXTURE_RGB 0x305D +#define EGL_TEXTURE_RGBA 0x305E +#define EGL_TEXTURE_TARGET 0x3081 +EGLAPI EGLBoolean EGLAPIENTRY eglBindTexImage (EGLDisplay dpy, EGLSurface surface, EGLint buffer); +EGLAPI EGLBoolean EGLAPIENTRY eglReleaseTexImage (EGLDisplay dpy, EGLSurface surface, EGLint buffer); +EGLAPI EGLBoolean EGLAPIENTRY eglSurfaceAttrib (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value); +EGLAPI EGLBoolean EGLAPIENTRY eglSwapInterval (EGLDisplay dpy, EGLint interval); +#endif /* EGL_VERSION_1_1 */ + +#ifndef EGL_VERSION_1_2 +#define EGL_VERSION_1_2 1 +typedef unsigned int EGLenum; +typedef void *EGLClientBuffer; +#define EGL_ALPHA_FORMAT 0x3088 +#define EGL_ALPHA_FORMAT_NONPRE 0x308B +#define EGL_ALPHA_FORMAT_PRE 0x308C +#define EGL_ALPHA_MASK_SIZE 0x303E +#define EGL_BUFFER_PRESERVED 0x3094 +#define EGL_BUFFER_DESTROYED 0x3095 +#define EGL_CLIENT_APIS 0x308D +#define EGL_COLORSPACE 0x3087 +#define EGL_COLORSPACE_sRGB 0x3089 +#define EGL_COLORSPACE_LINEAR 0x308A +#define EGL_COLOR_BUFFER_TYPE 0x303F +#define EGL_CONTEXT_CLIENT_TYPE 0x3097 +#define EGL_DISPLAY_SCALING 10000 +#define EGL_HORIZONTAL_RESOLUTION 0x3090 +#define EGL_LUMINANCE_BUFFER 0x308F +#define EGL_LUMINANCE_SIZE 0x303D +#define EGL_OPENGL_ES_BIT 0x0001 +#define EGL_OPENVG_BIT 0x0002 +#define EGL_OPENGL_ES_API 0x30A0 +#define EGL_OPENVG_API 0x30A1 +#define EGL_OPENVG_IMAGE 0x3096 +#define EGL_PIXEL_ASPECT_RATIO 0x3092 +#define EGL_RENDERABLE_TYPE 0x3040 +#define EGL_RENDER_BUFFER 0x3086 +#define EGL_RGB_BUFFER 0x308E +#define EGL_SINGLE_BUFFER 0x3085 +#define EGL_SWAP_BEHAVIOR 0x3093 +#define EGL_UNKNOWN ((EGLint)-1) +#define EGL_VERTICAL_RESOLUTION 0x3091 +EGLAPI EGLBoolean EGLAPIENTRY eglBindAPI (EGLenum api); +EGLAPI EGLenum EGLAPIENTRY eglQueryAPI (void); +EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferFromClientBuffer (EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglReleaseThread (void); +EGLAPI EGLBoolean EGLAPIENTRY eglWaitClient (void); +#endif /* EGL_VERSION_1_2 */ + +#ifndef EGL_VERSION_1_3 +#define EGL_VERSION_1_3 1 +#define EGL_CONFORMANT 0x3042 +#define EGL_CONTEXT_CLIENT_VERSION 0x3098 +#define EGL_MATCH_NATIVE_PIXMAP 0x3041 +#define EGL_OPENGL_ES2_BIT 0x0004 +#define EGL_VG_ALPHA_FORMAT 0x3088 +#define EGL_VG_ALPHA_FORMAT_NONPRE 0x308B +#define EGL_VG_ALPHA_FORMAT_PRE 0x308C +#define EGL_VG_ALPHA_FORMAT_PRE_BIT 0x0040 +#define EGL_VG_COLORSPACE 0x3087 +#define EGL_VG_COLORSPACE_sRGB 0x3089 +#define EGL_VG_COLORSPACE_LINEAR 0x308A +#define EGL_VG_COLORSPACE_LINEAR_BIT 0x0020 +#endif /* EGL_VERSION_1_3 */ + +#ifndef EGL_VERSION_1_4 +#define EGL_VERSION_1_4 1 +#define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType)0) +#define EGL_MULTISAMPLE_RESOLVE_BOX_BIT 0x0200 +#define EGL_MULTISAMPLE_RESOLVE 0x3099 +#define EGL_MULTISAMPLE_RESOLVE_DEFAULT 0x309A +#define EGL_MULTISAMPLE_RESOLVE_BOX 0x309B +#define EGL_OPENGL_API 0x30A2 +#define EGL_OPENGL_BIT 0x0008 +#define EGL_SWAP_BEHAVIOR_PRESERVED_BIT 0x0400 +EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext (void); +#endif /* EGL_VERSION_1_4 */ + +#ifndef EGL_VERSION_1_5 +#define EGL_VERSION_1_5 1 +typedef void *EGLSync; +typedef intptr_t EGLAttrib; +typedef khronos_utime_nanoseconds_t EGLTime; +#define EGL_CONTEXT_MAJOR_VERSION 0x3098 +#define EGL_CONTEXT_MINOR_VERSION 0x30FB +#define EGL_CONTEXT_OPENGL_PROFILE_MASK 0x30FD +#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY 0x31BD +#define EGL_NO_RESET_NOTIFICATION 0x31BE +#define EGL_LOSE_CONTEXT_ON_RESET 0x31BF +#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT 0x00000001 +#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT 0x00000002 +#define EGL_CONTEXT_OPENGL_DEBUG 0x31B0 +#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE 0x31B1 +#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS 0x31B2 +#define EGL_OPENGL_ES3_BIT 0x00000040 +#define EGL_CL_EVENT_HANDLE 0x309C +#define EGL_SYNC_CL_EVENT 0x30FE +#define EGL_SYNC_CL_EVENT_COMPLETE 0x30FF +#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE 0x30F0 +#define EGL_SYNC_TYPE 0x30F7 +#define EGL_SYNC_STATUS 0x30F1 +#define EGL_SYNC_CONDITION 0x30F8 +#define EGL_SIGNALED 0x30F2 +#define EGL_UNSIGNALED 0x30F3 +#define EGL_SYNC_FLUSH_COMMANDS_BIT 0x0001 +#define EGL_FOREVER 0xFFFFFFFFFFFFFFFFull +#define EGL_TIMEOUT_EXPIRED 0x30F5 +#define EGL_CONDITION_SATISFIED 0x30F6 +#define EGL_NO_SYNC ((EGLSync)0) +#define EGL_SYNC_FENCE 0x30F9 +#define EGL_GL_COLORSPACE 0x309D +#define EGL_GL_COLORSPACE_SRGB 0x3089 +#define EGL_GL_COLORSPACE_LINEAR 0x308A +#define EGL_GL_RENDERBUFFER 0x30B9 +#define EGL_GL_TEXTURE_2D 0x30B1 +#define EGL_GL_TEXTURE_LEVEL 0x30BC +#define EGL_GL_TEXTURE_3D 0x30B2 +#define EGL_GL_TEXTURE_ZOFFSET 0x30BD +#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x30B3 +#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x30B4 +#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x30B5 +#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x30B6 +#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x30B7 +#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x30B8 +EGLAPI EGLSync EGLAPIENTRY eglCreateSync (EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglDestroySync (EGLDisplay dpy, EGLSync sync); +EGLAPI EGLint EGLAPIENTRY eglClientWaitSync (EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout); +EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttrib (EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value); +EGLAPI EGLDisplay EGLAPIENTRY eglGetPlatformDisplay (EGLenum platform, void *native_display, const EGLAttrib *attrib_list); +EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformWindowSurface (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list); +EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurface (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglWaitSync (EGLDisplay dpy, EGLSync sync, EGLint flags); +#endif /* EGL_VERSION_1_5 */ #ifdef __cplusplus } #endif -#endif /* __egl_h_ */ +#endif diff --git a/gfx/angle/include/EGL/eglext.h b/gfx/angle/include/EGL/eglext.h index 937af4193b5c..9e29605cf0ee 100644 --- a/gfx/angle/include/EGL/eglext.h +++ b/gfx/angle/include/EGL/eglext.h @@ -1,12 +1,12 @@ #ifndef __eglext_h_ -#define __eglext_h_ +#define __eglext_h_ 1 #ifdef __cplusplus extern "C" { #endif /* -** Copyright (c) 2007-2013 The Khronos Group Inc. +** Copyright (c) 2013-2014 The Khronos Group Inc. ** ** Permission is hereby granted, free of charge, to any person obtaining a ** copy of this software and/or associated documentation files (the @@ -27,186 +27,706 @@ extern "C" { ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. */ +/* +** This header is generated from the Khronos OpenGL / OpenGL ES XML +** API Registry. The current version of the Registry, generator scripts +** used to make the header, and the header can be found at +** http://www.opengl.org/registry/ +** +** Khronos $Revision: 27018 $ on $Date: 2014-06-10 08:06:12 -0700 (Tue, 10 Jun 2014) $ +*/ #include -/*************************************************************/ +#define EGL_EGLEXT_VERSION 20140610 -/* Header file version number */ -/* Current version at http://www.khronos.org/registry/egl/ */ -/* $Revision: 20690 $ on $Date: 2013-02-22 20:15:05 -0500 (Fri, 22 Feb 2013) $ */ -#define EGL_EGLEXT_VERSION 15 +/* Generated C header for: + * API: egl + * Versions considered: .* + * Versions emitted: _nomatch_^ + * Default extensions included: egl + * Additional extensions included: _nomatch_^ + * Extensions removed: _nomatch_^ + */ + +#ifndef EGL_KHR_cl_event +#define EGL_KHR_cl_event 1 +#define EGL_CL_EVENT_HANDLE_KHR 0x309C +#define EGL_SYNC_CL_EVENT_KHR 0x30FE +#define EGL_SYNC_CL_EVENT_COMPLETE_KHR 0x30FF +#endif /* EGL_KHR_cl_event */ + +#ifndef EGL_KHR_cl_event2 +#define EGL_KHR_cl_event2 1 +typedef void *EGLSyncKHR; +typedef intptr_t EGLAttribKHR; +typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNC64KHRPROC) (EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSync64KHR (EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list); +#endif +#endif /* EGL_KHR_cl_event2 */ + +#ifndef EGL_KHR_client_get_all_proc_addresses +#define EGL_KHR_client_get_all_proc_addresses 1 +#endif /* EGL_KHR_client_get_all_proc_addresses */ #ifndef EGL_KHR_config_attribs #define EGL_KHR_config_attribs 1 -#define EGL_CONFORMANT_KHR 0x3042 /* EGLConfig attribute */ -#define EGL_VG_COLORSPACE_LINEAR_BIT_KHR 0x0020 /* EGL_SURFACE_TYPE bitfield */ -#define EGL_VG_ALPHA_FORMAT_PRE_BIT_KHR 0x0040 /* EGL_SURFACE_TYPE bitfield */ -#endif +#define EGL_CONFORMANT_KHR 0x3042 +#define EGL_VG_COLORSPACE_LINEAR_BIT_KHR 0x0020 +#define EGL_VG_ALPHA_FORMAT_PRE_BIT_KHR 0x0040 +#endif /* EGL_KHR_config_attribs */ -#ifndef EGL_KHR_lock_surface -#define EGL_KHR_lock_surface 1 -#define EGL_READ_SURFACE_BIT_KHR 0x0001 /* EGL_LOCK_USAGE_HINT_KHR bitfield */ -#define EGL_WRITE_SURFACE_BIT_KHR 0x0002 /* EGL_LOCK_USAGE_HINT_KHR bitfield */ -#define EGL_LOCK_SURFACE_BIT_KHR 0x0080 /* EGL_SURFACE_TYPE bitfield */ -#define EGL_OPTIMAL_FORMAT_BIT_KHR 0x0100 /* EGL_SURFACE_TYPE bitfield */ -#define EGL_MATCH_FORMAT_KHR 0x3043 /* EGLConfig attribute */ -#define EGL_FORMAT_RGB_565_EXACT_KHR 0x30C0 /* EGL_MATCH_FORMAT_KHR value */ -#define EGL_FORMAT_RGB_565_KHR 0x30C1 /* EGL_MATCH_FORMAT_KHR value */ -#define EGL_FORMAT_RGBA_8888_EXACT_KHR 0x30C2 /* EGL_MATCH_FORMAT_KHR value */ -#define EGL_FORMAT_RGBA_8888_KHR 0x30C3 /* EGL_MATCH_FORMAT_KHR value */ -#define EGL_MAP_PRESERVE_PIXELS_KHR 0x30C4 /* eglLockSurfaceKHR attribute */ -#define EGL_LOCK_USAGE_HINT_KHR 0x30C5 /* eglLockSurfaceKHR attribute */ -#define EGL_BITMAP_POINTER_KHR 0x30C6 /* eglQuerySurface attribute */ -#define EGL_BITMAP_PITCH_KHR 0x30C7 /* eglQuerySurface attribute */ -#define EGL_BITMAP_ORIGIN_KHR 0x30C8 /* eglQuerySurface attribute */ -#define EGL_BITMAP_PIXEL_RED_OFFSET_KHR 0x30C9 /* eglQuerySurface attribute */ -#define EGL_BITMAP_PIXEL_GREEN_OFFSET_KHR 0x30CA /* eglQuerySurface attribute */ -#define EGL_BITMAP_PIXEL_BLUE_OFFSET_KHR 0x30CB /* eglQuerySurface attribute */ -#define EGL_BITMAP_PIXEL_ALPHA_OFFSET_KHR 0x30CC /* eglQuerySurface attribute */ -#define EGL_BITMAP_PIXEL_LUMINANCE_OFFSET_KHR 0x30CD /* eglQuerySurface attribute */ -#define EGL_LOWER_LEFT_KHR 0x30CE /* EGL_BITMAP_ORIGIN_KHR value */ -#define EGL_UPPER_LEFT_KHR 0x30CF /* EGL_BITMAP_ORIGIN_KHR value */ -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLBoolean EGLAPIENTRY eglLockSurfaceKHR (EGLDisplay display, EGLSurface surface, const EGLint *attrib_list); -EGLAPI EGLBoolean EGLAPIENTRY eglUnlockSurfaceKHR (EGLDisplay display, EGLSurface surface); -#endif /* EGL_EGLEXT_PROTOTYPES */ -typedef EGLBoolean (EGLAPIENTRYP PFNEGLLOCKSURFACEKHRPROC) (EGLDisplay display, EGLSurface surface, const EGLint *attrib_list); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLUNLOCKSURFACEKHRPROC) (EGLDisplay display, EGLSurface surface); -#endif +#ifndef EGL_KHR_create_context +#define EGL_KHR_create_context 1 +#define EGL_CONTEXT_MAJOR_VERSION_KHR 0x3098 +#define EGL_CONTEXT_MINOR_VERSION_KHR 0x30FB +#define EGL_CONTEXT_FLAGS_KHR 0x30FC +#define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR 0x30FD +#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR 0x31BD +#define EGL_NO_RESET_NOTIFICATION_KHR 0x31BE +#define EGL_LOSE_CONTEXT_ON_RESET_KHR 0x31BF +#define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 0x00000001 +#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002 +#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR 0x00000004 +#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 0x00000001 +#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR 0x00000002 +#define EGL_OPENGL_ES3_BIT_KHR 0x00000040 +#endif /* EGL_KHR_create_context */ -#ifndef EGL_KHR_image -#define EGL_KHR_image 1 -#define EGL_NATIVE_PIXMAP_KHR 0x30B0 /* eglCreateImageKHR target */ -typedef void *EGLImageKHR; -#define EGL_NO_IMAGE_KHR ((EGLImageKHR)0) -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLImageKHR EGLAPIENTRY eglCreateImageKHR (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list); -EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImageKHR (EGLDisplay dpy, EGLImageKHR image); -#endif /* EGL_EGLEXT_PROTOTYPES */ -typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEIMAGEKHRPROC) (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYIMAGEKHRPROC) (EGLDisplay dpy, EGLImageKHR image); -#endif +#ifndef EGL_KHR_fence_sync +#define EGL_KHR_fence_sync 1 +#ifdef KHRONOS_SUPPORT_INT64 +#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR 0x30F0 +#define EGL_SYNC_CONDITION_KHR 0x30F8 +#define EGL_SYNC_FENCE_KHR 0x30F9 +#endif /* KHRONOS_SUPPORT_INT64 */ +#endif /* EGL_KHR_fence_sync */ -#ifndef EGL_KHR_vg_parent_image -#define EGL_KHR_vg_parent_image 1 -#define EGL_VG_PARENT_IMAGE_KHR 0x30BA /* eglCreateImageKHR target */ -#endif +#ifndef EGL_KHR_get_all_proc_addresses +#define EGL_KHR_get_all_proc_addresses 1 +#endif /* EGL_KHR_get_all_proc_addresses */ -#ifndef EGL_KHR_gl_texture_2D_image -#define EGL_KHR_gl_texture_2D_image 1 -#define EGL_GL_TEXTURE_2D_KHR 0x30B1 /* eglCreateImageKHR target */ -#define EGL_GL_TEXTURE_LEVEL_KHR 0x30BC /* eglCreateImageKHR attribute */ -#endif - -#ifndef EGL_KHR_gl_texture_cubemap_image -#define EGL_KHR_gl_texture_cubemap_image 1 -#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR 0x30B3 /* eglCreateImageKHR target */ -#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR 0x30B4 /* eglCreateImageKHR target */ -#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR 0x30B5 /* eglCreateImageKHR target */ -#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR 0x30B6 /* eglCreateImageKHR target */ -#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR 0x30B7 /* eglCreateImageKHR target */ -#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR 0x30B8 /* eglCreateImageKHR target */ -#endif - -#ifndef EGL_KHR_gl_texture_3D_image -#define EGL_KHR_gl_texture_3D_image 1 -#define EGL_GL_TEXTURE_3D_KHR 0x30B2 /* eglCreateImageKHR target */ -#define EGL_GL_TEXTURE_ZOFFSET_KHR 0x30BD /* eglCreateImageKHR attribute */ -#endif +#ifndef EGL_KHR_gl_colorspace +#define EGL_KHR_gl_colorspace 1 +#define EGL_GL_COLORSPACE_KHR 0x309D +#define EGL_GL_COLORSPACE_SRGB_KHR 0x3089 +#define EGL_GL_COLORSPACE_LINEAR_KHR 0x308A +#endif /* EGL_KHR_gl_colorspace */ #ifndef EGL_KHR_gl_renderbuffer_image #define EGL_KHR_gl_renderbuffer_image 1 -#define EGL_GL_RENDERBUFFER_KHR 0x30B9 /* eglCreateImageKHR target */ -#endif +#define EGL_GL_RENDERBUFFER_KHR 0x30B9 +#endif /* EGL_KHR_gl_renderbuffer_image */ + +#ifndef EGL_KHR_gl_texture_2D_image +#define EGL_KHR_gl_texture_2D_image 1 +#define EGL_GL_TEXTURE_2D_KHR 0x30B1 +#define EGL_GL_TEXTURE_LEVEL_KHR 0x30BC +#endif /* EGL_KHR_gl_texture_2D_image */ + +#ifndef EGL_KHR_gl_texture_3D_image +#define EGL_KHR_gl_texture_3D_image 1 +#define EGL_GL_TEXTURE_3D_KHR 0x30B2 +#define EGL_GL_TEXTURE_ZOFFSET_KHR 0x30BD +#endif /* EGL_KHR_gl_texture_3D_image */ + +#ifndef EGL_KHR_gl_texture_cubemap_image +#define EGL_KHR_gl_texture_cubemap_image 1 +#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR 0x30B3 +#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR 0x30B4 +#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR 0x30B5 +#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR 0x30B6 +#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR 0x30B7 +#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR 0x30B8 +#endif /* EGL_KHR_gl_texture_cubemap_image */ + +#ifndef EGL_KHR_image +#define EGL_KHR_image 1 +typedef void *EGLImageKHR; +#define EGL_NATIVE_PIXMAP_KHR 0x30B0 +#define EGL_NO_IMAGE_KHR ((EGLImageKHR)0) +typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEIMAGEKHRPROC) (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYIMAGEKHRPROC) (EGLDisplay dpy, EGLImageKHR image); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLImageKHR EGLAPIENTRY eglCreateImageKHR (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImageKHR (EGLDisplay dpy, EGLImageKHR image); +#endif +#endif /* EGL_KHR_image */ + +#ifndef EGL_KHR_image_base +#define EGL_KHR_image_base 1 +#define EGL_IMAGE_PRESERVED_KHR 0x30D2 +#endif /* EGL_KHR_image_base */ + +#ifndef EGL_KHR_image_pixmap +#define EGL_KHR_image_pixmap 1 +#endif /* EGL_KHR_image_pixmap */ + +#ifndef EGL_KHR_lock_surface +#define EGL_KHR_lock_surface 1 +#define EGL_READ_SURFACE_BIT_KHR 0x0001 +#define EGL_WRITE_SURFACE_BIT_KHR 0x0002 +#define EGL_LOCK_SURFACE_BIT_KHR 0x0080 +#define EGL_OPTIMAL_FORMAT_BIT_KHR 0x0100 +#define EGL_MATCH_FORMAT_KHR 0x3043 +#define EGL_FORMAT_RGB_565_EXACT_KHR 0x30C0 +#define EGL_FORMAT_RGB_565_KHR 0x30C1 +#define EGL_FORMAT_RGBA_8888_EXACT_KHR 0x30C2 +#define EGL_FORMAT_RGBA_8888_KHR 0x30C3 +#define EGL_MAP_PRESERVE_PIXELS_KHR 0x30C4 +#define EGL_LOCK_USAGE_HINT_KHR 0x30C5 +#define EGL_BITMAP_POINTER_KHR 0x30C6 +#define EGL_BITMAP_PITCH_KHR 0x30C7 +#define EGL_BITMAP_ORIGIN_KHR 0x30C8 +#define EGL_BITMAP_PIXEL_RED_OFFSET_KHR 0x30C9 +#define EGL_BITMAP_PIXEL_GREEN_OFFSET_KHR 0x30CA +#define EGL_BITMAP_PIXEL_BLUE_OFFSET_KHR 0x30CB +#define EGL_BITMAP_PIXEL_ALPHA_OFFSET_KHR 0x30CC +#define EGL_BITMAP_PIXEL_LUMINANCE_OFFSET_KHR 0x30CD +#define EGL_LOWER_LEFT_KHR 0x30CE +#define EGL_UPPER_LEFT_KHR 0x30CF +typedef EGLBoolean (EGLAPIENTRYP PFNEGLLOCKSURFACEKHRPROC) (EGLDisplay dpy, EGLSurface surface, const EGLint *attrib_list); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLUNLOCKSURFACEKHRPROC) (EGLDisplay dpy, EGLSurface surface); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglLockSurfaceKHR (EGLDisplay dpy, EGLSurface surface, const EGLint *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglUnlockSurfaceKHR (EGLDisplay dpy, EGLSurface surface); +#endif +#endif /* EGL_KHR_lock_surface */ + +#ifndef EGL_KHR_lock_surface2 +#define EGL_KHR_lock_surface2 1 +#define EGL_BITMAP_PIXEL_SIZE_KHR 0x3110 +#endif /* EGL_KHR_lock_surface2 */ + +#ifndef EGL_KHR_lock_surface3 +#define EGL_KHR_lock_surface3 1 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACE64KHRPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLAttribKHR *value); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface64KHR (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLAttribKHR *value); +#endif +#endif /* EGL_KHR_lock_surface3 */ + +#ifndef EGL_KHR_platform_android +#define EGL_KHR_platform_android 1 +#define EGL_PLATFORM_ANDROID_KHR 0x3141 +#endif /* EGL_KHR_platform_android */ + +#ifndef EGL_KHR_platform_gbm +#define EGL_KHR_platform_gbm 1 +#define EGL_PLATFORM_GBM_KHR 0x31D7 +#endif /* EGL_KHR_platform_gbm */ + +#ifndef EGL_KHR_platform_wayland +#define EGL_KHR_platform_wayland 1 +#define EGL_PLATFORM_WAYLAND_KHR 0x31D8 +#endif /* EGL_KHR_platform_wayland */ + +#ifndef EGL_KHR_platform_x11 +#define EGL_KHR_platform_x11 1 +#define EGL_PLATFORM_X11_KHR 0x31D5 +#define EGL_PLATFORM_X11_SCREEN_KHR 0x31D6 +#endif /* EGL_KHR_platform_x11 */ -#if KHRONOS_SUPPORT_INT64 /* EGLTimeKHR requires 64-bit uint support */ #ifndef EGL_KHR_reusable_sync #define EGL_KHR_reusable_sync 1 - -typedef void* EGLSyncKHR; typedef khronos_utime_nanoseconds_t EGLTimeKHR; - -#define EGL_SYNC_STATUS_KHR 0x30F1 -#define EGL_SIGNALED_KHR 0x30F2 -#define EGL_UNSIGNALED_KHR 0x30F3 -#define EGL_TIMEOUT_EXPIRED_KHR 0x30F5 -#define EGL_CONDITION_SATISFIED_KHR 0x30F6 -#define EGL_SYNC_TYPE_KHR 0x30F7 -#define EGL_SYNC_REUSABLE_KHR 0x30FA -#define EGL_SYNC_FLUSH_COMMANDS_BIT_KHR 0x0001 /* eglClientWaitSyncKHR bitfield */ -#define EGL_FOREVER_KHR 0xFFFFFFFFFFFFFFFFull -#define EGL_NO_SYNC_KHR ((EGLSyncKHR)0) -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list); -EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync); -EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout); -EGLAPI EGLBoolean EGLAPIENTRY eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode); -EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value); -#endif /* EGL_EGLEXT_PROTOTYPES */ +#ifdef KHRONOS_SUPPORT_INT64 +#define EGL_SYNC_STATUS_KHR 0x30F1 +#define EGL_SIGNALED_KHR 0x30F2 +#define EGL_UNSIGNALED_KHR 0x30F3 +#define EGL_TIMEOUT_EXPIRED_KHR 0x30F5 +#define EGL_CONDITION_SATISFIED_KHR 0x30F6 +#define EGL_SYNC_TYPE_KHR 0x30F7 +#define EGL_SYNC_REUSABLE_KHR 0x30FA +#define EGL_SYNC_FLUSH_COMMANDS_BIT_KHR 0x0001 +#define EGL_FOREVER_KHR 0xFFFFFFFFFFFFFFFFull +#define EGL_NO_SYNC_KHR ((EGLSyncKHR)0) typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNCKHRPROC) (EGLDisplay dpy, EGLenum type, const EGLint *attrib_list); typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync); typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout); typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode); typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSyncKHR (EGLDisplay dpy, EGLenum type, const EGLint *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncKHR (EGLDisplay dpy, EGLSyncKHR sync); +EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout); +EGLAPI EGLBoolean EGLAPIENTRY eglSignalSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode); +EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value); #endif -#endif +#endif /* KHRONOS_SUPPORT_INT64 */ +#endif /* EGL_KHR_reusable_sync */ -#ifndef EGL_KHR_image_base -#define EGL_KHR_image_base 1 -/* Most interfaces defined by EGL_KHR_image_pixmap above */ -#define EGL_IMAGE_PRESERVED_KHR 0x30D2 /* eglCreateImageKHR attribute */ +#ifndef EGL_KHR_stream +#define EGL_KHR_stream 1 +typedef void *EGLStreamKHR; +typedef khronos_uint64_t EGLuint64KHR; +#ifdef KHRONOS_SUPPORT_INT64 +#define EGL_NO_STREAM_KHR ((EGLStreamKHR)0) +#define EGL_CONSUMER_LATENCY_USEC_KHR 0x3210 +#define EGL_PRODUCER_FRAME_KHR 0x3212 +#define EGL_CONSUMER_FRAME_KHR 0x3213 +#define EGL_STREAM_STATE_KHR 0x3214 +#define EGL_STREAM_STATE_CREATED_KHR 0x3215 +#define EGL_STREAM_STATE_CONNECTING_KHR 0x3216 +#define EGL_STREAM_STATE_EMPTY_KHR 0x3217 +#define EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR 0x3218 +#define EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR 0x3219 +#define EGL_STREAM_STATE_DISCONNECTED_KHR 0x321A +#define EGL_BAD_STREAM_KHR 0x321B +#define EGL_BAD_STATE_KHR 0x321C +typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMKHRPROC) (EGLDisplay dpy, const EGLint *attrib_list); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSTREAMKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMATTRIBKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint value); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint *value); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMU64KHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLuint64KHR *value); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLStreamKHR EGLAPIENTRY eglCreateStreamKHR (EGLDisplay dpy, const EGLint *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglDestroyStreamKHR (EGLDisplay dpy, EGLStreamKHR stream); +EGLAPI EGLBoolean EGLAPIENTRY eglStreamAttribKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint value); +EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint *value); +EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamu64KHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLuint64KHR *value); #endif +#endif /* KHRONOS_SUPPORT_INT64 */ +#endif /* EGL_KHR_stream */ -#ifndef EGL_KHR_image_pixmap -#define EGL_KHR_image_pixmap 1 -/* Interfaces defined by EGL_KHR_image above */ +#ifndef EGL_KHR_stream_consumer_gltexture +#define EGL_KHR_stream_consumer_gltexture 1 +#ifdef EGL_KHR_stream +#define EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR 0x321E +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERACQUIREKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERRELEASEKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerGLTextureExternalKHR (EGLDisplay dpy, EGLStreamKHR stream); +EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerAcquireKHR (EGLDisplay dpy, EGLStreamKHR stream); +EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerReleaseKHR (EGLDisplay dpy, EGLStreamKHR stream); #endif +#endif /* EGL_KHR_stream */ +#endif /* EGL_KHR_stream_consumer_gltexture */ + +#ifndef EGL_KHR_stream_cross_process_fd +#define EGL_KHR_stream_cross_process_fd 1 +typedef int EGLNativeFileDescriptorKHR; +#ifdef EGL_KHR_stream +#define EGL_NO_FILE_DESCRIPTOR_KHR ((EGLNativeFileDescriptorKHR)(-1)) +typedef EGLNativeFileDescriptorKHR (EGLAPIENTRYP PFNEGLGETSTREAMFILEDESCRIPTORKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream); +typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMFROMFILEDESCRIPTORKHRPROC) (EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLNativeFileDescriptorKHR EGLAPIENTRY eglGetStreamFileDescriptorKHR (EGLDisplay dpy, EGLStreamKHR stream); +EGLAPI EGLStreamKHR EGLAPIENTRY eglCreateStreamFromFileDescriptorKHR (EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor); +#endif +#endif /* EGL_KHR_stream */ +#endif /* EGL_KHR_stream_cross_process_fd */ + +#ifndef EGL_KHR_stream_fifo +#define EGL_KHR_stream_fifo 1 +#ifdef EGL_KHR_stream +#define EGL_STREAM_FIFO_LENGTH_KHR 0x31FC +#define EGL_STREAM_TIME_NOW_KHR 0x31FD +#define EGL_STREAM_TIME_CONSUMER_KHR 0x31FE +#define EGL_STREAM_TIME_PRODUCER_KHR 0x31FF +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMTIMEKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLTimeKHR *value); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamTimeKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLTimeKHR *value); +#endif +#endif /* EGL_KHR_stream */ +#endif /* EGL_KHR_stream_fifo */ + +#ifndef EGL_KHR_stream_producer_aldatalocator +#define EGL_KHR_stream_producer_aldatalocator 1 +#ifdef EGL_KHR_stream +#endif /* EGL_KHR_stream */ +#endif /* EGL_KHR_stream_producer_aldatalocator */ + +#ifndef EGL_KHR_stream_producer_eglsurface +#define EGL_KHR_stream_producer_eglsurface 1 +#ifdef EGL_KHR_stream +#define EGL_STREAM_BIT_KHR 0x0800 +typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC) (EGLDisplay dpy, EGLConfig config, EGLStreamKHR stream, const EGLint *attrib_list); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLSurface EGLAPIENTRY eglCreateStreamProducerSurfaceKHR (EGLDisplay dpy, EGLConfig config, EGLStreamKHR stream, const EGLint *attrib_list); +#endif +#endif /* EGL_KHR_stream */ +#endif /* EGL_KHR_stream_producer_eglsurface */ + +#ifndef EGL_KHR_surfaceless_context +#define EGL_KHR_surfaceless_context 1 +#endif /* EGL_KHR_surfaceless_context */ + +#ifndef EGL_KHR_vg_parent_image +#define EGL_KHR_vg_parent_image 1 +#define EGL_VG_PARENT_IMAGE_KHR 0x30BA +#endif /* EGL_KHR_vg_parent_image */ + +#ifndef EGL_KHR_wait_sync +#define EGL_KHR_wait_sync 1 +typedef EGLint (EGLAPIENTRYP PFNEGLWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLint EGLAPIENTRY eglWaitSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags); +#endif +#endif /* EGL_KHR_wait_sync */ + +#ifndef EGL_ANDROID_blob_cache +#define EGL_ANDROID_blob_cache 1 +typedef khronos_ssize_t EGLsizeiANDROID; +typedef void (*EGLSetBlobFuncANDROID) (const void *key, EGLsizeiANDROID keySize, const void *value, EGLsizeiANDROID valueSize); +typedef EGLsizeiANDROID (*EGLGetBlobFuncANDROID) (const void *key, EGLsizeiANDROID keySize, void *value, EGLsizeiANDROID valueSize); +typedef void (EGLAPIENTRYP PFNEGLSETBLOBCACHEFUNCSANDROIDPROC) (EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI void EGLAPIENTRY eglSetBlobCacheFuncsANDROID (EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get); +#endif +#endif /* EGL_ANDROID_blob_cache */ + +#ifndef EGL_ANDROID_framebuffer_target +#define EGL_ANDROID_framebuffer_target 1 +#define EGL_FRAMEBUFFER_TARGET_ANDROID 0x3147 +#endif /* EGL_ANDROID_framebuffer_target */ + +#ifndef EGL_ANDROID_image_native_buffer +#define EGL_ANDROID_image_native_buffer 1 +#define EGL_NATIVE_BUFFER_ANDROID 0x3140 +#endif /* EGL_ANDROID_image_native_buffer */ + +#ifndef EGL_ANDROID_native_fence_sync +#define EGL_ANDROID_native_fence_sync 1 +#define EGL_SYNC_NATIVE_FENCE_ANDROID 0x3144 +#define EGL_SYNC_NATIVE_FENCE_FD_ANDROID 0x3145 +#define EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID 0x3146 +#define EGL_NO_NATIVE_FENCE_FD_ANDROID -1 +typedef EGLint (EGLAPIENTRYP PFNEGLDUPNATIVEFENCEFDANDROIDPROC) (EGLDisplay dpy, EGLSyncKHR sync); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLint EGLAPIENTRY eglDupNativeFenceFDANDROID (EGLDisplay dpy, EGLSyncKHR sync); +#endif +#endif /* EGL_ANDROID_native_fence_sync */ + +#ifndef EGL_ANDROID_recordable +#define EGL_ANDROID_recordable 1 +#define EGL_RECORDABLE_ANDROID 0x3142 +#endif /* EGL_ANDROID_recordable */ + +#ifndef EGL_ANGLE_d3d_share_handle_client_buffer +#define EGL_ANGLE_d3d_share_handle_client_buffer 1 +#define EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE 0x3200 +#endif /* EGL_ANGLE_d3d_share_handle_client_buffer */ + +#ifndef EGL_ANGLE_window_fixed_size +#define EGL_ANGLE_window_fixed_size 1 +#define EGL_FIXED_SIZE_ANGLE 0x3201 +#endif /* EGL_ANGLE_window_fixed_size */ + +#ifndef EGL_ANGLE_query_surface_pointer +#define EGL_ANGLE_query_surface_pointer 1 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACEPOINTERANGLEPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE (EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value); +#endif +#endif /* EGL_ANGLE_query_surface_pointer */ + +#ifndef EGL_ANGLE_software_display +#define EGL_ANGLE_software_display 1 +#define EGL_SOFTWARE_DISPLAY_ANGLE ((EGLNativeDisplayType)-1) +#endif /* EGL_ANGLE_software_display */ + +#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 /* EGL_ANGLE_direct3d_display */ + +#ifndef EGL_ANGLE_surface_d3d_texture_2d_share_handle +#define EGL_ANGLE_surface_d3d_texture_2d_share_handle 1 +#endif /* EGL_ANGLE_surface_d3d_texture_2d_share_handle */ + +#ifndef EGL_ANGLE_platform_angle +#define EGL_ANGLE_platform_angle 1 +#define EGL_PLATFORM_ANGLE_ANGLE 0x3201 +#define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3202 +#define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3203 +#endif /* EGL_ANGLE_platform_angle */ + +#ifndef EGL_ANGLE_platform_angle_d3d +#define EGL_ANGLE_platform_angle_d3d 1 +#define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE 0x3204 +#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3205 +#define EGL_PLATFORM_ANGLE_TYPE_D3D11_WARP_ANGLE 0x3206 +#endif /* EGL_ANGLE_platform_angle_d3d */ + +#ifndef EGL_ANGLE_platform_angle_opengl +#define EGL_ANGLE_platform_angle_opengl 1 +#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x3207 +#define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x3208 +#endif /* EGL_ANGLE_platform_angle_opengl */ + +#ifndef EGL_ARM_pixmap_multisample_discard +#define EGL_ARM_pixmap_multisample_discard 1 +#define EGL_DISCARD_SAMPLES_ARM 0x3286 +#endif /* EGL_ARM_pixmap_multisample_discard */ + +#ifndef EGL_EXT_buffer_age +#define EGL_EXT_buffer_age 1 +#define EGL_BUFFER_AGE_EXT 0x313D +#endif /* EGL_EXT_buffer_age */ + +#ifndef EGL_EXT_client_extensions +#define EGL_EXT_client_extensions 1 +#endif /* EGL_EXT_client_extensions */ + +#ifndef EGL_EXT_create_context_robustness +#define EGL_EXT_create_context_robustness 1 +#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT 0x30BF +#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT 0x3138 +#define EGL_NO_RESET_NOTIFICATION_EXT 0x31BE +#define EGL_LOSE_CONTEXT_ON_RESET_EXT 0x31BF +#endif /* EGL_EXT_create_context_robustness */ + +#ifndef EGL_EXT_device_base +#define EGL_EXT_device_base 1 +typedef void *EGLDeviceEXT; +#define EGL_NO_DEVICE_EXT ((EGLDeviceEXT)(0)) +#define EGL_BAD_DEVICE_EXT 0x322B +#define EGL_DEVICE_EXT 0x322C +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDEVICEATTRIBEXTPROC) (EGLDeviceEXT device, EGLint attribute, EGLAttrib *value); +typedef const char *(EGLAPIENTRYP PFNEGLQUERYDEVICESTRINGEXTPROC) (EGLDeviceEXT device, EGLint name); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDEVICESEXTPROC) (EGLint max_devices, EGLDeviceEXT *devices, EGLint *num_devices); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDISPLAYATTRIBEXTPROC) (EGLDisplay dpy, EGLint attribute, EGLAttrib *value); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglQueryDeviceAttribEXT (EGLDeviceEXT device, EGLint attribute, EGLAttrib *value); +EGLAPI const char *EGLAPIENTRY eglQueryDeviceStringEXT (EGLDeviceEXT device, EGLint name); +EGLAPI EGLBoolean EGLAPIENTRY eglQueryDevicesEXT (EGLint max_devices, EGLDeviceEXT *devices, EGLint *num_devices); +EGLAPI EGLBoolean EGLAPIENTRY eglQueryDisplayAttribEXT (EGLDisplay dpy, EGLint attribute, EGLAttrib *value); +#endif +#endif /* EGL_EXT_device_base */ + +#ifndef EGL_EXT_image_dma_buf_import +#define EGL_EXT_image_dma_buf_import 1 +#define EGL_LINUX_DMA_BUF_EXT 0x3270 +#define EGL_LINUX_DRM_FOURCC_EXT 0x3271 +#define EGL_DMA_BUF_PLANE0_FD_EXT 0x3272 +#define EGL_DMA_BUF_PLANE0_OFFSET_EXT 0x3273 +#define EGL_DMA_BUF_PLANE0_PITCH_EXT 0x3274 +#define EGL_DMA_BUF_PLANE1_FD_EXT 0x3275 +#define EGL_DMA_BUF_PLANE1_OFFSET_EXT 0x3276 +#define EGL_DMA_BUF_PLANE1_PITCH_EXT 0x3277 +#define EGL_DMA_BUF_PLANE2_FD_EXT 0x3278 +#define EGL_DMA_BUF_PLANE2_OFFSET_EXT 0x3279 +#define EGL_DMA_BUF_PLANE2_PITCH_EXT 0x327A +#define EGL_YUV_COLOR_SPACE_HINT_EXT 0x327B +#define EGL_SAMPLE_RANGE_HINT_EXT 0x327C +#define EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT 0x327D +#define EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT 0x327E +#define EGL_ITU_REC601_EXT 0x327F +#define EGL_ITU_REC709_EXT 0x3280 +#define EGL_ITU_REC2020_EXT 0x3281 +#define EGL_YUV_FULL_RANGE_EXT 0x3282 +#define EGL_YUV_NARROW_RANGE_EXT 0x3283 +#define EGL_YUV_CHROMA_SITING_0_EXT 0x3284 +#define EGL_YUV_CHROMA_SITING_0_5_EXT 0x3285 +#endif /* EGL_EXT_image_dma_buf_import */ + +#ifndef EGL_EXT_multiview_window +#define EGL_EXT_multiview_window 1 +#define EGL_MULTIVIEW_VIEW_COUNT_EXT 0x3134 +#endif /* EGL_EXT_multiview_window */ + +#ifndef EGL_EXT_platform_base +#define EGL_EXT_platform_base 1 +typedef EGLDisplay (EGLAPIENTRYP PFNEGLGETPLATFORMDISPLAYEXTPROC) (EGLenum platform, void *native_display, const EGLint *attrib_list); +typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC) (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list); +typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPLATFORMPIXMAPSURFACEEXTPROC) (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLDisplay EGLAPIENTRY eglGetPlatformDisplayEXT (EGLenum platform, void *native_display, const EGLint *attrib_list); +EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformWindowSurfaceEXT (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list); +EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurfaceEXT (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list); +#endif +#endif /* EGL_EXT_platform_base */ + +#ifndef EGL_EXT_platform_device +#define EGL_EXT_platform_device 1 +#define EGL_PLATFORM_DEVICE_EXT 0x313F +#endif /* EGL_EXT_platform_device */ + +#ifndef EGL_EXT_platform_wayland +#define EGL_EXT_platform_wayland 1 +#define EGL_PLATFORM_WAYLAND_EXT 0x31D8 +#endif /* EGL_EXT_platform_wayland */ + +#ifndef EGL_EXT_platform_x11 +#define EGL_EXT_platform_x11 1 +#define EGL_PLATFORM_X11_EXT 0x31D5 +#define EGL_PLATFORM_X11_SCREEN_EXT 0x31D6 +#endif /* EGL_EXT_platform_x11 */ + +#ifndef EGL_EXT_protected_surface +#define EGL_EXT_protected_surface 1 +#define EGL_PROTECTED_CONTENT_EXT 0x32C0 +#endif /* EGL_EXT_protected_surface */ + +#ifndef EGL_EXT_swap_buffers_with_damage +#define EGL_EXT_swap_buffers_with_damage 1 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC) (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersWithDamageEXT (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects); +#endif +#endif /* EGL_EXT_swap_buffers_with_damage */ + +#ifndef EGL_HI_clientpixmap +#define EGL_HI_clientpixmap 1 +struct EGLClientPixmapHI { + void *pData; + EGLint iWidth; + EGLint iHeight; + EGLint iStride; +}; +#define EGL_CLIENT_PIXMAP_POINTER_HI 0x8F74 +typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPIXMAPSURFACEHIPROC) (EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI *pixmap); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurfaceHI (EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI *pixmap); +#endif +#endif /* EGL_HI_clientpixmap */ + +#ifndef EGL_HI_colorformats +#define EGL_HI_colorformats 1 +#define EGL_COLOR_FORMAT_HI 0x8F70 +#define EGL_COLOR_RGB_HI 0x8F71 +#define EGL_COLOR_RGBA_HI 0x8F72 +#define EGL_COLOR_ARGB_HI 0x8F73 +#endif /* EGL_HI_colorformats */ #ifndef EGL_IMG_context_priority #define EGL_IMG_context_priority 1 -#define EGL_CONTEXT_PRIORITY_LEVEL_IMG 0x3100 -#define EGL_CONTEXT_PRIORITY_HIGH_IMG 0x3101 -#define EGL_CONTEXT_PRIORITY_MEDIUM_IMG 0x3102 -#define EGL_CONTEXT_PRIORITY_LOW_IMG 0x3103 -#endif +#define EGL_CONTEXT_PRIORITY_LEVEL_IMG 0x3100 +#define EGL_CONTEXT_PRIORITY_HIGH_IMG 0x3101 +#define EGL_CONTEXT_PRIORITY_MEDIUM_IMG 0x3102 +#define EGL_CONTEXT_PRIORITY_LOW_IMG 0x3103 +#endif /* EGL_IMG_context_priority */ -#ifndef EGL_KHR_lock_surface2 -#define EGL_KHR_lock_surface2 1 -#define EGL_BITMAP_PIXEL_SIZE_KHR 0x3110 +#ifndef EGL_MESA_drm_image +#define EGL_MESA_drm_image 1 +#define EGL_DRM_BUFFER_FORMAT_MESA 0x31D0 +#define EGL_DRM_BUFFER_USE_MESA 0x31D1 +#define EGL_DRM_BUFFER_FORMAT_ARGB32_MESA 0x31D2 +#define EGL_DRM_BUFFER_MESA 0x31D3 +#define EGL_DRM_BUFFER_STRIDE_MESA 0x31D4 +#define EGL_DRM_BUFFER_USE_SCANOUT_MESA 0x00000001 +#define EGL_DRM_BUFFER_USE_SHARE_MESA 0x00000002 +typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEDRMIMAGEMESAPROC) (EGLDisplay dpy, const EGLint *attrib_list); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLEXPORTDRMIMAGEMESAPROC) (EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLImageKHR EGLAPIENTRY eglCreateDRMImageMESA (EGLDisplay dpy, const EGLint *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglExportDRMImageMESA (EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride); #endif +#endif /* EGL_MESA_drm_image */ + +#ifndef EGL_MESA_platform_gbm +#define EGL_MESA_platform_gbm 1 +#define EGL_PLATFORM_GBM_MESA 0x31D7 +#endif /* EGL_MESA_platform_gbm */ + +#ifndef EGL_NOK_swap_region +#define EGL_NOK_swap_region 1 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSREGIONNOKPROC) (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersRegionNOK (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects); +#endif +#endif /* EGL_NOK_swap_region */ + +#ifndef EGL_NOK_swap_region2 +#define EGL_NOK_swap_region2 1 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSREGION2NOKPROC) (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersRegion2NOK (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects); +#endif +#endif /* EGL_NOK_swap_region2 */ + +#ifndef EGL_NOK_texture_from_pixmap +#define EGL_NOK_texture_from_pixmap 1 +#define EGL_Y_INVERTED_NOK 0x307F +#endif /* EGL_NOK_texture_from_pixmap */ + +#ifndef EGL_NV_3dvision_surface +#define EGL_NV_3dvision_surface 1 +#define EGL_AUTO_STEREO_NV 0x3136 +#endif /* EGL_NV_3dvision_surface */ #ifndef EGL_NV_coverage_sample #define EGL_NV_coverage_sample 1 -#define EGL_COVERAGE_BUFFERS_NV 0x30E0 -#define EGL_COVERAGE_SAMPLES_NV 0x30E1 -#endif +#define EGL_COVERAGE_BUFFERS_NV 0x30E0 +#define EGL_COVERAGE_SAMPLES_NV 0x30E1 +#endif /* EGL_NV_coverage_sample */ + +#ifndef EGL_NV_coverage_sample_resolve +#define EGL_NV_coverage_sample_resolve 1 +#define EGL_COVERAGE_SAMPLE_RESOLVE_NV 0x3131 +#define EGL_COVERAGE_SAMPLE_RESOLVE_DEFAULT_NV 0x3132 +#define EGL_COVERAGE_SAMPLE_RESOLVE_NONE_NV 0x3133 +#endif /* EGL_NV_coverage_sample_resolve */ #ifndef EGL_NV_depth_nonlinear #define EGL_NV_depth_nonlinear 1 -#define EGL_DEPTH_ENCODING_NV 0x30E2 -#define EGL_DEPTH_ENCODING_NONE_NV 0 -#define EGL_DEPTH_ENCODING_NONLINEAR_NV 0x30E3 -#endif +#define EGL_DEPTH_ENCODING_NV 0x30E2 +#define EGL_DEPTH_ENCODING_NONE_NV 0 +#define EGL_DEPTH_ENCODING_NONLINEAR_NV 0x30E3 +#endif /* EGL_NV_depth_nonlinear */ + +#ifndef EGL_NV_native_query +#define EGL_NV_native_query 1 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEDISPLAYNVPROC) (EGLDisplay dpy, EGLNativeDisplayType *display_id); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEWINDOWNVPROC) (EGLDisplay dpy, EGLSurface surf, EGLNativeWindowType *window); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEPIXMAPNVPROC) (EGLDisplay dpy, EGLSurface surf, EGLNativePixmapType *pixmap); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativeDisplayNV (EGLDisplay dpy, EGLNativeDisplayType *display_id); +EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativeWindowNV (EGLDisplay dpy, EGLSurface surf, EGLNativeWindowType *window); +EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativePixmapNV (EGLDisplay dpy, EGLSurface surf, EGLNativePixmapType *pixmap); +#endif +#endif /* EGL_NV_native_query */ + +#ifndef EGL_NV_post_convert_rounding +#define EGL_NV_post_convert_rounding 1 +#endif /* EGL_NV_post_convert_rounding */ + +#ifndef EGL_NV_post_sub_buffer +#define EGL_NV_post_sub_buffer 1 +#define EGL_POST_SUB_BUFFER_SUPPORTED_NV 0x30BE +typedef EGLBoolean (EGLAPIENTRYP PFNEGLPOSTSUBBUFFERNVPROC) (EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglPostSubBufferNV (EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height); +#endif +#endif /* EGL_NV_post_sub_buffer */ + +#ifndef EGL_NV_stream_sync +#define EGL_NV_stream_sync 1 +#define EGL_SYNC_NEW_FRAME_NV 0x321F +typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESTREAMSYNCNVPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum type, const EGLint *attrib_list); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateStreamSyncNV (EGLDisplay dpy, EGLStreamKHR stream, EGLenum type, const EGLint *attrib_list); +#endif +#endif /* EGL_NV_stream_sync */ -#if KHRONOS_SUPPORT_INT64 /* EGLTimeNV requires 64-bit uint support */ #ifndef EGL_NV_sync #define EGL_NV_sync 1 -#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_NV 0x30E6 -#define EGL_SYNC_STATUS_NV 0x30E7 -#define EGL_SIGNALED_NV 0x30E8 -#define EGL_UNSIGNALED_NV 0x30E9 -#define EGL_SYNC_FLUSH_COMMANDS_BIT_NV 0x0001 -#define EGL_FOREVER_NV 0xFFFFFFFFFFFFFFFFull -#define EGL_ALREADY_SIGNALED_NV 0x30EA -#define EGL_TIMEOUT_EXPIRED_NV 0x30EB -#define EGL_CONDITION_SATISFIED_NV 0x30EC -#define EGL_SYNC_TYPE_NV 0x30ED -#define EGL_SYNC_CONDITION_NV 0x30EE -#define EGL_SYNC_FENCE_NV 0x30EF -#define EGL_NO_SYNC_NV ((EGLSyncNV)0) -typedef void* EGLSyncNV; +typedef void *EGLSyncNV; typedef khronos_utime_nanoseconds_t EGLTimeNV; +#ifdef KHRONOS_SUPPORT_INT64 +#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_NV 0x30E6 +#define EGL_SYNC_STATUS_NV 0x30E7 +#define EGL_SIGNALED_NV 0x30E8 +#define EGL_UNSIGNALED_NV 0x30E9 +#define EGL_SYNC_FLUSH_COMMANDS_BIT_NV 0x0001 +#define EGL_FOREVER_NV 0xFFFFFFFFFFFFFFFFull +#define EGL_ALREADY_SIGNALED_NV 0x30EA +#define EGL_TIMEOUT_EXPIRED_NV 0x30EB +#define EGL_CONDITION_SATISFIED_NV 0x30EC +#define EGL_SYNC_TYPE_NV 0x30ED +#define EGL_SYNC_CONDITION_NV 0x30EE +#define EGL_SYNC_FENCE_NV 0x30EF +#define EGL_NO_SYNC_NV ((EGLSyncNV)0) +typedef EGLSyncNV (EGLAPIENTRYP PFNEGLCREATEFENCESYNCNVPROC) (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCNVPROC) (EGLSyncNV sync); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLFENCENVPROC) (EGLSyncNV sync); +typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCNVPROC) (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCNVPROC) (EGLSyncNV sync, EGLenum mode); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBNVPROC) (EGLSyncNV sync, EGLint attribute, EGLint *value); #ifdef EGL_EGLEXT_PROTOTYPES EGLAPI EGLSyncNV EGLAPIENTRY eglCreateFenceSyncNV (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list); EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncNV (EGLSyncNV sync); @@ -214,368 +734,25 @@ EGLAPI EGLBoolean EGLAPIENTRY eglFenceNV (EGLSyncNV sync); EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncNV (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout); EGLAPI EGLBoolean EGLAPIENTRY eglSignalSyncNV (EGLSyncNV sync, EGLenum mode); EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribNV (EGLSyncNV sync, EGLint attribute, EGLint *value); -#endif /* EGL_EGLEXT_PROTOTYPES */ -typedef EGLSyncNV (EGLAPIENTRYP PFNEGLCREATEFENCESYNCNVPROC) (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCNVPROC) (EGLSyncNV sync); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLFENCENVPROC) (EGLSyncNV sync); -typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCNVPROC) (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCNVPROC) (EGLSyncNV sync, EGLenum mode); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBNVPROC) (EGLSyncNV sync, EGLint attribute, EGLint *value); -#endif #endif +#endif /* KHRONOS_SUPPORT_INT64 */ +#endif /* EGL_NV_sync */ -#if KHRONOS_SUPPORT_INT64 /* Dependent on EGL_KHR_reusable_sync which requires 64-bit uint support */ -#ifndef EGL_KHR_fence_sync -#define EGL_KHR_fence_sync 1 -/* Reuses most tokens and entry points from EGL_KHR_reusable_sync */ -#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR 0x30F0 -#define EGL_SYNC_CONDITION_KHR 0x30F8 -#define EGL_SYNC_FENCE_KHR 0x30F9 -#endif -#endif - -#ifndef EGL_HI_clientpixmap -#define EGL_HI_clientpixmap 1 - -/* Surface Attribute */ -#define EGL_CLIENT_PIXMAP_POINTER_HI 0x8F74 -/* - * Structure representing a client pixmap - * (pixmap's data is in client-space memory). - */ -struct EGLClientPixmapHI -{ - void* pData; - EGLint iWidth; - EGLint iHeight; - EGLint iStride; -}; -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurfaceHI(EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI* pixmap); -#endif /* EGL_EGLEXT_PROTOTYPES */ -typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPIXMAPSURFACEHIPROC) (EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI* pixmap); -#endif /* EGL_HI_clientpixmap */ - -#ifndef EGL_HI_colorformats -#define EGL_HI_colorformats 1 -/* Config Attribute */ -#define EGL_COLOR_FORMAT_HI 0x8F70 -/* Color Formats */ -#define EGL_COLOR_RGB_HI 0x8F71 -#define EGL_COLOR_RGBA_HI 0x8F72 -#define EGL_COLOR_ARGB_HI 0x8F73 -#endif /* EGL_HI_colorformats */ - -#ifndef EGL_MESA_drm_image -#define EGL_MESA_drm_image 1 -#define EGL_DRM_BUFFER_FORMAT_MESA 0x31D0 /* CreateDRMImageMESA attribute */ -#define EGL_DRM_BUFFER_USE_MESA 0x31D1 /* CreateDRMImageMESA attribute */ -#define EGL_DRM_BUFFER_FORMAT_ARGB32_MESA 0x31D2 /* EGL_IMAGE_FORMAT_MESA attribute value */ -#define EGL_DRM_BUFFER_MESA 0x31D3 /* eglCreateImageKHR target */ -#define EGL_DRM_BUFFER_STRIDE_MESA 0x31D4 -#define EGL_DRM_BUFFER_USE_SCANOUT_MESA 0x00000001 /* EGL_DRM_BUFFER_USE_MESA bits */ -#define EGL_DRM_BUFFER_USE_SHARE_MESA 0x00000002 /* EGL_DRM_BUFFER_USE_MESA bits */ -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLImageKHR EGLAPIENTRY eglCreateDRMImageMESA (EGLDisplay dpy, const EGLint *attrib_list); -EGLAPI EGLBoolean EGLAPIENTRY eglExportDRMImageMESA (EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride); -#endif /* EGL_EGLEXT_PROTOTYPES */ -typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEDRMIMAGEMESAPROC) (EGLDisplay dpy, const EGLint *attrib_list); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLEXPORTDRMIMAGEMESAPROC) (EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride); -#endif - -#ifndef EGL_NV_post_sub_buffer -#define EGL_NV_post_sub_buffer 1 -#define EGL_POST_SUB_BUFFER_SUPPORTED_NV 0x30BE -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLBoolean EGLAPIENTRY eglPostSubBufferNV (EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height); -#endif /* EGL_EGLEXT_PROTOTYPES */ -typedef EGLBoolean (EGLAPIENTRYP PFNEGLPOSTSUBBUFFERNVPROC) (EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height); -#endif - -#ifndef EGL_ANGLE_query_surface_pointer -#define EGL_ANGLE_query_surface_pointer 1 -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLBoolean eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value); -#endif -typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACEPOINTERANGLEPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value); -#endif - -#ifndef EGL_ANGLE_software_display -#define EGL_ANGLE_software_display 1 -#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 -#endif - -#ifndef EGL_NV_coverage_sample_resolve -#define EGL_NV_coverage_sample_resolve 1 -#define EGL_COVERAGE_SAMPLE_RESOLVE_NV 0x3131 -#define EGL_COVERAGE_SAMPLE_RESOLVE_DEFAULT_NV 0x3132 -#define EGL_COVERAGE_SAMPLE_RESOLVE_NONE_NV 0x3133 -#endif - -#if KHRONOS_SUPPORT_INT64 /* EGLuint64NV requires 64-bit uint support */ #ifndef EGL_NV_system_time #define EGL_NV_system_time 1 typedef khronos_utime_nanoseconds_t EGLuint64NV; -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeFrequencyNV(void); -EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeNV(void); -#endif /* EGL_EGLEXT_PROTOTYPES */ +#ifdef KHRONOS_SUPPORT_INT64 typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC) (void); typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMENVPROC) (void); -#endif -#endif - -#if KHRONOS_SUPPORT_INT64 /* EGLuint64KHR requires 64-bit uint support */ -#ifndef EGL_KHR_stream -#define EGL_KHR_stream 1 -typedef void* EGLStreamKHR; -typedef khronos_uint64_t EGLuint64KHR; -#define EGL_NO_STREAM_KHR ((EGLStreamKHR)0) -#define EGL_CONSUMER_LATENCY_USEC_KHR 0x3210 -#define EGL_PRODUCER_FRAME_KHR 0x3212 -#define EGL_CONSUMER_FRAME_KHR 0x3213 -#define EGL_STREAM_STATE_KHR 0x3214 -#define EGL_STREAM_STATE_CREATED_KHR 0x3215 -#define EGL_STREAM_STATE_CONNECTING_KHR 0x3216 -#define EGL_STREAM_STATE_EMPTY_KHR 0x3217 -#define EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR 0x3218 -#define EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR 0x3219 -#define EGL_STREAM_STATE_DISCONNECTED_KHR 0x321A -#define EGL_BAD_STREAM_KHR 0x321B -#define EGL_BAD_STATE_KHR 0x321C #ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLStreamKHR EGLAPIENTRY eglCreateStreamKHR(EGLDisplay dpy, const EGLint *attrib_list); -EGLAPI EGLBoolean EGLAPIENTRY eglDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream); -EGLAPI EGLBoolean EGLAPIENTRY eglStreamAttribKHR(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint value); -EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamKHR(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint *value); -EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamu64KHR(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLuint64KHR *value); -#endif /* EGL_EGLEXT_PROTOTYPES */ -typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMKHRPROC)(EGLDisplay dpy, const EGLint *attrib_list); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSTREAMKHRPROC)(EGLDisplay dpy, EGLStreamKHR stream); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMATTRIBKHRPROC)(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint value); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMKHRPROC)(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint *value); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMU64KHRPROC)(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLuint64KHR *value); -#endif -#endif - -#ifdef EGL_KHR_stream /* Requires KHR_stream extension */ -#ifndef EGL_KHR_stream_consumer_gltexture -#define EGL_KHR_stream_consumer_gltexture 1 -#define EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR 0x321E -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerGLTextureExternalKHR(EGLDisplay dpy, EGLStreamKHR stream); -EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerAcquireKHR(EGLDisplay dpy, EGLStreamKHR stream); -EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerReleaseKHR(EGLDisplay dpy, EGLStreamKHR stream); -#endif /* EGL_EGLEXT_PROTOTYPES */ -typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALKHRPROC)(EGLDisplay dpy, EGLStreamKHR stream); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERACQUIREKHRPROC)(EGLDisplay dpy, EGLStreamKHR stream); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERRELEASEKHRPROC)(EGLDisplay dpy, EGLStreamKHR stream); -#endif -#endif - -#ifdef EGL_KHR_stream /* Requires KHR_stream extension */ -#ifndef EGL_KHR_stream_producer_eglsurface -#define EGL_KHR_stream_producer_eglsurface 1 -#define EGL_STREAM_BIT_KHR 0x0800 -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLSurface EGLAPIENTRY eglCreateStreamProducerSurfaceKHR(EGLDisplay dpy, EGLConfig config, EGLStreamKHR stream, const EGLint *attrib_list); -#endif /* EGL_EGLEXT_PROTOTYPES */ -typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC)(EGLDisplay dpy, EGLConfig config, EGLStreamKHR stream, const EGLint *attrib_list); -#endif -#endif - -#ifdef EGL_KHR_stream /* Requires KHR_stream extension */ -#ifndef EGL_KHR_stream_producer_aldatalocator -#define EGL_KHR_stream_producer_aldatalocator 1 -#endif -#endif - -#ifdef EGL_KHR_stream /* Requires KHR_stream extension */ -#ifndef EGL_KHR_stream_fifo -#define EGL_KHR_stream_fifo 1 -/* reuse EGLTimeKHR */ -#define EGL_STREAM_FIFO_LENGTH_KHR 0x31FC -#define EGL_STREAM_TIME_NOW_KHR 0x31FD -#define EGL_STREAM_TIME_CONSUMER_KHR 0x31FE -#define EGL_STREAM_TIME_PRODUCER_KHR 0x31FF -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamTimeKHR(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLTimeKHR *value); -#endif /* EGL_EGLEXT_PROTOTYPES */ -typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMTIMEKHRPROC)(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLTimeKHR *value); -#endif -#endif - -#ifndef EGL_EXT_create_context_robustness -#define EGL_EXT_create_context_robustness 1 -#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT 0x30BF -#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT 0x3138 -#define EGL_NO_RESET_NOTIFICATION_EXT 0x31BE -#define EGL_LOSE_CONTEXT_ON_RESET_EXT 0x31BF -#endif - -#ifndef EGL_ANGLE_d3d_share_handle_client_buffer -#define EGL_ANGLE_d3d_share_handle_client_buffer 1 -/* reuse EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE */ -#endif - -#ifndef EGL_ANGLE_window_fixed_size -#define EGL_ANGLE_window_fixed_size 1 -#define EGL_FIXED_SIZE_ANGLE 0x3201 -#endif - -#ifndef EGL_KHR_create_context -#define EGL_KHR_create_context 1 -#define EGL_CONTEXT_MAJOR_VERSION_KHR EGL_CONTEXT_CLIENT_VERSION -#define EGL_CONTEXT_MINOR_VERSION_KHR 0x30FB -#define EGL_CONTEXT_FLAGS_KHR 0x30FC -#define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR 0x30FD -#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR 0x31BD -#define EGL_NO_RESET_NOTIFICATION_KHR 0x31BE -#define EGL_LOSE_CONTEXT_ON_RESET_KHR 0x31BF -#define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 0x00000001 -#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002 -#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR 0x00000004 -#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 0x00000001 -#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR 0x00000002 -#define EGL_OPENGL_ES3_BIT_KHR 0x00000040 -#endif - -#ifndef EGL_KHR_surfaceless_context -#define EGL_KHR_surfaceless_context 1 -/* No tokens/entry points, just relaxes an error condition */ -#endif - -#ifdef EGL_KHR_stream /* Requires KHR_stream extension */ -#ifndef EGL_KHR_stream_cross_process_fd -#define EGL_KHR_stream_cross_process_fd 1 -typedef int EGLNativeFileDescriptorKHR; -#define EGL_NO_FILE_DESCRIPTOR_KHR ((EGLNativeFileDescriptorKHR)(-1)) -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLNativeFileDescriptorKHR EGLAPIENTRY eglGetStreamFileDescriptorKHR(EGLDisplay dpy, EGLStreamKHR stream); -EGLAPI EGLStreamKHR EGLAPIENTRY eglCreateStreamFromFileDescriptorKHR(EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor); -#endif /* EGL_EGLEXT_PROTOTYPES */ -typedef EGLNativeFileDescriptorKHR (EGLAPIENTRYP PFNEGLGETSTREAMFILEDESCRIPTORKHRPROC)(EGLDisplay dpy, EGLStreamKHR stream); -typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMFROMFILEDESCRIPTORKHRPROC)(EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor); -#endif -#endif - -#ifndef EGL_EXT_multiview_window -#define EGL_EXT_multiview_window 1 -#define EGL_MULTIVIEW_VIEW_COUNT_EXT 0x3134 -#endif - -#ifndef EGL_KHR_wait_sync -#define EGL_KHR_wait_sync 1 -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLint EGLAPIENTRY eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags); -#endif /* EGL_EGLEXT_PROTOTYPES */ -typedef EGLint (EGLAPIENTRYP PFNEGLWAITSYNCKHRPROC)(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags); -#endif - -#ifndef EGL_NV_post_convert_rounding -#define EGL_NV_post_convert_rounding 1 -/* No tokens or entry points, just relaxes behavior of SwapBuffers */ -#endif - -#ifndef EGL_NV_native_query -#define EGL_NV_native_query 1 -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativeDisplayNV( EGLDisplay dpy, EGLNativeDisplayType* display_id); -EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativeWindowNV( EGLDisplay dpy, EGLSurface surf, EGLNativeWindowType* window); -EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativePixmapNV( EGLDisplay dpy, EGLSurface surf, EGLNativePixmapType* pixmap); -#endif /* EGL_EGLEXT_PROTOTYPES */ -typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEDISPLAYNVPROC)(EGLDisplay dpy, EGLNativeDisplayType *display_id); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEWINDOWNVPROC)(EGLDisplay dpy, EGLSurface surf, EGLNativeWindowType *window); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEPIXMAPNVPROC)(EGLDisplay dpy, EGLSurface surf, EGLNativePixmapType *pixmap); -#endif - -#ifndef EGL_NV_3dvision_surface -#define EGL_NV_3dvision_surface 1 -#define EGL_AUTO_STEREO_NV 0x3136 -#endif - -#ifndef EGL_ANDROID_framebuffer_target -#define EGL_ANDROID_framebuffer_target 1 -#define EGL_FRAMEBUFFER_TARGET_ANDROID 0x3147 -#endif - -#ifndef EGL_ANDROID_blob_cache -#define EGL_ANDROID_blob_cache 1 -typedef khronos_ssize_t EGLsizeiANDROID; -typedef void (*EGLSetBlobFuncANDROID) (const void *key, EGLsizeiANDROID keySize, const void *value, EGLsizeiANDROID valueSize); -typedef EGLsizeiANDROID (*EGLGetBlobFuncANDROID) (const void *key, EGLsizeiANDROID keySize, void *value, EGLsizeiANDROID valueSize); -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI void EGLAPIENTRY eglSetBlobCacheFuncsANDROID(EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get); -#endif /* EGL_EGLEXT_PROTOTYPES */ -typedef void (EGLAPIENTRYP PFNEGLSETBLOBCACHEFUNCSANDROIDPROC)(EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get); -#endif - -#ifndef EGL_ANDROID_image_native_buffer -#define EGL_ANDROID_image_native_buffer 1 -#define EGL_NATIVE_BUFFER_ANDROID 0x3140 -#endif - -#ifndef EGL_ANDROID_native_fence_sync -#define EGL_ANDROID_native_fence_sync 1 -#define EGL_SYNC_NATIVE_FENCE_ANDROID 0x3144 -#define EGL_SYNC_NATIVE_FENCE_FD_ANDROID 0x3145 -#define EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID 0x3146 -#define EGL_NO_NATIVE_FENCE_FD_ANDROID -1 -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLint EGLAPIENTRY eglDupNativeFenceFDANDROID( EGLDisplay dpy, EGLSyncKHR); -#endif /* EGL_EGLEXT_PROTOTYPES */ -typedef EGLint (EGLAPIENTRYP PFNEGLDUPNATIVEFENCEFDANDROIDPROC)(EGLDisplay dpy, EGLSyncKHR); -#endif - -#ifndef EGL_ANDROID_recordable -#define EGL_ANDROID_recordable 1 -#define EGL_RECORDABLE_ANDROID 0x3142 -#endif - -#ifndef EGL_EXT_buffer_age -#define EGL_EXT_buffer_age 1 -#define EGL_BUFFER_AGE_EXT 0x313D -#endif - -#ifndef EGL_EXT_image_dma_buf_import -#define EGL_EXT_image_dma_buf_import 1 -#define EGL_LINUX_DMA_BUF_EXT 0x3270 -#define EGL_LINUX_DRM_FOURCC_EXT 0x3271 -#define EGL_DMA_BUF_PLANE0_FD_EXT 0x3272 -#define EGL_DMA_BUF_PLANE0_OFFSET_EXT 0x3273 -#define EGL_DMA_BUF_PLANE0_PITCH_EXT 0x3274 -#define EGL_DMA_BUF_PLANE1_FD_EXT 0x3275 -#define EGL_DMA_BUF_PLANE1_OFFSET_EXT 0x3276 -#define EGL_DMA_BUF_PLANE1_PITCH_EXT 0x3277 -#define EGL_DMA_BUF_PLANE2_FD_EXT 0x3278 -#define EGL_DMA_BUF_PLANE2_OFFSET_EXT 0x3279 -#define EGL_DMA_BUF_PLANE2_PITCH_EXT 0x327A -#define EGL_YUV_COLOR_SPACE_HINT_EXT 0x327B -#define EGL_SAMPLE_RANGE_HINT_EXT 0x327C -#define EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT 0x327D -#define EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT 0x327E -#define EGL_ITU_REC601_EXT 0x327F -#define EGL_ITU_REC709_EXT 0x3280 -#define EGL_ITU_REC2020_EXT 0x3281 -#define EGL_YUV_FULL_RANGE_EXT 0x3282 -#define EGL_YUV_NARROW_RANGE_EXT 0x3283 -#define EGL_YUV_CHROMA_SITING_0_EXT 0x3284 -#define EGL_YUV_CHROMA_SITING_0_5_EXT 0x3285 +EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeFrequencyNV (void); +EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeNV (void); #endif +#endif /* KHRONOS_SUPPORT_INT64 */ +#endif /* EGL_NV_system_time */ #ifdef __cplusplus } #endif -#endif /* __eglext_h_ */ +#endif diff --git a/gfx/angle/include/EGL/eglplatform.h b/gfx/angle/include/EGL/eglplatform.h index 9a89420ebf93..3ab8844f09c1 100644 --- a/gfx/angle/include/EGL/eglplatform.h +++ b/gfx/angle/include/EGL/eglplatform.h @@ -2,7 +2,7 @@ #define __eglplatform_h_ /* -** Copyright (c) 2007-2009 The Khronos Group Inc. +** Copyright (c) 2007-2013 The Khronos Group Inc. ** ** Permission is hereby granted, free of charge, to any person obtaining a ** copy of this software and/or associated documentation files (the @@ -25,7 +25,7 @@ */ /* Platform-specific types and definitions for egl.h - * $Revision: 12306 $ on $Date: 2010-08-25 12:51:28 -0400 (Wed, 25 Aug 2010) $ + * $Revision: 23432 $ on $Date: 2013-10-09 00:57:24 -0700 (Wed, 09 Oct 2013) $ * * Adopters may modify khrplatform.h and this file to suit their platform. * You are encouraged to submit all modifications to the Khronos group so that @@ -83,6 +83,16 @@ typedef int EGLNativeDisplayType; typedef void *EGLNativeWindowType; typedef void *EGLNativePixmapType; +#elif defined(__ANDROID__) || defined(ANDROID) + +#include + +struct egl_native_pixmap_t; + +typedef struct ANativeWindow* EGLNativeWindowType; +typedef struct egl_native_pixmap_t* EGLNativePixmapType; +typedef void* EGLNativeDisplayType; + #elif defined(__unix__) /* X11 (tentative) */ diff --git a/gfx/angle/include/GLSLANG/ShaderLang.h b/gfx/angle/include/GLSLANG/ShaderLang.h index c38fdae96cd1..b7989f5f7ed9 100644 --- a/gfx/angle/include/GLSLANG/ShaderLang.h +++ b/gfx/angle/include/GLSLANG/ShaderLang.h @@ -23,32 +23,32 @@ #define COMPILER_EXPORT #endif -#include "KHR/khrplatform.h" #include +#include "KHR/khrplatform.h" + // // This is the platform independent interface between an OGL driver // and the shading language compiler. // +namespace sh +{ +// GLenum alias +typedef unsigned int GLenum; +} + +// Must be included after GLenum proxy typedef +// Note: make sure to increment ANGLE_SH_VERSION when changing ShaderVars.h +#include "ShaderVars.h" + #ifdef __cplusplus extern "C" { #endif // Version number for shader translation API. // It is incremented every time the API changes. -#define ANGLE_SH_VERSION 125 - -// -// The names of the following enums have been derived by replacing GL prefix -// with SH. For example, SH_INFO_LOG_LENGTH is equivalent to GL_INFO_LOG_LENGTH. -// The enum values are also equal to the values of their GL counterpart. This -// is done to make it easier for applications to use the shader library. -// -typedef enum { - SH_FRAGMENT_SHADER = 0x8B30, - SH_VERTEX_SHADER = 0x8B31 -} ShShaderType; +#define ANGLE_SH_VERSION 130 typedef enum { SH_GLES2_SPEC = 0x8B40, @@ -85,52 +85,6 @@ typedef enum { SH_HLSL11_OUTPUT = 0x8B48 } ShShaderOutput; -typedef enum { - SH_NONE = 0, - SH_INT = 0x1404, - SH_UNSIGNED_INT = 0x1405, - SH_FLOAT = 0x1406, - SH_FLOAT_VEC2 = 0x8B50, - SH_FLOAT_VEC3 = 0x8B51, - SH_FLOAT_VEC4 = 0x8B52, - SH_INT_VEC2 = 0x8B53, - SH_INT_VEC3 = 0x8B54, - SH_INT_VEC4 = 0x8B55, - SH_UNSIGNED_INT_VEC2 = 0x8DC6, - SH_UNSIGNED_INT_VEC3 = 0x8DC7, - SH_UNSIGNED_INT_VEC4 = 0x8DC8, - SH_BOOL = 0x8B56, - SH_BOOL_VEC2 = 0x8B57, - SH_BOOL_VEC3 = 0x8B58, - SH_BOOL_VEC4 = 0x8B59, - SH_FLOAT_MAT2 = 0x8B5A, - SH_FLOAT_MAT3 = 0x8B5B, - SH_FLOAT_MAT4 = 0x8B5C, - SH_FLOAT_MAT2x3 = 0x8B65, - SH_FLOAT_MAT2x4 = 0x8B66, - SH_FLOAT_MAT3x2 = 0x8B67, - SH_FLOAT_MAT3x4 = 0x8B68, - SH_FLOAT_MAT4x2 = 0x8B69, - SH_FLOAT_MAT4x3 = 0x8B6A, - SH_SAMPLER_2D = 0x8B5E, - SH_SAMPLER_3D = 0x8B5F, - SH_SAMPLER_CUBE = 0x8B60, - SH_SAMPLER_2D_RECT_ARB = 0x8B63, - SH_SAMPLER_EXTERNAL_OES = 0x8D66, - SH_SAMPLER_2D_ARRAY = 0x8DC1, - SH_INT_SAMPLER_2D = 0x8DCA, - SH_INT_SAMPLER_3D = 0x8DCB, - SH_INT_SAMPLER_CUBE = 0x8DCC, - SH_INT_SAMPLER_2D_ARRAY = 0x8DCF, - SH_UNSIGNED_INT_SAMPLER_2D = 0x8DD2, - SH_UNSIGNED_INT_SAMPLER_3D = 0x8DD3, - SH_UNSIGNED_INT_SAMPLER_CUBE = 0x8DD4, - SH_UNSIGNED_INT_SAMPLER_2D_ARRAY = 0x8DD7, - SH_SAMPLER_2D_SHADOW = 0x8B62, - SH_SAMPLER_CUBE_SHADOW = 0x8DC5, - SH_SAMPLER_2D_ARRAY_SHADOW = 0x8DC4 -} ShDataType; - typedef enum { SH_PRECISION_HIGHP = 0x5001, SH_PRECISION_MEDIUMP = 0x5002, @@ -151,14 +105,9 @@ typedef enum { SH_NAME_MAX_LENGTH = 0x6001, SH_HASHED_NAME_MAX_LENGTH = 0x6002, SH_HASHED_NAMES_COUNT = 0x6003, - SH_ACTIVE_UNIFORMS_ARRAY = 0x6004, - SH_SHADER_VERSION = 0x6005, - SH_ACTIVE_INTERFACE_BLOCKS_ARRAY = 0x6006, - SH_ACTIVE_OUTPUT_VARIABLES_ARRAY = 0x6007, - SH_ACTIVE_ATTRIBUTES_ARRAY = 0x6008, - SH_ACTIVE_VARYINGS_ARRAY = 0x6009, - SH_RESOURCES_STRING_LENGTH = 0x600A, - SH_OUTPUT_TYPE = 0x600B + SH_SHADER_VERSION = 0x6004, + SH_RESOURCES_STRING_LENGTH = 0x6005, + SH_OUTPUT_TYPE = 0x6006 } ShShaderInfo; // Compile options. @@ -193,7 +142,7 @@ typedef enum { // This flag only has an effect if all of the following are true: // - The shader spec is SH_WEBGL_SPEC. // - The compile options contain the SH_TIMING_RESTRICTIONS flag. - // - The shader type is SH_FRAGMENT_SHADER. + // - The shader type is GL_FRAGMENT_SHADER. SH_DEPENDENCY_GRAPH = 0x0400, // Enforce the GLSL 1.017 Appendix A section 7 packing restrictions. @@ -236,6 +185,15 @@ typedef enum { // It is intended as a workaround for drivers which incorrectly optimize // out such varyings and cause a link failure. SH_INIT_VARYINGS_WITHOUT_STATIC_USE = 0x20000, + + // This flag scalarizes vec/ivec/bvec/mat constructor args. + // It is intended as a workaround for Linux/Mac driver bugs. + SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS = 0x40000, + + // This flag overwrites a struct name with a unique prefix. + // It is intended as a workaround for drivers that do not handle + // struct scopes correctly, including all Mac drivers and Linux AMD. + SH_REGENERATE_STRUCT_NAMES = 0x80000, } ShCompileOptions; // Defines alternate strategies for implementing array index clamping. @@ -345,14 +303,14 @@ COMPILER_EXPORT void ShGetBuiltInResourcesString(const ShHandle handle, size_t o // Returns the handle of constructed compiler, null if the requested compiler is // not supported. // Parameters: -// type: Specifies the type of shader - SH_FRAGMENT_SHADER or SH_VERTEX_SHADER. +// type: Specifies the type of shader - GL_FRAGMENT_SHADER or GL_VERTEX_SHADER. // 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, // SH_HLSL9_OUTPUT or SH_HLSL11_OUTPUT. // resources: Specifies the built-in resources. COMPILER_EXPORT ShHandle ShConstructCompiler( - ShShaderType type, + sh::GLenum type, ShShaderSpec spec, ShShaderOutput output, const ShBuiltInResources* resources); @@ -476,7 +434,7 @@ COMPILER_EXPORT void ShGetVariableInfo(const ShHandle handle, int index, size_t* length, int* size, - ShDataType* type, + sh::GLenum* type, ShPrecisionType* precision, int* staticUse, char* name, @@ -500,21 +458,21 @@ COMPILER_EXPORT void ShGetNameHashingEntry(const ShHandle handle, char* name, char* hashedName); -// Returns a parameter from a compiled shader. +// Shader variable inspection. +// Returns a pointer to a list of variables of the designated type. +// (See ShaderVars.h for type definitions, included above) +// Returns NULL on failure. // 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); +COMPILER_EXPORT const std::vector *ShGetUniforms(const ShHandle handle); +COMPILER_EXPORT const std::vector *ShGetVaryings(const ShHandle handle); +COMPILER_EXPORT const std::vector *ShGetAttributes(const ShHandle handle); +COMPILER_EXPORT const std::vector *ShGetOutputVariables(const ShHandle handle); +COMPILER_EXPORT const std::vector *ShGetInterfaceBlocks(const ShHandle handle); typedef struct { - ShDataType type; + sh::GLenum type; int size; } ShVariableInfo; @@ -531,6 +489,29 @@ COMPILER_EXPORT int ShCheckVariablesWithinPackingLimits( ShVariableInfo* varInfoArray, size_t varInfoArraySize); +// Gives the compiler-assigned register for an interface block. +// The method writes the value to the output variable "indexOut". +// Returns true if it found a valid interface block, false otherwise. +// Parameters: +// handle: Specifies the compiler +// interfaceBlockName: Specifies the interface block +// indexOut: output variable that stores the assigned register +COMPILER_EXPORT bool ShGetInterfaceBlockRegister(const ShHandle handle, + const char *interfaceBlockName, + unsigned int *indexOut); + +// Gives the compiler-assigned register for uniforms in the default +// interface block. +// The method writes the value to the output variable "indexOut". +// Returns true if it found a valid default uniform, false otherwise. +// Parameters: +// handle: Specifies the compiler +// interfaceBlockName: Specifies the uniform +// indexOut: output variable that stores the assigned register +COMPILER_EXPORT bool ShGetUniformRegister(const ShHandle handle, + const char *uniformName, + unsigned int *indexOut); + #ifdef __cplusplus } #endif diff --git a/gfx/angle/include/GLSLANG/ShaderVars.h b/gfx/angle/include/GLSLANG/ShaderVars.h new file mode 100644 index 000000000000..9c38647dda67 --- /dev/null +++ b/gfx/angle/include/GLSLANG/ShaderVars.h @@ -0,0 +1,123 @@ +// +// Copyright (c) 2013-2014 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. +// +// ShaderVars.h: +// Types to represent GL variables (varyings, uniforms, etc) +// + +#ifndef _COMPILER_INTERFACE_VARIABLES_ +#define _COMPILER_INTERFACE_VARIABLES_ + +#include +#include +#include + +// Assume ShaderLang.h is included before ShaderVars.h, for sh::GLenum +// Note: make sure to increment ANGLE_SH_VERSION when changing ShaderVars.h + +namespace sh +{ + +// Varying interpolation qualifier, see section 4.3.9 of the ESSL 3.00.4 spec +enum InterpolationType +{ + INTERPOLATION_SMOOTH, + INTERPOLATION_CENTROID, + INTERPOLATION_FLAT +}; + +// Uniform block layout qualifier, see section 4.3.8.3 of the ESSL 3.00.4 spec +enum BlockLayoutType +{ + BLOCKLAYOUT_STANDARD, + BLOCKLAYOUT_PACKED, + BLOCKLAYOUT_SHARED +}; + +// Base class for all variables defined in shaders, including Varyings, Uniforms, etc +// Note: we must override the copy constructor and assignment operator so we can +// work around excessive GCC binary bloating: +// See https://code.google.com/p/angleproject/issues/detail?id=697 +struct COMPILER_EXPORT ShaderVariable +{ + ShaderVariable(); + ShaderVariable(GLenum typeIn, unsigned int arraySizeIn); + ~ShaderVariable(); + ShaderVariable(const ShaderVariable &other); + ShaderVariable &operator=(const ShaderVariable &other); + + bool isArray() const { return arraySize > 0; } + unsigned int elementCount() const { return std::max(1u, arraySize); } + bool isStruct() const { return !fields.empty(); } + + GLenum type; + GLenum precision; + std::string name; + std::string mappedName; + unsigned int arraySize; + bool staticUse; + std::vector fields; + std::string structName; +}; + +struct COMPILER_EXPORT Uniform : public ShaderVariable +{ + Uniform(); + ~Uniform(); + Uniform(const Uniform &other); + Uniform &operator=(const Uniform &other); +}; + +struct COMPILER_EXPORT Attribute : public ShaderVariable +{ + Attribute(); + ~Attribute(); + Attribute(const Attribute &other); + Attribute &operator=(const Attribute &other); + + int location; +}; + +struct COMPILER_EXPORT InterfaceBlockField : public ShaderVariable +{ + InterfaceBlockField(); + ~InterfaceBlockField(); + InterfaceBlockField(const InterfaceBlockField &other); + InterfaceBlockField &operator=(const InterfaceBlockField &other); + + bool isRowMajorLayout; +}; + +struct COMPILER_EXPORT Varying : public ShaderVariable +{ + Varying(); + ~Varying(); + Varying(const Varying &other); + Varying &operator=(const Varying &other); + + InterpolationType interpolation; + bool isInvariant; +}; + +struct COMPILER_EXPORT InterfaceBlock +{ + InterfaceBlock(); + ~InterfaceBlock(); + InterfaceBlock(const InterfaceBlock &other); + InterfaceBlock &operator=(const InterfaceBlock &other); + + std::string name; + std::string mappedName; + std::string instanceName; + unsigned int arraySize; + BlockLayoutType layout; + bool isRowMajorLayout; + bool staticUse; + std::vector fields; +}; + +} + +#endif // _COMPILER_INTERFACE_VARIABLES_ diff --git a/gfx/angle/include/KHR/khrplatform.h b/gfx/angle/include/KHR/khrplatform.h old mode 100644 new mode 100755 diff --git a/gfx/angle/include/angle_gl.h b/gfx/angle/include/angle_gl.h new file mode 100644 index 000000000000..d093f75ee294 --- /dev/null +++ b/gfx/angle/include/angle_gl.h @@ -0,0 +1,23 @@ +// +// Copyright (c) 2014 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. +// +// angle_gl.h: +// Includes all necessary GL headers and definitions for ANGLE. +// + +#ifndef ANGLE_GL_H_ +#define ANGLE_GL_H_ + +#include "GLES2/gl2.h" +#include "GLES2/gl2ext.h" +#include "GLES3/gl3.h" +#include "GLES3/gl3ext.h" + +// The following enum is used in ANGLE, but is from desktop GL +#ifndef GL_SAMPLER_2D_RECT_ARB +#define GL_SAMPLER_2D_RECT_ARB 0x8B63 +#endif + +#endif // ANGLE_GL_H_ diff --git a/gfx/angle/moz.build b/gfx/angle/moz.build index c8da8f0c5a8f..36ecd4990dc9 100644 --- a/gfx/angle/moz.build +++ b/gfx/angle/moz.build @@ -7,6 +7,7 @@ UNIFIED_SOURCES += [ 'src/common/event_tracer.cpp', 'src/common/mathutil.cpp', 'src/common/RefCountObject.cpp', + 'src/common/tls.cpp', 'src/common/utilities.cpp', 'src/compiler/preprocessor/DiagnosticsBase.cpp', 'src/compiler/preprocessor/DirectiveHandlerBase.cpp', @@ -39,6 +40,7 @@ UNIFIED_SOURCES += [ 'src/compiler/translator/InitializeParseContext.cpp', 'src/compiler/translator/InitializeVariables.cpp', 'src/compiler/translator/Intermediate.cpp', + 'src/compiler/translator/IntermNode.cpp', 'src/compiler/translator/intermOut.cpp', 'src/compiler/translator/IntermTraverse.cpp', 'src/compiler/translator/LoopInfo.cpp', @@ -50,10 +52,14 @@ UNIFIED_SOURCES += [ 'src/compiler/translator/ParseContext.cpp', 'src/compiler/translator/PoolAlloc.cpp', 'src/compiler/translator/QualifierAlive.cpp', + 'src/compiler/translator/RegenerateStructNames.cpp', 'src/compiler/translator/RemoveTree.cpp', 'src/compiler/translator/RewriteElseBlocks.cpp', + 'src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp', 'src/compiler/translator/SearchSymbol.cpp', 'src/compiler/translator/ShaderLang.cpp', + 'src/compiler/translator/ShaderVars.cpp', + 'src/compiler/translator/StructureHLSL.cpp', 'src/compiler/translator/SymbolTable.cpp', 'src/compiler/translator/timing/RestrictFragmentShaderTiming.cpp', 'src/compiler/translator/timing/RestrictVertexShaderTiming.cpp', @@ -63,7 +69,9 @@ UNIFIED_SOURCES += [ 'src/compiler/translator/Types.cpp', 'src/compiler/translator/UnfoldShortCircuit.cpp', 'src/compiler/translator/UnfoldShortCircuitAST.cpp', + 'src/compiler/translator/UniformHLSL.cpp', 'src/compiler/translator/util.cpp', + 'src/compiler/translator/UtilsHLSL.cpp', 'src/compiler/translator/ValidateLimitations.cpp', 'src/compiler/translator/ValidateOutputs.cpp', 'src/compiler/translator/VariableInfo.cpp', @@ -75,26 +83,6 @@ SOURCES += [ 'src/compiler/translator/glslang_lex.cpp', 'src/compiler/translator/glslang_tab.cpp', ] -if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gonk'): - UNIFIED_SOURCES += [ - 'src/compiler/translator/ossource_posix.cpp', - ] -if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa': - UNIFIED_SOURCES += [ - 'src/compiler/translator/ossource_posix.cpp', - ] -if CONFIG['MOZ_WIDGET_GTK']: - UNIFIED_SOURCES += [ - 'src/compiler/translator/ossource_posix.cpp', - ] -if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'qt': - UNIFIED_SOURCES += [ - 'src/compiler/translator/ossource_posix.cpp', - ] -if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': - UNIFIED_SOURCES += [ - 'src/compiler/translator/ossource_win.cpp', - ] if CONFIG['GNU_CXX']: @@ -136,7 +124,7 @@ DISABLE_STL_WRAPPING = True if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': DIRS += [ 'src/libGLESv2', 'src/libEGL' ] -EXPORTS.angle += [ 'include/GLSLANG/ShaderLang.h' ] +EXPORTS.angle += [ 'include/GLSLANG/ShaderLang.h', 'include/GLSLANG/ShaderVars.h' ] EXPORTS.angle.KHR += [ 'include/KHR/khrplatform.h' ] LOCAL_INCLUDES += [ 'include', 'src' ] diff --git a/gfx/angle/src/angle.gypi b/gfx/angle/src/angle.gypi index 5339369f41c2..09f70ffa0561 100644 --- a/gfx/angle/src/angle.gypi +++ b/gfx/angle/src/angle.gypi @@ -7,6 +7,12 @@ { 'angle_code': 1, 'angle_post_build_script%': 0, + 'angle_gen_path': '<(SHARED_INTERMEDIATE_DIR)/angle', + 'angle_id_script_base': 'commit_id.py', + 'angle_id_script': '<(angle_gen_path)/<(angle_id_script_base)', + 'angle_id_header_base': 'commit.h', + 'angle_id_header': '<(angle_gen_path)/id/<(angle_id_header_base)', + 'angle_use_commit_id%': ' %1%\commit.h - -REM commit hash size -set _Str=#define ANGLE_COMMIT_HASH_SIZE 12 -echo %_Str% >> %1%\commit.h - -REM commit date -(FOR /F "delims=" %%i IN ('call git show -s --format^="%%ci" HEAD') DO set _Str=%%i) || (set _Str=Unknown Date) -set _Str=#define ANGLE_COMMIT_DATE "%_Str%" -echo %_Str% >> %1%\commit.h diff --git a/gfx/angle/src/commit_id.py b/gfx/angle/src/commit_id.py index 6339cca3f2cc..7f711e75a623 100644 --- a/gfx/angle/src/commit_id.py +++ b/gfx/angle/src/commit_id.py @@ -1,19 +1,35 @@ import subprocess as sp import sys +import os -def grab_output(*command): - return sp.Popen(command, stdout=sp.PIPE).communicate()[0].strip() +# Usage: commit_id.py check (checks if git is present) +# Usage: commit_id.py gen (generates commit id) +def grab_output(command, cwd): + return sp.Popen(command, stdout=sp.PIPE, shell=True, cwd=cwd).communicate()[0].strip() + +operation = sys.argv[1] +cwd = sys.argv[2] + +if operation == 'check': + index_path = os.path.join(cwd, '.git', 'index') + if os.path.exists(index_path): + print("1") + else: + print("0") + sys.exit(0) + +output_file = sys.argv[3] commit_id_size = 12 try: - commit_id = grab_output('git', 'rev-parse', '--short=%d' % commit_id_size, 'HEAD') - commit_date = grab_output('git', 'show', '-s', '--format=%ci', 'HEAD') + commit_id = grab_output('git rev-parse --short=%d HEAD' % commit_id_size, cwd) + commit_date = grab_output('git show -s --format=%ci HEAD', cwd) except: commit_id = 'invalid-hash' commit_date = 'invalid-date' -hfile = open(sys.argv[1], 'w') +hfile = open(output_file, 'w') hfile.write('#define ANGLE_COMMIT_HASH "%s"\n' % commit_id) hfile.write('#define ANGLE_COMMIT_HASH_SIZE %d\n' % commit_id_size) diff --git a/gfx/angle/src/common/RefCountObject.h b/gfx/angle/src/common/RefCountObject.h index 88b639312249..6eeaee1928ee 100644 --- a/gfx/angle/src/common/RefCountObject.h +++ b/gfx/angle/src/common/RefCountObject.h @@ -12,13 +12,12 @@ #ifndef COMMON_REFCOUNTOBJECT_H_ #define COMMON_REFCOUNTOBJECT_H_ -#include - -#include -#include - #include "common/debug.h" +#include "angle_gl.h" + +#include + class RefCountObject { public: @@ -62,33 +61,6 @@ class BindingPointer : public RefCountObjectBindingPointer ObjectType *operator->() const { return get(); } }; -template -class FramebufferTextureBindingPointer : public RefCountObjectBindingPointer -{ -public: - FramebufferTextureBindingPointer() : mType(GL_NONE), mMipLevel(0), mLayer(0) { } - - void set(ObjectType *newObject, GLenum type, GLint mipLevel, GLint layer) - { - RefCountObjectBindingPointer::set(newObject); - mType = type; - mMipLevel = mipLevel; - mLayer = layer; - } - - ObjectType *get() const { return static_cast(RefCountObjectBindingPointer::get()); } - ObjectType *operator->() const { return get(); } - - GLenum type() const { return mType; } - GLint mipLevel() const { return mMipLevel; } - GLint layer() const { return mLayer; } - -private: - GLenum mType; - GLint mMipLevel; - GLint mLayer; -}; - template class OffsetBindingPointer : public RefCountObjectBindingPointer { diff --git a/gfx/angle/src/common/angleutils.cpp b/gfx/angle/src/common/angleutils.cpp new file mode 100644 index 000000000000..2673abf30acb --- /dev/null +++ b/gfx/angle/src/common/angleutils.cpp @@ -0,0 +1,37 @@ +// +// Copyright (c) 2014 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 "common/angleutils.h" + +#include + +std::string FormatString(const char *fmt, va_list vararg) +{ + static std::vector buffer(512); + + // Attempt to just print to the current buffer + int len = vsnprintf(&buffer[0], buffer.size(), fmt, vararg); + if (len < 0 || static_cast(len) >= buffer.size()) + { + // Buffer was not large enough, calculate the required size and resize the buffer + len = vsnprintf(NULL, 0, fmt, vararg); + buffer.resize(len + 1); + + // Print again + vsnprintf(&buffer[0], buffer.size(), fmt, vararg); + } + + return std::string(buffer.data(), len); +} + +std::string FormatString(const char *fmt, ...) +{ + va_list vararg; + va_start(vararg, fmt); + std::string result = FormatString(fmt, vararg); + va_end(vararg); + return result; +} diff --git a/gfx/angle/src/common/angleutils.h b/gfx/angle/src/common/angleutils.h index 58f6494163df..50a4132a9aa3 100644 --- a/gfx/angle/src/common/angleutils.h +++ b/gfx/angle/src/common/angleutils.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2014 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,7 +9,14 @@ #ifndef COMMON_ANGLEUTILS_H_ #define COMMON_ANGLEUTILS_H_ +#include "common/platform.h" + #include +#include +#include +#include +#include +#include // A macro to disallow the copy constructor and operator= functions // This must be used in the private: declarations for a class @@ -17,19 +24,8 @@ TypeName(const TypeName&); \ void operator=(const TypeName&) -// Macros for writing try catch blocks. Defining ANGLE_NO_EXCEPTIONS -// when building angle will disable the usage of try/catch for compilers -// without proper support for them (such as clang-cl). -#ifdef ANGLE_NO_EXCEPTIONS -#define ANGLE_TRY if (true) -#define ANGLE_CATCH_ALL else -#else -#define ANGLE_TRY try -#define ANGLE_CATCH_ALL catch(...) -#endif - -template -inline unsigned int ArraySize(T(&)[N]) +template +inline size_t ArraySize(T(&)[N]) { return N; } @@ -60,6 +56,16 @@ void SafeDelete(T*& resource) resource = NULL; } +template +void SafeDeleteContainer(T& resource) +{ + for (typename T::iterator i = resource.begin(); i != resource.end(); i++) + { + SafeDelete(*i); + } + resource.clear(); +} + template void SafeDeleteArray(T*& resource) { @@ -89,6 +95,46 @@ inline void StructZero(T *obj) memset(obj, 0, sizeof(T)); } +inline const char* MakeStaticString(const std::string &str) +{ + static std::set strings; + std::set::iterator it = strings.find(str); + if (it != strings.end()) + { + return it->c_str(); + } + + return strings.insert(str).first->c_str(); +} + +inline std::string ArrayString(unsigned int i) +{ + // We assume UINT_MAX and GL_INVALID_INDEX are equal + // See DynamicHLSL.cpp + if (i == UINT_MAX) + { + return ""; + } + + std::stringstream strstr; + + strstr << "["; + strstr << i; + strstr << "]"; + + return strstr.str(); +} + +inline std::string Str(int i) +{ + std::stringstream strstr; + strstr << i; + return strstr.str(); +} + +std::string FormatString(const char *fmt, va_list vararg); +std::string FormatString(const char *fmt, ...); + #if defined(_MSC_VER) #define snprintf _snprintf #endif diff --git a/gfx/angle/src/common/blocklayout.cpp b/gfx/angle/src/common/blocklayout.cpp index a0c9289d7906..e3b2d43566c9 100644 --- a/gfx/angle/src/common/blocklayout.cpp +++ b/gfx/angle/src/common/blocklayout.cpp @@ -8,62 +8,18 @@ // #include "common/blocklayout.h" -#include "common/shadervars.h" #include "common/mathutil.h" #include "common/utilities.h" -namespace gl +namespace sh { -BlockLayoutEncoder::BlockLayoutEncoder(std::vector *blockInfoOut) - : mCurrentOffset(0), - mBlockInfoOut(blockInfoOut) +BlockLayoutEncoder::BlockLayoutEncoder() + : mCurrentOffset(0) { } -void BlockLayoutEncoder::encodeInterfaceBlockFields(const std::vector &fields) -{ - for (unsigned int fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++) - { - const InterfaceBlockField &variable = fields[fieldIndex]; - - if (variable.fields.size() > 0) - { - const unsigned int elementCount = std::max(1u, variable.arraySize); - - for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++) - { - enterAggregateType(); - encodeInterfaceBlockFields(variable.fields); - exitAggregateType(); - } - } - else - { - encodeInterfaceBlockField(variable); - } - } -} - -void BlockLayoutEncoder::encodeInterfaceBlockField(const InterfaceBlockField &field) -{ - int arrayStride; - int matrixStride; - - ASSERT(field.fields.empty()); - getBlockLayoutInfo(field.type, field.arraySize, field.isRowMajorMatrix, &arrayStride, &matrixStride); - - const BlockMemberInfo memberInfo(mCurrentOffset * BytesPerComponent, arrayStride * BytesPerComponent, matrixStride * BytesPerComponent, field.isRowMajorMatrix); - - if (mBlockInfoOut) - { - mBlockInfoOut->push_back(memberInfo); - } - - advanceOffset(field.type, field.arraySize, field.isRowMajorMatrix, arrayStride, matrixStride); -} - -void BlockLayoutEncoder::encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix) +BlockMemberInfo BlockLayoutEncoder::encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix) { int arrayStride; int matrixStride; @@ -72,12 +28,9 @@ void BlockLayoutEncoder::encodeType(GLenum type, unsigned int arraySize, bool is const BlockMemberInfo memberInfo(mCurrentOffset * BytesPerComponent, arrayStride * BytesPerComponent, matrixStride * BytesPerComponent, isRowMajorMatrix); - if (mBlockInfoOut) - { - mBlockInfoOut->push_back(memberInfo); - } - advanceOffset(type, arraySize, isRowMajorMatrix, arrayStride, matrixStride); + + return memberInfo; } void BlockLayoutEncoder::nextRegister() @@ -85,8 +38,7 @@ void BlockLayoutEncoder::nextRegister() mCurrentOffset = rx::roundUp(mCurrentOffset, ComponentsPerRegister); } -Std140BlockEncoder::Std140BlockEncoder(std::vector *blockInfoOut) - : BlockLayoutEncoder(blockInfoOut) +Std140BlockEncoder::Std140BlockEncoder() { } @@ -103,7 +55,7 @@ void Std140BlockEncoder::exitAggregateType() void Std140BlockEncoder::getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut) { // We assume we are only dealing with 4 byte components (no doubles or half-words currently) - ASSERT(gl::UniformComponentSize(gl::UniformComponentType(type)) == BytesPerComponent); + ASSERT(gl::VariableComponentSize(gl::VariableComponentType(type)) == BytesPerComponent); size_t baseAlignment = 0; int matrixStride = 0; @@ -127,7 +79,7 @@ void Std140BlockEncoder::getBlockLayoutInfo(GLenum type, unsigned int arraySize, } else { - const int numComponents = gl::UniformComponentCount(type); + const int numComponents = gl::VariableComponentCount(type); baseAlignment = (numComponents == 3 ? 4u : static_cast(numComponents)); } @@ -151,13 +103,12 @@ void Std140BlockEncoder::advanceOffset(GLenum type, unsigned int arraySize, bool } else { - mCurrentOffset += gl::UniformComponentCount(type); + mCurrentOffset += gl::VariableComponentCount(type); } } -HLSLBlockEncoder::HLSLBlockEncoder(std::vector *blockInfoOut, HLSLBlockEncoderStrategy strategy) - : BlockLayoutEncoder(blockInfoOut), - mEncoderStrategy(strategy) +HLSLBlockEncoder::HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy) + : mEncoderStrategy(strategy) { } @@ -173,7 +124,7 @@ void HLSLBlockEncoder::exitAggregateType() void HLSLBlockEncoder::getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut) { // We assume we are only dealing with 4 byte components (no doubles or half-words currently) - ASSERT(gl::UniformComponentSize(gl::UniformComponentType(type)) == BytesPerComponent); + ASSERT(gl::VariableComponentSize(gl::VariableComponentType(type)) == BytesPerComponent); int matrixStride = 0; int arrayStride = 0; @@ -204,7 +155,7 @@ void HLSLBlockEncoder::getBlockLayoutInfo(GLenum type, unsigned int arraySize, b } else if (isPacked()) { - int numComponents = gl::UniformComponentCount(type); + int numComponents = gl::VariableComponentCount(type); if ((numComponents + (mCurrentOffset % ComponentsPerRegister)) > ComponentsPerRegister) { nextRegister(); @@ -232,7 +183,7 @@ void HLSLBlockEncoder::advanceOffset(GLenum type, unsigned int arraySize, bool i } else if (isPacked()) { - mCurrentOffset += gl::UniformComponentCount(type); + mCurrentOffset += gl::VariableComponentCount(type); } else { @@ -245,50 +196,14 @@ void HLSLBlockEncoder::skipRegisters(unsigned int numRegisters) mCurrentOffset += (numRegisters * ComponentsPerRegister); } -void HLSLVariableGetRegisterInfo(unsigned int baseRegisterIndex, gl::Uniform *variable, HLSLBlockEncoder *encoder, - const std::vector &blockInfo, ShShaderOutput outputType) +HLSLBlockEncoder::HLSLBlockEncoderStrategy HLSLBlockEncoder::GetStrategyFor(ShShaderOutput outputType) { - // because this method computes offsets (element indexes) instead of any total sizes, - // we can ignore the array size of the variable - - if (variable->isStruct()) + switch (outputType) { - encoder->enterAggregateType(); - - variable->registerIndex = baseRegisterIndex; - - for (size_t fieldIndex = 0; fieldIndex < variable->fields.size(); fieldIndex++) - { - HLSLVariableGetRegisterInfo(baseRegisterIndex, &variable->fields[fieldIndex], encoder, blockInfo, outputType); - } - - // Since the above loop only encodes one element of an array, ensure we don't lose track of the - // current register offset - if (variable->isArray()) - { - unsigned int structRegisterCount = (HLSLVariableRegisterCount(*variable, outputType) / variable->arraySize); - encoder->skipRegisters(structRegisterCount * (variable->arraySize - 1)); - } - - encoder->exitAggregateType(); + case SH_HLSL9_OUTPUT: return ENCODE_LOOSE; + case SH_HLSL11_OUTPUT: return ENCODE_PACKED; + default: UNREACHABLE(); return ENCODE_PACKED; } - else - { - encoder->encodeType(variable->type, variable->arraySize, false); - - const size_t registerBytes = (encoder->BytesPerComponent * encoder->ComponentsPerRegister); - variable->registerIndex = baseRegisterIndex + (blockInfo.back().offset / registerBytes); - variable->elementIndex = (blockInfo.back().offset % registerBytes) / sizeof(float); - } -} - -void HLSLVariableGetRegisterInfo(unsigned int baseRegisterIndex, gl::Uniform *variable, ShShaderOutput outputType) -{ - std::vector blockInfo; - HLSLBlockEncoder encoder(&blockInfo, - outputType == SH_HLSL9_OUTPUT ? HLSLBlockEncoder::ENCODE_LOOSE - : HLSLBlockEncoder::ENCODE_PACKED); - HLSLVariableGetRegisterInfo(baseRegisterIndex, variable, &encoder, blockInfo, outputType); } template @@ -317,7 +232,7 @@ void HLSLVariableRegisterCount(const ShaderVarType &variable, HLSLBlockEncoder * unsigned int HLSLVariableRegisterCount(const Varying &variable) { - HLSLBlockEncoder encoder(NULL, HLSLBlockEncoder::ENCODE_PACKED); + HLSLBlockEncoder encoder(HLSLBlockEncoder::ENCODE_PACKED); HLSLVariableRegisterCount(variable, &encoder); const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister); @@ -326,10 +241,7 @@ unsigned int HLSLVariableRegisterCount(const Varying &variable) unsigned int HLSLVariableRegisterCount(const Uniform &variable, ShShaderOutput outputType) { - HLSLBlockEncoder encoder(NULL, - outputType == SH_HLSL9_OUTPUT ? HLSLBlockEncoder::ENCODE_LOOSE - : HLSLBlockEncoder::ENCODE_PACKED); - + HLSLBlockEncoder encoder(HLSLBlockEncoder::GetStrategyFor(outputType)); HLSLVariableRegisterCount(variable, &encoder); const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister); diff --git a/gfx/angle/src/common/blocklayout.h b/gfx/angle/src/common/blocklayout.h index e6ffff1a9e55..d46ac6e5474b 100644 --- a/gfx/angle/src/common/blocklayout.h +++ b/gfx/angle/src/common/blocklayout.h @@ -10,30 +10,53 @@ #ifndef COMMON_BLOCKLAYOUT_H_ #define COMMON_BLOCKLAYOUT_H_ -#include -#include -#include -#include #include +#include -namespace gl +#include "angle_gl.h" +#include + +namespace sh { - struct ShaderVariable; struct InterfaceBlockField; -struct BlockMemberInfo; struct Uniform; struct Varying; +struct InterfaceBlock; + +struct BlockMemberInfo +{ + BlockMemberInfo(int offset, int arrayStride, int matrixStride, bool isRowMajorMatrix) + : offset(offset), + arrayStride(arrayStride), + matrixStride(matrixStride), + isRowMajorMatrix(isRowMajorMatrix) + {} + + static BlockMemberInfo getDefaultBlockInfo() + { + return BlockMemberInfo(-1, -1, -1, false); + } + + int offset; + int arrayStride; + int matrixStride; + bool isRowMajorMatrix; +}; class BlockLayoutEncoder { public: - BlockLayoutEncoder(std::vector *blockInfoOut); + BlockLayoutEncoder(); + + BlockMemberInfo encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix); - void encodeInterfaceBlockFields(const std::vector &fields); - void encodeInterfaceBlockField(const InterfaceBlockField &field); - void encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix); size_t getBlockSize() const { return mCurrentOffset * BytesPerComponent; } + size_t getCurrentRegister() const { return mCurrentOffset / ComponentsPerRegister; } + size_t getCurrentElement() const { return mCurrentOffset % ComponentsPerRegister; } + + virtual void enterAggregateType() = 0; + virtual void exitAggregateType() = 0; static const size_t BytesPerComponent = 4u; static const unsigned int ComponentsPerRegister = 4u; @@ -43,13 +66,8 @@ class BlockLayoutEncoder void nextRegister(); - virtual void enterAggregateType() = 0; - virtual void exitAggregateType() = 0; virtual void getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut) = 0; virtual void advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride) = 0; - - private: - std::vector *mBlockInfoOut; }; // Block layout according to the std140 block layout @@ -58,18 +76,19 @@ class BlockLayoutEncoder class Std140BlockEncoder : public BlockLayoutEncoder { public: - Std140BlockEncoder(std::vector *blockInfoOut); + Std140BlockEncoder(); - protected: virtual void enterAggregateType(); virtual void exitAggregateType(); + + protected: virtual void getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut); virtual void advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride); }; // Block layout packed according to the D3D9 or default D3D10+ register packing rules // See http://msdn.microsoft.com/en-us/library/windows/desktop/bb509632(v=vs.85).aspx -// The strategy should be ENCODE_LOOSE for D3D9 constnat blocks, and ENCODE_PACKED +// The strategy should be ENCODE_LOOSE for D3D9 constant blocks, and ENCODE_PACKED // for everything else (D3D10+ constant blocks and all attributes/varyings). class HLSLBlockEncoder : public BlockLayoutEncoder @@ -81,8 +100,7 @@ class HLSLBlockEncoder : public BlockLayoutEncoder ENCODE_LOOSE }; - HLSLBlockEncoder(std::vector *blockInfoOut, - HLSLBlockEncoderStrategy strategy); + HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy); virtual void enterAggregateType(); virtual void exitAggregateType(); @@ -90,6 +108,8 @@ class HLSLBlockEncoder : public BlockLayoutEncoder bool isPacked() const { return mEncoderStrategy == ENCODE_PACKED; } + static HLSLBlockEncoderStrategy GetStrategyFor(ShShaderOutput outputType); + protected: virtual void getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut); virtual void advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride); @@ -97,10 +117,6 @@ class HLSLBlockEncoder : public BlockLayoutEncoder HLSLBlockEncoderStrategy mEncoderStrategy; }; -// This method assigns values to the variable's "registerIndex" and "elementIndex" fields. -// "elementIndex" is only used for structures. -void HLSLVariableGetRegisterInfo(unsigned int baseRegisterIndex, Uniform *variable, ShShaderOutput outputType); - // This method returns the number of used registers for a ShaderVariable. It is dependent on the HLSLBlockEncoder // class to count the number of used registers in a struct (which are individually packed according to the same rules). unsigned int HLSLVariableRegisterCount(const Varying &variable); diff --git a/gfx/angle/src/common/debug.cpp b/gfx/angle/src/common/debug.cpp index ac0a86ae2ef5..dcad32756404 100644 --- a/gfx/angle/src/common/debug.cpp +++ b/gfx/angle/src/common/debug.cpp @@ -7,15 +7,14 @@ // debug.cpp: Debugging utilities. #include "common/debug.h" +#include "common/platform.h" +#include "common/angleutils.h" + #include #include #include #include -#if defined(ANGLE_ENABLE_PERF) -#include -#endif - namespace gl { #if defined(ANGLE_ENABLE_PERF) @@ -27,22 +26,7 @@ typedef void (*PerfOutputFunction)(unsigned int, const wchar_t*); static void output(bool traceFileDebugOnly, PerfOutputFunction perfFunc, const char *format, va_list vararg) { #if defined(ANGLE_ENABLE_PERF) || defined(ANGLE_ENABLE_TRACE) - static std::vector asciiMessageBuffer(512); - - // Attempt to just print to the current buffer - int len = vsnprintf(&asciiMessageBuffer[0], asciiMessageBuffer.size(), format, vararg); - if (len < 0 || static_cast(len) >= asciiMessageBuffer.size()) - { - // Buffer was not large enough, calculate the required size and resize the buffer - len = vsnprintf(NULL, 0, format, vararg); - asciiMessageBuffer.resize(len + 1); - - // Print again - vsnprintf(&asciiMessageBuffer[0], asciiMessageBuffer.size(), format, vararg); - } - - // NULL terminate the buffer to be safe - asciiMessageBuffer[len] = '\0'; + std::string formattedMessage = FormatString(format, vararg); #endif #if defined(ANGLE_ENABLE_PERF) @@ -50,12 +34,12 @@ static void output(bool traceFileDebugOnly, PerfOutputFunction perfFunc, const c { // The perf function only accepts wide strings, widen the ascii message static std::wstring wideMessage; - if (wideMessage.capacity() < asciiMessageBuffer.size()) + if (wideMessage.capacity() < formattedMessage.length()) { - wideMessage.reserve(asciiMessageBuffer.size()); + wideMessage.reserve(formattedMessage.size()); } - wideMessage.assign(asciiMessageBuffer.begin(), asciiMessageBuffer.begin() + len); + wideMessage.assign(formattedMessage.begin(), formattedMessage.end()); perfFunc(0, wideMessage.c_str()); } @@ -72,7 +56,7 @@ static void output(bool traceFileDebugOnly, PerfOutputFunction perfFunc, const c static std::ofstream file(TRACE_OUTPUT_FILE, std::ofstream::app); if (file) { - file.write(&asciiMessageBuffer[0], len); + file.write(formattedMessage.c_str(), formattedMessage.length()); file.flush(); } diff --git a/gfx/angle/src/common/debug.h b/gfx/angle/src/common/debug.h index 09cd249f8cd4..997ebca6be0d 100644 --- a/gfx/angle/src/common/debug.h +++ b/gfx/angle/src/common/debug.h @@ -83,6 +83,12 @@ namespace gl #define UNUSED_ASSERTION_VARIABLE(variable) ((void)variable) #endif +#ifndef ANGLE_ENABLE_TRACE +#define UNUSED_TRACE_VARIABLE(variable) ((void)variable) +#else +#define UNUSED_TRACE_VARIABLE(variable) +#endif + // A macro to indicate unimplemented functionality // Define NOASSERT_UNIMPLEMENTED to non zero to skip the assert fail in the unimplemented checks diff --git a/gfx/angle/src/common/event_tracer.h b/gfx/angle/src/common/event_tracer.h index 14b7b298fd84..fa97435faac4 100644 --- a/gfx/angle/src/common/event_tracer.h +++ b/gfx/angle/src/common/event_tracer.h @@ -5,12 +5,14 @@ #ifndef COMMON_EVENT_TRACER_H_ #define COMMON_EVENT_TRACER_H_ +#include "common/platform.h" + #if !defined(TRACE_ENTRY) -#if defined(_WIN32) -#define TRACE_ENTRY __stdcall -#else -#define TRACE_ENTRY -#endif // // _WIN32 +# ifdef ANGLE_PLATFORM_WINDOWS +# define TRACE_ENTRY __stdcall +# else +# define TRACE_ENTRY +# endif // ANGLE_PLATFORM_WINDOWS #endif //TRACE_ENTRY extern "C" { diff --git a/gfx/angle/src/common/mathutil.cpp b/gfx/angle/src/common/mathutil.cpp index 20b3f0c113a5..496633632bf1 100644 --- a/gfx/angle/src/common/mathutil.cpp +++ b/gfx/angle/src/common/mathutil.cpp @@ -7,6 +7,7 @@ // mathutil.cpp: Math and bit manipulation functions. #include "common/mathutil.h" + #include #include diff --git a/gfx/angle/src/common/mathutil.h b/gfx/angle/src/common/mathutil.h index 2d36631b4114..9e7a8de17f1a 100644 --- a/gfx/angle/src/common/mathutil.h +++ b/gfx/angle/src/common/mathutil.h @@ -10,10 +10,7 @@ #define LIBGLESV2_MATHUTIL_H_ #include "common/debug.h" - -#if defined(_WIN32) -#include -#endif +#include "common/platform.h" #include #include @@ -112,7 +109,7 @@ inline unsigned int unorm(float x) inline bool supportsSSE2() { -#if defined(_WIN32) +#ifdef ANGLE_PLATFORM_WINDOWS static bool checked = false; static bool supports = false; @@ -506,21 +503,33 @@ inline unsigned int averageFloat10(unsigned int a, unsigned int b) namespace rx { +template struct Range { Range() {} - Range(int lo, int hi) : start(lo), end(hi) { ASSERT(lo <= hi); } + Range(T lo, T hi) : start(lo), end(hi) { } - int start; - int end; + T start; + T end; + + T length() const { return (end > start ? (end - start) : 0); } }; +typedef Range RangeI; +typedef Range RangeUI; + template T roundUp(const T value, const T alignment) { return value + alignment - 1 - (value - 1) % alignment; } +inline unsigned int UnsignedCeilDivide(unsigned int value, unsigned int divisor) +{ + unsigned int divided = value / divisor; + return (divided + ((value % divisor == 0) ? 0 : 1)); +} + template inline bool IsUnsignedAdditionSafe(T lhs, T rhs) { diff --git a/gfx/angle/src/common/platform.h b/gfx/angle/src/common/platform.h new file mode 100644 index 000000000000..d07297dfd4b4 --- /dev/null +++ b/gfx/angle/src/common/platform.h @@ -0,0 +1,67 @@ +// +// Copyright (c) 2014 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. +// + +// platform.h: Operating system specific includes and defines. + +#ifndef COMMON_PLATFORM_H_ +#define COMMON_PLATFORM_H_ + +#if defined(_WIN32) || defined(_WIN64) +# define ANGLE_PLATFORM_WINDOWS 1 +#elif defined(__APPLE__) +# define ANGLE_PLATFORM_APPLE 1 +# define ANGLE_PLATFORM_POSIX 1 +#elif defined(__linux__) +# define ANGLE_PLATFORM_LINUX 1 +# define ANGLE_PLATFORM_POSIX 1 +#elif defined(ANDROID) +# define ANGLE_PLATFORM_ANDROID 1 +# define ANGLE_PLATFORM_POSIX 1 +#elif defined(__FreeBSD__) || \ + defined(__OpenBSD__) || \ + defined(__NetBSD__) || \ + defined(__DragonFly__) || \ + defined(__sun) || \ + defined(__GLIBC__) || \ + defined(__GNU__) || \ + defined(__QNX__) +# define ANGLE_PLATFORM_POSIX 1 +#else +# error Unsupported platform. +#endif + +#ifdef ANGLE_PLATFORM_WINDOWS +# ifndef STRICT +# define STRICT 1 +# endif +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN 1 +# endif +# ifndef NOMINMAX +# define NOMINMAX 1 +# endif + +# include +# include + +# if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_PERF) +# include +# include +# endif + +# if defined(ANGLE_ENABLE_D3D11) +# include +# include +# include +# include +# include +# endif + +# undef near +# undef far +#endif + +#endif // COMMON_PLATFORM_H_ diff --git a/gfx/angle/src/common/shadervars.h b/gfx/angle/src/common/shadervars.h deleted file mode 100644 index 99187a0dc19d..000000000000 --- a/gfx/angle/src/common/shadervars.h +++ /dev/null @@ -1,162 +0,0 @@ -// -// Copyright (c) 2013-2014 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. -// -// shadervars.h: -// Types to represent GL variables (varyings, uniforms, etc) -// - -#ifndef COMMON_SHADERVARIABLE_H_ -#define COMMON_SHADERVARIABLE_H_ - -#include -#include -#include - -#include -#include - -namespace gl -{ - -// Varying interpolation qualifier, see section 4.3.9 of the ESSL 3.00.4 spec -enum InterpolationType -{ - INTERPOLATION_SMOOTH, - INTERPOLATION_CENTROID, - INTERPOLATION_FLAT -}; - -// Uniform block layout qualifier, see section 4.3.8.3 of the ESSL 3.00.4 spec -enum BlockLayoutType -{ - BLOCKLAYOUT_STANDARD, - BLOCKLAYOUT_PACKED, - BLOCKLAYOUT_SHARED -}; - -// Base class for all variables defined in shaders, including Varyings, Uniforms, etc -struct ShaderVariable -{ - GLenum type; - GLenum precision; - std::string name; - unsigned int arraySize; - - ShaderVariable(GLenum typeIn, GLenum precisionIn, const char *nameIn, unsigned int arraySizeIn) - : type(typeIn), - precision(precisionIn), - name(nameIn), - arraySize(arraySizeIn) - {} - - bool isArray() const { return arraySize > 0; } - unsigned int elementCount() const { return std::max(1u, arraySize); } -}; - -// Uniform registers (and element indices) are assigned when outputting shader code -struct Uniform : public ShaderVariable -{ - unsigned int registerIndex; - unsigned int elementIndex; // Offset within a register, for struct members - std::vector fields; - - Uniform(GLenum typeIn, GLenum precisionIn, const char *nameIn, unsigned int arraySizeIn, - unsigned int registerIndexIn, unsigned int elementIndexIn) - : ShaderVariable(typeIn, precisionIn, nameIn, arraySizeIn), - registerIndex(registerIndexIn), - elementIndex(elementIndexIn) - {} - - bool isStruct() const { return !fields.empty(); } -}; - -struct Attribute : public ShaderVariable -{ - int location; - - Attribute() - : ShaderVariable(GL_NONE, GL_NONE, "", 0), - location(-1) - {} - - Attribute(GLenum typeIn, GLenum precisionIn, const char *nameIn, unsigned int arraySizeIn, int locationIn) - : ShaderVariable(typeIn, precisionIn, nameIn, arraySizeIn), - location(locationIn) - {} -}; - -struct InterfaceBlockField : public ShaderVariable -{ - bool isRowMajorMatrix; - std::vector fields; - - InterfaceBlockField(GLenum typeIn, GLenum precisionIn, const char *nameIn, unsigned int arraySizeIn, bool isRowMajorMatrix) - : ShaderVariable(typeIn, precisionIn, nameIn, arraySizeIn), - isRowMajorMatrix(isRowMajorMatrix) - {} - - bool isStruct() const { return !fields.empty(); } -}; - -struct Varying : public ShaderVariable -{ - InterpolationType interpolation; - std::vector fields; - std::string structName; - - Varying(GLenum typeIn, GLenum precisionIn, const char *nameIn, unsigned int arraySizeIn, InterpolationType interpolationIn) - : ShaderVariable(typeIn, precisionIn, nameIn, arraySizeIn), - interpolation(interpolationIn) - {} - - bool isStruct() const { return !fields.empty(); } -}; - -struct BlockMemberInfo -{ - int offset; - int arrayStride; - int matrixStride; - bool isRowMajorMatrix; - - static BlockMemberInfo getDefaultBlockInfo() - { - return BlockMemberInfo(-1, -1, -1, false); - } - - BlockMemberInfo(int offset, int arrayStride, int matrixStride, bool isRowMajorMatrix) - : offset(offset), - arrayStride(arrayStride), - matrixStride(matrixStride), - isRowMajorMatrix(isRowMajorMatrix) - {} -}; - -typedef std::vector BlockMemberInfoArray; - -struct InterfaceBlock -{ - std::string name; - unsigned int arraySize; - size_t dataSize; - BlockLayoutType layout; - bool isRowMajorLayout; - std::vector fields; - std::vector blockInfo; - - unsigned int registerIndex; - - InterfaceBlock(const char *name, unsigned int arraySize, unsigned int registerIndex) - : name(name), - arraySize(arraySize), - layout(BLOCKLAYOUT_SHARED), - registerIndex(registerIndex), - isRowMajorLayout(false) - {} -}; - -} - -#endif // COMMON_SHADERVARIABLE_H_ diff --git a/gfx/angle/src/common/tls.cpp b/gfx/angle/src/common/tls.cpp new file mode 100644 index 000000000000..6b7821978557 --- /dev/null +++ b/gfx/angle/src/common/tls.cpp @@ -0,0 +1,74 @@ +// +// Copyright (c) 2014 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. +// + +// tls.cpp: Simple cross-platform interface for thread local storage. + +#include "common/tls.h" + +#include + +TLSIndex CreateTLSIndex() +{ + TLSIndex index; + +#ifdef ANGLE_PLATFORM_WINDOWS + index = TlsAlloc(); +#elif defined(ANGLE_PLATFORM_POSIX) + // Create global pool key + if ((pthread_key_create(&index, NULL)) != 0) + { + index = TLS_INVALID_INDEX; + } +#endif + + assert(index != TLS_INVALID_INDEX && "CreateTLSIndex(): Unable to allocate Thread Local Storage"); + return index; +} + +bool DestroyTLSIndex(TLSIndex index) +{ + assert(index != TLS_INVALID_INDEX && "DestroyTLSIndex(): Invalid TLS Index"); + if (index == TLS_INVALID_INDEX) + { + return false; + } + +#ifdef ANGLE_PLATFORM_WINDOWS + return (TlsFree(index) == TRUE); +#elif defined(ANGLE_PLATFORM_POSIX) + return (pthread_key_delete(index) == 0); +#endif +} + +bool SetTLSValue(TLSIndex index, void *value) +{ + assert(index != TLS_INVALID_INDEX && "SetTLSValue(): Invalid TLS Index"); + if (index == TLS_INVALID_INDEX) + { + return false; + } + +#ifdef ANGLE_PLATFORM_WINDOWS + return (TlsSetValue(index, value) == TRUE); +#elif defined(ANGLE_PLATFORM_POSIX) + return (pthread_setspecific(index, value) == 0); +#endif +} + +void *GetTLSValue(TLSIndex index) +{ + assert(index != TLS_INVALID_INDEX && "GetTLSValue(): Invalid TLS Index"); + if (index == TLS_INVALID_INDEX) + { + return NULL; + } + +#ifdef ANGLE_PLATFORM_WINDOWS + return TlsGetValue(index); +#elif defined(ANGLE_PLATFORM_POSIX) + return pthread_getspecific(index); +#endif +} diff --git a/gfx/angle/src/common/tls.h b/gfx/angle/src/common/tls.h new file mode 100644 index 000000000000..4b25fbc597d9 --- /dev/null +++ b/gfx/angle/src/common/tls.h @@ -0,0 +1,33 @@ +// +// Copyright (c) 2014 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. +// + +// tls.h: Simple cross-platform interface for thread local storage. + +#ifndef COMMON_TLS_H_ +#define COMMON_TLS_H_ + +#include "common/platform.h" + +#ifdef ANGLE_PLATFORM_WINDOWS + typedef DWORD TLSIndex; +# define TLS_INVALID_INDEX (TLS_OUT_OF_INDEXES) +#elif defined(ANGLE_PLATFORM_POSIX) +# include +# include +# include + typedef pthread_key_t TLSIndex; +# define TLS_INVALID_INDEX (static_cast(-1)) +#else +# error Unsupported platform. +#endif + +TLSIndex CreateTLSIndex(); +bool DestroyTLSIndex(TLSIndex index); + +bool SetTLSValue(TLSIndex index, void *value); +void *GetTLSValue(TLSIndex index); + +#endif // COMMON_TLS_H_ diff --git a/gfx/angle/src/common/utilities.cpp b/gfx/angle/src/common/utilities.cpp index b1e989bbf640..405f119c5198 100644 --- a/gfx/angle/src/common/utilities.cpp +++ b/gfx/angle/src/common/utilities.cpp @@ -8,77 +8,19 @@ #include "common/utilities.h" #include "common/mathutil.h" - -#if defined(_WIN32) -#include -#endif +#include "common/platform.h" #include namespace gl { -int UniformComponentCount(GLenum type) +int VariableComponentCount(GLenum type) { - switch (type) - { - case GL_BOOL: - case GL_FLOAT: - case GL_INT: - case GL_SAMPLER_2D: - case GL_SAMPLER_3D: - case GL_SAMPLER_CUBE: - case GL_SAMPLER_2D_ARRAY: - case GL_INT_SAMPLER_2D: - case GL_INT_SAMPLER_3D: - case GL_INT_SAMPLER_CUBE: - case GL_INT_SAMPLER_2D_ARRAY: - case GL_UNSIGNED_INT_SAMPLER_2D: - case GL_UNSIGNED_INT_SAMPLER_3D: - case GL_UNSIGNED_INT_SAMPLER_CUBE: - case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: - case GL_SAMPLER_2D_SHADOW: - case GL_SAMPLER_CUBE_SHADOW: - case GL_SAMPLER_2D_ARRAY_SHADOW: - case GL_UNSIGNED_INT: - return 1; - case GL_BOOL_VEC2: - case GL_FLOAT_VEC2: - case GL_INT_VEC2: - case GL_UNSIGNED_INT_VEC2: - return 2; - case GL_INT_VEC3: - case GL_FLOAT_VEC3: - case GL_BOOL_VEC3: - case GL_UNSIGNED_INT_VEC3: - return 3; - case GL_BOOL_VEC4: - case GL_FLOAT_VEC4: - case GL_INT_VEC4: - case GL_UNSIGNED_INT_VEC4: - case GL_FLOAT_MAT2: - return 4; - case GL_FLOAT_MAT2x3: - case GL_FLOAT_MAT3x2: - return 6; - case GL_FLOAT_MAT2x4: - case GL_FLOAT_MAT4x2: - return 8; - case GL_FLOAT_MAT3: - return 9; - case GL_FLOAT_MAT3x4: - case GL_FLOAT_MAT4x3: - return 12; - case GL_FLOAT_MAT4: - return 16; - default: - UNREACHABLE(); - } - - return 0; + return VariableRowCount(type) * VariableColumnCount(type); } -GLenum UniformComponentType(GLenum type) +GLenum VariableComponentType(GLenum type) { switch(type) { @@ -133,7 +75,7 @@ GLenum UniformComponentType(GLenum type) return GL_NONE; } -size_t UniformComponentSize(GLenum type) +size_t VariableComponentSize(GLenum type) { switch(type) { @@ -147,18 +89,18 @@ size_t UniformComponentSize(GLenum type) return 0; } -size_t UniformInternalSize(GLenum type) +size_t VariableInternalSize(GLenum type) { // Expanded to 4-element vectors - return UniformComponentSize(UniformComponentType(type)) * VariableRowCount(type) * 4; + return VariableComponentSize(VariableComponentType(type)) * VariableRowCount(type) * 4; } -size_t UniformExternalSize(GLenum type) +size_t VariableExternalSize(GLenum type) { - return UniformComponentSize(UniformComponentType(type)) * UniformComponentCount(type); + return VariableComponentSize(VariableComponentType(type)) * VariableComponentCount(type); } -GLenum UniformBoolVectorType(GLenum type) +GLenum VariableBoolVectorType(GLenum type) { switch (type) { @@ -212,6 +154,8 @@ int VariableRowCount(GLenum type) case GL_SAMPLER_3D: case GL_SAMPLER_CUBE: case GL_SAMPLER_2D_ARRAY: + case GL_SAMPLER_EXTERNAL_OES: + case GL_SAMPLER_2D_RECT_ARB: case GL_INT_SAMPLER_2D: case GL_INT_SAMPLER_3D: case GL_INT_SAMPLER_CUBE: @@ -262,6 +206,8 @@ int VariableColumnCount(GLenum type) case GL_INT_SAMPLER_3D: case GL_INT_SAMPLER_CUBE: case GL_INT_SAMPLER_2D_ARRAY: + case GL_SAMPLER_EXTERNAL_OES: + case GL_SAMPLER_2D_RECT_ARB: case GL_UNSIGNED_INT_SAMPLER_2D: case GL_UNSIGNED_INT_SAMPLER_3D: case GL_UNSIGNED_INT_SAMPLER_CUBE: @@ -365,7 +311,7 @@ int MatrixComponentCount(GLenum type, bool isRowMajorMatrix) return isRowMajorMatrix ? VariableColumnCount(type) : VariableRowCount(type); } -int AttributeRegisterCount(GLenum type) +int VariableRegisterCount(GLenum type) { return IsMatrixType(type) ? VariableColumnCount(type) : 1; } @@ -395,24 +341,6 @@ bool IsCubemapTextureTarget(GLenum target) return (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z); } -bool IsInternalTextureTarget(GLenum target, GLuint clientVersion) -{ - if (clientVersion == 2) - { - return target == GL_TEXTURE_2D || IsCubemapTextureTarget(target); - } - else if (clientVersion == 3) - { - return target == GL_TEXTURE_2D || IsCubemapTextureTarget(target) || - target == GL_TEXTURE_3D || target == GL_TEXTURE_2D_ARRAY; - } - else - { - UNREACHABLE(); - return false; - } -} - bool IsTriangleMode(GLenum drawMode) { switch (drawMode) @@ -432,11 +360,88 @@ bool IsTriangleMode(GLenum drawMode) return false; } +// [OpenGL ES SL 3.00.4] Section 11 p. 120 +// Vertex Outs/Fragment Ins packing priorities +int VariableSortOrder(GLenum type) +{ + switch (type) + { + // 1. Arrays of mat4 and mat4 + // Non-square matrices of type matCxR consume the same space as a square + // matrix of type matN where N is the greater of C and R + case GL_FLOAT_MAT4: + case GL_FLOAT_MAT2x4: + case GL_FLOAT_MAT3x4: + case GL_FLOAT_MAT4x2: + case GL_FLOAT_MAT4x3: + return 0; + + // 2. Arrays of mat2 and mat2 (since they occupy full rows) + case GL_FLOAT_MAT2: + return 1; + + // 3. Arrays of vec4 and vec4 + case GL_FLOAT_VEC4: + case GL_INT_VEC4: + case GL_BOOL_VEC4: + case GL_UNSIGNED_INT_VEC4: + return 2; + + // 4. Arrays of mat3 and mat3 + case GL_FLOAT_MAT3: + case GL_FLOAT_MAT2x3: + case GL_FLOAT_MAT3x2: + return 3; + + // 5. Arrays of vec3 and vec3 + case GL_FLOAT_VEC3: + case GL_INT_VEC3: + case GL_BOOL_VEC3: + case GL_UNSIGNED_INT_VEC3: + return 4; + + // 6. Arrays of vec2 and vec2 + case GL_FLOAT_VEC2: + case GL_INT_VEC2: + case GL_BOOL_VEC2: + case GL_UNSIGNED_INT_VEC2: + return 5; + + // 7. Single component types + case GL_FLOAT: + case GL_INT: + case GL_BOOL: + case GL_UNSIGNED_INT: + case GL_SAMPLER_2D: + case GL_SAMPLER_CUBE: + case GL_SAMPLER_EXTERNAL_OES: + case GL_SAMPLER_2D_RECT_ARB: + case GL_SAMPLER_2D_ARRAY: + case GL_SAMPLER_3D: + case GL_INT_SAMPLER_2D: + case GL_INT_SAMPLER_3D: + case GL_INT_SAMPLER_CUBE: + case GL_INT_SAMPLER_2D_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_2D: + case GL_UNSIGNED_INT_SAMPLER_3D: + case GL_UNSIGNED_INT_SAMPLER_CUBE: + case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: + case GL_SAMPLER_2D_SHADOW: + case GL_SAMPLER_2D_ARRAY_SHADOW: + case GL_SAMPLER_CUBE_SHADOW: + return 6; + + default: + UNREACHABLE(); + return 0; + } +} + } std::string getTempPath() { -#if defined (_WIN32) +#ifdef ANGLE_PLATFORM_WINDOWS char path[MAX_PATH]; DWORD pathLen = GetTempPathA(sizeof(path) / sizeof(path[0]), path); if (pathLen == 0) diff --git a/gfx/angle/src/common/utilities.h b/gfx/angle/src/common/utilities.h index f69e33a79d20..a823184ecdb4 100644 --- a/gfx/angle/src/common/utilities.h +++ b/gfx/angle/src/common/utilities.h @@ -9,36 +9,32 @@ #ifndef LIBGLESV2_UTILITIES_H #define LIBGLESV2_UTILITIES_H -#include -#include -#include -#include - +#include "angle_gl.h" #include #include namespace gl { -int UniformComponentCount(GLenum type); -GLenum UniformComponentType(GLenum type); -size_t UniformComponentSize(GLenum type); -size_t UniformInternalSize(GLenum type); -size_t UniformExternalSize(GLenum type); -GLenum UniformBoolVectorType(GLenum type); +int VariableComponentCount(GLenum type); +GLenum VariableComponentType(GLenum type); +size_t VariableComponentSize(GLenum type); +size_t VariableInternalSize(GLenum type); +size_t VariableExternalSize(GLenum type); +GLenum VariableBoolVectorType(GLenum type); int VariableRowCount(GLenum type); int VariableColumnCount(GLenum type); bool IsSampler(GLenum type); bool IsMatrixType(GLenum type); GLenum TransposeMatrixType(GLenum type); -int AttributeRegisterCount(GLenum type); +int VariableRegisterCount(GLenum type); int MatrixRegisterCount(GLenum type, bool isRowMajorMatrix); int MatrixComponentCount(GLenum type, bool isRowMajorMatrix); +int VariableSortOrder(GLenum type); int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize); bool IsCubemapTextureTarget(GLenum target); -bool IsInternalTextureTarget(GLenum target, GLuint clientVersion); bool IsTriangleMode(GLenum drawMode); diff --git a/gfx/angle/src/compiler.gypi b/gfx/angle/src/compiler.gypi index df62d1171f2f..dadc4ca9c152 100644 --- a/gfx/angle/src/compiler.gypi +++ b/gfx/angle/src/compiler.gypi @@ -3,13 +3,207 @@ # found in the LICENSE file. { + 'variables': + { + # This file list is shared with the GN build. + 'angle_translator_lib_sources': + [ + '../include/EGL/egl.h', + '../include/EGL/eglext.h', + '../include/EGL/eglplatform.h', + '../include/GLES2/gl2.h', + '../include/GLES2/gl2ext.h', + '../include/GLES2/gl2platform.h', + '../include/GLES3/gl3.h', + '../include/GLES3/gl3ext.h', + '../include/GLES3/gl3platform.h', + '../include/GLSLANG/ShaderLang.h', + '../include/GLSLANG/ShaderVars.h', + '../include/KHR/khrplatform.h', + '../include/angle_gl.h', + 'common/RefCountObject.cpp', + 'common/RefCountObject.h', + 'common/angleutils.h', + 'common/blocklayout.cpp', + 'common/blocklayout.h', + 'common/debug.cpp', + 'common/debug.h', + 'common/event_tracer.cpp', + 'common/event_tracer.h', + 'common/mathutil.cpp', + 'common/mathutil.h', + 'common/platform.h', + 'common/tls.cpp', + 'common/tls.h', + 'common/utilities.cpp', + 'common/utilities.h', + 'common/version.h', + 'compiler/translator/BaseTypes.h', + 'compiler/translator/BuiltInFunctionEmulator.cpp', + 'compiler/translator/BuiltInFunctionEmulator.h', + 'compiler/translator/CodeGen.cpp', + 'compiler/translator/Common.h', + 'compiler/translator/Compiler.cpp', + 'compiler/translator/Compiler.h', + 'compiler/translator/ConstantUnion.h', + 'compiler/translator/DetectCallDepth.cpp', + 'compiler/translator/DetectCallDepth.h', + 'compiler/translator/DetectDiscontinuity.cpp', + 'compiler/translator/DetectDiscontinuity.h', + 'compiler/translator/Diagnostics.cpp', + 'compiler/translator/Diagnostics.h', + 'compiler/translator/DirectiveHandler.cpp', + 'compiler/translator/DirectiveHandler.h', + 'compiler/translator/ExtensionBehavior.h', + 'compiler/translator/FlagStd140Structs.cpp', + 'compiler/translator/FlagStd140Structs.h', + 'compiler/translator/ForLoopUnroll.cpp', + 'compiler/translator/ForLoopUnroll.h', + 'compiler/translator/HashNames.h', + 'compiler/translator/InfoSink.cpp', + 'compiler/translator/InfoSink.h', + 'compiler/translator/Initialize.cpp', + 'compiler/translator/Initialize.h', + 'compiler/translator/InitializeDll.cpp', + 'compiler/translator/InitializeDll.h', + 'compiler/translator/InitializeGlobals.h', + 'compiler/translator/InitializeParseContext.cpp', + 'compiler/translator/InitializeParseContext.h', + 'compiler/translator/InitializeVariables.cpp', + 'compiler/translator/InitializeVariables.h', + 'compiler/translator/IntermTraverse.cpp', + 'compiler/translator/Intermediate.h', + 'compiler/translator/Intermediate.cpp', + 'compiler/translator/IntermNode.h', + 'compiler/translator/IntermNode.cpp', + 'compiler/translator/LoopInfo.cpp', + 'compiler/translator/LoopInfo.h', + 'compiler/translator/MMap.h', + 'compiler/translator/NodeSearch.h', + 'compiler/translator/OutputESSL.cpp', + 'compiler/translator/OutputESSL.h', + 'compiler/translator/OutputGLSL.cpp', + 'compiler/translator/OutputGLSL.h', + 'compiler/translator/OutputGLSLBase.cpp', + 'compiler/translator/OutputGLSLBase.h', + 'compiler/translator/OutputHLSL.cpp', + 'compiler/translator/OutputHLSL.h', + 'compiler/translator/ParseContext.cpp', + 'compiler/translator/ParseContext.h', + 'compiler/translator/PoolAlloc.cpp', + 'compiler/translator/PoolAlloc.h', + 'compiler/translator/Pragma.h', + 'compiler/translator/QualifierAlive.cpp', + 'compiler/translator/QualifierAlive.h', + 'compiler/translator/RegenerateStructNames.cpp', + 'compiler/translator/RegenerateStructNames.h', + 'compiler/translator/RemoveTree.cpp', + 'compiler/translator/RemoveTree.h', + 'compiler/translator/RenameFunction.h', + 'compiler/translator/RewriteElseBlocks.cpp', + 'compiler/translator/RewriteElseBlocks.h', + 'compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp', + 'compiler/translator/ScalarizeVecAndMatConstructorArgs.h', + 'compiler/translator/SearchSymbol.cpp', + 'compiler/translator/SearchSymbol.h', + 'compiler/translator/StructureHLSL.cpp', + 'compiler/translator/StructureHLSL.h', + 'compiler/translator/SymbolTable.cpp', + 'compiler/translator/SymbolTable.h', + 'compiler/translator/TranslatorESSL.cpp', + 'compiler/translator/TranslatorESSL.h', + 'compiler/translator/TranslatorGLSL.cpp', + 'compiler/translator/TranslatorGLSL.h', + 'compiler/translator/TranslatorHLSL.cpp', + 'compiler/translator/TranslatorHLSL.h', + 'compiler/translator/Types.cpp', + 'compiler/translator/Types.h', + 'compiler/translator/UnfoldShortCircuit.cpp', + 'compiler/translator/UnfoldShortCircuit.h', + 'compiler/translator/UnfoldShortCircuitAST.cpp', + 'compiler/translator/UnfoldShortCircuitAST.h', + 'compiler/translator/UniformHLSL.cpp', + 'compiler/translator/UniformHLSL.h', + 'compiler/translator/UtilsHLSL.cpp', + 'compiler/translator/UtilsHLSL.h', + 'compiler/translator/ValidateLimitations.cpp', + 'compiler/translator/ValidateLimitations.h', + 'compiler/translator/ValidateOutputs.cpp', + 'compiler/translator/ValidateOutputs.h', + 'compiler/translator/VariableInfo.cpp', + 'compiler/translator/VariableInfo.h', + 'compiler/translator/VariablePacker.cpp', + 'compiler/translator/VariablePacker.h', + 'compiler/translator/VersionGLSL.cpp', + 'compiler/translator/VersionGLSL.h', + 'compiler/translator/compilerdebug.cpp', + 'compiler/translator/compilerdebug.h', + 'compiler/translator/depgraph/DependencyGraph.cpp', + 'compiler/translator/depgraph/DependencyGraph.h', + 'compiler/translator/depgraph/DependencyGraphBuilder.cpp', + 'compiler/translator/depgraph/DependencyGraphBuilder.h', + 'compiler/translator/depgraph/DependencyGraphOutput.cpp', + 'compiler/translator/depgraph/DependencyGraphOutput.h', + 'compiler/translator/depgraph/DependencyGraphTraverse.cpp', + 'compiler/translator/glslang.h', + 'compiler/translator/glslang.l', + 'compiler/translator/glslang.y', + 'compiler/translator/glslang_lex.cpp', + 'compiler/translator/glslang_tab.cpp', + 'compiler/translator/glslang_tab.h', + 'compiler/translator/intermOut.cpp', + 'compiler/translator/intermediate.h', + 'compiler/translator/length_limits.h', + 'compiler/translator/parseConst.cpp', + 'compiler/translator/timing/RestrictFragmentShaderTiming.cpp', + 'compiler/translator/timing/RestrictFragmentShaderTiming.h', + 'compiler/translator/timing/RestrictVertexShaderTiming.cpp', + 'compiler/translator/timing/RestrictVertexShaderTiming.h', + 'compiler/translator/util.cpp', + 'compiler/translator/util.h', + 'third_party/compiler/ArrayBoundsClamper.cpp', + 'third_party/compiler/ArrayBoundsClamper.h', + ], + 'angle_preprocessor_sources': + [ + 'compiler/preprocessor/DiagnosticsBase.cpp', + 'compiler/preprocessor/DiagnosticsBase.h', + 'compiler/preprocessor/DirectiveHandlerBase.cpp', + 'compiler/preprocessor/DirectiveHandlerBase.h', + 'compiler/preprocessor/DirectiveParser.cpp', + 'compiler/preprocessor/DirectiveParser.h', + 'compiler/preprocessor/ExpressionParser.cpp', + 'compiler/preprocessor/ExpressionParser.h', + 'compiler/preprocessor/ExpressionParser.y', + 'compiler/preprocessor/Input.cpp', + 'compiler/preprocessor/Input.h', + 'compiler/preprocessor/Lexer.cpp', + 'compiler/preprocessor/Lexer.h', + 'compiler/preprocessor/Macro.cpp', + 'compiler/preprocessor/Macro.h', + 'compiler/preprocessor/MacroExpander.cpp', + 'compiler/preprocessor/MacroExpander.h', + 'compiler/preprocessor/Preprocessor.cpp', + 'compiler/preprocessor/Preprocessor.h', + 'compiler/preprocessor/SourceLocation.h', + 'compiler/preprocessor/Token.cpp', + 'compiler/preprocessor/Token.h', + 'compiler/preprocessor/Tokenizer.cpp', + 'compiler/preprocessor/Tokenizer.h', + 'compiler/preprocessor/Tokenizer.l', + 'compiler/preprocessor/numeric_lex.h', + 'compiler/preprocessor/pp_utils.h', + ], + }, + # Everything below this is duplicated in the GN build. If you change + # anything also change angle/BUILD.gn 'targets': [ { 'target_name': 'preprocessor', 'type': 'static_library', 'includes': [ '../build/common_defines.gypi', ], - 'sources': [ 'getSequence(); + const TIntermSequence& sequence = *(node->getSequence()); bool needToEmulate = false; if (sequence.size() == 2) { @@ -304,9 +304,9 @@ private: } // anonymous namepsace -BuiltInFunctionEmulator::BuiltInFunctionEmulator(ShShaderType shaderType) +BuiltInFunctionEmulator::BuiltInFunctionEmulator(sh::GLenum shaderType) { - if (shaderType == SH_FRAGMENT_SHADER) { + if (shaderType == GL_FRAGMENT_SHADER) { mFunctionMask = kFunctionEmulationFragmentMask; mFunctionSource = kFunctionEmulationFragmentSource; } else { diff --git a/gfx/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp.orig b/gfx/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp.orig new file mode 100644 index 000000000000..f7b1e1394d7e --- /dev/null +++ b/gfx/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp.orig @@ -0,0 +1,490 @@ +// +// 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 "angle_gl.h" +#include "compiler/translator/BuiltInFunctionEmulator.h" +#include "compiler/translator/SymbolTable.h" + +namespace { + +// we use macros here instead of function definitions to work around more GLSL +// compiler bugs, in particular on NVIDIA hardware on Mac OSX. Macros are +// problematic because if the argument has side-effects they will be repeatedly +// evaluated. This is unlikely to show up in real shaders, but is something to +// consider. +const char* kFunctionEmulationVertexSource[] = { + "#error no emulation for cos(float)", + "#error no emulation for cos(vec2)", + "#error no emulation for cos(vec3)", + "#error no emulation for cos(vec4)", + + "#define webgl_distance_emu(x, y) ((x) >= (y) ? (x) - (y) : (y) - (x))", + "#error no emulation for distance(vec2, vec2)", + "#error no emulation for distance(vec3, vec3)", + "#error no emulation for distance(vec4, vec4)", + + "#define webgl_dot_emu(x, y) ((x) * (y))", + "#error no emulation for dot(vec2, vec2)", + "#error no emulation for dot(vec3, vec3)", + "#error no emulation for dot(vec4, vec4)", + + "#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))", + "#error no emulation for length(vec2)", + "#error no emulation for length(vec3)", + "#error no emulation for length(vec4)", + + "#define webgl_normalize_emu(x) ((x) == 0.0 ? 0.0 : ((x) > 0.0 ? 1.0 : -1.0))", + "#error no emulation for normalize(vec2)", + "#error no emulation for normalize(vec3)", + "#error no emulation for normalize(vec4)", + + "#define webgl_reflect_emu(I, N) ((I) - 2.0 * (N) * (I) * (N))", + "#error no emulation for reflect(vec2, vec2)", + "#error no emulation for reflect(vec3, vec3)", + "#error no emulation for reflect(vec4, vec4)", + + // |faceforward(N, I, Nref)| is |dot(NRef, I) < 0 ? N : -N| + "#define webgl_faceforward_emu(N, I, Nref) (((Nref) * (I) < 0.0) ? (N) : -(N))", + "#error no emulation for faceforward(vec2, vec2, vec2)", + "#error no emulation for faceforward(vec3, vec3, vec3)", + "#error no emulation for faceforward(vec4, vec4, vec4)" +}; + +const char* kFunctionEmulationFragmentSource[] = { + "webgl_emu_precision float webgl_cos_emu(webgl_emu_precision float a) { return cos(a); }", + "webgl_emu_precision vec2 webgl_cos_emu(webgl_emu_precision vec2 a) { return cos(a); }", + "webgl_emu_precision vec3 webgl_cos_emu(webgl_emu_precision vec3 a) { return cos(a); }", + "webgl_emu_precision vec4 webgl_cos_emu(webgl_emu_precision vec4 a) { return cos(a); }", + + "#define webgl_distance_emu(x, y) ((x) >= (y) ? (x) - (y) : (y) - (x))", + "#error no emulation for distance(vec2, vec2)", + "#error no emulation for distance(vec3, vec3)", + "#error no emulation for distance(vec4, vec4)", + + "#define webgl_dot_emu(x, y) ((x) * (y))", + "#error no emulation for dot(vec2, vec2)", + "#error no emulation for dot(vec3, vec3)", + "#error no emulation for dot(vec4, vec4)", + + "#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))", + "#error no emulation for length(vec2)", + "#error no emulation for length(vec3)", + "#error no emulation for length(vec4)", + + "#define webgl_normalize_emu(x) ((x) == 0.0 ? 0.0 : ((x) > 0.0 ? 1.0 : -1.0))", + "#error no emulation for normalize(vec2)", + "#error no emulation for normalize(vec3)", + "#error no emulation for normalize(vec4)", + + "#define webgl_reflect_emu(I, N) ((I) - 2.0 * (N) * (I) * (N))", + "#error no emulation for reflect(vec2, vec2)", + "#error no emulation for reflect(vec3, vec3)", + "#error no emulation for reflect(vec4, vec4)", + + // |faceforward(N, I, Nref)| is |dot(NRef, I) < 0 ? N : -N| + "#define webgl_faceforward_emu(N, I, Nref) (((Nref) * (I) < 0.0) ? (N) : -(N))", + "#error no emulation for faceforward(vec2, vec2, vec2)", + "#error no emulation for faceforward(vec3, vec3, vec3)", + "#error no emulation for faceforward(vec4, vec4, vec4)" +}; + +const bool kFunctionEmulationVertexMask[] = { +#if defined(__APPLE__) + // Work around ATI driver bugs in Mac. + false, // TFunctionCos1 + false, // TFunctionCos2 + false, // TFunctionCos3 + false, // TFunctionCos4 + true, // TFunctionDistance1_1 + false, // TFunctionDistance2_2 + false, // TFunctionDistance3_3 + false, // TFunctionDistance4_4 + true, // TFunctionDot1_1 + false, // TFunctionDot2_2 + false, // TFunctionDot3_3 + false, // TFunctionDot4_4 + true, // TFunctionLength1 + false, // TFunctionLength2 + false, // TFunctionLength3 + false, // TFunctionLength4 + true, // TFunctionNormalize1 + false, // TFunctionNormalize2 + false, // TFunctionNormalize3 + false, // TFunctionNormalize4 + true, // TFunctionReflect1_1 + false, // TFunctionReflect2_2 + false, // TFunctionReflect3_3 + false, // TFunctionReflect4_4 + true, // TFunctionFaceForward1_1_1 + false, // TFunctionFaceForward2_2_2 + false, // TFunctionFaceForward3_3_3 + false, // TFunctionFaceForward4_4_4 +#else + // Work around D3D driver bug in Win. + false, // TFunctionCos1 + false, // TFunctionCos2 + false, // TFunctionCos3 + false, // TFunctionCos4 + false, // TFunctionDistance1_1 + false, // TFunctionDistance2_2 + false, // TFunctionDistance3_3 + false, // TFunctionDistance4_4 + false, // TFunctionDot1_1 + false, // TFunctionDot2_2 + false, // TFunctionDot3_3 + false, // TFunctionDot4_4 + false, // TFunctionLength1 + false, // TFunctionLength2 + false, // TFunctionLength3 + false, // TFunctionLength4 + false, // TFunctionNormalize1 + false, // TFunctionNormalize2 + false, // TFunctionNormalize3 + false, // TFunctionNormalize4 + false, // TFunctionReflect1_1 + false, // TFunctionReflect2_2 + false, // TFunctionReflect3_3 + false, // TFunctionReflect4_4 + false, // TFunctionFaceForward1_1_1 + false, // TFunctionFaceForward2_2_2 + false, // TFunctionFaceForward3_3_3 + false, // TFunctionFaceForward4_4_4 +#endif + false // TFunctionUnknown +}; + +const bool kFunctionEmulationFragmentMask[] = { +#if defined(__APPLE__) + // Work around ATI driver bugs in Mac. + true, // TFunctionCos1 + true, // TFunctionCos2 + true, // TFunctionCos3 + true, // TFunctionCos4 + true, // TFunctionDistance1_1 + false, // TFunctionDistance2_2 + false, // TFunctionDistance3_3 + false, // TFunctionDistance4_4 + true, // TFunctionDot1_1 + false, // TFunctionDot2_2 + false, // TFunctionDot3_3 + false, // TFunctionDot4_4 + true, // TFunctionLength1 + false, // TFunctionLength2 + false, // TFunctionLength3 + false, // TFunctionLength4 + true, // TFunctionNormalize1 + false, // TFunctionNormalize2 + false, // TFunctionNormalize3 + false, // TFunctionNormalize4 + true, // TFunctionReflect1_1 + false, // TFunctionReflect2_2 + false, // TFunctionReflect3_3 + false, // TFunctionReflect4_4 + true, // TFunctionFaceForward1_1_1 + false, // TFunctionFaceForward2_2_2 + false, // TFunctionFaceForward3_3_3 + false, // TFunctionFaceForward4_4_4 +#else + // Work around D3D driver bug in Win. + false, // TFunctionCos1 + false, // TFunctionCos2 + false, // TFunctionCos3 + false, // TFunctionCos4 + false, // TFunctionDistance1_1 + false, // TFunctionDistance2_2 + false, // TFunctionDistance3_3 + false, // TFunctionDistance4_4 + false, // TFunctionDot1_1 + false, // TFunctionDot2_2 + false, // TFunctionDot3_3 + false, // TFunctionDot4_4 + false, // TFunctionLength1 + false, // TFunctionLength2 + false, // TFunctionLength3 + false, // TFunctionLength4 + false, // TFunctionNormalize1 + false, // TFunctionNormalize2 + false, // TFunctionNormalize3 + false, // TFunctionNormalize4 + false, // TFunctionReflect1_1 + false, // TFunctionReflect2_2 + false, // TFunctionReflect3_3 + false, // TFunctionReflect4_4 + false, // TFunctionFaceForward1_1_1 + false, // TFunctionFaceForward2_2_2 + false, // TFunctionFaceForward3_3_3 + false, // TFunctionFaceForward4_4_4 +#endif + false // TFunctionUnknown +}; + +class BuiltInFunctionEmulationMarker : public TIntermTraverser { +public: + BuiltInFunctionEmulationMarker(BuiltInFunctionEmulator& emulator) + : mEmulator(emulator) + { + } + + virtual bool visitUnary(Visit visit, TIntermUnary* node) + { + if (visit == PreVisit) { + bool needToEmulate = mEmulator.SetFunctionCalled( + node->getOp(), node->getOperand()->getType()); + if (needToEmulate) + node->setUseEmulatedFunction(); + } + return true; + } + + virtual bool visitAggregate(Visit visit, TIntermAggregate* node) + { + if (visit == PreVisit) { + // Here we handle all the built-in functions instead of the ones we + // currently identified as problematic. + switch (node->getOp()) { + case EOpLessThan: + case EOpGreaterThan: + case EOpLessThanEqual: + case EOpGreaterThanEqual: + case EOpVectorEqual: + case EOpVectorNotEqual: + case EOpMod: + case EOpPow: + case EOpAtan: + case EOpMin: + case EOpMax: + case EOpClamp: + case EOpMix: + case EOpStep: + case EOpSmoothStep: + case EOpDistance: + case EOpDot: + case EOpCross: + case EOpFaceForward: + case EOpReflect: + case EOpRefract: + case EOpMul: + break; + default: + return true; + }; +<<<<<<< HEAD + const TIntermSequence& sequence = *(node->getSequence()); + // Right now we only handle built-in functions with two parameters. + if (sequence.size() != 2) + return true; + TIntermTyped* param1 = sequence[0]->getAsTyped(); + TIntermTyped* param2 = sequence[1]->getAsTyped(); + if (!param1 || !param2) +======= + const TIntermSequence& sequence = node->getSequence(); + bool needToEmulate = false; + + if (sequence.size() == 2) { + TIntermTyped* param1 = sequence[0]->getAsTyped(); + TIntermTyped* param2 = sequence[1]->getAsTyped(); + if (!param1 || !param2) + return true; + needToEmulate = mEmulator.SetFunctionCalled( + node->getOp(), param1->getType(), param2->getType()); + } else if (sequence.size() == 3) { + TIntermTyped* param1 = sequence[0]->getAsTyped(); + TIntermTyped* param2 = sequence[1]->getAsTyped(); + TIntermTyped* param3 = sequence[2]->getAsTyped(); + if (!param1 || !param2 || !param3) + return true; + needToEmulate = mEmulator.SetFunctionCalled( + node->getOp(), param1->getType(), param2->getType(), param3->getType()); + } else { +>>>>>>> 700b9c6... Emulate faceforward(float, float, float) when function emulation is enabled + return true; + } + if (needToEmulate) + node->setUseEmulatedFunction(); + } + return true; + } + +private: + BuiltInFunctionEmulator& mEmulator; +}; + +} // anonymous namepsace + +BuiltInFunctionEmulator::BuiltInFunctionEmulator(sh::GLenum shaderType) +{ + if (shaderType == GL_FRAGMENT_SHADER) { + mFunctionMask = kFunctionEmulationFragmentMask; + mFunctionSource = kFunctionEmulationFragmentSource; + } else { + mFunctionMask = kFunctionEmulationVertexMask; + mFunctionSource = kFunctionEmulationVertexSource; + } +} + +bool BuiltInFunctionEmulator::SetFunctionCalled( + TOperator op, const TType& param) +{ + TBuiltInFunction function = IdentifyFunction(op, param); + return SetFunctionCalled(function); +} + +bool BuiltInFunctionEmulator::SetFunctionCalled( + TOperator op, const TType& param1, const TType& param2) +{ + TBuiltInFunction function = IdentifyFunction(op, param1, param2); + return SetFunctionCalled(function); +} + +bool BuiltInFunctionEmulator::SetFunctionCalled( + TOperator op, const TType& param1, const TType& param2, const TType& param3) +{ + TBuiltInFunction function = IdentifyFunction(op, param1, param2, param3); + return SetFunctionCalled(function); +} + +bool BuiltInFunctionEmulator::SetFunctionCalled( + BuiltInFunctionEmulator::TBuiltInFunction function) { + if (function == TFunctionUnknown || mFunctionMask[function] == false) + return false; + for (size_t i = 0; i < mFunctions.size(); ++i) { + if (mFunctions[i] == function) + return true; + } + mFunctions.push_back(function); + return true; +} + +void BuiltInFunctionEmulator::OutputEmulatedFunctionDefinition( + TInfoSinkBase& out, bool withPrecision) const +{ + if (mFunctions.size() == 0) + return; + out << "// BEGIN: Generated code for built-in function emulation\n\n"; + if (withPrecision) { + out << "#if defined(GL_FRAGMENT_PRECISION_HIGH)\n" + << "#define webgl_emu_precision highp\n" + << "#else\n" + << "#define webgl_emu_precision mediump\n" + << "#endif\n\n"; + } else { + out << "#define webgl_emu_precision\n\n"; + } + for (size_t i = 0; i < mFunctions.size(); ++i) { + out << mFunctionSource[mFunctions[i]] << "\n\n"; + } + out << "// END: Generated code for built-in function emulation\n\n"; +} + +BuiltInFunctionEmulator::TBuiltInFunction +BuiltInFunctionEmulator::IdentifyFunction( + TOperator op, const TType& param) +{ + if (param.getNominalSize() > 4 || param.getSecondarySize() > 4) + return TFunctionUnknown; + unsigned int function = TFunctionUnknown; + switch (op) { + case EOpCos: + function = TFunctionCos1; + break; + case EOpLength: + function = TFunctionLength1; + break; + case EOpNormalize: + function = TFunctionNormalize1; + break; + default: + break; + } + if (function == TFunctionUnknown) + return TFunctionUnknown; + if (param.isVector()) + function += param.getNominalSize() - 1; + return static_cast(function); +} + +BuiltInFunctionEmulator::TBuiltInFunction +BuiltInFunctionEmulator::IdentifyFunction( + TOperator op, const TType& param1, const TType& param2) +{ + // Right now for all the emulated functions with two parameters, the two + // parameters have the same type. + if (param1.getNominalSize() != param2.getNominalSize() || + param1.getSecondarySize() != param2.getSecondarySize() || + param1.getNominalSize() > 4 || param1.getSecondarySize() > 4) + return TFunctionUnknown; + + unsigned int function = TFunctionUnknown; + switch (op) { + case EOpDistance: + function = TFunctionDistance1_1; + break; + case EOpDot: + function = TFunctionDot1_1; + break; + case EOpReflect: + function = TFunctionReflect1_1; + break; + default: + break; + } + if (function == TFunctionUnknown) + return TFunctionUnknown; + if (param1.isVector()) + function += param1.getNominalSize() - 1; + return static_cast(function); +} + +BuiltInFunctionEmulator::TBuiltInFunction +BuiltInFunctionEmulator::IdentifyFunction( + TOperator op, const TType& param1, const TType& param2, const TType& param3) +{ + // Check that all params have the same type, length, + // and that they're not too large. + if (param1.isVector() != param2.isVector() || + param2.isVector() != param3.isVector() || + param1.getNominalSize() != param2.getNominalSize() || + param2.getNominalSize() != param3.getNominalSize() || + param1.getNominalSize() > 4) + return TFunctionUnknown; + + unsigned int function = TFunctionUnknown; + switch (op) { + case EOpFaceForward: + function = TFunctionFaceForward1_1_1; + break; + default: + break; + } + if (function == TFunctionUnknown) + return TFunctionUnknown; + if (param1.isVector()) + function += param1.getNominalSize() - 1; + return static_cast(function); +} + +void BuiltInFunctionEmulator::MarkBuiltInFunctionsForEmulation( + TIntermNode* root) +{ + ASSERT(root); + + BuiltInFunctionEmulationMarker marker(*this); + root->traverse(&marker); +} + +void BuiltInFunctionEmulator::Cleanup() +{ + mFunctions.clear(); +} + +//static +TString BuiltInFunctionEmulator::GetEmulatedFunctionName( + const TString& name) +{ + ASSERT(name[name.length() - 1] == '('); + return "webgl_" + name.substr(0, name.length() - 1) + "_emu("; +} + diff --git a/gfx/angle/src/compiler/translator/BuiltInFunctionEmulator.h b/gfx/angle/src/compiler/translator/BuiltInFunctionEmulator.h index 4c4d729dd307..d1ebe799f836 100644 --- a/gfx/angle/src/compiler/translator/BuiltInFunctionEmulator.h +++ b/gfx/angle/src/compiler/translator/BuiltInFunctionEmulator.h @@ -8,7 +8,7 @@ #define COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_ #include "compiler/translator/InfoSink.h" -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" // // This class decides which built-in functions need to be replaced with the @@ -17,7 +17,7 @@ // class BuiltInFunctionEmulator { public: - BuiltInFunctionEmulator(ShShaderType shaderType); + BuiltInFunctionEmulator(sh::GLenum shaderType); // Records that a function is called by the shader and might needs to be // emulated. If the function's group is not in mFunctionGroupFilter, this // becomes an no-op. diff --git a/gfx/angle/src/compiler/translator/CodeGen.cpp b/gfx/angle/src/compiler/translator/CodeGen.cpp index c35dbdc77ff9..71056f429782 100644 --- a/gfx/angle/src/compiler/translator/CodeGen.cpp +++ b/gfx/angle/src/compiler/translator/CodeGen.cpp @@ -14,7 +14,7 @@ // a subclass of TCompiler. // TCompiler* ConstructCompiler( - ShShaderType type, ShShaderSpec spec, ShShaderOutput output) + sh::GLenum type, ShShaderSpec spec, ShShaderOutput output) { switch (output) { case SH_ESSL_OUTPUT: diff --git a/gfx/angle/src/compiler/translator/Compiler.cpp b/gfx/angle/src/compiler/translator/Compiler.cpp index 402715b8af18..bcb431a6229d 100644 --- a/gfx/angle/src/compiler/translator/Compiler.cpp +++ b/gfx/angle/src/compiler/translator/Compiler.cpp @@ -5,14 +5,16 @@ // #include "compiler/translator/BuiltInFunctionEmulator.h" +#include "compiler/translator/Compiler.h" #include "compiler/translator/DetectCallDepth.h" #include "compiler/translator/ForLoopUnroll.h" #include "compiler/translator/Initialize.h" #include "compiler/translator/InitializeParseContext.h" #include "compiler/translator/InitializeVariables.h" #include "compiler/translator/ParseContext.h" +#include "compiler/translator/RegenerateStructNames.h" #include "compiler/translator/RenameFunction.h" -#include "compiler/translator/ShHandle.h" +#include "compiler/translator/ScalarizeVecAndMatConstructorArgs.h" #include "compiler/translator/UnfoldShortCircuitAST.h" #include "compiler/translator/ValidateLimitations.h" #include "compiler/translator/ValidateOutputs.h" @@ -22,6 +24,8 @@ #include "compiler/translator/timing/RestrictFragmentShaderTiming.h" #include "compiler/translator/timing/RestrictVertexShaderTiming.h" #include "third_party/compiler/ArrayBoundsClamper.h" +#include "angle_gl.h" +#include "common/utilities.h" bool IsWebGLBasedSpec(ShShaderSpec spec) { @@ -92,7 +96,7 @@ TShHandleBase::~TShHandleBase() allocator.popAll(); } -TCompiler::TCompiler(ShShaderType type, ShShaderSpec spec, ShShaderOutput output) +TCompiler::TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output) : shaderType(type), shaderSpec(spec), outputType(output), @@ -112,7 +116,7 @@ TCompiler::~TCompiler() bool TCompiler::Init(const ShBuiltInResources& resources) { shaderVersion = 100; - maxUniformVectors = (shaderType == SH_VERTEX_SHADER) ? + maxUniformVectors = (shaderType == GL_VERTEX_SHADER) ? resources.MaxVertexUniformVectors : resources.MaxFragmentUniformVectors; maxExpressionComplexity = resources.MaxExpressionComplexity; @@ -187,7 +191,7 @@ bool TCompiler::compile(const char* const shaderStrings[], if (success) success = detectCallDepth(root, infoSink, (compileOptions & SH_LIMIT_CALL_STACK_DEPTH) != 0); - if (success && shaderVersion == 300 && shaderType == SH_FRAGMENT_SHADER) + if (success && shaderVersion == 300 && shaderType == GL_FRAGMENT_SHADER) success = validateOutputs(root); if (success && (compileOptions & SH_VALIDATE_LOOP_INDEXING)) @@ -225,7 +229,7 @@ bool TCompiler::compile(const char* const shaderStrings[], if (success && (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS)) arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root); - if (success && shaderType == SH_VERTEX_SHADER && (compileOptions & SH_INIT_GL_POSITION)) + if (success && shaderType == GL_VERTEX_SHADER && (compileOptions & SH_INIT_GL_POSITION)) initializeGLPosition(root); if (success && (compileOptions & SH_UNFOLD_SHORT_CIRCUIT)) @@ -247,11 +251,24 @@ bool TCompiler::compile(const char* const shaderStrings[], infoSink.info << "too many uniforms"; } } - if (success && shaderType == SH_VERTEX_SHADER && + if (success && shaderType == GL_VERTEX_SHADER && (compileOptions & SH_INIT_VARYINGS_WITHOUT_STATIC_USE)) initializeVaryingsWithoutStaticUse(root); } + if (success && (compileOptions & SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS)) + { + ScalarizeVecAndMatConstructorArgs scalarizer( + shaderType, fragmentPrecisionHigh); + root->traverse(&scalarizer); + } + + if (success && (compileOptions & SH_REGENERATE_STRUCT_NAMES)) + { + RegenerateStructNames gen(symbolTable, shaderVersion); + root->traverse(&gen); + } + if (success && (compileOptions & SH_INTERMEDIATE_TREE)) intermediate.outputTree(root); @@ -294,10 +311,10 @@ bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources) switch(shaderType) { - case SH_FRAGMENT_SHADER: + case GL_FRAGMENT_SHADER: symbolTable.setDefaultPrecision(integer, EbpMedium); break; - case SH_VERTEX_SHADER: + case GL_VERTEX_SHADER: symbolTable.setDefaultPrecision(integer, EbpHigh); symbolTable.setDefaultPrecision(floatingPoint, EbpHigh); break; @@ -355,9 +372,13 @@ void TCompiler::clearResults() infoSink.obj.erase(); infoSink.debug.erase(); - attribs.clear(); + attributes.clear(); + outputVariables.clear(); uniforms.clear(); + expandedUniforms.clear(); varyings.clear(); + expandedVaryings.clear(); + interfaceBlocks.clear(); builtInFunctionEmulator.Cleanup(); @@ -418,7 +439,7 @@ bool TCompiler::enforceTimingRestrictions(TIntermNode* root, bool outputGraph) return false; } - if (shaderType == SH_FRAGMENT_SHADER) + if (shaderType == GL_FRAGMENT_SHADER) { TDependencyGraph graph(root); @@ -481,14 +502,24 @@ bool TCompiler::enforceVertexShaderTimingRestrictions(TIntermNode* root) void TCompiler::collectVariables(TIntermNode* root) { - CollectVariables collect(attribs, uniforms, varyings, hashFunction); + CollectVariables collect(&attributes, + &outputVariables, + &uniforms, + &varyings, + &interfaceBlocks, + hashFunction); root->traverse(&collect); + + // For backwards compatiblity with ShGetVariableInfo, expand struct + // uniforms and varyings into separate variables for each field. + ExpandVariables(uniforms, &expandedUniforms); + ExpandVariables(varyings, &expandedVaryings); } bool TCompiler::enforcePackingRestrictions() { VariablePacker packer; - return packer.CheckVariablesWithinPackingLimits(maxUniformVectors, uniforms); + return packer.CheckVariablesWithinPackingLimits(maxUniformVectors, expandedUniforms); } void TCompiler::initializeGLPosition(TIntermNode* root) @@ -506,43 +537,16 @@ void TCompiler::initializeVaryingsWithoutStaticUse(TIntermNode* root) InitializeVariables::InitVariableInfoList variables; for (size_t ii = 0; ii < varyings.size(); ++ii) { - const TVariableInfo& varying = varyings[ii]; + const sh::Varying& varying = varyings[ii]; if (varying.staticUse) continue; - unsigned char primarySize = 1, secondarySize = 1; - switch (varying.type) - { - case SH_FLOAT: - break; - case SH_FLOAT_VEC2: - primarySize = 2; - break; - case SH_FLOAT_VEC3: - primarySize = 3; - break; - case SH_FLOAT_VEC4: - primarySize = 4; - break; - case SH_FLOAT_MAT2: - primarySize = 2; - secondarySize = 2; - break; - case SH_FLOAT_MAT3: - primarySize = 3; - secondarySize = 3; - break; - case SH_FLOAT_MAT4: - primarySize = 4; - secondarySize = 4; - break; - default: - ASSERT(false); - } - TType type(EbtFloat, EbpUndefined, EvqVaryingOut, primarySize, secondarySize, varying.isArray); + unsigned char primarySize = static_cast(gl::VariableColumnCount(varying.type)); + unsigned char secondarySize = static_cast(gl::VariableRowCount(varying.type)); + TType type(EbtFloat, EbpUndefined, EvqVaryingOut, primarySize, secondarySize, varying.isArray()); TString name = varying.name.c_str(); - if (varying.isArray) + if (varying.isArray()) { - type.setArraySize(varying.size); + type.setArraySize(varying.arraySize); name = name.substr(0, name.find_first_of('[')); } diff --git a/gfx/angle/src/compiler/translator/ShHandle.h b/gfx/angle/src/compiler/translator/Compiler.h similarity index 82% rename from gfx/angle/src/compiler/translator/ShHandle.h rename to gfx/angle/src/compiler/translator/Compiler.h index bb6a60c519f4..6bef5c1ab08b 100644 --- a/gfx/angle/src/compiler/translator/ShHandle.h +++ b/gfx/angle/src/compiler/translator/Compiler.h @@ -52,9 +52,10 @@ protected: // The base class for the machine dependent compiler to derive from // for managing object code from the compile. // -class TCompiler : public TShHandleBase { -public: - TCompiler(ShShaderType type, ShShaderSpec spec, ShShaderOutput output); +class TCompiler : public TShHandleBase +{ + public: + TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output); virtual ~TCompiler(); virtual TCompiler* getAsCompiler() { return this; } @@ -66,9 +67,14 @@ public: // Get results of the last compilation. int getShaderVersion() const { return shaderVersion; } TInfoSink& getInfoSink() { return infoSink; } - const TVariableInfoList& getAttribs() const { return attribs; } - const TVariableInfoList& getUniforms() const { return uniforms; } - const TVariableInfoList& getVaryings() const { return varyings; } + + const std::vector &getAttributes() const { return attributes; } + const std::vector &getOutputVariables() const { return outputVariables; } + const std::vector &getUniforms() const { return uniforms; } + const std::vector &getExpandedUniforms() const { return expandedUniforms; } + const std::vector &getVaryings() const { return varyings; } + const std::vector &getExpandedVaryings() const { return expandedVaryings; } + const std::vector &getInterfaceBlocks() const { return interfaceBlocks; } ShHashFunction64 getHashFunction() const { return hashFunction; } NameMap& getNameMap() { return nameMap; } @@ -77,8 +83,8 @@ public: ShShaderOutput getOutputType() const { return outputType; } std::string getBuiltInResourcesString() const { return builtInResourcesString; } -protected: - ShShaderType getShaderType() const { return shaderType; } + protected: + sh::GLenum getShaderType() const { return shaderType; } // Initialize symbol-table with built-in symbols. bool InitBuiltInSymbolTable(const ShBuiltInResources& resources); // Compute the string representation of the built-in resources @@ -115,7 +121,7 @@ protected: bool enforceTimingRestrictions(TIntermNode* root, bool outputGraph); // Returns true if the shader does not use samplers. bool enforceVertexShaderTimingRestrictions(TIntermNode* root); - // Returns true if the shader does not use sampler dependent values to affect control + // 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 is below the limit. @@ -129,8 +135,16 @@ protected: ShArrayIndexClampingStrategy getArrayIndexClampingStrategy() const; const BuiltInFunctionEmulator& getBuiltInFunctionEmulator() const; -private: - ShShaderType shaderType; + std::vector attributes; + std::vector outputVariables; + std::vector uniforms; + std::vector expandedUniforms; + std::vector varyings; + std::vector expandedVaryings; + std::vector interfaceBlocks; + + private: + sh::GLenum shaderType; ShShaderSpec shaderSpec; ShShaderOutput outputType; @@ -155,9 +169,6 @@ private: // Results of compilation. int shaderVersion; TInfoSink infoSink; // Output sink. - TVariableInfoList attribs; // Active attributes in the compiled shader. - TVariableInfoList uniforms; // Active uniforms in the compiled shader. - TVariableInfoList varyings; // Varyings in the compiled shader. // name hashing. ShHashFunction64 hashFunction; @@ -169,12 +180,12 @@ private: // and the machine dependent code. // // The machine dependent code should derive from the classes -// above. Then Construct*() and Delete*() will create and +// above. Then Construct*() and Delete*() will create and // destroy the machine dependent objects, which contain the // above machine independent information. // TCompiler* ConstructCompiler( - ShShaderType type, ShShaderSpec spec, ShShaderOutput output); + sh::GLenum type, ShShaderSpec spec, ShShaderOutput output); void DeleteCompiler(TCompiler*); #endif // _SHHANDLE_INCLUDED_ diff --git a/gfx/angle/src/compiler/translator/ConstantUnion.h b/gfx/angle/src/compiler/translator/ConstantUnion.h index 5fdba61546c1..5e86c64805c4 100644 --- a/gfx/angle/src/compiler/translator/ConstantUnion.h +++ b/gfx/angle/src/compiler/translator/ConstantUnion.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2014 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,6 +18,67 @@ public: type = EbtVoid; } + bool cast(TBasicType newType, const ConstantUnion &constant) + { + switch (newType) + { + case EbtFloat: + switch (constant.type) + { + case EbtInt: setFConst(static_cast(constant.getIConst())); break; + case EbtUInt: setFConst(static_cast(constant.getUConst())); break; + case EbtBool: setFConst(static_cast(constant.getBConst())); break; + case EbtFloat: setFConst(static_cast(constant.getFConst())); break; + default: return false; + } + break; + case EbtInt: + switch (constant.type) + { + case EbtInt: setIConst(static_cast(constant.getIConst())); break; + case EbtUInt: setIConst(static_cast(constant.getUConst())); break; + case EbtBool: setIConst(static_cast(constant.getBConst())); break; + case EbtFloat: setIConst(static_cast(constant.getFConst())); break; + default: return false; + } + break; + case EbtUInt: + switch (constant.type) + { + case EbtInt: setUConst(static_cast(constant.getIConst())); break; + case EbtUInt: setUConst(static_cast(constant.getUConst())); break; + case EbtBool: setUConst(static_cast(constant.getBConst())); break; + case EbtFloat: setUConst(static_cast(constant.getFConst())); break; + default: return false; + } + break; + case EbtBool: + switch (constant.type) + { + case EbtInt: setBConst(constant.getIConst() != 0); break; + case EbtUInt: setBConst(constant.getUConst() != 0); break; + case EbtBool: setBConst(constant.getBConst()); break; + case EbtFloat: setBConst(constant.getFConst() != 0.0f); break; + default: return false; + } + break; + case EbtStruct: // Struct fields don't get cast + switch (constant.type) + { + case EbtInt: setIConst(constant.getIConst()); break; + case EbtUInt: setUConst(constant.getUConst()); break; + case EbtBool: setBConst(constant.getBConst()); break; + case EbtFloat: setFConst(constant.getFConst()); break; + default: return false; + } + break; + default: + return false; + } + + return true; + } + void setIConst(int i) {iConst = i; type = EbtInt; } void setUConst(unsigned int u) { uConst = u; type = EbtUInt; } void setFConst(float f) {fConst = f; type = EbtFloat; } diff --git a/gfx/angle/src/compiler/translator/DetectCallDepth.h b/gfx/angle/src/compiler/translator/DetectCallDepth.h index cb76f1de02ab..86810650dcbd 100644 --- a/gfx/angle/src/compiler/translator/DetectCallDepth.h +++ b/gfx/angle/src/compiler/translator/DetectCallDepth.h @@ -8,7 +8,7 @@ #define COMPILER_DETECT_RECURSION_H_ #include -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include "compiler/translator/VariableInfo.h" class TInfoSink; diff --git a/gfx/angle/src/compiler/translator/DetectDiscontinuity.h b/gfx/angle/src/compiler/translator/DetectDiscontinuity.h index 1dd8be923359..35d66cbc2e5f 100644 --- a/gfx/angle/src/compiler/translator/DetectDiscontinuity.h +++ b/gfx/angle/src/compiler/translator/DetectDiscontinuity.h @@ -11,7 +11,7 @@ #ifndef COMPILER_DETECTDISCONTINUITY_H_ #define COMPILER_DETECTDISCONTINUITY_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" namespace sh { diff --git a/gfx/angle/src/compiler/translator/FlagStd140Structs.h b/gfx/angle/src/compiler/translator/FlagStd140Structs.h index 610205eb92e9..c93a6f808ee2 100644 --- a/gfx/angle/src/compiler/translator/FlagStd140Structs.h +++ b/gfx/angle/src/compiler/translator/FlagStd140Structs.h @@ -7,7 +7,7 @@ #ifndef COMPILER_FLAGSTD140STRUCTS_H_ #define COMPILER_FLAGSTD140STRUCTS_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" namespace sh { diff --git a/gfx/angle/src/compiler/translator/ForLoopUnroll.cpp b/gfx/angle/src/compiler/translator/ForLoopUnroll.cpp index 5cb51645593e..f3be20d9783b 100644 --- a/gfx/angle/src/compiler/translator/ForLoopUnroll.cpp +++ b/gfx/angle/src/compiler/translator/ForLoopUnroll.cpp @@ -43,8 +43,8 @@ bool ForLoopUnrollMarker::visitLoop(Visit, TIntermLoop *node) // Check if loop index type is integer. // This is called after ValidateLimitations pass, so all the calls // should be valid. See ValidateLimitations::validateForLoopInit(). - TIntermSequence& declSeq = node->getInit()->getAsAggregate()->getSequence(); - TIntermSymbol* symbol = declSeq[0]->getAsBinaryNode()->getLeft()->getAsSymbolNode(); + TIntermSequence *declSeq = node->getInit()->getAsAggregate()->getSequence(); + TIntermSymbol *symbol = (*declSeq)[0]->getAsBinaryNode()->getLeft()->getAsSymbolNode(); if (symbol->getBasicType() == EbtInt) node->setUnrollFlag(true); } diff --git a/gfx/angle/src/compiler/translator/HashNames.h b/gfx/angle/src/compiler/translator/HashNames.h index 85161428b2a9..26546a3e7beb 100644 --- a/gfx/angle/src/compiler/translator/HashNames.h +++ b/gfx/angle/src/compiler/translator/HashNames.h @@ -9,7 +9,7 @@ #include -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #define HASHED_NAME_PREFIX "webgl_" diff --git a/gfx/angle/src/compiler/translator/Initialize.cpp b/gfx/angle/src/compiler/translator/Initialize.cpp index 27e96f4014a2..10b21e6d2869 100644 --- a/gfx/angle/src/compiler/translator/Initialize.cpp +++ b/gfx/angle/src/compiler/translator/Initialize.cpp @@ -12,9 +12,10 @@ #include "compiler/translator/Initialize.h" -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" +#include "angle_gl.h" -void InsertBuiltInFunctions(ShShaderType type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &symbolTable) +void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &symbolTable) { TType *float1 = new TType(EbtFloat); TType *float2 = new TType(EbtFloat, 2); @@ -362,7 +363,7 @@ void InsertBuiltInFunctions(ShShaderType type, ShShaderSpec spec, const ShBuiltI symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "textureCubeGradEXT", samplerCube, float3, float3, float3); } - if (type == SH_FRAGMENT_SHADER) + if (type == GL_FRAGMENT_SHADER) { symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2D", sampler2D, float2, float1); symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", sampler2D, float3, float1); @@ -396,7 +397,7 @@ void InsertBuiltInFunctions(ShShaderType type, ShShaderSpec spec, const ShBuiltI } } - if(type == SH_VERTEX_SHADER) + if(type == GL_VERTEX_SHADER) { symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DLod", sampler2D, float2, float1); symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjLod", sampler2D, float3, float1); @@ -426,7 +427,7 @@ void InsertBuiltInFunctions(ShShaderType type, ShShaderSpec spec, const ShBuiltI symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLod", gsamplerCube, float3, float1); symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLod", gsampler2DArray, float3, float1); - if (type == SH_FRAGMENT_SHADER) + if (type == GL_FRAGMENT_SHADER) { symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler2D, float2, float1); symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler3D, float3, float1); @@ -447,7 +448,7 @@ void InsertBuiltInFunctions(ShShaderType type, ShShaderSpec spec, const ShBuiltI symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProj", sampler2DShadow, float4); symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureLod", sampler2DShadow, float3, float1); - if (type == SH_FRAGMENT_SHADER) + if (type == GL_FRAGMENT_SHADER) { symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "texture", sampler2DShadow, float3, float1); symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "texture", samplerCubeShadow, float4, float1); @@ -462,7 +463,7 @@ void InsertBuiltInFunctions(ShShaderType type, ShShaderSpec spec, const ShBuiltI symbolTable.insertBuiltIn(ESSL3_BUILTINS, int2, "textureSize", samplerCubeShadow, int1); symbolTable.insertBuiltIn(ESSL3_BUILTINS, int3, "textureSize", sampler2DArrayShadow, int1); - if(type == SH_FRAGMENT_SHADER) + if(type == GL_FRAGMENT_SHADER) { symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "dFdx", float1); symbolTable.insertBuiltIn(ESSL3_BUILTINS, float2, "dFdx", float2); @@ -485,7 +486,7 @@ void InsertBuiltInFunctions(ShShaderType type, ShShaderSpec spec, const ShBuiltI symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureOffset", sampler2DShadow, float3, int2); symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler2DArray, float3, int2); - if(type == SH_FRAGMENT_SHADER) + if(type == GL_FRAGMENT_SHADER) { symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler2D, float2, int2, float1); symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler3D, float3, int3, float1); @@ -498,7 +499,7 @@ void InsertBuiltInFunctions(ShShaderType type, ShShaderSpec spec, const ShBuiltI symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler3D, float4, int3); symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjOffset", sampler2DShadow, float4, int2); - if(type == SH_FRAGMENT_SHADER) + if(type == GL_FRAGMENT_SHADER) { symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler2D, float3, int2, float1); symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler2D, float4, int2, float1); @@ -566,10 +567,10 @@ void InsertBuiltInFunctions(ShShaderType type, ShShaderSpec spec, const ShBuiltI fields->push_back(diff); TStructure *depthRangeStruct = new TStructure(NewPoolTString("gl_DepthRangeParameters"), fields); TVariable *depthRangeParameters = new TVariable(&depthRangeStruct->name(), depthRangeStruct, true); - symbolTable.insert(COMMON_BUILTINS, *depthRangeParameters); + symbolTable.insert(COMMON_BUILTINS, depthRangeParameters); TVariable *depthRange = new TVariable(NewPoolTString("gl_DepthRange"), TType(depthRangeStruct)); depthRange->setQualifier(EvqUniform); - symbolTable.insert(COMMON_BUILTINS, *depthRange); + symbolTable.insert(COMMON_BUILTINS, depthRange); // // Implementation dependent built-in constants. @@ -594,7 +595,7 @@ void InsertBuiltInFunctions(ShShaderType type, ShShaderSpec spec, const ShBuiltI symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MaxProgramTexelOffset", resources.MaxProgramTexelOffset); } -void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec, +void IdentifyBuiltIns(sh::GLenum type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &symbolTable) { @@ -603,32 +604,32 @@ void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec, // the built-in header files. // switch(type) { - case SH_FRAGMENT_SHADER: - symbolTable.insert(COMMON_BUILTINS, *new TVariable(NewPoolTString("gl_FragCoord"), TType(EbtFloat, EbpMedium, EvqFragCoord, 4))); - symbolTable.insert(COMMON_BUILTINS, *new TVariable(NewPoolTString("gl_FrontFacing"), TType(EbtBool, EbpUndefined, EvqFrontFacing, 1))); - symbolTable.insert(COMMON_BUILTINS, *new TVariable(NewPoolTString("gl_PointCoord"), TType(EbtFloat, EbpMedium, EvqPointCoord, 2))); + case GL_FRAGMENT_SHADER: + symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_FragCoord"), TType(EbtFloat, EbpMedium, EvqFragCoord, 4))); + symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_FrontFacing"), TType(EbtBool, EbpUndefined, EvqFrontFacing, 1))); + symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_PointCoord"), TType(EbtFloat, EbpMedium, EvqPointCoord, 2))); // // In CSS Shaders, gl_FragColor, gl_FragData, and gl_MaxDrawBuffers are not available. // Instead, css_MixColor and css_ColorMatrix are available. // if (spec != SH_CSS_SHADERS_SPEC) { - symbolTable.insert(ESSL1_BUILTINS, *new TVariable(NewPoolTString("gl_FragColor"), TType(EbtFloat, EbpMedium, EvqFragColor, 4))); - symbolTable.insert(ESSL1_BUILTINS, *new TVariable(NewPoolTString("gl_FragData[gl_MaxDrawBuffers]"), TType(EbtFloat, EbpMedium, EvqFragData, 4))); + symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_FragColor"), TType(EbtFloat, EbpMedium, EvqFragColor, 4))); + symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_FragData[gl_MaxDrawBuffers]"), TType(EbtFloat, EbpMedium, EvqFragData, 4))); if (resources.EXT_frag_depth) { - symbolTable.insert(ESSL1_BUILTINS, *new TVariable(NewPoolTString("gl_FragDepthEXT"), TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium, EvqFragDepth, 1))); + symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_FragDepthEXT"), TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium, EvqFragDepth, 1))); symbolTable.relateToExtension(ESSL1_BUILTINS, "gl_FragDepthEXT", "GL_EXT_frag_depth"); } } else { - symbolTable.insert(ESSL1_BUILTINS, *new TVariable(NewPoolTString("css_MixColor"), TType(EbtFloat, EbpMedium, EvqGlobal, 4))); - symbolTable.insert(ESSL1_BUILTINS, *new TVariable(NewPoolTString("css_ColorMatrix"), TType(EbtFloat, EbpMedium, EvqGlobal, 4, 4))); + symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("css_MixColor"), TType(EbtFloat, EbpMedium, EvqGlobal, 4))); + symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("css_ColorMatrix"), TType(EbtFloat, EbpMedium, EvqGlobal, 4, 4))); } break; - case SH_VERTEX_SHADER: - symbolTable.insert(COMMON_BUILTINS, *new TVariable(NewPoolTString("gl_Position"), TType(EbtFloat, EbpHigh, EvqPosition, 4))); - symbolTable.insert(COMMON_BUILTINS, *new TVariable(NewPoolTString("gl_PointSize"), TType(EbtFloat, EbpMedium, EvqPointSize, 1))); + case GL_VERTEX_SHADER: + symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_Position"), TType(EbtFloat, EbpHigh, EvqPosition, 4))); + symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_PointSize"), TType(EbtFloat, EbpMedium, EvqPointSize, 1))); break; default: assert(false && "Language not supported"); @@ -694,9 +695,9 @@ void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec, // Map language-specific operators. switch(type) { - case SH_VERTEX_SHADER: + case GL_VERTEX_SHADER: break; - case SH_FRAGMENT_SHADER: + case GL_FRAGMENT_SHADER: if (resources.OES_standard_derivatives) { symbolTable.relateToOperator(ESSL1_BUILTINS, "dFdx", EOpDFdx); @@ -730,12 +731,12 @@ void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec, // Finally add resource-specific variables. switch(type) { - case SH_FRAGMENT_SHADER: + case GL_FRAGMENT_SHADER: if (spec != SH_CSS_SHADERS_SPEC) { // Set up gl_FragData. The array size. TType fragData(EbtFloat, EbpMedium, EvqFragData, 4, 1, true); fragData.setArraySize(resources.MaxDrawBuffers); - symbolTable.insert(ESSL1_BUILTINS, *new TVariable(NewPoolTString("gl_FragData"), fragData)); + symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_FragData"), fragData)); } break; default: break; diff --git a/gfx/angle/src/compiler/translator/Initialize.h b/gfx/angle/src/compiler/translator/Initialize.h index b5642869aa19..cc1862c90e60 100644 --- a/gfx/angle/src/compiler/translator/Initialize.h +++ b/gfx/angle/src/compiler/translator/Initialize.h @@ -8,12 +8,12 @@ #define _INITIALIZE_INCLUDED_ #include "compiler/translator/Common.h" -#include "compiler/translator/ShHandle.h" +#include "compiler/translator/Compiler.h" #include "compiler/translator/SymbolTable.h" -void InsertBuiltInFunctions(ShShaderType type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &table); +void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &table); -void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec, +void IdentifyBuiltIns(sh::GLenum type, ShShaderSpec spec, const ShBuiltInResources& resources, TSymbolTable& symbolTable); diff --git a/gfx/angle/src/compiler/translator/InitializeDll.cpp b/gfx/angle/src/compiler/translator/InitializeDll.cpp index 43f81784d0ad..c98430662aab 100644 --- a/gfx/angle/src/compiler/translator/InitializeDll.cpp +++ b/gfx/angle/src/compiler/translator/InitializeDll.cpp @@ -5,10 +5,12 @@ // #include "compiler/translator/InitializeDll.h" - #include "compiler/translator/InitializeGlobals.h" #include "compiler/translator/InitializeParseContext.h" -#include "compiler/translator/osinclude.h" + +#include "common/platform.h" + +#include bool InitProcess() { diff --git a/gfx/angle/src/compiler/translator/InitializeParseContext.cpp b/gfx/angle/src/compiler/translator/InitializeParseContext.cpp index b4defae56953..c35cedb348be 100644 --- a/gfx/angle/src/compiler/translator/InitializeParseContext.cpp +++ b/gfx/angle/src/compiler/translator/InitializeParseContext.cpp @@ -6,35 +6,37 @@ #include "compiler/translator/InitializeParseContext.h" -#include "compiler/translator/osinclude.h" +#include "common/tls.h" -OS_TLSIndex GlobalParseContextIndex = OS_INVALID_TLS_INDEX; +#include + +TLSIndex GlobalParseContextIndex = TLS_INVALID_INDEX; bool InitializeParseContextIndex() { - assert(GlobalParseContextIndex == OS_INVALID_TLS_INDEX); + assert(GlobalParseContextIndex == TLS_INVALID_INDEX); - GlobalParseContextIndex = OS_AllocTLSIndex(); - return GlobalParseContextIndex != OS_INVALID_TLS_INDEX; + GlobalParseContextIndex = CreateTLSIndex(); + return GlobalParseContextIndex != TLS_INVALID_INDEX; } void FreeParseContextIndex() { - assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX); + assert(GlobalParseContextIndex != TLS_INVALID_INDEX); - OS_FreeTLSIndex(GlobalParseContextIndex); - GlobalParseContextIndex = OS_INVALID_TLS_INDEX; + DestroyTLSIndex(GlobalParseContextIndex); + GlobalParseContextIndex = TLS_INVALID_INDEX; } void SetGlobalParseContext(TParseContext* context) { - assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX); - OS_SetTLSValue(GlobalParseContextIndex, context); + assert(GlobalParseContextIndex != TLS_INVALID_INDEX); + SetTLSValue(GlobalParseContextIndex, context); } TParseContext* GetGlobalParseContext() { - assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX); - return static_cast(OS_GetTLSValue(GlobalParseContextIndex)); + assert(GlobalParseContextIndex != TLS_INVALID_INDEX); + return static_cast(GetTLSValue(GlobalParseContextIndex)); } diff --git a/gfx/angle/src/compiler/translator/InitializeVariables.cpp b/gfx/angle/src/compiler/translator/InitializeVariables.cpp index 115c561c775f..0e3e2ebe5542 100644 --- a/gfx/angle/src/compiler/translator/InitializeVariables.cpp +++ b/gfx/angle/src/compiler/translator/InitializeVariables.cpp @@ -10,7 +10,7 @@ namespace { -TIntermConstantUnion* constructFloatConstUnionNode(const TType& type) +TIntermConstantUnion *constructFloatConstUnionNode(const TType &type) { TType myType = type; unsigned char size = myType.getNominalSize(); @@ -26,7 +26,7 @@ TIntermConstantUnion* constructFloatConstUnionNode(const TType& type) return node; } -TIntermConstantUnion* constructIndexNode(int index) +TIntermConstantUnion *constructIndexNode(int index) { ConstantUnion *u = new ConstantUnion[1]; u[0].setIConst(index); @@ -38,7 +38,7 @@ TIntermConstantUnion* constructIndexNode(int index) } // namespace anonymous -bool InitializeVariables::visitAggregate(Visit visit, TIntermAggregate* node) +bool InitializeVariables::visitAggregate(Visit visit, TIntermAggregate *node) { bool visitChildren = !mCodeInserted; switch (node->getOp()) @@ -51,17 +51,17 @@ bool InitializeVariables::visitAggregate(Visit visit, TIntermAggregate* node) ASSERT(visit == PreVisit); if (node->getName() == "main(") { - TIntermSequence &sequence = node->getSequence(); - ASSERT((sequence.size() == 1) || (sequence.size() == 2)); + TIntermSequence *sequence = node->getSequence(); + ASSERT((sequence->size() == 1) || (sequence->size() == 2)); TIntermAggregate *body = NULL; - if (sequence.size() == 1) + if (sequence->size() == 1) { body = new TIntermAggregate(EOpSequence); - sequence.push_back(body); + sequence->push_back(body); } else { - body = sequence[1]->getAsAggregate(); + body = (*sequence)[1]->getAsAggregate(); } ASSERT(body); insertInitCode(body->getSequence()); @@ -76,18 +76,18 @@ bool InitializeVariables::visitAggregate(Visit visit, TIntermAggregate* node) return visitChildren; } -void InitializeVariables::insertInitCode(TIntermSequence& sequence) +void InitializeVariables::insertInitCode(TIntermSequence *sequence) { for (size_t ii = 0; ii < mVariables.size(); ++ii) { - const InitVariableInfo& varInfo = mVariables[ii]; + const InitVariableInfo &varInfo = mVariables[ii]; if (varInfo.type.isArray()) { for (int index = varInfo.type.getArraySize() - 1; index >= 0; --index) { TIntermBinary *assign = new TIntermBinary(EOpAssign); - sequence.insert(sequence.begin(), assign); + sequence->insert(sequence->begin(), assign); TIntermBinary *indexDirect = new TIntermBinary(EOpIndexDirect); TIntermSymbol *symbol = new TIntermSymbol(0, varInfo.name, varInfo.type); @@ -104,7 +104,7 @@ void InitializeVariables::insertInitCode(TIntermSequence& sequence) else { TIntermBinary *assign = new TIntermBinary(EOpAssign); - sequence.insert(sequence.begin(), assign); + sequence->insert(sequence->begin(), assign); TIntermSymbol *symbol = new TIntermSymbol(0, varInfo.name, varInfo.type); assign->setLeft(symbol); TIntermConstantUnion *zeroConst = constructFloatConstUnionNode(varInfo.type); diff --git a/gfx/angle/src/compiler/translator/InitializeVariables.h b/gfx/angle/src/compiler/translator/InitializeVariables.h index 1cd6d7e1b511..59c3ea0a39de 100644 --- a/gfx/angle/src/compiler/translator/InitializeVariables.h +++ b/gfx/angle/src/compiler/translator/InitializeVariables.h @@ -7,7 +7,7 @@ #ifndef COMPILER_INITIALIZE_VARIABLES_H_ #define COMPILER_INITIALIZE_VARIABLES_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" class InitializeVariables : public TIntermTraverser { @@ -17,7 +17,7 @@ class InitializeVariables : public TIntermTraverser TString name; TType type; - InitVariableInfo(const TString& _name, const TType& _type) + InitVariableInfo(const TString &_name, const TType &_type) : name(_name), type(_type) { @@ -25,23 +25,23 @@ class InitializeVariables : public TIntermTraverser }; typedef TVector InitVariableInfoList; - InitializeVariables(const InitVariableInfoList& vars) + InitializeVariables(const InitVariableInfoList &vars) : mCodeInserted(false), mVariables(vars) { } protected: - virtual bool visitBinary(Visit visit, TIntermBinary* node) { return false; } - virtual bool visitUnary(Visit visit, TIntermUnary* node) { return false; } - virtual bool visitSelection(Visit visit, TIntermSelection* node) { return false; } - virtual bool visitLoop(Visit visit, TIntermLoop* node) { return false; } - virtual bool visitBranch(Visit visit, TIntermBranch* node) { return false; } + virtual bool visitBinary(Visit, TIntermBinary *node) { return false; } + virtual bool visitUnary(Visit, TIntermUnary *node) { return false; } + virtual bool visitSelection(Visit, TIntermSelection *node) { return false; } + virtual bool visitLoop(Visit, TIntermLoop *node) { return false; } + virtual bool visitBranch(Visit, TIntermBranch *node) { return false; } virtual bool visitAggregate(Visit visit, TIntermAggregate* node); private: - void insertInitCode(TIntermSequence& sequence); + void insertInitCode(TIntermSequence *sequence); InitVariableInfoList mVariables; bool mCodeInserted; diff --git a/gfx/angle/src/compiler/translator/IntermNode.cpp b/gfx/angle/src/compiler/translator/IntermNode.cpp new file mode 100644 index 000000000000..b155545ad2b6 --- /dev/null +++ b/gfx/angle/src/compiler/translator/IntermNode.cpp @@ -0,0 +1,1107 @@ +// +// Copyright (c) 2002-2014 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. +// + +// +// Build the intermediate representation. +// + +#include +#include +#include + +#include "compiler/translator/HashNames.h" +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/SymbolTable.h" + +namespace +{ + +TPrecision GetHigherPrecision(TPrecision left, TPrecision right) +{ + return left > right ? left : right; +} + +bool ValidateMultiplication(TOperator op, const TType &left, const TType &right) +{ + switch (op) + { + case EOpMul: + case EOpMulAssign: + return left.getNominalSize() == right.getNominalSize() && + left.getSecondarySize() == right.getSecondarySize(); + case EOpVectorTimesScalar: + case EOpVectorTimesScalarAssign: + return true; + case EOpVectorTimesMatrix: + return left.getNominalSize() == right.getRows(); + case EOpVectorTimesMatrixAssign: + return left.getNominalSize() == right.getRows() && + left.getNominalSize() == right.getCols(); + case EOpMatrixTimesVector: + return left.getCols() == right.getNominalSize(); + case EOpMatrixTimesScalar: + case EOpMatrixTimesScalarAssign: + return true; + case EOpMatrixTimesMatrix: + return left.getCols() == right.getRows(); + case EOpMatrixTimesMatrixAssign: + return left.getCols() == right.getCols() && + left.getRows() == right.getRows(); + + default: + UNREACHABLE(); + return false; + } +} + +bool CompareStructure(const TType& leftNodeType, + ConstantUnion *rightUnionArray, + ConstantUnion *leftUnionArray); + +bool CompareStruct(const TType &leftNodeType, + ConstantUnion *rightUnionArray, + ConstantUnion *leftUnionArray) +{ + const TFieldList &fields = leftNodeType.getStruct()->fields(); + + size_t structSize = fields.size(); + size_t index = 0; + + for (size_t j = 0; j < structSize; j++) + { + 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; +} + +bool CompareStructure(const TType &leftNodeType, + ConstantUnion *rightUnionArray, + ConstantUnion *leftUnionArray) +{ + if (leftNodeType.isArray()) + { + TType typeWithoutArrayness = leftNodeType; + typeWithoutArrayness.clearArrayness(); + + size_t arraySize = leftNodeType.getArraySize(); + + for (size_t i = 0; i < arraySize; ++i) + { + size_t offset = typeWithoutArrayness.getObjectSize() * i; + if (!CompareStruct(typeWithoutArrayness, + &rightUnionArray[offset], + &leftUnionArray[offset])) + { + return false; + } + } + } + else + { + return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray); + } + return true; +} + +} // namespace anonymous + + +//////////////////////////////////////////////////////////////// +// +// Member functions of the nodes used for building the tree. +// +//////////////////////////////////////////////////////////////// + +#define REPLACE_IF_IS(node, type, original, replacement) \ + if (node == original) { \ + node = static_cast(replacement); \ + return true; \ + } + +bool TIntermLoop::replaceChildNode( + TIntermNode *original, TIntermNode *replacement) +{ + REPLACE_IF_IS(mInit, TIntermNode, original, replacement); + REPLACE_IF_IS(mCond, TIntermTyped, original, replacement); + REPLACE_IF_IS(mExpr, TIntermTyped, original, replacement); + REPLACE_IF_IS(mBody, TIntermNode, original, replacement); + return false; +} + +void TIntermLoop::enqueueChildren(std::queue *nodeQueue) const +{ + if (mInit) + { + nodeQueue->push(mInit); + } + if (mCond) + { + nodeQueue->push(mCond); + } + if (mExpr) + { + nodeQueue->push(mExpr); + } + if (mBody) + { + nodeQueue->push(mBody); + } +} + +bool TIntermBranch::replaceChildNode( + TIntermNode *original, TIntermNode *replacement) +{ + REPLACE_IF_IS(mExpression, TIntermTyped, original, replacement); + return false; +} + +void TIntermBranch::enqueueChildren(std::queue *nodeQueue) const +{ + if (mExpression) + { + nodeQueue->push(mExpression); + } +} + +bool TIntermBinary::replaceChildNode( + TIntermNode *original, TIntermNode *replacement) +{ + REPLACE_IF_IS(mLeft, TIntermTyped, original, replacement); + REPLACE_IF_IS(mRight, TIntermTyped, original, replacement); + return false; +} + +void TIntermBinary::enqueueChildren(std::queue *nodeQueue) const +{ + if (mLeft) + { + nodeQueue->push(mLeft); + } + if (mRight) + { + nodeQueue->push(mRight); + } +} + +bool TIntermUnary::replaceChildNode( + TIntermNode *original, TIntermNode *replacement) +{ + REPLACE_IF_IS(mOperand, TIntermTyped, original, replacement); + return false; +} + +void TIntermUnary::enqueueChildren(std::queue *nodeQueue) const +{ + if (mOperand) + { + nodeQueue->push(mOperand); + } +} + +bool TIntermAggregate::replaceChildNode( + TIntermNode *original, TIntermNode *replacement) +{ + for (size_t ii = 0; ii < mSequence.size(); ++ii) + { + REPLACE_IF_IS(mSequence[ii], TIntermNode, original, replacement); + } + return false; +} + +void TIntermAggregate::enqueueChildren(std::queue *nodeQueue) const +{ + for (size_t childIndex = 0; childIndex < mSequence.size(); childIndex++) + { + nodeQueue->push(mSequence[childIndex]); + } +} + +bool TIntermSelection::replaceChildNode( + TIntermNode *original, TIntermNode *replacement) +{ + REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement); + REPLACE_IF_IS(mTrueBlock, TIntermNode, original, replacement); + REPLACE_IF_IS(mFalseBlock, TIntermNode, original, replacement); + return false; +} + +void TIntermSelection::enqueueChildren(std::queue *nodeQueue) const +{ + if (mCondition) + { + nodeQueue->push(mCondition); + } + if (mTrueBlock) + { + nodeQueue->push(mTrueBlock); + } + if (mFalseBlock) + { + nodeQueue->push(mFalseBlock); + } +} + +// +// Say whether or not an operation node changes the value of a variable. +// +bool TIntermOperator::isAssignment() const +{ + switch (mOp) + { + case EOpPostIncrement: + case EOpPostDecrement: + case EOpPreIncrement: + case EOpPreDecrement: + case EOpAssign: + case EOpAddAssign: + case EOpSubAssign: + case EOpMulAssign: + case EOpVectorTimesMatrixAssign: + case EOpVectorTimesScalarAssign: + case EOpMatrixTimesScalarAssign: + case EOpMatrixTimesMatrixAssign: + case EOpDivAssign: + return true; + default: + return false; + } +} + +// +// returns true if the operator is for one of the constructors +// +bool TIntermOperator::isConstructor() const +{ + switch (mOp) + { + case EOpConstructVec2: + case EOpConstructVec3: + case EOpConstructVec4: + case EOpConstructMat2: + case EOpConstructMat3: + case EOpConstructMat4: + case EOpConstructFloat: + case EOpConstructIVec2: + case EOpConstructIVec3: + case EOpConstructIVec4: + case EOpConstructInt: + case EOpConstructUVec2: + case EOpConstructUVec3: + case EOpConstructUVec4: + case EOpConstructUInt: + case EOpConstructBVec2: + case EOpConstructBVec3: + case EOpConstructBVec4: + case EOpConstructBool: + case EOpConstructStruct: + return true; + default: + return false; + } +} + +// +// Make sure the type of a unary operator is appropriate for its +// combination of operation and operand type. +// +// Returns false in nothing makes sense. +// +bool TIntermUnary::promote(TInfoSink &) +{ + switch (mOp) + { + case EOpLogicalNot: + if (mOperand->getBasicType() != EbtBool) + return false; + break; + case EOpNegative: + case EOpPostIncrement: + case EOpPostDecrement: + case EOpPreIncrement: + case EOpPreDecrement: + if (mOperand->getBasicType() == EbtBool) + return false; + break; + + // operators for built-ins are already type checked against their prototype + case EOpAny: + case EOpAll: + case EOpVectorLogicalNot: + return true; + + default: + if (mOperand->getBasicType() != EbtFloat) + return false; + } + + setType(mOperand->getType()); + mType.setQualifier(EvqTemporary); + + return true; +} + +// +// Establishes the type of the resultant operation, as well as +// makes the operator the correct one for the operands. +// +// Returns false if operator can't work on operands. +// +bool TIntermBinary::promote(TInfoSink &infoSink) +{ + // This function only handles scalars, vectors, and matrices. + if (mLeft->isArray() || mRight->isArray()) + { + infoSink.info.message(EPrefixInternalError, getLine(), + "Invalid operation for arrays"); + return false; + } + + // GLSL ES 2.0 does not support implicit type casting. + // So the basic type should always match. + if (mLeft->getBasicType() != mRight->getBasicType()) + { + return false; + } + + // + // Base assumption: just make the type the same as the left + // operand. Then only deviations from this need be coded. + // + setType(mLeft->getType()); + + // The result gets promoted to the highest precision. + TPrecision higherPrecision = GetHigherPrecision( + mLeft->getPrecision(), mRight->getPrecision()); + getTypePointer()->setPrecision(higherPrecision); + + // Binary operations results in temporary variables unless both + // operands are const. + if (mLeft->getQualifier() != EvqConst || mRight->getQualifier() != EvqConst) + { + getTypePointer()->setQualifier(EvqTemporary); + } + + const int nominalSize = + std::max(mLeft->getNominalSize(), mRight->getNominalSize()); + + // + // All scalars or structs. Code after this test assumes this case is removed! + // + if (nominalSize == 1) + { + switch (mOp) + { + // + // Promote to conditional + // + case EOpEqual: + case EOpNotEqual: + case EOpLessThan: + case EOpGreaterThan: + case EOpLessThanEqual: + case EOpGreaterThanEqual: + setType(TType(EbtBool, EbpUndefined)); + break; + + // + // And and Or operate on conditionals + // + case EOpLogicalAnd: + case EOpLogicalOr: + // Both operands must be of type bool. + if (mLeft->getBasicType() != EbtBool || mRight->getBasicType() != EbtBool) + { + return false; + } + setType(TType(EbtBool, EbpUndefined)); + break; + + default: + break; + } + return true; + } + + // If we reach here, at least one of the operands is vector or matrix. + // The other operand could be a scalar, vector, or matrix. + // Can these two operands be combined? + // + TBasicType basicType = mLeft->getBasicType(); + switch (mOp) + { + case EOpMul: + if (!mLeft->isMatrix() && mRight->isMatrix()) + { + if (mLeft->isVector()) + { + mOp = EOpVectorTimesMatrix; + setType(TType(basicType, higherPrecision, EvqTemporary, + mRight->getCols(), 1)); + } + else + { + mOp = EOpMatrixTimesScalar; + setType(TType(basicType, higherPrecision, EvqTemporary, + mRight->getCols(), mRight->getRows())); + } + } + else if (mLeft->isMatrix() && !mRight->isMatrix()) + { + if (mRight->isVector()) + { + mOp = EOpMatrixTimesVector; + setType(TType(basicType, higherPrecision, EvqTemporary, + mLeft->getRows(), 1)); + } + else + { + mOp = EOpMatrixTimesScalar; + } + } + else if (mLeft->isMatrix() && mRight->isMatrix()) + { + mOp = EOpMatrixTimesMatrix; + setType(TType(basicType, higherPrecision, EvqTemporary, + mRight->getCols(), mLeft->getRows())); + } + else if (!mLeft->isMatrix() && !mRight->isMatrix()) + { + if (mLeft->isVector() && mRight->isVector()) + { + // leave as component product + } + else if (mLeft->isVector() || mRight->isVector()) + { + mOp = EOpVectorTimesScalar; + setType(TType(basicType, higherPrecision, EvqTemporary, + nominalSize, 1)); + } + } + else + { + infoSink.info.message(EPrefixInternalError, getLine(), + "Missing elses"); + return false; + } + + if (!ValidateMultiplication(mOp, mLeft->getType(), mRight->getType())) + { + return false; + } + break; + + case EOpMulAssign: + if (!mLeft->isMatrix() && mRight->isMatrix()) + { + if (mLeft->isVector()) + { + mOp = EOpVectorTimesMatrixAssign; + } + else + { + return false; + } + } + else if (mLeft->isMatrix() && !mRight->isMatrix()) + { + if (mRight->isVector()) + { + return false; + } + else + { + mOp = EOpMatrixTimesScalarAssign; + } + } + else if (mLeft->isMatrix() && mRight->isMatrix()) + { + mOp = EOpMatrixTimesMatrixAssign; + setType(TType(basicType, higherPrecision, EvqTemporary, + mRight->getCols(), mLeft->getRows())); + } + else if (!mLeft->isMatrix() && !mRight->isMatrix()) + { + if (mLeft->isVector() && mRight->isVector()) + { + // leave as component product + } + else if (mLeft->isVector() || mRight->isVector()) + { + if (!mLeft->isVector()) + return false; + mOp = EOpVectorTimesScalarAssign; + setType(TType(basicType, higherPrecision, EvqTemporary, + mLeft->getNominalSize(), 1)); + } + } + else + { + infoSink.info.message(EPrefixInternalError, getLine(), + "Missing elses"); + return false; + } + + if (!ValidateMultiplication(mOp, mLeft->getType(), mRight->getType())) + { + return false; + } + break; + + case EOpAssign: + case EOpInitialize: + case EOpAdd: + case EOpSub: + case EOpDiv: + case EOpAddAssign: + case EOpSubAssign: + case EOpDivAssign: + if ((mLeft->isMatrix() && mRight->isVector()) || + (mLeft->isVector() && mRight->isMatrix())) + { + return false; + } + + // Are the sizes compatible? + if (mLeft->getNominalSize() != mRight->getNominalSize() || + mLeft->getSecondarySize() != mRight->getSecondarySize()) + { + // If the nominal size of operands do not match: + // One of them must be scalar. + if (!mLeft->isScalar() && !mRight->isScalar()) + return false; + + // Operator cannot be of type pure assignment. + if (mOp == EOpAssign || mOp == EOpInitialize) + return false; + } + + { + const int secondarySize = std::max( + mLeft->getSecondarySize(), mRight->getSecondarySize()); + setType(TType(basicType, higherPrecision, EvqTemporary, + nominalSize, secondarySize)); + } + break; + + case EOpEqual: + case EOpNotEqual: + case EOpLessThan: + case EOpGreaterThan: + case EOpLessThanEqual: + case EOpGreaterThanEqual: + if ((mLeft->getNominalSize() != mRight->getNominalSize()) || + (mLeft->getSecondarySize() != mRight->getSecondarySize())) + { + return false; + } + setType(TType(EbtBool, EbpUndefined)); + break; + + default: + return false; + } + return true; +} + +// +// The fold functions see if an operation on a constant can be done in place, +// without generating run-time code. +// +// Returns the node to keep using, which may or may not be the node passed in. +// +TIntermTyped *TIntermConstantUnion::fold( + TOperator op, TIntermTyped *constantNode, TInfoSink &infoSink) +{ + ConstantUnion *unionArray = getUnionArrayPointer(); + + if (!unionArray) + return NULL; + + size_t objectSize = getType().getObjectSize(); + + if (constantNode) + { + // binary operations + TIntermConstantUnion *node = constantNode->getAsConstantUnion(); + ConstantUnion *rightUnionArray = node->getUnionArrayPointer(); + TType returnType = getType(); + + if (!rightUnionArray) + return NULL; + + // 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 (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 (size_t i = 0; i < constantNode->getType().getObjectSize(); ++i) + { + unionArray[i] = *getUnionArrayPointer(); + } + returnType = node->getType(); + objectSize = constantNode->getType().getObjectSize(); + } + + ConstantUnion *tempConstArray = NULL; + TIntermConstantUnion *tempNode; + + bool boolNodeFlag = false; + switch(op) + { + case EOpAdd: + tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] + rightUnionArray[i]; + break; + case EOpSub: + tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] - rightUnionArray[i]; + break; + + case EOpMul: + case EOpVectorTimesScalar: + case EOpMatrixTimesScalar: + tempConstArray = new ConstantUnion[objectSize]; + 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, getLine(), + "Constant Folding cannot be done for matrix multiply"); + return NULL; + } + + const int leftCols = getCols(); + const int leftRows = getRows(); + const int rightCols = constantNode->getType().getCols(); + const int rightRows = constantNode->getType().getRows(); + const int resultCols = rightCols; + const int resultRows = leftRows; + + tempConstArray = new ConstantUnion[resultCols*resultRows]; + for (int row = 0; row < resultRows; row++) + { + for (int column = 0; column < resultCols; column++) + { + tempConstArray[resultRows * column + row].setFConst(0.0f); + for (int i = 0; i < leftCols; i++) + { + tempConstArray[resultRows * column + row].setFConst( + tempConstArray[resultRows * column + row].getFConst() + + unionArray[i * leftRows + row].getFConst() * + rightUnionArray[column * rightRows + i].getFConst()); + } + } + } + + // update return type for matrix product + returnType.setPrimarySize(resultCols); + returnType.setSecondarySize(resultRows); + } + break; + + case EOpDiv: + { + tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + { + switch (getType().getBasicType()) + { + case EbtFloat: + if (rightUnionArray[i] == 0.0f) + { + 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()); + } + break; + + case EbtInt: + if (rightUnionArray[i] == 0) + { + 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; + + case EbtUInt: + if (rightUnionArray[i] == 0) + { + infoSink.info.message( + EPrefixWarning, getLine(), + "Divide by zero error during constant folding"); + tempConstArray[i].setUConst(UINT_MAX); + } + else + { + tempConstArray[i].setUConst( + unionArray[i].getUConst() / + rightUnionArray[i].getUConst()); + } + break; + + default: + infoSink.info.message( + EPrefixInternalError, getLine(), + "Constant folding cannot be done for \"/\""); + return NULL; + } + } + } + break; + + case EOpMatrixTimesVector: + { + if (node->getBasicType() != EbtFloat) + { + infoSink.info.message( + EPrefixInternalError, getLine(), + "Constant Folding cannot be done for matrix times vector"); + return NULL; + } + + const int matrixCols = getCols(); + const int matrixRows = getRows(); + + tempConstArray = new ConstantUnion[matrixRows]; + + for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++) + { + tempConstArray[matrixRow].setFConst(0.0f); + for (int col = 0; col < matrixCols; col++) + { + tempConstArray[matrixRow].setFConst( + tempConstArray[matrixRow].getFConst() + + unionArray[col * matrixRows + matrixRow].getFConst() * + rightUnionArray[col].getFConst()); + } + } + + returnType = node->getType(); + returnType.setPrimarySize(matrixRows); + + tempNode = new TIntermConstantUnion(tempConstArray, returnType); + tempNode->setLine(getLine()); + + return tempNode; + } + + case EOpVectorTimesMatrix: + { + if (getType().getBasicType() != EbtFloat) + { + infoSink.info.message( + EPrefixInternalError, getLine(), + "Constant Folding cannot be done for vector times matrix"); + return NULL; + } + + const int matrixCols = constantNode->getType().getCols(); + const int matrixRows = constantNode->getType().getRows(); + + tempConstArray = new ConstantUnion[matrixCols]; + + for (int matrixCol = 0; matrixCol < matrixCols; matrixCol++) + { + tempConstArray[matrixCol].setFConst(0.0f); + for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++) + { + tempConstArray[matrixCol].setFConst( + tempConstArray[matrixCol].getFConst() + + unionArray[matrixRow].getFConst() * + rightUnionArray[matrixCol * matrixRows + matrixRow].getFConst()); + } + } + + returnType.setPrimarySize(matrixCols); + } + break; + + case EOpLogicalAnd: + // this code is written for possible future use, + // will not get executed currently + { + tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + { + tempConstArray[i] = unionArray[i] && rightUnionArray[i]; + } + } + break; + + case EOpLogicalOr: + // this code is written for possible future use, + // will not get executed currently + { + tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + { + tempConstArray[i] = unionArray[i] || rightUnionArray[i]; + } + } + break; + + case EOpLogicalXor: + { + tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + { + switch (getType().getBasicType()) + { + case EbtBool: + tempConstArray[i].setBConst( + unionArray[i] == rightUnionArray[i] ? false : true); + break; + default: + UNREACHABLE(); + break; + } + } + } + break; + + case EOpLessThan: + ASSERT(objectSize == 1); + tempConstArray = new ConstantUnion[1]; + tempConstArray->setBConst(*unionArray < *rightUnionArray); + returnType = TType(EbtBool, EbpUndefined, EvqConst); + break; + + case EOpGreaterThan: + ASSERT(objectSize == 1); + tempConstArray = new ConstantUnion[1]; + tempConstArray->setBConst(*unionArray > *rightUnionArray); + returnType = TType(EbtBool, EbpUndefined, EvqConst); + break; + + case EOpLessThanEqual: + { + ASSERT(objectSize == 1); + ConstantUnion constant; + constant.setBConst(*unionArray > *rightUnionArray); + tempConstArray = new ConstantUnion[1]; + tempConstArray->setBConst(!constant.getBConst()); + returnType = TType(EbtBool, EbpUndefined, EvqConst); + break; + } + + case EOpGreaterThanEqual: + { + ASSERT(objectSize == 1); + ConstantUnion constant; + constant.setBConst(*unionArray < *rightUnionArray); + tempConstArray = new ConstantUnion[1]; + tempConstArray->setBConst(!constant.getBConst()); + returnType = TType(EbtBool, EbpUndefined, EvqConst); + break; + } + + case EOpEqual: + if (getType().getBasicType() == EbtStruct) + { + if (!CompareStructure(node->getType(), + node->getUnionArrayPointer(), + unionArray)) + { + boolNodeFlag = true; + } + } + else + { + for (size_t i = 0; i < objectSize; i++) + { + if (unionArray[i] != rightUnionArray[i]) + { + boolNodeFlag = true; + break; // break out of for loop + } + } + } + + tempConstArray = new ConstantUnion[1]; + if (!boolNodeFlag) + { + tempConstArray->setBConst(true); + } + else + { + tempConstArray->setBConst(false); + } + + tempNode = new TIntermConstantUnion( + tempConstArray, TType(EbtBool, EbpUndefined, EvqConst)); + tempNode->setLine(getLine()); + + return tempNode; + + case EOpNotEqual: + if (getType().getBasicType() == EbtStruct) + { + if (CompareStructure(node->getType(), + node->getUnionArrayPointer(), + unionArray)) + { + boolNodeFlag = true; + } + } + else + { + for (size_t i = 0; i < objectSize; i++) + { + if (unionArray[i] == rightUnionArray[i]) + { + boolNodeFlag = true; + break; // break out of for loop + } + } + } + + tempConstArray = new ConstantUnion[1]; + if (!boolNodeFlag) + { + tempConstArray->setBConst(true); + } + else + { + tempConstArray->setBConst(false); + } + + tempNode = new TIntermConstantUnion( + tempConstArray, TType(EbtBool, EbpUndefined, EvqConst)); + tempNode->setLine(getLine()); + + return tempNode; + + default: + infoSink.info.message( + EPrefixInternalError, getLine(), + "Invalid operator for constant folding"); + return NULL; + } + tempNode = new TIntermConstantUnion(tempConstArray, returnType); + tempNode->setLine(getLine()); + + return tempNode; + } + else + { + // + // Do unary operations + // + TIntermConstantUnion *newNode = 0; + ConstantUnion* tempConstArray = new ConstantUnion[objectSize]; + 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; + case EbtUInt: + tempConstArray[i].setUConst(static_cast( + -static_cast(unionArray[i].getUConst()))); + break; + default: + infoSink.info.message( + EPrefixInternalError, getLine(), + "Unary operation not folded into constant"); + return NULL; + } + break; + + case EOpLogicalNot: + // this code is written for possible future use, + // will not get executed currently + switch (getType().getBasicType()) + { + case EbtBool: + tempConstArray[i].setBConst(!unionArray[i].getBConst()); + break; + default: + infoSink.info.message( + EPrefixInternalError, getLine(), + "Unary operation not folded into constant"); + return NULL; + } + break; + + default: + return NULL; + } + } + newNode = new TIntermConstantUnion(tempConstArray, getType()); + newNode->setLine(getLine()); + return newNode; + } +} + +// static +TString TIntermTraverser::hash(const TString &name, ShHashFunction64 hashFunction) +{ + if (hashFunction == NULL || name.empty()) + return name; + khronos_uint64_t number = (*hashFunction)(name.c_str(), name.length()); + TStringStream stream; + stream << HASHED_NAME_PREFIX << std::hex << number; + TString hashedName = stream.str(); + return hashedName; +} diff --git a/gfx/angle/src/compiler/translator/IntermNode.h b/gfx/angle/src/compiler/translator/IntermNode.h new file mode 100644 index 000000000000..ec440da0109e --- /dev/null +++ b/gfx/angle/src/compiler/translator/IntermNode.h @@ -0,0 +1,772 @@ +// +// Copyright (c) 2002-2014 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. +// + +// +// Definition of the in-memory high-level intermediate representation +// of shaders. This is a tree that parser creates. +// +// Nodes in the tree are defined as a hierarchy of classes derived from +// TIntermNode. Each is a node in a tree. There is no preset branching factor; +// each node can have it's own type of list of children. +// + +#ifndef COMPILER_TRANSLATOR_INTERMEDIATE_H_ +#define COMPILER_TRANSLATOR_INTERMEDIATE_H_ + +#include "GLSLANG/ShaderLang.h" + +#include +#include + +#include "compiler/translator/Common.h" +#include "compiler/translator/Types.h" +#include "compiler/translator/ConstantUnion.h" + +// +// Operators used by the high-level (parse tree) representation. +// +enum TOperator +{ + EOpNull, // if in a node, should only mean a node is still being built + EOpSequence, // denotes a list of statements, or parameters, etc. + EOpFunctionCall, + EOpFunction, // For function definition + EOpParameters, // an aggregate listing the parameters to a function + + EOpDeclaration, + EOpInvariantDeclaration, // Specialized declarations for attributing invariance + EOpPrototype, + + // + // Unary operators + // + + EOpNegative, + EOpLogicalNot, + EOpVectorLogicalNot, + + EOpPostIncrement, + EOpPostDecrement, + EOpPreIncrement, + EOpPreDecrement, + + // + // binary operations + // + + EOpAdd, + EOpSub, + EOpMul, + EOpDiv, + EOpEqual, + EOpNotEqual, + EOpVectorEqual, + EOpVectorNotEqual, + EOpLessThan, + EOpGreaterThan, + EOpLessThanEqual, + EOpGreaterThanEqual, + EOpComma, + + EOpVectorTimesScalar, + EOpVectorTimesMatrix, + EOpMatrixTimesVector, + EOpMatrixTimesScalar, + + EOpLogicalOr, + EOpLogicalXor, + EOpLogicalAnd, + + EOpIndexDirect, + EOpIndexIndirect, + EOpIndexDirectStruct, + EOpIndexDirectInterfaceBlock, + + EOpVectorSwizzle, + + // + // Built-in functions potentially mapped to operators + // + + EOpRadians, + EOpDegrees, + EOpSin, + EOpCos, + EOpTan, + EOpAsin, + EOpAcos, + EOpAtan, + + EOpPow, + EOpExp, + EOpLog, + EOpExp2, + EOpLog2, + EOpSqrt, + EOpInverseSqrt, + + EOpAbs, + EOpSign, + EOpFloor, + EOpCeil, + EOpFract, + EOpMod, + EOpMin, + EOpMax, + EOpClamp, + EOpMix, + EOpStep, + EOpSmoothStep, + + EOpLength, + EOpDistance, + EOpDot, + EOpCross, + EOpNormalize, + EOpFaceForward, + EOpReflect, + EOpRefract, + + EOpDFdx, // Fragment only, OES_standard_derivatives extension + EOpDFdy, // Fragment only, OES_standard_derivatives extension + EOpFwidth, // Fragment only, OES_standard_derivatives extension + + EOpMatrixTimesMatrix, + + EOpAny, + EOpAll, + + // + // Branch + // + + EOpKill, // Fragment only + EOpReturn, + EOpBreak, + EOpContinue, + + // + // Constructors + // + + EOpConstructInt, + EOpConstructUInt, + EOpConstructBool, + EOpConstructFloat, + EOpConstructVec2, + EOpConstructVec3, + EOpConstructVec4, + EOpConstructBVec2, + EOpConstructBVec3, + EOpConstructBVec4, + EOpConstructIVec2, + EOpConstructIVec3, + EOpConstructIVec4, + EOpConstructUVec2, + EOpConstructUVec3, + EOpConstructUVec4, + EOpConstructMat2, + EOpConstructMat3, + EOpConstructMat4, + EOpConstructStruct, + + // + // moves + // + + EOpAssign, + EOpInitialize, + EOpAddAssign, + EOpSubAssign, + EOpMulAssign, + EOpVectorTimesMatrixAssign, + EOpVectorTimesScalarAssign, + EOpMatrixTimesScalarAssign, + EOpMatrixTimesMatrixAssign, + EOpDivAssign +}; + +class TIntermTraverser; +class TIntermAggregate; +class TIntermBinary; +class TIntermUnary; +class TIntermConstantUnion; +class TIntermSelection; +class TIntermTyped; +class TIntermSymbol; +class TIntermLoop; +class TInfoSink; +class TIntermRaw; + +// +// Base class for the tree nodes +// +class TIntermNode +{ + public: + POOL_ALLOCATOR_NEW_DELETE(); + TIntermNode() + { + // TODO: Move this to TSourceLoc constructor + // after getting rid of TPublicType. + mLine.first_file = mLine.last_file = 0; + mLine.first_line = mLine.last_line = 0; + } + virtual ~TIntermNode() { } + + const TSourceLoc &getLine() const { return mLine; } + void setLine(const TSourceLoc &l) { mLine = l; } + + virtual void traverse(TIntermTraverser *) = 0; + virtual TIntermTyped *getAsTyped() { return 0; } + virtual TIntermConstantUnion *getAsConstantUnion() { return 0; } + virtual TIntermAggregate *getAsAggregate() { return 0; } + virtual TIntermBinary *getAsBinaryNode() { return 0; } + virtual TIntermUnary *getAsUnaryNode() { return 0; } + virtual TIntermSelection *getAsSelectionNode() { return 0; } + virtual TIntermSymbol *getAsSymbolNode() { return 0; } + virtual TIntermLoop *getAsLoopNode() { return 0; } + virtual TIntermRaw *getAsRawNode() { return 0; } + + // Replace a child node. Return true if |original| is a child + // node and it is replaced; otherwise, return false. + virtual bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement) = 0; + + // For traversing a tree in no particular order, but using + // heap memory. + virtual void enqueueChildren(std::queue *nodeQueue) const = 0; + + protected: + TSourceLoc mLine; +}; + +// +// This is just to help yacc. +// +struct TIntermNodePair +{ + TIntermNode *node1; + TIntermNode *node2; +}; + +// +// Intermediate class for nodes that have a type. +// +class TIntermTyped : public TIntermNode +{ + public: + TIntermTyped(const TType &t) : mType(t) { } + virtual TIntermTyped *getAsTyped() { return this; } + + virtual bool hasSideEffects() const = 0; + + void setType(const TType &t) { mType = t; } + const TType &getType() const { return mType; } + TType *getTypePointer() { return &mType; } + + TBasicType getBasicType() const { return mType.getBasicType(); } + TQualifier getQualifier() const { return mType.getQualifier(); } + TPrecision getPrecision() const { return mType.getPrecision(); } + int getCols() const { return mType.getCols(); } + int getRows() const { return mType.getRows(); } + int getNominalSize() const { return mType.getNominalSize(); } + int getSecondarySize() const { return mType.getSecondarySize(); } + + bool isInterfaceBlock() const { return mType.isInterfaceBlock(); } + bool isMatrix() const { return mType.isMatrix(); } + bool isArray() const { return mType.isArray(); } + bool isVector() const { return mType.isVector(); } + bool isScalar() const { return mType.isScalar(); } + bool isScalarInt() const { return mType.isScalarInt(); } + const char *getBasicString() const { return mType.getBasicString(); } + const char *getQualifierString() const { return mType.getQualifierString(); } + TString getCompleteString() const { return mType.getCompleteString(); } + + int getArraySize() const { return mType.getArraySize(); } + + protected: + TType mType; +}; + +// +// Handle for, do-while, and while loops. +// +enum TLoopType +{ + ELoopFor, + ELoopWhile, + ELoopDoWhile +}; + +class TIntermLoop : public TIntermNode +{ + public: + TIntermLoop(TLoopType type, + TIntermNode *init, TIntermTyped *cond, TIntermTyped *expr, + TIntermNode *body) + : mType(type), + mInit(init), + mCond(cond), + mExpr(expr), + mBody(body), + mUnrollFlag(false) { } + + virtual TIntermLoop *getAsLoopNode() { return this; } + virtual void traverse(TIntermTraverser *); + virtual bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement); + + TLoopType getType() const { return mType; } + TIntermNode *getInit() { return mInit; } + TIntermTyped *getCondition() { return mCond; } + TIntermTyped *getExpression() { return mExpr; } + TIntermNode *getBody() { return mBody; } + + void setUnrollFlag(bool flag) { mUnrollFlag = flag; } + bool getUnrollFlag() const { return mUnrollFlag; } + + virtual void enqueueChildren(std::queue *nodeQueue) const; + + protected: + TLoopType mType; + TIntermNode *mInit; // for-loop initialization + TIntermTyped *mCond; // loop exit condition + TIntermTyped *mExpr; // for-loop expression + TIntermNode *mBody; // loop body + + bool mUnrollFlag; // Whether the loop should be unrolled or not. +}; + +// +// Handle break, continue, return, and kill. +// +class TIntermBranch : public TIntermNode +{ + public: + TIntermBranch(TOperator op, TIntermTyped *e) + : mFlowOp(op), + mExpression(e) { } + + virtual void traverse(TIntermTraverser *); + virtual bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement); + + TOperator getFlowOp() { return mFlowOp; } + TIntermTyped* getExpression() { return mExpression; } + + virtual void enqueueChildren(std::queue *nodeQueue) const; + +protected: + TOperator mFlowOp; + TIntermTyped *mExpression; // non-zero except for "return exp;" statements +}; + +// +// Nodes that correspond to symbols or constants in the source code. +// +class TIntermSymbol : public TIntermTyped +{ + public: + // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym. + // If sym comes from per process globalpoolallocator, then it causes increased memory usage + // per compile it is essential to use "symbol = sym" to assign to symbol + TIntermSymbol(int id, const TString &symbol, const TType &type) + : TIntermTyped(type), + mId(id) + { + mSymbol = symbol; + } + + virtual bool hasSideEffects() const { return false; } + + int getId() const { return mId; } + const TString &getSymbol() const { return mSymbol; } + + void setId(int newId) { mId = newId; } + + virtual void traverse(TIntermTraverser *); + virtual TIntermSymbol *getAsSymbolNode() { return this; } + virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; } + + virtual void enqueueChildren(std::queue *nodeQueue) const {} + + protected: + int mId; + TString mSymbol; +}; + +// A Raw node stores raw code, that the translator will insert verbatim +// into the output stream. Useful for transformation operations that make +// complex code that might not fit naturally into the GLSL model. +class TIntermRaw : public TIntermTyped +{ + public: + TIntermRaw(const TType &type, const TString &rawText) + : TIntermTyped(type), + mRawText(rawText) { } + + virtual bool hasSideEffects() const { return false; } + + TString getRawText() const { return mRawText; } + + virtual void traverse(TIntermTraverser *); + + virtual TIntermRaw *getAsRawNode() { return this; } + virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; } + virtual void enqueueChildren(std::queue *nodeQueue) const {} + + protected: + TString mRawText; +}; + +class TIntermConstantUnion : public TIntermTyped +{ + public: + TIntermConstantUnion(ConstantUnion *unionPointer, const TType &type) + : TIntermTyped(type), + mUnionArrayPointer(unionPointer) { } + + virtual bool hasSideEffects() const { return false; } + + ConstantUnion *getUnionArrayPointer() const { return mUnionArrayPointer; } + + int getIConst(size_t index) const + { + return mUnionArrayPointer ? mUnionArrayPointer[index].getIConst() : 0; + } + unsigned int getUConst(size_t index) const + { + return mUnionArrayPointer ? mUnionArrayPointer[index].getUConst() : 0; + } + float getFConst(size_t index) const + { + return mUnionArrayPointer ? mUnionArrayPointer[index].getFConst() : 0.0f; + } + bool getBConst(size_t index) const + { + return mUnionArrayPointer ? mUnionArrayPointer[index].getBConst() : false; + } + + virtual TIntermConstantUnion *getAsConstantUnion() { return this; } + virtual void traverse(TIntermTraverser *); + virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; } + + TIntermTyped *fold(TOperator, TIntermTyped *, TInfoSink &); + + virtual void enqueueChildren(std::queue *nodeQueue) const {} + + protected: + ConstantUnion *mUnionArrayPointer; +}; + +// +// Intermediate class for node types that hold operators. +// +class TIntermOperator : public TIntermTyped +{ + public: + TOperator getOp() const { return mOp; } + void setOp(TOperator op) { mOp = op; } + + bool isAssignment() const; + bool isConstructor() const; + + virtual bool hasSideEffects() const { return isAssignment(); } + + protected: + TIntermOperator(TOperator op) + : TIntermTyped(TType(EbtFloat, EbpUndefined)), + mOp(op) {} + TIntermOperator(TOperator op, const TType &type) + : TIntermTyped(type), + mOp(op) {} + + TOperator mOp; +}; + +// +// Nodes for all the basic binary math operators. +// +class TIntermBinary : public TIntermOperator +{ + public: + TIntermBinary(TOperator op) + : TIntermOperator(op), + mAddIndexClamp(false) {} + + virtual TIntermBinary *getAsBinaryNode() { return this; } + virtual void traverse(TIntermTraverser *); + virtual bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement); + + virtual bool hasSideEffects() const + { + return isAssignment() || mLeft->hasSideEffects() || mRight->hasSideEffects(); + } + + void setLeft(TIntermTyped *node) { mLeft = node; } + void setRight(TIntermTyped *node) { mRight = node; } + TIntermTyped *getLeft() const { return mLeft; } + TIntermTyped *getRight() const { return mRight; } + bool promote(TInfoSink &); + + void setAddIndexClamp() { mAddIndexClamp = true; } + bool getAddIndexClamp() { return mAddIndexClamp; } + + virtual void enqueueChildren(std::queue *nodeQueue) const; + + protected: + TIntermTyped* mLeft; + TIntermTyped* mRight; + + // If set to true, wrap any EOpIndexIndirect with a clamp to bounds. + bool mAddIndexClamp; +}; + +// +// Nodes for unary math operators. +// +class TIntermUnary : public TIntermOperator +{ + public: + TIntermUnary(TOperator op, const TType &type) + : TIntermOperator(op, type), + mOperand(NULL), + mUseEmulatedFunction(false) {} + TIntermUnary(TOperator op) + : TIntermOperator(op), + mOperand(NULL), + mUseEmulatedFunction(false) {} + + virtual void traverse(TIntermTraverser *); + virtual TIntermUnary *getAsUnaryNode() { return this; } + virtual bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement); + + virtual bool hasSideEffects() const + { + return isAssignment() || mOperand->hasSideEffects(); + } + + void setOperand(TIntermTyped *operand) { mOperand = operand; } + TIntermTyped *getOperand() { return mOperand; } + bool promote(TInfoSink &); + + void setUseEmulatedFunction() { mUseEmulatedFunction = true; } + bool getUseEmulatedFunction() { return mUseEmulatedFunction; } + + virtual void enqueueChildren(std::queue *nodeQueue) const; + + protected: + TIntermTyped *mOperand; + + // If set to true, replace the built-in function call with an emulated one + // to work around driver bugs. + bool mUseEmulatedFunction; +}; + +typedef TVector TIntermSequence; +typedef TVector TQualifierList; + +// +// Nodes that operate on an arbitrary sized set of children. +// +class TIntermAggregate : public TIntermOperator +{ + public: + TIntermAggregate() + : TIntermOperator(EOpNull), + mUserDefined(false), + mUseEmulatedFunction(false) { } + TIntermAggregate(TOperator op) + : TIntermOperator(op), + mUseEmulatedFunction(false) { } + ~TIntermAggregate() { } + + virtual TIntermAggregate *getAsAggregate() { return this; } + virtual void traverse(TIntermTraverser *); + virtual bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement); + + // Conservatively assume function calls and other aggregate operators have side-effects + virtual bool hasSideEffects() const { return true; } + + TIntermSequence *getSequence() { return &mSequence; } + + void setName(const TString &name) { mName = name; } + const TString &getName() const { return mName; } + + void setUserDefined() { mUserDefined = true; } + bool isUserDefined() const { return mUserDefined; } + + void setOptimize(bool optimize) { mOptimize = optimize; } + bool getOptimize() const { return mOptimize; } + void setDebug(bool debug) { mDebug = debug; } + bool getDebug() const { return mDebug; } + + void setUseEmulatedFunction() { mUseEmulatedFunction = true; } + bool getUseEmulatedFunction() { return mUseEmulatedFunction; } + + virtual void enqueueChildren(std::queue *nodeQueue) const; + + protected: + TIntermAggregate(const TIntermAggregate &); // disallow copy constructor + TIntermAggregate &operator=(const TIntermAggregate &); // disallow assignment operator + TIntermSequence mSequence; + TString mName; + bool mUserDefined; // used for user defined function names + + bool mOptimize; + bool mDebug; + + // If set to true, replace the built-in function call with an emulated one + // to work around driver bugs. + bool mUseEmulatedFunction; +}; + +// +// For if tests. Simplified since there is no switch statement. +// +class TIntermSelection : public TIntermTyped +{ + public: + TIntermSelection(TIntermTyped *cond, TIntermNode *trueB, TIntermNode *falseB) + : TIntermTyped(TType(EbtVoid, EbpUndefined)), + mCondition(cond), + mTrueBlock(trueB), + mFalseBlock(falseB) {} + TIntermSelection(TIntermTyped *cond, TIntermNode *trueB, TIntermNode *falseB, + const TType &type) + : TIntermTyped(type), + mCondition(cond), + mTrueBlock(trueB), + mFalseBlock(falseB) {} + + virtual void traverse(TIntermTraverser *); + virtual bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement); + + // Conservatively assume selections have side-effects + virtual bool hasSideEffects() const { return true; } + + bool usesTernaryOperator() const { return getBasicType() != EbtVoid; } + TIntermNode *getCondition() const { return mCondition; } + TIntermNode *getTrueBlock() const { return mTrueBlock; } + TIntermNode *getFalseBlock() const { return mFalseBlock; } + TIntermSelection *getAsSelectionNode() { return this; } + + virtual void enqueueChildren(std::queue *nodeQueue) const; + +protected: + TIntermTyped *mCondition; + TIntermNode *mTrueBlock; + TIntermNode *mFalseBlock; +}; + +enum Visit +{ + PreVisit, + InVisit, + PostVisit +}; + +// +// For traversing the tree. User should derive from this, +// put their traversal specific data in it, and then pass +// it to a Traverse method. +// +// When using this, just fill in the methods for nodes you want visited. +// Return false from a pre-visit to skip visiting that node's subtree. +// +class TIntermTraverser +{ + public: + POOL_ALLOCATOR_NEW_DELETE(); + // TODO(zmo): remove default values. + TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, + bool rightToLeft = false) + : preVisit(preVisit), + inVisit(inVisit), + postVisit(postVisit), + rightToLeft(rightToLeft), + mDepth(0), + mMaxDepth(0) {} + virtual ~TIntermTraverser() {} + + virtual void visitSymbol(TIntermSymbol *) {} + virtual void visitRaw(TIntermRaw *) {} + virtual void visitConstantUnion(TIntermConstantUnion *) {} + virtual bool visitBinary(Visit, TIntermBinary *) { return true; } + virtual bool visitUnary(Visit, TIntermUnary *) { return true; } + virtual bool visitSelection(Visit, TIntermSelection *) { return true; } + virtual bool visitAggregate(Visit, TIntermAggregate *) { return true; } + virtual bool visitLoop(Visit, TIntermLoop *) { return true; } + virtual bool visitBranch(Visit, TIntermBranch *) { return true; } + + int getMaxDepth() const { return mMaxDepth; } + + void incrementDepth(TIntermNode *current) + { + mDepth++; + mMaxDepth = std::max(mMaxDepth, mDepth); + mPath.push_back(current); + } + + void decrementDepth() + { + mDepth--; + mPath.pop_back(); + } + + TIntermNode *getParentNode() + { + return mPath.size() == 0 ? NULL : mPath.back(); + } + + // Return the original name if hash function pointer is NULL; + // otherwise return the hashed name. + static TString hash(const TString& name, ShHashFunction64 hashFunction); + + const bool preVisit; + const bool inVisit; + const bool postVisit; + const bool rightToLeft; + + protected: + int mDepth; + int mMaxDepth; + + // All the nodes from root to the current node's parent during traversing. + TVector mPath; +}; + +// +// For traversing the tree, and computing max depth. +// Takes a maximum depth limit to prevent stack overflow. +// +class TMaxDepthTraverser : public TIntermTraverser +{ + public: + POOL_ALLOCATOR_NEW_DELETE(); + TMaxDepthTraverser(int depthLimit) + : TIntermTraverser(true, true, false, false), + mDepthLimit(depthLimit) { } + + virtual bool visitBinary(Visit, TIntermBinary *) { return depthCheck(); } + virtual bool visitUnary(Visit, TIntermUnary *) { return depthCheck(); } + virtual bool visitSelection(Visit, TIntermSelection *) { return depthCheck(); } + virtual bool visitAggregate(Visit, TIntermAggregate *) { return depthCheck(); } + virtual bool visitLoop(Visit, TIntermLoop *) { return depthCheck(); } + virtual bool visitBranch(Visit, TIntermBranch *) { return depthCheck(); } + +protected: + bool depthCheck() const { return mMaxDepth < mDepthLimit; } + + int mDepthLimit; +}; + +#endif // COMPILER_TRANSLATOR_INTERMEDIATE_H_ diff --git a/gfx/angle/src/compiler/translator/IntermTraverse.cpp b/gfx/angle/src/compiler/translator/IntermTraverse.cpp index a5794880cdfe..72b2033fb314 100644 --- a/gfx/angle/src/compiler/translator/IntermTraverse.cpp +++ b/gfx/angle/src/compiler/translator/IntermTraverse.cpp @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" // // Traverse the intermediate representation tree, and @@ -55,25 +55,25 @@ void TIntermBinary::traverse(TIntermTraverser *it) if (it->rightToLeft) { - if (right) - right->traverse(it); + if (mRight) + mRight->traverse(it); if (it->inVisit) visit = it->visitBinary(InVisit, this); - if (visit && left) - left->traverse(it); + if (visit && mLeft) + mLeft->traverse(it); } else { - if (left) - left->traverse(it); + if (mLeft) + mLeft->traverse(it); if (it->inVisit) visit = it->visitBinary(InVisit, this); - if (visit && right) - right->traverse(it); + if (visit && mRight) + mRight->traverse(it); } it->decrementDepth(); @@ -99,7 +99,7 @@ void TIntermUnary::traverse(TIntermTraverser *it) if (visit) { it->incrementDepth(this); - operand->traverse(it); + mOperand->traverse(it); it->decrementDepth(); } @@ -123,26 +123,28 @@ void TIntermAggregate::traverse(TIntermTraverser *it) if (it->rightToLeft) { - for (TIntermSequence::reverse_iterator sit = sequence.rbegin(); sit != sequence.rend(); sit++) + for (TIntermSequence::reverse_iterator sit = mSequence.rbegin(); + sit != mSequence.rend(); sit++) { (*sit)->traverse(it); if (visit && it->inVisit) { - if (*sit != sequence.front()) + if (*sit != mSequence.front()) visit = it->visitAggregate(InVisit, this); } } } else { - for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++) + for (TIntermSequence::iterator sit = mSequence.begin(); + sit != mSequence.end(); sit++) { (*sit)->traverse(it); if (visit && it->inVisit) { - if (*sit != sequence.back()) + if (*sit != mSequence.back()) visit = it->visitAggregate(InVisit, this); } } @@ -165,20 +167,24 @@ void TIntermSelection::traverse(TIntermTraverser *it) if (it->preVisit) visit = it->visitSelection(PreVisit, this); - if (visit) { + if (visit) + { it->incrementDepth(this); - if (it->rightToLeft) { - if (falseBlock) - falseBlock->traverse(it); - if (trueBlock) - trueBlock->traverse(it); - condition->traverse(it); - } else { - condition->traverse(it); - if (trueBlock) - trueBlock->traverse(it); - if (falseBlock) - falseBlock->traverse(it); + if (it->rightToLeft) + { + if (mFalseBlock) + mFalseBlock->traverse(it); + if (mTrueBlock) + mTrueBlock->traverse(it); + mCondition->traverse(it); + } + else + { + mCondition->traverse(it); + if (mTrueBlock) + mTrueBlock->traverse(it); + if (mFalseBlock) + mFalseBlock->traverse(it); } it->decrementDepth(); } @@ -203,31 +209,31 @@ void TIntermLoop::traverse(TIntermTraverser *it) if (it->rightToLeft) { - if (expr) - expr->traverse(it); + if (mExpr) + mExpr->traverse(it); - if (body) - body->traverse(it); + if (mBody) + mBody->traverse(it); - if (cond) - cond->traverse(it); + if (mCond) + mCond->traverse(it); - if (init) - init->traverse(it); + if (mInit) + mInit->traverse(it); } else { - if (init) - init->traverse(it); + if (mInit) + mInit->traverse(it); - if (cond) - cond->traverse(it); + if (mCond) + mCond->traverse(it); - if (body) - body->traverse(it); + if (mBody) + mBody->traverse(it); - if (expr) - expr->traverse(it); + if (mExpr) + mExpr->traverse(it); } it->decrementDepth(); @@ -247,9 +253,9 @@ void TIntermBranch::traverse(TIntermTraverser *it) if (it->preVisit) visit = it->visitBranch(PreVisit, this); - if (visit && expression) { + if (visit && mExpression) { it->incrementDepth(this); - expression->traverse(it); + mExpression->traverse(it); it->decrementDepth(); } @@ -257,3 +263,7 @@ void TIntermBranch::traverse(TIntermTraverser *it) it->visitBranch(PostVisit, this); } +void TIntermRaw::traverse(TIntermTraverser *it) +{ + it->visitRaw(this); +} diff --git a/gfx/angle/src/compiler/translator/Intermediate.cpp b/gfx/angle/src/compiler/translator/Intermediate.cpp index 9df2afc53c28..ef4f83307cdd 100644 --- a/gfx/angle/src/compiler/translator/Intermediate.cpp +++ b/gfx/angle/src/compiler/translator/Intermediate.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2014 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,124 +12,10 @@ #include #include -#include "compiler/translator/HashNames.h" -#include "compiler/translator/localintermediate.h" -#include "compiler/translator/QualifierAlive.h" +#include "compiler/translator/Intermediate.h" #include "compiler/translator/RemoveTree.h" #include "compiler/translator/SymbolTable.h" -bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray); - -static TPrecision GetHigherPrecision(TPrecision left, TPrecision right) -{ - return left > right ? left : right; -} - -const char* getOperatorString(TOperator op) -{ - switch (op) { - case EOpInitialize: return "="; - case EOpAssign: return "="; - case EOpAddAssign: return "+="; - case EOpSubAssign: return "-="; - case EOpDivAssign: return "/="; - - // Fall-through. - case EOpMulAssign: - case EOpVectorTimesMatrixAssign: - case EOpVectorTimesScalarAssign: - case EOpMatrixTimesScalarAssign: - case EOpMatrixTimesMatrixAssign: return "*="; - - // Fall-through. - case EOpIndexDirect: - case EOpIndexIndirect: return "[]"; - - case EOpIndexDirectStruct: - case EOpIndexDirectInterfaceBlock: return "."; - case EOpVectorSwizzle: return "."; - case EOpAdd: return "+"; - case EOpSub: return "-"; - case EOpMul: return "*"; - case EOpDiv: return "/"; - case EOpMod: UNIMPLEMENTED(); break; - case EOpEqual: return "=="; - case EOpNotEqual: return "!="; - case EOpLessThan: return "<"; - case EOpGreaterThan: return ">"; - case EOpLessThanEqual: return "<="; - case EOpGreaterThanEqual: return ">="; - - // Fall-through. - case EOpVectorTimesScalar: - case EOpVectorTimesMatrix: - case EOpMatrixTimesVector: - case EOpMatrixTimesScalar: - case EOpMatrixTimesMatrix: return "*"; - - case EOpLogicalOr: return "||"; - case EOpLogicalXor: return "^^"; - case EOpLogicalAnd: return "&&"; - case EOpNegative: return "-"; - case EOpVectorLogicalNot: return "not"; - case EOpLogicalNot: return "!"; - case EOpPostIncrement: return "++"; - case EOpPostDecrement: return "--"; - case EOpPreIncrement: return "++"; - case EOpPreDecrement: return "--"; - - // Fall-through. - case EOpConvIntToBool: - case EOpConvUIntToBool: - case EOpConvFloatToBool: return "bool"; - - // Fall-through. - case EOpConvBoolToFloat: - case EOpConvUIntToFloat: - case EOpConvIntToFloat: return "float"; - - // Fall-through. - case EOpConvFloatToInt: - case EOpConvUIntToInt: - case EOpConvBoolToInt: return "int"; - - // Fall-through. - case EOpConvIntToUInt: - case EOpConvFloatToUInt: - case EOpConvBoolToUInt: return "uint"; - - case EOpRadians: return "radians"; - case EOpDegrees: return "degrees"; - case EOpSin: return "sin"; - case EOpCos: return "cos"; - case EOpTan: return "tan"; - case EOpAsin: return "asin"; - case EOpAcos: return "acos"; - case EOpAtan: return "atan"; - case EOpExp: return "exp"; - case EOpLog: return "log"; - case EOpExp2: return "exp2"; - case EOpLog2: return "log2"; - case EOpSqrt: return "sqrt"; - case EOpInverseSqrt: return "inversesqrt"; - case EOpAbs: return "abs"; - case EOpSign: return "sign"; - case EOpFloor: return "floor"; - case EOpCeil: return "ceil"; - case EOpFract: return "fract"; - case EOpLength: return "length"; - case EOpNormalize: return "normalize"; - case EOpDFdx: return "dFdx"; - case EOpDFdy: return "dFdy"; - case EOpFwidth: return "fwidth"; - case EOpAny: return "any"; - case EOpAll: return "all"; - - default: break; - } - return ""; -} - //////////////////////////////////////////////////////////////////////////// // // First set of functions are to help build the intermediate representation. @@ -143,9 +29,10 @@ const char* getOperatorString(TOperator op) // // Returns the added node. // -TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, const TSourceLoc& line) +TIntermSymbol *TIntermediate::addSymbol( + int id, const TString &name, const TType &type, const TSourceLoc &line) { - TIntermSymbol* node = new TIntermSymbol(id, name, type); + TIntermSymbol *node = new TIntermSymbol(id, name, type); node->setLine(line); return node; @@ -156,76 +43,71 @@ TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType // // Returns the added node. // -TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line) +TIntermTyped *TIntermediate::addBinaryMath( + TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line) { - switch (op) { - case EOpEqual: - case EOpNotEqual: - if (left->isArray()) - return 0; - break; - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - if (left->isMatrix() || left->isArray() || left->isVector() || left->getBasicType() == EbtStruct) { - return 0; - } - break; - case EOpLogicalOr: - case EOpLogicalXor: - case EOpLogicalAnd: - if (left->getBasicType() != EbtBool || left->isMatrix() || left->isArray() || left->isVector()) { - return 0; - } - break; - case EOpAdd: - case EOpSub: - case EOpDiv: - case EOpMul: - if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool) - return 0; - default: break; + switch (op) + { + case EOpEqual: + case EOpNotEqual: + if (left->isArray()) + return NULL; + break; + case EOpLessThan: + case EOpGreaterThan: + case EOpLessThanEqual: + case EOpGreaterThanEqual: + if (left->isMatrix() || left->isArray() || left->isVector() || + left->getBasicType() == EbtStruct) + { + return NULL; + } + break; + case EOpLogicalOr: + case EOpLogicalXor: + case EOpLogicalAnd: + if (left->getBasicType() != EbtBool || + left->isMatrix() || left->isArray() || left->isVector()) + { + return NULL; + } + break; + case EOpAdd: + case EOpSub: + case EOpDiv: + case EOpMul: + if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool) + return NULL; + default: + break; } - // - // First try converting the children to compatible types. - // - if (left->getType().getStruct() && right->getType().getStruct()) { - if (left->getType() != right->getType()) - return 0; - } else { - TIntermTyped* child = addConversion(op, left->getType(), right); - if (child) - right = child; - else { - child = addConversion(op, right->getType(), left); - if (child) - left = child; - else - return 0; - } + if (left->getBasicType() != right->getBasicType()) + { + return NULL; } // // Need a new node holding things together then. Make // one and promote it to the right type. // - TIntermBinary* node = new TIntermBinary(op); + TIntermBinary *node = new TIntermBinary(op); node->setLine(line); node->setLeft(left); node->setRight(right); - if (!node->promote(infoSink)) - return 0; + if (!node->promote(mInfoSink)) + return NULL; // // See if we can fold constants. // TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion(); TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion(); - if (leftTempConstant && rightTempConstant) { - TIntermTyped *typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, infoSink); + if (leftTempConstant && rightTempConstant) + { + TIntermTyped *typedReturnNode = + leftTempConstant->fold(node->getOp(), rightTempConstant, mInfoSink); if (typedReturnNode) return typedReturnNode; @@ -239,23 +121,24 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn // // Returns the added node. // -TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const 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 (left->getType().getStruct() || right->getType().getStruct()) + { + if (left->getType() != right->getType()) + { + return NULL; + } + } + + TIntermBinary *node = new TIntermBinary(op); node->setLine(line); - TIntermTyped* child = addConversion(op, left->getType(), right); - if (child == 0) - return 0; - node->setLeft(left); - node->setRight(child); - if (! node->promote(infoSink)) - return 0; + node->setRight(right); + if (!node->promote(mInfoSink)) + return NULL; return node; } @@ -267,9 +150,10 @@ 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, const TSourceLoc& line) +TIntermTyped *TIntermediate::addIndex( + TOperator op, TIntermTyped *base, TIntermTyped *index, const TSourceLoc &line) { - TIntermBinary* node = new TIntermBinary(op); + TIntermBinary *node = new TIntermBinary(op); node->setLine(line); node->setLeft(base); node->setRight(index); @@ -284,67 +168,43 @@ TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermT // // Returns the added node. // -TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, const TSourceLoc& line) +TIntermTyped *TIntermediate::addUnaryMath( + TOperator op, TIntermNode *childNode, const TSourceLoc &line) { - TIntermUnary* node; - TIntermTyped* child = childNode->getAsTyped(); + TIntermUnary *node; + TIntermTyped *child = childNode->getAsTyped(); - if (child == 0) { - infoSink.info.message(EPrefixInternalError, line, "Bad type in AddUnaryMath"); - return 0; + if (child == NULL) + { + mInfoSink.info.message(EPrefixInternalError, line, + "Bad type in AddUnaryMath"); + return NULL; } - switch (op) { - case EOpLogicalNot: - if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) { - return 0; - } - break; + switch (op) + { + case EOpLogicalNot: + if (child->getType().getBasicType() != EbtBool || + child->getType().isMatrix() || + child->getType().isArray() || + child->getType().isVector()) + { + return NULL; + } + break; - case EOpPostIncrement: - case EOpPreIncrement: - case EOpPostDecrement: - case EOpPreDecrement: - case EOpNegative: - if (child->getType().getBasicType() == EbtStruct || child->getType().isArray()) - return 0; - default: break; - } - - // - // Do we need to promote the operand? - // - // Note: Implicit promotions were removed from the language. - // - TBasicType newType = EbtVoid; - switch (op) { - case EOpConstructInt: newType = EbtInt; break; - case EOpConstructUInt: newType = EbtUInt; break; - case EOpConstructBool: newType = EbtBool; break; - case EOpConstructFloat: newType = EbtFloat; break; - default: break; - } - - if (newType != EbtVoid) { - child = addConversion(op, TType(newType, child->getPrecision(), EvqTemporary, - child->getNominalSize(), - child->getSecondarySize(), - child->isArray()), - child); - if (child == 0) - return 0; - } - - // - // For constructors, we are now done, it's all in the conversion. - // - switch (op) { - case EOpConstructInt: - case EOpConstructUInt: - case EOpConstructBool: - case EOpConstructFloat: - return child; - default: break; + case EOpPostIncrement: + case EOpPreIncrement: + case EOpPostDecrement: + case EOpPreDecrement: + case EOpNegative: + if (child->getType().getBasicType() == EbtStruct || + child->getType().isArray()) + { + return NULL; + } + default: + break; } TIntermConstantUnion *childTempConstant = 0; @@ -358,11 +218,12 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, node->setLine(line); node->setOperand(child); - if (! node->promote(infoSink)) + if (!node->promote(mInfoSink)) return 0; - if (childTempConstant) { - TIntermTyped* newChild = childTempConstant->fold(op, 0, infoSink); + if (childTempConstant) + { + TIntermTyped *newChild = childTempConstant->fold(op, 0, mInfoSink); if (newChild) return newChild; @@ -381,24 +242,30 @@ 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, const TSourceLoc& line) +TIntermAggregate *TIntermediate::setAggregateOperator( + TIntermNode *node, TOperator op, const TSourceLoc &line) { - TIntermAggregate* aggNode; + TIntermAggregate *aggNode; // // Make sure we have an aggregate. If not turn it into one. // - if (node) { + if (node) + { aggNode = node->getAsAggregate(); - if (aggNode == 0 || aggNode->getOp() != EOpNull) { + if (aggNode == NULL || aggNode->getOp() != EOpNull) + { // // Make an aggregate containing this node. // aggNode = new TIntermAggregate(); - aggNode->getSequence().push_back(node); + aggNode->getSequence()->push_back(node); } - } else + } + else + { aggNode = new TIntermAggregate(); + } // // Set the operator. @@ -409,140 +276,6 @@ TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperat return aggNode; } -// -// Convert one type to another. -// -// Returns the node representing the conversion, which could be the same -// node passed in if no conversion was needed. -// -// Return 0 if a conversion can't be done. -// -TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TIntermTyped* node) -{ - // - // Does the base type allow operation? - // - if (node->getBasicType() == EbtVoid || - IsSampler(node->getBasicType())) - { - return 0; - } - - // - // Otherwise, if types are identical, no problem - // - if (type == node->getType()) - return node; - - // - // If one's a structure, then no conversions. - // - if (type.getStruct() || node->getType().getStruct()) - return 0; - - // - // If one's an array, then no conversions. - // - if (type.isArray() || node->getType().isArray()) - return 0; - - TBasicType promoteTo; - - switch (op) { - // - // Explicit conversions - // - case EOpConstructBool: - promoteTo = EbtBool; - break; - case EOpConstructFloat: - promoteTo = EbtFloat; - break; - case EOpConstructInt: - promoteTo = EbtInt; - break; - case EOpConstructUInt: - promoteTo = EbtUInt; - break; - default: - // - // implicit conversions were removed from the language. - // - if (type.getBasicType() != node->getType().getBasicType()) - return 0; - // - // Size and structure could still differ, but that's - // handled by operator promotion. - // - return node; - } - - if (node->getAsConstantUnion()) { - - return (promoteConstantUnion(promoteTo, node->getAsConstantUnion())); - } else { - - // - // Add a new newNode for the conversion. - // - TIntermUnary* newNode = 0; - - TOperator newOp = EOpNull; - switch (promoteTo) { - case EbtFloat: - switch (node->getBasicType()) { - case EbtInt: newOp = EOpConvIntToFloat; break; - case EbtUInt: newOp = EOpConvFloatToUInt; break; - case EbtBool: newOp = EOpConvBoolToFloat; break; - default: - infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node"); - return 0; - } - break; - case EbtBool: - switch (node->getBasicType()) { - case EbtInt: newOp = EOpConvIntToBool; break; - case EbtUInt: newOp = EOpConvBoolToUInt; break; - case EbtFloat: newOp = EOpConvFloatToBool; break; - default: - infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node"); - return 0; - } - break; - case EbtInt: - switch (node->getBasicType()) { - case EbtUInt: newOp = EOpConvUIntToInt; break; - case EbtBool: newOp = EOpConvBoolToInt; break; - case EbtFloat: newOp = EOpConvFloatToInt; break; - default: - infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node"); - return 0; - } - break; - case EbtUInt: - switch (node->getBasicType()) { - case EbtInt: newOp = EOpConvIntToUInt; break; - case EbtBool: newOp = EOpConvBoolToUInt; break; - case EbtFloat: newOp = EOpConvFloatToUInt; break; - default: - infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node"); - return 0; - } - break; - default: - infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion type"); - return 0; - } - - TType type(promoteTo, node->getPrecision(), EvqTemporary, node->getNominalSize(), node->getSecondarySize(), node->isArray()); - newNode = new TIntermUnary(newOp, type); - newNode->setLine(node->getLine()); - newNode->setOperand(node); - - return newNode; - } -} - // // Safe way to combine two nodes into an aggregate. Works with null pointers, // a node that's not a aggregate yet, etc. @@ -550,22 +283,24 @@ 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, const TSourceLoc& line) +TIntermAggregate *TIntermediate::growAggregate( + TIntermNode *left, TIntermNode *right, const TSourceLoc &line) { - if (left == 0 && right == 0) - return 0; + if (left == NULL && right == NULL) + return NULL; - TIntermAggregate* aggNode = 0; + TIntermAggregate *aggNode = NULL; if (left) aggNode = left->getAsAggregate(); - if (!aggNode || aggNode->getOp() != EOpNull) { + if (!aggNode || aggNode->getOp() != EOpNull) + { aggNode = new TIntermAggregate; if (left) - aggNode->getSequence().push_back(left); + aggNode->getSequence()->push_back(left); } if (right) - aggNode->getSequence().push_back(right); + aggNode->getSequence()->push_back(right); aggNode->setLine(line); @@ -575,15 +310,16 @@ TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* r // // Turn an existing node into an aggregate. // -// Returns an aggregate, unless 0 was passed in for the existing node. +// Returns an aggregate, unless NULL was passed in for the existing node. // -TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, const TSourceLoc& line) +TIntermAggregate *TIntermediate::makeAggregate( + TIntermNode *node, const TSourceLoc &line) { - if (node == 0) - return 0; + if (node == NULL) + return NULL; - TIntermAggregate* aggNode = new TIntermAggregate; - aggNode->getSequence().push_back(node); + TIntermAggregate *aggNode = new TIntermAggregate; + aggNode->getSequence()->push_back(node); aggNode->setLine(line); @@ -597,32 +333,45 @@ TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, const TSourceL // // Returns the selection node created. // -TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, const TSourceLoc& line) +TIntermNode *TIntermediate::addSelection( + TIntermTyped *cond, TIntermNodePair nodePair, const TSourceLoc &line) { // // For compile time constant selections, prune the code and // test now. // - if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion()) { + if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion()) + { if (cond->getAsConstantUnion()->getBConst(0) == true) - return nodePair.node1 ? setAggregateOperator(nodePair.node1, EOpSequence, nodePair.node1->getLine()) : NULL; + { + return nodePair.node1 ? setAggregateOperator( + nodePair.node1, EOpSequence, nodePair.node1->getLine()) : NULL; + } else - return nodePair.node2 ? setAggregateOperator(nodePair.node2, EOpSequence, nodePair.node2->getLine()) : NULL; + { + return nodePair.node2 ? setAggregateOperator( + nodePair.node2, EOpSequence, nodePair.node2->getLine()) : NULL; + } } - TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2); + TIntermSelection *node = new TIntermSelection( + cond, nodePair.node1, nodePair.node2); node->setLine(line); return node; } - -TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line) +TIntermTyped *TIntermediate::addComma( + TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line) { - if (left->getType().getQualifier() == EvqConst && right->getType().getQualifier() == EvqConst) { + if (left->getType().getQualifier() == EvqConst && + right->getType().getQualifier() == EvqConst) + { return right; - } else { + } + else + { TIntermTyped *commaAggregate = growAggregate(left, right, line); commaAggregate->getAsAggregate()->setOp(EOpComma); commaAggregate->setType(right->getType()); @@ -638,27 +387,24 @@ TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, c // // Returns the selection node created, or 0 if one could not be. // -TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc& line) +TIntermTyped *TIntermediate::addSelection( + TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock, + const TSourceLoc &line) { - // - // Get compatible types. - // - TIntermTyped* child = addConversion(EOpSequence, trueBlock->getType(), falseBlock); - if (child) - falseBlock = child; - else { - child = addConversion(EOpSequence, falseBlock->getType(), trueBlock); - if (child) - trueBlock = child; - else - return 0; + if (!cond || !trueBlock || !falseBlock || + trueBlock->getType() != falseBlock->getType()) + { + return NULL; } // // See if all the operands are constant, then fold it otherwise not. // - if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) { + if (cond->getAsConstantUnion() && + trueBlock->getAsConstantUnion() && + falseBlock->getAsConstantUnion()) + { if (cond->getAsConstantUnion()->getBConst(0)) return trueBlock; else @@ -668,7 +414,8 @@ TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* true // // Make a selection node. // - TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType()); + TIntermSelection *node = new TIntermSelection( + cond, trueBlock, falseBlock, trueBlock->getType()); node->getTypePointer()->setQualifier(EvqTemporary); node->setLine(line); @@ -681,29 +428,33 @@ TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* true // Returns the constant union node created. // -TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, const TSourceLoc& line) +TIntermConstantUnion *TIntermediate::addConstantUnion( + ConstantUnion *unionArrayPointer, const TType &t, const TSourceLoc &line) { - TIntermConstantUnion* node = new TIntermConstantUnion(unionArrayPointer, t); + TIntermConstantUnion *node = new TIntermConstantUnion(unionArrayPointer, t); node->setLine(line); return node; } -TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, const TSourceLoc& line) +TIntermTyped *TIntermediate::addSwizzle( + TVectorFields &fields, const TSourceLoc &line) { - TIntermAggregate* node = new TIntermAggregate(EOpSequence); + TIntermAggregate *node = new TIntermAggregate(EOpSequence); node->setLine(line); - TIntermConstantUnion* constIntNode; - TIntermSequence &sequenceVector = node->getSequence(); - ConstantUnion* unionArray; + TIntermConstantUnion *constIntNode; + TIntermSequence *sequenceVector = node->getSequence(); + ConstantUnion *unionArray; - for (int i = 0; i < fields.num; i++) { + for (int i = 0; i < fields.num; i++) + { unionArray = new ConstantUnion[1]; unionArray->setIConst(fields.offsets[i]); - constIntNode = addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), line); - sequenceVector.push_back(constIntNode); + constIntNode = addConstantUnion( + unionArray, TType(EbtInt, EbpUndefined, EvqConst), line); + sequenceVector->push_back(constIntNode); } return node; @@ -712,9 +463,11 @@ TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, const TSourceLoc& // // Create loop nodes. // -TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTyped* cond, TIntermTyped* expr, TIntermNode* body, const 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); + TIntermNode *node = new TIntermLoop(type, init, cond, expr, body); node->setLine(line); return node; @@ -723,14 +476,16 @@ TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTy // // Add branches. // -TIntermBranch* TIntermediate::addBranch(TOperator branchOp, const TSourceLoc& line) +TIntermBranch* TIntermediate::addBranch( + TOperator branchOp, const TSourceLoc &line) { return addBranch(branchOp, 0, line); } -TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, const TSourceLoc& line) +TIntermBranch* TIntermediate::addBranch( + TOperator branchOp, TIntermTyped *expression, const TSourceLoc &line) { - TIntermBranch* node = new TIntermBranch(branchOp, expression); + TIntermBranch *node = new TIntermBranch(branchOp, expression); node->setLine(line); return node; @@ -740,15 +495,15 @@ TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expres // This is to be executed once the final root is put on top by the parsing // process. // -bool TIntermediate::postProcess(TIntermNode* root) +bool TIntermediate::postProcess(TIntermNode *root) { - if (root == 0) + if (root == NULL) return true; // // First, finish off the top level sequence, if any // - TIntermAggregate* aggRoot = root->getAsAggregate(); + TIntermAggregate *aggRoot = root->getAsAggregate(); if (aggRoot && aggRoot->getOp() == EOpNull) aggRoot->setOp(EOpSequence); @@ -758,1078 +513,8 @@ bool TIntermediate::postProcess(TIntermNode* root) // // This deletes the tree. // -void TIntermediate::remove(TIntermNode* root) +void TIntermediate::remove(TIntermNode *root) { if (root) RemoveAllTreeNodes(root); } - -//////////////////////////////////////////////////////////////// -// -// Member functions of the nodes used for building the tree. -// -//////////////////////////////////////////////////////////////// - -#define REPLACE_IF_IS(node, type, original, replacement) \ - if (node == original) { \ - node = static_cast(replacement); \ - return true; \ - } - -bool TIntermLoop::replaceChildNode( - TIntermNode *original, TIntermNode *replacement) -{ - REPLACE_IF_IS(init, TIntermNode, original, replacement); - REPLACE_IF_IS(cond, TIntermTyped, original, replacement); - REPLACE_IF_IS(expr, TIntermTyped, original, replacement); - REPLACE_IF_IS(body, TIntermNode, original, replacement); - return false; -} - -void TIntermLoop::enqueueChildren(std::queue *nodeQueue) const -{ - if (init) - { - nodeQueue->push(init); - } - if (cond) - { - nodeQueue->push(cond); - } - if (expr) - { - nodeQueue->push(expr); - } - if (body) - { - nodeQueue->push(body); - } -} - -bool TIntermBranch::replaceChildNode( - TIntermNode *original, TIntermNode *replacement) -{ - REPLACE_IF_IS(expression, TIntermTyped, original, replacement); - return false; -} - -void TIntermBranch::enqueueChildren(std::queue *nodeQueue) const -{ - if (expression) - { - nodeQueue->push(expression); - } -} - -bool TIntermBinary::replaceChildNode( - TIntermNode *original, TIntermNode *replacement) -{ - REPLACE_IF_IS(left, TIntermTyped, original, replacement); - REPLACE_IF_IS(right, TIntermTyped, original, replacement); - return false; -} - -void TIntermBinary::enqueueChildren(std::queue *nodeQueue) const -{ - if (left) - { - nodeQueue->push(left); - } - if (right) - { - nodeQueue->push(right); - } -} - -bool TIntermUnary::replaceChildNode( - TIntermNode *original, TIntermNode *replacement) -{ - REPLACE_IF_IS(operand, TIntermTyped, original, replacement); - return false; -} - -void TIntermUnary::enqueueChildren(std::queue *nodeQueue) const -{ - if (operand) - { - nodeQueue->push(operand); - } -} - -bool TIntermAggregate::replaceChildNode( - TIntermNode *original, TIntermNode *replacement) -{ - for (size_t ii = 0; ii < sequence.size(); ++ii) - { - REPLACE_IF_IS(sequence[ii], TIntermNode, original, replacement); - } - return false; -} - -void TIntermAggregate::enqueueChildren(std::queue *nodeQueue) const -{ - for (size_t childIndex = 0; childIndex < sequence.size(); childIndex++) - { - nodeQueue->push(sequence[childIndex]); - } -} - -bool TIntermSelection::replaceChildNode( - TIntermNode *original, TIntermNode *replacement) -{ - REPLACE_IF_IS(condition, TIntermTyped, original, replacement); - REPLACE_IF_IS(trueBlock, TIntermNode, original, replacement); - REPLACE_IF_IS(falseBlock, TIntermNode, original, replacement); - return false; -} - -void TIntermSelection::enqueueChildren(std::queue *nodeQueue) const -{ - if (condition) - { - nodeQueue->push(condition); - } - if (trueBlock) - { - nodeQueue->push(trueBlock); - } - if (falseBlock) - { - nodeQueue->push(falseBlock); - } -} - -// -// Say whether or not an operation node changes the value of a variable. -// -bool TIntermOperator::isAssignment() const -{ - switch (op) { - case EOpPostIncrement: - case EOpPostDecrement: - case EOpPreIncrement: - case EOpPreDecrement: - case EOpAssign: - case EOpAddAssign: - case EOpSubAssign: - case EOpMulAssign: - case EOpVectorTimesMatrixAssign: - case EOpVectorTimesScalarAssign: - case EOpMatrixTimesScalarAssign: - case EOpMatrixTimesMatrixAssign: - case EOpDivAssign: - return true; - default: - return false; - } -} - -// -// returns true if the operator is for one of the constructors -// -bool TIntermOperator::isConstructor() const -{ - switch (op) { - case EOpConstructVec2: - case EOpConstructVec3: - case EOpConstructVec4: - case EOpConstructMat2: - case EOpConstructMat3: - case EOpConstructMat4: - case EOpConstructFloat: - case EOpConstructIVec2: - case EOpConstructIVec3: - case EOpConstructIVec4: - case EOpConstructInt: - case EOpConstructUVec2: - case EOpConstructUVec3: - case EOpConstructUVec4: - case EOpConstructUInt: - case EOpConstructBVec2: - case EOpConstructBVec3: - case EOpConstructBVec4: - case EOpConstructBool: - case EOpConstructStruct: - return true; - default: - return false; - } -} - -// -// Make sure the type of a unary operator is appropriate for its -// combination of operation and operand type. -// -// Returns false in nothing makes sense. -// -bool TIntermUnary::promote(TInfoSink&) -{ - switch (op) { - case EOpLogicalNot: - if (operand->getBasicType() != EbtBool) - return false; - break; - case EOpNegative: - case EOpPostIncrement: - case EOpPostDecrement: - case EOpPreIncrement: - case EOpPreDecrement: - if (operand->getBasicType() == EbtBool) - return false; - break; - - // operators for built-ins are already type checked against their prototype - case EOpAny: - case EOpAll: - case EOpVectorLogicalNot: - return true; - - default: - if (operand->getBasicType() != EbtFloat) - return false; - } - - setType(operand->getType()); - type.setQualifier(EvqTemporary); - - return true; -} - -bool validateMultiplication(TOperator op, const TType &left, const TType &right) -{ - switch (op) - { - case EOpMul: - case EOpMulAssign: - return left.getNominalSize() == right.getNominalSize() && left.getSecondarySize() == right.getSecondarySize(); - case EOpVectorTimesScalar: - case EOpVectorTimesScalarAssign: - return true; - case EOpVectorTimesMatrix: - return left.getNominalSize() == right.getRows(); - case EOpVectorTimesMatrixAssign: - return left.getNominalSize() == right.getRows() && left.getNominalSize() == right.getCols(); - case EOpMatrixTimesVector: - return left.getCols() == right.getNominalSize(); - case EOpMatrixTimesScalar: - case EOpMatrixTimesScalarAssign: - return true; - case EOpMatrixTimesMatrix: - return left.getCols() == right.getRows(); - case EOpMatrixTimesMatrixAssign: - return left.getCols() == right.getCols() && left.getRows() == right.getRows(); - - default: - UNREACHABLE(); - return false; - } -} - -// -// Establishes the type of the resultant operation, as well as -// makes the operator the correct one for the operands. -// -// Returns false if operator can't work on operands. -// -bool TIntermBinary::promote(TInfoSink& infoSink) -{ - // This function only handles scalars, vectors, and matrices. - if (left->isArray() || right->isArray()) - { - infoSink.info.message(EPrefixInternalError, getLine(), "Invalid operation for arrays"); - return false; - } - - // GLSL ES 2.0 does not support implicit type casting. - // So the basic type should always match. - if (left->getBasicType() != right->getBasicType()) - return false; - - // - // Base assumption: just make the type the same as the left - // operand. Then only deviations from this need be coded. - // - setType(left->getType()); - - // The result gets promoted to the highest precision. - TPrecision higherPrecision = GetHigherPrecision(left->getPrecision(), right->getPrecision()); - getTypePointer()->setPrecision(higherPrecision); - - // Binary operations results in temporary variables unless both - // operands are const. - if (left->getQualifier() != EvqConst || right->getQualifier() != EvqConst) - { - getTypePointer()->setQualifier(EvqTemporary); - } - - const int nominalSize = std::max(left->getNominalSize(), right->getNominalSize()); - - // - // All scalars or structs. Code after this test assumes this case is removed! - // - if (nominalSize == 1) - { - switch (op) - { - // - // Promote to conditional - // - case EOpEqual: - case EOpNotEqual: - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - setType(TType(EbtBool, EbpUndefined)); - break; - - // - // And and Or operate on conditionals - // - case EOpLogicalAnd: - case EOpLogicalOr: - // Both operands must be of type bool. - if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool) - { - return false; - } - setType(TType(EbtBool, EbpUndefined)); - break; - - default: - break; - } - return true; - } - - // If we reach here, at least one of the operands is vector or matrix. - // The other operand could be a scalar, vector, or matrix. - // Can these two operands be combined? - // - TBasicType basicType = left->getBasicType(); - switch (op) - { - case EOpMul: - if (!left->isMatrix() && right->isMatrix()) - { - if (left->isVector()) - { - op = EOpVectorTimesMatrix; - setType(TType(basicType, higherPrecision, EvqTemporary, right->getCols(), 1)); - } - else - { - op = EOpMatrixTimesScalar; - setType(TType(basicType, higherPrecision, EvqTemporary, right->getCols(), right->getRows())); - } - } - else if (left->isMatrix() && !right->isMatrix()) - { - if (right->isVector()) - { - op = EOpMatrixTimesVector; - setType(TType(basicType, higherPrecision, EvqTemporary, left->getRows(), 1)); - } - else - { - op = EOpMatrixTimesScalar; - } - } - else if (left->isMatrix() && right->isMatrix()) - { - op = EOpMatrixTimesMatrix; - setType(TType(basicType, higherPrecision, EvqTemporary, right->getCols(), left->getRows())); - } - else if (!left->isMatrix() && !right->isMatrix()) - { - if (left->isVector() && right->isVector()) - { - // leave as component product - } - else if (left->isVector() || right->isVector()) - { - op = EOpVectorTimesScalar; - setType(TType(basicType, higherPrecision, EvqTemporary, nominalSize, 1)); - } - } - else - { - infoSink.info.message(EPrefixInternalError, getLine(), "Missing elses"); - return false; - } - - if (!validateMultiplication(op, left->getType(), right->getType())) - { - return false; - } - break; - - case EOpMulAssign: - if (!left->isMatrix() && right->isMatrix()) - { - if (left->isVector()) - { - op = EOpVectorTimesMatrixAssign; - } - else - { - return false; - } - } - else if (left->isMatrix() && !right->isMatrix()) - { - if (right->isVector()) - { - return false; - } - else - { - op = EOpMatrixTimesScalarAssign; - } - } - else if (left->isMatrix() && right->isMatrix()) - { - op = EOpMatrixTimesMatrixAssign; - setType(TType(basicType, higherPrecision, EvqTemporary, right->getCols(), left->getRows())); - } - else if (!left->isMatrix() && !right->isMatrix()) - { - if (left->isVector() && right->isVector()) - { - // leave as component product - } - else if (left->isVector() || right->isVector()) - { - if (! left->isVector()) - return false; - op = EOpVectorTimesScalarAssign; - setType(TType(basicType, higherPrecision, EvqTemporary, left->getNominalSize(), 1)); - } - } - else - { - infoSink.info.message(EPrefixInternalError, getLine(), "Missing elses"); - return false; - } - - if (!validateMultiplication(op, left->getType(), right->getType())) - { - return false; - } - break; - - case EOpAssign: - case EOpInitialize: - case EOpAdd: - case EOpSub: - case EOpDiv: - case EOpAddAssign: - case EOpSubAssign: - case EOpDivAssign: - { - if ((left->isMatrix() && right->isVector()) || - (left->isVector() && right->isMatrix())) - return false; - - // Are the sizes compatible? - if (left->getNominalSize() != right->getNominalSize() || left->getSecondarySize() != right->getSecondarySize()) - { - // If the nominal size of operands do not match: - // One of them must be scalar. - if (!left->isScalar() && !right->isScalar()) - return false; - - // Operator cannot be of type pure assignment. - if (op == EOpAssign || op == EOpInitialize) - return false; - } - - const int secondarySize = std::max(left->getSecondarySize(), right->getSecondarySize()); - - setType(TType(basicType, higherPrecision, EvqTemporary, nominalSize, secondarySize)); - } - break; - - case EOpEqual: - case EOpNotEqual: - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - if ((left->getNominalSize() != right->getNominalSize()) || - (left->getSecondarySize() != right->getSecondarySize())) - return false; - setType(TType(EbtBool, EbpUndefined)); - break; - - default: - return false; - } - - return true; -} - -bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray) -{ - const TFieldList& fields = leftNodeType.getStruct()->fields(); - - size_t structSize = fields.size(); - size_t index = 0; - - for (size_t j = 0; j < structSize; j++) { - 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; -} - -bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray) -{ - if (leftNodeType.isArray()) { - TType typeWithoutArrayness = leftNodeType; - typeWithoutArrayness.clearArrayness(); - - size_t arraySize = leftNodeType.getArraySize(); - - for (size_t i = 0; i < arraySize; ++i) { - size_t offset = typeWithoutArrayness.getObjectSize() * i; - if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset])) - return false; - } - } else - return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray); - - return true; -} - -// -// The fold functions see if an operation on a constant can be done in place, -// without generating run-time code. -// -// Returns the node to keep using, which may or may not be the node passed in. -// - -TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink) -{ - ConstantUnion *unionArray = getUnionArrayPointer(); - - if (!unionArray) - return 0; - - size_t objectSize = getType().getObjectSize(); - - if (constantNode) - { - // binary operations - TIntermConstantUnion *node = constantNode->getAsConstantUnion(); - ConstantUnion *rightUnionArray = node->getUnionArrayPointer(); - TType returnType = getType(); - - if (!rightUnionArray) - return 0; - - // 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 (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 (size_t i = 0; i < constantNode->getType().getObjectSize(); ++i) - { - unionArray[i] = *getUnionArrayPointer(); - } - returnType = node->getType(); - objectSize = constantNode->getType().getObjectSize(); - } - - ConstantUnion* tempConstArray = 0; - TIntermConstantUnion *tempNode; - - bool boolNodeFlag = false; - switch(op) { - case EOpAdd: - tempConstArray = new ConstantUnion[objectSize]; - { - for (size_t i = 0; i < objectSize; i++) - tempConstArray[i] = unionArray[i] + rightUnionArray[i]; - } - break; - case EOpSub: - tempConstArray = new ConstantUnion[objectSize]; - { - for (size_t i = 0; i < objectSize; i++) - tempConstArray[i] = unionArray[i] - rightUnionArray[i]; - } - break; - - case EOpMul: - case EOpVectorTimesScalar: - case EOpMatrixTimesScalar: - tempConstArray = new ConstantUnion[objectSize]; - { - 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, getLine(), "Constant Folding cannot be done for matrix multiply"); - return 0; - } - - const int leftCols = getCols(); - const int leftRows = getRows(); - const int rightCols = constantNode->getType().getCols(); - const int rightRows = constantNode->getType().getRows(); - const int resultCols = rightCols; - const int resultRows = leftRows; - - tempConstArray = new ConstantUnion[resultCols*resultRows]; - for (int row = 0; row < resultRows; row++) - { - for (int column = 0; column < resultCols; column++) - { - tempConstArray[resultRows * column + row].setFConst(0.0f); - for (int i = 0; i < leftCols; i++) - { - tempConstArray[resultRows * column + row].setFConst(tempConstArray[resultRows * column + row].getFConst() + unionArray[i * leftRows + row].getFConst() * (rightUnionArray[column * rightRows + i].getFConst())); - } - } - } - - // update return type for matrix product - returnType.setPrimarySize(resultCols); - returnType.setSecondarySize(resultRows); - } - break; - - case EOpDiv: - { - tempConstArray = new ConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - { - switch (getType().getBasicType()) - { - case EbtFloat: - if (rightUnionArray[i] == 0.0f) - { - 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()); - } - break; - - case EbtInt: - if (rightUnionArray[i] == 0) - { - 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; - - case EbtUInt: - if (rightUnionArray[i] == 0) - { - infoSink.info.message(EPrefixWarning, getLine(), "Divide by zero error during constant folding"); - tempConstArray[i].setUConst(UINT_MAX); - } - else - { - tempConstArray[i].setUConst(unionArray[i].getUConst() / rightUnionArray[i].getUConst()); - } - break; - - default: - infoSink.info.message(EPrefixInternalError, getLine(), "Constant folding cannot be done for \"/\""); - return 0; - } - } - } - break; - - case EOpMatrixTimesVector: - { - if (node->getBasicType() != EbtFloat) - { - infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for matrix times vector"); - return 0; - } - - const int matrixCols = getCols(); - const int matrixRows = getRows(); - - tempConstArray = new ConstantUnion[matrixRows]; - - for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++) - { - tempConstArray[matrixRow].setFConst(0.0f); - for (int col = 0; col < matrixCols; col++) - { - tempConstArray[matrixRow].setFConst(tempConstArray[matrixRow].getFConst() + ((unionArray[col * matrixRows + matrixRow].getFConst()) * rightUnionArray[col].getFConst())); - } - } - - returnType = node->getType(); - returnType.setPrimarySize(matrixRows); - - tempNode = new TIntermConstantUnion(tempConstArray, returnType); - tempNode->setLine(getLine()); - - return tempNode; - } - - case EOpVectorTimesMatrix: - { - if (getType().getBasicType() != EbtFloat) - { - infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for vector times matrix"); - return 0; - } - - const int matrixCols = constantNode->getType().getCols(); - const int matrixRows = constantNode->getType().getRows(); - - tempConstArray = new ConstantUnion[matrixCols]; - - for (int matrixCol = 0; matrixCol < matrixCols; matrixCol++) - { - tempConstArray[matrixCol].setFConst(0.0f); - for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++) - { - tempConstArray[matrixCol].setFConst(tempConstArray[matrixCol].getFConst() + ((unionArray[matrixRow].getFConst()) * rightUnionArray[matrixCol * matrixRows + matrixRow].getFConst())); - } - } - - returnType.setPrimarySize(matrixCols); - } - break; - - case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently - { - tempConstArray = new ConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - { - tempConstArray[i] = unionArray[i] && rightUnionArray[i]; - } - } - break; - - case EOpLogicalOr: // this code is written for possible future use, will not get executed currently - { - tempConstArray = new ConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - { - tempConstArray[i] = unionArray[i] || rightUnionArray[i]; - } - } - break; - - case EOpLogicalXor: - { - tempConstArray = new ConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - { - switch (getType().getBasicType()) - { - case EbtBool: - tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); - break; - default: - UNREACHABLE(); - break; - } - } - } - break; - - case EOpLessThan: - assert(objectSize == 1); - tempConstArray = new ConstantUnion[1]; - tempConstArray->setBConst(*unionArray < *rightUnionArray); - returnType = TType(EbtBool, EbpUndefined, EvqConst); - break; - - case EOpGreaterThan: - assert(objectSize == 1); - tempConstArray = new ConstantUnion[1]; - tempConstArray->setBConst(*unionArray > *rightUnionArray); - returnType = TType(EbtBool, EbpUndefined, EvqConst); - break; - - case EOpLessThanEqual: - { - assert(objectSize == 1); - ConstantUnion constant; - constant.setBConst(*unionArray > *rightUnionArray); - tempConstArray = new ConstantUnion[1]; - tempConstArray->setBConst(!constant.getBConst()); - returnType = TType(EbtBool, EbpUndefined, EvqConst); - break; - } - - case EOpGreaterThanEqual: - { - assert(objectSize == 1); - ConstantUnion constant; - constant.setBConst(*unionArray < *rightUnionArray); - tempConstArray = new ConstantUnion[1]; - tempConstArray->setBConst(!constant.getBConst()); - returnType = TType(EbtBool, EbpUndefined, EvqConst); - break; - } - - case EOpEqual: - if (getType().getBasicType() == EbtStruct) - { - if (!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray)) - boolNodeFlag = true; - } - else - { - for (size_t i = 0; i < objectSize; i++) - { - if (unionArray[i] != rightUnionArray[i]) - { - boolNodeFlag = true; - break; // break out of for loop - } - } - } - - tempConstArray = new ConstantUnion[1]; - if (!boolNodeFlag) - { - tempConstArray->setBConst(true); - } - else - { - tempConstArray->setBConst(false); - } - - tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst)); - tempNode->setLine(getLine()); - - return tempNode; - - case EOpNotEqual: - if (getType().getBasicType() == EbtStruct) - { - if (CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray)) - boolNodeFlag = true; - } - else - { - for (size_t i = 0; i < objectSize; i++) - { - if (unionArray[i] == rightUnionArray[i]) - { - boolNodeFlag = true; - break; // break out of for loop - } - } - } - - tempConstArray = new ConstantUnion[1]; - if (!boolNodeFlag) - { - tempConstArray->setBConst(true); - } - else - { - tempConstArray->setBConst(false); - } - - tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst)); - tempNode->setLine(getLine()); - - return tempNode; - - default: - infoSink.info.message(EPrefixInternalError, getLine(), "Invalid operator for constant folding"); - return 0; - } - tempNode = new TIntermConstantUnion(tempConstArray, returnType); - tempNode->setLine(getLine()); - - return tempNode; - } - else - { - // - // Do unary operations - // - TIntermConstantUnion *newNode = 0; - ConstantUnion* tempConstArray = new ConstantUnion[objectSize]; - 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; - case EbtUInt: tempConstArray[i].setUConst(static_cast(-static_cast(unionArray[i].getUConst()))); break; - default: - infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); - return 0; - } - break; - - case EOpLogicalNot: // this code is written for possible future use, will not get executed currently - switch (getType().getBasicType()) - { - case EbtBool: tempConstArray[i].setBConst(!unionArray[i].getBConst()); break; - default: - infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); - return 0; - } - break; - - default: - return 0; - } - } - newNode = new TIntermConstantUnion(tempConstArray, getType()); - newNode->setLine(getLine()); - return newNode; - } -} - -TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node) -{ - size_t size = node->getType().getObjectSize(); - - ConstantUnion *leftUnionArray = new ConstantUnion[size]; - - for (size_t i=0; i < size; i++) { - - switch (promoteTo) { - case EbtFloat: - switch (node->getType().getBasicType()) { - case EbtInt: - leftUnionArray[i].setFConst(static_cast(node->getIConst(i))); - break; - case EbtUInt: - leftUnionArray[i].setFConst(static_cast(node->getUConst(i))); - break; - case EbtBool: - leftUnionArray[i].setFConst(static_cast(node->getBConst(i))); - break; - case EbtFloat: - leftUnionArray[i].setFConst(static_cast(node->getFConst(i))); - break; - default: - infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote"); - return 0; - } - break; - case EbtInt: - switch (node->getType().getBasicType()) { - case EbtInt: - leftUnionArray[i].setIConst(static_cast(node->getIConst(i))); - break; - case EbtUInt: - leftUnionArray[i].setIConst(static_cast(node->getUConst(i))); - break; - case EbtBool: - leftUnionArray[i].setIConst(static_cast(node->getBConst(i))); - break; - case EbtFloat: - leftUnionArray[i].setIConst(static_cast(node->getFConst(i))); - break; - default: - infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote"); - return 0; - } - break; - case EbtUInt: - switch (node->getType().getBasicType()) { - case EbtInt: - leftUnionArray[i].setUConst(static_cast(node->getIConst(i))); - break; - case EbtUInt: - leftUnionArray[i].setUConst(static_cast(node->getUConst(i))); - break; - case EbtBool: - leftUnionArray[i].setUConst(static_cast(node->getBConst(i))); - break; - case EbtFloat: - leftUnionArray[i].setUConst(static_cast(node->getFConst(i))); - break; - default: - infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote"); - return 0; - } - break; - case EbtBool: - switch (node->getType().getBasicType()) { - case EbtInt: - leftUnionArray[i].setBConst(node->getIConst(i) != 0); - break; - case EbtUInt: - leftUnionArray[i].setBConst(node->getUConst(i) != 0); - break; - case EbtBool: - leftUnionArray[i].setBConst(node->getBConst(i)); - break; - case EbtFloat: - leftUnionArray[i].setBConst(node->getFConst(i) != 0.0f); - break; - default: - infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote"); - return 0; - } - - break; - default: - infoSink.info.message(EPrefixInternalError, node->getLine(), "Incorrect data type found"); - return 0; - } - - } - - const TType& t = node->getType(); - - return addConstantUnion(leftUnionArray, TType(promoteTo, t.getPrecision(), t.getQualifier(), t.getNominalSize(), t.getSecondarySize(), t.isArray()), node->getLine()); -} - -// static -TString TIntermTraverser::hash(const TString& name, ShHashFunction64 hashFunction) -{ - if (hashFunction == NULL || name.empty()) - return name; - khronos_uint64_t number = (*hashFunction)(name.c_str(), name.length()); - TStringStream stream; - stream << HASHED_NAME_PREFIX << std::hex << number; - TString hashedName = stream.str(); - return hashedName; -} diff --git a/gfx/angle/src/compiler/translator/Intermediate.h b/gfx/angle/src/compiler/translator/Intermediate.h new file mode 100644 index 000000000000..3b7e7bd80238 --- /dev/null +++ b/gfx/angle/src/compiler/translator/Intermediate.h @@ -0,0 +1,67 @@ +// +// Copyright (c) 2002-2014 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_TRANSLATOR_LOCAL_INTERMEDIATE_H_ +#define COMPILER_TRANSLATOR_LOCAL_INTERMEDIATE_H_ + +#include "compiler/translator/IntermNode.h" + +struct TVectorFields +{ + int offsets[4]; + int num; +}; + +// +// Set of helper functions to help parse and build the tree. +// +class TInfoSink; +class TIntermediate +{ + public: + POOL_ALLOCATOR_NEW_DELETE(); + TIntermediate(TInfoSink &i) + : mInfoSink(i) { } + + TIntermSymbol *addSymbol( + int id, const TString &, const TType &, const TSourceLoc &); + TIntermTyped *addBinaryMath( + TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &); + 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 &); + 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 &); + // TODO(zmo): Get rid of default value. + bool parseConstTree(const TSourceLoc &, TIntermNode *, ConstantUnion *, + TOperator, 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 outputTree(TIntermNode *); + + private: + void operator=(TIntermediate &); // prevent assignments + + TInfoSink & mInfoSink; +}; + +#endif // COMPILER_TRANSLATOR_LOCAL_INTERMEDIATE_H_ diff --git a/gfx/angle/src/compiler/translator/LoopInfo.cpp b/gfx/angle/src/compiler/translator/LoopInfo.cpp index 226f1b238071..d931a18a2312 100644 --- a/gfx/angle/src/compiler/translator/LoopInfo.cpp +++ b/gfx/angle/src/compiler/translator/LoopInfo.cpp @@ -93,9 +93,9 @@ void TLoopIndexInfo::fillInfo(TIntermLoop *node) // Here we assume all the operations are valid, because the loop node is // already validated in ValidateLimitations. - TIntermSequence &declSeq = + TIntermSequence *declSeq = node->getInit()->getAsAggregate()->getSequence(); - TIntermBinary *declInit = declSeq[0]->getAsBinaryNode(); + TIntermBinary *declInit = (*declSeq)[0]->getAsBinaryNode(); TIntermSymbol *symbol = declInit->getLeft()->getAsSymbolNode(); mId = symbol->getId(); diff --git a/gfx/angle/src/compiler/translator/LoopInfo.h b/gfx/angle/src/compiler/translator/LoopInfo.h index 5a140c339e99..5f72a6e9448f 100644 --- a/gfx/angle/src/compiler/translator/LoopInfo.h +++ b/gfx/angle/src/compiler/translator/LoopInfo.h @@ -7,7 +7,7 @@ #ifndef COMPILER_TRANSLATOR_LOOP_INFO_H_ #define COMPILER_TRANSLATOR_LOOP_INFO_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" class TLoopIndexInfo { diff --git a/gfx/angle/src/compiler/translator/NodeSearch.h b/gfx/angle/src/compiler/translator/NodeSearch.h index b58c7ec68945..60070c9d33a2 100644 --- a/gfx/angle/src/compiler/translator/NodeSearch.h +++ b/gfx/angle/src/compiler/translator/NodeSearch.h @@ -9,7 +9,7 @@ #ifndef TRANSLATOR_NODESEARCH_H_ #define TRANSLATOR_NODESEARCH_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" namespace sh { diff --git a/gfx/angle/src/compiler/translator/OutputGLSLBase.cpp b/gfx/angle/src/compiler/translator/OutputGLSLBase.cpp index 6995594e7606..6d07cccc04fc 100644 --- a/gfx/angle/src/compiler/translator/OutputGLSLBase.cpp +++ b/gfx/angle/src/compiler/translator/OutputGLSLBase.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2014 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. // @@ -55,8 +55,6 @@ TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase &objSink, mSymbolTable(symbolTable), mShaderVersion(shaderVersion) { - // Set up global scope. - mDeclaredStructs.push_back(ScopedDeclaredStructs()); } void TOutputGLSLBase::writeTriplet( @@ -83,14 +81,21 @@ void TOutputGLSLBase::writeVariableType(const TType &type) { TInfoSinkBase &out = objSink(); TQualifier qualifier = type.getQualifier(); - // TODO(alokp): Validate qualifier for variable declarations. if (qualifier != EvqTemporary && qualifier != EvqGlobal) + { out << type.getQualifierString() << " "; + } // Declare the struct if we have not done so already. if (type.getBasicType() == EbtStruct && !structDeclared(type.getStruct())) { - declareStruct(type.getStruct()); - mDeclaredStructs[mDeclaredStructs.size() - 1].push_back(type.getStruct()); + TStructure *structure = type.getStruct(); + + declareStruct(structure); + + if (!structure->name().empty()) + { + mDeclaredStructs.insert(structure->uniqueId()); + } } else { @@ -293,8 +298,8 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node) { out << "."; TIntermAggregate *rightChild = node->getRight()->getAsAggregate(); - TIntermSequence &sequence = rightChild->getSequence(); - for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); ++sit) + TIntermSequence *sequence = rightChild->getSequence(); + for (TIntermSequence::iterator sit = sequence->begin(); sit != sequence->end(); ++sit) { TIntermConstantUnion *element = (*sit)->getAsConstantUnion(); ASSERT(element->getBasicType() == EbtInt); @@ -398,67 +403,6 @@ bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary *node) case EOpPreIncrement: preString = "(++"; break; case EOpPreDecrement: preString = "(--"; break; - case EOpConvIntToBool: - case EOpConvFloatToBool: - switch (node->getOperand()->getType().getNominalSize()) - { - case 1: - preString = "bool("; - break; - case 2: - preString = "bvec2("; - break; - case 3: - preString = "bvec3("; - break; - case 4: - preString = "bvec4("; - break; - default: - UNREACHABLE(); - } - break; - case EOpConvBoolToFloat: - case EOpConvIntToFloat: - switch (node->getOperand()->getType().getNominalSize()) - { - case 1: - preString = "float("; - break; - case 2: - preString = "vec2("; - break; - case 3: - preString = "vec3("; - break; - case 4: - preString = "vec4("; - break; - default: - UNREACHABLE(); - } - break; - case EOpConvFloatToInt: - case EOpConvBoolToInt: - switch (node->getOperand()->getType().getNominalSize()) - { - case 1: - preString = "int("; - break; - case 2: - preString = "ivec2("; - break; - case 3: - preString = "ivec3("; - break; - case 4: - preString = "ivec4("; - break; - default: - UNREACHABLE(); - } - break; - case EOpRadians: preString = "radians("; break; @@ -601,15 +545,14 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) { case EOpSequence: // Scope the sequences except when at the global scope. - if (depth > 0) + if (mDepth > 0) { out << "{\n"; - pushDeclaredStructsScope(); } incrementDepth(node); - for (TIntermSequence::const_iterator iter = node->getSequence().begin(); - iter != node->getSequence().end(); ++iter) + for (TIntermSequence::const_iterator iter = node->getSequence()->begin(); + iter != node->getSequence()->end(); ++iter) { TIntermNode *node = *iter; ASSERT(node != NULL); @@ -621,9 +564,8 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) decrementDepth(); // Scope the sequences except when at the global scope. - if (depth > 0) + if (mDepth > 0) { - popDeclaredStructsScope(); out << "}\n"; } visitChildren = false; @@ -635,7 +577,7 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) out << " " << hashName(node->getName()); out << "("; - writeFunctionParameters(node->getSequence()); + writeFunctionParameters(*(node->getSequence())); out << ")"; visitChildren = false; @@ -650,7 +592,7 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) // Function definition node contains one or two children nodes // representing function parameters and function body. The latter // is not present in case of empty function bodies. - const TIntermSequence &sequence = node->getSequence(); + const TIntermSequence &sequence = *(node->getSequence()); ASSERT((sequence.size() == 1) || (sequence.size() == 2)); TIntermSequence::const_iterator seqIter = sequence.begin(); @@ -683,7 +625,7 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) // Function parameters. ASSERT(visit == PreVisit); out << "("; - writeFunctionParameters(node->getSequence()); + writeFunctionParameters(*(node->getSequence())); out << ")"; visitChildren = false; break; @@ -691,7 +633,7 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) // Variable declaration. if (visit == PreVisit) { - const TIntermSequence &sequence = node->getSequence(); + const TIntermSequence &sequence = *(node->getSequence()); const TIntermTyped *variable = sequence.front()->getAsTyped(); writeVariableType(variable->getType()); out << " "; @@ -707,6 +649,17 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) mDeclaringVariables = false; } break; + case EOpInvariantDeclaration: { + // Invariant declaration. + ASSERT(visit == PreVisit); + const TIntermSequence *sequence = node->getSequence(); + ASSERT(sequence && sequence->size() == 1); + const TIntermSymbol *symbol = sequence->front()->getAsSymbolNode(); + ASSERT(symbol); + out << "invariant " << symbol->getSymbol() << ";"; + visitChildren = false; + break; + } case EOpConstructFloat: writeTriplet(visit, "float(", NULL, ")"); break; @@ -873,10 +826,10 @@ bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop *node) else { // Need to put a one-iteration loop here to handle break. - TIntermSequence &declSeq = + TIntermSequence *declSeq = node->getInit()->getAsAggregate()->getSequence(); TIntermSymbol *indexSymbol = - declSeq[0]->getAsBinaryNode()->getLeft()->getAsSymbolNode(); + (*declSeq)[0]->getAsBinaryNode()->getLeft()->getAsSymbolNode(); TString name = hashVariableName(indexSymbol->getSymbol()); out << "for (int " << name << " = 0; " << name << " < 1; " @@ -1035,17 +988,12 @@ TString TOutputGLSLBase::hashFunctionName(const TString &mangled_name) bool TOutputGLSLBase::structDeclared(const TStructure *structure) const { ASSERT(structure); - ASSERT(mDeclaredStructs.size() > 0); - for (size_t ii = mDeclaredStructs.size(); ii > 0; --ii) + if (structure->name().empty()) { - const ScopedDeclaredStructs &scope = mDeclaredStructs[ii - 1]; - for (size_t jj = 0; jj < scope.size(); ++jj) - { - if (scope[jj]->equals(*structure)) - return true; - } + return false; } - return false; + + return (mDeclaredStructs.count(structure->uniqueId()) > 0); } void TOutputGLSLBase::declareStruct(const TStructure *structure) @@ -1067,14 +1015,3 @@ void TOutputGLSLBase::declareStruct(const TStructure *structure) out << "}"; } -void TOutputGLSLBase::pushDeclaredStructsScope() -{ - mDeclaredStructs.push_back(ScopedDeclaredStructs()); -} - -void TOutputGLSLBase::popDeclaredStructsScope() -{ - // We should never pop the global scope. - ASSERT(mDeclaredStructs.size() >= 2); - mDeclaredStructs.pop_back(); -} diff --git a/gfx/angle/src/compiler/translator/OutputGLSLBase.h b/gfx/angle/src/compiler/translator/OutputGLSLBase.h index ae40f85e0d5e..e5174f56605e 100644 --- a/gfx/angle/src/compiler/translator/OutputGLSLBase.h +++ b/gfx/angle/src/compiler/translator/OutputGLSLBase.h @@ -7,9 +7,9 @@ #ifndef CROSSCOMPILERGLSL_OUTPUTGLSLBASE_H_ #define CROSSCOMPILERGLSL_OUTPUTGLSLBASE_H_ -#include +#include -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include "compiler/translator/LoopInfo.h" #include "compiler/translator/ParseContext.h" @@ -56,22 +56,14 @@ class TOutputGLSLBase : public TIntermTraverser private: bool structDeclared(const TStructure *structure) const; void declareStruct(const TStructure *structure); - void pushDeclaredStructsScope(); - void popDeclaredStructsScope(); void writeBuiltInFunctionTriplet(Visit visit, const char *preStr, bool useEmulatedFunction); TInfoSinkBase &mObjSink; bool mDeclaringVariables; - // Structs are declared as the tree is traversed. This list contains all - // the structs already declared within a scope. It is maintained so that - // a struct is declared only once within a scope. - typedef std::vector ScopedDeclaredStructs; - // This vector contains all the structs from the global scope to the - // current scope. When the traverser exits a scope, the scope is discarded. - typedef std::vector DeclaredStructs; - DeclaredStructs mDeclaredStructs; + // This set contains all the ids of the structs from every scope. + std::set mDeclaredStructs; // Stack of loops that need to be unrolled. TLoopStack mLoopUnrollStack; diff --git a/gfx/angle/src/compiler/translator/OutputHLSL.cpp b/gfx/angle/src/compiler/translator/OutputHLSL.cpp index 2d7818b64b46..defb34a272b8 100644 --- a/gfx/angle/src/compiler/translator/OutputHLSL.cpp +++ b/gfx/angle/src/compiler/translator/OutputHLSL.cpp @@ -17,6 +17,10 @@ #include "compiler/translator/FlagStd140Structs.h" #include "compiler/translator/NodeSearch.h" #include "compiler/translator/RewriteElseBlocks.h" +#include "compiler/translator/UtilsHLSL.h" +#include "compiler/translator/util.h" +#include "compiler/translator/UniformHLSL.h" +#include "compiler/translator/StructureHLSL.h" #include #include @@ -25,6 +29,18 @@ namespace sh { +static sh::Attribute MakeAttributeFromType(const TType &type, const TString &name) +{ + sh::Attribute attributeVar; + attributeVar.type = GLVariableType(type); + attributeVar.precision = GLVariablePrecision(type); + attributeVar.name = name.c_str(); + attributeVar.arraySize = static_cast(type.getArraySize()); + attributeVar.location = type.getLayoutQualifier().location; + + return attributeVar; +} + TString OutputHLSL::TextureFunction::name() const { TString name = "gl_texture"; @@ -69,18 +85,6 @@ TString OutputHLSL::TextureFunction::name() const return name + "("; } -const char *RegisterPrefix(const TType &type) -{ - if (IsSampler(type.getBasicType())) - { - return "s"; - } - else - { - return "c"; - } -} - bool OutputHLSL::TextureFunction::operator<(const TextureFunction &rhs) const { if (sampler < rhs.sampler) return true; @@ -136,8 +140,6 @@ OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resourc mNumRenderTargets = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1; - mScopeDepth = 0; - mUniqueIndex = 0; mContainsLoopDiscontinuity = false; @@ -147,41 +149,43 @@ OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resourc mExcessiveLoopIndex = NULL; + mStructureHLSL = new StructureHLSL; + mUniformHLSL = new UniformHLSL(mStructureHLSL, mOutputType); + if (mOutputType == SH_HLSL9_OUTPUT) { - if (mContext.shaderType == SH_FRAGMENT_SHADER) + if (mContext.shaderType == GL_FRAGMENT_SHADER) { - mUniformRegister = 3; // Reserve registers for dx_DepthRange, dx_ViewCoords and dx_DepthFront + // Reserve registers for dx_DepthRange, dx_ViewCoords and dx_DepthFront + mUniformHLSL->reserveUniformRegisters(3); } else { - mUniformRegister = 2; // Reserve registers for dx_DepthRange and dx_ViewAdjust + // Reserve registers for dx_DepthRange and dx_ViewAdjust + mUniformHLSL->reserveUniformRegisters(2); } } - else - { - mUniformRegister = 0; - } - mSamplerRegister = 0; - mInterfaceBlockRegister = 2; // Reserve registers for the default uniform block and driver constants - mPaddingCounter = 0; + // Reserve registers for the default uniform block and driver constants + mUniformHLSL->reserveInterfaceBlockRegisters(2); } OutputHLSL::~OutputHLSL() { - delete mUnfoldShortCircuit; + SafeDelete(mUnfoldShortCircuit); + SafeDelete(mStructureHLSL); + SafeDelete(mUniformHLSL); } void OutputHLSL::output() { - mContainsLoopDiscontinuity = mContext.shaderType == SH_FRAGMENT_SHADER && containsLoopDiscontinuity(mContext.treeRoot); + mContainsLoopDiscontinuity = mContext.shaderType == GL_FRAGMENT_SHADER && containsLoopDiscontinuity(mContext.treeRoot); const std::vector &flaggedStructs = FlagStd140ValueStructs(mContext.treeRoot); makeFlaggedStructMaps(flaggedStructs); // Work around D3D9 bug that would manifest in vertex shaders with selection blocks which // use a vertex attribute as a condition, and some related computation in the else block. - if (mOutputType == SH_HLSL9_OUTPUT && mContext.shaderType == SH_VERTEX_SHADER) + if (mOutputType == SH_HLSL9_OUTPUT && mContext.shaderType == GL_VERTEX_SHADER) { RewriteElseBlocks(mContext.treeRoot); } @@ -220,31 +224,41 @@ TInfoSinkBase &OutputHLSL::getBodyStream() return mBody; } -const std::vector &OutputHLSL::getUniforms() +const std::vector &OutputHLSL::getUniforms() { - return mActiveUniforms; + return mUniformHLSL->getUniforms(); } -const std::vector &OutputHLSL::getInterfaceBlocks() const +const std::vector &OutputHLSL::getInterfaceBlocks() const { - return mActiveInterfaceBlocks; + return mUniformHLSL->getInterfaceBlocks(); } -const std::vector &OutputHLSL::getOutputVariables() const +const std::vector &OutputHLSL::getOutputVariables() const { return mActiveOutputVariables; } -const std::vector &OutputHLSL::getAttributes() const +const std::vector &OutputHLSL::getAttributes() const { return mActiveAttributes; } -const std::vector &OutputHLSL::getVaryings() const +const std::vector &OutputHLSL::getVaryings() const { return mActiveVaryings; } +const std::map &OutputHLSL::getInterfaceBlockRegisterMap() const +{ + return mUniformHLSL->getInterfaceBlockRegisterMap(); +} + +const std::map &OutputHLSL::getUniformRegisterMap() const +{ + return mUniformHLSL->getUniformRegisterMap(); +} + int OutputHLSL::vectorSize(const TType &type) const { int elementSize = type.isMatrix() ? type.getCols() : 1; @@ -253,267 +267,6 @@ int OutputHLSL::vectorSize(const TType &type) const return elementSize * arraySize; } -TString OutputHLSL::interfaceBlockFieldString(const TInterfaceBlock &interfaceBlock, const TField &field) -{ - if (interfaceBlock.hasInstanceName()) - { - return interfaceBlock.name() + "." + field.name(); - } - else - { - return field.name(); - } -} - -TString OutputHLSL::decoratePrivate(const TString &privateText) -{ - return "dx_" + privateText; -} - -TString OutputHLSL::interfaceBlockStructNameString(const TInterfaceBlock &interfaceBlock) -{ - return decoratePrivate(interfaceBlock.name()) + "_type"; -} - -TString OutputHLSL::interfaceBlockInstanceString(const TInterfaceBlock& interfaceBlock, unsigned int arrayIndex) -{ - if (!interfaceBlock.hasInstanceName()) - { - return ""; - } - else if (interfaceBlock.isArray()) - { - return decoratePrivate(interfaceBlock.instanceName()) + "_" + str(arrayIndex); - } - else - { - return decorate(interfaceBlock.instanceName()); - } -} - -TString OutputHLSL::interfaceBlockFieldTypeString(const TField &field, TLayoutBlockStorage blockStorage) -{ - const TType &fieldType = *field.type(); - const TLayoutMatrixPacking matrixPacking = fieldType.getLayoutQualifier().matrixPacking; - ASSERT(matrixPacking != EmpUnspecified); - - if (fieldType.isMatrix()) - { - // Use HLSL row-major packing for GLSL column-major matrices - const TString &matrixPackString = (matrixPacking == EmpRowMajor ? "column_major" : "row_major"); - return matrixPackString + " " + typeString(fieldType); - } - else if (fieldType.getStruct()) - { - // Use HLSL row-major packing for GLSL column-major matrices - return structureTypeName(*fieldType.getStruct(), matrixPacking == EmpColumnMajor, blockStorage == EbsStd140); - } - else - { - return typeString(fieldType); - } -} - -TString OutputHLSL::interfaceBlockFieldString(const TInterfaceBlock &interfaceBlock, TLayoutBlockStorage blockStorage) -{ - TString hlsl; - - int elementIndex = 0; - - for (unsigned int typeIndex = 0; typeIndex < interfaceBlock.fields().size(); typeIndex++) - { - const TField &field = *interfaceBlock.fields()[typeIndex]; - const TType &fieldType = *field.type(); - - if (blockStorage == EbsStd140) - { - // 2 and 3 component vector types in some cases need pre-padding - hlsl += std140PrePaddingString(fieldType, &elementIndex); - } - - hlsl += " " + interfaceBlockFieldTypeString(field, blockStorage) + - " " + decorate(field.name()) + arrayString(fieldType) + ";\n"; - - // must pad out after matrices and arrays, where HLSL usually allows itself room to pack stuff - if (blockStorage == EbsStd140) - { - const bool useHLSLRowMajorPacking = (fieldType.getLayoutQualifier().matrixPacking == EmpColumnMajor); - hlsl += std140PostPaddingString(fieldType, useHLSLRowMajorPacking); - } - } - - return hlsl; -} - -TString OutputHLSL::interfaceBlockStructString(const TInterfaceBlock &interfaceBlock) -{ - const TLayoutBlockStorage blockStorage = interfaceBlock.blockStorage(); - - return "struct " + interfaceBlockStructNameString(interfaceBlock) + "\n" - "{\n" + - interfaceBlockFieldString(interfaceBlock, blockStorage) + - "};\n\n"; -} - -TString OutputHLSL::interfaceBlockString(const TInterfaceBlock &interfaceBlock, unsigned int registerIndex, unsigned int arrayIndex) -{ - const TString &arrayIndexString = (arrayIndex != GL_INVALID_INDEX ? decorate(str(arrayIndex)) : ""); - const TString &blockName = interfaceBlock.name() + arrayIndexString; - TString hlsl; - - hlsl += "cbuffer " + blockName + " : register(b" + str(registerIndex) + ")\n" - "{\n"; - - if (interfaceBlock.hasInstanceName()) - { - hlsl += " " + interfaceBlockStructNameString(interfaceBlock) + " " + interfaceBlockInstanceString(interfaceBlock, arrayIndex) + ";\n"; - } - else - { - const TLayoutBlockStorage blockStorage = interfaceBlock.blockStorage(); - hlsl += interfaceBlockFieldString(interfaceBlock, blockStorage); - } - - hlsl += "};\n\n"; - - return hlsl; -} - -TString OutputHLSL::std140PrePaddingString(const TType &type, int *elementIndex) -{ - if (type.getBasicType() == EbtStruct || type.isMatrix() || type.isArray()) - { - // no padding needed, HLSL will align the field to a new register - *elementIndex = 0; - return ""; - } - - const GLenum glType = glVariableType(type); - const int numComponents = gl::UniformComponentCount(glType); - - if (numComponents >= 4) - { - // no padding needed, HLSL will align the field to a new register - *elementIndex = 0; - return ""; - } - - if (*elementIndex + numComponents > 4) - { - // no padding needed, HLSL will align the field to a new register - *elementIndex = numComponents; - return ""; - } - - TString padding; - - const int alignment = numComponents == 3 ? 4 : numComponents; - const int paddingOffset = (*elementIndex % alignment); - - if (paddingOffset != 0) - { - // padding is neccessary - for (int paddingIndex = paddingOffset; paddingIndex < alignment; paddingIndex++) - { - padding += " float pad_" + str(mPaddingCounter++) + ";\n"; - } - - *elementIndex += (alignment - paddingOffset); - } - - *elementIndex += numComponents; - *elementIndex %= 4; - - return padding; -} - -TString OutputHLSL::std140PostPaddingString(const TType &type, bool useHLSLRowMajorPacking) -{ - if (!type.isMatrix() && !type.isArray() && type.getBasicType() != EbtStruct) - { - return ""; - } - - int numComponents = 0; - - if (type.isMatrix()) - { - // This method can also be called from structureString, which does not use layout qualifiers. - // Thus, use the method parameter for determining the matrix packing. - // - // Note HLSL row major packing corresponds to GL API column-major, and vice-versa, since we - // wish to always transpose GL matrices to play well with HLSL's matrix array indexing. - // - const bool isRowMajorMatrix = !useHLSLRowMajorPacking; - const GLenum glType = glVariableType(type); - numComponents = gl::MatrixComponentCount(glType, isRowMajorMatrix); - } - else if (type.getStruct()) - { - const TString &structName = structureTypeName(*type.getStruct(), useHLSLRowMajorPacking, true); - numComponents = mStd140StructElementIndexes[structName]; - - if (numComponents == 0) - { - return ""; - } - } - else - { - const GLenum glType = glVariableType(type); - numComponents = gl::UniformComponentCount(glType); - } - - TString padding; - for (int paddingOffset = numComponents; paddingOffset < 4; paddingOffset++) - { - padding += " float pad_" + str(mPaddingCounter++) + ";\n"; - } - return padding; -} - -// Use the same layout for packed and shared -void setBlockLayout(gl::InterfaceBlock *interfaceBlock, gl::BlockLayoutType newLayout) -{ - interfaceBlock->layout = newLayout; - interfaceBlock->blockInfo.clear(); - - switch (newLayout) - { - case gl::BLOCKLAYOUT_SHARED: - case gl::BLOCKLAYOUT_PACKED: - { - gl::HLSLBlockEncoder hlslEncoder(&interfaceBlock->blockInfo, gl::HLSLBlockEncoder::ENCODE_PACKED); - hlslEncoder.encodeInterfaceBlockFields(interfaceBlock->fields); - interfaceBlock->dataSize = hlslEncoder.getBlockSize(); - } - break; - - case gl::BLOCKLAYOUT_STANDARD: - { - gl::Std140BlockEncoder stdEncoder(&interfaceBlock->blockInfo); - stdEncoder.encodeInterfaceBlockFields(interfaceBlock->fields); - interfaceBlock->dataSize = stdEncoder.getBlockSize(); - } - break; - - default: - UNREACHABLE(); - break; - } -} - -gl::BlockLayoutType convertBlockLayoutType(TLayoutBlockStorage blockStorage) -{ - switch (blockStorage) - { - case EbsPacked: return gl::BLOCKLAYOUT_PACKED; - case EbsShared: return gl::BLOCKLAYOUT_SHARED; - case EbsStd140: return gl::BLOCKLAYOUT_STANDARD; - default: UNREACHABLE(); return gl::BLOCKLAYOUT_SHARED; - } -} - TString OutputHLSL::structInitializerString(int indent, const TStructure &structure, const TString &rhsStructName) { TString init; @@ -537,7 +290,7 @@ TString OutputHLSL::structInitializerString(int indent, const TStructure &struct for (unsigned int fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++) { const TField &field = *fields[fieldIndex]; - const TString &fieldName = rhsStructName + "." + decorate(field.name()); + const TString &fieldName = rhsStructName + "." + Decorate(field.name()); const TType &fieldType = *field.type(); if (fieldType.getStruct()) @@ -559,84 +312,10 @@ void OutputHLSL::header() { TInfoSinkBase &out = mHeader; - TString uniforms; - TString interfaceBlocks; TString varyings; TString attributes; TString flaggedStructs; - for (ReferencedSymbols::const_iterator uniformIt = mReferencedUniforms.begin(); uniformIt != mReferencedUniforms.end(); uniformIt++) - { - const TIntermSymbol &uniform = *uniformIt->second; - const TType &type = uniform.getType(); - const TString &name = uniform.getSymbol(); - - int registerIndex = declareUniformAndAssignRegister(type, name); - - if (mOutputType == SH_HLSL11_OUTPUT && IsSampler(type.getBasicType())) // Also declare the texture - { - uniforms += "uniform " + samplerString(type) + " sampler_" + decorateUniform(name, type) + arrayString(type) + - " : register(s" + str(registerIndex) + ");\n"; - - uniforms += "uniform " + textureString(type) + " texture_" + decorateUniform(name, type) + arrayString(type) + - " : register(t" + str(registerIndex) + ");\n"; - } - else - { - const TStructure *structure = type.getStruct(); - const TString &typeName = (structure ? structureTypeName(*structure, false, false) : typeString(type)); - - const TString ®isterString = TString("register(") + RegisterPrefix(type) + str(registerIndex) + ")"; - - uniforms += "uniform " + typeName + " " + decorateUniform(name, type) + arrayString(type) + " : " + registerString + ";\n"; - } - } - - for (ReferencedSymbols::const_iterator interfaceBlockIt = mReferencedInterfaceBlocks.begin(); interfaceBlockIt != mReferencedInterfaceBlocks.end(); interfaceBlockIt++) - { - const TType &nodeType = interfaceBlockIt->second->getType(); - const TInterfaceBlock &interfaceBlock = *nodeType.getInterfaceBlock(); - const TFieldList &fieldList = interfaceBlock.fields(); - - unsigned int arraySize = static_cast(interfaceBlock.arraySize()); - gl::InterfaceBlock activeBlock(interfaceBlock.name().c_str(), arraySize, mInterfaceBlockRegister); - for (unsigned int typeIndex = 0; typeIndex < fieldList.size(); typeIndex++) - { - const TField &field = *fieldList[typeIndex]; - const TString &fullUniformName = interfaceBlockFieldString(interfaceBlock, field); - declareInterfaceBlockField(*field.type(), fullUniformName, activeBlock.fields); - } - - mInterfaceBlockRegister += std::max(1u, arraySize); - - gl::BlockLayoutType blockLayoutType = convertBlockLayoutType(interfaceBlock.blockStorage()); - setBlockLayout(&activeBlock, blockLayoutType); - - if (interfaceBlock.matrixPacking() == EmpRowMajor) - { - activeBlock.isRowMajorLayout = true; - } - - mActiveInterfaceBlocks.push_back(activeBlock); - - if (interfaceBlock.hasInstanceName()) - { - interfaceBlocks += interfaceBlockStructString(interfaceBlock); - } - - if (arraySize > 0) - { - for (unsigned int arrayIndex = 0; arrayIndex < arraySize; arrayIndex++) - { - interfaceBlocks += interfaceBlockString(interfaceBlock, activeBlock.registerIndex + arrayIndex, arrayIndex); - } - } - else - { - interfaceBlocks += interfaceBlockString(interfaceBlock, activeBlock.registerIndex, GL_INVALID_INDEX); - } - } - for (std::map::const_iterator flaggedStructIt = mFlaggedStructMappedNames.begin(); flaggedStructIt != mFlaggedStructMappedNames.end(); flaggedStructIt++) { TIntermTyped *structNode = flaggedStructIt->first; @@ -644,7 +323,7 @@ void OutputHLSL::header() const TStructure &structure = *structNode->getType().getStruct(); const TString &originalName = mFlaggedStructOriginalNames[structNode]; - flaggedStructs += "static " + decorate(structure.name()) + " " + mappedName + " =\n"; + flaggedStructs += "static " + Decorate(structure.name()) + " " + mappedName + " =\n"; flaggedStructs += structInitializerString(0, structure, originalName); flaggedStructs += "\n"; } @@ -655,8 +334,8 @@ void OutputHLSL::header() const TString &name = varying->second->getSymbol(); // Program linking depends on this exact format - varyings += "static " + interpolationString(type.getQualifier()) + " " + typeString(type) + " " + - decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n"; + varyings += "static " + InterpolationString(type.getQualifier()) + " " + TypeString(type) + " " + + Decorate(name) + ArrayString(type) + " = " + initializer(type) + ";\n"; declareVaryingToList(type, type.getQualifier(), name, mActiveVaryings); } @@ -666,22 +345,16 @@ void OutputHLSL::header() const TType &type = attribute->second->getType(); const TString &name = attribute->second->getSymbol(); - attributes += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n"; + attributes += "static " + TypeString(type) + " " + Decorate(name) + ArrayString(type) + " = " + initializer(type) + ";\n"; - gl::Attribute attributeVar(glVariableType(type), glVariablePrecision(type), name.c_str(), - (unsigned int)type.getArraySize(), type.getLayoutQualifier().location); + sh::Attribute attributeVar = MakeAttributeFromType(type, name); mActiveAttributes.push_back(attributeVar); } - for (StructDeclarations::iterator structDeclaration = mStructDeclarations.begin(); structDeclaration != mStructDeclarations.end(); structDeclaration++) - { - out << *structDeclaration; - } + out << mStructureHLSL->structsHeader(); - for (Constructors::iterator constructor = mConstructors.begin(); constructor != mConstructors.end(); constructor++) - { - out << *constructor; - } + out << mUniformHLSL->uniformsHeader(mOutputType, mReferencedUniforms); + out << mUniformHLSL->interfaceBlocksHeader(mReferencedInterfaceBlocks); if (mUsesDiscardRewriting) { @@ -693,7 +366,7 @@ void OutputHLSL::header() out << "#define ANGLE_USES_NESTED_BREAK" << "\n"; } - if (mContext.shaderType == SH_FRAGMENT_SHADER) + if (mContext.shaderType == GL_FRAGMENT_SHADER) { TExtensionBehavior::const_iterator iter = mContext.extensionBehavior().find("GL_EXT_draw_buffers"); const bool usingMRTExtension = (iter != mContext.extensionBehavior().end() && (iter->second == EBhEnable || iter->second == EBhRequire)); @@ -708,13 +381,11 @@ void OutputHLSL::header() { const TString &variableName = outputVariableIt->first; const TType &variableType = outputVariableIt->second->getType(); - const TLayoutQualifier &layoutQualifier = variableType.getLayoutQualifier(); - out << "static " + typeString(variableType) + " out_" + variableName + arrayString(variableType) + + out << "static " + TypeString(variableType) + " out_" + variableName + ArrayString(variableType) + " = " + initializer(variableType) + ";\n"; - gl::Attribute outputVar(glVariableType(variableType), glVariablePrecision(variableType), variableName.c_str(), - (unsigned int)variableType.getArraySize(), layoutQualifier.location); + sh::Attribute outputVar = MakeAttributeFromType(variableType, variableName); mActiveOutputVariables.push_back(outputVar); } } @@ -817,22 +488,13 @@ void OutputHLSL::header() out << "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, dx_DepthRange.y, dx_DepthRange.z};\n" "\n"; } - - out << uniforms; - out << "\n"; - if (!interfaceBlocks.empty()) + if (!flaggedStructs.empty()) { - out << interfaceBlocks; + out << "// Std140 Structures accessed by value\n"; + out << "\n"; + out << flaggedStructs; out << "\n"; - - if (!flaggedStructs.empty()) - { - out << "// Std140 Structures accessed by value\n"; - out << "\n"; - out << flaggedStructs; - out << "\n"; - } } if (usingMRTExtension && mNumRenderTargets > 1) @@ -856,7 +518,7 @@ void OutputHLSL::header() out << attributes; out << "\n" "static float4 gl_Position = float4(0, 0, 0, 0);\n"; - + if (mUsesPointSize) { out << "static float gl_PointSize = float(1);\n"; @@ -906,21 +568,12 @@ void OutputHLSL::header() "\n"; } - out << uniforms; - out << "\n"; - - if (!interfaceBlocks.empty()) + if (!flaggedStructs.empty()) { - out << interfaceBlocks; + out << "// Std140 Structures accessed by value\n"; + out << "\n"; + out << flaggedStructs; out << "\n"; - - if (!flaggedStructs.empty()) - { - out << "// Std140 Structures accessed by value\n"; - out << "\n"; - out << flaggedStructs; - out << "\n"; - } } } @@ -1390,7 +1043,7 @@ void OutputHLSL::header() case 3: out << "int4("; break; default: UNREACHABLE(); } - + // Convert from normalized floating-point to integer if (textureFunction->method != TextureFunction::FETCH) { @@ -1425,7 +1078,7 @@ void OutputHLSL::header() } TString proj = ""; // Only used for projected textures - + if (textureFunction->proj) { switch(textureFunction->coords) @@ -1609,7 +1262,7 @@ void OutputHLSL::header() "}\n" "\n"; } - + if (mUsesMod3v) { out << "float3 mod(float3 x, float3 y)\n" @@ -1789,17 +1442,17 @@ void OutputHLSL::visitSymbol(TIntermSymbol *node) mReferencedUniforms[name] = node; } - out << decorateUniform(name, nodeType); + out << DecorateUniform(name, nodeType); } else if (qualifier == EvqAttribute || qualifier == EvqVertexIn) { mReferencedAttributes[name] = node; - out << decorate(name); + out << Decorate(name); } - else if (isVarying(qualifier)) + else if (IsVarying(qualifier)) { mReferencedVaryings[name] = node; - out << decorate(name); + out << Decorate(name); } else if (qualifier == EvqFragmentOut) { @@ -1847,11 +1500,16 @@ void OutputHLSL::visitSymbol(TIntermSymbol *node) } else { - out << decorate(name); + out << Decorate(name); } } } +void OutputHLSL::visitRaw(TIntermRaw *node) +{ + mBody << node->getRawText(); +} + bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) { TInfoSinkBase &out = mBody; @@ -1913,7 +1571,7 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) { out << " = mul("; node->getLeft()->traverse(this); - out << ", transpose("; + out << ", transpose("; } else { @@ -1929,7 +1587,7 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) { out << " = mul("; node->getLeft()->traverse(this); - out << ", "; + out << ", "; } else { @@ -1946,10 +1604,8 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) { TInterfaceBlock* interfaceBlock = leftType.getInterfaceBlock(); const int arrayIndex = node->getRight()->getAsConstantUnion()->getIConst(0); - mReferencedInterfaceBlocks[interfaceBlock->instanceName()] = node->getLeft()->getAsSymbolNode(); - out << interfaceBlockInstanceString(*interfaceBlock, arrayIndex); - + out << mUniformHLSL->interfaceBlockInstanceString(*interfaceBlock, arrayIndex); return false; } } @@ -1970,7 +1626,7 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) 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(), *structure); + out << "." + DecorateField(field->name(), *structure); return false; } @@ -1981,7 +1637,7 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) const TInterfaceBlock* interfaceBlock = node->getLeft()->getType().getInterfaceBlock(); const TIntermConstantUnion* index = node->getRight()->getAsConstantUnion(); const TField* field = interfaceBlock->fields()[index->getIConst(0)]; - out << "." + decorate(field->name()); + out << "." + Decorate(field->name()); return false; } @@ -1995,9 +1651,9 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) if (swizzle) { - TIntermSequence &sequence = swizzle->getSequence(); + TIntermSequence *sequence = swizzle->getSequence(); - for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++) + for (TIntermSequence::iterator sit = sequence->begin(); sit != sequence->end(); sit++) { TIntermConstantUnion *element = (*sit)->getAsConstantUnion(); @@ -2058,9 +1714,9 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) const TField *field = fields[i]; node->getLeft()->traverse(this); - out << "." + decorateField(field->name(), structure) + " == "; + out << "." + DecorateField(field->name(), structure) + " == "; node->getRight()->traverse(this); - out << "." + decorateField(field->name(), structure); + out << "." + DecorateField(field->name(), structure); if (i < fields.size() - 1) { @@ -2131,61 +1787,13 @@ bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node) { switch (node->getOp()) { - case EOpNegative: outputTriplet(visit, "(-", "", ")"); break; - case EOpVectorLogicalNot: outputTriplet(visit, "(!", "", ")"); break; - case EOpLogicalNot: outputTriplet(visit, "(!", "", ")"); break; - case EOpPostIncrement: outputTriplet(visit, "(", "", "++)"); break; - case EOpPostDecrement: outputTriplet(visit, "(", "", "--)"); break; - case EOpPreIncrement: outputTriplet(visit, "(++", "", ")"); break; - case EOpPreDecrement: outputTriplet(visit, "(--", "", ")"); break; - case EOpConvIntToBool: - case EOpConvUIntToBool: - case EOpConvFloatToBool: - switch (node->getOperand()->getType().getNominalSize()) - { - case 1: outputTriplet(visit, "bool(", "", ")"); break; - case 2: outputTriplet(visit, "bool2(", "", ")"); break; - case 3: outputTriplet(visit, "bool3(", "", ")"); break; - case 4: outputTriplet(visit, "bool4(", "", ")"); break; - default: UNREACHABLE(); - } - break; - case EOpConvBoolToFloat: - case EOpConvIntToFloat: - case EOpConvUIntToFloat: - switch (node->getOperand()->getType().getNominalSize()) - { - case 1: outputTriplet(visit, "float(", "", ")"); break; - case 2: outputTriplet(visit, "float2(", "", ")"); break; - case 3: outputTriplet(visit, "float3(", "", ")"); break; - case 4: outputTriplet(visit, "float4(", "", ")"); break; - default: UNREACHABLE(); - } - break; - case EOpConvFloatToInt: - case EOpConvBoolToInt: - case EOpConvUIntToInt: - switch (node->getOperand()->getType().getNominalSize()) - { - case 1: outputTriplet(visit, "int(", "", ")"); break; - case 2: outputTriplet(visit, "int2(", "", ")"); break; - case 3: outputTriplet(visit, "int3(", "", ")"); break; - case 4: outputTriplet(visit, "int4(", "", ")"); break; - default: UNREACHABLE(); - } - break; - case EOpConvFloatToUInt: - case EOpConvBoolToUInt: - case EOpConvIntToUInt: - switch (node->getOperand()->getType().getNominalSize()) - { - case 1: outputTriplet(visit, "uint(", "", ")"); break; - case 2: outputTriplet(visit, "uint2(", "", ")"); break; - case 3: outputTriplet(visit, "uint3(", "", ")"); break; - case 4: outputTriplet(visit, "uint4(", "", ")"); break; - default: UNREACHABLE(); - } - break; + case EOpNegative: outputTriplet(visit, "(-", "", ")"); break; + case EOpVectorLogicalNot: outputTriplet(visit, "(!", "", ")"); break; + case EOpLogicalNot: outputTriplet(visit, "(!", "", ")"); break; + case EOpPostIncrement: outputTriplet(visit, "(", "", "++)"); break; + case EOpPostDecrement: outputTriplet(visit, "(", "", "--)"); break; + case EOpPreIncrement: outputTriplet(visit, "(++", "", ")"); break; + case EOpPreDecrement: outputTriplet(visit, "(--", "", ")"); break; case EOpRadians: outputTriplet(visit, "radians(", "", ")"); break; case EOpDegrees: outputTriplet(visit, "degrees(", "", ")"); break; case EOpSin: outputTriplet(visit, "sin(", "", ")"); break; @@ -2257,20 +1865,9 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) { outputLineDirective(node->getLine().first_line); out << "{\n"; - - mScopeDepth++; - - if (mScopeBracket.size() < mScopeDepth) - { - mScopeBracket.push_back(0); // New scope level - } - else - { - mScopeBracket[mScopeDepth - 1]++; // New scope at existing level - } } - for (TIntermSequence::iterator sit = node->getSequence().begin(); sit != node->getSequence().end(); sit++) + for (TIntermSequence::iterator sit = node->getSequence()->begin(); sit != node->getSequence()->end(); sit++) { outputLineDirective((*sit)->getLine().first_line); @@ -2283,8 +1880,6 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) { outputLineDirective(node->getLine().last_line); out << "}\n"; - - mScopeDepth--; } return false; @@ -2292,14 +1887,16 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) case EOpDeclaration: if (visit == PreVisit) { - TIntermSequence &sequence = node->getSequence(); - TIntermTyped *variable = sequence[0]->getAsTyped(); + TIntermSequence *sequence = node->getSequence(); + TIntermTyped *variable = (*sequence)[0]->getAsTyped(); if (variable && (variable->getQualifier() == EvqTemporary || variable->getQualifier() == EvqGlobal)) { - if (variable->getType().getStruct()) + TStructure *structure = variable->getType().getStruct(); + + if (structure) { - addConstructor(variable->getType(), scopedStruct(variable->getType().getStruct()->name()), NULL); + mStructureHLSL->addConstructor(variable->getType(), StructNameString(*structure), NULL); } if (!variable->getAsSymbolNode() || variable->getAsSymbolNode()->getSymbol() != "") // Variable declaration @@ -2309,16 +1906,16 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) out << "static "; } - out << typeString(variable->getType()) + " "; + out << TypeString(variable->getType()) + " "; - for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++) + for (TIntermSequence::iterator sit = sequence->begin(); sit != sequence->end(); sit++) { TIntermSymbol *symbol = (*sit)->getAsSymbolNode(); if (symbol) { symbol->traverse(this); - out << arrayString(symbol->getType()); + out << ArrayString(symbol->getType()); out << " = " + initializer(symbol->getType()); } else @@ -2326,7 +1923,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) (*sit)->traverse(this); } - if (*sit != sequence.back()) + if (*sit != sequence->back()) { out << ", "; } @@ -2338,9 +1935,9 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) } else UNREACHABLE(); } - else if (variable && isVaryingOut(variable->getQualifier())) + else if (variable && IsVaryingOut(variable->getQualifier())) { - for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++) + for (TIntermSequence::iterator sit = sequence->begin(); sit != sequence->end(); sit++) { TIntermSymbol *symbol = (*sit)->getAsSymbolNode(); @@ -2363,22 +1960,25 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) out << ", "; } break; + case EOpInvariantDeclaration: + // Do not do any translation + return false; case EOpPrototype: if (visit == PreVisit) { - out << typeString(node->getType()) << " " << decorate(node->getName()) << (mOutputLod0Function ? "Lod0(" : "("); + out << TypeString(node->getType()) << " " << Decorate(node->getName()) << (mOutputLod0Function ? "Lod0(" : "("); - TIntermSequence &arguments = node->getSequence(); + TIntermSequence *arguments = node->getSequence(); - for (unsigned int i = 0; i < arguments.size(); i++) + for (unsigned int i = 0; i < arguments->size(); i++) { - TIntermSymbol *symbol = arguments[i]->getAsSymbolNode(); + TIntermSymbol *symbol = (*arguments)[i]->getAsSymbolNode(); if (symbol) { out << argumentString(symbol); - if (i < arguments.size() - 1) + if (i < arguments->size() - 1) { out << ", "; } @@ -2404,7 +2004,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) { TString name = TFunction::unmangleName(node->getName()); - out << typeString(node->getType()) << " "; + out << TypeString(node->getType()) << " "; if (name == "main") { @@ -2412,26 +2012,28 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) } else { - out << decorate(name) << (mOutputLod0Function ? "Lod0(" : "("); + out << Decorate(name) << (mOutputLod0Function ? "Lod0(" : "("); } - TIntermSequence &sequence = node->getSequence(); - TIntermSequence &arguments = sequence[0]->getAsAggregate()->getSequence(); + TIntermSequence *sequence = node->getSequence(); + TIntermSequence *arguments = (*sequence)[0]->getAsAggregate()->getSequence(); - for (unsigned int i = 0; i < arguments.size(); i++) + for (unsigned int i = 0; i < arguments->size(); i++) { - TIntermSymbol *symbol = arguments[i]->getAsSymbolNode(); + TIntermSymbol *symbol = (*arguments)[i]->getAsSymbolNode(); if (symbol) { - if (symbol->getType().getStruct()) + TStructure *structure = symbol->getType().getStruct(); + + if (structure) { - addConstructor(symbol->getType(), scopedStruct(symbol->getType().getStruct()->name()), NULL); + mStructureHLSL->addConstructor(symbol->getType(), StructNameString(*structure), NULL); } out << argumentString(symbol); - if (i < arguments.size() - 1) + if (i < arguments->size() - 1) { out << ", "; } @@ -2441,14 +2043,14 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) out << ")\n" "{\n"; - - if (sequence.size() > 1) + + if (sequence->size() > 1) { mInsideFunction = true; - sequence[1]->traverse(this); + (*sequence)[1]->traverse(this); mInsideFunction = false; } - + out << "}\n"; if (mContainsLoopDiscontinuity && !mOutputLod0Function) @@ -2468,19 +2070,19 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) { TString name = TFunction::unmangleName(node->getName()); bool lod0 = mInsideDiscontinuousLoop || mOutputLod0Function; - TIntermSequence &arguments = node->getSequence(); + TIntermSequence *arguments = node->getSequence(); if (node->isUserDefined()) { - out << decorate(name) << (lod0 ? "Lod0(" : "("); + out << Decorate(name) << (lod0 ? "Lod0(" : "("); } else { - TBasicType samplerType = arguments[0]->getAsTyped()->getType().getBasicType(); + TBasicType samplerType = (*arguments)[0]->getAsTyped()->getType().getBasicType(); TextureFunction textureFunction; textureFunction.sampler = samplerType; - textureFunction.coords = arguments[1]->getAsTyped()->getNominalSize(); + textureFunction.coords = (*arguments)[1]->getAsTyped()->getNominalSize(); textureFunction.method = TextureFunction::IMPLICIT; textureFunction.proj = false; textureFunction.offset = false; @@ -2570,9 +2172,9 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) mandatoryArgumentCount++; } - bool bias = (arguments.size() > mandatoryArgumentCount); // Bias argument is optional + bool bias = (arguments->size() > mandatoryArgumentCount); // Bias argument is optional - if (lod0 || mContext.shaderType == SH_VERTEX_SHADER) + if (lod0 || mContext.shaderType == GL_VERTEX_SHADER) { if (bias) { @@ -2594,7 +2196,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) out << textureFunction.name(); } - for (TIntermSequence::iterator arg = arguments.begin(); arg != arguments.end(); arg++) + for (TIntermSequence::iterator arg = arguments->begin(); arg != arguments->end(); arg++) { if (mOutputType == SH_HLSL11_OUTPUT && IsSampler((*arg)->getAsTyped()->getBasicType())) { @@ -2605,7 +2207,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) (*arg)->traverse(this); - if (arg < arguments.end() - 1) + if (arg < arguments->end() - 1) { out << ", "; } @@ -2616,86 +2218,32 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) return false; } break; - case EOpParameters: outputTriplet(visit, "(", ", ", ")\n{\n"); break; - case EOpConstructFloat: - addConstructor(node->getType(), "vec1", &node->getSequence()); - outputTriplet(visit, "vec1(", "", ")"); - break; - case EOpConstructVec2: - addConstructor(node->getType(), "vec2", &node->getSequence()); - outputTriplet(visit, "vec2(", ", ", ")"); - break; - case EOpConstructVec3: - addConstructor(node->getType(), "vec3", &node->getSequence()); - outputTriplet(visit, "vec3(", ", ", ")"); - break; - case EOpConstructVec4: - addConstructor(node->getType(), "vec4", &node->getSequence()); - outputTriplet(visit, "vec4(", ", ", ")"); - break; - case EOpConstructBool: - addConstructor(node->getType(), "bvec1", &node->getSequence()); - outputTriplet(visit, "bvec1(", "", ")"); - break; - case EOpConstructBVec2: - addConstructor(node->getType(), "bvec2", &node->getSequence()); - outputTriplet(visit, "bvec2(", ", ", ")"); - break; - case EOpConstructBVec3: - addConstructor(node->getType(), "bvec3", &node->getSequence()); - outputTriplet(visit, "bvec3(", ", ", ")"); - break; - case EOpConstructBVec4: - addConstructor(node->getType(), "bvec4", &node->getSequence()); - outputTriplet(visit, "bvec4(", ", ", ")"); - break; - case EOpConstructInt: - addConstructor(node->getType(), "ivec1", &node->getSequence()); - outputTriplet(visit, "ivec1(", "", ")"); - break; - case EOpConstructIVec2: - addConstructor(node->getType(), "ivec2", &node->getSequence()); - outputTriplet(visit, "ivec2(", ", ", ")"); - break; - case EOpConstructIVec3: - addConstructor(node->getType(), "ivec3", &node->getSequence()); - outputTriplet(visit, "ivec3(", ", ", ")"); - break; - case EOpConstructIVec4: - addConstructor(node->getType(), "ivec4", &node->getSequence()); - outputTriplet(visit, "ivec4(", ", ", ")"); - break; - case EOpConstructUInt: - addConstructor(node->getType(), "uvec1", &node->getSequence()); - outputTriplet(visit, "uvec1(", "", ")"); - break; - case EOpConstructUVec2: - addConstructor(node->getType(), "uvec2", &node->getSequence()); - outputTriplet(visit, "uvec2(", ", ", ")"); - break; - case EOpConstructUVec3: - addConstructor(node->getType(), "uvec3", &node->getSequence()); - outputTriplet(visit, "uvec3(", ", ", ")"); - break; - case EOpConstructUVec4: - addConstructor(node->getType(), "uvec4", &node->getSequence()); - outputTriplet(visit, "uvec4(", ", ", ")"); - break; - case EOpConstructMat2: - addConstructor(node->getType(), "mat2", &node->getSequence()); - outputTriplet(visit, "mat2(", ", ", ")"); - break; - case EOpConstructMat3: - addConstructor(node->getType(), "mat3", &node->getSequence()); - outputTriplet(visit, "mat3(", ", ", ")"); - break; - case EOpConstructMat4: - addConstructor(node->getType(), "mat4", &node->getSequence()); - outputTriplet(visit, "mat4(", ", ", ")"); - break; + case EOpParameters: outputTriplet(visit, "(", ", ", ")\n{\n"); break; + case EOpConstructFloat: outputConstructor(visit, node->getType(), "vec1", node->getSequence()); break; + case EOpConstructVec2: outputConstructor(visit, node->getType(), "vec2", node->getSequence()); break; + case EOpConstructVec3: outputConstructor(visit, node->getType(), "vec3", node->getSequence()); break; + case EOpConstructVec4: outputConstructor(visit, node->getType(), "vec4", node->getSequence()); break; + case EOpConstructBool: outputConstructor(visit, node->getType(), "bvec1", node->getSequence()); break; + case EOpConstructBVec2: outputConstructor(visit, node->getType(), "bvec2", node->getSequence()); break; + case EOpConstructBVec3: outputConstructor(visit, node->getType(), "bvec3", node->getSequence()); break; + case EOpConstructBVec4: outputConstructor(visit, node->getType(), "bvec4", node->getSequence()); break; + case EOpConstructInt: outputConstructor(visit, node->getType(), "ivec1", node->getSequence()); break; + case EOpConstructIVec2: outputConstructor(visit, node->getType(), "ivec2", node->getSequence()); break; + case EOpConstructIVec3: outputConstructor(visit, node->getType(), "ivec3", node->getSequence()); break; + case EOpConstructIVec4: outputConstructor(visit, node->getType(), "ivec4", node->getSequence()); break; + case EOpConstructUInt: outputConstructor(visit, node->getType(), "uvec1", node->getSequence()); break; + case EOpConstructUVec2: outputConstructor(visit, node->getType(), "uvec2", node->getSequence()); break; + case EOpConstructUVec3: outputConstructor(visit, node->getType(), "uvec3", node->getSequence()); break; + case EOpConstructUVec4: outputConstructor(visit, node->getType(), "uvec4", node->getSequence()); break; + case EOpConstructMat2: outputConstructor(visit, node->getType(), "mat2", node->getSequence()); break; + case EOpConstructMat3: outputConstructor(visit, node->getType(), "mat3", node->getSequence()); break; + case EOpConstructMat4: outputConstructor(visit, node->getType(), "mat4", node->getSequence()); break; case EOpConstructStruct: - addConstructor(node->getType(), scopedStruct(node->getType().getStruct()->name()), &node->getSequence()); - outputTriplet(visit, structLookup(node->getType().getStruct()->name()) + "_ctor(", ", ", ")"); + { + const TString &structName = StructNameString(*node->getType().getStruct()); + mStructureHLSL->addConstructor(node->getType(), structName, node->getSequence()); + outputTriplet(visit, structName + "_ctor(", ", ", ")"); + } break; case EOpLessThan: outputTriplet(visit, "(", " < ", ")"); break; case EOpGreaterThan: outputTriplet(visit, "(", " > ", ")"); break; @@ -2706,8 +2254,8 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) case EOpMod: { // We need to look at the number of components in both arguments - const int modValue = node->getSequence()[0]->getAsTyped()->getNominalSize() * 10 - + node->getSequence()[1]->getAsTyped()->getNominalSize(); + const int modValue = (*node->getSequence())[0]->getAsTyped()->getNominalSize() * 10 + + (*node->getSequence())[1]->getAsTyped()->getNominalSize(); switch (modValue) { case 11: mUsesMod1 = true; break; @@ -2725,8 +2273,8 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) break; case EOpPow: outputTriplet(visit, "pow(", ", ", ")"); break; case EOpAtan: - ASSERT(node->getSequence().size() == 2); // atan(x) is a unary operator - switch (node->getSequence()[0]->getAsTyped()->getNominalSize()) + ASSERT(node->getSequence()->size() == 2); // atan(x) is a unary operator + switch ((*node->getSequence())[0]->getAsTyped()->getNominalSize()) { case 1: mUsesAtan2_1 = true; break; case 2: mUsesAtan2_2 = true; break; @@ -2747,7 +2295,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) case EOpCross: outputTriplet(visit, "cross(", ", ", ")"); break; case EOpFaceForward: { - switch (node->getSequence()[0]->getAsTyped()->getNominalSize()) // Number of components in the first argument + switch ((*node->getSequence())[0]->getAsTyped()->getNominalSize()) // Number of components in the first argument { case 1: mUsesFaceforward1 = true; break; case 2: mUsesFaceforward2 = true; break; @@ -2755,7 +2303,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) case 4: mUsesFaceforward4 = true; break; default: UNREACHABLE(); } - + outputTriplet(visit, "faceforward(", ", ", ")"); } break; @@ -2785,7 +2333,7 @@ bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node) node->getCondition()->traverse(this); out << ")\n"; - + outputLineDirective(node->getLine().first_line); out << "{\n"; @@ -2868,7 +2416,7 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node) else { out << "{for("; - + if (node->getInit()) { node->getInit()->traverse(this); @@ -2889,7 +2437,7 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node) } out << ")\n"; - + outputLineDirective(node->getLine().first_line); out << "{\n"; } @@ -2998,7 +2546,7 @@ bool OutputHLSL::isSingleStatement(TIntermNode *node) } else { - for (TIntermSequence::iterator sit = aggregate->getSequence().begin(); sit != aggregate->getSequence().end(); sit++) + for (TIntermSequence::iterator sit = aggregate->getSequence()->begin(); sit != aggregate->getSequence()->end(); sit++) { if (!isSingleStatement(*sit)) { @@ -3035,8 +2583,8 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node) if (init) { - TIntermSequence &sequence = init->getSequence(); - TIntermTyped *variable = sequence[0]->getAsTyped(); + TIntermSequence *sequence = init->getSequence(); + TIntermTyped *variable = (*sequence)[0]->getAsTyped(); if (variable && variable->getQualifier() == EvqTemporary) { @@ -3064,7 +2612,7 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node) if (index != NULL && node->getCondition()) { TIntermBinary *test = node->getCondition()->getAsBinaryNode(); - + if (test && test->getLeft()->getAsSymbolNode()->getId() == index->getId()) { TIntermConstantUnion *constant = test->getRight()->getAsConstantUnion(); @@ -3085,7 +2633,7 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node) { TIntermBinary *binaryTerminal = node->getExpression()->getAsBinaryNode(); TIntermUnary *unaryTerminal = node->getExpression()->getAsUnaryNode(); - + if (binaryTerminal) { TOperator op = binaryTerminal->getOp(); @@ -3165,7 +2713,7 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node) { mExcessiveLoopIndex = NULL; // Stops setting the Break flag } - + // for(int index = initial; index < clampedLimit; index += increment) out << "for("; @@ -3183,7 +2731,7 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node) out << " += "; out << increment; out << ")\n"; - + outputLineDirective(node->getLine().first_line); out << "{\n"; @@ -3205,7 +2753,7 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node) initial += MAX_LOOP_ITERATIONS * increment; iterations -= MAX_LOOP_ITERATIONS; } - + out << "}"; mExcessiveLoopIndex = restoreIndex; @@ -3247,7 +2795,7 @@ void OutputHLSL::outputLineDirective(int line) { mBody << " \"" << mContext.sourcePath << "\""; } - + mBody << "\n"; } } @@ -3264,181 +2812,16 @@ TString OutputHLSL::argumentString(const TIntermSymbol *symbol) } else { - name = decorate(name); + name = Decorate(name); } if (mOutputType == SH_HLSL11_OUTPUT && IsSampler(type.getBasicType())) { - return qualifierString(qualifier) + " " + textureString(type) + " texture_" + name + arrayString(type) + ", " + - qualifierString(qualifier) + " " + samplerString(type) + " sampler_" + name + arrayString(type); + return QualifierString(qualifier) + " " + TextureString(type) + " texture_" + name + ArrayString(type) + ", " + + QualifierString(qualifier) + " " + SamplerString(type) + " sampler_" + name + ArrayString(type); } - return qualifierString(qualifier) + " " + typeString(type) + " " + name + arrayString(type); -} - -TString OutputHLSL::interpolationString(TQualifier qualifier) -{ - switch(qualifier) - { - case EvqVaryingIn: return ""; - case EvqFragmentIn: return ""; - case EvqInvariantVaryingIn: return ""; - case EvqSmoothIn: return "linear"; - case EvqFlatIn: return "nointerpolation"; - case EvqCentroidIn: return "centroid"; - case EvqVaryingOut: return ""; - case EvqVertexOut: return ""; - case EvqInvariantVaryingOut: return ""; - case EvqSmoothOut: return "linear"; - case EvqFlatOut: return "nointerpolation"; - case EvqCentroidOut: return "centroid"; - default: UNREACHABLE(); - } - - return ""; -} - -TString OutputHLSL::qualifierString(TQualifier qualifier) -{ - switch(qualifier) - { - case EvqIn: return "in"; - case EvqOut: return "inout"; // 'out' results in an HLSL error if not all fields are written, for GLSL it's undefined - case EvqInOut: return "inout"; - case EvqConstReadOnly: return "const"; - default: UNREACHABLE(); - } - - return ""; -} - -TString OutputHLSL::typeString(const TType &type) -{ - const TStructure* structure = type.getStruct(); - if (structure) - { - const TString& typeName = structure->name(); - if (typeName != "") - { - return structLookup(typeName); - } - else // Nameless structure, define in place - { - return structureString(*structure, false, false); - } - } - else if (type.isMatrix()) - { - int cols = type.getCols(); - int rows = type.getRows(); - return "float" + str(cols) + "x" + str(rows); - } - else - { - switch (type.getBasicType()) - { - case EbtFloat: - switch (type.getNominalSize()) - { - case 1: return "float"; - case 2: return "float2"; - case 3: return "float3"; - case 4: return "float4"; - } - case EbtInt: - switch (type.getNominalSize()) - { - case 1: return "int"; - case 2: return "int2"; - case 3: return "int3"; - case 4: return "int4"; - } - case EbtUInt: - switch (type.getNominalSize()) - { - case 1: return "uint"; - case 2: return "uint2"; - case 3: return "uint3"; - case 4: return "uint4"; - } - case EbtBool: - switch (type.getNominalSize()) - { - case 1: return "bool"; - case 2: return "bool2"; - case 3: return "bool3"; - case 4: return "bool4"; - } - case EbtVoid: - return "void"; - case EbtSampler2D: - case EbtISampler2D: - case EbtUSampler2D: - case EbtSampler2DArray: - case EbtISampler2DArray: - case EbtUSampler2DArray: - return "sampler2D"; - case EbtSamplerCube: - case EbtISamplerCube: - case EbtUSamplerCube: - return "samplerCUBE"; - case EbtSamplerExternalOES: - return "sampler2D"; - default: - break; - } - } - - UNREACHABLE(); - return ""; -} - -TString OutputHLSL::textureString(const TType &type) -{ - switch (type.getBasicType()) - { - case EbtSampler2D: return "Texture2D"; - case EbtSamplerCube: return "TextureCube"; - case EbtSamplerExternalOES: return "Texture2D"; - case EbtSampler2DArray: return "Texture2DArray"; - case EbtSampler3D: return "Texture3D"; - case EbtISampler2D: return "Texture2D"; - case EbtISampler3D: return "Texture3D"; - case EbtISamplerCube: return "Texture2DArray"; - case EbtISampler2DArray: return "Texture2DArray"; - case EbtUSampler2D: return "Texture2D"; - case EbtUSampler3D: return "Texture3D"; - case EbtUSamplerCube: return "Texture2DArray"; - case EbtUSampler2DArray: return "Texture2DArray"; - case EbtSampler2DShadow: return "Texture2D"; - case EbtSamplerCubeShadow: return "TextureCube"; - case EbtSampler2DArrayShadow: return "Texture2DArray"; - default: UNREACHABLE(); - } - - return ""; -} - -TString OutputHLSL::samplerString(const TType &type) -{ - if (IsShadowSampler(type.getBasicType())) - { - return "SamplerComparisonState"; - } - else - { - return "SamplerState"; - } -} - -TString OutputHLSL::arrayString(const TType &type) -{ - if (!type.isArray()) - { - return ""; - } - - return "[" + str(type.getArraySize()) + "]"; + return QualifierString(qualifier) + " " + TypeString(type) + " " + name + ArrayString(type); } TString OutputHLSL::initializer(const TType &type) @@ -3459,292 +2842,24 @@ TString OutputHLSL::initializer(const TType &type) return "{" + string + "}"; } -TString OutputHLSL::structureString(const TStructure &structure, bool useHLSLRowMajorPacking, bool useStd140Packing) +void OutputHLSL::outputConstructor(Visit visit, const TType &type, const TString &name, const TIntermSequence *parameters) { - const TFieldList &fields = structure.fields(); - const bool isNameless = (structure.name() == ""); - const TString &structName = structureTypeName(structure, useHLSLRowMajorPacking, useStd140Packing); - const TString declareString = (isNameless ? "struct" : "struct " + structName); + TInfoSinkBase &out = mBody; - TString string; - string += declareString + "\n" - "{\n"; - - int elementIndex = 0; - - for (unsigned int i = 0; i < fields.size(); i++) + if (visit == PreVisit) { - const TField &field = *fields[i]; - const TType &fieldType = *field.type(); - const TStructure *fieldStruct = fieldType.getStruct(); - const TString &fieldTypeString = fieldStruct ? structureTypeName(*fieldStruct, useHLSLRowMajorPacking, useStd140Packing) : typeString(fieldType); + mStructureHLSL->addConstructor(type, name, parameters); - if (useStd140Packing) - { - string += std140PrePaddingString(*field.type(), &elementIndex); - } - - string += " " + fieldTypeString + " " + decorateField(field.name(), structure) + arrayString(fieldType) + ";\n"; - - if (useStd140Packing) - { - string += std140PostPaddingString(*field.type(), useHLSLRowMajorPacking); - } + out << name + "("; } - - // Nameless structs do not finish with a semicolon and newline, to leave room for an instance variable - string += (isNameless ? "} " : "};\n"); - - // Add remaining element index to the global map, for use with nested structs in standard layouts - if (useStd140Packing) + else if (visit == InVisit) { - mStd140StructElementIndexes[structName] = elementIndex; + out << ", "; } - - return string; -} - -TString OutputHLSL::structureTypeName(const TStructure &structure, bool useHLSLRowMajorPacking, bool useStd140Packing) -{ - if (structure.name() == "") + else if (visit == PostVisit) { - return ""; + out << ")"; } - - TString prefix = ""; - - // Structs packed with row-major matrices in HLSL are prefixed with "rm" - // GLSL column-major maps to HLSL row-major, and the converse is true - - if (useStd140Packing) - { - prefix += "std"; - } - - if (useHLSLRowMajorPacking) - { - if (prefix != "") prefix += "_"; - prefix += "rm"; - } - - return prefix + structLookup(structure.name()); -} - -void OutputHLSL::addConstructor(const TType &type, const TString &name, const TIntermSequence *parameters) -{ - if (name == "") - { - return; // Nameless structures don't have constructors - } - - if (type.getStruct() && mStructNames.find(decorate(name)) != mStructNames.end()) - { - return; // Already added - } - - TType ctorType = type; - ctorType.clearArrayness(); - ctorType.setPrecision(EbpHigh); - ctorType.setQualifier(EvqTemporary); - - TString ctorName = type.getStruct() ? decorate(name) : name; - - typedef std::vector ParameterArray; - ParameterArray ctorParameters; - - const TStructure* structure = type.getStruct(); - if (structure) - { - mStructNames.insert(decorate(name)); - - const TString &structString = structureString(*structure, false, false); - - if (std::find(mStructDeclarations.begin(), mStructDeclarations.end(), structString) == mStructDeclarations.end()) - { - // Add row-major packed struct for interface blocks - TString rowMajorString = "#pragma pack_matrix(row_major)\n" + - structureString(*structure, true, false) + - "#pragma pack_matrix(column_major)\n"; - - TString std140String = structureString(*structure, false, true); - TString std140RowMajorString = "#pragma pack_matrix(row_major)\n" + - structureString(*structure, true, true) + - "#pragma pack_matrix(column_major)\n"; - - mStructDeclarations.push_back(structString); - mStructDeclarations.push_back(rowMajorString); - mStructDeclarations.push_back(std140String); - mStructDeclarations.push_back(std140RowMajorString); - } - - const TFieldList &fields = structure->fields(); - for (unsigned int i = 0; i < fields.size(); i++) - { - ctorParameters.push_back(*fields[i]->type()); - } - } - else if (parameters) - { - for (TIntermSequence::const_iterator parameter = parameters->begin(); parameter != parameters->end(); parameter++) - { - ctorParameters.push_back((*parameter)->getAsTyped()->getType()); - } - } - else UNREACHABLE(); - - TString constructor; - - if (ctorType.getStruct()) - { - constructor += ctorName + " " + ctorName + "_ctor("; - } - else // Built-in type - { - constructor += typeString(ctorType) + " " + ctorName + "("; - } - - for (unsigned int parameter = 0; parameter < ctorParameters.size(); parameter++) - { - const TType &type = ctorParameters[parameter]; - - constructor += typeString(type) + " x" + str(parameter) + arrayString(type); - - if (parameter < ctorParameters.size() - 1) - { - constructor += ", "; - } - } - - constructor += ")\n" - "{\n"; - - if (ctorType.getStruct()) - { - constructor += " " + ctorName + " structure = {"; - } - else - { - constructor += " return " + typeString(ctorType) + "("; - } - - if (ctorType.isMatrix() && ctorParameters.size() == 1) - { - int rows = ctorType.getRows(); - int cols = ctorType.getCols(); - const TType ¶meter = ctorParameters[0]; - - if (parameter.isScalar()) - { - for (int row = 0; row < rows; row++) - { - for (int col = 0; col < cols; col++) - { - constructor += TString((row == col) ? "x0" : "0.0"); - - if (row < rows - 1 || col < cols - 1) - { - constructor += ", "; - } - } - } - } - else if (parameter.isMatrix()) - { - for (int row = 0; row < rows; row++) - { - for (int col = 0; col < cols; col++) - { - if (row < parameter.getRows() && col < parameter.getCols()) - { - constructor += TString("x0") + "[" + str(row) + "]" + "[" + str(col) + "]"; - } - else - { - constructor += TString((row == col) ? "1.0" : "0.0"); - } - - if (row < rows - 1 || col < cols - 1) - { - constructor += ", "; - } - } - } - } - else UNREACHABLE(); - } - else - { - size_t remainingComponents = ctorType.getObjectSize(); - size_t parameterIndex = 0; - - while (remainingComponents > 0) - { - const TType ¶meter = ctorParameters[parameterIndex]; - const size_t parameterSize = parameter.getObjectSize(); - bool moreParameters = parameterIndex + 1 < ctorParameters.size(); - - constructor += "x" + str(parameterIndex); - - if (parameter.isScalar()) - { - remainingComponents -= parameter.getObjectSize(); - } - else if (parameter.isVector()) - { - if (remainingComponents == parameterSize || moreParameters) - { - ASSERT(parameterSize <= remainingComponents); - remainingComponents -= parameterSize; - } - else if (remainingComponents < static_cast(parameter.getNominalSize())) - { - switch (remainingComponents) - { - case 1: constructor += ".x"; break; - case 2: constructor += ".xy"; break; - case 3: constructor += ".xyz"; break; - case 4: constructor += ".xyzw"; break; - default: UNREACHABLE(); - } - - remainingComponents = 0; - } - else UNREACHABLE(); - } - else if (parameter.isMatrix() || parameter.getStruct()) - { - ASSERT(remainingComponents == parameterSize || moreParameters); - ASSERT(parameterSize <= remainingComponents); - - remainingComponents -= parameterSize; - } - else UNREACHABLE(); - - if (moreParameters) - { - parameterIndex++; - } - - if (remainingComponents) - { - constructor += ", "; - } - } - } - - if (ctorType.getStruct()) - { - constructor += "};\n" - " return structure;\n" - "}\n"; - } - else - { - constructor += ");\n" - "}\n"; - } - - mConstructors.insert(constructor); } const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const ConstantUnion *constUnion) @@ -3754,14 +2869,13 @@ const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const Con const TStructure* structure = type.getStruct(); if (structure) { - out << structLookup(structure->name()) + "_ctor("; - + out << StructNameString(*structure) + "_ctor("; + const TFieldList& fields = structure->fields(); for (size_t i = 0; i < fields.size(); i++) { const TType *fieldType = fields[i]->type(); - constUnion = writeConstantUnion(*fieldType, constUnion); if (i != fields.size() - 1) @@ -3776,10 +2890,10 @@ const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const Con { size_t size = type.getObjectSize(); bool writeType = size > 1; - + if (writeType) { - out << typeString(type) << "("; + out << TypeString(type) << "("; } for (size_t i = 0; i < size; i++, constUnion++) @@ -3808,418 +2922,12 @@ const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const Con return constUnion; } -TString OutputHLSL::scopeString(unsigned int depthLimit) +void OutputHLSL::declareVaryingToList(const TType &type, TQualifier baseTypeQualifier, + const TString &name, std::vector &fieldsOut) { - TString string; - - for (unsigned int i = 0; i < mScopeBracket.size() && i < depthLimit; i++) - { - string += "_" + str(mScopeBracket[i]); - } - - return string; -} - -TString OutputHLSL::scopedStruct(const TString &typeName) -{ - if (typeName == "") - { - return typeName; - } - - return typeName + scopeString(mScopeDepth); -} - -TString OutputHLSL::structLookup(const TString &typeName) -{ - for (int depth = mScopeDepth; depth >= 0; depth--) - { - TString scopedName = decorate(typeName + scopeString(depth)); - - for (StructNames::iterator structName = mStructNames.begin(); structName != mStructNames.end(); structName++) - { - if (*structName == scopedName) - { - return scopedName; - } - } - } - - UNREACHABLE(); // Should have found a matching constructor - - return typeName; -} - -TString OutputHLSL::decorate(const TString &string) -{ - if (string.compare(0, 3, "gl_") != 0 && string.compare(0, 3, "dx_") != 0) - { - return "_" + string; - } - - return string; -} - -TString OutputHLSL::decorateUniform(const TString &string, const TType &type) -{ - if (type.getBasicType() == EbtSamplerExternalOES) - { - return "ex_" + string; - } - - return decorate(string); -} - -TString OutputHLSL::decorateField(const TString &string, const TStructure &structure) -{ - if (structure.name().compare(0, 3, "gl_") != 0) - { - return decorate(string); - } - - return string; -} - -void OutputHLSL::declareInterfaceBlockField(const TType &type, const TString &name, std::vector& output) -{ - const TStructure *structure = type.getStruct(); - - if (!structure) - { - const bool isRowMajorMatrix = (type.isMatrix() && type.getLayoutQualifier().matrixPacking == EmpRowMajor); - gl::InterfaceBlockField field(glVariableType(type), glVariablePrecision(type), name.c_str(), - (unsigned int)type.getArraySize(), isRowMajorMatrix); - output.push_back(field); - } - else - { - gl::InterfaceBlockField structField(GL_STRUCT_ANGLEX, GL_NONE, name.c_str(), (unsigned int)type.getArraySize(), false); - - const TFieldList &fields = structure->fields(); - - for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++) - { - TField *field = fields[fieldIndex]; - TType *fieldType = field->type(); - - // make sure to copy matrix packing information - fieldType->setLayoutQualifier(type.getLayoutQualifier()); - - declareInterfaceBlockField(*fieldType, field->name(), structField.fields); - } - - output.push_back(structField); - } -} - -gl::Uniform OutputHLSL::declareUniformToList(const TType &type, const TString &name, int registerIndex, std::vector& output) -{ - const TStructure *structure = type.getStruct(); - - if (!structure) - { - gl::Uniform uniform(glVariableType(type), glVariablePrecision(type), name.c_str(), - (unsigned int)type.getArraySize(), (unsigned int)registerIndex, 0); - output.push_back(uniform); - - return uniform; - } - else - { - gl::Uniform structUniform(GL_STRUCT_ANGLEX, GL_NONE, name.c_str(), (unsigned int)type.getArraySize(), - (unsigned int)registerIndex, GL_INVALID_INDEX); - - const TFieldList &fields = structure->fields(); - - for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++) - { - TField *field = fields[fieldIndex]; - TType *fieldType = field->type(); - - declareUniformToList(*fieldType, field->name(), GL_INVALID_INDEX, structUniform.fields); - } - - // assign register offset information -- this will override the information in any sub-structures. - HLSLVariableGetRegisterInfo(registerIndex, &structUniform, mOutputType); - - output.push_back(structUniform); - - return structUniform; - } -} - -gl::InterpolationType getInterpolationType(TQualifier qualifier) -{ - switch (qualifier) - { - case EvqFlatIn: - case EvqFlatOut: - return gl::INTERPOLATION_FLAT; - - case EvqSmoothIn: - case EvqSmoothOut: - case EvqVertexOut: - case EvqFragmentIn: - case EvqVaryingIn: - case EvqVaryingOut: - return gl::INTERPOLATION_SMOOTH; - - case EvqCentroidIn: - case EvqCentroidOut: - return gl::INTERPOLATION_CENTROID; - - default: UNREACHABLE(); - return gl::INTERPOLATION_SMOOTH; - } -} - -void OutputHLSL::declareVaryingToList(const TType &type, TQualifier baseTypeQualifier, const TString &name, std::vector& fieldsOut) -{ - const TStructure *structure = type.getStruct(); - - gl::InterpolationType interpolation = getInterpolationType(baseTypeQualifier); - if (!structure) - { - gl::Varying varying(glVariableType(type), glVariablePrecision(type), name.c_str(), (unsigned int)type.getArraySize(), interpolation); - fieldsOut.push_back(varying); - } - else - { - gl::Varying structVarying(GL_STRUCT_ANGLEX, GL_NONE, name.c_str(), (unsigned int)type.getArraySize(), interpolation); - const TFieldList &fields = structure->fields(); - - structVarying.structName = structure->name().c_str(); - - for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++) - { - const TField &field = *fields[fieldIndex]; - declareVaryingToList(*field.type(), baseTypeQualifier, field.name(), structVarying.fields); - } - - fieldsOut.push_back(structVarying); - } -} - -int OutputHLSL::declareUniformAndAssignRegister(const TType &type, const TString &name) -{ - int registerIndex = (IsSampler(type.getBasicType()) ? mSamplerRegister : mUniformRegister); - - const gl::Uniform &uniform = declareUniformToList(type, name, registerIndex, mActiveUniforms); - - if (IsSampler(type.getBasicType())) - { - mSamplerRegister += gl::HLSLVariableRegisterCount(uniform, mOutputType); - } - else - { - mUniformRegister += gl::HLSLVariableRegisterCount(uniform, mOutputType); - } - - return registerIndex; -} - -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.getCols()) - { - case 2: - switch(type.getRows()) - { - case 2: return GL_FLOAT_MAT2; - case 3: return GL_FLOAT_MAT2x3; - case 4: return GL_FLOAT_MAT2x4; - default: UNREACHABLE(); - } - - case 3: - switch(type.getRows()) - { - case 2: return GL_FLOAT_MAT3x2; - case 3: return GL_FLOAT_MAT3; - case 4: return GL_FLOAT_MAT3x4; - default: UNREACHABLE(); - } - - case 4: - switch(type.getRows()) - { - case 2: return GL_FLOAT_MAT4x2; - case 3: return GL_FLOAT_MAT4x3; - case 4: return GL_FLOAT_MAT4; - default: UNREACHABLE(); - } - - 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() == EbtUInt) - { - if (type.isScalar()) - { - return GL_UNSIGNED_INT; - } - else if (type.isVector()) - { - switch(type.getNominalSize()) - { - case 2: return GL_UNSIGNED_INT_VEC2; - case 3: return GL_UNSIGNED_INT_VEC3; - case 4: return GL_UNSIGNED_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(); - } - - switch(type.getBasicType()) - { - case EbtSampler2D: return GL_SAMPLER_2D; - case EbtSampler3D: return GL_SAMPLER_3D; - case EbtSamplerCube: return GL_SAMPLER_CUBE; - case EbtSampler2DArray: return GL_SAMPLER_2D_ARRAY; - case EbtISampler2D: return GL_INT_SAMPLER_2D; - case EbtISampler3D: return GL_INT_SAMPLER_3D; - case EbtISamplerCube: return GL_INT_SAMPLER_CUBE; - case EbtISampler2DArray: return GL_INT_SAMPLER_2D_ARRAY; - case EbtUSampler2D: return GL_UNSIGNED_INT_SAMPLER_2D; - case EbtUSampler3D: return GL_UNSIGNED_INT_SAMPLER_3D; - case EbtUSamplerCube: return GL_UNSIGNED_INT_SAMPLER_CUBE; - case EbtUSampler2DArray: return GL_UNSIGNED_INT_SAMPLER_2D_ARRAY; - case EbtSampler2DShadow: return GL_SAMPLER_2D_SHADOW; - case EbtSamplerCubeShadow: return GL_SAMPLER_CUBE_SHADOW; - case EbtSampler2DArrayShadow: return GL_SAMPLER_2D_ARRAY_SHADOW; - default: 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 || type.getBasicType() == EbtUInt) - { - 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; -} - -bool OutputHLSL::isVaryingOut(TQualifier qualifier) -{ - switch(qualifier) - { - case EvqVaryingOut: - case EvqInvariantVaryingOut: - case EvqSmoothOut: - case EvqFlatOut: - case EvqCentroidOut: - case EvqVertexOut: - return true; - - default: break; - } - - return false; -} - -bool OutputHLSL::isVaryingIn(TQualifier qualifier) -{ - switch(qualifier) - { - case EvqVaryingIn: - case EvqInvariantVaryingIn: - case EvqSmoothIn: - case EvqFlatIn: - case EvqCentroidIn: - case EvqFragmentIn: - return true; - - default: break; - } - - return false; -} - -bool OutputHLSL::isVarying(TQualifier qualifier) -{ - return isVaryingIn(qualifier) || isVaryingOut(qualifier); + GetVariableTraverser traverser; + traverser.traverse(type, name, &fieldsOut); + fieldsOut.back().interpolation = GetInterpolationType(baseTypeQualifier); } } diff --git a/gfx/angle/src/compiler/translator/OutputHLSL.h b/gfx/angle/src/compiler/translator/OutputHLSL.h index 55d6441b2310..61afc41a6731 100644 --- a/gfx/angle/src/compiler/translator/OutputHLSL.h +++ b/gfx/angle/src/compiler/translator/OutputHLSL.h @@ -11,16 +11,18 @@ #include #include -#include -#include +#include "angle_gl.h" -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include "compiler/translator/ParseContext.h" -#include "common/shadervars.h" namespace sh { class UnfoldShortCircuit; +class StructureHLSL; +class UniformHLSL; + +typedef std::map ReferencedSymbols; class OutputHLSL : public TIntermTraverser { @@ -31,30 +33,23 @@ class OutputHLSL : public TIntermTraverser void output(); TInfoSinkBase &getBodyStream(); - const std::vector &getUniforms(); - const std::vector &getInterfaceBlocks() const; - const std::vector &getOutputVariables() const; - const std::vector &getAttributes() const; - const std::vector &getVaryings() const; + const std::vector &getUniforms(); + const std::vector &getInterfaceBlocks() const; + const std::vector &getOutputVariables() const; + const std::vector &getAttributes() const; + const std::vector &getVaryings() const; + + const std::map &getInterfaceBlockRegisterMap() const; + const std::map &getUniformRegisterMap() const; - TString typeString(const TType &type); - TString textureString(const TType &type); - TString samplerString(const TType &type); - TString interpolationString(TQualifier qualifier); - TString structureString(const TStructure &structure, bool useHLSLRowMajorPacking, bool useStd140Packing); - TString structureTypeName(const TStructure &structure, bool useHLSLRowMajorPacking, bool useStd140Packing); - static TString qualifierString(TQualifier qualifier); - static TString arrayString(const TType &type); static TString initializer(const TType &type); - static TString decorate(const TString &string); // Prepends an underscore to avoid naming clashes - static TString decorateUniform(const TString &string, const TType &type); - static TString decorateField(const TString &string, const TStructure &structure); protected: void header(); // Visit AST nodes and output their code to the body stream void visitSymbol(TIntermSymbol*); + void visitRaw(TIntermRaw*); void visitConstantUnion(TIntermConstantUnion*); bool visitBinary(Visit visit, TIntermBinary*); bool visitUnary(Visit visit, TIntermUnary*); @@ -71,13 +66,9 @@ class OutputHLSL : public TIntermTraverser TString argumentString(const TIntermSymbol *symbol); int vectorSize(const TType &type) const; - void addConstructor(const TType &type, const TString &name, const TIntermSequence *parameters); + void outputConstructor(Visit visit, const TType &type, const TString &name, const TIntermSequence *parameters); const ConstantUnion *writeConstantUnion(const TType &type, const ConstantUnion *constUnion); - TString scopeString(unsigned int depthLimit); - TString scopedStruct(const TString &typeName); - TString structLookup(const TString &typeName); - TParseContext &mContext; const ShShaderOutput mOutputType; UnfoldShortCircuit *mUnfoldShortCircuit; @@ -88,13 +79,15 @@ class OutputHLSL : public TIntermTraverser TInfoSinkBase mBody; TInfoSinkBase mFooter; - typedef std::map ReferencedSymbols; ReferencedSymbols mReferencedUniforms; ReferencedSymbols mReferencedInterfaceBlocks; ReferencedSymbols mReferencedAttributes; ReferencedSymbols mReferencedVaryings; ReferencedSymbols mReferencedOutputVariables; + StructureHLSL *mStructureHLSL; + UniformHLSL *mUniformHLSL; + struct TextureFunction { enum Method @@ -153,19 +146,6 @@ class OutputHLSL : public TIntermTraverser int mNumRenderTargets; - typedef std::set Constructors; - Constructors mConstructors; - - typedef std::set StructNames; - StructNames mStructNames; - - typedef std::list StructDeclarations; - StructDeclarations mStructDeclarations; - - typedef std::vector ScopeBracket; - ScopeBracket mScopeBracket; - unsigned int mScopeDepth; - int mUniqueIndex; // For creating unique names bool mContainsLoopDiscontinuity; @@ -175,51 +155,19 @@ class OutputHLSL : public TIntermTraverser TIntermSymbol *mExcessiveLoopIndex; - int mUniformRegister; - int mInterfaceBlockRegister; - int mSamplerRegister; - int mPaddingCounter; + void declareVaryingToList(const TType &type, TQualifier baseTypeQualifier, const TString &name, std::vector& fieldsOut); - TString registerString(TIntermSymbol *operand); - int samplerRegister(TIntermSymbol *sampler); - int uniformRegister(TIntermSymbol *uniform); - void declareInterfaceBlockField(const TType &type, const TString &name, std::vector& output); - gl::Uniform declareUniformToList(const TType &type, const TString &name, int registerIndex, std::vector& output); - void declareUniform(const TType &type, const TString &name, int index); - void declareVaryingToList(const TType &type, TQualifier baseTypeQualifier, const TString &name, std::vector& fieldsOut); - - // Returns the uniform's register index - int declareUniformAndAssignRegister(const TType &type, const TString &name); - - TString interfaceBlockFieldString(const TInterfaceBlock &interfaceBlock, const TField &field); - TString decoratePrivate(const TString &privateText); - TString interfaceBlockStructNameString(const TInterfaceBlock &interfaceBlockType); - TString interfaceBlockInstanceString(const TInterfaceBlock& interfaceBlock, unsigned int arrayIndex); - TString interfaceBlockFieldTypeString(const TField &field, TLayoutBlockStorage blockStorage); - TString interfaceBlockFieldString(const TInterfaceBlock &interfaceBlock, TLayoutBlockStorage blockStorage); - TString interfaceBlockStructString(const TInterfaceBlock &interfaceBlock); - TString interfaceBlockString(const TInterfaceBlock &interfaceBlock, unsigned int registerIndex, unsigned int arrayIndex); - TString std140PrePaddingString(const TType &type, int *elementIndex); - TString std140PostPaddingString(const TType &type, bool useHLSLRowMajorPacking); TString structInitializerString(int indent, const TStructure &structure, const TString &rhsStructName); - - static GLenum glVariableType(const TType &type); - static GLenum glVariablePrecision(const TType &type); - static bool isVaryingIn(TQualifier qualifier); - static bool isVaryingOut(TQualifier qualifier); - static bool isVarying(TQualifier qualifier); - std::vector mActiveUniforms; - std::vector mActiveInterfaceBlocks; - std::vector mActiveOutputVariables; - std::vector mActiveAttributes; - std::vector mActiveVaryings; - std::map mStd140StructElementIndexes; + std::vector mActiveOutputVariables; + std::vector mActiveAttributes; + std::vector mActiveVaryings; std::map mFlaggedStructMappedNames; std::map mFlaggedStructOriginalNames; void makeFlaggedStructMaps(const std::vector &flaggedStructs); }; + } #endif // COMPILER_OUTPUTHLSL_H_ diff --git a/gfx/angle/src/compiler/translator/ParseContext.cpp b/gfx/angle/src/compiler/translator/ParseContext.cpp index 8ff9d30efbad..ff0a49667c81 100644 --- a/gfx/angle/src/compiler/translator/ParseContext.cpp +++ b/gfx/angle/src/compiler/translator/ParseContext.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2014 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. // @@ -286,21 +286,21 @@ bool TParseContext::lValueErrorCheck(const TSourceLoc& line, const char* op, TIn TIntermTyped* rightNode = binaryNode->getRight(); TIntermAggregate *aggrNode = rightNode->getAsAggregate(); - - for (TIntermSequence::iterator p = aggrNode->getSequence().begin(); - p != aggrNode->getSequence().end(); p++) { + + for (TIntermSequence::iterator p = aggrNode->getSequence()->begin(); + p != aggrNode->getSequence()->end(); p++) { int value = (*p)->getAsTyped()->getAsConstantUnion()->getIConst(0); - offset[value]++; + offset[value]++; if (offset[value] > 1) { error(line, " l-value of swizzle cannot have duplicate components", op); return true; } } - } + } return errorReturn; - default: + default: break; } error(line, " l-value required", op); @@ -701,28 +701,44 @@ bool TParseContext::arraySizeErrorCheck(const TSourceLoc& line, TIntermTyped* ex return true; } + unsigned int unsignedSize = 0; + if (constant->getBasicType() == EbtUInt) { - unsigned int uintSize = constant->getUConst(0); - if (uintSize > static_cast(std::numeric_limits::max())) - { - error(line, "array size too large", ""); - size = 1; - return true; - } - - size = static_cast(uintSize); + unsignedSize = constant->getUConst(0); + size = static_cast(unsignedSize); } else { size = constant->getIConst(0); - if (size <= 0) + if (size < 0) { - error(line, "array size must be a positive integer", ""); + error(line, "array size must be non-negative", ""); size = 1; return true; } + + unsignedSize = static_cast(size); + } + + if (size == 0) + { + error(line, "array size must be greater than zero", ""); + size = 1; + return true; + } + + // The size of arrays is restricted here to prevent issues further down the + // compiler/translator/driver stack. Shader Model 5 generation hardware is limited to + // 4096 registers so this should be reasonable even for aggressively optimizable code. + const unsigned int sizeLimit = 65536; + + if (unsignedSize > sizeLimit) + { + error(line, "array size too large", ""); + size = 1; + return true; } return false; @@ -788,7 +804,7 @@ bool TParseContext::arrayErrorCheck(const TSourceLoc& line, const TString& ident if (type.arraySize) variable->getType().setArraySize(type.arraySize); - if (! symbolTable.declare(*variable)) { + if (! symbolTable.declare(variable)) { delete variable; error(line, "INTERNAL ERROR inserting new symbol", identifier.c_str()); return true; @@ -868,7 +884,7 @@ bool TParseContext::nonInitErrorCheck(const TSourceLoc& line, const TString& ide variable = new TVariable(&identifier, TType(type)); - if (! symbolTable.declare(*variable)) { + if (! symbolTable.declare(variable)) { error(line, "redefinition", variable->getName().c_str()); delete variable; variable = 0; @@ -1002,6 +1018,45 @@ void TParseContext::handlePragmaDirective(const TSourceLoc& loc, const char* nam // ///////////////////////////////////////////////////////////////////////////////// +const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location, + const TString *name, + const TSymbol *symbol) +{ + const TVariable *variable = NULL; + + if (!symbol) + { + error(location, "undeclared identifier", name->c_str()); + recover(); + } + else if (!symbol->isVariable()) + { + error(location, "variable expected", name->c_str()); + recover(); + } + else + { + variable = static_cast(symbol); + + if (symbolTable.findBuiltIn(variable->getName(), shaderVersion) && + !variable->getExtension().empty() && + extensionErrorCheck(location, variable->getExtension())) + { + recover(); + } + } + + if (!variable) + { + TType type(EbtFloat, EbpUndefined); + TVariable *fakeVariable = new TVariable(name, type); + symbolTable.declare(fakeVariable); + variable = fakeVariable; + } + + return variable; +} + // // Look up a function name in the symbol table, and make sure it is a function. // @@ -1034,6 +1089,8 @@ const TFunction* TParseContext::findFunction(const TSourceLoc& line, TFunction* // Initializers show up in several places in the grammar. Have one set of // code to handle them here. // +// Returns true on error, false if no error +// bool TParseContext::executeInitializer(const TSourceLoc& line, const TString& identifier, TPublicType& pType, TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable) { @@ -1050,7 +1107,7 @@ bool TParseContext::executeInitializer(const TSourceLoc& line, const TString& id // add variable to symbol table // variable = new TVariable(&identifier, type); - if (! symbolTable.declare(*variable)) { + if (! symbolTable.declare(variable)) { error(line, "redefinition", variable->getName().c_str()); return true; // don't delete variable, it's used by error recovery, and the pool @@ -1126,8 +1183,8 @@ bool TParseContext::areAllChildConst(TIntermAggregate* aggrNode) // check if all the child nodes are constants so that they can be inserted into // the parent node - TIntermSequence &sequence = aggrNode->getSequence() ; - for (TIntermSequence::iterator p = sequence.begin(); p != sequence.end(); ++p) { + TIntermSequence *sequence = aggrNode->getSequence() ; + for (TIntermSequence::iterator p = sequence->begin(); p != sequence->end(); ++p) { if (!(*p)->getAsTyped()->getAsConstantUnion()) return false; } @@ -1292,14 +1349,40 @@ TIntermAggregate* TParseContext::parseSingleInitDeclaration(TPublicType &publicT } } -TIntermAggregate* TParseContext::parseDeclarator(TPublicType &publicType, TIntermAggregate *aggregateDeclaration, TSymbol *identifierSymbol, const TSourceLoc& identifierLocation, const TString &identifier) +TIntermAggregate* TParseContext::parseInvariantDeclaration(const TSourceLoc &invariantLoc, + const TSourceLoc &identifierLoc, + const TString *identifier, + const TSymbol *symbol) { - if (publicType.type == EbtInvariant && !identifierSymbol) + // invariant declaration + if (globalErrorCheck(invariantLoc, symbolTable.atGlobalLevel(), "invariant varying")) { - error(identifierLocation, "undeclared identifier declared as invariant", identifier.c_str()); recover(); } + if (!symbol) + { + error(identifierLoc, "undeclared identifier declared as invariant", identifier->c_str()); + recover(); + + return NULL; + } + else + { + const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol); + ASSERT(variable); + const TType &type = variable->getType(); + TIntermSymbol *intermSymbol = intermediate.addSymbol(variable->getUniqueId(), + *identifier, type, identifierLoc); + + TIntermAggregate *aggregate = intermediate.makeAggregate(intermSymbol, identifierLoc); + aggregate->setOp(EOpInvariantDeclaration); + return aggregate; + } +} + +TIntermAggregate* TParseContext::parseDeclarator(TPublicType &publicType, TIntermAggregate *aggregateDeclaration, TSymbol *identifierSymbol, const TSourceLoc& identifierLocation, const TString &identifier) +{ TIntermSymbol* symbol = intermediate.addSymbol(0, identifier, TType(publicType), identifierLocation); TIntermAggregate* intermAggregate = intermediate.growAggregate(aggregateDeclaration, symbol, identifierLocation); @@ -1515,81 +1598,40 @@ TFunction *TParseContext::addConstructorFunc(TPublicType publicType) // // 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, const TSourceLoc& line) +TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments, const TType *type, TOperator op, TFunction *fnCall, const TSourceLoc &line) { - if (node == 0) - return 0; + TIntermAggregate *aggregateArguments = arguments->getAsAggregate(); + + if (!aggregateArguments) + { + aggregateArguments = new TIntermAggregate; + aggregateArguments->getSequence()->push_back(arguments); + } - TIntermAggregate* aggrNode = node->getAsAggregate(); - - TFieldList::const_iterator memberTypes; if (op == EOpConstructStruct) - memberTypes = type->getStruct()->fields().begin(); - - TType elementType = *type; - if (type->isArray()) - elementType.clearArrayness(); + { + const TFieldList &fields = type->getStruct()->fields(); + TIntermSequence *args = aggregateArguments->getSequence(); - bool singleArg; - if (aggrNode) { - if (aggrNode->getOp() != EOpNull || aggrNode->getSequence().size() == 1) - singleArg = true; - else - singleArg = false; - } else - singleArg = true; + for (size_t i = 0; i < fields.size(); i++) + { + if (i >= args->size() || (*args)[i]->getAsTyped()->getType() != *fields[i]->type()) + { + error(line, "Structure constructor arguments do not match structure fields", "Error"); + recover(); - TIntermTyped *newNode; - if (singleArg) { - // If structure constructor or array constructor is being called - // for only one parameter inside the structure, we need to call constructStruct function once. - if (type->isArray()) - newNode = constructStruct(node, &elementType, 1, node->getLine(), false); - else if (op == EOpConstructStruct) - newNode = constructStruct(node, (*memberTypes)->type(), 1, node->getLine(), false); - else - newNode = constructBuiltIn(type, op, node, node->getLine(), false); - - if (newNode && newNode->getAsAggregate()) { - TIntermTyped* constConstructor = foldConstConstructor(newNode->getAsAggregate(), *type); - if (constConstructor) - return constConstructor; - } - - return newNode; - } - - // - // Handle list of arguments. - // - TIntermSequence &sequenceVector = aggrNode->getSequence() ; // Stores the information about the parameter to the constructor - // if the structure constructor contains more than one parameter, then construct - // each parameter - - int paramCount = 0; // keeps a track of the constructor parameter number being checked - - // for each parameter to the constructor call, check to see if the right type is passed or convert them - // to the right type if possible (and allowed). - // for structure constructors, just check if the right type is passed, no conversion is allowed. - - for (TIntermSequence::iterator p = sequenceVector.begin(); - p != sequenceVector.end(); p++, paramCount++) { - 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); - else - newNode = constructBuiltIn(type, op, *p, node->getLine(), true); - - if (newNode) { - *p = newNode; + return 0; + } } } - TIntermTyped* constructor = intermediate.setAggregateOperator(aggrNode, op, line); - TIntermTyped* constConstructor = foldConstConstructor(constructor->getAsAggregate(), *type); + // Turn the argument list itself into a constructor + TIntermTyped *constructor = intermediate.setAggregateOperator(aggregateArguments, op, line); + TIntermTyped *constConstructor = foldConstConstructor(constructor->getAsAggregate(), *type); if (constConstructor) + { return constConstructor; + } return constructor; } @@ -1601,7 +1643,7 @@ TIntermTyped* TParseContext::foldConstConstructor(TIntermAggregate* aggrNode, co if (canBeFolded) { bool returnVal = false; ConstantUnion* unionArray = new ConstantUnion[type.getObjectSize()]; - if (aggrNode->getSequence().size() == 1) { + if (aggrNode->getSequence()->size() == 1) { returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), type, true); } else { @@ -1616,102 +1658,6 @@ TIntermTyped* TParseContext::foldConstConstructor(TIntermAggregate* aggrNode, co return 0; } -// Function for constructor implementation. Calls addUnaryMath with appropriate EOp value -// for the parameter to the constructor (passed to this function). Essentially, it converts -// the parameter types correctly. If a constructor expects an int (like ivec2) and is passed a -// float, then float is converted to int. -// -// Returns 0 for an error or the constructed node. -// -TIntermTyped* TParseContext::constructBuiltIn(const TType* type, TOperator op, TIntermNode* node, const TSourceLoc& line, bool subset) -{ - TIntermTyped* newNode; - TOperator basicOp; - - // - // First, convert types as needed. - // - switch (op) { - case EOpConstructVec2: - case EOpConstructVec3: - case EOpConstructVec4: - case EOpConstructMat2: - case EOpConstructMat3: - case EOpConstructMat4: - case EOpConstructFloat: - basicOp = EOpConstructFloat; - break; - - case EOpConstructIVec2: - case EOpConstructIVec3: - case EOpConstructIVec4: - case EOpConstructInt: - basicOp = EOpConstructInt; - break; - - case EOpConstructUVec2: - case EOpConstructUVec3: - case EOpConstructUVec4: - case EOpConstructUInt: - basicOp = EOpConstructUInt; - break; - - case EOpConstructBVec2: - case EOpConstructBVec3: - case EOpConstructBVec4: - case EOpConstructBool: - basicOp = EOpConstructBool; - break; - - default: - error(line, "unsupported construction", ""); - recover(); - - return 0; - } - newNode = intermediate.addUnaryMath(basicOp, node, node->getLine()); - if (newNode == 0) { - error(line, "can't convert", "constructor"); - return 0; - } - - // - // Now, if there still isn't an operation to do the construction, and we need one, add one. - // - - // Otherwise, skip out early. - if (subset || (newNode != node && newNode->getType() == *type)) - return newNode; - - // setAggregateOperator will insert a new node for the constructor, as needed. - return intermediate.setAggregateOperator(newNode, op, line); -} - -// This function tests for the type of the parameters to the structures constructors. Raises -// an error message if the expected type does not match the parameter passed to the constructor. -// -// 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, const TSourceLoc& line, bool subset) -{ - if (*type == node->getAsTyped()->getType()) { - if (subset) - return node->getAsTyped(); - else - return intermediate.setAggregateOperator(node->getAsTyped(), EOpConstructStruct, line); - } else { - std::stringstream extraInfoStream; - extraInfoStream << "cannot convert parameter " << paramCount - << " from '" << node->getAsTyped()->getType().getBasicString() - << "' to '" << type->getBasicString() << "'"; - std::string extraInfo = extraInfoStream.str(); - error(line, "", "constructor", extraInfo.c_str()); - recover(); - } - - return 0; -} - // // This function returns the tree representation for the vector field(s) being accessed from contant vector. // If only one component of vector is accessed (v.x or v[0] where v is a contant vector), then a contant node is @@ -1895,7 +1841,7 @@ TIntermAggregate* TParseContext::addInterfaceBlock(const TPublicType& typeQualif } TSymbol* blockNameSymbol = new TInterfaceBlockName(&blockName); - if (!symbolTable.declare(*blockNameSymbol)) { + if (!symbolTable.declare(blockNameSymbol)) { error(nameLine, "redefinition", blockName.c_str(), "interface block name"); recover(); } @@ -1975,7 +1921,7 @@ TIntermAggregate* TParseContext::addInterfaceBlock(const TPublicType& typeQualif TVariable* fieldVariable = new TVariable(&field->name(), *fieldType); fieldVariable->setQualifier(typeQualifier.qualifier); - if (!symbolTable.declare(*fieldVariable)) { + if (!symbolTable.declare(fieldVariable)) { error(field->line(), "redefinition", field->name().c_str(), "interface block member name"); recover(); } @@ -1987,7 +1933,7 @@ TIntermAggregate* TParseContext::addInterfaceBlock(const TPublicType& typeQualif TVariable* instanceTypeDef = new TVariable(instanceName, interfaceBlockType, false); instanceTypeDef->setQualifier(typeQualifier.qualifier); - if (!symbolTable.declare(*instanceTypeDef)) { + if (!symbolTable.declare(instanceTypeDef)) { error(instanceLine, "redefinition", instanceName->c_str(), "interface block instance name"); recover(); } @@ -2567,6 +2513,8 @@ TPublicType TParseContext::addStructure(const TSourceLoc& structLine, const TSou TStructure* structure = new TStructure(structName, fieldList); TType* structureType = new TType(structure); + structure->setUniqueId(TSymbolTable::nextUniqueId()); + if (!structName->empty()) { if (reservedErrorCheck(nameLine, *structName)) @@ -2574,7 +2522,7 @@ TPublicType TParseContext::addStructure(const TSourceLoc& structLine, const TSou recover(); } TVariable* userTypeDef = new TVariable(structName, *structureType, true); - if (!symbolTable.declare(*userTypeDef)) { + if (!symbolTable.declare(userTypeDef)) { error(nameLine, "redefinition", structName->c_str(), "struct"); recover(); } diff --git a/gfx/angle/src/compiler/translator/ParseContext.h b/gfx/angle/src/compiler/translator/ParseContext.h index 3cd4b915e3ce..1f4cbdeba959 100644 --- a/gfx/angle/src/compiler/translator/ParseContext.h +++ b/gfx/angle/src/compiler/translator/ParseContext.h @@ -1,15 +1,15 @@ // -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2014 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 _PARSER_HELPER_INCLUDED_ #define _PARSER_HELPER_INCLUDED_ +#include "compiler/translator/Compiler.h" #include "compiler/translator/Diagnostics.h" #include "compiler/translator/DirectiveHandler.h" -#include "compiler/translator/localintermediate.h" -#include "compiler/translator/ShHandle.h" +#include "compiler/translator/Intermediate.h" #include "compiler/translator/SymbolTable.h" #include "compiler/preprocessor/Preprocessor.h" @@ -25,7 +25,7 @@ struct TMatrixFields { // they can be passed to the parser without needing a global. // struct TParseContext { - TParseContext(TSymbolTable& symt, TExtensionBehavior& ext, TIntermediate& interm, ShShaderType type, ShShaderSpec spec, int options, bool checksPrecErrors, const char* sourcePath, TInfoSink& is) : + TParseContext(TSymbolTable& symt, TExtensionBehavior& ext, TIntermediate& interm, sh::GLenum type, ShShaderSpec spec, int options, bool checksPrecErrors, const char* sourcePath, TInfoSink& is) : intermediate(interm), symbolTable(symt), shaderType(type), @@ -47,7 +47,7 @@ struct TParseContext { scanner(NULL) { } TIntermediate& intermediate; // to hold and build a parse tree TSymbolTable& symbolTable; // symbol table that goes with the language currently being parsed - ShShaderType shaderType; // vertex or fragment language (future: pack or unpack) + sh::GLenum shaderType; // vertex or fragment language (future: pack or unpack) ShShaderSpec shaderSpec; // The language specification compiler conforms to - GLES2 or WebGL. int shaderVersion; int compileOptions; @@ -77,6 +77,9 @@ struct TParseContext { void trace(const char* str); void recover(); + // This method is guaranteed to succeed, even if no variable with 'name' exists. + const TVariable *getNamedVariable(const TSourceLoc &location, const TString *name, const TSymbol *symbol); + bool parseVectorFields(const TString&, int vecSize, TVectorFields&, const TSourceLoc& line); bool parseMatrixFields(const TString&, int matCols, int matRows, TMatrixFields&, const TSourceLoc& line); @@ -126,6 +129,8 @@ struct TParseContext { TIntermAggregate* parseSingleDeclaration(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier); TIntermAggregate* parseSingleArrayDeclaration(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier, const TSourceLoc& indexLocation, TIntermTyped *indexExpression); TIntermAggregate* parseSingleInitDeclaration(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier, const TSourceLoc& initLocation, TIntermTyped *initializer); + TIntermAggregate* parseInvariantDeclaration(const TSourceLoc &invariantLoc, const TSourceLoc &identifierLoc, const TString *identifier, const TSymbol *symbol); + TIntermAggregate* parseDeclarator(TPublicType &publicType, TIntermAggregate *aggregateDeclaration, TSymbol *identifierSymbol, const TSourceLoc& identifierLocation, const TString &identifier); TIntermAggregate* parseArrayDeclarator(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier, const TSourceLoc& arrayLocation, TIntermNode *declaratorList, TIntermTyped *indexExpression); TIntermAggregate* parseInitDeclarator(TPublicType &publicType, TIntermAggregate *declaratorList, const TSourceLoc& identifierLocation, const TString &identifier, const TSourceLoc& initLocation, TIntermTyped *initializer); @@ -133,8 +138,6 @@ struct TParseContext { TFunction *addConstructorFunc(TPublicType publicType); TIntermTyped* addConstructor(TIntermNode*, const TType*, TOperator, TFunction*, const TSourceLoc&); TIntermTyped* foldConstConstructor(TIntermAggregate* aggrNode, const TType& type); - 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); diff --git a/gfx/angle/src/compiler/translator/PoolAlloc.cpp b/gfx/angle/src/compiler/translator/PoolAlloc.cpp index abe70262f2d0..887cb66504ab 100644 --- a/gfx/angle/src/compiler/translator/PoolAlloc.cpp +++ b/gfx/angle/src/compiler/translator/PoolAlloc.cpp @@ -6,43 +6,44 @@ #include "compiler/translator/PoolAlloc.h" -#ifndef _MSC_VER -#include -#endif -#include - -#include "common/angleutils.h" #include "compiler/translator/InitializeGlobals.h" -#include "compiler/translator/osinclude.h" -OS_TLSIndex PoolIndex = OS_INVALID_TLS_INDEX; +#include "common/platform.h" +#include "common/angleutils.h" +#include "common/tls.h" + +#include +#include +#include + +TLSIndex PoolIndex = TLS_INVALID_INDEX; bool InitializePoolIndex() { - assert(PoolIndex == OS_INVALID_TLS_INDEX); + assert(PoolIndex == TLS_INVALID_INDEX); - PoolIndex = OS_AllocTLSIndex(); - return PoolIndex != OS_INVALID_TLS_INDEX; + PoolIndex = CreateTLSIndex(); + return PoolIndex != TLS_INVALID_INDEX; } void FreePoolIndex() { - assert(PoolIndex != OS_INVALID_TLS_INDEX); + assert(PoolIndex != TLS_INVALID_INDEX); - OS_FreeTLSIndex(PoolIndex); - PoolIndex = OS_INVALID_TLS_INDEX; + DestroyTLSIndex(PoolIndex); + PoolIndex = TLS_INVALID_INDEX; } TPoolAllocator* GetGlobalPoolAllocator() { - assert(PoolIndex != OS_INVALID_TLS_INDEX); - return static_cast(OS_GetTLSValue(PoolIndex)); + assert(PoolIndex != TLS_INVALID_INDEX); + return static_cast(GetTLSValue(PoolIndex)); } void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator) { - assert(PoolIndex != OS_INVALID_TLS_INDEX); - OS_SetTLSValue(PoolIndex, poolAllocator); + assert(PoolIndex != TLS_INVALID_INDEX); + SetTLSValue(PoolIndex, poolAllocator); } // diff --git a/gfx/angle/src/compiler/translator/QualifierAlive.cpp b/gfx/angle/src/compiler/translator/QualifierAlive.cpp index 1ba087e17658..1f6fb758216b 100644 --- a/gfx/angle/src/compiler/translator/QualifierAlive.cpp +++ b/gfx/angle/src/compiler/translator/QualifierAlive.cpp @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" class TAliveTraverser : public TIntermTraverser { public: diff --git a/gfx/angle/src/compiler/translator/RegenerateStructNames.cpp b/gfx/angle/src/compiler/translator/RegenerateStructNames.cpp new file mode 100644 index 000000000000..767b18085c64 --- /dev/null +++ b/gfx/angle/src/compiler/translator/RegenerateStructNames.cpp @@ -0,0 +1,82 @@ +// +// Copyright (c) 2002-2014 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/translator/RegenerateStructNames.h" +#include "compiler/translator/compilerdebug.h" + +void RegenerateStructNames::visitSymbol(TIntermSymbol *symbol) +{ + ASSERT(symbol); + TType *type = symbol->getTypePointer(); + ASSERT(type); + TStructure *userType = type->getStruct(); + if (!userType) + return; + + if (mSymbolTable.findBuiltIn(userType->name(), mShaderVersion)) + { + // Built-in struct, do not touch it. + return; + } + + int uniqueId = userType->uniqueId(); + + ASSERT(mScopeDepth > 0); + if (mScopeDepth == 1) + { + // If a struct is defined at global scope, we don't map its name. + // This is because at global level, the struct might be used to + // declare a uniform, so the same name needs to stay the same for + // vertex/fragment shaders. However, our mapping uses internal ID, + // which will be different for the same struct in vertex/fragment + // shaders. + // This is OK because names for any structs defined in other scopes + // will begin with "_webgl", which is reserved. So there will be + // no conflicts among unmapped struct names from global scope and + // mapped struct names from other scopes. + // However, we need to keep track of these global structs, so if a + // variable is used in a local scope, we don't try to modify the + // struct name through that variable. + mDeclaredGlobalStructs.insert(uniqueId); + return; + } + if (mDeclaredGlobalStructs.count(uniqueId) > 0) + return; + // Map {name} to _webgl_struct_{uniqueId}_{name}. + const char kPrefix[] = "_webgl_struct_"; + if (userType->name().find(kPrefix) == 0) + { + // The name has already been regenerated. + return; + } + std::string id = Str(uniqueId); + TString tmp = kPrefix + TString(id.c_str()); + tmp += "_" + userType->name(); + userType->setName(tmp); +} + +bool RegenerateStructNames::visitAggregate(Visit, TIntermAggregate *aggregate) +{ + ASSERT(aggregate); + switch (aggregate->getOp()) + { + case EOpSequence: + ++mScopeDepth; + { + TIntermSequence &sequence = *(aggregate->getSequence()); + for (size_t ii = 0; ii < sequence.size(); ++ii) + { + TIntermNode *node = sequence[ii]; + ASSERT(node != NULL); + node->traverse(this); + } + } + --mScopeDepth; + return false; + default: + return true; + } +} diff --git a/gfx/angle/src/compiler/translator/RegenerateStructNames.h b/gfx/angle/src/compiler/translator/RegenerateStructNames.h new file mode 100644 index 000000000000..ac8760034759 --- /dev/null +++ b/gfx/angle/src/compiler/translator/RegenerateStructNames.h @@ -0,0 +1,40 @@ +// +// Copyright (c) 2002-2014 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_TRANSLATOR_REGENERATE_STRUCT_NAMES_H_ +#define COMPILER_TRANSLATOR_REGENERATE_STRUCT_NAMES_H_ + +#include "compiler/translator/Intermediate.h" +#include "compiler/translator/SymbolTable.h" + +#include + +class RegenerateStructNames : public TIntermTraverser +{ + public: + RegenerateStructNames(const TSymbolTable &symbolTable, + int shaderVersion) + : mSymbolTable(symbolTable), + mShaderVersion(shaderVersion), + mScopeDepth(0) {} + + protected: + virtual void visitSymbol(TIntermSymbol *); + virtual bool visitAggregate(Visit, TIntermAggregate *); + + private: + const TSymbolTable &mSymbolTable; + int mShaderVersion; + + // Indicating the depth of the current scope. + // The global scope is 1. + int mScopeDepth; + + // If a struct's declared globally, push its ID in this set. + std::set mDeclaredGlobalStructs; +}; + +#endif // COMPILER_TRANSLATOR_REGENERATE_STRUCT_NAMES_H_ diff --git a/gfx/angle/src/compiler/translator/RemoveTree.cpp b/gfx/angle/src/compiler/translator/RemoveTree.cpp index e381c3269001..0cf6910aa2a8 100644 --- a/gfx/angle/src/compiler/translator/RemoveTree.cpp +++ b/gfx/angle/src/compiler/translator/RemoveTree.cpp @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include "compiler/translator/RemoveTree.h" // diff --git a/gfx/angle/src/compiler/translator/RenameFunction.h b/gfx/angle/src/compiler/translator/RenameFunction.h index 1f7fb16c4597..d43e6ef7be05 100644 --- a/gfx/angle/src/compiler/translator/RenameFunction.h +++ b/gfx/angle/src/compiler/translator/RenameFunction.h @@ -7,7 +7,7 @@ #ifndef COMPILER_RENAME_FUNCTION #define COMPILER_RENAME_FUNCTION -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" // // Renames a function, including its declaration and any calls to it. diff --git a/gfx/angle/src/compiler/translator/RewriteElseBlocks.cpp b/gfx/angle/src/compiler/translator/RewriteElseBlocks.cpp index 48e87cd57a88..b03beb5c6cfb 100644 --- a/gfx/angle/src/compiler/translator/RewriteElseBlocks.cpp +++ b/gfx/angle/src/compiler/translator/RewriteElseBlocks.cpp @@ -14,6 +14,24 @@ namespace sh { +namespace +{ + +class ElseBlockRewriter : public TIntermTraverser +{ + public: + ElseBlockRewriter(); + + protected: + bool visitAggregate(Visit visit, TIntermAggregate *aggregate); + + private: + int mTemporaryIndex; + const TType *mFunctionType; + + TIntermNode *rewriteSelection(TIntermSelection *selection); +}; + TIntermSymbol *MakeNewTemporary(const TString &name, TBasicType type) { TType variableType(type, EbpHigh, EvqInternal); @@ -36,25 +54,45 @@ TIntermUnary *MakeNewUnary(TOperator op, TIntermTyped *operand) return unary; } +ElseBlockRewriter::ElseBlockRewriter() + : TIntermTraverser(true, false, true, false), + mTemporaryIndex(0), + mFunctionType(NULL) +{} + bool ElseBlockRewriter::visitAggregate(Visit visit, TIntermAggregate *node) { switch (node->getOp()) { case EOpSequence: + if (visit == PostVisit) { - for (size_t statementIndex = 0; statementIndex != node->getSequence().size(); statementIndex++) + for (size_t statementIndex = 0; statementIndex != node->getSequence()->size(); statementIndex++) { - TIntermNode *statement = node->getSequence()[statementIndex]; + TIntermNode *statement = (*node->getSequence())[statementIndex]; TIntermSelection *selection = statement->getAsSelectionNode(); if (selection && selection->getFalseBlock() != NULL) { - node->getSequence()[statementIndex] = rewriteSelection(selection); + // Check for if / else if + TIntermSelection *elseIfBranch = selection->getFalseBlock()->getAsSelectionNode(); + if (elseIfBranch) + { + selection->replaceChildNode(elseIfBranch, rewriteSelection(elseIfBranch)); + delete elseIfBranch; + } + + (*node->getSequence())[statementIndex] = rewriteSelection(selection); delete selection; } } } break; + case EOpFunction: + // Store the current function context (see comment below) + mFunctionType = ((visit == PreVisit) ? &node->getType() : NULL); + break; + default: break; } @@ -63,32 +101,54 @@ bool ElseBlockRewriter::visitAggregate(Visit visit, TIntermAggregate *node) TIntermNode *ElseBlockRewriter::rewriteSelection(TIntermSelection *selection) { - ASSERT(selection->getFalseBlock() != NULL); + ASSERT(selection != NULL); TString temporaryName = "cond_" + str(mTemporaryIndex++); TIntermTyped *typedCondition = selection->getCondition()->getAsTyped(); TType resultType(EbtBool, EbpUndefined); - TIntermSymbol *conditionSymbolA = MakeNewTemporary(temporaryName, EbtBool); - TIntermSymbol *conditionSymbolB = MakeNewTemporary(temporaryName, EbtBool); - TIntermSymbol *conditionSymbolC = MakeNewTemporary(temporaryName, EbtBool); - TIntermBinary *storeCondition = MakeNewBinary(EOpInitialize, conditionSymbolA, + TIntermSymbol *conditionSymbolInit = MakeNewTemporary(temporaryName, EbtBool); + TIntermBinary *storeCondition = MakeNewBinary(EOpInitialize, conditionSymbolInit, typedCondition, resultType); - TIntermUnary *negatedCondition = MakeNewUnary(EOpLogicalNot, conditionSymbolB); - TIntermSelection *falseBlock = new TIntermSelection(negatedCondition, - selection->getFalseBlock(), NULL); - TIntermSelection *newIfElse = new TIntermSelection(conditionSymbolC, - selection->getTrueBlock(), falseBlock); + TIntermNode *negatedElse = NULL; + + TIntermSelection *falseBlock = NULL; + + if (selection->getFalseBlock()) + { + // crbug.com/346463 + // D3D generates error messages claiming a function has no return value, when rewriting + // an if-else clause that returns something non-void in a function. By appending dummy + // returns (that are unreachable) we can silence this compile error. + if (mFunctionType && mFunctionType->getBasicType() != EbtVoid) + { + TString typeString = mFunctionType->getStruct() ? mFunctionType->getStruct()->name() : + mFunctionType->getBasicString(); + TString rawText = "return (" + typeString + ")0"; + negatedElse = new TIntermRaw(*mFunctionType, rawText); + } + + TIntermSymbol *conditionSymbolElse = MakeNewTemporary(temporaryName, EbtBool); + TIntermUnary *negatedCondition = MakeNewUnary(EOpLogicalNot, conditionSymbolElse); + falseBlock = new TIntermSelection(negatedCondition, + selection->getFalseBlock(), negatedElse); + } + + TIntermSymbol *conditionSymbolSel = MakeNewTemporary(temporaryName, EbtBool); + TIntermSelection *newSelection = new TIntermSelection(conditionSymbolSel, + selection->getTrueBlock(), falseBlock); TIntermAggregate *declaration = new TIntermAggregate(EOpDeclaration); - declaration->getSequence().push_back(storeCondition); + declaration->getSequence()->push_back(storeCondition); TIntermAggregate *block = new TIntermAggregate(EOpSequence); - block->getSequence().push_back(declaration); - block->getSequence().push_back(newIfElse); + block->getSequence()->push_back(declaration); + block->getSequence()->push_back(newSelection); return block; } +} + void RewriteElseBlocks(TIntermNode *node) { ElseBlockRewriter rewriter; diff --git a/gfx/angle/src/compiler/translator/RewriteElseBlocks.h b/gfx/angle/src/compiler/translator/RewriteElseBlocks.h index 10221335ce70..d87baea0febf 100644 --- a/gfx/angle/src/compiler/translator/RewriteElseBlocks.h +++ b/gfx/angle/src/compiler/translator/RewriteElseBlocks.h @@ -10,28 +10,11 @@ #ifndef COMPILER_REWRITE_ELSE_BLOCKS_H_ #define COMPILER_REWRITE_ELSE_BLOCKS_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" namespace sh { -class ElseBlockRewriter : public TIntermTraverser -{ - public: - ElseBlockRewriter() - : TIntermTraverser(false, false, true, false) - , mTemporaryIndex(0) - {} - - protected: - bool visitAggregate(Visit visit, TIntermAggregate *aggregate); - - private: - int mTemporaryIndex; - - TIntermNode *rewriteSelection(TIntermSelection *selection); -}; - void RewriteElseBlocks(TIntermNode *node); } diff --git a/gfx/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp b/gfx/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp new file mode 100644 index 000000000000..8857ad59bdee --- /dev/null +++ b/gfx/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp @@ -0,0 +1,277 @@ +// +// Copyright (c) 2002-2014 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/translator/ScalarizeVecAndMatConstructorArgs.h" +#include "compiler/translator/compilerdebug.h" + +#include + +#include "angle_gl.h" +#include "common/angleutils.h" + +namespace +{ + +bool ContainsMatrixNode(const TIntermSequence &sequence) +{ + for (size_t ii = 0; ii < sequence.size(); ++ii) + { + TIntermTyped *node = sequence[ii]->getAsTyped(); + if (node && node->isMatrix()) + return true; + } + return false; +} + +bool ContainsVectorNode(const TIntermSequence &sequence) +{ + for (size_t ii = 0; ii < sequence.size(); ++ii) + { + TIntermTyped *node = sequence[ii]->getAsTyped(); + if (node && node->isVector()) + return true; + } + return false; +} + +TIntermConstantUnion *ConstructIndexNode(int index) +{ + ConstantUnion *u = new ConstantUnion[1]; + u[0].setIConst(index); + + TType type(EbtInt, EbpUndefined, EvqConst, 1); + TIntermConstantUnion *node = new TIntermConstantUnion(u, type); + return node; +} + +TIntermBinary *ConstructVectorIndexBinaryNode(TIntermSymbol *symbolNode, int index) +{ + TIntermBinary *binary = new TIntermBinary(EOpIndexDirect); + binary->setLeft(symbolNode); + TIntermConstantUnion *indexNode = ConstructIndexNode(index); + binary->setRight(indexNode); + return binary; +} + +TIntermBinary *ConstructMatrixIndexBinaryNode( + TIntermSymbol *symbolNode, int colIndex, int rowIndex) +{ + TIntermBinary *colVectorNode = + ConstructVectorIndexBinaryNode(symbolNode, colIndex); + + TIntermBinary *binary = new TIntermBinary(EOpIndexDirect); + binary->setLeft(colVectorNode); + TIntermConstantUnion *rowIndexNode = ConstructIndexNode(rowIndex); + binary->setRight(rowIndexNode); + return binary; +} + +} // namespace anonymous + +bool ScalarizeVecAndMatConstructorArgs::visitAggregate(Visit visit, TIntermAggregate *node) +{ + if (visit == PreVisit) + { + switch (node->getOp()) + { + case EOpSequence: + mSequenceStack.push_back(TIntermSequence()); + { + for (TIntermSequence::const_iterator iter = node->getSequence()->begin(); + iter != node->getSequence()->end(); ++iter) + { + TIntermNode *child = *iter; + ASSERT(child != NULL); + child->traverse(this); + mSequenceStack.back().push_back(child); + } + } + if (mSequenceStack.back().size() > node->getSequence()->size()) + { + node->getSequence()->clear(); + *(node->getSequence()) = mSequenceStack.back(); + } + mSequenceStack.pop_back(); + return false; + case EOpConstructVec2: + case EOpConstructVec3: + case EOpConstructVec4: + case EOpConstructBVec2: + case EOpConstructBVec3: + case EOpConstructBVec4: + case EOpConstructIVec2: + case EOpConstructIVec3: + case EOpConstructIVec4: + if (ContainsMatrixNode(*(node->getSequence()))) + scalarizeArgs(node, false, true); + break; + case EOpConstructMat2: + case EOpConstructMat3: + case EOpConstructMat4: + if (ContainsVectorNode(*(node->getSequence()))) + scalarizeArgs(node, true, false); + break; + default: + break; + } + } + return true; +} + +void ScalarizeVecAndMatConstructorArgs::scalarizeArgs( + TIntermAggregate *aggregate, bool scalarizeVector, bool scalarizeMatrix) +{ + ASSERT(aggregate); + int size = 0; + switch (aggregate->getOp()) + { + case EOpConstructVec2: + case EOpConstructBVec2: + case EOpConstructIVec2: + size = 2; + break; + case EOpConstructVec3: + case EOpConstructBVec3: + case EOpConstructIVec3: + size = 3; + break; + case EOpConstructVec4: + case EOpConstructBVec4: + case EOpConstructIVec4: + case EOpConstructMat2: + size = 4; + break; + case EOpConstructMat3: + size = 9; + break; + case EOpConstructMat4: + size = 16; + break; + default: + break; + } + TIntermSequence *sequence = aggregate->getSequence(); + TIntermSequence original(*sequence); + sequence->clear(); + for (size_t ii = 0; ii < original.size(); ++ii) + { + ASSERT(size > 0); + TIntermTyped *node = original[ii]->getAsTyped(); + ASSERT(node); + TString varName = createTempVariable(node); + if (node->isScalar()) + { + TIntermSymbol *symbolNode = + new TIntermSymbol(-1, varName, node->getType()); + sequence->push_back(symbolNode); + size--; + } + else if (node->isVector()) + { + if (scalarizeVector) + { + int repeat = std::min(size, node->getNominalSize()); + size -= repeat; + for (int index = 0; index < repeat; ++index) + { + TIntermSymbol *symbolNode = + new TIntermSymbol(-1, varName, node->getType()); + TIntermBinary *newNode = ConstructVectorIndexBinaryNode( + symbolNode, index); + sequence->push_back(newNode); + } + } + else + { + TIntermSymbol *symbolNode = + new TIntermSymbol(-1, varName, node->getType()); + sequence->push_back(symbolNode); + size -= node->getNominalSize(); + } + } + else + { + ASSERT(node->isMatrix()); + if (scalarizeMatrix) + { + int colIndex = 0, rowIndex = 0; + int repeat = std::min(size, node->getCols() * node->getRows()); + size -= repeat; + while (repeat > 0) + { + TIntermSymbol *symbolNode = + new TIntermSymbol(-1, varName, node->getType()); + TIntermBinary *newNode = ConstructMatrixIndexBinaryNode( + symbolNode, colIndex, rowIndex); + sequence->push_back(newNode); + rowIndex++; + if (rowIndex >= node->getRows()) + { + rowIndex = 0; + colIndex++; + } + repeat--; + } + } + else + { + TIntermSymbol *symbolNode = + new TIntermSymbol(-1, varName, node->getType()); + sequence->push_back(symbolNode); + size -= node->getCols() * node->getRows(); + } + } + } +} + +TString ScalarizeVecAndMatConstructorArgs::createTempVariable(TIntermTyped *original) +{ + TString tempVarName = "_webgl_tmp_"; + if (original->isScalar()) + { + tempVarName += "scalar_"; + } + else if (original->isVector()) + { + tempVarName += "vec_"; + } + else + { + ASSERT(original->isMatrix()); + tempVarName += "mat_"; + } + tempVarName += Str(mTempVarCount).c_str(); + mTempVarCount++; + + ASSERT(original); + TType type = original->getType(); + type.setQualifier(EvqTemporary); + + if (mShaderType == GL_FRAGMENT_SHADER && + type.getBasicType() == EbtFloat && + type.getPrecision() == EbpUndefined) + { + // We use the highest available precision for the temporary variable + // to avoid computing the actual precision using the rules defined + // in GLSL ES 1.0 Section 4.5.2. + type.setPrecision(mFragmentPrecisionHigh ? EbpHigh : EbpMedium); + } + + TIntermBinary *init = new TIntermBinary(EOpInitialize); + TIntermSymbol *symbolNode = new TIntermSymbol(-1, tempVarName, type); + init->setLeft(symbolNode); + init->setRight(original); + init->setType(type); + + TIntermAggregate *decl = new TIntermAggregate(EOpDeclaration); + decl->getSequence()->push_back(init); + + ASSERT(mSequenceStack.size() > 0); + TIntermSequence &sequence = mSequenceStack.back(); + sequence.push_back(decl); + + return tempVarName; +} diff --git a/gfx/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h b/gfx/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h new file mode 100644 index 000000000000..7c6d09c1bb94 --- /dev/null +++ b/gfx/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h @@ -0,0 +1,47 @@ +// +// Copyright (c) 2002-2014 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_TRANSLATOR_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS_H_ +#define COMPILER_TRANSLATOR_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS_H_ + +#include "compiler/translator/IntermNode.h" + +class ScalarizeVecAndMatConstructorArgs : public TIntermTraverser +{ + public: + ScalarizeVecAndMatConstructorArgs(sh::GLenum shaderType, + bool fragmentPrecisionHigh) + : mTempVarCount(0), + mShaderType(shaderType), + mFragmentPrecisionHigh(fragmentPrecisionHigh) {} + + protected: + virtual bool visitAggregate(Visit visit, TIntermAggregate *node); + + private: + void scalarizeArgs(TIntermAggregate *aggregate, + bool scalarizeVector, bool scalarizeMatrix); + + // If we have the following code: + // mat4 m(0); + // vec4 v(1, m); + // We will rewrite to: + // mat4 m(0); + // mat4 _webgl_tmp_mat_0 = m; + // vec4 v(1, _webgl_tmp_mat_0[0][0], _webgl_tmp_mat_0[0][1], _webgl_tmp_mat_0[0][2]); + // This function is to create nodes for "mat4 _webgl_tmp_mat_0 = m;" and insert it to + // the code sequence. + // Return the temporary variable name. + TString createTempVariable(TIntermTyped *original); + + std::vector mSequenceStack; + int mTempVarCount; + + sh::GLenum mShaderType; + bool mFragmentPrecisionHigh; +}; + +#endif // COMPILER_TRANSLATOR_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS_H_ diff --git a/gfx/angle/src/compiler/translator/SearchSymbol.h b/gfx/angle/src/compiler/translator/SearchSymbol.h index 8ddd3cb1ac3a..029ac30b9af8 100644 --- a/gfx/angle/src/compiler/translator/SearchSymbol.h +++ b/gfx/angle/src/compiler/translator/SearchSymbol.h @@ -9,7 +9,7 @@ #ifndef COMPILER_SEARCHSYMBOL_H_ #define COMPILER_SEARCHSYMBOL_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include "compiler/translator/ParseContext.h" namespace sh diff --git a/gfx/angle/src/compiler/translator/ShaderLang.cpp b/gfx/angle/src/compiler/translator/ShaderLang.cpp index bf0587a34ce2..20ce71605cea 100644 --- a/gfx/angle/src/compiler/translator/ShaderLang.cpp +++ b/gfx/angle/src/compiler/translator/ShaderLang.cpp @@ -11,20 +11,33 @@ #include "GLSLANG/ShaderLang.h" +#include "compiler/translator/Compiler.h" #include "compiler/translator/InitializeDll.h" #include "compiler/translator/length_limits.h" -#include "compiler/translator/ShHandle.h" #include "compiler/translator/TranslatorHLSL.h" #include "compiler/translator/VariablePacker.h" +#include "angle_gl.h" -static bool isInitialized = false; +namespace +{ + +enum ShaderVariableType +{ + SHADERVAR_UNIFORM, + SHADERVAR_VARYING, + SHADERVAR_ATTRIBUTE, + SHADERVAR_OUTPUTVARIABLE, + SHADERVAR_INTERFACEBLOCK +}; + +bool isInitialized = false; // // This is the platform independent interface between an OGL driver // and the shading language compiler. // -static bool checkVariableMaxLengths(const ShHandle handle, +static bool CheckVariableMaxLengths(const ShHandle handle, size_t expectedValue) { size_t activeUniformLimit = 0; @@ -38,13 +51,107 @@ static bool checkVariableMaxLengths(const ShHandle handle, expectedValue == varyingLimit); } -static bool checkMappedNameMaxLength(const ShHandle handle, size_t expectedValue) +bool CheckMappedNameMaxLength(const ShHandle handle, size_t expectedValue) { size_t mappedNameMaxLength = 0; ShGetInfo(handle, SH_MAPPED_NAME_MAX_LENGTH, &mappedNameMaxLength); return (expectedValue == mappedNameMaxLength); } +template +const sh::ShaderVariable *ReturnVariable(const std::vector &infoList, int index) +{ + if (index < 0 || static_cast(index) >= infoList.size()) + { + return NULL; + } + + return &infoList[index]; +} + +const sh::ShaderVariable *GetVariable(const TCompiler *compiler, ShShaderInfo varType, int index) +{ + switch (varType) + { + case SH_ACTIVE_ATTRIBUTES: + return ReturnVariable(compiler->getAttributes(), index); + case SH_ACTIVE_UNIFORMS: + return ReturnVariable(compiler->getExpandedUniforms(), index); + case SH_VARYINGS: + return ReturnVariable(compiler->getExpandedVaryings(), index); + default: + UNREACHABLE(); + return NULL; + } +} + +ShPrecisionType ConvertPrecision(sh::GLenum precision) +{ + switch (precision) + { + case GL_HIGH_FLOAT: + case GL_HIGH_INT: + return SH_PRECISION_HIGHP; + case GL_MEDIUM_FLOAT: + case GL_MEDIUM_INT: + return SH_PRECISION_MEDIUMP; + case GL_LOW_FLOAT: + case GL_LOW_INT: + return SH_PRECISION_LOWP; + default: + return SH_PRECISION_UNDEFINED; + } +} + +template +const std::vector *GetVariableList(const TCompiler *compiler, ShaderVariableType variableType); + +template <> +const std::vector *GetVariableList(const TCompiler *compiler, ShaderVariableType) +{ + return &compiler->getUniforms(); +} + +template <> +const std::vector *GetVariableList(const TCompiler *compiler, ShaderVariableType) +{ + return &compiler->getVaryings(); +} + +template <> +const std::vector *GetVariableList(const TCompiler *compiler, ShaderVariableType variableType) +{ + return (variableType == SHADERVAR_ATTRIBUTE ? + &compiler->getAttributes() : + &compiler->getOutputVariables()); +} + +template <> +const std::vector *GetVariableList(const TCompiler *compiler, ShaderVariableType) +{ + return &compiler->getInterfaceBlocks(); +} + +template +const std::vector *GetShaderVariables(const ShHandle handle, ShaderVariableType variableType) +{ + if (!handle) + { + return NULL; + } + + TShHandleBase* base = static_cast(handle); + TCompiler* compiler = base->getAsCompiler(); + if (!compiler) + { + return NULL; + } + + return GetVariableList(compiler, variableType); +} + +} + // // Driver must call this first, once, before doing any other compiler operations. // Subsequent calls to this function are no-op. @@ -115,7 +222,7 @@ void ShInitBuiltInResources(ShBuiltInResources* resources) // // Driver calls these to create and destroy compiler objects. // -ShHandle ShConstructCompiler(ShShaderType type, ShShaderSpec spec, +ShHandle ShConstructCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output, const ShBuiltInResources* resources) { @@ -204,19 +311,19 @@ void ShGetInfo(const ShHandle handle, ShShaderInfo pname, size_t* params) *params = compiler->getInfoSink().obj.size() + 1; break; case SH_ACTIVE_UNIFORMS: - *params = compiler->getUniforms().size(); + *params = compiler->getExpandedUniforms().size(); break; case SH_ACTIVE_UNIFORM_MAX_LENGTH: *params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec()); break; case SH_ACTIVE_ATTRIBUTES: - *params = compiler->getAttribs().size(); + *params = compiler->getAttributes().size(); break; case SH_ACTIVE_ATTRIBUTE_MAX_LENGTH: *params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec()); break; case SH_VARYINGS: - *params = compiler->getVaryings().size(); + *params = compiler->getExpandedVaryings().size(); break; case SH_VARYING_MAX_LENGTH: *params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec()); @@ -293,7 +400,7 @@ void ShGetVariableInfo(const ShHandle handle, int index, size_t* length, int* size, - ShDataType* type, + sh::GLenum* type, ShPrecisionType* precision, int* staticUse, char* name, @@ -310,47 +417,32 @@ void ShGetVariableInfo(const ShHandle handle, if (compiler == 0) return; - const TVariableInfoList& varList = - varType == SH_ACTIVE_ATTRIBUTES ? compiler->getAttribs() : - (varType == SH_ACTIVE_UNIFORMS ? compiler->getUniforms() : - compiler->getVaryings()); - if (index < 0 || index >= static_cast(varList.size())) + const sh::ShaderVariable *varInfo = GetVariable(compiler, varType, index); + if (!varInfo) + { return; - - const TVariableInfo& varInfo = varList[index]; - if (length) *length = varInfo.name.size(); - *size = varInfo.size; - *type = varInfo.type; - switch (varInfo.precision) { - case EbpLow: - *precision = SH_PRECISION_LOWP; - break; - case EbpMedium: - *precision = SH_PRECISION_MEDIUMP; - break; - case EbpHigh: - *precision = SH_PRECISION_HIGHP; - break; - default: - // Some types does not support precision, for example, boolean. - *precision = SH_PRECISION_UNDEFINED; - break; } - *staticUse = varInfo.staticUse ? 1 : 0; + + if (length) *length = varInfo->name.size(); + *size = varInfo->elementCount(); + *type = varInfo->type; + *precision = ConvertPrecision(varInfo->precision); + *staticUse = varInfo->staticUse ? 1 : 0; // This size must match that queried by // SH_ACTIVE_UNIFORM_MAX_LENGTH, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, SH_VARYING_MAX_LENGTH // in ShGetInfo, below. size_t variableLength = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec()); - ASSERT(checkVariableMaxLengths(handle, variableLength)); - strncpy(name, varInfo.name.c_str(), variableLength); + ASSERT(CheckVariableMaxLengths(handle, variableLength)); + strncpy(name, varInfo->name.c_str(), variableLength); name[variableLength - 1] = 0; - if (mappedName) { + if (mappedName) + { // This size must match that queried by // SH_MAPPED_NAME_MAX_LENGTH in ShGetInfo, below. size_t maxMappedNameLength = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec()); - ASSERT(checkMappedNameMaxLength(handle, maxMappedNameLength)); - strncpy(mappedName, varInfo.mappedName.c_str(), maxMappedNameLength); + ASSERT(CheckMappedNameMaxLength(handle, maxMappedNameLength)); + strncpy(mappedName, varInfo->mappedName.c_str(), maxMappedNameLength); mappedName[maxMappedNameLength - 1] = 0; } } @@ -398,34 +490,29 @@ void ShGetNameHashingEntry(const ShHandle handle, hashedName[len - 1] = '\0'; } -void ShGetInfoPointer(const ShHandle handle, ShShaderInfo pname, void** params) +const std::vector *ShGetUniforms(const ShHandle handle) { - if (!handle || !params) - return; + return GetShaderVariables(handle, SHADERVAR_UNIFORM); +} - TShHandleBase* base = static_cast(handle); - TranslatorHLSL* translator = base->getAsTranslatorHLSL(); - if (!translator) return; +const std::vector *ShGetVaryings(const ShHandle handle) +{ + return GetShaderVariables(handle, SHADERVAR_VARYING); +} - switch(pname) - { - case SH_ACTIVE_UNIFORMS_ARRAY: - *params = (void*)&translator->getUniforms(); - break; - case SH_ACTIVE_INTERFACE_BLOCKS_ARRAY: - *params = (void*)&translator->getInterfaceBlocks(); - break; - case SH_ACTIVE_OUTPUT_VARIABLES_ARRAY: - *params = (void*)&translator->getOutputVariables(); - break; - case SH_ACTIVE_ATTRIBUTES_ARRAY: - *params = (void*)&translator->getAttributes(); - break; - case SH_ACTIVE_VARYINGS_ARRAY: - *params = (void*)&translator->getVaryings(); - break; - default: UNREACHABLE(); - } +const std::vector *ShGetAttributes(const ShHandle handle) +{ + return GetShaderVariables(handle, SHADERVAR_ATTRIBUTE); +} + +const std::vector *ShGetOutputVariables(const ShHandle handle) +{ + return GetShaderVariables(handle, SHADERVAR_OUTPUTVARIABLE); +} + +const std::vector *ShGetInterfaceBlocks(const ShHandle handle) +{ + return GetShaderVariables(handle, SHADERVAR_INTERFACEBLOCK); } int ShCheckVariablesWithinPackingLimits( @@ -434,12 +521,62 @@ int ShCheckVariablesWithinPackingLimits( if (varInfoArraySize == 0) return 1; ASSERT(varInfoArray); - TVariableInfoList variables; + std::vector variables; for (size_t ii = 0; ii < varInfoArraySize; ++ii) { - TVariableInfo var(varInfoArray[ii].type, varInfoArray[ii].size); + sh::ShaderVariable var(varInfoArray[ii].type, varInfoArray[ii].size); variables.push_back(var); } VariablePacker packer; return packer.CheckVariablesWithinPackingLimits(maxVectors, variables) ? 1 : 0; } + +bool ShGetInterfaceBlockRegister(const ShHandle handle, + const char *interfaceBlockName, + unsigned int *indexOut) +{ + if (!handle || !interfaceBlockName || !indexOut) + { + return false; + } + + TShHandleBase* base = static_cast(handle); + TranslatorHLSL* translator = base->getAsTranslatorHLSL(); + if (!translator) + { + return false; + } + + if (!translator->hasInterfaceBlock(interfaceBlockName)) + { + return false; + } + + *indexOut = translator->getInterfaceBlockRegister(interfaceBlockName); + return true; +} + +bool ShGetUniformRegister(const ShHandle handle, + const char *uniformName, + unsigned int *indexOut) +{ + if (!handle || !uniformName || !indexOut) + { + return false; + } + + TShHandleBase* base = static_cast(handle); + TranslatorHLSL* translator = base->getAsTranslatorHLSL(); + if (!translator) + { + return false; + } + + if (!translator->hasUniform(uniformName)) + { + return false; + } + + *indexOut = translator->getUniformRegister(uniformName); + return true; +} diff --git a/gfx/angle/src/compiler/translator/ShaderVars.cpp b/gfx/angle/src/compiler/translator/ShaderVars.cpp new file mode 100644 index 000000000000..822c558c9bd0 --- /dev/null +++ b/gfx/angle/src/compiler/translator/ShaderVars.cpp @@ -0,0 +1,166 @@ +// +// Copyright (c) 2014 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. +// +// ShaderVars.cpp: +// Methods for GL variable types (varyings, uniforms, etc) +// + +#include + +namespace sh +{ + +ShaderVariable::ShaderVariable() + : type(0), + precision(0), + arraySize(0), + staticUse(false) +{} + +ShaderVariable::ShaderVariable(GLenum typeIn, unsigned int arraySizeIn) + : type(typeIn), + precision(0), + arraySize(arraySizeIn), + staticUse(false) +{} + +ShaderVariable::~ShaderVariable() +{} + +ShaderVariable::ShaderVariable(const ShaderVariable &other) + : type(other.type), + precision(other.precision), + name(other.name), + mappedName(other.mappedName), + arraySize(other.arraySize), + staticUse(other.staticUse), + fields(other.fields), + structName(other.structName) +{} + +ShaderVariable &ShaderVariable::operator=(const ShaderVariable &other) +{ + type = other.type; + precision = other.precision; + name = other.name; + mappedName = other.mappedName; + arraySize = other.arraySize; + staticUse = other.staticUse; + fields = other.fields; + structName = other.structName; + return *this; +} + +Uniform::Uniform() +{} + +Uniform::~Uniform() +{} + +Uniform::Uniform(const Uniform &other) + : ShaderVariable(other) +{} + +Uniform &Uniform::operator=(const Uniform &other) +{ + ShaderVariable::operator=(other); + return *this; +} + +Attribute::Attribute() + : location(-1) +{} + +Attribute::~Attribute() +{} + +Attribute::Attribute(const Attribute &other) + : ShaderVariable(other), + location(other.location) +{} + +Attribute &Attribute::operator=(const Attribute &other) +{ + ShaderVariable::operator=(other); + location = other.location; + return *this; +} + +InterfaceBlockField::InterfaceBlockField() + : isRowMajorLayout(false) +{} + +InterfaceBlockField::~InterfaceBlockField() +{} + +InterfaceBlockField::InterfaceBlockField(const InterfaceBlockField &other) + : ShaderVariable(other), + isRowMajorLayout(other.isRowMajorLayout) +{} + +InterfaceBlockField &InterfaceBlockField::operator=(const InterfaceBlockField &other) +{ + ShaderVariable::operator=(other); + isRowMajorLayout = other.isRowMajorLayout; + return *this; +} + +Varying::Varying() + : interpolation(INTERPOLATION_SMOOTH), + isInvariant(false) +{} + +Varying::~Varying() +{} + +Varying::Varying(const Varying &other) + : ShaderVariable(other), + interpolation(other.interpolation), + isInvariant(other.isInvariant) +{} + +Varying &Varying::operator=(const Varying &other) +{ + ShaderVariable::operator=(other); + interpolation = other.interpolation; + isInvariant = other.isInvariant; + return *this; +} + +InterfaceBlock::InterfaceBlock() + : arraySize(0), + layout(BLOCKLAYOUT_PACKED), + isRowMajorLayout(false), + staticUse(false) +{} + +InterfaceBlock::~InterfaceBlock() +{} + +InterfaceBlock::InterfaceBlock(const InterfaceBlock &other) + : name(other.name), + mappedName(other.mappedName), + instanceName(other.instanceName), + arraySize(other.arraySize), + layout(other.layout), + isRowMajorLayout(other.isRowMajorLayout), + staticUse(other.staticUse), + fields(other.fields) +{} + +InterfaceBlock &InterfaceBlock::operator=(const InterfaceBlock &other) +{ + name = other.name; + mappedName = other.mappedName; + instanceName = other.instanceName; + arraySize = other.arraySize; + layout = other.layout; + isRowMajorLayout = other.isRowMajorLayout; + staticUse = other.staticUse; + fields = other.fields; + return *this; +} + +} diff --git a/gfx/angle/src/compiler/translator/StructureHLSL.cpp b/gfx/angle/src/compiler/translator/StructureHLSL.cpp new file mode 100644 index 000000000000..48929affe636 --- /dev/null +++ b/gfx/angle/src/compiler/translator/StructureHLSL.cpp @@ -0,0 +1,490 @@ +// +// Copyright (c) 2014 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. +// +// StructureHLSL.cpp: +// Definitions of methods for HLSL translation of GLSL structures. +// + +#include "compiler/translator/StructureHLSL.h" +#include "common/utilities.h" +#include "compiler/translator/OutputHLSL.h" +#include "compiler/translator/Types.h" +#include "compiler/translator/util.h" +#include "compiler/translator/UtilsHLSL.h" + +namespace sh +{ + +Std140PaddingHelper::Std140PaddingHelper(const std::map &structElementIndexes, + unsigned *uniqueCounter) + : mPaddingCounter(uniqueCounter), + mElementIndex(0), + mStructElementIndexes(structElementIndexes) +{} + +TString Std140PaddingHelper::next() +{ + unsigned value = (*mPaddingCounter)++; + return str(value); +} + +int Std140PaddingHelper::prePadding(const TType &type) +{ + if (type.getBasicType() == EbtStruct || type.isMatrix() || type.isArray()) + { + // no padding needed, HLSL will align the field to a new register + mElementIndex = 0; + return 0; + } + + const GLenum glType = GLVariableType(type); + const int numComponents = gl::VariableComponentCount(glType); + + if (numComponents >= 4) + { + // no padding needed, HLSL will align the field to a new register + mElementIndex = 0; + return 0; + } + + if (mElementIndex + numComponents > 4) + { + // no padding needed, HLSL will align the field to a new register + mElementIndex = numComponents; + return 0; + } + + const int alignment = numComponents == 3 ? 4 : numComponents; + const int paddingOffset = (mElementIndex % alignment); + const int paddingCount = (paddingOffset != 0 ? (alignment - paddingOffset) : 0); + + mElementIndex += paddingCount; + mElementIndex += numComponents; + mElementIndex %= 4; + + return paddingCount; +} + +TString Std140PaddingHelper::prePaddingString(const TType &type) +{ + int paddingCount = prePadding(type); + + TString padding; + + for (int paddingIndex = 0; paddingIndex < paddingCount; paddingIndex++) + { + padding += " float pad_" + next() + ";\n"; + } + + return padding; +} + +TString Std140PaddingHelper::postPaddingString(const TType &type, bool useHLSLRowMajorPacking) +{ + if (!type.isMatrix() && !type.isArray() && type.getBasicType() != EbtStruct) + { + return ""; + } + + int numComponents = 0; + TStructure *structure = type.getStruct(); + + if (type.isMatrix()) + { + // This method can also be called from structureString, which does not use layout qualifiers. + // Thus, use the method parameter for determining the matrix packing. + // + // Note HLSL row major packing corresponds to GL API column-major, and vice-versa, since we + // wish to always transpose GL matrices to play well with HLSL's matrix array indexing. + // + const bool isRowMajorMatrix = !useHLSLRowMajorPacking; + const GLenum glType = GLVariableType(type); + numComponents = gl::MatrixComponentCount(glType, isRowMajorMatrix); + } + else if (structure) + { + const TString &structName = QualifiedStructNameString(*structure, + useHLSLRowMajorPacking, true); + numComponents = mStructElementIndexes.find(structName)->second; + + if (numComponents == 0) + { + return ""; + } + } + else + { + const GLenum glType = GLVariableType(type); + numComponents = gl::VariableComponentCount(glType); + } + + TString padding; + for (int paddingOffset = numComponents; paddingOffset < 4; paddingOffset++) + { + padding += " float pad_" + next() + ";\n"; + } + return padding; +} + +StructureHLSL::StructureHLSL() + : mUniquePaddingCounter(0) +{} + +Std140PaddingHelper StructureHLSL::getPaddingHelper() +{ + return Std140PaddingHelper(mStd140StructElementIndexes, &mUniquePaddingCounter); +} + +TString StructureHLSL::defineQualified(const TStructure &structure, bool useHLSLRowMajorPacking, bool useStd140Packing) +{ + if (useStd140Packing) + { + Std140PaddingHelper padHelper = getPaddingHelper(); + return define(structure, useHLSLRowMajorPacking, useStd140Packing, &padHelper); + } + else + { + return define(structure, useHLSLRowMajorPacking, useStd140Packing, NULL); + } +} + +TString StructureHLSL::defineNameless(const TStructure &structure) +{ + return define(structure, false, false, NULL); +} + +TString StructureHLSL::define(const TStructure &structure, bool useHLSLRowMajorPacking, + bool useStd140Packing, Std140PaddingHelper *padHelper) +{ + const TFieldList &fields = structure.fields(); + const bool isNameless = (structure.name() == ""); + const TString &structName = QualifiedStructNameString(structure, useHLSLRowMajorPacking, + useStd140Packing); + const TString declareString = (isNameless ? "struct" : "struct " + structName); + + TString string; + string += declareString + "\n" + "{\n"; + + for (unsigned int i = 0; i < fields.size(); i++) + { + const TField &field = *fields[i]; + const TType &fieldType = *field.type(); + const TStructure *fieldStruct = fieldType.getStruct(); + const TString &fieldTypeString = fieldStruct ? + QualifiedStructNameString(*fieldStruct, useHLSLRowMajorPacking, + useStd140Packing) : + TypeString(fieldType); + + if (padHelper) + { + string += padHelper->prePaddingString(fieldType); + } + + string += " " + fieldTypeString + " " + DecorateField(field.name(), structure) + ArrayString(fieldType) + ";\n"; + + if (padHelper) + { + string += padHelper->postPaddingString(fieldType, useHLSLRowMajorPacking); + } + } + + // Nameless structs do not finish with a semicolon and newline, to leave room for an instance variable + string += (isNameless ? "} " : "};\n"); + + return string; +} + +void StructureHLSL::addConstructor(const TType &type, const TString &name, const TIntermSequence *parameters) +{ + if (name == "") + { + return; // Nameless structures don't have constructors + } + + if (type.getStruct() && mStructNames.find(name) != mStructNames.end()) + { + return; // Already added + } + + TType ctorType = type; + ctorType.clearArrayness(); + ctorType.setPrecision(EbpHigh); + ctorType.setQualifier(EvqTemporary); + + typedef std::vector ParameterArray; + ParameterArray ctorParameters; + + const TStructure* structure = type.getStruct(); + if (structure) + { + mStructNames.insert(name); + + // Add element index + storeStd140ElementIndex(*structure, false); + storeStd140ElementIndex(*structure, true); + + const TString &structString = defineQualified(*structure, false, false); + + if (std::find(mStructDeclarations.begin(), mStructDeclarations.end(), structString) == mStructDeclarations.end()) + { + // Add row-major packed struct for interface blocks + TString rowMajorString = "#pragma pack_matrix(row_major)\n" + + defineQualified(*structure, true, false) + + "#pragma pack_matrix(column_major)\n"; + + TString std140String = defineQualified(*structure, false, true); + TString std140RowMajorString = "#pragma pack_matrix(row_major)\n" + + defineQualified(*structure, true, true) + + "#pragma pack_matrix(column_major)\n"; + + mStructDeclarations.push_back(structString); + mStructDeclarations.push_back(rowMajorString); + mStructDeclarations.push_back(std140String); + mStructDeclarations.push_back(std140RowMajorString); + } + + const TFieldList &fields = structure->fields(); + for (unsigned int i = 0; i < fields.size(); i++) + { + ctorParameters.push_back(*fields[i]->type()); + } + } + else if (parameters) + { + for (TIntermSequence::const_iterator parameter = parameters->begin(); parameter != parameters->end(); parameter++) + { + ctorParameters.push_back((*parameter)->getAsTyped()->getType()); + } + } + else UNREACHABLE(); + + TString constructor; + + if (ctorType.getStruct()) + { + constructor += name + " " + name + "_ctor("; + } + else // Built-in type + { + constructor += TypeString(ctorType) + " " + name + "("; + } + + for (unsigned int parameter = 0; parameter < ctorParameters.size(); parameter++) + { + const TType &type = ctorParameters[parameter]; + + constructor += TypeString(type) + " x" + str(parameter) + ArrayString(type); + + if (parameter < ctorParameters.size() - 1) + { + constructor += ", "; + } + } + + constructor += ")\n" + "{\n"; + + if (ctorType.getStruct()) + { + constructor += " " + name + " structure = {"; + } + else + { + constructor += " return " + TypeString(ctorType) + "("; + } + + if (ctorType.isMatrix() && ctorParameters.size() == 1) + { + int rows = ctorType.getRows(); + int cols = ctorType.getCols(); + const TType ¶meter = ctorParameters[0]; + + if (parameter.isScalar()) + { + for (int col = 0; col < cols; col++) + { + for (int row = 0; row < rows; row++) + { + constructor += TString((row == col) ? "x0" : "0.0"); + + if (row < rows - 1 || col < cols - 1) + { + constructor += ", "; + } + } + } + } + else if (parameter.isMatrix()) + { + for (int col = 0; col < cols; col++) + { + for (int row = 0; row < rows; row++) + { + if (row < parameter.getRows() && col < parameter.getCols()) + { + constructor += TString("x0") + "[" + str(col) + "][" + str(row) + "]"; + } + else + { + constructor += TString((row == col) ? "1.0" : "0.0"); + } + + if (row < rows - 1 || col < cols - 1) + { + constructor += ", "; + } + } + } + } + else + { + ASSERT(rows == 2 && cols == 2 && parameter.isVector() && parameter.getNominalSize() == 4); + + constructor += "x0"; + } + } + else + { + size_t remainingComponents = ctorType.getObjectSize(); + size_t parameterIndex = 0; + + while (remainingComponents > 0) + { + const TType ¶meter = ctorParameters[parameterIndex]; + const size_t parameterSize = parameter.getObjectSize(); + bool moreParameters = parameterIndex + 1 < ctorParameters.size(); + + constructor += "x" + str(parameterIndex); + + if (ctorType.getStruct()) + { + ASSERT(remainingComponents == parameterSize || moreParameters); + ASSERT(parameterSize <= remainingComponents); + + remainingComponents -= parameterSize; + } + else if (parameter.isScalar()) + { + remainingComponents -= parameter.getObjectSize(); + } + else if (parameter.isVector()) + { + if (remainingComponents == parameterSize || moreParameters) + { + ASSERT(parameterSize <= remainingComponents); + remainingComponents -= parameterSize; + } + else if (remainingComponents < static_cast(parameter.getNominalSize())) + { + switch (remainingComponents) + { + case 1: constructor += ".x"; break; + case 2: constructor += ".xy"; break; + case 3: constructor += ".xyz"; break; + case 4: constructor += ".xyzw"; break; + default: UNREACHABLE(); + } + + remainingComponents = 0; + } + else UNREACHABLE(); + } + else if (parameter.isMatrix()) + { + int column = 0; + while (remainingComponents > 0 && column < parameter.getCols()) + { + constructor += "[" + str(column) + "]"; + + if (remainingComponents < static_cast(parameter.getRows())) + { + switch (remainingComponents) + { + case 1: constructor += ".x"; break; + case 2: constructor += ".xy"; break; + case 3: constructor += ".xyz"; break; + default: UNREACHABLE(); + } + + remainingComponents = 0; + } + else + { + remainingComponents -= parameter.getRows(); + + if (remainingComponents > 0) + { + constructor += ", x" + str(parameterIndex); + } + } + + column++; + } + } + else UNREACHABLE(); + + if (moreParameters) + { + parameterIndex++; + } + + if (remainingComponents) + { + constructor += ", "; + } + } + } + + if (ctorType.getStruct()) + { + constructor += "};\n" + " return structure;\n" + "}\n"; + } + else + { + constructor += ");\n" + "}\n"; + } + + mConstructors.insert(constructor); +} + +std::string StructureHLSL::structsHeader() const +{ + TInfoSinkBase out; + + for (size_t structIndex = 0; structIndex < mStructDeclarations.size(); structIndex++) + { + out << mStructDeclarations[structIndex]; + } + + for (Constructors::const_iterator constructor = mConstructors.begin(); + constructor != mConstructors.end(); + constructor++) + { + out << *constructor; + } + + return out.str(); +} + +void StructureHLSL::storeStd140ElementIndex(const TStructure &structure, bool useHLSLRowMajorPacking) +{ + Std140PaddingHelper padHelper = getPaddingHelper(); + const TFieldList &fields = structure.fields(); + + for (unsigned int i = 0; i < fields.size(); i++) + { + padHelper.prePadding(*fields[i]->type()); + } + + // Add remaining element index to the global map, for use with nested structs in standard layouts + const TString &structName = QualifiedStructNameString(structure, useHLSLRowMajorPacking, true); + mStd140StructElementIndexes[structName] = padHelper.elementIndex(); +} + +} diff --git a/gfx/angle/src/compiler/translator/StructureHLSL.h b/gfx/angle/src/compiler/translator/StructureHLSL.h new file mode 100644 index 000000000000..ed002fef30a6 --- /dev/null +++ b/gfx/angle/src/compiler/translator/StructureHLSL.h @@ -0,0 +1,79 @@ +// +// Copyright (c) 2014 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. +// +// StructureHLSL.h: +// Interfaces of methods for HLSL translation of GLSL structures. +// + +#ifndef TRANSLATOR_STRUCTUREHLSL_H_ +#define TRANSLATOR_STRUCTUREHLSL_H_ + +#include "compiler/translator/Common.h" +#include "compiler/translator/IntermNode.h" + +#include + +class TInfoSinkBase; +class TScopeBracket; + +namespace sh +{ + +// This helper class assists structure and interface block definitions in determining +// how to pack std140 structs within HLSL's packing rules. +class Std140PaddingHelper +{ + public: + explicit Std140PaddingHelper(const std::map &structElementIndexes, + unsigned *uniqueCounter); + + int elementIndex() const { return mElementIndex; } + int prePadding(const TType &type); + TString prePaddingString(const TType &type); + TString postPaddingString(const TType &type, bool useHLSLRowMajorPacking); + + private: + TString next(); + + unsigned *mPaddingCounter; + int mElementIndex; + const std::map &mStructElementIndexes; +}; + +class StructureHLSL +{ + public: + StructureHLSL(); + + void addConstructor(const TType &type, const TString &name, const TIntermSequence *parameters); + std::string structsHeader() const; + + TString defineQualified(const TStructure &structure, bool useHLSLRowMajorPacking, bool useStd140Packing); + static TString defineNameless(const TStructure &structure); + + Std140PaddingHelper getPaddingHelper(); + + private: + unsigned mUniquePaddingCounter; + + std::map mStd140StructElementIndexes; + + typedef std::set StructNames; + StructNames mStructNames; + + typedef std::set Constructors; + Constructors mConstructors; + + typedef std::vector StructDeclarations; + StructDeclarations mStructDeclarations; + + void storeStd140ElementIndex(const TStructure &structure, bool useHLSLRowMajorPacking); + static TString define(const TStructure &structure, bool useHLSLRowMajorPacking, + bool useStd140Packing, Std140PaddingHelper *padHelper); +}; + +} + +#endif // COMPILER_STRUCTUREHLSL_H_ diff --git a/gfx/angle/src/compiler/translator/SymbolTable.cpp b/gfx/angle/src/compiler/translator/SymbolTable.cpp index 5eb043480baa..028da2115140 100644 --- a/gfx/angle/src/compiler/translator/SymbolTable.cpp +++ b/gfx/angle/src/compiler/translator/SymbolTable.cpp @@ -18,7 +18,7 @@ #include #include -int TSymbolTableLevel::uniqueId = 0; +int TSymbolTable::uniqueIdCounter = 0; // // Functions have buried pointers to delete. @@ -38,6 +38,25 @@ TSymbolTableLevel::~TSymbolTableLevel() delete (*it).second; } +bool TSymbolTableLevel::insert(TSymbol *symbol) +{ + symbol->setUniqueId(TSymbolTable::nextUniqueId()); + + // returning true means symbol was added to the table + tInsertResult result = level.insert(tLevelPair(symbol->getMangledName(), symbol)); + + return result.second; +} + +TSymbol *TSymbolTableLevel::find(const TString &name) const +{ + tLevel::const_iterator it = level.find(name); + if (it == level.end()) + return 0; + else + return (*it).second; +} + // // Change all function entries in the table with the non-mangled name // to be related to the provided built-in operation. This is a low @@ -79,7 +98,8 @@ TSymbol::TSymbol(const TSymbol ©Of) uniqueId = copyOf.uniqueId; } -TSymbol *TSymbolTable::find(const TString &name, int shaderVersion, bool *builtIn, bool *sameScope) +TSymbol *TSymbolTable::find(const TString &name, int shaderVersion, + bool *builtIn, bool *sameScope) const { int level = currentLevel(); TSymbol *symbol; @@ -103,7 +123,8 @@ TSymbol *TSymbolTable::find(const TString &name, int shaderVersion, bool *builtI return symbol; } -TSymbol *TSymbolTable::findBuiltIn(const TString &name, int shaderVersion) +TSymbol *TSymbolTable::findBuiltIn( + const TString &name, int shaderVersion) const { for (int level = LAST_BUILTIN_LEVEL; level >= 0; level--) { @@ -188,10 +209,10 @@ void TSymbolTable::insertBuiltIn( } } - insert(level, *function); + insert(level, function); } -TPrecision TSymbolTable::getDefaultPrecision(TBasicType type) +TPrecision TSymbolTable::getDefaultPrecision(TBasicType type) const { if (!SupportsPrecision(type)) return EbpUndefined; diff --git a/gfx/angle/src/compiler/translator/SymbolTable.h b/gfx/angle/src/compiler/translator/SymbolTable.h index 2119d8b27450..6b0e0c0a0337 100644 --- a/gfx/angle/src/compiler/translator/SymbolTable.h +++ b/gfx/angle/src/compiler/translator/SymbolTable.h @@ -34,7 +34,7 @@ #include "common/angleutils.h" #include "compiler/translator/InfoSink.h" -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" // Symbol base class. (Can build functions or variables out of these...) class TSymbol @@ -185,7 +185,7 @@ class TFunction : public TSymbol defined(false) { } - TFunction(const TString *name, TType &retType, TOperator tOp = EOpNull) + TFunction(const TString *name, const TType &retType, TOperator tOp = EOpNull) : TSymbol(name), returnType(retType), mangledName(TFunction::mangleName(*name)), @@ -288,36 +288,15 @@ class TSymbolTableLevel } ~TSymbolTableLevel(); - bool insert(const TString &name, TSymbol &symbol) - { - symbol.setUniqueId(++uniqueId); + bool insert(TSymbol *symbol); - // returning true means symbol was added to the table - tInsertResult 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); - if (it == level.end()) - return 0; - else - return (*it).second; - } + TSymbol *find(const TString &name) const; void relateToOperator(const char *name, TOperator op); void relateToExtension(const char *name, const TString &ext); protected: tLevel level; - static int uniqueId; // for unique identification in code generation }; enum ESymbolLevel @@ -344,15 +323,15 @@ class TSymbolTable // When the symbol table is initialized with the built-ins, there should // 'push' calls, so that built-ins are at level 0 and the shader // globals are at level 1. - bool isEmpty() + bool isEmpty() const { return table.empty(); } - bool atBuiltInLevel() + bool atBuiltInLevel() const { return currentLevel() <= LAST_BUILTIN_LEVEL; } - bool atGlobalLevel() + bool atGlobalLevel() const { return currentLevel() <= GLOBAL_LEVEL; } @@ -371,12 +350,12 @@ class TSymbolTable precisionStack.pop_back(); } - bool declare(TSymbol &symbol) + bool declare(TSymbol *symbol) { return insert(currentLevel(), symbol); } - bool insert(ESymbolLevel level, TSymbol &symbol) + bool insert(ESymbolLevel level, TSymbol *symbol) { return table[level]->insert(symbol); } @@ -386,7 +365,7 @@ class TSymbolTable TVariable *constant = new TVariable( NewPoolTString(name), TType(EbtInt, EbpUndefined, EvqConst, 1)); constant->getConstPointer()->setIConst(value); - return insert(level, *constant); + return insert(level, constant); } void insertBuiltIn(ESymbolLevel level, TType *rvalue, const char *name, @@ -394,8 +373,8 @@ class TSymbolTable TType *ptype4 = 0, TType *ptype5 = 0); TSymbol *find(const TString &name, int shaderVersion, - bool *builtIn = NULL, bool *sameScope = NULL); - TSymbol *findBuiltIn(const TString &name, int shaderVersion); + bool *builtIn = NULL, bool *sameScope = NULL) const; + TSymbol *findBuiltIn(const TString &name, int shaderVersion) const; TSymbolTableLevel *getOuterLevel() { @@ -427,7 +406,12 @@ class TSymbolTable // Searches down the precisionStack for a precision qualifier // for the specified TBasicType - TPrecision getDefaultPrecision(TBasicType type); + TPrecision getDefaultPrecision(TBasicType type) const; + + static int nextUniqueId() + { + return ++uniqueIdCounter; + } private: ESymbolLevel currentLevel() const @@ -438,6 +422,8 @@ class TSymbolTable std::vector table; typedef TMap PrecisionStackLevel; std::vector< PrecisionStackLevel *> precisionStack; + + static int uniqueIdCounter; }; #endif // _SYMBOL_TABLE_INCLUDED_ diff --git a/gfx/angle/src/compiler/translator/TranslatorESSL.cpp b/gfx/angle/src/compiler/translator/TranslatorESSL.cpp index c956e29c5be3..5b99fea94897 100644 --- a/gfx/angle/src/compiler/translator/TranslatorESSL.cpp +++ b/gfx/angle/src/compiler/translator/TranslatorESSL.cpp @@ -7,8 +7,9 @@ #include "compiler/translator/TranslatorESSL.h" #include "compiler/translator/OutputESSL.h" +#include "angle_gl.h" -TranslatorESSL::TranslatorESSL(ShShaderType type, ShShaderSpec spec) +TranslatorESSL::TranslatorESSL(sh::GLenum type, ShShaderSpec spec) : TCompiler(type, spec, SH_ESSL_OUTPUT) { } @@ -20,7 +21,7 @@ void TranslatorESSL::translate(TIntermNode* root) { // Write emulated built-in functions if needed. getBuiltInFunctionEmulator().OutputEmulatedFunctionDefinition( - sink, getShaderType() == SH_FRAGMENT_SHADER); + sink, getShaderType() == GL_FRAGMENT_SHADER); // Write array bounds clamping emulation if needed. getArrayBoundsClamper().OutputClampingFunctionDefinition(sink); diff --git a/gfx/angle/src/compiler/translator/TranslatorESSL.h b/gfx/angle/src/compiler/translator/TranslatorESSL.h index e18f3c25ec8b..55766822d1b4 100644 --- a/gfx/angle/src/compiler/translator/TranslatorESSL.h +++ b/gfx/angle/src/compiler/translator/TranslatorESSL.h @@ -7,11 +7,11 @@ #ifndef COMPILER_TRANSLATORESSL_H_ #define COMPILER_TRANSLATORESSL_H_ -#include "compiler/translator/ShHandle.h" +#include "compiler/translator/Compiler.h" class TranslatorESSL : public TCompiler { public: - TranslatorESSL(ShShaderType type, ShShaderSpec spec); + TranslatorESSL(sh::GLenum type, ShShaderSpec spec); protected: virtual void translate(TIntermNode* root); diff --git a/gfx/angle/src/compiler/translator/TranslatorGLSL.cpp b/gfx/angle/src/compiler/translator/TranslatorGLSL.cpp index 749d8377f0cc..4b2aecab33a8 100644 --- a/gfx/angle/src/compiler/translator/TranslatorGLSL.cpp +++ b/gfx/angle/src/compiler/translator/TranslatorGLSL.cpp @@ -9,7 +9,7 @@ #include "compiler/translator/OutputGLSL.h" #include "compiler/translator/VersionGLSL.h" -static void writeVersion(ShShaderType type, TIntermNode* root, +static void writeVersion(sh::GLenum type, TIntermNode* root, TInfoSinkBase& sink) { TVersionGLSL versionGLSL(type); root->traverse(&versionGLSL); @@ -21,7 +21,7 @@ static void writeVersion(ShShaderType type, TIntermNode* root, } } -TranslatorGLSL::TranslatorGLSL(ShShaderType type, ShShaderSpec spec) +TranslatorGLSL::TranslatorGLSL(sh::GLenum type, ShShaderSpec spec) : TCompiler(type, spec, SH_GLSL_OUTPUT) { } diff --git a/gfx/angle/src/compiler/translator/TranslatorGLSL.h b/gfx/angle/src/compiler/translator/TranslatorGLSL.h index 1e16b2605e4d..3c6c2e426af8 100644 --- a/gfx/angle/src/compiler/translator/TranslatorGLSL.h +++ b/gfx/angle/src/compiler/translator/TranslatorGLSL.h @@ -7,11 +7,11 @@ #ifndef COMPILER_TRANSLATORGLSL_H_ #define COMPILER_TRANSLATORGLSL_H_ -#include "compiler/translator/ShHandle.h" +#include "compiler/translator/Compiler.h" class TranslatorGLSL : public TCompiler { public: - TranslatorGLSL(ShShaderType type, ShShaderSpec spec); + TranslatorGLSL(sh::GLenum type, ShShaderSpec spec); protected: virtual void translate(TIntermNode* root); diff --git a/gfx/angle/src/compiler/translator/TranslatorHLSL.cpp b/gfx/angle/src/compiler/translator/TranslatorHLSL.cpp index da6f9801ad0f..52588e462671 100644 --- a/gfx/angle/src/compiler/translator/TranslatorHLSL.cpp +++ b/gfx/angle/src/compiler/translator/TranslatorHLSL.cpp @@ -9,8 +9,8 @@ #include "compiler/translator/InitializeParseContext.h" #include "compiler/translator/OutputHLSL.h" -TranslatorHLSL::TranslatorHLSL(ShShaderType type, ShShaderSpec spec, ShShaderOutput output) - : TCompiler(type, spec, output) +TranslatorHLSL::TranslatorHLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output) + : TCompiler(type, spec, output) { } @@ -21,9 +21,34 @@ void TranslatorHLSL::translate(TIntermNode *root) outputHLSL.output(); - mActiveUniforms = outputHLSL.getUniforms(); - mActiveInterfaceBlocks = outputHLSL.getInterfaceBlocks(); - mActiveOutputVariables = outputHLSL.getOutputVariables(); - mActiveAttributes = outputHLSL.getAttributes(); - mActiveVaryings = outputHLSL.getVaryings(); + attributes = outputHLSL.getAttributes(); + outputVariables = outputHLSL.getOutputVariables(); + uniforms = outputHLSL.getUniforms(); + varyings = outputHLSL.getVaryings(); + interfaceBlocks = outputHLSL.getInterfaceBlocks(); + + mInterfaceBlockRegisterMap = outputHLSL.getInterfaceBlockRegisterMap(); + mUniformRegisterMap = outputHLSL.getUniformRegisterMap(); +} + +bool TranslatorHLSL::hasInterfaceBlock(const std::string &interfaceBlockName) const +{ + return (mInterfaceBlockRegisterMap.count(interfaceBlockName) > 0); +} + +unsigned int TranslatorHLSL::getInterfaceBlockRegister(const std::string &interfaceBlockName) const +{ + ASSERT(hasInterfaceBlock(interfaceBlockName)); + return mInterfaceBlockRegisterMap.find(interfaceBlockName)->second; +} + +bool TranslatorHLSL::hasUniform(const std::string &uniformName) const +{ + return (mUniformRegisterMap.count(uniformName) > 0); +} + +unsigned int TranslatorHLSL::getUniformRegister(const std::string &uniformName) const +{ + ASSERT(hasUniform(uniformName)); + return mUniformRegisterMap.find(uniformName)->second; } diff --git a/gfx/angle/src/compiler/translator/TranslatorHLSL.h b/gfx/angle/src/compiler/translator/TranslatorHLSL.h index 8b16587b6b13..11a042d83a50 100644 --- a/gfx/angle/src/compiler/translator/TranslatorHLSL.h +++ b/gfx/angle/src/compiler/translator/TranslatorHLSL.h @@ -7,28 +7,25 @@ #ifndef COMPILER_TRANSLATORHLSL_H_ #define COMPILER_TRANSLATORHLSL_H_ -#include "compiler/translator/ShHandle.h" -#include "common/shadervars.h" - -class TranslatorHLSL : public TCompiler { -public: - TranslatorHLSL(ShShaderType type, ShShaderSpec spec, ShShaderOutput output); +#include "compiler/translator/Compiler.h" +class TranslatorHLSL : public TCompiler +{ + public: + TranslatorHLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output); virtual TranslatorHLSL *getAsTranslatorHLSL() { return this; } - const std::vector &getUniforms() { return mActiveUniforms; } - const std::vector &getInterfaceBlocks() const { return mActiveInterfaceBlocks; } - const std::vector &getOutputVariables() { return mActiveOutputVariables; } - const std::vector &getAttributes() { return mActiveAttributes; } - const std::vector &getVaryings() { return mActiveVaryings; } -protected: + bool hasInterfaceBlock(const std::string &interfaceBlockName) const; + unsigned int getInterfaceBlockRegister(const std::string &interfaceBlockName) const; + + bool hasUniform(const std::string &uniformName) const; + unsigned int getUniformRegister(const std::string &uniformName) const; + + protected: virtual void translate(TIntermNode* root); - std::vector mActiveUniforms; - std::vector mActiveInterfaceBlocks; - std::vector mActiveOutputVariables; - std::vector mActiveAttributes; - std::vector mActiveVaryings; + std::map mInterfaceBlockRegisterMap; + std::map mUniformRegisterMap; }; #endif // COMPILER_TRANSLATORHLSL_H_ diff --git a/gfx/angle/src/compiler/translator/Types.cpp b/gfx/angle/src/compiler/translator/Types.cpp index 4763920f86eb..d36936fb23b5 100644 --- a/gfx/angle/src/compiler/translator/Types.cpp +++ b/gfx/angle/src/compiler/translator/Types.cpp @@ -13,6 +13,38 @@ #include #include +const char* getBasicString(TBasicType t) +{ + switch (t) + { + case EbtVoid: return "void"; break; + case EbtFloat: return "float"; break; + case EbtInt: return "int"; break; + case EbtUInt: return "uint"; break; + case EbtBool: return "bool"; break; + case EbtSampler2D: return "sampler2D"; break; + case EbtSampler3D: return "sampler3D"; break; + case EbtSamplerCube: return "samplerCube"; break; + case EbtSamplerExternalOES: return "samplerExternalOES"; break; + case EbtSampler2DRect: return "sampler2DRect"; break; + case EbtSampler2DArray: return "sampler2DArray"; break; + case EbtISampler2D: return "isampler2D"; break; + case EbtISampler3D: return "isampler3D"; break; + case EbtISamplerCube: return "isamplerCube"; break; + case EbtISampler2DArray: return "isampler2DArray"; break; + case EbtUSampler2D: return "usampler2D"; break; + case EbtUSampler3D: return "usampler3D"; break; + case EbtUSamplerCube: return "usamplerCube"; break; + case EbtUSampler2DArray: return "usampler2DArray"; break; + case EbtSampler2DShadow: return "sampler2DShadow"; break; + case EbtSamplerCubeShadow: return "samplerCubeShadow"; break; + case EbtSampler2DArrayShadow: return "sampler2DArrayShadow"; break; + case EbtStruct: return "structure"; break; + case EbtInterfaceBlock: return "interface block"; break; + default: UNREACHABLE(); return "unknown type"; + } +} + TType::TType(const TPublicType &p) : type(p.type), precision(p.precision), qualifier(p.qualifier), layoutQualifier(p.layoutQualifier), primarySize(p.primarySize), secondarySize(p.secondarySize), array(p.array), arraySize(p.arraySize), @@ -22,57 +54,9 @@ TType::TType(const TPublicType &p) structure = p.userDef->getStruct(); } -bool TType::equals(const TType &other) const -{ - if (type != other.type || precision != other.precision || - primarySize != other.primarySize || secondarySize != other.secondarySize || - array != other.array || (array && arraySize != other.arraySize) || - interfaceBlock != other.interfaceBlock || structure != other.structure) - { - return false; - } - if (interfaceBlock && !interfaceBlock->equals(*(other.interfaceBlock))) - return false; - if (structure && !structure->equals(*(other.structure))) - return false; - return true; -} - -bool TField::equals(const TField &other) const -{ - ASSERT(mType && mName); - ASSERT(other.mType && other.mName); - return mType->equals(*(other.mType)) && *mName == *(other.mName); -} - -bool TFieldListCollection::equals(const TFieldListCollection &other) const -{ - ASSERT(mName && mFields); - ASSERT(other.mName && other.mFields); - if (*mName != *(other.mName)) - return false; - if (mFields->size() != other.mFields->size()) - return false; - for (size_t ii = 0; ii < mFields->size(); ++ii) - { - ASSERT((*mFields)[ii] && (*(other.mFields))[ii]); - if (!(*mFields)[ii]->equals(*((*(other.mFields))[ii]))) - return false; - } - return true; -} - bool TStructure::equals(const TStructure &other) const { - return TFieldListCollection::equals(other); -} - -bool TInterfaceBlock::equals(const TInterfaceBlock &other) const -{ - if (!TFieldListCollection::equals(other)) - return false; - // TODO(zmo): do we need to consider mBlockStorage and mMatrixPacking? - return mArraySize == other.mArraySize; + return (uniqueId() == other.uniqueId()); } // diff --git a/gfx/angle/src/compiler/translator/Types.h b/gfx/angle/src/compiler/translator/Types.h index 91c36a657b3b..075196daa3ff 100644 --- a/gfx/angle/src/compiler/translator/Types.h +++ b/gfx/angle/src/compiler/translator/Types.h @@ -15,6 +15,7 @@ struct TPublicType; class TType; +class TSymbol; class TField { @@ -47,8 +48,6 @@ class TField return mLine; } - bool equals(const TField &other) const; - private: DISALLOW_COPY_AND_ASSIGN(TField); TType *mType; @@ -99,8 +98,6 @@ class TFieldListCollection size_t calculateObjectSize() const; virtual TString mangledNamePrefix() const = 0; - bool equals(const TFieldListCollection &other) const; - const TString *mName; TFieldList *mFields; @@ -115,7 +112,8 @@ class TStructure : public TFieldListCollection POOL_ALLOCATOR_NEW_DELETE(); TStructure(const TString *name, TFieldList *fields) : TFieldListCollection(name, fields), - mDeepestNesting(0) + mDeepestNesting(0), + mUniqueId(0) { } @@ -129,8 +127,30 @@ class TStructure : public TFieldListCollection bool equals(const TStructure &other) const; + void setUniqueId(int uniqueId) + { + mUniqueId = uniqueId; + } + + int uniqueId() const + { + ASSERT(mUniqueId != 0); + return mUniqueId; + } + private: DISALLOW_COPY_AND_ASSIGN(TStructure); + + // TODO(zmo): Find a way to get rid of the const_cast in function + // setName(). At the moment keep this function private so only + // friend class RegenerateStructNames may call it. + friend class RegenerateStructNames; + void setName(const TString &name) + { + TString *mutableName = const_cast(mName); + *mutableName = name; + } + virtual TString mangledNamePrefix() const { return "struct-"; @@ -138,6 +158,7 @@ class TStructure : public TFieldListCollection int calculateDeepestNesting() const; mutable int mDeepestNesting; + int mUniqueId; }; class TInterfaceBlock : public TFieldListCollection @@ -179,8 +200,6 @@ class TInterfaceBlock : public TFieldListCollection return mMatrixPacking; } - bool equals(const TInterfaceBlock &other) const; - private: DISALLOW_COPY_AND_ASSIGN(TInterfaceBlock); virtual TString mangledNamePrefix() const @@ -371,10 +390,6 @@ class TType return mangled; } - // This is different from operator== as we also compare - // precision here. - bool equals(const TType &other) const; - bool sameElementType(const TType &right) const { return type == right.type && diff --git a/gfx/angle/src/compiler/translator/UnfoldShortCircuit.cpp b/gfx/angle/src/compiler/translator/UnfoldShortCircuit.cpp index b7826119aea0..65f50c4cc37f 100644 --- a/gfx/angle/src/compiler/translator/UnfoldShortCircuit.cpp +++ b/gfx/angle/src/compiler/translator/UnfoldShortCircuit.cpp @@ -12,6 +12,7 @@ #include "compiler/translator/InfoSink.h" #include "compiler/translator/OutputHLSL.h" +#include "compiler/translator/UtilsHLSL.h" namespace sh { @@ -117,7 +118,7 @@ bool UnfoldShortCircuit::visitSelection(Visit visit, TIntermSelection *node) { int i = mTemporaryIndex; - out << mOutputHLSL->typeString(node->getType()) << " s" << i << ";\n"; + out << TypeString(node->getType()) << " s" << i << ";\n"; out << "{\n"; diff --git a/gfx/angle/src/compiler/translator/UnfoldShortCircuit.h b/gfx/angle/src/compiler/translator/UnfoldShortCircuit.h index 1e416bc04c14..6fd3b457bdac 100644 --- a/gfx/angle/src/compiler/translator/UnfoldShortCircuit.h +++ b/gfx/angle/src/compiler/translator/UnfoldShortCircuit.h @@ -9,7 +9,7 @@ #ifndef COMPILER_UNFOLDSHORTCIRCUIT_H_ #define COMPILER_UNFOLDSHORTCIRCUIT_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include "compiler/translator/ParseContext.h" namespace sh diff --git a/gfx/angle/src/compiler/translator/UnfoldShortCircuitAST.h b/gfx/angle/src/compiler/translator/UnfoldShortCircuitAST.h index 24c14a60e37f..3acaf7ee7cb8 100644 --- a/gfx/angle/src/compiler/translator/UnfoldShortCircuitAST.h +++ b/gfx/angle/src/compiler/translator/UnfoldShortCircuitAST.h @@ -11,7 +11,7 @@ #define COMPILER_UNFOLD_SHORT_CIRCUIT_AST_H_ #include "common/angleutils.h" -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" // This traverser identifies all the short circuit binary nodes that need to // be replaced, and creates the corresponding replacement nodes. However, diff --git a/gfx/angle/src/compiler/translator/UniformHLSL.cpp b/gfx/angle/src/compiler/translator/UniformHLSL.cpp new file mode 100644 index 000000000000..2c99a904c626 --- /dev/null +++ b/gfx/angle/src/compiler/translator/UniformHLSL.cpp @@ -0,0 +1,278 @@ +// +// Copyright (c) 2014 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. +// +// UniformHLSL.cpp: +// Methods for GLSL to HLSL translation for uniforms and interface blocks. +// + +#include "OutputHLSL.h" +#include "common/blocklayout.h" +#include "common/utilities.h" +#include "compiler/translator/UniformHLSL.h" +#include "compiler/translator/StructureHLSL.h" +#include "compiler/translator/util.h" +#include "compiler/translator/UtilsHLSL.h" + +namespace sh +{ + +static const char *UniformRegisterPrefix(const TType &type) +{ + if (IsSampler(type.getBasicType())) + { + return "s"; + } + else + { + return "c"; + } +} + +static TString InterfaceBlockFieldTypeString(const TField &field, TLayoutBlockStorage blockStorage) +{ + const TType &fieldType = *field.type(); + const TLayoutMatrixPacking matrixPacking = fieldType.getLayoutQualifier().matrixPacking; + ASSERT(matrixPacking != EmpUnspecified); + TStructure *structure = fieldType.getStruct(); + + if (fieldType.isMatrix()) + { + // Use HLSL row-major packing for GLSL column-major matrices + const TString &matrixPackString = (matrixPacking == EmpRowMajor ? "column_major" : "row_major"); + return matrixPackString + " " + TypeString(fieldType); + } + else if (structure) + { + // Use HLSL row-major packing for GLSL column-major matrices + return QualifiedStructNameString(*structure, matrixPacking == EmpColumnMajor, + blockStorage == EbsStd140); + } + else + { + return TypeString(fieldType); + } +} + +static TString InterfaceBlockStructName(const TInterfaceBlock &interfaceBlock) +{ + return DecoratePrivate(interfaceBlock.name()) + "_type"; +} + +UniformHLSL::UniformHLSL(StructureHLSL *structureHLSL, ShShaderOutput outputType) + : mUniformRegister(0), + mInterfaceBlockRegister(0), + mSamplerRegister(0), + mStructureHLSL(structureHLSL), + mOutputType(outputType) +{} + +void UniformHLSL::reserveUniformRegisters(unsigned int registerCount) +{ + mUniformRegister = registerCount; +} + +void UniformHLSL::reserveInterfaceBlockRegisters(unsigned int registerCount) +{ + mInterfaceBlockRegister = registerCount; +} + +unsigned int UniformHLSL::declareUniformAndAssignRegister(const TType &type, const TString &name) +{ + unsigned int registerIndex = (IsSampler(type.getBasicType()) ? mSamplerRegister : mUniformRegister); + + GetVariableTraverser traverser; + traverser.traverse(type, name, &mActiveUniforms); + + const sh::Uniform &activeUniform = mActiveUniforms.back(); + mUniformRegisterMap[activeUniform.name] = registerIndex; + + unsigned int registerCount = HLSLVariableRegisterCount(activeUniform, mOutputType); + if (IsSampler(type.getBasicType())) + { + mSamplerRegister += registerCount; + } + else + { + mUniformRegister += registerCount; + } + + return registerIndex; +} + +TString UniformHLSL::uniformsHeader(ShShaderOutput outputType, const ReferencedSymbols &referencedUniforms) +{ + TString uniforms; + + for (ReferencedSymbols::const_iterator uniformIt = referencedUniforms.begin(); + uniformIt != referencedUniforms.end(); uniformIt++) + { + const TIntermSymbol &uniform = *uniformIt->second; + const TType &type = uniform.getType(); + const TString &name = uniform.getSymbol(); + + unsigned int registerIndex = declareUniformAndAssignRegister(type, name); + + if (outputType == SH_HLSL11_OUTPUT && IsSampler(type.getBasicType())) // Also declare the texture + { + uniforms += "uniform " + SamplerString(type) + " sampler_" + DecorateUniform(name, type) + ArrayString(type) + + " : register(s" + str(registerIndex) + ");\n"; + + uniforms += "uniform " + TextureString(type) + " texture_" + DecorateUniform(name, type) + ArrayString(type) + + " : register(t" + str(registerIndex) + ");\n"; + } + else + { + const TStructure *structure = type.getStruct(); + // If this is a nameless struct, we need to use its full definition, rather than its (empty) name. + // TypeString() will invoke defineNameless in this case; qualifier prefixes are unnecessary for + // nameless structs in ES, as nameless structs cannot be used anywhere that layout qualifiers are + // permitted. + const TString &typeName = ((structure && !structure->name().empty()) ? + QualifiedStructNameString(*structure, false, false) : TypeString(type)); + + const TString ®isterString = TString("register(") + UniformRegisterPrefix(type) + str(registerIndex) + ")"; + + uniforms += "uniform " + typeName + " " + DecorateUniform(name, type) + ArrayString(type) + " : " + registerString + ";\n"; + } + } + + return (uniforms.empty() ? "" : ("// Uniforms\n\n" + uniforms)); +} + +TString UniformHLSL::interfaceBlocksHeader(const ReferencedSymbols &referencedInterfaceBlocks) +{ + TString interfaceBlocks; + + for (ReferencedSymbols::const_iterator interfaceBlockIt = referencedInterfaceBlocks.begin(); + interfaceBlockIt != referencedInterfaceBlocks.end(); interfaceBlockIt++) + { + const TType &nodeType = interfaceBlockIt->second->getType(); + const TInterfaceBlock &interfaceBlock = *nodeType.getInterfaceBlock(); + + unsigned int arraySize = static_cast(interfaceBlock.arraySize()); + unsigned int activeRegister = mInterfaceBlockRegister; + + InterfaceBlock activeBlock; + activeBlock.name = interfaceBlock.name().c_str(); + activeBlock.arraySize = arraySize; + + GetInterfaceBlockFields(interfaceBlock, &activeBlock.fields); + + mInterfaceBlockRegisterMap[activeBlock.name] = activeRegister; + mInterfaceBlockRegister += std::max(1u, arraySize); + + activeBlock.layout = GetBlockLayoutType(interfaceBlock.blockStorage()); + + if (interfaceBlock.matrixPacking() == EmpRowMajor) + { + activeBlock.isRowMajorLayout = true; + } + + mActiveInterfaceBlocks.push_back(activeBlock); + + if (interfaceBlock.hasInstanceName()) + { + interfaceBlocks += interfaceBlockStructString(interfaceBlock); + } + + if (arraySize > 0) + { + for (unsigned int arrayIndex = 0; arrayIndex < arraySize; arrayIndex++) + { + interfaceBlocks += interfaceBlockString(interfaceBlock, activeRegister + arrayIndex, arrayIndex); + } + } + else + { + interfaceBlocks += interfaceBlockString(interfaceBlock, activeRegister, GL_INVALID_INDEX); + } + } + + return (interfaceBlocks.empty() ? "" : ("// Interface Blocks\n\n" + interfaceBlocks)); +} + +TString UniformHLSL::interfaceBlockString(const TInterfaceBlock &interfaceBlock, unsigned int registerIndex, unsigned int arrayIndex) +{ + const TString &arrayIndexString = (arrayIndex != GL_INVALID_INDEX ? Decorate(str(arrayIndex)) : ""); + const TString &blockName = interfaceBlock.name() + arrayIndexString; + TString hlsl; + + hlsl += "cbuffer " + blockName + " : register(b" + str(registerIndex) + ")\n" + "{\n"; + + if (interfaceBlock.hasInstanceName()) + { + hlsl += " " + InterfaceBlockStructName(interfaceBlock) + " " + + interfaceBlockInstanceString(interfaceBlock, arrayIndex) + ";\n"; + } + else + { + const TLayoutBlockStorage blockStorage = interfaceBlock.blockStorage(); + hlsl += interfaceBlockMembersString(interfaceBlock, blockStorage); + } + + hlsl += "};\n\n"; + + return hlsl; +} + +TString UniformHLSL::interfaceBlockInstanceString(const TInterfaceBlock& interfaceBlock, unsigned int arrayIndex) +{ + if (!interfaceBlock.hasInstanceName()) + { + return ""; + } + else if (interfaceBlock.isArray()) + { + return DecoratePrivate(interfaceBlock.instanceName()) + "_" + str(arrayIndex); + } + else + { + return Decorate(interfaceBlock.instanceName()); + } +} + +TString UniformHLSL::interfaceBlockMembersString(const TInterfaceBlock &interfaceBlock, TLayoutBlockStorage blockStorage) +{ + TString hlsl; + + Std140PaddingHelper padHelper = mStructureHLSL->getPaddingHelper(); + + for (unsigned int typeIndex = 0; typeIndex < interfaceBlock.fields().size(); typeIndex++) + { + const TField &field = *interfaceBlock.fields()[typeIndex]; + const TType &fieldType = *field.type(); + + if (blockStorage == EbsStd140) + { + // 2 and 3 component vector types in some cases need pre-padding + hlsl += padHelper.prePaddingString(fieldType); + } + + hlsl += " " + InterfaceBlockFieldTypeString(field, blockStorage) + + " " + Decorate(field.name()) + ArrayString(fieldType) + ";\n"; + + // must pad out after matrices and arrays, where HLSL usually allows itself room to pack stuff + if (blockStorage == EbsStd140) + { + const bool useHLSLRowMajorPacking = (fieldType.getLayoutQualifier().matrixPacking == EmpColumnMajor); + hlsl += padHelper.postPaddingString(fieldType, useHLSLRowMajorPacking); + } + } + + return hlsl; +} + +TString UniformHLSL::interfaceBlockStructString(const TInterfaceBlock &interfaceBlock) +{ + const TLayoutBlockStorage blockStorage = interfaceBlock.blockStorage(); + + return "struct " + InterfaceBlockStructName(interfaceBlock) + "\n" + "{\n" + + interfaceBlockMembersString(interfaceBlock, blockStorage) + + "};\n\n"; +} + +} diff --git a/gfx/angle/src/compiler/translator/UniformHLSL.h b/gfx/angle/src/compiler/translator/UniformHLSL.h new file mode 100644 index 000000000000..d61457d29583 --- /dev/null +++ b/gfx/angle/src/compiler/translator/UniformHLSL.h @@ -0,0 +1,65 @@ +// +// Copyright (c) 2014 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. +// +// UniformHLSL.h: +// Methods for GLSL to HLSL translation for uniforms and interface blocks. +// + +#ifndef TRANSLATOR_UNIFORMHLSL_H_ +#define TRANSLATOR_UNIFORMHLSL_H_ + +#include "compiler/translator/Types.h" + +namespace sh +{ +class StructureHLSL; + +class UniformHLSL +{ + public: + UniformHLSL(StructureHLSL *structureHLSL, ShShaderOutput outputType); + + void reserveUniformRegisters(unsigned int registerCount); + void reserveInterfaceBlockRegisters(unsigned int registerCount); + TString uniformsHeader(ShShaderOutput outputType, const ReferencedSymbols &referencedUniforms); + TString interfaceBlocksHeader(const ReferencedSymbols &referencedInterfaceBlocks); + + // Used for direct index references + static TString interfaceBlockInstanceString(const TInterfaceBlock& interfaceBlock, unsigned int arrayIndex); + + const std::vector &getUniforms() const { return mActiveUniforms; } + const std::vector &getInterfaceBlocks() const { return mActiveInterfaceBlocks; } + const std::map &getInterfaceBlockRegisterMap() const + { + return mInterfaceBlockRegisterMap; + } + const std::map &getUniformRegisterMap() const + { + return mUniformRegisterMap; + } + + private: + TString interfaceBlockString(const TInterfaceBlock &interfaceBlock, unsigned int registerIndex, unsigned int arrayIndex); + TString interfaceBlockMembersString(const TInterfaceBlock &interfaceBlock, TLayoutBlockStorage blockStorage); + TString interfaceBlockStructString(const TInterfaceBlock &interfaceBlock); + + // Returns the uniform's register index + unsigned int declareUniformAndAssignRegister(const TType &type, const TString &name); + + unsigned int mUniformRegister; + unsigned int mInterfaceBlockRegister; + unsigned int mSamplerRegister; + StructureHLSL *mStructureHLSL; + ShShaderOutput mOutputType; + + std::vector mActiveUniforms; + std::vector mActiveInterfaceBlocks; + std::map mInterfaceBlockRegisterMap; + std::map mUniformRegisterMap; +}; + +} + +#endif // TRANSLATOR_UNIFORMHLSL_H_ diff --git a/gfx/angle/src/compiler/translator/UtilsHLSL.cpp b/gfx/angle/src/compiler/translator/UtilsHLSL.cpp new file mode 100644 index 000000000000..de0c36ca65b8 --- /dev/null +++ b/gfx/angle/src/compiler/translator/UtilsHLSL.cpp @@ -0,0 +1,243 @@ +// +// Copyright (c) 2014 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. +// +// UtilsHLSL.cpp: +// Utility methods for GLSL to HLSL translation. +// + +#include "compiler/translator/UtilsHLSL.h" +#include "compiler/translator/StructureHLSL.h" +#include "compiler/translator/SymbolTable.h" + +namespace sh +{ + +TString SamplerString(const TType &type) +{ + if (IsShadowSampler(type.getBasicType())) + { + return "SamplerComparisonState"; + } + else + { + return "SamplerState"; + } +} + +TString TextureString(const TType &type) +{ + switch (type.getBasicType()) + { + case EbtSampler2D: return "Texture2D"; + case EbtSamplerCube: return "TextureCube"; + case EbtSamplerExternalOES: return "Texture2D"; + case EbtSampler2DArray: return "Texture2DArray"; + case EbtSampler3D: return "Texture3D"; + case EbtISampler2D: return "Texture2D"; + case EbtISampler3D: return "Texture3D"; + case EbtISamplerCube: return "Texture2DArray"; + case EbtISampler2DArray: return "Texture2DArray"; + case EbtUSampler2D: return "Texture2D"; + case EbtUSampler3D: return "Texture3D"; + case EbtUSamplerCube: return "Texture2DArray"; + case EbtUSampler2DArray: return "Texture2DArray"; + case EbtSampler2DShadow: return "Texture2D"; + case EbtSamplerCubeShadow: return "TextureCube"; + case EbtSampler2DArrayShadow: return "Texture2DArray"; + default: UNREACHABLE(); + } + + return ""; +} + +TString DecorateUniform(const TString &string, const TType &type) +{ + if (type.getBasicType() == EbtSamplerExternalOES) + { + return "ex_" + string; + } + + return Decorate(string); +} + +TString DecorateField(const TString &string, const TStructure &structure) +{ + if (structure.name().compare(0, 3, "gl_") != 0) + { + return Decorate(string); + } + + return string; +} + +TString DecoratePrivate(const TString &privateText) +{ + return "dx_" + privateText; +} + +TString Decorate(const TString &string) +{ + if (string.compare(0, 3, "gl_") != 0) + { + return "_" + string; + } + + return string; +} + +TString TypeString(const TType &type) +{ + const TStructure* structure = type.getStruct(); + if (structure) + { + const TString& typeName = structure->name(); + if (typeName != "") + { + return StructNameString(*structure); + } + else // Nameless structure, define in place + { + return StructureHLSL::defineNameless(*structure); + } + } + else if (type.isMatrix()) + { + int cols = type.getCols(); + int rows = type.getRows(); + return "float" + str(cols) + "x" + str(rows); + } + else + { + switch (type.getBasicType()) + { + case EbtFloat: + switch (type.getNominalSize()) + { + case 1: return "float"; + case 2: return "float2"; + case 3: return "float3"; + case 4: return "float4"; + } + case EbtInt: + switch (type.getNominalSize()) + { + case 1: return "int"; + case 2: return "int2"; + case 3: return "int3"; + case 4: return "int4"; + } + case EbtUInt: + switch (type.getNominalSize()) + { + case 1: return "uint"; + case 2: return "uint2"; + case 3: return "uint3"; + case 4: return "uint4"; + } + case EbtBool: + switch (type.getNominalSize()) + { + case 1: return "bool"; + case 2: return "bool2"; + case 3: return "bool3"; + case 4: return "bool4"; + } + case EbtVoid: + return "void"; + case EbtSampler2D: + case EbtISampler2D: + case EbtUSampler2D: + case EbtSampler2DArray: + case EbtISampler2DArray: + case EbtUSampler2DArray: + return "sampler2D"; + case EbtSamplerCube: + case EbtISamplerCube: + case EbtUSamplerCube: + return "samplerCUBE"; + case EbtSamplerExternalOES: + return "sampler2D"; + default: + break; + } + } + + UNREACHABLE(); + return ""; +} + +TString StructNameString(const TStructure &structure) +{ + if (structure.name().empty()) + { + return ""; + } + + return "ss" + str(structure.uniqueId()) + "_" + structure.name(); +} + +TString QualifiedStructNameString(const TStructure &structure, bool useHLSLRowMajorPacking, + bool useStd140Packing) +{ + if (structure.name() == "") + { + return ""; + } + + TString prefix = ""; + + // Structs packed with row-major matrices in HLSL are prefixed with "rm" + // GLSL column-major maps to HLSL row-major, and the converse is true + + if (useStd140Packing) + { + prefix += "std_"; + } + + if (useHLSLRowMajorPacking) + { + prefix += "rm_"; + } + + return prefix + StructNameString(structure); +} + +TString InterpolationString(TQualifier qualifier) +{ + switch (qualifier) + { + case EvqVaryingIn: return ""; + case EvqFragmentIn: return ""; + case EvqInvariantVaryingIn: return ""; + case EvqSmoothIn: return "linear"; + case EvqFlatIn: return "nointerpolation"; + case EvqCentroidIn: return "centroid"; + case EvqVaryingOut: return ""; + case EvqVertexOut: return ""; + case EvqInvariantVaryingOut: return ""; + case EvqSmoothOut: return "linear"; + case EvqFlatOut: return "nointerpolation"; + case EvqCentroidOut: return "centroid"; + default: UNREACHABLE(); + } + + return ""; +} + +TString QualifierString(TQualifier qualifier) +{ + switch (qualifier) + { + case EvqIn: return "in"; + case EvqOut: return "inout"; // 'out' results in an HLSL error if not all fields are written, for GLSL it's undefined + case EvqInOut: return "inout"; + case EvqConstReadOnly: return "const"; + default: UNREACHABLE(); + } + + return ""; +} + +} diff --git a/gfx/angle/src/compiler/translator/UtilsHLSL.h b/gfx/angle/src/compiler/translator/UtilsHLSL.h new file mode 100644 index 000000000000..aaa3ddf5d2ad --- /dev/null +++ b/gfx/angle/src/compiler/translator/UtilsHLSL.h @@ -0,0 +1,37 @@ +// +// Copyright (c) 2014 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. +// +// UtilsHLSL.h: +// Utility methods for GLSL to HLSL translation. +// + +#ifndef TRANSLATOR_UTILSHLSL_H_ +#define TRANSLATOR_UTILSHLSL_H_ + +#include +#include "compiler/translator/Types.h" + +#include "angle_gl.h" + +namespace sh +{ + +TString TextureString(const TType &type); +TString SamplerString(const TType &type); +// Prepends an underscore to avoid naming clashes +TString Decorate(const TString &string); +TString DecorateUniform(const TString &string, const TType &type); +TString DecorateField(const TString &string, const TStructure &structure); +TString DecoratePrivate(const TString &privateText); +TString TypeString(const TType &type); +TString StructNameString(const TStructure &structure); +TString QualifiedStructNameString(const TStructure &structure, bool useHLSLRowMajorPacking, + bool useStd140Packing); +TString InterpolationString(TQualifier qualifier); +TString QualifierString(TQualifier qualifier); + +} + +#endif // TRANSLATOR_UTILSHLSL_H_ diff --git a/gfx/angle/src/compiler/translator/ValidateLimitations.cpp b/gfx/angle/src/compiler/translator/ValidateLimitations.cpp index e96a777cee3e..c1a7b7524f1d 100644 --- a/gfx/angle/src/compiler/translator/ValidateLimitations.cpp +++ b/gfx/angle/src/compiler/translator/ValidateLimitations.cpp @@ -8,6 +8,7 @@ #include "compiler/translator/InfoSink.h" #include "compiler/translator/InitializeParseContext.h" #include "compiler/translator/ParseContext.h" +#include "angle_gl.h" namespace { @@ -46,9 +47,95 @@ class ValidateConstIndexExpr : public TIntermTraverser TLoopStack& mLoopStack; }; +const char *GetOperatorString(TOperator op) +{ + switch (op) + { + case EOpInitialize: return "="; + case EOpAssign: return "="; + case EOpAddAssign: return "+="; + case EOpSubAssign: return "-="; + case EOpDivAssign: return "/="; + + // Fall-through. + case EOpMulAssign: + case EOpVectorTimesMatrixAssign: + case EOpVectorTimesScalarAssign: + case EOpMatrixTimesScalarAssign: + case EOpMatrixTimesMatrixAssign: return "*="; + + // Fall-through. + case EOpIndexDirect: + case EOpIndexIndirect: return "[]"; + + case EOpIndexDirectStruct: + case EOpIndexDirectInterfaceBlock: return "."; + case EOpVectorSwizzle: return "."; + case EOpAdd: return "+"; + case EOpSub: return "-"; + case EOpMul: return "*"; + case EOpDiv: return "/"; + case EOpMod: UNIMPLEMENTED(); break; + case EOpEqual: return "=="; + case EOpNotEqual: return "!="; + case EOpLessThan: return "<"; + case EOpGreaterThan: return ">"; + case EOpLessThanEqual: return "<="; + case EOpGreaterThanEqual: return ">="; + + // Fall-through. + case EOpVectorTimesScalar: + case EOpVectorTimesMatrix: + case EOpMatrixTimesVector: + case EOpMatrixTimesScalar: + case EOpMatrixTimesMatrix: return "*"; + + case EOpLogicalOr: return "||"; + case EOpLogicalXor: return "^^"; + case EOpLogicalAnd: return "&&"; + case EOpNegative: return "-"; + case EOpVectorLogicalNot: return "not"; + case EOpLogicalNot: return "!"; + case EOpPostIncrement: return "++"; + case EOpPostDecrement: return "--"; + case EOpPreIncrement: return "++"; + case EOpPreDecrement: return "--"; + + case EOpRadians: return "radians"; + case EOpDegrees: return "degrees"; + case EOpSin: return "sin"; + case EOpCos: return "cos"; + case EOpTan: return "tan"; + case EOpAsin: return "asin"; + case EOpAcos: return "acos"; + case EOpAtan: return "atan"; + case EOpExp: return "exp"; + case EOpLog: return "log"; + case EOpExp2: return "exp2"; + case EOpLog2: return "log2"; + case EOpSqrt: return "sqrt"; + case EOpInverseSqrt: return "inversesqrt"; + case EOpAbs: return "abs"; + case EOpSign: return "sign"; + case EOpFloor: return "floor"; + case EOpCeil: return "ceil"; + case EOpFract: return "fract"; + case EOpLength: return "length"; + case EOpNormalize: return "normalize"; + case EOpDFdx: return "dFdx"; + case EOpDFdy: return "dFdy"; + case EOpFwidth: return "fwidth"; + case EOpAny: return "any"; + case EOpAll: return "all"; + + default: break; + } + return ""; +} + } // namespace anonymous -ValidateLimitations::ValidateLimitations(ShShaderType shaderType, +ValidateLimitations::ValidateLimitations(sh::GLenum shaderType, TInfoSinkBase &sink) : mShaderType(shaderType), mSink(sink), @@ -185,13 +272,13 @@ int ValidateLimitations::validateForLoopInit(TIntermLoop *node) return -1; } // To keep things simple do not allow declaration list. - TIntermSequence &declSeq = decl->getSequence(); - if (declSeq.size() != 1) + TIntermSequence *declSeq = decl->getSequence(); + if (declSeq->size() != 1) { error(decl->getLine(), "Invalid init declaration", "for"); return -1; } - TIntermBinary *declInit = declSeq[0]->getAsBinaryNode(); + TIntermBinary *declInit = (*declSeq)[0]->getAsBinaryNode(); if ((declInit == NULL) || (declInit->getOp() != EOpInitialize)) { error(decl->getLine(), "Invalid init declaration", "for"); @@ -267,7 +354,7 @@ bool ValidateLimitations::validateForLoopCond(TIntermLoop *node, default: error(binOp->getLine(), "Invalid relational operator", - getOperatorString(binOp->getOp())); + GetOperatorString(binOp->getOp())); break; } // Loop index must be compared with a constant. @@ -344,7 +431,7 @@ bool ValidateLimitations::validateForLoopExpr(TIntermLoop *node, ASSERT((unOp == NULL) && (binOp != NULL)); break; default: - error(expr->getLine(), "Invalid operator", getOperatorString(op)); + error(expr->getLine(), "Invalid operator", GetOperatorString(op)); return false; } @@ -374,10 +461,10 @@ bool ValidateLimitations::validateFunctionCall(TIntermAggregate *node) // List of param indices for which loop indices are used as argument. typedef std::vector ParamIndex; ParamIndex pIndex; - TIntermSequence& params = node->getSequence(); - for (TIntermSequence::size_type i = 0; i < params.size(); ++i) + TIntermSequence *params = node->getSequence(); + for (TIntermSequence::size_type i = 0; i < params->size(); ++i) { - TIntermSymbol *symbol = params[i]->getAsSymbolNode(); + TIntermSymbol *symbol = (*params)[i]->getAsSymbolNode(); if (symbol && isLoopIndex(symbol)) pIndex.push_back(i); } @@ -398,9 +485,9 @@ bool ValidateLimitations::validateFunctionCall(TIntermAggregate *node) TQualifier qual = param.type->getQualifier(); if ((qual == EvqOut) || (qual == EvqInOut)) { - error(params[*i]->getLine(), + error((*params)[*i]->getLine(), "Loop index cannot be used as argument to a function out or inout parameter", - params[*i]->getAsSymbolNode()->getSymbol().c_str()); + (*params)[*i]->getAsSymbolNode()->getSymbol().c_str()); valid = false; } } @@ -457,7 +544,7 @@ bool ValidateLimitations::validateIndexing(TIntermBinary *node) // The index expession must be a constant-index-expression unless // the operand is a uniform in a vertex shader. TIntermTyped *operand = node->getLeft(); - bool skip = (mShaderType == SH_VERTEX_SHADER) && + bool skip = (mShaderType == GL_VERTEX_SHADER) && (operand->getQualifier() == EvqUniform); if (!skip && !isConstIndexExpr(index)) { diff --git a/gfx/angle/src/compiler/translator/ValidateLimitations.h b/gfx/angle/src/compiler/translator/ValidateLimitations.h index f28995c640b3..e6e8a9619f8e 100644 --- a/gfx/angle/src/compiler/translator/ValidateLimitations.h +++ b/gfx/angle/src/compiler/translator/ValidateLimitations.h @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include "compiler/translator/LoopInfo.h" class TInfoSinkBase; @@ -14,7 +14,7 @@ class TInfoSinkBase; class ValidateLimitations : public TIntermTraverser { public: - ValidateLimitations(ShShaderType shaderType, TInfoSinkBase &sink); + ValidateLimitations(sh::GLenum shaderType, TInfoSinkBase &sink); int numErrors() const { return mNumErrors; } @@ -47,7 +47,7 @@ class ValidateLimitations : public TIntermTraverser bool isConstIndexExpr(TIntermNode *node); bool validateIndexing(TIntermBinary *node); - ShShaderType mShaderType; + sh::GLenum mShaderType; TInfoSinkBase &mSink; int mNumErrors; TLoopStack mLoopStack; diff --git a/gfx/angle/src/compiler/translator/ValidateOutputs.h b/gfx/angle/src/compiler/translator/ValidateOutputs.h index e391ad948602..0f808dbb9720 100644 --- a/gfx/angle/src/compiler/translator/ValidateOutputs.h +++ b/gfx/angle/src/compiler/translator/ValidateOutputs.h @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include diff --git a/gfx/angle/src/compiler/translator/VariableInfo.cpp b/gfx/angle/src/compiler/translator/VariableInfo.cpp index d0b19907f4c0..b023c29cf0b2 100644 --- a/gfx/angle/src/compiler/translator/VariableInfo.cpp +++ b/gfx/angle/src/compiler/translator/VariableInfo.cpp @@ -4,242 +4,108 @@ // found in the LICENSE file. // +#include "angle_gl.h" #include "compiler/translator/VariableInfo.h" +#include "compiler/translator/util.h" +#include "common/utilities.h" -namespace { +static void ExpandUserDefinedVariable(const sh::ShaderVariable &variable, + const std::string &name, + const std::string &mappedName, + bool markStaticUse, + std::vector *expanded); -TString arrayBrackets(int index) +static void ExpandVariable(const sh::ShaderVariable &variable, + const std::string &name, + const std::string &mappedName, + bool markStaticUse, + std::vector *expanded) { - TStringStream stream; - stream << "[" << index << "]"; - return stream.str(); -} - -// Returns the data type for an attribute, uniform, or varying. -ShDataType getVariableDataType(const TType& type) -{ - switch (type.getBasicType()) { - case EbtFloat: - if (type.isMatrix()) { - switch (type.getCols()) - { - case 2: - switch (type.getRows()) - { - case 2: return SH_FLOAT_MAT2; - case 3: return SH_FLOAT_MAT2x3; - case 4: return SH_FLOAT_MAT2x4; - default: UNREACHABLE(); - } - case 3: - switch (type.getRows()) - { - case 2: return SH_FLOAT_MAT3x2; - case 3: return SH_FLOAT_MAT3; - case 4: return SH_FLOAT_MAT3x4; - default: UNREACHABLE(); - } - case 4: - switch (type.getRows()) - { - case 2: return SH_FLOAT_MAT4x2; - case 3: return SH_FLOAT_MAT4x3; - case 4: return SH_FLOAT_MAT4; - default: UNREACHABLE(); - } - } - } else if (type.isVector()) { - switch (type.getNominalSize()) { - case 2: return SH_FLOAT_VEC2; - case 3: return SH_FLOAT_VEC3; - case 4: return SH_FLOAT_VEC4; - default: UNREACHABLE(); - } - } else { - return SH_FLOAT; - } - case EbtInt: - if (type.isMatrix()) { - UNREACHABLE(); - } else if (type.isVector()) { - switch (type.getNominalSize()) { - case 2: return SH_INT_VEC2; - case 3: return SH_INT_VEC3; - case 4: return SH_INT_VEC4; - default: UNREACHABLE(); - } - } else { - return SH_INT; - } - case EbtUInt: - if (type.isMatrix()) { - UNREACHABLE(); - } else if (type.isVector()) { - switch (type.getNominalSize()) { - case 2: return SH_UNSIGNED_INT_VEC2; - case 3: return SH_UNSIGNED_INT_VEC3; - case 4: return SH_UNSIGNED_INT_VEC4; - default: UNREACHABLE(); - } - } else { - return SH_UNSIGNED_INT; - } - case EbtBool: - if (type.isMatrix()) { - UNREACHABLE(); - } else if (type.isVector()) { - switch (type.getNominalSize()) { - case 2: return SH_BOOL_VEC2; - case 3: return SH_BOOL_VEC3; - case 4: return SH_BOOL_VEC4; - default: UNREACHABLE(); - } - } else { - return SH_BOOL; - } - case EbtSampler2D: return SH_SAMPLER_2D; - case EbtSampler3D: return SH_SAMPLER_3D; - case EbtSamplerCube: return SH_SAMPLER_CUBE; - case EbtSamplerExternalOES: return SH_SAMPLER_EXTERNAL_OES; - case EbtSampler2DRect: return SH_SAMPLER_2D_RECT_ARB; - case EbtSampler2DArray: return SH_SAMPLER_2D_ARRAY; - case EbtISampler2D: return SH_INT_SAMPLER_2D; - case EbtISampler3D: return SH_INT_SAMPLER_3D; - case EbtISamplerCube: return SH_INT_SAMPLER_CUBE; - case EbtISampler2DArray: return SH_INT_SAMPLER_2D_ARRAY; - case EbtUSampler2D: return SH_UNSIGNED_INT_SAMPLER_2D; - case EbtUSampler3D: return SH_UNSIGNED_INT_SAMPLER_3D; - case EbtUSamplerCube: return SH_UNSIGNED_INT_SAMPLER_CUBE; - case EbtUSampler2DArray: return SH_UNSIGNED_INT_SAMPLER_2D_ARRAY; - case EbtSampler2DShadow: return SH_SAMPLER_2D_SHADOW; - case EbtSamplerCubeShadow: return SH_SAMPLER_CUBE_SHADOW; - case EbtSampler2DArrayShadow: return SH_SAMPLER_2D_ARRAY_SHADOW; - default: UNREACHABLE(); - } - return SH_NONE; -} - -void getBuiltInVariableInfo(const TType& type, - const TString& name, - const TString& mappedName, - TVariableInfoList& infoList); -void getUserDefinedVariableInfo(const TType& type, - const TString& name, - const TString& mappedName, - TVariableInfoList& infoList, - ShHashFunction64 hashFunction); - -// Returns info for an attribute, uniform, or varying. -void getVariableInfo(const TType& type, - const TString& name, - const TString& mappedName, - TVariableInfoList& infoList, - ShHashFunction64 hashFunction) -{ - if (type.getBasicType() == EbtStruct || type.isInterfaceBlock()) { - if (type.isArray()) { - for (int i = 0; i < type.getArraySize(); ++i) { - TString lname = name + arrayBrackets(i); - TString lmappedName = mappedName + arrayBrackets(i); - getUserDefinedVariableInfo(type, lname, lmappedName, infoList, hashFunction); + if (variable.isStruct()) + { + if (variable.isArray()) + { + for (size_t elementIndex = 0; elementIndex < variable.elementCount(); elementIndex++) + { + std::string lname = name + ArrayString(elementIndex); + std::string lmappedName = mappedName + ArrayString(elementIndex); + ExpandUserDefinedVariable(variable, lname, lmappedName, markStaticUse, expanded); } - } else { - getUserDefinedVariableInfo(type, name, mappedName, infoList, hashFunction); } - } else { - getBuiltInVariableInfo(type, name, mappedName, infoList); + else + { + ExpandUserDefinedVariable(variable, name, mappedName, markStaticUse, expanded); + } + } + else + { + sh::ShaderVariable expandedVar = variable; + + expandedVar.name = name; + expandedVar.mappedName = mappedName; + + // Mark all expanded fields as used if the parent is used + if (markStaticUse) + { + expandedVar.staticUse = true; + } + + if (expandedVar.isArray()) + { + expandedVar.name += "[0]"; + expandedVar.mappedName += "[0]"; + } + + expanded->push_back(expandedVar); } } -void getBuiltInVariableInfo(const TType& type, - const TString& name, - const TString& mappedName, - TVariableInfoList& infoList) +static void ExpandUserDefinedVariable(const sh::ShaderVariable &variable, + const std::string &name, + const std::string &mappedName, + bool markStaticUse, + std::vector *expanded) { - ASSERT(type.getBasicType() != EbtStruct); + ASSERT(variable.isStruct()); - TVariableInfo varInfo; - if (type.isArray()) { - varInfo.name = (name + "[0]").c_str(); - varInfo.mappedName = (mappedName + "[0]").c_str(); - varInfo.size = type.getArraySize(); - varInfo.isArray = true; - } else { - varInfo.name = name.c_str(); - varInfo.mappedName = mappedName.c_str(); - varInfo.size = 1; - varInfo.isArray = false; - } - varInfo.precision = type.getPrecision(); - varInfo.type = getVariableDataType(type); - infoList.push_back(varInfo); -} + const std::vector &fields = variable.fields; -void getUserDefinedVariableInfo(const TType& type, - const TString& name, - const TString& mappedName, - TVariableInfoList& infoList, - ShHashFunction64 hashFunction) -{ - ASSERT(type.getBasicType() == EbtStruct || type.isInterfaceBlock()); - - const TFieldList& fields = type.isInterfaceBlock() ? - type.getInterfaceBlock()->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); + for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++) + { + const sh::ShaderVariable &field = fields[fieldIndex]; + ExpandVariable(field, + name + "." + field.name, + mappedName + "." + field.mappedName, + markStaticUse, + expanded); } } -TVariableInfo* findVariable(const TType& type, - const TString& name, - TVariableInfoList& infoList) +template +static VarT *FindVariable(const TString &name, + std::vector *infoList) { // TODO(zmo): optimize this function. - TString myName = name; - if (type.isArray()) - myName += "[0]"; - for (size_t ii = 0; ii < infoList.size(); ++ii) + for (size_t ii = 0; ii < infoList->size(); ++ii) { - if (infoList[ii].name.c_str() == myName) - return &(infoList[ii]); + if ((*infoList)[ii].name.c_str() == name) + return &((*infoList)[ii]); } + return NULL; } -} // namespace anonymous - -TVariableInfo::TVariableInfo() - : type(SH_NONE), - size(0), - isArray(false), - precision(EbpUndefined), - staticUse(false) -{ -} - -TVariableInfo::TVariableInfo(ShDataType type, int size) - : type(type), - size(size), - isArray(false), - precision(EbpUndefined), - staticUse(false) -{ -} - -CollectVariables::CollectVariables(TVariableInfoList& attribs, - TVariableInfoList& uniforms, - TVariableInfoList& varyings, +CollectVariables::CollectVariables(std::vector *attribs, + std::vector *outputVariables, + std::vector *uniforms, + std::vector *varyings, + std::vector *interfaceBlocks, ShHashFunction64 hashFunction) : mAttribs(attribs), + mOutputVariables(outputVariables), mUniforms(uniforms), mVaryings(varyings), + mInterfaceBlocks(interfaceBlocks), mPointCoordAdded(false), mFrontFacingAdded(false), mFragCoordAdded(false), @@ -252,123 +118,276 @@ CollectVariables::CollectVariables(TVariableInfoList& attribs, // Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count // toward varying counting if they are statically used in a fragment // shader. -void CollectVariables::visitSymbol(TIntermSymbol* symbol) +void CollectVariables::visitSymbol(TIntermSymbol *symbol) { ASSERT(symbol != NULL); - TVariableInfo* var = NULL; - switch (symbol->getQualifier()) + sh::ShaderVariable *var = NULL; + const TString &symbolName = symbol->getSymbol(); + + if (sh::IsVarying(symbol->getQualifier())) { - case EvqVaryingOut: - case EvqInvariantVaryingOut: - case EvqVaryingIn: - case EvqInvariantVaryingIn: - var = findVariable(symbol->getType(), symbol->getSymbol(), mVaryings); - break; - case EvqUniform: - var = findVariable(symbol->getType(), symbol->getSymbol(), mUniforms); - break; - case EvqFragCoord: - if (!mFragCoordAdded) { - TVariableInfo info; - info.name = "gl_FragCoord"; - info.mappedName = "gl_FragCoord"; - info.type = SH_FLOAT_VEC4; - info.size = 1; - info.precision = EbpMedium; // Use mediump as it doesn't really matter. - info.staticUse = true; - mVaryings.push_back(info); - mFragCoordAdded = true; + var = FindVariable(symbolName, mVaryings); + } + else if (symbol->getType().getBasicType() == EbtInterfaceBlock) + { + UNREACHABLE(); + } + else + { + switch (symbol->getQualifier()) + { + case EvqAttribute: + case EvqVertexIn: + var = FindVariable(symbolName, mAttribs); + break; + case EvqFragmentOut: + var = FindVariable(symbolName, mOutputVariables); + break; + case EvqUniform: + { + const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock(); + if (interfaceBlock) + { + sh::InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), mInterfaceBlocks); + ASSERT(namedBlock); + var = FindVariable(symbolName, &namedBlock->fields); + + // Set static use on the parent interface block here + namedBlock->staticUse = true; + + } + else + { + var = FindVariable(symbolName, mUniforms); + } + + // It's an internal error to reference an undefined user uniform + ASSERT(symbolName.compare(0, 3, "gl_") == 0 || var); + } + break; + case EvqFragCoord: + if (!mFragCoordAdded) + { + sh::Varying info; + info.name = "gl_FragCoord"; + info.mappedName = "gl_FragCoord"; + info.type = GL_FLOAT_VEC4; + info.arraySize = 0; + info.precision = GL_MEDIUM_FLOAT; // Use mediump as it doesn't really matter. + info.staticUse = true; + mVaryings->push_back(info); + mFragCoordAdded = true; + } + return; + case EvqFrontFacing: + if (!mFrontFacingAdded) + { + sh::Varying info; + info.name = "gl_FrontFacing"; + info.mappedName = "gl_FrontFacing"; + info.type = GL_BOOL; + info.arraySize = 0; + info.precision = GL_NONE; + info.staticUse = true; + mVaryings->push_back(info); + mFrontFacingAdded = true; + } + return; + case EvqPointCoord: + if (!mPointCoordAdded) + { + sh::Varying info; + info.name = "gl_PointCoord"; + info.mappedName = "gl_PointCoord"; + info.type = GL_FLOAT_VEC2; + info.arraySize = 0; + info.precision = GL_MEDIUM_FLOAT; // Use mediump as it doesn't really matter. + info.staticUse = true; + mVaryings->push_back(info); + mPointCoordAdded = true; + } + return; + default: + break; } - return; - case EvqFrontFacing: - if (!mFrontFacingAdded) { - TVariableInfo info; - info.name = "gl_FrontFacing"; - info.mappedName = "gl_FrontFacing"; - info.type = SH_BOOL; - info.size = 1; - info.precision = EbpUndefined; - info.staticUse = true; - mVaryings.push_back(info); - mFrontFacingAdded = true; - } - return; - case EvqPointCoord: - if (!mPointCoordAdded) { - TVariableInfo info; - info.name = "gl_PointCoord"; - info.mappedName = "gl_PointCoord"; - info.type = SH_FLOAT_VEC2; - info.size = 1; - info.precision = EbpMedium; // Use mediump as it doesn't really matter. - info.staticUse = true; - mVaryings.push_back(info); - mPointCoordAdded = true; - } - return; - default: - break; } if (var) + { var->staticUse = true; + } } -bool CollectVariables::visitAggregate(Visit, TIntermAggregate* node) +class NameHashingTraverser : public sh::GetVariableTraverser +{ + public: + NameHashingTraverser(ShHashFunction64 hashFunction) + : mHashFunction(hashFunction) + {} + + private: + DISALLOW_COPY_AND_ASSIGN(NameHashingTraverser); + + virtual void visitVariable(sh::ShaderVariable *variable) + { + TString stringName = TString(variable->name.c_str()); + variable->mappedName = TIntermTraverser::hash(stringName, mHashFunction).c_str(); + } + + ShHashFunction64 mHashFunction; +}; + +// Attributes, which cannot have struct fields, are a special case +template <> +void CollectVariables::visitVariable(const TIntermSymbol *variable, + std::vector *infoList) const +{ + ASSERT(variable); + const TType &type = variable->getType(); + ASSERT(!type.getStruct()); + + sh::Attribute attribute; + + attribute.type = sh::GLVariableType(type); + attribute.precision = sh::GLVariablePrecision(type); + attribute.name = variable->getSymbol().c_str(); + attribute.arraySize = static_cast(type.getArraySize()); + attribute.mappedName = TIntermTraverser::hash(variable->getSymbol(), mHashFunction).c_str(); + attribute.location = variable->getType().getLayoutQualifier().location; + + infoList->push_back(attribute); +} + +template <> +void CollectVariables::visitVariable(const TIntermSymbol *variable, + std::vector *infoList) const +{ + sh::InterfaceBlock interfaceBlock; + const TInterfaceBlock *blockType = variable->getType().getInterfaceBlock(); + ASSERT(blockType); + + interfaceBlock.name = blockType->name().c_str(); + interfaceBlock.mappedName = TIntermTraverser::hash(variable->getSymbol(), mHashFunction).c_str(); + interfaceBlock.instanceName = (blockType->hasInstanceName() ? blockType->instanceName().c_str() : ""); + interfaceBlock.arraySize = variable->getArraySize(); + interfaceBlock.isRowMajorLayout = (blockType->matrixPacking() == EmpRowMajor); + interfaceBlock.layout = sh::GetBlockLayoutType(blockType->blockStorage()); + + // Gather field information + sh::GetInterfaceBlockFields(*blockType, &interfaceBlock.fields); + + infoList->push_back(interfaceBlock); +} + +template +void CollectVariables::visitVariable(const TIntermSymbol *variable, + std::vector *infoList) const +{ + NameHashingTraverser traverser(mHashFunction); + traverser.traverse(variable->getType(), variable->getSymbol(), infoList); +} + +template +void CollectVariables::visitInfoList(const TIntermSequence &sequence, + std::vector *infoList) const +{ + for (size_t seqIndex = 0; seqIndex < sequence.size(); seqIndex++) + { + const TIntermSymbol *variable = sequence[seqIndex]->getAsSymbolNode(); + // The only case in which the sequence will not contain a + // TIntermSymbol node is initialization. It will contain a + // TInterBinary node in that case. Since attributes, uniforms, + // and varyings cannot be initialized in a shader, we must have + // only TIntermSymbol nodes in the sequence. + ASSERT(variable != NULL); + visitVariable(variable, infoList); + } +} + +bool CollectVariables::visitAggregate(Visit, TIntermAggregate *node) { bool visitChildren = true; switch (node->getOp()) { - case EOpDeclaration: { - const TIntermSequence& sequence = node->getSequence(); - TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier(); - if (qualifier == EvqAttribute || qualifier == EvqVertexIn || qualifier == EvqUniform || - qualifier == EvqVaryingIn || qualifier == EvqVaryingOut || - qualifier == EvqInvariantVaryingIn || qualifier == EvqInvariantVaryingOut) + case EOpDeclaration: { - TVariableInfoList *infoList = NULL; + const TIntermSequence &sequence = *(node->getSequence()); + ASSERT(!sequence.empty()); - switch (qualifier) - { - case EvqAttribute: - case EvqVertexIn: - infoList = &mAttribs; - break; - case EvqUniform: - infoList = &mUniforms; - break; - default: - infoList = &mVaryings; - break; - } + const TIntermTyped &typedNode = *(sequence.front()->getAsTyped()); + TQualifier qualifier = typedNode.getQualifier(); - for (TIntermSequence::const_iterator i = sequence.begin(); - i != sequence.end(); ++i) + if (typedNode.getBasicType() == EbtInterfaceBlock) { - const TIntermSymbol* variable = (*i)->getAsSymbolNode(); - // The only case in which the sequence will not contain a - // TIntermSymbol node is initialization. It will contain a - // TInterBinary node in that case. Since attributes, uniforms, - // and varyings cannot be initialized in a shader, we must have - // only TIntermSymbol nodes in the sequence. - ASSERT(variable != NULL); - TString processedSymbol; - if (mHashFunction == NULL) - processedSymbol = variable->getSymbol(); - else - processedSymbol = TIntermTraverser::hash(variable->getSymbol(), mHashFunction); - getVariableInfo(variable->getType(), - variable->getSymbol(), - processedSymbol, - *infoList, - mHashFunction); + visitInfoList(sequence, mInterfaceBlocks); visitChildren = false; } + else if (qualifier == EvqAttribute || qualifier == EvqVertexIn || + qualifier == EvqFragmentOut || qualifier == EvqUniform || + sh::IsVarying(qualifier)) + { + switch (qualifier) + { + case EvqAttribute: + case EvqVertexIn: + visitInfoList(sequence, mAttribs); + break; + case EvqFragmentOut: + visitInfoList(sequence, mOutputVariables); + break; + case EvqUniform: + visitInfoList(sequence, mUniforms); + break; + default: + visitInfoList(sequence, mVaryings); + break; + } + + visitChildren = false; + } + break; } - break; - } - default: break; + default: break; } return visitChildren; } + +bool CollectVariables::visitBinary(Visit, TIntermBinary *binaryNode) +{ + if (binaryNode->getOp() == EOpIndexDirectInterfaceBlock) + { + // NOTE: we do not determine static use for individual blocks of an array + TIntermTyped *blockNode = binaryNode->getLeft()->getAsTyped(); + ASSERT(blockNode); + + TIntermConstantUnion *constantUnion = binaryNode->getRight()->getAsConstantUnion(); + ASSERT(constantUnion); + + const TInterfaceBlock *interfaceBlock = blockNode->getType().getInterfaceBlock(); + sh::InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), mInterfaceBlocks); + ASSERT(namedBlock); + namedBlock->staticUse = true; + + unsigned int fieldIndex = constantUnion->getUConst(0); + ASSERT(fieldIndex < namedBlock->fields.size()); + namedBlock->fields[fieldIndex].staticUse = true; + return false; + } + + return true; +} + +template +void ExpandVariables(const std::vector &compact, + std::vector *expanded) +{ + for (size_t variableIndex = 0; variableIndex < compact.size(); variableIndex++) + { + const sh::ShaderVariable &variable = compact[variableIndex]; + ExpandVariable(variable, variable.name, variable.mappedName, variable.staticUse, expanded); + } +} + +template void ExpandVariables(const std::vector &, std::vector *); +template void ExpandVariables(const std::vector &, std::vector *); diff --git a/gfx/angle/src/compiler/translator/VariableInfo.h b/gfx/angle/src/compiler/translator/VariableInfo.h index fc9e15301bc7..b4b18863571b 100644 --- a/gfx/angle/src/compiler/translator/VariableInfo.h +++ b/gfx/angle/src/compiler/translator/VariableInfo.h @@ -7,39 +7,39 @@ #ifndef COMPILER_VARIABLE_INFO_H_ #define COMPILER_VARIABLE_INFO_H_ -#include "compiler/translator/intermediate.h" +#include -// Provides information about a variable. -// It is currently being used to store info about active attribs and uniforms. -struct TVariableInfo { - TVariableInfo(ShDataType type, int size); - TVariableInfo(); - - TPersistString name; - TPersistString mappedName; - ShDataType type; - int size; - bool isArray; - TPrecision precision; - bool staticUse; -}; -typedef std::vector TVariableInfoList; +#include "compiler/translator/IntermNode.h" // Traverses intermediate tree to collect all attributes, uniforms, varyings. -class CollectVariables : public TIntermTraverser { -public: - CollectVariables(TVariableInfoList& attribs, - TVariableInfoList& uniforms, - TVariableInfoList& varyings, +class CollectVariables : public TIntermTraverser +{ + public: + CollectVariables(std::vector *attribs, + std::vector *outputVariables, + std::vector *uniforms, + std::vector *varyings, + std::vector *interfaceBlocks, ShHashFunction64 hashFunction); - virtual void visitSymbol(TIntermSymbol*); - virtual bool visitAggregate(Visit, TIntermAggregate*); + virtual void visitSymbol(TIntermSymbol *symbol); + virtual bool visitAggregate(Visit, TIntermAggregate *node); + virtual bool visitBinary(Visit visit, TIntermBinary *binaryNode); -private: - TVariableInfoList& mAttribs; - TVariableInfoList& mUniforms; - TVariableInfoList& mVaryings; + private: + template + void visitVariable(const TIntermSymbol *variable, std::vector *infoList) const; + + template + void visitInfoList(const TIntermSequence &sequence, std::vector *infoList) const; + + std::vector *mAttribs; + std::vector *mOutputVariables; + std::vector *mUniforms; + std::vector *mVaryings; + std::vector *mInterfaceBlocks; + + std::map mInterfaceBlockFields; bool mPointCoordAdded; bool mFrontFacingAdded; @@ -48,4 +48,9 @@ private: ShHashFunction64 mHashFunction; }; +// Expand struct variables to flattened lists of split variables +template +void ExpandVariables(const std::vector &compact, + std::vector *expanded); + #endif // COMPILER_VARIABLE_INFO_H_ diff --git a/gfx/angle/src/compiler/translator/VariablePacker.cpp b/gfx/angle/src/compiler/translator/VariablePacker.cpp index 6390e3039410..e69052162a69 100644 --- a/gfx/angle/src/compiler/translator/VariablePacker.cpp +++ b/gfx/angle/src/compiler/translator/VariablePacker.cpp @@ -3,140 +3,81 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -#include "compiler/translator/VariablePacker.h" #include -#include "compiler/translator/ShHandle.h" -namespace { -int GetSortOrder(ShDataType type) +#include "angle_gl.h" + +#include "compiler/translator/VariablePacker.h" +#include "common/utilities.h" + +int VariablePacker::GetNumComponentsPerRow(sh::GLenum type) { - switch (type) { - case SH_FLOAT_MAT4: - case SH_FLOAT_MAT2x4: - case SH_FLOAT_MAT3x4: - case SH_FLOAT_MAT4x2: - case SH_FLOAT_MAT4x3: - return 0; - case SH_FLOAT_MAT2: - return 1; - case SH_FLOAT_VEC4: - case SH_INT_VEC4: - case SH_BOOL_VEC4: - return 2; - case SH_FLOAT_MAT3: - case SH_FLOAT_MAT2x3: - case SH_FLOAT_MAT3x2: - return 3; - case SH_FLOAT_VEC3: - case SH_INT_VEC3: - case SH_BOOL_VEC3: - return 4; - case SH_FLOAT_VEC2: - case SH_INT_VEC2: - case SH_BOOL_VEC2: - return 5; - case SH_FLOAT: - case SH_INT: - case SH_BOOL: - case SH_SAMPLER_2D: - case SH_SAMPLER_CUBE: - case SH_SAMPLER_EXTERNAL_OES: - case SH_SAMPLER_2D_RECT_ARB: - return 6; - default: - ASSERT(false); - return 7; - } -} -} // namespace - -int VariablePacker::GetNumComponentsPerRow(ShDataType type) -{ - switch (type) { - case SH_FLOAT_MAT4: - case SH_FLOAT_MAT2: - case SH_FLOAT_MAT2x4: - case SH_FLOAT_MAT3x4: - case SH_FLOAT_MAT4x2: - case SH_FLOAT_MAT4x3: - case SH_FLOAT_VEC4: - case SH_INT_VEC4: - case SH_BOOL_VEC4: - return 4; - case SH_FLOAT_MAT3: - case SH_FLOAT_MAT2x3: - case SH_FLOAT_MAT3x2: - case SH_FLOAT_VEC3: - case SH_INT_VEC3: - case SH_BOOL_VEC3: - return 3; - case SH_FLOAT_VEC2: - case SH_INT_VEC2: - case SH_BOOL_VEC2: - return 2; - case SH_FLOAT: - case SH_INT: - case SH_BOOL: - case SH_SAMPLER_2D: - case SH_SAMPLER_CUBE: - case SH_SAMPLER_EXTERNAL_OES: - case SH_SAMPLER_2D_RECT_ARB: - return 1; - default: - ASSERT(false); - return 5; - } -} - -int VariablePacker::GetNumRows(ShDataType type) -{ - switch (type) { - case SH_FLOAT_MAT4: - case SH_FLOAT_MAT2x4: - case SH_FLOAT_MAT3x4: - case SH_FLOAT_MAT4x3: - case SH_FLOAT_MAT4x2: - return 4; - case SH_FLOAT_MAT3: - case SH_FLOAT_MAT2x3: - case SH_FLOAT_MAT3x2: - return 3; - case SH_FLOAT_MAT2: - return 2; - case SH_FLOAT_VEC4: - case SH_INT_VEC4: - case SH_BOOL_VEC4: - case SH_FLOAT_VEC3: - case SH_INT_VEC3: - case SH_BOOL_VEC3: - case SH_FLOAT_VEC2: - case SH_INT_VEC2: - case SH_BOOL_VEC2: - case SH_FLOAT: - case SH_INT: - case SH_BOOL: - case SH_SAMPLER_2D: - case SH_SAMPLER_CUBE: - case SH_SAMPLER_EXTERNAL_OES: - case SH_SAMPLER_2D_RECT_ARB: - return 1; - default: - ASSERT(false); - return 100000; - } -} - -struct TVariableInfoComparer { - bool operator()(const TVariableInfo& lhs, const TVariableInfo& rhs) const + switch (type) { - int lhsSortOrder = GetSortOrder(lhs.type); - int rhsSortOrder = GetSortOrder(rhs.type); + case GL_FLOAT_MAT4: + case GL_FLOAT_MAT2: + case GL_FLOAT_MAT2x4: + case GL_FLOAT_MAT3x4: + case GL_FLOAT_MAT4x2: + case GL_FLOAT_MAT4x3: + case GL_FLOAT_VEC4: + case GL_INT_VEC4: + case GL_BOOL_VEC4: + case GL_UNSIGNED_INT_VEC4: + return 4; + case GL_FLOAT_MAT3: + case GL_FLOAT_MAT2x3: + case GL_FLOAT_MAT3x2: + case GL_FLOAT_VEC3: + case GL_INT_VEC3: + case GL_BOOL_VEC3: + case GL_UNSIGNED_INT_VEC3: + return 3; + case GL_FLOAT_VEC2: + case GL_INT_VEC2: + case GL_BOOL_VEC2: + case GL_UNSIGNED_INT_VEC2: + return 2; + default: + ASSERT(gl::VariableComponentCount(type) == 1); + return 1; + } +} + +int VariablePacker::GetNumRows(sh::GLenum type) +{ + switch (type) + { + case GL_FLOAT_MAT4: + case GL_FLOAT_MAT2x4: + case GL_FLOAT_MAT3x4: + case GL_FLOAT_MAT4x3: + case GL_FLOAT_MAT4x2: + return 4; + case GL_FLOAT_MAT3: + case GL_FLOAT_MAT2x3: + case GL_FLOAT_MAT3x2: + return 3; + case GL_FLOAT_MAT2: + return 2; + default: + ASSERT(gl::VariableRowCount(type) == 1); + return 1; + } +} + +struct TVariableInfoComparer +{ + bool operator()(const sh::ShaderVariable &lhs, const sh::ShaderVariable &rhs) const + { + int lhsSortOrder = gl::VariableSortOrder(lhs.type); + int rhsSortOrder = gl::VariableSortOrder(rhs.type); if (lhsSortOrder != rhsSortOrder) { return lhsSortOrder < rhsSortOrder; } // Sort by largest first. - return lhs.size > rhs.size; + return lhs.arraySize > rhs.arraySize; } }; @@ -207,18 +148,20 @@ bool VariablePacker::searchColumn(int column, int numRows, int* destRow, int* de return true; } -bool VariablePacker::CheckVariablesWithinPackingLimits(int maxVectors, const TVariableInfoList& in_variables) +template +bool VariablePacker::CheckVariablesWithinPackingLimits(unsigned int maxVectors, + const std::vector &in_variables) { ASSERT(maxVectors > 0); maxRows_ = maxVectors; topNonFullRow_ = 0; bottomNonFullRow_ = maxRows_ - 1; - TVariableInfoList variables(in_variables); + std::vector variables(in_variables); // Check whether each variable fits in the available vectors. for (size_t i = 0; i < variables.size(); i++) { - const TVariableInfo& variable = variables[i]; - if (variable.size > maxVectors / GetNumRows(variable.type)) { + const sh::ShaderVariable &variable = variables[i]; + if (variable.elementCount() > maxVectors / GetNumRows(variable.type)) { return false; } } @@ -232,11 +175,11 @@ bool VariablePacker::CheckVariablesWithinPackingLimits(int maxVectors, const TVa // Packs the 4 column variables. size_t ii = 0; for (; ii < variables.size(); ++ii) { - const TVariableInfo& variable = variables[ii]; + const sh::ShaderVariable &variable = variables[ii]; if (GetNumComponentsPerRow(variable.type) != 4) { break; } - topNonFullRow_ += GetNumRows(variable.type) * variable.size; + topNonFullRow_ += GetNumRows(variable.type) * variable.elementCount(); } if (topNonFullRow_ > maxRows_) { @@ -246,11 +189,11 @@ bool VariablePacker::CheckVariablesWithinPackingLimits(int maxVectors, const TVa // Packs the 3 column variables. int num3ColumnRows = 0; for (; ii < variables.size(); ++ii) { - const TVariableInfo& variable = variables[ii]; + const sh::ShaderVariable &variable = variables[ii]; if (GetNumComponentsPerRow(variable.type) != 3) { break; } - num3ColumnRows += GetNumRows(variable.type) * variable.size; + num3ColumnRows += GetNumRows(variable.type) * variable.elementCount(); } if (topNonFullRow_ + num3ColumnRows > maxRows_) { @@ -265,11 +208,11 @@ bool VariablePacker::CheckVariablesWithinPackingLimits(int maxVectors, const TVa int rowsAvailableInColumns01 = twoColumnRowsAvailable; int rowsAvailableInColumns23 = twoColumnRowsAvailable; for (; ii < variables.size(); ++ii) { - const TVariableInfo& variable = variables[ii]; + const sh::ShaderVariable &variable = variables[ii]; if (GetNumComponentsPerRow(variable.type) != 2) { break; } - int numRows = GetNumRows(variable.type) * variable.size; + int numRows = GetNumRows(variable.type) * variable.elementCount(); if (numRows <= rowsAvailableInColumns01) { rowsAvailableInColumns01 -= numRows; } else if (numRows <= rowsAvailableInColumns23) { @@ -289,9 +232,9 @@ bool VariablePacker::CheckVariablesWithinPackingLimits(int maxVectors, const TVa // Packs the 1 column variables. for (; ii < variables.size(); ++ii) { - const TVariableInfo& variable = variables[ii]; + const sh::ShaderVariable &variable = variables[ii]; ASSERT(1 == GetNumComponentsPerRow(variable.type)); - int numRows = GetNumRows(variable.type) * variable.size; + int numRows = GetNumRows(variable.type) * variable.elementCount(); int smallestColumn = -1; int smallestSize = maxRows_ + 1; int topRow = -1; @@ -319,5 +262,8 @@ bool VariablePacker::CheckVariablesWithinPackingLimits(int maxVectors, const TVa return true; } - - +// Instantiate all possible variable packings +template bool VariablePacker::CheckVariablesWithinPackingLimits(unsigned int, const std::vector &); +template bool VariablePacker::CheckVariablesWithinPackingLimits(unsigned int, const std::vector &); +template bool VariablePacker::CheckVariablesWithinPackingLimits(unsigned int, const std::vector &); +template bool VariablePacker::CheckVariablesWithinPackingLimits(unsigned int, const std::vector &); diff --git a/gfx/angle/src/compiler/translator/VariablePacker.h b/gfx/angle/src/compiler/translator/VariablePacker.h index fd6090827cd8..1de5332d8a39 100644 --- a/gfx/angle/src/compiler/translator/VariablePacker.h +++ b/gfx/angle/src/compiler/translator/VariablePacker.h @@ -8,23 +8,23 @@ #define _VARIABLEPACKER_INCLUDED_ #include -#include "compiler/translator/ShHandle.h" +#include "compiler/translator/VariableInfo.h" class VariablePacker { public: // Returns true if the passed in variables pack in maxVectors following // the packing rules from the GLSL 1.017 spec, Appendix A, section 7. - bool CheckVariablesWithinPackingLimits( - int maxVectors, - const TVariableInfoList& in_variables); + template + bool CheckVariablesWithinPackingLimits(unsigned int maxVectors, + const std::vector &in_variables); // Gets how many components in a row a data type takes. - static int GetNumComponentsPerRow(ShDataType type); + static int GetNumComponentsPerRow(sh::GLenum type); // Gets how many rows a data type takes. - static int GetNumRows(ShDataType type); + static int GetNumRows(sh::GLenum type); - private: + private: static const int kNumColumns = 4; static const unsigned kColumnMask = (1 << kNumColumns) - 1; diff --git a/gfx/angle/src/compiler/translator/VersionGLSL.cpp b/gfx/angle/src/compiler/translator/VersionGLSL.cpp index dd11f99eb89c..8edbd009b069 100644 --- a/gfx/angle/src/compiler/translator/VersionGLSL.cpp +++ b/gfx/angle/src/compiler/translator/VersionGLSL.cpp @@ -35,104 +35,84 @@ static const int GLSL_VERSION_120 = 120; // - invariant gl_Position; // - varying vec3 color; invariant color; // -TVersionGLSL::TVersionGLSL(ShShaderType type) - : mShaderType(type), - mVersion(GLSL_VERSION_110) +TVersionGLSL::TVersionGLSL(sh::GLenum type) + : mVersion(GLSL_VERSION_110) { } -void TVersionGLSL::visitSymbol(TIntermSymbol* node) +void TVersionGLSL::visitSymbol(TIntermSymbol *node) { if (node->getSymbol() == "gl_PointCoord") updateVersion(GLSL_VERSION_120); } -void TVersionGLSL::visitConstantUnion(TIntermConstantUnion*) -{ -} - -bool TVersionGLSL::visitBinary(Visit, TIntermBinary*) -{ - return true; -} - -bool TVersionGLSL::visitUnary(Visit, TIntermUnary*) -{ - return true; -} - -bool TVersionGLSL::visitSelection(Visit, TIntermSelection*) -{ - return true; -} - -bool TVersionGLSL::visitAggregate(Visit, TIntermAggregate* node) +bool TVersionGLSL::visitAggregate(Visit, TIntermAggregate *node) { bool visitChildren = true; - switch (node->getOp()) { + switch (node->getOp()) + { case EOpSequence: // We need to visit sequence children to get to global or inner scope. visitChildren = true; break; - case EOpDeclaration: { - const TIntermSequence& sequence = node->getSequence(); - TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier(); - if ((qualifier == EvqInvariantVaryingIn) || - (qualifier == EvqInvariantVaryingOut)) { - updateVersion(GLSL_VERSION_120); - } - break; - } - case EOpParameters: { - const TIntermSequence& params = node->getSequence(); - for (TIntermSequence::const_iterator iter = params.begin(); - iter != params.end(); ++iter) + case EOpDeclaration: { - const TIntermTyped* param = (*iter)->getAsTyped(); - if (param->isArray()) + const TIntermSequence &sequence = *(node->getSequence()); + TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier(); + if ((qualifier == EvqInvariantVaryingIn) || + (qualifier == EvqInvariantVaryingOut)) { - TQualifier qualifier = param->getQualifier(); - if ((qualifier == EvqOut) || (qualifier == EvqInOut)) + updateVersion(GLSL_VERSION_120); + } + break; + } + case EOpInvariantDeclaration: + updateVersion(GLSL_VERSION_120); + break; + case EOpParameters: + { + const TIntermSequence ¶ms = *(node->getSequence()); + for (TIntermSequence::const_iterator iter = params.begin(); + iter != params.end(); ++iter) + { + const TIntermTyped *param = (*iter)->getAsTyped(); + if (param->isArray()) { - updateVersion(GLSL_VERSION_120); - break; + TQualifier qualifier = param->getQualifier(); + if ((qualifier == EvqOut) || (qualifier == EvqInOut)) + { + updateVersion(GLSL_VERSION_120); + break; + } } } + // Fully processed. No need to visit children. + visitChildren = false; + break; } - // Fully processed. No need to visit children. - visitChildren = false; - break; - } case EOpConstructMat2: case EOpConstructMat3: - case EOpConstructMat4: { - const TIntermSequence& sequence = node->getSequence(); - if (sequence.size() == 1) { - TIntermTyped* typed = sequence.front()->getAsTyped(); - if (typed && typed->isMatrix()) { - updateVersion(GLSL_VERSION_120); - } + case EOpConstructMat4: + { + const TIntermSequence &sequence = *(node->getSequence()); + if (sequence.size() == 1) + { + TIntermTyped *typed = sequence.front()->getAsTyped(); + if (typed && typed->isMatrix()) + { + updateVersion(GLSL_VERSION_120); + } + } + break; } + default: break; - } - - default: break; } return visitChildren; } -bool TVersionGLSL::visitLoop(Visit, TIntermLoop*) -{ - return true; -} - -bool TVersionGLSL::visitBranch(Visit, TIntermBranch*) -{ - return true; -} - void TVersionGLSL::updateVersion(int version) { mVersion = std::max(version, mVersion); diff --git a/gfx/angle/src/compiler/translator/VersionGLSL.h b/gfx/angle/src/compiler/translator/VersionGLSL.h index 8a401c4e92b9..30f5a138a0f9 100644 --- a/gfx/angle/src/compiler/translator/VersionGLSL.h +++ b/gfx/angle/src/compiler/translator/VersionGLSL.h @@ -4,10 +4,10 @@ // found in the LICENSE file. // -#ifndef COMPILER_VERSIONGLSL_H_ -#define COMPILER_VERSIONGLSL_H_ +#ifndef COMPILER_TRANSLATOR_VERSIONGLSL_H_ +#define COMPILER_TRANSLATOR_VERSIONGLSL_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" // Traverses the intermediate tree to return the minimum GLSL version // required to legally access all built-in features used in the shader. @@ -24,9 +24,10 @@ // - array as "out" function parameters // // TODO: ES3 equivalent versions of GLSL -class TVersionGLSL : public TIntermTraverser { -public: - TVersionGLSL(ShShaderType type); +class TVersionGLSL : public TIntermTraverser +{ + public: + TVersionGLSL(sh::GLenum type); // Returns 120 if the following is used the shader: // - "invariant", @@ -36,21 +37,14 @@ public: // Else 110 is returned. int getVersion() { return mVersion; } - virtual void visitSymbol(TIntermSymbol*); - virtual void visitConstantUnion(TIntermConstantUnion*); - virtual bool visitBinary(Visit, TIntermBinary*); - virtual bool visitUnary(Visit, TIntermUnary*); - virtual bool visitSelection(Visit, TIntermSelection*); - virtual bool visitAggregate(Visit, TIntermAggregate*); - virtual bool visitLoop(Visit, TIntermLoop*); - virtual bool visitBranch(Visit, TIntermBranch*); + virtual void visitSymbol(TIntermSymbol *); + virtual bool visitAggregate(Visit, TIntermAggregate *); -protected: + protected: void updateVersion(int version); -private: - ShShaderType mShaderType; + private: int mVersion; }; -#endif // COMPILER_VERSIONGLSL_H_ +#endif // COMPILER_TRANSLATOR_VERSIONGLSL_H_ diff --git a/gfx/angle/src/compiler/translator/depgraph/DependencyGraph.h b/gfx/angle/src/compiler/translator/depgraph/DependencyGraph.h index 5ea1cbb837dc..bc25fe7cbc0e 100644 --- a/gfx/angle/src/compiler/translator/depgraph/DependencyGraph.h +++ b/gfx/angle/src/compiler/translator/depgraph/DependencyGraph.h @@ -7,7 +7,7 @@ #ifndef COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_H #define COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_H -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include #include diff --git a/gfx/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.cpp b/gfx/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.cpp index d5f2cba5fc01..1aeb822d5121 100644 --- a/gfx/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.cpp +++ b/gfx/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.cpp @@ -6,24 +6,32 @@ #include "compiler/translator/depgraph/DependencyGraphBuilder.h" -void TDependencyGraphBuilder::build(TIntermNode* node, TDependencyGraph* graph) +void TDependencyGraphBuilder::build(TIntermNode *node, TDependencyGraph *graph) { TDependencyGraphBuilder builder(graph); builder.build(node); } -bool TDependencyGraphBuilder::visitAggregate(Visit visit, TIntermAggregate* intermAggregate) +bool TDependencyGraphBuilder::visitAggregate( + Visit visit, TIntermAggregate *intermAggregate) { - switch (intermAggregate->getOp()) { - case EOpFunction: visitFunctionDefinition(intermAggregate); break; - case EOpFunctionCall: visitFunctionCall(intermAggregate); break; - default: visitAggregateChildren(intermAggregate); break; + switch (intermAggregate->getOp()) + { + case EOpFunction: + visitFunctionDefinition(intermAggregate); + break; + case EOpFunctionCall: + visitFunctionCall(intermAggregate); + break; + default: + visitAggregateChildren(intermAggregate); + break; } - return false; } -void TDependencyGraphBuilder::visitFunctionDefinition(TIntermAggregate* intermAggregate) +void TDependencyGraphBuilder::visitFunctionDefinition( + TIntermAggregate *intermAggregate) { // Currently, we do not support user defined functions. if (intermAggregate->getName() != "main(") @@ -34,64 +42,71 @@ void TDependencyGraphBuilder::visitFunctionDefinition(TIntermAggregate* intermAg // Takes an expression like "f(x)" and creates a dependency graph like // "x -> argument 0 -> function call". -void TDependencyGraphBuilder::visitFunctionCall(TIntermAggregate* intermFunctionCall) +void TDependencyGraphBuilder::visitFunctionCall( + TIntermAggregate *intermFunctionCall) { - TGraphFunctionCall* functionCall = mGraph->createFunctionCall(intermFunctionCall); + TGraphFunctionCall *functionCall = + mGraph->createFunctionCall(intermFunctionCall); // Run through the function call arguments. int argumentNumber = 0; - TIntermSequence& intermArguments = intermFunctionCall->getSequence(); - for (TIntermSequence::const_iterator iter = intermArguments.begin(); - iter != intermArguments.end(); + TIntermSequence *intermArguments = intermFunctionCall->getSequence(); + for (TIntermSequence::const_iterator iter = intermArguments->begin(); + iter != intermArguments->end(); ++iter, ++argumentNumber) { TNodeSetMaintainer nodeSetMaintainer(this); - TIntermNode* intermArgument = *iter; + TIntermNode *intermArgument = *iter; intermArgument->traverse(this); - if (TParentNodeSet* argumentNodes = mNodeSets.getTopSet()) { - TGraphArgument* argument = mGraph->createArgument(intermFunctionCall, argumentNumber); + if (TParentNodeSet *argumentNodes = mNodeSets.getTopSet()) + { + TGraphArgument *argument = mGraph->createArgument( + intermFunctionCall, argumentNumber); connectMultipleNodesToSingleNode(argumentNodes, argument); argument->addDependentNode(functionCall); } } - // Push the leftmost symbol of this function call into the current set of dependent symbols to - // represent the result of this function call. + // Push the leftmost symbol of this function call into the current set of + // dependent symbols to represent the result of this function call. // Thus, an expression like "y = f(x)" will yield a dependency graph like // "x -> argument 0 -> function call -> y". - // This line essentially passes the function call node back up to an earlier visitAssignment - // call, which will create the connection "function call -> y". + // This line essentially passes the function call node back up to an earlier + // visitAssignment call, which will create the connection "function call -> y". mNodeSets.insertIntoTopSet(functionCall); } -void TDependencyGraphBuilder::visitAggregateChildren(TIntermAggregate* intermAggregate) +void TDependencyGraphBuilder::visitAggregateChildren( + TIntermAggregate *intermAggregate) { - TIntermSequence& sequence = intermAggregate->getSequence(); - for(TIntermSequence::const_iterator iter = sequence.begin(); iter != sequence.end(); ++iter) + TIntermSequence *sequence = intermAggregate->getSequence(); + for (TIntermSequence::const_iterator iter = sequence->begin(); + iter != sequence->end(); ++iter) { - TIntermNode* intermChild = *iter; + TIntermNode *intermChild = *iter; intermChild->traverse(this); } } -void TDependencyGraphBuilder::visitSymbol(TIntermSymbol* intermSymbol) +void TDependencyGraphBuilder::visitSymbol(TIntermSymbol *intermSymbol) { - // Push this symbol into the set of dependent symbols for the current assignment or condition - // that we are traversing. - TGraphSymbol* symbol = mGraph->getOrCreateSymbol(intermSymbol); + // Push this symbol into the set of dependent symbols for the current + // assignment or condition that we are traversing. + TGraphSymbol *symbol = mGraph->getOrCreateSymbol(intermSymbol); mNodeSets.insertIntoTopSet(symbol); - // If this symbol is the current leftmost symbol under an assignment, replace the previous - // leftmost symbol with this symbol. - if (!mLeftmostSymbols.empty() && mLeftmostSymbols.top() != &mRightSubtree) { + // If this symbol is the current leftmost symbol under an assignment, replace + // the previous leftmost symbol with this symbol. + if (!mLeftmostSymbols.empty() && mLeftmostSymbols.top() != &mRightSubtree) + { mLeftmostSymbols.pop(); mLeftmostSymbols.push(symbol); } } -bool TDependencyGraphBuilder::visitBinary(Visit visit, TIntermBinary* intermBinary) +bool TDependencyGraphBuilder::visitBinary(Visit visit, TIntermBinary *intermBinary) { TOperator op = intermBinary->getOp(); if (op == EOpInitialize || intermBinary->isAssignment()) @@ -104,13 +119,13 @@ bool TDependencyGraphBuilder::visitBinary(Visit visit, TIntermBinary* intermBina return false; } -void TDependencyGraphBuilder::visitAssignment(TIntermBinary* intermAssignment) +void TDependencyGraphBuilder::visitAssignment(TIntermBinary *intermAssignment) { - TIntermTyped* intermLeft = intermAssignment->getLeft(); + TIntermTyped *intermLeft = intermAssignment->getLeft(); if (!intermLeft) return; - TGraphSymbol* leftmostSymbol = NULL; + TGraphSymbol *leftmostSymbol = NULL; { TNodeSetMaintainer nodeSetMaintainer(this); @@ -120,88 +135,100 @@ void TDependencyGraphBuilder::visitAssignment(TIntermBinary* intermAssignment) intermLeft->traverse(this); leftmostSymbol = mLeftmostSymbols.top(); - // After traversing the left subtree of this assignment, we should have found a real - // leftmost symbol, and the leftmost symbol should not be a placeholder. + // After traversing the left subtree of this assignment, we should + // have found a real leftmost symbol, and the leftmost symbol should + // not be a placeholder. ASSERT(leftmostSymbol != &mLeftSubtree); ASSERT(leftmostSymbol != &mRightSubtree); } - if (TIntermTyped* intermRight = intermAssignment->getRight()) { + if (TIntermTyped *intermRight = intermAssignment->getRight()) + { TLeftmostSymbolMaintainer leftmostSymbolMaintainer(this, mRightSubtree); intermRight->traverse(this); } - if (TParentNodeSet* assignmentNodes = mNodeSets.getTopSet()) + if (TParentNodeSet *assignmentNodes = mNodeSets.getTopSet()) connectMultipleNodesToSingleNode(assignmentNodes, leftmostSymbol); } - // Push the leftmost symbol of this assignment into the current set of dependent symbols to - // represent the result of this assignment. - // An expression like "a = (b = c)" will yield a dependency graph like "c -> b -> a". - // This line essentially passes the leftmost symbol of the nested assignment ("b" in this - // example) back up to the earlier visitAssignment call for the outer assignment, which will - // create the connection "b -> a". + // Push the leftmost symbol of this assignment into the current set of dependent + // symbols to represent the result of this assignment. + // An expression like "a = (b = c)" will yield a dependency graph like + // "c -> b -> a". + // This line essentially passes the leftmost symbol of the nested assignment + // ("b" in this example) back up to the earlier visitAssignment call for the + // outer assignment, which will create the connection "b -> a". mNodeSets.insertIntoTopSet(leftmostSymbol); } -void TDependencyGraphBuilder::visitLogicalOp(TIntermBinary* intermLogicalOp) +void TDependencyGraphBuilder::visitLogicalOp(TIntermBinary *intermLogicalOp) { - if (TIntermTyped* intermLeft = intermLogicalOp->getLeft()) { + if (TIntermTyped *intermLeft = intermLogicalOp->getLeft()) + { TNodeSetPropagatingMaintainer nodeSetMaintainer(this); intermLeft->traverse(this); - if (TParentNodeSet* leftNodes = mNodeSets.getTopSet()) { - TGraphLogicalOp* logicalOp = mGraph->createLogicalOp(intermLogicalOp); + if (TParentNodeSet *leftNodes = mNodeSets.getTopSet()) + { + TGraphLogicalOp *logicalOp = mGraph->createLogicalOp(intermLogicalOp); connectMultipleNodesToSingleNode(leftNodes, logicalOp); } } - if (TIntermTyped* intermRight = intermLogicalOp->getRight()) { + if (TIntermTyped *intermRight = intermLogicalOp->getRight()) + { TLeftmostSymbolMaintainer leftmostSymbolMaintainer(this, mRightSubtree); intermRight->traverse(this); } } -void TDependencyGraphBuilder::visitBinaryChildren(TIntermBinary* intermBinary) +void TDependencyGraphBuilder::visitBinaryChildren(TIntermBinary *intermBinary) { - if (TIntermTyped* intermLeft = intermBinary->getLeft()) + if (TIntermTyped *intermLeft = intermBinary->getLeft()) intermLeft->traverse(this); - if (TIntermTyped* intermRight = intermBinary->getRight()) { + if (TIntermTyped *intermRight = intermBinary->getRight()) + { TLeftmostSymbolMaintainer leftmostSymbolMaintainer(this, mRightSubtree); intermRight->traverse(this); } } -bool TDependencyGraphBuilder::visitSelection(Visit visit, TIntermSelection* intermSelection) +bool TDependencyGraphBuilder::visitSelection( + Visit visit, TIntermSelection *intermSelection) { - if (TIntermNode* intermCondition = intermSelection->getCondition()) { + if (TIntermNode *intermCondition = intermSelection->getCondition()) + { TNodeSetMaintainer nodeSetMaintainer(this); intermCondition->traverse(this); - if (TParentNodeSet* conditionNodes = mNodeSets.getTopSet()) { - TGraphSelection* selection = mGraph->createSelection(intermSelection); + if (TParentNodeSet *conditionNodes = mNodeSets.getTopSet()) + { + TGraphSelection *selection = mGraph->createSelection(intermSelection); connectMultipleNodesToSingleNode(conditionNodes, selection); } } - if (TIntermNode* intermTrueBlock = intermSelection->getTrueBlock()) + if (TIntermNode *intermTrueBlock = intermSelection->getTrueBlock()) intermTrueBlock->traverse(this); - if (TIntermNode* intermFalseBlock = intermSelection->getFalseBlock()) + if (TIntermNode *intermFalseBlock = intermSelection->getFalseBlock()) intermFalseBlock->traverse(this); return false; } -bool TDependencyGraphBuilder::visitLoop(Visit visit, TIntermLoop* intermLoop) +bool TDependencyGraphBuilder::visitLoop(Visit visit, TIntermLoop *intermLoop) { - if (TIntermTyped* intermCondition = intermLoop->getCondition()) { + if (TIntermTyped *intermCondition = intermLoop->getCondition()) + { TNodeSetMaintainer nodeSetMaintainer(this); intermCondition->traverse(this); - if (TParentNodeSet* conditionNodes = mNodeSets.getTopSet()) { - TGraphLoop* loop = mGraph->createLoop(intermLoop); + if (TParentNodeSet *conditionNodes = mNodeSets.getTopSet()) + { + TGraphLoop *loop = mGraph->createLoop(intermLoop); connectMultipleNodesToSingleNode(conditionNodes, loop); } } @@ -209,19 +236,20 @@ bool TDependencyGraphBuilder::visitLoop(Visit visit, TIntermLoop* intermLoop) if (TIntermNode* intermBody = intermLoop->getBody()) intermBody->traverse(this); - if (TIntermTyped* intermExpression = intermLoop->getExpression()) + if (TIntermTyped *intermExpression = intermLoop->getExpression()) intermExpression->traverse(this); return false; } -void TDependencyGraphBuilder::connectMultipleNodesToSingleNode(TParentNodeSet* nodes, - TGraphNode* node) const +void TDependencyGraphBuilder::connectMultipleNodesToSingleNode( + TParentNodeSet *nodes, TGraphNode *node) const { - for (TParentNodeSet::const_iterator iter = nodes->begin(); iter != nodes->end(); ++iter) + for (TParentNodeSet::const_iterator iter = nodes->begin(); + iter != nodes->end(); ++iter) { - TGraphParentNode* currentNode = *iter; + TGraphParentNode *currentNode = *iter; currentNode->addDependentNode(node); } } diff --git a/gfx/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.h b/gfx/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.h index 3e928fb77eb4..b76f075e68ab 100644 --- a/gfx/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.h +++ b/gfx/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.h @@ -4,55 +4,58 @@ // found in the LICENSE file. // -#ifndef COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H -#define COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H +#ifndef COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H +#define COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H #include "compiler/translator/depgraph/DependencyGraph.h" // -// Creates a dependency graph of symbols, function calls, conditions etc. by traversing a -// intermediate tree. +// Creates a dependency graph of symbols, function calls, conditions etc. by +// traversing a intermediate tree. // -class TDependencyGraphBuilder : public TIntermTraverser { -public: - static void build(TIntermNode* node, TDependencyGraph* graph); +class TDependencyGraphBuilder : public TIntermTraverser +{ + public: + static void build(TIntermNode *node, TDependencyGraph *graph); - virtual void visitSymbol(TIntermSymbol*); - virtual bool visitBinary(Visit visit, TIntermBinary*); - virtual bool visitSelection(Visit visit, TIntermSelection*); - virtual bool visitAggregate(Visit visit, TIntermAggregate*); - virtual bool visitLoop(Visit visit, TIntermLoop*); + virtual void visitSymbol(TIntermSymbol *); + virtual bool visitBinary(Visit visit, TIntermBinary *); + virtual bool visitSelection(Visit visit, TIntermSelection *); + virtual bool visitAggregate(Visit visit, TIntermAggregate *); + virtual bool visitLoop(Visit visit, TIntermLoop *); -private: - typedef std::stack TSymbolStack; - typedef std::set TParentNodeSet; + private: + typedef std::stack TSymbolStack; + typedef std::set TParentNodeSet; // // For collecting the dependent nodes of assignments, conditions, etc. // while traversing the intermediate tree. // - // This data structure is stack of sets. Each set contains dependency graph parent nodes. + // This data structure is stack of sets. Each set contains dependency graph + // parent nodes. // - class TNodeSetStack { - public: + class TNodeSetStack + { + public: TNodeSetStack() {}; ~TNodeSetStack() { clear(); } // This should only be called after a pushSet. // Returns NULL if the top set is empty. - TParentNodeSet* getTopSet() const + TParentNodeSet *getTopSet() const { - ASSERT(!nodeSets.empty()); - TParentNodeSet* topSet = nodeSets.top(); + ASSERT(!mNodeSets.empty()); + TParentNodeSet *topSet = mNodeSets.top(); return !topSet->empty() ? topSet : NULL; } - void pushSet() { nodeSets.push(new TParentNodeSet()); } + void pushSet() { mNodeSets.push(new TParentNodeSet()); } void popSet() { - ASSERT(!nodeSets.empty()); - delete nodeSets.top(); - nodeSets.pop(); + ASSERT(!mNodeSets.empty()); + delete mNodeSets.top(); + mNodeSets.pop(); } // Pops the top set and adds its contents to the new top set. @@ -60,12 +63,13 @@ private: // If there is no set below the top set, the top set is just deleted. void popSetIntoNext() { - ASSERT(!nodeSets.empty()); - TParentNodeSet* oldTopSet = nodeSets.top(); - nodeSets.pop(); + ASSERT(!mNodeSets.empty()); + TParentNodeSet *oldTopSet = mNodeSets.top(); + mNodeSets.pop(); - if (!nodeSets.empty()) { - TParentNodeSet* newTopSet = nodeSets.top(); + if (!mNodeSets.empty()) + { + TParentNodeSet *newTopSet = mNodeSets.top(); newTopSet->insert(oldTopSet->begin(), oldTopSet->end()); } @@ -76,106 +80,120 @@ private: // This can be called when there is no top set if we are visiting // symbols that are not under an assignment or condition. // We don't need to track those symbols. - void insertIntoTopSet(TGraphParentNode* node) + void insertIntoTopSet(TGraphParentNode *node) { - if (nodeSets.empty()) + if (mNodeSets.empty()) return; - nodeSets.top()->insert(node); + mNodeSets.top()->insert(node); } void clear() { - while (!nodeSets.empty()) + while (!mNodeSets.empty()) popSet(); } - private: - typedef std::stack TParentNodeSetStack; + private: + typedef std::stack TParentNodeSetStack; - TParentNodeSetStack nodeSets; + TParentNodeSetStack mNodeSets; }; // // An instance of this class pushes a new node set when instantiated. // When the instance goes out of scope, it and pops the node set. // - class TNodeSetMaintainer { - public: - TNodeSetMaintainer(TDependencyGraphBuilder* factory) - : sets(factory->mNodeSets) { sets.pushSet(); } - ~TNodeSetMaintainer() { sets.popSet(); } - protected: - TNodeSetStack& sets; + class TNodeSetMaintainer + { + public: + TNodeSetMaintainer(TDependencyGraphBuilder *factory) + : mSets(factory->mNodeSets) + { + mSets.pushSet(); + } + ~TNodeSetMaintainer() { mSets.popSet(); } + protected: + TNodeSetStack &mSets; }; // // An instance of this class pushes a new node set when instantiated. - // When the instance goes out of scope, it and pops the top node set and adds its contents to - // the new top node set. + // When the instance goes out of scope, it and pops the top node set and adds + // its contents to the new top node set. // - class TNodeSetPropagatingMaintainer { - public: - TNodeSetPropagatingMaintainer(TDependencyGraphBuilder* factory) - : sets(factory->mNodeSets) { sets.pushSet(); } - ~TNodeSetPropagatingMaintainer() { sets.popSetIntoNext(); } - protected: - TNodeSetStack& sets; + class TNodeSetPropagatingMaintainer + { + public: + TNodeSetPropagatingMaintainer(TDependencyGraphBuilder *factory) + : mSets(factory->mNodeSets) + { + mSets.pushSet(); + } + ~TNodeSetPropagatingMaintainer() { mSets.popSetIntoNext(); } + protected: + TNodeSetStack &mSets; }; // - // An instance of this class keeps track of the leftmost symbol while we're exploring an - // assignment. - // It will push the placeholder symbol kLeftSubtree when instantiated under a left subtree, - // and kRightSubtree under a right subtree. - // When it goes out of scope, it will pop the leftmost symbol at the top of the scope. - // During traversal, the TDependencyGraphBuilder will replace kLeftSubtree with a real symbol. - // kRightSubtree will never be replaced by a real symbol because we are tracking the leftmost - // symbol. + // An instance of this class keeps track of the leftmost symbol while we're + // exploring an assignment. + // It will push the placeholder symbol kLeftSubtree when instantiated under a + // left subtree, and kRightSubtree under a right subtree. + // When it goes out of scope, it will pop the leftmost symbol at the top of the + // scope. + // During traversal, the TDependencyGraphBuilder will replace kLeftSubtree with + // a real symbol. + // kRightSubtree will never be replaced by a real symbol because we are tracking + // the leftmost symbol. // - class TLeftmostSymbolMaintainer { - public: - TLeftmostSymbolMaintainer(TDependencyGraphBuilder* factory, TGraphSymbol& subtree) - : leftmostSymbols(factory->mLeftmostSymbols) + class TLeftmostSymbolMaintainer + { + public: + TLeftmostSymbolMaintainer( + TDependencyGraphBuilder *factory, TGraphSymbol &subtree) + : mLeftmostSymbols(factory->mLeftmostSymbols) { - needsPlaceholderSymbol = leftmostSymbols.empty() || leftmostSymbols.top() != &subtree; - if (needsPlaceholderSymbol) - leftmostSymbols.push(&subtree); + mNeedsPlaceholderSymbol = + mLeftmostSymbols.empty() || mLeftmostSymbols.top() != &subtree; + if (mNeedsPlaceholderSymbol) + mLeftmostSymbols.push(&subtree); } ~TLeftmostSymbolMaintainer() { - if (needsPlaceholderSymbol) - leftmostSymbols.pop(); + if (mNeedsPlaceholderSymbol) + mLeftmostSymbols.pop(); } - protected: - TSymbolStack& leftmostSymbols; - bool needsPlaceholderSymbol; + protected: + TSymbolStack& mLeftmostSymbols; + bool mNeedsPlaceholderSymbol; }; - TDependencyGraphBuilder(TDependencyGraph* graph) - : TIntermTraverser(true, false, false) - , mLeftSubtree(NULL) - , mRightSubtree(NULL) - , mGraph(graph) {} - void build(TIntermNode* intermNode) { intermNode->traverse(this); } + TDependencyGraphBuilder(TDependencyGraph *graph) + : TIntermTraverser(true, false, false), + mLeftSubtree(NULL), + mRightSubtree(NULL), + mGraph(graph) {} + void build(TIntermNode *intermNode) { intermNode->traverse(this); } - void connectMultipleNodesToSingleNode(TParentNodeSet* nodes, TGraphNode* node) const; + void connectMultipleNodesToSingleNode( + TParentNodeSet *nodes, TGraphNode *node) const; - void visitAssignment(TIntermBinary*); - void visitLogicalOp(TIntermBinary*); - void visitBinaryChildren(TIntermBinary*); - void visitFunctionDefinition(TIntermAggregate*); - void visitFunctionCall(TIntermAggregate* intermFunctionCall); - void visitAggregateChildren(TIntermAggregate*); + void visitAssignment(TIntermBinary *); + void visitLogicalOp(TIntermBinary *); + void visitBinaryChildren(TIntermBinary *); + void visitFunctionDefinition(TIntermAggregate *); + void visitFunctionCall(TIntermAggregate *intermFunctionCall); + void visitAggregateChildren(TIntermAggregate *); TGraphSymbol mLeftSubtree; TGraphSymbol mRightSubtree; - TDependencyGraph* mGraph; + TDependencyGraph *mGraph; TNodeSetStack mNodeSets; TSymbolStack mLeftmostSymbols; }; -#endif // COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H +#endif // COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H diff --git a/gfx/angle/src/compiler/translator/generate_parser.sh b/gfx/angle/src/compiler/translator/generate_parser.sh old mode 100755 new mode 100644 diff --git a/gfx/angle/src/compiler/translator/glslang.y b/gfx/angle/src/compiler/translator/glslang.y index 304e4a927fa9..5c945ad5adc6 100644 --- a/gfx/angle/src/compiler/translator/glslang.y +++ b/gfx/angle/src/compiler/translator/glslang.y @@ -34,6 +34,7 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h). #pragma warning(disable: 4701) #endif +#include "angle_gl.h" #include "compiler/translator/SymbolTable.h" #include "compiler/translator/ParseContext.h" #include "GLSLANG/ShaderLang.h" @@ -106,14 +107,14 @@ extern void yyerror(YYLTYPE* yylloc, TParseContext* context, const char* reason) } while (0) #define VERTEX_ONLY(S, L) { \ - if (context->shaderType != SH_VERTEX_SHADER) { \ + if (context->shaderType != GL_VERTEX_SHADER) { \ context->error(L, " supported in vertex shaders only ", S); \ context->recover(); \ } \ } #define FRAG_ONLY(S, L) { \ - if (context->shaderType != SH_FRAGMENT_SHADER) { \ + if (context->shaderType != GL_FRAGMENT_SHADER) { \ context->error(L, " supported in fragment shaders only ", S); \ context->recover(); \ } \ @@ -208,38 +209,7 @@ identifier variable_identifier : IDENTIFIER { // The symbol table search was done in the lexical phase - const TSymbol *symbol = $1.symbol; - const TVariable *variable = 0; - - if (!symbol) - { - context->error(@1, "undeclared identifier", $1.string->c_str()); - context->recover(); - } - else if (!symbol->isVariable()) - { - context->error(@1, "variable expected", $1.string->c_str()); - context->recover(); - } - else - { - variable = static_cast(symbol); - - if (context->symbolTable.findBuiltIn(variable->getName(), context->shaderVersion) && - !variable->getExtension().empty() && - context->extensionErrorCheck(@1, variable->getExtension())) - { - context->recover(); - } - } - - if (!variable) - { - TType type(EbtFloat, EbpUndefined); - TVariable *fakeVariable = new TVariable($1.string, type); - context->symbolTable.declare(*fakeVariable); - variable = fakeVariable; - } + const TVariable *variable = context->getNamedVariable(@1, $1.string, $1.symbol); if (variable->getType().getQualifier() == EvqConst) { @@ -411,7 +381,7 @@ function_call for (size_t i = 0; i < fnCandidate->getParamCount(); ++i) { qual = fnCandidate->getParam(i).type->getQualifier(); if (qual == EvqOut || qual == EvqInOut) { - if (context->lValueErrorCheck($$->getLine(), "assign", $$->getAsAggregate()->getSequence()[i]->getAsTyped())) { + if (context->lValueErrorCheck($$->getLine(), "assign", (*($$->getAsAggregate()->getSequence()))[i]->getAsTyped())) { context->error($1.intermNode->getLine(), "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error"); context->recover(); } @@ -815,12 +785,13 @@ declaration context->symbolTable.pop(); } | init_declarator_list SEMICOLON { - if ($1.intermAggregate) - $1.intermAggregate->setOp(EOpDeclaration); - $$ = $1.intermAggregate; + TIntermAggregate *aggNode = $1.intermAggregate; + if (aggNode && aggNode->getOp() == EOpNull) + aggNode->setOp(EOpDeclaration); + $$ = aggNode; } | PRECISION precision_qualifier type_specifier_no_prec SEMICOLON { - if (($2 == EbpHigh) && (context->shaderType == SH_FRAGMENT_SHADER) && !context->fragmentPrecisionHigh) { + if (($2 == EbpHigh) && (context->shaderType == GL_FRAGMENT_SHADER) && !context->fragmentPrecisionHigh) { context->error(@1, "precision is not supported in fragment shader", "highp"); context->recover(); } @@ -887,7 +858,8 @@ function_prototype else { // Insert the unmangled name to detect potential future redefinition as a variable. - context->symbolTable.getOuterLevel()->insert($1->getName(), *$1); + TFunction *function = new TFunction(NewPoolTString($1->getName().c_str()), $1->getReturnType()); + context->symbolTable.getOuterLevel()->insert(function); } // @@ -899,7 +871,7 @@ function_prototype // We're at the inner scope level of the function's arguments and body statement. // Add the function prototype to the surrounding scope instead. - context->symbolTable.getOuterLevel()->insert(*$$.function); + context->symbolTable.getOuterLevel()->insert($$.function); } ; @@ -1100,22 +1072,8 @@ single_declaration $$.intermAggregate = context->parseSingleInitDeclaration($$.type, @2, *$2.string, @3, $4); } | INVARIANT IDENTIFIER { - VERTEX_ONLY("invariant declaration", @1); - if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "invariant varying")) - context->recover(); - $$.type.setBasic(EbtInvariant, EvqInvariantVaryingOut, @2); - if (!$2.symbol) - { - 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); - $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2); - } + // $$.type is not used in invariant declarations. + $$.intermAggregate = context->parseInvariantDeclaration(@1, @2, $2.string, $2.symbol); } ; @@ -1161,7 +1119,7 @@ type_qualifier ES2_ONLY("varying", @1); if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "varying")) context->recover(); - if (context->shaderType == SH_VERTEX_SHADER) + if (context->shaderType == GL_VERTEX_SHADER) $$.setBasic(EbtVoid, EvqVaryingOut, @1); else $$.setBasic(EbtVoid, EvqVaryingIn, @1); @@ -1170,7 +1128,7 @@ type_qualifier ES2_ONLY("varying", @1); if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "invariant varying")) context->recover(); - if (context->shaderType == SH_VERTEX_SHADER) + if (context->shaderType == GL_VERTEX_SHADER) $$.setBasic(EbtVoid, EvqInvariantVaryingOut, @1); else $$.setBasic(EbtVoid, EvqInvariantVaryingIn, @1); @@ -1209,29 +1167,29 @@ storage_qualifier } | IN_QUAL { ES3_ONLY("in", @1, "storage qualifier"); - $$.qualifier = (context->shaderType == SH_FRAGMENT_SHADER) ? EvqFragmentIn : EvqVertexIn; + $$.qualifier = (context->shaderType == GL_FRAGMENT_SHADER) ? EvqFragmentIn : EvqVertexIn; } | OUT_QUAL { ES3_ONLY("out", @1, "storage qualifier"); - $$.qualifier = (context->shaderType == SH_FRAGMENT_SHADER) ? EvqFragmentOut : EvqVertexOut; + $$.qualifier = (context->shaderType == GL_FRAGMENT_SHADER) ? EvqFragmentOut : EvqVertexOut; } | CENTROID IN_QUAL { ES3_ONLY("centroid in", @1, "storage qualifier"); - if (context->shaderType == SH_VERTEX_SHADER) + if (context->shaderType == GL_VERTEX_SHADER) { context->error(@1, "invalid storage qualifier", "it is an error to use 'centroid in' in the vertex shader"); context->recover(); } - $$.qualifier = (context->shaderType == SH_FRAGMENT_SHADER) ? EvqCentroidIn : EvqVertexIn; + $$.qualifier = (context->shaderType == GL_FRAGMENT_SHADER) ? EvqCentroidIn : EvqVertexIn; } | CENTROID OUT_QUAL { ES3_ONLY("centroid out", @1, "storage qualifier"); - if (context->shaderType == SH_FRAGMENT_SHADER) + if (context->shaderType == GL_FRAGMENT_SHADER) { context->error(@1, "invalid storage qualifier", "it is an error to use 'centroid out' in the fragment shader"); context->recover(); } - $$.qualifier = (context->shaderType == SH_FRAGMENT_SHADER) ? EvqFragmentOut : EvqCentroidOut; + $$.qualifier = (context->shaderType == GL_FRAGMENT_SHADER) ? EvqFragmentOut : EvqCentroidOut; } | UNIFORM { if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "uniform")) @@ -1255,7 +1213,7 @@ type_specifier $$ = $2; $$.precision = $1; - if (!SupportsPrecision($2.type) { + if (!SupportsPrecision($2.type)) { context->error(@1, "illegal type for precision qualifier", getBasicString($2.type)); context->recover(); } @@ -1899,7 +1857,7 @@ function_definition // // Insert the parameters with name in the symbol table. // - if (! context->symbolTable.declare(*variable)) { + if (! context->symbolTable.declare(variable)) { context->error(@1, "redefinition", variable->getName().c_str()); context->recover(); delete variable; diff --git a/gfx/angle/src/compiler/translator/glslang_tab.cpp b/gfx/angle/src/compiler/translator/glslang_tab.cpp index 4743696d8bd2..6d483b12ec03 100644 --- a/gfx/angle/src/compiler/translator/glslang_tab.cpp +++ b/gfx/angle/src/compiler/translator/glslang_tab.cpp @@ -84,6 +84,7 @@ #pragma warning(disable: 4701) #endif +#include "angle_gl.h" #include "compiler/translator/SymbolTable.h" #include "compiler/translator/ParseContext.h" #include "GLSLANG/ShaderLang.h" @@ -362,14 +363,14 @@ extern void yyerror(YYLTYPE* yylloc, TParseContext* context, const char* reason) } while (0) #define VERTEX_ONLY(S, L) { \ - if (context->shaderType != SH_VERTEX_SHADER) { \ + if (context->shaderType != GL_VERTEX_SHADER) { \ context->error(L, " supported in vertex shaders only ", S); \ context->recover(); \ } \ } #define FRAG_ONLY(S, L) { \ - if (context->shaderType != SH_FRAGMENT_SHADER) { \ + if (context->shaderType != GL_FRAGMENT_SHADER) { \ context->error(L, " supported in fragment shaders only ", S); \ context->recover(); \ } \ @@ -794,32 +795,32 @@ static const yytype_int16 yyrhs[] = /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { - 0, 205, 205, 206, 209, 264, 267, 272, 277, 282, - 287, 293, 296, 299, 302, 305, 315, 328, 336, 436, - 439, 447, 450, 456, 460, 467, 473, 482, 490, 493, - 503, 506, 516, 526, 547, 548, 549, 554, 555, 563, - 574, 575, 583, 594, 598, 599, 609, 619, 629, 642, - 643, 653, 666, 670, 674, 678, 679, 692, 693, 706, - 707, 720, 721, 738, 739, 752, 753, 754, 755, 756, - 760, 763, 774, 782, 790, 817, 822, 833, 837, 841, - 845, 852, 907, 910, 917, 925, 946, 967, 977, 1005, - 1010, 1020, 1025, 1035, 1038, 1041, 1044, 1050, 1057, 1060, - 1064, 1068, 1072, 1079, 1083, 1087, 1094, 1098, 1102, 1123, - 1132, 1138, 1141, 1147, 1153, 1160, 1169, 1178, 1186, 1189, - 1196, 1200, 1207, 1210, 1214, 1218, 1227, 1236, 1244, 1254, - 1261, 1264, 1267, 1273, 1280, 1283, 1289, 1292, 1295, 1301, - 1304, 1319, 1323, 1327, 1331, 1335, 1339, 1344, 1349, 1354, - 1359, 1364, 1369, 1374, 1379, 1384, 1389, 1394, 1399, 1404, - 1409, 1414, 1419, 1424, 1429, 1434, 1439, 1444, 1448, 1452, - 1456, 1460, 1464, 1468, 1472, 1476, 1480, 1484, 1488, 1492, - 1496, 1500, 1504, 1512, 1520, 1524, 1537, 1537, 1540, 1540, - 1546, 1549, 1565, 1568, 1577, 1581, 1587, 1594, 1609, 1613, - 1617, 1618, 1624, 1625, 1626, 1627, 1628, 1632, 1633, 1633, - 1633, 1643, 1644, 1648, 1648, 1649, 1649, 1654, 1657, 1667, - 1670, 1676, 1677, 1681, 1689, 1693, 1703, 1708, 1725, 1725, - 1730, 1730, 1737, 1737, 1745, 1748, 1754, 1757, 1763, 1767, - 1774, 1781, 1788, 1795, 1806, 1815, 1819, 1826, 1829, 1835, - 1835 + 0, 206, 206, 207, 210, 234, 237, 242, 247, 252, + 257, 263, 266, 269, 272, 275, 285, 298, 306, 406, + 409, 417, 420, 426, 430, 437, 443, 452, 460, 463, + 473, 476, 486, 496, 517, 518, 519, 524, 525, 533, + 544, 545, 553, 564, 568, 569, 579, 589, 599, 612, + 613, 623, 636, 640, 644, 648, 649, 662, 663, 676, + 677, 690, 691, 708, 709, 722, 723, 724, 725, 726, + 730, 733, 744, 752, 760, 787, 793, 804, 808, 812, + 816, 823, 879, 882, 889, 897, 918, 939, 949, 977, + 982, 992, 997, 1007, 1010, 1013, 1016, 1022, 1029, 1032, + 1036, 1040, 1044, 1051, 1055, 1059, 1066, 1070, 1074, 1081, + 1090, 1096, 1099, 1105, 1111, 1118, 1127, 1136, 1144, 1147, + 1154, 1158, 1165, 1168, 1172, 1176, 1185, 1194, 1202, 1212, + 1224, 1227, 1230, 1236, 1243, 1246, 1252, 1255, 1258, 1264, + 1267, 1282, 1286, 1290, 1294, 1298, 1302, 1307, 1312, 1317, + 1322, 1327, 1332, 1337, 1342, 1347, 1352, 1357, 1362, 1367, + 1372, 1377, 1382, 1387, 1392, 1397, 1402, 1407, 1411, 1415, + 1419, 1423, 1427, 1431, 1435, 1439, 1443, 1447, 1451, 1455, + 1459, 1463, 1467, 1475, 1483, 1487, 1500, 1500, 1503, 1503, + 1509, 1512, 1528, 1531, 1540, 1544, 1550, 1557, 1572, 1576, + 1580, 1581, 1587, 1588, 1589, 1590, 1591, 1595, 1596, 1596, + 1596, 1606, 1607, 1611, 1611, 1612, 1612, 1617, 1620, 1630, + 1633, 1639, 1640, 1644, 1652, 1656, 1666, 1671, 1688, 1688, + 1693, 1693, 1700, 1700, 1708, 1711, 1717, 1720, 1726, 1730, + 1737, 1744, 1751, 1758, 1769, 1778, 1782, 1789, 1792, 1798, + 1798 }; #endif @@ -2546,38 +2547,7 @@ yyreduce: { // The symbol table search was done in the lexical phase - const TSymbol *symbol = (yyvsp[(1) - (1)].lex).symbol; - const TVariable *variable = 0; - - if (!symbol) - { - context->error((yylsp[(1) - (1)]), "undeclared identifier", (yyvsp[(1) - (1)].lex).string->c_str()); - context->recover(); - } - else if (!symbol->isVariable()) - { - context->error((yylsp[(1) - (1)]), "variable expected", (yyvsp[(1) - (1)].lex).string->c_str()); - context->recover(); - } - else - { - variable = static_cast(symbol); - - if (context->symbolTable.findBuiltIn(variable->getName(), context->shaderVersion) && - !variable->getExtension().empty() && - context->extensionErrorCheck((yylsp[(1) - (1)]), variable->getExtension())) - { - context->recover(); - } - } - - if (!variable) - { - TType type(EbtFloat, EbpUndefined); - TVariable *fakeVariable = new TVariable((yyvsp[(1) - (1)].lex).string, type); - context->symbolTable.declare(*fakeVariable); - variable = fakeVariable; - } + const TVariable *variable = context->getNamedVariable((yylsp[(1) - (1)]), (yyvsp[(1) - (1)].lex).string, (yyvsp[(1) - (1)].lex).symbol); if (variable->getType().getQualifier() == EvqConst) { @@ -2793,7 +2763,7 @@ yyreduce: for (size_t i = 0; i < fnCandidate->getParamCount(); ++i) { qual = fnCandidate->getParam(i).type->getQualifier(); if (qual == EvqOut || qual == EvqInOut) { - if (context->lValueErrorCheck((yyval.interm.intermTypedNode)->getLine(), "assign", (yyval.interm.intermTypedNode)->getAsAggregate()->getSequence()[i]->getAsTyped())) { + if (context->lValueErrorCheck((yyval.interm.intermTypedNode)->getLine(), "assign", (*((yyval.interm.intermTypedNode)->getAsAggregate()->getSequence()))[i]->getAsTyped())) { context->error((yyvsp[(1) - (1)].interm).intermNode->getLine(), "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error"); context->recover(); } @@ -3343,16 +3313,17 @@ yyreduce: case 75: { - if ((yyvsp[(1) - (2)].interm).intermAggregate) - (yyvsp[(1) - (2)].interm).intermAggregate->setOp(EOpDeclaration); - (yyval.interm.intermNode) = (yyvsp[(1) - (2)].interm).intermAggregate; + TIntermAggregate *aggNode = (yyvsp[(1) - (2)].interm).intermAggregate; + if (aggNode && aggNode->getOp() == EOpNull) + aggNode->setOp(EOpDeclaration); + (yyval.interm.intermNode) = aggNode; } break; case 76: { - if (((yyvsp[(2) - (4)].interm.precision) == EbpHigh) && (context->shaderType == SH_FRAGMENT_SHADER) && !context->fragmentPrecisionHigh) { + if (((yyvsp[(2) - (4)].interm.precision) == EbpHigh) && (context->shaderType == GL_FRAGMENT_SHADER) && !context->fragmentPrecisionHigh) { context->error((yylsp[(1) - (4)]), "precision is not supported in fragment shader", "highp"); context->recover(); } @@ -3436,7 +3407,8 @@ yyreduce: 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)); + TFunction *function = new TFunction(NewPoolTString((yyvsp[(1) - (2)].interm.function)->getName().c_str()), (yyvsp[(1) - (2)].interm.function)->getReturnType()); + context->symbolTable.getOuterLevel()->insert(function); } // @@ -3448,7 +3420,7 @@ yyreduce: // We're at the inner scope level of the function's arguments and body statement. // Add the function prototype to the surrounding scope instead. - context->symbolTable.getOuterLevel()->insert(*(yyval.interm).function); + context->symbolTable.getOuterLevel()->insert((yyval.interm).function); } break; @@ -3717,22 +3689,8 @@ yyreduce: case 108: { - 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, (yylsp[(2) - (2)])); - if (!(yyvsp[(2) - (2)].lex).symbol) - { - 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), (yylsp[(2) - (2)])); - (yyval.interm).intermAggregate = context->intermediate.makeAggregate(symbol, (yylsp[(2) - (2)])); - } + // $$.type is not used in invariant declarations. + (yyval.interm).intermAggregate = context->parseInvariantDeclaration((yylsp[(1) - (2)]), (yylsp[(2) - (2)]), (yyvsp[(2) - (2)].lex).string, (yyvsp[(2) - (2)].lex).symbol); } break; @@ -3794,7 +3752,7 @@ yyreduce: ES2_ONLY("varying", (yylsp[(1) - (1)])); if (context->globalErrorCheck((yylsp[(1) - (1)]), context->symbolTable.atGlobalLevel(), "varying")) context->recover(); - if (context->shaderType == SH_VERTEX_SHADER) + if (context->shaderType == GL_VERTEX_SHADER) (yyval.interm.type).setBasic(EbtVoid, EvqVaryingOut, (yylsp[(1) - (1)])); else (yyval.interm.type).setBasic(EbtVoid, EvqVaryingIn, (yylsp[(1) - (1)])); @@ -3807,7 +3765,7 @@ yyreduce: ES2_ONLY("varying", (yylsp[(1) - (2)])); if (context->globalErrorCheck((yylsp[(1) - (2)]), context->symbolTable.atGlobalLevel(), "invariant varying")) context->recover(); - if (context->shaderType == SH_VERTEX_SHADER) + if (context->shaderType == GL_VERTEX_SHADER) (yyval.interm.type).setBasic(EbtVoid, EvqInvariantVaryingOut, (yylsp[(1) - (2)])); else (yyval.interm.type).setBasic(EbtVoid, EvqInvariantVaryingIn, (yylsp[(1) - (2)])); @@ -3871,7 +3829,7 @@ yyreduce: { ES3_ONLY("in", (yylsp[(1) - (1)]), "storage qualifier"); - (yyval.interm.type).qualifier = (context->shaderType == SH_FRAGMENT_SHADER) ? EvqFragmentIn : EvqVertexIn; + (yyval.interm.type).qualifier = (context->shaderType == GL_FRAGMENT_SHADER) ? EvqFragmentIn : EvqVertexIn; } break; @@ -3879,7 +3837,7 @@ yyreduce: { ES3_ONLY("out", (yylsp[(1) - (1)]), "storage qualifier"); - (yyval.interm.type).qualifier = (context->shaderType == SH_FRAGMENT_SHADER) ? EvqFragmentOut : EvqVertexOut; + (yyval.interm.type).qualifier = (context->shaderType == GL_FRAGMENT_SHADER) ? EvqFragmentOut : EvqVertexOut; } break; @@ -3887,12 +3845,12 @@ yyreduce: { ES3_ONLY("centroid in", (yylsp[(1) - (2)]), "storage qualifier"); - if (context->shaderType == SH_VERTEX_SHADER) + if (context->shaderType == GL_VERTEX_SHADER) { context->error((yylsp[(1) - (2)]), "invalid storage qualifier", "it is an error to use 'centroid in' in the vertex shader"); context->recover(); } - (yyval.interm.type).qualifier = (context->shaderType == SH_FRAGMENT_SHADER) ? EvqCentroidIn : EvqVertexIn; + (yyval.interm.type).qualifier = (context->shaderType == GL_FRAGMENT_SHADER) ? EvqCentroidIn : EvqVertexIn; } break; @@ -3900,12 +3858,12 @@ yyreduce: { ES3_ONLY("centroid out", (yylsp[(1) - (2)]), "storage qualifier"); - if (context->shaderType == SH_FRAGMENT_SHADER) + if (context->shaderType == GL_FRAGMENT_SHADER) { context->error((yylsp[(1) - (2)]), "invalid storage qualifier", "it is an error to use 'centroid out' in the fragment shader"); context->recover(); } - (yyval.interm.type).qualifier = (context->shaderType == SH_FRAGMENT_SHADER) ? EvqFragmentOut : EvqCentroidOut; + (yyval.interm.type).qualifier = (context->shaderType == GL_FRAGMENT_SHADER) ? EvqFragmentOut : EvqCentroidOut; } break; @@ -3939,7 +3897,7 @@ yyreduce: (yyval.interm.type).precision = (yyvsp[(1) - (2)].interm.precision); if (!SupportsPrecision((yyvsp[(2) - (2)].interm.type).type)) { - context->error((yylsp[(1) - (1)]), "illegal type for precision qualifier", getBasicString((yyvsp[(2) - (2)].interm.type).type)); + context->error((yylsp[(1) - (2)]), "illegal type for precision qualifier", getBasicString((yyvsp[(2) - (2)].interm.type).type)); context->recover(); } } @@ -4967,7 +4925,7 @@ yyreduce: // // Insert the parameters with name in the symbol table. // - if (! context->symbolTable.declare(*variable)) { + if (! context->symbolTable.declare(variable)) { context->error((yylsp[(1) - (1)]), "redefinition", variable->getName().c_str()); context->recover(); delete variable; diff --git a/gfx/angle/src/compiler/translator/intermOut.cpp b/gfx/angle/src/compiler/translator/intermOut.cpp index 7f94ac31416b..56340c6f9e70 100644 --- a/gfx/angle/src/compiler/translator/intermOut.cpp +++ b/gfx/angle/src/compiler/translator/intermOut.cpp @@ -1,12 +1,15 @@ // -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2014 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/translator/localintermediate.h" +#include "compiler/translator/Intermediate.h" #include "compiler/translator/SymbolTable.h" +namespace +{ + // // Two purposes: // 1. Show an example of how to iterate tree. Functions can @@ -20,22 +23,40 @@ // Use this class to carry along data from node to node in // the traversal // -class TOutputTraverser : public TIntermTraverser { -public: - TOutputTraverser(TInfoSinkBase& i) : sink(i) { } +class TOutputTraverser : public TIntermTraverser +{ + public: + TOutputTraverser(TInfoSinkBase &i) + : sink(i) { } TInfoSinkBase& sink; -protected: - void visitSymbol(TIntermSymbol*); - void visitConstantUnion(TIntermConstantUnion*); - bool visitBinary(Visit visit, TIntermBinary*); - bool visitUnary(Visit visit, TIntermUnary*); - bool visitSelection(Visit visit, TIntermSelection*); - bool visitAggregate(Visit visit, TIntermAggregate*); - bool visitLoop(Visit visit, TIntermLoop*); - bool visitBranch(Visit visit, TIntermBranch*); + protected: + void visitSymbol(TIntermSymbol *); + void visitConstantUnion(TIntermConstantUnion *); + bool visitBinary(Visit visit, TIntermBinary *); + bool visitUnary(Visit visit, TIntermUnary *); + bool visitSelection(Visit visit, TIntermSelection *); + bool visitAggregate(Visit visit, TIntermAggregate *); + bool visitLoop(Visit visit, TIntermLoop *); + bool visitBranch(Visit visit, TIntermBranch *); }; +// +// Helper functions for printing, not part of traversing. +// +void OutputTreeText(TInfoSinkBase &sink, TIntermNode *node, const int depth) +{ + int i; + + sink.location(node->getLine()); + + for (i = 0; i < depth; ++i) + sink << " "; +} + +} // namespace anonymous + + TString TType::getCompleteString() const { TStringStream stream; @@ -53,20 +74,6 @@ TString TType::getCompleteString() const return stream.str(); } -// -// Helper functions for printing, not part of traversing. -// - -void OutputTreeText(TInfoSinkBase& sink, TIntermNode* node, const int depth) -{ - int i; - - sink.location(node->getLine()); - - for (i = 0; i < depth; ++i) - sink << " "; -} - // // The rest of the file are the traversal functions. The last one // is the one that starts the traversal. @@ -76,58 +83,126 @@ void OutputTreeText(TInfoSinkBase& sink, TIntermNode* node, const int depth) // return false. // -void TOutputTraverser::visitSymbol(TIntermSymbol* node) +void TOutputTraverser::visitSymbol(TIntermSymbol *node) { - OutputTreeText(sink, node, depth); + OutputTreeText(sink, node, mDepth); sink << "'" << node->getSymbol() << "' "; sink << "(" << node->getCompleteString() << ")\n"; } -bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary* node) +bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node) { TInfoSinkBase& out = sink; - OutputTreeText(out, node, depth); + OutputTreeText(out, node, mDepth); - switch (node->getOp()) { - case EOpAssign: out << "move second child to first child"; break; - case EOpInitialize: out << "initialize first child with second child"; break; - case EOpAddAssign: out << "add second child into first child"; break; - case EOpSubAssign: out << "subtract second child into first child"; break; - case EOpMulAssign: out << "multiply second child into first child"; break; - case EOpVectorTimesMatrixAssign: out << "matrix mult second child into first child"; break; - case EOpVectorTimesScalarAssign: out << "vector scale second child into first child"; break; - case EOpMatrixTimesScalarAssign: out << "matrix scale second child into first child"; break; - case EOpMatrixTimesMatrixAssign: out << "matrix mult second child into first child"; break; - case EOpDivAssign: out << "divide second child into first child"; break; - case EOpIndexDirect: out << "direct index"; break; - case EOpIndexIndirect: out << "indirect index"; break; - case EOpIndexDirectStruct: out << "direct index for structure"; break; - case EOpIndexDirectInterfaceBlock: out << "direct index for interface block"; break; - case EOpVectorSwizzle: out << "vector swizzle"; break; + switch (node->getOp()) + { + case EOpAssign: + out << "move second child to first child"; + break; + case EOpInitialize: + out << "initialize first child with second child"; + break; + case EOpAddAssign: + out << "add second child into first child"; + break; + case EOpSubAssign: + out << "subtract second child into first child"; + break; + case EOpMulAssign: + out << "multiply second child into first child"; + break; + case EOpVectorTimesMatrixAssign: + out << "matrix mult second child into first child"; + break; + case EOpVectorTimesScalarAssign: + out << "vector scale second child into first child"; + break; + case EOpMatrixTimesScalarAssign: + out << "matrix scale second child into first child"; + break; + case EOpMatrixTimesMatrixAssign: + out << "matrix mult second child into first child"; + break; + case EOpDivAssign: + out << "divide second child into first child"; + break; + case EOpIndexDirect: + out << "direct index"; + break; + case EOpIndexIndirect: + out << "indirect index"; + break; + case EOpIndexDirectStruct: + out << "direct index for structure"; + break; + case EOpIndexDirectInterfaceBlock: + out << "direct index for interface block"; + break; + case EOpVectorSwizzle: + out << "vector swizzle"; + break; - case EOpAdd: out << "add"; break; - case EOpSub: out << "subtract"; break; - case EOpMul: out << "component-wise multiply"; break; - case EOpDiv: out << "divide"; break; - case EOpEqual: out << "Compare Equal"; break; - case EOpNotEqual: out << "Compare Not Equal"; break; - case EOpLessThan: out << "Compare Less Than"; break; - case EOpGreaterThan: out << "Compare Greater Than"; break; - case EOpLessThanEqual: out << "Compare Less Than or Equal"; break; - case EOpGreaterThanEqual: out << "Compare Greater Than or Equal"; break; + case EOpAdd: + out << "add"; + break; + case EOpSub: + out << "subtract"; + break; + case EOpMul: + out << "component-wise multiply"; + break; + case EOpDiv: + out << "divide"; + break; + case EOpEqual: + out << "Compare Equal"; + break; + case EOpNotEqual: + out << "Compare Not Equal"; + break; + case EOpLessThan: + out << "Compare Less Than"; + break; + case EOpGreaterThan: + out << "Compare Greater Than"; + break; + case EOpLessThanEqual: + out << "Compare Less Than or Equal"; + break; + case EOpGreaterThanEqual: + out << "Compare Greater Than or Equal"; + break; - case EOpVectorTimesScalar: out << "vector-scale"; break; - case EOpVectorTimesMatrix: out << "vector-times-matrix"; break; - case EOpMatrixTimesVector: out << "matrix-times-vector"; break; - case EOpMatrixTimesScalar: out << "matrix-scale"; break; - case EOpMatrixTimesMatrix: out << "matrix-multiply"; break; + case EOpVectorTimesScalar: + out << "vector-scale"; + break; + case EOpVectorTimesMatrix: + out << "vector-times-matrix"; + break; + case EOpMatrixTimesVector: + out << "matrix-times-vector"; + break; + case EOpMatrixTimesScalar: + out << "matrix-scale"; + break; + case EOpMatrixTimesMatrix: + out << "matrix-multiply"; + break; - case EOpLogicalOr: out << "logical-or"; break; - case EOpLogicalXor: out << "logical-xor"; break; - case EOpLogicalAnd: out << "logical-and"; break; - default: out << ""; + case EOpLogicalOr: + out << "logical-or"; + break; + case EOpLogicalXor: + out << "logical-xor"; + break; + case EOpLogicalAnd: + out << "logical-and"; + break; + default: + out << ""; } out << " (" << node->getCompleteString() << ")"; @@ -137,68 +212,57 @@ bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary* node) return true; } -bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary* node) +bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node) { TInfoSinkBase& out = sink; - OutputTreeText(out, node, depth); + OutputTreeText(out, node, mDepth); - switch (node->getOp()) { - case EOpNegative: out << "Negate value"; break; - case EOpVectorLogicalNot: - case EOpLogicalNot: out << "Negate conditional"; break; + switch (node->getOp()) + { + case EOpNegative: out << "Negate value"; break; + case EOpVectorLogicalNot: + case EOpLogicalNot: out << "Negate conditional"; break; - case EOpPostIncrement: out << "Post-Increment"; break; - case EOpPostDecrement: out << "Post-Decrement"; break; - case EOpPreIncrement: out << "Pre-Increment"; break; - case EOpPreDecrement: out << "Pre-Decrement"; break; + case EOpPostIncrement: out << "Post-Increment"; break; + case EOpPostDecrement: out << "Post-Decrement"; break; + case EOpPreIncrement: out << "Pre-Increment"; break; + case EOpPreDecrement: out << "Pre-Decrement"; break; - case EOpConvIntToBool: out << "Convert int to bool"; break; - case EOpConvUIntToBool: out << "Convert uint to bool"; break; - case EOpConvFloatToBool:out << "Convert float to bool";break; - case EOpConvBoolToFloat:out << "Convert bool to float";break; - case EOpConvIntToFloat: out << "Convert int to float"; break; - case EOpConvUIntToFloat:out << "Convert uint to float";break; - case EOpConvFloatToInt: out << "Convert float to int"; break; - case EOpConvBoolToInt: out << "Convert bool to int"; break; - case EOpConvIntToUInt: out << "Convert int to uint"; break; - case EOpConvFloatToUInt:out << "Convert float to uint";break; - case EOpConvBoolToUInt: out << "Convert bool to uint"; break; + case EOpRadians: out << "radians"; break; + case EOpDegrees: out << "degrees"; break; + case EOpSin: out << "sine"; break; + case EOpCos: out << "cosine"; break; + case EOpTan: out << "tangent"; break; + case EOpAsin: out << "arc sine"; break; + case EOpAcos: out << "arc cosine"; break; + case EOpAtan: out << "arc tangent"; break; - case EOpRadians: out << "radians"; break; - case EOpDegrees: out << "degrees"; break; - case EOpSin: out << "sine"; break; - case EOpCos: out << "cosine"; break; - case EOpTan: out << "tangent"; break; - case EOpAsin: out << "arc sine"; break; - case EOpAcos: out << "arc cosine"; break; - case EOpAtan: out << "arc tangent"; break; + case EOpExp: out << "exp"; break; + case EOpLog: out << "log"; break; + case EOpExp2: out << "exp2"; break; + case EOpLog2: out << "log2"; break; + case EOpSqrt: out << "sqrt"; break; + case EOpInverseSqrt: out << "inverse sqrt"; break; - case EOpExp: out << "exp"; break; - case EOpLog: out << "log"; break; - case EOpExp2: out << "exp2"; break; - case EOpLog2: out << "log2"; break; - case EOpSqrt: out << "sqrt"; break; - case EOpInverseSqrt: out << "inverse sqrt"; break; + case EOpAbs: out << "Absolute value"; break; + case EOpSign: out << "Sign"; break; + case EOpFloor: out << "Floor"; break; + case EOpCeil: out << "Ceiling"; break; + case EOpFract: out << "Fraction"; break; - case EOpAbs: out << "Absolute value"; break; - case EOpSign: out << "Sign"; break; - case EOpFloor: out << "Floor"; break; - case EOpCeil: out << "Ceiling"; break; - case EOpFract: out << "Fraction"; break; + case EOpLength: out << "length"; break; + case EOpNormalize: out << "normalize"; break; + // case EOpDPdx: out << "dPdx"; break; + // case EOpDPdy: out << "dPdy"; break; + // case EOpFwidth: out << "fwidth"; break; - case EOpLength: out << "length"; break; - case EOpNormalize: out << "normalize"; break; - // case EOpDPdx: out << "dPdx"; break; - // case EOpDPdy: out << "dPdy"; break; - // case EOpFwidth: out << "fwidth"; break; + case EOpAny: out << "any"; break; + case EOpAll: out << "all"; break; - case EOpAny: out << "any"; break; - case EOpAll: out << "all"; break; - - default: - out.prefix(EPrefixError); - out << "Bad unary op"; + default: + out.prefix(EPrefixError); + out << "Bad unary op"; } out << " (" << node->getCompleteString() << ")"; @@ -208,78 +272,81 @@ bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary* node) return true; } -bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate* node) +bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node) { - TInfoSinkBase& out = sink; + TInfoSinkBase &out = sink; - if (node->getOp() == EOpNull) { + if (node->getOp() == EOpNull) + { out.prefix(EPrefixError); out << "node is still EOpNull!"; return true; } - OutputTreeText(out, node, depth); + OutputTreeText(out, node, mDepth); - switch (node->getOp()) { - case EOpSequence: out << "Sequence\n"; return true; - case EOpComma: out << "Comma\n"; return true; - case EOpFunction: out << "Function Definition: " << node->getName(); break; - case EOpFunctionCall: out << "Function Call: " << node->getName(); break; - case EOpParameters: out << "Function Parameters: "; break; + switch (node->getOp()) + { + case EOpSequence: out << "Sequence\n"; return true; + case EOpComma: out << "Comma\n"; return true; + case EOpFunction: out << "Function Definition: " << node->getName(); break; + case EOpFunctionCall: out << "Function Call: " << node->getName(); break; + case EOpParameters: out << "Function Parameters: "; break; - case EOpConstructFloat: out << "Construct float"; break; - case EOpConstructVec2: out << "Construct vec2"; break; - case EOpConstructVec3: out << "Construct vec3"; break; - case EOpConstructVec4: out << "Construct vec4"; break; - case EOpConstructBool: out << "Construct bool"; break; - case EOpConstructBVec2: out << "Construct bvec2"; break; - case EOpConstructBVec3: out << "Construct bvec3"; break; - case EOpConstructBVec4: out << "Construct bvec4"; break; - case EOpConstructInt: out << "Construct int"; break; - case EOpConstructIVec2: out << "Construct ivec2"; break; - case EOpConstructIVec3: out << "Construct ivec3"; break; - case EOpConstructIVec4: out << "Construct ivec4"; break; - case EOpConstructUInt: out << "Construct uint"; break; - case EOpConstructUVec2: out << "Construct uvec2"; break; - case EOpConstructUVec3: out << "Construct uvec3"; break; - case EOpConstructUVec4: out << "Construct uvec4"; break; - case EOpConstructMat2: out << "Construct mat2"; break; - case EOpConstructMat3: out << "Construct mat3"; break; - case EOpConstructMat4: out << "Construct mat4"; break; - case EOpConstructStruct: out << "Construct structure"; break; + case EOpConstructFloat: out << "Construct float"; break; + case EOpConstructVec2: out << "Construct vec2"; break; + case EOpConstructVec3: out << "Construct vec3"; break; + case EOpConstructVec4: out << "Construct vec4"; break; + case EOpConstructBool: out << "Construct bool"; break; + case EOpConstructBVec2: out << "Construct bvec2"; break; + case EOpConstructBVec3: out << "Construct bvec3"; break; + case EOpConstructBVec4: out << "Construct bvec4"; break; + case EOpConstructInt: out << "Construct int"; break; + case EOpConstructIVec2: out << "Construct ivec2"; break; + case EOpConstructIVec3: out << "Construct ivec3"; break; + case EOpConstructIVec4: out << "Construct ivec4"; break; + case EOpConstructUInt: out << "Construct uint"; break; + case EOpConstructUVec2: out << "Construct uvec2"; break; + case EOpConstructUVec3: out << "Construct uvec3"; break; + case EOpConstructUVec4: out << "Construct uvec4"; break; + case EOpConstructMat2: out << "Construct mat2"; break; + case EOpConstructMat3: out << "Construct mat3"; break; + case EOpConstructMat4: out << "Construct mat4"; break; + case EOpConstructStruct: out << "Construct structure"; break; - case EOpLessThan: out << "Compare Less Than"; break; - case EOpGreaterThan: out << "Compare Greater Than"; break; - case EOpLessThanEqual: out << "Compare Less Than or Equal"; break; - case EOpGreaterThanEqual: out << "Compare Greater Than or Equal"; break; - case EOpVectorEqual: out << "Equal"; break; - case EOpVectorNotEqual: out << "NotEqual"; break; + case EOpLessThan: out << "Compare Less Than"; break; + case EOpGreaterThan: out << "Compare Greater Than"; break; + case EOpLessThanEqual: out << "Compare Less Than or Equal"; break; + case EOpGreaterThanEqual: out << "Compare Greater Than or Equal"; break; + case EOpVectorEqual: out << "Equal"; break; + case EOpVectorNotEqual: out << "NotEqual"; break; - case EOpMod: out << "mod"; break; - case EOpPow: out << "pow"; break; + case EOpMod: out << "mod"; break; + case EOpPow: out << "pow"; break; - case EOpAtan: out << "arc tangent"; break; + case EOpAtan: out << "arc tangent"; break; - case EOpMin: out << "min"; break; - case EOpMax: out << "max"; break; - case EOpClamp: out << "clamp"; break; - case EOpMix: out << "mix"; break; - case EOpStep: out << "step"; break; - case EOpSmoothStep: out << "smoothstep"; break; + case EOpMin: out << "min"; break; + case EOpMax: out << "max"; break; + case EOpClamp: out << "clamp"; break; + case EOpMix: out << "mix"; break; + case EOpStep: out << "step"; break; + case EOpSmoothStep: out << "smoothstep"; break; - case EOpDistance: out << "distance"; break; - case EOpDot: out << "dot-product"; break; - case EOpCross: out << "cross-product"; break; - case EOpFaceForward: out << "face-forward"; break; - case EOpReflect: out << "reflect"; break; - case EOpRefract: out << "refract"; break; - case EOpMul: out << "component-wise multiply"; break; + case EOpDistance: out << "distance"; break; + case EOpDot: out << "dot-product"; break; + case EOpCross: out << "cross-product"; break; + case EOpFaceForward: out << "face-forward"; break; + case EOpReflect: out << "reflect"; break; + case EOpRefract: out << "refract"; break; + case EOpMul: out << "component-wise multiply"; break; - case EOpDeclaration: out << "Declaration: "; break; + case EOpDeclaration: out << "Declaration: "; break; + case EOpInvariantDeclaration: out << "Invariant Declaration: "; break; - default: - out.prefix(EPrefixError); - out << "Bad aggregation op"; + default: + out.prefix(EPrefixError); + out << "Bad aggregation op"; } if (node->getOp() != EOpSequence && node->getOp() != EOpParameters) @@ -290,135 +357,156 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate* node) return true; } -bool TOutputTraverser::visitSelection(Visit visit, TIntermSelection* node) +bool TOutputTraverser::visitSelection(Visit visit, TIntermSelection *node) { - TInfoSinkBase& out = sink; + TInfoSinkBase &out = sink; - OutputTreeText(out, node, depth); + OutputTreeText(out, node, mDepth); out << "Test condition and select"; out << " (" << node->getCompleteString() << ")\n"; - ++depth; + ++mDepth; - OutputTreeText(sink, node, depth); + OutputTreeText(sink, node, mDepth); out << "Condition\n"; node->getCondition()->traverse(this); - OutputTreeText(sink, node, depth); - if (node->getTrueBlock()) { + OutputTreeText(sink, node, mDepth); + if (node->getTrueBlock()) + { out << "true case\n"; node->getTrueBlock()->traverse(this); - } else + } + else + { out << "true case is null\n"; + } - if (node->getFalseBlock()) { - OutputTreeText(sink, node, depth); + if (node->getFalseBlock()) + { + OutputTreeText(sink, node, mDepth); out << "false case\n"; node->getFalseBlock()->traverse(this); } - --depth; + --mDepth; return false; } -void TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node) +void TOutputTraverser::visitConstantUnion(TIntermConstantUnion *node) { - TInfoSinkBase& out = sink; + TInfoSinkBase &out = sink; size_t size = node->getType().getObjectSize(); - for (size_t i = 0; i < size; i++) { - OutputTreeText(out, node, depth); - switch (node->getUnionArrayPointer()[i].getType()) { - case EbtBool: - if (node->getUnionArrayPointer()[i].getBConst()) - out << "true"; - else - out << "false"; + for (size_t i = 0; i < size; i++) + { + OutputTreeText(out, node, mDepth); + switch (node->getUnionArrayPointer()[i].getType()) + { + case EbtBool: + if (node->getUnionArrayPointer()[i].getBConst()) + out << "true"; + else + out << "false"; - out << " (" << "const bool" << ")"; - out << "\n"; - break; - case EbtFloat: - out << node->getUnionArrayPointer()[i].getFConst(); - out << " (const float)\n"; - break; - case EbtInt: - out << node->getUnionArrayPointer()[i].getIConst(); - out << " (const int)\n"; - break; - case EbtUInt: - out << node->getUnionArrayPointer()[i].getUConst(); - out << " (const uint)\n"; - break; - default: - out.message(EPrefixInternalError, node->getLine(), "Unknown constant"); - break; + out << " (" << "const bool" << ")"; + out << "\n"; + break; + case EbtFloat: + out << node->getUnionArrayPointer()[i].getFConst(); + out << " (const float)\n"; + break; + case EbtInt: + out << node->getUnionArrayPointer()[i].getIConst(); + out << " (const int)\n"; + break; + case EbtUInt: + out << node->getUnionArrayPointer()[i].getUConst(); + out << " (const uint)\n"; + break; + default: + out.message(EPrefixInternalError, node->getLine(), "Unknown constant"); + break; } } } -bool TOutputTraverser::visitLoop(Visit visit, TIntermLoop* node) +bool TOutputTraverser::visitLoop(Visit visit, TIntermLoop *node) { - TInfoSinkBase& out = sink; + TInfoSinkBase &out = sink; - OutputTreeText(out, node, depth); + OutputTreeText(out, node, mDepth); out << "Loop with condition "; if (node->getType() == ELoopDoWhile) out << "not "; out << "tested first\n"; - ++depth; + ++mDepth; - OutputTreeText(sink, node, depth); - if (node->getCondition()) { + OutputTreeText(sink, node, mDepth); + if (node->getCondition()) + { out << "Loop Condition\n"; node->getCondition()->traverse(this); - } else + } + else + { out << "No loop condition\n"; + } - OutputTreeText(sink, node, depth); - if (node->getBody()) { + OutputTreeText(sink, node, mDepth); + if (node->getBody()) + { out << "Loop Body\n"; node->getBody()->traverse(this); - } else + } + else + { out << "No loop body\n"; + } - if (node->getExpression()) { - OutputTreeText(sink, node, depth); + if (node->getExpression()) + { + OutputTreeText(sink, node, mDepth); out << "Loop Terminal Expression\n"; node->getExpression()->traverse(this); } - --depth; + --mDepth; return false; } -bool TOutputTraverser::visitBranch(Visit visit, TIntermBranch* node) +bool TOutputTraverser::visitBranch(Visit visit, TIntermBranch *node) { - TInfoSinkBase& out = sink; + TInfoSinkBase &out = sink; - OutputTreeText(out, node, depth); + OutputTreeText(out, node, mDepth); - switch (node->getFlowOp()) { - case EOpKill: out << "Branch: Kill"; break; - case EOpBreak: out << "Branch: Break"; break; - case EOpContinue: out << "Branch: Continue"; break; - case EOpReturn: out << "Branch: Return"; break; - default: out << "Branch: Unknown Branch"; break; + switch (node->getFlowOp()) + { + case EOpKill: out << "Branch: Kill"; break; + case EOpBreak: out << "Branch: Break"; break; + case EOpContinue: out << "Branch: Continue"; break; + case EOpReturn: out << "Branch: Return"; break; + default: out << "Branch: Unknown Branch"; break; } - if (node->getExpression()) { + if (node->getExpression()) + { out << " with expression\n"; - ++depth; + ++mDepth; node->getExpression()->traverse(this); - --depth; - } else + --mDepth; + } + else + { out << "\n"; + } return false; } @@ -428,12 +516,12 @@ bool TOutputTraverser::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. // -void TIntermediate::outputTree(TIntermNode* root) +void TIntermediate::outputTree(TIntermNode *root) { - if (root == 0) + if (root == NULL) return; - TOutputTraverser it(infoSink.info); + TOutputTraverser it(mInfoSink.info); root->traverse(&it); } diff --git a/gfx/angle/src/compiler/translator/intermediate.h b/gfx/angle/src/compiler/translator/intermediate.h deleted file mode 100644 index 7c72099fe49c..000000000000 --- a/gfx/angle/src/compiler/translator/intermediate.h +++ /dev/null @@ -1,693 +0,0 @@ -// -// 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. -// - -// -// Definition of the in-memory high-level intermediate representation -// of shaders. This is a tree that parser creates. -// -// Nodes in the tree are defined as a hierarchy of classes derived from -// TIntermNode. Each is a node in a tree. There is no preset branching factor; -// each node can have it's own type of list of children. -// - -#ifndef __INTERMEDIATE_H -#define __INTERMEDIATE_H - -#include "GLSLANG/ShaderLang.h" - -#include -#include -#include "compiler/translator/Common.h" -#include "compiler/translator/Types.h" -#include "compiler/translator/ConstantUnion.h" - -// -// Operators used by the high-level (parse tree) representation. -// -enum TOperator { - EOpNull, // if in a node, should only mean a node is still being built - EOpSequence, // denotes a list of statements, or parameters, etc. - EOpFunctionCall, - EOpFunction, // For function definition - EOpParameters, // an aggregate listing the parameters to a function - - EOpDeclaration, - EOpPrototype, - - // - // Unary operators - // - - EOpNegative, - EOpLogicalNot, - EOpVectorLogicalNot, - - EOpPostIncrement, - EOpPostDecrement, - EOpPreIncrement, - EOpPreDecrement, - - EOpConvIntToBool, - EOpConvUIntToBool, - EOpConvFloatToBool, - EOpConvBoolToFloat, - EOpConvIntToFloat, - EOpConvUIntToFloat, - EOpConvFloatToInt, - EOpConvBoolToInt, - EOpConvUIntToInt, - EOpConvIntToUInt, - EOpConvFloatToUInt, - EOpConvBoolToUInt, - - // - // binary operations - // - - EOpAdd, - EOpSub, - EOpMul, - EOpDiv, - EOpEqual, - EOpNotEqual, - EOpVectorEqual, - EOpVectorNotEqual, - EOpLessThan, - EOpGreaterThan, - EOpLessThanEqual, - EOpGreaterThanEqual, - EOpComma, - - EOpVectorTimesScalar, - EOpVectorTimesMatrix, - EOpMatrixTimesVector, - EOpMatrixTimesScalar, - - EOpLogicalOr, - EOpLogicalXor, - EOpLogicalAnd, - - EOpIndexDirect, - EOpIndexIndirect, - EOpIndexDirectStruct, - EOpIndexDirectInterfaceBlock, - - EOpVectorSwizzle, - - // - // Built-in functions potentially mapped to operators - // - - EOpRadians, - EOpDegrees, - EOpSin, - EOpCos, - EOpTan, - EOpAsin, - EOpAcos, - EOpAtan, - - EOpPow, - EOpExp, - EOpLog, - EOpExp2, - EOpLog2, - EOpSqrt, - EOpInverseSqrt, - - EOpAbs, - EOpSign, - EOpFloor, - EOpCeil, - EOpFract, - EOpMod, - EOpMin, - EOpMax, - EOpClamp, - EOpMix, - EOpStep, - EOpSmoothStep, - - EOpLength, - EOpDistance, - EOpDot, - EOpCross, - EOpNormalize, - EOpFaceForward, - EOpReflect, - EOpRefract, - - EOpDFdx, // Fragment only, OES_standard_derivatives extension - EOpDFdy, // Fragment only, OES_standard_derivatives extension - EOpFwidth, // Fragment only, OES_standard_derivatives extension - - EOpMatrixTimesMatrix, - - EOpAny, - EOpAll, - - // - // Branch - // - - EOpKill, // Fragment only - EOpReturn, - EOpBreak, - EOpContinue, - - // - // Constructors - // - - EOpConstructInt, - EOpConstructUInt, - EOpConstructBool, - EOpConstructFloat, - EOpConstructVec2, - EOpConstructVec3, - EOpConstructVec4, - EOpConstructBVec2, - EOpConstructBVec3, - EOpConstructBVec4, - EOpConstructIVec2, - EOpConstructIVec3, - EOpConstructIVec4, - EOpConstructUVec2, - EOpConstructUVec3, - EOpConstructUVec4, - EOpConstructMat2, - EOpConstructMat3, - EOpConstructMat4, - EOpConstructStruct, - - // - // moves - // - - EOpAssign, - EOpInitialize, - EOpAddAssign, - EOpSubAssign, - EOpMulAssign, - EOpVectorTimesMatrixAssign, - EOpVectorTimesScalarAssign, - EOpMatrixTimesScalarAssign, - EOpMatrixTimesMatrixAssign, - EOpDivAssign -}; - -extern const char* getOperatorString(TOperator op); - -class TIntermTraverser; -class TIntermAggregate; -class TIntermBinary; -class TIntermUnary; -class TIntermConstantUnion; -class TIntermSelection; -class TIntermTyped; -class TIntermSymbol; -class TIntermLoop; -class TInfoSink; - -// -// Base class for the tree nodes -// -class TIntermNode { -public: - 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() { } - - const TSourceLoc& getLine() const { return line; } - void setLine(const TSourceLoc& l) { line = l; } - - virtual void traverse(TIntermTraverser*) = 0; - virtual TIntermTyped* getAsTyped() { return 0; } - virtual TIntermConstantUnion* getAsConstantUnion() { return 0; } - virtual TIntermAggregate* getAsAggregate() { return 0; } - virtual TIntermBinary* getAsBinaryNode() { return 0; } - virtual TIntermUnary* getAsUnaryNode() { return 0; } - virtual TIntermSelection* getAsSelectionNode() { return 0; } - virtual TIntermSymbol* getAsSymbolNode() { return 0; } - virtual TIntermLoop* getAsLoopNode() { return 0; } - - // Replace a child node. Return true if |original| is a child - // node and it is replaced; otherwise, return false. - virtual bool replaceChildNode( - TIntermNode *original, TIntermNode *replacement) = 0; - - // For traversing a tree in no particular order, but using - // heap memory. - virtual void enqueueChildren(std::queue *nodeQueue) const = 0; - -protected: - TSourceLoc line; -}; - -// -// This is just to help yacc. -// -struct TIntermNodePair { - TIntermNode* node1; - TIntermNode* node2; -}; - -// -// Intermediate class for nodes that have a type. -// -class TIntermTyped : public TIntermNode { -public: - TIntermTyped(const TType& t) : type(t) { } - virtual TIntermTyped* getAsTyped() { return this; } - - virtual bool hasSideEffects() const = 0; - - void setType(const TType& t) { type = t; } - const TType& getType() const { return type; } - TType* getTypePointer() { return &type; } - - TBasicType getBasicType() const { return type.getBasicType(); } - TQualifier getQualifier() const { return type.getQualifier(); } - TPrecision getPrecision() const { return type.getPrecision(); } - int getCols() const { return type.getCols(); } - int getRows() const { return type.getRows(); } - int getNominalSize() const { return type.getNominalSize(); } - int getSecondarySize() const { return type.getSecondarySize(); } - - bool isInterfaceBlock() const { return type.isInterfaceBlock(); } - bool isMatrix() const { return type.isMatrix(); } - bool isArray() const { return type.isArray(); } - bool isVector() const { return type.isVector(); } - bool isScalar() const { return type.isScalar(); } - bool isScalarInt() const { return type.isScalarInt(); } - const char* getBasicString() const { return type.getBasicString(); } - const char* getQualifierString() const { return type.getQualifierString(); } - TString getCompleteString() const { return type.getCompleteString(); } - - int getArraySize() const { return type.getArraySize(); } - -protected: - TType type; -}; - -// -// Handle for, do-while, and while loops. -// -enum TLoopType { - ELoopFor, - ELoopWhile, - ELoopDoWhile -}; - -class TIntermLoop : public TIntermNode { -public: - TIntermLoop(TLoopType aType, - TIntermNode *aInit, TIntermTyped* aCond, TIntermTyped* aExpr, - TIntermNode* aBody) : - type(aType), - init(aInit), - cond(aCond), - expr(aExpr), - body(aBody), - unrollFlag(false) { } - - virtual TIntermLoop* getAsLoopNode() { return this; } - virtual void traverse(TIntermTraverser*); - virtual bool replaceChildNode( - TIntermNode *original, TIntermNode *replacement); - - TLoopType getType() const { return type; } - TIntermNode* getInit() { return init; } - TIntermTyped* getCondition() { return cond; } - TIntermTyped* getExpression() { return expr; } - TIntermNode* getBody() { return body; } - - void setUnrollFlag(bool flag) { unrollFlag = flag; } - bool getUnrollFlag() { return unrollFlag; } - - virtual void enqueueChildren(std::queue *nodeQueue) const; - -protected: - TLoopType type; - TIntermNode* init; // for-loop initialization - TIntermTyped* cond; // loop exit condition - TIntermTyped* expr; // for-loop expression - TIntermNode* body; // loop body - - bool unrollFlag; // Whether the loop should be unrolled or not. -}; - -// -// Handle break, continue, return, and kill. -// -class TIntermBranch : public TIntermNode { -public: - TIntermBranch(TOperator op, TIntermTyped* e) : - flowOp(op), - expression(e) { } - - virtual void traverse(TIntermTraverser*); - virtual bool replaceChildNode( - TIntermNode *original, TIntermNode *replacement); - - TOperator getFlowOp() { return flowOp; } - TIntermTyped* getExpression() { return expression; } - - virtual void enqueueChildren(std::queue *nodeQueue) const; - -protected: - TOperator flowOp; - TIntermTyped* expression; // non-zero except for "return exp;" statements -}; - -// -// Nodes that correspond to symbols or constants in the source code. -// -class TIntermSymbol : public TIntermTyped { -public: - // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym. If sym comes from - // per process globalpoolallocator, then it causes increased memory usage per compile - // it is essential to use "symbol = sym" to assign to symbol - TIntermSymbol(int i, const TString& sym, const TType& t) : - TIntermTyped(t), id(i) { symbol = sym; } - - virtual bool hasSideEffects() const { return false; } - - int getId() const { return id; } - const TString& getSymbol() const { return symbol; } - - void setId(int newId) { id = newId; } - - virtual void traverse(TIntermTraverser*); - virtual TIntermSymbol* getAsSymbolNode() { return this; } - virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; } - - virtual void enqueueChildren(std::queue *nodeQueue) const {} - -protected: - int id; - TString symbol; -}; - -class TIntermConstantUnion : public TIntermTyped { -public: - TIntermConstantUnion(ConstantUnion *unionPointer, const TType& t) : TIntermTyped(t), unionArrayPointer(unionPointer) { } - - virtual bool hasSideEffects() const { return false; } - - ConstantUnion* getUnionArrayPointer() const { return unionArrayPointer; } - - int getIConst(size_t index) const { return unionArrayPointer ? unionArrayPointer[index].getIConst() : 0; } - unsigned int getUConst(size_t index) const { return unionArrayPointer ? unionArrayPointer[index].getUConst() : 0; } - float getFConst(size_t index) const { return unionArrayPointer ? unionArrayPointer[index].getFConst() : 0.0f; } - bool getBConst(size_t index) const { return unionArrayPointer ? unionArrayPointer[index].getBConst() : false; } - - virtual TIntermConstantUnion* getAsConstantUnion() { return this; } - virtual void traverse(TIntermTraverser*); - virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; } - - TIntermTyped* fold(TOperator, TIntermTyped*, TInfoSink&); - - virtual void enqueueChildren(std::queue *nodeQueue) const {} - -protected: - ConstantUnion *unionArrayPointer; -}; - -// -// Intermediate class for node types that hold operators. -// -class TIntermOperator : public TIntermTyped { -public: - TOperator getOp() const { return op; } - void setOp(TOperator o) { op = o; } - - bool isAssignment() const; - bool isConstructor() const; - - virtual bool hasSideEffects() const { return isAssignment(); } - -protected: - TIntermOperator(TOperator o) : TIntermTyped(TType(EbtFloat, EbpUndefined)), op(o) {} - TIntermOperator(TOperator o, const TType& t) : TIntermTyped(t), op(o) {} - TOperator op; -}; - -// -// Nodes for all the basic binary math operators. -// -class TIntermBinary : public TIntermOperator { -public: - TIntermBinary(TOperator o) : TIntermOperator(o), addIndexClamp(false) {} - - virtual TIntermBinary* getAsBinaryNode() { return this; } - virtual void traverse(TIntermTraverser*); - virtual bool replaceChildNode( - TIntermNode *original, TIntermNode *replacement); - - virtual bool hasSideEffects() const { return (isAssignment() || left->hasSideEffects() || right->hasSideEffects()); } - - void setLeft(TIntermTyped* n) { left = n; } - void setRight(TIntermTyped* n) { right = n; } - TIntermTyped* getLeft() const { return left; } - TIntermTyped* getRight() const { return right; } - bool promote(TInfoSink&); - - void setAddIndexClamp() { addIndexClamp = true; } - bool getAddIndexClamp() { return addIndexClamp; } - - virtual void enqueueChildren(std::queue *nodeQueue) const; - -protected: - TIntermTyped* left; - TIntermTyped* right; - - // If set to true, wrap any EOpIndexIndirect with a clamp to bounds. - bool addIndexClamp; -}; - -// -// Nodes for unary math operators. -// -class TIntermUnary : public TIntermOperator { -public: - TIntermUnary(TOperator o, const TType& t) : TIntermOperator(o, t), operand(0), useEmulatedFunction(false) {} - TIntermUnary(TOperator o) : TIntermOperator(o), operand(0), useEmulatedFunction(false) {} - - virtual void traverse(TIntermTraverser*); - virtual TIntermUnary* getAsUnaryNode() { return this; } - virtual bool replaceChildNode( - TIntermNode *original, TIntermNode *replacement); - - virtual bool hasSideEffects() const { return (isAssignment() || operand->hasSideEffects()); } - - void setOperand(TIntermTyped* o) { operand = o; } - TIntermTyped* getOperand() { return operand; } - bool promote(TInfoSink&); - - void setUseEmulatedFunction() { useEmulatedFunction = true; } - bool getUseEmulatedFunction() { return useEmulatedFunction; } - - virtual void enqueueChildren(std::queue *nodeQueue) const; - -protected: - TIntermTyped* operand; - - // If set to true, replace the built-in function call with an emulated one - // to work around driver bugs. - bool useEmulatedFunction; -}; - -typedef TVector TIntermSequence; -typedef TVector TQualifierList; - -// -// Nodes that operate on an arbitrary sized set of children. -// -class TIntermAggregate : public TIntermOperator { -public: - TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), useEmulatedFunction(false) { } - TIntermAggregate(TOperator o) : TIntermOperator(o), useEmulatedFunction(false) { } - ~TIntermAggregate() { } - - virtual TIntermAggregate* getAsAggregate() { return this; } - virtual void traverse(TIntermTraverser*); - virtual bool replaceChildNode( - TIntermNode *original, TIntermNode *replacement); - - // Conservatively assume function calls and other aggregate operators have side-effects - virtual bool hasSideEffects() const { return true; } - - TIntermSequence& getSequence() { return sequence; } - - void setName(const TString& n) { name = n; } - const TString& getName() const { return name; } - - void setUserDefined() { userDefined = true; } - bool isUserDefined() const { return userDefined; } - - void setOptimize(bool o) { optimize = o; } - bool getOptimize() { return optimize; } - void setDebug(bool d) { debug = d; } - bool getDebug() { return debug; } - - void setUseEmulatedFunction() { useEmulatedFunction = true; } - bool getUseEmulatedFunction() { return useEmulatedFunction; } - - virtual void enqueueChildren(std::queue *nodeQueue) const; - -protected: - TIntermAggregate(const TIntermAggregate&); // disallow copy constructor - TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator - TIntermSequence sequence; - TString name; - bool userDefined; // used for user defined function names - - bool optimize; - bool debug; - - // If set to true, replace the built-in function call with an emulated one - // to work around driver bugs. - bool useEmulatedFunction; -}; - -// -// For if tests. Simplified since there is no switch statement. -// -class TIntermSelection : public TIntermTyped { -public: - TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) : - TIntermTyped(TType(EbtVoid, EbpUndefined)), condition(cond), trueBlock(trueB), falseBlock(falseB) {} - TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) : - TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB) {} - - virtual void traverse(TIntermTraverser*); - virtual bool replaceChildNode( - TIntermNode *original, TIntermNode *replacement); - - // Conservatively assume selections have side-effects - virtual bool hasSideEffects() const { return true; } - - bool usesTernaryOperator() const { return getBasicType() != EbtVoid; } - TIntermNode* getCondition() const { return condition; } - TIntermNode* getTrueBlock() const { return trueBlock; } - TIntermNode* getFalseBlock() const { return falseBlock; } - TIntermSelection* getAsSelectionNode() { return this; } - - virtual void enqueueChildren(std::queue *nodeQueue) const; - -protected: - TIntermTyped* condition; - TIntermNode* trueBlock; - TIntermNode* falseBlock; -}; - -enum Visit -{ - PreVisit, - InVisit, - PostVisit -}; - -// -// For traversing the tree. User should derive from this, -// put their traversal specific data in it, and then pass -// it to a Traverse method. -// -// When using this, just fill in the methods for nodes you want visited. -// Return false from a pre-visit to skip visiting that node's subtree. -// -class TIntermTraverser -{ -public: - 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), - maxDepth(0) {} - virtual ~TIntermTraverser() {} - - virtual void visitSymbol(TIntermSymbol*) {} - virtual void visitConstantUnion(TIntermConstantUnion*) {} - virtual bool visitBinary(Visit visit, TIntermBinary*) {return true;} - virtual bool visitUnary(Visit visit, TIntermUnary*) {return true;} - virtual bool visitSelection(Visit visit, TIntermSelection*) {return true;} - virtual bool visitAggregate(Visit visit, TIntermAggregate*) {return true;} - virtual bool visitLoop(Visit visit, TIntermLoop*) {return true;} - virtual bool visitBranch(Visit visit, TIntermBranch*) {return true;} - - int getMaxDepth() const {return maxDepth;} - - void incrementDepth(TIntermNode *current) - { - depth++; - maxDepth = std::max(maxDepth, depth); - path.push_back(current); - } - - void decrementDepth() - { - depth--; - path.pop_back(); - } - - TIntermNode *getParentNode() - { - return path.size() == 0 ? NULL : path.back(); - } - - // Return the original name if hash function pointer is NULL; - // otherwise return the hashed name. - static TString hash(const TString& name, ShHashFunction64 hashFunction); - - const bool preVisit; - const bool inVisit; - const bool postVisit; - const bool rightToLeft; - -protected: - int depth; - int maxDepth; - - // All the nodes from root to the current node's parent during traversing. - TVector path; -}; - -// -// For traversing the tree, and computing max depth. -// Takes a maximum depth limit to prevent stack overflow. -// -class TMaxDepthTraverser : public TIntermTraverser -{ -public: - POOL_ALLOCATOR_NEW_DELETE(); - TMaxDepthTraverser(int depthLimit) - : TIntermTraverser(true, true, false, false), - depthLimit(depthLimit) - {} - - virtual bool visitBinary(Visit visit, TIntermBinary*) { return depthCheck(); } - virtual bool visitUnary(Visit visit, TIntermUnary*) { return depthCheck(); } - virtual bool visitSelection(Visit visit, TIntermSelection*) { return depthCheck(); } - virtual bool visitAggregate(Visit visit, TIntermAggregate*) { return depthCheck(); } - virtual bool visitLoop(Visit visit, TIntermLoop*) { return depthCheck(); } - virtual bool visitBranch(Visit visit, TIntermBranch*) { return depthCheck(); } - -protected: - int depthLimit; - - bool depthCheck() const { return maxDepth < depthLimit; } -}; - -#endif // __INTERMEDIATE_H diff --git a/gfx/angle/src/compiler/translator/localintermediate.h b/gfx/angle/src/compiler/translator/localintermediate.h deleted file mode 100644 index 125dcd989a26..000000000000 --- a/gfx/angle/src/compiler/translator/localintermediate.h +++ /dev/null @@ -1,55 +0,0 @@ -// -// 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. -// - -#ifndef _LOCAL_INTERMEDIATE_INCLUDED_ -#define _LOCAL_INTERMEDIATE_INCLUDED_ - -#include "compiler/translator/intermediate.h" - -struct TVectorFields { - int offsets[4]; - int num; -}; - -// -// Set of helper functions to help parse and build the tree. -// -class TInfoSink; -class TIntermediate { -public: - POOL_ALLOCATOR_NEW_DELETE(); - TIntermediate(TInfoSink& i) : infoSink(i) { } - - TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TSourceLoc&); - TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*); - TIntermTyped* addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&); - 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&); - 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(const TSourceLoc&, TIntermNode*, ConstantUnion*, TOperator, 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 outputTree(TIntermNode*); - -private: - void operator=(TIntermediate&); // prevent assignments - - TInfoSink& infoSink; -}; - -#endif // _LOCAL_INTERMEDIATE_INCLUDED_ diff --git a/gfx/angle/src/compiler/translator/osinclude.h b/gfx/angle/src/compiler/translator/osinclude.h deleted file mode 100644 index c3063d624a87..000000000000 --- a/gfx/angle/src/compiler/translator/osinclude.h +++ /dev/null @@ -1,66 +0,0 @@ -// -// 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 -// found in the LICENSE file. -// - -#ifndef __OSINCLUDE_H -#define __OSINCLUDE_H - -// -// This file contains contains os-specific datatypes and -// declares any os-specific functions. -// - -#if defined(_WIN32) || defined(_WIN64) -#define ANGLE_OS_WIN -#elif defined(__APPLE__) || defined(__linux__) || \ - defined(__FreeBSD__) || defined(__OpenBSD__) || \ - defined(__NetBSD__) || defined(__DragonFly__) || \ - defined(__sun) || defined(ANDROID) || \ - defined(__GLIBC__) || defined(__GNU__) || \ - defined(__QNX__) -#define ANGLE_OS_POSIX -#else -#error Unsupported platform. -#endif - -#if defined(ANGLE_OS_WIN) -#define STRICT -#define VC_EXTRALEAN 1 -#include -#elif defined(ANGLE_OS_POSIX) -#include -#include -#include -#endif // ANGLE_OS_WIN - - -#include "compiler/translator/compilerdebug.h" - -// -// Thread Local Storage Operations -// -#if defined(ANGLE_OS_WIN) -typedef DWORD OS_TLSIndex; -#define OS_INVALID_TLS_INDEX (TLS_OUT_OF_INDEXES) -#elif defined(ANGLE_OS_POSIX) -typedef pthread_key_t OS_TLSIndex; -#define OS_INVALID_TLS_INDEX (static_cast(-1)) -#endif // ANGLE_OS_WIN - -OS_TLSIndex OS_AllocTLSIndex(); -bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue); -bool OS_FreeTLSIndex(OS_TLSIndex nIndex); - -inline void* OS_GetTLSValue(OS_TLSIndex nIndex) -{ - ASSERT(nIndex != OS_INVALID_TLS_INDEX); -#if defined(ANGLE_OS_WIN) - return TlsGetValue(nIndex); -#elif defined(ANGLE_OS_POSIX) - return pthread_getspecific(nIndex); -#endif // ANGLE_OS_WIN -} - -#endif // __OSINCLUDE_H diff --git a/gfx/angle/src/compiler/translator/ossource_posix.cpp b/gfx/angle/src/compiler/translator/ossource_posix.cpp deleted file mode 100644 index 90a37574441c..000000000000 --- a/gfx/angle/src/compiler/translator/ossource_posix.cpp +++ /dev/null @@ -1,64 +0,0 @@ -// -// 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 -// found in the LICENSE file. -// - -// -// This file contains the posix specific functions -// -#include "compiler/translator/osinclude.h" - -#if !defined(ANGLE_OS_POSIX) -#error Trying to build a posix specific file in a non-posix build. -#endif - -// -// Thread Local Storage Operations -// -OS_TLSIndex OS_AllocTLSIndex() -{ - pthread_key_t pPoolIndex; - - // - // Create global pool key. - // - if ((pthread_key_create(&pPoolIndex, NULL)) != 0) { - assert(0 && "OS_AllocTLSIndex(): Unable to allocate Thread Local Storage"); - return false; - } - else { - return pPoolIndex; - } -} - - -bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue) -{ - if (nIndex == OS_INVALID_TLS_INDEX) { - assert(0 && "OS_SetTLSValue(): Invalid TLS Index"); - return false; - } - - if (pthread_setspecific(nIndex, lpvValue) == 0) - return true; - else - return false; -} - - -bool OS_FreeTLSIndex(OS_TLSIndex nIndex) -{ - if (nIndex == OS_INVALID_TLS_INDEX) { - assert(0 && "OS_SetTLSValue(): Invalid TLS Index"); - return false; - } - - // - // Delete the global pool key. - // - if (pthread_key_delete(nIndex) == 0) - return true; - else - return false; -} diff --git a/gfx/angle/src/compiler/translator/ossource_win.cpp b/gfx/angle/src/compiler/translator/ossource_win.cpp deleted file mode 100644 index 2cc5871b71d3..000000000000 --- a/gfx/angle/src/compiler/translator/ossource_win.cpp +++ /dev/null @@ -1,57 +0,0 @@ -// -// 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 -// found in the LICENSE file. -// - -#include "compiler/translator/osinclude.h" -// -// This file contains contains the window's specific functions -// - -#if !defined(ANGLE_OS_WIN) -#error Trying to build a windows specific file in a non windows build. -#endif - - -// -// Thread Local Storage Operations -// -OS_TLSIndex OS_AllocTLSIndex() -{ - DWORD dwIndex = TlsAlloc(); - if (dwIndex == TLS_OUT_OF_INDEXES) { - assert(0 && "OS_AllocTLSIndex(): Unable to allocate Thread Local Storage"); - return OS_INVALID_TLS_INDEX; - } - - return dwIndex; -} - - -bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue) -{ - if (nIndex == OS_INVALID_TLS_INDEX) { - assert(0 && "OS_SetTLSValue(): Invalid TLS Index"); - return false; - } - - if (TlsSetValue(nIndex, lpvValue)) - return true; - else - return false; -} - - -bool OS_FreeTLSIndex(OS_TLSIndex nIndex) -{ - if (nIndex == OS_INVALID_TLS_INDEX) { - assert(0 && "OS_SetTLSValue(): Invalid TLS Index"); - return false; - } - - if (TlsFree(nIndex)) - return true; - else - return false; -} diff --git a/gfx/angle/src/compiler/translator/parseConst.cpp b/gfx/angle/src/compiler/translator/parseConst.cpp index 33617e53d9a2..1897ed151c1a 100644 --- a/gfx/angle/src/compiler/translator/parseConst.cpp +++ b/gfx/angle/src/compiler/translator/parseConst.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2014 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,47 +7,50 @@ #include "compiler/translator/ParseContext.h" // -// Use this class to carry along data from node to node in +// Use this class to carry along data from node to node in // the traversal // -class TConstTraverser : public TIntermTraverser { -public: - TConstTraverser(ConstantUnion* cUnion, bool singleConstParam, TOperator constructType, TInfoSink& sink, TType& t) +class TConstTraverser : public TIntermTraverser +{ + public: + TConstTraverser(ConstantUnion *cUnion, bool singleConstParam, + TOperator constructType, TInfoSink &sink, TType &t) : error(false), - index(0), - unionArray(cUnion), - type(t), - constructorType(constructType), - singleConstantParam(singleConstParam), - infoSink(sink), - size(0), - isDiagonalMatrixInit(false), - matrixCols(0), - matrixRows(0) { + mIndex(0), + mUnionArray(cUnion), + mType(t), + mConstructorType(constructType), + mSingleConstantParam(singleConstParam), + mInfoSink(sink), + mSize(0), + mIsDiagonalMatrixInit(false), + mMatrixCols(0), + mMatrixRows(0) + { } bool error; -protected: - void visitSymbol(TIntermSymbol*); - void visitConstantUnion(TIntermConstantUnion*); - bool visitBinary(Visit visit, TIntermBinary*); - bool visitUnary(Visit visit, TIntermUnary*); - bool visitSelection(Visit visit, TIntermSelection*); - bool visitAggregate(Visit visit, TIntermAggregate*); - bool visitLoop(Visit visit, TIntermLoop*); - bool visitBranch(Visit visit, TIntermBranch*); + protected: + void visitSymbol(TIntermSymbol *); + void visitConstantUnion(TIntermConstantUnion *); + bool visitBinary(Visit visit, TIntermBinary *); + bool visitUnary(Visit visit, TIntermUnary *); + bool visitSelection(Visit visit, TIntermSelection *); + bool visitAggregate(Visit visit, TIntermAggregate *); + bool visitLoop(Visit visit, TIntermLoop *); + bool visitBranch(Visit visit, TIntermBranch *); - size_t index; - ConstantUnion *unionArray; - TType type; - TOperator constructorType; - bool singleConstantParam; - TInfoSink& infoSink; - size_t size; // size of the constructor ( 4 for vec4) - bool isDiagonalMatrixInit; - int matrixCols; // columns of the matrix - int matrixRows; // rows of the matrix + size_t mIndex; + ConstantUnion *mUnionArray; + TType mType; + TOperator mConstructorType; + bool mSingleConstantParam; + TInfoSink &mInfoSink; + size_t mSize; // size of the constructor ( 4 for vec4) + bool mIsDiagonalMatrixInit; + int mMatrixCols; // columns of the matrix + int mMatrixRows; // rows of the matrix }; // @@ -58,138 +61,144 @@ protected: // continue on to children. If you process children yourself, // return false. // - -void TConstTraverser::visitSymbol(TIntermSymbol* node) +void TConstTraverser::visitSymbol(TIntermSymbol *node) { - infoSink.info.message(EPrefixInternalError, node->getLine(), "Symbol Node found in constant constructor"); + mInfoSink.info.message(EPrefixInternalError, node->getLine(), + "Symbol Node found in constant constructor"); return; - } -bool TConstTraverser::visitBinary(Visit visit, TIntermBinary* node) +bool TConstTraverser::visitBinary(Visit visit, TIntermBinary *node) { TQualifier qualifier = node->getType().getQualifier(); - - if (qualifier != EvqConst) { + + if (qualifier != EvqConst) + { TString buf; buf.append("'constructor' : assigning non-constant to "); - buf.append(type.getCompleteString()); - infoSink.info.message(EPrefixError, node->getLine(), buf.c_str()); - error = true; - return false; - } - - infoSink.info.message(EPrefixInternalError, node->getLine(), "Binary Node found in constant constructor"); - - return false; -} - -bool TConstTraverser::visitUnary(Visit visit, TIntermUnary* node) -{ - TString buf; - buf.append("'constructor' : assigning non-constant to "); - buf.append(type.getCompleteString()); - infoSink.info.message(EPrefixError, node->getLine(), buf.c_str()); - error = true; - return false; -} - -bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate* node) -{ - if (!node->isConstructor() && node->getOp() != EOpComma) { - TString buf; - buf.append("'constructor' : assigning non-constant to "); - buf.append(type.getCompleteString()); - infoSink.info.message(EPrefixError, node->getLine(), buf.c_str()); - error = true; - return false; - } - - if (node->getSequence().size() == 0) { + buf.append(mType.getCompleteString()); + mInfoSink.info.message(EPrefixError, node->getLine(), buf.c_str()); error = true; return false; } - bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion(); - if (flag) - { - singleConstantParam = true; - constructorType = node->getOp(); - size = node->getType().getObjectSize(); - - if (node->getType().isMatrix()) { - isDiagonalMatrixInit = true; - matrixCols = node->getType().getCols(); - matrixRows = node->getType().getRows(); - } - } - - for (TIntermSequence::iterator p = node->getSequence().begin(); - p != node->getSequence().end(); p++) { - - if (node->getOp() == EOpComma) - index = 0; - - (*p)->traverse(this); - } - if (flag) - { - singleConstantParam = false; - constructorType = EOpNull; - size = 0; - isDiagonalMatrixInit = false; - matrixCols = 0; - matrixRows = 0; - } + mInfoSink.info.message(EPrefixInternalError, node->getLine(), + "Binary Node found in constant constructor"); return false; } -bool TConstTraverser::visitSelection(Visit visit, TIntermSelection* node) +bool TConstTraverser::visitUnary(Visit visit, TIntermUnary *node) { - infoSink.info.message(EPrefixInternalError, node->getLine(), "Selection Node found in constant constructor"); + TString buf; + buf.append("'constructor' : assigning non-constant to "); + buf.append(mType.getCompleteString()); + mInfoSink.info.message(EPrefixError, node->getLine(), buf.c_str()); error = true; return false; } -void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node) +bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate *node) +{ + if (!node->isConstructor() && node->getOp() != EOpComma) + { + TString buf; + buf.append("'constructor' : assigning non-constant to "); + buf.append(mType.getCompleteString()); + mInfoSink.info.message(EPrefixError, node->getLine(), buf.c_str()); + error = true; + return false; + } + + if (node->getSequence()->size() == 0) + { + error = true; + return false; + } + + bool flag = node->getSequence()->size() == 1 && + (*node->getSequence())[0]->getAsTyped()->getAsConstantUnion(); + if (flag) + { + mSingleConstantParam = true; + mConstructorType = node->getOp(); + mSize = node->getType().getObjectSize(); + + if (node->getType().isMatrix()) + { + mIsDiagonalMatrixInit = true; + mMatrixCols = node->getType().getCols(); + mMatrixRows = node->getType().getRows(); + } + } + + for (TIntermSequence::iterator p = node->getSequence()->begin(); + p != node->getSequence()->end(); p++) + { + if (node->getOp() == EOpComma) + mIndex = 0; + (*p)->traverse(this); + } + if (flag) + { + mSingleConstantParam = false; + mConstructorType = EOpNull; + mSize = 0; + mIsDiagonalMatrixInit = false; + mMatrixCols = 0; + mMatrixRows = 0; + } + return false; +} + +bool TConstTraverser::visitSelection(Visit visit, TIntermSelection *node) +{ + mInfoSink.info.message(EPrefixInternalError, node->getLine(), + "Selection Node found in constant constructor"); + error = true; + return false; +} + +void TConstTraverser::visitConstantUnion(TIntermConstantUnion *node) { if (!node->getUnionArrayPointer()) { // The constant was not initialized, this should already have been logged - assert(infoSink.info.size() != 0); + ASSERT(mInfoSink.info.size() != 0); return; } - ConstantUnion* leftUnionArray = unionArray; - size_t instanceSize = type.getObjectSize(); + ConstantUnion *leftUnionArray = mUnionArray; + size_t instanceSize = mType.getObjectSize(); + TBasicType basicType = mType.getBasicType(); - if (index >= instanceSize) + if (mIndex >= instanceSize) return; - if (!singleConstantParam) { + if (!mSingleConstantParam) + { size_t objectSize = node->getType().getObjectSize(); - ConstantUnion *rightUnionArray = node->getUnionArrayPointer(); - for (size_t i=0; i < objectSize; i++) { - if (index >= instanceSize) + for (size_t i=0; i < objectSize; i++) + { + if (mIndex >= instanceSize) return; - leftUnionArray[index] = rightUnionArray[i]; - - (index)++; + leftUnionArray[mIndex].cast(basicType, rightUnionArray[i]); + mIndex++; } - } else { - size_t totalSize = index + size; + } + else + { + size_t totalSize = mIndex + mSize; ConstantUnion *rightUnionArray = node->getUnionArrayPointer(); - if (!isDiagonalMatrixInit) { + if (!mIsDiagonalMatrixInit) + { int count = 0; - for (size_t i = index; i < totalSize; i++) { + for (size_t i = mIndex; i < totalSize; i++) + { if (i >= instanceSize) return; - - leftUnionArray[i] = rightUnionArray[count]; - - (index)++; - + leftUnionArray[i].cast(basicType, rightUnionArray[count]); + mIndex++; if (node->getType().getObjectSize() > 1) count++; } @@ -197,36 +206,37 @@ void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node) else { // for matrix diagonal constructors from a single scalar - for (int i = 0, col = 0; col < matrixCols; col++) + for (int i = 0, col = 0; col < mMatrixCols; col++) { - for (int row = 0; row < matrixRows; row++, i++) + for (int row = 0; row < mMatrixRows; row++, i++) { if (col == row) { - leftUnionArray[i] = rightUnionArray[0]; + leftUnionArray[i].cast(basicType, rightUnionArray[0]); } else { leftUnionArray[i].setFConst(0.0f); } - - (index)++; + mIndex++; } } } } } -bool TConstTraverser::visitLoop(Visit visit, TIntermLoop* node) +bool TConstTraverser::visitLoop(Visit visit, TIntermLoop *node) { - infoSink.info.message(EPrefixInternalError, node->getLine(), "Loop Node found in constant constructor"); + mInfoSink.info.message(EPrefixInternalError, node->getLine(), + "Loop Node found in constant constructor"); error = true; return false; } -bool TConstTraverser::visitBranch(Visit visit, TIntermBranch* node) +bool TConstTraverser::visitBranch(Visit visit, TIntermBranch *node) { - infoSink.info.message(EPrefixInternalError, node->getLine(), "Branch Node found in constant constructor"); + mInfoSink.info.message(EPrefixInternalError, node->getLine(), + "Branch Node found in constant constructor"); error = true; return false; } @@ -236,12 +246,15 @@ 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(const TSourceLoc& line, TIntermNode* root, ConstantUnion* unionArray, TOperator constructorType, TType t, bool singleConstantParam) +bool TIntermediate::parseConstTree( + const TSourceLoc &line, TIntermNode *root, ConstantUnion *unionArray, + TOperator constructorType, TType t, bool singleConstantParam) { if (root == 0) return false; - TConstTraverser it(unionArray, singleConstantParam, constructorType, infoSink, t); + TConstTraverser it(unionArray, singleConstantParam, constructorType, + mInfoSink, t); root->traverse(&it); if (it.error) diff --git a/gfx/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h b/gfx/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h index e77d8c21cbc8..80d5f7fa7fb0 100644 --- a/gfx/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h +++ b/gfx/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h @@ -7,7 +7,7 @@ #ifndef COMPILER_TIMING_RESTRICT_FRAGMENT_SHADER_TIMING_H_ #define COMPILER_TIMING_RESTRICT_FRAGMENT_SHADER_TIMING_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include "compiler/translator/depgraph/DependencyGraph.h" class TInfoSinkBase; diff --git a/gfx/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h b/gfx/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h index d461fbdbfeae..a6263567b4e1 100644 --- a/gfx/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h +++ b/gfx/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h @@ -7,7 +7,7 @@ #ifndef COMPILER_TIMING_RESTRICT_VERTEX_SHADER_TIMING_H_ #define COMPILER_TIMING_RESTRICT_VERTEX_SHADER_TIMING_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include "compiler/translator/InfoSink.h" class TInfoSinkBase; diff --git a/gfx/angle/src/compiler/translator/util.cpp b/gfx/angle/src/compiler/translator/util.cpp index 077bdcc48b86..40c90d8f2281 100644 --- a/gfx/angle/src/compiler/translator/util.cpp +++ b/gfx/angle/src/compiler/translator/util.cpp @@ -9,6 +9,7 @@ #include #include "compiler/preprocessor/numeric_lex.h" +#include "common/utilities.h" bool atof_clamp(const char *str, float *value) { @@ -26,3 +27,337 @@ bool atoi_clamp(const char *str, int *value) return success; } +namespace sh +{ + +GLenum 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.getCols()) + { + case 2: + switch (type.getRows()) + { + case 2: return GL_FLOAT_MAT2; + case 3: return GL_FLOAT_MAT2x3; + case 4: return GL_FLOAT_MAT2x4; + default: UNREACHABLE(); + } + + case 3: + switch (type.getRows()) + { + case 2: return GL_FLOAT_MAT3x2; + case 3: return GL_FLOAT_MAT3; + case 4: return GL_FLOAT_MAT3x4; + default: UNREACHABLE(); + } + + case 4: + switch (type.getRows()) + { + case 2: return GL_FLOAT_MAT4x2; + case 3: return GL_FLOAT_MAT4x3; + case 4: return GL_FLOAT_MAT4; + default: UNREACHABLE(); + } + + 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() == EbtUInt) + { + if (type.isScalar()) + { + return GL_UNSIGNED_INT; + } + else if (type.isVector()) + { + switch (type.getNominalSize()) + { + case 2: return GL_UNSIGNED_INT_VEC2; + case 3: return GL_UNSIGNED_INT_VEC3; + case 4: return GL_UNSIGNED_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(); + } + + switch (type.getBasicType()) + { + case EbtSampler2D: return GL_SAMPLER_2D; + case EbtSampler3D: return GL_SAMPLER_3D; + case EbtSamplerCube: return GL_SAMPLER_CUBE; + case EbtSamplerExternalOES: return GL_SAMPLER_EXTERNAL_OES; + case EbtSampler2DRect: return GL_SAMPLER_2D_RECT_ARB; + case EbtSampler2DArray: return GL_SAMPLER_2D_ARRAY; + case EbtISampler2D: return GL_INT_SAMPLER_2D; + case EbtISampler3D: return GL_INT_SAMPLER_3D; + case EbtISamplerCube: return GL_INT_SAMPLER_CUBE; + case EbtISampler2DArray: return GL_INT_SAMPLER_2D_ARRAY; + case EbtUSampler2D: return GL_UNSIGNED_INT_SAMPLER_2D; + case EbtUSampler3D: return GL_UNSIGNED_INT_SAMPLER_3D; + case EbtUSamplerCube: return GL_UNSIGNED_INT_SAMPLER_CUBE; + case EbtUSampler2DArray: return GL_UNSIGNED_INT_SAMPLER_2D_ARRAY; + case EbtSampler2DShadow: return GL_SAMPLER_2D_SHADOW; + case EbtSamplerCubeShadow: return GL_SAMPLER_CUBE_SHADOW; + case EbtSampler2DArrayShadow: return GL_SAMPLER_2D_ARRAY_SHADOW; + default: UNREACHABLE(); + } + + return GL_NONE; +} + +GLenum 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 || type.getBasicType() == EbtUInt) + { + 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; +} + +TString ArrayString(const TType &type) +{ + if (!type.isArray()) + { + return ""; + } + + return "[" + str(type.getArraySize()) + "]"; +} + +bool IsVaryingOut(TQualifier qualifier) +{ + switch (qualifier) + { + case EvqVaryingOut: + case EvqInvariantVaryingOut: + case EvqSmoothOut: + case EvqFlatOut: + case EvqCentroidOut: + case EvqVertexOut: + return true; + + default: break; + } + + return false; +} + +bool IsVaryingIn(TQualifier qualifier) +{ + switch (qualifier) + { + case EvqVaryingIn: + case EvqInvariantVaryingIn: + case EvqSmoothIn: + case EvqFlatIn: + case EvqCentroidIn: + case EvqFragmentIn: + return true; + + default: break; + } + + return false; +} + +bool IsVarying(TQualifier qualifier) +{ + return IsVaryingIn(qualifier) || IsVaryingOut(qualifier); +} + +InterpolationType GetInterpolationType(TQualifier qualifier) +{ + switch (qualifier) + { + case EvqFlatIn: + case EvqFlatOut: + return INTERPOLATION_FLAT; + + case EvqSmoothIn: + case EvqSmoothOut: + case EvqVertexOut: + case EvqFragmentIn: + case EvqVaryingIn: + case EvqVaryingOut: + case EvqInvariantVaryingIn: + case EvqInvariantVaryingOut: + return INTERPOLATION_SMOOTH; + + case EvqCentroidIn: + case EvqCentroidOut: + return INTERPOLATION_CENTROID; + + default: UNREACHABLE(); + return INTERPOLATION_SMOOTH; + } +} + +template +void GetVariableTraverser::traverse(const TType &type, const TString &name, std::vector *output) +{ + const TStructure *structure = type.getStruct(); + + VarT variable; + variable.name = name.c_str(); + variable.arraySize = static_cast(type.getArraySize()); + + if (!structure) + { + variable.type = GLVariableType(type); + variable.precision = GLVariablePrecision(type); + } + else + { + // Note: this enum value is not exposed outside ANGLE + variable.type = GL_STRUCT_ANGLEX; + variable.structName = structure->name().c_str(); + + const TFieldList &fields = structure->fields(); + + for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++) + { + TField *field = fields[fieldIndex]; + traverse(*field->type(), field->name(), &variable.fields); + } + } + + visitVariable(&variable); + + ASSERT(output); + output->push_back(variable); +} + +template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector *); +template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector *); +template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector *); + +BlockLayoutType GetBlockLayoutType(TLayoutBlockStorage blockStorage) +{ + switch (blockStorage) + { + case EbsPacked: return BLOCKLAYOUT_PACKED; + case EbsShared: return BLOCKLAYOUT_SHARED; + case EbsStd140: return BLOCKLAYOUT_STANDARD; + default: UNREACHABLE(); return BLOCKLAYOUT_SHARED; + } +} + +static TString InterfaceBlockFieldName(const TInterfaceBlock &interfaceBlock, const TField &field) +{ + if (interfaceBlock.hasInstanceName()) + { + return interfaceBlock.name() + "." + field.name(); + } + else + { + return field.name(); + } +} + +void GetInterfaceBlockFields(const TInterfaceBlock &interfaceBlock, std::vector *fieldsOut) +{ + const TFieldList &fieldList = interfaceBlock.fields(); + + for (size_t fieldIndex = 0; fieldIndex < fieldList.size(); ++fieldIndex) + { + const TField &field = *fieldList[fieldIndex]; + const TString &fullFieldName = InterfaceBlockFieldName(interfaceBlock, field); + const TType &fieldType = *field.type(); + + GetVariableTraverser traverser; + traverser.traverse(fieldType, fullFieldName, fieldsOut); + + fieldsOut->back().isRowMajorLayout = (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor); + } +} + +} diff --git a/gfx/angle/src/compiler/translator/util.h b/gfx/angle/src/compiler/translator/util.h index dc69f39060d2..6a39d5642128 100644 --- a/gfx/angle/src/compiler/translator/util.h +++ b/gfx/angle/src/compiler/translator/util.h @@ -7,6 +7,13 @@ #ifndef COMPILER_UTIL_H #define COMPILER_UTIL_H +#include + +#include "angle_gl.h" +#include + +#include "compiler/translator/Types.h" + // atof_clamp is like atof but // 1. it forces C locale, i.e. forcing '.' as decimal point. // 2. it clamps the value to -FLT_MAX or FLT_MAX if overflow happens. @@ -17,4 +24,36 @@ extern bool atof_clamp(const char *str, float *value); // Return false if overflow happens. extern bool atoi_clamp(const char *str, int *value); +namespace sh +{ + +GLenum GLVariableType(const TType &type); +GLenum GLVariablePrecision(const TType &type); +bool IsVaryingIn(TQualifier qualifier); +bool IsVaryingOut(TQualifier qualifier); +bool IsVarying(TQualifier qualifier); +InterpolationType GetInterpolationType(TQualifier qualifier); +BlockLayoutType GetBlockLayoutType(TLayoutBlockStorage blockStorage); +TString ArrayString(const TType &type); + +class GetVariableTraverser +{ + public: + GetVariableTraverser() {} + + template + void traverse(const TType &type, const TString &name, std::vector *output); + + protected: + // May be overloaded + virtual void visitVariable(ShaderVariable *newVar) {} + + private: + DISALLOW_COPY_AND_ASSIGN(GetVariableTraverser); +}; + +void GetInterfaceBlockFields(const TInterfaceBlock &interfaceBlock, std::vector *fieldsOut); + +} + #endif // COMPILER_UTIL_H diff --git a/gfx/angle/src/libEGL.gypi b/gfx/angle/src/libEGL.gypi index f5def3ff08db..85ac31587165 100644 --- a/gfx/angle/src/libEGL.gypi +++ b/gfx/angle/src/libEGL.gypi @@ -3,6 +3,58 @@ # found in the LICENSE file. { + 'variables': + { + 'angle_enable_d3d9%': 1, + 'angle_enable_d3d11%': 1, + # This file list is shared with the GN build. + 'angle_libegl_sources': + [ + '../include/EGL/egl.h', + '../include/EGL/eglext.h', + '../include/EGL/eglplatform.h', + '../include/GLES2/gl2.h', + '../include/GLES2/gl2ext.h', + '../include/GLES2/gl2platform.h', + '../include/GLES3/gl3.h', + '../include/GLES3/gl3ext.h', + '../include/GLES3/gl3platform.h', + '../include/GLSLANG/ShaderLang.h', + '../include/GLSLANG/ShaderVars.h', + '../include/KHR/khrplatform.h', + '../include/angle_gl.h', + 'common/RefCountObject.cpp', + 'common/RefCountObject.h', + 'common/angleutils.cpp', + 'common/angleutils.h', + 'common/debug.cpp', + 'common/debug.h', + 'common/event_tracer.cpp', + 'common/event_tracer.h', + 'common/mathutil.cpp', + 'common/mathutil.h', + 'common/platform.h', + 'common/tls.cpp', + 'common/tls.h', + 'common/utilities.cpp', + 'common/utilities.h', + 'common/version.h', + 'libEGL/Config.cpp', + 'libEGL/Config.h', + 'libEGL/Display.cpp', + 'libEGL/Display.h', + 'libEGL/Surface.cpp', + 'libEGL/Surface.h', + 'libEGL/libEGL.cpp', + 'libEGL/libEGL.def', + 'libEGL/libEGL.rc', + 'libEGL/main.cpp', + 'libEGL/main.h', + 'libEGL/resource.h', + ], + }, + # Everything below this is duplicated in the GN build. If you change + # anything also change angle/BUILD.gn 'conditions': [ ['OS=="win"', @@ -21,9 +73,7 @@ ], 'sources': [ - ' #include -#include -#include -#include -#include +#include "angle_gl.h" #include #include "common/debug.h" diff --git a/gfx/angle/src/libEGL/Config.h b/gfx/angle/src/libEGL/Config.h index 680337b7009f..98441142f4e6 100644 --- a/gfx/angle/src/libEGL/Config.h +++ b/gfx/angle/src/libEGL/Config.h @@ -11,7 +11,6 @@ #ifndef INCLUDE_CONFIG_H_ #define INCLUDE_CONFIG_H_ -#define EGLAPI #include #include diff --git a/gfx/angle/src/libEGL/Display.cpp b/gfx/angle/src/libEGL/Display.cpp index 07b2daca849a..43d9b2602e5c 100644 --- a/gfx/angle/src/libEGL/Display.cpp +++ b/gfx/angle/src/libEGL/Display.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2014 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. // @@ -13,6 +13,7 @@ #include #include #include +#include #include "common/debug.h" #include "common/mathutil.h" @@ -25,42 +26,47 @@ namespace egl { -namespace + +typedef std::map DisplayMap; +static DisplayMap *GetDisplayMap() { - typedef std::map DisplayMap; - DisplayMap displays; + static DisplayMap displays; + return &displays; } -egl::Display *Display::getDisplay(EGLNativeDisplayType displayId) +egl::Display *Display::getDisplay(EGLNativeDisplayType displayId, EGLint displayType) { - if (displays.find(displayId) != displays.end()) + DisplayMap *displays = GetDisplayMap(); + DisplayMap::const_iterator iter = displays->find(displayId); + if (iter != displays->end()) { - return displays[displayId]; + return iter->second; } // FIXME: Check if displayId is a valid display device context - egl::Display *display = new egl::Display(displayId, (HDC)displayId); + egl::Display *display = new egl::Display(displayId, displayType); + displays->insert(std::make_pair(displayId, display)); - displays[displayId] = display; return display; } -Display::Display(EGLNativeDisplayType displayId, HDC deviceContext) : mDc(deviceContext) +Display::Display(EGLNativeDisplayType displayId, EGLint displayType) + : mDisplayId(displayId), + mRequestedDisplayType(displayType), + mRenderer(NULL) { - mDisplayId = displayId; - mRenderer = NULL; } Display::~Display() { terminate(); - DisplayMap::iterator thisDisplay = displays.find(mDisplayId); - - if (thisDisplay != displays.end()) + DisplayMap *displays = GetDisplayMap(); + DisplayMap::iterator iter = displays->find(mDisplayId); + if (iter != displays->end()) { - displays.erase(thisDisplay); + displays->erase(iter); } } @@ -71,8 +77,8 @@ bool Display::initialize() return true; } - mRenderer = glCreateRenderer(this, mDc, mDisplayId); - + mRenderer = glCreateRenderer(this, mDisplayId, mRequestedDisplayType); + if (!mRenderer) { terminate(); @@ -81,16 +87,16 @@ bool Display::initialize() EGLint minSwapInterval = mRenderer->getMinSwapInterval(); EGLint maxSwapInterval = mRenderer->getMaxSwapInterval(); - EGLint maxTextureWidth = mRenderer->getMaxTextureWidth(); - EGLint maxTextureHeight = mRenderer->getMaxTextureHeight(); + EGLint maxTextureSize = mRenderer->getRendererCaps().max2DTextureSize; rx::ConfigDesc *descList; int numConfigs = mRenderer->generateConfigs(&descList); ConfigSet configSet; for (int i = 0; i < numConfigs; ++i) - configSet.add(descList[i], minSwapInterval, maxSwapInterval, - maxTextureWidth, maxTextureHeight); + { + configSet.add(descList[i], minSwapInterval, maxSwapInterval, maxTextureSize, maxTextureSize); + } // Give the sorted configs a unique ID and store them internally EGLint index = 1; @@ -112,7 +118,7 @@ bool Display::initialize() return false; } - initExtensionString(); + initDisplayExtensionString(); initVendorString(); return true; @@ -343,7 +349,7 @@ EGLSurface Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle, return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); } - if (textureFormat != EGL_NO_TEXTURE && !mRenderer->getNonPower2TextureSupport() && (!gl::isPow2(width) || !gl::isPow2(height))) + if (textureFormat != EGL_NO_TEXTURE && !mRenderer->getRendererExtensions().textureNPOT && (!gl::isPow2(width) || !gl::isPow2(height))) { return error(EGL_BAD_MATCH, EGL_NO_SURFACE); } @@ -500,48 +506,84 @@ bool Display::hasExistingWindowSurface(HWND window) return false; } -void Display::initExtensionString() +std::string Display::generateClientExtensionString() { - bool shareHandleSupported = mRenderer->getShareHandleSupport(); + std::vector extensions; - mExtensionString = ""; + extensions.push_back("EGL_EXT_client_extensions"); + + extensions.push_back("ANGLE_platform_angle"); + + if (supportsPlatformD3D()) + { + extensions.push_back("ANGLE_platform_angle_d3d"); + } + + if (supportsPlatformOpenGL()) + { + extensions.push_back("ANGLE_platform_angle_opengl"); + } + + std::ostringstream stream; + std::copy(extensions.begin(), extensions.end(), std::ostream_iterator(stream, " ")); + return stream.str(); +} + +void Display::initDisplayExtensionString() +{ + std::vector extensions; // Multi-vendor (EXT) extensions - mExtensionString += "EGL_EXT_create_context_robustness "; + extensions.push_back("EGL_EXT_create_context_robustness"); // ANGLE-specific extensions - if (shareHandleSupported) + if (mRenderer->getShareHandleSupport()) { - mExtensionString += "EGL_ANGLE_d3d_share_handle_client_buffer "; + extensions.push_back("EGL_ANGLE_d3d_share_handle_client_buffer"); + extensions.push_back("EGL_ANGLE_surface_d3d_texture_2d_share_handle"); } - mExtensionString += "EGL_ANGLE_query_surface_pointer "; - - mExtensionString += "EGL_ANGLE_window_fixed_size "; - - if (shareHandleSupported) - { - mExtensionString += "EGL_ANGLE_surface_d3d_texture_2d_share_handle "; - } + extensions.push_back("EGL_ANGLE_query_surface_pointer"); + extensions.push_back("EGL_ANGLE_window_fixed_size"); if (mRenderer->getPostSubBufferSupport()) { - mExtensionString += "EGL_NV_post_sub_buffer "; + extensions.push_back("EGL_NV_post_sub_buffer"); } // TODO: complete support for the EGL_KHR_create_context extension - mExtensionString += "EGL_KHR_create_context "; + extensions.push_back("EGL_KHR_create_context"); - std::string::size_type end = mExtensionString.find_last_not_of(' '); - if (end != std::string::npos) + std::ostringstream stream; + std::copy(extensions.begin(), extensions.end(), std::ostream_iterator(stream, " ")); + mDisplayExtensionString = stream.str(); +} + +const char *Display::getExtensionString(egl::Display *display) +{ + if (display != EGL_NO_DISPLAY) { - mExtensionString.resize(end+1); + return display->mDisplayExtensionString.c_str(); + } + else + { + static std::string clientExtensions = generateClientExtensionString(); + return clientExtensions.c_str(); } } -const char *Display::getExtensionString() const +bool Display::supportsPlatformD3D() { - return mExtensionString.c_str(); +#if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11) + return true; +#else + return false; +#endif +} + +bool Display::supportsPlatformOpenGL() +{ + return false; } void Display::initVendorString() diff --git a/gfx/angle/src/libEGL/Display.h b/gfx/angle/src/libEGL/Display.h index e394260e3187..250878f0ef43 100644 --- a/gfx/angle/src/libEGL/Display.h +++ b/gfx/angle/src/libEGL/Display.h @@ -33,7 +33,12 @@ class Display bool initialize(); void terminate(); - static egl::Display *getDisplay(EGLNativeDisplayType displayId); + static egl::Display *getDisplay(EGLNativeDisplayType displayId, EGLint displayType); + + static const char *getExtensionString(egl::Display *display); + + static bool supportsPlatformD3D(); + static bool supportsPlatformOpenGL(); bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig); bool getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value); @@ -63,15 +68,13 @@ class Display private: DISALLOW_COPY_AND_ASSIGN(Display); - Display(EGLNativeDisplayType displayId, HDC deviceContext); + Display(EGLNativeDisplayType displayId, EGLint displayType); bool restoreLostDevice(); EGLNativeDisplayType mDisplayId; - const HDC mDc; + EGLint mRequestedDisplayType; - bool mSoftwareDevice; - typedef std::set SurfaceSet; SurfaceSet mSurfaceSet; @@ -82,9 +85,12 @@ class Display rx::Renderer *mRenderer; - void initExtensionString(); + static std::string generateClientExtensionString(); + + void initDisplayExtensionString(); + std::string mDisplayExtensionString; + void initVendorString(); - std::string mExtensionString; std::string mVendorString; }; } diff --git a/gfx/angle/src/libEGL/Surface.h b/gfx/angle/src/libEGL/Surface.h index 2361fcd1b515..24c66b70cef2 100644 --- a/gfx/angle/src/libEGL/Surface.h +++ b/gfx/angle/src/libEGL/Surface.h @@ -11,7 +11,6 @@ #ifndef LIBEGL_SURFACE_H_ #define LIBEGL_SURFACE_H_ -#define EGLAPI #include #include "common/angleutils.h" @@ -105,7 +104,7 @@ private: EGLint mSwapInterval; EGLint mPostSubBufferSupported; EGLint mFixedSize; - + bool mSwapIntervalDirty; gl::Texture2D *mTexture; }; diff --git a/gfx/angle/src/libEGL/libEGL.cpp b/gfx/angle/src/libEGL/libEGL.cpp index f5a60227f8b5..f9a4780bec6a 100644 --- a/gfx/angle/src/libEGL/libEGL.cpp +++ b/gfx/angle/src/libEGL/libEGL.cpp @@ -99,14 +99,75 @@ EGLDisplay __stdcall eglGetDisplay(EGLNativeDisplayType display_id) { EVENT("(EGLNativeDisplayType display_id = 0x%0.8p)", display_id); - ANGLE_TRY + return egl::Display::getDisplay(display_id, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE); +} + +EGLDisplay __stdcall eglGetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list) +{ + EVENT("(EGLenum platform = %d, void* native_display = 0x%0.8p, const EGLint* attrib_list = 0x%0.8p)", + platform, native_display, attrib_list); + + switch (platform) { - return egl::Display::getDisplay(display_id); + case EGL_PLATFORM_ANGLE_ANGLE: + break; + + default: + return egl::error(EGL_BAD_CONFIG, EGL_NO_DISPLAY); } - ANGLE_CATCH_ALL + + EGLNativeDisplayType displayId = static_cast(native_display); + + // Validate the display device context + if (WindowFromDC(displayId) == NULL) { - return egl::error(EGL_BAD_ALLOC, EGL_NO_DISPLAY); + return egl::success(EGL_NO_DISPLAY); } + + EGLint requestedDisplayType = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE; + if (attrib_list) + { + for (const EGLint *curAttrib = attrib_list; curAttrib[0] != EGL_NONE; curAttrib += 2) + { + switch (curAttrib[0]) + { + case EGL_PLATFORM_ANGLE_TYPE_ANGLE: + requestedDisplayType = curAttrib[1]; + break; + + default: + break; + } + } + } + + switch (requestedDisplayType) + { + case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE: + break; + + case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE: + case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE: + case EGL_PLATFORM_ANGLE_TYPE_D3D11_WARP_ANGLE: + if (!egl::Display::supportsPlatformD3D()) + { + return egl::success(EGL_NO_DISPLAY); + } + break; + + case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE: + case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE: + if (!egl::Display::supportsPlatformOpenGL()) + { + return egl::success(EGL_NO_DISPLAY); + } + break; + + default: + return egl::success(EGL_NO_DISPLAY); + } + + return egl::Display::getDisplay(displayId, requestedDisplayType); } EGLBoolean __stdcall eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) @@ -114,84 +175,62 @@ EGLBoolean __stdcall eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint *major = 0x%0.8p, EGLint *minor = 0x%0.8p)", dpy, major, minor); - ANGLE_TRY + if (dpy == EGL_NO_DISPLAY) { - if (dpy == EGL_NO_DISPLAY) - { - return egl::error(EGL_BAD_DISPLAY, EGL_FALSE); - } - - egl::Display *display = static_cast(dpy); - - if (!display->initialize()) - { - return egl::error(EGL_NOT_INITIALIZED, EGL_FALSE); - } - - if (major) *major = 1; - if (minor) *minor = 4; - - return egl::success(EGL_TRUE); + return egl::error(EGL_BAD_DISPLAY, EGL_FALSE); } - ANGLE_CATCH_ALL + + egl::Display *display = static_cast(dpy); + + if (!display->initialize()) { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_NOT_INITIALIZED, EGL_FALSE); } + + if (major) *major = 1; + if (minor) *minor = 4; + + return egl::success(EGL_TRUE); } EGLBoolean __stdcall eglTerminate(EGLDisplay dpy) { EVENT("(EGLDisplay dpy = 0x%0.8p)", dpy); - ANGLE_TRY + if (dpy == EGL_NO_DISPLAY) { - if (dpy == EGL_NO_DISPLAY) - { - return egl::error(EGL_BAD_DISPLAY, EGL_FALSE); - } - - egl::Display *display = static_cast(dpy); - - display->terminate(); - - return egl::success(EGL_TRUE); - } - ANGLE_CATCH_ALL - { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_DISPLAY, EGL_FALSE); } + + egl::Display *display = static_cast(dpy); + + display->terminate(); + + return egl::success(EGL_TRUE); } const char *__stdcall eglQueryString(EGLDisplay dpy, EGLint name) { EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint name = %d)", dpy, name); - ANGLE_TRY + egl::Display *display = static_cast(dpy); + if (!(display == EGL_NO_DISPLAY && name == EGL_EXTENSIONS) && !validateDisplay(display)) { - egl::Display *display = static_cast(dpy); - - if (!validateDisplay(display)) - { - return NULL; - } - - switch (name) - { - case EGL_CLIENT_APIS: - return egl::success("OpenGL_ES"); - case EGL_EXTENSIONS: - return egl::success(display->getExtensionString()); - case EGL_VENDOR: - return egl::success(display->getVendorString()); - case EGL_VERSION: - return egl::success("1.4 (ANGLE " ANGLE_VERSION_STRING ")"); - } - - return egl::error(EGL_BAD_PARAMETER, (const char*)NULL); + return NULL; } - ANGLE_CATCH_ALL + + switch (name) { - return egl::error(EGL_BAD_ALLOC, (const char*)NULL); + case EGL_CLIENT_APIS: + return egl::success("OpenGL_ES"); + case EGL_EXTENSIONS: + return egl::success(egl::Display::getExtensionString(display)); + case EGL_VENDOR: + return egl::success(display->getVendorString()); + case EGL_VERSION: + return egl::success("1.4 (ANGLE " ANGLE_VERSION_STRING ")"); + default: + return egl::error(EGL_BAD_PARAMETER, (const char*)NULL); } } @@ -201,33 +240,26 @@ EGLBoolean __stdcall eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint co "EGLint config_size = %d, EGLint *num_config = 0x%0.8p)", dpy, configs, config_size, num_config); - ANGLE_TRY + egl::Display *display = static_cast(dpy); + + if (!validateDisplay(display)) { - egl::Display *display = static_cast(dpy); - - if (!validateDisplay(display)) - { - return EGL_FALSE; - } - - if (!num_config) - { - return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); - } - - const EGLint attribList[] = {EGL_NONE}; - - if (!display->getConfigs(configs, attribList, config_size, num_config)) - { - return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE); - } - - return egl::success(EGL_TRUE); + return EGL_FALSE; } - ANGLE_CATCH_ALL + + if (!num_config) { - return egl::error(EGL_BAD_ALLOC, 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 egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE); + } + + return egl::success(EGL_TRUE); } EGLBoolean __stdcall eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config) @@ -236,35 +268,28 @@ EGLBoolean __stdcall eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, "EGLConfig *configs = 0x%0.8p, EGLint config_size = %d, EGLint *num_config = 0x%0.8p)", dpy, attrib_list, configs, config_size, num_config); - ANGLE_TRY + egl::Display *display = static_cast(dpy); + + if (!validateDisplay(display)) { - egl::Display *display = static_cast(dpy); - - if (!validateDisplay(display)) - { - return EGL_FALSE; - } - - if (!num_config) - { - return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); - } - - const EGLint attribList[] = {EGL_NONE}; - - if (!attrib_list) - { - attrib_list = attribList; - } - - display->getConfigs(configs, attrib_list, config_size, num_config); - - return egl::success(EGL_TRUE); + return EGL_FALSE; } - ANGLE_CATCH_ALL + + if (!num_config) { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); } + + const EGLint attribList[] = {EGL_NONE}; + + if (!attrib_list) + { + attrib_list = attribList; + } + + display->getConfigs(configs, attrib_list, config_size, num_config); + + return egl::success(EGL_TRUE); } EGLBoolean __stdcall eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value) @@ -272,26 +297,19 @@ EGLBoolean __stdcall eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)", dpy, config, attribute, value); - ANGLE_TRY + egl::Display *display = static_cast(dpy); + + if (!validateConfig(display, config)) { - egl::Display *display = static_cast(dpy); - - if (!validateConfig(display, config)) - { - return EGL_FALSE; - } - - if (!display->getConfigAttrib(config, attribute, value)) - { - return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE); - } - - return egl::success(EGL_TRUE); + return EGL_FALSE; } - ANGLE_CATCH_ALL + + if (!display->getConfigAttrib(config, attribute, value)) { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE); } + + return egl::success(EGL_TRUE); } EGLSurface __stdcall eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list) @@ -299,28 +317,21 @@ EGLSurface __stdcall eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EG EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLNativeWindowType win = 0x%0.8p, " "const EGLint *attrib_list = 0x%0.8p)", dpy, config, win, attrib_list); - ANGLE_TRY + egl::Display *display = static_cast(dpy); + + if (!validateConfig(display, config)) { - egl::Display *display = static_cast(dpy); - - if (!validateConfig(display, config)) - { - return EGL_NO_SURFACE; - } - - HWND window = (HWND)win; - - if (!IsWindow(window)) - { - return egl::error(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); - } - - return display->createWindowSurface(window, config, attrib_list); + return EGL_NO_SURFACE; } - ANGLE_CATCH_ALL + + HWND window = (HWND)win; + + if (!IsWindow(window)) { - return egl::error(EGL_BAD_ALLOC, EGL_NO_SURFACE); + return egl::error(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); } + + return display->createWindowSurface(window, config, attrib_list); } EGLSurface __stdcall eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) @@ -328,21 +339,14 @@ EGLSurface __stdcall eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, c EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)", dpy, config, attrib_list); - ANGLE_TRY - { - egl::Display *display = static_cast(dpy); + egl::Display *display = static_cast(dpy); - if (!validateConfig(display, config)) - { - return EGL_NO_SURFACE; - } - - return display->createOffscreenSurface(config, NULL, attrib_list); - } - ANGLE_CATCH_ALL + if (!validateConfig(display, config)) { - return egl::error(EGL_BAD_ALLOC, EGL_NO_SURFACE); + return EGL_NO_SURFACE; } + + return display->createOffscreenSurface(config, NULL, attrib_list); } EGLSurface __stdcall eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list) @@ -350,52 +354,38 @@ EGLSurface __stdcall eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EG EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLNativePixmapType pixmap = 0x%0.8p, " "const EGLint *attrib_list = 0x%0.8p)", dpy, config, pixmap, attrib_list); - ANGLE_TRY + egl::Display *display = static_cast(dpy); + + if (!validateConfig(display, config)) { - egl::Display *display = static_cast(dpy); - - if (!validateConfig(display, config)) - { - return EGL_NO_SURFACE; - } - - UNIMPLEMENTED(); // FIXME - - return egl::success(EGL_NO_SURFACE); - } - ANGLE_CATCH_ALL - { - return egl::error(EGL_BAD_ALLOC, EGL_NO_SURFACE); + return EGL_NO_SURFACE; } + + UNIMPLEMENTED(); // FIXME + + return egl::success(EGL_NO_SURFACE); } EGLBoolean __stdcall eglDestroySurface(EGLDisplay dpy, EGLSurface surface) { EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p)", dpy, surface); - ANGLE_TRY + egl::Display *display = static_cast(dpy); + egl::Surface *eglSurface = static_cast(surface); + + if (!validateSurface(display, eglSurface)) { - egl::Display *display = static_cast(dpy); - egl::Surface *eglSurface = static_cast(surface); - - if (!validateSurface(display, eglSurface)) - { - return EGL_FALSE; - } - - if (surface == EGL_NO_SURFACE) - { - return egl::error(EGL_BAD_SURFACE, EGL_FALSE); - } - - display->destroySurface((egl::Surface*)surface); - - return egl::success(EGL_TRUE); + return EGL_FALSE; } - ANGLE_CATCH_ALL + + if (surface == EGL_NO_SURFACE) { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_SURFACE, EGL_FALSE); } + + display->destroySurface((egl::Surface*)surface); + + return egl::success(EGL_TRUE); } EGLBoolean __stdcall eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value) @@ -403,87 +393,80 @@ EGLBoolean __stdcall eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)", dpy, surface, attribute, value); - ANGLE_TRY + egl::Display *display = static_cast(dpy); + egl::Surface *eglSurface = (egl::Surface*)surface; + + if (!validateSurface(display, eglSurface)) { - egl::Display *display = static_cast(dpy); - egl::Surface *eglSurface = (egl::Surface*)surface; - - if (!validateSurface(display, eglSurface)) - { - return EGL_FALSE; - } - - if (surface == EGL_NO_SURFACE) - { - return egl::error(EGL_BAD_SURFACE, EGL_FALSE); - } - - switch (attribute) - { - case EGL_VG_ALPHA_FORMAT: - UNIMPLEMENTED(); // FIXME - break; - case EGL_VG_COLORSPACE: - UNIMPLEMENTED(); // FIXME - break; - case EGL_CONFIG_ID: - *value = eglSurface->getConfigID(); - break; - case EGL_HEIGHT: - *value = eglSurface->getHeight(); - break; - case EGL_HORIZONTAL_RESOLUTION: - UNIMPLEMENTED(); // FIXME - break; - case EGL_LARGEST_PBUFFER: - UNIMPLEMENTED(); // FIXME - break; - case EGL_MIPMAP_TEXTURE: - UNIMPLEMENTED(); // FIXME - break; - case EGL_MIPMAP_LEVEL: - UNIMPLEMENTED(); // FIXME - break; - case EGL_MULTISAMPLE_RESOLVE: - UNIMPLEMENTED(); // FIXME - break; - case EGL_PIXEL_ASPECT_RATIO: - *value = eglSurface->getPixelAspectRatio(); - break; - case EGL_RENDER_BUFFER: - *value = eglSurface->getRenderBuffer(); - break; - case EGL_SWAP_BEHAVIOR: - *value = eglSurface->getSwapBehavior(); - break; - case EGL_TEXTURE_FORMAT: - *value = eglSurface->getTextureFormat(); - break; - case EGL_TEXTURE_TARGET: - *value = eglSurface->getTextureTarget(); - break; - case EGL_VERTICAL_RESOLUTION: - UNIMPLEMENTED(); // FIXME - break; - case EGL_WIDTH: - *value = eglSurface->getWidth(); - break; - case EGL_POST_SUB_BUFFER_SUPPORTED_NV: - *value = eglSurface->isPostSubBufferSupported(); - break; - case EGL_FIXED_SIZE_ANGLE: - *value = eglSurface->isFixedSize(); - break; - default: - return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE); - } - - return egl::success(EGL_TRUE); + return EGL_FALSE; } - ANGLE_CATCH_ALL + + if (surface == EGL_NO_SURFACE) { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_SURFACE, EGL_FALSE); } + + switch (attribute) + { + case EGL_VG_ALPHA_FORMAT: + UNIMPLEMENTED(); // FIXME + break; + case EGL_VG_COLORSPACE: + UNIMPLEMENTED(); // FIXME + break; + case EGL_CONFIG_ID: + *value = eglSurface->getConfigID(); + break; + case EGL_HEIGHT: + *value = eglSurface->getHeight(); + break; + case EGL_HORIZONTAL_RESOLUTION: + UNIMPLEMENTED(); // FIXME + break; + case EGL_LARGEST_PBUFFER: + UNIMPLEMENTED(); // FIXME + break; + case EGL_MIPMAP_TEXTURE: + UNIMPLEMENTED(); // FIXME + break; + case EGL_MIPMAP_LEVEL: + UNIMPLEMENTED(); // FIXME + break; + case EGL_MULTISAMPLE_RESOLVE: + UNIMPLEMENTED(); // FIXME + break; + case EGL_PIXEL_ASPECT_RATIO: + *value = eglSurface->getPixelAspectRatio(); + break; + case EGL_RENDER_BUFFER: + *value = eglSurface->getRenderBuffer(); + break; + case EGL_SWAP_BEHAVIOR: + *value = eglSurface->getSwapBehavior(); + break; + case EGL_TEXTURE_FORMAT: + *value = eglSurface->getTextureFormat(); + break; + case EGL_TEXTURE_TARGET: + *value = eglSurface->getTextureTarget(); + break; + case EGL_VERTICAL_RESOLUTION: + UNIMPLEMENTED(); // FIXME + break; + case EGL_WIDTH: + *value = eglSurface->getWidth(); + break; + case EGL_POST_SUB_BUFFER_SUPPORTED_NV: + *value = eglSurface->isPostSubBufferSupported(); + break; + case EGL_FIXED_SIZE_ANGLE: + *value = eglSurface->isFixedSize(); + break; + default: + return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE); + } + + return egl::success(EGL_TRUE); } EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value) @@ -491,114 +474,79 @@ EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surf TRACE("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, void **value = 0x%0.8p)", dpy, surface, attribute, value); - ANGLE_TRY + egl::Display *display = static_cast(dpy); + egl::Surface *eglSurface = (egl::Surface*)surface; + + if (!validateSurface(display, eglSurface)) { - egl::Display *display = static_cast(dpy); - egl::Surface *eglSurface = (egl::Surface*)surface; - - if (!validateSurface(display, eglSurface)) - { - return EGL_FALSE; - } - - if (surface == EGL_NO_SURFACE) - { - return egl::error(EGL_BAD_SURFACE, EGL_FALSE); - } - - switch (attribute) - { - case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE: - { - rx::SwapChain *swapchain = eglSurface->getSwapChain(); - *value = (void*) (swapchain ? swapchain->getShareHandle() : NULL); - } - break; - default: - return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE); - } - - return egl::success(EGL_TRUE); + return EGL_FALSE; } - ANGLE_CATCH_ALL + + if (surface == EGL_NO_SURFACE) { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_SURFACE, EGL_FALSE); } + + switch (attribute) + { + case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE: + { + rx::SwapChain *swapchain = eglSurface->getSwapChain(); + *value = (void*) (swapchain ? swapchain->getShareHandle() : NULL); + } + break; + default: + return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE); + } + + return egl::success(EGL_TRUE); } EGLBoolean __stdcall eglBindAPI(EGLenum api) { EVENT("(EGLenum api = 0x%X)", api); - ANGLE_TRY + switch (api) { - switch (api) - { - case EGL_OPENGL_API: - case EGL_OPENVG_API: - return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); // Not supported by this implementation - case EGL_OPENGL_ES_API: - break; - default: - return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); - } - - egl::setCurrentAPI(api); - - return egl::success(EGL_TRUE); - } - ANGLE_CATCH_ALL - { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); + case EGL_OPENGL_API: + case EGL_OPENVG_API: + return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); // Not supported by this implementation + case EGL_OPENGL_ES_API: + break; + default: + return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); } + + egl::setCurrentAPI(api); + + return egl::success(EGL_TRUE); } EGLenum __stdcall eglQueryAPI(void) { EVENT("()"); - ANGLE_TRY - { - EGLenum API = egl::getCurrentAPI(); + EGLenum API = egl::getCurrentAPI(); - return egl::success(API); - } - ANGLE_CATCH_ALL - { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); - } + return egl::success(API); } EGLBoolean __stdcall eglWaitClient(void) { EVENT("()"); - ANGLE_TRY - { - UNIMPLEMENTED(); // FIXME + UNIMPLEMENTED(); // FIXME - return egl::success(0); - } - ANGLE_CATCH_ALL - { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); - } + return egl::success(0); } EGLBoolean __stdcall eglReleaseThread(void) { EVENT("()"); - ANGLE_TRY - { - eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE); + eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE); - return egl::success(EGL_TRUE); - } - ANGLE_CATCH_ALL - { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); - } + return egl::success(EGL_TRUE); } EGLSurface __stdcall eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list) @@ -607,26 +555,19 @@ EGLSurface __stdcall eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum bu "EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)", dpy, buftype, buffer, config, attrib_list); - ANGLE_TRY + egl::Display *display = static_cast(dpy); + + if (!validateConfig(display, config)) { - egl::Display *display = static_cast(dpy); - - if (!validateConfig(display, config)) - { - return EGL_NO_SURFACE; - } - - if (buftype != EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE || !buffer) - { - return egl::error(EGL_BAD_PARAMETER, EGL_NO_SURFACE); - } - - return display->createOffscreenSurface(config, (HANDLE)buffer, attrib_list); + return EGL_NO_SURFACE; } - ANGLE_CATCH_ALL + + if (buftype != EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE || !buffer) { - return egl::error(EGL_BAD_ALLOC, EGL_NO_SURFACE); + return egl::error(EGL_BAD_PARAMETER, EGL_NO_SURFACE); } + + return display->createOffscreenSurface(config, (HANDLE)buffer, attrib_list); } EGLBoolean __stdcall eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) @@ -634,145 +575,117 @@ EGLBoolean __stdcall eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint value = %d)", dpy, surface, attribute, value); - ANGLE_TRY + egl::Display *display = static_cast(dpy); + egl::Surface *eglSurface = static_cast(surface); + + if (!validateSurface(display, eglSurface)) { - egl::Display *display = static_cast(dpy); - egl::Surface *eglSurface = static_cast(surface); - - if (!validateSurface(display, eglSurface)) - { - return EGL_FALSE; - } - - UNIMPLEMENTED(); // FIXME - - return egl::success(EGL_TRUE); - } - ANGLE_CATCH_ALL - { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); + return EGL_FALSE; } + + UNIMPLEMENTED(); // FIXME + + return egl::success(EGL_TRUE); } EGLBoolean __stdcall eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) { EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy, surface, buffer); - ANGLE_TRY + egl::Display *display = static_cast(dpy); + egl::Surface *eglSurface = static_cast(surface); + + if (!validateSurface(display, eglSurface)) { - egl::Display *display = static_cast(dpy); - egl::Surface *eglSurface = static_cast(surface); - - if (!validateSurface(display, eglSurface)) - { - return EGL_FALSE; - } - - if (buffer != EGL_BACK_BUFFER) - { - return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); - } - - if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle()) - { - return egl::error(EGL_BAD_SURFACE, EGL_FALSE); - } - - if (eglSurface->getBoundTexture()) - { - return egl::error(EGL_BAD_ACCESS, EGL_FALSE); - } - - if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE) - { - return egl::error(EGL_BAD_MATCH, EGL_FALSE); - } - - if (!glBindTexImage(eglSurface)) - { - return egl::error(EGL_BAD_MATCH, EGL_FALSE); - } - - return egl::success(EGL_TRUE); + return EGL_FALSE; } - ANGLE_CATCH_ALL + + if (buffer != EGL_BACK_BUFFER) { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); } + + if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle()) + { + return egl::error(EGL_BAD_SURFACE, EGL_FALSE); + } + + if (eglSurface->getBoundTexture()) + { + return egl::error(EGL_BAD_ACCESS, EGL_FALSE); + } + + if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE) + { + return egl::error(EGL_BAD_MATCH, EGL_FALSE); + } + + if (!glBindTexImage(eglSurface)) + { + return egl::error(EGL_BAD_MATCH, EGL_FALSE); + } + + return egl::success(EGL_TRUE); } EGLBoolean __stdcall eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) { EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy, surface, buffer); - ANGLE_TRY + egl::Display *display = static_cast(dpy); + egl::Surface *eglSurface = static_cast(surface); + + if (!validateSurface(display, eglSurface)) { - egl::Display *display = static_cast(dpy); - egl::Surface *eglSurface = static_cast(surface); - - if (!validateSurface(display, eglSurface)) - { - return EGL_FALSE; - } - - if (buffer != EGL_BACK_BUFFER) - { - return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); - } - - if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle()) - { - return egl::error(EGL_BAD_SURFACE, EGL_FALSE); - } - - if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE) - { - return egl::error(EGL_BAD_MATCH, EGL_FALSE); - } - - gl::Texture2D *texture = eglSurface->getBoundTexture(); - - if (texture) - { - texture->releaseTexImage(); - } - - return egl::success(EGL_TRUE); + return EGL_FALSE; } - ANGLE_CATCH_ALL + + if (buffer != EGL_BACK_BUFFER) { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); } + + if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle()) + { + return egl::error(EGL_BAD_SURFACE, EGL_FALSE); + } + + if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE) + { + return egl::error(EGL_BAD_MATCH, EGL_FALSE); + } + + gl::Texture2D *texture = eglSurface->getBoundTexture(); + + if (texture) + { + texture->releaseTexImage(); + } + + return egl::success(EGL_TRUE); } EGLBoolean __stdcall eglSwapInterval(EGLDisplay dpy, EGLint interval) { EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint interval = %d)", dpy, interval); - ANGLE_TRY + egl::Display *display = static_cast(dpy); + + if (!validateDisplay(display)) { - egl::Display *display = static_cast(dpy); - - if (!validateDisplay(display)) - { - return EGL_FALSE; - } - - egl::Surface *draw_surface = static_cast(egl::getCurrentDrawSurface()); - - if (draw_surface == NULL) - { - return egl::error(EGL_BAD_SURFACE, EGL_FALSE); - } - - draw_surface->setSwapInterval(interval); - - return egl::success(EGL_TRUE); + return EGL_FALSE; } - ANGLE_CATCH_ALL + + egl::Surface *draw_surface = static_cast(egl::getCurrentDrawSurface()); + + if (draw_surface == NULL) { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_SURFACE, EGL_FALSE); } + + draw_surface->setSwapInterval(interval); + + return egl::success(EGL_TRUE); } EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list) @@ -780,111 +693,97 @@ EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLConte EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLContext share_context = 0x%0.8p, " "const EGLint *attrib_list = 0x%0.8p)", dpy, config, share_context, attrib_list); - ANGLE_TRY - { - // Get the requested client version (default is 1) and check it is 2 or 3. - EGLint client_version = 1; - bool reset_notification = false; - bool robust_access = false; + // Get the requested client version (default is 1) and check it is 2 or 3. + EGLint client_version = 1; + bool reset_notification = false; + bool robust_access = false; - if (attrib_list) + if (attrib_list) + { + for (const EGLint* attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2) { - for (const EGLint* attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2) + switch (attribute[0]) { - switch (attribute[0]) + case EGL_CONTEXT_CLIENT_VERSION: + client_version = attribute[1]; + break; + case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT: + if (attribute[1] == EGL_TRUE) { - case EGL_CONTEXT_CLIENT_VERSION: - client_version = attribute[1]; - break; - case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT: - if (attribute[1] == EGL_TRUE) - { - return egl::error(EGL_BAD_CONFIG, EGL_NO_CONTEXT); // Unimplemented - // robust_access = true; - } - else if (attribute[1] != EGL_FALSE) - 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 egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); - break; - default: - return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); + return egl::error(EGL_BAD_CONFIG, EGL_NO_CONTEXT); // Unimplemented + // robust_access = true; } + else if (attribute[1] != EGL_FALSE) + 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 egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); + break; + default: + return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); } } - - if (client_version != 2 && client_version != 3) - { - return egl::error(EGL_BAD_CONFIG, EGL_NO_CONTEXT); - } - - egl::Display *display = static_cast(dpy); - - if (share_context) - { - gl::Context* sharedGLContext = static_cast(share_context); - - if (sharedGLContext->isResetNotificationEnabled() != reset_notification) - { - return egl::error(EGL_BAD_MATCH, EGL_NO_CONTEXT); - } - - if (sharedGLContext->getClientVersion() != client_version) - { - return egl::error(EGL_BAD_CONTEXT, EGL_NO_CONTEXT); - } - - // Can not share contexts between displays - if (sharedGLContext->getRenderer() != display->getRenderer()) - { - return egl::error(EGL_BAD_MATCH, EGL_NO_CONTEXT); - } - } - - if (!validateConfig(display, config)) - { - return EGL_NO_CONTEXT; - } - - return display->createContext(config, client_version, static_cast(share_context), reset_notification, robust_access); } - ANGLE_CATCH_ALL + + if (client_version != 2 && client_version != 3) { - return egl::error(EGL_BAD_ALLOC, EGL_NO_CONTEXT); + return egl::error(EGL_BAD_CONFIG, EGL_NO_CONTEXT); } + + egl::Display *display = static_cast(dpy); + + if (share_context) + { + gl::Context* sharedGLContext = static_cast(share_context); + + if (sharedGLContext->isResetNotificationEnabled() != reset_notification) + { + return egl::error(EGL_BAD_MATCH, EGL_NO_CONTEXT); + } + + if (sharedGLContext->getClientVersion() != client_version) + { + return egl::error(EGL_BAD_CONTEXT, EGL_NO_CONTEXT); + } + + // Can not share contexts between displays + if (sharedGLContext->getRenderer() != display->getRenderer()) + { + return egl::error(EGL_BAD_MATCH, EGL_NO_CONTEXT); + } + } + + if (!validateConfig(display, config)) + { + return EGL_NO_CONTEXT; + } + + return display->createContext(config, client_version, static_cast(share_context), reset_notification, robust_access); } EGLBoolean __stdcall eglDestroyContext(EGLDisplay dpy, EGLContext ctx) { EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p)", dpy, ctx); - ANGLE_TRY + egl::Display *display = static_cast(dpy); + gl::Context *context = static_cast(ctx); + + if (!validateContext(display, context)) { - egl::Display *display = static_cast(dpy); - gl::Context *context = static_cast(ctx); - - if (!validateContext(display, context)) - { - return EGL_FALSE; - } - - if (ctx == EGL_NO_CONTEXT) - { - return egl::error(EGL_BAD_CONTEXT, EGL_FALSE); - } - - display->destroyContext(context); - - return egl::success(EGL_TRUE); + return EGL_FALSE; } - ANGLE_CATCH_ALL + + if (ctx == EGL_NO_CONTEXT) { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_CONTEXT, EGL_FALSE); } + + display->destroyContext(context); + + return egl::success(EGL_TRUE); } EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) @@ -892,95 +791,81 @@ EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface draw = 0x%0.8p, EGLSurface read = 0x%0.8p, EGLContext ctx = 0x%0.8p)", dpy, draw, read, ctx); - ANGLE_TRY - { - egl::Display *display = static_cast(dpy); - gl::Context *context = static_cast(ctx); + egl::Display *display = static_cast(dpy); + gl::Context *context = static_cast(ctx); - if (ctx != EGL_NO_CONTEXT && !validateContext(display, context)) + bool noContext = (ctx == EGL_NO_CONTEXT); + bool noSurface = (draw == EGL_NO_SURFACE || read == EGL_NO_SURFACE); + if (noContext != noSurface) + { + return egl::error(EGL_BAD_MATCH, EGL_FALSE); + } + + if (ctx != EGL_NO_CONTEXT && !validateContext(display, context)) + { + return EGL_FALSE; + } + + if (dpy != EGL_NO_DISPLAY && display->isInitialized()) + { + rx::Renderer *renderer = display->getRenderer(); + if (renderer->testDeviceLost(true)) { return EGL_FALSE; } - if (dpy != EGL_NO_DISPLAY) + if (renderer->isDeviceLost()) { - rx::Renderer *renderer = display->getRenderer(); - if (renderer->testDeviceLost(true)) - { - return EGL_FALSE; - } - - if (renderer->isDeviceLost()) - { - return egl::error(EGL_CONTEXT_LOST, EGL_FALSE); - } + 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)))) - { - return EGL_FALSE; - } - - if (draw != read) - { - UNIMPLEMENTED(); // FIXME - } - - egl::setCurrentDisplay(dpy); - egl::setCurrentDrawSurface(draw); - egl::setCurrentReadSurface(read); - - glMakeCurrent(context, display, static_cast(draw)); - - return egl::success(EGL_TRUE); } - ANGLE_CATCH_ALL + + if ((draw != EGL_NO_SURFACE && !validateSurface(display, static_cast(draw))) || + (read != EGL_NO_SURFACE && !validateSurface(display, static_cast(read)))) { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); + return EGL_FALSE; } + + if (draw != read) + { + UNIMPLEMENTED(); // FIXME + } + + egl::setCurrentDisplay(dpy); + egl::setCurrentDrawSurface(draw); + egl::setCurrentReadSurface(read); + + glMakeCurrent(context, display, static_cast(draw)); + + return egl::success(EGL_TRUE); } EGLContext __stdcall eglGetCurrentContext(void) { EVENT("()"); - ANGLE_TRY - { - EGLContext context = glGetCurrentContext(); + EGLContext context = glGetCurrentContext(); - return egl::success(context); - } - ANGLE_CATCH_ALL - { - return egl::error(EGL_BAD_ALLOC, EGL_NO_CONTEXT); - } + return egl::success(context); } EGLSurface __stdcall eglGetCurrentSurface(EGLint readdraw) { EVENT("(EGLint readdraw = %d)", readdraw); - ANGLE_TRY + if (readdraw == EGL_READ) { - if (readdraw == EGL_READ) - { - EGLSurface read = egl::getCurrentReadSurface(); - return egl::success(read); - } - else if (readdraw == EGL_DRAW) - { - EGLSurface draw = egl::getCurrentDrawSurface(); - return egl::success(draw); - } - else - { - return egl::error(EGL_BAD_PARAMETER, EGL_NO_SURFACE); - } + EGLSurface read = egl::getCurrentReadSurface(); + return egl::success(read); } - ANGLE_CATCH_ALL + else if (readdraw == EGL_DRAW) { - return egl::error(EGL_BAD_ALLOC, EGL_NO_SURFACE); + EGLSurface draw = egl::getCurrentDrawSurface(); + return egl::success(draw); + } + else + { + return egl::error(EGL_BAD_PARAMETER, EGL_NO_SURFACE); } } @@ -988,16 +873,9 @@ EGLDisplay __stdcall eglGetCurrentDisplay(void) { EVENT("()"); - ANGLE_TRY - { - EGLDisplay dpy = egl::getCurrentDisplay(); + EGLDisplay dpy = egl::getCurrentDisplay(); - return egl::success(dpy); - } - ANGLE_CATCH_ALL - { - return egl::error(EGL_BAD_ALLOC, EGL_NO_DISPLAY); - } + return egl::success(dpy); } EGLBoolean __stdcall eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value) @@ -1005,90 +883,62 @@ EGLBoolean __stdcall eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attr EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)", dpy, ctx, attribute, value); - ANGLE_TRY + egl::Display *display = static_cast(dpy); + gl::Context *context = static_cast(ctx); + + if (!validateContext(display, context)) { - egl::Display *display = static_cast(dpy); - gl::Context *context = static_cast(ctx); - - if (!validateContext(display, context)) - { - return EGL_FALSE; - } - - UNIMPLEMENTED(); // FIXME - - return egl::success(0); - } - ANGLE_CATCH_ALL - { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); + return EGL_FALSE; } + + UNIMPLEMENTED(); // FIXME + + return egl::success(0); } EGLBoolean __stdcall eglWaitGL(void) { EVENT("()"); - ANGLE_TRY - { - UNIMPLEMENTED(); // FIXME + UNIMPLEMENTED(); // FIXME - return egl::success(0); - } - ANGLE_CATCH_ALL - { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); - } + return egl::success(0); } EGLBoolean __stdcall eglWaitNative(EGLint engine) { EVENT("(EGLint engine = %d)", engine); - ANGLE_TRY - { - UNIMPLEMENTED(); // FIXME + UNIMPLEMENTED(); // FIXME - return egl::success(0); - } - ANGLE_CATCH_ALL - { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); - } + return egl::success(0); } EGLBoolean __stdcall eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) { EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p)", dpy, surface); - ANGLE_TRY + egl::Display *display = static_cast(dpy); + egl::Surface *eglSurface = (egl::Surface*)surface; + + if (!validateSurface(display, eglSurface)) { - egl::Display *display = static_cast(dpy); - egl::Surface *eglSurface = (egl::Surface*)surface; - - if (!validateSurface(display, eglSurface)) - { - return EGL_FALSE; - } - - if (display->getRenderer()->isDeviceLost()) - { - return egl::error(EGL_CONTEXT_LOST, EGL_FALSE); - } - - if (surface == EGL_NO_SURFACE) - { - return egl::error(EGL_BAD_SURFACE, EGL_FALSE); - } - - if (eglSurface->swap()) - { - return egl::success(EGL_TRUE); - } + return EGL_FALSE; } - ANGLE_CATCH_ALL + + if (display->getRenderer()->isDeviceLost()) { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_CONTEXT_LOST, EGL_FALSE); + } + + if (surface == EGL_NO_SURFACE) + { + return egl::error(EGL_BAD_SURFACE, EGL_FALSE); + } + + if (eglSurface->swap()) + { + return egl::success(EGL_TRUE); } return EGL_FALSE; @@ -1098,68 +948,54 @@ EGLBoolean __stdcall eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativ { EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLNativePixmapType target = 0x%0.8p)", dpy, surface, target); - ANGLE_TRY + egl::Display *display = static_cast(dpy); + egl::Surface *eglSurface = static_cast(surface); + + if (!validateSurface(display, eglSurface)) { - egl::Display *display = static_cast(dpy); - egl::Surface *eglSurface = static_cast(surface); - - if (!validateSurface(display, eglSurface)) - { - return EGL_FALSE; - } - - if (display->getRenderer()->isDeviceLost()) - { - return egl::error(EGL_CONTEXT_LOST, EGL_FALSE); - } - - UNIMPLEMENTED(); // FIXME - - return egl::success(0); + return EGL_FALSE; } - ANGLE_CATCH_ALL + + if (display->getRenderer()->isDeviceLost()) { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_CONTEXT_LOST, EGL_FALSE); } + + UNIMPLEMENTED(); // FIXME + + return egl::success(0); } EGLBoolean __stdcall eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height) { EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint x = %d, EGLint y = %d, EGLint width = %d, EGLint height = %d)", dpy, surface, x, y, width, height); - ANGLE_TRY + if (x < 0 || y < 0 || width < 0 || height < 0) { - if (x < 0 || y < 0 || width < 0 || height < 0) - { - return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); - } - - egl::Display *display = static_cast(dpy); - egl::Surface *eglSurface = static_cast(surface); - - if (!validateSurface(display, eglSurface)) - { - return EGL_FALSE; - } - - if (display->getRenderer()->isDeviceLost()) - { - return egl::error(EGL_CONTEXT_LOST, EGL_FALSE); - } - - if (surface == EGL_NO_SURFACE) - { - return egl::error(EGL_BAD_SURFACE, EGL_FALSE); - } - - if (eglSurface->postSubBuffer(x, y, width, height)) - { - return egl::success(EGL_TRUE); - } + return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); } - ANGLE_CATCH_ALL + + egl::Display *display = static_cast(dpy); + egl::Surface *eglSurface = static_cast(surface); + + if (!validateSurface(display, eglSurface)) { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); + return EGL_FALSE; + } + + if (display->getRenderer()->isDeviceLost()) + { + return egl::error(EGL_CONTEXT_LOST, EGL_FALSE); + } + + if (surface == EGL_NO_SURFACE) + { + return egl::error(EGL_BAD_SURFACE, EGL_FALSE); + } + + if (eglSurface->postSubBuffer(x, y, width, height)) + { + return egl::success(EGL_TRUE); } return EGL_FALSE; @@ -1169,34 +1005,28 @@ __eglMustCastToProperFunctionPointerType __stdcall eglGetProcAddress(const char { EVENT("(const char *procname = \"%s\")", procname); - ANGLE_TRY + struct Extension { - struct Extension - { - const char *name; - __eglMustCastToProperFunctionPointerType address; - }; + const char *name; + __eglMustCastToProperFunctionPointerType address; + }; - static const Extension eglExtensions[] = - { - {"eglQuerySurfacePointerANGLE", (__eglMustCastToProperFunctionPointerType)eglQuerySurfacePointerANGLE}, - {"eglPostSubBufferNV", (__eglMustCastToProperFunctionPointerType)eglPostSubBufferNV}, - {"", NULL}, - }; + static const Extension eglExtensions[] = + { + { "eglQuerySurfacePointerANGLE", (__eglMustCastToProperFunctionPointerType)eglQuerySurfacePointerANGLE }, + { "eglPostSubBufferNV", (__eglMustCastToProperFunctionPointerType)eglPostSubBufferNV }, + { "eglGetPlatformDisplayEXT", (__eglMustCastToProperFunctionPointerType)eglGetPlatformDisplayEXT }, + { "", NULL }, + }; - for (unsigned int ext = 0; ext < ArraySize(eglExtensions); ext++) + for (unsigned int ext = 0; ext < ArraySize(eglExtensions); ext++) + { + if (strcmp(procname, eglExtensions[ext].name) == 0) { - if (strcmp(procname, eglExtensions[ext].name) == 0) - { - return (__eglMustCastToProperFunctionPointerType)eglExtensions[ext].address; - } + return (__eglMustCastToProperFunctionPointerType)eglExtensions[ext].address; } + } - return glGetProcAddress(procname); - } - ANGLE_CATCH_ALL - { - return egl::error(EGL_BAD_ALLOC, (__eglMustCastToProperFunctionPointerType)NULL); - } + return glGetProcAddress(procname); } } diff --git a/gfx/angle/src/libEGL/libEGL.def b/gfx/angle/src/libEGL/libEGL.def index 71a5e6797704..d7949d03543a 100644 --- a/gfx/angle/src/libEGL/libEGL.def +++ b/gfx/angle/src/libEGL/libEGL.def @@ -1,36 +1,41 @@ -LIBRARY libEGL +LIBRARY libEGL EXPORTS - eglBindAPI @14 - eglBindTexImage @20 - eglChooseConfig @7 - eglCopyBuffers @33 - eglCreateContext @23 - eglCreatePbufferFromClientBuffer @18 - eglCreatePbufferSurface @10 - eglCreatePixmapSurface @11 - eglCreateWindowSurface @9 - eglDestroyContext @24 - eglDestroySurface @12 - eglGetConfigAttrib @8 - eglGetConfigs @6 - eglGetCurrentContext @26 - eglGetCurrentDisplay @28 - eglGetCurrentSurface @27 - eglGetDisplay @2 - eglGetError @1 - eglGetProcAddress @34 - eglInitialize @3 - eglMakeCurrent @25 - eglQueryAPI @15 - eglQueryContext @29 - eglQueryString @5 - eglQuerySurface @13 - eglReleaseTexImage @21 - eglReleaseThread @17 - eglSurfaceAttrib @19 - eglSwapBuffers @32 - eglSwapInterval @22 - eglTerminate @4 - eglWaitClient @16 - eglWaitGL @30 - eglWaitNative @31 \ No newline at end of file + eglBindAPI @14 + eglBindTexImage @20 + eglChooseConfig @7 + eglCopyBuffers @33 + eglCreateContext @23 + eglCreatePbufferFromClientBuffer @18 + eglCreatePbufferSurface @10 + eglCreatePixmapSurface @11 + eglCreateWindowSurface @9 + eglDestroyContext @24 + eglDestroySurface @12 + eglGetConfigAttrib @8 + eglGetConfigs @6 + eglGetCurrentContext @26 + eglGetCurrentDisplay @28 + eglGetCurrentSurface @27 + eglGetDisplay @2 + eglGetError @1 + eglGetProcAddress @34 + eglInitialize @3 + eglMakeCurrent @25 + eglQueryAPI @15 + eglQueryContext @29 + eglQueryString @5 + eglQuerySurface @13 + eglReleaseTexImage @21 + eglReleaseThread @17 + eglSurfaceAttrib @19 + eglSwapBuffers @32 + eglSwapInterval @22 + eglTerminate @4 + eglWaitClient @16 + eglWaitGL @30 + eglWaitNative @31 + + ; Extensions + eglGetPlatformDisplayEXT @35 + eglQuerySurfacePointerANGLE @36 + eglPostSubBufferNV @37 diff --git a/gfx/angle/src/libEGL/main.cpp b/gfx/angle/src/libEGL/main.cpp index 80dcc3458075..0f8439c4a453 100644 --- a/gfx/angle/src/libEGL/main.cpp +++ b/gfx/angle/src/libEGL/main.cpp @@ -9,42 +9,42 @@ #include "libEGL/main.h" #include "common/debug.h" +#include "common/tls.h" -static DWORD currentTLS = TLS_OUT_OF_INDEXES; +static TLSIndex currentTLS = TLS_OUT_OF_INDEXES; namespace egl { Current *AllocateCurrent() { - Current *current = (egl::Current*)LocalAlloc(LPTR, sizeof(egl::Current)); - - if (!current) + ASSERT(currentTLS != TLS_OUT_OF_INDEXES); + if (currentTLS == TLS_OUT_OF_INDEXES) { - ERR("Could not allocate thread local storage."); return NULL; } - ASSERT(currentTLS != TLS_OUT_OF_INDEXES); - TlsSetValue(currentTLS, current); - + Current *current = new Current(); current->error = EGL_SUCCESS; current->API = EGL_OPENGL_ES_API; current->display = EGL_NO_DISPLAY; current->drawSurface = EGL_NO_SURFACE; current->readSurface = EGL_NO_SURFACE; + if (!SetTLSValue(currentTLS, current)) + { + ERR("Could not set thread local storage."); + return NULL; + } + return current; } void DeallocateCurrent() { - void *current = TlsGetValue(currentTLS); - - if (current) - { - LocalFree((HLOCAL)current); - } + Current *current = reinterpret_cast(GetTLSValue(currentTLS)); + SafeDelete(current); + SetTLSValue(currentTLS, NULL); } } @@ -70,14 +70,13 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved } #endif - currentTLS = TlsAlloc(); - + currentTLS = CreateTLSIndex(); if (currentTLS == TLS_OUT_OF_INDEXES) { return FALSE; } } - // Fall throught to initialize index + // Fall through to initialize index case DLL_THREAD_ATTACH: { egl::AllocateCurrent(); @@ -91,7 +90,7 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved case DLL_PROCESS_DETACH: { egl::DeallocateCurrent(); - TlsFree(currentTLS); + DestroyTLSIndex(currentTLS); } break; default: @@ -106,7 +105,7 @@ namespace egl Current *GetCurrentData() { - Current *current = (Current*)TlsGetValue(currentTLS); + Current *current = reinterpret_cast(GetTLSValue(currentTLS)); // ANGLE issue 488: when the dll is loaded after thread initialization, // thread local storage (current) might not exist yet. diff --git a/gfx/angle/src/libEGL/main.h b/gfx/angle/src/libEGL/main.h index 77da8f0f8e73..07f5b9e6754e 100644 --- a/gfx/angle/src/libEGL/main.h +++ b/gfx/angle/src/libEGL/main.h @@ -9,7 +9,6 @@ #ifndef LIBEGL_MAIN_H_ #define LIBEGL_MAIN_H_ -#define EGLAPI #include #include diff --git a/gfx/angle/src/libEGL/moz.build b/gfx/angle/src/libEGL/moz.build index 1542034fd06e..636812642c8e 100644 --- a/gfx/angle/src/libEGL/moz.build +++ b/gfx/angle/src/libEGL/moz.build @@ -2,11 +2,12 @@ # Please note this file is autogenerated from generate_mozbuild.py, so do not modify it directly UNIFIED_SOURCES += [ - '../common/blocklayout.cpp', + '../common/angleutils.cpp', '../common/debug.cpp', '../common/event_tracer.cpp', '../common/mathutil.cpp', '../common/RefCountObject.cpp', + '../common/tls.cpp', '../common/utilities.cpp', 'Config.cpp', 'Display.cpp', @@ -53,6 +54,7 @@ DISABLE_STL_WRAPPING = True LOCAL_INCLUDES += [ '../../include', '../../src' ] USE_LIBS += [ 'libGLESv2' ] +EXTRA_DSO_LDOPTS += [ '../libGLESv2/libGLESv2.lib' ] SharedLibrary('libEGL') diff --git a/gfx/angle/src/libGLESv2.gypi b/gfx/angle/src/libGLESv2.gypi index b2dce1224da6..bc0c31067734 100644 --- a/gfx/angle/src/libGLESv2.gypi +++ b/gfx/angle/src/libGLESv2.gypi @@ -7,15 +7,300 @@ { 'angle_enable_d3d9%': 1, 'angle_enable_d3d11%': 1, - }, - 'target_defaults': - { - 'defines': + # These file lists are shared with the GN build. + 'angle_libglesv2_sources': [ - 'ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES={ TEXT("d3dcompiler_46.dll"), TEXT("d3dcompiler_43.dll") }', + '../include/EGL/egl.h', + '../include/EGL/eglext.h', + '../include/EGL/eglplatform.h', + '../include/GLES2/gl2.h', + '../include/GLES2/gl2ext.h', + '../include/GLES2/gl2platform.h', + '../include/GLES3/gl3.h', + '../include/GLES3/gl3ext.h', + '../include/GLES3/gl3platform.h', + '../include/GLSLANG/ShaderLang.h', + '../include/GLSLANG/ShaderVars.h', + '../include/KHR/khrplatform.h', + '../include/angle_gl.h', + 'common/RefCountObject.cpp', + 'common/RefCountObject.h', + 'common/angleutils.cpp', + 'common/angleutils.h', + 'common/blocklayout.cpp', + 'common/blocklayout.h', + 'common/debug.cpp', + 'common/debug.h', + 'common/event_tracer.cpp', + 'common/event_tracer.h', + 'common/mathutil.cpp', + 'common/mathutil.h', + 'common/platform.h', + 'common/tls.cpp', + 'common/tls.h', + 'common/utilities.cpp', + 'common/utilities.h', + 'common/version.h', + 'libGLESv2/BinaryStream.h', + 'libGLESv2/Buffer.cpp', + 'libGLESv2/Buffer.h', + 'libGLESv2/Caps.cpp', + 'libGLESv2/Caps.h', + 'libGLESv2/Context.cpp', + 'libGLESv2/Context.h', + 'libGLESv2/Error.cpp', + 'libGLESv2/Error.h', + 'libGLESv2/Fence.cpp', + 'libGLESv2/Fence.h', + 'libGLESv2/Float16ToFloat32.cpp', + 'libGLESv2/Framebuffer.cpp', + 'libGLESv2/Framebuffer.h', + 'libGLESv2/FramebufferAttachment.cpp', + 'libGLESv2/FramebufferAttachment.h', + 'libGLESv2/HandleAllocator.cpp', + 'libGLESv2/HandleAllocator.h', + 'libGLESv2/Program.cpp', + 'libGLESv2/Program.h', + 'libGLESv2/ProgramBinary.cpp', + 'libGLESv2/ProgramBinary.h', + 'libGLESv2/Query.cpp', + 'libGLESv2/Query.h', + 'libGLESv2/Renderbuffer.cpp', + 'libGLESv2/Renderbuffer.h', + 'libGLESv2/ResourceManager.cpp', + 'libGLESv2/ResourceManager.h', + 'libGLESv2/Sampler.cpp', + 'libGLESv2/Sampler.h', + 'libGLESv2/Shader.cpp', + 'libGLESv2/Shader.h', + 'libGLESv2/State.cpp', + 'libGLESv2/State.h', + 'libGLESv2/Texture.cpp', + 'libGLESv2/Texture.h', + 'libGLESv2/TransformFeedback.cpp', + 'libGLESv2/TransformFeedback.h', + 'libGLESv2/Uniform.cpp', + 'libGLESv2/Uniform.h', + 'libGLESv2/VertexArray.cpp', + 'libGLESv2/VertexArray.h', + 'libGLESv2/VertexAttribute.cpp', + 'libGLESv2/VertexAttribute.h', + 'libGLESv2/angletypes.cpp', + 'libGLESv2/angletypes.h', + 'libGLESv2/constants.h', + 'libGLESv2/formatutils.cpp', + 'libGLESv2/formatutils.h', + 'libGLESv2/libGLESv2.cpp', + 'libGLESv2/libGLESv2.def', + 'libGLESv2/libGLESv2.rc', + 'libGLESv2/main.cpp', + 'libGLESv2/main.h', + 'libGLESv2/queryconversions.cpp', + 'libGLESv2/queryconversions.h', + 'libGLESv2/renderer/BufferImpl.h', + 'libGLESv2/renderer/FenceImpl.h', + 'libGLESv2/renderer/Image.cpp', + 'libGLESv2/renderer/Image.h', + 'libGLESv2/renderer/IndexRangeCache.cpp', + 'libGLESv2/renderer/IndexRangeCache.h', + 'libGLESv2/renderer/QueryImpl.h', + 'libGLESv2/renderer/RenderTarget.h', + 'libGLESv2/renderer/Renderer.cpp', + 'libGLESv2/renderer/Renderer.h', + 'libGLESv2/renderer/ShaderExecutable.h', + 'libGLESv2/renderer/ShaderImpl.h', + 'libGLESv2/renderer/SwapChain.h', + 'libGLESv2/renderer/TextureImpl.h', + 'libGLESv2/renderer/TransformFeedbackImpl.h', + 'libGLESv2/renderer/VertexArrayImpl.h', + 'libGLESv2/renderer/copyimage.cpp', + 'libGLESv2/renderer/copyimage.h', + 'libGLESv2/renderer/copyimage.inl', + 'libGLESv2/renderer/copyvertex.h', + 'libGLESv2/renderer/copyvertex.inl', + 'libGLESv2/renderer/generatemip.h', + 'libGLESv2/renderer/generatemip.inl', + 'libGLESv2/renderer/imageformats.h', + 'libGLESv2/renderer/loadimage.cpp', + 'libGLESv2/renderer/loadimage.h', + 'libGLESv2/renderer/loadimage.inl', + 'libGLESv2/renderer/loadimageSSE2.cpp', + 'libGLESv2/renderer/vertexconversion.h', + 'libGLESv2/resource.h', + 'libGLESv2/validationES.cpp', + 'libGLESv2/validationES.h', + 'libGLESv2/validationES2.cpp', + 'libGLESv2/validationES2.h', + 'libGLESv2/validationES3.cpp', + 'libGLESv2/validationES3.h', + 'third_party/murmurhash/MurmurHash3.cpp', + 'third_party/murmurhash/MurmurHash3.h', + 'third_party/systeminfo/SystemInfo.cpp', + 'third_party/systeminfo/SystemInfo.h', ], + 'angle_d3d_shared_sources': + [ + 'libGLESv2/renderer/d3d/BufferD3D.cpp', + 'libGLESv2/renderer/d3d/BufferD3D.h', + 'libGLESv2/renderer/d3d/DynamicHLSL.cpp', + 'libGLESv2/renderer/d3d/DynamicHLSL.h', + 'libGLESv2/renderer/d3d/HLSLCompiler.cpp', + 'libGLESv2/renderer/d3d/HLSLCompiler.h', + 'libGLESv2/renderer/d3d/ImageD3D.cpp', + 'libGLESv2/renderer/d3d/ImageD3D.h', + 'libGLESv2/renderer/d3d/IndexBuffer.cpp', + 'libGLESv2/renderer/d3d/IndexBuffer.h', + 'libGLESv2/renderer/d3d/IndexDataManager.cpp', + 'libGLESv2/renderer/d3d/IndexDataManager.h', + 'libGLESv2/renderer/d3d/MemoryBuffer.cpp', + 'libGLESv2/renderer/d3d/MemoryBuffer.h', + 'libGLESv2/renderer/d3d/ShaderD3D.cpp', + 'libGLESv2/renderer/d3d/ShaderD3D.h', + 'libGLESv2/renderer/d3d/TextureD3D.cpp', + 'libGLESv2/renderer/d3d/TextureD3D.h', + 'libGLESv2/renderer/d3d/TextureStorage.cpp', + 'libGLESv2/renderer/d3d/TextureStorage.h', + 'libGLESv2/renderer/d3d/TransformFeedbackD3D.cpp', + 'libGLESv2/renderer/d3d/TransformFeedbackD3D.h', + 'libGLESv2/renderer/d3d/VertexBuffer.cpp', + 'libGLESv2/renderer/d3d/VertexBuffer.h', + 'libGLESv2/renderer/d3d/VertexDataManager.cpp', + 'libGLESv2/renderer/d3d/VertexDataManager.h', + ], + 'angle_d3d9_sources': + [ + 'libGLESv2/renderer/d3d/d3d9/Blit9.cpp', + 'libGLESv2/renderer/d3d/d3d9/Blit9.h', + 'libGLESv2/renderer/d3d/d3d9/Buffer9.cpp', + 'libGLESv2/renderer/d3d/d3d9/Buffer9.h', + 'libGLESv2/renderer/d3d/d3d9/Fence9.cpp', + 'libGLESv2/renderer/d3d/d3d9/Fence9.h', + 'libGLESv2/renderer/d3d/d3d9/formatutils9.cpp', + 'libGLESv2/renderer/d3d/d3d9/formatutils9.h', + 'libGLESv2/renderer/d3d/d3d9/Image9.cpp', + 'libGLESv2/renderer/d3d/d3d9/Image9.h', + 'libGLESv2/renderer/d3d/d3d9/IndexBuffer9.cpp', + 'libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h', + 'libGLESv2/renderer/d3d/d3d9/Query9.cpp', + 'libGLESv2/renderer/d3d/d3d9/Query9.h', + 'libGLESv2/renderer/d3d/d3d9/Renderer9.cpp', + 'libGLESv2/renderer/d3d/d3d9/Renderer9.h', + 'libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp', + 'libGLESv2/renderer/d3d/d3d9/renderer9_utils.h', + 'libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp', + 'libGLESv2/renderer/d3d/d3d9/RenderTarget9.h', + 'libGLESv2/renderer/d3d/d3d9/ShaderCache.h', + 'libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.cpp', + 'libGLESv2/renderer/d3d/d3d9/shaders/compiled/componentmaskps.h', + 'libGLESv2/renderer/d3d/d3d9/shaders/compiled/flipyvs.h', + 'libGLESv2/renderer/d3d/d3d9/shaders/compiled/luminanceps.h', + 'libGLESv2/renderer/d3d/d3d9/shaders/compiled/passthroughps.h', + 'libGLESv2/renderer/d3d/d3d9/shaders/compiled/standardvs.h', + 'libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp', + 'libGLESv2/renderer/d3d/d3d9/SwapChain9.h', + 'libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp', + 'libGLESv2/renderer/d3d/d3d9/TextureStorage9.h', + 'libGLESv2/renderer/d3d/d3d9/VertexArray9.h', + 'libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp', + 'libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h', + 'libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.cpp', + 'libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h', + ], + 'angle_d3d11_sources': + [ + 'libGLESv2/renderer/d3d/d3d11/Blit11.cpp', + 'libGLESv2/renderer/d3d/d3d11/Blit11.h', + 'libGLESv2/renderer/d3d/d3d11/Buffer11.cpp', + 'libGLESv2/renderer/d3d/d3d11/Buffer11.h', + 'libGLESv2/renderer/d3d/d3d11/Clear11.cpp', + 'libGLESv2/renderer/d3d/d3d11/Clear11.h', + 'libGLESv2/renderer/d3d/d3d11/Fence11.cpp', + 'libGLESv2/renderer/d3d/d3d11/Fence11.h', + 'libGLESv2/renderer/d3d/d3d11/formatutils11.cpp', + 'libGLESv2/renderer/d3d/d3d11/formatutils11.h', + 'libGLESv2/renderer/d3d/d3d11/Image11.cpp', + 'libGLESv2/renderer/d3d/d3d11/Image11.h', + 'libGLESv2/renderer/d3d/d3d11/IndexBuffer11.cpp', + 'libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h', + 'libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp', + 'libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h', + 'libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp', + 'libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h', + 'libGLESv2/renderer/d3d/d3d11/Query11.cpp', + 'libGLESv2/renderer/d3d/d3d11/Query11.h', + 'libGLESv2/renderer/d3d/d3d11/Renderer11.cpp', + 'libGLESv2/renderer/d3d/d3d11/Renderer11.h', + 'libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp', + 'libGLESv2/renderer/d3d/d3d11/renderer11_utils.h', + 'libGLESv2/renderer/d3d/d3d11/RenderStateCache.cpp', + 'libGLESv2/renderer/d3d/d3d11/RenderStateCache.h', + 'libGLESv2/renderer/d3d/d3d11/RenderTarget11.cpp', + 'libGLESv2/renderer/d3d/d3d11/RenderTarget11.h', + 'libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.cpp', + 'libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_gs.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4f.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4i.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4ui.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_vs.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearfloat11vs.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearsint11ps.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearsint11vs.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearuint11ps.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearuint11vs.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough3d11gs.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough3d11vs.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughdepth2d11ps.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlum2d11ps.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlum3d11ps.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2d11ps.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha3d11ps.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2d11ps.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2di11ps.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2dui11ps.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3d11ps.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3di11ps.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3dui11ps.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2d11ps.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2di11ps.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dui11ps.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3d11ps.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3di11ps.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dui11ps.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2d11ps.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2di11ps.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dui11ps.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3d11ps.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3di11ps.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dui11ps.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2di11ps.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dui11ps.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d11ps.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3di11ps.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dui11ps.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlef2darrayps.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlef2dps.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlef3dps.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlei2darrayps.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlei3dps.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzleui2darrayps.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzleui2dps.h', + 'libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzleui3dps.h', + 'libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp', + 'libGLESv2/renderer/d3d/d3d11/SwapChain11.h', + 'libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp', + 'libGLESv2/renderer/d3d/d3d11/TextureStorage11.h', + 'libGLESv2/renderer/d3d/d3d11/VertexArray11.h', + 'libGLESv2/renderer/d3d/d3d11/VertexBuffer11.cpp', + 'libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h', + ] }, - + # Everything below this is duplicated in the GN build. If you change + # anything also change angle/BUILD.gn 'conditions': [ ['OS=="win"', @@ -35,26 +320,29 @@ ], 'sources': [ - ' +#include +#include + namespace gl { diff --git a/gfx/angle/src/libGLESv2/Buffer.cpp b/gfx/angle/src/libGLESv2/Buffer.cpp index e7d2c00f005b..c4fbe2b38bbd 100644 --- a/gfx/angle/src/libGLESv2/Buffer.cpp +++ b/gfx/angle/src/libGLESv2/Buffer.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -10,81 +9,68 @@ // [OpenGL ES 2.0.24] section 2.9 page 21. #include "libGLESv2/Buffer.h" - -#include "libGLESv2/renderer/VertexBuffer.h" -#include "libGLESv2/renderer/IndexBuffer.h" -#include "libGLESv2/renderer/BufferStorage.h" +#include "libGLESv2/renderer/BufferImpl.h" #include "libGLESv2/renderer/Renderer.h" namespace gl { -Buffer::Buffer(rx::Renderer *renderer, GLuint id) +Buffer::Buffer(rx::BufferImpl *impl, GLuint id) : RefCountObject(id), - mRenderer(renderer), + mBuffer(impl), mUsage(GL_DYNAMIC_DRAW), + mSize(0), mAccessFlags(0), mMapped(GL_FALSE), mMapPointer(NULL), mMapOffset(0), - mMapLength(0), - mBufferStorage(NULL), - mStaticVertexBuffer(NULL), - mStaticIndexBuffer(NULL), - mUnmodifiedDataUse(0) + mMapLength(0) { - mBufferStorage = renderer->createBufferStorage(); } Buffer::~Buffer() { - delete mBufferStorage; - delete mStaticVertexBuffer; - delete mStaticIndexBuffer; + SafeDelete(mBuffer); } void Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage) { - mBufferStorage->clear(); mIndexRangeCache.clear(); - mBufferStorage->setData(data, size, 0); - mUsage = usage; - - invalidateStaticData(); - - if (usage == GL_STATIC_DRAW) - { - mStaticVertexBuffer = new rx::StaticVertexBufferInterface(mRenderer); - mStaticIndexBuffer = new rx::StaticIndexBufferInterface(mRenderer); - } + mSize = size; + mBuffer->setData(data, size, usage); } void Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset) { - mBufferStorage->setData(data, size, offset); mIndexRangeCache.invalidateRange(offset, size); - invalidateStaticData(); + mBuffer->setSubData(data, size, offset); } void Buffer::copyBufferSubData(Buffer* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) { - mBufferStorage->copyData(source->mBufferStorage, size, sourceOffset, destOffset); - invalidateStaticData(); + mIndexRangeCache.invalidateRange(destOffset, size); + mBuffer->copySubData(source->getImplementation(), sourceOffset, destOffset, size); } GLvoid *Buffer::mapRange(GLintptr offset, GLsizeiptr length, GLbitfield access) { ASSERT(!mMapped); + ASSERT(offset + length <= mSize); - void *dataPointer = mBufferStorage->map(access); + void *dataPointer = mBuffer->map(offset, length, access); mMapped = GL_TRUE; - mMapPointer = static_cast(static_cast(dataPointer) + offset); + mMapPointer = static_cast(static_cast(dataPointer)); mMapOffset = static_cast(offset); mMapLength = static_cast(length); mAccessFlags = static_cast(access); + if ((access & GL_MAP_WRITE_BIT) > 0) + { + mIndexRangeCache.invalidateRange(offset, length); + } + return mMapPointer; } @@ -92,7 +78,7 @@ void Buffer::unmap() { ASSERT(mMapped); - mBufferStorage->unmap(); + mBuffer->unmap(); mMapped = GL_FALSE; mMapPointer = NULL; @@ -101,94 +87,11 @@ void Buffer::unmap() mAccessFlags = 0; } -rx::BufferStorage *Buffer::getStorage() const -{ - return mBufferStorage; -} - -GLint64 Buffer::size() const -{ - return static_cast(mBufferStorage->getSize()); -} - -GLenum Buffer::usage() const -{ - return mUsage; -} - -GLint Buffer::accessFlags() const -{ - return mAccessFlags; -} - -GLboolean Buffer::mapped() const -{ - return mMapped; -} - -GLvoid *Buffer::mapPointer() const -{ - return mMapPointer; -} - -GLint64 Buffer::mapOffset() const -{ - return mMapOffset; -} - -GLint64 Buffer::mapLength() const -{ - return mMapLength; -} - void Buffer::markTransformFeedbackUsage() { - mBufferStorage->markTransformFeedbackUsage(); - invalidateStaticData(); -} - -rx::StaticVertexBufferInterface *Buffer::getStaticVertexBuffer() -{ - return mStaticVertexBuffer; -} - -rx::StaticIndexBufferInterface *Buffer::getStaticIndexBuffer() -{ - return mStaticIndexBuffer; -} - -void Buffer::invalidateStaticData() -{ - if ((mStaticVertexBuffer && mStaticVertexBuffer->getBufferSize() != 0) || (mStaticIndexBuffer && mStaticIndexBuffer->getBufferSize() != 0)) - { - delete mStaticVertexBuffer; - mStaticVertexBuffer = NULL; - - delete mStaticIndexBuffer; - mStaticIndexBuffer = NULL; - } - - mUnmodifiedDataUse = 0; -} - -// Creates static buffers if sufficient used data has been left unmodified -void Buffer::promoteStaticUsage(int dataSize) -{ - if (!mStaticVertexBuffer && !mStaticIndexBuffer) - { - mUnmodifiedDataUse += dataSize; - - if (mUnmodifiedDataUse > 3 * mBufferStorage->getSize()) - { - mStaticVertexBuffer = new rx::StaticVertexBufferInterface(mRenderer); - mStaticIndexBuffer = new rx::StaticIndexBufferInterface(mRenderer); - } - } -} - -rx::IndexRangeCache *Buffer::getIndexRangeCache() -{ - return &mIndexRangeCache; + // TODO: Only used by the DX11 backend. Refactor to a more appropriate place. + mBuffer->markTransformFeedbackUsage(); + mIndexRangeCache.clear(); } } diff --git a/gfx/angle/src/libGLESv2/Buffer.h b/gfx/angle/src/libGLESv2/Buffer.h index 55fbdeb1c9b3..c39d7d7b42b8 100644 --- a/gfx/angle/src/libGLESv2/Buffer.h +++ b/gfx/angle/src/libGLESv2/Buffer.h @@ -18,9 +18,7 @@ namespace rx { class Renderer; -class BufferStorage; -class StaticIndexBufferInterface; -class StaticVertexBufferInterface; +class BufferImpl; }; namespace gl @@ -29,7 +27,7 @@ namespace gl class Buffer : public RefCountObject { public: - Buffer(rx::Renderer *renderer, GLuint id); + Buffer(rx::BufferImpl *impl, GLuint id); virtual ~Buffer(); @@ -39,43 +37,35 @@ class Buffer : public RefCountObject GLvoid *mapRange(GLintptr offset, GLsizeiptr length, GLbitfield access); void unmap(); - GLenum usage() const; - GLint accessFlags() const; - GLboolean mapped() const; - GLvoid *mapPointer() const; - GLint64 mapOffset() const; - GLint64 mapLength() const; + GLenum getUsage() const { return mUsage; } + GLint getAccessFlags() const { return mAccessFlags; } + GLboolean isMapped() const { return mMapped; } + GLvoid *getMapPointer() const { return mMapPointer; } + GLint64 getMapOffset() const { return mMapOffset; } + GLint64 getMapLength() const { return mMapLength; } + GLint64 getSize() const { return mSize; } - rx::BufferStorage *getStorage() const; - GLint64 size() const; + rx::BufferImpl *getImplementation() const { return mBuffer; } void markTransformFeedbackUsage(); - rx::StaticVertexBufferInterface *getStaticVertexBuffer(); - rx::StaticIndexBufferInterface *getStaticIndexBuffer(); - void invalidateStaticData(); - void promoteStaticUsage(int dataSize); - - rx::IndexRangeCache *getIndexRangeCache(); + rx::IndexRangeCache *getIndexRangeCache() { return &mIndexRangeCache; } + const rx::IndexRangeCache *getIndexRangeCache() const { return &mIndexRangeCache; } private: DISALLOW_COPY_AND_ASSIGN(Buffer); - rx::Renderer *mRenderer; + rx::BufferImpl *mBuffer; + GLenum mUsage; + GLint64 mSize; GLint mAccessFlags; GLboolean mMapped; GLvoid *mMapPointer; GLint64 mMapOffset; GLint64 mMapLength; - rx::BufferStorage *mBufferStorage; - rx::IndexRangeCache mIndexRangeCache; - - rx::StaticVertexBufferInterface *mStaticVertexBuffer; - rx::StaticIndexBufferInterface *mStaticIndexBuffer; - unsigned int mUnmodifiedDataUse; }; } diff --git a/gfx/angle/src/libGLESv2/Caps.cpp b/gfx/angle/src/libGLESv2/Caps.cpp new file mode 100644 index 000000000000..0c2b82105e12 --- /dev/null +++ b/gfx/angle/src/libGLESv2/Caps.cpp @@ -0,0 +1,420 @@ +// +// Copyright (c) 2014 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/Caps.h" +#include "common/debug.h" +#include "common/angleutils.h" + +#include "angle_gl.h" + +#include +#include + +namespace gl +{ + +TextureCaps::TextureCaps() + : texturable(false), + filterable(false), + renderable(false), + sampleCounts() +{ +} + +GLuint TextureCaps::getMaxSamples() const +{ + return !sampleCounts.empty() ? *sampleCounts.rbegin() : 0; +} + +GLuint TextureCaps::getNearestSamples(GLuint requestedSamples) const +{ + if (requestedSamples == 0) + { + return 0; + } + + for (SupportedSampleSet::const_iterator i = sampleCounts.begin(); i != sampleCounts.end(); i++) + { + GLuint samples = *i; + if (samples >= requestedSamples) + { + return samples; + } + } + + return 0; +} + +void TextureCapsMap::insert(GLenum internalFormat, const TextureCaps &caps) +{ + mCapsMap.insert(std::make_pair(internalFormat, caps)); +} + +void TextureCapsMap::remove(GLenum internalFormat) +{ + InternalFormatToCapsMap::iterator i = mCapsMap.find(internalFormat); + if (i != mCapsMap.end()) + { + mCapsMap.erase(i); + } +} + +const TextureCaps &TextureCapsMap::get(GLenum internalFormat) const +{ + static TextureCaps defaultUnsupportedTexture; + InternalFormatToCapsMap::const_iterator iter = mCapsMap.find(internalFormat); + return (iter != mCapsMap.end()) ? iter->second : defaultUnsupportedTexture; +} + +TextureCapsMap::const_iterator TextureCapsMap::begin() const +{ + return mCapsMap.begin(); +} + +TextureCapsMap::const_iterator TextureCapsMap::end() const +{ + return mCapsMap.end(); +} + +size_t TextureCapsMap::size() const +{ + return mCapsMap.size(); +} + +Extensions::Extensions() + : elementIndexUint(false), + packedDepthStencil(false), + getProgramBinary(false), + rgb8rgba8(false), + textureFormatBGRA8888(false), + readFormatBGRA(false), + pixelBufferObject(false), + mapBuffer(false), + mapBufferRange(false), + textureHalfFloat(false), + textureHalfFloatLinear(false), + textureFloat(false), + textureFloatLinear(false), + textureRG(false), + textureCompressionDXT1(false), + textureCompressionDXT3(false), + textureCompressionDXT5(false), + depthTextures(false), + textureNPOT(false), + drawBuffers(false), + textureStorage(false), + textureFilterAnisotropic(false), + maxTextureAnisotropy(false), + occlusionQueryBoolean(false), + fence(false), + timerQuery(false), + robustness(false), + blendMinMax(false), + framebufferBlit(false), + framebufferMultisample(false), + instancedArrays(false), + packReverseRowOrder(false), + standardDerivatives(false), + shaderTextureLOD(false), + fragDepth(false), + textureUsage(false), + translatedShaderSource(false), + colorBufferFloat(false) +{ +} + +static void InsertExtensionString(const std::string &extension, bool supported, std::vector *extensionVector) +{ + if (supported) + { + extensionVector->push_back(extension); + } +} + +std::vector Extensions::getStrings() const +{ + std::vector extensionStrings; + + // | Extension name | Supported flag | Output vector | + InsertExtensionString("GL_OES_element_index_uint", elementIndexUint, &extensionStrings); + InsertExtensionString("GL_OES_packed_depth_stencil", packedDepthStencil, &extensionStrings); + InsertExtensionString("GL_OES_get_program_binary", getProgramBinary, &extensionStrings); + InsertExtensionString("GL_OES_rgb8_rgba8", rgb8rgba8, &extensionStrings); + InsertExtensionString("GL_EXT_texture_format_BGRA8888", textureFormatBGRA8888, &extensionStrings); + InsertExtensionString("GL_EXT_read_format_bgra", readFormatBGRA, &extensionStrings); + InsertExtensionString("GL_NV_pixel_buffer_object", pixelBufferObject, &extensionStrings); + InsertExtensionString("GL_OES_mapbuffer", mapBuffer, &extensionStrings); + InsertExtensionString("GL_EXT_map_buffer_range", mapBufferRange, &extensionStrings); + InsertExtensionString("GL_OES_texture_half_float", textureHalfFloat, &extensionStrings); + InsertExtensionString("GL_OES_texture_half_float_linear", textureHalfFloatLinear, &extensionStrings); + InsertExtensionString("GL_OES_texture_float", textureFloat, &extensionStrings); + InsertExtensionString("GL_OES_texture_float_linear", textureFloatLinear, &extensionStrings); + InsertExtensionString("GL_EXT_texture_rg", textureRG, &extensionStrings); + InsertExtensionString("GL_EXT_texture_compression_dxt1", textureCompressionDXT1, &extensionStrings); + InsertExtensionString("GL_ANGLE_texture_compression_dxt3", textureCompressionDXT3, &extensionStrings); + InsertExtensionString("GL_ANGLE_texture_compression_dxt5", textureCompressionDXT5, &extensionStrings); + InsertExtensionString("GL_EXT_sRGB", sRGB, &extensionStrings); + InsertExtensionString("GL_ANGLE_depth_texture", depthTextures, &extensionStrings); + InsertExtensionString("GL_EXT_texture_storage", textureStorage, &extensionStrings); + InsertExtensionString("GL_OES_texture_npot", textureNPOT, &extensionStrings); + InsertExtensionString("GL_EXT_draw_buffers", drawBuffers, &extensionStrings); + InsertExtensionString("GL_EXT_texture_filter_anisotropic", textureFilterAnisotropic, &extensionStrings); + InsertExtensionString("GL_EXT_occlusion_query_boolean", occlusionQueryBoolean, &extensionStrings); + InsertExtensionString("GL_NV_fence", fence, &extensionStrings); + InsertExtensionString("GL_ANGLE_timer_query", timerQuery, &extensionStrings); + InsertExtensionString("GL_EXT_robustness", robustness, &extensionStrings); + InsertExtensionString("GL_EXT_blend_minmax", blendMinMax, &extensionStrings); + InsertExtensionString("GL_ANGLE_framebuffer_blit", framebufferBlit, &extensionStrings); + InsertExtensionString("GL_ANGLE_framebuffer_multisample", framebufferMultisample, &extensionStrings); + InsertExtensionString("GL_ANGLE_instanced_arrays", instancedArrays, &extensionStrings); + InsertExtensionString("GL_ANGLE_pack_reverse_row_order", packReverseRowOrder, &extensionStrings); + InsertExtensionString("GL_OES_standard_derivatives", standardDerivatives, &extensionStrings); + InsertExtensionString("GL_EXT_shader_texture_lod", shaderTextureLOD, &extensionStrings); + InsertExtensionString("GL_EXT_frag_depth", fragDepth, &extensionStrings); + InsertExtensionString("GL_ANGLE_texture_usage", textureUsage, &extensionStrings); + InsertExtensionString("GL_ANGLE_translated_shader_source", translatedShaderSource, &extensionStrings); + InsertExtensionString("GL_EXT_color_buffer_float", colorBufferFloat, &extensionStrings); + + return extensionStrings; +} + +static bool GetFormatSupport(const TextureCapsMap &textureCaps, const std::vector &requiredFormats, + bool requiresFiltering, bool requiresRendering) +{ + for (size_t i = 0; i < requiredFormats.size(); i++) + { + const TextureCaps &cap = textureCaps.get(requiredFormats[i]); + + if (requiresFiltering && !cap.filterable) + { + return false; + } + + if (requiresRendering && !cap.renderable) + { + return false; + } + } + + return true; +} + +// Checks for GL_OES_rgb8_rgba8 support +static bool DetermineRGB8AndRGBA8TextureSupport(const TextureCapsMap &textureCaps) +{ + std::vector requiredFormats; + requiredFormats.push_back(GL_RGB8); + requiredFormats.push_back(GL_RGBA8); + + return GetFormatSupport(textureCaps, requiredFormats, true, true); +} + +// Checks for GL_EXT_texture_format_BGRA8888 support +static bool DetermineBGRA8TextureSupport(const TextureCapsMap &textureCaps) +{ + std::vector requiredFormats; + requiredFormats.push_back(GL_BGRA8_EXT); + + return GetFormatSupport(textureCaps, requiredFormats, true, true); +} + +// Checks for GL_OES_texture_half_float support +static bool DetermineHalfFloatTextureSupport(const TextureCapsMap &textureCaps) +{ + std::vector requiredFormats; + requiredFormats.push_back(GL_RGB16F); + requiredFormats.push_back(GL_RGBA16F); + + return GetFormatSupport(textureCaps, requiredFormats, false, true); +} + +// Checks for GL_OES_texture_half_float_linear support +static bool DetermineHalfFloatTextureFilteringSupport(const TextureCapsMap &textureCaps) +{ + std::vector requiredFormats; + requiredFormats.push_back(GL_RGB16F); + requiredFormats.push_back(GL_RGBA16F); + + return GetFormatSupport(textureCaps, requiredFormats, true, false); +} + +// Checks for GL_OES_texture_float support +static bool DetermineFloatTextureSupport(const TextureCapsMap &textureCaps) +{ + std::vector requiredFormats; + requiredFormats.push_back(GL_RGB32F); + requiredFormats.push_back(GL_RGBA32F); + + return GetFormatSupport(textureCaps, requiredFormats, false, true); +} + +// Checks for GL_OES_texture_float_linear support +static bool DetermineFloatTextureFilteringSupport(const TextureCapsMap &textureCaps) +{ + std::vector requiredFormats; + requiredFormats.push_back(GL_RGB32F); + requiredFormats.push_back(GL_RGBA32F); + + return GetFormatSupport(textureCaps, requiredFormats, true, false); +} + +// Checks for GL_EXT_texture_rg support +static bool DetermineRGTextureSupport(const TextureCapsMap &textureCaps, bool checkHalfFloatFormats, bool checkFloatFormats) +{ + std::vector requiredFormats; + requiredFormats.push_back(GL_R8); + requiredFormats.push_back(GL_RG8); + if (checkHalfFloatFormats) + { + requiredFormats.push_back(GL_R16F); + requiredFormats.push_back(GL_RG16F); + } + if (checkFloatFormats) + { + requiredFormats.push_back(GL_R32F); + requiredFormats.push_back(GL_RG32F); + } + + return GetFormatSupport(textureCaps, requiredFormats, true, false); +} + +// Check for GL_EXT_texture_compression_dxt1 +static bool DetermineDXT1TextureSupport(const TextureCapsMap &textureCaps) +{ + std::vector requiredFormats; + requiredFormats.push_back(GL_COMPRESSED_RGB_S3TC_DXT1_EXT); + requiredFormats.push_back(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT); + + return GetFormatSupport(textureCaps, requiredFormats, true, false); +} + +// Check for GL_ANGLE_texture_compression_dxt3 +static bool DetermineDXT3TextureSupport(const TextureCapsMap &textureCaps) +{ + std::vector requiredFormats; + requiredFormats.push_back(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE); + + return GetFormatSupport(textureCaps, requiredFormats, true, false); +} + +// Check for GL_ANGLE_texture_compression_dxt5 +static bool DetermineDXT5TextureSupport(const TextureCapsMap &textureCaps) +{ + std::vector requiredFormats; + requiredFormats.push_back(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE); + + return GetFormatSupport(textureCaps, requiredFormats, true, false); +} + +// Check for GL_ANGLE_texture_compression_dxt5 +static bool DetermineSRGBTextureSupport(const TextureCapsMap &textureCaps) +{ + std::vector requiredFilterFormats; + requiredFilterFormats.push_back(GL_SRGB8); + requiredFilterFormats.push_back(GL_SRGB8_ALPHA8); + + std::vector requiredRenderFormats; + requiredRenderFormats.push_back(GL_SRGB8_ALPHA8); + + return GetFormatSupport(textureCaps, requiredFilterFormats, true, false) && + GetFormatSupport(textureCaps, requiredRenderFormats, false, true); +} + +// Check for GL_ANGLE_depth_texture +static bool DetermineDepthTextureSupport(const TextureCapsMap &textureCaps) +{ + std::vector requiredFormats; + requiredFormats.push_back(GL_DEPTH_COMPONENT16); + requiredFormats.push_back(GL_DEPTH_COMPONENT32_OES); + requiredFormats.push_back(GL_DEPTH24_STENCIL8_OES); + + return GetFormatSupport(textureCaps, requiredFormats, true, true); +} + +// Check for GL_EXT_color_buffer_float +static bool DetermineColorBufferFloatSupport(const TextureCapsMap &textureCaps) +{ + std::vector requiredFormats; + requiredFormats.push_back(GL_R16F); + requiredFormats.push_back(GL_RG16F); + requiredFormats.push_back(GL_RGBA16F); + requiredFormats.push_back(GL_R32F); + requiredFormats.push_back(GL_RG32F); + requiredFormats.push_back(GL_RGBA32F); + requiredFormats.push_back(GL_R11F_G11F_B10F); + + return GetFormatSupport(textureCaps, requiredFormats, false, true); +} + +void Extensions::setTextureExtensionSupport(const TextureCapsMap &textureCaps) +{ + rgb8rgba8 = DetermineRGB8AndRGBA8TextureSupport(textureCaps); + textureFormatBGRA8888 = DetermineBGRA8TextureSupport(textureCaps); + textureHalfFloat = DetermineHalfFloatTextureSupport(textureCaps); + textureHalfFloatLinear = DetermineHalfFloatTextureFilteringSupport(textureCaps); + textureFloat = DetermineFloatTextureSupport(textureCaps); + textureFloatLinear = DetermineFloatTextureFilteringSupport(textureCaps); + textureRG = DetermineRGTextureSupport(textureCaps, textureHalfFloat, textureFloat); + textureCompressionDXT1 = DetermineDXT1TextureSupport(textureCaps); + textureCompressionDXT3 = DetermineDXT3TextureSupport(textureCaps); + textureCompressionDXT5 = DetermineDXT5TextureSupport(textureCaps); + sRGB = DetermineSRGBTextureSupport(textureCaps); + depthTextures = DetermineDepthTextureSupport(textureCaps); + colorBufferFloat = DetermineColorBufferFloatSupport(textureCaps); +} + +Caps::Caps() + : maxElementIndex(0), + max3DTextureSize(0), + max2DTextureSize(0), + maxArrayTextureLayers(0), + maxLODBias(0), + maxCubeMapTextureSize(0), + maxRenderbufferSize(0), + maxDrawBuffers(0), + maxColorAttachments(0), + maxViewportWidth(0), + maxViewportHeight(0), + minAliasedPointSize(0), + maxAliasedPointSize(0), + minAliasedLineWidth(0), + // Table 6.29 + maxElementsIndices(0), + maxElementsVertices(0), + maxServerWaitTimeout(0), + // Table 6.31 + maxVertexAttributes(0), + maxVertexUniformComponents(0), + maxVertexUniformVectors(0), + maxVertexUniformBlocks(0), + maxVertexOutputComponents(0), + maxVertexTextureImageUnits(0), + // Table 6.32 + maxFragmentUniformComponents(0), + maxFragmentUniformVectors(0), + maxFragmentUniformBlocks(0), + maxFragmentInputComponents(0), + maxTextureImageUnits(0), + minProgramTexelOffset(0), + maxProgramTexelOffset(0), + + maxUniformBufferBindings(0), + maxUniformBlockSize(0), + uniformBufferOffsetAlignment(0), + maxCombinedUniformBlocks(0), + maxCombinedVertexUniformComponents(0), + maxCombinedFragmentUniformComponents(0), + maxVaryingComponents(0), + maxVaryingVectors(0), + maxCombinedTextureImageUnits(0), + + maxTransformFeedbackInterleavedComponents(0), + maxTransformFeedbackSeparateAttributes(0), + maxTransformFeedbackSeparateComponents(0) +{ +} + +} diff --git a/gfx/angle/src/libGLESv2/Caps.h b/gfx/angle/src/libGLESv2/Caps.h new file mode 100644 index 000000000000..a00e554176a0 --- /dev/null +++ b/gfx/angle/src/libGLESv2/Caps.h @@ -0,0 +1,273 @@ +#ifndef LIBGLESV2_CAPS_H +#define LIBGLESV2_CAPS_H + +// +// Copyright (c) 2014 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 "angle_gl.h" + +#include +#include +#include +#include + +namespace gl +{ + +typedef std::set SupportedSampleSet; + +struct TextureCaps +{ + TextureCaps(); + + // Supports for basic texturing: glTexImage, glTexSubImage, etc + bool texturable; + + // Support for linear or anisotropic filtering + bool filterable; + + // Support for being used as a framebuffer attachment or renderbuffer format + bool renderable; + + SupportedSampleSet sampleCounts; + + // Get the maximum number of samples supported + GLuint getMaxSamples() const; + + // Get the number of supported samples that is at least as many as requested. Returns 0 if + // there are no sample counts available + GLuint getNearestSamples(GLuint requestedSamples) const; +}; + +class TextureCapsMap +{ + public: + typedef std::unordered_map::const_iterator const_iterator; + + void insert(GLenum internalFormat, const TextureCaps &caps); + void remove(GLenum internalFormat); + + const TextureCaps &get(GLenum internalFormat) const; + + const_iterator begin() const; + const_iterator end() const; + + size_t size() const; + + private: + typedef std::unordered_map InternalFormatToCapsMap; + InternalFormatToCapsMap mCapsMap; +}; + +struct Extensions +{ + Extensions(); + + // Generate a vector of supported extension strings + std::vector getStrings() const; + + // Set all texture related extension support based on the supported textures. + // Determines support for: + // GL_OES_rgb8_rgba8 + // GL_EXT_texture_format_BGRA8888 + // GL_OES_texture_half_float, GL_OES_texture_half_float_linear + // GL_OES_texture_float, GL_OES_texture_float_linear + // GL_EXT_texture_rg + // GL_EXT_texture_compression_dxt1, GL_ANGLE_texture_compression_dxt3, GL_ANGLE_texture_compression_dxt5 + // GL_EXT_sRGB + // GL_ANGLE_depth_texture + // GL_EXT_color_buffer_float + void setTextureExtensionSupport(const TextureCapsMap &textureCaps); + + // ES2 Extension support + + // GL_OES_element_index_uint + bool elementIndexUint; + + // GL_OES_packed_depth_stencil + bool packedDepthStencil; + + // GL_OES_get_program_binary + bool getProgramBinary; + + // GL_OES_rgb8_rgba8 + // Implies that TextureCaps for GL_RGB8 and GL_RGBA8 exist + bool rgb8rgba8; + + // GL_EXT_texture_format_BGRA8888 + // Implies that TextureCaps for GL_BGRA8 exist + bool textureFormatBGRA8888; + + // GL_EXT_read_format_bgra + bool readFormatBGRA; + + // GL_NV_pixel_buffer_object + bool pixelBufferObject; + + // GL_OES_mapbuffer and GL_EXT_map_buffer_range + bool mapBuffer; + bool mapBufferRange; + + // GL_OES_texture_half_float and GL_OES_texture_half_float_linear + // Implies that TextureCaps for GL_RGB16F, GL_RGBA16F, GL_ALPHA32F_EXT, GL_LUMINANCE32F_EXT and + // GL_LUMINANCE_ALPHA32F_EXT exist + bool textureHalfFloat; + bool textureHalfFloatLinear; + + // GL_OES_texture_float and GL_OES_texture_float_linear + // Implies that TextureCaps for GL_RGB32F, GL_RGBA32F, GL_ALPHA16F_EXT, GL_LUMINANCE16F_EXT and + // GL_LUMINANCE_ALPHA16F_EXT exist + bool textureFloat; + bool textureFloatLinear; + + // GL_EXT_texture_rg + // Implies that TextureCaps for GL_R8, GL_RG8 (and floating point R/RG texture formats if floating point extensions + // are also present) exist + bool textureRG; + + // GL_EXT_texture_compression_dxt1, GL_ANGLE_texture_compression_dxt3 and GL_ANGLE_texture_compression_dxt5 + // Implies that TextureCaps for GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT + // GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE and GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE + bool textureCompressionDXT1; + bool textureCompressionDXT3; + bool textureCompressionDXT5; + + // GL_EXT_sRGB + // Implies that TextureCaps for GL_SRGB8_ALPHA8 and GL_SRGB8 exist + // TODO: Don't advertise this extension in ES3 + bool sRGB; + + // GL_ANGLE_depth_texture + bool depthTextures; + + // GL_EXT_texture_storage + bool textureStorage; + + // GL_OES_texture_npot + bool textureNPOT; + + // GL_EXT_draw_buffers + bool drawBuffers; + + // GL_EXT_texture_filter_anisotropic + bool textureFilterAnisotropic; + GLfloat maxTextureAnisotropy; + + // GL_EXT_occlusion_query_boolean + bool occlusionQueryBoolean; + + // GL_NV_fence + bool fence; + + // GL_ANGLE_timer_query + bool timerQuery; + + // GL_EXT_robustness + bool robustness; + + // GL_EXT_blend_minmax + bool blendMinMax; + + // GL_ANGLE_framebuffer_blit + bool framebufferBlit; + + // GL_ANGLE_framebuffer_multisample + bool framebufferMultisample; + GLuint maxSamples; + + // GL_ANGLE_instanced_arrays + bool instancedArrays; + + // GL_ANGLE_pack_reverse_row_order + bool packReverseRowOrder; + + // GL_OES_standard_derivatives + bool standardDerivatives; + + // GL_EXT_shader_texture_lod + bool shaderTextureLOD; + + // GL_EXT_frag_depth + bool fragDepth; + + // GL_ANGLE_texture_usage + bool textureUsage; + + // GL_ANGLE_translated_shader_source + bool translatedShaderSource; + + // ES3 Extension support + + // GL_EXT_color_buffer_float + bool colorBufferFloat; +}; + +struct Caps +{ + Caps(); + + // Table 6.28, implementation dependent values + GLuint64 maxElementIndex; + GLuint max3DTextureSize; + GLuint max2DTextureSize; + GLuint maxArrayTextureLayers; + GLfloat maxLODBias; + GLuint maxCubeMapTextureSize; + GLuint maxRenderbufferSize; + GLuint maxDrawBuffers; + GLuint maxColorAttachments; + GLuint maxViewportWidth; + GLuint maxViewportHeight; + GLfloat minAliasedPointSize; + GLfloat maxAliasedPointSize; + GLfloat minAliasedLineWidth; + GLfloat maxAliasedLineWidth; + + // Table 6.29, implementation dependent values (cont.) + GLuint maxElementsIndices; + GLuint maxElementsVertices; + std::vector compressedTextureFormats; + std::vector programBinaryFormats; + std::vector shaderBinaryFormats; + GLuint64 maxServerWaitTimeout; + + // Table 6.31, implementation dependent vertex shader limits + GLuint maxVertexAttributes; + GLuint maxVertexUniformComponents; + GLuint maxVertexUniformVectors; + GLuint maxVertexUniformBlocks; + GLuint maxVertexOutputComponents; + GLuint maxVertexTextureImageUnits; + + // Table 6.32, implementation dependent fragment shader limits + GLuint maxFragmentUniformComponents; + GLuint maxFragmentUniformVectors; + GLuint maxFragmentUniformBlocks; + GLuint maxFragmentInputComponents; + GLuint maxTextureImageUnits; + GLint minProgramTexelOffset; + GLint maxProgramTexelOffset; + + // Table 6.33, implementation dependent aggregate shader limits + GLuint maxUniformBufferBindings; + GLuint64 maxUniformBlockSize; + GLuint uniformBufferOffsetAlignment; + GLuint maxCombinedUniformBlocks; + GLuint64 maxCombinedVertexUniformComponents; + GLuint64 maxCombinedFragmentUniformComponents; + GLuint maxVaryingComponents; + GLuint maxVaryingVectors; + GLuint maxCombinedTextureImageUnits; + + // Table 6.34, implementation dependent transform feedback limits + GLuint maxTransformFeedbackInterleavedComponents; + GLuint maxTransformFeedbackSeparateAttributes; + GLuint maxTransformFeedbackSeparateComponents; +}; + +} + +#endif // LIBGLESV2_CAPS_H diff --git a/gfx/angle/src/libGLESv2/Context.cpp b/gfx/angle/src/libGLESv2/Context.cpp index 79b47c8c1e16..5569bd01760e 100644 --- a/gfx/angle/src/libGLESv2/Context.cpp +++ b/gfx/angle/src/libGLESv2/Context.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -12,18 +11,19 @@ #include "libGLESv2/main.h" #include "common/utilities.h" +#include "common/platform.h" #include "libGLESv2/formatutils.h" #include "libGLESv2/Buffer.h" #include "libGLESv2/Fence.h" #include "libGLESv2/Framebuffer.h" +#include "libGLESv2/FramebufferAttachment.h" #include "libGLESv2/Renderbuffer.h" #include "libGLESv2/Program.h" #include "libGLESv2/ProgramBinary.h" #include "libGLESv2/Query.h" #include "libGLESv2/Texture.h" #include "libGLESv2/ResourceManager.h" -#include "libGLESv2/renderer/IndexDataManager.h" -#include "libGLESv2/renderer/RenderTarget.h" +#include "libGLESv2/renderer/d3d/IndexDataManager.h" #include "libGLESv2/renderer/Renderer.h" #include "libGLESv2/VertexArray.h" #include "libGLESv2/Sampler.h" @@ -32,109 +32,21 @@ #include "libEGL/Surface.h" -#undef near -#undef far +#include namespace gl { -static const char* makeStaticString(const std::string& str) -{ - static std::set strings; - std::set::iterator it = strings.find(str); - if (it != strings.end()) - return it->c_str(); - return strings.insert(str).first->c_str(); -} - -Context::Context(int clientVersion, const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess) : mRenderer(renderer) +Context::Context(int clientVersion, const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess) + : mRenderer(renderer) { ASSERT(robustAccess == false); // Unimplemented - mFenceNVHandleAllocator.setBaseHandle(0); - - setClearColor(0.0f, 0.0f, 0.0f, 0.0f); + initCaps(clientVersion); mClientVersion = clientVersion; - mState.depthClearValue = 1.0f; - mState.stencilClearValue = 0; - - mState.rasterizer.rasterizerDiscard = false; - 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.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.stencilBackRef = 0; - - mState.sampleCoverage = false; - mState.sampleCoverageValue = 1.0f; - mState.sampleCoverageInvert = false; - mState.generateMipmapHint = GL_DONT_CARE; - mState.fragmentShaderDerivativeHint = GL_DONT_CARE; - - mState.lineWidth = 1.0f; - - 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.blend.colorMaskRed = true; - mState.blend.colorMaskGreen = true; - mState.blend.colorMaskBlue = true; - mState.blend.colorMaskAlpha = true; - - const GLfloat defaultFloatValues[] = { 0.0f, 0.0f, 0.0f, 1.0f }; - for (int attribIndex = 0; attribIndex < MAX_VERTEX_ATTRIBS; attribIndex++) - { - mState.vertexAttribCurrentValues[attribIndex].setFloatValues(defaultFloatValues); - } + mFenceNVHandleAllocator.setBaseHandle(0); if (shareContext != NULL) { @@ -152,17 +64,11 @@ Context::Context(int clientVersion, const gl::Context *shareContext, rx::Rendere // 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(mRenderer, 0)); - mTextureCubeMapZero.set(new TextureCubeMap(mRenderer, 0)); - mTexture3DZero.set(new Texture3D(mRenderer, 0)); - mTexture2DArrayZero.set(new Texture2DArray(mRenderer, 0)); + mTexture2DZero.set(new Texture2D(mRenderer->createTexture(GL_TEXTURE_2D), 0)); + mTextureCubeMapZero.set(new TextureCubeMap(mRenderer->createTexture(GL_TEXTURE_CUBE_MAP), 0)); + mTexture3DZero.set(new Texture3D(mRenderer->createTexture(GL_TEXTURE_3D), 0)); + mTexture2DArrayZero.set(new Texture2DArray(mRenderer->createTexture(GL_TEXTURE_2D_ARRAY), 0)); - for (unsigned int textureUnit = 0; textureUnit < ArraySize(mState.samplers); textureUnit++) - { - mState.samplers[textureUnit] = 0; - } - - mState.activeSampler = 0; bindVertexArray(0); bindArrayBuffer(0); bindElementArrayBuffer(0); @@ -172,10 +78,6 @@ Context::Context(int clientVersion, const gl::Context *shareContext, rx::Rendere bindDrawFramebuffer(0); bindRenderbuffer(0); - mState.activeQueries[GL_ANY_SAMPLES_PASSED].set(NULL); - mState.activeQueries[GL_ANY_SAMPLES_PASSED_CONSERVATIVE].set(NULL); - mState.activeQueries[GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN].set(NULL); - bindGenericUniformBuffer(0); for (int i = 0; i < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS; i++) { @@ -197,48 +99,31 @@ Context::Context(int clientVersion, const gl::Context *shareContext, rx::Rendere // In the initial state, a default transform feedback object is bound and treated as // a transform feedback object with a name of zero. That object is bound any time // BindTransformFeedback is called with id of zero - mTransformFeedbackZero.set(new TransformFeedback(0)); + mTransformFeedbackZero.set(new TransformFeedback(mRenderer->createTransformFeedback(), 0)); bindTransformFeedback(0); - mState.currentProgram = 0; - mCurrentProgramBinary.set(NULL); - - mCombinedExtensionsString = NULL; - mRendererString = NULL; - - mInvalidEnum = false; - mInvalidValue = false; - mInvalidOperation = false; - mOutOfMemory = false; - mInvalidFramebufferOperation = false; - mHasBeenCurrent = false; mContextLost = false; mResetStatus = GL_NO_ERROR; 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; + mState.setContext(this); } Context::~Context() { - if (mState.currentProgram != 0) + GLuint currentProgram = mState.getCurrentProgramId(); + if (currentProgram != 0) { - Program *programObject = mResourceManager->getProgram(mState.currentProgram); + Program *programObject = mResourceManager->getProgram(currentProgram); if (programObject) { programObject->release(); } - mState.currentProgram = 0; + currentProgram = 0; } - mCurrentProgramBinary.set(NULL); + mState.setCurrentProgram(0, NULL); while (!mFramebufferMap.empty()) { @@ -266,58 +151,16 @@ Context::~Context() deleteTransformFeedback(mTransformFeedbackMap.begin()->first); } - for (int type = 0; type < TEXTURE_TYPE_COUNT; type++) - { - for (int sampler = 0; sampler < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS; sampler++) - { - mState.samplerTexture[type][sampler].set(NULL); - } - } - for (int type = 0; type < TEXTURE_TYPE_COUNT; type++) { mIncompleteTextures[type].set(NULL); } - const GLfloat defaultFloatValues[] = { 0.0f, 0.0f, 0.0f, 1.0f }; - for (int attribIndex = 0; attribIndex < MAX_VERTEX_ATTRIBS; attribIndex++) - { - mState.vertexAttribCurrentValues[attribIndex].setFloatValues(defaultFloatValues); - } - - mState.arrayBuffer.set(NULL); - mState.renderbuffer.set(NULL); - - mState.transformFeedback.set(NULL); - mTexture2DZero.set(NULL); mTextureCubeMapZero.set(NULL); mTexture3DZero.set(NULL); mTexture2DArrayZero.set(NULL); - for (State::ActiveQueryMap::iterator i = mState.activeQueries.begin(); i != mState.activeQueries.end(); i++) - { - i->second.set(NULL); - } - - mState.genericUniformBuffer.set(NULL); - for (int i = 0; i < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS; i++) - { - mState.uniformBuffers[i].set(NULL); - } - - mState.genericTransformFeedbackBuffer.set(NULL); - for (int i = 0; i < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++) - { - mState.transformFeedbackBuffers[i].set(NULL); - } - - mState.copyReadBuffer.set(NULL); - mState.copyWriteBuffer.set(NULL); - - mState.pack.pixelBuffer.set(NULL); - mState.unpack.pixelBuffer.set(NULL); - mResourceManager->release(); } @@ -325,78 +168,11 @@ void Context::makeCurrent(egl::Surface *surface) { if (!mHasBeenCurrent) { - mMajorShaderModel = mRenderer->getMajorShaderModel(); - mMaximumPointSize = mRenderer->getMaxPointSize(); - mSupportsVertexTexture = mRenderer->getVertexTextureSupport(); - mSupportsNonPower2Texture = mRenderer->getNonPower2TextureSupport(); - mSupportsInstancing = mRenderer->getInstancingSupport(); - - mMaxViewportDimension = mRenderer->getMaxViewportDimension(); - mMax2DTextureDimension = std::min(std::min(mRenderer->getMaxTextureWidth(), mRenderer->getMaxTextureHeight()), - (int)gl::IMPLEMENTATION_MAX_2D_TEXTURE_SIZE); - mMaxCubeTextureDimension = std::min(mMax2DTextureDimension, (int)gl::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE); - mMax3DTextureDimension = std::min(std::min(mMax2DTextureDimension, mRenderer->getMaxTextureDepth()), - (int)gl::IMPLEMENTATION_MAX_3D_TEXTURE_SIZE); - mMax2DArrayTextureLayers = mRenderer->getMaxTextureArrayLayers(); - mMaxRenderbufferDimension = mMax2DTextureDimension; - mMax2DTextureLevel = log2(mMax2DTextureDimension) + 1; - mMaxCubeTextureLevel = log2(mMaxCubeTextureDimension) + 1; - mMax3DTextureLevel = log2(mMax3DTextureDimension) + 1; - mMax2DArrayTextureLevel = log2(mMax2DTextureDimension) + 1; - mMaxTextureAnisotropy = mRenderer->getTextureMaxAnisotropy(); - TRACE("Max2DTextureDimension=%d, MaxCubeTextureDimension=%d, Max3DTextureDimension=%d, Max2DArrayTextureLayers = %d, " - "Max2DTextureLevel=%d, MaxCubeTextureLevel=%d, Max3DTextureLevel=%d, Max2DArrayTextureLevel=%d, " - "MaxRenderbufferDimension=%d, MaxTextureAnisotropy=%f", - mMax2DTextureDimension, mMaxCubeTextureDimension, mMax3DTextureDimension, mMax2DArrayTextureLayers, - mMax2DTextureLevel, mMaxCubeTextureLevel, mMax3DTextureLevel, mMax2DArrayTextureLevel, - mMaxRenderbufferDimension, mMaxTextureAnisotropy); - - mSupportsEventQueries = mRenderer->getEventQuerySupport(); - mSupportsOcclusionQueries = mRenderer->getOcclusionQuerySupport(); - mSupportsBGRATextures = mRenderer->getBGRATextureSupport(); - mSupportsDXT1Textures = mRenderer->getDXT1TextureSupport(); - mSupportsDXT3Textures = mRenderer->getDXT3TextureSupport(); - mSupportsDXT5Textures = mRenderer->getDXT5TextureSupport(); - mSupportsFloat32Textures = mRenderer->getFloat32TextureSupport(); - mSupportsFloat32LinearFilter = mRenderer->getFloat32TextureFilteringSupport(); - mSupportsFloat32RenderableTextures = mRenderer->getFloat32TextureRenderingSupport(); - mSupportsFloat16Textures = mRenderer->getFloat16TextureSupport(); - mSupportsFloat16LinearFilter = mRenderer->getFloat16TextureFilteringSupport(); - mSupportsFloat16RenderableTextures = mRenderer->getFloat16TextureRenderingSupport(); - mSupportsLuminanceTextures = mRenderer->getLuminanceTextureSupport(); - mSupportsLuminanceAlphaTextures = mRenderer->getLuminanceAlphaTextureSupport(); - mSupportsRGTextures = mRenderer->getRGTextureSupport(); - mSupportsDepthTextures = mRenderer->getDepthTextureSupport(); - mSupportsTextureFilterAnisotropy = mRenderer->getTextureFilterAnisotropySupport(); - mSupports32bitIndices = mRenderer->get32BitIndexSupport(); - mSupportsPBOs = mRenderer->getPBOSupport(); - - mNumCompressedTextureFormats = 0; - if (supportsDXT1Textures()) - { - mNumCompressedTextureFormats += 2; - } - if (supportsDXT3Textures()) - { - mNumCompressedTextureFormats += 1; - } - if (supportsDXT5Textures()) - { - mNumCompressedTextureFormats += 1; - } - - initExtensionString(); initRendererString(); + initExtensionStrings(); - mState.viewport.x = 0; - mState.viewport.y = 0; - mState.viewport.width = surface->getWidth(); - mState.viewport.height = surface->getHeight(); - - mState.scissor.x = 0; - mState.scissor.y = 0; - mState.scissor.width = surface->getWidth(); - mState.scissor.height = surface->getHeight(); + mState.setViewportParams(0, 0, surface->getWidth(), surface->getHeight()); + mState.setScissorParams(0, 0, surface->getWidth(), surface->getHeight()); mHasBeenCurrent = true; } @@ -427,447 +203,6 @@ bool Context::isContextLost() return mContextLost; } -void Context::setCap(GLenum cap, bool enabled) -{ - switch (cap) - { - case GL_CULL_FACE: setCullFace(enabled); break; - case GL_POLYGON_OFFSET_FILL: setPolygonOffsetFill(enabled); break; - case GL_SAMPLE_ALPHA_TO_COVERAGE: setSampleAlphaToCoverage(enabled); break; - case GL_SAMPLE_COVERAGE: setSampleCoverage(enabled); break; - case GL_SCISSOR_TEST: setScissorTest(enabled); break; - case GL_STENCIL_TEST: setStencilTest(enabled); break; - case GL_DEPTH_TEST: setDepthTest(enabled); break; - case GL_BLEND: setBlend(enabled); break; - case GL_DITHER: setDither(enabled); break; - case GL_PRIMITIVE_RESTART_FIXED_INDEX: UNIMPLEMENTED(); break; - case GL_RASTERIZER_DISCARD: setRasterizerDiscard(enabled); break; - default: UNREACHABLE(); - } -} - -bool Context::getCap(GLenum cap) -{ - switch (cap) - { - case GL_CULL_FACE: return isCullFaceEnabled(); - case GL_POLYGON_OFFSET_FILL: return isPolygonOffsetFillEnabled(); - case GL_SAMPLE_ALPHA_TO_COVERAGE: return isSampleAlphaToCoverageEnabled(); - case GL_SAMPLE_COVERAGE: return isSampleCoverageEnabled(); - case GL_SCISSOR_TEST: return isScissorTestEnabled(); - case GL_STENCIL_TEST: return isStencilTestEnabled(); - case GL_DEPTH_TEST: return isDepthTestEnabled(); - case GL_BLEND: return isBlendEnabled(); - case GL_DITHER: return isDitherEnabled(); - case GL_PRIMITIVE_RESTART_FIXED_INDEX: UNIMPLEMENTED(); return false; - case GL_RASTERIZER_DISCARD: return isRasterizerDiscardEnabled(); - default: UNREACHABLE(); return false; - } -} - -void Context::setClearColor(float red, float green, float blue, float alpha) -{ - mState.colorClearValue.red = red; - mState.colorClearValue.green = green; - mState.colorClearValue.blue = blue; - mState.colorClearValue.alpha = alpha; -} - -void Context::setClearDepth(float depth) -{ - mState.depthClearValue = depth; -} - -void Context::setClearStencil(int stencil) -{ - mState.stencilClearValue = stencil; -} - -void Context::setRasterizerDiscard(bool enabled) -{ - mState.rasterizer.rasterizerDiscard = enabled; -} - -bool Context::isRasterizerDiscardEnabled() const -{ - return mState.rasterizer.rasterizerDiscard; -} - -void Context::setCullFace(bool enabled) -{ - mState.rasterizer.cullFace = enabled; -} - -bool Context::isCullFaceEnabled() const -{ - return mState.rasterizer.cullFace; -} - -void Context::setCullMode(GLenum mode) -{ - mState.rasterizer.cullMode = mode; -} - -void Context::setFrontFace(GLenum front) -{ - mState.rasterizer.frontFace = front; -} - -void Context::setDepthTest(bool enabled) -{ - mState.depthStencil.depthTest = enabled; -} - -bool Context::isDepthTestEnabled() const -{ - return mState.depthStencil.depthTest; -} - -void Context::setDepthFunc(GLenum depthFunc) -{ - mState.depthStencil.depthFunc = depthFunc; -} - -void Context::setDepthRange(float zNear, float zFar) -{ - mState.zNear = zNear; - mState.zFar = zFar; -} - -void Context::setBlend(bool enabled) -{ - mState.blend.blend = enabled; -} - -bool Context::isBlendEnabled() const -{ - return mState.blend.blend; -} - -void Context::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha) -{ - 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) -{ - mState.blendColor.red = red; - mState.blendColor.green = green; - mState.blendColor.blue = blue; - mState.blendColor.alpha = alpha; -} - -void Context::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation) -{ - mState.blend.blendEquationRGB = rgbEquation; - mState.blend.blendEquationAlpha = alphaEquation; -} - -void Context::setStencilTest(bool enabled) -{ - mState.depthStencil.stencilTest = enabled; -} - -bool Context::isStencilTestEnabled() const -{ - return mState.depthStencil.stencilTest; -} - -void Context::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask) -{ - mState.depthStencil.stencilFunc = stencilFunc; - mState.stencilRef = (stencilRef > 0) ? stencilRef : 0; - mState.depthStencil.stencilMask = stencilMask; -} - -void Context::setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask) -{ - mState.depthStencil.stencilBackFunc = stencilBackFunc; - mState.stencilBackRef = (stencilBackRef > 0) ? stencilBackRef : 0; - mState.depthStencil.stencilBackMask = stencilBackMask; -} - -void Context::setStencilWritemask(GLuint stencilWritemask) -{ - mState.depthStencil.stencilWritemask = stencilWritemask; -} - -void Context::setStencilBackWritemask(GLuint stencilBackWritemask) -{ - mState.depthStencil.stencilBackWritemask = stencilBackWritemask; -} - -void Context::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass) -{ - mState.depthStencil.stencilFail = stencilFail; - mState.depthStencil.stencilPassDepthFail = stencilPassDepthFail; - mState.depthStencil.stencilPassDepthPass = stencilPassDepthPass; -} - -void Context::setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass) -{ - mState.depthStencil.stencilBackFail = stencilBackFail; - mState.depthStencil.stencilBackPassDepthFail = stencilBackPassDepthFail; - mState.depthStencil.stencilBackPassDepthPass = stencilBackPassDepthPass; -} - -void Context::setPolygonOffsetFill(bool enabled) -{ - mState.rasterizer.polygonOffsetFill = enabled; -} - -bool Context::isPolygonOffsetFillEnabled() const -{ - return mState.rasterizer.polygonOffsetFill; -} - -void Context::setPolygonOffsetParams(GLfloat factor, GLfloat units) -{ - // 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) -{ - mState.blend.sampleAlphaToCoverage = enabled; -} - -bool Context::isSampleAlphaToCoverageEnabled() const -{ - return mState.blend.sampleAlphaToCoverage; -} - -void Context::setSampleCoverage(bool enabled) -{ - mState.sampleCoverage = enabled; -} - -bool Context::isSampleCoverageEnabled() const -{ - return mState.sampleCoverage; -} - -void Context::setSampleCoverageParams(GLclampf value, bool invert) -{ - mState.sampleCoverageValue = value; - mState.sampleCoverageInvert = invert; -} - -void Context::setScissorTest(bool enabled) -{ - mState.scissorTest = enabled; -} - -bool Context::isScissorTestEnabled() const -{ - return mState.scissorTest; -} - -void Context::setDither(bool enabled) -{ - mState.blend.dither = enabled; -} - -bool Context::isDitherEnabled() const -{ - return mState.blend.dither; -} - -void Context::setLineWidth(GLfloat width) -{ - mState.lineWidth = width; -} - -void Context::setGenerateMipmapHint(GLenum hint) -{ - mState.generateMipmapHint = hint; -} - -void Context::setFragmentShaderDerivativeHint(GLenum hint) -{ - mState.fragmentShaderDerivativeHint = hint; - // TODO: Propagate the hint to shader translator so we can write - // ddx, ddx_coarse, or ddx_fine depending on the hint. - // Ignore for now. It is valid for implementations to ignore hint. -} - -void Context::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei 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) -{ - mState.scissor.x = x; - mState.scissor.y = y; - mState.scissor.width = width; - mState.scissor.height = height; -} - -void Context::getScissorParams(GLint *x, GLint *y, GLsizei *width, GLsizei *height) -{ - *x = mState.scissor.x; - *y = mState.scissor.y; - *width = mState.scissor.width; - *height = mState.scissor.height; -} - -void Context::setColorMask(bool red, bool green, bool blue, bool alpha) -{ - mState.blend.colorMaskRed = red; - mState.blend.colorMaskGreen = green; - mState.blend.colorMaskBlue = blue; - mState.blend.colorMaskAlpha = alpha; -} - -void Context::setDepthMask(bool mask) -{ - mState.depthStencil.depthMask = mask; -} - -void Context::setActiveSampler(unsigned int active) -{ - mState.activeSampler = active; -} - -GLuint Context::getReadFramebufferHandle() const -{ - return mState.readFramebuffer; -} - -GLuint Context::getDrawFramebufferHandle() const -{ - return mState.drawFramebuffer; -} - -GLuint Context::getRenderbufferHandle() const -{ - return mState.renderbuffer.id(); -} - -GLuint Context::getVertexArrayHandle() const -{ - return mState.vertexArray; -} - -GLuint Context::getSamplerHandle(GLuint textureUnit) const -{ - ASSERT(textureUnit < ArraySize(mState.samplers)); - return mState.samplers[textureUnit]; -} - -unsigned int Context::getActiveSampler() const -{ - return mState.activeSampler; -} - -GLuint Context::getArrayBufferHandle() const -{ - return mState.arrayBuffer.id(); -} - -bool Context::isQueryActive() const -{ - for (State::ActiveQueryMap::const_iterator i = mState.activeQueries.begin(); - i != mState.activeQueries.end(); i++) - { - if (i->second.get() != NULL) - { - return true; - } - } - - return false; -} - -const Query *Context::getActiveQuery(GLenum target) const -{ - // All query types should already exist in the activeQueries map - ASSERT(mState.activeQueries.find(target) != mState.activeQueries.end()); - - return mState.activeQueries.at(target).get(); -} - -GLuint Context::getActiveQueryId(GLenum target) const -{ - const Query *query = getActiveQuery(target); - return (query ? query->id() : 0u); -} - -void Context::setEnableVertexAttribArray(unsigned int attribNum, bool enabled) -{ - getCurrentVertexArray()->enableAttribute(attribNum, enabled); -} - -const VertexAttribute &Context::getVertexAttribState(unsigned int attribNum) const -{ - return getCurrentVertexArray()->getVertexAttribute(attribNum); -} - -const VertexAttribCurrentValueData &Context::getVertexAttribCurrentValue(unsigned int attribNum) const -{ - ASSERT(attribNum < MAX_VERTEX_ATTRIBS); - return mState.vertexAttribCurrentValues[attribNum]; -} - -void Context::setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type, bool normalized, - bool pureInteger, GLsizei stride, const void *pointer) -{ - getCurrentVertexArray()->setAttributeState(attribNum, boundBuffer, size, type, normalized, pureInteger, stride, pointer); -} - -const void *Context::getVertexAttribPointer(unsigned int attribNum) const -{ - return getCurrentVertexArray()->getVertexAttribute(attribNum).mPointer; -} - -void Context::setPackAlignment(GLint alignment) -{ - mState.pack.alignment = alignment; -} - -GLint Context::getPackAlignment() const -{ - return mState.pack.alignment; -} - -void Context::setUnpackAlignment(GLint alignment) -{ - mState.unpack.alignment = alignment; -} - -GLint Context::getUnpackAlignment() const -{ - return mState.unpack.alignment; -} - -void Context::setPackReverseRowOrder(bool reverseRowOrder) -{ - mState.pack.reverseRowOrder = reverseRowOrder; -} - -bool Context::getPackReverseRowOrder() const -{ - return mState.pack.reverseRowOrder; -} - -const PixelUnpackState &Context::getUnpackState() const -{ - return mState.unpack; -} - -const PixelPackState &Context::getPackState() const -{ - return mState.pack; -} - GLuint Context::createBuffer() { return mResourceManager->createBuffer(); @@ -912,8 +247,8 @@ GLuint Context::createVertexArray() // Although the spec states VAO state is not initialized until the object is bound, // we create it immediately. The resulting behaviour is transparent to the application, // since it's not currently possible to access the state until the object is bound. - mVertexArrayMap[handle] = new VertexArray(mRenderer, handle); - + VertexArray *vertexArray = new VertexArray(mRenderer->createVertexArray(), handle, MAX_VERTEX_ATTRIBS); + mVertexArrayMap[handle] = vertexArray; return handle; } @@ -925,7 +260,7 @@ GLuint Context::createSampler() GLuint Context::createTransformFeedback() { GLuint handle = mTransformFeedbackAllocator.allocate(); - TransformFeedback *transformFeedback = new TransformFeedback(handle); + TransformFeedback *transformFeedback = new TransformFeedback(mRenderer->createTransformFeedback(), handle); transformFeedback->addRef(); mTransformFeedbackMap[handle] = transformFeedback; return handle; @@ -1100,7 +435,7 @@ Program *Context::getProgram(GLuint handle) const return mResourceManager->getProgram(handle); } -Texture *Context::getTexture(GLuint handle) +Texture *Context::getTexture(GLuint handle) const { return mResourceManager->getTexture(handle); } @@ -1147,28 +482,6 @@ TransformFeedback *Context::getTransformFeedback(GLuint handle) const } } -Framebuffer *Context::getReadFramebuffer() -{ - return getFramebuffer(mState.readFramebuffer); -} - -Framebuffer *Context::getDrawFramebuffer() -{ - return mBoundDrawFramebuffer; -} - -VertexArray *Context::getCurrentVertexArray() const -{ - VertexArray *vao = getVertexArray(mState.vertexArray); - ASSERT(vao != NULL); - return vao; -} - -TransformFeedback *Context::getCurrentTransformFeedback() const -{ - return mState.transformFeedback.get(); -} - bool Context::isSampler(GLuint samplerName) const { return mResourceManager->isSampler(samplerName); @@ -1178,167 +491,158 @@ void Context::bindArrayBuffer(unsigned int buffer) { mResourceManager->checkBufferAllocation(buffer); - mState.arrayBuffer.set(getBuffer(buffer)); + mState.setArrayBufferBinding(getBuffer(buffer)); } void Context::bindElementArrayBuffer(unsigned int buffer) { mResourceManager->checkBufferAllocation(buffer); - getCurrentVertexArray()->setElementArrayBuffer(getBuffer(buffer)); + mState.getVertexArray()->setElementArrayBuffer(getBuffer(buffer)); } void Context::bindTexture2D(GLuint texture) { mResourceManager->checkTextureAllocation(texture, TEXTURE_2D); - mState.samplerTexture[TEXTURE_2D][mState.activeSampler].set(getTexture(texture)); + mState.setSamplerTexture(TEXTURE_2D, getTexture(texture)); } void Context::bindTextureCubeMap(GLuint texture) { mResourceManager->checkTextureAllocation(texture, TEXTURE_CUBE); - mState.samplerTexture[TEXTURE_CUBE][mState.activeSampler].set(getTexture(texture)); + mState.setSamplerTexture(TEXTURE_CUBE, getTexture(texture)); } void Context::bindTexture3D(GLuint texture) { mResourceManager->checkTextureAllocation(texture, TEXTURE_3D); - mState.samplerTexture[TEXTURE_3D][mState.activeSampler].set(getTexture(texture)); + mState.setSamplerTexture(TEXTURE_3D, getTexture(texture)); } void Context::bindTexture2DArray(GLuint texture) { mResourceManager->checkTextureAllocation(texture, TEXTURE_2D_ARRAY); - mState.samplerTexture[TEXTURE_2D_ARRAY][mState.activeSampler].set(getTexture(texture)); + mState.setSamplerTexture(TEXTURE_2D_ARRAY, getTexture(texture)); } void Context::bindReadFramebuffer(GLuint framebuffer) { if (!getFramebuffer(framebuffer)) { - mFramebufferMap[framebuffer] = new Framebuffer(mRenderer); + mFramebufferMap[framebuffer] = new Framebuffer(mRenderer, framebuffer); } - mState.readFramebuffer = framebuffer; + mState.setReadFramebufferBinding(getFramebuffer(framebuffer)); } void Context::bindDrawFramebuffer(GLuint framebuffer) { if (!getFramebuffer(framebuffer)) { - mFramebufferMap[framebuffer] = new Framebuffer(mRenderer); + mFramebufferMap[framebuffer] = new Framebuffer(mRenderer, framebuffer); } - mState.drawFramebuffer = framebuffer; - - mBoundDrawFramebuffer = getFramebuffer(framebuffer); + mState.setDrawFramebufferBinding(getFramebuffer(framebuffer)); } void Context::bindRenderbuffer(GLuint renderbuffer) { mResourceManager->checkRenderbufferAllocation(renderbuffer); - mState.renderbuffer.set(getRenderbuffer(renderbuffer)); + mState.setRenderbufferBinding(getRenderbuffer(renderbuffer)); } void Context::bindVertexArray(GLuint vertexArray) { if (!getVertexArray(vertexArray)) { - mVertexArrayMap[vertexArray] = new VertexArray(mRenderer, vertexArray); + VertexArray *vertexArrayObject = new VertexArray(mRenderer->createVertexArray(), vertexArray, MAX_VERTEX_ATTRIBS); + mVertexArrayMap[vertexArray] = vertexArrayObject; } - mState.vertexArray = vertexArray; + mState.setVertexArrayBinding(getVertexArray(vertexArray)); } void Context::bindSampler(GLuint textureUnit, GLuint sampler) { - ASSERT(textureUnit < ArraySize(mState.samplers)); + ASSERT(textureUnit < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS); // TODO: Update for backend-determined array size mResourceManager->checkSamplerAllocation(sampler); - mState.samplers[textureUnit] = sampler; + mState.setSamplerBinding(textureUnit, getSampler(sampler)); } void Context::bindGenericUniformBuffer(GLuint buffer) { mResourceManager->checkBufferAllocation(buffer); - mState.genericUniformBuffer.set(getBuffer(buffer)); + mState.setGenericUniformBufferBinding(getBuffer(buffer)); } void Context::bindIndexedUniformBuffer(GLuint buffer, GLuint index, GLintptr offset, GLsizeiptr size) { mResourceManager->checkBufferAllocation(buffer); - mState.uniformBuffers[index].set(getBuffer(buffer), offset, size); + mState.setIndexedUniformBufferBinding(index, getBuffer(buffer), offset, size); } void Context::bindGenericTransformFeedbackBuffer(GLuint buffer) { mResourceManager->checkBufferAllocation(buffer); - mState.genericTransformFeedbackBuffer.set(getBuffer(buffer)); + mState.setGenericTransformFeedbackBufferBinding(getBuffer(buffer)); } void Context::bindIndexedTransformFeedbackBuffer(GLuint buffer, GLuint index, GLintptr offset, GLsizeiptr size) { mResourceManager->checkBufferAllocation(buffer); - mState.transformFeedbackBuffers[index].set(getBuffer(buffer), offset, size); + mState.setIndexedTransformFeedbackBufferBinding(index, getBuffer(buffer), offset, size); } void Context::bindCopyReadBuffer(GLuint buffer) { mResourceManager->checkBufferAllocation(buffer); - mState.copyReadBuffer.set(getBuffer(buffer)); + mState.setCopyReadBufferBinding(getBuffer(buffer)); } void Context::bindCopyWriteBuffer(GLuint buffer) { mResourceManager->checkBufferAllocation(buffer); - mState.copyWriteBuffer.set(getBuffer(buffer)); + mState.setCopyWriteBufferBinding(getBuffer(buffer)); } void Context::bindPixelPackBuffer(GLuint buffer) { mResourceManager->checkBufferAllocation(buffer); - mState.pack.pixelBuffer.set(getBuffer(buffer)); + mState.setPixelPackBufferBinding(getBuffer(buffer)); } void Context::bindPixelUnpackBuffer(GLuint buffer) { mResourceManager->checkBufferAllocation(buffer); - mState.unpack.pixelBuffer.set(getBuffer(buffer)); + mState.setPixelUnpackBufferBinding(getBuffer(buffer)); } void Context::useProgram(GLuint program) { - GLuint priorProgram = mState.currentProgram; - mState.currentProgram = program; // Must switch before trying to delete, otherwise it only gets flagged. + GLuint priorProgramId = mState.getCurrentProgramId(); + Program *priorProgram = mResourceManager->getProgram(priorProgramId); - if (priorProgram != program) + if (priorProgramId != program) { - Program *newProgram = mResourceManager->getProgram(program); - Program *oldProgram = mResourceManager->getProgram(priorProgram); - mCurrentProgramBinary.set(NULL); + mState.setCurrentProgram(program, mResourceManager->getProgram(program)); - if (newProgram) + if (priorProgram) { - newProgram->addRef(); - mCurrentProgramBinary.set(newProgram->getProgramBinary()); - } - - if (oldProgram) - { - oldProgram->release(); + priorProgram->release(); } } } @@ -1347,35 +651,34 @@ void Context::linkProgram(GLuint program) { Program *programObject = mResourceManager->getProgram(program); - bool linked = programObject->link(); + bool linked = programObject->link(getCaps()); // if the current program was relinked successfully we // need to install the new executables - if (linked && program == mState.currentProgram) + if (linked && program == mState.getCurrentProgramId()) { - mCurrentProgramBinary.set(programObject->getProgramBinary()); + mState.setCurrentProgramBinary(programObject->getProgramBinary()); } } -void Context::setProgramBinary(GLuint program, const void *binary, GLint length) +void Context::setProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLint length) { Program *programObject = mResourceManager->getProgram(program); - bool loaded = programObject->setProgramBinary(binary, length); + bool loaded = programObject->setProgramBinary(binaryFormat, binary, length); // if the current program was reloaded successfully we // need to install the new executables - if (loaded && program == mState.currentProgram) + if (loaded && program == mState.getCurrentProgramId()) { - mCurrentProgramBinary.set(programObject->getProgramBinary()); + mState.setCurrentProgramBinary(programObject->getProgramBinary()); } } void Context::bindTransformFeedback(GLuint transformFeedback) { - TransformFeedback *transformFeedbackObject = getTransformFeedback(transformFeedback); - mState.transformFeedback.set(transformFeedbackObject); + mState.setTransformFeedbackBinding(getTransformFeedback(transformFeedback)); } void Context::beginQuery(GLenum target, GLuint query) @@ -1384,7 +687,7 @@ void Context::beginQuery(GLenum target, GLuint query) ASSERT(queryObject); // set query as active for specified target - mState.activeQueries[target].set(queryObject); + mState.setActiveQuery(target, queryObject); // begin query queryObject->begin(); @@ -1392,56 +695,58 @@ void Context::beginQuery(GLenum target, GLuint query) void Context::endQuery(GLenum target) { - Query *queryObject = mState.activeQueries[target].get(); + Query *queryObject = mState.getActiveQuery(target); ASSERT(queryObject); queryObject->end(); - mState.activeQueries[target].set(NULL); + mState.setActiveQuery(target, NULL); } void Context::setFramebufferZero(Framebuffer *buffer) { + // First, check to see if the old default framebuffer + // was set for draw or read framebuffer, and change + // the bindings to point to the new one before deleting it. + if (mState.getDrawFramebuffer()->id() == 0) + { + mState.setDrawFramebufferBinding(buffer); + } + + if (mState.getReadFramebuffer()->id() == 0) + { + mState.setReadFramebufferBinding(buffer); + } + delete mFramebufferMap[0]; mFramebufferMap[0] = buffer; - if (mState.drawFramebuffer == 0) - { - mBoundDrawFramebuffer = buffer; - } } void Context::setRenderbufferStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples) { - const bool color = gl::IsColorRenderingSupported(internalformat, this); - const bool depth = gl::IsDepthRenderingSupported(internalformat, this); - const bool stencil = gl::IsStencilRenderingSupported(internalformat, this); + ASSERT(getTextureCaps().get(internalformat).renderable); RenderbufferStorage *renderbuffer = NULL; - if (color) - { - renderbuffer = new gl::Colorbuffer(mRenderer,width, height, internalformat, samples); - } - else if (depth && stencil) + const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); + if (formatInfo.depthBits > 0 && formatInfo.stencilBits > 0) { renderbuffer = new gl::DepthStencilbuffer(mRenderer, width, height, samples); } - else if (depth) + else if (formatInfo.depthBits > 0) { renderbuffer = new gl::Depthbuffer(mRenderer, width, height, samples); } - else if (stencil) + else if (formatInfo.stencilBits > 0) { renderbuffer = new gl::Stencilbuffer(mRenderer, width, height, samples); } else { - UNREACHABLE(); - return; + renderbuffer = new gl::Colorbuffer(mRenderer, width, height, internalformat, samples); } - Renderbuffer *renderbufferObject = mState.renderbuffer.get(); - renderbufferObject->setStorage(renderbuffer); + mState.getCurrentRenderbuffer()->setStorage(renderbuffer); } Framebuffer *Context::getFramebuffer(unsigned int handle) const @@ -1484,44 +789,13 @@ Query *Context::getQuery(unsigned int handle, bool create, GLenum type) { if (!query->second && create) { - query->second = new Query(mRenderer, type, handle); + query->second = new Query(mRenderer->createQuery(type), handle); query->second->addRef(); } return query->second; } } -Buffer *Context::getTargetBuffer(GLenum target) const -{ - switch (target) - { - case GL_ARRAY_BUFFER: return mState.arrayBuffer.get(); - case GL_COPY_READ_BUFFER: return mState.copyReadBuffer.get(); - case GL_COPY_WRITE_BUFFER: return mState.copyWriteBuffer.get(); - case GL_ELEMENT_ARRAY_BUFFER: return getCurrentVertexArray()->getElementArrayBuffer(); - case GL_PIXEL_PACK_BUFFER: return mState.pack.pixelBuffer.get(); - case GL_PIXEL_UNPACK_BUFFER: return mState.unpack.pixelBuffer.get(); - case GL_TRANSFORM_FEEDBACK_BUFFER: return mState.genericTransformFeedbackBuffer.get(); - case GL_UNIFORM_BUFFER: return mState.genericUniformBuffer.get(); - default: UNREACHABLE(); return NULL; - } -} - -Buffer *Context::getArrayBuffer() -{ - return mState.arrayBuffer.get(); -} - -Buffer *Context::getElementArrayBuffer() const -{ - return getCurrentVertexArray()->getElementArrayBuffer(); -} - -ProgramBinary *Context::getCurrentProgramBinary() -{ - return mCurrentProgramBinary.get(); -} - Texture *Context::getTargetTexture(GLenum target) const { if (!ValidTextureTarget(this, target)) @@ -1539,84 +813,29 @@ Texture *Context::getTargetTexture(GLenum target) const } } -GLuint Context::getTargetFramebufferHandle(GLenum target) const -{ - if (!ValidFramebufferTarget(target)) - { - return GL_INVALID_INDEX; - } - - if (target == GL_READ_FRAMEBUFFER_ANGLE) - { - return mState.readFramebuffer; - } - else - { - return mState.drawFramebuffer; - } -} - -Framebuffer *Context::getTargetFramebuffer(GLenum target) const -{ - GLuint framebufferHandle = getTargetFramebufferHandle(target); - return (framebufferHandle == GL_INVALID_INDEX ? NULL : getFramebuffer(framebufferHandle)); -} - Texture2D *Context::getTexture2D() const { - return static_cast(getSamplerTexture(mState.activeSampler, TEXTURE_2D)); + return static_cast(getSamplerTexture(mState.getActiveSampler(), TEXTURE_2D)); } TextureCubeMap *Context::getTextureCubeMap() const { - return static_cast(getSamplerTexture(mState.activeSampler, TEXTURE_CUBE)); + return static_cast(getSamplerTexture(mState.getActiveSampler(), TEXTURE_CUBE)); } Texture3D *Context::getTexture3D() const { - return static_cast(getSamplerTexture(mState.activeSampler, TEXTURE_3D)); + return static_cast(getSamplerTexture(mState.getActiveSampler(), TEXTURE_3D)); } Texture2DArray *Context::getTexture2DArray() const { - return static_cast(getSamplerTexture(mState.activeSampler, TEXTURE_2D_ARRAY)); -} - -Buffer *Context::getGenericUniformBuffer() -{ - return mState.genericUniformBuffer.get(); -} - -Buffer *Context::getGenericTransformFeedbackBuffer() -{ - return mState.genericTransformFeedbackBuffer.get(); -} - -Buffer *Context::getCopyReadBuffer() -{ - return mState.copyReadBuffer.get(); -} - -Buffer *Context::getCopyWriteBuffer() -{ - return mState.copyWriteBuffer.get(); -} - -Buffer *Context::getPixelPackBuffer() -{ - return mState.pack.pixelBuffer.get(); -} - -Buffer *Context::getPixelUnpackBuffer() -{ - return mState.unpack.pixelBuffer.get(); + return static_cast(getSamplerTexture(mState.getActiveSampler(), TEXTURE_2D_ARRAY)); } Texture *Context::getSamplerTexture(unsigned int sampler, TextureType type) const { - GLuint texid = mState.samplerTexture[type][sampler].id(); - - if (texid == 0) // Special case: 0 refers to different initial textures based on the target + if (mState.getSamplerTextureId(sampler, type) == 0) { switch (type) { @@ -1627,8 +846,10 @@ Texture *Context::getSamplerTexture(unsigned int sampler, TextureType type) cons case TEXTURE_2D_ARRAY: return mTexture2DArrayZero.get(); } } - - return mState.samplerTexture[type][sampler].get(); + else + { + return mState.getSamplerTexture(sampler, type); + } } void Context::getBooleanv(GLenum pname, GLboolean *params) @@ -1636,200 +857,77 @@ void 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.depthStencil.depthMask; break; - case GL_COLOR_WRITEMASK: - 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.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; - case GL_TRANSFORM_FEEDBACK_ACTIVE: *params = getCurrentTransformFeedback()->isStarted(); break; - case GL_TRANSFORM_FEEDBACK_PAUSED: *params = getCurrentTransformFeedback()->isPaused(); break; default: - UNREACHABLE(); + mState.getBooleanv(pname, params); break; } } void Context::getFloatv(GLenum pname, GLfloat *params) { - // Please note: DEPTH_CLEAR_VALUE is included in our internal getFloatv 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 - // case, this should make no difference to the calling application. + // Queries about context capabilities and maximums are answered by Context. + // Queries about current GL state values are answered by State. 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.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; + params[0] = mCaps.minAliasedLineWidth; + params[1] = mCaps.maxAliasedLineWidth; break; case GL_ALIASED_POINT_SIZE_RANGE: - params[0] = gl::ALIASED_POINT_SIZE_RANGE_MIN; - params[1] = getMaximumPointSize(); - break; - case GL_DEPTH_RANGE: - params[0] = mState.zNear; - params[1] = mState.zFar; - break; - case GL_COLOR_CLEAR_VALUE: - params[0] = mState.colorClearValue.red; - params[1] = mState.colorClearValue.green; - params[2] = mState.colorClearValue.blue; - params[3] = mState.colorClearValue.alpha; - break; - case GL_BLEND_COLOR: - params[0] = mState.blendColor.red; - params[1] = mState.blendColor.green; - params[2] = mState.blendColor.blue; - params[3] = mState.blendColor.alpha; + params[0] = mCaps.minAliasedPointSize; + params[1] = mCaps.maxAliasedPointSize; break; case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT: - ASSERT(supportsTextureFilterAnisotropy()); - *params = mMaxTextureAnisotropy; + ASSERT(mExtensions.textureFilterAnisotropic); + *params = mExtensions.maxTextureAnisotropy; break; default: - UNREACHABLE(); + mState.getFloatv(pname, params); break; } } void 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); - ASSERT(colorAttachment < mRenderer->getMaxRenderTargets()); - Framebuffer *framebuffer = getDrawFramebuffer(); - *params = framebuffer->getDrawBufferState(colorAttachment); - return; - } + // Queries about context capabilities and maximums are answered by Context. + // Queries about current GL state values are answered by State. - // 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 - // case, this should make no difference to the calling application. You may find it in - // Context::getFloatv. switch (pname) { - case GL_MAX_VERTEX_ATTRIBS: *params = gl::MAX_VERTEX_ATTRIBS; break; - case GL_MAX_VERTEX_UNIFORM_VECTORS: *params = mRenderer->getMaxVertexUniformVectors(); break; - case GL_MAX_VERTEX_UNIFORM_COMPONENTS: *params = mRenderer->getMaxVertexUniformVectors() * 4; break; - case GL_MAX_VARYING_VECTORS: *params = mRenderer->getMaxVaryingVectors(); break; - case GL_MAX_VARYING_COMPONENTS: *params = mRenderer->getMaxVaryingVectors() * 4; 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 = mRenderer->getMaxFragmentUniformVectors(); break; - case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS: *params = mRenderer->getMaxFragmentUniformVectors() * 4; 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; - case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = getCurrentVertexArray()->getElementArrayBufferId(); break; + case GL_MAX_VERTEX_ATTRIBS: *params = mCaps.maxVertexAttributes; break; + case GL_MAX_VERTEX_UNIFORM_VECTORS: *params = mCaps.maxVertexUniformVectors; break; + case GL_MAX_VERTEX_UNIFORM_COMPONENTS: *params = mCaps.maxVertexUniformComponents; break; + case GL_MAX_VARYING_VECTORS: *params = mCaps.maxVaryingVectors; break; + case GL_MAX_VARYING_COMPONENTS: *params = mCaps.maxVertexOutputComponents; break; + case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = mCaps.maxCombinedTextureImageUnits; break; + case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = mCaps.maxVertexTextureImageUnits; break; + case GL_MAX_TEXTURE_IMAGE_UNITS: *params = mCaps.maxTextureImageUnits; break; + case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = mCaps.maxFragmentUniformVectors; break; + case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS: *params = mCaps.maxFragmentInputComponents; break; + case GL_MAX_RENDERBUFFER_SIZE: *params = mCaps.maxRenderbufferSize; break; + case GL_MAX_COLOR_ATTACHMENTS_EXT: *params = mCaps.maxColorAttachments; break; + case GL_MAX_DRAW_BUFFERS_EXT: *params = mCaps.maxDrawBuffers; break; //case GL_FRAMEBUFFER_BINDING: // now equivalent to GL_DRAW_FRAMEBUFFER_BINDING_ANGLE - case GL_DRAW_FRAMEBUFFER_BINDING_ANGLE: *params = mState.drawFramebuffer; break; - case GL_READ_FRAMEBUFFER_BINDING_ANGLE: *params = mState.readFramebuffer; break; - case GL_RENDERBUFFER_BINDING: *params = mState.renderbuffer.id(); break; - case GL_VERTEX_ARRAY_BINDING: *params = mState.vertexArray; break; - case GL_CURRENT_PROGRAM: *params = mState.currentProgram; break; - case GL_PACK_ALIGNMENT: *params = mState.pack.alignment; break; - case GL_PACK_REVERSE_ROW_ORDER_ANGLE: *params = mState.pack.reverseRowOrder; break; - case GL_UNPACK_ALIGNMENT: *params = mState.unpack.alignment; break; - 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.depthStencil.stencilFunc; break; - case GL_STENCIL_REF: *params = mState.stencilRef; break; - case GL_STENCIL_VALUE_MASK: *params = clampToInt(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 = clampToInt(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 = clampToInt(mState.depthStencil.stencilWritemask); break; - case GL_STENCIL_BACK_WRITEMASK: *params = clampToInt(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 = getMaximum2DTextureDimension(); break; - case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = getMaximumCubeTextureDimension(); break; - case GL_MAX_3D_TEXTURE_SIZE: *params = getMaximum3DTextureDimension(); break; - case GL_MAX_ARRAY_TEXTURE_LAYERS: *params = getMaximum2DArrayTextureLayers(); break; - case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT: *params = getUniformBufferOffsetAlignment(); break; - case GL_MAX_UNIFORM_BUFFER_BINDINGS: *params = getMaximumCombinedUniformBufferBindings(); break; - case GL_MAX_VERTEX_UNIFORM_BLOCKS: *params = mRenderer->getMaxVertexShaderUniformBuffers(); break; - case GL_MAX_FRAGMENT_UNIFORM_BLOCKS: *params = mRenderer->getMaxFragmentShaderUniformBuffers(); break; - case GL_MAX_COMBINED_UNIFORM_BLOCKS: *params = getMaximumCombinedUniformBufferBindings(); break; + case GL_MAX_TEXTURE_SIZE: *params = mCaps.max2DTextureSize; break; + case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = mCaps.maxCubeMapTextureSize; break; + case GL_MAX_3D_TEXTURE_SIZE: *params = mCaps.max3DTextureSize; break; + case GL_MAX_ARRAY_TEXTURE_LAYERS: *params = mCaps.maxArrayTextureLayers; break; + case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT: *params = mCaps.uniformBufferOffsetAlignment; break; + case GL_MAX_UNIFORM_BUFFER_BINDINGS: *params = mCaps.maxUniformBufferBindings; break; + case GL_MAX_VERTEX_UNIFORM_BLOCKS: *params = mCaps.maxVertexUniformBlocks; break; + case GL_MAX_FRAGMENT_UNIFORM_BLOCKS: *params = mCaps.maxFragmentUniformBlocks; break; + case GL_MAX_COMBINED_UNIFORM_BLOCKS: *params = mCaps.maxCombinedTextureImageUnits; break; case GL_MAJOR_VERSION: *params = mClientVersion; break; case GL_MINOR_VERSION: *params = 0; break; - case GL_MAX_ELEMENTS_INDICES: *params = mRenderer->getMaxRecommendedElementsIndices(); break; - case GL_MAX_ELEMENTS_VERTICES: *params = mRenderer->getMaxRecommendedElementsVertices(); break; - case GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS: *params = mRenderer->getMaxTransformFeedbackInterleavedComponents(); break; - case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS: *params = mRenderer->getMaxTransformFeedbackBuffers(); break; - case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS: *params = mRenderer->getMaxTransformFeedbackSeparateComponents(); break; - case GL_NUM_COMPRESSED_TEXTURE_FORMATS: - params[0] = mNumCompressedTextureFormats; - break; - case GL_MAX_SAMPLES_ANGLE: - *params = static_cast(getMaxSupportedSamples()); - break; - case GL_SAMPLE_BUFFERS: - case GL_SAMPLES: - { - gl::Framebuffer *framebuffer = getDrawFramebuffer(); - if (framebuffer->completeness() == GL_FRAMEBUFFER_COMPLETE) - { - switch (pname) - { - case GL_SAMPLE_BUFFERS: - if (framebuffer->getSamples() != 0) - { - *params = 1; - } - else - { - *params = 0; - } - break; - case GL_SAMPLES: - *params = framebuffer->getSamples(); - break; - } - } - else - { - *params = 0; - } - } - break; + case GL_MAX_ELEMENTS_INDICES: *params = mCaps.maxElementsIndices; break; + case GL_MAX_ELEMENTS_VERTICES: *params = mCaps.maxElementsVertices; break; + case GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS: *params = mCaps.maxTransformFeedbackInterleavedComponents; break; + case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS: *params = mCaps.maxTransformFeedbackSeparateAttributes; break; + case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS: *params = mCaps.maxTransformFeedbackSeparateComponents; break; + case GL_NUM_COMPRESSED_TEXTURE_FORMATS: *params = mCaps.compressedTextureFormats.size(); break; + case GL_MAX_SAMPLES_ANGLE: *params = mExtensions.maxSamples; break; case GL_IMPLEMENTATION_COLOR_READ_TYPE: case GL_IMPLEMENTATION_COLOR_READ_FORMAT: { @@ -1843,174 +941,57 @@ void Context::getIntegerv(GLenum pname, GLint *params) break; case GL_MAX_VIEWPORT_DIMS: { - params[0] = mMaxViewportDimension; - params[1] = mMaxViewportDimension; + params[0] = mCaps.maxViewportWidth; + params[1] = mCaps.maxViewportHeight; } break; case GL_COMPRESSED_TEXTURE_FORMATS: - { - if (supportsDXT1Textures()) - { - *params++ = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; - *params++ = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; - } - if (supportsDXT3Textures()) - { - *params++ = GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE; - } - if (supportsDXT5Textures()) - { - *params++ = GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE; - } - } - break; - case GL_VIEWPORT: - 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.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.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->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; - } - } - else - { - *params = 0; - } - } - break; - case GL_DEPTH_BITS: - { - gl::Framebuffer *framebuffer = getDrawFramebuffer(); - gl::Renderbuffer *depthbuffer = framebuffer->getDepthbuffer(); - - if (depthbuffer) - { - *params = depthbuffer->getDepthSize(); - } - else - { - *params = 0; - } - } - break; - case GL_STENCIL_BITS: - { - gl::Framebuffer *framebuffer = getDrawFramebuffer(); - gl::Renderbuffer *stencilbuffer = framebuffer->getStencilbuffer(); - - if (stencilbuffer) - { - *params = stencilbuffer->getStencilSize(); - } - else - { - *params = 0; - } - } - break; - case GL_TEXTURE_BINDING_2D: - ASSERT(mState.activeSampler < mRenderer->getMaxCombinedTextureImageUnits()); - *params = mState.samplerTexture[TEXTURE_2D][mState.activeSampler].id(); - break; - case GL_TEXTURE_BINDING_CUBE_MAP: - ASSERT(mState.activeSampler < mRenderer->getMaxCombinedTextureImageUnits()); - *params = mState.samplerTexture[TEXTURE_CUBE][mState.activeSampler].id(); - break; - case GL_TEXTURE_BINDING_3D: - ASSERT(mState.activeSampler < mRenderer->getMaxCombinedTextureImageUnits()); - *params = mState.samplerTexture[TEXTURE_3D][mState.activeSampler].id(); - break; - case GL_TEXTURE_BINDING_2D_ARRAY: - ASSERT(mState.activeSampler < mRenderer->getMaxCombinedTextureImageUnits()); - *params = mState.samplerTexture[TEXTURE_2D_ARRAY][mState.activeSampler].id(); + std::copy(mCaps.compressedTextureFormats.begin(), mCaps.compressedTextureFormats.end(), params); break; case GL_RESET_NOTIFICATION_STRATEGY_EXT: *params = mResetStrategy; break; - case GL_NUM_PROGRAM_BINARY_FORMATS_OES: - *params = 1; + case GL_NUM_SHADER_BINARY_FORMATS: + *params = mCaps.shaderBinaryFormats.size(); break; - case GL_PROGRAM_BINARY_FORMATS_OES: - *params = GL_PROGRAM_BINARY_ANGLE; + case GL_SHADER_BINARY_FORMATS: + std::copy(mCaps.shaderBinaryFormats.begin(), mCaps.shaderBinaryFormats.end(), params); break; - case GL_UNIFORM_BUFFER_BINDING: - *params = mState.genericUniformBuffer.id(); + case GL_NUM_PROGRAM_BINARY_FORMATS: + *params = mCaps.programBinaryFormats.size(); break; - case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: - *params = mState.genericTransformFeedbackBuffer.id(); - break; - case GL_COPY_READ_BUFFER_BINDING: - *params = mState.copyReadBuffer.id(); - break; - case GL_COPY_WRITE_BUFFER_BINDING: - *params = mState.copyWriteBuffer.id(); - break; - case GL_PIXEL_PACK_BUFFER_BINDING: - *params = mState.pack.pixelBuffer.id(); - break; - case GL_PIXEL_UNPACK_BUFFER_BINDING: - *params = mState.unpack.pixelBuffer.id(); + case GL_PROGRAM_BINARY_FORMATS: + std::copy(mCaps.programBinaryFormats.begin(), mCaps.programBinaryFormats.end(), params); break; case GL_NUM_EXTENSIONS: - *params = static_cast(getNumExtensions()); + *params = static_cast(mExtensionStrings.size()); break; default: - UNREACHABLE(); + mState.getIntegerv(pname, params); break; } } void Context::getInteger64v(GLenum pname, GLint64 *params) { + // Queries about context capabilities and maximums are answered by Context. + // Queries about current GL state values are answered by State. switch (pname) { case GL_MAX_ELEMENT_INDEX: - *params = static_cast(std::numeric_limits::max()); + *params = mCaps.maxElementIndex; break; case GL_MAX_UNIFORM_BLOCK_SIZE: - *params = static_cast(mRenderer->getMaxUniformBufferSize()); + *params = mCaps.maxUniformBlockSize; break; case GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS: - { - GLint64 uniformBufferComponents = static_cast(mRenderer->getMaxVertexShaderUniformBuffers()) * static_cast(mRenderer->getMaxUniformBufferSize() / 4); - GLint64 defaultBufferComponents = static_cast(mRenderer->getMaxVertexUniformVectors() * 4); - *params = uniformBufferComponents + defaultBufferComponents; - } + *params = mCaps.maxCombinedVertexUniformComponents; break; case GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS: - { - GLint64 uniformBufferComponents = static_cast(mRenderer->getMaxFragmentShaderUniformBuffers()) * static_cast(mRenderer->getMaxUniformBufferSize() / 4); - GLint64 defaultBufferComponents = static_cast(mRenderer->getMaxVertexUniformVectors() * 4); - *params = uniformBufferComponents + defaultBufferComponents; - } + *params = mCaps.maxCombinedFragmentUniformComponents; break; case GL_MAX_SERVER_WAIT_TIMEOUT: - // We do not wait for server fence objects internally, so report a max timeout of zero. - *params = 0; + *params = mCaps.maxServerWaitTimeout; break; default: UNREACHABLE(); @@ -2020,60 +1001,20 @@ void Context::getInteger64v(GLenum pname, GLint64 *params) bool Context::getIndexedIntegerv(GLenum target, GLuint index, GLint *data) { - switch (target) - { - case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: - if (index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS) - { - *data = mState.transformFeedbackBuffers[index].id(); - } - break; - case GL_UNIFORM_BUFFER_BINDING: - if (index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS) - { - *data = mState.uniformBuffers[index].id(); - } - break; - default: - return false; - } - - return true; + // Queries about context capabilities and maximums are answered by Context. + // Queries about current GL state values are answered by State. + // Indexed integer queries all refer to current state, so this function is a + // mere passthrough. + return mState.getIndexedIntegerv(target, index, data); } bool Context::getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data) { - switch (target) - { - case GL_TRANSFORM_FEEDBACK_BUFFER_START: - if (index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS) - { - *data = mState.transformFeedbackBuffers[index].getOffset(); - } - break; - case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: - if (index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS) - { - *data = mState.transformFeedbackBuffers[index].getSize(); - } - break; - case GL_UNIFORM_BUFFER_START: - if (index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS) - { - *data = mState.uniformBuffers[index].getOffset(); - } - break; - case GL_UNIFORM_BUFFER_SIZE: - if (index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS) - { - *data = mState.uniformBuffers[index].getSize(); - } - break; - default: - return false; - } - - return true; + // Queries about context capabilities and maximums are answered by Context. + // Queries about current GL state values are answered by State. + // Indexed integer queries all refer to current state, so this function is a + // mere passthrough. + return mState.getIndexedInteger64v(target, index, data); } bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams) @@ -2097,13 +1038,19 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu case GL_COMPRESSED_TEXTURE_FORMATS: { *type = GL_INT; - *numParams = mNumCompressedTextureFormats; + *numParams = mCaps.compressedTextureFormats.size(); + } + return true; + case GL_PROGRAM_BINARY_FORMATS_OES: + { + *type = GL_INT; + *numParams = mCaps.programBinaryFormats.size(); } return true; case GL_SHADER_BINARY_FORMATS: { *type = GL_INT; - *numParams = 0; + *numParams = mCaps.shaderBinaryFormats.size(); } return true; case GL_MAX_VERTEX_ATTRIBS: @@ -2172,7 +1119,6 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu case GL_TEXTURE_BINDING_CUBE_MAP: case GL_RESET_NOTIFICATION_STRATEGY_EXT: case GL_NUM_PROGRAM_BINARY_FORMATS_OES: - case GL_PROGRAM_BINARY_FORMATS_OES: { *type = GL_INT; *numParams = 1; @@ -2180,7 +1126,7 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu return true; case GL_MAX_SAMPLES_ANGLE: { - if (getMaxSupportedSamples() != 0) + if (mExtensions.framebufferMultisample) { *type = GL_INT; *numParams = 1; @@ -2194,7 +1140,7 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu case GL_PIXEL_PACK_BUFFER_BINDING: case GL_PIXEL_UNPACK_BUFFER_BINDING: { - if (supportsPBOs()) + if (mExtensions.pixelBufferObject) { *type = GL_INT; *numParams = 1; @@ -2268,7 +1214,7 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu } return true; case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT: - if (!supportsTextureFilterAnisotropy()) + if (!mExtensions.maxTextureAnisotropy) { return false; } @@ -2372,22 +1318,20 @@ bool Context::getIndexedQueryParameterInfo(GLenum target, GLenum *type, unsigned // scissor rectangle to the renderer bool Context::applyRenderTarget(GLenum drawMode, bool ignoreViewport) { - Framebuffer *framebufferObject = getDrawFramebuffer(); - - if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE) - { - return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION, false); - } + Framebuffer *framebufferObject = mState.getDrawFramebuffer(); + ASSERT(framebufferObject && framebufferObject->completeness() == GL_FRAMEBUFFER_COMPLETE); mRenderer->applyRenderTarget(framebufferObject); - if (!mRenderer->setViewport(mState.viewport, mState.zNear, mState.zFar, drawMode, mState.rasterizer.frontFace, + float nearZ, farZ; + mState.getDepthRange(&nearZ, &farZ); + if (!mRenderer->setViewport(mState.getViewport(), nearZ, farZ, drawMode, mState.getRasterizerState().frontFace, ignoreViewport)) { return false; } - mRenderer->setScissorRectangle(mState.scissor, mState.scissorTest); + mRenderer->setScissorRectangle(mState.getScissor(), mState.isScissorTestEnabled()); return true; } @@ -2395,17 +1339,22 @@ bool Context::applyRenderTarget(GLenum drawMode, bool ignoreViewport) // Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D 9 device void Context::applyState(GLenum drawMode) { - Framebuffer *framebufferObject = getDrawFramebuffer(); + Framebuffer *framebufferObject = mState.getDrawFramebuffer(); int samples = framebufferObject->getSamples(); - mState.rasterizer.pointDrawMode = (drawMode == GL_POINTS); - mState.rasterizer.multiSample = (samples != 0); - mRenderer->setRasterizerState(mState.rasterizer); + RasterizerState rasterizer = mState.getRasterizerState(); + rasterizer.pointDrawMode = (drawMode == GL_POINTS); + rasterizer.multiSample = (samples != 0); + + mRenderer->setRasterizerState(rasterizer); unsigned int mask = 0; - if (mState.sampleCoverage) + if (mState.isSampleCoverageEnabled()) { - if (mState.sampleCoverageValue != 0) + GLclampf coverageValue; + bool coverageInvert = false; + mState.getSampleCoverageParams(&coverageValue, &coverageInvert); + if (coverageValue != 0) { float threshold = 0.5f; @@ -2414,7 +1363,7 @@ void Context::applyState(GLenum drawMode) { mask <<= 1; - if ((i + 1) * mState.sampleCoverageValue >= threshold) + if ((i + 1) * coverageValue >= threshold) { threshold += 1.0f; mask |= 1; @@ -2422,7 +1371,7 @@ void Context::applyState(GLenum drawMode) } } - if (mState.sampleCoverageInvert) + if (coverageInvert) { mask = ~mask; } @@ -2431,21 +1380,23 @@ void Context::applyState(GLenum drawMode) { mask = 0xFFFFFFFF; } - mRenderer->setBlendState(framebufferObject, mState.blend, mState.blendColor, mask); + mRenderer->setBlendState(framebufferObject, mState.getBlendState(), mState.getBlendColor(), mask); - mRenderer->setDepthStencilState(mState.depthStencil, mState.stencilRef, mState.stencilBackRef, - mState.rasterizer.frontFace == GL_CCW); + mRenderer->setDepthStencilState(mState.getDepthStencilState(), mState.getStencilRef(), mState.getStencilBackRef(), + rasterizer.frontFace == GL_CCW); } // Applies the shaders and shader constants to the Direct3D 9 device void Context::applyShaders(ProgramBinary *programBinary, bool transformFeedbackActive) { - const VertexAttribute *vertexAttributes = getCurrentVertexArray()->getVertexAttributes(); + const VertexAttribute *vertexAttributes = mState.getVertexArray()->getVertexAttributes(); VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS]; - VertexFormat::GetInputLayout(inputLayout, programBinary, vertexAttributes, mState.vertexAttribCurrentValues); + VertexFormat::GetInputLayout(inputLayout, programBinary, vertexAttributes, mState.getVertexAttribCurrentValues()); - mRenderer->applyShaders(programBinary, mState.rasterizer.rasterizerDiscard, transformFeedbackActive, inputLayout); + const Framebuffer *fbo = mState.getDrawFramebuffer(); + + mRenderer->applyShaders(programBinary, inputLayout, fbo, mState.getRasterizerState().rasterizerDiscard, transformFeedbackActive); programBinary->applyUniforms(); } @@ -2457,14 +1408,14 @@ size_t Context::getCurrentTexturesAndSamplerStates(ProgramBinary *programBinary, for (size_t i = 0; i < samplerRange; i++) { outTextureTypes[i] = programBinary->getSamplerTextureType(type, i); - GLint textureUnit = programBinary->getSamplerMapping(type, i); // OpenGL texture image unit index + GLint textureUnit = programBinary->getSamplerMapping(type, i, getCaps()); // OpenGL texture image unit index if (textureUnit != -1) { outTextures[i] = getSamplerTexture(textureUnit, outTextureTypes[i]); - outTextures[i]->getSamplerState(&outSamplers[i]); - if (mState.samplers[textureUnit] != 0) + outTextures[i]->getSamplerStateWithNativeOffset(&outSamplers[i]); + Sampler *samplerObject = mState.getSampler(textureUnit); + if (samplerObject) { - Sampler *samplerObject = getSampler(mState.samplers[textureUnit]); samplerObject->getState(&outSamplers[i]); } } @@ -2481,7 +1432,7 @@ void Context::generateSwizzles(Texture *textures[], size_t count) { for (size_t i = 0; i < count; i++) { - if (textures[i] && textures[i]->isSwizzled()) + if (textures[i] && textures[i]->getSamplerState().swizzleRequired()) { mRenderer->generateSwizzle(textures[i]); } @@ -2496,8 +1447,8 @@ void Context::applyTextures(SamplerType shaderType, Texture *textures[], Texture size_t framebufferSerialCount) { // Range of Direct3D samplers of given sampler type - size_t samplerCount = (shaderType == SAMPLER_PIXEL) ? MAX_TEXTURE_IMAGE_UNITS - : mRenderer->getMaxVertexTextureImageUnits(); + size_t samplerCount = (shaderType == SAMPLER_PIXEL) ? mCaps.maxTextureImageUnits + : mCaps.maxVertexTextureImageUnits; for (size_t samplerIndex = 0; samplerIndex < textureCount; samplerIndex++) { @@ -2508,18 +1459,16 @@ void Context::applyTextures(SamplerType shaderType, Texture *textures[], Texture if (texture) { // TODO: std::binary_search may become unavailable using older versions of GCC - if (texture->isSamplerComplete(sampler) && + if (texture->isSamplerComplete(sampler, mTextureCaps, mExtensions, mClientVersion) && !std::binary_search(framebufferSerials.begin(), framebufferSerials.begin() + framebufferSerialCount, texture->getTextureSerial())) { mRenderer->setSamplerState(shaderType, samplerIndex, sampler); mRenderer->setTexture(shaderType, samplerIndex, texture); - texture->resetDirty(); } else { Texture *incompleteTexture = getIncompleteTexture(textureType); mRenderer->setTexture(shaderType, samplerIndex, incompleteTexture); - incompleteTexture->resetDirty(); } } else @@ -2536,7 +1485,7 @@ void Context::applyTextures(SamplerType shaderType, Texture *textures[], Texture bool Context::applyUniformBuffers() { - Program *programObject = getProgram(mState.currentProgram); + Program *programObject = getProgram(mState.getCurrentProgramId()); ProgramBinary *programBinary = programObject->getProgramBinary(); std::vector boundBuffers; @@ -2544,34 +1493,34 @@ bool Context::applyUniformBuffers() for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < programBinary->getActiveUniformBlockCount(); uniformBlockIndex++) { GLuint blockBinding = programObject->getUniformBlockBinding(uniformBlockIndex); - const OffsetBindingPointer& boundBuffer = mState.uniformBuffers[blockBinding]; - if (boundBuffer.id() == 0) + + if (mState.getIndexedUniformBuffer(blockBinding)->id() == 0) { // undefined behaviour return false; } else { - gl::Buffer *uniformBuffer = boundBuffer.get(); + Buffer *uniformBuffer = mState.getIndexedUniformBuffer(blockBinding); ASSERT(uniformBuffer); boundBuffers.push_back(uniformBuffer); } } - return programBinary->applyUniformBuffers(boundBuffers); + return programBinary->applyUniformBuffers(boundBuffers, getCaps()); } bool Context::applyTransformFeedbackBuffers() { - TransformFeedback *curTransformFeedback = getCurrentTransformFeedback(); + TransformFeedback *curTransformFeedback = mState.getCurrentTransformFeedback(); if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused()) { Buffer *transformFeedbackBuffers[IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; GLintptr transformFeedbackOffsets[IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; for (size_t i = 0; i < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++) { - transformFeedbackBuffers[i] = mState.transformFeedbackBuffers[i].get(); - transformFeedbackOffsets[i] = mState.transformFeedbackBuffers[i].getOffset(); + transformFeedbackBuffers[i] = mState.getIndexedTransformFeedbackBuffer(i); + transformFeedbackOffsets[i] = mState.getIndexedTransformFeedbackBufferOffset(i); } mRenderer->applyTransformFeedbackBuffers(transformFeedbackBuffers, transformFeedbackOffsets); return true; @@ -2586,7 +1535,7 @@ void Context::markTransformFeedbackUsage() { for (size_t i = 0; i < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++) { - Buffer *buffer = mState.transformFeedbackBuffers[i].get(); + Buffer *buffer = mState.getIndexedTransformFeedbackBuffer(i); if (buffer) { buffer->markTransformFeedbackUsage(); @@ -2596,86 +1545,30 @@ void Context::markTransformFeedbackUsage() void Context::clear(GLbitfield mask) { - if (isRasterizerDiscardEnabled()) + if (mState.isRasterizerDiscardEnabled()) { return; } - ClearParameters clearParams = { 0 }; - for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) - { - clearParams.clearColor[i] = false; - } - clearParams.colorFClearValue = mState.colorClearValue; - clearParams.colorClearType = GL_FLOAT; - clearParams.colorMaskRed = mState.blend.colorMaskRed; - clearParams.colorMaskGreen = mState.blend.colorMaskGreen; - clearParams.colorMaskBlue = mState.blend.colorMaskBlue; - clearParams.colorMaskAlpha = mState.blend.colorMaskAlpha; - clearParams.clearDepth = false; - clearParams.depthClearValue = mState.depthClearValue; - clearParams.clearStencil = false; - clearParams.stencilClearValue = mState.stencilClearValue; - clearParams.stencilWriteMask = mState.depthStencil.stencilWritemask; - clearParams.scissorEnabled = mState.scissorTest; - clearParams.scissor = mState.scissor; - - Framebuffer *framebufferObject = getDrawFramebuffer(); - if (mask & GL_COLOR_BUFFER_BIT) - { - if (framebufferObject->hasEnabledColorAttachment()) - { - for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) - { - clearParams.clearColor[i] = true; - } - } - } - - if (mask & GL_DEPTH_BUFFER_BIT) - { - if (mState.depthStencil.depthMask && framebufferObject->getDepthbufferType() != GL_NONE) - { - clearParams.clearDepth = true; - } - } - - if (mask & GL_STENCIL_BUFFER_BIT) - { - if (framebufferObject->getStencilbufferType() != GL_NONE) - { - rx::RenderTarget *depthStencil = framebufferObject->getStencilbuffer()->getDepthStencil(); - if (!depthStencil) - { - ERR("Depth stencil pointer unexpectedly null."); - return; - } - - if (gl::GetStencilBits(depthStencil->getActualFormat(), mClientVersion) > 0) - { - clearParams.clearStencil = true; - } - } - } - + ClearParameters clearParams = mState.getClearParameters(mask); if (!applyRenderTarget(GL_TRIANGLES, true)) // Clips the clear to the scissor rectangle but not the viewport { return; } - mRenderer->clear(clearParams, framebufferObject); + mRenderer->clear(clearParams, mState.getDrawFramebuffer()); } void Context::clearBufferfv(GLenum buffer, int drawbuffer, const float *values) { - if (isRasterizerDiscardEnabled()) + if (mState.isRasterizerDiscardEnabled()) { return; } // glClearBufferfv can be called to clear the color buffer or depth buffer - ClearParameters clearParams = { 0 }; + ClearParameters clearParams = mState.getClearParameters(0); if (buffer == GL_COLOR) { @@ -2686,90 +1579,54 @@ void Context::clearBufferfv(GLenum buffer, int drawbuffer, const float *values) clearParams.colorFClearValue = ColorF(values[0], values[1], values[2], values[3]); clearParams.colorClearType = GL_FLOAT; } - else - { - for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) - { - clearParams.clearColor[i] = false; - } - clearParams.colorFClearValue = mState.colorClearValue; - clearParams.colorClearType = GL_FLOAT; - } - - clearParams.colorMaskRed = mState.blend.colorMaskRed; - clearParams.colorMaskGreen = mState.blend.colorMaskGreen; - clearParams.colorMaskBlue = mState.blend.colorMaskBlue; - clearParams.colorMaskAlpha = mState.blend.colorMaskAlpha; if (buffer == GL_DEPTH) { clearParams.clearDepth = true; clearParams.depthClearValue = values[0]; } - else - { - clearParams.clearDepth = false; - clearParams.depthClearValue = mState.depthClearValue; - } - - clearParams.clearStencil = false; - clearParams.stencilClearValue = mState.stencilClearValue; - clearParams.stencilWriteMask = mState.depthStencil.stencilWritemask; - clearParams.scissorEnabled = mState.scissorTest; - clearParams.scissor = mState.scissor; if (!applyRenderTarget(GL_TRIANGLES, true)) // Clips the clear to the scissor rectangle but not the viewport { return; } - mRenderer->clear(clearParams, getDrawFramebuffer()); + mRenderer->clear(clearParams, mState.getDrawFramebuffer()); } void Context::clearBufferuiv(GLenum buffer, int drawbuffer, const unsigned int *values) { - if (isRasterizerDiscardEnabled()) + if (mState.isRasterizerDiscardEnabled()) { return; } // glClearBufferuv can only be called to clear a color buffer - ClearParameters clearParams = { 0 }; + ClearParameters clearParams = mState.getClearParameters(0); for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) { clearParams.clearColor[i] = (drawbuffer == static_cast(i)); } clearParams.colorUIClearValue = ColorUI(values[0], values[1], values[2], values[3]); clearParams.colorClearType = GL_UNSIGNED_INT; - clearParams.colorMaskRed = mState.blend.colorMaskRed; - clearParams.colorMaskGreen = mState.blend.colorMaskGreen; - clearParams.colorMaskBlue = mState.blend.colorMaskBlue; - clearParams.colorMaskAlpha = mState.blend.colorMaskAlpha; - clearParams.clearDepth = false; - clearParams.depthClearValue = mState.depthClearValue; - clearParams.clearStencil = false; - clearParams.stencilClearValue = mState.stencilClearValue; - clearParams.stencilWriteMask = mState.depthStencil.stencilWritemask; - clearParams.scissorEnabled = mState.scissorTest; - clearParams.scissor = mState.scissor; if (!applyRenderTarget(GL_TRIANGLES, true)) // Clips the clear to the scissor rectangle but not the viewport { return; } - mRenderer->clear(clearParams, getDrawFramebuffer()); + mRenderer->clear(clearParams, mState.getDrawFramebuffer()); } void Context::clearBufferiv(GLenum buffer, int drawbuffer, const int *values) { - if (isRasterizerDiscardEnabled()) + if (mState.isRasterizerDiscardEnabled()) { return; } // glClearBufferfv can be called to clear the color buffer or stencil buffer - ClearParameters clearParams = { 0 }; + ClearParameters clearParams = mState.getClearParameters(0); if (buffer == GL_COLOR) { @@ -2780,103 +1637,62 @@ void Context::clearBufferiv(GLenum buffer, int drawbuffer, const int *values) clearParams.colorIClearValue = ColorI(values[0], values[1], values[2], values[3]); clearParams.colorClearType = GL_INT; } - else - { - for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) - { - clearParams.clearColor[i] = false; - } - clearParams.colorFClearValue = mState.colorClearValue; - clearParams.colorClearType = GL_FLOAT; - } - - clearParams.colorMaskRed = mState.blend.colorMaskRed; - clearParams.colorMaskGreen = mState.blend.colorMaskGreen; - clearParams.colorMaskBlue = mState.blend.colorMaskBlue; - clearParams.colorMaskAlpha = mState.blend.colorMaskAlpha; - - clearParams.clearDepth = false; - clearParams.depthClearValue = mState.depthClearValue; if (buffer == GL_STENCIL) { clearParams.clearStencil = true; clearParams.stencilClearValue = values[1]; } - else - { - clearParams.clearStencil = false; - clearParams.stencilClearValue = mState.stencilClearValue; - } - clearParams.stencilWriteMask = mState.depthStencil.stencilWritemask; - - clearParams.scissorEnabled = mState.scissorTest; - clearParams.scissor = mState.scissor; if (!applyRenderTarget(GL_TRIANGLES, true)) // Clips the clear to the scissor rectangle but not the viewport { return; } - mRenderer->clear(clearParams, getDrawFramebuffer()); + mRenderer->clear(clearParams, mState.getDrawFramebuffer()); } void Context::clearBufferfi(GLenum buffer, int drawbuffer, float depth, int stencil) { - if (isRasterizerDiscardEnabled()) + if (mState.isRasterizerDiscardEnabled()) { return; } // glClearBufferfi can only be called to clear a depth stencil buffer - ClearParameters clearParams = { 0 }; - for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) - { - clearParams.clearColor[i] = false; - } - clearParams.colorFClearValue = mState.colorClearValue; - clearParams.colorClearType = GL_FLOAT; - clearParams.colorMaskRed = mState.blend.colorMaskRed; - clearParams.colorMaskGreen = mState.blend.colorMaskGreen; - clearParams.colorMaskBlue = mState.blend.colorMaskBlue; - clearParams.colorMaskAlpha = mState.blend.colorMaskAlpha; + ClearParameters clearParams = mState.getClearParameters(0); clearParams.clearDepth = true; clearParams.depthClearValue = depth; clearParams.clearStencil = true; clearParams.stencilClearValue = stencil; - clearParams.stencilWriteMask = mState.depthStencil.stencilWritemask; - clearParams.scissorEnabled = mState.scissorTest; - clearParams.scissor = mState.scissor; if (!applyRenderTarget(GL_TRIANGLES, true)) // Clips the clear to the scissor rectangle but not the viewport { return; } - mRenderer->clear(clearParams, getDrawFramebuffer()); + mRenderer->clear(clearParams, mState.getDrawFramebuffer()); } void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei *bufSize, void* pixels) { - gl::Framebuffer *framebuffer = getReadFramebuffer(); + gl::Framebuffer *framebuffer = mState.getReadFramebuffer(); - bool isSized = IsSizedInternalFormat(format, mClientVersion); - GLenum sizedInternalFormat = (isSized ? format : GetSizedInternalFormat(format, type, mClientVersion)); - GLuint outputPitch = GetRowPitch(sizedInternalFormat, type, mClientVersion, width, mState.pack.alignment); + GLenum sizedInternalFormat = GetSizedInternalFormat(format, type); + const InternalFormat &sizedFormatInfo = GetInternalFormatInfo(sizedInternalFormat); + GLuint outputPitch = sizedFormatInfo.computeRowPitch(type, width, mState.getPackAlignment()); - mRenderer->readPixels(framebuffer, x, y, width, height, format, type, outputPitch, mState.pack, pixels); + mRenderer->readPixels(framebuffer, x, y, width, height, format, type, outputPitch, mState.getPackState(), + reinterpret_cast(pixels)); } void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances) { - if (!mState.currentProgram) - { - return gl::error(GL_INVALID_OPERATION); - } + ASSERT(mState.getCurrentProgramId() != 0); - ProgramBinary *programBinary = getCurrentProgramBinary(); - programBinary->applyUniforms(); + ProgramBinary *programBinary = mState.getCurrentProgramBinary(); + programBinary->updateSamplerMapping(); Texture *vsTextures[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; TextureType vsTextureTypes[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; @@ -2903,7 +1719,7 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instan applyState(mode); - GLenum err = mRenderer->applyVertexBuffer(programBinary, getCurrentVertexArray()->getVertexAttributes(), mState.vertexAttribCurrentValues, first, count, instances); + GLenum err = mRenderer->applyVertexBuffer(programBinary, mState.getVertexArray()->getVertexAttributes(), mState.getVertexAttribCurrentValues(), first, count, instances); if (err != GL_NO_ERROR) { return gl::error(err); @@ -2924,11 +1740,6 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instan return; } - if (!programBinary->validateSamplers(NULL)) - { - return gl::error(GL_INVALID_OPERATION); - } - if (!skipDraw(mode)) { mRenderer->drawArrays(mode, count, instances, transformFeedbackActive); @@ -2940,21 +1751,14 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instan } } -void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instances) +void Context::drawElements(GLenum mode, GLsizei count, GLenum type, + const GLvoid *indices, GLsizei instances, + const rx::RangeUI &indexRange) { - if (!mState.currentProgram) - { - return gl::error(GL_INVALID_OPERATION); - } + ASSERT(mState.getCurrentProgramId() != 0); - VertexArray *vao = getCurrentVertexArray(); - if (!indices && !vao->getElementArrayBuffer()) - { - return gl::error(GL_INVALID_OPERATION); - } - - ProgramBinary *programBinary = getCurrentProgramBinary(); - programBinary->applyUniforms(); + ProgramBinary *programBinary = mState.getCurrentProgramBinary(); + programBinary->updateSamplerMapping(); Texture *vsTextures[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; TextureType vsTextureTypes[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; @@ -2981,15 +1785,19 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid applyState(mode); + VertexArray *vao = mState.getVertexArray(); rx::TranslatedIndexData indexInfo; + indexInfo.indexRange = indexRange; GLenum err = mRenderer->applyIndexBuffer(indices, vao->getElementArrayBuffer(), count, mode, type, &indexInfo); if (err != GL_NO_ERROR) { return gl::error(err); } - GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1; - err = mRenderer->applyVertexBuffer(programBinary, vao->getVertexAttributes(), mState.vertexAttribCurrentValues, indexInfo.minIndex, vertexCount, instances); + GLsizei vertexCount = indexInfo.indexRange.length() + 1; + err = mRenderer->applyVertexBuffer(programBinary, vao->getVertexAttributes(), + mState.getVertexAttribCurrentValues(), + indexInfo.indexRange.start, vertexCount, instances); if (err != GL_NO_ERROR) { return gl::error(err); @@ -3013,11 +1821,6 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid return; } - if (!programBinary->validateSamplers(NULL)) - { - return gl::error(GL_INVALID_OPERATION); - } - if (!skipDraw(mode)) { mRenderer->drawElements(mode, count, type, indices, vao->getElementArrayBuffer(), indexInfo, instances); @@ -3030,71 +1833,28 @@ void Context::sync(bool block) mRenderer->sync(block); } -void Context::recordInvalidEnum() +void Context::recordError(const Error &error) { - mInvalidEnum = true; -} - -void Context::recordInvalidValue() -{ - mInvalidValue = true; -} - -void Context::recordInvalidOperation() -{ - mInvalidOperation = true; -} - -void Context::recordOutOfMemory() -{ - mOutOfMemory = true; -} - -void Context::recordInvalidFramebufferOperation() -{ - mInvalidFramebufferOperation = true; + if (error.isError()) + { + mErrors.insert(error.getCode()); + } } // Get one of the recorded errors and clear its flag, if any. // [OpenGL ES 2.0.24] section 2.5 page 13. GLenum Context::getError() { - if (mInvalidEnum) + if (mErrors.empty()) { - mInvalidEnum = false; - - return GL_INVALID_ENUM; + return GL_NO_ERROR; } - - if (mInvalidValue) + else { - mInvalidValue = false; - - return GL_INVALID_VALUE; + GLenum error = *mErrors.begin(); + mErrors.erase(mErrors.begin()); + return error; } - - if (mInvalidOperation) - { - mInvalidOperation = false; - - return GL_INVALID_OPERATION; - } - - if (mOutOfMemory) - { - mOutOfMemory = false; - - return GL_OUT_OF_MEMORY; - } - - if (mInvalidFramebufferOperation) - { - mInvalidFramebufferOperation = false; - - return GL_INVALID_FRAMEBUFFER_OPERATION; - } - - return GL_NO_ERROR; } GLenum Context::getResetStatus() @@ -3131,241 +1891,56 @@ int Context::getClientVersion() const return mClientVersion; } -int Context::getMajorShaderModel() const +const Caps &Context::getCaps() const { - return mMajorShaderModel; + return mCaps; } -float Context::getMaximumPointSize() const +const TextureCapsMap &Context::getTextureCaps() const { - return mMaximumPointSize; + return mTextureCaps; } -unsigned int Context::getMaximumCombinedTextureImageUnits() const +const Extensions &Context::getExtensions() const { - return mRenderer->getMaxCombinedTextureImageUnits(); -} - -unsigned int Context::getMaximumCombinedUniformBufferBindings() const -{ - return mRenderer->getMaxVertexShaderUniformBuffers() + - mRenderer->getMaxFragmentShaderUniformBuffers(); -} - -int Context::getMaxSupportedSamples() const -{ - return mRenderer->getMaxSupportedSamples(); -} - -GLsizei Context::getMaxSupportedFormatSamples(GLenum internalFormat) const -{ - return mRenderer->getMaxSupportedFormatSamples(internalFormat); -} - -GLsizei Context::getNumSampleCounts(GLenum internalFormat) const -{ - return mRenderer->getNumSampleCounts(internalFormat); -} - -void Context::getSampleCounts(GLenum internalFormat, GLsizei bufSize, GLint *params) const -{ - mRenderer->getSampleCounts(internalFormat, bufSize, params); -} - -unsigned int Context::getMaxTransformFeedbackBufferBindings() const -{ - return mRenderer->getMaxTransformFeedbackBuffers(); -} - -GLintptr Context::getUniformBufferOffsetAlignment() const -{ - // setting a large alignment forces uniform buffers to bind with zero offset - return static_cast(std::numeric_limits::max()); -} - -unsigned int Context::getMaximumRenderTargets() const -{ - return mRenderer->getMaxRenderTargets(); -} - -bool Context::supportsEventQueries() const -{ - return mSupportsEventQueries; -} - -bool Context::supportsOcclusionQueries() const -{ - return mSupportsOcclusionQueries; -} - -bool Context::supportsBGRATextures() const -{ - return mSupportsBGRATextures; -} - -bool Context::supportsDXT1Textures() const -{ - return mSupportsDXT1Textures; -} - -bool Context::supportsDXT3Textures() const -{ - return mSupportsDXT3Textures; -} - -bool Context::supportsDXT5Textures() const -{ - return mSupportsDXT5Textures; -} - -bool Context::supportsFloat32Textures() const -{ - return mSupportsFloat32Textures; -} - -bool Context::supportsFloat32LinearFilter() const -{ - return mSupportsFloat32LinearFilter; -} - -bool Context::supportsFloat32RenderableTextures() const -{ - return mSupportsFloat32RenderableTextures; -} - -bool Context::supportsFloat16Textures() const -{ - return mSupportsFloat16Textures; -} - -bool Context::supportsFloat16LinearFilter() const -{ - return mSupportsFloat16LinearFilter; -} - -bool Context::supportsFloat16RenderableTextures() const -{ - return mSupportsFloat16RenderableTextures; -} - -int Context::getMaximumRenderbufferDimension() const -{ - return mMaxRenderbufferDimension; -} - -int Context::getMaximum2DTextureDimension() const -{ - return mMax2DTextureDimension; -} - -int Context::getMaximumCubeTextureDimension() const -{ - return mMaxCubeTextureDimension; -} - -int Context::getMaximum3DTextureDimension() const -{ - return mMax3DTextureDimension; -} - -int Context::getMaximum2DArrayTextureLayers() const -{ - return mMax2DArrayTextureLayers; -} - -int Context::getMaximum2DTextureLevel() const -{ - return mMax2DTextureLevel; -} - -int Context::getMaximumCubeTextureLevel() const -{ - return mMaxCubeTextureLevel; -} - -int Context::getMaximum3DTextureLevel() const -{ - return mMax3DTextureLevel; -} - -int Context::getMaximum2DArrayTextureLevel() const -{ - return mMax2DArrayTextureLevel; -} - -bool Context::supportsLuminanceTextures() const -{ - return mSupportsLuminanceTextures; -} - -bool Context::supportsLuminanceAlphaTextures() const -{ - return mSupportsLuminanceAlphaTextures; -} - -bool Context::supportsRGTextures() const -{ - return mSupportsRGTextures; -} - -bool Context::supportsDepthTextures() const -{ - return mSupportsDepthTextures; -} - -bool Context::supports32bitIndices() const -{ - return mSupports32bitIndices; -} - -bool Context::supportsNonPower2Texture() const -{ - return mSupportsNonPower2Texture; -} - -bool Context::supportsInstancing() const -{ - return mSupportsInstancing; -} - -bool Context::supportsTextureFilterAnisotropy() const -{ - return mSupportsTextureFilterAnisotropy; -} - -bool Context::supportsPBOs() const -{ - return mSupportsPBOs; -} - -float Context::getTextureMaxAnisotropy() const -{ - return mMaxTextureAnisotropy; + return mExtensions; } void Context::getCurrentReadFormatType(GLenum *internalFormat, GLenum *format, GLenum *type) { - Framebuffer *framebuffer = getReadFramebuffer(); + Framebuffer *framebuffer = mState.getReadFramebuffer(); ASSERT(framebuffer && framebuffer->completeness() == GL_FRAMEBUFFER_COMPLETE); - Renderbuffer *renderbuffer = framebuffer->getReadColorbuffer(); - ASSERT(renderbuffer); + FramebufferAttachment *attachment = framebuffer->getReadColorbuffer(); + ASSERT(attachment); - *internalFormat = renderbuffer->getActualFormat(); - *format = gl::GetFormat(renderbuffer->getActualFormat(), mClientVersion); - *type = gl::GetType(renderbuffer->getActualFormat(), mClientVersion); + GLenum actualFormat = attachment->getActualFormat(); + const InternalFormat &actualFormatInfo = GetInternalFormatInfo(actualFormat); + + *internalFormat = actualFormat; + *format = actualFormatInfo.format; + *type = actualFormatInfo.type; +} + +void Context::detachTexture(GLuint texture) +{ + // Simple pass-through to State's detachTexture method, as textures do not require + // allocation map management either here or in the resource manager at detach time. + // Zero textures are held by the Context, and we don't attempt to request them from + // the State. + mState.detachTexture(texture); } void Context::detachBuffer(GLuint buffer) { + // Buffer detachment is handled by Context, because the buffer must also be + // attached from any VAOs in existence, and Context holds the VAO map. + // [OpenGL ES 2.0.24] section 2.9 page 22: // If a buffer object is deleted while it is bound, all bindings to that object in the current context // (i.e. in the thread that called Delete-Buffers) are reset to zero. - if (mState.arrayBuffer.id() == buffer) - { - mState.arrayBuffer.set(NULL); - } + mState.removeArrayBufferBinding(buffer); // mark as freed among the vertex array objects for (auto vaoIt = mVertexArrayMap.begin(); vaoIt != mVertexArrayMap.end(); vaoIt++) @@ -3374,54 +1949,22 @@ void Context::detachBuffer(GLuint buffer) } } -void Context::detachTexture(GLuint texture) -{ - // [OpenGL ES 2.0.24] section 3.8 page 84: - // If a texture object is deleted, it is as if all texture units which are bound to that texture object are - // rebound to texture object zero - - for (int type = 0; type < TEXTURE_TYPE_COUNT; type++) - { - for (int sampler = 0; sampler < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS; sampler++) - { - if (mState.samplerTexture[type][sampler].id() == texture) - { - mState.samplerTexture[type][sampler].set(NULL); - } - } - } - - // [OpenGL ES 2.0.24] section 4.4 page 112: - // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is - // as if FramebufferTexture2D had been called, with a texture of 0, for each attachment point to which this - // image was attached in the currently bound framebuffer. - - Framebuffer *readFramebuffer = getReadFramebuffer(); - Framebuffer *drawFramebuffer = getDrawFramebuffer(); - - if (readFramebuffer) - { - readFramebuffer->detachTexture(texture); - } - - if (drawFramebuffer && drawFramebuffer != readFramebuffer) - { - drawFramebuffer->detachTexture(texture); - } -} - void Context::detachFramebuffer(GLuint framebuffer) { + // Framebuffer detachment is handled by Context, because 0 is a valid + // Framebuffer object, and a pointer to it must be passed from Context + // to State at binding time. + // [OpenGL ES 2.0.24] section 4.4 page 107: // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero. - if (mState.readFramebuffer == framebuffer) + if (mState.removeReadFramebufferBinding(framebuffer)) { bindReadFramebuffer(0); } - if (mState.drawFramebuffer == framebuffer) + if (mState.removeDrawFramebufferBinding(framebuffer)) { bindDrawFramebuffer(0); } @@ -3429,40 +1972,19 @@ void Context::detachFramebuffer(GLuint framebuffer) void Context::detachRenderbuffer(GLuint renderbuffer) { - // [OpenGL ES 2.0.24] section 4.4 page 109: - // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer - // had been executed with the target RENDERBUFFER and name of zero. - - if (mState.renderbuffer.id() == renderbuffer) - { - bindRenderbuffer(0); - } - - // [OpenGL ES 2.0.24] section 4.4 page 111: - // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer, - // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment - // point to which this image was attached in the currently bound framebuffer. - - Framebuffer *readFramebuffer = getReadFramebuffer(); - Framebuffer *drawFramebuffer = getDrawFramebuffer(); - - if (readFramebuffer) - { - readFramebuffer->detachRenderbuffer(renderbuffer); - } - - if (drawFramebuffer && drawFramebuffer != readFramebuffer) - { - drawFramebuffer->detachRenderbuffer(renderbuffer); - } + mState.detachRenderbuffer(renderbuffer); } void Context::detachVertexArray(GLuint vertexArray) { + // Vertex array detachment is handled by Context, because 0 is a valid + // VAO, and a pointer to it must be passed from Context to State at + // binding time. + // [OpenGL ES 3.0.2] section 2.10 page 43: // If a vertex array object that is currently bound is deleted, the binding // for that object reverts to zero and the default vertex array becomes current. - if (mState.vertexArray == vertexArray) + if (mState.removeVertexArrayBinding(vertexArray)) { bindVertexArray(0); } @@ -3470,25 +1992,12 @@ void Context::detachVertexArray(GLuint vertexArray) void Context::detachTransformFeedback(GLuint transformFeedback) { - if (mState.transformFeedback.id() == transformFeedback) - { - bindTransformFeedback(0); - } + mState.detachTransformFeedback(transformFeedback); } void Context::detachSampler(GLuint sampler) { - // [OpenGL ES 3.0.2] section 3.8.2 pages 123-124: - // If a sampler object that is currently bound to one or more texture units is - // deleted, it is as though BindSampler is called once for each texture unit to - // which the sampler is bound, with unit set to the texture unit and sampler set to zero. - for (unsigned int textureUnit = 0; textureUnit < ArraySize(mState.samplers); textureUnit++) - { - if (mState.samplers[textureUnit] == sampler) - { - mState.samplers[textureUnit] = 0; - } - } + mState.detachSampler(sampler); } Texture *Context::getIncompleteTexture(TextureType type) @@ -3508,7 +2017,7 @@ Texture *Context::getIncompleteTexture(TextureType type) case TEXTURE_2D: { - Texture2D *incomplete2d = new Texture2D(mRenderer, Texture::INCOMPLETE_TEXTURE_ID); + Texture2D *incomplete2d = new Texture2D(mRenderer->createTexture(GL_TEXTURE_2D), Texture::INCOMPLETE_TEXTURE_ID); incomplete2d->setImage(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); t = incomplete2d; } @@ -3516,7 +2025,7 @@ Texture *Context::getIncompleteTexture(TextureType type) case TEXTURE_CUBE: { - TextureCubeMap *incompleteCube = new TextureCubeMap(mRenderer, Texture::INCOMPLETE_TEXTURE_ID); + TextureCubeMap *incompleteCube = new TextureCubeMap(mRenderer->createTexture(GL_TEXTURE_CUBE_MAP), Texture::INCOMPLETE_TEXTURE_ID); incompleteCube->setImagePosX(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); incompleteCube->setImageNegX(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); @@ -3531,7 +2040,7 @@ Texture *Context::getIncompleteTexture(TextureType type) case TEXTURE_3D: { - Texture3D *incomplete3d = new Texture3D(mRenderer, Texture::INCOMPLETE_TEXTURE_ID); + Texture3D *incomplete3d = new Texture3D(mRenderer->createTexture(GL_TEXTURE_3D), Texture::INCOMPLETE_TEXTURE_ID); incomplete3d->setImage(0, 1, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); t = incomplete3d; @@ -3540,7 +2049,7 @@ Texture *Context::getIncompleteTexture(TextureType type) case TEXTURE_2D_ARRAY: { - Texture2DArray *incomplete2darray = new Texture2DArray(mRenderer, Texture::INCOMPLETE_TEXTURE_ID); + Texture2DArray *incomplete2darray = new Texture2DArray(mRenderer->createTexture(GL_TEXTURE_2D_ARRAY), Texture::INCOMPLETE_TEXTURE_ID); incomplete2darray->setImage(0, 1, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); t = incomplete2darray; @@ -3561,7 +2070,7 @@ bool Context::skipDraw(GLenum drawMode) // ProgramBinary assumes non-point rendering if gl_PointSize isn't written, // which affects varying interpolation. Since the value of gl_PointSize is // undefined when not written, just skip drawing to avoid unexpected results. - if (!getCurrentProgramBinary()->usesPointSize()) + if (!mState.getCurrentProgramBinary()->usesPointSize()) { // This is stictly speaking not an error, but developers should be // notified of risking undefined behavior. @@ -3572,7 +2081,7 @@ bool Context::skipDraw(GLenum drawMode) } else if (IsTriangleMode(drawMode)) { - if (mState.rasterizer.cullFace && mState.rasterizer.cullMode == GL_FRONT_AND_BACK) + if (mState.getRasterizerState().cullFace && mState.getRasterizerState().cullMode == GL_FRONT_AND_BACK) { return true; } @@ -3581,27 +2090,9 @@ bool Context::skipDraw(GLenum drawMode) return false; } -void Context::setVertexAttribf(GLuint index, const GLfloat values[4]) -{ - ASSERT(index < gl::MAX_VERTEX_ATTRIBS); - mState.vertexAttribCurrentValues[index].setFloatValues(values); -} - -void Context::setVertexAttribu(GLuint index, const GLuint values[4]) -{ - ASSERT(index < gl::MAX_VERTEX_ATTRIBS); - mState.vertexAttribCurrentValues[index].setUnsignedIntValues(values); -} - -void Context::setVertexAttribi(GLuint index, const GLint values[4]) -{ - ASSERT(index < gl::MAX_VERTEX_ATTRIBS); - mState.vertexAttribCurrentValues[index].setIntValues(values); -} - void Context::setVertexAttribDivisor(GLuint index, GLuint divisor) { - getCurrentVertexArray()->setVertexAttribDivisor(index, divisor); + mState.getVertexArray()->setVertexAttribDivisor(index, divisor); } void Context::samplerParameteri(GLuint sampler, GLenum pname, GLint param) @@ -3640,8 +2131,8 @@ void Context::samplerParameterf(GLuint sampler, GLenum pname, GLfloat param) case GL_TEXTURE_WRAP_S: samplerObject->setWrapS(uiround(param)); break; case GL_TEXTURE_WRAP_T: samplerObject->setWrapT(uiround(param)); break; case GL_TEXTURE_WRAP_R: samplerObject->setWrapR(uiround(param)); break; - case GL_TEXTURE_MIN_LOD: samplerObject->setMinLod(param); break; - case GL_TEXTURE_MAX_LOD: samplerObject->setMaxLod(param); break; + case GL_TEXTURE_MIN_LOD: samplerObject->setMinLod(param); break; + case GL_TEXTURE_MAX_LOD: samplerObject->setMaxLod(param); break; case GL_TEXTURE_COMPARE_MODE: samplerObject->setComparisonMode(uiround(param)); break; case GL_TEXTURE_COMPARE_FUNC: samplerObject->setComparisonFunc(uiround(param)); break; default: UNREACHABLE(); break; @@ -3692,175 +2183,6 @@ GLfloat Context::getSamplerParameterf(GLuint sampler, GLenum pname) } } -// keep list sorted in following order -// OES extensions -// EXT extensions -// Vendor extensions -void Context::initExtensionString() -{ - // Do not report extension in GLES 3 contexts for now - if (mClientVersion == 2) - { - // OES extensions - if (supports32bitIndices()) - { - mExtensionStringList.push_back("GL_OES_element_index_uint"); - } - - mExtensionStringList.push_back("GL_OES_packed_depth_stencil"); - mExtensionStringList.push_back("GL_OES_get_program_binary"); - mExtensionStringList.push_back("GL_OES_rgb8_rgba8"); - - if (supportsPBOs()) - { - mExtensionStringList.push_back("NV_pixel_buffer_object"); - mExtensionStringList.push_back("GL_OES_mapbuffer"); - mExtensionStringList.push_back("GL_EXT_map_buffer_range"); - } - - if (mRenderer->getDerivativeInstructionSupport()) - { - mExtensionStringList.push_back("GL_OES_standard_derivatives"); - } - - if (supportsFloat16Textures()) - { - mExtensionStringList.push_back("GL_OES_texture_half_float"); - } - if (supportsFloat16LinearFilter()) - { - mExtensionStringList.push_back("GL_OES_texture_half_float_linear"); - } - if (supportsFloat32Textures()) - { - mExtensionStringList.push_back("GL_OES_texture_float"); - } - if (supportsFloat32LinearFilter()) - { - mExtensionStringList.push_back("GL_OES_texture_float_linear"); - } - - if (supportsRGTextures()) - { - mExtensionStringList.push_back("GL_EXT_texture_rg"); - } - - if (supportsNonPower2Texture()) - { - mExtensionStringList.push_back("GL_OES_texture_npot"); - } - - // Multi-vendor (EXT) extensions - if (supportsOcclusionQueries()) - { - mExtensionStringList.push_back("GL_EXT_occlusion_query_boolean"); - } - - mExtensionStringList.push_back("GL_EXT_read_format_bgra"); - mExtensionStringList.push_back("GL_EXT_robustness"); - mExtensionStringList.push_back("GL_EXT_shader_texture_lod"); - - if (supportsDXT1Textures()) - { - mExtensionStringList.push_back("GL_EXT_texture_compression_dxt1"); - } - - if (supportsTextureFilterAnisotropy()) - { - mExtensionStringList.push_back("GL_EXT_texture_filter_anisotropic"); - } - - if (supportsBGRATextures()) - { - mExtensionStringList.push_back("GL_EXT_texture_format_BGRA8888"); - } - - if (mRenderer->getMaxRenderTargets() > 1) - { - mExtensionStringList.push_back("GL_EXT_draw_buffers"); - } - - mExtensionStringList.push_back("GL_EXT_texture_storage"); - mExtensionStringList.push_back("GL_EXT_frag_depth"); - mExtensionStringList.push_back("GL_EXT_blend_minmax"); - - // ANGLE-specific extensions - if (supportsDepthTextures()) - { - mExtensionStringList.push_back("GL_ANGLE_depth_texture"); - } - - mExtensionStringList.push_back("GL_ANGLE_framebuffer_blit"); - if (getMaxSupportedSamples() != 0) - { - mExtensionStringList.push_back("GL_ANGLE_framebuffer_multisample"); - } - - if (supportsInstancing()) - { - mExtensionStringList.push_back("GL_ANGLE_instanced_arrays"); - } - - mExtensionStringList.push_back("GL_ANGLE_pack_reverse_row_order"); - - if (supportsDXT3Textures()) - { - mExtensionStringList.push_back("GL_ANGLE_texture_compression_dxt3"); - } - if (supportsDXT5Textures()) - { - mExtensionStringList.push_back("GL_ANGLE_texture_compression_dxt5"); - } - - mExtensionStringList.push_back("GL_ANGLE_texture_usage"); - mExtensionStringList.push_back("GL_ANGLE_translated_shader_source"); - - // Other vendor-specific extensions - if (supportsEventQueries()) - { - mExtensionStringList.push_back("GL_NV_fence"); - } - } - - if (mClientVersion == 3) - { - mExtensionStringList.push_back("GL_EXT_color_buffer_float"); - - mExtensionStringList.push_back("GL_EXT_read_format_bgra"); - - if (supportsBGRATextures()) - { - mExtensionStringList.push_back("GL_EXT_texture_format_BGRA8888"); - } - } - - // Join the extension strings to one long string for use with GetString - std::stringstream strstr; - for (unsigned int extensionIndex = 0; extensionIndex < mExtensionStringList.size(); extensionIndex++) - { - strstr << mExtensionStringList[extensionIndex]; - strstr << " "; - } - - mCombinedExtensionsString = makeStaticString(strstr.str()); -} - -const char *Context::getCombinedExtensionsString() const -{ - return mCombinedExtensionsString; -} - -const char *Context::getExtensionString(const GLuint index) const -{ - ASSERT(index < mExtensionStringList.size()); - return mExtensionStringList[index].c_str(); -} - -unsigned int Context::getNumExtensions() const -{ - return mExtensionStringList.size(); -} - void Context::initRendererString() { std::ostringstream rendererString; @@ -3868,32 +2190,56 @@ void Context::initRendererString() rendererString << mRenderer->getRendererDescription(); rendererString << ")"; - mRendererString = makeStaticString(rendererString.str()); + mRendererString = MakeStaticString(rendererString.str()); } -const char *Context::getRendererString() const +const std::string &Context::getRendererString() const { return mRendererString; } +void Context::initExtensionStrings() +{ + mExtensionStrings = mExtensions.getStrings(); + + std::ostringstream combinedStringStream; + std::copy(mExtensionStrings.begin(), mExtensionStrings.end(), std::ostream_iterator(combinedStringStream, " ")); + mExtensionString = combinedStringStream.str(); +} + +const std::string &Context::getExtensionString() const +{ + return mExtensionString; +} + +const std::string &Context::getExtensionString(size_t idx) const +{ + return mExtensionStrings[idx]; +} + +size_t Context::getExtensionStringCount() const +{ + return mExtensionStrings.size(); +} + size_t Context::getBoundFramebufferTextureSerials(FramebufferTextureSerialArray *outSerialArray) { size_t serialCount = 0; - Framebuffer *drawFramebuffer = getDrawFramebuffer(); + Framebuffer *drawFramebuffer = mState.getDrawFramebuffer(); for (unsigned int i = 0; i < IMPLEMENTATION_MAX_DRAW_BUFFERS; i++) { - Renderbuffer *renderBuffer = drawFramebuffer->getColorbuffer(i); - if (renderBuffer && renderBuffer->isTexture()) + FramebufferAttachment *attachment = drawFramebuffer->getColorbuffer(i); + if (attachment && attachment->isTexture()) { - (*outSerialArray)[serialCount++] = renderBuffer->getTextureSerial(); + (*outSerialArray)[serialCount++] = attachment->getTextureSerial(); } } - Renderbuffer *depthStencilBuffer = drawFramebuffer->getDepthOrStencilbuffer(); - if (depthStencilBuffer && depthStencilBuffer->isTexture()) + FramebufferAttachment *depthStencilAttachment = drawFramebuffer->getDepthOrStencilbuffer(); + if (depthStencilAttachment && depthStencilAttachment->isTexture()) { - (*outSerialArray)[serialCount++] = depthStencilBuffer->getTextureSerial(); + (*outSerialArray)[serialCount++] = depthStencilAttachment->getTextureSerial(); } std::sort(outSerialArray->begin(), outSerialArray->begin() + serialCount); @@ -3904,8 +2250,8 @@ size_t Context::getBoundFramebufferTextureSerials(FramebufferTextureSerialArray void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) { - Framebuffer *readFramebuffer = getReadFramebuffer(); - Framebuffer *drawFramebuffer = getDrawFramebuffer(); + Framebuffer *readFramebuffer = mState.getReadFramebuffer(); + Framebuffer *drawFramebuffer = mState.getDrawFramebuffer(); bool blitRenderTarget = false; bool blitDepth = false; @@ -3927,110 +2273,79 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1 gl::Rectangle dstRect(dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0); if (blitRenderTarget || blitDepth || blitStencil) { - const gl::Rectangle *scissor = mState.scissorTest ? &mState.scissor : NULL; + const gl::Rectangle *scissor = mState.isScissorTestEnabled() ? &mState.getScissor() : NULL; mRenderer->blitRect(readFramebuffer, srcRect, drawFramebuffer, dstRect, scissor, blitRenderTarget, blitDepth, blitStencil, filter); } } -void Context::invalidateFrameBuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments, - GLint x, GLint y, GLsizei width, GLsizei height) +void Context::releaseShaderCompiler() { - Framebuffer *frameBuffer = NULL; - switch (target) - { - case GL_FRAMEBUFFER: - case GL_DRAW_FRAMEBUFFER: - frameBuffer = getDrawFramebuffer(); - break; - case GL_READ_FRAMEBUFFER: - frameBuffer = getReadFramebuffer(); - break; - default: - UNREACHABLE(); - } - - if (frameBuffer && frameBuffer->completeness() == GL_FRAMEBUFFER_COMPLETE) - { - for (int i = 0; i < numAttachments; ++i) - { - rx::RenderTarget *renderTarget = NULL; - - if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT15) - { - gl::Renderbuffer *renderBuffer = frameBuffer->getColorbuffer(attachments[i] - GL_COLOR_ATTACHMENT0); - if (renderBuffer) - { - renderTarget = renderBuffer->getRenderTarget(); - } - } - else if (attachments[i] == GL_COLOR) - { - gl::Renderbuffer *renderBuffer = frameBuffer->getColorbuffer(0); - if (renderBuffer) - { - renderTarget = renderBuffer->getRenderTarget(); - } - } - else - { - gl::Renderbuffer *renderBuffer = NULL; - switch (attachments[i]) - { - case GL_DEPTH_ATTACHMENT: - case GL_DEPTH: - renderBuffer = frameBuffer->getDepthbuffer(); - break; - case GL_STENCIL_ATTACHMENT: - case GL_STENCIL: - renderBuffer = frameBuffer->getStencilbuffer(); - break; - case GL_DEPTH_STENCIL_ATTACHMENT: - renderBuffer = frameBuffer->getDepthOrStencilbuffer(); - break; - default: - UNREACHABLE(); - } - - if (renderBuffer) - { - renderTarget = renderBuffer->getDepthStencil(); - } - } - - if (renderTarget) - { - renderTarget->invalidate(x, y, width, height); - } - } - } + mRenderer->releaseShaderCompiler(); } -bool Context::hasMappedBuffer(GLenum target) const +void Context::initCaps(GLuint clientVersion) { - if (target == GL_ARRAY_BUFFER) + mCaps = mRenderer->getRendererCaps(); + + mExtensions = mRenderer->getRendererExtensions(); + + if (clientVersion < 3) { - for (unsigned int attribIndex = 0; attribIndex < gl::MAX_VERTEX_ATTRIBS; attribIndex++) + // Disable ES3+ extensions + mExtensions.colorBufferFloat = false; + } + + if (clientVersion > 2) + { + // FIXME(geofflang): Don't support EXT_sRGB in non-ES2 contexts + //mExtensions.sRGB = false; + } + + // Apply implementation limits + mCaps.maxVertexAttributes = std::min(mCaps.maxVertexAttributes, MAX_VERTEX_ATTRIBS); + mCaps.maxVertexTextureImageUnits = std::min(mCaps.maxVertexTextureImageUnits, IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS); + mCaps.maxVertexUniformBlocks = std::min(mCaps.maxVertexUniformBlocks, IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS); + mCaps.maxVertexOutputComponents = std::min(mCaps.maxVertexOutputComponents, IMPLEMENTATION_MAX_VARYING_VECTORS * 4); + + mCaps.maxFragmentInputComponents = std::min(mCaps.maxFragmentInputComponents, IMPLEMENTATION_MAX_VARYING_VECTORS * 4); + mCaps.maxTextureImageUnits = std::min(mCaps.maxTextureImageUnits, MAX_TEXTURE_IMAGE_UNITS); + + mCaps.maxCombinedTextureImageUnits = std::min(mCaps.maxCombinedTextureImageUnits, IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS); + + GLuint maxSamples = 0; + mCaps.compressedTextureFormats.clear(); + + const TextureCapsMap &rendererFormats = mRenderer->getRendererTextureCaps(); + for (TextureCapsMap::const_iterator i = rendererFormats.begin(); i != rendererFormats.end(); i++) + { + GLenum format = i->first; + TextureCaps formatCaps = i->second; + + const InternalFormat &formatInfo = GetInternalFormatInfo(format); + if (formatCaps.texturable && formatInfo.textureSupport(clientVersion, mExtensions)) { - const gl::VertexAttribute &vertexAttrib = getVertexAttribState(attribIndex); - gl::Buffer *boundBuffer = vertexAttrib.mBoundBuffer.get(); - if (vertexAttrib.mArrayEnabled && boundBuffer && boundBuffer->mapped()) + // Update the format caps based on the client version and extensions + formatCaps.renderable = formatInfo.renderSupport(clientVersion, mExtensions); + formatCaps.filterable = formatInfo.filterSupport(clientVersion, mExtensions); + + // OpenGL ES does not support multisampling with integer formats + if (formatInfo.componentType == GL_INT || formatInfo.componentType == GL_UNSIGNED_INT) { - return true; + formatCaps.sampleCounts.clear(); } + maxSamples = std::max(maxSamples, formatCaps.getMaxSamples()); + + if (formatInfo.compressed) + { + mCaps.compressedTextureFormats.push_back(format); + } + + mTextureCaps.insert(format, formatCaps); } } - else if (target == GL_ELEMENT_ARRAY_BUFFER) - { - Buffer *elementBuffer = getElementArrayBuffer(); - return (elementBuffer && elementBuffer->mapped()); - } - else if (target == GL_TRANSFORM_FEEDBACK_BUFFER) - { - UNIMPLEMENTED(); - } - else UNREACHABLE(); - return false; + + mExtensions.maxSamples = maxSamples; } } diff --git a/gfx/angle/src/libGLESv2/Context.h b/gfx/angle/src/libGLESv2/Context.h index b3c8a3fc2512..5a19eea07ce4 100644 --- a/gfx/angle/src/libGLESv2/Context.h +++ b/gfx/angle/src/libGLESv2/Context.h @@ -10,11 +10,17 @@ #ifndef LIBGLESV2_CONTEXT_H_ #define LIBGLESV2_CONTEXT_H_ -#include -#include -#include -#include -#include +#include "common/angleutils.h" +#include "common/RefCountObject.h" +#include "libGLESv2/Caps.h" +#include "libGLESv2/Error.h" +#include "libGLESv2/HandleAllocator.h" +#include "libGLESv2/angletypes.h" +#include "libGLESv2/Constants.h" +#include "libGLESv2/VertexAttribute.h" +#include "libGLESv2/State.h" + +#include "angle_gl.h" #include #include @@ -22,13 +28,6 @@ #include #include -#include "common/angleutils.h" -#include "common/RefCountObject.h" -#include "libGLESv2/HandleAllocator.h" -#include "libGLESv2/angletypes.h" -#include "libGLESv2/Constants.h" -#include "libGLESv2/VertexAttribute.h" - namespace rx { class Renderer; @@ -61,71 +60,11 @@ class FenceSync; class Query; class ResourceManager; class Buffer; -class VertexAttribute; +struct VertexAttribute; class VertexArray; class Sampler; class TransformFeedback; -// Helper structure to store all raw state -struct State -{ - ColorF colorClearValue; - GLclampf depthClearValue; - int stencilClearValue; - - RasterizerState rasterizer; - bool scissorTest; - Rectangle scissor; - - BlendState blend; - ColorF blendColor; - bool sampleCoverage; - GLclampf sampleCoverageValue; - bool sampleCoverageInvert; - - DepthStencilState depthStencil; - GLint stencilRef; - GLint stencilBackRef; - - GLfloat lineWidth; - - GLenum generateMipmapHint; - GLenum fragmentShaderDerivativeHint; - - Rectangle viewport; - float zNear; - float zFar; - - unsigned int activeSampler; // Active texture unit selector - GL_TEXTURE0 - BindingPointer arrayBuffer; - GLuint readFramebuffer; - GLuint drawFramebuffer; - BindingPointer renderbuffer; - GLuint currentProgram; - - VertexAttribCurrentValueData vertexAttribCurrentValues[MAX_VERTEX_ATTRIBS]; // From glVertexAttrib - unsigned int vertexArray; - - BindingPointer samplerTexture[TEXTURE_TYPE_COUNT][IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS]; - GLuint samplers[IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS]; - - typedef std::map< GLenum, BindingPointer > ActiveQueryMap; - ActiveQueryMap activeQueries; - - BindingPointer genericUniformBuffer; - OffsetBindingPointer uniformBuffers[IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS]; - - BindingPointer transformFeedback; - BindingPointer genericTransformFeedbackBuffer; - OffsetBindingPointer transformFeedbackBuffers[IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; - - BindingPointer copyReadBuffer; - BindingPointer copyWriteBuffer; - - PixelUnpackState unpack; - PixelPackState pack; -}; - class Context { public: @@ -138,115 +77,6 @@ class Context virtual void markContextLost(); bool isContextLost(); - // State manipulation - void setCap(GLenum cap, bool enabled); - bool getCap(GLenum cap); - - void setClearColor(float red, float green, float blue, float alpha); - - void setClearDepth(float depth); - - void setClearStencil(int stencil); - - void setRasterizerDiscard(bool enabled); - bool isRasterizerDiscardEnabled() const; - - void setCullFace(bool enabled); - bool isCullFaceEnabled() const; - - void setCullMode(GLenum mode); - - void setFrontFace(GLenum front); - - void setDepthTest(bool enabled); - bool isDepthTestEnabled() const; - - void setDepthFunc(GLenum depthFunc); - - void setDepthRange(float zNear, float zFar); - - void setBlend(bool enabled); - bool isBlendEnabled() const; - - void setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha); - void setBlendColor(float red, float green, float blue, float alpha); - void setBlendEquation(GLenum rgbEquation, GLenum alphaEquation); - - void setStencilTest(bool enabled); - bool isStencilTestEnabled() const; - - void setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask); - void setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask); - void setStencilWritemask(GLuint stencilWritemask); - void setStencilBackWritemask(GLuint stencilBackWritemask); - void setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass); - void setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass); - - void setPolygonOffsetFill(bool enabled); - bool isPolygonOffsetFillEnabled() const; - - void setPolygonOffsetParams(GLfloat factor, GLfloat units); - - void setSampleAlphaToCoverage(bool enabled); - bool isSampleAlphaToCoverageEnabled() const; - - void setSampleCoverage(bool enabled); - bool isSampleCoverageEnabled() const; - - void setSampleCoverageParams(GLclampf value, bool invert); - - void setScissorTest(bool enabled); - bool isScissorTestEnabled() const; - - void setDither(bool enabled); - bool isDitherEnabled() const; - - void setLineWidth(GLfloat width); - - void setGenerateMipmapHint(GLenum hint); - void setFragmentShaderDerivativeHint(GLenum hint); - - void setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height); - - void setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height); - void getScissorParams(GLint *x, GLint *y, GLsizei *width, GLsizei *height); - - void setColorMask(bool red, bool green, bool blue, bool alpha); - void setDepthMask(bool mask); - - void setActiveSampler(unsigned int active); - - GLuint getReadFramebufferHandle() const; - GLuint getDrawFramebufferHandle() const; - GLuint getRenderbufferHandle() const; - GLuint getVertexArrayHandle() const; - GLuint getSamplerHandle(GLuint textureUnit) const; - unsigned int getActiveSampler() const; - - GLuint getArrayBufferHandle() const; - - bool isQueryActive() const; - const Query *getActiveQuery(GLenum target) const; - GLuint getActiveQueryId(GLenum target) const; - - void setEnableVertexAttribArray(unsigned int attribNum, bool enabled); - const VertexAttribute &getVertexAttribState(unsigned int attribNum) const; - const VertexAttribCurrentValueData &getVertexAttribCurrentValue(unsigned int attribNum) const; - void setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type, - bool normalized, bool pureInteger, GLsizei stride, const void *pointer); - const void *getVertexAttribPointer(unsigned int attribNum) const; - - void setUnpackAlignment(GLint alignment); - GLint getUnpackAlignment() const; - const PixelUnpackState &getUnpackState() const; - - void setPackAlignment(GLint alignment); - GLint getPackAlignment() const; - const PixelPackState &getPackState() const; - - void setPackReverseRowOrder(bool reverseRowOrder); - bool getPackReverseRowOrder() const; - // These create and destroy methods are merely pass-throughs to // ResourceManager, which owns these object types GLuint createBuffer(); @@ -304,7 +134,7 @@ class Context void bindPixelUnpackBuffer(GLuint buffer); void useProgram(GLuint program); void linkProgram(GLuint program); - void setProgramBinary(GLuint program, const void *binary, GLint length); + void setProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLint length); void bindTransformFeedback(GLuint transformFeedback); void beginQuery(GLenum target, GLuint query); @@ -314,9 +144,6 @@ class Context void setRenderbufferStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples); - void setVertexAttribf(GLuint index, const GLfloat values[4]); - void setVertexAttribu(GLuint index, const GLuint values[4]); - void setVertexAttribi(GLuint index, const GLint values[4]); void setVertexAttribDivisor(GLuint index, GLuint divisor); void samplerParameteri(GLuint sampler, GLenum pname, GLint param); @@ -329,7 +156,7 @@ class Context FenceSync *getFenceSync(GLsync handle) const; Shader *getShader(GLuint handle) const; Program *getProgram(GLuint handle) const; - Texture *getTexture(GLuint handle); + Texture *getTexture(GLuint handle) const; Framebuffer *getFramebuffer(GLuint handle) const; Renderbuffer *getRenderbuffer(GLuint handle); VertexArray *getVertexArray(GLuint handle) const; @@ -337,32 +164,14 @@ class Context Query *getQuery(GLuint handle, bool create, GLenum type); TransformFeedback *getTransformFeedback(GLuint handle) const; - Buffer *getTargetBuffer(GLenum target) const; - Buffer *getArrayBuffer(); - Buffer *getElementArrayBuffer() const; - ProgramBinary *getCurrentProgramBinary(); - Texture *getTargetTexture(GLenum target) const; Texture2D *getTexture2D() const; TextureCubeMap *getTextureCubeMap() const; Texture3D *getTexture3D() const; Texture2DArray *getTexture2DArray() const; - Buffer *getGenericUniformBuffer(); - Buffer *getGenericTransformFeedbackBuffer(); - Buffer *getCopyReadBuffer(); - Buffer *getCopyWriteBuffer(); - Buffer *getPixelPackBuffer(); - Buffer *getPixelUnpackBuffer(); Texture *getSamplerTexture(unsigned int sampler, TextureType type) const; - Framebuffer *getTargetFramebuffer(GLenum target) const; - GLuint getTargetFramebufferHandle(GLenum target) const; - Framebuffer *getReadFramebuffer(); - Framebuffer *getDrawFramebuffer(); - VertexArray *getCurrentVertexArray() const; - TransformFeedback *getCurrentTransformFeedback() const; - bool isSampler(GLuint samplerName) const; void getBooleanv(GLenum pname, GLboolean *params); @@ -384,14 +193,12 @@ class Context void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei *bufSize, void* pixels); void drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances); - void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instances); + void drawElements(GLenum mode, GLsizei count, GLenum type, + const GLvoid *indices, GLsizei instances, + const rx::RangeUI &indexRange); void sync(bool block); // flush/finish - void recordInvalidEnum(); - void recordInvalidValue(); - void recordInvalidOperation(); - void recordOutOfMemory(); - void recordInvalidFramebufferOperation(); + void recordError(const Error &error); GLenum getError(); GLenum getResetStatus(); @@ -399,66 +206,28 @@ class Context virtual int getClientVersion() const; - int getMajorShaderModel() const; - float getMaximumPointSize() const; - unsigned int getMaximumCombinedTextureImageUnits() const; - unsigned int getMaximumCombinedUniformBufferBindings() const; - int getMaximumRenderbufferDimension() const; - int getMaximum2DTextureDimension() const; - int getMaximumCubeTextureDimension() const; - int getMaximum3DTextureDimension() const; - int getMaximum2DArrayTextureLayers() const; - int getMaximum2DTextureLevel() const; - int getMaximumCubeTextureLevel() const; - int getMaximum3DTextureLevel() const; - int getMaximum2DArrayTextureLevel() const; - unsigned int getMaximumRenderTargets() const; - GLsizei getMaxSupportedSamples() const; - GLsizei getMaxSupportedFormatSamples(GLenum internalFormat) const; - GLsizei getNumSampleCounts(GLenum internalFormat) const; - void getSampleCounts(GLenum internalFormat, GLsizei bufSize, GLint *params) const; - unsigned int getMaxTransformFeedbackBufferBindings() const; - GLintptr getUniformBufferOffsetAlignment() const; - const char *getCombinedExtensionsString() const; - const char *getExtensionString(const GLuint index) const; - unsigned int getNumExtensions() const; - const char *getRendererString() const; - bool supportsEventQueries() const; - bool supportsOcclusionQueries() const; - bool supportsBGRATextures() const; - bool supportsDXT1Textures() const; - bool supportsDXT3Textures() const; - bool supportsDXT5Textures() const; - bool supportsFloat32Textures() const; - bool supportsFloat32LinearFilter() const; - bool supportsFloat32RenderableTextures() const; - bool supportsFloat16Textures() const; - bool supportsFloat16LinearFilter() const; - bool supportsFloat16RenderableTextures() const; - bool supportsLuminanceTextures() const; - bool supportsLuminanceAlphaTextures() const; - bool supportsRGTextures() const; - bool supportsDepthTextures() const; - bool supports32bitIndices() const; - bool supportsNonPower2Texture() const; - bool supportsInstancing() const; - bool supportsTextureFilterAnisotropy() const; - bool supportsPBOs() const; + const Caps &getCaps() const; + const TextureCapsMap &getTextureCaps() const; + const Extensions &getExtensions() const; + + const std::string &getRendererString() const; + + const std::string &getExtensionString() const; + const std::string &getExtensionString(size_t idx) const; + size_t getExtensionStringCount() const; void getCurrentReadFormatType(GLenum *internalFormat, GLenum *format, GLenum *type); - float getTextureMaxAnisotropy() const; - void blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); - void invalidateFrameBuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments, - GLint x, GLint y, GLsizei width, GLsizei height); - - bool hasMappedBuffer(GLenum target) const; - rx::Renderer *getRenderer() { return mRenderer; } + State &getState() { return mState; } + const State &getState() const { return mState; } + + void releaseShaderCompiler(); + private: DISALLOW_COPY_AND_ASSIGN(Context); @@ -490,17 +259,23 @@ class Context bool skipDraw(GLenum drawMode); - void initExtensionString(); void initRendererString(); + void initExtensionStrings(); size_t getBoundFramebufferTextureSerials(FramebufferTextureSerialArray *outSerialArray); + void initCaps(GLuint clientVersion); + + // Caps to use for validation + Caps mCaps; + TextureCapsMap mTextureCaps; + Extensions mExtensions; + rx::Renderer *const mRenderer; + State mState; int mClientVersion; - State mState; - BindingPointer mTexture2DZero; BindingPointer mTextureCubeMapZero; BindingPointer mTexture3DZero; @@ -527,18 +302,15 @@ class Context TransformFeedbackMap mTransformFeedbackMap; HandleAllocator mTransformFeedbackAllocator; - std::vector mExtensionStringList; - const char *mCombinedExtensionsString; - const char *mRendererString; - + std::string mRendererString; + std::string mExtensionString; + std::vector mExtensionStrings; + BindingPointer mIncompleteTextures[TEXTURE_TYPE_COUNT]; // Recorded errors - bool mInvalidEnum; - bool mInvalidValue; - bool mInvalidOperation; - bool mOutOfMemory; - bool mInvalidFramebufferOperation; + typedef std::set ErrorSet; + ErrorSet mErrors; // Current/lost context flags bool mHasBeenCurrent; @@ -547,46 +319,6 @@ class Context GLenum mResetStrategy; bool mRobustAccess; - BindingPointer mCurrentProgramBinary; - Framebuffer *mBoundDrawFramebuffer; - - int mMajorShaderModel; - float mMaximumPointSize; - bool mSupportsVertexTexture; - bool mSupportsNonPower2Texture; - bool mSupportsInstancing; - int mMaxViewportDimension; - int mMaxRenderbufferDimension; - int mMax2DTextureDimension; - int mMaxCubeTextureDimension; - int mMax3DTextureDimension; - int mMax2DArrayTextureLayers; - int mMax2DTextureLevel; - int mMaxCubeTextureLevel; - int mMax3DTextureLevel; - int mMax2DArrayTextureLevel; - float mMaxTextureAnisotropy; - bool mSupportsEventQueries; - bool mSupportsOcclusionQueries; - bool mSupportsBGRATextures; - bool mSupportsDXT1Textures; - bool mSupportsDXT3Textures; - bool mSupportsDXT5Textures; - bool mSupportsFloat32Textures; - bool mSupportsFloat32LinearFilter; - bool mSupportsFloat32RenderableTextures; - bool mSupportsFloat16Textures; - bool mSupportsFloat16LinearFilter; - bool mSupportsFloat16RenderableTextures; - bool mSupportsLuminanceTextures; - bool mSupportsLuminanceAlphaTextures; - bool mSupportsRGTextures; - bool mSupportsDepthTextures; - bool mSupports32bitIndices; - bool mSupportsTextureFilterAnisotropy; - bool mSupportsPBOs; - int mNumCompressedTextureFormats; - ResourceManager *mResourceManager; }; } diff --git a/gfx/angle/src/libGLESv2/DynamicHLSL.h b/gfx/angle/src/libGLESv2/DynamicHLSL.h deleted file mode 100644 index 07c2a2f2bbc5..000000000000 --- a/gfx/angle/src/libGLESv2/DynamicHLSL.h +++ /dev/null @@ -1,78 +0,0 @@ -// -// Copyright (c) 2014 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. -// -// DynamicHLSL.h: Interface for link and run-time HLSL generation -// - -#ifndef LIBGLESV2_DYNAMIC_HLSL_H_ -#define LIBGLESV2_DYNAMIC_HLSL_H_ - -#include "common/angleutils.h" -#include "libGLESv2/constants.h" - -namespace rx -{ -class Renderer; -} - -namespace gl -{ - -class InfoLog; -class FragmentShader; -class VertexShader; -struct VariableLocation; -struct LinkedVarying; -class VertexAttribute; -struct VertexFormat; -struct ShaderVariable; -struct Varying; -struct Attribute; -struct PackedVarying; - -typedef const PackedVarying *VaryingPacking[IMPLEMENTATION_MAX_VARYING_VECTORS][4]; - -class DynamicHLSL -{ - public: - explicit DynamicHLSL(rx::Renderer *const renderer); - - int packVaryings(InfoLog &infoLog, VaryingPacking packing, FragmentShader *fragmentShader, - VertexShader *vertexShader, const std::vector& transformFeedbackVaryings); - std::string generateInputLayoutHLSL(const VertexFormat inputLayout[], const Attribute shaderAttributes[]) const; - bool generateShaderLinkHLSL(InfoLog &infoLog, int registers, const VaryingPacking packing, - std::string& pixelHLSL, std::string& vertexHLSL, - FragmentShader *fragmentShader, VertexShader *vertexShader, - const std::vector& transformFeedbackVaryings, - std::vector *linkedVaryings, - std::map *programOutputVars) const; - - std::string generateGeometryShaderHLSL(int registers, FragmentShader *fragmentShader, VertexShader *vertexShader) const; - void getInputLayoutSignature(const VertexFormat inputLayout[], GLenum signature[]) const; - - static const std::string VERTEX_ATTRIBUTE_STUB_STRING; - - private: - DISALLOW_COPY_AND_ASSIGN(DynamicHLSL); - - rx::Renderer *const mRenderer; - - std::string generateVaryingHLSL(VertexShader *shader, const std::string &varyingSemantic, - std::vector *linkedVaryings) const; - void defineOutputVariables(FragmentShader *fragmentShader, std::map *programOutputVars) const; - std::string generatePointSpriteHLSL(int registers, FragmentShader *fragmentShader, VertexShader *vertexShader) const; - - // Prepend an underscore - static std::string decorateVariable(const std::string &name); - - std::string generateAttributeConversionHLSL(const VertexFormat &vertexFormat, const ShaderVariable &shaderAttrib) const; -}; - -// Utility method shared between ProgramBinary and DynamicHLSL -std::string ArrayString(unsigned int i); - -} - -#endif // LIBGLESV2_DYNAMIC_HLSL_H_ diff --git a/gfx/angle/src/libGLESv2/Error.cpp b/gfx/angle/src/libGLESv2/Error.cpp new file mode 100644 index 000000000000..cc7d17eb3718 --- /dev/null +++ b/gfx/angle/src/libGLESv2/Error.cpp @@ -0,0 +1,48 @@ +// +// Copyright (c) 2014 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. +// + +// Error.cpp: Implements the gl::Error class which encapsulates an OpenGL error +// and optional error message. + +#include "libGLESv2/Error.h" + +#include "common/angleutils.h" + +#include + +namespace gl +{ + +Error::Error(GLenum errorCode) + : mCode(errorCode), + mMessage() +{ +} + +Error::Error(GLenum errorCode, const char *msg, ...) + : mCode(errorCode), + mMessage() +{ + va_list vararg; + va_start(vararg, msg); + mMessage = FormatString(msg, vararg); + va_end(vararg); +} + +Error::Error(const Error &other) + : mCode(other.mCode), + mMessage(other.mMessage) +{ +} + +Error &Error::operator=(const Error &other) +{ + mCode = other.mCode; + mMessage = other.mMessage; + return *this; +} + +} diff --git a/gfx/angle/src/libGLESv2/Error.h b/gfx/angle/src/libGLESv2/Error.h new file mode 100644 index 000000000000..b70b5a531c6c --- /dev/null +++ b/gfx/angle/src/libGLESv2/Error.h @@ -0,0 +1,39 @@ +// +// Copyright (c) 2014 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. + +// Error.h: Defines the gl::Error class which encapsulates an OpenGL error +// and optional error message. + +#ifndef LIBGLESV2_ERROR_H_ +#define LIBGLESV2_ERROR_H_ + +#include "angle_gl.h" + +#include + +namespace gl +{ + +class Error +{ + public: + explicit Error(GLenum errorCode); + Error(GLenum errorCode, const char *msg, ...); + Error(const Error &other); + Error &operator=(const Error &other); + + GLenum getCode() const { return mCode; } + bool isError() const { return (mCode != GL_NO_ERROR); } + + const std::string &getMessage() const { return mMessage; } + + private: + GLenum mCode; + std::string mMessage; +}; + +} + +#endif // LIBGLESV2_ERROR_H_ diff --git a/gfx/angle/src/libGLESv2/Fence.cpp b/gfx/angle/src/libGLESv2/Fence.cpp index 31d149d629fd..ee9a07a5c48f 100644 --- a/gfx/angle/src/libGLESv2/Fence.cpp +++ b/gfx/angle/src/libGLESv2/Fence.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // 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 @@ -23,6 +22,8 @@ #include "libGLESv2/renderer/Renderer.h" #include "libGLESv2/main.h" +#include "angle_gl.h" + namespace gl { diff --git a/gfx/angle/src/libGLESv2/Float16ToFloat32.cpp b/gfx/angle/src/libGLESv2/Float16ToFloat32.cpp index b90d2f6023c5..5bf7b3fce883 100644 --- a/gfx/angle/src/libGLESv2/Float16ToFloat32.cpp +++ b/gfx/angle/src/libGLESv2/Float16ToFloat32.cpp @@ -1,4 +1,3 @@ -#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 diff --git a/gfx/angle/src/libGLESv2/Framebuffer.cpp b/gfx/angle/src/libGLESv2/Framebuffer.cpp index 97d37d005add..c32b96bf2e2b 100644 --- a/gfx/angle/src/libGLESv2/Framebuffer.cpp +++ b/gfx/angle/src/libGLESv2/Framebuffer.cpp @@ -1,6 +1,5 @@ -#include "precompiled.h" // -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2014 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,41 +8,52 @@ // objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105. #include "libGLESv2/Framebuffer.h" - #include "libGLESv2/main.h" -#include "common/utilities.h" #include "libGLESv2/formatutils.h" #include "libGLESv2/Texture.h" #include "libGLESv2/Context.h" -#include "libGLESv2/renderer/Renderer.h" #include "libGLESv2/Renderbuffer.h" +#include "libGLESv2/FramebufferAttachment.h" +#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/renderer/RenderTarget.h" + +#include "common/utilities.h" namespace gl { -Framebuffer::Framebuffer(rx::Renderer *renderer) - : mRenderer(renderer) +Framebuffer::Framebuffer(rx::Renderer *renderer, GLuint id) + : mRenderer(renderer), + mId(id), + mReadBufferState(GL_COLOR_ATTACHMENT0_EXT), + mDepthbuffer(NULL), + mStencilbuffer(NULL) { for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) { + mColorbuffers[colorAttachment] = NULL; mDrawBufferStates[colorAttachment] = GL_NONE; } mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT; - mReadBufferState = GL_COLOR_ATTACHMENT0_EXT; } Framebuffer::~Framebuffer() { for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) { - mColorbuffers[colorAttachment].set(NULL, GL_NONE, 0, 0); + SafeDelete(mColorbuffers[colorAttachment]); } - mDepthbuffer.set(NULL, GL_NONE, 0, 0); - mStencilbuffer.set(NULL, GL_NONE, 0, 0); + SafeDelete(mDepthbuffer); + SafeDelete(mStencilbuffer); } -Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle, GLint level, GLint layer) const +FramebufferAttachment *Framebuffer::createAttachment(GLenum type, GLuint handle, GLint level, GLint layer) const { + if (handle == 0) + { + return NULL; + } + gl::Context *context = gl::getContext(); switch (type) @@ -52,14 +62,15 @@ Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle, GLint return NULL; case GL_RENDERBUFFER: - return context->getRenderbuffer(handle); + return new RenderbufferAttachment(context->getRenderbuffer(handle)); case GL_TEXTURE_2D: { Texture *texture = context->getTexture(handle); if (texture && texture->getTarget() == GL_TEXTURE_2D) { - return static_cast(texture)->getRenderbuffer(level); + Texture2D *tex2D = static_cast(texture); + return new Texture2DAttachment(tex2D, level); } else { @@ -77,7 +88,8 @@ Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle, GLint Texture *texture = context->getTexture(handle); if (texture && texture->getTarget() == GL_TEXTURE_CUBE_MAP) { - return static_cast(texture)->getRenderbuffer(type, level); + TextureCubeMap *texCube = static_cast(texture); + return new TextureCubeMapAttachment(texCube, type, level); } else { @@ -90,7 +102,8 @@ Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle, GLint Texture *texture = context->getTexture(handle); if (texture && texture->getTarget() == GL_TEXTURE_3D) { - return static_cast(texture)->getRenderbuffer(level, layer); + Texture3D *tex3D = static_cast(texture); + return new Texture3DAttachment(tex3D, level, layer); } else { @@ -103,7 +116,8 @@ Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle, GLint Texture *texture = context->getTexture(handle); if (texture && texture->getTarget() == GL_TEXTURE_2D_ARRAY) { - return static_cast(texture)->getRenderbuffer(level, layer); + Texture2DArray *tex2DArray = static_cast(texture); + return new Texture2DArrayAttachment(tex2DArray, level, layer); } else { @@ -120,279 +134,165 @@ Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle, GLint void Framebuffer::setColorbuffer(unsigned int colorAttachment, GLenum type, GLuint colorbuffer, GLint level, GLint layer) { ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); - Renderbuffer *renderBuffer = lookupRenderbuffer(type, colorbuffer, level, layer); - if (renderBuffer) - { - mColorbuffers[colorAttachment].set(renderBuffer, type, level, layer); - } - else - { - mColorbuffers[colorAttachment].set(NULL, GL_NONE, 0, 0); - } + SafeDelete(mColorbuffers[colorAttachment]); + mColorbuffers[colorAttachment] = createAttachment(type, colorbuffer, level, layer); } void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer, GLint level, GLint layer) { - Renderbuffer *renderBuffer = lookupRenderbuffer(type, depthbuffer, level, layer); - if (renderBuffer) - { - mDepthbuffer.set(renderBuffer, type, level, layer); - } - else - { - mDepthbuffer.set(NULL, GL_NONE, 0, 0); - } + SafeDelete(mDepthbuffer); + mDepthbuffer = createAttachment(type, depthbuffer, level, layer); } void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer, GLint level, GLint layer) { - Renderbuffer *renderBuffer = lookupRenderbuffer(type, stencilbuffer, level, layer); - if (renderBuffer) - { - mStencilbuffer.set(renderBuffer, type, level, layer); - } - else - { - mStencilbuffer.set(NULL, GL_NONE, 0, 0); - } + SafeDelete(mStencilbuffer); + mStencilbuffer = createAttachment(type, stencilbuffer, level, layer); } void Framebuffer::setDepthStencilBuffer(GLenum type, GLuint depthStencilBuffer, GLint level, GLint layer) { - Renderbuffer *renderBuffer = lookupRenderbuffer(type, depthStencilBuffer, level, layer); - if (renderBuffer && renderBuffer->getDepthSize() > 0 && renderBuffer->getStencilSize() > 0) + FramebufferAttachment *attachment = createAttachment(type, depthStencilBuffer, level, layer); + + SafeDelete(mDepthbuffer); + SafeDelete(mStencilbuffer); + + // ensure this is a legitimate depth+stencil format + if (attachment && attachment->getDepthSize() > 0 && attachment->getStencilSize() > 0) { - mDepthbuffer.set(renderBuffer, type, level, layer); - mStencilbuffer.set(renderBuffer, type, level, layer); - } - else - { - mDepthbuffer.set(NULL, GL_NONE, 0, 0); - mStencilbuffer.set(NULL, GL_NONE, 0, 0); + mDepthbuffer = attachment; + + // Make a new attachment object to ensure we do not double-delete + // See angle issue 686 + mStencilbuffer = createAttachment(type, depthStencilBuffer, level, layer); } } -void Framebuffer::detachTexture(GLuint texture) +void Framebuffer::detachTexture(GLuint textureId) { for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) { - if (mColorbuffers[colorAttachment].id() == texture && - IsInternalTextureTarget(mColorbuffers[colorAttachment].type(), mRenderer->getCurrentClientVersion())) + FramebufferAttachment *attachment = mColorbuffers[colorAttachment]; + + if (attachment && attachment->isTextureWithId(textureId)) { - mColorbuffers[colorAttachment].set(NULL, GL_NONE, 0, 0); + SafeDelete(mColorbuffers[colorAttachment]); } } - if (mDepthbuffer.id() == texture && IsInternalTextureTarget(mDepthbuffer.type(), mRenderer->getCurrentClientVersion())) + if (mDepthbuffer && mDepthbuffer->isTextureWithId(textureId)) { - mDepthbuffer.set(NULL, GL_NONE, 0, 0); + SafeDelete(mDepthbuffer); } - if (mStencilbuffer.id() == texture && IsInternalTextureTarget(mStencilbuffer.type(), mRenderer->getCurrentClientVersion())) + if (mStencilbuffer && mStencilbuffer->isTextureWithId(textureId)) { - mStencilbuffer.set(NULL, GL_NONE, 0, 0); + SafeDelete(mStencilbuffer); } } -void Framebuffer::detachRenderbuffer(GLuint renderbuffer) +void Framebuffer::detachRenderbuffer(GLuint renderbufferId) { for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) { - if (mColorbuffers[colorAttachment].id() == renderbuffer && mColorbuffers[colorAttachment].type() == GL_RENDERBUFFER) + FramebufferAttachment *attachment = mColorbuffers[colorAttachment]; + + if (attachment && attachment->isRenderbufferWithId(renderbufferId)) { - mColorbuffers[colorAttachment].set(NULL, GL_NONE, 0, 0); + SafeDelete(mColorbuffers[colorAttachment]); } } - if (mDepthbuffer.id() == renderbuffer && mDepthbuffer.type() == GL_RENDERBUFFER) + if (mDepthbuffer && mDepthbuffer->isRenderbufferWithId(renderbufferId)) { - mDepthbuffer.set(NULL, GL_NONE, 0, 0); + SafeDelete(mDepthbuffer); } - if (mStencilbuffer.id() == renderbuffer && mStencilbuffer.type() == GL_RENDERBUFFER) + if (mStencilbuffer && mStencilbuffer->isRenderbufferWithId(renderbufferId)) { - mStencilbuffer.set(NULL, GL_NONE, 0, 0); + SafeDelete(mStencilbuffer); } } -unsigned int Framebuffer::getRenderTargetSerial(unsigned int colorAttachment) const +FramebufferAttachment *Framebuffer::getColorbuffer(unsigned int colorAttachment) const { ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); - - Renderbuffer *colorbuffer = mColorbuffers[colorAttachment].get(); - - if (colorbuffer) - { - return colorbuffer->getSerial(); - } - - return 0; + return mColorbuffers[colorAttachment]; } -unsigned int Framebuffer::getDepthbufferSerial() const +FramebufferAttachment *Framebuffer::getDepthbuffer() const { - Renderbuffer *depthbuffer = mDepthbuffer.get(); - - if (depthbuffer) - { - return depthbuffer->getSerial(); - } - - return 0; + return mDepthbuffer; } -unsigned int Framebuffer::getStencilbufferSerial() const +FramebufferAttachment *Framebuffer::getStencilbuffer() const { - Renderbuffer *stencilbuffer = mStencilbuffer.get(); - - if (stencilbuffer) - { - return stencilbuffer->getSerial(); - } - - return 0; + return mStencilbuffer; } -Renderbuffer *Framebuffer::getColorbuffer(unsigned int colorAttachment) const +FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const { - ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); - return mColorbuffers[colorAttachment].get(); + return (hasValidDepthStencil() ? mDepthbuffer : NULL); } -Renderbuffer *Framebuffer::getDepthbuffer() const +FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const { - return mDepthbuffer.get(); -} - -Renderbuffer *Framebuffer::getStencilbuffer() const -{ - return mStencilbuffer.get(); -} - -Renderbuffer *Framebuffer::getDepthStencilBuffer() const -{ - return (mDepthbuffer.id() == mStencilbuffer.id()) ? mDepthbuffer.get() : NULL; -} - -Renderbuffer *Framebuffer::getDepthOrStencilbuffer() const -{ - Renderbuffer *depthstencilbuffer = mDepthbuffer.get(); + FramebufferAttachment *depthstencilbuffer = mDepthbuffer; if (!depthstencilbuffer) { - depthstencilbuffer = mStencilbuffer.get(); + depthstencilbuffer = mStencilbuffer; } return depthstencilbuffer; } -Renderbuffer *Framebuffer::getReadColorbuffer() const +FramebufferAttachment *Framebuffer::getReadColorbuffer() const { // Will require more logic if glReadBuffers is supported - return mColorbuffers[0].get(); + return mColorbuffers[0]; } GLenum Framebuffer::getReadColorbufferType() const { // Will require more logic if glReadBuffers is supported - return mColorbuffers[0].type(); + return (mColorbuffers[0] ? mColorbuffers[0]->type() : GL_NONE); } -Renderbuffer *Framebuffer::getFirstColorbuffer() const +FramebufferAttachment *Framebuffer::getFirstColorbuffer() const { for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) { - if (mColorbuffers[colorAttachment].type() != GL_NONE) + if (mColorbuffers[colorAttachment]) { - return mColorbuffers[colorAttachment].get(); + return mColorbuffers[colorAttachment]; } } return NULL; } -GLenum Framebuffer::getColorbufferType(unsigned int colorAttachment) const +FramebufferAttachment *Framebuffer::getAttachment(GLenum attachment) const { - ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); - return mColorbuffers[colorAttachment].type(); -} - -GLenum Framebuffer::getDepthbufferType() const -{ - return mDepthbuffer.type(); -} - -GLenum Framebuffer::getStencilbufferType() const -{ - return mStencilbuffer.type(); -} - -GLenum Framebuffer::getDepthStencilbufferType() const -{ - return (mDepthbuffer.id() == mStencilbuffer.id()) ? mDepthbuffer.type() : GL_NONE; -} - -GLuint Framebuffer::getColorbufferHandle(unsigned int colorAttachment) const -{ - ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); - return mColorbuffers[colorAttachment].id(); -} - -GLuint Framebuffer::getDepthbufferHandle() const -{ - return mDepthbuffer.id(); -} - -GLuint Framebuffer::getStencilbufferHandle() const -{ - return mStencilbuffer.id(); -} - -GLenum Framebuffer::getDepthStencilbufferHandle() const -{ - return (mDepthbuffer.id() == mStencilbuffer.id()) ? mDepthbuffer.id() : 0; -} - -GLenum Framebuffer::getColorbufferMipLevel(unsigned int colorAttachment) const -{ - ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); - return mColorbuffers[colorAttachment].mipLevel(); -} - -GLenum Framebuffer::getDepthbufferMipLevel() const -{ - return mDepthbuffer.mipLevel(); -} - -GLenum Framebuffer::getStencilbufferMipLevel() const -{ - return mStencilbuffer.mipLevel(); -} - -GLenum Framebuffer::getDepthStencilbufferMipLevel() const -{ - return (mDepthbuffer.id() == mStencilbuffer.id()) ? mDepthbuffer.mipLevel() : 0; -} - -GLenum Framebuffer::getColorbufferLayer(unsigned int colorAttachment) const -{ - ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); - return mColorbuffers[colorAttachment].layer(); -} - -GLenum Framebuffer::getDepthbufferLayer() const -{ - return mDepthbuffer.layer(); -} - -GLenum Framebuffer::getStencilbufferLayer() const -{ - return mStencilbuffer.layer(); -} - -GLenum Framebuffer::getDepthStencilbufferLayer() const -{ - return (mDepthbuffer.id() == mStencilbuffer.id()) ? mDepthbuffer.layer() : 0; + if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15) + { + return getColorbuffer(attachment - GL_COLOR_ATTACHMENT0); + } + else + { + switch (attachment) + { + case GL_DEPTH_ATTACHMENT: + return getDepthbuffer(); + case GL_STENCIL_ATTACHMENT: + return getStencilbuffer(); + case GL_DEPTH_STENCIL_ATTACHMENT: + return getDepthStencilBuffer(); + default: + UNREACHABLE(); + return NULL; + } + } } GLenum Framebuffer::getDrawBufferState(unsigned int colorAttachment) const @@ -407,7 +307,7 @@ void Framebuffer::setDrawBufferState(unsigned int colorAttachment, GLenum drawBu bool Framebuffer::isEnabledColorAttachment(unsigned int colorAttachment) const { - return (mColorbuffers[colorAttachment].type() != GL_NONE && mDrawBufferStates[colorAttachment] != GL_NONE); + return (mColorbuffers[colorAttachment] && mDrawBufferStates[colorAttachment] != GL_NONE); } bool Framebuffer::hasEnabledColorAttachment() const @@ -425,17 +325,7 @@ bool Framebuffer::hasEnabledColorAttachment() const bool Framebuffer::hasStencil() const { - if (mStencilbuffer.type() != GL_NONE) - { - const Renderbuffer *stencilbufferObject = getStencilbuffer(); - - if (stencilbufferObject) - { - return stencilbufferObject->getStencilSize() > 0; - } - } - - return false; + return (mStencilbuffer && mStencilbuffer->getStencilSize() > 0); } bool Framebuffer::usingExtendedDrawBuffers() const @@ -462,46 +352,37 @@ GLenum Framebuffer::completeness() const for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) { - if (mColorbuffers[colorAttachment].type() != GL_NONE) + const FramebufferAttachment *colorbuffer = mColorbuffers[colorAttachment]; + + if (colorbuffer) { - const Renderbuffer *colorbuffer = getColorbuffer(colorAttachment); - - if (!colorbuffer) - { - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - } - if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } - if (mColorbuffers[colorAttachment].type() == GL_RENDERBUFFER) + GLenum internalformat = colorbuffer->getInternalFormat(); + // TODO(geofflang): use context's texture caps + const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat); + const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); + if (colorbuffer->isTexture()) { - if (!gl::IsColorRenderingSupported(colorbuffer->getInternalFormat(), mRenderer)) - { - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - } - } - else if (IsInternalTextureTarget(mColorbuffers[colorAttachment].type(), mRenderer->getCurrentClientVersion())) - { - GLenum internalformat = colorbuffer->getInternalFormat(); - - if (!gl::IsColorRenderingSupported(internalformat, mRenderer)) + if (!formatCaps.renderable) { return GL_FRAMEBUFFER_UNSUPPORTED; } - if (gl::GetDepthBits(internalformat, clientVersion) > 0 || - gl::GetStencilBits(internalformat, clientVersion) > 0) + if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } } else { - UNREACHABLE(); - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + if (!formatCaps.renderable || formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) + { + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + } } if (!missingAttachment) @@ -523,7 +404,7 @@ GLenum Framebuffer::completeness() const // in GLES 3.0, there is no such restriction if (clientVersion < 3) { - if (gl::GetPixelBytes(colorbuffer->getInternalFormat(), clientVersion) != colorbufferSize) + if (formatInfo.pixelBytes != colorbufferSize) { return GL_FRAMEBUFFER_UNSUPPORTED; } @@ -532,7 +413,11 @@ GLenum Framebuffer::completeness() const // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness for (unsigned int previousColorAttachment = 0; previousColorAttachment < colorAttachment; previousColorAttachment++) { - if (mColorbuffers[colorAttachment].get() == mColorbuffers[previousColorAttachment].get()) + const FramebufferAttachment *previousAttachment = mColorbuffers[previousColorAttachment]; + + if (previousAttachment && + (colorbuffer->id() == previousAttachment->id() && + colorbuffer->type() == previousAttachment->type())) { return GL_FRAMEBUFFER_UNSUPPORTED; } @@ -543,129 +428,118 @@ GLenum Framebuffer::completeness() const width = colorbuffer->getWidth(); height = colorbuffer->getHeight(); samples = colorbuffer->getSamples(); - colorbufferSize = gl::GetPixelBytes(colorbuffer->getInternalFormat(), clientVersion); + colorbufferSize = formatInfo.pixelBytes; missingAttachment = false; } } } - const Renderbuffer *depthbuffer = NULL; - const Renderbuffer *stencilbuffer = NULL; - - if (mDepthbuffer.type() != GL_NONE) + if (mDepthbuffer) { - depthbuffer = getDepthbuffer(); - - if (!depthbuffer) + if (mDepthbuffer->getWidth() == 0 || mDepthbuffer->getHeight() == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } - if (depthbuffer->getWidth() == 0 || depthbuffer->getHeight() == 0) + GLenum internalformat = mDepthbuffer->getInternalFormat(); + // TODO(geofflang): use context's texture caps + const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat); + const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); + if (mDepthbuffer->isTexture()) { - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - } - - if (mDepthbuffer.type() == GL_RENDERBUFFER) - { - if (!gl::IsDepthRenderingSupported(depthbuffer->getInternalFormat(), mRenderer)) - { - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - } - } - else if (IsInternalTextureTarget(mDepthbuffer.type(), mRenderer->getCurrentClientVersion())) - { - GLenum internalformat = depthbuffer->getInternalFormat(); - // depth texture attachments require OES/ANGLE_depth_texture - if (!mRenderer->getDepthTextureSupport()) + // TODO(geofflang): use context's extensions + if (!mRenderer->getRendererExtensions().depthTextures) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } - if (gl::GetDepthBits(internalformat, clientVersion) == 0) + if (!formatCaps.renderable) + { + return GL_FRAMEBUFFER_UNSUPPORTED; + } + + if (formatInfo.depthBits == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } } else { - UNREACHABLE(); - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + if (!formatCaps.renderable || formatInfo.depthBits == 0) + { + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + } } if (missingAttachment) { - width = depthbuffer->getWidth(); - height = depthbuffer->getHeight(); - samples = depthbuffer->getSamples(); + width = mDepthbuffer->getWidth(); + height = mDepthbuffer->getHeight(); + samples = mDepthbuffer->getSamples(); missingAttachment = false; } - else if (width != depthbuffer->getWidth() || height != depthbuffer->getHeight()) + else if (width != mDepthbuffer->getWidth() || height != mDepthbuffer->getHeight()) { return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; } - else if (samples != depthbuffer->getSamples()) + else if (samples != mDepthbuffer->getSamples()) { return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE; } } - if (mStencilbuffer.type() != GL_NONE) + if (mStencilbuffer) { - stencilbuffer = getStencilbuffer(); - - if (!stencilbuffer) + if (mStencilbuffer->getWidth() == 0 || mStencilbuffer->getHeight() == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } - if (stencilbuffer->getWidth() == 0 || stencilbuffer->getHeight() == 0) + GLenum internalformat = mStencilbuffer->getInternalFormat(); + // TODO(geofflang): use context's texture caps + const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat); + const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); + if (mStencilbuffer->isTexture()) { - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - } - - if (mStencilbuffer.type() == GL_RENDERBUFFER) - { - if (!gl::IsStencilRenderingSupported(stencilbuffer->getInternalFormat(), mRenderer)) - { - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - } - } - else if (IsInternalTextureTarget(mStencilbuffer.type(), mRenderer->getCurrentClientVersion())) - { - GLenum internalformat = stencilbuffer->getInternalFormat(); - // texture stencil attachments come along as part // of OES_packed_depth_stencil + OES/ANGLE_depth_texture - if (!mRenderer->getDepthTextureSupport()) + // TODO(geofflang): use context's extensions + if (!mRenderer->getRendererExtensions().depthTextures) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } - if (gl::GetStencilBits(internalformat, clientVersion) == 0) + if (!formatCaps.renderable) + { + return GL_FRAMEBUFFER_UNSUPPORTED; + } + + if (formatInfo.stencilBits == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } } else { - UNREACHABLE(); - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + if (!formatCaps.renderable || formatInfo.stencilBits == 0) + { + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + } } if (missingAttachment) { - width = stencilbuffer->getWidth(); - height = stencilbuffer->getHeight(); - samples = stencilbuffer->getSamples(); + width = mStencilbuffer->getWidth(); + height = mStencilbuffer->getHeight(); + samples = mStencilbuffer->getSamples(); missingAttachment = false; } - else if (width != stencilbuffer->getWidth() || height != stencilbuffer->getHeight()) + else if (width != mStencilbuffer->getWidth() || height != mStencilbuffer->getHeight()) { return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; } - else if (samples != stencilbuffer->getSamples()) + else if (samples != mStencilbuffer->getSamples()) { return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE; } @@ -673,7 +547,7 @@ GLenum Framebuffer::completeness() const // if we have both a depth and stencil buffer, they must refer to the same object // since we only support packed_depth_stencil and not separate depth and stencil - if (depthbuffer && stencilbuffer && (depthbuffer != stencilbuffer)) + if (mDepthbuffer && mStencilbuffer && !hasValidDepthStencil()) { return GL_FRAMEBUFFER_UNSUPPORTED; } @@ -687,14 +561,81 @@ GLenum Framebuffer::completeness() const return GL_FRAMEBUFFER_COMPLETE; } -DefaultFramebuffer::DefaultFramebuffer(rx::Renderer *renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil) - : Framebuffer(renderer) +void Framebuffer::invalidate(const Caps &caps, GLsizei numAttachments, const GLenum *attachments) { - mColorbuffers[0].set(new Renderbuffer(mRenderer, 0, colorbuffer), GL_RENDERBUFFER, 0, 0); + GLuint maxDimension = caps.maxRenderbufferSize; + invalidateSub(caps, numAttachments, attachments, 0, 0, maxDimension, maxDimension); +} - Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(mRenderer, 0, depthStencil); - mDepthbuffer.set(depthStencilRenderbuffer, (depthStencilRenderbuffer->getDepthSize() != 0) ? GL_RENDERBUFFER : GL_NONE, 0, 0); - mStencilbuffer.set(depthStencilRenderbuffer, (depthStencilRenderbuffer->getStencilSize() != 0) ? GL_RENDERBUFFER : GL_NONE, 0, 0); +void Framebuffer::invalidateSub(const Caps &caps, GLsizei numAttachments, const GLenum *attachments, + GLint x, GLint y, GLsizei width, GLsizei height) +{ + ASSERT(completeness() == GL_FRAMEBUFFER_COMPLETE); + for (int i = 0; i < numAttachments; ++i) + { + rx::RenderTarget *renderTarget = NULL; + + if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT15) + { + gl::FramebufferAttachment *attachment = getColorbuffer(attachments[i] - GL_COLOR_ATTACHMENT0); + if (attachment) + { + renderTarget = attachment->getRenderTarget(); + } + } + else if (attachments[i] == GL_COLOR) + { + gl::FramebufferAttachment *attachment = getColorbuffer(0); + if (attachment) + { + renderTarget = attachment->getRenderTarget(); + } + } + else + { + gl::FramebufferAttachment *attachment = NULL; + switch (attachments[i]) + { + case GL_DEPTH_ATTACHMENT: + case GL_DEPTH: + attachment = mDepthbuffer; + break; + case GL_STENCIL_ATTACHMENT: + case GL_STENCIL: + attachment = mStencilbuffer; + break; + case GL_DEPTH_STENCIL_ATTACHMENT: + attachment = getDepthOrStencilbuffer(); + break; + default: + UNREACHABLE(); + } + + if (attachment) + { + renderTarget = attachment->getRenderTarget(); + } + } + + if (renderTarget) + { + renderTarget->invalidate(x, y, width, height); + } + } +} + +DefaultFramebuffer::DefaultFramebuffer(rx::Renderer *renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil) + : Framebuffer(renderer, 0) +{ + Renderbuffer *colorRenderbuffer = new Renderbuffer(0, colorbuffer); + mColorbuffers[0] = new RenderbufferAttachment(colorRenderbuffer); + + Renderbuffer *depthStencilBuffer = new Renderbuffer(0, depthStencil); + + // Make a new attachment objects to ensure we do not double-delete + // See angle issue 686 + mDepthbuffer = (depthStencilBuffer->getDepthSize() != 0 ? new RenderbufferAttachment(depthStencilBuffer) : NULL); + mStencilbuffer = (depthStencilBuffer->getStencilSize() != 0 ? new RenderbufferAttachment(depthStencilBuffer) : NULL); mDrawBufferStates[0] = GL_BACK; mReadBufferState = GL_BACK; @@ -708,9 +649,9 @@ int Framebuffer::getSamples() const // in this case return the first nonzero sample size for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) { - if (mColorbuffers[colorAttachment].type() != GL_NONE) + if (mColorbuffers[colorAttachment]) { - return getColorbuffer(colorAttachment)->getSamples(); + return mColorbuffers[colorAttachment]->getSamples(); } } } @@ -718,6 +659,15 @@ int Framebuffer::getSamples() const return 0; } +bool Framebuffer::hasValidDepthStencil() const +{ + // A valid depth-stencil attachment has the same resource bound to both the + // depth and stencil attachment points. + return (mDepthbuffer && mStencilbuffer && + mDepthbuffer->type() == mStencilbuffer->type() && + mDepthbuffer->id() == mStencilbuffer->id()); +} + GLenum DefaultFramebuffer::completeness() const { // The default framebuffer *must* always be complete, though it may not be @@ -725,4 +675,22 @@ GLenum DefaultFramebuffer::completeness() const return GL_FRAMEBUFFER_COMPLETE; } +FramebufferAttachment *DefaultFramebuffer::getAttachment(GLenum attachment) const +{ + switch (attachment) + { + case GL_BACK: + return getColorbuffer(0); + case GL_DEPTH: + return getDepthbuffer(); + case GL_STENCIL: + return getStencilbuffer(); + case GL_DEPTH_STENCIL: + return getDepthStencilBuffer(); + default: + UNREACHABLE(); + return NULL; + } +} + } diff --git a/gfx/angle/src/libGLESv2/Framebuffer.h b/gfx/angle/src/libGLESv2/Framebuffer.h index c0d8ee882d7b..de84fbfe5a84 100644 --- a/gfx/angle/src/libGLESv2/Framebuffer.h +++ b/gfx/angle/src/libGLESv2/Framebuffer.h @@ -21,19 +21,22 @@ class Renderer; namespace gl { -class Renderbuffer; +class FramebufferAttachment; class Colorbuffer; class Depthbuffer; class Stencilbuffer; class DepthStencilbuffer; +struct Caps; class Framebuffer { public: - explicit Framebuffer(rx::Renderer *renderer); + Framebuffer(rx::Renderer *renderer, GLuint id); virtual ~Framebuffer(); + GLuint id() const { return mId; } + void setColorbuffer(unsigned int colorAttachment, GLenum type, GLuint colorbuffer, GLint level, GLint layer); void setDepthbuffer(GLenum type, GLuint depthbuffer, GLint level, GLint layer); void setStencilbuffer(GLenum type, GLuint stencilbuffer, GLint level, GLint layer); @@ -42,38 +45,16 @@ class Framebuffer void detachTexture(GLuint texture); void detachRenderbuffer(GLuint renderbuffer); - unsigned int getRenderTargetSerial(unsigned int colorAttachment) const; - unsigned int getDepthbufferSerial() const; - unsigned int getStencilbufferSerial() const; - - Renderbuffer *getColorbuffer(unsigned int colorAttachment) const; - Renderbuffer *getDepthbuffer() const; - Renderbuffer *getStencilbuffer() const; - Renderbuffer *getDepthStencilBuffer() const; - Renderbuffer *getDepthOrStencilbuffer() const; - Renderbuffer *getReadColorbuffer() const; + FramebufferAttachment *getColorbuffer(unsigned int colorAttachment) const; + FramebufferAttachment *getDepthbuffer() const; + FramebufferAttachment *getStencilbuffer() const; + FramebufferAttachment *getDepthStencilBuffer() const; + FramebufferAttachment *getDepthOrStencilbuffer() const; + FramebufferAttachment *getReadColorbuffer() const; GLenum getReadColorbufferType() const; - Renderbuffer *getFirstColorbuffer() const; + FramebufferAttachment *getFirstColorbuffer() const; - GLenum getColorbufferType(unsigned int colorAttachment) const; - GLenum getDepthbufferType() const; - GLenum getStencilbufferType() const; - GLenum getDepthStencilbufferType() const; - - GLuint getColorbufferHandle(unsigned int colorAttachment) const; - GLuint getDepthbufferHandle() const; - GLuint getStencilbufferHandle() const; - GLenum getDepthStencilbufferHandle() const; - - GLenum getColorbufferMipLevel(unsigned int colorAttachment) const; - GLenum getDepthbufferMipLevel() const; - GLenum getStencilbufferMipLevel() const; - GLenum getDepthStencilbufferMipLevel() const; - - GLenum getColorbufferLayer(unsigned int colorAttachment) const; - GLenum getDepthbufferLayer() const; - GLenum getStencilbufferLayer() const; - GLenum getDepthStencilbufferLayer() const; + virtual FramebufferAttachment *getAttachment(GLenum attachment) const; GLenum getDrawBufferState(unsigned int colorAttachment) const; void setDrawBufferState(unsigned int colorAttachment, GLenum drawBuffer); @@ -85,21 +66,28 @@ class Framebuffer bool usingExtendedDrawBuffers() const; virtual GLenum completeness() const; + bool hasValidDepthStencil() const; + + void invalidate(const Caps &caps, GLsizei numAttachments, const GLenum *attachments); + void invalidateSub(const Caps &caps, GLsizei numAttachments, const GLenum *attachments, + GLint x, GLint y, GLsizei width, GLsizei height); protected: - FramebufferTextureBindingPointer mColorbuffers[IMPLEMENTATION_MAX_DRAW_BUFFERS]; + rx::Renderer *mRenderer; + + GLuint mId; + + FramebufferAttachment *mColorbuffers[IMPLEMENTATION_MAX_DRAW_BUFFERS]; GLenum mDrawBufferStates[IMPLEMENTATION_MAX_DRAW_BUFFERS]; GLenum mReadBufferState; - FramebufferTextureBindingPointer mDepthbuffer; - FramebufferTextureBindingPointer mStencilbuffer; + FramebufferAttachment *mDepthbuffer; + FramebufferAttachment *mStencilbuffer; - rx::Renderer *mRenderer; - - private: +private: DISALLOW_COPY_AND_ASSIGN(Framebuffer); - Renderbuffer *lookupRenderbuffer(GLenum type, GLuint handle, GLint level, GLint layer) const; + FramebufferAttachment *createAttachment(GLenum type, GLuint handle, GLint level, GLint layer) const; }; class DefaultFramebuffer : public Framebuffer @@ -108,6 +96,7 @@ class DefaultFramebuffer : public Framebuffer DefaultFramebuffer(rx::Renderer *Renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil); virtual GLenum completeness() const; + virtual FramebufferAttachment *getAttachment(GLenum attachment) const; private: DISALLOW_COPY_AND_ASSIGN(DefaultFramebuffer); diff --git a/gfx/angle/src/libGLESv2/FramebufferAttachment.cpp b/gfx/angle/src/libGLESv2/FramebufferAttachment.cpp new file mode 100644 index 000000000000..0cabf39ec8d5 --- /dev/null +++ b/gfx/angle/src/libGLESv2/FramebufferAttachment.cpp @@ -0,0 +1,469 @@ +// +// Copyright (c) 2014 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. +// + +// FramebufferAttachment.cpp: the gl::FramebufferAttachment class and its derived classes +// objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108. + +#include "libGLESv2/FramebufferAttachment.h" +#include "libGLESv2/Texture.h" +#include "libGLESv2/formatutils.h" +#include "libGLESv2/Renderbuffer.h" +#include "libGLESv2/renderer/RenderTarget.h" +#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/renderer/d3d/TextureStorage.h" + +#include "common/utilities.h" + +namespace gl +{ + +////// FramebufferAttachment Implementation ////// + +FramebufferAttachment::FramebufferAttachment() +{ +} + +FramebufferAttachment::~FramebufferAttachment() +{ +} + +GLuint FramebufferAttachment::getRedSize() const +{ + return (GetInternalFormatInfo(getInternalFormat()).redBits > 0) ? GetInternalFormatInfo(getActualFormat()).redBits : 0; +} + +GLuint FramebufferAttachment::getGreenSize() const +{ + return (GetInternalFormatInfo(getInternalFormat()).greenBits > 0) ? GetInternalFormatInfo(getActualFormat()).greenBits : 0; +} + +GLuint FramebufferAttachment::getBlueSize() const +{ + return (GetInternalFormatInfo(getInternalFormat()).blueBits > 0) ? GetInternalFormatInfo(getActualFormat()).blueBits : 0; +} + +GLuint FramebufferAttachment::getAlphaSize() const +{ + return (GetInternalFormatInfo(getInternalFormat()).alphaBits > 0) ? GetInternalFormatInfo(getActualFormat()).alphaBits : 0; +} + +GLuint FramebufferAttachment::getDepthSize() const +{ + return (GetInternalFormatInfo(getInternalFormat()).depthBits > 0) ? GetInternalFormatInfo(getActualFormat()).depthBits : 0; +} + +GLuint FramebufferAttachment::getStencilSize() const +{ + return (GetInternalFormatInfo(getInternalFormat()).stencilBits > 0) ? GetInternalFormatInfo(getActualFormat()).stencilBits : 0; +} + +GLenum FramebufferAttachment::getComponentType() const +{ + return GetInternalFormatInfo(getActualFormat()).componentType; +} + +GLenum FramebufferAttachment::getColorEncoding() const +{ + return GetInternalFormatInfo(getActualFormat()).colorEncoding; +} + +bool FramebufferAttachment::isTexture() const +{ + return (type() != GL_RENDERBUFFER); +} + +///// Texture2DAttachment Implementation //////// + +Texture2DAttachment::Texture2DAttachment(Texture2D *texture, GLint level) : mLevel(level) +{ + mTexture2D.set(texture); +} + +Texture2DAttachment::~Texture2DAttachment() +{ + mTexture2D.set(NULL); +} + +rx::RenderTarget *Texture2DAttachment::getRenderTarget() +{ + return mTexture2D->getRenderTarget(mLevel); +} + +rx::TextureStorage *Texture2DAttachment::getTextureStorage() +{ + return mTexture2D->getNativeTexture()->getStorageInstance(); +} + +GLsizei Texture2DAttachment::getWidth() const +{ + return mTexture2D->getWidth(mLevel); +} + +GLsizei Texture2DAttachment::getHeight() const +{ + return mTexture2D->getHeight(mLevel); +} + +GLenum Texture2DAttachment::getInternalFormat() const +{ + return mTexture2D->getInternalFormat(mLevel); +} + +GLenum Texture2DAttachment::getActualFormat() const +{ + return mTexture2D->getActualFormat(mLevel); +} + +GLsizei Texture2DAttachment::getSamples() const +{ + return 0; +} + +unsigned int Texture2DAttachment::getSerial() const +{ + return mTexture2D->getRenderTargetSerial(mLevel); +} + +GLuint Texture2DAttachment::id() const +{ + return mTexture2D->id(); +} + +GLenum Texture2DAttachment::type() const +{ + return GL_TEXTURE_2D; +} + +GLint Texture2DAttachment::mipLevel() const +{ + return mLevel; +} + +GLint Texture2DAttachment::layer() const +{ + return 0; +} + +unsigned int Texture2DAttachment::getTextureSerial() const +{ + return mTexture2D->getTextureSerial(); +} + +///// TextureCubeMapAttachment Implementation //////// + +TextureCubeMapAttachment::TextureCubeMapAttachment(TextureCubeMap *texture, GLenum faceTarget, GLint level) + : mFaceTarget(faceTarget), mLevel(level) +{ + mTextureCubeMap.set(texture); +} + +TextureCubeMapAttachment::~TextureCubeMapAttachment() +{ + mTextureCubeMap.set(NULL); +} + +rx::RenderTarget *TextureCubeMapAttachment::getRenderTarget() +{ + return mTextureCubeMap->getRenderTarget(mFaceTarget, mLevel); +} + +rx::TextureStorage *TextureCubeMapAttachment::getTextureStorage() +{ + return mTextureCubeMap->getNativeTexture()->getStorageInstance(); +} + +GLsizei TextureCubeMapAttachment::getWidth() const +{ + return mTextureCubeMap->getWidth(mFaceTarget, mLevel); +} + +GLsizei TextureCubeMapAttachment::getHeight() const +{ + return mTextureCubeMap->getHeight(mFaceTarget, mLevel); +} + +GLenum TextureCubeMapAttachment::getInternalFormat() const +{ + return mTextureCubeMap->getInternalFormat(mFaceTarget, mLevel); +} + +GLenum TextureCubeMapAttachment::getActualFormat() const +{ + return mTextureCubeMap->getActualFormat(mFaceTarget, mLevel); +} + +GLsizei TextureCubeMapAttachment::getSamples() const +{ + return 0; +} + +unsigned int TextureCubeMapAttachment::getSerial() const +{ + return mTextureCubeMap->getRenderTargetSerial(mFaceTarget, mLevel); +} + +GLuint TextureCubeMapAttachment::id() const +{ + return mTextureCubeMap->id(); +} + +GLenum TextureCubeMapAttachment::type() const +{ + return mFaceTarget; +} + +GLint TextureCubeMapAttachment::mipLevel() const +{ + return mLevel; +} + +GLint TextureCubeMapAttachment::layer() const +{ + return 0; +} + +unsigned int TextureCubeMapAttachment::getTextureSerial() const +{ + return mTextureCubeMap->getTextureSerial(); +} + +///// Texture3DAttachment Implementation //////// + +Texture3DAttachment::Texture3DAttachment(Texture3D *texture, GLint level, GLint layer) + : mLevel(level), mLayer(layer) +{ + mTexture3D.set(texture); +} + +Texture3DAttachment::~Texture3DAttachment() +{ + mTexture3D.set(NULL); +} + +rx::RenderTarget *Texture3DAttachment::getRenderTarget() +{ + return mTexture3D->getRenderTarget(mLevel, mLayer); +} + +rx::TextureStorage *Texture3DAttachment::getTextureStorage() +{ + return mTexture3D->getNativeTexture()->getStorageInstance(); +} + +GLsizei Texture3DAttachment::getWidth() const +{ + return mTexture3D->getWidth(mLevel); +} + +GLsizei Texture3DAttachment::getHeight() const +{ + return mTexture3D->getHeight(mLevel); +} + +GLenum Texture3DAttachment::getInternalFormat() const +{ + return mTexture3D->getInternalFormat(mLevel); +} + +GLenum Texture3DAttachment::getActualFormat() const +{ + return mTexture3D->getActualFormat(mLevel); +} + +GLsizei Texture3DAttachment::getSamples() const +{ + return 0; +} + +unsigned int Texture3DAttachment::getSerial() const +{ + return mTexture3D->getRenderTargetSerial(mLevel, mLayer); +} + +GLuint Texture3DAttachment::id() const +{ + return mTexture3D->id(); +} + +GLenum Texture3DAttachment::type() const +{ + return GL_TEXTURE_3D; +} + +GLint Texture3DAttachment::mipLevel() const +{ + return mLevel; +} + +GLint Texture3DAttachment::layer() const +{ + return mLayer; +} + +unsigned int Texture3DAttachment::getTextureSerial() const +{ + return mTexture3D->getTextureSerial(); +} + +////// Texture2DArrayAttachment Implementation ////// + +Texture2DArrayAttachment::Texture2DArrayAttachment(Texture2DArray *texture, GLint level, GLint layer) + : mLevel(level), mLayer(layer) +{ + mTexture2DArray.set(texture); +} + +Texture2DArrayAttachment::~Texture2DArrayAttachment() +{ + mTexture2DArray.set(NULL); +} + +rx::RenderTarget *Texture2DArrayAttachment::getRenderTarget() +{ + return mTexture2DArray->getRenderTarget(mLevel, mLayer); +} + +rx::TextureStorage *Texture2DArrayAttachment::getTextureStorage() +{ + return mTexture2DArray->getNativeTexture()->getStorageInstance(); +} + +GLsizei Texture2DArrayAttachment::getWidth() const +{ + return mTexture2DArray->getWidth(mLevel); +} + +GLsizei Texture2DArrayAttachment::getHeight() const +{ + return mTexture2DArray->getHeight(mLevel); +} + +GLenum Texture2DArrayAttachment::getInternalFormat() const +{ + return mTexture2DArray->getInternalFormat(mLevel); +} + +GLenum Texture2DArrayAttachment::getActualFormat() const +{ + return mTexture2DArray->getActualFormat(mLevel); +} + +GLsizei Texture2DArrayAttachment::getSamples() const +{ + return 0; +} + +unsigned int Texture2DArrayAttachment::getSerial() const +{ + return mTexture2DArray->getRenderTargetSerial(mLevel, mLayer); +} + +GLuint Texture2DArrayAttachment::id() const +{ + return mTexture2DArray->id(); +} + +GLenum Texture2DArrayAttachment::type() const +{ + return GL_TEXTURE_2D_ARRAY; +} + +GLint Texture2DArrayAttachment::mipLevel() const +{ + return mLevel; +} + +GLint Texture2DArrayAttachment::layer() const +{ + return mLayer; +} + +unsigned int Texture2DArrayAttachment::getTextureSerial() const +{ + return mTexture2DArray->getTextureSerial(); +} + +////// RenderbufferAttachment Implementation ////// + +RenderbufferAttachment::RenderbufferAttachment(Renderbuffer *renderbuffer) +{ + ASSERT(renderbuffer); + mRenderbuffer.set(renderbuffer); +} + +RenderbufferAttachment::~RenderbufferAttachment() +{ + mRenderbuffer.set(NULL); +} + +rx::RenderTarget *RenderbufferAttachment::getRenderTarget() +{ + return mRenderbuffer->getStorage()->getRenderTarget(); +} + +rx::TextureStorage *RenderbufferAttachment::getTextureStorage() +{ + UNREACHABLE(); + return NULL; +} + +GLsizei RenderbufferAttachment::getWidth() const +{ + return mRenderbuffer->getWidth(); +} + +GLsizei RenderbufferAttachment::getHeight() const +{ + return mRenderbuffer->getHeight(); +} + +GLenum RenderbufferAttachment::getInternalFormat() const +{ + return mRenderbuffer->getInternalFormat(); +} + +GLenum RenderbufferAttachment::getActualFormat() const +{ + return mRenderbuffer->getActualFormat(); +} + +GLsizei RenderbufferAttachment::getSamples() const +{ + return mRenderbuffer->getStorage()->getSamples(); +} + +unsigned int RenderbufferAttachment::getSerial() const +{ + return mRenderbuffer->getStorage()->getSerial(); +} + +GLuint RenderbufferAttachment::id() const +{ + return mRenderbuffer->id(); +} + +GLenum RenderbufferAttachment::type() const +{ + return GL_RENDERBUFFER; +} + +GLint RenderbufferAttachment::mipLevel() const +{ + return 0; +} + +GLint RenderbufferAttachment::layer() const +{ + return 0; +} + +unsigned int RenderbufferAttachment::getTextureSerial() const +{ + UNREACHABLE(); + return 0; +} + +} diff --git a/gfx/angle/src/libGLESv2/FramebufferAttachment.h b/gfx/angle/src/libGLESv2/FramebufferAttachment.h new file mode 100644 index 000000000000..f12b55edceee --- /dev/null +++ b/gfx/angle/src/libGLESv2/FramebufferAttachment.h @@ -0,0 +1,240 @@ +// +// Copyright (c) 2014 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. +// + +// FramebufferAttachment.h: Defines the wrapper class gl::FramebufferAttachment, as well as the +// objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108. + +#ifndef LIBGLESV2_FRAMEBUFFERATTACHMENT_H_ +#define LIBGLESV2_FRAMEBUFFERATTACHMENT_H_ + +#include "common/angleutils.h" +#include "common/RefCountObject.h" + +#include "angle_gl.h" + +namespace rx +{ +class Renderer; +class RenderTarget; +class TextureStorage; +} + +namespace gl +{ +class Texture2D; +class TextureCubeMap; +class Texture3D; +class Texture2DArray; +class Renderbuffer; + +// FramebufferAttachment implements a GL framebuffer attachment. +// Attachments are "light" containers, which store pointers to ref-counted GL objects. +// We support GL texture (2D/3D/Cube/2D array) and renderbuffer object attachments. +// Note: Our old naming scheme used the term "Renderbuffer" for both GL renderbuffers and for +// framebuffer attachments, which confused their usage. + +class FramebufferAttachment +{ + public: + FramebufferAttachment(); + virtual ~FramebufferAttachment(); + + // Helper methods + GLuint getRedSize() const; + GLuint getGreenSize() const; + GLuint getBlueSize() const; + GLuint getAlphaSize() const; + GLuint getDepthSize() const; + GLuint getStencilSize() const; + GLenum getComponentType() const; + GLenum getColorEncoding() const; + bool isTexture() const; + + bool isTextureWithId(GLuint textureId) const { return isTexture() && id() == textureId; } + bool isRenderbufferWithId(GLuint renderbufferId) const { return !isTexture() && id() == renderbufferId; } + + // Child class interface + virtual rx::RenderTarget *getRenderTarget() = 0; + virtual rx::TextureStorage *getTextureStorage() = 0; + + virtual GLsizei getWidth() const = 0; + virtual GLsizei getHeight() const = 0; + virtual GLenum getInternalFormat() const = 0; + virtual GLenum getActualFormat() const = 0; + virtual GLsizei getSamples() const = 0; + + virtual unsigned int getSerial() const = 0; + + virtual GLuint id() const = 0; + virtual GLenum type() const = 0; + virtual GLint mipLevel() const = 0; + virtual GLint layer() const = 0; + virtual unsigned int getTextureSerial() const = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(FramebufferAttachment); +}; + +class Texture2DAttachment : public FramebufferAttachment +{ + public: + Texture2DAttachment(Texture2D *texture, GLint level); + + virtual ~Texture2DAttachment(); + + rx::RenderTarget *getRenderTarget(); + rx::TextureStorage *getTextureStorage(); + + virtual GLsizei getWidth() const; + virtual GLsizei getHeight() const; + virtual GLenum getInternalFormat() const; + virtual GLenum getActualFormat() const; + virtual GLsizei getSamples() const; + + virtual unsigned int getSerial() const; + + virtual GLuint id() const; + virtual GLenum type() const; + virtual GLint mipLevel() const; + virtual GLint layer() const; + virtual unsigned int getTextureSerial() const; + + private: + DISALLOW_COPY_AND_ASSIGN(Texture2DAttachment); + + BindingPointer mTexture2D; + const GLint mLevel; +}; + +class TextureCubeMapAttachment : public FramebufferAttachment +{ + public: + TextureCubeMapAttachment(TextureCubeMap *texture, GLenum faceTarget, GLint level); + + virtual ~TextureCubeMapAttachment(); + + rx::RenderTarget *getRenderTarget(); + rx::TextureStorage *getTextureStorage(); + + virtual GLsizei getWidth() const; + virtual GLsizei getHeight() const; + virtual GLenum getInternalFormat() const; + virtual GLenum getActualFormat() const; + virtual GLsizei getSamples() const; + + virtual unsigned int getSerial() const; + + virtual GLuint id() const; + virtual GLenum type() const; + virtual GLint mipLevel() const; + virtual GLint layer() const; + virtual unsigned int getTextureSerial() const; + + private: + DISALLOW_COPY_AND_ASSIGN(TextureCubeMapAttachment); + + BindingPointer mTextureCubeMap; + const GLint mLevel; + const GLenum mFaceTarget; +}; + +class Texture3DAttachment : public FramebufferAttachment +{ + public: + Texture3DAttachment(Texture3D *texture, GLint level, GLint layer); + + virtual ~Texture3DAttachment(); + + rx::RenderTarget *getRenderTarget(); + rx::TextureStorage *getTextureStorage(); + + virtual GLsizei getWidth() const; + virtual GLsizei getHeight() const; + virtual GLenum getInternalFormat() const; + virtual GLenum getActualFormat() const; + virtual GLsizei getSamples() const; + + virtual unsigned int getSerial() const; + + virtual GLuint id() const; + virtual GLenum type() const; + virtual GLint mipLevel() const; + virtual GLint layer() const; + virtual unsigned int getTextureSerial() const; + + private: + DISALLOW_COPY_AND_ASSIGN(Texture3DAttachment); + + BindingPointer mTexture3D; + const GLint mLevel; + const GLint mLayer; +}; + +class Texture2DArrayAttachment : public FramebufferAttachment +{ + public: + Texture2DArrayAttachment(Texture2DArray *texture, GLint level, GLint layer); + + virtual ~Texture2DArrayAttachment(); + + rx::RenderTarget *getRenderTarget(); + rx::TextureStorage *getTextureStorage(); + + virtual GLsizei getWidth() const; + virtual GLsizei getHeight() const; + virtual GLenum getInternalFormat() const; + virtual GLenum getActualFormat() const; + virtual GLsizei getSamples() const; + + virtual unsigned int getSerial() const; + + virtual GLuint id() const; + virtual GLenum type() const; + virtual GLint mipLevel() const; + virtual GLint layer() const; + virtual unsigned int getTextureSerial() const; + + private: + DISALLOW_COPY_AND_ASSIGN(Texture2DArrayAttachment); + + BindingPointer mTexture2DArray; + const GLint mLevel; + const GLint mLayer; +}; + +class RenderbufferAttachment : public FramebufferAttachment +{ + public: + RenderbufferAttachment(Renderbuffer *renderbuffer); + + virtual ~RenderbufferAttachment(); + + rx::RenderTarget *getRenderTarget(); + rx::TextureStorage *getTextureStorage(); + + virtual GLsizei getWidth() const; + virtual GLsizei getHeight() const; + virtual GLenum getInternalFormat() const; + virtual GLenum getActualFormat() const; + virtual GLsizei getSamples() const; + + virtual unsigned int getSerial() const; + + virtual GLuint id() const; + virtual GLenum type() const; + virtual GLint mipLevel() const; + virtual GLint layer() const; + virtual unsigned int getTextureSerial() const; + + private: + DISALLOW_COPY_AND_ASSIGN(RenderbufferAttachment); + + BindingPointer mRenderbuffer; +}; + +} + +#endif // LIBGLESV2_FRAMEBUFFERATTACHMENT_H_ diff --git a/gfx/angle/src/libGLESv2/HandleAllocator.cpp b/gfx/angle/src/libGLESv2/HandleAllocator.cpp index 37da99aa1828..c498f8a17809 100644 --- a/gfx/angle/src/libGLESv2/HandleAllocator.cpp +++ b/gfx/angle/src/libGLESv2/HandleAllocator.cpp @@ -1,4 +1,3 @@ -#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/HandleAllocator.h b/gfx/angle/src/libGLESv2/HandleAllocator.h index e23010d918b5..a89cc8677573 100644 --- a/gfx/angle/src/libGLESv2/HandleAllocator.h +++ b/gfx/angle/src/libGLESv2/HandleAllocator.h @@ -10,13 +10,12 @@ #ifndef LIBGLESV2_HANDLEALLOCATOR_H_ #define LIBGLESV2_HANDLEALLOCATOR_H_ -#include -#include +#include "common/angleutils.h" + +#include "angle_gl.h" #include -#include "common/angleutils.h" - namespace gl { diff --git a/gfx/angle/src/libGLESv2/Program.cpp b/gfx/angle/src/libGLESv2/Program.cpp index 8a9fb048007a..bd9b38b2ded1 100644 --- a/gfx/angle/src/libGLESv2/Program.cpp +++ b/gfx/angle/src/libGLESv2/Program.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -173,7 +172,7 @@ bool Program::attachShader(Shader *shader) return false; } - mVertexShader = (VertexShader*)shader; + mVertexShader = shader; mVertexShader->addRef(); } else if (shader->getType() == GL_FRAGMENT_SHADER) @@ -183,7 +182,7 @@ bool Program::attachShader(Shader *shader) return false; } - mFragmentShader = (FragmentShader*)shader; + mFragmentShader = shader; mFragmentShader->addRef(); } else UNREACHABLE(); @@ -244,7 +243,7 @@ void Program::bindAttributeLocation(GLuint index, const char *name) // Links the HLSL code of the vertex and pixel shader by matching up their varyings, // compiling them into binaries, determining the attribute mappings, and collecting // a list of uniforms -bool Program::link() +bool Program::link(const Caps &caps) { unlink(false); @@ -253,7 +252,7 @@ bool Program::link() mProgramBinary.set(new ProgramBinary(mRenderer)); mLinked = mProgramBinary->link(mInfoLog, mAttributeBindings, mFragmentShader, mVertexShader, - mTransformFeedbackVaryings, mTransformFeedbackBufferMode); + mTransformFeedbackVaryings, mTransformFeedbackBufferMode, caps); return mLinked; } @@ -303,14 +302,14 @@ ProgramBinary* Program::getProgramBinary() const return mProgramBinary.get(); } -bool Program::setProgramBinary(const void *binary, GLsizei length) +bool Program::setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length) { unlink(false); mInfoLog.reset(); mProgramBinary.set(new ProgramBinary(mRenderer)); - mLinked = mProgramBinary->load(mInfoLog, binary, length); + mLinked = mProgramBinary->load(mInfoLog, binaryFormat, binary, length); if (!mLinked) { mProgramBinary.set(NULL); @@ -502,14 +501,14 @@ bool Program::isFlaggedForDeletion() const return mDeleteStatus; } -void Program::validate() +void Program::validate(const Caps &caps) { mInfoLog.reset(); ProgramBinary *programBinary = getProgramBinary(); if (isLinked() && programBinary) { - programBinary->validate(mInfoLog); + programBinary->validate(mInfoLog, caps); } else { diff --git a/gfx/angle/src/libGLESv2/Program.h b/gfx/angle/src/libGLESv2/Program.h index 7576be43c0f8..6528dd119146 100644 --- a/gfx/angle/src/libGLESv2/Program.h +++ b/gfx/angle/src/libGLESv2/Program.h @@ -10,12 +10,16 @@ #ifndef LIBGLESV2_PROGRAM_H_ #define LIBGLESV2_PROGRAM_H_ -#include -#include - #include "common/angleutils.h" #include "common/RefCountObject.h" #include "libGLESv2/Constants.h" +#include "libGLESv2/ProgramBinary.h" + +#include + +#include +#include +#include namespace rx { @@ -24,10 +28,8 @@ class Renderer; namespace gl { +struct Caps; class ResourceManager; -class FragmentShader; -class VertexShader; -class ProgramBinary; class Shader; extern const char * const g_fakepath; @@ -75,9 +77,9 @@ class Program void bindAttributeLocation(GLuint index, const char *name); - bool link(); + bool link(const Caps &caps); bool isLinked(); - bool setProgramBinary(const void *binary, GLsizei length); + bool setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length); ProgramBinary *getProgramBinary() const; int getInfoLogLength() const; @@ -110,7 +112,7 @@ class Program void flagForDeletion(); bool isFlaggedForDeletion() const; - void validate(); + void validate(const Caps &caps); bool isValidated() const; GLint getProgramBinaryLength() const; @@ -121,8 +123,8 @@ class Program void unlink(bool destroy = false); void resetUniformBlockBindings(); - FragmentShader *mFragmentShader; - VertexShader *mVertexShader; + Shader *mFragmentShader; + Shader *mVertexShader; AttributeBindings mAttributeBindings; diff --git a/gfx/angle/src/libGLESv2/ProgramBinary.cpp b/gfx/angle/src/libGLESv2/ProgramBinary.cpp index b25b457dc178..232e0ad42a91 100644 --- a/gfx/angle/src/libGLESv2/ProgramBinary.cpp +++ b/gfx/angle/src/libGLESv2/ProgramBinary.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -10,31 +9,62 @@ #include "libGLESv2/BinaryStream.h" #include "libGLESv2/ProgramBinary.h" +#include "libGLESv2/Framebuffer.h" +#include "libGLESv2/Renderbuffer.h" #include "libGLESv2/renderer/ShaderExecutable.h" #include "common/debug.h" #include "common/version.h" #include "common/utilities.h" +#include "common/platform.h" #include "libGLESv2/main.h" #include "libGLESv2/Shader.h" #include "libGLESv2/Program.h" #include "libGLESv2/renderer/Renderer.h" -#include "libGLESv2/renderer/VertexDataManager.h" +#include "libGLESv2/renderer/d3d/DynamicHLSL.h" +#include "libGLESv2/renderer/d3d/ShaderD3D.h" +#include "libGLESv2/renderer/d3d/VertexDataManager.h" #include "libGLESv2/Context.h" #include "libGLESv2/Buffer.h" -#include "libGLESv2/DynamicHLSL.h" #include "common/blocklayout.h" -#undef near -#undef far - namespace gl { namespace { +TextureType GetTextureType(GLenum samplerType) +{ + switch (samplerType) + { + case GL_SAMPLER_2D: + case GL_INT_SAMPLER_2D: + case GL_UNSIGNED_INT_SAMPLER_2D: + case GL_SAMPLER_2D_SHADOW: + return TEXTURE_2D; + case GL_SAMPLER_3D: + case GL_INT_SAMPLER_3D: + case GL_UNSIGNED_INT_SAMPLER_3D: + return TEXTURE_3D; + case GL_SAMPLER_CUBE: + case GL_SAMPLER_CUBE_SHADOW: + return TEXTURE_CUBE; + case GL_INT_SAMPLER_CUBE: + case GL_UNSIGNED_INT_SAMPLER_CUBE: + return TEXTURE_CUBE; + case GL_SAMPLER_2D_ARRAY: + case GL_INT_SAMPLER_2D_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: + case GL_SAMPLER_2D_ARRAY_SHADOW: + return TEXTURE_2D_ARRAY; + default: UNREACHABLE(); + } + + return TEXTURE_2D; +} + unsigned int ParseAndStripArrayIndex(std::string* name) { unsigned int subscript = GL_INVALID_INDEX; @@ -51,14 +81,14 @@ unsigned int ParseAndStripArrayIndex(std::string* name) return subscript; } -void GetInputLayoutFromShader(const std::vector &shaderAttributes, VertexFormat inputLayout[MAX_VERTEX_ATTRIBS]) +void GetInputLayoutFromShader(const std::vector &shaderAttributes, VertexFormat inputLayout[MAX_VERTEX_ATTRIBS]) { size_t layoutIndex = 0; for (size_t attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++) { ASSERT(layoutIndex < MAX_VERTEX_ATTRIBS); - const gl::Attribute &shaderAttr = shaderAttributes[attributeIndex]; + const sh::Attribute &shaderAttr = shaderAttributes[attributeIndex]; if (shaderAttr.type != GL_NONE) { @@ -68,7 +98,7 @@ void GetInputLayoutFromShader(const std::vector &shaderAttributes { VertexFormat *defaultFormat = &inputLayout[layoutIndex]; - defaultFormat->mType = UniformComponentType(transposedType); + defaultFormat->mType = VariableComponentType(transposedType); defaultFormat->mNormalized = false; defaultFormat->mPureInteger = (defaultFormat->mType != GL_FLOAT); // note: inputs can not be bool defaultFormat->mComponents = VariableColumnCount(transposedType); @@ -77,6 +107,16 @@ void GetInputLayoutFromShader(const std::vector &shaderAttributes } } +bool IsRowMajorLayout(const sh::InterfaceBlockField &var) +{ + return var.isRowMajorLayout; +} + +bool IsRowMajorLayout(const sh::ShaderVariable &var) +{ + return false; +} + } VariableLocation::VariableLocation(const std::string &name, unsigned int element, unsigned int index) @@ -84,8 +124,7 @@ VariableLocation::VariableLocation(const std::string &name, unsigned int element { } -ProgramBinary::VertexExecutable::VertexExecutable(rx::Renderer *const renderer, - const VertexFormat inputLayout[], +ProgramBinary::VertexExecutable::VertexExecutable(const VertexFormat inputLayout[], const GLenum signature[], rx::ShaderExecutable *shaderExecutable) : mShaderExecutable(shaderExecutable) @@ -99,7 +138,7 @@ ProgramBinary::VertexExecutable::VertexExecutable(rx::Renderer *const renderer, ProgramBinary::VertexExecutable::~VertexExecutable() { - delete mShaderExecutable; + SafeDelete(mShaderExecutable); } bool ProgramBinary::VertexExecutable::matchesSignature(const GLenum signature[]) const @@ -115,6 +154,17 @@ bool ProgramBinary::VertexExecutable::matchesSignature(const GLenum signature[]) return true; } +ProgramBinary::PixelExecutable::PixelExecutable(const std::vector &outputSignature, rx::ShaderExecutable *shaderExecutable) + : mOutputSignature(outputSignature), + mShaderExecutable(shaderExecutable) +{ +} + +ProgramBinary::PixelExecutable::~PixelExecutable() +{ + SafeDelete(mShaderExecutable); +} + LinkedVarying::LinkedVarying() { } @@ -132,12 +182,13 @@ ProgramBinary::ProgramBinary(rx::Renderer *renderer) mRenderer(renderer), mDynamicHLSL(NULL), mVertexWorkarounds(rx::ANGLE_D3D_WORKAROUND_NONE), - mPixelExecutable(NULL), + mPixelWorkarounds(rx::ANGLE_D3D_WORKAROUND_NONE), mGeometryExecutable(NULL), mUsedVertexSamplerRange(0), mUsedPixelSamplerRange(0), mUsesPointSize(false), mShaderVersion(100), + mDirtySamplerMapping(true), mVertexUniformStorage(NULL), mFragmentUniformStorage(NULL), mValidated(false), @@ -158,34 +209,12 @@ ProgramBinary::ProgramBinary(rx::Renderer *renderer) mSamplersVS[index].active = false; } - mDynamicHLSL = new DynamicHLSL(renderer); + mDynamicHLSL = new rx::DynamicHLSL(renderer); } ProgramBinary::~ProgramBinary() { - while (!mVertexExecutables.empty()) - { - delete mVertexExecutables.back(); - mVertexExecutables.pop_back(); - } - - SafeDelete(mGeometryExecutable); - SafeDelete(mPixelExecutable); - - while (!mUniforms.empty()) - { - delete mUniforms.back(); - mUniforms.pop_back(); - } - - while (!mUniformBlocks.empty()) - { - delete mUniformBlocks.back(); - mUniformBlocks.pop_back(); - } - - SafeDelete(mVertexUniformStorage); - SafeDelete(mFragmentUniformStorage); + reset(); SafeDelete(mDynamicHLSL); } @@ -204,9 +233,57 @@ unsigned int ProgramBinary::issueSerial() return mCurrentSerial++; } -rx::ShaderExecutable *ProgramBinary::getPixelExecutable() const +rx::ShaderExecutable *ProgramBinary::getPixelExecutableForFramebuffer(const Framebuffer *fbo) { - return mPixelExecutable; + std::vector outputs(IMPLEMENTATION_MAX_DRAW_BUFFERS); + for (size_t outputIndex = 0; outputIndex < IMPLEMENTATION_MAX_DRAW_BUFFERS; outputIndex++) + { + if (fbo->getColorbuffer(outputIndex) != NULL) + { + // Always output floats for now + outputs[outputIndex] = GL_FLOAT; + } + else + { + outputs[outputIndex] = GL_NONE; + } + } + + return getPixelExecutableForOutputLayout(outputs); +} + +rx::ShaderExecutable *ProgramBinary::getPixelExecutableForOutputLayout(const std::vector &outputSignature) +{ + for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++) + { + if (mPixelExecutables[executableIndex]->matchesSignature(outputSignature)) + { + return mPixelExecutables[executableIndex]->shaderExecutable(); + } + } + + std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(mPixelHLSL, mPixelShaderKey, mUsesFragDepth, + outputSignature); + + // Generate new pixel executable + InfoLog tempInfoLog; + rx::ShaderExecutable *pixelExecutable = mRenderer->compileToExecutable(tempInfoLog, finalPixelHLSL.c_str(), rx::SHADER_PIXEL, + mTransformFeedbackLinkedVaryings, + (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), + mPixelWorkarounds); + + if (!pixelExecutable) + { + std::vector tempCharBuffer(tempInfoLog.getLength() + 3); + tempInfoLog.getLog(tempInfoLog.getLength(), NULL, &tempCharBuffer[0]); + ERR("Error compiling dynamic pixel executable:\n%s\n", &tempCharBuffer[0]); + } + else + { + mPixelExecutables.push_back(new PixelExecutable(outputSignature, pixelExecutable)); + } + + return pixelExecutable; } rx::ShaderExecutable *ProgramBinary::getVertexExecutableForInputLayout(const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS]) @@ -223,16 +300,11 @@ rx::ShaderExecutable *ProgramBinary::getVertexExecutableForInputLayout(const Ver } // Generate new dynamic layout with attribute conversions - const std::string &layoutHLSL = mDynamicHLSL->generateInputLayoutHLSL(inputLayout, mShaderAttributes); - - // Generate new shader source by replacing the attributes stub with the defined input layout - std::string vertexHLSL = mVertexHLSL; - size_t insertPos = vertexHLSL.find(DynamicHLSL::VERTEX_ATTRIBUTE_STUB_STRING); - vertexHLSL.replace(insertPos, DynamicHLSL::VERTEX_ATTRIBUTE_STUB_STRING.length(), layoutHLSL); + std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(mVertexHLSL, inputLayout, mShaderAttributes); // Generate new vertex executable InfoLog tempInfoLog; - rx::ShaderExecutable *vertexExecutable = mRenderer->compileToExecutable(tempInfoLog, vertexHLSL.c_str(), + rx::ShaderExecutable *vertexExecutable = mRenderer->compileToExecutable(tempInfoLog, finalVertexHLSL.c_str(), rx::SHADER_VERTEX, mTransformFeedbackLinkedVaryings, (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), @@ -246,7 +318,7 @@ rx::ShaderExecutable *ProgramBinary::getVertexExecutableForInputLayout(const Ver } else { - mVertexExecutables.push_back(new VertexExecutable(mRenderer, inputLayout, signature, vertexExecutable)); + mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, vertexExecutable)); } return vertexExecutable; @@ -312,14 +384,14 @@ bool ProgramBinary::usesGeometryShader() const // 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) +GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerIndex, const Caps &caps) { GLint logicalTextureUnit = -1; switch (type) { case SAMPLER_PIXEL: - ASSERT(samplerIndex < sizeof(mSamplersPS)/sizeof(mSamplersPS[0])); + ASSERT(samplerIndex < ArraySize(mSamplersPS)); if (mSamplersPS[samplerIndex].active) { @@ -327,7 +399,7 @@ GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerInd } break; case SAMPLER_VERTEX: - ASSERT(samplerIndex < sizeof(mSamplersVS)/sizeof(mSamplersVS[0])); + ASSERT(samplerIndex < ArraySize(mSamplersVS)); if (mSamplersVS[samplerIndex].active) { @@ -337,7 +409,7 @@ GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerInd default: UNREACHABLE(); } - if (logicalTextureUnit >= 0 && logicalTextureUnit < (GLint)mRenderer->getMaxCombinedTextureImageUnits()) + if (logicalTextureUnit >= 0 && logicalTextureUnit < static_cast(caps.maxCombinedTextureImageUnits)) { return logicalTextureUnit; } @@ -352,11 +424,11 @@ TextureType ProgramBinary::getSamplerTextureType(SamplerType type, unsigned int switch (type) { case SAMPLER_PIXEL: - ASSERT(samplerIndex < sizeof(mSamplersPS)/sizeof(mSamplersPS[0])); + ASSERT(samplerIndex < ArraySize(mSamplersPS)); ASSERT(mSamplersPS[samplerIndex].active); return mSamplersPS[samplerIndex].textureType; case SAMPLER_VERTEX: - ASSERT(samplerIndex < sizeof(mSamplersVS)/sizeof(mSamplersVS[0])); + ASSERT(samplerIndex < ArraySize(mSamplersVS)); ASSERT(mSamplersVS[samplerIndex].active); return mSamplersVS[samplerIndex].textureType; default: UNREACHABLE(); @@ -487,8 +559,8 @@ static inline void SetIfDirty(T *dest, const T& source, bool *dirtyFlag) template void ProgramBinary::setUniform(GLint location, GLsizei count, const T* v, GLenum targetUniformType) { - const int components = UniformComponentCount(targetUniformType); - const GLenum targetBoolType = UniformBoolVectorType(targetUniformType); + const int components = VariableComponentCount(targetUniformType); + const GLenum targetBoolType = VariableBoolVectorType(targetUniformType); LinkedUniform *targetUniform = getUniformByLocation(location); @@ -732,6 +804,13 @@ void ProgramBinary::setUniform1iv(GLint location, GLsizei count, const GLint *v) } } else UNREACHABLE(); + + // Set a special flag if we change a sampler uniform + if (IsSampler(targetUniform->type) && + (memcmp(targetUniform->data, v, sizeof(GLint)) != 0)) + { + mDirtySamplerMapping = true; + } } void ProgramBinary::setUniform2iv(GLint location, GLsizei count, const GLint *v) @@ -770,36 +849,26 @@ void ProgramBinary::setUniform4uiv(GLint location, GLsizei count, const GLuint * } template -bool ProgramBinary::getUniformv(GLint location, GLsizei *bufSize, T *params, GLenum uniformType) +void ProgramBinary::getUniformv(GLint location, T *params, GLenum uniformType) { LinkedUniform *targetUniform = mUniforms[mUniformIndex[location].index]; - // sized queries -- ensure the provided buffer is large enough - if (bufSize) - { - int requiredBytes = UniformExternalSize(targetUniform->type); - if (*bufSize < requiredBytes) - { - return false; - } - } - if (IsMatrixType(targetUniform->type)) { const int rows = VariableRowCount(targetUniform->type); const int cols = VariableColumnCount(targetUniform->type); transposeMatrix(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4 * rows, rows, cols, 4, rows); } - else if (uniformType == UniformComponentType(targetUniform->type)) + else if (uniformType == VariableComponentType(targetUniform->type)) { - unsigned int size = UniformComponentCount(targetUniform->type); + unsigned int size = VariableComponentCount(targetUniform->type); memcpy(params, targetUniform->data + mUniformIndex[location].element * 4 * sizeof(T), size * sizeof(T)); } else { - unsigned int size = UniformComponentCount(targetUniform->type); - switch (UniformComponentType(targetUniform->type)) + unsigned int size = VariableComponentCount(targetUniform->type); + switch (VariableComponentType(targetUniform->type)) { case GL_BOOL: { @@ -848,23 +917,21 @@ bool ProgramBinary::getUniformv(GLint location, GLsizei *bufSize, T *params, GLe default: UNREACHABLE(); } } - - return true; } -bool ProgramBinary::getUniformfv(GLint location, GLsizei *bufSize, GLfloat *params) +void ProgramBinary::getUniformfv(GLint location, GLfloat *params) { - return getUniformv(location, bufSize, params, GL_FLOAT); + getUniformv(location, params, GL_FLOAT); } -bool ProgramBinary::getUniformiv(GLint location, GLsizei *bufSize, GLint *params) +void ProgramBinary::getUniformiv(GLint location, GLint *params) { - return getUniformv(location, bufSize, params, GL_INT); + getUniformv(location, params, GL_INT); } -bool ProgramBinary::getUniformuiv(GLint location, GLsizei *bufSize, GLuint *params) +void ProgramBinary::getUniformuiv(GLint location, GLuint *params) { - return getUniformv(location, bufSize, params, GL_UNSIGNED_INT); + getUniformv(location, params, GL_UNSIGNED_INT); } void ProgramBinary::dirtyAllUniforms() @@ -876,9 +943,15 @@ void ProgramBinary::dirtyAllUniforms() } } -// Applies all the uniforms set for this program object to the renderer -void ProgramBinary::applyUniforms() +void ProgramBinary::updateSamplerMapping() { + if (!mDirtySamplerMapping) + { + return; + } + + mDirtySamplerMapping = false; + // Retrieve sampler uniform values for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) { @@ -889,7 +962,7 @@ void ProgramBinary::applyUniforms() if (IsSampler(targetUniform->type)) { int count = targetUniform->elementCount(); - GLint (*v)[4] = (GLint(*)[4])targetUniform->data; + GLint (*v)[4] = reinterpret_cast(targetUniform->data); if (targetUniform->isReferencedByFragmentShader()) { @@ -925,6 +998,12 @@ void ProgramBinary::applyUniforms() } } } +} + +// Applies all the uniforms set for this program object to the renderer +void ProgramBinary::applyUniforms() +{ + updateSamplerMapping(); mRenderer->applyUniforms(*this); @@ -934,7 +1013,7 @@ void ProgramBinary::applyUniforms() } } -bool ProgramBinary::applyUniformBuffers(const std::vector boundBuffers) +bool ProgramBinary::applyUniformBuffers(const std::vector boundBuffers, const Caps &caps) { const gl::Buffer *vertexUniformBuffers[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS] = {NULL}; const gl::Buffer *fragmentUniformBuffers[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS] = {NULL}; @@ -946,12 +1025,12 @@ bool ProgramBinary::applyUniformBuffers(const std::vector boundBuff for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mUniformBlocks.size(); uniformBlockIndex++) { - gl::UniformBlock *uniformBlock = getUniformBlockByIndex(uniformBlockIndex); + UniformBlock *uniformBlock = getUniformBlockByIndex(uniformBlockIndex); gl::Buffer *uniformBuffer = boundBuffers[uniformBlockIndex]; ASSERT(uniformBlock && uniformBuffer); - if (uniformBuffer->size() < uniformBlock->dataSize) + if (uniformBuffer->getSize() < uniformBlock->dataSize) { // undefined behaviour return false; @@ -963,7 +1042,7 @@ bool ProgramBinary::applyUniformBuffers(const std::vector boundBuff { unsigned int registerIndex = uniformBlock->vsRegisterIndex - reservedBuffersInVS; ASSERT(vertexUniformBuffers[registerIndex] == NULL); - ASSERT(registerIndex < mRenderer->getMaxVertexShaderUniformBuffers()); + ASSERT(registerIndex < caps.maxVertexUniformBlocks); vertexUniformBuffers[registerIndex] = uniformBuffer; } @@ -971,7 +1050,7 @@ bool ProgramBinary::applyUniformBuffers(const std::vector boundBuff { unsigned int registerIndex = uniformBlock->psRegisterIndex - reservedBuffersInFS; ASSERT(fragmentUniformBuffers[registerIndex] == NULL); - ASSERT(registerIndex < mRenderer->getMaxFragmentShaderUniformBuffers()); + ASSERT(registerIndex < caps.maxFragmentUniformBlocks); fragmentUniformBuffers[registerIndex] = uniformBuffer; } } @@ -979,10 +1058,13 @@ bool ProgramBinary::applyUniformBuffers(const std::vector boundBuff return mRenderer->setUniformBuffers(vertexUniformBuffers, fragmentUniformBuffers); } -bool ProgramBinary::linkVaryings(InfoLog &infoLog, FragmentShader *fragmentShader, VertexShader *vertexShader) +bool ProgramBinary::linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shader *vertexShader) { - std::vector &fragmentVaryings = fragmentShader->getVaryings(); - std::vector &vertexVaryings = vertexShader->getVaryings(); + rx::VertexShaderD3D *vertexShaderD3D = rx::VertexShaderD3D::makeVertexShaderD3D(vertexShader->getImplementation()); + rx::FragmentShaderD3D *fragmentShaderD3D = rx::FragmentShaderD3D::makeFragmentShaderD3D(fragmentShader->getImplementation()); + + std::vector &fragmentVaryings = fragmentShaderD3D->getVaryings(); + std::vector &vertexVaryings = vertexShaderD3D->getVaryings(); for (size_t fragVaryingIndex = 0; fragVaryingIndex < fragmentVaryings.size(); fragVaryingIndex++) { @@ -994,7 +1076,7 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, FragmentShader *fragmentShade PackedVarying *output = &vertexVaryings[vertVaryingIndex]; if (output->name == input->name) { - if (!linkValidateVariables(infoLog, output->name, *input, *output)) + if (!linkValidateVaryings(infoLog, output->name, *input, *output)) { return false; } @@ -1016,8 +1098,15 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, FragmentShader *fragmentShade return true; } -bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) +bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length) { +#ifdef ANGLE_DISABLE_PROGRAM_BINARY_LOAD + return false; +#else + ASSERT(binaryFormat == GL_PROGRAM_BINARY_ANGLE); + + reset(); + BinaryInputStream stream(binary, length); int format = stream.readInt(); @@ -1101,7 +1190,7 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) int matrixStride = stream.readInt(); bool isRowMajorMatrix = stream.readBool(); - const gl::BlockMemberInfo blockInfo(offset, arrayStride, matrixStride, isRowMajorMatrix); + const sh::BlockMemberInfo blockInfo(offset, arrayStride, matrixStride, isRowMajorMatrix); LinkedUniform *uniform = new LinkedUniform(type, precision, name, arraySize, blockIndex, blockInfo); @@ -1177,7 +1266,6 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) stream.readInt(&mVertexWorkarounds); const unsigned int vertexShaderCount = stream.readInt(); - for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount; vertexShaderIndex++) { VertexFormat inputLayout[MAX_VERTEX_ATTRIBS]; @@ -1192,9 +1280,7 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) } unsigned int vertexShaderSize = stream.readInt(); - - const char *vertexShaderFunction = (const char*) binary + stream.offset(); - + const unsigned char *vertexShaderFunction = reinterpret_cast(binary) + stream.offset(); rx::ShaderExecutable *shaderExecutable = mRenderer->loadExecutable(reinterpret_cast(vertexShaderFunction), vertexShaderSize, rx::SHADER_VERTEX, mTransformFeedbackLinkedVaryings, @@ -1210,23 +1296,52 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) mDynamicHLSL->getInputLayoutSignature(inputLayout, signature); // add new binary - mVertexExecutables.push_back(new VertexExecutable(mRenderer, inputLayout, signature, shaderExecutable)); + mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, shaderExecutable)); stream.skip(vertexShaderSize); } - unsigned int pixelShaderSize = stream.readInt(); + stream.readString(&mPixelHLSL); + stream.readInt(&mPixelWorkarounds); + stream.readBool(&mUsesFragDepth); - const char *pixelShaderFunction = (const char*) binary + stream.offset(); - mPixelExecutable = mRenderer->loadExecutable(reinterpret_cast(pixelShaderFunction), - pixelShaderSize, rx::SHADER_PIXEL, mTransformFeedbackLinkedVaryings, - (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS)); - if (!mPixelExecutable) + const size_t pixelShaderKeySize = stream.readInt(); + mPixelShaderKey.resize(pixelShaderKeySize); + for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKeySize; pixelShaderKeyIndex++) { - infoLog.append("Could not create pixel shader."); - return false; + stream.readInt(&mPixelShaderKey[pixelShaderKeyIndex].type); + stream.readString(&mPixelShaderKey[pixelShaderKeyIndex].name); + stream.readString(&mPixelShaderKey[pixelShaderKeyIndex].source); + stream.readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputIndex); + } + + const size_t pixelShaderCount = stream.readInt(); + for (size_t pixelShaderIndex = 0; pixelShaderIndex < pixelShaderCount; pixelShaderIndex++) + { + const size_t outputCount = stream.readInt(); + std::vector outputs(outputCount); + for (size_t outputIndex = 0; outputIndex < outputCount; outputIndex++) + { + stream.readInt(&outputs[outputIndex]); + } + + const size_t pixelShaderSize = stream.readInt(); + const unsigned char *pixelShaderFunction = reinterpret_cast(binary) + stream.offset(); + rx::ShaderExecutable *shaderExecutable = mRenderer->loadExecutable(pixelShaderFunction, pixelShaderSize, + rx::SHADER_PIXEL, + mTransformFeedbackLinkedVaryings, + (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS)); + if (!shaderExecutable) + { + infoLog.append("Could not create pixel shader."); + return false; + } + + // add new binary + mPixelExecutables.push_back(new PixelExecutable(outputs, shaderExecutable)); + + stream.skip(pixelShaderSize); } - stream.skip(pixelShaderSize); unsigned int geometryShaderSize = stream.readInt(); @@ -1239,7 +1354,6 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) if (!mGeometryExecutable) { infoLog.append("Could not create geometry shader."); - SafeDelete(mPixelExecutable); return false; } stream.skip(geometryShaderSize); @@ -1260,10 +1374,16 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) initializeUniformStorage(); return true; +#endif // #ifdef ANGLE_DISABLE_PROGRAM_BINARY_LOAD } -bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) +bool ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length) { + if (binaryFormat) + { + *binaryFormat = GL_PROGRAM_BINARY_ANGLE; + } + BinaryOutputStream stream; stream.writeInt(GL_PROGRAM_BINARY_ANGLE); @@ -1383,22 +1503,49 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) size_t vertexShaderSize = vertexExecutable->shaderExecutable()->getLength(); stream.writeInt(vertexShaderSize); - unsigned char *vertexBlob = static_cast(vertexExecutable->shaderExecutable()->getFunction()); + const uint8_t *vertexBlob = vertexExecutable->shaderExecutable()->getFunction(); stream.writeBytes(vertexBlob, vertexShaderSize); } - size_t pixelShaderSize = mPixelExecutable->getLength(); - stream.writeInt(pixelShaderSize); + stream.writeString(mPixelHLSL); + stream.writeInt(mPixelWorkarounds); + stream.writeInt(mUsesFragDepth); - unsigned char *pixelBlob = static_cast(mPixelExecutable->getFunction()); - stream.writeBytes(pixelBlob, pixelShaderSize); + stream.writeInt(mPixelShaderKey.size()); + for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < mPixelShaderKey.size(); pixelShaderKeyIndex++) + { + const rx::PixelShaderOuputVariable &variable = mPixelShaderKey[pixelShaderKeyIndex]; + stream.writeInt(variable.type); + stream.writeString(variable.name); + stream.writeString(variable.source); + stream.writeInt(variable.outputIndex); + } + + stream.writeInt(mPixelExecutables.size()); + for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size(); pixelExecutableIndex++) + { + PixelExecutable *pixelExecutable = mPixelExecutables[pixelExecutableIndex]; + + const std::vector outputs = pixelExecutable->outputSignature(); + stream.writeInt(outputs.size()); + for (size_t outputIndex = 0; outputIndex < outputs.size(); outputIndex++) + { + stream.writeInt(outputs[outputIndex]); + } + + size_t pixelShaderSize = pixelExecutable->shaderExecutable()->getLength(); + stream.writeInt(pixelShaderSize); + + const uint8_t *pixelBlob = pixelExecutable->shaderExecutable()->getFunction(); + stream.writeBytes(pixelBlob, pixelShaderSize); + } size_t geometryShaderSize = (mGeometryExecutable != NULL) ? mGeometryExecutable->getLength() : 0; stream.writeInt(geometryShaderSize); if (mGeometryExecutable != NULL && geometryShaderSize > 0) { - unsigned char *geometryBlob = static_cast(mGeometryExecutable->getFunction()); + const uint8_t *geometryBlob = mGeometryExecutable->getFunction(); stream.writeBytes(geometryBlob, geometryShaderSize); } @@ -1442,7 +1589,7 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) GLint ProgramBinary::getLength() { GLint length; - if (save(NULL, INT_MAX, &length)) + if (save(NULL, NULL, INT_MAX, &length)) { return length; } @@ -1452,31 +1599,39 @@ GLint ProgramBinary::getLength() } } -bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader, - const std::vector& transformFeedbackVaryings, GLenum transformFeedbackBufferMode) +bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBindings, Shader *fragmentShader, Shader *vertexShader, + const std::vector& transformFeedbackVaryings, GLenum transformFeedbackBufferMode, const Caps &caps) { if (!fragmentShader || !fragmentShader->isCompiled()) { return false; } + ASSERT(fragmentShader->getType() == GL_FRAGMENT_SHADER); if (!vertexShader || !vertexShader->isCompiled()) { return false; } + ASSERT(vertexShader->getType() == GL_VERTEX_SHADER); + + reset(); - mTransformFeedbackLinkedVaryings.clear(); mTransformFeedbackBufferMode = transformFeedbackBufferMode; - mShaderVersion = vertexShader->getShaderVersion(); + rx::VertexShaderD3D *vertexShaderD3D = rx::VertexShaderD3D::makeVertexShaderD3D(vertexShader->getImplementation()); + rx::FragmentShaderD3D *fragmentShaderD3D = rx::FragmentShaderD3D::makeFragmentShaderD3D(fragmentShader->getImplementation()); - std::string pixelHLSL = fragmentShader->getHLSL(); - mVertexHLSL = vertexShader->getHLSL(); - mVertexWorkarounds = vertexShader->getD3DWorkarounds(); + mShaderVersion = vertexShaderD3D->getShaderVersion(); + + mPixelHLSL = fragmentShaderD3D->getTranslatedSource(); + mPixelWorkarounds = fragmentShaderD3D->getD3DWorkarounds(); + + mVertexHLSL = vertexShaderD3D->getTranslatedSource(); + mVertexWorkarounds = vertexShaderD3D->getD3DWorkarounds(); // Map the varyings to the register file - VaryingPacking packing = { NULL }; - int registers = mDynamicHLSL->packVaryings(infoLog, packing, fragmentShader, vertexShader, transformFeedbackVaryings); + rx::VaryingPacking packing = { NULL }; + int registers = mDynamicHLSL->packVaryings(infoLog, packing, fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings); if (registers < 0) { @@ -1488,11 +1643,11 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin return false; } - mUsesPointSize = vertexShader->usesPointSize(); + mUsesPointSize = vertexShaderD3D->usesPointSize(); std::vector linkedVaryings; - if (!mDynamicHLSL->generateShaderLinkHLSL(infoLog, registers, packing, pixelHLSL, mVertexHLSL, - fragmentShader, vertexShader, transformFeedbackVaryings, - &linkedVaryings, &mOutputVariables)) + if (!mDynamicHLSL->generateShaderLinkHLSL(infoLog, registers, packing, mPixelHLSL, mVertexHLSL, + fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings, + &linkedVaryings, &mOutputVariables, &mPixelShaderKey, &mUsesFragDepth)) { return false; } @@ -1504,26 +1659,28 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin success = false; } - if (!linkUniforms(infoLog, vertexShader->getUniforms(), fragmentShader->getUniforms())) + if (!linkUniforms(infoLog, *vertexShader, *fragmentShader, caps)) { success = false; } // special case for gl_DepthRange, the only built-in uniform (also a struct) - if (vertexShader->usesDepthRange() || fragmentShader->usesDepthRange()) + if (vertexShaderD3D->usesDepthRange() || fragmentShaderD3D->usesDepthRange()) { - mUniforms.push_back(new LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.near", 0, -1, BlockMemberInfo::getDefaultBlockInfo())); - mUniforms.push_back(new LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.far", 0, -1, BlockMemberInfo::getDefaultBlockInfo())); - mUniforms.push_back(new LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.diff", 0, -1, BlockMemberInfo::getDefaultBlockInfo())); + const sh::BlockMemberInfo &defaultInfo = sh::BlockMemberInfo::getDefaultBlockInfo(); + + mUniforms.push_back(new LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.near", 0, -1, defaultInfo)); + mUniforms.push_back(new LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.far", 0, -1, defaultInfo)); + mUniforms.push_back(new LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.diff", 0, -1, defaultInfo)); } - if (!linkUniformBlocks(infoLog, vertexShader->getInterfaceBlocks(), fragmentShader->getInterfaceBlocks())) + if (!linkUniformBlocks(infoLog, *vertexShader, *fragmentShader, caps)) { success = false; } if (!gatherTransformFeedbackLinkedVaryings(infoLog, linkedVaryings, transformFeedbackVaryings, - transformFeedbackBufferMode, &mTransformFeedbackLinkedVaryings)) + transformFeedbackBufferMode, &mTransformFeedbackLinkedVaryings, caps)) { success = false; } @@ -1531,38 +1688,30 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin if (success) { VertexFormat defaultInputLayout[MAX_VERTEX_ATTRIBS]; - GetInputLayoutFromShader(vertexShader->activeAttributes(), defaultInputLayout); - + GetInputLayoutFromShader(vertexShaderD3D->getActiveAttributes(), defaultInputLayout); rx::ShaderExecutable *defaultVertexExecutable = getVertexExecutableForInputLayout(defaultInputLayout); - mPixelExecutable = mRenderer->compileToExecutable(infoLog, pixelHLSL.c_str(), rx::SHADER_PIXEL, - mTransformFeedbackLinkedVaryings, - (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), - fragmentShader->getD3DWorkarounds()); + + std::vector defaultPixelOutput(IMPLEMENTATION_MAX_DRAW_BUFFERS); + for (size_t i = 0; i < defaultPixelOutput.size(); i++) + { + defaultPixelOutput[i] = (i == 0) ? GL_FLOAT : GL_NONE; + } + rx::ShaderExecutable *defaultPixelExecutable = getPixelExecutableForOutputLayout(defaultPixelOutput); if (usesGeometryShader()) { - std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(registers, fragmentShader, vertexShader); + std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(registers, fragmentShaderD3D, vertexShaderD3D); mGeometryExecutable = mRenderer->compileToExecutable(infoLog, geometryHLSL.c_str(), rx::SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings, (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), rx::ANGLE_D3D_WORKAROUND_NONE); } - if (!defaultVertexExecutable || !mPixelExecutable || (usesGeometryShader() && !mGeometryExecutable)) + if (!defaultVertexExecutable || !defaultPixelExecutable || (usesGeometryShader() && !mGeometryExecutable)) { infoLog.append("Failed to create D3D shaders."); success = false; - - while (!mVertexExecutables.empty()) - { - delete mVertexExecutables.back(); - mVertexExecutables.pop_back(); - } - - SafeDelete(mGeometryExecutable); - SafeDelete(mPixelExecutable); - - mTransformFeedbackLinkedVaryings.clear(); + reset(); } } @@ -1570,22 +1719,24 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin } // Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices -bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader) +bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, Shader *fragmentShader, Shader *vertexShader) { + rx::VertexShaderD3D *vertexShaderD3D = rx::VertexShaderD3D::makeVertexShaderD3D(vertexShader->getImplementation()); + unsigned int usedLocations = 0; - const std::vector &activeAttributes = vertexShader->activeAttributes(); + const std::vector &activeAttributes = vertexShaderD3D->getActiveAttributes(); // Link attributes that have a binding location for (unsigned int attributeIndex = 0; attributeIndex < activeAttributes.size(); attributeIndex++) { - const gl::Attribute &attribute = activeAttributes[attributeIndex]; + const sh::Attribute &attribute = activeAttributes[attributeIndex]; const int location = attribute.location == -1 ? attributeBindings.getAttributeBinding(attribute.name) : attribute.location; mShaderAttributes[attributeIndex] = attribute; if (location != -1) // Set by glBindAttribLocation or by location layout qualifier { - const int rows = AttributeRegisterCount(attribute.type); + const int rows = VariableRegisterCount(attribute.type); if (rows + location > MAX_VERTEX_ATTRIBS) { @@ -1597,7 +1748,7 @@ bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &at for (int row = 0; row < rows; row++) { const int rowLocation = location + row; - gl::ShaderVariable &linkedAttribute = mLinkedAttribute[rowLocation]; + sh::ShaderVariable &linkedAttribute = mLinkedAttribute[rowLocation]; // In GLSL 3.00, attribute aliasing produces a link error // In GLSL 1.00, attribute aliasing is allowed @@ -1619,12 +1770,12 @@ bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &at // Link attributes that don't have a binding location for (unsigned int attributeIndex = 0; attributeIndex < activeAttributes.size(); attributeIndex++) { - const gl::Attribute &attribute = activeAttributes[attributeIndex]; + const sh::Attribute &attribute = activeAttributes[attributeIndex]; const int location = attribute.location == -1 ? attributeBindings.getAttributeBinding(attribute.name) : attribute.location; if (location == -1) // Not set by glBindAttribLocation or by location layout qualifier { - int rows = AttributeRegisterCount(attribute.type); + int rows = VariableRegisterCount(attribute.type); int availableIndex = AllocateFirstFreeBits(&usedLocations, rows, MAX_VERTEX_ATTRIBS); if (availableIndex == -1 || availableIndex + rows > MAX_VERTEX_ATTRIBS) @@ -1640,8 +1791,8 @@ bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &at for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; ) { - int index = vertexShader->getSemanticIndex(mLinkedAttribute[attributeIndex].name); - int rows = AttributeRegisterCount(mLinkedAttribute[attributeIndex].type); + int index = vertexShaderD3D->getSemanticIndex(mLinkedAttribute[attributeIndex].name); + int rows = VariableRegisterCount(mLinkedAttribute[attributeIndex].type); for (int r = 0; r < rows; r++) { @@ -1654,7 +1805,8 @@ bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &at return true; } -bool ProgramBinary::linkValidateVariablesBase(InfoLog &infoLog, const std::string &variableName, const gl::ShaderVariable &vertexVariable, const gl::ShaderVariable &fragmentVariable, bool validatePrecision) +bool ProgramBinary::linkValidateVariablesBase(InfoLog &infoLog, const std::string &variableName, const sh::ShaderVariable &vertexVariable, + const sh::ShaderVariable &fragmentVariable, bool validatePrecision) { if (vertexVariable.type != fragmentVariable.type) { @@ -1672,32 +1824,29 @@ bool ProgramBinary::linkValidateVariablesBase(InfoLog &infoLog, const std::strin return false; } - return true; -} - -template -bool ProgramBinary::linkValidateFields(InfoLog &infoLog, const std::string &varName, const ShaderVarType &vertexVar, const ShaderVarType &fragmentVar) -{ - if (vertexVar.fields.size() != fragmentVar.fields.size()) + if (vertexVariable.fields.size() != fragmentVariable.fields.size()) { - infoLog.append("Structure lengths for %s differ between vertex and fragment shaders", varName.c_str()); + infoLog.append("Structure lengths for %s differ between vertex and fragment shaders", variableName.c_str()); return false; } - const unsigned int numMembers = vertexVar.fields.size(); + const unsigned int numMembers = vertexVariable.fields.size(); for (unsigned int memberIndex = 0; memberIndex < numMembers; memberIndex++) { - const ShaderVarType &vertexMember = vertexVar.fields[memberIndex]; - const ShaderVarType &fragmentMember = fragmentVar.fields[memberIndex]; + const sh::ShaderVariable &vertexMember = vertexVariable.fields[memberIndex]; + const sh::ShaderVariable &fragmentMember = fragmentVariable.fields[memberIndex]; if (vertexMember.name != fragmentMember.name) { infoLog.append("Name mismatch for field '%d' of %s: (in vertex: '%s', in fragment: '%s')", - memberIndex, varName.c_str(), vertexMember.name.c_str(), fragmentMember.name.c_str()); + memberIndex, variableName.c_str(), + vertexMember.name.c_str(), fragmentMember.name.c_str()); return false; } - const std::string memberName = varName.substr(0, varName.length()-1) + "." + vertexVar.name + "'"; - if (!linkValidateVariables(infoLog, memberName, vertexMember, fragmentMember)) + const std::string memberName = variableName.substr(0, variableName.length() - 1) + "." + + vertexMember.name + "'"; + + if (!linkValidateVariablesBase(infoLog, vertexMember.name, vertexMember, fragmentMember, validatePrecision)) { return false; } @@ -1706,22 +1855,17 @@ bool ProgramBinary::linkValidateFields(InfoLog &infoLog, const std::string &varN return true; } -bool ProgramBinary::linkValidateVariables(InfoLog &infoLog, const std::string &uniformName, const gl::Uniform &vertexUniform, const gl::Uniform &fragmentUniform) +bool ProgramBinary::linkValidateUniforms(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform) { if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, true)) { return false; } - if (!linkValidateFields(infoLog, uniformName, vertexUniform, fragmentUniform)) - { - return false; - } - return true; } -bool ProgramBinary::linkValidateVariables(InfoLog &infoLog, const std::string &varyingName, const gl::Varying &vertexVarying, const gl::Varying &fragmentVarying) +bool ProgramBinary::linkValidateVaryings(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying) { if (!linkValidateVariablesBase(infoLog, varyingName, vertexVarying, fragmentVarying, false)) { @@ -1734,56 +1878,52 @@ bool ProgramBinary::linkValidateVariables(InfoLog &infoLog, const std::string &v return false; } - if (!linkValidateFields(infoLog, varyingName, vertexVarying, fragmentVarying)) - { - return false; - } - return true; } -bool ProgramBinary::linkValidateVariables(InfoLog &infoLog, const std::string &uniformName, const gl::InterfaceBlockField &vertexUniform, const gl::InterfaceBlockField &fragmentUniform) +bool ProgramBinary::linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform) { if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, true)) { return false; } - if (vertexUniform.isRowMajorMatrix != fragmentUniform.isRowMajorMatrix) + if (vertexUniform.isRowMajorLayout != fragmentUniform.isRowMajorLayout) { infoLog.append("Matrix packings for %s differ between vertex and fragment shaders", uniformName.c_str()); return false; } - if (!linkValidateFields(infoLog, uniformName, vertexUniform, fragmentUniform)) - { - return false; - } - return true; } -bool ProgramBinary::linkUniforms(InfoLog &infoLog, const std::vector &vertexUniforms, const std::vector &fragmentUniforms) +bool ProgramBinary::linkUniforms(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps) { + const rx::VertexShaderD3D *vertexShaderD3D = rx::VertexShaderD3D::makeVertexShaderD3D(vertexShader.getImplementation()); + const rx::FragmentShaderD3D *fragmentShaderD3D = rx::FragmentShaderD3D::makeFragmentShaderD3D(fragmentShader.getImplementation()); + + const std::vector &vertexUniforms = vertexShaderD3D->getUniforms(); + const std::vector &fragmentUniforms = fragmentShaderD3D->getUniforms(); + // Check that uniforms defined in the vertex and fragment shaders are identical - typedef std::map UniformMap; + typedef std::map UniformMap; UniformMap linkedUniforms; for (unsigned int vertexUniformIndex = 0; vertexUniformIndex < vertexUniforms.size(); vertexUniformIndex++) { - const gl::Uniform &vertexUniform = vertexUniforms[vertexUniformIndex]; + const sh::Uniform &vertexUniform = vertexUniforms[vertexUniformIndex]; linkedUniforms[vertexUniform.name] = &vertexUniform; } for (unsigned int fragmentUniformIndex = 0; fragmentUniformIndex < fragmentUniforms.size(); fragmentUniformIndex++) { - const gl::Uniform &fragmentUniform = fragmentUniforms[fragmentUniformIndex]; + const sh::Uniform &fragmentUniform = fragmentUniforms[fragmentUniformIndex]; UniformMap::const_iterator entry = linkedUniforms.find(fragmentUniform.name); if (entry != linkedUniforms.end()) { - const gl::Uniform &vertexUniform = *entry->second; + const sh::Uniform &vertexUniform = *entry->second; const std::string &uniformName = "uniform '" + vertexUniform.name + "'"; - if (!linkValidateVariables(infoLog, uniformName, vertexUniform, fragmentUniform)) + if (!linkValidateUniforms(infoLog, uniformName, vertexUniform, fragmentUniform)) { return false; } @@ -1792,18 +1932,19 @@ bool ProgramBinary::linkUniforms(InfoLog &infoLog, const std::vectorgetUniformRegister(uniform.name)); } for (unsigned int uniformIndex = 0; uniformIndex < fragmentUniforms.size(); uniformIndex++) { - if (!defineUniform(GL_FRAGMENT_SHADER, fragmentUniforms[uniformIndex], infoLog)) - { - return false; - } + const sh::Uniform &uniform = fragmentUniforms[uniformIndex]; + defineUniformBase(GL_FRAGMENT_SHADER, uniform, fragmentShaderD3D->getUniformRegister(uniform.name)); + } + + if (!indexUniforms(infoLog, caps)) + { + return false; } initializeUniformStorage(); @@ -1811,194 +1952,178 @@ bool ProgramBinary::linkUniforms(InfoLog &infoLog, const std::vector 0) + for (unsigned int elementIndex = 0; elementIndex < uniform.elementCount(); elementIndex++) { - ShShaderOutput outputType = Shader::getCompilerOutputType(shader); - const unsigned int elementRegisterCount = HLSLVariableRegisterCount(constant, outputType) / constant.arraySize; + const std::string &elementString = (uniform.isArray() ? ArrayString(elementIndex) : ""); - for (unsigned int elementIndex = 0; elementIndex < constant.arraySize; elementIndex++) + encoder->enterAggregateType(); + + for (size_t fieldIndex = 0; fieldIndex < uniform.fields.size(); fieldIndex++) { - const unsigned int elementRegisterOffset = elementRegisterCount * elementIndex; + const sh::ShaderVariable &field = uniform.fields[fieldIndex]; + const std::string &fieldFullName = (fullName + elementString + "." + field.name); - for (size_t fieldIndex = 0; fieldIndex < constant.fields.size(); fieldIndex++) - { - const gl::Uniform &field = constant.fields[fieldIndex]; - const std::string &uniformName = constant.name + ArrayString(elementIndex) + "." + field.name; - const unsigned int fieldRegisterIndex = field.registerIndex + elementRegisterOffset; - gl::Uniform fieldUniform(field.type, field.precision, uniformName.c_str(), field.arraySize, - fieldRegisterIndex, field.elementIndex); - - fieldUniform.fields = field.fields; - if (!defineUniform(shader, fieldUniform, infoLog)) - { - return false; - } - } + defineUniform(shader, field, fieldFullName, encoder); } + + encoder->exitAggregateType(); } - else + } + else // Not a struct + { + // Arrays are treated as aggregate types + if (uniform.isArray()) { - for (size_t fieldIndex = 0; fieldIndex < constant.fields.size(); fieldIndex++) - { - const gl::Uniform &field = constant.fields[fieldIndex]; - const std::string &uniformName = constant.name + "." + field.name; - - gl::Uniform fieldUniform(field.type, field.precision, uniformName.c_str(), field.arraySize, - field.registerIndex, field.elementIndex); - - fieldUniform.fields = field.fields; - - if (!defineUniform(shader, fieldUniform, infoLog)) - { - return false; - } - } + encoder->enterAggregateType(); } - return true; - } + LinkedUniform *linkedUniform = getUniformByName(fullName); - if (IsSampler(constant.type)) - { - unsigned int samplerIndex = constant.registerIndex; - - do + if (!linkedUniform) { - if (shader == GL_VERTEX_SHADER) - { - if (samplerIndex < mRenderer->getMaxVertexTextureImageUnits()) - { - mSamplersVS[samplerIndex].active = true; - mSamplersVS[samplerIndex].textureType = getTextureType(constant.type, infoLog); - 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) - { - if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS) - { - mSamplersPS[samplerIndex].active = true; - mSamplersPS[samplerIndex].textureType = getTextureType(constant.type, infoLog); - mSamplersPS[samplerIndex].logicalTextureUnit = 0; - mUsedPixelSamplerRange = std::max(samplerIndex + 1, mUsedPixelSamplerRange); - } - else - { - infoLog.append("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).", MAX_TEXTURE_IMAGE_UNITS); - return false; - } - } - else UNREACHABLE(); - - samplerIndex++; + linkedUniform = new LinkedUniform(uniform.type, uniform.precision, fullName, uniform.arraySize, + -1, sh::BlockMemberInfo::getDefaultBlockInfo()); + ASSERT(linkedUniform); + linkedUniform->registerElement = encoder->getCurrentElement(); + mUniforms.push_back(linkedUniform); } - while (samplerIndex < constant.registerIndex + constant.arraySize); - } - LinkedUniform *uniform = NULL; - GLint location = getUniformLocation(constant.name); + ASSERT(linkedUniform->registerElement == encoder->getCurrentElement()); - if (location >= 0) // Previously defined, type and precision must match - { - uniform = mUniforms[mUniformIndex[location].index]; - } - else - { - uniform = new LinkedUniform(constant.type, constant.precision, constant.name, constant.arraySize, - -1, BlockMemberInfo::getDefaultBlockInfo()); - uniform->registerElement = constant.elementIndex; - } - - 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 == constant.type; - } - - mUniforms.push_back(uniform); - unsigned int uniformIndex = mUniforms.size() - 1; - - for (unsigned int arrayElementIndex = 0; arrayElementIndex < uniform->elementCount(); arrayElementIndex++) - { - mUniformIndex.push_back(VariableLocation(uniform->name, arrayElementIndex, uniformIndex)); - } - - if (shader == GL_VERTEX_SHADER) - { - if (constant.registerIndex + uniform->registerCount > mRenderer->getReservedVertexUniformVectors() + mRenderer->getMaxVertexUniformVectors()) + if (shader == GL_FRAGMENT_SHADER) { - infoLog.append("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%u)", mRenderer->getMaxVertexUniformVectors()); + linkedUniform->psRegisterIndex = encoder->getCurrentRegister(); + } + else if (shader == GL_VERTEX_SHADER) + { + linkedUniform->vsRegisterIndex = encoder->getCurrentRegister(); + } + else UNREACHABLE(); + + // Advance the uniform offset, to track registers allocation for structs + encoder->encodeType(uniform.type, uniform.arraySize, false); + + // Arrays are treated as aggregate types + if (uniform.isArray()) + { + encoder->exitAggregateType(); + } + } +} + +bool ProgramBinary::indexSamplerUniform(const LinkedUniform &uniform, InfoLog &infoLog, const Caps &caps) +{ + ASSERT(IsSampler(uniform.type)); + ASSERT(uniform.vsRegisterIndex != GL_INVALID_INDEX || uniform.psRegisterIndex != GL_INVALID_INDEX); + + if (uniform.vsRegisterIndex != GL_INVALID_INDEX) + { + if (!assignSamplers(uniform.vsRegisterIndex, uniform.type, uniform.arraySize, mSamplersVS, + &mUsedVertexSamplerRange, caps.maxVertexTextureImageUnits)) + { + infoLog.append("Vertex shader sampler count exceeds the maximum vertex texture units (%d).", + caps.maxVertexTextureImageUnits); + return false; + } + + unsigned int maxVertexVectors = mRenderer->getReservedVertexUniformVectors() + caps.maxVertexUniformVectors; + if (uniform.vsRegisterIndex + uniform.registerCount > maxVertexVectors) + { + infoLog.append("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%u)", + caps.maxVertexUniformVectors); return false; } } - else if (shader == GL_FRAGMENT_SHADER) + + if (uniform.psRegisterIndex != GL_INVALID_INDEX) { - if (constant.registerIndex + uniform->registerCount > mRenderer->getReservedFragmentUniformVectors() + mRenderer->getMaxFragmentUniformVectors()) + if (!assignSamplers(uniform.psRegisterIndex, uniform.type, uniform.arraySize, mSamplersPS, + &mUsedPixelSamplerRange, caps.maxTextureImageUnits)) { - infoLog.append("Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS (%u)", mRenderer->getMaxFragmentUniformVectors()); + infoLog.append("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).", + caps.maxTextureImageUnits); + return false; + } + + unsigned int maxFragmentVectors = mRenderer->getReservedFragmentUniformVectors() + caps.maxFragmentUniformVectors; + if (uniform.psRegisterIndex + uniform.registerCount > maxFragmentVectors) + { + infoLog.append("Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS (%u)", + caps.maxFragmentUniformVectors); return false; } } - else UNREACHABLE(); return true; } -bool ProgramBinary::areMatchingInterfaceBlocks(InfoLog &infoLog, const gl::InterfaceBlock &vertexInterfaceBlock, const gl::InterfaceBlock &fragmentInterfaceBlock) +bool ProgramBinary::indexUniforms(InfoLog &infoLog, const Caps &caps) +{ + for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) + { + const LinkedUniform &uniform = *mUniforms[uniformIndex]; + + if (IsSampler(uniform.type)) + { + if (!indexSamplerUniform(uniform, infoLog, caps)) + { + return false; + } + } + + for (unsigned int arrayElementIndex = 0; arrayElementIndex < uniform.elementCount(); arrayElementIndex++) + { + mUniformIndex.push_back(VariableLocation(uniform.name, arrayElementIndex, uniformIndex)); + } + } + + return true; +} + +bool ProgramBinary::assignSamplers(unsigned int startSamplerIndex, + GLenum samplerType, + unsigned int samplerCount, + Sampler *outArray, + GLuint *usedRange, + unsigned int limit) +{ + unsigned int samplerIndex = startSamplerIndex; + + do + { + if (samplerIndex < limit) + { + outArray[samplerIndex].active = true; + outArray[samplerIndex].textureType = GetTextureType(samplerType); + outArray[samplerIndex].logicalTextureUnit = 0; + *usedRange = std::max(samplerIndex + 1, *usedRange); + } + else + { + return false; + } + + samplerIndex++; + } while (samplerIndex < startSamplerIndex + samplerCount); + + return true; +} + +bool ProgramBinary::areMatchingInterfaceBlocks(InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock, const sh::InterfaceBlock &fragmentInterfaceBlock) { const char* blockName = vertexInterfaceBlock.name.c_str(); @@ -2024,8 +2149,8 @@ bool ProgramBinary::areMatchingInterfaceBlocks(InfoLog &infoLog, const gl::Inter const unsigned int numBlockMembers = vertexInterfaceBlock.fields.size(); for (unsigned int blockMemberIndex = 0; blockMemberIndex < numBlockMembers; blockMemberIndex++) { - const gl::InterfaceBlockField &vertexMember = vertexInterfaceBlock.fields[blockMemberIndex]; - const gl::InterfaceBlockField &fragmentMember = fragmentInterfaceBlock.fields[blockMemberIndex]; + const sh::InterfaceBlockField &vertexMember = vertexInterfaceBlock.fields[blockMemberIndex]; + const sh::InterfaceBlockField &fragmentMember = fragmentInterfaceBlock.fields[blockMemberIndex]; if (vertexMember.name != fragmentMember.name) { @@ -2034,8 +2159,8 @@ bool ProgramBinary::areMatchingInterfaceBlocks(InfoLog &infoLog, const gl::Inter return false; } - std::string uniformName = "interface block '" + vertexInterfaceBlock.name + "' member '" + vertexMember.name + "'"; - if (!linkValidateVariables(infoLog, uniformName, vertexMember, fragmentMember)) + std::string memberName = "interface block '" + vertexInterfaceBlock.name + "' member '" + vertexMember.name + "'"; + if (!linkValidateInterfaceBlockFields(infoLog, memberName, vertexMember, fragmentMember)) { return false; } @@ -2044,26 +2169,31 @@ bool ProgramBinary::areMatchingInterfaceBlocks(InfoLog &infoLog, const gl::Inter return true; } -bool ProgramBinary::linkUniformBlocks(InfoLog &infoLog, const std::vector &vertexInterfaceBlocks, - const std::vector &fragmentInterfaceBlocks) +bool ProgramBinary::linkUniformBlocks(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps) { + const rx::VertexShaderD3D *vertexShaderD3D = rx::VertexShaderD3D::makeVertexShaderD3D(vertexShader.getImplementation()); + const rx::FragmentShaderD3D *fragmentShaderD3D = rx::FragmentShaderD3D::makeFragmentShaderD3D(fragmentShader.getImplementation()); + + const std::vector &vertexInterfaceBlocks = vertexShaderD3D->getInterfaceBlocks(); + const std::vector &fragmentInterfaceBlocks = fragmentShaderD3D->getInterfaceBlocks(); + // Check that interface blocks defined in the vertex and fragment shaders are identical - typedef std::map UniformBlockMap; + typedef std::map UniformBlockMap; UniformBlockMap linkedUniformBlocks; for (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++) { - const gl::InterfaceBlock &vertexInterfaceBlock = vertexInterfaceBlocks[blockIndex]; + const sh::InterfaceBlock &vertexInterfaceBlock = vertexInterfaceBlocks[blockIndex]; linkedUniformBlocks[vertexInterfaceBlock.name] = &vertexInterfaceBlock; } for (unsigned int blockIndex = 0; blockIndex < fragmentInterfaceBlocks.size(); blockIndex++) { - const gl::InterfaceBlock &fragmentInterfaceBlock = fragmentInterfaceBlocks[blockIndex]; + const sh::InterfaceBlock &fragmentInterfaceBlock = fragmentInterfaceBlocks[blockIndex]; UniformBlockMap::const_iterator entry = linkedUniformBlocks.find(fragmentInterfaceBlock.name); if (entry != linkedUniformBlocks.end()) { - const gl::InterfaceBlock &vertexInterfaceBlock = *entry->second; + const sh::InterfaceBlock &vertexInterfaceBlock = *entry->second; if (!areMatchingInterfaceBlocks(infoLog, vertexInterfaceBlock, fragmentInterfaceBlock)) { return false; @@ -2073,7 +2203,7 @@ bool ProgramBinary::linkUniformBlocks(InfoLog &infoLog, const std::vector &linkedVaryings, const std::vector &transformFeedbackVaryingNames, GLenum transformFeedbackBufferMode, - std::vector *outTransformFeedbackLinkedVaryings) const + std::vector *outTransformFeedbackLinkedVaryings, + const Caps &caps) const { size_t totalComponents = 0; - const size_t maxSeparateComponents = mRenderer->getMaxTransformFeedbackSeparateComponents(); - const size_t maxInterleavedComponents = mRenderer->getMaxTransformFeedbackInterleavedComponents(); // Gather the linked varyings that are used for transform feedback, they should all exist. outTransformFeedbackLinkedVaryings->clear(); @@ -2119,10 +2248,10 @@ bool ProgramBinary::gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, cons size_t componentCount = linkedVaryings[j].semanticIndexCount * 4; if (transformFeedbackBufferMode == GL_SEPARATE_ATTRIBS && - componentCount > maxSeparateComponents) + componentCount > caps.maxTransformFeedbackSeparateComponents) { infoLog.append("Transform feedback varying's %s components (%u) exceed the maximum separate components (%u).", - linkedVaryings[j].name.c_str(), componentCount, maxSeparateComponents); + linkedVaryings[j].name.c_str(), componentCount, caps.maxTransformFeedbackSeparateComponents); return false; } @@ -2138,53 +2267,60 @@ bool ProgramBinary::gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, cons ASSERT(found); } - if (transformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS && totalComponents > maxInterleavedComponents) + if (transformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS && totalComponents > caps.maxTransformFeedbackInterleavedComponents) { infoLog.append("Transform feedback varying total components (%u) exceed the maximum interleaved components (%u).", - totalComponents, maxInterleavedComponents); + totalComponents, caps.maxTransformFeedbackInterleavedComponents); return false; } return true; } -void ProgramBinary::defineUniformBlockMembers(const std::vector &fields, const std::string &prefix, int blockIndex, BlockInfoItr *blockInfoItr, std::vector *blockUniformIndexes) +template +void ProgramBinary::defineUniformBlockMembers(const std::vector &fields, const std::string &prefix, int blockIndex, + sh::BlockLayoutEncoder *encoder, std::vector *blockUniformIndexes, + bool inRowMajorLayout) { for (unsigned int uniformIndex = 0; uniformIndex < fields.size(); uniformIndex++) { - const gl::InterfaceBlockField &field = fields[uniformIndex]; + const VarT &field = fields[uniformIndex]; const std::string &fieldName = (prefix.empty() ? field.name : prefix + "." + field.name); - if (!field.fields.empty()) + if (field.isStruct()) { - if (field.arraySize > 0) + bool rowMajorLayout = (inRowMajorLayout || IsRowMajorLayout(field)); + + for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++) { - for (unsigned int arrayElement = 0; arrayElement < field.arraySize; arrayElement++) - { - const std::string uniformElementName = fieldName + ArrayString(arrayElement); - defineUniformBlockMembers(field.fields, uniformElementName, blockIndex, blockInfoItr, blockUniformIndexes); - } - } - else - { - defineUniformBlockMembers(field.fields, fieldName, blockIndex, blockInfoItr, blockUniformIndexes); + encoder->enterAggregateType(); + + const std::string uniformElementName = fieldName + (field.isArray() ? ArrayString(arrayElement) : ""); + defineUniformBlockMembers(field.fields, uniformElementName, blockIndex, encoder, blockUniformIndexes, rowMajorLayout); + + encoder->exitAggregateType(); } } else { + bool isRowMajorMatrix = (IsMatrixType(field.type) && inRowMajorLayout); + + sh::BlockMemberInfo memberInfo = encoder->encodeType(field.type, field.arraySize, isRowMajorMatrix); + LinkedUniform *newUniform = new LinkedUniform(field.type, field.precision, fieldName, field.arraySize, - blockIndex, **blockInfoItr); + blockIndex, memberInfo); // add to uniform list, but not index, since uniform block uniforms have no location blockUniformIndexes->push_back(mUniforms.size()); mUniforms.push_back(newUniform); - (*blockInfoItr)++; } } } -bool ProgramBinary::defineUniformBlock(InfoLog &infoLog, GLenum shader, const gl::InterfaceBlock &interfaceBlock) +bool ProgramBinary::defineUniformBlock(InfoLog &infoLog, const Shader &shader, const sh::InterfaceBlock &interfaceBlock, const Caps &caps) { + const rx::ShaderD3D* shaderD3D = rx::ShaderD3D::makeShaderD3D(shader.getImplementation()); + // create uniform block entries if they do not exist if (getUniformBlockIndex(interfaceBlock.name) == GL_INVALID_INDEX) { @@ -2192,22 +2328,35 @@ bool ProgramBinary::defineUniformBlock(InfoLog &infoLog, GLenum shader, const gl const unsigned int blockIndex = mUniformBlocks.size(); // define member uniforms - BlockInfoItr blockInfoItr = interfaceBlock.blockInfo.cbegin(); - defineUniformBlockMembers(interfaceBlock.fields, "", blockIndex, &blockInfoItr, &blockUniformIndexes); + sh::BlockLayoutEncoder *encoder = NULL; + + if (interfaceBlock.layout == sh::BLOCKLAYOUT_STANDARD) + { + encoder = new sh::Std140BlockEncoder; + } + else + { + encoder = new sh::HLSLBlockEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED); + } + ASSERT(encoder); + + defineUniformBlockMembers(interfaceBlock.fields, "", blockIndex, encoder, &blockUniformIndexes, interfaceBlock.isRowMajorLayout); + + size_t dataSize = encoder->getBlockSize(); // create all the uniform blocks if (interfaceBlock.arraySize > 0) { for (unsigned int uniformBlockElement = 0; uniformBlockElement < interfaceBlock.arraySize; uniformBlockElement++) { - gl::UniformBlock *newUniformBlock = new UniformBlock(interfaceBlock.name, uniformBlockElement, interfaceBlock.dataSize); + UniformBlock *newUniformBlock = new UniformBlock(interfaceBlock.name, uniformBlockElement, dataSize); newUniformBlock->memberUniformIndexes = blockUniformIndexes; mUniformBlocks.push_back(newUniformBlock); } } else { - gl::UniformBlock *newUniformBlock = new UniformBlock(interfaceBlock.name, GL_INVALID_INDEX, interfaceBlock.dataSize); + UniformBlock *newUniformBlock = new UniformBlock(interfaceBlock.name, GL_INVALID_INDEX, dataSize); newUniformBlock->memberUniformIndexes = blockUniformIndexes; mUniformBlocks.push_back(newUniformBlock); } @@ -2219,12 +2368,15 @@ bool ProgramBinary::defineUniformBlock(InfoLog &infoLog, GLenum shader, const gl ASSERT(blockIndex != GL_INVALID_INDEX); ASSERT(blockIndex + elementCount <= mUniformBlocks.size()); + unsigned int interfaceBlockRegister = shaderD3D->getInterfaceBlockRegister(interfaceBlock.name); + for (unsigned int uniformBlockElement = 0; uniformBlockElement < elementCount; uniformBlockElement++) { - gl::UniformBlock *uniformBlock = mUniformBlocks[blockIndex + uniformBlockElement]; + UniformBlock *uniformBlock = mUniformBlocks[blockIndex + uniformBlockElement]; ASSERT(uniformBlock->name == interfaceBlock.name); - if (!assignUniformBlockRegister(infoLog, uniformBlock, shader, interfaceBlock.registerIndex + uniformBlockElement)) + if (!assignUniformBlockRegister(infoLog, uniformBlock, shader.getType(), + interfaceBlockRegister + uniformBlockElement, caps)) { return false; } @@ -2233,27 +2385,23 @@ bool ProgramBinary::defineUniformBlock(InfoLog &infoLog, GLenum shader, const gl return true; } -bool ProgramBinary::assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex) +bool ProgramBinary::assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex, const Caps &caps) { if (shader == GL_VERTEX_SHADER) { uniformBlock->vsRegisterIndex = registerIndex; - unsigned int maximumBlocks = mRenderer->getMaxVertexShaderUniformBuffers(); - - if (registerIndex - mRenderer->getReservedVertexUniformBuffers() >= maximumBlocks) + if (registerIndex - mRenderer->getReservedVertexUniformBuffers() >= caps.maxVertexUniformBlocks) { - infoLog.append("Vertex shader uniform block count exceed GL_MAX_VERTEX_UNIFORM_BLOCKS (%u)", maximumBlocks); + infoLog.append("Vertex shader uniform block count exceed GL_MAX_VERTEX_UNIFORM_BLOCKS (%u)", caps.maxVertexUniformBlocks); return false; } } else if (shader == GL_FRAGMENT_SHADER) { uniformBlock->psRegisterIndex = registerIndex; - unsigned int maximumBlocks = mRenderer->getMaxFragmentShaderUniformBuffers(); - - if (registerIndex - mRenderer->getReservedFragmentUniformBuffers() >= maximumBlocks) + if (registerIndex - mRenderer->getReservedFragmentUniformBuffers() >= caps.maxFragmentUniformBlocks) { - infoLog.append("Fragment shader uniform block count exceed GL_MAX_FRAGMENT_UNIFORM_BLOCKS (%u)", maximumBlocks); + infoLog.append("Fragment shader uniform block count exceed GL_MAX_FRAGMENT_UNIFORM_BLOCKS (%u)", caps.maxFragmentUniformBlocks); return false; } } @@ -2423,6 +2571,19 @@ LinkedUniform *ProgramBinary::getUniformByLocation(GLint location) const return mUniforms[mUniformIndex[location].index]; } +LinkedUniform *ProgramBinary::getUniformByName(const std::string &name) const +{ + for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) + { + if (mUniforms[uniformIndex]->name == name) + { + return mUniforms[uniformIndex]; + } + } + + return NULL; +} + void ProgramBinary::getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const { ASSERT(uniformBlockIndex < mUniformBlocks.size()); // index must be smaller than getActiveUniformBlockCount() @@ -2510,10 +2671,10 @@ GLuint ProgramBinary::getActiveUniformBlockMaxLength() const return maxLength; } -void ProgramBinary::validate(InfoLog &infoLog) +void ProgramBinary::validate(InfoLog &infoLog, const Caps &caps) { applyUniforms(); - if (!validateSamplers(&infoLog)) + if (!validateSamplers(&infoLog, caps)) { mValidated = false; } @@ -2523,13 +2684,14 @@ void ProgramBinary::validate(InfoLog &infoLog) } } -bool ProgramBinary::validateSamplers(InfoLog *infoLog) +bool ProgramBinary::validateSamplers(InfoLog *infoLog, const Caps &caps) { // if any two active samplers in a program are of different types, but refer to the same // texture image unit, and this is the current program, then ValidateProgram will fail, and // DrawArrays and DrawElements will issue the INVALID_OPERATION error. + updateSamplerMapping(); - const unsigned int maxCombinedTextureImageUnits = mRenderer->getMaxCombinedTextureImageUnits(); + const unsigned int maxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits; TextureType textureUnitType[IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS]; for (unsigned int i = 0; i < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS; ++i) @@ -2684,4 +2846,45 @@ void ProgramBinary::initializeUniformStorage() mFragmentUniformStorage = mRenderer->createUniformStorage(fragmentRegisters * 16u); } +void ProgramBinary::reset() +{ + mVertexHLSL.clear(); + mVertexWorkarounds = rx::ANGLE_D3D_WORKAROUND_NONE; + SafeDeleteContainer(mVertexExecutables); + + mPixelHLSL.clear(); + mPixelWorkarounds = rx::ANGLE_D3D_WORKAROUND_NONE; + mUsesFragDepth = false; + mPixelShaderKey.clear(); + SafeDeleteContainer(mPixelExecutables); + + SafeDelete(mGeometryExecutable); + + mTransformFeedbackBufferMode = GL_NONE; + mTransformFeedbackLinkedVaryings.clear(); + + for (size_t i = 0; i < ArraySize(mSamplersPS); i++) + { + mSamplersPS[i] = Sampler(); + } + for (size_t i = 0; i < ArraySize(mSamplersVS); i++) + { + mSamplersVS[i] = Sampler(); + } + mUsedVertexSamplerRange = 0; + mUsedPixelSamplerRange = 0; + mUsesPointSize = false; + mShaderVersion = 0; + mDirtySamplerMapping = true; + + SafeDeleteContainer(mUniforms); + SafeDeleteContainer(mUniformBlocks); + mUniformIndex.clear(); + mOutputVariables.clear(); + SafeDelete(mVertexUniformStorage); + SafeDelete(mFragmentUniformStorage); + + mValidated = false; +} + } diff --git a/gfx/angle/src/libGLESv2/ProgramBinary.h b/gfx/angle/src/libGLESv2/ProgramBinary.h index 839923b68c2f..246bd160b87c 100644 --- a/gfx/angle/src/libGLESv2/ProgramBinary.h +++ b/gfx/angle/src/libGLESv2/ProgramBinary.h @@ -10,21 +10,31 @@ #ifndef LIBGLESV2_PROGRAM_BINARY_H_ #define LIBGLESV2_PROGRAM_BINARY_H_ -#include -#include -#include -#include - -#include -#include - #include "common/RefCountObject.h" #include "angletypes.h" #include "common/mathutil.h" #include "libGLESv2/Uniform.h" #include "libGLESv2/Shader.h" #include "libGLESv2/Constants.h" -#include "libGLESv2/renderer/VertexDataManager.h" +#include "libGLESv2/renderer/d3d/VertexDataManager.h" +#include "libGLESv2/renderer/d3d/DynamicHLSL.h" + +#include "angle_gl.h" + +#include +#include + +namespace sh +{ +class HLSLBlockEncoder; +} + +#include +#include +#include + +#include +#include namespace rx { @@ -32,16 +42,16 @@ class ShaderExecutable; class Renderer; struct TranslatedAttribute; class UniformStorage; -class DynamicHLSL; } namespace gl { -class FragmentShader; -class VertexShader; +struct Caps; +class Shader; class InfoLog; class AttributeBindings; class Buffer; +class Framebuffer; // Struct used for correlating uniforms/elements of uniform arrays to handles struct VariableLocation @@ -82,14 +92,15 @@ class ProgramBinary : public RefCountObject explicit ProgramBinary(rx::Renderer *renderer); ~ProgramBinary(); - rx::ShaderExecutable *getPixelExecutable() const; + rx::ShaderExecutable *getPixelExecutableForFramebuffer(const Framebuffer *fbo); + rx::ShaderExecutable *getPixelExecutableForOutputLayout(const std::vector &outputLayout); rx::ShaderExecutable *getVertexExecutableForInputLayout(const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS]); rx::ShaderExecutable *getGeometryExecutable() const; GLuint getAttributeLocation(const char *name); int getSemanticIndex(int attributeIndex); - GLint getSamplerMapping(SamplerType type, unsigned int samplerIndex); + GLint getSamplerMapping(SamplerType type, unsigned int samplerIndex, const Caps &caps); TextureType getSamplerTextureType(SamplerType type, unsigned int samplerIndex); GLint getUsedSamplerRange(SamplerType type); bool usesPointSize() const; @@ -121,20 +132,20 @@ class ProgramBinary : public RefCountObject void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); void setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); - bool getUniformfv(GLint location, GLsizei *bufSize, GLfloat *params); - bool getUniformiv(GLint location, GLsizei *bufSize, GLint *params); - bool getUniformuiv(GLint location, GLsizei *bufSize, GLuint *params); + void getUniformfv(GLint location, GLfloat *params); + void getUniformiv(GLint location, GLint *params); + void getUniformuiv(GLint location, GLuint *params); void dirtyAllUniforms(); void applyUniforms(); - bool applyUniformBuffers(const std::vector boundBuffers); + bool applyUniformBuffers(const std::vector boundBuffers, const Caps &caps); - bool load(InfoLog &infoLog, const void *binary, GLsizei length); - bool save(void* binary, GLsizei bufSize, GLsizei *length); + bool load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length); + bool save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length); GLint getLength(); - bool link(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader, - const std::vector& transformFeedbackVaryings, GLenum transformFeedbackBufferMode); + bool link(InfoLog &infoLog, const AttributeBindings &attributeBindings, Shader *fragmentShader, Shader *vertexShader, + const std::vector& transformFeedbackVaryings, GLenum transformFeedbackBufferMode, const Caps &caps); void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders); void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const; @@ -147,6 +158,7 @@ class ProgramBinary : public RefCountObject GLint getActiveUniformi(GLuint index, GLenum pname) const; bool isValidUniformLocation(GLint location) const; LinkedUniform *getUniformByLocation(GLint location) const; + LinkedUniform *getUniformByName(const std::string &name) const; void getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const; void getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const; @@ -160,9 +172,10 @@ class ProgramBinary : public RefCountObject const LinkedVarying &getTransformFeedbackVarying(size_t idx) const; GLenum getTransformFeedbackBufferMode() const; - void validate(InfoLog &infoLog); - bool validateSamplers(InfoLog *infoLog); + void validate(InfoLog &infoLog, const Caps &caps); + bool validateSamplers(InfoLog *infoLog, const Caps &caps); bool isValidated() const; + void updateSamplerMapping(); unsigned int getSerial() const; int getShaderVersion() const; @@ -177,30 +190,50 @@ class ProgramBinary : public RefCountObject private: DISALLOW_COPY_AND_ASSIGN(ProgramBinary); - bool linkVaryings(InfoLog &infoLog, FragmentShader *fragmentShader, VertexShader *vertexShader); - bool linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader); + struct Sampler + { + Sampler(); - typedef std::vector::const_iterator BlockInfoItr; + bool active; + GLint logicalTextureUnit; + TextureType textureType; + }; - template - bool linkValidateFields(InfoLog &infoLog, const std::string &varName, const ShaderVarType &vertexVar, const ShaderVarType &fragmentVar); - bool linkValidateVariablesBase(InfoLog &infoLog, const std::string &variableName, const ShaderVariable &vertexVariable, const ShaderVariable &fragmentVariable, bool validatePrecision); + void reset(); - bool linkValidateVariables(InfoLog &infoLog, const std::string &uniformName, const Uniform &vertexUniform, const Uniform &fragmentUniform); - bool linkValidateVariables(InfoLog &infoLog, const std::string &varyingName, const Varying &vertexVarying, const Varying &fragmentVarying); - bool linkValidateVariables(InfoLog &infoLog, const std::string &uniformName, const InterfaceBlockField &vertexUniform, const InterfaceBlockField &fragmentUniform); - bool linkUniforms(InfoLog &infoLog, const std::vector &vertexUniforms, const std::vector &fragmentUniforms); - bool defineUniform(GLenum shader, const Uniform &constant, InfoLog &infoLog); - bool areMatchingInterfaceBlocks(InfoLog &infoLog, const InterfaceBlock &vertexInterfaceBlock, const InterfaceBlock &fragmentInterfaceBlock); - bool linkUniformBlocks(InfoLog &infoLog, const std::vector &vertexUniformBlocks, const std::vector &fragmentUniformBlocks); + bool linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shader *vertexShader); + bool linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, Shader *fragmentShader, Shader *vertexShader); + + bool linkValidateVariablesBase(InfoLog &infoLog, + const std::string &variableName, + const sh::ShaderVariable &vertexVariable, + const sh::ShaderVariable &fragmentVariable, + bool validatePrecision); + + bool linkValidateUniforms(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform); + bool linkValidateVaryings(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying); + bool linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform); + bool linkUniforms(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps); + void defineUniformBase(GLenum shader, const sh::Uniform &uniform, unsigned int uniformRegister); + void defineUniform(GLenum shader, const sh::ShaderVariable &uniform, const std::string &fullName, sh::HLSLBlockEncoder *encoder); + bool indexSamplerUniform(const LinkedUniform &uniform, InfoLog &infoLog, const Caps &caps); + bool indexUniforms(InfoLog &infoLog, const Caps &caps); + static bool assignSamplers(unsigned int startSamplerIndex, GLenum samplerType, unsigned int samplerCount, + Sampler *outArray, GLuint *usedRange, unsigned int limit); + bool areMatchingInterfaceBlocks(InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock, const sh::InterfaceBlock &fragmentInterfaceBlock); + bool linkUniformBlocks(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps); bool gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, const std::vector &linkedVaryings, const std::vector &transformFeedbackVaryingNames, GLenum transformFeedbackBufferMode, - std::vector *outTransformFeedbackLinkedVaryings) const; - void defineUniformBlockMembers(const std::vector &fields, const std::string &prefix, int blockIndex, BlockInfoItr *blockInfoItr, std::vector *blockUniformIndexes); - bool defineUniformBlock(InfoLog &infoLog, GLenum shader, const InterfaceBlock &interfaceBlock); - bool assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex); - void defineOutputVariables(FragmentShader *fragmentShader); + std::vector *outTransformFeedbackLinkedVaryings, + const Caps &caps) const; + template + void defineUniformBlockMembers(const std::vector &fields, const std::string &prefix, int blockIndex, + sh::BlockLayoutEncoder *encoder, std::vector *blockUniformIndexes, + bool inRowMajorLayout); + bool defineUniformBlock(InfoLog &infoLog, const Shader &shader, const sh::InterfaceBlock &interfaceBlock, const Caps &caps); + bool assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex, const Caps &caps); + void defineOutputVariables(Shader *fragmentShader); void initializeUniformStorage(); template @@ -210,15 +243,12 @@ class ProgramBinary : public RefCountObject void setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum targetUniformType); template - bool getUniformv(GLint location, GLsizei *bufSize, T *params, GLenum uniformType); - - static TextureType getTextureType(GLenum samplerType, InfoLog &infoLog); + void getUniformv(GLint location, T *params, GLenum uniformType); class VertexExecutable { public: - VertexExecutable(rx::Renderer *const renderer, - const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS], + VertexExecutable(const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS], const GLenum signature[MAX_VERTEX_ATTRIBS], rx::ShaderExecutable *shaderExecutable); ~VertexExecutable(); @@ -235,38 +265,53 @@ class ProgramBinary : public RefCountObject rx::ShaderExecutable *mShaderExecutable; }; + class PixelExecutable + { + public: + PixelExecutable(const std::vector &outputSignature, rx::ShaderExecutable *shaderExecutable); + ~PixelExecutable(); + + // FIXME(geofflang): Work around NVIDIA driver bug by repacking buffers + bool matchesSignature(const std::vector &signature) const { return true; /* mOutputSignature == signature; */ } + + const std::vector &outputSignature() const { return mOutputSignature; } + rx::ShaderExecutable *shaderExecutable() const { return mShaderExecutable; } + + private: + std::vector mOutputSignature; + rx::ShaderExecutable *mShaderExecutable; + }; + rx::Renderer *const mRenderer; - DynamicHLSL *mDynamicHLSL; + rx::DynamicHLSL *mDynamicHLSL; std::string mVertexHLSL; rx::D3DWorkaroundType mVertexWorkarounds; std::vector mVertexExecutables; - rx::ShaderExecutable *mGeometryExecutable; - rx::ShaderExecutable *mPixelExecutable; - Attribute mLinkedAttribute[MAX_VERTEX_ATTRIBS]; - Attribute mShaderAttributes[MAX_VERTEX_ATTRIBS]; + std::string mPixelHLSL; + rx::D3DWorkaroundType mPixelWorkarounds; + bool mUsesFragDepth; + std::vector mPixelShaderKey; + std::vector mPixelExecutables; + + rx::ShaderExecutable *mGeometryExecutable; + + sh::Attribute mLinkedAttribute[MAX_VERTEX_ATTRIBS]; + sh::Attribute mShaderAttributes[MAX_VERTEX_ATTRIBS]; int mSemanticIndex[MAX_VERTEX_ATTRIBS]; int mAttributesByLayout[MAX_VERTEX_ATTRIBS]; GLenum mTransformFeedbackBufferMode; std::vector mTransformFeedbackLinkedVaryings; - struct Sampler - { - Sampler(); - - bool active; - GLint logicalTextureUnit; - TextureType textureType; - }; - Sampler mSamplersPS[MAX_TEXTURE_IMAGE_UNITS]; Sampler mSamplersVS[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; GLuint mUsedVertexSamplerRange; GLuint mUsedPixelSamplerRange; bool mUsesPointSize; int mShaderVersion; + bool mDirtySamplerMapping; std::vector mUniforms; std::vector mUniformBlocks; diff --git a/gfx/angle/src/libGLESv2/Query.cpp b/gfx/angle/src/libGLESv2/Query.cpp index 6546d06c34c8..a99461e7dd77 100644 --- a/gfx/angle/src/libGLESv2/Query.cpp +++ b/gfx/angle/src/libGLESv2/Query.cpp @@ -1,4 +1,3 @@ -#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 @@ -9,14 +8,13 @@ #include "libGLESv2/Query.h" #include "libGLESv2/renderer/QueryImpl.h" -#include "libGLESv2/renderer/Renderer.h" namespace gl { - -Query::Query(rx::Renderer *renderer, GLenum type, GLuint id) : RefCountObject(id) -{ - mQuery = renderer->createQuery(type); +Query::Query(rx::QueryImpl *impl, GLuint id) + : RefCountObject(id), + mQuery(impl) +{ } Query::~Query() @@ -26,7 +24,11 @@ Query::~Query() void Query::begin() { - mQuery->begin(); + // TODO: Rather than keeping track of whether the query was successfully + // created via a boolean in the GL-level Query object, we should probably + // use the error system to track these failed creations at the context level, + // and reset the active query ID for the target to 0 upon failure. + mStarted = mQuery->begin(); } void Query::end() @@ -51,7 +53,7 @@ GLenum Query::getType() const bool Query::isStarted() const { - return mQuery->isStarted(); + return mStarted; } } diff --git a/gfx/angle/src/libGLESv2/Query.h b/gfx/angle/src/libGLESv2/Query.h index 4eb236f1041c..b98a78e534b9 100644 --- a/gfx/angle/src/libGLESv2/Query.h +++ b/gfx/angle/src/libGLESv2/Query.h @@ -9,15 +9,13 @@ #ifndef LIBGLESV2_QUERY_H_ #define LIBGLESV2_QUERY_H_ -#include -#include - #include "common/angleutils.h" #include "common/RefCountObject.h" +#include "angle_gl.h" + namespace rx { -class Renderer; class QueryImpl; } @@ -27,7 +25,7 @@ namespace gl class Query : public RefCountObject { public: - Query(rx::Renderer *renderer, GLenum type, GLuint id); + Query(rx::QueryImpl *impl, GLuint id); virtual ~Query(); void begin(); @@ -42,6 +40,8 @@ class Query : public RefCountObject private: DISALLOW_COPY_AND_ASSIGN(Query); + bool mStarted; + rx::QueryImpl *mQuery; }; diff --git a/gfx/angle/src/libGLESv2/Renderbuffer.cpp b/gfx/angle/src/libGLESv2/Renderbuffer.cpp index ea3f40bd00bf..16ee775171b2 100644 --- a/gfx/angle/src/libGLESv2/Renderbuffer.cpp +++ b/gfx/angle/src/libGLESv2/Renderbuffer.cpp @@ -1,4 +1,3 @@ -#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 @@ -10,525 +9,102 @@ // objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108. #include "libGLESv2/Renderbuffer.h" +#include "libGLESv2/Texture.h" +#include "libGLESv2/formatutils.h" +#include "libGLESv2/FramebufferAttachment.h" +#include "libGLESv2/renderer/Renderer.h" #include "libGLESv2/renderer/RenderTarget.h" -#include "libGLESv2/Texture.h" -#include "libGLESv2/renderer/Renderer.h" -#include "libGLESv2/renderer/TextureStorage.h" #include "common/utilities.h" -#include "libGLESv2/formatutils.h" namespace gl { unsigned int RenderbufferStorage::mCurrentSerial = 1; -RenderbufferInterface::RenderbufferInterface() +Renderbuffer::Renderbuffer(GLuint id, RenderbufferStorage *newStorage) + : RefCountObject(id), + mStorage(newStorage) { -} - -// The default case for classes inherited from RenderbufferInterface is not to -// need to do anything upon the reference count to the parent Renderbuffer incrementing -// or decrementing. -void RenderbufferInterface::addProxyRef(const Renderbuffer *proxy) -{ -} - -void RenderbufferInterface::releaseProxy(const Renderbuffer *proxy) -{ -} - -///// RenderbufferTexture2D Implementation //////// - -RenderbufferTexture2D::RenderbufferTexture2D(Texture2D *texture, GLint level) : mLevel(level) -{ - mTexture2D.set(texture); -} - -RenderbufferTexture2D::~RenderbufferTexture2D() -{ - mTexture2D.set(NULL); -} - -// Textures need to maintain their own reference count for references via -// Renderbuffers acting as proxies. Here, we notify the texture of a reference. -void RenderbufferTexture2D::addProxyRef(const Renderbuffer *proxy) -{ - mTexture2D->addProxyRef(proxy); -} - -void RenderbufferTexture2D::releaseProxy(const Renderbuffer *proxy) -{ - mTexture2D->releaseProxy(proxy); -} - -rx::RenderTarget *RenderbufferTexture2D::getRenderTarget() -{ - return mTexture2D->getRenderTarget(mLevel); -} - -rx::RenderTarget *RenderbufferTexture2D::getDepthStencil() -{ - return mTexture2D->getDepthSencil(mLevel); -} - -rx::TextureStorage *RenderbufferTexture2D::getTextureStorage() -{ - return mTexture2D->getNativeTexture()->getStorageInstance(); -} - -GLsizei RenderbufferTexture2D::getWidth() const -{ - return mTexture2D->getWidth(mLevel); -} - -GLsizei RenderbufferTexture2D::getHeight() const -{ - return mTexture2D->getHeight(mLevel); -} - -GLenum RenderbufferTexture2D::getInternalFormat() const -{ - return mTexture2D->getInternalFormat(mLevel); -} - -GLenum RenderbufferTexture2D::getActualFormat() const -{ - return mTexture2D->getActualFormat(mLevel); -} - -GLsizei RenderbufferTexture2D::getSamples() const -{ - return 0; -} - -unsigned int RenderbufferTexture2D::getSerial() const -{ - return mTexture2D->getRenderTargetSerial(mLevel); -} - -bool RenderbufferTexture2D::isTexture() const -{ - return true; -} - -unsigned int RenderbufferTexture2D::getTextureSerial() const -{ - return mTexture2D->getTextureSerial(); -} - -///// RenderbufferTextureCubeMap Implementation //////// - -RenderbufferTextureCubeMap::RenderbufferTextureCubeMap(TextureCubeMap *texture, GLenum faceTarget, GLint level) - : mFaceTarget(faceTarget), mLevel(level) -{ - mTextureCubeMap.set(texture); -} - -RenderbufferTextureCubeMap::~RenderbufferTextureCubeMap() -{ - mTextureCubeMap.set(NULL); -} - -// Textures need to maintain their own reference count for references via -// Renderbuffers acting as proxies. Here, we notify the texture of a reference. -void RenderbufferTextureCubeMap::addProxyRef(const Renderbuffer *proxy) -{ - mTextureCubeMap->addProxyRef(proxy); -} - -void RenderbufferTextureCubeMap::releaseProxy(const Renderbuffer *proxy) -{ - mTextureCubeMap->releaseProxy(proxy); -} - -rx::RenderTarget *RenderbufferTextureCubeMap::getRenderTarget() -{ - return mTextureCubeMap->getRenderTarget(mFaceTarget, mLevel); -} - -rx::RenderTarget *RenderbufferTextureCubeMap::getDepthStencil() -{ - return mTextureCubeMap->getDepthStencil(mFaceTarget, mLevel); -} - -rx::TextureStorage *RenderbufferTextureCubeMap::getTextureStorage() -{ - return mTextureCubeMap->getNativeTexture()->getStorageInstance(); -} - -GLsizei RenderbufferTextureCubeMap::getWidth() const -{ - return mTextureCubeMap->getWidth(mFaceTarget, mLevel); -} - -GLsizei RenderbufferTextureCubeMap::getHeight() const -{ - return mTextureCubeMap->getHeight(mFaceTarget, mLevel); -} - -GLenum RenderbufferTextureCubeMap::getInternalFormat() const -{ - return mTextureCubeMap->getInternalFormat(mFaceTarget, mLevel); -} - -GLenum RenderbufferTextureCubeMap::getActualFormat() const -{ - return mTextureCubeMap->getActualFormat(mFaceTarget, mLevel); -} - -GLsizei RenderbufferTextureCubeMap::getSamples() const -{ - return 0; -} - -unsigned int RenderbufferTextureCubeMap::getSerial() const -{ - return mTextureCubeMap->getRenderTargetSerial(mFaceTarget, mLevel); -} - -bool RenderbufferTextureCubeMap::isTexture() const -{ - return true; -} - -unsigned int RenderbufferTextureCubeMap::getTextureSerial() const -{ - return mTextureCubeMap->getTextureSerial(); -} - -///// RenderbufferTexture3DLayer Implementation //////// - -RenderbufferTexture3DLayer::RenderbufferTexture3DLayer(Texture3D *texture, GLint level, GLint layer) - : mLevel(level), mLayer(layer) -{ - mTexture3D.set(texture); -} - -RenderbufferTexture3DLayer::~RenderbufferTexture3DLayer() -{ - mTexture3D.set(NULL); -} - -// Textures need to maintain their own reference count for references via -// Renderbuffers acting as proxies. Here, we notify the texture of a reference. -void RenderbufferTexture3DLayer::addProxyRef(const Renderbuffer *proxy) -{ - mTexture3D->addProxyRef(proxy); -} - -void RenderbufferTexture3DLayer::releaseProxy(const Renderbuffer *proxy) -{ - mTexture3D->releaseProxy(proxy); -} - -rx::RenderTarget *RenderbufferTexture3DLayer::getRenderTarget() -{ - return mTexture3D->getRenderTarget(mLevel, mLayer); -} - -rx::RenderTarget *RenderbufferTexture3DLayer::getDepthStencil() -{ - return mTexture3D->getDepthStencil(mLevel, mLayer); -} - -rx::TextureStorage *RenderbufferTexture3DLayer::getTextureStorage() -{ - return mTexture3D->getNativeTexture()->getStorageInstance(); -} - -GLsizei RenderbufferTexture3DLayer::getWidth() const -{ - return mTexture3D->getWidth(mLevel); -} - -GLsizei RenderbufferTexture3DLayer::getHeight() const -{ - return mTexture3D->getHeight(mLevel); -} - -GLenum RenderbufferTexture3DLayer::getInternalFormat() const -{ - return mTexture3D->getInternalFormat(mLevel); -} - -GLenum RenderbufferTexture3DLayer::getActualFormat() const -{ - return mTexture3D->getActualFormat(mLevel); -} - -GLsizei RenderbufferTexture3DLayer::getSamples() const -{ - return 0; -} - -unsigned int RenderbufferTexture3DLayer::getSerial() const -{ - return mTexture3D->getRenderTargetSerial(mLevel, mLayer); -} - -bool RenderbufferTexture3DLayer::isTexture() const -{ - return true; -} - -unsigned int RenderbufferTexture3DLayer::getTextureSerial() const -{ - return mTexture3D->getTextureSerial(); -} - -////// RenderbufferTexture2DArrayLayer Implementation ////// - -RenderbufferTexture2DArrayLayer::RenderbufferTexture2DArrayLayer(Texture2DArray *texture, GLint level, GLint layer) - : mLevel(level), mLayer(layer) -{ - mTexture2DArray.set(texture); -} - -RenderbufferTexture2DArrayLayer::~RenderbufferTexture2DArrayLayer() -{ - mTexture2DArray.set(NULL); -} - -void RenderbufferTexture2DArrayLayer::addProxyRef(const Renderbuffer *proxy) -{ - mTexture2DArray->addProxyRef(proxy); -} - -void RenderbufferTexture2DArrayLayer::releaseProxy(const Renderbuffer *proxy) -{ - mTexture2DArray->releaseProxy(proxy); -} - -rx::RenderTarget *RenderbufferTexture2DArrayLayer::getRenderTarget() -{ - return mTexture2DArray->getRenderTarget(mLevel, mLayer); -} - -rx::RenderTarget *RenderbufferTexture2DArrayLayer::getDepthStencil() -{ - return mTexture2DArray->getDepthStencil(mLevel, mLayer); -} - -rx::TextureStorage *RenderbufferTexture2DArrayLayer::getTextureStorage() -{ - return mTexture2DArray->getNativeTexture()->getStorageInstance(); -} - -GLsizei RenderbufferTexture2DArrayLayer::getWidth() const -{ - return mTexture2DArray->getWidth(mLevel); -} - -GLsizei RenderbufferTexture2DArrayLayer::getHeight() const -{ - return mTexture2DArray->getHeight(mLevel); -} - -GLenum RenderbufferTexture2DArrayLayer::getInternalFormat() const -{ - return mTexture2DArray->getInternalFormat(mLevel); -} - -GLenum RenderbufferTexture2DArrayLayer::getActualFormat() const -{ - return mTexture2DArray->getActualFormat(mLevel); -} - -GLsizei RenderbufferTexture2DArrayLayer::getSamples() const -{ - return 0; -} - -unsigned int RenderbufferTexture2DArrayLayer::getSerial() const -{ - return mTexture2DArray->getRenderTargetSerial(mLevel, mLayer); -} - -bool RenderbufferTexture2DArrayLayer::isTexture() const -{ - return true; -} - -unsigned int RenderbufferTexture2DArrayLayer::getTextureSerial() const -{ - return mTexture2DArray->getTextureSerial(); -} - -////// Renderbuffer Implementation ////// - -Renderbuffer::Renderbuffer(rx::Renderer *renderer, GLuint id, RenderbufferInterface *instance) : RefCountObject(id) -{ - ASSERT(instance != NULL); - mInstance = instance; - - ASSERT(renderer != NULL); - mRenderer = renderer; + ASSERT(mStorage); } Renderbuffer::~Renderbuffer() { - delete mInstance; -} - -// The RenderbufferInterface contained in this Renderbuffer may need to maintain -// its own reference count, so we pass it on here. -void Renderbuffer::addRef() const -{ - mInstance->addProxyRef(this); - - RefCountObject::addRef(); -} - -void Renderbuffer::release() const -{ - mInstance->releaseProxy(this); - - RefCountObject::release(); -} - -rx::RenderTarget *Renderbuffer::getRenderTarget() -{ - return mInstance->getRenderTarget(); -} - -rx::RenderTarget *Renderbuffer::getDepthStencil() -{ - return mInstance->getDepthStencil(); -} - -rx::TextureStorage *Renderbuffer::getTextureStorage() -{ - return mInstance->getTextureStorage(); -} - -GLsizei Renderbuffer::getWidth() const -{ - return mInstance->getWidth(); -} - -GLsizei Renderbuffer::getHeight() const -{ - return mInstance->getHeight(); -} - -GLenum Renderbuffer::getInternalFormat() const -{ - return mInstance->getInternalFormat(); -} - -GLenum Renderbuffer::getActualFormat() const -{ - return mInstance->getActualFormat(); -} - -GLuint Renderbuffer::getRedSize() const -{ - if (gl::GetRedBits(getInternalFormat(), mRenderer->getCurrentClientVersion()) > 0) - { - return gl::GetRedBits(getActualFormat(), mRenderer->getCurrentClientVersion()); - } - else - { - return 0; - } -} - -GLuint Renderbuffer::getGreenSize() const -{ - if (gl::GetGreenBits(getInternalFormat(), mRenderer->getCurrentClientVersion()) > 0) - { - return gl::GetGreenBits(getActualFormat(), mRenderer->getCurrentClientVersion()); - } - else - { - return 0; - } -} - -GLuint Renderbuffer::getBlueSize() const -{ - if (gl::GetBlueBits(getInternalFormat(), mRenderer->getCurrentClientVersion()) > 0) - { - return gl::GetBlueBits(getActualFormat(), mRenderer->getCurrentClientVersion()); - } - else - { - return 0; - } -} - -GLuint Renderbuffer::getAlphaSize() const -{ - if (gl::GetAlphaBits(getInternalFormat(), mRenderer->getCurrentClientVersion()) > 0) - { - return gl::GetAlphaBits(getActualFormat(), mRenderer->getCurrentClientVersion()); - } - else - { - return 0; - } -} - -GLuint Renderbuffer::getDepthSize() const -{ - if (gl::GetDepthBits(getInternalFormat(), mRenderer->getCurrentClientVersion()) > 0) - { - return gl::GetDepthBits(getActualFormat(), mRenderer->getCurrentClientVersion()); - } - else - { - return 0; - } -} - -GLuint Renderbuffer::getStencilSize() const -{ - if (gl::GetStencilBits(getInternalFormat(), mRenderer->getCurrentClientVersion()) > 0) - { - return gl::GetStencilBits(getActualFormat(), mRenderer->getCurrentClientVersion()); - } - else - { - return 0; - } -} - -GLenum Renderbuffer::getComponentType() const -{ - return gl::GetComponentType(getActualFormat(), mRenderer->getCurrentClientVersion()); -} - -GLenum Renderbuffer::getColorEncoding() const -{ - return gl::GetColorEncoding(getActualFormat(), mRenderer->getCurrentClientVersion()); -} - -GLsizei Renderbuffer::getSamples() const -{ - return mInstance->getSamples(); -} - -unsigned int Renderbuffer::getSerial() const -{ - return mInstance->getSerial(); -} - -bool Renderbuffer::isTexture() const -{ - return mInstance->isTexture(); -} - -unsigned int Renderbuffer::getTextureSerial() const -{ - return mInstance->getTextureSerial(); + SafeDelete(mStorage); } void Renderbuffer::setStorage(RenderbufferStorage *newStorage) { - ASSERT(newStorage != NULL); + ASSERT(newStorage); - delete mInstance; - mInstance = newStorage; + SafeDelete(mStorage); + mStorage = newStorage; +} + +RenderbufferStorage *Renderbuffer::getStorage() +{ + ASSERT(mStorage); + return mStorage; +} + +GLsizei Renderbuffer::getWidth() const +{ + ASSERT(mStorage); + return mStorage->getWidth(); +} + +GLsizei Renderbuffer::getHeight() const +{ + ASSERT(mStorage); + return mStorage->getHeight(); +} + +GLenum Renderbuffer::getInternalFormat() const +{ + ASSERT(mStorage); + return mStorage->getInternalFormat(); +} + +GLenum Renderbuffer::getActualFormat() const +{ + ASSERT(mStorage); + return mStorage->getActualFormat(); +} + +GLsizei Renderbuffer::getSamples() const +{ + ASSERT(mStorage); + return mStorage->getSamples(); +} + +GLuint Renderbuffer::getRedSize() const +{ + return GetInternalFormatInfo(getActualFormat()).redBits; +} + +GLuint Renderbuffer::getGreenSize() const +{ + return GetInternalFormatInfo(getActualFormat()).greenBits; +} + +GLuint Renderbuffer::getBlueSize() const +{ + return GetInternalFormatInfo(getActualFormat()).blueBits; +} + +GLuint Renderbuffer::getAlphaSize() const +{ + return GetInternalFormatInfo(getActualFormat()).alphaBits; +} + +GLuint Renderbuffer::getDepthSize() const +{ + return GetInternalFormatInfo(getActualFormat()).depthBits; +} + +GLuint Renderbuffer::getStencilSize() const +{ + return GetInternalFormatInfo(getActualFormat()).stencilBits; } RenderbufferStorage::RenderbufferStorage() : mSerial(issueSerials(1)) @@ -554,11 +130,6 @@ rx::RenderTarget *RenderbufferStorage::getDepthStencil() return NULL; } -rx::TextureStorage *RenderbufferStorage::getTextureStorage() -{ - return NULL; -} - GLsizei RenderbufferStorage::getWidth() const { return mWidth; @@ -680,7 +251,7 @@ DepthStencilbuffer::~DepthStencilbuffer() } } -rx::RenderTarget *DepthStencilbuffer::getDepthStencil() +rx::RenderTarget *DepthStencilbuffer::getRenderTarget() { return mDepthStencil; } diff --git a/gfx/angle/src/libGLESv2/Renderbuffer.h b/gfx/angle/src/libGLESv2/Renderbuffer.h index 969232b164a9..c23a54a2a902 100644 --- a/gfx/angle/src/libGLESv2/Renderbuffer.h +++ b/gfx/angle/src/libGLESv2/Renderbuffer.h @@ -12,8 +12,7 @@ #ifndef LIBGLESV2_RENDERBUFFER_H_ #define LIBGLESV2_RENDERBUFFER_H_ -#include -#include +#include "angle_gl.h" #include "common/angleutils.h" #include "common/RefCountObject.h" @@ -28,178 +27,43 @@ class TextureStorage; namespace gl { -class Texture2D; -class TextureCubeMap; -class Texture3D; -class Texture2DArray; -class Renderbuffer; -class Colorbuffer; -class DepthStencilbuffer; +class RenderbufferStorage; +class FramebufferAttachment; -class RenderbufferInterface +// A GL renderbuffer object is usually used as a depth or stencil buffer attachment +// for a framebuffer object. The renderbuffer itself is a distinct GL object, see +// FramebufferAttachment and Framebuffer for how they are applied to an FBO via an +// attachment point. + +class Renderbuffer : public RefCountObject { public: - RenderbufferInterface(); + Renderbuffer(GLuint id, RenderbufferStorage *newStorage); + virtual ~Renderbuffer(); - virtual ~RenderbufferInterface() {}; + void setStorage(RenderbufferStorage *newStorage); + RenderbufferStorage *getStorage(); - virtual void addProxyRef(const Renderbuffer *proxy); - virtual void releaseProxy(const Renderbuffer *proxy); - - virtual rx::RenderTarget *getRenderTarget() = 0; - virtual rx::RenderTarget *getDepthStencil() = 0; - virtual rx::TextureStorage *getTextureStorage() = 0; - - virtual GLsizei getWidth() const = 0; - virtual GLsizei getHeight() const = 0; - virtual GLenum getInternalFormat() const = 0; - virtual GLenum getActualFormat() const = 0; - virtual GLsizei getSamples() const = 0; - - virtual unsigned int getSerial() const = 0; - - virtual bool isTexture() const = 0; - virtual unsigned int getTextureSerial() const = 0; + GLsizei getWidth() const; + GLsizei getHeight() const; + GLenum getInternalFormat() const; + GLenum getActualFormat() const; + GLsizei getSamples() const; + GLuint getRedSize() const; + GLuint getGreenSize() const; + GLuint getBlueSize() const; + GLuint getAlphaSize() const; + GLuint getDepthSize() const; + GLuint getStencilSize() const; private: - DISALLOW_COPY_AND_ASSIGN(RenderbufferInterface); -}; - -class RenderbufferTexture2D : public RenderbufferInterface -{ - public: - RenderbufferTexture2D(Texture2D *texture, GLint level); - - virtual ~RenderbufferTexture2D(); - - void addProxyRef(const Renderbuffer *proxy); - void releaseProxy(const Renderbuffer *proxy); - - rx::RenderTarget *getRenderTarget(); - rx::RenderTarget *getDepthStencil(); - rx::TextureStorage *getTextureStorage(); - - virtual GLsizei getWidth() const; - virtual GLsizei getHeight() const; - virtual GLenum getInternalFormat() const; - virtual GLenum getActualFormat() const; - virtual GLsizei getSamples() const; - - virtual unsigned int getSerial() const; - - virtual bool isTexture() const; - virtual unsigned int getTextureSerial() const; - - private: - DISALLOW_COPY_AND_ASSIGN(RenderbufferTexture2D); - - BindingPointer mTexture2D; - const GLint mLevel; -}; - -class RenderbufferTextureCubeMap : public RenderbufferInterface -{ - public: - RenderbufferTextureCubeMap(TextureCubeMap *texture, GLenum faceTarget, GLint level); - - virtual ~RenderbufferTextureCubeMap(); - - void addProxyRef(const Renderbuffer *proxy); - void releaseProxy(const Renderbuffer *proxy); - - rx::RenderTarget *getRenderTarget(); - rx::RenderTarget *getDepthStencil(); - rx::TextureStorage *getTextureStorage(); - - virtual GLsizei getWidth() const; - virtual GLsizei getHeight() const; - virtual GLenum getInternalFormat() const; - virtual GLenum getActualFormat() const; - virtual GLsizei getSamples() const; - - virtual unsigned int getSerial() const; - - virtual bool isTexture() const; - virtual unsigned int getTextureSerial() const; - - private: - DISALLOW_COPY_AND_ASSIGN(RenderbufferTextureCubeMap); - - BindingPointer mTextureCubeMap; - const GLint mLevel; - const GLenum mFaceTarget; -}; - -class RenderbufferTexture3DLayer : public RenderbufferInterface -{ -public: - RenderbufferTexture3DLayer(Texture3D *texture, GLint level, GLint layer); - - virtual ~RenderbufferTexture3DLayer(); - - void addProxyRef(const Renderbuffer *proxy); - void releaseProxy(const Renderbuffer *proxy); - - rx::RenderTarget *getRenderTarget(); - rx::RenderTarget *getDepthStencil(); - rx::TextureStorage *getTextureStorage(); - - virtual GLsizei getWidth() const; - virtual GLsizei getHeight() const; - virtual GLenum getInternalFormat() const; - virtual GLenum getActualFormat() const; - virtual GLsizei getSamples() const; - - virtual unsigned int getSerial() const; - - virtual bool isTexture() const; - virtual unsigned int getTextureSerial() const; - -private: - DISALLOW_COPY_AND_ASSIGN(RenderbufferTexture3DLayer); - - BindingPointer mTexture3D; - const GLint mLevel; - const GLint mLayer; -}; - -class RenderbufferTexture2DArrayLayer : public RenderbufferInterface -{ -public: - RenderbufferTexture2DArrayLayer(Texture2DArray *texture, GLint level, GLint layer); - - virtual ~RenderbufferTexture2DArrayLayer(); - - void addProxyRef(const Renderbuffer *proxy); - void releaseProxy(const Renderbuffer *proxy); - - rx::RenderTarget *getRenderTarget(); - rx::RenderTarget *getDepthStencil(); - rx::TextureStorage *getTextureStorage(); - - virtual GLsizei getWidth() const; - virtual GLsizei getHeight() const; - virtual GLenum getInternalFormat() const; - virtual GLenum getActualFormat() const; - virtual GLsizei getSamples() const; - - virtual unsigned int getSerial() const; - - virtual bool isTexture() const; - virtual unsigned int getTextureSerial() const; - -private: - DISALLOW_COPY_AND_ASSIGN(RenderbufferTexture2DArrayLayer); - - BindingPointer mTexture2DArray; - const GLint mLevel; - const GLint mLayer; + RenderbufferStorage *mStorage; }; // A class derived from RenderbufferStorage is created whenever glRenderbufferStorage // is called. The specific concrete type depends on whether the internal format is // colour depth, stencil or packed depth/stencil. -class RenderbufferStorage : public RenderbufferInterface +class RenderbufferStorage { public: RenderbufferStorage(); @@ -208,7 +72,6 @@ class RenderbufferStorage : public RenderbufferInterface virtual rx::RenderTarget *getRenderTarget(); virtual rx::RenderTarget *getDepthStencil(); - virtual rx::TextureStorage *getTextureStorage(); virtual GLsizei getWidth() const; virtual GLsizei getHeight() const; @@ -238,55 +101,6 @@ class RenderbufferStorage : public RenderbufferInterface static unsigned int mCurrentSerial; }; -// Renderbuffer implements the GL renderbuffer object. -// It's only a proxy for a RenderbufferInterface instance; the internal object -// can change whenever glRenderbufferStorage is called. -class Renderbuffer : public RefCountObject -{ - public: - Renderbuffer(rx::Renderer *renderer, GLuint id, RenderbufferInterface *storage); - - virtual ~Renderbuffer(); - - // These functions from RefCountObject are overloaded here because - // Textures need to maintain their own count of references to them via - // Renderbuffers/RenderbufferTextures. These functions invoke those - // reference counting functions on the RenderbufferInterface. - void addRef() const; - void release() const; - - rx::RenderTarget *getRenderTarget(); - rx::RenderTarget *getDepthStencil(); - rx::TextureStorage *getTextureStorage(); - - GLsizei getWidth() const; - GLsizei getHeight() const; - GLenum getInternalFormat() const; - GLenum getActualFormat() const; - GLuint getRedSize() const; - GLuint getGreenSize() const; - GLuint getBlueSize() const; - GLuint getAlphaSize() const; - GLuint getDepthSize() const; - GLuint getStencilSize() const; - GLenum getComponentType() const; - GLenum getColorEncoding() const; - GLsizei getSamples() const; - - unsigned int getSerial() const; - - bool isTexture() const; - unsigned int getTextureSerial() const; - - void setStorage(RenderbufferStorage *newStorage); - - private: - DISALLOW_COPY_AND_ASSIGN(Renderbuffer); - - rx::Renderer const *mRenderer; - RenderbufferInterface *mInstance; -}; - class Colorbuffer : public RenderbufferStorage { public: @@ -311,7 +125,7 @@ class DepthStencilbuffer : public RenderbufferStorage ~DepthStencilbuffer(); - virtual rx::RenderTarget *getDepthStencil(); + virtual rx::RenderTarget *getRenderTarget(); protected: rx::RenderTarget *mDepthStencil; @@ -341,6 +155,7 @@ class Stencilbuffer : public DepthStencilbuffer private: DISALLOW_COPY_AND_ASSIGN(Stencilbuffer); }; + } #endif // LIBGLESV2_RENDERBUFFER_H_ diff --git a/gfx/angle/src/libGLESv2/RenderbufferProxySet.cpp b/gfx/angle/src/libGLESv2/RenderbufferProxySet.cpp deleted file mode 100644 index 009c7a6b7348..000000000000 --- a/gfx/angle/src/libGLESv2/RenderbufferProxySet.cpp +++ /dev/null @@ -1,87 +0,0 @@ -#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. -// - -// RenderbufferProxySet.cpp: Implements the gl::RenderbufferProxySet, a class for -// maintaining a Texture's weak references to the Renderbuffers that represent it. - -#include "libGLESv2/RenderbufferProxySet.h" -#include "common/debug.h" - -namespace gl -{ - -void RenderbufferProxySet::addRef(const Renderbuffer *proxy) -{ - RefCountMap::iterator i = mRefCountMap.find(proxy); - if (i != mRefCountMap.end()) - { - i->second++; - } -} - -void RenderbufferProxySet::release(const Renderbuffer *proxy) -{ - RefCountMap::iterator i = mRefCountMap.find(proxy); - if (i != mRefCountMap.end()) - { - if (i->second > 0) - { - i->second--; - } - - if (i->second == 0) - { - // Clear the buffer map of references to this Renderbuffer - BufferMap::iterator j = mBufferMap.begin(); - while (j != mBufferMap.end()) - { - if (j->second == proxy) - { - j = mBufferMap.erase(j); - } - else - { - ++j; - } - } - - mRefCountMap.erase(i); - } - } -} - -void RenderbufferProxySet::add(unsigned int mipLevel, unsigned int layer, Renderbuffer *renderBuffer) -{ - if (mRefCountMap.find(renderBuffer) == mRefCountMap.end()) - { - mRefCountMap.insert(std::make_pair(renderBuffer, 0)); - } - - RenderbufferKey key; - key.mipLevel = mipLevel; - key.layer = layer; - if (mBufferMap.find(key) == mBufferMap.end()) - { - mBufferMap.insert(std::make_pair(key, renderBuffer)); - } -} - -Renderbuffer *RenderbufferProxySet::get(unsigned int mipLevel, unsigned int layer) const -{ - RenderbufferKey key; - key.mipLevel = mipLevel; - key.layer = layer; - BufferMap::const_iterator i = mBufferMap.find(key); - return (i != mBufferMap.end()) ? i->second : NULL; -} - -bool RenderbufferProxySet::RenderbufferKey::operator<(const RenderbufferKey &other) const -{ - return (mipLevel != other.mipLevel) ? mipLevel < other.mipLevel : layer < other.layer; -} - -} diff --git a/gfx/angle/src/libGLESv2/RenderbufferProxySet.h b/gfx/angle/src/libGLESv2/RenderbufferProxySet.h deleted file mode 100644 index ae5bf944f07e..000000000000 --- a/gfx/angle/src/libGLESv2/RenderbufferProxySet.h +++ /dev/null @@ -1,46 +0,0 @@ -// -// 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. -// - -// RenderbufferProxySet.h: Defines the gl::RenderbufferProxySet, a class for -// maintaining a Texture's weak references to the Renderbuffers that represent it. - -#ifndef LIBGLESV2_RENDERBUFFERPROXYSET_H_ -#define LIBGLESV2_RENDERBUFFERPROXYSET_H_ - -#include - -namespace gl -{ -class Renderbuffer; - -class RenderbufferProxySet -{ - public: - void addRef(const Renderbuffer *proxy); - void release(const Renderbuffer *proxy); - - void add(unsigned int mipLevel, unsigned int layer, Renderbuffer *renderBuffer); - Renderbuffer *get(unsigned int mipLevel, unsigned int layer) const; - - private: - struct RenderbufferKey - { - unsigned int mipLevel; - unsigned int layer; - - bool operator<(const RenderbufferKey &other) const; - }; - - typedef std::map BufferMap; - BufferMap mBufferMap; - - typedef std::map RefCountMap; - RefCountMap mRefCountMap; -}; - -} - -#endif // LIBGLESV2_RENDERBUFFERPROXYSET_H_ diff --git a/gfx/angle/src/libGLESv2/ResourceManager.cpp b/gfx/angle/src/libGLESv2/ResourceManager.cpp index 97c28cb99134..eccc13997e2a 100644 --- a/gfx/angle/src/libGLESv2/ResourceManager.cpp +++ b/gfx/angle/src/libGLESv2/ResourceManager.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // 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 @@ -17,6 +16,7 @@ #include "libGLESv2/Texture.h" #include "libGLESv2/Sampler.h" #include "libGLESv2/Fence.h" +#include "libGLESv2/renderer/Renderer.h" namespace gl { @@ -92,13 +92,9 @@ GLuint ResourceManager::createShader(GLenum type) { GLuint handle = mProgramShaderHandleAllocator.allocate(); - if (type == GL_VERTEX_SHADER) + if (type == GL_VERTEX_SHADER || type == GL_FRAGMENT_SHADER) { - mShaderMap[handle] = new VertexShader(this, mRenderer, handle); - } - else if (type == GL_FRAGMENT_SHADER) - { - mShaderMap[handle] = new FragmentShader(this, mRenderer, handle); + mShaderMap[handle] = new Shader(this, mRenderer->createShader(type), type, handle); } else UNREACHABLE(); @@ -150,7 +146,9 @@ GLuint ResourceManager::createFenceSync() { GLuint handle = mFenceSyncHandleAllocator.allocate(); - mFenceSyncMap[handle] = new FenceSync(mRenderer, handle); + FenceSync *fenceSync = new FenceSync(mRenderer, handle); + fenceSync->addRef(); + mFenceSyncMap[handle] = fenceSync; return handle; } @@ -362,7 +360,7 @@ void ResourceManager::checkBufferAllocation(unsigned int buffer) { if (buffer != 0 && !getBuffer(buffer)) { - Buffer *bufferObject = new Buffer(mRenderer, buffer); + Buffer *bufferObject = new Buffer(mRenderer->createBuffer(), buffer); mBufferMap[buffer] = bufferObject; bufferObject->addRef(); } @@ -376,19 +374,19 @@ void ResourceManager::checkTextureAllocation(GLuint texture, TextureType type) if (type == TEXTURE_2D) { - textureObject = new Texture2D(mRenderer, texture); + textureObject = new Texture2D(mRenderer->createTexture(GL_TEXTURE_2D), texture); } else if (type == TEXTURE_CUBE) { - textureObject = new TextureCubeMap(mRenderer, texture); + textureObject = new TextureCubeMap(mRenderer->createTexture(GL_TEXTURE_CUBE_MAP), texture); } else if (type == TEXTURE_3D) { - textureObject = new Texture3D(mRenderer, texture); + textureObject = new Texture3D(mRenderer->createTexture(GL_TEXTURE_3D), texture); } else if (type == TEXTURE_2D_ARRAY) { - textureObject = new Texture2DArray(mRenderer, texture); + textureObject = new Texture2DArray(mRenderer->createTexture(GL_TEXTURE_2D_ARRAY), texture); } else { @@ -405,7 +403,7 @@ void ResourceManager::checkRenderbufferAllocation(GLuint renderbuffer) { if (renderbuffer != 0 && !getRenderbuffer(renderbuffer)) { - Renderbuffer *renderbufferObject = new Renderbuffer(mRenderer, renderbuffer, new Colorbuffer(mRenderer, 0, 0, GL_RGBA4, 0)); + Renderbuffer *renderbufferObject = new Renderbuffer(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 85e6b4bc22bf..7ef90d292c36 100644 --- a/gfx/angle/src/libGLESv2/ResourceManager.h +++ b/gfx/angle/src/libGLESv2/ResourceManager.h @@ -10,15 +10,14 @@ #ifndef LIBGLESV2_RESOURCEMANAGER_H_ #define LIBGLESV2_RESOURCEMANAGER_H_ -#include -#include - -#include - #include "common/angleutils.h" #include "libGLESv2/angletypes.h" #include "libGLESv2/HandleAllocator.h" +#include "angle_gl.h" + +#include + namespace rx { class Renderer; diff --git a/gfx/angle/src/libGLESv2/Sampler.cpp b/gfx/angle/src/libGLESv2/Sampler.cpp index ed6e29f89ef6..b906e6555767 100644 --- a/gfx/angle/src/libGLESv2/Sampler.cpp +++ b/gfx/angle/src/libGLESv2/Sampler.cpp @@ -1,4 +1,3 @@ -#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 diff --git a/gfx/angle/src/libGLESv2/Shader.cpp b/gfx/angle/src/libGLESv2/Shader.cpp index 7d0d781093e4..1b4b09c1d75a 100644 --- a/gfx/angle/src/libGLESv2/Shader.cpp +++ b/gfx/angle/src/libGLESv2/Shader.cpp @@ -1,6 +1,5 @@ -#include "precompiled.h" // -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2014 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,27 +9,29 @@ // functionality. [OpenGL ES 2.0.24] section 2.10 page 24 and section 3.8 page 84. #include "libGLESv2/Shader.h" - -#include "GLSLANG/ShaderLang.h" -#include "common/utilities.h" #include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/renderer/ShaderImpl.h" #include "libGLESv2/Constants.h" #include "libGLESv2/ResourceManager.h" +#include "common/utilities.h" + +#include "GLSLANG/ShaderLang.h" + +#include + namespace gl { -void *Shader::mFragmentCompiler = NULL; -void *Shader::mVertexCompiler = NULL; -Shader::Shader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle) - : mHandle(handle), mRenderer(renderer), mResourceManager(manager) +Shader::Shader(ResourceManager *manager, rx::ShaderImpl *impl, GLenum type, GLuint handle) + : mShader(impl), + mType(type), + mHandle(handle), + mResourceManager(manager), + mRefCount(0), + mDeleteStatus(false), + mCompiled(false) { - uncompile(); - initializeCompiler(); - - mRefCount = 0; - mDeleteStatus = false; - mShaderVersion = 100; } Shader::~Shader() @@ -56,7 +57,7 @@ void Shader::setSource(GLsizei count, const char *const *string, const GLint *le int Shader::getInfoLogLength() const { - return mInfoLog.empty() ? 0 : (mInfoLog.length() + 1); + return mShader->getInfoLog().empty() ? 0 : (mShader->getInfoLog().length() + 1); } void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const @@ -65,8 +66,8 @@ void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const if (bufSize > 0) { - index = std::min(bufSize - 1, static_cast(mInfoLog.length())); - memcpy(infoLog, mInfoLog.c_str(), index); + index = std::min(bufSize - 1, static_cast(mShader->getInfoLog().length())); + memcpy(infoLog, mShader->getInfoLog().c_str(), index); infoLog[index] = '\0'; } @@ -84,10 +85,10 @@ int Shader::getSourceLength() const int Shader::getTranslatedSourceLength() const { - return mHlsl.empty() ? 0 : (mHlsl.length() + 1); + return mShader->getTranslatedSource().empty() ? 0 : (mShader->getTranslatedSource().length() + 1); } -void Shader::getSourceImpl(const std::string &source, GLsizei bufSize, GLsizei *length, char *buffer) const +void Shader::getSourceImpl(const std::string &source, GLsizei bufSize, GLsizei *length, char *buffer) { int index = 0; @@ -112,32 +113,12 @@ void Shader::getSource(GLsizei bufSize, GLsizei *length, char *buffer) const void Shader::getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer) const { - getSourceImpl(mHlsl, bufSize, length, buffer); + getSourceImpl(mShader->getTranslatedSource(), bufSize, length, buffer); } -const std::vector &Shader::getUniforms() const +void Shader::compile() { - return mActiveUniforms; -} - -const std::vector &Shader::getInterfaceBlocks() const -{ - return mActiveInterfaceBlocks; -} - -std::vector &Shader::getVaryings() -{ - return mVaryings; -} - -bool Shader::isCompiled() const -{ - return !mHlsl.empty(); -} - -const std::string &Shader::getHLSL() const -{ - return mHlsl; + mCompiled = mShader->compile(mSource); } void Shader::addRef() @@ -170,434 +151,4 @@ void Shader::flagForDeletion() mDeleteStatus = true; } -// Perform a one-time initialization of the shader compiler (or after being destructed by releaseCompiler) -void Shader::initializeCompiler() -{ - if (!mFragmentCompiler) - { - int result = ShInitialize(); - - if (result) - { - ShShaderOutput hlslVersion = (mRenderer->getMajorShaderModel() >= 4) ? SH_HLSL11_OUTPUT : SH_HLSL9_OUTPUT; - - ShBuiltInResources resources; - ShInitBuiltInResources(&resources); - - resources.MaxVertexAttribs = MAX_VERTEX_ATTRIBS; - resources.MaxVertexUniformVectors = mRenderer->getMaxVertexUniformVectors(); - resources.MaxVaryingVectors = mRenderer->getMaxVaryingVectors(); - resources.MaxVertexTextureImageUnits = mRenderer->getMaxVertexTextureImageUnits(); - resources.MaxCombinedTextureImageUnits = mRenderer->getMaxCombinedTextureImageUnits(); - resources.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS; - resources.MaxFragmentUniformVectors = mRenderer->getMaxFragmentUniformVectors(); - resources.MaxDrawBuffers = mRenderer->getMaxRenderTargets(); - resources.OES_standard_derivatives = mRenderer->getDerivativeInstructionSupport(); - resources.EXT_draw_buffers = mRenderer->getMaxRenderTargets() > 1; - resources.EXT_shader_texture_lod = 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 - // GLSL ES 3.0 constants - resources.MaxVertexOutputVectors = mRenderer->getMaxVaryingVectors(); - resources.MaxFragmentInputVectors = mRenderer->getMaxVaryingVectors(); - resources.MinProgramTexelOffset = -8; // D3D10_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE - resources.MaxProgramTexelOffset = 7; // D3D10_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE - - mFragmentCompiler = ShConstructCompiler(SH_FRAGMENT_SHADER, SH_GLES2_SPEC, hlslVersion, &resources); - mVertexCompiler = ShConstructCompiler(SH_VERTEX_SHADER, SH_GLES2_SPEC, hlslVersion, &resources); - } - } -} - -void Shader::releaseCompiler() -{ - ShDestruct(mFragmentCompiler); - ShDestruct(mVertexCompiler); - - mFragmentCompiler = NULL; - mVertexCompiler = NULL; - - ShFinalize(); -} - -void Shader::parseVaryings(void *compiler) -{ - if (!mHlsl.empty()) - { - std::vector *activeVaryings; - ShGetInfoPointer(compiler, SH_ACTIVE_VARYINGS_ARRAY, reinterpret_cast(&activeVaryings)); - - for (size_t varyingIndex = 0; varyingIndex < activeVaryings->size(); varyingIndex++) - { - mVaryings.push_back(PackedVarying((*activeVaryings)[varyingIndex])); - } - - mUsesMultipleRenderTargets = mHlsl.find("GL_USES_MRT") != std::string::npos; - mUsesFragColor = mHlsl.find("GL_USES_FRAG_COLOR") != std::string::npos; - mUsesFragData = mHlsl.find("GL_USES_FRAG_DATA") != std::string::npos; - mUsesFragCoord = mHlsl.find("GL_USES_FRAG_COORD") != std::string::npos; - mUsesFrontFacing = mHlsl.find("GL_USES_FRONT_FACING") != std::string::npos; - mUsesPointSize = mHlsl.find("GL_USES_POINT_SIZE") != std::string::npos; - mUsesPointCoord = mHlsl.find("GL_USES_POINT_COORD") != std::string::npos; - mUsesDepthRange = mHlsl.find("GL_USES_DEPTH_RANGE") != std::string::npos; - mUsesFragDepth = mHlsl.find("GL_USES_FRAG_DEPTH") != std::string::npos; - mUsesDiscardRewriting = mHlsl.find("ANGLE_USES_DISCARD_REWRITING") != std::string::npos; - mUsesNestedBreak = mHlsl.find("ANGLE_USES_NESTED_BREAK") != std::string::npos; - } -} - -void Shader::resetVaryingsRegisterAssignment() -{ - for (unsigned int varyingIndex = 0; varyingIndex < mVaryings.size(); varyingIndex++) - { - mVaryings[varyingIndex].resetRegisterAssignment(); - } -} - -// initialize/clean up previous state -void Shader::uncompile() -{ - // set by compileToHLSL - mHlsl.clear(); - mInfoLog.clear(); - - // set by parseVaryings - mVaryings.clear(); - - mUsesMultipleRenderTargets = false; - mUsesFragColor = false; - mUsesFragData = false; - mUsesFragCoord = false; - mUsesFrontFacing = false; - mUsesPointSize = false; - mUsesPointCoord = false; - mUsesDepthRange = false; - mUsesFragDepth = false; - mShaderVersion = 100; - mUsesDiscardRewriting = false; - mUsesNestedBreak = false; - - mActiveUniforms.clear(); - mActiveInterfaceBlocks.clear(); -} - -void Shader::compileToHLSL(void *compiler) -{ - // ensure the compiler is loaded - initializeCompiler(); - - int compileOptions = SH_OBJECT_CODE; - std::string sourcePath; - if (perfActive()) - { - sourcePath = getTempPath(); - writeFile(sourcePath.c_str(), mSource.c_str(), mSource.length()); - compileOptions |= SH_LINE_DIRECTIVES; - } - - int result; - if (sourcePath.empty()) - { - const char* sourceStrings[] = - { - mSource.c_str(), - }; - - result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions); - } - else - { - const char* sourceStrings[] = - { - sourcePath.c_str(), - mSource.c_str(), - }; - - result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions | SH_SOURCE_PATH); - } - - size_t shaderVersion = 100; - ShGetInfo(compiler, SH_SHADER_VERSION, &shaderVersion); - - mShaderVersion = static_cast(shaderVersion); - - if (shaderVersion == 300 && mRenderer->getCurrentClientVersion() < 3) - { - mInfoLog = "GLSL ES 3.00 is not supported by OpenGL ES 2.0 contexts"; - TRACE("\n%s", mInfoLog.c_str()); - } - else if (result) - { - size_t objCodeLen = 0; - ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &objCodeLen); - - char* outputHLSL = new char[objCodeLen]; - ShGetObjectCode(compiler, outputHLSL); - -#ifdef _DEBUG - std::ostringstream hlslStream; - hlslStream << "// GLSL\n"; - hlslStream << "//\n"; - - size_t curPos = 0; - while (curPos != std::string::npos) - { - size_t nextLine = mSource.find("\n", curPos); - size_t len = (nextLine == std::string::npos) ? std::string::npos : (nextLine - curPos + 1); - - hlslStream << "// " << mSource.substr(curPos, len); - - curPos = (nextLine == std::string::npos) ? std::string::npos : (nextLine + 1); - } - hlslStream << "\n\n"; - hlslStream << outputHLSL; - mHlsl = hlslStream.str(); -#else - mHlsl = outputHLSL; -#endif - - delete[] outputHLSL; - - void *activeUniforms; - ShGetInfoPointer(compiler, SH_ACTIVE_UNIFORMS_ARRAY, &activeUniforms); - mActiveUniforms = *(std::vector*)activeUniforms; - - void *activeInterfaceBlocks; - ShGetInfoPointer(compiler, SH_ACTIVE_INTERFACE_BLOCKS_ARRAY, &activeInterfaceBlocks); - mActiveInterfaceBlocks = *(std::vector*)activeInterfaceBlocks; - } - else - { - size_t infoLogLen = 0; - ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &infoLogLen); - - char* infoLog = new char[infoLogLen]; - ShGetInfoLog(compiler, infoLog); - mInfoLog = infoLog; - - TRACE("\n%s", mInfoLog.c_str()); - } -} - -rx::D3DWorkaroundType Shader::getD3DWorkarounds() const -{ - if (mUsesDiscardRewriting) - { - // ANGLE issue 486: - // Work-around a D3D9 compiler bug that presents itself when using conditional discard, by disabling optimization - return rx::ANGLE_D3D_WORKAROUND_SKIP_OPTIMIZATION; - } - - if (mUsesNestedBreak) - { - // ANGLE issue 603: - // Work-around a D3D9 compiler bug that presents itself when using break in a nested loop, by maximizing optimization - // We want to keep the use of ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION minimal to prevent hangs, so usesDiscard takes precedence - return rx::ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION; - } - - return rx::ANGLE_D3D_WORKAROUND_NONE; -} - -// [OpenGL ES SL 3.00.4] Section 11 p. 120 -// Vertex Outs/Fragment Ins packing priorities -static const GLenum varyingPriorityList[] = -{ - // 1. Arrays of mat4 and mat4 - GL_FLOAT_MAT4, - - // Non-square matrices of type matCxR consume the same space as a square - // matrix of type matN where N is the greater of C and R - GL_FLOAT_MAT3x4, - GL_FLOAT_MAT4x3, - GL_FLOAT_MAT2x4, - GL_FLOAT_MAT4x2, - - // 2. Arrays of mat2 and mat2 (since they occupy full rows) - GL_FLOAT_MAT2, - - // 3. Arrays of vec4 and vec4 - GL_FLOAT_VEC4, - GL_INT_VEC4, - GL_UNSIGNED_INT_VEC4, - - // 4. Arrays of mat3 and mat3 - GL_FLOAT_MAT3, - GL_FLOAT_MAT2x3, - GL_FLOAT_MAT3x2, - - // 5. Arrays of vec3 and vec3 - GL_FLOAT_VEC3, - GL_INT_VEC3, - GL_UNSIGNED_INT_VEC3, - - // 6. Arrays of vec2 and vec2 - GL_FLOAT_VEC2, - GL_INT_VEC2, - GL_UNSIGNED_INT_VEC2, - - // 7. Arrays of float and float - GL_FLOAT, - GL_INT, - GL_UNSIGNED_INT, -}; - -// true if varying x has a higher priority in packing than y -bool Shader::compareVarying(const PackedVarying &x, const PackedVarying &y) -{ - if (x.type == y.type) - { - return x.arraySize > y.arraySize; - } - - // Special case for handling structs: we sort these to the end of the list - if (x.type == GL_STRUCT_ANGLEX) - { - return false; - } - - unsigned int xPriority = GL_INVALID_INDEX; - unsigned int yPriority = GL_INVALID_INDEX; - - for (unsigned int priorityIndex = 0; priorityIndex < ArraySize(varyingPriorityList); priorityIndex++) - { - if (varyingPriorityList[priorityIndex] == x.type) xPriority = priorityIndex; - if (varyingPriorityList[priorityIndex] == y.type) yPriority = priorityIndex; - if (xPriority != GL_INVALID_INDEX && yPriority != GL_INVALID_INDEX) break; - } - - ASSERT(xPriority != GL_INVALID_INDEX && yPriority != GL_INVALID_INDEX); - - return xPriority <= yPriority; -} - -int Shader::getShaderVersion() const -{ - return mShaderVersion; -} - -VertexShader::VertexShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle) - : Shader(manager, renderer, handle) -{ -} - -VertexShader::~VertexShader() -{ -} - -GLenum VertexShader::getType() -{ - return GL_VERTEX_SHADER; -} - -void VertexShader::uncompile() -{ - Shader::uncompile(); - - // set by ParseAttributes - mActiveAttributes.clear(); -} - -void VertexShader::compile() -{ - uncompile(); - - compileToHLSL(mVertexCompiler); - parseAttributes(); - parseVaryings(mVertexCompiler); -} - -int VertexShader::getSemanticIndex(const std::string &attributeName) -{ - if (!attributeName.empty()) - { - int semanticIndex = 0; - for (unsigned int attributeIndex = 0; attributeIndex < mActiveAttributes.size(); attributeIndex++) - { - const ShaderVariable &attribute = mActiveAttributes[attributeIndex]; - - if (attribute.name == attributeName) - { - return semanticIndex; - } - - semanticIndex += AttributeRegisterCount(attribute.type); - } - } - - return -1; -} - -void VertexShader::parseAttributes() -{ - const std::string &hlsl = getHLSL(); - if (!hlsl.empty()) - { - void *activeAttributes; - ShGetInfoPointer(mVertexCompiler, SH_ACTIVE_ATTRIBUTES_ARRAY, &activeAttributes); - mActiveAttributes = *(std::vector*)activeAttributes; - } -} - -FragmentShader::FragmentShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle) - : Shader(manager, renderer, handle) -{ -} - -FragmentShader::~FragmentShader() -{ -} - -GLenum FragmentShader::getType() -{ - return GL_FRAGMENT_SHADER; -} - -void FragmentShader::compile() -{ - uncompile(); - - compileToHLSL(mFragmentCompiler); - parseVaryings(mFragmentCompiler); - std::sort(mVaryings.begin(), mVaryings.end(), compareVarying); - - const std::string &hlsl = getHLSL(); - if (!hlsl.empty()) - { - void *activeOutputVariables; - ShGetInfoPointer(mFragmentCompiler, SH_ACTIVE_OUTPUT_VARIABLES_ARRAY, &activeOutputVariables); - mActiveOutputVariables = *(std::vector*)activeOutputVariables; - } -} - -void FragmentShader::uncompile() -{ - Shader::uncompile(); - - mActiveOutputVariables.clear(); -} - -const std::vector &FragmentShader::getOutputVariables() const -{ - return mActiveOutputVariables; -} - -ShShaderOutput Shader::getCompilerOutputType(GLenum shader) -{ - void *compiler = NULL; - - switch (shader) - { - case GL_VERTEX_SHADER: compiler = mVertexCompiler; break; - case GL_FRAGMENT_SHADER: compiler = mFragmentCompiler; break; - default: UNREACHABLE(); return SH_HLSL9_OUTPUT; - } - - size_t outputType = 0; - ShGetInfo(compiler, SH_OUTPUT_TYPE, &outputType); - - return static_cast(outputType); -} - } diff --git a/gfx/angle/src/libGLESv2/Shader.h b/gfx/angle/src/libGLESv2/Shader.h index a41894994063..db3a14510ac4 100644 --- a/gfx/angle/src/libGLESv2/Shader.h +++ b/gfx/angle/src/libGLESv2/Shader.h @@ -12,32 +12,32 @@ #ifndef LIBGLESV2_SHADER_H_ #define LIBGLESV2_SHADER_H_ -#include -#include + #include #include #include -#include "common/shadervars.h" +#include "angle_gl.h" +#include + #include "common/angleutils.h" #include "libGLESv2/angletypes.h" -#include "GLSLANG/ShaderLang.h" namespace rx { -class Renderer; +class ShaderImpl; } namespace gl { class ResourceManager; -struct PackedVarying : public Varying +struct PackedVarying : public sh::Varying { unsigned int registerIndex; // Assigned during link - PackedVarying(const Varying &varying) - : Varying(varying), + PackedVarying(const sh::Varying &varying) + : sh::Varying(varying), registerIndex(GL_INVALID_INDEX) {} @@ -51,16 +51,17 @@ struct PackedVarying : public Varying class Shader { - friend class DynamicHLSL; - public: - Shader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle); + Shader(ResourceManager *manager, rx::ShaderImpl *impl, GLenum type, GLuint handle); virtual ~Shader(); - virtual GLenum getType() = 0; + GLenum getType() const { return mType; } GLuint getHandle() const; + rx::ShaderImpl *getImplementation() { return mShader; } + const rx::ShaderImpl *getImplementation() const { return mShader; } + void deleteSource(); void setSource(GLsizei count, const char *const *string, const GLint *length); int getInfoLogLength() const; @@ -69,118 +70,32 @@ class Shader void getSource(GLsizei bufSize, GLsizei *length, char *buffer) const; int getTranslatedSourceLength() const; void getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer) const; - const std::vector &getUniforms() const; - const std::vector &getInterfaceBlocks() const; - std::vector &getVaryings(); - virtual void compile() = 0; - virtual void uncompile(); - bool isCompiled() const; - const std::string &getHLSL() const; + void compile(); + bool isCompiled() const { return mCompiled; } void addRef(); void release(); unsigned int getRefCount() const; bool isFlaggedForDeletion() const; void flagForDeletion(); - int getShaderVersion() const; - void resetVaryingsRegisterAssignment(); - - static void releaseCompiler(); - static ShShaderOutput getCompilerOutputType(GLenum shader); - - bool usesDepthRange() const { return mUsesDepthRange; } - bool usesPointSize() const { return mUsesPointSize; } - rx::D3DWorkaroundType getD3DWorkarounds() const; - - protected: - void parseVaryings(void *compiler); - - void compileToHLSL(void *compiler); - - void getSourceImpl(const std::string &source, GLsizei bufSize, GLsizei *length, char *buffer) const; - - static bool compareVarying(const PackedVarying &x, const PackedVarying &y); - - const rx::Renderer *const mRenderer; - - std::vector mVaryings; - - bool mUsesMultipleRenderTargets; - bool mUsesFragColor; - bool mUsesFragData; - bool mUsesFragCoord; - bool mUsesFrontFacing; - bool mUsesPointSize; - bool mUsesPointCoord; - bool mUsesDepthRange; - bool mUsesFragDepth; - int mShaderVersion; - bool mUsesDiscardRewriting; - bool mUsesNestedBreak; - - static void *mFragmentCompiler; - static void *mVertexCompiler; private: DISALLOW_COPY_AND_ASSIGN(Shader); - void initializeCompiler(); + static void getSourceImpl(const std::string &source, GLsizei bufSize, GLsizei *length, char *buffer); + rx::ShaderImpl *mShader; const GLuint mHandle; + const GLenum mType; + std::string mSource; unsigned int mRefCount; // Number of program objects this shader is attached to bool mDeleteStatus; // Flag to indicate that the shader can be deleted when no longer in use - - std::string mSource; - std::string mHlsl; - std::string mInfoLog; - std::vector mActiveUniforms; - std::vector mActiveInterfaceBlocks; + bool mCompiled; // Indicates if this shader has been successfully compiled ResourceManager *mResourceManager; }; -class VertexShader : public Shader -{ - friend class DynamicHLSL; - - public: - VertexShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle); - - ~VertexShader(); - - virtual GLenum getType(); - virtual void compile(); - virtual void uncompile(); - int getSemanticIndex(const std::string &attributeName); - - const std::vector &activeAttributes() const { return mActiveAttributes; } - - private: - DISALLOW_COPY_AND_ASSIGN(VertexShader); - - void parseAttributes(); - - std::vector mActiveAttributes; -}; - -class FragmentShader : public Shader -{ - public: - FragmentShader(ResourceManager *manager,const rx::Renderer *renderer, GLuint handle); - - ~FragmentShader(); - - virtual GLenum getType(); - virtual void compile(); - virtual void uncompile(); - const std::vector &getOutputVariables() const; - - private: - DISALLOW_COPY_AND_ASSIGN(FragmentShader); - - std::vector mActiveOutputVariables; -}; } #endif // LIBGLESV2_SHADER_H_ diff --git a/gfx/angle/src/libGLESv2/State.cpp b/gfx/angle/src/libGLESv2/State.cpp new file mode 100644 index 000000000000..b472eeb8cc6d --- /dev/null +++ b/gfx/angle/src/libGLESv2/State.cpp @@ -0,0 +1,1437 @@ +// +// Copyright (c) 2014 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. +// + +// State.cpp: Implements the State class, encapsulating raw GL state. + +#include "libGLESv2/State.h" + +#include "libGLESv2/Context.h" +#include "libGLESv2/VertexArray.h" +#include "libGLESv2/Query.h" +#include "libGLESv2/Framebuffer.h" +#include "libGLESv2/FramebufferAttachment.h" +#include "libGLESv2/renderer/RenderTarget.h" +#include "libGLESv2/formatutils.h" + +namespace gl +{ +State::State() +{ + mContext = NULL; + + setClearColor(0.0f, 0.0f, 0.0f, 0.0f); + + mDepthClearValue = 1.0f; + mStencilClearValue = 0; + + mRasterizer.rasterizerDiscard = false; + mRasterizer.cullFace = false; + mRasterizer.cullMode = GL_BACK; + mRasterizer.frontFace = GL_CCW; + mRasterizer.polygonOffsetFill = false; + mRasterizer.polygonOffsetFactor = 0.0f; + mRasterizer.polygonOffsetUnits = 0.0f; + mRasterizer.pointDrawMode = false; + mRasterizer.multiSample = false; + mScissorTest = false; + mScissor.x = 0; + mScissor.y = 0; + mScissor.width = 0; + mScissor.height = 0; + + mBlend.blend = false; + mBlend.sourceBlendRGB = GL_ONE; + mBlend.sourceBlendAlpha = GL_ONE; + mBlend.destBlendRGB = GL_ZERO; + mBlend.destBlendAlpha = GL_ZERO; + mBlend.blendEquationRGB = GL_FUNC_ADD; + mBlend.blendEquationAlpha = GL_FUNC_ADD; + mBlend.sampleAlphaToCoverage = false; + mBlend.dither = true; + + mBlendColor.red = 0; + mBlendColor.green = 0; + mBlendColor.blue = 0; + mBlendColor.alpha = 0; + + mDepthStencil.depthTest = false; + mDepthStencil.depthFunc = GL_LESS; + mDepthStencil.depthMask = true; + mDepthStencil.stencilTest = false; + mDepthStencil.stencilFunc = GL_ALWAYS; + mDepthStencil.stencilMask = -1; + mDepthStencil.stencilWritemask = -1; + mDepthStencil.stencilBackFunc = GL_ALWAYS; + mDepthStencil.stencilBackMask = - 1; + mDepthStencil.stencilBackWritemask = -1; + mDepthStencil.stencilFail = GL_KEEP; + mDepthStencil.stencilPassDepthFail = GL_KEEP; + mDepthStencil.stencilPassDepthPass = GL_KEEP; + mDepthStencil.stencilBackFail = GL_KEEP; + mDepthStencil.stencilBackPassDepthFail = GL_KEEP; + mDepthStencil.stencilBackPassDepthPass = GL_KEEP; + + mStencilRef = 0; + mStencilBackRef = 0; + + mSampleCoverage = false; + mSampleCoverageValue = 1.0f; + mSampleCoverageInvert = false; + mGenerateMipmapHint = GL_DONT_CARE; + mFragmentShaderDerivativeHint = GL_DONT_CARE; + + mLineWidth = 1.0f; + + mViewport.x = 0; + mViewport.y = 0; + mViewport.width = 0; + mViewport.height = 0; + mNearZ = 0.0f; + mFarZ = 1.0f; + + mBlend.colorMaskRed = true; + mBlend.colorMaskGreen = true; + mBlend.colorMaskBlue = true; + mBlend.colorMaskAlpha = true; + + const GLfloat defaultFloatValues[] = { 0.0f, 0.0f, 0.0f, 1.0f }; + for (int attribIndex = 0; attribIndex < MAX_VERTEX_ATTRIBS; attribIndex++) + { + mVertexAttribCurrentValues[attribIndex].setFloatValues(defaultFloatValues); + } + + for (unsigned int textureUnit = 0; textureUnit < ArraySize(mSamplers); textureUnit++) + { + mSamplers[textureUnit].set(NULL); + } + + mActiveSampler = 0; + + mActiveQueries[GL_ANY_SAMPLES_PASSED].set(NULL); + mActiveQueries[GL_ANY_SAMPLES_PASSED_CONSERVATIVE].set(NULL); + mActiveQueries[GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN].set(NULL); + + mCurrentProgramId = 0; + mCurrentProgramBinary.set(NULL); + + mReadFramebuffer = NULL; + mDrawFramebuffer = NULL; +} + +State::~State() +{ + for (int type = 0; type < TEXTURE_TYPE_COUNT; type++) + { + for (int sampler = 0; sampler < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS; sampler++) + { + mSamplerTexture[type][sampler].set(NULL); + } + } + + const GLfloat defaultFloatValues[] = { 0.0f, 0.0f, 0.0f, 1.0f }; + for (int attribIndex = 0; attribIndex < MAX_VERTEX_ATTRIBS; attribIndex++) + { + mVertexAttribCurrentValues[attribIndex].setFloatValues(defaultFloatValues); + } + + mArrayBuffer.set(NULL); + mRenderbuffer.set(NULL); + + mTransformFeedback.set(NULL); + + for (State::ActiveQueryMap::iterator i = mActiveQueries.begin(); i != mActiveQueries.end(); i++) + { + i->second.set(NULL); + } + + mGenericUniformBuffer.set(NULL); + for (int i = 0; i < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS; i++) + { + mUniformBuffers[i].set(NULL); + } + + mGenericTransformFeedbackBuffer.set(NULL); + for (int i = 0; i < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++) + { + mTransformFeedbackBuffers[i].set(NULL); + } + + mCopyReadBuffer.set(NULL); + mCopyWriteBuffer.set(NULL); + + mPack.pixelBuffer.set(NULL); + mUnpack.pixelBuffer.set(NULL); +} + +const RasterizerState &State::getRasterizerState() const +{ + return mRasterizer; +} + +const BlendState &State::getBlendState() const +{ + return mBlend; +} + +const DepthStencilState &State::getDepthStencilState() const +{ + return mDepthStencil; +} + +void State::setClearColor(float red, float green, float blue, float alpha) +{ + mColorClearValue.red = red; + mColorClearValue.green = green; + mColorClearValue.blue = blue; + mColorClearValue.alpha = alpha; +} + +void State::setClearDepth(float depth) +{ + mDepthClearValue = depth; +} + +void State::setClearStencil(int stencil) +{ + mStencilClearValue = stencil; +} + +ClearParameters State::getClearParameters(GLbitfield mask) const +{ + ClearParameters clearParams = { 0 }; + for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) + { + clearParams.clearColor[i] = false; + } + clearParams.colorFClearValue = mColorClearValue; + clearParams.colorClearType = GL_FLOAT; + clearParams.colorMaskRed = mBlend.colorMaskRed; + clearParams.colorMaskGreen = mBlend.colorMaskGreen; + clearParams.colorMaskBlue = mBlend.colorMaskBlue; + clearParams.colorMaskAlpha = mBlend.colorMaskAlpha; + clearParams.clearDepth = false; + clearParams.depthClearValue = mDepthClearValue; + clearParams.clearStencil = false; + clearParams.stencilClearValue = mStencilClearValue; + clearParams.stencilWriteMask = mDepthStencil.stencilWritemask; + clearParams.scissorEnabled = mScissorTest; + clearParams.scissor = mScissor; + + const Framebuffer *framebufferObject = getDrawFramebuffer(); + if (mask & GL_COLOR_BUFFER_BIT) + { + if (framebufferObject->hasEnabledColorAttachment()) + { + for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) + { + clearParams.clearColor[i] = true; + } + } + } + + if (mask & GL_DEPTH_BUFFER_BIT) + { + if (mDepthStencil.depthMask && framebufferObject->getDepthbuffer() != NULL) + { + clearParams.clearDepth = true; + } + } + + if (mask & GL_STENCIL_BUFFER_BIT) + { + if (framebufferObject->getStencilbuffer() != NULL) + { + rx::RenderTarget *depthStencil = framebufferObject->getStencilbuffer()->getRenderTarget(); + if (!depthStencil) + { + ERR("Depth stencil pointer unexpectedly null."); + ClearParameters nullClearParam = { 0 }; + return nullClearParam; + } + + if (GetInternalFormatInfo(depthStencil->getActualFormat()).stencilBits > 0) + { + clearParams.clearStencil = true; + } + } + } + + return clearParams; +} + +void State::setColorMask(bool red, bool green, bool blue, bool alpha) +{ + mBlend.colorMaskRed = red; + mBlend.colorMaskGreen = green; + mBlend.colorMaskBlue = blue; + mBlend.colorMaskAlpha = alpha; +} + +void State::setDepthMask(bool mask) +{ + mDepthStencil.depthMask = mask; +} + +bool State::isRasterizerDiscardEnabled() const +{ + return mRasterizer.rasterizerDiscard; +} + +void State::setRasterizerDiscard(bool enabled) +{ + mRasterizer.rasterizerDiscard = enabled; +} + +bool State::isCullFaceEnabled() const +{ + return mRasterizer.cullFace; +} + +void State::setCullFace(bool enabled) +{ + mRasterizer.cullFace = enabled; +} + +void State::setCullMode(GLenum mode) +{ + mRasterizer.cullMode = mode; +} + +void State::setFrontFace(GLenum front) +{ + mRasterizer.frontFace = front; +} + +bool State::isDepthTestEnabled() const +{ + return mDepthStencil.depthTest; +} + +void State::setDepthTest(bool enabled) +{ + mDepthStencil.depthTest = enabled; +} + +void State::setDepthFunc(GLenum depthFunc) +{ + mDepthStencil.depthFunc = depthFunc; +} + +void State::setDepthRange(float zNear, float zFar) +{ + mNearZ = zNear; + mFarZ = zFar; +} + +void State::getDepthRange(float *zNear, float *zFar) const +{ + *zNear = mNearZ; + *zFar = mFarZ; +} + +bool State::isBlendEnabled() const +{ + return mBlend.blend; +} + +void State::setBlend(bool enabled) +{ + mBlend.blend = enabled; +} + +void State::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha) +{ + mBlend.sourceBlendRGB = sourceRGB; + mBlend.destBlendRGB = destRGB; + mBlend.sourceBlendAlpha = sourceAlpha; + mBlend.destBlendAlpha = destAlpha; +} + +void State::setBlendColor(float red, float green, float blue, float alpha) +{ + mBlendColor.red = red; + mBlendColor.green = green; + mBlendColor.blue = blue; + mBlendColor.alpha = alpha; +} + +void State::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation) +{ + mBlend.blendEquationRGB = rgbEquation; + mBlend.blendEquationAlpha = alphaEquation; +} + +const ColorF &State::getBlendColor() const +{ + return mBlendColor; +} + +bool State::isStencilTestEnabled() const +{ + return mDepthStencil.stencilTest; +} + +void State::setStencilTest(bool enabled) +{ + mDepthStencil.stencilTest = enabled; +} + +void State::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask) +{ + mDepthStencil.stencilFunc = stencilFunc; + mStencilRef = (stencilRef > 0) ? stencilRef : 0; + mDepthStencil.stencilMask = stencilMask; +} + +void State::setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask) +{ + mDepthStencil.stencilBackFunc = stencilBackFunc; + mStencilBackRef = (stencilBackRef > 0) ? stencilBackRef : 0; + mDepthStencil.stencilBackMask = stencilBackMask; +} + +void State::setStencilWritemask(GLuint stencilWritemask) +{ + mDepthStencil.stencilWritemask = stencilWritemask; +} + +void State::setStencilBackWritemask(GLuint stencilBackWritemask) +{ + mDepthStencil.stencilBackWritemask = stencilBackWritemask; +} + +void State::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass) +{ + mDepthStencil.stencilFail = stencilFail; + mDepthStencil.stencilPassDepthFail = stencilPassDepthFail; + mDepthStencil.stencilPassDepthPass = stencilPassDepthPass; +} + +void State::setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass) +{ + mDepthStencil.stencilBackFail = stencilBackFail; + mDepthStencil.stencilBackPassDepthFail = stencilBackPassDepthFail; + mDepthStencil.stencilBackPassDepthPass = stencilBackPassDepthPass; +} + +GLint State::getStencilRef() const +{ + return mStencilRef; +} + +GLint State::getStencilBackRef() const +{ + return mStencilBackRef; +} + +bool State::isPolygonOffsetFillEnabled() const +{ + return mRasterizer.polygonOffsetFill; +} + +void State::setPolygonOffsetFill(bool enabled) +{ + mRasterizer.polygonOffsetFill = enabled; +} + +void State::setPolygonOffsetParams(GLfloat factor, GLfloat units) +{ + // An application can pass NaN values here, so handle this gracefully + mRasterizer.polygonOffsetFactor = factor != factor ? 0.0f : factor; + mRasterizer.polygonOffsetUnits = units != units ? 0.0f : units; +} + +bool State::isSampleAlphaToCoverageEnabled() const +{ + return mBlend.sampleAlphaToCoverage; +} + +void State::setSampleAlphaToCoverage(bool enabled) +{ + mBlend.sampleAlphaToCoverage = enabled; +} + +bool State::isSampleCoverageEnabled() const +{ + return mSampleCoverage; +} + +void State::setSampleCoverage(bool enabled) +{ + mSampleCoverage = enabled; +} + +void State::setSampleCoverageParams(GLclampf value, bool invert) +{ + mSampleCoverageValue = value; + mSampleCoverageInvert = invert; +} + +void State::getSampleCoverageParams(GLclampf *value, bool *invert) +{ + ASSERT(value != NULL && invert != NULL); + + *value = mSampleCoverageValue; + *invert = mSampleCoverageInvert; +} + +bool State::isScissorTestEnabled() const +{ + return mScissorTest; +} + +void State::setScissorTest(bool enabled) +{ + mScissorTest = enabled; +} + +void State::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height) +{ + mScissor.x = x; + mScissor.y = y; + mScissor.width = width; + mScissor.height = height; +} + +const Rectangle &State::getScissor() const +{ + return mScissor; +} + +bool State::isDitherEnabled() const +{ + return mBlend.dither; +} + +void State::setDither(bool enabled) +{ + mBlend.dither = enabled; +} + +void State::setEnableFeature(GLenum feature, bool enabled) +{ + switch (feature) + { + case GL_CULL_FACE: setCullFace(enabled); break; + case GL_POLYGON_OFFSET_FILL: setPolygonOffsetFill(enabled); break; + case GL_SAMPLE_ALPHA_TO_COVERAGE: setSampleAlphaToCoverage(enabled); break; + case GL_SAMPLE_COVERAGE: setSampleCoverage(enabled); break; + case GL_SCISSOR_TEST: setScissorTest(enabled); break; + case GL_STENCIL_TEST: setStencilTest(enabled); break; + case GL_DEPTH_TEST: setDepthTest(enabled); break; + case GL_BLEND: setBlend(enabled); break; + case GL_DITHER: setDither(enabled); break; + case GL_PRIMITIVE_RESTART_FIXED_INDEX: UNIMPLEMENTED(); break; + case GL_RASTERIZER_DISCARD: setRasterizerDiscard(enabled); break; + default: UNREACHABLE(); + } +} + +bool State::getEnableFeature(GLenum feature) +{ + switch (feature) + { + case GL_CULL_FACE: return isCullFaceEnabled(); + case GL_POLYGON_OFFSET_FILL: return isPolygonOffsetFillEnabled(); + case GL_SAMPLE_ALPHA_TO_COVERAGE: return isSampleAlphaToCoverageEnabled(); + case GL_SAMPLE_COVERAGE: return isSampleCoverageEnabled(); + case GL_SCISSOR_TEST: return isScissorTestEnabled(); + case GL_STENCIL_TEST: return isStencilTestEnabled(); + case GL_DEPTH_TEST: return isDepthTestEnabled(); + case GL_BLEND: return isBlendEnabled(); + case GL_DITHER: return isDitherEnabled(); + case GL_PRIMITIVE_RESTART_FIXED_INDEX: UNIMPLEMENTED(); return false; + case GL_RASTERIZER_DISCARD: return isRasterizerDiscardEnabled(); + default: UNREACHABLE(); return false; + } +} + +void State::setLineWidth(GLfloat width) +{ + mLineWidth = width; +} + +void State::setGenerateMipmapHint(GLenum hint) +{ + mGenerateMipmapHint = hint; +} + +void State::setFragmentShaderDerivativeHint(GLenum hint) +{ + mFragmentShaderDerivativeHint = hint; + // TODO: Propagate the hint to shader translator so we can write + // ddx, ddx_coarse, or ddx_fine depending on the hint. + // Ignore for now. It is valid for implementations to ignore hint. +} + +void State::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height) +{ + mViewport.x = x; + mViewport.y = y; + mViewport.width = width; + mViewport.height = height; +} + +const Rectangle &State::getViewport() const +{ + return mViewport; +} + +void State::setActiveSampler(unsigned int active) +{ + mActiveSampler = active; +} + +unsigned int State::getActiveSampler() const +{ + return mActiveSampler; +} + +void State::setSamplerTexture(TextureType type, Texture *texture) +{ + mSamplerTexture[type][mActiveSampler].set(texture); +} + +Texture *State::getSamplerTexture(unsigned int sampler, TextureType type) const +{ + GLuint texid = mSamplerTexture[type][sampler].id(); + + if (texid == 0) // Special case: 0 refers to default textures held by Context + { + return NULL; + } + + return mSamplerTexture[type][sampler].get(); +} + +GLuint State::getSamplerTextureId(unsigned int sampler, TextureType type) const +{ + return mSamplerTexture[type][sampler].id(); +} + +void State::detachTexture(GLuint texture) +{ + // Textures have a detach method on State rather than a simple + // removeBinding, because the zero/null texture objects are managed + // separately, and don't have to go through the Context's maps or + // the ResourceManager. + + // [OpenGL ES 2.0.24] section 3.8 page 84: + // If a texture object is deleted, it is as if all texture units which are bound to that texture object are + // rebound to texture object zero + + for (int type = 0; type < TEXTURE_TYPE_COUNT; type++) + { + for (int sampler = 0; sampler < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS; sampler++) + { + if (mSamplerTexture[type][sampler].id() == texture) + { + mSamplerTexture[type][sampler].set(NULL); + } + } + } + + // [OpenGL ES 2.0.24] section 4.4 page 112: + // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is + // as if Texture2DAttachment had been called, with a texture of 0, for each attachment point to which this + // image was attached in the currently bound framebuffer. + + if (mReadFramebuffer) + { + mReadFramebuffer->detachTexture(texture); + } + + if (mDrawFramebuffer) + { + mDrawFramebuffer->detachTexture(texture); + } +} + +void State::setSamplerBinding(GLuint textureUnit, Sampler *sampler) +{ + mSamplers[textureUnit].set(sampler); +} + +GLuint State::getSamplerId(GLuint textureUnit) const +{ + ASSERT(textureUnit < ArraySize(mSamplers)); + return mSamplers[textureUnit].id(); +} + +Sampler *State::getSampler(GLuint textureUnit) const +{ + return mSamplers[textureUnit].get(); +} + +void State::detachSampler(GLuint sampler) +{ + // [OpenGL ES 3.0.2] section 3.8.2 pages 123-124: + // If a sampler object that is currently bound to one or more texture units is + // deleted, it is as though BindSampler is called once for each texture unit to + // which the sampler is bound, with unit set to the texture unit and sampler set to zero. + for (unsigned int textureUnit = 0; textureUnit < ArraySize(mSamplers); textureUnit++) + { + if (mSamplers[textureUnit].id() == sampler) + { + mSamplers[textureUnit].set(NULL); + } + } +} + +void State::setRenderbufferBinding(Renderbuffer *renderbuffer) +{ + mRenderbuffer.set(renderbuffer); +} + +GLuint State::getRenderbufferId() const +{ + return mRenderbuffer.id(); +} + +Renderbuffer *State::getCurrentRenderbuffer() +{ + return mRenderbuffer.get(); +} + +void State::detachRenderbuffer(GLuint renderbuffer) +{ + // [OpenGL ES 2.0.24] section 4.4 page 109: + // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer + // had been executed with the target RENDERBUFFER and name of zero. + + if (mRenderbuffer.id() == renderbuffer) + { + mRenderbuffer.set(NULL); + } + + // [OpenGL ES 2.0.24] section 4.4 page 111: + // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer, + // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment + // point to which this image was attached in the currently bound framebuffer. + + Framebuffer *readFramebuffer = mReadFramebuffer; + Framebuffer *drawFramebuffer = mDrawFramebuffer; + + if (readFramebuffer) + { + readFramebuffer->detachRenderbuffer(renderbuffer); + } + + if (drawFramebuffer && drawFramebuffer != readFramebuffer) + { + drawFramebuffer->detachRenderbuffer(renderbuffer); + } + +} + +void State::setReadFramebufferBinding(Framebuffer *framebuffer) +{ + mReadFramebuffer = framebuffer; +} + +void State::setDrawFramebufferBinding(Framebuffer *framebuffer) +{ + mDrawFramebuffer = framebuffer; +} + +Framebuffer *State::getTargetFramebuffer(GLenum target) const +{ + switch (target) + { + case GL_READ_FRAMEBUFFER_ANGLE: return mReadFramebuffer; + case GL_DRAW_FRAMEBUFFER_ANGLE: + case GL_FRAMEBUFFER: return mDrawFramebuffer; + default: UNREACHABLE(); return NULL; + } +} + +Framebuffer *State::getReadFramebuffer() +{ + return mReadFramebuffer; +} + +Framebuffer *State::getDrawFramebuffer() +{ + return mDrawFramebuffer; +} + +const Framebuffer *State::getReadFramebuffer() const +{ + return mReadFramebuffer; +} + +const Framebuffer *State::getDrawFramebuffer() const +{ + return mDrawFramebuffer; +} + +bool State::removeReadFramebufferBinding(GLuint framebuffer) +{ + if (mReadFramebuffer->id() == framebuffer) + { + mReadFramebuffer = NULL; + return true; + } + + return false; +} + +bool State::removeDrawFramebufferBinding(GLuint framebuffer) +{ + if (mDrawFramebuffer->id() == framebuffer) + { + mDrawFramebuffer = NULL; + return true; + } + + return false; +} + +void State::setVertexArrayBinding(VertexArray *vertexArray) +{ + mVertexArray = vertexArray; +} + +GLuint State::getVertexArrayId() const +{ + ASSERT(mVertexArray != NULL); + return mVertexArray->id(); +} + +VertexArray *State::getVertexArray() const +{ + ASSERT(mVertexArray != NULL); + return mVertexArray; +} + +bool State::removeVertexArrayBinding(GLuint vertexArray) +{ + if (mVertexArray->id() == vertexArray) + { + mVertexArray = NULL; + return true; + } + + return false; +} + +void State::setCurrentProgram(GLuint programId, Program *newProgram) +{ + mCurrentProgramId = programId; // set new ID before trying to delete program binary; otherwise it will only be flagged for deletion + mCurrentProgramBinary.set(NULL); + + if (newProgram) + { + newProgram->addRef(); + mCurrentProgramBinary.set(newProgram->getProgramBinary()); + } +} + +void State::setCurrentProgramBinary(ProgramBinary *binary) +{ + mCurrentProgramBinary.set(binary); +} + +GLuint State::getCurrentProgramId() const +{ + return mCurrentProgramId; +} + +ProgramBinary *State::getCurrentProgramBinary() const +{ + return mCurrentProgramBinary.get(); +} + +void State::setTransformFeedbackBinding(TransformFeedback *transformFeedback) +{ + mTransformFeedback.set(transformFeedback); +} + +TransformFeedback *State::getCurrentTransformFeedback() const +{ + return mTransformFeedback.get(); +} + +void State::detachTransformFeedback(GLuint transformFeedback) +{ + if (mTransformFeedback.id() == transformFeedback) + { + mTransformFeedback.set(NULL); + } +} + +bool State::isQueryActive() const +{ + for (State::ActiveQueryMap::const_iterator i = mActiveQueries.begin(); + i != mActiveQueries.end(); i++) + { + if (i->second.get() != NULL) + { + return true; + } + } + + return false; +} + +void State::setActiveQuery(GLenum target, Query *query) +{ + mActiveQueries[target].set(query); +} + +GLuint State::getActiveQueryId(GLenum target) const +{ + const Query *query = getActiveQuery(target); + return (query ? query->id() : 0u); +} + +Query *State::getActiveQuery(GLenum target) const +{ + // All query types should already exist in the activeQueries map + ASSERT(mActiveQueries.find(target) != mActiveQueries.end()); + + return mActiveQueries.at(target).get(); +} + +void State::setArrayBufferBinding(Buffer *buffer) +{ + mArrayBuffer.set(buffer); +} + +GLuint State::getArrayBufferId() const +{ + return mArrayBuffer.id(); +} + +bool State::removeArrayBufferBinding(GLuint buffer) +{ + if (mArrayBuffer.id() == buffer) + { + mArrayBuffer.set(NULL); + return true; + } + + return false; +} + +void State::setGenericUniformBufferBinding(Buffer *buffer) +{ + mGenericUniformBuffer.set(buffer); +} + +void State::setIndexedUniformBufferBinding(GLuint index, Buffer *buffer, GLintptr offset, GLsizeiptr size) +{ + mUniformBuffers[index].set(buffer, offset, size); +} + +GLuint State::getIndexedUniformBufferId(GLuint index) const +{ + ASSERT(index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS); + + return mUniformBuffers[index].id(); +} + +Buffer *State::getIndexedUniformBuffer(GLuint index) const +{ + ASSERT(index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS); + + return mUniformBuffers[index].get(); +} + +void State::setGenericTransformFeedbackBufferBinding(Buffer *buffer) +{ + mGenericTransformFeedbackBuffer.set(buffer); +} + +void State::setIndexedTransformFeedbackBufferBinding(GLuint index, Buffer *buffer, GLintptr offset, GLsizeiptr size) +{ + mTransformFeedbackBuffers[index].set(buffer, offset, size); +} + +GLuint State::getIndexedTransformFeedbackBufferId(GLuint index) const +{ + ASSERT(index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS); + + return mTransformFeedbackBuffers[index].id(); +} + +Buffer *State::getIndexedTransformFeedbackBuffer(GLuint index) const +{ + ASSERT(index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS); + + return mTransformFeedbackBuffers[index].get(); +} + +GLuint State::getIndexedTransformFeedbackBufferOffset(GLuint index) const +{ + ASSERT(index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS); + + return mTransformFeedbackBuffers[index].getOffset(); +} + +void State::setCopyReadBufferBinding(Buffer *buffer) +{ + mCopyReadBuffer.set(buffer); +} + +void State::setCopyWriteBufferBinding(Buffer *buffer) +{ + mCopyWriteBuffer.set(buffer); +} + +void State::setPixelPackBufferBinding(Buffer *buffer) +{ + mPack.pixelBuffer.set(buffer); +} + +void State::setPixelUnpackBufferBinding(Buffer *buffer) +{ + mUnpack.pixelBuffer.set(buffer); +} + +Buffer *State::getTargetBuffer(GLenum target) const +{ + switch (target) + { + case GL_ARRAY_BUFFER: return mArrayBuffer.get(); + case GL_COPY_READ_BUFFER: return mCopyReadBuffer.get(); + case GL_COPY_WRITE_BUFFER: return mCopyWriteBuffer.get(); + case GL_ELEMENT_ARRAY_BUFFER: return getVertexArray()->getElementArrayBuffer(); + case GL_PIXEL_PACK_BUFFER: return mPack.pixelBuffer.get(); + case GL_PIXEL_UNPACK_BUFFER: return mUnpack.pixelBuffer.get(); + case GL_TRANSFORM_FEEDBACK_BUFFER: return mGenericTransformFeedbackBuffer.get(); + case GL_UNIFORM_BUFFER: return mGenericUniformBuffer.get(); + default: UNREACHABLE(); return NULL; + } +} + +void State::setEnableVertexAttribArray(unsigned int attribNum, bool enabled) +{ + getVertexArray()->enableAttribute(attribNum, enabled); +} + +void State::setVertexAttribf(GLuint index, const GLfloat values[4]) +{ + ASSERT(index < gl::MAX_VERTEX_ATTRIBS); + mVertexAttribCurrentValues[index].setFloatValues(values); +} + +void State::setVertexAttribu(GLuint index, const GLuint values[4]) +{ + ASSERT(index < gl::MAX_VERTEX_ATTRIBS); + mVertexAttribCurrentValues[index].setUnsignedIntValues(values); +} + +void State::setVertexAttribi(GLuint index, const GLint values[4]) +{ + ASSERT(index < gl::MAX_VERTEX_ATTRIBS); + mVertexAttribCurrentValues[index].setIntValues(values); +} + +void State::setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type, bool normalized, + bool pureInteger, GLsizei stride, const void *pointer) +{ + getVertexArray()->setAttributeState(attribNum, boundBuffer, size, type, normalized, pureInteger, stride, pointer); +} + +const VertexAttribute &State::getVertexAttribState(unsigned int attribNum) const +{ + return getVertexArray()->getVertexAttribute(attribNum); +} + +const VertexAttribCurrentValueData &State::getVertexAttribCurrentValue(unsigned int attribNum) const +{ + ASSERT(attribNum < MAX_VERTEX_ATTRIBS); + return mVertexAttribCurrentValues[attribNum]; +} + +const VertexAttribCurrentValueData *State::getVertexAttribCurrentValues() const +{ + return mVertexAttribCurrentValues; +} + +const void *State::getVertexAttribPointer(unsigned int attribNum) const +{ + return getVertexArray()->getVertexAttribute(attribNum).pointer; +} + +void State::setPackAlignment(GLint alignment) +{ + mPack.alignment = alignment; +} + +GLint State::getPackAlignment() const +{ + return mPack.alignment; +} + +void State::setPackReverseRowOrder(bool reverseRowOrder) +{ + mPack.reverseRowOrder = reverseRowOrder; +} + +bool State::getPackReverseRowOrder() const +{ + return mPack.reverseRowOrder; +} + +const PixelPackState &State::getPackState() const +{ + return mPack; +} + +void State::setUnpackAlignment(GLint alignment) +{ + mUnpack.alignment = alignment; +} + +GLint State::getUnpackAlignment() const +{ + return mUnpack.alignment; +} + +const PixelUnpackState &State::getUnpackState() const +{ + return mUnpack; +} + +void State::getBooleanv(GLenum pname, GLboolean *params) +{ + switch (pname) + { + case GL_SAMPLE_COVERAGE_INVERT: *params = mSampleCoverageInvert; break; + case GL_DEPTH_WRITEMASK: *params = mDepthStencil.depthMask; break; + case GL_COLOR_WRITEMASK: + params[0] = mBlend.colorMaskRed; + params[1] = mBlend.colorMaskGreen; + params[2] = mBlend.colorMaskBlue; + params[3] = mBlend.colorMaskAlpha; + break; + case GL_CULL_FACE: *params = mRasterizer.cullFace; break; + case GL_POLYGON_OFFSET_FILL: *params = mRasterizer.polygonOffsetFill; break; + case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mBlend.sampleAlphaToCoverage; break; + case GL_SAMPLE_COVERAGE: *params = mSampleCoverage; break; + case GL_SCISSOR_TEST: *params = mScissorTest; break; + case GL_STENCIL_TEST: *params = mDepthStencil.stencilTest; break; + case GL_DEPTH_TEST: *params = mDepthStencil.depthTest; break; + case GL_BLEND: *params = mBlend.blend; break; + case GL_DITHER: *params = mBlend.dither; break; + case GL_TRANSFORM_FEEDBACK_ACTIVE: *params = getCurrentTransformFeedback()->isStarted(); break; + case GL_TRANSFORM_FEEDBACK_PAUSED: *params = getCurrentTransformFeedback()->isPaused(); break; + default: + UNREACHABLE(); + break; + } +} + +void State::getFloatv(GLenum pname, GLfloat *params) +{ + // Please note: DEPTH_CLEAR_VALUE is included in our internal getFloatv 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 + // case, this should make no difference to the calling application. + switch (pname) + { + case GL_LINE_WIDTH: *params = mLineWidth; break; + case GL_SAMPLE_COVERAGE_VALUE: *params = mSampleCoverageValue; break; + case GL_DEPTH_CLEAR_VALUE: *params = mDepthClearValue; break; + case GL_POLYGON_OFFSET_FACTOR: *params = mRasterizer.polygonOffsetFactor; break; + case GL_POLYGON_OFFSET_UNITS: *params = mRasterizer.polygonOffsetUnits; break; + case GL_DEPTH_RANGE: + params[0] = mNearZ; + params[1] = mFarZ; + break; + case GL_COLOR_CLEAR_VALUE: + params[0] = mColorClearValue.red; + params[1] = mColorClearValue.green; + params[2] = mColorClearValue.blue; + params[3] = mColorClearValue.alpha; + break; + case GL_BLEND_COLOR: + params[0] = mBlendColor.red; + params[1] = mBlendColor.green; + params[2] = mBlendColor.blue; + params[3] = mBlendColor.alpha; + break; + default: + UNREACHABLE(); + break; + } +} + +void State::getIntegerv(GLenum pname, GLint *params) +{ + if (pname >= GL_DRAW_BUFFER0_EXT && pname <= GL_DRAW_BUFFER15_EXT) + { + unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0_EXT); + ASSERT(colorAttachment < mContext->getCaps().maxDrawBuffers); + Framebuffer *framebuffer = mDrawFramebuffer; + *params = framebuffer->getDrawBufferState(colorAttachment); + return; + } + + // 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 + // case, this should make no difference to the calling application. You may find it in + // State::getFloatv. + switch (pname) + { + case GL_ARRAY_BUFFER_BINDING: *params = mArrayBuffer.id(); break; + case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = getVertexArray()->getElementArrayBufferId(); break; + //case GL_FRAMEBUFFER_BINDING: // now equivalent to GL_DRAW_FRAMEBUFFER_BINDING_ANGLE + case GL_DRAW_FRAMEBUFFER_BINDING_ANGLE: *params = mDrawFramebuffer->id(); break; + case GL_READ_FRAMEBUFFER_BINDING_ANGLE: *params = mReadFramebuffer->id(); break; + case GL_RENDERBUFFER_BINDING: *params = mRenderbuffer.id(); break; + case GL_VERTEX_ARRAY_BINDING: *params = mVertexArray->id(); break; + case GL_CURRENT_PROGRAM: *params = mCurrentProgramId; break; + case GL_PACK_ALIGNMENT: *params = mPack.alignment; break; + case GL_PACK_REVERSE_ROW_ORDER_ANGLE: *params = mPack.reverseRowOrder; break; + case GL_UNPACK_ALIGNMENT: *params = mUnpack.alignment; break; + case GL_GENERATE_MIPMAP_HINT: *params = mGenerateMipmapHint; break; + case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: *params = mFragmentShaderDerivativeHint; break; + case GL_ACTIVE_TEXTURE: *params = (mActiveSampler + GL_TEXTURE0); break; + case GL_STENCIL_FUNC: *params = mDepthStencil.stencilFunc; break; + case GL_STENCIL_REF: *params = mStencilRef; break; + case GL_STENCIL_VALUE_MASK: *params = clampToInt(mDepthStencil.stencilMask); break; + case GL_STENCIL_BACK_FUNC: *params = mDepthStencil.stencilBackFunc; break; + case GL_STENCIL_BACK_REF: *params = mStencilBackRef; break; + case GL_STENCIL_BACK_VALUE_MASK: *params = clampToInt(mDepthStencil.stencilBackMask); break; + case GL_STENCIL_FAIL: *params = mDepthStencil.stencilFail; break; + case GL_STENCIL_PASS_DEPTH_FAIL: *params = mDepthStencil.stencilPassDepthFail; break; + case GL_STENCIL_PASS_DEPTH_PASS: *params = mDepthStencil.stencilPassDepthPass; break; + case GL_STENCIL_BACK_FAIL: *params = mDepthStencil.stencilBackFail; break; + case GL_STENCIL_BACK_PASS_DEPTH_FAIL: *params = mDepthStencil.stencilBackPassDepthFail; break; + case GL_STENCIL_BACK_PASS_DEPTH_PASS: *params = mDepthStencil.stencilBackPassDepthPass; break; + case GL_DEPTH_FUNC: *params = mDepthStencil.depthFunc; break; + case GL_BLEND_SRC_RGB: *params = mBlend.sourceBlendRGB; break; + case GL_BLEND_SRC_ALPHA: *params = mBlend.sourceBlendAlpha; break; + case GL_BLEND_DST_RGB: *params = mBlend.destBlendRGB; break; + case GL_BLEND_DST_ALPHA: *params = mBlend.destBlendAlpha; break; + case GL_BLEND_EQUATION_RGB: *params = mBlend.blendEquationRGB; break; + case GL_BLEND_EQUATION_ALPHA: *params = mBlend.blendEquationAlpha; break; + case GL_STENCIL_WRITEMASK: *params = clampToInt(mDepthStencil.stencilWritemask); break; + case GL_STENCIL_BACK_WRITEMASK: *params = clampToInt(mDepthStencil.stencilBackWritemask); break; + case GL_STENCIL_CLEAR_VALUE: *params = mStencilClearValue; break; + case GL_SAMPLE_BUFFERS: + case GL_SAMPLES: + { + gl::Framebuffer *framebuffer = mDrawFramebuffer; + if (framebuffer->completeness() == GL_FRAMEBUFFER_COMPLETE) + { + switch (pname) + { + case GL_SAMPLE_BUFFERS: + if (framebuffer->getSamples() != 0) + { + *params = 1; + } + else + { + *params = 0; + } + break; + case GL_SAMPLES: + *params = framebuffer->getSamples(); + break; + } + } + else + { + *params = 0; + } + } + break; + case GL_VIEWPORT: + params[0] = mViewport.x; + params[1] = mViewport.y; + params[2] = mViewport.width; + params[3] = mViewport.height; + break; + case GL_SCISSOR_BOX: + params[0] = mScissor.x; + params[1] = mScissor.y; + params[2] = mScissor.width; + params[3] = mScissor.height; + break; + case GL_CULL_FACE_MODE: *params = mRasterizer.cullMode; break; + case GL_FRONT_FACE: *params = mRasterizer.frontFace; break; + case GL_RED_BITS: + case GL_GREEN_BITS: + case GL_BLUE_BITS: + case GL_ALPHA_BITS: + { + gl::Framebuffer *framebuffer = getDrawFramebuffer(); + gl::FramebufferAttachment *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; + } + } + else + { + *params = 0; + } + } + break; + case GL_DEPTH_BITS: + { + gl::Framebuffer *framebuffer = getDrawFramebuffer(); + gl::FramebufferAttachment *depthbuffer = framebuffer->getDepthbuffer(); + + if (depthbuffer) + { + *params = depthbuffer->getDepthSize(); + } + else + { + *params = 0; + } + } + break; + case GL_STENCIL_BITS: + { + gl::Framebuffer *framebuffer = getDrawFramebuffer(); + gl::FramebufferAttachment *stencilbuffer = framebuffer->getStencilbuffer(); + + if (stencilbuffer) + { + *params = stencilbuffer->getStencilSize(); + } + else + { + *params = 0; + } + } + break; + case GL_TEXTURE_BINDING_2D: + ASSERT(mActiveSampler < mContext->getCaps().maxCombinedTextureImageUnits); + *params = mSamplerTexture[TEXTURE_2D][mActiveSampler].id(); + break; + case GL_TEXTURE_BINDING_CUBE_MAP: + ASSERT(mActiveSampler < mContext->getCaps().maxCombinedTextureImageUnits); + *params = mSamplerTexture[TEXTURE_CUBE][mActiveSampler].id(); + break; + case GL_TEXTURE_BINDING_3D: + ASSERT(mActiveSampler getCaps().maxCombinedTextureImageUnits); + *params = mSamplerTexture[TEXTURE_3D][mActiveSampler].id(); + break; + case GL_TEXTURE_BINDING_2D_ARRAY: + ASSERT(mActiveSampler < mContext->getCaps().maxCombinedTextureImageUnits); + *params = mSamplerTexture[TEXTURE_2D_ARRAY][mActiveSampler].id(); + break; + case GL_UNIFORM_BUFFER_BINDING: + *params = mGenericUniformBuffer.id(); + break; + case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: + *params = mGenericTransformFeedbackBuffer.id(); + break; + case GL_COPY_READ_BUFFER_BINDING: + *params = mCopyReadBuffer.id(); + break; + case GL_COPY_WRITE_BUFFER_BINDING: + *params = mCopyWriteBuffer.id(); + break; + case GL_PIXEL_PACK_BUFFER_BINDING: + *params = mPack.pixelBuffer.id(); + break; + case GL_PIXEL_UNPACK_BUFFER_BINDING: + *params = mUnpack.pixelBuffer.id(); + break; + default: + UNREACHABLE(); + break; + } +} + +bool State::getIndexedIntegerv(GLenum target, GLuint index, GLint *data) +{ + switch (target) + { + case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: + if (index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS) + { + *data = mTransformFeedbackBuffers[index].id(); + } + break; + case GL_UNIFORM_BUFFER_BINDING: + if (index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS) + { + *data = mUniformBuffers[index].id(); + } + break; + default: + return false; + } + + return true; +} + +bool State::getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data) +{ + switch (target) + { + case GL_TRANSFORM_FEEDBACK_BUFFER_START: + if (index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS) + { + *data = mTransformFeedbackBuffers[index].getOffset(); + } + break; + case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: + if (index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS) + { + *data = mTransformFeedbackBuffers[index].getSize(); + } + break; + case GL_UNIFORM_BUFFER_START: + if (index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS) + { + *data = mUniformBuffers[index].getOffset(); + } + break; + case GL_UNIFORM_BUFFER_SIZE: + if (index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS) + { + *data = mUniformBuffers[index].getSize(); + } + break; + default: + return false; + } + + return true; +} + +bool State::hasMappedBuffer(GLenum target) const +{ + if (target == GL_ARRAY_BUFFER) + { + for (unsigned int attribIndex = 0; attribIndex < gl::MAX_VERTEX_ATTRIBS; attribIndex++) + { + const gl::VertexAttribute &vertexAttrib = getVertexAttribState(attribIndex); + gl::Buffer *boundBuffer = vertexAttrib.buffer.get(); + if (vertexAttrib.enabled && boundBuffer && boundBuffer->isMapped()) + { + return true; + } + } + + return false; + } + else + { + Buffer *buffer = getTargetBuffer(target); + return (buffer && buffer->isMapped()); + } +} + +} diff --git a/gfx/angle/src/libGLESv2/State.h b/gfx/angle/src/libGLESv2/State.h new file mode 100644 index 000000000000..d3b3edc5a042 --- /dev/null +++ b/gfx/angle/src/libGLESv2/State.h @@ -0,0 +1,309 @@ +// +// Copyright (c) 2014 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. +// + +// State.h: Defines the State class, encapsulating raw GL state + +#ifndef LIBGLESV2_STATE_H_ +#define LIBGLESV2_STATE_H_ + +#include "common/angleutils.h" +#include "common/RefCountObject.h" +#include "libGLESv2/angletypes.h" +#include "libGLESv2/VertexAttribute.h" +#include "libGLESv2/Renderbuffer.h" +#include "libGLESv2/Texture.h" +#include "libGLESv2/TransformFeedback.h" +#include "libGLESv2/Program.h" +#include "libGLESv2/Sampler.h" + +namespace gl +{ +class Query; +class VertexArray; +class Context; + +class State +{ + public: + State(); + ~State(); + + void setContext(Context *context) { mContext = context; } + + // State chunk getters + const RasterizerState &getRasterizerState() const; + const BlendState &getBlendState() const; + const DepthStencilState &getDepthStencilState() const; + + // Clear behavior setters & state parameter block generation function + void setClearColor(float red, float green, float blue, float alpha); + void setClearDepth(float depth); + void setClearStencil(int stencil); + ClearParameters getClearParameters(GLbitfield mask) const; + + // Write mask manipulation + void setColorMask(bool red, bool green, bool blue, bool alpha); + void setDepthMask(bool mask); + + // Discard toggle & query + bool isRasterizerDiscardEnabled() const; + void setRasterizerDiscard(bool enabled); + + // Face culling state manipulation + bool isCullFaceEnabled() const; + void setCullFace(bool enabled); + void setCullMode(GLenum mode); + void setFrontFace(GLenum front); + + // Depth test state manipulation + bool isDepthTestEnabled() const; + void setDepthTest(bool enabled); + void setDepthFunc(GLenum depthFunc); + void setDepthRange(float zNear, float zFar); + void getDepthRange(float *zNear, float *zFar) const; + + // Blend state manipulation + bool isBlendEnabled() const; + void setBlend(bool enabled); + void setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha); + void setBlendColor(float red, float green, float blue, float alpha); + void setBlendEquation(GLenum rgbEquation, GLenum alphaEquation); + const ColorF &getBlendColor() const; + + // Stencil state maniupulation + bool isStencilTestEnabled() const; + void setStencilTest(bool enabled); + void setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask); + void setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask); + void setStencilWritemask(GLuint stencilWritemask); + void setStencilBackWritemask(GLuint stencilBackWritemask); + void setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass); + void setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass); + GLint getStencilRef() const; + GLint getStencilBackRef() const; + + // Depth bias/polygon offset state manipulation + bool isPolygonOffsetFillEnabled() const; + void setPolygonOffsetFill(bool enabled); + void setPolygonOffsetParams(GLfloat factor, GLfloat units); + + // Multisample coverage state manipulation + bool isSampleAlphaToCoverageEnabled() const; + void setSampleAlphaToCoverage(bool enabled); + bool isSampleCoverageEnabled() const; + void setSampleCoverage(bool enabled); + void setSampleCoverageParams(GLclampf value, bool invert); + void getSampleCoverageParams(GLclampf *value, bool *invert); + + // Scissor test state toggle & query + bool isScissorTestEnabled() const; + void setScissorTest(bool enabled); + void setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height); + const Rectangle &getScissor() const; + + // Dither state toggle & query + bool isDitherEnabled() const; + void setDither(bool enabled); + + // Generic state toggle & query + void setEnableFeature(GLenum feature, bool enabled); + bool getEnableFeature(GLenum feature); + + // Line width state setter + void setLineWidth(GLfloat width); + + // Hint setters + void setGenerateMipmapHint(GLenum hint); + void setFragmentShaderDerivativeHint(GLenum hint); + + // Viewport state setter/getter + void setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height); + const Rectangle &getViewport() const; + + // Texture binding & active texture unit manipulation + void setActiveSampler(unsigned int active); + unsigned int getActiveSampler() const; + void setSamplerTexture(TextureType type, Texture *texture); + Texture *getSamplerTexture(unsigned int sampler, TextureType type) const; + GLuint getSamplerTextureId(unsigned int sampler, TextureType type) const; + void detachTexture(GLuint texture); + + // Sampler object binding manipulation + void setSamplerBinding(GLuint textureUnit, Sampler *sampler); + GLuint getSamplerId(GLuint textureUnit) const; + Sampler *getSampler(GLuint textureUnit) const; + void detachSampler(GLuint sampler); + + // Renderbuffer binding manipulation + void setRenderbufferBinding(Renderbuffer *renderbuffer); + GLuint getRenderbufferId() const; + Renderbuffer *getCurrentRenderbuffer(); + void detachRenderbuffer(GLuint renderbuffer); + + // Framebuffer binding manipulation + void setReadFramebufferBinding(Framebuffer *framebuffer); + void setDrawFramebufferBinding(Framebuffer *framebuffer); + Framebuffer *getTargetFramebuffer(GLenum target) const; + Framebuffer *getReadFramebuffer(); + Framebuffer *getDrawFramebuffer(); + const Framebuffer *getReadFramebuffer() const; + const Framebuffer *getDrawFramebuffer() const; + bool removeReadFramebufferBinding(GLuint framebuffer); + bool removeDrawFramebufferBinding(GLuint framebuffer); + + // Vertex array object binding manipulation + void setVertexArrayBinding(VertexArray *vertexArray); + GLuint getVertexArrayId() const; + VertexArray *getVertexArray() const; + bool removeVertexArrayBinding(GLuint vertexArray); + + // Program binding manipulation + void setCurrentProgram(GLuint programId, Program *newProgram); + void setCurrentProgramBinary(ProgramBinary *binary); + GLuint getCurrentProgramId() const; + ProgramBinary *getCurrentProgramBinary() const; + + // Transform feedback object (not buffer) binding manipulation + void setTransformFeedbackBinding(TransformFeedback *transformFeedback); + TransformFeedback *getCurrentTransformFeedback() const; + void detachTransformFeedback(GLuint transformFeedback); + + // Query binding manipulation + bool isQueryActive() const; + void setActiveQuery(GLenum target, Query *query); + GLuint getActiveQueryId(GLenum target) const; + Query *getActiveQuery(GLenum target) const; + + //// Typed buffer binding point manipulation //// + // GL_ARRAY_BUFFER + void setArrayBufferBinding(Buffer *buffer); + GLuint getArrayBufferId() const; + bool removeArrayBufferBinding(GLuint buffer); + + // GL_UNIFORM_BUFFER - Both indexed and generic targets + void setGenericUniformBufferBinding(Buffer *buffer); + void setIndexedUniformBufferBinding(GLuint index, Buffer *buffer, GLintptr offset, GLsizeiptr size); + GLuint getIndexedUniformBufferId(GLuint index) const; + Buffer *getIndexedUniformBuffer(GLuint index) const; + + // GL_TRANSFORM_FEEDBACK_BUFFER - Both indexed and generic targets + void setGenericTransformFeedbackBufferBinding(Buffer *buffer); + void setIndexedTransformFeedbackBufferBinding(GLuint index, Buffer *buffer, GLintptr offset, GLsizeiptr size); + GLuint getIndexedTransformFeedbackBufferId(GLuint index) const; + Buffer *getIndexedTransformFeedbackBuffer(GLuint index) const; + GLuint getIndexedTransformFeedbackBufferOffset(GLuint index) const; + + // GL_COPY_[READ/WRITE]_BUFFER + void setCopyReadBufferBinding(Buffer *buffer); + void setCopyWriteBufferBinding(Buffer *buffer); + + // GL_PIXEL[PACK/UNPACK]_BUFFER + void setPixelPackBufferBinding(Buffer *buffer); + void setPixelUnpackBufferBinding(Buffer *buffer); + + // Retrieve typed buffer by target (non-indexed) + Buffer *getTargetBuffer(GLenum target) const; + + // Vertex attrib manipulation + void setEnableVertexAttribArray(unsigned int attribNum, bool enabled); + void setVertexAttribf(GLuint index, const GLfloat values[4]); + void setVertexAttribu(GLuint index, const GLuint values[4]); + void setVertexAttribi(GLuint index, const GLint values[4]); + void setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type, + bool normalized, bool pureInteger, GLsizei stride, const void *pointer); + const VertexAttribute &getVertexAttribState(unsigned int attribNum) const; + const VertexAttribCurrentValueData &getVertexAttribCurrentValue(unsigned int attribNum) const; + const VertexAttribCurrentValueData *getVertexAttribCurrentValues() const; + const void *getVertexAttribPointer(unsigned int attribNum) const; + + // Pixel pack state manipulation + void setPackAlignment(GLint alignment); + GLint getPackAlignment() const; + void setPackReverseRowOrder(bool reverseRowOrder); + bool getPackReverseRowOrder() const; + const PixelPackState &getPackState() const; + + // Pixel unpack state manipulation + void setUnpackAlignment(GLint alignment); + GLint getUnpackAlignment() const; + const PixelUnpackState &getUnpackState() const; + + // State query functions + void getBooleanv(GLenum pname, GLboolean *params); + void getFloatv(GLenum pname, GLfloat *params); + void getIntegerv(GLenum pname, GLint *params); + bool getIndexedIntegerv(GLenum target, GLuint index, GLint *data); + bool getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data); + + bool hasMappedBuffer(GLenum target) const; + + private: + DISALLOW_COPY_AND_ASSIGN(State); + + Context *mContext; + + ColorF mColorClearValue; + GLclampf mDepthClearValue; + int mStencilClearValue; + + RasterizerState mRasterizer; + bool mScissorTest; + Rectangle mScissor; + + BlendState mBlend; + ColorF mBlendColor; + bool mSampleCoverage; + GLclampf mSampleCoverageValue; + bool mSampleCoverageInvert; + + DepthStencilState mDepthStencil; + GLint mStencilRef; + GLint mStencilBackRef; + + GLfloat mLineWidth; + + GLenum mGenerateMipmapHint; + GLenum mFragmentShaderDerivativeHint; + + Rectangle mViewport; + float mNearZ; + float mFarZ; + + unsigned int mActiveSampler; // Active texture unit selector - GL_TEXTURE0 + BindingPointer mArrayBuffer; + Framebuffer *mReadFramebuffer; + Framebuffer *mDrawFramebuffer; + BindingPointer mRenderbuffer; + GLuint mCurrentProgramId; + BindingPointer mCurrentProgramBinary; + + VertexAttribCurrentValueData mVertexAttribCurrentValues[MAX_VERTEX_ATTRIBS]; // From glVertexAttrib + VertexArray *mVertexArray; + + BindingPointer mSamplerTexture[TEXTURE_TYPE_COUNT][IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS]; + BindingPointer mSamplers[IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS]; + + typedef std::map< GLenum, BindingPointer > ActiveQueryMap; + ActiveQueryMap mActiveQueries; + + BindingPointer mGenericUniformBuffer; + OffsetBindingPointer mUniformBuffers[IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS]; + + BindingPointer mTransformFeedback; + BindingPointer mGenericTransformFeedbackBuffer; + OffsetBindingPointer mTransformFeedbackBuffers[IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; + + BindingPointer mCopyReadBuffer; + BindingPointer mCopyWriteBuffer; + + PixelUnpackState mUnpack; + PixelPackState mPack; +}; + +} + +#endif // LIBGLESV2_STATE_H_ + diff --git a/gfx/angle/src/libGLESv2/Texture.cpp b/gfx/angle/src/libGLESv2/Texture.cpp index 68d368b67184..4f7453282d2c 100644 --- a/gfx/angle/src/libGLESv2/Texture.cpp +++ b/gfx/angle/src/libGLESv2/Texture.cpp @@ -1,6 +1,5 @@ -#include "precompiled.h" // -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2014 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,24 +9,23 @@ // functionality. [OpenGL ES 2.0.24] section 3.7 page 63. #include "libGLESv2/Texture.h" - #include "libGLESv2/main.h" -#include "common/mathutil.h" -#include "common/utilities.h" +#include "libGLESv2/Context.h" #include "libGLESv2/formatutils.h" #include "libGLESv2/Renderbuffer.h" #include "libGLESv2/renderer/Image.h" -#include "libGLESv2/renderer/Renderer.h" -#include "libGLESv2/renderer/TextureStorage.h" -#include "libEGL/Surface.h" -#include "libGLESv2/Buffer.h" -#include "libGLESv2/renderer/BufferStorage.h" #include "libGLESv2/renderer/RenderTarget.h" +#include "libGLESv2/renderer/d3d/TextureStorage.h" + +#include "libEGL/Surface.h" + +#include "common/mathutil.h" +#include "common/utilities.h" namespace gl { -bool IsMipmapFiltered(const SamplerState &samplerState) +bool IsMipmapFiltered(const gl::SamplerState &samplerState) { switch (samplerState.minFilter) { @@ -44,42 +42,23 @@ bool IsMipmapFiltered(const SamplerState &samplerState) } } -bool IsRenderTargetUsage(GLenum usage) +bool IsPointSampled(const gl::SamplerState &samplerState) { - return (usage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE); + return (samplerState.magFilter == GL_NEAREST && (samplerState.minFilter == GL_NEAREST || samplerState.minFilter == GL_NEAREST_MIPMAP_NEAREST)); } -Texture::Texture(rx::Renderer *renderer, GLuint id, GLenum target) : RefCountObject(id) +Texture::Texture(rx::TextureImpl *impl, GLuint id, GLenum target) + : RefCountObject(id), + mTexture(impl), + mUsage(GL_NONE), + mImmutable(false), + mTarget(target) { - mRenderer = renderer; - - mSamplerState.minFilter = GL_NEAREST_MIPMAP_LINEAR; - mSamplerState.magFilter = GL_LINEAR; - mSamplerState.wrapS = GL_REPEAT; - mSamplerState.wrapT = GL_REPEAT; - mSamplerState.wrapR = GL_REPEAT; - mSamplerState.maxAnisotropy = 1.0f; - mSamplerState.baseLevel = 0; - mSamplerState.maxLevel = 1000; - mSamplerState.minLod = -1000.0f; - mSamplerState.maxLod = 1000.0f; - mSamplerState.compareMode = GL_NONE; - mSamplerState.compareFunc = GL_LEQUAL; - mSamplerState.swizzleRed = GL_RED; - mSamplerState.swizzleGreen = GL_GREEN; - mSamplerState.swizzleBlue = GL_BLUE; - mSamplerState.swizzleAlpha = GL_ALPHA; - mUsage = GL_NONE; - - mDirtyImages = true; - - mImmutable = false; - - mTarget = target; } Texture::~Texture() { + SafeDelete(mTexture); } GLenum Texture::getTarget() const @@ -87,180 +66,13 @@ GLenum Texture::getTarget() const return mTarget; } -void Texture::addProxyRef(const Renderbuffer *proxy) -{ - mRenderbufferProxies.addRef(proxy); -} - -void Texture::releaseProxy(const Renderbuffer *proxy) -{ - mRenderbufferProxies.release(proxy); -} - -void Texture::setMinFilter(GLenum filter) -{ - mSamplerState.minFilter = filter; -} - -void Texture::setMagFilter(GLenum filter) -{ - mSamplerState.magFilter = filter; -} - -void Texture::setWrapS(GLenum wrap) -{ - mSamplerState.wrapS = wrap; -} - -void Texture::setWrapT(GLenum wrap) -{ - mSamplerState.wrapT = wrap; -} - -void Texture::setWrapR(GLenum wrap) -{ - mSamplerState.wrapR = wrap; -} - -void Texture::setMaxAnisotropy(float textureMaxAnisotropy, float contextMaxAnisotropy) -{ - mSamplerState.maxAnisotropy = std::min(textureMaxAnisotropy, contextMaxAnisotropy); -} - -void Texture::setCompareMode(GLenum mode) -{ - mSamplerState.compareMode = mode; -} - -void Texture::setCompareFunc(GLenum func) -{ - mSamplerState.compareFunc = func; -} - -void Texture::setSwizzleRed(GLenum swizzle) -{ - mSamplerState.swizzleRed = swizzle; -} - -void Texture::setSwizzleGreen(GLenum swizzle) -{ - mSamplerState.swizzleGreen = swizzle; -} - -void Texture::setSwizzleBlue(GLenum swizzle) -{ - mSamplerState.swizzleBlue = swizzle; -} - -void Texture::setSwizzleAlpha(GLenum swizzle) -{ - mSamplerState.swizzleAlpha = swizzle; -} - -void Texture::setBaseLevel(GLint baseLevel) -{ - mSamplerState.baseLevel = baseLevel; -} - -void Texture::setMaxLevel(GLint maxLevel) -{ - mSamplerState.maxLevel = maxLevel; -} - -void Texture::setMinLod(GLfloat minLod) -{ - mSamplerState.minLod = minLod; -} - -void Texture::setMaxLod(GLfloat maxLod) -{ - mSamplerState.maxLod = maxLod; -} - void Texture::setUsage(GLenum usage) { mUsage = usage; + getImplementation()->setUsage(usage); } -GLenum Texture::getMinFilter() const -{ - return mSamplerState.minFilter; -} - -GLenum Texture::getMagFilter() const -{ - return mSamplerState.magFilter; -} - -GLenum Texture::getWrapS() const -{ - return mSamplerState.wrapS; -} - -GLenum Texture::getWrapT() const -{ - return mSamplerState.wrapT; -} - -GLenum Texture::getWrapR() const -{ - return mSamplerState.wrapR; -} - -float Texture::getMaxAnisotropy() const -{ - return mSamplerState.maxAnisotropy; -} - -GLenum Texture::getSwizzleRed() const -{ - return mSamplerState.swizzleRed; -} - -GLenum Texture::getSwizzleGreen() const -{ - return mSamplerState.swizzleGreen; -} - -GLenum Texture::getSwizzleBlue() const -{ - return mSamplerState.swizzleBlue; -} - -GLenum Texture::getSwizzleAlpha() const -{ - return mSamplerState.swizzleAlpha; -} - -GLint Texture::getBaseLevel() const -{ - return mSamplerState.baseLevel; -} - -GLint Texture::getMaxLevel() const -{ - return mSamplerState.maxLevel; -} - -GLfloat Texture::getMinLod() const -{ - return mSamplerState.minLod; -} - -GLfloat Texture::getMaxLod() const -{ - return mSamplerState.maxLod; -} - -bool Texture::isSwizzled() const -{ - return mSamplerState.swizzleRed != GL_RED || - mSamplerState.swizzleGreen != GL_GREEN || - mSamplerState.swizzleBlue != GL_BLUE || - mSamplerState.swizzleAlpha != GL_ALPHA; -} - -void Texture::getSamplerState(SamplerState *sampler) +void Texture::getSamplerStateWithNativeOffset(SamplerState *sampler) { *sampler = mSamplerState; @@ -302,122 +114,19 @@ GLenum Texture::getBaseLevelInternalFormat() const return (baseImage ? baseImage->getInternalFormat() : GL_NONE); } -void Texture::setImage(const PixelUnpackState &unpack, GLenum type, const void *pixels, rx::Image *image) -{ - // No-op - if (image->getWidth() == 0 || image->getHeight() == 0 || image->getDepth() == 0) - { - return; - } - - // We no longer need the "GLenum format" parameter to TexImage to determine what data format "pixels" contains. - // From our image internal format we know how many channels to expect, and "type" gives the format of pixel's components. - const void *pixelData = pixels; - - if (unpack.pixelBuffer.id() != 0) - { - // Do a CPU readback here, if we have an unpack buffer bound and the fast GPU path is not supported - Buffer *pixelBuffer = unpack.pixelBuffer.get(); - ptrdiff_t offset = reinterpret_cast(pixels); - const void *bufferData = pixelBuffer->getStorage()->getData(); - pixelData = static_cast(bufferData) + offset; - } - - if (pixelData != NULL) - { - image->loadData(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth(), unpack.alignment, type, pixelData); - mDirtyImages = true; - } -} - -bool Texture::isFastUnpackable(const PixelUnpackState &unpack, GLenum sizedInternalFormat) -{ - return unpack.pixelBuffer.id() != 0 && mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat); -} - -bool Texture::fastUnpackPixels(const PixelUnpackState &unpack, const void *pixels, const Box &destArea, - GLenum sizedInternalFormat, GLenum type, rx::RenderTarget *destRenderTarget) -{ - if (destArea.width <= 0 && destArea.height <= 0 && destArea.depth <= 0) - { - return true; - } - - // In order to perform the fast copy through the shader, we must have the right format, and be able - // to create a render target. - ASSERT(mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat)); - - unsigned int offset = reinterpret_cast(pixels); - - return mRenderer->fastCopyBufferToTexture(unpack, offset, destRenderTarget, sizedInternalFormat, type, destArea); -} - -void Texture::setCompressedImage(GLsizei imageSize, const void *pixels, rx::Image *image) -{ - if (pixels != NULL) - { - image->loadCompressedData(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth(), pixels); - mDirtyImages = true; - } -} - -bool Texture::subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels, rx::Image *image) -{ - const void *pixelData = pixels; - - // CPU readback & copy where direct GPU copy is not supported - if (unpack.pixelBuffer.id() != 0) - { - Buffer *pixelBuffer = unpack.pixelBuffer.get(); - unsigned int offset = reinterpret_cast(pixels); - const void *bufferData = pixelBuffer->getStorage()->getData(); - pixelData = static_cast(bufferData) + offset; - } - - if (pixelData != NULL) - { - image->loadData(xoffset, yoffset, zoffset, width, height, depth, unpack.alignment, type, pixelData); - mDirtyImages = true; - } - - return true; -} - -bool Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLsizei imageSize, const void *pixels, rx::Image *image) -{ - if (pixels != NULL) - { - image->loadCompressedData(xoffset, yoffset, zoffset, width, height, depth, pixels); - mDirtyImages = true; - } - - return true; -} - rx::TextureStorageInterface *Texture::getNativeTexture() { - // ensure the underlying texture is created - initializeStorage(false); - - rx::TextureStorageInterface *storage = getBaseLevelStorage(); - if (storage) - { - updateStorage(); - } - - return storage; + return getImplementation()->getNativeTexture(); } -bool Texture::hasDirtyImages() const +void Texture::generateMipmaps() { - return mDirtyImages; + getImplementation()->generateMipmaps(); } -void Texture::resetDirty() +void Texture::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) { - mDirtyImages = false; + getImplementation()->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, source); } unsigned int Texture::getTextureSerial() @@ -436,57 +145,35 @@ int Texture::immutableLevelCount() return (mImmutable ? getNativeTexture()->getStorageInstance()->getLevelCount() : 0); } -GLint Texture::creationLevels(GLsizei width, GLsizei height, GLsizei depth) const -{ - if ((isPow2(width) && isPow2(height) && isPow2(depth)) || mRenderer->getNonPower2TextureSupport()) - { - // Maximum number of levels - return log2(std::max(std::max(width, height), depth)) + 1; - } - else - { - // OpenGL ES 2.0 without GL_OES_texture_npot does not permit NPOT mipmaps. - return 1; - } -} - int Texture::mipLevels() const { return log2(std::max(std::max(getBaseLevelWidth(), getBaseLevelHeight()), getBaseLevelDepth())) + 1; } -Texture2D::Texture2D(rx::Renderer *renderer, GLuint id) : Texture(renderer, id, GL_TEXTURE_2D) +const rx::Image *Texture::getBaseLevelImage() const { - mTexStorage = NULL; - mSurface = NULL; + return (getImplementation()->getLayerCount(0) > 0 ? getImplementation()->getImage(0, 0) : NULL); +} - for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i) - { - mImageArray[i] = renderer->createImage(); - } +Texture2D::Texture2D(rx::TextureImpl *impl, GLuint id) + : Texture(impl, id, GL_TEXTURE_2D) +{ + mSurface = NULL; } Texture2D::~Texture2D() { - delete mTexStorage; - mTexStorage = NULL; - if (mSurface) { mSurface->setBoundTexture(NULL); mSurface = NULL; } - - for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i) - { - delete mImageArray[i]; - } } GLsizei Texture2D::getWidth(GLint level) const { if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mImageArray[level]->getWidth(); + return mTexture->getImage(level, 0)->getWidth(); else return 0; } @@ -494,7 +181,7 @@ GLsizei Texture2D::getWidth(GLint level) const GLsizei Texture2D::getHeight(GLint level) const { if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mImageArray[level]->getHeight(); + return mTexture->getImage(level, 0)->getHeight(); else return 0; } @@ -502,7 +189,7 @@ GLsizei Texture2D::getHeight(GLint level) const GLenum Texture2D::getInternalFormat(GLint level) const { if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mImageArray[level]->getInternalFormat(); + return mTexture->getImage(level, 0)->getInternalFormat(); else return GL_NONE; } @@ -510,86 +197,24 @@ GLenum Texture2D::getInternalFormat(GLint level) const GLenum Texture2D::getActualFormat(GLint level) const { if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mImageArray[level]->getActualFormat(); + return mTexture->getImage(level, 0)->getActualFormat(); else return GL_NONE; } -void Texture2D::redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height) +void Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { releaseTexImage(); - // If there currently is a corresponding storage texture image, it has these parameters - const int storageWidth = std::max(1, getBaseLevelWidth() >> level); - const int storageHeight = std::max(1, getBaseLevelHeight() >> level); - const GLenum storageFormat = getBaseLevelInternalFormat(); - - mImageArray[level]->redefine(mRenderer, GL_TEXTURE_2D, internalformat, width, height, 1, false); - - if (mTexStorage) - { - const int storageLevels = mTexStorage->getLevelCount(); - - if ((level >= storageLevels && storageLevels != 0) || - width != storageWidth || - height != storageHeight || - internalformat != storageFormat) // Discard mismatched storage - { - for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) - { - mImageArray[i]->markDirty(); - } - - delete mTexStorage; - mTexStorage = NULL; - mDirtyImages = true; - } - } -} - -void Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) -{ - GLuint clientVersion = mRenderer->getCurrentClientVersion(); - GLenum sizedInternalFormat = IsSizedInternalFormat(internalFormat, clientVersion) ? internalFormat - : GetSizedInternalFormat(format, type, clientVersion); - redefineImage(level, sizedInternalFormat, width, height); - - bool fastUnpacked = false; - - // Attempt a fast gpu copy of the pixel data to the surface - if (isFastUnpackable(unpack, sizedInternalFormat) && isLevelComplete(level)) - { - // Will try to create RT storage if it does not exist - rx::RenderTarget *destRenderTarget = getRenderTarget(level); - Box destArea(0, 0, 0, getWidth(level), getHeight(level), 1); - - if (destRenderTarget && fastUnpackPixels(unpack, pixels, destArea, sizedInternalFormat, type, destRenderTarget)) - { - // Ensure we don't overwrite our newly initialized data - mImageArray[level]->markClean(); - - fastUnpacked = true; - } - } - - if (!fastUnpacked) - { - Texture::setImage(unpack, type, pixels, mImageArray[level]); - } + mTexture->setImage(GL_TEXTURE_2D, level, width, height, 1, internalFormat, format, type, unpack, pixels); } void Texture2D::bindTexImage(egl::Surface *surface) { releaseTexImage(); - GLenum internalformat = surface->getFormat(); + mTexture->bindTexImage(surface); - mImageArray[0]->redefine(mRenderer, GL_TEXTURE_2D, internalformat, surface->getWidth(), surface->getHeight(), 1, true); - - delete mTexStorage; - mTexStorage = new rx::TextureStorageInterface2D(mRenderer, surface->getSwapChain()); - - mDirtyImages = true; mSurface = surface; mSurface->setBoundTexture(this); } @@ -601,177 +226,43 @@ void Texture2D::releaseTexImage() mSurface->setBoundTexture(NULL); mSurface = NULL; - if (mTexStorage) - { - delete mTexStorage; - mTexStorage = NULL; - } - - for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) - { - mImageArray[i]->redefine(mRenderer, GL_TEXTURE_2D, GL_NONE, 0, 0, 0, true); - } + mTexture->releaseTexImage(); } } void Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels) { - // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly - redefineImage(level, format, width, height); + releaseTexImage(); - Texture::setCompressedImage(imageSize, pixels, mImageArray[level]); -} - -void Texture2D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) -{ - if (isValidLevel(level)) - { - rx::Image *image = mImageArray[level]; - if (image->copyToStorage(mTexStorage, level, xoffset, yoffset, width, height)) - { - image->markClean(); - } - } + mTexture->setCompressedImage(GL_TEXTURE_2D, level, format, width, height, 1, imageSize, pixels); } void Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - bool fastUnpacked = false; - - if (isFastUnpackable(unpack, getInternalFormat(level)) && isLevelComplete(level)) - { - rx::RenderTarget *renderTarget = getRenderTarget(level); - Box destArea(xoffset, yoffset, 0, width, height, 1); - - if (renderTarget && fastUnpackPixels(unpack, pixels, destArea, getInternalFormat(level), type, renderTarget)) - { - // Ensure we don't overwrite our newly initialized data - mImageArray[level]->markClean(); - - fastUnpacked = true; - } - } - - if (!fastUnpacked && Texture::subImage(xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels, mImageArray[level])) - { - commitRect(level, xoffset, yoffset, width, height); - } + mTexture->subImage(GL_TEXTURE_2D, level, xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels); } 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, 0, width, height, 1, format, imageSize, pixels, mImageArray[level])) - { - commitRect(level, xoffset, yoffset, width, height); - } + mTexture->subImageCompressed(GL_TEXTURE_2D, level, xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels); } void Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) { - GLuint clientVersion = mRenderer->getCurrentClientVersion(); - GLenum sizedInternalFormat = IsSizedInternalFormat(format, clientVersion) ? format - : GetSizedInternalFormat(format, GL_UNSIGNED_BYTE, clientVersion); - redefineImage(level, sizedInternalFormat, width, height); + releaseTexImage(); - if (!mImageArray[level]->isRenderableFormat()) - { - mImageArray[level]->copy(0, 0, 0, x, y, width, height, source); - mDirtyImages = true; - } - else - { - ensureRenderTarget(); - mImageArray[level]->markClean(); - - if (width != 0 && height != 0 && isValidLevel(level)) - { - gl::Rectangle sourceRect; - sourceRect.x = x; - sourceRect.width = width; - sourceRect.y = y; - sourceRect.height = height; - - mRenderer->copyImage(source, sourceRect, format, 0, 0, mTexStorage, level); - } - } -} - -void Texture2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) -{ - if (xoffset + width > mImageArray[level]->getWidth() || yoffset + height > mImageArray[level]->getHeight() || zoffset != 0) - { - return gl::error(GL_INVALID_VALUE); - } - - // can only make our texture storage to a render target if level 0 is defined (with a width & height) and - // the current level we're copying to is defined (with appropriate format, width & height) - bool canCreateRenderTarget = isLevelComplete(level) && isLevelComplete(0); - - if (!mImageArray[level]->isRenderableFormat() || (!mTexStorage && !canCreateRenderTarget)) - { - mImageArray[level]->copy(xoffset, yoffset, 0, x, y, width, height, source); - mDirtyImages = true; - } - else - { - ensureRenderTarget(); - - if (isValidLevel(level)) - { - updateStorageLevel(level); - - GLuint clientVersion = mRenderer->getCurrentClientVersion(); - - gl::Rectangle sourceRect; - sourceRect.x = x; - sourceRect.width = width; - sourceRect.y = y; - sourceRect.height = height; - - mRenderer->copyImage(source, sourceRect, - gl::GetFormat(getBaseLevelInternalFormat(), clientVersion), - xoffset, yoffset, mTexStorage, level); - } - } + mTexture->copyImage(GL_TEXTURE_2D, level, format, x, y, width, height, source); } void Texture2D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) { - for (int level = 0; level < levels; level++) - { - GLsizei levelWidth = std::max(1, width >> level); - GLsizei levelHeight = std::max(1, height >> level); - mImageArray[level]->redefine(mRenderer, GL_TEXTURE_2D, internalformat, levelWidth, levelHeight, 1, true); - } - - for (int level = levels; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) - { - mImageArray[level]->redefine(mRenderer, GL_TEXTURE_2D, GL_NONE, 0, 0, 0, true); - } - mImmutable = true; - setCompleteTexStorage(new rx::TextureStorageInterface2D(mRenderer, internalformat, IsRenderTargetUsage(mUsage), width, height, levels)); -} - -void Texture2D::setCompleteTexStorage(rx::TextureStorageInterface2D *newCompleteTexStorage) -{ - SafeDelete(mTexStorage); - mTexStorage = newCompleteTexStorage; - - if (mTexStorage && mTexStorage->isManaged()) - { - for (int level = 0; level < mTexStorage->getLevelCount(); level++) - { - mImageArray[level]->setManagedSurface(mTexStorage, level); - } - } - - mDirtyImages = true; + mTexture->storage(GL_TEXTURE_2D, levels, internalformat, width, height, 1); } // Tests for 2D texture sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 85. -bool Texture2D::isSamplerComplete(const SamplerState &samplerState) const +bool Texture2D::isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const { GLsizei width = getBaseLevelWidth(); GLsizei height = getBaseLevelHeight(); @@ -781,21 +272,17 @@ bool Texture2D::isSamplerComplete(const SamplerState &samplerState) const return false; } - if (!IsTextureFilteringSupported(getInternalFormat(0), mRenderer)) + if (!textureCaps.get(getInternalFormat(0)).filterable && !IsPointSampled(samplerState)) { - if (samplerState.magFilter != GL_NEAREST || - (samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST)) - { - return false; - } + return false; } - bool npotSupport = mRenderer->getNonPower2TextureSupport(); + bool npotSupport = extensions.textureNPOT; if (!npotSupport) { - if ((samplerState.wrapS != GL_CLAMP_TO_EDGE && !isPow2(width)) || - (samplerState.wrapT != GL_CLAMP_TO_EDGE && !isPow2(height))) + if ((samplerState.wrapS != GL_CLAMP_TO_EDGE && !gl::isPow2(width)) || + (samplerState.wrapT != GL_CLAMP_TO_EDGE && !gl::isPow2(height))) { return false; } @@ -805,7 +292,7 @@ bool Texture2D::isSamplerComplete(const SamplerState &samplerState) const { if (!npotSupport) { - if (!isPow2(width) || !isPow2(height)) + if (!gl::isPow2(width) || !gl::isPow2(height)) { return false; } @@ -822,13 +309,13 @@ bool Texture2D::isSamplerComplete(const SamplerState &samplerState) const // depth and stencil format (see table 3.13), the value of TEXTURE_COMPARE_- // MODE is NONE, and either the magnification filter is not NEAREST or the mini- // fication filter is neither NEAREST nor NEAREST_MIPMAP_NEAREST. - if (gl::GetDepthBits(getInternalFormat(0), mRenderer->getCurrentClientVersion()) > 0 && - mRenderer->getCurrentClientVersion() > 2) + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(getInternalFormat(0)); + if (formatInfo.depthBits > 0 && clientVersion > 2) { - if (mSamplerState.compareMode == GL_NONE) + if (samplerState.compareMode == GL_NONE) { - if ((mSamplerState.minFilter != GL_NEAREST && mSamplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST) || - mSamplerState.magFilter != GL_NEAREST) + if ((samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST) || + samplerState.magFilter != GL_NEAREST) { return false; } @@ -838,6 +325,33 @@ bool Texture2D::isSamplerComplete(const SamplerState &samplerState) const return true; } +bool Texture2D::isCompressed(GLint level) const +{ + return GetInternalFormatInfo(getInternalFormat(level)).compressed; +} + +bool Texture2D::isDepth(GLint level) const +{ + return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; +} + +void Texture2D::generateMipmaps() +{ + releaseTexImage(); + + mTexture->generateMipmaps(); +} + +unsigned int Texture2D::getRenderTargetSerial(GLint level) +{ + return mTexture->getRenderTargetSerial(level, 0); +} + +rx::RenderTarget *Texture2D::getRenderTarget(GLint level) +{ + return mTexture->getRenderTarget(level, 0); +} + // Tests for 2D texture (mipmap) completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81. bool Texture2D::isMipmapComplete() const { @@ -877,8 +391,8 @@ bool Texture2D::isLevelComplete(int level) const return true; } - ASSERT(level >= 1 && level <= (int)ArraySize(mImageArray) && mImageArray[level] != NULL); - rx::Image *image = mImageArray[level]; + ASSERT(level >= 1 && level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getImage(level, 0) != NULL); + rx::Image *image = mTexture->getImage(level, 0); if (image->getInternalFormat() != baseImage->getInternalFormat()) { @@ -898,230 +412,19 @@ bool Texture2D::isLevelComplete(int level) const return true; } -bool Texture2D::isCompressed(GLint level) const +TextureCubeMap::TextureCubeMap(rx::TextureImpl *impl, GLuint id) + : Texture(impl, id, GL_TEXTURE_CUBE_MAP) { - return IsFormatCompressed(getInternalFormat(level), mRenderer->getCurrentClientVersion()); -} - -bool Texture2D::isDepth(GLint level) const -{ - return GetDepthBits(getInternalFormat(level), mRenderer->getCurrentClientVersion()) > 0; -} - -// Constructs a native texture resource from the texture images -void Texture2D::initializeStorage(bool renderTarget) -{ - // Only initialize the first time this texture is used as a render target or shader resource - if (mTexStorage) - { - return; - } - - // do not attempt to create storage for nonexistant data - if (!isLevelComplete(0)) - { - return; - } - - bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mUsage)); - - setCompleteTexStorage(createCompleteStorage(createRenderTarget)); - ASSERT(mTexStorage); - - // flush image data to the storage - updateStorage(); -} - -rx::TextureStorageInterface2D *Texture2D::createCompleteStorage(bool renderTarget) const -{ - GLsizei width = getBaseLevelWidth(); - GLsizei height = getBaseLevelHeight(); - - ASSERT(width > 0 && height > 0); - - // use existing storage level count, when previously specified by TexStorage*D - GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, 1)); - - return new rx::TextureStorageInterface2D(mRenderer, getBaseLevelInternalFormat(), renderTarget, width, height, levels); -} - -void Texture2D::updateStorage() -{ - ASSERT(mTexStorage != NULL); - GLint storageLevels = mTexStorage->getLevelCount(); - for (int level = 0; level < storageLevels; level++) - { - if (mImageArray[level]->isDirty() && isLevelComplete(level)) - { - updateStorageLevel(level); - } - } -} - -void Texture2D::updateStorageLevel(int level) -{ - ASSERT(level <= (int)ArraySize(mImageArray) && mImageArray[level] != NULL); - ASSERT(isLevelComplete(level)); - - if (mImageArray[level]->isDirty()) - { - commitRect(level, 0, 0, getWidth(level), getHeight(level)); - } -} - -bool Texture2D::ensureRenderTarget() -{ - initializeStorage(true); - - if (getBaseLevelWidth() > 0 && getBaseLevelHeight() > 0) - { - ASSERT(mTexStorage); - if (!mTexStorage->isRenderTarget()) - { - rx::TextureStorageInterface2D *newRenderTargetStorage = createCompleteStorage(true); - - if (!mRenderer->copyToRenderTarget(newRenderTargetStorage, mTexStorage)) - { - delete newRenderTargetStorage; - return gl::error(GL_OUT_OF_MEMORY, false); - } - - setCompleteTexStorage(newRenderTargetStorage); - } - } - - return (mTexStorage && mTexStorage->isRenderTarget()); -} - -void Texture2D::generateMipmaps() -{ - // Purge array levels 1 through q and reset them to represent the generated mipmap levels. - int levelCount = mipLevels(); - for (int level = 1; level < levelCount; level++) - { - redefineImage(level, getBaseLevelInternalFormat(), - std::max(getBaseLevelWidth() >> level, 1), - std::max(getBaseLevelHeight() >> level, 1)); - } - - if (mTexStorage && mTexStorage->isRenderTarget()) - { - for (int level = 1; level < levelCount; level++) - { - mTexStorage->generateMipmap(level); - - mImageArray[level]->markClean(); - } - } - else - { - for (int level = 1; level < levelCount; level++) - { - mRenderer->generateMipmap(mImageArray[level], mImageArray[level - 1]); - } - } -} - -const rx::Image *Texture2D::getBaseLevelImage() const -{ - return mImageArray[0]; -} - -rx::TextureStorageInterface *Texture2D::getBaseLevelStorage() -{ - return mTexStorage; -} - -Renderbuffer *Texture2D::getRenderbuffer(GLint level) -{ - Renderbuffer *renderBuffer = mRenderbufferProxies.get(level, 0); - if (!renderBuffer) - { - renderBuffer = new Renderbuffer(mRenderer, id(), new RenderbufferTexture2D(this, level)); - mRenderbufferProxies.add(level, 0, renderBuffer); - } - - return renderBuffer; -} - -unsigned int Texture2D::getRenderTargetSerial(GLint level) -{ - return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(level) : 0); -} - -rx::RenderTarget *Texture2D::getRenderTarget(GLint level) -{ - // ensure the underlying texture is created - if (!ensureRenderTarget()) - { - return NULL; - } - - updateStorageLevel(level); - - // ensure this is NOT a depth texture - if (isDepth(level)) - { - return NULL; - } - - return mTexStorage->getRenderTarget(level); -} - -rx::RenderTarget *Texture2D::getDepthSencil(GLint level) -{ - // ensure the underlying texture is created - if (!ensureRenderTarget()) - { - return NULL; - } - - updateStorageLevel(level); - - // ensure this is actually a depth texture - if (!isDepth(level)) - { - return NULL; - } - - return mTexStorage->getRenderTarget(level); -} - -bool Texture2D::isValidLevel(int level) const -{ - return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : false); -} - -TextureCubeMap::TextureCubeMap(rx::Renderer *renderer, GLuint id) : Texture(renderer, id, GL_TEXTURE_CUBE_MAP) -{ - mTexStorage = NULL; - for (int i = 0; i < 6; i++) - { - for (int j = 0; j < IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++j) - { - mImageArray[i][j] = renderer->createImage(); - } - } } TextureCubeMap::~TextureCubeMap() { - for (int i = 0; i < 6; i++) - { - for (int j = 0; j < IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++j) - { - delete mImageArray[i][j]; - } - } - - delete mTexStorage; - mTexStorage = NULL; } GLsizei TextureCubeMap::getWidth(GLenum target, GLint level) const { if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mImageArray[targetToIndex(target)][level]->getWidth(); + return mTexture->getImage(level, targetToLayerIndex(target))->getWidth(); else return 0; } @@ -1129,7 +432,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[targetToIndex(target)][level]->getHeight(); + return mTexture->getImage(level, targetToLayerIndex(target))->getHeight(); else return 0; } @@ -1137,7 +440,7 @@ GLsizei TextureCubeMap::getHeight(GLenum target, GLint level) const GLenum TextureCubeMap::getInternalFormat(GLenum target, GLint level) const { if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mImageArray[targetToIndex(target)][level]->getInternalFormat(); + return mTexture->getImage(level, targetToLayerIndex(target))->getInternalFormat(); else return GL_NONE; } @@ -1145,118 +448,54 @@ GLenum TextureCubeMap::getInternalFormat(GLenum target, GLint level) const GLenum TextureCubeMap::getActualFormat(GLenum target, GLint level) const { if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mImageArray[targetToIndex(target)][level]->getActualFormat(); + return mTexture->getImage(level, targetToLayerIndex(target))->getActualFormat(); else return GL_NONE; } void TextureCubeMap::setImagePosX(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - setImage(0, level, width, height, internalFormat, format, type, unpack, pixels); + mTexture->setImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, width, height, 1, internalFormat, format, type, unpack, pixels); } void TextureCubeMap::setImageNegX(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - setImage(1, level, width, height, internalFormat, format, type, unpack, pixels); + mTexture->setImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, width, height, 1, internalFormat, format, type, unpack, pixels); } void TextureCubeMap::setImagePosY(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - setImage(2, level, width, height, internalFormat, format, type, unpack, pixels); + mTexture->setImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, width, height, 1, internalFormat, format, type, unpack, pixels); } void TextureCubeMap::setImageNegY(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - setImage(3, level, width, height, internalFormat, format, type, unpack, pixels); + mTexture->setImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, width, height, 1, internalFormat, format, type, unpack, pixels); } void TextureCubeMap::setImagePosZ(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - setImage(4, level, width, height, internalFormat, format, type, unpack, pixels); + mTexture->setImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, width, height, 1, internalFormat, format, type, unpack, pixels); } void TextureCubeMap::setImageNegZ(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - setImage(5, level, width, height, internalFormat, format, type, unpack, pixels); + mTexture->setImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, width, height, 1, internalFormat, format, type, unpack, pixels); } void TextureCubeMap::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels) { - // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly - int faceIndex = targetToIndex(target); - redefineImage(faceIndex, level, format, width, height); - - Texture::setCompressedImage(imageSize, pixels, mImageArray[faceIndex][level]); -} - -void TextureCubeMap::commitRect(int faceIndex, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) -{ - if (isValidFaceLevel(faceIndex, level)) - { - rx::Image *image = mImageArray[faceIndex][level]; - if (image->copyToStorage(mTexStorage, faceIndex, level, xoffset, yoffset, width, height)) - image->markClean(); - } + mTexture->setCompressedImage(target, level, format, width, height, 1, imageSize, pixels); } void TextureCubeMap::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - int faceIndex = targetToIndex(target); - if (Texture::subImage(xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels, mImageArray[faceIndex][level])) - { - commitRect(faceIndex, level, xoffset, yoffset, width, height); - } + mTexture->subImage(target, level, xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels); } void TextureCubeMap::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels) { - int faceIndex = targetToIndex(target); - if (Texture::subImageCompressed(xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels, mImageArray[faceIndex][level])) - { - commitRect(faceIndex, level, xoffset, yoffset, width, height); - } -} - -// Tests for cube map sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 86. -bool TextureCubeMap::isSamplerComplete(const SamplerState &samplerState) const -{ - int size = getBaseLevelWidth(); - - bool mipmapping = IsMipmapFiltered(samplerState); - - if (!IsTextureFilteringSupported(getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0), mRenderer)) - { - if (samplerState.magFilter != GL_NEAREST || - (samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST)) - { - return false; - } - } - - if (!isPow2(size) && !mRenderer->getNonPower2TextureSupport()) - { - if (samplerState.wrapS != GL_CLAMP_TO_EDGE || samplerState.wrapT != GL_CLAMP_TO_EDGE || mipmapping) - { - return false; - } - } - - if (!mipmapping) - { - if (!isCubeComplete()) - { - return false; - } - } - else - { - if (!isMipmapCubeComplete()) // Also tests for isCubeComplete() - { - return false; - } - } - - return true; + mTexture->subImageCompressed(target, level, xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels); } // Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81. @@ -1273,11 +512,11 @@ bool TextureCubeMap::isCubeComplete() const for (int faceIndex = 1; faceIndex < 6; faceIndex++) { - const rx::Image &faceBaseImage = *mImageArray[faceIndex][0]; + const rx::Image *faceBaseImage = mTexture->getImage(0, faceIndex); - if (faceBaseImage.getWidth() != baseWidth || - faceBaseImage.getHeight() != baseHeight || - faceBaseImage.getInternalFormat() != baseFormat ) + if (faceBaseImage->getWidth() != baseWidth || + faceBaseImage->getHeight() != baseHeight || + faceBaseImage->getInternalFormat() != baseFormat ) { return false; } @@ -1286,7 +525,99 @@ bool TextureCubeMap::isCubeComplete() const return true; } -bool TextureCubeMap::isMipmapCubeComplete() const +bool TextureCubeMap::isCompressed(GLenum target, GLint level) const +{ + return GetInternalFormatInfo(getInternalFormat(target, level)).compressed; +} + +bool TextureCubeMap::isDepth(GLenum target, GLint level) const +{ + return GetInternalFormatInfo(getInternalFormat(target, level)).depthBits > 0; +} + +void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) +{ + mTexture->copyImage(target, level, format, x, y, width, height, source); +} + +void TextureCubeMap::storage(GLsizei levels, GLenum internalformat, GLsizei size) +{ + mImmutable = true; + + mTexture->storage(GL_TEXTURE_CUBE_MAP, levels, internalformat, size, size, 1); +} + +// Tests for texture sampling completeness +bool TextureCubeMap::isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const +{ + int size = getBaseLevelWidth(); + + bool mipmapping = IsMipmapFiltered(samplerState); + + if (!textureCaps.get(getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0)).filterable && !IsPointSampled(samplerState)) + { + return false; + } + + if (!gl::isPow2(size) && !extensions.textureNPOT) + { + if (samplerState.wrapS != GL_CLAMP_TO_EDGE || samplerState.wrapT != GL_CLAMP_TO_EDGE || mipmapping) + { + return false; + } + } + + if (!mipmapping) + { + if (!isCubeComplete()) + { + return false; + } + } + else + { + if (!isMipmapComplete()) // Also tests for isCubeComplete() + { + return false; + } + } + + return true; +} + +unsigned int TextureCubeMap::getRenderTargetSerial(GLenum target, GLint level) +{ + return mTexture->getRenderTargetSerial(level, targetToLayerIndex(target)); +} + +int TextureCubeMap::targetToLayerIndex(GLenum target) +{ + META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1); + META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2); + META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3); + META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4); + META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5); + + return target - GL_TEXTURE_CUBE_MAP_POSITIVE_X; +} + +GLenum TextureCubeMap::layerIndexToTarget(GLint layer) +{ + META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1); + META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2); + META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3); + META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4); + META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5); + + return GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer; +} + +rx::RenderTarget *TextureCubeMap::getRenderTarget(GLenum target, GLint level) +{ + return mTexture->getRenderTarget(level, targetToLayerIndex(target)); +} + +bool TextureCubeMap::isMipmapComplete() const { if (isImmutable()) { @@ -1316,7 +647,7 @@ bool TextureCubeMap::isMipmapCubeComplete() const bool TextureCubeMap::isFaceLevelComplete(int faceIndex, int level) const { - ASSERT(level >= 0 && faceIndex < 6 && level < (int)ArraySize(mImageArray[faceIndex]) && mImageArray[faceIndex][level] != NULL); + ASSERT(level >= 0 && faceIndex < 6 && level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getImage(level, faceIndex) != NULL); if (isImmutable()) { @@ -1339,7 +670,7 @@ bool TextureCubeMap::isFaceLevelComplete(int faceIndex, int level) const } // Check that non-zero levels are consistent with the base level. - const rx::Image *faceLevelImage = mImageArray[faceIndex][level]; + const rx::Image *faceLevelImage = mTexture->getImage(level, faceIndex); if (faceLevelImage->getInternalFormat() != getBaseLevelInternalFormat()) { @@ -1354,625 +685,79 @@ bool TextureCubeMap::isFaceLevelComplete(int faceIndex, int level) const return true; } -bool TextureCubeMap::isCompressed(GLenum target, GLint level) const + +Texture3D::Texture3D(rx::TextureImpl *impl, GLuint id) + : Texture(impl, id, GL_TEXTURE_3D) { - return IsFormatCompressed(getInternalFormat(target, level), mRenderer->getCurrentClientVersion()); -} - -bool TextureCubeMap::isDepth(GLenum target, GLint level) const -{ - return GetDepthBits(getInternalFormat(target, level), mRenderer->getCurrentClientVersion()) > 0; -} - -void TextureCubeMap::initializeStorage(bool renderTarget) -{ - // Only initialize the first time this texture is used as a render target or shader resource - if (mTexStorage) - { - return; - } - - // do not attempt to create storage for nonexistant data - if (!isFaceLevelComplete(0, 0)) - { - return; - } - - bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mUsage)); - - setCompleteTexStorage(createCompleteStorage(createRenderTarget)); - ASSERT(mTexStorage); - - // flush image data to the storage - updateStorage(); -} - -rx::TextureStorageInterfaceCube *TextureCubeMap::createCompleteStorage(bool renderTarget) const -{ - GLsizei size = getBaseLevelWidth(); - - ASSERT(size > 0); - - // use existing storage level count, when previously specified by TexStorage*D - GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(size, size, 1)); - - return new rx::TextureStorageInterfaceCube(mRenderer, getBaseLevelInternalFormat(), renderTarget, size, levels); -} - -void TextureCubeMap::setCompleteTexStorage(rx::TextureStorageInterfaceCube *newCompleteTexStorage) -{ - SafeDelete(mTexStorage); - mTexStorage = newCompleteTexStorage; - - if (mTexStorage && mTexStorage->isManaged()) - { - for (int faceIndex = 0; faceIndex < 6; faceIndex++) - { - for (int level = 0; level < mTexStorage->getLevelCount(); level++) - { - mImageArray[faceIndex][level]->setManagedSurface(mTexStorage, faceIndex, level); - } - } - } - - mDirtyImages = true; -} - -void TextureCubeMap::updateStorage() -{ - ASSERT(mTexStorage != NULL); - GLint storageLevels = mTexStorage->getLevelCount(); - for (int face = 0; face < 6; face++) - { - for (int level = 0; level < storageLevels; level++) - { - if (mImageArray[face][level]->isDirty() && isFaceLevelComplete(face, level)) - { - updateStorageFaceLevel(face, level); - } - } - } -} - -void TextureCubeMap::updateStorageFaceLevel(int faceIndex, int level) -{ - ASSERT(level >= 0 && faceIndex < 6 && level < (int)ArraySize(mImageArray[faceIndex]) && mImageArray[faceIndex][level] != NULL); - rx::Image *image = mImageArray[faceIndex][level]; - - if (image->isDirty()) - { - commitRect(faceIndex, level, 0, 0, image->getWidth(), image->getHeight()); - } -} - -bool TextureCubeMap::ensureRenderTarget() -{ - initializeStorage(true); - - if (getBaseLevelWidth() > 0) - { - ASSERT(mTexStorage); - if (!mTexStorage->isRenderTarget()) - { - rx::TextureStorageInterfaceCube *newRenderTargetStorage = createCompleteStorage(true); - - if (!mRenderer->copyToRenderTarget(newRenderTargetStorage, mTexStorage)) - { - delete newRenderTargetStorage; - return gl::error(GL_OUT_OF_MEMORY, false); - } - - setCompleteTexStorage(newRenderTargetStorage); - } - } - - return (mTexStorage && mTexStorage->isRenderTarget()); -} - -void TextureCubeMap::setImage(int faceIndex, GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) -{ - GLuint clientVersion = mRenderer->getCurrentClientVersion(); - GLenum sizedInternalFormat = IsSizedInternalFormat(internalFormat, clientVersion) ? internalFormat - : GetSizedInternalFormat(format, type, clientVersion); - - redefineImage(faceIndex, level, sizedInternalFormat, width, height); - - Texture::setImage(unpack, type, pixels, mImageArray[faceIndex][level]); -} - -int TextureCubeMap::targetToIndex(GLenum target) -{ - META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1); - META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2); - META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3); - META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4); - META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5); - - return target - GL_TEXTURE_CUBE_MAP_POSITIVE_X; -} - -void TextureCubeMap::redefineImage(int faceIndex, GLint level, GLenum internalformat, GLsizei width, GLsizei height) -{ - // If there currently is a corresponding storage texture image, it has these parameters - const int storageWidth = std::max(1, getBaseLevelWidth() >> level); - const int storageHeight = std::max(1, getBaseLevelHeight() >> level); - const GLenum storageFormat = getBaseLevelInternalFormat(); - - mImageArray[faceIndex][level]->redefine(mRenderer, GL_TEXTURE_CUBE_MAP, internalformat, width, height, 1, false); - - if (mTexStorage) - { - const int storageLevels = mTexStorage->getLevelCount(); - - if ((level >= storageLevels && storageLevels != 0) || - width != storageWidth || - height != storageHeight || - internalformat != storageFormat) // Discard mismatched storage - { - for (int level = 0; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) - { - for (int faceIndex = 0; faceIndex < 6; faceIndex++) - { - mImageArray[faceIndex][level]->markDirty(); - } - } - - 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) -{ - int faceIndex = targetToIndex(target); - GLuint clientVersion = mRenderer->getCurrentClientVersion(); - GLenum sizedInternalFormat = IsSizedInternalFormat(format, clientVersion) ? format - : GetSizedInternalFormat(format, GL_UNSIGNED_BYTE, clientVersion); - redefineImage(faceIndex, level, sizedInternalFormat, width, height); - - if (!mImageArray[faceIndex][level]->isRenderableFormat()) - { - mImageArray[faceIndex][level]->copy(0, 0, 0, x, y, width, height, source); - mDirtyImages = true; - } - else - { - ensureRenderTarget(); - mImageArray[faceIndex][level]->markClean(); - - ASSERT(width == height); - - if (width > 0 && isValidFaceLevel(faceIndex, level)) - { - gl::Rectangle sourceRect; - sourceRect.x = x; - sourceRect.width = width; - sourceRect.y = y; - sourceRect.height = height; - - mRenderer->copyImage(source, sourceRect, format, 0, 0, mTexStorage, target, level); - } - } -} - -void TextureCubeMap::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) -{ - int faceIndex = targetToIndex(target); - - GLsizei size = mImageArray[faceIndex][level]->getWidth(); - - if (xoffset + width > size || yoffset + height > size || zoffset != 0) - { - return gl::error(GL_INVALID_VALUE); - } - - // We can only make our texture storage to a render target if the level we're copying *to* is complete - // and the base level is cube-complete. The base level must be cube complete (common case) because we cannot - // rely on the "getBaseLevel*" methods reliably otherwise. - bool canCreateRenderTarget = isFaceLevelComplete(faceIndex, level) && isCubeComplete(); - - if (!mImageArray[faceIndex][level]->isRenderableFormat() || (!mTexStorage && !canCreateRenderTarget)) - { - mImageArray[faceIndex][level]->copy(0, 0, 0, x, y, width, height, source); - mDirtyImages = true; - } - else - { - ensureRenderTarget(); - - if (isValidFaceLevel(faceIndex, level)) - { - updateStorageFaceLevel(faceIndex, level); - - GLuint clientVersion = mRenderer->getCurrentClientVersion(); - - gl::Rectangle sourceRect; - sourceRect.x = x; - sourceRect.width = width; - sourceRect.y = y; - sourceRect.height = height; - - mRenderer->copyImage(source, sourceRect, gl::GetFormat(getBaseLevelInternalFormat(), clientVersion), - xoffset, yoffset, mTexStorage, target, level); - } - } -} - -void TextureCubeMap::storage(GLsizei levels, GLenum internalformat, GLsizei size) -{ - for (int level = 0; level < levels; level++) - { - GLsizei mipSize = std::max(1, size >> level); - for (int faceIndex = 0; faceIndex < 6; faceIndex++) - { - mImageArray[faceIndex][level]->redefine(mRenderer, GL_TEXTURE_CUBE_MAP, internalformat, mipSize, mipSize, 1, true); - } - } - - for (int level = levels; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) - { - for (int faceIndex = 0; faceIndex < 6; faceIndex++) - { - mImageArray[faceIndex][level]->redefine(mRenderer, GL_TEXTURE_CUBE_MAP, GL_NONE, 0, 0, 0, true); - } - } - - mImmutable = true; - - setCompleteTexStorage(new rx::TextureStorageInterfaceCube(mRenderer, internalformat, IsRenderTargetUsage(mUsage), size, levels)); -} - -void TextureCubeMap::generateMipmaps() -{ - // Purge array levels 1 through q and reset them to represent the generated mipmap levels. - int levelCount = mipLevels(); - for (int faceIndex = 0; faceIndex < 6; faceIndex++) - { - for (int level = 1; level < levelCount; level++) - { - int faceLevelSize = (std::max(mImageArray[faceIndex][0]->getWidth() >> level, 1)); - redefineImage(faceIndex, level, mImageArray[faceIndex][0]->getInternalFormat(), faceLevelSize, faceLevelSize); - } - } - - if (mTexStorage && mTexStorage->isRenderTarget()) - { - for (int faceIndex = 0; faceIndex < 6; faceIndex++) - { - for (int level = 1; level < levelCount; level++) - { - mTexStorage->generateMipmap(faceIndex, level); - - mImageArray[faceIndex][level]->markClean(); - } - } - } - else - { - for (int faceIndex = 0; faceIndex < 6; faceIndex++) - { - for (int level = 1; level < levelCount; level++) - { - mRenderer->generateMipmap(mImageArray[faceIndex][level], mImageArray[faceIndex][level - 1]); - } - } - } -} - -const rx::Image *TextureCubeMap::getBaseLevelImage() const -{ - // Note: if we are not cube-complete, there is no single base level image that can describe all - // cube faces, so this method is only well-defined for a cube-complete base level. - return mImageArray[0][0]; -} - -rx::TextureStorageInterface *TextureCubeMap::getBaseLevelStorage() -{ - return mTexStorage; -} - -Renderbuffer *TextureCubeMap::getRenderbuffer(GLenum target, GLint level) -{ - if (!IsCubemapTextureTarget(target)) - { - return gl::error(GL_INVALID_OPERATION, (Renderbuffer *)NULL); - } - - int faceIndex = targetToIndex(target); - - Renderbuffer *renderBuffer = mRenderbufferProxies.get(level, faceIndex); - if (!renderBuffer) - { - renderBuffer = new Renderbuffer(mRenderer, id(), new RenderbufferTextureCubeMap(this, target, level)); - mRenderbufferProxies.add(level, faceIndex, renderBuffer); - } - - return renderBuffer; -} - -unsigned int TextureCubeMap::getRenderTargetSerial(GLenum target, GLint level) -{ - return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(target, level) : 0); -} - -rx::RenderTarget *TextureCubeMap::getRenderTarget(GLenum target, GLint level) -{ - ASSERT(IsCubemapTextureTarget(target)); - - // ensure the underlying texture is created - if (!ensureRenderTarget()) - { - return NULL; - } - - updateStorageFaceLevel(targetToIndex(target), level); - - // ensure this is NOT a depth texture - if (isDepth(target, level)) - { - return NULL; - } - - return mTexStorage->getRenderTarget(target, level); -} - -rx::RenderTarget *TextureCubeMap::getDepthStencil(GLenum target, GLint level) -{ - ASSERT(IsCubemapTextureTarget(target)); - - // ensure the underlying texture is created - if (!ensureRenderTarget()) - { - return NULL; - } - - updateStorageFaceLevel(targetToIndex(target), level); - - // ensure this is a depth texture - if (!isDepth(target, level)) - { - return NULL; - } - - return mTexStorage->getRenderTarget(target, level); -} - -bool TextureCubeMap::isValidFaceLevel(int faceIndex, int level) const -{ - return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : 0); -} - -Texture3D::Texture3D(rx::Renderer *renderer, GLuint id) : Texture(renderer, id, GL_TEXTURE_3D) -{ - mTexStorage = NULL; - - for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i) - { - mImageArray[i] = renderer->createImage(); - } } Texture3D::~Texture3D() { - delete mTexStorage; - mTexStorage = NULL; - - for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i) - { - delete mImageArray[i]; - } } GLsizei Texture3D::getWidth(GLint level) const { - return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mImageArray[level]->getWidth() : 0; + return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getWidth() : 0; } GLsizei Texture3D::getHeight(GLint level) const { - return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mImageArray[level]->getHeight() : 0; + return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getHeight() : 0; } GLsizei Texture3D::getDepth(GLint level) const { - return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mImageArray[level]->getDepth() : 0; + return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getDepth() : 0; } GLenum Texture3D::getInternalFormat(GLint level) const { - return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mImageArray[level]->getInternalFormat() : GL_NONE; + return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getInternalFormat() : GL_NONE; } GLenum Texture3D::getActualFormat(GLint level) const { - return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mImageArray[level]->getActualFormat() : GL_NONE; + return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getActualFormat() : GL_NONE; } bool Texture3D::isCompressed(GLint level) const { - return IsFormatCompressed(getInternalFormat(level), mRenderer->getCurrentClientVersion()); + return GetInternalFormatInfo(getInternalFormat(level)).compressed; } bool Texture3D::isDepth(GLint level) const { - return GetDepthBits(getInternalFormat(level), mRenderer->getCurrentClientVersion()) > 0; + return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; } void Texture3D::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - GLuint clientVersion = mRenderer->getCurrentClientVersion(); - GLenum sizedInternalFormat = IsSizedInternalFormat(internalFormat, clientVersion) ? internalFormat - : GetSizedInternalFormat(format, type, clientVersion); - redefineImage(level, sizedInternalFormat, width, height, depth); - - bool fastUnpacked = false; - - // Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer - if (isFastUnpackable(unpack, sizedInternalFormat)) - { - // Will try to create RT storage if it does not exist - rx::RenderTarget *destRenderTarget = getRenderTarget(level); - Box destArea(0, 0, 0, getWidth(level), getHeight(level), getDepth(level)); - - if (destRenderTarget && fastUnpackPixels(unpack, pixels, destArea, sizedInternalFormat, type, destRenderTarget)) - { - // Ensure we don't overwrite our newly initialized data - mImageArray[level]->markClean(); - - fastUnpacked = true; - } - } - - if (!fastUnpacked) - { - Texture::setImage(unpack, type, pixels, mImageArray[level]); - } + mTexture->setImage(GL_TEXTURE_3D, level, width, height, depth, internalFormat, format, type, unpack, pixels); } void Texture3D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels) { - // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly - redefineImage(level, format, width, height, depth); - - Texture::setCompressedImage(imageSize, pixels, mImageArray[level]); + mTexture->setCompressedImage(GL_TEXTURE_3D, level, format, width, height, depth, imageSize, pixels); } void Texture3D::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - bool fastUnpacked = false; - - // Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer - if (isFastUnpackable(unpack, getInternalFormat(level))) - { - rx::RenderTarget *destRenderTarget = getRenderTarget(level); - Box destArea(xoffset, yoffset, zoffset, width, height, depth); - - if (destRenderTarget && fastUnpackPixels(unpack, pixels, destArea, getInternalFormat(level), type, destRenderTarget)) - { - // Ensure we don't overwrite our newly initialized data - mImageArray[level]->markClean(); - - fastUnpacked = true; - } - } - - if (!fastUnpacked && Texture::subImage(xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels, mImageArray[level])) - { - commitRect(level, xoffset, yoffset, zoffset, width, height, depth); - } + mTexture->subImage(GL_TEXTURE_3D, level, xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels); } void Texture3D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels) { - if (Texture::subImageCompressed(xoffset, yoffset, zoffset, width, height, depth, format, imageSize, pixels, mImageArray[level])) - { - commitRect(level, xoffset, yoffset, zoffset, width, height, depth); - } + mTexture->subImageCompressed(GL_TEXTURE_3D, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, pixels); } void Texture3D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) { - for (int level = 0; level < levels; level++) - { - GLsizei levelWidth = std::max(1, width >> level); - GLsizei levelHeight = std::max(1, height >> level); - GLsizei levelDepth = std::max(1, depth >> level); - mImageArray[level]->redefine(mRenderer, GL_TEXTURE_3D, internalformat, levelWidth, levelHeight, levelDepth, true); - } - - for (int level = levels; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) - { - mImageArray[level]->redefine(mRenderer, GL_TEXTURE_3D, GL_NONE, 0, 0, 0, true); - } - mImmutable = true; - setCompleteTexStorage(new rx::TextureStorageInterface3D(mRenderer, internalformat, IsRenderTargetUsage(mUsage), width, height, depth, levels)); + mTexture->storage(GL_TEXTURE_3D, levels, internalformat, width, height, depth); } -void Texture3D::generateMipmaps() -{ - // Purge array levels 1 through q and reset them to represent the generated mipmap levels. - int levelCount = mipLevels(); - for (int level = 1; level < levelCount; level++) - { - redefineImage(level, getBaseLevelInternalFormat(), - std::max(getBaseLevelWidth() >> level, 1), - std::max(getBaseLevelHeight() >> level, 1), - std::max(getBaseLevelDepth() >> level, 1)); - } - - if (mTexStorage && mTexStorage->isRenderTarget()) - { - for (int level = 1; level < levelCount; level++) - { - mTexStorage->generateMipmap(level); - - mImageArray[level]->markClean(); - } - } - else - { - for (int level = 1; level < levelCount; level++) - { - mRenderer->generateMipmap(mImageArray[level], mImageArray[level - 1]); - } - } -} - -const rx::Image *Texture3D::getBaseLevelImage() const -{ - return mImageArray[0]; -} - -rx::TextureStorageInterface *Texture3D::getBaseLevelStorage() -{ - return mTexStorage; -} - -void Texture3D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) -{ - if (xoffset + width > mImageArray[level]->getWidth() || yoffset + height > mImageArray[level]->getHeight() || zoffset >= mImageArray[level]->getDepth()) - { - return gl::error(GL_INVALID_VALUE); - } - - // can only make our texture storage to a render target if level 0 is defined (with a width & height) and - // the current level we're copying to is defined (with appropriate format, width & height) - bool canCreateRenderTarget = isLevelComplete(level) && isLevelComplete(0); - - if (!mImageArray[level]->isRenderableFormat() || (!mTexStorage && !canCreateRenderTarget)) - { - mImageArray[level]->copy(xoffset, yoffset, zoffset, x, y, width, height, source); - mDirtyImages = true; - } - else - { - ensureRenderTarget(); - - if (isValidLevel(level)) - { - updateStorageLevel(level); - - gl::Rectangle sourceRect; - sourceRect.x = x; - sourceRect.width = width; - sourceRect.y = y; - sourceRect.height = height; - - GLuint clientVersion = mRenderer->getCurrentClientVersion(); - - mRenderer->copyImage(source, sourceRect, - gl::GetFormat(getBaseLevelInternalFormat(), clientVersion), - xoffset, yoffset, zoffset, mTexStorage, level); - } - } -} - -bool Texture3D::isSamplerComplete(const SamplerState &samplerState) const +bool Texture3D::isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const { GLsizei width = getBaseLevelWidth(); GLsizei height = getBaseLevelHeight(); @@ -1983,13 +768,9 @@ bool Texture3D::isSamplerComplete(const SamplerState &samplerState) const return false; } - if (!IsTextureFilteringSupported(getInternalFormat(0), mRenderer)) + if (!textureCaps.get(getInternalFormat(0)).filterable && !IsPointSampled(samplerState)) { - if (samplerState.magFilter != GL_NEAREST || - (samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST)) - { - return false; - } + return false; } if (IsMipmapFiltered(samplerState) && !isMipmapComplete()) @@ -2000,6 +781,17 @@ bool Texture3D::isSamplerComplete(const SamplerState &samplerState) const return true; } +unsigned int Texture3D::getRenderTargetSerial(GLint level, GLint layer) +{ + return mTexture->getRenderTargetSerial(level, layer); +} + + +rx::RenderTarget *Texture3D::getRenderTarget(GLint level, GLint layer) +{ + return mTexture->getRenderTarget(level, layer); +} + bool Texture3D::isMipmapComplete() const { int levelCount = mipLevels(); @@ -2017,7 +809,7 @@ bool Texture3D::isMipmapComplete() const bool Texture3D::isLevelComplete(int level) const { - ASSERT(level >= 0 && level < (int)ArraySize(mImageArray) && mImageArray[level] != NULL); + ASSERT(level >= 0 && level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getImage(level, 0) != NULL); if (isImmutable()) { @@ -2038,7 +830,7 @@ bool Texture3D::isLevelComplete(int level) const return true; } - rx::Image *levelImage = mImageArray[level]; + rx::Image *levelImage = mTexture->getImage(level, 0); if (levelImage->getInternalFormat() != getBaseLevelInternalFormat()) { @@ -2063,474 +855,78 @@ bool Texture3D::isLevelComplete(int level) const return true; } -Renderbuffer *Texture3D::getRenderbuffer(GLint level, GLint layer) +Texture2DArray::Texture2DArray(rx::TextureImpl *impl, GLuint id) + : Texture(impl, id, GL_TEXTURE_2D_ARRAY) { - Renderbuffer *renderBuffer = mRenderbufferProxies.get(level, layer); - if (!renderBuffer) - { - renderBuffer = new Renderbuffer(mRenderer, id(), new RenderbufferTexture3DLayer(this, level, layer)); - mRenderbufferProxies.add(level, 0, renderBuffer); - } - - return renderBuffer; -} - -unsigned int Texture3D::getRenderTargetSerial(GLint level, GLint layer) -{ - return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(level, layer) : 0); -} - -bool Texture3D::isValidLevel(int level) const -{ - return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : 0); -} - -void Texture3D::initializeStorage(bool renderTarget) -{ - // Only initialize the first time this texture is used as a render target or shader resource - if (mTexStorage) - { - return; - } - - // do not attempt to create storage for nonexistant data - if (!isLevelComplete(0)) - { - return; - } - - bool createRenderTarget = (renderTarget || mUsage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE); - - setCompleteTexStorage(createCompleteStorage(createRenderTarget)); - ASSERT(mTexStorage); - - // flush image data to the storage - updateStorage(); -} - -rx::TextureStorageInterface3D *Texture3D::createCompleteStorage(bool renderTarget) const -{ - GLsizei width = getBaseLevelWidth(); - GLsizei height = getBaseLevelHeight(); - GLsizei depth = getBaseLevelDepth(); - - ASSERT(width > 0 && height > 0 && depth > 0); - - // use existing storage level count, when previously specified by TexStorage*D - GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, depth)); - - return new rx::TextureStorageInterface3D(mRenderer, getBaseLevelInternalFormat(), renderTarget, width, height, depth, levels); -} - -void Texture3D::setCompleteTexStorage(rx::TextureStorageInterface3D *newCompleteTexStorage) -{ - SafeDelete(mTexStorage); - mTexStorage = newCompleteTexStorage; - mDirtyImages = true; - - // We do not support managed 3D storage, as that is D3D9/ES2-only - ASSERT(!mTexStorage->isManaged()); -} - -void Texture3D::updateStorage() -{ - ASSERT(mTexStorage != NULL); - GLint storageLevels = mTexStorage->getLevelCount(); - for (int level = 0; level < storageLevels; level++) - { - if (mImageArray[level]->isDirty() && isLevelComplete(level)) - { - updateStorageLevel(level); - } - } -} - -void Texture3D::updateStorageLevel(int level) -{ - ASSERT(level >= 0 && level < (int)ArraySize(mImageArray) && mImageArray[level] != NULL); - ASSERT(isLevelComplete(level)); - - if (mImageArray[level]->isDirty()) - { - commitRect(level, 0, 0, 0, getWidth(level), getHeight(level), getDepth(level)); - } -} - -bool Texture3D::ensureRenderTarget() -{ - initializeStorage(true); - - if (getBaseLevelWidth() > 0 && getBaseLevelHeight() > 0 && getBaseLevelDepth() > 0) - { - ASSERT(mTexStorage); - if (!mTexStorage->isRenderTarget()) - { - rx::TextureStorageInterface3D *newRenderTargetStorage = createCompleteStorage(true); - - if (!mRenderer->copyToRenderTarget(newRenderTargetStorage, mTexStorage)) - { - delete newRenderTargetStorage; - return gl::error(GL_OUT_OF_MEMORY, false); - } - - setCompleteTexStorage(newRenderTargetStorage); - } - } - - return (mTexStorage && mTexStorage->isRenderTarget()); -} - -rx::RenderTarget *Texture3D::getRenderTarget(GLint level) -{ - // ensure the underlying texture is created - if (!ensureRenderTarget()) - { - return NULL; - } - - updateStorageLevel(level); - - // ensure this is NOT a depth texture - if (isDepth(level)) - { - return NULL; - } - - return mTexStorage->getRenderTarget(level); -} - -rx::RenderTarget *Texture3D::getRenderTarget(GLint level, GLint layer) -{ - // ensure the underlying texture is created - if (!ensureRenderTarget()) - { - return NULL; - } - - updateStorage(); - - // ensure this is NOT a depth texture - if (isDepth(level)) - { - return NULL; - } - - return mTexStorage->getRenderTarget(level, layer); -} - -rx::RenderTarget *Texture3D::getDepthStencil(GLint level, GLint layer) -{ - // ensure the underlying texture is created - if (!ensureRenderTarget()) - { - return NULL; - } - - updateStorageLevel(level); - - // ensure this is a depth texture - if (!isDepth(level)) - { - return NULL; - } - - return mTexStorage->getRenderTarget(level, layer); -} - -void Texture3D::redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) -{ - // If there currently is a corresponding storage texture image, it has these parameters - const int storageWidth = std::max(1, getBaseLevelWidth() >> level); - const int storageHeight = std::max(1, getBaseLevelHeight() >> level); - const int storageDepth = std::max(1, getBaseLevelDepth() >> level); - const GLenum storageFormat = getBaseLevelInternalFormat(); - - mImageArray[level]->redefine(mRenderer, GL_TEXTURE_3D, internalformat, width, height, depth, false); - - if (mTexStorage) - { - const int storageLevels = mTexStorage->getLevelCount(); - - if ((level >= storageLevels && storageLevels != 0) || - width != storageWidth || - height != storageHeight || - depth != storageDepth || - internalformat != storageFormat) // Discard mismatched storage - { - for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) - { - mImageArray[i]->markDirty(); - } - - delete mTexStorage; - mTexStorage = NULL; - mDirtyImages = true; - } - } -} - -void Texture3D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth) -{ - if (isValidLevel(level)) - { - rx::Image *image = mImageArray[level]; - if (image->copyToStorage(mTexStorage, level, xoffset, yoffset, zoffset, width, height, depth)) - { - image->markClean(); - } - } -} - -Texture2DArray::Texture2DArray(rx::Renderer *renderer, GLuint id) : Texture(renderer, id, GL_TEXTURE_2D_ARRAY) -{ - mTexStorage = NULL; - - for (int level = 0; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++level) - { - mLayerCounts[level] = 0; - mImageArray[level] = NULL; - } } Texture2DArray::~Texture2DArray() { - delete mTexStorage; - mTexStorage = NULL; - - deleteImages(); -} - -void Texture2DArray::deleteImages() -{ - for (int level = 0; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++level) - { - for (int layer = 0; layer < mLayerCounts[level]; ++layer) - { - delete mImageArray[level][layer]; - } - delete[] mImageArray[level]; - mImageArray[level] = NULL; - mLayerCounts[level] = 0; - } } GLsizei Texture2DArray::getWidth(GLint level) const { - return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mImageArray[level][0]->getWidth() : 0; + return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getLayerCount(level) > 0) ? mTexture->getImage(level, 0)->getWidth() : 0; } GLsizei Texture2DArray::getHeight(GLint level) const { - return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mImageArray[level][0]->getHeight() : 0; + return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getLayerCount(level) > 0) ? mTexture->getImage(level, 0)->getHeight() : 0; } GLsizei Texture2DArray::getLayers(GLint level) const { - return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mLayerCounts[level] : 0; + return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getLayerCount(level) : 0; } GLenum Texture2DArray::getInternalFormat(GLint level) const { - return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mImageArray[level][0]->getInternalFormat() : GL_NONE; + return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getLayerCount(level) > 0) ? mTexture->getImage(level, 0)->getInternalFormat() : GL_NONE; } GLenum Texture2DArray::getActualFormat(GLint level) const { - return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mImageArray[level][0]->getActualFormat() : GL_NONE; + return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getLayerCount(level) > 0) ? mTexture->getImage(level, 0)->getActualFormat() : GL_NONE; } bool Texture2DArray::isCompressed(GLint level) const { - return IsFormatCompressed(getInternalFormat(level), mRenderer->getCurrentClientVersion()); + return GetInternalFormatInfo(getInternalFormat(level)).compressed; } bool Texture2DArray::isDepth(GLint level) const { - return GetDepthBits(getInternalFormat(level), mRenderer->getCurrentClientVersion()) > 0; + return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; } void Texture2DArray::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - GLuint clientVersion = mRenderer->getCurrentClientVersion(); - GLenum sizedInternalFormat = IsSizedInternalFormat(internalFormat, clientVersion) ? internalFormat - : GetSizedInternalFormat(format, type, clientVersion); - redefineImage(level, sizedInternalFormat, width, height, depth); - - GLsizei inputDepthPitch = gl::GetDepthPitch(sizedInternalFormat, type, clientVersion, width, height, unpack.alignment); - - for (int i = 0; i < depth; i++) - { - const void *layerPixels = pixels ? (reinterpret_cast(pixels) + (inputDepthPitch * i)) : NULL; - Texture::setImage(unpack, type, layerPixels, mImageArray[level][i]); - } + mTexture->setImage(GL_TEXTURE_2D_ARRAY, level, width, height, depth, internalFormat, format, type, unpack, pixels); } void Texture2DArray::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels) { - // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly - redefineImage(level, format, width, height, depth); - - GLuint clientVersion = mRenderer->getCurrentClientVersion(); - GLsizei inputDepthPitch = gl::GetDepthPitch(format, GL_UNSIGNED_BYTE, clientVersion, width, height, 1); - - for (int i = 0; i < depth; i++) - { - const void *layerPixels = pixels ? (reinterpret_cast(pixels) + (inputDepthPitch * i)) : NULL; - Texture::setCompressedImage(imageSize, layerPixels, mImageArray[level][i]); - } + mTexture->setCompressedImage(GL_TEXTURE_2D_ARRAY, level, format, width, height, depth, imageSize, pixels); } void Texture2DArray::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - GLenum internalformat = getInternalFormat(level); - GLuint clientVersion = mRenderer->getCurrentClientVersion(); - GLsizei inputDepthPitch = gl::GetDepthPitch(internalformat, type, clientVersion, width, height, unpack.alignment); - - for (int i = 0; i < depth; i++) - { - int layer = zoffset + i; - const void *layerPixels = pixels ? (reinterpret_cast(pixels) + (inputDepthPitch * i)) : NULL; - - if (Texture::subImage(xoffset, yoffset, zoffset, width, height, 1, format, type, unpack, layerPixels, mImageArray[level][layer])) - { - commitRect(level, xoffset, yoffset, layer, width, height); - } - } + mTexture->subImage(GL_TEXTURE_2D_ARRAY, level, xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels); } void Texture2DArray::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels) { - GLuint clientVersion = mRenderer->getCurrentClientVersion(); - GLsizei inputDepthPitch = gl::GetDepthPitch(format, GL_UNSIGNED_BYTE, clientVersion, width, height, 1); - - for (int i = 0; i < depth; i++) - { - int layer = zoffset + i; - const void *layerPixels = pixels ? (reinterpret_cast(pixels) + (inputDepthPitch * i)) : NULL; - - if (Texture::subImageCompressed(xoffset, yoffset, zoffset, width, height, 1, format, imageSize, layerPixels, mImageArray[level][layer])) - { - commitRect(level, xoffset, yoffset, layer, width, height); - } - } + mTexture->subImageCompressed(GL_TEXTURE_2D_ARRAY, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, pixels); } void Texture2DArray::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) { - deleteImages(); - - for (int level = 0; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) - { - GLsizei levelWidth = std::max(1, width >> level); - GLsizei levelHeight = std::max(1, height >> level); - - mLayerCounts[level] = (level < levels ? depth : 0); - - if (mLayerCounts[level] > 0) - { - // Create new images for this level - mImageArray[level] = new rx::Image*[mLayerCounts[level]]; - - for (int layer = 0; layer < mLayerCounts[level]; layer++) - { - mImageArray[level][layer] = mRenderer->createImage(); - mImageArray[level][layer]->redefine(mRenderer, GL_TEXTURE_2D_ARRAY, internalformat, levelWidth, - levelHeight, 1, true); - } - } - } - mImmutable = true; - setCompleteTexStorage(new rx::TextureStorageInterface2DArray(mRenderer, internalformat, IsRenderTargetUsage(mUsage), width, height, depth, levels)); + + mTexture->storage(GL_TEXTURE_2D_ARRAY, levels, internalformat, width, height, depth); } -void Texture2DArray::generateMipmaps() -{ - int baseWidth = getBaseLevelWidth(); - int baseHeight = getBaseLevelHeight(); - int baseDepth = getBaseLevelDepth(); - GLenum baseFormat = getBaseLevelInternalFormat(); - - // Purge array levels 1 through q and reset them to represent the generated mipmap levels. - int levelCount = mipLevels(); - for (int level = 1; level < levelCount; level++) - { - redefineImage(level, baseFormat, std::max(baseWidth >> level, 1), std::max(baseHeight >> level, 1), baseDepth); - } - - if (mTexStorage && mTexStorage->isRenderTarget()) - { - for (int level = 1; level < levelCount; level++) - { - mTexStorage->generateMipmap(level); - - for (int layer = 0; layer < mLayerCounts[level]; layer++) - { - mImageArray[level][layer]->markClean(); - } - } - } - else - { - for (int level = 1; level < levelCount; level++) - { - for (int layer = 0; layer < mLayerCounts[level]; layer++) - { - mRenderer->generateMipmap(mImageArray[level][layer], mImageArray[level - 1][layer]); - } - } - } -} - -const rx::Image *Texture2DArray::getBaseLevelImage() const -{ - return (mLayerCounts[0] > 0 ? mImageArray[0][0] : NULL); -} - -rx::TextureStorageInterface *Texture2DArray::getBaseLevelStorage() -{ - return mTexStorage; -} - -void Texture2DArray::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) -{ - if (xoffset + width > getWidth(level) || yoffset + height > getHeight(level) || zoffset >= getLayers(level) || getLayers(level) == 0) - { - return gl::error(GL_INVALID_VALUE); - } - - // can only make our texture storage to a render target if level 0 is defined (with a width & height) and - // the current level we're copying to is defined (with appropriate format, width & height) - bool canCreateRenderTarget = isLevelComplete(level) && isLevelComplete(0); - - if (!mImageArray[level][0]->isRenderableFormat() || (!mTexStorage && !canCreateRenderTarget)) - { - mImageArray[level][zoffset]->copy(xoffset, yoffset, 0, x, y, width, height, source); - mDirtyImages = true; - } - else - { - ensureRenderTarget(); - - if (isValidLevel(level)) - { - updateStorageLevel(level); - - GLuint clientVersion = mRenderer->getCurrentClientVersion(); - - gl::Rectangle sourceRect; - sourceRect.x = x; - sourceRect.width = width; - sourceRect.y = y; - sourceRect.height = height; - - mRenderer->copyImage(source, sourceRect, gl::GetFormat(getInternalFormat(0), clientVersion), - xoffset, yoffset, zoffset, mTexStorage, level); - } - } -} - -bool Texture2DArray::isSamplerComplete(const SamplerState &samplerState) const +bool Texture2DArray::isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const { GLsizei width = getBaseLevelWidth(); GLsizei height = getBaseLevelHeight(); @@ -2541,13 +937,9 @@ bool Texture2DArray::isSamplerComplete(const SamplerState &samplerState) const return false; } - if (!IsTextureFilteringSupported(getBaseLevelInternalFormat(), mRenderer)) + if (!textureCaps.get(getBaseLevelInternalFormat()).filterable && !IsPointSampled(samplerState)) { - if (samplerState.magFilter != GL_NEAREST || - (samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST)) - { - return false; - } + return false; } if (IsMipmapFiltered(samplerState) && !isMipmapComplete()) @@ -2558,6 +950,16 @@ bool Texture2DArray::isSamplerComplete(const SamplerState &samplerState) const return true; } +unsigned int Texture2DArray::getRenderTargetSerial(GLint level, GLint layer) +{ + return mTexture->getRenderTargetSerial(level, layer); +} + +rx::RenderTarget *Texture2DArray::getRenderTarget(GLint level, GLint layer) +{ + return mTexture->getRenderTarget(level, layer); +} + bool Texture2DArray::isMipmapComplete() const { int levelCount = mipLevels(); @@ -2575,7 +977,7 @@ bool Texture2DArray::isMipmapComplete() const bool Texture2DArray::isLevelComplete(int level) const { - ASSERT(level >= 0 && level < (int)ArraySize(mImageArray)); + ASSERT(level >= 0 && level < IMPLEMENTATION_MAX_TEXTURE_LEVELS); if (isImmutable()) { @@ -2619,227 +1021,4 @@ bool Texture2DArray::isLevelComplete(int level) const return true; } -Renderbuffer *Texture2DArray::getRenderbuffer(GLint level, GLint layer) -{ - Renderbuffer *renderBuffer = mRenderbufferProxies.get(level, layer); - if (!renderBuffer) - { - renderBuffer = new Renderbuffer(mRenderer, id(), new RenderbufferTexture2DArrayLayer(this, level, layer)); - mRenderbufferProxies.add(level, 0, renderBuffer); - } - - return renderBuffer; -} - -unsigned int Texture2DArray::getRenderTargetSerial(GLint level, GLint layer) -{ - return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(level, layer) : 0); -} - -bool Texture2DArray::isValidLevel(int level) const -{ - return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : 0); -} - -void Texture2DArray::initializeStorage(bool renderTarget) -{ - // Only initialize the first time this texture is used as a render target or shader resource - if (mTexStorage) - { - return; - } - - // do not attempt to create storage for nonexistant data - if (!isLevelComplete(0)) - { - return; - } - - bool createRenderTarget = (renderTarget || mUsage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE); - - setCompleteTexStorage(createCompleteStorage(createRenderTarget)); - ASSERT(mTexStorage); - - // flush image data to the storage - updateStorage(); -} - -rx::TextureStorageInterface2DArray *Texture2DArray::createCompleteStorage(bool renderTarget) const -{ - GLsizei width = getBaseLevelWidth(); - GLsizei height = getBaseLevelHeight(); - GLsizei depth = getLayers(0); - - ASSERT(width > 0 && height > 0 && depth > 0); - - // use existing storage level count, when previously specified by TexStorage*D - GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, 1)); - - return new rx::TextureStorageInterface2DArray(mRenderer, getBaseLevelInternalFormat(), renderTarget, width, height, depth, levels); -} - -void Texture2DArray::setCompleteTexStorage(rx::TextureStorageInterface2DArray *newCompleteTexStorage) -{ - SafeDelete(mTexStorage); - mTexStorage = newCompleteTexStorage; - mDirtyImages = true; - - // We do not support managed 2D array storage, as managed storage is ES2/D3D9 only - ASSERT(!mTexStorage->isManaged()); -} - -void Texture2DArray::updateStorage() -{ - ASSERT(mTexStorage != NULL); - GLint storageLevels = mTexStorage->getLevelCount(); - for (int level = 0; level < storageLevels; level++) - { - if (isLevelComplete(level)) - { - updateStorageLevel(level); - } - } -} - -void Texture2DArray::updateStorageLevel(int level) -{ - ASSERT(level >= 0 && level < (int)ArraySize(mLayerCounts)); - ASSERT(isLevelComplete(level)); - - for (int layer = 0; layer < mLayerCounts[level]; layer++) - { - ASSERT(mImageArray[level] != NULL && mImageArray[level][layer] != NULL); - if (mImageArray[level][layer]->isDirty()) - { - commitRect(level, 0, 0, layer, getWidth(level), getHeight(level)); - } - } -} - -bool Texture2DArray::ensureRenderTarget() -{ - initializeStorage(true); - - if (getBaseLevelWidth() > 0 && getBaseLevelHeight() > 0 && getLayers(0) > 0) - { - ASSERT(mTexStorage); - if (!mTexStorage->isRenderTarget()) - { - rx::TextureStorageInterface2DArray *newRenderTargetStorage = createCompleteStorage(true); - - if (!mRenderer->copyToRenderTarget(newRenderTargetStorage, mTexStorage)) - { - delete newRenderTargetStorage; - return gl::error(GL_OUT_OF_MEMORY, false); - } - - setCompleteTexStorage(newRenderTargetStorage); - } - } - - return (mTexStorage && mTexStorage->isRenderTarget()); -} - -rx::RenderTarget *Texture2DArray::getRenderTarget(GLint level, GLint layer) -{ - // ensure the underlying texture is created - if (!ensureRenderTarget()) - { - return NULL; - } - - updateStorageLevel(level); - - // ensure this is NOT a depth texture - if (isDepth(level)) - { - return NULL; - } - - return mTexStorage->getRenderTarget(level, layer); -} - -rx::RenderTarget *Texture2DArray::getDepthStencil(GLint level, GLint layer) -{ - // ensure the underlying texture is created - if (!ensureRenderTarget()) - { - return NULL; - } - - updateStorageLevel(level); - - // ensure this is a depth texture - if (!isDepth(level)) - { - return NULL; - } - - return mTexStorage->getRenderTarget(level, layer); -} - -void Texture2DArray::redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) -{ - // If there currently is a corresponding storage texture image, it has these parameters - const int storageWidth = std::max(1, getBaseLevelWidth() >> level); - const int storageHeight = std::max(1, getBaseLevelHeight() >> level); - const int storageDepth = getLayers(0); - const GLenum storageFormat = getBaseLevelInternalFormat(); - - for (int layer = 0; layer < mLayerCounts[level]; layer++) - { - delete mImageArray[level][layer]; - } - delete[] mImageArray[level]; - mImageArray[level] = NULL; - mLayerCounts[level] = depth; - - if (depth > 0) - { - mImageArray[level] = new rx::Image*[depth](); - - for (int layer = 0; layer < mLayerCounts[level]; layer++) - { - mImageArray[level][layer] = mRenderer->createImage(); - mImageArray[level][layer]->redefine(mRenderer, GL_TEXTURE_2D_ARRAY, internalformat, width, height, 1, false); - } - } - - if (mTexStorage) - { - const int storageLevels = mTexStorage->getLevelCount(); - - if ((level >= storageLevels && storageLevels != 0) || - width != storageWidth || - height != storageHeight || - depth != storageDepth || - internalformat != storageFormat) // Discard mismatched storage - { - for (int level = 0; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) - { - for (int layer = 0; layer < mLayerCounts[level]; layer++) - { - mImageArray[level][layer]->markDirty(); - } - } - - delete mTexStorage; - mTexStorage = NULL; - mDirtyImages = true; - } - } -} - -void Texture2DArray::commitRect(GLint level, GLint xoffset, GLint yoffset, GLint layerTarget, GLsizei width, GLsizei height) -{ - if (isValidLevel(level) && layerTarget < getLayers(level)) - { - rx::Image *image = mImageArray[level][layerTarget]; - if (image->copyToStorage(mTexStorage, level, xoffset, yoffset, layerTarget, width, height)) - { - image->markClean(); - } - } -} - } diff --git a/gfx/angle/src/libGLESv2/Texture.h b/gfx/angle/src/libGLESv2/Texture.h index a44a70193200..3008a8488407 100644 --- a/gfx/angle/src/libGLESv2/Texture.h +++ b/gfx/angle/src/libGLESv2/Texture.h @@ -11,15 +11,16 @@ #ifndef LIBGLESV2_TEXTURE_H_ #define LIBGLESV2_TEXTURE_H_ -#include - -#include -#include - #include "common/debug.h" #include "common/RefCountObject.h" #include "libGLESv2/angletypes.h" -#include "libGLESv2/RenderbufferProxySet.h" +#include "libGLESv2/constants.h" +#include "libGLESv2/renderer/TextureImpl.h" +#include "libGLESv2/Caps.h" + +#include "angle_gl.h" + +#include namespace egl { @@ -28,12 +29,7 @@ class Surface; namespace rx { -class Renderer; class TextureStorageInterface; -class TextureStorageInterface2D; -class TextureStorageInterfaceCube; -class TextureStorageInterface3D; -class TextureStorageInterface2DArray; class RenderTarget; class Image; } @@ -41,69 +37,24 @@ class Image; namespace gl { class Framebuffer; -class Renderbuffer; +class FramebufferAttachment; -enum -{ - // These are the maximums the implementation can support - // The actual GL caps are limited by the device caps - // and should be queried from the Context - IMPLEMENTATION_MAX_2D_TEXTURE_SIZE = 16384, - IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE = 16384, - IMPLEMENTATION_MAX_3D_TEXTURE_SIZE = 2048, - IMPLEMENTATION_MAX_2D_ARRAY_TEXTURE_LAYERS = 2048, - - IMPLEMENTATION_MAX_TEXTURE_LEVELS = 15 // 1+log2 of MAX_TEXTURE_SIZE -}; - -bool IsMipmapFiltered(const SamplerState &samplerState); +bool IsMipmapFiltered(const gl::SamplerState &samplerState); class Texture : public RefCountObject { public: - Texture(rx::Renderer *renderer, GLuint id, GLenum target); + Texture(rx::TextureImpl *impl, GLuint id, GLenum target); virtual ~Texture(); - void addProxyRef(const Renderbuffer *proxy); - void releaseProxy(const Renderbuffer *proxy); - GLenum getTarget() const; - void setMinFilter(GLenum filter); - void setMagFilter(GLenum filter); - void setWrapS(GLenum wrap); - void setWrapT(GLenum wrap); - void setWrapR(GLenum wrap); - void setMaxAnisotropy(float textureMaxAnisotropy, float contextMaxAnisotropy); - void setCompareMode(GLenum mode); - void setCompareFunc(GLenum func); - void setSwizzleRed(GLenum swizzle); - void setSwizzleGreen(GLenum swizzle); - void setSwizzleBlue(GLenum swizzle); - void setSwizzleAlpha(GLenum swizzle); - void setBaseLevel(GLint baseLevel); - void setMaxLevel(GLint maxLevel); - void setMinLod(GLfloat minLod); - void setMaxLod(GLfloat maxLod); - void setUsage(GLenum usage); + const SamplerState &getSamplerState() const { return mSamplerState; } + SamplerState &getSamplerState() { return mSamplerState; } + void getSamplerStateWithNativeOffset(SamplerState *sampler); - GLenum getMinFilter() const; - GLenum getMagFilter() const; - GLenum getWrapS() const; - GLenum getWrapT() const; - GLenum getWrapR() const; - float getMaxAnisotropy() const; - GLenum getSwizzleRed() const; - GLenum getSwizzleGreen() const; - GLenum getSwizzleBlue() const; - GLenum getSwizzleAlpha() const; - GLint getBaseLevel() const; - GLint getMaxLevel() const; - GLfloat getMinLod() const; - GLfloat getMaxLod() const; - bool isSwizzled() const; - void getSamplerState(SamplerState *sampler); + void setUsage(GLenum usage); GLenum getUsage() const; GLint getBaseLevelWidth() const; @@ -111,72 +62,47 @@ class Texture : public RefCountObject GLint getBaseLevelDepth() const; GLenum getBaseLevelInternalFormat() const; - virtual bool isSamplerComplete(const SamplerState &samplerState) const = 0; + virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const = 0; rx::TextureStorageInterface *getNativeTexture(); - virtual void generateMipmaps() = 0; - virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) = 0; + virtual void generateMipmaps(); + virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source); - bool hasDirtyParameters() const; - bool hasDirtyImages() const; - void resetDirty(); unsigned int getTextureSerial(); bool isImmutable() const; int immutableLevelCount(); + rx::TextureImpl *getImplementation() { return mTexture; } + const rx::TextureImpl *getImplementation() const { return mTexture; } + 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(const PixelUnpackState &unpack, GLenum type, const void *pixels, rx::Image *image); - bool subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels, rx::Image *image); - void setCompressedImage(GLsizei imageSize, const void *pixels, rx::Image *image); - bool subImageCompressed(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLsizei imageSize, const void *pixels, rx::Image *image); - bool isFastUnpackable(const PixelUnpackState &unpack, GLenum sizedInternalFormat); - bool fastUnpackPixels(const PixelUnpackState &unpack, const void *pixels, const Box &destArea, - GLenum sizedInternalFormat, GLenum type, rx::RenderTarget *destRenderTarget); - - GLint creationLevels(GLsizei width, GLsizei height, GLsizei depth) const; int mipLevels() const; - virtual void initializeStorage(bool renderTarget) = 0; - virtual void updateStorage() = 0; - virtual bool ensureRenderTarget() = 0; - - rx::Renderer *mRenderer; + rx::TextureImpl *mTexture; SamplerState mSamplerState; GLenum mUsage; - bool mDirtyImages; - bool mImmutable; GLenum mTarget; - // A specific internal reference count is kept for colorbuffer proxy references, - // because, as the renderbuffer acting as proxy will maintain a binding pointer - // back to this texture, there would be a circular reference if we used a binding - // pointer here. This reference count will cause the pointer to be set to NULL if - // the count drops to zero, but will not cause deletion of the Renderbuffer. - RenderbufferProxySet mRenderbufferProxies; + const rx::Image *getBaseLevelImage() const; private: DISALLOW_COPY_AND_ASSIGN(Texture); - - virtual rx::TextureStorageInterface *getBaseLevelStorage() = 0; - virtual const rx::Image *getBaseLevelImage() const = 0; }; class Texture2D : public Texture { public: - Texture2D(rx::Renderer *renderer, GLuint id); + Texture2D(rx::TextureImpl *impl, GLuint id); - ~Texture2D(); + virtual ~Texture2D(); GLsizei getWidth(GLint level) const; GLsizei getHeight(GLint level) const; @@ -190,55 +116,35 @@ class Texture2D : public Texture void subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels); void copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source); - virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source); void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); - virtual bool isSamplerComplete(const SamplerState &samplerState) const; + virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const; virtual void bindTexImage(egl::Surface *surface); virtual void releaseTexImage(); virtual void generateMipmaps(); - Renderbuffer *getRenderbuffer(GLint level); unsigned int getRenderTargetSerial(GLint level); protected: - friend class RenderbufferTexture2D; + friend class Texture2DAttachment; rx::RenderTarget *getRenderTarget(GLint level); - rx::RenderTarget *getDepthSencil(GLint level); private: DISALLOW_COPY_AND_ASSIGN(Texture2D); - virtual void initializeStorage(bool renderTarget); - rx::TextureStorageInterface2D *createCompleteStorage(bool renderTarget) const; - void setCompleteTexStorage(rx::TextureStorageInterface2D *newCompleteTexStorage); - - virtual void updateStorage(); - virtual bool ensureRenderTarget(); - virtual rx::TextureStorageInterface *getBaseLevelStorage(); - virtual const rx::Image *getBaseLevelImage() const; - bool isMipmapComplete() const; - bool isValidLevel(int level) const; bool isLevelComplete(int level) const; - void updateStorageLevel(int level); - void redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height); - void commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); - - rx::Image *mImageArray[IMPLEMENTATION_MAX_TEXTURE_LEVELS]; - - rx::TextureStorageInterface2D *mTexStorage; egl::Surface *mSurface; }; class TextureCubeMap : public Texture { public: - TextureCubeMap(rx::Renderer *renderer, GLuint id); + TextureCubeMap(rx::TextureImpl *impl, GLuint id); - ~TextureCubeMap(); + virtual ~TextureCubeMap(); GLsizei getWidth(GLenum target, GLint level) const; GLsizei getHeight(GLenum target, GLint level) const; @@ -259,56 +165,34 @@ class TextureCubeMap : public Texture void subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels); void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source); - virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source); void storage(GLsizei levels, GLenum internalformat, GLsizei size); - virtual bool isSamplerComplete(const SamplerState &samplerState) const; + virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const; + bool isCubeComplete() const; - virtual void generateMipmaps(); - - Renderbuffer *getRenderbuffer(GLenum target, GLint level); unsigned int getRenderTargetSerial(GLenum target, GLint level); - static int targetToIndex(GLenum target); + static int targetToLayerIndex(GLenum target); + static GLenum layerIndexToTarget(GLint layer); protected: - friend class RenderbufferTextureCubeMap; + friend class TextureCubeMapAttachment; rx::RenderTarget *getRenderTarget(GLenum target, GLint level); - rx::RenderTarget *getDepthStencil(GLenum target, GLint level); private: DISALLOW_COPY_AND_ASSIGN(TextureCubeMap); - virtual void initializeStorage(bool renderTarget); - rx::TextureStorageInterfaceCube *createCompleteStorage(bool renderTarget) const; - void setCompleteTexStorage(rx::TextureStorageInterfaceCube *newCompleteTexStorage); - - virtual void updateStorage(); - virtual bool ensureRenderTarget(); - virtual rx::TextureStorageInterface *getBaseLevelStorage(); - virtual const rx::Image *getBaseLevelImage() const; - - bool isMipmapCubeComplete() const; - bool isValidFaceLevel(int faceIndex, int level) const; + bool isMipmapComplete() const; bool isFaceLevelComplete(int faceIndex, int level) const; - void updateStorageFaceLevel(int faceIndex, int level); - - void setImage(int faceIndex, GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); - void commitRect(int faceIndex, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); - void redefineImage(int faceIndex, GLint level, GLenum internalformat, GLsizei width, GLsizei height); - - rx::Image *mImageArray[6][IMPLEMENTATION_MAX_TEXTURE_LEVELS]; - - rx::TextureStorageInterfaceCube *mTexStorage; }; class Texture3D : public Texture { public: - Texture3D(rx::Renderer *renderer, GLuint id); + Texture3D(rx::TextureImpl *impl, GLuint id); - ~Texture3D(); + virtual ~Texture3D(); GLsizei getWidth(GLint level) const; GLsizei getHeight(GLint level) const; @@ -324,52 +208,27 @@ class Texture3D : public Texture void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels); void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); - virtual void generateMipmaps(); - virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source); + virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const; - virtual bool isSamplerComplete(const SamplerState &samplerState) const; - virtual bool isMipmapComplete() const; - - Renderbuffer *getRenderbuffer(GLint level, GLint layer); unsigned int getRenderTargetSerial(GLint level, GLint layer); protected: - friend class RenderbufferTexture3DLayer; - rx::RenderTarget *getRenderTarget(GLint level); + friend class Texture3DAttachment; rx::RenderTarget *getRenderTarget(GLint level, GLint layer); - rx::RenderTarget *getDepthStencil(GLint level, GLint layer); private: DISALLOW_COPY_AND_ASSIGN(Texture3D); - virtual void initializeStorage(bool renderTarget); - rx::TextureStorageInterface3D *createCompleteStorage(bool renderTarget) const; - void setCompleteTexStorage(rx::TextureStorageInterface3D *newCompleteTexStorage); - - virtual void updateStorage(); - virtual bool ensureRenderTarget(); - - virtual rx::TextureStorageInterface *getBaseLevelStorage(); - virtual const rx::Image *getBaseLevelImage() const; - - void redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); - void commitRect(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth); - - bool isValidLevel(int level) const; + bool isMipmapComplete() const; bool isLevelComplete(int level) const; - void updateStorageLevel(int level); - - rx::Image *mImageArray[IMPLEMENTATION_MAX_TEXTURE_LEVELS]; - - rx::TextureStorageInterface3D *mTexStorage; }; class Texture2DArray : public Texture { public: - Texture2DArray(rx::Renderer *renderer, GLuint id); + Texture2DArray(rx::TextureImpl *impl, GLuint id); - ~Texture2DArray(); + virtual ~Texture2DArray(); GLsizei getWidth(GLint level) const; GLsizei getHeight(GLint level) const; @@ -385,49 +244,19 @@ class Texture2DArray : public Texture void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels); void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); - virtual void generateMipmaps(); - virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source); + virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const; - virtual bool isSamplerComplete(const SamplerState &samplerState) const; - virtual bool isMipmapComplete() const; - - Renderbuffer *getRenderbuffer(GLint level, GLint layer); unsigned int getRenderTargetSerial(GLint level, GLint layer); protected: - friend class RenderbufferTexture2DArrayLayer; + friend class Texture2DArrayAttachment; rx::RenderTarget *getRenderTarget(GLint level, GLint layer); - rx::RenderTarget *getDepthStencil(GLint level, GLint layer); private: DISALLOW_COPY_AND_ASSIGN(Texture2DArray); - virtual void initializeStorage(bool renderTarget); - rx::TextureStorageInterface2DArray *createCompleteStorage(bool renderTarget) const; - void setCompleteTexStorage(rx::TextureStorageInterface2DArray *newCompleteTexStorage); - - virtual void updateStorage(); - virtual bool ensureRenderTarget(); - - virtual rx::TextureStorageInterface *getBaseLevelStorage(); - virtual const rx::Image *getBaseLevelImage() const; - - void deleteImages(); - void redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); - void commitRect(GLint level, GLint xoffset, GLint yoffset, GLint layerTarget, GLsizei width, GLsizei height); - - bool isValidLevel(int level) const; + bool isMipmapComplete() const; bool isLevelComplete(int level) const; - void updateStorageLevel(int level); - - // Storing images as an array of single depth textures since D3D11 treats each array level of a - // Texture2D object as a separate subresource. Each layer would have to be looped over - // to update all the texture layers since they cannot all be updated at once and it makes the most - // sense for the Image class to not have to worry about layer subresource as well as mip subresources. - GLsizei mLayerCounts[IMPLEMENTATION_MAX_TEXTURE_LEVELS]; - rx::Image **mImageArray[IMPLEMENTATION_MAX_TEXTURE_LEVELS]; - - rx::TextureStorageInterface2DArray *mTexStorage; }; } diff --git a/gfx/angle/src/libGLESv2/TransformFeedback.cpp b/gfx/angle/src/libGLESv2/TransformFeedback.cpp index 79ce08405d1c..bfa7072326ac 100644 --- a/gfx/angle/src/libGLESv2/TransformFeedback.cpp +++ b/gfx/angle/src/libGLESv2/TransformFeedback.cpp @@ -5,20 +5,24 @@ // #include "libGLESv2/TransformFeedback.h" +#include "libGLESv2/renderer/TransformFeedbackImpl.h" namespace gl { -TransformFeedback::TransformFeedback(GLuint id) +TransformFeedback::TransformFeedback(rx::TransformFeedbackImpl* impl, GLuint id) : RefCountObject(id), + mTransformFeedback(impl), mStarted(GL_FALSE), mPrimitiveMode(GL_NONE), mPaused(GL_FALSE) { + ASSERT(impl != NULL); } TransformFeedback::~TransformFeedback() { + SafeDelete(mTransformFeedback); } void TransformFeedback::start(GLenum primitiveMode) @@ -26,6 +30,7 @@ void TransformFeedback::start(GLenum primitiveMode) mStarted = GL_TRUE; mPrimitiveMode = primitiveMode; mPaused = GL_FALSE; + mTransformFeedback->begin(primitiveMode); } void TransformFeedback::stop() @@ -33,6 +38,7 @@ void TransformFeedback::stop() mStarted = GL_FALSE; mPrimitiveMode = GL_NONE; mPaused = GL_FALSE; + mTransformFeedback->end(); } GLboolean TransformFeedback::isStarted() const @@ -48,11 +54,13 @@ GLenum TransformFeedback::getDrawMode() const void TransformFeedback::pause() { mPaused = GL_TRUE; + mTransformFeedback->pause(); } void TransformFeedback::resume() { mPaused = GL_FALSE; + mTransformFeedback->resume(); } GLboolean TransformFeedback::isPaused() const diff --git a/gfx/angle/src/libGLESv2/TransformFeedback.h b/gfx/angle/src/libGLESv2/TransformFeedback.h index 183873c82ff9..885a4fe172a6 100644 --- a/gfx/angle/src/libGLESv2/TransformFeedback.h +++ b/gfx/angle/src/libGLESv2/TransformFeedback.h @@ -10,8 +10,12 @@ #include "common/angleutils.h" #include "common/RefCountObject.h" -#include -#include +#include "angle_gl.h" + +namespace rx +{ +class TransformFeedbackImpl; +} namespace gl { @@ -19,7 +23,7 @@ namespace gl class TransformFeedback : public RefCountObject { public: - explicit TransformFeedback(GLuint id); + TransformFeedback(rx::TransformFeedbackImpl* impl, GLuint id); virtual ~TransformFeedback(); void start(GLenum primitiveMode); @@ -35,6 +39,8 @@ class TransformFeedback : public RefCountObject private: DISALLOW_COPY_AND_ASSIGN(TransformFeedback); + rx::TransformFeedbackImpl* mTransformFeedback; + GLboolean mStarted; GLenum mPrimitiveMode; GLboolean mPaused; diff --git a/gfx/angle/src/libGLESv2/Uniform.cpp b/gfx/angle/src/libGLESv2/Uniform.cpp index a5ab7cb517d9..bd0cd2eeec2a 100644 --- a/gfx/angle/src/libGLESv2/Uniform.cpp +++ b/gfx/angle/src/libGLESv2/Uniform.cpp @@ -1,4 +1,3 @@ -#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 @@ -13,7 +12,7 @@ namespace gl { LinkedUniform::LinkedUniform(GLenum type, GLenum precision, const std::string &name, unsigned int arraySize, - const int blockIndex, const BlockMemberInfo &blockInfo) + const int blockIndex, const sh::BlockMemberInfo &blockInfo) : type(type), precision(precision), name(name), @@ -71,7 +70,7 @@ bool LinkedUniform::isInDefaultBlock() const size_t LinkedUniform::dataSize() const { ASSERT(type != GL_STRUCT_ANGLEX); - return UniformInternalSize(type) * elementCount(); + return VariableInternalSize(type) * elementCount(); } bool LinkedUniform::isSampler() const diff --git a/gfx/angle/src/libGLESv2/Uniform.h b/gfx/angle/src/libGLESv2/Uniform.h index 221ba48f9497..633d70bb1937 100644 --- a/gfx/angle/src/libGLESv2/Uniform.h +++ b/gfx/angle/src/libGLESv2/Uniform.h @@ -7,23 +7,23 @@ #ifndef LIBGLESV2_UNIFORM_H_ #define LIBGLESV2_UNIFORM_H_ +#include "common/debug.h" +#include "common/blocklayout.h" + +#include "libGLESv2/angletypes.h" + +#include "angle_gl.h" + #include #include -#include -#include - -#include "common/debug.h" -#include "angletypes.h" -#include "common/shadervars.h" - namespace gl { // Helper struct representing a single shader uniform struct LinkedUniform { - LinkedUniform(GLenum type, GLenum precision, const std::string &name, unsigned int arraySize, const int blockIndex, const BlockMemberInfo &blockInfo); + LinkedUniform(GLenum type, GLenum precision, const std::string &name, unsigned int arraySize, const int blockIndex, const sh::BlockMemberInfo &blockInfo); ~LinkedUniform(); @@ -40,7 +40,7 @@ struct LinkedUniform const std::string name; const unsigned int arraySize; const int blockIndex; - const BlockMemberInfo blockInfo; + const sh::BlockMemberInfo blockInfo; unsigned char *data; bool dirty; diff --git a/gfx/angle/src/libGLESv2/VertexArray.cpp b/gfx/angle/src/libGLESv2/VertexArray.cpp index bd2df391695a..f8ca661062c5 100644 --- a/gfx/angle/src/libGLESv2/VertexArray.cpp +++ b/gfx/angle/src/libGLESv2/VertexArray.cpp @@ -1,4 +1,3 @@ -#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 @@ -9,31 +8,42 @@ #include "libGLESv2/VertexArray.h" #include "libGLESv2/Buffer.h" +#include "libGLESv2/renderer/VertexArrayImpl.h" namespace gl { -VertexArray::VertexArray(rx::Renderer *renderer, GLuint id) - : RefCountObject(id) +VertexArray::VertexArray(rx::VertexArrayImpl *impl, GLuint id, size_t maxAttribs) + : mId(id), + mVertexArray(impl), + mVertexAttributes(maxAttribs) { + ASSERT(impl != NULL); } VertexArray::~VertexArray() { - for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) + SafeDelete(mVertexArray); + + for (size_t i = 0; i < getMaxAttribs(); i++) { - mVertexAttributes[i].mBoundBuffer.set(NULL); + mVertexAttributes[i].buffer.set(NULL); } mElementArrayBuffer.set(NULL); } +GLuint VertexArray::id() const +{ + return mId; +} + void VertexArray::detachBuffer(GLuint bufferName) { - for (int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++) + for (size_t attribute = 0; attribute < getMaxAttribs(); attribute++) { - if (mVertexAttributes[attribute].mBoundBuffer.id() == bufferName) + if (mVertexAttributes[attribute].buffer.id() == bufferName) { - mVertexAttributes[attribute].mBoundBuffer.set(NULL); + mVertexAttributes[attribute].buffer.set(NULL); } } @@ -43,29 +53,44 @@ void VertexArray::detachBuffer(GLuint bufferName) } } -const VertexAttribute& VertexArray::getVertexAttribute(unsigned int attributeIndex) const +const VertexAttribute& VertexArray::getVertexAttribute(size_t attributeIndex) const { - ASSERT(attributeIndex < MAX_VERTEX_ATTRIBS); + ASSERT(attributeIndex < getMaxAttribs()); return mVertexAttributes[attributeIndex]; } void VertexArray::setVertexAttribDivisor(GLuint index, GLuint divisor) { - ASSERT(index < gl::MAX_VERTEX_ATTRIBS); - mVertexAttributes[index].mDivisor = divisor; + ASSERT(index < getMaxAttribs()); + mVertexAttributes[index].divisor = divisor; + mVertexArray->setAttributeDivisor(index, divisor); } void VertexArray::enableAttribute(unsigned int attributeIndex, bool enabledState) { - ASSERT(attributeIndex < gl::MAX_VERTEX_ATTRIBS); - mVertexAttributes[attributeIndex].mArrayEnabled = enabledState; + ASSERT(attributeIndex < getMaxAttribs()); + mVertexAttributes[attributeIndex].enabled = enabledState; + mVertexArray->enableAttribute(attributeIndex, enabledState); } void VertexArray::setAttributeState(unsigned int attributeIndex, gl::Buffer *boundBuffer, GLint size, GLenum type, bool normalized, bool pureInteger, GLsizei stride, const void *pointer) { - ASSERT(attributeIndex < gl::MAX_VERTEX_ATTRIBS); - mVertexAttributes[attributeIndex].setState(boundBuffer, size, type, normalized, pureInteger, stride, pointer); + ASSERT(attributeIndex < getMaxAttribs()); + mVertexAttributes[attributeIndex].buffer.set(boundBuffer); + mVertexAttributes[attributeIndex].size = size; + mVertexAttributes[attributeIndex].type = type; + mVertexAttributes[attributeIndex].normalized = normalized; + mVertexAttributes[attributeIndex].pureInteger = pureInteger; + mVertexAttributes[attributeIndex].stride = stride; + mVertexAttributes[attributeIndex].pointer = pointer; + mVertexArray->setAttribute(attributeIndex, mVertexAttributes[attributeIndex]); +} + +void VertexArray::setElementArrayBuffer(Buffer *buffer) +{ + mElementArrayBuffer.set(buffer); + mVertexArray->setElementArrayBuffer(buffer); } } \ No newline at end of file diff --git a/gfx/angle/src/libGLESv2/VertexArray.h b/gfx/angle/src/libGLESv2/VertexArray.h index ecfe7ad8f91e..993ba042cfd4 100644 --- a/gfx/angle/src/libGLESv2/VertexArray.h +++ b/gfx/angle/src/libGLESv2/VertexArray.h @@ -17,35 +17,44 @@ #include "libGLESv2/constants.h" #include "libGLESv2/VertexAttribute.h" +#include + namespace rx { class Renderer; +class VertexArrayImpl; } namespace gl { class Buffer; -class VertexArray : public RefCountObject +class VertexArray { public: - VertexArray(rx::Renderer *renderer, GLuint id); + VertexArray(rx::VertexArrayImpl *impl, GLuint id, size_t maxAttribs); ~VertexArray(); - const VertexAttribute& getVertexAttribute(unsigned int attributeIndex) const; + GLuint id() const; + + const VertexAttribute& getVertexAttribute(size_t attributeIndex) const; void detachBuffer(GLuint bufferName); void setVertexAttribDivisor(GLuint index, GLuint divisor); void enableAttribute(unsigned int attributeIndex, bool enabledState); void setAttributeState(unsigned int attributeIndex, gl::Buffer *boundBuffer, GLint size, GLenum type, bool normalized, bool pureInteger, GLsizei stride, const void *pointer); - const VertexAttribute* getVertexAttributes() const { return mVertexAttributes; } + const VertexAttribute* getVertexAttributes() const { return mVertexAttributes.data(); } Buffer *getElementArrayBuffer() const { return mElementArrayBuffer.get(); } - void setElementArrayBuffer(Buffer *elementArrayBuffer) { mElementArrayBuffer.set(elementArrayBuffer); } + void setElementArrayBuffer(Buffer *buffer); GLuint getElementArrayBufferId() const { return mElementArrayBuffer.id(); } + size_t getMaxAttribs() const { return mVertexAttributes.size(); } private: - VertexAttribute mVertexAttributes[MAX_VERTEX_ATTRIBS]; + GLuint mId; + + rx::VertexArrayImpl *mVertexArray; + std::vector mVertexAttributes; BindingPointer mElementArrayBuffer; }; diff --git a/gfx/angle/src/libGLESv2/VertexAttribute.cpp b/gfx/angle/src/libGLESv2/VertexAttribute.cpp new file mode 100644 index 000000000000..1096856b8a57 --- /dev/null +++ b/gfx/angle/src/libGLESv2/VertexAttribute.cpp @@ -0,0 +1,55 @@ +// +// Copyright 2014 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. +// +// Implementation of the state class for mananging GLES 3 Vertex Array Objects. +// + +#include "libGLESv2/VertexAttribute.h" + +namespace gl +{ + +VertexAttribute::VertexAttribute() + : enabled(false), + type(GL_FLOAT), + size(4), + normalized(false), + pureInteger(false), + stride(0), + pointer(NULL), + divisor(0) +{ +} + +size_t ComputeVertexAttributeTypeSize(const VertexAttribute& attrib) +{ + GLuint size = attrib.size; + switch (attrib.type) + { + case GL_BYTE: return size * sizeof(GLbyte); + case GL_UNSIGNED_BYTE: return size * sizeof(GLubyte); + case GL_SHORT: return size * sizeof(GLshort); + case GL_UNSIGNED_SHORT: return size * sizeof(GLushort); + case GL_INT: return size * sizeof(GLint); + case GL_UNSIGNED_INT: return size * sizeof(GLuint); + case GL_INT_2_10_10_10_REV: return 4; + case GL_UNSIGNED_INT_2_10_10_10_REV: return 4; + case GL_FIXED: return size * sizeof(GLfixed); + case GL_HALF_FLOAT: return size * sizeof(GLhalf); + case GL_FLOAT: return size * sizeof(GLfloat); + default: UNREACHABLE(); return size * sizeof(GLfloat); + } +} + +size_t ComputeVertexAttributeStride(const VertexAttribute& attrib) +{ + if (!attrib.enabled) + { + return 16; + } + return attrib.stride ? attrib.stride : ComputeVertexAttributeTypeSize(attrib); +} + +} \ No newline at end of file diff --git a/gfx/angle/src/libGLESv2/VertexAttribute.h b/gfx/angle/src/libGLESv2/VertexAttribute.h index e9364d66e831..e9757b618b41 100644 --- a/gfx/angle/src/libGLESv2/VertexAttribute.h +++ b/gfx/angle/src/libGLESv2/VertexAttribute.h @@ -14,95 +14,58 @@ namespace gl { -class VertexAttribute +struct VertexAttribute { - public: - VertexAttribute() : mType(GL_FLOAT), mSize(4), mNormalized(false), mPureInteger(false), - mStride(0), mPointer(NULL), mArrayEnabled(false), mDivisor(0) - { - } + bool enabled; // From glEnable/DisableVertexAttribArray - int typeSize() const - { - switch (mType) - { - case GL_BYTE: return mSize * sizeof(GLbyte); - case GL_UNSIGNED_BYTE: return mSize * sizeof(GLubyte); - case GL_SHORT: return mSize * sizeof(GLshort); - case GL_UNSIGNED_SHORT: return mSize * sizeof(GLushort); - case GL_INT: return mSize * sizeof(GLint); - case GL_UNSIGNED_INT: return mSize * sizeof(GLuint); - case GL_INT_2_10_10_10_REV: return 4; - case GL_UNSIGNED_INT_2_10_10_10_REV: return 4; - case GL_FIXED: return mSize * sizeof(GLfixed); - case GL_HALF_FLOAT: return mSize * sizeof(GLhalf); - case GL_FLOAT: return mSize * sizeof(GLfloat); - default: UNREACHABLE(); return mSize * sizeof(GLfloat); - } - } - - GLsizei stride() const - { - return (mArrayEnabled ? (mStride ? mStride : typeSize()) : 16); - } - - void setState(gl::Buffer *boundBuffer, GLint size, GLenum type, bool normalized, - bool pureInteger, GLsizei stride, const void *pointer) - { - mBoundBuffer.set(boundBuffer); - mSize = size; - mType = type; - mNormalized = normalized; - mPureInteger = pureInteger; - mStride = stride; - mPointer = pointer; - } - - template - T querySingleParameter(GLenum pname) const - { - switch (pname) - { - case GL_VERTEX_ATTRIB_ARRAY_ENABLED: - return static_cast(mArrayEnabled ? GL_TRUE : GL_FALSE); - case GL_VERTEX_ATTRIB_ARRAY_SIZE: - return static_cast(mSize); - case GL_VERTEX_ATTRIB_ARRAY_STRIDE: - return static_cast(mStride); - case GL_VERTEX_ATTRIB_ARRAY_TYPE: - return static_cast(mType); - case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED: - return static_cast(mNormalized ? GL_TRUE : GL_FALSE); - case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: - return static_cast(mBoundBuffer.id()); - case GL_VERTEX_ATTRIB_ARRAY_DIVISOR: - return static_cast(mDivisor); - case GL_VERTEX_ATTRIB_ARRAY_INTEGER: - return static_cast(mPureInteger ? GL_TRUE : GL_FALSE); - default: - UNREACHABLE(); - return static_cast(0); - } - } - - // From glVertexAttribPointer - GLenum mType; - GLint mSize; - bool mNormalized; - bool mPureInteger; - GLsizei mStride; // 0 means natural stride + GLenum type; + GLuint size; + bool normalized; + bool pureInteger; + GLuint stride; // 0 means natural stride union { - const void *mPointer; - intptr_t mOffset; + const GLvoid *pointer; + GLintptr offset; }; + BindingPointer buffer; // Captured when glVertexAttribPointer is called. - BindingPointer mBoundBuffer; // Captured when glVertexAttribPointer is called. - bool mArrayEnabled; // From glEnable/DisableVertexAttribArray - unsigned int mDivisor; + GLuint divisor; + + VertexAttribute(); }; +template +T QuerySingleVertexAttributeParameter(const VertexAttribute& attrib, GLenum pname) +{ + switch (pname) + { + case GL_VERTEX_ATTRIB_ARRAY_ENABLED: + return static_cast(attrib.enabled ? GL_TRUE : GL_FALSE); + case GL_VERTEX_ATTRIB_ARRAY_SIZE: + return static_cast(attrib.size); + case GL_VERTEX_ATTRIB_ARRAY_STRIDE: + return static_cast(attrib.stride); + case GL_VERTEX_ATTRIB_ARRAY_TYPE: + return static_cast(attrib.type); + case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED: + return static_cast(attrib.normalized ? GL_TRUE : GL_FALSE); + case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: + return static_cast(attrib.buffer.id()); + case GL_VERTEX_ATTRIB_ARRAY_DIVISOR: + return static_cast(attrib.divisor); + case GL_VERTEX_ATTRIB_ARRAY_INTEGER: + return static_cast(attrib.pureInteger ? GL_TRUE : GL_FALSE); + default: + UNREACHABLE(); + return static_cast(0); + } +} + +size_t ComputeVertexAttributeTypeSize(const VertexAttribute& attrib); +size_t ComputeVertexAttributeStride(const VertexAttribute& attrib); + struct VertexAttribCurrentValueData { union diff --git a/gfx/angle/src/libGLESv2/angletypes.cpp b/gfx/angle/src/libGLESv2/angletypes.cpp index acb3da8999d5..06618d554c3d 100644 --- a/gfx/angle/src/libGLESv2/angletypes.cpp +++ b/gfx/angle/src/libGLESv2/angletypes.cpp @@ -1,4 +1,3 @@ -#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 @@ -14,6 +13,25 @@ namespace gl { +SamplerState::SamplerState() + : minFilter(GL_NEAREST_MIPMAP_LINEAR), + magFilter(GL_LINEAR), + wrapS(GL_REPEAT), + wrapT(GL_REPEAT), + wrapR(GL_REPEAT), + maxAnisotropy(1.0f), + baseLevel(0), + maxLevel(1000), + minLod(-1000.0f), + maxLod(1000.0f), + compareMode(GL_NONE), + compareFunc(GL_LEQUAL), + swizzleRed(GL_RED), + swizzleGreen(GL_GREEN), + swizzleBlue(GL_BLUE), + swizzleAlpha(GL_ALPHA) +{} + bool SamplerState::swizzleRequired() const { return swizzleRed != GL_RED || swizzleGreen != GL_GREEN || @@ -90,15 +108,15 @@ VertexFormat::VertexFormat(GLenum type, GLboolean normalized, GLuint components, } } -VertexFormat::VertexFormat(const VertexAttribute &attribute) - : mType(attribute.mType), - mNormalized(attribute.mNormalized ? GL_TRUE : GL_FALSE), - mComponents(attribute.mSize), - mPureInteger(attribute.mPureInteger) +VertexFormat::VertexFormat(const VertexAttribute &attrib) + : mType(attrib.type), + mNormalized(attrib.normalized ? GL_TRUE : GL_FALSE), + mComponents(attrib.size), + mPureInteger(attrib.pureInteger) { // Ensure we aren't initializing a vertex format which should be using // the current-value type - ASSERT(attribute.mArrayEnabled); + ASSERT(attrib.enabled); // Float data can not be normalized, so ignore the user setting if (mType == GL_FLOAT || mType == GL_HALF_FLOAT || mType == GL_FIXED) @@ -107,13 +125,13 @@ VertexFormat::VertexFormat(const VertexAttribute &attribute) } } -VertexFormat::VertexFormat(const VertexAttribute &attribute, GLenum currentValueType) - : mType(attribute.mType), - mNormalized(attribute.mNormalized ? GL_TRUE : GL_FALSE), - mComponents(attribute.mSize), - mPureInteger(attribute.mPureInteger) +VertexFormat::VertexFormat(const VertexAttribute &attrib, GLenum currentValueType) + : mType(attrib.type), + mNormalized(attrib.normalized ? GL_TRUE : GL_FALSE), + mComponents(attrib.size), + mPureInteger(attrib.pureInteger) { - if (!attribute.mArrayEnabled) + if (!attrib.enabled) { mType = currentValueType; mNormalized = GL_FALSE; diff --git a/gfx/angle/src/libGLESv2/angletypes.h b/gfx/angle/src/libGLESv2/angletypes.h index 0e91279d2418..79ad810e9e43 100644 --- a/gfx/angle/src/libGLESv2/angletypes.h +++ b/gfx/angle/src/libGLESv2/angletypes.h @@ -16,7 +16,7 @@ namespace gl { class Buffer; class ProgramBinary; -class VertexAttribute; +struct VertexAttribute; struct VertexAttribCurrentValueData; enum TextureType @@ -147,6 +147,8 @@ struct DepthStencilState struct SamplerState { + SamplerState(); + GLenum minFilter; GLenum magFilter; GLenum wrapS; diff --git a/gfx/angle/src/libGLESv2/Constants.h b/gfx/angle/src/libGLESv2/constants.h similarity index 74% rename from gfx/angle/src/libGLESv2/Constants.h rename to gfx/angle/src/libGLESv2/constants.h index 0c1c0ef13750..c87f92d4978a 100644 --- a/gfx/angle/src/libGLESv2/Constants.h +++ b/gfx/angle/src/libGLESv2/constants.h @@ -31,11 +31,17 @@ enum IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS, IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS = 4, -}; -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; + // These are the maximums the implementation can support + // The actual GL caps are limited by the device caps + // and should be queried from the Context + IMPLEMENTATION_MAX_2D_TEXTURE_SIZE = 16384, + IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE = 16384, + IMPLEMENTATION_MAX_3D_TEXTURE_SIZE = 2048, + IMPLEMENTATION_MAX_2D_ARRAY_TEXTURE_LAYERS = 2048, + + IMPLEMENTATION_MAX_TEXTURE_LEVELS = 15 // 1+log2 of MAX_TEXTURE_SIZE +}; } diff --git a/gfx/angle/src/libGLESv2/formatutils.cpp b/gfx/angle/src/libGLESv2/formatutils.cpp index 3aac25efadd0..9d988292a746 100644 --- a/gfx/angle/src/libGLESv2/formatutils.cpp +++ b/gfx/angle/src/libGLESv2/formatutils.cpp @@ -1,6 +1,5 @@ -#include "precompiled.h" // -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2013-2014 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. // @@ -22,82 +21,26 @@ namespace gl // can decide the true, sized, internal format. The ES2FormatMap determines the internal format for all valid // format and type combinations. -struct FormatTypeInfo +FormatType::FormatType() + : internalFormat(GL_NONE), + colorWriteFunction(NULL) { - GLenum mInternalFormat; - ColorWriteFunction mColorWriteFunction; - - FormatTypeInfo(GLenum internalFormat, ColorWriteFunction writeFunc) - : mInternalFormat(internalFormat), mColorWriteFunction(writeFunc) - { } -}; +} typedef std::pair FormatTypePair; -typedef std::pair FormatPair; -typedef std::map FormatMap; +typedef std::pair FormatPair; +typedef std::map FormatMap; // A helper function to insert data into the format map with fewer characters. static inline void InsertFormatMapping(FormatMap *map, GLenum format, GLenum type, GLenum internalFormat, ColorWriteFunction writeFunc) { - map->insert(FormatPair(FormatTypePair(format, type), FormatTypeInfo(internalFormat, writeFunc))); + FormatType info; + info.internalFormat = internalFormat; + info.colorWriteFunction = writeFunc; + map->insert(FormatPair(FormatTypePair(format, type), info)); } -FormatMap BuildES2FormatMap() -{ - FormatMap map; - - using namespace rx; - - // | Format | Type | Internal format | Color write function | - InsertFormatMapping(&map, GL_ALPHA, GL_UNSIGNED_BYTE, GL_ALPHA8_EXT, WriteColor ); - InsertFormatMapping(&map, GL_ALPHA, GL_FLOAT, GL_ALPHA32F_EXT, WriteColor ); - InsertFormatMapping(&map, GL_ALPHA, GL_HALF_FLOAT_OES, GL_ALPHA16F_EXT, WriteColor ); - - InsertFormatMapping(&map, GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_LUMINANCE8_EXT, WriteColor ); - InsertFormatMapping(&map, GL_LUMINANCE, GL_FLOAT, GL_LUMINANCE32F_EXT, WriteColor ); - InsertFormatMapping(&map, GL_LUMINANCE, GL_HALF_FLOAT_OES, GL_LUMINANCE16F_EXT, WriteColor ); - - InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_LUMINANCE8_ALPHA8_EXT, WriteColor ); - InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_FLOAT, GL_LUMINANCE_ALPHA32F_EXT, WriteColor ); - InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, GL_LUMINANCE_ALPHA16F_EXT, WriteColor ); - - InsertFormatMapping(&map, GL_RED, GL_UNSIGNED_BYTE, GL_R8_EXT, WriteColor ); - InsertFormatMapping(&map, GL_RED, GL_FLOAT, GL_R32F_EXT, WriteColor ); - InsertFormatMapping(&map, GL_RED, GL_HALF_FLOAT_OES, GL_R16F_EXT, WriteColor ); - - InsertFormatMapping(&map, GL_RG, GL_UNSIGNED_BYTE, GL_RG8_EXT, WriteColor ); - InsertFormatMapping(&map, GL_RG, GL_FLOAT, GL_RG32F_EXT, WriteColor ); - InsertFormatMapping(&map, GL_RG, GL_HALF_FLOAT_OES, GL_RG16F_EXT, WriteColor ); - - InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_BYTE, GL_RGB8_OES, WriteColor ); - InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, GL_RGB565, WriteColor ); - InsertFormatMapping(&map, GL_RGB, GL_FLOAT, GL_RGB32F_EXT, WriteColor ); - InsertFormatMapping(&map, GL_RGB, GL_HALF_FLOAT_OES, GL_RGB16F_EXT, WriteColor ); - - InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_BYTE, GL_RGBA8_OES, WriteColor ); - InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, GL_RGBA4, WriteColor ); - InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, GL_RGB5_A1, WriteColor ); - InsertFormatMapping(&map, GL_RGBA, GL_FLOAT, GL_RGBA32F_EXT, WriteColor); - InsertFormatMapping(&map, GL_RGBA, GL_HALF_FLOAT_OES, GL_RGBA16F_EXT, WriteColor); - - InsertFormatMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_BGRA8_EXT, WriteColor ); - InsertFormatMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, GL_BGRA4_ANGLEX, WriteColor ); - InsertFormatMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, GL_BGR5_A1_ANGLEX, WriteColor ); - - InsertFormatMapping(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, NULL ); - InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, NULL ); - InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, NULL ); - InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, NULL ); - - InsertFormatMapping(&map, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_DEPTH_COMPONENT16, NULL ); - InsertFormatMapping(&map, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_DEPTH_COMPONENT32_OES, NULL ); - - InsertFormatMapping(&map, GL_DEPTH_STENCIL_OES, GL_UNSIGNED_INT_24_8_OES, GL_DEPTH24_STENCIL8_OES, NULL ); - - return map; -} - -FormatMap BuildES3FormatMap() +FormatMap BuildFormatMap() { FormatMap map; @@ -111,6 +54,7 @@ FormatMap BuildES3FormatMap() InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, GL_RGB10_A2, WriteColor ); InsertFormatMapping(&map, GL_RGBA, GL_FLOAT, GL_RGBA32F, WriteColor); InsertFormatMapping(&map, GL_RGBA, GL_HALF_FLOAT, GL_RGBA16F, WriteColor); + InsertFormatMapping(&map, GL_RGBA, GL_HALF_FLOAT_OES, GL_RGBA16F, WriteColor); InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, GL_RGBA8UI, WriteColor ); InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_BYTE, GL_RGBA8I, WriteColor ); @@ -127,6 +71,7 @@ FormatMap BuildES3FormatMap() InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, GL_RGB9_E5, WriteColor ); InsertFormatMapping(&map, GL_RGB, GL_FLOAT, GL_RGB32F, WriteColor ); InsertFormatMapping(&map, GL_RGB, GL_HALF_FLOAT, GL_RGB16F, WriteColor ); + InsertFormatMapping(&map, GL_RGB, GL_HALF_FLOAT_OES, GL_RGB16F, WriteColor ); InsertFormatMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, GL_RGB8UI, WriteColor ); InsertFormatMapping(&map, GL_RGB_INTEGER, GL_BYTE, GL_RGB8I, WriteColor ); @@ -139,6 +84,7 @@ FormatMap BuildES3FormatMap() InsertFormatMapping(&map, GL_RG, GL_BYTE, GL_RG8_SNORM, WriteColor ); InsertFormatMapping(&map, GL_RG, GL_FLOAT, GL_RG32F, WriteColor ); InsertFormatMapping(&map, GL_RG, GL_HALF_FLOAT, GL_RG16F, WriteColor ); + InsertFormatMapping(&map, GL_RG, GL_HALF_FLOAT_OES, GL_RG16F, WriteColor ); InsertFormatMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_BYTE, GL_RG8UI, WriteColor ); InsertFormatMapping(&map, GL_RG_INTEGER, GL_BYTE, GL_RG8I, WriteColor ); @@ -151,6 +97,7 @@ FormatMap BuildES3FormatMap() InsertFormatMapping(&map, GL_RED, GL_BYTE, GL_R8_SNORM, WriteColor ); InsertFormatMapping(&map, GL_RED, GL_FLOAT, GL_R32F, WriteColor ); InsertFormatMapping(&map, GL_RED, GL_HALF_FLOAT, GL_R16F, WriteColor ); + InsertFormatMapping(&map, GL_RED, GL_HALF_FLOAT_OES, GL_R16F, WriteColor ); InsertFormatMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_BYTE, GL_R8UI, WriteColor ); InsertFormatMapping(&map, GL_RED_INTEGER, GL_BYTE, GL_R8I, WriteColor ); @@ -166,1647 +113,510 @@ FormatMap BuildES3FormatMap() InsertFormatMapping(&map, GL_LUMINANCE, GL_FLOAT, GL_LUMINANCE32F_EXT, WriteColor ); InsertFormatMapping(&map, GL_ALPHA, GL_FLOAT, GL_ALPHA32F_EXT, WriteColor ); InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT, GL_LUMINANCE_ALPHA16F_EXT, WriteColor ); + InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, GL_LUMINANCE_ALPHA16F_EXT, WriteColor ); InsertFormatMapping(&map, GL_LUMINANCE, GL_HALF_FLOAT, GL_LUMINANCE16F_EXT, WriteColor ); + InsertFormatMapping(&map, GL_LUMINANCE, GL_HALF_FLOAT_OES, GL_LUMINANCE16F_EXT, WriteColor ); InsertFormatMapping(&map, GL_ALPHA, GL_HALF_FLOAT, GL_ALPHA16F_EXT, WriteColor ); + InsertFormatMapping(&map, GL_ALPHA, GL_HALF_FLOAT_OES, GL_ALPHA16F_EXT, WriteColor ); InsertFormatMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_BGRA8_EXT, WriteColor ); InsertFormatMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, GL_BGRA4_ANGLEX, WriteColor ); InsertFormatMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, GL_BGR5_A1_ANGLEX, WriteColor ); + InsertFormatMapping(&map, GL_SRGB_EXT, GL_UNSIGNED_BYTE, GL_SRGB8, WriteColor ); + InsertFormatMapping(&map, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, GL_SRGB8_ALPHA8, WriteColor ); + + InsertFormatMapping(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, NULL ); + InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, NULL ); + InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, NULL ); + InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, NULL ); + InsertFormatMapping(&map, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_DEPTH_COMPONENT16, NULL ); - InsertFormatMapping(&map, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_DEPTH_COMPONENT24, NULL ); + InsertFormatMapping(&map, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_DEPTH_COMPONENT32_OES, NULL ); InsertFormatMapping(&map, GL_DEPTH_COMPONENT, GL_FLOAT, GL_DEPTH_COMPONENT32F, NULL ); + InsertFormatMapping(&map, GL_STENCIL, GL_UNSIGNED_BYTE, GL_STENCIL_INDEX8, NULL ); + InsertFormatMapping(&map, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_DEPTH24_STENCIL8, NULL ); InsertFormatMapping(&map, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_DEPTH32F_STENCIL8, NULL ); return map; } -static const FormatMap &GetFormatMap(GLuint clientVersion) +Type::Type() + : bytes(0), + specialInterpretation(false) { - if (clientVersion == 2) - { - static const FormatMap formats = BuildES2FormatMap(); - return formats; - } - else if (clientVersion == 3) - { - static const FormatMap formats = BuildES3FormatMap(); - return formats; - } - else - { - UNREACHABLE(); - static FormatMap emptyMap; - return emptyMap; - } -} - -struct FormatInfo -{ - GLenum mInternalformat; - GLenum mFormat; - GLenum mType; - - FormatInfo(GLenum internalformat, GLenum format, GLenum type) - : mInternalformat(internalformat), mFormat(format), mType(type) { } - - bool operator<(const FormatInfo& other) const - { - return memcmp(this, &other, sizeof(FormatInfo)) < 0; - } -}; - -// ES3 has a specific set of permutations of internal formats, formats and types which are acceptable. -typedef std::set ES3FormatSet; - -ES3FormatSet BuildES3FormatSet() -{ - ES3FormatSet set; - - // Format combinations from ES 3.0.1 spec, table 3.2 - - // | Internal format | Format | Type | - // | | | | - set.insert(FormatInfo(GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_RGBA4, GL_RGBA, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_RGBA8_SNORM, GL_RGBA, GL_BYTE )); - set.insert(FormatInfo(GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 )); - set.insert(FormatInfo(GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV )); - set.insert(FormatInfo(GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV )); - set.insert(FormatInfo(GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 )); - set.insert(FormatInfo(GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT )); - set.insert(FormatInfo(GL_RGBA32F, GL_RGBA, GL_FLOAT )); - set.insert(FormatInfo(GL_RGBA16F, GL_RGBA, GL_FLOAT )); - set.insert(FormatInfo(GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE )); - set.insert(FormatInfo(GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT )); - set.insert(FormatInfo(GL_RGBA16I, GL_RGBA_INTEGER, GL_SHORT )); - set.insert(FormatInfo(GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT )); - set.insert(FormatInfo(GL_RGBA32I, GL_RGBA_INTEGER, GL_INT )); - set.insert(FormatInfo(GL_RGB10_A2UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV )); - set.insert(FormatInfo(GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_RGB565, GL_RGB, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_SRGB8, GL_RGB, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_RGB8_SNORM, GL_RGB, GL_BYTE )); - set.insert(FormatInfo(GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 )); - set.insert(FormatInfo(GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV )); - set.insert(FormatInfo(GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV )); - set.insert(FormatInfo(GL_RGB16F, GL_RGB, GL_HALF_FLOAT )); - set.insert(FormatInfo(GL_R11F_G11F_B10F, GL_RGB, GL_HALF_FLOAT )); - set.insert(FormatInfo(GL_RGB9_E5, GL_RGB, GL_HALF_FLOAT )); - set.insert(FormatInfo(GL_RGB32F, GL_RGB, GL_FLOAT )); - set.insert(FormatInfo(GL_RGB16F, GL_RGB, GL_FLOAT )); - set.insert(FormatInfo(GL_R11F_G11F_B10F, GL_RGB, GL_FLOAT )); - set.insert(FormatInfo(GL_RGB9_E5, GL_RGB, GL_FLOAT )); - set.insert(FormatInfo(GL_RGB8UI, GL_RGB_INTEGER, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_RGB8I, GL_RGB_INTEGER, GL_BYTE )); - set.insert(FormatInfo(GL_RGB16UI, GL_RGB_INTEGER, GL_UNSIGNED_SHORT )); - set.insert(FormatInfo(GL_RGB16I, GL_RGB_INTEGER, GL_SHORT )); - set.insert(FormatInfo(GL_RGB32UI, GL_RGB_INTEGER, GL_UNSIGNED_INT )); - set.insert(FormatInfo(GL_RGB32I, GL_RGB_INTEGER, GL_INT )); - set.insert(FormatInfo(GL_RG8, GL_RG, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_RG8_SNORM, GL_RG, GL_BYTE )); - set.insert(FormatInfo(GL_RG16F, GL_RG, GL_HALF_FLOAT )); - set.insert(FormatInfo(GL_RG32F, GL_RG, GL_FLOAT )); - set.insert(FormatInfo(GL_RG16F, GL_RG, GL_FLOAT )); - set.insert(FormatInfo(GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_RG8I, GL_RG_INTEGER, GL_BYTE )); - set.insert(FormatInfo(GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT )); - set.insert(FormatInfo(GL_RG16I, GL_RG_INTEGER, GL_SHORT )); - set.insert(FormatInfo(GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT )); - set.insert(FormatInfo(GL_RG32I, GL_RG_INTEGER, GL_INT )); - set.insert(FormatInfo(GL_R8, GL_RED, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_R8_SNORM, GL_RED, GL_BYTE )); - set.insert(FormatInfo(GL_R16F, GL_RED, GL_HALF_FLOAT )); - set.insert(FormatInfo(GL_R32F, GL_RED, GL_FLOAT )); - set.insert(FormatInfo(GL_R16F, GL_RED, GL_FLOAT )); - set.insert(FormatInfo(GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_R8I, GL_RED_INTEGER, GL_BYTE )); - set.insert(FormatInfo(GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT )); - set.insert(FormatInfo(GL_R16I, GL_RED_INTEGER, GL_SHORT )); - set.insert(FormatInfo(GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT )); - set.insert(FormatInfo(GL_R32I, GL_RED_INTEGER, GL_INT )); - - // Unsized formats - set.insert(FormatInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 )); - set.insert(FormatInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 )); - set.insert(FormatInfo(GL_RGB, GL_RGB, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 )); - set.insert(FormatInfo(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE )); - - // Depth stencil formats - set.insert(FormatInfo(GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT )); - set.insert(FormatInfo(GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT )); - set.insert(FormatInfo(GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT )); - set.insert(FormatInfo(GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT )); - set.insert(FormatInfo(GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8 )); - set.insert(FormatInfo(GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV)); - - // From GL_OES_texture_float - set.insert(FormatInfo(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT )); - set.insert(FormatInfo(GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT )); - set.insert(FormatInfo(GL_ALPHA, GL_ALPHA, GL_FLOAT )); - - // From GL_OES_texture_half_float - set.insert(FormatInfo(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT )); - set.insert(FormatInfo(GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT )); - set.insert(FormatInfo(GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT )); - - // From GL_EXT_texture_format_BGRA8888 - set.insert(FormatInfo(GL_BGRA_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE )); - - // From GL_EXT_texture_storage - // | Internal format | Format | Type | - // | | | | - set.insert(FormatInfo(GL_ALPHA8_EXT, GL_ALPHA, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_LUMINANCE8_EXT, GL_LUMINANCE, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_ALPHA32F_EXT, GL_ALPHA, GL_FLOAT )); - set.insert(FormatInfo(GL_LUMINANCE32F_EXT, GL_LUMINANCE, GL_FLOAT )); - set.insert(FormatInfo(GL_LUMINANCE_ALPHA32F_EXT, GL_LUMINANCE_ALPHA, GL_FLOAT )); - set.insert(FormatInfo(GL_ALPHA16F_EXT, GL_ALPHA, GL_HALF_FLOAT )); - set.insert(FormatInfo(GL_LUMINANCE16F_EXT, GL_LUMINANCE, GL_HALF_FLOAT )); - set.insert(FormatInfo(GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT )); - - // From GL_EXT_texture_storage and GL_EXT_texture_format_BGRA8888 - set.insert(FormatInfo(GL_BGRA8_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_BGRA4_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT)); - set.insert(FormatInfo(GL_BGRA4_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_BGR5_A1_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT)); - set.insert(FormatInfo(GL_BGR5_A1_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_BYTE )); - - // From GL_ANGLE_depth_texture - set.insert(FormatInfo(GL_DEPTH_COMPONENT32_OES, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT_24_8_OES )); - - // Compressed formats - // From ES 3.0.1 spec, table 3.16 - // | Internal format | Format | Type | - // | | | | - set.insert(FormatInfo(GL_COMPRESSED_R11_EAC, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE)); - set.insert(FormatInfo(GL_COMPRESSED_R11_EAC, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE)); - set.insert(FormatInfo(GL_COMPRESSED_SIGNED_R11_EAC, GL_COMPRESSED_SIGNED_R11_EAC, GL_UNSIGNED_BYTE)); - set.insert(FormatInfo(GL_COMPRESSED_RG11_EAC, GL_COMPRESSED_RG11_EAC, GL_UNSIGNED_BYTE)); - set.insert(FormatInfo(GL_COMPRESSED_SIGNED_RG11_EAC, GL_COMPRESSED_SIGNED_RG11_EAC, GL_UNSIGNED_BYTE)); - set.insert(FormatInfo(GL_COMPRESSED_RGB8_ETC2, GL_COMPRESSED_RGB8_ETC2, GL_UNSIGNED_BYTE)); - set.insert(FormatInfo(GL_COMPRESSED_SRGB8_ETC2, GL_COMPRESSED_SRGB8_ETC2, GL_UNSIGNED_BYTE)); - set.insert(FormatInfo(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE)); - set.insert(FormatInfo(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE)); - set.insert(FormatInfo(GL_COMPRESSED_RGBA8_ETC2_EAC, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_UNSIGNED_BYTE)); - set.insert(FormatInfo(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_UNSIGNED_BYTE)); - - - // From GL_EXT_texture_compression_dxt1 - set.insert(FormatInfo(GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE)); - set.insert(FormatInfo(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE)); - - // From GL_ANGLE_texture_compression_dxt3 - set.insert(FormatInfo(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE)); - - // From GL_ANGLE_texture_compression_dxt5 - set.insert(FormatInfo(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE)); - - return set; -} - -static const ES3FormatSet &GetES3FormatSet() -{ - static const ES3FormatSet es3FormatSet = BuildES3FormatSet(); - return es3FormatSet; } // Map of sizes of input types -struct TypeInfo +typedef std::pair TypeInfoPair; +typedef std::map TypeInfoMap; + +static inline void InsertTypeInfo(TypeInfoMap *map, GLenum type, GLuint bytes, bool specialInterpretation) { - GLuint mTypeBytes; - bool mSpecialInterpretation; + Type info; + info.bytes = bytes; + info.specialInterpretation = specialInterpretation; - TypeInfo() - : mTypeBytes(0), mSpecialInterpretation(false) { } + map->insert(std::make_pair(type, info)); +} - TypeInfo(GLuint typeBytes, bool specialInterpretation) - : mTypeBytes(typeBytes), mSpecialInterpretation(specialInterpretation) { } - - bool operator<(const TypeInfo& other) const - { - return memcmp(this, &other, sizeof(TypeInfo)) < 0; - } -}; - -typedef std::pair TypeInfoPair; -typedef std::map TypeInfoMap; +bool operator<(const Type& a, const Type& b) +{ + return memcmp(&a, &b, sizeof(Type)) < 0; +} static TypeInfoMap BuildTypeInfoMap() { TypeInfoMap map; - map.insert(TypeInfoPair(GL_UNSIGNED_BYTE, TypeInfo( 1, false))); - map.insert(TypeInfoPair(GL_BYTE, TypeInfo( 1, false))); - map.insert(TypeInfoPair(GL_UNSIGNED_SHORT, TypeInfo( 2, false))); - map.insert(TypeInfoPair(GL_SHORT, TypeInfo( 2, false))); - map.insert(TypeInfoPair(GL_UNSIGNED_INT, TypeInfo( 4, false))); - map.insert(TypeInfoPair(GL_INT, TypeInfo( 4, false))); - map.insert(TypeInfoPair(GL_HALF_FLOAT, TypeInfo( 2, false))); - map.insert(TypeInfoPair(GL_HALF_FLOAT_OES, TypeInfo( 2, false))); - map.insert(TypeInfoPair(GL_FLOAT, TypeInfo( 4, false))); - map.insert(TypeInfoPair(GL_UNSIGNED_SHORT_5_6_5, TypeInfo( 2, true ))); - map.insert(TypeInfoPair(GL_UNSIGNED_SHORT_4_4_4_4, TypeInfo( 2, true ))); - map.insert(TypeInfoPair(GL_UNSIGNED_SHORT_5_5_5_1, TypeInfo( 2, true ))); - map.insert(TypeInfoPair(GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, TypeInfo( 2, true ))); - map.insert(TypeInfoPair(GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, TypeInfo( 2, true ))); - map.insert(TypeInfoPair(GL_UNSIGNED_INT_2_10_10_10_REV, TypeInfo( 4, true ))); - map.insert(TypeInfoPair(GL_UNSIGNED_INT_24_8, TypeInfo( 4, true ))); - map.insert(TypeInfoPair(GL_UNSIGNED_INT_10F_11F_11F_REV, TypeInfo( 4, true ))); - map.insert(TypeInfoPair(GL_UNSIGNED_INT_5_9_9_9_REV, TypeInfo( 4, true ))); - map.insert(TypeInfoPair(GL_UNSIGNED_INT_24_8_OES, TypeInfo( 4, true ))); - map.insert(TypeInfoPair(GL_FLOAT_32_UNSIGNED_INT_24_8_REV, TypeInfo( 8, true ))); + InsertTypeInfo(&map, GL_UNSIGNED_BYTE, 1, false); + InsertTypeInfo(&map, GL_BYTE, 1, false); + InsertTypeInfo(&map, GL_UNSIGNED_SHORT, 2, false); + InsertTypeInfo(&map, GL_SHORT, 2, false); + InsertTypeInfo(&map, GL_UNSIGNED_INT, 4, false); + InsertTypeInfo(&map, GL_INT, 4, false); + InsertTypeInfo(&map, GL_HALF_FLOAT, 2, false); + InsertTypeInfo(&map, GL_HALF_FLOAT_OES, 2, false); + InsertTypeInfo(&map, GL_FLOAT, 4, false); + InsertTypeInfo(&map, GL_UNSIGNED_SHORT_5_6_5, 2, true ); + InsertTypeInfo(&map, GL_UNSIGNED_SHORT_4_4_4_4, 2, true ); + InsertTypeInfo(&map, GL_UNSIGNED_SHORT_5_5_5_1, 2, true ); + InsertTypeInfo(&map, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, 2, true ); + InsertTypeInfo(&map, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, 2, true ); + InsertTypeInfo(&map, GL_UNSIGNED_INT_2_10_10_10_REV, 4, true ); + InsertTypeInfo(&map, GL_UNSIGNED_INT_24_8, 4, true ); + InsertTypeInfo(&map, GL_UNSIGNED_INT_10F_11F_11F_REV, 4, true ); + InsertTypeInfo(&map, GL_UNSIGNED_INT_5_9_9_9_REV, 4, true ); + InsertTypeInfo(&map, GL_UNSIGNED_INT_24_8_OES, 4, true ); + InsertTypeInfo(&map, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, 8, true ); return map; } -static bool GetTypeInfo(GLenum type, TypeInfo *outTypeInfo) +// Information about internal formats +static bool AlwaysSupported(GLuint, const Extensions &) +{ + return true; +} + +static bool UnimplementedSupport(GLuint, const Extensions &) +{ + return false; +} + +static bool NeverSupported(GLuint, const Extensions &) +{ + return false; +} + +template +static bool RequireESVersion(GLuint clientVersion, const Extensions &) +{ + return clientVersion >= minCoreGLVersion; +} + +// Pointer to a boolean memeber of the Extensions struct +typedef bool(Extensions::*ExtensionBool); + +// Check support for a single extension +template +static bool RequireExtension(GLuint, const Extensions & extensions) +{ + return extensions.*bool1; +} + +// Check for a minimum client version or a single extension +template +static bool RequireESVersionOrExtension(GLuint clientVersion, const Extensions &extensions) +{ + return clientVersion >= minCoreGLVersion || extensions.*bool1; +} + +// Check for a minimum client version or two extensions +template +static bool RequireESVersionOrExtensions(GLuint clientVersion, const Extensions &extensions) +{ + return clientVersion >= minCoreGLVersion || (extensions.*bool1 || extensions.*bool2); +} + +// Check support for two extensions +template +static bool RequireExtensions(GLuint, const Extensions &extensions) +{ + return extensions.*bool1 || extensions.*bool2; +} + +InternalFormat::InternalFormat() + : redBits(0), + greenBits(0), + blueBits(0), + luminanceBits(0), + alphaBits(0), + sharedBits(0), + depthBits(0), + stencilBits(0), + pixelBytes(0), + componentCount(0), + compressedBlockWidth(0), + compressedBlockHeight(0), + format(GL_NONE), + type(GL_NONE), + componentType(GL_NONE), + colorEncoding(GL_NONE), + compressed(false), + textureSupport(NeverSupported), + renderSupport(NeverSupported), + filterSupport(NeverSupported) +{ +} + +static InternalFormat UnsizedFormat(GLenum format, InternalFormat::SupportCheckFunction textureSupport, + InternalFormat::SupportCheckFunction renderSupport, + InternalFormat::SupportCheckFunction filterSupport) +{ + InternalFormat formatInfo; + formatInfo.format = format; + formatInfo.textureSupport = textureSupport; + formatInfo.renderSupport = renderSupport; + formatInfo.filterSupport = filterSupport; + return formatInfo; +} + +static InternalFormat RGBAFormat(GLuint red, GLuint green, GLuint blue, GLuint alpha, GLuint shared, + GLenum format, GLenum type, GLenum componentType, bool srgb, + InternalFormat::SupportCheckFunction textureSupport, + InternalFormat::SupportCheckFunction renderSupport, + InternalFormat::SupportCheckFunction filterSupport) +{ + InternalFormat formatInfo; + formatInfo.redBits = red; + formatInfo.greenBits = green; + formatInfo.blueBits = blue; + formatInfo.alphaBits = alpha; + formatInfo.sharedBits = shared; + formatInfo.pixelBytes = (red + green + blue + alpha + shared) / 8; + formatInfo.componentCount = ((red > 0) ? 1 : 0) + ((green > 0) ? 1 : 0) + ((blue > 0) ? 1 : 0) + ((alpha > 0) ? 1 : 0); + formatInfo.format = format; + formatInfo.type = type; + formatInfo.componentType = componentType; + formatInfo.colorEncoding = (srgb ? GL_SRGB : GL_LINEAR); + formatInfo.textureSupport = textureSupport; + formatInfo.renderSupport = renderSupport; + formatInfo.filterSupport = filterSupport; + return formatInfo; +} + +static InternalFormat LUMAFormat(GLuint luminance, GLuint alpha, GLenum format, GLenum type, GLenum componentType, + InternalFormat::SupportCheckFunction textureSupport, + InternalFormat::SupportCheckFunction renderSupport, + InternalFormat::SupportCheckFunction filterSupport) +{ + InternalFormat formatInfo; + formatInfo.luminanceBits = luminance; + formatInfo.alphaBits = alpha; + formatInfo.pixelBytes = (luminance + alpha) / 8; + formatInfo.componentCount = ((luminance > 0) ? 1 : 0) + ((alpha > 0) ? 1 : 0); + formatInfo.format = format; + formatInfo.type = type; + formatInfo.componentType = componentType; + formatInfo.colorEncoding = GL_LINEAR; + formatInfo.textureSupport = textureSupport; + formatInfo.renderSupport = renderSupport; + formatInfo.filterSupport = filterSupport; + return formatInfo; +} + +static InternalFormat DepthStencilFormat(GLuint depthBits, GLuint stencilBits, GLuint unusedBits, GLenum format, + GLenum type, GLenum componentType, InternalFormat::SupportCheckFunction textureSupport, + InternalFormat::SupportCheckFunction renderSupport, + InternalFormat::SupportCheckFunction filterSupport) +{ + InternalFormat formatInfo; + formatInfo.depthBits = depthBits; + formatInfo.stencilBits = stencilBits; + formatInfo.pixelBytes = (depthBits + stencilBits + unusedBits) / 8; + formatInfo.componentCount = ((depthBits > 0) ? 1 : 0) + ((stencilBits > 0) ? 1 : 0); + formatInfo.format = format; + formatInfo.type = type; + formatInfo.componentType = componentType; + formatInfo.colorEncoding = GL_LINEAR; + formatInfo.textureSupport = textureSupport; + formatInfo.renderSupport = renderSupport; + formatInfo.filterSupport = filterSupport; + return formatInfo; +} + +static InternalFormat CompressedFormat(GLuint compressedBlockWidth, GLuint compressedBlockHeight, GLuint compressedBlockSize, + GLuint componentCount, GLenum format, GLenum type, bool srgb, + InternalFormat::SupportCheckFunction textureSupport, + InternalFormat::SupportCheckFunction renderSupport, + InternalFormat::SupportCheckFunction filterSupport) +{ + InternalFormat formatInfo; + formatInfo.compressedBlockWidth = compressedBlockWidth; + formatInfo.compressedBlockHeight = compressedBlockHeight; + formatInfo.pixelBytes = compressedBlockSize / 8; + formatInfo.componentCount = componentCount; + formatInfo.format = format; + formatInfo.type = type; + formatInfo.componentType = GL_UNSIGNED_NORMALIZED; + formatInfo.colorEncoding = (srgb ? GL_SRGB : GL_LINEAR); + formatInfo.compressed = true; + formatInfo.textureSupport = textureSupport; + formatInfo.renderSupport = renderSupport; + formatInfo.filterSupport = filterSupport; + return formatInfo; +} + +typedef std::pair InternalFormatInfoPair; +typedef std::map InternalFormatInfoMap; + +static InternalFormatInfoMap BuildInternalFormatInfoMap() +{ + InternalFormatInfoMap map; + + // From ES 3.0.1 spec, table 3.12 + map.insert(InternalFormatInfoPair(GL_NONE, InternalFormat())); + + // | Internal format | | R | G | B | A |S | Format | Type | Component type | SRGB | Texture supported | Renderable | Filterable | + map.insert(InternalFormatInfoPair(GL_R8, RGBAFormat( 8, 0, 0, 0, 0, GL_RED, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireESVersionOrExtension<3, &Extensions::textureRG>, AlwaysSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_R8_SNORM, RGBAFormat( 8, 0, 0, 0, 0, GL_RED, GL_BYTE, GL_SIGNED_NORMALIZED, false, RequireESVersion<3>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_RG8, RGBAFormat( 8, 8, 0, 0, 0, GL_RG, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireESVersionOrExtension<3, &Extensions::textureRG>, AlwaysSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_RG8_SNORM, RGBAFormat( 8, 8, 0, 0, 0, GL_RG, GL_BYTE, GL_SIGNED_NORMALIZED, false, RequireESVersion<3>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_RGB8, RGBAFormat( 8, 8, 8, 0, 0, GL_RGB, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireESVersionOrExtension<3, &Extensions::rgb8rgba8>, AlwaysSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_RGB8_SNORM, RGBAFormat( 8, 8, 8, 0, 0, GL_RGB, GL_BYTE, GL_SIGNED_NORMALIZED, false, RequireESVersion<3>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_RGB565, RGBAFormat( 5, 6, 5, 0, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_NORMALIZED, false, RequireESVersion<2>, AlwaysSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_RGBA4, RGBAFormat( 4, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_NORMALIZED, false, RequireESVersion<2>, AlwaysSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_RGB5_A1, RGBAFormat( 5, 5, 5, 1, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_NORMALIZED, false, RequireESVersion<2>, AlwaysSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_RGBA8, RGBAFormat( 8, 8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireESVersionOrExtension<3, &Extensions::rgb8rgba8>, AlwaysSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_RGBA8_SNORM, RGBAFormat( 8, 8, 8, 8, 0, GL_RGBA, GL_BYTE, GL_SIGNED_NORMALIZED, false, RequireESVersion<3>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_RGB10_A2, RGBAFormat(10, 10, 10, 2, 0, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_NORMALIZED, false, RequireESVersion<3>, AlwaysSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_RGB10_A2UI, RGBAFormat(10, 10, 10, 2, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT, false, RequireESVersion<3>, NeverSupported, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_SRGB8, RGBAFormat( 8, 8, 8, 0, 0, GL_RGB, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, true, RequireESVersionOrExtension<3, &Extensions::sRGB>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_SRGB8_ALPHA8, RGBAFormat( 8, 8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, true, RequireESVersionOrExtension<3, &Extensions::sRGB>, AlwaysSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_R11F_G11F_B10F, RGBAFormat(11, 11, 10, 0, 0, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, GL_FLOAT, false, RequireESVersion<3>, RequireExtension<&Extensions::colorBufferFloat>, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_RGB9_E5, RGBAFormat( 9, 9, 9, 0, 5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, GL_FLOAT, false, RequireESVersion<3>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_R8I, RGBAFormat( 8, 0, 0, 0, 0, GL_RED_INTEGER, GL_BYTE, GL_INT, false, RequireESVersion<3>, AlwaysSupported, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_R8UI, RGBAFormat( 8, 0, 0, 0, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireESVersion<3>, AlwaysSupported, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_R16I, RGBAFormat(16, 0, 0, 0, 0, GL_RED_INTEGER, GL_SHORT, GL_INT, false, RequireESVersion<3>, AlwaysSupported, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_R16UI, RGBAFormat(16, 0, 0, 0, 0, GL_RED_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireESVersion<3>, AlwaysSupported, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_R32I, RGBAFormat(32, 0, 0, 0, 0, GL_RED_INTEGER, GL_INT, GL_INT, false, RequireESVersion<3>, AlwaysSupported, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_R32UI, RGBAFormat(32, 0, 0, 0, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireESVersion<3>, AlwaysSupported, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_RG8I, RGBAFormat( 8, 8, 0, 0, 0, GL_RG_INTEGER, GL_BYTE, GL_INT, false, RequireESVersion<3>, AlwaysSupported, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_RG8UI, RGBAFormat( 8, 8, 0, 0, 0, GL_RG_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireESVersion<3>, AlwaysSupported, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_RG16I, RGBAFormat(16, 16, 0, 0, 0, GL_RG_INTEGER, GL_SHORT, GL_INT, false, RequireESVersion<3>, AlwaysSupported, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_RG16UI, RGBAFormat(16, 16, 0, 0, 0, GL_RG_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireESVersion<3>, AlwaysSupported, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_RG32I, RGBAFormat(32, 32, 0, 0, 0, GL_RG_INTEGER, GL_INT, GL_INT, false, RequireESVersion<3>, AlwaysSupported, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_RG32UI, RGBAFormat(32, 32, 0, 0, 0, GL_RG_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireESVersion<3>, AlwaysSupported, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_RGB8I, RGBAFormat( 8, 8, 8, 0, 0, GL_RGB_INTEGER, GL_BYTE, GL_INT, false, RequireESVersion<3>, NeverSupported, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_RGB8UI, RGBAFormat( 8, 8, 8, 0, 0, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireESVersion<3>, NeverSupported, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_RGB16I, RGBAFormat(16, 16, 16, 0, 0, GL_RGB_INTEGER, GL_SHORT, GL_INT, false, RequireESVersion<3>, NeverSupported, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_RGB16UI, RGBAFormat(16, 16, 16, 0, 0, GL_RGB_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireESVersion<3>, NeverSupported, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_RGB32I, RGBAFormat(32, 32, 32, 0, 0, GL_RGB_INTEGER, GL_INT, GL_INT, false, RequireESVersion<3>, NeverSupported, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_RGB32UI, RGBAFormat(32, 32, 32, 0, 0, GL_RGB_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireESVersion<3>, NeverSupported, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_RGBA8I, RGBAFormat( 8, 8, 8, 8, 0, GL_RGBA_INTEGER, GL_BYTE, GL_INT, false, RequireESVersion<3>, AlwaysSupported, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_RGBA8UI, RGBAFormat( 8, 8, 8, 8, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireESVersion<3>, AlwaysSupported, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_RGBA16I, RGBAFormat(16, 16, 16, 16, 0, GL_RGBA_INTEGER, GL_SHORT, GL_INT, false, RequireESVersion<3>, AlwaysSupported, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_RGBA16UI, RGBAFormat(16, 16, 16, 16, 0, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireESVersion<3>, AlwaysSupported, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_RGBA32I, RGBAFormat(32, 32, 32, 32, 0, GL_RGBA_INTEGER, GL_INT, GL_INT, false, RequireESVersion<3>, AlwaysSupported, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_RGBA32UI, RGBAFormat(32, 32, 32, 32, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireESVersion<3>, AlwaysSupported, NeverSupported))); + + map.insert(InternalFormatInfoPair(GL_BGRA8_EXT, RGBAFormat( 8, 8, 8, 8, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireExtension<&Extensions::textureFormatBGRA8888>, AlwaysSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_BGRA4_ANGLEX, RGBAFormat( 4, 4, 4, 4, 0, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, GL_UNSIGNED_NORMALIZED, false, RequireExtension<&Extensions::textureFormatBGRA8888>, AlwaysSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_BGR5_A1_ANGLEX, RGBAFormat( 5, 5, 5, 1, 0, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, GL_UNSIGNED_NORMALIZED, false, RequireExtension<&Extensions::textureFormatBGRA8888>, AlwaysSupported, AlwaysSupported))); + + // Floating point renderability and filtering is provided by OES_texture_float and OES_texture_half_float + // | Internal format | | D |S | Format | Type | Comp | SRGB | Texture supported | Renderable | Filterable | + // | | | | | | | type | | | | | + map.insert(InternalFormatInfoPair(GL_R16F, RGBAFormat(16, 0, 0, 0, 0, GL_RED, GL_HALF_FLOAT, GL_FLOAT, false, RequireESVersionOrExtensions<3, &Extensions::textureHalfFloat, &Extensions::textureRG>, AlwaysSupported, RequireExtension<&Extensions::textureHalfFloatLinear>))); + map.insert(InternalFormatInfoPair(GL_RG16F, RGBAFormat(16, 16, 0, 0, 0, GL_RG, GL_HALF_FLOAT, GL_FLOAT, false, RequireESVersionOrExtensions<3, &Extensions::textureHalfFloat, &Extensions::textureRG>, AlwaysSupported, RequireExtension<&Extensions::textureHalfFloatLinear>))); + map.insert(InternalFormatInfoPair(GL_RGB16F, RGBAFormat(16, 16, 16, 0, 0, GL_RGB, GL_HALF_FLOAT, GL_FLOAT, false, RequireESVersionOrExtension<3, &Extensions::textureHalfFloat>, AlwaysSupported, RequireExtension<&Extensions::textureHalfFloatLinear>))); + map.insert(InternalFormatInfoPair(GL_RGBA16F, RGBAFormat(16, 16, 16, 16, 0, GL_RGBA, GL_HALF_FLOAT, GL_FLOAT, false, RequireESVersionOrExtension<3, &Extensions::textureHalfFloat>, AlwaysSupported, RequireExtension<&Extensions::textureHalfFloatLinear>))); + map.insert(InternalFormatInfoPair(GL_R32F, RGBAFormat(32, 0, 0, 0, 0, GL_RED, GL_FLOAT, GL_FLOAT, false, RequireESVersionOrExtensions<3, &Extensions::textureFloat, &Extensions::textureRG>, AlwaysSupported, RequireExtension<&Extensions::textureFloatLinear> ))); + map.insert(InternalFormatInfoPair(GL_RG32F, RGBAFormat(32, 32, 0, 0, 0, GL_RG, GL_FLOAT, GL_FLOAT, false, RequireESVersionOrExtensions<3, &Extensions::textureFloat, &Extensions::textureRG>, AlwaysSupported, RequireExtension<&Extensions::textureFloatLinear> ))); + map.insert(InternalFormatInfoPair(GL_RGB32F, RGBAFormat(32, 32, 32, 0, 0, GL_RGB, GL_FLOAT, GL_FLOAT, false, RequireESVersionOrExtension<3, &Extensions::textureFloat>, AlwaysSupported, RequireExtension<&Extensions::textureFloatLinear> ))); + map.insert(InternalFormatInfoPair(GL_RGBA32F, RGBAFormat(32, 32, 32, 32, 0, GL_RGBA, GL_FLOAT, GL_FLOAT, false, RequireESVersionOrExtension<3, &Extensions::textureFloat>, AlwaysSupported, RequireExtension<&Extensions::textureFloatLinear> ))); + + // Depth stencil formats + // | Internal format | | D |S | X | Format | Type | Component type | Supported | + map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT16, DepthStencilFormat(16, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_UNSIGNED_NORMALIZED, RequireESVersion<2>, AlwaysSupported, RequireESVersionOrExtension<3, &Extensions::depthTextures>))); + map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT24, DepthStencilFormat(24, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_UNSIGNED_NORMALIZED, RequireESVersion<3>, AlwaysSupported, RequireESVersionOrExtension<3, &Extensions::depthTextures>))); + map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT32F, DepthStencilFormat(32, 0, 0, GL_DEPTH_COMPONENT, GL_FLOAT, GL_FLOAT, RequireESVersion<3>, AlwaysSupported, RequireESVersionOrExtension<3, &Extensions::depthTextures>))); + map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT32_OES, DepthStencilFormat(32, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_UNSIGNED_NORMALIZED, RequireExtension<&Extensions::depthTextures>, AlwaysSupported, AlwaysSupported ))); + map.insert(InternalFormatInfoPair(GL_DEPTH24_STENCIL8, DepthStencilFormat(24, 8, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_UNSIGNED_NORMALIZED, RequireESVersionOrExtension<2, &Extensions::depthTextures>, AlwaysSupported, AlwaysSupported ))); + map.insert(InternalFormatInfoPair(GL_DEPTH32F_STENCIL8, DepthStencilFormat(32, 8, 24, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_FLOAT, RequireESVersion<3>, AlwaysSupported, AlwaysSupported ))); + map.insert(InternalFormatInfoPair(GL_STENCIL_INDEX8, DepthStencilFormat( 0, 8, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, RequireESVersion<2>, AlwaysSupported, NeverSupported ))); + + // Luminance alpha formats + // | Internal format | | L | A | Format | Type | Component type | Supported | Renderable | Filterable | + map.insert(InternalFormatInfoPair(GL_ALPHA8_EXT, LUMAFormat( 0, 8, GL_ALPHA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireExtension<&Extensions::textureStorage>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_LUMINANCE8_EXT, LUMAFormat( 8, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireExtension<&Extensions::textureStorage>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_ALPHA32F_EXT, LUMAFormat( 0, 32, GL_ALPHA, GL_FLOAT, GL_FLOAT, RequireExtensions<&Extensions::textureStorage, &Extensions::textureFloat>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_LUMINANCE32F_EXT, LUMAFormat(32, 0, GL_LUMINANCE, GL_FLOAT, GL_FLOAT, RequireExtensions<&Extensions::textureStorage, &Extensions::textureFloat>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_ALPHA16F_EXT, LUMAFormat( 0, 16, GL_ALPHA, GL_HALF_FLOAT, GL_FLOAT, RequireExtensions<&Extensions::textureStorage, &Extensions::textureHalfFloat>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_LUMINANCE16F_EXT, LUMAFormat(16, 0, GL_LUMINANCE, GL_HALF_FLOAT, GL_FLOAT, RequireExtensions<&Extensions::textureStorage, &Extensions::textureHalfFloat>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_LUMINANCE8_ALPHA8_EXT, LUMAFormat( 8, 8, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireExtension<&Extensions::textureStorage>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_LUMINANCE_ALPHA32F_EXT, LUMAFormat(32, 32, GL_LUMINANCE_ALPHA, GL_FLOAT, GL_FLOAT, RequireExtensions<&Extensions::textureStorage, &Extensions::textureFloat>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_LUMINANCE_ALPHA16F_EXT, LUMAFormat(16, 16, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT, GL_FLOAT, RequireExtensions<&Extensions::textureStorage, &Extensions::textureHalfFloat>, NeverSupported, AlwaysSupported))); + + // Unsized formats + // | Internal format | | Format | Supported | Renderable | Filterable | + map.insert(InternalFormatInfoPair(GL_ALPHA, UnsizedFormat(GL_ALPHA, RequireESVersion<2>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_LUMINANCE, UnsizedFormat(GL_LUMINANCE, RequireESVersion<2>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_LUMINANCE_ALPHA, UnsizedFormat(GL_LUMINANCE_ALPHA, RequireESVersion<2>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_RED, UnsizedFormat(GL_RED, RequireESVersionOrExtension<3, &Extensions::textureRG>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_RG, UnsizedFormat(GL_RG, RequireESVersionOrExtension<3, &Extensions::textureRG>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_RGB, UnsizedFormat(GL_RGB, RequireESVersion<2>, AlwaysSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_RGBA, UnsizedFormat(GL_RGBA, RequireESVersion<2>, AlwaysSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_RED_INTEGER, UnsizedFormat(GL_RED_INTEGER, RequireESVersion<3>, NeverSupported, NeverSupported ))); + map.insert(InternalFormatInfoPair(GL_RG_INTEGER, UnsizedFormat(GL_RG_INTEGER, RequireESVersion<3>, NeverSupported, NeverSupported ))); + map.insert(InternalFormatInfoPair(GL_RGB_INTEGER, UnsizedFormat(GL_RGB_INTEGER, RequireESVersion<3>, NeverSupported, NeverSupported ))); + map.insert(InternalFormatInfoPair(GL_RGBA_INTEGER, UnsizedFormat(GL_RGBA_INTEGER, RequireESVersion<3>, NeverSupported, NeverSupported ))); + map.insert(InternalFormatInfoPair(GL_BGRA_EXT, UnsizedFormat(GL_BGRA_EXT, RequireExtension<&Extensions::textureFormatBGRA8888>, AlwaysSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT, UnsizedFormat(GL_DEPTH_COMPONENT, RequireESVersion<2>, AlwaysSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_DEPTH_STENCIL, UnsizedFormat(GL_DEPTH_STENCIL, RequireESVersionOrExtension<3, &Extensions::packedDepthStencil>, AlwaysSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_SRGB_EXT, UnsizedFormat(GL_RGB, RequireESVersionOrExtension<3, &Extensions::sRGB>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_SRGB_ALPHA_EXT, UnsizedFormat(GL_RGBA, RequireESVersionOrExtension<3, &Extensions::sRGB>, AlwaysSupported, AlwaysSupported))); + + // Compressed formats, From ES 3.0.1 spec, table 3.16 + // | Internal format | |W |H | BS |CC| Format | Type | SRGB | Supported | Renderable | Filterable | + map.insert(InternalFormatInfoPair(GL_COMPRESSED_R11_EAC, CompressedFormat(4, 4, 64, 1, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_SIGNED_R11_EAC, CompressedFormat(4, 4, 64, 1, GL_COMPRESSED_SIGNED_R11_EAC, GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_RG11_EAC, CompressedFormat(4, 4, 128, 2, GL_COMPRESSED_RG11_EAC, GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_SIGNED_RG11_EAC, CompressedFormat(4, 4, 128, 2, GL_COMPRESSED_SIGNED_RG11_EAC, GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGB8_ETC2, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_RGB8_ETC2, GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ETC2, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_SRGB8_ETC2, GL_UNSIGNED_BYTE, true, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, true, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA8_ETC2_EAC, CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_UNSIGNED_BYTE, true, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); + + // From GL_EXT_texture_compression_dxt1 + // | Internal format | |W |H | BS |CC| Format | Type | SRGB | Supported | Renderable | Filterable | + map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGB_S3TC_DXT1_EXT, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, false, RequireExtension<&Extensions::textureCompressionDXT1>, NeverSupported, AlwaysSupported ))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, CompressedFormat(4, 4, 64, 4, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, false, RequireExtension<&Extensions::textureCompressionDXT1>, NeverSupported, AlwaysSupported ))); + + // From GL_ANGLE_texture_compression_dxt3 + map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, false, RequireExtension<&Extensions::textureCompressionDXT5>, NeverSupported, AlwaysSupported ))); + + // From GL_ANGLE_texture_compression_dxt5 + map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, false, RequireExtension<&Extensions::textureCompressionDXT5>, NeverSupported, AlwaysSupported ))); + + return map; +} + +static const InternalFormatInfoMap &GetInternalFormatMap() +{ + static const InternalFormatInfoMap formatMap = BuildInternalFormatInfoMap(); + return formatMap; +} + +static FormatSet BuildAllSizedInternalFormatSet() +{ + FormatSet result; + + const InternalFormatInfoMap &formats = GetInternalFormatMap(); + for (InternalFormatInfoMap::const_iterator i = formats.begin(); i != formats.end(); i++) + { + if (i->second.pixelBytes > 0) + { + result.insert(i->first); + } + } + + return result; +} + +const FormatType &GetFormatTypeInfo(GLenum format, GLenum type) +{ + static const FormatMap formatMap = BuildFormatMap(); + FormatMap::const_iterator iter = formatMap.find(FormatTypePair(format, type)); + if (iter != formatMap.end()) + { + return iter->second; + } + else + { + static const FormatType defaultInfo; + return defaultInfo; + } +} + +const Type &GetTypeInfo(GLenum type) { static const TypeInfoMap infoMap = BuildTypeInfoMap(); TypeInfoMap::const_iterator iter = infoMap.find(type); if (iter != infoMap.end()) { - if (outTypeInfo) - { - *outTypeInfo = iter->second; - } - return true; + return iter->second; } else { - return false; + static const Type defaultInfo; + return defaultInfo; } } -// Information about internal formats -typedef bool ((Context::*ContextSupportCheckMemberFunction)(void) const); -typedef bool (*ContextSupportCheckFunction)(const Context *context); - -typedef bool ((rx::Renderer::*RendererSupportCheckMemberFunction)(void) const); -typedef bool (*ContextRendererSupportCheckFunction)(const Context *context, const rx::Renderer *renderer); - -template -bool CheckSupport(const Context *context) +const InternalFormat &GetInternalFormatInfo(GLenum internalFormat) { - return (context->*func)(); -} - -template -bool CheckSupport(const Context *context, const rx::Renderer *renderer) -{ - if (context) + const InternalFormatInfoMap &formatMap = GetInternalFormatMap(); + InternalFormatInfoMap::const_iterator iter = formatMap.find(internalFormat); + if (iter != formatMap.end()) { - return (context->*contextFunc)(); - } - else if (renderer) - { - return (renderer->*rendererFunc)(); + return iter->second; } else { - UNREACHABLE(); - return false; + static const InternalFormat defaultInternalFormat; + return defaultInternalFormat; } } -template -bool AlwaysSupported(const objectType*) -{ - return true; -} - -template -bool AlwaysSupported(const objectTypeA*, const objectTypeB*) -{ - return true; -} - -template -bool NeverSupported(const objectType*) -{ - return false; -} - -template -bool NeverSupported(const objectTypeA *, const objectTypeB *) -{ - return false; -} - -template -bool UnimplementedSupport(const objectType*) -{ - UNIMPLEMENTED(); - return false; -} - -template -bool UnimplementedSupport(const objectTypeA*, const objectTypeB*) -{ - UNIMPLEMENTED(); - return false; -} - -struct InternalFormatInfo -{ - GLuint mRedBits; - GLuint mGreenBits; - GLuint mBlueBits; - - GLuint mLuminanceBits; - - GLuint mAlphaBits; - GLuint mSharedBits; - - GLuint mDepthBits; - GLuint mStencilBits; - - GLuint mPixelBits; - - GLuint mComponentCount; - - GLuint mCompressedBlockWidth; - GLuint mCompressedBlockHeight; - - GLenum mFormat; - GLenum mType; - - GLenum mComponentType; - GLenum mColorEncoding; - - bool mIsCompressed; - - ContextRendererSupportCheckFunction mIsColorRenderable; - ContextRendererSupportCheckFunction mIsDepthRenderable; - ContextRendererSupportCheckFunction mIsStencilRenderable; - ContextRendererSupportCheckFunction mIsTextureFilterable; - - ContextSupportCheckFunction mSupportFunction; - - InternalFormatInfo() : mRedBits(0), mGreenBits(0), mBlueBits(0), mLuminanceBits(0), mAlphaBits(0), mSharedBits(0), mDepthBits(0), mStencilBits(0), - mPixelBits(0), mComponentCount(0), mCompressedBlockWidth(0), mCompressedBlockHeight(0), mFormat(GL_NONE), mType(GL_NONE), - mComponentType(GL_NONE), mColorEncoding(GL_NONE), mIsCompressed(false), mIsColorRenderable(NeverSupported), - mIsDepthRenderable(NeverSupported), mIsStencilRenderable(NeverSupported), mIsTextureFilterable(NeverSupported), - mSupportFunction(NeverSupported) - { - } - - static InternalFormatInfo UnsizedFormat(GLenum format, ContextSupportCheckFunction supportFunction) - { - InternalFormatInfo formatInfo; - formatInfo.mFormat = format; - formatInfo.mSupportFunction = supportFunction; - - if (format == GL_RGB || format == GL_RGBA) - formatInfo.mIsColorRenderable = AlwaysSupported; - - return formatInfo; - } - - static InternalFormatInfo RGBAFormat(GLuint red, GLuint green, GLuint blue, GLuint alpha, GLuint shared, - GLenum format, GLenum type, GLenum componentType, bool srgb, - ContextRendererSupportCheckFunction colorRenderable, - ContextRendererSupportCheckFunction textureFilterable, - ContextSupportCheckFunction supportFunction) - { - InternalFormatInfo formatInfo; - formatInfo.mRedBits = red; - formatInfo.mGreenBits = green; - formatInfo.mBlueBits = blue; - formatInfo.mAlphaBits = alpha; - formatInfo.mSharedBits = shared; - formatInfo.mPixelBits = red + green + blue + alpha + shared; - formatInfo.mComponentCount = ((red > 0) ? 1 : 0) + ((green > 0) ? 1 : 0) + ((blue > 0) ? 1 : 0) + ((alpha > 0) ? 1 : 0); - formatInfo.mFormat = format; - formatInfo.mType = type; - formatInfo.mComponentType = componentType; - formatInfo.mColorEncoding = (srgb ? GL_SRGB : GL_LINEAR); - formatInfo.mIsColorRenderable = colorRenderable; - formatInfo.mIsTextureFilterable = textureFilterable; - formatInfo.mSupportFunction = supportFunction; - return formatInfo; - } - - static InternalFormatInfo LUMAFormat(GLuint luminance, GLuint alpha, GLenum format, GLenum type, GLenum componentType, - ContextSupportCheckFunction supportFunction) - { - InternalFormatInfo formatInfo; - formatInfo.mLuminanceBits = luminance; - formatInfo.mAlphaBits = alpha; - formatInfo.mPixelBits = luminance + alpha; - formatInfo.mComponentCount = ((luminance > 0) ? 1 : 0) + ((alpha > 0) ? 1 : 0); - formatInfo.mFormat = format; - formatInfo.mType = type; - formatInfo.mComponentType = componentType; - formatInfo.mColorEncoding = GL_LINEAR; - formatInfo.mIsTextureFilterable = AlwaysSupported; - formatInfo.mSupportFunction = supportFunction; - return formatInfo; - } - - static InternalFormatInfo DepthStencilFormat(GLuint depthBits, GLuint stencilBits, GLuint unusedBits, GLenum format, - GLenum type, GLenum componentType, - ContextRendererSupportCheckFunction depthRenderable, - ContextRendererSupportCheckFunction stencilRenderable, - ContextSupportCheckFunction supportFunction) - { - InternalFormatInfo formatInfo; - formatInfo.mDepthBits = depthBits; - formatInfo.mStencilBits = stencilBits; - formatInfo.mPixelBits = depthBits + stencilBits + unusedBits; - formatInfo.mComponentCount = ((depthBits > 0) ? 1 : 0) + ((stencilBits > 0) ? 1 : 0); - formatInfo.mFormat = format; - formatInfo.mType = type; - formatInfo.mComponentType = componentType; - formatInfo.mColorEncoding = GL_LINEAR; - formatInfo.mIsDepthRenderable = depthRenderable; - formatInfo.mIsStencilRenderable = stencilRenderable; - formatInfo.mIsTextureFilterable = AlwaysSupported; - formatInfo.mSupportFunction = supportFunction; - return formatInfo; - } - - static InternalFormatInfo CompressedFormat(GLuint compressedBlockWidth, GLuint compressedBlockHeight, GLuint compressedBlockSize, - GLuint componentCount, GLenum format, GLenum type, bool srgb, - ContextSupportCheckFunction supportFunction) - { - InternalFormatInfo formatInfo; - formatInfo.mCompressedBlockWidth = compressedBlockWidth; - formatInfo.mCompressedBlockHeight = compressedBlockHeight; - formatInfo.mPixelBits = compressedBlockSize; - formatInfo.mComponentCount = componentCount; - formatInfo.mFormat = format; - formatInfo.mType = type; - formatInfo.mComponentType = GL_UNSIGNED_NORMALIZED; - formatInfo.mColorEncoding = (srgb ? GL_SRGB : GL_LINEAR); - formatInfo.mIsCompressed = true; - formatInfo.mIsTextureFilterable = AlwaysSupported; - formatInfo.mSupportFunction = supportFunction; - return formatInfo; - } -}; - -typedef std::pair InternalFormatInfoPair; -typedef std::map InternalFormatInfoMap; - -static InternalFormatInfoMap BuildES3InternalFormatInfoMap() -{ - InternalFormatInfoMap map; - - // From ES 3.0.1 spec, table 3.12 - map.insert(InternalFormatInfoPair(GL_NONE, InternalFormatInfo())); - - // | Internal format | | R | G | B | A |S | Format | Type | Component type | SRGB | Color | Texture | Supported | - // | | | | | | | | | | | | renderable | filterable | | - map.insert(InternalFormatInfoPair(GL_R8, InternalFormatInfo::RGBAFormat( 8, 0, 0, 0, 0, GL_RED, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, AlwaysSupported, AlwaysSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_R8_SNORM, InternalFormatInfo::RGBAFormat( 8, 0, 0, 0, 0, GL_RED, GL_BYTE, GL_SIGNED_NORMALIZED, false, NeverSupported, AlwaysSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_RG8, InternalFormatInfo::RGBAFormat( 8, 8, 0, 0, 0, GL_RG, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, AlwaysSupported, AlwaysSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_RG8_SNORM, InternalFormatInfo::RGBAFormat( 8, 8, 0, 0, 0, GL_RG, GL_BYTE, GL_SIGNED_NORMALIZED, false, NeverSupported, AlwaysSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_RGB8, InternalFormatInfo::RGBAFormat( 8, 8, 8, 0, 0, GL_RGB, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, AlwaysSupported, AlwaysSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_RGB8_SNORM, InternalFormatInfo::RGBAFormat( 8, 8, 8, 0, 0, GL_RGB, GL_BYTE, GL_SIGNED_NORMALIZED, false, NeverSupported, AlwaysSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_RGB565, InternalFormatInfo::RGBAFormat( 5, 6, 5, 0, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_NORMALIZED, false, AlwaysSupported, AlwaysSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_RGBA4, InternalFormatInfo::RGBAFormat( 4, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_NORMALIZED, false, AlwaysSupported, AlwaysSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_RGB5_A1, InternalFormatInfo::RGBAFormat( 5, 5, 5, 1, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_NORMALIZED, false, AlwaysSupported, AlwaysSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_RGBA8, InternalFormatInfo::RGBAFormat( 8, 8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, AlwaysSupported, AlwaysSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_RGBA8_SNORM, InternalFormatInfo::RGBAFormat( 8, 8, 8, 8, 0, GL_RGBA, GL_BYTE, GL_SIGNED_NORMALIZED, false, NeverSupported, AlwaysSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_RGB10_A2, InternalFormatInfo::RGBAFormat(10, 10, 10, 2, 0, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_NORMALIZED, false, AlwaysSupported, AlwaysSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_RGB10_A2UI, InternalFormatInfo::RGBAFormat(10, 10, 10, 2, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT, false, AlwaysSupported, NeverSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_SRGB8, InternalFormatInfo::RGBAFormat( 8, 8, 8, 0, 0, GL_RGB, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, true, NeverSupported, AlwaysSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_SRGB8_ALPHA8, InternalFormatInfo::RGBAFormat( 8, 8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, true, AlwaysSupported, AlwaysSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_R11F_G11F_B10F, InternalFormatInfo::RGBAFormat(11, 11, 10, 0, 0, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, GL_FLOAT, false, AlwaysSupported, AlwaysSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_RGB9_E5, InternalFormatInfo::RGBAFormat( 9, 9, 9, 0, 5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, GL_FLOAT, false, NeverSupported, AlwaysSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_R8I, InternalFormatInfo::RGBAFormat( 8, 0, 0, 0, 0, GL_RED_INTEGER, GL_BYTE, GL_INT, false, AlwaysSupported, NeverSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_R8UI, InternalFormatInfo::RGBAFormat( 8, 0, 0, 0, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, AlwaysSupported, NeverSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_R16I, InternalFormatInfo::RGBAFormat(16, 0, 0, 0, 0, GL_RED_INTEGER, GL_SHORT, GL_INT, false, AlwaysSupported, NeverSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_R16UI, InternalFormatInfo::RGBAFormat(16, 0, 0, 0, 0, GL_RED_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, AlwaysSupported, NeverSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_R32I, InternalFormatInfo::RGBAFormat(32, 0, 0, 0, 0, GL_RED_INTEGER, GL_INT, GL_INT, false, AlwaysSupported, NeverSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_R32UI, InternalFormatInfo::RGBAFormat(32, 0, 0, 0, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, AlwaysSupported, NeverSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_RG8I, InternalFormatInfo::RGBAFormat( 8, 8, 0, 0, 0, GL_RG_INTEGER, GL_BYTE, GL_INT, false, AlwaysSupported, NeverSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_RG8UI, InternalFormatInfo::RGBAFormat( 8, 8, 0, 0, 0, GL_RG_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, AlwaysSupported, NeverSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_RG16I, InternalFormatInfo::RGBAFormat(16, 16, 0, 0, 0, GL_RG_INTEGER, GL_SHORT, GL_INT, false, AlwaysSupported, NeverSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_RG16UI, InternalFormatInfo::RGBAFormat(16, 16, 0, 0, 0, GL_RG_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, AlwaysSupported, NeverSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_RG32I, InternalFormatInfo::RGBAFormat(32, 32, 0, 0, 0, GL_RG_INTEGER, GL_INT, GL_INT, false, AlwaysSupported, NeverSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_RG32UI, InternalFormatInfo::RGBAFormat(32, 32, 0, 0, 0, GL_RG_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, AlwaysSupported, NeverSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_RGB8I, InternalFormatInfo::RGBAFormat( 8, 8, 8, 0, 0, GL_RGB_INTEGER, GL_BYTE, GL_INT, false, NeverSupported, NeverSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_RGB8UI, InternalFormatInfo::RGBAFormat( 8, 8, 8, 0, 0, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, NeverSupported, NeverSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_RGB16I, InternalFormatInfo::RGBAFormat(16, 16, 16, 0, 0, GL_RGB_INTEGER, GL_SHORT, GL_INT, false, NeverSupported, NeverSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_RGB16UI, InternalFormatInfo::RGBAFormat(16, 16, 16, 0, 0, GL_RGB_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, NeverSupported, NeverSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_RGB32I, InternalFormatInfo::RGBAFormat(32, 32, 32, 0, 0, GL_RGB_INTEGER, GL_INT, GL_INT, false, NeverSupported, NeverSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_RGB32UI, InternalFormatInfo::RGBAFormat(32, 32, 32, 0, 0, GL_RGB_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, NeverSupported, NeverSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_RGBA8I, InternalFormatInfo::RGBAFormat( 8, 8, 8, 8, 0, GL_RGBA_INTEGER, GL_BYTE, GL_INT, false, AlwaysSupported, NeverSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_RGBA8UI, InternalFormatInfo::RGBAFormat( 8, 8, 8, 8, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, AlwaysSupported, NeverSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_RGBA16I, InternalFormatInfo::RGBAFormat(16, 16, 16, 16, 0, GL_RGBA_INTEGER, GL_SHORT, GL_INT, false, AlwaysSupported, NeverSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_RGBA16UI, InternalFormatInfo::RGBAFormat(16, 16, 16, 16, 0, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, AlwaysSupported, NeverSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_RGBA32I, InternalFormatInfo::RGBAFormat(32, 32, 32, 32, 0, GL_RGBA_INTEGER, GL_INT, GL_INT, false, AlwaysSupported, NeverSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_RGBA32UI, InternalFormatInfo::RGBAFormat(32, 32, 32, 32, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, AlwaysSupported, NeverSupported, AlwaysSupported ))); - - map.insert(InternalFormatInfoPair(GL_BGRA8_EXT, InternalFormatInfo::RGBAFormat( 8, 8, 8, 8, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, AlwaysSupported, AlwaysSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_BGRA4_ANGLEX, InternalFormatInfo::RGBAFormat( 4, 4, 4, 4, 0, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, GL_UNSIGNED_NORMALIZED, false, AlwaysSupported, AlwaysSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_BGR5_A1_ANGLEX, InternalFormatInfo::RGBAFormat( 5, 5, 5, 1, 0, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, GL_UNSIGNED_NORMALIZED, false, AlwaysSupported, AlwaysSupported, AlwaysSupported ))); - - // Floating point renderability and filtering is provided by OES_texture_float and OES_texture_half_float - // | Internal format | | D |S | Format | Type | Comp | SRGB | Color renderable | Texture filterable | Supported | - // | | | | | | | type | | | | | - map.insert(InternalFormatInfoPair(GL_R16F, InternalFormatInfo::RGBAFormat(16, 0, 0, 0, 0, GL_RED, GL_HALF_FLOAT, GL_FLOAT, false, CheckSupport<&Context::supportsFloat16RenderableTextures, &rx::Renderer::getFloat16TextureRenderingSupport>, CheckSupport<&Context::supportsFloat16LinearFilter, &rx::Renderer::getFloat16TextureFilteringSupport>, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_RG16F, InternalFormatInfo::RGBAFormat(16, 16, 0, 0, 0, GL_RG, GL_HALF_FLOAT, GL_FLOAT, false, CheckSupport<&Context::supportsFloat16RenderableTextures, &rx::Renderer::getFloat16TextureRenderingSupport>, CheckSupport<&Context::supportsFloat16LinearFilter, &rx::Renderer::getFloat16TextureFilteringSupport>, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_RGB16F, InternalFormatInfo::RGBAFormat(16, 16, 16, 0, 0, GL_RGB, GL_HALF_FLOAT, GL_FLOAT, false, CheckSupport<&Context::supportsFloat16RenderableTextures, &rx::Renderer::getFloat16TextureRenderingSupport>, CheckSupport<&Context::supportsFloat16LinearFilter, &rx::Renderer::getFloat16TextureFilteringSupport>, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_RGBA16F, InternalFormatInfo::RGBAFormat(16, 16, 16, 16, 0, GL_RGBA, GL_HALF_FLOAT, GL_FLOAT, false, CheckSupport<&Context::supportsFloat16RenderableTextures, &rx::Renderer::getFloat16TextureRenderingSupport>, CheckSupport<&Context::supportsFloat16LinearFilter, &rx::Renderer::getFloat16TextureFilteringSupport>, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_R32F, InternalFormatInfo::RGBAFormat(32, 0, 0, 0, 0, GL_RED, GL_FLOAT, GL_FLOAT, false, CheckSupport<&Context::supportsFloat32RenderableTextures, &rx::Renderer::getFloat32TextureRenderingSupport>, CheckSupport<&Context::supportsFloat32LinearFilter, &rx::Renderer::getFloat32TextureFilteringSupport>, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_RG32F, InternalFormatInfo::RGBAFormat(32, 32, 0, 0, 0, GL_RG, GL_FLOAT, GL_FLOAT, false, CheckSupport<&Context::supportsFloat32RenderableTextures, &rx::Renderer::getFloat32TextureRenderingSupport>, CheckSupport<&Context::supportsFloat32LinearFilter, &rx::Renderer::getFloat32TextureFilteringSupport>, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_RGB32F, InternalFormatInfo::RGBAFormat(32, 32, 32, 0, 0, GL_RGB, GL_FLOAT, GL_FLOAT, false, CheckSupport<&Context::supportsFloat32RenderableTextures, &rx::Renderer::getFloat32TextureRenderingSupport>, CheckSupport<&Context::supportsFloat32LinearFilter, &rx::Renderer::getFloat32TextureFilteringSupport>, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_RGBA32F, InternalFormatInfo::RGBAFormat(32, 32, 32, 32, 0, GL_RGBA, GL_FLOAT, GL_FLOAT, false, CheckSupport<&Context::supportsFloat32RenderableTextures, &rx::Renderer::getFloat32TextureRenderingSupport>, CheckSupport<&Context::supportsFloat32LinearFilter, &rx::Renderer::getFloat32TextureFilteringSupport>, AlwaysSupported ))); - - // Depth stencil formats - // | Internal format | | D |S | X | Format | Type | Component type | Depth | Stencil | Supported | - // | | | | | | | | | renderable | renderable | | - map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT16, InternalFormatInfo::DepthStencilFormat(16, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_UNSIGNED_NORMALIZED, AlwaysSupported, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT24, InternalFormatInfo::DepthStencilFormat(24, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_UNSIGNED_NORMALIZED, AlwaysSupported, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT32F, InternalFormatInfo::DepthStencilFormat(32, 0, 0, GL_DEPTH_COMPONENT, GL_FLOAT, GL_FLOAT, AlwaysSupported, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT32_OES, InternalFormatInfo::DepthStencilFormat(32, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_UNSIGNED_NORMALIZED, AlwaysSupported, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_DEPTH24_STENCIL8, InternalFormatInfo::DepthStencilFormat(24, 8, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_UNSIGNED_NORMALIZED, AlwaysSupported, AlwaysSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_DEPTH32F_STENCIL8, InternalFormatInfo::DepthStencilFormat(32, 8, 24, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_FLOAT, AlwaysSupported, AlwaysSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_STENCIL_INDEX8, InternalFormatInfo::DepthStencilFormat( 0, 8, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, NeverSupported, AlwaysSupported, AlwaysSupported))); - - // Luminance alpha formats - // | Internal format | | L | A | Format | Type | Component type | Supported | - map.insert(InternalFormatInfoPair(GL_ALPHA8_EXT, InternalFormatInfo::LUMAFormat( 0, 8, GL_ALPHA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_LUMINANCE8_EXT, InternalFormatInfo::LUMAFormat( 8, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_ALPHA32F_EXT, InternalFormatInfo::LUMAFormat( 0, 32, GL_ALPHA, GL_FLOAT, GL_FLOAT, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_LUMINANCE32F_EXT, InternalFormatInfo::LUMAFormat(32, 0, GL_LUMINANCE, GL_FLOAT, GL_FLOAT, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_ALPHA16F_EXT, InternalFormatInfo::LUMAFormat( 0, 16, GL_ALPHA, GL_HALF_FLOAT, GL_FLOAT, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_LUMINANCE16F_EXT, InternalFormatInfo::LUMAFormat(16, 0, GL_LUMINANCE, GL_HALF_FLOAT, GL_FLOAT, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_LUMINANCE8_ALPHA8_EXT, InternalFormatInfo::LUMAFormat( 8, 8, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_LUMINANCE_ALPHA32F_EXT, InternalFormatInfo::LUMAFormat(32, 32, GL_LUMINANCE_ALPHA, GL_FLOAT, GL_FLOAT, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_LUMINANCE_ALPHA16F_EXT, InternalFormatInfo::LUMAFormat(16, 16, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT, GL_FLOAT, AlwaysSupported))); - - // Unsized formats - // | Internal format | | Format | Supported | - map.insert(InternalFormatInfoPair(GL_ALPHA, InternalFormatInfo::UnsizedFormat(GL_ALPHA, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_LUMINANCE, InternalFormatInfo::UnsizedFormat(GL_LUMINANCE, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_LUMINANCE_ALPHA, InternalFormatInfo::UnsizedFormat(GL_LUMINANCE_ALPHA, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RED, InternalFormatInfo::UnsizedFormat(GL_RED, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RG, InternalFormatInfo::UnsizedFormat(GL_RG, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RGB, InternalFormatInfo::UnsizedFormat(GL_RGB, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RGBA, InternalFormatInfo::UnsizedFormat(GL_RGBA, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RED_INTEGER, InternalFormatInfo::UnsizedFormat(GL_RED_INTEGER, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RG_INTEGER, InternalFormatInfo::UnsizedFormat(GL_RG_INTEGER, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RGB_INTEGER, InternalFormatInfo::UnsizedFormat(GL_RGB_INTEGER, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RGBA_INTEGER, InternalFormatInfo::UnsizedFormat(GL_RGBA_INTEGER, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_BGRA_EXT, InternalFormatInfo::UnsizedFormat(GL_BGRA_EXT, AlwaysSupported))); - - // Compressed formats, From ES 3.0.1 spec, table 3.16 - // | Internal format | |W |H | BS |CC| Format | Type | SRGB | Supported | - map.insert(InternalFormatInfoPair(GL_COMPRESSED_R11_EAC, InternalFormatInfo::CompressedFormat(4, 4, 64, 1, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE, false, UnimplementedSupport))); - map.insert(InternalFormatInfoPair(GL_COMPRESSED_SIGNED_R11_EAC, InternalFormatInfo::CompressedFormat(4, 4, 64, 1, GL_COMPRESSED_SIGNED_R11_EAC, GL_UNSIGNED_BYTE, false, UnimplementedSupport))); - map.insert(InternalFormatInfoPair(GL_COMPRESSED_RG11_EAC, InternalFormatInfo::CompressedFormat(4, 4, 128, 2, GL_COMPRESSED_RG11_EAC, GL_UNSIGNED_BYTE, false, UnimplementedSupport))); - map.insert(InternalFormatInfoPair(GL_COMPRESSED_SIGNED_RG11_EAC, InternalFormatInfo::CompressedFormat(4, 4, 128, 2, GL_COMPRESSED_SIGNED_RG11_EAC, GL_UNSIGNED_BYTE, false, UnimplementedSupport))); - map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGB8_ETC2, InternalFormatInfo::CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_RGB8_ETC2, GL_UNSIGNED_BYTE, false, UnimplementedSupport))); - map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ETC2, InternalFormatInfo::CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_SRGB8_ETC2, GL_UNSIGNED_BYTE, true, UnimplementedSupport))); - map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, InternalFormatInfo::CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, false, UnimplementedSupport))); - map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, InternalFormatInfo::CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, true, UnimplementedSupport))); - map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA8_ETC2_EAC, InternalFormatInfo::CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_UNSIGNED_BYTE, false, UnimplementedSupport))); - map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, InternalFormatInfo::CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_UNSIGNED_BYTE, true, UnimplementedSupport))); - - // From GL_EXT_texture_compression_dxt1 - // | Internal format | |W |H | BS |CC| Format | Type | SRGB | Supported | - map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGB_S3TC_DXT1_EXT, InternalFormatInfo::CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, false, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, InternalFormatInfo::CompressedFormat(4, 4, 64, 4, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, false, AlwaysSupported))); - - // From GL_ANGLE_texture_compression_dxt3 - map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, InternalFormatInfo::CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, false, AlwaysSupported))); - - // From GL_ANGLE_texture_compression_dxt5 - map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, InternalFormatInfo::CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, false, AlwaysSupported))); - - return map; -} - -static InternalFormatInfoMap BuildES2InternalFormatInfoMap() -{ - InternalFormatInfoMap map; - - // From ES 2.0.25 table 4.5 - map.insert(InternalFormatInfoPair(GL_NONE, InternalFormatInfo())); - - // | Internal format | | R | G | B | A |S | Format | Type | Component type | SRGB | Color | Texture | Supported | - // | | | | | | | | | | | | renderable | filterable | | - map.insert(InternalFormatInfoPair(GL_RGBA4, InternalFormatInfo::RGBAFormat( 4, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_NORMALIZED, false, AlwaysSupported, AlwaysSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RGB5_A1, InternalFormatInfo::RGBAFormat( 5, 5, 5, 1, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_NORMALIZED, false, AlwaysSupported, AlwaysSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RGB565, InternalFormatInfo::RGBAFormat( 5, 6, 5, 0, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_NORMALIZED, false, AlwaysSupported, AlwaysSupported, AlwaysSupported))); - - // Extension formats - map.insert(InternalFormatInfoPair(GL_R8_EXT, InternalFormatInfo::RGBAFormat( 8, 0, 0, 0, 0, GL_RED_EXT, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, CheckSupport<&Context::supportsRGTextures, &rx::Renderer::getRGTextureSupport>, CheckSupport<&Context::supportsRGTextures, &rx::Renderer::getRGTextureSupport>, CheckSupport<&Context::supportsRGTextures>))); - map.insert(InternalFormatInfoPair(GL_RG8_EXT, InternalFormatInfo::RGBAFormat( 8, 8, 0, 0, 0, GL_RG_EXT, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, CheckSupport<&Context::supportsRGTextures, &rx::Renderer::getRGTextureSupport>, CheckSupport<&Context::supportsRGTextures, &rx::Renderer::getRGTextureSupport>, CheckSupport<&Context::supportsRGTextures>))); - map.insert(InternalFormatInfoPair(GL_RGB8_OES, InternalFormatInfo::RGBAFormat( 8, 8, 8, 0, 0, GL_RGB, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, AlwaysSupported, AlwaysSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RGBA8_OES, InternalFormatInfo::RGBAFormat( 8, 8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, AlwaysSupported, AlwaysSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_BGRA8_EXT, InternalFormatInfo::RGBAFormat( 8, 8, 8, 8, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, AlwaysSupported, AlwaysSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_BGRA4_ANGLEX, InternalFormatInfo::RGBAFormat( 4, 4, 4, 4, 0, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_NORMALIZED, false, NeverSupported, AlwaysSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_BGR5_A1_ANGLEX, InternalFormatInfo::RGBAFormat( 5, 5, 5, 1, 0, GL_BGRA_EXT, GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_NORMALIZED, false, NeverSupported, AlwaysSupported, AlwaysSupported))); - - // Floating point formats have to query the renderer for support - // | Internal format | | R | G | B | A |S | Format | Type | Comp | SRGB | Color renderable | Texture filterable | Supported | - // | | | | | | | | | | type | | | | | - map.insert(InternalFormatInfoPair(GL_R16F_EXT, InternalFormatInfo::RGBAFormat(16, 0, 0, 0, 0, GL_RED, GL_HALF_FLOAT_OES, GL_FLOAT, false, CheckSupport<&Context::supportsRGTextures, &rx::Renderer::getRGTextureSupport>, CheckSupport<&Context::supportsRGTextures, &rx::Renderer::getRGTextureSupport>, CheckSupport<&Context::supportsRGTextures> ))); - map.insert(InternalFormatInfoPair(GL_R32F_EXT, InternalFormatInfo::RGBAFormat(32, 0, 0, 0, 0, GL_RED, GL_FLOAT, GL_FLOAT, false, CheckSupport<&Context::supportsRGTextures, &rx::Renderer::getRGTextureSupport>, CheckSupport<&Context::supportsRGTextures, &rx::Renderer::getRGTextureSupport>, CheckSupport<&Context::supportsRGTextures> ))); - map.insert(InternalFormatInfoPair(GL_RG16F_EXT, InternalFormatInfo::RGBAFormat(16, 16, 0, 0, 0, GL_RG, GL_HALF_FLOAT_OES, GL_FLOAT, false, CheckSupport<&Context::supportsRGTextures, &rx::Renderer::getRGTextureSupport>, CheckSupport<&Context::supportsRGTextures, &rx::Renderer::getRGTextureSupport>, CheckSupport<&Context::supportsRGTextures> ))); - map.insert(InternalFormatInfoPair(GL_RG32F_EXT, InternalFormatInfo::RGBAFormat(32, 32, 0, 0, 0, GL_RG, GL_FLOAT, GL_FLOAT, false, CheckSupport<&Context::supportsRGTextures, &rx::Renderer::getRGTextureSupport>, CheckSupport<&Context::supportsRGTextures, &rx::Renderer::getRGTextureSupport>, CheckSupport<&Context::supportsRGTextures> ))); - map.insert(InternalFormatInfoPair(GL_RGB16F_EXT, InternalFormatInfo::RGBAFormat(16, 16, 16, 0, 0, GL_RGB, GL_HALF_FLOAT_OES, GL_FLOAT, false, CheckSupport<&Context::supportsFloat16RenderableTextures, &rx::Renderer::getFloat16TextureRenderingSupport>, CheckSupport<&Context::supportsFloat16LinearFilter, &rx::Renderer::getFloat16TextureFilteringSupport>, CheckSupport<&Context::supportsFloat16Textures>))); - map.insert(InternalFormatInfoPair(GL_RGB32F_EXT, InternalFormatInfo::RGBAFormat(32, 32, 32, 0, 0, GL_RGB, GL_FLOAT, GL_FLOAT, false, CheckSupport<&Context::supportsFloat32RenderableTextures, &rx::Renderer::getFloat32TextureRenderingSupport>, CheckSupport<&Context::supportsFloat32LinearFilter, &rx::Renderer::getFloat32TextureFilteringSupport>, CheckSupport<&Context::supportsFloat32Textures>))); - map.insert(InternalFormatInfoPair(GL_RGBA16F_EXT, InternalFormatInfo::RGBAFormat(16, 16, 16, 16, 0, GL_RGBA, GL_HALF_FLOAT_OES, GL_FLOAT, false, CheckSupport<&Context::supportsFloat16RenderableTextures, &rx::Renderer::getFloat16TextureRenderingSupport>, CheckSupport<&Context::supportsFloat16LinearFilter, &rx::Renderer::getFloat16TextureFilteringSupport>, CheckSupport<&Context::supportsFloat16Textures>))); - map.insert(InternalFormatInfoPair(GL_RGBA32F_EXT, InternalFormatInfo::RGBAFormat(32, 32, 32, 32, 0, GL_RGBA, GL_FLOAT, GL_FLOAT, false, CheckSupport<&Context::supportsFloat32RenderableTextures, &rx::Renderer::getFloat32TextureRenderingSupport>, CheckSupport<&Context::supportsFloat32LinearFilter, &rx::Renderer::getFloat32TextureFilteringSupport>, CheckSupport<&Context::supportsFloat32Textures>))); - - // Depth and stencil formats - // | Internal format | | D |S |X | Format | Type | Internal format | Depth | Stencil | Supported | - // | | | | | | | | type | renderable | renderable | | - map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT32_OES,InternalFormatInfo::DepthStencilFormat(32, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_UNSIGNED_NORMALIZED, AlwaysSupported, NeverSupported, CheckSupport<&Context::supportsDepthTextures>))); - map.insert(InternalFormatInfoPair(GL_DEPTH24_STENCIL8_OES, InternalFormatInfo::DepthStencilFormat(24, 8, 0, GL_DEPTH_STENCIL_OES, GL_UNSIGNED_INT_24_8_OES, GL_UNSIGNED_NORMALIZED, AlwaysSupported, AlwaysSupported, CheckSupport<&Context::supportsDepthTextures>))); - map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT16, InternalFormatInfo::DepthStencilFormat(16, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_UNSIGNED_NORMALIZED, AlwaysSupported, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_STENCIL_INDEX8, InternalFormatInfo::DepthStencilFormat( 0, 8, 0, GL_DEPTH_STENCIL_OES, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, NeverSupported, AlwaysSupported, AlwaysSupported))); - - // Unsized formats - // | Internal format | | Format | Supported | - map.insert(InternalFormatInfoPair(GL_ALPHA, InternalFormatInfo::UnsizedFormat(GL_ALPHA, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_LUMINANCE, InternalFormatInfo::UnsizedFormat(GL_LUMINANCE, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_LUMINANCE_ALPHA, InternalFormatInfo::UnsizedFormat(GL_LUMINANCE_ALPHA, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RED_EXT, InternalFormatInfo::UnsizedFormat(GL_RED_EXT, CheckSupport<&Context::supportsRGTextures>))); - map.insert(InternalFormatInfoPair(GL_RG_EXT, InternalFormatInfo::UnsizedFormat(GL_RG_EXT, CheckSupport<&Context::supportsRGTextures>))); - map.insert(InternalFormatInfoPair(GL_RGB, InternalFormatInfo::UnsizedFormat(GL_RGB, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RGBA, InternalFormatInfo::UnsizedFormat(GL_RGBA, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_BGRA_EXT, InternalFormatInfo::UnsizedFormat(GL_BGRA_EXT, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT, InternalFormatInfo::UnsizedFormat(GL_DEPTH_COMPONENT, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_DEPTH_STENCIL_OES, InternalFormatInfo::UnsizedFormat(GL_DEPTH_STENCIL_OES, AlwaysSupported))); - - // Luminance alpha formats from GL_EXT_texture_storage - // | Internal format | | L | A | Format | Type | Component type | Supported | - map.insert(InternalFormatInfoPair(GL_ALPHA8_EXT, InternalFormatInfo::LUMAFormat( 0, 8, GL_ALPHA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_LUMINANCE8_EXT, InternalFormatInfo::LUMAFormat( 8, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_ALPHA32F_EXT, InternalFormatInfo::LUMAFormat( 0, 32, GL_ALPHA, GL_FLOAT, GL_FLOAT, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_LUMINANCE32F_EXT, InternalFormatInfo::LUMAFormat(32, 0, GL_LUMINANCE, GL_FLOAT, GL_FLOAT, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_ALPHA16F_EXT, InternalFormatInfo::LUMAFormat( 0, 16, GL_ALPHA, GL_HALF_FLOAT_OES, GL_FLOAT, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_LUMINANCE16F_EXT, InternalFormatInfo::LUMAFormat(16, 0, GL_LUMINANCE, GL_HALF_FLOAT_OES, GL_FLOAT, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_LUMINANCE8_ALPHA8_EXT, InternalFormatInfo::LUMAFormat( 8, 8, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_LUMINANCE_ALPHA32F_EXT, InternalFormatInfo::LUMAFormat(32, 32, GL_LUMINANCE_ALPHA, GL_FLOAT, GL_FLOAT, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_LUMINANCE_ALPHA16F_EXT, InternalFormatInfo::LUMAFormat(16, 16, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, GL_FLOAT, AlwaysSupported))); - - // From GL_EXT_texture_compression_dxt1 - // | Internal format | |W |H | BS |CC|Format | Type | SRGB | Supported | - map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGB_S3TC_DXT1_EXT, InternalFormatInfo::CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, false, CheckSupport<&Context::supportsDXT1Textures>))); - map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, InternalFormatInfo::CompressedFormat(4, 4, 64, 4, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, false, CheckSupport<&Context::supportsDXT1Textures>))); - - // From GL_ANGLE_texture_compression_dxt3 - map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, InternalFormatInfo::CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, false, CheckSupport<&Context::supportsDXT3Textures>))); - - // From GL_ANGLE_texture_compression_dxt5 - map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, InternalFormatInfo::CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, false, CheckSupport<&Context::supportsDXT5Textures>))); - - return map; -} - -static bool GetInternalFormatInfo(GLenum internalFormat, GLuint clientVersion, InternalFormatInfo *outFormatInfo) -{ - const InternalFormatInfoMap* map = NULL; - - if (clientVersion == 2) - { - static const InternalFormatInfoMap formatMap = BuildES2InternalFormatInfoMap(); - map = &formatMap; - } - else if (clientVersion == 3) - { - static const InternalFormatInfoMap formatMap = BuildES3InternalFormatInfoMap(); - map = &formatMap; - } - else - { - UNREACHABLE(); - } - - InternalFormatInfoMap::const_iterator iter = map->find(internalFormat); - if (iter != map->end()) - { - if (outFormatInfo) - { - *outFormatInfo = iter->second; - } - return true; - } - else - { - return false; - } -} - -typedef std::set FormatSet; - -static FormatSet BuildES2ValidFormatSet() -{ - static const FormatMap &formatMap = GetFormatMap(2); - - FormatSet set; - - for (FormatMap::const_iterator i = formatMap.begin(); i != formatMap.end(); i++) - { - const FormatTypePair& formatPair = i->first; - set.insert(formatPair.first); - } - - return set; -} - -static FormatSet BuildES3ValidFormatSet() -{ - static const ES3FormatSet &formatSet = GetES3FormatSet(); - - FormatSet set; - - for (ES3FormatSet::const_iterator i = formatSet.begin(); i != formatSet.end(); i++) - { - const FormatInfo& formatInfo = *i; - set.insert(formatInfo.mFormat); - } - - return set; -} - -typedef std::set TypeSet; - -static TypeSet BuildES2ValidTypeSet() -{ - static const FormatMap &formatMap = GetFormatMap(2); - - TypeSet set; - - for (FormatMap::const_iterator i = formatMap.begin(); i != formatMap.end(); i++) - { - const FormatTypePair& formatPair = i->first; - set.insert(formatPair.second); - } - - return set; -} - -static TypeSet BuildES3ValidTypeSet() -{ - static const ES3FormatSet &formatSet = GetES3FormatSet(); - - TypeSet set; - - for (ES3FormatSet::const_iterator i = formatSet.begin(); i != formatSet.end(); i++) - { - const FormatInfo& formatInfo = *i; - set.insert(formatInfo.mType); - } - - return set; -} - -struct EffectiveInternalFormatInfo -{ - GLenum mEffectiveFormat; - GLenum mDestFormat; - GLuint mMinRedBits; - GLuint mMaxRedBits; - GLuint mMinGreenBits; - GLuint mMaxGreenBits; - GLuint mMinBlueBits; - GLuint mMaxBlueBits; - GLuint mMinAlphaBits; - GLuint mMaxAlphaBits; - - EffectiveInternalFormatInfo(GLenum effectiveFormat, GLenum destFormat, GLuint minRedBits, GLuint maxRedBits, - GLuint minGreenBits, GLuint maxGreenBits, GLuint minBlueBits, GLuint maxBlueBits, - GLuint minAlphaBits, GLuint maxAlphaBits) - : mEffectiveFormat(effectiveFormat), mDestFormat(destFormat), mMinRedBits(minRedBits), - mMaxRedBits(maxRedBits), mMinGreenBits(minGreenBits), mMaxGreenBits(maxGreenBits), - mMinBlueBits(minBlueBits), mMaxBlueBits(maxBlueBits), mMinAlphaBits(minAlphaBits), - mMaxAlphaBits(maxAlphaBits) {}; -}; - -typedef std::vector EffectiveInternalFormatList; - -static EffectiveInternalFormatList BuildSizedEffectiveInternalFormatList() -{ - EffectiveInternalFormatList list; - - // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and - // linear source buffer component sizes. - // | Source channel min/max sizes | - // Effective Internal Format | N/A | R | G | B | A | - list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8)); - list.push_back(EffectiveInternalFormatInfo(GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0)); - list.push_back(EffectiveInternalFormatInfo(GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0)); - list.push_back(EffectiveInternalFormatInfo(GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0)); - list.push_back(EffectiveInternalFormatInfo(GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0)); - list.push_back(EffectiveInternalFormatInfo(GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4)); - list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1)); - list.push_back(EffectiveInternalFormatInfo(GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8)); - list.push_back(EffectiveInternalFormatInfo(GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2)); - - return list; -} - - -static EffectiveInternalFormatList BuildUnsizedEffectiveInternalFormatList() -{ - EffectiveInternalFormatList list; - - // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and - // linear source buffer component sizes. - // | Source channel min/max sizes | - // Effective Internal Format | Dest Format | R | G | B | A | - list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT, GL_ALPHA, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX, 1, 8)); - list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX)); - list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, UINT_MAX, 0, UINT_MAX, 1, 8)); - list.push_back(EffectiveInternalFormatInfo(GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, UINT_MAX)); - list.push_back(EffectiveInternalFormatInfo(GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, UINT_MAX)); - list.push_back(EffectiveInternalFormatInfo(GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4)); - list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1)); - list.push_back(EffectiveInternalFormatInfo(GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8)); - - return list; -} - -static bool GetEffectiveInternalFormat(const InternalFormatInfo &srcFormat, const InternalFormatInfo &destFormat, - GLuint clientVersion, GLenum *outEffectiveFormat) -{ - const EffectiveInternalFormatList *list = NULL; - GLenum targetFormat = GL_NONE; - - if (gl::IsSizedInternalFormat(destFormat.mFormat, clientVersion)) - { - static const EffectiveInternalFormatList sizedList = BuildSizedEffectiveInternalFormatList(); - list = &sizedList; - } - else - { - static const EffectiveInternalFormatList unsizedList = BuildUnsizedEffectiveInternalFormatList(); - list = &unsizedList; - targetFormat = destFormat.mFormat; - } - - for (size_t curFormat = 0; curFormat < list->size(); ++curFormat) - { - const EffectiveInternalFormatInfo& formatInfo = list->at(curFormat); - if ((formatInfo.mDestFormat == targetFormat) && - (formatInfo.mMinRedBits <= srcFormat.mRedBits && formatInfo.mMaxRedBits >= srcFormat.mRedBits) && - (formatInfo.mMinGreenBits <= srcFormat.mGreenBits && formatInfo.mMaxGreenBits >= srcFormat.mGreenBits) && - (formatInfo.mMinBlueBits <= srcFormat.mBlueBits && formatInfo.mMaxBlueBits >= srcFormat.mBlueBits) && - (formatInfo.mMinAlphaBits <= srcFormat.mAlphaBits && formatInfo.mMaxAlphaBits >= srcFormat.mAlphaBits)) - { - *outEffectiveFormat = formatInfo.mEffectiveFormat; - return true; - } - } - - return false; -} - -struct CopyConversion -{ - GLenum mTextureFormat; - GLenum mFramebufferFormat; - - CopyConversion(GLenum textureFormat, GLenum framebufferFormat) - : mTextureFormat(textureFormat), mFramebufferFormat(framebufferFormat) { } - - bool operator<(const CopyConversion& other) const - { - return memcmp(this, &other, sizeof(CopyConversion)) < 0; - } -}; - -typedef std::set CopyConversionSet; - -static CopyConversionSet BuildValidES3CopyTexImageCombinations() -{ - CopyConversionSet set; - - // From ES 3.0.1 spec, table 3.15 - set.insert(CopyConversion(GL_ALPHA, GL_RGBA)); - set.insert(CopyConversion(GL_LUMINANCE, GL_RED)); - set.insert(CopyConversion(GL_LUMINANCE, GL_RG)); - set.insert(CopyConversion(GL_LUMINANCE, GL_RGB)); - set.insert(CopyConversion(GL_LUMINANCE, GL_RGBA)); - set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_RGBA)); - set.insert(CopyConversion(GL_RED, GL_RED)); - set.insert(CopyConversion(GL_RED, GL_RG)); - set.insert(CopyConversion(GL_RED, GL_RGB)); - set.insert(CopyConversion(GL_RED, GL_RGBA)); - set.insert(CopyConversion(GL_RG, GL_RG)); - set.insert(CopyConversion(GL_RG, GL_RGB)); - set.insert(CopyConversion(GL_RG, GL_RGBA)); - set.insert(CopyConversion(GL_RGB, GL_RGB)); - set.insert(CopyConversion(GL_RGB, GL_RGBA)); - set.insert(CopyConversion(GL_RGBA, GL_RGBA)); - - // Necessary for ANGLE back-buffers - set.insert(CopyConversion(GL_ALPHA, GL_BGRA_EXT)); - set.insert(CopyConversion(GL_LUMINANCE, GL_BGRA_EXT)); - set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_BGRA_EXT)); - set.insert(CopyConversion(GL_RED, GL_BGRA_EXT)); - set.insert(CopyConversion(GL_RG, GL_BGRA_EXT)); - set.insert(CopyConversion(GL_RGB, GL_BGRA_EXT)); - set.insert(CopyConversion(GL_RGBA, GL_BGRA_EXT)); - - set.insert(CopyConversion(GL_RED_INTEGER, GL_RED_INTEGER)); - set.insert(CopyConversion(GL_RED_INTEGER, GL_RG_INTEGER)); - set.insert(CopyConversion(GL_RED_INTEGER, GL_RGB_INTEGER)); - set.insert(CopyConversion(GL_RED_INTEGER, GL_RGBA_INTEGER)); - set.insert(CopyConversion(GL_RG_INTEGER, GL_RG_INTEGER)); - set.insert(CopyConversion(GL_RG_INTEGER, GL_RGB_INTEGER)); - set.insert(CopyConversion(GL_RG_INTEGER, GL_RGBA_INTEGER)); - set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGB_INTEGER)); - set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGBA_INTEGER)); - set.insert(CopyConversion(GL_RGBA_INTEGER, GL_RGBA_INTEGER)); - - return set; -} - -bool IsValidInternalFormat(GLenum internalFormat, const Context *context) -{ - if (!context) - { - return false; - } - - InternalFormatInfo internalFormatInfo; - if (GetInternalFormatInfo(internalFormat, context->getClientVersion(), &internalFormatInfo)) - { - ASSERT(internalFormatInfo.mSupportFunction != NULL); - return internalFormatInfo.mSupportFunction(context); - } - else - { - return false; - } -} - -bool IsValidFormat(GLenum format, GLuint clientVersion) -{ - if (clientVersion == 2) - { - static const FormatSet formatSet = BuildES2ValidFormatSet(); - return formatSet.find(format) != formatSet.end(); - } - else if (clientVersion == 3) - { - static const FormatSet formatSet = BuildES3ValidFormatSet(); - return formatSet.find(format) != formatSet.end(); - } - else - { - UNREACHABLE(); - return false; - } -} - -bool IsValidType(GLenum type, GLuint clientVersion) -{ - if (clientVersion == 2) - { - static const TypeSet typeSet = BuildES2ValidTypeSet(); - return typeSet.find(type) != typeSet.end(); - } - else if (clientVersion == 3) - { - static const TypeSet typeSet = BuildES3ValidTypeSet(); - return typeSet.find(type) != typeSet.end(); - } - else - { - UNREACHABLE(); - return false; - } -} - -bool IsValidFormatCombination(GLenum internalFormat, GLenum format, GLenum type, GLuint clientVersion) -{ - if (clientVersion == 2) - { - static const FormatMap &formats = GetFormatMap(clientVersion); - FormatMap::const_iterator iter = formats.find(FormatTypePair(format, type)); - - return (iter != formats.end()) && ((internalFormat == (GLint)type) || (internalFormat == iter->second.mInternalFormat)); - } - else if (clientVersion == 3) - { - static const ES3FormatSet &formats = GetES3FormatSet(); - return formats.find(FormatInfo(internalFormat, format, type)) != formats.end(); - } - else - { - UNREACHABLE(); - return false; - } -} - -bool IsValidCopyTexImageCombination(GLenum textureInternalFormat, GLenum frameBufferInternalFormat, GLuint readBufferHandle, GLuint clientVersion) -{ - InternalFormatInfo textureInternalFormatInfo; - InternalFormatInfo framebufferInternalFormatInfo; - if (GetInternalFormatInfo(textureInternalFormat, clientVersion, &textureInternalFormatInfo) && - GetInternalFormatInfo(frameBufferInternalFormat, clientVersion, &framebufferInternalFormatInfo)) - { - if (clientVersion == 2) - { - UNIMPLEMENTED(); - return false; - } - else if (clientVersion == 3) - { - static const CopyConversionSet conversionSet = BuildValidES3CopyTexImageCombinations(); - const CopyConversion conversion = CopyConversion(textureInternalFormatInfo.mFormat, - framebufferInternalFormatInfo.mFormat); - if (conversionSet.find(conversion) != conversionSet.end()) - { - // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats - // must both be signed, unsigned, or fixed point and both source and destinations - // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed - // conversion between fixed and floating point. - - if ((textureInternalFormatInfo.mColorEncoding == GL_SRGB) != (framebufferInternalFormatInfo.mColorEncoding == GL_SRGB)) - { - return false; - } - - if (((textureInternalFormatInfo.mComponentType == GL_INT) != (framebufferInternalFormatInfo.mComponentType == GL_INT)) || - ((textureInternalFormatInfo.mComponentType == GL_UNSIGNED_INT) != (framebufferInternalFormatInfo.mComponentType == GL_UNSIGNED_INT))) - { - return false; - } - - if (gl::IsFloatOrFixedComponentType(textureInternalFormatInfo.mComponentType) && - !gl::IsFloatOrFixedComponentType(framebufferInternalFormatInfo.mComponentType)) - { - return false; - } - - // GLES specification 3.0.3, sec 3.8.5, pg 139-140: - // The effective internal format of the source buffer is determined with the following rules applied in order: - // * If the source buffer is a texture or renderbuffer that was created with a sized internal format then the - // effective internal format is the source buffer's sized internal format. - // * If the source buffer is a texture that was created with an unsized base internal format, then the - // effective internal format is the source image array's effective internal format, as specified by table - // 3.12, which is determined from the and that were used when the source image array was - // specified by TexImage*. - // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18 where - // Destination Internal Format matches internalformat and where the [source channel sizes] are consistent - // with the values of the source buffer's [channel sizes]. Table 3.17 is used if the - // FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the FRAMEBUFFER_ATTACHMENT_ENCODING - // is SRGB. - InternalFormatInfo sourceEffectiveFormat; - if (readBufferHandle != 0) - { - // Not the default framebuffer, therefore the read buffer must be a user-created texture or renderbuffer - if (gl::IsSizedInternalFormat(framebufferInternalFormatInfo.mFormat, clientVersion)) - { - sourceEffectiveFormat = framebufferInternalFormatInfo; - } - else - { - // Renderbuffers cannot be created with an unsized internal format, so this must be an unsized-format - // texture. We can use the same table we use when creating textures to get its effective sized format. - GLenum effectiveFormat = gl::GetSizedInternalFormat(framebufferInternalFormatInfo.mFormat, - framebufferInternalFormatInfo.mType, clientVersion); - gl::GetInternalFormatInfo(effectiveFormat, clientVersion, &sourceEffectiveFormat); - } - } - else - { - // The effective internal format must be derived from the source framebuffer's channel sizes. - // This is done in GetEffectiveInternalFormat for linear buffers (table 3.17) - if (framebufferInternalFormatInfo.mColorEncoding == GL_LINEAR) - { - GLenum effectiveFormat; - if (GetEffectiveInternalFormat(framebufferInternalFormatInfo, textureInternalFormatInfo, clientVersion, &effectiveFormat)) - { - gl::GetInternalFormatInfo(effectiveFormat, clientVersion, &sourceEffectiveFormat); - } - else - { - return false; - } - } - else if (framebufferInternalFormatInfo.mColorEncoding == GL_SRGB) - { - // SRGB buffers can only be copied to sized format destinations according to table 3.18 - if (gl::IsSizedInternalFormat(textureInternalFormat, clientVersion) && - (framebufferInternalFormatInfo.mRedBits >= 1 && framebufferInternalFormatInfo.mRedBits <= 8) && - (framebufferInternalFormatInfo.mGreenBits >= 1 && framebufferInternalFormatInfo.mGreenBits <= 8) && - (framebufferInternalFormatInfo.mBlueBits >= 1 && framebufferInternalFormatInfo.mBlueBits <= 8) && - (framebufferInternalFormatInfo.mAlphaBits >= 1 && framebufferInternalFormatInfo.mAlphaBits <= 8)) - { - gl::GetInternalFormatInfo(GL_SRGB8_ALPHA8, clientVersion, &sourceEffectiveFormat); - } - else - { - return false; - } - } - else - { - UNREACHABLE(); - } - } - - if (gl::IsSizedInternalFormat(textureInternalFormatInfo.mFormat, clientVersion)) - { - // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is sized, - // component sizes of the source and destination formats must exactly match - if (textureInternalFormatInfo.mRedBits != sourceEffectiveFormat.mRedBits || - textureInternalFormatInfo.mGreenBits != sourceEffectiveFormat.mGreenBits || - textureInternalFormatInfo.mBlueBits != sourceEffectiveFormat.mBlueBits || - textureInternalFormatInfo.mAlphaBits != sourceEffectiveFormat.mAlphaBits) - { - return false; - } - } - - - return true; // A conversion function exists, and no rule in the specification has precluded conversion - // between these formats. - } - - return false; - } - else - { - UNREACHABLE(); - return false; - } - } - else - { - UNREACHABLE(); - return false; - } -} - -bool IsSizedInternalFormat(GLenum internalFormat, GLuint clientVersion) -{ - InternalFormatInfo internalFormatInfo; - if (GetInternalFormatInfo(internalFormat, clientVersion, &internalFormatInfo)) - { - return internalFormatInfo.mPixelBits > 0; - } - else - { - UNREACHABLE(); - return false; - } -} - -GLenum GetSizedInternalFormat(GLenum format, GLenum type, GLuint clientVersion) -{ - const FormatMap &formats = GetFormatMap(clientVersion); - FormatMap::const_iterator iter = formats.find(FormatTypePair(format, type)); - return (iter != formats.end()) ? iter->second.mInternalFormat : GL_NONE; -} - -GLuint GetPixelBytes(GLenum internalFormat, GLuint clientVersion) -{ - InternalFormatInfo internalFormatInfo; - if (GetInternalFormatInfo(internalFormat, clientVersion, &internalFormatInfo)) - { - return internalFormatInfo.mPixelBits / 8; - } - else - { - UNREACHABLE(); - return 0; - } -} - -GLuint GetAlphaBits(GLenum internalFormat, GLuint clientVersion) -{ - InternalFormatInfo internalFormatInfo; - if (GetInternalFormatInfo(internalFormat, clientVersion, &internalFormatInfo)) - { - return internalFormatInfo.mAlphaBits; - } - else - { - UNREACHABLE(); - return 0; - } -} - -GLuint GetRedBits(GLenum internalFormat, GLuint clientVersion) -{ - InternalFormatInfo internalFormatInfo; - if (GetInternalFormatInfo(internalFormat, clientVersion, &internalFormatInfo)) - { - return internalFormatInfo.mRedBits; - } - else - { - UNREACHABLE(); - return 0; - } -} - -GLuint GetGreenBits(GLenum internalFormat, GLuint clientVersion) -{ - InternalFormatInfo internalFormatInfo; - if (GetInternalFormatInfo(internalFormat, clientVersion, &internalFormatInfo)) - { - return internalFormatInfo.mGreenBits; - } - else - { - UNREACHABLE(); - return 0; - } -} - -GLuint GetBlueBits(GLenum internalFormat, GLuint clientVersion) -{ - InternalFormatInfo internalFormatInfo; - if (GetInternalFormatInfo(internalFormat, clientVersion, &internalFormatInfo)) - { - return internalFormatInfo.mBlueBits; - } - else - { - UNREACHABLE(); - return 0; - } -} - -GLuint GetLuminanceBits(GLenum internalFormat, GLuint clientVersion) -{ - InternalFormatInfo internalFormatInfo; - if (GetInternalFormatInfo(internalFormat, clientVersion, &internalFormatInfo)) - { - return internalFormatInfo.mLuminanceBits; - } - else - { - UNREACHABLE(); - return 0; - } -} - -GLuint GetDepthBits(GLenum internalFormat, GLuint clientVersion) -{ - InternalFormatInfo internalFormatInfo; - if (GetInternalFormatInfo(internalFormat, clientVersion, &internalFormatInfo)) - { - return internalFormatInfo.mDepthBits; - } - else - { - UNREACHABLE(); - return 0; - } -} - -GLuint GetStencilBits(GLenum internalFormat, GLuint clientVersion) -{ - InternalFormatInfo internalFormatInfo; - if (GetInternalFormatInfo(internalFormat, clientVersion, &internalFormatInfo)) - { - return internalFormatInfo.mStencilBits; - } - else - { - UNREACHABLE(); - return 0; - } -} - -GLuint GetTypeBytes(GLenum type) -{ - TypeInfo typeInfo; - if (GetTypeInfo(type, &typeInfo)) - { - return typeInfo.mTypeBytes; - } - else - { - UNREACHABLE(); - return 0; - } -} - -bool IsSpecialInterpretationType(GLenum type) -{ - TypeInfo typeInfo; - if (GetTypeInfo(type, &typeInfo)) - { - return typeInfo.mSpecialInterpretation; - } - else - { - UNREACHABLE(); - return false; - } -} - -bool IsFloatOrFixedComponentType(GLenum type) -{ - if (type == GL_UNSIGNED_NORMALIZED || - type == GL_SIGNED_NORMALIZED || - type == GL_FLOAT) - { - return true; - } - else - { - return false; - } -} - -GLenum GetFormat(GLenum internalFormat, GLuint clientVersion) -{ - InternalFormatInfo internalFormatInfo; - if (GetInternalFormatInfo(internalFormat, clientVersion, &internalFormatInfo)) - { - return internalFormatInfo.mFormat; - } - else - { - UNREACHABLE(); - return GL_NONE; - } -} - -GLenum GetType(GLenum internalFormat, GLuint clientVersion) -{ - InternalFormatInfo internalFormatInfo; - if (GetInternalFormatInfo(internalFormat, clientVersion, &internalFormatInfo)) - { - return internalFormatInfo.mType; - } - else - { - UNREACHABLE(); - return GL_NONE; - } -} - -GLenum GetComponentType(GLenum internalFormat, GLuint clientVersion) -{ - InternalFormatInfo internalFormatInfo; - if (GetInternalFormatInfo(internalFormat, clientVersion, &internalFormatInfo)) - { - return internalFormatInfo.mComponentType; - } - else - { - UNREACHABLE(); - return GL_NONE; - } -} - -GLuint GetComponentCount(GLenum internalFormat, GLuint clientVersion) -{ - InternalFormatInfo internalFormatInfo; - if (GetInternalFormatInfo(internalFormat, clientVersion, &internalFormatInfo)) - { - return internalFormatInfo.mComponentCount; - } - else - { - UNREACHABLE(); - return false; - } -} - -GLenum GetColorEncoding(GLenum internalFormat, GLuint clientVersion) -{ - InternalFormatInfo internalFormatInfo; - if (GetInternalFormatInfo(internalFormat, clientVersion, &internalFormatInfo)) - { - return internalFormatInfo.mColorEncoding; - } - else - { - UNREACHABLE(); - return false; - } -} - -bool IsColorRenderingSupported(GLenum internalFormat, const rx::Renderer *renderer) -{ - InternalFormatInfo internalFormatInfo; - if (renderer && GetInternalFormatInfo(internalFormat, renderer->getCurrentClientVersion(), &internalFormatInfo)) - { - return internalFormatInfo.mIsColorRenderable(NULL, renderer); - } - else - { - UNREACHABLE(); - return false; - } -} - -bool IsColorRenderingSupported(GLenum internalFormat, const Context *context) -{ - InternalFormatInfo internalFormatInfo; - if (context && GetInternalFormatInfo(internalFormat, context->getClientVersion(), &internalFormatInfo)) - { - return internalFormatInfo.mIsColorRenderable(context, NULL); - } - else - { - UNREACHABLE(); - return false; - } -} - -bool IsTextureFilteringSupported(GLenum internalFormat, const rx::Renderer *renderer) -{ - InternalFormatInfo internalFormatInfo; - if (renderer && GetInternalFormatInfo(internalFormat, renderer->getCurrentClientVersion(), &internalFormatInfo)) - { - return internalFormatInfo.mIsTextureFilterable(NULL, renderer); - } - else - { - UNREACHABLE(); - return false; - } -} - -bool IsTextureFilteringSupported(GLenum internalFormat, const Context *context) -{ - InternalFormatInfo internalFormatInfo; - if (context && GetInternalFormatInfo(internalFormat, context->getClientVersion(), &internalFormatInfo)) - { - return internalFormatInfo.mIsTextureFilterable(context, NULL); - } - else - { - UNREACHABLE(); - return false; - } -} - -bool IsDepthRenderingSupported(GLenum internalFormat, const rx::Renderer *renderer) -{ - InternalFormatInfo internalFormatInfo; - if (renderer && GetInternalFormatInfo(internalFormat, renderer->getCurrentClientVersion(), &internalFormatInfo)) - { - return internalFormatInfo.mIsDepthRenderable(NULL, renderer); - } - else - { - UNREACHABLE(); - return false; - } -} - -bool IsDepthRenderingSupported(GLenum internalFormat, const Context *context) -{ - InternalFormatInfo internalFormatInfo; - if (context && GetInternalFormatInfo(internalFormat, context->getClientVersion(), &internalFormatInfo)) - { - return internalFormatInfo.mIsDepthRenderable(context, NULL); - } - else - { - UNREACHABLE(); - return false; - } -} - -bool IsStencilRenderingSupported(GLenum internalFormat, const rx::Renderer *renderer) -{ - InternalFormatInfo internalFormatInfo; - if (renderer && GetInternalFormatInfo(internalFormat, renderer->getCurrentClientVersion(), &internalFormatInfo)) - { - return internalFormatInfo.mIsStencilRenderable(NULL, renderer); - } - else - { - UNREACHABLE(); - return false; - } -} - -bool IsStencilRenderingSupported(GLenum internalFormat, const Context *context) -{ - InternalFormatInfo internalFormatInfo; - if (context && GetInternalFormatInfo(internalFormat, context->getClientVersion(), &internalFormatInfo)) - { - return internalFormatInfo.mIsStencilRenderable(context, NULL); - } - else - { - UNREACHABLE(); - return false; - } -} - -GLuint GetRowPitch(GLenum internalFormat, GLenum type, GLuint clientVersion, GLsizei width, GLint alignment) +GLuint InternalFormat::computeRowPitch(GLenum type, GLsizei width, GLint alignment) const { ASSERT(alignment > 0 && isPow2(alignment)); - return rx::roundUp(GetBlockSize(internalFormat, type, clientVersion, width, 1), static_cast(alignment)); + return rx::roundUp(computeBlockSize(type, width, 1), static_cast(alignment)); } -GLuint GetDepthPitch(GLenum internalFormat, GLenum type, GLuint clientVersion, GLsizei width, GLsizei height, GLint alignment) +GLuint InternalFormat::computeDepthPitch(GLenum type, GLsizei width, GLsizei height, GLint alignment) const { - return GetRowPitch(internalFormat, type, clientVersion, width, alignment) * height; + return computeRowPitch(type, width, alignment) * height; } -GLuint GetBlockSize(GLenum internalFormat, GLenum type, GLuint clientVersion, GLsizei width, GLsizei height) +GLuint InternalFormat::computeBlockSize(GLenum type, GLsizei width, GLsizei height) const { - InternalFormatInfo internalFormatInfo; - if (GetInternalFormatInfo(internalFormat, clientVersion, &internalFormatInfo)) + if (compressed) { - if (internalFormatInfo.mIsCompressed) + GLsizei numBlocksWide = (width + compressedBlockWidth - 1) / compressedBlockWidth; + GLsizei numBlocksHight = (height + compressedBlockHeight - 1) / compressedBlockHeight; + return (pixelBytes * numBlocksWide * numBlocksHight); + } + else + { + const Type &typeInfo = GetTypeInfo(type); + if (typeInfo.specialInterpretation) { - GLsizei numBlocksWide = (width + internalFormatInfo.mCompressedBlockWidth - 1) / internalFormatInfo.mCompressedBlockWidth; - GLsizei numBlocksHight = (height + internalFormatInfo.mCompressedBlockHeight - 1) / internalFormatInfo.mCompressedBlockHeight; - - return (internalFormatInfo.mPixelBits * numBlocksWide * numBlocksHight) / 8; + return typeInfo.bytes * width * height; } else { - TypeInfo typeInfo; - if (GetTypeInfo(type, &typeInfo)) - { - if (typeInfo.mSpecialInterpretation) - { - return typeInfo.mTypeBytes * width * height; - } - else - { - return internalFormatInfo.mComponentCount * typeInfo.mTypeBytes * width * height; - } - } - else - { - UNREACHABLE(); - return 0; - } + return componentCount * typeInfo.bytes * width * height; } } - else - { - UNREACHABLE(); - return 0; - } } -bool IsFormatCompressed(GLenum internalFormat, GLuint clientVersion) +GLenum GetSizedInternalFormat(GLenum internalFormat, GLenum type) { - InternalFormatInfo internalFormatInfo; - if (GetInternalFormatInfo(internalFormat, clientVersion, &internalFormatInfo)) - { - return internalFormatInfo.mIsCompressed; - } - else - { - UNREACHABLE(); - return false; - } + const InternalFormat& formatInfo = GetInternalFormatInfo(internalFormat); + return (formatInfo.pixelBytes > 0) ? internalFormat : GetFormatTypeInfo(internalFormat, type).internalFormat; } -GLuint GetCompressedBlockWidth(GLenum internalFormat, GLuint clientVersion) +const FormatSet &GetAllSizedInternalFormats() { - InternalFormatInfo internalFormatInfo; - if (GetInternalFormatInfo(internalFormat, clientVersion, &internalFormatInfo)) - { - return internalFormatInfo.mCompressedBlockWidth; - } - else - { - UNREACHABLE(); - return 0; - } -} - -GLuint GetCompressedBlockHeight(GLenum internalFormat, GLuint clientVersion) -{ - InternalFormatInfo internalFormatInfo; - if (GetInternalFormatInfo(internalFormat, clientVersion, &internalFormatInfo)) - { - return internalFormatInfo.mCompressedBlockHeight; - } - else - { - UNREACHABLE(); - return 0; - } -} - -ColorWriteFunction GetColorWriteFunction(GLenum format, GLenum type, GLuint clientVersion) -{ - static const FormatMap &formats = GetFormatMap(clientVersion); - FormatMap::const_iterator iter = formats.find(FormatTypePair(format, type)); - return (iter != formats.end()) ? iter->second.mColorWriteFunction : NULL; + static FormatSet formatSet = BuildAllSizedInternalFormatSet(); + return formatSet; } } diff --git a/gfx/angle/src/libGLESv2/formatutils.h b/gfx/angle/src/libGLESv2/formatutils.h index 004c8eda83bb..b53cd9354677 100644 --- a/gfx/angle/src/libGLESv2/formatutils.h +++ b/gfx/angle/src/libGLESv2/formatutils.h @@ -9,89 +9,97 @@ #ifndef LIBGLESV2_FORMATUTILS_H_ #define LIBGLESV2_FORMATUTILS_H_ -#include -#include -#include - +#include "libGLESv2/Caps.h" #include "libGLESv2/angletypes.h" -typedef void (*MipGenerationFunction)(unsigned int sourceWidth, unsigned int sourceHeight, unsigned int sourceDepth, - const unsigned char *sourceData, int sourceRowPitch, int sourceDepthPitch, - unsigned char *destData, int destRowPitch, int destDepthPitch); +#include "angle_gl.h" -typedef void (*LoadImageFunction)(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); +#include +#include -typedef void (*InitializeTextureDataFunction)(int width, int height, int depth, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); +typedef void (*MipGenerationFunction)(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch); -typedef void (*ColorReadFunction)(const void *source, void *dest); -typedef void (*ColorWriteFunction)(const void *source, void *dest); -typedef void (*ColorCopyFunction)(const void *source, void *dest); +typedef void (*LoadImageFunction)(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); -typedef void (*VertexCopyFunction)(const void *input, size_t stride, size_t count, void *output); +typedef void (*InitializeTextureDataFunction)(size_t width, size_t height, size_t depth, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); -namespace rx -{ +typedef void (*ColorReadFunction)(const uint8_t *source, uint8_t *dest); +typedef void (*ColorWriteFunction)(const uint8_t *source, uint8_t *dest); +typedef void (*ColorCopyFunction)(const uint8_t *source, uint8_t *dest); -class Renderer; - -} +typedef void (*VertexCopyFunction)(const uint8_t *input, size_t stride, size_t count, uint8_t *output); namespace gl { -class Context; +struct FormatType +{ + FormatType(); -bool IsValidInternalFormat(GLenum internalFormat, const Context *context); -bool IsValidFormat(GLenum format, GLuint clientVersion); -bool IsValidType(GLenum type, GLuint clientVersion); + GLenum internalFormat; + ColorWriteFunction colorWriteFunction; +}; +const FormatType &GetFormatTypeInfo(GLenum format, GLenum type); -bool IsValidFormatCombination(GLenum internalFormat, GLenum format, GLenum type, GLuint clientVersion); -bool IsValidCopyTexImageCombination(GLenum textureInternalFormat, GLenum frameBufferInternalFormat, GLuint readBufferHandle, GLuint clientVersion); +struct Type +{ + Type(); -bool IsSizedInternalFormat(GLenum internalFormat, GLuint clientVersion); -GLenum GetSizedInternalFormat(GLenum format, GLenum type, GLuint clientVersion); + GLuint bytes; + bool specialInterpretation; +}; +const Type &GetTypeInfo(GLenum type); -GLuint GetPixelBytes(GLenum internalFormat, GLuint clientVersion); -GLuint GetAlphaBits(GLenum internalFormat, GLuint clientVersion); -GLuint GetRedBits(GLenum internalFormat, GLuint clientVersion); -GLuint GetGreenBits(GLenum internalFormat, GLuint clientVersion); -GLuint GetBlueBits(GLenum internalFormat, GLuint clientVersion); -GLuint GetLuminanceBits(GLenum internalFormat, GLuint clientVersion); -GLuint GetDepthBits(GLenum internalFormat, GLuint clientVersion); -GLuint GetStencilBits(GLenum internalFormat, GLuint clientVersion); +struct InternalFormat +{ + InternalFormat(); -GLuint GetTypeBytes(GLenum type); -bool IsSpecialInterpretationType(GLenum type); -bool IsFloatOrFixedComponentType(GLenum type); + GLuint redBits; + GLuint greenBits; + GLuint blueBits; -GLenum GetFormat(GLenum internalFormat, GLuint clientVersion); -GLenum GetType(GLenum internalFormat, GLuint clientVersion); + GLuint luminanceBits; -GLenum GetComponentType(GLenum internalFormat, GLuint clientVersion); -GLuint GetComponentCount(GLenum internalFormat, GLuint clientVersion); -GLenum GetColorEncoding(GLenum internalFormat, GLuint clientVersion); + GLuint alphaBits; + GLuint sharedBits; -bool IsColorRenderingSupported(GLenum internalFormat, const rx::Renderer *renderer); -bool IsColorRenderingSupported(GLenum internalFormat, const Context *context); -bool IsTextureFilteringSupported(GLenum internalFormat, const rx::Renderer *renderer); -bool IsTextureFilteringSupported(GLenum internalFormat, const Context *context); -bool IsDepthRenderingSupported(GLenum internalFormat, const rx::Renderer *renderer); -bool IsDepthRenderingSupported(GLenum internalFormat, const Context *context); -bool IsStencilRenderingSupported(GLenum internalFormat, const rx::Renderer *renderer); -bool IsStencilRenderingSupported(GLenum internalFormat, const Context *context); + GLuint depthBits; + GLuint stencilBits; -GLuint GetRowPitch(GLenum internalFormat, GLenum type, GLuint clientVersion, GLsizei width, GLint alignment); -GLuint GetDepthPitch(GLenum internalFormat, GLenum type, GLuint clientVersion, GLsizei width, GLsizei height, GLint alignment); -GLuint GetBlockSize(GLenum internalFormat, GLenum type, GLuint clientVersion, GLsizei width, GLsizei height); + GLuint pixelBytes; -bool IsFormatCompressed(GLenum internalFormat, GLuint clientVersion); -GLuint GetCompressedBlockWidth(GLenum internalFormat, GLuint clientVersion); -GLuint GetCompressedBlockHeight(GLenum internalFormat, GLuint clientVersion); + GLuint componentCount; -ColorWriteFunction GetColorWriteFunction(GLenum format, GLenum type, GLuint clientVersion); + bool compressed; + GLuint compressedBlockWidth; + GLuint compressedBlockHeight; + + GLenum format; + GLenum type; + + GLenum componentType; + GLenum colorEncoding; + + typedef bool (*SupportCheckFunction)(GLuint, const Extensions &); + SupportCheckFunction textureSupport; + SupportCheckFunction renderSupport; + SupportCheckFunction filterSupport; + + GLuint computeRowPitch(GLenum type, GLsizei width, GLint alignment) const; + GLuint computeDepthPitch(GLenum type, GLsizei width, GLsizei height, GLint alignment) const; + GLuint computeBlockSize(GLenum type, GLsizei width, GLsizei height) const; +}; +const InternalFormat &GetInternalFormatInfo(GLenum internalFormat); + +GLenum GetSizedInternalFormat(GLenum internalFormat, GLenum type); + +typedef std::set FormatSet; +const FormatSet &GetAllSizedInternalFormats(); } diff --git a/gfx/angle/src/libGLESv2/libGLESv2.cpp b/gfx/angle/src/libGLESv2/libGLESv2.cpp index cb9326302ab2..62f98d8a781f 100644 --- a/gfx/angle/src/libGLESv2/libGLESv2.cpp +++ b/gfx/angle/src/libGLESv2/libGLESv2.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -8,9 +7,9 @@ // libGLESv2.cpp: Implements the exported OpenGL ES 2.0 functions. #include "common/version.h" +#include "common/utilities.h" #include "libGLESv2/main.h" -#include "common/utilities.h" #include "libGLESv2/formatutils.h" #include "libGLESv2/Buffer.h" #include "libGLESv2/Fence.h" @@ -22,7 +21,9 @@ #include "libGLESv2/Query.h" #include "libGLESv2/Context.h" #include "libGLESv2/VertexArray.h" +#include "libGLESv2/VertexAttribute.h" #include "libGLESv2/TransformFeedback.h" +#include "libGLESv2/FramebufferAttachment.h" #include "libGLESv2/validationES.h" #include "libGLESv2/validationES2.h" @@ -38,23 +39,16 @@ void __stdcall glActiveTexture(GLenum texture) { EVENT("(GLenum texture = 0x%X)", texture); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1) { - if (texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + context->getMaximumCombinedTextureImageUnits() - 1) - { - return gl::error(GL_INVALID_ENUM); - } - - context->setActiveSampler(texture - GL_TEXTURE0); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + context->getState().setActiveSampler(texture - GL_TEXTURE0); } } @@ -62,48 +56,45 @@ void __stdcall glAttachShader(GLuint program, GLuint shader) { EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::Program *programObject = context->getProgram(program); + gl::Shader *shaderObject = context->getShader(shader); - if (context) + if (!programObject) { - gl::Program *programObject = context->getProgram(program); - gl::Shader *shaderObject = context->getShader(shader); - - if (!programObject) + if (context->getShader(program)) { - if (context->getShader(program)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - - if (!shaderObject) + else { - if (context->getProgram(shader)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } - } - - if (!programObject->attachShader(shaderObject)) - { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + if (!shaderObject) + { + if (context->getProgram(shader)) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + } + + if (!programObject->attachShader(shaderObject)) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } } } @@ -111,23 +102,15 @@ void __stdcall glBeginQueryEXT(GLenum target, GLuint id) { EVENT("(GLenum target = 0x%X, GLuint %d)", target, id); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!ValidateBeginQuery(context, target, id)) { - if (!ValidateBeginQuery(context, target, id)) - { - return; - } - - context->beginQuery(target, id); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + context->beginQuery(target, id); } } @@ -135,42 +118,38 @@ void __stdcall glBindAttribLocation(GLuint program, GLuint index, const GLchar* { EVENT("(GLuint program = %d, GLuint index = %d, const GLchar* name = 0x%0.8p)", program, index, name); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - gl::Context *context = gl::getNonLostContext(); + gl::Program *programObject = context->getProgram(program); - if (context) + if (!programObject) { - gl::Program *programObject = context->getProgram(program); - - if (!programObject) + if (context->getShader(program)) { - if (context->getShader(program)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - - if (strncmp(name, "gl_", 3) == 0) + else { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - - programObject->bindAttributeLocation(index, name); } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + if (strncmp(name, "gl_", 3) == 0) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + programObject->bindAttributeLocation(index, name); } } @@ -178,51 +157,46 @@ void __stdcall glBindBuffer(GLenum target, GLuint buffer) { EVENT("(GLenum target = 0x%X, GLuint buffer = %d)", target, buffer); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!gl::ValidBufferTarget(context, target)) { - if (!gl::ValidBufferTarget(context, target)) - { - return gl::error(GL_INVALID_ENUM); - } - - switch (target) - { - case GL_ARRAY_BUFFER: - context->bindArrayBuffer(buffer); - return; - case GL_ELEMENT_ARRAY_BUFFER: - context->bindElementArrayBuffer(buffer); - return; - case GL_COPY_READ_BUFFER: - context->bindCopyReadBuffer(buffer); - return; - case GL_COPY_WRITE_BUFFER: - context->bindCopyWriteBuffer(buffer); - return; - case GL_PIXEL_PACK_BUFFER: - context->bindPixelPackBuffer(buffer); - return; - case GL_PIXEL_UNPACK_BUFFER: - context->bindPixelUnpackBuffer(buffer); - return; - case GL_UNIFORM_BUFFER: - context->bindGenericUniformBuffer(buffer); - return; - case GL_TRANSFORM_FEEDBACK_BUFFER: - context->bindGenericTransformFeedbackBuffer(buffer); - return; - default: - return gl::error(GL_INVALID_ENUM); - } + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + + switch (target) + { + case GL_ARRAY_BUFFER: + context->bindArrayBuffer(buffer); + return; + case GL_ELEMENT_ARRAY_BUFFER: + context->bindElementArrayBuffer(buffer); + return; + case GL_COPY_READ_BUFFER: + context->bindCopyReadBuffer(buffer); + return; + case GL_COPY_WRITE_BUFFER: + context->bindCopyWriteBuffer(buffer); + return; + case GL_PIXEL_PACK_BUFFER: + context->bindPixelPackBuffer(buffer); + return; + case GL_PIXEL_UNPACK_BUFFER: + context->bindPixelUnpackBuffer(buffer); + return; + case GL_UNIFORM_BUFFER: + context->bindGenericUniformBuffer(buffer); + return; + case GL_TRANSFORM_FEEDBACK_BUFFER: + context->bindGenericTransformFeedbackBuffer(buffer); + return; + + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -230,31 +204,24 @@ void __stdcall glBindFramebuffer(GLenum target, GLuint framebuffer) { EVENT("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (!gl::ValidFramebufferTarget(target)) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (target == GL_READ_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER) { - if (target == GL_READ_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER) - { - context->bindReadFramebuffer(framebuffer); - } - - if (target == GL_DRAW_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER) - { - context->bindDrawFramebuffer(framebuffer); - } + context->bindReadFramebuffer(framebuffer); + } + + if (target == GL_DRAW_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER) + { + context->bindDrawFramebuffer(framebuffer); } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -262,23 +229,16 @@ void __stdcall glBindRenderbuffer(GLenum target, GLuint renderbuffer) { EVENT("(GLenum target = 0x%X, GLuint renderbuffer = %d)", target, renderbuffer); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (target != GL_RENDERBUFFER) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - context->bindRenderbuffer(renderbuffer); - } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + context->bindRenderbuffer(renderbuffer); } } @@ -286,49 +246,49 @@ void __stdcall glBindTexture(GLenum target, GLuint texture) { EVENT("(GLenum target = 0x%X, GLuint texture = %d)", target, texture); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::Texture *textureObject = context->getTexture(texture); - if (context) + if (textureObject && textureObject->getTarget() != target && texture != 0) { - gl::Texture *textureObject = context->getTexture(texture); - - if (textureObject && textureObject->getTarget() != target && texture != 0) - { - return gl::error(GL_INVALID_OPERATION); - } - - switch (target) - { - case GL_TEXTURE_2D: - context->bindTexture2D(texture); - return; - case GL_TEXTURE_CUBE_MAP: - context->bindTextureCubeMap(texture); - return; - case GL_TEXTURE_3D: - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_ENUM); - } - context->bindTexture3D(texture); - return; - case GL_TEXTURE_2D_ARRAY: - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_ENUM); - } - context->bindTexture2DArray(texture); - return; - default: - return gl::error(GL_INVALID_ENUM); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + switch (target) + { + case GL_TEXTURE_2D: + context->bindTexture2D(texture); + return; + + case GL_TEXTURE_CUBE_MAP: + context->bindTextureCubeMap(texture); + return; + + case GL_TEXTURE_3D: + if (context->getClientVersion() < 3) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + context->bindTexture3D(texture); + return; + + case GL_TEXTURE_2D_ARRAY: + if (context->getClientVersion() < 3) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + context->bindTexture2DArray(texture); + return; + + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -337,18 +297,11 @@ void __stdcall glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclamp EVENT("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)", red, green, blue, alpha); - ANGLE_TRY - { - gl::Context* context = gl::getNonLostContext(); + gl::Context* context = gl::getNonLostContext(); - if (context) - { - context->setBlendColor(gl::clamp01(red), gl::clamp01(green), gl::clamp01(blue), gl::clamp01(alpha)); - } - } - ANGLE_CATCH_ALL + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setBlendColor(gl::clamp01(red), gl::clamp01(green), gl::clamp01(blue), gl::clamp01(alpha)); } } @@ -361,10 +314,9 @@ void __stdcall glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) { EVENT("(GLenum modeRGB = 0x%X, GLenum modeAlpha = 0x%X)", modeRGB, modeAlpha); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - switch (modeRGB) { case GL_FUNC_ADD: @@ -375,7 +327,8 @@ void __stdcall glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) break; default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } switch (modeAlpha) @@ -388,17 +341,11 @@ void __stdcall glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) break; default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - if (context) - { - context->setBlendEquation(modeRGB, modeAlpha); - } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setBlendEquation(modeRGB, modeAlpha); } } @@ -412,10 +359,9 @@ void __stdcall glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha EVENT("(GLenum srcRGB = 0x%X, GLenum dstRGB = 0x%X, GLenum srcAlpha = 0x%X, GLenum dstAlpha = 0x%X)", srcRGB, dstRGB, srcAlpha, dstAlpha); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - switch (srcRGB) { case GL_ZERO: @@ -434,8 +380,10 @@ void __stdcall glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha case GL_ONE_MINUS_CONSTANT_ALPHA: case GL_SRC_ALPHA_SATURATE: break; + default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } switch (dstRGB) @@ -457,14 +405,16 @@ void __stdcall glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha break; case GL_SRC_ALPHA_SATURATE: - if (!context || context->getClientVersion() < 3) + if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } break; default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } switch (srcAlpha) @@ -485,8 +435,10 @@ void __stdcall glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha case GL_ONE_MINUS_CONSTANT_ALPHA: case GL_SRC_ALPHA_SATURATE: break; + default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } switch (dstAlpha) @@ -508,14 +460,16 @@ void __stdcall glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha break; case GL_SRC_ALPHA_SATURATE: - if (!context || context->getClientVersion() < 3) + if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } break; default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } bool constantColorUsed = (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR || @@ -527,17 +481,11 @@ 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 gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - if (context) - { - context->setBlendFactors(srcRGB, dstRGB, srcAlpha, dstAlpha); - } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setBlendFactors(srcRGB, dstRGB, srcAlpha, dstAlpha); } } @@ -546,15 +494,15 @@ void __stdcall glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, EVENT("(GLenum target = 0x%X, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p, GLenum usage = %d)", target, size, data, usage); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (size < 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - gl::Context *context = gl::getNonLostContext(); - switch (usage) { case GL_STREAM_DRAW: @@ -568,36 +516,33 @@ void __stdcall glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, case GL_STATIC_COPY: case GL_DYNAMIC_READ: case GL_DYNAMIC_COPY: - if (context && context->getClientVersion() < 3) + if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } break; default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - if (context) + if (!gl::ValidBufferTarget(context, target)) { - if (!gl::ValidBufferTarget(context, target)) - { - return gl::error(GL_INVALID_ENUM); - } - - gl::Buffer *buffer = context->getTargetBuffer(target); - - if (!buffer) - { - return gl::error(GL_INVALID_OPERATION); - } - - buffer->bufferData(data, size, usage); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + gl::Buffer *buffer = context->getState().getTargetBuffer(target); + + if (!buffer) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + buffer->bufferData(data, size, usage); } } @@ -606,11 +551,13 @@ void __stdcall glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p)", target, offset, size, data); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (size < 0 || offset < 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } if (data == NULL) @@ -618,44 +565,40 @@ void __stdcall glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!gl::ValidBufferTarget(context, target)) { - if (!gl::ValidBufferTarget(context, target)) - { - return gl::error(GL_INVALID_ENUM); - } - - gl::Buffer *buffer = context->getTargetBuffer(target); - - if (!buffer) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (buffer->mapped()) - { - return gl::error(GL_INVALID_OPERATION); - } - - // Check for possible overflow of size + offset - if (!rx::IsUnsignedAdditionSafe(size, offset)) - { - return gl::error(GL_OUT_OF_MEMORY); - } - - if (size + offset > buffer->size()) - { - return gl::error(GL_INVALID_VALUE); - } - - buffer->bufferSubData(data, size, offset); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + gl::Buffer *buffer = context->getState().getTargetBuffer(target); + + if (!buffer) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + if (buffer->isMapped()) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + // Check for possible overflow of size + offset + if (!rx::IsUnsignedAdditionSafe(size, offset)) + { + context->recordError(gl::Error(GL_OUT_OF_MEMORY)); + return; + } + + if (size + offset > buffer->getSize()) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + buffer->bufferSubData(data, size, offset); } } @@ -663,25 +606,18 @@ GLenum __stdcall glCheckFramebufferStatus(GLenum target) { EVENT("(GLenum target = 0x%X)", target); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (!gl::ValidFramebufferTarget(target)) { - return gl::error(GL_INVALID_ENUM, 0); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return 0; } - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - gl::Framebuffer *framebuffer = context->getTargetFramebuffer(target); - ASSERT(framebuffer); - return framebuffer->completeness(); - } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY, 0); + gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); + ASSERT(framebuffer); + return framebuffer->completeness(); } return 0; @@ -691,30 +627,24 @@ void __stdcall glClear(GLbitfield mask) { EVENT("(GLbitfield mask = 0x%X)", mask); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::Framebuffer *framebufferObject = context->getState().getDrawFramebuffer(); - if (context) + if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE) { - gl::Framebuffer *framebufferObject = context->getDrawFramebuffer(); - - if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE) - { - return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION); - } - - if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0) - { - return gl::error(GL_INVALID_VALUE); - } - - context->clear(mask); + context->recordError(gl::Error(GL_INVALID_FRAMEBUFFER_OPERATION)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + context->clear(mask); } } @@ -723,18 +653,10 @@ void __stdcall glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclamp EVENT("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)", red, green, blue, alpha); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - context->setClearColor(red, green, blue, alpha); - } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setClearColor(red, green, blue, alpha); } } @@ -742,18 +664,10 @@ void __stdcall glClearDepthf(GLclampf depth) { EVENT("(GLclampf depth = %f)", depth); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - context->setClearDepth(depth); - } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setClearDepth(depth); } } @@ -761,18 +675,10 @@ void __stdcall glClearStencil(GLint s) { EVENT("(GLint s = %d)", s); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - context->setClearStencil(s); - } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setClearStencil(s); } } @@ -781,18 +687,10 @@ void __stdcall glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboo EVENT("(GLboolean red = %d, GLboolean green = %u, GLboolean blue = %u, GLboolean alpha = %u)", red, green, blue, alpha); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - context->setColorMask(red == GL_TRUE, green == GL_TRUE, blue == GL_TRUE, alpha == GL_TRUE); - } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setColorMask(red == GL_TRUE, green == GL_TRUE, blue == GL_TRUE, alpha == GL_TRUE); } } @@ -800,96 +698,85 @@ void __stdcall glCompileShader(GLuint shader) { EVENT("(GLuint shader = %d)", shader); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::Shader *shaderObject = context->getShader(shader); - if (context) + if (!shaderObject) { - gl::Shader *shaderObject = context->getShader(shader); - - if (!shaderObject) + if (context->getProgram(shader)) { - if (context->getProgram(shader)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - - shaderObject->compile(); } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + shaderObject->compile(); } } -void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, +void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data) { - EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, " + EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, " "GLsizei height = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)", target, level, internalformat, width, height, border, imageSize, data); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3 && + !ValidateES2TexImageParameters(context, target, level, internalformat, true, false, + 0, 0, width, height, border, GL_NONE, GL_NONE, data)) { - if (context->getClientVersion() < 3 && - !ValidateES2TexImageParameters(context, target, level, internalformat, true, false, - 0, 0, width, height, 0, GL_NONE, GL_NONE, data)) - { - return; - } - - if (context->getClientVersion() >= 3 && - !ValidateES3TexImageParameters(context, target, level, internalformat, true, false, - 0, 0, 0, width, height, 1, 0, GL_NONE, GL_NONE, data)) - { - return; - } - - if (imageSize < 0 || imageSize != (GLsizei)gl::GetBlockSize(internalformat, GL_UNSIGNED_BYTE, context->getClientVersion(), width, height)) - { - return gl::error(GL_INVALID_VALUE); - } - - switch (target) - { - case GL_TEXTURE_2D: - { - gl::Texture2D *texture = context->getTexture2D(); - texture->setCompressedImage(level, internalformat, width, height, imageSize, data); - } - break; - - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - { - gl::TextureCubeMap *texture = context->getTextureCubeMap(); - texture->setCompressedImage(target, level, internalformat, width, height, imageSize, data); - } - break; - - default: - return gl::error(GL_INVALID_ENUM); - } + return; + } + + if (context->getClientVersion() >= 3 && + !ValidateES3TexImageParameters(context, target, level, internalformat, true, false, + 0, 0, 0, width, height, 1, border, GL_NONE, GL_NONE, data)) + { + return; + } + + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat); + if (imageSize < 0 || static_cast(imageSize) != formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height)) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + switch (target) + { + case GL_TEXTURE_2D: + { + gl::Texture2D *texture = context->getTexture2D(); + texture->setCompressedImage(level, internalformat, width, height, imageSize, data); + } + break; + + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + { + gl::TextureCubeMap *texture = context->getTextureCubeMap(); + texture->setCompressedImage(target, level, internalformat, width, height, imageSize, data); + } + break; + + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -901,60 +788,55 @@ void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffs "GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)", target, level, xoffset, yoffset, width, height, format, imageSize, data); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3 && + !ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, + xoffset, yoffset, width, height, 0, GL_NONE, GL_NONE, data)) { - if (context->getClientVersion() < 3 && - !ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, - xoffset, yoffset, width, height, 0, GL_NONE, GL_NONE, data)) - { - return; - } - - if (context->getClientVersion() >= 3 && - !ValidateES3TexImageParameters(context, target, level, GL_NONE, true, true, - xoffset, yoffset, 0, width, height, 1, 0, GL_NONE, GL_NONE, data)) - { - return; - } - - if (imageSize < 0 || imageSize != (GLsizei)gl::GetBlockSize(format, GL_UNSIGNED_BYTE, context->getClientVersion(), width, height)) - { - return gl::error(GL_INVALID_VALUE); - } - - switch (target) - { - case GL_TEXTURE_2D: - { - gl::Texture2D *texture = context->getTexture2D(); - texture->subImageCompressed(level, xoffset, yoffset, width, height, format, imageSize, data); - } - break; - - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - { - gl::TextureCubeMap *texture = context->getTextureCubeMap(); - texture->subImageCompressed(target, level, xoffset, yoffset, width, height, format, imageSize, data); - } - break; - - default: - return gl::error(GL_INVALID_ENUM); - } + return; + } + + if (context->getClientVersion() >= 3 && + !ValidateES3TexImageParameters(context, target, level, GL_NONE, true, true, + xoffset, yoffset, 0, width, height, 1, 0, GL_NONE, GL_NONE, data)) + { + return; + } + + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format); + if (imageSize < 0 || static_cast(imageSize) != formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height)) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + switch (target) + { + case GL_TEXTURE_2D: + { + gl::Texture2D *texture = context->getTexture2D(); + texture->subImageCompressed(level, xoffset, yoffset, width, height, format, imageSize, data); + } + break; + + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + { + gl::TextureCubeMap *texture = context->getTextureCubeMap(); + texture->subImageCompressed(target, level, xoffset, yoffset, width, height, format, imageSize, data); + } + break; + + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -964,57 +846,50 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLint border = %d)", target, level, internalformat, x, y, width, height, border); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3 && + !ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, + 0, 0, x, y, width, height, border)) { - if (context->getClientVersion() < 3 && - !ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, - 0, 0, x, y, width, height, border)) - { - return; - } - - if (context->getClientVersion() >= 3 && - !ValidateES3CopyTexImageParameters(context, target, level, internalformat, false, - 0, 0, 0, x, y, width, height, border)) - { - return; - } - - gl::Framebuffer *framebuffer = context->getReadFramebuffer(); - - switch (target) - { - case GL_TEXTURE_2D: - { - gl::Texture2D *texture = context->getTexture2D(); - texture->copyImage(level, internalformat, x, y, width, height, framebuffer); - } - break; - - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - { - gl::TextureCubeMap *texture = context->getTextureCubeMap(); - texture->copyImage(target, level, internalformat, x, y, width, height, framebuffer); - } - break; - - default: - return gl::error(GL_INVALID_ENUM); - } + return; + } + + if (context->getClientVersion() >= 3 && + !ValidateES3CopyTexImageParameters(context, target, level, internalformat, false, + 0, 0, 0, x, y, width, height, border)) + { + return; + } + + gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); + + switch (target) + { + case GL_TEXTURE_2D: + { + gl::Texture2D *texture = context->getTexture2D(); + texture->copyImage(level, internalformat, x, y, width, height, framebuffer); + } + break; + + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + { + gl::TextureCubeMap *texture = context->getTextureCubeMap(); + texture->copyImage(target, level, internalformat, x, y, width, height, framebuffer); + } + break; + + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -1024,58 +899,50 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", target, level, xoffset, yoffset, x, y, width, height); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3 && + !ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, + xoffset, yoffset, x, y, width, height, 0)) { - if (context->getClientVersion() < 3 && - !ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, - xoffset, yoffset, x, y, width, height, 0)) - { - return; - } - - if (context->getClientVersion() >= 3 && - !ValidateES3CopyTexImageParameters(context, target, level, GL_NONE, true, - xoffset, yoffset, 0, x, y, width, height, 0)) - { - return; - } - - gl::Framebuffer *framebuffer = context->getReadFramebuffer(); - - switch (target) - { - case GL_TEXTURE_2D: - { - gl::Texture2D *texture = context->getTexture2D(); - texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, framebuffer); - } - break; - - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - { - gl::TextureCubeMap *texture = context->getTextureCubeMap(); - texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, framebuffer); - } - break; - - default: - return gl::error(GL_INVALID_ENUM); - } + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + if (context->getClientVersion() >= 3 && + !ValidateES3CopyTexImageParameters(context, target, level, GL_NONE, true, + xoffset, yoffset, 0, x, y, width, height, 0)) + { + return; + } + + gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); + + switch (target) + { + case GL_TEXTURE_2D: + { + gl::Texture2D *texture = context->getTexture2D(); + texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, framebuffer); + } + break; + + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + { + gl::TextureCubeMap *texture = context->getTextureCubeMap(); + texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, framebuffer); + } + break; + + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } } } @@ -1083,18 +950,10 @@ GLuint __stdcall glCreateProgram(void) { EVENT("()"); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - return context->createProgram(); - } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY, 0); + return context->createProgram(); } return 0; @@ -1104,26 +963,20 @@ GLuint __stdcall glCreateShader(GLenum type) { EVENT("(GLenum type = 0x%X)", type); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + switch (type) { - switch (type) - { - case GL_FRAGMENT_SHADER: - case GL_VERTEX_SHADER: - return context->createShader(type); - default: - return gl::error(GL_INVALID_ENUM, 0); - } + case GL_FRAGMENT_SHADER: + case GL_VERTEX_SHADER: + return context->createShader(type); + + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return 0; } } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY, 0); - } return 0; } @@ -1132,29 +985,22 @@ void __stdcall glCullFace(GLenum mode) { EVENT("(GLenum mode = 0x%X)", mode); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { switch (mode) { case GL_FRONT: case GL_BACK: case GL_FRONT_AND_BACK: - { - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - context->setCullMode(mode); - } - } break; + default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + context->getState().setCullMode(mode); } } @@ -1162,119 +1008,92 @@ void __stdcall glDeleteBuffers(GLsizei n, const GLuint* buffers) { EVENT("(GLsizei n = %d, const GLuint* buffers = 0x%0.8p)", n, buffers); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (n < 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) + for (int i = 0; i < n; i++) { - for (int i = 0; i < n; i++) - { - context->deleteBuffer(buffers[i]); - } + context->deleteBuffer(buffers[i]); } } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glDeleteFencesNV(GLsizei n, const GLuint* fences) { EVENT("(GLsizei n = %d, const GLuint* fences = 0x%0.8p)", n, fences); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (n < 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) + for (int i = 0; i < n; i++) { - for (int i = 0; i < n; i++) - { - context->deleteFenceNV(fences[i]); - } + context->deleteFenceNV(fences[i]); } } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers) { EVENT("(GLsizei n = %d, const GLuint* framebuffers = 0x%0.8p)", n, framebuffers); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (n < 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) + for (int i = 0; i < n; i++) { - for (int i = 0; i < n; i++) + if (framebuffers[i] != 0) { - if (framebuffers[i] != 0) - { - context->deleteFramebuffer(framebuffers[i]); - } + context->deleteFramebuffer(framebuffers[i]); } } } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glDeleteProgram(GLuint program) { EVENT("(GLuint program = %d)", program); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (program == 0) { return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!context->getProgram(program)) { - if (!context->getProgram(program)) + if(context->getShader(program)) { - if(context->getShader(program)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - - context->deleteProgram(program); } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + context->deleteProgram(program); } } @@ -1282,89 +1101,69 @@ void __stdcall glDeleteQueriesEXT(GLsizei n, const GLuint *ids) { EVENT("(GLsizei n = %d, const GLuint *ids = 0x%0.8p)", n, ids); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (n < 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) + for (int i = 0; i < n; i++) { - for (int i = 0; i < n; i++) - { - context->deleteQuery(ids[i]); - } + context->deleteQuery(ids[i]); } } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) { EVENT("(GLsizei n = %d, const GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (n < 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) + for (int i = 0; i < n; i++) { - for (int i = 0; i < n; i++) - { - context->deleteRenderbuffer(renderbuffers[i]); - } + context->deleteRenderbuffer(renderbuffers[i]); } } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glDeleteShader(GLuint shader) { EVENT("(GLuint shader = %d)", shader); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (shader == 0) { return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!context->getShader(shader)) { - if (!context->getShader(shader)) + if(context->getProgram(shader)) { - if(context->getProgram(shader)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - - context->deleteShader(shader); } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + context->deleteShader(shader); } } @@ -1372,37 +1171,31 @@ void __stdcall glDeleteTextures(GLsizei n, const GLuint* textures) { EVENT("(GLsizei n = %d, const GLuint* textures = 0x%0.8p)", n, textures); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (n < 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) + for (int i = 0; i < n; i++) { - for (int i = 0; i < n; i++) + if (textures[i] != 0) { - if (textures[i] != 0) - { - context->deleteTexture(textures[i]); - } + context->deleteTexture(textures[i]); } } } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glDepthFunc(GLenum func) { EVENT("(GLenum func = 0x%X)", func); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { switch (func) { @@ -1414,21 +1207,13 @@ void __stdcall glDepthFunc(GLenum func) case GL_GREATER: case GL_GEQUAL: case GL_NOTEQUAL: + context->getState().setDepthFunc(func); break; + default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - context->setDepthFunc(func); - } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -1436,18 +1221,10 @@ void __stdcall glDepthMask(GLboolean flag) { EVENT("(GLboolean flag = %u)", flag); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - context->setDepthMask(flag != GL_FALSE); - } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setDepthMask(flag != GL_FALSE); } } @@ -1455,18 +1232,10 @@ void __stdcall glDepthRangef(GLclampf zNear, GLclampf zFar) { EVENT("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - context->setDepthRange(zNear, zFar); - } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setDepthRange(zNear, zFar); } } @@ -1474,52 +1243,48 @@ void __stdcall glDetachShader(GLuint program, GLuint shader) { EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::Program *programObject = context->getProgram(program); + gl::Shader *shaderObject = context->getShader(shader); - if (context) + if (!programObject) { - - gl::Program *programObject = context->getProgram(program); - gl::Shader *shaderObject = context->getShader(shader); - - if (!programObject) + gl::Shader *shaderByProgramHandle; + shaderByProgramHandle = context->getShader(program); + if (!shaderByProgramHandle) { - gl::Shader *shaderByProgramHandle; - shaderByProgramHandle = context->getShader(program); - if (!shaderByProgramHandle) - { - return gl::error(GL_INVALID_VALUE); - } - else - { - return gl::error(GL_INVALID_OPERATION); - } + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - - if (!shaderObject) + else { - gl::Program *programByShaderHandle = context->getProgram(shader); - if (!programByShaderHandle) - { - return gl::error(GL_INVALID_VALUE); - } - else - { - return gl::error(GL_INVALID_OPERATION); - } - } - - if (!programObject->detachShader(shaderObject)) - { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + if (!shaderObject) + { + gl::Program *programByShaderHandle = context->getProgram(shader); + if (!programByShaderHandle) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + else + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + } + + if (!programObject->detachShader(shaderObject)) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } } } @@ -1527,23 +1292,16 @@ void __stdcall glDisable(GLenum cap) { EVENT("(GLenum cap = 0x%X)", cap); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!ValidCap(context, cap)) { - if (!ValidCap(context, cap)) - { - return gl::error(GL_INVALID_ENUM); - } - - context->setCap(cap, false); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + context->getState().setEnableFeature(cap, false); } } @@ -1551,23 +1309,16 @@ void __stdcall glDisableVertexAttribArray(GLuint index) { EVENT("(GLuint index = %d)", index); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - context->setEnableVertexAttribArray(index, false); - } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setEnableVertexAttribArray(index, false); } } @@ -1575,39 +1326,15 @@ void __stdcall glDrawArrays(GLenum mode, GLint first, GLsizei count) { EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - if (count < 0 || first < 0) + if (!ValidateDrawArrays(context, mode, first, count, 0)) { - return gl::error(GL_INVALID_VALUE); + return; } - gl::Context *context = gl::getNonLostContext(); - - // Check for mapped buffers - if (context->hasMappedBuffer(GL_ARRAY_BUFFER)) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (context) - { - gl::TransformFeedback *curTransformFeedback = context->getCurrentTransformFeedback(); - if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused() && - curTransformFeedback->getDrawMode() != mode) - { - // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode - // that does not match the current transform feedback object's draw mode (if transform feedback - // is active), (3.0.2, section 2.14, pg 86) - return gl::error(GL_INVALID_OPERATION); - } - - context->drawArrays(mode, first, count, 0); - } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + context->drawArrays(mode, first, count, 0); } } @@ -1615,42 +1342,15 @@ void __stdcall glDrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei coun { EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei primcount = %d)", mode, first, count, primcount); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - if (count < 0 || first < 0 || primcount < 0) + if (!ValidateDrawArraysInstanced(context, mode, first, count, primcount)) { - return gl::error(GL_INVALID_VALUE); + return; } - if (primcount > 0) - { - gl::Context *context = gl::getNonLostContext(); - - // Check for mapped buffers - if (context->hasMappedBuffer(GL_ARRAY_BUFFER)) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (context) - { - gl::TransformFeedback *curTransformFeedback = context->getCurrentTransformFeedback(); - if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused() && - curTransformFeedback->getDrawMode() != mode) - { - // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode - // that does not match the current transform feedback object's draw mode (if transform feedback - // is active), (3.0.2, section 2.14, pg 86) - return gl::error(GL_INVALID_OPERATION); - } - - context->drawArrays(mode, first, count, primcount); - } - } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + context->drawArrays(mode, first, count, primcount); } } @@ -1659,52 +1359,16 @@ void __stdcall glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLv EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p)", mode, count, type, indices); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - if (count < 0) + rx::RangeUI indexRange; + if (!ValidateDrawElements(context, mode, count, type, indices, 0, &indexRange)) { - return gl::error(GL_INVALID_VALUE); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - switch (type) - { - case GL_UNSIGNED_BYTE: - case GL_UNSIGNED_SHORT: - break; - case GL_UNSIGNED_INT: - if (!context->supports32bitIndices()) - { - return gl::error(GL_INVALID_ENUM); - } - break; - default: - return gl::error(GL_INVALID_ENUM); - } - - gl::TransformFeedback *curTransformFeedback = context->getCurrentTransformFeedback(); - if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused()) - { - // It is an invalid operation to call DrawElements, DrawRangeElements or DrawElementsInstanced - // while transform feedback is active, (3.0.2, section 2.14, pg 86) - return gl::error(GL_INVALID_OPERATION); - } - - // Check for mapped buffers - if (context->hasMappedBuffer(GL_ARRAY_BUFFER) || context->hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER)) - { - return gl::error(GL_INVALID_OPERATION); - } - - context->drawElements(mode, count, type, indices, 0); - } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + context->drawElements(mode, count, type, indices, 0, indexRange); } } @@ -1713,55 +1377,16 @@ void __stdcall glDrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum t EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p, GLsizei primcount = %d)", mode, count, type, indices, primcount); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - if (count < 0 || primcount < 0) + rx::RangeUI indexRange; + if (!ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount, &indexRange)) { - return gl::error(GL_INVALID_VALUE); + return; } - if (primcount > 0) - { - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - switch (type) - { - case GL_UNSIGNED_BYTE: - case GL_UNSIGNED_SHORT: - break; - case GL_UNSIGNED_INT: - if (!context->supports32bitIndices()) - { - return gl::error(GL_INVALID_ENUM); - } - break; - default: - return gl::error(GL_INVALID_ENUM); - } - - gl::TransformFeedback *curTransformFeedback = context->getCurrentTransformFeedback(); - if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused()) - { - // It is an invalid operation to call DrawElements, DrawRangeElements or DrawElementsInstanced - // while transform feedback is active, (3.0.2, section 2.14, pg 86) - return gl::error(GL_INVALID_OPERATION); - } - - // Check for mapped buffers - if (context->hasMappedBuffer(GL_ARRAY_BUFFER) || context->hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER)) - { - return gl::error(GL_INVALID_OPERATION); - } - - context->drawElements(mode, count, type, indices, primcount); - } - } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + context->drawElements(mode, count, type, indices, primcount, indexRange); } } @@ -1769,23 +1394,16 @@ void __stdcall glEnable(GLenum cap) { EVENT("(GLenum cap = 0x%X)", cap); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!ValidCap(context, cap)) { - if (!ValidCap(context, cap)) - { - return gl::error(GL_INVALID_ENUM); - } - - context->setCap(cap, true); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + context->getState().setEnableFeature(cap, true); } } @@ -1793,23 +1411,16 @@ void __stdcall glEnableVertexAttribArray(GLuint index) { EVENT("(GLuint index = %d)", index); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - context->setEnableVertexAttribArray(index, true); - } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setEnableVertexAttribArray(index, true); } } @@ -1817,23 +1428,15 @@ void __stdcall glEndQueryEXT(GLenum target) { EVENT("GLenum target = 0x%X)", target); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!ValidateEndQuery(context, target)) { - if (!ValidateEndQuery(context, target)) - { - return; - } - - context->endQuery(target); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + context->endQuery(target); } } @@ -1841,30 +1444,24 @@ void __stdcall glFinishFenceNV(GLuint fence) { EVENT("(GLuint fence = %d)", fence); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::FenceNV *fenceObject = context->getFenceNV(fence); - if (context) + if (fenceObject == NULL) { - gl::FenceNV *fenceObject = context->getFenceNV(fence); - - if (fenceObject == NULL) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (fenceObject->isFence() != GL_TRUE) - { - return gl::error(GL_INVALID_OPERATION); - } - - fenceObject->finishFence(); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + if (fenceObject->isFence() != GL_TRUE) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + fenceObject->finishFence(); } } @@ -1872,18 +1469,10 @@ void __stdcall glFinish(void) { EVENT("()"); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - context->sync(true); - } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + context->sync(true); } } @@ -1891,18 +1480,10 @@ void __stdcall glFlush(void) { EVENT("()"); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - context->sync(false); - } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + context->sync(false); } } @@ -1911,54 +1492,47 @@ void __stdcall glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenu EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, " "GLuint renderbuffer = %d)", target, attachment, renderbuffertarget, renderbuffer); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (!gl::ValidFramebufferTarget(target) || (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0)) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!gl::ValidateFramebufferRenderbufferParameters(context, target, attachment, renderbuffertarget, renderbuffer)) { - if (!gl::ValidateFramebufferRenderbufferParameters(context, target, attachment, renderbuffertarget, renderbuffer)) - { - return; - } + return; + } - gl::Framebuffer *framebuffer = context->getTargetFramebuffer(target); - ASSERT(framebuffer); + gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); + ASSERT(framebuffer); - if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) + if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) + { + unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT); + framebuffer->setColorbuffer(colorAttachment, GL_RENDERBUFFER, renderbuffer, 0, 0); + } + else + { + switch (attachment) { - unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT); - framebuffer->setColorbuffer(colorAttachment, GL_RENDERBUFFER, renderbuffer, 0, 0); - } - else - { - switch (attachment) - { - case GL_DEPTH_ATTACHMENT: - framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer, 0, 0); - break; - case GL_STENCIL_ATTACHMENT: - framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer, 0, 0); - break; - case GL_DEPTH_STENCIL_ATTACHMENT: - framebuffer->setDepthStencilBuffer(GL_RENDERBUFFER, renderbuffer, 0, 0); - break; - default: - UNREACHABLE(); - break; - } + case GL_DEPTH_ATTACHMENT: + framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer, 0, 0); + break; + case GL_STENCIL_ATTACHMENT: + framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer, 0, 0); + break; + case GL_DEPTH_STENCIL_ATTACHMENT: + framebuffer->setDepthStencilBuffer(GL_RENDERBUFFER, renderbuffer, 0, 0); + break; + default: + UNREACHABLE(); + break; } } } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) @@ -1966,169 +1540,149 @@ void __stdcall glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum t EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, " "GLuint texture = %d, GLint level = %d)", target, attachment, textarget, texture, level); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - if (context) + if (!ValidateFramebufferTexture2D(context, target, attachment, textarget, texture, level)) { - if (context->getClientVersion() < 3 && - !ValidateES2FramebufferTextureParameters(context, target, attachment, textarget, texture, level)) - { - return; - } + return; + } - if (context->getClientVersion() >= 3 && - !ValidateES3FramebufferTextureParameters(context, target, attachment, textarget, texture, level, 0, false)) - { - return; - } + if (texture == 0) + { + textarget = GL_NONE; + } - if (texture == 0) - { - textarget = GL_NONE; - } + gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); - gl::Framebuffer *framebuffer = context->getTargetFramebuffer(target); - - if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) + if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) + { + const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT); + framebuffer->setColorbuffer(colorAttachment, textarget, texture, level, 0); + } + else + { + switch (attachment) { - const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT); - framebuffer->setColorbuffer(colorAttachment, textarget, texture, level, 0); - } - else - { - switch (attachment) - { - case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture, level, 0); break; - case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture, level, 0); break; - case GL_DEPTH_STENCIL_ATTACHMENT: framebuffer->setDepthStencilBuffer(textarget, texture, level, 0); break; - } + case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture, level, 0); break; + case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture, level, 0); break; + case GL_DEPTH_STENCIL_ATTACHMENT: framebuffer->setDepthStencilBuffer(textarget, texture, level, 0); break; } } } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glFrontFace(GLenum mode) { EVENT("(GLenum mode = 0x%X)", mode); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { switch (mode) { case GL_CW: case GL_CCW: - { - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - context->setFrontFace(mode); - } - } + context->getState().setFrontFace(mode); break; default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glGenBuffers(GLsizei n, GLuint* buffers) { EVENT("(GLsizei n = %d, GLuint* buffers = 0x%0.8p)", n, buffers); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (n < 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) + for (int i = 0; i < n; i++) { - for (int i = 0; i < n; i++) - { - buffers[i] = context->createBuffer(); - } + buffers[i] = context->createBuffer(); } } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glGenerateMipmap(GLenum target) { EVENT("(GLenum target = 0x%X)", target); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!ValidTextureTarget(context, target)) { - if (!ValidTextureTarget(context, target)) - { - return gl::error(GL_INVALID_ENUM); - } - - gl::Texture *texture = context->getTargetTexture(target); - - if (texture == NULL) - { - return gl::error(GL_INVALID_OPERATION); - } - - GLenum internalFormat = texture->getBaseLevelInternalFormat(); - - // Internally, all texture formats are sized so checking if the format - // is color renderable and filterable will not fail. - - bool validRenderable = (gl::IsColorRenderingSupported(internalFormat, context) || - gl::IsSizedInternalFormat(internalFormat, context->getClientVersion())); - - if (gl::IsDepthRenderingSupported(internalFormat, context) || - gl::IsFormatCompressed(internalFormat, context->getClientVersion()) || - !gl::IsTextureFilteringSupported(internalFormat, context) || - !validRenderable) - { - return gl::error(GL_INVALID_OPERATION); - } - - // Non-power of 2 ES2 check - if (!context->supportsNonPower2Texture() && (!gl::isPow2(texture->getBaseLevelWidth()) || !gl::isPow2(texture->getBaseLevelHeight()))) - { - ASSERT(context->getClientVersion() <= 2 && (target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP)); - return gl::error(GL_INVALID_OPERATION); - } - - // Cube completeness check - if (target == GL_TEXTURE_CUBE_MAP) - { - gl::TextureCubeMap *textureCube = static_cast(texture); - if (!textureCube->isCubeComplete()) - { - return gl::error(GL_INVALID_OPERATION); - } - } - - texture->generateMipmaps(); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + gl::Texture *texture = context->getTargetTexture(target); + + if (texture == NULL) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + GLenum internalFormat = texture->getBaseLevelInternalFormat(); + const gl::TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat); + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); + + // GenerateMipmap should not generate an INVALID_OPERATION for textures created with + // unsized formats or that are color renderable and filterable. Since we do not track if + // the texture was created with sized or unsized format (only sized formats are stored), + // it is not possible to make sure the the LUMA formats can generate mipmaps (they should + // be able to) because they aren't color renderable. Simply do a special case for LUMA + // textures since they're the only texture format that can be created with unsized formats + // that is not color renderable. New unsized formats are unlikely to be added, since ES2 + // was the last version to use add them. + bool isLUMA = internalFormat == GL_LUMINANCE8_EXT || + internalFormat == GL_LUMINANCE8_ALPHA8_EXT || + internalFormat == GL_ALPHA8_EXT; + + if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0 || !formatCaps.filterable || + (!formatCaps.renderable && !isLUMA) || formatInfo.compressed) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + // GL_EXT_sRGB does not support mipmap generation on sRGB textures + if (context->getClientVersion() == 2 && formatInfo.colorEncoding == GL_SRGB) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + // Non-power of 2 ES2 check + if (!context->getExtensions().textureNPOT && (!gl::isPow2(texture->getBaseLevelWidth()) || !gl::isPow2(texture->getBaseLevelHeight()))) + { + ASSERT(context->getClientVersion() <= 2 && (target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP)); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + // Cube completeness check + if (target == GL_TEXTURE_CUBE_MAP) + { + gl::TextureCubeMap *textureCube = static_cast(texture); + if (!textureCube->isCubeComplete()) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + } + + texture->generateMipmaps(); } } @@ -2136,80 +1690,59 @@ void __stdcall glGenFencesNV(GLsizei n, GLuint* fences) { EVENT("(GLsizei n = %d, GLuint* fences = 0x%0.8p)", n, fences); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (n < 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) + for (int i = 0; i < n; i++) { - for (int i = 0; i < n; i++) - { - fences[i] = context->createFenceNV(); - } + fences[i] = context->createFenceNV(); } } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glGenFramebuffers(GLsizei n, GLuint* framebuffers) { EVENT("(GLsizei n = %d, GLuint* framebuffers = 0x%0.8p)", n, framebuffers); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (n < 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) + for (int i = 0; i < n; i++) { - for (int i = 0; i < n; i++) - { - framebuffers[i] = context->createFramebuffer(); - } + framebuffers[i] = context->createFramebuffer(); } } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glGenQueriesEXT(GLsizei n, GLuint* ids) { EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (n < 0) { - if (n < 0) - { - return gl::error(GL_INVALID_VALUE); - } - - for (GLsizei i = 0; i < n; i++) - { - ids[i] = context->createQuery(); - } + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + for (GLsizei i = 0; i < n; i++) + { + ids[i] = context->createQuery(); } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -2217,54 +1750,40 @@ void __stdcall glGenRenderbuffers(GLsizei n, GLuint* renderbuffers) { EVENT("(GLsizei n = %d, GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (n < 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) + for (int i = 0; i < n; i++) { - for (int i = 0; i < n; i++) - { - renderbuffers[i] = context->createRenderbuffer(); - } + renderbuffers[i] = context->createRenderbuffer(); } } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glGenTextures(GLsizei n, GLuint* textures) { EVENT("(GLsizei n = %d, GLuint* textures = 0x%0.8p)", n, textures); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (n < 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) + for (int i = 0; i < n; i++) { - for (int i = 0; i < n; i++) - { - textures[i] = context->createTexture(); - } + textures[i] = context->createTexture(); } } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) @@ -2273,42 +1792,38 @@ void __stdcall glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, "GLint *size = 0x%0.8p, GLenum *type = %0.8p, GLchar *name = %0.8p)", program, index, bufsize, length, size, type, name); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (bufsize < 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - gl::Context *context = gl::getNonLostContext(); + gl::Program *programObject = context->getProgram(program); - if (context) + if (!programObject) { - gl::Program *programObject = context->getProgram(program); - - if (!programObject) + if (context->getShader(program)) { - if (context->getShader(program)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - - if (index >= (GLuint)programObject->getActiveAttributeCount()) + else { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - - programObject->getActiveAttribute(index, bufsize, length, size, type, name); } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + if (index >= (GLuint)programObject->getActiveAttributeCount()) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + programObject->getActiveAttribute(index, bufsize, length, size, type, name); } } @@ -2318,42 +1833,39 @@ void __stdcall glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, "GLsizei* length = 0x%0.8p, GLint* size = 0x%0.8p, GLenum* type = 0x%0.8p, GLchar* name = 0x%0.8p)", program, index, bufsize, length, size, type, name); - ANGLE_TRY + + gl::Context *context = gl::getNonLostContext(); + if (context) { if (bufsize < 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - gl::Context *context = gl::getNonLostContext(); + gl::Program *programObject = context->getProgram(program); - if (context) + if (!programObject) { - gl::Program *programObject = context->getProgram(program); - - if (!programObject) + if (context->getShader(program)) { - if (context->getShader(program)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - - if (index >= (GLuint)programObject->getActiveUniformCount()) + else { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - - programObject->getActiveUniform(index, bufsize, length, size, type, name); } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + if (index >= (GLuint)programObject->getActiveUniformCount()) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + programObject->getActiveUniform(index, bufsize, length, size, type, name); } } @@ -2362,77 +1874,66 @@ void __stdcall glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* c EVENT("(GLuint program = %d, GLsizei maxcount = %d, GLsizei* count = 0x%0.8p, GLuint* shaders = 0x%0.8p)", program, maxcount, count, shaders); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (maxcount < 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - gl::Context *context = gl::getNonLostContext(); + gl::Program *programObject = context->getProgram(program); - if (context) + if (!programObject) { - gl::Program *programObject = context->getProgram(program); - - if (!programObject) + if (context->getShader(program)) { - if (context->getShader(program)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - - return programObject->getAttachedShaders(maxcount, count, shaders); } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + return programObject->getAttachedShaders(maxcount, count, shaders); } } -int __stdcall glGetAttribLocation(GLuint program, const GLchar* name) +GLint __stdcall glGetAttribLocation(GLuint program, const GLchar* name) { EVENT("(GLuint program = %d, const GLchar* name = %s)", program, name); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::Program *programObject = context->getProgram(program); - if (context) + if (!programObject) { - - gl::Program *programObject = context->getProgram(program); - - if (!programObject) + if (context->getShader(program)) { - if (context->getShader(program)) - { - return gl::error(GL_INVALID_OPERATION, -1); - } - else - { - return gl::error(GL_INVALID_VALUE, -1); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return -1; } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (!programObject->isLinked() || !programBinary) + else { - return gl::error(GL_INVALID_OPERATION, -1); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return -1; } - - return programBinary->getAttributeLocation(name); } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY, -1); + + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + if (!programObject->isLinked() || !programBinary) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return -1; + } + + return programBinary->getAttributeLocation(name); } return -1; @@ -2442,32 +1943,24 @@ void __stdcall glGetBooleanv(GLenum pname, GLboolean* params) { EVENT("(GLenum pname = 0x%X, GLboolean* params = 0x%0.8p)", pname, params); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + GLenum nativeType; + unsigned int numParams = 0; + if (!ValidateStateQuery(context, pname, &nativeType, &numParams)) { - GLenum nativeType; - unsigned int numParams = 0; - if (!ValidateStateQuery(context, pname, &nativeType, &numParams)) - { - return; - } - - if (nativeType == GL_BOOL) - { - context->getBooleanv(pname, params); - } - else - { - CastStateValues(context, nativeType, pname, numParams, params); - } + return; + } + + if (nativeType == GL_BOOL) + { + context->getBooleanv(pname, params); + } + else + { + CastStateValues(context, nativeType, pname, numParams, params); } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -2475,57 +1968,52 @@ void __stdcall glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params { EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!gl::ValidBufferTarget(context, target)) { - if (!gl::ValidBufferTarget(context, target)) - { - return gl::error(GL_INVALID_ENUM); - } - - if (!gl::ValidBufferParameter(context, pname)) - { - return gl::error(GL_INVALID_ENUM); - } - - gl::Buffer *buffer = context->getTargetBuffer(target); - - if (!buffer) - { - // A null buffer means that "0" is bound to the requested buffer target - return gl::error(GL_INVALID_OPERATION); - } - - switch (pname) - { - case GL_BUFFER_USAGE: - *params = static_cast(buffer->usage()); - break; - case GL_BUFFER_SIZE: - *params = gl::clampCast(buffer->size()); - break; - case GL_BUFFER_ACCESS_FLAGS: - *params = buffer->accessFlags(); - break; - case GL_BUFFER_MAPPED: - *params = static_cast(buffer->mapped()); - break; - case GL_BUFFER_MAP_OFFSET: - *params = gl::clampCast(buffer->mapOffset()); - break; - case GL_BUFFER_MAP_LENGTH: - *params = gl::clampCast(buffer->mapLength()); - break; - default: UNREACHABLE(); break; - } + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + + if (!gl::ValidBufferParameter(context, pname)) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + + gl::Buffer *buffer = context->getState().getTargetBuffer(target); + + if (!buffer) + { + // A null buffer means that "0" is bound to the requested buffer target + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + switch (pname) + { + case GL_BUFFER_USAGE: + *params = static_cast(buffer->getUsage()); + break; + case GL_BUFFER_SIZE: + *params = gl::clampCast(buffer->getSize()); + break; + case GL_BUFFER_ACCESS_FLAGS: + *params = buffer->getAccessFlags(); + break; + case GL_BUFFER_MAPPED: + *params = static_cast(buffer->isMapped()); + break; + case GL_BUFFER_MAP_OFFSET: + *params = gl::clampCast(buffer->getMapOffset()); + break; + case GL_BUFFER_MAP_LENGTH: + *params = gl::clampCast(buffer->getMapLength()); + break; + default: UNREACHABLE(); break; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -2547,40 +2035,35 @@ void __stdcall glGetFenceivNV(GLuint fence, GLenum pname, GLint *params) { EVENT("(GLuint fence = %d, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", fence, pname, params); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - - gl::Context *context = gl::getNonLostContext(); + gl::FenceNV *fenceObject = context->getFenceNV(fence); - if (context) + if (fenceObject == NULL) { - gl::FenceNV *fenceObject = context->getFenceNV(fence); - - if (fenceObject == NULL) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (fenceObject->isFence() != GL_TRUE) - { - return gl::error(GL_INVALID_OPERATION); - } - - switch (pname) - { - case GL_FENCE_STATUS_NV: - case GL_FENCE_CONDITION_NV: - break; - - default: return gl::error(GL_INVALID_ENUM); - } - - params[0] = fenceObject->getFencei(pname); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + if (fenceObject->isFence() != GL_TRUE) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + switch (pname) + { + case GL_FENCE_STATUS_NV: + case GL_FENCE_CONDITION_NV: + break; + + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + + params[0] = fenceObject->getFencei(pname); } } @@ -2588,32 +2071,24 @@ void __stdcall glGetFloatv(GLenum pname, GLfloat* params) { EVENT("(GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", pname, params); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + GLenum nativeType; + unsigned int numParams = 0; + if (!ValidateStateQuery(context, pname, &nativeType, &numParams)) { - GLenum nativeType; - unsigned int numParams = 0; - if (!ValidateStateQuery(context, pname, &nativeType, &numParams)) - { - return; - } - - if (nativeType == GL_FLOAT) - { - context->getFloatv(pname, params); - } - else - { - CastStateValues(context, nativeType, pname, numParams, params); - } + return; + } + + if (nativeType == GL_FLOAT) + { + context->getFloatv(pname, params); + } + else + { + CastStateValues(context, nativeType, pname, numParams, params); } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -2622,301 +2097,295 @@ void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attac EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, attachment, pname, params); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!gl::ValidFramebufferTarget(target)) { - if (!gl::ValidFramebufferTarget(target)) + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + + int clientVersion = context->getClientVersion(); + + switch (pname) + { + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: + break; + + case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING: + if (clientVersion < 3 && !context->getExtensions().sRGB) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } + break; + + case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE: + case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE: + case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE: + case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE: + case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE: + case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE: + case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE: + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER: + if (clientVersion < 3) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + break; + + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + + // Determine if the attachment is a valid enum + switch (attachment) + { + case GL_BACK: + case GL_FRONT: + case GL_DEPTH: + case GL_STENCIL: + case GL_DEPTH_STENCIL_ATTACHMENT: + if (clientVersion < 3) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + break; + + case GL_DEPTH_ATTACHMENT: + case GL_STENCIL_ATTACHMENT: + break; + + default: + if (attachment < GL_COLOR_ATTACHMENT0_EXT || + (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + break; + } + + GLuint framebufferHandle = context->getState().getTargetFramebuffer(target)->id(); + gl::Framebuffer *framebuffer = context->getFramebuffer(framebufferHandle); + + if (framebufferHandle == 0) + { + if (clientVersion < 3) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + switch (attachment) + { + case GL_BACK: + case GL_DEPTH: + case GL_STENCIL: + break; + + default: + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + } + else + { + if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) + { + // Valid attachment query + } + else + { + switch (attachment) + { + case GL_DEPTH_ATTACHMENT: + case GL_STENCIL_ATTACHMENT: + break; + + case GL_DEPTH_STENCIL_ATTACHMENT: + if (framebuffer->hasValidDepthStencil()) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + break; + + default: + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + } + } + + GLenum attachmentType = GL_NONE; + GLuint attachmentHandle = 0; + GLuint attachmentLevel = 0; + GLuint attachmentLayer = 0; + + const gl::FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment); + + if (attachmentObject) + { + attachmentType = attachmentObject->type(); + attachmentHandle = attachmentObject->id(); + attachmentLevel = attachmentObject->mipLevel(); + attachmentLayer = attachmentObject->layer(); + } + + GLenum attachmentObjectType; // Type category + if (framebufferHandle == 0) + { + attachmentObjectType = GL_FRAMEBUFFER_DEFAULT; + } + else if (attachmentType == GL_NONE || attachmentType == GL_RENDERBUFFER) + { + attachmentObjectType = attachmentType; + } + else if (gl::ValidTexture2DDestinationTarget(context, attachmentType)) + { + attachmentObjectType = GL_TEXTURE; + } + else + { + UNREACHABLE(); + return; + } + + if (attachmentObjectType == GL_NONE) + { + // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE + // is NONE, then querying any other pname will generate INVALID_ENUM. + + // ES 3.0.2 spec pg 235 states that if the attachment type is none, + // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an + // INVALID_OPERATION for all other pnames switch (pname) { case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: + *params = attachmentObjectType; + break; + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: - case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: - case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: - break; - case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE: - case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE: - case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE: - case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE: - case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE: - case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE: - case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE: - case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING: - case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER: - if (context->getClientVersion() >= 3) + if (clientVersion < 3) { - break; + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - default: - return gl::error(GL_INVALID_ENUM); - } - - // Determine if the attachment is a valid enum - switch (attachment) - { - case GL_BACK: - case GL_FRONT: - case GL_DEPTH: - case GL_STENCIL: - case GL_DEPTH_STENCIL_ATTACHMENT: - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_ENUM); - } - break; - - case GL_DEPTH_ATTACHMENT: - case GL_STENCIL_ATTACHMENT: + *params = 0; break; default: - if (attachment < GL_COLOR_ATTACHMENT0_EXT || - (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getMaximumRenderTargets()) + if (clientVersion < 3) { - return gl::error(GL_INVALID_ENUM); - } - break; - } - - GLuint framebufferHandle = context->getTargetFramebufferHandle(target); - ASSERT(framebufferHandle != GL_INVALID_INDEX); - gl::Framebuffer *framebuffer = context->getFramebuffer(framebufferHandle); - - GLenum attachmentType; - GLuint attachmentHandle; - GLuint attachmentLevel; - GLuint attachmentLayer; - gl::Renderbuffer *renderbuffer; - - if(framebufferHandle == 0) - { - if(context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - switch (attachment) - { - case GL_BACK: - attachmentType = framebuffer->getColorbufferType(0); - attachmentHandle = framebuffer->getColorbufferHandle(0); - attachmentLevel = framebuffer->getColorbufferMipLevel(0); - attachmentLayer = framebuffer->getColorbufferLayer(0); - renderbuffer = framebuffer->getColorbuffer(0); - break; - case GL_DEPTH: - attachmentType = framebuffer->getDepthbufferType(); - attachmentHandle = framebuffer->getDepthbufferHandle(); - attachmentLevel = framebuffer->getDepthbufferMipLevel(); - attachmentLayer = framebuffer->getDepthbufferLayer(); - renderbuffer = framebuffer->getDepthbuffer(); - break; - case GL_STENCIL: - attachmentType = framebuffer->getStencilbufferType(); - attachmentHandle = framebuffer->getStencilbufferHandle(); - attachmentLevel = framebuffer->getStencilbufferMipLevel(); - attachmentLayer = framebuffer->getStencilbufferLayer(); - renderbuffer = framebuffer->getStencilbuffer(); - break; - default: - return gl::error(GL_INVALID_OPERATION); - } - } - else - { - if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) - { - const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT); - attachmentType = framebuffer->getColorbufferType(colorAttachment); - attachmentHandle = framebuffer->getColorbufferHandle(colorAttachment); - attachmentLevel = framebuffer->getColorbufferMipLevel(colorAttachment); - attachmentLayer = framebuffer->getColorbufferLayer(colorAttachment); - renderbuffer = framebuffer->getColorbuffer(colorAttachment); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } else { - switch (attachment) - { - case GL_DEPTH_ATTACHMENT: - attachmentType = framebuffer->getDepthbufferType(); - attachmentHandle = framebuffer->getDepthbufferHandle(); - attachmentLevel = framebuffer->getDepthbufferMipLevel(); - attachmentLayer = framebuffer->getDepthbufferLayer(); - renderbuffer = framebuffer->getDepthbuffer(); - break; - case GL_STENCIL_ATTACHMENT: - attachmentType = framebuffer->getStencilbufferType(); - attachmentHandle = framebuffer->getStencilbufferHandle(); - attachmentLevel = framebuffer->getStencilbufferMipLevel(); - attachmentLayer = framebuffer->getStencilbufferLayer(); - renderbuffer = framebuffer->getStencilbuffer(); - break; - case GL_DEPTH_STENCIL_ATTACHMENT: - if (framebuffer->getDepthbufferHandle() != framebuffer->getStencilbufferHandle()) - { - return gl::error(GL_INVALID_OPERATION); - } - attachmentType = framebuffer->getDepthStencilbufferType(); - attachmentHandle = framebuffer->getDepthStencilbufferHandle(); - attachmentLevel = framebuffer->getDepthStencilbufferMipLevel(); - attachmentLayer = framebuffer->getDepthStencilbufferLayer(); - renderbuffer = framebuffer->getDepthStencilBuffer(); - break; - default: - return gl::error(GL_INVALID_OPERATION); - } - } - } - - GLenum attachmentObjectType; // Type category - if (framebufferHandle == 0) - { - attachmentObjectType = GL_FRAMEBUFFER_DEFAULT; - } - else if (attachmentType == GL_NONE || attachmentType == GL_RENDERBUFFER) - { - attachmentObjectType = attachmentType; - } - else if (gl::IsInternalTextureTarget(attachmentType, context->getClientVersion())) - { - attachmentObjectType = GL_TEXTURE; - } - else - { - UNREACHABLE(); - return; - } - - if (attachmentObjectType == GL_NONE) - { - // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE - // is NONE, then querying any other pname will generate INVALID_ENUM. - - // ES 3.0.2 spec pg 235 states that if the attachment type is none, - // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an - // INVALID_OPERATION for all other pnames - - switch (pname) - { - case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: - *params = attachmentObjectType; - break; - - case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_ENUM); - } - *params = 0; - break; - - default: - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_ENUM); - } - else - { - gl::error(GL_INVALID_OPERATION); - } - } - } - else - { - ASSERT(attachmentObjectType == GL_RENDERBUFFER || attachmentObjectType == GL_TEXTURE || - attachmentObjectType == GL_FRAMEBUFFER_DEFAULT); - ASSERT(renderbuffer != NULL); - - switch (pname) - { - case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: - *params = attachmentObjectType; - break; - - case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: - if (attachmentObjectType != GL_RENDERBUFFER && attachmentObjectType != GL_TEXTURE) - { - return gl::error(GL_INVALID_ENUM); - } - *params = attachmentHandle; - break; - - case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: - if (attachmentObjectType != GL_TEXTURE) - { - return gl::error(GL_INVALID_ENUM); - } - *params = attachmentLevel; - break; - - case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: - if (attachmentObjectType != GL_TEXTURE) - { - return gl::error(GL_INVALID_ENUM); - } - *params = gl::IsCubemapTextureTarget(attachmentType) ? attachmentType : 0; - break; - - case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE: - *params = renderbuffer->getRedSize(); - break; - - case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE: - *params = renderbuffer->getGreenSize(); - break; - - case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE: - *params = renderbuffer->getBlueSize(); - break; - - case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE: - *params = renderbuffer->getAlphaSize(); - break; - - case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE: - *params = renderbuffer->getDepthSize(); - break; - - case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE: - *params = renderbuffer->getStencilSize(); - break; - - case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE: - if (attachment == GL_DEPTH_STENCIL) - { - gl::error(GL_INVALID_OPERATION); - } - *params = renderbuffer->getComponentType(); - break; - - case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING: - *params = renderbuffer->getColorEncoding(); - break; - - case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER: - if (attachmentObjectType != GL_TEXTURE) - { - return gl::error(GL_INVALID_ENUM); - } - *params = attachmentLayer; - break; - - default: - UNREACHABLE(); - break; + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } } } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + else + { + ASSERT(attachmentObjectType == GL_RENDERBUFFER || attachmentObjectType == GL_TEXTURE || + attachmentObjectType == GL_FRAMEBUFFER_DEFAULT); + ASSERT(attachmentObject != NULL); + + switch (pname) + { + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: + *params = attachmentObjectType; + break; + + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: + if (attachmentObjectType != GL_RENDERBUFFER && attachmentObjectType != GL_TEXTURE) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + *params = attachmentHandle; + break; + + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: + if (attachmentObjectType != GL_TEXTURE) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + *params = attachmentLevel; + break; + + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: + if (attachmentObjectType != GL_TEXTURE) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + *params = gl::IsCubemapTextureTarget(attachmentType) ? attachmentType : 0; + break; + + case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE: + *params = attachmentObject->getRedSize(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE: + *params = attachmentObject->getGreenSize(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE: + *params = attachmentObject->getBlueSize(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE: + *params = attachmentObject->getAlphaSize(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE: + *params = attachmentObject->getDepthSize(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE: + *params = attachmentObject->getStencilSize(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE: + if (attachment == GL_DEPTH_STENCIL) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + *params = attachmentObject->getComponentType(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING: + *params = attachmentObject->getColorEncoding(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER: + if (attachmentObjectType != GL_TEXTURE) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + *params = attachmentLayer; + break; + + default: + UNREACHABLE(); + break; + } + } } } @@ -2924,54 +2393,39 @@ GLenum __stdcall glGetGraphicsResetStatusEXT(void) { EVENT("()"); - ANGLE_TRY - { - gl::Context *context = gl::getContext(); + gl::Context *context = gl::getContext(); - if (context) - { - return context->getResetStatus(); - } - - return GL_NO_ERROR; - } - ANGLE_CATCH_ALL + if (context) { - return GL_OUT_OF_MEMORY; + return context->getResetStatus(); } + + return GL_NO_ERROR; } void __stdcall glGetIntegerv(GLenum pname, GLint* params) { EVENT("(GLenum pname = 0x%X, GLint* params = 0x%0.8p)", pname, params); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); + GLenum nativeType; + unsigned int numParams = 0; - if (context) + if (!ValidateStateQuery(context, pname, &nativeType, &numParams)) { - GLenum nativeType; - unsigned int numParams = 0; - - if (!ValidateStateQuery(context, pname, &nativeType, &numParams)) - { - return; - } - - if (nativeType == GL_INT) - { - context->getIntegerv(pname, params); - } - else - { - CastStateValues(context, nativeType, pname, numParams, params); - } + return; + } + + if (nativeType == GL_INT) + { + context->getIntegerv(pname, params); + } + else + { + CastStateValues(context, nativeType, pname, numParams, params); } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -2979,87 +2433,83 @@ void __stdcall glGetProgramiv(GLuint program, GLenum pname, GLint* params) { EVENT("(GLuint program = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", program, pname, params); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::Program *programObject = context->getProgram(program); - if (context) + if (!programObject) { - gl::Program *programObject = context->getProgram(program); - - if (!programObject) - { - return gl::error(GL_INVALID_VALUE); - } - - if (context->getClientVersion() < 3) - { - switch (pname) - { - case GL_ACTIVE_UNIFORM_BLOCKS: - case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH: - case GL_TRANSFORM_FEEDBACK_BUFFER_MODE: - case GL_TRANSFORM_FEEDBACK_VARYINGS: - case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH: - return gl::error(GL_INVALID_ENUM); - } - } + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + if (context->getClientVersion() < 3) + { switch (pname) { - case GL_DELETE_STATUS: - *params = programObject->isFlaggedForDeletion(); - return; - case GL_LINK_STATUS: - *params = programObject->isLinked(); - return; - case GL_VALIDATE_STATUS: - *params = programObject->isValidated(); - return; - case GL_INFO_LOG_LENGTH: - *params = programObject->getInfoLogLength(); - return; - case GL_ATTACHED_SHADERS: - *params = programObject->getAttachedShadersCount(); - return; - case GL_ACTIVE_ATTRIBUTES: - *params = programObject->getActiveAttributeCount(); - return; - case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH: - *params = programObject->getActiveAttributeMaxLength(); - return; - case GL_ACTIVE_UNIFORMS: - *params = programObject->getActiveUniformCount(); - return; - case GL_ACTIVE_UNIFORM_MAX_LENGTH: - *params = programObject->getActiveUniformMaxLength(); - return; - case GL_PROGRAM_BINARY_LENGTH_OES: - *params = programObject->getProgramBinaryLength(); - return; case GL_ACTIVE_UNIFORM_BLOCKS: - *params = programObject->getActiveUniformBlockCount(); - return; case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH: - *params = programObject->getActiveUniformBlockMaxLength(); - break; case GL_TRANSFORM_FEEDBACK_BUFFER_MODE: - *params = programObject->getTransformFeedbackBufferMode(); - break; case GL_TRANSFORM_FEEDBACK_VARYINGS: - *params = programObject->getTransformFeedbackVaryingCount(); - break; case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH: - *params = programObject->getTransformFeedbackVaryingMaxLength(); - break; - default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + switch (pname) + { + case GL_DELETE_STATUS: + *params = programObject->isFlaggedForDeletion(); + return; + case GL_LINK_STATUS: + *params = programObject->isLinked(); + return; + case GL_VALIDATE_STATUS: + *params = programObject->isValidated(); + return; + case GL_INFO_LOG_LENGTH: + *params = programObject->getInfoLogLength(); + return; + case GL_ATTACHED_SHADERS: + *params = programObject->getAttachedShadersCount(); + return; + case GL_ACTIVE_ATTRIBUTES: + *params = programObject->getActiveAttributeCount(); + return; + case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH: + *params = programObject->getActiveAttributeMaxLength(); + return; + case GL_ACTIVE_UNIFORMS: + *params = programObject->getActiveUniformCount(); + return; + case GL_ACTIVE_UNIFORM_MAX_LENGTH: + *params = programObject->getActiveUniformMaxLength(); + return; + case GL_PROGRAM_BINARY_LENGTH_OES: + *params = programObject->getProgramBinaryLength(); + return; + case GL_ACTIVE_UNIFORM_BLOCKS: + *params = programObject->getActiveUniformBlockCount(); + return; + case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH: + *params = programObject->getActiveUniformBlockMaxLength(); + break; + case GL_TRANSFORM_FEEDBACK_BUFFER_MODE: + *params = programObject->getTransformFeedbackBufferMode(); + break; + case GL_TRANSFORM_FEEDBACK_VARYINGS: + *params = programObject->getTransformFeedbackVaryingCount(); + break; + case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH: + *params = programObject->getTransformFeedbackVaryingMaxLength(); + break; + + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } } } @@ -3068,30 +2518,24 @@ void __stdcall glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* len EVENT("(GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)", program, bufsize, length, infolog); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (bufsize < 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - gl::Context *context = gl::getNonLostContext(); + gl::Program *programObject = context->getProgram(program); - if (context) + if (!programObject) { - gl::Program *programObject = context->getProgram(program); - - if (!programObject) - { - return gl::error(GL_INVALID_VALUE); - } - - programObject->getInfoLog(bufsize, length, infolog); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + programObject->getInfoLog(bufsize, length, infolog); } } @@ -3099,31 +2543,25 @@ void __stdcall glGetQueryivEXT(GLenum target, GLenum pname, GLint *params) { EVENT("GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", target, pname, params); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!ValidQueryType(context, target)) { - if (!ValidQueryType(context, target)) - { - return gl::error(GL_INVALID_ENUM); - } - - switch (pname) - { - case GL_CURRENT_QUERY_EXT: - params[0] = context->getActiveQueryId(target); - break; - - default: - return gl::error(GL_INVALID_ENUM); - } + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + + switch (pname) + { + case GL_CURRENT_QUERY_EXT: + params[0] = context->getState().getActiveQueryId(target); + break; + + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -3131,40 +2569,35 @@ void __stdcall glGetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params) { EVENT("(GLuint id = %d, GLenum pname = 0x%X, GLuint *params = 0x%0.8p)", id, pname, params); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::Query *queryObject = context->getQuery(id, false, GL_NONE); - if (context) + if (!queryObject) { - gl::Query *queryObject = context->getQuery(id, false, GL_NONE); - - if (!queryObject) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (context->getActiveQueryId(queryObject->getType()) == id) - { - return gl::error(GL_INVALID_OPERATION); - } - - switch(pname) - { - case GL_QUERY_RESULT_EXT: - params[0] = queryObject->getResult(); - break; - case GL_QUERY_RESULT_AVAILABLE_EXT: - params[0] = queryObject->isResultAvailable(); - break; - default: - return gl::error(GL_INVALID_ENUM); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + if (context->getState().getActiveQueryId(queryObject->getType()) == id) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + switch(pname) + { + case GL_QUERY_RESULT_EXT: + params[0] = queryObject->getResult(); + break; + case GL_QUERY_RESULT_AVAILABLE_EXT: + params[0] = queryObject->isResultAvailable(); + break; + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -3172,53 +2605,48 @@ void __stdcall glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* { EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (target != GL_RENDERBUFFER) { - if (target != GL_RENDERBUFFER) - { - return gl::error(GL_INVALID_ENUM); - } - - if (context->getRenderbufferHandle() == 0) - { - return gl::error(GL_INVALID_OPERATION); - } - - gl::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getRenderbufferHandle()); - - switch (pname) - { - case GL_RENDERBUFFER_WIDTH: *params = renderbuffer->getWidth(); break; - case GL_RENDERBUFFER_HEIGHT: *params = renderbuffer->getHeight(); break; - case GL_RENDERBUFFER_INTERNAL_FORMAT: *params = renderbuffer->getInternalFormat(); break; - case GL_RENDERBUFFER_RED_SIZE: *params = renderbuffer->getRedSize(); break; - case GL_RENDERBUFFER_GREEN_SIZE: *params = renderbuffer->getGreenSize(); break; - case GL_RENDERBUFFER_BLUE_SIZE: *params = renderbuffer->getBlueSize(); break; - case GL_RENDERBUFFER_ALPHA_SIZE: *params = renderbuffer->getAlphaSize(); break; - case GL_RENDERBUFFER_DEPTH_SIZE: *params = renderbuffer->getDepthSize(); break; - case GL_RENDERBUFFER_STENCIL_SIZE: *params = renderbuffer->getStencilSize(); break; - case GL_RENDERBUFFER_SAMPLES_ANGLE: - if (context->getMaxSupportedSamples() != 0) - { - *params = renderbuffer->getSamples(); - } - else - { - return gl::error(GL_INVALID_ENUM); - } - break; - default: - return gl::error(GL_INVALID_ENUM); - } + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + + if (context->getState().getRenderbufferId() == 0) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + gl::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getState().getRenderbufferId()); + + switch (pname) + { + case GL_RENDERBUFFER_WIDTH: *params = renderbuffer->getWidth(); break; + case GL_RENDERBUFFER_HEIGHT: *params = renderbuffer->getHeight(); break; + case GL_RENDERBUFFER_INTERNAL_FORMAT: *params = renderbuffer->getInternalFormat(); break; + case GL_RENDERBUFFER_RED_SIZE: *params = renderbuffer->getRedSize(); break; + case GL_RENDERBUFFER_GREEN_SIZE: *params = renderbuffer->getGreenSize(); break; + case GL_RENDERBUFFER_BLUE_SIZE: *params = renderbuffer->getBlueSize(); break; + case GL_RENDERBUFFER_ALPHA_SIZE: *params = renderbuffer->getAlphaSize(); break; + case GL_RENDERBUFFER_DEPTH_SIZE: *params = renderbuffer->getDepthSize(); break; + case GL_RENDERBUFFER_STENCIL_SIZE: *params = renderbuffer->getStencilSize(); break; + + case GL_RENDERBUFFER_SAMPLES_ANGLE: + if (!context->getExtensions().framebufferMultisample) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + *params = renderbuffer->getSamples(); + break; + + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -3226,47 +2654,42 @@ void __stdcall glGetShaderiv(GLuint shader, GLenum pname, GLint* params) { EVENT("(GLuint shader = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", shader, pname, params); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::Shader *shaderObject = context->getShader(shader); - if (context) + if (!shaderObject) { - gl::Shader *shaderObject = context->getShader(shader); - - if (!shaderObject) - { - return gl::error(GL_INVALID_VALUE); - } - - switch (pname) - { - case GL_SHADER_TYPE: - *params = shaderObject->getType(); - return; - case GL_DELETE_STATUS: - *params = shaderObject->isFlaggedForDeletion(); - return; - case GL_COMPILE_STATUS: - *params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE; - return; - case GL_INFO_LOG_LENGTH: - *params = shaderObject->getInfoLogLength(); - return; - case GL_SHADER_SOURCE_LENGTH: - *params = shaderObject->getSourceLength(); - return; - case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE: - *params = shaderObject->getTranslatedSourceLength(); - return; - default: - return gl::error(GL_INVALID_ENUM); - } + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + switch (pname) + { + case GL_SHADER_TYPE: + *params = shaderObject->getType(); + return; + case GL_DELETE_STATUS: + *params = shaderObject->isFlaggedForDeletion(); + return; + case GL_COMPILE_STATUS: + *params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE; + return; + case GL_INFO_LOG_LENGTH: + *params = shaderObject->getInfoLogLength(); + return; + case GL_SHADER_SOURCE_LENGTH: + *params = shaderObject->getSourceLength(); + return; + case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE: + *params = shaderObject->getTranslatedSourceLength(); + return; + + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -3275,30 +2698,24 @@ void __stdcall glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* lengt EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)", shader, bufsize, length, infolog); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (bufsize < 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - gl::Context *context = gl::getNonLostContext(); + gl::Shader *shaderObject = context->getShader(shader); - if (context) + if (!shaderObject) { - gl::Shader *shaderObject = context->getShader(shader); - - if (!shaderObject) - { - return gl::error(GL_INVALID_VALUE); - } - - shaderObject->getInfoLog(bufsize, length, infolog); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + shaderObject->getInfoLog(bufsize, length, infolog); } } @@ -3307,15 +2724,18 @@ void __stdcall glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontyp EVENT("(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint* range = 0x%0.8p, GLint* precision = 0x%0.8p)", shadertype, precisiontype, range, precision); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { switch (shadertype) { case GL_VERTEX_SHADER: case GL_FRAGMENT_SHADER: break; + default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } switch (precisiontype) @@ -3328,6 +2748,7 @@ void __stdcall glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontyp range[1] = 127; *precision = 23; break; + case GL_LOW_INT: case GL_MEDIUM_INT: case GL_HIGH_INT: @@ -3337,14 +2758,12 @@ void __stdcall glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontyp range[1] = 24; *precision = 0; break; + default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source) @@ -3352,30 +2771,24 @@ void __stdcall glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)", shader, bufsize, length, source); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (bufsize < 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - gl::Context *context = gl::getNonLostContext(); + gl::Shader *shaderObject = context->getShader(shader); - if (context) + if (!shaderObject) { - gl::Shader *shaderObject = context->getShader(shader); - - if (!shaderObject) - { - return gl::error(GL_INVALID_OPERATION); - } - - shaderObject->getSource(bufsize, length, source); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + shaderObject->getSource(bufsize, length, source); } } @@ -3384,30 +2797,24 @@ void __stdcall glGetTranslatedShaderSourceANGLE(GLuint shader, GLsizei bufsize, EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)", shader, bufsize, length, source); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (bufsize < 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - gl::Context *context = gl::getNonLostContext(); + gl::Shader *shaderObject = context->getShader(shader); - if (context) + if (!shaderObject) { - gl::Shader *shaderObject = context->getShader(shader); - - if (!shaderObject) - { - return gl::error(GL_INVALID_OPERATION); - } - - shaderObject->getTranslatedSource(bufsize, length, source); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + shaderObject->getTranslatedSource(bufsize, length, source); } } @@ -3415,43 +2822,45 @@ const GLubyte* __stdcall glGetString(GLenum name) { EVENT("(GLenum name = 0x%X)", name); - ANGLE_TRY - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - switch (name) - { - case GL_VENDOR: - return (GLubyte*)"Google Inc."; - case GL_RENDERER: - return (GLubyte*)((context != NULL) ? context->getRendererString() : "ANGLE"); - case GL_VERSION: - if (context->getClientVersion() == 2) - { - return (GLubyte*)"OpenGL ES 2.0 (ANGLE " ANGLE_VERSION_STRING ")"; - } - else - { - return (GLubyte*)"OpenGL ES 3.0 (ANGLE " ANGLE_VERSION_STRING ")"; - } - case GL_SHADING_LANGUAGE_VERSION: - if (context->getClientVersion() == 2) - { - return (GLubyte*)"OpenGL ES GLSL ES 1.00 (ANGLE " ANGLE_VERSION_STRING ")"; - } - else - { - return (GLubyte*)"OpenGL ES GLSL ES 3.00 (ANGLE " ANGLE_VERSION_STRING ")"; - } - case GL_EXTENSIONS: - return (GLubyte*)((context != NULL) ? context->getCombinedExtensionsString() : ""); - default: - return gl::error(GL_INVALID_ENUM, (GLubyte*)NULL); - } - } - ANGLE_CATCH_ALL + switch (name) { - return gl::error(GL_OUT_OF_MEMORY, (GLubyte*)NULL); + case GL_VENDOR: + return (GLubyte*)"Google Inc."; + + case GL_RENDERER: + return (GLubyte*)((context != NULL) ? context->getRendererString().c_str() : "ANGLE"); + + case GL_VERSION: + if (context->getClientVersion() == 2) + { + return (GLubyte*)"OpenGL ES 2.0 (ANGLE " ANGLE_VERSION_STRING ")"; + } + else + { + return (GLubyte*)"OpenGL ES 3.0 (ANGLE " ANGLE_VERSION_STRING ")"; + } + + case GL_SHADING_LANGUAGE_VERSION: + if (context->getClientVersion() == 2) + { + return (GLubyte*)"OpenGL ES GLSL ES 1.00 (ANGLE " ANGLE_VERSION_STRING ")"; + } + else + { + return (GLubyte*)"OpenGL ES GLSL ES 3.00 (ANGLE " ANGLE_VERSION_STRING ")"; + } + + case GL_EXTENSIONS: + return (GLubyte*)((context != NULL) ? context->getExtensionString().c_str() : ""); + + default: + if (context) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + } + return NULL; } } @@ -3459,125 +2868,131 @@ void __stdcall glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params) { EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", target, pname, params); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::Texture *texture = context->getTargetTexture(target); - if (context) + if (!texture) { - gl::Texture *texture = context->getTargetTexture(target); - - if (!texture) - { - return gl::error(GL_INVALID_ENUM); - } - - switch (pname) - { - case GL_TEXTURE_MAG_FILTER: - *params = (GLfloat)texture->getMagFilter(); - break; - case GL_TEXTURE_MIN_FILTER: - *params = (GLfloat)texture->getMinFilter(); - break; - case GL_TEXTURE_WRAP_S: - *params = (GLfloat)texture->getWrapS(); - break; - case GL_TEXTURE_WRAP_T: - *params = (GLfloat)texture->getWrapT(); - break; - case GL_TEXTURE_WRAP_R: - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_ENUM); - } - *params = (GLfloat)texture->getWrapR(); - break; - case GL_TEXTURE_IMMUTABLE_FORMAT: - // Exposed to ES2.0 through EXT_texture_storage, no client version validation. - *params = (GLfloat)(texture->isImmutable() ? GL_TRUE : GL_FALSE); - break; - case GL_TEXTURE_IMMUTABLE_LEVELS: - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_ENUM); - } - *params = (GLfloat)texture->immutableLevelCount(); - break; - case GL_TEXTURE_USAGE_ANGLE: - *params = (GLfloat)texture->getUsage(); - break; - case GL_TEXTURE_MAX_ANISOTROPY_EXT: - if (!context->supportsTextureFilterAnisotropy()) - { - return gl::error(GL_INVALID_ENUM); - } - *params = (GLfloat)texture->getMaxAnisotropy(); - break; - case GL_TEXTURE_SWIZZLE_R: - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_ENUM); - } - *params = (GLfloat)texture->getSwizzleRed(); - break; - case GL_TEXTURE_SWIZZLE_G: - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_ENUM); - } - *params = (GLfloat)texture->getSwizzleGreen(); - break; - case GL_TEXTURE_SWIZZLE_B: - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_ENUM); - } - *params = (GLfloat)texture->getSwizzleBlue(); - break; - case GL_TEXTURE_SWIZZLE_A: - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_ENUM); - } - *params = (GLfloat)texture->getSwizzleAlpha(); - break; - case GL_TEXTURE_BASE_LEVEL: - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_ENUM); - } - *params = (GLfloat)texture->getBaseLevel(); - break; - case GL_TEXTURE_MAX_LEVEL: - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_ENUM); - } - *params = (GLfloat)texture->getMaxLevel(); - break; - case GL_TEXTURE_MIN_LOD: - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_ENUM); - } - *params = texture->getMinLod(); - break; - case GL_TEXTURE_MAX_LOD: - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_ENUM); - } - *params = texture->getMaxLod(); - break; - default: - return gl::error(GL_INVALID_ENUM); - } + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + + switch (pname) + { + case GL_TEXTURE_MAG_FILTER: + *params = (GLfloat)texture->getSamplerState().magFilter; + break; + case GL_TEXTURE_MIN_FILTER: + *params = (GLfloat)texture->getSamplerState().minFilter; + break; + case GL_TEXTURE_WRAP_S: + *params = (GLfloat)texture->getSamplerState().wrapS; + break; + case GL_TEXTURE_WRAP_T: + *params = (GLfloat)texture->getSamplerState().wrapT; + break; + case GL_TEXTURE_WRAP_R: + if (context->getClientVersion() < 3) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + *params = (GLfloat)texture->getSamplerState().wrapR; + break; + case GL_TEXTURE_IMMUTABLE_FORMAT: + // Exposed to ES2.0 through EXT_texture_storage, no client version validation. + *params = (GLfloat)(texture->isImmutable() ? GL_TRUE : GL_FALSE); + break; + case GL_TEXTURE_IMMUTABLE_LEVELS: + if (context->getClientVersion() < 3) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + *params = (GLfloat)texture->immutableLevelCount(); + break; + case GL_TEXTURE_USAGE_ANGLE: + *params = (GLfloat)texture->getUsage(); + break; + case GL_TEXTURE_MAX_ANISOTROPY_EXT: + if (!context->getExtensions().textureFilterAnisotropic) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + *params = (GLfloat)texture->getSamplerState().maxAnisotropy; + break; + case GL_TEXTURE_SWIZZLE_R: + if (context->getClientVersion() < 3) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + *params = (GLfloat)texture->getSamplerState().swizzleRed; + break; + case GL_TEXTURE_SWIZZLE_G: + if (context->getClientVersion() < 3) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + *params = (GLfloat)texture->getSamplerState().swizzleGreen; + break; + case GL_TEXTURE_SWIZZLE_B: + if (context->getClientVersion() < 3) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + *params = (GLfloat)texture->getSamplerState().swizzleBlue; + break; + case GL_TEXTURE_SWIZZLE_A: + if (context->getClientVersion() < 3) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + *params = (GLfloat)texture->getSamplerState().swizzleAlpha; + break; + case GL_TEXTURE_BASE_LEVEL: + if (context->getClientVersion() < 3) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + *params = (GLfloat)texture->getSamplerState().baseLevel; + break; + case GL_TEXTURE_MAX_LEVEL: + if (context->getClientVersion() < 3) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + *params = (GLfloat)texture->getSamplerState().maxLevel; + break; + case GL_TEXTURE_MIN_LOD: + if (context->getClientVersion() < 3) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + *params = texture->getSamplerState().minLod; + break; + case GL_TEXTURE_MAX_LOD: + if (context->getClientVersion() < 3) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + *params = texture->getSamplerState().maxLod; + break; + + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -3585,125 +3000,131 @@ void __stdcall glGetTexParameteriv(GLenum target, GLenum pname, GLint* params) { EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::Texture *texture = context->getTargetTexture(target); - if (context) + if (!texture) { - gl::Texture *texture = context->getTargetTexture(target); - - if (!texture) - { - return gl::error(GL_INVALID_ENUM); - } - - switch (pname) - { - case GL_TEXTURE_MAG_FILTER: - *params = texture->getMagFilter(); - break; - case GL_TEXTURE_MIN_FILTER: - *params = texture->getMinFilter(); - break; - case GL_TEXTURE_WRAP_S: - *params = texture->getWrapS(); - break; - case GL_TEXTURE_WRAP_T: - *params = texture->getWrapT(); - break; - case GL_TEXTURE_WRAP_R: - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_ENUM); - } - *params = texture->getWrapR(); - break; - case GL_TEXTURE_IMMUTABLE_FORMAT: - // Exposed to ES2.0 through EXT_texture_storage, no client version validation. - *params = texture->isImmutable() ? GL_TRUE : GL_FALSE; - break; - case GL_TEXTURE_IMMUTABLE_LEVELS: - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_ENUM); - } - *params = texture->immutableLevelCount(); - break; - case GL_TEXTURE_USAGE_ANGLE: - *params = texture->getUsage(); - break; - case GL_TEXTURE_MAX_ANISOTROPY_EXT: - if (!context->supportsTextureFilterAnisotropy()) - { - return gl::error(GL_INVALID_ENUM); - } - *params = (GLint)texture->getMaxAnisotropy(); - break; - case GL_TEXTURE_SWIZZLE_R: - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_ENUM); - } - *params = texture->getSwizzleRed(); - break; - case GL_TEXTURE_SWIZZLE_G: - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_ENUM); - } - *params = texture->getSwizzleGreen(); - break; - case GL_TEXTURE_SWIZZLE_B: - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_ENUM); - } - *params = texture->getSwizzleBlue(); - break; - case GL_TEXTURE_SWIZZLE_A: - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_ENUM); - } - *params = texture->getSwizzleAlpha(); - break; - case GL_TEXTURE_BASE_LEVEL: - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_ENUM); - } - *params = texture->getBaseLevel(); - break; - case GL_TEXTURE_MAX_LEVEL: - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_ENUM); - } - *params = texture->getMaxLevel(); - break; - case GL_TEXTURE_MIN_LOD: - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_ENUM); - } - *params = (GLint)texture->getMinLod(); - break; - case GL_TEXTURE_MAX_LOD: - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_ENUM); - } - *params = (GLint)texture->getMaxLod(); - break; - default: - return gl::error(GL_INVALID_ENUM); - } + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + + switch (pname) + { + case GL_TEXTURE_MAG_FILTER: + *params = texture->getSamplerState().magFilter; + break; + case GL_TEXTURE_MIN_FILTER: + *params = texture->getSamplerState().minFilter; + break; + case GL_TEXTURE_WRAP_S: + *params = texture->getSamplerState().wrapS; + break; + case GL_TEXTURE_WRAP_T: + *params = texture->getSamplerState().wrapT; + break; + case GL_TEXTURE_WRAP_R: + if (context->getClientVersion() < 3) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + *params = texture->getSamplerState().wrapR; + break; + case GL_TEXTURE_IMMUTABLE_FORMAT: + // Exposed to ES2.0 through EXT_texture_storage, no client version validation. + *params = texture->isImmutable() ? GL_TRUE : GL_FALSE; + break; + case GL_TEXTURE_IMMUTABLE_LEVELS: + if (context->getClientVersion() < 3) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + *params = texture->immutableLevelCount(); + break; + case GL_TEXTURE_USAGE_ANGLE: + *params = texture->getUsage(); + break; + case GL_TEXTURE_MAX_ANISOTROPY_EXT: + if (!context->getExtensions().textureFilterAnisotropic) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + *params = (GLint)texture->getSamplerState().maxAnisotropy; + break; + case GL_TEXTURE_SWIZZLE_R: + if (context->getClientVersion() < 3) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + *params = texture->getSamplerState().swizzleRed; + break; + case GL_TEXTURE_SWIZZLE_G: + if (context->getClientVersion() < 3) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + *params = texture->getSamplerState().swizzleGreen; + break; + case GL_TEXTURE_SWIZZLE_B: + if (context->getClientVersion() < 3) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + *params = texture->getSamplerState().swizzleBlue; + break; + case GL_TEXTURE_SWIZZLE_A: + if (context->getClientVersion() < 3) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + *params = texture->getSamplerState().swizzleAlpha; + break; + case GL_TEXTURE_BASE_LEVEL: + if (context->getClientVersion() < 3) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + *params = texture->getSamplerState().baseLevel; + break; + case GL_TEXTURE_MAX_LEVEL: + if (context->getClientVersion() < 3) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + *params = texture->getSamplerState().maxLevel; + break; + case GL_TEXTURE_MIN_LOD: + if (context->getClientVersion() < 3) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + *params = (GLint)texture->getSamplerState().minLod; + break; + case GL_TEXTURE_MAX_LOD: + if (context->getClientVersion() < 3) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + *params = (GLint)texture->getSamplerState().maxLod; + break; + + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -3712,44 +3133,20 @@ void __stdcall glGetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSiz EVENT("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLfloat* params = 0x%0.8p)", program, location, bufSize, params); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - if (bufSize < 0) + if (!ValidateGetnUniformfvEXT(context, program, location, bufSize, params)) { - return gl::error(GL_INVALID_VALUE); + return; } - gl::Context *context = gl::getNonLostContext(); + gl::Program *programObject = context->getProgram(program); + ASSERT(programObject); + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + ASSERT(programBinary); - if (context) - { - if (program == 0) - { - return gl::error(GL_INVALID_VALUE); - } - - gl::Program *programObject = context->getProgram(program); - - if (!programObject || !programObject->isLinked()) - { - return gl::error(GL_INVALID_OPERATION); - } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (!programBinary) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (!programBinary->getUniformfv(location, &bufSize, params)) - { - return gl::error(GL_INVALID_OPERATION); - } - } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + programBinary->getUniformfv(location, params); } } @@ -3757,85 +3154,42 @@ void __stdcall glGetUniformfv(GLuint program, GLint location, GLfloat* params) { EVENT("(GLuint program = %d, GLint location = %d, GLfloat* params = 0x%0.8p)", program, location, params); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!ValidateGetUniformfv(context, program, location, params)) { - if (program == 0) - { - return gl::error(GL_INVALID_VALUE); - } - - gl::Program *programObject = context->getProgram(program); - - if (!programObject || !programObject->isLinked()) - { - return gl::error(GL_INVALID_OPERATION); - } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (!programBinary) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (!programBinary->getUniformfv(location, NULL, params)) - { - return gl::error(GL_INVALID_OPERATION); - } + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + gl::Program *programObject = context->getProgram(program); + ASSERT(programObject); + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + ASSERT(programBinary); + + programBinary->getUniformfv(location, params); } } void __stdcall glGetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint* params) { - EVENT("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = 0x%0.8p)", + EVENT("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = 0x%0.8p)", program, location, bufSize, params); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - if (bufSize < 0) + if (!ValidateGetnUniformivEXT(context, program, location, bufSize, params)) { - return gl::error(GL_INVALID_VALUE); + return; } - gl::Context *context = gl::getNonLostContext(); + gl::Program *programObject = context->getProgram(program); + ASSERT(programObject); + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + ASSERT(programBinary); - if (context) - { - if (program == 0) - { - return gl::error(GL_INVALID_VALUE); - } - - gl::Program *programObject = context->getProgram(program); - - if (!programObject || !programObject->isLinked()) - { - return gl::error(GL_INVALID_OPERATION); - } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (!programBinary) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (!programBinary->getUniformiv(location, &bufSize, params)) - { - return gl::error(GL_INVALID_OPERATION); - } - } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + programBinary->getUniformiv(location, params); } } @@ -3843,83 +3197,59 @@ void __stdcall glGetUniformiv(GLuint program, GLint location, GLint* params) { EVENT("(GLuint program = %d, GLint location = %d, GLint* params = 0x%0.8p)", program, location, params); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!ValidateGetUniformiv(context, program, location, params)) { - if (program == 0) - { - return gl::error(GL_INVALID_VALUE); - } - - gl::Program *programObject = context->getProgram(program); - - if (!programObject || !programObject->isLinked()) - { - return gl::error(GL_INVALID_OPERATION); - } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (!programBinary) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (!programBinary->getUniformiv(location, NULL, params)) - { - return gl::error(GL_INVALID_OPERATION); - } + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + gl::Program *programObject = context->getProgram(program); + ASSERT(programObject); + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + ASSERT(programBinary); + + programBinary->getUniformiv(location, params); } } -int __stdcall glGetUniformLocation(GLuint program, const GLchar* name) +GLint __stdcall glGetUniformLocation(GLuint program, const GLchar* name) { EVENT("(GLuint program = %d, const GLchar* name = 0x%0.8p)", program, name); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - if (strstr(name, "gl_") == name) { return -1; } - if (context) + gl::Program *programObject = context->getProgram(program); + + if (!programObject) { - gl::Program *programObject = context->getProgram(program); - - if (!programObject) + if (context->getShader(program)) { - if (context->getShader(program)) - { - return gl::error(GL_INVALID_OPERATION, -1); - } - else - { - return gl::error(GL_INVALID_VALUE, -1); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return -1; } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (!programObject->isLinked() || !programBinary) + else { - return gl::error(GL_INVALID_OPERATION, -1); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return -1; } - - return programBinary->getUniformLocation(name); } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY, -1); + + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + if (!programObject->isLinked() || !programBinary) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return -1; + } + + return programBinary->getUniformLocation(name); } return -1; @@ -3929,41 +3259,33 @@ void __stdcall glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params) { EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", index, pname, params); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (index >= gl::MAX_VERTEX_ATTRIBS) { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - return gl::error(GL_INVALID_VALUE); - } + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } - const gl::VertexAttribute &attribState = context->getVertexAttribState(index); + const gl::VertexAttribute &attribState = context->getState().getVertexAttribState(index); + if (!gl::ValidateGetVertexAttribParameters(context, pname)) + { + return; + } - if (!gl::ValidateGetVertexAttribParameters(pname, context->getClientVersion())) + if (pname == GL_CURRENT_VERTEX_ATTRIB) + { + const gl::VertexAttribCurrentValueData ¤tValueData = context->getState().getVertexAttribCurrentValue(index); + for (int i = 0; i < 4; ++i) { - return; - } - - if (pname == GL_CURRENT_VERTEX_ATTRIB) - { - const gl::VertexAttribCurrentValueData ¤tValueData = context->getVertexAttribCurrentValue(index); - for (int i = 0; i < 4; ++i) - { - params[i] = currentValueData.FloatValues[i]; - } - } - else - { - *params = attribState.querySingleParameter(pname); + params[i] = currentValueData.FloatValues[i]; } } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + else + { + *params = gl::QuerySingleVertexAttributeParameter(attribState, pname); + } } } @@ -3971,42 +3293,35 @@ void __stdcall glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params) { EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", index, pname, params); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (index >= gl::MAX_VERTEX_ATTRIBS) { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - return gl::error(GL_INVALID_VALUE); - } + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } - const gl::VertexAttribute &attribState = context->getVertexAttribState(index); + const gl::VertexAttribute &attribState = context->getState().getVertexAttribState(index); - if (!gl::ValidateGetVertexAttribParameters(pname, context->getClientVersion())) - { - return; - } + if (!gl::ValidateGetVertexAttribParameters(context, pname)) + { + return; + } - if (pname == GL_CURRENT_VERTEX_ATTRIB) + if (pname == GL_CURRENT_VERTEX_ATTRIB) + { + const gl::VertexAttribCurrentValueData ¤tValueData = context->getState().getVertexAttribCurrentValue(index); + for (int i = 0; i < 4; ++i) { - const gl::VertexAttribCurrentValueData ¤tValueData = context->getVertexAttribCurrentValue(index); - for (int i = 0; i < 4; ++i) - { - float currentValue = currentValueData.FloatValues[i]; - params[i] = gl::iround(currentValue); - } - } - else - { - *params = attribState.querySingleParameter(pname); + float currentValue = currentValueData.FloatValues[i]; + params[i] = gl::iround(currentValue); } } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + else + { + *params = gl::QuerySingleVertexAttributeParameter(attribState, pname); + } } } @@ -4014,28 +3329,22 @@ void __stdcall glGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** po { EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLvoid** pointer = 0x%0.8p)", index, pname, pointer); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (index >= gl::MAX_VERTEX_ATTRIBS) { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - return gl::error(GL_INVALID_VALUE); - } - - if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER) - { - return gl::error(GL_INVALID_ENUM); - } - - *pointer = const_cast(context->getVertexAttribPointer(index)); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + + *pointer = const_cast(context->getState().getVertexAttribPointer(index)); } } @@ -4043,7 +3352,8 @@ void __stdcall glHint(GLenum target, GLenum mode) { EVENT("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { switch (mode) { @@ -4051,51 +3361,43 @@ void __stdcall glHint(GLenum target, GLenum mode) case GL_NICEST: case GL_DONT_CARE: break; + default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - gl::Context *context = gl::getNonLostContext(); switch (target) { case GL_GENERATE_MIPMAP_HINT: - if (context) context->setGenerateMipmapHint(mode); + context->getState().setGenerateMipmapHint(mode); break; + case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: - if (context) context->setFragmentShaderDerivativeHint(mode); + context->getState().setFragmentShaderDerivativeHint(mode); break; + default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); - } } GLboolean __stdcall glIsBuffer(GLuint buffer) { EVENT("(GLuint buffer = %d)", buffer); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context && buffer) { - gl::Context *context = gl::getNonLostContext(); + gl::Buffer *bufferObject = context->getBuffer(buffer); - if (context && buffer) + if (bufferObject) { - gl::Buffer *bufferObject = context->getBuffer(buffer); - - if (bufferObject) - { - return GL_TRUE; - } + return GL_TRUE; } } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); - } return GL_FALSE; } @@ -4104,23 +3406,16 @@ GLboolean __stdcall glIsEnabled(GLenum cap) { EVENT("(GLenum cap = 0x%X)", cap); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!ValidCap(context, cap)) { - if (!ValidCap(context, cap)) - { - return gl::error(GL_INVALID_ENUM, false); - } - - return context->getCap(cap); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return GL_FALSE; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY, false); + + return context->getState().getEnableFeature(cap); } return false; @@ -4130,25 +3425,17 @@ GLboolean __stdcall glIsFenceNV(GLuint fence) { EVENT("(GLuint fence = %d)", fence); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::FenceNV *fenceObject = context->getFenceNV(fence); - if (context) + if (fenceObject == NULL) { - gl::FenceNV *fenceObject = context->getFenceNV(fence); - - if (fenceObject == NULL) - { - return GL_FALSE; - } - - return fenceObject->isFence(); + return GL_FALSE; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); + + return fenceObject->isFence(); } return GL_FALSE; @@ -4158,24 +3445,16 @@ GLboolean __stdcall glIsFramebuffer(GLuint framebuffer) { EVENT("(GLuint framebuffer = %d)", framebuffer); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context && framebuffer) { - gl::Context *context = gl::getNonLostContext(); + gl::Framebuffer *framebufferObject = context->getFramebuffer(framebuffer); - if (context && framebuffer) + if (framebufferObject) { - gl::Framebuffer *framebufferObject = context->getFramebuffer(framebuffer); - - if (framebufferObject) - { - return GL_TRUE; - } + return GL_TRUE; } } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); - } return GL_FALSE; } @@ -4184,24 +3463,16 @@ GLboolean __stdcall glIsProgram(GLuint program) { EVENT("(GLuint program = %d)", program); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context && program) { - gl::Context *context = gl::getNonLostContext(); + gl::Program *programObject = context->getProgram(program); - if (context && program) + if (programObject) { - gl::Program *programObject = context->getProgram(program); - - if (programObject) - { - return GL_TRUE; - } + return GL_TRUE; } } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); - } return GL_FALSE; } @@ -4210,18 +3481,10 @@ GLboolean __stdcall glIsQueryEXT(GLuint id) { EVENT("(GLuint id = %d)", id); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - return (context->getQuery(id, false, GL_NONE) != NULL) ? GL_TRUE : GL_FALSE; - } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); + return (context->getQuery(id, false, GL_NONE) != NULL) ? GL_TRUE : GL_FALSE; } return GL_FALSE; @@ -4231,24 +3494,16 @@ GLboolean __stdcall glIsRenderbuffer(GLuint renderbuffer) { EVENT("(GLuint renderbuffer = %d)", renderbuffer); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context && renderbuffer) { - gl::Context *context = gl::getNonLostContext(); + gl::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer); - if (context && renderbuffer) + if (renderbufferObject) { - gl::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer); - - if (renderbufferObject) - { - return GL_TRUE; - } + return GL_TRUE; } } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); - } return GL_FALSE; } @@ -4257,24 +3512,16 @@ GLboolean __stdcall glIsShader(GLuint shader) { EVENT("(GLuint shader = %d)", shader); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context && shader) { - gl::Context *context = gl::getNonLostContext(); + gl::Shader *shaderObject = context->getShader(shader); - if (context && shader) + if (shaderObject) { - gl::Shader *shaderObject = context->getShader(shader); - - if (shaderObject) - { - return GL_TRUE; - } + return GL_TRUE; } } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); - } return GL_FALSE; } @@ -4283,24 +3530,16 @@ GLboolean __stdcall glIsTexture(GLuint texture) { EVENT("(GLuint texture = %d)", texture); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context && texture) { - gl::Context *context = gl::getNonLostContext(); + gl::Texture *textureObject = context->getTexture(texture); - if (context && texture) + if (textureObject) { - gl::Texture *textureObject = context->getTexture(texture); - - if (textureObject) - { - return GL_TRUE; - } + return GL_TRUE; } } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); - } return GL_FALSE; } @@ -4309,23 +3548,16 @@ void __stdcall glLineWidth(GLfloat width) { EVENT("(GLfloat width = %f)", width); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (width <= 0.0f) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - context->setLineWidth(width); - } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setLineWidth(width); } } @@ -4333,32 +3565,26 @@ void __stdcall glLinkProgram(GLuint program) { EVENT("(GLuint program = %d)", program); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::Program *programObject = context->getProgram(program); - if (context) + if (!programObject) { - gl::Program *programObject = context->getProgram(program); - - if (!programObject) + if (context->getShader(program)) { - if (context->getShader(program)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - - context->linkProgram(program); } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + context->linkProgram(program); } } @@ -4366,78 +3592,66 @@ void __stdcall glPixelStorei(GLenum pname, GLint param) { EVENT("(GLenum pname = 0x%X, GLint param = %d)", pname, param); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + switch (pname) { - switch (pname) + case GL_UNPACK_ALIGNMENT: + if (param != 1 && param != 2 && param != 4 && param != 8) { - case GL_UNPACK_ALIGNMENT: - if (param != 1 && param != 2 && param != 4 && param != 8) - { - return gl::error(GL_INVALID_VALUE); - } - - context->setUnpackAlignment(param); - break; - - case GL_PACK_ALIGNMENT: - if (param != 1 && param != 2 && param != 4 && param != 8) - { - return gl::error(GL_INVALID_VALUE); - } - - context->setPackAlignment(param); - break; - - case GL_PACK_REVERSE_ROW_ORDER_ANGLE: - context->setPackReverseRowOrder(param != 0); - break; - - case GL_UNPACK_IMAGE_HEIGHT: - case GL_UNPACK_SKIP_IMAGES: - case GL_UNPACK_ROW_LENGTH: - case GL_UNPACK_SKIP_ROWS: - case GL_UNPACK_SKIP_PIXELS: - case GL_PACK_ROW_LENGTH: - case GL_PACK_SKIP_ROWS: - case GL_PACK_SKIP_PIXELS: - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_ENUM); - } - UNIMPLEMENTED(); - break; - - default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } + + context->getState().setUnpackAlignment(param); + break; + + case GL_PACK_ALIGNMENT: + if (param != 1 && param != 2 && param != 4 && param != 8) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + context->getState().setPackAlignment(param); + break; + + case GL_PACK_REVERSE_ROW_ORDER_ANGLE: + context->getState().setPackReverseRowOrder(param != 0); + break; + + case GL_UNPACK_IMAGE_HEIGHT: + case GL_UNPACK_SKIP_IMAGES: + case GL_UNPACK_ROW_LENGTH: + case GL_UNPACK_SKIP_ROWS: + case GL_UNPACK_SKIP_PIXELS: + case GL_PACK_ROW_LENGTH: + case GL_PACK_SKIP_ROWS: + case GL_PACK_SKIP_PIXELS: + if (context->getClientVersion() < 3) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + UNIMPLEMENTED(); + break; + + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glPolygonOffset(GLfloat factor, GLfloat units) { EVENT("(GLfloat factor = %f, GLfloat units = %f)", factor, units); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - context->setPolygonOffsetParams(factor, units); - } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setPolygonOffsetParams(factor, units); } } @@ -4449,29 +3663,22 @@ void __stdcall glReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height, "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufSize = 0x%d, GLvoid *data = 0x%0.8p)", x, y, width, height, format, type, bufSize, data); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (width < 0 || height < 0 || bufSize < 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!gl::ValidateReadPixelsParameters(context, x, y, width, height, + format, type, &bufSize, data)) { - if (!gl::ValidateReadPixelsParameters(context, x, y, width, height, - format, type, &bufSize, data)) - { - return; - } - - context->readPixels(x, y, width, height, format, type, &bufSize, data); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + context->readPixels(x, y, width, height, format, type, &bufSize, data); } } @@ -4482,29 +3689,22 @@ void __stdcall glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, "GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = 0x%0.8p)", x, y, width, height, format, type, pixels); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (width < 0 || height < 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!gl::ValidateReadPixelsParameters(context, x, y, width, height, + format, type, NULL, pixels)) { - if (!gl::ValidateReadPixelsParameters(context, x, y, width, height, - format, type, NULL, pixels)) - { - return; - } - - context->readPixels(x, y, width, height, format, type, NULL, pixels); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + context->readPixels(x, y, width, height, format, type, NULL, pixels); } } @@ -4512,13 +3712,11 @@ void __stdcall glReleaseShaderCompiler(void) { EVENT("()"); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + + if (context) { - gl::Shader::releaseCompiler(); - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + context->releaseShaderCompiler(); } } @@ -4527,24 +3725,16 @@ void __stdcall glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samp EVENT("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)", target, samples, internalformat, width, height); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!ValidateRenderbufferStorageParameters(context, target, samples, internalformat, + width, height, true)) { - if (!ValidateRenderbufferStorageParameters(context, target, samples, internalformat, - width, height, true)) - { - return; - } - - context->setRenderbufferStorage(width, height, internalformat, samples); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + context->setRenderbufferStorage(width, height, internalformat, samples); } } @@ -4557,18 +3747,11 @@ void __stdcall glSampleCoverage(GLclampf value, GLboolean invert) { EVENT("(GLclampf value = %f, GLboolean invert = %u)", value, invert); - ANGLE_TRY - { - gl::Context* context = gl::getNonLostContext(); + gl::Context* context = gl::getNonLostContext(); - if (context) - { - context->setSampleCoverageParams(gl::clamp01(value), invert == GL_TRUE); - } - } - ANGLE_CATCH_ALL + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setSampleCoverageParams(gl::clamp01(value), invert == GL_TRUE); } } @@ -4576,30 +3759,24 @@ void __stdcall glSetFenceNV(GLuint fence, GLenum condition) { EVENT("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (condition != GL_ALL_COMPLETED_NV) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - gl::Context *context = gl::getNonLostContext(); + gl::FenceNV *fenceObject = context->getFenceNV(fence); - if (context) + if (fenceObject == NULL) { - gl::FenceNV *fenceObject = context->getFenceNV(fence); - - if (fenceObject == NULL) - { - return gl::error(GL_INVALID_OPERATION); - } - - fenceObject->setFence(condition); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + fenceObject->setFence(condition); } } @@ -4607,23 +3784,16 @@ void __stdcall glScissor(GLint x, GLint y, GLsizei width, GLsizei height) { EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height); - ANGLE_TRY + gl::Context* context = gl::getNonLostContext(); + if (context) { if (width < 0 || height < 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - gl::Context* context = gl::getNonLostContext(); - - if (context) - { - context->setScissorParams(x, y, width, height); - } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setScissorParams(x, y, width, height); } } @@ -4633,14 +3803,18 @@ void __stdcall glShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryfor "const GLvoid* binary = 0x%0.8p, GLsizei length = %d)", n, shaders, binaryformat, binary, length); - ANGLE_TRY + gl::Context* context = gl::getNonLostContext(); + if (context) { + const std::vector &shaderBinaryFormats = context->getCaps().shaderBinaryFormats; + if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) == shaderBinaryFormats.end()) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + // No binary shader formats are supported. - return gl::error(GL_INVALID_ENUM); - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + UNIMPLEMENTED(); } } @@ -4649,37 +3823,32 @@ void __stdcall glShaderSource(GLuint shader, GLsizei count, const GLchar* const* EVENT("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = 0x%0.8p, const GLint* length = 0x%0.8p)", shader, count, string, length); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (count < 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - gl::Context *context = gl::getNonLostContext(); + gl::Shader *shaderObject = context->getShader(shader); - if (context) + if (!shaderObject) { - gl::Shader *shaderObject = context->getShader(shader); - - if (!shaderObject) + if (context->getProgram(shader)) { - if (context->getProgram(shader)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - - shaderObject->setSource(count, string, length); } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + shaderObject->setSource(count, string, length); } } @@ -4692,7 +3861,8 @@ void __stdcall glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint { EVENT("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { switch (face) { @@ -4700,8 +3870,10 @@ void __stdcall glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint case GL_BACK: case GL_FRONT_AND_BACK: break; + default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } switch (func) @@ -4715,28 +3887,21 @@ void __stdcall glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint case GL_GREATER: case GL_NOTEQUAL: break; + default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (face == GL_FRONT || face == GL_FRONT_AND_BACK) { - if (face == GL_FRONT || face == GL_FRONT_AND_BACK) - { - context->setStencilParams(func, ref, mask); - } - - if (face == GL_BACK || face == GL_FRONT_AND_BACK) - { - context->setStencilBackParams(func, ref, mask); - } + context->getState().setStencilParams(func, ref, mask); + } + + if (face == GL_BACK || face == GL_FRONT_AND_BACK) + { + context->getState().setStencilBackParams(func, ref, mask); } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -4749,7 +3914,8 @@ void __stdcall glStencilMaskSeparate(GLenum face, GLuint mask) { EVENT("(GLenum face = 0x%X, GLuint mask = %d)", face, mask); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { switch (face) { @@ -4757,28 +3923,21 @@ void __stdcall glStencilMaskSeparate(GLenum face, GLuint mask) case GL_BACK: case GL_FRONT_AND_BACK: break; + default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (face == GL_FRONT || face == GL_FRONT_AND_BACK) { - if (face == GL_FRONT || face == GL_FRONT_AND_BACK) - { - context->setStencilWritemask(mask); - } - - if (face == GL_BACK || face == GL_FRONT_AND_BACK) - { - context->setStencilBackWritemask(mask); - } + context->getState().setStencilWritemask(mask); + } + + if (face == GL_BACK || face == GL_FRONT_AND_BACK) + { + context->getState().setStencilBackWritemask(mask); } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -4792,7 +3951,8 @@ void __stdcall glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenu EVENT("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)", face, fail, zfail, zpass); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { switch (face) { @@ -4800,8 +3960,10 @@ void __stdcall glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenu case GL_BACK: case GL_FRONT_AND_BACK: break; + default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } switch (fail) @@ -4815,8 +3977,10 @@ void __stdcall glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenu case GL_INCR_WRAP: case GL_DECR_WRAP: break; + default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } switch (zfail) @@ -4830,8 +3994,10 @@ void __stdcall glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenu case GL_INCR_WRAP: case GL_DECR_WRAP: break; + default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } switch (zpass) @@ -4845,28 +4011,21 @@ void __stdcall glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenu case GL_INCR_WRAP: case GL_DECR_WRAP: break; + default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (face == GL_FRONT || face == GL_FRONT_AND_BACK) { - if (face == GL_FRONT || face == GL_FRONT_AND_BACK) - { - context->setStencilOperations(fail, zfail, zpass); - } - - if (face == GL_BACK || face == GL_FRONT_AND_BACK) - { - context->setStencilBackOperations(fail, zfail, zpass); - } + context->getState().setStencilOperations(fail, zfail, zpass); + } + + if (face == GL_BACK || face == GL_FRONT_AND_BACK) + { + context->getState().setStencilBackOperations(fail, zfail, zpass); } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -4874,32 +4033,26 @@ GLboolean __stdcall glTestFenceNV(GLuint fence) { EVENT("(GLuint fence = %d)", fence); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::FenceNV *fenceObject = context->getFenceNV(fence); - if (context) + if (fenceObject == NULL) { - gl::FenceNV *fenceObject = context->getFenceNV(fence); - - if (fenceObject == NULL) - { - return gl::error(GL_INVALID_OPERATION, GL_TRUE); - } - - if (fenceObject->isFence() != GL_TRUE) - { - return gl::error(GL_INVALID_OPERATION, GL_TRUE); - } - - return fenceObject->testFence(); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return GL_TRUE; } + + if (fenceObject->isFence() != GL_TRUE) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return GL_TRUE; + } + + return fenceObject->testFence(); } - ANGLE_CATCH_ALL - { - gl::error(GL_OUT_OF_MEMORY); - } - + return GL_TRUE; } @@ -4910,77 +4063,69 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)", target, level, internalformat, width, height, border, format, type, pixels); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3 && + !ValidateES2TexImageParameters(context, target, level, internalformat, false, false, + 0, 0, width, height, border, format, type, pixels)) { - if (context->getClientVersion() < 3 && - !ValidateES2TexImageParameters(context, target, level, internalformat, false, false, - 0, 0, width, height, border, format, type, pixels)) - { - return; - } - - if (context->getClientVersion() >= 3 && - !ValidateES3TexImageParameters(context, target, level, internalformat, false, false, - 0, 0, 0, width, height, 1, border, format, type, pixels)) - { - return; - } - - switch (target) - { - case GL_TEXTURE_2D: - { - gl::Texture2D *texture = context->getTexture2D(); - texture->setImage(level, width, height, internalformat, format, type, context->getUnpackState(), pixels); - } - break; - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - { - gl::TextureCubeMap *texture = context->getTextureCubeMap(); - texture->setImagePosX(level, width, height, internalformat, format, type, context->getUnpackState(), pixels); - } - break; - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - { - gl::TextureCubeMap *texture = context->getTextureCubeMap(); - texture->setImageNegX(level, width, height, internalformat, format, type, context->getUnpackState(), pixels); - } - break; - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - { - gl::TextureCubeMap *texture = context->getTextureCubeMap(); - texture->setImagePosY(level, width, height, internalformat, format, type, context->getUnpackState(), pixels); - } - break; - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - { - gl::TextureCubeMap *texture = context->getTextureCubeMap(); - texture->setImageNegY(level, width, height, internalformat, format, type, context->getUnpackState(), pixels); - } - break; - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - { - gl::TextureCubeMap *texture = context->getTextureCubeMap(); - texture->setImagePosZ(level, width, height, internalformat, format, type, context->getUnpackState(), pixels); - } - break; - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - { - gl::TextureCubeMap *texture = context->getTextureCubeMap(); - texture->setImageNegZ(level, width, height, internalformat, format, type, context->getUnpackState(), pixels); - } - break; - default: UNREACHABLE(); - } + return; + } + + if (context->getClientVersion() >= 3 && + !ValidateES3TexImageParameters(context, target, level, internalformat, false, false, + 0, 0, 0, width, height, 1, border, format, type, pixels)) + { + return; + } + + switch (target) + { + case GL_TEXTURE_2D: + { + gl::Texture2D *texture = context->getTexture2D(); + texture->setImage(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels); + } + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + { + gl::TextureCubeMap *texture = context->getTextureCubeMap(); + texture->setImagePosX(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels); + } + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + { + gl::TextureCubeMap *texture = context->getTextureCubeMap(); + texture->setImageNegX(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels); + } + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + { + gl::TextureCubeMap *texture = context->getTextureCubeMap(); + texture->setImagePosY(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels); + } + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + { + gl::TextureCubeMap *texture = context->getTextureCubeMap(); + texture->setImageNegY(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels); + } + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + { + gl::TextureCubeMap *texture = context->getTextureCubeMap(); + texture->setImagePosZ(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels); + } + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + { + gl::TextureCubeMap *texture = context->getTextureCubeMap(); + texture->setImageNegZ(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels); + } + break; + default: UNREACHABLE(); } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -4988,50 +4133,43 @@ void __stdcall glTexParameterf(GLenum target, GLenum pname, GLfloat param) { EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %f)", target, pname, param); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!ValidateTexParamParameters(context, pname, static_cast(param))) { - if (!ValidateTexParamParameters(context, pname, static_cast(param))) - { - return; - } - - gl::Texture *texture = context->getTargetTexture(target); - - if (!texture) - { - return gl::error(GL_INVALID_ENUM); - } - - switch (pname) - { - case GL_TEXTURE_WRAP_S: texture->setWrapS(gl::uiround(param)); break; - case GL_TEXTURE_WRAP_T: texture->setWrapT(gl::uiround(param)); break; - case GL_TEXTURE_WRAP_R: texture->setWrapR(gl::uiround(param)); break; - case GL_TEXTURE_MIN_FILTER: texture->setMinFilter(gl::uiround(param)); break; - case GL_TEXTURE_MAG_FILTER: texture->setMagFilter(gl::uiround(param)); break; - case GL_TEXTURE_USAGE_ANGLE: texture->setUsage(gl::uiround(param)); break; - case GL_TEXTURE_MAX_ANISOTROPY_EXT: texture->setMaxAnisotropy(param, context->getTextureMaxAnisotropy()); break; - case GL_TEXTURE_COMPARE_MODE: texture->setCompareMode(gl::uiround(param)); break; - case GL_TEXTURE_COMPARE_FUNC: texture->setCompareFunc(gl::uiround(param)); break; - case GL_TEXTURE_SWIZZLE_R: texture->setSwizzleRed(gl::uiround(param)); break; - case GL_TEXTURE_SWIZZLE_G: texture->setSwizzleGreen(gl::uiround(param)); break; - case GL_TEXTURE_SWIZZLE_B: texture->setSwizzleBlue(gl::uiround(param)); break; - case GL_TEXTURE_SWIZZLE_A: texture->setSwizzleAlpha(gl::uiround(param)); break; - case GL_TEXTURE_BASE_LEVEL: texture->setBaseLevel(gl::iround(param)); break; - case GL_TEXTURE_MAX_LEVEL: texture->setMaxLevel(gl::iround(param)); break; - case GL_TEXTURE_MIN_LOD: texture->setMinLod(param); break; - case GL_TEXTURE_MAX_LOD: texture->setMaxLod(param); break; - default: UNREACHABLE(); break; - } + return; + } + + gl::Texture *texture = context->getTargetTexture(target); + + if (!texture) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + + switch (pname) + { + case GL_TEXTURE_WRAP_S: texture->getSamplerState().wrapS = gl::uiround(param); break; + case GL_TEXTURE_WRAP_T: texture->getSamplerState().wrapT = gl::uiround(param); break; + case GL_TEXTURE_WRAP_R: texture->getSamplerState().wrapR = gl::uiround(param); break; + case GL_TEXTURE_MIN_FILTER: texture->getSamplerState().minFilter = gl::uiround(param); break; + case GL_TEXTURE_MAG_FILTER: texture->getSamplerState().magFilter = gl::uiround(param); break; + case GL_TEXTURE_USAGE_ANGLE: texture->setUsage(gl::uiround(param)); break; + case GL_TEXTURE_MAX_ANISOTROPY_EXT: texture->getSamplerState().maxAnisotropy = std::min(param, context->getExtensions().maxTextureAnisotropy); break; + case GL_TEXTURE_COMPARE_MODE: texture->getSamplerState().compareMode = gl::uiround(param); break; + case GL_TEXTURE_COMPARE_FUNC: texture->getSamplerState().compareFunc = gl::uiround(param); break; + case GL_TEXTURE_SWIZZLE_R: texture->getSamplerState().swizzleRed = gl::uiround(param); break; + case GL_TEXTURE_SWIZZLE_G: texture->getSamplerState().swizzleGreen = gl::uiround(param); break; + case GL_TEXTURE_SWIZZLE_B: texture->getSamplerState().swizzleBlue = gl::uiround(param); break; + case GL_TEXTURE_SWIZZLE_A: texture->getSamplerState().swizzleAlpha = gl::uiround(param); break; + case GL_TEXTURE_BASE_LEVEL: texture->getSamplerState().baseLevel = gl::iround(param); break; + case GL_TEXTURE_MAX_LEVEL: texture->getSamplerState().maxLevel = gl::iround(param); break; + case GL_TEXTURE_MIN_LOD: texture->getSamplerState().minLod = param; break; + case GL_TEXTURE_MAX_LOD: texture->getSamplerState().maxLod = param; break; + default: UNREACHABLE(); break; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -5044,50 +4182,43 @@ void __stdcall glTexParameteri(GLenum target, GLenum pname, GLint param) { EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!ValidateTexParamParameters(context, pname, param)) { - if (!ValidateTexParamParameters(context, pname, param)) - { - return; - } - - gl::Texture *texture = context->getTargetTexture(target); - - if (!texture) - { - return gl::error(GL_INVALID_ENUM); - } - - switch (pname) - { - case GL_TEXTURE_WRAP_S: texture->setWrapS((GLenum)param); break; - case GL_TEXTURE_WRAP_T: texture->setWrapT((GLenum)param); break; - case GL_TEXTURE_WRAP_R: texture->setWrapR((GLenum)param); break; - case GL_TEXTURE_MIN_FILTER: texture->setMinFilter((GLenum)param); break; - case GL_TEXTURE_MAG_FILTER: texture->setMagFilter((GLenum)param); break; - case GL_TEXTURE_USAGE_ANGLE: texture->setUsage((GLenum)param); break; - case GL_TEXTURE_MAX_ANISOTROPY_EXT: texture->setMaxAnisotropy((float)param, context->getTextureMaxAnisotropy()); break; - case GL_TEXTURE_COMPARE_MODE: texture->setCompareMode((GLenum)param); break; - case GL_TEXTURE_COMPARE_FUNC: texture->setCompareFunc((GLenum)param); break; - case GL_TEXTURE_SWIZZLE_R: texture->setSwizzleRed((GLenum)param); break; - case GL_TEXTURE_SWIZZLE_G: texture->setSwizzleGreen((GLenum)param); break; - case GL_TEXTURE_SWIZZLE_B: texture->setSwizzleBlue((GLenum)param); break; - case GL_TEXTURE_SWIZZLE_A: texture->setSwizzleAlpha((GLenum)param); break; - case GL_TEXTURE_BASE_LEVEL: texture->setBaseLevel(param); break; - case GL_TEXTURE_MAX_LEVEL: texture->setMaxLevel(param); break; - case GL_TEXTURE_MIN_LOD: texture->setMinLod((GLfloat)param); break; - case GL_TEXTURE_MAX_LOD: texture->setMaxLod((GLfloat)param); break; - default: UNREACHABLE(); break; - } + return; + } + + gl::Texture *texture = context->getTargetTexture(target); + + if (!texture) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + + switch (pname) + { + case GL_TEXTURE_WRAP_S: texture->getSamplerState().wrapS = (GLenum)param; break; + case GL_TEXTURE_WRAP_T: texture->getSamplerState().wrapT = (GLenum)param; break; + case GL_TEXTURE_WRAP_R: texture->getSamplerState().wrapR = (GLenum)param; break; + case GL_TEXTURE_MIN_FILTER: texture->getSamplerState().minFilter = (GLenum)param; break; + case GL_TEXTURE_MAG_FILTER: texture->getSamplerState().magFilter = (GLenum)param; break; + case GL_TEXTURE_USAGE_ANGLE: texture->setUsage((GLenum)param); break; + case GL_TEXTURE_MAX_ANISOTROPY_EXT: texture->getSamplerState().maxAnisotropy = std::min((float)param, context->getExtensions().maxTextureAnisotropy); break; + case GL_TEXTURE_COMPARE_MODE: texture->getSamplerState().compareMode = (GLenum)param; break; + case GL_TEXTURE_COMPARE_FUNC: texture->getSamplerState().compareFunc = (GLenum)param; break; + case GL_TEXTURE_SWIZZLE_R: texture->getSamplerState().swizzleRed = (GLenum)param; break; + case GL_TEXTURE_SWIZZLE_G: texture->getSamplerState().swizzleGreen = (GLenum)param; break; + case GL_TEXTURE_SWIZZLE_B: texture->getSamplerState().swizzleBlue = (GLenum)param; break; + case GL_TEXTURE_SWIZZLE_A: texture->getSamplerState().swizzleAlpha = (GLenum)param; break; + case GL_TEXTURE_BASE_LEVEL: texture->getSamplerState().baseLevel = param; break; + case GL_TEXTURE_MAX_LEVEL: texture->getSamplerState().maxLevel = param; break; + case GL_TEXTURE_MIN_LOD: texture->getSamplerState().minLod = (GLfloat)param; break; + case GL_TEXTURE_MAX_LOD: texture->getSamplerState().maxLod = (GLfloat)param; break; + default: UNREACHABLE(); break; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -5101,48 +4232,47 @@ void __stdcall glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalf EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)", target, levels, internalformat, width, height); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!context->getExtensions().textureStorage) { - if (context->getClientVersion() < 3 && - !ValidateES2TexStorageParameters(context, target, levels, internalformat, width, height)) - { - return; - } - - if (context->getClientVersion() >= 3 && - !ValidateES3TexStorageParameters(context, target, levels, internalformat, width, height, 1)) - { - return; - } - - switch (target) - { - case GL_TEXTURE_2D: - { - gl::Texture2D *texture2d = context->getTexture2D(); - texture2d->storage(levels, internalformat, width, height); - } - break; - - case GL_TEXTURE_CUBE_MAP: - { - gl::TextureCubeMap *textureCube = context->getTextureCubeMap(); - textureCube->storage(levels, internalformat, width); - } - break; - - default: - return gl::error(GL_INVALID_ENUM); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + if (context->getClientVersion() < 3 && + !ValidateES2TexStorageParameters(context, target, levels, internalformat, width, height)) + { + return; + } + + if (context->getClientVersion() >= 3 && + !ValidateES3TexStorageParameters(context, target, levels, internalformat, width, height, 1)) + { + return; + } + + switch (target) + { + case GL_TEXTURE_2D: + { + gl::Texture2D *texture2d = context->getTexture2D(); + texture2d->storage(levels, internalformat, width, height); + } + break; + + case GL_TEXTURE_CUBE_MAP: + { + gl::TextureCubeMap *textureCube = context->getTextureCubeMap(); + textureCube->storage(levels, internalformat, width); + } + break; + + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -5154,61 +4284,53 @@ void __stdcall glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint "const GLvoid* pixels = 0x%0.8p)", target, level, xoffset, yoffset, width, height, format, type, pixels); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3 && + !ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, + xoffset, yoffset, width, height, 0, format, type, pixels)) { - if (context->getClientVersion() < 3 && - !ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, - xoffset, yoffset, width, height, 0, format, type, pixels)) - { - return; - } - - if (context->getClientVersion() >= 3 && - !ValidateES3TexImageParameters(context, target, level, GL_NONE, false, true, - xoffset, yoffset, 0, width, height, 1, 0, format, type, pixels)) - { - return; - } - - // Zero sized uploads are valid but no-ops - if (width == 0 || height == 0) - { - return; - } - - switch (target) - { - case GL_TEXTURE_2D: - { - gl::Texture2D *texture = context->getTexture2D(); - texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getUnpackState(), pixels); - } - break; - - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - { - gl::TextureCubeMap *texture = context->getTextureCubeMap(); - texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getUnpackState(), pixels); - } - break; - - default: - UNREACHABLE(); - } + return; + } + + if (context->getClientVersion() >= 3 && + !ValidateES3TexImageParameters(context, target, level, GL_NONE, false, true, + xoffset, yoffset, 0, width, height, 1, 0, format, type, pixels)) + { + return; + } + + // Zero sized uploads are valid but no-ops + if (width == 0 || height == 0) + { + return; + } + + switch (target) + { + case GL_TEXTURE_2D: + { + gl::Texture2D *texture = context->getTexture2D(); + texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getState().getUnpackState(), pixels); + } + break; + + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + { + gl::TextureCubeMap *texture = context->getTextureCubeMap(); + texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getState().getUnpackState(), pixels); + } + break; + + default: + UNREACHABLE(); } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -5221,24 +4343,16 @@ void __stdcall glUniform1fv(GLint location, GLsizei count, const GLfloat* v) { EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!ValidateUniform(context, GL_FLOAT, location, count)) { - if (!ValidateUniform(context, GL_FLOAT, location, count)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - programBinary->setUniform1fv(location, count, v); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniform1fv(location, count, v); } } @@ -5251,24 +4365,16 @@ void __stdcall glUniform1iv(GLint location, GLsizei count, const GLint* v) { EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!ValidateUniform(context, GL_INT, location, count)) { - if (!ValidateUniform(context, GL_INT, location, count)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - programBinary->setUniform1iv(location, count, v); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniform1iv(location, count, v); } } @@ -5283,24 +4389,16 @@ void __stdcall glUniform2fv(GLint location, GLsizei count, const GLfloat* v) { EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!ValidateUniform(context, GL_FLOAT_VEC2, location, count)) { - if (!ValidateUniform(context, GL_FLOAT_VEC2, location, count)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - programBinary->setUniform2fv(location, count, v); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniform2fv(location, count, v); } } @@ -5315,24 +4413,16 @@ void __stdcall glUniform2iv(GLint location, GLsizei count, const GLint* v) { EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!ValidateUniform(context, GL_INT_VEC2, location, count)) { - if (!ValidateUniform(context, GL_INT_VEC2, location, count)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - programBinary->setUniform2iv(location, count, v); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniform2iv(location, count, v); } } @@ -5347,24 +4437,16 @@ void __stdcall glUniform3fv(GLint location, GLsizei count, const GLfloat* v) { EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!ValidateUniform(context, GL_FLOAT_VEC3, location, count)) { - if (!ValidateUniform(context, GL_FLOAT_VEC3, location, count)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - programBinary->setUniform3fv(location, count, v); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniform3fv(location, count, v); } } @@ -5379,24 +4461,16 @@ void __stdcall glUniform3iv(GLint location, GLsizei count, const GLint* v) { EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!ValidateUniform(context, GL_INT_VEC3, location, count)) { - if (!ValidateUniform(context, GL_INT_VEC3, location, count)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - programBinary->setUniform3iv(location, count, v); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniform3iv(location, count, v); } } @@ -5411,24 +4485,16 @@ void __stdcall glUniform4fv(GLint location, GLsizei count, const GLfloat* v) { EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!ValidateUniform(context, GL_FLOAT_VEC4, location, count)) { - if (!ValidateUniform(context, GL_FLOAT_VEC4, location, count)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - programBinary->setUniform4fv(location, count, v); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniform4fv(location, count, v); } } @@ -5443,24 +4509,16 @@ void __stdcall glUniform4iv(GLint location, GLsizei count, const GLint* v) { EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!ValidateUniform(context, GL_INT_VEC4, location, count)) { - if (!ValidateUniform(context, GL_INT_VEC4, location, count)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - programBinary->setUniform4iv(location, count, v); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniform4iv(location, count, v); } } @@ -5469,24 +4527,16 @@ void __stdcall glUniformMatrix2fv(GLint location, GLsizei count, GLboolean trans EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", location, count, transpose, value); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose)) { - if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - programBinary->setUniformMatrix2fv(location, count, transpose, value); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniformMatrix2fv(location, count, transpose, value); } } @@ -5495,24 +4545,16 @@ void __stdcall glUniformMatrix3fv(GLint location, GLsizei count, GLboolean trans EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", location, count, transpose, value); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose)) { - if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - programBinary->setUniformMatrix3fv(location, count, transpose, value); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniformMatrix3fv(location, count, transpose, value); } } @@ -5521,24 +4563,16 @@ void __stdcall glUniformMatrix4fv(GLint location, GLsizei count, GLboolean trans EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", location, count, transpose, value); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose)) { - if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - programBinary->setUniformMatrix4fv(location, count, transpose, value); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniformMatrix4fv(location, count, transpose, value); } } @@ -5546,37 +4580,32 @@ void __stdcall glUseProgram(GLuint program) { EVENT("(GLuint program = %d)", program); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::Program *programObject = context->getProgram(program); - if (context) + if (!programObject && program != 0) { - gl::Program *programObject = context->getProgram(program); - - if (!programObject && program != 0) + if (context->getShader(program)) { - if (context->getShader(program)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - - if (program != 0 && !programObject->isLinked()) + else { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - - context->useProgram(program); } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + if (program != 0 && !programObject->isLinked()) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + context->useProgram(program); } } @@ -5584,32 +4613,26 @@ void __stdcall glValidateProgram(GLuint program) { EVENT("(GLuint program = %d)", program); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::Program *programObject = context->getProgram(program); - if (context) + if (!programObject) { - gl::Program *programObject = context->getProgram(program); - - if (!programObject) + if (context->getShader(program)) { - if (context->getShader(program)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - - programObject->validate(); } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + programObject->validate(context->getCaps()); } } @@ -5617,24 +4640,17 @@ void __stdcall glVertexAttrib1f(GLuint index, GLfloat x) { EVENT("(GLuint index = %d, GLfloat x = %f)", index, x); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - GLfloat vals[4] = { x, 0, 0, 1 }; - context->setVertexAttribf(index, vals); - } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + GLfloat vals[4] = { x, 0, 0, 1 }; + context->getState().setVertexAttribf(index, vals); } } @@ -5642,24 +4658,17 @@ void __stdcall glVertexAttrib1fv(GLuint index, const GLfloat* values) { EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - GLfloat vals[4] = { values[0], 0, 0, 1 }; - context->setVertexAttribf(index, vals); - } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + GLfloat vals[4] = { values[0], 0, 0, 1 }; + context->getState().setVertexAttribf(index, vals); } } @@ -5667,24 +4676,17 @@ void __stdcall glVertexAttrib2f(GLuint index, GLfloat x, GLfloat y) { EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - GLfloat vals[4] = { x, y, 0, 1 }; - context->setVertexAttribf(index, vals); - } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + GLfloat vals[4] = { x, y, 0, 1 }; + context->getState().setVertexAttribf(index, vals); } } @@ -5692,24 +4694,17 @@ void __stdcall glVertexAttrib2fv(GLuint index, const GLfloat* values) { EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - GLfloat vals[4] = { values[0], values[1], 0, 1 }; - context->setVertexAttribf(index, vals); - } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + GLfloat vals[4] = { values[0], values[1], 0, 1 }; + context->getState().setVertexAttribf(index, vals); } } @@ -5717,24 +4712,17 @@ void __stdcall glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z) { EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - GLfloat vals[4] = { x, y, z, 1 }; - context->setVertexAttribf(index, vals); - } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + GLfloat vals[4] = { x, y, z, 1 }; + context->getState().setVertexAttribf(index, vals); } } @@ -5742,24 +4730,17 @@ void __stdcall glVertexAttrib3fv(GLuint index, const GLfloat* values) { EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - GLfloat vals[4] = { values[0], values[1], values[2], 1 }; - context->setVertexAttribf(index, vals); - } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + GLfloat vals[4] = { values[0], values[1], values[2], 1 }; + context->getState().setVertexAttribf(index, vals); } } @@ -5767,24 +4748,17 @@ void __stdcall glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, G { EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - GLfloat vals[4] = { x, y, z, w }; - context->setVertexAttribf(index, vals); - } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + GLfloat vals[4] = { x, y, z, w }; + context->getState().setVertexAttribf(index, vals); } } @@ -5792,23 +4766,16 @@ void __stdcall glVertexAttrib4fv(GLuint index, const GLfloat* values) { EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - context->setVertexAttribf(index, values); - } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setVertexAttribf(index, values); } } @@ -5816,23 +4783,16 @@ void __stdcall glVertexAttribDivisorANGLE(GLuint index, GLuint divisor) { EVENT("(GLuint index = %d, GLuint divisor = %d)", index, divisor); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - context->setVertexAttribDivisor(index, divisor); - } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + context->setVertexAttribDivisor(index, divisor); } } @@ -5842,20 +4802,21 @@ void __stdcall glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLbo "GLboolean normalized = %u, GLsizei stride = %d, const GLvoid* ptr = 0x%0.8p)", index, size, type, normalized, stride, ptr); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } if (size < 1 || size > 4) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - gl::Context *context = gl::getNonLostContext(); - switch (type) { case GL_BYTE: @@ -5865,51 +4826,48 @@ void __stdcall glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLbo case GL_FIXED: case GL_FLOAT: break; + case GL_HALF_FLOAT: case GL_INT: case GL_UNSIGNED_INT: case GL_INT_2_10_10_10_REV: case GL_UNSIGNED_INT_2_10_10_10_REV: - if (context && context->getClientVersion() < 3) + if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_ENUM); - } - else - { - break; + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } + break; + default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } if (stride < 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } if ((type == GL_INT_2_10_10_10_REV || type == GL_UNSIGNED_INT_2_10_10_10_REV) && size != 4) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - if (context) + // [OpenGL ES 3.0.2] Section 2.8 page 24: + // An INVALID_OPERATION error is generated when a non-zero vertex array object + // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point, + // and the pointer argument is not NULL. + if (context->getState().getVertexArray()->id() != 0 && context->getState().getArrayBufferId() == 0 && ptr != NULL) { - // [OpenGL ES 3.0.2] Section 2.8 page 24: - // An INVALID_OPERATION error is generated when a non-zero vertex array object - // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point, - // and the pointer argument is not NULL. - if (context->getVertexArrayHandle() != 0 && context->getArrayBufferHandle() == 0 && ptr != NULL) - { - return gl::error(GL_INVALID_OPERATION); - } - - context->setVertexAttribState(index, context->getArrayBuffer(), size, type, - normalized == GL_TRUE, false, stride, ptr); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + context->getState().setVertexAttribState(index, context->getState().getTargetBuffer(GL_ARRAY_BUFFER), size, type, + normalized == GL_TRUE, false, stride, ptr); } } @@ -5917,23 +4875,16 @@ void __stdcall glViewport(GLint x, GLint y, GLsizei width, GLsizei height) { EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { if (width < 0 || height < 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - context->setViewportParams(x, y, width, height); - } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setViewportParams(x, y, width, height); } } @@ -5943,24 +4894,17 @@ void __stdcall glReadBuffer(GLenum mode) { EVENT("(GLenum mode = 0x%X)", mode); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - // glReadBuffer - UNIMPLEMENTED(); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + // glReadBuffer + UNIMPLEMENTED(); } } @@ -5969,24 +4913,17 @@ void __stdcall glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsize EVENT("(GLenum mode = 0x%X, GLuint start = %u, GLuint end = %u, GLsizei count = %d, GLenum type = 0x%X, " "const GLvoid* indices = 0x%0.8p)", mode, start, end, count, type, indices); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - // glDrawRangeElements - UNIMPLEMENTED(); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + // glDrawRangeElements + UNIMPLEMENTED(); } } @@ -5997,48 +4934,42 @@ void __stdcall glTexImage3D(GLenum target, GLint level, GLint internalformat, GL "GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)", target, level, internalformat, width, height, depth, border, format, type, pixels); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - // validateES3TexImageFormat sets the error code if there is an error - if (!ValidateES3TexImageParameters(context, target, level, internalformat, false, false, - 0, 0, 0, width, height, depth, border, format, type, pixels)) - { - return; - } - - switch(target) - { - case GL_TEXTURE_3D: - { - gl::Texture3D *texture = context->getTexture3D(); - texture->setImage(level, width, height, depth, internalformat, format, type, context->getUnpackState(), pixels); - } - break; - - case GL_TEXTURE_2D_ARRAY: - { - gl::Texture2DArray *texture = context->getTexture2DArray(); - texture->setImage(level, width, height, depth, internalformat, format, type, context->getUnpackState(), pixels); - } - break; - - default: - return gl::error(GL_INVALID_ENUM); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + // validateES3TexImageFormat sets the error code if there is an error + if (!ValidateES3TexImageParameters(context, target, level, internalformat, false, false, + 0, 0, 0, width, height, depth, border, format, type, pixels)) + { + return; + } + + switch(target) + { + case GL_TEXTURE_3D: + { + gl::Texture3D *texture = context->getTexture3D(); + texture->setImage(level, width, height, depth, internalformat, format, type, context->getState().getUnpackState(), pixels); + } + break; + + case GL_TEXTURE_2D_ARRAY: + { + gl::Texture2DArray *texture = context->getTexture2DArray(); + texture->setImage(level, width, height, depth, internalformat, format, type, context->getState().getUnpackState(), pixels); + } + break; + + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -6049,55 +4980,49 @@ void __stdcall glTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint "GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)", target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - // validateES3TexImageFormat sets the error code if there is an error - if (!ValidateES3TexImageParameters(context, target, level, GL_NONE, false, true, - xoffset, yoffset, zoffset, width, height, depth, 0, - format, type, pixels)) - { - return; - } - - // Zero sized uploads are valid but no-ops - if (width == 0 || height == 0 || depth == 0) - { - return; - } - - switch(target) - { - case GL_TEXTURE_3D: - { - gl::Texture3D *texture = context->getTexture3D(); - texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getUnpackState(), pixels); - } - break; - - case GL_TEXTURE_2D_ARRAY: - { - gl::Texture2DArray *texture = context->getTexture2DArray(); - texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getUnpackState(), pixels); - } - break; - - default: - return gl::error(GL_INVALID_ENUM); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + // validateES3TexImageFormat sets the error code if there is an error + if (!ValidateES3TexImageParameters(context, target, level, GL_NONE, false, true, + xoffset, yoffset, zoffset, width, height, depth, 0, + format, type, pixels)) + { + return; + } + + // Zero sized uploads are valid but no-ops + if (width == 0 || height == 0 || depth == 0) + { + return; + } + + switch(target) + { + case GL_TEXTURE_3D: + { + gl::Texture3D *texture = context->getTexture3D(); + texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getState().getUnpackState(), pixels); + } + break; + + case GL_TEXTURE_2D_ARRAY: + { + gl::Texture2DArray *texture = context->getTexture2DArray(); + texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getState().getUnpackState(), pixels); + } + break; + + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -6107,51 +5032,39 @@ void __stdcall glCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GL "GLint zoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", target, level, xoffset, yoffset, zoffset, x, y, width, height); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (!ValidateES3CopyTexImageParameters(context, target, level, GL_NONE, false, xoffset, yoffset, zoffset, - x, y, width, height, 0)) - { - return; - } - - // Zero sized copies are valid but no-ops - if (width == 0 || height == 0) - { - return; - } - - gl::Framebuffer *framebuffer = context->getReadFramebuffer(); - gl::Texture *texture = NULL; - switch (target) - { - case GL_TEXTURE_3D: - texture = context->getTexture3D(); - break; - - case GL_TEXTURE_2D_ARRAY: - texture = context->getTexture2DArray(); - break; - - default: - return gl::error(GL_INVALID_ENUM); - } - - texture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, framebuffer); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + if (!ValidateES3CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset, yoffset, zoffset, + x, y, width, height, 0)) + { + return; + } + + gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); + gl::Texture *texture = NULL; + switch (target) + { + case GL_TEXTURE_3D: + texture = context->getTexture3D(); + break; + + case GL_TEXTURE_2D_ARRAY: + texture = context->getTexture2DArray(); + break; + + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + + texture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, framebuffer); } } @@ -6162,53 +5075,49 @@ void __stdcall glCompressedTexImage3D(GLenum target, GLint level, GLenum interna "const GLvoid* data = 0x%0.8p)", target, level, internalformat, width, height, depth, border, imageSize, data); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (imageSize < 0 || imageSize != (GLsizei)gl::GetBlockSize(internalformat, GL_UNSIGNED_BYTE, context->getClientVersion(), width, height)) - { - return gl::error(GL_INVALID_VALUE); - } - - // validateES3TexImageFormat sets the error code if there is an error - if (!ValidateES3TexImageParameters(context, target, level, internalformat, true, false, - 0, 0, 0, width, height, depth, border, GL_NONE, GL_NONE, data)) - { - return; - } - - switch(target) - { - case GL_TEXTURE_3D: - { - gl::Texture3D *texture = context->getTexture3D(); - texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data); - } - break; - - case GL_TEXTURE_2D_ARRAY: - { - gl::Texture2DArray *texture = context->getTexture2DArray(); - texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data); - } - break; - - default: - return gl::error(GL_INVALID_ENUM); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat); + if (imageSize < 0 || static_cast(imageSize) != formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height)) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + // validateES3TexImageFormat sets the error code if there is an error + if (!ValidateES3TexImageParameters(context, target, level, internalformat, true, false, + 0, 0, 0, width, height, depth, border, GL_NONE, GL_NONE, data)) + { + return; + } + + switch(target) + { + case GL_TEXTURE_3D: + { + gl::Texture3D *texture = context->getTexture3D(); + texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data); + } + break; + + case GL_TEXTURE_2D_ARRAY: + { + gl::Texture2DArray *texture = context->getTexture2DArray(); + texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data); + } + break; + + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -6219,66 +5128,63 @@ void __stdcall glCompressedTexSubImage3D(GLenum target, GLint level, GLint xoffs "GLenum format = 0x%X, GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)", target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (imageSize < 0 || imageSize != (GLsizei)gl::GetBlockSize(format, GL_UNSIGNED_BYTE, context->getClientVersion(), width, height)) - { - return gl::error(GL_INVALID_VALUE); - } - - if (!data) - { - return gl::error(GL_INVALID_VALUE); - } - - // validateES3TexImageFormat sets the error code if there is an error - if (!ValidateES3TexImageParameters(context, target, level, GL_NONE, true, true, - 0, 0, 0, width, height, depth, 0, GL_NONE, GL_NONE, data)) - { - return; - } - - // Zero sized uploads are valid but no-ops - if (width == 0 || height == 0) - { - return; - } - - switch(target) - { - case GL_TEXTURE_3D: - { - gl::Texture3D *texture = context->getTexture3D(); - texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, - format, imageSize, data); - } - break; - - case GL_TEXTURE_2D_ARRAY: - { - gl::Texture2DArray *texture = context->getTexture2DArray(); - texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, - format, imageSize, data); - } - break; - - default: - return gl::error(GL_INVALID_ENUM); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format); + if (imageSize < 0 || static_cast(imageSize) != formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height)) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + if (!data) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + // validateES3TexImageFormat sets the error code if there is an error + if (!ValidateES3TexImageParameters(context, target, level, GL_NONE, true, true, + 0, 0, 0, width, height, depth, 0, GL_NONE, GL_NONE, data)) + { + return; + } + + // Zero sized uploads are valid but no-ops + if (width == 0 || height == 0) + { + return; + } + + switch(target) + { + case GL_TEXTURE_3D: + { + gl::Texture3D *texture = context->getTexture3D(); + texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, + format, imageSize, data); + } + break; + + case GL_TEXTURE_2D_ARRAY: + { + gl::Texture2DArray *texture = context->getTexture2DArray(); + texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, + format, imageSize, data); + } + break; + + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -6286,31 +5192,25 @@ void __stdcall glGenQueries(GLsizei n, GLuint* ids) { EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (n < 0) - { - return gl::error(GL_INVALID_VALUE); - } - - for (GLsizei i = 0; i < n; i++) - { - ids[i] = context->createQuery(); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + if (n < 0) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + for (GLsizei i = 0; i < n; i++) + { + ids[i] = context->createQuery(); } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -6318,31 +5218,25 @@ void __stdcall glDeleteQueries(GLsizei n, const GLuint* ids) { EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (n < 0) - { - return gl::error(GL_INVALID_VALUE); - } - - for (GLsizei i = 0; i < n; i++) - { - context->deleteQuery(ids[i]); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + if (n < 0) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + for (GLsizei i = 0; i < n; i++) + { + context->deleteQuery(ids[i]); } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -6350,23 +5244,16 @@ GLboolean __stdcall glIsQuery(GLuint id) { EVENT("(GLuint id = %u)", id); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION, GL_FALSE); - } - - return (context->getQuery(id, false, GL_NONE) != NULL) ? GL_TRUE : GL_FALSE; + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return GL_FALSE; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); + + return (context->getQuery(id, false, GL_NONE) != NULL) ? GL_TRUE : GL_FALSE; } return GL_FALSE; @@ -6376,27 +5263,20 @@ void __stdcall glBeginQuery(GLenum target, GLuint id) { EVENT("(GLenum target = 0x%X, GLuint id = %u)", target, id); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (!ValidateBeginQuery(context, target, id)) - { - return; - } - context->beginQuery(target, id); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + if (!ValidateBeginQuery(context, target, id)) + { + return; + } + context->beginQuery(target, id); } } @@ -6404,28 +5284,21 @@ void __stdcall glEndQuery(GLenum target) { EVENT("(GLenum target = 0x%X)", target); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (!ValidateEndQuery(context, target)) - { - return; - } - - context->endQuery(target); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + if (!ValidateEndQuery(context, target)) + { + return; + } + + context->endQuery(target); } } @@ -6433,36 +5306,31 @@ void __stdcall glGetQueryiv(GLenum target, GLenum pname, GLint* params) { EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (!ValidQueryType(context, target)) - { - return gl::error(GL_INVALID_ENUM); - } - - switch (pname) - { - case GL_CURRENT_QUERY: - params[0] = static_cast(context->getActiveQueryId(target)); - break; - - default: - return gl::error(GL_INVALID_ENUM); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + if (!ValidQueryType(context, target)) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + + switch (pname) + { + case GL_CURRENT_QUERY: + params[0] = static_cast(context->getState().getActiveQueryId(target)); + break; + + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -6470,45 +5338,43 @@ void __stdcall glGetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params) { EVENT("(GLuint id = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", id, pname, params); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - gl::Query *queryObject = context->getQuery(id, false, GL_NONE); - - if (!queryObject) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (context->getActiveQueryId(queryObject->getType()) == id) - { - return gl::error(GL_INVALID_OPERATION); - } - - switch(pname) - { - case GL_QUERY_RESULT: - params[0] = queryObject->getResult(); - break; - case GL_QUERY_RESULT_AVAILABLE: - params[0] = queryObject->isResultAvailable(); - break; - default: - return gl::error(GL_INVALID_ENUM); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + gl::Query *queryObject = context->getQuery(id, false, GL_NONE); + + if (!queryObject) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + if (context->getState().getActiveQueryId(queryObject->getType()) == id) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + switch(pname) + { + case GL_QUERY_RESULT: + params[0] = queryObject->getResult(); + break; + + case GL_QUERY_RESULT_AVAILABLE: + params[0] = queryObject->isResultAvailable(); + break; + + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -6516,23 +5382,16 @@ GLboolean __stdcall glUnmapBuffer(GLenum target) { EVENT("(GLenum target = 0x%X)", target); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION, GL_FALSE); - } - - return glUnmapBufferOES(target); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return GL_FALSE; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); + + return glUnmapBufferOES(target); } return GL_FALSE; @@ -6542,45 +5401,31 @@ void __stdcall glGetBufferPointerv(GLenum target, GLenum pname, GLvoid** params) { EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLvoid** params = 0x%0.8p)", target, pname, params); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - glGetBufferPointervOES(target, pname, params); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + glGetBufferPointervOES(target, pname, params); } } void __stdcall glDrawBuffers(GLsizei n, const GLenum* bufs) { - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - glDrawBuffersEXT(n, bufs); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + glDrawBuffersEXT(n, bufs); } } @@ -6589,24 +5434,16 @@ void __stdcall glUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean tra EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", location, count, transpose, value); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2x3, location, count, transpose)) { - if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2x3, location, count, transpose)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - programBinary->setUniformMatrix2x3fv(location, count, transpose, value); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniformMatrix2x3fv(location, count, transpose, value); } } @@ -6615,24 +5452,16 @@ void __stdcall glUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean tra EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", location, count, transpose, value); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3x2, location, count, transpose)) { - if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3x2, location, count, transpose)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - programBinary->setUniformMatrix3x2fv(location, count, transpose, value); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniformMatrix3x2fv(location, count, transpose, value); } } @@ -6641,24 +5470,16 @@ void __stdcall glUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean tra EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", location, count, transpose, value); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2x4, location, count, transpose)) { - if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2x4, location, count, transpose)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - programBinary->setUniformMatrix2x4fv(location, count, transpose, value); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniformMatrix2x4fv(location, count, transpose, value); } } @@ -6667,24 +5488,16 @@ void __stdcall glUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean tra EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", location, count, transpose, value); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4x2, location, count, transpose)) { - if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4x2, location, count, transpose)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - programBinary->setUniformMatrix4x2fv(location, count, transpose, value); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniformMatrix4x2fv(location, count, transpose, value); } } @@ -6693,24 +5506,16 @@ void __stdcall glUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean tra EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", location, count, transpose, value); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3x4, location, count, transpose)) { - if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3x4, location, count, transpose)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - programBinary->setUniformMatrix3x4fv(location, count, transpose, value); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniformMatrix3x4fv(location, count, transpose, value); } } @@ -6719,24 +5524,16 @@ void __stdcall glUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean tra EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", location, count, transpose, value); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4x3, location, count, transpose)) { - if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4x3, location, count, transpose)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - programBinary->setUniformMatrix4x3fv(location, count, transpose, value); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniformMatrix4x3fv(location, count, transpose, value); } } @@ -6746,30 +5543,24 @@ void __stdcall glBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint sr "GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, GLbitfield mask = 0x%X, GLenum filter = 0x%X)", srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (!ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, - dstX0, dstY0, dstX1, dstY1, mask, filter, - false)) - { - return; - } - - context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, - mask, filter); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + if (!ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1, mask, filter, + false)) + { + return; + } + + context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, + mask, filter); } } @@ -6778,29 +5569,22 @@ void __stdcall glRenderbufferStorageMultisample(GLenum target, GLsizei samples, EVENT("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)", target, samples, internalformat, width, height); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (!ValidateRenderbufferStorageParameters(context, target, samples, internalformat, - width, height, false)) - { - return; - } - - context->setRenderbufferStorage(width, height, internalformat, samples); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + if (!ValidateRenderbufferStorageParameters(context, target, samples, internalformat, + width, height, false)) + { + return; + } + + context->setRenderbufferStorage(width, height, internalformat, samples); } } @@ -6809,48 +5593,36 @@ void __stdcall glFramebufferTextureLayer(GLenum target, GLenum attachment, GLuin EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLuint texture = %u, GLint level = %d, GLint layer = %d)", target, attachment, texture, level, layer); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!ValidateFramebufferTextureLayer(context, target, attachment, texture, + level, layer)) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } + return; + } - if (!ValidateES3FramebufferTextureParameters(context, target, attachment, GL_NONE, texture, level, layer, true)) - { - return; - } + gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); + ASSERT(framebuffer); - gl::Framebuffer *framebuffer = context->getTargetFramebuffer(target); - ASSERT(framebuffer); + gl::Texture *textureObject = context->getTexture(texture); + GLenum textarget = textureObject ? textureObject->getTarget() : GL_NONE; - gl::Texture *textureObject = context->getTexture(texture); - GLenum textarget = textureObject ? textureObject->getTarget() : GL_NONE; - - if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) + if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) + { + const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT); + framebuffer->setColorbuffer(colorAttachment, textarget, texture, level, layer); + } + else + { + switch (attachment) { - const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT); - framebuffer->setColorbuffer(colorAttachment, textarget, texture, level, layer); - } - else - { - switch (attachment) - { - case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture, level, layer); break; - case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture, level, layer); break; - case GL_DEPTH_STENCIL_ATTACHMENT: framebuffer->setDepthStencilBuffer(textarget, texture, level, layer); break; - } + case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture, level, layer); break; + case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture, level, layer); break; + case GL_DEPTH_STENCIL_ATTACHMENT: framebuffer->setDepthStencilBuffer(textarget, texture, level, layer); break; } } } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); - } } GLvoid* __stdcall glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) @@ -6858,23 +5630,16 @@ GLvoid* __stdcall glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr le EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d, GLbitfield access = 0x%X)", target, offset, length, access); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION, reinterpret_cast(NULL)); - } - - return glMapBufferRangeEXT(target, offset, length, access); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return NULL; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY, reinterpret_cast(NULL)); + + return glMapBufferRangeEXT(target, offset, length, access); } return NULL; @@ -6884,23 +5649,16 @@ void __stdcall glFlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeip { EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d)", target, offset, length); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - glFlushMappedBufferRangeEXT(target, offset, length); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + glFlushMappedBufferRangeEXT(target, offset, length); } } @@ -6908,32 +5666,26 @@ void __stdcall glBindVertexArray(GLuint array) { EVENT("(GLuint array = %u)", array); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - gl::VertexArray *vao = context->getVertexArray(array); - - if (!vao) - { - // The default VAO should always exist - ASSERT(array != 0); - return gl::error(GL_INVALID_OPERATION); - } - - context->bindVertexArray(array); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + gl::VertexArray *vao = context->getVertexArray(array); + + if (!vao) + { + // The default VAO should always exist + ASSERT(array != 0); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + context->bindVertexArray(array); } } @@ -6941,66 +5693,54 @@ void __stdcall glDeleteVertexArrays(GLsizei n, const GLuint* arrays) { EVENT("(GLsizei n = %d, const GLuint* arrays = 0x%0.8p)", n, arrays); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } - if (n < 0) - { - return gl::error(GL_INVALID_VALUE); - } + if (n < 0) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } - for (int arrayIndex = 0; arrayIndex < n; arrayIndex++) + for (int arrayIndex = 0; arrayIndex < n; arrayIndex++) + { + if (arrays[arrayIndex] != 0) { - if (arrays[arrayIndex] != 0) - { - context->deleteVertexArray(arrays[arrayIndex]); - } + context->deleteVertexArray(arrays[arrayIndex]); } } } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glGenVertexArrays(GLsizei n, GLuint* arrays) { EVENT("(GLsizei n = %d, GLuint* arrays = 0x%0.8p)", n, arrays); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (n < 0) - { - return gl::error(GL_INVALID_VALUE); - } - - for (int arrayIndex = 0; arrayIndex < n; arrayIndex++) - { - arrays[arrayIndex] = context->createVertexArray(); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + if (n < 0) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + for (int arrayIndex = 0; arrayIndex < n; arrayIndex++) + { + arrays[arrayIndex] = context->createVertexArray(); } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -7008,30 +5748,23 @@ GLboolean __stdcall glIsVertexArray(GLuint array) { EVENT("(GLuint array = %u)", array); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION, GL_FALSE); - } - - if (array == 0) - { - return GL_FALSE; - } - - gl::VertexArray *vao = context->getVertexArray(array); - - return (vao != NULL ? GL_TRUE : GL_FALSE); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return GL_FALSE; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); + + if (array == 0) + { + return GL_FALSE; + } + + gl::VertexArray *vao = context->getVertexArray(array); + + return (vao != NULL ? GL_TRUE : GL_FALSE); } return GL_FALSE; @@ -7042,120 +5775,124 @@ void __stdcall glGetIntegeri_v(GLenum target, GLuint index, GLint* data) EVENT("(GLenum target = 0x%X, GLuint index = %u, GLint* data = 0x%0.8p)", target, index, data); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + const gl::Caps &caps = context->getCaps(); + switch (target) + { + case GL_TRANSFORM_FEEDBACK_BUFFER_START: + case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: + case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: + if (index >= caps.maxTransformFeedbackSeparateAttributes) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + break; + + case GL_UNIFORM_BUFFER_START: + case GL_UNIFORM_BUFFER_SIZE: + case GL_UNIFORM_BUFFER_BINDING: + if (index >= caps.maxCombinedUniformBlocks) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + break; + + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + + if (!(context->getIndexedIntegerv(target, index, data))) + { + GLenum nativeType; + unsigned int numParams = 0; + if (!context->getIndexedQueryParameterInfo(target, &nativeType, &numParams)) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - switch (target) + if (numParams == 0) { - case GL_TRANSFORM_FEEDBACK_BUFFER_START: - case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: - case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: - if (index >= context->getMaxTransformFeedbackBufferBindings()) - return gl::error(GL_INVALID_VALUE); - break; - case GL_UNIFORM_BUFFER_START: - case GL_UNIFORM_BUFFER_SIZE: - case GL_UNIFORM_BUFFER_BINDING: - if (index >= context->getMaximumCombinedUniformBufferBindings()) - return gl::error(GL_INVALID_VALUE); - break; - default: - return gl::error(GL_INVALID_ENUM); + return; // it is known that pname is valid, but there are no parameters to return } - if (!(context->getIndexedIntegerv(target, index, data))) + if (nativeType == GL_INT_64_ANGLEX) { - GLenum nativeType; - unsigned int numParams = 0; - if (!context->getIndexedQueryParameterInfo(target, &nativeType, &numParams)) - return gl::error(GL_INVALID_ENUM); + GLint64 minIntValue = static_cast(std::numeric_limits::min()); + GLint64 maxIntValue = static_cast(std::numeric_limits::max()); + GLint64 *int64Params = new GLint64[numParams]; - if (numParams == 0) - return; // it is known that pname is valid, but there are no parameters to return + context->getIndexedInteger64v(target, index, int64Params); - if (nativeType == GL_INT_64_ANGLEX) + for (unsigned int i = 0; i < numParams; ++i) { - GLint64 minIntValue = static_cast(std::numeric_limits::min()); - GLint64 maxIntValue = static_cast(std::numeric_limits::max()); - GLint64 *int64Params = new GLint64[numParams]; - - context->getIndexedInteger64v(target, index, int64Params); - - for (unsigned int i = 0; i < numParams; ++i) - { - GLint64 clampedValue = std::max(std::min(int64Params[i], maxIntValue), minIntValue); - data[i] = static_cast(clampedValue); - } - - delete [] int64Params; - } - else - { - UNREACHABLE(); + GLint64 clampedValue = std::max(std::min(int64Params[i], maxIntValue), minIntValue); + data[i] = static_cast(clampedValue); } + + delete [] int64Params; + } + else + { + UNREACHABLE(); } } } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glBeginTransformFeedback(GLenum primitiveMode) { EVENT("(GLenum primitiveMode = 0x%X)", primitiveMode); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - switch (primitiveMode) - { - case GL_TRIANGLES: - case GL_LINES: - case GL_POINTS: - break; - default: - return gl::error(GL_INVALID_ENUM); - } - - gl::TransformFeedback *transformFeedback = context->getCurrentTransformFeedback(); - ASSERT(transformFeedback != NULL); - - if (transformFeedback->isStarted()) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (transformFeedback->isPaused()) - { - transformFeedback->resume(); - } - else - { - transformFeedback->start(primitiveMode); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + switch (primitiveMode) + { + case GL_TRIANGLES: + case GL_LINES: + case GL_POINTS: + break; + + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + + gl::TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback(); + ASSERT(transformFeedback != NULL); + + if (transformFeedback->isStarted()) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + if (transformFeedback->isPaused()) + { + transformFeedback->resume(); + } + else + { + transformFeedback->start(primitiveMode); } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -7163,31 +5900,25 @@ void __stdcall glEndTransformFeedback(void) { EVENT("(void)"); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - gl::TransformFeedback *transformFeedback = context->getCurrentTransformFeedback(); - ASSERT(transformFeedback != NULL); - - if (!transformFeedback->isStarted()) - { - return gl::error(GL_INVALID_OPERATION); - } - - transformFeedback->stop(); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + gl::TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback(); + ASSERT(transformFeedback != NULL); + + if (!transformFeedback->isStarted()) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + transformFeedback->stop(); } } @@ -7196,76 +5927,76 @@ void __stdcall glBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLi EVENT("(GLenum target = 0x%X, GLuint index = %u, GLuint buffer = %u, GLintptr offset = %d, GLsizeiptr size = %d)", target, index, buffer, offset, size); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - switch (target) - { - case GL_TRANSFORM_FEEDBACK_BUFFER: - if (index >= context->getMaxTransformFeedbackBufferBindings()) - { - return gl::error(GL_INVALID_VALUE); - } - break; - - case GL_UNIFORM_BUFFER: - if (index >= context->getMaximumCombinedUniformBufferBindings()) - { - return gl::error(GL_INVALID_VALUE); - } - break; - - default: - return gl::error(GL_INVALID_ENUM); - } - - if (buffer != 0 && size <= 0) - { - return gl::error(GL_INVALID_VALUE); - } - - switch (target) - { - case GL_TRANSFORM_FEEDBACK_BUFFER: - - // size and offset must be a multiple of 4 - if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0)) - { - return gl::error(GL_INVALID_VALUE); - } - - context->bindIndexedTransformFeedbackBuffer(buffer, index, offset, size); - context->bindGenericTransformFeedbackBuffer(buffer); - break; - - case GL_UNIFORM_BUFFER: - - // it is an error to bind an offset not a multiple of the alignment - if (buffer != 0 && (offset % context->getUniformBufferOffsetAlignment()) != 0) - { - return gl::error(GL_INVALID_VALUE); - } - - context->bindIndexedUniformBuffer(buffer, index, offset, size); - context->bindGenericUniformBuffer(buffer); - break; - - default: - UNREACHABLE(); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + const gl::Caps &caps = context->getCaps(); + switch (target) + { + case GL_TRANSFORM_FEEDBACK_BUFFER: + if (index >= caps.maxTransformFeedbackSeparateAttributes) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + break; + + case GL_UNIFORM_BUFFER: + if (index >= caps.maxUniformBufferBindings) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + break; + + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + + if (buffer != 0 && size <= 0) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + switch (target) + { + case GL_TRANSFORM_FEEDBACK_BUFFER: + + // size and offset must be a multiple of 4 + if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0)) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + context->bindIndexedTransformFeedbackBuffer(buffer, index, offset, size); + context->bindGenericTransformFeedbackBuffer(buffer); + break; + + case GL_UNIFORM_BUFFER: + + // it is an error to bind an offset not a multiple of the alignment + if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + context->bindIndexedUniformBuffer(buffer, index, offset, size); + context->bindGenericUniformBuffer(buffer); + break; + + default: + UNREACHABLE(); } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -7274,57 +6005,54 @@ void __stdcall glBindBufferBase(GLenum target, GLuint index, GLuint buffer) EVENT("(GLenum target = 0x%X, GLuint index = %u, GLuint buffer = %u)", target, index, buffer); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - switch (target) - { - case GL_TRANSFORM_FEEDBACK_BUFFER: - if (index >= context->getMaxTransformFeedbackBufferBindings()) - { - return gl::error(GL_INVALID_VALUE); - } - break; - - case GL_UNIFORM_BUFFER: - if (index >= context->getMaximumCombinedUniformBufferBindings()) - { - return gl::error(GL_INVALID_VALUE); - } - break; - - default: - return gl::error(GL_INVALID_ENUM); - } - - switch (target) - { - case GL_TRANSFORM_FEEDBACK_BUFFER: - context->bindIndexedTransformFeedbackBuffer(buffer, index, 0, 0); - context->bindGenericTransformFeedbackBuffer(buffer); - break; - - case GL_UNIFORM_BUFFER: - context->bindIndexedUniformBuffer(buffer, index, 0, 0); - context->bindGenericUniformBuffer(buffer); - break; - - default: - UNREACHABLE(); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + const gl::Caps &caps = context->getCaps(); + switch (target) + { + case GL_TRANSFORM_FEEDBACK_BUFFER: + if (index >= caps.maxTransformFeedbackSeparateAttributes) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + break; + + case GL_UNIFORM_BUFFER: + if (index >= caps.maxUniformBufferBindings) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + break; + + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + + switch (target) + { + case GL_TRANSFORM_FEEDBACK_BUFFER: + context->bindIndexedTransformFeedbackBuffer(buffer, index, 0, 0); + context->bindGenericTransformFeedbackBuffer(buffer); + break; + + case GL_UNIFORM_BUFFER: + context->bindIndexedUniformBuffer(buffer, index, 0, 0); + context->bindGenericUniformBuffer(buffer); + break; + + default: + UNREACHABLE(); } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -7333,50 +6061,47 @@ void __stdcall glTransformFeedbackVaryings(GLuint program, GLsizei count, const EVENT("(GLuint program = %u, GLsizei count = %d, const GLchar* const* varyings = 0x%0.8p, GLenum bufferMode = 0x%X)", program, count, varyings, bufferMode); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } - if (count < 0) - { - return gl::error(GL_INVALID_VALUE); - } + if (count < 0) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } - switch (bufferMode) - { - case GL_INTERLEAVED_ATTRIBS: - break; - case GL_SEPARATE_ATTRIBS: - if (static_cast(count) > context->getMaxTransformFeedbackBufferBindings()) - { - return gl::error(GL_INVALID_VALUE); - } - break; - default: - return gl::error(GL_INVALID_ENUM); - } - - if (!gl::ValidProgram(context, program)) + const gl::Caps &caps = context->getCaps(); + switch (bufferMode) + { + case GL_INTERLEAVED_ATTRIBS: + break; + case GL_SEPARATE_ATTRIBS: + if (static_cast(count) > caps.maxTransformFeedbackSeparateAttributes) { + context->recordError(gl::Error(GL_INVALID_VALUE)); return; } - - gl::Program *programObject = context->getProgram(program); - ASSERT(programObject); - - programObject->setTransformFeedbackVaryings(count, varyings, bufferMode); + break; + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + if (!gl::ValidProgram(context, program)) + { + return; + } + + gl::Program *programObject = context->getProgram(program); + ASSERT(programObject); + + programObject->setTransformFeedbackVaryings(count, varyings, bufferMode); } } @@ -7386,41 +6111,36 @@ void __stdcall glGetTransformFeedbackVarying(GLuint program, GLuint index, GLsiz "GLsizei* size = 0x%0.8p, GLenum* type = 0x%0.8p, GLchar* name = 0x%0.8p)", program, index, bufSize, length, size, type, name); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (bufSize < 0) - { - return gl::error(GL_INVALID_VALUE); - } - - if (!gl::ValidProgram(context, program)) - { - return; - } - - gl::Program *programObject = context->getProgram(program); - ASSERT(programObject); - - if (index >= static_cast(programObject->getTransformFeedbackVaryingCount())) - { - return gl::error(GL_INVALID_VALUE); - } - - programObject->getTransformFeedbackVarying(index, bufSize, length, size, type, name); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + if (bufSize < 0) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + if (!gl::ValidProgram(context, program)) + { + return; + } + + gl::Program *programObject = context->getProgram(program); + ASSERT(programObject); + + if (index >= static_cast(programObject->getTransformFeedbackVaryingCount())) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + programObject->getTransformFeedbackVarying(index, bufSize, length, size, type, name); } } @@ -7429,26 +6149,25 @@ void __stdcall glVertexAttribIPointer(GLuint index, GLint size, GLenum type, GLs EVENT("(GLuint index = %u, GLint size = %d, GLenum type = 0x%X, GLsizei stride = %d, const GLvoid* pointer = 0x%0.8p)", index, size, type, stride, pointer); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } if (index >= gl::MAX_VERTEX_ATTRIBS) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } if (size < 1 || size > 4) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } switch (type) @@ -7462,38 +6181,36 @@ void __stdcall glVertexAttribIPointer(GLuint index, GLint size, GLenum type, GLs case GL_INT_2_10_10_10_REV: case GL_UNSIGNED_INT_2_10_10_10_REV: break; + default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } if (stride < 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } if ((type == GL_INT_2_10_10_10_REV || type == GL_UNSIGNED_INT_2_10_10_10_REV) && size != 4) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - if (context) + // [OpenGL ES 3.0.2] Section 2.8 page 24: + // An INVALID_OPERATION error is generated when a non-zero vertex array object + // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point, + // and the pointer argument is not NULL. + if (context->getState().getVertexArray()->id() != 0 && context->getState().getArrayBufferId() == 0 && pointer != NULL) { - // [OpenGL ES 3.0.2] Section 2.8 page 24: - // An INVALID_OPERATION error is generated when a non-zero vertex array object - // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point, - // and the pointer argument is not NULL. - if (context->getVertexArrayHandle() != 0 && context->getArrayBufferHandle() == 0 && pointer != NULL) - { - return gl::error(GL_INVALID_OPERATION); - } - - context->setVertexAttribState(index, context->getArrayBuffer(), size, type, false, true, - stride, pointer); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + context->getState().setVertexAttribState(index, context->getState().getTargetBuffer(GL_ARRAY_BUFFER), size, type, false, true, + stride, pointer); } } @@ -7502,46 +6219,40 @@ void __stdcall glGetVertexAttribIiv(GLuint index, GLenum pname, GLint* params) EVENT("(GLuint index = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", index, pname, params); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - return gl::error(GL_INVALID_VALUE); - } + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } - const gl::VertexAttribute &attribState = context->getVertexAttribState(index); + const gl::VertexAttribute &attribState = context->getState().getVertexAttribState(index); - if (!gl::ValidateGetVertexAttribParameters(pname, context->getClientVersion())) - { - return; - } + if (!gl::ValidateGetVertexAttribParameters(context, pname)) + { + return; + } - if (pname == GL_CURRENT_VERTEX_ATTRIB) + if (pname == GL_CURRENT_VERTEX_ATTRIB) + { + const gl::VertexAttribCurrentValueData ¤tValueData = context->getState().getVertexAttribCurrentValue(index); + for (int i = 0; i < 4; ++i) { - const gl::VertexAttribCurrentValueData ¤tValueData = context->getVertexAttribCurrentValue(index); - for (int i = 0; i < 4; ++i) - { - params[i] = currentValueData.IntValues[i]; - } - } - else - { - *params = attribState.querySingleParameter(pname); + params[i] = currentValueData.IntValues[i]; } } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + else + { + *params = gl::QuerySingleVertexAttributeParameter(attribState, pname); + } } } @@ -7550,46 +6261,40 @@ void __stdcall glGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params) EVENT("(GLuint index = %u, GLenum pname = 0x%X, GLuint* params = 0x%0.8p)", index, pname, params); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - return gl::error(GL_INVALID_VALUE); - } + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } - const gl::VertexAttribute &attribState = context->getVertexAttribState(index); + const gl::VertexAttribute &attribState = context->getState().getVertexAttribState(index); - if (!gl::ValidateGetVertexAttribParameters(pname, context->getClientVersion())) - { - return; - } + if (!gl::ValidateGetVertexAttribParameters(context, pname)) + { + return; + } - if (pname == GL_CURRENT_VERTEX_ATTRIB) + if (pname == GL_CURRENT_VERTEX_ATTRIB) + { + const gl::VertexAttribCurrentValueData ¤tValueData = context->getState().getVertexAttribCurrentValue(index); + for (int i = 0; i < 4; ++i) { - const gl::VertexAttribCurrentValueData ¤tValueData = context->getVertexAttribCurrentValue(index); - for (int i = 0; i < 4; ++i) - { - params[i] = currentValueData.UnsignedIntValues[i]; - } - } - else - { - *params = attribState.querySingleParameter(pname); + params[i] = currentValueData.UnsignedIntValues[i]; } } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + else + { + *params = gl::QuerySingleVertexAttributeParameter(attribState, pname); + } } } @@ -7598,29 +6303,23 @@ void __stdcall glVertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint EVENT("(GLuint index = %u, GLint x = %d, GLint y = %d, GLint z = %d, GLint w = %d)", index, x, y, z, w); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - return gl::error(GL_INVALID_VALUE); - } - - GLint vals[4] = { x, y, z, w }; - context->setVertexAttribi(index, vals); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + GLint vals[4] = { x, y, z, w }; + context->getState().setVertexAttribi(index, vals); } } @@ -7629,29 +6328,23 @@ void __stdcall glVertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GL EVENT("(GLuint index = %u, GLuint x = %u, GLuint y = %u, GLuint z = %u, GLuint w = %u)", index, x, y, z, w); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - return gl::error(GL_INVALID_VALUE); - } - - GLuint vals[4] = { x, y, z, w }; - context->setVertexAttribu(index, vals); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + GLuint vals[4] = { x, y, z, w }; + context->getState().setVertexAttribu(index, vals); } } @@ -7659,28 +6352,22 @@ void __stdcall glVertexAttribI4iv(GLuint index, const GLint* v) { EVENT("(GLuint index = %u, const GLint* v = 0x%0.8p)", index, v); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - return gl::error(GL_INVALID_VALUE); - } - - context->setVertexAttribi(index, v); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + context->getState().setVertexAttribi(index, v); } } @@ -7688,28 +6375,22 @@ void __stdcall glVertexAttribI4uiv(GLuint index, const GLuint* v) { EVENT("(GLuint index = %u, const GLuint* v = 0x%0.8p)", index, v); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - return gl::error(GL_INVALID_VALUE); - } - - context->setVertexAttribu(index, v); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + context->getState().setVertexAttribu(index, v); } } @@ -7718,44 +6399,20 @@ void __stdcall glGetUniformuiv(GLuint program, GLint location, GLuint* params) EVENT("(GLuint program = %u, GLint location = %d, GLuint* params = 0x%0.8p)", program, location, params); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!ValidateGetUniformuiv(context, program, location, params)) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (program == 0) - { - return gl::error(GL_INVALID_VALUE); - } - - gl::Program *programObject = context->getProgram(program); - - if (!programObject || !programObject->isLinked()) - { - return gl::error(GL_INVALID_OPERATION); - } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (!programBinary) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (!programBinary->getUniformuiv(location, NULL, params)) - { - return gl::error(GL_INVALID_OPERATION); - } + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + gl::Program *programObject = context->getProgram(program); + ASSERT(programObject); + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + ASSERT(programBinary); + + programBinary->getUniformuiv(location, params); } } @@ -7764,41 +6421,37 @@ GLint __stdcall glGetFragDataLocation(GLuint program, const GLchar *name) EVENT("(GLuint program = %u, const GLchar *name = 0x%0.8p)", program, name); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION, -1); - } - - if (program == 0) - { - return gl::error(GL_INVALID_VALUE, -1); - } - - gl::Program *programObject = context->getProgram(program); - - if (!programObject || !programObject->isLinked()) - { - return gl::error(GL_INVALID_OPERATION, -1); - } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (!programBinary) - { - return gl::error(GL_INVALID_OPERATION, -1); - } - - return programBinary->getFragDataLocation(name); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return -1; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY, 0); + + if (program == 0) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return -1; + } + + gl::Program *programObject = context->getProgram(program); + + if (!programObject || !programObject->isLinked()) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return -1; + } + + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + if (!programBinary) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return -1; + } + + return programBinary->getFragDataLocation(name); } return 0; @@ -7832,24 +6485,16 @@ void __stdcall glUniform1uiv(GLint location, GLsizei count, const GLuint* value) EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)", location, count, value); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!ValidateUniform(context, GL_UNSIGNED_INT, location, count)) { - if (!ValidateUniform(context, GL_UNSIGNED_INT, location, count)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - programBinary->setUniform1uiv(location, count, value); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniform1uiv(location, count, value); } } @@ -7858,24 +6503,16 @@ void __stdcall glUniform2uiv(GLint location, GLsizei count, const GLuint* value) EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)", location, count, value); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC2, location, count)) { - if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC2, location, count)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - programBinary->setUniform2uiv(location, count, value); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniform2uiv(location, count, value); } } @@ -7884,24 +6521,16 @@ void __stdcall glUniform3uiv(GLint location, GLsizei count, const GLuint* value) EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value)", location, count, value); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC3, location, count)) { - if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC3, location, count)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - programBinary->setUniform3uiv(location, count, value); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniform3uiv(location, count, value); } } @@ -7910,24 +6539,16 @@ void __stdcall glUniform4uiv(GLint location, GLsizei count, const GLuint* value) EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)", location, count, value); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC4, location, count)) { - if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC4, location, count)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - programBinary->setUniform4uiv(location, count, value); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniform4uiv(location, count, value); } } @@ -7936,41 +6557,38 @@ void __stdcall glClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* val EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLint* value = 0x%0.8p)", buffer, drawbuffer, value); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!ValidateClearBuffer(context)) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - switch (buffer) - { - case GL_COLOR: - if (drawbuffer < 0 || drawbuffer >= static_cast(context->getMaximumRenderTargets())) - { - return gl::error(GL_INVALID_VALUE); - } - break; - case GL_STENCIL: - if (drawbuffer != 0) - { - return gl::error(GL_INVALID_VALUE); - } - break; - default: - return gl::error(GL_INVALID_ENUM); - } - - context->clearBufferiv(buffer, drawbuffer, value); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + switch (buffer) + { + case GL_COLOR: + if (drawbuffer < 0 || static_cast(drawbuffer) >= context->getCaps().maxDrawBuffers) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + break; + + case GL_STENCIL: + if (drawbuffer != 0) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + break; + + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + + context->clearBufferiv(buffer, drawbuffer, value); } } @@ -7979,35 +6597,30 @@ void __stdcall glClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* v EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLuint* value = 0x%0.8p)", buffer, drawbuffer, value); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!ValidateClearBuffer(context)) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - switch (buffer) - { - case GL_COLOR: - if (drawbuffer < 0 || drawbuffer >= static_cast(context->getMaximumRenderTargets())) - { - return gl::error(GL_INVALID_VALUE); - } - break; - default: - return gl::error(GL_INVALID_ENUM); - } - - context->clearBufferuiv(buffer, drawbuffer, value); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + switch (buffer) + { + case GL_COLOR: + if (drawbuffer < 0 || static_cast(drawbuffer) >= context->getCaps().maxDrawBuffers) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + break; + + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + + context->clearBufferuiv(buffer, drawbuffer, value); } } @@ -8016,41 +6629,38 @@ void __stdcall glClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* v EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLfloat* value = 0x%0.8p)", buffer, drawbuffer, value); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!ValidateClearBuffer(context)) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - switch (buffer) - { - case GL_COLOR: - if (drawbuffer < 0 || drawbuffer >= static_cast(context->getMaximumRenderTargets())) - { - return gl::error(GL_INVALID_VALUE); - } - break; - case GL_DEPTH: - if (drawbuffer != 0) - { - return gl::error(GL_INVALID_VALUE); - } - break; - default: - return gl::error(GL_INVALID_ENUM); - } - - context->clearBufferfv(buffer, drawbuffer, value); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + switch (buffer) + { + case GL_COLOR: + if (drawbuffer < 0 || static_cast(drawbuffer) >= context->getCaps().maxDrawBuffers) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + break; + + case GL_DEPTH: + if (drawbuffer != 0) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + break; + + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + + context->clearBufferfv(buffer, drawbuffer, value); } } @@ -8059,35 +6669,30 @@ void __stdcall glClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, G EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, GLfloat depth, GLint stencil = %d)", buffer, drawbuffer, depth, stencil); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!ValidateClearBuffer(context)) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - switch (buffer) - { - case GL_DEPTH_STENCIL: - if (drawbuffer != 0) - { - return gl::error(GL_INVALID_VALUE); - } - break; - default: - return gl::error(GL_INVALID_ENUM); - } - - context->clearBufferfi(buffer, drawbuffer, depth, stencil); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + switch (buffer) + { + case GL_DEPTH_STENCIL: + if (drawbuffer != 0) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + break; + + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + + context->clearBufferfi(buffer, drawbuffer, depth, stencil); } } @@ -8095,33 +6700,28 @@ const GLubyte* __stdcall glGetStringi(GLenum name, GLuint index) { EVENT("(GLenum name = 0x%X, GLuint index = %u)", name, index); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION, reinterpret_cast(NULL)); - } - - if (name != GL_EXTENSIONS) - { - return gl::error(GL_INVALID_ENUM, reinterpret_cast(NULL)); - } - - if (index >= context->getNumExtensions()) - { - return gl::error(GL_INVALID_VALUE, reinterpret_cast(NULL)); - } - - return reinterpret_cast(context->getExtensionString(index)); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return NULL; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY, reinterpret_cast(NULL)); + + if (name != GL_EXTENSIONS) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return NULL; + } + + if (index >= context->getExtensionStringCount()) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return NULL; + } + + return reinterpret_cast(context->getExtensionString(index).c_str()); } return NULL; @@ -8132,59 +6732,56 @@ void __stdcall glCopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintp EVENT("(GLenum readTarget = 0x%X, GLenum writeTarget = 0x%X, GLintptr readOffset = %d, GLintptr writeOffset = %d, GLsizeiptr size = %d)", readTarget, writeTarget, readOffset, writeOffset, size); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (!gl::ValidBufferTarget(context, readTarget) || !gl::ValidBufferTarget(context, readTarget)) - { - return gl::error(GL_INVALID_ENUM); - } - - gl::Buffer *readBuffer = context->getTargetBuffer(readTarget); - gl::Buffer *writeBuffer = context->getTargetBuffer(writeTarget); - - if (!readBuffer || !writeBuffer) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (readBuffer->mapped() || writeBuffer->mapped()) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (readOffset < 0 || writeOffset < 0 || size < 0 || - static_cast(readOffset + size) > readBuffer->size() || - static_cast(writeOffset + size) > writeBuffer->size()) - { - return gl::error(GL_INVALID_VALUE); - } - - if (readBuffer == writeBuffer && abs(readOffset - writeOffset) < size) - { - return gl::error(GL_INVALID_VALUE); - } - - // TODO: Verify that readBuffer and writeBuffer are not currently mapped (GL_INVALID_OPERATION) - - // if size is zero, the copy is a successful no-op - if (size > 0) - { - writeBuffer->copyBufferSubData(readBuffer, readOffset, writeOffset, size); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + if (!gl::ValidBufferTarget(context, readTarget) || !gl::ValidBufferTarget(context, readTarget)) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + + gl::Buffer *readBuffer = context->getState().getTargetBuffer(readTarget); + gl::Buffer *writeBuffer = context->getState().getTargetBuffer(writeTarget); + + if (!readBuffer || !writeBuffer) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + // Verify that readBuffer and writeBuffer are not currently mapped + if (readBuffer->isMapped() || writeBuffer->isMapped()) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + if (readOffset < 0 || writeOffset < 0 || size < 0 || + static_cast(readOffset + size) > readBuffer->getSize() || + static_cast(writeOffset + size) > writeBuffer->getSize()) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + if (readBuffer == writeBuffer && abs(readOffset - writeOffset) < size) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + // if size is zero, the copy is a successful no-op + if (size > 0) + { + writeBuffer->copyBufferSubData(readBuffer, readOffset, writeOffset, size); } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -8193,56 +6790,52 @@ void __stdcall glGetUniformIndices(GLuint program, GLsizei uniformCount, const G EVENT("(GLuint program = %u, GLsizei uniformCount = %d, const GLchar* const* uniformNames = 0x%0.8p, GLuint* uniformIndices = 0x%0.8p)", program, uniformCount, uniformNames, uniformIndices); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } - if (uniformCount < 0) - { - return gl::error(GL_INVALID_VALUE); - } + if (uniformCount < 0) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } - gl::Program *programObject = context->getProgram(program); + gl::Program *programObject = context->getProgram(program); - if (!programObject) + if (!programObject) + { + if (context->getShader(program)) { - if (context->getShader(program)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } - } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (!programObject->isLinked() || !programBinary) - { - for (int uniformId = 0; uniformId < uniformCount; uniformId++) - { - uniformIndices[uniformId] = GL_INVALID_INDEX; - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } else { - for (int uniformId = 0; uniformId < uniformCount; uniformId++) - { - uniformIndices[uniformId] = programBinary->getUniformIndex(uniformNames[uniformId]); - } + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + } + + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + if (!programObject->isLinked() || !programBinary) + { + for (int uniformId = 0; uniformId < uniformCount; uniformId++) + { + uniformIndices[uniformId] = GL_INVALID_INDEX; + } + } + else + { + for (int uniformId = 0; uniformId < uniformCount; uniformId++) + { + uniformIndices[uniformId] = programBinary->getUniformIndex(uniformNames[uniformId]); } } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -8251,78 +6844,78 @@ void __stdcall glGetActiveUniformsiv(GLuint program, GLsizei uniformCount, const EVENT("(GLuint program = %u, GLsizei uniformCount = %d, const GLuint* uniformIndices = 0x%0.8p, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", program, uniformCount, uniformIndices, pname, params); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + if (uniformCount < 0) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + gl::Program *programObject = context->getProgram(program); + + if (!programObject) + { + if (context->getShader(program)) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - - if (uniformCount < 0) + else { - return gl::error(GL_INVALID_VALUE); - } - - gl::Program *programObject = context->getProgram(program); - - if (!programObject) - { - if (context->getShader(program)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } - } - - switch (pname) - { - case GL_UNIFORM_TYPE: - case GL_UNIFORM_SIZE: - case GL_UNIFORM_NAME_LENGTH: - case GL_UNIFORM_BLOCK_INDEX: - case GL_UNIFORM_OFFSET: - case GL_UNIFORM_ARRAY_STRIDE: - case GL_UNIFORM_MATRIX_STRIDE: - case GL_UNIFORM_IS_ROW_MAJOR: - break; - default: - return gl::error(GL_INVALID_ENUM); - } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - - if (!programBinary && uniformCount > 0) - { - return gl::error(GL_INVALID_VALUE); - } - - for (int uniformId = 0; uniformId < uniformCount; uniformId++) - { - const GLuint index = uniformIndices[uniformId]; - - if (index >= (GLuint)programBinary->getActiveUniformCount()) - { - return gl::error(GL_INVALID_VALUE); - } - } - - for (int uniformId = 0; uniformId < uniformCount; uniformId++) - { - const GLuint index = uniformIndices[uniformId]; - params[uniformId] = programBinary->getActiveUniformi(index, pname); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + switch (pname) + { + case GL_UNIFORM_TYPE: + case GL_UNIFORM_SIZE: + case GL_UNIFORM_NAME_LENGTH: + case GL_UNIFORM_BLOCK_INDEX: + case GL_UNIFORM_OFFSET: + case GL_UNIFORM_ARRAY_STRIDE: + case GL_UNIFORM_MATRIX_STRIDE: + case GL_UNIFORM_IS_ROW_MAJOR: + break; + + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + + if (!programBinary && uniformCount > 0) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + for (int uniformId = 0; uniformId < uniformCount; uniformId++) + { + const GLuint index = uniformIndices[uniformId]; + + if (index >= (GLuint)programBinary->getActiveUniformCount()) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + } + + for (int uniformId = 0; uniformId < uniformCount; uniformId++) + { + const GLuint index = uniformIndices[uniformId]; + params[uniformId] = programBinary->getActiveUniformi(index, pname); + } } } @@ -8330,43 +6923,38 @@ GLuint __stdcall glGetUniformBlockIndex(GLuint program, const GLchar* uniformBlo { EVENT("(GLuint program = %u, const GLchar* uniformBlockName = 0x%0.8p)", program, uniformBlockName); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION, GL_INVALID_INDEX); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return GL_INVALID_INDEX; + } - gl::Program *programObject = context->getProgram(program); + gl::Program *programObject = context->getProgram(program); - if (!programObject) - { - if (context->getShader(program)) - { - return gl::error(GL_INVALID_OPERATION, GL_INVALID_INDEX); - } - else - { - return gl::error(GL_INVALID_VALUE, GL_INVALID_INDEX); - } - } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (!programBinary) + if (!programObject) + { + if (context->getShader(program)) { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return GL_INVALID_INDEX; + } + else + { + context->recordError(gl::Error(GL_INVALID_VALUE)); return GL_INVALID_INDEX; } - - return programBinary->getUniformBlockIndex(uniformBlockName); } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY, 0); + + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + if (!programBinary) + { + return GL_INVALID_INDEX; + } + + return programBinary->getUniformBlockIndex(uniformBlockName); } return 0; @@ -8377,60 +6965,57 @@ void __stdcall glGetActiveUniformBlockiv(GLuint program, GLuint uniformBlockInde EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", program, uniformBlockIndex, pname, params); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + gl::Program *programObject = context->getProgram(program); + + if (!programObject) + { + if (context->getShader(program)) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - gl::Program *programObject = context->getProgram(program); - - if (!programObject) + else { - if (context->getShader(program)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } - } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - - if (!programBinary || uniformBlockIndex >= programBinary->getActiveUniformBlockCount()) - { - return gl::error(GL_INVALID_VALUE); - } - - switch (pname) - { - case GL_UNIFORM_BLOCK_BINDING: - *params = static_cast(programObject->getUniformBlockBinding(uniformBlockIndex)); - break; - - case GL_UNIFORM_BLOCK_DATA_SIZE: - case GL_UNIFORM_BLOCK_NAME_LENGTH: - case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS: - case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES: - case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER: - case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER: - programBinary->getActiveUniformBlockiv(uniformBlockIndex, pname, params); - break; - - default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + + if (!programBinary || uniformBlockIndex >= programBinary->getActiveUniformBlockCount()) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + switch (pname) + { + case GL_UNIFORM_BLOCK_BINDING: + *params = static_cast(programObject->getUniformBlockBinding(uniformBlockIndex)); + break; + + case GL_UNIFORM_BLOCK_DATA_SIZE: + case GL_UNIFORM_BLOCK_NAME_LENGTH: + case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS: + case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES: + case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER: + case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER: + programBinary->getActiveUniformBlockiv(uniformBlockIndex, pname, params); + break; + + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } } } @@ -8439,44 +7024,40 @@ void __stdcall glGetActiveUniformBlockName(GLuint program, GLuint uniformBlockIn EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLchar* uniformBlockName = 0x%0.8p)", program, uniformBlockIndex, bufSize, length, uniformBlockName); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - gl::Program *programObject = context->getProgram(program); - - if (!programObject) - { - if (context->getShader(program)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } - } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - - if (!programBinary || uniformBlockIndex >= programBinary->getActiveUniformBlockCount()) - { - return gl::error(GL_INVALID_VALUE); - } - - programBinary->getActiveUniformBlockName(uniformBlockIndex, bufSize, length, uniformBlockName); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + gl::Program *programObject = context->getProgram(program); + + if (!programObject) + { + if (context->getShader(program)) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + } + + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + + if (!programBinary || uniformBlockIndex >= programBinary->getActiveUniformBlockCount()) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + programBinary->getActiveUniformBlockName(uniformBlockIndex, bufSize, length, uniformBlockName); } } @@ -8485,50 +7066,47 @@ void __stdcall glUniformBlockBinding(GLuint program, GLuint uniformBlockIndex, G EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLuint uniformBlockBinding = %u)", program, uniformBlockIndex, uniformBlockBinding); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (uniformBlockBinding >= context->getMaximumCombinedUniformBufferBindings()) - { - return gl::error(GL_INVALID_VALUE); - } - - gl::Program *programObject = context->getProgram(program); - - if (!programObject) - { - if (context->getShader(program)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } - } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - - // if never linked, there won't be any uniform blocks - if (!programBinary || uniformBlockIndex >= programBinary->getActiveUniformBlockCount()) - { - return gl::error(GL_INVALID_VALUE); - } - - programObject->bindUniformBlock(uniformBlockIndex, uniformBlockBinding); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + if (uniformBlockBinding >= context->getCaps().maxUniformBufferBindings) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + gl::Program *programObject = context->getProgram(program); + + if (!programObject) + { + if (context->getShader(program)) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + } + + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + + // if never linked, there won't be any uniform blocks + if (!programBinary || uniformBlockIndex >= programBinary->getActiveUniformBlockCount()) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + programObject->bindUniformBlock(uniformBlockIndex, uniformBlockBinding); } } @@ -8537,24 +7115,17 @@ void __stdcall glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GL EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)", mode, first, count, instanceCount); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - // glDrawArraysInstanced - UNIMPLEMENTED(); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + // glDrawArraysInstanced + UNIMPLEMENTED(); } } @@ -8563,24 +7134,17 @@ void __stdcall glDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p, GLsizei instanceCount = %d)", mode, count, type, indices, instanceCount); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - // glDrawElementsInstanced - UNIMPLEMENTED(); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + // glDrawElementsInstanced + UNIMPLEMENTED(); } } @@ -8588,33 +7152,28 @@ GLsync __stdcall glFenceSync(GLenum condition, GLbitfield flags) { EVENT("(GLenum condition = 0x%X, GLbitfield flags = 0x%X)", condition, flags); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION, reinterpret_cast(0)); - } - - if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE) - { - return gl::error(GL_INVALID_ENUM, reinterpret_cast(0)); - } - - if (flags != 0) - { - return gl::error(GL_INVALID_VALUE, reinterpret_cast(0)); - } - - return context->createFenceSync(condition); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return 0; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY, reinterpret_cast(NULL)); + + if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return 0; + } + + if (flags != 0) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return 0; + } + + return context->createFenceSync(condition); } return NULL; @@ -8624,23 +7183,16 @@ GLboolean __stdcall glIsSync(GLsync sync) { EVENT("(GLsync sync = 0x%0.8p)", sync); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION, GL_FALSE); - } - - return (context->getFenceSync(sync) != NULL); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return GL_FALSE; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); + + return (context->getFenceSync(sync) != NULL); } return GL_FALSE; @@ -8650,28 +7202,22 @@ void __stdcall glDeleteSync(GLsync sync) { EVENT("(GLsync sync = 0x%0.8p)", sync); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (sync != static_cast(0) && !context->getFenceSync(sync)) - { - return gl::error(GL_INVALID_VALUE); - } - - context->deleteFenceSync(sync); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + if (sync != static_cast(0) && !context->getFenceSync(sync)) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + context->deleteFenceSync(sync); } } @@ -8680,35 +7226,30 @@ GLenum __stdcall glClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeou EVENT("(GLsync sync = 0x%0.8p, GLbitfield flags = 0x%X, GLuint64 timeout = %llu)", sync, flags, timeout); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION, GL_WAIT_FAILED); - } - - if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0) - { - return gl::error(GL_INVALID_VALUE, GL_WAIT_FAILED); - } - - gl::FenceSync *fenceSync = context->getFenceSync(sync); - - if (!fenceSync) - { - return gl::error(GL_INVALID_VALUE, GL_WAIT_FAILED); - } - - return fenceSync->clientWait(flags, timeout); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return GL_WAIT_FAILED; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); + + if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return GL_WAIT_FAILED; + } + + gl::FenceSync *fenceSync = context->getFenceSync(sync); + + if (!fenceSync) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return GL_WAIT_FAILED; + } + + return fenceSync->clientWait(flags, timeout); } return GL_FALSE; @@ -8719,40 +7260,36 @@ void __stdcall glWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) EVENT("(GLsync sync = 0x%0.8p, GLbitfield flags = 0x%X, GLuint64 timeout = %llu)", sync, flags, timeout); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (flags != 0) - { - return gl::error(GL_INVALID_VALUE); - } - - if (timeout != GL_TIMEOUT_IGNORED) - { - return gl::error(GL_INVALID_VALUE); - } - - gl::FenceSync *fenceSync = context->getFenceSync(sync); - - if (!fenceSync) - { - return gl::error(GL_INVALID_VALUE); - } - - fenceSync->serverWait(); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + if (flags != 0) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + if (timeout != GL_TIMEOUT_IGNORED) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + gl::FenceSync *fenceSync = context->getFenceSync(sync); + + if (!fenceSync) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + fenceSync->serverWait(); } } @@ -8761,37 +7298,30 @@ void __stdcall glGetInteger64v(GLenum pname, GLint64* params) EVENT("(GLenum pname = 0x%X, GLint64* params = 0x%0.8p)", pname, params); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - GLenum nativeType; - unsigned int numParams = 0; - if (!ValidateStateQuery(context, pname, &nativeType, &numParams)) - { - return; - } - - if (nativeType == GL_INT_64_ANGLEX) - { - context->getInteger64v(pname, params); - } - else - { - CastStateValues(context, nativeType, pname, numParams, params); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + GLenum nativeType; + unsigned int numParams = 0; + if (!ValidateStateQuery(context, pname, &nativeType, &numParams)) + { + return; + } + + if (nativeType == GL_INT_64_ANGLEX) + { + context->getInteger64v(pname, params); + } + else + { + CastStateValues(context, nativeType, pname, numParams, params); } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -8800,44 +7330,40 @@ void __stdcall glGetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* EVENT("(GLsync sync = 0x%0.8p, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLint* values = 0x%0.8p)", sync, pname, bufSize, length, values); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (bufSize < 0) - { - return gl::error(GL_INVALID_VALUE); - } - - gl::FenceSync *fenceSync = context->getFenceSync(sync); - - if (!fenceSync) - { - return gl::error(GL_INVALID_VALUE); - } - - switch (pname) - { - case GL_OBJECT_TYPE: values[0] = static_cast(GL_SYNC_FENCE); break; - case GL_SYNC_STATUS: values[0] = static_cast(fenceSync->getStatus()); break; - case GL_SYNC_CONDITION: values[0] = static_cast(fenceSync->getCondition()); break; - case GL_SYNC_FLAGS: values[0] = 0; break; - - default: - return gl::error(GL_INVALID_ENUM); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + if (bufSize < 0) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + gl::FenceSync *fenceSync = context->getFenceSync(sync); + + if (!fenceSync) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + switch (pname) + { + case GL_OBJECT_TYPE: values[0] = static_cast(GL_SYNC_FENCE); break; + case GL_SYNC_STATUS: values[0] = static_cast(fenceSync->getStatus()); break; + case GL_SYNC_CONDITION: values[0] = static_cast(fenceSync->getCondition()); break; + case GL_SYNC_FLAGS: values[0] = 0; break; + + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -8846,69 +7372,75 @@ void __stdcall glGetInteger64i_v(GLenum target, GLuint index, GLint64* data) EVENT("(GLenum target = 0x%X, GLuint index = %u, GLint64* data = 0x%0.8p)", target, index, data); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + const gl::Caps &caps = context->getCaps(); + switch (target) + { + case GL_TRANSFORM_FEEDBACK_BUFFER_START: + case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: + case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: + if (index >= caps.maxTransformFeedbackSeparateAttributes) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + break; + + case GL_UNIFORM_BUFFER_START: + case GL_UNIFORM_BUFFER_SIZE: + case GL_UNIFORM_BUFFER_BINDING: + if (index >= caps.maxUniformBufferBindings) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + break; + + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + + if (!(context->getIndexedInteger64v(target, index, data))) + { + GLenum nativeType; + unsigned int numParams = 0; + if (!context->getIndexedQueryParameterInfo(target, &nativeType, &numParams)) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - switch (target) + if (numParams == 0) + return; // it is known that pname is valid, but there are no parameters to return + + if (nativeType == GL_INT) { - case GL_TRANSFORM_FEEDBACK_BUFFER_START: - case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: - case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: - if (index >= context->getMaxTransformFeedbackBufferBindings()) - return gl::error(GL_INVALID_VALUE); - break; - case GL_UNIFORM_BUFFER_START: - case GL_UNIFORM_BUFFER_SIZE: - case GL_UNIFORM_BUFFER_BINDING: - if (index >= context->getMaximumCombinedUniformBufferBindings()) - return gl::error(GL_INVALID_VALUE); - break; - default: - return gl::error(GL_INVALID_ENUM); + GLint *intParams = new GLint[numParams]; + + context->getIndexedIntegerv(target, index, intParams); + + for (unsigned int i = 0; i < numParams; ++i) + { + data[i] = static_cast(intParams[i]); + } + + delete [] intParams; } - - if (!(context->getIndexedInteger64v(target, index, data))) + else { - GLenum nativeType; - unsigned int numParams = 0; - if (!context->getIndexedQueryParameterInfo(target, &nativeType, &numParams)) - return gl::error(GL_INVALID_ENUM); - - if (numParams == 0) - return; // it is known that pname is valid, but there are no parameters to return - - if (nativeType == GL_INT) - { - GLint *intParams = new GLint[numParams]; - - context->getIndexedIntegerv(target, index, intParams); - - for (unsigned int i = 0; i < numParams; ++i) - { - data[i] = static_cast(intParams[i]); - } - - delete [] intParams; - } - else - { - UNREACHABLE(); - } + UNREACHABLE(); } } } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glGetBufferParameteri64v(GLenum target, GLenum pname, GLint64* params) @@ -8916,62 +7448,58 @@ void __stdcall glGetBufferParameteri64v(GLenum target, GLenum pname, GLint64* pa EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint64* params = 0x%0.8p)", target, pname, params); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (!gl::ValidBufferTarget(context, target)) - { - return gl::error(GL_INVALID_ENUM); - } - - if (!gl::ValidBufferParameter(context, pname)) - { - return gl::error(GL_INVALID_ENUM); - } - - gl::Buffer *buffer = context->getTargetBuffer(target); - - if (!buffer) - { - // A null buffer means that "0" is bound to the requested buffer target - return gl::error(GL_INVALID_OPERATION); - } - - switch (pname) - { - case GL_BUFFER_USAGE: - *params = static_cast(buffer->usage()); - break; - case GL_BUFFER_SIZE: - *params = buffer->size(); - break; - case GL_BUFFER_ACCESS_FLAGS: - *params = static_cast(buffer->accessFlags()); - break; - case GL_BUFFER_MAPPED: - *params = static_cast(buffer->mapped()); - break; - case GL_BUFFER_MAP_OFFSET: - *params = buffer->mapOffset(); - break; - case GL_BUFFER_MAP_LENGTH: - *params = buffer->mapLength(); - break; - default: UNREACHABLE(); break; - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + if (!gl::ValidBufferTarget(context, target)) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + + if (!gl::ValidBufferParameter(context, pname)) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + + gl::Buffer *buffer = context->getState().getTargetBuffer(target); + + if (!buffer) + { + // A null buffer means that "0" is bound to the requested buffer target + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + switch (pname) + { + case GL_BUFFER_USAGE: + *params = static_cast(buffer->getUsage()); + break; + case GL_BUFFER_SIZE: + *params = buffer->getSize(); + break; + case GL_BUFFER_ACCESS_FLAGS: + *params = static_cast(buffer->getAccessFlags()); + break; + case GL_BUFFER_MAPPED: + *params = static_cast(buffer->isMapped()); + break; + case GL_BUFFER_MAP_OFFSET: + *params = buffer->getMapOffset(); + break; + case GL_BUFFER_MAP_LENGTH: + *params = buffer->getMapLength(); + break; + default: UNREACHABLE(); break; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -8979,31 +7507,25 @@ void __stdcall glGenSamplers(GLsizei count, GLuint* samplers) { EVENT("(GLsizei count = %d, GLuint* samplers = 0x%0.8p)", count, samplers); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (count < 0) - { - return gl::error(GL_INVALID_VALUE); - } - - for (int i = 0; i < count; i++) - { - samplers[i] = context->createSampler(); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + if (count < 0) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + for (int i = 0; i < count; i++) + { + samplers[i] = context->createSampler(); } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -9011,31 +7533,25 @@ void __stdcall glDeleteSamplers(GLsizei count, const GLuint* samplers) { EVENT("(GLsizei count = %d, const GLuint* samplers = 0x%0.8p)", count, samplers); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (count < 0) - { - return gl::error(GL_INVALID_VALUE); - } - - for (int i = 0; i < count; i++) - { - context->deleteSampler(samplers[i]); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + if (count < 0) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + for (int i = 0; i < count; i++) + { + context->deleteSampler(samplers[i]); } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -9043,23 +7559,16 @@ GLboolean __stdcall glIsSampler(GLuint sampler) { EVENT("(GLuint sampler = %u)", sampler); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION, GL_FALSE); - } - - return context->isSampler(sampler); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return GL_FALSE; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); + + return context->isSampler(sampler); } return GL_FALSE; @@ -9069,33 +7578,28 @@ void __stdcall glBindSampler(GLuint unit, GLuint sampler) { EVENT("(GLuint unit = %u, GLuint sampler = %u)", unit, sampler); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (sampler != 0 && !context->isSampler(sampler)) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (unit >= context->getMaximumCombinedTextureImageUnits()) - { - return gl::error(GL_INVALID_VALUE); - } - - context->bindSampler(unit, sampler); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + if (sampler != 0 && !context->isSampler(sampler)) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + if (unit >= context->getCaps().maxCombinedTextureImageUnits) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + context->bindSampler(unit, sampler); } } @@ -9103,38 +7607,32 @@ void __stdcall glSamplerParameteri(GLuint sampler, GLenum pname, GLint param) { EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLint param = %d)", sampler, pname, param); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (!gl::ValidateSamplerObjectParameter(pname)) - { - return; - } - - if (!gl::ValidateTexParamParameters(context, pname, param)) - { - return; - } - - if (!context->isSampler(sampler)) - { - return gl::error(GL_INVALID_OPERATION); - } - - context->samplerParameteri(sampler, pname, param); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + if (!gl::ValidateSamplerObjectParameter(context, pname)) + { + return; + } + + if (!gl::ValidateTexParamParameters(context, pname, param)) + { + return; + } + + if (!context->isSampler(sampler)) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + context->samplerParameteri(sampler, pname, param); } } @@ -9147,38 +7645,32 @@ void __stdcall glSamplerParameterf(GLuint sampler, GLenum pname, GLfloat param) { EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLfloat param = %g)", sampler, pname, param); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (!gl::ValidateSamplerObjectParameter(pname)) - { - return; - } - - if (!gl::ValidateTexParamParameters(context, pname, static_cast(param))) - { - return; - } - - if (!context->isSampler(sampler)) - { - return gl::error(GL_INVALID_OPERATION); - } - - context->samplerParameterf(sampler, pname, param); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + if (!gl::ValidateSamplerObjectParameter(context, pname)) + { + return; + } + + if (!gl::ValidateTexParamParameters(context, pname, static_cast(param))) + { + return; + } + + if (!context->isSampler(sampler)) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + context->samplerParameterf(sampler, pname, param); } } @@ -9191,33 +7683,27 @@ void __stdcall glGetSamplerParameteriv(GLuint sampler, GLenum pname, GLint* para { EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", sampler, pname, params); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (!gl::ValidateSamplerObjectParameter(pname)) - { - return; - } - - if (!context->isSampler(sampler)) - { - return gl::error(GL_INVALID_OPERATION); - } - - *params = context->getSamplerParameteri(sampler, pname); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + if (!gl::ValidateSamplerObjectParameter(context, pname)) + { + return; + } + + if (!context->isSampler(sampler)) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + *params = context->getSamplerParameteri(sampler, pname); } } @@ -9225,33 +7711,27 @@ void __stdcall glGetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat* pa { EVENT("(GLuint sample = %ur, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", sampler, pname, params); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (!gl::ValidateSamplerObjectParameter(pname)) - { - return; - } - - if (!context->isSampler(sampler)) - { - return gl::error(GL_INVALID_OPERATION); - } - - *params = context->getSamplerParameterf(sampler, pname); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + if (!gl::ValidateSamplerObjectParameter(context, pname)) + { + return; + } + + if (!context->isSampler(sampler)) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + *params = context->getSamplerParameterf(sampler, pname); } } @@ -9259,28 +7739,22 @@ void __stdcall glVertexAttribDivisor(GLuint index, GLuint divisor) { EVENT("(GLuint index = %u, GLuint divisor = %u)", index, divisor); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { + if (context->getClientVersion() < 3) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + if (index >= gl::MAX_VERTEX_ATTRIBS) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - context->setVertexAttribDivisor(index, divisor); - } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + context->setVertexAttribDivisor(index, divisor); } } @@ -9288,46 +7762,42 @@ void __stdcall glBindTransformFeedback(GLenum target, GLuint id) { EVENT("(GLenum target = 0x%X, GLuint id = %u)", target, id); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - switch (target) - { - case GL_TRANSFORM_FEEDBACK: - { - // Cannot bind a transform feedback object if the current one is started and not paused (3.0.2 pg 85 section 2.14.1) - gl::TransformFeedback *curTransformFeedback = context->getCurrentTransformFeedback(); - if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused()) - { - return gl::error(GL_INVALID_OPERATION); - } - - // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section 2.14.1) - if (context->getTransformFeedback(id) == NULL) - { - return gl::error(GL_INVALID_OPERATION); - } - - context->bindTransformFeedback(id); - } - break; - - default: - return gl::error(GL_INVALID_ENUM); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + switch (target) + { + case GL_TRANSFORM_FEEDBACK: + { + // Cannot bind a transform feedback object if the current one is started and not paused (3.0.2 pg 85 section 2.14.1) + gl::TransformFeedback *curTransformFeedback = context->getState().getCurrentTransformFeedback(); + if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused()) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section 2.14.1) + if (context->getTransformFeedback(id) == NULL) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + context->bindTransformFeedback(id); + } + break; + + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -9335,26 +7805,19 @@ void __stdcall glDeleteTransformFeedbacks(GLsizei n, const GLuint* ids) { EVENT("(GLsizei n = %d, const GLuint* ids = 0x%0.8p)", n, ids); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - for (int i = 0; i < n; i++) - { - context->deleteTransformFeedback(ids[i]); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + for (int i = 0; i < n; i++) + { + context->deleteTransformFeedback(ids[i]); } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -9362,26 +7825,19 @@ void __stdcall glGenTransformFeedbacks(GLsizei n, GLuint* ids) { EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - for (int i = 0; i < n; i++) - { - ids[i] = context->createTransformFeedback(); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + for (int i = 0; i < n; i++) + { + ids[i] = context->createTransformFeedback(); } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -9389,23 +7845,16 @@ GLboolean __stdcall glIsTransformFeedback(GLuint id) { EVENT("(GLuint id = %u)", id); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION, GL_FALSE); - } - - return ((context->getTransformFeedback(id) != NULL) ? GL_TRUE : GL_FALSE); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return GL_FALSE; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); + + return ((context->getTransformFeedback(id) != NULL) ? GL_TRUE : GL_FALSE); } return GL_FALSE; @@ -9415,32 +7864,26 @@ void __stdcall glPauseTransformFeedback(void) { EVENT("(void)"); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - gl::TransformFeedback *transformFeedback = context->getCurrentTransformFeedback(); - ASSERT(transformFeedback != NULL); - - // Current transform feedback must be started and not paused in order to pause (3.0.2 pg 86) - if (!transformFeedback->isStarted() || transformFeedback->isPaused()) - { - return gl::error(GL_INVALID_OPERATION); - } - - transformFeedback->pause(); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + gl::TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback(); + ASSERT(transformFeedback != NULL); + + // Current transform feedback must be started and not paused in order to pause (3.0.2 pg 86) + if (!transformFeedback->isStarted() || transformFeedback->isPaused()) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + transformFeedback->pause(); } } @@ -9448,32 +7891,26 @@ void __stdcall glResumeTransformFeedback(void) { EVENT("(void)"); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - gl::TransformFeedback *transformFeedback = context->getCurrentTransformFeedback(); - ASSERT(transformFeedback != NULL); - - // Current transform feedback must be started and paused in order to resume (3.0.2 pg 86) - if (!transformFeedback->isStarted() || !transformFeedback->isPaused()) - { - return gl::error(GL_INVALID_OPERATION); - } - - transformFeedback->resume(); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + gl::TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback(); + ASSERT(transformFeedback != NULL); + + // Current transform feedback must be started and paused in order to resume (3.0.2 pg 86) + if (!transformFeedback->isStarted() || !transformFeedback->isPaused()) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + transformFeedback->resume(); } } @@ -9482,24 +7919,17 @@ void __stdcall glGetProgramBinary(GLuint program, GLsizei bufSize, GLsizei* leng EVENT("(GLuint program = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLenum* binaryFormat = 0x%0.8p, GLvoid* binary = 0x%0.8p)", program, bufSize, length, binaryFormat, binary); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - // glGetProgramBinary - UNIMPLEMENTED(); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + // glGetProgramBinary + UNIMPLEMENTED(); } } @@ -9508,24 +7938,17 @@ void __stdcall glProgramBinary(GLuint program, GLenum binaryFormat, const GLvoid EVENT("(GLuint program = %u, GLenum binaryFormat = 0x%X, const GLvoid* binary = 0x%0.8p, GLsizei length = %d)", program, binaryFormat, binary, length); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - // glProgramBinary - UNIMPLEMENTED(); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + // glProgramBinary + UNIMPLEMENTED(); } } @@ -9534,24 +7957,17 @@ void __stdcall glProgramParameteri(GLuint program, GLenum pname, GLint value) EVENT("(GLuint program = %u, GLenum pname = 0x%X, GLint value = %d)", program, pname, value); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - // glProgramParameteri - UNIMPLEMENTED(); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + // glProgramParameteri + UNIMPLEMENTED(); } } @@ -9560,29 +7976,25 @@ void __stdcall glInvalidateFramebuffer(GLenum target, GLsizei numAttachments, co EVENT("(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum* attachments = 0x%0.8p)", target, numAttachments, attachments); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (!ValidateInvalidateFramebufferParameters(context, target, numAttachments, attachments)) - { - return; - } - - int maxDimension = context->getMaximumRenderbufferDimension(); - context->invalidateFrameBuffer(target, numAttachments, attachments, 0, 0, maxDimension, maxDimension); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + if (!ValidateInvalidateFramebufferParameters(context, target, numAttachments, attachments)) + { + return; + } + + gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); + if (framebuffer && framebuffer->completeness() == GL_FRAMEBUFFER_COMPLETE) + { + framebuffer->invalidate(context->getCaps(), numAttachments, attachments); } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -9592,28 +8004,25 @@ void __stdcall glInvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, "GLint y = %d, GLsizei width = %d, GLsizei height = %d)", target, numAttachments, attachments, x, y, width, height); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (!ValidateInvalidateFramebufferParameters(context, target, numAttachments, attachments)) - { - return; - } - - context->invalidateFrameBuffer(target, numAttachments, attachments, x, y, width, height); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + if (!ValidateInvalidateFramebufferParameters(context, target, numAttachments, attachments)) + { + return; + } + + gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); + if (framebuffer && framebuffer->completeness() == GL_FRAMEBUFFER_COMPLETE) + { + framebuffer->invalidateSub(context->getCaps(), numAttachments, attachments, x, y, width, height); } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -9622,46 +8031,40 @@ void __stdcall glTexStorage2D(GLenum target, GLsizei levels, GLenum internalform EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)", target, levels, internalformat, width, height); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (!ValidateES3TexStorageParameters(context, target, levels, internalformat, width, height, 1)) - { - return; - } - - switch (target) - { - case GL_TEXTURE_2D: - { - gl::Texture2D *texture2d = context->getTexture2D(); - texture2d->storage(levels, internalformat, width, height); - } - break; - - case GL_TEXTURE_CUBE_MAP: - { - gl::TextureCubeMap *textureCube = context->getTextureCubeMap(); - textureCube->storage(levels, internalformat, width); - } - break; - - default: - return gl::error(GL_INVALID_ENUM); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + if (!ValidateES3TexStorageParameters(context, target, levels, internalformat, width, height, 1)) + { + return; + } + + switch (target) + { + case GL_TEXTURE_2D: + { + gl::Texture2D *texture2d = context->getTexture2D(); + texture2d->storage(levels, internalformat, width, height); + } + break; + + case GL_TEXTURE_CUBE_MAP: + { + gl::TextureCubeMap *textureCube = context->getTextureCubeMap(); + textureCube->storage(levels, internalformat, width); + } + break; + + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -9671,46 +8074,39 @@ void __stdcall glTexStorage3D(GLenum target, GLsizei levels, GLenum internalform "GLsizei height = %d, GLsizei depth = %d)", target, levels, internalformat, width, height, depth); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (!ValidateES3TexStorageParameters(context, target, levels, internalformat, width, height, depth)) - { - return; - } - - switch (target) - { - case GL_TEXTURE_3D: - { - gl::Texture3D *texture3d = context->getTexture3D(); - texture3d->storage(levels, internalformat, width, height, depth); - } - break; - - case GL_TEXTURE_2D_ARRAY: - { - gl::Texture2DArray *texture2darray = context->getTexture2DArray(); - texture2darray->storage(levels, internalformat, width, height, depth); - } - break; - - default: - UNREACHABLE(); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + if (!ValidateES3TexStorageParameters(context, target, levels, internalformat, width, height, depth)) + { + return; + } + + switch (target) + { + case GL_TEXTURE_3D: + { + gl::Texture3D *texture3d = context->getTexture3D(); + texture3d->storage(levels, internalformat, width, height, depth); + } + break; + + case GL_TEXTURE_2D_ARRAY: + { + gl::Texture2DArray *texture2darray = context->getTexture2DArray(); + texture2darray->storage(levels, internalformat, width, height, depth); + } + break; + + default: + UNREACHABLE(); } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -9720,51 +8116,51 @@ void __stdcall glGetInternalformativ(GLenum target, GLenum internalformat, GLenu "GLint* params = 0x%0.8p)", target, internalformat, pname, bufSize, params); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (context->getClientVersion() < 3) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (!gl::IsColorRenderingSupported(internalformat, context) && - !gl::IsDepthRenderingSupported(internalformat, context) && - !gl::IsStencilRenderingSupported(internalformat, context)) - { - return gl::error(GL_INVALID_ENUM); - } - - if (target != GL_RENDERBUFFER) - { - return gl::error(GL_INVALID_ENUM); - } - - if (bufSize < 0) - { - return gl::error(GL_INVALID_VALUE); - } - - switch (pname) - { - case GL_NUM_SAMPLE_COUNTS: - if (bufSize != 0) - *params = context->getNumSampleCounts(internalformat); - break; - case GL_SAMPLES: - context->getSampleCounts(internalformat, bufSize, params); - break; - default: - return gl::error(GL_INVALID_ENUM); - } + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + const gl::TextureCaps &formatCaps = context->getTextureCaps().get(internalformat); + if (!formatCaps.renderable) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + + if (target != GL_RENDERBUFFER) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + + if (bufSize < 0) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + switch (pname) + { + case GL_NUM_SAMPLE_COUNTS: + if (bufSize != 0) + { + *params = formatCaps.sampleCounts.size(); + } + break; + + case GL_SAMPLES: + std::copy_n(formatCaps.sampleCounts.rbegin(), std::min(bufSize, formatCaps.sampleCounts.size()), params); + break; + + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -9778,26 +8174,18 @@ void __stdcall glBlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLi "GLbitfield mask = 0x%X, GLenum filter = 0x%X)", srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1, mask, filter, + true)) { - if (!ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, - dstX0, dstY0, dstX1, dstY1, mask, filter, - true)) - { - return; - } - - context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, - mask, filter); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, + mask, filter); } } @@ -9809,53 +8197,39 @@ void __stdcall glTexImage3DOES(GLenum target, GLint level, GLenum internalformat "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* pixels = 0x%0.8p)", target, level, internalformat, width, height, depth, border, format, type, pixels); - ANGLE_TRY - { - UNIMPLEMENTED(); // FIXME - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); - } + UNIMPLEMENTED(); // FIXME } -void __stdcall glGetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *length, +void __stdcall glGetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary) { EVENT("(GLenum program = 0x%X, bufSize = %d, length = 0x%0.8p, binaryFormat = 0x%0.8p, binary = 0x%0.8p)", program, bufSize, length, binaryFormat, binary); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::Program *programObject = context->getProgram(program); - if (context) + if (!programObject || !programObject->isLinked()) { - gl::Program *programObject = context->getProgram(program); - - if (!programObject || !programObject->isLinked()) - { - return gl::error(GL_INVALID_OPERATION); - } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - - if (!programBinary) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (!programBinary->save(binary, bufSize, length)) - { - return gl::error(GL_INVALID_OPERATION); - } - - *binaryFormat = GL_PROGRAM_BINARY_ANGLE; + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + + if (!programBinary) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + if (!programBinary->save(binaryFormat, binary, bufSize, length)) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -9865,30 +8239,24 @@ void __stdcall glProgramBinaryOES(GLuint program, GLenum binaryFormat, EVENT("(GLenum program = 0x%X, binaryFormat = 0x%x, binary = 0x%0.8p, length = %d)", program, binaryFormat, binary, length); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + const std::vector &programBinaryFormats = context->getCaps().programBinaryFormats; + if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) == programBinaryFormats.end()) { - if (binaryFormat != GL_PROGRAM_BINARY_ANGLE) - { - return gl::error(GL_INVALID_ENUM); - } - - gl::Program *programObject = context->getProgram(program); - - if (!programObject) - { - return gl::error(GL_INVALID_OPERATION); - } - - context->setProgramBinary(program, binary, length); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + gl::Program *programObject = context->getProgram(program); + if (!programObject) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + context->setProgramBinary(program, binaryFormat, binary, length); } } @@ -9896,57 +8264,53 @@ void __stdcall glDrawBuffersEXT(GLsizei n, const GLenum *bufs) { EVENT("(GLenum n = %d, bufs = 0x%0.8p)", n, bufs); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (n < 0 || static_cast(n) > context->getCaps().maxDrawBuffers) { - if (n < 0 || (unsigned int)n > context->getMaximumRenderTargets()) + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + if (context->getState().getDrawFramebuffer()->id() == 0) + { + if (n != 1) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - if (context->getDrawFramebufferHandle() == 0) + if (bufs[0] != GL_NONE && bufs[0] != GL_BACK) { - 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); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + else + { + for (int colorAttachment = 0; colorAttachment < n; colorAttachment++) + { + const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment; + if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + } + } + + gl::Framebuffer *framebuffer = context->getState().getDrawFramebuffer(); + + for (unsigned int colorAttachment = 0; colorAttachment < static_cast(n); colorAttachment++) + { + framebuffer->setDrawBufferState(colorAttachment, bufs[colorAttachment]); + } + + for (unsigned int colorAttachment = n; colorAttachment < context->getCaps().maxDrawBuffers; colorAttachment++) + { + framebuffer->setDrawBufferState(colorAttachment, GL_NONE); + } } } @@ -9954,40 +8318,31 @@ void __stdcall glGetBufferPointervOES(GLenum target, GLenum pname, void** params { EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLvoid** params = 0x%0.8p)", target, pname, params); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!gl::ValidBufferTarget(context, target)) { - if (!context->supportsPBOs()) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (!gl::ValidBufferTarget(context, target)) - { - return gl::error(GL_INVALID_ENUM); - } - - if (pname != GL_BUFFER_MAP_POINTER) - { - return gl::error(GL_INVALID_ENUM); - } - - gl::Buffer *buffer = context->getTargetBuffer(target); - - if (!buffer || !buffer->mapped()) - { - *params = NULL; - } - - *params = buffer->mapPointer(); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + + if (pname != GL_BUFFER_MAP_POINTER) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + + gl::Buffer *buffer = context->getState().getTargetBuffer(target); + + if (!buffer || !buffer->isMapped()) + { + *params = NULL; + } + else + { + *params = buffer->getMapPointer(); } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -9995,40 +8350,36 @@ void * __stdcall glMapBufferOES(GLenum target, GLenum access) { EVENT("(GLenum target = 0x%X, GLbitfield access = 0x%X)", target, access); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!gl::ValidBufferTarget(context, target)) { - if (!gl::ValidBufferTarget(context, target)) - { - return gl::error(GL_INVALID_ENUM, reinterpret_cast(NULL)); - } - - gl::Buffer *buffer = context->getTargetBuffer(target); - - if (buffer == NULL) - { - return gl::error(GL_INVALID_OPERATION, reinterpret_cast(NULL)); - } - - if (access != GL_WRITE_ONLY_OES) - { - return gl::error(GL_INVALID_ENUM, reinterpret_cast(NULL)); - } - - if (buffer->mapped()) - { - return gl::error(GL_INVALID_OPERATION, reinterpret_cast(NULL)); - } - - return buffer->mapRange(0, buffer->size(), GL_MAP_WRITE_BIT); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return NULL; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY, reinterpret_cast(NULL)); + + gl::Buffer *buffer = context->getState().getTargetBuffer(target); + + if (buffer == NULL) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return NULL; + } + + if (access != GL_WRITE_ONLY_OES) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return NULL; + } + + if (buffer->isMapped()) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return NULL; + } + + return buffer->mapRange(0, buffer->getSize(), GL_MAP_WRITE_BIT); } return NULL; @@ -10038,34 +8389,28 @@ GLboolean __stdcall glUnmapBufferOES(GLenum target) { EVENT("(GLenum target = 0x%X)", target); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!gl::ValidBufferTarget(context, target)) { - if (!gl::ValidBufferTarget(context, target)) - { - return gl::error(GL_INVALID_ENUM, GL_FALSE); - } - - gl::Buffer *buffer = context->getTargetBuffer(target); - - if (buffer == NULL || !buffer->mapped()) - { - return gl::error(GL_INVALID_OPERATION, GL_FALSE); - } - - // TODO: detect if we had corruption. if so, throw an error and return false. - - buffer->unmap(); - - return GL_TRUE; + context->recordError(gl::Error(GL_INVALID_ENUM)); + return GL_FALSE; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); + + gl::Buffer *buffer = context->getState().getTargetBuffer(target); + + if (buffer == NULL || !buffer->isMapped()) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return GL_FALSE; + } + + // TODO: detect if we had corruption. if so, throw an error and return false. + + buffer->unmap(); + + return GL_TRUE; } return GL_FALSE; @@ -10076,83 +8421,84 @@ void* __stdcall glMapBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d, GLbitfield access = 0x%X)", target, offset, length, access); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!gl::ValidBufferTarget(context, target)) { - if (!gl::ValidBufferTarget(context, target)) - { - return gl::error(GL_INVALID_ENUM, reinterpret_cast(NULL)); - } - - if (offset < 0 || length < 0) - { - return gl::error(GL_INVALID_VALUE, reinterpret_cast(NULL)); - } - - gl::Buffer *buffer = context->getTargetBuffer(target); - - if (buffer == NULL) - { - return gl::error(GL_INVALID_OPERATION, reinterpret_cast(NULL)); - } - - // Check for buffer overflow - size_t offsetSize = static_cast(offset); - size_t lengthSize = static_cast(length); - - if (!rx::IsUnsignedAdditionSafe(offsetSize, lengthSize) || - offsetSize + lengthSize > static_cast(buffer->size())) - { - return gl::error(GL_INVALID_VALUE, reinterpret_cast(NULL)); - } - - // Check for invalid bits in the mask - GLbitfield allAccessBits = GL_MAP_READ_BIT | - GL_MAP_WRITE_BIT | - GL_MAP_INVALIDATE_RANGE_BIT | - GL_MAP_INVALIDATE_BUFFER_BIT | - GL_MAP_FLUSH_EXPLICIT_BIT | - GL_MAP_UNSYNCHRONIZED_BIT; - - if (access & ~(allAccessBits)) - { - return gl::error(GL_INVALID_VALUE, reinterpret_cast(NULL)); - } - - if (length == 0 || buffer->mapped()) - { - return gl::error(GL_INVALID_OPERATION, reinterpret_cast(NULL)); - } - - // Check for invalid bit combinations - if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0) - { - return gl::error(GL_INVALID_OPERATION, reinterpret_cast(NULL)); - } - - GLbitfield writeOnlyBits = GL_MAP_INVALIDATE_RANGE_BIT | - GL_MAP_INVALIDATE_BUFFER_BIT | - GL_MAP_UNSYNCHRONIZED_BIT; - - if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0) - { - return gl::error(GL_INVALID_OPERATION, reinterpret_cast(NULL)); - } - - if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0) - { - return gl::error(GL_INVALID_OPERATION, reinterpret_cast(NULL)); - } - - return buffer->mapRange(offset, length, access); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return NULL; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY, reinterpret_cast(NULL)); + + if (offset < 0 || length < 0) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return NULL; + } + + gl::Buffer *buffer = context->getState().getTargetBuffer(target); + + if (buffer == NULL) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return NULL; + } + + // Check for buffer overflow + size_t offsetSize = static_cast(offset); + size_t lengthSize = static_cast(length); + + if (!rx::IsUnsignedAdditionSafe(offsetSize, lengthSize) || + offsetSize + lengthSize > static_cast(buffer->getSize())) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return NULL; + } + + // Check for invalid bits in the mask + GLbitfield allAccessBits = GL_MAP_READ_BIT | + GL_MAP_WRITE_BIT | + GL_MAP_INVALIDATE_RANGE_BIT | + GL_MAP_INVALIDATE_BUFFER_BIT | + GL_MAP_FLUSH_EXPLICIT_BIT | + GL_MAP_UNSYNCHRONIZED_BIT; + + if (access & ~(allAccessBits)) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return NULL; + } + + if (length == 0 || buffer->isMapped()) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return NULL; + } + + // Check for invalid bit combinations + if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return NULL; + } + + GLbitfield writeOnlyBits = GL_MAP_INVALIDATE_RANGE_BIT | + GL_MAP_INVALIDATE_BUFFER_BIT | + GL_MAP_UNSYNCHRONIZED_BIT; + + if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return NULL; + } + + if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return NULL; + } + + return buffer->mapRange(offset, length, access); } return NULL; @@ -10162,50 +8508,47 @@ void __stdcall glFlushMappedBufferRangeEXT (GLenum target, GLintptr offset, GLsi { EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d)", target, offset, length); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (offset < 0 || length < 0) { - if (offset < 0 || length < 0) - { - return gl::error(GL_INVALID_VALUE); - } - - if (!gl::ValidBufferTarget(context, target)) - { - return gl::error(GL_INVALID_ENUM); - } - - gl::Buffer *buffer = context->getTargetBuffer(target); - - if (buffer == NULL) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (!buffer->mapped() || (buffer->accessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0) - { - return gl::error(GL_INVALID_OPERATION); - } - - // Check for buffer overflow - size_t offsetSize = static_cast(offset); - size_t lengthSize = static_cast(length); - - if (!rx::IsUnsignedAdditionSafe(offsetSize, lengthSize) || - offsetSize + lengthSize > static_cast(buffer->mapLength())) - { - return gl::error(GL_INVALID_VALUE); - } - - // We do not currently support a non-trivial implementation of FlushMappedBufferRange + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY); + + if (!gl::ValidBufferTarget(context, target)) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + + gl::Buffer *buffer = context->getState().getTargetBuffer(target); + + if (buffer == NULL) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0) + { + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + // Check for buffer overflow + size_t offsetSize = static_cast(offset); + size_t lengthSize = static_cast(length); + + if (!rx::IsUnsignedAdditionSafe(offsetSize, lengthSize) || + offsetSize + lengthSize > static_cast(buffer->getMapLength())) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + + // We do not currently support a non-trivial implementation of FlushMappedBufferRange } } @@ -10272,26 +8615,18 @@ bool __stdcall glBindTexImage(egl::Surface *surface) EVENT("(egl::Surface* surface = 0x%0.8p)", surface); - ANGLE_TRY + gl::Context *context = gl::getNonLostContext(); + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::Texture2D *textureObject = context->getTexture2D(); + ASSERT(textureObject != NULL); - if (context) + if (textureObject->isImmutable()) { - gl::Texture2D *textureObject = context->getTexture2D(); - ASSERT(textureObject != NULL); - - if (textureObject->isImmutable()) - { - return false; - } - - textureObject->bindTexImage(surface); + return false; } - } - ANGLE_CATCH_ALL - { - return gl::error(GL_OUT_OF_MEMORY, false); + + textureObject->bindTexImage(surface); } return true; diff --git a/gfx/angle/src/libGLESv2/main.cpp b/gfx/angle/src/libGLESv2/main.cpp index 50e2593328d1..4444d1ac2317 100644 --- a/gfx/angle/src/libGLESv2/main.cpp +++ b/gfx/angle/src/libGLESv2/main.cpp @@ -1,4 +1,3 @@ -#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 @@ -8,41 +7,41 @@ // main.cpp: DLL entry point and management of thread-local data. #include "libGLESv2/main.h" - #include "libGLESv2/Context.h" -static DWORD currentTLS = TLS_OUT_OF_INDEXES; +#include "common/tls.h" + +static TLSIndex currentTLS = TLS_OUT_OF_INDEXES; namespace gl { Current *AllocateCurrent() { - Current *current = (Current*)LocalAlloc(LPTR, sizeof(Current)); - - if (!current) + ASSERT(currentTLS != TLS_OUT_OF_INDEXES); + if (currentTLS == TLS_OUT_OF_INDEXES) { - ERR("Could not allocate thread local storage."); return NULL; } - ASSERT(currentTLS != TLS_OUT_OF_INDEXES); - TlsSetValue(currentTLS, current); - + Current *current = new Current(); current->context = NULL; current->display = NULL; + if (!SetTLSValue(currentTLS, current)) + { + ERR("Could not set thread local storage."); + return NULL; + } + return current; } void DeallocateCurrent() { - void *current = TlsGetValue(currentTLS); - - if (current) - { - LocalFree((HLOCAL)current); - } + Current *current = reinterpret_cast(GetTLSValue(currentTLS)); + SafeDelete(current); + SetTLSValue(currentTLS, NULL); } } @@ -53,14 +52,13 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved { case DLL_PROCESS_ATTACH: { - currentTLS = TlsAlloc(); - + currentTLS = CreateTLSIndex(); if (currentTLS == TLS_OUT_OF_INDEXES) { return FALSE; } } - // Fall throught to initialize index + // Fall through to initialize index case DLL_THREAD_ATTACH: { gl::AllocateCurrent(); @@ -74,7 +72,7 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved case DLL_PROCESS_DETACH: { gl::DeallocateCurrent(); - TlsFree(currentTLS); + DestroyTLSIndex(currentTLS); } break; default: @@ -89,7 +87,7 @@ namespace gl Current *GetCurrentData() { - Current *current = (Current*)TlsGetValue(currentTLS); + Current *current = reinterpret_cast(GetTLSValue(currentTLS)); // ANGLE issue 488: when the dll is loaded after thread initialization, // thread local storage (current) might not exist yet. @@ -119,7 +117,7 @@ Context *getContext() Context *getNonLostContext() { Context *context = getContext(); - + if (context) { if (context->isContextLost()) @@ -146,33 +144,26 @@ egl::Display *getDisplay() void error(GLenum errorCode) { gl::Context *context = glGetCurrentContext(); + context->recordError(Error(errorCode)); - if (context) + switch (errorCode) { - switch (errorCode) - { - case GL_INVALID_ENUM: - context->recordInvalidEnum(); - TRACE("\t! Error generated: invalid enum\n"); - break; - case GL_INVALID_VALUE: - context->recordInvalidValue(); - TRACE("\t! Error generated: invalid value\n"); - break; - case GL_INVALID_OPERATION: - context->recordInvalidOperation(); - TRACE("\t! Error generated: invalid operation\n"); - break; - case GL_OUT_OF_MEMORY: - context->recordOutOfMemory(); - TRACE("\t! Error generated: out of memory\n"); - break; - case GL_INVALID_FRAMEBUFFER_OPERATION: - context->recordInvalidFramebufferOperation(); - TRACE("\t! Error generated: invalid framebuffer operation\n"); - break; - default: UNREACHABLE(); - } + case GL_INVALID_ENUM: + TRACE("\t! Error generated: invalid enum\n"); + break; + case GL_INVALID_VALUE: + TRACE("\t! Error generated: invalid value\n"); + break; + case GL_INVALID_OPERATION: + TRACE("\t! Error generated: invalid operation\n"); + break; + case GL_OUT_OF_MEMORY: + TRACE("\t! Error generated: out of memory\n"); + break; + case GL_INVALID_FRAMEBUFFER_OPERATION: + TRACE("\t! Error generated: invalid framebuffer operation\n"); + break; + default: UNREACHABLE(); } } diff --git a/gfx/angle/src/libGLESv2/main.h b/gfx/angle/src/libGLESv2/main.h index d17facf20dc9..684c302b78ec 100644 --- a/gfx/angle/src/libGLESv2/main.h +++ b/gfx/angle/src/libGLESv2/main.h @@ -11,6 +11,9 @@ #include "common/debug.h" +#include +#include + namespace egl { class Display; @@ -57,7 +60,7 @@ gl::Context *glCreateContext(int clientVersion, const gl::Context *shareContext, 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); +rx::Renderer *glCreateRenderer(egl::Display *display, EGLNativeDisplayType nativeDisplay, EGLint requestedDisplayType); void glDestroyRenderer(rx::Renderer *renderer); __eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char *procname); diff --git a/gfx/angle/src/libGLESv2/moz.build b/gfx/angle/src/libGLESv2/moz.build index 997d0562362a..0f4dd2759be2 100644 --- a/gfx/angle/src/libGLESv2/moz.build +++ b/gfx/angle/src/libGLESv2/moz.build @@ -2,11 +2,13 @@ # Please note this file is autogenerated from generate_mozbuild.py, so do not modify it directly UNIFIED_SOURCES += [ + '../common/angleutils.cpp', '../common/blocklayout.cpp', '../common/debug.cpp', '../common/event_tracer.cpp', '../common/mathutil.cpp', '../common/RefCountObject.cpp', + '../common/tls.cpp', '../common/utilities.cpp', '../compiler/preprocessor/DiagnosticsBase.cpp', '../compiler/preprocessor/DirectiveHandlerBase.cpp', @@ -39,10 +41,10 @@ UNIFIED_SOURCES += [ '../compiler/translator/InitializeParseContext.cpp', '../compiler/translator/InitializeVariables.cpp', '../compiler/translator/Intermediate.cpp', + '../compiler/translator/IntermNode.cpp', '../compiler/translator/intermOut.cpp', '../compiler/translator/IntermTraverse.cpp', '../compiler/translator/LoopInfo.cpp', - '../compiler/translator/ossource_win.cpp', '../compiler/translator/OutputESSL.cpp', '../compiler/translator/OutputGLSL.cpp', '../compiler/translator/OutputGLSLBase.cpp', @@ -51,10 +53,14 @@ UNIFIED_SOURCES += [ '../compiler/translator/ParseContext.cpp', '../compiler/translator/PoolAlloc.cpp', '../compiler/translator/QualifierAlive.cpp', + '../compiler/translator/RegenerateStructNames.cpp', '../compiler/translator/RemoveTree.cpp', '../compiler/translator/RewriteElseBlocks.cpp', + '../compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp', '../compiler/translator/SearchSymbol.cpp', '../compiler/translator/ShaderLang.cpp', + '../compiler/translator/ShaderVars.cpp', + '../compiler/translator/StructureHLSL.cpp', '../compiler/translator/SymbolTable.cpp', '../compiler/translator/timing/RestrictFragmentShaderTiming.cpp', '../compiler/translator/timing/RestrictVertexShaderTiming.cpp', @@ -64,7 +70,9 @@ UNIFIED_SOURCES += [ '../compiler/translator/Types.cpp', '../compiler/translator/UnfoldShortCircuit.cpp', '../compiler/translator/UnfoldShortCircuitAST.cpp', + '../compiler/translator/UniformHLSL.cpp', '../compiler/translator/util.cpp', + '../compiler/translator/UtilsHLSL.cpp', '../compiler/translator/ValidateLimitations.cpp', '../compiler/translator/ValidateOutputs.cpp', '../compiler/translator/VariableInfo.cpp', @@ -75,52 +83,59 @@ UNIFIED_SOURCES += [ '../third_party/systeminfo/SystemInfo.cpp', 'angletypes.cpp', 'Buffer.cpp', + 'Caps.cpp', 'Context.cpp', - 'DynamicHLSL.cpp', + 'Error.cpp', 'Fence.cpp', 'Float16ToFloat32.cpp', 'formatutils.cpp', 'Framebuffer.cpp', + 'FramebufferAttachment.cpp', 'HandleAllocator.cpp', 'libGLESv2.cpp', 'main.cpp', - 'precompiled.cpp', 'Program.cpp', 'ProgramBinary.cpp', 'Query.cpp', 'queryconversions.cpp', 'Renderbuffer.cpp', - 'RenderbufferProxySet.cpp', - 'renderer/BufferStorage.cpp', 'renderer/copyimage.cpp', + 'renderer/d3d/BufferD3D.cpp', + 'renderer/d3d/d3d9/Blit9.cpp', + 'renderer/d3d/d3d9/Buffer9.cpp', + 'renderer/d3d/d3d9/Fence9.cpp', + 'renderer/d3d/d3d9/formatutils9.cpp', + 'renderer/d3d/d3d9/Image9.cpp', + 'renderer/d3d/d3d9/IndexBuffer9.cpp', + 'renderer/d3d/d3d9/Query9.cpp', + 'renderer/d3d/d3d9/Renderer9.cpp', + 'renderer/d3d/d3d9/renderer9_utils.cpp', + 'renderer/d3d/d3d9/RenderTarget9.cpp', + 'renderer/d3d/d3d9/ShaderExecutable9.cpp', + 'renderer/d3d/d3d9/SwapChain9.cpp', + 'renderer/d3d/d3d9/TextureStorage9.cpp', + 'renderer/d3d/d3d9/VertexBuffer9.cpp', + 'renderer/d3d/d3d9/VertexDeclarationCache.cpp', + 'renderer/d3d/DynamicHLSL.cpp', 'renderer/d3d/HLSLCompiler.cpp', - 'renderer/d3d9/Blit9.cpp', - 'renderer/d3d9/BufferStorage9.cpp', - 'renderer/d3d9/Fence9.cpp', - 'renderer/d3d9/formatutils9.cpp', - 'renderer/d3d9/Image9.cpp', - 'renderer/d3d9/IndexBuffer9.cpp', - 'renderer/d3d9/Query9.cpp', - 'renderer/d3d9/Renderer9.cpp', - 'renderer/d3d9/renderer9_utils.cpp', - 'renderer/d3d9/RenderTarget9.cpp', - 'renderer/d3d9/ShaderExecutable9.cpp', - 'renderer/d3d9/SwapChain9.cpp', - 'renderer/d3d9/TextureStorage9.cpp', - 'renderer/d3d9/VertexBuffer9.cpp', - 'renderer/d3d9/VertexDeclarationCache.cpp', + 'renderer/d3d/ImageD3D.cpp', + 'renderer/d3d/IndexBuffer.cpp', + 'renderer/d3d/IndexDataManager.cpp', + 'renderer/d3d/MemoryBuffer.cpp', + 'renderer/d3d/ShaderD3D.cpp', + 'renderer/d3d/TextureD3D.cpp', + 'renderer/d3d/TextureStorage.cpp', + 'renderer/d3d/TransformFeedbackD3D.cpp', + 'renderer/d3d/VertexBuffer.cpp', + 'renderer/d3d/VertexDataManager.cpp', 'renderer/Image.cpp', - 'renderer/IndexBuffer.cpp', - 'renderer/IndexDataManager.cpp', 'renderer/IndexRangeCache.cpp', 'renderer/loadimage.cpp', 'renderer/Renderer.cpp', - 'renderer/TextureStorage.cpp', - 'renderer/VertexBuffer.cpp', - 'renderer/VertexDataManager.cpp', 'ResourceManager.cpp', 'Sampler.cpp', 'Shader.cpp', + 'State.cpp', 'Texture.cpp', 'TransformFeedback.cpp', 'Uniform.cpp', @@ -128,6 +143,7 @@ UNIFIED_SOURCES += [ 'validationES2.cpp', 'validationES3.cpp', 'VertexArray.cpp', + 'VertexAttribute.cpp', ] SOURCES += [ '../compiler/translator/glslang_lex.cpp', @@ -137,24 +153,24 @@ SOURCES += [ SOURCES['renderer/loadimageSSE2.cpp'].flags += CONFIG['SSE2_FLAGS'] if CONFIG['MOZ_HAS_WINSDK_WITH_D3D']: UNIFIED_SOURCES += [ - 'renderer/d3d11/Blit11.cpp', - 'renderer/d3d11/BufferStorage11.cpp', - 'renderer/d3d11/Clear11.cpp', - 'renderer/d3d11/Fence11.cpp', - 'renderer/d3d11/formatutils11.cpp', - 'renderer/d3d11/Image11.cpp', - 'renderer/d3d11/IndexBuffer11.cpp', - 'renderer/d3d11/InputLayoutCache.cpp', - 'renderer/d3d11/PixelTransfer11.cpp', - 'renderer/d3d11/Query11.cpp', - 'renderer/d3d11/Renderer11.cpp', - 'renderer/d3d11/renderer11_utils.cpp', - 'renderer/d3d11/RenderStateCache.cpp', - 'renderer/d3d11/RenderTarget11.cpp', - 'renderer/d3d11/ShaderExecutable11.cpp', - 'renderer/d3d11/SwapChain11.cpp', - 'renderer/d3d11/TextureStorage11.cpp', - 'renderer/d3d11/VertexBuffer11.cpp', + 'renderer/d3d/d3d11/Blit11.cpp', + 'renderer/d3d/d3d11/Buffer11.cpp', + 'renderer/d3d/d3d11/Clear11.cpp', + 'renderer/d3d/d3d11/Fence11.cpp', + 'renderer/d3d/d3d11/formatutils11.cpp', + 'renderer/d3d/d3d11/Image11.cpp', + 'renderer/d3d/d3d11/IndexBuffer11.cpp', + 'renderer/d3d/d3d11/InputLayoutCache.cpp', + 'renderer/d3d/d3d11/PixelTransfer11.cpp', + 'renderer/d3d/d3d11/Query11.cpp', + 'renderer/d3d/d3d11/Renderer11.cpp', + 'renderer/d3d/d3d11/renderer11_utils.cpp', + 'renderer/d3d/d3d11/RenderStateCache.cpp', + 'renderer/d3d/d3d11/RenderTarget11.cpp', + 'renderer/d3d/d3d11/ShaderExecutable11.cpp', + 'renderer/d3d/d3d11/SwapChain11.cpp', + 'renderer/d3d/d3d11/TextureStorage11.cpp', + 'renderer/d3d/d3d11/VertexBuffer11.cpp', ] diff --git a/gfx/angle/src/libGLESv2/precompiled.cpp b/gfx/angle/src/libGLESv2/precompiled.cpp deleted file mode 100644 index 2621cd6ce3e2..000000000000 --- a/gfx/angle/src/libGLESv2/precompiled.cpp +++ /dev/null @@ -1,9 +0,0 @@ -// -// 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 deleted file mode 100644 index 3bc66a1d41e1..000000000000 --- a/gfx/angle/src/libGLESv2/precompiled.h +++ /dev/null @@ -1,48 +0,0 @@ -// -// 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. - -#include -#include -#include - -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include // for std::min and std::max -#include -#include -#include -#include -#include -#include -#include - -#if defined(ANGLE_ENABLE_D3D9) -#include -#include -#endif // ANGLE_ENABLE_D3D9 - -#if defined(ANGLE_ENABLE_D3D11) -#include -#include -#include -#include -#include -#endif // ANGLE_ENABLE_D3D11 diff --git a/gfx/angle/src/libGLESv2/queryconversions.cpp b/gfx/angle/src/libGLESv2/queryconversions.cpp index 67578efe3a21..7245902c518d 100644 --- a/gfx/angle/src/libGLESv2/queryconversions.cpp +++ b/gfx/angle/src/libGLESv2/queryconversions.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2014 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/renderer/BufferImpl.h b/gfx/angle/src/libGLESv2/renderer/BufferImpl.h new file mode 100644 index 000000000000..bea689b9566c --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/BufferImpl.h @@ -0,0 +1,34 @@ +// +// Copyright 2014 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. +// + +// BufferImpl.h: Defines the abstract rx::BufferImpl class. + +#ifndef LIBGLESV2_RENDERER_BUFFERIMPL_H_ +#define LIBGLESV2_RENDERER_BUFFERIMPL_H_ + +#include "common/angleutils.h" +#include "libGLESv2/Buffer.h" + +namespace rx +{ + +class BufferImpl +{ + public: + virtual ~BufferImpl() { } + + virtual void setData(const void* data, size_t size, GLenum usage) = 0; + virtual void *getData() = 0; + virtual void setSubData(const void* data, size_t size, size_t offset) = 0; + virtual void copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) = 0; + virtual GLvoid* map(size_t offset, size_t length, GLbitfield access) = 0; + virtual void unmap() = 0; + virtual void markTransformFeedbackUsage() = 0; +}; + +} + +#endif // LIBGLESV2_RENDERER_BUFFERIMPL_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/BufferStorage.cpp b/gfx/angle/src/libGLESv2/renderer/BufferStorage.cpp deleted file mode 100644 index 4d245f89daa6..000000000000 --- a/gfx/angle/src/libGLESv2/renderer/BufferStorage.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#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++; -} - -} diff --git a/gfx/angle/src/libGLESv2/renderer/BufferStorage.h b/gfx/angle/src/libGLESv2/renderer/BufferStorage.h deleted file mode 100644 index a5f95d1eb79d..000000000000 --- a/gfx/angle/src/libGLESv2/renderer/BufferStorage.h +++ /dev/null @@ -1,49 +0,0 @@ -// -// Copyright (c) 2014 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, size_t size, size_t offset) = 0; - virtual void copyData(BufferStorage* sourceStorage, size_t size, size_t sourceOffset, size_t destOffset) = 0; - virtual void clear() = 0; - virtual void markTransformFeedbackUsage() = 0; - virtual size_t getSize() const = 0; - virtual bool supportsDirectBinding() const = 0; - unsigned int getSerial() const; - - virtual bool isMapped() const = 0; - virtual void *map(GLbitfield access) = 0; - virtual void unmap() = 0; - - 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/Image.cpp b/gfx/angle/src/libGLESv2/renderer/Image.cpp index 5963534e03c4..370b086233ec 100644 --- a/gfx/angle/src/libGLESv2/renderer/Image.cpp +++ b/gfx/angle/src/libGLESv2/renderer/Image.cpp @@ -1,4 +1,3 @@ -#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 diff --git a/gfx/angle/src/libGLESv2/renderer/Image.h b/gfx/angle/src/libGLESv2/renderer/Image.h index 73e4e843d7d4..3bfc66376216 100644 --- a/gfx/angle/src/libGLESv2/renderer/Image.h +++ b/gfx/angle/src/libGLESv2/renderer/Image.h @@ -13,6 +13,8 @@ #include "common/debug.h" +#include + namespace gl { class Framebuffer; @@ -20,11 +22,8 @@ class Framebuffer; namespace rx { + class Renderer; -class TextureStorageInterface2D; -class TextureStorageInterfaceCube; -class TextureStorageInterface3D; -class TextureStorageInterface2DArray; class Image { @@ -44,15 +43,6 @@ class Image 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 void setManagedSurface(TextureStorageInterface3D *storage, int level) {}; - virtual void setManagedSurface(TextureStorageInterface2DArray *storage, int layer, int level) {}; - virtual bool copyToStorage(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) = 0; - virtual bool copyToStorage(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) = 0; - virtual bool copyToStorage(TextureStorageInterface3D *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth) = 0; - virtual bool copyToStorage(TextureStorageInterface2DArray *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height) = 0; - virtual bool redefine(Renderer *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease) = 0; virtual void loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, diff --git a/gfx/angle/src/libGLESv2/renderer/IndexRangeCache.cpp b/gfx/angle/src/libGLESv2/renderer/IndexRangeCache.cpp index 14410d0245e7..d472e1499e32 100644 --- a/gfx/angle/src/libGLESv2/renderer/IndexRangeCache.cpp +++ b/gfx/angle/src/libGLESv2/renderer/IndexRangeCache.cpp @@ -1,4 +1,3 @@ -#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 @@ -10,16 +9,49 @@ #include "libGLESv2/renderer/IndexRangeCache.h" #include "libGLESv2/formatutils.h" + #include "common/debug.h" + #include namespace rx { -void IndexRangeCache::addRange(GLenum type, unsigned int offset, GLsizei count, unsigned int minIdx, unsigned int maxIdx, +template +static RangeUI ComputeTypedRange(const IndexType *indices, GLsizei count) +{ + unsigned int minIndex = indices[0]; + unsigned int maxIndex = indices[0]; + + for (GLsizei i = 1; i < count; i++) + { + if (minIndex > indices[i]) minIndex = indices[i]; + if (maxIndex < indices[i]) maxIndex = indices[i]; + } + + return RangeUI(minIndex, maxIndex); +} + +RangeUI IndexRangeCache::ComputeRange(GLenum type, const GLvoid *indices, GLsizei count) +{ + switch (type) + { + case GL_UNSIGNED_BYTE: + return ComputeTypedRange(static_cast(indices), count); + case GL_UNSIGNED_INT: + return ComputeTypedRange(static_cast(indices), count); + case GL_UNSIGNED_SHORT: + return ComputeTypedRange(static_cast(indices), count); + default: + UNREACHABLE(); + return RangeUI(); + } +} + +void IndexRangeCache::addRange(GLenum type, unsigned int offset, GLsizei count, const RangeUI &range, unsigned int streamOffset) { - mIndexRangeCache[IndexRange(type, offset, count)] = IndexBounds(minIdx, maxIdx, streamOffset); + mIndexRangeCache[IndexRange(type, offset, count)] = IndexBounds(range, streamOffset); } void IndexRangeCache::invalidateRange(unsigned int offset, unsigned int size) @@ -31,7 +63,7 @@ void IndexRangeCache::invalidateRange(unsigned int offset, unsigned int size) while (i != mIndexRangeCache.end()) { unsigned int rangeStart = i->second.streamOffset; - unsigned int rangeEnd = i->second.streamOffset + (gl::GetTypeBytes(i->first.type) * i->first.count); + unsigned int rangeEnd = i->second.streamOffset + (gl::GetTypeInfo(i->first.type).bytes * i->first.count); if (invalidateEnd < rangeStart || invalidateStart > rangeEnd) { @@ -44,21 +76,19 @@ void IndexRangeCache::invalidateRange(unsigned int offset, unsigned int size) } } -bool IndexRangeCache::findRange(GLenum type, unsigned int offset, GLsizei count, unsigned int *outMinIndex, - unsigned int *outMaxIndex, unsigned int *outStreamOffset) const +bool IndexRangeCache::findRange(GLenum type, unsigned int offset, GLsizei count, + RangeUI *outRange, 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 (outRange) *outRange = i->second.range; if (outStreamOffset) *outStreamOffset = i->second.streamOffset; return true; } else { - if (outMinIndex) *outMinIndex = 0; - if (outMaxIndex) *outMaxIndex = 0; + if (outRange) *outRange = RangeUI(0, 0); if (outStreamOffset) *outStreamOffset = 0; return false; } @@ -85,12 +115,13 @@ bool IndexRangeCache::IndexRange::operator<(const IndexRange& rhs) const } IndexRangeCache::IndexBounds::IndexBounds() - : minIndex(0), maxIndex(0), streamOffset(0) + : range(0, 0), + streamOffset(0) { } -IndexRangeCache::IndexBounds::IndexBounds(unsigned int minIdx, unsigned int maxIdx, unsigned int offset) - : minIndex(minIdx), maxIndex(maxIdx), streamOffset(offset) +IndexRangeCache::IndexBounds::IndexBounds(const RangeUI &rangeIn, unsigned int offset) + : range(rangeIn), streamOffset(offset) { } diff --git a/gfx/angle/src/libGLESv2/renderer/IndexRangeCache.h b/gfx/angle/src/libGLESv2/renderer/IndexRangeCache.h index 4318e2b7a431..0c41c0f2d3d0 100644 --- a/gfx/angle/src/libGLESv2/renderer/IndexRangeCache.h +++ b/gfx/angle/src/libGLESv2/renderer/IndexRangeCache.h @@ -11,6 +11,10 @@ #define LIBGLESV2_RENDERER_INDEXRANGECACHE_H_ #include "common/angleutils.h" +#include "common/mathutil.h" + +#include "angle_gl.h" + #include namespace rx @@ -19,14 +23,16 @@ namespace rx class IndexRangeCache { public: - void addRange(GLenum type, unsigned int offset, GLsizei count, unsigned int minIdx, unsigned int maxIdx, + void addRange(GLenum type, unsigned int offset, GLsizei count, const RangeUI &range, unsigned int streamOffset); - bool findRange(GLenum type, unsigned int offset, GLsizei count, unsigned int *outMinIndex, - unsigned int *outMaxIndex, unsigned int *outStreamOffset) const; + bool findRange(GLenum type, unsigned int offset, GLsizei count, RangeUI *rangeOut, + unsigned int *outStreamOffset) const; void invalidateRange(unsigned int offset, unsigned int size); void clear(); + static RangeUI ComputeRange(GLenum type, const GLvoid *indices, GLsizei count); + private: struct IndexRange { @@ -42,12 +48,11 @@ class IndexRangeCache struct IndexBounds { - unsigned int minIndex; - unsigned int maxIndex; + RangeUI range; unsigned int streamOffset; IndexBounds(); - IndexBounds(unsigned int minIdx, unsigned int maxIdx, unsigned int offset); + IndexBounds(const RangeUI &range, unsigned int offset); }; typedef std::map IndexRangeMap; diff --git a/gfx/angle/src/libGLESv2/renderer/QueryImpl.h b/gfx/angle/src/libGLESv2/renderer/QueryImpl.h index a6750a204b79..1ecfbdb81aa4 100644 --- a/gfx/angle/src/libGLESv2/renderer/QueryImpl.h +++ b/gfx/angle/src/libGLESv2/renderer/QueryImpl.h @@ -11,26 +11,23 @@ #include "common/angleutils.h" +#include + namespace rx { class QueryImpl { public: - explicit QueryImpl(GLenum type) : mType(type), mStatus(GL_FALSE), mResult(0) { } + explicit QueryImpl(GLenum type) { mType = type; } virtual ~QueryImpl() { } - virtual void begin() = 0; + virtual bool begin() = 0; virtual void end() = 0; virtual GLuint getResult() = 0; virtual GLboolean isResultAvailable() = 0; - virtual bool isStarted() const = 0; - GLenum getType() const { return mType; } - - protected: - GLuint mResult; - GLboolean mStatus; + GLenum getType() const { return mType; } private: DISALLOW_COPY_AND_ASSIGN(QueryImpl); diff --git a/gfx/angle/src/libGLESv2/renderer/Renderer.cpp b/gfx/angle/src/libGLESv2/renderer/Renderer.cpp index 92594a4d5664..a0682e96d823 100644 --- a/gfx/angle/src/libGLESv2/renderer/Renderer.cpp +++ b/gfx/angle/src/libGLESv2/renderer/Renderer.cpp @@ -1,13 +1,11 @@ -#include "precompiled.h" // -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2012-2014 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" @@ -16,11 +14,11 @@ #include "libGLESv2/Shader.h" #if defined (ANGLE_ENABLE_D3D9) -#include "libGLESv2/renderer/d3d9/Renderer9.h" +#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" #endif // ANGLE_ENABLE_D3D9 #if defined (ANGLE_ENABLE_D3D11) -#include "libGLESv2/renderer/d3d11/Renderer11.h" +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" #endif // ANGLE_ENABLE_D3D11 #if !defined(ANGLE_DEFAULT_D3D11) @@ -28,17 +26,61 @@ #define ANGLE_DEFAULT_D3D11 0 #endif +#include + namespace rx { -Renderer::Renderer(egl::Display *display) : mDisplay(display) +Renderer::Renderer(egl::Display *display) + : mDisplay(display), + mCapsInitialized(false), + mCurrentClientVersion(2) { - mCurrentClientVersion = 2; } Renderer::~Renderer() { - gl::Shader::releaseCompiler(); +} + +const gl::Caps &Renderer::getRendererCaps() const +{ + if (!mCapsInitialized) + { + generateCaps(&mCaps, &mTextureCaps, &mExtensions); + mCapsInitialized = true; + } + + return mCaps; +} + +const gl::TextureCapsMap &Renderer::getRendererTextureCaps() const +{ + if (!mCapsInitialized) + { + generateCaps(&mCaps, &mTextureCaps, &mExtensions); + mCapsInitialized = true; + } + + return mTextureCaps; +} + +const gl::Extensions &Renderer::getRendererExtensions() const +{ + if (!mCapsInitialized) + { + generateCaps(&mCaps, &mTextureCaps, &mExtensions); + mCapsInitialized = true; + } + + return mExtensions; +} + +typedef Renderer *(*CreateRendererFunction)(egl::Display*, EGLNativeDisplayType, EGLint); + +template +Renderer *CreateRenderer(egl::Display *display, EGLNativeDisplayType nativeDisplay, EGLint requestedDisplayType) +{ + return new RendererType(display, nativeDisplay, requestedDisplayType); } } @@ -46,40 +88,64 @@ Renderer::~Renderer() extern "C" { -rx::Renderer *glCreateRenderer(egl::Display *display, HDC hDc, EGLNativeDisplayType displayId) +rx::Renderer *glCreateRenderer(egl::Display *display, EGLNativeDisplayType nativeDisplay, EGLint requestedDisplayType) { -#if defined(ANGLE_ENABLE_D3D11) - if (ANGLE_DEFAULT_D3D11 || - displayId == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE || - displayId == EGL_D3D11_ONLY_DISPLAY_ANGLE) - { - rx::Renderer11 *renderer = new rx::Renderer11(display, hDc); - if (renderer->initialize() == EGL_SUCCESS) - { - return renderer; - } - else - { - // Failed to create a D3D11 renderer, try D3D9 - SafeDelete(renderer); - } - } -#endif + std::vector rendererCreationFunctions; -#if defined(ANGLE_ENABLE_D3D9) - if (displayId != EGL_D3D11_ONLY_DISPLAY_ANGLE) +# if defined(ANGLE_ENABLE_D3D11) + if (nativeDisplay == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE || + nativeDisplay == EGL_D3D11_ONLY_DISPLAY_ANGLE || + requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE || + requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D11_WARP_ANGLE) + { + rendererCreationFunctions.push_back(rx::CreateRenderer); + } +# endif + +# if defined(ANGLE_ENABLE_D3D9) + if (nativeDisplay == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE || + requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE) + { + rendererCreationFunctions.push_back(rx::CreateRenderer); + } +# endif + + if (nativeDisplay != EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE && + nativeDisplay != EGL_D3D11_ONLY_DISPLAY_ANGLE && + requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE) { - rx::Renderer9 *renderer = new rx::Renderer9(display, hDc); + // The default display is requested, try the D3D9 and D3D11 renderers, order them using + // the definition of ANGLE_DEFAULT_D3D11 +# if ANGLE_DEFAULT_D3D11 +# if defined(ANGLE_ENABLE_D3D11) + rendererCreationFunctions.push_back(rx::CreateRenderer); +# endif +# if defined(ANGLE_ENABLE_D3D9) + rendererCreationFunctions.push_back(rx::CreateRenderer); +# endif +# else +# if defined(ANGLE_ENABLE_D3D9) + rendererCreationFunctions.push_back(rx::CreateRenderer); +# endif +# if defined(ANGLE_ENABLE_D3D11) + rendererCreationFunctions.push_back(rx::CreateRenderer); +# endif +# endif + } + + for (size_t i = 0; i < rendererCreationFunctions.size(); i++) + { + rx::Renderer *renderer = rendererCreationFunctions[i](display, nativeDisplay, requestedDisplayType); if (renderer->initialize() == EGL_SUCCESS) { return renderer; } else { + // Failed to create the renderer, try the next SafeDelete(renderer); } } -#endif return NULL; } diff --git a/gfx/angle/src/libGLESv2/renderer/Renderer.h b/gfx/angle/src/libGLESv2/renderer/Renderer.h index b2a05d92d2c2..d3d253bc54e3 100644 --- a/gfx/angle/src/libGLESv2/renderer/Renderer.h +++ b/gfx/angle/src/libGLESv2/renderer/Renderer.h @@ -12,6 +12,11 @@ #include "libGLESv2/Uniform.h" #include "libGLESv2/angletypes.h" +#include "libGLESv2/Caps.h" + +#include + +#include #if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL) // WARNING: D3DCOMPILE_OPTIMIZATION_LEVEL3 may lead to a DX9 shader compiler hang. @@ -29,7 +34,7 @@ namespace gl class InfoLog; class ProgramBinary; struct LinkedVarying; -class VertexAttribute; +struct VertexAttribute; class Buffer; class Texture; class Framebuffer; @@ -46,14 +51,19 @@ class VertexBuffer; class IndexBuffer; class QueryImpl; class FenceImpl; +class BufferImpl; +class VertexArrayImpl; class BufferStorage; struct TranslatedIndexData; +class ShaderImpl; class ShaderExecutable; class SwapChain; class RenderTarget; class Image; class TextureStorage; class UniformStorage; +class TextureImpl; +class TransformFeedbackImpl; struct ConfigDesc { @@ -117,10 +127,11 @@ class Renderer bool ignoreViewport) = 0; virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer) = 0; - virtual void applyShaders(gl::ProgramBinary *programBinary, bool rasterizerDiscard, bool transformFeedbackActive, const gl::VertexFormat inputLayout[]) = 0; + virtual void applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, + bool rasterizerDiscard, bool transformFeedbackActive) = 0; virtual void applyUniforms(const gl::ProgramBinary &programBinary) = 0; virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount) = 0; - virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], gl::VertexAttribCurrentValueData currentValues[], + virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], const gl::VertexAttribCurrentValueData currentValues[], 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 applyTransformFeedbackBuffers(gl::Buffer *transformFeedbackBuffers[], GLintptr offsets[]) = 0; @@ -139,73 +150,26 @@ class Renderer virtual bool testDeviceLost(bool notify) = 0; virtual bool testDeviceResettable() = 0; - // Renderer capabilities + // Renderer capabilities (virtual because it is used by egl::Display, do not override) + virtual const gl::Caps &getRendererCaps() const; + virtual const gl::TextureCapsMap &getRendererTextureCaps() const; + virtual const gl::Extensions &getRendererExtensions() const; + virtual DWORD getAdapterVendor() const = 0; virtual std::string getRendererDescription() const = 0; virtual GUID getAdapterIdentifier() const = 0; - virtual bool getBGRATextureSupport() const = 0; - virtual bool getDXT1TextureSupport() const = 0; - virtual bool getDXT3TextureSupport() const = 0; - virtual bool getDXT5TextureSupport() const = 0; - virtual bool getEventQuerySupport() const = 0; - virtual bool getFloat32TextureSupport() const = 0; - virtual bool getFloat32TextureFilteringSupport() const= 0; - virtual bool getFloat32TextureRenderingSupport() const= 0; - virtual bool getFloat16TextureSupport() const= 0; - virtual bool getFloat16TextureFilteringSupport() const= 0; - virtual bool getFloat16TextureRenderingSupport() const = 0; - virtual bool getRGB565TextureSupport() const = 0; - virtual bool getLuminanceTextureSupport() const = 0; - virtual bool getLuminanceAlphaTextureSupport() const = 0; - virtual bool getRGTextureSupport() const = 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 unsigned int getMaxVertexShaderUniformBuffers() const = 0; - virtual unsigned int getMaxFragmentShaderUniformBuffers() const = 0; virtual unsigned int getReservedVertexUniformBuffers() const = 0; virtual unsigned int getReservedFragmentUniformBuffers() const = 0; - virtual unsigned int getMaxTransformFeedbackBuffers() const = 0; - virtual unsigned int getMaxTransformFeedbackSeparateComponents() const = 0; - virtual unsigned int getMaxTransformFeedbackInterleavedComponents() const = 0; - virtual unsigned int getMaxUniformBufferSize() 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 bool getPBOSupport() const = 0; - virtual float getTextureMaxAnisotropy() const = 0; virtual bool getShareHandleSupport() const = 0; - virtual bool getDerivativeInstructionSupport() const = 0; virtual bool getPostSubBufferSupport() const = 0; - virtual int getMaxRecommendedElementsIndices() const = 0; - virtual int getMaxRecommendedElementsVertices() 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 int getMaxTextureDepth() const = 0; - virtual int getMaxTextureArrayLayers() const = 0; - virtual bool get32BitIndexSupport() const = 0; virtual int getMinSwapInterval() const = 0; virtual int getMaxSwapInterval() const = 0; - virtual GLsizei getMaxSupportedSamples() const = 0; - virtual GLsizei getMaxSupportedFormatSamples(GLenum internalFormat) const = 0; - virtual GLsizei getNumSampleCounts(GLenum internalFormat) const = 0; - virtual void getSampleCounts(GLenum internalFormat, GLsizei bufSize, GLint *params) 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; @@ -224,13 +188,17 @@ class Renderer virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter) = 0; virtual void readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, - GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, void* pixels) = 0; + GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) = 0; // RenderTarget creation virtual RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth) = 0; virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples) = 0; + // Shader creation + virtual ShaderImpl *createShader(GLenum type) = 0; + // Shader operations + virtual void releaseShaderCompiler() = 0; virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type, const std::vector &transformFeedbackVaryings, bool separatedOutputBuffers) = 0; @@ -248,15 +216,24 @@ class Renderer virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) = 0; virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) = 0; + // Texture creation + virtual TextureImpl *createTexture(GLenum target) = 0; + // Buffer creation + virtual BufferImpl *createBuffer() = 0; virtual VertexBuffer *createVertexBuffer() = 0; virtual IndexBuffer *createIndexBuffer() = 0; - virtual BufferStorage *createBufferStorage() = 0; + + // Vertex Array creation + virtual VertexArrayImpl *createVertexArray() = 0; // Query and Fence creation virtual QueryImpl *createQuery(GLenum type) = 0; virtual FenceImpl *createFence() = 0; + // Transform Feedback creation + virtual TransformFeedbackImpl* createTransformFeedback() = 0; + // Current GLES client version void setCurrentClientVersion(int clientVersion) { mCurrentClientVersion = clientVersion; } int getCurrentClientVersion() const { return mCurrentClientVersion; } @@ -267,7 +244,6 @@ class Renderer GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) = 0; virtual bool getLUID(LUID *adapterLuid) const = 0; - virtual GLenum getNativeTextureFormat(GLenum internalFormat) const = 0; virtual rx::VertexConversionType getVertexConversionType(const gl::VertexFormat &vertexFormat) const = 0; virtual GLenum getVertexComponentType(const gl::VertexFormat &vertexFormat) const = 0; @@ -277,6 +253,13 @@ class Renderer private: DISALLOW_COPY_AND_ASSIGN(Renderer); + virtual void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap* outTextureCaps, gl::Extensions *outExtensions) const = 0; + + mutable bool mCapsInitialized; + mutable gl::Caps mCaps; + mutable gl::TextureCapsMap mTextureCaps; + mutable gl::Extensions mExtensions; + int mCurrentClientVersion; }; diff --git a/gfx/angle/src/libGLESv2/renderer/ShaderExecutable.h b/gfx/angle/src/libGLESv2/renderer/ShaderExecutable.h index 5e229d7d5e85..f17195673dab 100644 --- a/gfx/angle/src/libGLESv2/renderer/ShaderExecutable.h +++ b/gfx/angle/src/libGLESv2/renderer/ShaderExecutable.h @@ -13,38 +13,37 @@ #include "common/angleutils.h" #include "common/debug.h" +#include +#include + namespace rx { class ShaderExecutable { public: - ShaderExecutable(const void *function, size_t length) : mLength(length) + ShaderExecutable(const void *function, size_t length) + : mFunctionBuffer(length) { - mFunction = new char[length]; - memcpy(mFunction, function, length); - } - - virtual ~ShaderExecutable() - { - delete[] mFunction; + memcpy(mFunctionBuffer.data(), function, length); } - void *getFunction() const + virtual ~ShaderExecutable() {} + + const uint8_t *getFunction() const { - return mFunction; + return mFunctionBuffer.data(); } size_t getLength() const { - return mLength; + return mFunctionBuffer.size(); } private: DISALLOW_COPY_AND_ASSIGN(ShaderExecutable); - void *mFunction; - const size_t mLength; + std::vector mFunctionBuffer; }; class UniformStorage diff --git a/gfx/angle/src/libGLESv2/renderer/ShaderImpl.h b/gfx/angle/src/libGLESv2/renderer/ShaderImpl.h new file mode 100644 index 000000000000..e87d40e872ad --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/ShaderImpl.h @@ -0,0 +1,29 @@ +// +// Copyright 2014 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. +// + +// ShaderImpl.h: Defines the abstract rx::ShaderImpl class. + +#ifndef LIBGLESV2_RENDERER_SHADERIMPL_H_ +#define LIBGLESV2_RENDERER_SHADERIMPL_H_ + +#include "common/angleutils.h" + +namespace rx +{ + +class ShaderImpl +{ + public: + virtual ~ShaderImpl() { } + + virtual bool compile(const std::string &source) = 0; + virtual const std::string &getInfoLog() const = 0; + virtual const std::string &getTranslatedSource() const = 0; +}; + +} + +#endif // LIBGLESV2_RENDERER_SHADERIMPL_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/SwapChain.h b/gfx/angle/src/libGLESv2/renderer/SwapChain.h index f09f19b2006d..c53b2af6515f 100644 --- a/gfx/angle/src/libGLESv2/renderer/SwapChain.h +++ b/gfx/angle/src/libGLESv2/renderer/SwapChain.h @@ -11,6 +11,10 @@ #define LIBGLESV2_RENDERER_SWAPCHAIN_H_ #include "common/angleutils.h" +#include "common/platform.h" + +#include +#include #if !defined(ANGLE_FORCE_VSYNC_OFF) #define ANGLE_FORCE_VSYNC_OFF 0 diff --git a/gfx/angle/src/libGLESv2/renderer/TextureImpl.h b/gfx/angle/src/libGLESv2/renderer/TextureImpl.h new file mode 100644 index 000000000000..c34485a31d31 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/TextureImpl.h @@ -0,0 +1,70 @@ +// +// Copyright 2014 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. +// + +// TextureImpl.h: Defines the abstract rx::TextureImpl classes. + +#ifndef LIBGLESV2_RENDERER_TEXTUREIMPL_H_ +#define LIBGLESV2_RENDERER_TEXTUREIMPL_H_ + +#include "common/angleutils.h" + +#include "angle_gl.h" + +namespace egl +{ +class Surface; +} + +namespace gl +{ +class Framebuffer; +struct PixelUnpackState; +struct SamplerState; +} + +namespace rx +{ + +class Image; +class RenderTarget; +class Renderer; +class TextureStorageInterface; + +class TextureImpl +{ + public: + virtual ~TextureImpl() {}; + + // TODO: If this methods could go away that would be ideal; + // TextureStorage should only be necessary for the D3D backend, and as such + // higher level code should not rely on it. + virtual TextureStorageInterface *getNativeTexture() = 0; + + virtual Image *getImage(int level, int layer) const = 0; + virtual GLsizei getLayerCount(int level) const = 0; + + virtual void setUsage(GLenum usage) = 0; + + virtual void setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) = 0; + virtual void setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels) = 0; + virtual void subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) = 0; + virtual void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels) = 0; + virtual void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0; + virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0; + virtual void storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) = 0; + + virtual void generateMipmaps() = 0; + + virtual unsigned int getRenderTargetSerial(GLint level, GLint layer) = 0; + virtual RenderTarget *getRenderTarget(GLint level, GLint layer) = 0; + + virtual void bindTexImage(egl::Surface *surface) = 0; + virtual void releaseTexImage() = 0; +}; + +} + +#endif // LIBGLESV2_RENDERER_TEXTUREIMPL_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/TransformFeedbackImpl.h b/gfx/angle/src/libGLESv2/renderer/TransformFeedbackImpl.h new file mode 100644 index 000000000000..8425604d8741 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/TransformFeedbackImpl.h @@ -0,0 +1,31 @@ +// +// Copyright 2014 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. +// + +// TransformFeedbackImpl.h: Defines the abstract rx::TransformFeedbackImpl class. + +#ifndef LIBGLESV2_RENDERER_TRANSFORMFEEDBACKIMPL_H_ +#define LIBGLESV2_RENDERER_TRANSFORMFEEDBACKIMPL_H_ + +#include "common/angleutils.h" +#include "libGLESv2/TransformFeedback.h" + +namespace rx +{ + +class TransformFeedbackImpl +{ + public: + virtual ~TransformFeedbackImpl() { } + + virtual void begin(GLenum primitiveMode) = 0; + virtual void end() = 0; + virtual void pause() = 0; + virtual void resume() = 0; +}; + +} + +#endif // LIBGLESV2_RENDERER_TRANSFORMFEEDBACKIMPL_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/VertexArrayImpl.h b/gfx/angle/src/libGLESv2/renderer/VertexArrayImpl.h new file mode 100644 index 000000000000..b013f9cdf43d --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/VertexArrayImpl.h @@ -0,0 +1,32 @@ +// +// Copyright 2014 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. +// + +// VertexAttribImpl.h: Defines the abstract rx::VertexAttribImpl class. + +#ifndef LIBGLESV2_RENDERER_VERTEXARRAYIMPL_H_ +#define LIBGLESV2_RENDERER_VERTEXARRAYIMPL_H_ + +#include "common/angleutils.h" +#include "libGLESv2/Buffer.h" +#include "libGLESv2/VertexAttribute.h" + +namespace rx +{ + +class VertexArrayImpl +{ + public: + virtual ~VertexArrayImpl() { } + + virtual void setElementArrayBuffer(const gl::Buffer *buffer) = 0; + virtual void setAttribute(size_t idx, const gl::VertexAttribute &attr) = 0; + virtual void setAttributeDivisor(size_t idx, GLuint divisor) = 0; + virtual void enableAttribute(size_t idx, bool enabledState) = 0; +}; + +} + +#endif // LIBGLESV2_RENDERER_VERTEXARRAYIMPL_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/VertexDataManager.cpp b/gfx/angle/src/libGLESv2/renderer/VertexDataManager.cpp deleted file mode 100644 index 6aad5ebb826a..000000000000 --- a/gfx/angle/src/libGLESv2/renderer/VertexDataManager.cpp +++ /dev/null @@ -1,293 +0,0 @@ -#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/VertexAttribute.h" -#include "libGLESv2/renderer/VertexBuffer.h" -#include "libGLESv2/renderer/Renderer.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; -} - -static int StreamingBufferElementCount(const gl::VertexAttribute &attribute, int vertexDrawCount, int instanceDrawCount) -{ - // For instanced rendering, we draw "instanceDrawCount" sets of "vertexDrawCount" vertices. - // - // A vertex attribute with a positive divisor loads one instanced vertex for every set of - // non-instanced vertices, and the instanced vertex index advances once every "mDivisor" instances. - if (instanceDrawCount > 0 && attribute.mDivisor > 0) - { - return instanceDrawCount / attribute.mDivisor; - } - - return vertexDrawCount; -} - -VertexDataManager::VertexDataManager(Renderer *renderer) : mRenderer(renderer) -{ - for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - mCurrentValue[i].FloatValues[0] = std::numeric_limits::quiet_NaN(); - mCurrentValue[i].FloatValues[1] = std::numeric_limits::quiet_NaN(); - mCurrentValue[i].FloatValues[2] = std::numeric_limits::quiet_NaN(); - mCurrentValue[i].FloatValues[3] = std::numeric_limits::quiet_NaN(); - mCurrentValue[i].Type = GL_FLOAT; - 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]; - } -} - -GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], const gl::VertexAttribCurrentValueData currentValues[], - 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) && - !staticBuffer->directStoragePossible(attribs[i], currentValues[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 (!vertexBuffer->directStoragePossible(attribs[i], currentValues[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 - { - int totalCount = StreamingBufferElementCount(attribs[i], count, instances); - - // [OpenGL ES 3.0.2] section 2.9.4 page 40: - // We can return INVALID_OPERATION if our vertex attribute does not have enough backing data. - if (buffer && ElementsInBuffer(attribs[i], buffer->size()) < totalCount) - { - return GL_INVALID_OPERATION; - } - - if (!mStreamingBuffer->reserveVertexSpace(attribs[i], totalCount, 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 = vertexBuffer->directStoragePossible(attribs[i], currentValues[i]); - - unsigned int streamOffset = 0; - unsigned int outputElementSize = 0; - - if (directStorage) - { - outputElementSize = attribs[i].stride(); - streamOffset = attribs[i].mOffset + outputElementSize * start; - } - 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], currentValues[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 - { - int totalCount = StreamingBufferElementCount(attribs[i], count, instances); - if (!mStreamingBuffer->getVertexBuffer()->getSpaceRequired(attribs[i], 1, 0, &outputElementSize) || - !mStreamingBuffer->storeVertexAttributes(attribs[i], currentValues[i], start, totalCount, 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].currentValueType = currentValues[i].Type; - 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] != currentValues[i]) - { - if (!buffer->reserveVertexSpace(attribs[i], 1, 0)) - { - return GL_OUT_OF_MEMORY; - } - - unsigned int streamOffset; - if (!buffer->storeVertexAttributes(attribs[i], currentValues[i], 0, 1, 0, &streamOffset)) - { - return GL_OUT_OF_MEMORY; - } - - mCurrentValue[i] = currentValues[i]; - 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].currentValueType = currentValues[i].Type; - 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/copyimage.cpp b/gfx/angle/src/libGLESv2/renderer/copyimage.cpp index 765089cc969f..004223d70f88 100644 --- a/gfx/angle/src/libGLESv2/renderer/copyimage.cpp +++ b/gfx/angle/src/libGLESv2/renderer/copyimage.cpp @@ -1,4 +1,3 @@ -#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 @@ -12,12 +11,12 @@ namespace rx { -void CopyBGRAUByteToRGBAUByte(const void *source, void *dest) +void CopyBGRA8ToRGBA8(const uint8_t *source, uint8_t *dest) { - unsigned int argb = *(unsigned int*)source; - *(unsigned int*)dest = (argb & 0xFF00FF00) | // Keep alpha and green - (argb & 0x00FF0000) >> 16 | // Move red to blue - (argb & 0x000000FF) << 16; // Move blue to red + uint32_t argb = *reinterpret_cast(source); + *reinterpret_cast(dest) = (argb & 0xFF00FF00) | // Keep alpha and green + (argb & 0x00FF0000) >> 16 | // Move red to blue + (argb & 0x000000FF) << 16; // Move blue to red } } diff --git a/gfx/angle/src/libGLESv2/renderer/copyimage.h b/gfx/angle/src/libGLESv2/renderer/copyimage.h index 2f37e1cedd02..513eb5cb3d44 100644 --- a/gfx/angle/src/libGLESv2/renderer/copyimage.h +++ b/gfx/angle/src/libGLESv2/renderer/copyimage.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2013-2014 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,31 +12,24 @@ #include "common/mathutil.h" #include "libGLESv2/angletypes.h" +#include + namespace rx { template -void ReadColor(const void *source, void *dest) -{ - sourceType::readColor(reinterpret_cast*>(dest), reinterpret_cast(source)); -} +void ReadColor(const uint8_t *source, uint8_t *dest); template -void WriteColor(const void *source, void *dest) -{ - destType::writeColor(reinterpret_cast(dest), reinterpret_cast*>(source)); -} +void WriteColor(const uint8_t *source, uint8_t *dest); template -void CopyPixel(const void *source, void *dest) -{ - colorType temp; - ReadColor(source, &temp); - WriteColor(&temp, dest); -} +void CopyPixel(const uint8_t *source, uint8_t *dest); -void CopyBGRAUByteToRGBAUByte(const void *source, void *dest); +void CopyBGRA8ToRGBA8(const uint8_t *source, uint8_t *dest); } +#include "copyimage.inl" + #endif // LIBGLESV2_RENDERER_COPYIMAGE_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/copyimage.inl b/gfx/angle/src/libGLESv2/renderer/copyimage.inl new file mode 100644 index 000000000000..ea6970cef359 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/copyimage.inl @@ -0,0 +1,32 @@ +// +// Copyright (c) 2014 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. +// + +// copyimage.inl: Defines image copying functions + +namespace rx +{ + +template +inline void ReadColor(const uint8_t *source, uint8_t *dest) +{ + sourceType::readColor(reinterpret_cast*>(dest), reinterpret_cast(source)); +} + +template +inline void WriteColor(const uint8_t *source, uint8_t *dest) +{ + destType::writeColor(reinterpret_cast(dest), reinterpret_cast*>(source)); +} + +template +inline void CopyPixel(const uint8_t *source, uint8_t *dest) +{ + colorType temp; + ReadColor(source, &temp); + WriteColor(&temp, dest); +} + +} diff --git a/gfx/angle/src/libGLESv2/renderer/copyvertex.h b/gfx/angle/src/libGLESv2/renderer/copyvertex.h index aca031701ebe..e0e8af166b06 100644 --- a/gfx/angle/src/libGLESv2/renderer/copyvertex.h +++ b/gfx/angle/src/libGLESv2/renderer/copyvertex.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2013-2014 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,299 +11,25 @@ #include "common/mathutil.h" +namespace rx +{ + // 'widenDefaultValueBits' gives the default value for the alpha channel (4th component) // the sentinel value 0 means we do not want to widen the input or add an alpha channel -template -inline void copyVertexData(const void *input, size_t stride, size_t count, void *output) -{ - const unsigned int attribSize = sizeof(T) * componentCount; - const T defaultValue = gl::bitCast(widenDefaultValueBits); - const bool widen = (widenDefaultValueBits != 0); +template +inline void CopyNativeVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output); - if (attribSize == stride && !widen) - { - memcpy(output, input, count * attribSize); - } - else - { - unsigned int outputStride = widen ? 4 : componentCount; +template +inline void Copy32FixedTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output); - 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] = defaultValue; - } - } - } -} - -template -inline void copyFixedVertexData(const void* input, size_t stride, size_t 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 -inline void copyToFloatVertexData(const void* input, size_t stride, size_t 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]); - } - } - } -} - -inline void copyPackedUnsignedVertexData(const void* input, size_t stride, size_t count, void* output) -{ - const unsigned int attribSize = 4; - - if (attribSize == stride) - { - memcpy(output, input, count * attribSize); - } - else - { - for (unsigned int i = 0; i < count; i++) - { - const GLuint *offsetInput = reinterpret_cast(reinterpret_cast(input) + (i * stride)); - GLuint *offsetOutput = reinterpret_cast(output) + (i * attribSize); - - offsetOutput[i] = offsetInput[i]; - } - } -} +template +inline void CopyTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output); template -static inline void copyPackedRGB(unsigned int data, void *output) -{ - const unsigned int rgbSignMask = 0x200; // 1 set at the 9 bit - const unsigned int negativeMask = 0xFFFFFC00; // All bits from 10 to 31 set to 1 +inline void CopyXYZ10W2ToXYZW32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output); - if (toFloat) - { - GLfloat *floatOutput = reinterpret_cast(output); - if (isSigned) - { - GLfloat finalValue = 0; - if (data & rgbSignMask) - { - int negativeNumber = data | negativeMask; - finalValue = static_cast(negativeNumber); - } - else - { - finalValue = static_cast(data); - } - - if (normalized) - { - const int maxValue = 0x1FF; // 1 set in bits 0 through 8 - const int minValue = 0xFFFFFE01; // Inverse of maxValue - - // A 10-bit two's complement number has the possibility of being minValue - 1 but - // OpenGL's normalization rules dictate that it should be clamped to minValue in this - // case. - if (finalValue < minValue) - { - finalValue = minValue; - } - - const int halfRange = (maxValue - minValue) >> 1; - *floatOutput = ((finalValue - minValue) / halfRange) - 1.0f; - } - else - { - *floatOutput = finalValue; - } - } - else - { - if (normalized) - { - const unsigned int maxValue = 0x3FF; // 1 set in bits 0 through 9 - *floatOutput = static_cast(data) / static_cast(maxValue); - } - else - { - *floatOutput = static_cast(data); - } - } - } - else - { - if (isSigned) - { - GLshort *intOutput = reinterpret_cast(output); - - if (data & rgbSignMask) - { - *intOutput = data | negativeMask; - } - else - { - *intOutput = data; - } - } - else - { - GLushort *uintOutput = reinterpret_cast(output); - *uintOutput = data; - } - } } -template -inline void copyPackedAlpha(unsigned int data, void *output) -{ - if (toFloat) - { - GLfloat *floatOutput = reinterpret_cast(output); - if (isSigned) - { - if (normalized) - { - switch (data) - { - case 0x0: *floatOutput = 0.0f; break; - case 0x1: *floatOutput = 1.0f; break; - case 0x2: *floatOutput = -1.0f; break; - case 0x3: *floatOutput = -1.0f; break; - default: UNREACHABLE(); - } - } - else - { - switch (data) - { - case 0x0: *floatOutput = 0.0f; break; - case 0x1: *floatOutput = 1.0f; break; - case 0x2: *floatOutput = -2.0f; break; - case 0x3: *floatOutput = -1.0f; break; - default: UNREACHABLE(); - } - } - } - else - { - if (normalized) - { - switch (data) - { - case 0x0: *floatOutput = 0.0f / 3.0f; break; - case 0x1: *floatOutput = 1.0f / 3.0f; break; - case 0x2: *floatOutput = 2.0f / 3.0f; break; - case 0x3: *floatOutput = 3.0f / 3.0f; break; - default: UNREACHABLE(); - } - } - else - { - switch (data) - { - case 0x0: *floatOutput = 0.0f; break; - case 0x1: *floatOutput = 1.0f; break; - case 0x2: *floatOutput = 2.0f; break; - case 0x3: *floatOutput = 3.0f; break; - default: UNREACHABLE(); - } - } - } - } - else - { - if (isSigned) - { - GLshort *intOutput = reinterpret_cast(output); - switch (data) - { - case 0x0: *intOutput = 0; break; - case 0x1: *intOutput = 1; break; - case 0x2: *intOutput = -2; break; - case 0x3: *intOutput = -1; break; - default: UNREACHABLE(); - } - } - else - { - GLushort *uintOutput = reinterpret_cast(output); - switch (data) - { - case 0x0: *uintOutput = 0; break; - case 0x1: *uintOutput = 1; break; - case 0x2: *uintOutput = 2; break; - case 0x3: *uintOutput = 3; break; - default: UNREACHABLE(); - } - } - } -} - -template -inline void copyPackedVertexData(const void* input, size_t stride, size_t count, void* output) -{ - const unsigned int outputComponentSize = toFloat ? 4 : 2; - const unsigned int componentCount = 4; - - const unsigned int rgbMask = 0x3FF; // 1 set in bits 0 through 9 - const unsigned int redShift = 0; // red is bits 0 through 9 - const unsigned int greenShift = 10; // green is bits 10 through 19 - const unsigned int blueShift = 20; // blue is bits 20 through 29 - - const unsigned int alphaMask = 0x3; // 1 set in bits 0 and 1 - const unsigned int alphaShift = 30; // Alpha is the 30 and 31 bits - - for (unsigned int i = 0; i < count; i++) - { - GLuint packedValue = *reinterpret_cast(reinterpret_cast(input) + (i * stride)); - GLbyte *offsetOutput = reinterpret_cast(output) + (i * outputComponentSize * componentCount); - - copyPackedRGB( (packedValue >> redShift) & rgbMask, offsetOutput + (0 * outputComponentSize)); - copyPackedRGB( (packedValue >> greenShift) & rgbMask, offsetOutput + (1 * outputComponentSize)); - copyPackedRGB( (packedValue >> blueShift) & rgbMask, offsetOutput + (2 * outputComponentSize)); - copyPackedAlpha((packedValue >> alphaShift) & alphaMask, offsetOutput + (3* outputComponentSize)); - } -} +#include "copyvertex.inl" #endif // LIBGLESV2_RENDERER_COPYVERTEX_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/copyvertex.inl b/gfx/angle/src/libGLESv2/renderer/copyvertex.inl new file mode 100644 index 000000000000..7eef17b22b01 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/copyvertex.inl @@ -0,0 +1,288 @@ +// +// Copyright (c) 2014 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. +// + +namespace rx +{ + +template +inline void CopyNativeVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output) +{ + const size_t attribSize = sizeof(T)* componentCount; + const T defaultValue = gl::bitCast(widenDefaultValueBits); + const bool widen = (widenDefaultValueBits != 0); + + if (attribSize == stride && !widen) + { + memcpy(output, input, count * attribSize); + } + else + { + size_t outputStride = widen ? 4 : componentCount; + + for (size_t i = 0; i < count; i++) + { + const T *offsetInput = reinterpret_cast(input + (i * stride)); + T *offsetOutput = reinterpret_cast(output) + i * outputStride; + + for (size_t j = 0; j < componentCount; j++) + { + offsetOutput[j] = offsetInput[j]; + } + + if (widen) + { + offsetOutput[3] = defaultValue; + } + } + } +} + +template +inline void Copy32FixedTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output) +{ + static const float divisor = 1.0f / (1 << 16); + + for (size_t i = 0; i < count; i++) + { + const GLfixed* offsetInput = reinterpret_cast(input + (stride * i)); + float* offsetOutput = reinterpret_cast(output) + i * componentCount; + + for (size_t j = 0; j < componentCount; j++) + { + offsetOutput[j] = static_cast(offsetInput[j]) * divisor; + } + } +} + +template +inline void CopyTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output) +{ + typedef std::numeric_limits NL; + + for (size_t i = 0; i < count; i++) + { + const T *offsetInput = reinterpret_cast(input + (stride * i)); + float *offsetOutput = reinterpret_cast(output) + i * componentCount; + + for (size_t 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]); + } + } + } +} + +namespace priv +{ + +template +static inline void CopyPackedRGB(uint32_t data, uint8_t *output) +{ + const uint32_t rgbSignMask = 0x200; // 1 set at the 9 bit + const uint32_t negativeMask = 0xFFFFFC00; // All bits from 10 to 31 set to 1 + + if (toFloat) + { + GLfloat *floatOutput = reinterpret_cast(output); + if (isSigned) + { + GLfloat finalValue = 0; + if (data & rgbSignMask) + { + int negativeNumber = data | negativeMask; + finalValue = static_cast(negativeNumber); + } + else + { + finalValue = static_cast(data); + } + + if (normalized) + { + const int32_t maxValue = 0x1FF; // 1 set in bits 0 through 8 + const int32_t minValue = 0xFFFFFE01; // Inverse of maxValue + + // A 10-bit two's complement number has the possibility of being minValue - 1 but + // OpenGL's normalization rules dictate that it should be clamped to minValue in this + // case. + if (finalValue < minValue) + { + finalValue = minValue; + } + + const int32_t halfRange = (maxValue - minValue) >> 1; + *floatOutput = ((finalValue - minValue) / halfRange) - 1.0f; + } + else + { + *floatOutput = finalValue; + } + } + else + { + if (normalized) + { + const uint32_t maxValue = 0x3FF; // 1 set in bits 0 through 9 + *floatOutput = static_cast(data) / static_cast(maxValue); + } + else + { + *floatOutput = static_cast(data); + } + } + } + else + { + if (isSigned) + { + GLshort *intOutput = reinterpret_cast(output); + + if (data & rgbSignMask) + { + *intOutput = data | negativeMask; + } + else + { + *intOutput = data; + } + } + else + { + GLushort *uintOutput = reinterpret_cast(output); + *uintOutput = data; + } + } +} + +template +inline void CopyPackedAlpha(uint32_t data, uint8_t *output) +{ + if (toFloat) + { + GLfloat *floatOutput = reinterpret_cast(output); + if (isSigned) + { + if (normalized) + { + switch (data) + { + case 0x0: *floatOutput = 0.0f; break; + case 0x1: *floatOutput = 1.0f; break; + case 0x2: *floatOutput = -1.0f; break; + case 0x3: *floatOutput = -1.0f; break; + default: UNREACHABLE(); + } + } + else + { + switch (data) + { + case 0x0: *floatOutput = 0.0f; break; + case 0x1: *floatOutput = 1.0f; break; + case 0x2: *floatOutput = -2.0f; break; + case 0x3: *floatOutput = -1.0f; break; + default: UNREACHABLE(); + } + } + } + else + { + if (normalized) + { + switch (data) + { + case 0x0: *floatOutput = 0.0f / 3.0f; break; + case 0x1: *floatOutput = 1.0f / 3.0f; break; + case 0x2: *floatOutput = 2.0f / 3.0f; break; + case 0x3: *floatOutput = 3.0f / 3.0f; break; + default: UNREACHABLE(); + } + } + else + { + switch (data) + { + case 0x0: *floatOutput = 0.0f; break; + case 0x1: *floatOutput = 1.0f; break; + case 0x2: *floatOutput = 2.0f; break; + case 0x3: *floatOutput = 3.0f; break; + default: UNREACHABLE(); + } + } + } + } + else + { + if (isSigned) + { + GLshort *intOutput = reinterpret_cast(output); + switch (data) + { + case 0x0: *intOutput = 0; break; + case 0x1: *intOutput = 1; break; + case 0x2: *intOutput = -2; break; + case 0x3: *intOutput = -1; break; + default: UNREACHABLE(); + } + } + else + { + GLushort *uintOutput = reinterpret_cast(output); + switch (data) + { + case 0x0: *uintOutput = 0; break; + case 0x1: *uintOutput = 1; break; + case 0x2: *uintOutput = 2; break; + case 0x3: *uintOutput = 3; break; + default: UNREACHABLE(); + } + } + } +} + +} + +template +inline void CopyXYZ10W2ToXYZW32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output) +{ + const size_t outputComponentSize = toFloat ? 4 : 2; + const size_t componentCount = 4; + + const uint32_t rgbMask = 0x3FF; // 1 set in bits 0 through 9 + const size_t redShift = 0; // red is bits 0 through 9 + const size_t greenShift = 10; // green is bits 10 through 19 + const size_t blueShift = 20; // blue is bits 20 through 29 + + const uint32_t alphaMask = 0x3; // 1 set in bits 0 and 1 + const size_t alphaShift = 30; // Alpha is the 30 and 31 bits + + for (size_t i = 0; i < count; i++) + { + GLuint packedValue = *reinterpret_cast(input + (i * stride)); + uint8_t *offsetOutput = output + (i * outputComponentSize * componentCount); + + priv::CopyPackedRGB( (packedValue >> redShift) & rgbMask, offsetOutput + (0 * outputComponentSize)); + priv::CopyPackedRGB( (packedValue >> greenShift) & rgbMask, offsetOutput + (1 * outputComponentSize)); + priv::CopyPackedRGB( (packedValue >> blueShift) & rgbMask, offsetOutput + (2 * outputComponentSize)); + priv::CopyPackedAlpha((packedValue >> alphaShift) & alphaMask, offsetOutput + (3 * outputComponentSize)); + } +} + +} diff --git a/gfx/angle/src/libGLESv2/renderer/d3d/BufferD3D.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/BufferD3D.cpp new file mode 100644 index 000000000000..a34ef03fb859 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/d3d/BufferD3D.cpp @@ -0,0 +1,82 @@ +// +// Copyright 2014 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. +// + +// BufferD3D.cpp Defines common functionality between the Buffer9 and Buffer11 classes. + +#include "libGLESv2/renderer/d3d/BufferD3D.h" +#include "libGLESv2/renderer/d3d/VertexBuffer.h" +#include "libGLESv2/renderer/d3d/IndexBuffer.h" +#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/main.h" + +namespace rx +{ + +unsigned int BufferD3D::mNextSerial = 1; + +BufferD3D::BufferD3D() + : BufferImpl(), + mStaticVertexBuffer(NULL), + mStaticIndexBuffer(NULL) +{ + updateSerial(); +} + +BufferD3D::~BufferD3D() +{ + SafeDelete(mStaticVertexBuffer); + SafeDelete(mStaticIndexBuffer); +} + +BufferD3D *BufferD3D::makeBufferD3D(BufferImpl *buffer) +{ + ASSERT(HAS_DYNAMIC_TYPE(BufferD3D*, buffer)); + return static_cast(buffer); +} + +void BufferD3D::updateSerial() +{ + mSerial = mNextSerial++; +} + +void BufferD3D::initializeStaticData() +{ + if (!mStaticVertexBuffer) + { + mStaticVertexBuffer = new rx::StaticVertexBufferInterface(getRenderer()); + } + if (!mStaticIndexBuffer) + { + mStaticIndexBuffer = new rx::StaticIndexBufferInterface(getRenderer()); + } +} + +void BufferD3D::invalidateStaticData() +{ + if ((mStaticVertexBuffer && mStaticVertexBuffer->getBufferSize() != 0) || (mStaticIndexBuffer && mStaticIndexBuffer->getBufferSize() != 0)) + { + SafeDelete(mStaticVertexBuffer); + SafeDelete(mStaticIndexBuffer); + } + + mUnmodifiedDataUse = 0; +} + +// Creates static buffers if sufficient used data has been left unmodified +void BufferD3D::promoteStaticUsage(int dataSize) +{ + if (!mStaticVertexBuffer && !mStaticIndexBuffer) + { + mUnmodifiedDataUse += dataSize; + + if (mUnmodifiedDataUse > 3 * getSize()) + { + initializeStaticData(); + } + } +} + +} \ No newline at end of file diff --git a/gfx/angle/src/libGLESv2/renderer/d3d/BufferD3D.h b/gfx/angle/src/libGLESv2/renderer/d3d/BufferD3D.h new file mode 100644 index 000000000000..44f14cee589f --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/d3d/BufferD3D.h @@ -0,0 +1,56 @@ +// +// Copyright 2014 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. +// + +// BufferImpl.h: Defines the abstract rx::BufferImpl class. + +#ifndef LIBGLESV2_RENDERER_BUFFERD3D_H_ +#define LIBGLESV2_RENDERER_BUFFERD3D_H_ + +#include "libGLESv2/renderer/BufferImpl.h" +#include "libGLESv2/angletypes.h" + +namespace rx +{ + +class Renderer; +class StaticIndexBufferInterface; +class StaticVertexBufferInterface; + +class BufferD3D : public BufferImpl +{ + public: + BufferD3D(); + virtual ~BufferD3D(); + + static BufferD3D *makeBufferD3D(BufferImpl *buffer); + + unsigned int getSerial() const { return mSerial; } + + virtual size_t getSize() const = 0; + virtual bool supportsDirectBinding() const = 0; + virtual Renderer* getRenderer() = 0; + + rx::StaticVertexBufferInterface *getStaticVertexBuffer() { return mStaticVertexBuffer; } + rx::StaticIndexBufferInterface *getStaticIndexBuffer() { return mStaticIndexBuffer; } + + void initializeStaticData(); + void invalidateStaticData(); + void promoteStaticUsage(int dataSize); + + protected: + unsigned int mSerial; + static unsigned int mNextSerial; + + void updateSerial(); + + rx::StaticVertexBufferInterface *mStaticVertexBuffer; + rx::StaticIndexBufferInterface *mStaticIndexBuffer; + unsigned int mUnmodifiedDataUse; +}; + +} + +#endif // LIBGLESV2_RENDERER_BUFFERIMPLD3D_H_ diff --git a/gfx/angle/src/libGLESv2/DynamicHLSL.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.cpp similarity index 63% rename from gfx/angle/src/libGLESv2/DynamicHLSL.cpp rename to gfx/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.cpp index 20e4a2054885..a83ed54f84ce 100644 --- a/gfx/angle/src/libGLESv2/DynamicHLSL.cpp +++ b/gfx/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.cpp @@ -6,23 +6,21 @@ // DynamicHLSL.cpp: Implementation for link and run-time HLSL generation // -#include "precompiled.h" - -#include "libGLESv2/DynamicHLSL.h" +#include "libGLESv2/renderer/d3d/DynamicHLSL.h" +#include "libGLESv2/renderer/d3d/ShaderD3D.h" +#include "libGLESv2/renderer/Renderer.h" #include "libGLESv2/Shader.h" #include "libGLESv2/Program.h" -#include "libGLESv2/renderer/Renderer.h" -#include "common/utilities.h" #include "libGLESv2/ProgramBinary.h" #include "libGLESv2/formatutils.h" + +#include "common/utilities.h" #include "common/blocklayout.h" -static std::string Str(int i) -{ - char buffer[20]; - snprintf(buffer, sizeof(buffer), "%d", i); - return buffer; -} +// For use with ArrayString, see angleutils.h +META_ASSERT(GL_INVALID_INDEX == UINT_MAX); + +using namespace gl; namespace gl_d3d { @@ -69,20 +67,16 @@ std::string HLSLTypeString(GLenum type) return HLSLMatrixTypeString(type); } - return HLSLComponentTypeString(gl::UniformComponentType(type), gl::UniformComponentCount(type)); + return HLSLComponentTypeString(gl::VariableComponentType(type), gl::VariableComponentCount(type)); } } -namespace gl +namespace rx { -std::string ArrayString(unsigned int i) -{ - return (i == GL_INVALID_INDEX ? "" : "[" + Str(i) + "]"); -} - -const std::string DynamicHLSL::VERTEX_ATTRIBUTE_STUB_STRING = "@@ VERTEX ATTRIBUTES @@"; +const std::string VERTEX_ATTRIBUTE_STUB_STRING = "@@ VERTEX ATTRIBUTES @@"; +const std::string PIXEL_OUTPUT_STUB_STRING = "@@ PIXEL OUTPUT @@"; DynamicHLSL::DynamicHLSL(rx::Renderer *const renderer) : mRenderer(renderer) @@ -213,10 +207,11 @@ static bool packVarying(PackedVarying *varying, const int maxVaryingVectors, Var // 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 DynamicHLSL::packVaryings(InfoLog &infoLog, VaryingPacking packing, FragmentShader *fragmentShader, - VertexShader *vertexShader, const std::vector& transformFeedbackVaryings) +int DynamicHLSL::packVaryings(InfoLog &infoLog, VaryingPacking packing, rx::FragmentShaderD3D *fragmentShader, + rx::VertexShaderD3D *vertexShader, const std::vector& transformFeedbackVaryings) { - const int maxVaryingVectors = mRenderer->getMaxVaryingVectors(); + // TODO (geofflang): Use context's caps + const int maxVaryingVectors = mRenderer->getRendererCaps().maxVaryingVectors; vertexShader->resetVaryingsRegisterAssignment(); fragmentShader->resetVaryingsRegisterAssignment(); @@ -281,9 +276,9 @@ int DynamicHLSL::packVaryings(InfoLog &infoLog, VaryingPacking packing, Fragment return registers; } -std::string DynamicHLSL::generateVaryingHLSL(VertexShader *shader, const std::string &varyingSemantic, - std::vector *linkedVaryings) const +std::string DynamicHLSL::generateVaryingHLSL(rx::VertexShaderD3D *shader) const { + std::string varyingSemantic = getVaryingSemantic(shader->mUsesPointSize); std::string varyingHLSL; for (unsigned int varyingIndex = 0; varyingIndex < shader->mVaryings.size(); varyingIndex++) @@ -300,9 +295,9 @@ std::string DynamicHLSL::generateVaryingHLSL(VertexShader *shader, const std::st { switch (varying.interpolation) { - case INTERPOLATION_SMOOTH: varyingHLSL += " "; break; - case INTERPOLATION_FLAT: varyingHLSL += " nointerpolation "; break; - case INTERPOLATION_CENTROID: varyingHLSL += " centroid "; break; + case sh::INTERPOLATION_SMOOTH: varyingHLSL += " "; break; + case sh::INTERPOLATION_FLAT: varyingHLSL += " nointerpolation "; break; + case sh::INTERPOLATION_CENTROID: varyingHLSL += " centroid "; break; default: UNREACHABLE(); } @@ -319,27 +314,22 @@ std::string DynamicHLSL::generateVaryingHLSL(VertexShader *shader, const std::st } else { - GLenum componentType = UniformComponentType(transposedType); + GLenum componentType = VariableComponentType(transposedType); int columnCount = VariableColumnCount(transposedType); typeString = gl_d3d::HLSLComponentTypeString(componentType, columnCount); } varyingHLSL += typeString + " v" + n + " : " + varyingSemantic + n + ";\n"; } } - - if (linkedVaryings) - { - linkedVaryings->push_back(LinkedVarying(varying.name, varying.type, varying.elementCount(), - varyingSemantic, varying.registerIndex, - variableRows * varying.elementCount())); - } } } return varyingHLSL; } -std::string DynamicHLSL::generateInputLayoutHLSL(const VertexFormat inputLayout[], const Attribute shaderAttributes[]) const +std::string DynamicHLSL::generateVertexShaderForInputLayout(const std::string &sourceShader, + const VertexFormat inputLayout[], + const sh::Attribute shaderAttributes[]) const { std::string structHLSL, initHLSL; @@ -351,7 +341,7 @@ std::string DynamicHLSL::generateInputLayoutHLSL(const VertexFormat inputLayout[ ASSERT(inputIndex < MAX_VERTEX_ATTRIBS); const VertexFormat &vertexFormat = inputLayout[inputIndex]; - const Attribute &shaderAttribute = shaderAttributes[attributeIndex]; + const sh::Attribute &shaderAttribute = shaderAttributes[attributeIndex]; if (!shaderAttribute.name.empty()) { @@ -364,11 +354,11 @@ std::string DynamicHLSL::generateInputLayoutHLSL(const VertexFormat inputLayout[ else { GLenum componentType = mRenderer->getVertexComponentType(vertexFormat); - structHLSL += " " + gl_d3d::HLSLComponentTypeString(componentType, UniformComponentCount(shaderAttribute.type)); + structHLSL += " " + gl_d3d::HLSLComponentTypeString(componentType, VariableComponentCount(shaderAttribute.type)); } structHLSL += " " + decorateVariable(shaderAttribute.name) + " : TEXCOORD" + Str(semanticIndex) + ";\n"; - semanticIndex += AttributeRegisterCount(shaderAttribute.type); + semanticIndex += VariableRegisterCount(shaderAttribute.type); // HLSL code for initialization initHLSL += " " + decorateVariable(shaderAttribute.name) + " = "; @@ -392,23 +382,257 @@ std::string DynamicHLSL::generateInputLayoutHLSL(const VertexFormat inputLayout[ } } - return "struct VS_INPUT\n" - "{\n" + - structHLSL + - "};\n" - "\n" - "void initAttributes(VS_INPUT input)\n" - "{\n" + - initHLSL + - "}\n"; + std::string replacementHLSL = "struct VS_INPUT\n" + "{\n" + + structHLSL + + "};\n" + "\n" + "void initAttributes(VS_INPUT input)\n" + "{\n" + + initHLSL + + "}\n"; + + std::string vertexHLSL(sourceShader); + + size_t copyInsertionPos = vertexHLSL.find(VERTEX_ATTRIBUTE_STUB_STRING); + vertexHLSL.replace(copyInsertionPos, VERTEX_ATTRIBUTE_STUB_STRING.length(), replacementHLSL); + + return vertexHLSL; +} + +std::string DynamicHLSL::generatePixelShaderForOutputSignature(const std::string &sourceShader, const std::vector &outputVariables, + bool usesFragDepth, const std::vector &outputLayout) const +{ + const int shaderModel = mRenderer->getMajorShaderModel(); + std::string targetSemantic = (shaderModel >= 4) ? "SV_TARGET" : "COLOR"; + std::string depthSemantic = (shaderModel >= 4) ? "SV_Depth" : "DEPTH"; + + std::string declarationHLSL; + std::string copyHLSL; + for (size_t i = 0; i < outputVariables.size(); i++) + { + const PixelShaderOuputVariable& outputVariable = outputVariables[i]; + ASSERT(outputLayout.size() > outputVariable.outputIndex); + + // FIXME(geofflang): Work around NVIDIA driver bug by repacking buffers + bool outputIndexEnabled = true; // outputLayout[outputVariable.outputIndex] != GL_NONE + if (outputIndexEnabled) + { + declarationHLSL += " " + gl_d3d::HLSLTypeString(outputVariable.type) + " " + outputVariable.name + + " : " + targetSemantic + Str(outputVariable.outputIndex) + ";\n"; + + copyHLSL += " output." + outputVariable.name + " = " + outputVariable.source + ";\n"; + } + } + + if (usesFragDepth) + { + declarationHLSL += " float gl_Depth : " + depthSemantic + ";\n"; + copyHLSL += " output.gl_Depth = gl_Depth; \n"; + } + + std::string replacementHLSL = "struct PS_OUTPUT\n" + "{\n" + + declarationHLSL + + "};\n" + "\n" + "PS_OUTPUT generateOutput()\n" + "{\n" + " PS_OUTPUT output;\n" + + copyHLSL + + " return output;\n" + "}\n"; + + std::string pixelHLSL(sourceShader); + + size_t outputInsertionPos = pixelHLSL.find(PIXEL_OUTPUT_STUB_STRING); + pixelHLSL.replace(outputInsertionPos, PIXEL_OUTPUT_STUB_STRING.length(), replacementHLSL); + + return pixelHLSL; +} + +std::string DynamicHLSL::getVaryingSemantic(bool pointSize) const +{ + // SM3 reserves the TEXCOORD semantic for point sprite texcoords (gl_PointCoord) + // In D3D11 we manually compute gl_PointCoord in the GS. + int shaderModel = mRenderer->getMajorShaderModel(); + return ((pointSize && shaderModel < 4) ? "COLOR" : "TEXCOORD"); +} + +struct DynamicHLSL::SemanticInfo +{ + struct BuiltinInfo + { + BuiltinInfo() + : enabled(false), + index(0), + systemValue(false) + {} + + bool enabled; + std::string semantic; + unsigned int index; + bool systemValue; + + std::string str() const + { + return (systemValue ? semantic : (semantic + Str(index))); + } + + void enableSystem(const std::string &systemValueSemantic) + { + enabled = true; + semantic = systemValueSemantic; + systemValue = true; + } + + void enable(const std::string &semanticVal, unsigned int indexVal) + { + enabled = true; + semantic = semanticVal; + index = indexVal; + } + }; + + BuiltinInfo dxPosition; + BuiltinInfo glPosition; + BuiltinInfo glFragCoord; + BuiltinInfo glPointCoord; + BuiltinInfo glPointSize; +}; + +DynamicHLSL::SemanticInfo DynamicHLSL::getSemanticInfo(int startRegisters, bool fragCoord, bool pointCoord, + bool pointSize, bool pixelShader) const +{ + SemanticInfo info; + bool hlsl4 = (mRenderer->getMajorShaderModel() >= 4); + const std::string &varyingSemantic = getVaryingSemantic(pointSize); + + int reservedRegisterIndex = startRegisters; + + if (hlsl4) + { + info.dxPosition.enableSystem("SV_Position"); + } + else if (pixelShader) + { + info.dxPosition.enableSystem("VPOS"); + } + else + { + info.dxPosition.enableSystem("POSITION"); + } + + info.glPosition.enable(varyingSemantic, reservedRegisterIndex++); + + if (fragCoord) + { + info.glFragCoord.enable(varyingSemantic, reservedRegisterIndex++); + } + + if (pointCoord) + { + // SM3 reserves the TEXCOORD semantic for point sprite texcoords (gl_PointCoord) + // In D3D11 we manually compute gl_PointCoord in the GS. + if (hlsl4) + { + info.glPointCoord.enable(varyingSemantic, reservedRegisterIndex++); + } + else + { + info.glPointCoord.enable("TEXCOORD", 0); + } + } + + // Special case: do not include PSIZE semantic in HLSL 3 pixel shaders + if (pointSize && (!pixelShader || hlsl4)) + { + info.glPointSize.enableSystem("PSIZE"); + } + + return info; +} + +std::string DynamicHLSL::generateVaryingLinkHLSL(const SemanticInfo &info, const std::string &varyingHLSL) const +{ + std::string linkHLSL = "{\n"; + + ASSERT(info.dxPosition.enabled && info.glPosition.enabled); + + linkHLSL += " float4 dx_Position : " + info.dxPosition.str() + ";\n"; + linkHLSL += " float4 gl_Position : " + info.glPosition.str() + ";\n"; + + if (info.glFragCoord.enabled) + { + linkHLSL += " float4 gl_FragCoord : " + info.glFragCoord.str() + ";\n"; + } + + if (info.glPointCoord.enabled) + { + linkHLSL += " float2 gl_PointCoord : " + info.glPointCoord.str() + ";\n"; + } + + linkHLSL += varyingHLSL; + + if (info.glPointSize.enabled) + { + linkHLSL += " float gl_PointSize : " + info.glPointSize.str() + ";\n"; + } + + linkHLSL += "};\n"; + + return linkHLSL; +} + +void DynamicHLSL::storeBuiltinLinkedVaryings(const SemanticInfo &info, + std::vector *linkedVaryings) const +{ + ASSERT(info.glPosition.enabled); + + linkedVaryings->push_back(LinkedVarying("gl_Position", GL_FLOAT_VEC4, 1, info.glPosition.semantic, + info.glPosition.index, 1)); + + if (info.glFragCoord.enabled) + { + linkedVaryings->push_back(LinkedVarying("gl_FragCoord", GL_FLOAT_VEC4, 1, info.glFragCoord.semantic, + info.glFragCoord.index, 1)); + } + + if (info.glPointSize.enabled) + { + linkedVaryings->push_back(LinkedVarying("gl_PointSize", GL_FLOAT, 1, "PSIZE", 0, 1)); + } +} + +void DynamicHLSL::storeUserLinkedVaryings(const rx::VertexShaderD3D *vertexShader, + std::vector *linkedVaryings) const +{ + const std::string &varyingSemantic = getVaryingSemantic(vertexShader->mUsesPointSize); + const std::vector &varyings = vertexShader->mVaryings; + + for (unsigned int varyingIndex = 0; varyingIndex < varyings.size(); varyingIndex++) + { + const PackedVarying &varying = varyings[varyingIndex]; + if (varying.registerAssigned()) + { + GLenum transposedType = TransposeMatrixType(varying.type); + int variableRows = (varying.isStruct() ? 1 : VariableRowCount(transposedType)); + + linkedVaryings->push_back(LinkedVarying(varying.name, varying.type, varying.elementCount(), + varyingSemantic, varying.registerIndex, + variableRows * varying.elementCount())); + } + } } bool DynamicHLSL::generateShaderLinkHLSL(InfoLog &infoLog, int registers, const VaryingPacking packing, std::string& pixelHLSL, std::string& vertexHLSL, - FragmentShader *fragmentShader, VertexShader *vertexShader, + rx::FragmentShaderD3D *fragmentShader, rx::VertexShaderD3D *vertexShader, const std::vector& transformFeedbackVaryings, std::vector *linkedVaryings, - std::map *programOutputVars) const + std::map *programOutputVars, + std::vector *outPixelShaderKey, + bool *outUsesFragDepth) const { if (pixelHLSL.empty() || vertexHLSL.empty()) { @@ -418,6 +642,10 @@ bool DynamicHLSL::generateShaderLinkHLSL(InfoLog &infoLog, int registers, const bool usesMRT = fragmentShader->mUsesMultipleRenderTargets; bool usesFragColor = fragmentShader->mUsesFragColor; bool usesFragData = fragmentShader->mUsesFragData; + bool usesFragCoord = fragmentShader->mUsesFragCoord; + bool usesPointCoord = fragmentShader->mUsesPointCoord; + bool usesPointSize = vertexShader->mUsesPointSize; + if (usesFragColor && usesFragData) { infoLog.append("Cannot use both gl_FragColor and gl_FragData in the same fragment shader."); @@ -426,101 +654,36 @@ bool DynamicHLSL::generateShaderLinkHLSL(InfoLog &infoLog, int registers, const // Write the HLSL input/output declarations const int shaderModel = mRenderer->getMajorShaderModel(); - const int maxVaryingVectors = mRenderer->getMaxVaryingVectors(); - const int registersNeeded = registers + (fragmentShader->mUsesFragCoord ? 1 : 0) + (fragmentShader->mUsesPointCoord ? 1 : 0); + // TODO (geofflang): Use context's caps + const int maxVaryingVectors = mRenderer->getRendererCaps().maxVaryingVectors; + + const int registersNeeded = registers + (usesFragCoord ? 1 : 0) + (usesPointCoord ? 1 : 0); // Two cases when writing to gl_FragColor and using ESSL 1.0: // - with a 3.0 context, the output color is copied to channel 0 // - with a 2.0 context, the output color is broadcast to all channels const bool broadcast = (fragmentShader->mUsesFragColor && mRenderer->getCurrentClientVersion() < 3); - const unsigned int numRenderTargets = (broadcast || usesMRT ? mRenderer->getMaxRenderTargets() : 1); + const unsigned int numRenderTargets = (broadcast || usesMRT ? mRenderer->getRendererCaps().maxDrawBuffers : 1); int shaderVersion = vertexShader->getShaderVersion(); if (registersNeeded > maxVaryingVectors) { infoLog.append("No varying registers left to support gl_FragCoord/gl_PointCoord"); - return false; } - std::string varyingSemantic = (vertexShader->mUsesPointSize && shaderModel == 3) ? "COLOR" : "TEXCOORD"; - std::string targetSemantic = (shaderModel >= 4) ? "SV_Target" : "COLOR"; - std::string dxPositionSemantic = (shaderModel >= 4) ? "SV_Position" : "POSITION"; - std::string depthSemantic = (shaderModel >= 4) ? "SV_Depth" : "DEPTH"; + const std::string &varyingHLSL = generateVaryingHLSL(vertexShader); + const SemanticInfo &vertexSemantics = getSemanticInfo(registers, usesFragCoord, + false, usesPointSize, false); - std::string varyingHLSL = generateVaryingHLSL(vertexShader, varyingSemantic, linkedVaryings); - - // special varyings that use reserved registers - int reservedRegisterIndex = registers; - - unsigned int glPositionSemanticIndex = reservedRegisterIndex++; - std::string glPositionSemantic = varyingSemantic; - - std::string fragCoordSemantic; - unsigned int fragCoordSemanticIndex = 0; - if (fragmentShader->mUsesFragCoord) - { - fragCoordSemanticIndex = reservedRegisterIndex++; - fragCoordSemantic = varyingSemantic; - } - - std::string pointCoordSemantic; - unsigned int pointCoordSemanticIndex = 0; - 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) - { - pointCoordSemanticIndex = 0; - pointCoordSemantic = "TEXCOORD0"; - } - else if (shaderModel >= 4) - { - pointCoordSemanticIndex = reservedRegisterIndex++; - pointCoordSemantic = varyingSemantic; - } - } + storeUserLinkedVaryings(vertexShader, linkedVaryings); + storeBuiltinLinkedVaryings(vertexSemantics, linkedVaryings); // Add stub string to be replaced when shader is dynamically defined by its layout - vertexHLSL += "\n" + VERTEX_ATTRIBUTE_STUB_STRING + "\n"; - - vertexHLSL += "struct VS_OUTPUT\n" - "{\n"; - - if (shaderModel < 4) - { - vertexHLSL += " float4 _dx_Position : " + dxPositionSemantic + ";\n"; - vertexHLSL += " float4 gl_Position : " + glPositionSemantic + Str(glPositionSemanticIndex) + ";\n"; - linkedVaryings->push_back(LinkedVarying("gl_Position", GL_FLOAT_VEC4, 1, glPositionSemantic, glPositionSemanticIndex, 1)); - - } - - vertexHLSL += varyingHLSL; - - if (fragmentShader->mUsesFragCoord) - { - vertexHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + Str(fragCoordSemanticIndex) + ";\n"; - linkedVaryings->push_back(LinkedVarying("gl_FragCoord", GL_FLOAT_VEC4, 1, fragCoordSemantic, fragCoordSemanticIndex, 1)); - } - - if (vertexShader->mUsesPointSize && shaderModel >= 3) - { - vertexHLSL += " float gl_PointSize : PSIZE;\n"; - linkedVaryings->push_back(LinkedVarying("gl_PointSize", GL_FLOAT, 1, "PSIZE", 0, 1)); - } - - if (shaderModel >= 4) - { - vertexHLSL += " float4 _dx_Position : " + dxPositionSemantic + ";\n"; - vertexHLSL += " float4 gl_Position : " + glPositionSemantic + Str(glPositionSemanticIndex) + ";\n"; - linkedVaryings->push_back(LinkedVarying("gl_Position", GL_FLOAT_VEC4, 1, glPositionSemantic, glPositionSemanticIndex, 1)); - } - - vertexHLSL += "};\n" - "\n" + vertexHLSL += "\n" + VERTEX_ATTRIBUTE_STUB_STRING + "\n" + "struct VS_OUTPUT\n" + generateVaryingLinkHLSL(vertexSemantics, varyingHLSL) + "\n" "VS_OUTPUT main(VS_INPUT input)\n" "{\n" " initAttributes(input);\n"; @@ -532,10 +695,10 @@ bool DynamicHLSL::generateShaderLinkHLSL(InfoLog &infoLog, int registers, const "\n" " VS_OUTPUT output;\n" " output.gl_Position = gl_Position;\n" - " output._dx_Position.x = gl_Position.x;\n" - " output._dx_Position.y = -gl_Position.y;\n" - " output._dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n" - " output._dx_Position.w = gl_Position.w;\n"; + " output.dx_Position.x = gl_Position.x;\n" + " output.dx_Position.y = -gl_Position.y;\n" + " output.dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n" + " output.dx_Position.w = gl_Position.w;\n"; } else { @@ -544,18 +707,18 @@ bool DynamicHLSL::generateShaderLinkHLSL(InfoLog &infoLog, int registers, const "\n" " VS_OUTPUT output;\n" " output.gl_Position = gl_Position;\n" - " output._dx_Position.x = gl_Position.x * dx_ViewAdjust.z + dx_ViewAdjust.x * gl_Position.w;\n" - " output._dx_Position.y = -(gl_Position.y * dx_ViewAdjust.w + dx_ViewAdjust.y * gl_Position.w);\n" - " output._dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n" - " output._dx_Position.w = gl_Position.w;\n"; + " output.dx_Position.x = gl_Position.x * dx_ViewAdjust.z + dx_ViewAdjust.x * gl_Position.w;\n" + " output.dx_Position.y = -(gl_Position.y * dx_ViewAdjust.w + dx_ViewAdjust.y * gl_Position.w);\n" + " output.dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n" + " output.dx_Position.w = gl_Position.w;\n"; } - if (vertexShader->mUsesPointSize && shaderModel >= 3) + if (usesPointSize && shaderModel >= 3) { vertexHLSL += " output.gl_PointSize = gl_PointSize;\n"; } - if (fragmentShader->mUsesFragCoord) + if (usesFragCoord) { vertexHLSL += " output.gl_FragCoord = gl_Position;\n"; } @@ -626,76 +789,51 @@ bool DynamicHLSL::generateShaderLinkHLSL(InfoLog &infoLog, int registers, const " return output;\n" "}\n"; - pixelHLSL += "struct PS_INPUT\n" - "{\n"; + const SemanticInfo &pixelSemantics = getSemanticInfo(registers, usesFragCoord, usesPointCoord, + usesPointSize, true); - pixelHLSL += varyingHLSL; - - if (fragmentShader->mUsesFragCoord) - { - pixelHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + Str(fragCoordSemanticIndex) + ";\n"; - } - - if (fragmentShader->mUsesPointCoord && shaderModel >= 3) - { - pixelHLSL += " float2 gl_PointCoord : " + pointCoordSemantic + Str(pointCoordSemanticIndex) + ";\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"; - } - } - - pixelHLSL += "};\n" - "\n" - "struct PS_OUTPUT\n" - "{\n"; + pixelHLSL += "struct PS_INPUT\n" + generateVaryingLinkHLSL(pixelSemantics, varyingHLSL) + "\n"; if (shaderVersion < 300) { for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++) { - pixelHLSL += " float4 gl_Color" + Str(renderTargetIndex) + " : " + targetSemantic + Str(renderTargetIndex) + ";\n"; + PixelShaderOuputVariable outputKeyVariable; + outputKeyVariable.type = GL_FLOAT_VEC4; + outputKeyVariable.name = "gl_Color" + Str(renderTargetIndex); + outputKeyVariable.source = broadcast ? "gl_Color[0]" : "gl_Color[" + Str(renderTargetIndex) + "]"; + outputKeyVariable.outputIndex = renderTargetIndex; + + outPixelShaderKey->push_back(outputKeyVariable); } - if (fragmentShader->mUsesFragDepth) - { - pixelHLSL += " float gl_Depth : " + depthSemantic + ";\n"; - } + *outUsesFragDepth = fragmentShader->mUsesFragDepth; } else { defineOutputVariables(fragmentShader, programOutputVars); - const std::vector &shaderOutputVars = fragmentShader->getOutputVariables(); + const std::vector &shaderOutputVars = fragmentShader->getOutputVariables(); for (auto locationIt = programOutputVars->begin(); locationIt != programOutputVars->end(); locationIt++) { const VariableLocation &outputLocation = locationIt->second; - const ShaderVariable &outputVariable = shaderOutputVars[outputLocation.index]; + const sh::ShaderVariable &outputVariable = shaderOutputVars[outputLocation.index]; + const std::string &variableName = "out_" + outputLocation.name; const std::string &elementString = (outputLocation.element == GL_INVALID_INDEX ? "" : Str(outputLocation.element)); - pixelHLSL += " " + gl_d3d::HLSLTypeString(outputVariable.type) + - " out_" + outputLocation.name + elementString + - " : " + targetSemantic + Str(locationIt->first) + ";\n"; + PixelShaderOuputVariable outputKeyVariable; + outputKeyVariable.type = outputVariable.type; + outputKeyVariable.name = variableName + elementString; + outputKeyVariable.source = variableName + ArrayString(outputLocation.element); + outputKeyVariable.outputIndex = locationIt->first; + + outPixelShaderKey->push_back(outputKeyVariable); } + + *outUsesFragDepth = false; } - pixelHLSL += "};\n" - "\n"; + pixelHLSL += PIXEL_OUTPUT_STUB_STRING + "\n"; if (fragmentShader->mUsesFrontFacing) { @@ -716,19 +854,19 @@ bool DynamicHLSL::generateShaderLinkHLSL(InfoLog &infoLog, int registers, const "{\n"; } - if (fragmentShader->mUsesFragCoord) + if (usesFragCoord) { pixelHLSL += " float rhw = 1.0 / input.gl_FragCoord.w;\n"; if (shaderModel >= 4) { - pixelHLSL += " gl_FragCoord.x = input.dx_VPos.x;\n" - " gl_FragCoord.y = input.dx_VPos.y;\n"; + pixelHLSL += " gl_FragCoord.x = input.dx_Position.x;\n" + " gl_FragCoord.y = input.dx_Position.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"; + pixelHLSL += " gl_FragCoord.x = input.dx_Position.x + 0.5;\n" + " gl_FragCoord.y = input.dx_Position.y + 0.5;\n"; } else { @@ -741,7 +879,7 @@ bool DynamicHLSL::generateShaderLinkHLSL(InfoLog &infoLog, int registers, const " gl_FragCoord.w = rhw;\n"; } - if (fragmentShader->mUsesPointCoord && shaderModel >= 3) + if (usesPointCoord && shaderModel >= 3) { pixelHLSL += " gl_PointCoord.x = input.gl_PointCoord.x;\n"; pixelHLSL += " gl_PointCoord.y = 1.0 - input.gl_PointCoord.y;\n"; @@ -807,49 +945,19 @@ bool DynamicHLSL::generateShaderLinkHLSL(InfoLog &infoLog, int registers, const pixelHLSL += "\n" " gl_main();\n" "\n" - " PS_OUTPUT output;\n"; - - if (shaderVersion < 300) - { - 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"; - } - } - else - { - for (auto locationIt = programOutputVars->begin(); locationIt != programOutputVars->end(); locationIt++) - { - const VariableLocation &outputLocation = locationIt->second; - const std::string &variableName = "out_" + outputLocation.name; - const std::string &outVariableName = variableName + (outputLocation.element == GL_INVALID_INDEX ? "" : Str(outputLocation.element)); - const std::string &staticVariableName = variableName + ArrayString(outputLocation.element); - - pixelHLSL += " output." + outVariableName + " = " + staticVariableName + ";\n"; - } - } - - pixelHLSL += "\n" - " return output;\n" + " return generateOutput();\n" "}\n"; return true; } -void DynamicHLSL::defineOutputVariables(FragmentShader *fragmentShader, std::map *programOutputVars) const +void DynamicHLSL::defineOutputVariables(rx::FragmentShaderD3D *fragmentShader, std::map *programOutputVars) const { - const std::vector &shaderOutputVars = fragmentShader->getOutputVariables(); + const std::vector &shaderOutputVars = fragmentShader->getOutputVariables(); for (unsigned int outputVariableIndex = 0; outputVariableIndex < shaderOutputVars.size(); outputVariableIndex++) { - const Attribute &outputVariable = shaderOutputVars[outputVariableIndex]; + const sh::Attribute &outputVariable = shaderOutputVars[outputVariableIndex]; const int baseLocation = outputVariable.location == -1 ? 0 : outputVariable.location; if (outputVariable.arraySize > 0) @@ -869,14 +977,14 @@ void DynamicHLSL::defineOutputVariables(FragmentShader *fragmentShader, std::map } } -std::string DynamicHLSL::generateGeometryShaderHLSL(int registers, FragmentShader *fragmentShader, VertexShader *vertexShader) const +std::string DynamicHLSL::generateGeometryShaderHLSL(int registers, rx::FragmentShaderD3D *fragmentShader, rx::VertexShaderD3D *vertexShader) const { // for now we only handle point sprite emulation ASSERT(vertexShader->mUsesPointSize && mRenderer->getMajorShaderModel() >= 4); return generatePointSpriteHLSL(registers, fragmentShader, vertexShader); } -std::string DynamicHLSL::generatePointSpriteHLSL(int registers, FragmentShader *fragmentShader, VertexShader *vertexShader) const +std::string DynamicHLSL::generatePointSpriteHLSL(int registers, rx::FragmentShaderD3D *fragmentShader, rx::VertexShaderD3D *vertexShader) const { ASSERT(registers >= 0); ASSERT(vertexShader->mUsesPointSize); @@ -884,60 +992,21 @@ std::string DynamicHLSL::generatePointSpriteHLSL(int registers, FragmentShader * std::string geomHLSL; - std::string varyingSemantic = "TEXCOORD"; + const SemanticInfo &inSemantics = getSemanticInfo(registers, fragmentShader->mUsesFragCoord, + false, true, false); + const SemanticInfo &outSemantics = getSemanticInfo(registers, fragmentShader->mUsesFragCoord, + fragmentShader->mUsesPointCoord, true, false); - std::string fragCoordSemantic; - std::string pointCoordSemantic; - - int reservedRegisterIndex = registers; - - if (fragmentShader->mUsesFragCoord) - { - fragCoordSemantic = varyingSemantic + Str(reservedRegisterIndex++); - } - - if (fragmentShader->mUsesPointCoord) - { - pointCoordSemantic = varyingSemantic + Str(reservedRegisterIndex++); - } + std::string varyingHLSL = generateVaryingHLSL(vertexShader); + std::string inLinkHLSL = generateVaryingLinkHLSL(inSemantics, varyingHLSL); + std::string outLinkHLSL = generateVaryingLinkHLSL(outSemantics, varyingHLSL); + // TODO(geofflang): use context's caps geomHLSL += "uniform float4 dx_ViewCoords : register(c1);\n" "\n" - "struct GS_INPUT\n" - "{\n"; - - std::string varyingHLSL = generateVaryingHLSL(vertexShader, varyingSemantic, NULL); - - geomHLSL += varyingHLSL; - - if (fragmentShader->mUsesFragCoord) - { - geomHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + ";\n"; - } - - geomHLSL += " float gl_PointSize : PSIZE;\n" - " float4 gl_Position : SV_Position;\n" - "};\n" + "struct GS_INPUT\n" + inLinkHLSL + "\n" + + "struct GS_OUTPUT\n" + outLinkHLSL + "\n" + "\n" - "struct GS_OUTPUT\n" - "{\n"; - - geomHLSL += varyingHLSL; - - 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" @@ -954,13 +1023,14 @@ std::string DynamicHLSL::generatePointSpriteHLSL(int registers, FragmentShader * " 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" + "static float minPointSize = " + Str(mRenderer->getRendererCaps().minAliasedPointSize) + ".0f;\n" + "static float maxPointSize = " + Str(mRenderer->getRendererCaps().maxAliasedPointSize) + ".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_Position = input[0].gl_Position;\n"; " output.gl_PointSize = input[0].gl_PointSize;\n"; for (int r = 0; r < registers; r++) @@ -975,13 +1045,13 @@ std::string DynamicHLSL::generatePointSpriteHLSL(int registers, FragmentShader * 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"; + " float4 dx_Position = input[0].dx_Position;\n" + " float2 viewportScale = float2(1.0f / dx_ViewCoords.x, 1.0f / dx_ViewCoords.y) * dx_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"; + " output.dx_Position = dx_Position + float4(pointSpriteCorners[" + Str(corner) + "] * viewportScale * gl_PointSize, 0.0f, 0.0f);\n"; if (fragmentShader->mUsesPointCoord) { @@ -1001,7 +1071,7 @@ std::string DynamicHLSL::generatePointSpriteHLSL(int registers, FragmentShader * // This method needs to match OutputHLSL::decorate std::string DynamicHLSL::decorateVariable(const std::string &name) { - if (name.compare(0, 3, "gl_") != 0 && name.compare(0, 3, "dx_") != 0) + if (name.compare(0, 3, "gl_") != 0) { return "_" + name; } @@ -1009,7 +1079,7 @@ std::string DynamicHLSL::decorateVariable(const std::string &name) return name; } -std::string DynamicHLSL::generateAttributeConversionHLSL(const VertexFormat &vertexFormat, const ShaderVariable &shaderAttrib) const +std::string DynamicHLSL::generateAttributeConversionHLSL(const VertexFormat &vertexFormat, const sh::ShaderVariable &shaderAttrib) const { std::string attribString = "input." + decorateVariable(shaderAttrib.name); @@ -1019,8 +1089,8 @@ std::string DynamicHLSL::generateAttributeConversionHLSL(const VertexFormat &ver return "transpose(" + attribString + ")"; } - GLenum shaderComponentType = UniformComponentType(shaderAttrib.type); - int shaderComponentCount = UniformComponentCount(shaderAttrib.type); + GLenum shaderComponentType = VariableComponentType(shaderAttrib.type); + int shaderComponentCount = VariableComponentCount(shaderAttrib.type); // Perform integer to float conversion (if necessary) bool requiresTypeConversion = (shaderComponentType == GL_FLOAT && vertexFormat.mType != GL_FLOAT); diff --git a/gfx/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.h b/gfx/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.h new file mode 100644 index 000000000000..6ee7b11cf28b --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.h @@ -0,0 +1,106 @@ +// +// Copyright (c) 2014 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. +// +// DynamicHLSL.h: Interface for link and run-time HLSL generation +// + +#ifndef LIBGLESV2_RENDERER_DYNAMIC_HLSL_H_ +#define LIBGLESV2_RENDERER_DYNAMIC_HLSL_H_ + +#include "common/angleutils.h" +#include "libGLESv2/constants.h" + +#include "angle_gl.h" + +#include +#include + +namespace rx +{ +class Renderer; +} + +namespace sh +{ +struct Attribute; +struct ShaderVariable; +} + +namespace gl +{ +class InfoLog; +struct VariableLocation; +struct LinkedVarying; +struct VertexAttribute; +struct VertexFormat; +struct PackedVarying; +} + +namespace rx +{ +class Renderer; +class ShaderD3D; +class VertexShaderD3D; +class FragmentShaderD3D; + +typedef const gl::PackedVarying *VaryingPacking[gl::IMPLEMENTATION_MAX_VARYING_VECTORS][4]; + +struct PixelShaderOuputVariable +{ + GLenum type; + std::string name; + std::string source; + size_t outputIndex; +}; + +class DynamicHLSL +{ + public: + explicit DynamicHLSL(rx::Renderer *const renderer); + + int packVaryings(gl::InfoLog &infoLog, VaryingPacking packing, rx::FragmentShaderD3D *fragmentShader, + rx::VertexShaderD3D *vertexShader, const std::vector& transformFeedbackVaryings); + std::string generateVertexShaderForInputLayout(const std::string &sourceShader, const gl::VertexFormat inputLayout[], + const sh::Attribute shaderAttributes[]) const; + std::string generatePixelShaderForOutputSignature(const std::string &sourceShader, const std::vector &outputVariables, + bool usesFragDepth, const std::vector &outputLayout) const; + bool generateShaderLinkHLSL(gl::InfoLog &infoLog, int registers, const VaryingPacking packing, + std::string& pixelHLSL, std::string& vertexHLSL, + rx::FragmentShaderD3D *fragmentShader, rx::VertexShaderD3D *vertexShader, + const std::vector& transformFeedbackVaryings, + std::vector *linkedVaryings, + std::map *programOutputVars, + std::vector *outPixelShaderKey, + bool *outUsesFragDepth) const; + + std::string generateGeometryShaderHLSL(int registers, rx::FragmentShaderD3D *fragmentShader, rx::VertexShaderD3D *vertexShader) const; + void getInputLayoutSignature(const gl::VertexFormat inputLayout[], GLenum signature[]) const; + + private: + DISALLOW_COPY_AND_ASSIGN(DynamicHLSL); + + rx::Renderer *const mRenderer; + + struct SemanticInfo; + + std::string getVaryingSemantic(bool pointSize) const; + SemanticInfo getSemanticInfo(int startRegisters, bool fragCoord, bool pointCoord, bool pointSize, + bool pixelShader) const; + std::string generateVaryingLinkHLSL(const SemanticInfo &info, const std::string &varyingHLSL) const; + std::string generateVaryingHLSL(rx::VertexShaderD3D *shader) const; + void storeUserLinkedVaryings(const rx::VertexShaderD3D *vertexShader, std::vector *linkedVaryings) const; + void storeBuiltinLinkedVaryings(const SemanticInfo &info, std::vector *linkedVaryings) const; + void defineOutputVariables(rx::FragmentShaderD3D *fragmentShader, std::map *programOutputVars) const; + std::string generatePointSpriteHLSL(int registers, rx::FragmentShaderD3D *fragmentShader, rx::VertexShaderD3D *vertexShader) const; + + // Prepend an underscore + static std::string decorateVariable(const std::string &name); + + std::string generateAttributeConversionHLSL(const gl::VertexFormat &vertexFormat, const sh::ShaderVariable &shaderAttrib) const; +}; + +} + +#endif // LIBGLESV2_RENDERER_DYNAMIC_HLSL_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp index d3ddd98eea31..df2e46c612ba 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp +++ b/gfx/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp @@ -1,4 +1,9 @@ -#include "precompiled.h" +// +// Copyright 2014 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/renderer/d3d/HLSLCompiler.h" #include "libGLESv2/Program.h" #include "libGLESv2/main.h" @@ -26,11 +31,11 @@ bool HLSLCompiler::initialize() TRACE_EVENT0("gpu", "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; + static const char *d3dCompilerNames[] = ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES; for (size_t i = 0; i < ArraySize(d3dCompilerNames); ++i) { - if (GetModuleHandleEx(0, d3dCompilerNames[i], &mD3DCompilerModule)) + if (GetModuleHandleExA(0, d3dCompilerNames[i], &mD3DCompilerModule)) { break; } @@ -105,14 +110,11 @@ ShaderBlob *HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const char *hlsl return gl::error(GL_OUT_OF_MEMORY, (ShaderBlob*)NULL); } - infoLog.append("Warning: D3D shader compilation failed with "); - infoLog.append(flagNames[i]); - infoLog.append(" flags."); + infoLog.append("Warning: D3D shader compilation failed with %s flags.", flagNames[i]); + if (i + 1 < attempts) { - infoLog.append(" Retrying with "); - infoLog.append(flagNames[i + 1]); - infoLog.append(".\n"); + infoLog.append(" Retrying with %s.\n", flagNames[i + 1]); } } } diff --git a/gfx/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.h b/gfx/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.h index ab685f1f44a3..0ce9e44be54d 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.h +++ b/gfx/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.h @@ -3,8 +3,6 @@ #include "common/angleutils.h" -#include - namespace gl { class InfoLog; diff --git a/gfx/angle/src/libGLESv2/renderer/d3d/ImageD3D.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/ImageD3D.cpp new file mode 100644 index 000000000000..0854b968da6a --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/d3d/ImageD3D.cpp @@ -0,0 +1,26 @@ +// +// 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/d3d/ImageD3D.h" + +namespace rx +{ + +ImageD3D::ImageD3D() +{ +} + +ImageD3D *ImageD3D::makeImageD3D(Image *img) +{ + ASSERT(HAS_DYNAMIC_TYPE(rx::ImageD3D*, img)); + return static_cast(img); +} + +} diff --git a/gfx/angle/src/libGLESv2/renderer/d3d/ImageD3D.h b/gfx/angle/src/libGLESv2/renderer/d3d/ImageD3D.h new file mode 100644 index 000000000000..242ce5af70c3 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/d3d/ImageD3D.h @@ -0,0 +1,54 @@ +// +// 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_IMAGED3D_H_ +#define LIBGLESV2_RENDERER_IMAGED3D_H_ + +#include "common/debug.h" +#include "libGLESv2/renderer/Image.h" + +namespace gl +{ +class Framebuffer; +} + +namespace rx +{ +class TextureStorageInterface2D; +class TextureStorageInterfaceCube; +class TextureStorageInterface3D; +class TextureStorageInterface2DArray; + +class ImageD3D : public Image +{ + public: + ImageD3D(); + virtual ~ImageD3D() {}; + + static ImageD3D *makeImageD3D(Image *img); + + virtual bool isDirty() const = 0; + + virtual void setManagedSurface(TextureStorageInterface2D *storage, int level) {}; + virtual void setManagedSurface(TextureStorageInterfaceCube *storage, int face, int level) {}; + virtual void setManagedSurface(TextureStorageInterface3D *storage, int level) {}; + virtual void setManagedSurface(TextureStorageInterface2DArray *storage, int layer, int level) {}; + virtual bool copyToStorage(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) = 0; + virtual bool copyToStorage(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) = 0; + virtual bool copyToStorage(TextureStorageInterface3D *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth) = 0; + virtual bool copyToStorage(TextureStorageInterface2DArray *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height) = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(ImageD3D); +}; + +} + +#endif // LIBGLESV2_RENDERER_IMAGED3D_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/IndexBuffer.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/IndexBuffer.cpp similarity index 98% rename from gfx/angle/src/libGLESv2/renderer/IndexBuffer.cpp rename to gfx/angle/src/libGLESv2/renderer/d3d/IndexBuffer.cpp index 7fe2a3abe7ca..8bf9f2a1a14c 100644 --- a/gfx/angle/src/libGLESv2/renderer/IndexBuffer.cpp +++ b/gfx/angle/src/libGLESv2/renderer/d3d/IndexBuffer.cpp @@ -1,4 +1,3 @@ -#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 @@ -8,7 +7,7 @@ // 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/d3d/IndexBuffer.h" #include "libGLESv2/renderer/Renderer.h" namespace rx diff --git a/gfx/angle/src/libGLESv2/renderer/IndexBuffer.h b/gfx/angle/src/libGLESv2/renderer/d3d/IndexBuffer.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/IndexBuffer.h rename to gfx/angle/src/libGLESv2/renderer/d3d/IndexBuffer.h diff --git a/gfx/angle/src/libGLESv2/renderer/IndexDataManager.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/IndexDataManager.cpp similarity index 59% rename from gfx/angle/src/libGLESv2/renderer/IndexDataManager.cpp rename to gfx/angle/src/libGLESv2/renderer/d3d/IndexDataManager.cpp index b8c7fa977c08..10725d4f1844 100644 --- a/gfx/angle/src/libGLESv2/renderer/IndexDataManager.cpp +++ b/gfx/angle/src/libGLESv2/renderer/d3d/IndexDataManager.cpp @@ -1,6 +1,5 @@ -#include "precompiled.h" // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2014 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,56 +7,22 @@ // 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/renderer/d3d/IndexDataManager.h" +#include "libGLESv2/renderer/d3d/BufferD3D.h" +#include "libGLESv2/renderer/d3d/IndexBuffer.h" +#include "libGLESv2/renderer/Renderer.h" #include "libGLESv2/Buffer.h" #include "libGLESv2/main.h" #include "libGLESv2/formatutils.h" -#include "libGLESv2/renderer/IndexBuffer.h" namespace rx { -IndexDataManager::IndexDataManager(Renderer *renderer) : mRenderer(renderer) +static void ConvertIndices(GLenum sourceType, GLenum destinationType, const void *input, GLsizei count, void *output) { - 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) + if (sourceType == GL_UNSIGNED_BYTE) { + ASSERT(destinationType == GL_UNSIGNED_SHORT); const GLubyte *in = static_cast(input); GLushort *out = static_cast(output); @@ -66,45 +31,62 @@ static void convertIndices(GLenum type, const void *input, GLsizei count, void * out[i] = in[i]; } } - else if (type == GL_UNSIGNED_INT) + else if (sourceType == GL_UNSIGNED_INT) { + ASSERT(destinationType == GL_UNSIGNED_INT); memcpy(output, input, count * sizeof(GLuint)); } - else if (type == GL_UNSIGNED_SHORT) + else if (sourceType == GL_UNSIGNED_SHORT) { - memcpy(output, input, count * sizeof(GLushort)); + if (destinationType == GL_UNSIGNED_SHORT) + { + memcpy(output, input, count * sizeof(GLushort)); + } + else if (destinationType == GL_UNSIGNED_INT) + { + const GLushort *in = static_cast(input); + GLuint *out = static_cast(output); + + for (GLsizei i = 0; i < count; i++) + { + out[i] = in[i]; + } + } + else UNREACHABLE(); } else UNREACHABLE(); } -template -static void computeRange(const IndexType *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex) +IndexDataManager::IndexDataManager(Renderer *renderer) + : mRenderer(renderer) { - *minIndex = indices[0]; - *maxIndex = indices[0]; - - for (GLsizei i = 0; i < count; i++) + mStreamingBufferShort = new StreamingIndexBufferInterface(mRenderer); + if (!mStreamingBufferShort->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT)) { - if (*minIndex > indices[i]) *minIndex = indices[i]; - if (*maxIndex < indices[i]) *maxIndex = indices[i]; + SafeDelete(mStreamingBufferShort); } + + mStreamingBufferInt = new StreamingIndexBufferInterface(mRenderer); + if (!mStreamingBufferInt->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT)) + { + SafeDelete(mStreamingBufferInt); + } + + if (!mStreamingBufferShort) + { + // Make sure both buffers are deleted. + SafeDelete(mStreamingBufferInt); + ERR("Failed to allocate the streaming index buffer(s)."); + } + + mCountingBuffer = NULL; } -static void computeRange(GLenum type, const GLvoid *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex) +IndexDataManager::~IndexDataManager() { - 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(); + SafeDelete(mStreamingBufferShort); + SafeDelete(mStreamingBufferInt); + SafeDelete(mCountingBuffer); } GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer *buffer, const GLvoid *indices, TranslatedIndexData *translated) @@ -114,11 +96,14 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer return GL_OUT_OF_MEMORY; } + const gl::Type &typeInfo = gl::GetTypeInfo(type); + GLenum destinationIndexType = (type == GL_UNSIGNED_INT) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT; + unsigned int offset = 0; bool alignedOffset = false; - BufferStorage *storage = NULL; + BufferD3D *storage = NULL; if (buffer != NULL) { @@ -128,7 +113,7 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer } offset = static_cast(reinterpret_cast(indices)); - storage = buffer->getStorage(); + storage = BufferD3D::makeBufferD3D(buffer->getImplementation()); switch (type) { @@ -138,59 +123,52 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer default: UNREACHABLE(); alignedOffset = false; } - unsigned int typeSize = gl::GetTypeBytes(type); - - // check for integer overflows - if (static_cast(count) > (std::numeric_limits::max() / typeSize) || - typeSize * static_cast(count) + offset < offset) - { - return GL_OUT_OF_MEMORY; - } - - if (typeSize * static_cast(count) + offset > storage->getSize()) - { - return GL_INVALID_OPERATION; - } + ASSERT(typeInfo.bytes * static_cast(count) + offset <= storage->getSize()); indices = static_cast(storage->getData()) + offset; } - StreamingIndexBufferInterface *streamingBuffer = (type == GL_UNSIGNED_INT) ? mStreamingBufferInt : mStreamingBufferShort; - - StaticIndexBufferInterface *staticBuffer = buffer ? buffer->getStaticIndexBuffer() : NULL; - IndexBufferInterface *indexBuffer = streamingBuffer; + StaticIndexBufferInterface *staticBuffer = storage ? storage->getStaticIndexBuffer() : NULL; + IndexBufferInterface *indexBuffer = NULL; bool directStorage = alignedOffset && storage && storage->supportsDirectBinding() && destinationIndexType == type; unsigned int streamOffset = 0; if (directStorage) { - indexBuffer = streamingBuffer; streamOffset = offset; - if (!buffer->getIndexRangeCache()->findRange(type, offset, count, &translated->minIndex, - &translated->maxIndex, NULL)) + if (!buffer->getIndexRangeCache()->findRange(type, offset, count, NULL, NULL)) { - computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex); - buffer->getIndexRangeCache()->addRange(type, offset, count, translated->minIndex, - translated->maxIndex, offset); + buffer->getIndexRangeCache()->addRange(type, offset, count, translated->indexRange, 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)) + if (!staticBuffer->getIndexRangeCache()->findRange(type, offset, count, NULL, &streamOffset)) { - streamOffset = (offset / gl::GetTypeBytes(type)) * gl::GetTypeBytes(destinationIndexType); - computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex); - staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->minIndex, - translated->maxIndex, streamOffset); + streamOffset = (offset / typeInfo.bytes) * gl::GetTypeInfo(destinationIndexType).bytes; + staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->indexRange, streamOffset); } } - else + + // Avoid D3D11's primitive restart index value + // see http://msdn.microsoft.com/en-us/library/windows/desktop/bb205124(v=vs.85).aspx + if (translated->indexRange.end == 0xFFFF && type == GL_UNSIGNED_SHORT && mRenderer->getMajorShaderModel() > 3) { + destinationIndexType = GL_UNSIGNED_INT; + directStorage = false; + indexBuffer = NULL; + } + + const gl::Type &destTypeInfo = gl::GetTypeInfo(destinationIndexType); + + if (!directStorage && !indexBuffer) + { + indexBuffer = (destinationIndexType == GL_UNSIGNED_INT) ? mStreamingBufferInt : mStreamingBufferShort; + unsigned int convertCount = count; if (staticBuffer) @@ -198,29 +176,24 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer if (staticBuffer->getBufferSize() == 0 && alignedOffset) { indexBuffer = staticBuffer; - convertCount = storage->getSize() / gl::GetTypeBytes(type); + convertCount = storage->getSize() / typeInfo.bytes; } else { - buffer->invalidateStaticData(); + storage->invalidateStaticData(); staticBuffer = NULL; } } - if (!indexBuffer) - { - ERR("No valid index buffer."); - return GL_INVALID_OPERATION; - } + ASSERT(indexBuffer); - unsigned int indexTypeSize = gl::GetTypeBytes(destinationIndexType); - if (convertCount > std::numeric_limits::max() / indexTypeSize) + if (convertCount > std::numeric_limits::max() / destTypeInfo.bytes) { - ERR("Reserving %u indicies of %u bytes each exceeds the maximum buffer size.", convertCount, indexTypeSize); + ERR("Reserving %u indicies of %u bytes each exceeds the maximum buffer size.", convertCount, destTypeInfo.bytes); return GL_OUT_OF_MEMORY; } - unsigned int bufferSizeRequired = convertCount * indexTypeSize; + unsigned int bufferSizeRequired = convertCount * destTypeInfo.bytes; if (!indexBuffer->reserveBufferSpace(bufferSizeRequired, type)) { ERR("Failed to reserve %u bytes in an index buffer.", bufferSizeRequired); @@ -234,7 +207,7 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer return GL_OUT_OF_MEMORY; } - convertIndices(type, staticBuffer ? storage->getData() : indices, convertCount, output); + ConvertIndices(type, destinationIndexType, staticBuffer ? storage->getData() : indices, convertCount, output); if (!indexBuffer->unmapBuffer()) { @@ -242,25 +215,23 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer return GL_OUT_OF_MEMORY; } - computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex); - if (staticBuffer) { - streamOffset = (offset / gl::GetTypeBytes(type)) * gl::GetTypeBytes(destinationIndexType); - staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->minIndex, - translated->maxIndex, streamOffset); + streamOffset = (offset / typeInfo.bytes) * destTypeInfo.bytes; + staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->indexRange, streamOffset); } } translated->storage = directStorage ? storage : NULL; - translated->indexBuffer = indexBuffer->getIndexBuffer(); + translated->indexBuffer = indexBuffer ? indexBuffer->getIndexBuffer() : NULL; translated->serial = directStorage ? storage->getSerial() : indexBuffer->getSerial(); - translated->startIndex = streamOffset / gl::GetTypeBytes(destinationIndexType); + translated->startIndex = streamOffset / destTypeInfo.bytes; translated->startOffset = streamOffset; + translated->indexType = destinationIndexType; - if (buffer) + if (storage) { - buffer->promoteStaticUsage(count * gl::GetTypeBytes(type)); + storage->promoteStaticUsage(count * typeInfo.bytes); } return GL_NO_ERROR; diff --git a/gfx/angle/src/libGLESv2/renderer/IndexDataManager.h b/gfx/angle/src/libGLESv2/renderer/d3d/IndexDataManager.h similarity index 87% rename from gfx/angle/src/libGLESv2/renderer/IndexDataManager.h rename to gfx/angle/src/libGLESv2/renderer/d3d/IndexDataManager.h index 0e77c81d1bba..2a896678386f 100644 --- a/gfx/angle/src/libGLESv2/renderer/IndexDataManager.h +++ b/gfx/angle/src/libGLESv2/renderer/d3d/IndexDataManager.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2014 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,6 +11,9 @@ #define LIBGLESV2_INDEXDATAMANAGER_H_ #include "common/angleutils.h" +#include "common/mathutil.h" + +#include namespace { @@ -27,18 +30,18 @@ namespace rx class StaticIndexBufferInterface; class StreamingIndexBufferInterface; class IndexBuffer; -class BufferStorage; +class BufferD3D; class Renderer; struct TranslatedIndexData { - unsigned int minIndex; - unsigned int maxIndex; + RangeUI indexRange; unsigned int startIndex; unsigned int startOffset; // In bytes IndexBuffer *indexBuffer; - BufferStorage *storage; + BufferD3D *storage; + GLenum indexType; unsigned int serial; }; diff --git a/gfx/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.cpp new file mode 100644 index 000000000000..4634a341bec8 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.cpp @@ -0,0 +1,77 @@ +// +// Copyright (c) 2014 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/renderer/d3d/MemoryBuffer.h" + +#include +#include + +namespace rx +{ + +MemoryBuffer::MemoryBuffer() + : mSize(0), + mData(NULL) +{ +} + +MemoryBuffer::~MemoryBuffer() +{ + free(mData); + mData = NULL; +} + +bool MemoryBuffer::resize(size_t size) +{ + if (size == 0) + { + clear(); + } + else + { + uint8_t *newMemory = reinterpret_cast(malloc(sizeof(uint8_t) * size)); + if (newMemory == NULL) + { + return false; + } + + if (mData) + { + // Copy the intersection of the old data and the new data + std::copy(mData, mData + std::min(mSize, size), newMemory); + free(mData); + } + + mData = newMemory; + mSize = size; + } + + return true; +} + +size_t MemoryBuffer::size() const +{ + return mSize; +} + +const uint8_t *MemoryBuffer::data() const +{ + return mData; +} + +uint8_t *MemoryBuffer::data() +{ + return mData; +} + +void MemoryBuffer::clear() +{ + free(mData); + mData = NULL; + mSize = 0; +} + +} diff --git a/gfx/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.h b/gfx/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.h new file mode 100644 index 000000000000..47b5772c3cdb --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.h @@ -0,0 +1,38 @@ +// +// Copyright (c) 2014 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_RENDERER_D3D_MEMORYBUFFER_H_ +#define LIBGLESV2_RENDERER_D3D_MEMORYBUFFER_H_ + +#include +#include + +namespace rx +{ + +class MemoryBuffer +{ + public: + MemoryBuffer(); + ~MemoryBuffer(); + + bool resize(size_t size); + size_t size() const; + void clear(); + + const uint8_t *data() const; + uint8_t *data(); + + bool empty() const { return (mSize == 0); } + + private: + size_t mSize; + uint8_t *mData; +}; + +} + +#endif // LIBGLESV2_RENDERER_D3D_MEMORYBUFFER_H diff --git a/gfx/angle/src/libGLESv2/renderer/d3d/ShaderD3D.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/ShaderD3D.cpp new file mode 100644 index 000000000000..a033f024cfaa --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/d3d/ShaderD3D.cpp @@ -0,0 +1,473 @@ +// +// Copyright (c) 2014 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. +// + +// ShaderD3D.cpp: Defines the rx::ShaderD3D class which implements rx::ShaderImpl. + +#include "libGLESv2/renderer/d3d/ShaderD3D.h" +#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/Shader.h" +#include "libGLESv2/main.h" + +#include "common/utilities.h" + +namespace rx +{ + +void *ShaderD3D::mFragmentCompiler = NULL; +void *ShaderD3D::mVertexCompiler = NULL; + +template +const std::vector *GetShaderVariables(const std::vector *variableList) +{ + // TODO: handle staticUse. for now, assume all returned variables are active. + ASSERT(variableList); + return variableList; +} + +ShaderD3D::ShaderD3D(rx::Renderer *renderer) + : ShaderImpl(), + mRenderer(renderer), + mShaderVersion(100) +{ + uncompile(); + initializeCompiler(); +} + +ShaderD3D::~ShaderD3D() +{ +} + +ShaderD3D *ShaderD3D::makeShaderD3D(ShaderImpl *impl) +{ + ASSERT(HAS_DYNAMIC_TYPE(ShaderD3D*, impl)); + return static_cast(impl); +} + +const ShaderD3D *ShaderD3D::makeShaderD3D(const ShaderImpl *impl) +{ + ASSERT(HAS_DYNAMIC_TYPE(const ShaderD3D*, impl)); + return static_cast(impl); +} + +// Perform a one-time initialization of the shader compiler (or after being destructed by releaseCompiler) +void ShaderD3D::initializeCompiler() +{ + if (!mFragmentCompiler) + { + int result = ShInitialize(); + + if (result) + { + ShShaderOutput hlslVersion = (mRenderer->getMajorShaderModel() >= 4) ? SH_HLSL11_OUTPUT : SH_HLSL9_OUTPUT; + + ShBuiltInResources resources; + ShInitBuiltInResources(&resources); + + // TODO(geofflang): use context's caps + const gl::Caps &caps = mRenderer->getRendererCaps(); + const gl::Extensions &extensions = mRenderer->getRendererExtensions(); + + resources.MaxVertexAttribs = caps.maxVertexAttributes; + resources.MaxVertexUniformVectors = caps.maxVertexUniformVectors; + resources.MaxVaryingVectors = caps.maxVaryingVectors; + resources.MaxVertexTextureImageUnits = caps.maxVertexTextureImageUnits; + resources.MaxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits; + resources.MaxTextureImageUnits = caps.maxTextureImageUnits; + resources.MaxFragmentUniformVectors = caps.maxFragmentUniformVectors; + resources.MaxDrawBuffers = caps.maxDrawBuffers; + resources.OES_standard_derivatives = extensions.standardDerivatives; + resources.EXT_draw_buffers = extensions.drawBuffers; + resources.EXT_shader_texture_lod = 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 + // GLSL ES 3.0 constants + resources.MaxVertexOutputVectors = caps.maxVertexOutputComponents / 4; + resources.MaxFragmentInputVectors = caps.maxFragmentInputComponents / 4; + resources.MinProgramTexelOffset = caps.minProgramTexelOffset; + resources.MaxProgramTexelOffset = caps.maxProgramTexelOffset; + + mFragmentCompiler = ShConstructCompiler(GL_FRAGMENT_SHADER, SH_GLES2_SPEC, hlslVersion, &resources); + mVertexCompiler = ShConstructCompiler(GL_VERTEX_SHADER, SH_GLES2_SPEC, hlslVersion, &resources); + } + } +} + +void ShaderD3D::releaseCompiler() +{ + ShDestruct(mFragmentCompiler); + ShDestruct(mVertexCompiler); + + mFragmentCompiler = NULL; + mVertexCompiler = NULL; + + ShFinalize(); +} + +void ShaderD3D::parseVaryings(void *compiler) +{ + if (!mHlsl.empty()) + { + const std::vector *activeVaryings = ShGetVaryings(compiler); + ASSERT(activeVaryings); + + for (size_t varyingIndex = 0; varyingIndex < activeVaryings->size(); varyingIndex++) + { + mVaryings.push_back(gl::PackedVarying((*activeVaryings)[varyingIndex])); + } + + mUsesMultipleRenderTargets = mHlsl.find("GL_USES_MRT") != std::string::npos; + mUsesFragColor = mHlsl.find("GL_USES_FRAG_COLOR") != std::string::npos; + mUsesFragData = mHlsl.find("GL_USES_FRAG_DATA") != std::string::npos; + mUsesFragCoord = mHlsl.find("GL_USES_FRAG_COORD") != std::string::npos; + mUsesFrontFacing = mHlsl.find("GL_USES_FRONT_FACING") != std::string::npos; + mUsesPointSize = mHlsl.find("GL_USES_POINT_SIZE") != std::string::npos; + mUsesPointCoord = mHlsl.find("GL_USES_POINT_COORD") != std::string::npos; + mUsesDepthRange = mHlsl.find("GL_USES_DEPTH_RANGE") != std::string::npos; + mUsesFragDepth = mHlsl.find("GL_USES_FRAG_DEPTH") != std::string::npos; + mUsesDiscardRewriting = mHlsl.find("ANGLE_USES_DISCARD_REWRITING") != std::string::npos; + mUsesNestedBreak = mHlsl.find("ANGLE_USES_NESTED_BREAK") != std::string::npos; + } +} + +void ShaderD3D::resetVaryingsRegisterAssignment() +{ + for (unsigned int varyingIndex = 0; varyingIndex < mVaryings.size(); varyingIndex++) + { + mVaryings[varyingIndex].resetRegisterAssignment(); + } +} + +// initialize/clean up previous state +void ShaderD3D::uncompile() +{ + // set by compileToHLSL + mHlsl.clear(); + mInfoLog.clear(); + + // set by parseVaryings + mVaryings.clear(); + + mUsesMultipleRenderTargets = false; + mUsesFragColor = false; + mUsesFragData = false; + mUsesFragCoord = false; + mUsesFrontFacing = false; + mUsesPointSize = false; + mUsesPointCoord = false; + mUsesDepthRange = false; + mUsesFragDepth = false; + mShaderVersion = 100; + mUsesDiscardRewriting = false; + mUsesNestedBreak = false; + + mActiveUniforms.clear(); + mActiveInterfaceBlocks.clear(); +} + +void ShaderD3D::compileToHLSL(void *compiler, const std::string &source) +{ + // ensure the compiler is loaded + initializeCompiler(); + + int compileOptions = SH_OBJECT_CODE; + std::string sourcePath; + if (gl::perfActive()) + { + sourcePath = getTempPath(); + writeFile(sourcePath.c_str(), source.c_str(), source.length()); + compileOptions |= SH_LINE_DIRECTIVES; + } + + int result; + if (sourcePath.empty()) + { + const char* sourceStrings[] = + { + source.c_str(), + }; + + result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions); + } + else + { + const char* sourceStrings[] = + { + sourcePath.c_str(), + source.c_str(), + }; + + result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions | SH_SOURCE_PATH); + } + + size_t shaderVersion = 100; + ShGetInfo(compiler, SH_SHADER_VERSION, &shaderVersion); + + mShaderVersion = static_cast(shaderVersion); + + if (shaderVersion == 300 && mRenderer->getCurrentClientVersion() < 3) + { + mInfoLog = "GLSL ES 3.00 is not supported by OpenGL ES 2.0 contexts"; + TRACE("\n%s", mInfoLog.c_str()); + } + else if (result) + { + size_t objCodeLen = 0; + ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &objCodeLen); + + char* outputHLSL = new char[objCodeLen]; + ShGetObjectCode(compiler, outputHLSL); + +#ifdef _DEBUG + std::ostringstream hlslStream; + hlslStream << "// GLSL\n"; + hlslStream << "//\n"; + + size_t curPos = 0; + while (curPos != std::string::npos) + { + size_t nextLine = source.find("\n", curPos); + size_t len = (nextLine == std::string::npos) ? std::string::npos : (nextLine - curPos + 1); + + hlslStream << "// " << source.substr(curPos, len); + + curPos = (nextLine == std::string::npos) ? std::string::npos : (nextLine + 1); + } + hlslStream << "\n\n"; + hlslStream << outputHLSL; + mHlsl = hlslStream.str(); +#else + mHlsl = outputHLSL; +#endif + + SafeDeleteArray(outputHLSL); + + mActiveUniforms = *GetShaderVariables(ShGetUniforms(compiler)); + + for (size_t uniformIndex = 0; uniformIndex < mActiveUniforms.size(); uniformIndex++) + { + const sh::Uniform &uniform = mActiveUniforms[uniformIndex]; + + unsigned int index = -1; + bool result = ShGetUniformRegister(compiler, uniform.name.c_str(), &index); + UNUSED_ASSERTION_VARIABLE(result); + ASSERT(result); + + mUniformRegisterMap[uniform.name] = index; + } + + mActiveInterfaceBlocks = *GetShaderVariables(ShGetInterfaceBlocks(compiler)); + + for (size_t blockIndex = 0; blockIndex < mActiveInterfaceBlocks.size(); blockIndex++) + { + const sh::InterfaceBlock &interfaceBlock = mActiveInterfaceBlocks[blockIndex]; + + unsigned int index = -1; + bool result = ShGetInterfaceBlockRegister(compiler, interfaceBlock.name.c_str(), &index); + UNUSED_ASSERTION_VARIABLE(result); + ASSERT(result); + + mInterfaceBlockRegisterMap[interfaceBlock.name] = index; + } + } + else + { + size_t infoLogLen = 0; + ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &infoLogLen); + + char* infoLog = new char[infoLogLen]; + ShGetInfoLog(compiler, infoLog); + mInfoLog = infoLog; + + TRACE("\n%s", mInfoLog.c_str()); + } +} + +rx::D3DWorkaroundType ShaderD3D::getD3DWorkarounds() const +{ + if (mUsesDiscardRewriting) + { + // ANGLE issue 486: + // Work-around a D3D9 compiler bug that presents itself when using conditional discard, by disabling optimization + return rx::ANGLE_D3D_WORKAROUND_SKIP_OPTIMIZATION; + } + + if (mUsesNestedBreak) + { + // ANGLE issue 603: + // Work-around a D3D9 compiler bug that presents itself when using break in a nested loop, by maximizing optimization + // We want to keep the use of ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION minimal to prevent hangs, so usesDiscard takes precedence + return rx::ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION; + } + + return rx::ANGLE_D3D_WORKAROUND_NONE; +} + +// true if varying x has a higher priority in packing than y +bool ShaderD3D::compareVarying(const gl::PackedVarying &x, const gl::PackedVarying &y) +{ + if (x.type == y.type) + { + return x.arraySize > y.arraySize; + } + + // Special case for handling structs: we sort these to the end of the list + if (x.type == GL_STRUCT_ANGLEX) + { + return false; + } + + if (y.type == GL_STRUCT_ANGLEX) + { + return true; + } + + return gl::VariableSortOrder(x.type) <= gl::VariableSortOrder(y.type); +} + +unsigned int ShaderD3D::getUniformRegister(const std::string &uniformName) const +{ + ASSERT(mUniformRegisterMap.count(uniformName) > 0); + return mUniformRegisterMap.find(uniformName)->second; +} + +unsigned int ShaderD3D::getInterfaceBlockRegister(const std::string &blockName) const +{ + ASSERT(mInterfaceBlockRegisterMap.count(blockName) > 0); + return mInterfaceBlockRegisterMap.find(blockName)->second; +} + +ShShaderOutput ShaderD3D::getCompilerOutputType(GLenum shader) +{ + void *compiler = NULL; + + switch (shader) + { + case GL_VERTEX_SHADER: compiler = mVertexCompiler; break; + case GL_FRAGMENT_SHADER: compiler = mFragmentCompiler; break; + default: UNREACHABLE(); return SH_HLSL9_OUTPUT; + } + + size_t outputType = 0; + ShGetInfo(compiler, SH_OUTPUT_TYPE, &outputType); + + return static_cast(outputType); +} + +VertexShaderD3D::VertexShaderD3D(rx::Renderer *renderer) : ShaderD3D(renderer) +{ +} + +VertexShaderD3D::~VertexShaderD3D() +{ +} + +VertexShaderD3D *VertexShaderD3D::makeVertexShaderD3D(ShaderImpl *impl) +{ + ASSERT(HAS_DYNAMIC_TYPE(VertexShaderD3D*, impl)); + return static_cast(impl); +} + +const VertexShaderD3D *VertexShaderD3D::makeVertexShaderD3D(const ShaderImpl *impl) +{ + ASSERT(HAS_DYNAMIC_TYPE(const VertexShaderD3D*, impl)); + return static_cast(impl); +} + +bool VertexShaderD3D::compile(const std::string &source) +{ + uncompile(); + + compileToHLSL(mVertexCompiler, source); + parseAttributes(); + parseVaryings(mVertexCompiler); + + return !getTranslatedSource().empty(); +} + +void VertexShaderD3D::uncompile() +{ + ShaderD3D::uncompile(); + + // set by ParseAttributes + mActiveAttributes.clear(); +} + +void VertexShaderD3D::parseAttributes() +{ + const std::string &hlsl = getTranslatedSource(); + if (!hlsl.empty()) + { + mActiveAttributes = *GetShaderVariables(ShGetAttributes(mVertexCompiler)); + } +} + +int VertexShaderD3D::getSemanticIndex(const std::string &attributeName) +{ + if (!attributeName.empty()) + { + int semanticIndex = 0; + for (unsigned int attributeIndex = 0; attributeIndex < mActiveAttributes.size(); attributeIndex++) + { + const sh::ShaderVariable &attribute = mActiveAttributes[attributeIndex]; + + if (attribute.name == attributeName) + { + return semanticIndex; + } + + semanticIndex += gl::VariableRegisterCount(attribute.type); + } + } + + return -1; +} + +FragmentShaderD3D::FragmentShaderD3D(rx::Renderer *renderer) : ShaderD3D(renderer) +{ +} + +FragmentShaderD3D::~FragmentShaderD3D() +{ +} + +FragmentShaderD3D *FragmentShaderD3D::makeFragmentShaderD3D(ShaderImpl *impl) +{ + ASSERT(HAS_DYNAMIC_TYPE(FragmentShaderD3D*, impl)); + return static_cast(impl); +} + +const FragmentShaderD3D *FragmentShaderD3D::makeFragmentShaderD3D(const ShaderImpl *impl) +{ + ASSERT(HAS_DYNAMIC_TYPE(const FragmentShaderD3D*, impl)); + return static_cast(impl); +} + +bool FragmentShaderD3D::compile(const std::string &source) +{ + uncompile(); + + compileToHLSL(mFragmentCompiler, source); + parseVaryings(mFragmentCompiler); + std::sort(mVaryings.begin(), mVaryings.end(), compareVarying); + + const std::string &hlsl = getTranslatedSource(); + if (!hlsl.empty()) + { + mActiveOutputVariables = *GetShaderVariables(ShGetOutputVariables(mFragmentCompiler)); + return true; + } + return false; +} + +void FragmentShaderD3D::uncompile() +{ + ShaderD3D::uncompile(); + + mActiveOutputVariables.clear(); +} + +} diff --git a/gfx/angle/src/libGLESv2/renderer/d3d/ShaderD3D.h b/gfx/angle/src/libGLESv2/renderer/d3d/ShaderD3D.h new file mode 100644 index 000000000000..e0b7a76e87c3 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/d3d/ShaderD3D.h @@ -0,0 +1,142 @@ +// +// Copyright (c) 2014 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. +// + +// ShaderD3D.h: Defines the rx::ShaderD3D class which implements rx::ShaderImpl. + +#ifndef LIBGLESV2_RENDERER_SHADERD3D_H_ +#define LIBGLESV2_RENDERER_SHADERD3D_H_ + +#include "libGLESv2/renderer/ShaderImpl.h" +#include "libGLESv2/Shader.h" + +#include + +namespace rx +{ +class Renderer; + +class ShaderD3D : public ShaderImpl +{ + friend class DynamicHLSL; + + public: + ShaderD3D(rx::Renderer *renderer); + virtual ~ShaderD3D(); + + static ShaderD3D *makeShaderD3D(ShaderImpl *impl); + static const ShaderD3D *makeShaderD3D(const ShaderImpl *impl); + + // ShaderImpl implementation + const std::string &getInfoLog() const { return mInfoLog; } + const std::string &getTranslatedSource() const { return mHlsl; } + + // D3D-specific methods + virtual void uncompile(); + void resetVaryingsRegisterAssignment(); + unsigned int getUniformRegister(const std::string &uniformName) const; + unsigned int getInterfaceBlockRegister(const std::string &blockName) const; + + rx::D3DWorkaroundType getD3DWorkarounds() const; + int getShaderVersion() const { return mShaderVersion; } + bool usesDepthRange() const { return mUsesDepthRange; } + bool usesPointSize() const { return mUsesPointSize; } + std::vector &getVaryings() { return mVaryings; } + const std::vector &getUniforms() const { return mActiveUniforms; } + const std::vector &getInterfaceBlocks() const { return mActiveInterfaceBlocks; } + + static void releaseCompiler(); + static ShShaderOutput getCompilerOutputType(GLenum shader); + + protected: + void compileToHLSL(void *compiler, const std::string &source); + void parseVaryings(void *compiler); + + static bool compareVarying(const gl::PackedVarying &x, const gl::PackedVarying &y); + + static void *mFragmentCompiler; + static void *mVertexCompiler; + + rx::Renderer *mRenderer; + + std::vector mVaryings; + + int mShaderVersion; + + bool mUsesMultipleRenderTargets; + bool mUsesFragColor; + bool mUsesFragData; + bool mUsesFragCoord; + bool mUsesFrontFacing; + bool mUsesPointSize; + bool mUsesPointCoord; + bool mUsesDepthRange; + bool mUsesFragDepth; + bool mUsesDiscardRewriting; + bool mUsesNestedBreak; + + private: + DISALLOW_COPY_AND_ASSIGN(ShaderD3D); + + void initializeCompiler(); + + std::string mHlsl; + std::string mInfoLog; + std::vector mActiveUniforms; + std::vector mActiveInterfaceBlocks; + std::map mUniformRegisterMap; + std::map mInterfaceBlockRegisterMap; +}; + +class VertexShaderD3D : public ShaderD3D +{ + friend class DynamicHLSL; + + public: + VertexShaderD3D(rx::Renderer *renderer); + virtual ~VertexShaderD3D(); + + static VertexShaderD3D *makeVertexShaderD3D(ShaderImpl *impl); + static const VertexShaderD3D *makeVertexShaderD3D(const ShaderImpl *impl); + + virtual bool compile(const std::string &source); + virtual void uncompile(); + + int getSemanticIndex(const std::string &attributeName); + virtual const std::vector &getActiveAttributes() const { return mActiveAttributes; } + + private: + DISALLOW_COPY_AND_ASSIGN(VertexShaderD3D); + + void parseAttributes(); + + std::vector mActiveAttributes; +}; + +class FragmentShaderD3D : public ShaderD3D +{ + friend class DynamicHLSL; + + public: + FragmentShaderD3D(rx::Renderer *renderer); + virtual ~FragmentShaderD3D(); + + static FragmentShaderD3D *makeFragmentShaderD3D(ShaderImpl *impl); + static const FragmentShaderD3D *makeFragmentShaderD3D(const ShaderImpl *impl); + + virtual bool compile(const std::string &source); + virtual void uncompile(); + + virtual const std::vector &getOutputVariables() const { return mActiveOutputVariables; } + + private: + DISALLOW_COPY_AND_ASSIGN(FragmentShaderD3D); + + std::vector mActiveOutputVariables; +}; + +} + +#endif // LIBGLESV2_RENDERER_SHADERD3D_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/d3d/TextureD3D.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/TextureD3D.cpp new file mode 100644 index 000000000000..5e29e4b45be7 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/d3d/TextureD3D.cpp @@ -0,0 +1,2220 @@ +// +// Copyright 2014 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. +// + +// TextureD3D.cpp: Implementations of the Texture interfaces shared betweeen the D3D backends. + +#include "libGLESv2/renderer/d3d/TextureD3D.h" +#include "libGLESv2/renderer/d3d/TextureStorage.h" +#include "libGLESv2/renderer/d3d/ImageD3D.h" +#include "libGLESv2/Buffer.h" +#include "libGLESv2/Framebuffer.h" +#include "libGLESv2/Texture.h" +#include "libGLESv2/main.h" +#include "libGLESv2/formatutils.h" +#include "libGLESv2/renderer/BufferImpl.h" +#include "libGLESv2/renderer/RenderTarget.h" +#include "libGLESv2/renderer/Renderer.h" + +#include "libEGL/Surface.h" + +#include "common/mathutil.h" +#include "common/utilities.h" + +namespace rx +{ + +bool IsRenderTargetUsage(GLenum usage) +{ + return (usage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE); +} + +TextureD3D::TextureD3D(Renderer *renderer) + : mRenderer(renderer), + mUsage(GL_NONE), + mDirtyImages(true), + mImmutable(false) +{ +} + +TextureD3D::~TextureD3D() +{ +} + +TextureD3D *TextureD3D::makeTextureD3D(TextureImpl *texture) +{ + ASSERT(HAS_DYNAMIC_TYPE(TextureD3D*, texture)); + return static_cast(texture); +} + +TextureStorageInterface *TextureD3D::getNativeTexture() +{ + // ensure the underlying texture is created + initializeStorage(false); + + TextureStorageInterface *storage = getBaseLevelStorage(); + if (storage) + { + updateStorage(); + } + + return storage; +} + +GLint TextureD3D::getBaseLevelWidth() const +{ + const Image *baseImage = getBaseLevelImage(); + return (baseImage ? baseImage->getWidth() : 0); +} + +GLint TextureD3D::getBaseLevelHeight() const +{ + const Image *baseImage = getBaseLevelImage(); + return (baseImage ? baseImage->getHeight() : 0); +} + +GLint TextureD3D::getBaseLevelDepth() const +{ + const Image *baseImage = getBaseLevelImage(); + return (baseImage ? baseImage->getDepth() : 0); +} + +// Note: "base level image" is loosely defined to be any image from the base level, +// where in the base of 2D array textures and cube maps there are several. Don't use +// the base level image for anything except querying texture format and size. +GLenum TextureD3D::getBaseLevelInternalFormat() const +{ + const Image *baseImage = getBaseLevelImage(); + return (baseImage ? baseImage->getInternalFormat() : GL_NONE); +} + +void TextureD3D::setImage(const gl::PixelUnpackState &unpack, GLenum type, const void *pixels, Image *image) +{ + // No-op + if (image->getWidth() == 0 || image->getHeight() == 0 || image->getDepth() == 0) + { + return; + } + + // We no longer need the "GLenum format" parameter to TexImage to determine what data format "pixels" contains. + // From our image internal format we know how many channels to expect, and "type" gives the format of pixel's components. + const void *pixelData = pixels; + + if (unpack.pixelBuffer.id() != 0) + { + // Do a CPU readback here, if we have an unpack buffer bound and the fast GPU path is not supported + gl::Buffer *pixelBuffer = unpack.pixelBuffer.get(); + ptrdiff_t offset = reinterpret_cast(pixels); + // TODO: setImage/subImage is the only place outside of renderer that asks for a buffers raw data. + // This functionality should be moved into renderer and the getData method of BufferImpl removed. + const void *bufferData = pixelBuffer->getImplementation()->getData(); + pixelData = static_cast(bufferData) + offset; + } + + if (pixelData != NULL) + { + image->loadData(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth(), unpack.alignment, type, pixelData); + mDirtyImages = true; + } +} + +bool TextureD3D::subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels, Image *image) +{ + const void *pixelData = pixels; + + // CPU readback & copy where direct GPU copy is not supported + if (unpack.pixelBuffer.id() != 0) + { + gl::Buffer *pixelBuffer = unpack.pixelBuffer.get(); + unsigned int offset = reinterpret_cast(pixels); + // TODO: setImage/subImage is the only place outside of renderer that asks for a buffers raw data. + // This functionality should be moved into renderer and the getData method of BufferImpl removed. + const void *bufferData = pixelBuffer->getImplementation()->getData(); + pixelData = static_cast(bufferData) + offset; + } + + if (pixelData != NULL) + { + image->loadData(xoffset, yoffset, zoffset, width, height, depth, unpack.alignment, type, pixelData); + mDirtyImages = true; + } + + return true; +} + +void TextureD3D::setCompressedImage(GLsizei imageSize, const void *pixels, Image *image) +{ + if (pixels != NULL) + { + image->loadCompressedData(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth(), pixels); + mDirtyImages = true; + } +} + +bool TextureD3D::subImageCompressed(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLsizei imageSize, const void *pixels, Image *image) +{ + if (pixels != NULL) + { + image->loadCompressedData(xoffset, yoffset, zoffset, width, height, depth, pixels); + mDirtyImages = true; + } + + return true; +} + +bool TextureD3D::isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum sizedInternalFormat) +{ + return unpack.pixelBuffer.id() != 0 && mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat); +} + +bool TextureD3D::fastUnpackPixels(const gl::PixelUnpackState &unpack, const void *pixels, const gl::Box &destArea, + GLenum sizedInternalFormat, GLenum type, RenderTarget *destRenderTarget) +{ + if (destArea.width <= 0 && destArea.height <= 0 && destArea.depth <= 0) + { + return true; + } + + // In order to perform the fast copy through the shader, we must have the right format, and be able + // to create a render target. + ASSERT(mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat)); + + unsigned int offset = reinterpret_cast(pixels); + + return mRenderer->fastCopyBufferToTexture(unpack, offset, destRenderTarget, sizedInternalFormat, type, destArea); +} + +GLint TextureD3D::creationLevels(GLsizei width, GLsizei height, GLsizei depth) const +{ + if ((gl::isPow2(width) && gl::isPow2(height) && gl::isPow2(depth)) || mRenderer->getRendererExtensions().textureNPOT) + { + // Maximum number of levels + return gl::log2(std::max(std::max(width, height), depth)) + 1; + } + else + { + // OpenGL ES 2.0 without GL_OES_texture_npot does not permit NPOT mipmaps. + return 1; + } +} + +int TextureD3D::mipLevels() const +{ + return gl::log2(std::max(std::max(getBaseLevelWidth(), getBaseLevelHeight()), getBaseLevelDepth())) + 1; +} + + +TextureD3D_2D::TextureD3D_2D(Renderer *renderer) + : TextureD3D(renderer), + mTexStorage(NULL) +{ + for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i) + { + mImageArray[i] = ImageD3D::makeImageD3D(renderer->createImage()); + } +} + +TextureD3D_2D::~TextureD3D_2D() +{ + // Delete the Images before the TextureStorage. + // Images might be relying on the TextureStorage for some of their data. + // If TextureStorage is deleted before the Images, then their data will be wastefully copied back from the GPU before we delete the Images. + for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i) + { + delete mImageArray[i]; + } + + SafeDelete(mTexStorage); +} + +Image *TextureD3D_2D::getImage(int level, int layer) const +{ + ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT(layer == 0); + return mImageArray[level]; +} + +GLsizei TextureD3D_2D::getLayerCount(int level) const +{ + ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + return 1; +} + +GLsizei TextureD3D_2D::getWidth(GLint level) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[level]->getWidth(); + else + return 0; +} + +GLsizei TextureD3D_2D::getHeight(GLint level) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[level]->getHeight(); + else + return 0; +} + +GLenum TextureD3D_2D::getInternalFormat(GLint level) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[level]->getInternalFormat(); + else + return GL_NONE; +} + +GLenum TextureD3D_2D::getActualFormat(GLint level) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[level]->getActualFormat(); + else + return GL_NONE; +} + +bool TextureD3D_2D::isDepth(GLint level) const +{ + return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; +} + +void TextureD3D_2D::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) +{ + ASSERT(target == GL_TEXTURE_2D && depth == 1); + + GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type); + + bool fastUnpacked = false; + + redefineImage(level, sizedInternalFormat, width, height); + + // Attempt a fast gpu copy of the pixel data to the surface + if (isFastUnpackable(unpack, sizedInternalFormat) && isLevelComplete(level)) + { + // Will try to create RT storage if it does not exist + RenderTarget *destRenderTarget = getRenderTarget(level, 0); + gl::Box destArea(0, 0, 0, getWidth(level), getHeight(level), 1); + + if (destRenderTarget && fastUnpackPixels(unpack, pixels, destArea, sizedInternalFormat, type, destRenderTarget)) + { + // Ensure we don't overwrite our newly initialized data + mImageArray[level]->markClean(); + + fastUnpacked = true; + } + } + + if (!fastUnpacked) + { + TextureD3D::setImage(unpack, type, pixels, mImageArray[level]); + } +} + +void TextureD3D_2D::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels) +{ + ASSERT(target == GL_TEXTURE_2D && depth == 1); + + // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly + redefineImage(level, format, width, height); + + TextureD3D::setCompressedImage(imageSize, pixels, mImageArray[level]); +} + +void TextureD3D_2D::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) +{ + ASSERT(target == GL_TEXTURE_2D && depth == 1 && zoffset == 0); + + bool fastUnpacked = false; + + if (isFastUnpackable(unpack, getInternalFormat(level)) && isLevelComplete(level)) + { + RenderTarget *renderTarget = getRenderTarget(level, 0); + gl::Box destArea(xoffset, yoffset, 0, width, height, 1); + + if (renderTarget && fastUnpackPixels(unpack, pixels, destArea, getInternalFormat(level), type, renderTarget)) + { + // Ensure we don't overwrite our newly initialized data + mImageArray[level]->markClean(); + + fastUnpacked = true; + } + } + + if (!fastUnpacked && TextureD3D::subImage(xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels, mImageArray[level])) + { + commitRect(level, xoffset, yoffset, width, height); + } +} + +void TextureD3D_2D::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels) +{ + ASSERT(target == GL_TEXTURE_2D && depth == 1 && zoffset == 0); + + if (TextureD3D::subImageCompressed(xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels, mImageArray[level])) + { + commitRect(level, xoffset, yoffset, width, height); + } +} + +void TextureD3D_2D::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) +{ + ASSERT(target == GL_TEXTURE_2D); + + GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, GL_UNSIGNED_BYTE); + redefineImage(level, sizedInternalFormat, width, height); + + if (!mImageArray[level]->isRenderableFormat()) + { + mImageArray[level]->copy(0, 0, 0, x, y, width, height, source); + mDirtyImages = true; + } + else + { + ensureRenderTarget(); + mImageArray[level]->markClean(); + + if (width != 0 && height != 0 && isValidLevel(level)) + { + gl::Rectangle sourceRect; + sourceRect.x = x; + sourceRect.width = width; + sourceRect.y = y; + sourceRect.height = height; + + mRenderer->copyImage(source, sourceRect, format, 0, 0, mTexStorage, level); + } + } +} + +void TextureD3D_2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) +{ + ASSERT(target == GL_TEXTURE_2D && zoffset == 0); + + // can only make our texture storage to a render target if level 0 is defined (with a width & height) and + // the current level we're copying to is defined (with appropriate format, width & height) + bool canCreateRenderTarget = isLevelComplete(level) && isLevelComplete(0); + + if (!mImageArray[level]->isRenderableFormat() || (!mTexStorage && !canCreateRenderTarget)) + { + mImageArray[level]->copy(xoffset, yoffset, 0, x, y, width, height, source); + mDirtyImages = true; + } + else + { + ensureRenderTarget(); + + if (isValidLevel(level)) + { + updateStorageLevel(level); + + gl::Rectangle sourceRect; + sourceRect.x = x; + sourceRect.width = width; + sourceRect.y = y; + sourceRect.height = height; + + mRenderer->copyImage(source, sourceRect, + gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format, + xoffset, yoffset, mTexStorage, level); + } + } +} + +void TextureD3D_2D::storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) +{ + ASSERT(target == GL_TEXTURE_2D && depth == 1); + + for (int level = 0; level < levels; level++) + { + GLsizei levelWidth = std::max(1, width >> level); + GLsizei levelHeight = std::max(1, height >> level); + mImageArray[level]->redefine(mRenderer, GL_TEXTURE_2D, internalformat, levelWidth, levelHeight, 1, true); + } + + for (int level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + mImageArray[level]->redefine(mRenderer, GL_TEXTURE_2D, GL_NONE, 0, 0, 0, true); + } + + mImmutable = true; + + setCompleteTexStorage(new TextureStorageInterface2D(mRenderer, internalformat, IsRenderTargetUsage(mUsage), width, height, levels)); +} + +void TextureD3D_2D::bindTexImage(egl::Surface *surface) +{ + GLenum internalformat = surface->getFormat(); + + mImageArray[0]->redefine(mRenderer, GL_TEXTURE_2D, internalformat, surface->getWidth(), surface->getHeight(), 1, true); + + if (mTexStorage) + { + SafeDelete(mTexStorage); + } + mTexStorage = new TextureStorageInterface2D(mRenderer, surface->getSwapChain()); + + mDirtyImages = true; +} + +void TextureD3D_2D::releaseTexImage() +{ + if (mTexStorage) + { + SafeDelete(mTexStorage); + } + + for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + mImageArray[i]->redefine(mRenderer, GL_TEXTURE_2D, GL_NONE, 0, 0, 0, true); + } +} + +void TextureD3D_2D::generateMipmaps() +{ + // Purge array levels 1 through q and reset them to represent the generated mipmap levels. + int levelCount = mipLevels(); + for (int level = 1; level < levelCount; level++) + { + redefineImage(level, getBaseLevelInternalFormat(), + std::max(getBaseLevelWidth() >> level, 1), + std::max(getBaseLevelHeight() >> level, 1)); + } + + if (mTexStorage && mTexStorage->isRenderTarget()) + { + for (int level = 1; level < levelCount; level++) + { + mTexStorage->generateMipmap(level); + + mImageArray[level]->markClean(); + } + } + else + { + for (int level = 1; level < levelCount; level++) + { + mRenderer->generateMipmap(mImageArray[level], mImageArray[level - 1]); + } + } +} + +unsigned int TextureD3D_2D::getRenderTargetSerial(GLint level, GLint layer) +{ + ASSERT(layer == 0); + return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(level) : 0); +} + +RenderTarget *TextureD3D_2D::getRenderTarget(GLint level, GLint layer) +{ + ASSERT(layer == 0); + + // ensure the underlying texture is created + if (!ensureRenderTarget()) + { + return NULL; + } + + updateStorageLevel(level); + return mTexStorage->getRenderTarget(level); +} + +bool TextureD3D_2D::isValidLevel(int level) const +{ + return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : false); +} + +bool TextureD3D_2D::isLevelComplete(int level) const +{ + if (isImmutable()) + { + return true; + } + + const Image *baseImage = getBaseLevelImage(); + + GLsizei width = baseImage->getWidth(); + GLsizei height = baseImage->getHeight(); + + if (width <= 0 || height <= 0) + { + return false; + } + + // The base image level is complete if the width and height are positive + if (level == 0) + { + return true; + } + + ASSERT(level >= 1 && level <= (int)ArraySize(mImageArray) && mImageArray[level] != NULL); + ImageD3D *image = mImageArray[level]; + + if (image->getInternalFormat() != baseImage->getInternalFormat()) + { + return false; + } + + if (image->getWidth() != std::max(1, width >> level)) + { + return false; + } + + if (image->getHeight() != std::max(1, height >> level)) + { + return false; + } + + return true; +} + +// Constructs a native texture resource from the texture images +void TextureD3D_2D::initializeStorage(bool renderTarget) +{ + // Only initialize the first time this texture is used as a render target or shader resource + if (mTexStorage) + { + return; + } + + // do not attempt to create storage for nonexistant data + if (!isLevelComplete(0)) + { + return; + } + + bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mUsage)); + + setCompleteTexStorage(createCompleteStorage(createRenderTarget)); + ASSERT(mTexStorage); + + // flush image data to the storage + updateStorage(); +} + +TextureStorageInterface2D *TextureD3D_2D::createCompleteStorage(bool renderTarget) const +{ + GLsizei width = getBaseLevelWidth(); + GLsizei height = getBaseLevelHeight(); + + ASSERT(width > 0 && height > 0); + + // use existing storage level count, when previously specified by TexStorage*D + GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, 1)); + + return new TextureStorageInterface2D(mRenderer, getBaseLevelInternalFormat(), renderTarget, width, height, levels); +} + +void TextureD3D_2D::setCompleteTexStorage(TextureStorageInterface2D *newCompleteTexStorage) +{ + SafeDelete(mTexStorage); + mTexStorage = newCompleteTexStorage; + + if (mTexStorage && mTexStorage->isManaged()) + { + for (int level = 0; level < mTexStorage->getLevelCount(); level++) + { + mImageArray[level]->setManagedSurface(mTexStorage, level); + } + } + + mDirtyImages = true; +} + +void TextureD3D_2D::updateStorage() +{ + ASSERT(mTexStorage != NULL); + GLint storageLevels = mTexStorage->getLevelCount(); + for (int level = 0; level < storageLevels; level++) + { + if (mImageArray[level]->isDirty() && isLevelComplete(level)) + { + updateStorageLevel(level); + } + } +} + +bool TextureD3D_2D::ensureRenderTarget() +{ + initializeStorage(true); + + if (getBaseLevelWidth() > 0 && getBaseLevelHeight() > 0) + { + ASSERT(mTexStorage); + if (!mTexStorage->isRenderTarget()) + { + TextureStorageInterface2D *newRenderTargetStorage = createCompleteStorage(true); + + if (!mRenderer->copyToRenderTarget(newRenderTargetStorage, mTexStorage)) + { + delete newRenderTargetStorage; + return gl::error(GL_OUT_OF_MEMORY, false); + } + + setCompleteTexStorage(newRenderTargetStorage); + } + } + + return (mTexStorage && mTexStorage->isRenderTarget()); +} + +TextureStorageInterface *TextureD3D_2D::getBaseLevelStorage() +{ + return mTexStorage; +} + +const ImageD3D *TextureD3D_2D::getBaseLevelImage() const +{ + return mImageArray[0]; +} + +void TextureD3D_2D::updateStorageLevel(int level) +{ + ASSERT(level <= (int)ArraySize(mImageArray) && mImageArray[level] != NULL); + ASSERT(isLevelComplete(level)); + + if (mImageArray[level]->isDirty()) + { + commitRect(level, 0, 0, getWidth(level), getHeight(level)); + } +} + +void TextureD3D_2D::redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height) +{ + // If there currently is a corresponding storage texture image, it has these parameters + const int storageWidth = std::max(1, getBaseLevelWidth() >> level); + const int storageHeight = std::max(1, getBaseLevelHeight() >> level); + const GLenum storageFormat = getBaseLevelInternalFormat(); + + mImageArray[level]->redefine(mRenderer, GL_TEXTURE_2D, internalformat, width, height, 1, false); + + if (mTexStorage) + { + const int storageLevels = mTexStorage->getLevelCount(); + + if ((level >= storageLevels && storageLevels != 0) || + width != storageWidth || + height != storageHeight || + internalformat != storageFormat) // Discard mismatched storage + { + for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + mImageArray[i]->markDirty(); + } + + SafeDelete(mTexStorage); + mDirtyImages = true; + } + } +} + +void TextureD3D_2D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +{ + if (isValidLevel(level)) + { + ImageD3D *image = mImageArray[level]; + if (image->copyToStorage(mTexStorage, level, xoffset, yoffset, width, height)) + { + image->markClean(); + } + } +} + + +TextureD3D_Cube::TextureD3D_Cube(Renderer *renderer) + : TextureD3D(renderer), + mTexStorage(NULL) +{ + for (int i = 0; i < 6; i++) + { + for (int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++j) + { + mImageArray[i][j] = ImageD3D::makeImageD3D(renderer->createImage()); + } + } +} + +TextureD3D_Cube::~TextureD3D_Cube() +{ + // Delete the Images before the TextureStorage. + // Images might be relying on the TextureStorage for some of their data. + // If TextureStorage is deleted before the Images, then their data will be wastefully copied back from the GPU before we delete the Images. + for (int i = 0; i < 6; i++) + { + for (int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++j) + { + SafeDelete(mImageArray[i][j]); + } + } + + SafeDelete(mTexStorage); +} + +Image *TextureD3D_Cube::getImage(int level, int layer) const +{ + ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT(layer < 6); + return mImageArray[layer][level]; +} + +GLsizei TextureD3D_Cube::getLayerCount(int level) const +{ + ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + return 6; +} + +GLenum TextureD3D_Cube::getInternalFormat(GLint level, GLint layer) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[layer][level]->getInternalFormat(); + else + return GL_NONE; +} + +bool TextureD3D_Cube::isDepth(GLint level, GLint layer) const +{ + return gl::GetInternalFormatInfo(getInternalFormat(level, layer)).depthBits > 0; +} + +void TextureD3D_Cube::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) +{ + ASSERT(depth == 1); + + int faceIndex = gl::TextureCubeMap::targetToLayerIndex(target); + GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type); + + redefineImage(faceIndex, level, sizedInternalFormat, width, height); + + TextureD3D::setImage(unpack, type, pixels, mImageArray[faceIndex][level]); +} + +void TextureD3D_Cube::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels) +{ + ASSERT(depth == 1); + + // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly + int faceIndex = gl::TextureCubeMap::targetToLayerIndex(target); + + redefineImage(faceIndex, level, format, width, height); + + TextureD3D::setCompressedImage(imageSize, pixels, mImageArray[faceIndex][level]); +} + +void TextureD3D_Cube::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) +{ + ASSERT(depth == 1 && zoffset == 0); + + int faceIndex = gl::TextureCubeMap::targetToLayerIndex(target); + + if (TextureD3D::subImage(xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels, mImageArray[faceIndex][level])) + { + commitRect(faceIndex, level, xoffset, yoffset, width, height); + } +} + +void TextureD3D_Cube::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels) +{ + ASSERT(depth == 1 && zoffset == 0); + + int faceIndex = gl::TextureCubeMap::targetToLayerIndex(target); + + if (TextureD3D::subImageCompressed(xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels, mImageArray[faceIndex][level])) + { + commitRect(faceIndex, level, xoffset, yoffset, width, height); + } +} + +void TextureD3D_Cube::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) +{ + int faceIndex = gl::TextureCubeMap::targetToLayerIndex(target); + GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, GL_UNSIGNED_BYTE); + + redefineImage(faceIndex, level, sizedInternalFormat, width, height); + + if (!mImageArray[faceIndex][level]->isRenderableFormat()) + { + mImageArray[faceIndex][level]->copy(0, 0, 0, x, y, width, height, source); + mDirtyImages = true; + } + else + { + ensureRenderTarget(); + mImageArray[faceIndex][level]->markClean(); + + ASSERT(width == height); + + if (width > 0 && isValidFaceLevel(faceIndex, level)) + { + gl::Rectangle sourceRect; + sourceRect.x = x; + sourceRect.width = width; + sourceRect.y = y; + sourceRect.height = height; + + mRenderer->copyImage(source, sourceRect, format, 0, 0, mTexStorage, target, level); + } + } +} + +void TextureD3D_Cube::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) +{ + int faceIndex = gl::TextureCubeMap::targetToLayerIndex(target); + + // We can only make our texture storage to a render target if the level we're copying *to* is complete + // and the base level is cube-complete. The base level must be cube complete (common case) because we cannot + // rely on the "getBaseLevel*" methods reliably otherwise. + bool canCreateRenderTarget = isFaceLevelComplete(faceIndex, level) && isCubeComplete(); + + if (!mImageArray[faceIndex][level]->isRenderableFormat() || (!mTexStorage && !canCreateRenderTarget)) + { + mImageArray[faceIndex][level]->copy(0, 0, 0, x, y, width, height, source); + mDirtyImages = true; + } + else + { + ensureRenderTarget(); + + if (isValidFaceLevel(faceIndex, level)) + { + updateStorageFaceLevel(faceIndex, level); + + gl::Rectangle sourceRect; + sourceRect.x = x; + sourceRect.width = width; + sourceRect.y = y; + sourceRect.height = height; + + mRenderer->copyImage(source, sourceRect, gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format, + xoffset, yoffset, mTexStorage, target, level); + } + } +} + +void TextureD3D_Cube::storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) +{ + ASSERT(width == height); + ASSERT(depth == 1); + + for (int level = 0; level < levels; level++) + { + GLsizei mipSize = std::max(1, width >> level); + for (int faceIndex = 0; faceIndex < 6; faceIndex++) + { + mImageArray[faceIndex][level]->redefine(mRenderer, GL_TEXTURE_CUBE_MAP, internalformat, mipSize, mipSize, 1, true); + } + } + + for (int level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + for (int faceIndex = 0; faceIndex < 6; faceIndex++) + { + mImageArray[faceIndex][level]->redefine(mRenderer, GL_TEXTURE_CUBE_MAP, GL_NONE, 0, 0, 0, true); + } + } + + mImmutable = true; + + setCompleteTexStorage(new TextureStorageInterfaceCube(mRenderer, internalformat, IsRenderTargetUsage(mUsage), width, levels)); +} + +// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81. +bool TextureD3D_Cube::isCubeComplete() const +{ + int baseWidth = getBaseLevelWidth(); + int baseHeight = getBaseLevelHeight(); + GLenum baseFormat = getBaseLevelInternalFormat(); + + if (baseWidth <= 0 || baseWidth != baseHeight) + { + return false; + } + + for (int faceIndex = 1; faceIndex < 6; faceIndex++) + { + const ImageD3D &faceBaseImage = *mImageArray[faceIndex][0]; + + if (faceBaseImage.getWidth() != baseWidth || + faceBaseImage.getHeight() != baseHeight || + faceBaseImage.getInternalFormat() != baseFormat ) + { + return false; + } + } + + return true; +} + +void TextureD3D_Cube::bindTexImage(egl::Surface *surface) +{ + UNREACHABLE(); +} + +void TextureD3D_Cube::releaseTexImage() +{ + UNREACHABLE(); +} + + +void TextureD3D_Cube::generateMipmaps() +{ + // Purge array levels 1 through q and reset them to represent the generated mipmap levels. + int levelCount = mipLevels(); + for (int faceIndex = 0; faceIndex < 6; faceIndex++) + { + for (int level = 1; level < levelCount; level++) + { + int faceLevelSize = (std::max(mImageArray[faceIndex][0]->getWidth() >> level, 1)); + redefineImage(faceIndex, level, mImageArray[faceIndex][0]->getInternalFormat(), faceLevelSize, faceLevelSize); + } + } + + if (mTexStorage && mTexStorage->isRenderTarget()) + { + for (int faceIndex = 0; faceIndex < 6; faceIndex++) + { + for (int level = 1; level < levelCount; level++) + { + mTexStorage->generateMipmap(faceIndex, level); + + mImageArray[faceIndex][level]->markClean(); + } + } + } + else + { + for (int faceIndex = 0; faceIndex < 6; faceIndex++) + { + for (int level = 1; level < levelCount; level++) + { + mRenderer->generateMipmap(mImageArray[faceIndex][level], mImageArray[faceIndex][level - 1]); + } + } + } +} + +unsigned int TextureD3D_Cube::getRenderTargetSerial(GLint level, GLint layer) +{ + GLenum target = gl::TextureCubeMap::layerIndexToTarget(layer); + return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(target, level) : 0); +} + +RenderTarget *TextureD3D_Cube::getRenderTarget(GLint level, GLint layer) +{ + GLenum target = gl::TextureCubeMap::layerIndexToTarget(layer); + ASSERT(gl::IsCubemapTextureTarget(target)); + + // ensure the underlying texture is created + if (!ensureRenderTarget()) + { + return NULL; + } + + updateStorageFaceLevel(layer, level); + return mTexStorage->getRenderTarget(target, level); +} + +void TextureD3D_Cube::initializeStorage(bool renderTarget) +{ + // Only initialize the first time this texture is used as a render target or shader resource + if (mTexStorage) + { + return; + } + + // do not attempt to create storage for nonexistant data + if (!isFaceLevelComplete(0, 0)) + { + return; + } + + bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mUsage)); + + setCompleteTexStorage(createCompleteStorage(createRenderTarget)); + ASSERT(mTexStorage); + + // flush image data to the storage + updateStorage(); +} + +TextureStorageInterfaceCube *TextureD3D_Cube::createCompleteStorage(bool renderTarget) const +{ + GLsizei size = getBaseLevelWidth(); + + ASSERT(size > 0); + + // use existing storage level count, when previously specified by TexStorage*D + GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(size, size, 1)); + + return new TextureStorageInterfaceCube(mRenderer, getBaseLevelInternalFormat(), renderTarget, size, levels); +} + +void TextureD3D_Cube::setCompleteTexStorage(TextureStorageInterfaceCube *newCompleteTexStorage) +{ + SafeDelete(mTexStorage); + mTexStorage = newCompleteTexStorage; + + if (mTexStorage && mTexStorage->isManaged()) + { + for (int faceIndex = 0; faceIndex < 6; faceIndex++) + { + for (int level = 0; level < mTexStorage->getLevelCount(); level++) + { + mImageArray[faceIndex][level]->setManagedSurface(mTexStorage, faceIndex, level); + } + } + } + + mDirtyImages = true; +} + +void TextureD3D_Cube::updateStorage() +{ + ASSERT(mTexStorage != NULL); + GLint storageLevels = mTexStorage->getLevelCount(); + for (int face = 0; face < 6; face++) + { + for (int level = 0; level < storageLevels; level++) + { + if (mImageArray[face][level]->isDirty() && isFaceLevelComplete(face, level)) + { + updateStorageFaceLevel(face, level); + } + } + } +} + +bool TextureD3D_Cube::ensureRenderTarget() +{ + initializeStorage(true); + + if (getBaseLevelWidth() > 0) + { + ASSERT(mTexStorage); + if (!mTexStorage->isRenderTarget()) + { + TextureStorageInterfaceCube *newRenderTargetStorage = createCompleteStorage(true); + + if (!mRenderer->copyToRenderTarget(newRenderTargetStorage, mTexStorage)) + { + delete newRenderTargetStorage; + return gl::error(GL_OUT_OF_MEMORY, false); + } + + setCompleteTexStorage(newRenderTargetStorage); + } + } + + return (mTexStorage && mTexStorage->isRenderTarget()); +} + +TextureStorageInterface *TextureD3D_Cube::getBaseLevelStorage() +{ + return mTexStorage; +} + +const ImageD3D *TextureD3D_Cube::getBaseLevelImage() const +{ + // Note: if we are not cube-complete, there is no single base level image that can describe all + // cube faces, so this method is only well-defined for a cube-complete base level. + return mImageArray[0][0]; +} + +bool TextureD3D_Cube::isValidFaceLevel(int faceIndex, int level) const +{ + return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : 0); +} + +bool TextureD3D_Cube::isFaceLevelComplete(int faceIndex, int level) const +{ + ASSERT(level >= 0 && faceIndex < 6 && level < (int)ArraySize(mImageArray[faceIndex]) && mImageArray[faceIndex][level] != NULL); + + if (isImmutable()) + { + return true; + } + + int baseSize = getBaseLevelWidth(); + + if (baseSize <= 0) + { + return false; + } + + // "isCubeComplete" checks for base level completeness and we must call that + // to determine if any face at level 0 is complete. We omit that check here + // to avoid re-checking cube-completeness for every face at level 0. + if (level == 0) + { + return true; + } + + // Check that non-zero levels are consistent with the base level. + const ImageD3D *faceLevelImage = mImageArray[faceIndex][level]; + + if (faceLevelImage->getInternalFormat() != getBaseLevelInternalFormat()) + { + return false; + } + + if (faceLevelImage->getWidth() != std::max(1, baseSize >> level)) + { + return false; + } + + return true; +} + +void TextureD3D_Cube::updateStorageFaceLevel(int faceIndex, int level) +{ + ASSERT(level >= 0 && faceIndex < 6 && level < (int)ArraySize(mImageArray[faceIndex]) && mImageArray[faceIndex][level] != NULL); + ImageD3D *image = mImageArray[faceIndex][level]; + + if (image->isDirty()) + { + commitRect(faceIndex, level, 0, 0, image->getWidth(), image->getHeight()); + } +} + +void TextureD3D_Cube::redefineImage(int faceIndex, GLint level, GLenum internalformat, GLsizei width, GLsizei height) +{ + // If there currently is a corresponding storage texture image, it has these parameters + const int storageWidth = std::max(1, getBaseLevelWidth() >> level); + const int storageHeight = std::max(1, getBaseLevelHeight() >> level); + const GLenum storageFormat = getBaseLevelInternalFormat(); + + mImageArray[faceIndex][level]->redefine(mRenderer, GL_TEXTURE_CUBE_MAP, internalformat, width, height, 1, false); + + if (mTexStorage) + { + const int storageLevels = mTexStorage->getLevelCount(); + + if ((level >= storageLevels && storageLevels != 0) || + width != storageWidth || + height != storageHeight || + internalformat != storageFormat) // Discard mismatched storage + { + for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + for (int faceIndex = 0; faceIndex < 6; faceIndex++) + { + mImageArray[faceIndex][level]->markDirty(); + } + } + + SafeDelete(mTexStorage); + + mDirtyImages = true; + } + } +} + +void TextureD3D_Cube::commitRect(int faceIndex, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +{ + if (isValidFaceLevel(faceIndex, level)) + { + ImageD3D *image = mImageArray[faceIndex][level]; + if (image->copyToStorage(mTexStorage, faceIndex, level, xoffset, yoffset, width, height)) + image->markClean(); + } +} + + +TextureD3D_3D::TextureD3D_3D(Renderer *renderer) + : TextureD3D(renderer), + mTexStorage(NULL) +{ + for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i) + { + mImageArray[i] = ImageD3D::makeImageD3D(renderer->createImage()); + } +} + +TextureD3D_3D::~TextureD3D_3D() +{ + // Delete the Images before the TextureStorage. + // Images might be relying on the TextureStorage for some of their data. + // If TextureStorage is deleted before the Images, then their data will be wastefully copied back from the GPU before we delete the Images. + for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i) + { + delete mImageArray[i]; + } + + SafeDelete(mTexStorage); +} + +Image *TextureD3D_3D::getImage(int level, int layer) const +{ + ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT(layer == 0); + return mImageArray[level]; +} + +GLsizei TextureD3D_3D::getLayerCount(int level) const +{ + ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + return 1; +} + +GLsizei TextureD3D_3D::getWidth(GLint level) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[level]->getWidth(); + else + return 0; +} + +GLsizei TextureD3D_3D::getHeight(GLint level) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[level]->getHeight(); + else + return 0; +} + +GLsizei TextureD3D_3D::getDepth(GLint level) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[level]->getDepth(); + else + return 0; +} + +GLenum TextureD3D_3D::getInternalFormat(GLint level) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[level]->getInternalFormat(); + else + return GL_NONE; +} + +bool TextureD3D_3D::isDepth(GLint level) const +{ + return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; +} + +void TextureD3D_3D::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) +{ + ASSERT(target == GL_TEXTURE_3D); + GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type); + + redefineImage(level, sizedInternalFormat, width, height, depth); + + bool fastUnpacked = false; + + // Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer + if (isFastUnpackable(unpack, sizedInternalFormat)) + { + // Will try to create RT storage if it does not exist + RenderTarget *destRenderTarget = getRenderTarget(level); + gl::Box destArea(0, 0, 0, getWidth(level), getHeight(level), getDepth(level)); + + if (destRenderTarget && fastUnpackPixels(unpack, pixels, destArea, sizedInternalFormat, type, destRenderTarget)) + { + // Ensure we don't overwrite our newly initialized data + mImageArray[level]->markClean(); + + fastUnpacked = true; + } + } + + if (!fastUnpacked) + { + TextureD3D::setImage(unpack, type, pixels, mImageArray[level]); + } +} + +void TextureD3D_3D::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels) +{ + ASSERT(target == GL_TEXTURE_3D); + + // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly + redefineImage(level, format, width, height, depth); + + TextureD3D::setCompressedImage(imageSize, pixels, mImageArray[level]); +} + +void TextureD3D_3D::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) +{ + ASSERT(target == GL_TEXTURE_3D); + + bool fastUnpacked = false; + + // Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer + if (isFastUnpackable(unpack, getInternalFormat(level))) + { + RenderTarget *destRenderTarget = getRenderTarget(level); + gl::Box destArea(xoffset, yoffset, zoffset, width, height, depth); + + if (destRenderTarget && fastUnpackPixels(unpack, pixels, destArea, getInternalFormat(level), type, destRenderTarget)) + { + // Ensure we don't overwrite our newly initialized data + mImageArray[level]->markClean(); + + fastUnpacked = true; + } + } + + if (!fastUnpacked && TextureD3D::subImage(xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels, mImageArray[level])) + { + commitRect(level, xoffset, yoffset, zoffset, width, height, depth); + } +} + +void TextureD3D_3D::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels) +{ + ASSERT(target == GL_TEXTURE_3D); + + if (TextureD3D::subImageCompressed(xoffset, yoffset, zoffset, width, height, depth, format, imageSize, pixels, mImageArray[level])) + { + commitRect(level, xoffset, yoffset, zoffset, width, height, depth); + } +} + +void TextureD3D_3D::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) +{ + UNIMPLEMENTED(); +} + +void TextureD3D_3D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) +{ + ASSERT(target == GL_TEXTURE_3D); + + // can only make our texture storage to a render target if level 0 is defined (with a width & height) and + // the current level we're copying to is defined (with appropriate format, width & height) + bool canCreateRenderTarget = isLevelComplete(level) && isLevelComplete(0); + + if (!mImageArray[level]->isRenderableFormat() || (!mTexStorage && !canCreateRenderTarget)) + { + mImageArray[level]->copy(xoffset, yoffset, zoffset, x, y, width, height, source); + mDirtyImages = true; + } + else + { + ensureRenderTarget(); + + if (isValidLevel(level)) + { + updateStorageLevel(level); + + gl::Rectangle sourceRect; + sourceRect.x = x; + sourceRect.width = width; + sourceRect.y = y; + sourceRect.height = height; + + mRenderer->copyImage(source, sourceRect, + gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format, + xoffset, yoffset, zoffset, mTexStorage, level); + } + } +} + +void TextureD3D_3D::storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) +{ + ASSERT(target == GL_TEXTURE_3D); + + for (int level = 0; level < levels; level++) + { + GLsizei levelWidth = std::max(1, width >> level); + GLsizei levelHeight = std::max(1, height >> level); + GLsizei levelDepth = std::max(1, depth >> level); + mImageArray[level]->redefine(mRenderer, GL_TEXTURE_3D, internalformat, levelWidth, levelHeight, levelDepth, true); + } + + for (int level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + mImageArray[level]->redefine(mRenderer, GL_TEXTURE_3D, GL_NONE, 0, 0, 0, true); + } + + mImmutable = true; + + setCompleteTexStorage(new TextureStorageInterface3D(mRenderer, internalformat, IsRenderTargetUsage(mUsage), width, height, depth, levels)); +} + +void TextureD3D_3D::bindTexImage(egl::Surface *surface) +{ + UNREACHABLE(); +} + +void TextureD3D_3D::releaseTexImage() +{ + UNREACHABLE(); +} + + +void TextureD3D_3D::generateMipmaps() +{ + // Purge array levels 1 through q and reset them to represent the generated mipmap levels. + int levelCount = mipLevels(); + for (int level = 1; level < levelCount; level++) + { + redefineImage(level, getBaseLevelInternalFormat(), + std::max(getBaseLevelWidth() >> level, 1), + std::max(getBaseLevelHeight() >> level, 1), + std::max(getBaseLevelDepth() >> level, 1)); + } + + if (mTexStorage && mTexStorage->isRenderTarget()) + { + for (int level = 1; level < levelCount; level++) + { + mTexStorage->generateMipmap(level); + + mImageArray[level]->markClean(); + } + } + else + { + for (int level = 1; level < levelCount; level++) + { + mRenderer->generateMipmap(mImageArray[level], mImageArray[level - 1]); + } + } +} + +unsigned int TextureD3D_3D::getRenderTargetSerial(GLint level, GLint layer) +{ + return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(level, layer) : 0); +} + +RenderTarget *TextureD3D_3D::getRenderTarget(GLint level) +{ + // ensure the underlying texture is created + if (!ensureRenderTarget()) + { + return NULL; + } + + updateStorageLevel(level); + + // ensure this is NOT a depth texture + if (isDepth(level)) + { + return NULL; + } + + return mTexStorage->getRenderTarget(level); +} + +RenderTarget *TextureD3D_3D::getRenderTarget(GLint level, GLint layer) +{ + // ensure the underlying texture is created + if (!ensureRenderTarget()) + { + return NULL; + } + + updateStorage(); + + return mTexStorage->getRenderTarget(level, layer); +} + +void TextureD3D_3D::initializeStorage(bool renderTarget) +{ + // Only initialize the first time this texture is used as a render target or shader resource + if (mTexStorage) + { + return; + } + + // do not attempt to create storage for nonexistant data + if (!isLevelComplete(0)) + { + return; + } + + bool createRenderTarget = (renderTarget || mUsage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE); + + setCompleteTexStorage(createCompleteStorage(createRenderTarget)); + ASSERT(mTexStorage); + + // flush image data to the storage + updateStorage(); +} + +TextureStorageInterface3D *TextureD3D_3D::createCompleteStorage(bool renderTarget) const +{ + GLsizei width = getBaseLevelWidth(); + GLsizei height = getBaseLevelHeight(); + GLsizei depth = getBaseLevelDepth(); + + ASSERT(width > 0 && height > 0 && depth > 0); + + // use existing storage level count, when previously specified by TexStorage*D + GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, depth)); + + return new TextureStorageInterface3D(mRenderer, getBaseLevelInternalFormat(), renderTarget, width, height, depth, levels); +} + +void TextureD3D_3D::setCompleteTexStorage(TextureStorageInterface3D *newCompleteTexStorage) +{ + SafeDelete(mTexStorage); + mTexStorage = newCompleteTexStorage; + mDirtyImages = true; + + // We do not support managed 3D storage, as that is D3D9/ES2-only + ASSERT(!mTexStorage->isManaged()); +} + +void TextureD3D_3D::updateStorage() +{ + ASSERT(mTexStorage != NULL); + GLint storageLevels = mTexStorage->getLevelCount(); + for (int level = 0; level < storageLevels; level++) + { + if (mImageArray[level]->isDirty() && isLevelComplete(level)) + { + updateStorageLevel(level); + } + } +} + +bool TextureD3D_3D::ensureRenderTarget() +{ + initializeStorage(true); + + if (getBaseLevelWidth() > 0 && getBaseLevelHeight() > 0 && getBaseLevelDepth() > 0) + { + ASSERT(mTexStorage); + if (!mTexStorage->isRenderTarget()) + { + TextureStorageInterface3D *newRenderTargetStorage = createCompleteStorage(true); + + if (!mRenderer->copyToRenderTarget(newRenderTargetStorage, mTexStorage)) + { + delete newRenderTargetStorage; + return gl::error(GL_OUT_OF_MEMORY, false); + } + + setCompleteTexStorage(newRenderTargetStorage); + } + } + + return (mTexStorage && mTexStorage->isRenderTarget()); +} + +TextureStorageInterface *TextureD3D_3D::getBaseLevelStorage() +{ + return mTexStorage; +} + +const ImageD3D *TextureD3D_3D::getBaseLevelImage() const +{ + return mImageArray[0]; +} + +bool TextureD3D_3D::isValidLevel(int level) const +{ + return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : 0); +} + +bool TextureD3D_3D::isLevelComplete(int level) const +{ + ASSERT(level >= 0 && level < (int)ArraySize(mImageArray) && mImageArray[level] != NULL); + + if (isImmutable()) + { + return true; + } + + GLsizei width = getBaseLevelWidth(); + GLsizei height = getBaseLevelHeight(); + GLsizei depth = getBaseLevelDepth(); + + if (width <= 0 || height <= 0 || depth <= 0) + { + return false; + } + + if (level == 0) + { + return true; + } + + ImageD3D *levelImage = mImageArray[level]; + + if (levelImage->getInternalFormat() != getBaseLevelInternalFormat()) + { + return false; + } + + if (levelImage->getWidth() != std::max(1, width >> level)) + { + return false; + } + + if (levelImage->getHeight() != std::max(1, height >> level)) + { + return false; + } + + if (levelImage->getDepth() != std::max(1, depth >> level)) + { + return false; + } + + return true; +} + +void TextureD3D_3D::updateStorageLevel(int level) +{ + ASSERT(level >= 0 && level < (int)ArraySize(mImageArray) && mImageArray[level] != NULL); + ASSERT(isLevelComplete(level)); + + if (mImageArray[level]->isDirty()) + { + commitRect(level, 0, 0, 0, getWidth(level), getHeight(level), getDepth(level)); + } +} + +void TextureD3D_3D::redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) +{ + // If there currently is a corresponding storage texture image, it has these parameters + const int storageWidth = std::max(1, getBaseLevelWidth() >> level); + const int storageHeight = std::max(1, getBaseLevelHeight() >> level); + const int storageDepth = std::max(1, getBaseLevelDepth() >> level); + const GLenum storageFormat = getBaseLevelInternalFormat(); + + mImageArray[level]->redefine(mRenderer, GL_TEXTURE_3D, internalformat, width, height, depth, false); + + if (mTexStorage) + { + const int storageLevels = mTexStorage->getLevelCount(); + + if ((level >= storageLevels && storageLevels != 0) || + width != storageWidth || + height != storageHeight || + depth != storageDepth || + internalformat != storageFormat) // Discard mismatched storage + { + for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + mImageArray[i]->markDirty(); + } + + SafeDelete(mTexStorage); + mDirtyImages = true; + } + } +} + +void TextureD3D_3D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth) +{ + if (isValidLevel(level)) + { + ImageD3D *image = mImageArray[level]; + if (image->copyToStorage(mTexStorage, level, xoffset, yoffset, zoffset, width, height, depth)) + { + image->markClean(); + } + } +} + + +TextureD3D_2DArray::TextureD3D_2DArray(Renderer *renderer) + : TextureD3D(renderer), + mTexStorage(NULL) +{ + for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++level) + { + mLayerCounts[level] = 0; + mImageArray[level] = NULL; + } +} + +TextureD3D_2DArray::~TextureD3D_2DArray() +{ + // Delete the Images before the TextureStorage. + // Images might be relying on the TextureStorage for some of their data. + // If TextureStorage is deleted before the Images, then their data will be wastefully copied back from the GPU before we delete the Images. + deleteImages(); + SafeDelete(mTexStorage); +} + +Image *TextureD3D_2DArray::getImage(int level, int layer) const +{ + ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT(layer < mLayerCounts[level]); + return mImageArray[level][layer]; +} + +GLsizei TextureD3D_2DArray::getLayerCount(int level) const +{ + ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + return mLayerCounts[level]; +} + +GLsizei TextureD3D_2DArray::getWidth(GLint level) const +{ + return (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mImageArray[level][0]->getWidth() : 0; +} + +GLsizei TextureD3D_2DArray::getHeight(GLint level) const +{ + return (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mImageArray[level][0]->getHeight() : 0; +} + +GLsizei TextureD3D_2DArray::getLayers(GLint level) const +{ + return (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mLayerCounts[level] : 0; +} + +GLenum TextureD3D_2DArray::getInternalFormat(GLint level) const +{ + return (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mImageArray[level][0]->getInternalFormat() : GL_NONE; +} + +bool TextureD3D_2DArray::isDepth(GLint level) const +{ + return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; +} + +void TextureD3D_2DArray::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) +{ + ASSERT(target == GL_TEXTURE_2D_ARRAY); + + GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type); + + redefineImage(level, sizedInternalFormat, width, height, depth); + + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedInternalFormat); + GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, width, height, unpack.alignment); + + for (int i = 0; i < depth; i++) + { + const void *layerPixels = pixels ? (reinterpret_cast(pixels) + (inputDepthPitch * i)) : NULL; + TextureD3D::setImage(unpack, type, layerPixels, mImageArray[level][i]); + } +} + +void TextureD3D_2DArray::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels) +{ + ASSERT(target == GL_TEXTURE_2D_ARRAY); + + // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly + redefineImage(level, format, width, height, depth); + + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format); + GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, width, height, 1); + + for (int i = 0; i < depth; i++) + { + const void *layerPixels = pixels ? (reinterpret_cast(pixels) + (inputDepthPitch * i)) : NULL; + TextureD3D::setCompressedImage(imageSize, layerPixels, mImageArray[level][i]); + } +} + +void TextureD3D_2DArray::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) +{ + ASSERT(target == GL_TEXTURE_2D_ARRAY); + + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(getInternalFormat(level)); + GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, width, height, unpack.alignment); + + for (int i = 0; i < depth; i++) + { + int layer = zoffset + i; + const void *layerPixels = pixels ? (reinterpret_cast(pixels) + (inputDepthPitch * i)) : NULL; + + if (TextureD3D::subImage(xoffset, yoffset, zoffset, width, height, 1, format, type, unpack, layerPixels, mImageArray[level][layer])) + { + commitRect(level, xoffset, yoffset, layer, width, height); + } + } +} + +void TextureD3D_2DArray::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels) +{ + ASSERT(target == GL_TEXTURE_2D_ARRAY); + + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format); + GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, width, height, 1); + + for (int i = 0; i < depth; i++) + { + int layer = zoffset + i; + const void *layerPixels = pixels ? (reinterpret_cast(pixels) + (inputDepthPitch * i)) : NULL; + + if (TextureD3D::subImageCompressed(xoffset, yoffset, zoffset, width, height, 1, format, imageSize, layerPixels, mImageArray[level][layer])) + { + commitRect(level, xoffset, yoffset, layer, width, height); + } + } +} + +void TextureD3D_2DArray::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) +{ + UNIMPLEMENTED(); +} + +void TextureD3D_2DArray::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) +{ + ASSERT(target == GL_TEXTURE_2D_ARRAY); + + // can only make our texture storage to a render target if level 0 is defined (with a width & height) and + // the current level we're copying to is defined (with appropriate format, width & height) + bool canCreateRenderTarget = isLevelComplete(level) && isLevelComplete(0); + + if (!mImageArray[level][0]->isRenderableFormat() || (!mTexStorage && !canCreateRenderTarget)) + { + mImageArray[level][zoffset]->copy(xoffset, yoffset, 0, x, y, width, height, source); + mDirtyImages = true; + } + else + { + ensureRenderTarget(); + + if (isValidLevel(level)) + { + updateStorageLevel(level); + + gl::Rectangle sourceRect; + sourceRect.x = x; + sourceRect.width = width; + sourceRect.y = y; + sourceRect.height = height; + + mRenderer->copyImage(source, sourceRect, gl::GetInternalFormatInfo(getInternalFormat(0)).format, + xoffset, yoffset, zoffset, mTexStorage, level); + } + } +} + +void TextureD3D_2DArray::storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) +{ + ASSERT(target == GL_TEXTURE_2D_ARRAY); + + deleteImages(); + + for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + GLsizei levelWidth = std::max(1, width >> level); + GLsizei levelHeight = std::max(1, height >> level); + + mLayerCounts[level] = (level < levels ? depth : 0); + + if (mLayerCounts[level] > 0) + { + // Create new images for this level + mImageArray[level] = new ImageD3D*[mLayerCounts[level]]; + + for (int layer = 0; layer < mLayerCounts[level]; layer++) + { + mImageArray[level][layer] = ImageD3D::makeImageD3D(mRenderer->createImage()); + mImageArray[level][layer]->redefine(mRenderer, GL_TEXTURE_2D_ARRAY, internalformat, levelWidth, + levelHeight, 1, true); + } + } + } + + mImmutable = true; + setCompleteTexStorage(new TextureStorageInterface2DArray(mRenderer, internalformat, IsRenderTargetUsage(mUsage), width, height, depth, levels)); +} + +void TextureD3D_2DArray::bindTexImage(egl::Surface *surface) +{ + UNREACHABLE(); +} + +void TextureD3D_2DArray::releaseTexImage() +{ + UNREACHABLE(); +} + + +void TextureD3D_2DArray::generateMipmaps() +{ + int baseWidth = getBaseLevelWidth(); + int baseHeight = getBaseLevelHeight(); + int baseDepth = getBaseLevelDepth(); + GLenum baseFormat = getBaseLevelInternalFormat(); + + // Purge array levels 1 through q and reset them to represent the generated mipmap levels. + int levelCount = mipLevels(); + for (int level = 1; level < levelCount; level++) + { + redefineImage(level, baseFormat, std::max(baseWidth >> level, 1), std::max(baseHeight >> level, 1), baseDepth); + } + + if (mTexStorage && mTexStorage->isRenderTarget()) + { + for (int level = 1; level < levelCount; level++) + { + mTexStorage->generateMipmap(level); + + for (int layer = 0; layer < mLayerCounts[level]; layer++) + { + mImageArray[level][layer]->markClean(); + } + } + } + else + { + for (int level = 1; level < levelCount; level++) + { + for (int layer = 0; layer < mLayerCounts[level]; layer++) + { + mRenderer->generateMipmap(mImageArray[level][layer], mImageArray[level - 1][layer]); + } + } + } +} + +unsigned int TextureD3D_2DArray::getRenderTargetSerial(GLint level, GLint layer) +{ + return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(level, layer) : 0); +} + +RenderTarget *TextureD3D_2DArray::getRenderTarget(GLint level, GLint layer) +{ + // ensure the underlying texture is created + if (!ensureRenderTarget()) + { + return NULL; + } + + updateStorageLevel(level); + return mTexStorage->getRenderTarget(level, layer); +} + +void TextureD3D_2DArray::initializeStorage(bool renderTarget) +{ + // Only initialize the first time this texture is used as a render target or shader resource + if (mTexStorage) + { + return; + } + + // do not attempt to create storage for nonexistant data + if (!isLevelComplete(0)) + { + return; + } + + bool createRenderTarget = (renderTarget || mUsage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE); + + setCompleteTexStorage(createCompleteStorage(createRenderTarget)); + ASSERT(mTexStorage); + + // flush image data to the storage + updateStorage(); +} + +TextureStorageInterface2DArray *TextureD3D_2DArray::createCompleteStorage(bool renderTarget) const +{ + GLsizei width = getBaseLevelWidth(); + GLsizei height = getBaseLevelHeight(); + GLsizei depth = getLayers(0); + + ASSERT(width > 0 && height > 0 && depth > 0); + + // use existing storage level count, when previously specified by TexStorage*D + GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, 1)); + + return new TextureStorageInterface2DArray(mRenderer, getBaseLevelInternalFormat(), renderTarget, width, height, depth, levels); +} + +void TextureD3D_2DArray::setCompleteTexStorage(TextureStorageInterface2DArray *newCompleteTexStorage) +{ + SafeDelete(mTexStorage); + mTexStorage = newCompleteTexStorage; + mDirtyImages = true; + + // We do not support managed 2D array storage, as managed storage is ES2/D3D9 only + ASSERT(!mTexStorage->isManaged()); +} + +void TextureD3D_2DArray::updateStorage() +{ + ASSERT(mTexStorage != NULL); + GLint storageLevels = mTexStorage->getLevelCount(); + for (int level = 0; level < storageLevels; level++) + { + if (isLevelComplete(level)) + { + updateStorageLevel(level); + } + } +} + +bool TextureD3D_2DArray::ensureRenderTarget() +{ + initializeStorage(true); + + if (getBaseLevelWidth() > 0 && getBaseLevelHeight() > 0 && getLayers(0) > 0) + { + ASSERT(mTexStorage); + if (!mTexStorage->isRenderTarget()) + { + TextureStorageInterface2DArray *newRenderTargetStorage = createCompleteStorage(true); + + if (!mRenderer->copyToRenderTarget(newRenderTargetStorage, mTexStorage)) + { + delete newRenderTargetStorage; + return gl::error(GL_OUT_OF_MEMORY, false); + } + + setCompleteTexStorage(newRenderTargetStorage); + } + } + + return (mTexStorage && mTexStorage->isRenderTarget()); +} + +const ImageD3D *TextureD3D_2DArray::getBaseLevelImage() const +{ + return (mLayerCounts[0] > 0 ? mImageArray[0][0] : NULL); +} + +TextureStorageInterface *TextureD3D_2DArray::getBaseLevelStorage() +{ + return mTexStorage; +} + +bool TextureD3D_2DArray::isValidLevel(int level) const +{ + return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : 0); +} + +bool TextureD3D_2DArray::isLevelComplete(int level) const +{ + ASSERT(level >= 0 && level < (int)ArraySize(mImageArray)); + + if (isImmutable()) + { + return true; + } + + GLsizei width = getBaseLevelWidth(); + GLsizei height = getBaseLevelHeight(); + GLsizei layers = getLayers(0); + + if (width <= 0 || height <= 0 || layers <= 0) + { + return false; + } + + if (level == 0) + { + return true; + } + + if (getInternalFormat(level) != getInternalFormat(0)) + { + return false; + } + + if (getWidth(level) != std::max(1, width >> level)) + { + return false; + } + + if (getHeight(level) != std::max(1, height >> level)) + { + return false; + } + + if (getLayers(level) != layers) + { + return false; + } + + return true; +} + +void TextureD3D_2DArray::updateStorageLevel(int level) +{ + ASSERT(level >= 0 && level < (int)ArraySize(mLayerCounts)); + ASSERT(isLevelComplete(level)); + + for (int layer = 0; layer < mLayerCounts[level]; layer++) + { + ASSERT(mImageArray[level] != NULL && mImageArray[level][layer] != NULL); + if (mImageArray[level][layer]->isDirty()) + { + commitRect(level, 0, 0, layer, getWidth(level), getHeight(level)); + } + } +} + +void TextureD3D_2DArray::deleteImages() +{ + for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++level) + { + for (int layer = 0; layer < mLayerCounts[level]; ++layer) + { + delete mImageArray[level][layer]; + } + delete[] mImageArray[level]; + mImageArray[level] = NULL; + mLayerCounts[level] = 0; + } +} + +void TextureD3D_2DArray::redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) +{ + // If there currently is a corresponding storage texture image, it has these parameters + const int storageWidth = std::max(1, getBaseLevelWidth() >> level); + const int storageHeight = std::max(1, getBaseLevelHeight() >> level); + const int storageDepth = getLayers(0); + const GLenum storageFormat = getBaseLevelInternalFormat(); + + for (int layer = 0; layer < mLayerCounts[level]; layer++) + { + delete mImageArray[level][layer]; + } + delete[] mImageArray[level]; + mImageArray[level] = NULL; + mLayerCounts[level] = depth; + + if (depth > 0) + { + mImageArray[level] = new ImageD3D*[depth](); + + for (int layer = 0; layer < mLayerCounts[level]; layer++) + { + mImageArray[level][layer] = ImageD3D::makeImageD3D(mRenderer->createImage()); + mImageArray[level][layer]->redefine(mRenderer, GL_TEXTURE_2D_ARRAY, internalformat, width, height, 1, false); + } + } + + if (mTexStorage) + { + const int storageLevels = mTexStorage->getLevelCount(); + + if ((level >= storageLevels && storageLevels != 0) || + width != storageWidth || + height != storageHeight || + depth != storageDepth || + internalformat != storageFormat) // Discard mismatched storage + { + for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + for (int layer = 0; layer < mLayerCounts[level]; layer++) + { + mImageArray[level][layer]->markDirty(); + } + } + + delete mTexStorage; + mTexStorage = NULL; + mDirtyImages = true; + } + } +} + +void TextureD3D_2DArray::commitRect(GLint level, GLint xoffset, GLint yoffset, GLint layerTarget, GLsizei width, GLsizei height) +{ + if (isValidLevel(level) && layerTarget < getLayers(level)) + { + ImageD3D *image = mImageArray[level][layerTarget]; + if (image->copyToStorage(mTexStorage, level, xoffset, yoffset, layerTarget, width, height)) + { + image->markClean(); + } + } +} + +} diff --git a/gfx/angle/src/libGLESv2/renderer/d3d/TextureD3D.h b/gfx/angle/src/libGLESv2/renderer/d3d/TextureD3D.h new file mode 100644 index 000000000000..7f2163077b12 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/d3d/TextureD3D.h @@ -0,0 +1,321 @@ +// +// Copyright 2014 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. +// + +// TextureD3D.h: Implementations of the Texture interfaces shared betweeen the D3D backends. + +#ifndef LIBGLESV2_RENDERER_TEXTURED3D_H_ +#define LIBGLESV2_RENDERER_TEXTURED3D_H_ + +#include "libGLESv2/renderer/TextureImpl.h" +#include "libGLESv2/angletypes.h" +#include "libGLESv2/constants.h" + +namespace gl +{ +class Framebuffer; +} + +namespace rx +{ + +class Image; +class ImageD3D; +class Renderer; +class TextureStorageInterface; +class TextureStorageInterface2D; +class TextureStorageInterfaceCube; +class TextureStorageInterface3D; +class TextureStorageInterface2DArray; + +class TextureD3D : public TextureImpl +{ + public: + TextureD3D(Renderer *renderer); + virtual ~TextureD3D(); + + static TextureD3D *makeTextureD3D(TextureImpl *texture); + + virtual TextureStorageInterface *getNativeTexture(); + + virtual void setUsage(GLenum usage) { mUsage = usage; } + bool hasDirtyImages() const { return mDirtyImages; } + void resetDirty() { mDirtyImages = false; } + + GLint getBaseLevelWidth() const; + GLint getBaseLevelHeight() const; + GLint getBaseLevelDepth() const; + GLenum getBaseLevelInternalFormat() const; + + bool isImmutable() const { return mImmutable; } + + protected: + void setImage(const gl::PixelUnpackState &unpack, GLenum type, const void *pixels, Image *image); + bool subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels, Image *image); + void setCompressedImage(GLsizei imageSize, const void *pixels, Image *image); + bool subImageCompressed(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLsizei imageSize, const void *pixels, Image *image); + bool isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum sizedInternalFormat); + bool fastUnpackPixels(const gl::PixelUnpackState &unpack, const void *pixels, const gl::Box &destArea, + GLenum sizedInternalFormat, GLenum type, RenderTarget *destRenderTarget); + + GLint creationLevels(GLsizei width, GLsizei height, GLsizei depth) const; + int mipLevels() const; + + Renderer *mRenderer; + + GLenum mUsage; + + bool mDirtyImages; + + bool mImmutable; + + private: + DISALLOW_COPY_AND_ASSIGN(TextureD3D); + + virtual void initializeStorage(bool renderTarget) = 0; + + virtual void updateStorage() = 0; + virtual TextureStorageInterface *getBaseLevelStorage() = 0; + virtual const ImageD3D *getBaseLevelImage() const = 0; +}; + +class TextureD3D_2D : public TextureD3D +{ + public: + TextureD3D_2D(Renderer *renderer); + virtual ~TextureD3D_2D(); + + virtual Image *getImage(int level, int layer) const; + virtual GLsizei getLayerCount(int level) const; + + GLsizei getWidth(GLint level) const; + GLsizei getHeight(GLint level) const; + GLenum getInternalFormat(GLint level) const; + GLenum getActualFormat(GLint level) const; + bool isDepth(GLint level) const; + + virtual void setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); + virtual void setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels); + virtual void subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); + virtual void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels); + virtual void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); + virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); + virtual void storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); + + virtual void bindTexImage(egl::Surface *surface); + virtual void releaseTexImage(); + + virtual void generateMipmaps(); + + virtual unsigned int getRenderTargetSerial(GLint level, GLint layer); + + virtual RenderTarget *getRenderTarget(GLint level, GLint layer); + + private: + DISALLOW_COPY_AND_ASSIGN(TextureD3D_2D); + + virtual void initializeStorage(bool renderTarget); + TextureStorageInterface2D *createCompleteStorage(bool renderTarget) const; + void setCompleteTexStorage(TextureStorageInterface2D *newCompleteTexStorage); + + virtual void updateStorage(); + bool ensureRenderTarget(); + virtual TextureStorageInterface *getBaseLevelStorage(); + virtual const ImageD3D *getBaseLevelImage() const; + + bool isValidLevel(int level) const; + bool isLevelComplete(int level) const; + + void updateStorageLevel(int level); + + void redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height); + void commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); + + TextureStorageInterface2D *mTexStorage; + ImageD3D *mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; +}; + +class TextureD3D_Cube : public TextureD3D +{ + public: + TextureD3D_Cube(Renderer *renderer); + virtual ~TextureD3D_Cube(); + + virtual Image *getImage(int level, int layer) const; + virtual GLsizei getLayerCount(int level) const; + + virtual bool hasDirtyImages() const { return mDirtyImages; } + virtual void resetDirty() { mDirtyImages = false; } + virtual void setUsage(GLenum usage) { mUsage = usage; } + + GLenum getInternalFormat(GLint level, GLint layer) const; + bool isDepth(GLint level, GLint layer) const; + + virtual void setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); + virtual void setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels); + virtual void subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); + virtual void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels); + virtual void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); + virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); + virtual void storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); + + virtual void bindTexImage(egl::Surface *surface); + virtual void releaseTexImage(); + + virtual void generateMipmaps(); + + virtual unsigned int getRenderTargetSerial(GLint level, GLint layer); + + virtual RenderTarget *getRenderTarget(GLint level, GLint layer); + + private: + DISALLOW_COPY_AND_ASSIGN(TextureD3D_Cube); + + virtual void initializeStorage(bool renderTarget); + TextureStorageInterfaceCube *createCompleteStorage(bool renderTarget) const; + void setCompleteTexStorage(TextureStorageInterfaceCube *newCompleteTexStorage); + + virtual void updateStorage(); + bool ensureRenderTarget(); + virtual TextureStorageInterface *getBaseLevelStorage(); + virtual const ImageD3D *getBaseLevelImage() const; + + bool isValidFaceLevel(int faceIndex, int level) const; + bool isFaceLevelComplete(int faceIndex, int level) const; + bool isCubeComplete() const; + void updateStorageFaceLevel(int faceIndex, int level); + + void redefineImage(int faceIndex, GLint level, GLenum internalformat, GLsizei width, GLsizei height); + void commitRect(int faceIndex, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); + + ImageD3D *mImageArray[6][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + + TextureStorageInterfaceCube *mTexStorage; +}; + +class TextureD3D_3D : public TextureD3D +{ + public: + TextureD3D_3D(Renderer *renderer); + virtual ~TextureD3D_3D(); + + virtual Image *getImage(int level, int layer) const; + virtual GLsizei getLayerCount(int level) const; + + GLsizei getWidth(GLint level) const; + GLsizei getHeight(GLint level) const; + GLsizei getDepth(GLint level) const; + GLenum getInternalFormat(GLint level) const; + bool isDepth(GLint level) const; + + virtual void setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); + virtual void setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels); + virtual void subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); + virtual void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels); + virtual void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); + virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); + virtual void storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); + + virtual void bindTexImage(egl::Surface *surface); + virtual void releaseTexImage(); + + virtual void generateMipmaps(); + + virtual unsigned int getRenderTargetSerial(GLint level, GLint layer); + + virtual RenderTarget *getRenderTarget(GLint level); + virtual RenderTarget *getRenderTarget(GLint level, GLint layer); + + private: + DISALLOW_COPY_AND_ASSIGN(TextureD3D_3D); + + virtual void initializeStorage(bool renderTarget); + TextureStorageInterface3D *createCompleteStorage(bool renderTarget) const; + void setCompleteTexStorage(TextureStorageInterface3D *newCompleteTexStorage); + + virtual void updateStorage(); + bool ensureRenderTarget(); + virtual TextureStorageInterface *getBaseLevelStorage(); + virtual const ImageD3D *getBaseLevelImage() const; + + bool isValidLevel(int level) const; + bool isLevelComplete(int level) const; + void updateStorageLevel(int level); + + void redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); + void commitRect(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth); + + ImageD3D *mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + + TextureStorageInterface3D *mTexStorage; +}; + +class TextureD3D_2DArray : public TextureD3D +{ + public: + TextureD3D_2DArray(Renderer *renderer); + virtual ~TextureD3D_2DArray(); + + virtual Image *getImage(int level, int layer) const; + virtual GLsizei getLayerCount(int level) const; + + GLsizei getWidth(GLint level) const; + GLsizei getHeight(GLint level) const; + GLsizei getLayers(GLint level) const; + GLenum getInternalFormat(GLint level) const; + bool isDepth(GLint level) const; + + virtual void setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); + virtual void setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels); + virtual void subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); + virtual void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels); + virtual void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); + virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); + virtual void storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); + + virtual void bindTexImage(egl::Surface *surface); + virtual void releaseTexImage(); + + virtual void generateMipmaps(); + + virtual unsigned int getRenderTargetSerial(GLint level, GLint layer); + + virtual RenderTarget *getRenderTarget(GLint level, GLint layer); + + private: + DISALLOW_COPY_AND_ASSIGN(TextureD3D_2DArray); + + virtual void initializeStorage(bool renderTarget); + TextureStorageInterface2DArray *createCompleteStorage(bool renderTarget) const; + void setCompleteTexStorage(TextureStorageInterface2DArray *newCompleteTexStorage); + + virtual void updateStorage(); + bool ensureRenderTarget(); + virtual TextureStorageInterface *getBaseLevelStorage(); + virtual const ImageD3D *getBaseLevelImage() const; + + bool isValidLevel(int level) const; + bool isLevelComplete(int level) const; + void updateStorageLevel(int level); + + void deleteImages(); + void redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); + void commitRect(GLint level, GLint xoffset, GLint yoffset, GLint layerTarget, GLsizei width, GLsizei height); + + // Storing images as an array of single depth textures since D3D11 treats each array level of a + // Texture2D object as a separate subresource. Each layer would have to be looped over + // to update all the texture layers since they cannot all be updated at once and it makes the most + // sense for the Image class to not have to worry about layer subresource as well as mip subresources. + GLsizei mLayerCounts[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + ImageD3D **mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + + TextureStorageInterface2DArray *mTexStorage; +}; + +} + +#endif // LIBGLESV2_RENDERER_TEXTURED3D_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/TextureStorage.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/TextureStorage.cpp similarity index 97% rename from gfx/angle/src/libGLESv2/renderer/TextureStorage.cpp rename to gfx/angle/src/libGLESv2/renderer/d3d/TextureStorage.cpp index 650f368a1d88..86902e9008c5 100644 --- a/gfx/angle/src/libGLESv2/renderer/TextureStorage.cpp +++ b/gfx/angle/src/libGLESv2/renderer/d3d/TextureStorage.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // 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 @@ -9,7 +8,8 @@ // classes TextureStorageInterface2D and TextureStorageInterfaceCube, which act as the interface to the // GPU-side texture. -#include "libGLESv2/renderer/TextureStorage.h" +#include "libGLESv2/renderer/d3d/TextureStorage.h" +#include "libGLESv2/renderer/d3d/TextureD3D.h" #include "libGLESv2/renderer/Renderer.h" #include "libGLESv2/Renderbuffer.h" #include "libGLESv2/Texture.h" @@ -116,7 +116,7 @@ void TextureStorageInterfaceCube::generateMipmap(int faceIndex, int level) unsigned int TextureStorageInterfaceCube::getRenderTargetSerial(GLenum target, GLint level) const { - return mFirstRenderTargetSerial + (level * 6) + gl::TextureCubeMap::targetToIndex(target); + return mFirstRenderTargetSerial + (level * 6) + gl::TextureCubeMap::targetToLayerIndex(target); } TextureStorageInterface3D::TextureStorageInterface3D(Renderer *renderer, GLenum internalformat, bool renderTarget, diff --git a/gfx/angle/src/libGLESv2/renderer/TextureStorage.h b/gfx/angle/src/libGLESv2/renderer/d3d/TextureStorage.h similarity index 99% rename from gfx/angle/src/libGLESv2/renderer/TextureStorage.h rename to gfx/angle/src/libGLESv2/renderer/d3d/TextureStorage.h index 0a212e16f27e..c42d4b685b5e 100644 --- a/gfx/angle/src/libGLESv2/renderer/TextureStorage.h +++ b/gfx/angle/src/libGLESv2/renderer/d3d/TextureStorage.h @@ -13,6 +13,8 @@ #include "common/debug.h" +#include + namespace rx { class Renderer; diff --git a/gfx/angle/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.cpp new file mode 100644 index 000000000000..11596006d0d2 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.cpp @@ -0,0 +1,38 @@ +// +// Copyright 2014 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. +// + +// TransformFeedbackD3D.cpp is a no-op implementation for both the D3D9 and D3D11 renderers. + +#include "libGLESv2/renderer/d3d/TransformFeedbackD3D.h" + +namespace rx +{ + +TransformFeedbackD3D::TransformFeedbackD3D() +{ +} + +TransformFeedbackD3D::~TransformFeedbackD3D() +{ +} + +void TransformFeedbackD3D::begin(GLenum primitiveMode) +{ +} + +void TransformFeedbackD3D::end() +{ +} + +void TransformFeedbackD3D::pause() +{ +} + +void TransformFeedbackD3D::resume() +{ +} + +} diff --git a/gfx/angle/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.h b/gfx/angle/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.h new file mode 100644 index 000000000000..7c367aba1d22 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.h @@ -0,0 +1,32 @@ +// +// Copyright 2014 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. +// + +// TransformFeedbackD3D.h: Implements the abstract rx::TransformFeedbackImpl class. + +#ifndef LIBGLESV2_RENDERER_D3D_TRANSFORMFEEDBACKD3D_H_ +#define LIBGLESV2_RENDERER_D3D_TRANSFORMFEEDBACKD3D_H_ + +#include "libGLESv2/renderer/TransformFeedbackImpl.h" +#include "libGLESv2/angletypes.h" + +namespace rx +{ + +class TransformFeedbackD3D : public TransformFeedbackImpl +{ + public: + TransformFeedbackD3D(); + virtual ~TransformFeedbackD3D(); + + virtual void begin(GLenum primitiveMode); + virtual void end(); + virtual void pause(); + virtual void resume(); +}; + +} + +#endif // LIBGLESV2_RENDERER_D3D_TRANSFORMFEEDBACKD3D_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/VertexBuffer.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/VertexBuffer.cpp similarity index 82% rename from gfx/angle/src/libGLESv2/renderer/VertexBuffer.cpp rename to gfx/angle/src/libGLESv2/renderer/d3d/VertexBuffer.cpp index 8adfb5bfa745..d2a1e8fc1805 100644 --- a/gfx/angle/src/libGLESv2/renderer/VertexBuffer.cpp +++ b/gfx/angle/src/libGLESv2/renderer/d3d/VertexBuffer.cpp @@ -1,4 +1,3 @@ -#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 @@ -8,10 +7,11 @@ // 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/d3d/VertexBuffer.h" +#include "libGLESv2/renderer/d3d/BufferD3D.h" #include "libGLESv2/renderer/Renderer.h" #include "libGLESv2/VertexAttribute.h" -#include "libGLESv2/renderer/BufferStorage.h" + #include "common/mathutil.h" namespace rx @@ -127,10 +127,10 @@ bool VertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &att return true; } -bool VertexBufferInterface::reserveVertexSpace(const gl::VertexAttribute &attribute, GLsizei count, GLsizei instances) +bool VertexBufferInterface::reserveVertexSpace(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances) { unsigned int requiredSpace; - if (!mVertexBuffer->getSpaceRequired(attribute, count, instances, &requiredSpace)) + if (!mVertexBuffer->getSpaceRequired(attrib, count, instances, &requiredSpace)) { return false; } @@ -157,8 +157,8 @@ VertexBuffer* VertexBufferInterface::getVertexBuffer() const bool VertexBufferInterface::directStoragePossible(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue) const { - gl::Buffer *buffer = attrib.mBoundBuffer.get(); - BufferStorage *storage = buffer ? buffer->getStorage() : NULL; + gl::Buffer *buffer = attrib.buffer.get(); + BufferD3D *storage = buffer ? BufferD3D::makeBufferD3D(buffer->getImplementation()) : NULL; if (!storage || !storage->supportsDirectBinding()) { @@ -171,7 +171,7 @@ bool VertexBufferInterface::directStoragePossible(const gl::VertexAttribute &att size_t alignment = 4; bool requiresConversion = false; - if (attrib.mType != GL_FLOAT) + if (attrib.type != GL_FLOAT) { gl::VertexFormat vertexFormat(attrib, currentValue.Type); @@ -182,8 +182,8 @@ bool VertexBufferInterface::directStoragePossible(const gl::VertexAttribute &att requiresConversion = (mRenderer->getVertexConversionType(vertexFormat) & VERTEX_CONVERT_CPU) != 0; } - bool isAligned = (static_cast(attrib.stride()) % alignment == 0) && - (static_cast(attrib.mOffset) % alignment == 0); + bool isAligned = (static_cast(ComputeVertexAttributeStride(attrib)) % alignment == 0) && + (static_cast(attrib.offset) % alignment == 0); return !requiresConversion && isAligned; } @@ -226,17 +226,18 @@ StaticVertexBufferInterface::~StaticVertexBufferInterface() { } -bool StaticVertexBufferInterface::lookupAttribute(const gl::VertexAttribute &attribute, unsigned int *outStreamOffset) +bool StaticVertexBufferInterface::lookupAttribute(const gl::VertexAttribute &attrib, 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 && - mCache[element].pureInteger == attribute.mPureInteger) + if (mCache[element].type == attrib.type && + mCache[element].size == attrib.size && + mCache[element].stride == ComputeVertexAttributeStride(attrib) && + mCache[element].normalized == attrib.normalized && + mCache[element].pureInteger == attrib.pureInteger) { - if (mCache[element].attributeOffset == attribute.mOffset % attribute.stride()) + size_t offset = (static_cast(attrib.offset) % ComputeVertexAttributeStride(attrib)); + if (mCache[element].attributeOffset == offset) { if (outStreamOffset) { @@ -275,8 +276,8 @@ bool StaticVertexBufferInterface::storeVertexAttributes(const gl::VertexAttribut unsigned int streamOffset; if (VertexBufferInterface::storeVertexAttributes(attrib, currentValue, start, count, instances, &streamOffset)) { - int attributeOffset = attrib.mOffset % attrib.stride(); - VertexElement element = { attrib.mType, attrib.mSize, attrib.stride(), attrib.mNormalized, attrib.mPureInteger, attributeOffset, streamOffset }; + size_t attributeOffset = static_cast(attrib.offset) % ComputeVertexAttributeStride(attrib); + VertexElement element = { attrib.type, attrib.size, ComputeVertexAttributeStride(attrib), attrib.normalized, attrib.pureInteger, attributeOffset, streamOffset }; mCache.push_back(element); if (outStreamOffset) diff --git a/gfx/angle/src/libGLESv2/renderer/VertexBuffer.h b/gfx/angle/src/libGLESv2/renderer/d3d/VertexBuffer.h similarity index 92% rename from gfx/angle/src/libGLESv2/renderer/VertexBuffer.h rename to gfx/angle/src/libGLESv2/renderer/d3d/VertexBuffer.h index d4cdf9ee8522..e36084fe3c1d 100644 --- a/gfx/angle/src/libGLESv2/renderer/VertexBuffer.h +++ b/gfx/angle/src/libGLESv2/renderer/d3d/VertexBuffer.h @@ -12,9 +12,14 @@ #include "common/angleutils.h" +#include + +#include +#include + namespace gl { -class VertexAttribute; +struct VertexAttribute; struct VertexAttribCurrentValueData; } @@ -110,7 +115,7 @@ class StaticVertexBufferInterface : public VertexBufferInterface ~StaticVertexBufferInterface(); bool storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, - GLint start, GLsizei count, GLsizei instances, unsigned int *outStreamOffset); + GLint start, GLsizei count, GLsizei instances, unsigned int *outStreamOffset); bool lookupAttribute(const gl::VertexAttribute &attribute, unsigned int* outStreamFffset); @@ -121,11 +126,11 @@ class StaticVertexBufferInterface : public VertexBufferInterface struct VertexElement { GLenum type; - GLint size; - GLsizei stride; + GLuint size; + GLuint stride; bool normalized; bool pureInteger; - int attributeOffset; + size_t attributeOffset; unsigned int streamOffset; }; diff --git a/gfx/angle/src/libGLESv2/renderer/d3d/VertexDataManager.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/VertexDataManager.cpp new file mode 100644 index 000000000000..a69bc6797da5 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/d3d/VertexDataManager.cpp @@ -0,0 +1,335 @@ +// +// 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/d3d/VertexDataManager.h" +#include "libGLESv2/renderer/d3d/BufferD3D.h" +#include "libGLESv2/renderer/d3d/VertexBuffer.h" +#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/Buffer.h" +#include "libGLESv2/ProgramBinary.h" +#include "libGLESv2/VertexAttribute.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 &attrib, 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 = ComputeVertexAttributeStride(attrib); + return (size - attrib.offset % stride + (stride - ComputeVertexAttributeTypeSize(attrib))) / stride; +} + +static int StreamingBufferElementCount(const gl::VertexAttribute &attrib, int vertexDrawCount, int instanceDrawCount) +{ + // For instanced rendering, we draw "instanceDrawCount" sets of "vertexDrawCount" vertices. + // + // A vertex attribute with a positive divisor loads one instanced vertex for every set of + // non-instanced vertices, and the instanced vertex index advances once every "mDivisor" instances. + if (instanceDrawCount > 0 && attrib.divisor > 0) + { + return instanceDrawCount / attrib.divisor; + } + + return vertexDrawCount; +} + +VertexDataManager::VertexDataManager(Renderer *renderer) : mRenderer(renderer) +{ + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + mCurrentValue[i].FloatValues[0] = std::numeric_limits::quiet_NaN(); + mCurrentValue[i].FloatValues[1] = std::numeric_limits::quiet_NaN(); + mCurrentValue[i].FloatValues[2] = std::numeric_limits::quiet_NaN(); + mCurrentValue[i].FloatValues[3] = std::numeric_limits::quiet_NaN(); + mCurrentValue[i].Type = GL_FLOAT; + 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]; + } +} + +GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], const gl::VertexAttribCurrentValueData currentValues[], + gl::ProgramBinary *programBinary, GLint start, GLsizei count, TranslatedAttribute *translated, GLsizei instances) +{ + if (!mStreamingBuffer) + { + return GL_OUT_OF_MEMORY; + } + + // Invalidate static buffers that don't contain matching attributes + for (int attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++) + { + translated[attributeIndex].active = (programBinary->getSemanticIndex(attributeIndex) != -1); + + if (translated[attributeIndex].active && attribs[attributeIndex].enabled) + { + invalidateMatchingStaticData(attribs[attributeIndex], currentValues[attributeIndex]); + } + } + + // Reserve the required space in the buffers + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + if (translated[i].active && attribs[i].enabled) + { + if (!reserveSpaceForAttrib(attribs[i], currentValues[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) + { + GLenum result; + + if (attribs[i].enabled) + { + result = storeAttribute(attribs[i], currentValues[i], &translated[i], + start, count, instances); + } + else + { + if (!mCurrentValueBuffer[i]) + { + mCurrentValueBuffer[i] = new StreamingVertexBufferInterface(mRenderer, CONSTANT_VERTEX_BUFFER_SIZE); + } + + result = storeCurrentValue(attribs[i], currentValues[i], &translated[i], + &mCurrentValue[i], &mCurrentValueOffsets[i], + mCurrentValueBuffer[i]); + } + + if (result != GL_NO_ERROR) + { + return result; + } + } + } + + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + if (translated[i].active && attribs[i].enabled) + { + gl::Buffer *buffer = attribs[i].buffer.get(); + + if (buffer) + { + BufferD3D *bufferImpl = BufferD3D::makeBufferD3D(buffer->getImplementation()); + bufferImpl->promoteStaticUsage(count * ComputeVertexAttributeTypeSize(attribs[i])); + } + } + } + + return GL_NO_ERROR; +} + +void VertexDataManager::invalidateMatchingStaticData(const gl::VertexAttribute &attrib, + const gl::VertexAttribCurrentValueData ¤tValue) const +{ + gl::Buffer *buffer = attrib.buffer.get(); + + if (buffer) + { + BufferD3D *bufferImpl = BufferD3D::makeBufferD3D(buffer->getImplementation()); + StaticVertexBufferInterface *staticBuffer = bufferImpl->getStaticVertexBuffer(); + + if (staticBuffer && + staticBuffer->getBufferSize() > 0 && + !staticBuffer->lookupAttribute(attrib, NULL) && + !staticBuffer->directStoragePossible(attrib, currentValue)) + { + bufferImpl->invalidateStaticData(); + } + } +} + +bool VertexDataManager::reserveSpaceForAttrib(const gl::VertexAttribute &attrib, + const gl::VertexAttribCurrentValueData ¤tValue, + GLsizei count, + GLsizei instances) const +{ + gl::Buffer *buffer = attrib.buffer.get(); + BufferD3D *bufferImpl = buffer ? BufferD3D::makeBufferD3D(buffer->getImplementation()) : NULL; + StaticVertexBufferInterface *staticBuffer = bufferImpl ? bufferImpl->getStaticVertexBuffer() : NULL; + VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast(mStreamingBuffer); + + if (!vertexBuffer->directStoragePossible(attrib, currentValue)) + { + if (staticBuffer) + { + if (staticBuffer->getBufferSize() == 0) + { + int totalCount = ElementsInBuffer(attrib, bufferImpl->getSize()); + if (!staticBuffer->reserveVertexSpace(attrib, totalCount, 0)) + { + return false; + } + } + } + else + { + int totalCount = StreamingBufferElementCount(attrib, count, instances); + ASSERT(!bufferImpl || ElementsInBuffer(attrib, bufferImpl->getSize()) >= totalCount); + + if (!mStreamingBuffer->reserveVertexSpace(attrib, totalCount, instances)) + { + return false; + } + } + } + + return true; +} + +GLenum VertexDataManager::storeAttribute(const gl::VertexAttribute &attrib, + const gl::VertexAttribCurrentValueData ¤tValue, + TranslatedAttribute *translated, + GLint start, + GLsizei count, + GLsizei instances) +{ + gl::Buffer *buffer = attrib.buffer.get(); + ASSERT(buffer || attrib.pointer); + + BufferD3D *storage = buffer ? BufferD3D::makeBufferD3D(buffer->getImplementation()) : NULL; + StaticVertexBufferInterface *staticBuffer = storage ? storage->getStaticVertexBuffer() : NULL; + VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast(mStreamingBuffer); + bool directStorage = vertexBuffer->directStoragePossible(attrib, currentValue); + + unsigned int streamOffset = 0; + unsigned int outputElementSize = 0; + + if (directStorage) + { + outputElementSize = ComputeVertexAttributeStride(attrib); + streamOffset = attrib.offset + outputElementSize * start; + } + else if (staticBuffer) + { + if (!staticBuffer->getVertexBuffer()->getSpaceRequired(attrib, 1, 0, &outputElementSize)) + { + return GL_OUT_OF_MEMORY; + } + + if (!staticBuffer->lookupAttribute(attrib, &streamOffset)) + { + // Convert the entire buffer + int totalCount = ElementsInBuffer(attrib, storage->getSize()); + int startIndex = attrib.offset / ComputeVertexAttributeStride(attrib); + + if (!staticBuffer->storeVertexAttributes(attrib, currentValue, -startIndex, totalCount, + 0, &streamOffset)) + { + return GL_OUT_OF_MEMORY; + } + } + + unsigned int firstElementOffset = (attrib.offset / ComputeVertexAttributeStride(attrib)) * outputElementSize; + unsigned int startOffset = (instances == 0 || attrib.divisor == 0) ? start * outputElementSize : 0; + if (streamOffset + firstElementOffset + startOffset < streamOffset) + { + return GL_OUT_OF_MEMORY; + } + + streamOffset += firstElementOffset + startOffset; + } + else + { + int totalCount = StreamingBufferElementCount(attrib, count, instances); + if (!mStreamingBuffer->getVertexBuffer()->getSpaceRequired(attrib, 1, 0, &outputElementSize) || + !mStreamingBuffer->storeVertexAttributes(attrib, currentValue, start, totalCount, instances, + &streamOffset)) + { + return GL_OUT_OF_MEMORY; + } + } + + translated->storage = directStorage ? storage : NULL; + translated->vertexBuffer = vertexBuffer->getVertexBuffer(); + translated->serial = directStorage ? storage->getSerial() : vertexBuffer->getSerial(); + translated->divisor = attrib.divisor; + + translated->attribute = &attrib; + translated->currentValueType = currentValue.Type; + translated->stride = outputElementSize; + translated->offset = streamOffset; + + return GL_NO_ERROR; +} + +GLenum VertexDataManager::storeCurrentValue(const gl::VertexAttribute &attrib, + const gl::VertexAttribCurrentValueData ¤tValue, + TranslatedAttribute *translated, + gl::VertexAttribCurrentValueData *cachedValue, + size_t *cachedOffset, + StreamingVertexBufferInterface *buffer) +{ + if (*cachedValue != currentValue) + { + if (!buffer->reserveVertexSpace(attrib, 1, 0)) + { + return GL_OUT_OF_MEMORY; + } + + unsigned int streamOffset; + if (!buffer->storeVertexAttributes(attrib, currentValue, 0, 1, 0, &streamOffset)) + { + return GL_OUT_OF_MEMORY; + } + + *cachedValue = currentValue; + *cachedOffset = streamOffset; + } + + translated->storage = NULL; + translated->vertexBuffer = buffer->getVertexBuffer(); + translated->serial = buffer->getSerial(); + translated->divisor = 0; + + translated->attribute = &attrib; + translated->currentValueType = currentValue.Type; + translated->stride = 0; + translated->offset = *cachedOffset; + + return GL_NO_ERROR; +} + +} diff --git a/gfx/angle/src/libGLESv2/renderer/VertexDataManager.h b/gfx/angle/src/libGLESv2/renderer/d3d/VertexDataManager.h similarity index 55% rename from gfx/angle/src/libGLESv2/renderer/VertexDataManager.h rename to gfx/angle/src/libGLESv2/renderer/d3d/VertexDataManager.h index 1a69245b9454..9b27a44b8d0e 100644 --- a/gfx/angle/src/libGLESv2/renderer/VertexDataManager.h +++ b/gfx/angle/src/libGLESv2/renderer/d3d/VertexDataManager.h @@ -16,20 +16,23 @@ namespace gl { -class VertexAttribute; +struct VertexAttribute; class ProgramBinary; struct VertexAttribCurrentValueData; } namespace rx { -class BufferStorage; +class BufferD3D; class StreamingVertexBufferInterface; class VertexBuffer; class Renderer; struct TranslatedAttribute { + TranslatedAttribute() : active(false), attribute(NULL), currentValueType(GL_NONE), + offset(0), stride(0), vertexBuffer(NULL), storage(NULL), + serial(0), divisor(0) {}; bool active; const gl::VertexAttribute *attribute; @@ -38,7 +41,7 @@ struct TranslatedAttribute unsigned int stride; // 0 means not to advance the read pointer at all VertexBuffer *vertexBuffer; - BufferStorage *storage; + BufferD3D *storage; unsigned int serial; unsigned int divisor; }; @@ -55,6 +58,28 @@ class VertexDataManager private: DISALLOW_COPY_AND_ASSIGN(VertexDataManager); + bool reserveSpaceForAttrib(const gl::VertexAttribute &attrib, + const gl::VertexAttribCurrentValueData ¤tValue, + GLsizei count, + GLsizei instances) const; + + void invalidateMatchingStaticData(const gl::VertexAttribute &attrib, + const gl::VertexAttribCurrentValueData ¤tValue) const; + + GLenum storeAttribute(const gl::VertexAttribute &attrib, + const gl::VertexAttribCurrentValueData ¤tValue, + TranslatedAttribute *translated, + GLint start, + GLsizei count, + GLsizei instances); + + GLenum storeCurrentValue(const gl::VertexAttribute &attrib, + const gl::VertexAttribCurrentValueData ¤tValue, + TranslatedAttribute *translated, + gl::VertexAttribCurrentValueData *cachedValue, + size_t *cachedOffset, + StreamingVertexBufferInterface *buffer); + rx::Renderer *const mRenderer; StreamingVertexBufferInterface *mStreamingBuffer; diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/Blit11.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp similarity index 90% rename from gfx/angle/src/libGLESv2/renderer/d3d11/Blit11.cpp rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp index 9a4171393017..edbc169367bc 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d11/Blit11.cpp +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp @@ -1,4 +1,3 @@ -#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 @@ -7,56 +6,56 @@ // Blit11.cpp: Texture copy utility class. +#include "libGLESv2/renderer/d3d/d3d11/Blit11.h" +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" +#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" +#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" #include "libGLESv2/main.h" #include "libGLESv2/formatutils.h" -#include "libGLESv2/renderer/d3d11/Blit11.h" -#include "libGLESv2/renderer/d3d11/Renderer11.h" -#include "libGLESv2/renderer/d3d11/renderer11_utils.h" -#include "libGLESv2/renderer/d3d11/formatutils11.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthrough2d11vs.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughdepth2d11ps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba2d11ps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba2dui11ps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba2di11ps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgb2d11ps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgb2dui11ps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgb2di11ps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrg2d11ps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrg2dui11ps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrg2di11ps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughr2d11ps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughr2dui11ps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughr2di11ps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughlum2d11ps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughlumalpha2d11ps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughdepth2d11ps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dui11ps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2di11ps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2d11ps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dui11ps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2di11ps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2d11ps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dui11ps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2di11ps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2d11ps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2dui11ps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2di11ps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlum2d11ps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2d11ps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthrough3d11vs.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthrough3d11gs.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba3d11ps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba3dui11ps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba3di11ps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgb3d11ps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgb3dui11ps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgb3di11ps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrg3d11ps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrg3dui11ps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrg3di11ps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughr3d11ps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughr3dui11ps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughr3di11ps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughlum3d11ps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughlumalpha3d11ps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough3d11vs.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough3d11gs.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d11ps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dui11ps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3di11ps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3d11ps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dui11ps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3di11ps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3d11ps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dui11ps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3di11ps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3d11ps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3dui11ps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3di11ps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlum3d11ps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha3d11ps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/swizzlef2dps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/swizzlei2dps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/swizzleui2dps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/swizzlef3dps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/swizzlei3dps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/swizzleui3dps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/swizzlef2darrayps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/swizzlei2darrayps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/swizzleui2darrayps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlef2dps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzleui2dps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlef3dps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlei3dps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzleui3dps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlef2darrayps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlei2darrayps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzleui2darrayps.h" namespace rx { @@ -186,7 +185,7 @@ Blit11::Blit11(rx::Renderer11 *renderer) D3D11_BUFFER_DESC vbDesc; vbDesc.ByteWidth = std::max(sizeof(d3d11::PositionLayerTexCoord3DVertex), sizeof(d3d11::PositionTexCoordVertex)) * - 6 * renderer->getMaxTextureDepth(); + 6 * renderer->getRendererCaps().max3DTextureSize; vbDesc.Usage = D3D11_USAGE_DYNAMIC; vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; @@ -377,10 +376,12 @@ bool Blit11::swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderTarget D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc; source->GetDesc(&sourceSRVDesc); - GLenum sourceInternalFormat = d3d11_gl::GetInternalFormat(sourceSRVDesc.Format, mRenderer->getCurrentClientVersion()); + + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(sourceSRVDesc.Format); + const gl::InternalFormat &sourceFormatInfo = gl::GetInternalFormatInfo(dxgiFormatInfo.internalFormat); GLenum shaderType = GL_NONE; - switch (gl::GetComponentType(sourceInternalFormat, mRenderer->getCurrentClientVersion())) + switch (sourceFormatInfo.componentType) { case GL_UNSIGNED_NORMALIZED: case GL_SIGNED_NORMALIZED: @@ -516,11 +517,13 @@ bool Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &source // be GL_XXXX_INTEGER but it does not tell us if it is signed or unsigned. D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc; source->GetDesc(&sourceSRVDesc); - GLenum sourceInternalFormat = d3d11_gl::GetInternalFormat(sourceSRVDesc.Format, mRenderer->getCurrentClientVersion()); + + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(sourceSRVDesc.Format); + const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(dxgiFormatInfo.internalFormat); BlitParameters parameters = { 0 }; parameters.mDestinationFormat = destFormat; - parameters.mSignedInteger = gl::GetComponentType(sourceInternalFormat, mRenderer->getCurrentClientVersion()) == GL_INT; + parameters.mSignedInteger = (internalFormatInfo.componentType == GL_INT); parameters.m3DBlit = sourceArea.depth > 1; BlitShaderMap::const_iterator i = mBlitShaderMap.find(parameters); @@ -766,18 +769,19 @@ bool Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubreso DXGI_FORMAT format = GetTextureFormat(source); ASSERT(format == GetTextureFormat(dest)); - unsigned int pixelSize = d3d11::GetFormatPixelBytes(format); + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(format); + unsigned int pixelSize = dxgiFormatInfo.pixelBytes; unsigned int copyOffset = 0; unsigned int copySize = pixelSize; if (stencilOnly) { - copyOffset = d3d11::GetStencilOffset(format) / 8; - copySize = d3d11::GetStencilBits(format) / 8; + copyOffset = dxgiFormatInfo.depthBits / 8; + copySize = dxgiFormatInfo.stencilBits / 8; // It would be expensive to have non-byte sized stencil sizes since it would // require reading from the destination, currently there aren't any though. - ASSERT(d3d11::GetStencilBits(format) % 8 == 0 && - d3d11::GetStencilOffset(format) % 8 == 0); + ASSERT(dxgiFormatInfo.stencilBits % 8 == 0 && + dxgiFormatInfo.depthBits % 8 == 0); } D3D11_MAPPED_SUBRESOURCE sourceMapping, destMapping; diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/Blit11.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.h similarity index 99% rename from gfx/angle/src/libGLESv2/renderer/d3d11/Blit11.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.h index fba89e20ba89..4e57042f75b5 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d11/Blit11.h +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.h @@ -12,6 +12,8 @@ #include "common/angleutils.h" #include "libGLESv2/angletypes.h" +#include + namespace rx { class Renderer11; diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp similarity index 62% rename from gfx/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.cpp rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp index c0f8e00d83aa..b84e77c34768 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.cpp +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp @@ -1,17 +1,15 @@ -#include "precompiled.h" // -// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. +// Copyright 2014 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. +// Buffer11.cpp Defines the Buffer11 class. -#include "libGLESv2/renderer/d3d11/BufferStorage11.h" +#include "libGLESv2/renderer/d3d/d3d11/Buffer11.h" +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" +#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" #include "libGLESv2/main.h" -#include "libGLESv2/renderer/d3d11/Renderer11.h" -#include "libGLESv2/renderer/d3d11/formatutils11.h" -#include "libGLESv2/Buffer.h" namespace rx { @@ -69,15 +67,15 @@ D3D11_MAP GetD3DMapTypeFromBits(GLbitfield access) } -// Each instance of BufferStorageD3DBuffer11 is specialized for a class of D3D binding points +// Each instance of Buffer11::BufferStorage11 is specialized for a class of D3D binding points // - vertex/transform feedback buffers // - index buffers // - pixel unpack buffers // - uniform buffers -class BufferStorage11::TypedBufferStorage11 +class Buffer11::BufferStorage11 { public: - virtual ~TypedBufferStorage11() {} + virtual ~BufferStorage11() {} DataRevision getDataRevision() const { return mRevision; } BufferUsage getUsage() const { return mUsage; } @@ -86,15 +84,15 @@ class BufferStorage11::TypedBufferStorage11 void setDataRevision(DataRevision rev) { mRevision = rev; } - virtual bool copyFromStorage(TypedBufferStorage11 *source, size_t sourceOffset, + virtual bool copyFromStorage(BufferStorage11 *source, size_t sourceOffset, size_t size, size_t destOffset) = 0; virtual bool resize(size_t size, bool preserveData) = 0; - virtual void *map(GLbitfield access) = 0; + virtual void *map(size_t offset, size_t length, GLbitfield access) = 0; virtual void unmap() = 0; protected: - TypedBufferStorage11(Renderer11 *renderer, BufferUsage usage); + BufferStorage11(Renderer11 *renderer, BufferUsage usage); Renderer11 *mRenderer; DataRevision mRevision; @@ -104,7 +102,7 @@ class BufferStorage11::TypedBufferStorage11 // A native buffer storage represents an underlying D3D11 buffer for a particular // type of storage. -class BufferStorage11::NativeBuffer11 : public BufferStorage11::TypedBufferStorage11 +class Buffer11::NativeBuffer11 : public Buffer11::BufferStorage11 { public: NativeBuffer11(Renderer11 *renderer, BufferUsage usage); @@ -112,13 +110,15 @@ class BufferStorage11::NativeBuffer11 : public BufferStorage11::TypedBufferStora ID3D11Buffer *getNativeBuffer() const { return mNativeBuffer; } - virtual bool copyFromStorage(TypedBufferStorage11 *source, size_t sourceOffset, + virtual bool copyFromStorage(BufferStorage11 *source, size_t sourceOffset, size_t size, size_t destOffset); virtual bool resize(size_t size, bool preserveData); - virtual void *map(GLbitfield access); + virtual void *map(size_t offset, size_t length, GLbitfield access); virtual void unmap(); + bool setData(D3D11_MAP mapMode, const uint8_t *data, size_t size, size_t offset); + private: ID3D11Buffer *mNativeBuffer; @@ -127,17 +127,17 @@ class BufferStorage11::NativeBuffer11 : public BufferStorage11::TypedBufferStora // Pack storage represents internal storage for pack buffers. We implement pack buffers // as CPU memory, tied to a staging texture, for asynchronous texture readback. -class BufferStorage11::PackStorage11 : public BufferStorage11::TypedBufferStorage11 +class Buffer11::PackStorage11 : public Buffer11::BufferStorage11 { public: PackStorage11(Renderer11 *renderer); ~PackStorage11(); - virtual bool copyFromStorage(TypedBufferStorage11 *source, size_t sourceOffset, + virtual bool copyFromStorage(BufferStorage11 *source, size_t sourceOffset, size_t size, size_t destOffset); virtual bool resize(size_t size, bool preserveData); - virtual void *map(GLbitfield access); + virtual void *map(size_t offset, size_t length, GLbitfield access); virtual void unmap(); void packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams ¶ms); @@ -149,36 +149,59 @@ class BufferStorage11::PackStorage11 : public BufferStorage11::TypedBufferStorag ID3D11Texture2D *mStagingTexture; DXGI_FORMAT mTextureFormat; gl::Extents mTextureSize; - std::vector mMemoryBuffer; + MemoryBuffer mMemoryBuffer; PackPixelsParams *mQueuedPackCommand; PackPixelsParams mPackParams; bool mDataModified; }; -BufferStorage11::BufferStorage11(Renderer11 *renderer) - : mRenderer(renderer), + +Buffer11::Buffer11(Renderer11 *renderer) + : BufferD3D(), + mRenderer(renderer), + mSize(0), mMappedStorage(NULL), mResolvedDataRevision(0), mReadUsageCount(0), - mSize(0) -{ -} + mDynamicUsage(0), + mDynamicDirtyRange(std::numeric_limits::max(), std::numeric_limits::min()) +{} -BufferStorage11::~BufferStorage11() +Buffer11::~Buffer11() { - for (auto it = mTypedBuffers.begin(); it != mTypedBuffers.end(); it++) + for (auto it = mBufferStorages.begin(); it != mBufferStorages.end(); it++) { SafeDelete(it->second); } } -BufferStorage11 *BufferStorage11::makeBufferStorage11(BufferStorage *bufferStorage) +Buffer11 *Buffer11::makeBuffer11(BufferImpl *buffer) { - ASSERT(HAS_DYNAMIC_TYPE(BufferStorage11*, bufferStorage)); - return static_cast(bufferStorage); + ASSERT(HAS_DYNAMIC_TYPE(Buffer11*, buffer)); + return static_cast(buffer); } -void *BufferStorage11::getData() +void Buffer11::setData(const void *data, size_t size, GLenum usage) +{ + mDynamicUsage = (usage == GL_DYNAMIC_DRAW); + + if (mDynamicUsage) + { + if (!mDynamicData.resize(size)) + { + return gl::error(GL_OUT_OF_MEMORY); + } + } + + setSubData(data, size, 0); + + if (usage == GL_STATIC_DRAW) + { + initializeStaticData(); + } +} + +void *Buffer11::getData() { NativeBuffer11 *stagingBuffer = getStagingBuffer(); @@ -192,7 +215,10 @@ void *BufferStorage11::getData() { if (stagingBuffer->getSize() > mResolvedData.size()) { - mResolvedData.resize(stagingBuffer->getSize()); + if (!mResolvedData.resize(stagingBuffer->getSize())) + { + return gl::error(GL_OUT_OF_MEMORY, (void*)NULL); + } } ID3D11DeviceContext *context = mRenderer->getDeviceContext(); @@ -216,13 +242,23 @@ void *BufferStorage11::getData() return mResolvedData.data(); } -void BufferStorage11::setData(const void* data, size_t size, size_t offset) +void Buffer11::setSubData(const void *data, size_t size, size_t offset) { size_t requiredSize = size + offset; mSize = std::max(mSize, requiredSize); - if (data) + invalidateStaticData(); + + if (data && size > 0) { + if (mDynamicUsage) + { + mDynamicDirtyRange.start = std::min(mDynamicDirtyRange.start, offset); + mDynamicDirtyRange.end = std::max(mDynamicDirtyRange.end, size + offset); + memcpy(mDynamicData.data() + offset, data, size); + return; + } + NativeBuffer11 *stagingBuffer = getStagingBuffer(); if (!stagingBuffer) @@ -243,84 +279,115 @@ void BufferStorage11::setData(const void* data, size_t size, size_t offset) } } - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - - D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT result = context->Map(stagingBuffer->getNativeBuffer(), 0, D3D11_MAP_WRITE, 0, &mappedResource); - if (FAILED(result)) - { - return gl::error(GL_OUT_OF_MEMORY); - } - - unsigned char *offsetBufferPointer = reinterpret_cast(mappedResource.pData) + offset; - memcpy(offsetBufferPointer, data, size); - - context->Unmap(stagingBuffer->getNativeBuffer(), 0); - + stagingBuffer->setData(D3D11_MAP_WRITE, reinterpret_cast(data), size, offset); stagingBuffer->setDataRevision(stagingBuffer->getDataRevision() + 1); } } -void BufferStorage11::copyData(BufferStorage* sourceStorage, size_t size, size_t sourceOffset, size_t destOffset) +void Buffer11::copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) { - BufferStorage11* sourceStorage11 = makeBufferStorage11(sourceStorage); - if (sourceStorage11) + Buffer11 *sourceBuffer = makeBuffer11(source); + if (sourceBuffer) { - TypedBufferStorage11 *dest = getLatestStorage(); + BufferStorage11 *dest = getLatestBufferStorage(); if (!dest) { dest = getStagingBuffer(); } - TypedBufferStorage11 *source = sourceStorage11->getLatestStorage(); + BufferStorage11 *source = sourceBuffer->getLatestBufferStorage(); if (source && dest) { // If copying to/from a pixel pack buffer, we must have a staging or // pack buffer partner, because other native buffers can't be mapped if (dest->getUsage() == BUFFER_USAGE_PIXEL_PACK && !source->isMappable()) { - source = sourceStorage11->getStagingBuffer(); + source = sourceBuffer->getStagingBuffer(); } else if (source->getUsage() == BUFFER_USAGE_PIXEL_PACK && !dest->isMappable()) { dest = getStagingBuffer(); } + // D3D11 does not allow overlapped copies until 11.1, and only if the + // device supports D3D11_FEATURE_DATA_D3D11_OPTIONS::CopyWithOverlap + // Get around this via a different source buffer + if (source == dest) + { + if (source->getUsage() == BUFFER_USAGE_STAGING) + { + source = getBufferStorage(BUFFER_USAGE_VERTEX); + } + else + { + source = getStagingBuffer(); + } + } + dest->copyFromStorage(source, sourceOffset, size, destOffset); dest->setDataRevision(dest->getDataRevision() + 1); } mSize = std::max(mSize, destOffset + size); } + + invalidateStaticData(); } -void BufferStorage11::clear() +GLvoid *Buffer11::map(size_t offset, size_t length, GLbitfield access) { - mSize = 0; - mResolvedDataRevision = 0; + ASSERT(!mMappedStorage); + + BufferStorage11 *latestStorage = getLatestBufferStorage(); + if (latestStorage && + (latestStorage->getUsage() == BUFFER_USAGE_PIXEL_PACK || + latestStorage->getUsage() == BUFFER_USAGE_STAGING)) + { + // Latest storage is mappable. + mMappedStorage = latestStorage; + } + else + { + // Fall back to using the staging buffer if the latest storage does + // not exist or is not CPU-accessible. + mMappedStorage = getStagingBuffer(); + } + + if (!mMappedStorage) + { + // Out-of-memory + return NULL; + } + + if ((access & GL_MAP_WRITE_BIT) > 0) + { + // Update the data revision immediately, since the data might be changed at any time + mMappedStorage->setDataRevision(mMappedStorage->getDataRevision() + 1); + } + + return mMappedStorage->map(offset, length, access); } -void BufferStorage11::markTransformFeedbackUsage() +void Buffer11::unmap() { - TypedBufferStorage11 *transformFeedbackStorage = getStorage(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK); + ASSERT(mMappedStorage); + mMappedStorage->unmap(); + mMappedStorage = NULL; +} + +void Buffer11::markTransformFeedbackUsage() +{ + BufferStorage11 *transformFeedbackStorage = getBufferStorage(BUFFER_USAGE_TRANSFORM_FEEDBACK); if (transformFeedbackStorage) { transformFeedbackStorage->setDataRevision(transformFeedbackStorage->getDataRevision() + 1); } + + invalidateStaticData(); } -size_t BufferStorage11::getSize() const -{ - return mSize; -} - -bool BufferStorage11::supportsDirectBinding() const -{ - return true; -} - -void BufferStorage11::markBufferUsage() +void Buffer11::markBufferUsage() { mReadUsageCount++; @@ -333,26 +400,31 @@ void BufferStorage11::markBufferUsage() } } -ID3D11Buffer *BufferStorage11::getBuffer(BufferUsage usage) +Renderer* Buffer11::getRenderer() +{ + return mRenderer; +} + +ID3D11Buffer *Buffer11::getBuffer(BufferUsage usage) { markBufferUsage(); - TypedBufferStorage11 *typedBuffer = getStorage(usage); + BufferStorage11 *bufferStorage = getBufferStorage(usage); - if (!typedBuffer) + if (!bufferStorage) { // Storage out-of-memory return NULL; } - ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, typedBuffer)); + ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, bufferStorage)); - return static_cast(typedBuffer)->getNativeBuffer(); + return static_cast(bufferStorage)->getNativeBuffer(); } -ID3D11ShaderResourceView *BufferStorage11::getSRV(DXGI_FORMAT srvFormat) +ID3D11ShaderResourceView *Buffer11::getSRV(DXGI_FORMAT srvFormat) { - TypedBufferStorage11 *storage = getStorage(BUFFER_USAGE_PIXEL_UNPACK); + BufferStorage11 *storage = getBufferStorage(BUFFER_USAGE_PIXEL_UNPACK); if (!storage) { @@ -381,9 +453,11 @@ ID3D11ShaderResourceView *BufferStorage11::getSRV(DXGI_FORMAT srvFormat) ID3D11Device *device = mRenderer->getDevice(); ID3D11ShaderResourceView *bufferSRV = NULL; + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(srvFormat); + D3D11_SHADER_RESOURCE_VIEW_DESC bufferSRVDesc; bufferSRVDesc.Buffer.ElementOffset = 0; - bufferSRVDesc.Buffer.ElementWidth = mSize / d3d11::GetFormatPixelBytes(srvFormat); + bufferSRVDesc.Buffer.ElementWidth = mSize / dxgiFormatInfo.pixelBytes; bufferSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; bufferSRVDesc.Format = srvFormat; @@ -396,11 +470,11 @@ ID3D11ShaderResourceView *BufferStorage11::getSRV(DXGI_FORMAT srvFormat) return bufferSRV; } -void BufferStorage11::packPixels(ID3D11Texture2D *srcTexture, UINT srcSubresource, const PackPixelsParams ¶ms) +void Buffer11::packPixels(ID3D11Texture2D *srcTexture, UINT srcSubresource, const PackPixelsParams ¶ms) { PackStorage11 *packStorage = getPackStorage(); - TypedBufferStorage11 *latestStorage = getLatestStorage(); + BufferStorage11 *latestStorage = getLatestBufferStorage(); if (packStorage) { @@ -409,28 +483,56 @@ void BufferStorage11::packPixels(ID3D11Texture2D *srcTexture, UINT srcSubresourc } } -BufferStorage11::TypedBufferStorage11 *BufferStorage11::getStorage(BufferUsage usage) +Buffer11::BufferStorage11 *Buffer11::getBufferStorage(BufferUsage requestedUsage) { - TypedBufferStorage11 *directBuffer = NULL; - auto directBufferIt = mTypedBuffers.find(usage); - if (directBufferIt != mTypedBuffers.end()) + ASSERT(requestedUsage != BUFFER_USAGE_VERTEX_DYNAMIC); + ASSERT(requestedUsage != BUFFER_USAGE_INDEX_DYNAMIC); + + BufferUsage internalUsage = requestedUsage; + + if (mDynamicUsage) + { + if (requestedUsage == BUFFER_USAGE_VERTEX) + { + internalUsage = BUFFER_USAGE_VERTEX_DYNAMIC; + } + else if (requestedUsage == BUFFER_USAGE_INDEX) + { + internalUsage = BUFFER_USAGE_INDEX_DYNAMIC; + } + else + { + // Convert out of dynamic usage + setData(mDynamicData.data(), mDynamicData.size(), GL_STATIC_DRAW); + } + } + + // Internally we share the same NativeBuffer11 for stream out and vertex data + if (requestedUsage == BUFFER_USAGE_TRANSFORM_FEEDBACK) + { + internalUsage = BUFFER_USAGE_VERTEX; + } + + BufferStorage11 *directBuffer = NULL; + auto directBufferIt = mBufferStorages.find(internalUsage); + if (directBufferIt != mBufferStorages.end()) { directBuffer = directBufferIt->second; } if (!directBuffer) { - if (usage == BUFFER_USAGE_PIXEL_PACK) + if (internalUsage == BUFFER_USAGE_PIXEL_PACK) { directBuffer = new PackStorage11(mRenderer); } else { // buffer is not allocated, create it - directBuffer = new NativeBuffer11(mRenderer, usage); + directBuffer = new NativeBuffer11(mRenderer, internalUsage); } - mTypedBuffers.insert(std::make_pair(usage, directBuffer)); + mBufferStorages.insert(std::make_pair(internalUsage, directBuffer)); } // resize buffer @@ -443,7 +545,19 @@ BufferStorage11::TypedBufferStorage11 *BufferStorage11::getStorage(BufferUsage u } } - TypedBufferStorage11 *latestBuffer = getLatestStorage(); + if (mDynamicUsage) + { + if (!mDynamicData.empty() && mDynamicDirtyRange.length() > 0) + { + ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, directBuffer)); + NativeBuffer11 *dynamicBuffer = static_cast(directBuffer); + dynamicBuffer->setData(D3D11_MAP_WRITE_NO_OVERWRITE, mDynamicData.data(), mDynamicDirtyRange.length(), mDynamicDirtyRange.start); + } + + return directBuffer; + } + + BufferStorage11 *latestBuffer = getLatestBufferStorage(); if (latestBuffer && latestBuffer->getDataRevision() > directBuffer->getDataRevision()) { // if copying from a pack buffer to a non-staging native buffer, we must first @@ -470,15 +584,15 @@ BufferStorage11::TypedBufferStorage11 *BufferStorage11::getStorage(BufferUsage u return directBuffer; } -BufferStorage11::TypedBufferStorage11 *BufferStorage11::getLatestStorage() const +Buffer11::BufferStorage11 *Buffer11::getLatestBufferStorage() const { // Even though we iterate over all the direct buffers, it is expected that only // 1 or 2 will be present. - TypedBufferStorage11 *latestStorage = NULL; + BufferStorage11 *latestStorage = NULL; DataRevision latestRevision = 0; - for (auto it = mTypedBuffers.begin(); it != mTypedBuffers.end(); it++) + for (auto it = mBufferStorages.begin(); it != mBufferStorages.end(); it++) { - TypedBufferStorage11 *storage = it->second; + BufferStorage11 *storage = it->second; if (!latestStorage || storage->getDataRevision() > latestRevision) { latestStorage = storage; @@ -489,47 +603,9 @@ BufferStorage11::TypedBufferStorage11 *BufferStorage11::getLatestStorage() const return latestStorage; } -bool BufferStorage11::isMapped() const +Buffer11::NativeBuffer11 *Buffer11::getStagingBuffer() { - return mMappedStorage != NULL; -} - -void *BufferStorage11::map(GLbitfield access) -{ - ASSERT(!mMappedStorage); - - TypedBufferStorage11 *latestStorage = getLatestStorage(); - ASSERT(latestStorage); - - if (latestStorage->getUsage() == BUFFER_USAGE_PIXEL_PACK || - latestStorage->getUsage() == BUFFER_USAGE_STAGING) - { - mMappedStorage = latestStorage; - } - else - { - mMappedStorage = getStagingBuffer(); - } - - if (!mMappedStorage) - { - // Out-of-memory - return NULL; - } - - return mMappedStorage->map(access); -} - -void BufferStorage11::unmap() -{ - ASSERT(mMappedStorage); - mMappedStorage->unmap(); - mMappedStorage = NULL; -} - -BufferStorage11::NativeBuffer11 *BufferStorage11::getStagingBuffer() -{ - TypedBufferStorage11 *stagingStorage = getStorage(BUFFER_USAGE_STAGING); + BufferStorage11 *stagingStorage = getBufferStorage(BUFFER_USAGE_STAGING); if (!stagingStorage) { @@ -541,9 +617,9 @@ BufferStorage11::NativeBuffer11 *BufferStorage11::getStagingBuffer() return static_cast(stagingStorage); } -BufferStorage11::PackStorage11 *BufferStorage11::getPackStorage() +Buffer11::PackStorage11 *Buffer11::getPackStorage() { - TypedBufferStorage11 *packStorage = getStorage(BUFFER_USAGE_PIXEL_PACK); + BufferStorage11 *packStorage = getBufferStorage(BUFFER_USAGE_PIXEL_PACK); if (!packStorage) { @@ -555,7 +631,7 @@ BufferStorage11::PackStorage11 *BufferStorage11::getPackStorage() return static_cast(packStorage); } -BufferStorage11::TypedBufferStorage11::TypedBufferStorage11(Renderer11 *renderer, BufferUsage usage) +Buffer11::BufferStorage11::BufferStorage11(Renderer11 *renderer, BufferUsage usage) : mRenderer(renderer), mUsage(usage), mRevision(0), @@ -563,20 +639,20 @@ BufferStorage11::TypedBufferStorage11::TypedBufferStorage11(Renderer11 *renderer { } -BufferStorage11::NativeBuffer11::NativeBuffer11(Renderer11 *renderer, BufferUsage usage) - : TypedBufferStorage11(renderer, usage), +Buffer11::NativeBuffer11::NativeBuffer11(Renderer11 *renderer, BufferUsage usage) + : BufferStorage11(renderer, usage), mNativeBuffer(NULL) { } -BufferStorage11::NativeBuffer11::~NativeBuffer11() +Buffer11::NativeBuffer11::~NativeBuffer11() { SafeRelease(mNativeBuffer); } // Returns true if it recreates the direct buffer -bool BufferStorage11::NativeBuffer11::copyFromStorage(TypedBufferStorage11 *source, size_t sourceOffset, - size_t size, size_t destOffset) +bool Buffer11::NativeBuffer11::copyFromStorage(BufferStorage11 *source, size_t sourceOffset, + size_t size, size_t destOffset) { ID3D11DeviceContext *context = mRenderer->getDeviceContext(); @@ -594,7 +670,7 @@ bool BufferStorage11::NativeBuffer11::copyFromStorage(TypedBufferStorage11 *sour { ASSERT(HAS_DYNAMIC_TYPE(PackStorage11*, source)); - unsigned char *sourcePointer = static_cast(source->map(GL_MAP_READ_BIT)) + sourceOffset; + void *sourcePointer = source->map(sourceOffset, size, GL_MAP_READ_BIT); D3D11_MAPPED_SUBRESOURCE mappedResource; HRESULT hr = context->Map(mNativeBuffer, 0, D3D11_MAP_WRITE, 0, &mappedResource); @@ -628,7 +704,7 @@ bool BufferStorage11::NativeBuffer11::copyFromStorage(TypedBufferStorage11 *sour return createBuffer; } -bool BufferStorage11::NativeBuffer11::resize(size_t size, bool preserveData) +bool Buffer11::NativeBuffer11::resize(size_t size, bool preserveData) { ID3D11Device *device = mRenderer->getDevice(); ID3D11DeviceContext *context = mRenderer->getDeviceContext(); @@ -646,9 +722,12 @@ bool BufferStorage11::NativeBuffer11::resize(size_t size, bool preserveData) if (mNativeBuffer && preserveData) { + // We don't call resize if the buffer is big enough already. + ASSERT(mBufferSize <= size); + D3D11_BOX srcBox; srcBox.left = 0; - srcBox.right = size; + srcBox.right = mBufferSize; srcBox.top = 0; srcBox.bottom = 1; srcBox.front = 0; @@ -666,7 +745,7 @@ bool BufferStorage11::NativeBuffer11::resize(size_t size, bool preserveData) return true; } -void BufferStorage11::NativeBuffer11::fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer *renderer, +void Buffer11::NativeBuffer11::fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer *renderer, BufferUsage usage, unsigned int bufferSize) { bufferDesc->ByteWidth = bufferSize; @@ -681,7 +760,8 @@ void BufferStorage11::NativeBuffer11::fillBufferDesc(D3D11_BUFFER_DESC* bufferDe bufferDesc->CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; break; - case BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK: + case BUFFER_USAGE_VERTEX: + case BUFFER_USAGE_TRANSFORM_FEEDBACK: bufferDesc->Usage = D3D11_USAGE_DEFAULT; bufferDesc->BindFlags = D3D11_BIND_VERTEX_BUFFER | D3D11_BIND_STREAM_OUTPUT; bufferDesc->CPUAccessFlags = 0; @@ -707,7 +787,19 @@ void BufferStorage11::NativeBuffer11::fillBufferDesc(D3D11_BUFFER_DESC* bufferDe // Constant buffers must be of a limited size, and aligned to 16 byte boundaries // For our purposes we ignore any buffer data past the maximum constant buffer size bufferDesc->ByteWidth = roundUp(bufferDesc->ByteWidth, 16u); - bufferDesc->ByteWidth = std::min(bufferDesc->ByteWidth, renderer->getMaxUniformBufferSize()); + bufferDesc->ByteWidth = std::min(bufferDesc->ByteWidth, renderer->getRendererCaps().maxUniformBlockSize); + break; + + case BUFFER_USAGE_VERTEX_DYNAMIC: + bufferDesc->Usage = D3D11_USAGE_DYNAMIC; + bufferDesc->BindFlags = D3D11_BIND_VERTEX_BUFFER; + bufferDesc->CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + break; + + case BUFFER_USAGE_INDEX_DYNAMIC: + bufferDesc->Usage = D3D11_USAGE_DYNAMIC; + bufferDesc->BindFlags = D3D11_BIND_INDEX_BUFFER; + bufferDesc->CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; break; default: @@ -715,7 +807,7 @@ void BufferStorage11::NativeBuffer11::fillBufferDesc(D3D11_BUFFER_DESC* bufferDe } } -void *BufferStorage11::NativeBuffer11::map(GLbitfield access) +void *Buffer11::NativeBuffer11::map(size_t offset, size_t length, GLbitfield access) { ASSERT(mUsage == BUFFER_USAGE_STAGING); @@ -728,18 +820,37 @@ void *BufferStorage11::NativeBuffer11::map(GLbitfield access) UNUSED_ASSERTION_VARIABLE(result); ASSERT(SUCCEEDED(result)); - return mappedResource.pData; + return static_cast(mappedResource.pData) + offset; } -void BufferStorage11::NativeBuffer11::unmap() +bool Buffer11::NativeBuffer11::setData(D3D11_MAP mapMode, const uint8_t *data, size_t size, size_t offset) +{ + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT result = context->Map(mNativeBuffer, 0, mapMode, 0, &mappedResource); + if (FAILED(result)) + { + return gl::error(GL_OUT_OF_MEMORY, false); + } + + uint8_t *offsetBufferPointer = reinterpret_cast(mappedResource.pData) + offset; + memcpy(offsetBufferPointer, data, size); + + context->Unmap(mNativeBuffer, 0); + + return true; +} + +void Buffer11::NativeBuffer11::unmap() { ASSERT(mUsage == BUFFER_USAGE_STAGING); ID3D11DeviceContext *context = mRenderer->getDeviceContext(); context->Unmap(mNativeBuffer, 0); } -BufferStorage11::PackStorage11::PackStorage11(Renderer11 *renderer) - : TypedBufferStorage11(renderer, BUFFER_USAGE_PIXEL_PACK), +Buffer11::PackStorage11::PackStorage11(Renderer11 *renderer) + : BufferStorage11(renderer, BUFFER_USAGE_PIXEL_PACK), mStagingTexture(NULL), mTextureFormat(DXGI_FORMAT_UNKNOWN), mQueuedPackCommand(NULL), @@ -747,32 +858,38 @@ BufferStorage11::PackStorage11::PackStorage11(Renderer11 *renderer) { } -BufferStorage11::PackStorage11::~PackStorage11() +Buffer11::PackStorage11::~PackStorage11() { SafeRelease(mStagingTexture); SafeDelete(mQueuedPackCommand); } -bool BufferStorage11::PackStorage11::copyFromStorage(TypedBufferStorage11 *source, size_t sourceOffset, - size_t size, size_t destOffset) +bool Buffer11::PackStorage11::copyFromStorage(BufferStorage11 *source, size_t sourceOffset, + size_t size, size_t destOffset) { - UNIMPLEMENTED(); + // We copy through a staging buffer when drawing with a pack buffer, + // or for other cases where we access the pack buffer + UNREACHABLE(); return false; } -bool BufferStorage11::PackStorage11::resize(size_t size, bool preserveData) +bool Buffer11::PackStorage11::resize(size_t size, bool preserveData) { if (size != mBufferSize) { - mMemoryBuffer.resize(size, 0); + if (!mMemoryBuffer.resize(size)) + { + return false; + } mBufferSize = size; } return true; } -void *BufferStorage11::PackStorage11::map(GLbitfield access) +void *Buffer11::PackStorage11::map(size_t offset, size_t length, GLbitfield access) { + ASSERT(offset + length <= getSize()); // TODO: fast path // We might be able to optimize out one or more memcpy calls by detecting when // and if D3D packs the staging texture memory identically to how we would fill @@ -781,15 +898,15 @@ void *BufferStorage11::PackStorage11::map(GLbitfield access) flushQueuedPackCommand(); mDataModified = (mDataModified || (access & GL_MAP_WRITE_BIT) != 0); - return &mMemoryBuffer[0]; + return mMemoryBuffer.data() + offset; } -void BufferStorage11::PackStorage11::unmap() +void Buffer11::PackStorage11::unmap() { // No-op } -void BufferStorage11::PackStorage11::packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams ¶ms) +void Buffer11::PackStorage11::packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams ¶ms) { flushQueuedPackCommand(); mQueuedPackCommand = new PackPixelsParams(params); @@ -834,10 +951,8 @@ void BufferStorage11::PackStorage11::packPixels(ID3D11Texture2D *srcTexure, UINT ASSERT(SUCCEEDED(hr)); } - if (textureDesc.SampleDesc.Count > 1) - { - UNIMPLEMENTED(); - } + // ReadPixels from multisampled FBOs isn't supported in current GL + ASSERT(textureDesc.SampleDesc.Count <= 1); ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); D3D11_BOX srcBox; @@ -852,13 +967,13 @@ void BufferStorage11::PackStorage11::packPixels(ID3D11Texture2D *srcTexure, UINT immediateContext->CopySubresourceRegion(mStagingTexture, 0, 0, 0, 0, srcTexure, srcSubresource, &srcBox); } -void BufferStorage11::PackStorage11::flushQueuedPackCommand() +void Buffer11::PackStorage11::flushQueuedPackCommand() { - ASSERT(!mMemoryBuffer.empty()); + ASSERT(mMemoryBuffer.size() > 0); if (mQueuedPackCommand) { - mRenderer->packPixels(mStagingTexture, *mQueuedPackCommand, &mMemoryBuffer[0]); + mRenderer->packPixels(mStagingTexture, *mQueuedPackCommand, mMemoryBuffer.data()); SafeDelete(mQueuedPackCommand); } } diff --git a/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.h new file mode 100644 index 000000000000..41ab780d0f4b --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.h @@ -0,0 +1,114 @@ +// +// Copyright 2014 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. +// + +// Buffer11.h: Defines the rx::Buffer11 class which implements rx::BufferImpl via rx::BufferD3D. + +#ifndef LIBGLESV2_RENDERER_BUFFER11_H_ +#define LIBGLESV2_RENDERER_BUFFER11_H_ + +#include "libGLESv2/renderer/d3d/BufferD3D.h" +#include "libGLESv2/renderer/d3d/MemoryBuffer.h" +#include "libGLESv2/angletypes.h" + +namespace rx +{ +class Renderer11; + +enum BufferUsage +{ + BUFFER_USAGE_STAGING, + BUFFER_USAGE_VERTEX, + BUFFER_USAGE_TRANSFORM_FEEDBACK, + BUFFER_USAGE_INDEX, + BUFFER_USAGE_PIXEL_UNPACK, + BUFFER_USAGE_PIXEL_PACK, + BUFFER_USAGE_UNIFORM, + + // Internal flags + BUFFER_USAGE_VERTEX_DYNAMIC, + BUFFER_USAGE_INDEX_DYNAMIC +}; + +struct PackPixelsParams +{ + PackPixelsParams(); + PackPixelsParams(const gl::Rectangle &area, GLenum format, GLenum type, GLuint outputPitch, + const gl::PixelPackState &pack, ptrdiff_t offset); + + gl::Rectangle area; + GLenum format; + GLenum type; + GLuint outputPitch; + gl::Buffer *packBuffer; + gl::PixelPackState pack; + ptrdiff_t offset; +}; + +typedef size_t DataRevision; + +class Buffer11 : public BufferD3D +{ + public: + Buffer11(rx::Renderer11 *renderer); + virtual ~Buffer11(); + + static Buffer11 *makeBuffer11(BufferImpl *buffer); + + ID3D11Buffer *getBuffer(BufferUsage usage); + ID3D11ShaderResourceView *getSRV(DXGI_FORMAT srvFormat); + bool isMapped() const { return mMappedStorage != NULL; } + void packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams ¶ms); + + // BufferD3D implementation + virtual size_t getSize() const { return mSize; } + virtual bool supportsDirectBinding() const { return true; } + virtual Renderer* getRenderer(); + + // BufferImpl implementation + virtual void setData(const void* data, size_t size, GLenum usage); + virtual void *getData(); + virtual void setSubData(const void* data, size_t size, size_t offset); + virtual void copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size); + virtual GLvoid* map(size_t offset, size_t length, GLbitfield access); + virtual void unmap(); + virtual void markTransformFeedbackUsage(); + + private: + DISALLOW_COPY_AND_ASSIGN(Buffer11); + + class BufferStorage11; + class NativeBuffer11; + class PackStorage11; + + void markBufferUsage(); + NativeBuffer11 *getStagingBuffer(); + PackStorage11 *getPackStorage(); + + BufferStorage11 *getBufferStorage(BufferUsage usage); + BufferStorage11 *getLatestBufferStorage() const; + + rx::Renderer11 *mRenderer; + size_t mSize; + + BufferStorage11 *mMappedStorage; + + std::map mBufferStorages; + + typedef std::pair BufferSRVPair; + std::map mBufferResourceViews; + + MemoryBuffer mResolvedData; + DataRevision mResolvedDataRevision; + unsigned int mReadUsageCount; + + MemoryBuffer mDynamicData; + bool mDynamicUsage; + Range mDynamicDirtyRange; +}; + +} + +#endif // LIBGLESV2_RENDERER_BUFFER11_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/Clear11.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp similarity index 79% rename from gfx/angle/src/libGLESv2/renderer/d3d11/Clear11.cpp rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp index c02cd9ed2554..ba9970bf47bb 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d11/Clear11.cpp +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp @@ -1,4 +1,3 @@ -#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 @@ -7,23 +6,23 @@ // Clear11.cpp: Framebuffer clear utility class. -#include "libGLESv2/renderer/d3d11/Clear11.h" -#include "libGLESv2/renderer/d3d11/Renderer11.h" -#include "libGLESv2/renderer/d3d11/renderer11_utils.h" -#include "libGLESv2/renderer/d3d11/RenderTarget11.h" - +#include "libGLESv2/renderer/d3d/d3d11/Clear11.h" +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" +#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" +#include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h" #include "libGLESv2/formatutils.h" #include "libGLESv2/Framebuffer.h" -#include "libGLESv2/Renderbuffer.h" +#include "libGLESv2/FramebufferAttachment.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/clearfloat11vs.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/clearfloat11ps.h" +// Precompiled shaders +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearfloat11vs.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/clearuint11vs.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/clearuint11ps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearuint11vs.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearuint11ps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/clearsint11vs.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/clearsint11ps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearsint11vs.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearsint11ps.h" namespace rx { @@ -169,16 +168,16 @@ void Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, gl::Frame gl::Extents framebufferSize; if (frameBuffer->getFirstColorbuffer() != NULL) { - gl::Renderbuffer *renderBuffer = frameBuffer->getFirstColorbuffer(); - framebufferSize.width = renderBuffer->getWidth(); - framebufferSize.height = renderBuffer->getHeight(); + gl::FramebufferAttachment *attachment = frameBuffer->getFirstColorbuffer(); + framebufferSize.width = attachment->getWidth(); + framebufferSize.height = attachment->getHeight(); framebufferSize.depth = 1; } else if (frameBuffer->getDepthOrStencilbuffer() != NULL) { - gl::Renderbuffer *renderBuffer = frameBuffer->getDepthOrStencilbuffer(); - framebufferSize.width = renderBuffer->getWidth(); - framebufferSize.height = renderBuffer->getHeight(); + gl::FramebufferAttachment *attachment = frameBuffer->getDepthOrStencilbuffer(); + framebufferSize.width = attachment->getWidth(); + framebufferSize.height = attachment->getHeight(); framebufferSize.depth = 1; } else @@ -200,9 +199,7 @@ void Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, gl::Frame clearParams.scissor.x + clearParams.scissor.width < framebufferSize.width || clearParams.scissor.y + clearParams.scissor.height < framebufferSize.height); - GLuint clientVersion = mRenderer->getCurrentClientVersion(); - - std::vector maskedClearRenderTargets; + std::vector maskedClearRenderTargets; RenderTarget11* maskedClearDepthStencil = NULL; ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); @@ -211,47 +208,49 @@ void Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, gl::Frame { if (clearParams.clearColor[colorAttachment] && frameBuffer->isEnabledColorAttachment(colorAttachment)) { - gl::Renderbuffer *renderbuffer = frameBuffer->getColorbuffer(colorAttachment); - if (renderbuffer) + gl::FramebufferAttachment *attachment = frameBuffer->getColorbuffer(colorAttachment); + if (attachment) { - RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(renderbuffer->getRenderTarget()); + RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(attachment->getRenderTarget()); if (!renderTarget) { ERR("Render target pointer unexpectedly null."); return; } - GLenum internalFormat = renderbuffer->getInternalFormat(); - GLenum actualFormat = renderbuffer->getActualFormat(); - GLenum componentType = gl::GetComponentType(internalFormat, clientVersion); + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(attachment->getInternalFormat()); + if (clearParams.colorClearType == GL_FLOAT && - !(componentType == GL_FLOAT || componentType == GL_UNSIGNED_NORMALIZED || componentType == GL_SIGNED_NORMALIZED)) + !(formatInfo.componentType == GL_FLOAT || formatInfo.componentType == GL_UNSIGNED_NORMALIZED || formatInfo.componentType == GL_SIGNED_NORMALIZED)) { ERR("It is undefined behaviour to clear a render buffer which is not normalized fixed point or floating-" - "point to floating point values (color attachment %u has internal format 0x%X).", colorAttachment, internalFormat); + "point to floating point values (color attachment %u has internal format 0x%X).", colorAttachment, + attachment->getInternalFormat()); } - GLuint internalRedBits = gl::GetRedBits(internalFormat, clientVersion); - GLuint internalGreenBits = gl::GetGreenBits(internalFormat, clientVersion); - GLuint internalBlueBits = gl::GetBlueBits(internalFormat, clientVersion); - GLuint internalAlphaBits = gl::GetAlphaBits(internalFormat, clientVersion); - - if ((internalRedBits == 0 || !clearParams.colorMaskRed) && - (internalGreenBits == 0 || !clearParams.colorMaskGreen) && - (internalBlueBits == 0 || !clearParams.colorMaskBlue) && - (internalAlphaBits == 0 || !clearParams.colorMaskAlpha)) + if ((formatInfo.redBits == 0 || !clearParams.colorMaskRed) && + (formatInfo.greenBits == 0 || !clearParams.colorMaskGreen) && + (formatInfo.blueBits == 0 || !clearParams.colorMaskBlue) && + (formatInfo.alphaBits == 0 || !clearParams.colorMaskAlpha)) { // Every channel either does not exist in the render target or is masked out continue; } else if (needScissoredClear || clearParams.colorClearType != GL_FLOAT || - (internalRedBits > 0 && !clearParams.colorMaskRed) || - (internalGreenBits > 0 && !clearParams.colorMaskGreen) || - (internalBlueBits > 0 && !clearParams.colorMaskBlue) || - (internalAlphaBits > 0 && !clearParams.colorMaskAlpha)) + (formatInfo.redBits > 0 && !clearParams.colorMaskRed) || + (formatInfo.greenBits > 0 && !clearParams.colorMaskGreen) || + (formatInfo.blueBits > 0 && !clearParams.colorMaskBlue) || + (formatInfo.alphaBits > 0 && !clearParams.colorMaskAlpha)) { // A scissored or masked clear is required - maskedClearRenderTargets.push_back(renderTarget); + MaskedRenderTarget maskAndRt; + bool clearColor = clearParams.clearColor[colorAttachment]; + maskAndRt.colorMask[0] = (clearColor && clearParams.colorMaskRed); + maskAndRt.colorMask[1] = (clearColor && clearParams.colorMaskGreen); + maskAndRt.colorMask[2] = (clearColor && clearParams.colorMaskBlue); + maskAndRt.colorMask[3] = (clearColor && clearParams.colorMaskAlpha); + maskAndRt.renderTarget = renderTarget; + maskedClearRenderTargets.push_back(maskAndRt); } else { @@ -264,19 +263,16 @@ void Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, gl::Frame return; } + const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(attachment->getActualFormat()); + // Check if the actual format has a channel that the internal format does not and set them to the // default values - GLuint actualRedBits = gl::GetRedBits(actualFormat, clientVersion); - GLuint actualGreenBits = gl::GetGreenBits(actualFormat, clientVersion); - GLuint actualBlueBits = gl::GetBlueBits(actualFormat, clientVersion); - GLuint actualAlphaBits = gl::GetAlphaBits(actualFormat, clientVersion); - const float clearValues[4] = { - ((internalRedBits == 0 && actualRedBits > 0) ? 0.0f : clearParams.colorFClearValue.red), - ((internalGreenBits == 0 && actualGreenBits > 0) ? 0.0f : clearParams.colorFClearValue.green), - ((internalBlueBits == 0 && actualBlueBits > 0) ? 0.0f : clearParams.colorFClearValue.blue), - ((internalAlphaBits == 0 && actualAlphaBits > 0) ? 1.0f : clearParams.colorFClearValue.alpha), + ((formatInfo.redBits == 0 && actualFormatInfo.redBits > 0) ? 0.0f : clearParams.colorFClearValue.red), + ((formatInfo.greenBits == 0 && actualFormatInfo.greenBits > 0) ? 0.0f : clearParams.colorFClearValue.green), + ((formatInfo.blueBits == 0 && actualFormatInfo.blueBits > 0) ? 0.0f : clearParams.colorFClearValue.blue), + ((formatInfo.alphaBits == 0 && actualFormatInfo.alphaBits > 0) ? 1.0f : clearParams.colorFClearValue.alpha), }; deviceContext->ClearRenderTargetView(framebufferRTV, clearValues); @@ -287,19 +283,19 @@ void Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, gl::Frame if (clearParams.clearDepth || clearParams.clearStencil) { - gl::Renderbuffer *renderbuffer = frameBuffer->getDepthOrStencilbuffer(); - if (renderbuffer) + gl::FramebufferAttachment *attachment = frameBuffer->getDepthOrStencilbuffer(); + if (attachment) { - RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(renderbuffer->getDepthStencil()); + RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(attachment->getRenderTarget()); if (!renderTarget) { ERR("Depth stencil render target pointer unexpectedly null."); return; } - GLenum actualFormat = renderbuffer->getActualFormat(); + const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(attachment->getActualFormat()); - unsigned int stencilUnmasked = frameBuffer->hasStencil() ? (1 << gl::GetStencilBits(actualFormat, clientVersion)) - 1 : 0; + unsigned int stencilUnmasked = frameBuffer->hasStencil() ? (1 << actualFormatInfo.stencilBits) - 1 : 0; bool needMaskedStencilClear = clearParams.clearStencil && (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked; if (needScissoredClear || needMaskedStencilClear) @@ -351,22 +347,23 @@ void Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, gl::Frame // be a compatible clear type. // Bind all the render targets which need clearing - ASSERT(maskedClearRenderTargets.size() <= mRenderer->getMaxRenderTargets()); + ASSERT(maskedClearRenderTargets.size() <= mRenderer->getRendererCaps().maxDrawBuffers); std::vector rtvs(maskedClearRenderTargets.size()); for (unsigned int i = 0; i < maskedClearRenderTargets.size(); i++) { - ID3D11RenderTargetView *renderTarget = maskedClearRenderTargets[i]->getRenderTargetView(); - if (!renderTarget) + RenderTarget11 *renderTarget = maskedClearRenderTargets[i].renderTarget; + ID3D11RenderTargetView *rtv = renderTarget->getRenderTargetView(); + if (!rtv) { - ERR("Render target pointer unexpectedly null."); + ERR("Render target view unexpectedly null."); return; } - rtvs[i] = renderTarget; + rtvs[i] = rtv; } ID3D11DepthStencilView *dsv = maskedClearDepthStencil ? maskedClearDepthStencil->getDepthStencilView() : NULL; - ID3D11BlendState *blendState = getBlendState(clearParams, maskedClearRenderTargets); + ID3D11BlendState *blendState = getBlendState(maskedClearRenderTargets); const FLOAT blendFactors[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; const UINT sampleMask = 0xFFFFFFFF; @@ -449,21 +446,20 @@ void Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, gl::Frame } } -ID3D11BlendState *Clear11::getBlendState(const gl::ClearParameters &clearParams, const std::vector& rts) +ID3D11BlendState *Clear11::getBlendState(const std::vector& rts) { - GLuint clientVersion = mRenderer->getCurrentClientVersion(); - ClearBlendInfo blendKey = { 0 }; for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) { if (i < rts.size()) { - GLint internalFormat = rts[i]->getInternalFormat(); + RenderTarget11 *rt = rts[i].renderTarget; + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(rt->getInternalFormat()); - blendKey.maskChannels[i][0] = clearParams.clearColor ? (clearParams.colorMaskRed && gl::GetRedBits(internalFormat, clientVersion) > 0) : false; - blendKey.maskChannels[i][1] = clearParams.clearColor ? (clearParams.colorMaskGreen && gl::GetGreenBits(internalFormat, clientVersion) > 0) : false; - blendKey.maskChannels[i][2] = clearParams.clearColor ? (clearParams.colorMaskBlue && gl::GetBlueBits(internalFormat, clientVersion) > 0) : false; - blendKey.maskChannels[i][3] = clearParams.clearColor ? (clearParams.colorMaskAlpha && gl::GetAlphaBits(internalFormat, clientVersion) > 0) : false; + blendKey.maskChannels[i][0] = (rts[i].colorMask[0] && formatInfo.redBits > 0); + blendKey.maskChannels[i][1] = (rts[i].colorMask[1] && formatInfo.greenBits > 0); + blendKey.maskChannels[i][2] = (rts[i].colorMask[2] && formatInfo.blueBits > 0); + blendKey.maskChannels[i][3] = (rts[i].colorMask[3] && formatInfo.alphaBits > 0); } else { diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/Clear11.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.h similarity index 91% rename from gfx/angle/src/libGLESv2/renderer/d3d11/Clear11.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.h index e8e4c9ea2f1c..be1a9c725720 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d11/Clear11.h +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.h @@ -11,6 +11,9 @@ #include "libGLESv2/angletypes.h" +#include +#include + namespace gl { class Framebuffer; @@ -41,7 +44,13 @@ class Clear11 typedef std::map ClearBlendStateMap; ClearBlendStateMap mClearBlendStates; - ID3D11BlendState *getBlendState(const gl::ClearParameters &clearParams, const std::vector& rts); + struct MaskedRenderTarget + { + bool colorMask[4]; + RenderTarget11 *renderTarget; + }; + + ID3D11BlendState *getBlendState(const std::vector &rts); struct ClearShader { diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/Fence11.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.cpp similarity index 91% rename from gfx/angle/src/libGLESv2/renderer/d3d11/Fence11.cpp rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.cpp index f2a75438fbab..a841b5286256 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d11/Fence11.cpp +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.cpp @@ -1,4 +1,3 @@ -#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 @@ -7,9 +6,9 @@ // Fence11.cpp: Defines the rx::Fence11 class which implements rx::FenceImpl. -#include "libGLESv2/renderer/d3d11/Fence11.h" +#include "libGLESv2/renderer/d3d/d3d11/Fence11.h" +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" #include "libGLESv2/main.h" -#include "libGLESv2/renderer/d3d11/Renderer11.h" namespace rx { diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/Fence11.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/Fence11.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/Image11.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp similarity index 57% rename from gfx/angle/src/libGLESv2/renderer/d3d11/Image11.cpp rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp index 85484f9676f0..185bd9c0173f 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d11/Image11.cpp +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp @@ -1,4 +1,3 @@ -#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 @@ -8,16 +7,16 @@ // Image11.h: Implements the rx::Image11 class, which acts as the interface to // the actual underlying resources of a Texture -#include "libGLESv2/renderer/d3d11/Renderer11.h" -#include "libGLESv2/renderer/d3d11/Image11.h" -#include "libGLESv2/renderer/d3d11/TextureStorage11.h" +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" +#include "libGLESv2/renderer/d3d/d3d11/Image11.h" +#include "libGLESv2/renderer/d3d/d3d11/TextureStorage11.h" +#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" +#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" #include "libGLESv2/Framebuffer.h" -#include "libGLESv2/Renderbuffer.h" - +#include "libGLESv2/FramebufferAttachment.h" #include "libGLESv2/main.h" + #include "common/utilities.h" -#include "libGLESv2/renderer/d3d11/formatutils11.h" -#include "libGLESv2/renderer/d3d11/renderer11_utils.h" namespace rx { @@ -27,11 +26,17 @@ Image11::Image11() mStagingTexture = NULL; mRenderer = NULL; mDXGIFormat = DXGI_FORMAT_UNKNOWN; + mRecoverFromStorage = false; + mAssociatedStorage = NULL; + mAssociatedStorageLevel = 0; + mAssociatedStorageLayerTarget = 0; + mRecoveredFromStorageCount = 0; } Image11::~Image11() { - SafeRelease(mStagingTexture); + disassociateStorage(); + releaseStagingTexture(); } Image11 *Image11::makeImage11(Image *img) @@ -40,14 +45,14 @@ Image11 *Image11::makeImage11(Image *img) return static_cast(img); } -void Image11::generateMipmap(GLuint clientVersion, Image11 *dest, Image11 *src) +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()); - MipGenerationFunction mipFunction = d3d11::GetMipGenerationFunction(src->getDXGIFormat()); - ASSERT(mipFunction != NULL); + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(src->getDXGIFormat()); + ASSERT(dxgiFormatInfo.mipGenerationFunction != NULL); D3D11_MAPPED_SUBRESOURCE destMapped; HRESULT destMapResult = dest->map(D3D11_MAP_WRITE, &destMapped); @@ -67,11 +72,12 @@ void Image11::generateMipmap(GLuint clientVersion, Image11 *dest, Image11 *src) return; } - const unsigned char *sourceData = reinterpret_cast(srcMapped.pData); - unsigned char *destData = reinterpret_cast(destMapped.pData); + const uint8_t *sourceData = reinterpret_cast(srcMapped.pData); + uint8_t *destData = reinterpret_cast(destMapped.pData); - mipFunction(src->getWidth(), src->getHeight(), src->getDepth(), sourceData, srcMapped.RowPitch, srcMapped.DepthPitch, - destData, destMapped.RowPitch, destMapped.DepthPitch); + dxgiFormatInfo.mipGenerationFunction(src->getWidth(), src->getHeight(), src->getDepth(), + sourceData, srcMapped.RowPitch, srcMapped.DepthPitch, + destData, destMapped.RowPitch, destMapped.DepthPitch); dest->unmap(); src->unmap(); @@ -81,33 +87,117 @@ void Image11::generateMipmap(GLuint clientVersion, Image11 *dest, Image11 *src) bool Image11::isDirty() const { - // Make sure that this image is marked as dirty even if the staging texture hasn't been created yet - // if initialization is required before use. - return (mDirty && (mStagingTexture || gl_d3d11::RequiresTextureDataInitialization(mInternalFormat))); + // If mDirty is true + // AND mStagingTexture doesn't exist AND mStagingTexture doesn't need to be recovered from TextureStorage + // AND the texture doesn't require init data (i.e. a blank new texture will suffice) + // then isDirty should still return false. + if (mDirty && !mStagingTexture && !mRecoverFromStorage && !(d3d11::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL)) + { + return false; + } + + return mDirty; } bool Image11::copyToStorage(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, 0, width, height, 1); + return copyToStorageImpl(storage11, level, 0, xoffset, yoffset, width, height); } bool Image11::copyToStorage(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, 0, width, height, 1); + return copyToStorageImpl(storage11, level, face, xoffset, yoffset, width, height); } bool Image11::copyToStorage(TextureStorageInterface3D *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth) { TextureStorage11_3D *storage11 = TextureStorage11_3D::makeTextureStorage11_3D(storage->getStorageInstance()); - return storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, 0, xoffset, yoffset, zoffset, width, height, depth); + return copyToStorageImpl(storage11, level, 0, xoffset, yoffset, width, height); } bool Image11::copyToStorage(TextureStorageInterface2DArray *storage, int level, GLint xoffset, GLint yoffset, GLint arrayLayer, GLsizei width, GLsizei height) { TextureStorage11_2DArray *storage11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(storage->getStorageInstance()); - return storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, arrayLayer, xoffset, yoffset, 0, width, height, 1); + return copyToStorageImpl(storage11, level, arrayLayer, xoffset, yoffset, width, height); +} + +bool Image11::copyToStorageImpl(TextureStorage11 *storage11, int level, int layerTarget, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +{ + // If an app's behavior results in an Image11 copying its data to/from to a TextureStorage multiple times, + // then we should just keep the staging texture around to prevent the copying from impacting perf. + // We allow the Image11 to copy its data to/from TextureStorage once. + // This accounts for an app making a late call to glGenerateMipmap. + bool attemptToReleaseStagingTexture = (mRecoveredFromStorageCount < 2); + + if (attemptToReleaseStagingTexture) + { + // If another image is relying on this Storage for its data, then we must let it recover its data before we overwrite it. + storage11->releaseAssociatedImage(level, layerTarget, this); + } + + bool updateSubresourceSuccess = storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, layerTarget, xoffset, yoffset, 0, width, height, 1); + + // Once the image data has been copied into the Storage, we can release it locally. + if (attemptToReleaseStagingTexture && updateSubresourceSuccess) + { + storage11->associateImage(this, level, layerTarget); + releaseStagingTexture(); + mRecoverFromStorage = true; + mAssociatedStorage = storage11; + mAssociatedStorageLevel = level; + mAssociatedStorageLayerTarget = layerTarget; + } + + return updateSubresourceSuccess; +} + +bool Image11::isAssociatedStorageValid(TextureStorage11* textureStorage) const +{ + return (mAssociatedStorage == textureStorage); +} + +bool Image11::recoverFromAssociatedStorage() +{ + if (mRecoverFromStorage) + { + createStagingTexture(); + + bool textureStorageCorrect = mAssociatedStorage->isAssociatedImageValid(mAssociatedStorageLevel, mAssociatedStorageLayerTarget, this); + + // This means that the cached TextureStorage has been modified after this Image11 released its copy of its data. + // This should not have happened. The TextureStorage should have told this Image11 to recover its data before it was overwritten. + ASSERT(textureStorageCorrect); + + if (textureStorageCorrect) + { + // CopySubResource from the Storage to the Staging texture + mAssociatedStorage->copySubresourceLevel(mStagingTexture, mStagingSubresource, mAssociatedStorageLevel, mAssociatedStorageLayerTarget, 0, 0, 0, mWidth, mHeight, mDepth); + mRecoveredFromStorageCount += 1; + } + + // Reset all the recovery parameters, even if the texture storage association is broken. + disassociateStorage(); + + return textureStorageCorrect; + } + + return false; +} + +void Image11::disassociateStorage() +{ + if (mRecoverFromStorage) + { + // Make the texturestorage release the Image11 too + mAssociatedStorage->disassociateImage(mAssociatedStorageLevel, mAssociatedStorageLayerTarget, this); + + mRecoverFromStorage = false; + mAssociatedStorage = NULL; + mAssociatedStorageLevel = 0; + mAssociatedStorageLayerTarget = 0; + } } bool Image11::redefine(Renderer *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease) @@ -117,8 +207,12 @@ bool Image11::redefine(Renderer *renderer, GLenum target, GLenum internalformat, mInternalFormat != internalformat || forceRelease) { + // End the association with the TextureStorage, since that data will be out of date. + // Also reset mRecoveredFromStorageCount since this Image is getting completely redefined. + disassociateStorage(); + mRecoveredFromStorageCount = 0; + mRenderer = Renderer11::makeRenderer11(renderer); - GLuint clientVersion = mRenderer->getCurrentClientVersion(); mWidth = width; mHeight = height; @@ -127,12 +221,14 @@ bool Image11::redefine(Renderer *renderer, GLenum target, GLenum internalformat, mTarget = target; // compute the d3d format that will be used - mDXGIFormat = gl_d3d11::GetTexFormat(internalformat, clientVersion); - mActualFormat = d3d11_gl::GetInternalFormat(mDXGIFormat, clientVersion); - mRenderable = gl_d3d11::GetRTVFormat(internalformat, clientVersion) != DXGI_FORMAT_UNKNOWN; + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat); + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(formatInfo.texFormat); + mDXGIFormat = formatInfo.texFormat; + mActualFormat = dxgiFormatInfo.internalFormat; + mRenderable = (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN); SafeRelease(mStagingTexture); - mDirty = gl_d3d11::RequiresTextureDataInitialization(mInternalFormat); + mDirty = (formatInfo.dataInitializerFunction != NULL); return true; } @@ -154,13 +250,15 @@ DXGI_FORMAT Image11::getDXGIFormat() const void Image11::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLint unpackAlignment, GLenum type, const void *input) { - GLuint clientVersion = mRenderer->getCurrentClientVersion(); - GLsizei inputRowPitch = gl::GetRowPitch(mInternalFormat, type, clientVersion, width, unpackAlignment); - GLsizei inputDepthPitch = gl::GetDepthPitch(mInternalFormat, type, clientVersion, width, height, unpackAlignment); - GLuint outputPixelSize = d3d11::GetFormatPixelBytes(mDXGIFormat); + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat); + GLsizei inputRowPitch = formatInfo.computeRowPitch(type, width, unpackAlignment); + GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, width, height, unpackAlignment); - LoadImageFunction loadFunction = d3d11::GetImageLoadFunction(mInternalFormat, type, clientVersion); - ASSERT(loadFunction != NULL); + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mDXGIFormat); + GLuint outputPixelSize = dxgiFormatInfo.pixelBytes; + + const d3d11::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(mInternalFormat); + LoadImageFunction loadFunction = d3dFormatInfo.loadFunctions.at(type); D3D11_MAPPED_SUBRESOURCE mappedImage; HRESULT result = map(D3D11_MAP_WRITE, &mappedImage); @@ -170,8 +268,10 @@ void Image11::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei widt return; } - void* offsetMappedData = (void*)((BYTE *)mappedImage.pData + (yoffset * mappedImage.RowPitch + xoffset * outputPixelSize + zoffset * mappedImage.DepthPitch)); - loadFunction(width, height, depth, input, inputRowPitch, inputDepthPitch, offsetMappedData, mappedImage.RowPitch, mappedImage.DepthPitch); + uint8_t* offsetMappedData = (reinterpret_cast(mappedImage.pData) + (yoffset * mappedImage.RowPitch + xoffset * outputPixelSize + zoffset * mappedImage.DepthPitch)); + loadFunction(width, height, depth, + reinterpret_cast(input), inputRowPitch, inputDepthPitch, + offsetMappedData, mappedImage.RowPitch, mappedImage.DepthPitch); unmap(); } @@ -179,19 +279,20 @@ void Image11::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei widt void Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, const void *input) { - GLuint clientVersion = mRenderer->getCurrentClientVersion(); - GLsizei inputRowPitch = gl::GetRowPitch(mInternalFormat, GL_UNSIGNED_BYTE, clientVersion, width, 1); - GLsizei inputDepthPitch = gl::GetDepthPitch(mInternalFormat, GL_UNSIGNED_BYTE, clientVersion, width, height, 1); + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat); + GLsizei inputRowPitch = formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, width, 1); + GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, width, height, 1); - GLuint outputPixelSize = d3d11::GetFormatPixelBytes(mDXGIFormat); - GLuint outputBlockWidth = d3d11::GetBlockWidth(mDXGIFormat); - GLuint outputBlockHeight = d3d11::GetBlockHeight(mDXGIFormat); + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mDXGIFormat); + GLuint outputPixelSize = dxgiFormatInfo.pixelBytes; + GLuint outputBlockWidth = dxgiFormatInfo.blockWidth; + GLuint outputBlockHeight = dxgiFormatInfo.blockHeight; ASSERT(xoffset % outputBlockWidth == 0); ASSERT(yoffset % outputBlockHeight == 0); - LoadImageFunction loadFunction = d3d11::GetImageLoadFunction(mInternalFormat, GL_UNSIGNED_BYTE, clientVersion); - ASSERT(loadFunction != NULL); + const d3d11::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(mInternalFormat); + LoadImageFunction loadFunction = d3dFormatInfo.loadFunctions.at(GL_UNSIGNED_BYTE); D3D11_MAPPED_SUBRESOURCE mappedImage; HRESULT result = map(D3D11_MAP_WRITE, &mappedImage); @@ -201,11 +302,12 @@ void Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GL return; } - void* offsetMappedData = (void*)((BYTE*)mappedImage.pData + ((yoffset / outputBlockHeight) * mappedImage.RowPitch + - (xoffset / outputBlockWidth) * outputPixelSize + - zoffset * mappedImage.DepthPitch)); + uint8_t* offsetMappedData = reinterpret_cast(mappedImage.pData) + ((yoffset / outputBlockHeight) * mappedImage.RowPitch + + (xoffset / outputBlockWidth) * outputPixelSize + + zoffset * mappedImage.DepthPitch); - loadFunction(width, height, depth, input, inputRowPitch, inputDepthPitch, + loadFunction(width, height, depth, + reinterpret_cast(input), inputRowPitch, inputDepthPitch, offsetMappedData, mappedImage.RowPitch, mappedImage.DepthPitch); unmap(); @@ -213,7 +315,7 @@ void Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GL void Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) { - gl::Renderbuffer *colorbuffer = source->getReadColorbuffer(); + gl::FramebufferAttachment *colorbuffer = source->getReadColorbuffer(); if (colorbuffer && colorbuffer->getActualFormat() == mActualFormat) { @@ -287,14 +389,12 @@ void Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y } // determine the offset coordinate into the destination buffer - GLuint clientVersion = mRenderer->getCurrentClientVersion(); - GLsizei rowOffset = gl::GetPixelBytes(mActualFormat, clientVersion) * xoffset; - void *dataOffset = static_cast(mappedImage.pData) + mappedImage.RowPitch * yoffset + rowOffset + zoffset * mappedImage.DepthPitch; + GLsizei rowOffset = gl::GetInternalFormatInfo(mActualFormat).pixelBytes * xoffset; + uint8_t *dataOffset = static_cast(mappedImage.pData) + mappedImage.RowPitch * yoffset + rowOffset + zoffset * mappedImage.DepthPitch; - GLenum format = gl::GetFormat(mInternalFormat, clientVersion); - GLenum type = gl::GetType(mInternalFormat, clientVersion); + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat); - mRenderer->readPixels(source, x, y, width, height, format, type, mappedImage.RowPitch, gl::PixelPackState(), dataOffset); + mRenderer->readPixels(source, x, y, width, height, formatInfo.format, formatInfo.type, mappedImage.RowPitch, gl::PixelPackState(), dataOffset); unmap(); } @@ -307,6 +407,11 @@ ID3D11Resource *Image11::getStagingTexture() return mStagingTexture; } +void Image11::releaseStagingTexture() +{ + SafeRelease(mStagingTexture); +} + unsigned int Image11::getStagingSubresource() { createStagingTexture(); @@ -350,12 +455,12 @@ void Image11::createStagingTexture() desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (gl_d3d11::RequiresTextureDataInitialization(mInternalFormat)) + if (d3d11::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL) { std::vector initialData; std::vector< std::vector > textureData; - d3d11::GenerateInitialTextureData(mInternalFormat, mRenderer->getCurrentClientVersion(), width, height, - mDepth, lodOffset + 1, &initialData, &textureData); + d3d11::GenerateInitialTextureData(mInternalFormat, width, height, mDepth, + lodOffset + 1, &initialData, &textureData); result = device->CreateTexture3D(&desc, initialData.data(), &newTexture); } @@ -391,12 +496,12 @@ void Image11::createStagingTexture() desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (gl_d3d11::RequiresTextureDataInitialization(mInternalFormat)) + if (d3d11::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL) { std::vector initialData; std::vector< std::vector > textureData; - d3d11::GenerateInitialTextureData(mInternalFormat, mRenderer->getCurrentClientVersion(), width, height, - 1, lodOffset + 1, &initialData, &textureData); + d3d11::GenerateInitialTextureData(mInternalFormat, width, height, 1, + lodOffset + 1, &initialData, &textureData); result = device->CreateTexture2D(&desc, initialData.data(), &newTexture); } @@ -428,6 +533,9 @@ HRESULT Image11::map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map) { createStagingTexture(); + // We must recover from the TextureStorage if necessary, even for D3D11_MAP_WRITE. + recoverFromAssociatedStorage(); + HRESULT result = E_FAIL; if (mStagingTexture) diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/Image11.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.h similarity index 78% rename from gfx/angle/src/libGLESv2/renderer/d3d11/Image11.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.h index 300774cf2313..c815eaf4a8f7 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d11/Image11.h +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.h @@ -10,7 +10,7 @@ #ifndef LIBGLESV2_RENDERER_IMAGE11_H_ #define LIBGLESV2_RENDERER_IMAGE11_H_ -#include "libGLESv2/renderer/Image.h" +#include "libGLESv2/renderer/d3d/ImageD3D.h" #include "common/debug.h" @@ -25,8 +25,9 @@ class Renderer; class Renderer11; class TextureStorageInterface2D; class TextureStorageInterfaceCube; +class TextureStorage11; -class Image11 : public Image +class Image11 : public ImageD3D { public: Image11(); @@ -34,7 +35,7 @@ class Image11 : public Image static Image11 *makeImage11(Image *img); - static void generateMipmap(GLuint clientVersion, Image11 *dest, Image11 *src); + static void generateMipmap(Image11 *dest, Image11 *src); virtual bool isDirty() const; @@ -54,6 +55,10 @@ class Image11 : public Image virtual void copy(GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); + bool recoverFromAssociatedStorage(); + bool isAssociatedStorageValid(TextureStorage11* textureStorage) const; + void disassociateStorage(); + protected: HRESULT map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map); void unmap(); @@ -61,15 +66,24 @@ class Image11 : public Image private: DISALLOW_COPY_AND_ASSIGN(Image11); + bool copyToStorageImpl(TextureStorage11 *storage11, int level, int layerTarget, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); + ID3D11Resource *getStagingTexture(); unsigned int getStagingSubresource(); void createStagingTexture(); + void releaseStagingTexture(); Renderer11 *mRenderer; DXGI_FORMAT mDXGIFormat; ID3D11Resource *mStagingTexture; unsigned int mStagingSubresource; + + bool mRecoverFromStorage; + TextureStorage11 *mAssociatedStorage; + int mAssociatedStorageLevel; + int mAssociatedStorageLayerTarget; + unsigned int mRecoveredFromStorageCount; }; } diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/IndexBuffer11.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.cpp similarity index 97% rename from gfx/angle/src/libGLESv2/renderer/d3d11/IndexBuffer11.cpp rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.cpp index afceac7012b4..f2dd50523d0f 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d11/IndexBuffer11.cpp +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.cpp @@ -1,4 +1,3 @@ -#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,8 +6,8 @@ // IndexBuffer11.cpp: Defines the D3D11 IndexBuffer implementation. -#include "libGLESv2/renderer/d3d11/IndexBuffer11.h" -#include "libGLESv2/renderer/d3d11/Renderer11.h" +#include "libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h" +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" namespace rx { diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/IndexBuffer11.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h similarity index 93% rename from gfx/angle/src/libGLESv2/renderer/d3d11/IndexBuffer11.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h index 39a61946ad6e..e821b7f3d1f2 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d11/IndexBuffer11.h +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h @@ -9,7 +9,7 @@ #ifndef LIBGLESV2_RENDERER_INDEXBUFFER11_H_ #define LIBGLESV2_RENDERER_INDEXBUFFER11_H_ -#include "libGLESv2/renderer/IndexBuffer.h" +#include "libGLESv2/renderer/d3d/IndexBuffer.h" namespace rx { diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/InputLayoutCache.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp similarity index 92% rename from gfx/angle/src/libGLESv2/renderer/d3d11/InputLayoutCache.cpp rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp index 7092dc5ddd43..3050a497add0 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d11/InputLayoutCache.cpp +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp @@ -1,4 +1,3 @@ -#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 @@ -8,14 +7,14 @@ // InputLayoutCache.cpp: Defines InputLayoutCache, a class that builds and caches // D3D11 input layouts. -#include "libGLESv2/renderer/d3d11/InputLayoutCache.h" -#include "libGLESv2/renderer/d3d11/VertexBuffer11.h" -#include "libGLESv2/renderer/d3d11/BufferStorage11.h" -#include "libGLESv2/renderer/d3d11/ShaderExecutable11.h" +#include "libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h" +#include "libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h" +#include "libGLESv2/renderer/d3d/d3d11/Buffer11.h" +#include "libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h" +#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" +#include "libGLESv2/renderer/d3d/VertexDataManager.h" #include "libGLESv2/ProgramBinary.h" #include "libGLESv2/VertexAttribute.h" -#include "libGLESv2/renderer/VertexDataManager.h" -#include "libGLESv2/renderer/d3d11/formatutils11.h" #include "third_party/murmurhash/MurmurHash3.h" @@ -109,7 +108,7 @@ GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::M D3D11_INPUT_CLASSIFICATION inputClass = attributes[i].divisor > 0 ? D3D11_INPUT_PER_INSTANCE_DATA : D3D11_INPUT_PER_VERTEX_DATA; gl::VertexFormat vertexFormat(*attributes[i].attribute, attributes[i].currentValueType); - DXGI_FORMAT dxgiFormat = gl_d3d11::GetNativeVertexFormat(vertexFormat); + const d3d11::VertexFormat &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormat); // Record the type of the associated vertex shader vector in our key // This will prevent mismatched vertex shaders from using the same input layout @@ -118,7 +117,7 @@ GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::M ilKey.elements[ilKey.elementCount].desc.SemanticName = semanticName; ilKey.elements[ilKey.elementCount].desc.SemanticIndex = sortedSemanticIndices[i]; - ilKey.elements[ilKey.elementCount].desc.Format = dxgiFormat; + ilKey.elements[ilKey.elementCount].desc.Format = vertexFormatInfo.nativeFormat; ilKey.elements[ilKey.elementCount].desc.InputSlot = i; ilKey.elements[ilKey.elementCount].desc.AlignedByteOffset = 0; ilKey.elements[ilKey.elementCount].desc.InputSlotClass = inputClass; @@ -194,9 +193,9 @@ GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::M if (attributes[i].active) { VertexBuffer11 *vertexBuffer = VertexBuffer11::makeVertexBuffer11(attributes[i].vertexBuffer); - BufferStorage11 *bufferStorage = attributes[i].storage ? BufferStorage11::makeBufferStorage11(attributes[i].storage) : NULL; + Buffer11 *bufferStorage = attributes[i].storage ? Buffer11::makeBuffer11(attributes[i].storage) : NULL; - buffer = bufferStorage ? bufferStorage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK) + buffer = bufferStorage ? bufferStorage->getBuffer(BUFFER_USAGE_VERTEX) : vertexBuffer->getBuffer(); } diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/InputLayoutCache.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h similarity index 97% rename from gfx/angle/src/libGLESv2/renderer/d3d11/InputLayoutCache.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h index 5d0ac60537d2..8a64c5a280eb 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d11/InputLayoutCache.h +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h @@ -13,6 +13,11 @@ #include "libGLESv2/Constants.h" #include "common/angleutils.h" +#include + +#include +#include + namespace gl { class ProgramBinary; diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/PixelTransfer11.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp similarity index 86% rename from gfx/angle/src/libGLESv2/renderer/d3d11/PixelTransfer11.cpp rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp index dcd1f99ab95c..f54baccf2501 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d11/PixelTransfer11.cpp +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp @@ -1,4 +1,3 @@ -#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 @@ -10,24 +9,24 @@ // Used to implement pixel transfers from unpack and to pack buffers. // -#include "libGLESv2/renderer/d3d11/PixelTransfer11.h" +#include "libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h" +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" +#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" +#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" +#include "libGLESv2/renderer/d3d/d3d11/Buffer11.h" +#include "libGLESv2/renderer/d3d/d3d11/TextureStorage11.h" +#include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h" #include "libGLESv2/formatutils.h" #include "libGLESv2/Texture.h" #include "libGLESv2/Buffer.h" -#include "libGLESv2/renderer/d3d11/Renderer11.h" -#include "libGLESv2/renderer/d3d11/renderer11_utils.h" -#include "libGLESv2/renderer/d3d11/formatutils11.h" -#include "libGLESv2/renderer/d3d11/BufferStorage11.h" -#include "libGLESv2/renderer/d3d11/TextureStorage11.h" -#include "libGLESv2/renderer/d3d11/RenderTarget11.h" #include "libGLESv2/Context.h" // Precompiled shaders -#include "libGLESv2/renderer/d3d11/shaders/compiled/buffertotexture11_vs.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/buffertotexture11_gs.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/buffertotexture11_ps_4f.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/buffertotexture11_ps_4i.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/buffertotexture11_ps_4ui.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_vs.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_gs.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4f.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4i.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4ui.h" namespace rx { @@ -122,7 +121,7 @@ void PixelTransfer11::setBufferToTextureCopyParams(const gl::Box &destArea, cons float texelCenterX = 0.5f / static_cast(destSize.width - 1); float texelCenterY = 0.5f / static_cast(destSize.height - 1); - unsigned int bytesPerPixel = gl::GetPixelBytes(internalFormat, 3); + unsigned int bytesPerPixel = gl::GetInternalFormatInfo(internalFormat).pixelBytes; unsigned int alignmentBytes = static_cast(unpack.alignment); unsigned int alignmentPixels = (alignmentBytes <= bytesPerPixel ? 1 : alignmentBytes / bytesPerPixel); @@ -148,7 +147,6 @@ bool PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpack, un return false; } - int clientVersion = mRenderer->getCurrentClientVersion(); const gl::Buffer &sourceBuffer = *unpack.pixelBuffer.get(); ASSERT(mRenderer->supportsFastCopyBufferToTexture(destinationFormat)); @@ -158,12 +156,13 @@ bool PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpack, un // The SRV must be in the proper read format, which may be different from the destination format // EG: for half float data, we can load full precision floats with implicit conversion - GLenum unsizedFormat = gl::GetFormat(destinationFormat, clientVersion); - GLenum sourceFormat = gl::GetSizedInternalFormat(unsizedFormat, sourcePixelsType, clientVersion); + GLenum unsizedFormat = gl::GetInternalFormatInfo(destinationFormat).format; + GLenum sourceFormat = gl::GetFormatTypeInfo(unsizedFormat, sourcePixelsType).internalFormat; - DXGI_FORMAT srvFormat = gl_d3d11::GetSRVFormat(sourceFormat, clientVersion); + const d3d11::TextureFormat &sourceFormatInfo = d3d11::GetTextureFormatInfo(sourceFormat); + DXGI_FORMAT srvFormat = sourceFormatInfo.srvFormat; ASSERT(srvFormat != DXGI_FORMAT_UNKNOWN); - BufferStorage11 *bufferStorage11 = BufferStorage11::makeBufferStorage11(sourceBuffer.getStorage()); + Buffer11 *bufferStorage11 = Buffer11::makeBuffer11(sourceBuffer.getImplementation()); ID3D11ShaderResourceView *bufferSRV = bufferStorage11->getSRV(srvFormat); ASSERT(bufferSRV != NULL); @@ -237,9 +236,7 @@ void PixelTransfer11::buildShaderMap() ID3D11PixelShader *PixelTransfer11::findBufferToTexturePS(GLenum internalFormat) const { - int clientVersion = mRenderer->getCurrentClientVersion(); - GLenum componentType = gl::GetComponentType(internalFormat, clientVersion); - + GLenum componentType = gl::GetInternalFormatInfo(internalFormat).componentType; if (componentType == GL_SIGNED_NORMALIZED || componentType == GL_UNSIGNED_NORMALIZED) { componentType = GL_FLOAT; diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/PixelTransfer11.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h similarity index 97% rename from gfx/angle/src/libGLESv2/renderer/d3d11/PixelTransfer11.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h index 574140d1984e..ed1a3ae1d0a4 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d11/PixelTransfer11.h +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h @@ -11,6 +11,12 @@ #ifndef LIBGLESV2_PIXELTRANSFER11_H_ #define LIBGLESV2_PIXELTRANSFER11_H_ +#include "common/platform.h" + +#include + +#include + namespace gl { diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/Query11.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp similarity index 91% rename from gfx/angle/src/libGLESv2/renderer/d3d11/Query11.cpp rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp index 203f61f9f0ab..bc2f94199b4e 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d11/Query11.cpp +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp @@ -1,4 +1,3 @@ -#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 @@ -7,11 +6,13 @@ // Query11.cpp: Defines the rx::Query11 class which implements rx::QueryImpl. -#include "libGLESv2/renderer/d3d11/Query11.h" -#include "libGLESv2/renderer/d3d11/Renderer11.h" -#include "libGLESv2/renderer/d3d11/renderer11_utils.h" +#include "libGLESv2/renderer/d3d/d3d11/Query11.h" +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" +#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" #include "libGLESv2/main.h" +#include + namespace rx { @@ -29,7 +30,7 @@ static bool checkStreamOutPrimitivesWritten(ID3D11DeviceContext *context, ID3D11 return (result == S_OK); } -Query11::Query11(rx::Renderer11 *renderer, GLenum type) : QueryImpl(type) +Query11::Query11(rx::Renderer11 *renderer, GLenum type) : QueryImpl(type), mStatus(GL_FALSE), mResult(0) { mRenderer = renderer; mQuery = NULL; @@ -40,7 +41,7 @@ Query11::~Query11() SafeRelease(mQuery); } -void Query11::begin() +bool Query11::begin() { if (mQuery == NULL) { @@ -50,11 +51,12 @@ void Query11::begin() if (FAILED(mRenderer->getDevice()->CreateQuery(&queryDesc, &mQuery))) { - return gl::error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY, false); } } mRenderer->getDeviceContext()->Begin(mQuery); + return true; } void Query11::end() @@ -147,9 +149,4 @@ GLboolean Query11::testQuery() return GL_TRUE; // prevent blocking when query is null } -bool Query11::isStarted() const -{ - return (mQuery != NULL); -} - } diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/Query11.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.h similarity index 92% rename from gfx/angle/src/libGLESv2/renderer/d3d11/Query11.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.h index 7a3df46d4f74..40cfbb6dbdb9 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d11/Query11.h +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.h @@ -21,17 +21,19 @@ class Query11 : public QueryImpl Query11(rx::Renderer11 *renderer, GLenum type); virtual ~Query11(); - virtual void begin(); + virtual bool begin(); virtual void end(); virtual GLuint getResult(); virtual GLboolean isResultAvailable(); - virtual bool isStarted() const; private: DISALLOW_COPY_AND_ASSIGN(Query11); GLboolean testQuery(); + GLuint mResult; + GLboolean mStatus; + rx::Renderer11 *mRenderer; ID3D11Query *mQuery; }; diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/RenderStateCache.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.cpp similarity index 96% rename from gfx/angle/src/libGLESv2/renderer/d3d11/RenderStateCache.cpp rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.cpp index d0bfd6c8b9f5..b144078e7806 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d11/RenderStateCache.cpp +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -8,13 +7,14 @@ // RenderStateCache.cpp: Defines rx::RenderStateCache, a cache of Direct3D render // state objects. -#include "libGLESv2/renderer/d3d11/RenderStateCache.h" -#include "libGLESv2/renderer/d3d11/renderer11_utils.h" -#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/renderer/d3d/d3d11/RenderStateCache.h" +#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" #include "libGLESv2/Framebuffer.h" -#include "libGLESv2/Renderbuffer.h" +#include "libGLESv2/FramebufferAttachment.h" #include "common/debug.h" + #include "third_party/murmurhash/MurmurHash3.h" namespace rx @@ -23,7 +23,7 @@ namespace rx template static void ClearStateMap(mapType &map) { - for (mapType::iterator i = map.begin(); i != map.end(); i++) + for (typename mapType::iterator i = map.begin(); i != map.end(); i++) { SafeRelease(i->second.first); } @@ -93,18 +93,18 @@ ID3D11BlendState *RenderStateCache::getBlendState(const gl::Framebuffer *framebu key.blendState = blendState; for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) { - gl::Renderbuffer *renderBuffer = framebuffer->getColorbuffer(i); - if (renderBuffer) + const gl::FramebufferAttachment *attachment = framebuffer->getColorbuffer(i); + if (attachment) { if (i > 0) { mrt = true; } - key.rtChannels[i][0] = renderBuffer->getRedSize() > 0; - key.rtChannels[i][1] = renderBuffer->getGreenSize() > 0; - key.rtChannels[i][2] = renderBuffer->getBlueSize() > 0; - key.rtChannels[i][3] = renderBuffer->getAlphaSize() > 0; + key.rtChannels[i][0] = attachment->getRedSize() > 0; + key.rtChannels[i][1] = attachment->getGreenSize() > 0; + key.rtChannels[i][2] = attachment->getBlueSize() > 0; + key.rtChannels[i][3] = attachment->getAlphaSize() > 0; } else { diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/RenderStateCache.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.h similarity index 98% rename from gfx/angle/src/libGLESv2/renderer/d3d11/RenderStateCache.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.h index 7f3349627ae5..cc0688e7e58a 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d11/RenderStateCache.h +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.h @@ -13,6 +13,8 @@ #include "libGLESv2/angletypes.h" #include "common/angleutils.h" +#include + namespace gl { class Framebuffer; @@ -20,6 +22,7 @@ class Framebuffer; namespace rx { +class Renderer11; class RenderStateCache { diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/RenderTarget11.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.cpp similarity index 82% rename from gfx/angle/src/libGLESv2/renderer/d3d11/RenderTarget11.cpp rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.cpp index a5c3340eb9bd..3041f21faa6c 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d11/RenderTarget11.cpp +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.cpp @@ -1,4 +1,3 @@ -#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 @@ -8,11 +7,10 @@ // RenderTarget11.cpp: Implements a DX11-specific wrapper for ID3D11View pointers // retained by Renderbuffers. -#include "libGLESv2/renderer/d3d11/RenderTarget11.h" -#include "libGLESv2/renderer/d3d11/Renderer11.h" - -#include "libGLESv2/renderer/d3d11/renderer11_utils.h" -#include "libGLESv2/renderer/d3d11/formatutils11.h" +#include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h" +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" +#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" +#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" #include "libGLESv2/main.h" namespace rx @@ -219,8 +217,9 @@ RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11RenderTargetView *rtv, mDepth = depth; mSamples = samples; - mInternalFormat = d3d11_gl::GetInternalFormat(desc.Format, renderer->getCurrentClientVersion()); - mActualFormat = d3d11_gl::GetInternalFormat(desc.Format, renderer->getCurrentClientVersion()); + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(desc.Format); + mInternalFormat = dxgiFormatInfo.internalFormat; + mActualFormat = dxgiFormatInfo.internalFormat; } } @@ -265,8 +264,9 @@ RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11DepthStencilView *dsv, mDepth = depth; mSamples = samples; - mInternalFormat = d3d11_gl::GetInternalFormat(desc.Format, renderer->getCurrentClientVersion()); - mActualFormat = d3d11_gl::GetInternalFormat(desc.Format, renderer->getCurrentClientVersion()); + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(desc.Format); + mInternalFormat = dxgiFormatInfo.internalFormat; + mActualFormat = dxgiFormatInfo.internalFormat; } } @@ -278,20 +278,11 @@ RenderTarget11::RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height mDepthStencil = NULL; mShaderResource = NULL; - GLuint clientVersion = mRenderer->getCurrentClientVersion(); + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalFormat); + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(formatInfo.texFormat); - DXGI_FORMAT texFormat = gl_d3d11::GetTexFormat(internalFormat, clientVersion); - DXGI_FORMAT srvFormat = gl_d3d11::GetSRVFormat(internalFormat, clientVersion); - DXGI_FORMAT rtvFormat = gl_d3d11::GetRTVFormat(internalFormat, clientVersion); - DXGI_FORMAT dsvFormat = gl_d3d11::GetDSVFormat(internalFormat, clientVersion); - - DXGI_FORMAT multisampleFormat = (dsvFormat != DXGI_FORMAT_UNKNOWN ? dsvFormat : rtvFormat); - int supportedSamples = mRenderer->getNearestSupportedSamples(multisampleFormat, samples); - if (supportedSamples < 0) - { - gl::error(GL_OUT_OF_MEMORY); - return; - } + const gl::TextureCaps &textureCaps = mRenderer->getRendererTextureCaps().get(internalFormat); + GLuint supportedSamples = textureCaps.getNearestSamples(samples); if (width > 0 && height > 0) { @@ -301,15 +292,30 @@ RenderTarget11::RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height desc.Height = height; desc.MipLevels = 1; desc.ArraySize = 1; - desc.Format = texFormat; + desc.Format = formatInfo.texFormat; desc.SampleDesc.Count = (supportedSamples == 0) ? 1 : supportedSamples; desc.SampleDesc.Quality = 0; desc.Usage = D3D11_USAGE_DEFAULT; desc.CPUAccessFlags = 0; desc.MiscFlags = 0; - desc.BindFlags = ((srvFormat != DXGI_FORMAT_UNKNOWN) ? D3D11_BIND_SHADER_RESOURCE : 0) | - ((dsvFormat != DXGI_FORMAT_UNKNOWN) ? D3D11_BIND_DEPTH_STENCIL : 0) | - ((rtvFormat != DXGI_FORMAT_UNKNOWN) ? D3D11_BIND_RENDER_TARGET : 0); + + // If a rendertarget or depthstencil format exists for this texture format, + // we'll flag it to allow binding that way. Shader resource views are a little + // more complicated. + bool bindRTV = false, bindDSV = false, bindSRV = false; + bindRTV = (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN); + bindDSV = (formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN); + if (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN) + { + // Multisample targets flagged for binding as depth stencil cannot also be + // flagged for binding as SRV, so make certain not to add the SRV flag for + // these targets. + bindSRV = !(formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN && desc.SampleDesc.Count > 1); + } + + desc.BindFlags = (bindRTV ? D3D11_BIND_RENDER_TARGET : 0) | + (bindDSV ? D3D11_BIND_DEPTH_STENCIL : 0) | + (bindSRV ? D3D11_BIND_SHADER_RESOURCE : 0); ID3D11Device *device = mRenderer->getDevice(); ID3D11Texture2D *texture = NULL; @@ -323,10 +329,10 @@ RenderTarget11::RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height } ASSERT(SUCCEEDED(result)); - if (srvFormat != DXGI_FORMAT_UNKNOWN) + if (bindSRV) { D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srvDesc.Format = srvFormat; + srvDesc.Format = formatInfo.srvFormat; srvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_SRV_DIMENSION_TEXTURE2D : D3D11_SRV_DIMENSION_TEXTURE2DMS; srvDesc.Texture2D.MostDetailedMip = 0; srvDesc.Texture2D.MipLevels = 1; @@ -341,10 +347,10 @@ RenderTarget11::RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height ASSERT(SUCCEEDED(result)); } - if (dsvFormat != DXGI_FORMAT_UNKNOWN) + if (bindDSV) { D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; - dsvDesc.Format = dsvFormat; + dsvDesc.Format = formatInfo.dsvFormat; dsvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_DSV_DIMENSION_TEXTURE2D : D3D11_DSV_DIMENSION_TEXTURE2DMS; dsvDesc.Texture2D.MipSlice = 0; dsvDesc.Flags = 0; @@ -360,10 +366,10 @@ RenderTarget11::RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height ASSERT(SUCCEEDED(result)); } - if (rtvFormat != DXGI_FORMAT_UNKNOWN) + if (bindRTV) { D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = rtvFormat; + rtvDesc.Format = formatInfo.rtvFormat; rtvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_RTV_DIMENSION_TEXTURE2D : D3D11_RTV_DIMENSION_TEXTURE2DMS; rtvDesc.Texture2D.MipSlice = 0; result = device->CreateRenderTargetView(mTexture, &rtvDesc, &mRenderTarget); @@ -378,7 +384,7 @@ RenderTarget11::RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height } ASSERT(SUCCEEDED(result)); - if (gl_d3d11::RequiresTextureDataInitialization(internalFormat)) + if (formatInfo.dataInitializerFunction != NULL) { ID3D11DeviceContext *context = mRenderer->getDeviceContext(); @@ -388,12 +394,13 @@ RenderTarget11::RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height } } + mWidth = width; mHeight = height; mDepth = 1; mInternalFormat = internalFormat; mSamples = supportedSamples; - mActualFormat = d3d11_gl::GetInternalFormat(texFormat, renderer->getCurrentClientVersion()); + mActualFormat = dxgiFormatInfo.internalFormat; mSubresourceIndex = D3D11CalcSubresource(0, 0, 1); } diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/RenderTarget11.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/RenderTarget11.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp similarity index 73% rename from gfx/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp index 143799ab83e5..3a276e1a7594 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -8,31 +7,42 @@ // Renderer11.cpp: Implements a back-end specific class for the D3D11 renderer. #include "libGLESv2/main.h" -#include "common/utilities.h" #include "libGLESv2/Buffer.h" +#include "libGLESv2/FramebufferAttachment.h" #include "libGLESv2/ProgramBinary.h" #include "libGLESv2/Framebuffer.h" -#include "libGLESv2/RenderBuffer.h" -#include "libGLESv2/renderer/d3d11/Renderer11.h" -#include "libGLESv2/renderer/d3d11/RenderTarget11.h" -#include "libGLESv2/renderer/d3d11/renderer11_utils.h" -#include "libGLESv2/renderer/d3d11/formatutils11.h" -#include "libGLESv2/renderer/d3d11/ShaderExecutable11.h" -#include "libGLESv2/renderer/d3d11/SwapChain11.h" -#include "libGLESv2/renderer/d3d11/Image11.h" -#include "libGLESv2/renderer/d3d11/VertexBuffer11.h" -#include "libGLESv2/renderer/d3d11/IndexBuffer11.h" -#include "libGLESv2/renderer/d3d11/BufferStorage11.h" -#include "libGLESv2/renderer/VertexDataManager.h" -#include "libGLESv2/renderer/IndexDataManager.h" -#include "libGLESv2/renderer/d3d11/TextureStorage11.h" -#include "libGLESv2/renderer/d3d11/Query11.h" -#include "libGLESv2/renderer/d3d11/Fence11.h" -#include "libGLESv2/renderer/d3d11/Blit11.h" -#include "libGLESv2/renderer/d3d11/Clear11.h" -#include "libGLESv2/renderer/d3d11/PixelTransfer11.h" +#include "libGLESv2/renderer/d3d/ShaderD3D.h" +#include "libGLESv2/renderer/d3d/TextureD3D.h" +#include "libGLESv2/renderer/d3d/TransformFeedbackD3D.h" +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" +#include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h" +#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" +#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" +#include "libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h" +#include "libGLESv2/renderer/d3d/d3d11/SwapChain11.h" +#include "libGLESv2/renderer/d3d/d3d11/Image11.h" +#include "libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h" +#include "libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h" +#include "libGLESv2/renderer/d3d/d3d11/Buffer11.h" +#include "libGLESv2/renderer/d3d/VertexDataManager.h" +#include "libGLESv2/renderer/d3d/IndexDataManager.h" +#include "libGLESv2/renderer/d3d/d3d11/TextureStorage11.h" +#include "libGLESv2/renderer/d3d/d3d11/Query11.h" +#include "libGLESv2/renderer/d3d/d3d11/Fence11.h" +#include "libGLESv2/renderer/d3d/d3d11/Blit11.h" +#include "libGLESv2/renderer/d3d/d3d11/Clear11.h" +#include "libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h" +#include "libGLESv2/renderer/d3d/d3d11/VertexArray11.h" +#include "libGLESv2/renderer/d3d/d3d11/Buffer11.h" + #include "libEGL/Display.h" +#include "common/utilities.h" + +#include + +#include + // Enable ANGLE_SKIP_DXGI_1_2_CHECK if there is not a possibility of using cross-process // HWNDs or the Windows 7 Platform Update (KB2670838) is expected to be installed. #ifndef ANGLE_SKIP_DXGI_1_2_CHECK @@ -65,7 +75,10 @@ enum MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 = 16 }; -Renderer11::Renderer11(egl::Display *display, HDC hDc) : Renderer(display), mDc(hDc) +Renderer11::Renderer11(egl::Display *display, EGLNativeDisplayType hDc, EGLint requestedDisplay) + : Renderer(display), + mDc(hDc), + mRequestedDisplay(requestedDisplay) { mVertexDataManager = NULL; mIndexDataManager = NULL; @@ -85,8 +98,6 @@ Renderer11::Renderer11(egl::Display *display, HDC hDc) : Renderer(display), mDc( mDeviceLost = false; - mMaxSupportedSamples = 0; - mDevice = NULL; mDeviceContext = NULL; mDxgiAdapter = NULL; @@ -95,8 +106,6 @@ Renderer11::Renderer11(egl::Display *display, HDC hDc) : Renderer(display), mDc( mDriverConstantBufferVS = NULL; mDriverConstantBufferPS = NULL; - mBGRATextureSupport = false; - mAppliedVertexShader = NULL; mAppliedGeometryShader = NULL; mCurPointGeometryShader = NULL; @@ -151,11 +160,17 @@ EGLint Renderer11::initialize() D3D_FEATURE_LEVEL_10_0, }; + D3D_DRIVER_TYPE driverType = D3D_DRIVER_TYPE_HARDWARE; + if (mRequestedDisplay == EGL_PLATFORM_ANGLE_TYPE_D3D11_WARP_ANGLE) + { + driverType = D3D_DRIVER_TYPE_WARP; + } + HRESULT result = S_OK; #ifdef _DEBUG result = D3D11CreateDevice(NULL, - D3D_DRIVER_TYPE_HARDWARE, + driverType, NULL, D3D11_CREATE_DEVICE_DEBUG, featureLevels, @@ -174,7 +189,7 @@ EGLint Renderer11::initialize() #endif { result = D3D11CreateDevice(NULL, - D3D_DRIVER_TYPE_HARDWARE, + driverType, NULL, 0, featureLevels, @@ -273,166 +288,8 @@ EGLint Renderer11::initialize() } #endif - mMaxSupportedSamples = 0; - - const d3d11::DXGIFormatSet &dxgiFormats = d3d11::GetAllUsedDXGIFormats(); - for (d3d11::DXGIFormatSet::const_iterator i = dxgiFormats.begin(); i != dxgiFormats.end(); ++i) - { - MultisampleSupportInfo support = getMultisampleSupportInfo(*i); - mMultisampleSupportMap.insert(std::make_pair(*i, support)); - mMaxSupportedSamples = std::max(mMaxSupportedSamples, support.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_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; - } - } - - DXGI_FORMAT rgTextureFormats[] = - { - DXGI_FORMAT_R8_UNORM, - DXGI_FORMAT_R8G8_UNORM, - DXGI_FORMAT_R16_FLOAT, - DXGI_FORMAT_R16G16_FLOAT, - DXGI_FORMAT_R32_FLOAT, - DXGI_FORMAT_R32G32_FLOAT, - }; - - mRGTextureSupport = true; - for (unsigned int i = 0; i < ArraySize(rgTextureFormats); i++) - { - if (SUCCEEDED(mDevice->CheckFormatSupport(rgTextureFormats[i], &formatSupport))) - { - mRGTextureSupport = mRGTextureSupport && (formatSupport & requiredTextureFlags) == requiredTextureFlags; - mRGTextureSupport = mRGTextureSupport && (formatSupport & requiredFilterFlags) == requiredFilterFlags; - mRGTextureSupport = mRGTextureSupport && (formatSupport & requiredRenderableFlags) == requiredRenderableFlags; - } - else - { - mRGTextureSupport = 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; } @@ -469,35 +326,19 @@ int Renderer11::generateConfigs(ConfigDesc **configDescList) for (unsigned int formatIndex = 0; formatIndex < numRenderFormats; formatIndex++) { - for (unsigned int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++) + const d3d11::DXGIFormat &renderTargetFormatInfo = d3d11::GetDXGIFormatInfo(RenderTargetFormats[formatIndex]); + const gl::TextureCaps &renderTargetFormatCaps = getRendererTextureCaps().get(renderTargetFormatInfo.internalFormat); + if (renderTargetFormatCaps.renderable) { - DXGI_FORMAT renderTargetFormat = RenderTargetFormats[formatIndex]; - - UINT formatSupport = 0; - HRESULT result = mDevice->CheckFormatSupport(renderTargetFormat, &formatSupport); - - if (SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_RENDER_TARGET)) + for (unsigned int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++) { - DXGI_FORMAT depthStencilFormat = DepthStencilFormats[depthStencilIndex]; - - bool depthStencilFormatOK = true; - - if (depthStencilFormat != DXGI_FORMAT_UNKNOWN) + const d3d11::DXGIFormat &depthStencilFormatInfo = d3d11::GetDXGIFormatInfo(DepthStencilFormats[depthStencilIndex]); + const gl::TextureCaps &depthStencilFormatCaps = getRendererTextureCaps().get(depthStencilFormatInfo.internalFormat); + if (depthStencilFormatCaps.renderable || DepthStencilFormats[depthStencilIndex] == DXGI_FORMAT_UNKNOWN) { - UINT depthStencilSupport = 0; - result = mDevice->CheckFormatSupport(depthStencilFormat, &depthStencilSupport); - depthStencilFormatOK = SUCCEEDED(result) && (depthStencilSupport & D3D11_FORMAT_SUPPORT_DEPTH_STENCIL); - } - - if (depthStencilFormatOK) - { - // FIXME: parse types from context version - ASSERT(d3d11_gl::GetInternalFormat(renderTargetFormat, 2) == d3d11_gl::GetInternalFormat(renderTargetFormat, 3)); - ASSERT(d3d11_gl::GetInternalFormat(depthStencilFormat, 2) == d3d11_gl::GetInternalFormat(depthStencilFormat, 3)); - ConfigDesc newConfig; - newConfig.renderTargetFormat = d3d11_gl::GetInternalFormat(renderTargetFormat, getCurrentClientVersion()); - newConfig.depthStencilFormat = d3d11_gl::GetInternalFormat(depthStencilFormat, getCurrentClientVersion()); + newConfig.renderTargetFormat = renderTargetFormatInfo.internalFormat; + newConfig.depthStencilFormat = depthStencilFormatInfo.internalFormat; newConfig.multiSample = 0; // FIXME: enumerate multi-sampling newConfig.fastConfig = true; // Assume all DX11 format conversions to be fast newConfig.es3Capable = true; @@ -569,8 +410,10 @@ void Renderer11::generateSwizzle(gl::Texture *texture) { TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage->getStorageInstance()); - storage11->generateSwizzles(texture->getSwizzleRed(), texture->getSwizzleGreen(), texture->getSwizzleBlue(), - texture->getSwizzleAlpha()); + storage11->generateSwizzles(texture->getSamplerState().swizzleRed, + texture->getSamplerState().swizzleGreen, + texture->getSamplerState().swizzleBlue, + texture->getSamplerState().swizzleAlpha); } } } @@ -579,11 +422,7 @@ void Renderer11::setSamplerState(gl::SamplerType type, int index, const gl::Samp { 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; - } + ASSERT(static_cast(index) < getRendererCaps().maxTextureImageUnits); if (mForceSetPixelSamplerStates[index] || memcmp(&samplerState, &mCurPixelSamplerStates[index], sizeof(gl::SamplerState)) != 0) { @@ -604,11 +443,7 @@ void Renderer11::setSamplerState(gl::SamplerType type, int index, const gl::Samp } else if (type == gl::SAMPLER_VERTEX) { - if (index < 0 || index >= (int)getMaxVertexTextureImageUnits()) - { - ERR("Vertex shader sampler index %i is not valid.", index); - return; - } + ASSERT(static_cast(index) < getRendererCaps().maxVertexTextureImageUnits); if (mForceSetVertexSamplerStates[index] || memcmp(&samplerState, &mCurVertexSamplerStates[index], sizeof(gl::SamplerState)) != 0) { @@ -637,12 +472,14 @@ void Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *textur if (texture) { - TextureStorageInterface *texStorage = texture->getNativeTexture(); + TextureD3D* textureImpl = TextureD3D::makeTextureD3D(texture->getImplementation()); + + TextureStorageInterface *texStorage = textureImpl->getNativeTexture(); if (texStorage) { TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage->getStorageInstance()); gl::SamplerState samplerState; - texture->getSamplerState(&samplerState); + texture->getSamplerStateWithNativeOffset(&samplerState); textureSRV = storage11->getSRV(samplerState); } @@ -650,16 +487,13 @@ void Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *textur // missing the shader resource view ASSERT(textureSRV != NULL); - forceSetTexture = texture->hasDirtyImages(); + forceSetTexture = textureImpl->hasDirtyImages(); + textureImpl->resetDirty(); } 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; - } + ASSERT(static_cast(index) < getRendererCaps().maxTextureImageUnits); if (forceSetTexture || mCurPixelSRVs[index] != textureSRV) { @@ -670,11 +504,7 @@ void Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *textur } else if (type == gl::SAMPLER_VERTEX) { - if (index < 0 || index >= (int)getMaxVertexTextureImageUnits()) - { - ERR("Vertex shader sampler index %i is not valid.", index); - return; - } + ASSERT(static_cast(index) < getRendererCaps().maxVertexTextureImageUnits); if (forceSetTexture || mCurVertexSRVs[index] != textureSRV) { @@ -693,7 +523,7 @@ bool Renderer11::setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], con const gl::Buffer *uniformBuffer = vertexUniformBuffers[uniformBufferIndex]; if (uniformBuffer) { - BufferStorage11 *bufferStorage = BufferStorage11::makeBufferStorage11(uniformBuffer->getStorage()); + Buffer11 *bufferStorage = Buffer11::makeBuffer11(uniformBuffer->getImplementation()); ID3D11Buffer *constantBuffer = bufferStorage->getBuffer(BUFFER_USAGE_UNIFORM); if (!constantBuffer) @@ -715,7 +545,7 @@ bool Renderer11::setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], con const gl::Buffer *uniformBuffer = fragmentUniformBuffers[uniformBufferIndex]; if (uniformBuffer) { - BufferStorage11 *bufferStorage = BufferStorage11::makeBufferStorage11(uniformBuffer->getStorage()); + Buffer11 *bufferStorage = Buffer11::makeBuffer11(uniformBuffer->getImplementation()); ID3D11Buffer *constantBuffer = bufferStorage->getBuffer(BUFFER_USAGE_UNIFORM); if (!constantBuffer) @@ -803,14 +633,9 @@ void Renderer11::setDepthStencilState(const gl::DepthStencilState &depthStencilS 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); - } + ASSERT(depthStencilState.stencilWritemask == depthStencilState.stencilBackWritemask); + ASSERT(stencilRef == stencilBackRef); + ASSERT(depthStencilState.stencilMask == depthStencilState.stencilBackMask); ID3D11DepthStencilState *dxDepthStencilState = mStateCache.getDepthStencilState(depthStencilState); if (!dxDepthStencilState) @@ -879,17 +704,14 @@ bool Renderer11::setViewport(const gl::Rectangle &viewport, float zNear, float z actualZFar = 1.0f; } - // Get D3D viewport bounds, which depends on the feature level - const Range& viewportBounds = getViewportBounds(); + const gl::Caps& caps = getRendererCaps(); // 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.TopLeftX = gl::clamp(actualViewport.x, -static_cast(caps.maxViewportWidth), static_cast(caps.maxViewportWidth)); + dxViewport.TopLeftY = gl::clamp(actualViewport.y, -static_cast(caps.maxViewportHeight), static_cast(caps.maxViewportHeight)); + dxViewport.Width = gl::clamp(actualViewport.width, 0, static_cast(caps.maxViewportWidth - dxViewport.TopLeftX)); + dxViewport.Height = gl::clamp(actualViewport.height, 0, static_cast(caps.maxViewportHeight - dxViewport.TopLeftY)); dxViewport.MinDepth = actualZNear; dxViewport.MaxDepth = actualZFar; @@ -947,7 +769,8 @@ bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count) // 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); + UNREACHABLE(); + return false; } if (primitiveTopology != mCurrentPrimitiveTopology) @@ -973,20 +796,13 @@ bool Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer) for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) { const GLenum drawBufferState = framebuffer->getDrawBufferState(colorAttachment); + gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(colorAttachment); - if (framebuffer->getColorbufferType(colorAttachment) != GL_NONE && drawBufferState != GL_NONE) + if (colorbuffer && 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. @@ -1026,38 +842,23 @@ bool Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer) } // Get the depth stencil render buffer and serials - gl::Renderbuffer *depthStencil = NULL; + gl::FramebufferAttachment *depthStencil = framebuffer->getDepthbuffer(); unsigned int depthbufferSerial = 0; unsigned int stencilbufferSerial = 0; - if (framebuffer->getDepthbufferType() != GL_NONE) + if (depthStencil) { - depthStencil = framebuffer->getDepthbuffer(); - if (!depthStencil) - { - ERR("Depth stencil pointer unexpectedly null."); - SafeRelease(framebufferRTVs); - return false; - } - depthbufferSerial = depthStencil->getSerial(); } - else if (framebuffer->getStencilbufferType() != GL_NONE) + else if (framebuffer->getStencilbuffer()) { depthStencil = framebuffer->getStencilbuffer(); - if (!depthStencil) - { - ERR("Depth stencil pointer unexpectedly null."); - SafeRelease(framebufferRTVs); - return false; - } - stencilbufferSerial = depthStencil->getSerial(); } ID3D11DepthStencilView* framebufferDSV = NULL; if (depthStencil) { - RenderTarget11 *depthStencilRenderTarget = RenderTarget11::makeRenderTarget11(depthStencil->getDepthStencil()); + RenderTarget11 *depthStencilRenderTarget = RenderTarget11::makeRenderTarget11(depthStencil->getRenderTarget()); if (!depthStencilRenderTarget) { ERR("render target pointer unexpectedly null."); @@ -1089,7 +890,7 @@ bool Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer) depthbufferSerial != mAppliedDepthbufferSerial || stencilbufferSerial != mAppliedStencilbufferSerial) { - mDeviceContext->OMSetRenderTargets(getMaxRenderTargets(), framebufferRTVs, framebufferDSV); + mDeviceContext->OMSetRenderTargets(getRendererCaps().maxDrawBuffers, framebufferRTVs, framebufferDSV); mRenderTargetDesc.width = renderTargetWidth; mRenderTargetDesc.height = renderTargetHeight; @@ -1118,7 +919,7 @@ bool Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer) return true; } -GLenum Renderer11::applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], gl::VertexAttribCurrentValueData currentValues[], +GLenum Renderer11::applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], const gl::VertexAttribCurrentValueData currentValues[], GLint first, GLsizei count, GLsizei instances) { TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS]; @@ -1137,18 +938,17 @@ GLenum Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementAr if (err == GL_NO_ERROR) { - IndexBuffer11* indexBuffer = IndexBuffer11::makeIndexBuffer11(indexInfo->indexBuffer); - ID3D11Buffer *buffer = NULL; - DXGI_FORMAT bufferFormat = indexBuffer->getIndexFormat(); + DXGI_FORMAT bufferFormat = (indexInfo->indexType == GL_UNSIGNED_INT) ? DXGI_FORMAT_R32_UINT : DXGI_FORMAT_R16_UINT; if (indexInfo->storage) { - BufferStorage11 *storage = BufferStorage11::makeBufferStorage11(indexInfo->storage); + Buffer11 *storage = Buffer11::makeBuffer11(indexInfo->storage); buffer = storage->getBuffer(BUFFER_USAGE_INDEX); } else { + IndexBuffer11* indexBuffer = IndexBuffer11::makeIndexBuffer11(indexInfo->indexBuffer); buffer = indexBuffer->getBuffer(); } @@ -1174,8 +974,8 @@ void Renderer11::applyTransformFeedbackBuffers(gl::Buffer *transformFeedbackBuff { if (transformFeedbackBuffers[i]) { - BufferStorage11 *storage = BufferStorage11::makeBufferStorage11(transformFeedbackBuffers[i]->getStorage()); - ID3D11Buffer *buffer = storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK); + Buffer11 *storage = Buffer11::makeBuffer11(transformFeedbackBuffers[i]->getImplementation()); + ID3D11Buffer *buffer = storage->getBuffer(BUFFER_USAGE_TRANSFORM_FEEDBACK); d3dBuffers[i] = buffer; d3dOffsets[i] = (mAppliedTFBuffers[i] != buffer) ? static_cast(offsets[i]) : -1; @@ -1258,21 +1058,23 @@ void Renderer11::drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool void Renderer11::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances) { + int minIndex = static_cast(indexInfo.indexRange.start); + if (mode == GL_LINE_LOOP) { - drawLineLoop(count, type, indices, indexInfo.minIndex, elementArrayBuffer); + drawLineLoop(count, type, indices, minIndex, elementArrayBuffer); } else if (mode == GL_TRIANGLE_FAN) { - drawTriangleFan(count, type, indices, indexInfo.minIndex, elementArrayBuffer, instances); + drawTriangleFan(count, type, indices, minIndex, elementArrayBuffer, instances); } else if (instances > 0) { - mDeviceContext->DrawIndexedInstanced(count, instances, 0, -static_cast(indexInfo.minIndex), 0); + mDeviceContext->DrawIndexedInstanced(count, instances, 0, -minIndex, 0); } else { - mDeviceContext->DrawIndexed(count, 0, -static_cast(indexInfo.minIndex)); + mDeviceContext->DrawIndexed(count, 0, -minIndex); } } @@ -1282,7 +1084,7 @@ void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, if (type != GL_NONE && elementArrayBuffer) { gl::Buffer *indexBuffer = elementArrayBuffer; - BufferStorage *storage = indexBuffer->getStorage(); + BufferImpl *storage = indexBuffer->getImplementation(); intptr_t offset = reinterpret_cast(indices); indices = static_cast(storage->getData()) + offset; } @@ -1372,7 +1174,7 @@ void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat || mAppliedIBOffset != indexBufferOffset) { - mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexBufferOffset); + mDeviceContext->IASetIndexBuffer(d3dIndexBuffer, indexFormat, indexBufferOffset); mAppliedIB = d3dIndexBuffer; mAppliedIBFormat = indexFormat; mAppliedIBOffset = indexBufferOffset; @@ -1387,7 +1189,7 @@ void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indic if (type != GL_NONE && elementArrayBuffer) { gl::Buffer *indexBuffer = elementArrayBuffer; - BufferStorage *storage = indexBuffer->getStorage(); + BufferImpl *storage = indexBuffer->getImplementation(); intptr_t offset = reinterpret_cast(indices); indices = static_cast(storage->getData()) + offset; } @@ -1483,7 +1285,7 @@ void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indic if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat || mAppliedIBOffset != indexBufferOffset) { - mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexBufferOffset); + mDeviceContext->IASetIndexBuffer(d3dIndexBuffer, indexFormat, indexBufferOffset); mAppliedIB = d3dIndexBuffer; mAppliedIBFormat = indexFormat; mAppliedIBOffset = indexBufferOffset; @@ -1499,10 +1301,11 @@ void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indic } } -void Renderer11::applyShaders(gl::ProgramBinary *programBinary, bool rasterizerDiscard, bool transformFeedbackActive, const gl::VertexFormat inputLayout[]) +void Renderer11::applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, + bool rasterizerDiscard, bool transformFeedbackActive) { ShaderExecutable *vertexExe = programBinary->getVertexExecutableForInputLayout(inputLayout); - ShaderExecutable *pixelExe = programBinary->getPixelExecutable(); + ShaderExecutable *pixelExe = programBinary->getPixelExecutableForFramebuffer(framebuffer); ShaderExecutable *geometryExe = programBinary->getGeometryExecutable(); ID3D11VertexShader *vertexShader = (vertexExe ? ShaderExecutable11::makeShaderExecutable11(vertexExe)->getVertexShader() : NULL); @@ -1895,6 +1698,7 @@ bool Renderer11::testDeviceResettable() void Renderer11::release() { + releaseShaderCompiler(); releaseDeviceResources(); SafeRelease(mDxgiFactory); @@ -1969,143 +1773,6 @@ GUID Renderer11::getAdapterIdentifier() const return adapterId; } -bool Renderer11::getBGRATextureSupport() const -{ - return mBGRATextureSupport; -} - -bool Renderer11::getDXT1TextureSupport() const -{ - return mDXT1TextureSupport; -} - -bool Renderer11::getDXT3TextureSupport() const -{ - return mDXT3TextureSupport; -} - -bool Renderer11::getDXT5TextureSupport() const -{ - return mDXT5TextureSupport; -} - -bool Renderer11::getDepthTextureSupport() const -{ - return mDepthTextureSupport; -} - -bool Renderer11::getFloat32TextureSupport() const -{ - return mFloat32TextureSupport; -} - -bool Renderer11::getFloat32TextureFilteringSupport() const -{ - return mFloat32FilterSupport; -} - -bool Renderer11::getFloat32TextureRenderingSupport() const -{ - return mFloat32RenderSupport; -} - -bool Renderer11::getFloat16TextureSupport() const -{ - return mFloat16TextureSupport; -} - -bool Renderer11::getFloat16TextureFilteringSupport() const -{ - return mFloat16FilterSupport; -} - -bool Renderer11::getFloat16TextureRenderingSupport() const -{ - return mFloat16RenderSupport; -} - -bool Renderer11::getRGB565TextureSupport() const -{ - return false; -} - -bool Renderer11::getLuminanceTextureSupport() const -{ - return false; -} - -bool Renderer11::getLuminanceAlphaTextureSupport() const -{ - return false; -} - -bool Renderer11::getRGTextureSupport() const -{ - return mRGTextureSupport; -} - -bool Renderer11::getTextureFilterAnisotropySupport() const -{ - return true; -} - -bool Renderer11::getPBOSupport() 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() const -{ - 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 @@ -2116,72 +1783,6 @@ 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); - META_ASSERT(D3D11_VS_OUTPUT_REGISTER_COUNT <= D3D11_PS_INPUT_REGISTER_COUNT); - META_ASSERT(D3D10_VS_OUTPUT_REGISTER_COUNT <= D3D10_PS_INPUT_REGISTER_COUNT); - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_0: - return D3D11_VS_OUTPUT_REGISTER_COUNT - getReservedVaryings(); - case D3D_FEATURE_LEVEL_10_1: - return D3D10_1_VS_OUTPUT_REGISTER_COUNT - getReservedVaryings(); - case D3D_FEATURE_LEVEL_10_0: - return D3D10_VS_OUTPUT_REGISTER_COUNT - getReservedVaryings(); - default: UNREACHABLE(); - return 0; - } -} - -unsigned int Renderer11::getMaxVertexShaderUniformBuffers() const -{ - META_ASSERT(gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS >= D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT && - gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS >= D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT); - - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_0: - return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - getReservedVertexUniformBuffers(); - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - getReservedVertexUniformBuffers(); - default: UNREACHABLE(); - return 0; - } -} - -unsigned int Renderer11::getMaxFragmentShaderUniformBuffers() const -{ - META_ASSERT(gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS >= D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT && - gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS >= D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT); - - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_0: - return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - getReservedFragmentUniformBuffers(); - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - getReservedFragmentUniformBuffers(); - default: UNREACHABLE(); - return 0; - } -} - unsigned int Renderer11::getReservedVertexUniformBuffers() const { // we reserve one buffer for the application uniforms, and one for driver uniforms @@ -2194,127 +1795,12 @@ unsigned int Renderer11::getReservedFragmentUniformBuffers() const return 2; } -unsigned int Renderer11::getReservedVaryings() const -{ - // We potentially reserve varyings for gl_Position, _dx_Position, gl_FragCoord and gl_PointSize - return 4; -} - - -unsigned int Renderer11::getMaxTransformFeedbackBuffers() const -{ - META_ASSERT(gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS >= D3D11_SO_BUFFER_SLOT_COUNT && - gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS >= D3D10_SO_BUFFER_SLOT_COUNT); - - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_0: - return D3D11_SO_BUFFER_SLOT_COUNT; - case D3D_FEATURE_LEVEL_10_1: - return D3D10_1_SO_BUFFER_SLOT_COUNT; - case D3D_FEATURE_LEVEL_10_0: - return D3D10_SO_BUFFER_SLOT_COUNT; - default: UNREACHABLE(); - return 0; - } -} - -unsigned int Renderer11::getMaxTransformFeedbackSeparateComponents() const -{ - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_0: - return getMaxTransformFeedbackInterleavedComponents() / getMaxTransformFeedbackBuffers(); - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - // D3D 10 and 10.1 only allow one output per output slot if an output slot other than zero - // is used. - return 4; - default: UNREACHABLE(); - return 0; - } -} - -unsigned int Renderer11::getMaxTransformFeedbackInterleavedComponents() const -{ - return (getMaxVaryingVectors() * 4); -} - -unsigned int Renderer11::getMaxUniformBufferSize() const -{ - // Each component is a 4-element vector of 4-byte units (floats) - const unsigned int bytesPerComponent = 4 * sizeof(float); - - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_0: - return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent; - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - return D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent; - 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; - } + return getRendererExtensions().textureFormatBGRA8888 && !gl::perfActive(); } bool Renderer11::getPostSubBufferSupport() const @@ -2323,24 +1809,6 @@ bool Renderer11::getPostSubBufferSupport() const return false; } -int Renderer11::getMaxRecommendedElementsIndices() const -{ - META_ASSERT(D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP == 32); - META_ASSERT(D3D10_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP == 32); - - // D3D11 allows up to 2^32 elements, but we report max signed int for convenience. - return std::numeric_limits::max(); -} - -int Renderer11::getMaxRecommendedElementsVertices() const -{ - META_ASSERT(D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP == 32); - META_ASSERT(D3D10_REQ_DRAW_VERTEX_COUNT_2_TO_EXP == 32); - - // D3D11 allows up to 2^32 elements, but we report max signed int for convenience. - return std::numeric_limits::max(); -} - int Renderer11::getMajorShaderModel() const { switch (mFeatureLevel) @@ -2363,87 +1831,6 @@ int Renderer11::getMinorShaderModel() const } } -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; - } -} - -int Renderer11::getMaxTextureDepth() const -{ - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION; // 2048 - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION; // 2048 - default: UNREACHABLE(); return 0; - } -} - -int Renderer11::getMaxTextureArrayLayers() const -{ - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION; // 2048 - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION; // 512 - 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; @@ -2454,115 +1841,6 @@ int Renderer11::getMaxSwapInterval() const return 4; } -int Renderer11::getMaxSupportedSamples() const -{ - return mMaxSupportedSamples; -} - -GLsizei Renderer11::getMaxSupportedFormatSamples(GLenum internalFormat) const -{ - DXGI_FORMAT format = gl_d3d11::GetRenderableFormat(internalFormat, getCurrentClientVersion()); - MultisampleSupportMap::const_iterator iter = mMultisampleSupportMap.find(format); - return (iter != mMultisampleSupportMap.end()) ? iter->second.maxSupportedSamples : 0; -} - -GLsizei Renderer11::getNumSampleCounts(GLenum internalFormat) const -{ - unsigned int numCounts = 0; - - // D3D11 supports multisampling for signed and unsigned format, but ES 3.0 does not - GLenum componentType = gl::GetComponentType(internalFormat, getCurrentClientVersion()); - if (componentType != GL_INT && componentType != GL_UNSIGNED_INT) - { - DXGI_FORMAT format = gl_d3d11::GetRenderableFormat(internalFormat, getCurrentClientVersion()); - MultisampleSupportMap::const_iterator iter = mMultisampleSupportMap.find(format); - - if (iter != mMultisampleSupportMap.end()) - { - const MultisampleSupportInfo& info = iter->second; - for (int i = 0; i < D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; i++) - { - if (info.qualityLevels[i] > 0) - { - numCounts++; - } - } - } - } - - return numCounts; -} - -void Renderer11::getSampleCounts(GLenum internalFormat, GLsizei bufSize, GLint *params) const -{ - // D3D11 supports multisampling for signed and unsigned format, but ES 3.0 does not - GLenum componentType = gl::GetComponentType(internalFormat, getCurrentClientVersion()); - if (componentType == GL_INT || componentType == GL_UNSIGNED_INT) - { - return; - } - - DXGI_FORMAT format = gl_d3d11::GetRenderableFormat(internalFormat, getCurrentClientVersion()); - MultisampleSupportMap::const_iterator iter = mMultisampleSupportMap.find(format); - - if (iter != mMultisampleSupportMap.end()) - { - const MultisampleSupportInfo& info = iter->second; - int bufPos = 0; - for (int i = D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT - 1; i >= 0 && bufPos < bufSize; i--) - { - if (info.qualityLevels[i] > 0) - { - params[bufPos++] = i + 1; - } - } - } -} - -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: - // Feature level 10.0 and 10.1 cards perform very poorly when the pixel shader - // outputs to multiple RTs that are not bound. - // TODO: Remove pixel shader outputs for render targets that are not bound. - return 1; - default: - UNREACHABLE(); - return 1; - } -} - bool Renderer11::copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source) { if (source && dest) @@ -2634,7 +1912,7 @@ bool Renderer11::copyToRenderTarget(TextureStorageInterface2DArray *dest, Textur 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(); + gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); if (!colorbuffer) { ERR("Failed to retrieve the color buffer from the frame buffer."); @@ -2695,7 +1973,7 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so 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(); + gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); if (!colorbuffer) { ERR("Failed to retrieve the color buffer from the frame buffer."); @@ -2756,7 +2034,7 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, GLint zOffset, TextureStorageInterface3D *storage, GLint level) { - gl::Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer(); + gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); if (!colorbuffer) { ERR("Failed to retrieve the color buffer from the frame buffer."); @@ -2817,7 +2095,7 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, GLint zOffset, TextureStorageInterface2DArray *storage, GLint level) { - gl::Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer(); + gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); if (!colorbuffer) { ERR("Failed to retrieve the color buffer from the frame buffer."); @@ -2888,7 +2166,7 @@ void Renderer11::setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView rtvArray[0] = renderTargetView; - mDeviceContext->OMSetRenderTargets(getMaxRenderTargets(), rtvArray, NULL); + mDeviceContext->OMSetRenderTargets(getRendererCaps().maxDrawBuffers, 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++) @@ -2927,6 +2205,25 @@ RenderTarget *Renderer11::createRenderTarget(int width, int height, GLenum forma return renderTarget; } +ShaderImpl *Renderer11::createShader(GLenum type) +{ + switch (type) + { + case GL_VERTEX_SHADER: + return new VertexShaderD3D(this); + case GL_FRAGMENT_SHADER: + return new FragmentShaderD3D(this); + default: + UNREACHABLE(); + return NULL; + } +} + +void Renderer11::releaseShaderCompiler() +{ + ShaderD3D::releaseCompiler(); +} + ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length, rx::ShaderType type, const std::vector &transformFeedbackVaryings, bool separatedOutputBuffers) @@ -2950,6 +2247,8 @@ ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length for (size_t i = 0; i < transformFeedbackVaryings.size(); i++) { const gl::LinkedVarying &varying = transformFeedbackVaryings[i]; + GLenum transposedType = gl::TransposeMatrixType(varying.type); + for (size_t j = 0; j < varying.semanticIndexCount; j++) { D3D11_SO_DECLARATION_ENTRY entry = { 0 }; @@ -2957,7 +2256,7 @@ ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length entry.SemanticName = varying.semanticName.c_str(); entry.SemanticIndex = varying.semanticIndex + j; entry.StartComponent = 0; - entry.ComponentCount = gl::VariableRowCount(type); + entry.ComponentCount = gl::VariableColumnCount(transposedType); entry.OutputSlot = (separatedOutputBuffers ? i : 0); soDeclaration.push_back(entry); } @@ -3110,9 +2409,14 @@ IndexBuffer *Renderer11::createIndexBuffer() return new IndexBuffer11(this); } -BufferStorage *Renderer11::createBufferStorage() +BufferImpl *Renderer11::createBuffer() { - return new BufferStorage11(this); + return new Buffer11(this); +} + +VertexArrayImpl *Renderer11::createVertexArray() +{ + return new VertexArray11(this); } QueryImpl *Renderer11::createQuery(GLenum type) @@ -3125,36 +2429,39 @@ FenceImpl *Renderer11::createFence() return new Fence11(this); } +TransformFeedbackImpl* Renderer11::createTransformFeedback() +{ + return new TransformFeedbackD3D(); +} + bool Renderer11::supportsFastCopyBufferToTexture(GLenum internalFormat) const { - int clientVersion = getCurrentClientVersion(); + ASSERT(getRendererExtensions().pixelBufferObject); - // We only support buffer to texture copies in ES3 - if (clientVersion <= 2) - { - return false; - } + const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat); + const d3d11::TextureFormat &d3d11FormatInfo = d3d11::GetTextureFormatInfo(internalFormat); + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(d3d11FormatInfo.texFormat); // sRGB formats do not work with D3D11 buffer SRVs - if (gl::GetColorEncoding(internalFormat, clientVersion) == GL_SRGB) + if (internalFormatInfo.colorEncoding == GL_SRGB) { return false; } // We cannot support direct copies to non-color-renderable formats - if (!gl::IsColorRenderingSupported(internalFormat, this)) + if (d3d11FormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN) { return false; } // We skip all 3-channel formats since sometimes format support is missing - if (gl::GetComponentCount(internalFormat, clientVersion) == 3) + if (internalFormatInfo.componentCount == 3) { return false; } // We don't support formats which we can't represent without conversion - if (getNativeTextureFormat(internalFormat) != internalFormat) + if (dxgiFormatInfo.internalFormat != internalFormat) { return false; } @@ -3169,7 +2476,7 @@ bool Renderer11::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, uns return mPixelTransfer->copyBufferToTexture(unpack, offset, destRenderTarget, destinationFormat, sourcePixelsType, destArea); } -bool Renderer11::getRenderTargetResource(gl::Renderbuffer *colorbuffer, unsigned int *subresourceIndex, ID3D11Texture2D **resource) +bool Renderer11::getRenderTargetResource(gl::FramebufferAttachment *colorbuffer, unsigned int *subresourceIndex, ID3D11Texture2D **resource) { ASSERT(colorbuffer != NULL); @@ -3210,7 +2517,7 @@ bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &read { if (blitRenderTarget) { - gl::Renderbuffer *readBuffer = readTarget->getReadColorbuffer(); + gl::FramebufferAttachment *readBuffer = readTarget->getReadColorbuffer(); if (!readBuffer) { @@ -3224,7 +2531,7 @@ bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &read { if (drawTarget->isEnabledColorAttachment(colorAttachment)) { - gl::Renderbuffer *drawBuffer = drawTarget->getColorbuffer(colorAttachment); + gl::FramebufferAttachment *drawBuffer = drawTarget->getColorbuffer(colorAttachment); if (!drawBuffer) { @@ -3245,8 +2552,8 @@ bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &read if (blitDepth || blitStencil) { - gl::Renderbuffer *readBuffer = readTarget->getDepthOrStencilbuffer(); - gl::Renderbuffer *drawBuffer = drawTarget->getDepthOrStencilbuffer(); + gl::FramebufferAttachment *readBuffer = readTarget->getDepthOrStencilbuffer(); + gl::FramebufferAttachment *drawBuffer = drawTarget->getDepthOrStencilbuffer(); if (!readBuffer) { @@ -3260,8 +2567,9 @@ bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &read return gl::error(GL_OUT_OF_MEMORY, false); } - RenderTarget *readRenderTarget = readBuffer->getDepthStencil(); - RenderTarget *drawRenderTarget = drawBuffer->getDepthStencil(); + RenderTarget *readRenderTarget = readBuffer->getRenderTarget(); + RenderTarget *drawRenderTarget = drawBuffer->getRenderTarget(); + ASSERT(readRenderTarget && drawRenderTarget); if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, filter, scissor, false, blitDepth, blitStencil)) @@ -3276,12 +2584,12 @@ bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &read } void Renderer11::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, - GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, void* pixels) + GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) { ID3D11Texture2D *colorBufferTexture = NULL; unsigned int subresourceIndex = 0; - gl::Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer(); + gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); if (colorbuffer && getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture)) { @@ -3291,10 +2599,13 @@ void Renderer11::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsi area.width = width; area.height = height; - if (pack.pixelBuffer.get() != NULL) + gl::Buffer *packBuffer = pack.pixelBuffer.get(); + if (packBuffer != NULL) { - rx::BufferStorage11 *packBufferStorage = BufferStorage11::makeBufferStorage11(pack.pixelBuffer.get()->getStorage()); + rx::Buffer11 *packBufferStorage = Buffer11::makeBuffer11(packBuffer->getImplementation()); PackPixelsParams packParams(area, format, type, outputPitch, pack, reinterpret_cast(pixels)); + + packBuffer->getIndexRangeCache()->clear(); packBufferStorage->packPixels(colorBufferTexture, subresourceIndex, packParams); } else @@ -3315,7 +2626,7 @@ void Renderer11::generateMipmap(Image *dest, Image *src) { Image11 *dest11 = Image11::makeImage11(dest); Image11 *src11 = Image11::makeImage11(src); - Image11::generateMipmap(getCurrentClientVersion(), dest11, src11); + Image11::generateMipmap(dest11, src11); } TextureStorage *Renderer11::createTextureStorage2D(SwapChain *swapChain) @@ -3344,8 +2655,23 @@ TextureStorage *Renderer11::createTextureStorage2DArray(GLenum internalformat, b return new TextureStorage11_2DArray(this, internalformat, renderTarget, width, height, depth, levels); } +TextureImpl *Renderer11::createTexture(GLenum target) +{ + switch(target) + { + case GL_TEXTURE_2D: return new TextureD3D_2D(this); + case GL_TEXTURE_CUBE_MAP: return new TextureD3D_Cube(this); + case GL_TEXTURE_3D: return new TextureD3D_3D(this); + case GL_TEXTURE_2D_ARRAY: return new TextureD3D_2DArray(this); + default: + UNREACHABLE(); + } + + return NULL; +} + void Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area, GLenum format, - GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, void *pixels) + GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) { ASSERT(area.width >= 0); ASSERT(area.height >= 0); @@ -3445,7 +2771,7 @@ void Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int subResou SafeRelease(stagingTex); } -void Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams ¶ms, void *pixelsOut) +void Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams ¶ms, uint8_t *pixelsOut) { D3D11_TEXTURE2D_DESC textureDesc; readTexture->GetDesc(&textureDesc); @@ -3455,41 +2781,37 @@ void Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams UNUSED_ASSERTION_VARIABLE(hr); ASSERT(SUCCEEDED(hr)); - unsigned char *source; + uint8_t *source; int inputPitch; if (params.pack.reverseRowOrder) { - source = static_cast(mapping.pData) + mapping.RowPitch * (params.area.height - 1); + source = static_cast(mapping.pData) + mapping.RowPitch * (params.area.height - 1); inputPitch = -static_cast(mapping.RowPitch); } else { - source = static_cast(mapping.pData); + source = static_cast(mapping.pData); inputPitch = static_cast(mapping.RowPitch); } - GLuint clientVersion = getCurrentClientVersion(); - - GLenum sourceInternalFormat = d3d11_gl::GetInternalFormat(textureDesc.Format, clientVersion); - GLenum sourceFormat = gl::GetFormat(sourceInternalFormat, clientVersion); - GLenum sourceType = gl::GetType(sourceInternalFormat, clientVersion); - - GLuint sourcePixelSize = gl::GetPixelBytes(sourceInternalFormat, clientVersion); - - if (sourceFormat == params.format && sourceType == params.type) + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(textureDesc.Format); + const gl::InternalFormat &sourceFormatInfo = gl::GetInternalFormatInfo(dxgiFormatInfo.internalFormat); + if (sourceFormatInfo.format == params.format && sourceFormatInfo.type == params.type) { - unsigned char *dest = static_cast(pixelsOut) + params.offset; + uint8_t *dest = pixelsOut + params.offset; for (int y = 0; y < params.area.height; y++) { - memcpy(dest + y * params.outputPitch, source + y * inputPitch, params.area.width * sourcePixelSize); + memcpy(dest + y * params.outputPitch, source + y * inputPitch, params.area.width * sourceFormatInfo.pixelBytes); } } else { - GLenum destInternalFormat = gl::GetSizedInternalFormat(params.format, params.type, clientVersion); - GLuint destPixelSize = gl::GetPixelBytes(destInternalFormat, clientVersion); + const d3d11::DXGIFormat &sourceDXGIFormatInfo = d3d11::GetDXGIFormatInfo(textureDesc.Format); + ColorCopyFunction fastCopyFunc = sourceDXGIFormatInfo.getFastCopyFunction(params.format, params.type); + + const gl::FormatType &destFormatTypeInfo = gl::GetFormatTypeInfo(params.format, params.type); + const gl::InternalFormat &destFormatInfo = gl::GetInternalFormatInfo(destFormatTypeInfo.internalFormat); - ColorCopyFunction fastCopyFunc = d3d11::GetFastCopyFunction(textureDesc.Format, params.format, params.type); if (fastCopyFunc) { // Fast copy is possible through some special function @@ -3497,8 +2819,8 @@ void Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams { for (int x = 0; x < params.area.width; x++) { - void *dest = static_cast(pixelsOut) + params.offset + y * params.outputPitch + x * destPixelSize; - void *src = static_cast(source) + y * inputPitch + x * sourcePixelSize; + uint8_t *dest = pixelsOut + params.offset + y * params.outputPitch + x * destFormatInfo.pixelBytes; + const uint8_t *src = source + y * inputPitch + x * sourceFormatInfo.pixelBytes; fastCopyFunc(src, dest); } @@ -3506,10 +2828,7 @@ void Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams } else { - ColorReadFunction readFunc = d3d11::GetColorReadFunction(textureDesc.Format); - ColorWriteFunction writeFunc = gl::GetColorWriteFunction(params.format, params.type, clientVersion); - - unsigned char temp[16]; // Maximum size of any Color type used. + uint8_t temp[16]; // Maximum size of any Color type used. META_ASSERT(sizeof(temp) >= sizeof(gl::ColorF) && sizeof(temp) >= sizeof(gl::ColorUI) && sizeof(temp) >= sizeof(gl::ColorI)); @@ -3518,13 +2837,13 @@ void Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams { for (int x = 0; x < params.area.width; x++) { - void *dest = static_cast(pixelsOut) + params.offset + y * params.outputPitch + x * destPixelSize; - void *src = static_cast(source) + y * inputPitch + x * sourcePixelSize; + uint8_t *dest = pixelsOut + params.offset + y * params.outputPitch + x * destFormatInfo.pixelBytes; + const uint8_t *src = source + y * inputPitch + x * sourceFormatInfo.pixelBytes; // readFunc and writeFunc will be using the same type of color, CopyTexImage // will not allow the copy otherwise. - readFunc(src, temp); - writeFunc(temp, dest); + sourceDXGIFormatInfo.colorReadFunction(src, temp); + destFormatTypeInfo.colorWriteFunction(temp, dest); } } } @@ -3623,9 +2942,8 @@ bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::R drawRect.x < 0 || drawRect.x + drawRect.width > drawSize.width || drawRect.y < 0 || drawRect.y + drawRect.height > drawSize.height; - bool hasDepth = gl::GetDepthBits(drawRenderTarget11->getActualFormat(), getCurrentClientVersion()) > 0; - bool hasStencil = gl::GetStencilBits(drawRenderTarget11->getActualFormat(), getCurrentClientVersion()) > 0; - bool partialDSBlit = (hasDepth && depthBlit) != (hasStencil && stencilBlit); + const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(drawRenderTarget->getActualFormat()); + bool partialDSBlit = (actualFormatInfo.depthBits > 0 && depthBlit) != (actualFormatInfo.stencilBits > 0 && stencilBlit); if (readRenderTarget11->getActualFormat() == drawRenderTarget->getActualFormat() && !stretchRequired && !outOfBounds && !flipRequired && !partialDSBlit && @@ -3699,7 +3017,7 @@ bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::R } else { - GLenum format = gl::GetFormat(drawRenderTarget->getInternalFormat(), getCurrentClientVersion()); + GLenum format = gl::GetInternalFormatInfo(drawRenderTarget->getInternalFormat()).format; result = mBlit->copyTexture(readSRV, readArea, readSize, drawRTV, drawArea, drawSize, scissor, format, filter); } @@ -3749,9 +3067,10 @@ ID3D11Texture2D *Renderer11::resolveMultisampledTexture(ID3D11Texture2D *source, } } -void Renderer11::invalidateRenderbufferSwizzles(gl::Renderbuffer *renderBuffer, int mipLevel) +void Renderer11::invalidateFBOAttachmentSwizzles(gl::FramebufferAttachment *attachment, int mipLevel) { - TextureStorage *texStorage = renderBuffer->getTextureStorage(); + ASSERT(attachment->isTexture()); + TextureStorage *texStorage = attachment->getTextureStorage(); if (texStorage) { TextureStorage11 *texStorage11 = TextureStorage11::makeTextureStorage11(texStorage); @@ -3769,23 +3088,23 @@ void Renderer11::invalidateFramebufferSwizzles(gl::Framebuffer *framebuffer) { for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) { - gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(colorAttachment); - if (colorbuffer) + gl::FramebufferAttachment *attachment = framebuffer->getColorbuffer(colorAttachment); + if (attachment && attachment->isTexture()) { - invalidateRenderbufferSwizzles(colorbuffer, framebuffer->getColorbufferMipLevel(colorAttachment)); + invalidateFBOAttachmentSwizzles(attachment, attachment->mipLevel()); } } - gl::Renderbuffer *depthBuffer = framebuffer->getDepthbuffer(); - if (depthBuffer) + gl::FramebufferAttachment *depthAttachment = framebuffer->getDepthbuffer(); + if (depthAttachment && depthAttachment->isTexture()) { - invalidateRenderbufferSwizzles(depthBuffer, framebuffer->getDepthbufferMipLevel()); + invalidateFBOAttachmentSwizzles(depthAttachment, depthAttachment->mipLevel()); } - gl::Renderbuffer *stencilBuffer = framebuffer->getStencilbuffer(); - if (stencilBuffer) + gl::FramebufferAttachment *stencilAttachment = framebuffer->getStencilbuffer(); + if (stencilAttachment && stencilAttachment->isTexture()) { - invalidateRenderbufferSwizzles(stencilBuffer, framebuffer->getStencilbufferMipLevel()); + invalidateFBOAttachmentSwizzles(stencilAttachment, stencilAttachment->mipLevel()); } } @@ -3809,47 +3128,19 @@ bool Renderer11::getLUID(LUID *adapterLuid) const return true; } -GLenum Renderer11::getNativeTextureFormat(GLenum internalFormat) const -{ - int clientVersion = getCurrentClientVersion(); - return d3d11_gl::GetInternalFormat(gl_d3d11::GetTexFormat(internalFormat, clientVersion), clientVersion); -} - rx::VertexConversionType Renderer11::getVertexConversionType(const gl::VertexFormat &vertexFormat) const { - return gl_d3d11::GetVertexConversionType(vertexFormat); + return d3d11::GetVertexFormatInfo(vertexFormat).conversionType; } GLenum Renderer11::getVertexComponentType(const gl::VertexFormat &vertexFormat) const { - return d3d11::GetComponentType(gl_d3d11::GetNativeVertexFormat(vertexFormat)); + return d3d11::GetDXGIFormatInfo(d3d11::GetVertexFormatInfo(vertexFormat).nativeFormat).componentType; } -Renderer11::MultisampleSupportInfo Renderer11::getMultisampleSupportInfo(DXGI_FORMAT format) +void Renderer11::generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const { - MultisampleSupportInfo supportInfo = { 0 }; - - UINT formatSupport; - HRESULT result; - - result = mDevice->CheckFormatSupport(format, &formatSupport); - if (SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET)) - { - for (unsigned int i = 1; i <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; i++) - { - result = mDevice->CheckMultisampleQualityLevels(format, i, &supportInfo.qualityLevels[i - 1]); - if (SUCCEEDED(result) && supportInfo.qualityLevels[i - 1] > 0) - { - supportInfo.maxSupportedSamples = std::max(supportInfo.maxSupportedSamples, i); - } - else - { - supportInfo.qualityLevels[i - 1] = 0; - } - } - } - - return supportInfo; + d3d11_gl::GenerateCaps(mDevice, outCaps, outTextureCaps, outExtensions); } } diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/Renderer11.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h similarity index 75% rename from gfx/angle/src/libGLESv2/renderer/d3d11/Renderer11.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h index 3e6a54a2af8b..47fcf2906b77 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d11/Renderer11.h +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h @@ -15,13 +15,13 @@ #include "libGLESv2/renderer/Renderer.h" #include "libGLESv2/renderer/d3d/HLSLCompiler.h" -#include "libGLESv2/renderer/d3d11/RenderStateCache.h" -#include "libGLESv2/renderer/d3d11/InputLayoutCache.h" +#include "libGLESv2/renderer/d3d/d3d11/RenderStateCache.h" +#include "libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h" #include "libGLESv2/renderer/RenderTarget.h" namespace gl { -class Renderbuffer; +class FramebufferAttachment; } namespace rx @@ -44,7 +44,7 @@ enum class Renderer11 : public Renderer { public: - Renderer11(egl::Display *display, HDC hDc); + Renderer11(egl::Display *display, EGLNativeDisplayType hDc, EGLint requestedDisplay); virtual ~Renderer11(); static Renderer11 *makeRenderer11(Renderer *renderer); @@ -77,9 +77,10 @@ class Renderer11 : public Renderer virtual bool applyPrimitiveType(GLenum mode, GLsizei count); virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer); - virtual void applyShaders(gl::ProgramBinary *programBinary, bool rasterizerDiscard, bool transformFeedbackActive, const gl::VertexFormat inputLayout[]); + virtual void applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, + bool rasterizerDiscard, bool transformFeedbackActive); virtual void applyUniforms(const gl::ProgramBinary &programBinary); - virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], gl::VertexAttribCurrentValueData currentValues[], + virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], const gl::VertexAttribCurrentValueData currentValues[], 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 applyTransformFeedbackBuffers(gl::Buffer *transformFeedbackBuffers[], GLintptr offsets[]); @@ -98,74 +99,21 @@ class Renderer11 : public Renderer 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() const; - virtual bool getDXT3TextureSupport() const; - virtual bool getDXT5TextureSupport() const; - virtual bool getEventQuerySupport() const; - virtual bool getFloat32TextureSupport() const; - virtual bool getFloat32TextureFilteringSupport() const; - virtual bool getFloat32TextureRenderingSupport() const; - virtual bool getFloat16TextureSupport() const; - virtual bool getFloat16TextureFilteringSupport() const; - virtual bool getFloat16TextureRenderingSupport() const; - virtual bool getRGB565TextureSupport() const; - virtual bool getLuminanceTextureSupport() const; - virtual bool getLuminanceAlphaTextureSupport() const; - virtual bool getRGTextureSupport() const; - 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 unsigned int getMaxVertexShaderUniformBuffers() const; - virtual unsigned int getMaxFragmentShaderUniformBuffers() const; virtual unsigned int getReservedVertexUniformBuffers() const; virtual unsigned int getReservedFragmentUniformBuffers() const; - unsigned int getReservedVaryings() const; - virtual unsigned int getMaxTransformFeedbackBuffers() const; - virtual unsigned int getMaxTransformFeedbackSeparateComponents() const; - virtual unsigned int getMaxTransformFeedbackInterleavedComponents() const; - virtual unsigned int getMaxUniformBufferSize() const; - virtual bool getNonPower2TextureSupport() const; - virtual bool getDepthTextureSupport() const; - virtual bool getOcclusionQuerySupport() const; - virtual bool getInstancingSupport() const; - virtual bool getTextureFilterAnisotropySupport() const; - virtual bool getPBOSupport() const; - virtual float getTextureMaxAnisotropy() const; virtual bool getShareHandleSupport() const; - virtual bool getDerivativeInstructionSupport() const; virtual bool getPostSubBufferSupport() const; - virtual int getMaxRecommendedElementsIndices() const; - virtual int getMaxRecommendedElementsVertices() const; virtual int getMajorShaderModel() const; - virtual float getMaxPointSize() const; - virtual int getMaxViewportDimension() const; - virtual int getMaxTextureWidth() const; - virtual int getMaxTextureHeight() const; - virtual int getMaxTextureDepth() const; - virtual int getMaxTextureArrayLayers() const; - virtual bool get32BitIndexSupport() const; virtual int getMinSwapInterval() const; virtual int getMaxSwapInterval() const; - virtual GLsizei getMaxSupportedSamples() const; - virtual GLsizei getMaxSupportedFormatSamples(GLenum internalFormat) const; - virtual GLsizei getNumSampleCounts(GLenum internalFormat) const; - virtual void getSampleCounts(GLenum internalFormat, GLsizei bufSize, GLint *params) 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); @@ -184,13 +132,17 @@ class Renderer11 : public Renderer virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter); virtual void readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, - GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, void* pixels); + GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels); // RenderTarget creation virtual RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth); virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples); + // Shader creation + virtual ShaderImpl *createShader(GLenum type); + // Shader operations + virtual void releaseShaderCompiler(); virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type, const std::vector &transformFeedbackVaryings, bool separatedOutputBuffers); @@ -208,15 +160,24 @@ class Renderer11 : public Renderer virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels); virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels); + // Texture creation + virtual TextureImpl *createTexture(GLenum target); + // Buffer creation + virtual BufferImpl *createBuffer(); virtual VertexBuffer *createVertexBuffer(); virtual IndexBuffer *createIndexBuffer(); - virtual BufferStorage *createBufferStorage(); + + // Vertex Array creation + virtual VertexArrayImpl *createVertexArray(); // Query and Fence creation virtual QueryImpl *createQuery(GLenum type); virtual FenceImpl *createFence(); + // Transform Feedback creation + virtual TransformFeedbackImpl* createTransformFeedback(); + // D3D11-renderer specific methods ID3D11Device *getDevice() { return mDevice; } ID3D11DeviceContext *getDeviceContext() { return mDeviceContext; }; @@ -229,38 +190,38 @@ class Renderer11 : public Renderer virtual bool fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea); - bool getRenderTargetResource(gl::Renderbuffer *colorbuffer, unsigned int *subresourceIndex, ID3D11Texture2D **resource); + bool getRenderTargetResource(gl::FramebufferAttachment *colorbuffer, unsigned int *subresourceIndex, ID3D11Texture2D **resource); void unapplyRenderTargets(); void setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView); - void packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams ¶ms, void *pixelsOut); + void packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams ¶ms, uint8_t *pixelsOut); virtual bool getLUID(LUID *adapterLuid) const; - virtual GLenum getNativeTextureFormat(GLenum internalFormat) const; virtual rx::VertexConversionType getVertexConversionType(const gl::VertexFormat &vertexFormat) const; virtual GLenum getVertexComponentType(const gl::VertexFormat &vertexFormat) const; private: DISALLOW_COPY_AND_ASSIGN(Renderer11); + virtual void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const; + 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, GLuint outputPitch, const gl::PixelPackState &pack, void *pixels); - - rx::Range getViewportBounds() const; + GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels); bool blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget, RenderTarget *drawRenderTarget, GLenum filter, const gl::Rectangle *scissor, bool colorBlit, bool depthBlit, bool stencilBlit); ID3D11Texture2D *resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource); - static void invalidateRenderbufferSwizzles(gl::Renderbuffer *renderBuffer, int mipLevel); + static void invalidateFBOAttachmentSwizzles(gl::FramebufferAttachment *attachment, int mipLevel); static void invalidateFramebufferSwizzles(gl::Framebuffer *framebuffer); HMODULE mD3d11Module; HMODULE mDxgiModule; HDC mDc; + EGLint mRequestedDisplay; HLSLCompiler mCompiler; @@ -273,36 +234,6 @@ class Renderer11 : public Renderer RenderStateCache mStateCache; - // Support flags - bool mFloat16TextureSupport; - bool mFloat16FilterSupport; - bool mFloat16RenderSupport; - - bool mFloat32TextureSupport; - bool mFloat32FilterSupport; - bool mFloat32RenderSupport; - - bool mDXT1TextureSupport; - bool mDXT3TextureSupport; - bool mDXT5TextureSupport; - - bool mRGTextureSupport; - - bool mDepthTextureSupport; - - // Multisample format support - struct MultisampleSupportInfo - { - unsigned int qualityLevels[D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT]; - unsigned int maxSupportedSamples; - }; - MultisampleSupportInfo getMultisampleSupportInfo(DXGI_FORMAT format); - - 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; @@ -406,9 +337,6 @@ class Renderer11 : public Renderer DXGI_ADAPTER_DESC mAdapterDescription; char mDescription[128]; IDXGIFactory *mDxgiFactory; - - // Cached device caps - bool mBGRATextureSupport; }; } diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/ShaderExecutable11.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.cpp similarity index 96% rename from gfx/angle/src/libGLESv2/renderer/d3d11/ShaderExecutable11.cpp rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.cpp index de2eeda4fc86..52f34887fb19 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d11/ShaderExecutable11.cpp +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -8,9 +7,8 @@ // ShaderExecutable11.cpp: Implements a D3D11-specific class to contain shader // executable implementation details. -#include "libGLESv2/renderer/d3d11/ShaderExecutable11.h" - -#include "libGLESv2/renderer/d3d11/Renderer11.h" +#include "libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h" +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" namespace rx { diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/ShaderExecutable11.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/ShaderExecutable11.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/SwapChain11.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp similarity index 92% rename from gfx/angle/src/libGLESv2/renderer/d3d11/SwapChain11.cpp rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp index a15d061feaf4..5ec132e0ec53 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d11/SwapChain11.cpp +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -7,13 +6,14 @@ // SwapChain11.cpp: Implements a back-end specific class for the D3D11 swap chain. -#include "libGLESv2/renderer/d3d11/SwapChain11.h" +#include "libGLESv2/renderer/d3d/d3d11/SwapChain11.h" +#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" +#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" -#include "libGLESv2/renderer/d3d11/renderer11_utils.h" -#include "libGLESv2/renderer/d3d11/formatutils11.h" -#include "libGLESv2/renderer/d3d11/Renderer11.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthrough2d11vs.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba2d11ps.h" +// Precompiled shaders +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h" namespace rx { @@ -102,6 +102,8 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei releaseOffscreenTexture(); + const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mBackBufferFormat); + // If the app passed in a share handle, open the resource // See EGL_ANGLE_d3d_share_handle_client_buffer if (mAppCreatedShareHandle) @@ -130,11 +132,11 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; mOffscreenTexture->GetDesc(&offscreenTextureDesc); - if (offscreenTextureDesc.Width != (UINT)backbufferWidth - || offscreenTextureDesc.Height != (UINT)backbufferHeight - || offscreenTextureDesc.Format != gl_d3d11::GetTexFormat(mBackBufferFormat, mRenderer->getCurrentClientVersion()) - || offscreenTextureDesc.MipLevels != 1 - || offscreenTextureDesc.ArraySize != 1) + if (offscreenTextureDesc.Width != (UINT)backbufferWidth || + offscreenTextureDesc.Height != (UINT)backbufferHeight || + offscreenTextureDesc.Format != backbufferFormatInfo.texFormat || + offscreenTextureDesc.MipLevels != 1 || + offscreenTextureDesc.ArraySize != 1) { ERR("Invalid texture parameters in the shared offscreen texture pbuffer"); release(); @@ -148,7 +150,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; offscreenTextureDesc.Width = backbufferWidth; offscreenTextureDesc.Height = backbufferHeight; - offscreenTextureDesc.Format = gl_d3d11::GetTexFormat(mBackBufferFormat, mRenderer->getCurrentClientVersion()); + offscreenTextureDesc.Format = backbufferFormatInfo.texFormat; offscreenTextureDesc.MipLevels = 1; offscreenTextureDesc.ArraySize = 1; offscreenTextureDesc.SampleDesc.Count = 1; @@ -204,7 +206,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei D3D11_RENDER_TARGET_VIEW_DESC offscreenRTVDesc; - offscreenRTVDesc.Format = gl_d3d11::GetRTVFormat(mBackBufferFormat, mRenderer->getCurrentClientVersion()); + offscreenRTVDesc.Format = backbufferFormatInfo.rtvFormat; offscreenRTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; offscreenRTVDesc.Texture2D.MipSlice = 0; @@ -213,7 +215,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei d3d11::SetDebugName(mOffscreenRTView, "Offscreen back buffer render target"); D3D11_SHADER_RESOURCE_VIEW_DESC offscreenSRVDesc; - offscreenSRVDesc.Format = gl_d3d11::GetSRVFormat(mBackBufferFormat, mRenderer->getCurrentClientVersion()); + offscreenSRVDesc.Format = backbufferFormatInfo.srvFormat; offscreenSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; offscreenSRVDesc.Texture2D.MostDetailedMip = 0; offscreenSRVDesc.Texture2D.MipLevels = -1; @@ -222,12 +224,14 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mOffscreenSRView, "Offscreen back buffer shader resource"); + const d3d11::TextureFormat &depthBufferFormatInfo = d3d11::GetTextureFormatInfo(mDepthBufferFormat); + if (mDepthBufferFormat != GL_NONE) { D3D11_TEXTURE2D_DESC depthStencilTextureDesc; depthStencilTextureDesc.Width = backbufferWidth; depthStencilTextureDesc.Height = backbufferHeight; - depthStencilTextureDesc.Format = gl_d3d11::GetTexFormat(mDepthBufferFormat, mRenderer->getCurrentClientVersion()); + depthStencilTextureDesc.Format = depthBufferFormatInfo.texFormat; depthStencilTextureDesc.MipLevels = 1; depthStencilTextureDesc.ArraySize = 1; depthStencilTextureDesc.SampleDesc.Count = 1; @@ -255,7 +259,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei d3d11::SetDebugName(mDepthStencilTexture, "Offscreen depth stencil texture"); D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilDesc; - depthStencilDesc.Format = gl_d3d11::GetDSVFormat(mDepthBufferFormat, mRenderer->getCurrentClientVersion()); + depthStencilDesc.Format = depthBufferFormatInfo.dsvFormat; depthStencilDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; depthStencilDesc.Flags = 0; depthStencilDesc.Texture2D.MipSlice = 0; @@ -265,7 +269,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei d3d11::SetDebugName(mDepthStencilDSView, "Offscreen depth stencil view"); D3D11_SHADER_RESOURCE_VIEW_DESC depthStencilSRVDesc; - depthStencilSRVDesc.Format = gl_d3d11::GetSRVFormat(mDepthBufferFormat, mRenderer->getCurrentClientVersion()); + depthStencilSRVDesc.Format = depthBufferFormatInfo.srvFormat; depthStencilSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; depthStencilSRVDesc.Texture2D.MostDetailedMip = 0; depthStencilSRVDesc.Texture2D.MipLevels = -1; @@ -325,8 +329,8 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) SafeRelease(mBackBufferRTView); // Resize swap chain - DXGI_FORMAT backbufferDXGIFormat = gl_d3d11::GetTexFormat(mBackBufferFormat, mRenderer->getCurrentClientVersion()); - HRESULT result = mSwapChain->ResizeBuffers(1, backbufferWidth, backbufferHeight, backbufferDXGIFormat, 0); + const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mBackBufferFormat); + HRESULT result = mSwapChain->ResizeBuffers(1, backbufferWidth, backbufferHeight, backbufferFormatInfo.texFormat, 0); if (FAILED(result)) { @@ -391,6 +395,8 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap if (mWindow) { + const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mBackBufferFormat); + IDXGIFactory *factory = mRenderer->getDxgiFactory(); DXGI_SWAP_CHAIN_DESC swapChainDesc = {0}; @@ -398,7 +404,7 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap swapChainDesc.BufferDesc.Height = backbufferHeight; swapChainDesc.BufferDesc.RefreshRate.Numerator = 0; swapChainDesc.BufferDesc.RefreshRate.Denominator = 1; - swapChainDesc.BufferDesc.Format = gl_d3d11::GetTexFormat(mBackBufferFormat, mRenderer->getCurrentClientVersion()); + swapChainDesc.BufferDesc.Format = backbufferFormatInfo.texFormat; swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; swapChainDesc.SampleDesc.Count = 1; @@ -584,7 +590,7 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) // Draw deviceContext->Draw(4, 0); -#if ANGLE_FORCE_VSYNC_OFF +#ifdef ANGLE_FORCE_VSYNC_OFF result = mSwapChain->Present(0, 0); #else result = mSwapChain->Present(mSwapInterval, 0); @@ -593,7 +599,7 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) if (result == DXGI_ERROR_DEVICE_REMOVED) { HRESULT removedReason = device->GetDeviceRemovedReason(); - UNUSED_ASSERTION_VARIABLE(removedReason); + UNUSED_TRACE_VARIABLE(removedReason); ERR("Present failed: the D3D11 device was removed: 0x%08X", removedReason); return EGL_CONTEXT_LOST; } diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/SwapChain11.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/SwapChain11.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp similarity index 73% rename from gfx/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.cpp rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp index 7e024accb806..10a5e7e55087 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.cpp +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp @@ -1,6 +1,5 @@ -#include "precompiled.h" // -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2012-2014 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,17 +7,18 @@ // 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/d3d11/TextureStorage11.h" - -#include "libGLESv2/renderer/d3d11/Renderer11.h" -#include "libGLESv2/renderer/d3d11/RenderTarget11.h" -#include "libGLESv2/renderer/d3d11/SwapChain11.h" -#include "libGLESv2/renderer/d3d11/renderer11_utils.h" -#include "libGLESv2/renderer/d3d11/Blit11.h" -#include "libGLESv2/renderer/d3d11/formatutils11.h" +#include "libGLESv2/renderer/d3d/d3d11/TextureStorage11.h" +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" +#include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h" +#include "libGLESv2/renderer/d3d/d3d11/SwapChain11.h" +#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" +#include "libGLESv2/renderer/d3d/d3d11/Blit11.h" +#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" +#include "libGLESv2/renderer/d3d/d3d11/Image11.h" +#include "libGLESv2/renderer/d3d/TextureD3D.h" +#include "libGLESv2/main.h" #include "common/utilities.h" -#include "libGLESv2/main.h" namespace rx { @@ -121,19 +121,20 @@ TextureStorage11 *TextureStorage11::makeTextureStorage11(TextureStorage *storage return static_cast(storage); } -DWORD TextureStorage11::GetTextureBindFlags(GLenum internalFormat, GLuint clientVersion, bool renderTarget) +DWORD TextureStorage11::GetTextureBindFlags(GLenum internalFormat, bool renderTarget) { UINT bindFlags = 0; - if (gl_d3d11::GetSRVFormat(internalFormat, clientVersion) != DXGI_FORMAT_UNKNOWN) + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalFormat); + if (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN) { bindFlags |= D3D11_BIND_SHADER_RESOURCE; } - if (gl_d3d11::GetDSVFormat(internalFormat, clientVersion) != DXGI_FORMAT_UNKNOWN) + if (formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN) { bindFlags |= D3D11_BIND_DEPTH_STENCIL; } - if (gl_d3d11::GetRTVFormat(internalFormat, clientVersion) != DXGI_FORMAT_UNKNOWN && renderTarget) + if (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN && renderTarget) { bindFlags |= D3D11_BIND_RENDER_TARGET; } @@ -307,7 +308,8 @@ bool TextureStorage11::updateSubresourceLevel(ID3D11Resource *srcTexture, unsign ASSERT(dstTexture); - if (!fullCopy && (d3d11::GetDepthBits(mTextureFormat) > 0 || d3d11::GetStencilBits(mTextureFormat) > 0)) + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mTextureFormat); + if (!fullCopy && (dxgiFormatInfo.depthBits > 0 || dxgiFormatInfo.stencilBits > 0)) { // CopySubresourceRegion cannot copy partial depth stencils, use the blitter instead Blit11 *blitter = mRenderer->getBlitter(); @@ -318,11 +320,13 @@ bool TextureStorage11::updateSubresourceLevel(ID3D11Resource *srcTexture, unsign } else { + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mTextureFormat); + D3D11_BOX srcBox; srcBox.left = copyArea.x; srcBox.top = copyArea.y; - srcBox.right = copyArea.x + roundUp((unsigned int)width, d3d11::GetBlockWidth(mTextureFormat)); - srcBox.bottom = copyArea.y + roundUp((unsigned int)height, d3d11::GetBlockHeight(mTextureFormat)); + srcBox.right = copyArea.x + roundUp((unsigned int)width, dxgiFormatInfo.blockWidth); + srcBox.bottom = copyArea.y + roundUp((unsigned int)height, dxgiFormatInfo.blockHeight); srcBox.front = copyArea.z; srcBox.back = copyArea.z + copyArea.depth; @@ -337,6 +341,27 @@ bool TextureStorage11::updateSubresourceLevel(ID3D11Resource *srcTexture, unsign return false; } +bool TextureStorage11::copySubresourceLevel(ID3D11Resource* dstTexture, unsigned int dstSubresource, + int level, int layerTarget, GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth) +{ + if (dstTexture) + { + ID3D11Resource *srcTexture = getResource(); + unsigned int srcSubresource = getSubresourceIndex(level + mTopLevel, layerTarget); + + ASSERT(srcTexture); + + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + context->CopySubresourceRegion(dstTexture, dstSubresource, xoffset, yoffset, zoffset, + srcTexture, srcSubresource, NULL); + return true; + } + + return false; +} + void TextureStorage11::generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest) { if (source && dest) @@ -355,8 +380,7 @@ void TextureStorage11::generateMipmapLayer(RenderTarget11 *source, RenderTarget1 Blit11 *blitter = mRenderer->getBlitter(); blitter->copyTexture(sourceSRV, sourceArea, sourceSize, destRTV, destArea, destSize, NULL, - gl::GetFormat(source->getInternalFormat(), mRenderer->getCurrentClientVersion()), - GL_LINEAR); + gl::GetInternalFormatInfo(source->getInternalFormat()).format, GL_LINEAR); } } } @@ -379,6 +403,7 @@ TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapch for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) { + mAssociatedImages[i] = NULL; mRenderTarget[i] = NULL; mSwizzleRenderTargets[i] = NULL; } @@ -401,35 +426,36 @@ TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapch offscreenRTV->GetDesc(&rtvDesc); mRenderTargetFormat = rtvDesc.Format; - GLint internalFormat = d3d11_gl::GetInternalFormat(mTextureFormat, renderer->getCurrentClientVersion()); - mSwizzleTextureFormat = gl_d3d11::GetSwizzleTexFormat(internalFormat, renderer); - mSwizzleShaderResourceFormat = gl_d3d11::GetSwizzleSRVFormat(internalFormat, renderer); - mSwizzleRenderTargetFormat = gl_d3d11::GetSwizzleRTVFormat(internalFormat, renderer); + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mTextureFormat); + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(dxgiFormatInfo.internalFormat); + mSwizzleTextureFormat = formatInfo.swizzleTexFormat; + mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat; + mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat; mDepthStencilFormat = DXGI_FORMAT_UNKNOWN; } TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) - : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderer->getCurrentClientVersion(), renderTarget)) + : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget)) { mTexture = NULL; mSwizzleTexture = NULL; for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) { + mAssociatedImages[i] = NULL; mRenderTarget[i] = NULL; mSwizzleRenderTargets[i] = NULL; } - GLuint clientVersion = mRenderer->getCurrentClientVersion(); - - mTextureFormat = gl_d3d11::GetTexFormat(internalformat, clientVersion); - mShaderResourceFormat = gl_d3d11::GetSRVFormat(internalformat, clientVersion); - mDepthStencilFormat = gl_d3d11::GetDSVFormat(internalformat, clientVersion); - mRenderTargetFormat = gl_d3d11::GetRTVFormat(internalformat, clientVersion); - mSwizzleTextureFormat = gl_d3d11::GetSwizzleTexFormat(internalformat, renderer); - mSwizzleShaderResourceFormat = gl_d3d11::GetSwizzleSRVFormat(internalformat, renderer); - mSwizzleRenderTargetFormat = gl_d3d11::GetSwizzleRTVFormat(internalformat, renderer); + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat); + mTextureFormat = formatInfo.texFormat; + mShaderResourceFormat = formatInfo.srvFormat; + mDepthStencilFormat = formatInfo.dsvFormat; + mRenderTargetFormat = formatInfo.rtvFormat; + mSwizzleTextureFormat = formatInfo.swizzleTexFormat; + mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat; + mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat; // 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 @@ -480,6 +506,21 @@ TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, GLenum internalform TextureStorage11_2D::~TextureStorage11_2D() { + for (unsigned i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + if (mAssociatedImages[i] != NULL) + { + bool imageAssociationCorrect = mAssociatedImages[i]->isAssociatedStorageValid(this); + ASSERT(imageAssociationCorrect); + + if (imageAssociationCorrect) + { + // We must let the Images recover their data before we delete it from the TextureStorage. + mAssociatedImages[i]->recoverFromAssociatedStorage(); + } + } + } + SafeRelease(mTexture); SafeRelease(mSwizzleTexture); @@ -496,6 +537,69 @@ TextureStorage11_2D *TextureStorage11_2D::makeTextureStorage11_2D(TextureStorage return static_cast(storage); } +void TextureStorage11_2D::associateImage(Image11* image, int level, int layerTarget) +{ + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + mAssociatedImages[level] = image; + } +} + +bool TextureStorage11_2D::isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage) +{ + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + // This validation check should never return false. It means the Image/TextureStorage association is broken. + bool retValue = (mAssociatedImages[level] == expectedImage); + ASSERT(retValue); + return retValue; + } + + return false; +} + +// disassociateImage allows an Image to end its association with a Storage. +void TextureStorage11_2D::disassociateImage(int level, int layerTarget, Image11* expectedImage) +{ + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + ASSERT(mAssociatedImages[level] == expectedImage); + + if (mAssociatedImages[level] == expectedImage) + { + mAssociatedImages[level] = NULL; + } + } +} + +// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association. +void TextureStorage11_2D::releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage) +{ + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + // No need to let the old Image recover its data, if it is also the incoming Image. + if (mAssociatedImages[level] != NULL && mAssociatedImages[level] != incomingImage) + { + // Ensure that the Image is still associated with this TextureStorage. This should be true. + bool imageAssociationCorrect = mAssociatedImages[level]->isAssociatedStorageValid(this); + ASSERT(imageAssociationCorrect); + + if (imageAssociationCorrect) + { + // Force the image to recover from storage before its data is overwritten. + // This will reset mAssociatedImages[level] to NULL too. + mAssociatedImages[level]->recoverFromAssociatedStorage(); + } + } + } +} + ID3D11Resource *TextureStorage11_2D::getResource() const { return mTexture; @@ -679,7 +783,7 @@ unsigned int TextureStorage11_2D::getTextureLevelDepth(int mipLevel) const } TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, GLenum internalformat, bool renderTarget, int size, int levels) - : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderer->getCurrentClientVersion(), renderTarget)) + : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget)) { mTexture = NULL; mSwizzleTexture = NULL; @@ -689,19 +793,19 @@ TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, GLenum internal mSwizzleRenderTargets[level] = NULL; for (unsigned int face = 0; face < 6; face++) { + mAssociatedImages[face][level] = NULL; mRenderTarget[face][level] = NULL; } } - GLuint clientVersion = mRenderer->getCurrentClientVersion(); - - mTextureFormat = gl_d3d11::GetTexFormat(internalformat, clientVersion); - mShaderResourceFormat = gl_d3d11::GetSRVFormat(internalformat, clientVersion); - mDepthStencilFormat = gl_d3d11::GetDSVFormat(internalformat, clientVersion); - mRenderTargetFormat = gl_d3d11::GetRTVFormat(internalformat, clientVersion); - mSwizzleTextureFormat = gl_d3d11::GetSwizzleTexFormat(internalformat, renderer); - mSwizzleShaderResourceFormat = gl_d3d11::GetSwizzleSRVFormat(internalformat, renderer); - mSwizzleRenderTargetFormat = gl_d3d11::GetSwizzleRTVFormat(internalformat, renderer); + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat); + mTextureFormat = formatInfo.texFormat; + mShaderResourceFormat = formatInfo.srvFormat; + mDepthStencilFormat = formatInfo.dsvFormat; + mRenderTargetFormat = formatInfo.rtvFormat; + mSwizzleTextureFormat = formatInfo.swizzleTexFormat; + mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat; + mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat; // if the size is not positive this should be treated as an incomplete texture // we handle that here by skipping the d3d texture creation @@ -747,6 +851,24 @@ TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, GLenum internal TextureStorage11_Cube::~TextureStorage11_Cube() { + for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + for (unsigned int face = 0; face < 6; face++) + { + if (mAssociatedImages[face][level] != NULL) + { + bool imageAssociationCorrect = mAssociatedImages[face][level]->isAssociatedStorageValid(this); + ASSERT(imageAssociationCorrect); + + if (imageAssociationCorrect) + { + // We must let the Images recover their data before we delete it from the TextureStorage. + mAssociatedImages[face][level]->recoverFromAssociatedStorage(); + } + } + } + } + SafeRelease(mTexture); SafeRelease(mSwizzleTexture); @@ -766,6 +888,84 @@ TextureStorage11_Cube *TextureStorage11_Cube::makeTextureStorage11_Cube(TextureS return static_cast(storage); } +void TextureStorage11_Cube::associateImage(Image11* image, int level, int layerTarget) +{ + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT(0 <= layerTarget && layerTarget < 6); + + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + if (0 <= layerTarget && layerTarget < 6) + { + mAssociatedImages[layerTarget][level] = image; + } + } +} + +bool TextureStorage11_Cube::isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage) +{ + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + if (0 <= layerTarget && layerTarget < 6) + { + // This validation check should never return false. It means the Image/TextureStorage association is broken. + bool retValue = (mAssociatedImages[layerTarget][level] == expectedImage); + ASSERT(retValue); + return retValue; + } + } + + return false; +} + +// disassociateImage allows an Image to end its association with a Storage. +void TextureStorage11_Cube::disassociateImage(int level, int layerTarget, Image11* expectedImage) +{ + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT(0 <= layerTarget && layerTarget < 6); + + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + if (0 <= layerTarget && layerTarget < 6) + { + ASSERT(mAssociatedImages[layerTarget][level] == expectedImage); + + if (mAssociatedImages[layerTarget][level] == expectedImage) + { + mAssociatedImages[layerTarget][level] = NULL; + } + } + } +} + +// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association. +void TextureStorage11_Cube::releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage) +{ + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT(0 <= layerTarget && layerTarget < 6); + + if ((0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)) + { + if (0 <= layerTarget && layerTarget < 6) + { + // No need to let the old Image recover its data, if it is also the incoming Image. + if (mAssociatedImages[layerTarget][level] != NULL && mAssociatedImages[layerTarget][level] != incomingImage) + { + // Ensure that the Image is still associated with this TextureStorage. This should be true. + bool imageAssociationCorrect = mAssociatedImages[layerTarget][level]->isAssociatedStorageValid(this); + ASSERT(imageAssociationCorrect); + + if (imageAssociationCorrect) + { + // Force the image to recover from storage before its data is overwritten. + // This will reset mAssociatedImages[level] to NULL too. + mAssociatedImages[layerTarget][level]->recoverFromAssociatedStorage(); + } + } + } + } +} + ID3D11Resource *TextureStorage11_Cube::getResource() const { return mTexture; @@ -775,7 +975,7 @@ RenderTarget *TextureStorage11_Cube::getRenderTargetFace(GLenum faceTarget, int { if (level >= 0 && level < getLevelCount()) { - int faceIndex = gl::TextureCubeMap::targetToIndex(faceTarget); + int faceIndex = gl::TextureCubeMap::targetToLayerIndex(faceTarget); if (!mRenderTarget[faceIndex][level]) { ID3D11Device *device = mRenderer->getDevice(); @@ -869,10 +1069,8 @@ ID3D11ShaderResourceView *TextureStorage11_Cube::createSRV(int baseLevel, int mi srvDesc.Format = format; // Unnormalized integer cube maps are not supported by DX11; we emulate them as an array of six 2D textures - bool unnormalizedInteger = (d3d11::GetComponentType(mTextureFormat) == GL_INT || - d3d11::GetComponentType(mTextureFormat) == GL_UNSIGNED_INT); - - if(unnormalizedInteger) + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(format); + if (dxgiFormatInfo.componentType == GL_INT || dxgiFormatInfo.componentType == GL_UNSIGNED_INT) { srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel; @@ -987,26 +1185,26 @@ unsigned int TextureStorage11_Cube::getTextureLevelDepth(int mipLevel) const TextureStorage11_3D::TextureStorage11_3D(Renderer *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) - : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderer->getCurrentClientVersion(), renderTarget)) + : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget)) { mTexture = NULL; mSwizzleTexture = NULL; for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) { + mAssociatedImages[i] = NULL; mLevelRenderTargets[i] = NULL; mSwizzleRenderTargets[i] = NULL; } - GLuint clientVersion = mRenderer->getCurrentClientVersion(); - - mTextureFormat = gl_d3d11::GetTexFormat(internalformat, clientVersion); - mShaderResourceFormat = gl_d3d11::GetSRVFormat(internalformat, clientVersion); - mDepthStencilFormat = gl_d3d11::GetDSVFormat(internalformat, clientVersion); - mRenderTargetFormat = gl_d3d11::GetRTVFormat(internalformat, clientVersion); - mSwizzleTextureFormat = gl_d3d11::GetSwizzleTexFormat(internalformat, renderer); - mSwizzleShaderResourceFormat = gl_d3d11::GetSwizzleSRVFormat(internalformat, renderer); - mSwizzleRenderTargetFormat = gl_d3d11::GetSwizzleRTVFormat(internalformat, renderer); + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat); + mTextureFormat = formatInfo.texFormat; + mShaderResourceFormat = formatInfo.srvFormat; + mDepthStencilFormat = formatInfo.dsvFormat; + mRenderTargetFormat = formatInfo.rtvFormat; + mSwizzleTextureFormat = formatInfo.swizzleTexFormat; + mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat; + mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat; // If the width, height or depth are not positive this should be treated as an incomplete texture // we handle that here by skipping the d3d texture creation @@ -1055,6 +1253,21 @@ TextureStorage11_3D::TextureStorage11_3D(Renderer *renderer, GLenum internalform TextureStorage11_3D::~TextureStorage11_3D() { + for (unsigned i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + if (mAssociatedImages[i] != NULL) + { + bool imageAssociationCorrect = mAssociatedImages[i]->isAssociatedStorageValid(this); + ASSERT(imageAssociationCorrect); + + if (imageAssociationCorrect) + { + // We must let the Images recover their data before we delete it from the TextureStorage. + mAssociatedImages[i]->recoverFromAssociatedStorage(); + } + } + } + SafeRelease(mTexture); SafeRelease(mSwizzleTexture); @@ -1077,6 +1290,69 @@ TextureStorage11_3D *TextureStorage11_3D::makeTextureStorage11_3D(TextureStorage return static_cast(storage); } +void TextureStorage11_3D::associateImage(Image11* image, int level, int layerTarget) +{ + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + mAssociatedImages[level] = image; + } +} + +bool TextureStorage11_3D::isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage) +{ + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + // This validation check should never return false. It means the Image/TextureStorage association is broken. + bool retValue = (mAssociatedImages[level] == expectedImage); + ASSERT(retValue); + return retValue; + } + + return false; +} + +// disassociateImage allows an Image to end its association with a Storage. +void TextureStorage11_3D::disassociateImage(int level, int layerTarget, Image11* expectedImage) +{ + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + ASSERT(mAssociatedImages[level] == expectedImage); + + if (mAssociatedImages[level] == expectedImage) + { + mAssociatedImages[level] = NULL; + } + } +} + +// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association. +void TextureStorage11_3D::releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage) +{ + ASSERT((0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)); + + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + // No need to let the old Image recover its data, if it is also the incoming Image. + if (mAssociatedImages[level] != NULL && mAssociatedImages[level] != incomingImage) + { + // Ensure that the Image is still associated with this TextureStorage. This should be true. + bool imageAssociationCorrect = mAssociatedImages[level]->isAssociatedStorageValid(this); + ASSERT(imageAssociationCorrect); + + if (imageAssociationCorrect) + { + // Force the image to recover from storage before its data is overwritten. + // This will reset mAssociatedImages[level] to NULL too. + mAssociatedImages[level]->recoverFromAssociatedStorage(); + } + } + } +} + ID3D11Resource *TextureStorage11_3D::getResource() const { return mTexture; @@ -1293,7 +1569,7 @@ unsigned int TextureStorage11_3D::getTextureLevelDepth(int mipLevel) const TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) - : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderer->getCurrentClientVersion(), renderTarget)) + : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget)) { mTexture = NULL; mSwizzleTexture = NULL; @@ -1303,15 +1579,14 @@ TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer *renderer, GLenum in mSwizzleRenderTargets[level] = NULL; } - GLuint clientVersion = mRenderer->getCurrentClientVersion(); - - mTextureFormat = gl_d3d11::GetTexFormat(internalformat, clientVersion); - mShaderResourceFormat = gl_d3d11::GetSRVFormat(internalformat, clientVersion); - mDepthStencilFormat = gl_d3d11::GetDSVFormat(internalformat, clientVersion); - mRenderTargetFormat = gl_d3d11::GetRTVFormat(internalformat, clientVersion); - mSwizzleTextureFormat = gl_d3d11::GetSwizzleTexFormat(internalformat, renderer); - mSwizzleShaderResourceFormat = gl_d3d11::GetSwizzleSRVFormat(internalformat, renderer); - mSwizzleRenderTargetFormat = gl_d3d11::GetSwizzleRTVFormat(internalformat, renderer); + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat); + mTextureFormat = formatInfo.texFormat; + mShaderResourceFormat = formatInfo.srvFormat; + mDepthStencilFormat = formatInfo.dsvFormat; + mRenderTargetFormat = formatInfo.rtvFormat; + mSwizzleTextureFormat = formatInfo.swizzleTexFormat; + mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat; + mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat; // if the width, height or depth is not positive this should be treated as an incomplete texture // we handle that here by skipping the d3d texture creation @@ -1362,6 +1637,19 @@ TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer *renderer, GLenum in TextureStorage11_2DArray::~TextureStorage11_2DArray() { + for (ImageMap::iterator i = mAssociatedImages.begin(); i != mAssociatedImages.end(); i++) + { + bool imageAssociationCorrect = i->second->isAssociatedStorageValid(this); + ASSERT(imageAssociationCorrect); + + if (imageAssociationCorrect) + { + // We must let the Images recover their data before we delete it from the TextureStorage. + i->second->recoverFromAssociatedStorage(); + } + } + mAssociatedImages.clear(); + SafeRelease(mTexture); SafeRelease(mSwizzleTexture); @@ -1383,6 +1671,66 @@ TextureStorage11_2DArray *TextureStorage11_2DArray::makeTextureStorage11_2DArray return static_cast(storage); } +void TextureStorage11_2DArray::associateImage(Image11* image, int level, int layerTarget) +{ + ASSERT(0 <= level && level < getLevelCount()); + + if (0 <= level && level < getLevelCount()) + { + LevelLayerKey key(level, layerTarget); + mAssociatedImages[key] = image; + } +} + +bool TextureStorage11_2DArray::isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage) +{ + LevelLayerKey key(level, layerTarget); + + // This validation check should never return false. It means the Image/TextureStorage association is broken. + bool retValue = (mAssociatedImages.find(key) != mAssociatedImages.end() && (mAssociatedImages[key] == expectedImage)); + ASSERT(retValue); + return retValue; +} + +// disassociateImage allows an Image to end its association with a Storage. +void TextureStorage11_2DArray::disassociateImage(int level, int layerTarget, Image11* expectedImage) +{ + LevelLayerKey key(level, layerTarget); + + bool imageAssociationCorrect = (mAssociatedImages.find(key) != mAssociatedImages.end() && (mAssociatedImages[key] == expectedImage)); + ASSERT(imageAssociationCorrect); + + if (imageAssociationCorrect) + { + mAssociatedImages[key] = NULL; + } +} + +// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association. +void TextureStorage11_2DArray::releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage) +{ + LevelLayerKey key(level, layerTarget); + + ASSERT(mAssociatedImages.find(key) != mAssociatedImages.end()); + + if (mAssociatedImages.find(key) != mAssociatedImages.end()) + { + if (mAssociatedImages[key] != NULL && mAssociatedImages[key] != incomingImage) + { + // Ensure that the Image is still associated with this TextureStorage. This should be true. + bool imageAssociationCorrect = mAssociatedImages[key]->isAssociatedStorageValid(this); + ASSERT(imageAssociationCorrect); + + if (imageAssociationCorrect) + { + // Force the image to recover from storage before its data is overwritten. + // This will reset mAssociatedImages[level] to NULL too. + mAssociatedImages[key]->recoverFromAssociatedStorage(); + } + } + } +} + ID3D11Resource *TextureStorage11_2DArray::getResource() const { return mTexture; diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.h similarity index 79% rename from gfx/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.h index 8a612bdd110b..76eeada59d91 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.h +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.h @@ -11,7 +11,9 @@ #define LIBGLESV2_RENDERER_TEXTURESTORAGE11_H_ #include "libGLESv2/Texture.h" -#include "libGLESv2/renderer/TextureStorage.h" +#include "libGLESv2/renderer/d3d/TextureStorage.h" + +#include namespace rx { @@ -20,6 +22,7 @@ class RenderTarget11; class Renderer; class Renderer11; class SwapChain11; +class Image11; class TextureStorage11 : public TextureStorage { @@ -28,7 +31,7 @@ class TextureStorage11 : public TextureStorage static TextureStorage11 *makeTextureStorage11(TextureStorage *storage); - static DWORD GetTextureBindFlags(GLenum internalFormat, GLuint clientVersion, bool renderTarget); + static DWORD GetTextureBindFlags(GLenum internalFormat, bool renderTarget); UINT getBindFlags() const; @@ -55,6 +58,15 @@ class TextureStorage11 : public TextureStorage int layerTarget, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth); + bool copySubresourceLevel(ID3D11Resource* dstTexture, unsigned int dstSubresource, int level, + int layerTarget, GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth); + + virtual void associateImage(Image11* image, int level, int layerTarget) = 0; + virtual void disassociateImage(int level, int layerTarget, Image11* expectedImage) = 0; + virtual bool isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage) = 0; + virtual void releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage) = 0; + protected: TextureStorage11(Renderer *renderer, UINT bindFlags); void generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest); @@ -152,6 +164,11 @@ class TextureStorage11_2D : public TextureStorage11 virtual void generateMipmap(int level); + virtual void associateImage(Image11* image, int level, int layerTarget); + virtual void disassociateImage(int level, int layerTarget, Image11* expectedImage); + virtual bool isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage); + virtual void releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage); + protected: virtual ID3D11Resource *getSwizzleTexture(); virtual ID3D11RenderTargetView *getSwizzleRenderTarget(int mipLevel); @@ -168,6 +185,8 @@ class TextureStorage11_2D : public TextureStorage11 ID3D11Texture2D *mSwizzleTexture; ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + + Image11 *mAssociatedImages[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; }; class TextureStorage11_Cube : public TextureStorage11 @@ -183,6 +202,11 @@ class TextureStorage11_Cube : public TextureStorage11 virtual void generateMipmap(int faceIndex, int level); + virtual void associateImage(Image11* image, int level, int layerTarget); + virtual void disassociateImage(int level, int layerTarget, Image11* expectedImage); + virtual bool isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage); + virtual void releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage); + protected: virtual ID3D11Resource *getSwizzleTexture(); virtual ID3D11RenderTargetView *getSwizzleRenderTarget(int mipLevel); @@ -199,6 +223,8 @@ class TextureStorage11_Cube : public TextureStorage11 ID3D11Texture2D *mSwizzleTexture; ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + + Image11 *mAssociatedImages[6][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; }; class TextureStorage11_3D : public TextureStorage11 @@ -216,6 +242,11 @@ class TextureStorage11_3D : public TextureStorage11 virtual void generateMipmap(int level); + virtual void associateImage(Image11* image, int level, int layerTarget); + virtual void disassociateImage(int level, int layerTarget, Image11* expectedImage); + virtual bool isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage); + virtual void releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage); + protected: virtual ID3D11Resource *getSwizzleTexture(); virtual ID3D11RenderTargetView *getSwizzleRenderTarget(int mipLevel); @@ -236,6 +267,8 @@ class TextureStorage11_3D : public TextureStorage11 ID3D11Texture3D *mTexture; ID3D11Texture3D *mSwizzleTexture; ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + + Image11 *mAssociatedImages[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; }; class TextureStorage11_2DArray : public TextureStorage11 @@ -252,6 +285,11 @@ class TextureStorage11_2DArray : public TextureStorage11 virtual void generateMipmap(int level); + virtual void associateImage(Image11* image, int level, int layerTarget); + virtual void disassociateImage(int level, int layerTarget, Image11* expectedImage); + virtual bool isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage); + virtual void releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage); + protected: virtual ID3D11Resource *getSwizzleTexture(); virtual ID3D11RenderTargetView *getSwizzleRenderTarget(int mipLevel); @@ -271,6 +309,9 @@ class TextureStorage11_2DArray : public TextureStorage11 ID3D11Texture2D *mSwizzleTexture; ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + + typedef std::map ImageMap; + ImageMap mAssociatedImages; }; } diff --git a/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/VertexArray11.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/VertexArray11.h new file mode 100644 index 000000000000..590cb9f05a4f --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/VertexArray11.h @@ -0,0 +1,42 @@ +// +// Copyright 2014 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. +// + +// VertexArray11.h: Defines the rx::VertexArray11 class which implements rx::VertexArrayImpl. + +#ifndef LIBGLESV2_RENDERER_VERTEXARRAY11_H_ +#define LIBGLESV2_RENDERER_VERTEXARRAY11_H_ + +#include "libGLESv2/renderer/VertexArrayImpl.h" +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" + +namespace rx +{ +class Renderer11; + +class VertexArray11 : public VertexArrayImpl +{ + public: + VertexArray11(rx::Renderer11 *renderer) + : VertexArrayImpl(), + mRenderer(renderer) + { + } + virtual ~VertexArray11() { } + + virtual void setElementArrayBuffer(const gl::Buffer *buffer) { } + virtual void setAttribute(size_t idx, const gl::VertexAttribute &attr) { } + virtual void setAttributeDivisor(size_t idx, GLuint divisor) { } + virtual void enableAttribute(size_t idx, bool enabledState) { } + + private: + DISALLOW_COPY_AND_ASSIGN(VertexArray11); + + rx::Renderer11 *mRenderer; +}; + +} + +#endif // LIBGLESV2_RENDERER_VERTEXARRAY11_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/VertexBuffer11.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.cpp similarity index 73% rename from gfx/angle/src/libGLESv2/renderer/d3d11/VertexBuffer11.cpp rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.cpp index d69668d8a37e..51ea8e586a41 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d11/VertexBuffer11.cpp +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.cpp @@ -1,4 +1,3 @@ -#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 @@ -7,13 +6,12 @@ // VertexBuffer11.cpp: Defines the D3D11 VertexBuffer implementation. -#include "libGLESv2/renderer/d3d11/VertexBuffer11.h" -#include "libGLESv2/renderer/BufferStorage.h" - +#include "libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h" +#include "libGLESv2/renderer/d3d/d3d11/Buffer11.h" +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" +#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" #include "libGLESv2/Buffer.h" -#include "libGLESv2/renderer/d3d11/Renderer11.h" #include "libGLESv2/VertexAttribute.h" -#include "libGLESv2/renderer/d3d11/formatutils11.h" namespace rx { @@ -71,8 +69,8 @@ bool VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attrib, co { if (mBuffer) { - gl::Buffer *buffer = attrib.mBoundBuffer.get(); - int inputStride = attrib.stride(); + gl::Buffer *buffer = attrib.buffer.get(); + int inputStride = ComputeVertexAttributeStride(attrib); ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); D3D11_MAPPED_SUBRESOURCE mappedResource; @@ -83,35 +81,35 @@ bool VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attrib, co return false; } - char* output = reinterpret_cast(mappedResource.pData) + offset; + uint8_t* output = reinterpret_cast(mappedResource.pData) + offset; - const char *input = NULL; - if (attrib.mArrayEnabled) + const uint8_t *input = NULL; + if (attrib.enabled) { if (buffer) { - BufferStorage *storage = buffer->getStorage(); - input = static_cast(storage->getData()) + static_cast(attrib.mOffset); + Buffer11 *storage = Buffer11::makeBuffer11(buffer->getImplementation()); + input = static_cast(storage->getData()) + static_cast(attrib.offset); } else { - input = static_cast(attrib.mPointer); + input = static_cast(attrib.pointer); } } else { - input = reinterpret_cast(currentValue.FloatValues); + input = reinterpret_cast(currentValue.FloatValues); } - if (instances == 0 || attrib.mDivisor == 0) + if (instances == 0 || attrib.divisor == 0) { input += inputStride * start; } gl::VertexFormat vertexFormat(attrib, currentValue.Type); - VertexCopyFunction conversionFunc = gl_d3d11::GetVertexCopyFunction(vertexFormat); - ASSERT(conversionFunc != NULL); - conversionFunc(input, inputStride, count, output); + const d3d11::VertexFormat &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormat); + ASSERT(vertexFormatInfo.copyFunction != NULL); + vertexFormatInfo.copyFunction(input, inputStride, count, output); dxContext->Unmap(mBuffer, 0); @@ -128,27 +126,22 @@ bool VertexBuffer11::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei GLsizei instances, unsigned int *outSpaceRequired) const { unsigned int elementCount = 0; - if (attrib.mArrayEnabled) + if (attrib.enabled) { - if (instances == 0 || attrib.mDivisor == 0) + if (instances == 0 || attrib.divisor == 0) { elementCount = count; } else { - if (static_cast(instances) < std::numeric_limits::max() - (attrib.mDivisor - 1)) - { - // Round up - elementCount = rx::roundUp(static_cast(instances), attrib.mDivisor); - } - else - { - elementCount = instances / attrib.mDivisor; - } + // Round up to divisor, if possible + elementCount = rx::UnsignedCeilDivide(static_cast(instances), attrib.divisor); } gl::VertexFormat vertexFormat(attrib); - unsigned int elementSize = static_cast(gl_d3d11::GetVertexElementSize(vertexFormat)); + const d3d11::VertexFormat &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormat); + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(vertexFormatInfo.nativeFormat); + unsigned int elementSize = dxgiFormatInfo.pixelBytes; if (elementSize <= std::numeric_limits::max() / elementCount) { if (outSpaceRequired) diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/VertexBuffer11.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h similarity index 96% rename from gfx/angle/src/libGLESv2/renderer/d3d11/VertexBuffer11.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h index 191791af3c4f..c2a5aa7afdbb 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d11/VertexBuffer11.h +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h @@ -9,7 +9,7 @@ #ifndef LIBGLESV2_RENDERER_VERTEXBUFFER11_H_ #define LIBGLESV2_RENDERER_VERTEXBUFFER11_H_ -#include "libGLESv2/renderer/VertexBuffer.h" +#include "libGLESv2/renderer/d3d/VertexBuffer.h" namespace rx { diff --git a/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp new file mode 100644 index 000000000000..1ea916db538a --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp @@ -0,0 +1,1075 @@ +// +// Copyright (c) 2013-2014 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. +// + +// formatutils11.cpp: Queries for GL image formats and their translations to D3D11 +// formats. + +#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" +#include "libGLESv2/renderer/generatemip.h" +#include "libGLESv2/renderer/loadimage.h" +#include "libGLESv2/renderer/copyimage.h" +#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/renderer/copyvertex.h" + +namespace rx +{ + +namespace d3d11 +{ + +typedef std::map DXGIToESFormatMap; + +inline void AddDXGIToESEntry(DXGIToESFormatMap *map, DXGI_FORMAT key, GLenum value) +{ + map->insert(std::make_pair(key, value)); +} + +static DXGIToESFormatMap BuildDXGIToESFormatMap() +{ + DXGIToESFormatMap map; + + AddDXGIToESEntry(&map, DXGI_FORMAT_UNKNOWN, GL_NONE); + + AddDXGIToESEntry(&map, DXGI_FORMAT_A8_UNORM, GL_ALPHA8_EXT); + AddDXGIToESEntry(&map, DXGI_FORMAT_R8_UNORM, GL_R8); + AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8_UNORM, GL_RG8); + AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_UNORM, GL_RGBA8); + AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, GL_SRGB8_ALPHA8); + AddDXGIToESEntry(&map, DXGI_FORMAT_B8G8R8A8_UNORM, GL_BGRA8_EXT); + + AddDXGIToESEntry(&map, DXGI_FORMAT_R8_SNORM, GL_R8_SNORM); + AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8_SNORM, GL_RG8_SNORM); + AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_SNORM, GL_RGBA8_SNORM); + + AddDXGIToESEntry(&map, DXGI_FORMAT_R8_UINT, GL_R8UI); + AddDXGIToESEntry(&map, DXGI_FORMAT_R16_UINT, GL_R16UI); + AddDXGIToESEntry(&map, DXGI_FORMAT_R32_UINT, GL_R32UI); + AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8_UINT, GL_RG8UI); + AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16_UINT, GL_RG16UI); + AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32_UINT, GL_RG32UI); + AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32_UINT, GL_RGB32UI); + AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_UINT, GL_RGBA8UI); + AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16B16A16_UINT, GL_RGBA16UI); + AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32A32_UINT, GL_RGBA32UI); + + AddDXGIToESEntry(&map, DXGI_FORMAT_R8_SINT, GL_R8I); + AddDXGIToESEntry(&map, DXGI_FORMAT_R16_SINT, GL_R16I); + AddDXGIToESEntry(&map, DXGI_FORMAT_R32_SINT, GL_R32I); + AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8_SINT, GL_RG8I); + AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16_SINT, GL_RG16I); + AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32_SINT, GL_RG32I); + AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32_SINT, GL_RGB32I); + AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_SINT, GL_RGBA8I); + AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16B16A16_SINT, GL_RGBA16I); + AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32A32_SINT, GL_RGBA32I); + + AddDXGIToESEntry(&map, DXGI_FORMAT_R10G10B10A2_UNORM, GL_RGB10_A2); + AddDXGIToESEntry(&map, DXGI_FORMAT_R10G10B10A2_UINT, GL_RGB10_A2UI); + + AddDXGIToESEntry(&map, DXGI_FORMAT_R16_FLOAT, GL_R16F); + AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16_FLOAT, GL_RG16F); + AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16B16A16_FLOAT, GL_RGBA16F); + + AddDXGIToESEntry(&map, DXGI_FORMAT_R32_FLOAT, GL_R32F); + AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32_FLOAT, GL_RG32F); + AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32_FLOAT, GL_RGB32F); + AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32A32_FLOAT, GL_RGBA32F); + + AddDXGIToESEntry(&map, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, GL_RGB9_E5); + AddDXGIToESEntry(&map, DXGI_FORMAT_R11G11B10_FLOAT, GL_R11F_G11F_B10F); + + AddDXGIToESEntry(&map, DXGI_FORMAT_R16_TYPELESS, GL_DEPTH_COMPONENT16); + AddDXGIToESEntry(&map, DXGI_FORMAT_R16_UNORM, GL_DEPTH_COMPONENT16); + AddDXGIToESEntry(&map, DXGI_FORMAT_D16_UNORM, GL_DEPTH_COMPONENT16); + AddDXGIToESEntry(&map, DXGI_FORMAT_R24G8_TYPELESS, GL_DEPTH24_STENCIL8_OES); + AddDXGIToESEntry(&map, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, GL_DEPTH24_STENCIL8_OES); + AddDXGIToESEntry(&map, DXGI_FORMAT_D24_UNORM_S8_UINT, GL_DEPTH24_STENCIL8_OES); + AddDXGIToESEntry(&map, DXGI_FORMAT_R32G8X24_TYPELESS, GL_DEPTH32F_STENCIL8); + AddDXGIToESEntry(&map, DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, GL_DEPTH32F_STENCIL8); + AddDXGIToESEntry(&map, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, GL_DEPTH32F_STENCIL8); + AddDXGIToESEntry(&map, DXGI_FORMAT_R32_TYPELESS, GL_DEPTH_COMPONENT32F); + AddDXGIToESEntry(&map, DXGI_FORMAT_D32_FLOAT, GL_DEPTH_COMPONENT32F); + + AddDXGIToESEntry(&map, DXGI_FORMAT_BC1_UNORM, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT); + AddDXGIToESEntry(&map, DXGI_FORMAT_BC2_UNORM, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE); + AddDXGIToESEntry(&map, DXGI_FORMAT_BC3_UNORM, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE); + + return map; +} + +struct D3D11FastCopyFormat +{ + GLenum destFormat; + GLenum destType; + ColorCopyFunction copyFunction; + + D3D11FastCopyFormat(GLenum destFormat, GLenum destType, ColorCopyFunction copyFunction) + : destFormat(destFormat), destType(destType), copyFunction(copyFunction) + { } + + bool operator<(const D3D11FastCopyFormat& other) const + { + return memcmp(this, &other, sizeof(D3D11FastCopyFormat)) < 0; + } +}; + +typedef std::multimap D3D11FastCopyMap; + +static D3D11FastCopyMap BuildFastCopyMap() +{ + D3D11FastCopyMap map; + + map.insert(std::make_pair(DXGI_FORMAT_B8G8R8A8_UNORM, D3D11FastCopyFormat(GL_RGBA, GL_UNSIGNED_BYTE, CopyBGRA8ToRGBA8))); + + return map; +} + +struct DXGIDepthStencilInfo +{ + unsigned int depthBits; + unsigned int depthOffset; + unsigned int stencilBits; + unsigned int stencilOffset; +}; + +typedef std::map DepthStencilInfoMap; +typedef std::pair DepthStencilInfoPair; + +static inline void InsertDXGIDepthStencilInfo(DepthStencilInfoMap *map, DXGI_FORMAT format, unsigned int depthBits, + unsigned int depthOffset, unsigned int stencilBits, unsigned int stencilOffset) +{ + DXGIDepthStencilInfo info; + info.depthBits = depthBits; + info.depthOffset = depthOffset; + info.stencilBits = stencilBits; + info.stencilOffset = stencilOffset; + + map->insert(std::make_pair(format, info)); +} + +static DepthStencilInfoMap BuildDepthStencilInfoMap() +{ + DepthStencilInfoMap map; + + InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R16_TYPELESS, 16, 0, 0, 0); + InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R16_UNORM, 16, 0, 0, 0); + InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_D16_UNORM, 16, 0, 0, 0); + + InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R24G8_TYPELESS, 24, 0, 8, 24); + InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, 24, 0, 8, 24); + InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_D24_UNORM_S8_UINT, 24, 0, 8, 24); + + InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R32_TYPELESS, 32, 0, 0, 0); + InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R32_FLOAT, 32, 0, 0, 0); + InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_D32_FLOAT, 32, 0, 0, 0); + + InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R32G8X24_TYPELESS, 32, 0, 8, 32); + InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, 32, 0, 8, 32); + InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, 32, 0, 8, 32); + + return map; +} + +typedef std::map DXGIFormatInfoMap; + +DXGIFormat::DXGIFormat() + : pixelBytes(0), + blockWidth(0), + blockHeight(0), + depthBits(0), + depthOffset(0), + stencilBits(0), + stencilOffset(0), + internalFormat(GL_NONE), + componentType(GL_NONE), + mipGenerationFunction(NULL), + colorReadFunction(NULL), + fastCopyFunctions() +{ +} + +ColorCopyFunction DXGIFormat::getFastCopyFunction(GLenum format, GLenum type) const +{ + FastCopyFunctionMap::const_iterator iter = fastCopyFunctions.find(std::make_pair(format, type)); + return (iter != fastCopyFunctions.end()) ? iter->second : NULL; +} + +void AddDXGIFormat(DXGIFormatInfoMap *map, DXGI_FORMAT dxgiFormat, GLuint pixelBits, GLuint blockWidth, GLuint blockHeight, + GLenum componentType, MipGenerationFunction mipFunc, ColorReadFunction readFunc) +{ + DXGIFormat info; + info.pixelBytes = pixelBits / 8; + info.blockWidth = blockWidth; + info.blockHeight = blockHeight; + + static const DepthStencilInfoMap dsInfoMap = BuildDepthStencilInfoMap(); + DepthStencilInfoMap::const_iterator dsInfoIter = dsInfoMap.find(dxgiFormat); + if (dsInfoIter != dsInfoMap.end()) + { + info.depthBits = dsInfoIter->second.depthBits; + info.depthOffset = dsInfoIter->second.depthOffset; + info.stencilBits = dsInfoIter->second.stencilBits; + info.stencilOffset = dsInfoIter->second.stencilOffset; + } + else + { + info.depthBits = 0; + info.depthOffset = 0; + info.stencilBits = 0; + info.stencilOffset = 0; + } + + static const DXGIToESFormatMap dxgiToESMap = BuildDXGIToESFormatMap(); + DXGIToESFormatMap::const_iterator dxgiToESIter = dxgiToESMap.find(dxgiFormat); + info.internalFormat = (dxgiToESIter != dxgiToESMap.end()) ? dxgiToESIter->second : GL_NONE; + + info.componentType = componentType; + + info.mipGenerationFunction = mipFunc; + info.colorReadFunction = readFunc; + + static const D3D11FastCopyMap fastCopyMap = BuildFastCopyMap(); + std::pair fastCopyIter = fastCopyMap.equal_range(dxgiFormat); + for (D3D11FastCopyMap::const_iterator i = fastCopyIter.first; i != fastCopyIter.second; i++) + { + info.fastCopyFunctions.insert(std::make_pair(std::make_pair(i->second.destFormat, i->second.destType), i->second.copyFunction)); + } + + map->insert(std::make_pair(dxgiFormat, info)); +} + +// A map to determine the pixel size and mipmap generation function of a given DXGI format +static DXGIFormatInfoMap BuildDXGIFormatInfoMap() +{ + DXGIFormatInfoMap map; + + // | DXGI format |S |W |H |Component Type | Mip generation function | Color read function + AddDXGIFormat(&map, DXGI_FORMAT_UNKNOWN, 0, 0, 0, GL_NONE, NULL, NULL); + + AddDXGIFormat(&map, DXGI_FORMAT_A8_UNORM, 8, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R8_UNORM, 8, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_B8G8R8A8_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor); + + AddDXGIFormat(&map, DXGI_FORMAT_R8_SNORM, 8, 1, 1, GL_SIGNED_NORMALIZED, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8_SNORM, 16, 1, 1, GL_SIGNED_NORMALIZED, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_SNORM, 32, 1, 1, GL_SIGNED_NORMALIZED, GenerateMip, ReadColor); + + AddDXGIFormat(&map, DXGI_FORMAT_R8_UINT, 8, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R16_UINT, 16, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R32_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8_UINT, 16, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32_UINT, 64, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32_UINT, 96, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_UINT, 64, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32A32_UINT, 128, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); + + AddDXGIFormat(&map, DXGI_FORMAT_R8_SINT, 8, 1, 1, GL_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R16_SINT, 16, 1, 1, GL_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R32_SINT, 32, 1, 1, GL_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8_SINT, 16, 1, 1, GL_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16_SINT, 32, 1, 1, GL_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32_SINT, 64, 1, 1, GL_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32_SINT, 96, 1, 1, GL_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_SINT, 32, 1, 1, GL_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_SINT, 64, 1, 1, GL_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32A32_SINT, 128, 1, 1, GL_INT, GenerateMip, ReadColor); + + AddDXGIFormat(&map, DXGI_FORMAT_R10G10B10A2_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R10G10B10A2_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); + + AddDXGIFormat(&map, DXGI_FORMAT_R16_FLOAT, 16, 1, 1, GL_FLOAT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16_FLOAT, 32, 1, 1, GL_FLOAT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_FLOAT, 64, 1, 1, GL_FLOAT, GenerateMip, ReadColor); + + AddDXGIFormat(&map, DXGI_FORMAT_R32_FLOAT, 32, 1, 1, GL_FLOAT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32_FLOAT, 64, 1, 1, GL_FLOAT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32_FLOAT, 96, 1, 1, GL_FLOAT, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32A32_FLOAT, 128, 1, 1, GL_FLOAT, GenerateMip, ReadColor); + + AddDXGIFormat(&map, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, 32, 1, 1, GL_FLOAT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R11G11B10_FLOAT, 32, 1, 1, GL_FLOAT, GenerateMip, ReadColor); + + AddDXGIFormat(&map, DXGI_FORMAT_R16_TYPELESS, 16, 1, 1, GL_NONE, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R16_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_D16_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R24G8_TYPELESS, 32, 1, 1, GL_NONE, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, 32, 1, 1, GL_NONE, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_D24_UNORM_S8_UINT, 32, 1, 1, GL_UNSIGNED_INT, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R32G8X24_TYPELESS, 64, 1, 1, GL_NONE, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, 64, 1, 1, GL_NONE, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, 64, 1, 1, GL_UNSIGNED_INT, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R32_TYPELESS, 32, 1, 1, GL_NONE, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_D32_FLOAT, 32, 1, 1, GL_FLOAT, NULL, NULL); + + AddDXGIFormat(&map, DXGI_FORMAT_BC1_UNORM, 64, 4, 4, GL_UNSIGNED_NORMALIZED, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_BC2_UNORM, 128, 4, 4, GL_UNSIGNED_NORMALIZED, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_BC3_UNORM, 128, 4, 4, GL_UNSIGNED_NORMALIZED, NULL, NULL); + + // Useful formats for vertex buffers + AddDXGIFormat(&map, DXGI_FORMAT_R16_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R16_SNORM, 16, 1, 1, GL_SIGNED_NORMALIZED, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16_SNORM, 32, 1, 1, GL_SIGNED_NORMALIZED, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_UNORM, 64, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_SNORM, 64, 1, 1, GL_SIGNED_NORMALIZED, NULL, NULL); + + return map; +} + +const DXGIFormat &GetDXGIFormatInfo(DXGI_FORMAT format) +{ + static const DXGIFormatInfoMap infoMap = BuildDXGIFormatInfoMap(); + DXGIFormatInfoMap::const_iterator iter = infoMap.find(format); + if (iter != infoMap.end()) + { + return iter->second; + } + else + { + static DXGIFormat defaultInfo; + return defaultInfo; + } +} + +struct SwizzleSizeType +{ + size_t maxComponentSize; + GLenum componentType; + + SwizzleSizeType() + : maxComponentSize(0), componentType(GL_NONE) + { } + + SwizzleSizeType(size_t maxComponentSize, GLenum componentType) + : maxComponentSize(maxComponentSize), componentType(componentType) + { } + + bool operator<(const SwizzleSizeType& other) const + { + return (maxComponentSize != other.maxComponentSize) ? (maxComponentSize < other.maxComponentSize) + : (componentType < other.componentType); + } +}; + +struct SwizzleFormatInfo +{ + DXGI_FORMAT mTexFormat; + DXGI_FORMAT mSRVFormat; + DXGI_FORMAT mRTVFormat; + + SwizzleFormatInfo() + : mTexFormat(DXGI_FORMAT_UNKNOWN), mSRVFormat(DXGI_FORMAT_UNKNOWN), mRTVFormat(DXGI_FORMAT_UNKNOWN) + { } + + SwizzleFormatInfo(DXGI_FORMAT texFormat, DXGI_FORMAT srvFormat, DXGI_FORMAT rtvFormat) + : mTexFormat(texFormat), mSRVFormat(srvFormat), mRTVFormat(rtvFormat) + { } +}; + +typedef std::map SwizzleInfoMap; +typedef std::pair SwizzleInfoPair; + +static SwizzleInfoMap BuildSwizzleInfoMap() +{ + SwizzleInfoMap map; + + map.insert(SwizzleInfoPair(SwizzleSizeType( 8, GL_UNSIGNED_NORMALIZED), SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM ))); + map.insert(SwizzleInfoPair(SwizzleSizeType(16, GL_UNSIGNED_NORMALIZED), SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R16G16B16A16_UNORM))); + map.insert(SwizzleInfoPair(SwizzleSizeType(24, GL_UNSIGNED_NORMALIZED), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT))); + map.insert(SwizzleInfoPair(SwizzleSizeType(32, GL_UNSIGNED_NORMALIZED), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT))); + + map.insert(SwizzleInfoPair(SwizzleSizeType( 8, GL_SIGNED_NORMALIZED ), SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM ))); + + map.insert(SwizzleInfoPair(SwizzleSizeType(16, GL_FLOAT ), SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT))); + map.insert(SwizzleInfoPair(SwizzleSizeType(32, GL_FLOAT ), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT))); + + map.insert(SwizzleInfoPair(SwizzleSizeType( 8, GL_UNSIGNED_INT ), SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT ))); + map.insert(SwizzleInfoPair(SwizzleSizeType(16, GL_UNSIGNED_INT ), SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT ))); + map.insert(SwizzleInfoPair(SwizzleSizeType(32, GL_UNSIGNED_INT ), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT ))); + + map.insert(SwizzleInfoPair(SwizzleSizeType( 8, GL_INT ), SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT ))); + map.insert(SwizzleInfoPair(SwizzleSizeType(16, GL_INT ), SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT ))); + map.insert(SwizzleInfoPair(SwizzleSizeType(32, GL_INT ), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT ))); + + return map; +} + +typedef std::pair InternalFormatInitializerPair; +typedef std::map InternalFormatInitializerMap; + +static InternalFormatInitializerMap BuildInternalFormatInitializerMap() +{ + InternalFormatInitializerMap map; + + map.insert(InternalFormatInitializerPair(GL_RGB8, Initialize4ComponentData )); + map.insert(InternalFormatInitializerPair(GL_RGB565, Initialize4ComponentData )); + map.insert(InternalFormatInitializerPair(GL_SRGB8, Initialize4ComponentData )); + map.insert(InternalFormatInitializerPair(GL_RGB16F, Initialize4ComponentData)); + map.insert(InternalFormatInitializerPair(GL_RGB32F, Initialize4ComponentData)); + map.insert(InternalFormatInitializerPair(GL_RGB8UI, Initialize4ComponentData )); + map.insert(InternalFormatInitializerPair(GL_RGB8I, Initialize4ComponentData )); + map.insert(InternalFormatInitializerPair(GL_RGB16UI, Initialize4ComponentData )); + map.insert(InternalFormatInitializerPair(GL_RGB16I, Initialize4ComponentData )); + map.insert(InternalFormatInitializerPair(GL_RGB32UI, Initialize4ComponentData )); + map.insert(InternalFormatInitializerPair(GL_RGB32I, Initialize4ComponentData )); + + return map; +} + +// ES3 image loading functions vary based on the internal format and data type given, +// this map type determines the loading function from the internal format and type supplied +// to glTex*Image*D and the destination DXGI_FORMAT. Source formats and types are taken from +// Tables 3.2 and 3.3 of the ES 3 spec. +typedef std::pair TypeLoadFunctionPair; +typedef std::map > D3D11LoadFunctionMap; + +static void UnimplementedLoadFunction(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + UNIMPLEMENTED(); +} + +static void UnreachableLoadFunction(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + UNREACHABLE(); +} + +// A helper function to insert data into the D3D11LoadFunctionMap with fewer characters. +static inline void InsertLoadFunction(D3D11LoadFunctionMap *map, GLenum internalFormat, GLenum type, + LoadImageFunction loadFunc) +{ + (*map)[internalFormat].push_back(TypeLoadFunctionPair(type, loadFunc)); +} + +D3D11LoadFunctionMap BuildD3D11LoadFunctionMap() +{ + D3D11LoadFunctionMap map; + + // | Internal format | Type | Load function | + InsertLoadFunction(&map, GL_RGBA8, GL_UNSIGNED_BYTE, LoadToNative ); + InsertLoadFunction(&map, GL_RGB5_A1, GL_UNSIGNED_BYTE, LoadToNative ); + InsertLoadFunction(&map, GL_RGBA4, GL_UNSIGNED_BYTE, LoadToNative ); + InsertLoadFunction(&map, GL_SRGB8_ALPHA8, GL_UNSIGNED_BYTE, LoadToNative ); + InsertLoadFunction(&map, GL_RGBA8_SNORM, GL_BYTE, LoadToNative ); + InsertLoadFunction(&map, GL_RGBA4, GL_UNSIGNED_SHORT_4_4_4_4, LoadRGBA4ToRGBA8 ); + InsertLoadFunction(&map, GL_RGB10_A2, GL_UNSIGNED_INT_2_10_10_10_REV, LoadToNative ); + InsertLoadFunction(&map, GL_RGB5_A1, GL_UNSIGNED_SHORT_5_5_5_1, LoadRGB5A1ToRGBA8 ); + InsertLoadFunction(&map, GL_RGB5_A1, GL_UNSIGNED_INT_2_10_10_10_REV, LoadRGB10A2ToRGBA8 ); + InsertLoadFunction(&map, GL_RGBA16F, GL_HALF_FLOAT, LoadToNative ); + InsertLoadFunction(&map, GL_RGBA16F, GL_HALF_FLOAT_OES, LoadToNative ); + InsertLoadFunction(&map, GL_RGBA32F, GL_FLOAT, LoadToNative ); + InsertLoadFunction(&map, GL_RGBA16F, GL_FLOAT, Load32FTo16F<4> ); + InsertLoadFunction(&map, GL_RGBA8UI, GL_UNSIGNED_BYTE, LoadToNative ); + InsertLoadFunction(&map, GL_RGBA8I, GL_BYTE, LoadToNative ); + InsertLoadFunction(&map, GL_RGBA16UI, GL_UNSIGNED_SHORT, LoadToNative ); + InsertLoadFunction(&map, GL_RGBA16I, GL_SHORT, LoadToNative ); + InsertLoadFunction(&map, GL_RGBA32UI, GL_UNSIGNED_INT, LoadToNative ); + InsertLoadFunction(&map, GL_RGBA32I, GL_INT, LoadToNative ); + InsertLoadFunction(&map, GL_RGB10_A2UI, GL_UNSIGNED_INT_2_10_10_10_REV, LoadToNative ); + InsertLoadFunction(&map, GL_RGB8, GL_UNSIGNED_BYTE, LoadToNative3To4 ); + InsertLoadFunction(&map, GL_RGB565, GL_UNSIGNED_BYTE, LoadToNative3To4 ); + InsertLoadFunction(&map, GL_SRGB8, GL_UNSIGNED_BYTE, LoadToNative3To4 ); + InsertLoadFunction(&map, GL_RGB8_SNORM, GL_BYTE, LoadToNative3To4 ); + InsertLoadFunction(&map, GL_RGB565, GL_UNSIGNED_SHORT_5_6_5, LoadR5G6B5ToRGBA8 ); + InsertLoadFunction(&map, GL_R11F_G11F_B10F, GL_UNSIGNED_INT_10F_11F_11F_REV, LoadToNative ); + InsertLoadFunction(&map, GL_RGB9_E5, GL_UNSIGNED_INT_5_9_9_9_REV, LoadToNative ); + InsertLoadFunction(&map, GL_RGB16F, GL_HALF_FLOAT, LoadToNative3To4); + InsertLoadFunction(&map, GL_RGB16F, GL_HALF_FLOAT_OES, LoadToNative3To4); + InsertLoadFunction(&map, GL_R11F_G11F_B10F, GL_HALF_FLOAT, LoadRGB16FToRG11B10F ); + InsertLoadFunction(&map, GL_R11F_G11F_B10F, GL_HALF_FLOAT_OES, LoadRGB16FToRG11B10F ); + InsertLoadFunction(&map, GL_RGB9_E5, GL_HALF_FLOAT, LoadRGB16FToRGB9E5 ); + InsertLoadFunction(&map, GL_RGB9_E5, GL_HALF_FLOAT_OES, LoadRGB16FToRGB9E5 ); + InsertLoadFunction(&map, GL_RGB32F, GL_FLOAT, LoadToNative3To4); + InsertLoadFunction(&map, GL_RGB16F, GL_FLOAT, LoadRGB32FToRGBA16F ); + InsertLoadFunction(&map, GL_R11F_G11F_B10F, GL_FLOAT, LoadRGB32FToRG11B10F ); + InsertLoadFunction(&map, GL_RGB9_E5, GL_FLOAT, LoadRGB32FToRGB9E5 ); + InsertLoadFunction(&map, GL_RGB8UI, GL_UNSIGNED_BYTE, LoadToNative3To4 ); + InsertLoadFunction(&map, GL_RGB8I, GL_BYTE, LoadToNative3To4 ); + InsertLoadFunction(&map, GL_RGB16UI, GL_UNSIGNED_SHORT, LoadToNative3To4 ); + InsertLoadFunction(&map, GL_RGB16I, GL_SHORT, LoadToNative3To4 ); + InsertLoadFunction(&map, GL_RGB32UI, GL_UNSIGNED_INT, LoadToNative3To4 ); + InsertLoadFunction(&map, GL_RGB32I, GL_INT, LoadToNative3To4 ); + InsertLoadFunction(&map, GL_RG8, GL_UNSIGNED_BYTE, LoadToNative ); + InsertLoadFunction(&map, GL_RG8_SNORM, GL_BYTE, LoadToNative ); + InsertLoadFunction(&map, GL_RG16F, GL_HALF_FLOAT, LoadToNative ); + InsertLoadFunction(&map, GL_RG16F, GL_HALF_FLOAT_OES, LoadToNative ); + InsertLoadFunction(&map, GL_RG32F, GL_FLOAT, LoadToNative ); + InsertLoadFunction(&map, GL_RG16F, GL_FLOAT, Load32FTo16F<2> ); + InsertLoadFunction(&map, GL_RG8UI, GL_UNSIGNED_BYTE, LoadToNative ); + InsertLoadFunction(&map, GL_RG8I, GL_BYTE, LoadToNative ); + InsertLoadFunction(&map, GL_RG16UI, GL_UNSIGNED_SHORT, LoadToNative ); + InsertLoadFunction(&map, GL_RG16I, GL_SHORT, LoadToNative ); + InsertLoadFunction(&map, GL_RG32UI, GL_UNSIGNED_INT, LoadToNative ); + InsertLoadFunction(&map, GL_RG32I, GL_INT, LoadToNative ); + InsertLoadFunction(&map, GL_R8, GL_UNSIGNED_BYTE, LoadToNative ); + InsertLoadFunction(&map, GL_R8_SNORM, GL_BYTE, LoadToNative ); + InsertLoadFunction(&map, GL_R16F, GL_HALF_FLOAT, LoadToNative ); + InsertLoadFunction(&map, GL_R16F, GL_HALF_FLOAT_OES, LoadToNative ); + InsertLoadFunction(&map, GL_R32F, GL_FLOAT, LoadToNative ); + InsertLoadFunction(&map, GL_R16F, GL_FLOAT, Load32FTo16F<1> ); + InsertLoadFunction(&map, GL_R8UI, GL_UNSIGNED_BYTE, LoadToNative ); + InsertLoadFunction(&map, GL_R8I, GL_BYTE, LoadToNative ); + InsertLoadFunction(&map, GL_R16UI, GL_UNSIGNED_SHORT, LoadToNative ); + InsertLoadFunction(&map, GL_R16I, GL_SHORT, LoadToNative ); + InsertLoadFunction(&map, GL_R32UI, GL_UNSIGNED_INT, LoadToNative ); + InsertLoadFunction(&map, GL_R32I, GL_INT, LoadToNative ); + InsertLoadFunction(&map, GL_DEPTH_COMPONENT16, GL_UNSIGNED_SHORT, LoadToNative ); + InsertLoadFunction(&map, GL_DEPTH_COMPONENT24, GL_UNSIGNED_INT, LoadR32ToR24G8 ); + InsertLoadFunction(&map, GL_DEPTH_COMPONENT16, GL_UNSIGNED_INT, LoadR32ToR16 ); + InsertLoadFunction(&map, GL_DEPTH_COMPONENT32F, GL_FLOAT, LoadToNative ); + InsertLoadFunction(&map, GL_DEPTH24_STENCIL8, GL_UNSIGNED_INT_24_8, LoadR32ToR24G8 ); + InsertLoadFunction(&map, GL_DEPTH32F_STENCIL8, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, LoadToNative ); + + // Unsized formats + // Load functions are unreachable because they are converted to sized internal formats based on + // the format and type before loading takes place. + InsertLoadFunction(&map, GL_RGBA, GL_UNSIGNED_BYTE, UnreachableLoadFunction ); + InsertLoadFunction(&map, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, UnreachableLoadFunction ); + InsertLoadFunction(&map, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, UnreachableLoadFunction ); + InsertLoadFunction(&map, GL_RGB, GL_UNSIGNED_BYTE, UnreachableLoadFunction ); + InsertLoadFunction(&map, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, UnreachableLoadFunction ); + InsertLoadFunction(&map, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, UnreachableLoadFunction ); + InsertLoadFunction(&map, GL_LUMINANCE, GL_UNSIGNED_BYTE, UnreachableLoadFunction ); + InsertLoadFunction(&map, GL_ALPHA, GL_UNSIGNED_BYTE, UnreachableLoadFunction ); + + // From GL_OES_texture_float + InsertLoadFunction(&map, GL_LUMINANCE_ALPHA, GL_FLOAT, LoadLA32FToRGBA32F ); + InsertLoadFunction(&map, GL_LUMINANCE, GL_FLOAT, LoadL32FToRGBA32F ); + InsertLoadFunction(&map, GL_ALPHA, GL_FLOAT, LoadA32FToRGBA32F ); + + // From GL_OES_texture_half_float + InsertLoadFunction(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT, LoadLA16FToRGBA16F ); + InsertLoadFunction(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, LoadLA16FToRGBA16F ); + InsertLoadFunction(&map, GL_LUMINANCE, GL_HALF_FLOAT, LoadL16FToRGBA16F ); + InsertLoadFunction(&map, GL_LUMINANCE, GL_HALF_FLOAT_OES, LoadL16FToRGBA16F ); + InsertLoadFunction(&map, GL_ALPHA, GL_HALF_FLOAT, LoadA16FToRGBA16F ); + InsertLoadFunction(&map, GL_ALPHA, GL_HALF_FLOAT_OES, LoadA16FToRGBA16F ); + + // From GL_EXT_texture_storage + InsertLoadFunction(&map, GL_ALPHA8_EXT, GL_UNSIGNED_BYTE, LoadToNative ); + InsertLoadFunction(&map, GL_LUMINANCE8_EXT, GL_UNSIGNED_BYTE, LoadL8ToRGBA8 ); + InsertLoadFunction(&map, GL_LUMINANCE8_ALPHA8_EXT, GL_UNSIGNED_BYTE, LoadLA8ToRGBA8 ); + InsertLoadFunction(&map, GL_ALPHA32F_EXT, GL_FLOAT, LoadA32FToRGBA32F ); + InsertLoadFunction(&map, GL_LUMINANCE32F_EXT, GL_FLOAT, LoadL32FToRGBA32F ); + InsertLoadFunction(&map, GL_LUMINANCE_ALPHA32F_EXT, GL_FLOAT, LoadLA32FToRGBA32F ); + InsertLoadFunction(&map, GL_ALPHA16F_EXT, GL_HALF_FLOAT, LoadA16FToRGBA16F ); + InsertLoadFunction(&map, GL_ALPHA16F_EXT, GL_HALF_FLOAT_OES, LoadA16FToRGBA16F ); + InsertLoadFunction(&map, GL_LUMINANCE16F_EXT, GL_HALF_FLOAT, LoadL16FToRGBA16F ); + InsertLoadFunction(&map, GL_LUMINANCE16F_EXT, GL_HALF_FLOAT_OES, LoadL16FToRGBA16F ); + InsertLoadFunction(&map, GL_LUMINANCE_ALPHA16F_EXT, GL_HALF_FLOAT, LoadLA16FToRGBA16F ); + InsertLoadFunction(&map, GL_LUMINANCE_ALPHA16F_EXT, GL_HALF_FLOAT_OES, LoadLA16FToRGBA16F ); + + // From GL_ANGLE_depth_texture + InsertLoadFunction(&map, GL_DEPTH_COMPONENT32_OES, GL_UNSIGNED_INT, LoadR32ToR24G8 ); + + // From GL_EXT_texture_format_BGRA8888 + InsertLoadFunction(&map, GL_BGRA8_EXT, GL_UNSIGNED_BYTE, LoadToNative ); + InsertLoadFunction(&map, GL_BGRA4_ANGLEX, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, LoadRGBA4ToRGBA8 ); + InsertLoadFunction(&map, GL_BGRA4_ANGLEX, GL_UNSIGNED_BYTE, LoadToNative ); + InsertLoadFunction(&map, GL_BGR5_A1_ANGLEX, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, LoadRGB5A1ToRGBA8 ); + InsertLoadFunction(&map, GL_BGR5_A1_ANGLEX, GL_UNSIGNED_BYTE, LoadToNative ); + + // Compressed formats + // From ES 3.0.1 spec, table 3.16 + // | Internal format | Type | Load function | + InsertLoadFunction(&map, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + InsertLoadFunction(&map, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + InsertLoadFunction(&map, GL_COMPRESSED_SIGNED_R11_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + InsertLoadFunction(&map, GL_COMPRESSED_RG11_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + InsertLoadFunction(&map, GL_COMPRESSED_SIGNED_RG11_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + InsertLoadFunction(&map, GL_COMPRESSED_RGB8_ETC2, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + InsertLoadFunction(&map, GL_COMPRESSED_SRGB8_ETC2, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + InsertLoadFunction(&map, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + InsertLoadFunction(&map, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + InsertLoadFunction(&map, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + InsertLoadFunction(&map, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + + // From GL_EXT_texture_compression_dxt1 + InsertLoadFunction(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, LoadCompressedToNative<4, 4, 8>); + InsertLoadFunction(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, LoadCompressedToNative<4, 4, 8>); + + // From GL_ANGLE_texture_compression_dxt3 + InsertLoadFunction(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, LoadCompressedToNative<4, 4, 16>); + + // From GL_ANGLE_texture_compression_dxt5 + InsertLoadFunction(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, LoadCompressedToNative<4, 4, 16>); + + return map; +} + +// For sized GL internal formats, there is only one corresponding D3D11 format. This map type allows +// querying for the DXGI texture formats to use for textures, SRVs, RTVs and DSVs given a GL internal +// format. +typedef std::map D3D11ES3FormatMap; + +TextureFormat::TextureFormat() + : texFormat(DXGI_FORMAT_UNKNOWN), + srvFormat(DXGI_FORMAT_UNKNOWN), + rtvFormat(DXGI_FORMAT_UNKNOWN), + dsvFormat(DXGI_FORMAT_UNKNOWN), + renderFormat(DXGI_FORMAT_UNKNOWN), + swizzleTexFormat(DXGI_FORMAT_UNKNOWN), + swizzleSRVFormat(DXGI_FORMAT_UNKNOWN), + swizzleRTVFormat(DXGI_FORMAT_UNKNOWN), + dataInitializerFunction(NULL), + loadFunctions() +{ +} + +static inline void InsertD3D11FormatInfo(D3D11ES3FormatMap *map, GLenum internalFormat, DXGI_FORMAT texFormat, + DXGI_FORMAT srvFormat, DXGI_FORMAT rtvFormat, DXGI_FORMAT dsvFormat) +{ + TextureFormat info; + info.texFormat = texFormat; + info.srvFormat = srvFormat; + info.rtvFormat = rtvFormat; + info.dsvFormat = dsvFormat; + + // Given a GL internal format, the renderFormat is the DSV format if it is depth- or stencil-renderable, + // the RTV format if it is color-renderable, and the (nonrenderable) texture format otherwise. + if (dsvFormat != DXGI_FORMAT_UNKNOWN) + { + info.renderFormat = dsvFormat; + } + else if (rtvFormat != DXGI_FORMAT_UNKNOWN) + { + info.renderFormat = rtvFormat; + } + else if (texFormat != DXGI_FORMAT_UNKNOWN) + { + info.renderFormat = texFormat; + } + else + { + info.renderFormat = DXGI_FORMAT_UNKNOWN; + } + + // Compute the swizzle formats + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); + if (internalFormat != GL_NONE && formatInfo.pixelBytes > 0) + { + if (formatInfo.componentCount != 4 || texFormat == DXGI_FORMAT_UNKNOWN || + srvFormat == DXGI_FORMAT_UNKNOWN || rtvFormat == DXGI_FORMAT_UNKNOWN) + { + // Get the maximum sized component + unsigned int maxBits = 1; + if (formatInfo.compressed) + { + unsigned int compressedBitsPerBlock = formatInfo.pixelBytes * 8; + unsigned int blockSize = formatInfo.compressedBlockWidth * formatInfo.compressedBlockHeight; + maxBits = std::max(compressedBitsPerBlock / blockSize, maxBits); + } + else + { + maxBits = std::max(maxBits, formatInfo.alphaBits); + maxBits = std::max(maxBits, formatInfo.redBits); + maxBits = std::max(maxBits, formatInfo.greenBits); + maxBits = std::max(maxBits, formatInfo.blueBits); + maxBits = std::max(maxBits, formatInfo.luminanceBits); + maxBits = std::max(maxBits, formatInfo.depthBits); + } + + maxBits = roundUp(maxBits, 8U); + + static const SwizzleInfoMap swizzleMap = BuildSwizzleInfoMap(); + SwizzleInfoMap::const_iterator swizzleIter = swizzleMap.find(SwizzleSizeType(maxBits, formatInfo.componentType)); + ASSERT(swizzleIter != swizzleMap.end()); + + const SwizzleFormatInfo &swizzleInfo = swizzleIter->second; + info.swizzleTexFormat = swizzleInfo.mTexFormat; + info.swizzleSRVFormat = swizzleInfo.mSRVFormat; + info.swizzleRTVFormat = swizzleInfo.mRTVFormat; + } + else + { + // The original texture format is suitable for swizzle operations + info.swizzleTexFormat = texFormat; + info.swizzleSRVFormat = srvFormat; + info.swizzleRTVFormat = rtvFormat; + } + } + else + { + // Not possible to swizzle with this texture format since it is either unsized or GL_NONE + info.swizzleTexFormat = DXGI_FORMAT_UNKNOWN; + info.swizzleSRVFormat = DXGI_FORMAT_UNKNOWN; + info.swizzleRTVFormat = DXGI_FORMAT_UNKNOWN; + } + + // Check if there is an initialization function for this texture format + static const InternalFormatInitializerMap initializerMap = BuildInternalFormatInitializerMap(); + InternalFormatInitializerMap::const_iterator initializerIter = initializerMap.find(internalFormat); + info.dataInitializerFunction = (initializerIter != initializerMap.end()) ? initializerIter->second : NULL; + + // Gather all the load functions for this internal format + static const D3D11LoadFunctionMap loadFunctions = BuildD3D11LoadFunctionMap(); + D3D11LoadFunctionMap::const_iterator loadFunctionIter = loadFunctions.find(internalFormat); + if (loadFunctionIter != loadFunctions.end()) + { + const std::vector &loadFunctionVector = loadFunctionIter->second; + for (size_t i = 0; i < loadFunctionVector.size(); i++) + { + GLenum type = loadFunctionVector[i].first; + LoadImageFunction function = loadFunctionVector[i].second; + info.loadFunctions.insert(std::make_pair(type, function)); + } + } + + map->insert(std::make_pair(internalFormat, info)); +} + +static D3D11ES3FormatMap BuildD3D11FormatMap() +{ + D3D11ES3FormatMap map; + + // | GL internal format | D3D11 texture format | D3D11 SRV format | D3D11 RTV format | D3D11 DSV format | + InsertD3D11FormatInfo(&map, GL_NONE, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_R8, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_R8_SNORM, DXGI_FORMAT_R8_SNORM, DXGI_FORMAT_R8_SNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RG8, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RG8_SNORM, DXGI_FORMAT_R8G8_SNORM, DXGI_FORMAT_R8G8_SNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGB8, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGB8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGB565, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGBA4, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGB5_A1, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGBA8, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGBA8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGB10_A2, DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGB10_A2UI, DXGI_FORMAT_R10G10B10A2_UINT, DXGI_FORMAT_R10G10B10A2_UINT, DXGI_FORMAT_R10G10B10A2_UINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_SRGB8, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_SRGB8_ALPHA8, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_R16F, DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RG16F, DXGI_FORMAT_R16G16_FLOAT, DXGI_FORMAT_R16G16_FLOAT, DXGI_FORMAT_R16G16_FLOAT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGB16F, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGBA16F, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_R32F, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RG32F, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGB32F, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGBA32F, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_R11F_G11F_B10F, DXGI_FORMAT_R11G11B10_FLOAT, DXGI_FORMAT_R11G11B10_FLOAT, DXGI_FORMAT_R11G11B10_FLOAT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGB9_E5, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_R8I, DXGI_FORMAT_R8_SINT, DXGI_FORMAT_R8_SINT, DXGI_FORMAT_R8_SINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_R8UI, DXGI_FORMAT_R8_UINT, DXGI_FORMAT_R8_UINT, DXGI_FORMAT_R8_UINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_R16I, DXGI_FORMAT_R16_SINT, DXGI_FORMAT_R16_SINT, DXGI_FORMAT_R16_SINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_R16UI, DXGI_FORMAT_R16_UINT, DXGI_FORMAT_R16_UINT, DXGI_FORMAT_R16_UINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_R32I, DXGI_FORMAT_R32_SINT, DXGI_FORMAT_R32_SINT, DXGI_FORMAT_R32_SINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_R32UI, DXGI_FORMAT_R32_UINT, DXGI_FORMAT_R32_UINT, DXGI_FORMAT_R32_UINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RG8I, DXGI_FORMAT_R8G8_SINT, DXGI_FORMAT_R8G8_SINT, DXGI_FORMAT_R8G8_SINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RG8UI, DXGI_FORMAT_R8G8_UINT, DXGI_FORMAT_R8G8_UINT, DXGI_FORMAT_R8G8_UINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RG16I, DXGI_FORMAT_R16G16_SINT, DXGI_FORMAT_R16G16_SINT, DXGI_FORMAT_R16G16_SINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RG16UI, DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RG32I, DXGI_FORMAT_R32G32_SINT, DXGI_FORMAT_R32G32_SINT, DXGI_FORMAT_R32G32_SINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RG32UI, DXGI_FORMAT_R32G32_UINT, DXGI_FORMAT_R32G32_UINT, DXGI_FORMAT_R32G32_UINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGB8I, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGB8UI, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGB16I, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGB16UI, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGB32I, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGB32UI, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGBA8I, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGBA8UI, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGBA16I, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGBA16UI, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGBA32I, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGBA32UI, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_UNKNOWN); + + // Unsized formats, TODO: Are types of float and half float allowed for the unsized types? Would it change the DXGI format? + InsertD3D11FormatInfo(&map, GL_ALPHA, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_LUMINANCE, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_LUMINANCE_ALPHA, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGB, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGBA, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_BGRA_EXT, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN); + + // From GL_EXT_texture_storage + // | GL internal format | D3D11 texture format | D3D11 SRV format | D3D11 RTV format | D3D11 DSV format | + InsertD3D11FormatInfo(&map, GL_ALPHA8_EXT, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_UNKNOWN ); + InsertD3D11FormatInfo(&map, GL_LUMINANCE8_EXT, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN ); + InsertD3D11FormatInfo(&map, GL_ALPHA32F_EXT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN ); + InsertD3D11FormatInfo(&map, GL_LUMINANCE32F_EXT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN ); + InsertD3D11FormatInfo(&map, GL_ALPHA16F_EXT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN ); + InsertD3D11FormatInfo(&map, GL_LUMINANCE16F_EXT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN ); + InsertD3D11FormatInfo(&map, GL_LUMINANCE8_ALPHA8_EXT, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN ); + InsertD3D11FormatInfo(&map, GL_LUMINANCE_ALPHA32F_EXT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN ); + InsertD3D11FormatInfo(&map, GL_LUMINANCE_ALPHA16F_EXT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN ); + InsertD3D11FormatInfo(&map, GL_BGRA8_EXT, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN ); + InsertD3D11FormatInfo(&map, GL_BGRA4_ANGLEX, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN ); + InsertD3D11FormatInfo(&map, GL_BGR5_A1_ANGLEX, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN ); + + // Depth stencil formats + InsertD3D11FormatInfo(&map, GL_DEPTH_COMPONENT16, DXGI_FORMAT_R16_TYPELESS, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D16_UNORM ); + InsertD3D11FormatInfo(&map, GL_DEPTH_COMPONENT24, DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT ); + InsertD3D11FormatInfo(&map, GL_DEPTH_COMPONENT32F, DXGI_FORMAT_R32_TYPELESS, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D32_FLOAT ); + InsertD3D11FormatInfo(&map, GL_DEPTH24_STENCIL8, DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT ); + InsertD3D11FormatInfo(&map, GL_DEPTH32F_STENCIL8, DXGI_FORMAT_R32G8X24_TYPELESS, DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D32_FLOAT_S8X24_UINT); + InsertD3D11FormatInfo(&map, GL_STENCIL_INDEX8, DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_X24_TYPELESS_G8_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT ); + + // From GL_ANGLE_depth_texture + // Since D3D11 doesn't have a D32_UNORM format, use D24S8 which has comparable precision and matches the ES3 format. + InsertD3D11FormatInfo(&map, GL_DEPTH_COMPONENT32_OES, DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT); + + // Compressed formats, From ES 3.0.1 spec, table 3.16 + // | GL internal format | D3D11 texture format | D3D11 SRV format | D3D11 RTV format | D3D11 DSV format | + InsertD3D11FormatInfo(&map, GL_COMPRESSED_R11_EAC, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_COMPRESSED_SIGNED_R11_EAC, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_COMPRESSED_RG11_EAC, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_COMPRESSED_SIGNED_RG11_EAC, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGB8_ETC2, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_COMPRESSED_SRGB8_ETC2, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGBA8_ETC2_EAC, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + + // From GL_EXT_texture_compression_dxt1 + InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + + // From GL_ANGLE_texture_compression_dxt3 + InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + + // From GL_ANGLE_texture_compression_dxt5 + InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + + return map; +} + +const TextureFormat &GetTextureFormatInfo(GLenum internalFormat) +{ + static const D3D11ES3FormatMap formatMap = BuildD3D11FormatMap(); + D3D11ES3FormatMap::const_iterator iter = formatMap.find(internalFormat); + if (iter != formatMap.end()) + { + return iter->second; + } + else + { + static const TextureFormat defaultInfo; + return defaultInfo; + } +} + +typedef std::map D3D11VertexFormatInfoMap; +typedef std::pair D3D11VertexFormatPair; + +VertexFormat::VertexFormat() + : conversionType(VERTEX_CONVERT_NONE), + nativeFormat(DXGI_FORMAT_UNKNOWN), + copyFunction(NULL) +{ +} + +static void AddVertexFormatInfo(D3D11VertexFormatInfoMap *map, GLenum inputType, GLboolean normalized, GLuint componentCount, + VertexConversionType conversionType, DXGI_FORMAT nativeFormat, VertexCopyFunction copyFunction) +{ + gl::VertexFormat inputFormat(inputType, normalized, componentCount, false); + + VertexFormat info; + info.conversionType = conversionType; + info.nativeFormat = nativeFormat; + info.copyFunction = copyFunction; + + map->insert(D3D11VertexFormatPair(inputFormat, info)); +} + +static void AddIntegerVertexFormatInfo(D3D11VertexFormatInfoMap *map, GLenum inputType, GLuint componentCount, + VertexConversionType conversionType, DXGI_FORMAT nativeFormat, VertexCopyFunction copyFunction) +{ + gl::VertexFormat inputFormat(inputType, GL_FALSE, componentCount, true); + + VertexFormat info; + info.conversionType = conversionType; + info.nativeFormat = nativeFormat; + info.copyFunction = copyFunction; + + map->insert(D3D11VertexFormatPair(inputFormat, info)); +} + +static D3D11VertexFormatInfoMap BuildD3D11VertexFormatInfoMap() +{ + D3D11VertexFormatInfoMap map; + + // TODO: column legend + + // + // Float formats + // + + // GL_BYTE -- un-normalized + AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_SINT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8_SINT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData); + + // GL_BYTE -- normalized + AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_SNORM, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_SNORM, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_SNORM, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_SNORM, &CopyNativeVertexData); + + // GL_UNSIGNED_BYTE -- un-normalized + AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_UINT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8_UINT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData); + + // GL_UNSIGNED_BYTE -- normalized + AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_UNORM, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_UNORM, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_UNORM, &CopyNativeVertexData); + + // GL_SHORT -- un-normalized + AddVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16_SINT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16_SINT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData); + + // GL_SHORT -- normalized + AddVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_SNORM, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_SNORM, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_SNORM, &CopyNativeVertexData); + + // GL_UNSIGNED_SHORT -- un-normalized + AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16_UINT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16_UINT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData); + + // GL_UNSIGNED_SHORT -- normalized + AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_UNORM, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_UNORM, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_UNORM, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_UNORM, &CopyNativeVertexData); + + // GL_INT -- un-normalized + AddVertexFormatInfo(&map, GL_INT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32_SINT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_INT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32_SINT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_INT, GL_FALSE, 3, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32_SINT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_INT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32A32_SINT, &CopyNativeVertexData); + + // GL_INT -- normalized + AddVertexFormatInfo(&map, GL_INT, GL_TRUE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT, &CopyTo32FVertexData); + AddVertexFormatInfo(&map, GL_INT, GL_TRUE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData); + AddVertexFormatInfo(&map, GL_INT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &CopyTo32FVertexData); + AddVertexFormatInfo(&map, GL_INT, GL_TRUE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyTo32FVertexData); + + // GL_UNSIGNED_INT -- un-normalized + AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32_UINT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32_UINT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 3, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32_UINT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32A32_UINT, &CopyNativeVertexData); + + // GL_UNSIGNED_INT -- normalized + AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_FLOAT, &CopyTo32FVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &CopyTo32FVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyTo32FVertexData); + + // GL_FIXED + AddVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT, &Copy32FixedTo32FVertexData<1>); + AddVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &Copy32FixedTo32FVertexData<2>); + AddVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &Copy32FixedTo32FVertexData<3>); + AddVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &Copy32FixedTo32FVertexData<4>); + + // GL_HALF_FLOAT + AddVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_FLOAT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_FLOAT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_FLOAT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_FLOAT, &CopyNativeVertexData); + + // GL_FLOAT + AddVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_FLOAT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_FLOAT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 3, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_FLOAT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyNativeVertexData); + + // GL_INT_2_10_10_10_REV + AddVertexFormatInfo(&map, GL_INT_2_10_10_10_REV, GL_FALSE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyXYZ10W2ToXYZW32FVertexData); + AddVertexFormatInfo(&map, GL_INT_2_10_10_10_REV, GL_TRUE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyXYZ10W2ToXYZW32FVertexData); + + // GL_UNSIGNED_INT_2_10_10_10_REV + AddVertexFormatInfo(&map, GL_UNSIGNED_INT_2_10_10_10_REV, GL_FALSE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyXYZ10W2ToXYZW32FVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_INT_2_10_10_10_REV, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UNORM, &CopyNativeVertexData); + + // + // Integer Formats + // + + // GL_BYTE + AddIntegerVertexFormatInfo(&map, GL_BYTE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_SINT, &CopyNativeVertexData); + AddIntegerVertexFormatInfo(&map, GL_BYTE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_SINT, &CopyNativeVertexData); + AddIntegerVertexFormatInfo(&map, GL_BYTE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData); + AddIntegerVertexFormatInfo(&map, GL_BYTE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData); + + // GL_UNSIGNED_BYTE + AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_UINT, &CopyNativeVertexData); + AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_UINT, &CopyNativeVertexData); + AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData); + AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData); + + // GL_SHORT + AddIntegerVertexFormatInfo(&map, GL_SHORT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_SINT, &CopyNativeVertexData); + AddIntegerVertexFormatInfo(&map, GL_SHORT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_SINT, &CopyNativeVertexData); + AddIntegerVertexFormatInfo(&map, GL_SHORT, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData); + AddIntegerVertexFormatInfo(&map, GL_SHORT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData); + + // GL_UNSIGNED_SHORT + AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_UINT, &CopyNativeVertexData); + AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_UINT, &CopyNativeVertexData); + AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData); + AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData); + + // GL_INT + AddIntegerVertexFormatInfo(&map, GL_INT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_SINT, &CopyNativeVertexData); + AddIntegerVertexFormatInfo(&map, GL_INT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_SINT, &CopyNativeVertexData); + AddIntegerVertexFormatInfo(&map, GL_INT, 3, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_SINT, &CopyNativeVertexData); + AddIntegerVertexFormatInfo(&map, GL_INT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_SINT, &CopyNativeVertexData); + + // GL_UNSIGNED_INT + AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_SINT, &CopyNativeVertexData); + AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_SINT, &CopyNativeVertexData); + AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 3, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_SINT, &CopyNativeVertexData); + AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_SINT, &CopyNativeVertexData); + + // GL_INT_2_10_10_10_REV + AddIntegerVertexFormatInfo(&map, GL_INT_2_10_10_10_REV, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SINT, &CopyXYZ10W2ToXYZW32FVertexData); + + // GL_UNSIGNED_INT_2_10_10_10_REV + AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT_2_10_10_10_REV, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UINT, &CopyNativeVertexData); + + return map; +} + +const VertexFormat &GetVertexFormatInfo(const gl::VertexFormat &vertexFormat) +{ + static const D3D11VertexFormatInfoMap vertexFormatMap = BuildD3D11VertexFormatInfoMap(); + + D3D11VertexFormatInfoMap::const_iterator iter = vertexFormatMap.find(vertexFormat); + if (iter != vertexFormatMap.end()) + { + return iter->second; + } + else + { + static const VertexFormat defaultInfo; + return defaultInfo; + } +} + +} + +} diff --git a/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.h new file mode 100644 index 000000000000..ea11aaa74c44 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.h @@ -0,0 +1,84 @@ +// +// Copyright (c) 2013-2014 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. +// + +// formatutils11.h: Queries for GL image formats and their translations to D3D11 +// formats. + +#ifndef LIBGLESV2_RENDERER_FORMATUTILS11_H_ +#define LIBGLESV2_RENDERER_FORMATUTILS11_H_ + +#include "libGLESv2/formatutils.h" + +#include + +namespace rx +{ + +namespace d3d11 +{ + +typedef std::map, ColorCopyFunction> FastCopyFunctionMap; + +struct DXGIFormat +{ + DXGIFormat(); + + GLuint pixelBytes; + GLuint blockWidth; + GLuint blockHeight; + + GLuint depthBits; + GLuint depthOffset; + GLuint stencilBits; + GLuint stencilOffset; + + GLenum internalFormat; + GLenum componentType; + + MipGenerationFunction mipGenerationFunction; + ColorReadFunction colorReadFunction; + + FastCopyFunctionMap fastCopyFunctions; + ColorCopyFunction getFastCopyFunction(GLenum format, GLenum type) const; +}; +const DXGIFormat &GetDXGIFormatInfo(DXGI_FORMAT format); + +struct TextureFormat +{ + TextureFormat(); + + DXGI_FORMAT texFormat; + DXGI_FORMAT srvFormat; + DXGI_FORMAT rtvFormat; + DXGI_FORMAT dsvFormat; + DXGI_FORMAT renderFormat; + + DXGI_FORMAT swizzleTexFormat; + DXGI_FORMAT swizzleSRVFormat; + DXGI_FORMAT swizzleRTVFormat; + + InitializeTextureDataFunction dataInitializerFunction; + + typedef std::map LoadFunctionMap; + LoadFunctionMap loadFunctions; +}; +const TextureFormat &GetTextureFormatInfo(GLenum internalFormat); + +struct VertexFormat +{ + VertexFormat(); + + VertexConversionType conversionType; + DXGI_FORMAT nativeFormat; + VertexCopyFunction copyFunction; +}; +const VertexFormat &GetVertexFormatInfo(const gl::VertexFormat &vertexFormat); + +} + +} + +#endif // LIBGLESV2_RENDERER_FORMATUTILS11_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp new file mode 100644 index 000000000000..c021e2ab0a53 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp @@ -0,0 +1,1068 @@ +// +// Copyright (c) 2012-2014 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/d3d/d3d11/renderer11_utils.h" +#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" + +#include "common/debug.h" + +#include + +namespace rx +{ + +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; + case GL_MIN: d3dBlendOp = D3D11_BLEND_OP_MIN; break; + case GL_MAX: d3dBlendOp = D3D11_BLEND_OP_MAX; 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, GLenum comparisonMode) +{ + bool comparison = comparisonMode != GL_NONE; + + if (maxAnisotropy > 1.0f) + { + return D3D11_ENCODE_ANISOTROPIC_FILTER(static_cast(comparison)); + } + 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, static_cast(comparison)); + } +} + +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; +} + +D3D11_QUERY ConvertQueryType(GLenum queryType) +{ + switch (queryType) + { + case GL_ANY_SAMPLES_PASSED_EXT: + case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: return D3D11_QUERY_OCCLUSION; + case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: return D3D11_QUERY_SO_STATISTICS; + default: UNREACHABLE(); return D3D11_QUERY_EVENT; + } +} + +} + + +namespace d3d11_gl +{ + +static gl::TextureCaps GenerateTextureFormatCaps(GLenum internalFormat, ID3D11Device *device) +{ + gl::TextureCaps textureCaps; + + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalFormat); + + UINT formatSupport; + if (SUCCEEDED(device->CheckFormatSupport(formatInfo.texFormat, &formatSupport))) + { + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); + if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) + { + textureCaps.texturable = ((formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0); + } + else + { + textureCaps.texturable = ((formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0) && + ((formatSupport & D3D11_FORMAT_SUPPORT_TEXTURECUBE) != 0) && + ((formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE3D) != 0); + } + } + + if (SUCCEEDED(device->CheckFormatSupport(formatInfo.renderFormat, &formatSupport)) && + ((formatSupport & D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET) != 0)) + { + for (size_t sampleCount = 1; sampleCount <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; sampleCount++) + { + UINT qualityCount = 0; + if (SUCCEEDED(device->CheckMultisampleQualityLevels(formatInfo.renderFormat, sampleCount, &qualityCount)) && + qualityCount > 0) + { + textureCaps.sampleCounts.insert(sampleCount); + } + } + } + + textureCaps.filterable = SUCCEEDED(device->CheckFormatSupport(formatInfo.srvFormat, &formatSupport)) && + ((formatSupport & D3D11_FORMAT_SUPPORT_SHADER_SAMPLE)) != 0; + textureCaps.renderable = (SUCCEEDED(device->CheckFormatSupport(formatInfo.rtvFormat, &formatSupport)) && + ((formatSupport & D3D11_FORMAT_SUPPORT_RENDER_TARGET)) != 0) || + (SUCCEEDED(device->CheckFormatSupport(formatInfo.dsvFormat, &formatSupport)) && + ((formatSupport & D3D11_FORMAT_SUPPORT_DEPTH_STENCIL) != 0)); + + return textureCaps; +} + +static bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return true; + + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return false; + + default: UNREACHABLE(); return false; + } +} + +static float GetMaximumAnisotropy(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + 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; + + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: return 16; + + case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_DEFAULT_MAX_ANISOTROPY; + + default: UNREACHABLE(); return 0; + } +} + +static bool GetOcclusionQuerySupport(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return true; + + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateQuery + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: return true; + case D3D_FEATURE_LEVEL_9_1: return false; + + default: UNREACHABLE(); return false; + } +} + +static bool GetEventQuerySupport(D3D_FEATURE_LEVEL featureLevel) +{ + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateQuery + + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return true; + + default: UNREACHABLE(); return false; + } +} + +static bool GetInstancingSupport(D3D_FEATURE_LEVEL featureLevel) +{ + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateInputLayout + + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + case D3D_FEATURE_LEVEL_9_3: return true; + + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return false; + + default: UNREACHABLE(); return false; + } +} + +static bool GetDerivativeInstructionSupport(D3D_FEATURE_LEVEL featureLevel) +{ + // http://msdn.microsoft.com/en-us/library/windows/desktop/bb509588.aspx states that shader model + // ps_2_x is required for the ddx (and other derivative functions). + + // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx states that feature level + // 9.3 supports shader model ps_2_x. + + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + case D3D_FEATURE_LEVEL_9_3: return true; + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return false; + + default: UNREACHABLE(); return false; + } +} + +static size_t GetMaximumSimultaneousRenderTargets(D3D_FEATURE_LEVEL featureLevel) +{ + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateInputLayout + + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; + + // FIXME(geofflang): Work around NVIDIA driver bug by repacking buffers + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return 1; /* D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT; */ + + case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT; + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximum2DTextureSize(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; + + case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximumCubeMapTextureSize(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURECUBE_DIMENSION; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURECUBE_DIMENSION; + + case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION; + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximum2DTextureArraySize(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION; + + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return 0; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximum3DTextureSize(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION; + + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximumViewportSize(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: return D3D11_VIEWPORT_BOUNDS_MAX; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_VIEWPORT_BOUNDS_MAX; + + // No constants for D3D9 viewport size limits, use the maximum texture sizes + case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximumDrawIndexedIndexCount(D3D_FEATURE_LEVEL featureLevel) +{ + // D3D11 allows up to 2^32 elements, but we report max signed int for convenience since that's what's + // returned from glGetInteger + META_ASSERT(D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP == 32); + META_ASSERT(D3D10_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP == 32); + + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return std::numeric_limits::max(); + + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: return D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT; + case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximumDrawVertexCount(D3D_FEATURE_LEVEL featureLevel) +{ + // D3D11 allows up to 2^32 elements, but we report max signed int for convenience since that's what's + // returned from glGetInteger + META_ASSERT(D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP == 32); + META_ASSERT(D3D10_REQ_DRAW_VERTEX_COUNT_2_TO_EXP == 32); + + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return std::numeric_limits::max(); + + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: return D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT; + case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximumVertexInputSlots(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: return D3D11_STANDARD_VERTEX_ELEMENT_COUNT; + + case D3D_FEATURE_LEVEL_10_1: return D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT; + case D3D_FEATURE_LEVEL_10_0: return D3D10_STANDARD_VERTEX_ELEMENT_COUNT; + + // From http://http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx "Max Input Slots" + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return 16; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximumVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel) +{ + // TODO(geofflang): Remove hard-coded limit once the gl-uniform-arrays test can pass + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: return 1024; // D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return 1024; // D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT; + + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx ID3D11DeviceContext::VSSetConstantBuffers + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return 255; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetReservedVertexUniformBuffers() +{ + // Reserve one buffer for the application uniforms, and one for driver uniforms + return 2; +} + +static size_t GetMaximumVertexUniformBlocks(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedVertexUniformBuffers(); + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedVertexUniformBuffers(); + + // Uniform blocks not supported in D3D9 feature levels + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return 0; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetReservedVertexOutputVectors() +{ + // We potentially reserve varyings for gl_Position, dx_Position, gl_FragCoord and gl_PointSize + return 4; +} + +static size_t GetMaximumVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel) +{ + META_ASSERT(gl::IMPLEMENTATION_MAX_VARYING_VECTORS == D3D11_VS_OUTPUT_REGISTER_COUNT); + + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: return D3D11_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(); + + case D3D_FEATURE_LEVEL_10_1: return D3D10_1_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(); + case D3D_FEATURE_LEVEL_10_0: return D3D10_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(); + + // Use D3D9 SM3 and SM2 limits + case D3D_FEATURE_LEVEL_9_3: return 10 - GetReservedVertexOutputVectors(); + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return 8 - GetReservedVertexOutputVectors(); + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximumVertexTextureUnits(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT; + + // Vertex textures not supported in D3D9 feature levels according to + // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx + // ID3D11DeviceContext::VSSetSamplers and ID3D11DeviceContext::VSSetShaderResources + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return 0; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximumPixelUniformVectors(D3D_FEATURE_LEVEL featureLevel) +{ + // TODO(geofflang): Remove hard-coded limit once the gl-uniform-arrays test can pass + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: return 1024; // D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return 1024; // D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT; + + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx ID3D11DeviceContext::PSSetConstantBuffers + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return 32; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetReservedPixelUniformBuffers() +{ + // Reserve one buffer for the application uniforms, and one for driver uniforms + return 2; +} + +static size_t GetMaximumPixelUniformBlocks(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedPixelUniformBuffers(); + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedPixelUniformBuffers(); + + // Uniform blocks not supported in D3D9 feature levels + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return 0; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximumPixelInputVectors(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: return D3D11_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(); + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(); + + // Use D3D9 SM3 and SM2 limits + case D3D_FEATURE_LEVEL_9_3: return 10 - GetReservedVertexOutputVectors(); + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return 8 - GetReservedVertexOutputVectors(); + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximumPixelTextureUnits(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT; + + // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx ID3D11DeviceContext::PSSetShaderResources + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return 16; + + default: UNREACHABLE(); return 0; + } +} + +static int GetMinimumTexelOffset(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE; + + // Sampling functions with offsets are not available below shader model 4.0. + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return 0; + + default: UNREACHABLE(); return 0; + } +} + +static int GetMaximumTexelOffset(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE; + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE; + + // Sampling functions with offsets are not available below shader model 4.0. + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return 0; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximumConstantBufferSize(D3D_FEATURE_LEVEL featureLevel) +{ + // Returns a size_t despite the limit being a GLuint64 because size_t is the maximum size of + // any buffer that could be allocated. + + const size_t bytesPerComponent = 4 * sizeof(float); + + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent; + + // Limits from http://msdn.microsoft.com/en-us/library/windows/desktop/ff476501.aspx remarks section + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return 4096 * bytesPerComponent; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximumStreamOutputBuffers(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: return D3D11_SO_BUFFER_SLOT_COUNT; + + case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SO_BUFFER_SLOT_COUNT; + case D3D_FEATURE_LEVEL_10_0: return D3D10_SO_BUFFER_SLOT_COUNT; + + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return 0; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximumStreamOutputInterleavedComponenets(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return GetMaximumVertexOutputVectors(featureLevel) * 4; + + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return 0; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximumStreamOutputSeparateCompeonents(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: return GetMaximumStreamOutputInterleavedComponenets(featureLevel) / + GetMaximumStreamOutputBuffers(featureLevel); + + + // D3D 10 and 10.1 only allow one output per output slot if an output slot other than zero is used. + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return 4; + + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return 0; + + default: UNREACHABLE(); return 0; + } +} + +void GenerateCaps(ID3D11Device *device, gl::Caps *caps, gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions) +{ + GLuint maxSamples = 0; + const gl::FormatSet &allFormats = gl::GetAllSizedInternalFormats(); + for (gl::FormatSet::const_iterator internalFormat = allFormats.begin(); internalFormat != allFormats.end(); ++internalFormat) + { + gl::TextureCaps textureCaps = GenerateTextureFormatCaps(*internalFormat, device); + textureCapsMap->insert(*internalFormat, textureCaps); + + maxSamples = std::max(maxSamples, textureCaps.getMaxSamples()); + + if (gl::GetInternalFormatInfo(*internalFormat).compressed) + { + caps->compressedTextureFormats.push_back(*internalFormat); + } + } + + D3D_FEATURE_LEVEL featureLevel = device->GetFeatureLevel(); + + // GL core feature limits + caps->maxElementIndex = static_cast(std::numeric_limits::max()); + caps->max3DTextureSize = GetMaximum3DTextureSize(featureLevel); + caps->max2DTextureSize = GetMaximum2DTextureSize(featureLevel); + caps->maxCubeMapTextureSize = GetMaximumCubeMapTextureSize(featureLevel); + caps->maxArrayTextureLayers = GetMaximum2DTextureArraySize(featureLevel); + + // Unimplemented, set to minimum required + caps->maxLODBias = 2.0f; + + // No specific limits on render target size, maximum 2D texture size is equivalent + caps->maxRenderbufferSize = caps->max2DTextureSize; + + // Maximum draw buffers and color attachments are the same, max color attachments could eventually be + // increased to 16 + caps->maxDrawBuffers = GetMaximumSimultaneousRenderTargets(featureLevel); + caps->maxColorAttachments = GetMaximumSimultaneousRenderTargets(featureLevel); + + // D3D11 has the same limit for viewport width and height + caps->maxViewportWidth = GetMaximumViewportSize(featureLevel); + caps->maxViewportHeight = caps->maxViewportWidth; + + // Choose a reasonable maximum, enforced in the shader. + caps->minAliasedPointSize = 1.0f; + caps->maxAliasedPointSize = 1024.0f; + + // Wide lines not supported + caps->minAliasedLineWidth = 1.0f; + caps->maxAliasedLineWidth = 1.0f; + + // Primitive count limits + caps->maxElementsIndices = GetMaximumDrawIndexedIndexCount(featureLevel); + caps->maxElementsVertices = GetMaximumDrawVertexCount(featureLevel); + + // Program and shader binary formats (no supported shader binary formats) + caps->programBinaryFormats.push_back(GL_PROGRAM_BINARY_ANGLE); + + // We do not wait for server fence objects internally, so report a max timeout of zero. + caps->maxServerWaitTimeout = 0; + + // Vertex shader limits + caps->maxVertexAttributes = GetMaximumVertexInputSlots(featureLevel); + caps->maxVertexUniformComponents = GetMaximumVertexUniformVectors(featureLevel) * 4; + caps->maxVertexUniformVectors = GetMaximumVertexUniformVectors(featureLevel); + caps->maxVertexUniformBlocks = GetMaximumVertexUniformBlocks(featureLevel); + caps->maxVertexOutputComponents = GetMaximumVertexOutputVectors(featureLevel) * 4; + caps->maxVertexTextureImageUnits = GetMaximumVertexTextureUnits(featureLevel); + + // Fragment shader limits + caps->maxFragmentUniformComponents = GetMaximumPixelUniformVectors(featureLevel) * 4; + caps->maxFragmentUniformVectors = GetMaximumPixelUniformVectors(featureLevel); + caps->maxFragmentUniformBlocks = GetMaximumPixelUniformBlocks(featureLevel); + caps->maxFragmentInputComponents = GetMaximumPixelInputVectors(featureLevel) * 4; + caps->maxTextureImageUnits = GetMaximumPixelTextureUnits(featureLevel); + caps->minProgramTexelOffset = GetMinimumTexelOffset(featureLevel); + caps->maxProgramTexelOffset = GetMaximumTexelOffset(featureLevel); + + // Aggregate shader limits + caps->maxUniformBufferBindings = caps->maxVertexUniformBlocks + caps->maxFragmentUniformBlocks; + caps->maxUniformBlockSize = GetMaximumConstantBufferSize(featureLevel); + + // Setting a large alignment forces uniform buffers to bind with zero offset + caps->uniformBufferOffsetAlignment = static_cast(std::numeric_limits::max()); + + caps->maxCombinedUniformBlocks = caps->maxVertexUniformBlocks + caps->maxFragmentUniformBlocks; + caps->maxCombinedVertexUniformComponents = (static_cast(caps->maxVertexUniformBlocks) * static_cast(caps->maxUniformBlockSize / 4)) + + static_cast(caps->maxVertexUniformComponents); + caps->maxCombinedFragmentUniformComponents = (static_cast(caps->maxFragmentUniformBlocks) * static_cast(caps->maxUniformBlockSize / 4)) + + static_cast(caps->maxFragmentUniformComponents); + caps->maxVaryingComponents = GetMaximumVertexOutputVectors(featureLevel) * 4; + caps->maxVaryingVectors = GetMaximumVertexOutputVectors(featureLevel); + caps->maxCombinedTextureImageUnits = caps->maxVertexTextureImageUnits + caps->maxFragmentInputComponents; + + // Transform feedback limits + caps->maxTransformFeedbackInterleavedComponents = GetMaximumStreamOutputInterleavedComponenets(featureLevel); + caps->maxTransformFeedbackSeparateAttributes = GetMaximumStreamOutputBuffers(featureLevel); + caps->maxTransformFeedbackSeparateComponents = GetMaximumStreamOutputSeparateCompeonents(featureLevel); + + // GL extension support + extensions->setTextureExtensionSupport(*textureCapsMap); + extensions->elementIndexUint = true; + extensions->packedDepthStencil = true; + extensions->getProgramBinary = true; + extensions->rgb8rgba8 = true; + extensions->readFormatBGRA = true; + extensions->pixelBufferObject = true; + extensions->mapBuffer = true; + extensions->mapBufferRange = true; + extensions->textureNPOT = GetNPOTTextureSupport(featureLevel); + extensions->drawBuffers = GetMaximumSimultaneousRenderTargets(featureLevel) > 1; + extensions->textureStorage = true; + extensions->textureFilterAnisotropic = true; + extensions->maxTextureAnisotropy = GetMaximumAnisotropy(featureLevel); + extensions->occlusionQueryBoolean = GetOcclusionQuerySupport(featureLevel); + extensions->fence = GetEventQuerySupport(featureLevel); + extensions->timerQuery = false; // Unimplemented + extensions->robustness = true; + extensions->blendMinMax = true; + extensions->framebufferBlit = true; + extensions->framebufferMultisample = true; + extensions->maxSamples = maxSamples; + extensions->instancedArrays = GetInstancingSupport(featureLevel); + extensions->packReverseRowOrder = true; + extensions->standardDerivatives = GetDerivativeInstructionSupport(featureLevel); + extensions->shaderTextureLOD = true; + extensions->fragDepth = true; + extensions->textureUsage = true; // This could be false since it has no effect in D3D11 + extensions->translatedShaderSource = true; +} + +} + +namespace d3d11 +{ + +void MakeValidSize(bool isImage, DXGI_FORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset) +{ + const DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(format); + + int upsampleCount = 0; + // Don't expand the size of full textures that are at least (blockWidth x blockHeight) already. + if (isImage || *requestWidth < static_cast(dxgiFormatInfo.blockWidth) || + *requestHeight < static_cast(dxgiFormatInfo.blockHeight)) + { + while (*requestWidth % dxgiFormatInfo.blockWidth != 0 || *requestHeight % dxgiFormatInfo.blockHeight != 0) + { + *requestWidth <<= 1; + *requestHeight <<= 1; + upsampleCount++; + } + } + *levelOffset = upsampleCount; +} + +void GenerateInitialTextureData(GLint internalFormat, GLuint width, GLuint height, GLuint depth, + GLuint mipLevels, std::vector *outSubresourceData, + std::vector< std::vector > *outData) +{ + const d3d11::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(internalFormat); + ASSERT(d3dFormatInfo.dataInitializerFunction != NULL); + + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(d3dFormatInfo.texFormat); + + outSubresourceData->resize(mipLevels); + outData->resize(mipLevels); + + for (unsigned int i = 0; i < mipLevels; i++) + { + unsigned int mipWidth = std::max(width >> i, 1U); + unsigned int mipHeight = std::max(height >> i, 1U); + unsigned int mipDepth = std::max(depth >> i, 1U); + + unsigned int rowWidth = dxgiFormatInfo.pixelBytes * mipWidth; + unsigned int imageSize = rowWidth * height; + + outData->at(i).resize(rowWidth * mipHeight * mipDepth); + d3dFormatInfo.dataInitializerFunction(mipWidth, mipHeight, mipDepth, outData->at(i).data(), rowWidth, imageSize); + + outSubresourceData->at(i).pSysMem = outData->at(i).data(); + outSubresourceData->at(i).SysMemPitch = rowWidth; + outSubresourceData->at(i).SysMemSlicePitch = imageSize; + } +} + +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 SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex* vertex, float x, float y, + unsigned int layer, float u, float v, float s) +{ + vertex->x = x; + vertex->y = y; + vertex->l = layer; + vertex->u = u; + vertex->v = v; + vertex->s = s; +} + +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/d3d11/renderer11_utils.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.h similarity index 90% rename from gfx/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.h index 94bb8f88fe29..4c5a3b5477fc 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.h +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2012-2014 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,6 +11,9 @@ #define LIBGLESV2_RENDERER_RENDERER11_UTILS_H #include "libGLESv2/angletypes.h" +#include "libGLESv2/Caps.h" + +#include namespace rx { @@ -36,10 +39,19 @@ D3D11_QUERY ConvertQueryType(GLenum queryType); } +namespace d3d11_gl +{ + +void GenerateCaps(ID3D11Device *device, gl::Caps *caps, gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions); + +} + namespace d3d11 { -void GenerateInitialTextureData(GLint internalFormat, GLuint clientVersion, GLuint width, GLuint height, GLuint depth, +void MakeValidSize(bool isImage, DXGI_FORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset); + +void GenerateInitialTextureData(GLint internalFormat, GLuint width, GLuint height, GLuint depth, GLuint mipLevels, std::vector *outSubresourceData, std::vector< std::vector > *outData); diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/BufferToTexture11.hlsl b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/BufferToTexture11.hlsl rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/Clear11.hlsl b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Clear11.hlsl similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/Clear11.hlsl rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Clear11.hlsl diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/Passthrough2D11.hlsl b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/Passthrough2D11.hlsl rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/Passthrough3D11.hlsl b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/Passthrough3D11.hlsl rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/Swizzle11.hlsl b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Swizzle11.hlsl similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/Swizzle11.hlsl rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Swizzle11.hlsl diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/buffertotexture11_gs.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_gs.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/buffertotexture11_gs.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_gs.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/buffertotexture11_ps_4f.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4f.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/buffertotexture11_ps_4f.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4f.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/buffertotexture11_ps_4i.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4i.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/buffertotexture11_ps_4i.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4i.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/buffertotexture11_ps_4ui.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4ui.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/buffertotexture11_ps_4ui.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4ui.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/buffertotexture11_vs.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_vs.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/buffertotexture11_vs.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_vs.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/clearfloat11ps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/clearfloat11ps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/clearfloat11vs.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearfloat11vs.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/clearfloat11vs.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearfloat11vs.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/clearsint11ps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearsint11ps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/clearsint11ps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearsint11ps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/clearsint11vs.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearsint11vs.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/clearsint11vs.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearsint11vs.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/clearuint11ps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearuint11ps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/clearuint11ps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearuint11ps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/clearuint11vs.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearuint11vs.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/clearuint11vs.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearuint11vs.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthrough2d11vs.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthrough2d11vs.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthrough3d11gs.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough3d11gs.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthrough3d11gs.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough3d11gs.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthrough3d11vs.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough3d11vs.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthrough3d11vs.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough3d11vs.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughdepth2d11ps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughdepth2d11ps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughdepth2d11ps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughdepth2d11ps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughlum2d11ps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlum2d11ps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughlum2d11ps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlum2d11ps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughlum3d11ps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlum3d11ps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughlum3d11ps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlum3d11ps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughlumalpha2d11ps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2d11ps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughlumalpha2d11ps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2d11ps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughlumalpha3d11ps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha3d11ps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughlumalpha3d11ps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha3d11ps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughr2d11ps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2d11ps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughr2d11ps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2d11ps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughr2di11ps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2di11ps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughr2di11ps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2di11ps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughr2dui11ps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2dui11ps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughr2dui11ps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2dui11ps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughr3d11ps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3d11ps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughr3d11ps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3d11ps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughr3di11ps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3di11ps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughr3di11ps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3di11ps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughr3dui11ps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3dui11ps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughr3dui11ps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3dui11ps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrg2d11ps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2d11ps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrg2d11ps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2d11ps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrg2di11ps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2di11ps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrg2di11ps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2di11ps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrg2dui11ps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dui11ps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrg2dui11ps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dui11ps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrg3d11ps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3d11ps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrg3d11ps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3d11ps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrg3di11ps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3di11ps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrg3di11ps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3di11ps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrg3dui11ps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dui11ps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrg3dui11ps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dui11ps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgb2d11ps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2d11ps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgb2d11ps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2d11ps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgb2di11ps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2di11ps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgb2di11ps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2di11ps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgb2dui11ps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dui11ps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgb2dui11ps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dui11ps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgb3d11ps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3d11ps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgb3d11ps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3d11ps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgb3di11ps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3di11ps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgb3di11ps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3di11ps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgb3dui11ps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dui11ps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgb3dui11ps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dui11ps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba2d11ps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba2d11ps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba2di11ps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2di11ps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba2di11ps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2di11ps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba2dui11ps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dui11ps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba2dui11ps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dui11ps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba3d11ps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d11ps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba3d11ps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d11ps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba3di11ps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3di11ps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba3di11ps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3di11ps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba3dui11ps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dui11ps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba3dui11ps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dui11ps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/swizzlef2darrayps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlef2darrayps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/swizzlef2darrayps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlef2darrayps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/swizzlef2dps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlef2dps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/swizzlef2dps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlef2dps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/swizzlef3dps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlef3dps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/swizzlef3dps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlef3dps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/swizzlei2darrayps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlei2darrayps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/swizzlei2darrayps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlei2darrayps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/swizzlei2dps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/swizzlei2dps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/swizzlei3dps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlei3dps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/swizzlei3dps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlei3dps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/swizzleui2darrayps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzleui2darrayps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/swizzleui2darrayps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzleui2darrayps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/swizzleui2dps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzleui2dps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/swizzleui2dps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzleui2dps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/swizzleui3dps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzleui3dps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/compiled/swizzleui3dps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzleui3dps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/shaders/generate_shaders.bat b/gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/generate_shaders.bat similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d11/shaders/generate_shaders.bat rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/generate_shaders.bat diff --git a/gfx/angle/src/libGLESv2/renderer/d3d9/Blit9.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp similarity index 94% rename from gfx/angle/src/libGLESv2/renderer/d3d9/Blit9.cpp rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp index a8485bd78d21..d5f421f1bf13 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d9/Blit9.cpp +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp @@ -1,4 +1,3 @@ -#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 @@ -7,24 +6,24 @@ // Blit9.cpp: Surface copy utility class. -#include "libGLESv2/renderer/d3d9/Blit9.h" - -#include "libGLESv2/main.h" -#include "libGLESv2/renderer/d3d9/renderer9_utils.h" -#include "libGLESv2/renderer/d3d9/formatutils9.h" -#include "libGLESv2/renderer/d3d9/TextureStorage9.h" -#include "libGLESv2/renderer/d3d9/RenderTarget9.h" -#include "libGLESv2/renderer/d3d9/Renderer9.h" +#include "libGLESv2/renderer/d3d/d3d9/Blit9.h" +#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" +#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" +#include "libGLESv2/renderer/d3d/d3d9/TextureStorage9.h" +#include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h" +#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" #include "libGLESv2/Framebuffer.h" -#include "libGLESv2/Renderbuffer.h" +#include "libGLESv2/FramebufferAttachment.h" +#include "libGLESv2/main.h" namespace { -#include "libGLESv2/renderer/d3d9/shaders/compiled/standardvs.h" -#include "libGLESv2/renderer/d3d9/shaders/compiled/flipyvs.h" -#include "libGLESv2/renderer/d3d9/shaders/compiled/passthroughps.h" -#include "libGLESv2/renderer/d3d9/shaders/compiled/luminanceps.h" -#include "libGLESv2/renderer/d3d9/shaders/compiled/componentmaskps.h" +// Precompiled shaders +#include "libGLESv2/renderer/d3d/d3d9/shaders/compiled/standardvs.h" +#include "libGLESv2/renderer/d3d/d3d9/shaders/compiled/flipyvs.h" +#include "libGLESv2/renderer/d3d/d3d9/shaders/compiled/passthroughps.h" +#include "libGLESv2/renderer/d3d/d3d9/shaders/compiled/luminanceps.h" +#include "libGLESv2/renderer/d3d/d3d9/shaders/compiled/componentmaskps.h" const BYTE* const g_shaderCode[] = { @@ -213,7 +212,7 @@ bool Blit9::copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum de { RenderTarget9 *renderTarget = NULL; IDirect3DSurface9 *source = NULL; - gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(0); + gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(0); if (colorbuffer) { @@ -249,7 +248,7 @@ bool Blit9::copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum de { RenderTarget9 *renderTarget = NULL; IDirect3DSurface9 *source = NULL; - gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(0); + gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(0); if (colorbuffer) { @@ -296,7 +295,7 @@ bool Blit9::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destF dest->GetDesc(&destDesc); if (sourceDesc.Format == destDesc.Format && destDesc.Usage & D3DUSAGE_RENDERTARGET && - d3d9_gl::IsFormatChannelEquivalent(destDesc.Format, destFormat, mRenderer->getCurrentClientVersion())) // 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); diff --git a/gfx/angle/src/libGLESv2/renderer/d3d9/Blit9.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.h similarity index 99% rename from gfx/angle/src/libGLESv2/renderer/d3d9/Blit9.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.h index 3635bca932b2..40bf8910fac2 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d9/Blit9.h +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.h @@ -11,6 +11,8 @@ #include "common/angleutils.h" +#include + namespace gl { class Framebuffer; diff --git a/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp new file mode 100644 index 000000000000..3b584eee58b5 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp @@ -0,0 +1,115 @@ +// +// Copyright 2014 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. +// + +// Buffer9.cpp Defines the Buffer9 class. + +#include "libGLESv2/renderer/d3d/d3d9/Buffer9.h" +#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" +#include "libGLESv2/main.h" + +namespace rx +{ + +Buffer9::Buffer9(rx::Renderer9 *renderer) + : BufferD3D(), + mRenderer(renderer), + mSize(0) +{} + +Buffer9::~Buffer9() +{ + mSize = 0; +} + +Buffer9 *Buffer9::makeBuffer9(BufferImpl *buffer) +{ + ASSERT(HAS_DYNAMIC_TYPE(Buffer9*, buffer)); + return static_cast(buffer); +} + +void Buffer9::setData(const void* data, size_t size, GLenum usage) +{ + if (size > mMemory.size()) + { + if (!mMemory.resize(size)) + { + return gl::error(GL_OUT_OF_MEMORY); + } + } + + mSize = size; + if (data) + { + memcpy(mMemory.data(), data, size); + } + + invalidateStaticData(); + + if (usage == GL_STATIC_DRAW) + { + initializeStaticData(); + } +} + +void *Buffer9::getData() +{ + return mMemory.data(); +} + +void Buffer9::setSubData(const void* data, size_t size, size_t offset) +{ + if (offset + size > mMemory.size()) + { + if (!mMemory.resize(offset + size)) + { + return gl::error(GL_OUT_OF_MEMORY); + } + } + + mSize = std::max(mSize, offset + size); + if (data) + { + memcpy(mMemory.data() + offset, data, size); + } + + invalidateStaticData(); +} + +void Buffer9::copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) +{ + // Note: this method is currently unreachable + Buffer9* sourceBuffer = makeBuffer9(source); + if (sourceBuffer) + { + memcpy(mMemory.data() + destOffset, sourceBuffer->mMemory.data() + sourceOffset, size); + } + + invalidateStaticData(); +} + +// We do not suppot buffer mapping in D3D9 +GLvoid* Buffer9::map(size_t offset, size_t length, GLbitfield access) +{ + UNREACHABLE(); + return NULL; +} + +void Buffer9::unmap() +{ + UNREACHABLE(); +} + +void Buffer9::markTransformFeedbackUsage() +{ + UNREACHABLE(); +} + +Renderer* Buffer9::getRenderer() +{ + return mRenderer; +} + +} diff --git a/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.h new file mode 100644 index 000000000000..f12ee0006cd5 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.h @@ -0,0 +1,52 @@ +// +// Copyright 2014 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. +// + +// Buffer9.h: Defines the rx::Buffer9 class which implements rx::BufferImpl via rx::BufferD3D. + +#ifndef LIBGLESV2_RENDERER_BUFFER9_H_ +#define LIBGLESV2_RENDERER_BUFFER9_H_ + +#include "libGLESv2/renderer/d3d/BufferD3D.h" +#include "libGLESv2/renderer/d3d/MemoryBuffer.h" +#include "libGLESv2/angletypes.h" + +namespace rx +{ +class Renderer9; + +class Buffer9 : public BufferD3D +{ + public: + Buffer9(rx::Renderer9 *renderer); + virtual ~Buffer9(); + + static Buffer9 *makeBuffer9(BufferImpl *buffer); + + // BufferD3D implementation + virtual size_t getSize() const { return mSize; } + virtual bool supportsDirectBinding() const { return false; } + virtual Renderer* getRenderer(); + + // BufferImpl implementation + virtual void setData(const void* data, size_t size, GLenum usage); + virtual void *getData(); + virtual void setSubData(const void* data, size_t size, size_t offset); + virtual void copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size); + virtual GLvoid* map(size_t offset, size_t length, GLbitfield access); + virtual void unmap(); + virtual void markTransformFeedbackUsage(); + + private: + DISALLOW_COPY_AND_ASSIGN(Buffer9); + + rx::Renderer9 *mRenderer; + MemoryBuffer mMemory; + size_t mSize; +}; + +} + +#endif // LIBGLESV2_RENDERER_BUFFER9_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/d3d9/Fence9.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.cpp similarity index 88% rename from gfx/angle/src/libGLESv2/renderer/d3d9/Fence9.cpp rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.cpp index 372a8a45a5eb..e352a5f50af4 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d9/Fence9.cpp +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.cpp @@ -1,4 +1,3 @@ -#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 @@ -7,10 +6,10 @@ // Fence9.cpp: Defines the rx::Fence9 class. -#include "libGLESv2/renderer/d3d9/Fence9.h" +#include "libGLESv2/renderer/d3d/d3d9/Fence9.h" +#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" +#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" #include "libGLESv2/main.h" -#include "libGLESv2/renderer/d3d9/renderer9_utils.h" -#include "libGLESv2/renderer/d3d9/Renderer9.h" namespace rx { diff --git a/gfx/angle/src/libGLESv2/renderer/d3d9/Fence9.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d9/Fence9.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d9/Image9.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp similarity index 84% rename from gfx/angle/src/libGLESv2/renderer/d3d9/Image9.cpp rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp index 7ddf957c2539..e52739cace91 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d9/Image9.cpp +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp @@ -1,4 +1,3 @@ -#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 @@ -8,17 +7,17 @@ // Image9.cpp: Implements the rx::Image9 class, which acts as the interface to // the actual underlying surfaces of a Texture. -#include "libGLESv2/renderer/d3d9/Image9.h" - +#include "libGLESv2/renderer/d3d/d3d9/Image9.h" +#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" +#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" +#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" +#include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h" +#include "libGLESv2/renderer/d3d/d3d9/TextureStorage9.h" #include "libGLESv2/main.h" #include "libGLESv2/Framebuffer.h" +#include "libGLESv2/FramebufferAttachment.h" #include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/renderer/d3d9/Renderer9.h" -#include "libGLESv2/renderer/d3d9/RenderTarget9.h" -#include "libGLESv2/renderer/d3d9/TextureStorage9.h" -#include "libGLESv2/renderer/d3d9/renderer9_utils.h" -#include "libGLESv2/renderer/d3d9/formatutils9.h" namespace rx { @@ -51,8 +50,8 @@ void Image9::generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sour ASSERT(sourceDesc.Width == 1 || sourceDesc.Width / 2 == destDesc.Width); ASSERT(sourceDesc.Height == 1 || sourceDesc.Height / 2 == destDesc.Height); - MipGenerationFunction mipFunction = d3d9::GetMipGenerationFunction(sourceDesc.Format); - ASSERT(mipFunction != NULL); + const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(sourceDesc.Format); + ASSERT(d3dFormatInfo.mipGenerationFunction != NULL); D3DLOCKED_RECT sourceLocked = {0}; result = sourceSurface->LockRect(&sourceLocked, NULL, D3DLOCK_READONLY); @@ -62,13 +61,13 @@ void Image9::generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sour result = destSurface->LockRect(&destLocked, NULL, 0); ASSERT(SUCCEEDED(result)); - const unsigned char *sourceData = reinterpret_cast(sourceLocked.pBits); - unsigned char *destData = reinterpret_cast(destLocked.pBits); + const uint8_t *sourceData = reinterpret_cast(sourceLocked.pBits); + uint8_t *destData = reinterpret_cast(destLocked.pBits); if (sourceData && destData) { - mipFunction(sourceDesc.Width, sourceDesc.Height, 1, sourceData, sourceLocked.Pitch, 0, - destData, destLocked.Pitch, 0); + d3dFormatInfo.mipGenerationFunction(sourceDesc.Width, sourceDesc.Height, 1, sourceData, sourceLocked.Pitch, 0, + destData, destLocked.Pitch, 0); } destSurface->UnlockRect(); @@ -97,22 +96,23 @@ void Image9::copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *so { 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 blockHeight = d3d9::GetBlockHeight(desc.Format); - int rows = desc.Height / blockHeight; + const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format); + unsigned int rows = desc.Height / d3dFormatInfo.blockHeight; - int bytes = d3d9::GetBlockSize(desc.Format, desc.Width, blockHeight); - ASSERT(bytes <= sourceLock.Pitch && bytes <= destLock.Pitch); + unsigned int bytes = d3d9::ComputeBlockSize(desc.Format, desc.Width, d3dFormatInfo.blockHeight); + ASSERT(bytes <= static_cast(sourceLock.Pitch) && + bytes <= static_cast(destLock.Pitch)); - for(int i = 0; i < rows; i++) + for(unsigned int i = 0; i < rows; i++) { memcpy((char*)destLock.pBits + destLock.Pitch * i, (char*)sourceLock.pBits + sourceLock.Pitch * i, bytes); } @@ -145,12 +145,14 @@ bool Image9::redefine(rx::Renderer *renderer, GLenum target, GLenum internalform mInternalFormat = internalformat; // compute the d3d format that will be used - mD3DFormat = gl_d3d9::GetTextureFormat(internalformat, mRenderer); - mActualFormat = d3d9_gl::GetInternalFormat(mD3DFormat); - mRenderable = gl_d3d9::GetRenderFormat(internalformat, mRenderer) != D3DFMT_UNKNOWN; + const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(internalformat); + const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(d3d9FormatInfo.texFormat); + mD3DFormat = d3d9FormatInfo.texFormat; + mActualFormat = d3dFormatInfo.internalFormat; + mRenderable = (d3d9FormatInfo.renderFormat != D3DFMT_UNKNOWN); SafeRelease(mSurface); - mDirty = gl_d3d9::RequiresTextureDataInitialization(mInternalFormat); + mDirty = (d3d9FormatInfo.dataInitializerFunction != NULL); return true; } @@ -192,10 +194,9 @@ void Image9::createSurface() newTexture->GetSurfaceLevel(levelToFetch, &newSurface); SafeRelease(newTexture); - if (gl_d3d9::RequiresTextureDataInitialization(mInternalFormat)) + const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat); + if (d3dFormatInfo.dataInitializerFunction != NULL) { - InitializeTextureDataFunction initializeFunc = gl_d3d9::GetTextureDataInitializationFunction(mInternalFormat); - RECT entireRect; entireRect.left = 0; entireRect.right = mWidth; @@ -206,7 +207,8 @@ void Image9::createSurface() result = newSurface->LockRect(&lockedRect, &entireRect, 0); ASSERT(SUCCEEDED(result)); - initializeFunc(mWidth, mHeight, 1, lockedRect.pBits, lockedRect.Pitch, 0); + d3dFormatInfo.dataInitializerFunction(mWidth, mHeight, 1, reinterpret_cast(lockedRect.pBits), + lockedRect.Pitch, 0); result = newSurface->UnlockRect(); ASSERT(SUCCEEDED(result)); @@ -258,7 +260,7 @@ bool Image9::isDirty() const { // Make sure to that this image is marked as dirty even if the staging texture hasn't been created yet // if initialization is required before use. - return (mSurface || gl_d3d9::RequiresTextureDataInitialization(mInternalFormat)) && mDirty; + return (mSurface || d3d9::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL) && mDirty; } IDirect3DSurface9 *Image9::getSurface() @@ -385,11 +387,11 @@ void Image9::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width // 3D textures are not supported by the D3D9 backend. ASSERT(zoffset == 0 && depth == 1); - GLuint clientVersion = mRenderer->getCurrentClientVersion(); - GLsizei inputRowPitch = gl::GetRowPitch(mInternalFormat, type, clientVersion, width, unpackAlignment); + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat); + GLsizei inputRowPitch = formatInfo.computeRowPitch(type, width, unpackAlignment); - LoadImageFunction loadFunction = d3d9::GetImageLoadFunction(mInternalFormat, mRenderer); - ASSERT(loadFunction != NULL); + const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat); + ASSERT(d3dFormatInfo.loadFunction != NULL); RECT lockRect = { @@ -404,7 +406,9 @@ void Image9::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width return; } - loadFunction(width, height, depth, input, inputRowPitch, 0, locked.pBits, locked.Pitch, 0); + d3dFormatInfo.loadFunction(width, height, depth, + reinterpret_cast(input), inputRowPitch, 0, + reinterpret_cast(locked.pBits), locked.Pitch, 0); unlock(); } @@ -415,15 +419,16 @@ void Image9::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLs // 3D textures are not supported by the D3D9 backend. ASSERT(zoffset == 0 && depth == 1); - GLuint clientVersion = mRenderer->getCurrentClientVersion(); - GLsizei inputRowPitch = gl::GetRowPitch(mInternalFormat, GL_UNSIGNED_BYTE, clientVersion, width, 1); - GLsizei inputDepthPitch = gl::GetDepthPitch(mInternalFormat, GL_UNSIGNED_BYTE, clientVersion, width, height, 1); + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat); + GLsizei inputRowPitch = formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, width, 1); + GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, width, height, 1); - ASSERT(xoffset % d3d9::GetBlockWidth(mD3DFormat) == 0); - ASSERT(yoffset % d3d9::GetBlockHeight(mD3DFormat) == 0); + const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat); - LoadImageFunction loadFunction = d3d9::GetImageLoadFunction(mInternalFormat, mRenderer); - ASSERT(loadFunction != NULL); + ASSERT(xoffset % d3d9::GetD3DFormatInfo(d3d9FormatInfo.texFormat).blockWidth == 0); + ASSERT(yoffset % d3d9::GetD3DFormatInfo(d3d9FormatInfo.texFormat).blockHeight == 0); + + ASSERT(d3d9FormatInfo.loadFunction != NULL); RECT lockRect = { @@ -438,8 +443,9 @@ void Image9::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLs return; } - loadFunction(width, height, depth, input, inputRowPitch, inputDepthPitch, - locked.pBits, locked.Pitch, 0); + d3d9FormatInfo.loadFunction(width, height, depth, + reinterpret_cast(input), inputRowPitch, inputDepthPitch, + reinterpret_cast(locked.pBits), locked.Pitch, 0); unlock(); } @@ -452,7 +458,7 @@ void Image9::copy(GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, RenderTarget9 *renderTarget = NULL; IDirect3DSurface9 *surface = NULL; - gl::Renderbuffer *colorbuffer = source->getColorbuffer(0); + gl::FramebufferAttachment *colorbuffer = source->getColorbuffer(0); if (colorbuffer) { diff --git a/gfx/angle/src/libGLESv2/renderer/d3d9/Image9.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.h similarity index 95% rename from gfx/angle/src/libGLESv2/renderer/d3d9/Image9.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.h index 8b5ba89ff24c..2d1536f24bf0 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d9/Image9.h +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2014 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,7 +10,7 @@ #ifndef LIBGLESV2_RENDERER_IMAGE9_H_ #define LIBGLESV2_RENDERER_IMAGE9_H_ -#include "libGLESv2/renderer/Image.h" +#include "libGLESv2/renderer/d3d/ImageD3D.h" #include "common/debug.h" namespace gl @@ -25,7 +25,7 @@ class Renderer9; class TextureStorageInterface2D; class TextureStorageInterfaceCube; -class Image9 : public Image +class Image9 : public ImageD3D { public: Image9(); diff --git a/gfx/angle/src/libGLESv2/renderer/d3d9/IndexBuffer9.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.cpp similarity index 94% rename from gfx/angle/src/libGLESv2/renderer/d3d9/IndexBuffer9.cpp rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.cpp index bc2e6a8002c7..451ede4c2f30 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d9/IndexBuffer9.cpp +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.cpp @@ -1,14 +1,13 @@ -#include "precompiled.h" // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2014 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/d3d9/IndexBuffer9.h" -#include "libGLESv2/renderer/d3d9/Renderer9.h" +#include "libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h" +#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" namespace rx { @@ -41,7 +40,7 @@ bool IndexBuffer9::initialize(unsigned int bufferSize, GLenum indexType, bool dy } else if (indexType == GL_UNSIGNED_INT) { - if (mRenderer->get32BitIndexSupport()) + if (mRenderer->getRendererExtensions().elementIndexUint) { format = D3DFMT_INDEX32; } diff --git a/gfx/angle/src/libGLESv2/renderer/d3d9/IndexBuffer9.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h similarity index 96% rename from gfx/angle/src/libGLESv2/renderer/d3d9/IndexBuffer9.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h index 680186753245..cfc20e1c64f4 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d9/IndexBuffer9.h +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h @@ -9,7 +9,7 @@ #ifndef LIBGLESV2_RENDERER_INDEXBUFFER9_H_ #define LIBGLESV2_RENDERER_INDEXBUFFER9_H_ -#include "libGLESv2/renderer/IndexBuffer.h" +#include "libGLESv2/renderer/d3d/IndexBuffer.h" namespace rx { diff --git a/gfx/angle/src/libGLESv2/renderer/d3d9/Query9.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.cpp similarity index 88% rename from gfx/angle/src/libGLESv2/renderer/d3d9/Query9.cpp rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.cpp index bc3f58fb7bde..c8752bb8c19e 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d9/Query9.cpp +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.cpp @@ -1,4 +1,3 @@ -#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 @@ -7,16 +6,16 @@ // Query9.cpp: Defines the rx::Query9 class which implements rx::QueryImpl. - -#include "libGLESv2/renderer/d3d9/Query9.h" +#include "libGLESv2/renderer/d3d/d3d9/Query9.h" +#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" +#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" #include "libGLESv2/main.h" -#include "libGLESv2/renderer/d3d9/renderer9_utils.h" -#include "libGLESv2/renderer/d3d9/Renderer9.h" + +#include namespace rx { - -Query9::Query9(rx::Renderer9 *renderer, GLenum type) : QueryImpl(type) +Query9::Query9(rx::Renderer9 *renderer, GLenum type) : QueryImpl(type), mStatus(GL_FALSE), mResult(0) { mRenderer = renderer; mQuery = NULL; @@ -27,19 +26,20 @@ Query9::~Query9() SafeRelease(mQuery); } -void Query9::begin() +bool Query9::begin() { if (mQuery == NULL) { if (FAILED(mRenderer->getDevice()->CreateQuery(D3DQUERYTYPE_OCCLUSION, &mQuery))) { - return gl::error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY, false); } } HRESULT result = mQuery->Issue(D3DISSUE_BEGIN); UNUSED_ASSERTION_VARIABLE(result); ASSERT(SUCCEEDED(result)); + return true; } void Query9::end() @@ -117,9 +117,4 @@ GLboolean Query9::testQuery() return GL_TRUE; // prevent blocking when query is null } -bool Query9::isStarted() const -{ - return (mQuery != NULL); -} - } diff --git a/gfx/angle/src/libGLESv2/renderer/d3d9/Query9.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.h similarity index 92% rename from gfx/angle/src/libGLESv2/renderer/d3d9/Query9.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.h index 62906230c479..fc7f0b310096 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d9/Query9.h +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.h @@ -21,17 +21,19 @@ class Query9 : public QueryImpl Query9(rx::Renderer9 *renderer, GLenum type); virtual ~Query9(); - virtual void begin(); + virtual bool begin(); virtual void end(); virtual GLuint getResult(); virtual GLboolean isResultAvailable(); - virtual bool isStarted() const; private: DISALLOW_COPY_AND_ASSIGN(Query9); GLboolean testQuery(); + GLuint mResult; + GLboolean mStatus; + rx::Renderer9 *mRenderer; IDirect3DQuery9 *mQuery; }; diff --git a/gfx/angle/src/libGLESv2/renderer/d3d9/RenderTarget9.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp similarity index 72% rename from gfx/angle/src/libGLESv2/renderer/d3d9/RenderTarget9.cpp rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp index 9456e482a165..b33e70da8c88 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d9/RenderTarget9.cpp +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp @@ -1,6 +1,5 @@ -#include "precompiled.h" // -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2012-2014 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,11 +7,10 @@ // RenderTarget9.cpp: Implements a D3D9-specific wrapper for IDirect3DSurface9 // pointers retained by renderbuffers. -#include "libGLESv2/renderer/d3d9/RenderTarget9.h" -#include "libGLESv2/renderer/d3d9/Renderer9.h" - -#include "libGLESv2/renderer/d3d9/renderer9_utils.h" -#include "libGLESv2/renderer/d3d9/formatutils9.h" +#include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h" +#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" +#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" +#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" #include "libGLESv2/main.h" namespace rx @@ -33,8 +31,9 @@ RenderTarget9::RenderTarget9(Renderer *renderer, IDirect3DSurface9 *surface) mHeight = description.Height; mDepth = 1; - mInternalFormat = d3d9_gl::GetInternalFormat(description.Format); - mActualFormat = d3d9_gl::GetInternalFormat(description.Format); + const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(description.Format); + mInternalFormat = d3dFormatInfo.internalFormat; + mActualFormat = d3dFormatInfo.internalFormat; mSamples = d3d9_gl::GetSamplesCount(description.MultiSampleType); } } @@ -44,38 +43,31 @@ RenderTarget9::RenderTarget9(Renderer *renderer, GLsizei width, GLsizei height, mRenderer = Renderer9::makeRenderer9(renderer); mRenderTarget = NULL; - D3DFORMAT renderFormat = gl_d3d9::GetRenderFormat(internalFormat, mRenderer); - int supportedSamples = mRenderer->getNearestSupportedSamples(renderFormat, samples); + const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(internalFormat); + const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(d3d9FormatInfo.renderFormat); - if (supportedSamples == -1) - { - gl::error(GL_OUT_OF_MEMORY); - - return; - } + const gl::TextureCaps &textureCaps = mRenderer->getRendererTextureCaps().get(internalFormat); + GLuint supportedSamples = textureCaps.getNearestSamples(samples); HRESULT result = D3DERR_INVALIDCALL; - GLuint clientVersion = mRenderer->getCurrentClientVersion(); - if (width > 0 && height > 0) { IDirect3DDevice9 *device = mRenderer->getDevice(); bool requiresInitialization = false; - if (gl::GetDepthBits(internalFormat, clientVersion) > 0 || - gl::GetStencilBits(internalFormat, clientVersion) > 0) + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); + if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) { - result = device->CreateDepthStencilSurface(width, height, renderFormat, + result = device->CreateDepthStencilSurface(width, height, d3d9FormatInfo.renderFormat, gl_d3d9::GetMultisampleType(supportedSamples), 0, FALSE, &mRenderTarget, NULL); } else { - requiresInitialization = gl_d3d9::RequiresTextureDataInitialization(internalFormat); - - result = device->CreateRenderTarget(width, height, renderFormat, + requiresInitialization = (d3d9FormatInfo.dataInitializerFunction != NULL); + result = device->CreateRenderTarget(width, height, d3d9FormatInfo.renderFormat, gl_d3d9::GetMultisampleType(supportedSamples), 0, FALSE, &mRenderTarget, NULL); } @@ -109,7 +101,7 @@ RenderTarget9::RenderTarget9(Renderer *renderer, GLsizei width, GLsizei height, mDepth = 1; mInternalFormat = internalFormat; mSamples = supportedSamples; - mActualFormat = d3d9_gl::GetInternalFormat(renderFormat); + mActualFormat = d3dFormatInfo.internalFormat; } RenderTarget9::~RenderTarget9() diff --git a/gfx/angle/src/libGLESv2/renderer/d3d9/RenderTarget9.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d9/RenderTarget9.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d9/Renderer9.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp similarity index 76% rename from gfx/angle/src/libGLESv2/renderer/d3d9/Renderer9.cpp rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp index 7ddd98b1675f..af510334b141 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d9/Renderer9.cpp +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -7,35 +6,41 @@ // Renderer9.cpp: Implements a back-end specific class for the D3D9 renderer. -#include "common/utilities.h" - +#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" +#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" +#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" +#include "libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.h" +#include "libGLESv2/renderer/d3d/d3d9/SwapChain9.h" +#include "libGLESv2/renderer/d3d/d3d9/TextureStorage9.h" +#include "libGLESv2/renderer/d3d/d3d9/Image9.h" +#include "libGLESv2/renderer/d3d/d3d9/Blit9.h" +#include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h" +#include "libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h" +#include "libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h" +#include "libGLESv2/renderer/d3d/d3d9/Buffer9.h" +#include "libGLESv2/renderer/d3d/d3d9/Query9.h" +#include "libGLESv2/renderer/d3d/d3d9/Fence9.h" +#include "libGLESv2/renderer/d3d/d3d9/VertexArray9.h" +#include "libGLESv2/renderer/d3d/IndexDataManager.h" +#include "libGLESv2/renderer/d3d/ShaderD3D.h" +#include "libGLESv2/renderer/d3d/TextureD3D.h" +#include "libGLESv2/renderer/d3d/TransformFeedbackD3D.h" #include "libGLESv2/main.h" #include "libGLESv2/Buffer.h" #include "libGLESv2/Texture.h" #include "libGLESv2/Framebuffer.h" +#include "libGLESv2/FramebufferAttachment.h" #include "libGLESv2/Renderbuffer.h" #include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/renderer/IndexDataManager.h" -#include "libGLESv2/renderer/d3d9/Renderer9.h" -#include "libGLESv2/renderer/d3d9/renderer9_utils.h" -#include "libGLESv2/renderer/d3d9/formatutils9.h" -#include "libGLESv2/renderer/d3d9/ShaderExecutable9.h" -#include "libGLESv2/renderer/d3d9/SwapChain9.h" -#include "libGLESv2/renderer/d3d9/TextureStorage9.h" -#include "libGLESv2/renderer/d3d9/Image9.h" -#include "libGLESv2/renderer/d3d9/Blit9.h" -#include "libGLESv2/renderer/d3d9/RenderTarget9.h" -#include "libGLESv2/renderer/d3d9/VertexBuffer9.h" -#include "libGLESv2/renderer/d3d9/IndexBuffer9.h" -#include "libGLESv2/renderer/d3d9/BufferStorage9.h" -#include "libGLESv2/renderer/d3d9/Query9.h" -#include "libGLESv2/renderer/d3d9/Fence9.h" #include "libGLESv2/angletypes.h" #include "libEGL/Display.h" +#include "common/utilities.h" + #include "third_party/trace_event/trace_event.h" -#include "third_party/systeminfo/SystemInfo.h" + +#include // Can also be enabled by defining FORCE_REF_RAST in the project's predefined macros #define REF_RAST 0 @@ -92,7 +97,9 @@ enum MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 = 4 }; -Renderer9::Renderer9(egl::Display *display, HDC hDc) : Renderer(display), mDc(hDc) +Renderer9::Renderer9(egl::Display *display, EGLNativeDisplayType hDc, EGLint requestedDisplay) + : Renderer(display), + mDc(hDc) { mD3d9Module = NULL; @@ -113,8 +120,6 @@ Renderer9::Renderer9(egl::Display *display, HDC hDc) : Renderer(display), mDc(hD mDeviceLost = false; - mMaxSupportedSamples = 0; - mMaskedClearSavedState = NULL; mVertexDataManager = NULL; @@ -146,11 +151,12 @@ Renderer9::~Renderer9() } } - deinitialize(); + release(); } -void Renderer9::deinitialize() +void Renderer9::release() { + releaseShaderCompiler(); releaseDeviceResources(); SafeRelease(mDevice); @@ -264,15 +270,6 @@ EGLint Renderer9::initialize() 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) && - !(!isWindowsVistaOrGreater() && 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; @@ -302,17 +299,6 @@ EGLint Renderer9::initialize() mMaxSwapInterval = std::max(mMaxSwapInterval, 4); } - mMaxSupportedSamples = 0; - - const d3d9::D3DFormatSet &d3d9Formats = d3d9::GetAllUsedD3DFormats(); - for (d3d9::D3DFormatSet::const_iterator i = d3d9Formats.begin(); i != d3d9Formats.end(); ++i) - { - TRACE_EVENT0("gpu", "getMultiSampleSupport"); - MultisampleSupportInfo support = getMultiSampleSupport(*i); - mMultiSampleSupport[*i] = support; - mMaxSupportedSamples = std::max(mMaxSupportedSamples, support.maxSupportedSamples); - } - static const TCHAR windowName[] = TEXT("AngleHiddenWindow"); static const TCHAR className[] = TEXT("STATIC"); @@ -358,36 +344,6 @@ EGLint Renderer9::initialize() mPixelShaderCache.initialize(mDevice); } - // Check occlusion query support - IDirect3DQuery9 *occlusionQuery = NULL; - { - TRACE_EVENT0("gpu", "device_CreateQuery"); - if (SUCCEEDED(mDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery)) && occlusionQuery) - { - SafeRelease(occlusionQuery); - mOcclusionQuerySupport = true; - } - else - { - mOcclusionQuerySupport = false; - } - } - - // Check event query support - IDirect3DQuery9 *eventQuery = NULL; - { - TRACE_EVENT0("gpu", "device_CreateQuery2"); - if (SUCCEEDED(mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery)) && eventQuery) - { - SafeRelease(eventQuery); - mEventQuerySupport = true; - } - else - { - mEventQuerySupport = false; - } - } - D3DDISPLAYMODE currentDisplayMode; mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); @@ -398,97 +354,8 @@ EGLint Renderer9::initialize() SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F)); - // Check RGB565 texture support - mRGB565TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, - D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_R5G6B5)); - - // 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; - } - - D3DFORMAT rgTextureFormats[] = - { - D3DFMT_R16F, - D3DFMT_G16R16F, - D3DFMT_R32F, - D3DFMT_G32R32F, - }; - - mRGTextureSupport = true; - for (unsigned int i = 0; i < ArraySize(rgTextureFormats); i++) - { - D3DFORMAT fmt = rgTextureFormats[i]; - mRGTextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER, D3DRTYPE_TEXTURE, fmt)) && - SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, fmt)) && - SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER, D3DRTYPE_CUBETEXTURE, fmt)) && - SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, D3DRTYPE_CUBETEXTURE, fmt)); - } - - - // 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(); - d3d9::InitializeVertexTranslations(this); - return EGL_SUCCESS; } @@ -554,40 +421,24 @@ int Renderer9::generateConfigs(ConfigDesc **configDescList) 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)) + const d3d9::D3DFormat &renderTargetFormatInfo = d3d9::GetD3DFormatInfo(RenderTargetFormats[formatIndex]); + const gl::TextureCaps &renderTargetFormatCaps = getRendererTextureCaps().get(renderTargetFormatInfo.internalFormat); + if (renderTargetFormatCaps.renderable) { for (unsigned int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++) { - D3DFORMAT depthStencilFormat = DepthStencilFormats[depthStencilIndex]; - HRESULT result = D3D_OK; - - if(depthStencilFormat != D3DFMT_UNKNOWN) + const d3d9::D3DFormat &depthStencilFormatInfo = d3d9::GetD3DFormatInfo(DepthStencilFormats[depthStencilIndex]); + const gl::TextureCaps &depthStencilFormatCaps = getRendererTextureCaps().get(depthStencilFormatInfo.internalFormat); + if (depthStencilFormatCaps.renderable || DepthStencilFormats[depthStencilIndex] == D3DFMT_UNKNOWN) { - result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, depthStencilFormat); - } + ConfigDesc newConfig; + newConfig.renderTargetFormat = renderTargetFormatInfo.internalFormat; + newConfig.depthStencilFormat = depthStencilFormatInfo.internalFormat; + newConfig.multiSample = 0; // FIXME: enumerate multi-sampling + newConfig.fastConfig = (currentDisplayMode.Format == RenderTargetFormats[formatIndex]); + newConfig.es3Capable = false; - 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::GetInternalFormat(renderTargetFormat); - newConfig.depthStencilFormat = d3d9_gl::GetInternalFormat(depthStencilFormat); - newConfig.multiSample = 0; // FIXME: enumerate multi-sampling - newConfig.fastConfig = (currentDisplayMode.Format == renderTargetFormat); - newConfig.es3Capable = false; - - (*configDescList)[numConfigs++] = newConfig; - } + (*configDescList)[numConfigs++] = newConfig; } } } @@ -733,9 +584,14 @@ IndexBuffer *Renderer9::createIndexBuffer() return new IndexBuffer9(this); } -BufferStorage *Renderer9::createBufferStorage() +BufferImpl *Renderer9::createBuffer() { - return new BufferStorage9(); + return new Buffer9(this); +} + +VertexArrayImpl *Renderer9::createVertexArray() +{ + return new VertexArray9(this); } QueryImpl *Renderer9::createQuery(GLenum type) @@ -748,6 +604,11 @@ FenceImpl *Renderer9::createFence() return new Fence9(this); } +TransformFeedbackImpl* Renderer9::createTransformFeedback() +{ + return new TransformFeedbackD3D(); +} + bool Renderer9::supportsFastCopyBufferToTexture(GLenum internalFormat) const { // Pixel buffer objects are not supported in D3D9, since D3D9 is ES2-only and PBOs are ES3. @@ -787,7 +648,7 @@ void Renderer9::setSamplerState(gl::SamplerType type, int index, const gl::Sampl mDevice->SetSamplerState(d3dSampler, D3DSAMP_MINFILTER, d3dMinFilter); mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter); mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXMIPLEVEL, samplerState.baseLevel); - if (mSupportsTextureFilterAnisotropy) + if (getRendererExtensions().textureFilterAnisotropic) { mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXANISOTROPY, (DWORD)samplerState.maxAnisotropy); } @@ -809,7 +670,9 @@ void Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *texture if (texture) { - TextureStorageInterface *texStorage = texture->getNativeTexture(); + TextureD3D* textureImpl = TextureD3D::makeTextureD3D(texture->getImplementation()); + + TextureStorageInterface *texStorage = textureImpl->getNativeTexture(); if (texStorage) { TextureStorage9 *storage9 = TextureStorage9::makeTextureStorage9(texStorage->getStorageInstance()); @@ -820,7 +683,8 @@ void Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *texture ASSERT(d3dTexture != NULL); serial = texture->getTextureSerial(); - forceSetTexture = texture->hasDirtyImages(); + forceSetTexture = textureImpl->hasDirtyImages(); + textureImpl->resetDirty(); } if (forceSetTexture || appliedSerials[index] != serial) @@ -930,9 +794,8 @@ void Renderer9::setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState FIXME("Sample alpha to coverage is unimplemented."); } - gl::Renderbuffer *renderBuffer = framebuffer->getFirstColorbuffer(); - GLenum internalFormat = renderBuffer ? renderBuffer->getInternalFormat() : GL_NONE; - GLuint clientVersion = getCurrentClientVersion(); + gl::FramebufferAttachment *attachment = framebuffer->getFirstColorbuffer(); + GLenum internalFormat = attachment ? attachment->getInternalFormat() : GL_NONE; // Set the color mask bool zeroColorMaskAllowed = getAdapterVendor() != VENDOR_ID_AMD; @@ -942,10 +805,11 @@ void Renderer9::setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState // drawing is done. // http://code.google.com/p/angleproject/issues/detail?id=169 - DWORD colorMask = gl_d3d9::ConvertColorMask(gl::GetRedBits(internalFormat, clientVersion) > 0 && blendState.colorMaskRed, - gl::GetGreenBits(internalFormat, clientVersion) > 0 && blendState.colorMaskGreen, - gl::GetBlueBits(internalFormat, clientVersion) > 0 && blendState.colorMaskBlue, - gl::GetAlphaBits(internalFormat, clientVersion) > 0 && blendState.colorMaskAlpha); + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); + DWORD colorMask = gl_d3d9::ConvertColorMask(formatInfo.redBits > 0 && blendState.colorMaskRed, + formatInfo.greenBits > 0 && blendState.colorMaskGreen, + formatInfo.blueBits > 0 && blendState.colorMaskBlue, + formatInfo.alphaBits > 0 && blendState.colorMaskAlpha); if (colorMask == 0 && !zeroColorMaskAllowed) { // Enable green channel, but set blending so nothing will be drawn. @@ -1014,13 +878,10 @@ void Renderer9::setDepthStencilState(const gl::DepthStencilState &depthStencilSt 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); - } + + ASSERT(depthStencilState.stencilWritemask == depthStencilState.stencilBackWritemask); + ASSERT(stencilRef == stencilBackRef); + ASSERT(depthStencilState.stencilMask == depthStencilState.stencilBackMask); // get the maximum size of the stencil ref unsigned int maxStencil = (1 << mCurStencilSize) - 1; @@ -1218,14 +1079,15 @@ bool Renderer9::applyPrimitiveType(GLenum mode, GLsizei count) mPrimitiveCount = count - 2; break; default: - return gl::error(GL_INVALID_ENUM, false); + UNREACHABLE(); + return false; } return mPrimitiveCount > 0; } -gl::Renderbuffer *Renderer9::getNullColorbuffer(gl::Renderbuffer *depthbuffer) +gl::FramebufferAttachment *Renderer9::getNullColorbuffer(gl::FramebufferAttachment *depthbuffer) { if (!depthbuffer) { @@ -1248,7 +1110,8 @@ gl::Renderbuffer *Renderer9::getNullColorbuffer(gl::Renderbuffer *depthbuffer) } } - gl::Renderbuffer *nullbuffer = new gl::Renderbuffer(this, 0, new gl::Colorbuffer(this, width, height, GL_NONE, 0)); + gl::Renderbuffer *nullRenderbuffer = new gl::Renderbuffer(0, new gl::Colorbuffer(this, width, height, GL_NONE, 0)); + gl::RenderbufferAttachment *nullbuffer = new gl::RenderbufferAttachment(nullRenderbuffer); // add nullbuffer to the cache NullColorbufferCacheEntry *oldest = &mNullColorbufferCache[0]; @@ -1273,29 +1136,25 @@ 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) + gl::FramebufferAttachment *attachment = framebuffer->getColorbuffer(0); + if (!attachment) { - renderbufferObject = framebuffer->getColorbuffer(0); + attachment = getNullColorbuffer(framebuffer->getDepthbuffer()); } - else - { - renderbufferObject = getNullColorbuffer(framebuffer->getDepthbuffer()); - } - if (!renderbufferObject) + if (!attachment) { ERR("unable to locate renderbuffer for FBO."); return false; } bool renderTargetChanged = false; - unsigned int renderTargetSerial = renderbufferObject->getSerial(); + unsigned int renderTargetSerial = attachment->getSerial(); if (renderTargetSerial != mAppliedRenderTargetSerial) { // Apply the render target on the device IDirect3DSurface9 *renderTargetSurface = NULL; - RenderTarget *renderTarget = renderbufferObject->getRenderTarget(); + RenderTarget *renderTarget = attachment->getRenderTarget(); if (renderTarget) { renderTargetSurface = RenderTarget9::makeRenderTarget9(renderTarget)->getSurface(); @@ -1314,29 +1173,16 @@ bool Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer) renderTargetChanged = true; } - gl::Renderbuffer *depthStencil = NULL; + gl::FramebufferAttachment *depthStencil = framebuffer->getDepthbuffer(); unsigned int depthbufferSerial = 0; unsigned int stencilbufferSerial = 0; - if (framebuffer->getDepthbufferType() != GL_NONE) + if (depthStencil) { - depthStencil = framebuffer->getDepthbuffer(); - if (!depthStencil) - { - ERR("Depth stencil pointer unexpectedly null."); - return false; - } - depthbufferSerial = depthStencil->getSerial(); } - else if (framebuffer->getStencilbufferType() != GL_NONE) + else if (framebuffer->getStencilbuffer()) { depthStencil = framebuffer->getStencilbuffer(); - if (!depthStencil) - { - ERR("Depth stencil pointer unexpectedly null."); - return false; - } - stencilbufferSerial = depthStencil->getSerial(); } @@ -1351,7 +1197,7 @@ bool Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer) if (depthStencil) { IDirect3DSurface9 *depthStencilSurface = NULL; - RenderTarget *depthStencilRenderTarget = depthStencil->getDepthStencil(); + RenderTarget *depthStencilRenderTarget = depthStencil->getRenderTarget(); if (depthStencilRenderTarget) { @@ -1398,16 +1244,16 @@ bool Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer) mForceSetViewport = true; mForceSetBlendState = true; - mRenderTargetDesc.width = renderbufferObject->getWidth(); - mRenderTargetDesc.height = renderbufferObject->getHeight(); - mRenderTargetDesc.format = renderbufferObject->getActualFormat(); + mRenderTargetDesc.width = attachment->getWidth(); + mRenderTargetDesc.height = attachment->getHeight(); + mRenderTargetDesc.format = attachment->getActualFormat(); mRenderTargetDescInitialized = true; } return true; } -GLenum Renderer9::applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], gl::VertexAttribCurrentValueData currentValues[], +GLenum Renderer9::applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], const gl::VertexAttribCurrentValueData currentValues[], GLint first, GLsizei count, GLsizei instances) { TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS]; @@ -1492,20 +1338,22 @@ void Renderer9::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvo { startScene(); + int minIndex = static_cast(indexInfo.indexRange.start); + if (mode == GL_POINTS) { - drawIndexedPoints(count, type, indices, indexInfo.minIndex, elementArrayBuffer); + drawIndexedPoints(count, type, indices, minIndex, elementArrayBuffer); } else if (mode == GL_LINE_LOOP) { - drawLineLoop(count, type, indices, indexInfo.minIndex, elementArrayBuffer); + drawLineLoop(count, type, indices, 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); + GLsizei vertexCount = static_cast(indexInfo.indexRange.length()) + 1; + mDevice->DrawIndexedPrimitive(mPrimitiveType, -minIndex, minIndex, vertexCount, indexInfo.startIndex, mPrimitiveCount); } } } @@ -1516,14 +1364,14 @@ void Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, if (type != GL_NONE && elementArrayBuffer) { gl::Buffer *indexBuffer = elementArrayBuffer; - BufferStorage *storage = indexBuffer->getStorage(); + BufferImpl *storage = indexBuffer->getImplementation(); intptr_t offset = reinterpret_cast(indices); indices = static_cast(storage->getData()) + offset; } unsigned int startIndex = 0; - if (get32BitIndexSupport()) + if (getRendererExtensions().elementIndexUint) { if (!mLineLoopIB) { @@ -1714,7 +1562,7 @@ void Renderer9::drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indi if (elementArrayBuffer) { - BufferStorage *storage = elementArrayBuffer->getStorage(); + BufferImpl *storage = elementArrayBuffer->getImplementation(); intptr_t offset = reinterpret_cast(indices); indices = static_cast(storage->getData()) + offset; } @@ -1728,13 +1576,14 @@ void Renderer9::drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indi } } -void Renderer9::applyShaders(gl::ProgramBinary *programBinary, bool rasterizerDiscard, bool transformFeedbackActive, const gl::VertexFormat inputLayout[]) +void Renderer9::applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, + bool rasterizerDiscard, bool transformFeedbackActive) { ASSERT(!transformFeedbackActive); ASSERT(!rasterizerDiscard); ShaderExecutable *vertexExe = programBinary->getVertexExecutableForInputLayout(inputLayout); - ShaderExecutable *pixelExe = programBinary->getPixelExecutable(); + ShaderExecutable *pixelExe = programBinary->getPixelExecutableForFramebuffer(framebuffer); IDirect3DVertexShader9 *vertexShader = (vertexExe ? ShaderExecutable9::makeShaderExecutable9(vertexExe)->getVertexShader() : NULL); IDirect3DPixelShader9 *pixelShader = (pixelExe ? ShaderExecutable9::makeShaderExecutable9(pixelExe)->getPixelShader() : NULL); @@ -1890,8 +1739,7 @@ void Renderer9::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *f unsigned int stencilUnmasked = 0x0; if (clearParams.clearStencil && frameBuffer->hasStencil()) { - unsigned int stencilSize = gl::GetStencilBits(frameBuffer->getStencilbuffer()->getActualFormat(), - getCurrentClientVersion()); + unsigned int stencilSize = gl::GetInternalFormatInfo((frameBuffer->getStencilbuffer()->getActualFormat())).stencilBits; stencilUnmasked = (0x1 << stencilSize) - 1; } @@ -1902,30 +1750,19 @@ void Renderer9::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *f D3DCOLOR color = D3DCOLOR_ARGB(255, 0, 0, 0); if (clearColor) { - gl::Renderbuffer *renderbuffer = frameBuffer->getFirstColorbuffer(); - GLenum internalFormat = renderbuffer->getInternalFormat(); - GLenum actualFormat = renderbuffer->getActualFormat(); + const gl::FramebufferAttachment *attachment = frameBuffer->getFirstColorbuffer(); + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(attachment->getInternalFormat()); + const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(attachment->getActualFormat()); - GLuint clientVersion = getCurrentClientVersion(); - GLuint internalRedBits = gl::GetRedBits(internalFormat, clientVersion); - GLuint internalGreenBits = gl::GetGreenBits(internalFormat, clientVersion); - GLuint internalBlueBits = gl::GetBlueBits(internalFormat, clientVersion); - GLuint internalAlphaBits = gl::GetAlphaBits(internalFormat, clientVersion); + color = D3DCOLOR_ARGB(gl::unorm<8>((formatInfo.alphaBits == 0 && actualFormatInfo.alphaBits > 0) ? 1.0f : clearParams.colorFClearValue.alpha), + gl::unorm<8>((formatInfo.redBits == 0 && actualFormatInfo.redBits > 0) ? 0.0f : clearParams.colorFClearValue.red), + gl::unorm<8>((formatInfo.greenBits == 0 && actualFormatInfo.greenBits > 0) ? 0.0f : clearParams.colorFClearValue.green), + gl::unorm<8>((formatInfo.blueBits == 0 && actualFormatInfo.blueBits > 0) ? 0.0f : clearParams.colorFClearValue.blue)); - GLuint actualRedBits = gl::GetRedBits(actualFormat, clientVersion); - GLuint actualGreenBits = gl::GetGreenBits(actualFormat, clientVersion); - GLuint actualBlueBits = gl::GetBlueBits(actualFormat, clientVersion); - GLuint actualAlphaBits = gl::GetAlphaBits(actualFormat, clientVersion); - - color = D3DCOLOR_ARGB(gl::unorm<8>((internalAlphaBits == 0 && actualAlphaBits > 0) ? 1.0f : clearParams.colorFClearValue.alpha), - gl::unorm<8>((internalRedBits == 0 && actualRedBits > 0) ? 0.0f : clearParams.colorFClearValue.red), - gl::unorm<8>((internalGreenBits == 0 && actualGreenBits > 0) ? 0.0f : clearParams.colorFClearValue.green), - gl::unorm<8>((internalBlueBits == 0 && actualBlueBits > 0) ? 0.0f : clearParams.colorFClearValue.blue)); - - if ((internalRedBits > 0 && !clearParams.colorMaskRed) || - (internalGreenBits > 0 && !clearParams.colorMaskGreen) || - (internalBlueBits > 0 && !clearParams.colorMaskBlue) || - (internalAlphaBits > 0 && !clearParams.colorMaskAlpha)) + if ((formatInfo.redBits > 0 && !clearParams.colorMaskRed) || + (formatInfo.greenBits > 0 && !clearParams.colorMaskGreen) || + (formatInfo.blueBits > 0 && !clearParams.colorMaskBlue) || + (formatInfo.alphaBits > 0 && !clearParams.colorMaskAlpha)) { needMaskedColorClear = true; } @@ -2318,7 +2155,7 @@ bool Renderer9::resetRemovedDevice() // The hardware adapter has been removed. Application must destroy the device, do enumeration of // adapters and create another Direct3D device. If application continues rendering without // calling Reset, the rendering calls will succeed. Applies to Direct3D 9Ex only. - deinitialize(); + release(); return (initialize() == EGL_SUCCESS); } @@ -2352,144 +2189,6 @@ GUID Renderer9::getAdapterIdentifier() const return mAdapterIdentifier.DeviceIdentifier; } -Renderer9::MultisampleSupportInfo Renderer9::getMultiSampleSupport(D3DFORMAT format) -{ - MultisampleSupportInfo support = { 0 }; - - for (unsigned int multiSampleIndex = 0; multiSampleIndex < ArraySize(support.supportedSamples); multiSampleIndex++) - { - HRESULT result = mD3d9->CheckDeviceMultiSampleType(mAdapter, mDeviceType, format, TRUE, - (D3DMULTISAMPLE_TYPE)multiSampleIndex, NULL); - - if (SUCCEEDED(result)) - { - support.supportedSamples[multiSampleIndex] = true; - if (multiSampleIndex != D3DMULTISAMPLE_NONMASKABLE) - { - support.maxSupportedSamples = std::max(support.maxSupportedSamples, multiSampleIndex); - } - } - else - { - support.supportedSamples[multiSampleIndex] = false; - } - } - - return support; -} - -bool Renderer9::getBGRATextureSupport() const -{ - // DirectX 9 always supports BGRA - return true; -} - -bool Renderer9::getDXT1TextureSupport() const -{ - return mDXT1TextureSupport; -} - -bool Renderer9::getDXT3TextureSupport() const -{ - return mDXT3TextureSupport; -} - -bool Renderer9::getDXT5TextureSupport() const -{ - return mDXT5TextureSupport; -} - -bool Renderer9::getDepthTextureSupport() const -{ - return mDepthTextureSupport; -} - -bool Renderer9::getFloat32TextureSupport() const -{ - return mFloat32TextureSupport; -} - -bool Renderer9::getFloat32TextureFilteringSupport() const -{ - return mFloat32FilterSupport; -} - -bool Renderer9::getFloat32TextureRenderingSupport() const -{ - return mFloat32RenderSupport; -} - -bool Renderer9::getFloat16TextureSupport() const -{ - return mFloat16TextureSupport; -} - -bool Renderer9::getFloat16TextureFilteringSupport() const -{ - return mFloat16FilterSupport; -} - -bool Renderer9::getFloat16TextureRenderingSupport() const -{ - return mFloat16RenderSupport; -} - -bool Renderer9::getRGB565TextureSupport() const -{ - return mRGB565TextureSupport; -} - -bool Renderer9::getLuminanceTextureSupport() const -{ - return mLuminanceTextureSupport; -} - -bool Renderer9::getLuminanceAlphaTextureSupport() const -{ - return mLuminanceAlphaTextureSupport; -} - -bool Renderer9::getRGTextureSupport() const -{ - return mRGTextureSupport; -} - -bool Renderer9::getTextureFilterAnisotropySupport() const -{ - return mSupportsTextureFilterAnisotropy; -} - -bool Renderer9::getPBOSupport() const -{ - // D3D9 cannot support PBOs - return false; -} - -float Renderer9::getTextureMaxAnisotropy() const -{ - if (mSupportsTextureFilterAnisotropy) - { - return static_cast(mDeviceCaps.MaxAnisotropy); - } - return 1.0f; -} - -bool Renderer9::getEventQuerySupport() const -{ - 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. @@ -2500,33 +2199,6 @@ 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; -} - -unsigned int Renderer9::getMaxVertexShaderUniformBuffers() const -{ - return 0; -} - -unsigned int Renderer9::getMaxFragmentShaderUniformBuffers() const -{ - return 0; -} - unsigned int Renderer9::getReservedVertexUniformBuffers() const { return 0; @@ -2537,116 +2209,22 @@ unsigned int Renderer9::getReservedFragmentUniformBuffers() const return 0; } -unsigned int Renderer9::getMaxTransformFeedbackBuffers() const -{ - return 0; -} - -unsigned int Renderer9::getMaxTransformFeedbackSeparateComponents() const -{ - return 0; -} - -unsigned int Renderer9::getMaxTransformFeedbackInterleavedComponents() const -{ - return 0; -} - -unsigned int Renderer9::getMaxUniformBufferSize() const -{ - return 0; -} - -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::getMaxRecommendedElementsIndices() const -{ - // ES3 only - UNREACHABLE(); - return 0; -} - -int Renderer9::getMaxRecommendedElementsVertices() const -{ - // ES3 only - UNREACHABLE(); - return 0; -} - 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_2D_TEXTURE_SIZE); - return maxTextureDimension; -} - -int Renderer9::getMaxTextureWidth() const -{ - return (int)mDeviceCaps.MaxTextureWidth; -} - -int Renderer9::getMaxTextureHeight() const -{ - return (int)mDeviceCaps.MaxTextureHeight; -} - -int Renderer9::getMaxTextureDepth() const -{ - // 3D textures are not available in the D3D9 backend. - return 1; -} - -int Renderer9::getMaxTextureArrayLayers() const -{ - // 2D array textures are not available in the D3D9 backend. - return 1; -} - -bool Renderer9::get32BitIndexSupport() const -{ - return mDeviceCaps.MaxVertexIndex >= (1 << 16); -} - DWORD Renderer9::getCapsDeclTypes() const { return mDeviceCaps.DeclTypes; @@ -2662,137 +2240,6 @@ int Renderer9::getMaxSwapInterval() const return mMaxSwapInterval; } -int Renderer9::getMaxSupportedSamples() const -{ - return mMaxSupportedSamples; -} - -GLsizei Renderer9::getMaxSupportedFormatSamples(GLenum internalFormat) const -{ - D3DFORMAT format = gl_d3d9::GetTextureFormat(internalFormat, this); - MultisampleSupportMap::const_iterator itr = mMultiSampleSupport.find(format); - return (itr != mMultiSampleSupport.end()) ? mMaxSupportedSamples : 0; -} - -GLsizei Renderer9::getNumSampleCounts(GLenum internalFormat) const -{ - D3DFORMAT format = gl_d3d9::GetTextureFormat(internalFormat, this); - MultisampleSupportMap::const_iterator iter = mMultiSampleSupport.find(format); - - unsigned int numCounts = 0; - if (iter != mMultiSampleSupport.end()) - { - const MultisampleSupportInfo& info = iter->second; - for (int i = 0; i < D3DMULTISAMPLE_16_SAMPLES; i++) - { - if (i != D3DMULTISAMPLE_NONMASKABLE && info.supportedSamples[i]) - { - numCounts++; - } - } - } - - return numCounts; -} - -void Renderer9::getSampleCounts(GLenum internalFormat, GLsizei bufSize, GLint *params) const -{ - D3DFORMAT format = gl_d3d9::GetTextureFormat(internalFormat, this); - MultisampleSupportMap::const_iterator iter = mMultiSampleSupport.find(format); - - if (iter != mMultiSampleSupport.end()) - { - const MultisampleSupportInfo& info = iter->second; - int bufPos = 0; - for (int i = D3DMULTISAMPLE_16_SAMPLES; i >= 0 && bufPos < bufSize; i--) - { - if (i != D3DMULTISAMPLE_NONMASKABLE && info.supportedSamples[i]) - { - params[bufPos++] = i; - } - } - } -} - -int Renderer9::getNearestSupportedSamples(D3DFORMAT format, int requested) const -{ - if (requested == 0) - { - return requested; - } - - MultisampleSupportMap::const_iterator itr = mMultiSampleSupport.find(format); - if (itr == mMultiSampleSupport.end()) - { - if (format == D3DFMT_UNKNOWN) - return 0; - return -1; - } - - for (unsigned int i = requested; i < ArraySize(itr->second.supportedSamples); ++i) - { - if (itr->second.supportedSamples[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(GLenum 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; @@ -2935,8 +2382,8 @@ bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle & if (blitRenderTarget) { - gl::Renderbuffer *readBuffer = readFramebuffer->getColorbuffer(0); - gl::Renderbuffer *drawBuffer = drawFramebuffer->getColorbuffer(0); + gl::FramebufferAttachment *readBuffer = readFramebuffer->getColorbuffer(0); + gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getColorbuffer(0); RenderTarget9 *readRenderTarget = NULL; RenderTarget9 *drawRenderTarget = NULL; IDirect3DSurface9* readSurface = NULL; @@ -3064,8 +2511,8 @@ bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle & if (blitDepth || blitStencil) { - gl::Renderbuffer *readBuffer = readFramebuffer->getDepthOrStencilbuffer(); - gl::Renderbuffer *drawBuffer = drawFramebuffer->getDepthOrStencilbuffer(); + gl::FramebufferAttachment *readBuffer = readFramebuffer->getDepthOrStencilbuffer(); + gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getDepthOrStencilbuffer(); RenderTarget9 *readDepthStencil = NULL; RenderTarget9 *drawDepthStencil = NULL; IDirect3DSurface9* readSurface = NULL; @@ -3073,11 +2520,11 @@ bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle & if (readBuffer) { - readDepthStencil = RenderTarget9::makeRenderTarget9(readBuffer->getDepthStencil()); + readDepthStencil = RenderTarget9::makeRenderTarget9(readBuffer->getRenderTarget()); } if (drawBuffer) { - drawDepthStencil = RenderTarget9::makeRenderTarget9(drawBuffer->getDepthStencil()); + drawDepthStencil = RenderTarget9::makeRenderTarget9(drawBuffer->getRenderTarget()); } if (readDepthStencil) @@ -3111,13 +2558,13 @@ bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle & } void Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, - GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, void* pixels) + GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) { ASSERT(pack.pixelBuffer.get() == NULL); RenderTarget9 *renderTarget = NULL; IDirect3DSurface9 *surface = NULL; - gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(0); + gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(0); if (colorbuffer) { @@ -3154,7 +2601,7 @@ void Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsiz { // 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); + D3DPOOL_SYSTEMMEM, &systemSurface, reinterpret_cast(&pixels)); if (FAILED(result)) { // Try again without the shared handle @@ -3219,43 +2666,37 @@ void Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsiz return; // No sensible error to generate } - unsigned char *source; + uint8_t *source; int inputPitch; if (pack.reverseRowOrder) { - source = ((unsigned char*)lock.pBits) + lock.Pitch * (rect.bottom - rect.top - 1); + source = reinterpret_cast(lock.pBits) + lock.Pitch * (rect.bottom - rect.top - 1); inputPitch = -lock.Pitch; } else { - source = (unsigned char*)lock.pBits; + source = reinterpret_cast(lock.pBits); inputPitch = lock.Pitch; } - GLuint clientVersion = getCurrentClientVersion(); - - GLenum sourceInternalFormat = d3d9_gl::GetInternalFormat(desc.Format); - GLenum sourceFormat = gl::GetFormat(sourceInternalFormat, clientVersion); - GLenum sourceType = gl::GetType(sourceInternalFormat, clientVersion); - - GLuint sourcePixelSize = gl::GetPixelBytes(sourceInternalFormat, clientVersion); - - if (sourceFormat == format && sourceType == type) + const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format); + const gl::InternalFormat &sourceFormatInfo = gl::GetInternalFormatInfo(d3dFormatInfo.internalFormat); + if (sourceFormatInfo.format == format && sourceFormatInfo.type == type) { // Direct copy possible - unsigned char *dest = static_cast(pixels); for (int y = 0; y < rect.bottom - rect.top; y++) { - memcpy(dest + y * outputPitch, source + y * inputPitch, (rect.right - rect.left) * sourcePixelSize); + memcpy(pixels + y * outputPitch, source + y * inputPitch, (rect.right - rect.left) * sourceFormatInfo.pixelBytes); } } else { - GLenum destInternalFormat = gl::GetSizedInternalFormat(format, type, clientVersion); - GLuint destPixelSize = gl::GetPixelBytes(destInternalFormat, clientVersion); - GLuint sourcePixelSize = gl::GetPixelBytes(sourceInternalFormat, clientVersion); + const d3d9::D3DFormat &sourceD3DFormatInfo = d3d9::GetD3DFormatInfo(desc.Format); + ColorCopyFunction fastCopyFunc = sourceD3DFormatInfo.getFastCopyFunction(format, type); + + const gl::FormatType &destFormatTypeInfo = gl::GetFormatTypeInfo(format, type); + const gl::InternalFormat &destFormatInfo = gl::GetInternalFormatInfo(destFormatTypeInfo.internalFormat); - ColorCopyFunction fastCopyFunc = d3d9::GetFastCopyFunction(desc.Format, format, type, getCurrentClientVersion()); if (fastCopyFunc) { // Fast copy is possible through some special function @@ -3263,8 +2704,8 @@ void Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsiz { for (int x = 0; x < rect.right - rect.left; x++) { - void *dest = static_cast(pixels) + y * outputPitch + x * destPixelSize; - void *src = static_cast(source) + y * inputPitch + x * sourcePixelSize; + uint8_t *dest = pixels + y * outputPitch + x * destFormatInfo.pixelBytes; + const uint8_t *src = source + y * inputPitch + x * sourceFormatInfo.pixelBytes; fastCopyFunc(src, dest); } @@ -3272,22 +2713,18 @@ void Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsiz } else { - ColorReadFunction readFunc = d3d9::GetColorReadFunction(desc.Format); - ColorWriteFunction writeFunc = gl::GetColorWriteFunction(format, type, clientVersion); - - gl::ColorF temp; - + uint8_t temp[sizeof(gl::ColorF)]; for (int y = 0; y < rect.bottom - rect.top; y++) { for (int x = 0; x < rect.right - rect.left; x++) { - void *dest = reinterpret_cast(pixels) + y * outputPitch + x * destPixelSize; - void *src = source + y * inputPitch + x * sourcePixelSize; + uint8_t *dest = pixels + y * outputPitch + x * destFormatInfo.pixelBytes; + const uint8_t *src = source + y * inputPitch + x * sourceFormatInfo.pixelBytes; // readFunc and writeFunc will be using the same type of color, CopyTexImage // will not allow the copy otherwise. - readFunc(src, &temp); - writeFunc(&temp, dest); + sourceD3DFormatInfo.colorReadFunction(src, temp); + destFormatTypeInfo.colorWriteFunction(temp, dest); } } } @@ -3321,6 +2758,25 @@ RenderTarget *Renderer9::createRenderTarget(int width, int height, GLenum format return renderTarget; } +ShaderImpl *Renderer9::createShader(GLenum type) +{ + switch (type) + { + case GL_VERTEX_SHADER: + return new VertexShaderD3D(this); + case GL_FRAGMENT_SHADER: + return new FragmentShaderD3D(this); + default: + UNREACHABLE(); + return NULL; + } +} + +void Renderer9::releaseShaderCompiler() +{ + ShaderD3D::releaseCompiler(); +} + ShaderExecutable *Renderer9::loadExecutable(const void *function, size_t length, rx::ShaderType type, const std::vector &transformFeedbackVaryings, bool separatedOutputBuffers) @@ -3538,6 +2994,21 @@ TextureStorage *Renderer9::createTextureStorage2DArray(GLenum internalformat, bo return NULL; } +TextureImpl *Renderer9::createTexture(GLenum target) +{ + switch(target) + { + case GL_TEXTURE_2D: return new TextureD3D_2D(this); + case GL_TEXTURE_CUBE_MAP: return new TextureD3D_Cube(this); + case GL_TEXTURE_3D: return new TextureD3D_3D(this); + case GL_TEXTURE_2D_ARRAY: return new TextureD3D_2DArray(this); + default: + UNREACHABLE(); + } + + return NULL; +} + bool Renderer9::getLUID(LUID *adapterLuid) const { adapterLuid->HighPart = 0; @@ -3552,20 +3023,19 @@ bool Renderer9::getLUID(LUID *adapterLuid) const return false; } -GLenum Renderer9::getNativeTextureFormat(GLenum internalFormat) const -{ - return d3d9_gl::GetInternalFormat(gl_d3d9::GetTextureFormat(internalFormat, this)); -} - rx::VertexConversionType Renderer9::getVertexConversionType(const gl::VertexFormat &vertexFormat) const { - return d3d9::GetVertexConversionType(vertexFormat); + return d3d9::GetVertexFormatInfo(getCapsDeclTypes(), vertexFormat).conversionType; } GLenum Renderer9::getVertexComponentType(const gl::VertexFormat &vertexFormat) const { - D3DDECLTYPE declType = d3d9::GetNativeVertexFormat(vertexFormat); - return d3d9::GetDeclTypeComponentType(declType); + return d3d9::GetVertexFormatInfo(getCapsDeclTypes(), vertexFormat).componentType; +} + +void Renderer9::generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const +{ + d3d9_gl::GenerateCaps(mD3d9, mDevice, mDeviceType, mAdapter, outCaps, outTextureCaps, outExtensions); } } diff --git a/gfx/angle/src/libGLESv2/renderer/d3d9/Renderer9.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h similarity index 74% rename from gfx/angle/src/libGLESv2/renderer/d3d9/Renderer9.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h index 8f723e3c6c99..5858d2d28c44 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d9/Renderer9.h +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h @@ -12,14 +12,14 @@ #include "common/angleutils.h" #include "common/mathutil.h" #include "libGLESv2/renderer/d3d/HLSLCompiler.h" -#include "libGLESv2/renderer/d3d9/ShaderCache.h" -#include "libGLESv2/renderer/d3d9/VertexDeclarationCache.h" +#include "libGLESv2/renderer/d3d/d3d9/ShaderCache.h" +#include "libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h" #include "libGLESv2/renderer/Renderer.h" #include "libGLESv2/renderer/RenderTarget.h" namespace gl { -class Renderbuffer; +class FramebufferAttachment; } namespace rx @@ -33,7 +33,7 @@ class Blit9; class Renderer9 : public Renderer { public: - Renderer9(egl::Display *display, HDC hDc); + Renderer9(egl::Display *display, EGLNativeDisplayType hDc, EGLint requestedDisplay); virtual ~Renderer9(); static Renderer9 *makeRenderer9(Renderer *renderer); @@ -76,10 +76,11 @@ class Renderer9 : public Renderer bool ignoreViewport); virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer); - virtual void applyShaders(gl::ProgramBinary *programBinary, bool rasterizerDiscard, bool transformFeedbackActive, const gl::VertexFormat inputLayout[]); + virtual void applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, + bool rasterizerDiscard, bool transformFeedbackActive); virtual void applyUniforms(const gl::ProgramBinary &programBinary); virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount); - virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], gl::VertexAttribCurrentValueData currentValues[], + virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], const gl::VertexAttribCurrentValueData currentValues[], GLint first, GLsizei count, GLsizei instances); virtual GLenum applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo); @@ -99,77 +100,23 @@ class Renderer9 : public Renderer 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() const; - virtual bool getDXT3TextureSupport() const; - virtual bool getDXT5TextureSupport() const; - virtual bool getEventQuerySupport() const; - virtual bool getFloat32TextureSupport() const; - virtual bool getFloat32TextureFilteringSupport() const; - virtual bool getFloat32TextureRenderingSupport() const; - virtual bool getFloat16TextureSupport() const; - virtual bool getFloat16TextureFilteringSupport() const; - virtual bool getFloat16TextureRenderingSupport() const; - virtual bool getRGB565TextureSupport() const; - virtual bool getLuminanceTextureSupport() const; - virtual bool getLuminanceAlphaTextureSupport() const; - virtual bool getRGTextureSupport() const; - 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 unsigned int getMaxVertexShaderUniformBuffers() const; - virtual unsigned int getMaxFragmentShaderUniformBuffers() const; virtual unsigned int getReservedVertexUniformBuffers() const; virtual unsigned int getReservedFragmentUniformBuffers() const; - virtual unsigned int getMaxTransformFeedbackBuffers() const; - virtual unsigned int getMaxTransformFeedbackSeparateComponents() const; - virtual unsigned int getMaxTransformFeedbackInterleavedComponents() const; - virtual unsigned int getMaxUniformBufferSize() const; - virtual bool getNonPower2TextureSupport() const; - virtual bool getDepthTextureSupport() const; - virtual bool getOcclusionQuerySupport() const; - virtual bool getInstancingSupport() const; - virtual bool getTextureFilterAnisotropySupport() const; - virtual bool getPBOSupport() const; - virtual float getTextureMaxAnisotropy() const; virtual bool getShareHandleSupport() const; - virtual bool getDerivativeInstructionSupport() const; virtual bool getPostSubBufferSupport() const; - virtual int getMaxRecommendedElementsIndices() const; - virtual int getMaxRecommendedElementsVertices() const; virtual int getMajorShaderModel() const; - virtual float getMaxPointSize() const; - virtual int getMaxViewportDimension() const; - virtual int getMaxTextureWidth() const; - virtual int getMaxTextureHeight() const; - virtual int getMaxTextureDepth() const; - virtual int getMaxTextureArrayLayers() const; - virtual bool get32BitIndexSupport() const; DWORD getCapsDeclTypes() const; virtual int getMinSwapInterval() const; virtual int getMaxSwapInterval() const; - virtual GLsizei getMaxSupportedSamples() const; - virtual GLsizei getMaxSupportedFormatSamples(GLenum internalFormat) const; - virtual GLsizei getNumSampleCounts(GLenum internalFormat) const; - virtual void getSampleCounts(GLenum internalFormat, GLsizei bufSize, GLint *params) const; - int getNearestSupportedSamples(D3DFORMAT format, int requested) const; - - virtual unsigned int getMaxRenderTargets() const; - - D3DFORMAT ConvertTextureInternalFormat(GLenum internalformat); - // Pixel operations virtual bool copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source); virtual bool copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source); @@ -188,13 +135,17 @@ class Renderer9 : public Renderer virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter); virtual void readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, - GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, void* pixels); + GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels); // RenderTarget creation virtual RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth); virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples); + // Shader creation + virtual ShaderImpl *createShader(GLenum type); + // Shader operations + virtual void releaseShaderCompiler(); virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type, const std::vector &transformFeedbackVaryings, bool separatedOutputBuffers); @@ -212,15 +163,24 @@ class Renderer9 : public Renderer virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels); virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels); + // Texture creation + virtual TextureImpl *createTexture(GLenum target); + // Buffer creation + virtual BufferImpl *createBuffer(); virtual VertexBuffer *createVertexBuffer(); virtual IndexBuffer *createIndexBuffer(); - virtual BufferStorage *createBufferStorage(); + + // Vertex Array creation + virtual VertexArrayImpl *createVertexArray(); // Query and Fence creation virtual QueryImpl *createQuery(GLenum type); virtual FenceImpl *createFence(); + // Transform Feedback creation + virtual TransformFeedbackImpl* createTransformFeedback(); + // Buffer-to-texture and Texture-to-buffer copies virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const; virtual bool fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, @@ -232,14 +192,15 @@ class Renderer9 : public Renderer D3DPOOL getTexturePool(DWORD usage) const; virtual bool getLUID(LUID *adapterLuid) const; - virtual GLenum getNativeTextureFormat(GLenum internalFormat) const; virtual rx::VertexConversionType getVertexConversionType(const gl::VertexFormat &vertexFormat) const; virtual GLenum getVertexComponentType(const gl::VertexFormat &vertexFormat) const; private: DISALLOW_COPY_AND_ASSIGN(Renderer9); - void deinitialize(); + virtual void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const; + + void release(); void applyUniformnfv(gl::LinkedUniform *targetUniform, const GLfloat *v); void applyUniformniv(gl::LinkedUniform *targetUniform, const GLint *v); @@ -249,7 +210,7 @@ class Renderer9 : public Renderer void drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer); bool copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged); - gl::Renderbuffer *getNullColorbuffer(gl::Renderbuffer *depthbuffer); + gl::FramebufferAttachment *getNullColorbuffer(gl::FramebufferAttachment *depthbuffer); D3DPOOL getBufferPool(DWORD usage) const; @@ -286,47 +247,11 @@ class Renderer9 : public Renderer GLsizei mRepeatDraw; bool mSceneStarted; - bool mSupportsNonPower2Textures; - bool mSupportsTextureFilterAnisotropy; int mMinSwapInterval; int mMaxSwapInterval; - bool mOcclusionQuerySupport; - bool mEventQuerySupport; bool mVertexTextureSupport; - bool mDepthTextureSupport; - - bool mRGB565TextureSupport; - - bool mFloat32TextureSupport; - bool mFloat32FilterSupport; - bool mFloat32RenderSupport; - - bool mFloat16TextureSupport; - bool mFloat16FilterSupport; - bool mFloat16RenderSupport; - - bool mDXT1TextureSupport; - bool mDXT3TextureSupport; - bool mDXT5TextureSupport; - - bool mLuminanceTextureSupport; - bool mLuminanceAlphaTextureSupport; - - bool mRGTextureSupport; - - struct MultisampleSupportInfo - { - bool supportedSamples[D3DMULTISAMPLE_16_SAMPLES + 1]; - unsigned int maxSupportedSamples; - }; - typedef std::map MultisampleSupportMap; - MultisampleSupportMap mMultiSampleSupport; - unsigned int mMaxSupportedSamples; - - MultisampleSupportInfo getMultiSampleSupport(D3DFORMAT format); - // current render target states unsigned int mAppliedRenderTargetSerial; unsigned int mAppliedDepthbufferSerial; @@ -401,7 +326,7 @@ class Renderer9 : public Renderer UINT lruCount; int width; int height; - gl::Renderbuffer *buffer; + gl::FramebufferAttachment *buffer; } mNullColorbufferCache[NUM_NULL_COLORBUFFER_CACHE_ENTRIES]; UINT mMaxNullColorbufferLRU; diff --git a/gfx/angle/src/libGLESv2/renderer/d3d9/ShaderCache.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderCache.h similarity index 97% rename from gfx/angle/src/libGLESv2/renderer/d3d9/ShaderCache.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderCache.h index a03528c9b558..2ad302283984 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d9/ShaderCache.h +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderCache.h @@ -12,6 +12,10 @@ #include "common/debug.h" +#include +#include +#include + namespace rx { template diff --git a/gfx/angle/src/libGLESv2/renderer/d3d9/ShaderExecutable9.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.cpp similarity index 94% rename from gfx/angle/src/libGLESv2/renderer/d3d9/ShaderExecutable9.cpp rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.cpp index 115ed0823c7f..bc7120461b45 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d9/ShaderExecutable9.cpp +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.cpp @@ -1,4 +1,3 @@ -#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 @@ -8,7 +7,7 @@ // ShaderExecutable9.cpp: Implements a D3D9-specific class to contain shader // executable implementation details. -#include "libGLESv2/renderer/d3d9/ShaderExecutable9.h" +#include "libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.h" #include "common/debug.h" diff --git a/gfx/angle/src/libGLESv2/renderer/d3d9/ShaderExecutable9.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d9/ShaderExecutable9.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d9/SwapChain9.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp similarity index 92% rename from gfx/angle/src/libGLESv2/renderer/d3d9/SwapChain9.cpp rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp index bfb34594c52a..f702b794c1c9 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d9/SwapChain9.cpp +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp @@ -1,16 +1,15 @@ -#include "precompiled.h" // -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2012-2014 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/d3d9/SwapChain9.h" -#include "libGLESv2/renderer/d3d9/renderer9_utils.h" -#include "libGLESv2/renderer/d3d9/formatutils9.h" -#include "libGLESv2/renderer/d3d9/Renderer9.h" +#include "libGLESv2/renderer/d3d/d3d9/SwapChain9.h" +#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" +#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" +#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" namespace rx { @@ -50,7 +49,7 @@ void SwapChain9::release() static DWORD convertInterval(EGLint interval) { -#if ANGLE_FORCE_VSYNC_OFF +#ifdef ANGLE_FORCE_VSYNC_OFF return D3DPRESENT_INTERVAL_IMMEDIATE; #else switch(interval) @@ -101,9 +100,10 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI pShareHandle = &mShareHandle; } + const d3d9::TextureFormat &backBufferd3dFormatInfo = d3d9::GetTextureFormatInfo(mBackBufferFormat); result = device->CreateTexture(backbufferWidth, backbufferHeight, 1, D3DUSAGE_RENDERTARGET, - gl_d3d9::GetTextureFormat(mBackBufferFormat, mRenderer), - D3DPOOL_DEFAULT, &mOffscreenTexture, pShareHandle); + backBufferd3dFormatInfo.texFormat, D3DPOOL_DEFAULT, &mOffscreenTexture, + pShareHandle); if (FAILED(result)) { ERR("Could not create offscreen texture: %08lX", result); @@ -150,12 +150,14 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI SafeRelease(oldRenderTarget); } + const d3d9::TextureFormat &depthBufferd3dFormatInfo = d3d9::GetTextureFormatInfo(mDepthBufferFormat); + if (mWindow) { D3DPRESENT_PARAMETERS presentParameters = {0}; - presentParameters.AutoDepthStencilFormat = gl_d3d9::GetRenderFormat(mDepthBufferFormat, mRenderer); + presentParameters.AutoDepthStencilFormat = depthBufferd3dFormatInfo.renderFormat; presentParameters.BackBufferCount = 1; - presentParameters.BackBufferFormat = gl_d3d9::GetRenderFormat(mBackBufferFormat, mRenderer); + presentParameters.BackBufferFormat = backBufferd3dFormatInfo.renderFormat; presentParameters.EnableAutoDepthStencil = FALSE; presentParameters.Flags = 0; presentParameters.hDeviceWindow = mWindow; @@ -207,7 +209,7 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI if (mDepthBufferFormat != GL_NONE) { result = device->CreateDepthStencilSurface(backbufferWidth, backbufferHeight, - gl_d3d9::GetRenderFormat(mDepthBufferFormat, mRenderer), + depthBufferd3dFormatInfo.renderFormat, D3DMULTISAMPLE_NONE, 0, FALSE, &mDepthStencil, NULL); if (FAILED(result)) diff --git a/gfx/angle/src/libGLESv2/renderer/d3d9/SwapChain9.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d9/SwapChain9.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d9/TextureStorage9.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp similarity index 83% rename from gfx/angle/src/libGLESv2/renderer/d3d9/TextureStorage9.cpp rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp index a8efca7fb4ba..5b658235a011 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d9/TextureStorage9.cpp +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp @@ -1,6 +1,5 @@ -#include "precompiled.h" // -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2012-2014 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 +8,15 @@ // classes TextureStorage9_2D and TextureStorage9_Cube, which act as the interface to the // D3D9 texture. -#include "libGLESv2/main.h" -#include "libGLESv2/renderer/d3d9/Renderer9.h" -#include "libGLESv2/renderer/d3d9/TextureStorage9.h" -#include "libGLESv2/renderer/d3d9/SwapChain9.h" -#include "libGLESv2/renderer/d3d9/RenderTarget9.h" -#include "libGLESv2/renderer/d3d9/renderer9_utils.h" -#include "libGLESv2/renderer/d3d9/formatutils9.h" +#include "libGLESv2/renderer/d3d/d3d9/TextureStorage9.h" +#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" +#include "libGLESv2/renderer/d3d/d3d9/SwapChain9.h" +#include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h" +#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" +#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" +#include "libGLESv2/renderer/d3d/TextureD3D.h" #include "libGLESv2/Texture.h" +#include "libGLESv2/main.h" namespace rx { @@ -38,18 +38,17 @@ TextureStorage9 *TextureStorage9::makeTextureStorage9(TextureStorage *storage) return static_cast(storage); } -DWORD TextureStorage9::GetTextureUsage(GLenum internalformat, Renderer9 *renderer, bool renderTarget) +DWORD TextureStorage9::GetTextureUsage(GLenum internalformat, bool renderTarget) { - GLuint clientVersion = renderer->getCurrentClientVersion(); - DWORD d3dusage = 0; - if (gl::GetDepthBits(internalformat, clientVersion) > 0 || - gl::GetStencilBits(internalformat, clientVersion) > 0) + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat); + const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat); + if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) { d3dusage |= D3DUSAGE_DEPTHSTENCIL; } - else if (renderTarget && (gl_d3d9::GetRenderFormat(internalformat, renderer) != D3DFMT_UNKNOWN)) + else if (renderTarget && (d3dFormatInfo.renderFormat != D3DFMT_UNKNOWN)) { d3dusage |= D3DUSAGE_RENDERTARGET; } @@ -99,7 +98,7 @@ TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, SwapChain9 *swapchain } TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) - : TextureStorage9(renderer, GetTextureUsage(internalformat, Renderer9::makeRenderer9(renderer), renderTarget)) + : TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget)) { mTexture = NULL; mRenderTarget = NULL; @@ -108,11 +107,11 @@ TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, GLenum internalformat if (width > 0 && height > 0) { IDirect3DDevice9 *device = mRenderer->getDevice(); - D3DFORMAT format = gl_d3d9::GetTextureFormat(internalformat, mRenderer); - d3d9::MakeValidSize(false, format, &width, &height, &mTopLevel); + const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat); + d3d9::MakeValidSize(false, d3dFormatInfo.texFormat, &width, &height, &mTopLevel); UINT creationLevels = (levels == 0) ? 0 : mTopLevel + levels; - HRESULT result = device->CreateTexture(width, height, creationLevels, getUsage(), format, getPool(), &mTexture, NULL); + HRESULT result = device->CreateTexture(width, height, creationLevels, getUsage(), d3dFormatInfo.texFormat, getPool(), &mTexture, NULL); if (FAILED(result)) { @@ -195,7 +194,7 @@ void TextureStorage9_2D::initializeRenderTarget() } TextureStorage9_Cube::TextureStorage9_Cube(Renderer *renderer, GLenum internalformat, bool renderTarget, int size, int levels) - : TextureStorage9(renderer, GetTextureUsage(internalformat, Renderer9::makeRenderer9(renderer), renderTarget)) + : TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget)) { mTexture = NULL; for (int i = 0; i < 6; ++i) @@ -209,11 +208,11 @@ TextureStorage9_Cube::TextureStorage9_Cube(Renderer *renderer, GLenum internalfo { IDirect3DDevice9 *device = mRenderer->getDevice(); int height = size; - D3DFORMAT format = gl_d3d9::GetTextureFormat(internalformat, mRenderer); - d3d9::MakeValidSize(false, format, &size, &height, &mTopLevel); + const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat); + d3d9::MakeValidSize(false, d3dFormatInfo.texFormat, &size, &height, &mTopLevel); UINT creationLevels = (levels == 0) ? 0 : mTopLevel + levels; - HRESULT result = device->CreateCubeTexture(size, creationLevels, getUsage(), format, getPool(), &mTexture, NULL); + HRESULT result = device->CreateCubeTexture(size, creationLevels, getUsage(), d3dFormatInfo.texFormat, getPool(), &mTexture, NULL); if (FAILED(result)) { @@ -266,7 +265,7 @@ IDirect3DSurface9 *TextureStorage9_Cube::getCubeMapSurface(GLenum faceTarget, in RenderTarget *TextureStorage9_Cube::getRenderTargetFace(GLenum faceTarget, int level) { - return mRenderTarget[gl::TextureCubeMap::targetToIndex(faceTarget)]; + return mRenderTarget[gl::TextureCubeMap::targetToLayerIndex(faceTarget)]; } void TextureStorage9_Cube::generateMipmap(int faceIndex, int level) diff --git a/gfx/angle/src/libGLESv2/renderer/d3d9/TextureStorage9.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.h similarity index 95% rename from gfx/angle/src/libGLESv2/renderer/d3d9/TextureStorage9.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.h index 1f4975f48e5e..cc7c155d3458 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d9/TextureStorage9.h +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.h @@ -11,7 +11,7 @@ #ifndef LIBGLESV2_RENDERER_TEXTURESTORAGE9_H_ #define LIBGLESV2_RENDERER_TEXTURESTORAGE9_H_ -#include "libGLESv2/renderer/TextureStorage.h" +#include "libGLESv2/renderer/d3d/TextureStorage.h" #include "common/debug.h" namespace rx @@ -28,7 +28,7 @@ class TextureStorage9 : public TextureStorage static TextureStorage9 *makeTextureStorage9(TextureStorage *storage); - static DWORD GetTextureUsage(GLenum internalformat, Renderer9 *renderer, bool renderTarget); + static DWORD GetTextureUsage(GLenum internalformat, bool renderTarget); D3DPOOL getPool() const; DWORD getUsage() const; diff --git a/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/VertexArray9.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/VertexArray9.h new file mode 100644 index 000000000000..66a6c64d81c4 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/VertexArray9.h @@ -0,0 +1,43 @@ +// +// Copyright 2014 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. +// + +// VertexArray9.h: Defines the rx::VertexArray9 class which implements rx::VertexArrayImpl. + +#ifndef LIBGLESV2_RENDERER_VERTEXARRAY9_H_ +#define LIBGLESV2_RENDERER_VERTEXARRAY9_H_ + +#include "libGLESv2/renderer/VertexArrayImpl.h" +#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" + +namespace rx +{ +class Renderer9; + +class VertexArray9 : public VertexArrayImpl +{ + public: + VertexArray9(rx::Renderer9 *renderer) + : VertexArrayImpl(), + mRenderer(renderer) + { + } + + virtual ~VertexArray9() { } + + virtual void setElementArrayBuffer(const gl::Buffer *buffer) { } + virtual void setAttribute(size_t idx, const gl::VertexAttribute &attr) { } + virtual void setAttributeDivisor(size_t idx, GLuint divisor) { } + virtual void enableAttribute(size_t idx, bool enabledState) { } + + private: + DISALLOW_COPY_AND_ASSIGN(VertexArray9); + + rx::Renderer9 *mRenderer; +}; + +} + +#endif // LIBGLESV2_RENDERER_VERTEXARRAY9_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/d3d9/VertexBuffer9.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp similarity index 70% rename from gfx/angle/src/libGLESv2/renderer/d3d9/VertexBuffer9.cpp rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp index 42ddfcae1cb9..7a20db3d483d 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d9/VertexBuffer9.cpp +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp @@ -1,4 +1,3 @@ -#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,19 +6,18 @@ // VertexBuffer9.cpp: Defines the D3D9 VertexBuffer implementation. -#include "libGLESv2/renderer/d3d9/VertexBuffer9.h" +#include "libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h" +#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" +#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" #include "libGLESv2/renderer/vertexconversion.h" -#include "libGLESv2/renderer/BufferStorage.h" +#include "libGLESv2/renderer/BufferImpl.h" #include "libGLESv2/VertexAttribute.h" -#include "libGLESv2/renderer/d3d9/Renderer9.h" -#include "libGLESv2/renderer/d3d9/formatutils9.h" - #include "libGLESv2/Buffer.h" namespace rx { -VertexBuffer9::VertexBuffer9(rx::Renderer9 *const renderer) : mRenderer(renderer) +VertexBuffer9::VertexBuffer9(rx::Renderer9 *renderer) : mRenderer(renderer) { mVertexBuffer = NULL; mBufferSize = 0; @@ -70,14 +68,14 @@ bool VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, con { if (mVertexBuffer) { - gl::Buffer *buffer = attrib.mBoundBuffer.get(); + gl::Buffer *buffer = attrib.buffer.get(); - int inputStride = attrib.stride(); - int elementSize = attrib.typeSize(); + int inputStride = gl::ComputeVertexAttributeStride(attrib); + int elementSize = gl::ComputeVertexAttributeTypeSize(attrib); DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0; - void *mapPtr = NULL; + uint8_t *mapPtr = NULL; unsigned int mapSize; if (!spaceRequired(attrib, count, instances, &mapSize)) @@ -85,7 +83,7 @@ bool VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, con return false; } - HRESULT result = mVertexBuffer->Lock(offset, mapSize, &mapPtr, lockFlags); + HRESULT result = mVertexBuffer->Lock(offset, mapSize, reinterpret_cast(&mapPtr), lockFlags); if (FAILED(result)) { @@ -93,31 +91,32 @@ bool VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, con return false; } - const char *input = NULL; - if (attrib.mArrayEnabled) + const uint8_t *input = NULL; + if (attrib.enabled) { if (buffer) { - BufferStorage *storage = buffer->getStorage(); - input = static_cast(storage->getData()) + static_cast(attrib.mOffset); + BufferImpl *storage = buffer->getImplementation(); + input = static_cast(storage->getData()) + static_cast(attrib.offset); } else { - input = static_cast(attrib.mPointer); + input = static_cast(attrib.pointer); } } else { - input = reinterpret_cast(currentValue.FloatValues); + input = reinterpret_cast(currentValue.FloatValues); } - if (instances == 0 || attrib.mDivisor == 0) + if (instances == 0 || attrib.divisor == 0) { input += inputStride * start; } gl::VertexFormat vertexFormat(attrib, currentValue.Type); - bool needsConversion = (d3d9::GetVertexConversionType(vertexFormat) & VERTEX_CONVERT_CPU) > 0; + const d3d9::VertexFormat &d3dVertexInfo = d3d9::GetVertexFormatInfo(mRenderer->getCapsDeclTypes(), vertexFormat); + bool needsConversion = (d3dVertexInfo.conversionType & VERTEX_CONVERT_CPU) > 0; if (!needsConversion && inputStride == elementSize) { @@ -126,8 +125,7 @@ bool VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, con } else { - VertexCopyFunction copyFunction = d3d9::GetVertexCopyFunction(vertexFormat); - copyFunction(input, inputStride, count, mapPtr); + d3dVertexInfo.copyFunction(input, inputStride, count, mapPtr); } mVertexBuffer->Unlock(); @@ -200,36 +198,29 @@ IDirect3DVertexBuffer9 * VertexBuffer9::getBuffer() const } bool VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances, - unsigned int *outSpaceRequired) + unsigned int *outSpaceRequired) const { gl::VertexFormat vertexFormat(attrib, GL_FLOAT); - unsigned int elementSize = d3d9::GetVertexElementSize(vertexFormat); + const d3d9::VertexFormat &d3d9VertexInfo = d3d9::GetVertexFormatInfo(mRenderer->getCapsDeclTypes(), vertexFormat); - if (attrib.mArrayEnabled) + if (attrib.enabled) { unsigned int elementCount = 0; - if (instances == 0 || attrib.mDivisor == 0) + if (instances == 0 || attrib.divisor == 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; - } + // Round up to divisor, if possible + elementCount = rx::UnsignedCeilDivide(static_cast(instances), attrib.divisor); } - if (elementSize <= std::numeric_limits::max() / elementCount) + if (d3d9VertexInfo.outputElementSize <= std::numeric_limits::max() / elementCount) { if (outSpaceRequired) { - *outSpaceRequired = elementSize * elementCount; + *outSpaceRequired = d3d9VertexInfo.outputElementSize * elementCount; } return true; } diff --git a/gfx/angle/src/libGLESv2/renderer/d3d9/VertexBuffer9.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h similarity index 81% rename from gfx/angle/src/libGLESv2/renderer/d3d9/VertexBuffer9.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h index 2fb5a36b37bf..6bde0cdeb797 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d9/VertexBuffer9.h +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h @@ -9,7 +9,7 @@ #ifndef LIBGLESV2_RENDERER_VERTEXBUFFER9_H_ #define LIBGLESV2_RENDERER_VERTEXBUFFER9_H_ -#include "libGLESv2/renderer/VertexBuffer.h" +#include "libGLESv2/renderer/d3d/VertexBuffer.h" namespace rx { @@ -18,7 +18,7 @@ class Renderer9; class VertexBuffer9 : public VertexBuffer { public: - explicit VertexBuffer9(rx::Renderer9 *const renderer); + explicit VertexBuffer9(rx::Renderer9 *renderer); virtual ~VertexBuffer9(); virtual bool initialize(unsigned int size, bool dynamicUsage); @@ -39,14 +39,14 @@ class VertexBuffer9 : public VertexBuffer private: DISALLOW_COPY_AND_ASSIGN(VertexBuffer9); - rx::Renderer9 *const mRenderer; + rx::Renderer9 *mRenderer; IDirect3DVertexBuffer9 *mVertexBuffer; unsigned int mBufferSize; bool mDynamicUsage; - static bool spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances, - unsigned int *outSpaceRequired); + bool spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances, + unsigned int *outSpaceRequired) const; }; } diff --git a/gfx/angle/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.cpp similarity index 89% rename from gfx/angle/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.cpp rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.cpp index 30c023378a1c..4c8d6dfbefca 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.cpp +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.cpp @@ -1,4 +1,3 @@ -#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,11 +6,11 @@ // VertexDeclarationCache.cpp: Implements a helper class to construct and cache vertex declarations. +#include "libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h" +#include "libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h" +#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" #include "libGLESv2/ProgramBinary.h" #include "libGLESv2/VertexAttribute.h" -#include "libGLESv2/renderer/d3d9/VertexBuffer9.h" -#include "libGLESv2/renderer/d3d9/VertexDeclarationCache.h" -#include "libGLESv2/renderer/d3d9/formatutils9.h" namespace rx { @@ -48,6 +47,20 @@ GLenum VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, Transl int indexedAttribute = gl::MAX_VERTEX_ATTRIBS; int instancedAttribute = gl::MAX_VERTEX_ATTRIBS; + if (instances == 0) + { + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; ++i) + { + if (attributes[i].divisor != 0) + { + // If a divisor is set, it still applies even if an instanced draw was not used, so treat + // as a single-instance draw. + instances = 1; + break; + } + } + } + if (instances > 0) { // Find an indexed attribute to be mapped to D3D stream 0 @@ -74,6 +87,9 @@ GLenum VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, Transl } } + D3DCAPS9 caps; + device->GetDeviceCaps(&caps); + D3DVERTEXELEMENT9 elements[gl::MAX_VERTEX_ATTRIBS + 1]; D3DVERTEXELEMENT9 *element = &elements[0]; @@ -133,10 +149,11 @@ GLenum VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, Transl } gl::VertexFormat vertexFormat(*attributes[i].attribute, GL_FLOAT); + const d3d9::VertexFormat &d3d9VertexInfo = d3d9::GetVertexFormatInfo(caps.DeclTypes, vertexFormat); element->Stream = stream; element->Offset = 0; - element->Type = d3d9::GetNativeVertexFormat(vertexFormat); + element->Type = d3d9VertexInfo.nativeFormat; element->Method = D3DDECLMETHOD_DEFAULT; element->Usage = D3DDECLUSAGE_TEXCOORD; element->UsageIndex = programBinary->getSemanticIndex(i); diff --git a/gfx/angle/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h similarity index 96% rename from gfx/angle/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h index 3fc024a9bab4..004e28df4fb8 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.h +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h @@ -9,7 +9,7 @@ #ifndef LIBGLESV2_RENDERER_VERTEXDECLARATIONCACHE_H_ #define LIBGLESV2_RENDERER_VERTEXDECLARATIONCACHE_H_ -#include "libGLESv2/renderer/VertexDataManager.h" +#include "libGLESv2/renderer/d3d/VertexDataManager.h" namespace gl { diff --git a/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.cpp new file mode 100644 index 000000000000..1e78802f7928 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.cpp @@ -0,0 +1,579 @@ +// +// Copyright (c) 2013-2014 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. +// + +// formatutils9.cpp: Queries for GL image formats and their translations to D3D9 +// formats. + +#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" +#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" +#include "libGLESv2/renderer/generatemip.h" +#include "libGLESv2/renderer/loadimage.h" +#include "libGLESv2/renderer/copyimage.h" +#include "libGLESv2/renderer/vertexconversion.h" + +namespace rx +{ + +namespace d3d9 +{ + +const D3DFORMAT D3DFMT_INTZ = ((D3DFORMAT)(MAKEFOURCC('I', 'N', 'T', 'Z'))); +const D3DFORMAT D3DFMT_NULL = ((D3DFORMAT)(MAKEFOURCC('N', 'U', 'L', 'L'))); + +struct D3D9FastCopyFormat +{ + GLenum destFormat; + GLenum destType; + ColorCopyFunction copyFunction; + + D3D9FastCopyFormat(GLenum destFormat, GLenum destType, ColorCopyFunction copyFunction) + : destFormat(destFormat), destType(destType), copyFunction(copyFunction) + { } + + bool operator<(const D3D9FastCopyFormat& other) const + { + return memcmp(this, &other, sizeof(D3D9FastCopyFormat)) < 0; + } +}; + +typedef std::multimap D3D9FastCopyMap; + +static D3D9FastCopyMap BuildFastCopyMap() +{ + D3D9FastCopyMap map; + + map.insert(std::make_pair(D3DFMT_A8R8G8B8, D3D9FastCopyFormat(GL_RGBA, GL_UNSIGNED_BYTE, CopyBGRA8ToRGBA8))); + + return map; +} + +// A map to determine the pixel size and mip generation function of a given D3D format +typedef std::map D3D9FormatInfoMap; + +D3DFormat::D3DFormat() + : pixelBytes(0), + blockWidth(0), + blockHeight(0), + internalFormat(GL_NONE), + mipGenerationFunction(NULL), + colorReadFunction(NULL), + fastCopyFunctions() +{ +} + +ColorCopyFunction D3DFormat::getFastCopyFunction(GLenum format, GLenum type) const +{ + FastCopyFunctionMap::const_iterator iter = fastCopyFunctions.find(std::make_pair(format, type)); + return (iter != fastCopyFunctions.end()) ? iter->second : NULL; +} + +static inline void InsertD3DFormatInfo(D3D9FormatInfoMap *map, D3DFORMAT format, GLuint bits, GLuint blockWidth, + GLuint blockHeight, GLenum internalFormat, MipGenerationFunction mipFunc, + ColorReadFunction colorReadFunc) +{ + D3DFormat info; + info.pixelBytes = bits / 8; + info.blockWidth = blockWidth; + info.blockHeight = blockHeight; + info.internalFormat = internalFormat; + info.mipGenerationFunction = mipFunc; + info.colorReadFunction = colorReadFunc; + + static const D3D9FastCopyMap fastCopyMap = BuildFastCopyMap(); + std::pair fastCopyIter = fastCopyMap.equal_range(format); + for (D3D9FastCopyMap::const_iterator i = fastCopyIter.first; i != fastCopyIter.second; i++) + { + info.fastCopyFunctions.insert(std::make_pair(std::make_pair(i->second.destFormat, i->second.destType), i->second.copyFunction)); + } + + map->insert(std::make_pair(format, info)); +} + +static D3D9FormatInfoMap BuildD3D9FormatInfoMap() +{ + D3D9FormatInfoMap map; + + // | D3DFORMAT | S |W |H | Internal format | Mip generation function | Color read function | + InsertD3DFormatInfo(&map, D3DFMT_NULL, 0, 0, 0, GL_NONE, NULL, NULL ); + InsertD3DFormatInfo(&map, D3DFMT_UNKNOWN, 0, 0, 0, GL_NONE, NULL, NULL ); + + InsertD3DFormatInfo(&map, D3DFMT_L8, 8, 1, 1, GL_LUMINANCE8_EXT, GenerateMip, ReadColor ); + InsertD3DFormatInfo(&map, D3DFMT_A8, 8, 1, 1, GL_ALPHA8_EXT, GenerateMip, ReadColor ); + InsertD3DFormatInfo(&map, D3DFMT_A8L8, 16, 1, 1, GL_LUMINANCE8_ALPHA8_EXT, GenerateMip, ReadColor ); + InsertD3DFormatInfo(&map, D3DFMT_A4R4G4B4, 16, 1, 1, GL_BGRA4_ANGLEX, GenerateMip, ReadColor ); + InsertD3DFormatInfo(&map, D3DFMT_A1R5G5B5, 16, 1, 1, GL_BGR5_A1_ANGLEX, GenerateMip, ReadColor ); + InsertD3DFormatInfo(&map, D3DFMT_R5G6B5, 16, 1, 1, GL_RGB565, GenerateMip, ReadColor ); + InsertD3DFormatInfo(&map, D3DFMT_X8R8G8B8, 32, 1, 1, GL_BGRA8_EXT, GenerateMip, ReadColor ); + InsertD3DFormatInfo(&map, D3DFMT_A8R8G8B8, 32, 1, 1, GL_BGRA8_EXT, GenerateMip, ReadColor ); + InsertD3DFormatInfo(&map, D3DFMT_R16F, 16, 1, 1, GL_R16F_EXT, GenerateMip, ReadColor ); + InsertD3DFormatInfo(&map, D3DFMT_G16R16F, 32, 1, 1, GL_RG16F_EXT, GenerateMip, ReadColor ); + InsertD3DFormatInfo(&map, D3DFMT_A16B16G16R16F, 64, 1, 1, GL_RGBA16F_EXT, GenerateMip, ReadColor); + InsertD3DFormatInfo(&map, D3DFMT_R32F, 32, 1, 1, GL_R32F_EXT, GenerateMip, ReadColor ); + InsertD3DFormatInfo(&map, D3DFMT_G32R32F, 64, 1, 1, GL_RG32F_EXT, GenerateMip, ReadColor ); + InsertD3DFormatInfo(&map, D3DFMT_A32B32G32R32F, 128, 1, 1, GL_RGBA32F_EXT, GenerateMip, ReadColor); + + InsertD3DFormatInfo(&map, D3DFMT_D16, 16, 1, 1, GL_DEPTH_COMPONENT16, NULL, NULL ); + InsertD3DFormatInfo(&map, D3DFMT_D24S8, 32, 1, 1, GL_DEPTH24_STENCIL8_OES, NULL, NULL ); + InsertD3DFormatInfo(&map, D3DFMT_D24X8, 32, 1, 1, GL_DEPTH_COMPONENT16, NULL, NULL ); + InsertD3DFormatInfo(&map, D3DFMT_D32, 32, 1, 1, GL_DEPTH_COMPONENT32_OES, NULL, NULL ); + + InsertD3DFormatInfo(&map, D3DFMT_INTZ, 32, 1, 1, GL_DEPTH24_STENCIL8_OES, NULL, NULL ); + + InsertD3DFormatInfo(&map, D3DFMT_DXT1, 64, 4, 4, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, NULL, NULL ); + InsertD3DFormatInfo(&map, D3DFMT_DXT3, 128, 4, 4, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, NULL, NULL ); + InsertD3DFormatInfo(&map, D3DFMT_DXT5, 128, 4, 4, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, NULL, NULL ); + + return map; +} + +const D3DFormat &GetD3DFormatInfo(D3DFORMAT format) +{ + static const D3D9FormatInfoMap infoMap = BuildD3D9FormatInfoMap(); + D3D9FormatInfoMap::const_iterator iter = infoMap.find(format); + if (iter != infoMap.end()) + { + return iter->second; + } + else + { + static const D3DFormat defaultInfo; + return defaultInfo; + } +} + + + +typedef std::pair InternalFormatInitialzerPair; +typedef std::map InternalFormatInitialzerMap; + +static InternalFormatInitialzerMap BuildInternalFormatInitialzerMap() +{ + InternalFormatInitialzerMap map; + + map.insert(InternalFormatInitialzerPair(GL_RGB16F, Initialize4ComponentData)); + map.insert(InternalFormatInitialzerPair(GL_RGB32F, Initialize4ComponentData)); + + return map; +} + +// Each GL internal format corresponds to one D3D format and data loading function. +// Due to not all formats being available all the time, some of the function/format types are wrapped +// in templates that perform format support queries on a Renderer9 object which is supplied +// when requesting the function or format. + +typedef bool(*FallbackPredicateFunction)(); + +template +static void FallbackLoad(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + if (pred()) + { + prefered(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch); + } + else + { + fallback(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch); + } +} + +static void UnreachableLoad(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + UNREACHABLE(); +} + +typedef std::pair D3D9FormatPair; +typedef std::map D3D9FormatMap; + +TextureFormat::TextureFormat() + : texFormat(D3DFMT_NULL), + renderFormat(D3DFMT_NULL), + dataInitializerFunction(NULL), + loadFunction(UnreachableLoad) +{ +} + +static inline void InsertD3D9FormatInfo(D3D9FormatMap *map, GLenum internalFormat, D3DFORMAT texFormat, + D3DFORMAT renderFormat, LoadImageFunction loadFunction) +{ + TextureFormat info; + info.texFormat = texFormat; + info.renderFormat = renderFormat; + + static const InternalFormatInitialzerMap dataInitializationMap = BuildInternalFormatInitialzerMap(); + InternalFormatInitialzerMap::const_iterator dataInitIter = dataInitializationMap.find(internalFormat); + info.dataInitializerFunction = (dataInitIter != dataInitializationMap.end()) ? dataInitIter->second : NULL; + + info.loadFunction = loadFunction; + + map->insert(std::make_pair(internalFormat, info)); +} + +static D3D9FormatMap BuildD3D9FormatMap() +{ + D3D9FormatMap map; + + // | Internal format | Texture format | Render format | Load function | + InsertD3D9FormatInfo(&map, GL_NONE, D3DFMT_NULL, D3DFMT_NULL, UnreachableLoad ); + + InsertD3D9FormatInfo(&map, GL_DEPTH_COMPONENT16, D3DFMT_INTZ, D3DFMT_D24S8, UnreachableLoad ); + InsertD3D9FormatInfo(&map, GL_DEPTH_COMPONENT32_OES, D3DFMT_INTZ, D3DFMT_D32, UnreachableLoad ); + InsertD3D9FormatInfo(&map, GL_DEPTH24_STENCIL8_OES, D3DFMT_INTZ, D3DFMT_D24S8, UnreachableLoad ); + InsertD3D9FormatInfo(&map, GL_STENCIL_INDEX8, D3DFMT_UNKNOWN, D3DFMT_D24S8, UnreachableLoad ); // TODO: What's the texture format? + + InsertD3D9FormatInfo(&map, GL_RGBA32F_EXT, D3DFMT_A32B32G32R32F, D3DFMT_A32B32G32R32F, LoadToNative ); + InsertD3D9FormatInfo(&map, GL_RGB32F_EXT, D3DFMT_A32B32G32R32F, D3DFMT_A32B32G32R32F, LoadToNative3To4); + InsertD3D9FormatInfo(&map, GL_RG32F_EXT, D3DFMT_G32R32F, D3DFMT_G32R32F, LoadToNative ); + InsertD3D9FormatInfo(&map, GL_R32F_EXT, D3DFMT_R32F, D3DFMT_R32F, LoadToNative ); + InsertD3D9FormatInfo(&map, GL_ALPHA32F_EXT, D3DFMT_A32B32G32R32F, D3DFMT_UNKNOWN, LoadA32FToRGBA32F ); + InsertD3D9FormatInfo(&map, GL_LUMINANCE32F_EXT, D3DFMT_A32B32G32R32F, D3DFMT_UNKNOWN, LoadL32FToRGBA32F ); + InsertD3D9FormatInfo(&map, GL_LUMINANCE_ALPHA32F_EXT, D3DFMT_A32B32G32R32F, D3DFMT_UNKNOWN, LoadLA32FToRGBA32F ); + + InsertD3D9FormatInfo(&map, GL_RGBA16F_EXT, D3DFMT_A16B16G16R16F, D3DFMT_A16B16G16R16F, LoadToNative ); + InsertD3D9FormatInfo(&map, GL_RGB16F_EXT, D3DFMT_A16B16G16R16F, D3DFMT_A16B16G16R16F, LoadToNative3To4 ); + InsertD3D9FormatInfo(&map, GL_RG16F_EXT, D3DFMT_G16R16F, D3DFMT_G16R16F, LoadToNative ); + InsertD3D9FormatInfo(&map, GL_R16F_EXT, D3DFMT_R16F, D3DFMT_R16F, LoadToNative ); + InsertD3D9FormatInfo(&map, GL_ALPHA16F_EXT, D3DFMT_A16B16G16R16F, D3DFMT_UNKNOWN, LoadA16FToRGBA16F ); + InsertD3D9FormatInfo(&map, GL_LUMINANCE16F_EXT, D3DFMT_A16B16G16R16F, D3DFMT_UNKNOWN, LoadL16FToRGBA16F ); + InsertD3D9FormatInfo(&map, GL_LUMINANCE_ALPHA16F_EXT, D3DFMT_A16B16G16R16F, D3DFMT_UNKNOWN, LoadLA16FToRGBA16F ); + + InsertD3D9FormatInfo(&map, GL_ALPHA8_EXT, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FallbackLoad); + + InsertD3D9FormatInfo(&map, GL_RGB8_OES, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadRGB8ToBGRX8 ); + InsertD3D9FormatInfo(&map, GL_RGB565, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadR5G6B5ToBGRA8 ); + InsertD3D9FormatInfo(&map, GL_RGBA8_OES, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FallbackLoad); + InsertD3D9FormatInfo(&map, GL_RGBA4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadRGBA4ToBGRA8 ); + InsertD3D9FormatInfo(&map, GL_RGB5_A1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadRGB5A1ToBGRA8 ); + InsertD3D9FormatInfo(&map, GL_R8_EXT, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadR8ToBGRX8 ); + InsertD3D9FormatInfo(&map, GL_RG8_EXT, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadRG8ToBGRX8 ); + + InsertD3D9FormatInfo(&map, GL_BGRA8_EXT, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadToNative ); + InsertD3D9FormatInfo(&map, GL_BGRA4_ANGLEX, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadBGRA4ToBGRA8 ); + InsertD3D9FormatInfo(&map, GL_BGR5_A1_ANGLEX, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadBGR5A1ToBGRA8 ); + + InsertD3D9FormatInfo(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, D3DFMT_DXT1, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 8> ); + InsertD3D9FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, D3DFMT_DXT1, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 8> ); + InsertD3D9FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, D3DFMT_DXT3, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 16> ); + InsertD3D9FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, D3DFMT_DXT5, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 16> ); + + // These formats require checking if the renderer supports D3DFMT_L8 or D3DFMT_A8L8 and + // then changing the format and loading function appropriately. + InsertD3D9FormatInfo(&map, GL_LUMINANCE8_EXT, D3DFMT_L8, D3DFMT_L8, LoadToNative ); + InsertD3D9FormatInfo(&map, GL_LUMINANCE8_ALPHA8_EXT, D3DFMT_A8L8, D3DFMT_A8L8, LoadToNative ); + + return map; +} + +const TextureFormat &GetTextureFormatInfo(GLenum internalFormat) +{ + static const D3D9FormatMap formatMap = BuildD3D9FormatMap(); + D3D9FormatMap::const_iterator iter = formatMap.find(internalFormat); + if (iter != formatMap.end()) + { + return iter->second; + } + else + { + static const TextureFormat defaultInfo; + return defaultInfo; + } +} + +static GLenum GetDeclTypeComponentType(D3DDECLTYPE declType) +{ + switch (declType) + { + case D3DDECLTYPE_FLOAT1: return GL_FLOAT; + case D3DDECLTYPE_FLOAT2: return GL_FLOAT; + case D3DDECLTYPE_FLOAT3: return GL_FLOAT; + case D3DDECLTYPE_FLOAT4: return GL_FLOAT; + case D3DDECLTYPE_UBYTE4: return GL_UNSIGNED_INT; + case D3DDECLTYPE_SHORT2: return GL_INT; + case D3DDECLTYPE_SHORT4: return GL_INT; + case D3DDECLTYPE_UBYTE4N: return GL_UNSIGNED_NORMALIZED; + case D3DDECLTYPE_SHORT4N: return GL_SIGNED_NORMALIZED; + case D3DDECLTYPE_USHORT4N: return GL_UNSIGNED_NORMALIZED; + case D3DDECLTYPE_SHORT2N: return GL_SIGNED_NORMALIZED; + case D3DDECLTYPE_USHORT2N: return GL_UNSIGNED_NORMALIZED; + default: UNREACHABLE(); return GL_NONE; + } +} + +// Attribute format conversion +enum { NUM_GL_VERTEX_ATTRIB_TYPES = 6 }; + +struct TranslationDescription +{ + DWORD capsFlag; + VertexFormat preferredConversion; + VertexFormat fallbackConversion; +}; + +// 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 }; +}; + +VertexFormat::VertexFormat() + : conversionType(VERTEX_CONVERT_NONE), + outputElementSize(0), + copyFunction(NULL), + nativeFormat(D3DDECLTYPE_UNUSED), + componentType(GL_NONE) +{ +} + +// Initialize a TranslationInfo +VertexFormat CreateVertexFormatInfo(bool identity, size_t elementSize, VertexCopyFunction copyFunc, D3DDECLTYPE nativeFormat) +{ + VertexFormat formatInfo; + formatInfo.conversionType = identity ? VERTEX_CONVERT_NONE : VERTEX_CONVERT_CPU; + formatInfo.outputElementSize = elementSize; + formatInfo.copyFunction = copyFunc; + formatInfo.nativeFormat = nativeFormat; + formatInfo.componentType = GetDeclTypeComponentType(nativeFormat); + return formatInfo; +} + +#define TRANSLATION(type, norm, size, preferred) \ + CreateVertexFormatInfo \ + ( \ + 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) }, \ + } + +static inline unsigned int ComputeTypeIndex(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 VertexFormat &GetVertexFormatInfo(DWORD supportedDeclTypes, const gl::VertexFormat &vertexFormat) +{ + static bool initialized = false; + static DWORD intializedDeclTypes = 0; + static VertexFormat formatConverters[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; + if (!initialized) + { + const TranslationDescription translations[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) + }; + 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 (translations[i][j][k].capsFlag == 0 || (supportedDeclTypes & translations[i][j][k].capsFlag) != 0) + { + formatConverters[i][j][k] = translations[i][j][k].preferredConversion; + } + else + { + formatConverters[i][j][k] = translations[i][j][k].fallbackConversion; + } + } + } + } + initialized = true; + intializedDeclTypes = supportedDeclTypes; + } + + ASSERT(intializedDeclTypes == supportedDeclTypes); + + // Pure integer attributes only supported in ES3.0 + ASSERT(!vertexFormat.mPureInteger); + return formatConverters[ComputeTypeIndex(vertexFormat.mType)][vertexFormat.mNormalized][vertexFormat.mComponents - 1]; +} + +} + +} diff --git a/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.cpp.orig b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.cpp.orig new file mode 100644 index 000000000000..d97f8fbcf999 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.cpp.orig @@ -0,0 +1,629 @@ +// +// Copyright (c) 2013-2014 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. +// + +// formatutils9.cpp: Queries for GL image formats and their translations to D3D9 +// formats. + +#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" +#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" +#include "libGLESv2/renderer/generatemip.h" +#include "libGLESv2/renderer/loadimage.h" +#include "libGLESv2/renderer/copyimage.h" +#include "libGLESv2/renderer/vertexconversion.h" + +namespace rx +{ + +namespace d3d9 +{ + +const D3DFORMAT D3DFMT_INTZ = ((D3DFORMAT)(MAKEFOURCC('I', 'N', 'T', 'Z'))); +const D3DFORMAT D3DFMT_NULL = ((D3DFORMAT)(MAKEFOURCC('N', 'U', 'L', 'L'))); + +struct D3D9FastCopyFormat +{ + GLenum destFormat; + GLenum destType; + ColorCopyFunction copyFunction; + + D3D9FastCopyFormat(GLenum destFormat, GLenum destType, ColorCopyFunction copyFunction) + : destFormat(destFormat), destType(destType), copyFunction(copyFunction) + { } + + bool operator<(const D3D9FastCopyFormat& other) const + { + return memcmp(this, &other, sizeof(D3D9FastCopyFormat)) < 0; + } +}; + +typedef std::multimap D3D9FastCopyMap; + +static D3D9FastCopyMap BuildFastCopyMap() +{ + D3D9FastCopyMap map; + +<<<<<<< HEAD + map.insert(std::make_pair(D3DFMT_A8R8G8B8, D3D9FastCopyFormat(GL_RGBA, GL_UNSIGNED_BYTE, CopyBGRA8ToRGBA8))); +======= + // | Internal format | Texture format | Render format | Load function | + map.insert(D3D9FormatPair(GL_NONE, D3D9FormatInfo(D3DFMT_NULL, D3DFMT_NULL, UnreachableLoad ))); + + map.insert(D3D9FormatPair(GL_DEPTH_COMPONENT16, D3D9FormatInfo(D3DFMT_INTZ, D3DFMT_D24S8, UnreachableLoad ))); + map.insert(D3D9FormatPair(GL_DEPTH_COMPONENT32_OES, D3D9FormatInfo(D3DFMT_INTZ, D3DFMT_D32, UnreachableLoad ))); + map.insert(D3D9FormatPair(GL_DEPTH24_STENCIL8_OES, D3D9FormatInfo(D3DFMT_INTZ, D3DFMT_D24S8, UnreachableLoad ))); + map.insert(D3D9FormatPair(GL_STENCIL_INDEX8, D3D9FormatInfo(D3DFMT_UNKNOWN, D3DFMT_D24S8, UnreachableLoad ))); // TODO: What's the texture format? + + map.insert(D3D9FormatPair(GL_RGBA32F_EXT, D3D9FormatInfo(D3DFMT_A32B32G32R32F, D3DFMT_A32B32G32R32F, loadToNative ))); + map.insert(D3D9FormatPair(GL_RGB32F_EXT, D3D9FormatInfo(D3DFMT_A32B32G32R32F, D3DFMT_A32B32G32R32F, loadToNative3To4))); + map.insert(D3D9FormatPair(GL_RG32F_EXT, D3D9FormatInfo(D3DFMT_G32R32F, D3DFMT_G32R32F, loadToNative ))); + map.insert(D3D9FormatPair(GL_R32F_EXT, D3D9FormatInfo(D3DFMT_R32F, D3DFMT_R32F, loadToNative ))); + map.insert(D3D9FormatPair(GL_ALPHA32F_EXT, D3D9FormatInfo(D3DFMT_A32B32G32R32F, D3DFMT_UNKNOWN, loadAlphaFloatDataToRGBA ))); + map.insert(D3D9FormatPair(GL_LUMINANCE32F_EXT, D3D9FormatInfo(D3DFMT_A32B32G32R32F, D3DFMT_UNKNOWN, loadLuminanceFloatDataToRGBA ))); + map.insert(D3D9FormatPair(GL_LUMINANCE_ALPHA32F_EXT, D3D9FormatInfo(D3DFMT_A32B32G32R32F, D3DFMT_UNKNOWN, loadLuminanceAlphaFloatDataToRGBA ))); + + map.insert(D3D9FormatPair(GL_RGBA16F_EXT, D3D9FormatInfo(D3DFMT_A16B16G16R16F, D3DFMT_A16B16G16R16F, loadToNative ))); + map.insert(D3D9FormatPair(GL_RGB16F_EXT, D3D9FormatInfo(D3DFMT_A16B16G16R16F, D3DFMT_A16B16G16R16F, loadToNative3To4 ))); + map.insert(D3D9FormatPair(GL_RG16F_EXT, D3D9FormatInfo(D3DFMT_G16R16F, D3DFMT_G16R16F, loadToNative ))); + map.insert(D3D9FormatPair(GL_R16F_EXT, D3D9FormatInfo(D3DFMT_R16F, D3DFMT_R16F, loadToNative ))); + map.insert(D3D9FormatPair(GL_ALPHA16F_EXT, D3D9FormatInfo(D3DFMT_A16B16G16R16F, D3DFMT_UNKNOWN, loadAlphaHalfFloatDataToRGBA ))); + map.insert(D3D9FormatPair(GL_LUMINANCE16F_EXT, D3D9FormatInfo(D3DFMT_A16B16G16R16F, D3DFMT_UNKNOWN, loadLuminanceHalfFloatDataToRGBA ))); + map.insert(D3D9FormatPair(GL_LUMINANCE_ALPHA16F_EXT, D3D9FormatInfo(D3DFMT_A16B16G16R16F, D3DFMT_UNKNOWN, loadLuminanceAlphaHalfFloatDataToRGBA ))); + + map.insert(D3D9FormatPair(GL_ALPHA8_EXT, D3D9FormatInfo(D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FallbackLoad))); + + map.insert(D3D9FormatPair(GL_RGB8_OES, D3D9FormatInfo(D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, loadRGBUByteDataToBGRX ))); + map.insert(D3D9FormatPair(GL_RGB565, D3D9FormatInfo(D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, loadRGB565DataToBGRA ))); + map.insert(D3D9FormatPair(GL_RGBA8_OES, D3D9FormatInfo(D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FallbackLoad))); + map.insert(D3D9FormatPair(GL_RGBA4, D3D9FormatInfo(D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, loadRGBA4444DataToBGRA ))); + map.insert(D3D9FormatPair(GL_RGB5_A1, D3D9FormatInfo(D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, loadRGBA5551DataToBGRA ))); + map.insert(D3D9FormatPair(GL_R8_EXT, D3D9FormatInfo(D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, loadRUByteDataToBGRX ))); + map.insert(D3D9FormatPair(GL_RG8_EXT, D3D9FormatInfo(D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, loadRGUByteDataToBGRX ))); + + map.insert(D3D9FormatPair(GL_BGRA8_EXT, D3D9FormatInfo(D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, loadToNative ))); + map.insert(D3D9FormatPair(GL_BGRA4_ANGLEX, D3D9FormatInfo(D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, loadRGBA4444DataToRGBA ))); + map.insert(D3D9FormatPair(GL_BGR5_A1_ANGLEX, D3D9FormatInfo(D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, loadRGBA5551DataToRGBA ))); + + map.insert(D3D9FormatPair(GL_COMPRESSED_RGB_S3TC_DXT1_EXT, D3D9FormatInfo(D3DFMT_DXT1, D3DFMT_UNKNOWN, loadCompressedBlockDataToNative<4, 4, 8> ))); + map.insert(D3D9FormatPair(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, D3D9FormatInfo(D3DFMT_DXT1, D3DFMT_UNKNOWN, loadCompressedBlockDataToNative<4, 4, 8> ))); + map.insert(D3D9FormatPair(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, D3D9FormatInfo(D3DFMT_DXT3, D3DFMT_UNKNOWN, loadCompressedBlockDataToNative<4, 4, 16> ))); + map.insert(D3D9FormatPair(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, D3D9FormatInfo(D3DFMT_DXT5, D3DFMT_UNKNOWN, loadCompressedBlockDataToNative<4, 4, 16> ))); + + // These formats require checking if the renderer supports D3DFMT_L8 or D3DFMT_A8L8 and + // then changing the format and loading function appropriately. + map.insert(D3D9FormatPair(GL_LUMINANCE8_EXT, D3D9FormatInfo(D3DFMT_L8, D3DFMT_L8, loadToNative ))); + map.insert(D3D9FormatPair(GL_LUMINANCE8_ALPHA8_EXT, D3D9FormatInfo(D3DFMT_A8L8, D3DFMT_A8L8, loadToNative ))); +>>>>>>> 20c20e0... Fix for Windows XP conformance crash + + return map; +} + +// A map to determine the pixel size and mip generation function of a given D3D format +typedef std::map D3D9FormatInfoMap; + +D3DFormat::D3DFormat() + : pixelBytes(0), + blockWidth(0), + blockHeight(0), + internalFormat(GL_NONE), + mipGenerationFunction(NULL), + colorReadFunction(NULL), + fastCopyFunctions() +{ +} + +ColorCopyFunction D3DFormat::getFastCopyFunction(GLenum format, GLenum type) const +{ + FastCopyFunctionMap::const_iterator iter = fastCopyFunctions.find(std::make_pair(format, type)); + return (iter != fastCopyFunctions.end()) ? iter->second : NULL; +} + +static inline void InsertD3DFormatInfo(D3D9FormatInfoMap *map, D3DFORMAT format, GLuint bits, GLuint blockWidth, + GLuint blockHeight, GLenum internalFormat, MipGenerationFunction mipFunc, + ColorReadFunction colorReadFunc) +{ + D3DFormat info; + info.pixelBytes = bits / 8; + info.blockWidth = blockWidth; + info.blockHeight = blockHeight; + info.internalFormat = internalFormat; + info.mipGenerationFunction = mipFunc; + info.colorReadFunction = colorReadFunc; + + static const D3D9FastCopyMap fastCopyMap = BuildFastCopyMap(); + std::pair fastCopyIter = fastCopyMap.equal_range(format); + for (D3D9FastCopyMap::const_iterator i = fastCopyIter.first; i != fastCopyIter.second; i++) + { + info.fastCopyFunctions.insert(std::make_pair(std::make_pair(i->second.destFormat, i->second.destType), i->second.copyFunction)); + } + + map->insert(std::make_pair(format, info)); +} + +static D3D9FormatInfoMap BuildD3D9FormatInfoMap() +{ + D3D9FormatInfoMap map; + + // | D3DFORMAT | S |W |H | Internal format | Mip generation function | Color read function | + InsertD3DFormatInfo(&map, D3DFMT_NULL, 0, 0, 0, GL_NONE, NULL, NULL ); + InsertD3DFormatInfo(&map, D3DFMT_UNKNOWN, 0, 0, 0, GL_NONE, NULL, NULL ); + + InsertD3DFormatInfo(&map, D3DFMT_L8, 8, 1, 1, GL_LUMINANCE8_EXT, GenerateMip, ReadColor ); + InsertD3DFormatInfo(&map, D3DFMT_A8, 8, 1, 1, GL_ALPHA8_EXT, GenerateMip, ReadColor ); + InsertD3DFormatInfo(&map, D3DFMT_A8L8, 16, 1, 1, GL_LUMINANCE8_ALPHA8_EXT, GenerateMip, ReadColor ); + InsertD3DFormatInfo(&map, D3DFMT_A4R4G4B4, 16, 1, 1, GL_BGRA4_ANGLEX, GenerateMip, ReadColor ); + InsertD3DFormatInfo(&map, D3DFMT_A1R5G5B5, 16, 1, 1, GL_BGR5_A1_ANGLEX, GenerateMip, ReadColor ); + InsertD3DFormatInfo(&map, D3DFMT_R5G6B5, 16, 1, 1, GL_RGB565, GenerateMip, ReadColor ); + InsertD3DFormatInfo(&map, D3DFMT_X8R8G8B8, 32, 1, 1, GL_BGRA8_EXT, GenerateMip, ReadColor ); + InsertD3DFormatInfo(&map, D3DFMT_A8R8G8B8, 32, 1, 1, GL_BGRA8_EXT, GenerateMip, ReadColor ); + InsertD3DFormatInfo(&map, D3DFMT_R16F, 16, 1, 1, GL_R16F_EXT, GenerateMip, ReadColor ); + InsertD3DFormatInfo(&map, D3DFMT_G16R16F, 32, 1, 1, GL_RG16F_EXT, GenerateMip, ReadColor ); + InsertD3DFormatInfo(&map, D3DFMT_A16B16G16R16F, 64, 1, 1, GL_RGBA16F_EXT, GenerateMip, ReadColor); + InsertD3DFormatInfo(&map, D3DFMT_R32F, 32, 1, 1, GL_R32F_EXT, GenerateMip, ReadColor ); + InsertD3DFormatInfo(&map, D3DFMT_G32R32F, 64, 1, 1, GL_RG32F_EXT, GenerateMip, ReadColor ); + InsertD3DFormatInfo(&map, D3DFMT_A32B32G32R32F, 128, 1, 1, GL_RGBA32F_EXT, GenerateMip, ReadColor); + + InsertD3DFormatInfo(&map, D3DFMT_D16, 16, 1, 1, GL_DEPTH_COMPONENT16, NULL, NULL ); + InsertD3DFormatInfo(&map, D3DFMT_D24S8, 32, 1, 1, GL_DEPTH24_STENCIL8_OES, NULL, NULL ); + InsertD3DFormatInfo(&map, D3DFMT_D24X8, 32, 1, 1, GL_DEPTH_COMPONENT16, NULL, NULL ); + InsertD3DFormatInfo(&map, D3DFMT_D32, 32, 1, 1, GL_DEPTH_COMPONENT32_OES, NULL, NULL ); + + InsertD3DFormatInfo(&map, D3DFMT_INTZ, 32, 1, 1, GL_DEPTH24_STENCIL8_OES, NULL, NULL ); + + InsertD3DFormatInfo(&map, D3DFMT_DXT1, 64, 4, 4, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, NULL, NULL ); + InsertD3DFormatInfo(&map, D3DFMT_DXT3, 128, 4, 4, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, NULL, NULL ); + InsertD3DFormatInfo(&map, D3DFMT_DXT5, 128, 4, 4, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, NULL, NULL ); + + return map; +} + +const D3DFormat &GetD3DFormatInfo(D3DFORMAT format) +{ + static const D3D9FormatInfoMap infoMap = BuildD3D9FormatInfoMap(); + D3D9FormatInfoMap::const_iterator iter = infoMap.find(format); + if (iter != infoMap.end()) + { + return iter->second; + } + else + { + static const D3DFormat defaultInfo; + return defaultInfo; + } +} + + + +typedef std::pair InternalFormatInitialzerPair; +typedef std::map InternalFormatInitialzerMap; + +static InternalFormatInitialzerMap BuildInternalFormatInitialzerMap() +{ + InternalFormatInitialzerMap map; + + map.insert(InternalFormatInitialzerPair(GL_RGB16F, Initialize4ComponentData)); + map.insert(InternalFormatInitialzerPair(GL_RGB32F, Initialize4ComponentData)); + + return map; +} + +// Each GL internal format corresponds to one D3D format and data loading function. +// Due to not all formats being available all the time, some of the function/format types are wrapped +// in templates that perform format support queries on a Renderer9 object which is supplied +// when requesting the function or format. + +typedef bool(*FallbackPredicateFunction)(); + +template +static void FallbackLoad(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + if (pred()) + { + prefered(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch); + } + else + { + fallback(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch); + } +} + +static void UnreachableLoad(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + UNREACHABLE(); +} + +typedef std::pair D3D9FormatPair; +typedef std::map D3D9FormatMap; + +TextureFormat::TextureFormat() + : texFormat(D3DFMT_NULL), + renderFormat(D3DFMT_NULL), + dataInitializerFunction(NULL), + loadFunction(UnreachableLoad) +{ +} + +static inline void InsertD3D9FormatInfo(D3D9FormatMap *map, GLenum internalFormat, D3DFORMAT texFormat, + D3DFORMAT renderFormat, LoadImageFunction loadFunction) +{ + TextureFormat info; + info.texFormat = texFormat; + info.renderFormat = renderFormat; + + static const InternalFormatInitialzerMap dataInitializationMap = BuildInternalFormatInitialzerMap(); + InternalFormatInitialzerMap::const_iterator dataInitIter = dataInitializationMap.find(internalFormat); + info.dataInitializerFunction = (dataInitIter != dataInitializationMap.end()) ? dataInitIter->second : NULL; + + info.loadFunction = loadFunction; + + map->insert(std::make_pair(internalFormat, info)); +} + +static D3D9FormatMap BuildD3D9FormatMap() +{ + D3D9FormatMap map; + + // | Internal format | Texture format | Render format | Load function | + InsertD3D9FormatInfo(&map, GL_NONE, D3DFMT_NULL, D3DFMT_NULL, UnreachableLoad ); + + InsertD3D9FormatInfo(&map, GL_DEPTH_COMPONENT16, D3DFMT_INTZ, D3DFMT_D24S8, UnreachableLoad ); + InsertD3D9FormatInfo(&map, GL_DEPTH_COMPONENT32_OES, D3DFMT_INTZ, D3DFMT_D32, UnreachableLoad ); + InsertD3D9FormatInfo(&map, GL_DEPTH24_STENCIL8_OES, D3DFMT_INTZ, D3DFMT_D24S8, UnreachableLoad ); + InsertD3D9FormatInfo(&map, GL_STENCIL_INDEX8, D3DFMT_UNKNOWN, D3DFMT_D24S8, UnreachableLoad ); // TODO: What's the texture format? + + InsertD3D9FormatInfo(&map, GL_RGBA32F_EXT, D3DFMT_A32B32G32R32F, D3DFMT_A32B32G32R32F, LoadToNative ); + InsertD3D9FormatInfo(&map, GL_RGB32F_EXT, D3DFMT_A32B32G32R32F, D3DFMT_A32B32G32R32F, LoadToNative3To4); + InsertD3D9FormatInfo(&map, GL_RG32F_EXT, D3DFMT_G32R32F, D3DFMT_G32R32F, LoadToNative ); + InsertD3D9FormatInfo(&map, GL_R32F_EXT, D3DFMT_R32F, D3DFMT_R32F, LoadToNative ); + InsertD3D9FormatInfo(&map, GL_ALPHA32F_EXT, D3DFMT_A32B32G32R32F, D3DFMT_UNKNOWN, LoadA32FToRGBA32F ); + InsertD3D9FormatInfo(&map, GL_LUMINANCE32F_EXT, D3DFMT_A32B32G32R32F, D3DFMT_UNKNOWN, LoadL32FToRGBA32F ); + InsertD3D9FormatInfo(&map, GL_LUMINANCE_ALPHA32F_EXT, D3DFMT_A32B32G32R32F, D3DFMT_UNKNOWN, LoadLA32FToRGBA32F ); + + InsertD3D9FormatInfo(&map, GL_RGBA16F_EXT, D3DFMT_A16B16G16R16F, D3DFMT_A16B16G16R16F, LoadToNative ); + InsertD3D9FormatInfo(&map, GL_RGB16F_EXT, D3DFMT_A16B16G16R16F, D3DFMT_A16B16G16R16F, LoadToNative3To4 ); + InsertD3D9FormatInfo(&map, GL_RG16F_EXT, D3DFMT_G16R16F, D3DFMT_G16R16F, LoadToNative ); + InsertD3D9FormatInfo(&map, GL_R16F_EXT, D3DFMT_R16F, D3DFMT_R16F, LoadToNative ); + InsertD3D9FormatInfo(&map, GL_ALPHA16F_EXT, D3DFMT_A16B16G16R16F, D3DFMT_UNKNOWN, LoadA16FToRGBA16F ); + InsertD3D9FormatInfo(&map, GL_LUMINANCE16F_EXT, D3DFMT_A16B16G16R16F, D3DFMT_UNKNOWN, LoadL16FToRGBA16F ); + InsertD3D9FormatInfo(&map, GL_LUMINANCE_ALPHA16F_EXT, D3DFMT_A16B16G16R16F, D3DFMT_UNKNOWN, LoadLA16FToRGBA16F ); + + InsertD3D9FormatInfo(&map, GL_ALPHA8_EXT, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FallbackLoad); + + InsertD3D9FormatInfo(&map, GL_RGB8_OES, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadRGB8ToBGRX8 ); + InsertD3D9FormatInfo(&map, GL_RGB565, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadR5G6B5ToBGRA8 ); + InsertD3D9FormatInfo(&map, GL_RGBA8_OES, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FallbackLoad); + InsertD3D9FormatInfo(&map, GL_RGBA4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadRGBA4ToBGRA8 ); + InsertD3D9FormatInfo(&map, GL_RGB5_A1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadRGB5A1ToBGRA8 ); + InsertD3D9FormatInfo(&map, GL_R8_EXT, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadR8ToBGRX8 ); + InsertD3D9FormatInfo(&map, GL_RG8_EXT, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadRG8ToBGRX8 ); + + InsertD3D9FormatInfo(&map, GL_BGRA8_EXT, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadToNative ); + InsertD3D9FormatInfo(&map, GL_BGRA4_ANGLEX, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadBGRA4ToBGRA8 ); + InsertD3D9FormatInfo(&map, GL_BGR5_A1_ANGLEX, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadBGR5A1ToBGRA8 ); + + InsertD3D9FormatInfo(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, D3DFMT_DXT1, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 8> ); + InsertD3D9FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, D3DFMT_DXT1, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 8> ); + InsertD3D9FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, D3DFMT_DXT3, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 16> ); + InsertD3D9FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, D3DFMT_DXT5, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 16> ); + + // These formats require checking if the renderer supports D3DFMT_L8 or D3DFMT_A8L8 and + // then changing the format and loading function appropriately. + InsertD3D9FormatInfo(&map, GL_LUMINANCE8_EXT, D3DFMT_L8, D3DFMT_UNKNOWN, LoadToNative ); + InsertD3D9FormatInfo(&map, GL_LUMINANCE8_ALPHA8_EXT, D3DFMT_A8L8, D3DFMT_UNKNOWN, LoadToNative ); + + return map; +} + +const TextureFormat &GetTextureFormatInfo(GLenum internalFormat) +{ + static const D3D9FormatMap formatMap = BuildD3D9FormatMap(); + D3D9FormatMap::const_iterator iter = formatMap.find(internalFormat); + if (iter != formatMap.end()) + { + return iter->second; + } + else + { + static const TextureFormat defaultInfo; + return defaultInfo; + } +} + +static GLenum GetDeclTypeComponentType(D3DDECLTYPE declType) +{ + switch (declType) + { + case D3DDECLTYPE_FLOAT1: return GL_FLOAT; + case D3DDECLTYPE_FLOAT2: return GL_FLOAT; + case D3DDECLTYPE_FLOAT3: return GL_FLOAT; + case D3DDECLTYPE_FLOAT4: return GL_FLOAT; + case D3DDECLTYPE_UBYTE4: return GL_UNSIGNED_INT; + case D3DDECLTYPE_SHORT2: return GL_INT; + case D3DDECLTYPE_SHORT4: return GL_INT; + case D3DDECLTYPE_UBYTE4N: return GL_UNSIGNED_NORMALIZED; + case D3DDECLTYPE_SHORT4N: return GL_SIGNED_NORMALIZED; + case D3DDECLTYPE_USHORT4N: return GL_UNSIGNED_NORMALIZED; + case D3DDECLTYPE_SHORT2N: return GL_SIGNED_NORMALIZED; + case D3DDECLTYPE_USHORT2N: return GL_UNSIGNED_NORMALIZED; + default: UNREACHABLE(); return GL_NONE; + } +} + +// Attribute format conversion +enum { NUM_GL_VERTEX_ATTRIB_TYPES = 6 }; + +struct TranslationDescription +{ + DWORD capsFlag; + VertexFormat preferredConversion; + VertexFormat fallbackConversion; +}; + +// 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 }; +}; + +VertexFormat::VertexFormat() + : conversionType(VERTEX_CONVERT_NONE), + outputElementSize(0), + copyFunction(NULL), + nativeFormat(D3DDECLTYPE_UNUSED), + componentType(GL_NONE) +{ +} + +// Initialize a TranslationInfo +VertexFormat CreateVertexFormatInfo(bool identity, size_t elementSize, VertexCopyFunction copyFunc, D3DDECLTYPE nativeFormat) +{ + VertexFormat formatInfo; + formatInfo.conversionType = identity ? VERTEX_CONVERT_NONE : VERTEX_CONVERT_CPU; + formatInfo.outputElementSize = elementSize; + formatInfo.copyFunction = copyFunc; + formatInfo.nativeFormat = nativeFormat; + formatInfo.componentType = GetDeclTypeComponentType(nativeFormat); + return formatInfo; +} + +#define TRANSLATION(type, norm, size, preferred) \ + CreateVertexFormatInfo \ + ( \ + 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) }, \ + } + +static inline unsigned int ComputeTypeIndex(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 VertexFormat &GetVertexFormatInfo(DWORD supportedDeclTypes, const gl::VertexFormat &vertexFormat) +{ + static bool initialized = false; + static DWORD intializedDeclTypes = 0; + static VertexFormat formatConverters[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; + if (!initialized) + { + const TranslationDescription translations[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) + }; + 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 (translations[i][j][k].capsFlag == 0 || (supportedDeclTypes & translations[i][j][k].capsFlag) != 0) + { + formatConverters[i][j][k] = translations[i][j][k].preferredConversion; + } + else + { + formatConverters[i][j][k] = translations[i][j][k].fallbackConversion; + } + } + } + } + initialized = true; + intializedDeclTypes = supportedDeclTypes; + } + + ASSERT(intializedDeclTypes == supportedDeclTypes); + + // Pure integer attributes only supported in ES3.0 + ASSERT(!vertexFormat.mPureInteger); + return formatConverters[ComputeTypeIndex(vertexFormat.mType)][vertexFormat.mNormalized][vertexFormat.mComponents - 1]; +} + +} + +} diff --git a/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.h new file mode 100644 index 000000000000..f26fe43b3608 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.h @@ -0,0 +1,74 @@ +// +// Copyright (c) 2013-2014 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. +// + +// formatutils9.h: Queries for GL image formats and their translations to D3D9 +// formats. + +#ifndef LIBGLESV2_RENDERER_FORMATUTILS9_H_ +#define LIBGLESV2_RENDERER_FORMATUTILS9_H_ + +#include "libGLESv2/formatutils.h" + +#include + +namespace rx +{ + +class Renderer9; + +namespace d3d9 +{ + +typedef std::map, ColorCopyFunction> FastCopyFunctionMap; + +struct D3DFormat +{ + D3DFormat(); + + GLuint pixelBytes; + GLuint blockWidth; + GLuint blockHeight; + + GLenum internalFormat; + + MipGenerationFunction mipGenerationFunction; + ColorReadFunction colorReadFunction; + + FastCopyFunctionMap fastCopyFunctions; + ColorCopyFunction getFastCopyFunction(GLenum format, GLenum type) const; +}; +const D3DFormat &GetD3DFormatInfo(D3DFORMAT format); + +struct VertexFormat +{ + VertexFormat(); + + VertexConversionType conversionType; + size_t outputElementSize; + VertexCopyFunction copyFunction; + D3DDECLTYPE nativeFormat; + GLenum componentType; +}; +const VertexFormat &GetVertexFormatInfo(DWORD supportedDeclTypes, const gl::VertexFormat &vertexFormat); + +struct TextureFormat +{ + TextureFormat(); + + D3DFORMAT texFormat; + D3DFORMAT renderFormat; + + InitializeTextureDataFunction dataInitializerFunction; + + LoadImageFunction loadFunction; +}; +const TextureFormat &GetTextureFormatInfo(GLenum internalFormat); + +} + +} + +#endif // LIBGLESV2_RENDERER_FORMATUTILS9_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp new file mode 100644 index 000000000000..b6ba530c5687 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp @@ -0,0 +1,536 @@ +// +// Copyright (c) 2002-2014 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/d3d/d3d9/renderer9_utils.h" +#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" +#include "libGLESv2/formatutils.h" + +#include "common/mathutil.h" +#include "common/debug.h" + +#include "third_party/systeminfo/SystemInfo.h" + +namespace rx +{ + +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::ColorF 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; + case GL_MIN_EXT: d3dBlendOp = D3DBLENDOP_MIN; break; + case GL_MAX_EXT: d3dBlendOp = D3DBLENDOP_MAX; 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; + } +} + +D3DMULTISAMPLE_TYPE GetMultisampleType(GLuint samples) +{ + return (samples > 1) ? static_cast(samples) : D3DMULTISAMPLE_NONE; +} + +} + +namespace d3d9_gl +{ + +GLsizei GetSamplesCount(D3DMULTISAMPLE_TYPE type) +{ + return (type != D3DMULTISAMPLE_NONMASKABLE) ? type : 0; +} + +bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format) +{ + GLenum internalFormat = d3d9::GetD3DFormatInfo(d3dformat).internalFormat; + GLenum convertedFormat = gl::GetInternalFormatInfo(internalFormat).format; + return convertedFormat == format; +} + +static gl::TextureCaps GenerateTextureFormatCaps(GLenum internalFormat, IDirect3D9 *d3d9, D3DDEVTYPE deviceType, + UINT adapter, D3DFORMAT adapterFormat) +{ + gl::TextureCaps textureCaps; + + const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalFormat); + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); + if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) + { + textureCaps.texturable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, 0, D3DRTYPE_TEXTURE, d3dFormatInfo.renderFormat)); + textureCaps.filterable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_QUERY_FILTER, D3DRTYPE_TEXTURE, d3dFormatInfo.renderFormat)); + textureCaps.renderable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, d3dFormatInfo.renderFormat)) || + SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, d3dFormatInfo.renderFormat)); + } + else + { + textureCaps.texturable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, 0, D3DRTYPE_TEXTURE, d3dFormatInfo.texFormat)) && + SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, 0, D3DRTYPE_CUBETEXTURE, d3dFormatInfo.texFormat)); + textureCaps.filterable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_QUERY_FILTER, D3DRTYPE_TEXTURE, d3dFormatInfo.texFormat)); + textureCaps.renderable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, d3dFormatInfo.texFormat)) || + SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, d3dFormatInfo.texFormat)); + } + + textureCaps.sampleCounts.insert(1); + for (size_t i = D3DMULTISAMPLE_2_SAMPLES; i <= D3DMULTISAMPLE_16_SAMPLES; i++) + { + D3DMULTISAMPLE_TYPE multisampleType = D3DMULTISAMPLE_TYPE(i); + + HRESULT result = d3d9->CheckDeviceMultiSampleType(adapter, deviceType, d3dFormatInfo.renderFormat, TRUE, multisampleType, NULL); + if (SUCCEEDED(result)) + { + textureCaps.sampleCounts.insert(i); + } + } + + return textureCaps; +} + +void GenerateCaps(IDirect3D9 *d3d9, IDirect3DDevice9 *device, D3DDEVTYPE deviceType, UINT adapter, gl::Caps *caps, + gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions) +{ + D3DCAPS9 deviceCaps; + if (FAILED(d3d9->GetDeviceCaps(adapter, deviceType, &deviceCaps))) + { + // Can't continue with out device caps + return; + } + + D3DDISPLAYMODE currentDisplayMode; + d3d9->GetAdapterDisplayMode(adapter, ¤tDisplayMode); + + GLuint maxSamples = 0; + const gl::FormatSet &allFormats = gl::GetAllSizedInternalFormats(); + for (gl::FormatSet::const_iterator internalFormat = allFormats.begin(); internalFormat != allFormats.end(); ++internalFormat) + { + gl::TextureCaps textureCaps = GenerateTextureFormatCaps(*internalFormat, d3d9, deviceType, adapter, + currentDisplayMode.Format); + textureCapsMap->insert(*internalFormat, textureCaps); + + maxSamples = std::max(maxSamples, textureCaps.getMaxSamples()); + + if (gl::GetInternalFormatInfo(*internalFormat).compressed) + { + caps->compressedTextureFormats.push_back(*internalFormat); + } + } + + // GL core feature limits + caps->maxElementIndex = static_cast(std::numeric_limits::max()); + + // 3D textures are unimplemented in D3D9 + caps->max3DTextureSize = 1; + + // Only one limit in GL, use the minimum dimension + caps->max2DTextureSize = std::min(deviceCaps.MaxTextureWidth, deviceCaps.MaxTextureHeight); + + // D3D treats cube maps as a special case of 2D textures + caps->maxCubeMapTextureSize = caps->max2DTextureSize; + + // Array textures are not available in D3D9 + caps->maxArrayTextureLayers = 1; + + // ES3-only feature + caps->maxLODBias = 0.0f; + + // No specific limits on render target size, maximum 2D texture size is equivalent + caps->maxRenderbufferSize = caps->max2DTextureSize; + + // Draw buffers are not supported in D3D9 + caps->maxDrawBuffers = 1; + caps->maxColorAttachments = 1; + + // No specific limits on viewport size, maximum 2D texture size is equivalent + caps->maxViewportWidth = caps->max2DTextureSize; + caps->maxViewportHeight = caps->maxViewportWidth; + + // Point size is clamped to 1.0f when the shader model is less than 3 + caps->minAliasedPointSize = 1.0f; + caps->maxAliasedPointSize = ((D3DSHADER_VERSION_MAJOR(deviceCaps.PixelShaderVersion) >= 3) ? deviceCaps.MaxPointSize : 1.0f); + + // Wide lines not supported + caps->minAliasedLineWidth = 1.0f; + caps->maxAliasedLineWidth = 1.0f; + + // Primitive count limits (unused in ES2) + caps->maxElementsIndices = 0; + caps->maxElementsVertices = 0; + + // Program and shader binary formats (no supported shader binary formats) + caps->programBinaryFormats.push_back(GL_PROGRAM_BINARY_ANGLE); + + // WaitSync is ES3-only, set to zero + caps->maxServerWaitTimeout = 0; + + // Vertex shader limits + caps->maxVertexAttributes = 16; + + const size_t reservedVertexUniformVectors = 2; // dx_ViewAdjust and dx_DepthRange. + const size_t MAX_VERTEX_CONSTANT_VECTORS_D3D9 = 256; + caps->maxVertexUniformVectors = MAX_VERTEX_CONSTANT_VECTORS_D3D9 - reservedVertexUniformVectors; + caps->maxVertexUniformComponents = caps->maxVertexUniformVectors * 4; + + caps->maxVertexUniformBlocks = 0; + + const size_t MAX_VERTEX_OUTPUT_VECTORS_SM3 = 10; + const size_t MAX_VERTEX_OUTPUT_VECTORS_SM2 = 8; + caps->maxVertexOutputComponents = ((deviceCaps.VertexShaderVersion >= D3DVS_VERSION(3, 0)) ? MAX_VERTEX_OUTPUT_VECTORS_SM3 + : MAX_VERTEX_OUTPUT_VECTORS_SM2) * 4; + + // Only Direct3D 10 ready devices support all the necessary vertex texture formats. + // We test this using D3D9 by checking support for the R16F format. + if (deviceCaps.VertexShaderVersion >= D3DVS_VERSION(3, 0) && + SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, currentDisplayMode.Format, + D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F))) + { + const size_t MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 = 4; + caps->maxVertexTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS_VTF_SM3; + } + else + { + caps->maxVertexTextureImageUnits = 0; + } + + // Fragment shader limits + const size_t reservedPixelUniformVectors = 3; // dx_ViewCoords, dx_DepthFront and dx_DepthRange. + + const size_t MAX_PIXEL_CONSTANT_VECTORS_SM3 = 224; + const size_t MAX_PIXEL_CONSTANT_VECTORS_SM2 = 32; + caps->maxFragmentUniformVectors = ((deviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0)) ? MAX_PIXEL_CONSTANT_VECTORS_SM3 + : MAX_PIXEL_CONSTANT_VECTORS_SM2) - reservedPixelUniformVectors; + caps->maxFragmentUniformComponents = caps->maxFragmentUniformVectors * 4; + caps->maxFragmentUniformBlocks = 0; + caps->maxFragmentInputComponents = caps->maxVertexOutputComponents; + caps->maxTextureImageUnits = 16; + caps->minProgramTexelOffset = 0; + caps->maxProgramTexelOffset = 0; + + // Aggregate shader limits (unused in ES2) + caps->maxUniformBufferBindings = 0; + caps->maxUniformBlockSize = 0; + caps->uniformBufferOffsetAlignment = 0; + caps->maxCombinedUniformBlocks = 0; + caps->maxCombinedVertexUniformComponents = 0; + caps->maxCombinedFragmentUniformComponents = 0; + caps->maxVaryingComponents = 0; + + // Aggregate shader limits + caps->maxVaryingVectors = caps->maxVertexOutputComponents / 4; + caps->maxCombinedTextureImageUnits = caps->maxVertexTextureImageUnits + caps->maxFragmentInputComponents; + + // Transform feedback limits + caps->maxTransformFeedbackInterleavedComponents = 0; + caps->maxTransformFeedbackSeparateAttributes = 0; + caps->maxTransformFeedbackSeparateComponents = 0; + + // GL extension support + extensions->setTextureExtensionSupport(*textureCapsMap); + extensions->elementIndexUint = deviceCaps.MaxVertexIndex >= (1 << 16); + extensions->packedDepthStencil = true; + extensions->getProgramBinary = true; + extensions->rgb8rgba8 = true; + extensions->readFormatBGRA = true; + extensions->pixelBufferObject = false; + extensions->mapBuffer = false; + extensions->mapBufferRange = false; + + // ATI cards on XP have problems with non-power-of-two textures. + D3DADAPTER_IDENTIFIER9 adapterId = { 0 }; + if (SUCCEEDED(d3d9->GetAdapterIdentifier(adapter, 0, &adapterId))) + { + extensions->textureNPOT = !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) && + !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) && + !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) && + !(isWindowsVistaOrGreater() && adapterId.VendorId == VENDOR_ID_AMD); + } + else + { + extensions->textureNPOT = false; + } + + extensions->drawBuffers = false; + extensions->textureStorage = true; + + // Must support a minimum of 2:1 anisotropy for max anisotropy to be considered supported, per the spec + extensions->textureFilterAnisotropic = (deviceCaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) != 0 && deviceCaps.MaxAnisotropy >= 2; + extensions->maxTextureAnisotropy = static_cast(deviceCaps.MaxAnisotropy); + + // Check occlusion query support by trying to create one + IDirect3DQuery9 *occlusionQuery = NULL; + extensions->occlusionQueryBoolean = SUCCEEDED(device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery)) && occlusionQuery; + SafeRelease(occlusionQuery); + + // Check event query support by trying to create one + IDirect3DQuery9 *eventQuery = NULL; + extensions->fence = SUCCEEDED(device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery)) && eventQuery; + SafeRelease(eventQuery); + + extensions->timerQuery = false; // Unimplemented + extensions->robustness = true; + extensions->blendMinMax = true; + extensions->framebufferBlit = true; + extensions->framebufferMultisample = true; + extensions->maxSamples = maxSamples; + extensions->instancedArrays = deviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0); + extensions->packReverseRowOrder = true; + extensions->standardDerivatives = (deviceCaps.PS20Caps.Caps & D3DPS20CAPS_GRADIENTINSTRUCTIONS) != 0; + extensions->shaderTextureLOD = true; + extensions->fragDepth = true; + extensions->textureUsage = true; + extensions->translatedShaderSource = true; + extensions->colorBufferFloat = false; +} + +} + +namespace d3d9 +{ + +GLuint ComputeBlockSize(D3DFORMAT format, GLuint width, GLuint height) +{ + const D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(format); + GLuint numBlocksWide = (width + d3dFormatInfo.blockWidth - 1) / d3dFormatInfo.blockWidth; + GLuint numBlocksHight = (height + d3dFormatInfo.blockHeight - 1) / d3dFormatInfo.blockHeight; + return (d3dFormatInfo.pixelBytes * numBlocksWide * numBlocksHight); +} + +void MakeValidSize(bool isImage, D3DFORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset) +{ + const D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(format); + + int upsampleCount = 0; + // Don't expand the size of full textures that are at least (blockWidth x blockHeight) already. + if (isImage || *requestWidth < static_cast(d3dFormatInfo.blockWidth) || + *requestHeight < static_cast(d3dFormatInfo.blockHeight)) + { + while (*requestWidth % d3dFormatInfo.blockWidth != 0 || *requestHeight % d3dFormatInfo.blockHeight != 0) + { + *requestWidth <<= 1; + *requestHeight <<= 1; + upsampleCount++; + } + } + *levelOffset = upsampleCount; +} + +} + +} diff --git a/gfx/angle/src/libGLESv2/renderer/d3d9/renderer9_utils.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.h similarity index 67% rename from gfx/angle/src/libGLESv2/renderer/d3d9/renderer9_utils.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.h index a115f9e3b9cb..5f19f3b7500c 100644 --- a/gfx/angle/src/libGLESv2/renderer/d3d9/renderer9_utils.h +++ b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2014 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,6 +11,7 @@ #define LIBGLESV2_RENDERER_RENDERER9_UTILS_H #include "libGLESv2/angletypes.h" +#include "libGLESv2/Caps.h" namespace rx { @@ -30,11 +31,29 @@ 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); +D3DMULTISAMPLE_TYPE GetMultisampleType(GLuint samples); + +} + +namespace d3d9_gl +{ + +GLsizei GetSamplesCount(D3DMULTISAMPLE_TYPE type); + +bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format); + +void GenerateCaps(IDirect3D9 *d3d9, IDirect3DDevice9 *device, D3DDEVTYPE deviceType, UINT adapter, gl::Caps *caps, + gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions); + } namespace d3d9 { +GLuint ComputeBlockSize(D3DFORMAT format, GLuint width, GLuint height); + +void MakeValidSize(bool isImage, D3DFORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset); + inline bool isDeviceLostError(HRESULT errorCode) { switch (errorCode) diff --git a/gfx/angle/src/libGLESv2/renderer/d3d9/shaders/Blit.ps b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.ps similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d9/shaders/Blit.ps rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.ps diff --git a/gfx/angle/src/libGLESv2/renderer/d3d9/shaders/Blit.vs b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.vs similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d9/shaders/Blit.vs rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.vs diff --git a/gfx/angle/src/libGLESv2/renderer/d3d9/shaders/compiled/componentmaskps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/compiled/componentmaskps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d9/shaders/compiled/componentmaskps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/compiled/componentmaskps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d9/shaders/compiled/flipyvs.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/compiled/flipyvs.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d9/shaders/compiled/flipyvs.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/compiled/flipyvs.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d9/shaders/compiled/luminanceps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/compiled/luminanceps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d9/shaders/compiled/luminanceps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/compiled/luminanceps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d9/shaders/compiled/passthroughps.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/compiled/passthroughps.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d9/shaders/compiled/passthroughps.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/compiled/passthroughps.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d9/shaders/compiled/standardvs.h b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/compiled/standardvs.h similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d9/shaders/compiled/standardvs.h rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/compiled/standardvs.h diff --git a/gfx/angle/src/libGLESv2/renderer/d3d9/shaders/generate_shaders.bat b/gfx/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/generate_shaders.bat similarity index 100% rename from gfx/angle/src/libGLESv2/renderer/d3d9/shaders/generate_shaders.bat rename to gfx/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/generate_shaders.bat diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.h b/gfx/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.h deleted file mode 100644 index 7934de192c1b..000000000000 --- a/gfx/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.h +++ /dev/null @@ -1,100 +0,0 @@ -// -// Copyright (c) 2013-2014 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" -#include "libGLESv2/angletypes.h" - -namespace rx -{ -class Renderer; -class Renderer11; - -enum BufferUsage -{ - BUFFER_USAGE_STAGING, - BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK, - BUFFER_USAGE_INDEX, - BUFFER_USAGE_PIXEL_UNPACK, - BUFFER_USAGE_PIXEL_PACK, - BUFFER_USAGE_UNIFORM, -}; - -struct PackPixelsParams -{ - PackPixelsParams(); - PackPixelsParams(const gl::Rectangle &area, GLenum format, GLenum type, GLuint outputPitch, - const gl::PixelPackState &pack, ptrdiff_t offset); - - gl::Rectangle area; - GLenum format; - GLenum type; - GLuint outputPitch; - gl::Buffer *packBuffer; - gl::PixelPackState pack; - ptrdiff_t offset; -}; - -typedef size_t DataRevision; - -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, size_t size, size_t offset); - virtual void copyData(BufferStorage* sourceStorage, size_t size, size_t sourceOffset, size_t destOffset); - virtual void clear(); - virtual void markTransformFeedbackUsage(); - virtual size_t getSize() const; - virtual bool supportsDirectBinding() const; - - ID3D11Buffer *getBuffer(BufferUsage usage); - ID3D11ShaderResourceView *getSRV(DXGI_FORMAT srvFormat); - void packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams ¶ms); - - virtual bool isMapped() const; - virtual void *map(GLbitfield access); - virtual void unmap(); - - private: - class TypedBufferStorage11; - class NativeBuffer11; - class PackStorage11; - - Renderer11 *mRenderer; - TypedBufferStorage11 *mMappedStorage; - - std::map mTypedBuffers; - - typedef std::pair BufferSRVPair; - std::map mBufferResourceViews; - - std::vector mResolvedData; - DataRevision mResolvedDataRevision; - unsigned int mReadUsageCount; - - size_t mSize; - - void markBufferUsage(); - NativeBuffer11 *getStagingBuffer(); - PackStorage11 *getPackStorage(); - - TypedBufferStorage11 *getStorage(BufferUsage usage); - TypedBufferStorage11 *getLatestStorage() const; -}; - -} - -#endif // LIBGLESV2_RENDERER_BUFFERSTORAGE11_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/formatutils11.cpp b/gfx/angle/src/libGLESv2/renderer/d3d11/formatutils11.cpp deleted file mode 100644 index 695e168478f1..000000000000 --- a/gfx/angle/src/libGLESv2/renderer/d3d11/formatutils11.cpp +++ /dev/null @@ -1,1665 +0,0 @@ -#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. -// - -// formatutils11.cpp: Queries for GL image formats and their translations to D3D11 -// formats. - -#include "libGLESv2/renderer/d3d11/formatutils11.h" -#include "libGLESv2/renderer/generatemip.h" -#include "libGLESv2/renderer/loadimage.h" -#include "libGLESv2/renderer/copyimage.h" -#include "libGLESv2/renderer/Renderer.h" -#include "libGLESv2/renderer/copyvertex.h" - -namespace rx -{ - -struct D3D11ES3FormatInfo -{ - DXGI_FORMAT mTexFormat; - DXGI_FORMAT mSRVFormat; - DXGI_FORMAT mRTVFormat; - DXGI_FORMAT mDSVFormat; - - D3D11ES3FormatInfo() - : mTexFormat(DXGI_FORMAT_UNKNOWN), mDSVFormat(DXGI_FORMAT_UNKNOWN), mRTVFormat(DXGI_FORMAT_UNKNOWN), mSRVFormat(DXGI_FORMAT_UNKNOWN) - { } - - D3D11ES3FormatInfo(DXGI_FORMAT texFormat, DXGI_FORMAT srvFormat, DXGI_FORMAT rtvFormat, DXGI_FORMAT dsvFormat) - : mTexFormat(texFormat), mDSVFormat(dsvFormat), mRTVFormat(rtvFormat), mSRVFormat(srvFormat) - { } -}; - -// For sized GL internal formats, there is only one corresponding D3D11 format. This map type allows -// querying for the DXGI texture formats to use for textures, SRVs, RTVs and DSVs given a GL internal -// format. -typedef std::pair D3D11ES3FormatPair; -typedef std::map D3D11ES3FormatMap; - -static D3D11ES3FormatMap BuildD3D11ES3FormatMap() -{ - D3D11ES3FormatMap map; - - // | GL internal format | | D3D11 texture format | D3D11 SRV format | D3D11 RTV format | D3D11 DSV format | - map.insert(D3D11ES3FormatPair(GL_NONE, D3D11ES3FormatInfo(DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_R8, D3D11ES3FormatInfo(DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_R8_SNORM, D3D11ES3FormatInfo(DXGI_FORMAT_R8_SNORM, DXGI_FORMAT_R8_SNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RG8, D3D11ES3FormatInfo(DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RG8_SNORM, D3D11ES3FormatInfo(DXGI_FORMAT_R8G8_SNORM, DXGI_FORMAT_R8G8_SNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGB8, D3D11ES3FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGB8_SNORM, D3D11ES3FormatInfo(DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGB565, D3D11ES3FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGBA4, D3D11ES3FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGB5_A1, D3D11ES3FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGBA8, D3D11ES3FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGBA8_SNORM, D3D11ES3FormatInfo(DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGB10_A2, D3D11ES3FormatInfo(DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGB10_A2UI, D3D11ES3FormatInfo(DXGI_FORMAT_R10G10B10A2_UINT, DXGI_FORMAT_R10G10B10A2_UINT, DXGI_FORMAT_R10G10B10A2_UINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_SRGB8, D3D11ES3FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_SRGB8_ALPHA8, D3D11ES3FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_R16F, D3D11ES3FormatInfo(DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RG16F, D3D11ES3FormatInfo(DXGI_FORMAT_R16G16_FLOAT, DXGI_FORMAT_R16G16_FLOAT, DXGI_FORMAT_R16G16_FLOAT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGB16F, D3D11ES3FormatInfo(DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGBA16F, D3D11ES3FormatInfo(DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_R32F, D3D11ES3FormatInfo(DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RG32F, D3D11ES3FormatInfo(DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGB32F, D3D11ES3FormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGBA32F, D3D11ES3FormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_R11F_G11F_B10F, D3D11ES3FormatInfo(DXGI_FORMAT_R11G11B10_FLOAT, DXGI_FORMAT_R11G11B10_FLOAT, DXGI_FORMAT_R11G11B10_FLOAT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGB9_E5, D3D11ES3FormatInfo(DXGI_FORMAT_R9G9B9E5_SHAREDEXP, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_R8I, D3D11ES3FormatInfo(DXGI_FORMAT_R8_SINT, DXGI_FORMAT_R8_SINT, DXGI_FORMAT_R8_SINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_R8UI, D3D11ES3FormatInfo(DXGI_FORMAT_R8_UINT, DXGI_FORMAT_R8_UINT, DXGI_FORMAT_R8_UINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_R16I, D3D11ES3FormatInfo(DXGI_FORMAT_R16_SINT, DXGI_FORMAT_R16_SINT, DXGI_FORMAT_R16_SINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_R16UI, D3D11ES3FormatInfo(DXGI_FORMAT_R16_UINT, DXGI_FORMAT_R16_UINT, DXGI_FORMAT_R16_UINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_R32I, D3D11ES3FormatInfo(DXGI_FORMAT_R32_SINT, DXGI_FORMAT_R32_SINT, DXGI_FORMAT_R32_SINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_R32UI, D3D11ES3FormatInfo(DXGI_FORMAT_R32_UINT, DXGI_FORMAT_R32_UINT, DXGI_FORMAT_R32_UINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RG8I, D3D11ES3FormatInfo(DXGI_FORMAT_R8G8_SINT, DXGI_FORMAT_R8G8_SINT, DXGI_FORMAT_R8G8_SINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RG8UI, D3D11ES3FormatInfo(DXGI_FORMAT_R8G8_UINT, DXGI_FORMAT_R8G8_UINT, DXGI_FORMAT_R8G8_UINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RG16I, D3D11ES3FormatInfo(DXGI_FORMAT_R16G16_SINT, DXGI_FORMAT_R16G16_SINT, DXGI_FORMAT_R16G16_SINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RG16UI, D3D11ES3FormatInfo(DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RG32I, D3D11ES3FormatInfo(DXGI_FORMAT_R32G32_SINT, DXGI_FORMAT_R32G32_SINT, DXGI_FORMAT_R32G32_SINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RG32UI, D3D11ES3FormatInfo(DXGI_FORMAT_R32G32_UINT, DXGI_FORMAT_R32G32_UINT, DXGI_FORMAT_R32G32_UINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGB8I, D3D11ES3FormatInfo(DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGB8UI, D3D11ES3FormatInfo(DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGB16I, D3D11ES3FormatInfo(DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGB16UI, D3D11ES3FormatInfo(DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGB32I, D3D11ES3FormatInfo(DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGB32UI, D3D11ES3FormatInfo(DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGBA8I, D3D11ES3FormatInfo(DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGBA8UI, D3D11ES3FormatInfo(DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGBA16I, D3D11ES3FormatInfo(DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGBA16UI, D3D11ES3FormatInfo(DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGBA32I, D3D11ES3FormatInfo(DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGBA32UI, D3D11ES3FormatInfo(DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_UNKNOWN))); - - // Unsized formats, TODO: Are types of float and half float allowed for the unsized types? Would it change the DXGI format? - map.insert(D3D11ES3FormatPair(GL_ALPHA, D3D11ES3FormatInfo(DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_LUMINANCE, D3D11ES3FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_LUMINANCE_ALPHA, D3D11ES3FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGB, D3D11ES3FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGBA, D3D11ES3FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_BGRA_EXT, D3D11ES3FormatInfo(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN))); - - // From GL_EXT_texture_storage - // | GL internal format | | D3D11 texture format | D3D11 SRV format | D3D11 RTV format | D3D11 DSV format | - map.insert(D3D11ES3FormatPair(GL_ALPHA8_EXT, D3D11ES3FormatInfo(DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_UNKNOWN ))); - map.insert(D3D11ES3FormatPair(GL_LUMINANCE8_EXT, D3D11ES3FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN ))); - map.insert(D3D11ES3FormatPair(GL_ALPHA32F_EXT, D3D11ES3FormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN ))); - map.insert(D3D11ES3FormatPair(GL_LUMINANCE32F_EXT, D3D11ES3FormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN ))); - map.insert(D3D11ES3FormatPair(GL_ALPHA16F_EXT, D3D11ES3FormatInfo(DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN ))); - map.insert(D3D11ES3FormatPair(GL_LUMINANCE16F_EXT, D3D11ES3FormatInfo(DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN ))); - map.insert(D3D11ES3FormatPair(GL_LUMINANCE8_ALPHA8_EXT, D3D11ES3FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN ))); - map.insert(D3D11ES3FormatPair(GL_LUMINANCE_ALPHA32F_EXT, D3D11ES3FormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN ))); - map.insert(D3D11ES3FormatPair(GL_LUMINANCE_ALPHA16F_EXT, D3D11ES3FormatInfo(DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN ))); - map.insert(D3D11ES3FormatPair(GL_BGRA8_EXT, D3D11ES3FormatInfo(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN ))); - map.insert(D3D11ES3FormatPair(GL_BGRA4_ANGLEX, D3D11ES3FormatInfo(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN ))); - map.insert(D3D11ES3FormatPair(GL_BGR5_A1_ANGLEX, D3D11ES3FormatInfo(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN ))); - - // Depth stencil formats - map.insert(D3D11ES3FormatPair(GL_DEPTH_COMPONENT16, D3D11ES3FormatInfo(DXGI_FORMAT_R16_TYPELESS, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D16_UNORM ))); - map.insert(D3D11ES3FormatPair(GL_DEPTH_COMPONENT24, D3D11ES3FormatInfo(DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT ))); - map.insert(D3D11ES3FormatPair(GL_DEPTH_COMPONENT32F, D3D11ES3FormatInfo(DXGI_FORMAT_R32_TYPELESS, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D32_FLOAT ))); - map.insert(D3D11ES3FormatPair(GL_DEPTH24_STENCIL8, D3D11ES3FormatInfo(DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT ))); - map.insert(D3D11ES3FormatPair(GL_DEPTH32F_STENCIL8, D3D11ES3FormatInfo(DXGI_FORMAT_R32G8X24_TYPELESS, DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D32_FLOAT_S8X24_UINT))); - map.insert(D3D11ES3FormatPair(GL_STENCIL_INDEX8, D3D11ES3FormatInfo(DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_X24_TYPELESS_G8_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT ))); - - // From GL_ANGLE_depth_texture - map.insert(D3D11ES3FormatPair(GL_DEPTH_COMPONENT32_OES, D3D11ES3FormatInfo(DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT ))); - - // Compressed formats, From ES 3.0.1 spec, table 3.16 - // | GL internal format | | D3D11 texture format | D3D11 SRV format | D3D11 RTV format | D3D11 DSV format | - map.insert(D3D11ES3FormatPair(GL_COMPRESSED_R11_EAC, D3D11ES3FormatInfo(DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_COMPRESSED_SIGNED_R11_EAC, D3D11ES3FormatInfo(DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_COMPRESSED_RG11_EAC, D3D11ES3FormatInfo(DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_COMPRESSED_SIGNED_RG11_EAC, D3D11ES3FormatInfo(DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_COMPRESSED_RGB8_ETC2, D3D11ES3FormatInfo(DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_COMPRESSED_SRGB8_ETC2, D3D11ES3FormatInfo(DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, D3D11ES3FormatInfo(DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, D3D11ES3FormatInfo(DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_COMPRESSED_RGBA8_ETC2_EAC, D3D11ES3FormatInfo(DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, D3D11ES3FormatInfo(DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); - - // From GL_EXT_texture_compression_dxt1 - map.insert(D3D11ES3FormatPair(GL_COMPRESSED_RGB_S3TC_DXT1_EXT, D3D11ES3FormatInfo(DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, D3D11ES3FormatInfo(DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); - - // From GL_ANGLE_texture_compression_dxt3 - map.insert(D3D11ES3FormatPair(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, D3D11ES3FormatInfo(DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); - - // From GL_ANGLE_texture_compression_dxt5 - map.insert(D3D11ES3FormatPair(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, D3D11ES3FormatInfo(DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); - - return map; -} - -static bool GetD3D11ES3FormatInfo(GLenum internalFormat, GLuint clientVersion, D3D11ES3FormatInfo *outFormatInfo) -{ - static const D3D11ES3FormatMap formatMap = BuildD3D11ES3FormatMap(); - D3D11ES3FormatMap::const_iterator iter = formatMap.find(internalFormat); - if (iter != formatMap.end()) - { - if (outFormatInfo) - { - *outFormatInfo = iter->second; - } - return true; - } - else - { - return false; - } -} - -// ES3 image loading functions vary based on the internal format and data type given, -// this map type determines the loading function from the internal format and type supplied -// to glTex*Image*D and the destination DXGI_FORMAT. Source formats and types are taken from -// Tables 3.2 and 3.3 of the ES 3 spec. -typedef std::pair InternalFormatTypePair; -typedef std::pair D3D11LoadFunctionPair; -typedef std::map D3D11LoadFunctionMap; - -static void UnimplementedLoadFunction(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) -{ - UNIMPLEMENTED(); -} - -static void UnreachableLoadFunction(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) -{ - UNREACHABLE(); -} - -// A helper function to insert data into the D3D11LoadFunctionMap with fewer characters. -static inline void insertLoadFunction(D3D11LoadFunctionMap *map, GLenum internalFormat, GLenum type, - LoadImageFunction loadFunc) -{ - map->insert(D3D11LoadFunctionPair(InternalFormatTypePair(internalFormat, type), loadFunc)); -} - -D3D11LoadFunctionMap buildD3D11LoadFunctionMap() -{ - D3D11LoadFunctionMap map; - - // | Internal format | Type | Load function | - insertLoadFunction(&map, GL_RGBA8, GL_UNSIGNED_BYTE, loadToNative ); - insertLoadFunction(&map, GL_RGB5_A1, GL_UNSIGNED_BYTE, loadToNative ); - insertLoadFunction(&map, GL_RGBA4, GL_UNSIGNED_BYTE, loadToNative ); - insertLoadFunction(&map, GL_SRGB8_ALPHA8, GL_UNSIGNED_BYTE, loadToNative ); - insertLoadFunction(&map, GL_RGBA8_SNORM, GL_BYTE, loadToNative ); - insertLoadFunction(&map, GL_RGBA4, GL_UNSIGNED_SHORT_4_4_4_4, loadRGBA4444DataToRGBA ); - insertLoadFunction(&map, GL_RGB10_A2, GL_UNSIGNED_INT_2_10_10_10_REV, loadToNative ); - insertLoadFunction(&map, GL_RGB5_A1, GL_UNSIGNED_SHORT_5_5_5_1, loadRGBA5551DataToRGBA ); - insertLoadFunction(&map, GL_RGB5_A1, GL_UNSIGNED_INT_2_10_10_10_REV, loadRGBA2101010ToRGBA ); - insertLoadFunction(&map, GL_RGBA16F, GL_HALF_FLOAT, loadToNative ); - insertLoadFunction(&map, GL_RGBA32F, GL_FLOAT, loadToNative ); - insertLoadFunction(&map, GL_RGBA16F, GL_FLOAT, loadFloatDataToHalfFloat<4> ); - insertLoadFunction(&map, GL_RGBA8UI, GL_UNSIGNED_BYTE, loadToNative ); - insertLoadFunction(&map, GL_RGBA8I, GL_BYTE, loadToNative ); - insertLoadFunction(&map, GL_RGBA16UI, GL_UNSIGNED_SHORT, loadToNative ); - insertLoadFunction(&map, GL_RGBA16I, GL_SHORT, loadToNative ); - insertLoadFunction(&map, GL_RGBA32UI, GL_UNSIGNED_INT, loadToNative ); - insertLoadFunction(&map, GL_RGBA32I, GL_INT, loadToNative ); - insertLoadFunction(&map, GL_RGB10_A2UI, GL_UNSIGNED_INT_2_10_10_10_REV, loadToNative ); - insertLoadFunction(&map, GL_RGB8, GL_UNSIGNED_BYTE, loadRGBUByteDataToRGBA ); - insertLoadFunction(&map, GL_RGB565, GL_UNSIGNED_BYTE, loadToNative3To4 ); - insertLoadFunction(&map, GL_SRGB8, GL_UNSIGNED_BYTE, loadToNative3To4 ); - insertLoadFunction(&map, GL_RGB8_SNORM, GL_BYTE, loadRGBSByteDataToRGBA ); - insertLoadFunction(&map, GL_RGB565, GL_UNSIGNED_SHORT_5_6_5, loadRGB565DataToRGBA ); - insertLoadFunction(&map, GL_R11F_G11F_B10F, GL_UNSIGNED_INT_10F_11F_11F_REV, loadToNative ); - insertLoadFunction(&map, GL_RGB9_E5, GL_UNSIGNED_INT_5_9_9_9_REV, loadToNative ); - insertLoadFunction(&map, GL_RGB16F, GL_HALF_FLOAT, loadToNative3To4); - insertLoadFunction(&map, GL_R11F_G11F_B10F, GL_HALF_FLOAT, loadRGBHalfFloatDataTo111110Float ); - insertLoadFunction(&map, GL_RGB9_E5, GL_HALF_FLOAT, loadRGBHalfFloatDataTo999E5 ); - insertLoadFunction(&map, GL_RGB32F, GL_FLOAT, loadToNative3To4); - insertLoadFunction(&map, GL_RGB16F, GL_FLOAT, loadFloatRGBDataToHalfFloatRGBA ); - insertLoadFunction(&map, GL_R11F_G11F_B10F, GL_FLOAT, loadRGBFloatDataTo111110Float ); - insertLoadFunction(&map, GL_RGB9_E5, GL_FLOAT, loadRGBFloatDataTo999E5 ); - insertLoadFunction(&map, GL_RGB8UI, GL_UNSIGNED_BYTE, loadToNative3To4 ); - insertLoadFunction(&map, GL_RGB8I, GL_BYTE, loadToNative3To4 ); - insertLoadFunction(&map, GL_RGB16UI, GL_UNSIGNED_SHORT, loadToNative3To4 ); - insertLoadFunction(&map, GL_RGB16I, GL_SHORT, loadToNative3To4 ); - insertLoadFunction(&map, GL_RGB32UI, GL_UNSIGNED_INT, loadToNative3To4 ); - insertLoadFunction(&map, GL_RGB32I, GL_INT, loadToNative3To4 ); - insertLoadFunction(&map, GL_RG8, GL_UNSIGNED_BYTE, loadToNative ); - insertLoadFunction(&map, GL_RG8_SNORM, GL_BYTE, loadToNative ); - insertLoadFunction(&map, GL_RG16F, GL_HALF_FLOAT, loadToNative ); - insertLoadFunction(&map, GL_RG32F, GL_FLOAT, loadToNative ); - insertLoadFunction(&map, GL_RG16F, GL_FLOAT, loadFloatDataToHalfFloat<2> ); - insertLoadFunction(&map, GL_RG8UI, GL_UNSIGNED_BYTE, loadToNative ); - insertLoadFunction(&map, GL_RG8I, GL_BYTE, loadToNative ); - insertLoadFunction(&map, GL_RG16UI, GL_UNSIGNED_SHORT, loadToNative ); - insertLoadFunction(&map, GL_RG16I, GL_SHORT, loadToNative ); - insertLoadFunction(&map, GL_RG32UI, GL_UNSIGNED_INT, loadToNative ); - insertLoadFunction(&map, GL_RG32I, GL_INT, loadToNative ); - insertLoadFunction(&map, GL_R8, GL_UNSIGNED_BYTE, loadToNative ); - insertLoadFunction(&map, GL_R8_SNORM, GL_BYTE, loadToNative ); - insertLoadFunction(&map, GL_R16F, GL_HALF_FLOAT, loadToNative ); - insertLoadFunction(&map, GL_R32F, GL_FLOAT, loadToNative ); - insertLoadFunction(&map, GL_R16F, GL_FLOAT, loadFloatDataToHalfFloat<1> ); - insertLoadFunction(&map, GL_R8UI, GL_UNSIGNED_BYTE, loadToNative ); - insertLoadFunction(&map, GL_R8I, GL_BYTE, loadToNative ); - insertLoadFunction(&map, GL_R16UI, GL_UNSIGNED_SHORT, loadToNative ); - insertLoadFunction(&map, GL_R16I, GL_SHORT, loadToNative ); - insertLoadFunction(&map, GL_R32UI, GL_UNSIGNED_INT, loadToNative ); - insertLoadFunction(&map, GL_R32I, GL_INT, loadToNative ); - insertLoadFunction(&map, GL_DEPTH_COMPONENT16, GL_UNSIGNED_SHORT, loadToNative ); - insertLoadFunction(&map, GL_DEPTH_COMPONENT24, GL_UNSIGNED_INT, loadG8R24DataToR24G8 ); - insertLoadFunction(&map, GL_DEPTH_COMPONENT16, GL_UNSIGNED_INT, loadUintDataToUshort ); - insertLoadFunction(&map, GL_DEPTH_COMPONENT32F, GL_FLOAT, loadToNative ); - insertLoadFunction(&map, GL_DEPTH24_STENCIL8, GL_UNSIGNED_INT_24_8, loadG8R24DataToR24G8 ); - insertLoadFunction(&map, GL_DEPTH32F_STENCIL8, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, loadToNative ); - - // Unsized formats - // Load functions are unreachable because they are converted to sized internal formats based on - // the format and type before loading takes place. - insertLoadFunction(&map, GL_RGBA, GL_UNSIGNED_BYTE, UnreachableLoadFunction ); - insertLoadFunction(&map, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, UnreachableLoadFunction ); - insertLoadFunction(&map, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, UnreachableLoadFunction ); - insertLoadFunction(&map, GL_RGB, GL_UNSIGNED_BYTE, UnreachableLoadFunction ); - insertLoadFunction(&map, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, UnreachableLoadFunction ); - insertLoadFunction(&map, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, UnreachableLoadFunction ); - insertLoadFunction(&map, GL_LUMINANCE, GL_UNSIGNED_BYTE, UnreachableLoadFunction ); - insertLoadFunction(&map, GL_ALPHA, GL_UNSIGNED_BYTE, UnreachableLoadFunction ); - - // From GL_OES_texture_float - insertLoadFunction(&map, GL_LUMINANCE_ALPHA, GL_FLOAT, loadLuminanceAlphaFloatDataToRGBA ); - insertLoadFunction(&map, GL_LUMINANCE, GL_FLOAT, loadLuminanceFloatDataToRGB ); - insertLoadFunction(&map, GL_ALPHA, GL_FLOAT, loadAlphaFloatDataToRGBA ); - - // From GL_OES_texture_half_float - insertLoadFunction(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT, loadLuminanceAlphaHalfFloatDataToRGBA); - insertLoadFunction(&map, GL_LUMINANCE, GL_HALF_FLOAT, loadLuminanceHalfFloatDataToRGBA ); - insertLoadFunction(&map, GL_ALPHA, GL_HALF_FLOAT, loadAlphaHalfFloatDataToRGBA ); - - // From GL_EXT_texture_storage - insertLoadFunction(&map, GL_ALPHA8_EXT, GL_UNSIGNED_BYTE, loadToNative ); - insertLoadFunction(&map, GL_LUMINANCE8_EXT, GL_UNSIGNED_BYTE, loadLuminanceDataToBGRA ); - insertLoadFunction(&map, GL_LUMINANCE8_ALPHA8_EXT, GL_UNSIGNED_BYTE, loadLuminanceAlphaDataToBGRA ); - insertLoadFunction(&map, GL_ALPHA32F_EXT, GL_FLOAT, loadAlphaFloatDataToRGBA ); - insertLoadFunction(&map, GL_LUMINANCE32F_EXT, GL_FLOAT, loadLuminanceFloatDataToRGB ); - insertLoadFunction(&map, GL_LUMINANCE_ALPHA32F_EXT, GL_FLOAT, loadLuminanceAlphaFloatDataToRGBA ); - insertLoadFunction(&map, GL_ALPHA16F_EXT, GL_HALF_FLOAT, loadAlphaHalfFloatDataToRGBA ); - insertLoadFunction(&map, GL_LUMINANCE16F_EXT, GL_HALF_FLOAT, loadLuminanceHalfFloatDataToRGBA ); - insertLoadFunction(&map, GL_LUMINANCE_ALPHA16F_EXT, GL_HALF_FLOAT, loadLuminanceAlphaHalfFloatDataToRGBA); - - insertLoadFunction(&map, GL_BGRA8_EXT, GL_UNSIGNED_BYTE, loadToNative ); - insertLoadFunction(&map, GL_BGRA4_ANGLEX, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, loadRGBA4444DataToRGBA ); - insertLoadFunction(&map, GL_BGRA4_ANGLEX, GL_UNSIGNED_BYTE, loadToNative ); - insertLoadFunction(&map, GL_BGR5_A1_ANGLEX, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, loadRGBA5551DataToRGBA ); - insertLoadFunction(&map, GL_BGR5_A1_ANGLEX, GL_UNSIGNED_BYTE, loadToNative ); - - // Compressed formats - // From ES 3.0.1 spec, table 3.16 - // | Internal format | Type | Load function | - insertLoadFunction(&map, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); - insertLoadFunction(&map, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); - insertLoadFunction(&map, GL_COMPRESSED_SIGNED_R11_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); - insertLoadFunction(&map, GL_COMPRESSED_RG11_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); - insertLoadFunction(&map, GL_COMPRESSED_SIGNED_RG11_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); - insertLoadFunction(&map, GL_COMPRESSED_RGB8_ETC2, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); - insertLoadFunction(&map, GL_COMPRESSED_SRGB8_ETC2, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); - insertLoadFunction(&map, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); - insertLoadFunction(&map, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); - insertLoadFunction(&map, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); - insertLoadFunction(&map, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); - - // From GL_EXT_texture_compression_dxt1 - insertLoadFunction(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, loadCompressedBlockDataToNative<4, 4, 8>); - insertLoadFunction(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, loadCompressedBlockDataToNative<4, 4, 8>); - - // From GL_ANGLE_texture_compression_dxt3 - insertLoadFunction(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, loadCompressedBlockDataToNative<4, 4, 16>); - - // From GL_ANGLE_texture_compression_dxt5 - insertLoadFunction(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, loadCompressedBlockDataToNative<4, 4, 16>); - - return map; -} - -struct D3D11ES2FormatInfo -{ - DXGI_FORMAT mTexFormat; - DXGI_FORMAT mSRVFormat; - DXGI_FORMAT mRTVFormat; - DXGI_FORMAT mDSVFormat; - - LoadImageFunction mLoadImageFunction; - - D3D11ES2FormatInfo() - : mTexFormat(DXGI_FORMAT_UNKNOWN), mDSVFormat(DXGI_FORMAT_UNKNOWN), mRTVFormat(DXGI_FORMAT_UNKNOWN), - mSRVFormat(DXGI_FORMAT_UNKNOWN), mLoadImageFunction(NULL) - { } - - D3D11ES2FormatInfo(DXGI_FORMAT texFormat, DXGI_FORMAT srvFormat, DXGI_FORMAT rtvFormat, DXGI_FORMAT dsvFormat, - LoadImageFunction loadFunc) - : mTexFormat(texFormat), mDSVFormat(dsvFormat), mRTVFormat(rtvFormat), mSRVFormat(srvFormat), - mLoadImageFunction(loadFunc) - { } -}; - -// ES2 internal formats can map to DXGI formats and loading functions -typedef std::pair D3D11ES2FormatPair; -typedef std::map D3D11ES2FormatMap; - -static D3D11ES2FormatMap BuildD3D11ES2FormatMap() -{ - D3D11ES2FormatMap map; - - // | Internal format | | Texture format | SRV format | RTV format | DSV format | Load function | - map.insert(D3D11ES2FormatPair(GL_NONE, D3D11ES2FormatInfo(DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, UnreachableLoadFunction ))); - map.insert(D3D11ES2FormatPair(GL_DEPTH_COMPONENT16, D3D11ES2FormatInfo(DXGI_FORMAT_R16_TYPELESS, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D16_UNORM, UnreachableLoadFunction ))); - map.insert(D3D11ES2FormatPair(GL_DEPTH_COMPONENT32_OES, D3D11ES2FormatInfo(DXGI_FORMAT_R32_TYPELESS, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D32_FLOAT, UnreachableLoadFunction ))); - map.insert(D3D11ES2FormatPair(GL_DEPTH24_STENCIL8_OES, D3D11ES2FormatInfo(DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT, UnreachableLoadFunction ))); - map.insert(D3D11ES2FormatPair(GL_STENCIL_INDEX8, D3D11ES2FormatInfo(DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_X24_TYPELESS_G8_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT, UnreachableLoadFunction ))); - - map.insert(D3D11ES2FormatPair(GL_RGBA32F_EXT, D3D11ES2FormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN, loadRGBAFloatDataToRGBA ))); - map.insert(D3D11ES2FormatPair(GL_RGB32F_EXT, D3D11ES2FormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN, loadRGBFloatDataToRGBA ))); - map.insert(D3D11ES2FormatPair(GL_ALPHA32F_EXT, D3D11ES2FormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN, loadAlphaFloatDataToRGBA ))); - map.insert(D3D11ES2FormatPair(GL_LUMINANCE32F_EXT, D3D11ES2FormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN, loadLuminanceFloatDataToRGBA ))); - map.insert(D3D11ES2FormatPair(GL_LUMINANCE_ALPHA32F_EXT, D3D11ES2FormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN, loadLuminanceAlphaFloatDataToRGBA ))); - - map.insert(D3D11ES2FormatPair(GL_RGBA16F_EXT, D3D11ES2FormatInfo(DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN, loadRGBAHalfFloatDataToRGBA ))); - map.insert(D3D11ES2FormatPair(GL_RGB16F_EXT, D3D11ES2FormatInfo(DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN, loadRGBHalfFloatDataToRGBA ))); - map.insert(D3D11ES2FormatPair(GL_ALPHA16F_EXT, D3D11ES2FormatInfo(DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN, loadAlphaHalfFloatDataToRGBA ))); - map.insert(D3D11ES2FormatPair(GL_LUMINANCE16F_EXT, D3D11ES2FormatInfo(DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN, loadLuminanceHalfFloatDataToRGBA ))); - map.insert(D3D11ES2FormatPair(GL_LUMINANCE_ALPHA16F_EXT, D3D11ES2FormatInfo(DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN, loadLuminanceAlphaHalfFloatDataToRGBA ))); - - map.insert(D3D11ES2FormatPair(GL_ALPHA8_EXT, D3D11ES2FormatInfo(DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_UNKNOWN, loadAlphaDataToNative ))); - map.insert(D3D11ES2FormatPair(GL_LUMINANCE8_EXT, D3D11ES2FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN, loadLuminanceDataToBGRA ))); - map.insert(D3D11ES2FormatPair(GL_LUMINANCE8_ALPHA8_EXT, D3D11ES2FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN, loadLuminanceAlphaDataToBGRA ))); - - map.insert(D3D11ES2FormatPair(GL_RGB8_OES, D3D11ES2FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN, loadRGBUByteDataToRGBA ))); - map.insert(D3D11ES2FormatPair(GL_RGB565, D3D11ES2FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN, loadRGB565DataToRGBA ))); - map.insert(D3D11ES2FormatPair(GL_RGBA8_OES, D3D11ES2FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN, loadRGBAUByteDataToNative ))); - map.insert(D3D11ES2FormatPair(GL_RGBA4, D3D11ES2FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN, loadRGBA4444DataToRGBA ))); - map.insert(D3D11ES2FormatPair(GL_RGB5_A1, D3D11ES2FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN, loadRGBA5551DataToRGBA ))); - map.insert(D3D11ES2FormatPair(GL_BGRA8_EXT, D3D11ES2FormatInfo(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN, loadBGRADataToBGRA ))); - map.insert(D3D11ES2FormatPair(GL_BGRA4_ANGLEX, D3D11ES2FormatInfo(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN, loadRGBA4444DataToRGBA ))); - map.insert(D3D11ES2FormatPair(GL_BGR5_A1_ANGLEX, D3D11ES2FormatInfo(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN, loadRGBA5551DataToRGBA ))); - - // From GL_EXT_texture_rg - map.insert(D3D11ES2FormatPair(GL_R8_EXT, D3D11ES2FormatInfo(DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_UNKNOWN, loadToNative ))); - map.insert(D3D11ES2FormatPair(GL_R32F_EXT, D3D11ES2FormatInfo(DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_UNKNOWN, loadToNative ))); - map.insert(D3D11ES2FormatPair(GL_R16F_EXT, D3D11ES2FormatInfo(DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_UNKNOWN, loadToNative ))); - map.insert(D3D11ES2FormatPair(GL_RG8_EXT, D3D11ES2FormatInfo(DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_UNKNOWN, loadToNative ))); - map.insert(D3D11ES2FormatPair(GL_RG32F_EXT, D3D11ES2FormatInfo(DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_UNKNOWN, loadToNative ))); - map.insert(D3D11ES2FormatPair(GL_RG16F_EXT, D3D11ES2FormatInfo(DXGI_FORMAT_R16G16_FLOAT, DXGI_FORMAT_R16G16_FLOAT, DXGI_FORMAT_R16G16_FLOAT, DXGI_FORMAT_UNKNOWN, loadToNative ))); - - map.insert(D3D11ES2FormatPair(GL_COMPRESSED_RGB_S3TC_DXT1_EXT, D3D11ES2FormatInfo(DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, loadCompressedBlockDataToNative<4, 4, 8>))); - map.insert(D3D11ES2FormatPair(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, D3D11ES2FormatInfo(DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, loadCompressedBlockDataToNative<4, 4, 8>))); - map.insert(D3D11ES2FormatPair(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, D3D11ES2FormatInfo(DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, loadCompressedBlockDataToNative<4, 4, 16>))); - map.insert(D3D11ES2FormatPair(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, D3D11ES2FormatInfo(DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, loadCompressedBlockDataToNative<4, 4, 16>))); - - return map; -} - -static bool GetD3D11ES2FormatInfo(GLenum internalFormat, GLuint clientVersion, D3D11ES2FormatInfo *outFormatInfo) -{ - static const D3D11ES2FormatMap formatMap = BuildD3D11ES2FormatMap(); - D3D11ES2FormatMap::const_iterator iter = formatMap.find(internalFormat); - if (iter != formatMap.end()) - { - if (outFormatInfo) - { - *outFormatInfo = iter->second; - } - return true; - } - else - { - return false; - } -} - -// A map to determine the pixel size and mipmap generation function of a given DXGI format -struct DXGIFormatInfo -{ - GLuint mPixelBits; - GLuint mBlockWidth; - GLuint mBlockHeight; - GLenum mComponentType; - - MipGenerationFunction mMipGenerationFunction; - ColorReadFunction mColorReadFunction; - - DXGIFormatInfo() - : mPixelBits(0), mBlockWidth(0), mBlockHeight(0), mComponentType(GL_NONE), mMipGenerationFunction(NULL), - mColorReadFunction(NULL) - { } - - DXGIFormatInfo(GLuint pixelBits, GLuint blockWidth, GLuint blockHeight, GLenum componentType, - MipGenerationFunction mipFunc, ColorReadFunction readFunc) - : mPixelBits(pixelBits), mBlockWidth(blockWidth), mBlockHeight(blockHeight), mComponentType(componentType), - mMipGenerationFunction(mipFunc), mColorReadFunction(readFunc) - { } -}; - -typedef std::map DXGIFormatInfoMap; - -void AddDXGIFormat(DXGIFormatInfoMap *map, DXGI_FORMAT dxgiFormat, GLuint pixelBits, GLuint blockWidth, GLuint blockHeight, - GLenum componentType, MipGenerationFunction mipFunc, ColorReadFunction readFunc) -{ - map->insert(std::make_pair(dxgiFormat, DXGIFormatInfo(pixelBits, blockWidth, blockHeight, componentType, mipFunc, readFunc))); -} - -static DXGIFormatInfoMap BuildDXGIFormatInfoMap() -{ - DXGIFormatInfoMap map; - - // | DXGI format |S |W |H |Component Type | Mip generation function | Color read function - AddDXGIFormat(&map, DXGI_FORMAT_UNKNOWN, 0, 0, 0, GL_NONE, NULL, NULL); - - AddDXGIFormat(&map, DXGI_FORMAT_A8_UNORM, 8, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R8_UNORM, 8, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R8G8_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_B8G8R8A8_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor); - - AddDXGIFormat(&map, DXGI_FORMAT_R8_SNORM, 8, 1, 1, GL_SIGNED_NORMALIZED, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R8G8_SNORM, 16, 1, 1, GL_SIGNED_NORMALIZED, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_SNORM, 32, 1, 1, GL_SIGNED_NORMALIZED, GenerateMip, ReadColor); - - AddDXGIFormat(&map, DXGI_FORMAT_R8_UINT, 8, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R16_UINT, 16, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R32_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R8G8_UINT, 16, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R16G16_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R32G32_UINT, 64, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32_UINT, 96, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_UINT, 64, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32A32_UINT, 128, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); - - AddDXGIFormat(&map, DXGI_FORMAT_R8_SINT, 8, 1, 1, GL_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R16_SINT, 16, 1, 1, GL_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R32_SINT, 32, 1, 1, GL_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R8G8_SINT, 16, 1, 1, GL_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R16G16_SINT, 32, 1, 1, GL_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R32G32_SINT, 64, 1, 1, GL_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32_SINT, 96, 1, 1, GL_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_SINT, 32, 1, 1, GL_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_SINT, 64, 1, 1, GL_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32A32_SINT, 128, 1, 1, GL_INT, GenerateMip, ReadColor); - - AddDXGIFormat(&map, DXGI_FORMAT_R10G10B10A2_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R10G10B10A2_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); - - AddDXGIFormat(&map, DXGI_FORMAT_R16_FLOAT, 16, 1, 1, GL_FLOAT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R16G16_FLOAT, 32, 1, 1, GL_FLOAT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_FLOAT, 64, 1, 1, GL_FLOAT, GenerateMip, ReadColor); - - AddDXGIFormat(&map, DXGI_FORMAT_R32_FLOAT, 32, 1, 1, GL_FLOAT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R32G32_FLOAT, 64, 1, 1, GL_FLOAT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32_FLOAT, 96, 1, 1, GL_FLOAT, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32A32_FLOAT, 128, 1, 1, GL_FLOAT, GenerateMip, ReadColor); - - AddDXGIFormat(&map, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, 32, 1, 1, GL_FLOAT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R11G11B10_FLOAT, 32, 1, 1, GL_FLOAT, GenerateMip, ReadColor); - - AddDXGIFormat(&map, DXGI_FORMAT_R16_TYPELESS, 16, 1, 1, GL_NONE, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_R16_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_D16_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_R24G8_TYPELESS, 32, 1, 1, GL_NONE, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, 32, 1, 1, GL_NONE, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_D24_UNORM_S8_UINT, 32, 1, 1, GL_UNSIGNED_INT, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_R32G8X24_TYPELESS, 64, 1, 1, GL_NONE, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, 64, 1, 1, GL_NONE, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, 64, 1, 1, GL_UNSIGNED_INT, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_R32_TYPELESS, 32, 1, 1, GL_NONE, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_D32_FLOAT, 32, 1, 1, GL_FLOAT, NULL, NULL); - - AddDXGIFormat(&map, DXGI_FORMAT_BC1_UNORM, 64, 4, 4, GL_UNSIGNED_NORMALIZED, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_BC2_UNORM, 128, 4, 4, GL_UNSIGNED_NORMALIZED, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_BC3_UNORM, 128, 4, 4, GL_UNSIGNED_NORMALIZED, NULL, NULL); - - // Useful formats for vertex buffers - AddDXGIFormat(&map, DXGI_FORMAT_R16_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_R16_SNORM, 16, 1, 1, GL_SIGNED_NORMALIZED, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_R16G16_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_R16G16_SNORM, 32, 1, 1, GL_SIGNED_NORMALIZED, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_UNORM, 64, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_SNORM, 64, 1, 1, GL_SIGNED_NORMALIZED, NULL, NULL); - - return map; -} - -typedef std::map DXGIToESFormatMap; - -inline void AddDXGIToESEntry(DXGIToESFormatMap *map, DXGI_FORMAT key, GLenum value) -{ - map->insert(std::make_pair(key, value)); -} - -static DXGIToESFormatMap BuildCommonDXGIToESFormatMap() -{ - DXGIToESFormatMap map; - - AddDXGIToESEntry(&map, DXGI_FORMAT_UNKNOWN, GL_NONE); - - AddDXGIToESEntry(&map, DXGI_FORMAT_A8_UNORM, GL_ALPHA8_EXT); - AddDXGIToESEntry(&map, DXGI_FORMAT_R8_UNORM, GL_R8); - AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8_UNORM, GL_RG8); - AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_UNORM, GL_RGBA8); - AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, GL_SRGB8_ALPHA8); - AddDXGIToESEntry(&map, DXGI_FORMAT_B8G8R8A8_UNORM, GL_BGRA8_EXT); - - AddDXGIToESEntry(&map, DXGI_FORMAT_R8_SNORM, GL_R8_SNORM); - AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8_SNORM, GL_RG8_SNORM); - AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_SNORM, GL_RGBA8_SNORM); - - AddDXGIToESEntry(&map, DXGI_FORMAT_R8_UINT, GL_R8UI); - AddDXGIToESEntry(&map, DXGI_FORMAT_R16_UINT, GL_R16UI); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32_UINT, GL_R32UI); - AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8_UINT, GL_RG8UI); - AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16_UINT, GL_RG16UI); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32_UINT, GL_RG32UI); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32_UINT, GL_RGB32UI); - AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_UINT, GL_RGBA8UI); - AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16B16A16_UINT, GL_RGBA16UI); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32A32_UINT, GL_RGBA32UI); - - AddDXGIToESEntry(&map, DXGI_FORMAT_R8_SINT, GL_R8I); - AddDXGIToESEntry(&map, DXGI_FORMAT_R16_SINT, GL_R16I); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32_SINT, GL_R32I); - AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8_SINT, GL_RG8I); - AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16_SINT, GL_RG16I); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32_SINT, GL_RG32I); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32_SINT, GL_RGB32I); - AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_SINT, GL_RGBA8I); - AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16B16A16_SINT, GL_RGBA16I); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32A32_SINT, GL_RGBA32I); - - AddDXGIToESEntry(&map, DXGI_FORMAT_R10G10B10A2_UNORM, GL_RGB10_A2); - AddDXGIToESEntry(&map, DXGI_FORMAT_R10G10B10A2_UINT, GL_RGB10_A2UI); - - AddDXGIToESEntry(&map, DXGI_FORMAT_R16_FLOAT, GL_R16F); - AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16_FLOAT, GL_RG16F); - AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16B16A16_FLOAT, GL_RGBA16F); - - AddDXGIToESEntry(&map, DXGI_FORMAT_R32_FLOAT, GL_R32F); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32_FLOAT, GL_RG32F); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32_FLOAT, GL_RGB32F); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32A32_FLOAT, GL_RGBA32F); - - AddDXGIToESEntry(&map, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, GL_RGB9_E5); - AddDXGIToESEntry(&map, DXGI_FORMAT_R11G11B10_FLOAT, GL_R11F_G11F_B10F); - - AddDXGIToESEntry(&map, DXGI_FORMAT_R16_TYPELESS, GL_DEPTH_COMPONENT16); - AddDXGIToESEntry(&map, DXGI_FORMAT_R16_UNORM, GL_DEPTH_COMPONENT16); - AddDXGIToESEntry(&map, DXGI_FORMAT_D16_UNORM, GL_DEPTH_COMPONENT16); - AddDXGIToESEntry(&map, DXGI_FORMAT_R24G8_TYPELESS, GL_DEPTH24_STENCIL8_OES); - AddDXGIToESEntry(&map, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, GL_DEPTH24_STENCIL8_OES); - AddDXGIToESEntry(&map, DXGI_FORMAT_D24_UNORM_S8_UINT, GL_DEPTH24_STENCIL8_OES); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32G8X24_TYPELESS, GL_DEPTH32F_STENCIL8); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, GL_DEPTH32F_STENCIL8); - AddDXGIToESEntry(&map, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, GL_DEPTH32F_STENCIL8); - - AddDXGIToESEntry(&map, DXGI_FORMAT_BC1_UNORM, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT); - AddDXGIToESEntry(&map, DXGI_FORMAT_BC2_UNORM, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE); - AddDXGIToESEntry(&map, DXGI_FORMAT_BC3_UNORM, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE); - - return map; -} - -static DXGIToESFormatMap BuildDXGIToES2FormatMap() -{ - DXGIToESFormatMap map = BuildCommonDXGIToESFormatMap(); - - AddDXGIToESEntry(&map, DXGI_FORMAT_R32_TYPELESS, GL_DEPTH_COMPONENT32_OES); - AddDXGIToESEntry(&map, DXGI_FORMAT_D32_FLOAT, GL_DEPTH_COMPONENT32_OES); - - return map; -} - -static DXGIToESFormatMap BuildDXGIToES3FormatMap() -{ - DXGIToESFormatMap map = BuildCommonDXGIToESFormatMap(); - - AddDXGIToESEntry(&map, DXGI_FORMAT_R32_TYPELESS, GL_DEPTH_COMPONENT32F); - AddDXGIToESEntry(&map, DXGI_FORMAT_D32_FLOAT, GL_DEPTH_COMPONENT32F); - - return map; -} - -static const DXGIFormatInfoMap &GetDXGIFormatInfoMap() -{ - static const DXGIFormatInfoMap infoMap = BuildDXGIFormatInfoMap(); - return infoMap; -} - -static bool GetDXGIFormatInfo(DXGI_FORMAT format, DXGIFormatInfo *outFormatInfo) -{ - const DXGIFormatInfoMap &infoMap = GetDXGIFormatInfoMap(); - DXGIFormatInfoMap::const_iterator iter = infoMap.find(format); - if (iter != infoMap.end()) - { - if (outFormatInfo) - { - *outFormatInfo = iter->second; - } - return true; - } - else - { - return false; - } -} - -static d3d11::DXGIFormatSet BuildAllDXGIFormatSet() -{ - d3d11::DXGIFormatSet set; - - const DXGIFormatInfoMap &infoMap = GetDXGIFormatInfoMap(); - for (DXGIFormatInfoMap::const_iterator i = infoMap.begin(); i != infoMap.end(); ++i) - { - set.insert(i->first); - } - - return set; -} - -struct D3D11FastCopyFormat -{ - DXGI_FORMAT mSourceFormat; - GLenum mDestFormat; - GLenum mDestType; - - D3D11FastCopyFormat(DXGI_FORMAT sourceFormat, GLenum destFormat, GLenum destType) - : mSourceFormat(sourceFormat), mDestFormat(destFormat), mDestType(destType) - { } - - bool operator<(const D3D11FastCopyFormat& other) const - { - return memcmp(this, &other, sizeof(D3D11FastCopyFormat)) < 0; - } -}; - -typedef std::map D3D11FastCopyMap; -typedef std::pair D3D11FastCopyPair; - -static D3D11FastCopyMap BuildFastCopyMap() -{ - D3D11FastCopyMap map; - - map.insert(D3D11FastCopyPair(D3D11FastCopyFormat(DXGI_FORMAT_B8G8R8A8_UNORM, GL_RGBA, GL_UNSIGNED_BYTE), CopyBGRAUByteToRGBAUByte)); - - return map; -} - -struct DXGIDepthStencilInfo -{ - unsigned int mDepthBits; - unsigned int mDepthOffset; - unsigned int mStencilBits; - unsigned int mStencilOffset; - - DXGIDepthStencilInfo() - : mDepthBits(0), mDepthOffset(0), mStencilBits(0), mStencilOffset(0) - { } - - DXGIDepthStencilInfo(unsigned int depthBits, unsigned int depthOffset, unsigned int stencilBits, unsigned int stencilOffset) - : mDepthBits(depthBits), mDepthOffset(depthOffset), mStencilBits(stencilBits), mStencilOffset(stencilOffset) - { } -}; - -typedef std::map DepthStencilInfoMap; -typedef std::pair DepthStencilInfoPair; - -static DepthStencilInfoMap BuildDepthStencilInfoMap() -{ - DepthStencilInfoMap map; - - map.insert(DepthStencilInfoPair(DXGI_FORMAT_R16_TYPELESS, DXGIDepthStencilInfo(16, 0, 0, 0))); - map.insert(DepthStencilInfoPair(DXGI_FORMAT_R16_UNORM, DXGIDepthStencilInfo(16, 0, 0, 0))); - map.insert(DepthStencilInfoPair(DXGI_FORMAT_D16_UNORM, DXGIDepthStencilInfo(16, 0, 0, 0))); - - map.insert(DepthStencilInfoPair(DXGI_FORMAT_R24G8_TYPELESS, DXGIDepthStencilInfo(24, 0, 8, 24))); - map.insert(DepthStencilInfoPair(DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGIDepthStencilInfo(24, 0, 8, 24))); - map.insert(DepthStencilInfoPair(DXGI_FORMAT_D24_UNORM_S8_UINT, DXGIDepthStencilInfo(24, 0, 8, 24))); - - map.insert(DepthStencilInfoPair(DXGI_FORMAT_R32_TYPELESS, DXGIDepthStencilInfo(32, 0, 0, 0))); - map.insert(DepthStencilInfoPair(DXGI_FORMAT_R32_FLOAT, DXGIDepthStencilInfo(32, 0, 0, 0))); - map.insert(DepthStencilInfoPair(DXGI_FORMAT_D32_FLOAT, DXGIDepthStencilInfo(32, 0, 0, 0))); - - map.insert(DepthStencilInfoPair(DXGI_FORMAT_R32G8X24_TYPELESS, DXGIDepthStencilInfo(32, 0, 8, 32))); - map.insert(DepthStencilInfoPair(DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, DXGIDepthStencilInfo(32, 0, 8, 32))); - map.insert(DepthStencilInfoPair(DXGI_FORMAT_D32_FLOAT_S8X24_UINT, DXGIDepthStencilInfo(32, 0, 8, 32))); - - return map; -} - -static const DepthStencilInfoMap &GetDepthStencilInfoMap() -{ - static const DepthStencilInfoMap infoMap = BuildDepthStencilInfoMap(); - return infoMap; -} - -bool GetDepthStencilInfo(DXGI_FORMAT format, DXGIDepthStencilInfo *outDepthStencilInfo) -{ - const DepthStencilInfoMap& infoMap = GetDepthStencilInfoMap(); - DepthStencilInfoMap::const_iterator iter = infoMap.find(format); - if (iter != infoMap.end()) - { - if (outDepthStencilInfo) - { - *outDepthStencilInfo = iter->second; - } - return true; - } - else - { - return false; - } -} - -struct SwizzleSizeType -{ - unsigned int mMaxComponentSize; - GLenum mComponentType; - - SwizzleSizeType() - : mMaxComponentSize(0), mComponentType(GL_NONE) - { } - - SwizzleSizeType(unsigned int maxComponentSize, GLenum componentType) - : mMaxComponentSize(maxComponentSize), mComponentType(componentType) - { } - - bool operator<(const SwizzleSizeType& other) const - { - return (mMaxComponentSize != other.mMaxComponentSize) ? (mMaxComponentSize < other.mMaxComponentSize) - : (mComponentType < other.mComponentType); - } -}; - -struct SwizzleFormatInfo -{ - DXGI_FORMAT mTexFormat; - DXGI_FORMAT mSRVFormat; - DXGI_FORMAT mRTVFormat; - - SwizzleFormatInfo() - : mTexFormat(DXGI_FORMAT_UNKNOWN), mSRVFormat(DXGI_FORMAT_UNKNOWN), mRTVFormat(DXGI_FORMAT_UNKNOWN) - { } - - SwizzleFormatInfo(DXGI_FORMAT texFormat, DXGI_FORMAT srvFormat, DXGI_FORMAT rtvFormat) - : mTexFormat(texFormat), mSRVFormat(srvFormat), mRTVFormat(rtvFormat) - { } -}; - -typedef std::map SwizzleInfoMap; -typedef std::pair SwizzleInfoPair; - -static SwizzleInfoMap BuildSwizzleInfoMap() -{ - SwizzleInfoMap map; - - map.insert(SwizzleInfoPair(SwizzleSizeType( 8, GL_UNSIGNED_NORMALIZED), SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM ))); - map.insert(SwizzleInfoPair(SwizzleSizeType(16, GL_UNSIGNED_NORMALIZED), SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R16G16B16A16_UNORM))); - map.insert(SwizzleInfoPair(SwizzleSizeType(24, GL_UNSIGNED_NORMALIZED), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT))); - map.insert(SwizzleInfoPair(SwizzleSizeType(32, GL_UNSIGNED_NORMALIZED), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT))); - - map.insert(SwizzleInfoPair(SwizzleSizeType( 8, GL_SIGNED_NORMALIZED ), SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM ))); - - map.insert(SwizzleInfoPair(SwizzleSizeType(16, GL_FLOAT ), SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT))); - map.insert(SwizzleInfoPair(SwizzleSizeType(32, GL_FLOAT ), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT))); - - map.insert(SwizzleInfoPair(SwizzleSizeType( 8, GL_UNSIGNED_INT ), SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT ))); - map.insert(SwizzleInfoPair(SwizzleSizeType(16, GL_UNSIGNED_INT ), SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT ))); - map.insert(SwizzleInfoPair(SwizzleSizeType(32, GL_UNSIGNED_INT ), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT ))); - - map.insert(SwizzleInfoPair(SwizzleSizeType( 8, GL_INT ), SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT ))); - map.insert(SwizzleInfoPair(SwizzleSizeType(16, GL_INT ), SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT ))); - map.insert(SwizzleInfoPair(SwizzleSizeType(32, GL_INT ), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT ))); - - return map; -} -typedef std::pair InternalFormatInitializerPair; -typedef std::map InternalFormatInitializerMap; - -static InternalFormatInitializerMap BuildInternalFormatInitializerMap() -{ - InternalFormatInitializerMap map; - - map.insert(InternalFormatInitializerPair(GL_RGB8, initialize4ComponentData )); - map.insert(InternalFormatInitializerPair(GL_RGB565, initialize4ComponentData )); - map.insert(InternalFormatInitializerPair(GL_SRGB8, initialize4ComponentData )); - map.insert(InternalFormatInitializerPair(GL_RGB16F, initialize4ComponentData)); - map.insert(InternalFormatInitializerPair(GL_RGB32F, initialize4ComponentData)); - map.insert(InternalFormatInitializerPair(GL_RGB8UI, initialize4ComponentData )); - map.insert(InternalFormatInitializerPair(GL_RGB8I, initialize4ComponentData )); - map.insert(InternalFormatInitializerPair(GL_RGB16UI, initialize4ComponentData )); - map.insert(InternalFormatInitializerPair(GL_RGB16I, initialize4ComponentData )); - map.insert(InternalFormatInitializerPair(GL_RGB32UI, initialize4ComponentData )); - map.insert(InternalFormatInitializerPair(GL_RGB32I, initialize4ComponentData )); - - return map; -} - -static const SwizzleInfoMap &GetSwizzleInfoMap() -{ - static const SwizzleInfoMap map = BuildSwizzleInfoMap(); - return map; -} - -static const SwizzleFormatInfo GetSwizzleFormatInfo(GLint internalFormat, GLuint clientVersion) -{ - // Get the maximum sized component - unsigned int maxBits = 1; - - if (gl::IsFormatCompressed(internalFormat, clientVersion)) - { - unsigned int compressedBitsPerBlock = gl::GetPixelBytes(internalFormat, clientVersion) * 8; - unsigned int blockSize = gl::GetCompressedBlockWidth(internalFormat, clientVersion) * - gl::GetCompressedBlockHeight(internalFormat, clientVersion); - maxBits = std::max(compressedBitsPerBlock / blockSize, maxBits); - } - else - { - maxBits = std::max(maxBits, gl::GetAlphaBits( internalFormat, clientVersion)); - maxBits = std::max(maxBits, gl::GetRedBits( internalFormat, clientVersion)); - maxBits = std::max(maxBits, gl::GetGreenBits( internalFormat, clientVersion)); - maxBits = std::max(maxBits, gl::GetBlueBits( internalFormat, clientVersion)); - maxBits = std::max(maxBits, gl::GetLuminanceBits(internalFormat, clientVersion)); - maxBits = std::max(maxBits, gl::GetDepthBits( internalFormat, clientVersion)); - } - - maxBits = roundUp(maxBits, 8U); - - GLenum componentType = gl::GetComponentType(internalFormat, clientVersion); - - const SwizzleInfoMap &map = GetSwizzleInfoMap(); - SwizzleInfoMap::const_iterator iter = map.find(SwizzleSizeType(maxBits, componentType)); - - if (iter != map.end()) - { - return iter->second; - } - else - { - UNREACHABLE(); - static const SwizzleFormatInfo defaultFormatInfo; - return defaultFormatInfo; - } -} - -static const InternalFormatInitializerMap &GetInternalFormatInitializerMap() -{ - static const InternalFormatInitializerMap map = BuildInternalFormatInitializerMap(); - return map; -} - -namespace d3d11 -{ - -MipGenerationFunction GetMipGenerationFunction(DXGI_FORMAT format) -{ - DXGIFormatInfo formatInfo; - if (GetDXGIFormatInfo(format, &formatInfo)) - { - return formatInfo.mMipGenerationFunction; - } - else - { - UNREACHABLE(); - return NULL; - } -} - -LoadImageFunction GetImageLoadFunction(GLenum internalFormat, GLenum type, GLuint clientVersion) -{ - if (clientVersion == 2) - { - D3D11ES2FormatInfo d3d11FormatInfo; - if (GetD3D11ES2FormatInfo(internalFormat, clientVersion, &d3d11FormatInfo)) - { - return d3d11FormatInfo.mLoadImageFunction; - } - else - { - UNREACHABLE(); - return NULL; - } - } - else if (clientVersion == 3) - { - static const D3D11LoadFunctionMap loadImageMap = buildD3D11LoadFunctionMap(); - D3D11LoadFunctionMap::const_iterator iter = loadImageMap.find(InternalFormatTypePair(internalFormat, type)); - if (iter != loadImageMap.end()) - { - return iter->second; - } - else - { - UNREACHABLE(); - return NULL; - } - } - else - { - UNREACHABLE(); - return NULL; - } -} - -GLuint GetFormatPixelBytes(DXGI_FORMAT format) -{ - DXGIFormatInfo dxgiFormatInfo; - if (GetDXGIFormatInfo(format, &dxgiFormatInfo)) - { - return dxgiFormatInfo.mPixelBits / 8; - } - else - { - UNREACHABLE(); - return 0; - } -} - -GLuint GetBlockWidth(DXGI_FORMAT format) -{ - DXGIFormatInfo dxgiFormatInfo; - if (GetDXGIFormatInfo(format, &dxgiFormatInfo)) - { - return dxgiFormatInfo.mBlockWidth; - } - else - { - UNREACHABLE(); - return 0; - } -} - -GLuint GetBlockHeight(DXGI_FORMAT format) -{ - DXGIFormatInfo dxgiFormatInfo; - if (GetDXGIFormatInfo(format, &dxgiFormatInfo)) - { - return dxgiFormatInfo.mBlockHeight; - } - else - { - UNREACHABLE(); - return 0; - } -} - -GLenum GetComponentType(DXGI_FORMAT format) -{ - DXGIFormatInfo dxgiFormatInfo; - if (GetDXGIFormatInfo(format, &dxgiFormatInfo)) - { - return dxgiFormatInfo.mComponentType; - } - else - { - UNREACHABLE(); - return GL_NONE; - } -} - -GLuint GetDepthBits(DXGI_FORMAT format) -{ - DXGIDepthStencilInfo dxgiDSInfo; - if (GetDepthStencilInfo(format, &dxgiDSInfo)) - { - return dxgiDSInfo.mDepthBits; - } - else - { - // Since the depth stencil info map does not contain all used DXGI formats, - // we should not assert that the format exists - return 0; - } -} - -GLuint GetDepthOffset(DXGI_FORMAT format) -{ - DXGIDepthStencilInfo dxgiDSInfo; - if (GetDepthStencilInfo(format, &dxgiDSInfo)) - { - return dxgiDSInfo.mDepthOffset; - } - else - { - // Since the depth stencil info map does not contain all used DXGI formats, - // we should not assert that the format exists - return 0; - } -} - -GLuint GetStencilBits(DXGI_FORMAT format) -{ - DXGIDepthStencilInfo dxgiDSInfo; - if (GetDepthStencilInfo(format, &dxgiDSInfo)) - { - return dxgiDSInfo.mStencilBits; - } - else - { - // Since the depth stencil info map does not contain all used DXGI formats, - // we should not assert that the format exists - return 0; - } -} - -GLuint GetStencilOffset(DXGI_FORMAT format) -{ - DXGIDepthStencilInfo dxgiDSInfo; - if (GetDepthStencilInfo(format, &dxgiDSInfo)) - { - return dxgiDSInfo.mStencilOffset; - } - else - { - // Since the depth stencil info map does not contain all used DXGI formats, - // we should not assert that the format exists - return 0; - } -} - -void MakeValidSize(bool isImage, DXGI_FORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset) -{ - DXGIFormatInfo dxgiFormatInfo; - if (GetDXGIFormatInfo(format, &dxgiFormatInfo)) - { - int upsampleCount = 0; - - GLsizei blockWidth = dxgiFormatInfo.mBlockWidth; - GLsizei blockHeight = dxgiFormatInfo.mBlockHeight; - - // Don't expand the size of full textures that are at least (blockWidth x blockHeight) already. - if (isImage || *requestWidth < blockWidth || *requestHeight < blockHeight) - { - while (*requestWidth % blockWidth != 0 || *requestHeight % blockHeight != 0) - { - *requestWidth <<= 1; - *requestHeight <<= 1; - upsampleCount++; - } - } - *levelOffset = upsampleCount; - } - else - { - UNREACHABLE(); - } -} - -const DXGIFormatSet &GetAllUsedDXGIFormats() -{ - static DXGIFormatSet formatSet = BuildAllDXGIFormatSet(); - return formatSet; -} - -ColorReadFunction GetColorReadFunction(DXGI_FORMAT format) -{ - DXGIFormatInfo dxgiFormatInfo; - if (GetDXGIFormatInfo(format, &dxgiFormatInfo)) - { - return dxgiFormatInfo.mColorReadFunction; - } - else - { - UNREACHABLE(); - return NULL; - } -} - -ColorCopyFunction GetFastCopyFunction(DXGI_FORMAT sourceFormat, GLenum destFormat, GLenum destType) -{ - static const D3D11FastCopyMap fastCopyMap = BuildFastCopyMap(); - D3D11FastCopyMap::const_iterator iter = fastCopyMap.find(D3D11FastCopyFormat(sourceFormat, destFormat, destType)); - return (iter != fastCopyMap.end()) ? iter->second : NULL; -} - -} - -namespace gl_d3d11 -{ - -DXGI_FORMAT GetTexFormat(GLenum internalFormat, GLuint clientVersion) -{ - if (clientVersion == 2) - { - D3D11ES2FormatInfo d3d11FormatInfo; - if (GetD3D11ES2FormatInfo(internalFormat, clientVersion, &d3d11FormatInfo)) - { - return d3d11FormatInfo.mTexFormat; - } - else - { - UNREACHABLE(); - return DXGI_FORMAT_UNKNOWN; - } - } - else if (clientVersion == 3) - { - D3D11ES3FormatInfo d3d11FormatInfo; - if (GetD3D11ES3FormatInfo(internalFormat, clientVersion, &d3d11FormatInfo)) - { - return d3d11FormatInfo.mTexFormat; - } - else - { - UNREACHABLE(); - return DXGI_FORMAT_UNKNOWN; - } - } - else - { - UNREACHABLE(); - return DXGI_FORMAT_UNKNOWN; - } -} - -DXGI_FORMAT GetSRVFormat(GLenum internalFormat, GLuint clientVersion) -{ - if (clientVersion == 2) - { - D3D11ES2FormatInfo d3d11FormatInfo; - if (GetD3D11ES2FormatInfo(internalFormat, clientVersion, &d3d11FormatInfo)) - { - return d3d11FormatInfo.mSRVFormat; - } - else - { - UNREACHABLE(); - return DXGI_FORMAT_UNKNOWN; - } - } - else if (clientVersion == 3) - { - D3D11ES3FormatInfo d3d11FormatInfo; - if (GetD3D11ES3FormatInfo(internalFormat, clientVersion, &d3d11FormatInfo)) - { - return d3d11FormatInfo.mSRVFormat; - } - else - { - UNREACHABLE(); - return DXGI_FORMAT_UNKNOWN; - } - } - else - { - UNREACHABLE(); - return DXGI_FORMAT_UNKNOWN; - } -} - -DXGI_FORMAT GetRTVFormat(GLenum internalFormat, GLuint clientVersion) -{ - if (clientVersion == 2) - { - D3D11ES2FormatInfo d3d11FormatInfo; - if (GetD3D11ES2FormatInfo(internalFormat, clientVersion, &d3d11FormatInfo)) - { - return d3d11FormatInfo.mRTVFormat; - } - else - { - UNREACHABLE(); - return DXGI_FORMAT_UNKNOWN; - } - } - else if (clientVersion == 3) - { - D3D11ES3FormatInfo d3d11FormatInfo; - if (GetD3D11ES3FormatInfo(internalFormat, clientVersion, &d3d11FormatInfo)) - { - return d3d11FormatInfo.mRTVFormat; - } - else - { - UNREACHABLE(); - return DXGI_FORMAT_UNKNOWN; - } - } - else - { - UNREACHABLE(); - return DXGI_FORMAT_UNKNOWN; - } -} - -DXGI_FORMAT GetDSVFormat(GLenum internalFormat, GLuint clientVersion) -{ - if (clientVersion == 2) - { - D3D11ES2FormatInfo d3d11FormatInfo; - if (GetD3D11ES2FormatInfo(internalFormat, clientVersion, &d3d11FormatInfo)) - { - return d3d11FormatInfo.mDSVFormat; - } - else - { - return DXGI_FORMAT_UNKNOWN; - } - } - else if (clientVersion == 3) - { - D3D11ES3FormatInfo d3d11FormatInfo; - if (GetD3D11ES3FormatInfo(internalFormat, clientVersion, &d3d11FormatInfo)) - { - return d3d11FormatInfo.mDSVFormat; - } - else - { - return DXGI_FORMAT_UNKNOWN; - } - } - else - { - UNREACHABLE(); - return DXGI_FORMAT_UNKNOWN; - } -} - -// Given a GL internal format, this function returns the DSV format if it is depth- or stencil-renderable, -// the RTV format if it is color-renderable, and the (nonrenderable) texture format otherwise. -DXGI_FORMAT GetRenderableFormat(GLenum internalFormat, GLuint clientVersion) -{ - DXGI_FORMAT targetFormat = GetDSVFormat(internalFormat, clientVersion); - if (targetFormat == DXGI_FORMAT_UNKNOWN) - targetFormat = GetRTVFormat(internalFormat, clientVersion); - if (targetFormat == DXGI_FORMAT_UNKNOWN) - targetFormat = GetTexFormat(internalFormat, clientVersion); - - return targetFormat; -} - -DXGI_FORMAT GetSwizzleTexFormat(GLint internalFormat, const Renderer *renderer) -{ - GLuint clientVersion = renderer->getCurrentClientVersion(); - if (gl::GetComponentCount(internalFormat, clientVersion) != 4 || !gl::IsColorRenderingSupported(internalFormat, renderer)) - { - const SwizzleFormatInfo &swizzleInfo = GetSwizzleFormatInfo(internalFormat, clientVersion); - return swizzleInfo.mTexFormat; - } - else - { - return GetTexFormat(internalFormat, clientVersion); - } -} - -DXGI_FORMAT GetSwizzleSRVFormat(GLint internalFormat, const Renderer *renderer) -{ - GLuint clientVersion = renderer->getCurrentClientVersion(); - if (gl::GetComponentCount(internalFormat, clientVersion) != 4 || !gl::IsColorRenderingSupported(internalFormat, renderer)) - { - const SwizzleFormatInfo &swizzleInfo = GetSwizzleFormatInfo(internalFormat, clientVersion); - return swizzleInfo.mSRVFormat; - } - else - { - return GetTexFormat(internalFormat, clientVersion); - } -} - -DXGI_FORMAT GetSwizzleRTVFormat(GLint internalFormat, const Renderer *renderer) -{ - GLuint clientVersion = renderer->getCurrentClientVersion(); - if (gl::GetComponentCount(internalFormat, clientVersion) != 4 || !gl::IsColorRenderingSupported(internalFormat, renderer)) - { - const SwizzleFormatInfo &swizzleInfo = GetSwizzleFormatInfo(internalFormat, clientVersion); - return swizzleInfo.mRTVFormat; - } - else - { - return GetTexFormat(internalFormat, clientVersion); - } -} - -bool RequiresTextureDataInitialization(GLint internalFormat) -{ - const InternalFormatInitializerMap &map = GetInternalFormatInitializerMap(); - return map.find(internalFormat) != map.end(); -} - -InitializeTextureDataFunction GetTextureDataInitializationFunction(GLint internalFormat) -{ - const InternalFormatInitializerMap &map = GetInternalFormatInitializerMap(); - InternalFormatInitializerMap::const_iterator iter = map.find(internalFormat); - if (iter != map.end()) - { - return iter->second; - } - else - { - UNREACHABLE(); - return NULL; - } -} - -struct D3D11VertexFormatInfo -{ - rx::VertexConversionType mConversionType; - DXGI_FORMAT mNativeFormat; - VertexCopyFunction mCopyFunction; - - D3D11VertexFormatInfo() - : mConversionType(VERTEX_CONVERT_NONE), - mNativeFormat(DXGI_FORMAT_UNKNOWN), - mCopyFunction(NULL) - {} - - D3D11VertexFormatInfo(VertexConversionType conversionType, DXGI_FORMAT nativeFormat, VertexCopyFunction copyFunction) - : mConversionType(conversionType), - mNativeFormat(nativeFormat), - mCopyFunction(copyFunction) - {} -}; - -typedef std::map D3D11VertexFormatInfoMap; - -typedef std::pair D3D11VertexFormatPair; - -static void addVertexFormatInfo(D3D11VertexFormatInfoMap *map, GLenum inputType, GLboolean normalized, GLuint componentCount, - VertexConversionType conversionType, DXGI_FORMAT nativeFormat, VertexCopyFunction copyFunction) -{ - gl::VertexFormat inputFormat(inputType, normalized, componentCount, false); - map->insert(D3D11VertexFormatPair(inputFormat, D3D11VertexFormatInfo(conversionType, nativeFormat, copyFunction))); -} - -static void addIntegerVertexFormatInfo(D3D11VertexFormatInfoMap *map, GLenum inputType, GLuint componentCount, - VertexConversionType conversionType, DXGI_FORMAT nativeFormat, VertexCopyFunction copyFunction) -{ - gl::VertexFormat inputFormat(inputType, GL_FALSE, componentCount, true); - map->insert(D3D11VertexFormatPair(inputFormat, D3D11VertexFormatInfo(conversionType, nativeFormat, copyFunction))); -} - -static D3D11VertexFormatInfoMap BuildD3D11VertexFormatInfoMap() -{ - D3D11VertexFormatInfoMap map; - - // TODO: column legend - - // - // Float formats - // - - // GL_BYTE -- un-normalized - addVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_SINT, ©VertexData); - addVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8_SINT, ©VertexData); - addVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_SINT, ©VertexData); - addVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8B8A8_SINT, ©VertexData); - - // GL_BYTE -- normalized - addVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_SNORM, ©VertexData); - addVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_SNORM, ©VertexData); - addVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_SNORM, ©VertexData); - addVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_SNORM, ©VertexData); - - // GL_UNSIGNED_BYTE -- un-normalized - addVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_UINT, ©VertexData); - addVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8_UINT, ©VertexData); - addVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT, ©VertexData); - addVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8B8A8_UINT, ©VertexData); - - // GL_UNSIGNED_BYTE -- normalized - addVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_UNORM, ©VertexData); - addVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_UNORM, ©VertexData); - addVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM, ©VertexData); - addVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_UNORM, ©VertexData); - - // GL_SHORT -- un-normalized - addVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16_SINT, ©VertexData); - addVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16_SINT, ©VertexData); - addVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT, ©VertexData); - addVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16B16A16_SINT, ©VertexData); - - // GL_SHORT -- normalized - addVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_SNORM, ©VertexData); - addVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_SNORM, ©VertexData); - addVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM, ©VertexData); - addVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_SNORM, ©VertexData); - - // GL_UNSIGNED_SHORT -- un-normalized - addVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16_UINT, ©VertexData); - addVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16_UINT, ©VertexData); - addVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_UINT, ©VertexData); - addVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16B16A16_UINT, ©VertexData); - - // GL_UNSIGNED_SHORT -- normalized - addVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_UNORM, ©VertexData); - addVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_UNORM, ©VertexData); - addVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_UNORM, ©VertexData); - addVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_UNORM, ©VertexData); - - // GL_INT -- un-normalized - addVertexFormatInfo(&map, GL_INT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32_SINT, ©VertexData); - addVertexFormatInfo(&map, GL_INT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32_SINT, ©VertexData); - addVertexFormatInfo(&map, GL_INT, GL_FALSE, 3, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32_SINT, ©VertexData); - addVertexFormatInfo(&map, GL_INT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32A32_SINT, ©VertexData); - - // GL_INT -- normalized - addVertexFormatInfo(&map, GL_INT, GL_TRUE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT, ©ToFloatVertexData); - addVertexFormatInfo(&map, GL_INT, GL_TRUE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, ©ToFloatVertexData); - addVertexFormatInfo(&map, GL_INT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, ©ToFloatVertexData); - addVertexFormatInfo(&map, GL_INT, GL_TRUE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, ©ToFloatVertexData); - - // GL_UNSIGNED_INT -- un-normalized - addVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32_UINT, ©VertexData); - addVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32_UINT, ©VertexData); - addVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 3, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32_UINT, ©VertexData); - addVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32A32_UINT, ©VertexData); - - // GL_UNSIGNED_INT -- normalized - addVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_FLOAT, ©ToFloatVertexData); - addVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_FLOAT, ©ToFloatVertexData); - addVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, ©ToFloatVertexData); - addVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_FLOAT, ©ToFloatVertexData); - - // GL_FIXED - addVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT, ©FixedVertexData<1>); - addVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, ©FixedVertexData<2>); - addVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, ©FixedVertexData<3>); - addVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, ©FixedVertexData<4>); - - // GL_HALF_FLOAT - addVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_FLOAT, ©VertexData); - addVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_FLOAT, ©VertexData); - addVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_FLOAT, ©VertexData); - addVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_FLOAT, ©VertexData); - - // GL_FLOAT - addVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_FLOAT, ©VertexData); - addVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_FLOAT, ©VertexData); - addVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 3, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_FLOAT, ©VertexData); - addVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_FLOAT, ©VertexData); - - // GL_INT_2_10_10_10_REV - addVertexFormatInfo(&map, GL_INT_2_10_10_10_REV, GL_FALSE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, ©PackedVertexData); - addVertexFormatInfo(&map, GL_INT_2_10_10_10_REV, GL_TRUE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, ©PackedVertexData); - - // GL_UNSIGNED_INT_2_10_10_10_REV - addVertexFormatInfo(&map, GL_UNSIGNED_INT_2_10_10_10_REV, GL_FALSE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, ©PackedVertexData); - addVertexFormatInfo(&map, GL_UNSIGNED_INT_2_10_10_10_REV, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UNORM, ©PackedUnsignedVertexData); - - // - // Integer Formats - // - - // GL_BYTE - addIntegerVertexFormatInfo(&map, GL_BYTE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_SINT, ©VertexData); - addIntegerVertexFormatInfo(&map, GL_BYTE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_SINT, ©VertexData); - addIntegerVertexFormatInfo(&map, GL_BYTE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_SINT, ©VertexData); - addIntegerVertexFormatInfo(&map, GL_BYTE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_SINT, ©VertexData); - - // GL_UNSIGNED_BYTE - addIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_UINT, ©VertexData); - addIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_UINT, ©VertexData); - addIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UINT, ©VertexData); - addIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_UINT, ©VertexData); - - // GL_SHORT - addIntegerVertexFormatInfo(&map, GL_SHORT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_SINT, ©VertexData); - addIntegerVertexFormatInfo(&map, GL_SHORT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_SINT, ©VertexData); - addIntegerVertexFormatInfo(&map, GL_SHORT, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SINT, ©VertexData); - addIntegerVertexFormatInfo(&map, GL_SHORT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_SINT, ©VertexData); - - // GL_UNSIGNED_SHORT - addIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_UINT, ©VertexData); - addIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_UINT, ©VertexData); - addIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_UINT, ©VertexData); - addIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_UINT, ©VertexData); - - // GL_INT - addIntegerVertexFormatInfo(&map, GL_INT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_SINT, ©VertexData); - addIntegerVertexFormatInfo(&map, GL_INT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_SINT, ©VertexData); - addIntegerVertexFormatInfo(&map, GL_INT, 3, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_SINT, ©VertexData); - addIntegerVertexFormatInfo(&map, GL_INT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_SINT, ©VertexData); - - // GL_UNSIGNED_INT - addIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_SINT, ©VertexData); - addIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_SINT, ©VertexData); - addIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 3, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_SINT, ©VertexData); - addIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_SINT, ©VertexData); - - // GL_INT_2_10_10_10_REV - addIntegerVertexFormatInfo(&map, GL_INT_2_10_10_10_REV, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SINT, ©PackedVertexData); - - // GL_UNSIGNED_INT_2_10_10_10_REV - addIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT_2_10_10_10_REV, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UINT, ©PackedUnsignedVertexData); - - return map; -} - -static bool GetD3D11VertexFormatInfo(const gl::VertexFormat &vertexFormat, D3D11VertexFormatInfo *outVertexFormatInfo) -{ - static const D3D11VertexFormatInfoMap vertexFormatMap = BuildD3D11VertexFormatInfoMap(); - - D3D11VertexFormatInfoMap::const_iterator iter = vertexFormatMap.find(vertexFormat); - if (iter != vertexFormatMap.end()) - { - if (outVertexFormatInfo) - { - *outVertexFormatInfo = iter->second; - } - return true; - } - else - { - return false; - } -} - -VertexCopyFunction GetVertexCopyFunction(const gl::VertexFormat &vertexFormat) -{ - D3D11VertexFormatInfo vertexFormatInfo; - if (GetD3D11VertexFormatInfo(vertexFormat, &vertexFormatInfo)) - { - return vertexFormatInfo.mCopyFunction; - } - else - { - UNREACHABLE(); - return NULL; - } -} - -size_t GetVertexElementSize(const gl::VertexFormat &vertexFormat) -{ - D3D11VertexFormatInfo vertexFormatInfo; - if (GetD3D11VertexFormatInfo(vertexFormat, &vertexFormatInfo)) - { - // FIXME: should not need a client version, and is not a pixel! - return d3d11::GetFormatPixelBytes(vertexFormatInfo.mNativeFormat); - } - else - { - UNREACHABLE(); - return 0; - } -} - -rx::VertexConversionType GetVertexConversionType(const gl::VertexFormat &vertexFormat) -{ - D3D11VertexFormatInfo vertexFormatInfo; - if (GetD3D11VertexFormatInfo(vertexFormat, &vertexFormatInfo)) - { - return vertexFormatInfo.mConversionType; - } - else - { - UNREACHABLE(); - return VERTEX_CONVERT_NONE; - } -} - -DXGI_FORMAT GetNativeVertexFormat(const gl::VertexFormat &vertexFormat) -{ - D3D11VertexFormatInfo vertexFormatInfo; - if (GetD3D11VertexFormatInfo(vertexFormat, &vertexFormatInfo)) - { - return vertexFormatInfo.mNativeFormat; - } - else - { - UNREACHABLE(); - return DXGI_FORMAT_UNKNOWN; - } -} - -} - -namespace d3d11_gl -{ - -GLenum GetInternalFormat(DXGI_FORMAT format, GLuint clientVersion) -{ - if (clientVersion == 2) - { - static DXGIToESFormatMap es2FormatMap = BuildDXGIToES2FormatMap(); - auto formatIt = es2FormatMap.find(format); - if (formatIt != es2FormatMap.end()) - { - return formatIt->second; - } - } - else if (clientVersion == 3) - { - static DXGIToESFormatMap es3FormatMap = BuildDXGIToES3FormatMap(); - auto formatIt = es3FormatMap.find(format); - if (formatIt != es3FormatMap.end()) - { - return formatIt->second; - } - } - - UNREACHABLE(); - return GL_NONE; -} - -} - -} diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/formatutils11.h b/gfx/angle/src/libGLESv2/renderer/d3d11/formatutils11.h deleted file mode 100644 index d7ae4e0b9d9f..000000000000 --- a/gfx/angle/src/libGLESv2/renderer/d3d11/formatutils11.h +++ /dev/null @@ -1,79 +0,0 @@ -// -// 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. -// - -// formatutils11.h: Queries for GL image formats and their translations to D3D11 -// formats. - -#ifndef LIBGLESV2_RENDERER_FORMATUTILS11_H_ -#define LIBGLESV2_RENDERER_FORMATUTILS11_H_ - -#include "libGLESv2/formatutils.h" - -namespace rx -{ - -class Renderer; - -namespace d3d11 -{ - -typedef std::set DXGIFormatSet; - -MipGenerationFunction GetMipGenerationFunction(DXGI_FORMAT format); -LoadImageFunction GetImageLoadFunction(GLenum internalFormat, GLenum type, GLuint clientVersion); - -GLuint GetFormatPixelBytes(DXGI_FORMAT format); -GLuint GetBlockWidth(DXGI_FORMAT format); -GLuint GetBlockHeight(DXGI_FORMAT format); -GLenum GetComponentType(DXGI_FORMAT format); - -GLuint GetDepthBits(DXGI_FORMAT format); -GLuint GetDepthOffset(DXGI_FORMAT format); -GLuint GetStencilBits(DXGI_FORMAT format); -GLuint GetStencilOffset(DXGI_FORMAT format); - -void MakeValidSize(bool isImage, DXGI_FORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset); - -const DXGIFormatSet &GetAllUsedDXGIFormats(); - -ColorReadFunction GetColorReadFunction(DXGI_FORMAT format); -ColorCopyFunction GetFastCopyFunction(DXGI_FORMAT sourceFormat, GLenum destFormat, GLenum destType); - -} - -namespace gl_d3d11 -{ - -DXGI_FORMAT GetTexFormat(GLenum internalFormat, GLuint clientVersion); -DXGI_FORMAT GetSRVFormat(GLenum internalFormat, GLuint clientVersion); -DXGI_FORMAT GetRTVFormat(GLenum internalFormat, GLuint clientVersion); -DXGI_FORMAT GetDSVFormat(GLenum internalFormat, GLuint clientVersion); -DXGI_FORMAT GetRenderableFormat(GLenum internalFormat, GLuint clientVersion); - -DXGI_FORMAT GetSwizzleTexFormat(GLint internalFormat, const Renderer *renderer); -DXGI_FORMAT GetSwizzleSRVFormat(GLint internalFormat, const Renderer *renderer); -DXGI_FORMAT GetSwizzleRTVFormat(GLint internalFormat, const Renderer *renderer); - -bool RequiresTextureDataInitialization(GLint internalFormat); -InitializeTextureDataFunction GetTextureDataInitializationFunction(GLint internalFormat); - -VertexCopyFunction GetVertexCopyFunction(const gl::VertexFormat &vertexFormat); -size_t GetVertexElementSize(const gl::VertexFormat &vertexFormat); -VertexConversionType GetVertexConversionType(const gl::VertexFormat &vertexFormat); -DXGI_FORMAT GetNativeVertexFormat(const gl::VertexFormat &vertexFormat); - -} - -namespace d3d11_gl -{ - -GLenum GetInternalFormat(DXGI_FORMAT format, GLuint clientVersion); - -} - -} - -#endif // LIBGLESV2_RENDERER_FORMATUTILS11_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.cpp b/gfx/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.cpp deleted file mode 100644 index 327d2f04f61f..000000000000 --- a/gfx/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.cpp +++ /dev/null @@ -1,280 +0,0 @@ -#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_utils.cpp: Conversion functions and other utility routines -// specific to the D3D11 renderer. - -#include "libGLESv2/renderer/d3d11/renderer11_utils.h" -#include "libGLESv2/renderer/d3d11/formatutils11.h" -#include "common/debug.h" - -namespace rx -{ - -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; - case GL_MIN: d3dBlendOp = D3D11_BLEND_OP_MIN; break; - case GL_MAX: d3dBlendOp = D3D11_BLEND_OP_MAX; 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, GLenum comparisonMode) -{ - bool comparison = comparisonMode != GL_NONE; - - if (maxAnisotropy > 1.0f) - { - return D3D11_ENCODE_ANISOTROPIC_FILTER(static_cast(comparison)); - } - 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, static_cast(comparison)); - } -} - -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; -} - -D3D11_QUERY ConvertQueryType(GLenum queryType) -{ - switch (queryType) - { - case GL_ANY_SAMPLES_PASSED_EXT: - case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: return D3D11_QUERY_OCCLUSION; - case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: return D3D11_QUERY_SO_STATISTICS; - default: UNREACHABLE(); return D3D11_QUERY_EVENT; - } -} - -} - -namespace d3d11 -{ - -void GenerateInitialTextureData(GLint internalFormat, GLuint clientVersion, GLuint width, GLuint height, GLuint depth, - GLuint mipLevels, std::vector *outSubresourceData, - std::vector< std::vector > *outData) -{ - InitializeTextureDataFunction initializeFunc = gl_d3d11::GetTextureDataInitializationFunction(internalFormat); - DXGI_FORMAT dxgiFormat = gl_d3d11::GetTexFormat(internalFormat, clientVersion); - - outSubresourceData->resize(mipLevels); - outData->resize(mipLevels); - - for (unsigned int i = 0; i < mipLevels; i++) - { - unsigned int mipWidth = std::max(width >> i, 1U); - unsigned int mipHeight = std::max(height >> i, 1U); - unsigned int mipDepth = std::max(depth >> i, 1U); - - unsigned int rowWidth = d3d11::GetFormatPixelBytes(dxgiFormat) * mipWidth; - unsigned int imageSize = rowWidth * height; - - outData->at(i).resize(rowWidth * mipHeight * mipDepth); - initializeFunc(mipWidth, mipHeight, mipDepth, outData->at(i).data(), rowWidth, imageSize); - - outSubresourceData->at(i).pSysMem = outData->at(i).data(); - outSubresourceData->at(i).SysMemPitch = rowWidth; - outSubresourceData->at(i).SysMemSlicePitch = imageSize; - } -} - -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 SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex* vertex, float x, float y, - unsigned int layer, float u, float v, float s) -{ - vertex->x = x; - vertex->y = y; - vertex->l = layer; - vertex->u = u; - vertex->v = v; - vertex->s = s; -} - -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/d3d9/BufferStorage9.cpp b/gfx/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.cpp deleted file mode 100644 index 489a0401cb6a..000000000000 --- a/gfx/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.cpp +++ /dev/null @@ -1,98 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2013-2014 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/d3d9/BufferStorage9.h" -#include "common/debug.h" -#include "libGLESv2/main.h" - -namespace rx -{ - -BufferStorage9::BufferStorage9() - : mSize(0) -{ -} - -BufferStorage9::~BufferStorage9() -{ -} - -BufferStorage9 *BufferStorage9::makeBufferStorage9(BufferStorage *bufferStorage) -{ - ASSERT(HAS_DYNAMIC_TYPE(BufferStorage9*, bufferStorage)); - return static_cast(bufferStorage); -} - -void *BufferStorage9::getData() -{ - return mMemory.data(); -} - -void BufferStorage9::setData(const void* data, size_t size, size_t offset) -{ - if (offset + size > mMemory.size()) - { - mMemory.resize(offset + size); - } - - mSize = std::max(mSize, offset + size); - if (data) - { - memcpy(mMemory.data() + offset, data, size); - } -} - -void BufferStorage9::copyData(BufferStorage* sourceStorage, size_t size, size_t sourceOffset, size_t destOffset) -{ - BufferStorage9* source = makeBufferStorage9(sourceStorage); - if (source) - { - memcpy(mMemory.data() + destOffset, source->mMemory.data() + sourceOffset, size); - } -} - -void BufferStorage9::clear() -{ - mSize = 0; -} - -void BufferStorage9::markTransformFeedbackUsage() -{ - UNREACHABLE(); -} - -size_t BufferStorage9::getSize() const -{ - return mSize; -} - -bool BufferStorage9::supportsDirectBinding() const -{ - return false; -} - -// We do not suppot buffer mapping facility in D3D9 -bool BufferStorage9::isMapped() const -{ - UNREACHABLE(); - return false; -} - -void *BufferStorage9::map(GLbitfield access) -{ - UNREACHABLE(); - return NULL; -} - -void BufferStorage9::unmap() -{ - UNREACHABLE(); -} - -} diff --git a/gfx/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.h b/gfx/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.h deleted file mode 100644 index dd61624c2859..000000000000 --- a/gfx/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.h +++ /dev/null @@ -1,46 +0,0 @@ -// -// Copyright (c) 2013-2014 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, size_t size, size_t offset); - virtual void copyData(BufferStorage* sourceStorage, size_t size, size_t sourceOffset, size_t destOffset); - virtual void clear(); - virtual void markTransformFeedbackUsage(); - virtual size_t getSize() const; - virtual bool supportsDirectBinding() const; - - virtual bool isMapped() const; - virtual void *map(GLbitfield access); - virtual void unmap(); - - private: - DISALLOW_COPY_AND_ASSIGN(BufferStorage9); - - std::vector mMemory; - size_t mSize; -}; - -} - -#endif // LIBGLESV2_RENDERER_BUFFERSTORAGE9_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/d3d9/formatutils9.cpp b/gfx/angle/src/libGLESv2/renderer/d3d9/formatutils9.cpp deleted file mode 100644 index 141bcc7c958c..000000000000 --- a/gfx/angle/src/libGLESv2/renderer/d3d9/formatutils9.cpp +++ /dev/null @@ -1,864 +0,0 @@ -#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. -// - -// formatutils9.cpp: Queries for GL image formats and their translations to D3D9 -// formats. - -#include "libGLESv2/renderer/d3d9/formatutils9.h" -#include "libGLESv2/renderer/d3d9/Renderer9.h" -#include "libGLESv2/renderer/generatemip.h" -#include "libGLESv2/renderer/loadimage.h" -#include "libGLESv2/renderer/copyimage.h" -#include "libGLESv2/renderer/vertexconversion.h" - -namespace rx -{ - -// Each GL internal format corresponds to one D3D format and data loading function. -// Due to not all formats being available all the time, some of the function/format types are wrapped -// in templates that perform format support queries on a Renderer9 object which is supplied -// when requesting the function or format. - -typedef bool ((Renderer9::*Renderer9FormatCheckFunction)(void) const); -typedef LoadImageFunction (*RendererCheckLoadFunction)(const Renderer9 *renderer); - -template -LoadImageFunction RendererCheckLoad(const Renderer9 *renderer) -{ - return ((renderer->*pred)()) ? prefered : fallback; -} - -template -LoadImageFunction SimpleLoad(const Renderer9 *renderer) -{ - return loadFunc; -} - -LoadImageFunction UnreachableLoad(const Renderer9 *renderer) -{ - UNREACHABLE(); - return NULL; -} - -typedef bool (*FallbackPredicateFunction)(void); - -template -LoadImageFunction FallbackLoadFunction(const Renderer9 *renderer) -{ - return pred() ? prefered : fallback; -} - -typedef D3DFORMAT (*FormatQueryFunction)(const rx::Renderer9 *renderer); - -template -D3DFORMAT CheckFormatSupport(const rx::Renderer9 *renderer) -{ - return (renderer->*pred)() ? prefered : fallback; -} - -template -D3DFORMAT D3D9Format(const rx::Renderer9 *renderer) -{ - return format; -} - -struct D3D9FormatInfo -{ - FormatQueryFunction mTexFormat; - FormatQueryFunction mRenderFormat; - RendererCheckLoadFunction mLoadFunction; - - D3D9FormatInfo() - : mTexFormat(NULL), mRenderFormat(NULL), mLoadFunction(NULL) - { } - - D3D9FormatInfo(FormatQueryFunction textureFormat, FormatQueryFunction renderFormat, RendererCheckLoadFunction loadFunc) - : mTexFormat(textureFormat), mRenderFormat(renderFormat), mLoadFunction(loadFunc) - { } -}; - -const D3DFORMAT D3DFMT_INTZ = ((D3DFORMAT)(MAKEFOURCC('I','N','T','Z'))); -const D3DFORMAT D3DFMT_NULL = ((D3DFORMAT)(MAKEFOURCC('N','U','L','L'))); - -typedef std::pair D3D9FormatPair; -typedef std::map D3D9FormatMap; - -static D3D9FormatMap BuildD3D9FormatMap() -{ - D3D9FormatMap map; - - // | Internal format | Texture format | Render format | Load function | - map.insert(D3D9FormatPair(GL_NONE, D3D9FormatInfo(D3D9Format, D3D9Format, UnreachableLoad ))); - - map.insert(D3D9FormatPair(GL_DEPTH_COMPONENT16, D3D9FormatInfo(D3D9Format, D3D9Format, UnreachableLoad ))); - map.insert(D3D9FormatPair(GL_DEPTH_COMPONENT32_OES, D3D9FormatInfo(D3D9Format, D3D9Format, UnreachableLoad ))); - map.insert(D3D9FormatPair(GL_DEPTH24_STENCIL8_OES, D3D9FormatInfo(D3D9Format, D3D9Format, UnreachableLoad ))); - map.insert(D3D9FormatPair(GL_STENCIL_INDEX8, D3D9FormatInfo(D3D9Format, D3D9Format, UnreachableLoad ))); // TODO: What's the texture format? - - map.insert(D3D9FormatPair(GL_RGBA32F_EXT, D3D9FormatInfo(D3D9Format, D3D9Format, SimpleLoad > ))); - map.insert(D3D9FormatPair(GL_RGB32F_EXT, D3D9FormatInfo(D3D9Format, D3D9Format, SimpleLoad >))); - map.insert(D3D9FormatPair(GL_RG32F_EXT, D3D9FormatInfo(D3D9Format, D3D9Format, SimpleLoad > ))); - map.insert(D3D9FormatPair(GL_R32F_EXT, D3D9FormatInfo(D3D9Format, D3D9Format, SimpleLoad > ))); - map.insert(D3D9FormatPair(GL_ALPHA32F_EXT, D3D9FormatInfo(D3D9Format, D3D9Format, SimpleLoad ))); - map.insert(D3D9FormatPair(GL_LUMINANCE32F_EXT, D3D9FormatInfo(D3D9Format, D3D9Format, SimpleLoad ))); - map.insert(D3D9FormatPair(GL_LUMINANCE_ALPHA32F_EXT, D3D9FormatInfo(D3D9Format, D3D9Format, SimpleLoad ))); - - map.insert(D3D9FormatPair(GL_RGBA16F_EXT, D3D9FormatInfo(D3D9Format, D3D9Format, SimpleLoad > ))); - map.insert(D3D9FormatPair(GL_RGB16F_EXT, D3D9FormatInfo(D3D9Format, D3D9Format, SimpleLoad >))); - map.insert(D3D9FormatPair(GL_RG16F_EXT, D3D9FormatInfo(D3D9Format, D3D9Format, SimpleLoad > ))); - map.insert(D3D9FormatPair(GL_R16F_EXT, D3D9FormatInfo(D3D9Format, D3D9Format, SimpleLoad > ))); - map.insert(D3D9FormatPair(GL_ALPHA16F_EXT, D3D9FormatInfo(D3D9Format, D3D9Format, SimpleLoad ))); - map.insert(D3D9FormatPair(GL_LUMINANCE16F_EXT, D3D9FormatInfo(D3D9Format, D3D9Format, SimpleLoad ))); - map.insert(D3D9FormatPair(GL_LUMINANCE_ALPHA16F_EXT, D3D9FormatInfo(D3D9Format, D3D9Format, SimpleLoad))); - - map.insert(D3D9FormatPair(GL_ALPHA8_EXT, D3D9FormatInfo(D3D9Format, D3D9Format, FallbackLoadFunction))); - - map.insert(D3D9FormatPair(GL_RGB8_OES, D3D9FormatInfo(D3D9Format, D3D9Format, SimpleLoad ))); - map.insert(D3D9FormatPair(GL_RGB565, D3D9FormatInfo(CheckFormatSupport<&Renderer9::getRGB565TextureSupport, D3DFMT_R5G6B5, D3DFMT_X8R8G8B8>, CheckFormatSupport<&Renderer9::getRGB565TextureSupport, D3DFMT_R5G6B5, D3DFMT_X8R8G8B8>, RendererCheckLoad<&Renderer9::getRGB565TextureSupport, loadToNative, loadRGB565DataToBGRA>))); - map.insert(D3D9FormatPair(GL_RGBA8_OES, D3D9FormatInfo(D3D9Format, D3D9Format, FallbackLoadFunction))); - map.insert(D3D9FormatPair(GL_RGBA4, D3D9FormatInfo(D3D9Format, D3D9Format, SimpleLoad ))); - map.insert(D3D9FormatPair(GL_RGB5_A1, D3D9FormatInfo(D3D9Format, D3D9Format, SimpleLoad ))); - map.insert(D3D9FormatPair(GL_R8_EXT, D3D9FormatInfo(D3D9Format, D3D9Format, SimpleLoad ))); - map.insert(D3D9FormatPair(GL_RG8_EXT, D3D9FormatInfo(D3D9Format, D3D9Format, SimpleLoad ))); - - map.insert(D3D9FormatPair(GL_BGRA8_EXT, D3D9FormatInfo(D3D9Format, D3D9Format, SimpleLoad > ))); - map.insert(D3D9FormatPair(GL_BGRA4_ANGLEX, D3D9FormatInfo(D3D9Format, D3D9Format, SimpleLoad ))); - map.insert(D3D9FormatPair(GL_BGR5_A1_ANGLEX, D3D9FormatInfo(D3D9Format, D3D9Format, SimpleLoad ))); - - map.insert(D3D9FormatPair(GL_COMPRESSED_RGB_S3TC_DXT1_EXT, D3D9FormatInfo(D3D9Format, D3D9Format, SimpleLoad >))); - map.insert(D3D9FormatPair(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, D3D9FormatInfo(D3D9Format, D3D9Format, SimpleLoad >))); - map.insert(D3D9FormatPair(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, D3D9FormatInfo(D3D9Format, D3D9Format, SimpleLoad >))); - map.insert(D3D9FormatPair(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, D3D9FormatInfo(D3D9Format, D3D9Format, SimpleLoad >))); - - // These formats require checking if the renderer supports D3DFMT_L8 or D3DFMT_A8L8 and - // then changing the format and loading function appropriately. - map.insert(D3D9FormatPair(GL_LUMINANCE8_EXT, D3D9FormatInfo(CheckFormatSupport<&Renderer9::getLuminanceTextureSupport, D3DFMT_L8, D3DFMT_A8R8G8B8>, D3D9Format, RendererCheckLoad<&Renderer9::getLuminanceTextureSupport, loadToNative, loadLuminanceDataToBGRA>))); - map.insert(D3D9FormatPair(GL_LUMINANCE8_ALPHA8_EXT, D3D9FormatInfo(CheckFormatSupport<&Renderer9::getLuminanceAlphaTextureSupport, D3DFMT_A8L8, D3DFMT_A8R8G8B8>, D3D9Format, RendererCheckLoad<&Renderer9::getLuminanceTextureSupport, loadToNative, loadLuminanceAlphaDataToBGRA>))); - - return map; -} - -static bool GetD3D9FormatInfo(GLenum internalFormat, D3D9FormatInfo *outFormatInfo) -{ - static const D3D9FormatMap formatMap = BuildD3D9FormatMap(); - D3D9FormatMap::const_iterator iter = formatMap.find(internalFormat); - if (iter != formatMap.end()) - { - if (outFormatInfo) - { - *outFormatInfo = iter->second; - } - return true; - } - else - { - return false; - } -} - -// A map to determine the pixel size and mip generation function of a given D3D format -struct D3DFormatInfo -{ - GLuint mPixelBits; - GLuint mBlockWidth; - GLuint mBlockHeight; - GLenum mInternalFormat; - - MipGenerationFunction mMipGenerationFunction; - ColorReadFunction mColorReadFunction; - - D3DFormatInfo() - : mPixelBits(0), mBlockWidth(0), mBlockHeight(0), mInternalFormat(GL_NONE), mMipGenerationFunction(NULL), - mColorReadFunction(NULL) - { } - - D3DFormatInfo(GLuint pixelBits, GLuint blockWidth, GLuint blockHeight, GLenum internalFormat, - MipGenerationFunction mipFunc, ColorReadFunction readFunc) - : mPixelBits(pixelBits), mBlockWidth(blockWidth), mBlockHeight(blockHeight), mInternalFormat(internalFormat), - mMipGenerationFunction(mipFunc), mColorReadFunction(readFunc) - { } -}; - -typedef std::pair D3D9FormatInfoPair; -typedef std::map D3D9FormatInfoMap; - -static D3D9FormatInfoMap BuildD3D9FormatInfoMap() -{ - D3D9FormatInfoMap map; - - // | D3DFORMAT | | S |W |H | Internal format | Mip generation function | Color read function | - map.insert(D3D9FormatInfoPair(D3DFMT_NULL, D3DFormatInfo( 0, 0, 0, GL_NONE, NULL, NULL ))); - map.insert(D3D9FormatInfoPair(D3DFMT_UNKNOWN, D3DFormatInfo( 0, 0, 0, GL_NONE, NULL, NULL ))); - - map.insert(D3D9FormatInfoPair(D3DFMT_L8, D3DFormatInfo( 8, 1, 1, GL_LUMINANCE8_EXT, GenerateMip, ReadColor ))); - map.insert(D3D9FormatInfoPair(D3DFMT_A8, D3DFormatInfo( 8, 1, 1, GL_ALPHA8_EXT, GenerateMip, ReadColor ))); - map.insert(D3D9FormatInfoPair(D3DFMT_A8L8, D3DFormatInfo( 16, 1, 1, GL_LUMINANCE8_ALPHA8_EXT, GenerateMip, ReadColor ))); - map.insert(D3D9FormatInfoPair(D3DFMT_A4R4G4B4, D3DFormatInfo( 16, 1, 1, GL_BGRA4_ANGLEX, GenerateMip, ReadColor ))); - map.insert(D3D9FormatInfoPair(D3DFMT_A1R5G5B5, D3DFormatInfo( 16, 1, 1, GL_BGR5_A1_ANGLEX, GenerateMip, ReadColor ))); - map.insert(D3D9FormatInfoPair(D3DFMT_R5G6B5, D3DFormatInfo( 16, 1, 1, GL_RGB565, GenerateMip, ReadColor ))); - map.insert(D3D9FormatInfoPair(D3DFMT_X8R8G8B8, D3DFormatInfo( 32, 1, 1, GL_BGRA8_EXT, GenerateMip, ReadColor ))); - map.insert(D3D9FormatInfoPair(D3DFMT_A8R8G8B8, D3DFormatInfo( 32, 1, 1, GL_BGRA8_EXT, GenerateMip, ReadColor ))); - map.insert(D3D9FormatInfoPair(D3DFMT_R16F, D3DFormatInfo( 16, 1, 1, GL_R16F_EXT, GenerateMip, ReadColor ))); - map.insert(D3D9FormatInfoPair(D3DFMT_G16R16F, D3DFormatInfo( 32, 1, 1, GL_RG16F_EXT, GenerateMip, ReadColor ))); - map.insert(D3D9FormatInfoPair(D3DFMT_A16B16G16R16F, D3DFormatInfo( 64, 1, 1, GL_RGBA16F_EXT, GenerateMip, ReadColor))); - map.insert(D3D9FormatInfoPair(D3DFMT_R32F, D3DFormatInfo( 32, 1, 1, GL_R32F_EXT, GenerateMip, ReadColor ))); - map.insert(D3D9FormatInfoPair(D3DFMT_G32R32F, D3DFormatInfo( 64, 1, 1, GL_RG32F_EXT, GenerateMip, ReadColor ))); - map.insert(D3D9FormatInfoPair(D3DFMT_A32B32G32R32F, D3DFormatInfo(128, 1, 1, GL_RGBA32F_EXT, GenerateMip, ReadColor))); - - map.insert(D3D9FormatInfoPair(D3DFMT_D16, D3DFormatInfo( 16, 1, 1, GL_DEPTH_COMPONENT16, NULL, NULL ))); - map.insert(D3D9FormatInfoPair(D3DFMT_D24S8, D3DFormatInfo( 32, 1, 1, GL_DEPTH24_STENCIL8_OES, NULL, NULL ))); - map.insert(D3D9FormatInfoPair(D3DFMT_D24X8, D3DFormatInfo( 32, 1, 1, GL_DEPTH_COMPONENT16, NULL, NULL ))); - map.insert(D3D9FormatInfoPair(D3DFMT_D32, D3DFormatInfo( 32, 1, 1, GL_DEPTH_COMPONENT32_OES, NULL, NULL ))); - - map.insert(D3D9FormatInfoPair(D3DFMT_INTZ, D3DFormatInfo( 32, 1, 1, GL_DEPTH24_STENCIL8_OES, NULL, NULL ))); - - map.insert(D3D9FormatInfoPair(D3DFMT_DXT1, D3DFormatInfo( 64, 4, 4, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, NULL, NULL ))); - map.insert(D3D9FormatInfoPair(D3DFMT_DXT3, D3DFormatInfo(128, 4, 4, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, NULL, NULL ))); - map.insert(D3D9FormatInfoPair(D3DFMT_DXT5, D3DFormatInfo(128, 4, 4, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, NULL, NULL ))); - - return map; -} - -static const D3D9FormatInfoMap &GetD3D9FormatInfoMap() -{ - static const D3D9FormatInfoMap infoMap = BuildD3D9FormatInfoMap(); - return infoMap; -} - -static bool GetD3D9FormatInfo(D3DFORMAT format, D3DFormatInfo *outFormatInfo) -{ - const D3D9FormatInfoMap &infoMap = GetD3D9FormatInfoMap(); - D3D9FormatInfoMap::const_iterator iter = infoMap.find(format); - if (iter != infoMap.end()) - { - if (outFormatInfo) - { - *outFormatInfo = iter->second; - } - return true; - } - else - { - return false; - } -} -static d3d9::D3DFormatSet BuildAllD3DFormatSet() -{ - d3d9::D3DFormatSet set; - - const D3D9FormatInfoMap &infoMap = GetD3D9FormatInfoMap(); - for (D3D9FormatInfoMap::const_iterator i = infoMap.begin(); i != infoMap.end(); ++i) - { - set.insert(i->first); - } - - return set; -} - -struct D3D9FastCopyFormat -{ - D3DFORMAT mSourceFormat; - GLenum mDestFormat; - GLenum mDestType; - - D3D9FastCopyFormat(D3DFORMAT sourceFormat, GLenum destFormat, GLenum destType) - : mSourceFormat(sourceFormat), mDestFormat(destFormat), mDestType(destType) - { } - - bool operator<(const D3D9FastCopyFormat& other) const - { - return memcmp(this, &other, sizeof(D3D9FastCopyFormat)) < 0; - } -}; - -typedef std::map D3D9FastCopyMap; -typedef std::pair D3D9FastCopyPair; - -static D3D9FastCopyMap BuildFastCopyMap() -{ - D3D9FastCopyMap map; - - map.insert(D3D9FastCopyPair(D3D9FastCopyFormat(D3DFMT_A8R8G8B8, GL_RGBA, GL_UNSIGNED_BYTE), CopyBGRAUByteToRGBAUByte)); - - return map; -} - -typedef std::pair InternalFormatInitialzerPair; -typedef std::map InternalFormatInitialzerMap; - -static InternalFormatInitialzerMap BuildInternalFormatInitialzerMap() -{ - InternalFormatInitialzerMap map; - - map.insert(InternalFormatInitialzerPair(GL_RGB16F, initialize4ComponentData)); - map.insert(InternalFormatInitialzerPair(GL_RGB32F, initialize4ComponentData)); - - return map; -} - -static const InternalFormatInitialzerMap &GetInternalFormatInitialzerMap() -{ - static const InternalFormatInitialzerMap map = BuildInternalFormatInitialzerMap(); - return map; -} - -namespace d3d9 -{ - -MipGenerationFunction GetMipGenerationFunction(D3DFORMAT format) -{ - D3DFormatInfo d3dFormatInfo; - if (GetD3D9FormatInfo(format, &d3dFormatInfo)) - { - return d3dFormatInfo.mMipGenerationFunction; - } - else - { - UNREACHABLE(); - return NULL; - } -} - -LoadImageFunction GetImageLoadFunction(GLenum internalFormat, const Renderer9 *renderer) -{ - if (!renderer) - { - return NULL; - } - - ASSERT(renderer->getCurrentClientVersion() == 2); - - D3D9FormatInfo d3d9FormatInfo; - if (GetD3D9FormatInfo(internalFormat, &d3d9FormatInfo)) - { - return d3d9FormatInfo.mLoadFunction(renderer); - } - else - { - UNREACHABLE(); - return NULL; - } -} - -GLuint GetFormatPixelBytes(D3DFORMAT format) -{ - D3DFormatInfo d3dFormatInfo; - if (GetD3D9FormatInfo(format, &d3dFormatInfo)) - { - return d3dFormatInfo.mPixelBits / 8; - } - else - { - UNREACHABLE(); - return 0; - } -} - -GLuint GetBlockWidth(D3DFORMAT format) -{ - D3DFormatInfo d3dFormatInfo; - if (GetD3D9FormatInfo(format, &d3dFormatInfo)) - { - return d3dFormatInfo.mBlockWidth; - } - else - { - UNREACHABLE(); - return 0; - } -} - -GLuint GetBlockHeight(D3DFORMAT format) -{ - D3DFormatInfo d3dFormatInfo; - if (GetD3D9FormatInfo(format, &d3dFormatInfo)) - { - return d3dFormatInfo.mBlockHeight; - } - else - { - UNREACHABLE(); - return 0; - } -} - -GLuint GetBlockSize(D3DFORMAT format, GLuint width, GLuint height) -{ - D3DFormatInfo d3dFormatInfo; - if (GetD3D9FormatInfo(format, &d3dFormatInfo)) - { - GLuint numBlocksWide = (width + d3dFormatInfo.mBlockWidth - 1) / d3dFormatInfo.mBlockWidth; - GLuint numBlocksHight = (height + d3dFormatInfo.mBlockHeight - 1) / d3dFormatInfo.mBlockHeight; - - return (d3dFormatInfo.mPixelBits * numBlocksWide * numBlocksHight) / 8; - } - else - { - UNREACHABLE(); - return 0; - } -} - -void MakeValidSize(bool isImage, D3DFORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset) -{ - D3DFormatInfo d3dFormatInfo; - if (GetD3D9FormatInfo(format, &d3dFormatInfo)) - { - int upsampleCount = 0; - - GLsizei blockWidth = d3dFormatInfo.mBlockWidth; - GLsizei blockHeight = d3dFormatInfo.mBlockHeight; - - // Don't expand the size of full textures that are at least (blockWidth x blockHeight) already. - if (isImage || *requestWidth < blockWidth || *requestHeight < blockHeight) - { - while (*requestWidth % blockWidth != 0 || *requestHeight % blockHeight != 0) - { - *requestWidth <<= 1; - *requestHeight <<= 1; - upsampleCount++; - } - } - *levelOffset = upsampleCount; - } -} - -const D3DFormatSet &GetAllUsedD3DFormats() -{ - static const D3DFormatSet formatSet = BuildAllD3DFormatSet(); - return formatSet; -} - -ColorReadFunction GetColorReadFunction(D3DFORMAT format) -{ - D3DFormatInfo d3dFormatInfo; - if (GetD3D9FormatInfo(format, &d3dFormatInfo)) - { - return d3dFormatInfo.mColorReadFunction; - } - else - { - UNREACHABLE(); - return NULL; - } -} - -ColorCopyFunction GetFastCopyFunction(D3DFORMAT sourceFormat, GLenum destFormat, GLenum destType, GLuint clientVersion) -{ - static const D3D9FastCopyMap fastCopyMap = BuildFastCopyMap(); - D3D9FastCopyMap::const_iterator iter = fastCopyMap.find(D3D9FastCopyFormat(sourceFormat, destFormat, destType)); - return (iter != fastCopyMap.end()) ? iter->second : NULL; -} - -GLenum GetDeclTypeComponentType(D3DDECLTYPE declType) -{ - switch (declType) - { - case D3DDECLTYPE_FLOAT1: return GL_FLOAT; - case D3DDECLTYPE_FLOAT2: return GL_FLOAT; - case D3DDECLTYPE_FLOAT3: return GL_FLOAT; - case D3DDECLTYPE_FLOAT4: return GL_FLOAT; - case D3DDECLTYPE_UBYTE4: return GL_UNSIGNED_INT; - case D3DDECLTYPE_SHORT2: return GL_INT; - case D3DDECLTYPE_SHORT4: return GL_INT; - case D3DDECLTYPE_UBYTE4N: return GL_UNSIGNED_NORMALIZED; - case D3DDECLTYPE_SHORT4N: return GL_SIGNED_NORMALIZED; - case D3DDECLTYPE_USHORT4N: return GL_UNSIGNED_NORMALIZED; - case D3DDECLTYPE_SHORT2N: return GL_SIGNED_NORMALIZED; - case D3DDECLTYPE_USHORT2N: return GL_UNSIGNED_NORMALIZED; - default: UNREACHABLE(); return GL_NONE; - } -} - -// 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; -}; - -struct TranslationDescription -{ - DWORD capsFlag; - FormatConverter preferredConversion; - FormatConverter fallbackConversion; -}; - -static unsigned int typeIndex(GLenum type); -static const FormatConverter &formatConverter(const gl::VertexAttribute &attribute); - -bool mTranslationsInitialized = false; -FormatConverter mFormatConverters[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; - -// 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 TranslationDescription 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 InitializeVertexTranslations(const rx::Renderer9 *renderer) -{ - DWORD declTypes = renderer->getCapsDeclTypes(); - - 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 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 FormatConverter &formatConverter(const gl::VertexFormat &vertexFormat) -{ - // Pure integer attributes only supported in ES3.0 - ASSERT(!vertexFormat.mPureInteger); - return mFormatConverters[typeIndex(vertexFormat.mType)][vertexFormat.mNormalized][vertexFormat.mComponents - 1]; -} - -VertexCopyFunction GetVertexCopyFunction(const gl::VertexFormat &vertexFormat) -{ - return formatConverter(vertexFormat).convertArray; -} - -size_t GetVertexElementSize(const gl::VertexFormat &vertexFormat) -{ - return formatConverter(vertexFormat).outputElementSize; -} - -VertexConversionType GetVertexConversionType(const gl::VertexFormat &vertexFormat) -{ - return (formatConverter(vertexFormat).identity ? VERTEX_CONVERT_NONE : VERTEX_CONVERT_CPU); -} - -D3DDECLTYPE GetNativeVertexFormat(const gl::VertexFormat &vertexFormat) -{ - return formatConverter(vertexFormat).d3dDeclType; -} - -} - -namespace gl_d3d9 -{ - -D3DFORMAT GetTextureFormat(GLenum internalFormat, const Renderer9 *renderer) -{ - if (!renderer) - { - UNREACHABLE(); - return D3DFMT_UNKNOWN; - } - - ASSERT(renderer->getCurrentClientVersion() == 2); - - D3D9FormatInfo d3d9FormatInfo; - if (GetD3D9FormatInfo(internalFormat, &d3d9FormatInfo)) - { - return d3d9FormatInfo.mTexFormat(renderer); - } - else - { - UNREACHABLE(); - return D3DFMT_UNKNOWN; - } -} - -D3DFORMAT GetRenderFormat(GLenum internalFormat, const Renderer9 *renderer) -{ - if (!renderer) - { - UNREACHABLE(); - return D3DFMT_UNKNOWN; - } - - ASSERT(renderer->getCurrentClientVersion() == 2); - - D3D9FormatInfo d3d9FormatInfo; - if (GetD3D9FormatInfo(internalFormat, &d3d9FormatInfo)) - { - return d3d9FormatInfo.mRenderFormat(renderer); - } - else - { - UNREACHABLE(); - return D3DFMT_UNKNOWN; - } -} - -D3DMULTISAMPLE_TYPE GetMultisampleType(GLsizei samples) -{ - return (samples > 1) ? static_cast(samples) : D3DMULTISAMPLE_NONE; -} - -bool RequiresTextureDataInitialization(GLint internalFormat) -{ - const InternalFormatInitialzerMap &map = GetInternalFormatInitialzerMap(); - return map.find(internalFormat) != map.end(); -} - -InitializeTextureDataFunction GetTextureDataInitializationFunction(GLint internalFormat) -{ - const InternalFormatInitialzerMap &map = GetInternalFormatInitialzerMap(); - InternalFormatInitialzerMap::const_iterator iter = map.find(internalFormat); - if (iter != map.end()) - { - return iter->second; - } - else - { - UNREACHABLE(); - return NULL; - } -} - -} - -namespace d3d9_gl -{ - -GLenum GetInternalFormat(D3DFORMAT format) -{ - static const D3D9FormatInfoMap infoMap = BuildD3D9FormatInfoMap(); - D3D9FormatInfoMap::const_iterator iter = infoMap.find(format); - if (iter != infoMap.end()) - { - return iter->second.mInternalFormat; - } - else - { - UNREACHABLE(); - return GL_NONE; - } -} - -GLsizei GetSamplesCount(D3DMULTISAMPLE_TYPE type) -{ - return (type != D3DMULTISAMPLE_NONMASKABLE) ? type : 0; -} - -bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format, GLuint clientVersion) -{ - GLenum internalFormat = d3d9_gl::GetInternalFormat(d3dformat); - GLenum convertedFormat = gl::GetFormat(internalFormat, clientVersion); - return convertedFormat == format; -} - -} - -} diff --git a/gfx/angle/src/libGLESv2/renderer/d3d9/formatutils9.h b/gfx/angle/src/libGLESv2/renderer/d3d9/formatutils9.h deleted file mode 100644 index 5b40c1054437..000000000000 --- a/gfx/angle/src/libGLESv2/renderer/d3d9/formatutils9.h +++ /dev/null @@ -1,77 +0,0 @@ -// -// 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. -// - -// formatutils9.h: Queries for GL image formats and their translations to D3D9 -// formats. - -#ifndef LIBGLESV2_RENDERER_FORMATUTILS9_H_ -#define LIBGLESV2_RENDERER_FORMATUTILS9_H_ - -#include "libGLESv2/formatutils.h" - -namespace rx -{ - -class Renderer9; - -namespace d3d9 -{ - -typedef std::set D3DFormatSet; - -MipGenerationFunction GetMipGenerationFunction(D3DFORMAT format); -LoadImageFunction GetImageLoadFunction(GLenum internalFormat, const Renderer9 *renderer); - -GLuint GetFormatPixelBytes(D3DFORMAT format); -GLuint GetBlockWidth(D3DFORMAT format); -GLuint GetBlockHeight(D3DFORMAT format); -GLuint GetBlockSize(D3DFORMAT format, GLuint width, GLuint height); - -void MakeValidSize(bool isImage, D3DFORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset); - -const D3DFormatSet &GetAllUsedD3DFormats(); - -ColorReadFunction GetColorReadFunction(D3DFORMAT format); -ColorCopyFunction GetFastCopyFunction(D3DFORMAT sourceFormat, GLenum destFormat, GLenum destType, GLuint clientVersion); - -VertexCopyFunction GetVertexCopyFunction(const gl::VertexFormat &vertexFormat); -size_t GetVertexElementSize(const gl::VertexFormat &vertexFormat); -VertexConversionType GetVertexConversionType(const gl::VertexFormat &vertexFormat); -D3DDECLTYPE GetNativeVertexFormat(const gl::VertexFormat &vertexFormat); - -GLenum GetDeclTypeComponentType(D3DDECLTYPE declType); -int GetDeclTypeComponentCount(D3DDECLTYPE declType); -bool IsDeclTypeNormalized(D3DDECLTYPE declType); - -void InitializeVertexTranslations(const rx::Renderer9 *renderer); - -} - -namespace gl_d3d9 -{ - -D3DFORMAT GetTextureFormat(GLenum internalFormat, const Renderer9 *renderer); -D3DFORMAT GetRenderFormat(GLenum internalFormat, const Renderer9 *renderer); - -D3DMULTISAMPLE_TYPE GetMultisampleType(GLsizei samples); - -bool RequiresTextureDataInitialization(GLint internalFormat); -InitializeTextureDataFunction GetTextureDataInitializationFunction(GLint internalFormat); - -} - -namespace d3d9_gl -{ - -GLenum GetInternalFormat(D3DFORMAT format); -GLsizei GetSamplesCount(D3DMULTISAMPLE_TYPE type); -bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format, GLuint clientVersion); - -} - -} - -#endif // LIBGLESV2_RENDERER_FORMATUTILS9_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/d3d9/renderer9_utils.cpp b/gfx/angle/src/libGLESv2/renderer/d3d9/renderer9_utils.cpp deleted file mode 100644 index 48c378838d6f..000000000000 --- a/gfx/angle/src/libGLESv2/renderer/d3d9/renderer9_utils.cpp +++ /dev/null @@ -1,247 +0,0 @@ -#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/d3d9/renderer9_utils.h" -#include "common/mathutil.h" -#include "libGLESv2/Context.h" - -#include "common/debug.h" - -namespace rx -{ - -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::ColorF 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; - case GL_MIN_EXT: d3dBlendOp = D3DBLENDOP_MIN; break; - case GL_MAX_EXT: d3dBlendOp = D3DBLENDOP_MAX; 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; - } -} - -} - -} diff --git a/gfx/angle/src/libGLESv2/renderer/generatemip.h b/gfx/angle/src/libGLESv2/renderer/generatemip.h index 3177a2b1f391..a57b00d444bb 100644 --- a/gfx/angle/src/libGLESv2/renderer/generatemip.h +++ b/gfx/angle/src/libGLESv2/renderer/generatemip.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2014 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,260 +10,19 @@ #ifndef LIBGLESV2_RENDERER_GENERATEMIP_H_ #define LIBGLESV2_RENDERER_GENERATEMIP_H_ -#include "common/mathutil.h" -#include "imageformats.h" +#include "libGLESv2/renderer/imageformats.h" +#include "libGLESv2/angletypes.h" namespace rx { -namespace priv -{ - template -static inline T *GetPixel(void *data, unsigned int x, unsigned int y, unsigned int z, unsigned int rowPitch, unsigned int depthPitch) -{ - return reinterpret_cast(reinterpret_cast(data) + (x * sizeof(T)) + (y * rowPitch) + (z * depthPitch)); -} - -template -static inline const T *GetPixel(const void *data, unsigned int x, unsigned int y, unsigned int z, unsigned int rowPitch, unsigned int depthPitch) -{ - return reinterpret_cast(reinterpret_cast(data) + (x * sizeof(T)) + (y * rowPitch) + (z * depthPitch)); -} - -template -static void GenerateMip_Y(unsigned int sourceWidth, unsigned int sourceHeight, unsigned int sourceDepth, - const unsigned char *sourceData, int sourceRowPitch, int sourceDepthPitch, - unsigned int destWidth, unsigned int destHeight, unsigned int destDepth, - unsigned char *destData, int destRowPitch, int destDepthPitch) -{ - ASSERT(sourceWidth == 1); - ASSERT(sourceHeight > 1); - ASSERT(sourceDepth == 1); - - for (unsigned int y = 0; y < destHeight; y++) - { - const T *src0 = GetPixel(sourceData, 0, y * 2, 0, sourceRowPitch, sourceDepthPitch); - const T *src1 = GetPixel(sourceData, 0, y * 2 + 1, 0, sourceRowPitch, sourceDepthPitch); - T *dst = GetPixel(destData, 0, y, 0, destRowPitch, destDepthPitch); - - T::average(dst, src0, src1); - } -} - -template -static void GenerateMip_X(unsigned int sourceWidth, unsigned int sourceHeight, unsigned int sourceDepth, - const unsigned char *sourceData, int sourceRowPitch, int sourceDepthPitch, - unsigned int destWidth, unsigned int destHeight, unsigned int destDepth, - unsigned char *destData, int destRowPitch, int destDepthPitch) -{ - ASSERT(sourceWidth > 1); - ASSERT(sourceHeight == 1); - ASSERT(sourceDepth == 1); - - for (unsigned int x = 0; x < destWidth; x++) - { - const T *src0 = GetPixel(sourceData, x * 2, 0, 0, sourceRowPitch, sourceDepthPitch); - const T *src1 = GetPixel(sourceData, x * 2 + 1, 0, 0, sourceRowPitch, sourceDepthPitch); - T *dst = GetPixel(destData, x, 0, 0, destRowPitch, destDepthPitch); - - T::average(dst, src0, src1); - } -} - -template -static void GenerateMip_Z(unsigned int sourceWidth, unsigned int sourceHeight, unsigned int sourceDepth, - const unsigned char *sourceData, int sourceRowPitch, int sourceDepthPitch, - unsigned int destWidth, unsigned int destHeight, unsigned int destDepth, - unsigned char *destData, int destRowPitch, int destDepthPitch) -{ - ASSERT(sourceWidth == 1); - ASSERT(sourceHeight == 1); - ASSERT(sourceDepth > 1); - - for (unsigned int z = 0; z < destDepth; z++) - { - const T *src0 = GetPixel(sourceData, 0, 0, z * 2, sourceRowPitch, sourceDepthPitch); - const T *src1 = GetPixel(sourceData, 0, 0, z * 2 + 1, sourceRowPitch, sourceDepthPitch); - T *dst = GetPixel(destData, 0, 0, z, destRowPitch, destDepthPitch); - - T::average(dst, src0, src1); - } -} - -template -static void GenerateMip_XY(unsigned int sourceWidth, unsigned int sourceHeight, unsigned int sourceDepth, - const unsigned char *sourceData, int sourceRowPitch, int sourceDepthPitch, - unsigned int destWidth, unsigned int destHeight, unsigned int destDepth, - unsigned char *destData, int destRowPitch, int destDepthPitch) -{ - ASSERT(sourceWidth > 1); - ASSERT(sourceHeight > 1); - ASSERT(sourceDepth == 1); - - for (unsigned int y = 0; y < destHeight; y++) - { - for (unsigned int x = 0; x < destWidth; x++) - { - const T *src0 = GetPixel(sourceData, x * 2, y * 2, 0, sourceRowPitch, sourceDepthPitch); - const T *src1 = GetPixel(sourceData, x * 2, y * 2 + 1, 0, sourceRowPitch, sourceDepthPitch); - const T *src2 = GetPixel(sourceData, x * 2 + 1, y * 2, 0, sourceRowPitch, sourceDepthPitch); - const T *src3 = GetPixel(sourceData, x * 2 + 1, y * 2 + 1, 0, sourceRowPitch, sourceDepthPitch); - T *dst = GetPixel(destData, x, y, 0, destRowPitch, destDepthPitch); - - T tmp0, tmp1; - - T::average(&tmp0, src0, src1); - T::average(&tmp1, src2, src3); - T::average(dst, &tmp0, &tmp1); - } - } -} - -template -static void GenerateMip_YZ(unsigned int sourceWidth, unsigned int sourceHeight, unsigned int sourceDepth, - const unsigned char *sourceData, int sourceRowPitch, int sourceDepthPitch, - unsigned int destWidth, unsigned int destHeight, unsigned int destDepth, - unsigned char *destData, int destRowPitch, int destDepthPitch) -{ - ASSERT(sourceWidth == 1); - ASSERT(sourceHeight > 1); - ASSERT(sourceDepth > 1); - - for (unsigned int z = 0; z < destDepth; z++) - { - for (unsigned int y = 0; y < destHeight; y++) - { - const T *src0 = GetPixel(sourceData, 0, y * 2, z * 2, sourceRowPitch, sourceDepthPitch); - const T *src1 = GetPixel(sourceData, 0, y * 2, z * 2 + 1, sourceRowPitch, sourceDepthPitch); - const T *src2 = GetPixel(sourceData, 0, y * 2 + 1, z * 2, sourceRowPitch, sourceDepthPitch); - const T *src3 = GetPixel(sourceData, 0, y * 2 + 1, z * 2 + 1, sourceRowPitch, sourceDepthPitch); - T *dst = GetPixel(destData, 0, y, z, destRowPitch, destDepthPitch); - - T tmp0, tmp1; - - T::average(&tmp0, src0, src1); - T::average(&tmp1, src2, src3); - T::average(dst, &tmp0, &tmp1); - } - } -} - -template -static void GenerateMip_XZ(unsigned int sourceWidth, unsigned int sourceHeight, unsigned int sourceDepth, - const unsigned char *sourceData, int sourceRowPitch, int sourceDepthPitch, - unsigned int destWidth, unsigned int destHeight, unsigned int destDepth, - unsigned char *destData, int destRowPitch, int destDepthPitch) -{ - ASSERT(sourceWidth > 1); - ASSERT(sourceHeight == 1); - ASSERT(sourceDepth > 1); - - for (unsigned int z = 0; z < destDepth; z++) - { - for (unsigned int x = 0; x < destWidth; x++) - { - const T *src0 = GetPixel(sourceData, x * 2, 0, z * 2, sourceRowPitch, sourceDepthPitch); - const T *src1 = GetPixel(sourceData, x * 2, 0, z * 2 + 1, sourceRowPitch, sourceDepthPitch); - const T *src2 = GetPixel(sourceData, x * 2 + 1, 0, z * 2, sourceRowPitch, sourceDepthPitch); - const T *src3 = GetPixel(sourceData, x * 2 + 1, 0, z * 2 + 1, sourceRowPitch, sourceDepthPitch); - T *dst = GetPixel(destData, x, 0, z, destRowPitch, destDepthPitch); - - T tmp0, tmp1; - - T::average(&tmp0, src0, src1); - T::average(&tmp1, src2, src3); - T::average(dst, &tmp0, &tmp1); - } - } -} - -template -static void GenerateMip_XYZ(unsigned int sourceWidth, unsigned int sourceHeight, unsigned int sourceDepth, - const unsigned char *sourceData, int sourceRowPitch, int sourceDepthPitch, - unsigned int destWidth, unsigned int destHeight, unsigned int destDepth, - unsigned char *destData, int destRowPitch, int destDepthPitch) -{ - ASSERT(sourceWidth > 1); - ASSERT(sourceHeight > 1); - ASSERT(sourceDepth > 1); - - for (unsigned int z = 0; z < destDepth; z++) - { - for (unsigned int y = 0; y < destHeight; y++) - { - for (unsigned int x = 0; x < destWidth; x++) - { - const T *src0 = GetPixel(sourceData, x * 2, y * 2, z * 2, sourceRowPitch, sourceDepthPitch); - const T *src1 = GetPixel(sourceData, x * 2, y * 2, z * 2 + 1, sourceRowPitch, sourceDepthPitch); - const T *src2 = GetPixel(sourceData, x * 2, y * 2 + 1, z * 2, sourceRowPitch, sourceDepthPitch); - const T *src3 = GetPixel(sourceData, x * 2, y * 2 + 1, z * 2 + 1, sourceRowPitch, sourceDepthPitch); - const T *src4 = GetPixel(sourceData, x * 2 + 1, y * 2, z * 2, sourceRowPitch, sourceDepthPitch); - const T *src5 = GetPixel(sourceData, x * 2 + 1, y * 2, z * 2 + 1, sourceRowPitch, sourceDepthPitch); - const T *src6 = GetPixel(sourceData, x * 2 + 1, y * 2 + 1, z * 2, sourceRowPitch, sourceDepthPitch); - const T *src7 = GetPixel(sourceData, x * 2 + 1, y * 2 + 1, z * 2 + 1, sourceRowPitch, sourceDepthPitch); - T *dst = GetPixel(destData, x, y, z, destRowPitch, destDepthPitch); - - T tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; - - T::average(&tmp0, src0, src1); - T::average(&tmp1, src2, src3); - T::average(&tmp2, src4, src5); - T::average(&tmp3, src6, src7); - - T::average(&tmp4, &tmp0, &tmp1); - T::average(&tmp5, &tmp2, &tmp3); - - T::average(dst, &tmp4, &tmp5); - } - } - } -} - - -typedef void (*MipGenerationFunction)(unsigned int sourceWidth, unsigned int sourceHeight, unsigned int sourceDepth, - const unsigned char *sourceData, int sourceRowPitch, int sourceDepthPitch, - unsigned int destWidth, unsigned int destHeight, unsigned int destDepth, - unsigned char *destData, int destRowPitch, int destDepthPitch); - -template -static MipGenerationFunction GetMipGenerationFunction(unsigned int sourceWidth, unsigned int sourceHeight, unsigned int sourceDepth) -{ - unsigned char index = ((sourceWidth > 1) ? 1 : 0) | - ((sourceHeight > 1) ? 2 : 0) | - ((sourceDepth > 1) ? 4 : 0); - - switch (index) - { - case 1: return GenerateMip_X; // W x 1 x 1 - case 2: return GenerateMip_Y; // 1 x H x 1 - case 3: return GenerateMip_XY; // W x H x 1 - case 4: return GenerateMip_Z; // 1 x 1 x D - case 5: return GenerateMip_XZ; // W x 1 x D - case 6: return GenerateMip_YZ; // 1 x H x D - case 7: return GenerateMip_XYZ; // W x H x D - default: return NULL; - } -} +inline void GenerateMip(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch); } -template -static void GenerateMip(unsigned int sourceWidth, unsigned int sourceHeight, unsigned int sourceDepth, - const unsigned char *sourceData, int sourceRowPitch, int sourceDepthPitch, - unsigned char *destData, int destRowPitch, int destDepthPitch) -{ - unsigned int mipWidth = std::max(1U, sourceWidth >> 1); - unsigned int mipHeight = std::max(1U, sourceHeight >> 1); - unsigned int mipDepth = std::max(1U, sourceDepth >> 1); - - priv::MipGenerationFunction generationFunction = priv::GetMipGenerationFunction(sourceWidth, sourceHeight, sourceDepth); - ASSERT(generationFunction != NULL); - - generationFunction(sourceWidth, sourceHeight, sourceDepth, sourceData, sourceRowPitch, sourceDepthPitch, - mipWidth, mipHeight, mipDepth, destData, destRowPitch, destDepthPitch); -} - -} +#include "generatemip.inl" #endif // LIBGLESV2_RENDERER_GENERATEMIP_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/generatemip.inl b/gfx/angle/src/libGLESv2/renderer/generatemip.inl new file mode 100644 index 000000000000..6788a42f03c0 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/generatemip.inl @@ -0,0 +1,266 @@ +// +// Copyright (c) 2014 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.inl: Defines the GenerateMip function, templated on the format +// type of the image for which mip levels are being generated. + +#include "common/mathutil.h" + +namespace rx +{ + +namespace priv +{ + +template +static inline T *GetPixel(uint8_t *data, size_t x, size_t y, size_t z, size_t rowPitch, size_t depthPitch) +{ + return reinterpret_cast(data + (x * sizeof(T)) + (y * rowPitch) + (z * depthPitch)); +} + +template +static inline const T *GetPixel(const uint8_t *data, size_t x, size_t y, size_t z, size_t rowPitch, size_t depthPitch) +{ + return reinterpret_cast(data + (x * sizeof(T)) + (y * rowPitch) + (z * depthPitch)); +} + +template +static void GenerateMip_Y(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + size_t destWidth, size_t destHeight, size_t destDepth, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) +{ + ASSERT(sourceWidth == 1); + ASSERT(sourceHeight > 1); + ASSERT(sourceDepth == 1); + + for (size_t y = 0; y < destHeight; y++) + { + const T *src0 = GetPixel(sourceData, 0, y * 2, 0, sourceRowPitch, sourceDepthPitch); + const T *src1 = GetPixel(sourceData, 0, y * 2 + 1, 0, sourceRowPitch, sourceDepthPitch); + T *dst = GetPixel(destData, 0, y, 0, destRowPitch, destDepthPitch); + + T::average(dst, src0, src1); + } +} + +template +static void GenerateMip_X(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + size_t destWidth, size_t destHeight, size_t destDepth, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) +{ + ASSERT(sourceWidth > 1); + ASSERT(sourceHeight == 1); + ASSERT(sourceDepth == 1); + + for (size_t x = 0; x < destWidth; x++) + { + const T *src0 = GetPixel(sourceData, x * 2, 0, 0, sourceRowPitch, sourceDepthPitch); + const T *src1 = GetPixel(sourceData, x * 2 + 1, 0, 0, sourceRowPitch, sourceDepthPitch); + T *dst = GetPixel(destData, x, 0, 0, destRowPitch, destDepthPitch); + + T::average(dst, src0, src1); + } +} + +template +static void GenerateMip_Z(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + size_t destWidth, size_t destHeight, size_t destDepth, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) +{ + ASSERT(sourceWidth == 1); + ASSERT(sourceHeight == 1); + ASSERT(sourceDepth > 1); + + for (size_t z = 0; z < destDepth; z++) + { + const T *src0 = GetPixel(sourceData, 0, 0, z * 2, sourceRowPitch, sourceDepthPitch); + const T *src1 = GetPixel(sourceData, 0, 0, z * 2 + 1, sourceRowPitch, sourceDepthPitch); + T *dst = GetPixel(destData, 0, 0, z, destRowPitch, destDepthPitch); + + T::average(dst, src0, src1); + } +} + +template +static void GenerateMip_XY(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + size_t destWidth, size_t destHeight, size_t destDepth, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) +{ + ASSERT(sourceWidth > 1); + ASSERT(sourceHeight > 1); + ASSERT(sourceDepth == 1); + + for (size_t y = 0; y < destHeight; y++) + { + for (size_t x = 0; x < destWidth; x++) + { + const T *src0 = GetPixel(sourceData, x * 2, y * 2, 0, sourceRowPitch, sourceDepthPitch); + const T *src1 = GetPixel(sourceData, x * 2, y * 2 + 1, 0, sourceRowPitch, sourceDepthPitch); + const T *src2 = GetPixel(sourceData, x * 2 + 1, y * 2, 0, sourceRowPitch, sourceDepthPitch); + const T *src3 = GetPixel(sourceData, x * 2 + 1, y * 2 + 1, 0, sourceRowPitch, sourceDepthPitch); + T *dst = GetPixel(destData, x, y, 0, destRowPitch, destDepthPitch); + + T tmp0, tmp1; + + T::average(&tmp0, src0, src1); + T::average(&tmp1, src2, src3); + T::average(dst, &tmp0, &tmp1); + } + } +} + +template +static void GenerateMip_YZ(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + size_t destWidth, size_t destHeight, size_t destDepth, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) +{ + ASSERT(sourceWidth == 1); + ASSERT(sourceHeight > 1); + ASSERT(sourceDepth > 1); + + for (size_t z = 0; z < destDepth; z++) + { + for (size_t y = 0; y < destHeight; y++) + { + const T *src0 = GetPixel(sourceData, 0, y * 2, z * 2, sourceRowPitch, sourceDepthPitch); + const T *src1 = GetPixel(sourceData, 0, y * 2, z * 2 + 1, sourceRowPitch, sourceDepthPitch); + const T *src2 = GetPixel(sourceData, 0, y * 2 + 1, z * 2, sourceRowPitch, sourceDepthPitch); + const T *src3 = GetPixel(sourceData, 0, y * 2 + 1, z * 2 + 1, sourceRowPitch, sourceDepthPitch); + T *dst = GetPixel(destData, 0, y, z, destRowPitch, destDepthPitch); + + T tmp0, tmp1; + + T::average(&tmp0, src0, src1); + T::average(&tmp1, src2, src3); + T::average(dst, &tmp0, &tmp1); + } + } +} + +template +static void GenerateMip_XZ(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + size_t destWidth, size_t destHeight, size_t destDepth, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) +{ + ASSERT(sourceWidth > 1); + ASSERT(sourceHeight == 1); + ASSERT(sourceDepth > 1); + + for (size_t z = 0; z < destDepth; z++) + { + for (size_t x = 0; x < destWidth; x++) + { + const T *src0 = GetPixel(sourceData, x * 2, 0, z * 2, sourceRowPitch, sourceDepthPitch); + const T *src1 = GetPixel(sourceData, x * 2, 0, z * 2 + 1, sourceRowPitch, sourceDepthPitch); + const T *src2 = GetPixel(sourceData, x * 2 + 1, 0, z * 2, sourceRowPitch, sourceDepthPitch); + const T *src3 = GetPixel(sourceData, x * 2 + 1, 0, z * 2 + 1, sourceRowPitch, sourceDepthPitch); + T *dst = GetPixel(destData, x, 0, z, destRowPitch, destDepthPitch); + + T tmp0, tmp1; + + T::average(&tmp0, src0, src1); + T::average(&tmp1, src2, src3); + T::average(dst, &tmp0, &tmp1); + } + } +} + +template +static void GenerateMip_XYZ(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + size_t destWidth, size_t destHeight, size_t destDepth, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) +{ + ASSERT(sourceWidth > 1); + ASSERT(sourceHeight > 1); + ASSERT(sourceDepth > 1); + + for (size_t z = 0; z < destDepth; z++) + { + for (size_t y = 0; y < destHeight; y++) + { + for (size_t x = 0; x < destWidth; x++) + { + const T *src0 = GetPixel(sourceData, x * 2, y * 2, z * 2, sourceRowPitch, sourceDepthPitch); + const T *src1 = GetPixel(sourceData, x * 2, y * 2, z * 2 + 1, sourceRowPitch, sourceDepthPitch); + const T *src2 = GetPixel(sourceData, x * 2, y * 2 + 1, z * 2, sourceRowPitch, sourceDepthPitch); + const T *src3 = GetPixel(sourceData, x * 2, y * 2 + 1, z * 2 + 1, sourceRowPitch, sourceDepthPitch); + const T *src4 = GetPixel(sourceData, x * 2 + 1, y * 2, z * 2, sourceRowPitch, sourceDepthPitch); + const T *src5 = GetPixel(sourceData, x * 2 + 1, y * 2, z * 2 + 1, sourceRowPitch, sourceDepthPitch); + const T *src6 = GetPixel(sourceData, x * 2 + 1, y * 2 + 1, z * 2, sourceRowPitch, sourceDepthPitch); + const T *src7 = GetPixel(sourceData, x * 2 + 1, y * 2 + 1, z * 2 + 1, sourceRowPitch, sourceDepthPitch); + T *dst = GetPixel(destData, x, y, z, destRowPitch, destDepthPitch); + + T tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + + T::average(&tmp0, src0, src1); + T::average(&tmp1, src2, src3); + T::average(&tmp2, src4, src5); + T::average(&tmp3, src6, src7); + + T::average(&tmp4, &tmp0, &tmp1); + T::average(&tmp5, &tmp2, &tmp3); + + T::average(dst, &tmp4, &tmp5); + } + } + } +} + + +typedef void (*MipGenerationFunction)(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + size_t destWidth, size_t destHeight, size_t destDepth, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch); + +template +static MipGenerationFunction GetMipGenerationFunction(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth) +{ + uint8_t index = ((sourceWidth > 1) ? 1 : 0) | + ((sourceHeight > 1) ? 2 : 0) | + ((sourceDepth > 1) ? 4 : 0); + + switch (index) + { + case 0: return NULL; + case 1: return GenerateMip_X; // W x 1 x 1 + case 2: return GenerateMip_Y; // 1 x H x 1 + case 3: return GenerateMip_XY; // W x H x 1 + case 4: return GenerateMip_Z; // 1 x 1 x D + case 5: return GenerateMip_XZ; // W x 1 x D + case 6: return GenerateMip_YZ; // 1 x H x D + case 7: return GenerateMip_XYZ; // W x H x D + } + + UNREACHABLE(); + return NULL; +} + +} + +template +inline void GenerateMip(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) +{ + size_t mipWidth = std::max(1, sourceWidth >> 1); + size_t mipHeight = std::max(1, sourceHeight >> 1); + size_t mipDepth = std::max(1, sourceDepth >> 1); + + priv::MipGenerationFunction generationFunction = priv::GetMipGenerationFunction(sourceWidth, sourceHeight, sourceDepth); + ASSERT(generationFunction != NULL); + + generationFunction(sourceWidth, sourceHeight, sourceDepth, sourceData, sourceRowPitch, sourceDepthPitch, + mipWidth, mipHeight, mipDepth, destData, destRowPitch, destDepthPitch); +} + +} diff --git a/gfx/angle/src/libGLESv2/renderer/imageformats.h b/gfx/angle/src/libGLESv2/renderer/imageformats.h index 1fd93fe56e19..2140a9ee7243 100644 --- a/gfx/angle/src/libGLESv2/renderer/imageformats.h +++ b/gfx/angle/src/libGLESv2/renderer/imageformats.h @@ -10,7 +10,7 @@ #ifndef LIBGLESV2_RENDERER_IMAGEFORMATS_H_ #define LIBGLESV2_RENDERER_IMAGEFORMATS_H_ -#include "libGLESv2/angletypes.h" +#include "common/mathutil.h" namespace rx { diff --git a/gfx/angle/src/libGLESv2/renderer/loadimage.cpp b/gfx/angle/src/libGLESv2/renderer/loadimage.cpp index 6e2d2460a52b..1986191a75b6 100644 --- a/gfx/angle/src/libGLESv2/renderer/loadimage.cpp +++ b/gfx/angle/src/libGLESv2/renderer/loadimage.cpp @@ -1,6 +1,5 @@ -#include "precompiled.h" // -// Copyright (c) 0013 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2013-2014 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 +11,64 @@ namespace rx { -void loadAlphaDataToBGRA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) +void LoadA8ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) { - const unsigned char *source = NULL; - unsigned char *dest = NULL; - - for (int z = 0; z < depth; z++) + for (size_t z = 0; z < depth; z++) { - for (int y = 0; y < height; y++) + for (size_t y = 0; y < height; y++) { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (int x = 0; x < width; x++) + const uint8_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint32_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[x] = static_cast(source[x]) << 24; + } + } + } +} + +void LoadA8ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + // Same as loading to RGBA + LoadA8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch); +} + +void LoadA32FToRGBA32F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const float *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + float *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[4 * x + 0] = 0.0f; + dest[4 * x + 1] = 0.0f; + dest[4 * x + 2] = 0.0f; + dest[4 * x + 3] = source[x]; + } + } + } +} + +void LoadA16FToRGBA16F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint16_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) { dest[4 * x + 0] = 0; dest[4 * x + 1] = 0; @@ -36,104 +79,17 @@ void loadAlphaDataToBGRA(int width, int height, int depth, } } -void loadAlphaDataToNative(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) +void LoadL8ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) { - const unsigned char *source = NULL; - unsigned char *dest = NULL; - - for (int z = 0; z < depth; z++) + for (size_t z = 0; z < depth; z++) { - for (int y = 0; y < height; y++) + for (size_t y = 0; y < height; y++) { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - memcpy(dest, source, width); - } - } -} - -void loadAlphaFloatDataToRGBA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) -{ - const float *source = NULL; - float *dest = NULL; - - for (int z = 0; z < depth; z++) - { - for (int y = 0; y < height; y++) - { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - 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 loadAlphaHalfFloatDataToRGBA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) -{ - const unsigned short *source = NULL; - unsigned short *dest = NULL; - - for (int z = 0; z < depth; z++) - { - for (int y = 0; y < height; y++) - { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - 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 loadLuminanceDataToNative(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) -{ - const unsigned char *source = NULL; - unsigned char *dest = NULL; - - for (int z = 0; z < depth; z++) - { - for (int y = 0; y < height; y++) - { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - memcpy(dest, source, width); - } - } -} - -void loadLuminanceDataToBGRA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) -{ - const unsigned char *source = NULL; - unsigned char *dest = NULL; - - for (int z = 0; z < depth; z++) - { - for (int y = 0; y < height; y++) - { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (int x = 0; x < width; x++) + const uint8_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) { dest[4 * x + 0] = source[x]; dest[4 * x + 1] = source[x]; @@ -144,20 +100,25 @@ void loadLuminanceDataToBGRA(int width, int height, int depth, } } -void loadLuminanceFloatDataToRGBA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) +void LoadL8ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) { - const float *source = NULL; - float *dest = NULL; + // Same as loading to RGBA + LoadL8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch); +} - for (int z = 0; z < depth; z++) +void LoadL32FToRGBA32F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) { - for (int y = 0; y < height; y++) + for (size_t y = 0; y < height; y++) { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (int x = 0; x < width; x++) + const float *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + float *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) { dest[4 * x + 0] = source[x]; dest[4 * x + 1] = source[x]; @@ -168,43 +129,17 @@ void loadLuminanceFloatDataToRGBA(int width, int height, int depth, } } -void loadLuminanceFloatDataToRGB(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) +void LoadL16FToRGBA16F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) { - const float *source = NULL; - float *dest = NULL; - - for (int z = 0; z < depth; z++) + for (size_t z = 0; z < depth; z++) { - for (int y = 0; y < height; y++) + for (size_t y = 0; y < height; y++) { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - 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 loadLuminanceHalfFloatDataToRGBA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) -{ - const unsigned short *source = NULL; - unsigned short *dest = NULL; - - for (int z = 0; z < depth; z++) - { - for (int y = 0; y < height; y++) - { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (int x = 0; x < width; x++) + const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint16_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) { dest[4 * x + 0] = source[x]; dest[4 * x + 1] = source[x]; @@ -215,112 +150,88 @@ void loadLuminanceHalfFloatDataToRGBA(int width, int height, int depth, } } -void loadLuminanceAlphaDataToNative(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) +void LoadLA8ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) { - const unsigned char *source = NULL; - unsigned char *dest = NULL; - - for (int z = 0; z < depth; z++) + for (size_t z = 0; z < depth; z++) { - for (int y = 0; y < height; y++) + for (size_t y = 0; y < height; y++) { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - - memcpy(dest, source, width * 2); - } - } -} - -void loadLuminanceAlphaDataToBGRA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) -{ - const unsigned char *source = NULL; - unsigned char *dest = NULL; - - for (int z = 0; z < depth; z++) - { - for (int y = 0; y < height; y++) - { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - - for (int x = 0; x < width; x++) + const uint8_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t 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]; + 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 loadLuminanceAlphaFloatDataToRGBA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) +void LoadLA8ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) { - const float *source = NULL; - float *dest = NULL; + // Same as loading to RGBA + LoadLA8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch); +} - for (int z = 0; z < depth; z++) +void LoadLA32FToRGBA32F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) { - for (int y = 0; y < height; y++) + for (size_t y = 0; y < height; y++) { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (int x = 0; x < width; x++) + const float *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + float *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t 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]; + 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 loadLuminanceAlphaHalfFloatDataToRGBA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) +void LoadLA16FToRGBA16F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) { - const unsigned short *source = NULL; - unsigned short *dest = NULL; - - for (int z = 0; z < depth; z++) + for (size_t z = 0; z < depth; z++) { - for (int y = 0; y < height; y++) + for (size_t y = 0; y < height; y++) { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (int x = 0; x < width; x++) + const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint16_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t 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]; + 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 loadRGBUByteDataToBGRX(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) +void LoadRGB8ToBGRX8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) { - const unsigned char *source = NULL; - unsigned char *dest = NULL; - - for (int z = 0; z < depth; z++) + for (size_t z = 0; z < depth; z++) { - for (int y = 0; y < height; y++) + for (size_t y = 0; y < height; y++) { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (int x = 0; x < width; x++) + const uint8_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) { dest[4 * x + 0] = source[x * 3 + 2]; dest[4 * x + 1] = source[x * 3 + 1]; @@ -331,20 +242,17 @@ void loadRGBUByteDataToBGRX(int width, int height, int depth, } } -void loadRGUByteDataToBGRX(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) +void LoadRG8ToBGRX8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) { - const unsigned char *source = NULL; - unsigned char *dest = NULL; - - for (int z = 0; z < depth; z++) + for (size_t z = 0; z < depth; z++) { - for (int y = 0; y < height; y++) + for (size_t y = 0; y < height; y++) { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (int x = 0; x < width; x++) + const uint8_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) { dest[4 * x + 0] = 0x00; dest[4 * x + 1] = source[x * 2 + 1]; @@ -355,20 +263,17 @@ void loadRGUByteDataToBGRX(int width, int height, int depth, } } -void loadRUByteDataToBGRX(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) +void LoadR8ToBGRX8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) { - const unsigned char *source = NULL; - unsigned char *dest = NULL; - - for (int z = 0; z < depth; z++) + for (size_t z = 0; z < depth; z++) { - for (int y = 0; y < height; y++) + for (size_t y = 0; y < height; y++) { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (int x = 0; x < width; x++) + const uint8_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) { dest[4 * x + 0] = 0x00; dest[4 * x + 1] = 0x00; @@ -379,228 +284,82 @@ void loadRUByteDataToBGRX(int width, int height, int depth, } } -void loadRGBUByteDataToRGBA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) +void LoadR5G6B5ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) { - const unsigned char *source = NULL; - unsigned char *dest = NULL; - - for (int z = 0; z < depth; z++) + for (size_t z = 0; z < depth; z++) { - for (int y = 0; y < height; y++) + for (size_t y = 0; y < height; y++) { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (int x = 0; x < width; x++) + const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t 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]; + uint16_t rgb = source[x]; + dest[4 * x + 0] = ((rgb & 0x001F) << 3) | ((rgb & 0x001F) >> 2); + dest[4 * x + 1] = ((rgb & 0x07E0) >> 3) | ((rgb & 0x07E0) >> 9); + dest[4 * x + 2] = ((rgb & 0xF800) >> 8) | ((rgb & 0xF800) >> 13); dest[4 * x + 3] = 0xFF; } } } } -void loadRGBSByteDataToRGBA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) +void LoadR5G6B5ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) { - const char *source = NULL; - char *dest = NULL; - - for (int z = 0; z < depth; z++) + for (size_t z = 0; z < depth; z++) { - for (int y = 0; y < height; y++) + for (size_t y = 0; y < height; y++) { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (int x = 0; x < width; x++) + const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t 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] = 0x7F; - } - } - } -} - -void loadRGB565DataToBGRA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) -{ - const unsigned short *source = NULL; - unsigned char *dest = NULL; - - for (int z = 0; z < depth; z++) - { - for (int y = 0; y < height; y++) - { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - 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); + uint16_t rgb = source[x]; + dest[4 * x + 0] = ((rgb & 0xF800) >> 8) | ((rgb & 0xF800) >> 13); + dest[4 * x + 1] = ((rgb & 0x07E0) >> 3) | ((rgb & 0x07E0) >> 9); + dest[4 * x + 2] = ((rgb & 0x001F) << 3) | ((rgb & 0x001F) >> 2); dest[4 * x + 3] = 0xFF; } } } } -void loadRGB565DataToRGBA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) +void LoadRGBA8ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) { - const unsigned short *source = NULL; - unsigned char *dest = NULL; - - for (int z = 0; z < depth; z++) + for (size_t z = 0; z < depth; z++) { - for (int y = 0; y < height; y++) + for (size_t y = 0; y < height; y++) { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (int x = 0; x < width; x++) + const uint32_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint32_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t 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 loadRGBFloatDataToRGBA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) -{ - const float *source = NULL; - float *dest = NULL; - - for (int z = 0; z < depth; z++) - { - for (int y = 0; y < height; y++) - { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - 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 loadRGBFloatDataToNative(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) -{ - const float *source = NULL; - float *dest = NULL; - - for (int z = 0; z < depth; z++) - { - for (int y = 0; y < height; y++) - { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - memcpy(dest, source, width * 12); - } - } -} - -void loadRGBHalfFloatDataToRGBA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) -{ - const unsigned short *source = NULL; - unsigned short *dest = NULL; - - for (int z = 0; z < depth; z++) - { - for (int y = 0; y < height; y++) - { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - 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 loadRGBAUByteDataToBGRA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) -{ - const unsigned int *source = NULL; - unsigned int *dest = NULL; - - for (int z = 0; z < depth; z++) - { - for (int y = 0; y < height; y++) - { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - - for (int x = 0; x < width; x++) - { - unsigned int rgba = source[x]; + uint32_t rgba = source[x]; dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00); } } } } -void loadRGBAUByteDataToNative(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) +void LoadRGBA4ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) { - const unsigned int *source = NULL; - unsigned int *dest = NULL; - - for (int z = 0; z < depth; z++) + for (size_t z = 0; z < depth; z++) { - for (int y = 0; y < height; y++) + for (size_t y = 0; y < height; y++) { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - - memcpy(dest, source, width * 4); - } - } -} - -void loadRGBA4444DataToBGRA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) -{ - const unsigned short *source = NULL; - unsigned char *dest = NULL; - - for (int z = 0; z < depth; z++) - { - for (int y = 0; y < height; y++) - { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (int x = 0; x < width; x++) + const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) { - unsigned short rgba = source[x]; + uint16_t 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); @@ -610,22 +369,19 @@ void loadRGBA4444DataToBGRA(int width, int height, int depth, } } -void loadRGBA4444DataToRGBA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) +void LoadRGBA4ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) { - const unsigned short *source = NULL; - unsigned char *dest = NULL; - - for (int z = 0; z < depth; z++) + for (size_t z = 0; z < depth; z++) { - for (int y = 0; y < height; y++) + for (size_t y = 0; y < height; y++) { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (int x = 0; x < width; x++) + const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) { - unsigned short rgba = source[x]; + uint16_t 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); @@ -635,22 +391,41 @@ void loadRGBA4444DataToRGBA(int width, int height, int depth, } } -void loadRGBA5551DataToBGRA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) +void LoadBGRA4ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) { - const unsigned short *source = NULL; - unsigned char *dest = NULL; - - for (int z = 0; z < depth; z++) + for (size_t z = 0; z < depth; z++) { - for (int y = 0; y < height; y++) + for (size_t y = 0; y < height; y++) { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (int x = 0; x < width; x++) + const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) { - unsigned short rgba = source[x]; + uint16_t bgra = source[x]; + dest[4 * x + 0] = ((bgra & 0xF000) >> 8) | ((bgra & 0xF000) >> 12); + dest[4 * x + 1] = ((bgra & 0x0F00) >> 4) | ((bgra & 0x0F00) >> 8); + dest[4 * x + 2] = ((bgra & 0x00F0) << 0) | ((bgra & 0x00F0) >> 4); + dest[4 * x + 3] = ((bgra & 0x000F) << 4) | ((bgra & 0x000F) >> 0); + } + } + } +} + +void LoadRGB5A1ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + uint16_t 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); @@ -659,22 +434,20 @@ void loadRGBA5551DataToBGRA(int width, int height, int depth, } } } -void loadRGBA5551DataToRGBA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) -{ - const unsigned short *source = NULL; - unsigned char *dest = NULL; - for (int z = 0; z < depth; z++) +void LoadRGB5A1ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) { - for (int y = 0; y < height; y++) + for (size_t y = 0; y < height; y++) { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (int x = 0; x < width; x++) + const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) { - unsigned short rgba = source[x]; + uint16_t 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); @@ -684,95 +457,42 @@ void loadRGBA5551DataToRGBA(int width, int height, int depth, } } -void loadRGBAFloatDataToRGBA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) + +void LoadBGR5A1ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) { - const float *source = NULL; - float *dest = NULL; - - for (int z = 0; z < depth; z++) + for (size_t z = 0; z < depth; z++) { - for (int y = 0; y < height; y++) + for (size_t y = 0; y < height; y++) { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - memcpy(dest, source, width * 16); - } - } -} - -void loadRGBAHalfFloatDataToRGBA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) -{ - const unsigned char *source = NULL; - unsigned char *dest = NULL; - - for (int z = 0; z < depth; z++) - { - for (int y = 0; y < height; y++) - { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - memcpy(dest, source, width * 8); - } - } -} - -void loadBGRADataToBGRA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) -{ - const unsigned char *source = NULL; - unsigned char *dest = NULL; - - for (int z = 0; z < depth; z++) - { - for (int y = 0; y < height; y++) - { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - memcpy(dest, source, width*4); - } - } -} - -void loadRGBA2101010ToNative(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) -{ - const unsigned int *source = NULL; - unsigned int *dest = NULL; - - for (int z = 0; z < depth; z++) - { - for (int y = 0; y < height; y++) - { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - memcpy(dest, source, width * sizeof(unsigned int)); - } - } -} - -void loadRGBA2101010ToRGBA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) -{ - const unsigned int *source = NULL; - unsigned char *dest = NULL; - - for (int z = 0; z < depth; z++) - { - for (int y = 0; y < height; y++) - { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - - for (int x = 0; x < width; x++) + const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) { - unsigned int rgba = source[x]; + uint16_t bgra = source[x]; + dest[4 * x + 0] = ((bgra & 0xF800) >> 8) | ((bgra & 0xF800) >> 13); + dest[4 * x + 1] = ((bgra & 0x07C0) >> 3) | ((bgra & 0x07C0) >> 8); + dest[4 * x + 2] = ((bgra & 0x003E) << 2) | ((bgra & 0x003E) >> 3); + dest[4 * x + 3] = (bgra & 0x0001) ? 0xFF : 0; + } + } + } +} + +void LoadRGB10A2ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint32_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + uint32_t rgba = source[x]; dest[4 * x + 0] = (rgba & 0x000003FF) >> 2; dest[4 * x + 1] = (rgba & 0x000FFC00) >> 12; dest[4 * x + 2] = (rgba & 0x3FF00000) >> 22; @@ -782,21 +502,17 @@ void loadRGBA2101010ToRGBA(int width, int height, int depth, } } -void loadRGBHalfFloatDataTo999E5(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) +void LoadRGB16FToRGB9E5(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) { - const unsigned short *source = NULL; - unsigned int *dest = NULL; - - for (int z = 0; z < depth; z++) + for (size_t z = 0; z < depth; z++) { - for (int y = 0; y < height; y++) + for (size_t y = 0; y < height; y++) { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - - for (int x = 0; x < width; x++) + const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint32_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) { dest[x] = gl::convertRGBFloatsTo999E5(gl::float16ToFloat32(source[x * 3 + 0]), gl::float16ToFloat32(source[x * 3 + 1]), @@ -806,21 +522,17 @@ void loadRGBHalfFloatDataTo999E5(int width, int height, int depth, } } -void loadRGBFloatDataTo999E5(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) +void LoadRGB32FToRGB9E5(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) { - const float *source = NULL; - unsigned int *dest = NULL; - - for (int z = 0; z < depth; z++) + for (size_t z = 0; z < depth; z++) { - for (int y = 0; y < height; y++) + for (size_t y = 0; y < height; y++) { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - - for (int x = 0; x < width; x++) + const float *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint32_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) { dest[x] = gl::convertRGBFloatsTo999E5(source[x * 3 + 0], source[x * 3 + 1], source[x * 3 + 2]); } @@ -828,21 +540,17 @@ void loadRGBFloatDataTo999E5(int width, int height, int depth, } } -void loadRGBHalfFloatDataTo111110Float(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) +void LoadRGB16FToRG11B10F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) { - const unsigned short *source = NULL; - unsigned int *dest = NULL; - - for (int z = 0; z < depth; z++) + for (size_t z = 0; z < depth; z++) { - for (int y = 0; y < height; y++) + for (size_t y = 0; y < height; y++) { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - - for (int x = 0; x < width; x++) + const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint32_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) { dest[x] = (gl::float32ToFloat11(gl::float16ToFloat32(source[x * 3 + 0])) << 0) | (gl::float32ToFloat11(gl::float16ToFloat32(source[x * 3 + 1])) << 11) | @@ -852,21 +560,17 @@ void loadRGBHalfFloatDataTo111110Float(int width, int height, int depth, } } -void loadRGBFloatDataTo111110Float(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) +void LoadRGB32FToRG11B10F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) { - const float *source = NULL; - unsigned int *dest = NULL; - - for (int z = 0; z < depth; z++) + for (size_t z = 0; z < depth; z++) { - for (int y = 0; y < height; y++) + for (size_t y = 0; y < height; y++) { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - - for (int x = 0; x < width; x++) + const float *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint32_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) { dest[x] = (gl::float32ToFloat11(source[x * 3 + 0]) << 0) | (gl::float32ToFloat11(source[x * 3 + 1]) << 11) | @@ -876,46 +580,37 @@ void loadRGBFloatDataTo111110Float(int width, int height, int depth, } } - -void loadG8R24DataToR24G8(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) +void LoadG8R24ToR24G8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) { - const unsigned int *source = NULL; - unsigned int *dest = NULL; - - for (int z = 0; z < depth; z++) + for (size_t z = 0; z < depth; z++) { - for (int y = 0; y < height; y++) + for (size_t y = 0; y < height; y++) { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - - for (int x = 0; x < width; x++) + const uint32_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint32_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) { - unsigned int d = source[x] >> 8; - unsigned int s = source[x] & 0xFF; + uint32_t d = source[x] >> 8; + uint8_t s = source[x] & 0xFF; dest[x] = d | (s << 24); } } } } -void loadFloatRGBDataToHalfFloatRGBA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) +void LoadRGB32FToRGBA16F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) { - const float *source = NULL; - unsigned short *dest = NULL; - - for (int z = 0; z < depth; z++) + for (size_t z = 0; z < depth; z++) { - for (int y = 0; y < height; y++) + for (size_t y = 0; y < height; y++) { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - - for (int x = 0; x < width; x++) + const float *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint16_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) { dest[x * 4 + 0] = gl::float32ToFloat16(source[x * 3 + 0]); dest[x * 4 + 1] = gl::float32ToFloat16(source[x * 3 + 1]); @@ -926,21 +621,17 @@ void loadFloatRGBDataToHalfFloatRGBA(int width, int height, int depth, } } -void loadUintDataToUshort(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) +void LoadR32ToR16(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) { - const unsigned int *source = NULL; - unsigned short *dest = NULL; - - for (int z = 0; z < depth; z++) + for (size_t z = 0; z < depth; z++) { - for (int y = 0; y < height; y++) + for (size_t y = 0; y < height; y++) { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - - for (int x = 0; x < width; x++) + const uint32_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint16_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) { dest[x] = source[x] >> 16; } @@ -948,4 +639,23 @@ void loadUintDataToUshort(int width, int height, int depth, } } +void LoadR32ToR24G8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint32_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint32_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + + for (size_t x = 0; x < width; x++) + { + dest[x] = source[x] >> 8; + } + } + } +} + } diff --git a/gfx/angle/src/libGLESv2/renderer/loadimage.h b/gfx/angle/src/libGLESv2/renderer/loadimage.h index 537a5e4c1706..bcdff24a6639 100644 --- a/gfx/angle/src/libGLESv2/renderer/loadimage.h +++ b/gfx/angle/src/libGLESv2/renderer/loadimage.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2013-2014 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,335 +9,185 @@ #ifndef LIBGLESV2_RENDERER_LOADIMAGE_H_ #define LIBGLESV2_RENDERER_LOADIMAGE_H_ -#include "common/mathutil.h" +#include "libGLESv2/angletypes.h" + +#include namespace rx { -template -inline static T *offsetDataPointer(void *data, int y, int z, int rowPitch, int depthPitch) -{ - return reinterpret_cast(reinterpret_cast(data) + (y * rowPitch) + (z * depthPitch)); -} +void LoadA8ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadA8ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadA32FToRGBA32F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadA16FToRGBA16F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadL8ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadL8ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadL32FToRGBA32F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadL16FToRGBA16F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadLA8ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadLA8ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadLA32FToRGBA32F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadLA16FToRGBA16F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGB8ToBGRX8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRG8ToBGRX8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadR8ToBGRX8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadR5G6B5ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadR5G6B5ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGBA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGBA8ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGBA4ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGBA4ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadBGRA4ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGB5A1ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGB5A1ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadBGR5A1ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGB10A2ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGB16FToRGB9E5(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGB32FToRGB9E5(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGB16FToRG11B10F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGB32FToRG11B10F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadG8R24ToR24G8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +template +inline void LoadToNative(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +template +inline void LoadToNative3To4(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +template +inline void Load32FTo16F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGB32FToRGBA16F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +template +inline void LoadCompressedToNative(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadR32ToR16(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +template +inline void Initialize4ComponentData(size_t width, size_t height, size_t depth, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadR32ToR24G8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); template -inline static const T *offsetDataPointer(const void *data, int y, int z, int rowPitch, int depthPitch) -{ - return reinterpret_cast(reinterpret_cast(data) + (y * rowPitch) + (z * depthPitch)); -} +inline T *OffsetDataPointer(uint8_t *data, size_t y, size_t z, size_t rowPitch, size_t depthPitch); -void loadAlphaDataToBGRA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -void loadAlphaDataToNative(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -void loadAlphaDataToBGRASSE2(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -void loadAlphaFloatDataToRGBA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -void loadAlphaHalfFloatDataToRGBA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -void loadLuminanceDataToNative(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -void loadLuminanceDataToBGRA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -void loadLuminanceFloatDataToRGBA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -void loadLuminanceFloatDataToRGB(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -void loadLuminanceHalfFloatDataToRGBA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -void loadLuminanceAlphaDataToNative(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -void loadLuminanceAlphaDataToBGRA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -void loadLuminanceAlphaFloatDataToRGBA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -void loadLuminanceAlphaHalfFloatDataToRGBA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -void loadRGBUByteDataToBGRX(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -void loadRGUByteDataToBGRX(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -void loadRUByteDataToBGRX(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -void loadRGBUByteDataToRGBA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -void loadRGBSByteDataToRGBA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -void loadRGB565DataToBGRA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -void loadRGB565DataToRGBA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -void loadRGBFloatDataToRGBA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -void loadRGBFloatDataToNative(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -void loadRGBHalfFloatDataToRGBA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -void loadRGBAUByteDataToBGRASSE2(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -void loadRGBAUByteDataToBGRA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -void loadRGBAUByteDataToNative(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -void loadRGBA4444DataToBGRA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -void loadRGBA4444DataToRGBA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -void loadRGBA5551DataToBGRA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -void loadRGBA5551DataToRGBA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -void loadRGBAFloatDataToRGBA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -void loadRGBAHalfFloatDataToRGBA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -void loadBGRADataToBGRA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -void loadRGBA2101010ToNative(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -void loadRGBA2101010ToRGBA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -void loadRGBHalfFloatDataTo999E5(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -void loadRGBFloatDataTo999E5(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -void loadRGBHalfFloatDataTo111110Float(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -void loadRGBFloatDataTo111110Float(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -void loadG8R24DataToR24G8(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -template -void loadToNative(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) -{ - const unsigned int rowSize = width * sizeof(type) * componentCount; - const unsigned int layerSize = rowSize * height; - const unsigned int imageSize = layerSize * depth; - - if (layerSize == inputDepthPitch && layerSize == outputDepthPitch) - { - ASSERT(rowSize == inputRowPitch && rowSize == outputRowPitch); - memcpy(output, input, imageSize); - } - else if (rowSize == inputRowPitch && rowSize == outputRowPitch) - { - for (int z = 0; z < depth; z++) - { - const type *source = offsetDataPointer(input, 0, z, inputRowPitch, inputDepthPitch); - type *dest = offsetDataPointer(output, 0, z, outputRowPitch, outputDepthPitch); - - memcpy(dest, source, layerSize); - } - } - else - { - for (int z = 0; z < depth; z++) - { - for (int y = 0; y < height; y++) - { - const type *source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - type *dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - memcpy(dest, source, width * sizeof(type) * componentCount); - } - } - } -} - -template -void loadToNative3To4(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) -{ - const type *source = NULL; - type *dest = NULL; - - const unsigned int fourthBits = fourthComponentBits; - const type fourthValue = *reinterpret_cast(&fourthBits); - - for (int z = 0; z < depth; z++) - { - for (int y = 0; y < height; y++) - { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - - for (int x = 0; x < width; x++) - { - dest[x * 4 + 0] = source[x * 3 + 0]; - dest[x * 4 + 1] = source[x * 3 + 1]; - dest[x * 4 + 2] = source[x * 3 + 2]; - dest[x * 4 + 3] = fourthValue; - } - } - } -} - -template -void loadFloatDataToHalfFloat(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) -{ - const float *source = NULL; - unsigned short *dest = NULL; - - const int elementWidth = componentCount * width; - - for (int z = 0; z < depth; z++) - { - for (int y = 0; y < height; y++) - { - source = offsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - dest = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - - for (int x = 0; x < elementWidth; x++) - { - dest[x] = gl::float32ToFloat16(source[x]); - } - } - } -} - -void loadFloatRGBDataToHalfFloatRGBA(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -template -void loadCompressedBlockDataToNative(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) -{ - int columns = (width + (blockWidth - 1)) / blockWidth; - int rows = (height + (blockHeight - 1)) / blockHeight; - - for (int z = 0; z < depth; ++z) - { - for (int y = 0; y < rows; ++y) - { - void *source = (void*)((char*)input + y * inputRowPitch + z * inputDepthPitch); - void *dest = (void*)((char*)output + y * outputRowPitch + z * outputDepthPitch); - - memcpy(dest, source, columns * blockSize); - } - } -} - -void loadUintDataToUshort(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch); - -template -void initialize4ComponentData(int width, int height, int depth, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) -{ - unsigned int writeBits[4] = { firstBits, secondBits, thirdBits, fourthBits }; - type writeValues[4] = { *reinterpret_cast(&writeBits[0]), - *reinterpret_cast(&writeBits[1]), - *reinterpret_cast(&writeBits[2]), - *reinterpret_cast(&writeBits[3]) }; - - for (int z = 0; z < depth; z++) - { - for (int y = 0; y < height; y++) - { - type* destRow = offsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - - for (int x = 0; x < width; x++) - { - type* destPixel = destRow + x * 4; - - // This could potentially be optimized by generating an entire row of initialization - // data and copying row by row instead of pixel by pixel. - memcpy(destPixel, writeValues, sizeof(type) * 4); - } - } - } -} +template +inline const T *OffsetDataPointer(const uint8_t *data, size_t y, size_t z, size_t rowPitch, size_t depthPitch); } +#include "loadimage.inl" + #endif // LIBGLESV2_RENDERER_LOADIMAGE_H_ diff --git a/gfx/angle/src/libGLESv2/renderer/loadimage.inl b/gfx/angle/src/libGLESv2/renderer/loadimage.inl new file mode 100644 index 000000000000..abd0a3673c29 --- /dev/null +++ b/gfx/angle/src/libGLESv2/renderer/loadimage.inl @@ -0,0 +1,156 @@ +// +// Copyright (c) 2014 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 "common/mathutil.h" + +namespace rx +{ + +template +inline T *OffsetDataPointer(uint8_t *data, size_t y, size_t z, size_t rowPitch, size_t depthPitch) +{ + return reinterpret_cast(data + (y * rowPitch) + (z * depthPitch)); +} + +template +inline const T *OffsetDataPointer(const uint8_t *data, size_t y, size_t z, size_t rowPitch, size_t depthPitch) +{ + return reinterpret_cast(data + (y * rowPitch) + (z * depthPitch)); +} + +template +inline void LoadToNative(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + const size_t rowSize = width * sizeof(type) * componentCount; + const size_t layerSize = rowSize * height; + const size_t imageSize = layerSize * depth; + + if (layerSize == inputDepthPitch && layerSize == outputDepthPitch) + { + ASSERT(rowSize == inputRowPitch && rowSize == outputRowPitch); + memcpy(output, input, imageSize); + } + else if (rowSize == inputRowPitch && rowSize == outputRowPitch) + { + for (size_t z = 0; z < depth; z++) + { + const type *source = OffsetDataPointer(input, 0, z, inputRowPitch, inputDepthPitch); + type *dest = OffsetDataPointer(output, 0, z, outputRowPitch, outputDepthPitch); + + memcpy(dest, source, layerSize); + } + } + else + { + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const type *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + type *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + memcpy(dest, source, width * sizeof(type) * componentCount); + } + } + } +} + +template +inline void LoadToNative3To4(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + const type fourthValue = gl::bitCast(fourthComponentBits); + + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const type *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + type *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[x * 4 + 0] = source[x * 3 + 0]; + dest[x * 4 + 1] = source[x * 3 + 1]; + dest[x * 4 + 2] = source[x * 3 + 2]; + dest[x * 4 + 3] = fourthValue; + } + } + } +} + +template +inline void Load32FTo16F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + const size_t elementWidth = componentCount * width; + + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const float *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint16_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + + for (size_t x = 0; x < elementWidth; x++) + { + dest[x] = gl::float32ToFloat16(source[x]); + } + } + } +} + +template +inline void LoadCompressedToNative(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + const size_t columns = (width + (blockWidth - 1)) / blockWidth; + const size_t rows = (height + (blockHeight - 1)) / blockHeight; + + for (size_t z = 0; z < depth; ++z) + { + for (size_t y = 0; y < rows; ++y) + { + const uint8_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + memcpy(dest, source, columns * blockSize); + } + } +} + +template +inline void Initialize4ComponentData(size_t width, size_t height, size_t depth, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + type writeValues[4] = + { + gl::bitCast(firstBits), + gl::bitCast(secondBits), + gl::bitCast(thirdBits), + gl::bitCast(fourthBits), + }; + + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + type *destRow = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + type* destPixel = destRow + x * 4; + + // This could potentially be optimized by generating an entire row of initialization + // data and copying row by row instead of pixel by pixel. + memcpy(destPixel, writeValues, sizeof(type) * 4); + } + } + } +} + +} diff --git a/gfx/angle/src/libGLESv2/renderer/loadimageSSE2.cpp b/gfx/angle/src/libGLESv2/renderer/loadimageSSE2.cpp index 129e39bbe20e..cc20d9497575 100644 --- a/gfx/angle/src/libGLESv2/renderer/loadimageSSE2.cpp +++ b/gfx/angle/src/libGLESv2/renderer/loadimageSSE2.cpp @@ -1,11 +1,10 @@ -#include "precompiled.h" // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2014 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. // -// loadimage.cpp: Defines image loading functions. It's +// loadimageSSE2.cpp: Defines image loading functions. It's // in a separated file for GCC, which can enable SSE usage only per-file, // not for code blocks that use SSE2 explicitly. @@ -14,94 +13,92 @@ namespace rx { - void loadAlphaDataToBGRASSE2(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) +void LoadA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + __m128i zeroWide = _mm_setzero_si128(); + + for (size_t z = 0; z < depth; z++) { - const unsigned char *source = NULL; - unsigned int *dest = NULL; - __m128i zeroWide = _mm_setzero_si128(); - - for (int z = 0; z < depth; z++) + for (size_t y = 0; y < height; y++) { - for (int y = 0; y < height; y++) + const uint8_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint32_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + + size_t x = 0; + + // Make output writes aligned + for (; ((reinterpret_cast(&dest[x]) & 0xF) != 0 && x < width); x++) { - source = static_cast(input) + y * inputRowPitch + z * inputDepthPitch; - dest = reinterpret_cast(static_cast(output) + y * outputRowPitch + z * outputDepthPitch); + dest[x] = static_cast(source[x]) << 24; + } - int x; - // Make output writes aligned - for (x = 0; ((reinterpret_cast(&dest[x]) & 0xF) != 0 && x < width); x++) - { - dest[x] = static_cast(source[x]) << 24; - } + for (; x + 7 < width; x += 8) + { + __m128i sourceData = _mm_loadl_epi64(reinterpret_cast(&source[x])); + // Interleave each byte to 16bit, make the lower byte to zero + sourceData = _mm_unpacklo_epi8(zeroWide, sourceData); + // Interleave each 16bit to 32bit, make the lower 16bit to zero + __m128i lo = _mm_unpacklo_epi16(zeroWide, sourceData); + __m128i hi = _mm_unpackhi_epi16(zeroWide, sourceData); - for (; x + 7 < width; x += 8) - { - __m128i sourceData = _mm_loadl_epi64(reinterpret_cast(&source[x])); - // Interleave each byte to 16bit, make the lower byte to zero - sourceData = _mm_unpacklo_epi8(zeroWide, sourceData); - // Interleave each 16bit to 32bit, make the lower 16bit to zero - __m128i lo = _mm_unpacklo_epi16(zeroWide, sourceData); - __m128i hi = _mm_unpackhi_epi16(zeroWide, sourceData); + _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x]), lo); + _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x + 4]), hi); + } - _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x]), lo); - _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x + 4]), hi); - } - - // Handle the remainder - for (; x < width; x++) - { - dest[x] = static_cast(source[x]) << 24; - } + // Handle the remainder + for (; x < width; x++) + { + dest[x] = static_cast(source[x]) << 24; } } } +} - void loadRGBAUByteDataToBGRASSE2(int width, int height, int depth, - const void *input, unsigned int inputRowPitch, unsigned int inputDepthPitch, - void *output, unsigned int outputRowPitch, unsigned int outputDepthPitch) +void LoadRGBA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + __m128i brMask = _mm_set1_epi32(0x00ff00ff); + + for (size_t z = 0; z < depth; z++) { - const unsigned int *source = NULL; - unsigned int *dest = NULL; - __m128i brMask = _mm_set1_epi32(0x00ff00ff); - - for (int z = 0; z < depth; z++) + for (size_t y = 0; y < height; y++) { - for (int y = 0; y < height; y++) + const uint32_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint32_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + + size_t x = 0; + + // Make output writes aligned + for (; ((reinterpret_cast(&dest[x]) & 15) != 0) && x < width; x++) { - source = reinterpret_cast(static_cast(input) + y * inputRowPitch + z * inputDepthPitch); - dest = reinterpret_cast(static_cast(output) + y * outputRowPitch + z * outputDepthPitch); - int x = 0; + uint32_t rgba = source[x]; + dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00); + } - // Make output writes aligned - for (x = 0; ((reinterpret_cast(&dest[x]) & 15) != 0) && x < width; x++) - { - unsigned int rgba = source[x]; - dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00); - } + for (; x + 3 < width; x += 4) + { + __m128i sourceData = _mm_loadu_si128(reinterpret_cast(&source[x])); + // Mask out g and a, which don't change + __m128i gaComponents = _mm_andnot_si128(brMask, sourceData); + // Mask out b and r + __m128i brComponents = _mm_and_si128(sourceData, brMask); + // Swap b and r + __m128i brSwapped = _mm_shufflehi_epi16(_mm_shufflelo_epi16(brComponents, _MM_SHUFFLE(2, 3, 0, 1)), _MM_SHUFFLE(2, 3, 0, 1)); + __m128i result = _mm_or_si128(gaComponents, brSwapped); + _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x]), result); + } - for (; x + 3 < width; x += 4) - { - __m128i sourceData = _mm_loadu_si128(reinterpret_cast(&source[x])); - // Mask out g and a, which don't change - __m128i gaComponents = _mm_andnot_si128(brMask, sourceData); - // Mask out b and r - __m128i brComponents = _mm_and_si128(sourceData, brMask); - // Swap b and r - __m128i brSwapped = _mm_shufflehi_epi16(_mm_shufflelo_epi16(brComponents, _MM_SHUFFLE(2, 3, 0, 1)), _MM_SHUFFLE(2, 3, 0, 1)); - __m128i result = _mm_or_si128(gaComponents, brSwapped); - _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x]), result); - } - - // Perform leftover writes - for (; x < width; x++) - { - unsigned int rgba = source[x]; - dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00); - } + // Perform leftover writes + for (; x < width; x++) + { + uint32_t rgba = source[x]; + dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00); } } } +} } diff --git a/gfx/angle/src/libGLESv2/renderer/vertexconversion.h b/gfx/angle/src/libGLESv2/renderer/vertexconversion.h index 590b9d48a386..81ba8a076728 100644 --- a/gfx/angle/src/libGLESv2/renderer/vertexconversion.h +++ b/gfx/angle/src/libGLESv2/renderer/vertexconversion.h @@ -10,6 +10,10 @@ #ifndef LIBGLESV2_VERTEXCONVERSION_H_ #define LIBGLESV2_VERTEXCONVERSION_H_ +#include +#include +#include + namespace rx { @@ -154,11 +158,13 @@ struct VertexDataConverter static const bool identity = (WidenRule::initialWidth == WidenRule::finalWidth) && Converter::identity; static const std::size_t finalSize = WidenRule::finalWidth * sizeof(OutputType); - static void convertArray(const InputType *in, std::size_t stride, std::size_t n, OutputType *out) + static void convertArray(const uint8_t *input, size_t stride, size_t n, uint8_t *output) { + OutputType *out = reinterpret_cast(output); + for (std::size_t i = 0; i < n; i++) { - const InputType *ein = pointerAddBytes(in, i * stride); + const InputType *ein = reinterpret_cast(input + i * stride); copyComponent(out, ein, 0, static_cast(DefaultValueRule::zero())); copyComponent(out, ein, 1, static_cast(DefaultValueRule::zero())); @@ -169,19 +175,7 @@ struct VertexDataConverter } } - static void convertArray(const void *in, std::size_t stride, std::size_t n, void *out) - { - return convertArray(static_cast(in), stride, n, static_cast(out)); - } - private: - // Advance the given pointer by a number of bytes (not pointed-to elements). - template - static T *pointerAddBytes(T *basePtr, std::size_t numBytes) - { - return reinterpret_cast(reinterpret_cast(basePtr) + numBytes); - } - static void copyComponent(OutputType *out, const InputType *in, std::size_t elementindex, OutputType defaultvalue) { if (WidenRule::finalWidth > elementindex) diff --git a/gfx/angle/src/libGLESv2/validationES.cpp b/gfx/angle/src/libGLESv2/validationES.cpp index a6ae90a28197..8016dfbf90ea 100644 --- a/gfx/angle/src/libGLESv2/validationES.cpp +++ b/gfx/angle/src/libGLESv2/validationES.cpp @@ -1,6 +1,5 @@ -#include "precompiled.h" // -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2013-2014 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. // @@ -13,11 +12,14 @@ #include "libGLESv2/Context.h" #include "libGLESv2/Texture.h" #include "libGLESv2/Framebuffer.h" -#include "libGLESv2/Renderbuffer.h" +#include "libGLESv2/FramebufferAttachment.h" #include "libGLESv2/formatutils.h" #include "libGLESv2/main.h" #include "libGLESv2/Query.h" #include "libGLESv2/ProgramBinary.h" +#include "libGLESv2/TransformFeedback.h" +#include "libGLESv2/VertexArray.h" +#include "libGLESv2/renderer/BufferImpl.h" #include "common/mathutil.h" #include "common/utilities.h" @@ -67,6 +69,7 @@ bool ValidTextureTarget(const Context *context, GLenum target) // This function differs from ValidTextureTarget in that the target must be // usable as the destination of a 2D operation-- so a cube face is valid, but // GL_TEXTURE_CUBE_MAP is not. +// Note: duplicate of IsInternalTextureTarget bool ValidTexture2DDestinationTarget(const Context *context, GLenum target) { switch (target) @@ -110,7 +113,7 @@ bool ValidBufferTarget(const Context *context, GLenum target) case GL_PIXEL_PACK_BUFFER: case GL_PIXEL_UNPACK_BUFFER: - return context->supportsPBOs(); + return context->getExtensions().pixelBufferObject; case GL_COPY_READ_BUFFER: case GL_COPY_WRITE_BUFFER: @@ -146,33 +149,35 @@ bool ValidBufferParameter(const Context *context, GLenum pname) bool ValidMipLevel(const Context *context, GLenum target, GLint level) { - int maxLevel = 0; + size_t maxDimension = 0; switch (target) { - case GL_TEXTURE_2D: maxLevel = context->getMaximum2DTextureLevel(); break; + case GL_TEXTURE_2D: maxDimension = context->getCaps().max2DTextureSize; break; case GL_TEXTURE_CUBE_MAP: case GL_TEXTURE_CUBE_MAP_POSITIVE_X: case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: maxLevel = context->getMaximumCubeTextureLevel(); break; - case GL_TEXTURE_3D: maxLevel = context->getMaximum3DTextureLevel(); break; - case GL_TEXTURE_2D_ARRAY: maxLevel = context->getMaximum2DArrayTextureLevel(); break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: maxDimension = context->getCaps().maxCubeMapTextureSize; break; + case GL_TEXTURE_3D: maxDimension = context->getCaps().max3DTextureSize; break; + case GL_TEXTURE_2D_ARRAY: maxDimension = context->getCaps().max2DTextureSize; break; default: UNREACHABLE(); } - return level < maxLevel; + return level <= gl::log2(maxDimension); } -bool ValidImageSize(const gl::Context *context, GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth) +bool ValidImageSize(const Context *context, GLenum target, GLint level, + GLsizei width, GLsizei height, GLsizei depth) { if (level < 0 || width < 0 || height < 0 || depth < 0) { return false; } - if (!context->supportsNonPower2Texture() && (level != 0 || !gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))) + if (!context->getExtensions().textureNPOT && + (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth)))) { return false; } @@ -185,18 +190,16 @@ bool ValidImageSize(const gl::Context *context, GLenum target, GLint level, GLsi return true; } -bool ValidCompressedImageSize(const gl::Context *context, GLenum internalFormat, GLsizei width, GLsizei height) +bool ValidCompressedImageSize(const Context *context, GLenum internalFormat, GLsizei width, GLsizei height) { - GLuint clientVersion = context->getClientVersion(); - if (!IsFormatCompressed(internalFormat, clientVersion)) + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); + if (!formatInfo.compressed) { return false; } - GLint blockWidth = GetCompressedBlockWidth(internalFormat, clientVersion); - GLint blockHeight = GetCompressedBlockHeight(internalFormat, clientVersion); - if (width < 0 || (width > blockWidth && width % blockWidth != 0) || - height < 0 || (height > blockHeight && height % blockHeight != 0)) + if (width < 0 || (static_cast(width) > formatInfo.compressedBlockWidth && width % formatInfo.compressedBlockWidth != 0) || + height < 0 || (static_cast(height) > formatInfo.compressedBlockHeight && height % formatInfo.compressedBlockHeight != 0)) { return false; } @@ -221,7 +224,7 @@ bool ValidQueryType(const Context *context, GLenum queryType) } } -bool ValidProgram(const Context *context, GLuint id) +bool ValidProgram(Context *context, GLuint id) { // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will generate the // error INVALID_VALUE if the provided name is not the name of either a shader or program object and @@ -234,16 +237,55 @@ bool ValidProgram(const Context *context, GLuint id) else if (context->getShader(id) != NULL) { // ID is the wrong type - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } else { // No shader/program object has this ID - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } } -bool ValidateRenderbufferStorageParameters(const gl::Context *context, GLenum target, GLsizei samples, +bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment) +{ + if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) + { + const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT); + + if (colorAttachment >= context->getCaps().maxColorAttachments) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + } + else + { + switch (attachment) + { + case GL_DEPTH_ATTACHMENT: + case GL_STENCIL_ATTACHMENT: + break; + + case GL_DEPTH_STENCIL_ATTACHMENT: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + } + + return true; +} + +bool ValidateRenderbufferStorageParameters(gl::Context *context, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, bool angleExtension) { @@ -252,44 +294,50 @@ bool ValidateRenderbufferStorageParameters(const gl::Context *context, GLenum ta case GL_RENDERBUFFER: break; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } if (width < 0 || height < 0 || samples < 0) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } - if (!gl::IsValidInternalFormat(internalformat, context)) + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat); + if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions())) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be // sized but it does state that the format must be in the ES2.0 spec table 4.5 which contains // only sized internal formats. The ES3 spec (section 4.4.2) does, however, state that the // internal format must be sized and not an integer format if samples is greater than zero. - if (!gl::IsSizedInternalFormat(internalformat, context->getClientVersion())) + if (formatInfo.pixelBytes == 0) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } - GLenum componentType = gl::GetComponentType(internalformat, context->getClientVersion()); - if ((componentType == GL_UNSIGNED_INT || componentType == GL_INT) && samples > 0) + if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) && samples > 0) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } - if (!gl::IsColorRenderingSupported(internalformat, context) && - !gl::IsDepthRenderingSupported(internalformat, context) && - !gl::IsStencilRenderingSupported(internalformat, context)) + const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat); + if (!formatCaps.renderable) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } - if (std::max(width, height) > context->getMaximumRenderbufferDimension()) + if (static_cast(std::max(width, height)) > context->getCaps().maxRenderbufferSize) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal @@ -298,23 +346,34 @@ bool ValidateRenderbufferStorageParameters(const gl::Context *context, GLenum ta // internal format. if (angleExtension) { - if (samples > context->getMaxSupportedSamples()) + ASSERT(context->getExtensions().framebufferMultisample); + if (static_cast(samples) > context->getExtensions().maxSamples) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + // Check if this specific format supports enough samples + if (static_cast(samples) > formatCaps.getMaxSamples()) + { + context->recordError(Error(GL_OUT_OF_MEMORY)); + return false; } } else { - if (samples > context->getMaxSupportedFormatSamples(internalformat)) + if (static_cast(samples) > formatCaps.getMaxSamples()) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } } - GLuint handle = context->getRenderbufferHandle(); + GLuint handle = context->getState().getRenderbufferId(); if (handle == 0) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } return true; @@ -323,40 +382,24 @@ bool ValidateRenderbufferStorageParameters(const gl::Context *context, GLenum ta bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) { - gl::Framebuffer *framebuffer = context->getTargetFramebuffer(target); - GLuint framebufferHandle = context->getTargetFramebufferHandle(target); + if (!ValidFramebufferTarget(target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); + GLuint framebufferHandle = context->getState().getTargetFramebuffer(target)->id(); if (!framebuffer || (framebufferHandle == 0 && renderbuffer != 0)) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } - if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) + if (!ValidateAttachmentTarget(context, attachment)) { - const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT); - - if (colorAttachment >= context->getMaximumRenderTargets()) - { - return gl::error(GL_INVALID_VALUE, false); - } - } - else - { - switch (attachment) - { - case GL_DEPTH_ATTACHMENT: - break; - case GL_STENCIL_ATTACHMENT: - break; - case GL_DEPTH_STENCIL_ATTACHMENT: - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_ENUM, false); - } - break; - default: - return gl::error(GL_INVALID_ENUM, false); - } + return false; } // [OpenGL ES 2.0.25] Section 4.4.3 page 112 @@ -367,14 +410,15 @@ bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum targ { if (!context->getRenderbuffer(renderbuffer)) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } return true; } -static bool IsPartialBlit(gl::Context *context, gl::Renderbuffer *readBuffer, gl::Renderbuffer *writeBuffer, +static bool IsPartialBlit(gl::Context *context, gl::FramebufferAttachment *readBuffer, gl::FramebufferAttachment *writeBuffer, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1) { @@ -384,14 +428,13 @@ static bool IsPartialBlit(gl::Context *context, gl::Renderbuffer *readBuffer, gl { return true; } - else if (context->isScissorTestEnabled()) + else if (context->getState().isScissorTestEnabled()) { - int scissorX, scissorY, scissorWidth, scissorHeight; - context->getScissorParams(&scissorX, &scissorY, &scissorWidth, &scissorHeight); + const Rectangle &scissor = context->getState().getScissor(); - return scissorX > 0 || scissorY > 0 || - scissorWidth < writeBuffer->getWidth() || - scissorHeight < writeBuffer->getHeight(); + return scissor.x > 0 || scissor.y > 0 || + scissor.width < writeBuffer->getWidth() || + scissor.height < writeBuffer->getHeight(); } else { @@ -410,16 +453,19 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint case GL_LINEAR: if (fromAngleExtension) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } if (mask == 0) @@ -432,90 +478,98 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint if (fromAngleExtension && (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)) { ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation."); - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the // color buffer, leaving only nearest being unfiltered from above if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } - if (context->getReadFramebufferHandle() == context->getDrawFramebufferHandle()) + if (context->getState().getReadFramebuffer()->id() == context->getState().getDrawFramebuffer()->id()) { if (fromAngleExtension) { ERR("Blits with the same source and destination framebuffer are not supported by this " "implementation."); } - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } - gl::Framebuffer *readFramebuffer = context->getReadFramebuffer(); - gl::Framebuffer *drawFramebuffer = context->getDrawFramebuffer(); + gl::Framebuffer *readFramebuffer = context->getState().getReadFramebuffer(); + gl::Framebuffer *drawFramebuffer = context->getState().getDrawFramebuffer(); if (!readFramebuffer || readFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE || !drawFramebuffer || drawFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) { - return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION, false); + context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); + return false; } if (drawFramebuffer->getSamples() != 0) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1; - GLuint clientVersion = context->getClientVersion(); - if (mask & GL_COLOR_BUFFER_BIT) { - gl::Renderbuffer *readColorBuffer = readFramebuffer->getReadColorbuffer(); - gl::Renderbuffer *drawColorBuffer = drawFramebuffer->getFirstColorbuffer(); + gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer(); + gl::FramebufferAttachment *drawColorBuffer = drawFramebuffer->getFirstColorbuffer(); if (readColorBuffer && drawColorBuffer) { GLenum readInternalFormat = readColorBuffer->getActualFormat(); - GLenum readComponentType = gl::GetComponentType(readInternalFormat, clientVersion); + const InternalFormat &readFormatInfo = GetInternalFormatInfo(readInternalFormat); for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; i++) { if (drawFramebuffer->isEnabledColorAttachment(i)) { GLenum drawInternalFormat = drawFramebuffer->getColorbuffer(i)->getActualFormat(); - GLenum drawComponentType = gl::GetComponentType(drawInternalFormat, clientVersion); + const InternalFormat &drawFormatInfo = GetInternalFormatInfo(drawInternalFormat); // The GL ES 3.0.2 spec (pg 193) states that: // 1) If the read buffer is fixed point format, the draw buffer must be as well // 2) If the read buffer is an unsigned integer format, the draw buffer must be as well // 3) If the read buffer is a signed integer format, the draw buffer must be as well - if ( (readComponentType == GL_UNSIGNED_NORMALIZED || readComponentType == GL_SIGNED_NORMALIZED) && - !(drawComponentType == GL_UNSIGNED_NORMALIZED || drawComponentType == GL_SIGNED_NORMALIZED)) + if ( (readFormatInfo.componentType == GL_UNSIGNED_NORMALIZED || readFormatInfo.componentType == GL_SIGNED_NORMALIZED) && + !(drawFormatInfo.componentType == GL_UNSIGNED_NORMALIZED || drawFormatInfo.componentType == GL_SIGNED_NORMALIZED)) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } - if (readComponentType == GL_UNSIGNED_INT && drawComponentType != GL_UNSIGNED_INT) + if (readFormatInfo.componentType == GL_UNSIGNED_INT && drawFormatInfo.componentType != GL_UNSIGNED_INT) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } - if (readComponentType == GL_INT && drawComponentType != GL_INT) + if (readFormatInfo.componentType == GL_INT && drawFormatInfo.componentType != GL_INT) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (readColorBuffer->getSamples() > 0 && (readInternalFormat != drawInternalFormat || !sameBounds)) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } } - if ((readComponentType == GL_INT || readComponentType == GL_UNSIGNED_INT) && filter == GL_LINEAR) + if ((readFormatInfo.componentType == GL_INT || readFormatInfo.componentType == GL_UNSIGNED_INT) && filter == GL_LINEAR) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (fromAngleExtension) @@ -523,22 +577,27 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint const GLenum readColorbufferType = readFramebuffer->getReadColorbufferType(); if (readColorbufferType != GL_TEXTURE_2D && readColorbufferType != GL_RENDERBUFFER) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } 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) + FramebufferAttachment *attachment = drawFramebuffer->getColorbuffer(colorAttachment); + ASSERT(attachment); + + if (attachment->type() != GL_TEXTURE_2D && attachment->type() != GL_RENDERBUFFER) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } - if (drawFramebuffer->getColorbuffer(colorAttachment)->getActualFormat() != readColorBuffer->getActualFormat()) + if (attachment->getActualFormat() != readColorBuffer->getActualFormat()) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } } @@ -546,7 +605,8 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1)) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } } @@ -554,19 +614,21 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint if (mask & GL_DEPTH_BUFFER_BIT) { - gl::Renderbuffer *readDepthBuffer = readFramebuffer->getDepthbuffer(); - gl::Renderbuffer *drawDepthBuffer = drawFramebuffer->getDepthbuffer(); + gl::FramebufferAttachment *readDepthBuffer = readFramebuffer->getDepthbuffer(); + gl::FramebufferAttachment *drawDepthBuffer = drawFramebuffer->getDepthbuffer(); if (readDepthBuffer && drawDepthBuffer) { if (readDepthBuffer->getActualFormat() != drawDepthBuffer->getActualFormat()) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (readDepthBuffer->getSamples() > 0 && !sameBounds) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (fromAngleExtension) @@ -575,12 +637,14 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1)) { ERR("Only whole-buffer depth and stencil blits are supported by this implementation."); - return gl::error(GL_INVALID_OPERATION, false); // only whole-buffer copies are permitted + context->recordError(Error(GL_INVALID_OPERATION)); // only whole-buffer copies are permitted + return false; } if (readDepthBuffer->getSamples() != 0 || drawDepthBuffer->getSamples() != 0) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } } @@ -588,19 +652,21 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint if (mask & GL_STENCIL_BUFFER_BIT) { - gl::Renderbuffer *readStencilBuffer = readFramebuffer->getStencilbuffer(); - gl::Renderbuffer *drawStencilBuffer = drawFramebuffer->getStencilbuffer(); + gl::FramebufferAttachment *readStencilBuffer = readFramebuffer->getStencilbuffer(); + gl::FramebufferAttachment *drawStencilBuffer = drawFramebuffer->getStencilbuffer(); if (readStencilBuffer && drawStencilBuffer) { if (readStencilBuffer->getActualFormat() != drawStencilBuffer->getActualFormat()) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (readStencilBuffer->getSamples() > 0 && !sameBounds) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (fromAngleExtension) @@ -609,12 +675,14 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1)) { ERR("Only whole-buffer depth and stencil blits are supported by this implementation."); - return gl::error(GL_INVALID_OPERATION, false); // only whole-buffer copies are permitted + context->recordError(Error(GL_INVALID_OPERATION)); // only whole-buffer copies are permitted + return false; } if (readStencilBuffer->getSamples() != 0 || drawStencilBuffer->getSamples() != 0) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } } @@ -623,7 +691,7 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint return true; } -bool ValidateGetVertexAttribParameters(GLenum pname, int clientVersion) +bool ValidateGetVertexAttribParameters(Context *context, GLenum pname) { switch (pname) { @@ -643,10 +711,16 @@ bool ValidateGetVertexAttribParameters(GLenum pname, int clientVersion) return true; case GL_VERTEX_ATTRIB_ARRAY_INTEGER: - return ((clientVersion >= 3) ? true : gl::error(GL_INVALID_ENUM, false)); + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + return true; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } } @@ -667,7 +741,8 @@ bool ValidateTexParamParameters(gl::Context *context, GLenum pname, GLint param) case GL_TEXTURE_MAX_LOD: if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; @@ -686,7 +761,8 @@ bool ValidateTexParamParameters(gl::Context *context, GLenum pname, GLint param) case GL_MIRRORED_REPEAT: return true; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } case GL_TEXTURE_MIN_FILTER: @@ -700,7 +776,8 @@ bool ValidateTexParamParameters(gl::Context *context, GLenum pname, GLint param) case GL_LINEAR_MIPMAP_LINEAR: return true; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; @@ -711,7 +788,8 @@ bool ValidateTexParamParameters(gl::Context *context, GLenum pname, GLint param) case GL_LINEAR: return true; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; @@ -722,20 +800,23 @@ bool ValidateTexParamParameters(gl::Context *context, GLenum pname, GLint param) case GL_FRAMEBUFFER_ATTACHMENT_ANGLE: return true; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; case GL_TEXTURE_MAX_ANISOTROPY_EXT: - if (!context->supportsTextureFilterAnisotropy()) + if (!context->getExtensions().textureFilterAnisotropic) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } // we assume the parameter passed to this validation method is truncated, not rounded if (param < 1) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } return true; @@ -752,7 +833,8 @@ bool ValidateTexParamParameters(gl::Context *context, GLenum pname, GLint param) case GL_COMPARE_REF_TO_TEXTURE: return true; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; @@ -770,7 +852,8 @@ bool ValidateTexParamParameters(gl::Context *context, GLenum pname, GLint param) case GL_NEVER: return true; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; @@ -788,7 +871,8 @@ bool ValidateTexParamParameters(gl::Context *context, GLenum pname, GLint param) case GL_ONE: return true; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; @@ -796,16 +880,18 @@ bool ValidateTexParamParameters(gl::Context *context, GLenum pname, GLint param) case GL_TEXTURE_MAX_LEVEL: if (param < 0) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } return true; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } } -bool ValidateSamplerObjectParameter(GLenum pname) +bool ValidateSamplerObjectParameter(gl::Context *context, GLenum pname) { switch (pname) { @@ -821,33 +907,37 @@ bool ValidateSamplerObjectParameter(GLenum pname) return true; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } } bool ValidateReadPixelsParameters(gl::Context *context, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei *bufSize, GLvoid *pixels) { - gl::Framebuffer *framebuffer = context->getReadFramebuffer(); + gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); ASSERT(framebuffer); if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) { - return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION, false); + context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); + return false; } - if (context->getReadFramebufferHandle() != 0 && framebuffer->getSamples() != 0) + if (context->getState().getReadFramebuffer()->id() != 0 && framebuffer->getSamples() != 0) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (!framebuffer->getReadColorbuffer()) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } GLenum currentInternalFormat, currentFormat, currentType; - int clientVersion = context->getClientVersion(); + GLuint clientVersion = context->getClientVersion(); context->getCurrentReadFormatType(¤tInternalFormat, ¤tFormat, ¤tType); @@ -856,20 +946,22 @@ bool ValidateReadPixelsParameters(gl::Context *context, GLint x, GLint y, GLsize if (!(currentFormat == format && currentType == type) && !validReadFormat) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } - GLenum sizedInternalFormat = IsSizedInternalFormat(format, clientVersion) ? format : - GetSizedInternalFormat(format, type, clientVersion); + GLenum sizedInternalFormat = GetSizedInternalFormat(format, type); + const InternalFormat &sizedFormatInfo = GetInternalFormatInfo(sizedInternalFormat); - GLsizei outputPitch = GetRowPitch(sizedInternalFormat, type, clientVersion, width, context->getPackAlignment()); + GLsizei outputPitch = sizedFormatInfo.computeRowPitch(type, width, context->getState().getPackAlignment()); // sized query sanity check if (bufSize) { int requiredSize = outputPitch * height; if (requiredSize > *bufSize) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } @@ -880,12 +972,14 @@ bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id) { if (!ValidQueryType(context, target)) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } if (id == 0) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an @@ -903,9 +997,10 @@ bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id) // b) There are no active queries for the requested target (and in the case // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, // no query may be active for either if glBeginQuery targets either. - if (context->isQueryActive()) + if (context->getState().isQueryActive()) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } Query *queryObject = context->getQuery(id, true, target); @@ -913,13 +1008,15 @@ bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id) // check that name was obtained with glGenQueries if (!queryObject) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } // check for type mismatch if (queryObject->getType() != target) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } return true; @@ -929,19 +1026,22 @@ bool ValidateEndQuery(gl::Context *context, GLenum target) { if (!ValidQueryType(context, target)) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } - const Query *queryObject = context->getActiveQuery(target); + const Query *queryObject = context->getState().getActiveQuery(target); if (queryObject == NULL) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (!queryObject->isStarted()) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } return true; @@ -952,13 +1052,15 @@ static bool ValidateUniformCommonBase(gl::Context *context, GLenum targetUniform { if (count < 0) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); if (!programBinary) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (location == -1) @@ -969,7 +1071,8 @@ static bool ValidateUniformCommonBase(gl::Context *context, GLenum targetUniform if (!programBinary->isValidUniformLocation(location)) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } LinkedUniform *uniform = programBinary->getUniformByLocation(location); @@ -977,7 +1080,8 @@ static bool ValidateUniformCommonBase(gl::Context *context, GLenum targetUniform // attempting to write an array to a non-array uniform is an INVALID_OPERATION if (uniform->elementCount() == 1 && count > 1) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } *uniformOut = uniform; @@ -987,9 +1091,10 @@ static bool ValidateUniformCommonBase(gl::Context *context, GLenum targetUniform bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, GLsizei count) { // Check for ES3 uniform entry points - if (UniformComponentType(uniformType) == GL_UNSIGNED_INT && context->getClientVersion() < 3) + if (VariableComponentType(uniformType) == GL_UNSIGNED_INT && context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } LinkedUniform *uniform = NULL; @@ -998,11 +1103,12 @@ bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, G return false; } - GLenum targetBoolType = UniformBoolVectorType(uniformType); + GLenum targetBoolType = VariableBoolVectorType(uniformType); bool samplerUniformCheck = (IsSampler(uniform->type) && uniformType == GL_INT); if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } return true; @@ -1016,12 +1122,14 @@ bool ValidateUniformMatrix(gl::Context *context, GLenum matrixType, GLint locati int cols = VariableColumnCount(matrixType); if (rows != cols && context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (transpose != GL_FALSE && context->getClientVersion() < 3) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } LinkedUniform *uniform = NULL; @@ -1032,7 +1140,8 @@ bool ValidateUniformMatrix(gl::Context *context, GLenum matrixType, GLint locati if (uniform->type != matrixType) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } return true; @@ -1042,16 +1151,18 @@ bool ValidateStateQuery(gl::Context *context, GLenum pname, GLenum *nativeType, { if (!context->getQueryParameterInfo(pname, nativeType, numParams)) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15) { unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0); - if (colorAttachment >= context->getMaximumRenderTargets()) + if (colorAttachment >= context->getCaps().maxDrawBuffers) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } @@ -1061,26 +1172,29 @@ bool ValidateStateQuery(gl::Context *context, GLenum pname, GLenum *nativeType, case GL_TEXTURE_BINDING_CUBE_MAP: case GL_TEXTURE_BINDING_3D: case GL_TEXTURE_BINDING_2D_ARRAY: - if (context->getActiveSampler() >= context->getMaximumCombinedTextureImageUnits()) + if (context->getState().getActiveSampler() >= context->getCaps().maxCombinedTextureImageUnits) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } break; case GL_IMPLEMENTATION_COLOR_READ_TYPE: case GL_IMPLEMENTATION_COLOR_READ_FORMAT: { - Framebuffer *framebuffer = context->getReadFramebuffer(); + Framebuffer *framebuffer = context->getState().getReadFramebuffer(); ASSERT(framebuffer); if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } - Renderbuffer *renderbuffer = framebuffer->getReadColorbuffer(); - if (!renderbuffer) + FramebufferAttachment *attachment = framebuffer->getReadColorbuffer(); + if (!attachment) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } break; @@ -1098,4 +1212,677 @@ bool ValidateStateQuery(gl::Context *context, GLenum pname, GLenum *nativeType, return true; } +bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLint level, GLenum internalformat, bool isSubImage, + GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, + GLint border, GLenum *textureFormatOut) +{ + + if (!ValidTexture2DDestinationTarget(context, target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + if (std::numeric_limits::max() - xoffset < width || std::numeric_limits::max() - yoffset < height) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + if (border != 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + if (!ValidMipLevel(context, target, level)) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); + if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) + { + context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); + return false; + } + + if (context->getState().getReadFramebuffer()->id() != 0 && framebuffer->getSamples() != 0) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + const gl::Caps &caps = context->getCaps(); + + gl::Texture *texture = NULL; + GLenum textureInternalFormat = GL_NONE; + GLint textureLevelWidth = 0; + GLint textureLevelHeight = 0; + GLint textureLevelDepth = 0; + GLuint maxDimension = 0; + + switch (target) + { + case GL_TEXTURE_2D: + { + gl::Texture2D *texture2d = context->getTexture2D(); + if (texture2d) + { + textureInternalFormat = texture2d->getInternalFormat(level); + textureLevelWidth = texture2d->getWidth(level); + textureLevelHeight = texture2d->getHeight(level); + textureLevelDepth = 1; + texture = texture2d; + maxDimension = caps.max2DTextureSize; + } + } + break; + + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + { + gl::TextureCubeMap *textureCube = context->getTextureCubeMap(); + if (textureCube) + { + textureInternalFormat = textureCube->getInternalFormat(target, level); + textureLevelWidth = textureCube->getWidth(target, level); + textureLevelHeight = textureCube->getHeight(target, level); + textureLevelDepth = 1; + texture = textureCube; + maxDimension = caps.maxCubeMapTextureSize; + } + } + break; + + case GL_TEXTURE_2D_ARRAY: + { + gl::Texture2DArray *texture2dArray = context->getTexture2DArray(); + if (texture2dArray) + { + textureInternalFormat = texture2dArray->getInternalFormat(level); + textureLevelWidth = texture2dArray->getWidth(level); + textureLevelHeight = texture2dArray->getHeight(level); + textureLevelDepth = texture2dArray->getLayers(level); + texture = texture2dArray; + maxDimension = caps.max2DTextureSize; + } + } + break; + + case GL_TEXTURE_3D: + { + gl::Texture3D *texture3d = context->getTexture3D(); + if (texture3d) + { + textureInternalFormat = texture3d->getInternalFormat(level); + textureLevelWidth = texture3d->getWidth(level); + textureLevelHeight = texture3d->getHeight(level); + textureLevelDepth = texture3d->getDepth(level); + texture = texture3d; + maxDimension = caps.max3DTextureSize; + } + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + if (!texture) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + if (texture->isImmutable() && !isSubImage) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat); + + if (formatInfo.depthBits > 0) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + if (formatInfo.compressed) + { + if (((width % formatInfo.compressedBlockWidth) != 0 && width != textureLevelWidth) || + ((height % formatInfo.compressedBlockHeight) != 0 && height != textureLevelHeight)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + } + + if (isSubImage) + { + if (xoffset + width > textureLevelWidth || + yoffset + height > textureLevelHeight || + zoffset >= textureLevelDepth) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + } + else + { + if (IsCubemapTextureTarget(target) && width != height) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions())) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + int maxLevelDimension = (maxDimension >> level); + if (static_cast(width) > maxLevelDimension || static_cast(height) > maxLevelDimension) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + } + + *textureFormatOut = textureInternalFormat; + return true; +} + +static bool ValidateDrawBase(Context *context, GLenum mode, GLsizei count, GLsizei maxVertex, GLsizei primcount) +{ + switch (mode) + { + case GL_POINTS: + case GL_LINES: + case GL_LINE_LOOP: + case GL_LINE_STRIP: + case GL_TRIANGLES: + case GL_TRIANGLE_STRIP: + case GL_TRIANGLE_FAN: + break; + default: + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + if (count < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + const State &state = context->getState(); + + // Check for mapped buffers + if (state.hasMappedBuffer(GL_ARRAY_BUFFER)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + const gl::DepthStencilState &depthStencilState = state.getDepthStencilState(); + if (depthStencilState.stencilWritemask != depthStencilState.stencilBackWritemask || + state.getStencilRef() != state.getStencilBackRef() || + depthStencilState.stencilMask != depthStencilState.stencilBackMask) + { + // Note: these separate values are not supported in WebGL, due to D3D's limitations. + // See Section 6.10 of the WebGL 1.0 spec + ERR("This ANGLE implementation does not support separate front/back stencil " + "writemasks, reference values, or stencil mask values."); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + const gl::Framebuffer *fbo = state.getDrawFramebuffer(); + if (!fbo || fbo->completeness() != GL_FRAMEBUFFER_COMPLETE) + { + context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); + return false; + } + + if (state.getCurrentProgramId() == 0) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + gl::ProgramBinary *programBinary = state.getCurrentProgramBinary(); + if (!programBinary->validateSamplers(NULL, context->getCaps())) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + // Buffer validations + const VertexArray *vao = state.getVertexArray(); + for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) + { + const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex); + bool attribActive = (programBinary->getSemanticIndex(attributeIndex) != -1); + if (attribActive && attrib.enabled) + { + gl::Buffer *buffer = attrib.buffer.get(); + + if (buffer) + { + GLint64 attribStride = static_cast(ComputeVertexAttributeStride(attrib)); + GLint64 maxVertexElement = 0; + + if (attrib.divisor > 0) + { + maxVertexElement = static_cast(primcount) / static_cast(attrib.divisor); + } + else + { + maxVertexElement = static_cast(maxVertex); + } + + GLint64 attribDataSize = maxVertexElement * attribStride; + + // [OpenGL ES 3.0.2] section 2.9.4 page 40: + // We can return INVALID_OPERATION if our vertex attribute does not have + // enough backing data. + if (attribDataSize > buffer->getSize()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + } + else if (attrib.pointer == NULL) + { + // This is an application error that would normally result in a crash, + // but we catch it and return an error + context->recordError(Error(GL_INVALID_OPERATION, "An enabled vertex array has no buffer and no pointer.")); + return false; + } + } + } + + // No-op if zero count + return (count > 0); +} + +bool ValidateDrawArrays(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount) +{ + if (first < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + const State &state = context->getState(); + gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback(); + if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused() && + curTransformFeedback->getDrawMode() != mode) + { + // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode + // that does not match the current transform feedback object's draw mode (if transform feedback + // is active), (3.0.2, section 2.14, pg 86) + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + if (!ValidateDrawBase(context, mode, count, count, primcount)) + { + return false; + } + + return true; +} + +bool ValidateDrawArraysInstanced(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount) +{ + if (primcount < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + if (!ValidateDrawArrays(context, mode, first, count, primcount)) + { + return false; + } + + // No-op if zero primitive count + return (primcount > 0); +} + +bool ValidateDrawElements(Context *context, GLenum mode, GLsizei count, GLenum type, + const GLvoid* indices, GLsizei primcount, rx::RangeUI *indexRangeOut) +{ + switch (type) + { + case GL_UNSIGNED_BYTE: + case GL_UNSIGNED_SHORT: + break; + case GL_UNSIGNED_INT: + if (!context->getExtensions().elementIndexUint) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + break; + default: + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + const State &state = context->getState(); + + gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback(); + if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused()) + { + // It is an invalid operation to call DrawElements, DrawRangeElements or DrawElementsInstanced + // while transform feedback is active, (3.0.2, section 2.14, pg 86) + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + // Check for mapped buffers + if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + const gl::VertexArray *vao = state.getVertexArray(); + const gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer(); + if (!indices && !elementArrayBuffer) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + if (elementArrayBuffer) + { + const gl::Type &typeInfo = gl::GetTypeInfo(type); + + GLint64 offset = reinterpret_cast(indices); + GLint64 byteCount = static_cast(typeInfo.bytes) * static_cast(count)+offset; + + // check for integer overflows + if (static_cast(count) > (std::numeric_limits::max() / typeInfo.bytes) || + byteCount > static_cast(std::numeric_limits::max())) + { + context->recordError(Error(GL_OUT_OF_MEMORY)); + return false; + } + + // Check for reading past the end of the bound buffer object + if (byteCount > elementArrayBuffer->getSize()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + } + else if (!indices) + { + // Catch this programming error here + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + // Use max index to validate if our vertex buffers are large enough for the pull. + // TODO: offer fast path, with disabled index validation. + // TODO: also disable index checking on back-ends that are robust to out-of-range accesses. + if (elementArrayBuffer) + { + unsigned int offset = reinterpret_cast(indices); + if (!elementArrayBuffer->getIndexRangeCache()->findRange(type, offset, count, indexRangeOut, NULL)) + { + const void *dataPointer = elementArrayBuffer->getImplementation()->getData(); + const uint8_t *offsetPointer = static_cast(dataPointer) + offset; + *indexRangeOut = rx::IndexRangeCache::ComputeRange(type, offsetPointer, count); + } + } + else + { + *indexRangeOut = rx::IndexRangeCache::ComputeRange(type, indices, count); + } + + if (!ValidateDrawBase(context, mode, count, static_cast(indexRangeOut->end), primcount)) + { + return false; + } + + return true; +} + +bool ValidateDrawElementsInstanced(Context *context, + GLenum mode, GLsizei count, GLenum type, + const GLvoid *indices, GLsizei primcount, + rx::RangeUI *indexRangeOut) +{ + if (primcount < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut)) + { + return false; + } + + // No-op zero primitive count + return (primcount > 0); +} + +bool ValidateFramebufferTextureBase(Context *context, GLenum target, GLenum attachment, + GLuint texture, GLint level) +{ + if (!ValidFramebufferTarget(target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + if (!ValidateAttachmentTarget(context, attachment)) + { + return false; + } + + if (texture != 0) + { + gl::Texture *tex = context->getTexture(texture); + + if (tex == NULL) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + if (level < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + } + + const gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); + GLuint framebufferHandle = context->getState().getTargetFramebuffer(target)->id(); + + if (framebufferHandle == 0 || !framebuffer) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + return true; +} + +bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attachment, + GLenum textarget, GLuint texture, GLint level) +{ + // Attachments are required to be bound to level 0 in ES2 + if (context->getClientVersion() < 3 && level != 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level)) + { + return false; + } + + if (texture != 0) + { + gl::Texture *tex = context->getTexture(texture); + ASSERT(tex); + + const gl::Caps &caps = context->getCaps(); + + switch (textarget) + { + case GL_TEXTURE_2D: + { + if (level > gl::log2(caps.max2DTextureSize)) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + if (tex->getTarget() != GL_TEXTURE_2D) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + gl::Texture2D *tex2d = static_cast(tex); + if (tex2d->isCompressed(level)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + } + break; + + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + { + if (level > gl::log2(caps.maxCubeMapTextureSize)) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + if (tex->getTarget() != GL_TEXTURE_CUBE_MAP) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + gl::TextureCubeMap *texcube = static_cast(tex); + if (texcube->isCompressed(textarget, level)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + } + + return true; +} + +bool ValidateGetUniformBase(Context *context, GLuint program, GLint location) +{ + if (program == 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + gl::Program *programObject = context->getProgram(program); + + if (!programObject || !programObject->isLinked()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + if (!programBinary) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + if (!programBinary->isValidUniformLocation(location)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + return true; +} + +bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat* params) +{ + return ValidateGetUniformBase(context, program, location); +} + +bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint* params) +{ + return ValidateGetUniformBase(context, program, location); +} + +static bool ValidateSizedGetUniform(Context *context, GLuint program, GLint location, GLsizei bufSize) +{ + if (!ValidateGetUniformBase(context, program, location)) + { + return false; + } + + gl::Program *programObject = context->getProgram(program); + ASSERT(programObject); + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + + // sized queries -- ensure the provided buffer is large enough + LinkedUniform *uniform = programBinary->getUniformByLocation(location); + size_t requiredBytes = VariableExternalSize(uniform->type); + if (static_cast(bufSize) < requiredBytes) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + return true; +} + +bool ValidateGetnUniformfvEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLfloat* params) +{ + return ValidateSizedGetUniform(context, program, location, bufSize); +} + +bool ValidateGetnUniformivEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLint* params) +{ + return ValidateSizedGetUniform(context, program, location, bufSize); +} + } diff --git a/gfx/angle/src/libGLESv2/validationES.h b/gfx/angle/src/libGLESv2/validationES.h index a61313ee65b7..30a9494d7fb6 100644 --- a/gfx/angle/src/libGLESv2/validationES.h +++ b/gfx/angle/src/libGLESv2/validationES.h @@ -9,6 +9,11 @@ #ifndef LIBGLESV2_VALIDATION_ES_H #define LIBGLESV2_VALIDATION_ES_H +#include "common/mathutil.h" + +#include +#include + namespace gl { @@ -21,38 +26,63 @@ bool ValidFramebufferTarget(GLenum target); bool ValidBufferTarget(const Context *context, GLenum target); bool ValidBufferParameter(const Context *context, GLenum pname); bool ValidMipLevel(const Context *context, GLenum target, GLint level); -bool ValidImageSize(const gl::Context *context, GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth); -bool ValidCompressedImageSize(const gl::Context *context, GLenum internalFormat, GLsizei width, GLsizei height); -bool ValidQueryType(const gl::Context *context, GLenum queryType); -bool ValidProgram(const gl::Context *context, GLuint id); +bool ValidImageSize(const Context *context, GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth); +bool ValidCompressedImageSize(const Context *context, GLenum internalFormat, GLsizei width, GLsizei height); +bool ValidQueryType(const Context *context, GLenum queryType); +bool ValidProgram(Context *context, GLuint id); -bool ValidateRenderbufferStorageParameters(const gl::Context *context, GLenum target, GLsizei samples, +bool ValidateAttachmentTarget(Context *context, GLenum attachment); +bool ValidateRenderbufferStorageParameters(Context *context, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, bool angleExtension); -bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum target, GLenum attachment, +bool ValidateFramebufferRenderbufferParameters(Context *context, GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); -bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, +bool ValidateBlitFramebufferParameters(Context *context, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter, bool fromAngleExtension); -bool ValidateGetVertexAttribParameters(GLenum pname, int clientVersion); +bool ValidateGetVertexAttribParameters(Context *context, GLenum pname); -bool ValidateTexParamParameters(gl::Context *context, GLenum pname, GLint param); +bool ValidateTexParamParameters(Context *context, GLenum pname, GLint param); -bool ValidateSamplerObjectParameter(GLenum pname); +bool ValidateSamplerObjectParameter(Context *context, GLenum pname); -bool ValidateReadPixelsParameters(gl::Context *context, GLint x, GLint y, GLsizei width, GLsizei height, +bool ValidateReadPixelsParameters(Context *context, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei *bufSize, GLvoid *pixels); -bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id); -bool ValidateEndQuery(gl::Context *context, GLenum target); +bool ValidateBeginQuery(Context *context, GLenum target, GLuint id); +bool ValidateEndQuery(Context *context, GLenum target); -bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, GLsizei count); -bool ValidateUniformMatrix(gl::Context *context, GLenum matrixType, GLint location, GLsizei count, +bool ValidateUniform(Context *context, GLenum uniformType, GLint location, GLsizei count); +bool ValidateUniformMatrix(Context *context, GLenum matrixType, GLint location, GLsizei count, GLboolean transpose); -bool ValidateStateQuery(gl::Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams); +bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams); + +bool ValidateCopyTexImageParametersBase(Context* context, GLenum target, GLint level, GLenum internalformat, bool isSubImage, + GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, + GLint border, GLenum *textureInternalFormatOut); + +bool ValidateDrawArrays(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount); +bool ValidateDrawArraysInstanced(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount); + +bool ValidateDrawElements(Context *context, GLenum mode, GLsizei count, GLenum type, + const GLvoid* indices, GLsizei primcount, rx::RangeUI *indexRangeOut); + +bool ValidateDrawElementsInstanced(Context *context, GLenum mode, GLsizei count, GLenum type, + const GLvoid *indices, GLsizei primcount, rx::RangeUI *indexRangeOut); + +bool ValidateFramebufferTextureBase(Context *context, GLenum target, GLenum attachment, + GLuint texture, GLint level); +bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attachment, + GLenum textarget, GLuint texture, GLint level); + +bool ValidateGetUniformBase(Context *context, GLuint program, GLint location); +bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat* params); +bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint* params); +bool ValidateGetnUniformfvEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLfloat* params); +bool ValidateGetnUniformivEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLint* params); } diff --git a/gfx/angle/src/libGLESv2/validationES2.cpp b/gfx/angle/src/libGLESv2/validationES2.cpp index 428d1385afb7..f950454df091 100644 --- a/gfx/angle/src/libGLESv2/validationES2.cpp +++ b/gfx/angle/src/libGLESv2/validationES2.cpp @@ -1,6 +1,5 @@ -#include "precompiled.h" // -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2013-2014 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,6 +14,7 @@ #include "libGLESv2/Renderbuffer.h" #include "libGLESv2/formatutils.h" #include "libGLESv2/main.h" +#include "libGLESv2/FramebufferAttachment.h" #include "common/mathutil.h" #include "common/utilities.h" @@ -22,26 +22,28 @@ namespace gl { -static bool validateSubImageParams2D(bool compressed, GLsizei width, GLsizei height, +static bool ValidateSubImageParams2D(Context *context, bool compressed, GLsizei width, GLsizei height, GLint xoffset, GLint yoffset, GLint level, GLenum format, GLenum type, gl::Texture2D *texture) { if (!texture) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (compressed != texture->isCompressed(level)) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (format != GL_NONE) { - GLenum internalformat = gl::GetSizedInternalFormat(format, type, 2); - if (internalformat != texture->getInternalFormat(level)) + if (gl::GetFormatTypeInfo(format, type).internalFormat != texture->getInternalFormat(level)) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } @@ -50,39 +52,43 @@ static bool validateSubImageParams2D(bool compressed, GLsizei width, GLsizei hei if ((width % 4 != 0 && width != texture->getWidth(level)) || (height % 4 != 0 && height != texture->getHeight(level))) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } if (xoffset + width > texture->getWidth(level) || yoffset + height > texture->getHeight(level)) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } return true; } -static bool validateSubImageParamsCube(bool compressed, GLsizei width, GLsizei height, +static bool ValidateSubImageParamsCube(Context *context, bool compressed, GLsizei width, GLsizei height, GLint xoffset, GLint yoffset, GLenum target, GLint level, GLenum format, GLenum type, gl::TextureCubeMap *texture) { if (!texture) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (compressed != texture->isCompressed(target, level)) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (format != GL_NONE) { - GLenum internalformat = gl::GetSizedInternalFormat(format, type, 2); - if (internalformat != texture->getInternalFormat(target, level)) + if (gl::GetFormatTypeInfo(format, type).internalFormat != texture->getInternalFormat(target, level)) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } @@ -91,40 +97,53 @@ static bool validateSubImageParamsCube(bool compressed, GLsizei width, GLsizei h if ((width % 4 != 0 && width != texture->getWidth(target, 0)) || (height % 4 != 0 && height != texture->getHeight(target, 0))) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } if (xoffset + width > texture->getWidth(target, level) || yoffset + height > texture->getHeight(target, level)) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } return true; } -bool ValidateES2TexImageParameters(gl::Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage, +bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels) { + if (!ValidTexture2DDestinationTarget(context, target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + if (!ValidImageSize(context, target, level, width, height, 1)) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } if (level < 0 || xoffset < 0 || std::numeric_limits::max() - xoffset < width || std::numeric_limits::max() - yoffset < height) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } if (!isSubImage && !isCompressed && internalformat != format) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } + const gl::Caps &caps = context->getCaps(); + gl::Texture *texture = NULL; bool textureCompressed = false; GLenum textureInternalFormat = GL_NONE; @@ -134,10 +153,11 @@ bool ValidateES2TexImageParameters(gl::Context *context, GLenum target, GLint le { case GL_TEXTURE_2D: { - if (width > (context->getMaximum2DTextureDimension() >> level) || - height > (context->getMaximum2DTextureDimension() >> level)) + if (static_cast(width) > (caps.max2DTextureSize >> level) || + static_cast(height) > (caps.max2DTextureSize >> level)) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } gl::Texture2D *tex2d = context->getTexture2D(); @@ -150,7 +170,7 @@ bool ValidateES2TexImageParameters(gl::Context *context, GLenum target, GLint le texture = tex2d; } - if (isSubImage && !validateSubImageParams2D(isCompressed, width, height, xoffset, yoffset, + if (isSubImage && !ValidateSubImageParams2D(context, isCompressed, width, height, xoffset, yoffset, level, format, type, tex2d)) { return false; @@ -169,13 +189,15 @@ bool ValidateES2TexImageParameters(gl::Context *context, GLenum target, GLint le { if (!isSubImage && width != height) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } - if (width > (context->getMaximumCubeTextureDimension() >> level) || - height > (context->getMaximumCubeTextureDimension() >> level)) + if (static_cast(width) > (caps.maxCubeMapTextureSize >> level) || + static_cast(height) > (caps.maxCubeMapTextureSize >> level)) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } gl::TextureCubeMap *texCube = context->getTextureCubeMap(); @@ -188,7 +210,7 @@ bool ValidateES2TexImageParameters(gl::Context *context, GLenum target, GLint le texture = texCube; } - if (isSubImage && !validateSubImageParamsCube(isCompressed, width, height, xoffset, yoffset, + if (isSubImage && !ValidateSubImageParamsCube(context, isCompressed, width, height, xoffset, yoffset, target, level, format, type, texCube)) { return false; @@ -197,23 +219,27 @@ bool ValidateES2TexImageParameters(gl::Context *context, GLenum target, GLint le break; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } if (!texture) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (!isSubImage && texture->isImmutable()) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } // Verify zero border if (border != 0) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } GLenum actualInternalFormat = isSubImage ? textureInternalFormat : internalformat; @@ -221,32 +247,37 @@ bool ValidateES2TexImageParameters(gl::Context *context, GLenum target, GLint le { if (!ValidCompressedImageSize(context, actualInternalFormat, width, height)) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } switch (actualInternalFormat) { case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - if (!context->supportsDXT1Textures()) + if (!context->getExtensions().textureCompressionDXT1) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: - if (!context->supportsDXT3Textures()) + if (!context->getExtensions().textureCompressionDXT1) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: - if (!context->supportsDXT5Textures()) + if (!context->getExtensions().textureCompressionDXT5) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } } else @@ -265,7 +296,8 @@ bool ValidateES2TexImageParameters(gl::Context *context, GLenum target, GLint le case GL_FLOAT: break; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } // validate + combinations @@ -282,14 +314,17 @@ bool ValidateES2TexImageParameters(gl::Context *context, GLenum target, GLint le case GL_FLOAT: case GL_HALF_FLOAT_OES: break; - default: - return gl::error(GL_INVALID_OPERATION, false); + default: + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } break; case GL_RED: - if (!context->supportsRGTextures()) + case GL_RG: + if (!context->getExtensions().textureRG) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } switch (type) { @@ -298,22 +333,8 @@ bool ValidateES2TexImageParameters(gl::Context *context, GLenum target, GLint le case GL_HALF_FLOAT_OES: break; default: - return gl::error(GL_INVALID_OPERATION, false); - } - break; - case GL_RG: - if (!context->supportsRGTextures()) - { - return gl::error(GL_INVALID_ENUM, false); - } - switch (type) - { - case GL_UNSIGNED_BYTE: - case GL_FLOAT: - case GL_HALF_FLOAT_OES: - break; - default: - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } break; case GL_RGB: @@ -325,7 +346,8 @@ bool ValidateES2TexImageParameters(gl::Context *context, GLenum target, GLint le case GL_HALF_FLOAT_OES: break; default: - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } break; case GL_RGBA: @@ -338,7 +360,8 @@ bool ValidateES2TexImageParameters(gl::Context *context, GLenum target, GLint le case GL_HALF_FLOAT_OES: break; default: - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } break; case GL_BGRA_EXT: @@ -347,7 +370,24 @@ bool ValidateES2TexImageParameters(gl::Context *context, GLenum target, GLint le case GL_UNSIGNED_BYTE: break; default: - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + break; + case GL_SRGB_EXT: + case GL_SRGB_ALPHA_EXT: + if (!context->getExtensions().sRGB) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + switch (type) + { + case GL_UNSIGNED_BYTE: + break; + default: + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } break; case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are handled below @@ -362,7 +402,8 @@ bool ValidateES2TexImageParameters(gl::Context *context, GLenum target, GLint le case GL_UNSIGNED_INT: break; default: - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } break; case GL_DEPTH_STENCIL_OES: @@ -371,61 +412,72 @@ bool ValidateES2TexImageParameters(gl::Context *context, GLenum target, GLint le case GL_UNSIGNED_INT_24_8_OES: break; default: - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } break; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } switch (format) { case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - if (context->supportsDXT1Textures()) + if (context->getExtensions().textureCompressionDXT1) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } else { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: - if (context->supportsDXT3Textures()) + if (context->getExtensions().textureCompressionDXT3) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } else { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: - if (context->supportsDXT5Textures()) + if (context->getExtensions().textureCompressionDXT5) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } else { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; case GL_DEPTH_COMPONENT: case GL_DEPTH_STENCIL_OES: - if (!context->supportsDepthTextures()) + if (!context->getExtensions().depthTextures) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } if (target != GL_TEXTURE_2D) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } // OES_depth_texture supports loading depth data and multiple levels, // but ANGLE_depth_texture does not if (pixels != NULL || level != 0) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } break; default: @@ -434,16 +486,18 @@ bool ValidateES2TexImageParameters(gl::Context *context, GLenum target, GLint le if (type == GL_FLOAT) { - if (!context->supportsFloat32Textures()) + if (!context->getExtensions().textureFloat) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } } else if (type == GL_HALF_FLOAT_OES) { - if (!context->supportsFloat16Textures()) + if (!context->getExtensions().textureHalfFloat) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } } } @@ -453,126 +507,21 @@ bool ValidateES2TexImageParameters(gl::Context *context, GLenum target, GLint le -bool ValidateES2CopyTexImageParameters(gl::Context* context, GLenum target, GLint level, GLenum internalformat, bool isSubImage, +bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint level, GLenum internalformat, bool isSubImage, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) { - if (!ValidTexture2DDestinationTarget(context, target)) + GLenum textureInternalFormat = GL_NONE; + + if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage, + xoffset, yoffset, 0, x, y, width, height, border, &textureInternalFormat)) { - return gl::error(GL_INVALID_ENUM, false); - } - - if (!gl::IsInternalTextureTarget(target, context->getClientVersion())) - { - return gl::error(GL_INVALID_ENUM, false); - } - - if (level < 0 || xoffset < 0 || yoffset < 0 || width < 0 || height < 0) - { - return gl::error(GL_INVALID_VALUE, false); - } - - if (std::numeric_limits::max() - xoffset < width || std::numeric_limits::max() - yoffset < height) - { - return gl::error(GL_INVALID_VALUE, false); - } - - // Verify zero border - if (border != 0) - { - return gl::error(GL_INVALID_VALUE, false); - } - - // Validate dimensions based on Context limits and validate the texture - if (!ValidMipLevel(context, target, level)) - { - return gl::error(GL_INVALID_VALUE, false); - } - - gl::Framebuffer *framebuffer = context->getReadFramebuffer(); - - if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) - { - return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION, false); - } - - if (context->getReadFramebufferHandle() != 0 && framebuffer->getSamples() != 0) - { - return gl::error(GL_INVALID_OPERATION, false); + return false; } + gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); GLenum colorbufferFormat = framebuffer->getReadColorbuffer()->getInternalFormat(); - gl::Texture *texture = NULL; - GLenum textureFormat = GL_RGBA; - - switch (target) - { - case GL_TEXTURE_2D: - { - if (width > (context->getMaximum2DTextureDimension() >> level) || - height > (context->getMaximum2DTextureDimension() >> level)) - { - return gl::error(GL_INVALID_VALUE, false); - } - - gl::Texture2D *tex2d = context->getTexture2D(); - if (tex2d) - { - if (isSubImage && !validateSubImageParams2D(false, width, height, xoffset, yoffset, level, GL_NONE, GL_NONE, tex2d)) - { - return false; // error already registered by validateSubImageParams - } - texture = tex2d; - textureFormat = gl::GetFormat(tex2d->getInternalFormat(level), context->getClientVersion()); - } - } - break; - - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - { - if (!isSubImage && width != height) - { - return gl::error(GL_INVALID_VALUE, false); - } - - if (width > (context->getMaximumCubeTextureDimension() >> level) || - height > (context->getMaximumCubeTextureDimension() >> level)) - { - return gl::error(GL_INVALID_VALUE, false); - } - - gl::TextureCubeMap *texcube = context->getTextureCubeMap(); - if (texcube) - { - if (isSubImage && !validateSubImageParamsCube(false, width, height, xoffset, yoffset, target, level, GL_NONE, GL_NONE, texcube)) - { - return false; // error already registered by validateSubImageParams - } - texture = texcube; - textureFormat = gl::GetFormat(texcube->getInternalFormat(target, level), context->getClientVersion()); - } - } - break; - - default: - return gl::error(GL_INVALID_ENUM, false); - } - - if (!texture) - { - return gl::error(GL_INVALID_OPERATION, false); - } - - if (texture->isImmutable() && !isSubImage) - { - return gl::error(GL_INVALID_OPERATION, false); - } - + GLenum textureFormat = gl::GetInternalFormatInfo(textureInternalFormat).format; // [OpenGL ES 2.0.24] table 3.9 if (isSubImage) @@ -585,7 +534,8 @@ bool ValidateES2CopyTexImageParameters(gl::Context* context, GLenum target, GLin colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } break; case GL_LUMINANCE: @@ -597,7 +547,8 @@ bool ValidateES2CopyTexImageParameters(gl::Context* context, GLenum target, GLin colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } break; case GL_RED_EXT: @@ -609,7 +560,8 @@ bool ValidateES2CopyTexImageParameters(gl::Context* context, GLenum target, GLin colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } break; case GL_RG_EXT: @@ -620,7 +572,8 @@ bool ValidateES2CopyTexImageParameters(gl::Context* context, GLenum target, GLin colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } break; case GL_RGB: @@ -630,7 +583,8 @@ bool ValidateES2CopyTexImageParameters(gl::Context* context, GLenum target, GLin colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } break; case GL_LUMINANCE_ALPHA: @@ -639,19 +593,23 @@ bool ValidateES2CopyTexImageParameters(gl::Context* context, GLenum target, GLin colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } 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 gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; case GL_DEPTH_COMPONENT: case GL_DEPTH_STENCIL_OES: - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; default: - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } else @@ -665,7 +623,8 @@ bool ValidateES2CopyTexImageParameters(gl::Context* context, GLenum target, GLin colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } break; case GL_LUMINANCE: @@ -678,7 +637,8 @@ bool ValidateES2CopyTexImageParameters(gl::Context* context, GLenum target, GLin colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } break; case GL_RED_EXT: @@ -691,7 +651,8 @@ bool ValidateES2CopyTexImageParameters(gl::Context* context, GLenum target, GLin colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } break; case GL_RG_EXT: @@ -703,7 +664,8 @@ bool ValidateES2CopyTexImageParameters(gl::Context* context, GLenum target, GLin colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } break; case GL_RGB: @@ -714,7 +676,8 @@ bool ValidateES2CopyTexImageParameters(gl::Context* context, GLenum target, GLin colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } break; case GL_LUMINANCE_ALPHA: @@ -724,38 +687,45 @@ bool ValidateES2CopyTexImageParameters(gl::Context* context, GLenum target, GLin colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } break; case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - if (context->supportsDXT1Textures()) + if (context->getExtensions().textureCompressionDXT1) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } else { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: - if (context->supportsDXT3Textures()) + if (context->getExtensions().textureCompressionDXT3) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } else { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: - if (context->supportsDXT5Textures()) + if (context->getExtensions().textureCompressionDXT5) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } else { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; case GL_DEPTH_COMPONENT: @@ -763,16 +733,19 @@ bool ValidateES2CopyTexImageParameters(gl::Context* context, GLenum target, GLin case GL_DEPTH_COMPONENT32_OES: case GL_DEPTH_STENCIL_OES: case GL_DEPTH24_STENCIL8_OES: - if (context->supportsDepthTextures()) + if (context->getExtensions().depthTextures) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } else { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } } @@ -780,62 +753,71 @@ bool ValidateES2CopyTexImageParameters(gl::Context* context, GLenum target, GLin return (width > 0 && height > 0); } -bool ValidateES2TexStorageParameters(gl::Context *context, GLenum target, GLsizei levels, GLenum internalformat, +bool ValidateES2TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) { if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } if (width < 1 || height < 1 || levels < 1) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } if (target == GL_TEXTURE_CUBE_MAP && width != height) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } - GLenum format = gl::GetFormat(internalformat, context->getClientVersion()); - GLenum type = gl::GetType(internalformat, context->getClientVersion()); - - if (format == GL_NONE || type == GL_NONE) + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat); + if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } + const gl::Caps &caps = context->getCaps(); + switch (target) { case GL_TEXTURE_2D: - if (width > context->getMaximum2DTextureDimension() || - height > context->getMaximum2DTextureDimension()) + if (static_cast(width) > caps.max2DTextureSize || + static_cast(height) > caps.max2DTextureSize) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } break; case GL_TEXTURE_CUBE_MAP: - if (width > context->getMaximumCubeTextureDimension() || - height > context->getMaximumCubeTextureDimension()) + if (static_cast(width) > caps.maxCubeMapTextureSize || + static_cast(height) > caps.maxCubeMapTextureSize) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } break; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } - if (levels != 1 && !context->supportsNonPower2Texture()) + if (levels != 1 && !context->getExtensions().textureNPOT) { if (!gl::isPow2(width) || !gl::isPow2(height)) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } @@ -843,21 +825,24 @@ bool ValidateES2TexStorageParameters(gl::Context *context, GLenum target, GLsize { case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - if (!context->supportsDXT1Textures()) + if (!context->getExtensions().textureCompressionDXT1) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: - if (!context->supportsDXT3Textures()) + if (!context->getExtensions().textureCompressionDXT3) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: - if (!context->supportsDXT5Textures()) + if (!context->getExtensions().textureCompressionDXT5) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; case GL_RGBA32F_EXT: @@ -865,9 +850,10 @@ bool ValidateES2TexStorageParameters(gl::Context *context, GLenum target, GLsize case GL_ALPHA32F_EXT: case GL_LUMINANCE32F_EXT: case GL_LUMINANCE_ALPHA32F_EXT: - if (!context->supportsFloat32Textures()) + if (!context->getExtensions().textureFloat) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; case GL_RGBA16F_EXT: @@ -875,9 +861,10 @@ bool ValidateES2TexStorageParameters(gl::Context *context, GLenum target, GLsize case GL_ALPHA16F_EXT: case GL_LUMINANCE16F_EXT: case GL_LUMINANCE_ALPHA16F_EXT: - if (!context->supportsFloat16Textures()) + if (!context->getExtensions().textureHalfFloat) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; case GL_R8_EXT: @@ -886,26 +873,30 @@ bool ValidateES2TexStorageParameters(gl::Context *context, GLenum target, GLsize case GL_RG16F_EXT: case GL_R32F_EXT: case GL_RG32F_EXT: - if (!context->supportsRGTextures()) + if (!context->getExtensions().textureRG) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; case GL_DEPTH_COMPONENT16: case GL_DEPTH_COMPONENT32_OES: case GL_DEPTH24_STENCIL8_OES: - if (!context->supportsDepthTextures()) + if (!context->getExtensions().depthTextures) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } if (target != GL_TEXTURE_2D) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } // ANGLE_depth_texture only supports 1-level textures if (levels != 1) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } break; default: @@ -927,124 +918,21 @@ bool ValidateES2TexStorageParameters(gl::Context *context, GLenum target, GLsize if (!texture || texture->id() == 0) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (texture->isImmutable()) { - return gl::error(GL_INVALID_OPERATION, false); - } - - return true; -} - -bool ValidateES2FramebufferTextureParameters(gl::Context *context, GLenum target, GLenum attachment, - GLenum textarget, GLuint texture, GLint level) -{ - META_ASSERT(GL_DRAW_FRAMEBUFFER == GL_DRAW_FRAMEBUFFER_ANGLE && GL_READ_FRAMEBUFFER == GL_READ_FRAMEBUFFER_ANGLE); - - if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER) - { - return gl::error(GL_INVALID_ENUM, false); - } - - if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15) - { - const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0); - if (colorAttachment >= context->getMaximumRenderTargets()) - { - return gl::error(GL_INVALID_VALUE, false); - } - } - else - { - switch (attachment) - { - case GL_DEPTH_ATTACHMENT: - case GL_STENCIL_ATTACHMENT: - break; - default: - return gl::error(GL_INVALID_ENUM, false); - } - } - - if (texture != 0) - { - gl::Texture *tex = context->getTexture(texture); - - if (tex == NULL) - { - return gl::error(GL_INVALID_OPERATION, false); - } - - switch (textarget) - { - case GL_TEXTURE_2D: - { - if (tex->getTarget() != GL_TEXTURE_2D) - { - return gl::error(GL_INVALID_OPERATION, false); - } - gl::Texture2D *tex2d = static_cast(tex); - if (tex2d->isCompressed(level)) - { - return gl::error(GL_INVALID_OPERATION, false); - } - break; - } - - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - { - if (tex->getTarget() != GL_TEXTURE_CUBE_MAP) - { - return gl::error(GL_INVALID_OPERATION, false); - } - gl::TextureCubeMap *texcube = static_cast(tex); - if (texcube->isCompressed(textarget, level)) - { - return gl::error(GL_INVALID_OPERATION, false); - } - break; - } - - default: - return gl::error(GL_INVALID_ENUM, false); - } - - if (level != 0) - { - return gl::error(GL_INVALID_VALUE, false); - } - } - - gl::Framebuffer *framebuffer = NULL; - GLuint framebufferHandle = 0; - if (target == GL_READ_FRAMEBUFFER) - { - framebuffer = context->getReadFramebuffer(); - framebufferHandle = context->getReadFramebufferHandle(); - } - else - { - framebuffer = context->getDrawFramebuffer(); - framebufferHandle = context->getDrawFramebufferHandle(); - } - - if (framebufferHandle == 0 || !framebuffer) - { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } return true; } // check for combinations of format and type that are valid for ReadPixels -bool ValidES2ReadFormatType(gl::Context *context, GLenum format, GLenum type) +bool ValidES2ReadFormatType(Context *context, GLenum format, GLenum type) { switch (format) { @@ -1070,7 +958,7 @@ bool ValidES2ReadFormatType(gl::Context *context, GLenum format, GLenum type) break; case GL_RG_EXT: case GL_RED_EXT: - if (!context->supportsRGTextures()) + if (!context->getExtensions().textureRG) { return false; } diff --git a/gfx/angle/src/libGLESv2/validationES2.h b/gfx/angle/src/libGLESv2/validationES2.h index 02775ff012bd..53a0b630eab0 100644 --- a/gfx/angle/src/libGLESv2/validationES2.h +++ b/gfx/angle/src/libGLESv2/validationES2.h @@ -9,26 +9,25 @@ #ifndef LIBGLESV2_VALIDATION_ES2_H #define LIBGLESV2_VALIDATION_ES2_H +#include + namespace gl { class Context; -bool ValidateES2TexImageParameters(gl::Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage, +bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -bool ValidateES2CopyTexImageParameters(gl::Context* context, GLenum target, GLint level, GLenum internalformat, bool isSubImage, +bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint level, GLenum internalformat, bool isSubImage, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); -bool ValidateES2TexStorageParameters(gl::Context *context, GLenum target, GLsizei levels, GLenum internalformat, +bool ValidateES2TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); -bool ValidateES2FramebufferTextureParameters(gl::Context *context, GLenum target, GLenum attachment, - GLenum textarget, GLuint texture, GLint level); - -bool ValidES2ReadFormatType(gl::Context *context, GLenum format, GLenum type); +bool ValidES2ReadFormatType(Context *context, GLenum format, GLenum type); } diff --git a/gfx/angle/src/libGLESv2/validationES3.cpp b/gfx/angle/src/libGLESv2/validationES3.cpp index ad1bde78de91..251c6ad2c4b2 100644 --- a/gfx/angle/src/libGLESv2/validationES3.cpp +++ b/gfx/angle/src/libGLESv2/validationES3.cpp @@ -1,6 +1,5 @@ -#include "precompiled.h" // -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2013-2014 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,28 +14,303 @@ #include "libGLESv2/Renderbuffer.h" #include "libGLESv2/formatutils.h" #include "libGLESv2/main.h" +#include "libGLESv2/FramebufferAttachment.h" #include "common/mathutil.h" namespace gl { -bool ValidateES3TexImageParameters(gl::Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage, +struct ES3FormatCombination +{ + GLenum internalFormat; + GLenum format; + GLenum type; +}; + +bool operator<(const ES3FormatCombination& a, const ES3FormatCombination& b) +{ + return memcmp(&a, &b, sizeof(ES3FormatCombination)) < 0; +} + +typedef std::set ES3FormatCombinationSet; + +static inline void InsertES3FormatCombo(ES3FormatCombinationSet *set, GLenum internalFormat, GLenum format, GLenum type) +{ + ES3FormatCombination info; + info.internalFormat = internalFormat; + info.format = format; + info.type = type; + set->insert(info); +} + +ES3FormatCombinationSet BuildES3FormatSet() +{ + ES3FormatCombinationSet set; + + // Format combinations from ES 3.0.1 spec, table 3.2 + + // | Internal format | Format | Type | + // | | | | + InsertES3FormatCombo(&set, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_RGBA4, GL_RGBA, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_RGBA8_SNORM, GL_RGBA, GL_BYTE ); + InsertES3FormatCombo(&set, GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 ); + InsertES3FormatCombo(&set, GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV ); + InsertES3FormatCombo(&set, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV ); + InsertES3FormatCombo(&set, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 ); + InsertES3FormatCombo(&set, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT ); + InsertES3FormatCombo(&set, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT_OES ); + InsertES3FormatCombo(&set, GL_RGBA32F, GL_RGBA, GL_FLOAT ); + InsertES3FormatCombo(&set, GL_RGBA16F, GL_RGBA, GL_FLOAT ); + InsertES3FormatCombo(&set, GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE ); + InsertES3FormatCombo(&set, GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT ); + InsertES3FormatCombo(&set, GL_RGBA16I, GL_RGBA_INTEGER, GL_SHORT ); + InsertES3FormatCombo(&set, GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT ); + InsertES3FormatCombo(&set, GL_RGBA32I, GL_RGBA_INTEGER, GL_INT ); + InsertES3FormatCombo(&set, GL_RGB10_A2UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV ); + InsertES3FormatCombo(&set, GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_RGB565, GL_RGB, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_SRGB8, GL_RGB, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_RGB8_SNORM, GL_RGB, GL_BYTE ); + InsertES3FormatCombo(&set, GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 ); + InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV ); + InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV ); + InsertES3FormatCombo(&set, GL_RGB16F, GL_RGB, GL_HALF_FLOAT ); + InsertES3FormatCombo(&set, GL_RGB16F, GL_RGB, GL_HALF_FLOAT_OES ); + InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_HALF_FLOAT ); + InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_HALF_FLOAT_OES ); + InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_HALF_FLOAT ); + InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_HALF_FLOAT_OES ); + InsertES3FormatCombo(&set, GL_RGB32F, GL_RGB, GL_FLOAT ); + InsertES3FormatCombo(&set, GL_RGB16F, GL_RGB, GL_FLOAT ); + InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_FLOAT ); + InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_FLOAT ); + InsertES3FormatCombo(&set, GL_RGB8UI, GL_RGB_INTEGER, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_RGB8I, GL_RGB_INTEGER, GL_BYTE ); + InsertES3FormatCombo(&set, GL_RGB16UI, GL_RGB_INTEGER, GL_UNSIGNED_SHORT ); + InsertES3FormatCombo(&set, GL_RGB16I, GL_RGB_INTEGER, GL_SHORT ); + InsertES3FormatCombo(&set, GL_RGB32UI, GL_RGB_INTEGER, GL_UNSIGNED_INT ); + InsertES3FormatCombo(&set, GL_RGB32I, GL_RGB_INTEGER, GL_INT ); + InsertES3FormatCombo(&set, GL_RG8, GL_RG, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_RG8_SNORM, GL_RG, GL_BYTE ); + InsertES3FormatCombo(&set, GL_RG16F, GL_RG, GL_HALF_FLOAT ); + InsertES3FormatCombo(&set, GL_RG16F, GL_RG, GL_HALF_FLOAT_OES ); + InsertES3FormatCombo(&set, GL_RG32F, GL_RG, GL_FLOAT ); + InsertES3FormatCombo(&set, GL_RG16F, GL_RG, GL_FLOAT ); + InsertES3FormatCombo(&set, GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_RG8I, GL_RG_INTEGER, GL_BYTE ); + InsertES3FormatCombo(&set, GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT ); + InsertES3FormatCombo(&set, GL_RG16I, GL_RG_INTEGER, GL_SHORT ); + InsertES3FormatCombo(&set, GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT ); + InsertES3FormatCombo(&set, GL_RG32I, GL_RG_INTEGER, GL_INT ); + InsertES3FormatCombo(&set, GL_R8, GL_RED, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_R8_SNORM, GL_RED, GL_BYTE ); + InsertES3FormatCombo(&set, GL_R16F, GL_RED, GL_HALF_FLOAT ); + InsertES3FormatCombo(&set, GL_R16F, GL_RED, GL_HALF_FLOAT_OES ); + InsertES3FormatCombo(&set, GL_R32F, GL_RED, GL_FLOAT ); + InsertES3FormatCombo(&set, GL_R16F, GL_RED, GL_FLOAT ); + InsertES3FormatCombo(&set, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_R8I, GL_RED_INTEGER, GL_BYTE ); + InsertES3FormatCombo(&set, GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT ); + InsertES3FormatCombo(&set, GL_R16I, GL_RED_INTEGER, GL_SHORT ); + InsertES3FormatCombo(&set, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT ); + InsertES3FormatCombo(&set, GL_R32I, GL_RED_INTEGER, GL_INT ); + + // Unsized formats + InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 ); + InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 ); + InsertES3FormatCombo(&set, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 ); + InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_SRGB_ALPHA_EXT, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_SRGB_EXT, GL_SRGB_EXT, GL_UNSIGNED_BYTE ); + + // Depth stencil formats + InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT ); + InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT ); + InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT ); + InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT ); + InsertES3FormatCombo(&set, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8 ); + InsertES3FormatCombo(&set, GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV); + + // From GL_EXT_sRGB + InsertES3FormatCombo(&set, GL_SRGB8_ALPHA8_EXT, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_SRGB8, GL_SRGB_EXT, GL_UNSIGNED_BYTE ); + + // From GL_OES_texture_float + InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT ); + InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT ); + InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_FLOAT ); + + // From GL_OES_texture_half_float + InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT ); + InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES ); + InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT ); + InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT_OES ); + InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT ); + InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT_OES ); + + // From GL_EXT_texture_format_BGRA8888 + InsertES3FormatCombo(&set, GL_BGRA_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE ); + + // From GL_EXT_texture_storage + // | Internal format | Format | Type | + // | | | | + InsertES3FormatCombo(&set, GL_ALPHA8_EXT, GL_ALPHA, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_LUMINANCE8_EXT, GL_LUMINANCE, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_ALPHA32F_EXT, GL_ALPHA, GL_FLOAT ); + InsertES3FormatCombo(&set, GL_LUMINANCE32F_EXT, GL_LUMINANCE, GL_FLOAT ); + InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA32F_EXT, GL_LUMINANCE_ALPHA, GL_FLOAT ); + InsertES3FormatCombo(&set, GL_ALPHA16F_EXT, GL_ALPHA, GL_HALF_FLOAT ); + InsertES3FormatCombo(&set, GL_ALPHA16F_EXT, GL_ALPHA, GL_HALF_FLOAT_OES ); + InsertES3FormatCombo(&set, GL_LUMINANCE16F_EXT, GL_LUMINANCE, GL_HALF_FLOAT ); + InsertES3FormatCombo(&set, GL_LUMINANCE16F_EXT, GL_LUMINANCE, GL_HALF_FLOAT_OES ); + InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT ); + InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES ); + + // From GL_EXT_texture_storage and GL_EXT_texture_format_BGRA8888 + InsertES3FormatCombo(&set, GL_BGRA8_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_BGRA4_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT); + InsertES3FormatCombo(&set, GL_BGRA4_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_BGR5_A1_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT); + InsertES3FormatCombo(&set, GL_BGR5_A1_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_BYTE ); + + // From GL_ANGLE_depth_texture + InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT32_OES, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT_24_8_OES ); + + // Compressed formats + // From ES 3.0.1 spec, table 3.16 + // | Internal format | Format | Type | + // | | | | + InsertES3FormatCombo(&set, GL_COMPRESSED_R11_EAC, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE); + InsertES3FormatCombo(&set, GL_COMPRESSED_R11_EAC, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE); + InsertES3FormatCombo(&set, GL_COMPRESSED_SIGNED_R11_EAC, GL_COMPRESSED_SIGNED_R11_EAC, GL_UNSIGNED_BYTE); + InsertES3FormatCombo(&set, GL_COMPRESSED_RG11_EAC, GL_COMPRESSED_RG11_EAC, GL_UNSIGNED_BYTE); + InsertES3FormatCombo(&set, GL_COMPRESSED_SIGNED_RG11_EAC, GL_COMPRESSED_SIGNED_RG11_EAC, GL_UNSIGNED_BYTE); + InsertES3FormatCombo(&set, GL_COMPRESSED_RGB8_ETC2, GL_COMPRESSED_RGB8_ETC2, GL_UNSIGNED_BYTE); + InsertES3FormatCombo(&set, GL_COMPRESSED_SRGB8_ETC2, GL_COMPRESSED_SRGB8_ETC2, GL_UNSIGNED_BYTE); + InsertES3FormatCombo(&set, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE); + InsertES3FormatCombo(&set, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE); + InsertES3FormatCombo(&set, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_UNSIGNED_BYTE); + InsertES3FormatCombo(&set, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_UNSIGNED_BYTE); + + + // From GL_EXT_texture_compression_dxt1 + InsertES3FormatCombo(&set, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE); + InsertES3FormatCombo(&set, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE); + + // From GL_ANGLE_texture_compression_dxt3 + InsertES3FormatCombo(&set, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE); + + // From GL_ANGLE_texture_compression_dxt5 + InsertES3FormatCombo(&set, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE); + + return set; +} + +static bool ValidateTexImageFormatCombination(gl::Context *context, GLenum internalFormat, GLenum format, GLenum type) +{ + // Note: dEQP 2013.4 expects an INVALID_VALUE error for TexImage3D with an invalid + // internal format. (dEQP-GLES3.functional.negative_api.texture.teximage3d) + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); + if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions())) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + // The type and format are valid if any supported internal format has that type and format + bool formatSupported = false; + bool typeSupported = false; + + static const ES3FormatCombinationSet es3FormatSet = BuildES3FormatSet(); + for (ES3FormatCombinationSet::const_iterator i = es3FormatSet.begin(); i != es3FormatSet.end(); i++) + { + if (i->format == format || i->type == type) + { + const gl::InternalFormat &info = gl::GetInternalFormatInfo(i->internalFormat); + bool supported = info.textureSupport(context->getClientVersion(), context->getExtensions()); + if (supported && i->type == type) + { + typeSupported = true; + } + if (supported && i->format == format) + { + formatSupported = true; + } + + // Early-out if both type and format are supported now + if (typeSupported && formatSupported) + { + break; + } + } + } + + if (!typeSupported || !formatSupported) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + // Check if this is a valid format combination to load texture data + ES3FormatCombination searchFormat; + searchFormat.internalFormat = internalFormat; + searchFormat.format = format; + searchFormat.type = type; + + if (es3FormatSet.find(searchFormat) == es3FormatSet.end()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + return true; +} + +bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels) { + if (!ValidTexture2DDestinationTarget(context, target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + // Validate image size if (!ValidImageSize(context, target, level, width, height, depth)) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } // Verify zero border if (border != 0) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } + if (xoffset < 0 || yoffset < 0 || zoffset < 0 || + std::numeric_limits::max() - xoffset < width || + std::numeric_limits::max() - yoffset < height || + std::numeric_limits::max() - zoffset < depth) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + const gl::Caps &caps = context->getCaps(); + gl::Texture *texture = NULL; bool textureCompressed = false; GLenum textureInternalFormat = GL_NONE; @@ -47,10 +321,11 @@ bool ValidateES3TexImageParameters(gl::Context *context, GLenum target, GLint le { case GL_TEXTURE_2D: { - if (width > (context->getMaximum2DTextureDimension() >> level) || - height > (context->getMaximum2DTextureDimension() >> level)) + if (static_cast(width) > (caps.max2DTextureSize >> level) || + static_cast(height) > (caps.max2DTextureSize >> level)) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } gl::Texture2D *texture2d = context->getTexture2D(); @@ -75,12 +350,14 @@ bool ValidateES3TexImageParameters(gl::Context *context, GLenum target, GLint le { if (!isSubImage && width != height) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } - if (width > (context->getMaximumCubeTextureDimension() >> level)) + if (static_cast(width) > (caps.maxCubeMapTextureSize >> level)) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } gl::TextureCubeMap *textureCube = context->getTextureCubeMap(); @@ -98,11 +375,12 @@ bool ValidateES3TexImageParameters(gl::Context *context, GLenum target, GLint le case GL_TEXTURE_3D: { - if (width > (context->getMaximum3DTextureDimension() >> level) || - height > (context->getMaximum3DTextureDimension() >> level) || - depth > (context->getMaximum3DTextureDimension() >> level)) + if (static_cast(width) > (caps.max3DTextureSize >> level) || + static_cast(height) > (caps.max3DTextureSize >> level) || + static_cast(depth) > (caps.max3DTextureSize >> level)) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } gl::Texture3D *texture3d = context->getTexture3D(); @@ -120,11 +398,12 @@ bool ValidateES3TexImageParameters(gl::Context *context, GLenum target, GLint le case GL_TEXTURE_2D_ARRAY: { - if (width > (context->getMaximum2DTextureDimension() >> level) || - height > (context->getMaximum2DTextureDimension() >> level) || - depth > (context->getMaximum2DArrayTextureLayers() >> level)) + if (static_cast(width) > (caps.max2DTextureSize >> level) || + static_cast(height) > (caps.max2DTextureSize >> level) || + static_cast(depth) > (caps.maxArrayTextureLayers >> level)) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } gl::Texture2DArray *texture2darray = context->getTexture2DArray(); @@ -141,55 +420,56 @@ bool ValidateES3TexImageParameters(gl::Context *context, GLenum target, GLint le break; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } if (!texture) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (texture->isImmutable() && !isSubImage) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } // Validate texture formats GLenum actualInternalFormat = isSubImage ? textureInternalFormat : internalformat; + const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(actualInternalFormat); if (isCompressed) { if (!ValidCompressedImageSize(context, actualInternalFormat, width, height)) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } - if (!gl::IsFormatCompressed(actualInternalFormat, context->getClientVersion())) + if (!actualFormatInfo.compressed) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } if (target == GL_TEXTURE_3D) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } else { - if (!gl::IsValidInternalFormat(actualInternalFormat, context) || - !gl::IsValidFormat(format, context->getClientVersion()) || - !gl::IsValidType(type, context->getClientVersion())) + if (!ValidateTexImageFormatCombination(context, actualInternalFormat, format, type)) { - return gl::error(GL_INVALID_ENUM, false); - } - - if (!gl::IsValidFormatCombination(actualInternalFormat, format, type, context->getClientVersion())) - { - return gl::error(GL_INVALID_OPERATION, false); + return false; } if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL)) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } @@ -198,7 +478,8 @@ bool ValidateES3TexImageParameters(gl::Context *context, GLenum target, GLint le { if (isCompressed != textureCompressed) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (isCompressed) @@ -206,7 +487,8 @@ bool ValidateES3TexImageParameters(gl::Context *context, GLenum target, GLint le if ((width % 4 != 0 && width != textureLevelWidth) || (height % 4 != 0 && height != textureLevelHeight)) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } @@ -217,26 +499,29 @@ bool ValidateES3TexImageParameters(gl::Context *context, GLenum target, GLint le if (xoffset < 0 || yoffset < 0 || zoffset < 0) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } if (std::numeric_limits::max() - xoffset < width || std::numeric_limits::max() - yoffset < height || std::numeric_limits::max() - zoffset < depth) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } if (xoffset + width > textureLevelWidth || yoffset + height > textureLevelHeight || zoffset + depth > textureLevelDepth) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } } // Check for pixel unpack buffer related API errors - gl::Buffer *pixelUnpackBuffer = context->getPixelUnpackBuffer(); + gl::Buffer *pixelUnpackBuffer = context->getState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER); if (pixelUnpackBuffer != NULL) { // ...the data would be unpacked from the buffer object such that the memory reads required @@ -244,236 +529,404 @@ bool ValidateES3TexImageParameters(gl::Context *context, GLenum target, GLint le size_t widthSize = static_cast(width); size_t heightSize = static_cast(height); size_t depthSize = static_cast(depth); - size_t pixelBytes = static_cast(gl::GetPixelBytes(actualInternalFormat, context->getClientVersion())); + GLenum sizedFormat = GetSizedInternalFormat(actualInternalFormat, type); + + size_t pixelBytes = static_cast(gl::GetInternalFormatInfo(sizedFormat).pixelBytes); if (!rx::IsUnsignedMultiplicationSafe(widthSize, heightSize) || !rx::IsUnsignedMultiplicationSafe(widthSize * heightSize, depthSize) || !rx::IsUnsignedMultiplicationSafe(widthSize * heightSize * depthSize, pixelBytes)) { // Overflow past the end of the buffer - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } size_t copyBytes = widthSize * heightSize * depthSize * pixelBytes; size_t offset = reinterpret_cast(pixels); - if (!rx::IsUnsignedAdditionSafe(offset, copyBytes) || ((offset + copyBytes) > static_cast(pixelUnpackBuffer->size()))) + if (!rx::IsUnsignedAdditionSafe(offset, copyBytes) || + ((offset + copyBytes) > static_cast(pixelUnpackBuffer->getSize()))) { // Overflow past the end of the buffer - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } // ...data is not evenly divisible into the number of bytes needed to store in memory a datum // indicated by type. - size_t dataBytesPerPixel = static_cast(gl::GetTypeBytes(type)); + size_t dataBytesPerPixel = static_cast(gl::GetTypeInfo(type).bytes); if ((offset % dataBytesPerPixel) != 0) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } // ...the buffer object's data store is currently mapped. - if (pixelUnpackBuffer->mapped()) + if (pixelUnpackBuffer->isMapped()) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } return true; } -bool ValidateES3CopyTexImageParameters(gl::Context *context, GLenum target, GLint level, GLenum internalformat, - bool isSubImage, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, - GLsizei width, GLsizei height, GLint border) +struct EffectiveInternalFormatInfo { - if (!ValidTexture2DDestinationTarget(context, target)) + GLenum mEffectiveFormat; + GLenum mDestFormat; + GLuint mMinRedBits; + GLuint mMaxRedBits; + GLuint mMinGreenBits; + GLuint mMaxGreenBits; + GLuint mMinBlueBits; + GLuint mMaxBlueBits; + GLuint mMinAlphaBits; + GLuint mMaxAlphaBits; + + EffectiveInternalFormatInfo(GLenum effectiveFormat, GLenum destFormat, GLuint minRedBits, GLuint maxRedBits, + GLuint minGreenBits, GLuint maxGreenBits, GLuint minBlueBits, GLuint maxBlueBits, + GLuint minAlphaBits, GLuint maxAlphaBits) + : mEffectiveFormat(effectiveFormat), mDestFormat(destFormat), mMinRedBits(minRedBits), + mMaxRedBits(maxRedBits), mMinGreenBits(minGreenBits), mMaxGreenBits(maxGreenBits), + mMinBlueBits(minBlueBits), mMaxBlueBits(maxBlueBits), mMinAlphaBits(minAlphaBits), + mMaxAlphaBits(maxAlphaBits) {}; +}; + +typedef std::vector EffectiveInternalFormatList; + +static EffectiveInternalFormatList BuildSizedEffectiveInternalFormatList() +{ + EffectiveInternalFormatList list; + + // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and + // linear source buffer component sizes. + // | Source channel min/max sizes | + // Effective Internal Format | N/A | R | G | B | A | + list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8)); + list.push_back(EffectiveInternalFormatInfo(GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0)); + list.push_back(EffectiveInternalFormatInfo(GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0)); + list.push_back(EffectiveInternalFormatInfo(GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0)); + list.push_back(EffectiveInternalFormatInfo(GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0)); + list.push_back(EffectiveInternalFormatInfo(GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4)); + list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1)); + list.push_back(EffectiveInternalFormatInfo(GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8)); + list.push_back(EffectiveInternalFormatInfo(GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2)); + + return list; +} + +static EffectiveInternalFormatList BuildUnsizedEffectiveInternalFormatList() +{ + EffectiveInternalFormatList list; + + // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and + // linear source buffer component sizes. + // | Source channel min/max sizes | + // Effective Internal Format | Dest Format | R | G | B | A | + list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT, GL_ALPHA, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX, 1, 8)); + list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX)); + list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, UINT_MAX, 0, UINT_MAX, 1, 8)); + list.push_back(EffectiveInternalFormatInfo(GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, UINT_MAX)); + list.push_back(EffectiveInternalFormatInfo(GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, UINT_MAX)); + list.push_back(EffectiveInternalFormatInfo(GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4)); + list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1)); + list.push_back(EffectiveInternalFormatInfo(GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8)); + + return list; +} + +static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat, const InternalFormat &destFormat, + GLenum *outEffectiveFormat) +{ + const EffectiveInternalFormatList *list = NULL; + GLenum targetFormat = GL_NONE; + + if (destFormat.pixelBytes > 0) { - return gl::error(GL_INVALID_ENUM, false); + static const EffectiveInternalFormatList sizedList = BuildSizedEffectiveInternalFormatList(); + list = &sizedList; + } + else + { + static const EffectiveInternalFormatList unsizedList = BuildUnsizedEffectiveInternalFormatList(); + list = &unsizedList; + targetFormat = destFormat.format; } - if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0) + for (size_t curFormat = 0; curFormat < list->size(); ++curFormat) { - return gl::error(GL_INVALID_VALUE, false); + const EffectiveInternalFormatInfo& formatInfo = list->at(curFormat); + if ((formatInfo.mDestFormat == targetFormat) && + (formatInfo.mMinRedBits <= srcFormat.redBits && formatInfo.mMaxRedBits >= srcFormat.redBits) && + (formatInfo.mMinGreenBits <= srcFormat.greenBits && formatInfo.mMaxGreenBits >= srcFormat.greenBits) && + (formatInfo.mMinBlueBits <= srcFormat.blueBits && formatInfo.mMaxBlueBits >= srcFormat.blueBits) && + (formatInfo.mMinAlphaBits <= srcFormat.alphaBits && formatInfo.mMaxAlphaBits >= srcFormat.alphaBits)) + { + *outEffectiveFormat = formatInfo.mEffectiveFormat; + return true; + } } - if (std::numeric_limits::max() - xoffset < width || std::numeric_limits::max() - yoffset < height) + return false; +} + +struct CopyConversion +{ + GLenum mTextureFormat; + GLenum mFramebufferFormat; + + CopyConversion(GLenum textureFormat, GLenum framebufferFormat) + : mTextureFormat(textureFormat), mFramebufferFormat(framebufferFormat) { } + + bool operator<(const CopyConversion& other) const { - return gl::error(GL_INVALID_VALUE, false); + return memcmp(this, &other, sizeof(CopyConversion)) < 0; + } +}; + +typedef std::set CopyConversionSet; + +static CopyConversionSet BuildValidES3CopyTexImageCombinations() +{ + CopyConversionSet set; + + // From ES 3.0.1 spec, table 3.15 + set.insert(CopyConversion(GL_ALPHA, GL_RGBA)); + set.insert(CopyConversion(GL_LUMINANCE, GL_RED)); + set.insert(CopyConversion(GL_LUMINANCE, GL_RG)); + set.insert(CopyConversion(GL_LUMINANCE, GL_RGB)); + set.insert(CopyConversion(GL_LUMINANCE, GL_RGBA)); + set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_RGBA)); + set.insert(CopyConversion(GL_RED, GL_RED)); + set.insert(CopyConversion(GL_RED, GL_RG)); + set.insert(CopyConversion(GL_RED, GL_RGB)); + set.insert(CopyConversion(GL_RED, GL_RGBA)); + set.insert(CopyConversion(GL_RG, GL_RG)); + set.insert(CopyConversion(GL_RG, GL_RGB)); + set.insert(CopyConversion(GL_RG, GL_RGBA)); + set.insert(CopyConversion(GL_RGB, GL_RGB)); + set.insert(CopyConversion(GL_RGB, GL_RGBA)); + set.insert(CopyConversion(GL_RGBA, GL_RGBA)); + + // Necessary for ANGLE back-buffers + set.insert(CopyConversion(GL_ALPHA, GL_BGRA_EXT)); + set.insert(CopyConversion(GL_LUMINANCE, GL_BGRA_EXT)); + set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_BGRA_EXT)); + set.insert(CopyConversion(GL_RED, GL_BGRA_EXT)); + set.insert(CopyConversion(GL_RG, GL_BGRA_EXT)); + set.insert(CopyConversion(GL_RGB, GL_BGRA_EXT)); + set.insert(CopyConversion(GL_RGBA, GL_BGRA_EXT)); + + set.insert(CopyConversion(GL_RED_INTEGER, GL_RED_INTEGER)); + set.insert(CopyConversion(GL_RED_INTEGER, GL_RG_INTEGER)); + set.insert(CopyConversion(GL_RED_INTEGER, GL_RGB_INTEGER)); + set.insert(CopyConversion(GL_RED_INTEGER, GL_RGBA_INTEGER)); + set.insert(CopyConversion(GL_RG_INTEGER, GL_RG_INTEGER)); + set.insert(CopyConversion(GL_RG_INTEGER, GL_RGB_INTEGER)); + set.insert(CopyConversion(GL_RG_INTEGER, GL_RGBA_INTEGER)); + set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGB_INTEGER)); + set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGBA_INTEGER)); + set.insert(CopyConversion(GL_RGBA_INTEGER, GL_RGBA_INTEGER)); + + return set; +} + +static bool IsValidES3CopyTexImageCombination(GLenum textureInternalFormat, GLenum frameBufferInternalFormat, GLuint readBufferHandle) +{ + const InternalFormat &textureInternalFormatInfo = GetInternalFormatInfo(textureInternalFormat); + const InternalFormat &framebufferInternalFormatInfo = GetInternalFormatInfo(frameBufferInternalFormat); + + static const CopyConversionSet conversionSet = BuildValidES3CopyTexImageCombinations(); + if (conversionSet.find(CopyConversion(textureInternalFormatInfo.format, framebufferInternalFormatInfo.format)) != conversionSet.end()) + { + // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats + // must both be signed, unsigned, or fixed point and both source and destinations + // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed + // conversion between fixed and floating point. + + if ((textureInternalFormatInfo.colorEncoding == GL_SRGB) != (framebufferInternalFormatInfo.colorEncoding == GL_SRGB)) + { + return false; + } + + if (((textureInternalFormatInfo.componentType == GL_INT) != (framebufferInternalFormatInfo.componentType == GL_INT )) || + ((textureInternalFormatInfo.componentType == GL_UNSIGNED_INT) != (framebufferInternalFormatInfo.componentType == GL_UNSIGNED_INT))) + { + return false; + } + + if ((textureInternalFormatInfo.componentType == GL_UNSIGNED_NORMALIZED || + textureInternalFormatInfo.componentType == GL_SIGNED_NORMALIZED || + textureInternalFormatInfo.componentType == GL_FLOAT) && + !(framebufferInternalFormatInfo.componentType == GL_UNSIGNED_NORMALIZED || + framebufferInternalFormatInfo.componentType == GL_SIGNED_NORMALIZED || + framebufferInternalFormatInfo.componentType == GL_FLOAT)) + { + return false; + } + + // GLES specification 3.0.3, sec 3.8.5, pg 139-140: + // The effective internal format of the source buffer is determined with the following rules applied in order: + // * If the source buffer is a texture or renderbuffer that was created with a sized internal format then the + // effective internal format is the source buffer's sized internal format. + // * If the source buffer is a texture that was created with an unsized base internal format, then the + // effective internal format is the source image array's effective internal format, as specified by table + // 3.12, which is determined from the and that were used when the source image array was + // specified by TexImage*. + // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18 where + // Destination Internal Format matches internalformat and where the [source channel sizes] are consistent + // with the values of the source buffer's [channel sizes]. Table 3.17 is used if the + // FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the FRAMEBUFFER_ATTACHMENT_ENCODING + // is SRGB. + const InternalFormat *sourceEffectiveFormat = NULL; + if (readBufferHandle != 0) + { + // Not the default framebuffer, therefore the read buffer must be a user-created texture or renderbuffer + if (framebufferInternalFormatInfo.pixelBytes > 0) + { + sourceEffectiveFormat = &framebufferInternalFormatInfo; + } + else + { + // Renderbuffers cannot be created with an unsized internal format, so this must be an unsized-format + // texture. We can use the same table we use when creating textures to get its effective sized format. + const FormatType &typeInfo = GetFormatTypeInfo(framebufferInternalFormatInfo.format, framebufferInternalFormatInfo.type); + sourceEffectiveFormat = &GetInternalFormatInfo(typeInfo.internalFormat); + } + } + else + { + // The effective internal format must be derived from the source framebuffer's channel sizes. + // This is done in GetEffectiveInternalFormat for linear buffers (table 3.17) + if (framebufferInternalFormatInfo.colorEncoding == GL_LINEAR) + { + GLenum effectiveFormat; + if (GetEffectiveInternalFormat(framebufferInternalFormatInfo, textureInternalFormatInfo, &effectiveFormat)) + { + sourceEffectiveFormat = &GetInternalFormatInfo(effectiveFormat); + } + else + { + return false; + } + } + else if (framebufferInternalFormatInfo.colorEncoding == GL_SRGB) + { + // SRGB buffers can only be copied to sized format destinations according to table 3.18 + if ((textureInternalFormatInfo.pixelBytes > 0) && + (framebufferInternalFormatInfo.redBits >= 1 && framebufferInternalFormatInfo.redBits <= 8) && + (framebufferInternalFormatInfo.greenBits >= 1 && framebufferInternalFormatInfo.greenBits <= 8) && + (framebufferInternalFormatInfo.blueBits >= 1 && framebufferInternalFormatInfo.blueBits <= 8) && + (framebufferInternalFormatInfo.alphaBits >= 1 && framebufferInternalFormatInfo.alphaBits <= 8)) + { + sourceEffectiveFormat = &GetInternalFormatInfo(GL_SRGB8_ALPHA8); + } + else + { + return false; + } + } + else + { + UNREACHABLE(); + return false; + } + } + + if (textureInternalFormatInfo.pixelBytes > 0) + { + // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is sized, + // component sizes of the source and destination formats must exactly match + if (textureInternalFormatInfo.redBits != sourceEffectiveFormat->redBits || + textureInternalFormatInfo.greenBits != sourceEffectiveFormat->greenBits || + textureInternalFormatInfo.blueBits != sourceEffectiveFormat->blueBits || + textureInternalFormatInfo.alphaBits != sourceEffectiveFormat->alphaBits) + { + return false; + } + } + + + return true; // A conversion function exists, and no rule in the specification has precluded conversion + // between these formats. } - if (border != 0) + return false; +} + +bool ValidateES3CopyTexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, + bool isSubImage, GLint xoffset, GLint yoffset, GLint zoffset, + GLint x, GLint y, GLsizei width, GLsizei height, GLint border) +{ + GLenum textureInternalFormat; + if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage, + xoffset, yoffset, zoffset, x, y, width, height, + border, &textureInternalFormat)) { - return gl::error(GL_INVALID_VALUE, false); + return false; } - if (!ValidMipLevel(context, target, level)) - { - return gl::error(GL_INVALID_VALUE, false); - } - - gl::Framebuffer *framebuffer = context->getReadFramebuffer(); + gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) { - return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION, false); + context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); + return false; } - if (context->getReadFramebufferHandle() != 0 && framebuffer->getSamples() != 0) + if (context->getState().getReadFramebuffer()->id() != 0 && framebuffer->getSamples() != 0) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } - gl::Renderbuffer *source = framebuffer->getReadColorbuffer(); + gl::FramebufferAttachment *source = framebuffer->getReadColorbuffer(); GLenum colorbufferInternalFormat = source->getInternalFormat(); - gl::Texture *texture = NULL; - GLenum textureInternalFormat = GL_NONE; - bool textureCompressed = false; - bool textureIsDepth = false; - GLint textureLevelWidth = 0; - GLint textureLevelHeight = 0; - GLint textureLevelDepth = 0; - switch (target) - { - case GL_TEXTURE_2D: - { - gl::Texture2D *texture2d = context->getTexture2D(); - if (texture2d) - { - textureInternalFormat = texture2d->getInternalFormat(level); - textureCompressed = texture2d->isCompressed(level); - textureIsDepth = texture2d->isDepth(level); - textureLevelWidth = texture2d->getWidth(level); - textureLevelHeight = texture2d->getHeight(level); - textureLevelDepth = 1; - texture = texture2d; - } - } - break; - - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - { - gl::TextureCubeMap *textureCube = context->getTextureCubeMap(); - if (textureCube) - { - textureInternalFormat = textureCube->getInternalFormat(target, level); - textureCompressed = textureCube->isCompressed(target, level); - textureIsDepth = false; - textureLevelWidth = textureCube->getWidth(target, level); - textureLevelHeight = textureCube->getHeight(target, level); - textureLevelDepth = 1; - texture = textureCube; - } - } - break; - - case GL_TEXTURE_2D_ARRAY: - { - gl::Texture2DArray *texture2dArray = context->getTexture2DArray(); - if (texture2dArray) - { - textureInternalFormat = texture2dArray->getInternalFormat(level); - textureCompressed = texture2dArray->isCompressed(level); - textureIsDepth = texture2dArray->isDepth(level); - textureLevelWidth = texture2dArray->getWidth(level); - textureLevelHeight = texture2dArray->getHeight(level); - textureLevelDepth = texture2dArray->getLayers(level); - texture = texture2dArray; - } - } - break; - - case GL_TEXTURE_3D: - { - gl::Texture3D *texture3d = context->getTexture3D(); - if (texture3d) - { - textureInternalFormat = texture3d->getInternalFormat(level); - textureCompressed = texture3d->isCompressed(level); - textureIsDepth = texture3d->isDepth(level); - textureLevelWidth = texture3d->getWidth(level); - textureLevelHeight = texture3d->getHeight(level); - textureLevelDepth = texture3d->getDepth(level); - texture = texture3d; - } - } - break; - - default: - return gl::error(GL_INVALID_ENUM, false); - } - - if (!texture) - { - return gl::error(GL_INVALID_OPERATION, false); - } - - if (texture->isImmutable() && !isSubImage) - { - return gl::error(GL_INVALID_OPERATION, false); - } - - if (textureIsDepth) - { - return gl::error(GL_INVALID_OPERATION, false); - } - - if (textureCompressed) - { - if ((width % 4 != 0 && width != textureLevelWidth) || - (height % 4 != 0 && height != textureLevelHeight)) - { - return gl::error(GL_INVALID_OPERATION, false); - } - } if (isSubImage) { - if (xoffset + width > textureLevelWidth || - yoffset + height > textureLevelHeight || - zoffset >= textureLevelDepth) + if (!IsValidES3CopyTexImageCombination(textureInternalFormat, colorbufferInternalFormat, + context->getState().getReadFramebuffer()->id())) { - return gl::error(GL_INVALID_VALUE, false); - } - - if (!gl::IsValidCopyTexImageCombination(textureInternalFormat, colorbufferInternalFormat, context->getReadFramebufferHandle(), - context->getClientVersion())) - { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } else { - if (!gl::IsValidCopyTexImageCombination(internalformat, colorbufferInternalFormat, context->getReadFramebufferHandle(), - context->getClientVersion())) + if (!gl::IsValidES3CopyTexImageCombination(internalformat, colorbufferInternalFormat, + context->getState().getReadFramebuffer()->id())) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } - - // If width or height is zero, it is a no-op. Return false without setting an error. return (width > 0 && height > 0); } -bool ValidateES3TexStorageParameters(gl::Context *context, GLenum target, GLsizei levels, GLenum internalformat, +bool ValidateES3TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) { if (width < 1 || height < 1 || depth < 1 || levels < 1) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } if (levels > gl::log2(std::max(std::max(width, height), depth)) + 1) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } + const gl::Caps &caps = context->getCaps(); + gl::Texture *texture = NULL; switch (target) { @@ -481,10 +934,11 @@ bool ValidateES3TexStorageParameters(gl::Context *context, GLenum target, GLsize { texture = context->getTexture2D(); - if (width > (context->getMaximum2DTextureDimension()) || - height > (context->getMaximum2DTextureDimension())) + if (static_cast(width) > caps.max2DTextureSize || + static_cast(height) > caps.max2DTextureSize) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } } break; @@ -495,12 +949,14 @@ bool ValidateES3TexStorageParameters(gl::Context *context, GLenum target, GLsize if (width != height) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } - if (width > (context->getMaximumCubeTextureDimension())) + if (static_cast(width) > caps.maxCubeMapTextureSize) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } } break; @@ -509,11 +965,12 @@ bool ValidateES3TexStorageParameters(gl::Context *context, GLenum target, GLsize { texture = context->getTexture3D(); - if (width > (context->getMaximum3DTextureDimension()) || - height > (context->getMaximum3DTextureDimension()) || - depth > (context->getMaximum3DTextureDimension())) + if (static_cast(width) > caps.max3DTextureSize || + static_cast(height) > caps.max3DTextureSize || + static_cast(depth) > caps.max3DTextureSize) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } } break; @@ -522,215 +979,136 @@ bool ValidateES3TexStorageParameters(gl::Context *context, GLenum target, GLsize { texture = context->getTexture2DArray(); - if (width > (context->getMaximum2DTextureDimension()) || - height > (context->getMaximum2DTextureDimension()) || - depth > (context->getMaximum2DArrayTextureLayers())) + if (static_cast(width) > caps.max2DTextureSize || + static_cast(height) > caps.max2DTextureSize || + static_cast(depth) > caps.maxArrayTextureLayers) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } } break; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } if (!texture || texture->id() == 0) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (texture->isImmutable()) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } - if (!gl::IsValidInternalFormat(internalformat, context)) + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat); + if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions())) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } - if (!gl::IsSizedInternalFormat(internalformat, context->getClientVersion())) + if (formatInfo.pixelBytes == 0) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } return true; } -bool ValidateES3FramebufferTextureParameters(gl::Context *context, GLenum target, GLenum attachment, - GLenum textarget, GLuint texture, GLint level, GLint layer, - bool layerCall) +bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum attachment, + GLuint texture, GLint level, GLint layer) { - if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER) + if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } - if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15) + if (layer < 0) { - const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0); - if (colorAttachment >= context->getMaximumRenderTargets()) - { - return gl::error(GL_INVALID_VALUE, false); - } - } - else - { - switch (attachment) - { - case GL_DEPTH_ATTACHMENT: - case GL_STENCIL_ATTACHMENT: - case GL_DEPTH_STENCIL_ATTACHMENT: - break; - default: - return gl::error(GL_INVALID_ENUM, false); - } + context->recordError(Error(GL_INVALID_VALUE)); + return false; } + if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level)) + { + return false; + } + + const gl::Caps &caps = context->getCaps(); if (texture != 0) { gl::Texture *tex = context->getTexture(texture); + ASSERT(tex); - if (tex == NULL) + switch (tex->getTarget()) { - return gl::error(GL_INVALID_OPERATION, false); - } - - if (level < 0) - { - return gl::error(GL_INVALID_VALUE, false); - } - - if (layer < 0) - { - return gl::error(GL_INVALID_VALUE, false); - } - - if (!layerCall) - { - switch (textarget) + case GL_TEXTURE_2D_ARRAY: { - case GL_TEXTURE_2D: + if (level > gl::log2(caps.max2DTextureSize)) { - if (level > gl::log2(context->getMaximum2DTextureDimension())) - { - return gl::error(GL_INVALID_VALUE, false); - } - if (tex->getTarget() != GL_TEXTURE_2D) - { - return gl::error(GL_INVALID_OPERATION, false); - } - gl::Texture2D *tex2d = static_cast(tex); - if (tex2d->isCompressed(level)) - { - return gl::error(GL_INVALID_OPERATION, false); - } - break; + context->recordError(Error(GL_INVALID_VALUE)); + return false; } - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + if (static_cast(layer) >= caps.maxArrayTextureLayers) { - if (level > gl::log2(context->getMaximumCubeTextureDimension())) - { - return gl::error(GL_INVALID_VALUE, false); - } - if (tex->getTarget() != GL_TEXTURE_CUBE_MAP) - { - return gl::error(GL_INVALID_OPERATION, false); - } - gl::TextureCubeMap *texcube = static_cast(tex); - if (texcube->isCompressed(textarget, level)) - { - return gl::error(GL_INVALID_OPERATION, false); - } - break; + context->recordError(Error(GL_INVALID_VALUE)); + return false; } - default: - return gl::error(GL_INVALID_ENUM, false); + gl::Texture2DArray *texArray = static_cast(tex); + if (texArray->isCompressed(level)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } } - } - else - { - switch (tex->getTarget()) + break; + + case GL_TEXTURE_3D: { - case GL_TEXTURE_2D_ARRAY: + if (level > gl::log2(caps.max3DTextureSize)) { - if (level > gl::log2(context->getMaximum2DTextureDimension())) - { - return gl::error(GL_INVALID_VALUE, false); - } - - if (layer >= context->getMaximum2DArrayTextureLayers()) - { - return gl::error(GL_INVALID_VALUE, false); - } - - gl::Texture2DArray *texArray = static_cast(tex); - if (texArray->isCompressed(level)) - { - return gl::error(GL_INVALID_OPERATION, false); - } - - break; + context->recordError(Error(GL_INVALID_VALUE)); + return false; } - case GL_TEXTURE_3D: + if (static_cast(layer) >= caps.max3DTextureSize) { - if (level > gl::log2(context->getMaximum3DTextureDimension())) - { - return gl::error(GL_INVALID_VALUE, false); - } - - if (layer >= context->getMaximum3DTextureDimension()) - { - return gl::error(GL_INVALID_VALUE, false); - } - - gl::Texture3D *tex3d = static_cast(tex); - if (tex3d->isCompressed(level)) - { - return gl::error(GL_INVALID_OPERATION, false); - } - - break; + context->recordError(Error(GL_INVALID_VALUE)); + return false; } - default: - return gl::error(GL_INVALID_OPERATION, false); + gl::Texture3D *tex3d = static_cast(tex); + if (tex3d->isCompressed(level)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } } + break; + + default: + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } - gl::Framebuffer *framebuffer = NULL; - GLuint framebufferHandle = 0; - if (target == GL_READ_FRAMEBUFFER) - { - framebuffer = context->getReadFramebuffer(); - framebufferHandle = context->getReadFramebufferHandle(); - } - else - { - framebuffer = context->getDrawFramebuffer(); - framebufferHandle = context->getDrawFramebufferHandle(); - } - - if (framebufferHandle == 0 || !framebuffer) - { - return gl::error(GL_INVALID_OPERATION, false); - } - return true; } -bool ValidES3ReadFormatType(gl::Context *context, GLenum internalFormat, GLenum format, GLenum type) +bool ValidES3ReadFormatType(Context *context, GLenum internalFormat, GLenum format, GLenum type) { + const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat); + switch (format) { case GL_RGBA: @@ -745,7 +1123,7 @@ bool ValidES3ReadFormatType(gl::Context *context, GLenum internalFormat, GLenum } break; case GL_FLOAT: - if (gl::GetComponentType(internalFormat, 3) != GL_FLOAT) + if (internalFormatInfo.componentType != GL_FLOAT) { return false; } @@ -758,13 +1136,13 @@ bool ValidES3ReadFormatType(gl::Context *context, GLenum internalFormat, GLenum switch (type) { case GL_INT: - if (gl::GetComponentType(internalFormat, 3) != GL_INT) + if (internalFormatInfo.componentType != GL_INT) { return false; } break; case GL_UNSIGNED_INT: - if (gl::GetComponentType(internalFormat, 3) != GL_UNSIGNED_INT) + if (internalFormatInfo.componentType != GL_UNSIGNED_INT) { return false; } @@ -786,7 +1164,7 @@ bool ValidES3ReadFormatType(gl::Context *context, GLenum internalFormat, GLenum break; case GL_RG_EXT: case GL_RED_EXT: - if (!context->supportsRGTextures()) + if (!context->getExtensions().textureRG) { return false; } @@ -804,7 +1182,7 @@ bool ValidES3ReadFormatType(gl::Context *context, GLenum internalFormat, GLenum return true; } -bool ValidateInvalidateFramebufferParameters(gl::Context *context, GLenum target, GLsizei numAttachments, +bool ValidateInvalidateFramebufferParameters(Context *context, GLenum target, GLsizei numAttachments, const GLenum* attachments) { bool defaultFramebuffer = false; @@ -813,13 +1191,14 @@ bool ValidateInvalidateFramebufferParameters(gl::Context *context, GLenum target { case GL_DRAW_FRAMEBUFFER: case GL_FRAMEBUFFER: - defaultFramebuffer = context->getDrawFramebufferHandle() == 0; + defaultFramebuffer = context->getState().getDrawFramebuffer()->id() == 0; break; case GL_READ_FRAMEBUFFER: - defaultFramebuffer = context->getReadFramebufferHandle() == 0; + defaultFramebuffer = context->getState().getReadFramebuffer()->id() == 0; break; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } for (int i = 0; i < numAttachments; ++i) @@ -828,12 +1207,14 @@ bool ValidateInvalidateFramebufferParameters(gl::Context *context, GLenum target { if (defaultFramebuffer) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } - if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getMaximumRenderTargets()) + if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } else @@ -845,7 +1226,8 @@ bool ValidateInvalidateFramebufferParameters(gl::Context *context, GLenum target case GL_DEPTH_STENCIL_ATTACHMENT: if (defaultFramebuffer) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; case GL_COLOR: @@ -853,11 +1235,13 @@ bool ValidateInvalidateFramebufferParameters(gl::Context *context, GLenum target case GL_STENCIL: if (!defaultFramebuffer) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } } } @@ -865,4 +1249,33 @@ bool ValidateInvalidateFramebufferParameters(gl::Context *context, GLenum target return true; } +bool ValidateClearBuffer(Context *context) +{ + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + const gl::Framebuffer *fbo = context->getState().getDrawFramebuffer(); + if (!fbo || fbo->completeness() != GL_FRAMEBUFFER_COMPLETE) + { + context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); + return false; + } + + return true; +} + +bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params) +{ + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + return ValidateGetUniformBase(context, program, location); +} + } diff --git a/gfx/angle/src/libGLESv2/validationES3.h b/gfx/angle/src/libGLESv2/validationES3.h index 93917c26bae2..cafacca601bf 100644 --- a/gfx/angle/src/libGLESv2/validationES3.h +++ b/gfx/angle/src/libGLESv2/validationES3.h @@ -9,31 +9,36 @@ #ifndef LIBGLESV2_VALIDATION_ES3_H #define LIBGLESV2_VALIDATION_ES3_H +#include + namespace gl { class Context; -bool ValidateES3TexImageParameters(gl::Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage, +bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -bool ValidateES3CopyTexImageParameters(gl::Context *context, GLenum target, GLint level, GLenum internalformat, +bool ValidateES3CopyTexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isSubImage, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); -bool ValidateES3TexStorageParameters(gl::Context *context, GLenum target, GLsizei levels, GLenum internalformat, +bool ValidateES3TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); -bool ValidateES3FramebufferTextureParameters(gl::Context *context, GLenum target, GLenum attachment, - GLenum textarget, GLuint texture, GLint level, GLint layer, - bool layerCall); +bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum attachment, + GLuint texture, GLint level, GLint layer); -bool ValidES3ReadFormatType(gl::Context *context, GLenum internalFormat, GLenum format, GLenum type); +bool ValidES3ReadFormatType(Context *context, GLenum internalFormat, GLenum format, GLenum type); -bool ValidateInvalidateFramebufferParameters(gl::Context *context, GLenum target, GLsizei numAttachments, +bool ValidateInvalidateFramebufferParameters(Context *context, GLenum target, GLsizei numAttachments, const GLenum* attachments); +bool ValidateClearBuffer(Context *context); + +bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params); + } #endif // LIBGLESV2_VALIDATION_ES3_H diff --git a/gfx/angle/src/third_party/compiler/ArrayBoundsClamper.h b/gfx/angle/src/third_party/compiler/ArrayBoundsClamper.h index 7d06a6c70d9b..30bb7e3b94d8 100644 --- a/gfx/angle/src/third_party/compiler/ArrayBoundsClamper.h +++ b/gfx/angle/src/third_party/compiler/ArrayBoundsClamper.h @@ -27,7 +27,7 @@ #define THIRD_PARTY_COMPILER_ARRAY_BOUNDS_CLAMPER_H_ #include "compiler/translator/InfoSink.h" -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" class ArrayBoundsClamper { public: From d4a0b9e59cccee4092c560a3a6b9f348cc8afe95 Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Sun, 31 Aug 2014 20:42:28 -0700 Subject: [PATCH 024/114] Bug 1063031: Remove mozilla::pkix::test::NSSTest, r=keeler --HG-- rename : security/pkix/test/gtest/nssgtest.cpp => security/pkix/test/gtest/pkixgtest.cpp extra : rebase_source : 205faf2054134b3a7aecd55d53f73d19f2f86103 --- security/pkix/test/gtest/moz.build | 2 +- security/pkix/test/gtest/nssgtest.h | 46 ------------------- security/pkix/test/gtest/pkixbuild_tests.cpp | 14 ++++-- .../test/gtest/pkixcert_extension_tests.cpp | 10 +--- .../test/gtest/pkixder_pki_types_tests.cpp | 7 ++- .../gtest/{nssgtest.cpp => pkixgtest.cpp} | 18 ++------ security/pkix/test/gtest/pkixgtest.h | 8 ++++ ...kixocsp_CreateEncodedOCSPRequest_tests.cpp | 4 +- .../pkixocsp_VerifyEncodedOCSPResponse.cpp | 15 ++---- security/pkix/test/lib/pkixtestnss.cpp | 29 +++++++++++- 10 files changed, 60 insertions(+), 93 deletions(-) delete mode 100644 security/pkix/test/gtest/nssgtest.h rename security/pkix/test/gtest/{nssgtest.cpp => pkixgtest.cpp} (86%) diff --git a/security/pkix/test/gtest/moz.build b/security/pkix/test/gtest/moz.build index 020fa0b4641a..4ebdd000fa9c 100644 --- a/security/pkix/test/gtest/moz.build +++ b/security/pkix/test/gtest/moz.build @@ -5,7 +5,6 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. SOURCES += [ - 'nssgtest.cpp', 'pkixbuild_tests.cpp', 'pkixcert_extension_tests.cpp', 'pkixcheck_CheckKeyUsage_tests.cpp', @@ -16,6 +15,7 @@ SOURCES += [ 'pkixder_input_tests.cpp', 'pkixder_pki_types_tests.cpp', 'pkixder_universal_types_tests.cpp', + 'pkixgtest.cpp', 'pkixocsp_CreateEncodedOCSPRequest_tests.cpp', 'pkixocsp_VerifyEncodedOCSPResponse.cpp', ] diff --git a/security/pkix/test/gtest/nssgtest.h b/security/pkix/test/gtest/nssgtest.h deleted file mode 100644 index 4c4a8ef62fa2..000000000000 --- a/security/pkix/test/gtest/nssgtest.h +++ /dev/null @@ -1,46 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This code is made available to you under your choice of the following sets - * of licensing terms: - */ -/* 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/. - */ -/* Copyright 2013 Mozilla Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef mozilla_pkix__nssgtest_h -#define mozilla_pkix__nssgtest_h - -#include "gtest/gtest.h" -#include "pkix/pkixtypes.h" -#include "pkixtestutil.h" - -namespace mozilla { namespace pkix { namespace test { - -extern const std::time_t now; -extern const std::time_t oneDayBeforeNow; -extern const std::time_t oneDayAfterNow; - -class NSSTest : public ::testing::Test -{ -public: - static void SetUpTestCase(); -}; - -} } } // namespace mozilla::pkix::test - -#endif // mozilla_pkix__nssgtest_h diff --git a/security/pkix/test/gtest/pkixbuild_tests.cpp b/security/pkix/test/gtest/pkixbuild_tests.cpp index 66ee157dceff..cb468d2ab7de 100644 --- a/security/pkix/test/gtest/pkixbuild_tests.cpp +++ b/security/pkix/test/gtest/pkixbuild_tests.cpp @@ -23,7 +23,7 @@ */ #include "cert.h" -#include "nssgtest.h" +#include "nss.h" #include "pkix/pkix.h" #include "pkix/pkixnss.h" #include "pkixgtest.h" @@ -201,20 +201,24 @@ public: } }; -class pkixbuild : public NSSTest +class pkixbuild : public ::testing::Test { public: static void SetUpTestCase() { - NSSTest::SetUpTestCase(); - // Initialize the tail of the cert chains we'll be using once, to make the - // tests run faster (generating the keys is slow). + // XXX(Bug 1070444): We have to initialize NSS explicitly for these tests, + // unlike other tests, because we're using NSS directly. + if (NSS_NoDB_Init(nullptr) != SECSuccess) { + abort(); + } + if (!trustDomain.SetUpCertChainTail()) { abort(); } } protected: + static TestTrustDomain trustDomain; }; diff --git a/security/pkix/test/gtest/pkixcert_extension_tests.cpp b/security/pkix/test/gtest/pkixcert_extension_tests.cpp index c1121472d89c..284d9b6b0594 100644 --- a/security/pkix/test/gtest/pkixcert_extension_tests.cpp +++ b/security/pkix/test/gtest/pkixcert_extension_tests.cpp @@ -22,8 +22,8 @@ * limitations under the License. */ -#include "nssgtest.h" #include "pkix/pkix.h" +#include "pkixgtest.h" #include "pkixtestutil.h" using namespace mozilla::pkix; @@ -110,14 +110,8 @@ private: } }; -class pkixcert_extension: public NSSTest +class pkixcert_extension : public ::testing::Test { -public: - static void SetUpTestCase() - { - NSSTest::SetUpTestCase(); - } - protected: static TrustEverythingTrustDomain trustDomain; }; diff --git a/security/pkix/test/gtest/pkixder_pki_types_tests.cpp b/security/pkix/test/gtest/pkixder_pki_types_tests.cpp index 22a1e3bd0267..bff6df613585 100644 --- a/security/pkix/test/gtest/pkixder_pki_types_tests.cpp +++ b/security/pkix/test/gtest/pkixder_pki_types_tests.cpp @@ -25,13 +25,12 @@ #include #include -#include "nssgtest.h" +#include "gtest/gtest.h" #include "pkix/pkixtypes.h" #include "pkixder.h" using namespace mozilla::pkix; using namespace mozilla::pkix::der; -using namespace mozilla::pkix::test; namespace { @@ -200,7 +199,7 @@ struct AlgorithmIdentifierTestInfo }; class pkixder_DigestAlgorithmIdentifier - : public NSSTest + : public ::testing::Test , public ::testing::WithParamInterface< AlgorithmIdentifierTestInfo> { @@ -364,7 +363,7 @@ static const AlgorithmIdentifierTestInfo }; class pkixder_SignatureAlgorithmIdentifier - : public NSSTest + : public ::testing::Test , public ::testing::WithParamInterface< AlgorithmIdentifierTestInfo> { diff --git a/security/pkix/test/gtest/nssgtest.cpp b/security/pkix/test/gtest/pkixgtest.cpp similarity index 86% rename from security/pkix/test/gtest/nssgtest.cpp rename to security/pkix/test/gtest/pkixgtest.cpp index 85bc796eef28..0045880854bf 100644 --- a/security/pkix/test/gtest/nssgtest.cpp +++ b/security/pkix/test/gtest/pkixgtest.cpp @@ -22,23 +22,15 @@ * limitations under the License. */ -#include "nssgtest.h" -#include "nss.h" -#include "pkixtestutil.h" +#include "pkixgtest.h" -using namespace std; -using namespace testing; +#include + +#include "pkix/nullptr.h" +#include "pkix/Time.h" namespace mozilla { namespace pkix { namespace test { -/*static*/ void -NSSTest::SetUpTestCase() -{ - if (NSS_NoDB_Init(nullptr) != SECSuccess) { - abort(); - } -} - // This assumes that time/time_t are POSIX-compliant in that time() returns // the number of seconds since the Unix epoch. const std::time_t now(time(nullptr)); diff --git a/security/pkix/test/gtest/pkixgtest.h b/security/pkix/test/gtest/pkixgtest.h index 862eb4056bb2..5f7b2657cfd8 100644 --- a/security/pkix/test/gtest/pkixgtest.h +++ b/security/pkix/test/gtest/pkixgtest.h @@ -45,4 +45,12 @@ PrintTo(const Result& result, ::std::ostream* os) } } // namespace mozilla::pkix +namespace mozilla { namespace pkix { namespace test { + +extern const std::time_t now; +extern const std::time_t oneDayBeforeNow; +extern const std::time_t oneDayAfterNow; + +} } } // namespace mozilla::pkix::test + #endif // mozilla_pkix__pkixgtest_h diff --git a/security/pkix/test/gtest/pkixocsp_CreateEncodedOCSPRequest_tests.cpp b/security/pkix/test/gtest/pkixocsp_CreateEncodedOCSPRequest_tests.cpp index 3317beec0bdb..4a159ebf3799 100644 --- a/security/pkix/test/gtest/pkixocsp_CreateEncodedOCSPRequest_tests.cpp +++ b/security/pkix/test/gtest/pkixocsp_CreateEncodedOCSPRequest_tests.cpp @@ -22,7 +22,7 @@ * limitations under the License. */ -#include "nssgtest.h" +#include "gtest/gtest.h" #include "pkix/pkix.h" #include "pkixder.h" #include "pkixtestutil.h" @@ -79,7 +79,7 @@ private: } }; -class pkixocsp_CreateEncodedOCSPRequest : public NSSTest +class pkixocsp_CreateEncodedOCSPRequest : public ::testing::Test { protected: void MakeIssuerCertIDComponents(const char* issuerASCII, diff --git a/security/pkix/test/gtest/pkixocsp_VerifyEncodedOCSPResponse.cpp b/security/pkix/test/gtest/pkixocsp_VerifyEncodedOCSPResponse.cpp index d23c1ef6d168..10be77a32688 100644 --- a/security/pkix/test/gtest/pkixocsp_VerifyEncodedOCSPResponse.cpp +++ b/security/pkix/test/gtest/pkixocsp_VerifyEncodedOCSPResponse.cpp @@ -22,7 +22,6 @@ * limitations under the License. */ -#include "nssgtest.h" #include "pkix/pkix.h" #include "pkixgtest.h" #include "pkixtestutil.h" @@ -97,27 +96,19 @@ char const* const rootName = "Test CA 1"; void deleteCertID(CertID* certID) { delete certID; } } // unnamed namespace -class pkixocsp_VerifyEncodedResponse : public NSSTest +class pkixocsp_VerifyEncodedResponse : public ::testing::Test { public: - static bool SetUpTestCaseInner() - { - rootKeyPair = GenerateKeyPair(); - return rootKeyPair.get() != nullptr; - } - static void SetUpTestCase() { - NSSTest::SetUpTestCase(); - if (!SetUpTestCaseInner()) { + rootKeyPair = GenerateKeyPair(); + if (!rootKeyPair) { abort(); } } void SetUp() { - NSSTest::SetUp(); - rootNameDER = CNToDERName(rootName); if (rootNameDER == ENCODING_FAILED) { abort(); diff --git a/security/pkix/test/lib/pkixtestnss.cpp b/security/pkix/test/lib/pkixtestnss.cpp index 84235089d395..c474bbb5eb61 100644 --- a/security/pkix/test/lib/pkixtestnss.cpp +++ b/security/pkix/test/lib/pkixtestnss.cpp @@ -28,6 +28,7 @@ #include "cryptohi.h" #include "keyhi.h" +#include "nss.h" #include "pk11pub.h" #include "pkix/pkixnss.h" #include "secerr.h" @@ -41,6 +42,15 @@ typedef ScopedPtr typedef ScopedPtr ScopedSECKEYPrivateKey; +Result +InitNSSIfNeeded() +{ + if (NSS_NoDB_Init(nullptr) != SECSuccess) { + return MapPRErrorCodeToResult(PR_GetError()); + } + return Success; +} + class NSSTestKeyPair : public TestKeyPair { public: @@ -109,6 +119,10 @@ TestKeyPair* CreateTestKeyPair(const ByteString& spki, TestKeyPair* GenerateKeyPair() { + if (InitNSSIfNeeded() != Success) { + return nullptr; + } + ScopedPtr slot(PK11_GetInternalSlot()); if (!slot) { return nullptr; @@ -167,8 +181,7 @@ GenerateKeyPair() ByteString SHA1(const ByteString& toHash) { - if (toHash.length() > - static_cast(std::numeric_limits::max())) { + if (InitNSSIfNeeded() != Success) { return ENCODING_FAILED; } @@ -184,6 +197,10 @@ SHA1(const ByteString& toHash) Result TestCheckPublicKey(Input subjectPublicKeyInfo) { + Result rv = InitNSSIfNeeded(); + if (rv != Success) { + return rv; + } return CheckPublicKey(subjectPublicKeyInfo); } @@ -191,12 +208,20 @@ Result TestVerifySignedData(const SignedDataWithSignature& signedData, Input subjectPublicKeyInfo) { + Result rv = InitNSSIfNeeded(); + if (rv != Success) { + return rv; + } return VerifySignedData(signedData, subjectPublicKeyInfo, nullptr); } Result TestDigestBuf(Input item, /*out*/ uint8_t* digestBuf, size_t digestBufLen) { + Result rv = InitNSSIfNeeded(); + if (rv != Success) { + return rv; + } return DigestBuf(item, digestBuf, digestBufLen); } From ddb8aedc1776b62b907117f26030ea49166d107c Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Mon, 8 Sep 2014 20:41:53 -0700 Subject: [PATCH 025/114] Bug 1065173: Move more NSS dependencies to pkixtestnss.cpp, r=keeler --HG-- extra : rebase_source : 205fa72506e175c0fe418c5428675e754a86c820 --- security/pkix/test/lib/pkixtestnss.cpp | 9 +++++++++ security/pkix/test/lib/pkixtestutil.cpp | 1 - security/pkix/test/lib/pkixtestutil.h | 18 +++--------------- 3 files changed, 12 insertions(+), 16 deletions(-) diff --git a/security/pkix/test/lib/pkixtestnss.cpp b/security/pkix/test/lib/pkixtestnss.cpp index c474bbb5eb61..41452a1c0256 100644 --- a/security/pkix/test/lib/pkixtestnss.cpp +++ b/security/pkix/test/lib/pkixtestnss.cpp @@ -32,6 +32,7 @@ #include "pk11pub.h" #include "pkix/pkixnss.h" #include "secerr.h" +#include "secitem.h" namespace mozilla { namespace pkix { namespace test { @@ -42,6 +43,14 @@ typedef ScopedPtr typedef ScopedPtr ScopedSECKEYPrivateKey; +inline void +SECITEM_FreeItem_true(SECItem* item) +{ + SECITEM_FreeItem(item, true); +} + +typedef mozilla::pkix::ScopedPtr ScopedSECItem; + Result InitNSSIfNeeded() { diff --git a/security/pkix/test/lib/pkixtestutil.cpp b/security/pkix/test/lib/pkixtestutil.cpp index d79d0e54a85f..7066e213e5ad 100644 --- a/security/pkix/test/lib/pkixtestutil.cpp +++ b/security/pkix/test/lib/pkixtestutil.cpp @@ -32,7 +32,6 @@ #include "pkixder.h" #include "pkixutil.h" -#include "prprf.h" using namespace std; diff --git a/security/pkix/test/lib/pkixtestutil.h b/security/pkix/test/lib/pkixtestutil.h index dbe67072d8df..57cf057ac9cd 100644 --- a/security/pkix/test/lib/pkixtestutil.h +++ b/security/pkix/test/lib/pkixtestutil.h @@ -32,7 +32,6 @@ #include "pkix/enumclass.h" #include "pkix/pkixtypes.h" #include "pkix/ScopedPtr.h" -#include "secitem.h" namespace mozilla { namespace pkix { namespace test { @@ -64,18 +63,6 @@ public: } }; -namespace { - -inline void -SECITEM_FreeItem_true(SECItem* item) -{ - SECITEM_FreeItem(item, true); -} - -} // unnamed namespace - -typedef mozilla::pkix::ScopedPtr ScopedSECItem; - // python DottedOIDToCode.py --tlv id-kp-OCSPSigning 1.3.6.1.5.5.7.3.9 static const uint8_t tlv_id_kp_OCSPSigning[] = { 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x09 @@ -156,8 +143,9 @@ enum Version { v1 = 0, v2 = 1, v3 = 2 }; // serialNumber is assumed to be the DER encoding of an INTEGER. // // If extensions is null, then no extensions will be encoded. Otherwise, -// extensions must point to a null-terminated array of SECItem*. If the first -// item of the array is null then an empty Extensions sequence will be encoded. +// extensions must point to an array of ByteStrings, terminated with an empty +// ByteString. (If the first item of the array is empty then an empty +// Extensions sequence will be encoded.) // // If issuerPrivateKey is null, then the certificate will be self-signed. // Parameter order is based on the order of the attributes of the certificate From c5500b85df26d1c35fbb2dd6af1f5d71d52eb513 Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Wed, 10 Sep 2014 00:17:24 -0700 Subject: [PATCH 026/114] Bug 1065264: Use MOZILLA_PKIX_MAP_LIST to define mozilla::pkix::Result, r=keeler --HG-- extra : rebase_source : a91f7ab118f802fed6441edf00a245fe90c8e506 --- security/pkix/include/pkix/Result.h | 247 +++++++++++----------------- security/pkix/lib/pkixnss.cpp | 8 +- security/pkix/lib/pkixresult.cpp | 4 +- 3 files changed, 106 insertions(+), 153 deletions(-) diff --git a/security/pkix/include/pkix/Result.h b/security/pkix/include/pkix/Result.h index d0fbb661af04..e82e6428d341 100644 --- a/security/pkix/include/pkix/Result.h +++ b/security/pkix/include/pkix/Result.h @@ -33,161 +33,114 @@ namespace mozilla { namespace pkix { static const unsigned int FATAL_ERROR_FLAG = 0x800; -MOZILLA_PKIX_ENUM_CLASS Result -{ - Success = 0, - - ERROR_BAD_DER = 1, - ERROR_CA_CERT_INVALID = 2, - ERROR_BAD_SIGNATURE = 3, - ERROR_CERT_BAD_ACCESS_LOCATION = 4, - ERROR_CERT_NOT_IN_NAME_SPACE = 5, - ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED = 6, - ERROR_CONNECT_REFUSED = 7, - ERROR_EXPIRED_CERTIFICATE = 8, - ERROR_EXTENSION_VALUE_INVALID = 9, - ERROR_INADEQUATE_CERT_TYPE = 10, - ERROR_INADEQUATE_KEY_USAGE = 11, - ERROR_INVALID_ALGORITHM = 12, - ERROR_INVALID_TIME = 13, - ERROR_KEY_PINNING_FAILURE = 14, - ERROR_PATH_LEN_CONSTRAINT_INVALID = 15, - ERROR_POLICY_VALIDATION_FAILED = 16, - ERROR_REVOKED_CERTIFICATE = 17, - ERROR_UNKNOWN_CRITICAL_EXTENSION = 18, - ERROR_UNKNOWN_ISSUER = 19, - ERROR_UNTRUSTED_CERT = 20, - ERROR_UNTRUSTED_ISSUER = 21, - - ERROR_OCSP_BAD_SIGNATURE = 22, - ERROR_OCSP_INVALID_SIGNING_CERT = 23, - ERROR_OCSP_MALFORMED_REQUEST = 24, - ERROR_OCSP_MALFORMED_RESPONSE = 25, - ERROR_OCSP_OLD_RESPONSE = 26, - ERROR_OCSP_REQUEST_NEEDS_SIG = 27, - ERROR_OCSP_RESPONDER_CERT_INVALID = 28, - ERROR_OCSP_SERVER_ERROR = 29, - ERROR_OCSP_TRY_SERVER_LATER = 30, - ERROR_OCSP_UNAUTHORIZED_REQUEST = 31, - ERROR_OCSP_UNKNOWN_RESPONSE_STATUS = 32, - ERROR_OCSP_UNKNOWN_CERT = 33, - ERROR_OCSP_FUTURE_RESPONSE = 34, - - ERROR_UNKNOWN_ERROR = 35, - ERROR_INVALID_KEY = 36, - ERROR_UNSUPPORTED_KEYALG = 37, - ERROR_EXPIRED_ISSUER_CERTIFICATE = 38, - ERROR_CA_CERT_USED_AS_END_ENTITY = 39, - ERROR_INADEQUATE_KEY_SIZE = 40, - - // Keep this in sync with MAP_LIST below - - FATAL_ERROR_INVALID_ARGS = FATAL_ERROR_FLAG | 1, - FATAL_ERROR_INVALID_STATE = FATAL_ERROR_FLAG | 2, - FATAL_ERROR_LIBRARY_FAILURE = FATAL_ERROR_FLAG | 3, - FATAL_ERROR_NO_MEMORY = FATAL_ERROR_FLAG | 4, - - // Keep this in sync with MAP_LIST below -}; - // The first argument to MOZILLA_PKIX_MAP() is used for building the mapping // from error code to error name in MapResultToName. // -// The second argument to MOZILLA_PKIX_MAP() is used, along with the first +// The second argument is for defining the value for the enum literal in the +// Result enum class. +// +// The third argument to MOZILLA_PKIX_MAP() is used, along with the first // argument, for maintaining the mapping of mozilla::pkix error codes to // NSS/NSPR error codes in pkixnss.cpp. #define MOZILLA_PKIX_MAP_LIST \ - MOZILLA_PKIX_MAP(Result::Success, 0) \ - MOZILLA_PKIX_MAP(Result::ERROR_BAD_DER, \ - SEC_ERROR_BAD_DER) \ - MOZILLA_PKIX_MAP(Result::ERROR_CA_CERT_INVALID, \ - SEC_ERROR_CA_CERT_INVALID) \ - MOZILLA_PKIX_MAP(Result::ERROR_BAD_SIGNATURE, \ - SEC_ERROR_BAD_SIGNATURE) \ - MOZILLA_PKIX_MAP(Result::ERROR_CERT_BAD_ACCESS_LOCATION, \ - SEC_ERROR_CERT_BAD_ACCESS_LOCATION) \ - MOZILLA_PKIX_MAP(Result::ERROR_CERT_NOT_IN_NAME_SPACE, \ - SEC_ERROR_CERT_NOT_IN_NAME_SPACE) \ - MOZILLA_PKIX_MAP(Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED, \ - SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED) \ - MOZILLA_PKIX_MAP(Result::ERROR_CONNECT_REFUSED, \ - PR_CONNECT_REFUSED_ERROR) \ - MOZILLA_PKIX_MAP(Result::ERROR_EXPIRED_CERTIFICATE, \ - SEC_ERROR_EXPIRED_CERTIFICATE) \ - MOZILLA_PKIX_MAP(Result::ERROR_EXTENSION_VALUE_INVALID, \ - SEC_ERROR_EXTENSION_VALUE_INVALID) \ - MOZILLA_PKIX_MAP(Result::ERROR_INADEQUATE_CERT_TYPE, \ - SEC_ERROR_INADEQUATE_CERT_TYPE) \ - MOZILLA_PKIX_MAP(Result::ERROR_INADEQUATE_KEY_USAGE, \ - SEC_ERROR_INADEQUATE_KEY_USAGE) \ - MOZILLA_PKIX_MAP(Result::ERROR_INVALID_ALGORITHM, \ - SEC_ERROR_INVALID_ALGORITHM) \ - MOZILLA_PKIX_MAP(Result::ERROR_INVALID_TIME, \ - SEC_ERROR_INVALID_TIME) \ - MOZILLA_PKIX_MAP(Result::ERROR_KEY_PINNING_FAILURE, \ - MOZILLA_PKIX_ERROR_KEY_PINNING_FAILURE) \ - MOZILLA_PKIX_MAP(Result::ERROR_PATH_LEN_CONSTRAINT_INVALID, \ - SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID) \ - MOZILLA_PKIX_MAP(Result::ERROR_POLICY_VALIDATION_FAILED, \ - SEC_ERROR_POLICY_VALIDATION_FAILED) \ - MOZILLA_PKIX_MAP(Result::ERROR_REVOKED_CERTIFICATE, \ - SEC_ERROR_REVOKED_CERTIFICATE) \ - MOZILLA_PKIX_MAP(Result::ERROR_UNKNOWN_CRITICAL_EXTENSION, \ - SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION) \ - MOZILLA_PKIX_MAP(Result::ERROR_UNKNOWN_ERROR, \ - PR_UNKNOWN_ERROR) \ - MOZILLA_PKIX_MAP(Result::ERROR_UNKNOWN_ISSUER, \ - SEC_ERROR_UNKNOWN_ISSUER) \ - MOZILLA_PKIX_MAP(Result::ERROR_UNTRUSTED_CERT, \ - SEC_ERROR_UNTRUSTED_CERT) \ - MOZILLA_PKIX_MAP(Result::ERROR_UNTRUSTED_ISSUER, \ - SEC_ERROR_UNTRUSTED_ISSUER) \ - MOZILLA_PKIX_MAP(Result::ERROR_OCSP_BAD_SIGNATURE, \ - SEC_ERROR_OCSP_BAD_SIGNATURE) \ - MOZILLA_PKIX_MAP(Result::ERROR_OCSP_INVALID_SIGNING_CERT, \ - SEC_ERROR_OCSP_INVALID_SIGNING_CERT) \ - MOZILLA_PKIX_MAP(Result::ERROR_OCSP_MALFORMED_REQUEST, \ - SEC_ERROR_OCSP_MALFORMED_REQUEST) \ - MOZILLA_PKIX_MAP(Result::ERROR_OCSP_MALFORMED_RESPONSE, \ - SEC_ERROR_OCSP_MALFORMED_RESPONSE) \ - MOZILLA_PKIX_MAP(Result::ERROR_OCSP_OLD_RESPONSE, \ - SEC_ERROR_OCSP_OLD_RESPONSE) \ - MOZILLA_PKIX_MAP(Result::ERROR_OCSP_REQUEST_NEEDS_SIG, \ - SEC_ERROR_OCSP_REQUEST_NEEDS_SIG) \ - MOZILLA_PKIX_MAP(Result::ERROR_OCSP_RESPONDER_CERT_INVALID, \ - SEC_ERROR_OCSP_RESPONDER_CERT_INVALID) \ - MOZILLA_PKIX_MAP(Result::ERROR_OCSP_SERVER_ERROR, \ - SEC_ERROR_OCSP_SERVER_ERROR) \ - MOZILLA_PKIX_MAP(Result::ERROR_OCSP_TRY_SERVER_LATER, \ - SEC_ERROR_OCSP_TRY_SERVER_LATER) \ - MOZILLA_PKIX_MAP(Result::ERROR_OCSP_UNAUTHORIZED_REQUEST, \ - SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST) \ - MOZILLA_PKIX_MAP(Result::ERROR_OCSP_UNKNOWN_RESPONSE_STATUS, \ - SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS) \ - MOZILLA_PKIX_MAP(Result::ERROR_OCSP_UNKNOWN_CERT, \ - SEC_ERROR_OCSP_UNKNOWN_CERT) \ - MOZILLA_PKIX_MAP(Result::ERROR_OCSP_FUTURE_RESPONSE, \ - SEC_ERROR_OCSP_FUTURE_RESPONSE) \ - MOZILLA_PKIX_MAP(Result::ERROR_INVALID_KEY, \ - SEC_ERROR_INVALID_KEY) \ - MOZILLA_PKIX_MAP(Result::ERROR_UNSUPPORTED_KEYALG, \ - SEC_ERROR_UNSUPPORTED_KEYALG) \ - MOZILLA_PKIX_MAP(Result::ERROR_EXPIRED_ISSUER_CERTIFICATE, \ - SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE) \ - MOZILLA_PKIX_MAP(Result::ERROR_CA_CERT_USED_AS_END_ENTITY, \ - MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY) \ - MOZILLA_PKIX_MAP(Result::ERROR_INADEQUATE_KEY_SIZE, \ - MOZILLA_PKIX_ERROR_INADEQUATE_KEY_SIZE) \ - MOZILLA_PKIX_MAP(Result::FATAL_ERROR_INVALID_ARGS, \ - SEC_ERROR_INVALID_ARGS) \ - MOZILLA_PKIX_MAP(Result::FATAL_ERROR_INVALID_STATE, \ - PR_INVALID_STATE_ERROR) \ - MOZILLA_PKIX_MAP(Result::FATAL_ERROR_LIBRARY_FAILURE, \ - SEC_ERROR_LIBRARY_FAILURE) \ - MOZILLA_PKIX_MAP(Result::FATAL_ERROR_NO_MEMORY, \ - SEC_ERROR_NO_MEMORY) \ + MOZILLA_PKIX_MAP(Success, 0, 0) \ + MOZILLA_PKIX_MAP(ERROR_BAD_DER, 1, \ + SEC_ERROR_BAD_DER) \ + MOZILLA_PKIX_MAP(ERROR_CA_CERT_INVALID, 2, \ + SEC_ERROR_CA_CERT_INVALID) \ + MOZILLA_PKIX_MAP(ERROR_BAD_SIGNATURE, 3, \ + SEC_ERROR_BAD_SIGNATURE) \ + MOZILLA_PKIX_MAP(ERROR_CERT_BAD_ACCESS_LOCATION, 4, \ + SEC_ERROR_CERT_BAD_ACCESS_LOCATION) \ + MOZILLA_PKIX_MAP(ERROR_CERT_NOT_IN_NAME_SPACE, 5, \ + SEC_ERROR_CERT_NOT_IN_NAME_SPACE) \ + MOZILLA_PKIX_MAP(ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED, 6, \ + SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED) \ + MOZILLA_PKIX_MAP(ERROR_CONNECT_REFUSED, 7, \ + PR_CONNECT_REFUSED_ERROR) \ + MOZILLA_PKIX_MAP(ERROR_EXPIRED_CERTIFICATE, 8, \ + SEC_ERROR_EXPIRED_CERTIFICATE) \ + MOZILLA_PKIX_MAP(ERROR_EXTENSION_VALUE_INVALID, 9, \ + SEC_ERROR_EXTENSION_VALUE_INVALID) \ + MOZILLA_PKIX_MAP(ERROR_INADEQUATE_CERT_TYPE, 10, \ + SEC_ERROR_INADEQUATE_CERT_TYPE) \ + MOZILLA_PKIX_MAP(ERROR_INADEQUATE_KEY_USAGE, 11, \ + SEC_ERROR_INADEQUATE_KEY_USAGE) \ + MOZILLA_PKIX_MAP(ERROR_INVALID_ALGORITHM, 12, \ + SEC_ERROR_INVALID_ALGORITHM) \ + MOZILLA_PKIX_MAP(ERROR_INVALID_TIME, 13, \ + SEC_ERROR_INVALID_TIME) \ + MOZILLA_PKIX_MAP(ERROR_KEY_PINNING_FAILURE, 14, \ + MOZILLA_PKIX_ERROR_KEY_PINNING_FAILURE) \ + MOZILLA_PKIX_MAP(ERROR_PATH_LEN_CONSTRAINT_INVALID, 15, \ + SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID) \ + MOZILLA_PKIX_MAP(ERROR_POLICY_VALIDATION_FAILED, 16, \ + SEC_ERROR_POLICY_VALIDATION_FAILED) \ + MOZILLA_PKIX_MAP(ERROR_REVOKED_CERTIFICATE, 17, \ + SEC_ERROR_REVOKED_CERTIFICATE) \ + MOZILLA_PKIX_MAP(ERROR_UNKNOWN_CRITICAL_EXTENSION, 18, \ + SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION) \ + MOZILLA_PKIX_MAP(ERROR_UNKNOWN_ERROR, 19, \ + PR_UNKNOWN_ERROR) \ + MOZILLA_PKIX_MAP(ERROR_UNKNOWN_ISSUER, 20, \ + SEC_ERROR_UNKNOWN_ISSUER) \ + MOZILLA_PKIX_MAP(ERROR_UNTRUSTED_CERT, 21, \ + SEC_ERROR_UNTRUSTED_CERT) \ + MOZILLA_PKIX_MAP(ERROR_UNTRUSTED_ISSUER, 22, \ + SEC_ERROR_UNTRUSTED_ISSUER) \ + MOZILLA_PKIX_MAP(ERROR_OCSP_BAD_SIGNATURE, 23, \ + SEC_ERROR_OCSP_BAD_SIGNATURE) \ + MOZILLA_PKIX_MAP(ERROR_OCSP_INVALID_SIGNING_CERT, 24, \ + SEC_ERROR_OCSP_INVALID_SIGNING_CERT) \ + MOZILLA_PKIX_MAP(ERROR_OCSP_MALFORMED_REQUEST, 25, \ + SEC_ERROR_OCSP_MALFORMED_REQUEST) \ + MOZILLA_PKIX_MAP(ERROR_OCSP_MALFORMED_RESPONSE, 26, \ + SEC_ERROR_OCSP_MALFORMED_RESPONSE) \ + MOZILLA_PKIX_MAP(ERROR_OCSP_OLD_RESPONSE, 27, \ + SEC_ERROR_OCSP_OLD_RESPONSE) \ + MOZILLA_PKIX_MAP(ERROR_OCSP_REQUEST_NEEDS_SIG, 28, \ + SEC_ERROR_OCSP_REQUEST_NEEDS_SIG) \ + MOZILLA_PKIX_MAP(ERROR_OCSP_RESPONDER_CERT_INVALID, 29, \ + SEC_ERROR_OCSP_RESPONDER_CERT_INVALID) \ + MOZILLA_PKIX_MAP(ERROR_OCSP_SERVER_ERROR, 30, \ + SEC_ERROR_OCSP_SERVER_ERROR) \ + MOZILLA_PKIX_MAP(ERROR_OCSP_TRY_SERVER_LATER, 31, \ + SEC_ERROR_OCSP_TRY_SERVER_LATER) \ + MOZILLA_PKIX_MAP(ERROR_OCSP_UNAUTHORIZED_REQUEST, 32, \ + SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST) \ + MOZILLA_PKIX_MAP(ERROR_OCSP_UNKNOWN_RESPONSE_STATUS, 33, \ + SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS) \ + MOZILLA_PKIX_MAP(ERROR_OCSP_UNKNOWN_CERT, 34, \ + SEC_ERROR_OCSP_UNKNOWN_CERT) \ + MOZILLA_PKIX_MAP(ERROR_OCSP_FUTURE_RESPONSE, 35, \ + SEC_ERROR_OCSP_FUTURE_RESPONSE) \ + MOZILLA_PKIX_MAP(ERROR_INVALID_KEY, 36, \ + SEC_ERROR_INVALID_KEY) \ + MOZILLA_PKIX_MAP(ERROR_UNSUPPORTED_KEYALG, 37, \ + SEC_ERROR_UNSUPPORTED_KEYALG) \ + MOZILLA_PKIX_MAP(ERROR_EXPIRED_ISSUER_CERTIFICATE, 38, \ + SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE) \ + MOZILLA_PKIX_MAP(ERROR_CA_CERT_USED_AS_END_ENTITY, 39, \ + MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY) \ + MOZILLA_PKIX_MAP(ERROR_INADEQUATE_KEY_SIZE, 40, \ + MOZILLA_PKIX_ERROR_INADEQUATE_KEY_SIZE) \ + MOZILLA_PKIX_MAP(FATAL_ERROR_INVALID_ARGS, FATAL_ERROR_FLAG | 1, \ + SEC_ERROR_INVALID_ARGS) \ + MOZILLA_PKIX_MAP(FATAL_ERROR_INVALID_STATE, FATAL_ERROR_FLAG | 2, \ + PR_INVALID_STATE_ERROR) \ + MOZILLA_PKIX_MAP(FATAL_ERROR_LIBRARY_FAILURE, FATAL_ERROR_FLAG | 3, \ + SEC_ERROR_LIBRARY_FAILURE) \ + MOZILLA_PKIX_MAP(FATAL_ERROR_NO_MEMORY, FATAL_ERROR_FLAG | 4, \ + SEC_ERROR_NO_MEMORY) \ /* nothing here */ +MOZILLA_PKIX_ENUM_CLASS Result +{ +#define MOZILLA_PKIX_MAP(name, value, nss_name) name = value, + MOZILLA_PKIX_MAP_LIST +#undef MOZILLA_PKIX_MAP +}; + // Returns the stringified name of the given result, e.g. "Result::Success", // or nullptr if result is unknown (invalid). const char* MapResultToName(Result result); diff --git a/security/pkix/lib/pkixnss.cpp b/security/pkix/lib/pkixnss.cpp index 4631fe6fa516..fd07a41b8609 100644 --- a/security/pkix/lib/pkixnss.cpp +++ b/security/pkix/lib/pkixnss.cpp @@ -195,8 +195,8 @@ MapPRErrorCodeToResult(PRErrorCode error) { switch (error) { -#define MOZILLA_PKIX_MAP(mozilla_pkix_result, nss_result) \ - case nss_result: return mozilla_pkix_result; +#define MOZILLA_PKIX_MAP(mozilla_pkix_result, value, nss_result) \ + case nss_result: return Result::mozilla_pkix_result; MOZILLA_PKIX_MAP_LIST @@ -212,8 +212,8 @@ MapResultToPRErrorCode(Result result) { switch (result) { -#define MOZILLA_PKIX_MAP(mozilla_pkix_result, nss_result) \ - case mozilla_pkix_result: return nss_result; +#define MOZILLA_PKIX_MAP(mozilla_pkix_result, value, nss_result) \ + case Result::mozilla_pkix_result: return nss_result; MOZILLA_PKIX_MAP_LIST diff --git a/security/pkix/lib/pkixresult.cpp b/security/pkix/lib/pkixresult.cpp index 7c5b395bb477..df3a8907d757 100644 --- a/security/pkix/lib/pkixresult.cpp +++ b/security/pkix/lib/pkixresult.cpp @@ -33,8 +33,8 @@ MapResultToName(Result result) { switch (result) { -#define MOZILLA_PKIX_MAP(mozilla_pkix_result, nss_result) \ - case mozilla_pkix_result: return #mozilla_pkix_result; +#define MOZILLA_PKIX_MAP(mozilla_pkix_result, value, nss_result) \ + case Result::mozilla_pkix_result: return "Result::" #mozilla_pkix_result; MOZILLA_PKIX_MAP_LIST From 1839b19b7662c72f8af4b94539eaae9376a04243 Mon Sep 17 00:00:00 2001 From: Lars T Hansen Date: Sat, 20 Sep 2014 12:12:06 +0200 Subject: [PATCH 027/114] Bug 1068458 - Limit SharedArrayBuffer and SharedTypedArray to INT32_MAX bytes. r=waldo --- .../tests/sharedbuf/bug1068458-toolong.js | 14 ++++++++++++++ js/src/vm/SharedArrayObject.cpp | 15 ++++++++++----- js/src/vm/SharedTypedArrayObject.cpp | 15 +++++++++------ 3 files changed, 33 insertions(+), 11 deletions(-) create mode 100644 js/src/jit-test/tests/sharedbuf/bug1068458-toolong.js diff --git a/js/src/jit-test/tests/sharedbuf/bug1068458-toolong.js b/js/src/jit-test/tests/sharedbuf/bug1068458-toolong.js new file mode 100644 index 000000000000..f1113d4d7e71 --- /dev/null +++ b/js/src/jit-test/tests/sharedbuf/bug1068458-toolong.js @@ -0,0 +1,14 @@ +// This used to assert, now it will throw because the limit +// (in bytes) on a SharedArrayBuffer is INT32_MAX. + +if (!this.SharedUint16Array) + quit(); + +var thrown = false; +try { + new SharedUint16Array(2147483647); +} +catch (e) { + thrown = true; +} +assertEq(thrown, true); diff --git a/js/src/vm/SharedArrayObject.cpp b/js/src/vm/SharedArrayObject.cpp index 25e307860c19..4c973d75a093 100644 --- a/js/src/vm/SharedArrayObject.cpp +++ b/js/src/vm/SharedArrayObject.cpp @@ -198,7 +198,8 @@ SharedArrayBufferObject::class_constructor(JSContext *cx, unsigned argc, Value * uint32_t length; bool overflow; if (!ToLengthClamped(cx, args.get(0), &length, &overflow)) { - if (overflow) + // Bug 1068458: Limit length to 2^31-1. + if (overflow || length > INT32_MAX) JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_SHARED_ARRAY_BAD_LENGTH); return false; } @@ -214,10 +215,14 @@ SharedArrayBufferObject * SharedArrayBufferObject::New(JSContext *cx, uint32_t length) { if (!IsValidAsmJSHeapLength(length)) { - ScopedJSFreePtr msg( - JS_smprintf("SharedArrayBuffer byteLength 0x%x is not a valid length. The next valid " - "length is 0x%x", length, RoundUpToNextValidAsmJSHeapLength(length))); - JS_ReportError(cx, msg.get()); + mozilla::UniquePtr msg; + if (length > INT32_MAX) + msg.reset(JS_smprintf("SharedArrayBuffer byteLength 0x%x is too large", length)); + else + msg.reset(JS_smprintf("SharedArrayBuffer byteLength 0x%x is not a valid length. The next valid " + "length is 0x%x", length, RoundUpToNextValidAsmJSHeapLength(length))); + if (msg) + JS_ReportError(cx, msg.get()); return nullptr; } diff --git a/js/src/vm/SharedTypedArrayObject.cpp b/js/src/vm/SharedTypedArrayObject.cpp index 7f267eac692c..2a34f0acae7f 100644 --- a/js/src/vm/SharedTypedArrayObject.cpp +++ b/js/src/vm/SharedTypedArrayObject.cpp @@ -87,9 +87,10 @@ class SharedTypedArrayObjectTemplate : public SharedTypedArrayObject // A value that signifies that we should use the buffer up to the end. static const uint32_t LENGTH_NOT_PROVIDED = (uint32_t)-1; - // This is the max implementation value of 'length': 2^32-2. - // The value 2^32-1 is reserved for LENGTH_NOT_PROVIDED. - static const uint32_t MAX_LENGTH = 0xFFFFFFFEU; + // This is the max implementation value of 'length': 2^31-1. + // The reason it is not 2^32-2 is due to Bug 1068458: most of the + // TypedArray code limits the length to INT32_MAX. + static const uint32_t MAX_LENGTH = INT32_MAX; // This is the max value of 'byteOffset': one below the length. static const uint32_t MAX_BYTEOFFSET = MAX_LENGTH - 1; @@ -275,7 +276,8 @@ class SharedTypedArrayObjectTemplate : public SharedTypedArrayObject uint32_t length; bool overflow; if (!ToLengthClamped(cx, args[0], &length, &overflow)) { - if (overflow) + // Bug 1068458: Limit length to 2^31-1. + if (overflow || length > INT32_MAX) JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_BAD_ARRAY_LENGTH); return nullptr; } @@ -307,7 +309,8 @@ class SharedTypedArrayObjectTemplate : public SharedTypedArrayObject if (args.length() > 2) { bool overflow; if (!ToLengthClamped(cx, args[2], &length, &overflow)) { - if (overflow) + // Bug 1068458: Limit length to 2^31-1. + if (overflow || length > INT32_MAX) JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_SHARED_TYPED_ARRAY_ARG_RANGE, "'length'"); return nullptr; @@ -323,7 +326,7 @@ class SharedTypedArrayObjectTemplate : public SharedTypedArrayObject { if (nelements > MAX_LENGTH / sizeof(NativeType)) { JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, - JSMSG_NEED_DIET, "size and count"); + JSMSG_NEED_DIET, "shared typed array"); return false; } buffer.set(SharedArrayBufferObject::New(cx, nelements * sizeof(NativeType))); From e7fea5e9095d48a8a79c3145eb33b55f99666e6b Mon Sep 17 00:00:00 2001 From: Lars T Hansen Date: Sat, 20 Sep 2014 12:26:20 +0200 Subject: [PATCH 028/114] Bug 1068451 - test case. r=waldo --- .../sharedbuf/sab-construct-noargs-1068458.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 js/src/jit-test/tests/sharedbuf/sab-construct-noargs-1068458.js diff --git a/js/src/jit-test/tests/sharedbuf/sab-construct-noargs-1068458.js b/js/src/jit-test/tests/sharedbuf/sab-construct-noargs-1068458.js new file mode 100644 index 000000000000..858808248ebb --- /dev/null +++ b/js/src/jit-test/tests/sharedbuf/sab-construct-noargs-1068458.js @@ -0,0 +1,15 @@ +if (!this.SharedArrayBuffer) + quit(); + +// Note that as of 2014-09-18 it is not correct to construct a SharedArrayBuffer without +// a length acceptable to asm.js: at-least 4K AND (power-of-two OR multiple-of-16M). +// That is likely to change however (see bug 1068684). The test case is constructed +// to take that into account by catching exceptions. That does not impact the +// original bug, which is an assertion in the implementation. + +try { + new SharedArrayBuffer // No arguments +} +catch (e) { + // Ignore it +} From b691107c767b2f240b1ebcdd395fc8e0a54291b3 Mon Sep 17 00:00:00 2001 From: John Sullivan Date: Sat, 20 Sep 2014 15:10:18 -0700 Subject: [PATCH 029/114] Bug 1067679 - Call DnsQuery in addition to getaddrinfo to get DNS TTL on Windows r=sworkman --- modules/libpref/init/all.js | 7 + netwerk/dns/DNS.cpp | 1 + netwerk/dns/DNS.h | 3 + netwerk/dns/GetAddrInfo.cpp | 339 +++++++++++++ netwerk/dns/GetAddrInfo.h | 67 +++ netwerk/dns/moz.build | 1 + netwerk/dns/nsDNSService2.cpp | 12 +- netwerk/dns/nsHostResolver.cpp | 487 ++++++++++++++++--- netwerk/dns/nsHostResolver.h | 62 ++- toolkit/components/telemetry/Histograms.json | 108 ++++ 10 files changed, 1004 insertions(+), 83 deletions(-) create mode 100644 netwerk/dns/GetAddrInfo.cpp create mode 100644 netwerk/dns/GetAddrInfo.h diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 1034736a1010..aa6e5868e698 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -4296,3 +4296,10 @@ pref("camera.control.low_memory_thresholdMB", 404); // UDPSocket API pref("dom.udpsocket.enabled", false); + +// Experiment: Get TTL from DNS records. +// Unset initially (0); Randomly chosen on first run; will remain unchanged +// unless adjusted by the user or experiment ends. Variants defined in +// nsHostResolver.cpp. +pref("dns.ttl-experiment.variant", 0); +pref("dns.ttl-experiment.enabled", true); diff --git a/netwerk/dns/DNS.cpp b/netwerk/dns/DNS.cpp index a2aaa534de28..817dc1097f73 100644 --- a/netwerk/dns/DNS.cpp +++ b/netwerk/dns/DNS.cpp @@ -296,6 +296,7 @@ AddrInfo::Init(const char *host, const char *cname) { MOZ_ASSERT(host, "Cannot initialize AddrInfo with a null host pointer!"); + ttl = NO_TTL_DATA; size_t hostlen = strlen(host); mHostName = static_cast(moz_xmalloc(hostlen + 1)); memcpy(mHostName, host, hostlen + 1); diff --git a/netwerk/dns/DNS.h b/netwerk/dns/DNS.h index e3beaf5646b6..4024cfe7d3cc 100644 --- a/netwerk/dns/DNS.h +++ b/netwerk/dns/DNS.h @@ -142,6 +142,9 @@ public: char *mHostName; char *mCanonicalName; + uint16_t ttl; + static const uint16_t NO_TTL_DATA = (uint16_t) -1; + LinkedList mAddresses; private: diff --git a/netwerk/dns/GetAddrInfo.cpp b/netwerk/dns/GetAddrInfo.cpp new file mode 100644 index 000000000000..952c56f4f6cc --- /dev/null +++ b/netwerk/dns/GetAddrInfo.cpp @@ -0,0 +1,339 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#if defined(MOZ_LOGGING) +#define FORCE_PR_LOG +#endif + +#include "GetAddrInfo.h" +#include "mozilla/net/DNS.h" +#include "prnetdb.h" +#include "nsHostResolver.h" +#include "nsError.h" +#include "mozilla/Mutex.h" +#include "nsAutoPtr.h" +#include "mozilla/StaticPtr.h" +#include "MainThreadUtils.h" +#include "mozilla/DebugOnly.h" +#include "mozilla/net/DNS.h" + +#include "prlog.h" +#if defined(PR_LOGGING) +static PRLogModuleInfo *gGetAddrInfoLog = PR_NewLogModule("GetAddrInfo"); +#define LOG(msg, ...) \ + PR_LOG(gGetAddrInfoLog, PR_LOG_DEBUG, ("[DNS]: " msg, ##__VA_ARGS__)) +#define LOG_WARNING(msg, ...) \ + PR_LOG(gGetAddrInfoLog, PR_LOG_WARNING, ("[DNS]: " msg, ##__VA_ARGS__)) +#else +#define LOG(args) +#define LOG_WARNING(args) +#endif + +#if DNSQUERY_AVAILABLE +// There is a bug in Windns.h where the type of parameter ppQueryResultsSet for +// DnsQuery_A is dependent on UNICODE being set. It should *always* be +// PDNS_RECORDA, but if UNICODE is set it is PDNS_RECORDW. To get around this +// we make sure that UNICODE is unset. +#undef UNICODE +#include +#undef GetAddrInfo +#include +#endif + +namespace mozilla { +namespace net { + +#if DNSQUERY_AVAILABLE +//////////////////////////// +// WINDOWS IMPLEMENTATION // +//////////////////////////// + +// Ensure consistency of PR_* and AF_* constants to allow for legacy usage of +// PR_* constants with this API. +static_assert(PR_AF_INET == AF_INET && PR_AF_INET6 == AF_INET6 + && PR_AF_UNSPEC == AF_UNSPEC, "PR_AF_* must match AF_*"); + +// We intentionally leak this mutex. This is because we can run into a +// situation where the worker threads are still running until the process +// is actually fully shut down, and at any time one of those worker +// threads can access gDnsapiInfoLock. +static OffTheBooksMutex* gDnsapiInfoLock = nullptr; + +struct DnsapiInfo +{ +public: + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DnsapiInfo); + + HMODULE mLibrary; + decltype(&DnsQuery_A) mDnsQueryFunc; + decltype(&DnsFree) mDnsFreeFunc; + +private: + // This will either be called during shutdown of the GetAddrInfo module, or + // when a worker thread is done doing a lookup (ie: within + // _GetAddrInfo_Windows). Note that the lock must be held when this is + // called. + ~DnsapiInfo() + { + if (gDnsapiInfoLock) { + gDnsapiInfoLock->AssertCurrentThreadOwns(); + } else { + MOZ_ASSERT_UNREACHABLE("No mutex available during GetAddrInfo " + "shutdown."); + return; + } + + LOG("Freeing Dnsapi.dll"); + MOZ_ASSERT(mLibrary); + DebugOnly rv = FreeLibrary(mLibrary); + NS_WARN_IF_FALSE(rv, "Failed to free Dnsapi.dll."); + } +}; + +static StaticRefPtr gDnsapiInfo; + +static MOZ_ALWAYS_INLINE nsresult +_GetAddrInfoInit_Windows() +{ + // This is necessary to ensure strict thread safety because if two threads + // run this function at the same time they can potentially create two + // mutexes. + MOZ_ASSERT(NS_IsMainThread(), + "Do not initialize GetAddrInfo off main thread!"); + + if (!gDnsapiInfoLock) { + gDnsapiInfoLock = new OffTheBooksMutex("GetAddrInfo.cpp::gDnsapiInfoLock"); + } + OffTheBooksMutexAutoLock lock(*gDnsapiInfoLock); + + if (gDnsapiInfo) { + MOZ_ASSERT_UNREACHABLE("GetAddrInfo is being initialized multiple times!"); + return NS_ERROR_ALREADY_INITIALIZED; + } + + HMODULE library = LoadLibraryA("Dnsapi.dll"); + if (NS_WARN_IF(!library)) { + return NS_ERROR_FAILURE; + } + + FARPROC dnsQueryFunc = GetProcAddress(library, "DnsQuery_A"); + FARPROC dnsFreeFunc = GetProcAddress(library, "DnsFree"); + if (NS_WARN_IF(!dnsQueryFunc) || NS_WARN_IF(!dnsFreeFunc)) { + DebugOnly rv = FreeLibrary(library); + NS_WARN_IF_FALSE(rv, "Failed to free Dnsapi.dll."); + return NS_ERROR_FAILURE; + } + + DnsapiInfo* info = new DnsapiInfo; + info->mLibrary = library; + info->mDnsQueryFunc = (decltype(info->mDnsQueryFunc)) dnsQueryFunc; + info->mDnsFreeFunc = (decltype(info->mDnsFreeFunc)) dnsFreeFunc; + gDnsapiInfo = info; + + return NS_OK; +} + +static MOZ_ALWAYS_INLINE nsresult +_GetAddrInfoShutdown_Windows() +{ + OffTheBooksMutexAutoLock lock(*gDnsapiInfoLock); + + if (NS_WARN_IF(!gDnsapiInfo) || NS_WARN_IF(!gDnsapiInfoLock)) { + MOZ_ASSERT_UNREACHABLE("GetAddrInfo not initialized!"); + return NS_ERROR_NOT_INITIALIZED; + } + + gDnsapiInfo = nullptr; + + return NS_OK; +} + +static MOZ_ALWAYS_INLINE nsresult +_GetTTLData_Windows(const char* aHost, uint16_t* aResult) +{ + MOZ_ASSERT(aHost); + MOZ_ASSERT(aResult); + + nsRefPtr dnsapi = nullptr; + { + OffTheBooksMutexAutoLock lock(*gDnsapiInfoLock); + dnsapi = gDnsapiInfo; + } + + if (!dnsapi) { + LOG_WARNING("GetAddrInfo has been shutdown or has not been initialized."); + return NS_ERROR_NOT_INITIALIZED; + } + + PDNS_RECORDA dnsData = nullptr; + DNS_STATUS status = dnsapi->mDnsQueryFunc( + aHost, + DNS_TYPE_ANY, + (DNS_QUERY_STANDARD | DNS_QUERY_NO_NETBT | DNS_QUERY_NO_HOSTS_FILE + | DNS_QUERY_NO_MULTICAST | DNS_QUERY_ACCEPT_TRUNCATED_RESPONSE + | DNS_QUERY_DONT_RESET_TTL_VALUES), + nullptr, + &dnsData, + nullptr); + if (status == DNS_INFO_NO_RECORDS || status == DNS_ERROR_RCODE_NAME_ERROR + || !dnsData) { + LOG("No DNS records found for %s.\n", aHost); + return NS_ERROR_UNKNOWN_HOST; + } else if (status != NOERROR) { + LOG_WARNING("DnsQuery_A failed with status %X.\n", status); + return NS_ERROR_FAILURE; + } + + unsigned int ttl = -1; + PDNS_RECORDA curRecord = dnsData; + for (; curRecord; curRecord = curRecord->pNext) { + // Only records in the answer section are important + if (curRecord->Flags.S.Section != DnsSectionAnswer) { + continue; + } + + if (curRecord->wType == DNS_TYPE_A || curRecord->wType == DNS_TYPE_AAAA) { + ttl = std::min(ttl, curRecord->dwTtl); + } + } + + dnsapi->mDnsFreeFunc(dnsData, DNS_FREE_TYPE::DnsFreeRecordList); + + { + // dnsapi's destructor is not thread-safe, so we release explicitly here + OffTheBooksMutexAutoLock lock(*gDnsapiInfoLock); + dnsapi = nullptr; + } + + if (ttl == -1) { + LOG("No useable TTL found."); + return NS_ERROR_FAILURE; + } + + *aResult = ttl; + return NS_OK; +} +#endif + +//////////////////////////////////// +// PORTABLE RUNTIME IMPLEMENTATION// +//////////////////////////////////// + +static MOZ_ALWAYS_INLINE nsresult +_GetAddrInfo_Portable(const char* aCanonHost, uint16_t aAddressFamily, + uint16_t aFlags, AddrInfo** aAddrInfo) +{ + MOZ_ASSERT(aCanonHost); + MOZ_ASSERT(aAddrInfo); + + // We accept the same aFlags that nsHostResolver::ResolveHost accepts, but we + // need to translate the aFlags into a form that PR_GetAddrInfoByName + // accepts. + int prFlags = PR_AI_ADDRCONFIG; + if (!(aFlags & nsHostResolver::RES_CANON_NAME)) { + prFlags |= PR_AI_NOCANONNAME; + } + + // We need to remove IPv4 records manually because PR_GetAddrInfoByName + // doesn't support PR_AF_INET6. + bool disableIPv4 = aAddressFamily == PR_AF_INET6; + if (disableIPv4) { + aAddressFamily = PR_AF_UNSPEC; + } + + PRAddrInfo* prai = PR_GetAddrInfoByName(aCanonHost, aAddressFamily, prFlags); + + if (!prai) { + return NS_ERROR_UNKNOWN_HOST; + } + + const char* canonName = nullptr; + if (aFlags & nsHostResolver::RES_CANON_NAME) { + canonName = PR_GetCanonNameFromAddrInfo(prai); + } + + nsAutoPtr ai(new AddrInfo(aCanonHost, prai, disableIPv4, canonName)); + PR_FreeAddrInfo(prai); + if (ai->mAddresses.isEmpty()) { + return NS_ERROR_UNKNOWN_HOST; + } + + *aAddrInfo = ai.forget(); + + return NS_OK; +} + +////////////////////////////////////// +// COMMON/PLATFORM INDEPENDENT CODE // +////////////////////////////////////// +nsresult +GetAddrInfoInit() { + LOG("Initializing GetAddrInfo.\n"); + +#if DNSQUERY_AVAILABLE + return _GetAddrInfoInit_Windows(); +#else + return NS_OK; +#endif +} + +nsresult +GetAddrInfoShutdown() { + LOG("Shutting down GetAddrInfo.\n"); + +#if DNSQUERY_AVAILABLE + return _GetAddrInfoShutdown_Windows(); +#else + return NS_OK; +#endif +} + +nsresult +GetAddrInfo(const char* aHost, uint16_t aAddressFamily, uint16_t aFlags, + AddrInfo** aAddrInfo, bool aGetTtl) +{ + if (NS_WARN_IF(!aHost) || NS_WARN_IF(!aAddrInfo)) { + return NS_ERROR_NULL_POINTER; + } + +#if DNSQUERY_AVAILABLE + // The GetTTLData needs the canonical name to function properly + if (aGetTtl) { + aFlags |= nsHostResolver::RES_CANON_NAME; + } +#endif + + *aAddrInfo = nullptr; + nsresult rv = _GetAddrInfo_Portable(aHost, aAddressFamily, aFlags, aAddrInfo); + +#if DNSQUERY_AVAILABLE + if (aGetTtl && NS_SUCCEEDED(rv)) { + // Figure out the canonical name, or if that fails, just use the host name + // we have. + const char *name = nullptr; + if (*aAddrInfo != nullptr && (*aAddrInfo)->mCanonicalName) { + name = (*aAddrInfo)->mCanonicalName; + } else { + name = aHost; + } + + LOG("Getting TTL for %s (cname = %s).", aHost, name); + uint16_t ttl = 0; + nsresult ttlRv = _GetTTLData_Windows(name, &ttl); + if (NS_SUCCEEDED(ttlRv)) { + (*aAddrInfo)->ttl = ttl; + LOG("Got TTL %u for %s (name = %s).", ttl, aHost, name); + } else { + LOG_WARNING("Could not get TTL for %s (cname = %s).", aHost, name); + } + } +#endif + + return rv; +} + +} // namespace net +} // namespace mozilla diff --git a/netwerk/dns/GetAddrInfo.h b/netwerk/dns/GetAddrInfo.h new file mode 100644 index 000000000000..2da7799a7c51 --- /dev/null +++ b/netwerk/dns/GetAddrInfo.h @@ -0,0 +1,67 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef netwerk_dns_GetAddrInfo_h +#define netwerk_dns_GetAddrInfo_h + +#include "nsError.h" +#include "nscore.h" + +#if defined(XP_WIN) && !defined(RELEASE_BUILD) +#define DNSQUERY_AVAILABLE 1 +#define TTL_AVAILABLE 1 +#else +#define DNSQUERY_AVAILABLE 0 +#define TTL_AVAILABLE 0 +#endif + +namespace mozilla { +namespace net { + +class AddrInfo; + +/** + * Look up a host by name. Mostly equivalent to getaddrinfo(host, NULL, ...) of + * RFC 3493. + * + * @param aHost[in] Character string defining the host name of interest + * @param aAddressFamily[in] May be AF_INET, AF_INET6, or AF_UNSPEC. + * @param aFlags[in] May be either PR_AI_ADDRCONFIG or + * PR_AI_ADDRCONFIG | PR_AI_NOCANONNAME. Include PR_AI_NOCANONNAME to + * suppress the determination of the canonical name corresponding to + * hostname (PR_AI_NOCANONNAME will be ignored if the TTL is retrieved). + * @param aAddrInfo[out] Will point to the results of the host lookup, or be + * null if the lookup failed. + * @param aGetTtl[in] If true, and TTL_AVAILABLE is truthy, the TTL will be + * retrieved if DNS provides the answers.. + */ +nsresult +GetAddrInfo(const char* aHost, uint16_t aAddressFamily, uint16_t aFlags, + AddrInfo** aAddrInfo, bool aGetTtl); + +/** + * Initialize the GetAddrInfo module. + * + * GetAddrInfoShutdown() should be called for every time this function is + * called. + */ +nsresult +GetAddrInfoInit(); + +/** + * Shutdown the GetAddrInfo module. + * + * This function should be called for every time GetAddrInfoInit() is called. + * An assertion may throw (but is not guarenteed) if this function is called + * too many times. + */ +nsresult +GetAddrInfoShutdown(); + +} // namespace net +} // namespace mozilla + +#endif // netwerk_dns_GetAddrInfo_h diff --git a/netwerk/dns/moz.build b/netwerk/dns/moz.build index 0b0717a5a8c8..a106daebdefc 100644 --- a/netwerk/dns/moz.build +++ b/netwerk/dns/moz.build @@ -25,6 +25,7 @@ EXPORTS.mozilla.net += [ ] SOURCES += [ + 'GetAddrInfo.cpp', # Excluded from UNIFIED_SOURCES due to NSPR forced logging. 'nsEffectiveTLDService.cpp', # Excluded from UNIFIED_SOURCES due to special build flags. 'nsHostResolver.cpp', # Excluded from UNIFIED_SOURCES due to NSPR forced logging. ] diff --git a/netwerk/dns/nsDNSService2.cpp b/netwerk/dns/nsDNSService2.cpp index 23366ea1f2c4..7b19ff29f1b2 100644 --- a/netwerk/dns/nsDNSService2.cpp +++ b/netwerk/dns/nsDNSService2.cpp @@ -489,8 +489,8 @@ nsDNSService::Init() // prefs uint32_t maxCacheEntries = 400; - uint32_t maxCacheLifetime = 120; // seconds - uint32_t lifetimeGracePeriod = 60; // seconds + uint32_t defaultCacheLifetime = 120; // seconds + uint32_t defaultGracePeriod = 60; // seconds bool disableIPv6 = false; bool disablePrefetch = false; int proxyType = nsIProtocolProxyService::PROXYCONFIG_DIRECT; @@ -506,9 +506,9 @@ nsDNSService::Init() if (NS_SUCCEEDED(prefs->GetIntPref(kPrefDnsCacheEntries, &val))) maxCacheEntries = (uint32_t) val; if (NS_SUCCEEDED(prefs->GetIntPref(kPrefDnsCacheExpiration, &val))) - maxCacheLifetime = val; + defaultCacheLifetime = val; if (NS_SUCCEEDED(prefs->GetIntPref(kPrefDnsCacheGrace, &val))) - lifetimeGracePeriod = val; + defaultGracePeriod = val; // ASSUMPTION: pref branch does not modify out params on failure prefs->GetBoolPref(kPrefDisableIPv6, &disableIPv6); @@ -562,8 +562,8 @@ nsDNSService::Init() nsRefPtr res; nsresult rv = nsHostResolver::Create(maxCacheEntries, - maxCacheLifetime, - lifetimeGracePeriod, + defaultCacheLifetime, + defaultGracePeriod, getter_AddRefs(res)); if (NS_SUCCEEDED(rv)) { // now, set all of our member variables while holding the lock diff --git a/netwerk/dns/nsHostResolver.cpp b/netwerk/dns/nsHostResolver.cpp index 1808fd1e3352..51931a4aebdb 100644 --- a/netwerk/dns/nsHostResolver.cpp +++ b/netwerk/dns/nsHostResolver.cpp @@ -17,6 +17,7 @@ #endif #include +#include #include "nsHostResolver.h" #include "nsError.h" #include "nsISupportsBase.h" @@ -30,15 +31,23 @@ #include "plstr.h" #include "nsURLHelper.h" #include "nsThreadUtils.h" +#include "GetAddrInfo.h" +#include "mtransport/runnable_utils.h" #include "mozilla/HashFunctions.h" #include "mozilla/TimeStamp.h" #include "mozilla/Telemetry.h" #include "mozilla/VisualEventTracer.h" +#include "mozilla/DebugOnly.h" +#include "mozilla/Preferences.h" using namespace mozilla; using namespace mozilla::net; +// None of our implementations expose a TTL for negative responses, so we use a +// constant always. +static const unsigned int NEGATIVE_RECORD_LIFETIME = 60; + //---------------------------------------------------------------------------- // Use a persistent thread pool in order to avoid spinning up new threads all the time. @@ -151,6 +160,117 @@ IsLowPriority(uint16_t flags) //---------------------------------------------------------------------------- +enum DnsExpirationVariant { + DNS_EXP_VARIANT_UNSET = 0, + DNS_EXP_VARIANT_CONTROL = 1, + DNS_EXP_VARIANT_TTL_ONLY = 2, + DNS_EXP_VARIANT_TTL_PLUS_CONST_GRACE = 3, + DNS_EXP_VARIANT_MAX_VALUE = 3, +}; +static DnsExpirationVariant sDnsVariant; + +static mozilla::Telemetry::ID +GetCacheHitHistogram(DnsExpirationVariant aVariant, + nsHostRecord::DnsPriority aPriority) +{ + using namespace mozilla::Telemetry; + + switch (aVariant) { + case DNS_EXP_VARIANT_CONTROL: + switch (aPriority) { + case nsHostRecord::DNS_PRIORITY_HIGH: + return DNS_CACHE_HIT_VAR_CONTROL_HIGH; + + case nsHostRecord::DNS_PRIORITY_MEDIUM: + return DNS_CACHE_HIT_VAR_CONTROL_MEDIUM; + + case nsHostRecord::DNS_PRIORITY_LOW: + return DNS_CACHE_HIT_VAR_CONTROL_LOW; + } + + case DNS_EXP_VARIANT_TTL_ONLY: + switch (aPriority) { + case nsHostRecord::DNS_PRIORITY_HIGH: + return DNS_CACHE_HIT_VAR_TTL_ONLY_HIGH; + + case nsHostRecord::DNS_PRIORITY_MEDIUM: + return DNS_CACHE_HIT_VAR_TTL_ONLY_MEDIUM; + + case nsHostRecord::DNS_PRIORITY_LOW: + return DNS_CACHE_HIT_VAR_TTL_ONLY_LOW; + } + + case DNS_EXP_VARIANT_TTL_PLUS_CONST_GRACE: + switch (aPriority) { + case nsHostRecord::DNS_PRIORITY_HIGH: + return DNS_CACHE_HIT_VAR_TTL_PLUS_CONST_GRACE_HIGH; + + case nsHostRecord::DNS_PRIORITY_MEDIUM: + return DNS_CACHE_HIT_VAR_TTL_PLUS_CONST_GRACE_MEDIUM; + + case nsHostRecord::DNS_PRIORITY_LOW: + return DNS_CACHE_HIT_VAR_TTL_PLUS_CONST_GRACE_LOW; + } + + case DNS_EXP_VARIANT_UNSET: + ; + } + + MOZ_ASSERT_UNREACHABLE("Invalid expiration variant."); + return DNS_CACHE_HIT_VAR_CONTROL_LOW; +} + +static mozilla::Telemetry::ID +GetBlacklistCountHistogram(DnsExpirationVariant aVariant, + nsHostRecord::DnsPriority aPriority) +{ + using namespace mozilla::Telemetry; + + switch (aVariant) { + case DNS_EXP_VARIANT_CONTROL: + switch (aPriority) { + case nsHostRecord::DNS_PRIORITY_HIGH: + return DNS_BLACKLIST_COUNT_VAR_CONTROL_HIGH; + + case nsHostRecord::DNS_PRIORITY_MEDIUM: + return DNS_BLACKLIST_COUNT_VAR_CONTROL_MEDIUM; + + case nsHostRecord::DNS_PRIORITY_LOW: + return DNS_BLACKLIST_COUNT_VAR_CONTROL_LOW; + } + + case DNS_EXP_VARIANT_TTL_ONLY: + switch (aPriority) { + case nsHostRecord::DNS_PRIORITY_HIGH: + return DNS_BLACKLIST_COUNT_VAR_TTL_ONLY_HIGH; + + case nsHostRecord::DNS_PRIORITY_MEDIUM: + return DNS_BLACKLIST_COUNT_VAR_TTL_ONLY_MEDIUM; + + case nsHostRecord::DNS_PRIORITY_LOW: + return DNS_BLACKLIST_COUNT_VAR_TTL_ONLY_LOW; + } + + case DNS_EXP_VARIANT_TTL_PLUS_CONST_GRACE: + switch (aPriority) { + case nsHostRecord::DNS_PRIORITY_HIGH: + return DNS_BLACKLIST_COUNT_VAR_TTL_PLUS_CONST_GRACE_HIGH; + + case nsHostRecord::DNS_PRIORITY_MEDIUM: + return DNS_BLACKLIST_COUNT_VAR_TTL_PLUS_CONST_GRACE_MEDIUM; + + case nsHostRecord::DNS_PRIORITY_LOW: + return DNS_BLACKLIST_COUNT_VAR_TTL_PLUS_CONST_GRACE_LOW; + } + + case DNS_EXP_VARIANT_UNSET: + ; // Fall through + } + + MOZ_ASSERT_UNREACHABLE("Invalid variant."); + return DNS_BLACKLIST_COUNT_VAR_CONTROL_LOW; +} + // this macro filters out any flags that are not used when constructing the // host key. the significant flags are those that would affect the resulting // host record (i.e., the flags that are passed down to PR_GetAddrInfoByName). @@ -166,14 +286,16 @@ nsHostRecord::nsHostRecord(const nsHostKey *key) , onQueue(false) , usingAnyThread(false) , mDoomed(false) +#if TTL_AVAILABLE + , mGetTtl(false) +#endif + , mBlacklistedCount(0) { host = ((char *) this) + sizeof(nsHostRecord); memcpy((char *) host, key->host, strlen(key->host) + 1); flags = key->flags; af = key->af; - expiration = TimeStamp::NowLoRes(); - PR_INIT_CLIST(this); PR_INIT_CLIST(&callbacks); } @@ -195,8 +317,20 @@ nsHostRecord::Create(const nsHostKey *key, nsHostRecord **result) return NS_OK; } +void +nsHostRecord::SetExpiration(const mozilla::TimeStamp& now, unsigned int valid, unsigned int grace) +{ + mValidStart = now; + mGraceStart = now + TimeDuration::FromSeconds(valid); + mValidEnd = now + TimeDuration::FromSeconds(valid + grace); +} + nsHostRecord::~nsHostRecord() { + Telemetry::Accumulate( + GetBlacklistCountHistogram(sDnsVariant, + nsHostRecord::GetPriority(flags)), + mBlacklistedCount); delete addr_info; delete addr; } @@ -234,6 +368,8 @@ nsHostRecord::ReportUnusable(NetAddr *aAddress) // must call locked LOG(("Adding address to blacklist for host [%s], host record [%p].\n", host, this)); + ++mBlacklistedCount; + if (negative) mDoomed = true; @@ -252,15 +388,34 @@ nsHostRecord::ResetBlacklist() mBlacklistedItems.Clear(); } +nsHostRecord::ExpirationStatus +nsHostRecord::CheckExpiration(const mozilla::TimeStamp& now) const { + if (!mGraceStart.IsNull() && now >= mGraceStart + && !mValidEnd.IsNull() && now < mValidEnd) { + return nsHostRecord::EXP_GRACE; + } else if (!mValidEnd.IsNull() && now < mValidEnd) { + return nsHostRecord::EXP_VALID; + } + + return nsHostRecord::EXP_EXPIRED; +} + + bool -nsHostRecord::HasUsableResult(uint16_t queryFlags) const +nsHostRecord::HasUsableResult(const mozilla::TimeStamp& now, uint16_t queryFlags) const { - if (mDoomed) + if (mDoomed) { return false; + } // don't use cached negative results for high priority queries. - if (negative && IsHighPriority(queryFlags)) + if (negative && IsHighPriority(queryFlags)) { return false; + } + + if (CheckExpiration(now) == EXP_EXPIRED) { + return false; + } return addr_info || addr || negative; } @@ -301,6 +456,18 @@ nsHostRecord::SizeOfIncludingThis(MallocSizeOf mallocSizeOf) const return n; } +nsHostRecord::DnsPriority +nsHostRecord::GetPriority(uint16_t aFlags) +{ + if (IsHighPriority(aFlags)){ + return nsHostRecord::DNS_PRIORITY_HIGH; + } else if (IsMediumPriority(aFlags)) { + return nsHostRecord::DNS_PRIORITY_MEDIUM; + } + + return nsHostRecord::DNS_PRIORITY_LOW; +} + //---------------------------------------------------------------------------- struct nsHostDBEnt : PLDHashEntryHdr @@ -354,8 +521,13 @@ HostDB_ClearEntry(PLDHashTable *table, if (!hr->addr_info) { LOG(("No address info for host [%s].\n", hr->host)); } else { - TimeDuration diff = hr->expiration - TimeStamp::NowLoRes(); - LOG(("Record for [%s] expires in %f seconds.\n", hr->host, diff.ToSeconds())); + if (!hr->mValidEnd.IsNull()) { + TimeDuration diff = hr->mValidEnd - TimeStamp::NowLoRes(); + LOG(("Record for [%s] expires in %f seconds.\n", hr->host, + diff.ToSeconds())); + } else { + LOG(("Record for [%s] not yet valid.\n", hr->host)); + } NetAddrElement *addrElement = nullptr; char buf[kIPv6CStrBufSize]; @@ -411,12 +583,82 @@ HostDB_RemoveEntry(PLDHashTable *table, //---------------------------------------------------------------------------- +#if TTL_AVAILABLE +static const char kTtlExperimentEnabled[] = "dns.ttl-experiment.enabled"; +static const char kNetworkExperimentsEnabled[] = "network.allow-experiments"; +static const char kTtlExperimentVariant[] = "dns.ttl-experiment.variant"; + + +static void +SetTtlExperimentVariantCallback(DnsExpirationVariant aVariant) +{ + DebugOnly rv = Preferences::SetInt( + "dns.ttl-experiment.variant", sDnsVariant); + NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), + "Could not save experiment variant."); +} + +static void +_DnsExperimentChangedInternal(const char* aPref, void*) +{ + if (!Preferences::GetBool(kTtlExperimentEnabled) || + !Preferences::GetBool(kNetworkExperimentsEnabled)) { + sDnsVariant = DNS_EXP_VARIANT_CONTROL; + LOG(("DNS TTL experiment is disabled.")); + return; + } + + auto variant = static_cast( + Preferences::GetInt(kTtlExperimentVariant)); + + // Setup this profile to use a particular DNS expiration strategy + if (variant == DNS_EXP_VARIANT_UNSET) { + variant = static_cast( + rand() % DNS_EXP_VARIANT_MAX_VALUE + 1); + LOG(("No DNS TTL experiment variant saved. Randomly picked %d.", + variant)); + + // We can't set a property inside of this callback, so run it on the + // main thread. + DebugOnly rv = NS_DispatchToMainThread( + WrapRunnableNM(SetTtlExperimentVariantCallback, variant)); + NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), + "Could not dispatch set TTL experiment callback."); + } else { + LOG(("Using saved DNS TTL experiment %d.", variant)); + } + + sDnsVariant = variant; +} + +static void +DnsExperimentChanged(const char* aPref, void*) +{ + if (strcmp(aPref, kNetworkExperimentsEnabled) != 0 + && strcmp(aPref, kTtlExperimentEnabled) != 0 + && strcmp(aPref, kTtlExperimentVariant) != 0) { + return; + } + + DebugOnly rv = NS_DispatchToMainThread( + WrapRunnableNM(_DnsExperimentChangedInternal, aPref, nullptr)); + NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), + "Could not dispatch DnsExperimentChanged event."); +} + +static void +InitCRandom() +{ + srand(time(nullptr)); +} +#endif + nsHostResolver::nsHostResolver(uint32_t maxCacheEntries, - uint32_t maxCacheLifetime, - uint32_t lifetimeGracePeriod) + uint32_t defaultCacheEntryLifetime, + uint32_t defaultGracePeriod) : mMaxCacheEntries(maxCacheEntries) - , mMaxCacheLifetime(TimeDuration::FromSeconds(maxCacheLifetime)) - , mGracePeriod(TimeDuration::FromSeconds(lifetimeGracePeriod)) + , mDefaultCacheLifetime(defaultCacheEntryLifetime) + , mDefaultGracePeriod(defaultGracePeriod) , mLock("nsHostResolver.mLock") , mIdleThreadCV(mLock, "nsHostResolver.mIdleThreadCV") , mNumIdleThreads(0) @@ -444,10 +686,37 @@ nsHostResolver::~nsHostResolver() nsresult nsHostResolver::Init() { + if (NS_FAILED(GetAddrInfoInit())) { + return NS_ERROR_FAILURE; + } + PL_DHashTableInit(&mDB, &gHostDB_ops, nullptr, sizeof(nsHostDBEnt), 0); mShutdown = false; + sDnsVariant = DNS_EXP_VARIANT_CONTROL; + +#if TTL_AVAILABLE + // The preferences probably haven't been loaded from the disk yet, so we + // need to register a callback that will set up the experiment once they + // are. We also need to explicitly set a value for the props otherwise the + // callback won't be called. + { + DebugOnly rv = NS_DispatchToMainThread( + WrapRunnableNM(InitCRandom)); + NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), + "Could not dispatch InitCRandom event."); + rv = Preferences::RegisterCallbackAndCall( + &DnsExperimentChanged, "dns.ttl-experiment.", nullptr); + NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), + "Could not register DNS experiment callback."); + rv = Preferences::RegisterCallback( + &DnsExperimentChanged, "network.", nullptr); + NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), + "Could not register network experiment callback."); + } +#endif + #if defined(HAVE_RES_NINIT) // We want to make sure the system is using the correct resolver settings, // so we force it to reload those settings whenever we startup a subsequent @@ -482,6 +751,19 @@ nsHostResolver::Shutdown() { LOG(("Shutting down host resolver.\n")); +#if TTL_AVAILABLE + { + DebugOnly rv = Preferences::UnregisterCallback( + &DnsExperimentChanged, "dns.ttl-experiment.", this); + NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), + "Could not unregister TTL experiment callback."); + rv = Preferences::UnregisterCallback( + &DnsExperimentChanged, "network.", this); + NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), + "Could not unregister network experiment callback."); + } +#endif + PRCList pendingQHigh, pendingQMed, pendingQLow, evictionQ; PR_INIT_CLIST(&pendingQHigh); PR_INIT_CLIST(&pendingQMed); @@ -534,6 +816,11 @@ nsHostResolver::Shutdown() while (mThreadCount && PR_IntervalNow() < stopTime) PR_Sleep(delay); #endif + + { + mozilla::DebugOnly rv = GetAddrInfoShutdown(); + NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to shutdown GetAddrInfo"); + } } void @@ -595,8 +882,7 @@ nsHostResolver::ResolveHost(const char *host, } // do we have a cached result that we can reuse? else if (!(flags & RES_BYPASS_CACHE) && - he->rec->HasUsableResult(flags) && - TimeStamp::NowLoRes() <= (he->rec->expiration + mGracePeriod)) { + he->rec->HasUsableResult(TimeStamp::NowLoRes(), flags)) { LOG((" Using cached record for host [%s].\n", host)); // put reference to host record on stack... result = he->rec; @@ -608,7 +894,7 @@ nsHostResolver::ResolveHost(const char *host, ConditionallyRefreshRecord(he->rec, host); if (he->rec->negative) { - LOG((" Negative cache entry for[%s].\n", host)); + LOG((" Negative cache entry for [%s].\n", host)); Telemetry::Accumulate(Telemetry::DNS_LOOKUP_METHOD2, METHOD_NEGATIVE_HIT); status = NS_ERROR_UNKNOWN_HOST; @@ -667,8 +953,7 @@ nsHostResolver::ResolveHost(const char *host, "Valid host entries should contain a record"); if (PL_DHASH_ENTRY_IS_BUSY(unspecHe) && unspecHe->rec && - unspecHe->rec->HasUsableResult(flags) && - TimeStamp::NowLoRes() <= (he->rec->expiration + mGracePeriod)) { + unspecHe->rec->HasUsableResult(TimeStamp::NowLoRes(), flags)) { MOZ_ASSERT(unspecHe->rec->addr_info || unspecHe->rec->negative, "Entry should be resolved or negative."); @@ -699,7 +984,7 @@ nsHostResolver::ResolveHost(const char *host, addrIter = addrIter->getNext(); } } - if (he->rec->HasUsableResult(flags)) { + if (he->rec->HasUsableResult(TimeStamp::NowLoRes(), flags)) { result = he->rec; Telemetry::Accumulate(Telemetry::DNS_LOOKUP_METHOD2, METHOD_HIT); @@ -769,8 +1054,13 @@ nsHostResolver::ResolveHost(const char *host, } } } - if (result) + if (result) { callback->OnLookupComplete(this, result, status); + } + + Telemetry::Accumulate( + GetCacheHitHistogram(sDnsVariant, nsHostRecord::GetPriority(flags)), + static_cast(result)); return rv; } @@ -860,12 +1150,19 @@ nsHostResolver::IssueLookup(nsHostRecord *rec) mEvictionQSize--; } - if (IsHighPriority(rec->flags)) - PR_APPEND_LINK(rec, &mHighQ); - else if (IsMediumPriority(rec->flags)) - PR_APPEND_LINK(rec, &mMediumQ); - else - PR_APPEND_LINK(rec, &mLowQ); + switch (nsHostRecord::GetPriority(rec->flags)) { + case nsHostRecord::DNS_PRIORITY_HIGH: + PR_APPEND_LINK(rec, &mHighQ); + break; + + case nsHostRecord::DNS_PRIORITY_MEDIUM: + PR_APPEND_LINK(rec, &mMediumQ); + break; + + case nsHostRecord::DNS_PRIORITY_LOW: + PR_APPEND_LINK(rec, &mLowQ); + break; + } mPendingCount++; rec->resolving = true; @@ -885,8 +1182,8 @@ nsHostResolver::IssueLookup(nsHostRecord *rec) nsresult nsHostResolver::ConditionallyRefreshRecord(nsHostRecord *rec, const char *host) { - if (((TimeStamp::NowLoRes() > rec->expiration) || rec->negative) && - !rec->resolving) { + if ((rec->CheckExpiration(TimeStamp::NowLoRes()) != nsHostRecord::EXP_VALID + || rec->negative) && !rec->resolving) { LOG((" Using %s cache entry for host [%s] but starting async renewal.", rec->negative ? "negative" :"positive", host)); IssueLookup(rec); @@ -924,8 +1221,16 @@ nsHostResolver::GetHostToLookup(nsHostRecord **result) while (!mShutdown) { // remove next record from Q; hand over owning reference. Check high, then med, then low +#if TTL_AVAILABLE + #define SET_GET_TTL(var, val) \ + (var)->mGetTtl = sDnsVariant != DNS_EXP_VARIANT_CONTROL && (val) +#else + #define SET_GET_TTL(var, val) +#endif + if (!PR_CLIST_IS_EMPTY(&mHighQ)) { DeQueue (mHighQ, result); + SET_GET_TTL(*result, false); return true; } @@ -934,6 +1239,7 @@ nsHostResolver::GetHostToLookup(nsHostRecord **result) DeQueue (mMediumQ, result); mActiveAnyThreadCount++; (*result)->usingAnyThread = true; + SET_GET_TTL(*result, true); return true; } @@ -941,6 +1247,7 @@ nsHostResolver::GetHostToLookup(nsHostRecord **result) DeQueue (mLowQ, result); mActiveAnyThreadCount++; (*result)->usingAnyThread = true; + SET_GET_TTL(*result, true); return true; } } @@ -978,7 +1285,54 @@ nsHostResolver::GetHostToLookup(nsHostRecord **result) } void -nsHostResolver::OnLookupComplete(nsHostRecord *rec, nsresult status, AddrInfo *result) +nsHostResolver::PrepareRecordExpiration(nsHostRecord* rec) const +{ + MOZ_ASSERT(((bool)rec->addr_info) != rec->negative); + if (!rec->addr_info) { + rec->SetExpiration(TimeStamp::NowLoRes(), + NEGATIVE_RECORD_LIFETIME, 0); + LOG(("Caching [%s] negative record for %u seconds.\n", rec->host, + NEGATIVE_RECORD_LIFETIME)); + return; + } + + unsigned int ttl = mDefaultCacheLifetime; +#if TTL_AVAILABLE + if (sDnsVariant == DNS_EXP_VARIANT_TTL_ONLY + || sDnsVariant == DNS_EXP_VARIANT_TTL_PLUS_CONST_GRACE) { + MutexAutoLock lock(rec->addr_info_lock); + if (rec->addr_info && rec->addr_info->ttl != AddrInfo::NO_TTL_DATA) { + ttl = rec->addr_info->ttl; + } + } +#endif + + unsigned int lifetime = 0; + unsigned int grace = 0; + switch (sDnsVariant) { + case DNS_EXP_VARIANT_TTL_ONLY: + lifetime = ttl; + grace = 0; + break; + + case DNS_EXP_VARIANT_TTL_PLUS_CONST_GRACE: + lifetime = ttl; + grace = mDefaultGracePeriod; + break; + + default: + lifetime = mDefaultCacheLifetime; + grace = mDefaultGracePeriod; + break; + } + + rec->SetExpiration(TimeStamp::NowLoRes(), lifetime, grace); + LOG(("Caching [%s] record for %u seconds (grace %d) (sDnsVariant = %d).", + rec->host, lifetime, grace, sDnsVariant)); +} + +void +nsHostResolver::OnLookupComplete(nsHostRecord* rec, nsresult status, AddrInfo* result) { // get the list of pending callbacks for this lookup, and notify // them that the lookup is complete. @@ -1001,15 +1355,8 @@ nsHostResolver::OnLookupComplete(nsHostRecord *rec, nsresult status, AddrInfo *r } delete old_addr_info; - rec->expiration = TimeStamp::NowLoRes(); - if (result) { - rec->expiration += mMaxCacheLifetime; - rec->negative = false; - } - else { - rec->expiration += TimeDuration::FromSeconds(60); /* one minute for negative cache */ - rec->negative = true; - } + rec->negative = !rec->addr_info; + PrepareRecordExpiration(rec); rec->resolving = false; if (rec->usingAnyThread) { @@ -1032,8 +1379,7 @@ nsHostResolver::OnLookupComplete(nsHostRecord *rec, nsresult status, AddrInfo *r if (!head->negative) { // record the age of the entry upon eviction. - TimeDuration age = TimeStamp::NowLoRes() - - (head->expiration - mMaxCacheLifetime); + TimeDuration age = TimeStamp::NowLoRes() - head->mValidStart; Telemetry::Accumulate(Telemetry::DNS_CLEANUP_AGE, static_cast(age.ToSeconds() / 60)); } @@ -1057,6 +1403,21 @@ nsHostResolver::OnLookupComplete(nsHostRecord *rec, nsresult status, AddrInfo *r } } +#if TTL_AVAILABLE + { + MutexAutoLock lock(mLock); + if (!mShutdown && !rec->mGetTtl + && sDnsVariant != DNS_EXP_VARIANT_CONTROL && !rec->resolving) { + LOG(("Issuing second async lookup for TTL for %s.", rec->host)); + rec->flags = + (rec->flags & ~RES_PRIORITY_MEDIUM) | RES_PRIORITY_LOW; + DebugOnly rv = IssueLookup(rec); + NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), + "Could not issue second async lookup for TTL."); + } + } +#endif + NS_RELEASE(rec); } @@ -1142,7 +1503,7 @@ nsHostResolver::ThreadFunc(void *arg) #endif nsHostResolver *resolver = (nsHostResolver *)arg; nsHostRecord *rec; - PRAddrInfo *prai = nullptr; + AddrInfo *ai = nullptr; while (resolver->GetHostToLookup(&rec)) { LOG(("DNS lookup thread - Calling getaddrinfo for host [%s].\n", rec->host)); @@ -1154,47 +1515,37 @@ nsHostResolver::ThreadFunc(void *arg) TimeStamp startTime = TimeStamp::Now(); MOZ_EVENT_TRACER_EXEC(rec, "net::dns::resolve"); +#if TTL_AVAILABLE + bool getTtl = rec->mGetTtl; +#else + bool getTtl = false; +#endif + // We need to remove IPv4 records manually // because PR_GetAddrInfoByName doesn't support PR_AF_INET6. bool disableIPv4 = rec->af == PR_AF_INET6; uint16_t af = disableIPv4 ? PR_AF_UNSPEC : rec->af; - prai = PR_GetAddrInfoByName(rec->host, af, flags); + nsresult status = GetAddrInfo(rec->host, af, flags, &ai, getTtl); #if defined(RES_RETRY_ON_FAILURE) - if (!prai && rs.Reset()) - prai = PR_GetAddrInfoByName(rec->host, af, flags); + if (NS_FAILED(status) && rs.Reset()) { + status = GetAddrInfo(rec->host, af, flags, &ai, getTtl); + } #endif TimeDuration elapsed = TimeStamp::Now() - startTime; uint32_t millis = static_cast(elapsed.ToMilliseconds()); - // convert error code to nsresult - nsresult status; - AddrInfo *ai = nullptr; - if (prai) { - const char *cname = nullptr; - if (rec->flags & RES_CANON_NAME) - cname = PR_GetCanonNameFromAddrInfo(prai); - ai = new AddrInfo(rec->host, prai, disableIPv4, cname); - PR_FreeAddrInfo(prai); - if (ai->mAddresses.isEmpty()) { - delete ai; - ai = nullptr; - } - } - if (ai) { - status = NS_OK; - + if (NS_SUCCEEDED(status)) { Telemetry::Accumulate(!rec->addr_info_gencnt ? Telemetry::DNS_LOOKUP_TIME : Telemetry::DNS_RENEWAL_TIME, millis); } else { - status = NS_ERROR_UNKNOWN_HOST; Telemetry::Accumulate(Telemetry::DNS_FAILED_LOOKUP_TIME, millis); } - // OnLookupComplete may release "rec", log before we lose it. + // OnLookupComplete may release "rec", long before we lose it. LOG(("DNS lookup thread - lookup completed for host [%s]: %s.\n", rec->host, ai ? "success" : "failure: unknown host")); resolver->OnLookupComplete(rec, status, ai); @@ -1204,9 +1555,9 @@ nsHostResolver::ThreadFunc(void *arg) } nsresult -nsHostResolver::Create(uint32_t maxCacheEntries, - uint32_t maxCacheLifetime, - uint32_t lifetimeGracePeriod, +nsHostResolver::Create(uint32_t maxCacheEntries, + uint32_t defaultCacheEntryLifetime, + uint32_t defaultGracePeriod, nsHostResolver **result) { #if defined(PR_LOGGING) @@ -1214,9 +1565,8 @@ nsHostResolver::Create(uint32_t maxCacheEntries, gHostResolverLog = PR_NewLogModule("nsHostResolver"); #endif - nsHostResolver *res = new nsHostResolver(maxCacheEntries, - maxCacheLifetime, - lifetimeGracePeriod); + nsHostResolver *res = new nsHostResolver(maxCacheEntries, defaultCacheEntryLifetime, + defaultGracePeriod); if (!res) return NS_ERROR_OUT_OF_MEMORY; NS_ADDREF(res); @@ -1244,7 +1594,8 @@ CacheEntryEnumerator(PLDHashTable *table, PLDHashEntryHdr *entry, DNSCacheEntries info; info.hostname = rec->host; info.family = rec->af; - info.expiration = (int64_t)(rec->expiration - TimeStamp::NowLoRes()).ToSeconds(); + info.expiration = + (int64_t)(rec->mValidEnd - TimeStamp::NowLoRes()).ToSeconds(); if (info.expiration <= 0) { // We only need valid DNS cache entries return PL_DHASH_NEXT; diff --git a/netwerk/dns/nsHostResolver.h b/netwerk/dns/nsHostResolver.h index 3c60152eab5b..30dbfc568e22 100644 --- a/netwerk/dns/nsHostResolver.h +++ b/netwerk/dns/nsHostResolver.h @@ -16,6 +16,7 @@ #include "nsIDNSListener.h" #include "nsString.h" #include "nsTArray.h" +#include "GetAddrInfo.h" #include "mozilla/net/DNS.h" #include "mozilla/net/DashboardTypes.h" #include "mozilla/TimeStamp.h" @@ -77,9 +78,32 @@ public: (though never for more than 60 seconds), but a use of that negative entry forces an asynchronous refresh. */ - mozilla::TimeStamp expiration; + enum ExpirationStatus { + EXP_VALID, + EXP_GRACE, + EXP_EXPIRED, + }; - bool HasUsableResult(uint16_t queryFlags) const; + ExpirationStatus CheckExpiration(const mozilla::TimeStamp& now) const; + + // When the record began being valid. Used mainly for bookkeeping. + mozilla::TimeStamp mValidStart; + + // When the record is no longer valid (it's time of expiration) + mozilla::TimeStamp mValidEnd; + + // When the record enters its grace period. This must be before mValidEnd. + // If a record is in its grace period (and not expired), it will be used + // but a request to refresh it will be made. + mozilla::TimeStamp mGraceStart; + + // Convenience function for setting the timestamps above (mValidStart, + // mValidEnd, and mGraceStart). valid and grace are durations in seconds. + void SetExpiration(const mozilla::TimeStamp& now, unsigned int valid, + unsigned int grace); + + // Checks if the record is usable (not expired and has a value) + bool HasUsableResult(const mozilla::TimeStamp& now, uint16_t queryFlags = 0) const; // hold addr_info_lock when calling the blacklist functions bool Blacklisted(mozilla::net::NetAddr *query); @@ -88,9 +112,17 @@ public: size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const; + enum DnsPriority { + DNS_PRIORITY_LOW, + DNS_PRIORITY_MEDIUM, + DNS_PRIORITY_HIGH, + }; + static DnsPriority GetPriority(uint16_t aFlags); + private: friend class nsHostResolver; + PRCList callbacks; /* list of callbacks */ bool resolving; /* true if this record is being resolved, which means @@ -101,6 +133,14 @@ private: bool usingAnyThread; /* true if off queue and contributing to mActiveAnyThreadCount */ bool mDoomed; /* explicitly expired */ +#if TTL_AVAILABLE + bool mGetTtl; +#endif + + // The number of times ReportUnusable() has been called in the record's + // lifetime. + uint32_t mBlacklistedCount; + // a list of addresses associated with this record that have been reported // as unusable. the list is kept as a set of strings to make it independent // of gencnt. @@ -172,9 +212,9 @@ public: /** * creates an addref'd instance of a nsHostResolver object. */ - static nsresult Create(uint32_t maxCacheEntries, // zero disables cache - uint32_t maxCacheLifetime, // seconds - uint32_t lifetimeGracePeriod, // seconds + static nsresult Create(uint32_t maxCacheEntries, // zero disables cache + uint32_t defaultCacheEntryLifetime, // seconds + uint32_t defaultGracePeriod, // seconds nsHostResolver **resolver); /** @@ -239,8 +279,9 @@ public: size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const; private: - explicit nsHostResolver(uint32_t maxCacheEntries = 50, uint32_t maxCacheLifetime = 60, - uint32_t lifetimeGracePeriod = 0); + explicit nsHostResolver(uint32_t maxCacheEntries, + uint32_t defaultCacheEntryLifetime, + uint32_t defaultGracePeriod); ~nsHostResolver(); nsresult Init(); @@ -272,8 +313,8 @@ private: }; uint32_t mMaxCacheEntries; - mozilla::TimeDuration mMaxCacheLifetime; // granularity seconds - mozilla::TimeDuration mGracePeriod; // granularity seconds + uint32_t mDefaultCacheLifetime; // granularity seconds + uint32_t mDefaultGracePeriod; // granularity seconds mutable Mutex mLock; // mutable so SizeOfIncludingThis can be const CondVar mIdleThreadCV; uint32_t mNumIdleThreads; @@ -291,6 +332,9 @@ private: PRIntervalTime mLongIdleTimeout; PRIntervalTime mShortIdleTimeout; + // Set the expiration time stamps appropriately. + void PrepareRecordExpiration(nsHostRecord* rec) const; + public: /* * Called by the networking dashboard via the DnsService2 diff --git a/toolkit/components/telemetry/Histograms.json b/toolkit/components/telemetry/Histograms.json index fd8ca8a01348..79728c92044d 100644 --- a/toolkit/components/telemetry/Histograms.json +++ b/toolkit/components/telemetry/Histograms.json @@ -2143,6 +2143,114 @@ "extended_statistics_ok": true, "description": "Time for an unsuccessful DNS OS resolution (msec)" }, + "DNS_CACHE_HIT_VAR_CONTROL_HIGH": { + "expires_in_version": "never", + "kind": "boolean", + "description": "Whether a cached value was available for a lookup. 0 is a miss, 1 is a hit. (variant: DNS_VARIANT_CONTROL, priority: high)" + }, + "DNS_CACHE_HIT_VAR_CONTROL_MEDIUM": { + "expires_in_version": "never", + "kind": "boolean", + "description": "Whether a cached value was available for a lookup. 0 is a miss, 1 is a hit. (variant: DNS_VARIANT_CONTROL, priority: medium)" + }, + "DNS_CACHE_HIT_VAR_CONTROL_LOW": { + "expires_in_version": "never", + "kind": "boolean", + "description": "Whether a cached value was available for a lookup. 0 is a miss, 1 is a hit. (variant: DNS_VARIANT_CONTROL, priority: low)" + }, + "DNS_CACHE_HIT_VAR_TTL_ONLY_HIGH": { + "expires_in_version": "never", + "kind": "boolean", + "description": "Whether a cached value was available for a lookup. 0 is a miss, 1 is a hit. (variant: DNS_VARIANT_TTL_ONLY, priority: high)" + }, + "DNS_CACHE_HIT_VAR_TTL_ONLY_MEDIUM": { + "expires_in_version": "never", + "kind": "boolean", + "description": "Whether a cached value was available for a lookup. 0 is a miss, 1 is a hit. (variant: DNS_VARIANT_TTL_ONLY, priority: medium)" + }, + "DNS_CACHE_HIT_VAR_TTL_ONLY_LOW": { + "expires_in_version": "never", + "kind": "boolean", + "description": "Whether a cached value was available for a lookup. 0 is a miss, 1 is a hit. (variant: DNS_VARIANT_TTL_ONLY, priority: low)" + }, + "DNS_CACHE_HIT_VAR_TTL_PLUS_CONST_GRACE_HIGH": { + "expires_in_version": "never", + "kind": "boolean", + "description": "Whether a cached value was available for a lookup. 0 is a miss, 1 is a hit. (variant: DNS_VARIANT_TTL_PLUS_CONST_GRACE, priority: high)" + }, + "DNS_CACHE_HIT_VAR_TTL_PLUS_CONST_GRACE_MEDIUM": { + "expires_in_version": "never", + "kind": "boolean", + "description": "Whether a cached value was available for a lookup. 0 is a miss, 1 is a hit. (variant: DNS_VARIANT_TTL_PLUS_CONST_GRACE, priority: medium)" + }, + "DNS_CACHE_HIT_VAR_TTL_PLUS_CONST_GRACE_LOW": { + "expires_in_version": "never", + "kind": "boolean", + "description": "Whether a cached value was available for a lookup. 0 is a miss, 1 is a hit. (variant: DNS_VARIANT_TTL_PLUS_CONST_GRACE, priority: low)" + }, + "DNS_BLACKLIST_COUNT_VAR_CONTROL_HIGH": { + "expires_in_version": "never", + "kind": "linear", + "high": 21, + "n_buckets": 20, + "description": "The number of unusable addresses reported for each record (variant: DNS_VARIANT_CONTROL, priority: high)" + }, + "DNS_BLACKLIST_COUNT_VAR_CONTROL_MEDIUM": { + "expires_in_version": "never", + "kind": "linear", + "high": 21, + "n_buckets": 20, + "description": "The number of unusable addresses reported for each record (variant: DNS_VARIANT_CONTROL, priority: medium)" + }, + "DNS_BLACKLIST_COUNT_VAR_CONTROL_LOW": { + "expires_in_version": "never", + "kind": "linear", + "high": 21, + "n_buckets": 20, + "description": "The number of unusable addresses reported for each record (variant: DNS_VARIANT_CONTROL, priority: low)" + }, + "DNS_BLACKLIST_COUNT_VAR_TTL_ONLY_HIGH": { + "expires_in_version": "never", + "kind": "linear", + "high": 21, + "n_buckets": 20, + "description": "The number of unusable addresses reported for each record (variant: DNS_VARIANT_TTL_ONLY, priority: high)" + }, + "DNS_BLACKLIST_COUNT_VAR_TTL_ONLY_MEDIUM": { + "expires_in_version": "never", + "kind": "linear", + "high": 21, + "n_buckets": 20, + "description": "The number of unusable addresses reported for each record (variant: DNS_VARIANT_TTL_ONLY, priority: medium)" + }, + "DNS_BLACKLIST_COUNT_VAR_TTL_ONLY_LOW": { + "expires_in_version": "never", + "kind": "linear", + "high": 21, + "n_buckets": 20, + "description": "The number of unusable addresses reported for each record (variant: DNS_VARIANT_TTL_ONLY, priority: low)" + }, + "DNS_BLACKLIST_COUNT_VAR_TTL_PLUS_CONST_GRACE_HIGH": { + "expires_in_version": "never", + "kind": "linear", + "high": 21, + "n_buckets": 20, + "description": "The number of unusable addresses reported for each record (variant: DNS_VARIANT_TTL_PLUS_CONST_GRACE, priority: high)" + }, + "DNS_BLACKLIST_COUNT_VAR_TTL_PLUS_CONST_GRACE_MEDIUM": { + "expires_in_version": "never", + "kind": "linear", + "high": 21, + "n_buckets": 20, + "description": "The number of unusable addresses reported for each record (variant: DNS_VARIANT_TTL_PLUS_CONST_GRACE, priority: medium)" + }, + "DNS_BLACKLIST_COUNT_VAR_TTL_PLUS_CONST_GRACE_LOW": { + "expires_in_version": "never", + "kind": "linear", + "high": 21, + "n_buckets": 20, + "description": "The number of unusable addresses reported for each record (variant: DNS_VARIANT_TTL_PLUS_CONST_GRACE, priority: low)" + }, "PREDICTOR_PREDICT_ATTEMPTS": { "expires_in_version": "never", "kind": "exponential", From ec15b5739786eb254d5c56cc5efbdcabbe2e189c Mon Sep 17 00:00:00 2001 From: Steffen Michalke Date: Mon, 15 Sep 2014 07:16:00 -0700 Subject: [PATCH 030/114] Bug 1067377 - Use VPX_ prefixed defines in VP8TrackEncoder. r=giles The unprefixed IMG_FMT and PLANE defines from libvpx 0.9.x are disabled by default subsequent to the 1.3.0 release. --- content/media/encoder/VP8TrackEncoder.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/content/media/encoder/VP8TrackEncoder.cpp b/content/media/encoder/VP8TrackEncoder.cpp index 452821ce8287..ede21c5dc86b 100644 --- a/content/media/encoder/VP8TrackEncoder.cpp +++ b/content/media/encoder/VP8TrackEncoder.cpp @@ -85,7 +85,7 @@ VP8TrackEncoder::Init(int32_t aWidth, int32_t aHeight, int32_t aDisplayWidth, // Creating a wrapper to the image - setting image data to NULL. Actual // pointer will be set in encode. Setting align to 1, as it is meaningless // (actual memory is not allocated). - vpx_img_wrap(mVPXImageWrapper, IMG_FMT_I420, + vpx_img_wrap(mVPXImageWrapper, VPX_IMG_FMT_I420, mFrameWidth, mFrameHeight, 1, nullptr); config.g_w = mFrameWidth; @@ -279,9 +279,9 @@ nsresult VP8TrackEncoder::PrepareRawFrame(VideoChunk &aChunk) const PlanarYCbCrImage::Data *data = yuv->GetData(); if (isYUV420(data) && !data->mCbSkip) { // 420 planar - mVPXImageWrapper->planes[PLANE_Y] = data->mYChannel; - mVPXImageWrapper->planes[PLANE_U] = data->mCbChannel; - mVPXImageWrapper->planes[PLANE_V] = data->mCrChannel; + mVPXImageWrapper->planes[VPX_PLANE_Y] = data->mYChannel; + mVPXImageWrapper->planes[VPX_PLANE_U] = data->mCbChannel; + mVPXImageWrapper->planes[VPX_PLANE_V] = data->mCrChannel; mVPXImageWrapper->stride[VPX_PLANE_Y] = data->mYStride; mVPXImageWrapper->stride[VPX_PLANE_U] = data->mCbCrStride; mVPXImageWrapper->stride[VPX_PLANE_V] = data->mCbCrStride; @@ -337,9 +337,9 @@ nsresult VP8TrackEncoder::PrepareRawFrame(VideoChunk &aChunk) return NS_ERROR_NOT_IMPLEMENTED; } - mVPXImageWrapper->planes[PLANE_Y] = y; - mVPXImageWrapper->planes[PLANE_U] = cb; - mVPXImageWrapper->planes[PLANE_V] = cr; + mVPXImageWrapper->planes[VPX_PLANE_Y] = y; + mVPXImageWrapper->planes[VPX_PLANE_U] = cb; + mVPXImageWrapper->planes[VPX_PLANE_V] = cr; mVPXImageWrapper->stride[VPX_PLANE_Y] = mFrameWidth; mVPXImageWrapper->stride[VPX_PLANE_U] = halfWidth; mVPXImageWrapper->stride[VPX_PLANE_V] = halfWidth; From 714eb24d2ad1bbcd3790c51e050aecc38e0e89b7 Mon Sep 17 00:00:00 2001 From: Steffen Michalke Date: Mon, 15 Sep 2014 07:17:00 -0700 Subject: [PATCH 031/114] Bug 1067377 - Use VPX_ prefixed defines in webrtc. r=rjesup --- .../trunk/webrtc/modules/video_coding/codecs/vp8/vp8_impl.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/media/webrtc/trunk/webrtc/modules/video_coding/codecs/vp8/vp8_impl.cc b/media/webrtc/trunk/webrtc/modules/video_coding/codecs/vp8/vp8_impl.cc index d9c3a2244028..75195ae76c3a 100644 --- a/media/webrtc/trunk/webrtc/modules/video_coding/codecs/vp8/vp8_impl.cc +++ b/media/webrtc/trunk/webrtc/modules/video_coding/codecs/vp8/vp8_impl.cc @@ -180,7 +180,7 @@ int VP8EncoderImpl::InitEncode(const VideoCodec* inst, // Creating a wrapper to the image - setting image data to NULL. Actual // pointer will be set in encode. Setting align to 1, as it is meaningless // (actual memory is not allocated). - raw_ = vpx_img_wrap(NULL, IMG_FMT_I420, codec_.width, codec_.height, + raw_ = vpx_img_wrap(NULL, VPX_IMG_FMT_I420, codec_.width, codec_.height, 1, NULL); // populate encoder configuration with default values if (vpx_codec_enc_config_default(vpx_codec_vp8_cx(), config_, 0)) { From f6ec236298fae162aab7cf24a8c6ce5d84bd098b Mon Sep 17 00:00:00 2001 From: Ralph Giles Date: Fri, 19 Sep 2014 15:01:00 -0700 Subject: [PATCH 032/114] Bug 1067377 - Use VPX_ prefixed defines in WebMReader. r=kinetik --- content/media/webm/WebMReader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/media/webm/WebMReader.cpp b/content/media/webm/WebMReader.cpp index b5ef14f0a162..8d7c40948057 100644 --- a/content/media/webm/WebMReader.cpp +++ b/content/media/webm/WebMReader.cpp @@ -925,7 +925,7 @@ bool WebMReader::DecodeVideoFrame(bool &aKeyframeSkip, vpx_image_t *img; while ((img = vpx_codec_get_frame(&mVPX, &iter))) { - NS_ASSERTION(img->fmt == IMG_FMT_I420, "WebM image format is not I420"); + NS_ASSERTION(img->fmt == VPX_IMG_FMT_I420, "WebM image format is not I420"); // Chroma shifts are rounded down as per the decoding examples in the VP8 SDK VideoData::YCbCrBuffer b; From ca7c8b601b12e76d5e738b85dae6a82e0dfd5313 Mon Sep 17 00:00:00 2001 From: ziyunfei <446240525@qq.com> Date: Thu, 18 Sep 2014 17:22:05 +0800 Subject: [PATCH 033/114] Bug 1069063 - Implement Array.prototype.contains. r=till --HG-- rename : js/src/tests/ecma_6/Array/browser.js => js/src/tests/ecma_7/Array/browser.js rename : js/src/tests/ecma_6/Array/browser.js => js/src/tests/ecma_7/Array/shell.js rename : js/src/tests/ecma_6/browser.js => js/src/tests/ecma_7/browser.js rename : js/src/tests/ecma_6/shell.js => js/src/tests/ecma_7/shell.js --- js/src/builtin/Array.js | 50 +++++++ js/src/builtin/Utilities.js | 5 + js/src/jsarray.cpp | 6 + js/src/tests/ecma_7/Array/browser.js | 0 js/src/tests/ecma_7/Array/contains.js | 61 ++++++++ js/src/tests/ecma_7/Array/shell.js | 0 js/src/tests/ecma_7/browser.js | 0 js/src/tests/ecma_7/shell.js | 197 ++++++++++++++++++++++++++ 8 files changed, 319 insertions(+) create mode 100644 js/src/tests/ecma_7/Array/browser.js create mode 100644 js/src/tests/ecma_7/Array/contains.js create mode 100644 js/src/tests/ecma_7/Array/shell.js create mode 100644 js/src/tests/ecma_7/browser.js create mode 100644 js/src/tests/ecma_7/shell.js diff --git a/js/src/builtin/Array.js b/js/src/builtin/Array.js index eaaf2c3b0eb2..fbfec82aa5d5 100644 --- a/js/src/builtin/Array.js +++ b/js/src/builtin/Array.js @@ -581,6 +581,56 @@ function ArrayFill(value, start = 0, end = undefined) { return O; } +// Proposed for ES7: +// https://github.com/domenic/Array.prototype.contains/blob/master/spec.md +function ArrayContains(searchElement, fromIndex = 0) { + // Steps 1-2. + var O = ToObject(this); + + // Steps 3-4. + var len = ToLength(O.length); + + // Step 5. + if (len === 0) + return false; + + // Steps 6-7. + var n = ToInteger(fromIndex); + + // Step 8. + if (n >= len) + return false; + + // Step 9. + var k; + if (n >= 0) + k = n; + // Step 10. + else { + // Step a. + k = len + n; + // Step b. + if (k < 0) + k = 0; + } + + // Step 11. + while (k < len) { + // Steps a-b. + var elementK = O[k]; + + // Step c. + if (SameValueZero(searchElement, elementK)) + return true; + + // Step d. + k++; + } + + // Step 12. + return false; +} + #define ARRAY_ITERATOR_SLOT_ITERATED_OBJECT 0 #define ARRAY_ITERATOR_SLOT_NEXT_INDEX 1 #define ARRAY_ITERATOR_SLOT_ITEM_KIND 2 diff --git a/js/src/builtin/Utilities.js b/js/src/builtin/Utilities.js index fae2a5b68650..237378f4617c 100644 --- a/js/src/builtin/Utilities.js +++ b/js/src/builtin/Utilities.js @@ -156,6 +156,11 @@ function ToLength(v) { return v < 0x1fffffffffffff ? v : 0x1fffffffffffff; } +/* Spec: ECMAScript Draft, 6 edition Aug 24, 2014, 7.2.4 */ +function SameValueZero(x, y) { + return x !== x && y !== y || x === y +} + /********** Testing code **********/ #ifdef ENABLE_PARALLEL_JS diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index a191279f2b77..8a3e729ffb5c 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -3023,6 +3023,12 @@ static const JSFunctionSpec array_methods[] = { JS_SELF_HOSTED_FN("@@iterator", "ArrayValues", 0,0), JS_SELF_HOSTED_FN("entries", "ArrayEntries", 0,0), JS_SELF_HOSTED_FN("keys", "ArrayKeys", 0,0), + + /* ES7 additions */ +#ifdef NIGHTLY_BUILD + JS_SELF_HOSTED_FN("contains", "ArrayContains", 2,0), +#endif + JS_FS_END }; diff --git a/js/src/tests/ecma_7/Array/browser.js b/js/src/tests/ecma_7/Array/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/ecma_7/Array/contains.js b/js/src/tests/ecma_7/Array/contains.js new file mode 100644 index 000000000000..90746a7fe090 --- /dev/null +++ b/js/src/tests/ecma_7/Array/contains.js @@ -0,0 +1,61 @@ +/* + * Any copyright is dedicated to the Public Domain. + * https://creativecommons.org/publicdomain/zero/1.0/ + */ + +var BUGNUMBER = 1069063; +var summary = "Implement Array.prototype.contains"; + +print(BUGNUMBER + ": " + summary); + +if ('contains' in Array.prototype) { + assertEq(typeof [].contains, "function"); + assertEq([].contains.length, 1); + + assertTrue([1, 2, 3].contains(2)); + assertTrue([1,,2].contains(2)); + assertTrue([1, 2, 3].contains(2, 1)); + assertTrue([1, 2, 3].contains(2, -2)); + assertTrue([1, 2, 3].contains(2, -100)); + assertTrue([Object, Function, Array].contains(Function)); + assertTrue([-0].contains(0)); + assertTrue([NaN].contains(NaN)); + assertTrue([,].contains()); + assertTrue(staticContains("123", "2")); + assertTrue(staticContains({length: 3, 1: 2}, 2)); + assertTrue(staticContains({length: 3, 1: 2, get 3(){throw ""}}, 2)); + assertTrue(staticContains({length: 3, get 1() {return 2}}, 2)); + assertTrue(staticContains({__proto__: {1: 2}, length: 3}, 2)); + assertTrue(staticContains(new Proxy([1], {get(){return 2}}), 2)); + + assertFalse([1, 2, 3].contains("2")); + assertFalse([1, 2, 3].contains(2, 2)); + assertFalse([1, 2, 3].contains(2, -1)); + assertFalse([undefined].contains(NaN)); + assertFalse([{}].contains({})); + assertFalse(staticContains({length: 3, 1: 2}, 2, 2)); + assertFalse(staticContains({length: 3, get 0(){delete this[1]}, 1: 2}, 2)); + assertFalse(staticContains({length: -100, 0: 1}, 1)); + + assertThrowsInstanceOf(() => staticContains(), TypeError); + assertThrowsInstanceOf(() => staticContains(null), TypeError); + assertThrowsInstanceOf(() => staticContains({get length(){throw TypeError()}}), TypeError); + assertThrowsInstanceOf(() => staticContains({length: 3, get 1() {throw TypeError()}}, 2), TypeError); + assertThrowsInstanceOf(() => staticContains({__proto__: {get 1() {throw TypeError()}}, length: 3}, 2), TypeError); + assertThrowsInstanceOf(() => staticContains(new Proxy([1], {get(){throw TypeError()}})), TypeError); +} + +function assertTrue(v){ + assertEq(v, true) +} + +function assertFalse(v){ + assertEq(v, false) +} + +function staticContains(o, v, f){ + return [].contains.call(o, v, f) +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/ecma_7/Array/shell.js b/js/src/tests/ecma_7/Array/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/ecma_7/browser.js b/js/src/tests/ecma_7/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/ecma_7/shell.js b/js/src/tests/ecma_7/shell.js new file mode 100644 index 000000000000..8334db7443a7 --- /dev/null +++ b/js/src/tests/ecma_7/shell.js @@ -0,0 +1,197 @@ +/* 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/. */ + + +if (typeof assertThrowsInstanceOf === 'undefined') { + var assertThrowsInstanceOf = function assertThrowsInstanceOf(f, ctor, msg) { + var fullmsg; + try { + f(); + } catch (exc) { + if (exc instanceof ctor) + return; + fullmsg = "Assertion failed: expected exception " + ctor.name + ", got " + exc; + } + if (fullmsg === undefined) + fullmsg = "Assertion failed: expected exception " + ctor.name + ", no exception thrown"; + if (msg !== undefined) + fullmsg += " - " + msg; + throw new Error(fullmsg); + }; +} + +if (typeof assertThrowsValue === 'undefined') { + var assertThrowsValue = function assertThrowsValue(f, val, msg) { + var fullmsg; + try { + f(); + } catch (exc) { + if ((exc === val) === (val === val) && (val !== 0 || 1 / exc === 1 / val)) + return; + fullmsg = "Assertion failed: expected exception " + val + ", got " + exc; + } + if (fullmsg === undefined) + fullmsg = "Assertion failed: expected exception " + val + ", no exception thrown"; + if (msg !== undefined) + fullmsg += " - " + msg; + throw new Error(fullmsg); + }; +} + +if (typeof assertDeepEq === 'undefined') { + var assertDeepEq = (function(){ + var call = Function.prototype.call, + Map_ = Map, + Error_ = Error, + Map_has = call.bind(Map.prototype.has), + Map_get = call.bind(Map.prototype.get), + Map_set = call.bind(Map.prototype.set), + Object_toString = call.bind(Object.prototype.toString), + Function_toString = call.bind(Function.prototype.toString), + Object_getPrototypeOf = Object.getPrototypeOf, + Object_hasOwnProperty = call.bind(Object.prototype.hasOwnProperty), + Object_getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor, + Object_isExtensible = Object.isExtensible, + Object_getOwnPropertyNames = Object.getOwnPropertyNames, + uneval_ = uneval; + + // Return true iff ES6 Type(v) isn't Object. + // Note that `typeof document.all === "undefined"`. + function isPrimitive(v) { + return (v === null || + v === undefined || + typeof v === "boolean" || + typeof v === "number" || + typeof v === "string" || + typeof v === "symbol"); + } + + function assertSameValue(a, b, msg) { + try { + assertEq(a, b); + } catch (exc) { + throw Error_(exc.message + (msg ? " " + msg : "")); + } + } + + function assertSameClass(a, b, msg) { + var ac = Object_toString(a), bc = Object_toString(b); + assertSameValue(ac, bc, msg); + switch (ac) { + case "[object Function]": + assertSameValue(Function_toString(a), Function_toString(b), msg); + } + } + + function at(prevmsg, segment) { + return prevmsg ? prevmsg + segment : "at _" + segment; + } + + // Assert that the arguments a and b are thoroughly structurally equivalent. + // + // For the sake of speed, we cut a corner: + // var x = {}, y = {}, ax = [x]; + // assertDeepEq([ax, x], [ax, y]); // passes (?!) + // + // Technically this should fail, since the two object graphs are different. + // (The graph of [ax, y] contains one more object than the graph of [ax, x].) + // + // To get technically correct behavior, pass {strictEquivalence: true}. + // This is slower because we have to walk the entire graph, and Object.prototype + // is big. + // + return function assertDeepEq(a, b, options) { + var strictEquivalence = options ? options.strictEquivalence : false; + + function assertSameProto(a, b, msg) { + check(Object_getPrototypeOf(a), Object_getPrototypeOf(b), at(msg, ".__proto__")); + } + + function failPropList(na, nb, msg) { + throw Error_("got own properties " + uneval_(na) + ", expected " + uneval_(nb) + + (msg ? " " + msg : "")); + } + + function assertSameProps(a, b, msg) { + var na = Object_getOwnPropertyNames(a), + nb = Object_getOwnPropertyNames(b); + if (na.length !== nb.length) + failPropList(na, nb, msg); + for (var i = 0; i < na.length; i++) { + var name = na[i]; + if (name !== nb[i]) + failPropList(na, nb, msg); + var da = Object_getOwnPropertyDescriptor(a, name), + db = Object_getOwnPropertyDescriptor(b, name); + var pmsg = at(msg, /^[_$A-Za-z0-9]+$/.test(name) + ? /0|[1-9][0-9]*/.test(name) ? "[" + name + "]" : "." + name + : "[" + uneval_(name) + "]"); + assertSameValue(da.configurable, db.configurable, at(pmsg, ".[[Configurable]]")); + assertSameValue(da.enumerable, db.enumerable, at(pmsg, ".[[Enumerable]]")); + if (Object_hasOwnProperty(da, "value")) { + if (!Object_hasOwnProperty(db, "value")) + throw Error_("got data property, expected accessor property" + pmsg); + check(da.value, db.value, pmsg); + } else { + if (Object_hasOwnProperty(db, "value")) + throw Error_("got accessor property, expected data property" + pmsg); + check(da.get, db.get, at(pmsg, ".[[Get]]")); + check(da.set, db.set, at(pmsg, ".[[Set]]")); + } + } + }; + + var ab = Map_(); + var bpath = Map_(); + + function check(a, b, path) { + if (typeof a === "symbol") { + // Symbols are primitives, but they have identity. + // Symbol("x") !== Symbol("x") but + // assertDeepEq(Symbol("x"), Symbol("x")) should pass. + if (typeof b !== "symbol") { + throw Error_("got " + uneval_(a) + ", expected " + uneval_(b) + " " + path); + } else if (uneval_(a) !== uneval_(b)) { + // We lamely use uneval_ to distinguish well-known symbols + // from user-created symbols. The standard doesn't offer + // a convenient way to do it. + throw Error_("got " + uneval_(a) + ", expected " + uneval_(b) + " " + path); + } else if (Map_has(ab, a)) { + assertSameValue(Map_get(ab, a), b, path); + } else if (Map_has(bpath, b)) { + var bPrevPath = Map_get(bpath, b) || "_"; + throw Error_("got distinct symbols " + at(path, "") + " and " + + at(bPrevPath, "") + ", expected the same symbol both places"); + } else { + Map_set(ab, a, b); + Map_set(bpath, b, path); + } + } else if (isPrimitive(a)) { + assertSameValue(a, b, path); + } else if (isPrimitive(b)) { + throw Error_("got " + Object_toString(a) + ", expected " + uneval_(b) + " " + path); + } else if (Map_has(ab, a)) { + assertSameValue(Map_get(ab, a), b, path); + } else if (Map_has(bpath, b)) { + var bPrevPath = Map_get(bpath, b) || "_"; + throw Error_("got distinct objects " + at(path, "") + " and " + at(bPrevPath, "") + + ", expected the same object both places"); + } else { + Map_set(ab, a, b); + Map_set(bpath, b, path); + if (a !== b || strictEquivalence) { + assertSameClass(a, b, path); + assertSameProto(a, b, path); + assertSameProps(a, b, path); + assertSameValue(Object_isExtensible(a), + Object_isExtensible(b), + at(path, ".[[Extensible]]")); + } + } + } + + check(a, b, ""); + }; + })(); +} From d47aa16266726fb55069066afe142e484d59af69 Mon Sep 17 00:00:00 2001 From: ziyunfei <446240525@qq.com> Date: Thu, 4 Sep 2014 21:08:33 +0800 Subject: [PATCH 034/114] Bug 1062860 - Object.isSealed() should return true when given primitive values as input. r=till --- js/src/builtin/Object.cpp | 16 ++++++++++------ js/src/tests/ecma_6/Object/isSealed.js | 21 +++++++++++++++++++++ 2 files changed, 31 insertions(+), 6 deletions(-) create mode 100644 js/src/tests/ecma_6/Object/isSealed.js diff --git a/js/src/builtin/Object.cpp b/js/src/builtin/Object.cpp index 748393dd8c70..734ef4c38d65 100644 --- a/js/src/builtin/Object.cpp +++ b/js/src/builtin/Object.cpp @@ -1094,17 +1094,21 @@ obj_seal(JSContext *cx, unsigned argc, Value *vp) return JSObject::seal(cx, obj); } +// ES6 draft rev27 (2014/08/24) 19.1.2.13 Object.isSealed(O) static bool obj_isSealed(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); - RootedObject obj(cx); - if (!GetFirstArgumentAsObject(cx, args, "Object.isSealed", &obj)) - return false; - bool sealed; - if (!JSObject::isSealed(cx, obj, &sealed)) - return false; + // step 1 + bool sealed = true; + + // step 2 + if (args.get(0).isObject()) { + RootedObject obj(cx, &args.get(0).toObject()); + if (!JSObject::isSealed(cx, obj, &sealed)) + return false; + } args.rval().setBoolean(sealed); return true; } diff --git a/js/src/tests/ecma_6/Object/isSealed.js b/js/src/tests/ecma_6/Object/isSealed.js new file mode 100644 index 000000000000..cd363a87e111 --- /dev/null +++ b/js/src/tests/ecma_6/Object/isSealed.js @@ -0,0 +1,21 @@ +/* + * Any copyright is dedicated to the Public Domain. + * https://creativecommons.org/publicdomain/zero/1.0/ + */ + +var BUGNUMBER = 1062860; +var summary = "Object.isSealed() should return true when given primitive values as input"; + +print(BUGNUMBER + ": " + summary); +assertEq(Object.isSealed(), true); +assertEq(Object.isSealed(undefined), true); +assertEq(Object.isSealed(null), true); +assertEq(Object.isSealed(1), true); +assertEq(Object.isSealed("foo"), true); +assertEq(Object.isSealed(true), true); +if (typeof Symbol === "function") { + assertEq(Object.isSealed(Symbol()), true); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); From 279596b4fce6cc6fadfc9f361d0152cbe46e5efb Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Sat, 20 Sep 2014 22:27:16 -0400 Subject: [PATCH 035/114] Bug 1068268 - Properly set the next-sibling pointer of an APZC when it is a child of a multi-layer APZ. r=botond --- gfx/layers/apz/src/APZCTreeManager.cpp | 21 ++++++++------ gfx/layers/apz/src/APZCTreeManager.h | 2 +- gfx/layers/apz/src/AsyncPanZoomController.h | 8 ++++++ .../gtest/TestAsyncPanZoomController.cpp | 28 +++++++++++++++++++ 4 files changed, 50 insertions(+), 9 deletions(-) diff --git a/gfx/layers/apz/src/APZCTreeManager.cpp b/gfx/layers/apz/src/APZCTreeManager.cpp index b49e4abf39dc..07d8bf2e4ef2 100644 --- a/gfx/layers/apz/src/APZCTreeManager.cpp +++ b/gfx/layers/apz/src/APZCTreeManager.cpp @@ -225,7 +225,7 @@ APZCTreeManager::PrepareAPZCForLayer(const LayerMetricsWrapper& aLayer, uint64_t aLayersId, const gfx::Matrix4x4& aAncestorTransform, const nsIntRegion& aObscured, - AsyncPanZoomController*& aOutParent, + AsyncPanZoomController* aParent, AsyncPanZoomController* aNextSibling, TreeBuildingState& aState) { @@ -321,9 +321,10 @@ APZCTreeManager::PrepareAPZCForLayer(const LayerMetricsWrapper& aLayer, // Bind the APZC instance into the tree of APZCs if (aNextSibling) { aNextSibling->SetPrevSibling(apzc); - } else if (aOutParent) { - aOutParent->SetLastChild(apzc); + } else if (aParent) { + aParent->SetLastChild(apzc); } else { + MOZ_ASSERT(!mRootApzc); mRootApzc = apzc; apzc->MakeRoot(); } @@ -379,9 +380,6 @@ APZCTreeManager::PrepareAPZCForLayer(const LayerMetricsWrapper& aLayer, APZCTM_LOG("Adding region %s to visible region of APZC %p\n", Stringify(unobscured).c_str(), apzc); } - // Let this apzc be the parent of other controllers when we recurse downwards - aOutParent = apzc; - return apzc; } @@ -438,8 +436,15 @@ APZCTreeManager::UpdatePanZoomControllerTree(TreeBuildingState& aState, } // If there's no APZC at this level, any APZCs for our child layers will - // have our siblings as siblings. - AsyncPanZoomController* next = apzc ? nullptr : aNextSibling; + // have our siblings as their siblings, and our parent as their parent. + AsyncPanZoomController* next = aNextSibling; + if (apzc) { + // Otherwise, use this APZC as the parent going downwards, and start off + // with its first child as the next sibling + aParent = apzc; + next = apzc->GetFirstChild(); + } + for (LayerMetricsWrapper child = aLayer.GetLastChild(); child; child = child.GetPrevSibling()) { gfx::TreeAutoIndent indent(mApzcTreeLog); next = UpdatePanZoomControllerTree(aState, child, childLayersId, diff --git a/gfx/layers/apz/src/APZCTreeManager.h b/gfx/layers/apz/src/APZCTreeManager.h index c0f749609d99..ae0c61420dc7 100644 --- a/gfx/layers/apz/src/APZCTreeManager.h +++ b/gfx/layers/apz/src/APZCTreeManager.h @@ -386,7 +386,7 @@ private: uint64_t aLayersId, const gfx::Matrix4x4& aAncestorTransform, const nsIntRegion& aObscured, - AsyncPanZoomController*& aOutParent, + AsyncPanZoomController* aParent, AsyncPanZoomController* aNextSibling, TreeBuildingState& aState); diff --git a/gfx/layers/apz/src/AsyncPanZoomController.h b/gfx/layers/apz/src/AsyncPanZoomController.h index 55deaed4af36..0da6d3984ee8 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.h +++ b/gfx/layers/apz/src/AsyncPanZoomController.h @@ -952,6 +952,14 @@ public: AsyncPanZoomController* GetPrevSibling() const { return mPrevSibling; } AsyncPanZoomController* GetParent() const { return mParent; } + AsyncPanZoomController* GetFirstChild() const { + AsyncPanZoomController* child = GetLastChild(); + while (child && child->GetPrevSibling()) { + child = child->GetPrevSibling(); + } + return child; + } + /* Returns true if there is no APZC higher in the tree with the same * layers id. */ diff --git a/gfx/tests/gtest/TestAsyncPanZoomController.cpp b/gfx/tests/gtest/TestAsyncPanZoomController.cpp index deca73fae644..c9f0964e3688 100644 --- a/gfx/tests/gtest/TestAsyncPanZoomController.cpp +++ b/gfx/tests/gtest/TestAsyncPanZoomController.cpp @@ -1535,6 +1535,17 @@ protected: }; root = CreateLayerTree(layerTreeSyntax, layerVisibleRegion, nullptr, lm, layers); } + + void CreatePotentiallyLeakingTree() { + const char* layerTreeSyntax = "c(c(c(c))c(c(c)))"; + // LayerID 0 1 2 3 4 5 6 + root = CreateLayerTree(layerTreeSyntax, nullptr, nullptr, lm, layers); + SetScrollableFrameMetrics(layers[0], FrameMetrics::START_SCROLL_ID); + SetScrollableFrameMetrics(layers[2], FrameMetrics::START_SCROLL_ID + 1); + SetScrollableFrameMetrics(layers[5], FrameMetrics::START_SCROLL_ID + 1); + SetScrollableFrameMetrics(layers[3], FrameMetrics::START_SCROLL_ID + 2); + SetScrollableFrameMetrics(layers[6], FrameMetrics::START_SCROLL_ID + 3); + } }; class APZHitTestingTester : public APZCTreeManagerTester { @@ -1823,6 +1834,23 @@ TEST_F(APZCTreeManagerTester, ScrollableThebesLayers) { EXPECT_EQ(ApzcOf(layers[1]), ApzcOf(layers[2])); } +TEST_F(APZCTreeManagerTester, Bug1068268) { + CreatePotentiallyLeakingTree(); + ScopedLayerTreeRegistration registration(0, root, mcc); + + manager->UpdatePanZoomControllerTree(nullptr, root, false, 0, 0); + EXPECT_EQ(ApzcOf(layers[2]), ApzcOf(layers[0])->GetLastChild()); + EXPECT_EQ(ApzcOf(layers[2]), ApzcOf(layers[0])->GetFirstChild()); + EXPECT_EQ(ApzcOf(layers[0]), ApzcOf(layers[2])->GetParent()); + EXPECT_EQ(ApzcOf(layers[2]), ApzcOf(layers[5])); + + EXPECT_EQ(ApzcOf(layers[3]), ApzcOf(layers[2])->GetFirstChild()); + EXPECT_EQ(ApzcOf(layers[6]), ApzcOf(layers[2])->GetLastChild()); + EXPECT_EQ(ApzcOf(layers[3]), ApzcOf(layers[6])->GetPrevSibling()); + EXPECT_EQ(ApzcOf(layers[2]), ApzcOf(layers[3])->GetParent()); + EXPECT_EQ(ApzcOf(layers[2]), ApzcOf(layers[6])->GetParent()); +} + TEST_F(APZHitTestingTester, ComplexMultiLayerTree) { CreateComplexMultiLayerTree(); ScopedLayerTreeRegistration registration(0, root, mcc); From 0618623a77343e6f010e8efe916fd02fe746d9a5 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Sat, 20 Sep 2014 22:27:17 -0400 Subject: [PATCH 036/114] Bug 1068268 - Remove redundant MOZ_COUNT_[CD]TOR macros in AsyncPanZoomController. r=botond --- gfx/layers/apz/src/AsyncPanZoomController.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp index 715cfe41c377..f58e8a64afff 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -55,7 +55,6 @@ #include "nsCOMPtr.h" // for already_AddRefed #include "nsDebug.h" // for NS_WARNING #include "nsIDOMWindowUtils.h" // for nsIDOMWindowUtils -#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc #include "nsMathUtils.h" // for NS_hypot #include "nsPoint.h" // for nsIntPoint #include "nsStyleConsts.h" @@ -886,15 +885,12 @@ AsyncPanZoomController::AsyncPanZoomController(uint64_t aLayersId, mSharedLock(nullptr), mAsyncTransformAppliedToContent(false) { - MOZ_COUNT_CTOR(AsyncPanZoomController); - if (aGestures == USE_GESTURE_DETECTOR) { mGestureEventListener = new GestureEventListener(this); } } AsyncPanZoomController::~AsyncPanZoomController() { - MOZ_COUNT_DTOR(AsyncPanZoomController); } PCompositorParent* From 6857449a63817ff727fabaa51a33d8facc77a373 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Sat, 20 Sep 2014 22:27:17 -0400 Subject: [PATCH 037/114] Bug 1068268 - Remove unnecessary forward-declare. r=botond --- layout/ipc/RenderFrameParent.h | 1 - 1 file changed, 1 deletion(-) diff --git a/layout/ipc/RenderFrameParent.h b/layout/ipc/RenderFrameParent.h index 9528a5045ca2..f53cd1ad770a 100644 --- a/layout/ipc/RenderFrameParent.h +++ b/layout/ipc/RenderFrameParent.h @@ -24,7 +24,6 @@ class InputEvent; namespace layers { class APZCTreeManager; -class GestureEventListener; class TargetConfig; class LayerTransactionParent; struct TextureFactoryIdentifier; From 1276bd7e4c52cba2017fffb6c829d7ff6f652cd9 Mon Sep 17 00:00:00 2001 From: Phil Ringnalda Date: Sat, 20 Sep 2014 20:53:35 -0700 Subject: [PATCH 038/114] Backed out 2 changesets (bug 1069063, bug 1062860) for mochitest-chrome and jsreftest bustage CLOSED TREE Backed out changeset 7f06ae718751 (bug 1062860) Backed out changeset 2c92e43e29d8 (bug 1069063) --- js/src/builtin/Array.js | 50 ------- js/src/builtin/Object.cpp | 16 +- js/src/builtin/Utilities.js | 5 - js/src/jsarray.cpp | 6 - js/src/tests/ecma_6/Object/isSealed.js | 21 --- js/src/tests/ecma_7/Array/browser.js | 0 js/src/tests/ecma_7/Array/contains.js | 61 -------- js/src/tests/ecma_7/Array/shell.js | 0 js/src/tests/ecma_7/browser.js | 0 js/src/tests/ecma_7/shell.js | 197 ------------------------- 10 files changed, 6 insertions(+), 350 deletions(-) delete mode 100644 js/src/tests/ecma_6/Object/isSealed.js delete mode 100644 js/src/tests/ecma_7/Array/browser.js delete mode 100644 js/src/tests/ecma_7/Array/contains.js delete mode 100644 js/src/tests/ecma_7/Array/shell.js delete mode 100644 js/src/tests/ecma_7/browser.js delete mode 100644 js/src/tests/ecma_7/shell.js diff --git a/js/src/builtin/Array.js b/js/src/builtin/Array.js index fbfec82aa5d5..eaaf2c3b0eb2 100644 --- a/js/src/builtin/Array.js +++ b/js/src/builtin/Array.js @@ -581,56 +581,6 @@ function ArrayFill(value, start = 0, end = undefined) { return O; } -// Proposed for ES7: -// https://github.com/domenic/Array.prototype.contains/blob/master/spec.md -function ArrayContains(searchElement, fromIndex = 0) { - // Steps 1-2. - var O = ToObject(this); - - // Steps 3-4. - var len = ToLength(O.length); - - // Step 5. - if (len === 0) - return false; - - // Steps 6-7. - var n = ToInteger(fromIndex); - - // Step 8. - if (n >= len) - return false; - - // Step 9. - var k; - if (n >= 0) - k = n; - // Step 10. - else { - // Step a. - k = len + n; - // Step b. - if (k < 0) - k = 0; - } - - // Step 11. - while (k < len) { - // Steps a-b. - var elementK = O[k]; - - // Step c. - if (SameValueZero(searchElement, elementK)) - return true; - - // Step d. - k++; - } - - // Step 12. - return false; -} - #define ARRAY_ITERATOR_SLOT_ITERATED_OBJECT 0 #define ARRAY_ITERATOR_SLOT_NEXT_INDEX 1 #define ARRAY_ITERATOR_SLOT_ITEM_KIND 2 diff --git a/js/src/builtin/Object.cpp b/js/src/builtin/Object.cpp index 734ef4c38d65..748393dd8c70 100644 --- a/js/src/builtin/Object.cpp +++ b/js/src/builtin/Object.cpp @@ -1094,21 +1094,17 @@ obj_seal(JSContext *cx, unsigned argc, Value *vp) return JSObject::seal(cx, obj); } -// ES6 draft rev27 (2014/08/24) 19.1.2.13 Object.isSealed(O) static bool obj_isSealed(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); + RootedObject obj(cx); + if (!GetFirstArgumentAsObject(cx, args, "Object.isSealed", &obj)) + return false; - // step 1 - bool sealed = true; - - // step 2 - if (args.get(0).isObject()) { - RootedObject obj(cx, &args.get(0).toObject()); - if (!JSObject::isSealed(cx, obj, &sealed)) - return false; - } + bool sealed; + if (!JSObject::isSealed(cx, obj, &sealed)) + return false; args.rval().setBoolean(sealed); return true; } diff --git a/js/src/builtin/Utilities.js b/js/src/builtin/Utilities.js index 237378f4617c..fae2a5b68650 100644 --- a/js/src/builtin/Utilities.js +++ b/js/src/builtin/Utilities.js @@ -156,11 +156,6 @@ function ToLength(v) { return v < 0x1fffffffffffff ? v : 0x1fffffffffffff; } -/* Spec: ECMAScript Draft, 6 edition Aug 24, 2014, 7.2.4 */ -function SameValueZero(x, y) { - return x !== x && y !== y || x === y -} - /********** Testing code **********/ #ifdef ENABLE_PARALLEL_JS diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index 8a3e729ffb5c..a191279f2b77 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -3023,12 +3023,6 @@ static const JSFunctionSpec array_methods[] = { JS_SELF_HOSTED_FN("@@iterator", "ArrayValues", 0,0), JS_SELF_HOSTED_FN("entries", "ArrayEntries", 0,0), JS_SELF_HOSTED_FN("keys", "ArrayKeys", 0,0), - - /* ES7 additions */ -#ifdef NIGHTLY_BUILD - JS_SELF_HOSTED_FN("contains", "ArrayContains", 2,0), -#endif - JS_FS_END }; diff --git a/js/src/tests/ecma_6/Object/isSealed.js b/js/src/tests/ecma_6/Object/isSealed.js deleted file mode 100644 index cd363a87e111..000000000000 --- a/js/src/tests/ecma_6/Object/isSealed.js +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Any copyright is dedicated to the Public Domain. - * https://creativecommons.org/publicdomain/zero/1.0/ - */ - -var BUGNUMBER = 1062860; -var summary = "Object.isSealed() should return true when given primitive values as input"; - -print(BUGNUMBER + ": " + summary); -assertEq(Object.isSealed(), true); -assertEq(Object.isSealed(undefined), true); -assertEq(Object.isSealed(null), true); -assertEq(Object.isSealed(1), true); -assertEq(Object.isSealed("foo"), true); -assertEq(Object.isSealed(true), true); -if (typeof Symbol === "function") { - assertEq(Object.isSealed(Symbol()), true); -} - -if (typeof reportCompare === "function") - reportCompare(true, true); diff --git a/js/src/tests/ecma_7/Array/browser.js b/js/src/tests/ecma_7/Array/browser.js deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/js/src/tests/ecma_7/Array/contains.js b/js/src/tests/ecma_7/Array/contains.js deleted file mode 100644 index 90746a7fe090..000000000000 --- a/js/src/tests/ecma_7/Array/contains.js +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Any copyright is dedicated to the Public Domain. - * https://creativecommons.org/publicdomain/zero/1.0/ - */ - -var BUGNUMBER = 1069063; -var summary = "Implement Array.prototype.contains"; - -print(BUGNUMBER + ": " + summary); - -if ('contains' in Array.prototype) { - assertEq(typeof [].contains, "function"); - assertEq([].contains.length, 1); - - assertTrue([1, 2, 3].contains(2)); - assertTrue([1,,2].contains(2)); - assertTrue([1, 2, 3].contains(2, 1)); - assertTrue([1, 2, 3].contains(2, -2)); - assertTrue([1, 2, 3].contains(2, -100)); - assertTrue([Object, Function, Array].contains(Function)); - assertTrue([-0].contains(0)); - assertTrue([NaN].contains(NaN)); - assertTrue([,].contains()); - assertTrue(staticContains("123", "2")); - assertTrue(staticContains({length: 3, 1: 2}, 2)); - assertTrue(staticContains({length: 3, 1: 2, get 3(){throw ""}}, 2)); - assertTrue(staticContains({length: 3, get 1() {return 2}}, 2)); - assertTrue(staticContains({__proto__: {1: 2}, length: 3}, 2)); - assertTrue(staticContains(new Proxy([1], {get(){return 2}}), 2)); - - assertFalse([1, 2, 3].contains("2")); - assertFalse([1, 2, 3].contains(2, 2)); - assertFalse([1, 2, 3].contains(2, -1)); - assertFalse([undefined].contains(NaN)); - assertFalse([{}].contains({})); - assertFalse(staticContains({length: 3, 1: 2}, 2, 2)); - assertFalse(staticContains({length: 3, get 0(){delete this[1]}, 1: 2}, 2)); - assertFalse(staticContains({length: -100, 0: 1}, 1)); - - assertThrowsInstanceOf(() => staticContains(), TypeError); - assertThrowsInstanceOf(() => staticContains(null), TypeError); - assertThrowsInstanceOf(() => staticContains({get length(){throw TypeError()}}), TypeError); - assertThrowsInstanceOf(() => staticContains({length: 3, get 1() {throw TypeError()}}, 2), TypeError); - assertThrowsInstanceOf(() => staticContains({__proto__: {get 1() {throw TypeError()}}, length: 3}, 2), TypeError); - assertThrowsInstanceOf(() => staticContains(new Proxy([1], {get(){throw TypeError()}})), TypeError); -} - -function assertTrue(v){ - assertEq(v, true) -} - -function assertFalse(v){ - assertEq(v, false) -} - -function staticContains(o, v, f){ - return [].contains.call(o, v, f) -} - -if (typeof reportCompare === "function") - reportCompare(true, true); diff --git a/js/src/tests/ecma_7/Array/shell.js b/js/src/tests/ecma_7/Array/shell.js deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/js/src/tests/ecma_7/browser.js b/js/src/tests/ecma_7/browser.js deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/js/src/tests/ecma_7/shell.js b/js/src/tests/ecma_7/shell.js deleted file mode 100644 index 8334db7443a7..000000000000 --- a/js/src/tests/ecma_7/shell.js +++ /dev/null @@ -1,197 +0,0 @@ -/* 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/. */ - - -if (typeof assertThrowsInstanceOf === 'undefined') { - var assertThrowsInstanceOf = function assertThrowsInstanceOf(f, ctor, msg) { - var fullmsg; - try { - f(); - } catch (exc) { - if (exc instanceof ctor) - return; - fullmsg = "Assertion failed: expected exception " + ctor.name + ", got " + exc; - } - if (fullmsg === undefined) - fullmsg = "Assertion failed: expected exception " + ctor.name + ", no exception thrown"; - if (msg !== undefined) - fullmsg += " - " + msg; - throw new Error(fullmsg); - }; -} - -if (typeof assertThrowsValue === 'undefined') { - var assertThrowsValue = function assertThrowsValue(f, val, msg) { - var fullmsg; - try { - f(); - } catch (exc) { - if ((exc === val) === (val === val) && (val !== 0 || 1 / exc === 1 / val)) - return; - fullmsg = "Assertion failed: expected exception " + val + ", got " + exc; - } - if (fullmsg === undefined) - fullmsg = "Assertion failed: expected exception " + val + ", no exception thrown"; - if (msg !== undefined) - fullmsg += " - " + msg; - throw new Error(fullmsg); - }; -} - -if (typeof assertDeepEq === 'undefined') { - var assertDeepEq = (function(){ - var call = Function.prototype.call, - Map_ = Map, - Error_ = Error, - Map_has = call.bind(Map.prototype.has), - Map_get = call.bind(Map.prototype.get), - Map_set = call.bind(Map.prototype.set), - Object_toString = call.bind(Object.prototype.toString), - Function_toString = call.bind(Function.prototype.toString), - Object_getPrototypeOf = Object.getPrototypeOf, - Object_hasOwnProperty = call.bind(Object.prototype.hasOwnProperty), - Object_getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor, - Object_isExtensible = Object.isExtensible, - Object_getOwnPropertyNames = Object.getOwnPropertyNames, - uneval_ = uneval; - - // Return true iff ES6 Type(v) isn't Object. - // Note that `typeof document.all === "undefined"`. - function isPrimitive(v) { - return (v === null || - v === undefined || - typeof v === "boolean" || - typeof v === "number" || - typeof v === "string" || - typeof v === "symbol"); - } - - function assertSameValue(a, b, msg) { - try { - assertEq(a, b); - } catch (exc) { - throw Error_(exc.message + (msg ? " " + msg : "")); - } - } - - function assertSameClass(a, b, msg) { - var ac = Object_toString(a), bc = Object_toString(b); - assertSameValue(ac, bc, msg); - switch (ac) { - case "[object Function]": - assertSameValue(Function_toString(a), Function_toString(b), msg); - } - } - - function at(prevmsg, segment) { - return prevmsg ? prevmsg + segment : "at _" + segment; - } - - // Assert that the arguments a and b are thoroughly structurally equivalent. - // - // For the sake of speed, we cut a corner: - // var x = {}, y = {}, ax = [x]; - // assertDeepEq([ax, x], [ax, y]); // passes (?!) - // - // Technically this should fail, since the two object graphs are different. - // (The graph of [ax, y] contains one more object than the graph of [ax, x].) - // - // To get technically correct behavior, pass {strictEquivalence: true}. - // This is slower because we have to walk the entire graph, and Object.prototype - // is big. - // - return function assertDeepEq(a, b, options) { - var strictEquivalence = options ? options.strictEquivalence : false; - - function assertSameProto(a, b, msg) { - check(Object_getPrototypeOf(a), Object_getPrototypeOf(b), at(msg, ".__proto__")); - } - - function failPropList(na, nb, msg) { - throw Error_("got own properties " + uneval_(na) + ", expected " + uneval_(nb) + - (msg ? " " + msg : "")); - } - - function assertSameProps(a, b, msg) { - var na = Object_getOwnPropertyNames(a), - nb = Object_getOwnPropertyNames(b); - if (na.length !== nb.length) - failPropList(na, nb, msg); - for (var i = 0; i < na.length; i++) { - var name = na[i]; - if (name !== nb[i]) - failPropList(na, nb, msg); - var da = Object_getOwnPropertyDescriptor(a, name), - db = Object_getOwnPropertyDescriptor(b, name); - var pmsg = at(msg, /^[_$A-Za-z0-9]+$/.test(name) - ? /0|[1-9][0-9]*/.test(name) ? "[" + name + "]" : "." + name - : "[" + uneval_(name) + "]"); - assertSameValue(da.configurable, db.configurable, at(pmsg, ".[[Configurable]]")); - assertSameValue(da.enumerable, db.enumerable, at(pmsg, ".[[Enumerable]]")); - if (Object_hasOwnProperty(da, "value")) { - if (!Object_hasOwnProperty(db, "value")) - throw Error_("got data property, expected accessor property" + pmsg); - check(da.value, db.value, pmsg); - } else { - if (Object_hasOwnProperty(db, "value")) - throw Error_("got accessor property, expected data property" + pmsg); - check(da.get, db.get, at(pmsg, ".[[Get]]")); - check(da.set, db.set, at(pmsg, ".[[Set]]")); - } - } - }; - - var ab = Map_(); - var bpath = Map_(); - - function check(a, b, path) { - if (typeof a === "symbol") { - // Symbols are primitives, but they have identity. - // Symbol("x") !== Symbol("x") but - // assertDeepEq(Symbol("x"), Symbol("x")) should pass. - if (typeof b !== "symbol") { - throw Error_("got " + uneval_(a) + ", expected " + uneval_(b) + " " + path); - } else if (uneval_(a) !== uneval_(b)) { - // We lamely use uneval_ to distinguish well-known symbols - // from user-created symbols. The standard doesn't offer - // a convenient way to do it. - throw Error_("got " + uneval_(a) + ", expected " + uneval_(b) + " " + path); - } else if (Map_has(ab, a)) { - assertSameValue(Map_get(ab, a), b, path); - } else if (Map_has(bpath, b)) { - var bPrevPath = Map_get(bpath, b) || "_"; - throw Error_("got distinct symbols " + at(path, "") + " and " + - at(bPrevPath, "") + ", expected the same symbol both places"); - } else { - Map_set(ab, a, b); - Map_set(bpath, b, path); - } - } else if (isPrimitive(a)) { - assertSameValue(a, b, path); - } else if (isPrimitive(b)) { - throw Error_("got " + Object_toString(a) + ", expected " + uneval_(b) + " " + path); - } else if (Map_has(ab, a)) { - assertSameValue(Map_get(ab, a), b, path); - } else if (Map_has(bpath, b)) { - var bPrevPath = Map_get(bpath, b) || "_"; - throw Error_("got distinct objects " + at(path, "") + " and " + at(bPrevPath, "") + - ", expected the same object both places"); - } else { - Map_set(ab, a, b); - Map_set(bpath, b, path); - if (a !== b || strictEquivalence) { - assertSameClass(a, b, path); - assertSameProto(a, b, path); - assertSameProps(a, b, path); - assertSameValue(Object_isExtensible(a), - Object_isExtensible(b), - at(path, ".[[Extensible]]")); - } - } - } - - check(a, b, ""); - }; - })(); -} From e3eca2660ed0040b1ed5a3e5649b829a2ce01593 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Sun, 21 Sep 2014 21:31:53 +0200 Subject: [PATCH 039/114] Bug 1070696 - Rename xpc::GetNativeForGlobal to xpc::NativeGlobal and make it accept non-global JSObjects. r=smaug The method is infallible, and making the callers invoke js::GetGlobalForObjectCrossCompartment manually is dumb. --- content/base/src/nsDOMFileReader.cpp | 2 +- content/base/src/nsDocument.cpp | 2 +- content/base/src/nsFrameMessageManager.cpp | 2 +- content/base/src/nsXMLHttpRequest.cpp | 2 +- dom/base/ScriptSettings.cpp | 4 ++-- dom/base/nsJSEnvironment.cpp | 4 ++-- dom/base/nsStructuredCloneContainer.cpp | 2 +- dom/bindings/CallbackObject.cpp | 2 +- dom/crypto/WebCryptoTask.cpp | 6 +++--- dom/promise/Promise.cpp | 2 +- ipc/testshell/TestShellParent.cpp | 2 +- js/xpconnect/loader/mozJSComponentLoader.cpp | 4 ++-- js/xpconnect/src/XPCWrappedJSClass.cpp | 4 ++-- js/xpconnect/src/nsXPConnect.cpp | 2 +- js/xpconnect/src/xpcpublic.h | 12 ++++++------ js/xpconnect/wrappers/WrapperFactory.cpp | 4 ++-- 16 files changed, 28 insertions(+), 28 deletions(-) diff --git a/content/base/src/nsDOMFileReader.cpp b/content/base/src/nsDOMFileReader.cpp index b8ed3b49fa1e..0a622bb74414 100644 --- a/content/base/src/nsDOMFileReader.cpp +++ b/content/base/src/nsDOMFileReader.cpp @@ -107,7 +107,7 @@ nsDOMFileReader::Init() // Instead of grabbing some random global from the context stack, // let's use the default one (junk scope) for now. // We should move away from this Init... - BindToOwner(xpc::GetNativeForGlobal(xpc::PrivilegedJunkScope())); + BindToOwner(xpc::NativeGlobal(xpc::PrivilegedJunkScope())); return NS_OK; } diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index 319d0aba2a42..11889f4868b5 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -2154,7 +2154,7 @@ nsDocument::Init() // we use the default compartment for this document, instead of creating // wrapper in some random compartment when the document is exposed to js // via some events. - nsCOMPtr global = xpc::GetNativeForGlobal(xpc::PrivilegedJunkScope()); + nsCOMPtr global = xpc::NativeGlobal(xpc::PrivilegedJunkScope()); NS_ENSURE_TRUE(global, NS_ERROR_FAILURE); mScopeObject = do_GetWeakReference(global); MOZ_ASSERT(mScopeObject); diff --git a/content/base/src/nsFrameMessageManager.cpp b/content/base/src/nsFrameMessageManager.cpp index 5665d36cffbc..f20468aa3c65 100644 --- a/content/base/src/nsFrameMessageManager.cpp +++ b/content/base/src/nsFrameMessageManager.cpp @@ -968,7 +968,7 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget, // } // JSContext* cx = aes.cx(); nsIGlobalObject* nativeGlobal = - xpc::GetNativeForGlobal(js::GetGlobalForObjectCrossCompartment(wrappedJS->GetJSObject())); + xpc::NativeGlobal(js::GetGlobalForObjectCrossCompartment(wrappedJS->GetJSObject())); AutoEntryScript aes(nativeGlobal); JSContext* cx = aes.cx(); JS::Rooted object(cx, wrappedJS->GetJSObject()); diff --git a/content/base/src/nsXMLHttpRequest.cpp b/content/base/src/nsXMLHttpRequest.cpp index ab087b844e0b..85dd71735770 100644 --- a/content/base/src/nsXMLHttpRequest.cpp +++ b/content/base/src/nsXMLHttpRequest.cpp @@ -352,7 +352,7 @@ nsXMLHttpRequest::Init() // Instead of grabbing some random global from the context stack, // let's use the default one (junk scope) for now. // We should move away from this Init... - Construct(subjectPrincipal, xpc::GetNativeForGlobal(xpc::PrivilegedJunkScope())); + Construct(subjectPrincipal, xpc::NativeGlobal(xpc::PrivilegedJunkScope())); return NS_OK; } diff --git a/dom/base/ScriptSettings.cpp b/dom/base/ScriptSettings.cpp index 1f20ec03fdf5..a91b06d3fe73 100644 --- a/dom/base/ScriptSettings.cpp +++ b/dom/base/ScriptSettings.cpp @@ -154,7 +154,7 @@ GetIncumbentGlobal() // there's nothing on the JS stack, which will cause us to check the // incumbent script stack below. if (JSObject *global = JS::GetScriptedCallerGlobal(cx)) { - return xpc::GetNativeForGlobal(global); + return xpc::NativeGlobal(global); } // Ok, nothing from the JS engine. Let's use whatever's on the @@ -175,7 +175,7 @@ GetCurrentGlobal() return nullptr; } - return xpc::GetNativeForGlobal(global); + return xpc::NativeGlobal(global); } nsIPrincipal* diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index 3e26b9efb2aa..587cc8951a3a 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -484,7 +484,7 @@ SystemErrorReporter(JSContext *cx, const char *message, JSErrorReport *report) } if (!globalObject) { - globalObject = xpc::GetNativeForGlobal(xpc::PrivilegedJunkScope()); + globalObject = xpc::NativeGlobal(xpc::PrivilegedJunkScope()); } if (globalObject) { @@ -2581,7 +2581,7 @@ NS_DOMReadStructuredClone(JSContext* cx, if (tag == SCTAG_DOM_IMAGEDATA) { return ReadStructuredCloneImageData(cx, reader); } else if (tag == SCTAG_DOM_WEBCRYPTO_KEY) { - nsIGlobalObject *global = xpc::GetNativeForGlobal(JS::CurrentGlobalOrNull(cx)); + nsIGlobalObject *global = xpc::NativeGlobal(JS::CurrentGlobalOrNull(cx)); if (!global) { return nullptr; } diff --git a/dom/base/nsStructuredCloneContainer.cpp b/dom/base/nsStructuredCloneContainer.cpp index a2f8e1483c95..90519b1f8c5f 100644 --- a/dom/base/nsStructuredCloneContainer.cpp +++ b/dom/base/nsStructuredCloneContainer.cpp @@ -61,7 +61,7 @@ nsStructuredCloneContainer::InitFromJSVal(JS::Handle aData) // part of the "own" "deep clone" sub-steps, so we need an AutoEntryScript. // http://www.whatwg.org/specs/web-apps/current-work/#internal-structured-cloning-algorithm nsIGlobalObject* nativeGlobal = - xpc::GetNativeForGlobal(js::GetGlobalForObjectCrossCompartment(&aData.toObject())); + xpc::NativeGlobal(js::GetGlobalForObjectCrossCompartment(&aData.toObject())); dom::AutoEntryScript aes(nativeGlobal); success = JS_WriteStructuredClone(aes.cx(), aData, &jsBytes, &mSize, nullptr, nullptr, diff --git a/dom/bindings/CallbackObject.cpp b/dom/bindings/CallbackObject.cpp index a2c92d5305cc..40137f93cc9a 100644 --- a/dom/bindings/CallbackObject.cpp +++ b/dom/bindings/CallbackObject.cpp @@ -109,7 +109,7 @@ CallbackObject::CallSetup::CallSetup(CallbackObject* aCallback, } else { // No DOM Window. Store the global and use the SafeJSContext. JSObject* glob = js::GetGlobalForObjectCrossCompartment(realCallback); - globalObject = xpc::GetNativeForGlobal(glob); + globalObject = xpc::NativeGlobal(glob); MOZ_ASSERT(globalObject); cx = nsContentUtils::GetSafeJSContext(); } diff --git a/dom/crypto/WebCryptoTask.cpp b/dom/crypto/WebCryptoTask.cpp index bad140e4d4ae..accb59954524 100644 --- a/dom/crypto/WebCryptoTask.cpp +++ b/dom/crypto/WebCryptoTask.cpp @@ -1286,7 +1286,7 @@ public: mDataIsSet = false; // Get the current global object from the context - nsIGlobalObject *global = xpc::GetNativeForGlobal(JS::CurrentGlobalOrNull(aCx)); + nsIGlobalObject *global = xpc::NativeGlobal(JS::CurrentGlobalOrNull(aCx)); if (!global) { mEarlyRv = NS_ERROR_DOM_UNKNOWN_ERR; return; @@ -1955,7 +1955,7 @@ public: const ObjectOrString& aAlgorithm, bool aExtractable, const Sequence& aKeyUsages) { - nsIGlobalObject* global = xpc::GetNativeForGlobal(JS::CurrentGlobalOrNull(aCx)); + nsIGlobalObject* global = xpc::NativeGlobal(JS::CurrentGlobalOrNull(aCx)); if (!global) { mEarlyRv = NS_ERROR_DOM_UNKNOWN_ERR; return; @@ -2082,7 +2082,7 @@ public: const ObjectOrString& aAlgorithm, bool aExtractable, const Sequence& aKeyUsages) { - nsIGlobalObject* global = xpc::GetNativeForGlobal(JS::CurrentGlobalOrNull(aCx)); + nsIGlobalObject* global = xpc::NativeGlobal(JS::CurrentGlobalOrNull(aCx)); if (!global) { mEarlyRv = NS_ERROR_DOM_UNKNOWN_ERR; return; diff --git a/dom/promise/Promise.cpp b/dom/promise/Promise.cpp index ad62e6626276..e49d2059b08c 100644 --- a/dom/promise/Promise.cpp +++ b/dom/promise/Promise.cpp @@ -1024,7 +1024,7 @@ Promise::MaybeReportRejected() nsRefPtr xpcReport = new xpc::ErrorReport(); if (MOZ_LIKELY(NS_IsMainThread())) { - nsIGlobalObject* global = xpc::GetNativeForGlobal(js::GetGlobalForObjectCrossCompartment(obj)); + nsIGlobalObject* global = xpc::NativeGlobal(js::GetGlobalForObjectCrossCompartment(obj)); xpcReport->Init(report.report(), report.message(), global); } else { xpcReport->InitOnWorkerThread(report.report(), report.message(), diff --git a/ipc/testshell/TestShellParent.cpp b/ipc/testshell/TestShellParent.cpp index 4f87bfa30734..543faf1baa4a 100644 --- a/ipc/testshell/TestShellParent.cpp +++ b/ipc/testshell/TestShellParent.cpp @@ -70,7 +70,7 @@ TestShellCommandParent::RunCallback(const nsString& aResponse) // We're about to run script via JS_CallFunctionValue, so we need an // AutoEntryScript. This is just for testing and not in any spec. - dom::AutoEntryScript aes(xpc::GetNativeForGlobal(js::GetGlobalForObjectCrossCompartment(mCallback.ToJSObject()))); + dom::AutoEntryScript aes(xpc::NativeGlobal(js::GetGlobalForObjectCrossCompartment(mCallback.ToJSObject()))); JSContext* cx = aes.cx(); JS::Rooted global(cx, JS::CurrentGlobalOrNull(cx)); diff --git a/js/xpconnect/loader/mozJSComponentLoader.cpp b/js/xpconnect/loader/mozJSComponentLoader.cpp index 90a14bbd0846..36735703dd91 100644 --- a/js/xpconnect/loader/mozJSComponentLoader.cpp +++ b/js/xpconnect/loader/mozJSComponentLoader.cpp @@ -728,7 +728,7 @@ mozJSComponentLoader::PrepareObjectForLocation(JSContext* aCx, if (createdNewGlobal) { // AutoEntryScript required to invoke debugger hook, which is a // Gecko-specific concept at present. - dom::AutoEntryScript aes(GetNativeForGlobal(holder->GetJSObject())); + dom::AutoEntryScript aes(NativeGlobal(holder->GetJSObject())); RootedObject global(aes.cx(), holder->GetJSObject()); JS_FireOnNewGlobalObject(aes.cx(), global); } @@ -1006,7 +1006,7 @@ mozJSComponentLoader::ObjectForLocation(ComponentLoaderInfo &aInfo, // We're going to run script via JS_ExecuteScriptVersion or // JS_CallFunction, so we need an AutoEntryScript. // This is Gecko-specific and not in any spec. - dom::AutoEntryScript aes(GetNativeForGlobal(CurrentGlobalOrNull(cx))); + dom::AutoEntryScript aes(NativeGlobal(CurrentGlobalOrNull(cx))); AutoSaveContextOptions asco(cx); if (aPropagateExceptions) ContextOptionsRef(cx).setDontReportUncaught(true); diff --git a/js/xpconnect/src/XPCWrappedJSClass.cpp b/js/xpconnect/src/XPCWrappedJSClass.cpp index 0f6a58304ee9..2d86c014ef34 100644 --- a/js/xpconnect/src/XPCWrappedJSClass.cpp +++ b/js/xpconnect/src/XPCWrappedJSClass.cpp @@ -489,7 +489,7 @@ nsXPCWrappedJSClass::DelegatedQueryInterface(nsXPCWrappedJS* self, // QI on an XPCWrappedJS can run script, so we need an AutoEntryScript. // This is inherently Gecko-specific. nsIGlobalObject* nativeGlobal = - GetNativeForGlobal(js::GetGlobalForObjectCrossCompartment(self->GetJSObject())); + NativeGlobal(js::GetGlobalForObjectCrossCompartment(self->GetJSObject())); AutoEntryScript aes(nativeGlobal, /* aIsMainThread = */ true); XPCCallContext ccx(NATIVE_CALLER, aes.cx()); if (!ccx.IsValid()) { @@ -890,7 +890,7 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16_t methodIndex, // AutoEntryScript. This is probably Gecko-specific at this point, and // definitely will be when we turn off XPConnect for the web. nsIGlobalObject* nativeGlobal = - GetNativeForGlobal(js::GetGlobalForObjectCrossCompartment(wrapper->GetJSObject())); + NativeGlobal(js::GetGlobalForObjectCrossCompartment(wrapper->GetJSObject())); AutoEntryScript aes(nativeGlobal, /* aIsMainThread = */ true); XPCCallContext ccx(NATIVE_CALLER, aes.cx()); if (!ccx.IsValid()) diff --git a/js/xpconnect/src/nsXPConnect.cpp b/js/xpconnect/src/nsXPConnect.cpp index 21901f961b0d..454a7ca7229d 100644 --- a/js/xpconnect/src/nsXPConnect.cpp +++ b/js/xpconnect/src/nsXPConnect.cpp @@ -1524,7 +1524,7 @@ SetAddonInterposition(const nsACString &addonIdStr, nsIAddonInterposition *inter // We enter the junk scope just to allocate a string, which actually will go // in the system zone. AutoJSAPI jsapi; - jsapi.Init(xpc::GetNativeForGlobal(xpc::PrivilegedJunkScope())); + jsapi.Init(xpc::NativeGlobal(xpc::PrivilegedJunkScope())); addonId = NewAddonId(jsapi.cx(), addonIdStr); if (!addonId) return false; diff --git a/js/xpconnect/src/xpcpublic.h b/js/xpconnect/src/xpcpublic.h index 932e11e51bdb..0f685ca22c1d 100644 --- a/js/xpconnect/src/xpcpublic.h +++ b/js/xpconnect/src/xpcpublic.h @@ -424,12 +424,6 @@ ReportJSRuntimeExplicitTreeStats(const JS::RuntimeStats &rtStats, bool Throw(JSContext *cx, nsresult rv); -/** - * Every global should hold a native that implements the nsIGlobalObject interface. - */ -nsIGlobalObject * -GetNativeForGlobal(JSObject *global); - /** * Returns the nsISupports native behind a given reflector (either DOM or * XPCWN). @@ -458,6 +452,12 @@ PrivilegedJunkScope(); JSObject * CompilationScope(); +/** + * Returns the nsIGlobalObject corresponding to |aObj|'s JS global. + */ +nsIGlobalObject* +NativeGlobal(JSObject *aObj); + /** * If |aObj| is a window, returns the associated nsGlobalWindow. * Otherwise, returns null. diff --git a/js/xpconnect/wrappers/WrapperFactory.cpp b/js/xpconnect/wrappers/WrapperFactory.cpp index 4b45981c3a36..6a69e6f3b3cc 100644 --- a/js/xpconnect/wrappers/WrapperFactory.cpp +++ b/js/xpconnect/wrappers/WrapperFactory.cpp @@ -644,9 +644,9 @@ TransplantObject(JSContext *cx, JS::HandleObject origobj, JS::HandleObject targe } nsIGlobalObject * -GetNativeForGlobal(JSObject *obj) +NativeGlobal(JSObject *obj) { - MOZ_ASSERT(JS_IsGlobalObject(obj)); + obj = js::GetGlobalForObjectCrossCompartment(obj); // Every global needs to hold a native as its private or be a // WebIDL object with an nsISupports DOM object. From be9e0c4e410b5de7b5e686ef9ee80d949b8b9c5b Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Sun, 21 Sep 2014 21:31:53 +0200 Subject: [PATCH 040/114] Bug 1070696 - Implement a JSObject* override to AutoJSAPI::Init(). r=smaug --- dom/base/ScriptSettings.cpp | 6 ++++++ dom/base/ScriptSettings.h | 4 ++++ js/xpconnect/src/nsXPConnect.cpp | 2 +- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/dom/base/ScriptSettings.cpp b/dom/base/ScriptSettings.cpp index a91b06d3fe73..62e64d21a56f 100644 --- a/dom/base/ScriptSettings.cpp +++ b/dom/base/ScriptSettings.cpp @@ -302,6 +302,12 @@ AutoJSAPI::Init(nsIGlobalObject* aGlobalObject) return Init(aGlobalObject, nsContentUtils::GetDefaultJSContextForThread()); } +bool +AutoJSAPI::Init(JSObject* aObject) +{ + return Init(xpc::NativeGlobal(aObject)); +} + bool AutoJSAPI::InitWithLegacyErrorReporting(nsIGlobalObject* aGlobalObject) { diff --git a/dom/base/ScriptSettings.h b/dom/base/ScriptSettings.h index 880023ebc7ee..7769eb5ecea3 100644 --- a/dom/base/ScriptSettings.h +++ b/dom/base/ScriptSettings.h @@ -214,6 +214,10 @@ public: // false and use of cx() will cause an assertion. bool Init(nsIGlobalObject* aGlobalObject); + // This is a helper that grabs the native global associated with aObject and + // invokes the above Init() with that. + bool Init(JSObject* aObject); + // Unsurprisingly, this uses aCx and enters the compartment of aGlobalObject. // If aGlobalObject or its associated JS global are null then it returns // false and use of cx() will cause an assertion. diff --git a/js/xpconnect/src/nsXPConnect.cpp b/js/xpconnect/src/nsXPConnect.cpp index 454a7ca7229d..a48921186d21 100644 --- a/js/xpconnect/src/nsXPConnect.cpp +++ b/js/xpconnect/src/nsXPConnect.cpp @@ -1524,7 +1524,7 @@ SetAddonInterposition(const nsACString &addonIdStr, nsIAddonInterposition *inter // We enter the junk scope just to allocate a string, which actually will go // in the system zone. AutoJSAPI jsapi; - jsapi.Init(xpc::NativeGlobal(xpc::PrivilegedJunkScope())); + jsapi.Init(xpc::PrivilegedJunkScope()); addonId = NewAddonId(jsapi.cx(), addonIdStr); if (!addonId) return false; From ea058db5ed227ac7f08294ccc4ed29b138c684e2 Mon Sep 17 00:00:00 2001 From: Till Schneidereit Date: Thu, 18 Sep 2014 17:22:05 +0800 Subject: [PATCH 041/114] changeset: 229386:2c92e43e29d8 user: ziyunfei <446240525@qq.com> files: js/src/builtin/Array.js js/src/builtin/Utilities.js js/src/jsarray.cpp js/src/tests/ecma_7/Array/browser.js js/src/tests/ecma_7/Array/contains.js js/src/tests/ecma_7/Array/shell.js js/src/tests/ecma_7/browser.js js/src/tests/ecma_7/shell.js description: Bug 1069063 - Implement Array.prototype.contains. r=till,securityAudit=bholley --HG-- rename : js/src/tests/ecma_6/Array/browser.js => js/src/tests/ecma_7/Array/browser.js rename : js/src/tests/ecma_6/Array/browser.js => js/src/tests/ecma_7/Array/shell.js rename : js/src/tests/ecma_6/browser.js => js/src/tests/ecma_7/browser.js rename : js/src/tests/ecma_6/shell.js => js/src/tests/ecma_7/shell.js --- js/src/builtin/Array.js | 50 +++++ js/src/builtin/Utilities.js | 5 + js/src/jsarray.cpp | 6 + js/src/tests/Makefile.in | 1 + js/src/tests/ecma_7/Array/browser.js | 0 js/src/tests/ecma_7/Array/contains.js | 61 ++++++ js/src/tests/ecma_7/Array/shell.js | 0 js/src/tests/ecma_7/browser.js | 0 js/src/tests/ecma_7/shell.js | 197 ++++++++++++++++++++ js/xpconnect/tests/chrome/test_xrayToJS.xul | 1 + 10 files changed, 321 insertions(+) create mode 100644 js/src/tests/ecma_7/Array/browser.js create mode 100644 js/src/tests/ecma_7/Array/contains.js create mode 100644 js/src/tests/ecma_7/Array/shell.js create mode 100644 js/src/tests/ecma_7/browser.js create mode 100644 js/src/tests/ecma_7/shell.js diff --git a/js/src/builtin/Array.js b/js/src/builtin/Array.js index eaaf2c3b0eb2..fbfec82aa5d5 100644 --- a/js/src/builtin/Array.js +++ b/js/src/builtin/Array.js @@ -581,6 +581,56 @@ function ArrayFill(value, start = 0, end = undefined) { return O; } +// Proposed for ES7: +// https://github.com/domenic/Array.prototype.contains/blob/master/spec.md +function ArrayContains(searchElement, fromIndex = 0) { + // Steps 1-2. + var O = ToObject(this); + + // Steps 3-4. + var len = ToLength(O.length); + + // Step 5. + if (len === 0) + return false; + + // Steps 6-7. + var n = ToInteger(fromIndex); + + // Step 8. + if (n >= len) + return false; + + // Step 9. + var k; + if (n >= 0) + k = n; + // Step 10. + else { + // Step a. + k = len + n; + // Step b. + if (k < 0) + k = 0; + } + + // Step 11. + while (k < len) { + // Steps a-b. + var elementK = O[k]; + + // Step c. + if (SameValueZero(searchElement, elementK)) + return true; + + // Step d. + k++; + } + + // Step 12. + return false; +} + #define ARRAY_ITERATOR_SLOT_ITERATED_OBJECT 0 #define ARRAY_ITERATOR_SLOT_NEXT_INDEX 1 #define ARRAY_ITERATOR_SLOT_ITEM_KIND 2 diff --git a/js/src/builtin/Utilities.js b/js/src/builtin/Utilities.js index fae2a5b68650..237378f4617c 100644 --- a/js/src/builtin/Utilities.js +++ b/js/src/builtin/Utilities.js @@ -156,6 +156,11 @@ function ToLength(v) { return v < 0x1fffffffffffff ? v : 0x1fffffffffffff; } +/* Spec: ECMAScript Draft, 6 edition Aug 24, 2014, 7.2.4 */ +function SameValueZero(x, y) { + return x !== x && y !== y || x === y +} + /********** Testing code **********/ #ifdef ENABLE_PARALLEL_JS diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index a191279f2b77..8a3e729ffb5c 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -3023,6 +3023,12 @@ static const JSFunctionSpec array_methods[] = { JS_SELF_HOSTED_FN("@@iterator", "ArrayValues", 0,0), JS_SELF_HOSTED_FN("entries", "ArrayEntries", 0,0), JS_SELF_HOSTED_FN("keys", "ArrayKeys", 0,0), + + /* ES7 additions */ +#ifdef NIGHTLY_BUILD + JS_SELF_HOSTED_FN("contains", "ArrayContains", 2,0), +#endif + JS_FS_END }; diff --git a/js/src/tests/Makefile.in b/js/src/tests/Makefile.in index 1d67364c947a..817d545787a1 100644 --- a/js/src/tests/Makefile.in +++ b/js/src/tests/Makefile.in @@ -18,6 +18,7 @@ TEST_FILES = \ ecma_3_1/ \ ecma_5/ \ ecma_6/ \ + ecma_7/ \ Intl/ \ js1_1/ \ js1_2/ \ diff --git a/js/src/tests/ecma_7/Array/browser.js b/js/src/tests/ecma_7/Array/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/ecma_7/Array/contains.js b/js/src/tests/ecma_7/Array/contains.js new file mode 100644 index 000000000000..90746a7fe090 --- /dev/null +++ b/js/src/tests/ecma_7/Array/contains.js @@ -0,0 +1,61 @@ +/* + * Any copyright is dedicated to the Public Domain. + * https://creativecommons.org/publicdomain/zero/1.0/ + */ + +var BUGNUMBER = 1069063; +var summary = "Implement Array.prototype.contains"; + +print(BUGNUMBER + ": " + summary); + +if ('contains' in Array.prototype) { + assertEq(typeof [].contains, "function"); + assertEq([].contains.length, 1); + + assertTrue([1, 2, 3].contains(2)); + assertTrue([1,,2].contains(2)); + assertTrue([1, 2, 3].contains(2, 1)); + assertTrue([1, 2, 3].contains(2, -2)); + assertTrue([1, 2, 3].contains(2, -100)); + assertTrue([Object, Function, Array].contains(Function)); + assertTrue([-0].contains(0)); + assertTrue([NaN].contains(NaN)); + assertTrue([,].contains()); + assertTrue(staticContains("123", "2")); + assertTrue(staticContains({length: 3, 1: 2}, 2)); + assertTrue(staticContains({length: 3, 1: 2, get 3(){throw ""}}, 2)); + assertTrue(staticContains({length: 3, get 1() {return 2}}, 2)); + assertTrue(staticContains({__proto__: {1: 2}, length: 3}, 2)); + assertTrue(staticContains(new Proxy([1], {get(){return 2}}), 2)); + + assertFalse([1, 2, 3].contains("2")); + assertFalse([1, 2, 3].contains(2, 2)); + assertFalse([1, 2, 3].contains(2, -1)); + assertFalse([undefined].contains(NaN)); + assertFalse([{}].contains({})); + assertFalse(staticContains({length: 3, 1: 2}, 2, 2)); + assertFalse(staticContains({length: 3, get 0(){delete this[1]}, 1: 2}, 2)); + assertFalse(staticContains({length: -100, 0: 1}, 1)); + + assertThrowsInstanceOf(() => staticContains(), TypeError); + assertThrowsInstanceOf(() => staticContains(null), TypeError); + assertThrowsInstanceOf(() => staticContains({get length(){throw TypeError()}}), TypeError); + assertThrowsInstanceOf(() => staticContains({length: 3, get 1() {throw TypeError()}}, 2), TypeError); + assertThrowsInstanceOf(() => staticContains({__proto__: {get 1() {throw TypeError()}}, length: 3}, 2), TypeError); + assertThrowsInstanceOf(() => staticContains(new Proxy([1], {get(){throw TypeError()}})), TypeError); +} + +function assertTrue(v){ + assertEq(v, true) +} + +function assertFalse(v){ + assertEq(v, false) +} + +function staticContains(o, v, f){ + return [].contains.call(o, v, f) +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/ecma_7/Array/shell.js b/js/src/tests/ecma_7/Array/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/ecma_7/browser.js b/js/src/tests/ecma_7/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/ecma_7/shell.js b/js/src/tests/ecma_7/shell.js new file mode 100644 index 000000000000..8334db7443a7 --- /dev/null +++ b/js/src/tests/ecma_7/shell.js @@ -0,0 +1,197 @@ +/* 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/. */ + + +if (typeof assertThrowsInstanceOf === 'undefined') { + var assertThrowsInstanceOf = function assertThrowsInstanceOf(f, ctor, msg) { + var fullmsg; + try { + f(); + } catch (exc) { + if (exc instanceof ctor) + return; + fullmsg = "Assertion failed: expected exception " + ctor.name + ", got " + exc; + } + if (fullmsg === undefined) + fullmsg = "Assertion failed: expected exception " + ctor.name + ", no exception thrown"; + if (msg !== undefined) + fullmsg += " - " + msg; + throw new Error(fullmsg); + }; +} + +if (typeof assertThrowsValue === 'undefined') { + var assertThrowsValue = function assertThrowsValue(f, val, msg) { + var fullmsg; + try { + f(); + } catch (exc) { + if ((exc === val) === (val === val) && (val !== 0 || 1 / exc === 1 / val)) + return; + fullmsg = "Assertion failed: expected exception " + val + ", got " + exc; + } + if (fullmsg === undefined) + fullmsg = "Assertion failed: expected exception " + val + ", no exception thrown"; + if (msg !== undefined) + fullmsg += " - " + msg; + throw new Error(fullmsg); + }; +} + +if (typeof assertDeepEq === 'undefined') { + var assertDeepEq = (function(){ + var call = Function.prototype.call, + Map_ = Map, + Error_ = Error, + Map_has = call.bind(Map.prototype.has), + Map_get = call.bind(Map.prototype.get), + Map_set = call.bind(Map.prototype.set), + Object_toString = call.bind(Object.prototype.toString), + Function_toString = call.bind(Function.prototype.toString), + Object_getPrototypeOf = Object.getPrototypeOf, + Object_hasOwnProperty = call.bind(Object.prototype.hasOwnProperty), + Object_getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor, + Object_isExtensible = Object.isExtensible, + Object_getOwnPropertyNames = Object.getOwnPropertyNames, + uneval_ = uneval; + + // Return true iff ES6 Type(v) isn't Object. + // Note that `typeof document.all === "undefined"`. + function isPrimitive(v) { + return (v === null || + v === undefined || + typeof v === "boolean" || + typeof v === "number" || + typeof v === "string" || + typeof v === "symbol"); + } + + function assertSameValue(a, b, msg) { + try { + assertEq(a, b); + } catch (exc) { + throw Error_(exc.message + (msg ? " " + msg : "")); + } + } + + function assertSameClass(a, b, msg) { + var ac = Object_toString(a), bc = Object_toString(b); + assertSameValue(ac, bc, msg); + switch (ac) { + case "[object Function]": + assertSameValue(Function_toString(a), Function_toString(b), msg); + } + } + + function at(prevmsg, segment) { + return prevmsg ? prevmsg + segment : "at _" + segment; + } + + // Assert that the arguments a and b are thoroughly structurally equivalent. + // + // For the sake of speed, we cut a corner: + // var x = {}, y = {}, ax = [x]; + // assertDeepEq([ax, x], [ax, y]); // passes (?!) + // + // Technically this should fail, since the two object graphs are different. + // (The graph of [ax, y] contains one more object than the graph of [ax, x].) + // + // To get technically correct behavior, pass {strictEquivalence: true}. + // This is slower because we have to walk the entire graph, and Object.prototype + // is big. + // + return function assertDeepEq(a, b, options) { + var strictEquivalence = options ? options.strictEquivalence : false; + + function assertSameProto(a, b, msg) { + check(Object_getPrototypeOf(a), Object_getPrototypeOf(b), at(msg, ".__proto__")); + } + + function failPropList(na, nb, msg) { + throw Error_("got own properties " + uneval_(na) + ", expected " + uneval_(nb) + + (msg ? " " + msg : "")); + } + + function assertSameProps(a, b, msg) { + var na = Object_getOwnPropertyNames(a), + nb = Object_getOwnPropertyNames(b); + if (na.length !== nb.length) + failPropList(na, nb, msg); + for (var i = 0; i < na.length; i++) { + var name = na[i]; + if (name !== nb[i]) + failPropList(na, nb, msg); + var da = Object_getOwnPropertyDescriptor(a, name), + db = Object_getOwnPropertyDescriptor(b, name); + var pmsg = at(msg, /^[_$A-Za-z0-9]+$/.test(name) + ? /0|[1-9][0-9]*/.test(name) ? "[" + name + "]" : "." + name + : "[" + uneval_(name) + "]"); + assertSameValue(da.configurable, db.configurable, at(pmsg, ".[[Configurable]]")); + assertSameValue(da.enumerable, db.enumerable, at(pmsg, ".[[Enumerable]]")); + if (Object_hasOwnProperty(da, "value")) { + if (!Object_hasOwnProperty(db, "value")) + throw Error_("got data property, expected accessor property" + pmsg); + check(da.value, db.value, pmsg); + } else { + if (Object_hasOwnProperty(db, "value")) + throw Error_("got accessor property, expected data property" + pmsg); + check(da.get, db.get, at(pmsg, ".[[Get]]")); + check(da.set, db.set, at(pmsg, ".[[Set]]")); + } + } + }; + + var ab = Map_(); + var bpath = Map_(); + + function check(a, b, path) { + if (typeof a === "symbol") { + // Symbols are primitives, but they have identity. + // Symbol("x") !== Symbol("x") but + // assertDeepEq(Symbol("x"), Symbol("x")) should pass. + if (typeof b !== "symbol") { + throw Error_("got " + uneval_(a) + ", expected " + uneval_(b) + " " + path); + } else if (uneval_(a) !== uneval_(b)) { + // We lamely use uneval_ to distinguish well-known symbols + // from user-created symbols. The standard doesn't offer + // a convenient way to do it. + throw Error_("got " + uneval_(a) + ", expected " + uneval_(b) + " " + path); + } else if (Map_has(ab, a)) { + assertSameValue(Map_get(ab, a), b, path); + } else if (Map_has(bpath, b)) { + var bPrevPath = Map_get(bpath, b) || "_"; + throw Error_("got distinct symbols " + at(path, "") + " and " + + at(bPrevPath, "") + ", expected the same symbol both places"); + } else { + Map_set(ab, a, b); + Map_set(bpath, b, path); + } + } else if (isPrimitive(a)) { + assertSameValue(a, b, path); + } else if (isPrimitive(b)) { + throw Error_("got " + Object_toString(a) + ", expected " + uneval_(b) + " " + path); + } else if (Map_has(ab, a)) { + assertSameValue(Map_get(ab, a), b, path); + } else if (Map_has(bpath, b)) { + var bPrevPath = Map_get(bpath, b) || "_"; + throw Error_("got distinct objects " + at(path, "") + " and " + at(bPrevPath, "") + + ", expected the same object both places"); + } else { + Map_set(ab, a, b); + Map_set(bpath, b, path); + if (a !== b || strictEquivalence) { + assertSameClass(a, b, path); + assertSameProto(a, b, path); + assertSameProps(a, b, path); + assertSameValue(Object_isExtensible(a), + Object_isExtensible(b), + at(path, ".[[Extensible]]")); + } + } + } + + check(a, b, ""); + }; + })(); +} diff --git a/js/xpconnect/tests/chrome/test_xrayToJS.xul b/js/xpconnect/tests/chrome/test_xrayToJS.xul index d5fdff2aa673..03c169ea9c03 100644 --- a/js/xpconnect/tests/chrome/test_xrayToJS.xul +++ b/js/xpconnect/tests/chrome/test_xrayToJS.xul @@ -176,6 +176,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=933681 "forEach", "map", "reduce", "reduceRight", "filter", "some", "every", "find", "findIndex", "copyWithin", "fill", "@@iterator", "entries", "keys", "constructor"]; if (isNightlyBuild) { + gPrototypeProperties['Array'].push('contains'); let pjsMethods = ['mapPar', 'reducePar', 'scanPar', 'scatterPar', 'filterPar']; gPrototypeProperties['Array'] = gPrototypeProperties['Array'].concat(pjsMethods); } From 99ba761309da8d0f61338287961032016faadf1e Mon Sep 17 00:00:00 2001 From: Till Schneidereit Date: Thu, 4 Sep 2014 21:08:33 +0800 Subject: [PATCH 042/114] changeset: 229387:7f06ae718751 user: ziyunfei <446240525@qq.com> files: js/src/builtin/Object.cpp js/src/tests/ecma_6/Object/isSealed.js description: Bug 1062860 - Object.isSealed() should return true when given primitive values as input. r=till --- js/src/builtin/Object.cpp | 16 ++++++++++------ js/src/tests/ecma_6/Object/isSealed.js | 21 +++++++++++++++++++++ 2 files changed, 31 insertions(+), 6 deletions(-) create mode 100644 js/src/tests/ecma_6/Object/isSealed.js diff --git a/js/src/builtin/Object.cpp b/js/src/builtin/Object.cpp index 748393dd8c70..734ef4c38d65 100644 --- a/js/src/builtin/Object.cpp +++ b/js/src/builtin/Object.cpp @@ -1094,17 +1094,21 @@ obj_seal(JSContext *cx, unsigned argc, Value *vp) return JSObject::seal(cx, obj); } +// ES6 draft rev27 (2014/08/24) 19.1.2.13 Object.isSealed(O) static bool obj_isSealed(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); - RootedObject obj(cx); - if (!GetFirstArgumentAsObject(cx, args, "Object.isSealed", &obj)) - return false; - bool sealed; - if (!JSObject::isSealed(cx, obj, &sealed)) - return false; + // step 1 + bool sealed = true; + + // step 2 + if (args.get(0).isObject()) { + RootedObject obj(cx, &args.get(0).toObject()); + if (!JSObject::isSealed(cx, obj, &sealed)) + return false; + } args.rval().setBoolean(sealed); return true; } diff --git a/js/src/tests/ecma_6/Object/isSealed.js b/js/src/tests/ecma_6/Object/isSealed.js new file mode 100644 index 000000000000..cd363a87e111 --- /dev/null +++ b/js/src/tests/ecma_6/Object/isSealed.js @@ -0,0 +1,21 @@ +/* + * Any copyright is dedicated to the Public Domain. + * https://creativecommons.org/publicdomain/zero/1.0/ + */ + +var BUGNUMBER = 1062860; +var summary = "Object.isSealed() should return true when given primitive values as input"; + +print(BUGNUMBER + ": " + summary); +assertEq(Object.isSealed(), true); +assertEq(Object.isSealed(undefined), true); +assertEq(Object.isSealed(null), true); +assertEq(Object.isSealed(1), true); +assertEq(Object.isSealed("foo"), true); +assertEq(Object.isSealed(true), true); +if (typeof Symbol === "function") { + assertEq(Object.isSealed(Symbol()), true); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); From cbc918194abd6510b409111b2003b3832b483841 Mon Sep 17 00:00:00 2001 From: Cameron McCormack Date: Mon, 22 Sep 2014 10:32:58 +1000 Subject: [PATCH 043/114] Bug 1069761 - Move AppendSerializedFontSrc to nsStyleUtil. r=jdaggett --- layout/style/nsCSSRules.cpp | 55 +----------------------------------- layout/style/nsStyleUtil.cpp | 55 ++++++++++++++++++++++++++++++++++++ layout/style/nsStyleUtil.h | 3 ++ 3 files changed, 59 insertions(+), 54 deletions(-) diff --git a/layout/style/nsCSSRules.cpp b/layout/style/nsCSSRules.cpp index 74a3f3c4f86f..8c1403a9645b 100644 --- a/layout/style/nsCSSRules.cpp +++ b/layout/style/nsCSSRules.cpp @@ -1397,59 +1397,6 @@ DOMCI_DATA(CSSNameSpaceRule, css::NameSpaceRule) // nsCSSFontFaceStyleDecl and related routines // -// A src: descriptor is represented as an array value; each entry in -// the array can be eCSSUnit_URL, eCSSUnit_Local_Font, or -// eCSSUnit_Font_Format. Blocks of eCSSUnit_Font_Format may appear -// only after one of the first two. (css3-fonts only contemplates -// annotating URLs with formats, but we handle the general case.) -static void -AppendSerializedFontSrc(const nsCSSValue& src, nsAString & aResult) -{ - NS_PRECONDITION(src.GetUnit() == eCSSUnit_Array, - "improper value unit for src:"); - - const nsCSSValue::Array& sources = *src.GetArrayValue(); - size_t i = 0; - - while (i < sources.Count()) { - nsAutoString formats; - - if (sources[i].GetUnit() == eCSSUnit_URL) { - aResult.AppendLiteral("url("); - nsDependentString url(sources[i].GetOriginalURLValue()); - nsStyleUtil::AppendEscapedCSSString(url, aResult); - aResult.Append(')'); - } else if (sources[i].GetUnit() == eCSSUnit_Local_Font) { - aResult.AppendLiteral("local("); - nsDependentString local(sources[i].GetStringBufferValue()); - nsStyleUtil::AppendEscapedCSSString(local, aResult); - aResult.Append(')'); - } else { - NS_NOTREACHED("entry in src: descriptor with improper unit"); - i++; - continue; - } - - i++; - formats.Truncate(); - while (i < sources.Count() && - sources[i].GetUnit() == eCSSUnit_Font_Format) { - formats.Append('"'); - formats.Append(sources[i].GetStringBufferValue()); - formats.AppendLiteral("\", "); - i++; - } - if (formats.Length() > 0) { - formats.Truncate(formats.Length() - 2); // remove the last comma - aResult.AppendLiteral(" format("); - aResult.Append(formats); - aResult.Append(')'); - } - aResult.AppendLiteral(", "); - } - aResult.Truncate(aResult.Length() - 2); // remove the last comma-space -} - // Mapping from nsCSSFontDesc codes to nsCSSFontFaceStyleDecl fields. nsCSSValue nsCSSFontFaceStyleDecl::* const nsCSSFontFaceStyleDecl::Fields[] = { @@ -1531,7 +1478,7 @@ nsCSSFontFaceStyleDecl::GetPropertyValue(nsCSSFontDesc aFontDescID, return NS_OK; case eCSSFontDesc_Src: - AppendSerializedFontSrc(val, aResult); + nsStyleUtil::AppendSerializedFontSrc(val, aResult); return NS_OK; case eCSSFontDesc_UnicodeRange: diff --git a/layout/style/nsStyleUtil.cpp b/layout/style/nsStyleUtil.cpp index cc8147657dde..4ea19b0b0f96 100644 --- a/layout/style/nsStyleUtil.cpp +++ b/layout/style/nsStyleUtil.cpp @@ -507,6 +507,61 @@ nsStyleUtil::AppendUnicodeRange(const nsCSSValue& aValue, nsAString& aResult) CopyASCIItoUTF16(buf, aResult); } +/* static */ void +nsStyleUtil::AppendSerializedFontSrc(const nsCSSValue& aValue, + nsAString& aResult) +{ + // A src: descriptor is represented as an array value; each entry in + // the array can be eCSSUnit_URL, eCSSUnit_Local_Font, or + // eCSSUnit_Font_Format. Blocks of eCSSUnit_Font_Format may appear + // only after one of the first two. (css3-fonts only contemplates + // annotating URLs with formats, but we handle the general case.) + + NS_PRECONDITION(aValue.GetUnit() == eCSSUnit_Array, + "improper value unit for src:"); + + const nsCSSValue::Array& sources = *aValue.GetArrayValue(); + size_t i = 0; + + while (i < sources.Count()) { + nsAutoString formats; + + if (sources[i].GetUnit() == eCSSUnit_URL) { + aResult.AppendLiteral("url("); + nsDependentString url(sources[i].GetOriginalURLValue()); + nsStyleUtil::AppendEscapedCSSString(url, aResult); + aResult.Append(')'); + } else if (sources[i].GetUnit() == eCSSUnit_Local_Font) { + aResult.AppendLiteral("local("); + nsDependentString local(sources[i].GetStringBufferValue()); + nsStyleUtil::AppendEscapedCSSString(local, aResult); + aResult.Append(')'); + } else { + NS_NOTREACHED("entry in src: descriptor with improper unit"); + i++; + continue; + } + + i++; + formats.Truncate(); + while (i < sources.Count() && + sources[i].GetUnit() == eCSSUnit_Font_Format) { + formats.Append('"'); + formats.Append(sources[i].GetStringBufferValue()); + formats.AppendLiteral("\", "); + i++; + } + if (formats.Length() > 0) { + formats.Truncate(formats.Length() - 2); // remove the last comma + aResult.AppendLiteral(" format("); + aResult.Append(formats); + aResult.Append(')'); + } + aResult.AppendLiteral(", "); + } + aResult.Truncate(aResult.Length() - 2); // remove the last comma-space +} + /* static */ float nsStyleUtil::ColorComponentToFloat(uint8_t aAlpha) { diff --git a/layout/style/nsStyleUtil.h b/layout/style/nsStyleUtil.h index 2f910163d722..67d945a25a7c 100644 --- a/layout/style/nsStyleUtil.h +++ b/layout/style/nsStyleUtil.h @@ -71,6 +71,9 @@ public: aResult.AppendFloat(aNumber); } + static void AppendSerializedFontSrc(const nsCSSValue& aValue, + nsAString& aResult); + // convert bitmask value to keyword name for a functional alternate static void GetFunctionalAlternatesName(int32_t aFeature, nsAString& aFeatureName); From e3cdc514c42da7d436d9a6f134054df57ee48711 Mon Sep 17 00:00:00 2001 From: Dan Glastonbury Date: Tue, 27 May 2014 20:13:09 +1000 Subject: [PATCH 044/114] Bug 1048668 - WebGL2 - Implement CopyBufferSubData.; r=jgilbert --HG-- extra : source : b4c58b9519fc35c634d2a912f3900605ccc081a3 --- dom/canvas/WebGL2ContextBuffers.cpp | 3 ++- gfx/gl/GLContext.cpp | 15 +++++++++++++++ gfx/gl/GLContext.h | 14 ++++++++++++++ gfx/gl/GLContextFeatures.cpp | 9 +++++++++ gfx/gl/GLContextSymbols.h | 6 ++++++ 5 files changed, 46 insertions(+), 1 deletion(-) diff --git a/dom/canvas/WebGL2ContextBuffers.cpp b/dom/canvas/WebGL2ContextBuffers.cpp index 5244ebddf13e..41e12b4af43f 100644 --- a/dom/canvas/WebGL2ContextBuffers.cpp +++ b/dom/canvas/WebGL2ContextBuffers.cpp @@ -16,7 +16,8 @@ void WebGL2Context::CopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) { - MOZ_CRASH("Not Implemented."); + MakeContextCurrent(); + gl->fCopyBufferSubData(readTarget, writeTarget, readOffset, writeOffset, size); } void diff --git a/gfx/gl/GLContext.cpp b/gfx/gl/GLContext.cpp index b9641b881409..e9c97780a9e5 100644 --- a/gfx/gl/GLContext.cpp +++ b/gfx/gl/GLContext.cpp @@ -77,6 +77,7 @@ static const char *sExtensionNames[] = { "GL_ARB_ES2_compatibility", "GL_ARB_ES3_compatibility", "GL_ARB_color_buffer_float", + "GL_ARB_copy_buffer", "GL_ARB_depth_texture", "GL_ARB_draw_buffers", "GL_ARB_draw_instanced", @@ -1029,6 +1030,20 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl) } } + if (IsSupported(GLFeature::copy_buffer)) { + SymLoadStruct copyBufferSymbols[] = { + { (PRFuncPtr*) &mSymbols.fCopyBufferSubData, { "CopyBufferSubData", nullptr } }, + END_SYMBOLS + }; + + if (!LoadSymbols(copyBufferSymbols, trygl, prefix)) { + NS_ERROR("GL supports copy_buffer without supplying its function."); + + MarkUnsupported(GLFeature::copy_buffer); + ClearSymbols(copyBufferSymbols); + } + } + if (IsSupported(GLFeature::draw_buffers)) { SymLoadStruct coreSymbols[] = { { (PRFuncPtr*) &mSymbols.fDrawBuffers, { "DrawBuffers", nullptr } }, diff --git a/gfx/gl/GLContext.h b/gfx/gl/GLContext.h index 22fd42f6aa18..75d15faa8cd2 100644 --- a/gfx/gl/GLContext.h +++ b/gfx/gl/GLContext.h @@ -81,6 +81,7 @@ MOZ_BEGIN_ENUM_CLASS(GLFeature) bind_buffer_offset, blend_minmax, clear_buffers, + copy_buffer, depth_texture, draw_buffers, draw_instanced, @@ -347,6 +348,7 @@ public: ARB_ES2_compatibility, ARB_ES3_compatibility, ARB_color_buffer_float, + ARB_copy_buffer, ARB_depth_texture, ARB_draw_buffers, ARB_draw_instanced, @@ -2664,6 +2666,18 @@ public: AFTER_GL_CALL; } +// Core GL & Extension ARB_copy_buffer +public: + void fCopyBufferSubData(GLenum readtarget, GLenum writetarget, + GLintptr readoffset, GLintptr writeoffset, + GLsizeiptr size) + { + BEFORE_GL_CALL; + ASSERT_SYMBOL_PRESENT(fCopyBufferSubData); + mSymbols.fCopyBufferSubData(readtarget, writetarget, readoffset, writeoffset, size); + AFTER_GL_CALL; + } + // ----------------------------------------------------------------------------- // Constructor diff --git a/gfx/gl/GLContextFeatures.cpp b/gfx/gl/GLContextFeatures.cpp index 004588c951bb..f57c220a783c 100644 --- a/gfx/gl/GLContextFeatures.cpp +++ b/gfx/gl/GLContextFeatures.cpp @@ -80,6 +80,15 @@ static const FeatureInfo sFeatureInfoArr[] = { GLContext::Extensions_End } }, + { + "copy_buffer", + 310, // OpenGL version + 300, // OpenGL ES version + GLContext::ARB_copy_buffer, + { + GLContext::Extensions_End + } + }, { "depth_texture", 200, // OpenGL version diff --git a/gfx/gl/GLContextSymbols.h b/gfx/gl/GLContextSymbols.h index a508f5ef48bb..51ae2a10fcca 100644 --- a/gfx/gl/GLContextSymbols.h +++ b/gfx/gl/GLContextSymbols.h @@ -420,6 +420,12 @@ struct GLContextSymbols typedef realGLboolean (GLAPIENTRY * PFNGLUNMAPBUFFER) (GLenum target); PFNGLUNMAPBUFFER fUnmapBuffer; + // ARB_copy_buffer / OpenGL 3.1 / OpenGL ES 3.0 + typedef void (GLAPIENTRY * PFNGLCOPYBUFFERSUBDATAPROC) (GLenum readTarget, GLenum writeTarget, + GLintptr readOffset, GLintptr writeOffset, + GLsizeiptr size); + PFNGLCOPYBUFFERSUBDATAPROC fCopyBufferSubData; + typedef GLenum (GLAPIENTRY * PFNGLGETGRAPHICSRESETSTATUS) (void); PFNGLGETGRAPHICSRESETSTATUS fGetGraphicsResetStatus; From 113341cd899b0d2100e39f6211512c44c56aa2bd Mon Sep 17 00:00:00 2001 From: David Major Date: Mon, 22 Sep 2014 13:52:28 +1200 Subject: [PATCH 045/114] Bug 1067679 followup - fix build bustage with VS2013. --HG-- extra : rebase_source : 63b5b6795d53d70b2d3b3efa1efee1ea2ae2b9df --- netwerk/dns/GetAddrInfo.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/netwerk/dns/GetAddrInfo.cpp b/netwerk/dns/GetAddrInfo.cpp index 952c56f4f6cc..270e27345512 100644 --- a/netwerk/dns/GetAddrInfo.cpp +++ b/netwerk/dns/GetAddrInfo.cpp @@ -19,6 +19,7 @@ #include "MainThreadUtils.h" #include "mozilla/DebugOnly.h" #include "mozilla/net/DNS.h" +#include #include "prlog.h" #if defined(PR_LOGGING) From 7f81beb5706b037a1d74998b6c614aa081f38802 Mon Sep 17 00:00:00 2001 From: Timothy Arceri Date: Thu, 18 Sep 2014 08:17:11 +1000 Subject: [PATCH 046/114] b=1068964 Bump GTK required version to 2.18.0 r=karlt Now that Seamonkey is building with CentOS 6 we can bump the gtk version ready for some code tidy ups. --HG-- extra : transplant_source : q%B0%27%5By%171%F2%21%04Q%B4%07s%0A%9C%BC%19%3C%8B --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 5ee9bb9a9d62..1f922eed4d64 100644 --- a/configure.in +++ b/configure.in @@ -62,7 +62,7 @@ GLIB_VERSION=1.2.0 PERL_VERSION=5.006 CAIRO_VERSION=1.10 PANGO_VERSION=1.22.0 -GTK2_VERSION=2.10.0 +GTK2_VERSION=2.18.0 GTK3_VERSION=3.0.0 WINDRES_VERSION=2.14.90 W32API_VERSION=3.14 From 5ddca8d5dd50140839ed25e9694dc51f26badd75 Mon Sep 17 00:00:00 2001 From: Timothy Arceri Date: Thu, 18 Sep 2014 16:23:57 +1000 Subject: [PATCH 047/114] b=1068964 Remove gtk_check_version for GTK 2 r=karlt Remove gtk_check_version() checks for GTK 2 as the minimum version now covers all cases --HG-- extra : transplant_source : Z%F4%8A2%B1a%D4%16%3B%C1%9F%92b%92%15%3E%AB%9Cg%81 --- widget/gtk/nsGtkIMModule.cpp | 31 +------------------------------ 1 file changed, 1 insertion(+), 30 deletions(-) diff --git a/widget/gtk/nsGtkIMModule.cpp b/widget/gtk/nsGtkIMModule.cpp index b308cceb3e06..65e6a43eb2f9 100644 --- a/widget/gtk/nsGtkIMModule.cpp +++ b/widget/gtk/nsGtkIMModule.cpp @@ -263,36 +263,7 @@ nsGtkIMModule::PrepareToDestroyContext(GtkIMContext *aContext) GType slaveType = G_TYPE_FROM_INSTANCE(slave); const gchar *im_type_name = g_type_name(slaveType); - if (strcmp(im_type_name, "GtkIMContextXIM") == 0) { - if (gtk_check_version(2, 12, 1) == nullptr) { - return; // gtk bug has been fixed - } - - struct GtkIMContextXIM - { - GtkIMContext parent; - gpointer private_data; - // ... other fields - }; - - gpointer signal_data = - reinterpret_cast(slave)->private_data; - if (!signal_data) { - return; - } - - g_signal_handlers_disconnect_matched( - gtk_widget_get_display(GTK_WIDGET(container)), - G_SIGNAL_MATCH_DATA, 0, 0, nullptr, nullptr, signal_data); - - // Add a reference to prevent the XIM module from being unloaded - // and reloaded: each time the module is loaded and used, it - // opens (and doesn't close) new XOpenIM connections. - static gpointer gtk_xim_context_class = - g_type_class_ref(slaveType); - // Mute unused variable warning: - (void)gtk_xim_context_class; - } else if (strcmp(im_type_name, "GtkIMContextIIIM") == 0) { + if (strcmp(im_type_name, "GtkIMContextIIIM") == 0) { // Add a reference to prevent the IIIM module from being unloaded static gpointer gtk_iiim_context_class = g_type_class_ref(slaveType); From b21342338f667afccbde61f71a8b1e238913d3e5 Mon Sep 17 00:00:00 2001 From: Timothy Arceri Date: Thu, 18 Sep 2014 15:59:01 +1000 Subject: [PATCH 048/114] b=1068964 Cleanup GTK print includes r=karlt --HG-- extra : transplant_source : %18%ED%1B%24%9C%AB%FDA%F8%BE%A3%85%92h%F1%B0%FF%92D%8D --- config/system-headers | 4 +--- widget/gtk/nsDeviceContextSpecG.h | 5 ----- widget/gtk/nsPrintDialogGTK.cpp | 4 ---- widget/gtk/nsPrintSettingsGTK.h | 5 ----- 4 files changed, 1 insertion(+), 17 deletions(-) diff --git a/config/system-headers b/config/system-headers index 39e812734833..31967bbf216b 100644 --- a/config/system-headers +++ b/config/system-headers @@ -508,9 +508,7 @@ gssapi/gssapi.h gssapi.h gtk/gtk.h gtk/gtkx.h -gtk/gtkprinter.h -gtk/gtkprintjob.h -gtk/gtkprintunixdialog.h +gtk/gtkunixprint.h #ifdef ANDROID gui/BufferQueue.h gui/ConsumerBase.h diff --git a/widget/gtk/nsDeviceContextSpecG.h b/widget/gtk/nsDeviceContextSpecG.h index 330d76b8d73d..d45993d6971e 100644 --- a/widget/gtk/nsDeviceContextSpecG.h +++ b/widget/gtk/nsDeviceContextSpecG.h @@ -16,12 +16,7 @@ #include "nsCRT.h" /* should be ? */ #include -#if (MOZ_WIDGET_GTK == 2) -#include -#include -#else #include -#endif #define NS_PORTRAIT 0 #define NS_LANDSCAPE 1 diff --git a/widget/gtk/nsPrintDialogGTK.cpp b/widget/gtk/nsPrintDialogGTK.cpp index b230e18a23e3..9c2aa83c836e 100644 --- a/widget/gtk/nsPrintDialogGTK.cpp +++ b/widget/gtk/nsPrintDialogGTK.cpp @@ -4,11 +4,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include -#if (MOZ_WIDGET_GTK == 2) -#include -#else #include -#endif #include #include "mozilla/ArrayUtils.h" diff --git a/widget/gtk/nsPrintSettingsGTK.h b/widget/gtk/nsPrintSettingsGTK.h index 7a0b87565b3d..a02e917fca82 100644 --- a/widget/gtk/nsPrintSettingsGTK.h +++ b/widget/gtk/nsPrintSettingsGTK.h @@ -11,12 +11,7 @@ extern "C" { #include -#if (MOZ_WIDGET_GTK == 2) -#include -#include -#else #include -#endif } #define NS_PRINTSETTINGSGTK_IID \ From 5c4bd64854f5c0e18baae67554a06264ca0ed0d1 Mon Sep 17 00:00:00 2001 From: Timothy Arceri Date: Thu, 18 Sep 2014 16:16:52 +1000 Subject: [PATCH 049/114] b=1068964 Remove GTK_CHECK_VERSION for GTK 2 r=karlt Remove all GTK_CHECK_VERSION checks for GTK 2 as the minimum version now covers all cases --HG-- extra : transplant_source : %CE%3A%BC%CCm%F3EO%CA%15Z%B9%90%3C%14j%A0%16%851 --- widget/gtk/compat/gtk/gtkcolorseldialog.h | 17 ----- widget/gtk/compat/gtk/gtkdialog.h | 15 ----- widget/gtk/compat/gtk/gtkplug.h | 15 ----- widget/gtk/compat/gtk/gtkselection.h | 35 ----------- widget/gtk/compat/gtk/gtkwidget.h | 76 ----------------------- widget/gtk/nsFilePicker.cpp | 2 - 6 files changed, 160 deletions(-) delete mode 100644 widget/gtk/compat/gtk/gtkcolorseldialog.h delete mode 100644 widget/gtk/compat/gtk/gtkdialog.h delete mode 100644 widget/gtk/compat/gtk/gtkplug.h delete mode 100644 widget/gtk/compat/gtk/gtkselection.h diff --git a/widget/gtk/compat/gtk/gtkcolorseldialog.h b/widget/gtk/compat/gtk/gtkcolorseldialog.h deleted file mode 100644 index fca7943e5a44..000000000000 --- a/widget/gtk/compat/gtk/gtkcolorseldialog.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef GTKCOLORSELDIALOG_WRAPPER_H -#define GTKCOLORSELDIALOG_WRAPPER_H - -#include_next -#include - -#if !GTK_CHECK_VERSION(2, 14, 0) -static inline GtkWidget* -gtk_color_selection_dialog_get_color_selection(GtkColorSelectionDialog* colorseldialog) -{ - GtkWidget* colorsel; - g_object_get(colorseldialog, "color-selection", &colorsel, NULL); - return colorsel; -} -#endif // GTK_CHECK_VERSION - -#endif // GTKCOLORSELDIALOG_WRAPPER_H diff --git a/widget/gtk/compat/gtk/gtkdialog.h b/widget/gtk/compat/gtk/gtkdialog.h deleted file mode 100644 index ad7129a347ef..000000000000 --- a/widget/gtk/compat/gtk/gtkdialog.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef GTKDIALOG_WRAPPER_H -#define GTKDIALOG_WRAPPER_H - -#include_next -#include - -#if !GTK_CHECK_VERSION(2, 14, 0) -static inline GtkWidget * -gtk_dialog_get_content_area(GtkDialog *dialog) -{ - return dialog->vbox; -} -#endif - -#endif /* GTKDIALOG_WRAPPER_H */ diff --git a/widget/gtk/compat/gtk/gtkplug.h b/widget/gtk/compat/gtk/gtkplug.h deleted file mode 100644 index 2cb35e1bd080..000000000000 --- a/widget/gtk/compat/gtk/gtkplug.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef GTKPLUG_WRAPPER_H -#define GTKPLUG_WRAPPER_H - -#include_next -#include - -#if !GTK_CHECK_VERSION(2, 14, 0) -static inline GdkWindow * -gtk_plug_get_socket_window(GtkPlug *plug) -{ - return plug->socket_window; -} -#endif - -#endif /* GTKPLUG_WRAPPER_H */ diff --git a/widget/gtk/compat/gtk/gtkselection.h b/widget/gtk/compat/gtk/gtkselection.h deleted file mode 100644 index 203e78bd9d89..000000000000 --- a/widget/gtk/compat/gtk/gtkselection.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef GTKSELECTION_WRAPPER_H -#define GTKSELECTION_WRAPPER_H - -#include_next -#include - -#if !GTK_CHECK_VERSION(2, 16, 0) -static inline GdkAtom -gtk_selection_data_get_selection(GtkSelectionData *selection_data) -{ - return selection_data->selection; -} -#endif - -#if !GTK_CHECK_VERSION(2, 14, 0) -static inline const guchar * -gtk_selection_data_get_data(GtkSelectionData *selection_data) -{ - return selection_data->data; -} - -static inline gint -gtk_selection_data_get_length(GtkSelectionData *selection_data) -{ - return selection_data->length; -} - -static inline GdkAtom -gtk_selection_data_get_target(GtkSelectionData *selection_data) -{ - return selection_data->target; -} -#endif - -#endif /* GTKSELECTION_WRAPPER_H */ diff --git a/widget/gtk/compat/gtk/gtkwidget.h b/widget/gtk/compat/gtk/gtkwidget.h index c8d487e08b9a..b1d4d140575e 100644 --- a/widget/gtk/compat/gtk/gtkwidget.h +++ b/widget/gtk/compat/gtk/gtkwidget.h @@ -47,80 +47,4 @@ gtk_widget_get_realized(GtkWidget *widget) return GTK_WIDGET_REALIZED (widget); } -#if !GTK_CHECK_VERSION(2, 18, 0) -static inline gboolean -gtk_widget_get_visible(GtkWidget *widget) -{ - return GTK_WIDGET_VISIBLE(widget); -} - -static inline gboolean -gtk_widget_has_focus(GtkWidget *widget) -{ - return GTK_WIDGET_HAS_FOCUS(widget); -} - -static inline gboolean -gtk_widget_has_grab(GtkWidget *widget) -{ - return GTK_WIDGET_HAS_GRAB(widget); -} - -static inline gboolean -gtk_widget_get_has_window(GtkWidget *widget) -{ - return !GTK_WIDGET_NO_WINDOW(widget); -} - -static inline void -gtk_widget_get_allocation(GtkWidget *widget, GtkAllocation *allocation) -{ - *allocation = widget->allocation; -} - -static inline void -gtk_widget_set_allocation(GtkWidget *widget, const GtkAllocation *allocation) -{ - widget->allocation = *allocation; -} - -static inline void -gtk_widget_set_can_focus(GtkWidget *widget, gboolean can_focus) -{ - if (can_focus) - GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS); - else - GTK_WIDGET_UNSET_FLAGS (widget, GTK_CAN_FOCUS); -} - -static inline void -gtk_widget_set_has_window(GtkWidget *widget, gboolean has_window) -{ - if (has_window) - GTK_WIDGET_UNSET_FLAGS (widget, GTK_NO_WINDOW); - else - GTK_WIDGET_SET_FLAGS (widget, GTK_NO_WINDOW); -} - -static inline void -gtk_widget_set_window(GtkWidget *widget, GdkWindow *window) -{ - widget->window = window; -} - -static inline gboolean -gtk_widget_is_toplevel(GtkWidget *widget) -{ - return GTK_WIDGET_TOPLEVEL(widget); -} -#endif - -#if !GTK_CHECK_VERSION(2, 14, 0) -static inline GdkWindow* -gtk_widget_get_window(GtkWidget *widget) -{ - return widget->window; -} -#endif - #endif /* GTKWIDGET_WRAPPER_H */ diff --git a/widget/gtk/nsFilePicker.cpp b/widget/gtk/nsFilePicker.cpp index 562947e9c8ef..cf0b25bbf709 100644 --- a/widget/gtk/nsFilePicker.cpp +++ b/widget/gtk/nsFilePicker.cpp @@ -106,11 +106,9 @@ UpdateFilePreviewWidget(GtkFileChooser *file_chooser, return; } -#if GTK_CHECK_VERSION(2,12,0) GdkPixbuf *preview_pixbuf_temp = preview_pixbuf; preview_pixbuf = gdk_pixbuf_apply_embedded_orientation(preview_pixbuf_temp); g_object_unref(preview_pixbuf_temp); -#endif // This is the easiest way to do center alignment without worrying about containers // Minimum 3px padding each side (hence the 6) just to make things nice From 922ba93d0c36545ee39949a0827a0b641cb26841 Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Thu, 24 Jul 2014 09:44:59 +1200 Subject: [PATCH 050/114] b=1000044 use direct resampler for 16->44.1k r=jmspeex This also changes the HUGEMEM test to be independent of quality. |oversample| has a maximum value of 32, so we know that the interpolating resampler will use less memory when st->den_rate > 441. --HG-- extra : transplant_source : vl%C1d%A5%FB%3Cd%FBC%86%FD%26%EC%FB%C0%5C%26%7D%8C --- media/libspeex_resampler/hugemem.patch | 12 ++++++++---- media/libspeex_resampler/src/resample.c | 8 +++++--- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/media/libspeex_resampler/hugemem.patch b/media/libspeex_resampler/hugemem.patch index 81462ab6bccf..4e1f5baa6cf3 100644 --- a/media/libspeex_resampler/hugemem.patch +++ b/media/libspeex_resampler/hugemem.patch @@ -20,7 +20,8 @@ diff --git a/media/libspeex_resampler/src/resample.c b/media/libspeex_resampler/ #include "speex_resampler.h" #include "arch.h" #else /* OUTSIDE_SPEEX */ -@@ -633,24 +635,23 @@ static int update_filter(SpeexResamplerS +@@ -632,25 +634,26 @@ static int update_filter(SpeexResamplerS + st->oversample >>= 1; if (st->oversample < 1) st->oversample = 1; } else { @@ -28,17 +29,20 @@ diff --git a/media/libspeex_resampler/src/resample.c b/media/libspeex_resampler/ st->cutoff = quality_map[st->quality].upsample_bandwidth; } - /* Choose the resampling type that requires the least amount of memory */ +- /* Choose the resampling type that requires the least amount of memory */ -#ifdef RESAMPLE_FULL_SINC_TABLE - use_direct = 1; - if (INT_MAX/sizeof(spx_word16_t)/st->den_rate < st->filt_len) - goto fail; + use_direct = +#ifdef RESAMPLE_HUGEMEM -+ st->den_rate <= 16*(st->oversample+8) ++ /* Choose the direct resampler, even with higher initialization costs, ++ when resampling any multiple of 100 to 44100. */ ++ st->den_rate <= 441 #else - use_direct = st->filt_len*st->den_rate <= st->filt_len*st->oversample+8 -+ st->filt_len*st->den_rate <= st->filt_len*st->oversample+8 ++ /* Choose the resampling type that requires the least amount of memory */ ++ st->filt_len*st->den_rate <= st->filt_len*st->oversample+8 +#endif && INT_MAX/sizeof(spx_word16_t)/st->den_rate >= st->filt_len; -#endif diff --git a/media/libspeex_resampler/src/resample.c b/media/libspeex_resampler/src/resample.c index a3a22ee8b36d..83ad119d4513 100644 --- a/media/libspeex_resampler/src/resample.c +++ b/media/libspeex_resampler/src/resample.c @@ -639,12 +639,14 @@ static int update_filter(SpeexResamplerState *st) st->cutoff = quality_map[st->quality].upsample_bandwidth; } - /* Choose the resampling type that requires the least amount of memory */ use_direct = #ifdef RESAMPLE_HUGEMEM - st->den_rate <= 16*(st->oversample+8) + /* Choose the direct resampler, even with higher initialization costs, + when resampling any multiple of 100 to 44100. */ + st->den_rate <= 441 #else - st->filt_len*st->den_rate <= st->filt_len*st->oversample+8 + /* Choose the resampling type that requires the least amount of memory */ + st->filt_len*st->den_rate <= st->filt_len*st->oversample+8 #endif && INT_MAX/sizeof(spx_word16_t)/st->den_rate >= st->filt_len; if (use_direct) From f9cddf833199cbcd89e388fc594bb77730c92f9c Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Fri, 12 Sep 2014 17:29:35 +1200 Subject: [PATCH 051/114] b=1069113 explicitly unset media.mediasource.enabled when testing disabling of MediaSource r=kinetik so that web platform tests can be run with MediaSource enabled. --HG-- extra : transplant_source : %C9%01%A22%DF%8C%89%CF%7E6%0E%FCR%EE%0E%BE%15%B1%D2%92 --- content/media/mediasource/test/mochitest.ini | 1 + .../mediasource/test/test_MediaSource.html | 6 ---- .../test/test_MediaSource_disabled.html | 28 +++++++++++++++++++ 3 files changed, 29 insertions(+), 6 deletions(-) create mode 100644 content/media/mediasource/test/test_MediaSource_disabled.html diff --git a/content/media/mediasource/test/mochitest.ini b/content/media/mediasource/test/mochitest.ini index 044b5037ac54..7701e71e4bbd 100644 --- a/content/media/mediasource/test/mochitest.ini +++ b/content/media/mediasource/test/mochitest.ini @@ -8,6 +8,7 @@ support-files = [test_BufferedSeek.html] [test_FrameSelection.html] [test_MediaSource.html] +[test_MediaSource_disabled.html] [test_SeekableAfterEndOfStream.html] [test_SeekableAfterEndOfStreamSplit.html] [test_SeekableBeforeEndOfStream.html] diff --git a/content/media/mediasource/test/test_MediaSource.html b/content/media/mediasource/test/test_MediaSource.html index f424b50a4e63..131d64b1c485 100644 --- a/content/media/mediasource/test/test_MediaSource.html +++ b/content/media/mediasource/test/test_MediaSource.html @@ -12,12 +12,6 @@ SimpleTest.waitForExplicitFinish(); -addLoadEvent(function () { - ok(!window.MediaSource && !window.SourceBuffer && !window.SourceBufferList, - "MediaSource should be hidden behind a pref"); - SimpleTest.doesThrow(() => new MediaSource, "MediaSource should be hidden behind a pref"); -}); - runWithMSE(function () { SimpleTest.doesThrow(() => new SourceBuffer, "new SourceBuffer should fail"); SimpleTest.doesThrow(() => new SourceBufferList, "new SourceBufferList direct should fail"); diff --git a/content/media/mediasource/test/test_MediaSource_disabled.html b/content/media/mediasource/test/test_MediaSource_disabled.html new file mode 100644 index 000000000000..e4d8d40a3f7d --- /dev/null +++ b/content/media/mediasource/test/test_MediaSource_disabled.html @@ -0,0 +1,28 @@ + + + + MSE: disabling via pref + + + + +
+
+
+ + From 14950615671eed8c349ab50d2567ea3fe0eca793 Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Thu, 18 Sep 2014 18:17:42 +1200 Subject: [PATCH 052/114] b=1066467 disable MediaSource tests that are unstable or interact badly with other tests r=kinetik --HG-- extra : transplant_source : %0B%14%3F%12w%A6%A2%C9%0E%7Eu%7E%83%D8%B3%C3%D7l%F79 --- .../mediasource-buffered.html.ini | 4 +--- ...ource-config-change-mp4-a-bitrate.html.ini | 4 +--- ...onfig-change-mp4-av-audio-bitrate.html.ini | 4 +--- ...ce-config-change-mp4-av-framesize.html.ini | 4 +--- ...onfig-change-mp4-av-video-bitrate.html.ini | 4 +--- ...ource-config-change-mp4-v-bitrate.html.ini | 4 +--- ...rce-config-change-mp4-v-framerate.html.ini | 4 +--- ...rce-config-change-mp4-v-framesize.html.ini | 4 +--- ...urce-config-change-webm-a-bitrate.html.ini | 4 +--- ...nfig-change-webm-av-audio-bitrate.html.ini | 4 +--- ...e-config-change-webm-av-framesize.html.ini | 4 +--- ...nfig-change-webm-av-video-bitrate.html.ini | 4 +--- ...urce-config-change-webm-v-bitrate.html.ini | 4 +--- ...ce-config-change-webm-v-framerate.html.ini | 4 +--- ...ce-config-change-webm-v-framesize.html.ini | 4 +--- .../mediasource-duration.html.ini | 13 +------------ ...diasource-getvideoplaybackquality.html.ini | 4 +--- .../mediasource-play-then-seek-back.html.ini | 4 +--- .../media-source/mediasource-play.html.ini | 4 +--- .../mediasource-redundant-seek.html.ini | 4 +--- .../mediasource-seek-beyond-duration.html.ini | 7 +------ ...iasource-seek-during-pending-seek.html.ini | 7 +------ .../mediasource-sourcebuffer-mode.html.ini | 19 +------------------ 23 files changed, 23 insertions(+), 99 deletions(-) diff --git a/testing/web-platform/meta/media-source/mediasource-buffered.html.ini b/testing/web-platform/meta/media-source/mediasource-buffered.html.ini index 49003756afb6..682414409a21 100644 --- a/testing/web-platform/meta/media-source/mediasource-buffered.html.ini +++ b/testing/web-platform/meta/media-source/mediasource-buffered.html.ini @@ -1,5 +1,3 @@ [mediasource-buffered.html] type: testharness - [SourceBuffer.buffered test cases.] - expected: FAIL - + disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1066467 diff --git a/testing/web-platform/meta/media-source/mediasource-config-change-mp4-a-bitrate.html.ini b/testing/web-platform/meta/media-source/mediasource-config-change-mp4-a-bitrate.html.ini index bac178b41b5d..6547fa045efb 100644 --- a/testing/web-platform/meta/media-source/mediasource-config-change-mp4-a-bitrate.html.ini +++ b/testing/web-platform/meta/media-source/mediasource-config-change-mp4-a-bitrate.html.ini @@ -1,5 +1,3 @@ [mediasource-config-change-mp4-a-bitrate.html] type: testharness - [Tests mp4 audio-only bitrate changes.] - expected: FAIL - + disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1066467 diff --git a/testing/web-platform/meta/media-source/mediasource-config-change-mp4-av-audio-bitrate.html.ini b/testing/web-platform/meta/media-source/mediasource-config-change-mp4-av-audio-bitrate.html.ini index 68ddfa906b57..45fd4061d110 100644 --- a/testing/web-platform/meta/media-source/mediasource-config-change-mp4-av-audio-bitrate.html.ini +++ b/testing/web-platform/meta/media-source/mediasource-config-change-mp4-av-audio-bitrate.html.ini @@ -1,5 +1,3 @@ [mediasource-config-change-mp4-av-audio-bitrate.html] type: testharness - [Tests mp4 audio bitrate changes in multiplexed content.] - expected: FAIL - + disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1066467 diff --git a/testing/web-platform/meta/media-source/mediasource-config-change-mp4-av-framesize.html.ini b/testing/web-platform/meta/media-source/mediasource-config-change-mp4-av-framesize.html.ini index 47c5d53465b5..655e637ade00 100644 --- a/testing/web-platform/meta/media-source/mediasource-config-change-mp4-av-framesize.html.ini +++ b/testing/web-platform/meta/media-source/mediasource-config-change-mp4-av-framesize.html.ini @@ -1,5 +1,3 @@ [mediasource-config-change-mp4-av-framesize.html] type: testharness - [Tests mp4 frame size changes in multiplexed content.] - expected: FAIL - + disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1066467 diff --git a/testing/web-platform/meta/media-source/mediasource-config-change-mp4-av-video-bitrate.html.ini b/testing/web-platform/meta/media-source/mediasource-config-change-mp4-av-video-bitrate.html.ini index 37d35deae582..7b58fc5a8a0c 100644 --- a/testing/web-platform/meta/media-source/mediasource-config-change-mp4-av-video-bitrate.html.ini +++ b/testing/web-platform/meta/media-source/mediasource-config-change-mp4-av-video-bitrate.html.ini @@ -1,5 +1,3 @@ [mediasource-config-change-mp4-av-video-bitrate.html] type: testharness - [Tests mp4 video bitrate changes in multiplexed content.] - expected: FAIL - + disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1066467 diff --git a/testing/web-platform/meta/media-source/mediasource-config-change-mp4-v-bitrate.html.ini b/testing/web-platform/meta/media-source/mediasource-config-change-mp4-v-bitrate.html.ini index d4f30e02e1da..728d83f02f94 100644 --- a/testing/web-platform/meta/media-source/mediasource-config-change-mp4-v-bitrate.html.ini +++ b/testing/web-platform/meta/media-source/mediasource-config-change-mp4-v-bitrate.html.ini @@ -1,5 +1,3 @@ [mediasource-config-change-mp4-v-bitrate.html] type: testharness - [Tests mp4 video-only bitrate changes.] - expected: FAIL - + disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1066467 diff --git a/testing/web-platform/meta/media-source/mediasource-config-change-mp4-v-framerate.html.ini b/testing/web-platform/meta/media-source/mediasource-config-change-mp4-v-framerate.html.ini index 7fcf76f9e170..a3e998d35746 100644 --- a/testing/web-platform/meta/media-source/mediasource-config-change-mp4-v-framerate.html.ini +++ b/testing/web-platform/meta/media-source/mediasource-config-change-mp4-v-framerate.html.ini @@ -1,5 +1,3 @@ [mediasource-config-change-mp4-v-framerate.html] type: testharness - [Tests mp4 video-only frame rate changes.] - expected: FAIL - + disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1066467 diff --git a/testing/web-platform/meta/media-source/mediasource-config-change-mp4-v-framesize.html.ini b/testing/web-platform/meta/media-source/mediasource-config-change-mp4-v-framesize.html.ini index 37d1e217409f..a8beb3268c31 100644 --- a/testing/web-platform/meta/media-source/mediasource-config-change-mp4-v-framesize.html.ini +++ b/testing/web-platform/meta/media-source/mediasource-config-change-mp4-v-framesize.html.ini @@ -1,5 +1,3 @@ [mediasource-config-change-mp4-v-framesize.html] type: testharness - [Tests mp4 video-only frame size changes.] - expected: FAIL - + disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1066467 diff --git a/testing/web-platform/meta/media-source/mediasource-config-change-webm-a-bitrate.html.ini b/testing/web-platform/meta/media-source/mediasource-config-change-webm-a-bitrate.html.ini index 9f2d8d56aa7b..34efa799dd23 100644 --- a/testing/web-platform/meta/media-source/mediasource-config-change-webm-a-bitrate.html.ini +++ b/testing/web-platform/meta/media-source/mediasource-config-change-webm-a-bitrate.html.ini @@ -1,5 +1,3 @@ [mediasource-config-change-webm-a-bitrate.html] type: testharness - [Tests webm audio-only bitrate changes.] - expected: FAIL - + disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1066467 diff --git a/testing/web-platform/meta/media-source/mediasource-config-change-webm-av-audio-bitrate.html.ini b/testing/web-platform/meta/media-source/mediasource-config-change-webm-av-audio-bitrate.html.ini index eff01438b967..d0cbe7a1bab4 100644 --- a/testing/web-platform/meta/media-source/mediasource-config-change-webm-av-audio-bitrate.html.ini +++ b/testing/web-platform/meta/media-source/mediasource-config-change-webm-av-audio-bitrate.html.ini @@ -1,5 +1,3 @@ [mediasource-config-change-webm-av-audio-bitrate.html] type: testharness - [Tests webm audio bitrate changes in multiplexed content.] - expected: FAIL - + disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1066467 diff --git a/testing/web-platform/meta/media-source/mediasource-config-change-webm-av-framesize.html.ini b/testing/web-platform/meta/media-source/mediasource-config-change-webm-av-framesize.html.ini index e0111b148a76..62af59b2ef4f 100644 --- a/testing/web-platform/meta/media-source/mediasource-config-change-webm-av-framesize.html.ini +++ b/testing/web-platform/meta/media-source/mediasource-config-change-webm-av-framesize.html.ini @@ -1,5 +1,3 @@ [mediasource-config-change-webm-av-framesize.html] type: testharness - [Tests webm frame size changes in multiplexed content.] - expected: FAIL - + disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1066467 diff --git a/testing/web-platform/meta/media-source/mediasource-config-change-webm-av-video-bitrate.html.ini b/testing/web-platform/meta/media-source/mediasource-config-change-webm-av-video-bitrate.html.ini index b1a947121be7..c2d1d3549324 100644 --- a/testing/web-platform/meta/media-source/mediasource-config-change-webm-av-video-bitrate.html.ini +++ b/testing/web-platform/meta/media-source/mediasource-config-change-webm-av-video-bitrate.html.ini @@ -1,5 +1,3 @@ [mediasource-config-change-webm-av-video-bitrate.html] type: testharness - [Tests webm video bitrate changes in multiplexed content.] - expected: FAIL - + disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1066467 diff --git a/testing/web-platform/meta/media-source/mediasource-config-change-webm-v-bitrate.html.ini b/testing/web-platform/meta/media-source/mediasource-config-change-webm-v-bitrate.html.ini index dd735661a26b..cc3eae45a9f6 100644 --- a/testing/web-platform/meta/media-source/mediasource-config-change-webm-v-bitrate.html.ini +++ b/testing/web-platform/meta/media-source/mediasource-config-change-webm-v-bitrate.html.ini @@ -1,5 +1,3 @@ [mediasource-config-change-webm-v-bitrate.html] type: testharness - [Tests webm video-only bitrate changes.] - expected: FAIL - + disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1066467 diff --git a/testing/web-platform/meta/media-source/mediasource-config-change-webm-v-framerate.html.ini b/testing/web-platform/meta/media-source/mediasource-config-change-webm-v-framerate.html.ini index c56d146e1cf5..6805af998798 100644 --- a/testing/web-platform/meta/media-source/mediasource-config-change-webm-v-framerate.html.ini +++ b/testing/web-platform/meta/media-source/mediasource-config-change-webm-v-framerate.html.ini @@ -1,5 +1,3 @@ [mediasource-config-change-webm-v-framerate.html] type: testharness - [Tests webm video-only frame rate changes.] - expected: FAIL - + disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1066467 diff --git a/testing/web-platform/meta/media-source/mediasource-config-change-webm-v-framesize.html.ini b/testing/web-platform/meta/media-source/mediasource-config-change-webm-v-framesize.html.ini index 00260760f3de..35cb72f445e2 100644 --- a/testing/web-platform/meta/media-source/mediasource-config-change-webm-v-framesize.html.ini +++ b/testing/web-platform/meta/media-source/mediasource-config-change-webm-v-framesize.html.ini @@ -1,5 +1,3 @@ [mediasource-config-change-webm-v-framesize.html] type: testharness - [Tests webm video-only frame size changes.] - expected: FAIL - + disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1066467 diff --git a/testing/web-platform/meta/media-source/mediasource-duration.html.ini b/testing/web-platform/meta/media-source/mediasource-duration.html.ini index 231dcc67580c..1705d3dbbc41 100644 --- a/testing/web-platform/meta/media-source/mediasource-duration.html.ini +++ b/testing/web-platform/meta/media-source/mediasource-duration.html.ini @@ -1,14 +1,3 @@ [mediasource-duration.html] type: testharness - [Test seek starts on duration truncation below currentTime] - expected: FAIL - - [Test appendBuffer completes previous seek to truncated duration] - expected: FAIL - - [Test endOfStream completes previous seek to truncated duration] - expected: FAIL - - [Test setting same duration multiple times does not fire duplicate durationchange] - expected: FAIL - + disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1066467 diff --git a/testing/web-platform/meta/media-source/mediasource-getvideoplaybackquality.html.ini b/testing/web-platform/meta/media-source/mediasource-getvideoplaybackquality.html.ini index e63ec88ed3e7..a1e333de9b2a 100644 --- a/testing/web-platform/meta/media-source/mediasource-getvideoplaybackquality.html.ini +++ b/testing/web-platform/meta/media-source/mediasource-getvideoplaybackquality.html.ini @@ -1,5 +1,3 @@ [mediasource-getvideoplaybackquality.html] type: testharness - [Test HTMLVideoElement.getVideoPlaybackQuality() with MediaSource API] - expected: FAIL - + disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1066467 diff --git a/testing/web-platform/meta/media-source/mediasource-play-then-seek-back.html.ini b/testing/web-platform/meta/media-source/mediasource-play-then-seek-back.html.ini index ee5d093010ef..4cfdd320d76c 100644 --- a/testing/web-platform/meta/media-source/mediasource-play-then-seek-back.html.ini +++ b/testing/web-platform/meta/media-source/mediasource-play-then-seek-back.html.ini @@ -1,5 +1,3 @@ [mediasource-play-then-seek-back.html] type: testharness - [Test playing then seeking back.] - expected: FAIL - + disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1066467 diff --git a/testing/web-platform/meta/media-source/mediasource-play.html.ini b/testing/web-platform/meta/media-source/mediasource-play.html.ini index 40518e66a4eb..d9b24c833d94 100644 --- a/testing/web-platform/meta/media-source/mediasource-play.html.ini +++ b/testing/web-platform/meta/media-source/mediasource-play.html.ini @@ -1,5 +1,3 @@ [mediasource-play.html] type: testharness - [Test normal playback case with MediaSource API] - expected: FAIL - + disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1066467 diff --git a/testing/web-platform/meta/media-source/mediasource-redundant-seek.html.ini b/testing/web-platform/meta/media-source/mediasource-redundant-seek.html.ini index 525be3649e92..fc3feeffb15d 100644 --- a/testing/web-platform/meta/media-source/mediasource-redundant-seek.html.ini +++ b/testing/web-platform/meta/media-source/mediasource-redundant-seek.html.ini @@ -1,5 +1,3 @@ [mediasource-redundant-seek.html] type: testharness - [Test redundant fully prebuffered seek] - expected: FAIL - + disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1066467 diff --git a/testing/web-platform/meta/media-source/mediasource-seek-beyond-duration.html.ini b/testing/web-platform/meta/media-source/mediasource-seek-beyond-duration.html.ini index 8452ef130919..34ce5a3b7f22 100644 --- a/testing/web-platform/meta/media-source/mediasource-seek-beyond-duration.html.ini +++ b/testing/web-platform/meta/media-source/mediasource-seek-beyond-duration.html.ini @@ -1,8 +1,3 @@ [mediasource-seek-beyond-duration.html] type: testharness - [Test seeking beyond updated media duration.] - expected: FAIL - - [Test seeking beyond media duration.] - expected: FAIL - + disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1066467 diff --git a/testing/web-platform/meta/media-source/mediasource-seek-during-pending-seek.html.ini b/testing/web-platform/meta/media-source/mediasource-seek-during-pending-seek.html.ini index 04723af33b35..5cf058456f42 100644 --- a/testing/web-platform/meta/media-source/mediasource-seek-during-pending-seek.html.ini +++ b/testing/web-platform/meta/media-source/mediasource-seek-during-pending-seek.html.ini @@ -1,8 +1,3 @@ [mediasource-seek-during-pending-seek.html] type: testharness - [Test seeking to a new location before transitioning beyond HAVE_METADATA.] - expected: FAIL - - [Test seeking to a new location during a pending seek.] - expected: FAIL - + disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1066467 diff --git a/testing/web-platform/meta/media-source/mediasource-sourcebuffer-mode.html.ini b/testing/web-platform/meta/media-source/mediasource-sourcebuffer-mode.html.ini index 20d352c6a728..5ce54c758586 100644 --- a/testing/web-platform/meta/media-source/mediasource-sourcebuffer-mode.html.ini +++ b/testing/web-platform/meta/media-source/mediasource-sourcebuffer-mode.html.ini @@ -1,20 +1,3 @@ [mediasource-sourcebuffer-mode.html] type: testharness - [Test initial value of SourceBuffer.mode is "segments"] - expected: FAIL - - [Test setting SourceBuffer.mode] - expected: FAIL - - [Test setting a removed SourceBuffer\'s mode] - expected: FAIL - - [Test setting SourceBuffer.mode while still updating] - expected: FAIL - - [Test setting SourceBuffer.mode triggers parent MediaSource \'ended\' to \'open\' transition.] - expected: FAIL - - [Test setting SourceBuffer.mode and SourceBuffer.timestampOffset while parsing media segment.] - expected: FAIL - + disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1066467 From 0176167cc428a7bc65cc2ef1cd136c36d1ddc156 Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Mon, 22 Sep 2014 16:00:52 +1200 Subject: [PATCH 053/114] backout 2a782a973a3d for error: unused variable 'container' b=1068964 CLOSED TREE --- widget/gtk/nsGtkIMModule.cpp | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/widget/gtk/nsGtkIMModule.cpp b/widget/gtk/nsGtkIMModule.cpp index 65e6a43eb2f9..b308cceb3e06 100644 --- a/widget/gtk/nsGtkIMModule.cpp +++ b/widget/gtk/nsGtkIMModule.cpp @@ -263,7 +263,36 @@ nsGtkIMModule::PrepareToDestroyContext(GtkIMContext *aContext) GType slaveType = G_TYPE_FROM_INSTANCE(slave); const gchar *im_type_name = g_type_name(slaveType); - if (strcmp(im_type_name, "GtkIMContextIIIM") == 0) { + if (strcmp(im_type_name, "GtkIMContextXIM") == 0) { + if (gtk_check_version(2, 12, 1) == nullptr) { + return; // gtk bug has been fixed + } + + struct GtkIMContextXIM + { + GtkIMContext parent; + gpointer private_data; + // ... other fields + }; + + gpointer signal_data = + reinterpret_cast(slave)->private_data; + if (!signal_data) { + return; + } + + g_signal_handlers_disconnect_matched( + gtk_widget_get_display(GTK_WIDGET(container)), + G_SIGNAL_MATCH_DATA, 0, 0, nullptr, nullptr, signal_data); + + // Add a reference to prevent the XIM module from being unloaded + // and reloaded: each time the module is loaded and used, it + // opens (and doesn't close) new XOpenIM connections. + static gpointer gtk_xim_context_class = + g_type_class_ref(slaveType); + // Mute unused variable warning: + (void)gtk_xim_context_class; + } else if (strcmp(im_type_name, "GtkIMContextIIIM") == 0) { // Add a reference to prevent the IIIM module from being unloaded static gpointer gtk_iiim_context_class = g_type_class_ref(slaveType); From 430a4988cbe7e4a04e3b827239b13a6dbd9eae47 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Fri, 19 Sep 2014 17:25:00 +0200 Subject: [PATCH 054/114] Bug 242448 - Add a basic scriptable TLS server. r=honzab --- netwerk/base/public/moz.build | 1 + netwerk/base/public/nsITLSServerSocket.idl | 179 ++++++++ netwerk/base/src/TLSServerSocket.cpp | 476 +++++++++++++++++++++ netwerk/base/src/TLSServerSocket.h | 81 ++++ netwerk/base/src/moz.build | 1 + netwerk/base/src/nsServerSocket.cpp | 60 ++- netwerk/base/src/nsServerSocket.h | 22 +- netwerk/base/src/nsSocketTransport2.cpp | 9 + netwerk/base/src/nsSocketTransport2.h | 6 + netwerk/build/nsNetCID.h | 11 + netwerk/build/nsNetModule.cpp | 7 + netwerk/test/unit/test_tls_server.js | 167 ++++++++ netwerk/test/unit/xpcshell.ini | 3 + 13 files changed, 999 insertions(+), 24 deletions(-) create mode 100644 netwerk/base/public/nsITLSServerSocket.idl create mode 100644 netwerk/base/src/TLSServerSocket.cpp create mode 100644 netwerk/base/src/TLSServerSocket.h create mode 100644 netwerk/test/unit/test_tls_server.js diff --git a/netwerk/base/public/moz.build b/netwerk/base/public/moz.build index 21f0c6be9914..9bde21513032 100644 --- a/netwerk/base/public/moz.build +++ b/netwerk/base/public/moz.build @@ -108,6 +108,7 @@ XPIDL_SOURCES += [ 'nsIThreadRetargetableRequest.idl', 'nsIThreadRetargetableStreamListener.idl', 'nsITimedChannel.idl', + 'nsITLSServerSocket.idl', 'nsITraceableChannel.idl', 'nsITransport.idl', 'nsIUDPSocket.idl', diff --git a/netwerk/base/public/nsITLSServerSocket.idl b/netwerk/base/public/nsITLSServerSocket.idl new file mode 100644 index 000000000000..e22596072ba6 --- /dev/null +++ b/netwerk/base/public/nsITLSServerSocket.idl @@ -0,0 +1,179 @@ +/* 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/. */ + +#include "nsIServerSocket.idl" + +interface nsIX509Cert; +interface nsITLSServerSecurityObserver; +interface nsISocketTransport; + +[scriptable, uuid(2e025b6c-96ba-4781-85fb-d1cf1a653207)] +interface nsITLSServerSocket : nsIServerSocket +{ + /** + * serverCert + * + * The server's certificate that is presented to the client during the TLS + * handshake. This is required to be set before calling |asyncListen|. + */ + attribute nsIX509Cert serverCert; + + /** + * setSessionCache + * + * Whether the server should use a session cache. Defaults to true. This + * should be set before calling |asyncListen| if you wish to change the + * default. + */ + void setSessionCache(in boolean aSessionCache); + + /** + * setSessionTickets + * + * Whether the server should support session tickets. Defaults to true. This + * should be set before calling |asyncListen| if you wish to change the + * default. + */ + void setSessionTickets(in boolean aSessionTickets); + + /** + * Values for setRequestClientCertificate + */ + // Never request + const unsigned long REQUEST_NEVER = 0; + // Request (but do not require) during the first handshake only + const unsigned long REQUEST_FIRST_HANDSHAKE = 1; + // Request (but do not require) during each handshake + const unsigned long REQUEST_ALWAYS = 2; + // Require during the first handshake only + const unsigned long REQUIRE_FIRST_HANDSHAKE = 3; + // Require during each handshake + const unsigned long REQUIRE_ALWAYS = 4; + + /** + * setRequestClientCertificate + * + * Whether the server should request and/or require a client auth certificate + * from the client. Defaults to REQUEST_NEVER. See the possible options + * above. This should be set before calling |asyncListen| if you wish to + * change the default. + */ + void setRequestClientCertificate(in unsigned long aRequestClientCert); +}; + +/** + * Security summary for a given TLS client connection being handled by a + * |nsITLSServerSocket| server. + * + * This is accessible through the security info object on the transport, which + * will be an instance of |nsITLSServerConnectionInfo| (see below). + * + * The values of these attributes are available once the |onHandshakeDone| + * method of the security observer has been called (see + * |nsITLSServerSecurityObserver| below). + */ +[scriptable, uuid(19668ea4-e5ad-4182-9698-7e890d48f327)] +interface nsITLSClientStatus : nsISupports +{ + /** + * peerCert + * + * The client's certificate, if one was requested via |requestCertificate| + * above and supplied by the client. + */ + readonly attribute nsIX509Cert peerCert; + + /** + * Values for tlsVersionUsed, as defined by TLS + */ + const short SSL_VERSION_3 = 0x0300; + const short TLS_VERSION_1 = 0x0301; + const short TLS_VERSION_1_1 = 0x0302; + const short TLS_VERSION_1_2 = 0x0303; + const short TLS_VERSION_UNKNOWN = -1; + + /** + * tlsVersionUsed + * + * The version of TLS used by the connection. See values above. + */ + readonly attribute short tlsVersionUsed; + + /** + * cipherName + * + * Name of the cipher suite used, such as + * "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256". + * See security/nss/lib/ssl/sslinfo.c for the possible values. + */ + readonly attribute ACString cipherName; + + /** + * keyLength + * + * The "effective" key size of the symmetric key in bits. + */ + readonly attribute unsigned long keyLength; + + /** + * macLength + * + * The size of the MAC in bits. + */ + readonly attribute unsigned long macLength; +}; + +/** + * Connection info for a given TLS client connection being handled by a + * |nsITLSServerSocket| server. This object is thread-safe. + * + * This is exposed as the security info object on the transport, so it can be + * accessed via |transport.securityInfo|. + * + * This interface is available by the time the |onSocketAttached| is called, + * which is the first time the TLS server consumer is notified of a new client. + */ +[scriptable, uuid(8a93f5d5-eddd-4c62-a4bd-bfd297653184)] +interface nsITLSServerConnectionInfo : nsISupports +{ + /** + * setSecurityObserver + * + * Set the security observer to be notified when the TLS handshake has + * completed. + */ + void setSecurityObserver(in nsITLSServerSecurityObserver observer); + + /** + * serverSocket + * + * The nsITLSServerSocket instance that accepted this client connection. + */ + readonly attribute nsITLSServerSocket serverSocket; + + /** + * status + * + * Security summary for this TLS client connection. Note that the values of + * this interface are not available until the TLS handshake has completed. + * See |nsITLSClientStatus| above for more details. + */ + readonly attribute nsITLSClientStatus status; +}; + +[scriptable, uuid(1f62e1ae-e546-4a38-8917-d428472ed736)] +interface nsITLSServerSecurityObserver : nsISupports +{ + /** + * onHandsakeDone + * + * This method is called once the TLS handshake is completed. This takes + * place after |onSocketAccepted| has been called, which typically opens the + * streams to keep things moving along. It's important to be aware that the + * handshake has not completed at the point that |onSocketAccepted| is called, + * so no security verification can be done until this method is called. + */ + void onHandshakeDone(in nsITLSServerSocket aServer, + in nsITLSClientStatus aStatus); +}; diff --git a/netwerk/base/src/TLSServerSocket.cpp b/netwerk/base/src/TLSServerSocket.cpp new file mode 100644 index 000000000000..c344b45facfa --- /dev/null +++ b/netwerk/base/src/TLSServerSocket.cpp @@ -0,0 +1,476 @@ +/* vim:set ts=2 sw=2 et cindent: */ +/* 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/. */ + +#include "TLSServerSocket.h" + +#include "mozilla/net/DNS.h" +#include "nsAutoPtr.h" +#include "nsComponentManagerUtils.h" +#include "nsIServerSocket.h" +#include "nsITimer.h" +#include "nsIX509Cert.h" +#include "nsIX509CertDB.h" +#include "nsNetCID.h" +#include "nsProxyRelease.h" +#include "nsServiceManagerUtils.h" +#include "nsSocketTransport2.h" +#include "nsThreadUtils.h" +#include "ScopedNSSTypes.h" +#include "ssl.h" + +extern PRThread *gSocketThread; + +namespace mozilla { +namespace net { + +//----------------------------------------------------------------------------- +// TLSServerSocket +//----------------------------------------------------------------------------- + +TLSServerSocket::TLSServerSocket() + : mServerCert(nullptr) +{ +} + +TLSServerSocket::~TLSServerSocket() +{ +} + +NS_IMPL_ISUPPORTS_INHERITED(TLSServerSocket, + nsServerSocket, + nsITLSServerSocket) + +nsresult +TLSServerSocket::SetSocketDefaults() +{ + // Set TLS options on the listening socket + mFD = SSL_ImportFD(nullptr, mFD); + if (NS_WARN_IF(!mFD)) { + return mozilla::psm::GetXPCOMFromNSSError(PR_GetError()); + } + + SSL_OptionSet(mFD, SSL_SECURITY, true); + SSL_OptionSet(mFD, SSL_HANDSHAKE_AS_CLIENT, false); + SSL_OptionSet(mFD, SSL_HANDSHAKE_AS_SERVER, true); + + // We don't currently notify the server API consumer of renegotiation events + // (to revalidate peer certs, etc.), so disable it for now. + SSL_OptionSet(mFD, SSL_ENABLE_RENEGOTIATION, SSL_RENEGOTIATE_NEVER); + + SetSessionCache(true); + SetSessionTickets(true); + SetRequestClientCertificate(REQUEST_NEVER); + + return NS_OK; +} + +void +TLSServerSocket::CreateClientTransport(PRFileDesc* aClientFD, + const NetAddr& aClientAddr) +{ + MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread); + nsresult rv; + + nsRefPtr trans = new nsSocketTransport; + if (NS_WARN_IF(!trans)) { + mCondition = NS_ERROR_OUT_OF_MEMORY; + return; + } + + nsRefPtr info = new TLSServerConnectionInfo(); + info->mServerSocket = this; + info->mTransport = trans; + nsCOMPtr infoSupports = + NS_ISUPPORTS_CAST(nsITLSServerConnectionInfo*, info); + rv = trans->InitWithConnectedSocket(aClientFD, &aClientAddr, infoSupports); + if (NS_WARN_IF(NS_FAILED(rv))) { + mCondition = rv; + return; + } + + // Override the default peer certificate validation, so that server consumers + // can make their own choice after the handshake completes. + SSL_AuthCertificateHook(aClientFD, AuthCertificateHook, nullptr); + // Once the TLS handshake has completed, the server consumer is notified and + // has access to various TLS state details. + // It's safe to pass info here because the socket transport holds it as + // |mSecInfo| which keeps it alive for the lifetime of the socket. + SSL_HandshakeCallback(aClientFD, TLSServerConnectionInfo::HandshakeCallback, + info); + + // Notify the consumer of the new client so it can manage the streams. + // Security details aren't known yet. The security observer will be notified + // later when they are ready. + nsCOMPtr serverSocket = + do_QueryInterface(NS_ISUPPORTS_CAST(nsITLSServerSocket*, this)); + mListener->OnSocketAccepted(serverSocket, trans); +} + +nsresult +TLSServerSocket::OnSocketListen() +{ + if (NS_WARN_IF(!mServerCert)) { + return NS_ERROR_NOT_INITIALIZED; + } + + ScopedCERTCertificate cert(mServerCert->GetCert()); + if (NS_WARN_IF(!cert)) { + return mozilla::psm::GetXPCOMFromNSSError(PR_GetError()); + } + + ScopedSECKEYPrivateKey key(PK11_FindKeyByAnyCert(cert, nullptr)); + if (NS_WARN_IF(!key)) { + return mozilla::psm::GetXPCOMFromNSSError(PR_GetError()); + } + + SSLKEAType certKEA = NSS_FindCertKEAType(cert); + + nsresult rv = MapSECStatus(SSL_ConfigSecureServer(mFD, cert, key, certKEA)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + return NS_OK; +} + +// static +SECStatus +TLSServerSocket::AuthCertificateHook(void* arg, PRFileDesc* fd, PRBool checksig, + PRBool isServer) +{ + // Allow any client cert here, server consumer code can decide whether it's + // okay after being notified of the new client socket. + return SECSuccess; +} + +//----------------------------------------------------------------------------- +// TLSServerSocket::nsITLSServerSocket +//----------------------------------------------------------------------------- + +NS_IMETHODIMP +TLSServerSocket::GetServerCert(nsIX509Cert** aCert) +{ + if (NS_WARN_IF(!aCert)) { + return NS_ERROR_INVALID_POINTER; + } + *aCert = mServerCert; + NS_IF_ADDREF(*aCert); + return NS_OK; +} + +NS_IMETHODIMP +TLSServerSocket::SetServerCert(nsIX509Cert* aCert) +{ + // If AsyncListen was already called (and set mListener), it's too late to set + // this. + if (NS_WARN_IF(mListener)) { + return NS_ERROR_IN_PROGRESS; + } + mServerCert = aCert; + return NS_OK; +} + +NS_IMETHODIMP +TLSServerSocket::SetSessionCache(bool aEnabled) +{ + // If AsyncListen was already called (and set mListener), it's too late to set + // this. + if (NS_WARN_IF(mListener)) { + return NS_ERROR_IN_PROGRESS; + } + SSL_OptionSet(mFD, SSL_NO_CACHE, !aEnabled); + return NS_OK; +} + +NS_IMETHODIMP +TLSServerSocket::SetSessionTickets(bool aEnabled) +{ + // If AsyncListen was already called (and set mListener), it's too late to set + // this. + if (NS_WARN_IF(mListener)) { + return NS_ERROR_IN_PROGRESS; + } + SSL_OptionSet(mFD, SSL_ENABLE_SESSION_TICKETS, aEnabled); + return NS_OK; +} + +NS_IMETHODIMP +TLSServerSocket::SetRequestClientCertificate(uint32_t aMode) +{ + // If AsyncListen was already called (and set mListener), it's too late to set + // this. + if (NS_WARN_IF(mListener)) { + return NS_ERROR_IN_PROGRESS; + } + SSL_OptionSet(mFD, SSL_REQUEST_CERTIFICATE, aMode != REQUEST_NEVER); + + switch (aMode) { + case REQUEST_ALWAYS: + SSL_OptionSet(mFD, SSL_REQUIRE_CERTIFICATE, SSL_REQUIRE_NO_ERROR); + break; + case REQUIRE_FIRST_HANDSHAKE: + SSL_OptionSet(mFD, SSL_REQUIRE_CERTIFICATE, SSL_REQUIRE_FIRST_HANDSHAKE); + break; + case REQUIRE_ALWAYS: + SSL_OptionSet(mFD, SSL_REQUIRE_CERTIFICATE, SSL_REQUIRE_ALWAYS); + break; + default: + SSL_OptionSet(mFD, SSL_REQUIRE_CERTIFICATE, SSL_REQUIRE_NEVER); + } + return NS_OK; +} + +//----------------------------------------------------------------------------- +// TLSServerConnectionInfo +//----------------------------------------------------------------------------- + +namespace { + +class TLSServerSecurityObserverProxy MOZ_FINAL : public nsITLSServerSecurityObserver +{ + ~TLSServerSecurityObserverProxy() {} + +public: + explicit TLSServerSecurityObserverProxy(nsITLSServerSecurityObserver* aListener) + : mListener(new nsMainThreadPtrHolder(aListener)) + { } + + NS_DECL_THREADSAFE_ISUPPORTS + NS_DECL_NSITLSSERVERSECURITYOBSERVER + + class OnHandshakeDoneRunnable : public nsRunnable + { + public: + OnHandshakeDoneRunnable(const nsMainThreadPtrHandle& aListener, + nsITLSServerSocket* aServer, + nsITLSClientStatus* aStatus) + : mListener(aListener) + , mServer(aServer) + , mStatus(aStatus) + { } + + NS_DECL_NSIRUNNABLE + + private: + nsMainThreadPtrHandle mListener; + nsCOMPtr mServer; + nsCOMPtr mStatus; + }; + +private: + nsMainThreadPtrHandle mListener; +}; + +NS_IMPL_ISUPPORTS(TLSServerSecurityObserverProxy, + nsITLSServerSecurityObserver) + +NS_IMETHODIMP +TLSServerSecurityObserverProxy::OnHandshakeDone(nsITLSServerSocket* aServer, + nsITLSClientStatus* aStatus) +{ + nsRefPtr r = + new OnHandshakeDoneRunnable(mListener, aServer, aStatus); + return NS_DispatchToMainThread(r); +} + +NS_IMETHODIMP +TLSServerSecurityObserverProxy::OnHandshakeDoneRunnable::Run() +{ + mListener->OnHandshakeDone(mServer, mStatus); + return NS_OK; +} + +} // anonymous namespace + +NS_IMPL_ISUPPORTS(TLSServerConnectionInfo, + nsITLSServerConnectionInfo, + nsITLSClientStatus) + +TLSServerConnectionInfo::TLSServerConnectionInfo() + : mServerSocket(nullptr) + , mTransport(nullptr) + , mPeerCert(nullptr) + , mTlsVersionUsed(TLS_VERSION_UNKNOWN) + , mKeyLength(0) + , mMacLength(0) + , mLock("TLSServerConnectionInfo.mLock") + , mSecurityObserver(nullptr) +{ +} + +TLSServerConnectionInfo::~TLSServerConnectionInfo() +{ + if (!mSecurityObserver) { + return; + } + + nsITLSServerSecurityObserver* observer; + { + MutexAutoLock lock(mLock); + mSecurityObserver.forget(&observer); + } + + if (observer) { + nsCOMPtr mainThread; + NS_GetMainThread(getter_AddRefs(mainThread)); + NS_ProxyRelease(mainThread, observer); + } +} + +NS_IMETHODIMP +TLSServerConnectionInfo::SetSecurityObserver(nsITLSServerSecurityObserver* aObserver) +{ + { + MutexAutoLock lock(mLock); + mSecurityObserver = new TLSServerSecurityObserverProxy(aObserver); + } + return NS_OK; +} + +NS_IMETHODIMP +TLSServerConnectionInfo::GetServerSocket(nsITLSServerSocket** aSocket) +{ + if (NS_WARN_IF(!aSocket)) { + return NS_ERROR_INVALID_POINTER; + } + *aSocket = mServerSocket; + NS_IF_ADDREF(*aSocket); + return NS_OK; +} + +NS_IMETHODIMP +TLSServerConnectionInfo::GetStatus(nsITLSClientStatus** aStatus) +{ + if (NS_WARN_IF(!aStatus)) { + return NS_ERROR_INVALID_POINTER; + } + *aStatus = this; + NS_IF_ADDREF(*aStatus); + return NS_OK; +} + +NS_IMETHODIMP +TLSServerConnectionInfo::GetPeerCert(nsIX509Cert** aCert) +{ + if (NS_WARN_IF(!aCert)) { + return NS_ERROR_INVALID_POINTER; + } + *aCert = mPeerCert; + NS_IF_ADDREF(*aCert); + return NS_OK; +} + +NS_IMETHODIMP +TLSServerConnectionInfo::GetTlsVersionUsed(int16_t* aTlsVersionUsed) +{ + if (NS_WARN_IF(!aTlsVersionUsed)) { + return NS_ERROR_INVALID_POINTER; + } + *aTlsVersionUsed = mTlsVersionUsed; + return NS_OK; +} + +NS_IMETHODIMP +TLSServerConnectionInfo::GetCipherName(nsACString& aCipherName) +{ + aCipherName.Assign(mCipherName); + return NS_OK; +} + +NS_IMETHODIMP +TLSServerConnectionInfo::GetKeyLength(uint32_t* aKeyLength) +{ + if (NS_WARN_IF(!aKeyLength)) { + return NS_ERROR_INVALID_POINTER; + } + *aKeyLength = mKeyLength; + return NS_OK; +} + +NS_IMETHODIMP +TLSServerConnectionInfo::GetMacLength(uint32_t* aMacLength) +{ + if (NS_WARN_IF(!aMacLength)) { + return NS_ERROR_INVALID_POINTER; + } + *aMacLength = mMacLength; + return NS_OK; +} + +// static +void +TLSServerConnectionInfo::HandshakeCallback(PRFileDesc* aFD, void* aArg) +{ + nsRefPtr info = + static_cast(aArg); + nsISocketTransport* transport = info->mTransport; + // No longer needed outside this function, so clear the weak ref + info->mTransport = nullptr; + nsresult rv = info->HandshakeCallback(aFD); + if (NS_WARN_IF(NS_FAILED(rv))) { + transport->Close(rv); + } +} + +nsresult +TLSServerConnectionInfo::HandshakeCallback(PRFileDesc* aFD) +{ + nsresult rv; + + ScopedCERTCertificate clientCert(SSL_PeerCertificate(aFD)); + if (clientCert) { + nsCOMPtr certDB = + do_GetService(NS_X509CERTDB_CONTRACTID, &rv); + if (NS_FAILED(rv)) { + return rv; + } + + nsCOMPtr clientCertPSM; + rv = certDB->ConstructX509(reinterpret_cast(clientCert->derCert.data), + clientCert->derCert.len, + getter_AddRefs(clientCertPSM)); + if (NS_FAILED(rv)) { + return rv; + } + + mPeerCert = clientCertPSM; + } + + SSLChannelInfo channelInfo; + rv = MapSECStatus(SSL_GetChannelInfo(aFD, &channelInfo, sizeof(channelInfo))); + if (NS_FAILED(rv)) { + return rv; + } + mTlsVersionUsed = channelInfo.protocolVersion; + + SSLCipherSuiteInfo cipherInfo; + rv = MapSECStatus(SSL_GetCipherSuiteInfo(channelInfo.cipherSuite, &cipherInfo, + sizeof(cipherInfo))); + if (NS_FAILED(rv)) { + return rv; + } + mCipherName.Assign(cipherInfo.cipherSuiteName); + mKeyLength = cipherInfo.effectiveKeyBits; + mMacLength = cipherInfo.macBits; + + if (!mSecurityObserver) { + return NS_OK; + } + + // Notify consumer code that handshake is complete + nsCOMPtr observer; + { + MutexAutoLock lock(mLock); + mSecurityObserver.swap(observer); + } + nsCOMPtr serverSocket; + GetServerSocket(getter_AddRefs(serverSocket)); + observer->OnHandshakeDone(serverSocket, this); + + return NS_OK; +} + +} // namespace net +} // namespace mozilla diff --git a/netwerk/base/src/TLSServerSocket.h b/netwerk/base/src/TLSServerSocket.h new file mode 100644 index 000000000000..7554a03c21f4 --- /dev/null +++ b/netwerk/base/src/TLSServerSocket.h @@ -0,0 +1,81 @@ +/* vim:set ts=2 sw=2 et cindent: */ +/* 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/. */ + +#ifndef mozilla_net_TLSServerSocket_h +#define mozilla_net_TLSServerSocket_h + +#include "nsAutoPtr.h" +#include "nsITLSServerSocket.h" +#include "nsServerSocket.h" +#include "nsString.h" +#include "mozilla/Mutex.h" +#include "seccomon.h" + +namespace mozilla { +namespace net { + +class TLSServerSocket : public nsServerSocket + , public nsITLSServerSocket +{ +public: + NS_DECL_ISUPPORTS_INHERITED + NS_FORWARD_NSISERVERSOCKET(nsServerSocket::) + NS_DECL_NSITLSSERVERSOCKET + + // Override methods from nsServerSocket + virtual void CreateClientTransport(PRFileDesc* clientFD, + const NetAddr& clientAddr) MOZ_OVERRIDE; + virtual nsresult SetSocketDefaults() MOZ_OVERRIDE; + virtual nsresult OnSocketListen() MOZ_OVERRIDE; + + TLSServerSocket(); + +private: + virtual ~TLSServerSocket(); + + static SECStatus AuthCertificateHook(void* arg, PRFileDesc* fd, + PRBool checksig, PRBool isServer); + + nsCOMPtr mServerCert; +}; + +class TLSServerConnectionInfo : public nsITLSServerConnectionInfo + , public nsITLSClientStatus +{ + friend class TLSServerSocket; + +public: + NS_DECL_THREADSAFE_ISUPPORTS + NS_DECL_NSITLSSERVERCONNECTIONINFO + NS_DECL_NSITLSCLIENTSTATUS + + TLSServerConnectionInfo(); + +private: + virtual ~TLSServerConnectionInfo(); + + static void HandshakeCallback(PRFileDesc* aFD, void* aArg); + nsresult HandshakeCallback(PRFileDesc* aFD); + + nsRefPtr mServerSocket; + // Weak ref to the transport, to avoid cycles since the transport holds a + // reference to the TLSServerConnectionInfo object. This is not handed out to + // anyone, and is only used in HandshakeCallback to close the transport in + // case of an error. After this, it's set to nullptr. + nsISocketTransport* mTransport; + nsCOMPtr mPeerCert; + int16_t mTlsVersionUsed; + nsCString mCipherName; + uint32_t mKeyLength; + uint32_t mMacLength; + // lock protects access to mSecurityObserver + mozilla::Mutex mLock; + nsCOMPtr mSecurityObserver; +}; + +} // namespace net +} // namespace mozilla + +#endif // mozilla_net_TLSServerSocket_h diff --git a/netwerk/base/src/moz.build b/netwerk/base/src/moz.build index cfeadf57beb7..0fb2fc3a97c1 100644 --- a/netwerk/base/src/moz.build +++ b/netwerk/base/src/moz.build @@ -77,6 +77,7 @@ UNIFIED_SOURCES += [ 'RedirectChannelRegistrar.cpp', 'StreamingProtocolService.cpp', 'Tickler.cpp', + 'TLSServerSocket.cpp', ] # These files cannot be built in unified mode because they force NSPR logging. diff --git a/netwerk/base/src/nsServerSocket.cpp b/netwerk/base/src/nsServerSocket.cpp index eb7317d3abd8..d3d09f7fd73d 100644 --- a/netwerk/base/src/nsServerSocket.cpp +++ b/netwerk/base/src/nsServerSocket.cpp @@ -45,8 +45,8 @@ PostEvent(nsServerSocket *s, nsServerSocketFunc func) //----------------------------------------------------------------------------- nsServerSocket::nsServerSocket() - : mLock("nsServerSocket.mLock") - , mFD(nullptr) + : mFD(nullptr) + , mLock("nsServerSocket.mLock") , mAttached(false) , mKeepWhenOffline(false) { @@ -154,6 +154,25 @@ nsServerSocket::TryAttach() return NS_OK; } +void +nsServerSocket::CreateClientTransport(PRFileDesc* aClientFD, + const NetAddr& aClientAddr) +{ + nsRefPtr trans = new nsSocketTransport; + if (NS_WARN_IF(!trans)) { + mCondition = NS_ERROR_OUT_OF_MEMORY; + return; + } + + nsresult rv = trans->InitWithConnectedSocket(aClientFD, &aClientAddr); + if (NS_WARN_IF(NS_FAILED(rv))) { + mCondition = rv; + return; + } + + mListener->OnSocketAccepted(this, trans); +} + //----------------------------------------------------------------------------- // nsServerSocket::nsASocketHandler //----------------------------------------------------------------------------- @@ -185,25 +204,14 @@ nsServerSocket::OnSocketReady(PRFileDesc *fd, int16_t outFlags) clientFD = PR_Accept(mFD, &prClientAddr, PR_INTERVAL_NO_WAIT); PRNetAddrToNetAddr(&prClientAddr, &clientAddr); - if (!clientFD) - { + if (!clientFD) { NS_WARNING("PR_Accept failed"); mCondition = NS_ERROR_UNEXPECTED; + return; } - else - { - nsRefPtr trans = new nsSocketTransport; - if (!trans) - mCondition = NS_ERROR_OUT_OF_MEMORY; - else - { - nsresult rv = trans->InitWithConnectedSocket(clientFD, &clientAddr); - if (NS_FAILED(rv)) - mCondition = rv; - else - mListener->OnSocketAccepted(this, trans); - } - } + + // Accept succeeded, create socket transport and notify consumer + CreateClientTransport(clientFD, clientAddr); } void @@ -328,6 +336,7 @@ NS_IMETHODIMP nsServerSocket::InitWithAddress(const PRNetAddr *aAddr, int32_t aBackLog) { NS_ENSURE_TRUE(mFD == nullptr, NS_ERROR_ALREADY_INITIALIZED); + nsresult rv; // // configure listening socket... @@ -373,12 +382,18 @@ nsServerSocket::InitWithAddress(const PRNetAddr *aAddr, int32_t aBackLog) goto fail; } + // Set any additional socket defaults needed by child classes + rv = SetSocketDefaults(); + if (NS_WARN_IF(NS_FAILED(rv))) { + goto fail; + } + // wait until AsyncListen is called before polling the socket for // client connections. return NS_OK; fail: - nsresult rv = ErrorAccordingToNSPR(PR_GetError()); + rv = ErrorAccordingToNSPR(PR_GetError()); Close(); return rv; } @@ -509,6 +524,13 @@ nsServerSocket::AsyncListen(nsIServerSocketListener *aListener) mListener = new ServerSocketListenerProxy(aListener); mListenerTarget = NS_GetCurrentThread(); } + + // Child classes may need to do additional setup just before listening begins + nsresult rv = OnSocketListen(); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + return PostEvent(this, &nsServerSocket::OnMsgAttach); } diff --git a/netwerk/base/src/nsServerSocket.h b/netwerk/base/src/nsServerSocket.h index 6f7d25bc6398..05a2568ad816 100644 --- a/netwerk/base/src/nsServerSocket.h +++ b/netwerk/base/src/nsServerSocket.h @@ -6,12 +6,18 @@ #ifndef nsServerSocket_h__ #define nsServerSocket_h__ +#include "prio.h" #include "nsASocketHandler.h" #include "nsIServerSocket.h" #include "mozilla/Mutex.h" //----------------------------------------------------------------------------- +class nsIEventTarget; +namespace mozilla { namespace net { +union NetAddr; +}} // namespace mozilla::net + class nsServerSocket : public nsASocketHandler , public nsIServerSocket { @@ -29,20 +35,26 @@ public: virtual uint64_t ByteCountReceived() { return 0; } nsServerSocket(); -private: - virtual ~nsServerSocket(); + virtual void CreateClientTransport(PRFileDesc* clientFD, + const mozilla::net::NetAddr& clientAddr); + virtual nsresult SetSocketDefaults() { return NS_OK; } + virtual nsresult OnSocketListen() { return NS_OK; } +protected: + virtual ~nsServerSocket(); + PRFileDesc* mFD; + nsCOMPtr mListener; + +private: void OnMsgClose(); void OnMsgAttach(); - + // try attaching our socket (mFD) to the STS's poll list. nsresult TryAttach(); // lock protects access to mListener; so it is not cleared while being used. mozilla::Mutex mLock; - PRFileDesc *mFD; PRNetAddr mAddr; - nsCOMPtr mListener; nsCOMPtr mListenerTarget; bool mAttached; bool mKeepWhenOffline; diff --git a/netwerk/base/src/nsSocketTransport2.cpp b/netwerk/base/src/nsSocketTransport2.cpp index d3261d02014a..eee15bef7339 100644 --- a/netwerk/base/src/nsSocketTransport2.cpp +++ b/netwerk/base/src/nsSocketTransport2.cpp @@ -942,6 +942,15 @@ nsSocketTransport::InitWithConnectedSocket(PRFileDesc *fd, const NetAddr *addr) return PostEvent(MSG_RETRY_INIT_SOCKET); } +nsresult +nsSocketTransport::InitWithConnectedSocket(PRFileDesc* aFD, + const NetAddr* aAddr, + nsISupports* aSecInfo) +{ + mSecInfo = aSecInfo; + return InitWithConnectedSocket(aFD, aAddr); +} + nsresult nsSocketTransport::PostEvent(uint32_t type, nsresult status, nsISupports *param) { diff --git a/netwerk/base/src/nsSocketTransport2.h b/netwerk/base/src/nsSocketTransport2.h index d043a1ee8f0c..6bd3d5d85fde 100644 --- a/netwerk/base/src/nsSocketTransport2.h +++ b/netwerk/base/src/nsSocketTransport2.h @@ -131,6 +131,12 @@ public: nsresult InitWithConnectedSocket(PRFileDesc *socketFD, const mozilla::net::NetAddr *addr); + // this method instructs the socket transport to use an already connected + // socket with the given address, and additionally supplies security info. + nsresult InitWithConnectedSocket(PRFileDesc* aSocketFD, + const mozilla::net::NetAddr* aAddr, + nsISupports* aSecInfo); + // This method instructs the socket transport to open a socket // connected to the given Unix domain address. We can only create // unlayered, simple, stream sockets. diff --git a/netwerk/build/nsNetCID.h b/netwerk/build/nsNetCID.h index 130170d9b782..4117a99a3561 100644 --- a/netwerk/build/nsNetCID.h +++ b/netwerk/build/nsNetCID.h @@ -335,6 +335,17 @@ {0xab, 0x1d, 0x5e, 0x68, 0xa9, 0xf4, 0x5f, 0x08} \ } +// component implementing nsITLSServerSocket +#define NS_TLSSERVERSOCKET_CONTRACTID \ + "@mozilla.org/network/tls-server-socket;1" +#define NS_TLSSERVERSOCKET_CID \ +{ /* 1813cbb4-c98e-4622-8c7d-839167f3f272 */ \ + 0x1813cbb4, \ + 0xc98e, \ + 0x4622, \ + {0x8c, 0x7d, 0x83, 0x91, 0x67, 0xf3, 0xf2, 0x72} \ +} + // component implementing nsIUDPSocket #define NS_UDPSOCKET_CONTRACTID \ "@mozilla.org/network/udp-socket;1" diff --git a/netwerk/build/nsNetModule.cpp b/netwerk/build/nsNetModule.cpp index 34ee5852e62e..51e20fb53d4b 100644 --- a/netwerk/build/nsNetModule.cpp +++ b/netwerk/build/nsNetModule.cpp @@ -75,6 +75,10 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsSocketTransportService, Init) #include "nsServerSocket.h" NS_GENERIC_FACTORY_CONSTRUCTOR(nsServerSocket) +#include "TLSServerSocket.h" +typedef mozilla::net::TLSServerSocket TLSServerSocket; +NS_GENERIC_FACTORY_CONSTRUCTOR(TLSServerSocket) + #include "nsUDPSocket.h" NS_GENERIC_FACTORY_CONSTRUCTOR(nsUDPSocket) @@ -665,6 +669,7 @@ NS_DEFINE_NAMED_CID(NS_IOSERVICE_CID); NS_DEFINE_NAMED_CID(NS_STREAMTRANSPORTSERVICE_CID); NS_DEFINE_NAMED_CID(NS_SOCKETTRANSPORTSERVICE_CID); NS_DEFINE_NAMED_CID(NS_SERVERSOCKET_CID); +NS_DEFINE_NAMED_CID(NS_TLSSERVERSOCKET_CID); NS_DEFINE_NAMED_CID(NS_UDPSOCKET_CID); NS_DEFINE_NAMED_CID(NS_SOCKETPROVIDERSERVICE_CID); NS_DEFINE_NAMED_CID(NS_DNSSERVICE_CID); @@ -804,6 +809,7 @@ static const mozilla::Module::CIDEntry kNeckoCIDs[] = { { &kNS_STREAMTRANSPORTSERVICE_CID, false, nullptr, nsStreamTransportServiceConstructor }, { &kNS_SOCKETTRANSPORTSERVICE_CID, false, nullptr, nsSocketTransportServiceConstructor }, { &kNS_SERVERSOCKET_CID, false, nullptr, nsServerSocketConstructor }, + { &kNS_TLSSERVERSOCKET_CID, false, nullptr, TLSServerSocketConstructor }, { &kNS_UDPSOCKET_CID, false, nullptr, nsUDPSocketConstructor }, { &kNS_SOCKETPROVIDERSERVICE_CID, false, nullptr, nsSocketProviderService::Create }, { &kNS_DNSSERVICE_CID, false, nullptr, nsIDNSServiceConstructor }, @@ -950,6 +956,7 @@ static const mozilla::Module::ContractIDEntry kNeckoContracts[] = { { NS_STREAMTRANSPORTSERVICE_CONTRACTID, &kNS_STREAMTRANSPORTSERVICE_CID }, { NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &kNS_SOCKETTRANSPORTSERVICE_CID }, { NS_SERVERSOCKET_CONTRACTID, &kNS_SERVERSOCKET_CID }, + { NS_TLSSERVERSOCKET_CONTRACTID, &kNS_TLSSERVERSOCKET_CID }, { NS_UDPSOCKET_CONTRACTID, &kNS_UDPSOCKET_CID }, { NS_SOCKETPROVIDERSERVICE_CONTRACTID, &kNS_SOCKETPROVIDERSERVICE_CID }, { NS_DNSSERVICE_CONTRACTID, &kNS_DNSSERVICE_CID }, diff --git a/netwerk/test/unit/test_tls_server.js b/netwerk/test/unit/test_tls_server.js new file mode 100644 index 000000000000..5b595ea08a63 --- /dev/null +++ b/netwerk/test/unit/test_tls_server.js @@ -0,0 +1,167 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Need profile dir to store the key / cert +do_get_profile(); +// Ensure PSM is initialized +Cc["@mozilla.org/psm;1"].getService(Ci.nsISupports); + +const { Services } = Cu.import("resource://gre/modules/Services.jsm", {}); +const { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm", {}); +const { Promise: promise } = + Cu.import("resource://gre/modules/Promise.jsm", {}); +const certService = Cc["@mozilla.org/security/local-cert-service;1"] + .getService(Ci.nsILocalCertService); +const certOverrideService = Cc["@mozilla.org/security/certoverride;1"] + .getService(Ci.nsICertOverrideService); +const socketTransportService = + Cc["@mozilla.org/network/socket-transport-service;1"] + .getService(Ci.nsISocketTransportService); + +function run_test() { + run_next_test(); +} + +function getCert() { + let deferred = promise.defer(); + certService.getOrCreateCert("tls-test", { + handleCert: function(c, rv) { + if (rv) { + deferred.reject(rv); + return; + } + deferred.resolve(c); + } + }); + return deferred.promise; +} + +function startServer(cert) { + let tlsServer = Cc["@mozilla.org/network/tls-server-socket;1"] + .createInstance(Ci.nsITLSServerSocket); + tlsServer.init(-1, true, -1); + tlsServer.serverCert = cert; + + let input, output; + + let listener = { + onSocketAccepted: function(socket, transport) { + do_print("Accept TLS client connection"); + let connectionInfo = transport.securityInfo + .QueryInterface(Ci.nsITLSServerConnectionInfo); + connectionInfo.setSecurityObserver(listener); + input = transport.openInputStream(0, 0, 0); + output = transport.openOutputStream(0, 0, 0); + }, + onHandshakeDone: function(socket, status) { + do_print("TLS handshake done"); + ok(!!status.peerCert, "Has peer cert"); + ok(status.peerCert.equals(cert), "Peer cert matches expected cert"); + + equal(status.tlsVersionUsed, Ci.nsITLSClientStatus.TLS_VERSION_1_2, + "Using TLS 1.2"); + equal(status.cipherName, "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", + "Using expected cipher"); + equal(status.keyLength, 128, "Using 128-bit key"); + equal(status.macLength, 128, "Using 128-bit MAC"); + + input.asyncWait({ + onInputStreamReady: function(input) { + NetUtil.asyncCopy(input, output); + } + }, 0, 0, Services.tm.currentThread); + }, + onStopListening: function() {} + }; + + tlsServer.setSessionCache(false); + tlsServer.setSessionTickets(false); + tlsServer.setRequestClientCertificate(Ci.nsITLSServerSocket.REQUIRE_ALWAYS); + + tlsServer.asyncListen(listener); + + return tlsServer.port; +} + +function storeCertOverride(port, cert) { + let overrideBits = Ci.nsICertOverrideService.ERROR_UNTRUSTED | + Ci.nsICertOverrideService.ERROR_MISMATCH; + certOverrideService.rememberValidityOverride("127.0.0.1", port, cert, + overrideBits, true); +} + +function startClient(port, cert) { + let transport = + socketTransportService.createTransport(["ssl"], 1, "127.0.0.1", port, null); + let input; + let output; + + let inputDeferred = promise.defer(); + let outputDeferred = promise.defer(); + + let handler = { + + onTransportStatus: function(transport, status) { + if (status === Ci.nsISocketTransport.STATUS_CONNECTED_TO) { + output.asyncWait(handler, 0, 0, Services.tm.currentThread); + } + }, + + onInputStreamReady: function(input) { + try { + let data = NetUtil.readInputStreamToString(input, input.available()); + equal(data, "HELLO", "Echoed data received"); + input.close(); + output.close(); + inputDeferred.resolve(); + } catch (e) { + let SEC_ERROR_BASE = Ci.nsINSSErrorsService.NSS_SEC_ERROR_BASE; + let SEC_ERROR_UNKNOWN_ISSUER = SEC_ERROR_BASE + 13; + let errorCode = -1 * (e.result & 0xFFFF); + if (errorCode == SEC_ERROR_UNKNOWN_ISSUER) { + do_print("Client doesn't like server cert"); + } + inputDeferred.reject(e); + } + }, + + onOutputStreamReady: function(output) { + try { + // Set the cert we want to avoid any cert UI prompts + let clientSecInfo = transport.securityInfo; + let tlsControl = clientSecInfo.QueryInterface(Ci.nsISSLSocketControl); + tlsControl.clientCert = cert; + + output.write("HELLO", 5); + do_print("Output to server written"); + outputDeferred.resolve(); + input = transport.openInputStream(0, 0, 0); + input.asyncWait(handler, 0, 0, Services.tm.currentThread); + } catch (e) { + let SSL_ERROR_BASE = Ci.nsINSSErrorsService.NSS_SSL_ERROR_BASE; + let SSL_ERROR_BAD_CERT_ALERT = SSL_ERROR_BASE + 17; + let errorCode = -1 * (e.result & 0xFFFF); + if (errorCode == SSL_ERROR_BAD_CERT_ALERT) { + do_print("Server doesn't like client cert"); + } + outputDeferred.reject(e); + } + } + + }; + + transport.setEventSink(handler, Services.tm.currentThread); + output = transport.openOutputStream(0, 0, 0); + + return promise.all([inputDeferred.promise, outputDeferred.promise]); +} + +add_task(function*() { + let cert = yield getCert(); + ok(!!cert, "Got self-signed cert"); + let port = startServer(cert); + storeCertOverride(port, cert); + yield startClient(port, cert); +}); diff --git a/netwerk/test/unit/xpcshell.ini b/netwerk/test/unit/xpcshell.ini index 821e3686f475..dfc2e5560dcc 100644 --- a/netwerk/test/unit/xpcshell.ini +++ b/netwerk/test/unit/xpcshell.ini @@ -299,3 +299,6 @@ run-if = os == "win" [test_redirect_history.js] [test_reply_without_content_type.js] [test_websocket_offline.js] +[test_tls_server.js] +# The local cert service used by this test is not currently shipped on Android +skip-if = os == "android" From c7c77e1e40097921be05c7cc620200e4a4694045 Mon Sep 17 00:00:00 2001 From: James Kitchener Date: Fri, 19 Sep 2014 20:13:00 +0200 Subject: [PATCH 055/114] Bug 687807 - Improvements to stretching of embellished operators. r=karlt --- layout/mathml/nsMathMLContainerFrame.cpp | 70 ++++++++++++++---------- 1 file changed, 40 insertions(+), 30 deletions(-) diff --git a/layout/mathml/nsMathMLContainerFrame.cpp b/layout/mathml/nsMathMLContainerFrame.cpp index 943d31911f9f..ebde6b9cc914 100644 --- a/layout/mathml/nsMathMLContainerFrame.cpp +++ b/layout/mathml/nsMathMLContainerFrame.cpp @@ -201,10 +201,14 @@ nsMathMLContainerFrame::GetPreferredStretchSize(nsRenderingContext& aRenderingCo aPreferredStretchSize = metrics.mBoundingMetrics; } else { - // compute a size that doesn't include embellishements - bool stretchAll = - NS_MATHML_WILL_STRETCH_ALL_CHILDREN_VERTICALLY(mPresentationData.flags) || - NS_MATHML_WILL_STRETCH_ALL_CHILDREN_HORIZONTALLY(mPresentationData.flags); + // compute a size that includes embellishments iff the container stretches + // in the same direction as the embellished operator. + bool stretchAll = aStretchDirection == NS_STRETCH_DIRECTION_VERTICAL ? + NS_MATHML_WILL_STRETCH_ALL_CHILDREN_VERTICALLY(mPresentationData.flags) : + NS_MATHML_WILL_STRETCH_ALL_CHILDREN_HORIZONTALLY(mPresentationData.flags); + NS_ASSERTION(aStretchDirection == NS_STRETCH_DIRECTION_HORIZONTAL || + aStretchDirection == NS_STRETCH_DIRECTION_VERTICAL, + "You must specify a direction in which to stretch"); NS_ASSERTION(NS_MATHML_IS_EMBELLISH_OPERATOR(mEmbellishData.flags) || stretchAll, "invalid call to GetPreferredStretchSize"); @@ -248,7 +252,7 @@ nsMathMLContainerFrame::GetPreferredStretchSize(nsRenderingContext& aRenderingCo } } else { - if (NS_MATHML_WILL_STRETCH_ALL_CHILDREN_HORIZONTALLY(mPresentationData.flags)) { + if (aStretchDirection == NS_STRETCH_DIRECTION_HORIZONTAL) { // if we get here, it means this is container that will stack its children // vertically and fire an horizontal stretch on each them. This is the case // for \munder, \mover, \munderover. We just sum-up the size vertically. @@ -266,7 +270,7 @@ nsMathMLContainerFrame::GetPreferredStretchSize(nsRenderingContext& aRenderingCo if (bm.rightBearing < bmChild.rightBearing) bm.rightBearing = bmChild.rightBearing; } - else if (NS_MATHML_WILL_STRETCH_ALL_CHILDREN_VERTICALLY(mPresentationData.flags)) { + else if (aStretchDirection == NS_STRETCH_DIRECTION_VERTICAL) { // just sum-up the sizes horizontally. bm += bmChild; } @@ -307,9 +311,6 @@ nsMathMLContainerFrame::Stretch(nsRenderingContext& aRenderingContext, nsIMathMLFrame* mathMLFrame = do_QueryFrame(baseFrame); NS_ASSERTION(mathMLFrame, "Something is wrong somewhere"); if (mathMLFrame) { - bool stretchAll = - NS_MATHML_WILL_STRETCH_ALL_CHILDREN_VERTICALLY(mPresentationData.flags) || - NS_MATHML_WILL_STRETCH_ALL_CHILDREN_HORIZONTALLY(mPresentationData.flags); // And the trick is that the child's rect.x is still holding the descent, // and rect.y is still holding the ascent ... @@ -328,21 +329,26 @@ nsMathMLContainerFrame::Stretch(nsRenderingContext& aRenderingContext, // // nsBoundingMetrics containerSize = aContainerSize; - if (aStretchDirection != NS_STRETCH_DIRECTION_DEFAULT && - aStretchDirection != mEmbellishData.direction) { - if (mEmbellishData.direction == NS_STRETCH_DIRECTION_UNSUPPORTED) { - containerSize = childSize.mBoundingMetrics; - } - else { - GetPreferredStretchSize(aRenderingContext, - stretchAll ? STRETCH_CONSIDER_EMBELLISHMENTS : 0, + if (aStretchDirection != mEmbellishData.direction && + mEmbellishData.direction != NS_STRETCH_DIRECTION_UNSUPPORTED) { + NS_ASSERTION(mEmbellishData.direction != NS_STRETCH_DIRECTION_DEFAULT, + "Stretches may have a default direction, operators can not."); + if (mEmbellishData.direction == NS_STRETCH_DIRECTION_VERTICAL ? + NS_MATHML_WILL_STRETCH_ALL_CHILDREN_VERTICALLY(mPresentationData.flags) : + NS_MATHML_WILL_STRETCH_ALL_CHILDREN_HORIZONTALLY(mPresentationData.flags)) { + GetPreferredStretchSize(aRenderingContext, 0, mEmbellishData.direction, containerSize); + // Stop further recalculations + aStretchDirection = mEmbellishData.direction; + } else { + // We aren't going to stretch the child, so just use the child metrics. + containerSize = childSize.mBoundingMetrics; } } // do the stretching... mathMLFrame->Stretch(aRenderingContext, - mEmbellishData.direction, containerSize, childSize); + aStretchDirection, containerSize, childSize); // store the updated metrics SaveReflowAndBoundingMetricsFor(baseFrame, childSize, childSize.mBoundingMetrics); @@ -351,7 +357,8 @@ nsMathMLContainerFrame::Stretch(nsRenderingContext& aRenderingContext, // Now that this embellished child may have changed, we need to // fire the stretch on its siblings using our updated size - if (stretchAll) { + if (NS_MATHML_WILL_STRETCH_ALL_CHILDREN_VERTICALLY(mPresentationData.flags) || + NS_MATHML_WILL_STRETCH_ALL_CHILDREN_HORIZONTALLY(mPresentationData.flags)) { nsStretchDirection stretchDir = NS_MATHML_WILL_STRETCH_ALL_CHILDREN_VERTICALLY(mPresentationData.flags) ? @@ -502,18 +509,21 @@ nsMathMLContainerFrame::FinalizeReflow(nsRenderingContext& aRenderingContext, /* NS_MATHML_WILL_STRETCH_ALL_CHILDREN_VERTICALLY(mPresentationData.flags) || */ NS_MATHML_WILL_STRETCH_ALL_CHILDREN_HORIZONTALLY(mPresentationData.flags); - nsBoundingMetrics defaultSize; - if (mEmbellishData.coreFrame == this /* case of a bare ... itself */ - || stretchAll) { /* or ......, or friends */ - // use our current size as computed earlier by Place() - defaultSize = aDesiredSize.mBoundingMetrics; + nsStretchDirection stretchDir; + if (mEmbellishData.coreFrame == this || /* case of a bare ... itself */ + (mEmbellishData.direction == NS_STRETCH_DIRECTION_HORIZONTAL && + stretchAll) || /* or ......, or friends */ + mEmbellishData.direction == NS_STRETCH_DIRECTION_UNSUPPORTED) { /* Doesn't stretch */ + stretchDir = mEmbellishData.direction; + } else { + // Let the Stretch() call decide the direction. + stretchDir = NS_STRETCH_DIRECTION_DEFAULT; } - else { /* case of ...... or friends */ - // compute a size that doesn't include embellishments - GetPreferredStretchSize(aRenderingContext, 0, mEmbellishData.direction, - defaultSize); - } - Stretch(aRenderingContext, NS_STRETCH_DIRECTION_DEFAULT, defaultSize, + // Use our current size as computed earlier by Place() + // The stretch call will detect if this is incorrect and recalculate the size. + nsBoundingMetrics defaultSize = aDesiredSize.mBoundingMetrics; + + Stretch(aRenderingContext, stretchDir, defaultSize, aDesiredSize); #ifdef DEBUG { From c9f45bcf619fed5aae813018753b87378bada2cd Mon Sep 17 00:00:00 2001 From: James Kitchener Date: Mon, 1 Sep 2014 06:49:00 +0200 Subject: [PATCH 056/114] Bug 687807 - Tests for stretchy MathML. r=fredw --- layout/reftests/mathml/reftest.list | 33 +++++++++++++++++++ .../mathml/stretchy-mfenced-1-ref.html | 19 +++++++++++ .../reftests/mathml/stretchy-mfenced-1a.html | 19 +++++++++++ .../reftests/mathml/stretchy-mfenced-1b.html | 21 ++++++++++++ .../mathml/stretchy-mfenced-2-ref.html | 18 ++++++++++ .../reftests/mathml/stretchy-mfenced-2a.html | 18 ++++++++++ .../reftests/mathml/stretchy-mfenced-2b.html | 20 +++++++++++ .../mathml/stretchy-mfenced-3-ref.html | 22 +++++++++++++ .../reftests/mathml/stretchy-mfenced-3a.html | 22 +++++++++++++ .../reftests/mathml/stretchy-mfenced-3b.html | 24 ++++++++++++++ .../mathml/stretchy-mfenced-4-ref.html | 19 +++++++++++ .../reftests/mathml/stretchy-mfenced-4a.html | 21 ++++++++++++ .../reftests/mathml/stretchy-mfenced-4b.html | 21 ++++++++++++ .../reftests/mathml/stretchy-mover-1-ref.html | 16 +++++++++ layout/reftests/mathml/stretchy-mover-1a.html | 22 +++++++++++++ layout/reftests/mathml/stretchy-mover-1b.html | 22 +++++++++++++ .../reftests/mathml/stretchy-mover-2-ref.html | 20 +++++++++++ layout/reftests/mathml/stretchy-mover-2a.html | 22 +++++++++++++ layout/reftests/mathml/stretchy-mover-2b.html | 22 +++++++++++++ .../reftests/mathml/stretchy-mover-3-ref.html | 16 +++++++++ layout/reftests/mathml/stretchy-mover-3.html | 16 +++++++++ .../reftests/mathml/stretchy-msup-1-ref.html | 16 +++++++++ layout/reftests/mathml/stretchy-msup-1a.html | 16 +++++++++ layout/reftests/mathml/stretchy-msup-1b.html | 18 ++++++++++ layout/reftests/mathml/stretchy-msup-1c.html | 20 +++++++++++ layout/reftests/mathml/stretchy-msup-1d.html | 19 +++++++++++ .../mathml/stretchy-munderover-1-ref.html | 19 +++++++++++ .../mathml/stretchy-munderover-1a.html | 19 +++++++++++ .../mathml/stretchy-munderover-1b.html | 21 ++++++++++++ .../mathml/stretchy-munderover-1c.html | 17 ++++++++++ .../mathml/stretchy-munderover-1d.html | 20 +++++++++++ .../mathml/stretchy-munderover-1e.html | 20 +++++++++++ .../mathml/stretchy-munderover-2-ref.html | 22 +++++++++++++ .../mathml/stretchy-munderover-2a.html | 22 +++++++++++++ .../mathml/stretchy-munderover-2b.html | 24 ++++++++++++++ .../mathml/stretchy-munderover-2c.html | 20 +++++++++++ .../mathml/stretchy-munderover-2d.html | 22 +++++++++++++ .../mathml/stretchy-munderover-2e.html | 22 +++++++++++++ .../mathml/stretchy-munderover-2f.html | 24 ++++++++++++++ .../mathml/stretchy-munderover-2g.html | 23 +++++++++++++ .../mathml/stretchy-munderover-3-ref.html | 19 +++++++++++ .../mathml/stretchy-munderover-3a.html | 19 +++++++++++ .../mathml/stretchy-munderover-3b.html | 17 ++++++++++ .../mathml/stretchy-munderover-3c.html | 20 +++++++++++ .../mathml/stretchy-munderover-3d.html | 17 ++++++++++ 45 files changed, 909 insertions(+) create mode 100644 layout/reftests/mathml/stretchy-mfenced-1-ref.html create mode 100644 layout/reftests/mathml/stretchy-mfenced-1a.html create mode 100644 layout/reftests/mathml/stretchy-mfenced-1b.html create mode 100644 layout/reftests/mathml/stretchy-mfenced-2-ref.html create mode 100644 layout/reftests/mathml/stretchy-mfenced-2a.html create mode 100644 layout/reftests/mathml/stretchy-mfenced-2b.html create mode 100644 layout/reftests/mathml/stretchy-mfenced-3-ref.html create mode 100644 layout/reftests/mathml/stretchy-mfenced-3a.html create mode 100644 layout/reftests/mathml/stretchy-mfenced-3b.html create mode 100644 layout/reftests/mathml/stretchy-mfenced-4-ref.html create mode 100644 layout/reftests/mathml/stretchy-mfenced-4a.html create mode 100644 layout/reftests/mathml/stretchy-mfenced-4b.html create mode 100644 layout/reftests/mathml/stretchy-mover-1-ref.html create mode 100644 layout/reftests/mathml/stretchy-mover-1a.html create mode 100644 layout/reftests/mathml/stretchy-mover-1b.html create mode 100644 layout/reftests/mathml/stretchy-mover-2-ref.html create mode 100644 layout/reftests/mathml/stretchy-mover-2a.html create mode 100644 layout/reftests/mathml/stretchy-mover-2b.html create mode 100644 layout/reftests/mathml/stretchy-mover-3-ref.html create mode 100644 layout/reftests/mathml/stretchy-mover-3.html create mode 100644 layout/reftests/mathml/stretchy-msup-1-ref.html create mode 100644 layout/reftests/mathml/stretchy-msup-1a.html create mode 100644 layout/reftests/mathml/stretchy-msup-1b.html create mode 100644 layout/reftests/mathml/stretchy-msup-1c.html create mode 100644 layout/reftests/mathml/stretchy-msup-1d.html create mode 100644 layout/reftests/mathml/stretchy-munderover-1-ref.html create mode 100644 layout/reftests/mathml/stretchy-munderover-1a.html create mode 100644 layout/reftests/mathml/stretchy-munderover-1b.html create mode 100644 layout/reftests/mathml/stretchy-munderover-1c.html create mode 100644 layout/reftests/mathml/stretchy-munderover-1d.html create mode 100644 layout/reftests/mathml/stretchy-munderover-1e.html create mode 100644 layout/reftests/mathml/stretchy-munderover-2-ref.html create mode 100644 layout/reftests/mathml/stretchy-munderover-2a.html create mode 100644 layout/reftests/mathml/stretchy-munderover-2b.html create mode 100644 layout/reftests/mathml/stretchy-munderover-2c.html create mode 100644 layout/reftests/mathml/stretchy-munderover-2d.html create mode 100644 layout/reftests/mathml/stretchy-munderover-2e.html create mode 100644 layout/reftests/mathml/stretchy-munderover-2f.html create mode 100644 layout/reftests/mathml/stretchy-munderover-2g.html create mode 100644 layout/reftests/mathml/stretchy-munderover-3-ref.html create mode 100644 layout/reftests/mathml/stretchy-munderover-3a.html create mode 100644 layout/reftests/mathml/stretchy-munderover-3b.html create mode 100644 layout/reftests/mathml/stretchy-munderover-3c.html create mode 100644 layout/reftests/mathml/stretchy-munderover-3d.html diff --git a/layout/reftests/mathml/reftest.list b/layout/reftests/mathml/reftest.list index 9b5ac9073e09..b31eb7d6e43c 100644 --- a/layout/reftests/mathml/reftest.list +++ b/layout/reftests/mathml/reftest.list @@ -44,6 +44,39 @@ fails-if(/^Windows\x20NT\x205\.1/.test(http.oscpu)) == mfenced-10.html mfenced-1 == overbar-width-1.xhtml overbar-width-1-ref.xhtml skip-if(B2G) == quotes-1.xhtml quotes-1-ref.xhtml != stretchy-underbar-1.xhtml stretchy-underbar-1-ref.xhtml +!= stretchy-munderover-1a.html stretchy-munderover-1-ref.html +== stretchy-munderover-1b.html stretchy-munderover-1-ref.html +== stretchy-munderover-1c.html stretchy-munderover-1-ref.html +== stretchy-munderover-1d.html stretchy-munderover-1-ref.html +== stretchy-munderover-1e.html stretchy-munderover-1-ref.html +!= stretchy-munderover-2a.html stretchy-munderover-2-ref.html +== stretchy-munderover-2b.html stretchy-munderover-2-ref.html +== stretchy-munderover-2c.html stretchy-munderover-2-ref.html +== stretchy-munderover-2d.html stretchy-munderover-2-ref.html +== stretchy-munderover-2e.html stretchy-munderover-2-ref.html +== stretchy-munderover-2f.html stretchy-munderover-2-ref.html +== stretchy-munderover-2g.html stretchy-munderover-2-ref.html +!= stretchy-munderover-3a.html stretchy-munderover-3-ref.html +== stretchy-munderover-3b.html stretchy-munderover-3-ref.html +== stretchy-munderover-3c.html stretchy-munderover-3-ref.html +!= stretchy-munderover-3d.html stretchy-munderover-3-ref.html +== stretchy-msup-1a.html stretchy-msup-1-ref.html +== stretchy-msup-1b.html stretchy-msup-1-ref.html +== stretchy-msup-1c.html stretchy-msup-1-ref.html +== stretchy-msup-1d.html stretchy-msup-1-ref.html +!= stretchy-mfenced-1a.html stretchy-mfenced-1-ref.html +!= stretchy-mfenced-1b.html stretchy-mfenced-1-ref.html +== stretchy-mfenced-2a.html stretchy-mfenced-2-ref.html +!= stretchy-mfenced-2b.html stretchy-mfenced-2-ref.html +!= stretchy-mfenced-3a.html stretchy-mfenced-3-ref.html +!= stretchy-mfenced-3b.html stretchy-mfenced-3-ref.html +== stretchy-mfenced-4a.html stretchy-mfenced-4-ref.html +== stretchy-mfenced-4b.html stretchy-mfenced-4-ref.html +== stretchy-mover-1a.html stretchy-mover-1-ref.html +== stretchy-mover-1b.html stretchy-mover-1-ref.html +fails == stretchy-mover-2a.html stretchy-mover-2-ref.html +!= stretchy-mover-2b.html stretchy-mover-2-ref.html +== stretchy-mover-3.html stretchy-mover-3-ref.html == table-width-1.xhtml table-width-1-ref.xhtml == table-width-2.html table-width-2-ref.html == table-width-3.html table-width-3-ref.html diff --git a/layout/reftests/mathml/stretchy-mfenced-1-ref.html b/layout/reftests/mathml/stretchy-mfenced-1-ref.html new file mode 100644 index 000000000000..448fe886e81d --- /dev/null +++ b/layout/reftests/mathml/stretchy-mfenced-1-ref.html @@ -0,0 +1,19 @@ + + + + Stretchy mfenced + + + + + + + + + AAAAAA + BBBBBB + + + + + diff --git a/layout/reftests/mathml/stretchy-mfenced-1a.html b/layout/reftests/mathml/stretchy-mfenced-1a.html new file mode 100644 index 000000000000..749e37e5766e --- /dev/null +++ b/layout/reftests/mathml/stretchy-mfenced-1a.html @@ -0,0 +1,19 @@ + + + + Stretchy mfenced + + + + + + + + + AAAAAA + BBBBBB + + + + + diff --git a/layout/reftests/mathml/stretchy-mfenced-1b.html b/layout/reftests/mathml/stretchy-mfenced-1b.html new file mode 100644 index 000000000000..1ffb9c25587b --- /dev/null +++ b/layout/reftests/mathml/stretchy-mfenced-1b.html @@ -0,0 +1,21 @@ + + + + Stretchy mfenced + + + + + + + ( + + + AAAAAA + BBBBBB + + ) + + + + diff --git a/layout/reftests/mathml/stretchy-mfenced-2-ref.html b/layout/reftests/mathml/stretchy-mfenced-2-ref.html new file mode 100644 index 000000000000..c7faff53624f --- /dev/null +++ b/layout/reftests/mathml/stretchy-mfenced-2-ref.html @@ -0,0 +1,18 @@ + + + + Stretchy mfenced + + + + + + + + + AAAAAA + + + + + diff --git a/layout/reftests/mathml/stretchy-mfenced-2a.html b/layout/reftests/mathml/stretchy-mfenced-2a.html new file mode 100644 index 000000000000..f8c997dbce79 --- /dev/null +++ b/layout/reftests/mathml/stretchy-mfenced-2a.html @@ -0,0 +1,18 @@ + + + + Stretchy mfenced + + + + + + + + + AAAAAA + + + + + diff --git a/layout/reftests/mathml/stretchy-mfenced-2b.html b/layout/reftests/mathml/stretchy-mfenced-2b.html new file mode 100644 index 000000000000..152eebc7e44c --- /dev/null +++ b/layout/reftests/mathml/stretchy-mfenced-2b.html @@ -0,0 +1,20 @@ + + + + Stretchy mfenced + + + + + + + ( + + + AAAAAA + + ) + + + + diff --git a/layout/reftests/mathml/stretchy-mfenced-3-ref.html b/layout/reftests/mathml/stretchy-mfenced-3-ref.html new file mode 100644 index 000000000000..5b9265a1bdcd --- /dev/null +++ b/layout/reftests/mathml/stretchy-mfenced-3-ref.html @@ -0,0 +1,22 @@ + + + + Stretchy mfenced + + + + + + + + + + AAAAAA + BBBBBB + + CCCCCC + + + + + diff --git a/layout/reftests/mathml/stretchy-mfenced-3a.html b/layout/reftests/mathml/stretchy-mfenced-3a.html new file mode 100644 index 000000000000..1e350f9c2aa6 --- /dev/null +++ b/layout/reftests/mathml/stretchy-mfenced-3a.html @@ -0,0 +1,22 @@ + + + + Stretchy mfenced + + + + + + + + + + AAAAAA + BBBBBB + + CCCCCC + + + + + diff --git a/layout/reftests/mathml/stretchy-mfenced-3b.html b/layout/reftests/mathml/stretchy-mfenced-3b.html new file mode 100644 index 000000000000..8d2b63a78b3a --- /dev/null +++ b/layout/reftests/mathml/stretchy-mfenced-3b.html @@ -0,0 +1,24 @@ + + + + Stretchy mfenced + + + + + + + ( + + + + AAAAAA + BBBBBB + + CCCCCC + + ) + + + + diff --git a/layout/reftests/mathml/stretchy-mfenced-4-ref.html b/layout/reftests/mathml/stretchy-mfenced-4-ref.html new file mode 100644 index 000000000000..fd5dc36f84ff --- /dev/null +++ b/layout/reftests/mathml/stretchy-mfenced-4-ref.html @@ -0,0 +1,19 @@ + + + + Stretchy mfenced + + + + + + + + + AAAAAA + BBBBBB + + + + + diff --git a/layout/reftests/mathml/stretchy-mfenced-4a.html b/layout/reftests/mathml/stretchy-mfenced-4a.html new file mode 100644 index 000000000000..73da809859a1 --- /dev/null +++ b/layout/reftests/mathml/stretchy-mfenced-4a.html @@ -0,0 +1,21 @@ + + + + Stretchy mfenced + + + + + + + + + + AAAAAA + BBBBBB + + + + + + diff --git a/layout/reftests/mathml/stretchy-mfenced-4b.html b/layout/reftests/mathml/stretchy-mfenced-4b.html new file mode 100644 index 000000000000..fd5f2bb36df8 --- /dev/null +++ b/layout/reftests/mathml/stretchy-mfenced-4b.html @@ -0,0 +1,21 @@ + + + + Stretchy mfenced + + + + + + + + + + AAAAAA + BBBBBB + + + + + + diff --git a/layout/reftests/mathml/stretchy-mover-1-ref.html b/layout/reftests/mathml/stretchy-mover-1-ref.html new file mode 100644 index 000000000000..94df54069228 --- /dev/null +++ b/layout/reftests/mathml/stretchy-mover-1-ref.html @@ -0,0 +1,16 @@ + + + + Stretchy mover + + + + + + + + BBBBBBBBB + + + + diff --git a/layout/reftests/mathml/stretchy-mover-1a.html b/layout/reftests/mathml/stretchy-mover-1a.html new file mode 100644 index 000000000000..0c2a765d89f5 --- /dev/null +++ b/layout/reftests/mathml/stretchy-mover-1a.html @@ -0,0 +1,22 @@ + + + + Stretchy mover + + + + + + + + + + + BBBBBBBBB + + + + + + + diff --git a/layout/reftests/mathml/stretchy-mover-1b.html b/layout/reftests/mathml/stretchy-mover-1b.html new file mode 100644 index 000000000000..97c69944a258 --- /dev/null +++ b/layout/reftests/mathml/stretchy-mover-1b.html @@ -0,0 +1,22 @@ + + + + Stretchy mover + + + + + + + + + + + BBBBBBBBB + + + + + + + diff --git a/layout/reftests/mathml/stretchy-mover-2-ref.html b/layout/reftests/mathml/stretchy-mover-2-ref.html new file mode 100644 index 000000000000..ab84f9463865 --- /dev/null +++ b/layout/reftests/mathml/stretchy-mover-2-ref.html @@ -0,0 +1,20 @@ + + + + Stretchy mover + + + + + + + + + + B + + + + + + diff --git a/layout/reftests/mathml/stretchy-mover-2a.html b/layout/reftests/mathml/stretchy-mover-2a.html new file mode 100644 index 000000000000..a51be9dfdf9c --- /dev/null +++ b/layout/reftests/mathml/stretchy-mover-2a.html @@ -0,0 +1,22 @@ + + + + Stretchy mover + + + + + + + + + + + B + + + + + + + diff --git a/layout/reftests/mathml/stretchy-mover-2b.html b/layout/reftests/mathml/stretchy-mover-2b.html new file mode 100644 index 000000000000..2cb72d0529cd --- /dev/null +++ b/layout/reftests/mathml/stretchy-mover-2b.html @@ -0,0 +1,22 @@ + + + + Stretchy mover + + + + + + + + + + + B + + + + + + + diff --git a/layout/reftests/mathml/stretchy-mover-3-ref.html b/layout/reftests/mathml/stretchy-mover-3-ref.html new file mode 100644 index 000000000000..848f610891d3 --- /dev/null +++ b/layout/reftests/mathml/stretchy-mover-3-ref.html @@ -0,0 +1,16 @@ + + + + Stretchy mover + + + + + + + + BBBBBBBBB + + + + diff --git a/layout/reftests/mathml/stretchy-mover-3.html b/layout/reftests/mathml/stretchy-mover-3.html new file mode 100644 index 000000000000..e9b85ef3ff05 --- /dev/null +++ b/layout/reftests/mathml/stretchy-mover-3.html @@ -0,0 +1,16 @@ + + + + Stretchy mover + + + + + + + + BBBBBBBBB + + + + diff --git a/layout/reftests/mathml/stretchy-msup-1-ref.html b/layout/reftests/mathml/stretchy-msup-1-ref.html new file mode 100644 index 000000000000..8a30da8c38b8 --- /dev/null +++ b/layout/reftests/mathml/stretchy-msup-1-ref.html @@ -0,0 +1,16 @@ + + + + Non-stretchy msup + + + + + + + + AAAAAA + + + + diff --git a/layout/reftests/mathml/stretchy-msup-1a.html b/layout/reftests/mathml/stretchy-msup-1a.html new file mode 100644 index 000000000000..f34333c888cc --- /dev/null +++ b/layout/reftests/mathml/stretchy-msup-1a.html @@ -0,0 +1,16 @@ + + + + Non-stretchy msup + + + + + + + + AAAAAA + + + + diff --git a/layout/reftests/mathml/stretchy-msup-1b.html b/layout/reftests/mathml/stretchy-msup-1b.html new file mode 100644 index 000000000000..5b27dd25650c --- /dev/null +++ b/layout/reftests/mathml/stretchy-msup-1b.html @@ -0,0 +1,18 @@ + + + + Non-stretchy msup + + + + + + + + + AAAAAA + + + + + diff --git a/layout/reftests/mathml/stretchy-msup-1c.html b/layout/reftests/mathml/stretchy-msup-1c.html new file mode 100644 index 000000000000..cbc58f517697 --- /dev/null +++ b/layout/reftests/mathml/stretchy-msup-1c.html @@ -0,0 +1,20 @@ + + + + Non-stretchy msup + + + + + + + + + + AAAAAA + + + + + + diff --git a/layout/reftests/mathml/stretchy-msup-1d.html b/layout/reftests/mathml/stretchy-msup-1d.html new file mode 100644 index 000000000000..9987d1de42dc --- /dev/null +++ b/layout/reftests/mathml/stretchy-msup-1d.html @@ -0,0 +1,19 @@ + + + + Non-stretchy msup + + + + + + + + + AAAAAA + + + + + + diff --git a/layout/reftests/mathml/stretchy-munderover-1-ref.html b/layout/reftests/mathml/stretchy-munderover-1-ref.html new file mode 100644 index 000000000000..f384a925aea2 --- /dev/null +++ b/layout/reftests/mathml/stretchy-munderover-1-ref.html @@ -0,0 +1,19 @@ + + + + Stretchy munderover + + + + + + + + + AAAAAA + BBBBBB + + + + + diff --git a/layout/reftests/mathml/stretchy-munderover-1a.html b/layout/reftests/mathml/stretchy-munderover-1a.html new file mode 100644 index 000000000000..0748c41058aa --- /dev/null +++ b/layout/reftests/mathml/stretchy-munderover-1a.html @@ -0,0 +1,19 @@ + + + + Stretchy munderover + + + + + + + + + AAAAAA + BBBBBB + + + + + diff --git a/layout/reftests/mathml/stretchy-munderover-1b.html b/layout/reftests/mathml/stretchy-munderover-1b.html new file mode 100644 index 000000000000..477a422fee28 --- /dev/null +++ b/layout/reftests/mathml/stretchy-munderover-1b.html @@ -0,0 +1,21 @@ + + + + Stretchy munderover + + + + + + + + + + AAAAAA + BBBBBB + + + + + + diff --git a/layout/reftests/mathml/stretchy-munderover-1c.html b/layout/reftests/mathml/stretchy-munderover-1c.html new file mode 100644 index 000000000000..08f391acc5e4 --- /dev/null +++ b/layout/reftests/mathml/stretchy-munderover-1c.html @@ -0,0 +1,17 @@ + + + + Stretchy munderover + + + + + + + + AAAAAA + BBBBBB + + + + diff --git a/layout/reftests/mathml/stretchy-munderover-1d.html b/layout/reftests/mathml/stretchy-munderover-1d.html new file mode 100644 index 000000000000..ec2aa43b7756 --- /dev/null +++ b/layout/reftests/mathml/stretchy-munderover-1d.html @@ -0,0 +1,20 @@ + + + + Stretchy munderover + + + + + + + + + AAAAAA + BBBBBB + + + + + + diff --git a/layout/reftests/mathml/stretchy-munderover-1e.html b/layout/reftests/mathml/stretchy-munderover-1e.html new file mode 100644 index 000000000000..3a12b2184340 --- /dev/null +++ b/layout/reftests/mathml/stretchy-munderover-1e.html @@ -0,0 +1,20 @@ + + + + Stretchy munderover + + + + + + + + + AAAAAA + BBBBBB + + + + + + diff --git a/layout/reftests/mathml/stretchy-munderover-2-ref.html b/layout/reftests/mathml/stretchy-munderover-2-ref.html new file mode 100644 index 000000000000..6d62a1a7219f --- /dev/null +++ b/layout/reftests/mathml/stretchy-munderover-2-ref.html @@ -0,0 +1,22 @@ + + + + Stretchy munderover + + + + + + + + + + AAAAAA + BBBBBB + + CCCCCC + + + + + diff --git a/layout/reftests/mathml/stretchy-munderover-2a.html b/layout/reftests/mathml/stretchy-munderover-2a.html new file mode 100644 index 000000000000..abe59569f21f --- /dev/null +++ b/layout/reftests/mathml/stretchy-munderover-2a.html @@ -0,0 +1,22 @@ + + + + Stretchy munderover + + + + + + + + + + AAAAAA + BBBBBB + + CCCCCC + + + + + diff --git a/layout/reftests/mathml/stretchy-munderover-2b.html b/layout/reftests/mathml/stretchy-munderover-2b.html new file mode 100644 index 000000000000..1cef4e0a4f4a --- /dev/null +++ b/layout/reftests/mathml/stretchy-munderover-2b.html @@ -0,0 +1,24 @@ + + + + Stretchy munderover + + + + + + + + + + + AAAAAA + BBBBBB + + CCCCCC + + + + + + diff --git a/layout/reftests/mathml/stretchy-munderover-2c.html b/layout/reftests/mathml/stretchy-munderover-2c.html new file mode 100644 index 000000000000..0346c344fb2f --- /dev/null +++ b/layout/reftests/mathml/stretchy-munderover-2c.html @@ -0,0 +1,20 @@ + + + + Stretchy munderover + + + + + + + + + AAAAAA + BBBBBB + + CCCCCC + + + + diff --git a/layout/reftests/mathml/stretchy-munderover-2d.html b/layout/reftests/mathml/stretchy-munderover-2d.html new file mode 100644 index 000000000000..aaa6986c8624 --- /dev/null +++ b/layout/reftests/mathml/stretchy-munderover-2d.html @@ -0,0 +1,22 @@ + + + + Stretchy munderover + + + + + + + + + + AAAAAA + BBBBBB + + CCCCCC + + + + + diff --git a/layout/reftests/mathml/stretchy-munderover-2e.html b/layout/reftests/mathml/stretchy-munderover-2e.html new file mode 100644 index 000000000000..4cde801129ab --- /dev/null +++ b/layout/reftests/mathml/stretchy-munderover-2e.html @@ -0,0 +1,22 @@ + + + + Stretchy munderover + + + + + + + + + + AAAAAA + BBBBBB + + + CCCCCC + + + + diff --git a/layout/reftests/mathml/stretchy-munderover-2f.html b/layout/reftests/mathml/stretchy-munderover-2f.html new file mode 100644 index 000000000000..08ade38d3726 --- /dev/null +++ b/layout/reftests/mathml/stretchy-munderover-2f.html @@ -0,0 +1,24 @@ + + + + Stretchy munderover + + + + + + + + + + + AAAAAA + BBBBBB + + + + CCCCCC + + + + diff --git a/layout/reftests/mathml/stretchy-munderover-2g.html b/layout/reftests/mathml/stretchy-munderover-2g.html new file mode 100644 index 000000000000..a91e8ce84311 --- /dev/null +++ b/layout/reftests/mathml/stretchy-munderover-2g.html @@ -0,0 +1,23 @@ + + + + Stretchy munderover + + + + + + + + + + AAAAAA + BBBBBB + + CCCCCC + + + + + + diff --git a/layout/reftests/mathml/stretchy-munderover-3-ref.html b/layout/reftests/mathml/stretchy-munderover-3-ref.html new file mode 100644 index 000000000000..9c4a80e99254 --- /dev/null +++ b/layout/reftests/mathml/stretchy-munderover-3-ref.html @@ -0,0 +1,19 @@ + + + + Stretchy munderover + + + + + + + + AAAAAA + + BBBBBB + + + + + diff --git a/layout/reftests/mathml/stretchy-munderover-3a.html b/layout/reftests/mathml/stretchy-munderover-3a.html new file mode 100644 index 000000000000..ccc8d1fb1344 --- /dev/null +++ b/layout/reftests/mathml/stretchy-munderover-3a.html @@ -0,0 +1,19 @@ + + + + Stretchy munderover + + + + + + + + AAAAAA + + BBBBBB + + + + + diff --git a/layout/reftests/mathml/stretchy-munderover-3b.html b/layout/reftests/mathml/stretchy-munderover-3b.html new file mode 100644 index 000000000000..4ef214dae5bc --- /dev/null +++ b/layout/reftests/mathml/stretchy-munderover-3b.html @@ -0,0 +1,17 @@ + + + + Stretchy munderover + + + + + + + AAAAAA + + BBBBBB + + + + diff --git a/layout/reftests/mathml/stretchy-munderover-3c.html b/layout/reftests/mathml/stretchy-munderover-3c.html new file mode 100644 index 000000000000..dced4057db59 --- /dev/null +++ b/layout/reftests/mathml/stretchy-munderover-3c.html @@ -0,0 +1,20 @@ + + + + Stretchy munderover + + + + + + + + AAAAAA + + BBBBBB + + + + + + diff --git a/layout/reftests/mathml/stretchy-munderover-3d.html b/layout/reftests/mathml/stretchy-munderover-3d.html new file mode 100644 index 000000000000..8497bd595164 --- /dev/null +++ b/layout/reftests/mathml/stretchy-munderover-3d.html @@ -0,0 +1,17 @@ + + + + Stretchy munderover + + + + + + + AAAAAA + + BBBBBB + + + + From f545276ac56a03d823b8547482c37eeaa6fa2910 Mon Sep 17 00:00:00 2001 From: Jed Davis Date: Thu, 18 Sep 2014 17:59:00 +0200 Subject: [PATCH 057/114] Bug 1064529 - Don't misuse invalid ipc::FileDescriptor in memory report requests. r=njn --- dom/ipc/ContentChild.cpp | 14 ++++++++------ dom/ipc/ContentChild.h | 4 ++-- dom/ipc/ContentParent.cpp | 4 ++-- dom/ipc/ContentParent.h | 2 +- dom/ipc/PContent.ipdl | 7 ++++++- 5 files changed, 19 insertions(+), 12 deletions(-) diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index acabb6697e56..78e8670b0570 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -202,7 +202,7 @@ public: NS_DECL_ISUPPORTS MemoryReportRequestChild(uint32_t aGeneration, bool aAnonymize, - const FileDescriptor& aDMDFile); + const MaybeFileDesc& aDMDFile); NS_IMETHOD Run(); private: virtual ~MemoryReportRequestChild(); @@ -215,11 +215,13 @@ private: NS_IMPL_ISUPPORTS(MemoryReportRequestChild, nsIRunnable) MemoryReportRequestChild::MemoryReportRequestChild( - uint32_t aGeneration, bool aAnonymize, const FileDescriptor& aDMDFile) - : mGeneration(aGeneration), mAnonymize(aAnonymize), - mDMDFile(aDMDFile) + uint32_t aGeneration, bool aAnonymize, const MaybeFileDesc& aDMDFile) + : mGeneration(aGeneration), mAnonymize(aAnonymize) { MOZ_COUNT_CTOR(MemoryReportRequestChild); + if (aDMDFile.type() == MaybeFileDesc::TFileDescriptor) { + mDMDFile = aDMDFile.get_FileDescriptor(); + } } MemoryReportRequestChild::~MemoryReportRequestChild() @@ -707,7 +709,7 @@ PMemoryReportRequestChild* ContentChild::AllocPMemoryReportRequestChild(const uint32_t& aGeneration, const bool &aAnonymize, const bool &aMinimizeMemoryUsage, - const FileDescriptor& aDMDFile) + const MaybeFileDesc& aDMDFile) { MemoryReportRequestChild *actor = new MemoryReportRequestChild(aGeneration, aAnonymize, aDMDFile); @@ -765,7 +767,7 @@ ContentChild::RecvPMemoryReportRequestConstructor( const uint32_t& aGeneration, const bool& aAnonymize, const bool& aMinimizeMemoryUsage, - const FileDescriptor& aDMDFile) + const MaybeFileDesc& aDMDFile) { MemoryReportRequestChild *actor = static_cast(aChild); diff --git a/dom/ipc/ContentChild.h b/dom/ipc/ContentChild.h index c85ff9ab0794..ee5a7a0384fa 100644 --- a/dom/ipc/ContentChild.h +++ b/dom/ipc/ContentChild.h @@ -161,7 +161,7 @@ public: AllocPMemoryReportRequestChild(const uint32_t& aGeneration, const bool& aAnonymize, const bool& aMinimizeMemoryUsage, - const FileDescriptor& aDMDFile) MOZ_OVERRIDE; + const MaybeFileDesc& aDMDFile) MOZ_OVERRIDE; virtual bool DeallocPMemoryReportRequestChild(PMemoryReportRequestChild* actor) MOZ_OVERRIDE; @@ -170,7 +170,7 @@ public: const uint32_t& aGeneration, const bool& aAnonymize, const bool &aMinimizeMemoryUsage, - const FileDescriptor &aDMDFile) MOZ_OVERRIDE; + const MaybeFileDesc &aDMDFile) MOZ_OVERRIDE; virtual PCycleCollectWithLogsChild* AllocPCycleCollectWithLogsChild(const bool& aDumpAllTraces, diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 0b340e648c21..ba5c0c538eb9 100755 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -2596,7 +2596,7 @@ ContentParent::Observe(nsISupports* aSubject, // The pre-%n part of the string should be all ASCII, so the byte // offset in identOffset should be correct as a char offset. MOZ_ASSERT(cmsg[identOffset - 1] == '='); - FileDescriptor dmdFileDesc; + MaybeFileDesc dmdFileDesc = void_t(); #ifdef MOZ_DMD nsAutoString dmdIdent(Substring(msg, identOffset)); if (!dmdIdent.IsEmpty()) { @@ -2984,7 +2984,7 @@ PMemoryReportRequestParent* ContentParent::AllocPMemoryReportRequestParent(const uint32_t& aGeneration, const bool &aAnonymize, const bool &aMinimizeMemoryUsage, - const FileDescriptor &aDMDFile) + const MaybeFileDesc &aDMDFile) { MemoryReportRequestParent* parent = new MemoryReportRequestParent(); return parent; diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h index 903a8188d800..772b1f661c82 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -455,7 +455,7 @@ private: AllocPMemoryReportRequestParent(const uint32_t& aGeneration, const bool &aAnonymize, const bool &aMinimizeMemoryUsage, - const FileDescriptor &aDMDFile) MOZ_OVERRIDE; + const MaybeFileDesc &aDMDFile) MOZ_OVERRIDE; virtual bool DeallocPMemoryReportRequestParent(PMemoryReportRequestParent* actor) MOZ_OVERRIDE; virtual PCycleCollectWithLogsParent* diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl index bbb1742b6c37..abf8c02ab97f 100644 --- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -303,6 +303,11 @@ struct VolumeInfo { bool isFake; }; +union MaybeFileDesc { + FileDescriptor; + void_t; +}; + intr protocol PContent { parent opens PCompositor; @@ -377,7 +382,7 @@ child: async SetProcessSandbox(); PMemoryReportRequest(uint32_t generation, bool anonymize, - bool minimizeMemoryUsage, FileDescriptor DMDFile); + bool minimizeMemoryUsage, MaybeFileDesc DMDFile); /** * Notify the AudioChannelService in the child processes. From b3480f243255fcd747e20ba707d0100d81a76592 Mon Sep 17 00:00:00 2001 From: Michael Shuen Date: Fri, 19 Sep 2014 18:35:00 +0200 Subject: [PATCH 058/114] Bug 1061652 - Inline setCrossCompartmentSlot on windows. r=luke --- js/src/vm/ObjectImpl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/vm/ObjectImpl.h b/js/src/vm/ObjectImpl.h index 6603da369993..c62051c7141c 100644 --- a/js/src/vm/ObjectImpl.h +++ b/js/src/vm/ObjectImpl.h @@ -769,7 +769,7 @@ class ObjectImpl : public gc::Cell getSlotRef(slot).set(this->asObjectPtr(), HeapSlot::Slot, slot, value); } - inline void setCrossCompartmentSlot(uint32_t slot, const Value &value) { + MOZ_ALWAYS_INLINE void setCrossCompartmentSlot(uint32_t slot, const Value &value) { MOZ_ASSERT(slotInRange(slot)); getSlotRef(slot).set(this->asObjectPtr(), HeapSlot::Slot, slot, value); } From 974eae2d0108c8ea25f69a814ba852116c05c7fb Mon Sep 17 00:00:00 2001 From: Xidorn Quan Date: Sat, 20 Sep 2014 03:43:00 +0200 Subject: [PATCH 059/114] Bug 1069716 - Fix deficient CalcDifference of nsStyleList. r=heycam --- layout/reftests/bugs/1069716-1-ref.html | 11 +++++++++++ layout/reftests/bugs/1069716-1.html | 20 ++++++++++++++++++++ layout/reftests/bugs/reftest.list | 1 + layout/style/nsStyleStruct.cpp | 7 +++++-- layout/style/nsStyleStruct.h | 3 ++- 5 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 layout/reftests/bugs/1069716-1-ref.html create mode 100644 layout/reftests/bugs/1069716-1.html diff --git a/layout/reftests/bugs/1069716-1-ref.html b/layout/reftests/bugs/1069716-1-ref.html new file mode 100644 index 000000000000..e2ed8da169ba --- /dev/null +++ b/layout/reftests/bugs/1069716-1-ref.html @@ -0,0 +1,11 @@ + + + + + + + +
  • <---That should be a 'b' character. diff --git a/layout/reftests/bugs/1069716-1.html b/layout/reftests/bugs/1069716-1.html new file mode 100644 index 000000000000..2615a1f01e73 --- /dev/null +++ b/layout/reftests/bugs/1069716-1.html @@ -0,0 +1,20 @@ + + + + + + + +
    • <---That should be a 'b' character. diff --git a/layout/reftests/bugs/reftest.list b/layout/reftests/bugs/reftest.list index 7de2777aa66c..71c998297606 100644 --- a/layout/reftests/bugs/reftest.list +++ b/layout/reftests/bugs/reftest.list @@ -1834,3 +1834,4 @@ test-pref(layout.css.grid.enabled,true) == 1053035-1-grid.html 1053035-1-ref.htm == 1059498-2.html 1059498-1-ref.html == 1059498-3.html 1059498-1-ref.html test-pref(dom.webcomponents.enabled,true) == 1066554-1.html 1066554-1-ref.html +== 1069716-1.html 1069716-1-ref.html diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp index ab5c0257a666..5c5c77ca2eb8 100644 --- a/layout/style/nsStyleStruct.cpp +++ b/layout/style/nsStyleStruct.cpp @@ -704,9 +704,12 @@ nsChangeHint nsStyleList::CalcDifference(const nsStyleList& aOther) const if (mListStylePosition != aOther.mListStylePosition) return NS_STYLE_HINT_FRAMECHANGE; if (EqualImages(mListStyleImage, aOther.mListStyleImage) && - mListStyleType == aOther.mListStyleType) { - if (mImageRegion.IsEqualInterior(aOther.mImageRegion)) + mCounterStyle == aOther.mCounterStyle) { + if (mImageRegion.IsEqualInterior(aOther.mImageRegion)) { + if (mListStyleType != aOther.mListStyleType) + return nsChangeHint_NeutralChange; return NS_STYLE_HINT_NONE; + } if (mImageRegion.width == aOther.mImageRegion.width && mImageRegion.height == aOther.mImageRegion.height) return NS_STYLE_HINT_VISUAL; diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h index 71c883be0f54..59db408fd961 100644 --- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -1154,7 +1154,8 @@ struct nsStyleList { nsChangeHint CalcDifference(const nsStyleList& aOther) const; static nsChangeHint MaxDifference() { - return NS_STYLE_HINT_FRAMECHANGE; + return NS_CombineHint(NS_STYLE_HINT_FRAMECHANGE, + nsChangeHint_NeutralChange); } static nsChangeHint MaxDifferenceNeverInherited() { // CalcDifference never returns nsChangeHint_NeedReflow or From 06d75be66691fc3ed26b04826b268640fee4d14f Mon Sep 17 00:00:00 2001 From: Jan-Ivar Bruaroey Date: Fri, 19 Sep 2014 15:25:06 -0400 Subject: [PATCH 060/114] Bug 1070076 - fixed createOffer options arg legacy-syntax-warning to not trip on absent arg. r=jesup --- dom/media/PeerConnection.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dom/media/PeerConnection.js b/dom/media/PeerConnection.js index 0499c4711654..0660570268bf 100644 --- a/dom/media/PeerConnection.js +++ b/dom/media/PeerConnection.js @@ -557,9 +557,10 @@ RTCPeerConnection.prototype = { createOffer: function(onSuccess, onError, options) { // TODO: Remove old constraint-like RTCOptions support soon (Bug 1064223). + // Note that webidl bindings make o.mandatory implicit but not o.optional. function convertLegacyOptions(o) { - if (!(o.mandatory || o.optional) || - Object.keys(o).length != ((o.mandatory && o.optional)? 2 : 1)) { + if (!(Object.keys(o.mandatory).length || o.optional) || + Object.keys(o).length != (o.optional? 2 : 1)) { return false; } let old = o.mandatory || {}; From fbde51300ebbdf2c497000b07c63f21412210a19 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Fri, 19 Sep 2014 12:37:02 -0700 Subject: [PATCH 061/114] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 0fa09301dc11..4a1cb925b465 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 5c937ca3f1c3..754280956501 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 438c106df08e..4f00ab6b8396 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 7e0cac93335c..528d1490ef91 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 5c937ca3f1c3..754280956501 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index 37262f8f6ecc..39bc05af0f8a 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 9b2d13ad4f59..9db0cd35dc38 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 4444e22acd31..cadf4dbc5410 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 47942959f44d..95745d470cf0 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 45d2ad2dc87c..1c76db7522bb 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 8c78f0029c60..51127adb9a89 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From 0fc10637c3eab63db741c9ef8bbc4b61b95307e2 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Fri, 19 Sep 2014 14:10:47 -0700 Subject: [PATCH 062/114] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/96f2947a5a91 Author: Arnau Desc: Merge pull request #24209 from rnowm/1069531 Bug 1069531 - [Calendar] Settings: sync and gear icons overlaps r=millermedeiros ======== https://hg.mozilla.org/integration/gaia-central/rev/0ba56b8c1b99 Author: rnowm Desc: Bug 1069531 - [Calendar] Settings: sync and gear icons overlaps --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 060b46c77483..5ca9fcbe5fa1 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "b5f6c10e258311d9f04ed759291bbe6af10a772b", + "revision": "96f2947a5a9145a7697110981d355869b7093dbb", "repo_path": "/integration/gaia-central" } From af89def73c04d5830e36f5c1dab02c35c7cda213 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Fri, 19 Sep 2014 14:17:01 -0700 Subject: [PATCH 063/114] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 4a1cb925b465..fb71468ba6f0 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 754280956501..c6ee2b3a9b8f 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 4f00ab6b8396..93d84e957b43 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 528d1490ef91..d0905d65bc63 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 754280956501..c6ee2b3a9b8f 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index 39bc05af0f8a..97398db479c0 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 9db0cd35dc38..d39deeec68e7 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index cadf4dbc5410..43e247617297 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 95745d470cf0..85388cf5846d 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 1c76db7522bb..61cb1d6b2d79 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 51127adb9a89..a0ac6830e7ea 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From eff62860342ad7680b9dadb951d6879b83b78d53 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Fri, 19 Sep 2014 14:30:48 -0700 Subject: [PATCH 064/114] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/dd5811658293 Author: Kevin Grandon Desc: Merge pull request #24223 from daleharvey/1067573 Bug 1067573 - Add test to ensure default preloaded top sites show. ======== https://hg.mozilla.org/integration/gaia-central/rev/18411172c4ac Author: Dale Harvey Desc: Bug 1067573 - Add test to ensure default preloaded top sites show. r=kgrandon --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 5ca9fcbe5fa1..7836d58bfc56 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "96f2947a5a9145a7697110981d355869b7093dbb", + "revision": "dd5811658293b5369132ecd05d4aaa79dba1ddef", "repo_path": "/integration/gaia-central" } From 1d9c2eb85bf844d88e2656ddb4514f534cdcb2ee Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Fri, 19 Sep 2014 14:36:57 -0700 Subject: [PATCH 065/114] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index fb71468ba6f0..562c27d8a608 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index c6ee2b3a9b8f..b91d28a20fed 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 93d84e957b43..051690fa7e0e 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index d0905d65bc63..004024295ac4 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index c6ee2b3a9b8f..b91d28a20fed 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index 97398db479c0..5a8628177e93 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index d39deeec68e7..89ccc83f485a 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 43e247617297..18c5efcb756d 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 85388cf5846d..61f9d625ce8b 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 61cb1d6b2d79..2ffbf4852648 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index a0ac6830e7ea..feff581d1710 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From 1c124be1f8f52fb3de4f733499d2990a5e52e98f Mon Sep 17 00:00:00 2001 From: Zoran Jovanovic Date: Fri, 19 Sep 2014 14:58:34 -0700 Subject: [PATCH 066/114] Bug 1059202 - CSP and CA verfication for Trusted Hosted Apps r=fabrice,sicking,rlb --- b2g/app/b2g.js | 9 ++ dom/apps/TrustedHostedAppsUtils.jsm | 148 ++++++++++++++++++++++++++++ dom/apps/Webapps.jsm | 51 ++++++++++ dom/apps/moz.build | 1 + modules/libpref/init/all.js | 4 +- 5 files changed, 211 insertions(+), 2 deletions(-) create mode 100644 dom/apps/TrustedHostedAppsUtils.jsm diff --git a/b2g/app/b2g.js b/b2g/app/b2g.js index 94b4a9fdf675..665dcf23a880 100644 --- a/b2g/app/b2g.js +++ b/b2g/app/b2g.js @@ -246,6 +246,15 @@ pref("security.alternate_certificate_error_page", "certerror"); pref("security.warn_viewing_mixed", false); // Warning is disabled. See Bug 616712. +// 2 = strict certificate pinning checks. +// This default preference is more strict than Firefox because B2G +// currently does not have a way to install local root certificates. +// Strict checking is effectively equivalent to non-strict checking as +// long as that is true. If an ability to add local certificates is +// added, there may be a need to change this pref. +pref("security.cert_pinning.enforcement_level", 2); + + // Override some named colors to avoid inverse OS themes pref("ui.-moz-dialog", "#efebe7"); pref("ui.-moz-dialogtext", "#101010"); diff --git a/dom/apps/TrustedHostedAppsUtils.jsm b/dom/apps/TrustedHostedAppsUtils.jsm new file mode 100644 index 000000000000..91642b38aeda --- /dev/null +++ b/dom/apps/TrustedHostedAppsUtils.jsm @@ -0,0 +1,148 @@ +/* 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/. */ + +/* global Components, Services, dump */ + +"use strict"; + +const Cu = Components.utils; +const Cc = Components.classes; +const Ci = Components.interfaces; + +this.EXPORTED_SYMBOLS = ["TrustedHostedAppsUtils"]; + +Cu.import("resource://gre/modules/Services.jsm"); + +#ifdef MOZ_WIDGET_ANDROID +// On Android, define the "debug" function as a binding of the "d" function +// from the AndroidLog module so it gets the "debug" priority and a log tag. +// We always report debug messages on Android because it's unnecessary +// to restrict reporting, per bug 1003469. +let debug = Cu + .import("resource://gre/modules/AndroidLog.jsm", {}) + .AndroidLog.d.bind(null, "TrustedHostedAppsUtils"); +#else +// Elsewhere, report debug messages only if dom.mozApps.debug is set to true. +// The pref is only checked once, on startup, so restart after changing it. +let debug = Services.prefs.getBoolPref("dom.mozApps.debug") ? + aMsg => dump("-*- TrustedHostedAppsUtils.jsm : " + aMsg + "\n") : + () => {}; +#endif + +/** + * Verification functions for Trusted Hosted Apps. + * (Manifest signature verification is in Webapps.jsm as part of + * regular signature verification.) + */ +this.TrustedHostedAppsUtils = { + + /** + * Check if the given host is pinned in the CA pinning database. + */ + isHostPinned: function (aUrl) { + let uri; + try { + uri = Services.io.newURI(aUrl, null, null); + } catch(e) { + debug("Host parsing failed: " + e); + return false; + } + + // TODO: use nsSiteSecurityService.isSecureURI() + if (!uri.host || "https" != uri.scheme) { + return false; + } + + // Check certificate pinning + let siteSecurityService; + try { + siteSecurityService = Cc["@mozilla.org/ssservice;1"] + .getService(Ci.nsISiteSecurityService); + } catch (e) { + debug("nsISiteSecurityService error: " + e); + // unrecoverable error, don't bug the user + throw "CERTDB_ERROR"; + } + + if (siteSecurityService.isSecureHost(Ci.nsISiteSecurityService.HEADER_HPKP, uri.host, 0)) { + debug("\tvalid certificate pinning for host: " + uri.host + "\n"); + return true; + } + + debug("\tHost NOT pinned: " + uri.host + "\n"); + return false; + }, + + /** + * Take a CSP policy string as input and ensure that it contains at + * least the directives that are required ('script-src' and + * 'style-src'). If the CSP policy string is 'undefined' or does + * not contain some of the required csp directives the function will + * return empty list with status set to false. Otherwise a parsed + * list of the unique sources listed from the required csp + * directives is returned. + */ + getCSPWhiteList: function(aCsp) { + let isValid = false; + let whiteList = []; + let requiredDirectives = [ "script-src", "style-src" ]; + + if (aCsp) { + let validDirectives = []; + let directives = aCsp.split(";"); + // TODO: Use nsIContentSecurityPolicy + directives + .map(aDirective => aDirective.trim().split(" ")) + .filter(aList => aList.length > 1) + // we only restrict on requiredDirectives + .filter(aList => (requiredDirectives.indexOf(aList[0]) != -1)) + .forEach(aList => { + // aList[0] contains the directive name. + // aList[1..n] contains sources. + let directiveName = aList.shift() + let sources = aList; + + if ((-1 == validDirectives.indexOf(directiveName))) { + validDirectives.push(directiveName); + } + whiteList.push(...sources.filter( + // 'self' is checked separately during manifest check + aSource => (aSource !="'self'" && whiteList.indexOf(aSource) == -1) + )); + }); + + // Check if all required directives are present. + isValid = requiredDirectives.length === validDirectives.length; + + if (!isValid) { + debug("White list doesn't contain all required directives!"); + whiteList = []; + } + } + + debug("White list contains " + whiteList.length + " hosts"); + return { list: whiteList, valid: isValid }; + }, + + /** + * Verify that the given csp is valid: + * 1. contains required directives "script-src" and "style-src" + * 2. required directives contain only "https" URLs + * 3. domains of the restricted sources exist in the CA pinning database + */ + verifyCSPWhiteList: function(aCsp) { + let domainWhitelist = this.getCSPWhiteList(aCsp); + if (!domainWhitelist.valid) { + debug("TRUSTED_APPLICATION_WHITELIST_PARSING_FAILED"); + return false; + } + + if (!domainWhitelist.list.every(aUrl => this.isHostPinned(aUrl))) { + debug("TRUSTED_APPLICATION_WHITELIST_VALIDATION_FAILED"); + return false; + } + + return true; + } +}; diff --git a/dom/apps/Webapps.jsm b/dom/apps/Webapps.jsm index 6d679edd55b6..b69ad2a5885b 100755 --- a/dom/apps/Webapps.jsm +++ b/dom/apps/Webapps.jsm @@ -64,6 +64,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "NetUtil", XPCOMUtils.defineLazyModuleGetter(this, "ScriptPreloader", "resource://gre/modules/ScriptPreloader.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "TrustedHostedAppsUtils", + "resource://gre/modules/TrustedHostedAppsUtils.jsm"); + #ifdef MOZ_WIDGET_GONK XPCOMUtils.defineLazyGetter(this, "libcutils", function() { Cu.import("resource://gre/modules/systemlibs.js"); @@ -1411,6 +1414,24 @@ this.DOMApplicationRegistry = { return; } + // Check if launching trusted hosted app + if (this.kTrustedHosted == app.kind) { + debug("Launching Trusted Hosted App!"); + // sanity check on manifest host's CA + // (proper CA check with pinning is done by regular networking code) + if (!TrustedHostedAppsUtils.isHostPinned(aManifestURL)) { + debug("Trusted App Host certificate Not OK"); + aOnFailure("TRUSTED_APPLICATION_HOST_CERTIFICATE_INVALID"); + return; + } + + debug("Trusted App Host pins exist"); + if (!TrustedHostedAppsUtils.verifyCSPWhiteList(app.csp)) { + aOnFailure("TRUSTED_APPLICATION_WHITELIST_VALIDATION_FAILED"); + return; + } + } + // We have to clone the app object as nsIDOMApplication objects are // stringified as an empty object. (see bug 830376) let appClone = AppsUtils.cloneAppObject(app); @@ -2295,6 +2316,23 @@ this.DOMApplicationRegistry = { // in which case we don't need to load it. if (app.manifest) { if (checkManifest()) { + if (this.kTrustedHosted == this.appKind(app, app.manifest)) { + // sanity check on manifest host's CA + // (proper CA check with pinning is done by regular networking code) + if (!TrustedHostedAppsUtils.isHostPinned(app.manifestURL)) { + sendError("TRUSTED_APPLICATION_HOST_CERTIFICATE_INVALID"); + return; + } + + // Signature of the manifest should be verified here. + // Bug 1059216. + + if (!TrustedHostedAppsUtils.verifyCSPWhiteList(app.manifest.csp)) { + sendError("TRUSTED_APPLICATION_WHITELIST_VALIDATION_FAILED"); + return; + } + } + installApp(); } return; @@ -2319,6 +2357,19 @@ this.DOMApplicationRegistry = { app.manifest = xhr.response; if (checkManifest()) { app.etag = xhr.getResponseHeader("Etag"); + if (this.kTrustedHosted == this.appKind(app, app.manifest)) { + // checking trusted host for pinning is not needed here, since + // network code will have already done that + + // Signature of the manifest should be verified here. + // Bug 1059216. + + if (!TrustedHostedAppsUtils.verifyCSPWhiteList(app.manifest.csp)) { + sendError("TRUSTED_APPLICATION_WHITELIST_VALIDATION_FAILED"); + return; + } + } + installApp(); } } else { diff --git a/dom/apps/moz.build b/dom/apps/moz.build index 9c6c8c14776c..b86cd7f32279 100644 --- a/dom/apps/moz.build +++ b/dom/apps/moz.build @@ -44,6 +44,7 @@ EXTRA_PP_JS_MODULES += [ 'AppsUtils.jsm', 'OperatorApps.jsm', 'ScriptPreloader.jsm', + 'TrustedHostedAppsUtils.jsm', 'Webapps.jsm', ] diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 1034736a1010..6776da9dee58 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -1729,7 +1729,7 @@ pref("security.mixed_content.block_active_content", false); pref("security.mixed_content.block_display_content", false); // Disable pinning checks by default. -pref("security.cert_pinning.enforcement_level", 0); +pref("security.cert_pinning.enforcement_level", 2); // Modifier key prefs: default to Windows settings, // menu access key = alt, accelerator key = control. @@ -4093,7 +4093,7 @@ pref("dom.mozApps.signed_apps_installable_from", "https://marketplace.firefox.co // Only checked on startup, so restart after changing this pref. // Ignored on Android, where we always report debug messages because it's // unnecessary to restrict reporting, per bug 1003469. -pref("dom.mozApps.debug", false); +pref("dom.mozApps.debug", true); // Minimum delay in milliseconds between network activity notifications (0 means // no notifications). The delay is the same for both download and upload, though From 7b427a5a9ebdd93f39096276b2239e84314b9995 Mon Sep 17 00:00:00 2001 From: Markus Nilsson Date: Fri, 19 Sep 2014 14:58:38 -0700 Subject: [PATCH 067/114] Bug 1059202 - Unit test - CSP and CA verfication for Trusted Hosted Apps r=sicking --- dom/apps/tests/chrome.ini | 1 + dom/apps/tests/test_app_update.html | 19 ++- dom/apps/tests/test_tha_utils.html | 237 ++++++++++++++++++++++++++++ 3 files changed, 249 insertions(+), 8 deletions(-) create mode 100644 dom/apps/tests/test_tha_utils.html diff --git a/dom/apps/tests/chrome.ini b/dom/apps/tests/chrome.ini index 4acdb2d71a56..80312505c4ec 100644 --- a/dom/apps/tests/chrome.ini +++ b/dom/apps/tests/chrome.ini @@ -7,6 +7,7 @@ support-files = [test_apps_service.xul] [test_bug_945152.html] run-if = os == 'linux' +[test_tha_utils.html] [test_manifest_helper.xul] [test_operator_app_install.js] [test_operator_app_install.xul] diff --git a/dom/apps/tests/test_app_update.html b/dom/apps/tests/test_app_update.html index ad9a15d94c88..8a2feb78dab3 100644 --- a/dom/apps/tests/test_app_update.html +++ b/dom/apps/tests/test_app_update.html @@ -196,8 +196,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=826058 yield undefined; info("Uninstalled hosted appcache app"); + /** + * DISABLED FOR NOW UNTIL WE CAN TEST PINNING PROPERLY + */ // Install the trusted app. - setAppVersion(4, continueTest); + /*setAppVersion(4, continueTest); yield undefined; ok(true, "Installing trusted app"); var request = navigator.mozApps.install(gTrustedManifestURL); @@ -215,14 +218,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=826058 } is(app.installState, "installed", "Trusted App is installed"); is(app.manifest.type, "trusted", "App is trusted"); - +*/ // Check the cached app. - checkAppState(app, true, 4, continueTest); - yield undefined; + /*checkAppState(app, true, 4, continueTest); + yield undefined;*/ // Check for updates. The current infrastructure always returns a new appcache // manifest, so there should always be an update. - var lastCheck = app.lastUpdateCheck; + /*var lastCheck = app.lastUpdateCheck; ok(true, "Setting callbacks"); app.ondownloadapplied = function() ok(true, "downloadapplied fired."); app.ondownloadavailable = function() ok(false, "downloadavailable fired"); @@ -231,15 +234,15 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=826058 request.onerror = mozAppsError; request.onsuccess = continueTest; yield undefined; - todo(app.lastUpdateCheck > lastCheck, "lastUpdateCheck updated appropriately"); + todo(app.lastUpdateCheck > lastCheck, "lastUpdateCheck updated appropriately");*/ // Uninstall the app. - request = navigator.mozApps.mgmt.uninstall(app); + /*request = navigator.mozApps.mgmt.uninstall(app); request.onerror = mozAppsError; request.onsuccess = continueTest; yield undefined; - info("Uninstalled trusted app"); + info("Uninstalled trusted app");*/ } function setAppVersion(version, cb) { diff --git a/dom/apps/tests/test_tha_utils.html b/dom/apps/tests/test_tha_utils.html new file mode 100644 index 000000000000..ff17de80665c --- /dev/null +++ b/dom/apps/tests/test_tha_utils.html @@ -0,0 +1,237 @@ + + + + + Test for Trusted Hosted Apps Utils + + + + + + +

      + +
      
      +  
      + + From 66bbd2404849ba08a5f1ed68fca2d33d132b6016 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Fri, 19 Sep 2014 16:50:46 -0700 Subject: [PATCH 068/114] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/9ded69d21786 Author: Wilson Page Desc: Merge pull request #24197 from wilsonpage/1069200 Bug 1069200 - [Camera]Rapidly click take button and switch picture/video mode ======== https://hg.mozilla.org/integration/gaia-central/rev/034c50fd752c Author: Wilson Page Desc: Bug 1069200 - [Camera]Rapidly click take button and switch picture/video mode will cause video recording and picture mode in the same time --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 7836d58bfc56..91f6f5283c0b 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "dd5811658293b5369132ecd05d4aaa79dba1ddef", + "revision": "9ded69d21786aaf37fa95cc3d4104ffc493fa473", "repo_path": "/integration/gaia-central" } From 824567391f6fbb9f40147cdd5acdec401af6282c Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Fri, 19 Sep 2014 16:56:57 -0700 Subject: [PATCH 069/114] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 562c27d8a608..ef59832e5662 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index b91d28a20fed..5dc44ab3ca4a 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 051690fa7e0e..d362b438d170 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 004024295ac4..67b0d74b1289 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index b91d28a20fed..5dc44ab3ca4a 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index 5a8628177e93..cd6077d82678 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 89ccc83f485a..cd11071f159f 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 18c5efcb756d..e8c992935a0e 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 61f9d625ce8b..f74eb6edd31d 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 2ffbf4852648..9697e1ece6ba 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index feff581d1710..c65878a250e0 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From 4f62710412c70d5a406393caf50cdb65ca4a2353 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Fri, 19 Sep 2014 17:35:46 -0700 Subject: [PATCH 070/114] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/4c4ffe7f2c16 Author: Dave Hylands Desc: Merge pull request #24236 from dhylands/bug-1059484-enable-sdcard1 Bug 1059484 - Enable sharing on the external storage card called sdcard1... ======== https://hg.mozilla.org/integration/gaia-central/rev/64a7678f2e6b Author: Dave Hylands Desc: Bug 1059484 - Enable sharing on the external storage card called sdcard1. r=arthur.chen --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 91f6f5283c0b..2216cf91a5c1 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "9ded69d21786aaf37fa95cc3d4104ffc493fa473", + "revision": "4c4ffe7f2c16edb4b612b8e81a3785c8384a33ad", "repo_path": "/integration/gaia-central" } From 96ce199f865a490a1c3a17778a784e3a72f2a93f Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Fri, 19 Sep 2014 17:37:36 -0700 Subject: [PATCH 071/114] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index ef59832e5662..9bc13a6e8850 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 5dc44ab3ca4a..737f2ce9befa 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index d362b438d170..03fd9ac8333f 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 67b0d74b1289..b6aefc2bf092 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 5dc44ab3ca4a..737f2ce9befa 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index cd6077d82678..65a5c53b47a2 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index cd11071f159f..984b8bcad349 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index e8c992935a0e..37d7eb83a65f 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index f74eb6edd31d..688112300712 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 9697e1ece6ba..b28292280d26 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index c65878a250e0..0e2d0f443648 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From bf01715c46a4942622c20ee8870249b47578c52b Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Fri, 19 Sep 2014 18:45:52 -0700 Subject: [PATCH 072/114] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/8edab03e2f1e Author: David Flanagan Desc: Merge pull request #24233 from davidflanagan/bug1070195 Bug 1070195: free canvas memory after creating a video poster image in Camera r=wilsonpage ======== https://hg.mozilla.org/integration/gaia-central/rev/8d9ddbb120af Author: David Flanagan Desc: Bug 1070195: free canvas memory after creating a video poster image in Camera app --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 2216cf91a5c1..7a7db044ce60 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "4c4ffe7f2c16edb4b612b8e81a3785c8384a33ad", + "revision": "8edab03e2f1e8ccb50854cce61a1612b2dc300be", "repo_path": "/integration/gaia-central" } From 3154b29d94815f7568eaa8ddc9055813202faa3b Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Fri, 19 Sep 2014 18:57:04 -0700 Subject: [PATCH 073/114] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 9bc13a6e8850..81917f5fb5ad 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 737f2ce9befa..185414cfe2ec 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 03fd9ac8333f..b87d3d43d9c5 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index b6aefc2bf092..c2d39cb2a994 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 737f2ce9befa..185414cfe2ec 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index 65a5c53b47a2..bf76d77e177e 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 984b8bcad349..c4d77d76abe7 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 37d7eb83a65f..fcd1b6930bb2 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 688112300712..c2185236f249 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index b28292280d26..748964210057 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 0e2d0f443648..b4beaddb66ae 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From e160a6a6da2983baa93cdfb0661ded7a93a90af9 Mon Sep 17 00:00:00 2001 From: Vlatko Markovic Date: Fri, 19 Sep 2014 20:13:47 -0700 Subject: [PATCH 074/114] Bug 1059204 - Prepare verification code for reuse. r=rlb --- security/apps/AppSignatureVerification.cpp | 85 ++++++++++++++-------- 1 file changed, 55 insertions(+), 30 deletions(-) diff --git a/security/apps/AppSignatureVerification.cpp b/security/apps/AppSignatureVerification.cpp index 86ea62945b43..c77ceb623964 100644 --- a/security/apps/AppSignatureVerification.cpp +++ b/security/apps/AppSignatureVerification.cpp @@ -44,6 +44,59 @@ extern PRLogModuleInfo* gPIPNSSLog; namespace { +// Reads a maximum of 1MB from a stream into the supplied buffer. +// The reason for the 1MB limit is because this function is used to read +// signature-related files and we want to avoid OOM. The uncompressed length of +// an entry can be hundreds of times larger than the compressed version, +// especially if someone has specifically crafted the entry to cause OOM or to +// consume massive amounts of disk space. +// +// @param stream The input stream to read from. +// @param buf The buffer that we read the stream into, which must have +// already been allocated. +nsresult +ReadStream(const nsCOMPtr& stream, /*out*/ SECItem& buf) +{ + // The size returned by Available() might be inaccurate so we need + // to check that Available() matches up with the actual length of + // the file. + uint64_t length; + nsresult rv = stream->Available(&length); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + // Cap the maximum accepted size of signature-related files at 1MB (which is + // still crazily huge) to avoid OOM. The uncompressed length of an entry can be + // hundreds of times larger than the compressed version, especially if + // someone has speifically crafted the entry to cause OOM or to consume + // massive amounts of disk space. + static const uint32_t MAX_LENGTH = 1024 * 1024; + if (length > MAX_LENGTH) { + return NS_ERROR_FILE_TOO_BIG; + } + + // With bug 164695 in mind we +1 to leave room for null-terminating + // the buffer. + SECITEM_AllocItem(buf, static_cast(length + 1)); + + // buf.len == length + 1. We attempt to read length + 1 bytes + // instead of length, so that we can check whether the metadata for + // the entry is incorrect. + uint32_t bytesRead; + rv = stream->Read(char_ptr_cast(buf.data), buf.len, &bytesRead); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + if (bytesRead != length) { + return NS_ERROR_FILE_CORRUPTED; + } + + buf.data[buf.len - 1] = 0; // null-terminate + + return NS_OK; +} + // Finds exactly one (signature metadata) entry that matches the given // search pattern, and then load it. Fails if there are no matches or if // there is more than one match. If bugDigest is not null then on success @@ -82,39 +135,11 @@ FindAndLoadOneEntry(nsIZipReader * zip, rv = zip->GetInputStream(filename, getter_AddRefs(stream)); NS_ENSURE_SUCCESS(rv, rv); - // The size returned by Available() might be inaccurate so we need to check - // that Available() matches up with the actual length of the file. - uint64_t len64; - rv = stream->Available(&len64); - NS_ENSURE_SUCCESS(rv, rv); - - - // Cap the maximum accepted size of signature-related files at 1MB (which is - // still crazily huge) to avoid OOM. The uncompressed length of an entry can be - // hundreds of times larger than the compressed version, especially if - // someone has speifically crafted the entry to cause OOM or to consume - // massive amounts of disk space. - // - // Also, keep in mind bug 164695 and that we must leave room for - // null-terminating the buffer. - static const uint32_t MAX_LENGTH = 1024 * 1024; - static_assert(MAX_LENGTH < UINT32_MAX, "MAX_LENGTH < UINT32_MAX"); - NS_ENSURE_TRUE(len64 < MAX_LENGTH, NS_ERROR_FILE_CORRUPTED); - NS_ENSURE_TRUE(len64 < UINT32_MAX, NS_ERROR_FILE_CORRUPTED); // bug 164695 - SECITEM_AllocItem(buf, static_cast(len64 + 1)); - - // buf.len == len64 + 1. We attempt to read len64 + 1 bytes instead of len64, - // so that we can check whether the metadata in the ZIP for the entry is - // incorrect. - uint32_t bytesRead; - rv = stream->Read(char_ptr_cast(buf.data), buf.len, &bytesRead); - NS_ENSURE_SUCCESS(rv, rv); - if (bytesRead != len64) { + rv = ReadStream(stream, buf); + if (NS_WARN_IF(NS_FAILED(rv))) { return NS_ERROR_SIGNED_JAR_ENTRY_INVALID; } - buf.data[buf.len - 1] = 0; // null-terminate - if (bufDigest) { rv = bufDigest->DigestBuf(SEC_OID_SHA1, buf.data, buf.len - 1); NS_ENSURE_SUCCESS(rv, rv); From ce9fead565039ea5cc6aec22a190711def44a493 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Sat, 20 Sep 2014 01:50:48 -0700 Subject: [PATCH 075/114] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ======== https://hg.mozilla.org/integration/gaia-central/rev/995979ab5d82 Author: Sam Foster Desc: Merge pull request #24127 from ddrmanxbxfr/bug_1062829 Bug 1062829 - Converted Json methods from XHR to LazyLoader in FTU APP. r=sfoster ======== https://hg.mozilla.org/integration/gaia-central/rev/423b744a533e Author: Mathieu Rhéaume Desc: Bug 1062829 - Converted Json methods from XHR to LazyLoader in the FTU APP --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 7a7db044ce60..6726efc070e9 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "8edab03e2f1e8ccb50854cce61a1612b2dc300be", + "revision": "995979ab5d825dacc4e3dba6338d45a4f54040a3", "repo_path": "/integration/gaia-central" } From fd7bd9249d62ea3c038dbfadc4be1f0c62f2ad67 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Sat, 20 Sep 2014 01:52:34 -0700 Subject: [PATCH 076/114] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 81917f5fb5ad..f453190abed0 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 185414cfe2ec..f96ae9859876 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index b87d3d43d9c5..e1dba0ad4f15 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index c2d39cb2a994..61e06cf97c14 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 185414cfe2ec..f96ae9859876 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index bf76d77e177e..434499138a45 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index c4d77d76abe7..67d1ec809247 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index fcd1b6930bb2..7777bc338764 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index c2185236f249..4de262e3b2c9 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 748964210057..72d59cae324a 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index b4beaddb66ae..a2372635d3fc 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From e7c4d3f0ab968521c09da65263aa8b6cd4d64dd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabrice=20Desr=C3=A9?= Date: Sat, 20 Sep 2014 13:47:52 -0700 Subject: [PATCH 077/114] Bug 1059202 - Followup to revert unwanted changes in all.js r=me --- modules/libpref/init/all.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 6776da9dee58..1034736a1010 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -1729,7 +1729,7 @@ pref("security.mixed_content.block_active_content", false); pref("security.mixed_content.block_display_content", false); // Disable pinning checks by default. -pref("security.cert_pinning.enforcement_level", 2); +pref("security.cert_pinning.enforcement_level", 0); // Modifier key prefs: default to Windows settings, // menu access key = alt, accelerator key = control. @@ -4093,7 +4093,7 @@ pref("dom.mozApps.signed_apps_installable_from", "https://marketplace.firefox.co // Only checked on startup, so restart after changing this pref. // Ignored on Android, where we always report debug messages because it's // unnecessary to restrict reporting, per bug 1003469. -pref("dom.mozApps.debug", true); +pref("dom.mozApps.debug", false); // Minimum delay in milliseconds between network activity notifications (0 means // no notifications). The delay is the same for both download and upload, though From a3dc3859a2c7d26403f857a2e6002ee784fff079 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Sat, 20 Sep 2014 14:37:30 -0700 Subject: [PATCH 078/114] Bumping manifests a=b2g-bump --- b2g/config/flame-kk/sources.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index 434499138a45..f9a8c07aa239 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -154,5 +154,5 @@ - + From 13a288395a812f2b38d497920af2cd63f609018b Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Sat, 20 Sep 2014 15:12:30 -0700 Subject: [PATCH 079/114] Bumping manifests a=b2g-bump --- b2g/config/flame-kk/sources.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index f9a8c07aa239..c6638cf753d4 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -135,7 +135,7 @@ - + From 2b9342288ec341f0028ebe64ef8124e64f476508 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Sat, 20 Sep 2014 15:17:40 -0700 Subject: [PATCH 080/114] Bumping manifests a=b2g-bump --- b2g/config/flame-kk/sources.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index c6638cf753d4..e6964f35f652 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -138,7 +138,7 @@ - + From 08f8a1ef731e9464f4c3712318e3e4da2a58ab16 Mon Sep 17 00:00:00 2001 From: Vicamo Yang Date: Sun, 21 Sep 2014 15:24:42 +0800 Subject: [PATCH 081/114] Bug 1063304 - 1/3: rename MobileConnectionGonkService.js to MobileConnectionService.js. r=echen --HG-- rename : dom/mobileconnection/gonk/MobileConnectionGonkService.js => dom/mobileconnection/gonk/MobileConnectionService.js rename : dom/mobileconnection/gonk/MobileConnectionGonkService.manifest => dom/mobileconnection/gonk/MobileConnectionService.manifest rename : dom/mobileconnection/interfaces/nsIMobileConnectionGonkService.idl => dom/mobileconnection/gonk/nsIGonkMobileConnectionService.idl --- b2g/installer/package-manifest.in | 4 +-- .../MobileConnectionCallback.h | 2 +- .../gonk/MobileConnectionGonkService.manifest | 2 -- ...kService.js => MobileConnectionService.js} | 32 +++++++++---------- .../gonk/MobileConnectionService.manifest | 2 ++ .../nsIGonkMobileConnectionService.idl} | 8 ++--- dom/mobileconnection/interfaces/moz.build | 21 ------------ dom/mobileconnection/moz.build | 20 +++++++++--- dom/system/gonk/RadioInterfaceLayer.js | 6 ++-- layout/build/nsLayoutModule.cpp | 4 +-- 10 files changed, 46 insertions(+), 55 deletions(-) delete mode 100644 dom/mobileconnection/gonk/MobileConnectionGonkService.manifest rename dom/mobileconnection/gonk/{MobileConnectionGonkService.js => MobileConnectionService.js} (98%) create mode 100644 dom/mobileconnection/gonk/MobileConnectionService.manifest rename dom/mobileconnection/{interfaces/nsIMobileConnectionGonkService.idl => gonk/nsIGonkMobileConnectionService.idl} (87%) delete mode 100644 dom/mobileconnection/interfaces/moz.build diff --git a/b2g/installer/package-manifest.in b/b2g/installer/package-manifest.in index 16e2cb3cdea3..c9b9c49dd0c9 100644 --- a/b2g/installer/package-manifest.in +++ b/b2g/installer/package-manifest.in @@ -438,6 +438,8 @@ #if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL) @BINPATH@/components/MmsService.js @BINPATH@/components/MmsService.manifest +@BINPATH@/components/MobileConnectionService.js +@BINPATH@/components/MobileConnectionService.manifest @BINPATH@/components/MobileMessageDatabaseService.js @BINPATH@/components/MobileMessageDatabaseService.manifest @BINPATH@/components/RadioInterfaceLayer.js @@ -445,8 +447,6 @@ @BINPATH@/components/RILContentHelper.js @BINPATH@/components/TelephonyService.js @BINPATH@/components/TelephonyService.manifest -@BINPATH@/components/MobileConnectionGonkService.js -@BINPATH@/components/MobileConnectionGonkService.manifest #endif // MOZ_WIDGET_GONK && MOZ_B2G_RIL #ifndef MOZ_WIDGET_GONK diff --git a/dom/mobileconnection/MobileConnectionCallback.h b/dom/mobileconnection/MobileConnectionCallback.h index aa63dd306df8..6f98f24bb878 100644 --- a/dom/mobileconnection/MobileConnectionCallback.h +++ b/dom/mobileconnection/MobileConnectionCallback.h @@ -20,7 +20,7 @@ namespace dom { * The modules hold the reference of MobileConnectionCallback in OOP mode and * non-OOP mode are different. * - OOP mode: MobileConnectionRequestChild - * - non-OOP mode: MobileConnectionGonkService + * - non-OOP mode: MobileConnectionService * The reference should be released after Notify*Success/Error is called. */ class MobileConnectionCallback MOZ_FINAL : public nsIMobileConnectionCallback diff --git a/dom/mobileconnection/gonk/MobileConnectionGonkService.manifest b/dom/mobileconnection/gonk/MobileConnectionGonkService.manifest deleted file mode 100644 index 927226e4d714..000000000000 --- a/dom/mobileconnection/gonk/MobileConnectionGonkService.manifest +++ /dev/null @@ -1,2 +0,0 @@ -component {05e20430-fe65-4984-8df9-a6a504b24a91} MobileConnectionGonkService.js -contract @mozilla.org/mobileconnection/mobileconnectiongonkservice;1 {05e20430-fe65-4984-8df9-a6a504b24a91} diff --git a/dom/mobileconnection/gonk/MobileConnectionGonkService.js b/dom/mobileconnection/gonk/MobileConnectionService.js similarity index 98% rename from dom/mobileconnection/gonk/MobileConnectionGonkService.js rename to dom/mobileconnection/gonk/MobileConnectionService.js index 7b59bdb8f341..404552312db5 100644 --- a/dom/mobileconnection/gonk/MobileConnectionGonkService.js +++ b/dom/mobileconnection/gonk/MobileConnectionService.js @@ -14,11 +14,11 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm"); var RIL = {}; Cu.import("resource://gre/modules/ril_consts.js", RIL); -const MOBILECONNECTIONGONKSERVICE_CONTRACTID = - "@mozilla.org/mobileconnection/mobileconnectiongonkservice;1"; +const GONK_MOBILECONNECTIONSERVICE_CONTRACTID = + "@mozilla.org/mobileconnection/gonkmobileconnectionservice;1"; -const MOBILECONNECTIONGONKSERVICE_CID = - Components.ID("{05e20430-fe65-4984-8df9-a6a504b24a91}"); +const GONK_MOBILECONNECTIONSERVICE_CID = + Components.ID("{0c9c1a96-2c72-4c55-9e27-0ca73eb16f63}"); const MOBILENETWORKINFO_CID = Components.ID("{a6c8416c-09b4-46d1-bf29-6520d677d085}"); const MOBILECELLINFO_CID = @@ -44,7 +44,7 @@ XPCOMUtils.defineLazyServiceGetter(this, "gRadioInterfaceLayer", let DEBUG = RIL.DEBUG_RIL; function debug(s) { - dump("MobileConnectionGonkService: " + s + "\n"); + dump("MobileConnectionService: " + s + "\n"); } function MobileNetworkInfo() { @@ -293,7 +293,7 @@ MobileConnectionProvider.prototype = { */ _checkRoamingBetweenOperators: function(aNetworkInfo) { // TODO: Bug 864489 - B2G RIL: use ipdl as IPC in MozIccManager - // Should get iccInfo from IccGonkProvider. + // Should get iccInfo from GonkIccProvider. let iccInfo = this._radioInterface.rilContext.iccInfo; let operator = aNetworkInfo.network; let state = aNetworkInfo.state; @@ -950,7 +950,7 @@ MobileConnectionProvider.prototype = { }, }; -function MobileConnectionGonkService() { +function MobileConnectionService() { this._providers = []; let numClients = gRadioInterfaceLayer.numRadioInterfaces; @@ -966,15 +966,15 @@ function MobileConnectionGonkService() { debug("init complete"); } -MobileConnectionGonkService.prototype = { - classID: MOBILECONNECTIONGONKSERVICE_CID, - classInfo: XPCOMUtils.generateCI({classID: MOBILECONNECTIONGONKSERVICE_CID, - contractID: MOBILECONNECTIONGONKSERVICE_CONTRACTID, - classDescription: "MobileConnectionGonkService", - interfaces: [Ci.nsIMobileConnectionGonkService, +MobileConnectionService.prototype = { + classID: GONK_MOBILECONNECTIONSERVICE_CID, + classInfo: XPCOMUtils.generateCI({classID: GONK_MOBILECONNECTIONSERVICE_CID, + contractID: GONK_MOBILECONNECTIONSERVICE_CONTRACTID, + classDescription: "MobileConnectionService", + interfaces: [Ci.nsIGonkMobileConnectionService, Ci.nsIMobileConnectionService], flags: Ci.nsIClassInfo.SINGLETON}), - QueryInterface: XPCOMUtils.generateQI([Ci.nsIMobileConnectionGonkService, + QueryInterface: XPCOMUtils.generateQI([Ci.nsIGonkMobileConnectionService, Ci.nsIMobileConnectionService, Ci.nsIObserver]), @@ -1286,7 +1286,7 @@ MobileConnectionGonkService.prototype = { }, /** - * nsIMobileConnectionGonkService interface. + * nsIGonkMobileConnectionService interface. */ notifyVoiceInfoChanged: function(aClientId, aVoiceInfo) { if (DEBUG) { @@ -1560,4 +1560,4 @@ MobileConnectionGonkService.prototype = { } }; -this.NSGetFactory = XPCOMUtils.generateNSGetFactory([MobileConnectionGonkService]); +this.NSGetFactory = XPCOMUtils.generateNSGetFactory([MobileConnectionService]); diff --git a/dom/mobileconnection/gonk/MobileConnectionService.manifest b/dom/mobileconnection/gonk/MobileConnectionService.manifest new file mode 100644 index 000000000000..5838900da94b --- /dev/null +++ b/dom/mobileconnection/gonk/MobileConnectionService.manifest @@ -0,0 +1,2 @@ +component {0c9c1a96-2c72-4c55-9e27-0ca73eb16f63} MobileConnectionService.js +contract @mozilla.org/mobileconnection/gonkmobileconnectionservice;1 {0c9c1a96-2c72-4c55-9e27-0ca73eb16f63} diff --git a/dom/mobileconnection/interfaces/nsIMobileConnectionGonkService.idl b/dom/mobileconnection/gonk/nsIGonkMobileConnectionService.idl similarity index 87% rename from dom/mobileconnection/interfaces/nsIMobileConnectionGonkService.idl rename to dom/mobileconnection/gonk/nsIGonkMobileConnectionService.idl index c0690fd9f9f5..d5b393c1b88b 100644 --- a/dom/mobileconnection/interfaces/nsIMobileConnectionGonkService.idl +++ b/dom/mobileconnection/gonk/nsIGonkMobileConnectionService.idl @@ -5,12 +5,12 @@ #include "nsIMobileConnectionService.idl" %{C++ -#define NS_MOBILECONNECTION_GONK_SERVICE_CONTRACTID \ - "@mozilla.org/mobileconnection/mobileconnectiongonkservice;1" +#define GONK_MOBILECONNECTION_SERVICE_CONTRACTID \ + "@mozilla.org/mobileconnection/gonkmobileconnectionservice;1" %} -[scriptable, uuid(c5baceda-247a-4018-855d-ad5b00f2e4e2)] -interface nsIMobileConnectionGonkService : nsIMobileConnectionService +[scriptable, uuid(e54fa0a4-d357-48ef-9a1e-ffc9705b44b1)] +interface nsIGonkMobileConnectionService : nsIMobileConnectionService { void notifyNetworkInfoChanged(in unsigned long clientId, in jsval networkInfo); diff --git a/dom/mobileconnection/interfaces/moz.build b/dom/mobileconnection/interfaces/moz.build deleted file mode 100644 index 9049a7c481ba..000000000000 --- a/dom/mobileconnection/interfaces/moz.build +++ /dev/null @@ -1,21 +0,0 @@ -# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: -# 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/. - -XPIDL_SOURCES += [ - 'nsICellInfo.idl', - 'nsIMobileCellInfo.idl', - 'nsIMobileConnectionInfo.idl', - 'nsIMobileConnectionService.idl', - 'nsIMobileNetworkInfo.idl', - 'nsINeighboringCellInfo.idl', -] - -if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['MOZ_B2G_RIL']: - XPIDL_SOURCES += [ - 'nsIMobileConnectionGonkService.idl', - ] - -XPIDL_MODULE = 'dom_mobileconnection' diff --git a/dom/mobileconnection/moz.build b/dom/mobileconnection/moz.build index 17f102a67bbb..9a68c5ad0dc9 100644 --- a/dom/mobileconnection/moz.build +++ b/dom/mobileconnection/moz.build @@ -4,8 +4,6 @@ # 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/. -DIRS += ['interfaces'] - MOCHITEST_MANIFESTS += ['tests/mochitest/mochitest.ini'] EXPORTS.mozilla.dom += [ @@ -25,6 +23,15 @@ EXPORTS.mozilla.dom.mobileconnection += [ 'ipc/MobileConnectionParent.h', ] +XPIDL_SOURCES += [ + 'interfaces/nsICellInfo.idl', + 'interfaces/nsIMobileCellInfo.idl', + 'interfaces/nsIMobileConnectionInfo.idl', + 'interfaces/nsIMobileConnectionService.idl', + 'interfaces/nsIMobileNetworkInfo.idl', + 'interfaces/nsINeighboringCellInfo.idl', +] + SOURCES += [ 'DOMMMIError.cpp', 'ipc/MobileConnectionChild.cpp', @@ -45,9 +52,12 @@ IPDL_SOURCES += [ ] if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['MOZ_B2G_RIL']: + XPIDL_SOURCES += [ + 'gonk/nsIGonkMobileConnectionService.idl', + ] EXTRA_COMPONENTS += [ - 'gonk/MobileConnectionGonkService.js', - 'gonk/MobileConnectionGonkService.manifest', + 'gonk/MobileConnectionService.js', + 'gonk/MobileConnectionService.manifest', ] FAIL_ON_WARNINGS = True @@ -55,3 +65,5 @@ FAIL_ON_WARNINGS = True include('/ipc/chromium/chromium-config.mozbuild') FINAL_LIBRARY = 'xul' + +XPIDL_MODULE = 'dom_mobileconnection' diff --git a/dom/system/gonk/RadioInterfaceLayer.js b/dom/system/gonk/RadioInterfaceLayer.js index ae68cb14024d..f3fa35c20b5c 100644 --- a/dom/system/gonk/RadioInterfaceLayer.js +++ b/dom/system/gonk/RadioInterfaceLayer.js @@ -201,7 +201,7 @@ XPCOMUtils.defineLazyServiceGetter(this, "gTelephonyService", XPCOMUtils.defineLazyServiceGetter(this, "gMobileConnectionService", "@mozilla.org/mobileconnection/mobileconnectionservice;1", - "nsIMobileConnectionGonkService"); + "nsIGonkMobileConnectionService"); XPCOMUtils.defineLazyGetter(this, "WAP", function() { let wap = {}; @@ -3002,8 +3002,8 @@ RadioInterface.prototype = { this.clientId, message.iccid ? message : null); - // In bug 864489, icc related code will be move to IccGonkProvider, we may - // need a better way to notify icc change to MobileConnectionGonkProvider. + // In bug 864489, icc related code will be move to gonk IccProvider, we may + // need a better way to notify icc change to MobileConnectionService. gMobileConnectionService.notifyIccChanged(this.clientId, message.iccid || null); diff --git a/layout/build/nsLayoutModule.cpp b/layout/build/nsLayoutModule.cpp index 195bf2a73506..27b46de6a314 100644 --- a/layout/build/nsLayoutModule.cpp +++ b/layout/build/nsLayoutModule.cpp @@ -130,7 +130,7 @@ using mozilla::system::nsVolumeService; #include "mozilla/dom/mobileconnection/MobileConnectionIPCService.h" using mozilla::dom::mobileconnection::MobileConnectionIPCService; #ifdef MOZ_WIDGET_GONK -#include "nsIMobileConnectionGonkService.h" +#include "nsIGonkMobileConnectionService.h" #endif #endif @@ -950,7 +950,7 @@ nsIMobileConnectionServiceConstructor(nsISupports *aOuter, REFNSIID aIID, service = MobileConnectionIPCService::GetSingleton(); } else { #ifdef MOZ_WIDGET_GONK - service = do_CreateInstance(NS_MOBILECONNECTION_GONK_SERVICE_CONTRACTID); + service = do_CreateInstance(GONK_MOBILECONNECTION_SERVICE_CONTRACTID); #endif } From b53afc7e4963e8d75697de24c811cdc9d6991333 Mon Sep 17 00:00:00 2001 From: Vicamo Yang Date: Sun, 21 Sep 2014 15:24:42 +0800 Subject: [PATCH 082/114] Bug 1063304 - 2/3: export header files in right namespace. r=echen --- dom/ipc/ContentChild.cpp | 7 ++----- dom/ipc/ContentParent.cpp | 8 +++----- dom/mobileconnection/DOMMMIError.cpp | 2 +- dom/mobileconnection/MobileCellInfo.cpp | 2 +- dom/mobileconnection/MobileConnection.cpp | 3 ++- dom/mobileconnection/MobileConnection.h | 4 ++-- dom/mobileconnection/MobileConnectionArray.cpp | 2 +- dom/mobileconnection/MobileConnectionArray.h | 2 +- dom/mobileconnection/MobileConnectionCallback.cpp | 10 ++++++++-- dom/mobileconnection/MobileConnectionCallback.h | 14 ++++++++------ dom/mobileconnection/MobileConnectionInfo.cpp | 2 +- dom/mobileconnection/MobileConnectionInfo.h | 4 ++-- dom/mobileconnection/MobileNetworkInfo.cpp | 2 +- dom/mobileconnection/ipc/MobileConnectionChild.cpp | 2 +- dom/mobileconnection/ipc/MobileConnectionChild.h | 7 ++++--- .../ipc/MobileConnectionIPCSerializer.h | 8 ++++---- .../ipc/MobileConnectionIPCService.h | 8 ++++---- .../ipc/MobileConnectionParent.cpp | 4 ++-- dom/mobileconnection/ipc/MobileConnectionParent.h | 4 ++-- dom/mobileconnection/ipc/PMobileConnection.ipdl | 4 +++- .../ipc/PMobileConnectionRequest.ipdl | 2 ++ .../ipc/PMobileConnectionTypes.ipdlh | 10 ++++++---- dom/mobileconnection/moz.build | 3 +-- 23 files changed, 62 insertions(+), 52 deletions(-) diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index acabb6697e56..15a270b2b985 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -127,6 +127,7 @@ #endif #include "mozilla/dom/indexedDB/PIndexedDBChild.h" +#include "mozilla/dom/mobileconnection/MobileConnectionChild.h" #include "mozilla/dom/mobilemessage/SmsChild.h" #include "mozilla/dom/devicestorage/DeviceStorageRequestChild.h" #include "mozilla/dom/PFileSystemRequestChild.h" @@ -155,17 +156,13 @@ #include "mozilla/net/NeckoMessageUtils.h" #include "mozilla/RemoteSpellCheckEngineChild.h" -#ifdef MOZ_B2G_RIL -#include "mozilla/dom/mobileconnection/MobileConnectionChild.h" -using namespace mozilla::dom::mobileconnection; -#endif - using namespace base; using namespace mozilla; using namespace mozilla::docshell; using namespace mozilla::dom::bluetooth; using namespace mozilla::dom::devicestorage; using namespace mozilla::dom::ipc; +using namespace mozilla::dom::mobileconnection; using namespace mozilla::dom::mobilemessage; using namespace mozilla::dom::indexedDB; using namespace mozilla::dom::telephony; diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 0b340e648c21..db6637ffa3dd 100755 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -49,9 +49,10 @@ #include "mozilla/dom/FileSystemRequestParent.h" #include "mozilla/dom/GeolocationBinding.h" #include "mozilla/dom/FileDescriptorSetParent.h" +#include "mozilla/dom/mobileconnection/MobileConnectionParent.h" +#include "mozilla/dom/mobilemessage/SmsParent.h" #include "mozilla/dom/telephony/TelephonyParent.h" #include "mozilla/dom/time/DateCacheCleaner.h" -#include "SmsParent.h" #include "mozilla/hal_sandbox/PHalParent.h" #include "mozilla/ipc/BackgroundChild.h" #include "mozilla/ipc/BackgroundParent.h" @@ -178,10 +179,6 @@ using namespace mozilla::system; #include "nsIIPCBackgroundChildCreateCallback.h" #endif -#ifdef MOZ_B2G_RIL -#include "mozilla/dom/mobileconnection/MobileConnectionParent.h" -using namespace mozilla::dom::mobileconnection; -#endif #if defined(MOZ_CONTENT_SANDBOX) && defined(XP_LINUX) #include "mozilla/Sandbox.h" @@ -196,6 +193,7 @@ using namespace mozilla::dom::bluetooth; using namespace mozilla::dom::devicestorage; using namespace mozilla::dom::indexedDB; using namespace mozilla::dom::power; +using namespace mozilla::dom::mobileconnection; using namespace mozilla::dom::mobilemessage; using namespace mozilla::dom::telephony; using namespace mozilla::hal; diff --git a/dom/mobileconnection/DOMMMIError.cpp b/dom/mobileconnection/DOMMMIError.cpp index 268945cc3617..d37d876d8177 100644 --- a/dom/mobileconnection/DOMMMIError.cpp +++ b/dom/mobileconnection/DOMMMIError.cpp @@ -4,7 +4,7 @@ * 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/. */ -#include "DOMMMIError.h" +#include "mozilla/dom/DOMMMIError.h" #include "mozilla/dom/DOMMMIErrorBinding.h" using namespace mozilla::dom; diff --git a/dom/mobileconnection/MobileCellInfo.cpp b/dom/mobileconnection/MobileCellInfo.cpp index 70faa222a0f1..589652a14bc3 100644 --- a/dom/mobileconnection/MobileCellInfo.cpp +++ b/dom/mobileconnection/MobileCellInfo.cpp @@ -4,7 +4,7 @@ * 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/. */ -#include "MobileCellInfo.h" +#include "mozilla/dom/MobileCellInfo.h" #include "mozilla/dom/MozMobileCellInfoBinding.h" using namespace mozilla::dom; diff --git a/dom/mobileconnection/MobileConnection.cpp b/dom/mobileconnection/MobileConnection.cpp index b23c7ae5a294..eb463aa3333d 100644 --- a/dom/mobileconnection/MobileConnection.cpp +++ b/dom/mobileconnection/MobileConnection.cpp @@ -2,7 +2,7 @@ * 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/. */ -#include "MobileConnection.h" +#include "mozilla/dom/MobileConnection.h" #include "MobileConnectionCallback.h" #include "mozilla/dom/CFStateChangeEvent.h" @@ -42,6 +42,7 @@ using mozilla::ErrorResult; using namespace mozilla::dom; +using namespace mozilla::dom::mobileconnection; class MobileConnection::Listener MOZ_FINAL : public nsIMobileConnectionListener { diff --git a/dom/mobileconnection/MobileConnection.h b/dom/mobileconnection/MobileConnection.h index 71a51e0b938f..3fbce851798e 100644 --- a/dom/mobileconnection/MobileConnection.h +++ b/dom/mobileconnection/MobileConnection.h @@ -5,10 +5,10 @@ #ifndef mozilla_dom_MobileConnection_h #define mozilla_dom_MobileConnection_h -#include "MobileConnectionInfo.h" -#include "MobileNetworkInfo.h" #include "mozilla/DOMEventTargetHelper.h" #include "mozilla/dom/DOMRequest.h" +#include "mozilla/dom/MobileConnectionInfo.h" +#include "mozilla/dom/MobileNetworkInfo.h" #include "mozilla/dom/MozMobileConnectionBinding.h" #include "nsCycleCollectionParticipant.h" #include "nsIMobileConnectionService.h" diff --git a/dom/mobileconnection/MobileConnectionArray.cpp b/dom/mobileconnection/MobileConnectionArray.cpp index 4e62d8505969..2a1e9e5f6e0b 100644 --- a/dom/mobileconnection/MobileConnectionArray.cpp +++ b/dom/mobileconnection/MobileConnectionArray.cpp @@ -4,7 +4,7 @@ * 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/. */ -#include "MobileConnectionArray.h" +#include "mozilla/dom/MobileConnectionArray.h" #include "mozilla/dom/MozMobileConnectionArrayBinding.h" #include "mozilla/Preferences.h" diff --git a/dom/mobileconnection/MobileConnectionArray.h b/dom/mobileconnection/MobileConnectionArray.h index 34b743ca0f85..aaaa6c4ff0ad 100644 --- a/dom/mobileconnection/MobileConnectionArray.h +++ b/dom/mobileconnection/MobileConnectionArray.h @@ -7,8 +7,8 @@ #ifndef mozilla_dom_network_MobileConnectionArray_h__ #define mozilla_dom_network_MobileConnectionArray_h__ +#include "mozilla/dom/MobileConnection.h" #include "nsWrapperCache.h" -#include "MobileConnection.h" namespace mozilla { namespace dom { diff --git a/dom/mobileconnection/MobileConnectionCallback.cpp b/dom/mobileconnection/MobileConnectionCallback.cpp index bdebdbadcd42..9370b125c06c 100644 --- a/dom/mobileconnection/MobileConnectionCallback.cpp +++ b/dom/mobileconnection/MobileConnectionCallback.cpp @@ -4,14 +4,16 @@ #include "MobileConnectionCallback.h" -#include "DOMMMIError.h" +#include "mozilla/dom/DOMMMIError.h" #include "mozilla/dom/MobileNetworkInfo.h" #include "mozilla/dom/MozMobileConnectionBinding.h" #include "mozilla/dom/ToJSValue.h" #include "nsJSUtils.h" #include "nsServiceManagerUtils.h" -using namespace mozilla::dom; +namespace mozilla { +namespace dom { +namespace mobileconnection { NS_IMPL_ISUPPORTS(MobileConnectionCallback, nsIMobileConnectionCallback) @@ -317,3 +319,7 @@ MobileConnectionCallback::NotifyError(const nsAString& aName, return NS_ERROR_FAILURE; } + +} // namespace mobileconnection +} // namespace dom +} // namespace mozilla diff --git a/dom/mobileconnection/MobileConnectionCallback.h b/dom/mobileconnection/MobileConnectionCallback.h index 6f98f24bb878..af6bc276b1e1 100644 --- a/dom/mobileconnection/MobileConnectionCallback.h +++ b/dom/mobileconnection/MobileConnectionCallback.h @@ -2,16 +2,17 @@ * 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/. */ -#ifndef mozilla_dom_MobileConnectionCallback_h -#define mozilla_dom_MobileConnectionCallback_h +#ifndef mozilla_dom_mobileconnection_MobileConnectionCallback_h +#define mozilla_dom_mobileconnection_MobileConnectionCallback_h #include "mozilla/dom/DOMRequest.h" -#include "mozilla/dom/MobileConnectionIPCSerializer.h" +#include "mozilla/dom/mobileconnection/MobileConnectionIPCSerializer.h" #include "nsCOMPtr.h" #include "nsIMobileConnectionService.h" namespace mozilla { namespace dom { +namespace mobileconnection { /** * A callback object for handling asynchronous request/response. This object is @@ -72,7 +73,8 @@ private: nsRefPtr mRequest; }; -} // name space dom -} // name space mozilla +} // namespace mobileconnection +} // namespace dom +} // namespace mozilla -#endif // mozilla_dom_MobileConnectionCallback_h +#endif // mozilla_dom_mobileconnection_MobileConnectionCallback_h diff --git a/dom/mobileconnection/MobileConnectionInfo.cpp b/dom/mobileconnection/MobileConnectionInfo.cpp index 030486d38493..62652548954d 100644 --- a/dom/mobileconnection/MobileConnectionInfo.cpp +++ b/dom/mobileconnection/MobileConnectionInfo.cpp @@ -4,7 +4,7 @@ * 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/. */ -#include "MobileConnectionInfo.h" +#include "mozilla/dom/MobileConnectionInfo.h" #include "mozilla/dom/ScriptSettings.h" diff --git a/dom/mobileconnection/MobileConnectionInfo.h b/dom/mobileconnection/MobileConnectionInfo.h index 7d117ec2760e..2f75e1490787 100644 --- a/dom/mobileconnection/MobileConnectionInfo.h +++ b/dom/mobileconnection/MobileConnectionInfo.h @@ -7,8 +7,8 @@ #ifndef mozilla_dom_MobileConnectionInfo_h #define mozilla_dom_MobileConnectionInfo_h -#include "MobileCellInfo.h" -#include "MobileNetworkInfo.h" +#include "mozilla/dom/MobileCellInfo.h" +#include "mozilla/dom/MobileNetworkInfo.h" #include "mozilla/dom/MozMobileConnectionInfoBinding.h" #include "nsIMobileConnectionInfo.h" #include "nsPIDOMWindow.h" diff --git a/dom/mobileconnection/MobileNetworkInfo.cpp b/dom/mobileconnection/MobileNetworkInfo.cpp index 66b808df07a1..241dd3ade91f 100644 --- a/dom/mobileconnection/MobileNetworkInfo.cpp +++ b/dom/mobileconnection/MobileNetworkInfo.cpp @@ -4,7 +4,7 @@ * 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/. */ -#include "MobileNetworkInfo.h" +#include "mozilla/dom/MobileNetworkInfo.h" using namespace mozilla::dom; diff --git a/dom/mobileconnection/ipc/MobileConnectionChild.cpp b/dom/mobileconnection/ipc/MobileConnectionChild.cpp index e96249a73d8e..281b3f8c0997 100644 --- a/dom/mobileconnection/ipc/MobileConnectionChild.cpp +++ b/dom/mobileconnection/ipc/MobileConnectionChild.cpp @@ -2,7 +2,7 @@ * 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/. */ -#include "MobileConnectionChild.h" +#include "mozilla/dom/mobileconnection/MobileConnectionChild.h" #include "MobileConnectionCallback.h" #include "mozilla/dom/MozMobileConnectionBinding.h" diff --git a/dom/mobileconnection/ipc/MobileConnectionChild.h b/dom/mobileconnection/ipc/MobileConnectionChild.h index 18c191a2d3c8..0c10a62e1501 100644 --- a/dom/mobileconnection/ipc/MobileConnectionChild.h +++ b/dom/mobileconnection/ipc/MobileConnectionChild.h @@ -5,15 +5,16 @@ #ifndef mozilla_dom_mobileconnection_MobileConnectionChild_h #define mozilla_dom_mobileconnection_MobileConnectionChild_h -#include "mozilla/dom/MobileConnectionCallback.h" #include "mozilla/dom/MobileConnectionInfo.h" -#include "mozilla/dom/PMobileConnectionChild.h" -#include "mozilla/dom/PMobileConnectionRequestChild.h" +#include "mozilla/dom/mobileconnection/PMobileConnectionChild.h" +#include "mozilla/dom/mobileconnection/PMobileConnectionRequestChild.h" #include "nsCOMArray.h" #include "nsCOMPtr.h" #include "nsIMobileConnectionService.h" #include "nsIVariant.h" +class nsIMobileConnectionCallback; + namespace mozilla { namespace dom { namespace mobileconnection { diff --git a/dom/mobileconnection/ipc/MobileConnectionIPCSerializer.h b/dom/mobileconnection/ipc/MobileConnectionIPCSerializer.h index 407b9b782f98..baac3e6a6c9e 100644 --- a/dom/mobileconnection/ipc/MobileConnectionIPCSerializer.h +++ b/dom/mobileconnection/ipc/MobileConnectionIPCSerializer.h @@ -2,14 +2,14 @@ * 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/. */ -#ifndef dom_mobileconnection_src_ipc_MobileConnectionIPCSerialiser_h -#define dom_mobileconnection_src_ipc_MobileConnectionIPCSerialiser_h +#ifndef mozilla_dom_mobileconnection_MobileConnectionIPCSerialiser_h +#define mozilla_dom_mobileconnection_MobileConnectionIPCSerialiser_h #include "ipc/IPCMessageUtils.h" #include "mozilla/dom/MobileCellInfo.h" #include "mozilla/dom/MobileConnectionInfo.h" #include "mozilla/dom/MobileNetworkInfo.h" -#include "MozMobileConnectionBinding.h" +#include "mozilla/dom/MozMobileConnectionBinding.h" using mozilla::AutoSafeJSContext; using mozilla::dom::MobileNetworkInfo; @@ -746,4 +746,4 @@ struct ParamTraits } // namespace IPC -#endif // dom_mobileconnection_src_ipc_MobileConnectionIPCSerialiser_h +#endif // mozilla_dom_mobileconnection_MobileConnectionIPCSerialiser_h diff --git a/dom/mobileconnection/ipc/MobileConnectionIPCService.h b/dom/mobileconnection/ipc/MobileConnectionIPCService.h index 28b6f3492a46..a5bf59cfdace 100644 --- a/dom/mobileconnection/ipc/MobileConnectionIPCService.h +++ b/dom/mobileconnection/ipc/MobileConnectionIPCService.h @@ -6,7 +6,7 @@ #define mozilla_dom_mobileconnection_MobileConnectionIPCService_h #include "nsCOMPtr.h" -#include "MobileConnectionChild.h" +#include "mozilla/dom/mobileconnection/MobileConnectionChild.h" #include "nsIMobileConnectionService.h" namespace mozilla { @@ -35,8 +35,8 @@ private: nsTArray> mClients; }; -} // name space mobileconnection -} // name space dom -} // name space mozilla +} // namespace mobileconnection +} // namespace dom +} // namespace mozilla #endif // mozilla_dom_mobileconnection_MobileConnectionIPCService_h diff --git a/dom/mobileconnection/ipc/MobileConnectionParent.cpp b/dom/mobileconnection/ipc/MobileConnectionParent.cpp index 0109e71fefa7..945f1e8793de 100644 --- a/dom/mobileconnection/ipc/MobileConnectionParent.cpp +++ b/dom/mobileconnection/ipc/MobileConnectionParent.cpp @@ -2,11 +2,11 @@ * 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/. */ -#include "MobileConnectionParent.h" +#include "mozilla/dom/mobileconnection/MobileConnectionParent.h" #include "mozilla/AppProcessChecker.h" #include "mozilla/dom/BindingUtils.h" -#include "mozilla/dom/MobileConnectionIPCSerializer.h" +#include "mozilla/dom/mobileconnection/MobileConnectionIPCSerializer.h" #include "mozilla/dom/MozMobileConnectionBinding.h" #include "mozilla/dom/ToJSValue.h" #include "nsIVariant.h" diff --git a/dom/mobileconnection/ipc/MobileConnectionParent.h b/dom/mobileconnection/ipc/MobileConnectionParent.h index edf1e9f61abf..f19c745a524d 100644 --- a/dom/mobileconnection/ipc/MobileConnectionParent.h +++ b/dom/mobileconnection/ipc/MobileConnectionParent.h @@ -5,8 +5,8 @@ #ifndef mozilla_dom_mobileconnection_MobileConnectionParent_h #define mozilla_dom_mobileconnection_MobileConnectionParent_h -#include "mozilla/dom/PMobileConnectionParent.h" -#include "mozilla/dom/PMobileConnectionRequestParent.h" +#include "mozilla/dom/mobileconnection/PMobileConnectionParent.h" +#include "mozilla/dom/mobileconnection/PMobileConnectionRequestParent.h" #include "nsIMobileConnectionInfo.h" #include "nsIMobileConnectionService.h" #include "nsServiceManagerUtils.h" diff --git a/dom/mobileconnection/ipc/PMobileConnection.ipdl b/dom/mobileconnection/ipc/PMobileConnection.ipdl index 149254f8342c..b76393539f95 100644 --- a/dom/mobileconnection/ipc/PMobileConnection.ipdl +++ b/dom/mobileconnection/ipc/PMobileConnection.ipdl @@ -10,6 +10,7 @@ include PMobileConnectionTypes; namespace mozilla { namespace dom { +namespace mobileconnection { sync protocol PMobileConnection { @@ -184,5 +185,6 @@ union MobileConnectionRequest SetRadioEnabledRequest; }; -} // namespace mozilla +} // namespace mobileconnection } // namespace dom +} // namespace mozilla diff --git a/dom/mobileconnection/ipc/PMobileConnectionRequest.ipdl b/dom/mobileconnection/ipc/PMobileConnectionRequest.ipdl index dda9a0249c00..2afa37ac2672 100644 --- a/dom/mobileconnection/ipc/PMobileConnectionRequest.ipdl +++ b/dom/mobileconnection/ipc/PMobileConnectionRequest.ipdl @@ -9,6 +9,7 @@ include PMobileConnectionTypes; namespace mozilla { namespace dom { +namespace mobileconnection { protocol PMobileConnectionRequest { @@ -99,5 +100,6 @@ union MobileConnectionReply MobileConnectionReplyErrorMmi; }; +} // namespace mobileconnection } // namespace dom } // namespace mozilla diff --git a/dom/mobileconnection/ipc/PMobileConnectionTypes.ipdlh b/dom/mobileconnection/ipc/PMobileConnectionTypes.ipdlh index e93eac758146..b57b3ed5321d 100644 --- a/dom/mobileconnection/ipc/PMobileConnectionTypes.ipdlh +++ b/dom/mobileconnection/ipc/PMobileConnectionTypes.ipdlh @@ -4,14 +4,15 @@ * 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/. */ -using nsMobileConnectionInfo from "mozilla/dom/MobileConnectionIPCSerializer.h"; -using nsMobileNetworkInfo from "mozilla/dom/MobileConnectionIPCSerializer.h"; +using nsMobileConnectionInfo from "mozilla/dom/mobileconnection/MobileConnectionIPCSerializer.h"; +using nsMobileNetworkInfo from "mozilla/dom/mobileconnection/MobileConnectionIPCSerializer.h"; using struct mozilla::void_t from "ipc/IPCMessageUtils.h"; -using struct IPC::MozCallForwardingOptions from "mozilla/dom/MobileConnectionIPCSerializer.h"; -using struct IPC::MozCallBarringOptions from "mozilla/dom/MobileConnectionIPCSerializer.h"; +using struct IPC::MozCallForwardingOptions from "mozilla/dom/mobileconnection/MobileConnectionIPCSerializer.h"; +using struct IPC::MozCallBarringOptions from "mozilla/dom/mobileconnection/MobileConnectionIPCSerializer.h"; namespace mozilla { namespace dom { +namespace mobileconnection { union AdditionalInformation { void_t; @@ -20,5 +21,6 @@ union AdditionalInformation { MozCallForwardingOptions[]; }; +} // namespace mobileconnection } // namespace dom } // namespace mozilla diff --git a/dom/mobileconnection/moz.build b/dom/mobileconnection/moz.build index 9a68c5ad0dc9..cc4ffd63f34a 100644 --- a/dom/mobileconnection/moz.build +++ b/dom/mobileconnection/moz.build @@ -8,17 +8,16 @@ MOCHITEST_MANIFESTS += ['tests/mochitest/mochitest.ini'] EXPORTS.mozilla.dom += [ 'DOMMMIError.h', - 'ipc/MobileConnectionIPCSerializer.h', 'MobileCellInfo.h', 'MobileConnection.h', 'MobileConnectionArray.h', - 'MobileConnectionCallback.h', 'MobileConnectionInfo.h', 'MobileNetworkInfo.h', ] EXPORTS.mozilla.dom.mobileconnection += [ 'ipc/MobileConnectionChild.h', + 'ipc/MobileConnectionIPCSerializer.h', 'ipc/MobileConnectionIPCService.h', 'ipc/MobileConnectionParent.h', ] From b3b3c7c9bb3e736fee55abfde1c40f09302b2315 Mon Sep 17 00:00:00 2001 From: Vicamo Yang Date: Sun, 21 Sep 2014 15:24:42 +0800 Subject: [PATCH 083/114] Bug 1063304 - 3.a/3: add nsIMobileConnection. Interface changes. r=echen, r=htsai --- .../interfaces/nsIMobileConnectionService.idl | 210 +++++------------- 1 file changed, 61 insertions(+), 149 deletions(-) diff --git a/dom/mobileconnection/interfaces/nsIMobileConnectionService.idl b/dom/mobileconnection/interfaces/nsIMobileConnectionService.idl index e43ad99a1864..5208237b67f0 100644 --- a/dom/mobileconnection/interfaces/nsIMobileConnectionService.idl +++ b/dom/mobileconnection/interfaces/nsIMobileConnectionService.idl @@ -4,6 +4,7 @@ #include "nsISupports.idl" +interface nsIMobileConnection; interface nsIMobileConnectionInfo; interface nsIMobileNetworkInfo; interface nsIVariant; @@ -200,12 +201,16 @@ interface nsIMobileConnectionCallback : nsISupports "@mozilla.org/mobileconnection/mobileconnectionservice;1" %} -/** - * XPCOM component (in the content process) that provides the mobile - * network information. - */ -[scriptable, uuid(b50ad32d-f70e-4729-a947-e8cfdb6ba81f)] +[scriptable, uuid(eaba3c4a-0dd5-4919-b1a2-7812e49dbbcb)] interface nsIMobileConnectionService : nsISupports +{ + readonly attribute unsigned long numItems; + + nsIMobileConnection getItemByServiceId(in unsigned long serviceId); +}; + +[scriptable, uuid(04db7331-54fe-4cf7-9347-b9481350f4c2)] +interface nsIMobileConnection : nsISupports { const long ICC_SERVICE_CLASS_VOICE = (1 << 0); const long ICC_SERVICE_CLASS_DATA = (1 << 1); @@ -258,95 +263,66 @@ interface nsIMobileConnectionService : nsISupports const long CLIR_INVOCATION = 1; const long CLIR_SUPPRESSION = 2; - /** - * Called when a content process registers receiving unsolicited messages from - * RadioInterfaceLayer in the chrome process. Only a content process that has - * the 'mobileconnection' permission is allowed to register. - */ - void registerListener(in unsigned long clientId, - in nsIMobileConnectionListener listener); - void unregisterListener(in unsigned long clientId, - in nsIMobileConnectionListener listener); + readonly attribute unsigned long serviceId; /** - * These two fields require the 'mobilenetwork' permission. + * Called when any one who is interested in receiving unsolicited messages + * from this nsIMobileConnection instance. */ - DOMString getLastKnownNetwork(in unsigned long clientId); - DOMString getLastKnownHomeNetwork(in unsigned long clientId); + void registerListener(in nsIMobileConnectionListener listener); + void unregisterListener(in nsIMobileConnectionListener listener); /** - * All fields below require the 'mobileconnection' permission. + * String of format '-'. When changed, listener method + * 'notifyLastKnownNetworkChanged' is called. */ + readonly attribute DOMString lastKnownNetwork; /** - * Get the connection information about the voice. - * - * @param clientId - * Indicate the RIL client, 0 ~ (number of client - 1). - * - * @return a nsIMobileConnectionInfo + * String of format '-[-]'. When changed, listener method + * 'notifyLastKnownHomeNetworkChanged' is called. */ - nsIMobileConnectionInfo getVoiceConnectionInfo(in unsigned long clientId); + readonly attribute DOMString lastKnownHomeNetwork; /** - * Get the connection information about the data. - * - * @param clientId - * Indicate the RIL client, 0 ~ (number of client - 1). - * - * @return a nsIMobileConnectionInfo + * Connection information about the voice. */ - nsIMobileConnectionInfo getDataConnectionInfo(in unsigned long clientId); + readonly attribute nsIMobileConnectionInfo voice; /** - * Get the integrated circuit card identifier of the SIM. - * - * @param clientId - * Indicate the RIL client, 0 ~ (number of client - 1). - * - * @return a DOMString indicates the iccId + * Connection information about the data. */ - DOMString getIccId(in unsigned long clientId); + readonly attribute nsIMobileConnectionInfo data; /** - * Get the selection mode of the voice and data networks. - * - * @param clientId - * Indicate the RIL client, 0 ~ (number of client - 1). - * - * @return a DOMString - * Possible values: 'automatic', 'manual', null (unknown). + * The integrated circuit card identifier of the SIM. */ - DOMString getNetworkSelectionMode(in unsigned long clientId); + readonly attribute DOMString iccId; /** - * Get the current radio state. - * - * @param clientId - * Indicate the RIL client, 0 ~ (number of client - 1). - * - * @return a DOMString - * Possible values: 'enabling', 'enabled', 'disabling', 'disabled', - * null (unknown). + * The selection mode of the voice and data networks. Possible values are + * 'automatic', 'manual', null (unknown). */ - DOMString getRadioState(in unsigned long clientId); + readonly attribute DOMString networkSelectionMode; /** - * Get the network types that are supported by this radio. - * - * @param clientId - * Indicate the RIL client, 0 ~ (number of client - 1). + * Current radio state. Possible values are 'enabling', 'enabled', + * 'disabling', 'disabled', null (unknown). + */ + readonly attribute DOMString radioState; + + /** + * The network types supported by this radio. * * @return an array of DOMString * Possible values: 'gsm', 'wcdma', 'cdma', 'evdo', 'lte'. */ - nsIVariant getSupportedNetworkTypes(in unsigned long clientId); + void getSupportedNetworkTypes([array, size_is(length)] out wstring types, + [retval] out unsigned long length); /** * Search for available networks. * - * @param clientId - * Indicate the RIL client, 0 ~ (number of client - 1). * @param requestCallback * Called when request is finished. * @@ -357,15 +333,12 @@ interface nsIMobileConnectionService : nsISupports * 'RadioNotAvailable', 'RequestNotSupported', 'IllegalSIMorME', or * 'GenericFailure'. */ - void getNetworks(in unsigned long clientId, - in nsIMobileConnectionCallback requestCallback); + void getNetworks(in nsIMobileConnectionCallback requestCallback); /** * Manually selects the passed in network, overriding the radio's current * selection. * - * @param clientId - * Indicate the RIL client, 0 ~ (number of client - 1). * @param network * The manually selecting network. * @param requestCallback @@ -377,15 +350,12 @@ interface nsIMobileConnectionService : nsISupports * 'RadioNotAvailable', 'RequestNotSupported', 'IllegalSIMorME', or * 'GenericFailure'. */ - void selectNetwork(in unsigned long clientId, - in nsIMobileNetworkInfo network, + void selectNetwork(in nsIMobileNetworkInfo network, in nsIMobileConnectionCallback requestCallback); /** * Tell the radio to automatically select a network. * - * @param clientId - * Indicate the RIL client, 0 ~ (number of client - 1). * @param requestCallback * Called when request is finished. * @@ -395,14 +365,11 @@ interface nsIMobileConnectionService : nsISupports * 'RadioNotAvailable', 'RequestNotSupported', 'IllegalSIMorME', or * 'GenericFailure'. */ - void selectNetworkAutomatically(in unsigned long clientId, - in nsIMobileConnectionCallback requestCallback); + void selectNetworkAutomatically(in nsIMobileConnectionCallback requestCallback); /** * Set preferred network type. * - * @param clientId - * Indicate the RIL client, 0 ~ (number of client - 1). * @param type * DOMString indicates the desired preferred network type. * Possible values: 'wcdma/gsm', 'gsm', 'wcdma', 'wcdma/gsm-auto', @@ -418,15 +385,12 @@ interface nsIMobileConnectionService : nsISupports * 'RadioNotAvailable', 'RequestNotSupported', 'InvalidParameter', * 'IllegalSIMorME', or 'GenericFailure'. */ - void setPreferredNetworkType(in unsigned long clientId, - in DOMString type, + void setPreferredNetworkType(in DOMString type, in nsIMobileConnectionCallback requestCallback); /** * Query current preferred network type. * - * @param clientId - * Indicate the RIL client, 0 ~ (number of client - 1). * @param requestCallback * Called when request is finished. * @@ -440,14 +404,11 @@ interface nsIMobileConnectionService : nsISupports * 'RadioNotAvailable', 'RequestNotSupported', 'IllegalSIMorME', or * 'GenericFailure'. */ - void getPreferredNetworkType(in unsigned long clientId, - in nsIMobileConnectionCallback requestCallback); + void getPreferredNetworkType(in nsIMobileConnectionCallback requestCallback); /** * Set roaming preference. * - * @param clientId - * Indicate the RIL client, 0 ~ (number of client - 1). * @param mode * DOMString indicates the desired roaming preference. * Possible values: 'home', 'affiliated', or 'any'. @@ -460,15 +421,12 @@ interface nsIMobileConnectionService : nsISupports * 'RadioNotAvailable', 'RequestNotSupported', InvalidParameter', * 'IllegalSIMorME', or 'GenericFailure'. */ - void setRoamingPreference(in unsigned long clientId, - in DOMString mode, + void setRoamingPreference(in DOMString mode, in nsIMobileConnectionCallback requestCallback); /** * Query current roaming preference. * - * @param clientId - * Indicate the RIL client, 0 ~ (number of client - 1). * @param requestCallback * Called when request is finished. * @@ -480,14 +438,11 @@ interface nsIMobileConnectionService : nsISupports * 'RadioNotAvailable', 'RequestNotSupported', 'IllegalSIMorME', or * 'GenericFailure'. */ - void getRoamingPreference(in unsigned long clientId, - in nsIMobileConnectionCallback requestCallback); + void getRoamingPreference(in nsIMobileConnectionCallback requestCallback); /** * Set voice privacy preference. * - * @param clientId - * Indicate the RIL client, 0 ~ (number of client - 1). * @param enabled * Boolean indicates the preferred voice privacy mode used in voice * scrambling in CDMA networks. 'True' means the enhanced voice security @@ -501,15 +456,12 @@ interface nsIMobileConnectionService : nsISupports * 'RadioNotAvailable', 'RequestNotSupported', 'IllegalSIMorME', or * 'GenericFailure'. */ - void setVoicePrivacyMode(in unsigned long clientId, - in bool enabled, + void setVoicePrivacyMode(in bool enabled, in nsIMobileConnectionCallback requestCallback); /** * Query current voice privacy mode. * - * @param clientId - * Indicate the RIL client, 0 ~ (number of client - 1). * @param requestCallback * Called when request is finished. * @@ -520,14 +472,11 @@ interface nsIMobileConnectionService : nsISupports * 'RadioNotAvailable', 'RequestNotSupported', 'IllegalSIMorME', or * 'GenericFailure'. */ - void getVoicePrivacyMode(in unsigned long clientId, - in nsIMobileConnectionCallback requestCallback); + void getVoicePrivacyMode(in nsIMobileConnectionCallback requestCallback); /** * Send a MMI message. * - * @param clientId - * Indicate the RIL client, 0 ~ (number of client - 1). * @param mmi * DOMString containing an MMI string that can be associated to a * USSD request or other RIL functionality. @@ -539,15 +488,12 @@ interface nsIMobileConnectionService : nsISupports * * Otherwise, the notifyError() will be called. */ - void sendMMI(in unsigned long clientId, - in DOMString mmi, + void sendMMI(in DOMString mmi, in nsIMobileConnectionCallback requestCallback); /** * Cancel the current MMI request if one exists. * - * @param clientId - * Indicate the RIL client, 0 ~ (number of client - 1). * @param requestCallback * Called when request is finished. * @@ -556,14 +502,11 @@ interface nsIMobileConnectionService : nsISupports * * Otherwise, the notifyError() will be called. */ - void cancelMMI(in unsigned long clientId, - in nsIMobileConnectionCallback requestCallback); + void cancelMMI(in nsIMobileConnectionCallback requestCallback); /** * Queries current call forwarding options. * - * @param clientId - * Indicate the RIL client, 0 ~ (number of client - 1). * @param reason * Indicates the reason the call is being forwarded. It shall be one of * the nsIMobileConnectionService.CALL_FORWARD_REASON_* values. @@ -578,15 +521,12 @@ interface nsIMobileConnectionService : nsISupports * 'RadioNotAvailable', 'RequestNotSupported', 'InvalidParameter', * 'IllegalSIMorME', or 'GenericFailure'. */ - void getCallForwarding(in unsigned long clientId, - in unsigned short reason, + void getCallForwarding(in unsigned short reason, in nsIMobileConnectionCallback requestCallback); /** * Configures call forwarding options. * - * @param clientId - * Indicate the RIL client, 0 ~ (number of client - 1). * @param options * An object containing the call forward rule to set. * @see MozCallForwardingOptions for the detail of options. @@ -599,15 +539,12 @@ interface nsIMobileConnectionService : nsISupports * 'RadioNotAvailable', 'RequestNotSupported', 'InvalidParameter', * 'IllegalSIMorME', or 'GenericFailure'. */ - void setCallForwarding(in unsigned long clientId, - in jsval options, + void setCallForwarding(in jsval options, in nsIMobileConnectionCallback requestCallback); /** * Queries current call barring status. * - * @param clientId - * Indicate the RIL client, 0 ~ (number of client - 1). * @param options * An object containing the call barring rule to query. No need to * specify 'enabled' property. @@ -623,15 +560,12 @@ interface nsIMobileConnectionService : nsISupports * 'RadioNotAvailable', 'RequestNotSupported', 'InvalidParameter', * 'IllegalSIMorME', or 'GenericFailure'. */ - void getCallBarring(in unsigned long clientId, - in jsval options, + void getCallBarring(in jsval options, in nsIMobileConnectionCallback requestCallback); /** * Configures call barring option. * - * @param clientId - * Indicate the RIL client, 0 ~ (number of client - 1). * @param options * An object containing the call barring rule to set. * @see MozCallBarringOptions for the detail of options. @@ -644,15 +578,12 @@ interface nsIMobileConnectionService : nsISupports * 'RadioNotAvailable', 'RequestNotSupported', 'InvalidParameter', * 'IllegalSIMorME', or 'GenericFailure'. */ - void setCallBarring(in unsigned long clientId, - in jsval options, + void setCallBarring(in jsval options, in nsIMobileConnectionCallback requestCallback); /** * Change call barring facility password. * - * @param clientId - * Indicate the RIL client, 0 ~ (number of client - 1). * @param options * An object containing information about pin and newPin, and, * this object must have both "pin" and "newPin" attributes @@ -667,15 +598,12 @@ interface nsIMobileConnectionService : nsISupports * 'RadioNotAvailable', 'RequestNotSupported', 'InvalidParameter', * 'IllegalSIMorME', or 'GenericFailure'. */ - void changeCallBarringPassword(in unsigned long clientId, - in jsval options, + void changeCallBarringPassword(in jsval options, in nsIMobileConnectionCallback requestCallback); /** * Configures call waiting options. * - * @param clientId - * Indicate the RIL client, 0 ~ (number of client - 1). * @param enabled * Boolean indicates the desired call waiting status. * @param requestCallback @@ -687,15 +615,12 @@ interface nsIMobileConnectionService : nsISupports * 'RadioNotAvailable', 'RequestNotSupported', 'IllegalSIMorME', or * 'GenericFailure'. */ - void setCallWaiting(in unsigned long clientId, - in bool enabled, + void setCallWaiting(in bool enabled, in nsIMobileConnectionCallback requestCallback); /** * Queries current call waiting options. * - * @param clientId - * Indicate the RIL client, 0 ~ (number of client - 1). * @param requestCallback * Called when request is finished. * @@ -706,15 +631,12 @@ interface nsIMobileConnectionService : nsISupports * 'RadioNotAvailable', 'RequestNotSupported', 'IllegalSIMorME', or * 'GenericFailure'. */ - void getCallWaiting(in unsigned long clientId, - in nsIMobileConnectionCallback requestCallback); + void getCallWaiting(in nsIMobileConnectionCallback requestCallback); /** * Enables or disables the presentation of the calling line identity (CLI) to * the called party when originating a call. * - * @param clientId - * Indicate the RIL client, 0 ~ (number of client - 1). * @param clirMode * One of the nsIMobileConnectionService.CLIR_* values. * @param requestCallback @@ -726,15 +648,12 @@ interface nsIMobileConnectionService : nsISupports * 'RadioNotAvailable', 'RequestNotSupported', 'InvalidParameter', * 'IllegalSIMorME', or 'GenericFailure'. */ - void setCallingLineIdRestriction(in unsigned long clientId, - in unsigned short clirMode, + void setCallingLineIdRestriction(in unsigned short clirMode, in nsIMobileConnectionCallback requestCallback); /** * Queries current CLIR status. * - * @param clientId - * Indicate the RIL client, 0 ~ (number of client - 1). * @param requestCallback * Called when request is finished. * @@ -746,14 +665,11 @@ interface nsIMobileConnectionService : nsISupports * 'RadioNotAvailable', 'RequestNotSupported', 'IllegalSIMorME', or * 'GenericFailure'. */ - void getCallingLineIdRestriction(in unsigned long clientId, - in nsIMobileConnectionCallback requestCallback); + void getCallingLineIdRestriction(in nsIMobileConnectionCallback requestCallback); /** * Exit emergency callback mode. * - * @param clientId - * Indicate the RIL client, 0 ~ (number of client - 1). * @param requestCallback * Called when request is finished. * @@ -763,14 +679,11 @@ interface nsIMobileConnectionService : nsISupports * 'RadioNotAvailable', 'RequestNotSupported', 'IllegalSIMorME', or * 'GenericFailure'. */ - void exitEmergencyCbMode(in unsigned long clientId, - in nsIMobileConnectionCallback requestCallback); + void exitEmergencyCbMode(in nsIMobileConnectionCallback requestCallback); /** * Set radio enabled/disabled. * - * @param clientId - * Indicate the RIL client, 0 ~ (number of client - 1). * @param enabled * Boolean indicates the desired radio power. True to enable the radio. * @param requestCallback @@ -786,7 +699,6 @@ interface nsIMobileConnectionService : nsISupports * 'disabling'. Calling the function in above conditions will receive * 'InvalidStateError' error. */ - void setRadioEnabled(in unsigned long clientId, - in bool enabled, + void setRadioEnabled(in bool enabled, in nsIMobileConnectionCallback requestCallback); }; From 75268db7f49f80df49407cd26bf7f2dbc0ff1a18 Mon Sep 17 00:00:00 2001 From: Vicamo Yang Date: Sun, 21 Sep 2014 15:24:43 +0800 Subject: [PATCH 084/114] Bug 1063304 - 3.b/3: implementation. r=echen --- dom/mobileconnection/MobileConnection.cpp | 190 +++++---- dom/mobileconnection/MobileConnection.h | 3 +- .../MobileConnectionArray.cpp | 48 +-- dom/mobileconnection/MobileConnectionArray.h | 7 +- .../ipc/MobileConnectionChild.cpp | 321 +++++++++++++--- .../ipc/MobileConnectionChild.h | 61 +-- .../ipc/MobileConnectionIPCService.cpp | 361 ++---------------- .../ipc/MobileConnectionIPCService.h | 8 +- .../ipc/MobileConnectionParent.cpp | 169 ++++---- .../ipc/MobileConnectionParent.h | 13 +- 10 files changed, 513 insertions(+), 668 deletions(-) diff --git a/dom/mobileconnection/MobileConnection.cpp b/dom/mobileconnection/MobileConnection.cpp index eb463aa3333d..de0d4e1d1504 100644 --- a/dom/mobileconnection/MobileConnection.cpp +++ b/dom/mobileconnection/MobileConnection.cpp @@ -78,8 +78,9 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(MobileConnection) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(MobileConnection, DOMEventTargetHelper) // Don't traverse mListener because it doesn't keep any reference to - // MobileConnection but a raw pointer instead. Neither does mService because - // it's an xpcom service and is only released at shutting down. + // MobileConnection but a raw pointer instead. Neither does mMobileConnection + // because it's an xpcom service owned object and is only released at shutting + // down. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVoice) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mData) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END @@ -102,25 +103,32 @@ NS_IMPL_RELEASE_INHERITED(MobileConnection, DOMEventTargetHelper) MobileConnection::MobileConnection(nsPIDOMWindow* aWindow, uint32_t aClientId) : DOMEventTargetHelper(aWindow) - , mClientId(aClientId) { SetIsDOMBinding(); - mService = do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID); + nsCOMPtr service = + do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID); // Not being able to acquire the service isn't fatal since we check // for it explicitly below. - if (!mService) { + if (!service) { NS_WARNING("Could not acquire nsIMobileConnectionService!"); return; } + nsresult rv = service->GetItemByServiceId(aClientId, + getter_AddRefs(mMobileConnection)); + if (NS_FAILED(rv) || !mMobileConnection) { + NS_WARNING("Could not acquire nsIMobileConnection!"); + return; + } + mListener = new Listener(this); mVoice = new MobileConnectionInfo(GetOwner()); mData = new MobileConnectionInfo(GetOwner()); if (CheckPermission("mobileconnection")) { - DebugOnly rv = mService->RegisterListener(mClientId, mListener); + DebugOnly rv = mMobileConnection->RegisterListener(mListener); NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed registering mobile connection messages with service"); UpdateVoice(); @@ -132,8 +140,8 @@ void MobileConnection::Shutdown() { if (mListener) { - if (mService) { - mService->UnregisterListener(mClientId, mListener); + if (mMobileConnection) { + mMobileConnection->UnregisterListener(mListener); } mListener->Disconnect(); @@ -176,24 +184,24 @@ MobileConnection::CheckPermission(const char* aType) const void MobileConnection::UpdateVoice() { - if (!mService) { + if (!mMobileConnection) { return; } nsCOMPtr info; - mService->GetVoiceConnectionInfo(mClientId, getter_AddRefs(info)); + mMobileConnection->GetVoice(getter_AddRefs(info)); mVoice->Update(info); } void MobileConnection::UpdateData() { - if (!mService) { + if (!mMobileConnection) { return; } nsCOMPtr info; - mService->GetDataConnectionInfo(mClientId, getter_AddRefs(info)); + mMobileConnection->GetData(getter_AddRefs(info)); mData->Update(info); } @@ -204,11 +212,11 @@ MobileConnection::GetLastKnownNetwork(nsString& aRetVal) const { aRetVal.SetIsVoid(true); - if (!mService) { + if (!mMobileConnection) { return; } - mService->GetLastKnownNetwork(mClientId, aRetVal); + mMobileConnection->GetLastKnownNetwork(aRetVal); } void @@ -216,11 +224,11 @@ MobileConnection::GetLastKnownHomeNetwork(nsString& aRetVal) const { aRetVal.SetIsVoid(true); - if (!mService) { + if (!mMobileConnection) { return; } - mService->GetLastKnownHomeNetwork(mClientId, aRetVal); + mMobileConnection->GetLastKnownHomeNetwork(aRetVal); } // All fields below require the "mobileconnection" permission. @@ -242,11 +250,11 @@ MobileConnection::GetIccId(nsString& aRetVal) const { aRetVal.SetIsVoid(true); - if (!mService) { + if (!mMobileConnection) { return; } - mService->GetIccId(mClientId, aRetVal); + mMobileConnection->GetIccId(aRetVal); } Nullable @@ -255,12 +263,12 @@ MobileConnection::GetNetworkSelectionMode() const Nullable retVal = Nullable(); - if (!mService) { + if (!mMobileConnection) { return retVal; } nsAutoString mode; - mService->GetNetworkSelectionMode(mClientId, mode); + mMobileConnection->GetNetworkSelectionMode(mode); CONVERT_STRING_TO_NULLABLE_ENUM(mode, MobileNetworkSelectionMode, retVal); return retVal; @@ -271,12 +279,12 @@ MobileConnection::GetRadioState() const { Nullable retVal = Nullable(); - if (!mService) { + if (!mMobileConnection) { return retVal; } nsAutoString state; - mService->GetRadioState(mClientId, state); + mMobileConnection->GetRadioState(state); CONVERT_STRING_TO_NULLABLE_ENUM(state, MobileRadioState, retVal); return retVal; @@ -285,45 +293,33 @@ MobileConnection::GetRadioState() const void MobileConnection::GetSupportedNetworkTypes(nsTArray& aTypes) const { - if (!mService) { + if (!mMobileConnection) { return; } - nsCOMPtr variant; - mService->GetSupportedNetworkTypes(mClientId, - getter_AddRefs(variant)); + char16_t** types = nullptr; + uint32_t length = 0; - uint16_t type; - nsIID iid; - uint32_t count; - void* data; + nsresult rv = mMobileConnection->GetSupportedNetworkTypes(&types, &length); + NS_ENSURE_SUCCESS_VOID(rv); - // Convert the nsIVariant to an array. We own the resulting buffer and its - // elements. - if (NS_FAILED(variant->GetAsArray(&type, &iid, &count, &data))) { - return; - } + for (uint32_t i = 0; i < length; ++i) { + nsDependentString rawType(types[i]); + Nullable type = Nullable(); + CONVERT_STRING_TO_NULLABLE_ENUM(rawType, MobileNetworkType, type); - // We expect the element type is wstring. - if (type == nsIDataType::VTYPE_WCHAR_STR) { - char16_t** rawArray = reinterpret_cast(data); - for (uint32_t i = 0; i < count; ++i) { - nsDependentString rawType(rawArray[i]); - Nullable type = Nullable(); - CONVERT_STRING_TO_NULLABLE_ENUM(rawType, MobileNetworkType, type); - - if (!type.IsNull()) { - aTypes.AppendElement(type.Value()); - } + if (!type.IsNull()) { + aTypes.AppendElement(type.Value()); } } - NS_Free(data); + + NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(length, types); } already_AddRefed MobileConnection::GetNetworks(ErrorResult& aRv) { - if (!mService) { + if (!mMobileConnection) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } @@ -332,7 +328,7 @@ MobileConnection::GetNetworks(ErrorResult& aRv) nsRefPtr requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = mService->GetNetworks(mClientId, requestCallback); + nsresult rv = mMobileConnection->GetNetworks(requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; @@ -344,7 +340,7 @@ MobileConnection::GetNetworks(ErrorResult& aRv) already_AddRefed MobileConnection::SelectNetwork(MobileNetworkInfo& aNetwork, ErrorResult& aRv) { - if (!mService) { + if (!mMobileConnection) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } @@ -353,7 +349,7 @@ MobileConnection::SelectNetwork(MobileNetworkInfo& aNetwork, ErrorResult& aRv) nsRefPtr requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = mService->SelectNetwork(mClientId, &aNetwork, requestCallback); + nsresult rv = mMobileConnection->SelectNetwork(&aNetwork, requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; @@ -365,7 +361,7 @@ MobileConnection::SelectNetwork(MobileNetworkInfo& aNetwork, ErrorResult& aRv) already_AddRefed MobileConnection::SelectNetworkAutomatically(ErrorResult& aRv) { - if (!mService) { + if (!mMobileConnection) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } @@ -374,8 +370,8 @@ MobileConnection::SelectNetworkAutomatically(ErrorResult& aRv) nsRefPtr requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = mService->SelectNetworkAutomatically(mClientId, - requestCallback); + nsresult rv = + mMobileConnection->SelectNetworkAutomatically(requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; @@ -388,7 +384,7 @@ already_AddRefed MobileConnection::SetPreferredNetworkType(MobilePreferredNetworkType& aType, ErrorResult& aRv) { - if (!mService) { + if (!mMobileConnection) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } @@ -400,8 +396,8 @@ MobileConnection::SetPreferredNetworkType(MobilePreferredNetworkType& aType, nsRefPtr requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = mService->SetPreferredNetworkType(mClientId, type, - requestCallback); + nsresult rv = + mMobileConnection->SetPreferredNetworkType(type, requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; @@ -413,7 +409,7 @@ MobileConnection::SetPreferredNetworkType(MobilePreferredNetworkType& aType, already_AddRefed MobileConnection::GetPreferredNetworkType(ErrorResult& aRv) { - if (!mService) { + if (!mMobileConnection) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } @@ -422,7 +418,7 @@ MobileConnection::GetPreferredNetworkType(ErrorResult& aRv) nsRefPtr requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = mService->GetPreferredNetworkType(mClientId, requestCallback); + nsresult rv = mMobileConnection->GetPreferredNetworkType(requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; @@ -435,7 +431,7 @@ already_AddRefed MobileConnection::SetRoamingPreference(MobileRoamingMode& aMode, ErrorResult& aRv) { - if (!mService) { + if (!mMobileConnection) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } @@ -447,7 +443,7 @@ MobileConnection::SetRoamingPreference(MobileRoamingMode& aMode, nsRefPtr requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = mService->SetRoamingPreference(mClientId, mode, requestCallback); + nsresult rv = mMobileConnection->SetRoamingPreference(mode, requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; @@ -459,7 +455,7 @@ MobileConnection::SetRoamingPreference(MobileRoamingMode& aMode, already_AddRefed MobileConnection::GetRoamingPreference(ErrorResult& aRv) { - if (!mService) { + if (!mMobileConnection) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } @@ -468,7 +464,7 @@ MobileConnection::GetRoamingPreference(ErrorResult& aRv) nsRefPtr requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = mService->GetRoamingPreference(mClientId, requestCallback); + nsresult rv = mMobileConnection->GetRoamingPreference(requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; @@ -480,7 +476,7 @@ MobileConnection::GetRoamingPreference(ErrorResult& aRv) already_AddRefed MobileConnection::SetVoicePrivacyMode(bool aEnabled, ErrorResult& aRv) { - if (!mService) { + if (!mMobileConnection) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } @@ -489,8 +485,8 @@ MobileConnection::SetVoicePrivacyMode(bool aEnabled, ErrorResult& aRv) nsRefPtr requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = mService->SetVoicePrivacyMode(mClientId, aEnabled, - requestCallback); + nsresult rv = + mMobileConnection->SetVoicePrivacyMode(aEnabled, requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; @@ -502,7 +498,7 @@ MobileConnection::SetVoicePrivacyMode(bool aEnabled, ErrorResult& aRv) already_AddRefed MobileConnection::GetVoicePrivacyMode(ErrorResult& aRv) { - if (!mService) { + if (!mMobileConnection) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } @@ -511,7 +507,7 @@ MobileConnection::GetVoicePrivacyMode(ErrorResult& aRv) nsRefPtr requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = mService->GetVoicePrivacyMode(mClientId, requestCallback); + nsresult rv = mMobileConnection->GetVoicePrivacyMode(requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; @@ -523,7 +519,7 @@ MobileConnection::GetVoicePrivacyMode(ErrorResult& aRv) already_AddRefed MobileConnection::SendMMI(const nsAString& aMMIString, ErrorResult& aRv) { - if (!mService) { + if (!mMobileConnection) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } @@ -532,7 +528,7 @@ MobileConnection::SendMMI(const nsAString& aMMIString, ErrorResult& aRv) nsRefPtr requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = mService->SendMMI(mClientId, aMMIString, requestCallback); + nsresult rv = mMobileConnection->SendMMI(aMMIString, requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; @@ -544,7 +540,7 @@ MobileConnection::SendMMI(const nsAString& aMMIString, ErrorResult& aRv) already_AddRefed MobileConnection::CancelMMI(ErrorResult& aRv) { - if (!mService) { + if (!mMobileConnection) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } @@ -553,7 +549,7 @@ MobileConnection::CancelMMI(ErrorResult& aRv) nsRefPtr requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = mService->CancelMMI(mClientId, requestCallback); + nsresult rv = mMobileConnection->CancelMMI(requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; @@ -565,7 +561,7 @@ MobileConnection::CancelMMI(ErrorResult& aRv) already_AddRefed MobileConnection::GetCallForwardingOption(uint16_t aReason, ErrorResult& aRv) { - if (!mService) { + if (!mMobileConnection) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } @@ -574,7 +570,7 @@ MobileConnection::GetCallForwardingOption(uint16_t aReason, ErrorResult& aRv) nsRefPtr requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = mService->GetCallForwarding(mClientId, aReason, requestCallback); + nsresult rv = mMobileConnection->GetCallForwarding(aReason, requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; @@ -587,7 +583,7 @@ already_AddRefed MobileConnection::SetCallForwardingOption(const MozCallForwardingOptions& aOptions, ErrorResult& aRv) { - if (!mService) { + if (!mMobileConnection) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } @@ -609,7 +605,7 @@ MobileConnection::SetCallForwardingOption(const MozCallForwardingOptions& aOptio nsRefPtr requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = mService->SetCallForwarding(mClientId, options, requestCallback); + nsresult rv = mMobileConnection->SetCallForwarding(options, requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; @@ -622,7 +618,7 @@ already_AddRefed MobileConnection::GetCallBarringOption(const MozCallBarringOptions& aOptions, ErrorResult& aRv) { - if (!mService) { + if (!mMobileConnection) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } @@ -644,7 +640,7 @@ MobileConnection::GetCallBarringOption(const MozCallBarringOptions& aOptions, nsRefPtr requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = mService->GetCallBarring(mClientId, options, requestCallback); + nsresult rv = mMobileConnection->GetCallBarring(options, requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; @@ -657,7 +653,7 @@ already_AddRefed MobileConnection::SetCallBarringOption(const MozCallBarringOptions& aOptions, ErrorResult& aRv) { - if (!mService) { + if (!mMobileConnection) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } @@ -679,7 +675,7 @@ MobileConnection::SetCallBarringOption(const MozCallBarringOptions& aOptions, nsRefPtr requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = mService->SetCallBarring(mClientId, options, requestCallback); + nsresult rv = mMobileConnection->SetCallBarring(options, requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; @@ -692,7 +688,7 @@ already_AddRefed MobileConnection::ChangeCallBarringPassword(const MozCallBarringOptions& aOptions, ErrorResult& aRv) { - if (!mService) { + if (!mMobileConnection) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } @@ -714,8 +710,8 @@ MobileConnection::ChangeCallBarringPassword(const MozCallBarringOptions& aOption nsRefPtr requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = mService->ChangeCallBarringPassword(mClientId, options, - requestCallback); + nsresult rv = + mMobileConnection->ChangeCallBarringPassword(options, requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; @@ -727,7 +723,7 @@ MobileConnection::ChangeCallBarringPassword(const MozCallBarringOptions& aOption already_AddRefed MobileConnection::GetCallWaitingOption(ErrorResult& aRv) { - if (!mService) { + if (!mMobileConnection) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } @@ -736,7 +732,7 @@ MobileConnection::GetCallWaitingOption(ErrorResult& aRv) nsRefPtr requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = mService->GetCallWaiting(mClientId, requestCallback); + nsresult rv = mMobileConnection->GetCallWaiting(requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; @@ -748,7 +744,7 @@ MobileConnection::GetCallWaitingOption(ErrorResult& aRv) already_AddRefed MobileConnection::SetCallWaitingOption(bool aEnabled, ErrorResult& aRv) { - if (!mService) { + if (!mMobileConnection) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } @@ -757,7 +753,7 @@ MobileConnection::SetCallWaitingOption(bool aEnabled, ErrorResult& aRv) nsRefPtr requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = mService->SetCallWaiting(mClientId, aEnabled, requestCallback); + nsresult rv = mMobileConnection->SetCallWaiting(aEnabled, requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; @@ -769,7 +765,7 @@ MobileConnection::SetCallWaitingOption(bool aEnabled, ErrorResult& aRv) already_AddRefed MobileConnection::GetCallingLineIdRestriction(ErrorResult& aRv) { - if (!mService) { + if (!mMobileConnection) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } @@ -778,8 +774,8 @@ MobileConnection::GetCallingLineIdRestriction(ErrorResult& aRv) nsRefPtr requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = mService->GetCallingLineIdRestriction(mClientId, - requestCallback); + nsresult rv = + mMobileConnection->GetCallingLineIdRestriction(requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; @@ -792,7 +788,7 @@ already_AddRefed MobileConnection::SetCallingLineIdRestriction(uint16_t aMode, ErrorResult& aRv) { - if (!mService) { + if (!mMobileConnection) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } @@ -801,8 +797,8 @@ MobileConnection::SetCallingLineIdRestriction(uint16_t aMode, nsRefPtr requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = mService->SetCallingLineIdRestriction(mClientId, aMode, - requestCallback); + nsresult rv = + mMobileConnection->SetCallingLineIdRestriction(aMode, requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; @@ -814,7 +810,7 @@ MobileConnection::SetCallingLineIdRestriction(uint16_t aMode, already_AddRefed MobileConnection::ExitEmergencyCbMode(ErrorResult& aRv) { - if (!mService) { + if (!mMobileConnection) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } @@ -823,7 +819,7 @@ MobileConnection::ExitEmergencyCbMode(ErrorResult& aRv) nsRefPtr requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = mService->ExitEmergencyCbMode(mClientId, requestCallback); + nsresult rv = mMobileConnection->ExitEmergencyCbMode(requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; @@ -835,7 +831,7 @@ MobileConnection::ExitEmergencyCbMode(ErrorResult& aRv) already_AddRefed MobileConnection::SetRadioEnabled(bool aEnabled, ErrorResult& aRv) { - if (!mService) { + if (!mMobileConnection) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } @@ -844,7 +840,7 @@ MobileConnection::SetRadioEnabled(bool aEnabled, ErrorResult& aRv) nsRefPtr requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = mService->SetRadioEnabled(mClientId, aEnabled, requestCallback); + nsresult rv = mMobileConnection->SetRadioEnabled(aEnabled, requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; diff --git a/dom/mobileconnection/MobileConnection.h b/dom/mobileconnection/MobileConnection.h index 3fbce851798e..01cad4742e65 100644 --- a/dom/mobileconnection/MobileConnection.h +++ b/dom/mobileconnection/MobileConnection.h @@ -163,8 +163,7 @@ private: ~MobileConnection(); private: - uint32_t mClientId; - nsCOMPtr mService; + nsCOMPtr mMobileConnection; nsRefPtr mListener; nsRefPtr mVoice; nsRefPtr mData; diff --git a/dom/mobileconnection/MobileConnectionArray.cpp b/dom/mobileconnection/MobileConnectionArray.cpp index 2a1e9e5f6e0b..ef2fe8249878 100644 --- a/dom/mobileconnection/MobileConnectionArray.cpp +++ b/dom/mobileconnection/MobileConnectionArray.cpp @@ -7,6 +7,7 @@ #include "mozilla/dom/MobileConnectionArray.h" #include "mozilla/dom/MozMobileConnectionArrayBinding.h" #include "mozilla/Preferences.h" +#include "nsServiceManagerUtils.h" using namespace mozilla::dom; @@ -23,14 +24,9 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MobileConnectionArray) NS_INTERFACE_MAP_END MobileConnectionArray::MobileConnectionArray(nsPIDOMWindow* aWindow) - : mInitialized(false) + : mLengthInitialized(false) , mWindow(aWindow) { - uint32_t numRil = mozilla::Preferences::GetUint("ril.numRadioInterfaces", 1); - MOZ_ASSERT(numRil > 0); - - mMobileConnections.SetLength(numRil); - SetIsDOMBinding(); } @@ -38,17 +34,6 @@ MobileConnectionArray::~MobileConnectionArray() { } -void -MobileConnectionArray::Init() -{ - mInitialized = true; - - for (uint32_t id = 0; id < mMobileConnections.Length(); id++) { - nsRefPtr mobileConnection = new MobileConnection(mWindow, id); - mMobileConnections[id] = mobileConnection; - } -} - nsPIDOMWindow* MobileConnectionArray::GetParentObject() const { @@ -70,20 +55,37 @@ MobileConnectionArray::Item(uint32_t aIndex) } uint32_t -MobileConnectionArray::Length() const +MobileConnectionArray::Length() { + if (!mLengthInitialized) { + mLengthInitialized = true; + + nsCOMPtr service = + do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID); + NS_ENSURE_TRUE(service, 0); + + uint32_t length = 0; + nsresult rv = service->GetNumItems(&length); + NS_ENSURE_SUCCESS(rv, 0); + + mMobileConnections.SetLength(length); + } + return mMobileConnections.Length(); } MobileConnection* MobileConnectionArray::IndexedGetter(uint32_t aIndex, bool& aFound) { - if (!mInitialized) { - Init(); + + aFound = aIndex < Length(); + if (!aFound) { + return nullptr; } - aFound = false; - aFound = aIndex < mMobileConnections.Length(); + if (!mMobileConnections[aIndex]) { + mMobileConnections[aIndex] = new MobileConnection(mWindow, aIndex); + } - return aFound ? mMobileConnections[aIndex] : nullptr; + return mMobileConnections[aIndex]; } diff --git a/dom/mobileconnection/MobileConnectionArray.h b/dom/mobileconnection/MobileConnectionArray.h index aaaa6c4ff0ad..9cdb7dccaa38 100644 --- a/dom/mobileconnection/MobileConnectionArray.h +++ b/dom/mobileconnection/MobileConnectionArray.h @@ -34,7 +34,7 @@ public: Item(uint32_t aIndex); uint32_t - Length() const; + Length(); MobileConnection* IndexedGetter(uint32_t aIndex, bool& aFound); @@ -42,10 +42,7 @@ public: private: ~MobileConnectionArray(); - void - Init(); - - bool mInitialized; + bool mLengthInitialized; nsCOMPtr mWindow; nsTArray> mMobileConnections; diff --git a/dom/mobileconnection/ipc/MobileConnectionChild.cpp b/dom/mobileconnection/ipc/MobileConnectionChild.cpp index 281b3f8c0997..aaeb037d6758 100644 --- a/dom/mobileconnection/ipc/MobileConnectionChild.cpp +++ b/dom/mobileconnection/ipc/MobileConnectionChild.cpp @@ -11,15 +11,23 @@ using namespace mozilla::dom; using namespace mozilla::dom::mobileconnection; +NS_IMPL_ISUPPORTS(MobileConnectionChild, nsIMobileConnection) + +MobileConnectionChild::MobileConnectionChild(uint32_t aServiceId) + : mServiceId(aServiceId) + , mLive(true) +{ + MOZ_COUNT_CTOR(MobileConnectionChild); +} + void MobileConnectionChild::Init() { nsIMobileConnectionInfo* rawVoice; nsIMobileConnectionInfo* rawData; - nsTArray types; SendInit(&rawVoice, &rawData, &mLastNetwork, &mLastHomeNetwork, &mIccId, - &mNetworkSelectionMode, &mRadioState, &types); + &mNetworkSelectionMode, &mRadioState, &mSupportedNetworkTypes); // Use dont_AddRef here because this instances is already AddRef-ed in // MobileConnectionIPCSerializer.h @@ -32,35 +40,6 @@ MobileConnectionChild::Init() nsCOMPtr data = dont_AddRef(rawData); mData = new MobileConnectionInfo(nullptr); mData->Update(data); - - - // Initial SupportedNetworkTypes - nsresult rv; - mSupportedNetworkTypes = do_CreateInstance(NS_VARIANT_CONTRACTID, &rv); - - if (NS_FAILED(rv)) { - return; - } - - uint32_t arrayLen = types.Length(); - if (arrayLen == 0) { - mSupportedNetworkTypes->SetAsEmptyArray(); - } else { - // Note: The resulting nsIVariant dupes both the array and its elements. - const char16_t** array = reinterpret_cast - (NS_Alloc(arrayLen * sizeof(const char16_t***))); - if (array) { - for (uint32_t i = 0; i < arrayLen; ++i) { - array[i] = types[i].get(); - } - - mSupportedNetworkTypes->SetAsArray(nsIDataType::VTYPE_WCHAR_STR, - nullptr, - arrayLen, - reinterpret_cast(array)); - NS_Free(array); - } - } } void @@ -74,79 +53,309 @@ MobileConnectionChild::Shutdown() mListeners.Clear(); mVoice = nullptr; mData = nullptr; - mSupportedNetworkTypes = nullptr; } -void +// nsIMobileConnection + +NS_IMETHODIMP +MobileConnectionChild::GetServiceId(uint32_t* aServiceId) +{ + *aServiceId = mServiceId; + return NS_OK; +} + +NS_IMETHODIMP MobileConnectionChild::RegisterListener(nsIMobileConnectionListener* aListener) { - if (!mListeners.Contains(aListener)) { - mListeners.AppendObject(aListener); - } + NS_ENSURE_TRUE(!mListeners.Contains(aListener), NS_ERROR_UNEXPECTED); + + mListeners.AppendObject(aListener); + return NS_OK; } -void +NS_IMETHODIMP MobileConnectionChild::UnregisterListener(nsIMobileConnectionListener* aListener) { + NS_ENSURE_TRUE(mListeners.Contains(aListener), NS_ERROR_UNEXPECTED); + mListeners.RemoveObject(aListener); + return NS_OK; } -MobileConnectionInfo* -MobileConnectionChild::GetVoiceInfo() +NS_IMETHODIMP +MobileConnectionChild::GetVoice(nsIMobileConnectionInfo** aVoice) { - return mVoice; + nsRefPtr voice(mVoice); + voice.forget(aVoice); + return NS_OK; } -MobileConnectionInfo* -MobileConnectionChild::GetDataInfo() +NS_IMETHODIMP +MobileConnectionChild::GetData(nsIMobileConnectionInfo** aData) { - return mData; + nsRefPtr data(mData); + data.forget(aData); + return NS_OK; } -void +NS_IMETHODIMP MobileConnectionChild::GetIccId(nsAString& aIccId) { aIccId = mIccId; + return NS_OK; } -void +NS_IMETHODIMP MobileConnectionChild::GetRadioState(nsAString& aRadioState) { aRadioState = mRadioState; + return NS_OK; } -nsIVariant* -MobileConnectionChild::GetSupportedNetworkTypes() +NS_IMETHODIMP +MobileConnectionChild::GetSupportedNetworkTypes(char16_t*** aTypes, + uint32_t* aLength) { - return mSupportedNetworkTypes; + NS_ENSURE_ARG(aTypes); + NS_ENSURE_ARG(aLength); + + *aLength = mSupportedNetworkTypes.Length(); + *aTypes = + static_cast(nsMemory::Alloc((*aLength) * sizeof(char16_t*))); + NS_ENSURE_TRUE(*aTypes, NS_ERROR_OUT_OF_MEMORY); + + for (uint32_t i = 0; i < *aLength; i++) { + (*aTypes)[i] = ToNewUnicode(mSupportedNetworkTypes[i]); + } + + return NS_OK; } -void -MobileConnectionChild::GetLastNetwork(nsAString& aNetwork) +NS_IMETHODIMP +MobileConnectionChild::GetLastKnownNetwork(nsAString& aNetwork) { aNetwork = mLastNetwork; + return NS_OK; } -void -MobileConnectionChild::GetLastHomeNetwork(nsAString& aNetwork) +NS_IMETHODIMP +MobileConnectionChild::GetLastKnownHomeNetwork(nsAString& aNetwork) { aNetwork = mLastHomeNetwork; + return NS_OK; } -void +NS_IMETHODIMP MobileConnectionChild::GetNetworkSelectionMode(nsAString& aMode) { aMode = mNetworkSelectionMode; + return NS_OK; +} + +NS_IMETHODIMP +MobileConnectionChild::GetNetworks(nsIMobileConnectionCallback* aCallback) +{ + return SendRequest(GetNetworksRequest(), aCallback) ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +MobileConnectionChild::SelectNetwork(nsIMobileNetworkInfo* aNetwork, + nsIMobileConnectionCallback* aCallback) +{ + nsCOMPtr network = aNetwork; + // We release the ref after serializing process is finished in + // MobileConnectionIPCSerializer. + return SendRequest(SelectNetworkRequest(network.forget().take()), aCallback) + ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +MobileConnectionChild::SelectNetworkAutomatically(nsIMobileConnectionCallback* aCallback) +{ + return SendRequest(SelectNetworkAutoRequest(), aCallback) + ? NS_OK : NS_ERROR_FAILURE; +} + + +NS_IMETHODIMP +MobileConnectionChild::SetPreferredNetworkType(const nsAString& aType, + nsIMobileConnectionCallback* aCallback) +{ + return SendRequest(SetPreferredNetworkTypeRequest(nsAutoString(aType)), + aCallback) + ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +MobileConnectionChild::GetPreferredNetworkType(nsIMobileConnectionCallback* aCallback) +{ + return SendRequest(GetPreferredNetworkTypeRequest(), aCallback) + ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +MobileConnectionChild::SetRoamingPreference(const nsAString& aMode, + nsIMobileConnectionCallback* aCallback) +{ + return SendRequest(SetRoamingPreferenceRequest(nsAutoString(aMode)), + aCallback) + ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +MobileConnectionChild::GetRoamingPreference(nsIMobileConnectionCallback* aCallback) +{ + return SendRequest(GetRoamingPreferenceRequest(), aCallback) + ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +MobileConnectionChild::SetVoicePrivacyMode(bool aEnabled, + nsIMobileConnectionCallback* aCallback) +{ + return SendRequest(SetVoicePrivacyModeRequest(aEnabled), aCallback) + ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +MobileConnectionChild::GetVoicePrivacyMode(nsIMobileConnectionCallback* aCallback) +{ + return SendRequest(GetVoicePrivacyModeRequest(), aCallback) + ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +MobileConnectionChild::SendMMI(const nsAString& aMmi, + nsIMobileConnectionCallback* aCallback) +{ + return SendRequest(SendMmiRequest(nsAutoString(aMmi)), aCallback) + ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +MobileConnectionChild::CancelMMI(nsIMobileConnectionCallback* aCallback) +{ + return SendRequest(CancelMmiRequest(), aCallback) ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +MobileConnectionChild::SetCallForwarding(JS::Handle aOptions, + nsIMobileConnectionCallback* aCallback) +{ + AutoSafeJSContext cx; + IPC::MozCallForwardingOptions options; + if(!options.Init(cx, aOptions)) { + return NS_ERROR_TYPE_ERR; + } + + return SendRequest(SetCallForwardingRequest(options), aCallback) + ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +MobileConnectionChild::GetCallForwarding(uint16_t aReason, + nsIMobileConnectionCallback* aCallback) +{ + return SendRequest(GetCallForwardingRequest(aReason), aCallback) + ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +MobileConnectionChild::SetCallBarring(JS::Handle aOptions, + nsIMobileConnectionCallback* aCallback) +{ + AutoSafeJSContext cx; + IPC::MozCallBarringOptions options; + if(!options.Init(cx, aOptions)) { + return NS_ERROR_TYPE_ERR; + } + + return SendRequest(SetCallBarringRequest(options), aCallback) + ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +MobileConnectionChild::GetCallBarring(JS::Handle aOptions, + nsIMobileConnectionCallback* aCallback) +{ + AutoSafeJSContext cx; + IPC::MozCallBarringOptions options; + if(!options.Init(cx, aOptions)) { + return NS_ERROR_TYPE_ERR; + } + + return SendRequest(GetCallBarringRequest(options), aCallback) + ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +MobileConnectionChild::ChangeCallBarringPassword(JS::Handle aOptions, + nsIMobileConnectionCallback* aCallback) +{ + AutoSafeJSContext cx; + IPC::MozCallBarringOptions options; + if(!options.Init(cx, aOptions)) { + return NS_ERROR_TYPE_ERR; + } + + return SendRequest(ChangeCallBarringPasswordRequest(options), aCallback) + ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +MobileConnectionChild::SetCallWaiting(bool aEnabled, + nsIMobileConnectionCallback* aCallback) +{ + return SendRequest(SetCallWaitingRequest(aEnabled), aCallback) + ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +MobileConnectionChild::GetCallWaiting(nsIMobileConnectionCallback* aCallback) +{ + return SendRequest(GetCallWaitingRequest(), aCallback) + ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +MobileConnectionChild::SetCallingLineIdRestriction(uint16_t aMode, + nsIMobileConnectionCallback* aCallback) +{ + return SendRequest(SetCallingLineIdRestrictionRequest(aMode), aCallback) + ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +MobileConnectionChild::GetCallingLineIdRestriction(nsIMobileConnectionCallback* aCallback) +{ + return SendRequest(GetCallingLineIdRestrictionRequest(), aCallback) + ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +MobileConnectionChild::ExitEmergencyCbMode(nsIMobileConnectionCallback* aCallback) +{ + return SendRequest(ExitEmergencyCbModeRequest(), aCallback) + ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +MobileConnectionChild::SetRadioEnabled(bool aEnabled, + nsIMobileConnectionCallback* aCallback) +{ + return SendRequest(SetRadioEnabledRequest(aEnabled), aCallback) + ? NS_OK : NS_ERROR_FAILURE; } bool -MobileConnectionChild::SendRequest(MobileConnectionRequest aRequest, - nsIMobileConnectionCallback* aRequestCallback) +MobileConnectionChild::SendRequest(const MobileConnectionRequest& aRequest, + nsIMobileConnectionCallback* aCallback) { NS_ENSURE_TRUE(mLive, false); // Deallocated in MobileConnectionChild::DeallocPMobileConnectionRequestChild(). - MobileConnectionRequestChild* actor = new MobileConnectionRequestChild(aRequestCallback); + MobileConnectionRequestChild* actor = + new MobileConnectionRequestChild(aCallback); SendPMobileConnectionRequestConstructor(actor, aRequest); return true; diff --git a/dom/mobileconnection/ipc/MobileConnectionChild.h b/dom/mobileconnection/ipc/MobileConnectionChild.h index 0c10a62e1501..e31fc2662a5c 100644 --- a/dom/mobileconnection/ipc/MobileConnectionChild.h +++ b/dom/mobileconnection/ipc/MobileConnectionChild.h @@ -25,16 +25,14 @@ namespace mobileconnection { * shutdown. For multi-sim device, more than one instance will * be created and each instance represents a sim slot. */ -class MobileConnectionChild : public PMobileConnectionChild +class MobileConnectionChild MOZ_FINAL : public PMobileConnectionChild + , public nsIMobileConnection { - NS_INLINE_DECL_REFCOUNTING(MobileConnectionChild) - public: - MobileConnectionChild() - : mLive(true) - { - MOZ_COUNT_CTOR(MobileConnectionChild); - } + NS_DECL_ISUPPORTS + NS_DECL_NSIMOBILECONNECTION + + MobileConnectionChild(uint32_t aServiceId); void Init(); @@ -42,48 +40,20 @@ public: void Shutdown(); - void - RegisterListener(nsIMobileConnectionListener* aListener); +private: + MobileConnectionChild() MOZ_DELETE; - void - UnregisterListener(nsIMobileConnectionListener* aListener); - - MobileConnectionInfo* - GetVoiceInfo(); - - MobileConnectionInfo* - GetDataInfo(); - - void - GetIccId(nsAString& aIccId); - - void - GetRadioState(nsAString& aRadioState); - - nsIVariant* - GetSupportedNetworkTypes(); - - void - GetLastNetwork(nsAString& aNetwork); - - void - GetLastHomeNetwork(nsAString& aNetwork); - - void - GetNetworkSelectionMode(nsAString& aMode); - - bool - SendRequest(MobileConnectionRequest aRequest, - nsIMobileConnectionCallback* aRequestCallback); - -protected: - virtual + // MOZ_FINAL suppresses -Werror,-Wdelete-non-virtual-dtor ~MobileConnectionChild() { MOZ_COUNT_DTOR(MobileConnectionChild); - Shutdown(); } +protected: + bool + SendRequest(const MobileConnectionRequest& aRequest, + nsIMobileConnectionCallback* aCallback); + virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE; @@ -137,9 +107,9 @@ protected: RecvNotifyNetworkSelectionModeChanged(const nsString& aMode) MOZ_OVERRIDE; private: + uint32_t mServiceId; bool mLive; nsCOMArray mListeners; - nsCOMPtr mSupportedNetworkTypes; nsRefPtr mVoice; nsRefPtr mData; nsString mIccId; @@ -147,6 +117,7 @@ private: nsString mLastNetwork; nsString mLastHomeNetwork; nsString mNetworkSelectionMode; + nsTArray mSupportedNetworkTypes; }; /****************************************************************************** diff --git a/dom/mobileconnection/ipc/MobileConnectionIPCService.cpp b/dom/mobileconnection/ipc/MobileConnectionIPCService.cpp index af6e9f439643..33750475320e 100644 --- a/dom/mobileconnection/ipc/MobileConnectionIPCService.cpp +++ b/dom/mobileconnection/ipc/MobileConnectionIPCService.cpp @@ -32,363 +32,48 @@ MobileConnectionIPCService::GetSingleton() MobileConnectionIPCService::MobileConnectionIPCService() { int32_t numRil = Preferences::GetInt("ril.numRadioInterfaces", 1); - for (int32_t i = 0; i < numRil; i++) { - // Deallocated in ContentChild::DeallocPMobileConnectionChild(). - nsRefPtr client = new MobileConnectionChild(); - NS_ASSERTION(client, "This shouldn't fail!"); - - ContentChild::GetSingleton()->SendPMobileConnectionConstructor(client, i); - client->Init(); - - mClients.AppendElement(client); - } + mItems.SetLength(numRil); } MobileConnectionIPCService::~MobileConnectionIPCService() { - uint32_t count = mClients.Length(); + uint32_t count = mItems.Length(); for (uint32_t i = 0; i < count; i++) { - mClients[i]->Shutdown(); + if (mItems[i]) { + mItems[i]->Shutdown(); + } } - - mClients.Clear(); -} - -nsresult -MobileConnectionIPCService::SendRequest(uint32_t aClientId, - MobileConnectionRequest aRequest, - nsIMobileConnectionCallback* aRequestCallback) -{ - if (aClientId >= mClients.Length()) { - return NS_ERROR_FAILURE; - } - - mClients[aClientId]->SendRequest(aRequest, aRequestCallback); - return NS_OK; } // nsIMobileConnectionService NS_IMETHODIMP -MobileConnectionIPCService::RegisterListener(uint32_t aClientId, - nsIMobileConnectionListener* aListener) +MobileConnectionIPCService::GetNumItems(uint32_t* aNumItems) { - if (aClientId >= mClients.Length()) { - return NS_ERROR_FAILURE; - } - - mClients[aClientId]->RegisterListener(aListener); + *aNumItems = mItems.Length(); return NS_OK; } NS_IMETHODIMP -MobileConnectionIPCService::UnregisterListener(uint32_t aClientId, - nsIMobileConnectionListener* aListener) +MobileConnectionIPCService::GetItemByServiceId(uint32_t aServiceId, + nsIMobileConnection** aItem) { - if (aClientId >= mClients.Length()) { - return NS_ERROR_FAILURE; + NS_ENSURE_TRUE(aServiceId < mItems.Length(), NS_ERROR_INVALID_ARG); + + if (!mItems[aServiceId]) { + nsRefPtr child = new MobileConnectionChild(aServiceId); + + // |SendPMobileConnectionConstructor| adds another reference to the child + // actor and removes in |DeallocPMobileConnectionChild|. + ContentChild::GetSingleton()->SendPMobileConnectionConstructor(child, + aServiceId); + child->Init(); + + mItems[aServiceId] = child; } - mClients[aClientId]->UnregisterListener(aListener); - return NS_OK; -} - -NS_IMETHODIMP -MobileConnectionIPCService::GetLastKnownNetwork(uint32_t aClientId, - nsAString& aLastNetwork) -{ - if (aClientId >= mClients.Length()) { - return NS_ERROR_FAILURE; - } - - mClients[aClientId]->GetLastNetwork(aLastNetwork); - return NS_OK; -} - -NS_IMETHODIMP -MobileConnectionIPCService::GetLastKnownHomeNetwork(uint32_t aClientId, - nsAString& aLastNetwork) -{ - if (aClientId >= mClients.Length()) { - return NS_ERROR_FAILURE; - } - - mClients[aClientId]->GetLastHomeNetwork(aLastNetwork); - return NS_OK; -} - -NS_IMETHODIMP -MobileConnectionIPCService::GetVoiceConnectionInfo(uint32_t aClientId, - nsIMobileConnectionInfo** aInfo) -{ - if (aClientId >= mClients.Length()) { - return NS_ERROR_FAILURE; - } - - nsCOMPtr info = mClients[aClientId]->GetVoiceInfo(); - info.forget(aInfo); + nsRefPtr item(mItems[aServiceId]); + item.forget(aItem); return NS_OK; } - -NS_IMETHODIMP -MobileConnectionIPCService::GetDataConnectionInfo(uint32_t aClientId, - nsIMobileConnectionInfo** aInfo) -{ - if (aClientId >= mClients.Length()) { - return NS_ERROR_FAILURE; - } - - nsCOMPtr info = mClients[aClientId]->GetDataInfo(); - info.forget(aInfo); - - return NS_OK; -} - -NS_IMETHODIMP -MobileConnectionIPCService::GetIccId(uint32_t aClientId, nsAString& aIccId) -{ - if (aClientId >= mClients.Length()) { - return NS_ERROR_FAILURE; - } - - mClients[aClientId]->GetIccId(aIccId); - return NS_OK; -} - -NS_IMETHODIMP -MobileConnectionIPCService::GetNetworkSelectionMode(uint32_t aClientId, - nsAString& aNetworkSelectionMode) -{ - if (aClientId >= mClients.Length()) { - return NS_ERROR_FAILURE; - } - - mClients[aClientId]->GetNetworkSelectionMode(aNetworkSelectionMode); - return NS_OK; -} - -NS_IMETHODIMP -MobileConnectionIPCService::GetRadioState(uint32_t aClientId, - nsAString& aRadioState) -{ - if (aClientId >= mClients.Length()) { - return NS_ERROR_FAILURE; - } - - mClients[aClientId]->GetRadioState(aRadioState); - return NS_OK; -} - -NS_IMETHODIMP -MobileConnectionIPCService::GetSupportedNetworkTypes(uint32_t aClientId, - nsIVariant** aSupportedTypes) -{ - if (aClientId >= mClients.Length()) { - return NS_ERROR_FAILURE; - } - - nsCOMPtr supportedTypes = mClients[aClientId]->GetSupportedNetworkTypes(); - supportedTypes.forget(aSupportedTypes); - - return NS_OK; -} - -NS_IMETHODIMP -MobileConnectionIPCService::GetNetworks(uint32_t aClientId, - nsIMobileConnectionCallback* aRequest) -{ - return SendRequest(aClientId, GetNetworksRequest(), aRequest); -} - -NS_IMETHODIMP -MobileConnectionIPCService::SelectNetwork(uint32_t aClientId, - nsIMobileNetworkInfo* aNetwork, - nsIMobileConnectionCallback* aRequest) -{ - nsCOMPtr network = aNetwork; - // We release the ref after serializing process is finished in - // MobileConnectionIPCSerializer. - return SendRequest(aClientId, SelectNetworkRequest(network.forget().take()), aRequest); -} - -NS_IMETHODIMP -MobileConnectionIPCService::SelectNetworkAutomatically(uint32_t aClientId, - nsIMobileConnectionCallback* aRequest) -{ - return SendRequest(aClientId, SelectNetworkAutoRequest(), aRequest); -} - - -NS_IMETHODIMP -MobileConnectionIPCService::SetPreferredNetworkType(uint32_t aClientId, - const nsAString& aType, - nsIMobileConnectionCallback* aRequest) -{ - return SendRequest(aClientId, - SetPreferredNetworkTypeRequest(nsAutoString(aType)), - aRequest); -} - -NS_IMETHODIMP -MobileConnectionIPCService::GetPreferredNetworkType(uint32_t aClientId, - nsIMobileConnectionCallback* aRequest) -{ - return SendRequest(aClientId, GetPreferredNetworkTypeRequest(), aRequest); -} - -NS_IMETHODIMP -MobileConnectionIPCService::SetRoamingPreference(uint32_t aClientId, - const nsAString& aMode, - nsIMobileConnectionCallback* aRequest) -{ - return SendRequest(aClientId, - SetRoamingPreferenceRequest(nsAutoString(aMode)), - aRequest); -} - -NS_IMETHODIMP -MobileConnectionIPCService::GetRoamingPreference(uint32_t aClientId, - nsIMobileConnectionCallback* aRequest) -{ - return SendRequest(aClientId, GetRoamingPreferenceRequest(), aRequest); -} - -NS_IMETHODIMP -MobileConnectionIPCService::SetVoicePrivacyMode(uint32_t aClientId, - bool aEnabled, - nsIMobileConnectionCallback* aRequest) -{ - return SendRequest(aClientId, SetVoicePrivacyModeRequest(aEnabled), aRequest); -} - -NS_IMETHODIMP -MobileConnectionIPCService::GetVoicePrivacyMode(uint32_t aClientId, - nsIMobileConnectionCallback* aRequest) -{ - return SendRequest(aClientId, GetVoicePrivacyModeRequest(), aRequest); -} - -NS_IMETHODIMP -MobileConnectionIPCService::SendMMI(uint32_t aClientId, - const nsAString& aMmi, - nsIMobileConnectionCallback* aRequest) -{ - return SendRequest(aClientId, SendMmiRequest(nsAutoString(aMmi)), aRequest); -} - -NS_IMETHODIMP -MobileConnectionIPCService::CancelMMI(uint32_t aClientId, - nsIMobileConnectionCallback* aRequest) -{ - return SendRequest(aClientId, CancelMmiRequest(), aRequest); -} - -NS_IMETHODIMP -MobileConnectionIPCService::SetCallForwarding(uint32_t aClientId, - JS::Handle aOptions, - nsIMobileConnectionCallback* aRequest) -{ - AutoSafeJSContext cx; - IPC::MozCallForwardingOptions options; - if(!options.Init(cx, aOptions)) { - return NS_ERROR_TYPE_ERR; - } - - return SendRequest(aClientId, SetCallForwardingRequest(options), aRequest); -} - -NS_IMETHODIMP -MobileConnectionIPCService::GetCallForwarding(uint32_t aClientId, - uint16_t aReason, - nsIMobileConnectionCallback* aRequest) -{ - return SendRequest(aClientId, GetCallForwardingRequest(aReason), aRequest); -} - -NS_IMETHODIMP -MobileConnectionIPCService::SetCallBarring(uint32_t aClientId, - JS::Handle aOptions, - nsIMobileConnectionCallback* aRequest) -{ - AutoSafeJSContext cx; - IPC::MozCallBarringOptions options; - if(!options.Init(cx, aOptions)) { - return NS_ERROR_TYPE_ERR; - } - - return SendRequest(aClientId, SetCallBarringRequest(options), aRequest); -} - -NS_IMETHODIMP -MobileConnectionIPCService::GetCallBarring(uint32_t aClientId, - JS::Handle aOptions, - nsIMobileConnectionCallback* aRequest) -{ - AutoSafeJSContext cx; - IPC::MozCallBarringOptions options; - if(!options.Init(cx, aOptions)) { - return NS_ERROR_TYPE_ERR; - } - - return SendRequest(aClientId, GetCallBarringRequest(options), aRequest); -} - -NS_IMETHODIMP -MobileConnectionIPCService::ChangeCallBarringPassword(uint32_t aClientId, - JS::Handle aOptions, - nsIMobileConnectionCallback* aRequest) -{ - AutoSafeJSContext cx; - IPC::MozCallBarringOptions options; - if(!options.Init(cx, aOptions)) { - return NS_ERROR_TYPE_ERR; - } - - return SendRequest(aClientId, ChangeCallBarringPasswordRequest(options), aRequest); -} - -NS_IMETHODIMP -MobileConnectionIPCService::SetCallWaiting(uint32_t aClientId, - bool aEnabled, - nsIMobileConnectionCallback* aRequest) -{ - return SendRequest(aClientId, SetCallWaitingRequest(aEnabled), aRequest); -} - -NS_IMETHODIMP -MobileConnectionIPCService::GetCallWaiting(uint32_t aClientId, - nsIMobileConnectionCallback* aRequest) -{ - return SendRequest(aClientId, GetCallWaitingRequest(), aRequest); -} - -NS_IMETHODIMP -MobileConnectionIPCService::SetCallingLineIdRestriction(uint32_t aClientId, - uint16_t aMode, - nsIMobileConnectionCallback* aRequest) -{ - return SendRequest(aClientId, SetCallingLineIdRestrictionRequest(aMode), aRequest); -} - -NS_IMETHODIMP -MobileConnectionIPCService::GetCallingLineIdRestriction(uint32_t aClientId, - nsIMobileConnectionCallback* aRequest) -{ - return SendRequest(aClientId, GetCallingLineIdRestrictionRequest(), aRequest); -} - -NS_IMETHODIMP -MobileConnectionIPCService::ExitEmergencyCbMode(uint32_t aClientId, - nsIMobileConnectionCallback* aRequest) -{ - return SendRequest(aClientId, ExitEmergencyCbModeRequest(), aRequest); -} - -NS_IMETHODIMP -MobileConnectionIPCService::SetRadioEnabled(uint32_t aClientId, - bool aEnabled, - nsIMobileConnectionCallback* aRequest) -{ - return SendRequest(aClientId, SetRadioEnabledRequest(aEnabled), aRequest); -} diff --git a/dom/mobileconnection/ipc/MobileConnectionIPCService.h b/dom/mobileconnection/ipc/MobileConnectionIPCService.h index a5bf59cfdace..7f145286979c 100644 --- a/dom/mobileconnection/ipc/MobileConnectionIPCService.h +++ b/dom/mobileconnection/ipc/MobileConnectionIPCService.h @@ -25,14 +25,10 @@ public: private: MobileConnectionIPCService(); + // MOZ_FINAL suppresses -Werror,-Wdelete-non-virtual-dtor ~MobileConnectionIPCService(); - /** Send request */ - nsresult - SendRequest(uint32_t aClientId, MobileConnectionRequest aRequest, - nsIMobileConnectionCallback* aRequestCallback); - - nsTArray> mClients; + nsTArray> mItems; }; } // namespace mobileconnection diff --git a/dom/mobileconnection/ipc/MobileConnectionParent.cpp b/dom/mobileconnection/ipc/MobileConnectionParent.cpp index 945f1e8793de..c7adcb04bd51 100644 --- a/dom/mobileconnection/ipc/MobileConnectionParent.cpp +++ b/dom/mobileconnection/ipc/MobileConnectionParent.cpp @@ -17,16 +17,18 @@ using namespace mozilla::dom; using namespace mozilla::dom::mobileconnection; MobileConnectionParent::MobileConnectionParent(uint32_t aClientId) - : mClientId(aClientId) - , mLive(true) + : mLive(true) { MOZ_COUNT_CTOR(MobileConnectionParent); - mService = do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID); - NS_ASSERTION(mService, "This shouldn't fail!"); + nsCOMPtr service = + do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID); + NS_ASSERTION(service, "This shouldn't fail!"); - if (mService) { - mService->RegisterListener(mClientId, this); + nsresult rv = service->GetItemByServiceId(aClientId, + getter_AddRefs(mMobileConnection)); + if (NS_SUCCEEDED(rv) && mMobileConnection) { + mMobileConnection->RegisterListener(this); } } @@ -34,9 +36,9 @@ void MobileConnectionParent::ActorDestroy(ActorDestroyReason why) { mLive = false; - if (mService) { - mService->UnregisterListener(mClientId, this); - mService = nullptr; + if (mMobileConnection) { + mMobileConnection->UnregisterListener(this); + mMobileConnection = nullptr; } } @@ -105,7 +107,8 @@ MobileConnectionParent::AllocPMobileConnectionRequestParent(const MobileConnecti return nullptr; } - MobileConnectionRequestParent* actor = new MobileConnectionRequestParent(mClientId); + MobileConnectionRequestParent* actor = + new MobileConnectionRequestParent(mMobileConnection); // Add an extra ref for IPDL. Will be released in // MobileConnectionParent::DeallocPMobileConnectionRequestParent(). actor->AddRef(); @@ -130,36 +133,28 @@ MobileConnectionParent::RecvInit(nsMobileConnectionInfo* aVoice, nsString* aRadioState, nsTArray* aSupportedNetworkTypes) { - NS_ENSURE_TRUE(mService, false); + NS_ENSURE_TRUE(mMobileConnection, false); - NS_ENSURE_SUCCESS(mService->GetVoiceConnectionInfo(mClientId, aVoice), false); - NS_ENSURE_SUCCESS(mService->GetDataConnectionInfo(mClientId, aData), false); - NS_ENSURE_SUCCESS(mService->GetLastKnownNetwork(mClientId, *aLastKnownNetwork), false); - NS_ENSURE_SUCCESS(mService->GetLastKnownHomeNetwork(mClientId, *aLastKnownHomeNetwork), false); - NS_ENSURE_SUCCESS(mService->GetIccId(mClientId, *aIccId), false); - NS_ENSURE_SUCCESS(mService->GetNetworkSelectionMode(mClientId, *aNetworkSelectionMode), false); - NS_ENSURE_SUCCESS(mService->GetRadioState(mClientId, *aRadioState), false); + NS_ENSURE_SUCCESS(mMobileConnection->GetVoice(aVoice), false); + NS_ENSURE_SUCCESS(mMobileConnection->GetData(aData), false); + NS_ENSURE_SUCCESS(mMobileConnection->GetLastKnownNetwork(*aLastKnownNetwork), false); + NS_ENSURE_SUCCESS(mMobileConnection->GetLastKnownHomeNetwork(*aLastKnownHomeNetwork), false); + NS_ENSURE_SUCCESS(mMobileConnection->GetIccId(*aIccId), false); + NS_ENSURE_SUCCESS(mMobileConnection->GetNetworkSelectionMode(*aNetworkSelectionMode), false); + NS_ENSURE_SUCCESS(mMobileConnection->GetRadioState(*aRadioState), false); - nsCOMPtr variant; - mService->GetSupportedNetworkTypes(mClientId, getter_AddRefs(variant)); + char16_t** types = nullptr; + uint32_t length = 0; - uint16_t type; - nsIID iid; - uint32_t count; - void* data; - if (NS_FAILED(variant->GetAsArray(&type, &iid, &count, &data))) { - return false; + nsresult rv = mMobileConnection->GetSupportedNetworkTypes(&types, &length); + NS_ENSURE_SUCCESS(rv, false); + + for (uint32_t i = 0; i < length; ++i) { + nsDependentString type(types[i]); + aSupportedNetworkTypes->AppendElement(type); } - // We expect the element type is wstring. - if (type == nsIDataType::VTYPE_WCHAR_STR) { - char16_t** rawArray = reinterpret_cast(data); - for (uint32_t i = 0; i < count; ++i) { - nsDependentString networkType(rawArray[i]); - aSupportedNetworkTypes->AppendElement(networkType); - } - } - NS_Free(data); + NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(length, types); return true; } @@ -175,7 +170,7 @@ MobileConnectionParent::NotifyVoiceChanged() nsresult rv; nsCOMPtr info; - rv = mService->GetVoiceConnectionInfo(mClientId, getter_AddRefs(info)); + rv = mMobileConnection->GetVoice(getter_AddRefs(info)); NS_ENSURE_SUCCESS(rv, rv); // We release the ref after serializing process is finished in @@ -190,7 +185,7 @@ MobileConnectionParent::NotifyDataChanged() nsresult rv; nsCOMPtr info; - rv = mService->GetDataConnectionInfo(mClientId, getter_AddRefs(info)); + rv = mMobileConnection->GetData(getter_AddRefs(info)); NS_ENSURE_SUCCESS(rv, rv); // We release the ref after serializing process is finished in @@ -256,7 +251,7 @@ MobileConnectionParent::NotifyIccChanged() NS_ENSURE_TRUE(mLive, NS_ERROR_FAILURE); nsAutoString iccId; - mService->GetIccId(mClientId, iccId); + mMobileConnection->GetIccId(iccId); return SendNotifyIccChanged(iccId) ? NS_OK : NS_ERROR_FAILURE; } @@ -268,7 +263,7 @@ MobileConnectionParent::NotifyRadioStateChanged() nsresult rv; nsAutoString radioState; - rv = mService->GetRadioState(mClientId, radioState); + rv = mMobileConnection->GetRadioState(radioState); NS_ENSURE_SUCCESS(rv, rv); return SendNotifyRadioStateChanged(radioState) ? NS_OK : NS_ERROR_FAILURE; @@ -289,7 +284,7 @@ MobileConnectionParent::NotifyLastKnownNetworkChanged() nsresult rv; nsAutoString network; - rv = mService->GetLastKnownNetwork(mClientId, network); + rv = mMobileConnection->GetLastKnownNetwork(network); NS_ENSURE_SUCCESS(rv, rv); return SendNotifyLastNetworkChanged(network) ? NS_OK : NS_ERROR_FAILURE; @@ -302,7 +297,7 @@ MobileConnectionParent::NotifyLastKnownHomeNetworkChanged() nsresult rv; nsAutoString network; - rv = mService->GetLastKnownHomeNetwork(mClientId, network); + rv = mMobileConnection->GetLastKnownHomeNetwork(network); NS_ENSURE_SUCCESS(rv, rv); return SendNotifyLastHomeNetworkChanged(network) ? NS_OK : NS_ERROR_FAILURE; @@ -315,7 +310,7 @@ MobileConnectionParent::NotifyNetworkSelectionModeChanged() nsresult rv; nsAutoString mode; - rv = mService->GetNetworkSelectionMode(mClientId, mode); + rv = mMobileConnection->GetNetworkSelectionMode(mode); NS_ENSURE_SUCCESS(rv, rv); return SendNotifyNetworkSelectionModeChanged(mode) ? NS_OK : NS_ERROR_FAILURE; @@ -329,104 +324,104 @@ void MobileConnectionRequestParent::ActorDestroy(ActorDestroyReason why) { mLive = false; - mService = nullptr; + mMobileConnection = nullptr; } bool MobileConnectionRequestParent::DoRequest(const GetNetworksRequest& aRequest) { - NS_ENSURE_TRUE(mService, false); + NS_ENSURE_TRUE(mMobileConnection, false); - return NS_SUCCEEDED(mService->GetNetworks(mClientId, this)); + return NS_SUCCEEDED(mMobileConnection->GetNetworks(this)); } bool MobileConnectionRequestParent::DoRequest(const SelectNetworkRequest& aRequest) { - NS_ENSURE_TRUE(mService, false); + NS_ENSURE_TRUE(mMobileConnection, false); // Use dont_AddRef here because this instances is already AddRef-ed in // MobileConnectionIPCSerializer.h nsCOMPtr network = dont_AddRef(aRequest.network()); - return NS_SUCCEEDED(mService->SelectNetwork(mClientId, network, this)); + return NS_SUCCEEDED(mMobileConnection->SelectNetwork(network, this)); } bool MobileConnectionRequestParent::DoRequest(const SelectNetworkAutoRequest& aRequest) { - NS_ENSURE_TRUE(mService, false); + NS_ENSURE_TRUE(mMobileConnection, false); - return NS_SUCCEEDED(mService->SelectNetworkAutomatically(mClientId, this)); + return NS_SUCCEEDED(mMobileConnection->SelectNetworkAutomatically(this)); } bool MobileConnectionRequestParent::DoRequest(const SetPreferredNetworkTypeRequest& aRequest) { - NS_ENSURE_TRUE(mService, false); + NS_ENSURE_TRUE(mMobileConnection, false); - return NS_SUCCEEDED(mService->SetPreferredNetworkType(mClientId, aRequest.type(), this)); + return NS_SUCCEEDED(mMobileConnection->SetPreferredNetworkType(aRequest.type(), this)); } bool MobileConnectionRequestParent::DoRequest(const GetPreferredNetworkTypeRequest& aRequest) { - NS_ENSURE_TRUE(mService, false); + NS_ENSURE_TRUE(mMobileConnection, false); - return NS_SUCCEEDED(mService->GetPreferredNetworkType(mClientId, this)); + return NS_SUCCEEDED(mMobileConnection->GetPreferredNetworkType(this)); } bool MobileConnectionRequestParent::DoRequest(const SetRoamingPreferenceRequest& aRequest) { - NS_ENSURE_TRUE(mService, false); + NS_ENSURE_TRUE(mMobileConnection, false); - return NS_SUCCEEDED(mService->SetRoamingPreference(mClientId, aRequest.mode(), this)); + return NS_SUCCEEDED(mMobileConnection->SetRoamingPreference(aRequest.mode(), this)); } bool MobileConnectionRequestParent::DoRequest(const GetRoamingPreferenceRequest& aRequest) { - NS_ENSURE_TRUE(mService, false); + NS_ENSURE_TRUE(mMobileConnection, false); - return NS_SUCCEEDED(mService->GetRoamingPreference(mClientId, this)); + return NS_SUCCEEDED(mMobileConnection->GetRoamingPreference(this)); } bool MobileConnectionRequestParent::DoRequest(const SetVoicePrivacyModeRequest& aRequest) { - NS_ENSURE_TRUE(mService, false); + NS_ENSURE_TRUE(mMobileConnection, false); - return NS_SUCCEEDED(mService->SetVoicePrivacyMode(mClientId, aRequest.enabled(), this)); + return NS_SUCCEEDED(mMobileConnection->SetVoicePrivacyMode(aRequest.enabled(), this)); } bool MobileConnectionRequestParent::DoRequest(const GetVoicePrivacyModeRequest& aRequest) { - NS_ENSURE_TRUE(mService, false); + NS_ENSURE_TRUE(mMobileConnection, false); - return NS_SUCCEEDED(mService->GetVoicePrivacyMode(mClientId, this)); + return NS_SUCCEEDED(mMobileConnection->GetVoicePrivacyMode(this)); } bool MobileConnectionRequestParent::DoRequest(const SendMmiRequest& aRequest) { - NS_ENSURE_TRUE(mService, false); + NS_ENSURE_TRUE(mMobileConnection, false); - return NS_SUCCEEDED(mService->SendMMI(mClientId, aRequest.mmi(), this)); + return NS_SUCCEEDED(mMobileConnection->SendMMI(aRequest.mmi(), this)); } bool MobileConnectionRequestParent::DoRequest(const CancelMmiRequest& aRequest) { - NS_ENSURE_TRUE(mService, false); + NS_ENSURE_TRUE(mMobileConnection, false); - return NS_SUCCEEDED(mService->CancelMMI(mClientId, this)); + return NS_SUCCEEDED(mMobileConnection->CancelMMI(this)); } bool MobileConnectionRequestParent::DoRequest(const SetCallForwardingRequest& aRequest) { - NS_ENSURE_TRUE(mService, false); + NS_ENSURE_TRUE(mMobileConnection, false); AutoSafeJSContext cx; JS::Rooted options(cx); @@ -435,21 +430,21 @@ MobileConnectionRequestParent::DoRequest(const SetCallForwardingRequest& aReques return false; } - return NS_SUCCEEDED(mService->SetCallForwarding(mClientId, options, this)); + return NS_SUCCEEDED(mMobileConnection->SetCallForwarding(options, this)); } bool MobileConnectionRequestParent::DoRequest(const GetCallForwardingRequest& aRequest) { - NS_ENSURE_TRUE(mService, false); + NS_ENSURE_TRUE(mMobileConnection, false); - return NS_SUCCEEDED(mService->GetCallForwarding(mClientId, aRequest.reason(), this)); + return NS_SUCCEEDED(mMobileConnection->GetCallForwarding(aRequest.reason(), this)); } bool MobileConnectionRequestParent::DoRequest(const SetCallBarringRequest& aRequest) { - NS_ENSURE_TRUE(mService, false); + NS_ENSURE_TRUE(mMobileConnection, false); AutoSafeJSContext cx; JS::Rooted options(cx); @@ -458,13 +453,13 @@ MobileConnectionRequestParent::DoRequest(const SetCallBarringRequest& aRequest) return false; } - return NS_SUCCEEDED(mService->SetCallBarring(mClientId, options, this)); + return NS_SUCCEEDED(mMobileConnection->SetCallBarring(options, this)); } bool MobileConnectionRequestParent::DoRequest(const GetCallBarringRequest& aRequest) { - NS_ENSURE_TRUE(mService, false); + NS_ENSURE_TRUE(mMobileConnection, false); AutoSafeJSContext cx; JS::Rooted options(cx); @@ -473,13 +468,13 @@ MobileConnectionRequestParent::DoRequest(const GetCallBarringRequest& aRequest) return false; } - return NS_SUCCEEDED(mService->GetCallBarring(mClientId, options, this)); + return NS_SUCCEEDED(mMobileConnection->GetCallBarring(options, this)); } bool MobileConnectionRequestParent::DoRequest(const ChangeCallBarringPasswordRequest& aRequest) { - NS_ENSURE_TRUE(mService, false); + NS_ENSURE_TRUE(mMobileConnection, false); AutoSafeJSContext cx; JS::Rooted options(cx); @@ -488,55 +483,55 @@ MobileConnectionRequestParent::DoRequest(const ChangeCallBarringPasswordRequest& return false; } - return NS_SUCCEEDED(mService->ChangeCallBarringPassword(mClientId, options, this)); + return NS_SUCCEEDED(mMobileConnection->ChangeCallBarringPassword(options, this)); } bool MobileConnectionRequestParent::DoRequest(const SetCallWaitingRequest& aRequest) { - NS_ENSURE_TRUE(mService, false); + NS_ENSURE_TRUE(mMobileConnection, false); - return NS_SUCCEEDED(mService->SetCallWaiting(mClientId, aRequest.enabled(), this)); + return NS_SUCCEEDED(mMobileConnection->SetCallWaiting(aRequest.enabled(), this)); } bool MobileConnectionRequestParent::DoRequest(const GetCallWaitingRequest& aRequest) { - NS_ENSURE_TRUE(mService, false); + NS_ENSURE_TRUE(mMobileConnection, false); - return NS_SUCCEEDED(mService->GetCallWaiting(mClientId, this)); + return NS_SUCCEEDED(mMobileConnection->GetCallWaiting(this)); } bool MobileConnectionRequestParent::DoRequest(const SetCallingLineIdRestrictionRequest& aRequest) { - NS_ENSURE_TRUE(mService, false); + NS_ENSURE_TRUE(mMobileConnection, false); - return NS_SUCCEEDED(mService->SetCallingLineIdRestriction(mClientId, aRequest.mode(), this)); + return NS_SUCCEEDED(mMobileConnection->SetCallingLineIdRestriction(aRequest.mode(), this)); } bool MobileConnectionRequestParent::DoRequest(const GetCallingLineIdRestrictionRequest& aRequest) { - NS_ENSURE_TRUE(mService, false); + NS_ENSURE_TRUE(mMobileConnection, false); - return NS_SUCCEEDED(mService->GetCallingLineIdRestriction(mClientId, this)); + return NS_SUCCEEDED(mMobileConnection->GetCallingLineIdRestriction(this)); } bool MobileConnectionRequestParent::DoRequest(const ExitEmergencyCbModeRequest& aRequest) { - NS_ENSURE_TRUE(mService, false); + NS_ENSURE_TRUE(mMobileConnection, false); - return NS_SUCCEEDED(mService->ExitEmergencyCbMode(mClientId, this)); + return NS_SUCCEEDED(mMobileConnection->ExitEmergencyCbMode(this)); } bool MobileConnectionRequestParent::DoRequest(const SetRadioEnabledRequest& aRequest) { - NS_ENSURE_TRUE(mService, false); + NS_ENSURE_TRUE(mMobileConnection, false); - return NS_SUCCEEDED(mService->SetRadioEnabled(mClientId, aRequest.enabled(), this)); + return NS_SUCCEEDED(mMobileConnection->SetRadioEnabled(aRequest.enabled(), this)); } nsresult diff --git a/dom/mobileconnection/ipc/MobileConnectionParent.h b/dom/mobileconnection/ipc/MobileConnectionParent.h index f19c745a524d..912552b0f629 100644 --- a/dom/mobileconnection/ipc/MobileConnectionParent.h +++ b/dom/mobileconnection/ipc/MobileConnectionParent.h @@ -55,9 +55,8 @@ protected: nsString* aRadioState, nsTArray* aSupportedNetworkTypes) MOZ_OVERRIDE; private: - uint32_t mClientId; + nsCOMPtr mMobileConnection; bool mLive; - nsCOMPtr mService; }; /****************************************************************************** @@ -78,14 +77,11 @@ public: NS_DECL_ISUPPORTS NS_DECL_NSIMOBILECONNECTIONCALLBACK - explicit MobileConnectionRequestParent(uint32_t aClientId) - : mClientId(aClientId) + explicit MobileConnectionRequestParent(nsIMobileConnection* aMobileConnection) + : mMobileConnection(aMobileConnection) , mLive(true) { MOZ_COUNT_CTOR(MobileConnectionRequestParent); - - mService = do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID); - NS_ASSERTION(mService, "This shouldn't fail!"); } bool @@ -168,9 +164,8 @@ protected: SendReply(const MobileConnectionReply& aReply); private: - uint32_t mClientId; + nsCOMPtr mMobileConnection; bool mLive; - nsCOMPtr mService; }; } // namespace mobileconnection From ede03dd674e19659a84ebf9772364787a6ec3975 Mon Sep 17 00:00:00 2001 From: Vicamo Yang Date: Sun, 21 Sep 2014 15:24:43 +0800 Subject: [PATCH 085/114] Bug 1063304 - 3.c/3: accommodate other components. r=echen --- dom/bluetooth/BluetoothRilListener.cpp | 43 +++++++++++------- .../bluedroid/hfp/BluetoothHfpManager.cpp | 8 +++- dom/bluetooth/bluez/BluetoothHfpManager.cpp | 10 +++-- dom/bluetooth2/BluetoothRilListener.cpp | 43 +++++++++++------- .../bluedroid/hfp/BluetoothHfpManager.cpp | 8 +++- dom/bluetooth2/bluez/BluetoothHfpManager.cpp | 10 +++-- dom/mobilemessage/gonk/MmsService.js | 5 ++- dom/phonenumberutils/PhoneNumberUtils.jsm | 3 +- dom/system/NetworkGeolocationProvider.js | 14 +++--- .../gonk/GonkGPSGeolocationProvider.cpp | 40 ++++++++++++----- dom/system/gonk/NetworkManager.js | 4 +- dom/system/gonk/RadioInterfaceLayer.js | 44 ++++++++++++------- services/mobileid/MobileIdentityManager.jsm | 13 +++--- 13 files changed, 160 insertions(+), 85 deletions(-) diff --git a/dom/bluetooth/BluetoothRilListener.cpp b/dom/bluetooth/BluetoothRilListener.cpp index 87963d201ffe..6860d50afdc5 100644 --- a/dom/bluetooth/BluetoothRilListener.cpp +++ b/dom/bluetooth/BluetoothRilListener.cpp @@ -7,9 +7,11 @@ #include "BluetoothRilListener.h" #include "BluetoothHfpManager.h" +#include "nsIIccProvider.h" #include "nsIMobileConnectionInfo.h" -#include "nsIRadioInterfaceLayer.h" -#include "nsRadioInterfaceLayer.h" +#include "nsIMobileConnectionService.h" +#include "nsITelephonyService.h" +#include "nsRadioInterfaceLayer.h" // For NS_RILCONTENTHELPER_CONTRACTID. #include "nsServiceManagerUtils.h" #include "nsString.h" @@ -179,11 +181,15 @@ MobileConnectionListener::Listen(bool aStart) do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID); NS_ENSURE_TRUE(service, false); + nsCOMPtr connection; + service->GetItemByServiceId(mClientId, getter_AddRefs(connection)); + NS_ENSURE_TRUE(connection, false); + nsresult rv; if (aStart) { - rv = service->RegisterListener(mClientId, this); + rv = connection->RegisterListener(this); } else { - rv = service->UnregisterListener(mClientId, this); + rv = connection->UnregisterListener(this); } return NS_SUCCEEDED(rv); @@ -329,17 +335,17 @@ TelephonyListener::Listen(bool aStart) */ BluetoothRilListener::BluetoothRilListener() { + nsCOMPtr service = + do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID); + NS_ENSURE_TRUE_VOID(service); + // Query number of total clients (sim slots) - uint32_t numOfClients; - nsCOMPtr radioInterfaceLayer = - do_GetService(NS_RADIOINTERFACELAYER_CONTRACTID); - NS_ENSURE_TRUE_VOID(radioInterfaceLayer); - - radioInterfaceLayer->GetNumRadioInterfaces(&numOfClients); - - // Init MobileConnectionListener array and IccInfoListener - for (uint32_t i = 0; i < numOfClients; i++) { - mMobileConnListeners.AppendElement(new MobileConnectionListener(i)); + uint32_t numItems = 0; + if (NS_SUCCEEDED(service->GetNumItems(&numItems))) { + // Init MobileConnectionListener array and IccInfoListener + for (uint32_t i = 0; i < numItems; i++) { + mMobileConnListeners.AppendElement(new MobileConnectionListener(i)); + } } mTelephonyListener = new TelephonyListener(); @@ -375,8 +381,15 @@ BluetoothRilListener::SelectClient() NS_ENSURE_TRUE_VOID(service); for (uint32_t i = 0; i < mMobileConnListeners.Length(); i++) { + nsCOMPtr connection; + service->GetItemByServiceId(i, getter_AddRefs(connection)); + if (!connection) { + BT_WARNING("%s: Failed to get mobile connection", __FUNCTION__); + continue; + } + nsCOMPtr voiceInfo; - service->GetVoiceConnectionInfo(i, getter_AddRefs(voiceInfo)); + connection->GetVoice(getter_AddRefs(voiceInfo)); if (!voiceInfo) { BT_WARNING("%s: Failed to get voice connection info", __FUNCTION__); continue; diff --git a/dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.cpp b/dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.cpp index 1dcfe7783f96..a83ddefae1b7 100644 --- a/dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.cpp +++ b/dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.cpp @@ -612,12 +612,16 @@ BluetoothHfpManager::HandleVolumeChanged(const nsAString& aData) void BluetoothHfpManager::HandleVoiceConnectionChanged(uint32_t aClientId) { - nsCOMPtr connection = + nsCOMPtr mcService = do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID); + NS_ENSURE_TRUE_VOID(mcService); + + nsCOMPtr connection; + mcService->GetItemByServiceId(aClientId, getter_AddRefs(connection)); NS_ENSURE_TRUE_VOID(connection); nsCOMPtr voiceInfo; - connection->GetVoiceConnectionInfo(aClientId, getter_AddRefs(voiceInfo)); + connection->GetVoice(getter_AddRefs(voiceInfo)); NS_ENSURE_TRUE_VOID(voiceInfo); nsString type; diff --git a/dom/bluetooth/bluez/BluetoothHfpManager.cpp b/dom/bluetooth/bluez/BluetoothHfpManager.cpp index 0eebcebcbd98..081463b692f3 100644 --- a/dom/bluetooth/bluez/BluetoothHfpManager.cpp +++ b/dom/bluetooth/bluez/BluetoothHfpManager.cpp @@ -606,12 +606,16 @@ BluetoothHfpManager::HandleVolumeChanged(const nsAString& aData) void BluetoothHfpManager::HandleVoiceConnectionChanged(uint32_t aClientId) { - nsCOMPtr connection = + nsCOMPtr mcService = do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID); + NS_ENSURE_TRUE_VOID(mcService); + + nsCOMPtr connection; + mcService->GetItemByServiceId(aClientId, getter_AddRefs(connection)); NS_ENSURE_TRUE_VOID(connection); nsCOMPtr voiceInfo; - connection->GetVoiceConnectionInfo(aClientId, getter_AddRefs(voiceInfo)); + connection->GetVoice(getter_AddRefs(voiceInfo)); NS_ENSURE_TRUE_VOID(voiceInfo); nsString type; @@ -646,7 +650,7 @@ BluetoothHfpManager::HandleVoiceConnectionChanged(uint32_t aClientId) * - manual: set mNetworkSelectionMode to 1 (manual) */ nsString mode; - connection->GetNetworkSelectionMode(aClientId, mode); + connection->GetNetworkSelectionMode(mode); if (mode.EqualsLiteral("manual")) { mNetworkSelectionMode = 1; } else { diff --git a/dom/bluetooth2/BluetoothRilListener.cpp b/dom/bluetooth2/BluetoothRilListener.cpp index 87963d201ffe..76c8153b5c35 100644 --- a/dom/bluetooth2/BluetoothRilListener.cpp +++ b/dom/bluetooth2/BluetoothRilListener.cpp @@ -7,9 +7,11 @@ #include "BluetoothRilListener.h" #include "BluetoothHfpManager.h" +#include "nsIIccProvider.h" #include "nsIMobileConnectionInfo.h" -#include "nsIRadioInterfaceLayer.h" -#include "nsRadioInterfaceLayer.h" +#include "nsIMobileConnectionService.h" +#include "nsITelephonyService.h" +#include "nsRadioInterfaceLayer.h" // For NS_RILCONTENTHELPER_CONTRACTID. #include "nsServiceManagerUtils.h" #include "nsString.h" @@ -179,11 +181,15 @@ MobileConnectionListener::Listen(bool aStart) do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID); NS_ENSURE_TRUE(service, false); + nsCOMPtr connection; + mcService->GetItemByServiceId(mClientId, getter_AddRefs(connection)); + NS_ENSURE_TRUE(connection, false); + nsresult rv; if (aStart) { - rv = service->RegisterListener(mClientId, this); + rv = connection->RegisterListener(this); } else { - rv = service->UnregisterListener(mClientId, this); + rv = connection->UnregisterListener(this); } return NS_SUCCEEDED(rv); @@ -329,17 +335,17 @@ TelephonyListener::Listen(bool aStart) */ BluetoothRilListener::BluetoothRilListener() { + nsCOMPtr service = + do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID); + NS_ENSURE_TRUE_VOID(service); + // Query number of total clients (sim slots) - uint32_t numOfClients; - nsCOMPtr radioInterfaceLayer = - do_GetService(NS_RADIOINTERFACELAYER_CONTRACTID); - NS_ENSURE_TRUE_VOID(radioInterfaceLayer); - - radioInterfaceLayer->GetNumRadioInterfaces(&numOfClients); - - // Init MobileConnectionListener array and IccInfoListener - for (uint32_t i = 0; i < numOfClients; i++) { - mMobileConnListeners.AppendElement(new MobileConnectionListener(i)); + uint32_t numItems = 0; + if (NS_SUCCEEDED(service->GetNumItems(&numItems))) { + // Init MobileConnectionListener array and IccInfoListener + for (uint32_t i = 0; i < numItems; i++) { + mMobileConnListeners.AppendElement(new MobileConnectionListener(i)); + } } mTelephonyListener = new TelephonyListener(); @@ -375,8 +381,15 @@ BluetoothRilListener::SelectClient() NS_ENSURE_TRUE_VOID(service); for (uint32_t i = 0; i < mMobileConnListeners.Length(); i++) { + nsCOMPtr connection; + service->GetItemByServiceId(i, getter_AddRefs(connection)); + if (!connection) { + BT_WARNING("%s: Failed to get mobile connection", __FUNCTION__); + continue; + } + nsCOMPtr voiceInfo; - service->GetVoiceConnectionInfo(i, getter_AddRefs(voiceInfo)); + connection->GetVoice(getter_AddRefs(voiceInfo)); if (!voiceInfo) { BT_WARNING("%s: Failed to get voice connection info", __FUNCTION__); continue; diff --git a/dom/bluetooth2/bluedroid/hfp/BluetoothHfpManager.cpp b/dom/bluetooth2/bluedroid/hfp/BluetoothHfpManager.cpp index 8b78a7520b3f..02885c2a2e84 100644 --- a/dom/bluetooth2/bluedroid/hfp/BluetoothHfpManager.cpp +++ b/dom/bluetooth2/bluedroid/hfp/BluetoothHfpManager.cpp @@ -615,12 +615,16 @@ BluetoothHfpManager::HandleVolumeChanged(const nsAString& aData) void BluetoothHfpManager::HandleVoiceConnectionChanged(uint32_t aClientId) { - nsCOMPtr connection = + nsCOMPtr mcService = do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID); + NS_ENSURE_TRUE_VOID(mcService); + + nsCOMPtr connection; + mcService->GetItemByServiceId(aClientId, getter_AddRefs(connection)); NS_ENSURE_TRUE_VOID(connection); nsCOMPtr voiceInfo; - connection->GetVoiceConnectionInfo(aClientId, getter_AddRefs(voiceInfo)); + connection->GetVoice(getter_AddRefs(voiceInfo)); NS_ENSURE_TRUE_VOID(voiceInfo); nsString type; diff --git a/dom/bluetooth2/bluez/BluetoothHfpManager.cpp b/dom/bluetooth2/bluez/BluetoothHfpManager.cpp index cd9d4f9044ec..9695d7833857 100644 --- a/dom/bluetooth2/bluez/BluetoothHfpManager.cpp +++ b/dom/bluetooth2/bluez/BluetoothHfpManager.cpp @@ -606,12 +606,16 @@ BluetoothHfpManager::HandleVolumeChanged(const nsAString& aData) void BluetoothHfpManager::HandleVoiceConnectionChanged(uint32_t aClientId) { - nsCOMPtr connection = + nsCOMPtr mcService = do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID); + NS_ENSURE_TRUE_VOID(mcService); + + nsCOMPtr connection; + mcService->GetItemByServiceId(aClientId, getter_AddRefs(connection)); NS_ENSURE_TRUE_VOID(connection); nsCOMPtr voiceInfo; - connection->GetVoiceConnectionInfo(aClientId, getter_AddRefs(voiceInfo)); + connection->GetVoice(getter_AddRefs(voiceInfo)); NS_ENSURE_TRUE_VOID(voiceInfo); nsString type; @@ -646,7 +650,7 @@ BluetoothHfpManager::HandleVoiceConnectionChanged(uint32_t aClientId) * - manual: set mNetworkSelectionMode to 1 (manual) */ nsString mode; - connection->GetNetworkSelectionMode(aClientId, mode); + connection->GetNetworkSelectionMode(mode); if (mode.EqualsLiteral("manual")) { mNetworkSelectionMode = 1; } else { diff --git a/dom/mobilemessage/gonk/MmsService.js b/dom/mobilemessage/gonk/MmsService.js index dadca29627e0..a474e9cd324e 100644 --- a/dom/mobilemessage/gonk/MmsService.js +++ b/dom/mobilemessage/gonk/MmsService.js @@ -328,8 +328,9 @@ MmsConnection.prototype = { * @return true if voice call is roaming. */ isVoiceRoaming: function() { - let voice = gMobileConnectionService.getVoiceConnectionInfo(this.serviceId); - let isRoaming = voice.roaming; + let connection = + gMobileConnectionService.getItemByServiceId(this.serviceId); + let isRoaming = connection && connection.voice && connection.voice.roaming; if (DEBUG) debug("isVoiceRoaming = " + isRoaming); return isRoaming; }, diff --git a/dom/phonenumberutils/PhoneNumberUtils.jsm b/dom/phonenumberutils/PhoneNumberUtils.jsm index 4a64e5ce4db1..c5c09ecff5b7 100644 --- a/dom/phonenumberutils/PhoneNumberUtils.jsm +++ b/dom/phonenumberutils/PhoneNumberUtils.jsm @@ -54,7 +54,8 @@ this.PhoneNumberUtils = { let clientId = 0; // Get network mcc - let voice = mobileConnection.getVoiceConnectionInfo(clientId); + let connection = mobileConnection.getItemByServiceId(clientId); + let voice = connection && connection.voice; if (voice && voice.network && voice.network.mcc) { mcc = voice.network.mcc; } diff --git a/dom/system/NetworkGeolocationProvider.js b/dom/system/NetworkGeolocationProvider.js index a3d0b58cf7d1..0e03666aa66a 100755 --- a/dom/system/NetworkGeolocationProvider.js +++ b/dom/system/NetworkGeolocationProvider.js @@ -412,14 +412,14 @@ WifiGeoPositionProvider.prototype = { let service = Cc["@mozilla.org/mobileconnection/mobileconnectionservice;1"] .getService(Ci.nsIMobileConnectionService); - let numInterfaces = radioService.numRadioInterfaces; let result = []; - for (let i = 0; i < numInterfaces; i++) { - LOG("Looking for SIM in slot:" + i + " of " + numInterfaces); - let voice = service.getVoiceConnectionInfo(i); - let cell = voice.cell; - let type = voice.type; - let network = voice.network; + for (let i = 0; i < service.length; i++) { + LOG("Looking for SIM in slot:" + i + " of " + service.length); + let connection = service.getItemByServiceId(i); + let voice = connection && connection.voice; + let cell = voice && voice.cell; + let type = voice && voice.type; + let network = voice && voice.network; if (network && cell && type) { if (type === "gsm" || type === "gprs" || type === "edge") { diff --git a/dom/system/gonk/GonkGPSGeolocationProvider.cpp b/dom/system/gonk/GonkGPSGeolocationProvider.cpp index 8cc4837852e9..59f19d90ae68 100644 --- a/dom/system/gonk/GonkGPSGeolocationProvider.cpp +++ b/dom/system/gonk/GonkGPSGeolocationProvider.cpp @@ -523,10 +523,14 @@ GonkGPSGeolocationProvider::SetReferenceLocation() return; } - nsCOMPtr voice; + nsCOMPtr connection; // TODO: Bug 878748 - B2G GPS: acquire correct RadioInterface instance in // MultiSIM configuration - service->GetVoiceConnectionInfo(0 /* Client Id */, getter_AddRefs(voice)); + service->GetItemByServiceId(0 /* Client Id */, getter_AddRefs(connection)); + NS_ENSURE_TRUE_VOID(connection); + + nsCOMPtr voice; + connection->GetVoice(getter_AddRefs(voice)); if (voice) { nsCOMPtr cell; voice->GetCell(getter_AddRefs(cell)); @@ -947,16 +951,28 @@ GonkGPSGeolocationProvider::Observe(nsISupports* aSubject, bool roaming = false; int gpsNetworkType = ConvertToGpsNetworkType(type); if (gpsNetworkType >= 0) { - nsCOMPtr service = - do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID); - if (rilface && service) { - nsCOMPtr voice; - // TODO: Bug 878748 - B2G GPS: acquire correct RadioInterface instance in - // MultiSIM configuration - service->GetVoiceConnectionInfo(0 /* Client Id */, getter_AddRefs(voice)); - if (voice) { - voice->GetRoaming(&roaming); - } + if (rilface) { + do { + nsCOMPtr service = + do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID); + if (!service) { + break; + } + + nsCOMPtr connection; + // TODO: Bug 878748 - B2G GPS: acquire correct RadioInterface instance in + // MultiSIM configuration + service->GetItemByServiceId(0 /* Client Id */, getter_AddRefs(connection)); + if (!connection) { + break; + } + + nsCOMPtr voice; + connection->GetVoice(getter_AddRefs(voice)); + if (voice) { + voice->GetRoaming(&roaming); + } + } while (0); } mAGpsRilInterface->update_network_state( connected, diff --git a/dom/system/gonk/NetworkManager.js b/dom/system/gonk/NetworkManager.js index fa172020eeb1..905c4decdc4d 100644 --- a/dom/system/gonk/NetworkManager.js +++ b/dom/system/gonk/NetworkManager.js @@ -859,7 +859,9 @@ NetworkManager.prototype = { dunRetryTimer: Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer), setupDunConnection: function() { this.dunRetryTimer.cancel(); - let data = gMobileConnectionService.getDataConnectionInfo(this._dataDefaultServiceId); + let connection = + gMobileConnectionService.getItemByServiceId(this._dataDefaultServiceId); + let data = connection && connection.data; if (data && data.state === "registered") { this.dunRetryTimes = 0; ril.setupDataCallByType("dun"); diff --git a/dom/system/gonk/RadioInterfaceLayer.js b/dom/system/gonk/RadioInterfaceLayer.js index f3fa35c20b5c..d7ec9cccc600 100644 --- a/dom/system/gonk/RadioInterfaceLayer.js +++ b/dom/system/gonk/RadioInterfaceLayer.js @@ -584,14 +584,12 @@ XPCOMUtils.defineLazyGetter(this, "gRadioEnabledController", function() { return false; }, - _isValidStateForSetRadioEnabled: function(clientId) { - let radioState = gMobileConnectionService.getRadioState(clientId); + _isValidStateForSetRadioEnabled: function(radioState) { return radioState == RIL.GECKO_RADIOSTATE_ENABLED || radioState == RIL.GECKO_RADIOSTATE_DISABLED; }, - _isDummyForSetRadioEnabled: function(clientId, data) { - let radioState = gMobileConnectionService.getRadioState(clientId); + _isDummyForSetRadioEnabled: function(radioState, data) { return (radioState == RIL.GECKO_RADIOSTATE_ENABLED && data.enabled) || (radioState == RIL.GECKO_RADIOSTATE_DISABLED && !data.enabled); }, @@ -599,16 +597,18 @@ XPCOMUtils.defineLazyGetter(this, "gRadioEnabledController", function() { _handleMessage: function(message) { if (DEBUG) debug("RadioControl: handleMessage: " + JSON.stringify(message)); let clientId = message.clientId || 0; - let radioInterface = _ril.getRadioInterface(clientId); + let connection = + gMobileConnectionService.getItemByServiceId(clientId); + let radioState = connection && connection.radioState; - if (!this._isValidStateForSetRadioEnabled(clientId)) { + if (!this._isValidStateForSetRadioEnabled(radioState)) { message.data.errorMsg = "InvalidStateError"; message.callback(message.data); this._processNextMessage(); return; } - if (this._isDummyForSetRadioEnabled(clientId, message.data)) { + if (this._isDummyForSetRadioEnabled(radioState, message.data)) { message.callback(message.data); this._processNextMessage(); return; @@ -1402,9 +1402,12 @@ DataConnectionHandler.prototype = { return; } + let connection = + gMobileConnectionService.getItemByServiceId(this.clientId); + // This check avoids data call connection if the radio is not ready // yet after toggling off airplane mode. - let radioState = gMobileConnectionService.getRadioState(this.clientId); + let radioState = connection && connection.radioState; if (radioState != RIL.GECKO_RADIOSTATE_ENABLED) { if (DEBUG) { this.debug("RIL is not ready for data connection: radio's not ready"); @@ -1424,10 +1427,12 @@ DataConnectionHandler.prototype = { return; } - let dataInfo = gMobileConnectionService.getDataConnectionInfo(this.clientId); + let dataInfo = connection && connection.data; let isRegistered = + dataInfo && dataInfo.state == RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED; let haveDataConnection = + dataInfo && dataInfo.type != RIL.GECKO_MOBILE_CONNECTION_STATE_UNKNOWN; if (!isRegistered || !haveDataConnection) { if (DEBUG) { @@ -1487,9 +1492,7 @@ DataConnectionHandler.prototype = { return; } - if (gRadioEnabledController.isDeactivatingDataCalls() || - radioState == RIL.GECKO_RADIOSTATE_ENABLING || - radioState == RIL.GECKO_RADIOSTATE_DISABLING) { + if (gRadioEnabledController.isDeactivatingDataCalls()) { // We're changing the radio power currently, ignore any changes. return; } @@ -3702,15 +3705,18 @@ RadioInterface.prototype = { Services.obs.notifyObservers(domMessage, kSmsSendingObserverTopic, null); } + let connection = + gMobileConnectionService.getItemByServiceId(this.clientId); // If the radio is disabled or the SIM card is not ready, just directly // return with the corresponding error code. let errorCode; - let radioState = gMobileConnectionService.getRadioState(this.clientId); + let radioState = connection && connection.radioState; if (!PhoneNumberUtils.isPlainPhoneNumber(options.number)) { if (DEBUG) this.debug("Error! Address is invalid when sending SMS: " + options.number); errorCode = Ci.nsIMobileMessageCallback.INVALID_ADDRESS_ERROR; - } else if (radioState == RIL.GECKO_RADIOSTATE_DISABLED) { + } else if (radioState == null || + radioState == RIL.GECKO_RADIOSTATE_DISABLED) { if (DEBUG) this.debug("Error! Radio is disabled when sending SMS."); errorCode = Ci.nsIMobileMessageCallback.RADIO_DISABLED_ERROR; } else if (this.rilContext.cardState != "ready") { @@ -4214,9 +4220,11 @@ DataCall.prototype = { this.apnProfile.apn); } - let radioInterface = this.gRIL.getRadioInterface(this.clientId); - let dataInfo = gMobileConnectionService.getDataConnectionInfo(this.clientId); - if (dataInfo.state != RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED || + let connection = + gMobileConnectionService.getItemByServiceId(this.clientId); + let dataInfo = connection && connection.data; + if (dataInfo == null || + dataInfo.state != RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED || dataInfo.type == RIL.GECKO_MOBILE_CONNECTION_STATE_UNKNOWN) { return; } @@ -4245,6 +4253,8 @@ DataCall.prototype = { pdpType = RIL.GECKO_DATACALL_PDP_TYPE_DEFAULT; } } + + let radioInterface = this.gRIL.getRadioInterface(this.clientId); radioInterface.sendWorkerMessage("setupDataCall", { radioTech: radioTechnology, apn: this.apnProfile.apn, diff --git a/services/mobileid/MobileIdentityManager.jsm b/services/mobileid/MobileIdentityManager.jsm index ef5f4d979d43..485305b62618 100644 --- a/services/mobileid/MobileIdentityManager.jsm +++ b/services/mobileid/MobileIdentityManager.jsm @@ -127,14 +127,17 @@ this.MobileIdentityManager = { continue; } - let voice = mobileConnectionService.getVoiceConnectionInfo(i); - let data = mobileConnectionService.getDataConnectionInfo(i); + let connection = mobileConnectionService.getItemByServiceId(i); + let voice = connection && connection.voice; + let data = connection && connection.data; let operator = null; - if (voice.network && + if (voice && + voice.network && voice.network.shortName && voice.network.shortName.length) { operator = voice.network.shortName; - } else if (data.network && + } else if (data && + data.network && data.network.shortName && data.network.shortName.length) { operator = data.network.shortName; @@ -148,7 +151,7 @@ this.MobileIdentityManager = { msisdn: info.msisdn || info.mdn || null, operator: operator, serviceId: i, - roaming: voice.roaming + roaming: voice && voice.roaming }); } From bdbba467b8a5950b63e2b70a9fdb4c0c5e2286fb Mon Sep 17 00:00:00 2001 From: Vicamo Yang Date: Sun, 21 Sep 2014 15:24:43 +0800 Subject: [PATCH 086/114] Bug 1063304 - 3.d/3: Gonk implementation. r=echen --- .../gonk/MobileConnectionService.js | 528 ++++-------------- 1 file changed, 102 insertions(+), 426 deletions(-) diff --git a/dom/mobileconnection/gonk/MobileConnectionService.js b/dom/mobileconnection/gonk/MobileConnectionService.js index 404552312db5..ac0141d93e26 100644 --- a/dom/mobileconnection/gonk/MobileConnectionService.js +++ b/dom/mobileconnection/gonk/MobileConnectionService.js @@ -19,6 +19,8 @@ const GONK_MOBILECONNECTIONSERVICE_CONTRACTID = const GONK_MOBILECONNECTIONSERVICE_CID = Components.ID("{0c9c1a96-2c72-4c55-9e27-0ca73eb16f63}"); +const MOBILECONNECTIONINFO_CID = + Components.ID("{8162b3c0-664b-45f6-96cd-f07b4e193b0e}"); const MOBILENETWORKINFO_CID = Components.ID("{a6c8416c-09b4-46d1-bf29-6520d677d085}"); const MOBILECELLINFO_CID = @@ -83,6 +85,27 @@ MobileCellInfo.prototype = { }) }; +function MobileConnectionInfo() {} +MobileConnectionInfo.prototype = { + QueryInterface: XPCOMUtils.generateQI([Ci.nsIMobileConnectionInfo]), + classID: MOBILECONNECTIONINFO_CID, + classInfo: XPCOMUtils.generateCI({ + classID: MOBILECONNECTIONINFO_CID, + classDescription: "MobileConnectionInfo", + interfaces: [Ci.nsIMobileConnectionInfo] + }), + + state: null, + connected: false, + emergencyCallsOnly: false, + roaming: false, + network: null, + cell: null, + type: null, + signalStrength: null, + relSignalStrength: null +}; + function CallForwardingOptions(aOptions) { this.active = aOptions.active; this.action = aOptions.action; @@ -119,28 +142,12 @@ function MobileConnectionProvider(aClientId, aRadioInterface) { this._listeners = []; this.supportedNetworkTypes = this._getSupportedNetworkTypes(); - // These objects implement the nsIMobileConnectionInfo interface, - // although the actual implementation lives in the content process. So are - // the child attributes `network` and `cell`, which implement - // nsIMobileNetworkInfo and nsIMobileCellInfo respectively. - this.voiceInfo = {connected: false, - emergencyCallsOnly: false, - roaming: false, - network: null, - cell: null, - type: null, - signalStrength: null, - relSignalStrength: null}; - this.dataInfo = {connected: false, - emergencyCallsOnly: false, - roaming: false, - network: null, - cell: null, - type: null, - signalStrength: null, - relSignalStrength: null}; + this.voice = new MobileConnectionInfo(); + this.data = new MobileConnectionInfo(); } MobileConnectionProvider.prototype = { + QueryInterface: XPCOMUtils.generateQI([Ci.nsIMobileConnection]), + _clientId: null, _radioInterface: null, _operatorInfo: null, @@ -152,10 +159,10 @@ MobileConnectionProvider.prototype = { */ _selectingNetwork: null, - voiceInfo: null, - dataInfo: null, + voice: null, + data: null, iccId: null, - networkSelectMode: null, + networkSelectionMode: null, radioState: null, lastKnownNetwork: null, lastKnownHomeNetwork: null, @@ -212,12 +219,12 @@ MobileConnectionProvider.prototype = { */ _isValidCallForwardingReason: function(aReason) { switch (aReason) { - case Ci.nsIMobileConnectionService.CALL_FORWARD_REASON_UNCONDITIONAL: - case Ci.nsIMobileConnectionService.CALL_FORWARD_REASON_MOBILE_BUSY: - case Ci.nsIMobileConnectionService.CALL_FORWARD_REASON_NO_REPLY: - case Ci.nsIMobileConnectionService.CALL_FORWARD_REASON_NOT_REACHABLE: - case Ci.nsIMobileConnectionService.CALL_FORWARD_REASON_ALL_CALL_FORWARDING: - case Ci.nsIMobileConnectionService.CALL_FORWARD_REASON_ALL_CONDITIONAL_CALL_FORWARDING: + case Ci.nsIMobileConnection.CALL_FORWARD_REASON_UNCONDITIONAL: + case Ci.nsIMobileConnection.CALL_FORWARD_REASON_MOBILE_BUSY: + case Ci.nsIMobileConnection.CALL_FORWARD_REASON_NO_REPLY: + case Ci.nsIMobileConnection.CALL_FORWARD_REASON_NOT_REACHABLE: + case Ci.nsIMobileConnection.CALL_FORWARD_REASON_ALL_CALL_FORWARDING: + case Ci.nsIMobileConnection.CALL_FORWARD_REASON_ALL_CONDITIONAL_CALL_FORWARDING: return true; default: return false; @@ -229,10 +236,10 @@ MobileConnectionProvider.prototype = { */ _isValidCallForwardingAction: function(aAction) { switch (aAction) { - case Ci.nsIMobileConnectionService.CALL_FORWARD_ACTION_DISABLE: - case Ci.nsIMobileConnectionService.CALL_FORWARD_ACTION_ENABLE: - case Ci.nsIMobileConnectionService.CALL_FORWARD_ACTION_REGISTRATION: - case Ci.nsIMobileConnectionService.CALL_FORWARD_ACTION_ERASURE: + case Ci.nsIMobileConnection.CALL_FORWARD_ACTION_DISABLE: + case Ci.nsIMobileConnection.CALL_FORWARD_ACTION_ENABLE: + case Ci.nsIMobileConnection.CALL_FORWARD_ACTION_REGISTRATION: + case Ci.nsIMobileConnection.CALL_FORWARD_ACTION_ERASURE: return true; default: return false; @@ -244,11 +251,11 @@ MobileConnectionProvider.prototype = { */ _isValidCallBarringProgram: function(aProgram) { switch (aProgram) { - case Ci.nsIMobileConnectionService.CALL_BARRING_PROGRAM_ALL_OUTGOING: - case Ci.nsIMobileConnectionService.CALL_BARRING_PROGRAM_OUTGOING_INTERNATIONAL: - case Ci.nsIMobileConnectionService.CALL_BARRING_PROGRAM_OUTGOING_INTERNATIONAL_EXCEPT_HOME: - case Ci.nsIMobileConnectionService.CALL_BARRING_PROGRAM_ALL_INCOMING: - case Ci.nsIMobileConnectionService.CALL_BARRING_PROGRAM_INCOMING_ROAMING: + case Ci.nsIMobileConnection.CALL_BARRING_PROGRAM_ALL_OUTGOING: + case Ci.nsIMobileConnection.CALL_BARRING_PROGRAM_OUTGOING_INTERNATIONAL: + case Ci.nsIMobileConnection.CALL_BARRING_PROGRAM_OUTGOING_INTERNATIONAL_EXCEPT_HOME: + case Ci.nsIMobileConnection.CALL_BARRING_PROGRAM_ALL_INCOMING: + case Ci.nsIMobileConnection.CALL_BARRING_PROGRAM_INCOMING_ROAMING: return true; default: return false; @@ -278,9 +285,9 @@ MobileConnectionProvider.prototype = { */ _isValidClirMode: function(aMode) { switch (aMode) { - case Ci.nsIMobileConnectionService.CLIR_DEFAULT: - case Ci.nsIMobileConnectionService.CLIR_INVOCATION: - case Ci.nsIMobileConnectionService.CLIR_SUPPRESSION: + case Ci.nsIMobileConnection.CLIR_DEFAULT: + case Ci.nsIMobileConnection.CLIR_INVOCATION: + case Ci.nsIMobileConnection.CLIR_SUPPRESSION: return true; default: return false; @@ -386,21 +393,21 @@ MobileConnectionProvider.prototype = { }, updateVoiceInfo: function(aNewInfo, aBatch = false) { - let isUpdated = this._updateInfo(this.voiceInfo, aNewInfo); + let isUpdated = this._updateInfo(this.voice, aNewInfo); // Make sure we also reset the operator and signal strength information // if we drop off the network. - if (this.voiceInfo.state !== RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED) { - this.voiceInfo.cell = null; - this.voiceInfo.network = null; - this.voiceInfo.signalStrength = null; - this.voiceInfo.relSignalStrength = null; + if (this.voice.state !== RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED) { + this.voice.cell = null; + this.voice.network = null; + this.voice.signalStrength = null; + this.voice.relSignalStrength = null; } else { - this.voiceInfo.network = this._operatorInfo; + this.voice.network = this._operatorInfo; } // Check roaming state - isUpdated = this._checkRoamingBetweenOperators(this.voiceInfo) || isUpdated; + isUpdated = this._checkRoamingBetweenOperators(this.voice) || isUpdated; if (isUpdated && !aBatch) { this.deliverListenerEvent("notifyVoiceChanged"); @@ -420,21 +427,21 @@ MobileConnectionProvider.prototype = { aNewInfo.connected = true; } - isUpdated = this._updateInfo(this.dataInfo, aNewInfo); + isUpdated = this._updateInfo(this.data, aNewInfo); // Make sure we also reset the operator and signal strength information // if we drop off the network. - if (this.dataInfo.state !== RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED) { - this.dataInfo.cell = null; - this.dataInfo.network = null; - this.dataInfo.signalStrength = null; - this.dataInfo.relSignalStrength = null; + if (this.data.state !== RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED) { + this.data.cell = null; + this.data.network = null; + this.data.signalStrength = null; + this.data.relSignalStrength = null; } else { - this.dataInfo.network = this._operatorInfo; + this.data.network = this._operatorInfo; } // Check roaming state - isUpdated = this._checkRoamingBetweenOperators(this.dataInfo) || isUpdated; + isUpdated = this._checkRoamingBetweenOperators(this.data) || isUpdated; if (isUpdated && !aBatch) { this.deliverListenerEvent("notifyDataChanged"); @@ -458,13 +465,13 @@ MobileConnectionProvider.prototype = { } // If the voice is unregistered, no need to send notification. - if (this.voiceInfo.state !== RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED && + if (this.voice.state !== RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED && isUpdated && !aBatch) { this.deliverListenerEvent("notifyVoiceChanged"); } // If the data is unregistered, no need to send notification. - if (this.dataInfo.state !== RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED && + if (this.data.state !== RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED && isUpdated && !aBatch) { this.deliverListenerEvent("notifyDataChanged"); } @@ -472,15 +479,15 @@ MobileConnectionProvider.prototype = { updateSignalInfo: function(aNewInfo, aBatch = false) { // If the voice is not registered, no need to update signal information. - if (this.voiceInfo.state === RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED) { - if (this._updateInfo(this.voiceInfo, aNewInfo.voice) && !aBatch) { + if (this.voice.state === RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED) { + if (this._updateInfo(this.voice, aNewInfo.voice) && !aBatch) { this.deliverListenerEvent("notifyVoiceChanged"); } } // If the data is not registered, no need to update signal information. - if (this.dataInfo.state === RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED) { - if (this._updateInfo(this.dataInfo, aNewInfo.data) && !aBatch) { + if (this.data.state === RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED) { + if (this._updateInfo(this.data, aNewInfo.data) && !aBatch) { this.deliverListenerEvent("notifyDataChanged"); } } @@ -504,6 +511,11 @@ MobileConnectionProvider.prototype = { this.deliverListenerEvent("notifyRadioStateChanged"); }, + getSupportedNetworkTypes: function(aTypes) { + aTypes.value = this.supportedNetworkTypes.slice(); + return aTypes.value.length; + }, + getNetworks: function(aCallback) { this._radioInterface.sendWorkerMessage("getAvailableNetworks", null, (function(aResponse) { @@ -997,292 +1009,17 @@ MobileConnectionService.prototype = { /** * nsIMobileConnectionService interface. */ - registerListener: function(aClientId, aListener) { - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - provider.registerListener(aListener); + get numItems() { + return this._providers.length; }, - unregisterListener: function(aClientId, aListener) { - let provider = this._providers[aClientId]; + getItemByServiceId: function(aServiceId) { + let provider = this._providers[aServiceId]; if (!provider) { throw Cr.NS_ERROR_UNEXPECTED; } - provider.unregisterListener(aListener); - }, - - getVoiceConnectionInfo: function(aClientId) { - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - return provider.voiceInfo; - }, - - getDataConnectionInfo: function(aClientId) { - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - return provider.dataInfo; - }, - - getIccId: function(aClientId) { - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - return provider.iccId; - }, - - getNetworkSelectionMode: function(aClientId) { - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - return provider.networkSelectMode; - }, - - getRadioState: function(aClientId) { - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - return provider.radioState; - }, - - getLastKnownNetwork: function(aClientId) { - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - return provider.lastKnownNetwork; - }, - - getLastKnownHomeNetwork: function(aClientId) { - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - return provider.lastKnownHomeNetwork; - }, - - getSupportedNetworkTypes: function(aClientId) { - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - return provider.supportedNetworkTypes; - }, - - getNetworks: function(aClientId, aCallback) { - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - provider.getNetworks(aCallback); - }, - - selectNetwork: function(aClientId, aNetwork, aCallback) { - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - provider.selectNetwork(aNetwork, aCallback); - }, - - selectNetworkAutomatically: function(aClientId, aCallback) { - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - provider.selectNetworkAutomatically(aCallback); - }, - - setPreferredNetworkType: function(aClientId, aType, aCallback) { - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - provider.setPreferredNetworkType(aType, aCallback); - }, - - getPreferredNetworkType: function(aClientId, aCallback) { - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - provider.getPreferredNetworkType(aCallback); - }, - - setRoamingPreference: function(aClientId, aMode, aCallback) { - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - provider.setRoamingPreference(aMode, aCallback); - }, - - getRoamingPreference: function(aClientId, aCallback) { - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - provider.getRoamingPreference(aCallback); - }, - - setVoicePrivacyMode: function(aClientId, aEnabled, aCallback) { - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - provider.setVoicePrivacyMode(aEnabled, aCallback); - }, - - getVoicePrivacyMode: function(aClientId, aCallback) { - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - provider.getVoicePrivacyMode(aCallback); - }, - - sendMMI: function(aClientId, aMmi, aCallback) { - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - provider.sendMMI(aMmi, aCallback); - }, - - cancelMMI: function(aClientId, aCallback) { - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - provider.cancelMMI(aCallback); - }, - - setCallForwarding: function(aClientId, aOptions, aCallback) { - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - provider.setCallForwarding(aOptions, aCallback); - }, - - getCallForwarding: function(aClientId, aReason, aCallback) { - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - provider.getCallForwarding(aReason, aCallback); - }, - - setCallBarring: function(aClientId, aOptions, aCallback) { - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - provider.setCallBarring(aOptions, aCallback); - }, - - getCallBarring: function(aClientId, aOptions, aCallback) { - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - provider.getCallBarring(aOptions, aCallback); - }, - - changeCallBarringPassword: function(aClientId, aOptions, aCallback) { - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - provider.changeCallBarringPassword(aOptions, aCallback); - }, - - setCallWaiting: function(aClientId, aEnabled, aCallback) { - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - provider.setCallWaiting(aEnabled, aCallback); - }, - - getCallWaiting: function(aClientId, aCallback) { - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - provider.getCallWaiting(aCallback); - }, - - setCallingLineIdRestriction: function(aClientId, aMode, aCallback) { - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - provider.setCallingLineIdRestriction(aMode, aCallback); - }, - - getCallingLineIdRestriction: function(aClientId, aCallback) { - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - provider.getCallingLineIdRestriction(aCallback); - }, - - exitEmergencyCbMode: function(aClientId, aCallback) { - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - provider.exitEmergencyCbMode(aCallback); - }, - - setRadioEnabled: function(aClientId, aEnabled, aCallback) { - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - provider.setRadioEnabled(aEnabled, aCallback); + return provider; }, /** @@ -1294,12 +1031,7 @@ MobileConnectionService.prototype = { JSON.stringify(aVoiceInfo)); } - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - provider.updateVoiceInfo(aVoiceInfo); + this.getItemByServiceId(aClientId).updateVoiceInfo(aVoiceInfo); }, notifyDataInfoChanged: function(aClientId, aDataInfo) { @@ -1308,12 +1040,7 @@ MobileConnectionService.prototype = { JSON.stringify(aDataInfo)); } - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - provider.updateDataInfo(aDataInfo); + this.getItemByServiceId(aClientId).updateDataInfo(aDataInfo); }, notifyUssdReceived: function(aClientId, aMessage, aSessionEnded) { @@ -1322,13 +1049,8 @@ MobileConnectionService.prototype = { aMessage + " (sessionEnded : " + aSessionEnded + ")"); } - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - provider.deliverListenerEvent("notifyUssdReceived", - [aMessage, aSessionEnded]); + this.getItemByServiceId(aClientId) + .deliverListenerEvent("notifyUssdReceived", [aMessage, aSessionEnded]); let info = { message: aMessage, @@ -1344,12 +1066,8 @@ MobileConnectionService.prototype = { debug("notifyDataError for " + aClientId + ": " + aMessage); } - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - provider.deliverListenerEvent("notifyDataError", [aMessage]); + this.getItemByServiceId(aClientId) + .deliverListenerEvent("notifyDataError", [aMessage]); }, notifyEmergencyCallbackModeChanged: function(aClientId, aActive, aTimeoutMs) { @@ -1358,13 +1076,9 @@ MobileConnectionService.prototype = { JSON.stringify({active: aActive, timeoutMs: aTimeoutMs})); } - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - provider.deliverListenerEvent("notifyEmergencyCbModeChanged", - [aActive, aTimeoutMs]); + this.getItemByServiceId(aClientId) + .deliverListenerEvent("notifyEmergencyCbModeChanged", + [aActive, aTimeoutMs]); }, notifyOtaStatusChanged: function(aClientId, aStatus) { @@ -1372,12 +1086,8 @@ MobileConnectionService.prototype = { debug("notifyOtaStatusChanged for " + aClientId + ": " + aStatus); } - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - provider.deliverListenerEvent("notifyOtaStatusChanged", [aStatus]); + this.getItemByServiceId(aClientId) + .deliverListenerEvent("notifyOtaStatusChanged", [aStatus]); }, notifyIccChanged: function(aClientId, aIccId) { @@ -1385,12 +1095,7 @@ MobileConnectionService.prototype = { debug("notifyIccChanged for " + aClientId + ": " + aIccId); } - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - provider.updateIccId(aIccId); + this.getItemByServiceId(aClientId).updateIccId(aIccId); }, notifyRadioStateChanged: function(aClientId, aRadioState) { @@ -1398,12 +1103,7 @@ MobileConnectionService.prototype = { debug("notifyRadioStateChanged for " + aClientId + ": " + aRadioState); } - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - provider.updateRadioState(aRadioState); + this.getItemByServiceId(aClientId).updateRadioState(aRadioState); }, notifyNetworkInfoChanged: function(aClientId, aNetworkInfo) { @@ -1412,10 +1112,7 @@ MobileConnectionService.prototype = { JSON.stringify(aNetworkInfo)); } - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } + let provider = this.getItemByServiceId(aClientId); let isVoiceUpdated = false; let isDataUpdated = false; @@ -1461,12 +1158,7 @@ MobileConnectionService.prototype = { JSON.stringify(aSignal)); } - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - provider.updateSignalInfo(aSignal); + this.getItemByServiceId(aClientId).updateSignalInfo(aSignal); }, notifyOperatorChanged: function(aClientId, aOperator) { @@ -1475,12 +1167,7 @@ MobileConnectionService.prototype = { JSON.stringify(aOperator)); } - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - provider.updateOperatorInfo(aOperator); + this.getItemByServiceId(aClientId).updateOperatorInfo(aOperator); }, notifyNetworkSelectModeChanged: function(aClientId, aMode) { @@ -1488,16 +1175,12 @@ MobileConnectionService.prototype = { debug("notifyNetworkSelectModeChanged for " + aClientId + ": " + aMode); } - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - if (provider.networkSelectMode === aMode) { + let provider = this.getItemByServiceId(aClientId); + if (provider.networkSelectionMode === aMode) { return; } - provider.networkSelectMode = aMode; + provider.networkSelectionMode = aMode; provider.deliverListenerEvent("notifyNetworkSelectionModeChanged"); }, @@ -1506,10 +1189,7 @@ MobileConnectionService.prototype = { debug("notifySpnAvailable for " + aClientId); } - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } + let provider = this.getItemByServiceId(aClientId); // Update voice roaming state provider.updateVoiceInfo({}); @@ -1523,11 +1203,7 @@ MobileConnectionService.prototype = { debug("notifyLastHomeNetworkChanged for " + aClientId + ": " + aNetwork); } - let provider = this._providers[aClientId]; - if (!provider) { - throw Cr.NS_ERROR_UNEXPECTED; - } - + let provider = this.getItemByServiceId(aClientId); if (provider.lastKnownHomeNetwork === aNetwork) { return; } @@ -1542,7 +1218,7 @@ MobileConnectionService.prototype = { observe: function(aSubject, aTopic, aData) { switch (aTopic) { case NS_NETWORK_ACTIVE_CHANGED_TOPIC_ID: - for (let i = 0; i < this._providers.length; i++) { + for (let i = 0; i < this.numItems; i++) { let provider = this._providers[i]; // Update connected flag only. provider.updateDataInfo({}); From 622a105ded9d079c9bdb55556385bd7caa762fa0 Mon Sep 17 00:00:00 2001 From: Vicamo Yang Date: Sun, 21 Sep 2014 15:24:44 +0800 Subject: [PATCH 087/114] Bug 1063304 - 3.e/3: ensure 'network', 'cell' are created with correct types. r=me --- .../gonk/MobileConnectionService.js | 84 ++++++++++--------- 1 file changed, 44 insertions(+), 40 deletions(-) diff --git a/dom/mobileconnection/gonk/MobileConnectionService.js b/dom/mobileconnection/gonk/MobileConnectionService.js index ac0141d93e26..e0402d42996e 100644 --- a/dom/mobileconnection/gonk/MobileConnectionService.js +++ b/dom/mobileconnection/gonk/MobileConnectionService.js @@ -137,7 +137,7 @@ MMIResult.prototype = { function MobileConnectionProvider(aClientId, aRadioInterface) { this._clientId = aClientId; this._radioInterface = aRadioInterface; - this._operatorInfo = {}; + this._operatorInfo = new MobileNetworkInfo(); // An array of nsIMobileConnectionListener instances. this._listeners = []; @@ -328,16 +328,52 @@ MobileConnectionProvider.prototype = { return true; }, - _updateInfo: function(aDestInfo, aSrcInfo) { + _updateConnectionInfo: function(aDestInfo, aSrcInfo) { let isUpdated = false; for (let key in aSrcInfo) { - // For updating MobileConnectionInfo - if (key === "cell" && aSrcInfo.cell) { - if (!aDestInfo.cell) { + if (key === "network" || key === "cell") { + // nsIMobileNetworkInfo and nsIMobileCellInfo are handled explicitly below. + continue; + } + + if (aDestInfo[key] !== aSrcInfo[key]) { + isUpdated = true; + aDestInfo[key] = aSrcInfo[key]; + } + } + + // Make sure we also reset the operator and signal strength information + // if we drop off the network. + if (aDestInfo.state !== RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED) { + aDestInfo.cell = null; + aDestInfo.network = null; + aDestInfo.signalStrength = null; + aDestInfo.relSignalStrength = null; + } else { + aDestInfo.network = this._operatorInfo; + + if (aSrcInfo.cell == null) { + if (aDestInfo.cell != null) { + isUpdated = true; + aDestInfo.cell = null; + } + } else { + if (aDestInfo.cell == null) { aDestInfo.cell = new MobileCellInfo(); } isUpdated = this._updateInfo(aDestInfo.cell, aSrcInfo.cell) || isUpdated; - } else if (aDestInfo[key] !== aSrcInfo[key]) { + } + } + + // Check roaming state + isUpdated = this._checkRoamingBetweenOperators(aDestInfo) || isUpdated; + return isUpdated; + }, + + _updateInfo: function(aDestInfo, aSrcInfo) { + let isUpdated = false; + for (let key in aSrcInfo) { + if (aDestInfo[key] !== aSrcInfo[key]) { isUpdated = true; aDestInfo[key] = aSrcInfo[key]; } @@ -393,30 +429,13 @@ MobileConnectionProvider.prototype = { }, updateVoiceInfo: function(aNewInfo, aBatch = false) { - let isUpdated = this._updateInfo(this.voice, aNewInfo); - - // Make sure we also reset the operator and signal strength information - // if we drop off the network. - if (this.voice.state !== RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED) { - this.voice.cell = null; - this.voice.network = null; - this.voice.signalStrength = null; - this.voice.relSignalStrength = null; - } else { - this.voice.network = this._operatorInfo; - } - - // Check roaming state - isUpdated = this._checkRoamingBetweenOperators(this.voice) || isUpdated; - + let isUpdated = this._updateConnectionInfo(this.voice, aNewInfo); if (isUpdated && !aBatch) { this.deliverListenerEvent("notifyVoiceChanged"); } }, updateDataInfo: function(aNewInfo, aBatch = false) { - let isUpdated = false; - // For the data connection, the `connected` flag indicates whether // there's an active data call. We get correct `connected` state here. let active = gNetworkManager.active; @@ -427,22 +446,7 @@ MobileConnectionProvider.prototype = { aNewInfo.connected = true; } - isUpdated = this._updateInfo(this.data, aNewInfo); - - // Make sure we also reset the operator and signal strength information - // if we drop off the network. - if (this.data.state !== RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED) { - this.data.cell = null; - this.data.network = null; - this.data.signalStrength = null; - this.data.relSignalStrength = null; - } else { - this.data.network = this._operatorInfo; - } - - // Check roaming state - isUpdated = this._checkRoamingBetweenOperators(this.data) || isUpdated; - + let isUpdated = this._updateConnectionInfo(this.data, aNewInfo); if (isUpdated && !aBatch) { this.deliverListenerEvent("notifyDataChanged"); } From 311da50812d1ea9df1ae4dcfe755c57b848e51c7 Mon Sep 17 00:00:00 2001 From: Vicamo Yang Date: Sun, 21 Sep 2014 15:24:44 +0800 Subject: [PATCH 088/114] Bug 1064231 - unify instantiation process for RIL services. r=smaug --- .../MobileConnectionArray.cpp | 23 ++++++ .../interfaces/nsIMobileConnectionService.idl | 7 ++ .../ipc/MobileConnectionIPCService.cpp | 15 ---- .../ipc/MobileConnectionIPCService.h | 5 +- dom/mobileconnection/moz.build | 1 - dom/mobilemessage/MobileMessageManager.cpp | 72 +++++++++++++++++ dom/mobilemessage/MobileMessageService.cpp | 14 ---- dom/mobilemessage/MobileMessageService.h | 11 +-- dom/mobilemessage/SmsServicesFactory.cpp | 77 ------------------- dom/mobilemessage/SmsServicesFactory.h | 31 -------- .../interfaces/nsIMmsService.idl | 8 ++ .../nsIMobileMessageDatabaseService.idl | 7 ++ .../interfaces/nsIMobileMessageService.idl | 7 ++ .../nsIRilMobileMessageDatabaseService.idl | 7 ++ .../interfaces/nsISmsService.idl | 7 ++ dom/mobilemessage/ipc/SmsIPCService.cpp | 21 +++++ dom/mobilemessage/ipc/SmsIPCService.h | 8 +- dom/mobilemessage/moz.build | 3 - dom/telephony/Telephony.cpp | 23 ++++++ dom/telephony/TelephonyFactory.cpp | 30 -------- dom/telephony/TelephonyFactory.h | 24 ------ dom/telephony/moz.build | 2 - dom/telephony/nsITelephonyService.idl | 7 ++ layout/build/nsLayoutModule.cpp | 64 +++------------ 24 files changed, 209 insertions(+), 265 deletions(-) delete mode 100644 dom/mobilemessage/SmsServicesFactory.cpp delete mode 100644 dom/mobilemessage/SmsServicesFactory.h delete mode 100644 dom/telephony/TelephonyFactory.cpp delete mode 100644 dom/telephony/TelephonyFactory.h diff --git a/dom/mobileconnection/MobileConnectionArray.cpp b/dom/mobileconnection/MobileConnectionArray.cpp index ef2fe8249878..19e7789cd46e 100644 --- a/dom/mobileconnection/MobileConnectionArray.cpp +++ b/dom/mobileconnection/MobileConnectionArray.cpp @@ -9,6 +9,13 @@ #include "mozilla/Preferences.h" #include "nsServiceManagerUtils.h" +// Service instantiation +#include "ipc/MobileConnectionIPCService.h" +#if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL) +#include "nsIGonkMobileConnectionService.h" +#endif +#include "nsXULAppAPI.h" // For XRE_GetProcessType() + using namespace mozilla::dom; NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(MobileConnectionArray, @@ -89,3 +96,19 @@ MobileConnectionArray::IndexedGetter(uint32_t aIndex, bool& aFound) return mMobileConnections[aIndex]; } + +already_AddRefed +NS_CreateMobileConnectionService() +{ + nsCOMPtr service; + + if (XRE_GetProcessType() == GeckoProcessType_Content) { + service = new mozilla::dom::mobileconnection::MobileConnectionIPCService(); + } else { +#if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL) + service = do_CreateInstance(GONK_MOBILECONNECTION_SERVICE_CONTRACTID); +#endif + } + + return service.forget(); +} diff --git a/dom/mobileconnection/interfaces/nsIMobileConnectionService.idl b/dom/mobileconnection/interfaces/nsIMobileConnectionService.idl index 5208237b67f0..e0eca9af4bc6 100644 --- a/dom/mobileconnection/interfaces/nsIMobileConnectionService.idl +++ b/dom/mobileconnection/interfaces/nsIMobileConnectionService.idl @@ -209,6 +209,13 @@ interface nsIMobileConnectionService : nsISupports nsIMobileConnection getItemByServiceId(in unsigned long serviceId); }; +%{C++ +template struct already_AddRefed; + +already_AddRefed +NS_CreateMobileConnectionService(); +%} + [scriptable, uuid(04db7331-54fe-4cf7-9347-b9481350f4c2)] interface nsIMobileConnection : nsISupports { diff --git a/dom/mobileconnection/ipc/MobileConnectionIPCService.cpp b/dom/mobileconnection/ipc/MobileConnectionIPCService.cpp index 33750475320e..4f575957a2eb 100644 --- a/dom/mobileconnection/ipc/MobileConnectionIPCService.cpp +++ b/dom/mobileconnection/ipc/MobileConnectionIPCService.cpp @@ -14,21 +14,6 @@ using namespace mozilla::dom::mobileconnection; NS_IMPL_ISUPPORTS(MobileConnectionIPCService, nsIMobileConnectionService) -StaticRefPtr sService; - -/* static */MobileConnectionIPCService* -MobileConnectionIPCService::GetSingleton() -{ - MOZ_ASSERT(NS_IsMainThread()); - - if (sService) { - return sService; - } - - sService = new MobileConnectionIPCService(); - return sService; -} - MobileConnectionIPCService::MobileConnectionIPCService() { int32_t numRil = Preferences::GetInt("ril.numRadioInterfaces", 1); diff --git a/dom/mobileconnection/ipc/MobileConnectionIPCService.h b/dom/mobileconnection/ipc/MobileConnectionIPCService.h index 7f145286979c..6f502609da00 100644 --- a/dom/mobileconnection/ipc/MobileConnectionIPCService.h +++ b/dom/mobileconnection/ipc/MobileConnectionIPCService.h @@ -19,12 +19,9 @@ public: NS_DECL_ISUPPORTS NS_DECL_NSIMOBILECONNECTIONSERVICE - static MobileConnectionIPCService* - GetSingleton(); - -private: MobileConnectionIPCService(); +private: // MOZ_FINAL suppresses -Werror,-Wdelete-non-virtual-dtor ~MobileConnectionIPCService(); diff --git a/dom/mobileconnection/moz.build b/dom/mobileconnection/moz.build index cc4ffd63f34a..416b10d2f478 100644 --- a/dom/mobileconnection/moz.build +++ b/dom/mobileconnection/moz.build @@ -18,7 +18,6 @@ EXPORTS.mozilla.dom += [ EXPORTS.mozilla.dom.mobileconnection += [ 'ipc/MobileConnectionChild.h', 'ipc/MobileConnectionIPCSerializer.h', - 'ipc/MobileConnectionIPCService.h', 'ipc/MobileConnectionParent.h', ] diff --git a/dom/mobilemessage/MobileMessageManager.cpp b/dom/mobilemessage/MobileMessageManager.cpp index b812baca8550..42c0aceedd9d 100644 --- a/dom/mobilemessage/MobileMessageManager.cpp +++ b/dom/mobilemessage/MobileMessageManager.cpp @@ -23,10 +23,23 @@ #include "nsIMmsService.h" #include "nsIMobileMessageCallback.h" #include "nsIMobileMessageDatabaseService.h" +#include "nsIMobileMessageService.h" #include "nsIObserverService.h" #include "nsISmsService.h" #include "nsServiceManagerUtils.h" // For do_GetService() +// Service instantiation +#include "ipc/SmsIPCService.h" +#include "MobileMessageService.h" +#ifdef MOZ_WIDGET_ANDROID +#include "android/MobileMessageDatabaseService.h" +#include "android/SmsService.h" +#elif defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL) +#include "nsIRilMobileMessageDatabaseService.h" +#include "gonk/SmsService.h" +#endif +#include "nsXULAppAPI.h" // For XRE_GetProcessType() + #define RECEIVED_EVENT_NAME NS_LITERAL_STRING("received") #define RETRIEVING_EVENT_NAME NS_LITERAL_STRING("retrieving") #define SENDING_EVENT_NAME NS_LITERAL_STRING("sending") @@ -686,3 +699,62 @@ MobileMessageManager::GetSmscAddress(const Optional& aServiceId, } // namespace dom } // namespace mozilla + +already_AddRefed +NS_CreateSmsService() +{ + nsCOMPtr smsService; + + if (XRE_GetProcessType() == GeckoProcessType_Content) { + smsService = SmsIPCService::GetSingleton(); + } else { +#ifdef MOZ_WIDGET_ANDROID + smsService = new SmsService(); +#elif defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL) + smsService = new SmsService(); +#endif + } + + return smsService.forget(); +} + +already_AddRefed +NS_CreateMobileMessageDatabaseService() +{ + nsCOMPtr mobileMessageDBService; + if (XRE_GetProcessType() == GeckoProcessType_Content) { + mobileMessageDBService = SmsIPCService::GetSingleton(); + } else { +#ifdef MOZ_WIDGET_ANDROID + mobileMessageDBService = new MobileMessageDatabaseService(); +#elif defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL) + mobileMessageDBService = + do_CreateInstance(RIL_MOBILE_MESSAGE_DATABASE_SERVICE_CONTRACTID); +#endif + } + + return mobileMessageDBService.forget(); +} + +already_AddRefed +NS_CreateMmsService() +{ + nsCOMPtr mmsService; + + if (XRE_GetProcessType() == GeckoProcessType_Content) { + mmsService = SmsIPCService::GetSingleton(); + } else { +#if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL) + mmsService = do_CreateInstance("@mozilla.org/mms/rilmmsservice;1"); +#endif + } + + return mmsService.forget(); +} + +already_AddRefed +NS_CreateMobileMessageService() +{ + nsCOMPtr service = new MobileMessageService(); + return service.forget(); +} diff --git a/dom/mobilemessage/MobileMessageService.cpp b/dom/mobilemessage/MobileMessageService.cpp index cb638eca4bfc..77fff9ea3019 100644 --- a/dom/mobilemessage/MobileMessageService.cpp +++ b/dom/mobilemessage/MobileMessageService.cpp @@ -14,20 +14,6 @@ namespace mobilemessage { NS_IMPL_ISUPPORTS(MobileMessageService, nsIMobileMessageService) -/* static */ StaticRefPtr MobileMessageService::sSingleton; - -/* static */ already_AddRefed -MobileMessageService::GetInstance() -{ - if (!sSingleton) { - sSingleton = new MobileMessageService(); - ClearOnShutdown(&sSingleton); - } - - nsRefPtr service = sSingleton.get(); - return service.forget(); -} - NS_IMETHODIMP MobileMessageService::CreateSmsMessage(int32_t aId, uint64_t aThreadId, diff --git a/dom/mobilemessage/MobileMessageService.h b/dom/mobilemessage/MobileMessageService.h index 5bdf30e03792..89f8ba14a517 100644 --- a/dom/mobilemessage/MobileMessageService.h +++ b/dom/mobilemessage/MobileMessageService.h @@ -5,9 +5,8 @@ #ifndef mozilla_dom_mobilemessage_MobileMessageService_h #define mozilla_dom_mobilemessage_MobileMessageService_h +#include "mozilla/Attributes.h" // For MOZ_FINAL #include "nsIMobileMessageService.h" -#include "mozilla/ClearOnShutdown.h" -#include "mozilla/StaticPtr.h" namespace mozilla { namespace dom { @@ -19,13 +18,11 @@ public: NS_DECL_ISUPPORTS NS_DECL_NSIMOBILEMESSAGESERVICE - static already_AddRefed GetInstance(); + MobileMessageService() { MOZ_COUNT_CTOR(MobileMessageService); } private: - ~MobileMessageService() {} - - static StaticRefPtr sSingleton; - + // MOZ_FINAL suppresses -Werror,-Wdelete-non-virtual-dtor + ~MobileMessageService() { MOZ_COUNT_DTOR(MobileMessageService); } }; } // namespace mobilemessage diff --git a/dom/mobilemessage/SmsServicesFactory.cpp b/dom/mobilemessage/SmsServicesFactory.cpp deleted file mode 100644 index f4466ac91405..000000000000 --- a/dom/mobilemessage/SmsServicesFactory.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "SmsServicesFactory.h" -#include "nsXULAppAPI.h" -#include "ipc/SmsIPCService.h" -#ifdef MOZ_WIDGET_ANDROID -#include "android/MobileMessageDatabaseService.h" -#include "android/SmsService.h" -#elif defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL) -#include "gonk/SmsService.h" -#endif -#include "nsServiceManagerUtils.h" - -#define RIL_MMSSERVICE_CONTRACTID "@mozilla.org/mms/rilmmsservice;1" -#define RIL_MOBILE_MESSAGE_DATABASE_SERVICE_CONTRACTID "@mozilla.org/mobilemessage/rilmobilemessagedatabaseservice;1" - -namespace mozilla { -namespace dom { -namespace mobilemessage { - -/* static */ already_AddRefed -SmsServicesFactory::CreateSmsService() -{ - nsCOMPtr smsService; - - if (XRE_GetProcessType() == GeckoProcessType_Content) { - smsService = new SmsIPCService(); - } else { -#ifdef MOZ_WIDGET_ANDROID - smsService = new SmsService(); -#elif defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL) - smsService = new SmsService(); -#endif - } - - return smsService.forget(); -} - -/* static */ already_AddRefed -SmsServicesFactory::CreateMobileMessageDatabaseService() -{ - nsCOMPtr mobileMessageDBService; - if (XRE_GetProcessType() == GeckoProcessType_Content) { - mobileMessageDBService = new SmsIPCService(); - } else { -#ifdef MOZ_WIDGET_ANDROID - mobileMessageDBService = new MobileMessageDatabaseService(); -#elif defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL) - mobileMessageDBService = do_GetService(RIL_MOBILE_MESSAGE_DATABASE_SERVICE_CONTRACTID); -#endif - } - - return mobileMessageDBService.forget(); -} - -/* static */ already_AddRefed -SmsServicesFactory::CreateMmsService() -{ - nsCOMPtr mmsService; - - if (XRE_GetProcessType() == GeckoProcessType_Content) { - mmsService = new SmsIPCService(); - } else { -#if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL) - mmsService = do_CreateInstance(RIL_MMSSERVICE_CONTRACTID); -#endif - } - - return mmsService.forget(); -} - -} // namespace mobilemessage -} // namespace dom -} // namespace mozilla diff --git a/dom/mobilemessage/SmsServicesFactory.h b/dom/mobilemessage/SmsServicesFactory.h deleted file mode 100644 index 899e49e9d56d..000000000000 --- a/dom/mobilemessage/SmsServicesFactory.h +++ /dev/null @@ -1,31 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef mozilla_dom_mobilemessage_SmsServicesFactory_h -#define mozilla_dom_mobilemessage_SmsServicesFactory_h - -#include "nsCOMPtr.h" - -class nsISmsService; -class nsIMmsService; -class nsIMobileMessageDatabaseService; - -namespace mozilla { -namespace dom { -namespace mobilemessage { - -class SmsServicesFactory -{ -public: - static already_AddRefed CreateSmsService(); - static already_AddRefed CreateMobileMessageDatabaseService(); - static already_AddRefed CreateMmsService(); -}; - -} // namespace mobilemessage -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_mobilemessage_SmsServicesFactory_h diff --git a/dom/mobilemessage/interfaces/nsIMmsService.idl b/dom/mobilemessage/interfaces/nsIMmsService.idl index 075c4153ef02..b5a2d4a6d63c 100644 --- a/dom/mobilemessage/interfaces/nsIMmsService.idl +++ b/dom/mobilemessage/interfaces/nsIMmsService.idl @@ -3,6 +3,7 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsISupports.idl" + interface nsIMobileMessageCallback; interface nsIDOMBlob; @@ -28,3 +29,10 @@ interface nsIMmsService : nsISupports in DOMString toAddress, in DOMString iccId); }; + +%{C++ +template struct already_AddRefed; + +already_AddRefed +NS_CreateMmsService(); +%} diff --git a/dom/mobilemessage/interfaces/nsIMobileMessageDatabaseService.idl b/dom/mobilemessage/interfaces/nsIMobileMessageDatabaseService.idl index 831d145bd906..ff78aa39892e 100644 --- a/dom/mobilemessage/interfaces/nsIMobileMessageDatabaseService.idl +++ b/dom/mobilemessage/interfaces/nsIMobileMessageDatabaseService.idl @@ -46,3 +46,10 @@ interface nsIMobileMessageDatabaseService : nsISupports nsICursorContinueCallback createThreadCursor(in nsIMobileMessageCursorCallback callback); }; + +%{C++ +template struct already_AddRefed; + +already_AddRefed +NS_CreateMobileMessageDatabaseService(); +%} diff --git a/dom/mobilemessage/interfaces/nsIMobileMessageService.idl b/dom/mobilemessage/interfaces/nsIMobileMessageService.idl index 320b7edb3bd9..2d4bdc08a2d1 100644 --- a/dom/mobilemessage/interfaces/nsIMobileMessageService.idl +++ b/dom/mobilemessage/interfaces/nsIMobileMessageService.idl @@ -64,3 +64,10 @@ interface nsIMobileMessageService : nsISupports [array, size_is(threadCount)] in unsigned long long threadIds, in uint32_t threadCount); }; + +%{C++ +template struct already_AddRefed; + +already_AddRefed +NS_CreateMobileMessageService(); +%} diff --git a/dom/mobilemessage/interfaces/nsIRilMobileMessageDatabaseService.idl b/dom/mobilemessage/interfaces/nsIRilMobileMessageDatabaseService.idl index 006a1c10d3f5..e708f1dcc04b 100644 --- a/dom/mobilemessage/interfaces/nsIRilMobileMessageDatabaseService.idl +++ b/dom/mobilemessage/interfaces/nsIRilMobileMessageDatabaseService.idl @@ -34,6 +34,13 @@ interface nsIRilMobileMessageDatabaseConcatenationCallback : nsISupports void notify(in nsresult aRv, in jsval aCompleteMessage); }; +%{C++ +#define RIL_MOBILE_MESSAGE_DATABASE_SERVICE_CID \ + { 0x29785f90, 0x6b5b, 0x11e2, { 0x92, 0x01, 0x3b, 0x28, 0x01, 0x70, 0xb2, 0xec } } +#define RIL_MOBILE_MESSAGE_DATABASE_SERVICE_CONTRACTID \ + "@mozilla.org/mobilemessage/rilmobilemessagedatabaseservice;1" +%} + [scriptable, uuid(0b437a5c-a2bc-11e3-bd1b-dbb173eb35f8)] interface nsIRilMobileMessageDatabaseService : nsIMobileMessageDatabaseService { diff --git a/dom/mobilemessage/interfaces/nsISmsService.idl b/dom/mobilemessage/interfaces/nsISmsService.idl index 615cedd15808..9bf7f2bfbee3 100644 --- a/dom/mobilemessage/interfaces/nsISmsService.idl +++ b/dom/mobilemessage/interfaces/nsISmsService.idl @@ -33,3 +33,10 @@ interface nsISmsService : nsISupports void getSmscAddress(in unsigned long serviceId, in nsIMobileMessageCallback request); }; + +%{C++ +template struct already_AddRefed; + +already_AddRefed +NS_CreateSmsService(); +%} diff --git a/dom/mobilemessage/ipc/SmsIPCService.cpp b/dom/mobilemessage/ipc/SmsIPCService.cpp index 57c3f8846ea2..2ef1d734e4fe 100644 --- a/dom/mobilemessage/ipc/SmsIPCService.cpp +++ b/dom/mobilemessage/ipc/SmsIPCService.cpp @@ -31,6 +31,9 @@ const char* kObservedPrefs[] = { // TODO: Bug 767082 - WebSMS: sSmsChild leaks at shutdown PSmsChild* gSmsChild; +// SmsIPCService is owned by nsLayoutModule. +SmsIPCService* sSingleton = nullptr; + PSmsChild* GetSmsChild() { @@ -101,6 +104,19 @@ NS_IMPL_ISUPPORTS(SmsIPCService, nsIMobileMessageDatabaseService, nsIObserver) +/* static */ already_AddRefed +SmsIPCService::GetSingleton() +{ + MOZ_ASSERT(NS_IsMainThread()); + + if (!sSingleton) { + sSingleton = new SmsIPCService(); + } + + nsRefPtr service = sSingleton; + return service.forget(); +} + SmsIPCService::SmsIPCService() { Preferences::AddStrongObservers(this, kObservedPrefs); @@ -108,6 +124,11 @@ SmsIPCService::SmsIPCService() mSmsDefaultServiceId = getDefaultServiceId(kPrefSmsDefaultServiceId); } +SmsIPCService::~SmsIPCService() +{ + sSingleton = nullptr; +} + /* * Implementation of nsIObserver. */ diff --git a/dom/mobilemessage/ipc/SmsIPCService.h b/dom/mobilemessage/ipc/SmsIPCService.h index 2376af68e937..0cebfd7d12c4 100644 --- a/dom/mobilemessage/ipc/SmsIPCService.h +++ b/dom/mobilemessage/ipc/SmsIPCService.h @@ -30,10 +30,14 @@ public: NS_DECL_NSIMOBILEMESSAGEDATABASESERVICE NS_DECL_NSIOBSERVER - SmsIPCService(); + static already_AddRefed + GetSingleton(); private: - ~SmsIPCService() {} + SmsIPCService(); + + // MOZ_FINAL suppresses -Werror,-Wdelete-non-virtual-dtor + ~SmsIPCService(); uint32_t mMmsDefaultServiceId; uint32_t mSmsDefaultServiceId; diff --git a/dom/mobilemessage/moz.build b/dom/mobilemessage/moz.build index b3d61af7733b..e0777fb92609 100644 --- a/dom/mobilemessage/moz.build +++ b/dom/mobilemessage/moz.build @@ -13,8 +13,6 @@ EXPORTS.mozilla.dom.mobilemessage += [ 'Constants.h', # Required by almost all cpp files 'ipc/SmsChild.h', 'ipc/SmsParent.h', - 'MobileMessageService.h', # Required by nsLayoutModule.cpp - 'SmsServicesFactory.h', # Required by nsLayoutModule.cpp 'Types.h', # Required by IPDL SmsTypes.h ] @@ -62,7 +60,6 @@ UNIFIED_SOURCES += [ 'MobileMessageService.cpp', 'MobileMessageThread.cpp', 'SmsMessage.cpp', - 'SmsServicesFactory.cpp', ] IPDL_SOURCES += [ diff --git a/dom/telephony/Telephony.cpp b/dom/telephony/Telephony.cpp index d58f9813f3bd..2460cc870d2a 100644 --- a/dom/telephony/Telephony.cpp +++ b/dom/telephony/Telephony.cpp @@ -26,6 +26,13 @@ #include "TelephonyCallGroup.h" #include "TelephonyCallId.h" +// Service instantiation +#include "ipc/TelephonyIPCService.h" +#if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL) +#include "nsIGonkTelephonyService.h" +#endif +#include "nsXULAppAPI.h" // For XRE_GetProcessType() + using namespace mozilla::dom; using mozilla::ErrorResult; @@ -738,3 +745,19 @@ Telephony::EnqueueEnumerationAck(const nsAString& aType) NS_WARNING("Failed to dispatch to current thread!"); } } + +already_AddRefed +NS_CreateTelephonyService() +{ + nsCOMPtr service; + + if (XRE_GetProcessType() == GeckoProcessType_Content) { + service = new mozilla::dom::telephony::TelephonyIPCService(); + } else { +#if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL) + service = do_CreateInstance(GONK_TELEPHONY_SERVICE_CONTRACTID); +#endif + } + + return service.forget(); +} diff --git a/dom/telephony/TelephonyFactory.cpp b/dom/telephony/TelephonyFactory.cpp deleted file mode 100644 index b5b9262a18fd..000000000000 --- a/dom/telephony/TelephonyFactory.cpp +++ /dev/null @@ -1,30 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "mozilla/dom/telephony/TelephonyFactory.h" -#if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL) -#include "nsIGonkTelephonyService.h" -#endif -#include "nsServiceManagerUtils.h" -#include "nsXULAppAPI.h" -#include "ipc/TelephonyIPCService.h" - -USING_TELEPHONY_NAMESPACE - -/* static */ already_AddRefed -TelephonyFactory::CreateTelephonyService() -{ - nsCOMPtr service; - - if (XRE_GetProcessType() == GeckoProcessType_Content) { - service = new TelephonyIPCService(); -#if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL) - } else { - service = do_CreateInstance(GONK_TELEPHONY_SERVICE_CONTRACTID); -#endif - } - - return service.forget(); -} diff --git a/dom/telephony/TelephonyFactory.h b/dom/telephony/TelephonyFactory.h deleted file mode 100644 index 96a529c1a22c..000000000000 --- a/dom/telephony/TelephonyFactory.h +++ /dev/null @@ -1,24 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef mozilla_dom_telephony_TelephonyFactory_h -#define mozilla_dom_telephony_TelephonyFactory_h - -#include "nsCOMPtr.h" -#include "mozilla/dom/telephony/TelephonyCommon.h" - -class nsITelephonyService; - -BEGIN_TELEPHONY_NAMESPACE - -class TelephonyFactory -{ -public: - static already_AddRefed CreateTelephonyService(); -}; - -END_TELEPHONY_NAMESPACE - -#endif // mozilla_dom_telephony_TelephonyFactory_h diff --git a/dom/telephony/moz.build b/dom/telephony/moz.build index f4d563ecaab6..2a27d76b33fe 100644 --- a/dom/telephony/moz.build +++ b/dom/telephony/moz.build @@ -22,7 +22,6 @@ EXPORTS.mozilla.dom.telephony += [ 'ipc/TelephonyChild.h', 'ipc/TelephonyParent.h', 'TelephonyCommon.h', - 'TelephonyFactory.h', ] UNIFIED_SOURCES += [ @@ -34,7 +33,6 @@ UNIFIED_SOURCES += [ 'TelephonyCall.cpp', 'TelephonyCallGroup.cpp', 'TelephonyCallId.cpp', - 'TelephonyFactory.cpp', ] IPDL_SOURCES += [ diff --git a/dom/telephony/nsITelephonyService.idl b/dom/telephony/nsITelephonyService.idl index e8ca89b74d5a..e0a028550a63 100644 --- a/dom/telephony/nsITelephonyService.idl +++ b/dom/telephony/nsITelephonyService.idl @@ -265,3 +265,10 @@ interface nsITelephonyService : nsISupports attribute bool microphoneMuted; attribute bool speakerEnabled; }; + +%{C++ +template struct already_AddRefed; + +already_AddRefed +NS_CreateTelephonyService(); +%} diff --git a/layout/build/nsLayoutModule.cpp b/layout/build/nsLayoutModule.cpp index 27b46de6a314..09e2e3dda387 100644 --- a/layout/build/nsLayoutModule.cpp +++ b/layout/build/nsLayoutModule.cpp @@ -125,15 +125,6 @@ using mozilla::dom::gonk::AudioManager; using mozilla::system::nsVolumeService; #endif -#ifdef MOZ_B2G_RIL -#include "nsIMobileConnectionService.h" -#include "mozilla/dom/mobileconnection/MobileConnectionIPCService.h" -using mozilla::dom::mobileconnection::MobileConnectionIPCService; -#ifdef MOZ_WIDGET_GONK -#include "nsIGonkMobileConnectionService.h" -#endif -#endif - #include "AudioChannelAgent.h" using mozilla::dom::AudioChannelAgent; @@ -225,10 +216,9 @@ static void Shutdown(); #include "nsCSPContext.h" #include "nsISmsService.h" #include "nsIMmsService.h" +#include "nsIMobileConnectionService.h" #include "nsIMobileMessageService.h" #include "nsIMobileMessageDatabaseService.h" -#include "mozilla/dom/mobilemessage/MobileMessageService.h" -#include "mozilla/dom/mobilemessage/SmsServicesFactory.h" #include "nsIPowerManagerService.h" #include "nsIAlarmHalService.h" #include "nsIMediaManager.h" @@ -243,7 +233,6 @@ static void Shutdown(); #include "mozilla/dom/time/TimeService.h" #include "StreamingProtocolService.h" -#include "mozilla/dom/telephony/TelephonyFactory.h" #include "nsITelephonyService.h" #ifdef MOZ_WIDGET_GONK @@ -255,8 +244,6 @@ static void Shutdown(); using namespace mozilla; using namespace mozilla::dom; -using namespace mozilla::dom::mobilemessage; -using namespace mozilla::dom::telephony; using mozilla::dom::alarm::AlarmHalService; using mozilla::dom::power::PowerManagerService; using mozilla::dom::quota::QuotaManager; @@ -330,14 +317,12 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsHapticFeedback) #endif #endif NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(ThirdPartyUtil, Init) -NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsISmsService, - SmsServicesFactory::CreateSmsService) -NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIMmsService, - SmsServicesFactory::CreateMmsService) +NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsISmsService, NS_CreateSmsService) +NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIMmsService, NS_CreateMmsService) NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIMobileMessageService, - MobileMessageService::GetInstance) + NS_CreateMobileMessageService) NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIMobileMessageDatabaseService, - SmsServicesFactory::CreateMobileMessageDatabaseService) + NS_CreateMobileMessageDatabaseService) NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIPowerManagerService, PowerManagerService::GetInstance) NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIAlarmHalService, @@ -363,8 +348,10 @@ NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsVolumeService, #endif NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIMediaManagerService, MediaManager::GetInstance) +NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIMobileConnectionService, + NS_CreateMobileConnectionService) NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsITelephonyService, - TelephonyFactory::CreateTelephonyService) + NS_CreateTelephonyService) //----------------------------------------------------------------------------- @@ -806,9 +793,7 @@ NS_DEFINE_NAMED_CID(TELEPHONY_SERVICE_CID); NS_DEFINE_NAMED_CID(GECKO_MEDIA_PLUGIN_SERVICE_CID); -#ifdef MOZ_B2G_RIL NS_DEFINE_NAMED_CID(NS_MOBILE_CONNECTION_SERVICE_CID); -#endif static nsresult CreateWindowCommandTableConstructor(nsISupports *aOuter, @@ -938,31 +923,6 @@ nsEditingCommandTableConstructor(nsISupports *aOuter, REFNSIID aIID, return commandTable->QueryInterface(aIID, aResult); } -#ifdef MOZ_B2G_RIL - -static nsresult -nsIMobileConnectionServiceConstructor(nsISupports *aOuter, REFNSIID aIID, - void **aResult) -{ - nsCOMPtr service; - - if (XRE_GetProcessType() == GeckoProcessType_Content) { - service = MobileConnectionIPCService::GetSingleton(); - } else { -#ifdef MOZ_WIDGET_GONK - service = do_CreateInstance(GONK_MOBILECONNECTION_SERVICE_CONTRACTID); -#endif - } - - if (!service) { - return NS_ERROR_NOT_AVAILABLE; - } - - return service->QueryInterface(aIID, aResult); -} - -#endif - static const mozilla::Module::CIDEntry kLayoutCIDs[] = { XPCONNECT_CIDENTRIES #ifdef DEBUG @@ -1118,9 +1078,7 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = { { &kNS_ACCESSIBILITY_SERVICE_CID, false, nullptr, CreateA11yService }, #endif { &kTELEPHONY_SERVICE_CID, false, nullptr, nsITelephonyServiceConstructor }, -#ifdef MOZ_B2G_RIL - { &kNS_MOBILE_CONNECTION_SERVICE_CID, true, NULL, nsIMobileConnectionServiceConstructor }, -#endif + { &kNS_MOBILE_CONNECTION_SERVICE_CID, false, NULL, nsIMobileConnectionServiceConstructor }, { nullptr } }; @@ -1278,9 +1236,7 @@ static const mozilla::Module::ContractIDEntry kLayoutContracts[] = { #endif { TELEPHONY_SERVICE_CONTRACTID, &kTELEPHONY_SERVICE_CID }, { "@mozilla.org/gecko-media-plugin-service;1", &kGECKO_MEDIA_PLUGIN_SERVICE_CID }, -#ifdef MOZ_B2G_RIL { NS_MOBILE_CONNECTION_SERVICE_CONTRACTID, &kNS_MOBILE_CONNECTION_SERVICE_CID }, -#endif { nullptr } }; @@ -1303,9 +1259,7 @@ static const mozilla::Module::CategoryEntry kLayoutCategories[] = { #ifdef MOZ_B2G_BT { "profile-after-change", "Bluetooth Service", BLUETOOTHSERVICE_CONTRACTID }, #endif -#ifdef MOZ_B2G_RIL { "profile-after-change", "MobileConnection Service", NS_MOBILE_CONNECTION_SERVICE_CONTRACTID }, -#endif { nullptr } }; From 78a900e1303d683c2569ebe39e5761066260ac5f Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Sun, 21 Sep 2014 03:00:49 -0700 Subject: [PATCH 089/114] Bumping gaia.json for 1 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/95f45aa5b9dd Author: Dale Harvey Desc: Bug 1031560 - Add a 750ms delay for taking screenshots. r=timdream --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 6726efc070e9..ab76a268b25d 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "995979ab5d825dacc4e3dba6338d45a4f54040a3", + "revision": "95f45aa5b9ddc94c990785a7d73bfe44b0082e56", "repo_path": "/integration/gaia-central" } From 51ba1c55822da782e802ceccbd39bcfb318efe32 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Sun, 21 Sep 2014 03:06:59 -0700 Subject: [PATCH 090/114] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index f453190abed0..408fd80f51da 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index f96ae9859876..82bd39ed1623 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index e1dba0ad4f15..d0e9b9417d3f 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 61e06cf97c14..da0814c97767 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index f96ae9859876..82bd39ed1623 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index e6964f35f652..72e9009c260b 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 67d1ec809247..ab78e71d189c 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 7777bc338764..e0ef61922a33 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 4de262e3b2c9..e5b103bccd17 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 72d59cae324a..317c49f0153a 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index a2372635d3fc..20084fe65bb0 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From c712daad9475ef76bdc1439241d7d40f95730703 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Sun, 21 Sep 2014 04:00:48 -0700 Subject: [PATCH 091/114] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ======== https://hg.mozilla.org/integration/gaia-central/rev/c758727ab927 Author: Timothy Guan-tin Chien Desc: Merge pull request #24248 from ddrmanxbxfr/bug_1056481 Bug 1056481 - Update reference to CDN to HTTPS, r=timdream ======== https://hg.mozilla.org/integration/gaia-central/rev/88314f2d7891 Author: Mathieu Rhéaume Desc: Bug 1056481 - Update reference to CDN to HTTPS --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index ab76a268b25d..13658ae35518 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "95f45aa5b9ddc94c990785a7d73bfe44b0082e56", + "revision": "c758727ab927f089212050e0c304a2fefbb8f7f3", "repo_path": "/integration/gaia-central" } From 879b4a38c6766f11f2ec03512faf16dad7b6f9a0 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Sun, 21 Sep 2014 04:06:58 -0700 Subject: [PATCH 092/114] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 408fd80f51da..1cb499f94a11 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 82bd39ed1623..82c7b0854298 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index d0e9b9417d3f..2aa9ede4e426 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index da0814c97767..649b8630e1ea 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 82bd39ed1623..82c7b0854298 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index 72e9009c260b..f1396c348088 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index ab78e71d189c..23c438374c9b 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index e0ef61922a33..62883b8a2d00 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index e5b103bccd17..bbf4294489f8 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 317c49f0153a..c41f64268bde 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 20084fe65bb0..bbb1d991ea36 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From c558ffdbcc7ea71e75cb5689b154f60a49902361 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Sun, 21 Sep 2014 18:05:47 -0700 Subject: [PATCH 093/114] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/f9afa260d5a1 Author: Kevin Grandon Desc: Merge pull request #24148 from KevinGrandon/bug_1068888_places_defer_save_appload Bug 1068888 - [Rocketbar] Debounce place saving until timeout or apploaded ======== https://hg.mozilla.org/integration/gaia-central/rev/d7826e288d26 Author: Kevin Grandon Desc: Bug 1068888 - [Rocketbar] Debounce place saving until timeout or apploaded r=daleharvey --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 13658ae35518..ccea0f842fc2 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "c758727ab927f089212050e0c304a2fefbb8f7f3", + "revision": "f9afa260d5a19194d0cf6d984e95d2d9fbafaf4e", "repo_path": "/integration/gaia-central" } From cdd8083d6ebc5f0dcd17e376c1fc1a03572e46aa Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Sun, 21 Sep 2014 18:11:56 -0700 Subject: [PATCH 094/114] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 1cb499f94a11..2affdbf48786 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 82c7b0854298..fe1aaef894ab 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 2aa9ede4e426..33725f42eb42 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 649b8630e1ea..f63b40d4d9b5 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 82c7b0854298..fe1aaef894ab 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index f1396c348088..b90b48a71cf7 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 23c438374c9b..2eaa4eee3bca 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 62883b8a2d00..c37b4d27b6b8 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index bbf4294489f8..6015b0febb8a 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index c41f64268bde..0d94b9128ee8 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index bbb1d991ea36..cee95b393063 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From fff047fa6f91601fea7877e7b73230e0df88ec3a Mon Sep 17 00:00:00 2001 From: Vicamo Yang Date: Mon, 22 Sep 2014 10:02:44 +0800 Subject: [PATCH 095/114] Bug 1063304: (follow-up) explicit clobber. r=me --- CLOBBER | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CLOBBER b/CLOBBER index 58a684de5c10..e54db0523951 100644 --- a/CLOBBER +++ b/CLOBBER @@ -22,4 +22,4 @@ # changes to stick? As of bug 928195, this shouldn't be necessary! Please # don't change CLOBBER for WebIDL changes any more. -The backout of bug 994190 needed a clobber. +Bug 1063304 moved IPDL PMobileConnection into its own namespace and needed a clobber. From 496ac80548413ad771885231052ce1140688023d Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Sun, 21 Sep 2014 20:00:51 -0700 Subject: [PATCH 096/114] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/b0ee9921f49a Author: Zibi Braniecki Desc: Merge pull request #23829 from zbraniecki/1064561-clean-up-l10n-id-on-nodes-witch-child-nodes Bug 1053629 - Update nodes with l10n-id's to not have children nodes. r=stas, crdlc, ehung, jmfc, bfrancis ======== https://hg.mozilla.org/integration/gaia-central/rev/19fa643fe891 Author: Zbigniew Braniecki Desc: Bug 1053629 - Update nodes with l10n-id's to not have children nodes --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index ccea0f842fc2..28e47818b084 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "f9afa260d5a19194d0cf6d984e95d2d9fbafaf4e", + "revision": "b0ee9921f49a42463ec72f9531e73c98b587dd68", "repo_path": "/integration/gaia-central" } From 99c9f87b965ee008a58a57b27a7e900d8bf6f8ac Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Sun, 21 Sep 2014 20:07:00 -0700 Subject: [PATCH 097/114] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 2affdbf48786..95409ee892e3 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index fe1aaef894ab..1877fcfae8a3 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 33725f42eb42..77bc1d65edeb 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index f63b40d4d9b5..8ccc79308238 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index fe1aaef894ab..1877fcfae8a3 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index b90b48a71cf7..d4228b4d1bce 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 2eaa4eee3bca..7d92d5200018 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index c37b4d27b6b8..f2365c7c0979 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 6015b0febb8a..b0d02a834726 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 0d94b9128ee8..84cf744d2030 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index cee95b393063..a282b36037d6 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From 44e482d0d73d25ad68e3baab9ead0dfe63b2bdec Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Sun, 21 Sep 2014 21:15:55 -0700 Subject: [PATCH 098/114] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/0d9a39491e44 Author: steveck-chung Desc: Merge pull request #23564 from jpruden92/bug836690-sms Bug 836690 - [SMS] Implement temporary in App message informing the user that they have started another SMS packet. r=steveck-chung ======== https://hg.mozilla.org/integration/gaia-central/rev/182d02aa89d4 Author: jprudencio Desc: Bug 836690 - [SMS] Implement temporary in App message informing the user that they have started another SMS packet --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 28e47818b084..af892a69dad8 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "b0ee9921f49a42463ec72f9531e73c98b587dd68", + "revision": "0d9a39491e4450a796cba284df0dde16d8e8799c", "repo_path": "/integration/gaia-central" } From 9523edac181b5bb2db977388d77923eb895d63f8 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Sun, 21 Sep 2014 21:22:06 -0700 Subject: [PATCH 099/114] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 95409ee892e3..0f221e5e7bd8 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 1877fcfae8a3..7a8ce96a0a68 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 77bc1d65edeb..567ef92e1d43 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 8ccc79308238..6deed2591335 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 1877fcfae8a3..7a8ce96a0a68 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index d4228b4d1bce..8ad1a57ef8ec 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 7d92d5200018..71ae2271d374 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index f2365c7c0979..d636be23f519 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index b0d02a834726..2eef3c74d021 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 84cf744d2030..8d9e7f64a841 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index a282b36037d6..5038156ddaa6 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From b3ebf247e4d826771ab1d487b77d4afc4061c504 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Sun, 21 Sep 2014 21:45:55 -0700 Subject: [PATCH 100/114] Bumping gaia.json for 1 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/b8eec55b4929 Author: nigelb Desc: Revert "Merge pull request #24127 from ddrmanxbxfr/bug_1062829" This reverts commit a416d1e2c1f82631de19ba476cb110304d0105c4, reversing changes made to 3563ddca35a52e7a533dcfc7996e74b78c6e36c8. --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index af892a69dad8..a3d917797100 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "0d9a39491e4450a796cba284df0dde16d8e8799c", + "revision": "b8eec55b492985012cd623fa22b55bd6a8383d29", "repo_path": "/integration/gaia-central" } From 08368a3b01b575ea075e41f367dafe65a8beca09 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Sun, 21 Sep 2014 21:52:05 -0700 Subject: [PATCH 101/114] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 0f221e5e7bd8..7c252dab5899 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 7a8ce96a0a68..3eac4d021273 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 567ef92e1d43..90633f676519 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 6deed2591335..dcdba61f1e67 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 7a8ce96a0a68..3eac4d021273 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index 8ad1a57ef8ec..1b17b27a5c26 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 71ae2271d374..4f76c0a6c0bf 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index d636be23f519..4e184755947a 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 2eef3c74d021..e85cd7eb304a 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 8d9e7f64a841..b0064e88a4db 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 5038156ddaa6..a8dda5723db3 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From c1dadf510e761ee418fb75cb79ec9f0144027b94 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Sun, 21 Sep 2014 22:30:49 -0700 Subject: [PATCH 102/114] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/28ec60b9e1eb Author: gasolin Desc: Merge pull request #24201 from gasolin/issue-1064898 Bug 1064898 - Time picker is not displaying AM/PM for 12 hours format af..., r=alive ======== https://hg.mozilla.org/integration/gaia-central/rev/aacb637b1d30 Author: gasolin Desc: Bug 1064898 - Time picker is not displaying AM/PM for 12 hours format after change locale --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index a3d917797100..a1a1083b0207 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "b8eec55b492985012cd623fa22b55bd6a8383d29", + "revision": "28ec60b9e1ebe0af79d2bed3e978ec90dbf1b847", "repo_path": "/integration/gaia-central" } From 15c03f4769a6793651848242b05413db45bf4e5b Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Sun, 21 Sep 2014 22:32:36 -0700 Subject: [PATCH 103/114] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 7c252dab5899..670ea1dbd4d7 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 3eac4d021273..f4f887a5796a 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 90633f676519..e02e3e0c2d0c 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index dcdba61f1e67..c109e3e42c6c 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 3eac4d021273..f4f887a5796a 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index 1b17b27a5c26..af1d2cbcef9f 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 4f76c0a6c0bf..968e30307092 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 4e184755947a..be82afedbdf4 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index e85cd7eb304a..79f8ac4f996c 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index b0064e88a4db..27a94987dbda 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index a8dda5723db3..a75db2732acd 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From 669ab90e8a86509c4794a9479ad64231f4df8af9 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Sun, 21 Sep 2014 23:00:49 -0700 Subject: [PATCH 104/114] Bumping gaia.json for 4 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/627341308031 Author: Ian Liu Desc: Merge pull request #23881 from ian-liu/settings/bug1058419_can_change_default_storage_to_sdcard_while_no_card_in_slot Bug 1058419 - [Devices][Storage][Flame] SD card is an option for default media location when no SD card inserted, r=ej ======== https://hg.mozilla.org/integration/gaia-central/rev/8f2ef15bb7d8 Author: ian-liu Desc: Bug 1058419 - [Devices][Storage][Flame] SD card is an option for default media location when no SD card inserted ======== https://hg.mozilla.org/integration/gaia-central/rev/ae74248f585b Author: Yi-Fan Liao Desc: Merge pull request #24203 from begeeben/1014605_cannot_add_a_rtsp_shortcut Bug 1014605 - [Browser][V2.0] Cannot add a RTSP shortcut on homescreen, r=crdlc ======== https://hg.mozilla.org/integration/gaia-central/rev/6fc07bc0ef92 Author: Yi-Fan Liao Desc: Bug 1014605 - [Browser][V2.0] Cannot add a RTSP shortcut on homescreen * Add rtsp url support in the manifest.webapp of the bookmark app. --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index a1a1083b0207..a6781a63b75b 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "28ec60b9e1ebe0af79d2bed3e978ec90dbf1b847", + "revision": "627341308031c17d87b45030c65458647175ad4a", "repo_path": "/integration/gaia-central" } From 468874ea0c8a5e1045adf8003ac539842f2abd8c Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Sun, 21 Sep 2014 23:06:59 -0700 Subject: [PATCH 105/114] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 670ea1dbd4d7..1bc555fbab0b 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index f4f887a5796a..ba39f29686f5 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index e02e3e0c2d0c..4f913755f698 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index c109e3e42c6c..453519294f17 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index f4f887a5796a..ba39f29686f5 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index af1d2cbcef9f..1a930f03e2c8 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 968e30307092..80f1048aa839 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index be82afedbdf4..1f28c7e8d6f1 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 79f8ac4f996c..bac6e22c2ff2 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 27a94987dbda..60e7be1109da 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index a75db2732acd..369c4d6d35a8 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From 1c169d3df1d181bc5a48ae0e079a46603916e822 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Sun, 21 Sep 2014 23:45:53 -0700 Subject: [PATCH 106/114] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/4c92a31418ae Author: Yuren Ju Desc: Merge pull request #23783 from sudheesh001/Patch_1061577 Fixes Bug 1061577, Clears the blocker for other jshint error bugs in tests folder r=@yurenju ======== https://hg.mozilla.org/integration/gaia-central/rev/734f2a97fbea Author: sudheesh001 Desc: Fixes Bug 1061577, clears blocker for jshint in tests folder. --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index a6781a63b75b..a87ef2d57ba5 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "627341308031c17d87b45030c65458647175ad4a", + "revision": "4c92a31418ae94a1c4418828ddb3b64b2073ee80", "repo_path": "/integration/gaia-central" } From eb1fe1024a98a730aad8824c0fb859a7a214bc17 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Sun, 21 Sep 2014 23:52:05 -0700 Subject: [PATCH 107/114] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 1bc555fbab0b..572d15f5e6a3 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index ba39f29686f5..a156f14baee4 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 4f913755f698..e1e896410c8a 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 453519294f17..fd9e7beb9012 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index ba39f29686f5..a156f14baee4 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index 1a930f03e2c8..d9094268ef82 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 80f1048aa839..61a34223a96f 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 1f28c7e8d6f1..b71a71c20ccb 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index bac6e22c2ff2..fa684514abe6 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 60e7be1109da..350afbb0dc49 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 369c4d6d35a8..f02b007591ab 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From 221dc66e581de612b3a47f4dee5a1ecd21af7d18 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Mon, 22 Sep 2014 00:45:58 -0700 Subject: [PATCH 108/114] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/4a2a66008181 Author: RickyChien Desc: Merge pull request #24159 from RickyChien/bug-1050709 Bug 1050709 - execute preference.js in pre-app.js r=@yurenju ======== https://hg.mozilla.org/integration/gaia-central/rev/2340bc7c3179 Author: Ricky Chien Desc: Bug 1050709 - execute preference.js in pre-app.js --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index a87ef2d57ba5..4968c69ee039 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "4c92a31418ae94a1c4418828ddb3b64b2073ee80", + "revision": "4a2a660081819215e31b97ea612a582f6829a16d", "repo_path": "/integration/gaia-central" } From 4512d8f28f851143067224d30dd89bc203dc47ba Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Mon, 22 Sep 2014 00:51:39 -0700 Subject: [PATCH 109/114] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 572d15f5e6a3..2c5d144358d6 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index a156f14baee4..1f1a5f820733 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index e1e896410c8a..0cfd1dc7b846 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index fd9e7beb9012..ebf35f4eb5a6 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index a156f14baee4..1f1a5f820733 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index d9094268ef82..122187fb1e1a 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 61a34223a96f..95a29b19df1d 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index b71a71c20ccb..80efed12576a 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index fa684514abe6..483086c49b4d 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 350afbb0dc49..2daba909a2c7 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index f02b007591ab..0ed2e0dbc873 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From d9c20bf1166964b933d6149ba1333cc9ecf9cac6 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Mon, 22 Sep 2014 01:30:47 -0700 Subject: [PATCH 110/114] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/a491e07757d7 Author: lissyx Desc: Merge pull request #24216 from lissyx/bug1068860 Bug 1068860 - Allow ModalDialog to display pure strings r=gandalf ======== https://hg.mozilla.org/integration/gaia-central/rev/d91ea3143e02 Author: Alexandre Lissy Desc: Bug 1068860 - Allow ModalDialog to display pure strings r=gandalf We may need to have to display strings that are not localized and for which it does not make sense to have localization at all. This happens for network-generated messages that we have to display to the user, on a CDMA network for example. --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 4968c69ee039..ed82acaf5df4 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "4a2a660081819215e31b97ea612a582f6829a16d", + "revision": "a491e07757d721d4bea7302cfbb2b18460a3820d", "repo_path": "/integration/gaia-central" } From 38b09f15c893b9cca173c9177014aa0eb32ec34c Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Mon, 22 Sep 2014 01:36:58 -0700 Subject: [PATCH 111/114] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 2c5d144358d6..43d3948923d9 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 1f1a5f820733..028e7b6e4f50 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 0cfd1dc7b846..f3959b8799a8 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index ebf35f4eb5a6..7beaecd0401c 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 1f1a5f820733..028e7b6e4f50 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index 122187fb1e1a..04d553c74230 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 95a29b19df1d..5f82295f2901 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 80efed12576a..78b82a80a951 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 483086c49b4d..fa5e1a4b0c8f 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 2daba909a2c7..d2c2ea17977c 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 0ed2e0dbc873..2b339a59e806 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From 5eb0402620e4d6dee645557fd56ebd092faf8a54 Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Mon, 22 Sep 2014 12:43:02 +0200 Subject: [PATCH 112/114] Backed out changeset 422fd81a4118 (bug 1032125) for causing regressions / Bug 1070850 --- dom/ipc/ContentParent.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 0b340e648c21..7019b0e74957 100755 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -3681,12 +3681,6 @@ ContentParent::DoSendAsyncMessage(JSContext* aCx, if (aCpows && !GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) { return false; } -#ifdef MOZ_NUWA_PROCESS - if (IsNuwaProcess() && IsNuwaReady()) { - // Nuwa won't receive frame messages after it is frozen. - return true; - } -#endif return SendAsyncMessage(nsString(aMessage), data, cpows, Principal(aPrincipal)); } From 1287213a1873837b2621c17aaa5794c6e1ec3357 Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Mon, 22 Sep 2014 12:45:22 +0200 Subject: [PATCH 113/114] Backed out changeset e193cf8cb616 (bug 1032125) for causing regressions --- dom/storage/DOMStorageIPC.cpp | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/dom/storage/DOMStorageIPC.cpp b/dom/storage/DOMStorageIPC.cpp index eb8726705eb5..26dc2d540790 100644 --- a/dom/storage/DOMStorageIPC.cpp +++ b/dom/storage/DOMStorageIPC.cpp @@ -589,15 +589,8 @@ DOMStorageDBParent::Observe(const char* aTopic, const nsACString& aScopePrefix) { if (mIPCOpen) { -#ifdef MOZ_NUWA_PROCESS - if (!(static_cast(Manager())->IsNuwaProcess() && - ContentParent::IsNuwaReady())) { -#endif - mozilla::unused << SendObserve(nsDependentCString(aTopic), - nsCString(aScopePrefix)); -#ifdef MOZ_NUWA_PROCESS - } -#endif + mozilla::unused << SendObserve(nsDependentCString(aTopic), + nsCString(aScopePrefix)); } return NS_OK; From 54645ad792553bc163aaa59ed467ecb24fbc5134 Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Mon, 22 Sep 2014 12:45:48 +0200 Subject: [PATCH 114/114] Backed out changeset 0b73bd6d5d9c (bug 1032125) for causing regressions --- dom/ipc/ContentParent.cpp | 3 --- dom/ipc/ContentParent.h | 5 ----- ipc/glue/MessageLink.cpp | 22 ---------------------- ipc/glue/MessageLink.h | 3 --- 4 files changed, 33 deletions(-) diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 7019b0e74957..eabea5e8d74b 100755 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -341,7 +341,6 @@ namespace mozilla { namespace dom { #ifdef MOZ_NUWA_PROCESS -int32_t ContentParent::sNuwaPid = 0; bool ContentParent::sNuwaReady = false; #endif @@ -587,7 +586,6 @@ ContentParent::RunNuwaProcess() /* aIsNuwaProcess = */ true); nuwaProcess->Init(); #ifdef MOZ_NUWA_PROCESS - sNuwaPid = nuwaProcess->Pid(); sNuwaReady = false; #endif return nuwaProcess.forget(); @@ -1989,7 +1987,6 @@ ContentParent::~ContentParent() #ifdef MOZ_NUWA_PROCESS if (IsNuwaProcess()) { sNuwaReady = false; - sNuwaPid = 0; } #endif } diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h index 903a8188d800..736dab0fe965 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -79,10 +79,6 @@ class ContentParent MOZ_FINAL : public PContentParent public: #ifdef MOZ_NUWA_PROCESS - static int32_t NuwaPid() { - return sNuwaPid; - } - static bool IsNuwaReady() { return sNuwaReady; } @@ -716,7 +712,6 @@ private: #endif #ifdef MOZ_NUWA_PROCESS - static int32_t sNuwaPid; static bool sNuwaReady; #endif }; diff --git a/ipc/glue/MessageLink.cpp b/ipc/glue/MessageLink.cpp index 7414082678b9..1c5ddeef6727 100644 --- a/ipc/glue/MessageLink.cpp +++ b/ipc/glue/MessageLink.cpp @@ -13,7 +13,6 @@ #ifdef MOZ_NUWA_PROCESS #include "ipc/Nuwa.h" #include "mozilla/Preferences.h" -#include "mozilla/dom/ContentParent.h" #endif #include "mozilla/Assertions.h" @@ -71,9 +70,6 @@ ProcessLink::ProcessLink(MessageChannel *aChan) , mTransport(nullptr) , mIOLoop(nullptr) , mExistingListener(nullptr) -#ifdef MOZ_NUWA_PROCESS - , mIsToNuwaProcess(false) -#endif { } @@ -172,20 +168,6 @@ ProcessLink::SendMessage(Message *msg) mChan->AssertWorkerThread(); mChan->mMonitor->AssertCurrentThreadOwns(); -#ifdef MOZ_NUWA_PROCESS - if (mIsToNuwaProcess && mozilla::dom::ContentParent::IsNuwaReady()) { - switch (msg->type()) { - case mozilla::dom::PContent::Msg_NuwaFork__ID: - case mozilla::dom::PContent::Reply_AddNewProcess__ID: - case mozilla::dom::PContent::Msg_NotifyPhoneStateChange__ID: - case GOODBYE_MESSAGE_TYPE: - break; - default: - MOZ_CRASH(); - } - } -#endif - mIOLoop->PostTask( FROM_HERE, NewRunnableMethod(mTransport, &Transport::Send, msg)); @@ -378,10 +360,6 @@ ProcessLink::OnChannelConnected(int32_t peer_pid) if (mExistingListener) mExistingListener->OnChannelConnected(peer_pid); -#ifdef MOZ_NUWA_PROCESS - mIsToNuwaProcess = (peer_pid == mozilla::dom::ContentParent::NuwaPid()); -#endif - if (notifyChannel) { mChan->OnChannelConnected(peer_pid); } diff --git a/ipc/glue/MessageLink.h b/ipc/glue/MessageLink.h index 42535c02c73b..c069112f6c11 100644 --- a/ipc/glue/MessageLink.h +++ b/ipc/glue/MessageLink.h @@ -170,9 +170,6 @@ class ProcessLink Transport* mTransport; MessageLoop* mIOLoop; // thread where IO happens Transport::Listener* mExistingListener; // channel's previous listener -#ifdef MOZ_NUWA_PROCESS - bool mIsToNuwaProcess; -#endif }; class ThreadLink : public MessageLink