Implement Core Graphics drawing model for out-of-process plugins. b=554676 r=josh sr=cjones

This commit is contained in:
Benoit Girard 2010-03-26 16:07:37 -04:00
parent fe512e0b26
commit 99e5fc5faf
8 changed files with 264 additions and 6 deletions

View File

@ -63,10 +63,35 @@ struct ParamTraits<mozilla::plugins::NPRemoteEvent>
static void Write(Message* aMsg, const paramType& aParam) static void Write(Message* aMsg, const paramType& aParam)
{ {
// Make a non-const copy of aParam so that we can muck with
// its insides for tranport
paramType paramCopy;
paramCopy.event = aParam.event;
switch (paramCopy.event.type) {
case NPCocoaEventDrawRect:
// Don't serialize the context pointer
paramCopy.event.data.draw.context = NULL;
break;
default:
// ignore any events we don't expect
return;
}
aMsg->WriteBytes(&paramCopy, sizeof(paramType));
} }
static bool Read(const Message* aMsg, void** aIter, paramType* aResult) static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
{ {
const char* bytes = 0;
if (!aMsg->ReadBytes(aIter, &bytes, sizeof(paramType))) {
return false;
}
memcpy(aResult, bytes, sizeof(paramType));
return true; return true;
} }

View File

@ -79,6 +79,9 @@ child:
rpc NPP_HandleEvent(NPRemoteEvent event) rpc NPP_HandleEvent(NPRemoteEvent event)
returns (int16_t handled); returns (int16_t handled);
// special cases where we need to a shared memory buffer
rpc NPP_HandleEvent_Shmem(NPRemoteEvent event, Shmem buffer)
returns (int16_t handled, Shmem rtnbuffer);
// special cases of HandleEvent to make mediating races simpler // special cases of HandleEvent to make mediating races simpler
rpc Paint(NPRemoteEvent event) rpc Paint(NPRemoteEvent event)
returns (int16_t handled); returns (int16_t handled);
@ -106,6 +109,10 @@ parent:
returns (NPError result); returns (NPError result);
rpc NPN_SetValue_NPPVpluginTransparent(bool transparent) rpc NPN_SetValue_NPPVpluginTransparent(bool transparent)
returns (NPError result); returns (NPError result);
rpc NPN_SetValue_NPPVpluginDrawingModel(int drawingModel)
returns (NPError result);
rpc NPN_SetValue_NPPVpluginEventModel(int eventModel)
returns (NPError result);
rpc NPN_GetURL(nsCString url, nsCString target) rpc NPN_GetURL(nsCString url, nsCString target)
returns (NPError result); returns (NPError result);

View File

@ -80,6 +80,7 @@ child:
returns (NPError rv); returns (NPError rv);
parent: parent:
async XXX_HACK_FIXME_cjones(Shmem _);
rpc NPN_UserAgent() rpc NPN_UserAgent()
returns (nsCString userAgent); returns (nsCString userAgent);

View File

