diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp index e7f2210d25..3bf68b9f9c 100644 --- a/dom/base/nsDOMWindowUtils.cpp +++ b/dom/base/nsDOMWindowUtils.cpp @@ -1075,9 +1075,10 @@ nsDOMWindowUtils::SendNativeTouchPoint(uint32_t aPointerId, } NS_DispatchToMainThread(NS_NewRunnableMethodWithArgs - + (widget, &nsIWidget::SynthesizeNativeTouchPoint, aPointerId, - (nsIWidget::TouchPointerState)aTouchState, nsIntPoint(aScreenX, aScreenY), + (nsIWidget::TouchPointerState)aTouchState, + ScreenIntPoint(aScreenX, aScreenY), aPressure, aOrientation, aObserver)); return NS_OK; } @@ -1094,9 +1095,9 @@ nsDOMWindowUtils::SendNativeTouchTap(int32_t aScreenX, } NS_DispatchToMainThread(NS_NewRunnableMethodWithArgs - + (widget, &nsIWidget::SynthesizeNativeTouchTap, - nsIntPoint(aScreenX, aScreenY), aLongTap, aObserver)); + ScreenIntPoint(aScreenX, aScreenY), aLongTap, aObserver)); return NS_OK; } diff --git a/dom/ipc/PBrowser.ipdl b/dom/ipc/PBrowser.ipdl index 3fbadef27a..443572854e 100644 --- a/dom/ipc/PBrowser.ipdl +++ b/dom/ipc/PBrowser.ipdl @@ -26,8 +26,9 @@ using class mozilla::gfx::Matrix from "mozilla/gfx/Matrix.h"; using struct gfxSize from "gfxPoint.h"; using CSSRect from "Units.h"; using CSSSize from "Units.h"; -using LayoutDeviceIntRect from "Units.h"; +using mozilla::LayoutDeviceIntRect from "Units.h"; using mozilla::LayoutDeviceIntPoint from "Units.h"; +using mozilla::ScreenIntPoint from "Units.h"; using ScreenIntSize from "Units.h"; using struct mozilla::layers::FrameMetrics from "FrameMetrics.h"; using struct mozilla::layers::ScrollableLayerGuid from "FrameMetrics.h"; @@ -490,11 +491,11 @@ parent: uint64_t aObserverId); SynthesizeNativeTouchPoint(uint32_t aPointerId, TouchPointerState aPointerState, - IntPoint aPointerScreenPoint, + ScreenIntPoint aPointerScreenPoint, double aPointerPressure, uint32_t aPointerOrientation, uint64_t aObserverId); - SynthesizeNativeTouchTap(IntPoint aPointerScreenPoint, + SynthesizeNativeTouchTap(ScreenIntPoint aPointerScreenPoint, bool aLongTap, uint64_t aObserverId); ClearNativeTouchSequence(uint64_t aObserverId); diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index 6cba0f4314..928fdd09d4 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -1808,10 +1808,11 @@ TabChild::RecvMouseWheelEvent(const WidgetWheelEvent& aEvent, event.widget = mPuppetWidget; APZCCallbackHelper::DispatchWidgetEvent(event); + if (event.mCanTriggerSwipe) { + SendRespondStartSwipeEvent(aInputBlockId, event.TriggersSwipe()); + } + if (aEvent.mFlags.mHandledByAPZ) { - if (event.mCanTriggerSwipe) { - SendRespondStartSwipeEvent(aInputBlockId, event.TriggersSwipe()); - } mAPZEventState->ProcessWheelEvent(event, aGuid, aInputBlockId); } return true; diff --git a/dom/ipc/TabParent.cpp b/dom/ipc/TabParent.cpp index ed13beb200..50daace0f9 100644 --- a/dom/ipc/TabParent.cpp +++ b/dom/ipc/TabParent.cpp @@ -1634,7 +1634,7 @@ TabParent::RecvSynthesizeNativeMouseScrollEvent(const LayoutDeviceIntPoint& aPoi bool TabParent::RecvSynthesizeNativeTouchPoint(const uint32_t& aPointerId, const TouchPointerState& aPointerState, - const nsIntPoint& aPointerScreenPoint, + const ScreenIntPoint& aPointerScreenPoint, const double& aPointerPressure, const uint32_t& aPointerOrientation, const uint64_t& aObserverId) @@ -1649,7 +1649,7 @@ TabParent::RecvSynthesizeNativeTouchPoint(const uint32_t& aPointerId, } bool -TabParent::RecvSynthesizeNativeTouchTap(const nsIntPoint& aPointerScreenPoint, +TabParent::RecvSynthesizeNativeTouchTap(const ScreenIntPoint& aPointerScreenPoint, const bool& aLongTap, const uint64_t& aObserverId) { @@ -2706,6 +2706,12 @@ TabParent::ApzAwareEventRoutingToChild(ScrollableLayerGuid* aOutTargetGuid, uint64_t* aOutInputBlockId, nsEventStatus* aOutApzResponse) { + // Let the widget know that the event will be sent to the child process, + // which will (hopefully) send a confirmation notice back to APZ. + // Do this even if APZ is off since we need it for swipe gesture support on + // OS X without APZ. + InputAPZContext::SetRoutedToChildProcess(); + if (AsyncPanZoomEnabled()) { if (aOutTargetGuid) { *aOutTargetGuid = InputAPZContext::GetTargetLayerGuid(); @@ -2727,10 +2733,6 @@ TabParent::ApzAwareEventRoutingToChild(ScrollableLayerGuid* aOutTargetGuid, if (aOutApzResponse) { *aOutApzResponse = InputAPZContext::GetApzResponse(); } - - // Let the widget know that the event will be sent to the child process, - // which will (hopefully) send a confirmation notice back to APZ. - InputAPZContext::SetRoutedToChildProcess(); } else { if (aOutInputBlockId) { *aOutInputBlockId = 0; diff --git a/dom/ipc/TabParent.h b/dom/ipc/TabParent.h index 8befdbaa68..2a74190b04 100644 --- a/dom/ipc/TabParent.h +++ b/dom/ipc/TabParent.h @@ -328,11 +328,11 @@ public: const uint64_t& aObserverId) override; virtual bool RecvSynthesizeNativeTouchPoint(const uint32_t& aPointerId, const TouchPointerState& aPointerState, - const nsIntPoint& aPointerScreenPoint, + const ScreenIntPoint& aPointerScreenPoint, const double& aPointerPressure, const uint32_t& aPointerOrientation, const uint64_t& aObserverId) override; - virtual bool RecvSynthesizeNativeTouchTap(const nsIntPoint& aPointerScreenPoint, + virtual bool RecvSynthesizeNativeTouchTap(const ScreenIntPoint& aPointerScreenPoint, const bool& aLongTap, const uint64_t& aObserverId) override; virtual bool RecvClearNativeTouchSequence(const uint64_t& aObserverId) override; diff --git a/dom/plugins/base/PluginPRLibrary.h b/dom/plugins/base/PluginPRLibrary.h index 8bbcd97736..838a564831 100644 --- a/dom/plugins/base/PluginPRLibrary.h +++ b/dom/plugins/base/PluginPRLibrary.h @@ -121,6 +121,7 @@ public: const nsIntRect&, gfxContext** aCtx) override; virtual nsresult EndUpdateBackground(NPP instance, gfxContext* aCtx, const nsIntRect&) override; + virtual void DidComposite(NPP aInstance) override { } virtual void GetLibraryPath(nsACString& aPath) { aPath.Assign(mFilePath); } virtual nsresult GetRunID(uint32_t* aRunID) override { return NS_ERROR_NOT_IMPLEMENTED; } virtual void SetHasLocalInstance() override { } diff --git a/dom/plugins/base/npapi.h b/dom/plugins/base/npapi.h index 2c773b096b..6e0fc753b9 100644 --- a/dom/plugins/base/npapi.h +++ b/dom/plugins/base/npapi.h @@ -59,7 +59,7 @@ /*----------------------------------------------------------------------*/ #define NP_VERSION_MAJOR 0 -#define NP_VERSION_MINOR 28 +#define NP_VERSION_MINOR 29 /* The OS/2 version of Netscape uses RC_DATA to define the @@ -186,6 +186,33 @@ typedef enum { NPFocusPrevious = 1 } NPFocusDirection; +/* These formats describe the format in the memory byte-order. This means if + * a 32-bit value of a pixel is viewed on a little-endian system the layout will + * be 0xAARRGGBB. The Alpha channel will be stored in the most significant + * bits. */ +typedef enum { + /* 32-bit per pixel 8-bit per channel - premultiplied alpha */ + NPImageFormatBGRA32 = 0x1, + /* 32-bit per pixel 8-bit per channel - 1 unused channel */ + NPImageFormatBGRX32 = 0x2 +} NPImageFormat; + +typedef struct _NPAsyncSurface +{ + uint32_t version; + NPSize size; + NPImageFormat format; + union { + struct { + uint32_t stride; + void *data; + } bitmap; +#if defined(XP_WIN) + HANDLE sharedHandle; +#endif + }; +} NPAsyncSurface; + /* Return values for NPP_HandleEvent */ #define kNPEventNotHandled 0 #define kNPEventHandled 1 @@ -248,11 +275,9 @@ typedef enum { #if defined(MOZ_X11) , NPDrawingModelSyncX = 6 #endif -#if 0 /* OBSOLETE */ - , NPDrawingModelAsyncBitmapSurfaceOBSOLETE = 7 + , NPDrawingModelAsyncBitmapSurface = 7 #if defined(XP_WIN) - , NPDrawingModelAsyncWindowsDXGISurfaceOBSOLETE = 8 -#endif + , NPDrawingModelAsyncWindowsDXGISurface = 8 #endif } NPDrawingModel; @@ -398,11 +423,9 @@ typedef enum { , NPNVsupportsCoreAnimationBool = 2003 , NPNVsupportsInvalidatingCoreAnimationBool = 2004 #endif -#if 0 /* OBSOLETE */ - , NPNVsupportsAsyncBitmapSurfaceBoolOBSOLETE = 2007 + , NPNVsupportsAsyncBitmapSurfaceBool = 2007 #if defined(XP_WIN) - , NPNVsupportsAsyncWindowsDXGISurfaceBoolOBSOLETE = 2008 -#endif + , NPNVsupportsAsyncWindowsDXGISurfaceBool = 2008 #endif #if defined(XP_MACOSX) #ifndef NP_NO_CARBON @@ -850,6 +873,11 @@ NPBool NPN_ConvertPoint(NPP instance, double sourceX, double sourceY, NPCoo NPBool NPN_HandleEvent(NPP instance, void *event, NPBool handled); NPBool NPN_UnfocusInstance(NPP instance, NPFocusDirection direction); void NPN_URLRedirectResponse(NPP instance, void* notifyData, NPBool allow); +NPError NPN_InitAsyncSurface(NPP instance, NPSize *size, + NPImageFormat format, void *initData, + NPAsyncSurface *surface); +NPError NPN_FinalizeAsyncSurface(NPP instance, NPAsyncSurface *surface); +void NPN_SetCurrentAsyncSurface(NPP instance, NPAsyncSurface *surface, NPRect *changed); #ifdef __cplusplus } /* end extern "C" */ diff --git a/dom/plugins/base/npfunctions.h b/dom/plugins/base/npfunctions.h index 9927258ec5..ccd549a560 100644 --- a/dom/plugins/base/npfunctions.h +++ b/dom/plugins/base/npfunctions.h @@ -92,6 +92,9 @@ typedef NPBool (*NPN_ConvertPointPtr)(NPP instance, double sourceX, double typedef NPBool (*NPN_HandleEventPtr)(NPP instance, void *event, NPBool handled); typedef NPBool (*NPN_UnfocusInstancePtr)(NPP instance, NPFocusDirection direction); typedef void (*NPN_URLRedirectResponsePtr)(NPP instance, void* notifyData, NPBool allow); +typedef NPError (*NPN_InitAsyncSurfacePtr)(NPP instance, NPSize *size, NPImageFormat format, void *initData, NPAsyncSurface *surface); +typedef NPError (*NPN_FinalizeAsyncSurfacePtr)(NPP instance, NPAsyncSurface *surface); +typedef void (*NPN_SetCurrentAsyncSurfacePtr)(NPP instance, NPAsyncSurface *surface, NPRect *changed); typedef void (*NPN_DummyPtr)(void); @@ -178,9 +181,9 @@ typedef struct _NPNetscapeFuncs { NPN_HandleEventPtr handleevent; NPN_UnfocusInstancePtr unfocusinstance; NPN_URLRedirectResponsePtr urlredirectresponse; - NPN_DummyPtr initasyncsurfaceOBSOLETE; - NPN_DummyPtr finalizeasyncsurfaceOBSOLETE; - NPN_DummyPtr setcurrentasyncsurfaceOBSOLETE; + NPN_InitAsyncSurfacePtr initasyncsurface; + NPN_FinalizeAsyncSurfacePtr finalizeasyncsurface; + NPN_SetCurrentAsyncSurfacePtr setcurrentasyncsurface; } NPNetscapeFuncs; #ifdef XP_MACOSX diff --git a/dom/plugins/base/nsIPluginInstanceOwner.idl b/dom/plugins/base/nsIPluginInstanceOwner.idl index 0a1d53d230..87e51599c9 100644 --- a/dom/plugins/base/nsIPluginInstanceOwner.idl +++ b/dom/plugins/base/nsIPluginInstanceOwner.idl @@ -26,7 +26,7 @@ enum nsPluginTagType { // Do not make this interface scriptable, because the virtual functions in C++ // blocks will make script call the wrong functions. -[uuid(8ff5f46e-96fa-4905-a75c-35aac30bdcee)] +[uuid(7d65452e-c167-4cba-a0e3-ddc61bdde8c3)] interface nsIPluginInstanceOwner : nsISupports { /** @@ -66,7 +66,8 @@ interface nsIPluginInstanceOwner : nsISupports NS_IMETHOD GetURL(const char *aURL, const char *aTarget, nsIInputStream *aPostStream, - void *aHeadersData, uint32_t aHeadersDataLen) = 0; + void *aHeadersData, uint32_t aHeadersDataLen, + bool aDoCheckLoadURIChecks) = 0; %} /** @@ -100,6 +101,10 @@ interface nsIPluginInstanceOwner : nsISupports %{C++ virtual NPBool ConvertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double *destX, double *destY, NPCoordinateSpace destSpace) = 0; + virtual NPError InitAsyncSurface(NPSize *size, NPImageFormat format, + void *initData, NPAsyncSurface *surface) = 0; + virtual NPError FinalizeAsyncSurface(NPAsyncSurface *surface) = 0; + virtual void SetCurrentAsyncSurface(NPAsyncSurface *surface, NPRect *changed) = 0; %} void setEventModel(in int32_t eventModel); diff --git a/dom/plugins/base/nsNPAPIPlugin.cpp b/dom/plugins/base/nsNPAPIPlugin.cpp index 01ffdfaedd..ac54062295 100644 --- a/dom/plugins/base/nsNPAPIPlugin.cpp +++ b/dom/plugins/base/nsNPAPIPlugin.cpp @@ -169,7 +169,10 @@ static NPNetscapeFuncs sBrowserFuncs = { _convertpoint, nullptr, // handleevent, unimplemented nullptr, // unfocusinstance, unimplemented - _urlredirectresponse + _urlredirectresponse, + _initasyncsurface, + _finalizeasyncsurface, + _setcurrentasyncsurface }; static Mutex *sPluginThreadAsyncCallLock = nullptr; @@ -2929,6 +2932,39 @@ _urlredirectresponse(NPP instance, void* notifyData, NPBool allow) inst->URLRedirectResponse(notifyData, allow); } +NPError +_initasyncsurface(NPP instance, NPSize *size, NPImageFormat format, void *initData, NPAsyncSurface *surface) +{ + nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata; + if (!inst) { + return NPERR_GENERIC_ERROR; + } + + return inst->InitAsyncSurface(size, format, initData, surface); +} + +NPError +_finalizeasyncsurface(NPP instance, NPAsyncSurface *surface) +{ + nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata; + if (!inst) { + return NPERR_GENERIC_ERROR; + } + + return inst->FinalizeAsyncSurface(surface); +} + +void +_setcurrentasyncsurface(NPP instance, NPAsyncSurface *surface, NPRect *changed) +{ + nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata; + if (!inst) { + return; + } + + inst->SetCurrentAsyncSurface(surface, changed); +} + } /* namespace parent */ } /* namespace plugins */ } /* namespace mozilla */ diff --git a/dom/plugins/base/nsNPAPIPlugin.h b/dom/plugins/base/nsNPAPIPlugin.h index 1d0cd16e6c..df947ffd4e 100644 --- a/dom/plugins/base/nsNPAPIPlugin.h +++ b/dom/plugins/base/nsNPAPIPlugin.h @@ -323,6 +323,15 @@ _getJavaPeer(NPP npp); void _urlredirectresponse(NPP instance, void* notifyData, NPBool allow); +NPError +_initasyncsurface(NPP instance, NPSize *size, NPImageFormat format, void *initData, NPAsyncSurface *surface); + +NPError +_finalizeasyncsurface(NPP instance, NPAsyncSurface *surface); + +void +_setcurrentasyncsurface(NPP instance, NPAsyncSurface *surface, NPRect *changed); + } /* namespace parent */ } /* namespace plugins */ } /* namespace mozilla */ diff --git a/dom/plugins/base/nsNPAPIPluginInstance.cpp b/dom/plugins/base/nsNPAPIPluginInstance.cpp index 3fd47abfc4..5624aac330 100644 --- a/dom/plugins/base/nsNPAPIPluginInstance.cpp +++ b/dom/plugins/base/nsNPAPIPluginInstance.cpp @@ -1067,12 +1067,8 @@ nsNPAPIPluginInstance* nsNPAPIPluginInstance::GetFromNPP(NPP npp) nsresult nsNPAPIPluginInstance::GetDrawingModel(int32_t* aModel) { -#if defined(XP_MACOSX) *aModel = (int32_t)mDrawingModel; return NS_OK; -#else - return NS_ERROR_FAILURE; -#endif } nsresult nsNPAPIPluginInstance::IsRemoteDrawingCoreAnimation(bool* aDrawing) @@ -1211,6 +1207,16 @@ nsNPAPIPluginInstance::GetImageSize(nsIntSize* aSize) return !library ? NS_ERROR_FAILURE : library->GetImageSize(&mNPP, aSize); } +void +nsNPAPIPluginInstance::DidComposite() +{ + if (RUNNING != mRunning) + return; + + AutoPluginLibraryCall library(this); + library->DidComposite(&mNPP); +} + nsresult nsNPAPIPluginInstance::NotifyPainted(void) { @@ -1625,6 +1631,35 @@ nsNPAPIPluginInstance::URLRedirectResponse(void* notifyData, NPBool allow) } } +NPError +nsNPAPIPluginInstance::InitAsyncSurface(NPSize *size, NPImageFormat format, + void *initData, NPAsyncSurface *surface) +{ + if (mOwner) { + return mOwner->InitAsyncSurface(size, format, initData, surface); + } + + return NPERR_GENERIC_ERROR; +} + +NPError +nsNPAPIPluginInstance::FinalizeAsyncSurface(NPAsyncSurface *surface) +{ + if (mOwner) { + return mOwner->FinalizeAsyncSurface(surface); + } + + return NPERR_GENERIC_ERROR; +} + +void +nsNPAPIPluginInstance::SetCurrentAsyncSurface(NPAsyncSurface *surface, NPRect *changed) +{ + if (mOwner) { + mOwner->SetCurrentAsyncSurface(surface, changed); + } +} + class CarbonEventModelFailureEvent : public nsRunnable { public: nsCOMPtr mContent; diff --git a/dom/plugins/base/nsNPAPIPluginInstance.h b/dom/plugins/base/nsNPAPIPluginInstance.h index 64a516e518..0cacf8ba36 100644 --- a/dom/plugins/base/nsNPAPIPluginInstance.h +++ b/dom/plugins/base/nsNPAPIPluginInstance.h @@ -122,6 +122,7 @@ public: nsresult GetJSContext(JSContext* *outContext); nsPluginInstanceOwner* GetOwner(); void SetOwner(nsPluginInstanceOwner *aOwner); + void DidComposite(); bool HasAudioChannelAgent() const { @@ -293,6 +294,11 @@ public: void URLRedirectResponse(void* notifyData, NPBool allow); + NPError InitAsyncSurface(NPSize *size, NPImageFormat format, + void *initData, NPAsyncSurface *surface); + NPError FinalizeAsyncSurface(NPAsyncSurface *surface); + void SetCurrentAsyncSurface(NPAsyncSurface *surface, NPRect *changed); + // Called when the instance fails to instantiate beceause the Carbon // event model is not supported. void CarbonNPAPIFailure(); diff --git a/dom/plugins/base/nsNPAPIPluginStreamListener.cpp b/dom/plugins/base/nsNPAPIPluginStreamListener.cpp index 51a727afe2..aa59329d6b 100644 --- a/dom/plugins/base/nsNPAPIPluginStreamListener.cpp +++ b/dom/plugins/base/nsNPAPIPluginStreamListener.cpp @@ -90,8 +90,7 @@ nsPluginStreamToFile::Write(const char* aBuf, uint32_t aCount, { mOutputStream->Write(aBuf, aCount, aWriteCount); mOutputStream->Flush(); - mOwner->GetURL(mFileURL.get(), mTarget, nullptr, nullptr, 0); - + mOwner->GetURL(mFileURL.get(), mTarget, nullptr, nullptr, 0, false); return NS_OK; } @@ -122,7 +121,7 @@ NS_IMETHODIMP nsPluginStreamToFile::Close(void) { mOutputStream->Close(); - mOwner->GetURL(mFileURL.get(), mTarget, nullptr, nullptr, 0); + mOwner->GetURL(mFileURL.get(), mTarget, nullptr, nullptr, 0, false); return NS_OK; } diff --git a/dom/plugins/base/nsPluginHost.cpp b/dom/plugins/base/nsPluginHost.cpp index 249798574b..d368ae4a04 100644 --- a/dom/plugins/base/nsPluginHost.cpp +++ b/dom/plugins/base/nsPluginHost.cpp @@ -88,7 +88,6 @@ #include "nsIWeakReferenceUtils.h" #include "nsIPresShell.h" #include "nsPluginNativeWindow.h" -#include "nsIScriptSecurityManager.h" #include "nsIContentPolicy.h" #include "nsContentPolicyUtils.h" #include "mozilla/TimeStamp.h" @@ -472,32 +471,24 @@ nsresult nsPluginHost::GetURLWithHeaders(nsNPAPIPluginInstance* pluginInst, { // we can only send a stream back to the plugin (as specified by a // null target) if we also have a nsNPAPIPluginStreamListener to talk to - if (!target && !streamListener) + if (!target && !streamListener) { return NS_ERROR_ILLEGAL_VALUE; + } nsresult rv = NS_OK; if (target) { - rv = DoURLLoadSecurityCheck(pluginInst, url); - NS_ENSURE_SUCCESS(rv, rv); - RefPtr owner = pluginInst->GetOwner(); if (owner) { - if ((0 == PL_strcmp(target, "newwindow")) || - (0 == PL_strcmp(target, "_new"))) - target = "_blank"; - else if (0 == PL_strcmp(target, "_current")) - target = "_self"; - - rv = owner->GetURL(url, target, nullptr, nullptr, 0); + rv = owner->GetURL(url, target, nullptr, nullptr, 0, true); } } - if (streamListener) + if (streamListener) { rv = NewPluginURLStream(NS_ConvertUTF8toUTF16(url), pluginInst, streamListener, nullptr, getHeaders, getHeadersLength); - + } return rv; } @@ -565,28 +556,19 @@ nsresult nsPluginHost::PostURL(nsISupports* pluginInst, } if (target) { - rv = DoURLLoadSecurityCheck(instance, url); - NS_ENSURE_SUCCESS(rv, rv); - RefPtr owner = instance->GetOwner(); if (owner) { - if ((0 == PL_strcmp(target, "newwindow")) || - (0 == PL_strcmp(target, "_new"))) { - target = "_blank"; - } else if (0 == PL_strcmp(target, "_current")) { - target = "_self"; - } rv = owner->GetURL(url, target, postStream, - (void*)postHeaders, postHeadersLength); + (void*)postHeaders, postHeadersLength, true); } } // if we don't have a target, just create a stream. - if (streamListener) + if (streamListener) { rv = NewPluginURLStream(NS_ConvertUTF8toUTF16(url), instance, streamListener, postStream, postHeaders, postHeadersLength); - + } return rv; } @@ -3471,45 +3453,6 @@ nsresult nsPluginHost::NewPluginURLStream(const nsString& aURL, return rv; } -// Called by GetURL and PostURL -nsresult -nsPluginHost::DoURLLoadSecurityCheck(nsNPAPIPluginInstance *aInstance, - const char* aURL) -{ - if (!aURL || *aURL == '\0') - return NS_OK; - - // get the base URI for the plugin element - RefPtr owner = aInstance->GetOwner(); - if (!owner) - return NS_ERROR_FAILURE; - - nsCOMPtr baseURI = owner->GetBaseURI(); - if (!baseURI) - return NS_ERROR_FAILURE; - - // Create an absolute URL for the target in case the target is relative - nsCOMPtr targetURL; - NS_NewURI(getter_AddRefs(targetURL), aURL, baseURI); - if (!targetURL) - return NS_ERROR_FAILURE; - - nsCOMPtr doc; - owner->GetDocument(getter_AddRefs(doc)); - if (!doc) - return NS_ERROR_FAILURE; - - nsresult rv; - nsCOMPtr secMan( - do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv)); - if (NS_FAILED(rv)) - return rv; - - return secMan->CheckLoadURIWithPrincipal(doc->NodePrincipal(), targetURL, - nsIScriptSecurityManager::STANDARD); - -} - nsresult nsPluginHost::AddHeadersToChannel(const char *aHeadersData, uint32_t aHeadersDataLen, diff --git a/dom/plugins/base/nsPluginHost.h b/dom/plugins/base/nsPluginHost.h index e492aa2da7..7921343174 100644 --- a/dom/plugins/base/nsPluginHost.h +++ b/dom/plugins/base/nsPluginHost.h @@ -180,10 +180,6 @@ public: uint32_t getHeadersLength = 0, const char* getHeaders = nullptr); - nsresult - DoURLLoadSecurityCheck(nsNPAPIPluginInstance *aInstance, - const char* aURL); - nsresult AddHeadersToChannel(const char *aHeadersData, uint32_t aHeadersDataLen, nsIChannel *aGenericChannel); diff --git a/dom/plugins/base/nsPluginInstanceOwner.cpp b/dom/plugins/base/nsPluginInstanceOwner.cpp index 85ec0b1bc6..b7e49fdf0a 100644 --- a/dom/plugins/base/nsPluginInstanceOwner.cpp +++ b/dom/plugins/base/nsPluginInstanceOwner.cpp @@ -44,6 +44,7 @@ using mozilla::DefaultXDisplay; #include "nsIFocusManager.h" #include "nsFocusManager.h" #include "nsIDOMDragEvent.h" +#include "nsIScriptSecurityManager.h" #include "nsIScrollableFrame.h" #include "nsIDocShell.h" #include "ImageContainer.h" @@ -471,7 +472,8 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetURL(const char *aURL, const char *aTarget, nsIInputStream *aPostStream, void *aHeadersData, - uint32_t aHeadersDataLen) + uint32_t aHeadersDataLen, + bool aDoCheckLoadURIChecks) { nsCOMPtr content = do_QueryReferent(mContent); if (!content) { @@ -503,17 +505,35 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetURL(const char *aURL, nsCOMPtr lh = do_QueryInterface(container); NS_ENSURE_TRUE(lh, NS_ERROR_FAILURE); - nsAutoString unitarget; - unitarget.AssignASCII(aTarget); // XXX could this be nonascii? + nsAutoString unitarget; + if ((0 == PL_strcmp(aTarget, "newwindow")) || + (0 == PL_strcmp(aTarget, "_new"))) { + unitarget.AssignASCII("_blank"); + } + else if (0 == PL_strcmp(aTarget, "_current")) { + unitarget.AssignASCII("_self"); + } + else { + unitarget.AssignASCII(aTarget); // XXX could this be nonascii? + } nsCOMPtr baseURI = GetBaseURI(); // Create an absolute URL nsCOMPtr uri; nsresult rv = NS_NewURI(getter_AddRefs(uri), aURL, baseURI); - NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE); + if (aDoCheckLoadURIChecks) { + nsCOMPtr secMan( + do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv)); + NS_ENSURE_TRUE(secMan, NS_ERROR_FAILURE); + + rv = secMan->CheckLoadURIWithPrincipal(content->NodePrincipal(), uri, + nsIScriptSecurityManager::STANDARD); + NS_ENSURE_SUCCESS(rv, rv); + } + nsCOMPtr headersDataStream; if (aPostStream && aHeadersData) { if (!aHeadersDataLen) @@ -1016,6 +1036,21 @@ NPBool nsPluginInstanceOwner::ConvertPoint(double sourceX, double sourceY, NPCoo #endif } +NPError nsPluginInstanceOwner::InitAsyncSurface(NPSize *size, NPImageFormat format, + void *initData, NPAsyncSurface *surface) +{ + return NPERR_INCOMPATIBLE_VERSION_ERROR; +} + +NPError nsPluginInstanceOwner::FinalizeAsyncSurface(NPAsyncSurface *) +{ + return NPERR_INCOMPATIBLE_VERSION_ERROR; +} + +void nsPluginInstanceOwner::SetCurrentAsyncSurface(NPAsyncSurface *, NPRect*) +{ +} + NS_IMETHODIMP nsPluginInstanceOwner::GetTagType(nsPluginTagType *result) { NS_ENSURE_ARG_POINTER(result); diff --git a/dom/plugins/base/nsPluginInstanceOwner.h b/dom/plugins/base/nsPluginInstanceOwner.h index fb7cda96eb..3c5e10ad68 100644 --- a/dom/plugins/base/nsPluginInstanceOwner.h +++ b/dom/plugins/base/nsPluginInstanceOwner.h @@ -61,11 +61,17 @@ public: NS_IMETHOD GetURL(const char *aURL, const char *aTarget, nsIInputStream *aPostStream, - void *aHeadersData, uint32_t aHeadersDataLen) override; + void *aHeadersData, uint32_t aHeadersDataLen, + bool aDoCheckLoadURIChecks) override; NPBool ConvertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double *destX, double *destY, NPCoordinateSpace destSpace) override; - + + NPError InitAsyncSurface(NPSize *size, NPImageFormat format, + void *initData, NPAsyncSurface *surface) override; + NPError FinalizeAsyncSurface(NPAsyncSurface *surface) override; + void SetCurrentAsyncSurface(NPAsyncSurface *surface, NPRect *changed) override; + /** * Get the type of the HTML tag that was used ot instantiate this * plugin. Currently supported tags are EMBED, OBJECT and APPLET. diff --git a/dom/plugins/ipc/PPluginInstance.ipdl b/dom/plugins/ipc/PPluginInstance.ipdl index 3187ca5371..b0694450d3 100644 --- a/dom/plugins/ipc/PPluginInstance.ipdl +++ b/dom/plugins/ipc/PPluginInstance.ipdl @@ -146,6 +146,10 @@ parent: returns (nsCString value, NPError result); intr NPN_GetValue_DrawingModelSupport(NPNVariable model) returns (bool value); + intr NPN_GetValue_SupportsAsyncBitmapSurface() + returns (bool value); + intr NPN_GetValue_SupportsAsyncDXGISurface() + returns (bool value); intr NPN_SetValue_NPPVpluginWindow(bool windowed) returns (NPError result); diff --git a/dom/plugins/ipc/PluginInstanceChild.cpp b/dom/plugins/ipc/PluginInstanceChild.cpp index 05006a983b..4d00403ecd 100644 --- a/dom/plugins/ipc/PluginInstanceChild.cpp +++ b/dom/plugins/ipc/PluginInstanceChild.cpp @@ -442,6 +442,22 @@ PluginInstanceChild::NPN_GetValue(NPNVariable aVar, #endif } + case NPNVsupportsAsyncBitmapSurfaceBool: { + bool value = false; + CallNPN_GetValue_SupportsAsyncBitmapSurface(&value); + *((NPBool*)aValue) = value; + return NPERR_NO_ERROR; + } + +#ifdef XP_WIN + case NPNVsupportsAsyncWindowsDXGISurfaceBool: { + bool value = false; + CallNPN_GetValue_SupportsAsyncDXGISurface(&value); + *((NPBool*)aValue) = value; + return NPERR_NO_ERROR; + } +#endif + #ifdef XP_MACOSX case NPNVsupportsCoreGraphicsBool: { *((NPBool*)aValue) = true; @@ -2531,6 +2547,50 @@ PluginInstanceChild::NPN_URLRedirectResponse(void* notifyData, NPBool allow) NS_ASSERTION(false, "Couldn't find stream for redirect response!"); } +bool +PluginInstanceChild::IsUsingDirectDrawing() +{ + return IsDrawingModelDirect(mDrawingModel); +} + +NPError +PluginInstanceChild::NPN_InitAsyncSurface(NPSize *size, NPImageFormat format, + void *initData, NPAsyncSurface *surface) +{ + AssertPluginThread(); + + surface->bitmap.data = NULL; + + if (!IsUsingDirectDrawing()) { + return NPERR_GENERIC_ERROR; + } + + MOZ_CRASH("NYI"); + return NPERR_GENERIC_ERROR; +} + +NPError +PluginInstanceChild::NPN_FinalizeAsyncSurface(NPAsyncSurface *surface) +{ + AssertPluginThread(); + + if (!IsUsingDirectDrawing()) { + return NPERR_GENERIC_ERROR; + } + + MOZ_CRASH("NYI"); + return NPERR_GENERIC_ERROR; +} + +void +PluginInstanceChild::NPN_SetCurrentAsyncSurface(NPAsyncSurface *surface, NPRect *changed) +{ + if (!IsUsingDirectDrawing()) { + return; + } + MOZ_CRASH("NYI"); +} + void PluginInstanceChild::DoAsyncRedraw() { @@ -2954,6 +3014,9 @@ PluginInstanceChild::PaintRectToPlatformSurface(const nsIntRect& aRect, { UpdateWindowAttributes(); + // We should not send an async surface if we're using direct rendering. + MOZ_ASSERT(!IsUsingDirectDrawing()); + #ifdef MOZ_X11 { NS_ASSERTION(aSurface->GetType() == gfxSurfaceType::Xlib, @@ -3189,6 +3252,10 @@ PluginInstanceChild::ShowPluginFrame() return false; } + // We should not attempt to asynchronously show the plugin if we're using + // direct rendering. + MOZ_ASSERT(!IsUsingDirectDrawing()); + AutoRestore pending(mPendingPluginCall); mPendingPluginCall = true; @@ -3468,6 +3535,13 @@ PluginInstanceChild::AsyncShowPluginFrame(void) return; } + // When the plugin is using direct surfaces to draw, it is not driving + // paints via paint events - it will drive painting via its own events + // and/or DidComposite callbacks. + if (IsUsingDirectDrawing()) { + return; + } + mCurrentInvalidateTask = NewRunnableMethod(this, &PluginInstanceChild::InvalidateRectDelayed); MessageLoop::current()->PostTask(FROM_HERE, mCurrentInvalidateTask); @@ -3489,6 +3563,11 @@ PluginInstanceChild::InvalidateRect(NPRect* aInvalidRect) } #endif + if (IsUsingDirectDrawing()) { + NS_ASSERTION(false, "Should not call InvalidateRect() in direct surface mode!"); + return; + } + if (mLayersRendering) { nsIntRect r(aInvalidRect->left, aInvalidRect->top, aInvalidRect->right - aInvalidRect->left, diff --git a/dom/plugins/ipc/PluginInstanceChild.h b/dom/plugins/ipc/PluginInstanceChild.h index eabae22f74..d06f4d4a83 100644 --- a/dom/plugins/ipc/PluginInstanceChild.h +++ b/dom/plugins/ipc/PluginInstanceChild.h @@ -261,6 +261,13 @@ public: void NPN_URLRedirectResponse(void* notifyData, NPBool allow); + + NPError NPN_InitAsyncSurface(NPSize *size, NPImageFormat format, + void *initData, NPAsyncSurface *surface); + NPError NPN_FinalizeAsyncSurface(NPAsyncSurface *surface); + + void NPN_SetCurrentAsyncSurface(NPAsyncSurface *surface, NPRect *changed); + void DoAsyncRedraw(); private: friend class PluginModuleChild; @@ -269,7 +276,7 @@ private: InternalGetNPObjectForValue(NPNVariable aValue, NPObject** aObject); - bool IsAsyncDrawing(); + bool IsUsingDirectDrawing(); virtual bool RecvUpdateBackground(const SurfaceDescriptor& aBackground, const nsIntRect& aRect) override; diff --git a/dom/plugins/ipc/PluginInstanceParent.cpp b/dom/plugins/ipc/PluginInstanceParent.cpp index 45e0b0e535..3654c94ae2 100644 --- a/dom/plugins/ipc/PluginInstanceParent.cpp +++ b/dom/plugins/ipc/PluginInstanceParent.cpp @@ -37,6 +37,7 @@ #include "ImageContainer.h" #include "GLContext.h" #include "GLContextProvider.h" +#include "gfxPrefs.h" #ifdef XP_MACOSX #include "MacIOSurfaceImage.h" @@ -229,6 +230,12 @@ PluginInstanceParent::Destroy() return retval; } +bool +PluginInstanceParent::IsUsingDirectDrawing() +{ + return IsDrawingModelDirect(mDrawingModel); +} + PBrowserStreamParent* PluginInstanceParent::AllocPBrowserStreamParent(const nsCString& url, const uint32_t& length, @@ -361,6 +368,42 @@ PluginInstanceParent::AnswerNPN_GetValue_NPNVdocumentOrigin(nsCString* value, return true; } +static inline bool +AllowDirectBitmapSurfaceDrawing() +{ + if (!gfxPrefs::PluginAsyncDrawingEnabled()) { + return false; + } + return gfxPlatform::GetPlatform()->SupportsPluginDirectBitmapDrawing(); +} + +static inline bool +AllowDirectDXGISurfaceDrawing() +{ + if (!gfxPrefs::PluginAsyncDrawingEnabled()) { + return false; + } +#if defined(XP_WIN) + return gfxWindowsPlatform::GetPlatform()->SupportsPluginDirectDXGIDrawing(); +#else + return false; +#endif +} + +bool +PluginInstanceParent::AnswerNPN_GetValue_SupportsAsyncBitmapSurface(bool* value) +{ + *value = AllowDirectBitmapSurfaceDrawing(); + return true; +} + +bool +PluginInstanceParent::AnswerNPN_GetValue_SupportsAsyncDXGISurface(bool* value) +{ + *value = AllowDirectDXGISurfaceDrawing(); + return true; +} + bool PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginWindow( const bool& windowed, NPError* result) @@ -395,35 +438,58 @@ bool PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginDrawingModel( const int& drawingModel, NPError* result) { + bool allowed = false; + + switch (drawingModel) { +#if defined(XP_MACOSX) + case NPDrawingModelCoreAnimation: + case NPDrawingModelInvalidatingCoreAnimation: + case NPDrawingModelOpenGL: + case NPDrawingModelCoreGraphics: + allowed = true; + break; +#elif defined(XP_WIN) + case NPDrawingModelSyncWin: + allowed = true; + break; + case NPDrawingModelAsyncWindowsDXGISurface: + allowed = AllowDirectDXGISurfaceDrawing(); + break; +#elif defined(MOZ_X11) + case NPDrawingModelSyncX: + allowed = true; + break; +#endif + case NPDrawingModelAsyncBitmapSurface: + allowed = AllowDirectBitmapSurfaceDrawing(); + break; + default: + allowed = false; + break; + } + + if (!allowed) { + *result = NPERR_GENERIC_ERROR; + return true; + } + + mDrawingModel = drawingModel; + + int requestModel = drawingModel; + #ifdef XP_MACOSX if (drawingModel == NPDrawingModelCoreAnimation || drawingModel == NPDrawingModelInvalidatingCoreAnimation) { // We need to request CoreGraphics otherwise // the nsPluginFrame will try to draw a CALayer // that can not be shared across process. - mDrawingModel = drawingModel; - *result = mNPNIface->setvalue(mNPP, NPPVpluginDrawingModel, - (void*)NPDrawingModelCoreGraphics); - } else -#endif - if ( -#if defined(XP_WIN) - drawingModel == NPDrawingModelSyncWin -#elif defined(XP_MACOSX) - drawingModel == NPDrawingModelOpenGL || - drawingModel == NPDrawingModelCoreGraphics -#elif defined(MOZ_X11) - drawingModel == NPDrawingModelSyncX -#else - false -#endif - ) { - mDrawingModel = drawingModel; - *result = mNPNIface->setvalue(mNPP, NPPVpluginDrawingModel, - (void*)(intptr_t)drawingModel); - } else { - *result = NPERR_GENERIC_ERROR; + requestModel = NPDrawingModelCoreGraphics; } +#endif + + *result = mNPNIface->setvalue(mNPP, NPPVpluginDrawingModel, + (void*)(intptr_t)requestModel); + return true; } @@ -552,6 +618,8 @@ PluginInstanceParent::RecvShow(const NPRect& updatedRect, updatedRect.right - updatedRect.left, updatedRect.bottom - updatedRect.top)); + MOZ_ASSERT(!IsUsingDirectDrawing()); + // XXXjwatt rewrite to use Moz2D RefPtr surface; if (newSurface.type() == SurfaceDescriptor::TShmem) { @@ -690,6 +758,16 @@ PluginInstanceParent::AsyncSetWindow(NPWindow* aWindow) nsresult PluginInstanceParent::GetImageContainer(ImageContainer** aContainer) { + if (IsUsingDirectDrawing()) { + // Use the image container created by the most recent direct surface + // call, if any. We don't create one if no surfaces were presented + // yet. + ImageContainer *container = mImageContainer; + NS_IF_ADDREF(container); + *aContainer = container; + return NS_OK; + } + #ifdef XP_MACOSX MacIOSurface* ioSurface = nullptr; @@ -730,6 +808,14 @@ PluginInstanceParent::GetImageContainer(ImageContainer** aContainer) nsresult PluginInstanceParent::GetImageSize(nsIntSize* aSize) { + if (IsUsingDirectDrawing()) { + if (!mImageContainer) { + return NS_ERROR_NOT_AVAILABLE; + } + *aSize = mImageContainer->GetCurrentSize(); + return NS_OK; + } + if (mFrontSurface) { mozilla::gfx::IntSize size = mFrontSurface->GetSize(); *aSize = nsIntSize(size.width, size.height); @@ -749,6 +835,15 @@ PluginInstanceParent::GetImageSize(nsIntSize* aSize) return NS_ERROR_NOT_AVAILABLE; } +void +PluginInstanceParent::DidComposite() +{ + if (!IsUsingDirectDrawing()) { + return; + } + Unused << SendNPP_DidComposite(); +} + #ifdef XP_MACOSX nsresult PluginInstanceParent::IsRemoteDrawingCoreAnimation(bool *aDrawing) diff --git a/dom/plugins/ipc/PluginInstanceParent.h b/dom/plugins/ipc/PluginInstanceParent.h index 9875a68cfb..e91d642f81 100644 --- a/dom/plugins/ipc/PluginInstanceParent.h +++ b/dom/plugins/ipc/PluginInstanceParent.h @@ -114,6 +114,12 @@ public: virtual bool AnswerNPN_GetValue_NPNVdocumentOrigin(nsCString* value, NPError* result) override; + virtual bool + AnswerNPN_GetValue_SupportsAsyncBitmapSurface(bool* value) override; + + virtual bool + AnswerNPN_GetValue_SupportsAsyncDXGISurface(bool* value) override; + virtual bool AnswerNPN_SetValue_NPPVpluginWindow(const bool& windowed, NPError* result) override; virtual bool @@ -307,7 +313,9 @@ public: gfxContext** aCtx); nsresult EndUpdateBackground(gfxContext* aCtx, const nsIntRect& aRect); - void DidComposite() { Unused << SendNPP_DidComposite(); } + void DidComposite(); + + bool IsUsingDirectDrawing(); virtual PluginAsyncSurrogate* GetAsyncSurrogate() override; @@ -347,7 +355,7 @@ private: nsCString mSrcAttribute; bool mIsWhitelistedForShumway; NPWindowType mWindowType; - int16_t mDrawingModel; + int16_t mDrawingModel; nsDataHashtable, PluginScriptableObjectParent*> mScriptableObjects; diff --git a/dom/plugins/ipc/PluginLibrary.h b/dom/plugins/ipc/PluginLibrary.h index 2622209567..60eea6b743 100644 --- a/dom/plugins/ipc/PluginLibrary.h +++ b/dom/plugins/ipc/PluginLibrary.h @@ -77,6 +77,7 @@ public: virtual nsresult AsyncSetWindow(NPP instance, NPWindow* window) = 0; virtual nsresult GetImageContainer(NPP instance, mozilla::layers::ImageContainer** aContainer) = 0; virtual nsresult GetImageSize(NPP instance, nsIntSize* aSize) = 0; + virtual void DidComposite(NPP instance) = 0; virtual bool IsOOP() = 0; #if defined(XP_MACOSX) virtual nsresult IsRemoteDrawingCoreAnimation(NPP instance, bool *aDrawing) = 0; diff --git a/dom/plugins/ipc/PluginMessageUtils.h b/dom/plugins/ipc/PluginMessageUtils.h index 3a8f7b3b83..89e7e81941 100644 --- a/dom/plugins/ipc/PluginMessageUtils.h +++ b/dom/plugins/ipc/PluginMessageUtils.h @@ -217,6 +217,15 @@ inline void AssertPluginThread() void DeferNPObjectLastRelease(const NPNetscapeFuncs* f, NPObject* o); void DeferNPVariantLastRelease(const NPNetscapeFuncs* f, NPVariant* v); +inline bool IsDrawingModelDirect(int16_t aModel) +{ + return aModel == NPDrawingModelAsyncBitmapSurface +#if defined(XP_WIN) + || aModel == NPDrawingModelAsyncWindowsDXGISurface +#endif + ; +} + // in NPAPI, char* == nullptr is sometimes meaningful. the following is // helper code for dealing with nullable nsCString's inline nsCString diff --git a/dom/plugins/ipc/PluginModuleChild.cpp b/dom/plugins/ipc/PluginModuleChild.cpp index 924dfe90fe..25c52df70f 100644 --- a/dom/plugins/ipc/PluginModuleChild.cpp +++ b/dom/plugins/ipc/PluginModuleChild.cpp @@ -1027,6 +1027,17 @@ _convertpoint(NPP instance, static void _urlredirectresponse(NPP instance, void* notifyData, NPBool allow); +static NPError +_initasyncsurface(NPP instance, NPSize *size, + NPImageFormat format, void *initData, + NPAsyncSurface *surface); + +static NPError +_finalizeasyncsurface(NPP instance, NPAsyncSurface *surface); + +static void +_setcurrentasyncsurface(NPP instance, NPAsyncSurface *surface, NPRect *changed); + } /* namespace child */ } /* namespace plugins */ } /* namespace mozilla */ @@ -1088,7 +1099,10 @@ const NPNetscapeFuncs PluginModuleChild::sBrowserFuncs = { mozilla::plugins::child::_convertpoint, nullptr, // handleevent, unimplemented nullptr, // unfocusinstance, unimplemented - mozilla::plugins::child::_urlredirectresponse + mozilla::plugins::child::_urlredirectresponse, + mozilla::plugins::child::_initasyncsurface, + mozilla::plugins::child::_finalizeasyncsurface, + mozilla::plugins::child::_setcurrentasyncsurface, }; PluginInstanceChild* @@ -1863,6 +1877,26 @@ _urlredirectresponse(NPP instance, void* notifyData, NPBool allow) InstCast(instance)->NPN_URLRedirectResponse(notifyData, allow); } +NPError +_initasyncsurface(NPP instance, NPSize *size, + NPImageFormat format, void *initData, + NPAsyncSurface *surface) +{ + return InstCast(instance)->NPN_InitAsyncSurface(size, format, initData, surface); +} + +NPError +_finalizeasyncsurface(NPP instance, NPAsyncSurface *surface) +{ + return InstCast(instance)->NPN_FinalizeAsyncSurface(surface); +} + +void +_setcurrentasyncsurface(NPP instance, NPAsyncSurface *surface, NPRect *changed) +{ + InstCast(instance)->NPN_SetCurrentAsyncSurface(surface, changed); +} + } /* namespace child */ } /* namespace plugins */ } /* namespace mozilla */ diff --git a/dom/plugins/ipc/PluginModuleParent.cpp b/dom/plugins/ipc/PluginModuleParent.cpp index a3e53a5947..408946ab17 100755 --- a/dom/plugins/ipc/PluginModuleParent.cpp +++ b/dom/plugins/ipc/PluginModuleParent.cpp @@ -1955,6 +1955,14 @@ PluginModuleParent::GetImageSize(NPP instance, return !i ? NS_ERROR_FAILURE : i->GetImageSize(aSize); } +void +PluginModuleParent::DidComposite(NPP aInstance) +{ + if (PluginInstanceParent* i = PluginInstanceParent::Cast(aInstance)) { + i->DidComposite(); + } +} + nsresult PluginModuleParent::SetBackgroundUnknown(NPP instance) { diff --git a/dom/plugins/ipc/PluginModuleParent.h b/dom/plugins/ipc/PluginModuleParent.h index ef46296aac..c94743046f 100644 --- a/dom/plugins/ipc/PluginModuleParent.h +++ b/dom/plugins/ipc/PluginModuleParent.h @@ -243,6 +243,7 @@ protected: virtual nsresult AsyncSetWindow(NPP aInstance, NPWindow* aWindow) override; virtual nsresult GetImageContainer(NPP aInstance, mozilla::layers::ImageContainer** aContainer) override; virtual nsresult GetImageSize(NPP aInstance, nsIntSize* aSize) override; + virtual void DidComposite(NPP aInstance) override; virtual bool IsOOP() override { return true; } virtual nsresult SetBackgroundUnknown(NPP instance) override; virtual nsresult BeginUpdateBackground(NPP instance, diff --git a/dom/plugins/test/testplugin/README b/dom/plugins/test/testplugin/README index 1e7cc04736..3c6a9fb634 100644 --- a/dom/plugins/test/testplugin/README +++ b/dom/plugins/test/testplugin/README @@ -23,6 +23,15 @@ The plugin will draw a solid color instead of the default rendering described above. The default solid color is completely transparent black (i.e., nothing). This should be specified when using one of the async models. +* asyncmodel="bitmap" +The plugin will use the NPAPI Async Bitmap drawing model extension. On +unsupported platforms this will fallback to non-async rendering. + +* asyncmodel="dxgi" +The plugin will use the NPAPI Async DXGI drawing model extension. Only +supported on Windows Vista or higher. On unsupported platforms this will +fallback to non-async rendering. + * color This specifies the color to use for drawmode="solid". The value should be 8 hex digits, 2 per channel in AARRGGBB format. diff --git a/dom/plugins/test/testplugin/nptest.cpp b/dom/plugins/test/testplugin/nptest.cpp index a00ff0cba0..7c8963d055 100644 --- a/dom/plugins/test/testplugin/nptest.cpp +++ b/dom/plugins/test/testplugin/nptest.cpp @@ -597,6 +597,37 @@ static bool bug813906(NPP npp, const char* const function, const char* const url return true; } +void +drawAsyncBitmapColor(InstanceData* instanceData) +{ + NPP npp = instanceData->npp; + + uint32_t *pixelData = (uint32_t*)instanceData->backBuffer->bitmap.data; + + uint32_t rgba = instanceData->scriptableObject->drawColor; + + unsigned char subpixels[4]; + memcpy(subpixels, &rgba, sizeof(subpixels)); + + subpixels[0] = uint8_t(float(subpixels[3] * subpixels[0]) / 0xFF); + subpixels[1] = uint8_t(float(subpixels[3] * subpixels[1]) / 0xFF); + subpixels[2] = uint8_t(float(subpixels[3] * subpixels[2]) / 0xFF); + uint32_t premultiplied; + memcpy(&premultiplied, subpixels, sizeof(premultiplied)); + + for (uint32_t* lastPixel = pixelData + instanceData->backBuffer->size.width * instanceData->backBuffer->size.height; + pixelData < lastPixel; + ++pixelData) + { + *pixelData = premultiplied; + } + + NPN_SetCurrentAsyncSurface(npp, instanceData->backBuffer, NULL); + NPAsyncSurface *oldFront = instanceData->frontBuffer; + instanceData->frontBuffer = instanceData->backBuffer; + instanceData->backBuffer = oldFront; +} + // // function signatures // @@ -807,6 +838,9 @@ NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char* instanceData->wantsAllStreams = false; instanceData->mouseUpEventCount = 0; instanceData->bugMode = -1; + instanceData->asyncDrawing = AD_NONE; + instanceData->frontBuffer = nullptr; + instanceData->backBuffer = nullptr; instance->pdata = instanceData; TestNPObject* scriptableObject = (TestNPObject*)NPN_CreateObject(instance, &sNPClass); @@ -828,6 +862,8 @@ NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char* addRange(instanceData, "100,100"); } + AsyncDrawing requestAsyncDrawing = AD_NONE; + bool requestWindow = false; // handle extra params for (int i = 0; i < argc; i++) { @@ -843,6 +879,13 @@ NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char* requestWindow = true; } } + else if (strcmp(argn[i], "asyncmodel") == 0) { + if (strcmp(argv[i], "bitmap") == 0) { + requestAsyncDrawing = AD_BITMAP; + } else if (strcmp(argv[i], "dxgi") == 0) { + requestAsyncDrawing = AD_DXGI; + } + } if (strcmp(argn[i], "streammode") == 0) { if (strcmp(argv[i], "normal") == 0) { instanceData->streamMode = NP_NORMAL; @@ -957,6 +1000,33 @@ NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char* NPN_SetValue(instance, NPPVpluginTransparentBool, (void*)true); } + if (requestAsyncDrawing == AD_BITMAP) { + NPBool supportsAsyncBitmap = false; + if ((NPN_GetValue(instance, NPNVsupportsAsyncBitmapSurfaceBool, &supportsAsyncBitmap) == NPERR_NO_ERROR) && + supportsAsyncBitmap) { + if (NPN_SetValue(instance, NPPVpluginDrawingModel, (void*)NPDrawingModelAsyncBitmapSurface) == NPERR_NO_ERROR) { + instanceData->asyncDrawing = AD_BITMAP; + } + } + } +#ifdef XP_WIN + else if (requestAsyncDrawing == AD_DXGI) { + NPBool supportsAsyncDXGI = false; + if ((NPN_GetValue(instance, NPNVsupportsAsyncWindowsDXGISurfaceBool, &supportsAsyncDXGI) == NPERR_NO_ERROR) && + supportsAsyncDXGI) { + if (NPN_SetValue(instance, NPPVpluginDrawingModel, (void*)NPDrawingModelAsyncWindowsDXGISurface) == NPERR_NO_ERROR) { + instanceData->asyncDrawing = AD_DXGI; + } + } + } +#endif + + // If we can't get the right drawing mode, we fail, otherwise our tests might + // appear to be passing when they shouldn't. Real plugins should not do this. + if (instanceData->asyncDrawing != requestAsyncDrawing) { + return NPERR_GENERIC_ERROR; + } + instanceData->lastReportedPrivateModeState = false; instanceData->lastMouseX = instanceData->lastMouseY = -1; instanceData->widthAtLastPaint = -1; @@ -1048,6 +1118,16 @@ NPP_Destroy(NPP instance, NPSavedData** save) currentrange = nextrange; } + if (instanceData->frontBuffer) { + NPN_SetCurrentAsyncSurface(instance, nullptr, nullptr); + NPN_FinalizeAsyncSurface(instance, instanceData->frontBuffer); + NPN_MemFree(instanceData->frontBuffer); + } + if (instanceData->backBuffer) { + NPN_FinalizeAsyncSurface(instance, instanceData->backBuffer); + NPN_MemFree(instanceData->backBuffer); + } + pluginInstanceShutdown(instanceData); NPN_ReleaseObject(instanceData->scriptableObject); @@ -1080,6 +1160,54 @@ NPP_SetWindow(NPP instance, NPWindow* window) pluginWidgetInit(instanceData, oldWindow); } + + if (instanceData->asyncDrawing != AD_NONE) { + if (instanceData->frontBuffer && + instanceData->frontBuffer->size.width >= 0 && + (uint32_t)instanceData->frontBuffer->size.width == window->width && + instanceData ->frontBuffer->size.height >= 0 && + (uint32_t)instanceData->frontBuffer->size.height == window->height) + { + return NPERR_NO_ERROR; + } + if (instanceData->frontBuffer) { + NPN_FinalizeAsyncSurface(instance, instanceData->frontBuffer); + NPN_MemFree(instanceData->frontBuffer); + } + if (instanceData->backBuffer) { + NPN_FinalizeAsyncSurface(instance, instanceData->backBuffer); + NPN_MemFree(instanceData->backBuffer); + } + instanceData->frontBuffer = (NPAsyncSurface*)NPN_MemAlloc(sizeof(NPAsyncSurface)); + instanceData->backBuffer = (NPAsyncSurface*)NPN_MemAlloc(sizeof(NPAsyncSurface)); + + NPSize size; + size.width = window->width; + size.height = window->height; + + memcpy(instanceData->backBuffer, instanceData->frontBuffer, sizeof(NPAsyncSurface)); + + NPN_InitAsyncSurface(instance, &size, NPImageFormatBGRA32, nullptr, instanceData->frontBuffer); + NPN_InitAsyncSurface(instance, &size, NPImageFormatBGRA32, nullptr, instanceData->backBuffer); + +#if defined(XP_WIN) + if (instanceData->asyncDrawing == AD_DXGI) { + if (!setupDxgiSurfaces(instanceData)) { + return NPERR_GENERIC_ERROR; + } + } +#endif + } + + if (instanceData->asyncDrawing == AD_BITMAP) { + drawAsyncBitmapColor(instanceData); + } +#if defined(XP_WIN) + else if (instanceData->asyncDrawing == AD_DXGI) { + drawDxgiBitmapColor(instanceData); + } +#endif + return NPERR_NO_ERROR; } @@ -1837,6 +1965,25 @@ NPN_URLRedirectResponse(NPP instance, void* notifyData, NPBool allow) return sBrowserFuncs->urlredirectresponse(instance, notifyData, allow); } +NPError +NPN_InitAsyncSurface(NPP instance, NPSize *size, NPImageFormat format, + void *initData, NPAsyncSurface *surface) +{ + return sBrowserFuncs->initasyncsurface(instance, size, format, initData, surface); +} + +NPError +NPN_FinalizeAsyncSurface(NPP instance, NPAsyncSurface *surface) +{ + return sBrowserFuncs->finalizeasyncsurface(instance, surface); +} + +void +NPN_SetCurrentAsyncSurface(NPP instance, NPAsyncSurface *surface, NPRect *changed) +{ + sBrowserFuncs->setcurrentasyncsurface(instance, surface, changed); +} + // // npruntime object functions // @@ -2738,7 +2885,11 @@ setColor(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* r r.top = 0; r.right = id->window.width; r.bottom = id->window.height; - NPN_InvalidateRect(npp, &r); + if (id->asyncDrawing == AD_NONE) { + NPN_InvalidateRect(npp, &r); + } else if (id->asyncDrawing == AD_BITMAP) { + drawAsyncBitmapColor(id); + } VOID_TO_NPVARIANT(*result); return true; diff --git a/dom/plugins/test/testplugin/nptest.h b/dom/plugins/test/testplugin/nptest.h index fd4fb9018c..16a562d032 100644 --- a/dom/plugins/test/testplugin/nptest.h +++ b/dom/plugins/test/testplugin/nptest.h @@ -61,6 +61,12 @@ typedef enum { FUNCTION_NPP_WRITE_RPC } TestFunction; +typedef enum { + AD_NONE, + AD_BITMAP, + AD_DXGI +} AsyncDrawing; + typedef enum { ACTIVATION_STATE_UNKNOWN, ACTIVATION_STATE_ACTIVATED, @@ -147,8 +153,16 @@ typedef struct InstanceData { int32_t mouseUpEventCount; int32_t bugMode; std::string javaCodebase; + AsyncDrawing asyncDrawing; + NPAsyncSurface *frontBuffer; + NPAsyncSurface *backBuffer; } InstanceData; void notifyDidPaint(InstanceData* instanceData); +#if defined(XP_WIN) +bool setupDxgiSurfaces(InstanceData* instanceData); +void drawDxgiBitmapColor(InstanceData* instanceData); +#endif + #endif // nptest_h_ diff --git a/dom/plugins/test/testplugin/nptest_windows.cpp b/dom/plugins/test/testplugin/nptest_windows.cpp index e6ab5b034e..6a752c6230 100644 --- a/dom/plugins/test/testplugin/nptest_windows.cpp +++ b/dom/plugins/test/testplugin/nptest_windows.cpp @@ -39,6 +39,7 @@ #include #include +#include using namespace std; @@ -48,9 +49,11 @@ LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara struct _PlatformData { HWND childWindow; + IDXGIAdapter1 *adapter; ID3D10Device1 *device; ID3D10Texture2D *frontBuffer; ID3D10Texture2D *backBuffer; + ID2D1Factory *d2d1Factory; }; bool @@ -79,9 +82,192 @@ pluginInstanceInit(InstanceData* instanceData) instanceData->platformData->device = nullptr; instanceData->platformData->frontBuffer = nullptr; instanceData->platformData->backBuffer = nullptr; + instanceData->platformData->adapter = nullptr; + instanceData->platformData->d2d1Factory = nullptr; return NPERR_NO_ERROR; } +static inline bool +openSharedTex2D(ID3D10Device* device, HANDLE handle, ID3D10Texture2D** out) +{ + HRESULT hr = device->OpenSharedResource(handle, __uuidof(ID3D10Texture2D), (void**)out); + if (FAILED(hr) || !*out) { + return false; + } + return true; +} + +// This is overloaded in d2d1.h so we can't use decltype(). +typedef HRESULT (WINAPI*D2D1CreateFactoryFunc)( + D2D1_FACTORY_TYPE factoryType, + REFIID iid, + CONST D2D1_FACTORY_OPTIONS *pFactoryOptions, + void **factory +); + +// Note: we leak modules since we need them anyway. +bool +setupDxgiSurfaces(InstanceData* instanceData) +{ + HMODULE dxgi = LoadLibraryA("dxgi.dll"); + if (!dxgi) { + return false; + } + decltype(CreateDXGIFactory1)* createDXGIFactory1 = + (decltype(CreateDXGIFactory1)*)GetProcAddress(dxgi, "CreateDXGIFactory1"); + if (!createDXGIFactory1) { + return false; + } + + IDXGIFactory1* factory1 = nullptr; + HRESULT hr = createDXGIFactory1(__uuidof(IDXGIFactory1), (void**)&factory1); + if (FAILED(hr) || !factory1) { + return false; + } + + hr = factory1->EnumAdapters1(0, &instanceData->platformData->adapter); + factory1->Release(); + if (FAILED(hr) || !instanceData->platformData->adapter) { + return false; + } + + HMODULE d3d10 = LoadLibraryA("d3d10_1.dll"); + if (!d3d10) { + return false; + } + + decltype(D3D10CreateDevice1)* createDevice = + (decltype(D3D10CreateDevice1)*)GetProcAddress(d3d10, "D3D10CreateDevice1"); + if (!createDevice) { + return false; + } + + + hr = createDevice( + instanceData->platformData->adapter, + D3D10_DRIVER_TYPE_HARDWARE, nullptr, + D3D10_CREATE_DEVICE_BGRA_SUPPORT | + D3D10_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS, + D3D10_FEATURE_LEVEL_10_1, + D3D10_1_SDK_VERSION, &instanceData->platformData->device); + if (FAILED(hr) || !instanceData->platformData->device) { + return false; + } + + if (!openSharedTex2D(instanceData->platformData->device, + instanceData->frontBuffer->sharedHandle, + &instanceData->platformData->frontBuffer)) + { + return false; + } + if (!openSharedTex2D(instanceData->platformData->device, + instanceData->backBuffer->sharedHandle, + &instanceData->platformData->backBuffer)) + { + return false; + } + + HMODULE d2d1 = LoadLibraryA("D2d1.dll"); + if (!d2d1) { + return false; + } + auto d2d1CreateFactory = (D2D1CreateFactoryFunc)GetProcAddress(d2d1, "D2D1CreateFactory"); + if (!d2d1CreateFactory) { + return false; + } + + D2D1_FACTORY_OPTIONS options; + options.debugLevel = D2D1_DEBUG_LEVEL_NONE; + + hr = d2d1CreateFactory(D2D1_FACTORY_TYPE_MULTI_THREADED, + __uuidof(ID2D1Factory), + &options, + (void**)&instanceData->platformData->d2d1Factory); + if (FAILED(hr) || !instanceData->platformData->d2d1Factory) { + return false; + } + + return true; +} + +void +drawDxgiBitmapColor(InstanceData* instanceData) +{ + NPP npp = instanceData->npp; + + HRESULT hr; + + IDXGISurface* surface = nullptr; + hr = instanceData->platformData->backBuffer->QueryInterface( + __uuidof(IDXGISurface), (void **)&surface); + if (FAILED(hr) || !surface) { + return; + } + + D2D1_RENDER_TARGET_PROPERTIES props = + D2D1::RenderTargetProperties( + D2D1_RENDER_TARGET_TYPE_DEFAULT, + D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED)); + + ID2D1RenderTarget* target = nullptr; + hr = instanceData->platformData->d2d1Factory->CreateDxgiSurfaceRenderTarget( + surface, + &props, + &target); + if (FAILED(hr) || !target) { + surface->Release(); + return; + } + + IDXGIKeyedMutex* mutex = nullptr; + hr = instanceData->platformData->backBuffer->QueryInterface(__uuidof(IDXGIKeyedMutex), (void**)&mutex); + if (mutex) { + mutex->AcquireSync(0, 0); + } + + target->BeginDraw(); + + unsigned char subpixels[4]; + memcpy(subpixels, + &instanceData->scriptableObject->drawColor, + sizeof(subpixels)); + + auto rect = D2D1::RectF( + 0, 0, + instanceData->backBuffer->size.width, + instanceData->backBuffer->size.height); + auto color = D2D1::ColorF( + float(subpixels[3] * subpixels[2]) / 0xFF, + float(subpixels[3] * subpixels[1]) / 0xFF, + float(subpixels[3] * subpixels[0]) / 0xFF, + float(subpixels[3]) / 0xff); + + ID2D1SolidColorBrush* brush = nullptr; + hr = target->CreateSolidColorBrush(color, &brush); + if (SUCCEEDED(hr) && brush) { + target->FillRectangle(rect, brush); + brush->Release(); + brush = nullptr; + } + hr = target->EndDraw(); + + if (mutex) { + mutex->ReleaseSync(0); + mutex->Release(); + mutex = nullptr; + } + + target->Release(); + surface->Release(); + target = nullptr; + surface = nullptr; + + NPN_SetCurrentAsyncSurface(npp, instanceData->backBuffer, NULL); + std::swap(instanceData->backBuffer, instanceData->frontBuffer); + std::swap(instanceData->platformData->backBuffer, + instanceData->platformData->frontBuffer); +} + void pluginInstanceShutdown(InstanceData* instanceData) { @@ -92,9 +278,15 @@ pluginInstanceShutdown(InstanceData* instanceData) if (pd->backBuffer) { pd->backBuffer->Release(); } + if (pd->d2d1Factory) { + pd->d2d1Factory->Release(); + } if (pd->device) { pd->device->Release(); } + if (pd->adapter) { + pd->adapter->Release(); + } NPN_MemFree(instanceData->platformData); instanceData->platformData = 0; } diff --git a/gfx/layers/ImageTypes.h b/gfx/layers/ImageTypes.h index 4509fd14af..2300085c2a 100644 --- a/gfx/layers/ImageTypes.h +++ b/gfx/layers/ImageTypes.h @@ -86,7 +86,12 @@ enum class ImageFormat { /** * A share handle to a ID3D11Texture2D. */ - D3D11_SHARE_HANDLE_TEXTURE + D3D11_SHARE_HANDLE_TEXTURE, + + /** + * A wrapper around a drawable TextureClient. + */ + TEXTURE_WRAPPER }; enum class StereoMode { diff --git a/gfx/layers/TextureWrapperImage.cpp b/gfx/layers/TextureWrapperImage.cpp new file mode 100644 index 0000000000..1329728ea5 --- /dev/null +++ b/gfx/layers/TextureWrapperImage.cpp @@ -0,0 +1,53 @@ +/* -*- Mode: C++; tab-width: 20; 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 "TextureWrapperImage.h" + +namespace mozilla { +namespace layers { + +using namespace mozilla::gfx; + +TextureWrapperImage::TextureWrapperImage(TextureClient* aClient, const IntRect& aPictureRect) + : Image(nullptr, ImageFormat::TEXTURE_WRAPPER), + mPictureRect(aPictureRect), + mTextureClient(aClient) +{ +} + +TextureWrapperImage::~TextureWrapperImage() +{ +} + +gfx::IntSize +TextureWrapperImage::GetSize() +{ + return mTextureClient->GetSize(); +} + +gfx::IntRect +TextureWrapperImage::GetPictureRect() +{ + return mPictureRect; +} + +already_AddRefed +TextureWrapperImage::GetAsSourceSurface() +{ + TextureClientAutoLock autoLock(mTextureClient, OpenMode::OPEN_READ); + if (!autoLock.Succeeded()) { + return nullptr; + } + + return mTextureClient->BorrowDrawTarget()->Snapshot(); +} + +TextureClient* +TextureWrapperImage::GetTextureClient(CompositableClient* aClient) +{ + return mTextureClient; +} + +} // namespace layers +} // namespace mozilla diff --git a/gfx/layers/TextureWrapperImage.h b/gfx/layers/TextureWrapperImage.h new file mode 100644 index 0000000000..fabb8c871f --- /dev/null +++ b/gfx/layers/TextureWrapperImage.h @@ -0,0 +1,37 @@ +/* -*- Mode: C++; tab-width: 20; 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 GFX_LAYERS_TEXTUREWRAPPINGIMAGE_H_ +#define GFX_LAYERS_TEXTUREWRAPPINGIMAGE_H_ + +#include "mozilla/RefPtr.h" +#include "ImageContainer.h" +#include "mozilla/layers/TextureClient.h" + +namespace mozilla { +namespace layers { + +// Wraps a TextureClient into an Image. This may only be used on the main +// thread, and only with TextureClients that support BorrowDrawTarget(). +class TextureWrapperImage final : public Image +{ +public: + TextureWrapperImage(TextureClient* aClient, const gfx::IntRect& aPictureRect); + ~TextureWrapperImage() override; + + gfx::IntSize GetSize() override; + gfx::IntRect GetPictureRect() override; + already_AddRefed GetAsSourceSurface() override; + TextureClient* GetTextureClient(CompositableClient* aClient) override; + +private: + gfx::IntRect mPictureRect; + RefPtr mTextureClient; +}; + +} // namespace layers +} // namespace mozilla + +#endif // GFX_LAYERS_TEXTUREWRAPPINGIMAGE_H_ diff --git a/gfx/layers/client/TextureClient.cpp b/gfx/layers/client/TextureClient.cpp index f5f833f6ed..4b87f89cd0 100644 --- a/gfx/layers/client/TextureClient.cpp +++ b/gfx/layers/client/TextureClient.cpp @@ -10,9 +10,11 @@ #include "gfxPlatform.h" // for gfxPlatform #include "mozilla/Atomics.h" #include "mozilla/ipc/SharedMemory.h" // for SharedMemory, etc +#include "mozilla/layers/AsyncTransactionTracker.h" #include "mozilla/layers/CompositableForwarder.h" #include "mozilla/layers/ISurfaceAllocator.h" #include "mozilla/layers/ImageDataSerializer.h" +#include "mozilla/layers/TextureClientRecycleAllocator.h" #include "mozilla/layers/YCbCrImageDataSerializer.h" #include "nsDebug.h" // for NS_ASSERTION, NS_WARNING, etc #include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc @@ -27,6 +29,7 @@ #include "gfxUtils.h" // for gfxUtils::GetAsLZ4Base64Str #include "IPDLActor.h" #include "BufferTexture.h" +#include "gfxPrefs.h" #ifdef XP_WIN #include "mozilla/layers/TextureD3D9.h" diff --git a/gfx/layers/composite/PaintedLayerComposite.cpp b/gfx/layers/composite/PaintedLayerComposite.cpp index e6493d3edf..87dd79b3ae 100644 --- a/gfx/layers/composite/PaintedLayerComposite.cpp +++ b/gfx/layers/composite/PaintedLayerComposite.cpp @@ -125,7 +125,7 @@ PaintedLayerComposite::RenderLayer(const gfx::IntRect& aClipRect) RenderWithAllMasks(this, compositor, aClipRect, - [&](EffectChain& effectChain, const Rect& clipRect) { + [&](EffectChain& effectChain, const gfx::Rect& clipRect) { mBuffer->SetPaintWillResample(MayResample()); mBuffer->Composite(this, effectChain, diff --git a/gfx/layers/ipc/ImageContainerParent.cpp b/gfx/layers/ipc/ImageContainerParent.cpp index f1bc194f46..31aba5bec5 100644 --- a/gfx/layers/ipc/ImageContainerParent.cpp +++ b/gfx/layers/ipc/ImageContainerParent.cpp @@ -9,6 +9,7 @@ #include "nsThreadUtils.h" #include "mozilla/layers/ImageHost.h" +#include "mozilla/unused.h" namespace mozilla { namespace layers { diff --git a/gfx/layers/moz.build b/gfx/layers/moz.build index 58f6612740..f450f5e199 100644 --- a/gfx/layers/moz.build +++ b/gfx/layers/moz.build @@ -177,6 +177,7 @@ EXPORTS.mozilla.layers += [ 'opengl/TextureHostOGL.h', 'PersistentBufferProvider.h', 'RenderTrace.h', + 'TextureWrapperImage.h', 'TransactionIdAllocator.h', 'YCbCrImageDataSerializer.h', ] @@ -348,6 +349,7 @@ UNIFIED_SOURCES += [ 'ReadbackProcessor.cpp', 'RenderTrace.cpp', 'RotatedBuffer.cpp', + 'TextureWrapperImage.cpp', 'YCbCrImageDataSerializer.cpp', ] diff --git a/gfx/thebes/gfxPlatform.h b/gfx/thebes/gfxPlatform.h index b571b917de..6ce806a198 100644 --- a/gfx/thebes/gfxPlatform.h +++ b/gfx/thebes/gfxPlatform.h @@ -633,6 +633,11 @@ public: // devices. Currently this is only used on Windows. virtual void GetDeviceInitData(mozilla::gfx::DeviceInitData* aOut); + // Plugin async drawing support. + virtual bool SupportsPluginDirectBitmapDrawing() { + return false; + } + protected: gfxPlatform(); virtual ~gfxPlatform(); diff --git a/gfx/thebes/gfxPrefs.h b/gfx/thebes/gfxPrefs.h index bbe10fcd4c..2a96f23e8e 100644 --- a/gfx/thebes/gfxPrefs.h +++ b/gfx/thebes/gfxPrefs.h @@ -192,6 +192,7 @@ private: DECL_GFX_PREF(Live, "browser.ui.zoom.force-user-scalable", ForceUserScalable, bool, false); DECL_GFX_PREF(Live, "browser.viewport.desktopWidth", DesktopViewportWidth, int32_t, 980); + DECL_GFX_PREF(Live, "dom.ipc.plugins.asyncdrawing.enabled", PluginAsyncDrawingEnabled, bool, false); DECL_GFX_PREF(Live, "dom.meta-viewport.enabled", MetaViewportEnabled, bool, false); DECL_GFX_PREF(Once, "dom.vr.enabled", VREnabled, bool, false); DECL_GFX_PREF(Once, "dom.vr.oculus.enabled", VROculusEnabled, bool, true); diff --git a/gfx/thebes/gfxWindowsPlatform.cpp b/gfx/thebes/gfxWindowsPlatform.cpp index 33e6fe1bc7..a99cb96b05 100644 --- a/gfx/thebes/gfxWindowsPlatform.cpp +++ b/gfx/thebes/gfxWindowsPlatform.cpp @@ -3062,3 +3062,9 @@ gfxWindowsPlatform::GetDeviceInitData(DeviceInitData* aOut) aOut->adapter() = DxgiAdapterDesc::From(desc); } } + +bool +gfxWindowsPlatform::SupportsPluginDirectDXGIDrawing() +{ + return false; +} diff --git a/gfx/thebes/gfxWindowsPlatform.h b/gfx/thebes/gfxWindowsPlatform.h index 1978bbd301..680d0fb62f 100644 --- a/gfx/thebes/gfxWindowsPlatform.h +++ b/gfx/thebes/gfxWindowsPlatform.h @@ -295,6 +295,8 @@ public: void GetDeviceInitData(mozilla::gfx::DeviceInitData* aOut) override; + bool SupportsPluginDirectDXGIDrawing(); + protected: bool AccelerateLayersByDefault() override { return true; diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 5e7ebe3451..52a2324fea 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -2907,6 +2907,9 @@ pref("dom.ipc.plugins.asyncInit.enabled", false); pref("dom.ipc.plugins.asyncInit.enabled", true); #endif +// Allow the AsyncDrawing mode to be used for plugins. +pref("dom.ipc.plugins.asyncdrawing.enabled", false); + pref("dom.ipc.processCount", 1); // Enable caching of Moz2D Path objects for SVG geometry elements diff --git a/widget/PuppetWidget.cpp b/widget/PuppetWidget.cpp index 9787c30110..f229560e8d 100644 --- a/widget/PuppetWidget.cpp +++ b/widget/PuppetWidget.cpp @@ -441,7 +441,7 @@ PuppetWidget::SynthesizeNativeMouseScrollEvent(mozilla::LayoutDeviceIntPoint aPo nsresult PuppetWidget::SynthesizeNativeTouchPoint(uint32_t aPointerId, TouchPointerState aPointerState, - nsIntPoint aPointerScreenPoint, + ScreenIntPoint aPointerScreenPoint, double aPointerPressure, uint32_t aPointerOrientation, nsIObserver* aObserver) @@ -457,7 +457,7 @@ PuppetWidget::SynthesizeNativeTouchPoint(uint32_t aPointerId, } nsresult -PuppetWidget::SynthesizeNativeTouchTap(nsIntPoint aPointerScreenPoint, +PuppetWidget::SynthesizeNativeTouchTap(ScreenIntPoint aPointerScreenPoint, bool aLongTap, nsIObserver* aObserver) { diff --git a/widget/PuppetWidget.h b/widget/PuppetWidget.h index c6d0f50d87..45f691074e 100644 --- a/widget/PuppetWidget.h +++ b/widget/PuppetWidget.h @@ -242,11 +242,11 @@ public: nsIObserver* aObserver) override; virtual nsresult SynthesizeNativeTouchPoint(uint32_t aPointerId, TouchPointerState aPointerState, - nsIntPoint aPointerScreenPoint, + ScreenIntPoint aPointerScreenPoint, double aPointerPressure, uint32_t aPointerOrientation, nsIObserver* aObserver) override; - virtual nsresult SynthesizeNativeTouchTap(nsIntPoint aPointerScreenPoint, + virtual nsresult SynthesizeNativeTouchTap(ScreenIntPoint aPointerScreenPoint, bool aLongTap, nsIObserver* aObserver) override; virtual nsresult ClearNativeTouchSequence(nsIObserver* aObserver) override; diff --git a/widget/cocoa/nsChildView.mm b/widget/cocoa/nsChildView.mm index f39a58cd95..8262285150 100644 --- a/widget/cocoa/nsChildView.mm +++ b/widget/cocoa/nsChildView.mm @@ -65,6 +65,7 @@ #include "mozilla/layers/CompositorOGL.h" #include "mozilla/layers/CompositorParent.h" #include "mozilla/layers/BasicCompositor.h" +#include "mozilla/layers/InputAPZContext.h" #include "gfxUtils.h" #include "gfxPrefs.h" #include "mozilla/gfx/2D.h" @@ -2619,6 +2620,10 @@ nsChildView::TrackScrollEventAsSwipe(const mozilla::PanGestureInput& aSwipeStart mSwipeTracker = new SwipeTracker(*this, aSwipeStartEvent, aAllowedDirections, direction); + + if (!mAPZC) { + mCurrentPanGestureBelongsToSwipe = true; + } } void @@ -2827,11 +2832,27 @@ nsChildView::DispatchAPZWheelInputEvent(InputData& aEvent, bool aCanTriggerSwipe event = panInput.ToWidgetWheelEvent(this); if (aCanTriggerSwipe) { SwipeInfo swipeInfo = SendMayStartSwipe(panInput); + + // We're in the non-APZ case here, but we still want to know whether + // the event was routed to a child process, so we use InputAPZContext + // to get that piece of information. + ScrollableLayerGuid guid; + InputAPZContext context(guid, 0, nsEventStatus_eIgnore); + event.mCanTriggerSwipe = swipeInfo.wantsSwipe; DispatchEvent(&event, status); - if (event.TriggersSwipe()) { - TrackScrollEventAsSwipe(panInput, swipeInfo.allowedDirections); - mCurrentPanGestureBelongsToSwipe = true; + if (swipeInfo.wantsSwipe) { + if (context.WasRoutedToChildProcess()) { + // We don't know whether this event can start a swipe, so we need + // to queue up events and wait for a call to ReportSwipeStarted. + mSwipeEventQueue = MakeUnique(swipeInfo.allowedDirections, 0); + } else if (event.TriggersSwipe()) { + TrackScrollEventAsSwipe(panInput, swipeInfo.allowedDirections); + } + } + + if (mSwipeEventQueue && mSwipeEventQueue->inputBlockId == 0) { + mSwipeEventQueue->queuedEvents.AppendElement(panInput); } return; } diff --git a/widget/gonk/nsWindow.cpp b/widget/gonk/nsWindow.cpp index 4248b2fdd9..6d5b070bad 100644 --- a/widget/gonk/nsWindow.cpp +++ b/widget/gonk/nsWindow.cpp @@ -258,7 +258,7 @@ private: nsresult nsWindow::SynthesizeNativeTouchPoint(uint32_t aPointerId, TouchPointerState aPointerState, - nsIntPoint aPointerScreenPoint, + ScreenIntPoint aPointerScreenPoint, double aPointerPressure, uint32_t aPointerOrientation, nsIObserver* aObserver) @@ -286,7 +286,7 @@ nsWindow::SynthesizeNativeTouchPoint(uint32_t aPointerId, if (index >= 0) { // found an existing touch point, update it SingleTouchData& point = mSynthesizedTouchInput->mTouches[index]; - point.mScreenPoint = ScreenIntPoint::FromUnknownPoint(aPointerScreenPoint); + point.mScreenPoint = aPointerScreenPoint; point.mRotationAngle = (float)aPointerOrientation; point.mForce = (float)aPointerPressure; inputToDispatch.mType = MultiTouchInput::MULTITOUCH_MOVE; @@ -294,7 +294,7 @@ nsWindow::SynthesizeNativeTouchPoint(uint32_t aPointerId, // new touch point, add it mSynthesizedTouchInput->mTouches.AppendElement(SingleTouchData( (int32_t)aPointerId, - ScreenIntPoint::FromUnknownPoint(aPointerScreenPoint), + aPointerScreenPoint, ScreenSize(0, 0), (float)aPointerOrientation, (float)aPointerPressure)); @@ -312,7 +312,7 @@ nsWindow::SynthesizeNativeTouchPoint(uint32_t aPointerId, : MultiTouchInput::MULTITOUCH_CANCEL); inputToDispatch.mTouches.AppendElement(SingleTouchData( (int32_t)aPointerId, - ScreenIntPoint::FromUnknownPoint(aPointerScreenPoint), + aPointerScreenPoint, ScreenSize(0, 0), (float)aPointerOrientation, (float)aPointerPressure)); diff --git a/widget/gonk/nsWindow.h b/widget/gonk/nsWindow.h index db3adfec94..415d560b42 100644 --- a/widget/gonk/nsWindow.h +++ b/widget/gonk/nsWindow.h @@ -89,7 +89,7 @@ public: nsEventStatus& aStatus); virtual nsresult SynthesizeNativeTouchPoint(uint32_t aPointerId, TouchPointerState aPointerState, - nsIntPoint aPointerScreenPoint, + ScreenIntPoint aPointerScreenPoint, double aPointerPressure, uint32_t aPointerOrientation, nsIObserver* aObserver) override; diff --git a/widget/nsBaseWidget.cpp b/widget/nsBaseWidget.cpp index 5b82338bb3..fd25cccd64 100644 --- a/widget/nsBaseWidget.cpp +++ b/widget/nsBaseWidget.cpp @@ -1834,7 +1834,7 @@ nsBaseWidget::GetWidgetScreen() } nsresult -nsIWidget::SynthesizeNativeTouchTap(nsIntPoint aPointerScreenPoint, bool aLongTap, +nsIWidget::SynthesizeNativeTouchTap(ScreenIntPoint aPointerScreenPoint, bool aLongTap, nsIObserver* aObserver) { AutoObserverNotifier notifier(aObserver, "touchtap"); @@ -1910,7 +1910,7 @@ nsIWidget::OnLongTapTimerCallback(nsITimer* aTimer, void* aClosure) return; } - AutoObserverNotifier notiifer(self->mLongTapTouchPoint->mObserver, "touchtap"); + AutoObserverNotifier notifier(self->mLongTapTouchPoint->mObserver, "touchtap"); // finished, remove the touch point self->mLongTapTimer->Cancel(); diff --git a/widget/nsBaseWidget.h b/widget/nsBaseWidget.h index f48e06c8b8..d6dd5cbc66 100644 --- a/widget/nsBaseWidget.h +++ b/widget/nsBaseWidget.h @@ -413,7 +413,7 @@ protected: virtual nsresult SynthesizeNativeTouchPoint(uint32_t aPointerId, TouchPointerState aPointerState, - nsIntPoint aPointerScreenPoint, + ScreenIntPoint aPointerScreenPoint, double aPointerPressure, uint32_t aPointerOrientation, nsIObserver* aObserver) override diff --git a/widget/nsIWidget.h b/widget/nsIWidget.h index c2e7d036aa..c3f91683da 100644 --- a/widget/nsIWidget.h +++ b/widget/nsIWidget.h @@ -337,6 +337,7 @@ class nsIWidget : public nsISupports { typedef mozilla::LayoutDeviceIntRect LayoutDeviceIntRect; typedef mozilla::LayoutDeviceIntRegion LayoutDeviceIntRegion; typedef mozilla::LayoutDeviceIntSize LayoutDeviceIntSize; + typedef mozilla::ScreenIntPoint ScreenIntPoint; // Used in UpdateThemeGeometries. struct ThemeGeometry { @@ -1643,7 +1644,7 @@ class nsIWidget : public nsISupports { */ virtual nsresult SynthesizeNativeTouchPoint(uint32_t aPointerId, TouchPointerState aPointerState, - nsIntPoint aPointerScreenPoint, + ScreenIntPoint aPointerScreenPoint, double aPointerPressure, uint32_t aPointerOrientation, nsIObserver* aObserver) = 0; @@ -1656,7 +1657,7 @@ class nsIWidget : public nsISupports { * @param aObserver The observer that will get notified once the events * have been dispatched. */ - virtual nsresult SynthesizeNativeTouchTap(nsIntPoint aPointerScreenPoint, + virtual nsresult SynthesizeNativeTouchTap(ScreenIntPoint aPointerScreenPoint, bool aLongTap, nsIObserver* aObserver); @@ -1692,7 +1693,7 @@ private: class LongTapInfo { public: - LongTapInfo(int32_t aPointerId, nsIntPoint& aPoint, + LongTapInfo(int32_t aPointerId, ScreenIntPoint& aPoint, mozilla::TimeDuration aDuration, nsIObserver* aObserver) : mPointerId(aPointerId), @@ -1704,7 +1705,7 @@ private: } int32_t mPointerId; - nsIntPoint mPosition; + ScreenIntPoint mPosition; mozilla::TimeDuration mDuration; nsCOMPtr mObserver; mozilla::TimeStamp mStamp; diff --git a/widget/windows/nsWindowBase.cpp b/widget/windows/nsWindowBase.cpp index 1141eb0a5f..55cbec2a6b 100644 --- a/widget/windows/nsWindowBase.cpp +++ b/widget/windows/nsWindowBase.cpp @@ -70,7 +70,7 @@ nsWindowBase::InitTouchInjection() } bool -nsWindowBase::InjectTouchPoint(uint32_t aId, nsIntPoint& aPointerScreenPoint, +nsWindowBase::InjectTouchPoint(uint32_t aId, ScreenIntPoint& aPointerScreenPoint, POINTER_FLAGS aFlags, uint32_t aPressure, uint32_t aOrientation) { @@ -108,7 +108,7 @@ nsWindowBase::InjectTouchPoint(uint32_t aId, nsIntPoint& aPointerScreenPoint, nsresult nsWindowBase::SynthesizeNativeTouchPoint(uint32_t aPointerId, nsIWidget::TouchPointerState aPointerState, - nsIntPoint aPointerScreenPoint, + ScreenIntPoint aPointerScreenPoint, double aPointerPressure, uint32_t aPointerOrientation, nsIObserver* aObserver) @@ -173,15 +173,6 @@ nsWindowBase::SynthesizeNativeTouchPoint(uint32_t aPointerId, NS_ERROR_UNEXPECTED : NS_OK; } -// static -PLDHashOperator -nsWindowBase::CancelTouchPoints(const unsigned int& aPointerId, nsAutoPtr& aInfo, void* aUserArg) -{ - nsWindowBase* self = static_cast(aUserArg); - self->InjectTouchPoint(aInfo.get()->mPointerId, aInfo.get()->mPosition, POINTER_FLAG_CANCELED); - return (PLDHashOperator)(PL_DHASH_NEXT|PL_DHASH_REMOVE); -} - nsresult nsWindowBase::ClearNativeTouchSequence(nsIObserver* aObserver) { @@ -191,7 +182,12 @@ nsWindowBase::ClearNativeTouchSequence(nsIObserver* aObserver) } // cancel all input points - mActivePointers.Enumerate(CancelTouchPoints, (void*)this); + for (auto iter = mActivePointers.Iter(); !iter.Done(); iter.Next()) { + nsAutoPtr& info = iter.Data(); + InjectTouchPoint(info.get()->mPointerId, info.get()->mPosition, + POINTER_FLAG_CANCELED); + iter.Remove(); + } nsBaseWidget::ClearNativeTouchSequence(nullptr); diff --git a/widget/windows/nsWindowBase.h b/widget/windows/nsWindowBase.h index 7e00405a41..ec5f4fc8d6 100644 --- a/widget/windows/nsWindowBase.h +++ b/widget/windows/nsWindowBase.h @@ -90,7 +90,7 @@ public: */ virtual nsresult SynthesizeNativeTouchPoint(uint32_t aPointerId, TouchPointerState aPointerState, - nsIntPoint aPointerScreenPoint, + ScreenIntPoint aPointerScreenPoint, double aPointerPressure, uint32_t aPointerOrientation, nsIObserver* aObserver) override; @@ -105,25 +105,23 @@ public: protected: static bool InitTouchInjection(); - bool InjectTouchPoint(uint32_t aId, nsIntPoint& aPointerScreenPoint, + bool InjectTouchPoint(uint32_t aId, ScreenIntPoint& aPointerScreenPoint, POINTER_FLAGS aFlags, uint32_t aPressure = 1024, uint32_t aOrientation = 90); class PointerInfo { public: - PointerInfo(int32_t aPointerId, nsIntPoint& aPoint) : + PointerInfo(int32_t aPointerId, ScreenIntPoint& aPoint) : mPointerId(aPointerId), mPosition(aPoint) { } int32_t mPointerId; - nsIntPoint mPosition; + ScreenIntPoint mPosition; }; - static PLDHashOperator CancelTouchPoints(const unsigned int& aPointerId, nsAutoPtr& aInfo, void* aUserArg); - nsClassHashtable mActivePointers; static bool sTouchInjectInitialized; static InjectTouchInputPtr sInjectTouchFuncPtr;