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)
{
// 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)
{
const char* bytes = 0;
if (!aMsg->ReadBytes(aIter, &bytes, sizeof(paramType))) {
return false;
}
memcpy(aResult, bytes, sizeof(paramType));
return true;
}

View File

@ -79,6 +79,9 @@ child:
rpc NPP_HandleEvent(NPRemoteEvent event)
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
rpc Paint(NPRemoteEvent event)
returns (int16_t handled);
@ -106,6 +109,10 @@ parent:
returns (NPError result);
rpc NPN_SetValue_NPPVpluginTransparent(bool transparent)
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)
returns (NPError result);

View File

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

View File

@ -77,8 +77,9 @@ using mozilla::gfx::SharedDIB;
#include <windowsx.h>
#define NS_OOPP_DOUBLEPASS_MSGID TEXT("MozDoublePassMsg")
#endif // defined(OS_WIN)
#elif defined(XP_MACOSX)
#include <ApplicationServices/ApplicationServices.h>
#endif // defined(XP_MACOSX)
PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface,
const nsCString& aMimeType)
@ -320,6 +321,30 @@ PluginInstanceChild::NPN_GetValue(NPNVariable aVar,
#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:
PR_LOG(gPluginLog, PR_LOG_WARNING,
("In PluginInstanceChild::NPN_GetValue: Unhandled NPNVariable %i (%s)",
@ -359,6 +384,28 @@ PluginInstanceChild::NPN_SetValue(NPPVariable aVar, void* aValue)
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:
PR_LOG(gPluginLog, PR_LOG_WARNING,
("In PluginInstanceChild::NPN_SetValue: Unhandled NPPVariable %i (%s)",
@ -464,7 +511,7 @@ PluginInstanceChild::AnswerNPP_HandleEvent(const NPRemoteEvent& event,
event.event.xgraphicsexpose.drawable));
#endif
#ifdef OS_MACOSX
#ifdef XP_MACOSX
// Mac OS X does not define an NPEvent structure. It defines more specific types.
NPCocoaEvent evcopy = event.event;
#else
@ -513,6 +560,73 @@ PluginInstanceChild::AnswerNPP_HandleEvent(const NPRemoteEvent& event,
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
PluginInstanceChild::RecvWindowPosChanged(const NPRemoteEvent& event)
{
@ -641,7 +755,7 @@ PluginInstanceChild::AnswerNPP_SetWindow(const NPRemoteWindow& aWindow)
break;
}
#elif defined(OS_MACOSX)
#elif defined(XP_MACOSX)
mWindow.x = aWindow.x;
mWindow.y = aWindow.y;
@ -650,6 +764,9 @@ PluginInstanceChild::AnswerNPP_SetWindow(const NPRemoteWindow& aWindow)
mWindow.clipRect = aWindow.clipRect;
mWindow.type = aWindow.type;
if (mPluginIface->setwindow)
(void) mPluginIface->setwindow(&mData, &mWindow);
#else
# error Implement me for your OS
#endif

View File

@ -88,6 +88,8 @@ protected:
virtual bool
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
virtual bool

View File

@ -59,7 +59,9 @@ UINT gOOPPStopNativeLoopEvent =
RegisterWindowMessage(L"SyncChannel Stop Inner Loop Message");
#elif defined(MOZ_WIDGET_GTK2)
#include <gdk/gdk.h>
#endif
#elif defined(XP_MACOSX)
#include <ApplicationServices/ApplicationServices.h>
#endif // defined(XP_MACOSX)
using namespace mozilla::plugins;
@ -75,6 +77,10 @@ PluginInstanceParent::PluginInstanceParent(PluginModuleParent* parent,
, mPluginWndProc(NULL)
, mNestedEventState(false)
#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;
}
bool
PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginWindow(
const bool& windowed, NPError* result)
@ -314,6 +319,33 @@ PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginTransparent(
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
PluginInstanceParent::AnswerNPN_GetURL(const nsCString& url,
@ -438,6 +470,20 @@ PluginInstanceParent::NPP_SetWindow(const NPWindow* aWindow)
window.type = aWindow->type;
#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)
const NPSetWindowCallbackStruct* ws_info =
static_cast<NPSetWindowCallbackStruct*>(aWindow->ws_info);
@ -626,6 +672,52 @@ PluginInstanceParent::NPP_HandleEvent(void* event)
}
#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))
return 0; // no good way to handle errors here...

View File

@ -126,6 +126,12 @@ public:
virtual bool
AnswerNPN_SetValue_NPPVpluginTransparent(const bool& transparent,
NPError* result);
virtual bool
AnswerNPN_SetValue_NPPVpluginDrawingModel(const int& drawingModel,
NPError* result);
virtual bool
AnswerNPN_SetValue_NPPVpluginEventModel(const int& eventModel,
NPError* result);
virtual bool
AnswerNPN_GetURL(const nsCString& url, const nsCString& target,
@ -263,6 +269,12 @@ private:
WNDPROC mPluginWndProc;
bool mNestedEventState;
#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);
}
virtual bool RecvXXX_HACK_FIXME_cjones(Shmem& mem) { NS_RUNTIMEABORT("not reached"); return false; }
NS_OVERRIDE
virtual bool ShouldContinueFromReplyTimeout();