@ -77,8 +77,9 @@ using mozilla::gfx::SharedDIB;
#include <windowsx.h> #include <windowsx.h>
#define NS_OOPP_DOUBLEPASS_MSGID TEXT("MozDoublePassMsg") #define NS_OOPP_DOUBLEPASS_MSGID TEXT("MozDoublePassMsg")
#elif defined(XP_MACOSX)
#endif // defined(OS_WIN) #include <ApplicationServices/ApplicationServices.h>
#endif // defined(XP_MACOSX)
PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface, PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface,
const nsCString& aMimeType) const nsCString& aMimeType)
@ -320,6 +321,30 @@ PluginInstanceChild::NPN_GetValue(NPNVariable aVar,
#endif #endif
} }
#ifdef XP_MACOSX
case NPNVsupportsCoreGraphicsBool: {
*((NPBool*)aValue) = true;
return NPERR_NO_ERROR;
}
case NPNVsupportsCoreAnimationBool: {
*((NPBool*)aValue) = false;
return NPERR_NO_ERROR;
}
case NPNVsupportsCocoaBool: {
*((NPBool*)aValue) = true;
return NPERR_NO_ERROR;
}
#ifndef NP_NO_QUICKDRAW
case NPNVsupportsQuickDrawBool: {
*((NPBool*)aValue) = false;
return NPERR_NO_ERROR;
}
#endif /* NP_NO_QUICKDRAW */
#endif /* XP_MACOSX */
default: default:
PR_LOG(gPluginLog, PR_LOG_WARNING, PR_LOG(gPluginLog, PR_LOG_WARNING,
("In PluginInstanceChild::NPN_GetValue: Unhandled NPNVariable %i (%s)", ("In PluginInstanceChild::NPN_GetValue: Unhandled NPNVariable %i (%s)",
@ -359,6 +384,28 @@ PluginInstanceChild::NPN_SetValue(NPPVariable aVar, void* aValue)
return rv; return rv;
} }
#ifdef XP_MACOSX
case NPPVpluginDrawingModel: {
NPError rv;
int drawingModel = (int16) (intptr_t) aValue;
if (!CallNPN_SetValue_NPPVpluginDrawingModel(drawingModel, &rv))
return NPERR_GENERIC_ERROR;
return rv;
}
case NPPVpluginEventModel: {
NPError rv;
int eventModel = (int16) (intptr_t) aValue;
if (!CallNPN_SetValue_NPPVpluginEventModel(eventModel, &rv))
return NPERR_GENERIC_ERROR;
return rv;
}
#endif
default: default:
PR_LOG(gPluginLog, PR_LOG_WARNING, PR_LOG(gPluginLog, PR_LOG_WARNING,
("In PluginInstanceChild::NPN_SetValue: Unhandled NPPVariable %i (%s)", ("In PluginInstanceChild::NPN_SetValue: Unhandled NPPVariable %i (%s)",
@ -464,7 +511,7 @@ PluginInstanceChild::AnswerNPP_HandleEvent(const NPRemoteEvent& event,
event.event.xgraphicsexpose.drawable)); event.event.xgraphicsexpose.drawable));
#endif #endif
#ifdef OS_MACOSX #ifdef XP_MACOSX
// Mac OS X does not define an NPEvent structure. It defines more specific types. // Mac OS X does not define an NPEvent structure. It defines more specific types.
NPCocoaEvent evcopy = event.event; NPCocoaEvent evcopy = event.event;
#else #else
@ -513,6 +560,73 @@ PluginInstanceChild::AnswerNPP_HandleEvent(const NPRemoteEvent& event,
return true; return true;
} }
#ifdef XP_MACOSX
bool
PluginInstanceChild::AnswerNPP_HandleEvent_Shmem(const NPRemoteEvent& event,
Shmem& mem,
int16_t* handled,
Shmem* rtnmem)
{
PLUGIN_LOG_DEBUG_FUNCTION;
AssertPluginThread();
// We return access to the shared memory buffer after returning.
NPCocoaEvent evcopy = event.event;
if (evcopy.type == NPCocoaEventDrawRect) {
CGColorSpaceRef cSpace = ::CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
if (!cSpace) {
PLUGIN_LOG_DEBUG(("Could not allocate ColorSpace."));
*handled = false;
*rtnmem = mem;
return true;
}
void* cgContextByte = mem.get<char>();
CGContextRef ctxt = ::CGBitmapContextCreate(cgContextByte, mWindow.width, mWindow.height, 8, mWindow.width * 4, cSpace, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host);
::CGColorSpaceRelease(cSpace);
if (!ctxt) {
PLUGIN_LOG_DEBUG(("Could not allocate CGBitmapContext."));
*handled = false;
*rtnmem = mem;
return true;
}
evcopy.data.draw.context = ctxt;
} else {
PLUGIN_LOG_DEBUG(("Invalid event type for AnswerNNP_HandleEvent_Shmem."));
*handled = false;
*rtnmem = mem;
return true;
}
if (!mPluginIface->event) {
*handled = false;
} else {
*handled = mPluginIface->event(&mData, reinterpret_cast<void*>(&evcopy));
}
// Some events need cleaning up.
if (evcopy.type == NPCocoaEventDrawRect) {
::CGContextRelease(evcopy.data.draw.context);
}
*rtnmem = mem;
return true;
}
#else
bool
PluginInstanceChild::AnswerNPP_HandleEvent_Shmem(const NPRemoteEvent& event,
Shmem& mem,
int16_t* handled,
Shmem* rtnmem)
{
NS_RUNTIMEABORT("not reached.");
*rtnmem = mem;
return true;
}
#endif
bool bool
PluginInstanceChild::RecvWindowPosChanged(const NPRemoteEvent& event) PluginInstanceChild::RecvWindowPosChanged(const NPRemoteEvent& event)
{ {
@ -641,7 +755,7 @@ PluginInstanceChild::AnswerNPP_SetWindow(const NPRemoteWindow& aWindow)
break; break;
} }
#elif defined(OS_MACOSX) #elif defined(XP_MACOSX)
mWindow.x = aWindow.x; mWindow.x = aWindow.x;
mWindow.y = aWindow.y; mWindow.y = aWindow.y;
@ -650,6 +764,9 @@ PluginInstanceChild::AnswerNPP_SetWindow(const NPRemoteWindow& aWindow)
mWindow.clipRect = aWindow.clipRect; mWindow.clipRect = aWindow.clipRect;
mWindow.type = aWindow.type; mWindow.type = aWindow.type;
if (mPluginIface->setwindow)
(void) mPluginIface->setwindow(&mData, &mWindow);
#else #else
# error Implement me for your OS # error Implement me for your OS
#endif #endif

View File

@ -88,6 +88,8 @@ protected:
virtual bool virtual bool
AnswerNPP_HandleEvent(const NPRemoteEvent& event, int16_t* handled); AnswerNPP_HandleEvent(const NPRemoteEvent& event, int16_t* handled);
virtual bool
AnswerNPP_HandleEvent_Shmem(const NPRemoteEvent& event, Shmem& mem, int16_t* handled, Shmem* rtnmem);
NS_OVERRIDE NS_OVERRIDE
virtual bool virtual bool

View File

@ -59,7 +59,9 @@ UINT gOOPPStopNativeLoopEvent =
RegisterWindowMessage(L"SyncChannel Stop Inner Loop Message"); RegisterWindowMessage(L"SyncChannel Stop Inner Loop Message");
#elif defined(MOZ_WIDGET_GTK2) #elif defined(MOZ_WIDGET_GTK2)
#include <gdk/gdk.h> #include <gdk/gdk.h>
#endif #elif defined(XP_MACOSX)
#include <ApplicationServices/ApplicationServices.h>
#endif // defined(XP_MACOSX)
using namespace mozilla::plugins; using namespace mozilla::plugins;
@ -75,6 +77,10 @@ PluginInstanceParent::PluginInstanceParent(PluginModuleParent* parent,
, mPluginWndProc(NULL) , mPluginWndProc(NULL)
, mNestedEventState(false) , mNestedEventState(false)
#endif // defined(XP_WIN) #endif // defined(XP_WIN)
#if defined(XP_MACOSX)
, mShWidth(0)
, mShHeight(0)
#endif
{ {
} }
@ -293,7 +299,6 @@ PluginInstanceParent::AnswerNPN_GetValue_NPNVprivateModeBool(bool* value,
return true; return true;
} }
bool bool
PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginWindow( PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginWindow(
const bool& windowed, NPError* result) const bool& windowed, NPError* result)
@ -314,6 +319,33 @@ PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginTransparent(
return true; return true;
} }
bool
PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginDrawingModel(
const int& drawingModel, NPError* result)
{
#ifdef XP_MACOSX
*result = mNPNIface->setvalue(mNPP, NPPVpluginDrawingModel,
(void*)drawingModel);
return true;
#else
*result = NPERR_GENERIC_ERROR;
return true;
#endif
}
bool
PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginEventModel(
const int& eventModel, NPError* result)
{
#ifdef XP_MACOSX
*result = mNPNIface->setvalue(mNPP, NPPVpluginEventModel,
(void*)eventModel);
return true;
#else
*result = NPERR_GENERIC_ERROR;
return true;
#endif
}
bool bool
PluginInstanceParent::AnswerNPN_GetURL(const nsCString& url, PluginInstanceParent::AnswerNPN_GetURL(const nsCString& url,
@ -438,6 +470,20 @@ PluginInstanceParent::NPP_SetWindow(const NPWindow* aWindow)
window.type = aWindow->type; window.type = aWindow->type;
#endif #endif
#if defined(XP_MACOSX)
if (mShWidth * mShHeight != window.width * window.height) {
// XXX: benwa: OMG MEMORY LEAK!
// There is currently no way dealloc the shmem
// so for now we will leak the memory and will fix this ASAP!
if (!AllocShmem(window.width * window.height * 4, &mShSurface)) {
PLUGIN_LOG_DEBUG(("Shared memory could not be allocated."));
return NPERR_GENERIC_ERROR;
}
mShWidth = window.width;
mShHeight = window.height;
}
#endif
#if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX) #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
const NPSetWindowCallbackStruct* ws_info = const NPSetWindowCallbackStruct* ws_info =
static_cast<NPSetWindowCallbackStruct*>(aWindow->ws_info); static_cast<NPSetWindowCallbackStruct*>(aWindow->ws_info);
@ -626,6 +672,52 @@ PluginInstanceParent::NPP_HandleEvent(void* event)
} }
#endif #endif
#ifdef XP_MACOSX
if (npevent->type == NPCocoaEventDrawRect) {
if (mShWidth == 0 && mShHeight == 0) {
PLUGIN_LOG_DEBUG(("NPCocoaEventDrawRect on window of size 0."));
return false;
}
if (!mShSurface.IsReadable()) {
PLUGIN_LOG_DEBUG(("Shmem is not readable."));
return false;
}
if (!CallNPP_HandleEvent_Shmem(npremoteevent, mShSurface, &handled, &mShSurface))
return false; // no good way to handle errors here...
if (!mShSurface.IsReadable()) {
PLUGIN_LOG_DEBUG(("Shmem not returned. Either the plugin crashed or we have a bug."));
return false;
}
char* shContextByte = mShSurface.get<char>();
CGColorSpaceRef cSpace = ::CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
if (!cSpace) {
PLUGIN_LOG_DEBUG(("Could not allocate ColorSpace."));
return true;
}
CGContextRef shContext = ::CGBitmapContextCreate(shContextByte,
mShWidth, mShHeight, 8, mShWidth*4, cSpace,
kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host);
::CGColorSpaceRelease(cSpace);
if (!shContext) {
PLUGIN_LOG_DEBUG(("Could not allocate CGBitmapContext."));
return true;
}
CGImageRef shImage = ::CGBitmapContextCreateImage(shContext);
if (shImage) {
CGContextRef cgContext = npevent->data.draw.context;
::CGContextDrawImage(cgContext, CGRectMake(0,0,mShWidth,mShHeight), shImage);
::CGImageRelease(shImage);
}
::CGContextRelease(shContext);
return handled;
}
#endif
if (!CallNPP_HandleEvent(npremoteevent, &handled)) if (!CallNPP_HandleEvent(npremoteevent, &handled))
return 0; // no good way to handle errors here... return 0; // no good way to handle errors here...

View File

@ -126,6 +126,12 @@ public:
virtual bool virtual bool
AnswerNPN_SetValue_NPPVpluginTransparent(const bool& transparent, AnswerNPN_SetValue_NPPVpluginTransparent(const bool& transparent,
NPError* result); NPError* result);
virtual bool
AnswerNPN_SetValue_NPPVpluginDrawingModel(const int& drawingModel,
NPError* result);
virtual bool
AnswerNPN_SetValue_NPPVpluginEventModel(const int& eventModel,
NPError* result);
virtual bool virtual bool
AnswerNPN_GetURL(const nsCString& url, const nsCString& target, AnswerNPN_GetURL(const nsCString& url, const nsCString& target,
@ -263,6 +269,12 @@ private:
WNDPROC mPluginWndProc; WNDPROC mPluginWndProc;
bool mNestedEventState; bool mNestedEventState;
#endif // defined(XP_WIN) #endif // defined(XP_WIN)
#if defined(OS_MACOSX)
private:
Shmem mShSurface;
size_t mShWidth;
size_t mShHeight;
#endif // definied(OS_MACOSX)
}; };

View File

@ -142,6 +142,8 @@ protected:
return MediateRace(parent, child); return MediateRace(parent, child);
} }
virtual bool RecvXXX_HACK_FIXME_cjones(Shmem& mem) { NS_RUNTIMEABORT("not reached"); return false; }
NS_OVERRIDE NS_OVERRIDE
virtual bool ShouldContinueFromReplyTimeout(); virtual bool ShouldContinueFromReplyTimeout();