diff --git a/layout/generic/nsObjectFrame.cpp b/layout/generic/nsObjectFrame.cpp --- a/layout/generic/nsObjectFrame.cpp +++ b/layout/generic/nsObjectFrame.cpp @@ -140,6 +140,8 @@ #include "gfxWindowsSurface.h" #endif +#include "gfxImageSurface.h" + // accessibility support #ifdef ACCESSIBILITY #include "nsIAccessibilityService.h" @@ -550,6 +552,10 @@ const nsIntRect& mDirtyRect; }; #endif + nsresult NativeImageDraw(gfxContext *aContext, + nsPluginWindow* mWindow, + const nsIntSize& mPluginSize, + const nsIntRect& mDirtyRect); }; @@ -2528,6 +2534,7 @@ presContext->DevPixelsToAppUnits(invalidRect->top), presContext->DevPixelsToAppUnits(invalidRect->right - invalidRect->left), presContext->DevPixelsToAppUnits(invalidRect->bottom - invalidRect->top)); + mOwner->Invalidate(rect); } @@ -4530,7 +4537,6 @@ nsPluginWindow* window; GetWindow(window); - Renderer renderer(window, mInstance, pluginSize, pluginDirtyRect); PRUint32 rendererFlags = Renderer::DRAW_SUPPORTS_OFFSET | Renderer::DRAW_SUPPORTS_CLIP_RECT | @@ -4547,6 +4553,17 @@ gfxContextAutoSaveRestore autoSR(aContext); aContext->Translate(pluginRect.pos); + PRBool simpleImageRender = PR_FALSE; + mInstance->GetValue(nsPluginInstanceVariable_WindowlessLocalBool, + (void *)&simpleImageRender); + + nsRefPtr target = aContext->CurrentSurface(); + if (simpleImageRender && target->GetType() == gfxASurface::SurfaceTypeImage) { + NativeImageDraw(aContext, window, pluginSize, pluginDirtyRect); + return; + } + + Renderer renderer(window, mInstance, pluginSize, pluginDirtyRect); renderer.Draw(aContext, window->width, window->height, rendererFlags, nsnull); } @@ -4567,6 +4584,115 @@ return 0; } #endif + +nsresult +nsPluginInstanceOwner::NativeImageDraw(gfxContext *aContext, + nsPluginWindow* mWindow, + const nsIntSize& mPluginSize, + const nsIntRect& mDirtyRect) + +{ + PRBool doupdatewindow = PR_FALSE; + + if (mWindow->x || mWindow->y) { + mWindow->x = 0; + mWindow->y = 0; + doupdatewindow = PR_TRUE; + } + + if (nsIntSize(mWindow->width, mWindow->height) != mPluginSize) { + mWindow->width = mPluginSize.width; + mWindow->height = mPluginSize.height; + doupdatewindow = PR_TRUE; + } + + // The clip rect is relative to drawable top-left. + nsIntRect clipRect; + clipRect.x = 0; + clipRect.y = 0; + clipRect.width = mWindow->width; + clipRect.height = mWindow->height; + + nsPluginRect newClipRect; + newClipRect.left = clipRect.x; + newClipRect.top = clipRect.y; + newClipRect.right = clipRect.XMost(); + newClipRect.bottom = clipRect.YMost(); + if (mWindow->clipRect.left != newClipRect.left || + mWindow->clipRect.top != newClipRect.top || + mWindow->clipRect.right != newClipRect.right || + mWindow->clipRect.bottom != newClipRect.bottom) { + mWindow->clipRect = newClipRect; + doupdatewindow = PR_TRUE; + } + + NPSetWindowCallbackStruct* ws_info = + static_cast(mWindow->ws_info); + ws_info->visual = 0; + ws_info->colormap = 0; + ws_info->depth = 24; + + if (doupdatewindow) + mInstance->SetWindow(mWindow); + + // Until we don't have agreement about how to pass NPImageExpose structure to plugin + // it will be packed into XEvent.xgraphicsexpose.drawable member + // Probably we have to use something like HandleEvent2 API. see bug 477456 in BMO +#ifdef MOZ_X11 + // Translate the dirty rect to drawable coordinates. + nsIntRect dirtyRect = mDirtyRect; + // Intersect the dirty rect with the clip rect to ensure that it lies within + // the drawable. + if (!dirtyRect.IntersectRect(dirtyRect, clipRect)) + return NS_OK; + + nsPluginEvent pluginEvent; + NPImageExpose imageExpose; + XGraphicsExposeEvent& exposeEvent = pluginEvent.event.xgraphicsexpose; + // set the drawing info + exposeEvent.type = GraphicsExpose; + exposeEvent.display = 0; + // Store imageExpose structure pointer as drawable member + exposeEvent.drawable = (Drawable)&imageExpose; + exposeEvent.x = mDirtyRect.x; + exposeEvent.y = mDirtyRect.y; + exposeEvent.width = mDirtyRect.width; + exposeEvent.height = mDirtyRect.height; + exposeEvent.count = 0; + // information not set: + exposeEvent.serial = 0; + exposeEvent.send_event = False; + exposeEvent.major_code = 0; + exposeEvent.minor_code = 0; + + nsRefPtr surface = static_cast(aContext->OriginalSurface()); + NS_ENSURE_TRUE(surface, NS_ERROR_OUT_OF_MEMORY); + // Calculate src buffer pointer according to translation + // and set it as drawable member + gfxMatrix matr = aContext->CurrentMatrix(); + gfxPoint pt = matr.GetTranslation(); + imageExpose.depth = 24; + imageExpose.x = mDirtyRect.x; + imageExpose.y = mDirtyRect.y; + imageExpose.width = mDirtyRect.width; + imageExpose.height = mDirtyRect.height; + // Setup temporary context scaled size + imageExpose.stride = surface->Stride(); + imageExpose.data = (char *)surface->Data(); + imageExpose.dataSize.width = surface->Width(); + imageExpose.dataSize.height = surface->Height(); + imageExpose.translateX = pt.x; + imageExpose.translateY = pt.y; + imageExpose.scaleX = matr.xx; + imageExpose.scaleY = matr.yy; + PRBool eventHandled = PR_FALSE; + // Get Image surface from original context + // Draw plugin content to temp surface + mInstance->HandleEvent(&pluginEvent, &eventHandled); +#endif + + return NS_OK; +} #if defined(MOZ_WIDGET_GTK2) nsresult diff --git a/modules/plugin/base/public/npapi.h b/modules/plugin/base/public/npapi.h --- a/modules/plugin/base/public/npapi.h +++ b/modules/plugin/base/public/npapi.h @@ -333,6 +333,7 @@ /* Used for negotiating drawing models */ , NPPVpluginDrawingModel = 1000 #endif + , NPPVpluginWindowlessLocalBool = 2002 } NPPVariable; /* @@ -371,6 +372,7 @@ #endif , NPNVsupportsCoreGraphicsBool = 2001 #endif + , NPNVSupportsWindowlessLocal = 2002 } NPNVariable; typedef enum { @@ -412,6 +414,21 @@ NPWindowType type; /* Is this a window or a drawable? */ } NPWindow; +typedef struct _NPImageExpose +{ + char* data; /* image pointer */ + int32_t stride; /* Stride of data image pointer */ + int32_t depth; /* Depth of image pointer */ + int32_t x; /* Expose x */ + int32_t y; /* Expose y */ + uint32_t width; /* Expose width */ + uint32_t height; /* Expose height */ + NPSize dataSize; /* Data buffer size */ + float translateX; /* translate X matrix value */ + float translateY; /* translate Y matrix value */ + float scaleX; /* scale X matrix value */ + float scaleY; /* scale Y matrix value */ +} NPImageExpose; typedef struct _NPFullPrint { @@ -580,6 +597,7 @@ #define NPVERS_HAS_PLUGIN_THREAD_ASYNC_CALL 19 #define NPVERS_HAS_ALL_NETWORK_STREAMS 20 #define NPVERS_HAS_URL_AND_AUTH_INFO 21 +#define NPVERS_HAS_WINDOWLESS_LOCAL 22 /*----------------------------------------------------------------------*/ /* Function Prototypes */ diff --git a/modules/plugin/base/public/nsplugindefs.h b/modules/plugin/base/public/nsplugindefs.h --- a/modules/plugin/base/public/nsplugindefs.h +++ b/modules/plugin/base/public/nsplugindefs.h @@ -204,6 +204,7 @@ #ifdef XP_MACOSX , nsPluginInstanceVariable_DrawingModel = 20 #endif + , nsPluginInstanceVariable_WindowlessLocalBool = 21 }; //////////////////////////////////////////////////////////////////////////////// diff --git a/modules/plugin/base/src/nsNPAPIPlugin.cpp b/modules/plugin/base/src/nsNPAPIPlugin.cpp --- a/modules/plugin/base/src/nsNPAPIPlugin.cpp +++ b/modules/plugin/base/src/nsNPAPIPlugin.cpp @@ -2054,6 +2054,15 @@ return NPERR_GENERIC_ERROR; } + case NPNVSupportsWindowlessLocal: { +#if defined(XP_WIN) || defined(XP_MACOSX) || (defined(MOZ_X11) && defined(MOZ_WIDGET_GTK2)) + *(NPBool*)result = PR_TRUE; +#else + *(NPBool*)result = PR_FALSE; +#endif + return NPERR_NO_ERROR; + } + #ifdef XP_MACOSX case NPNVpluginDrawingModel: { if (npp) { @@ -2126,6 +2135,11 @@ NPBool bWindowless = (result == nsnull); return inst->SetWindowless(bWindowless); #endif + } + + case NPPVpluginWindowlessLocalBool: { + NPBool bWindowlessLocal = (result != nsnull); + return inst->SetWindowlessLocal(bWindowlessLocal); } case NPPVpluginTransparentBool: { diff --git a/modules/plugin/base/src/nsNPAPIPluginInstance.cpp b/modules/plugin/base/src/nsNPAPIPluginInstance.cpp --- a/modules/plugin/base/src/nsNPAPIPluginInstance.cpp +++ b/modules/plugin/base/src/nsNPAPIPluginInstance.cpp @@ -764,6 +764,7 @@ #endif #endif mWindowless(PR_FALSE), + mWindowlessLocal(PR_FALSE), mTransparent(PR_FALSE), mStarted(PR_FALSE), mCached(PR_FALSE), @@ -1256,6 +1257,10 @@ *(PRBool *)value = mWindowless; break; + case nsPluginInstanceVariable_WindowlessLocalBool: + *(PRBool *)value = mWindowlessLocal; + break; + case nsPluginInstanceVariable_TransparentBool: *(PRBool *)value = mTransparent; break; @@ -1304,6 +1309,12 @@ NPError nsNPAPIPluginInstance::SetWindowless(PRBool aWindowless) { mWindowless = aWindowless; + return NPERR_NO_ERROR; +} + +NPError nsNPAPIPluginInstance::SetWindowlessLocal(PRBool aWindowlessLocal) +{ + mWindowlessLocal = aWindowlessLocal; return NPERR_NO_ERROR; } diff --git a/modules/plugin/base/src/nsNPAPIPluginInstance.h b/modules/plugin/base/src/nsNPAPIPluginInstance.h --- a/modules/plugin/base/src/nsNPAPIPluginInstance.h +++ b/modules/plugin/base/src/nsNPAPIPluginInstance.h @@ -96,6 +96,8 @@ NPError SetWindowless(PRBool aWindowless); + NPError SetWindowlessLocal(PRBool aWindowlessLocal); + NPError SetTransparent(PRBool aTransparent); NPError SetWantsAllNetworkStreams(PRBool aWantsAllNetworkStreams); @@ -156,6 +158,7 @@ // these are used to store the windowless properties // which the browser will later query PRPackedBool mWindowless; + PRPackedBool mWindowlessLocal; PRPackedBool mTransparent; PRPackedBool mStarted; PRPackedBool mCached;