mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 19:35:51 +00:00
Bug 521257 - Support NPImageExpose on Maemo/Hildon only. r=roc
This commit is contained in:
parent
b5f3112586
commit
cc4f335fc9
@ -139,6 +139,8 @@
|
||||
#include "gfxWindowsSurface.h"
|
||||
#endif
|
||||
|
||||
#include "gfxImageSurface.h"
|
||||
|
||||
// accessibility support
|
||||
#ifdef ACCESSIBILITY
|
||||
#include "nsIAccessibilityService.h"
|
||||
@ -169,7 +171,6 @@ enum { XKeyPress = KeyPress };
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_PLATFORM_HILDON
|
||||
#define MOZ_POST_VISIBILITY_EVENTS 1
|
||||
#define MOZ_COMPOSITED_PLUGINS 1
|
||||
#endif
|
||||
|
||||
@ -543,7 +544,19 @@ private:
|
||||
const nsIntRect& mDirtyRect;
|
||||
};
|
||||
#endif
|
||||
#ifdef MOZ_PLATFORM_HILDON
|
||||
|
||||
// On hildon, we attempt to use NPImageExpose which allows us faster
|
||||
// painting. We hold a memory buffer to avoid reallocations on
|
||||
// every plugin invalidate.
|
||||
unsigned char* mImageExposeBuffer;
|
||||
gfxIntSize mImageExposeBufferSize;
|
||||
|
||||
nsresult NativeImageDraw(gfxContext *aContext,
|
||||
NPWindow* mWindow,
|
||||
const nsIntSize& mPluginSize,
|
||||
const nsIntRect& mDirtyRect);
|
||||
#endif
|
||||
};
|
||||
|
||||
// Mac specific code to fix up port position and clip
|
||||
@ -2383,6 +2396,10 @@ nsPluginInstanceOwner::nsPluginInstanceOwner()
|
||||
mLastPoint = nsIntPoint(0,0);
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_PLATFORM_HILDON
|
||||
mImageExposeBuffer = nsnull;
|
||||
mImageExposeBufferSize = gfxIntSize(0,0);
|
||||
#endif
|
||||
PR_LOG(nsObjectFrameLM, PR_LOG_DEBUG,
|
||||
("nsPluginInstanceOwner %p created\n", this));
|
||||
}
|
||||
@ -2436,6 +2453,13 @@ nsPluginInstanceOwner::~nsPluginInstanceOwner()
|
||||
if (mInstance) {
|
||||
mInstance->InvalidateOwner();
|
||||
}
|
||||
|
||||
#ifdef MOZ_PLATFORM_HILDON
|
||||
if (mImageExposeBuffer)
|
||||
free(mImageExposeBuffer);
|
||||
mImageExposeBuffer = nsnull;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3228,7 +3252,7 @@ nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays()
|
||||
mNumCachedAttrs++;
|
||||
}
|
||||
|
||||
// "plugins.force.wmode" preference is forcing wmode type for plguins
|
||||
// "plugins.force.wmode" preference is forcing wmode type for plugins
|
||||
// possible values - "opaque", "transparent", "windowed"
|
||||
nsAdoptingCString wmodeType = nsContentUtils::GetCharPref("plugins.force.wmode");
|
||||
if (!wmodeType.IsEmpty())
|
||||
@ -4762,7 +4786,6 @@ void nsPluginInstanceOwner::Paint(gfxContext* aContext,
|
||||
NPWindow* window;
|
||||
GetWindow(window);
|
||||
|
||||
Renderer renderer(window, mInstance, pluginSize, pluginDirtyRect);
|
||||
PRUint32 rendererFlags =
|
||||
Renderer::DRAW_SUPPORTS_OFFSET |
|
||||
Renderer::DRAW_SUPPORTS_CLIP_RECT |
|
||||
@ -4778,6 +4801,16 @@ void nsPluginInstanceOwner::Paint(gfxContext* aContext,
|
||||
gfxContextAutoSaveRestore autoSR(aContext);
|
||||
aContext->Translate(pluginRect.pos);
|
||||
|
||||
#ifdef MOZ_PLATFORM_HILDON
|
||||
PRBool simpleImageRender = PR_FALSE;
|
||||
mInstance->GetValueFromPlugin(NPPVpluginWindowlessLocalBool, (void *)&simpleImageRender);
|
||||
|
||||
if (simpleImageRender && NS_SUCCEEDED(NativeImageDraw(aContext, window, pluginSize, pluginDirtyRect)))
|
||||
return;
|
||||
|
||||
#endif
|
||||
|
||||
Renderer renderer(window, mInstance, pluginSize, pluginDirtyRect);
|
||||
renderer.Draw(aContext, window->width, window->height,
|
||||
rendererFlags, nsnull);
|
||||
}
|
||||
@ -4799,6 +4832,164 @@ DepthOfVisual(const Screen* screen, const Visual* visual)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_PLATFORM_HILDON
|
||||
|
||||
// NativeImageDraw
|
||||
//
|
||||
// This method supports the NPImageExpose API which is specific to the
|
||||
// HILDON platform. Basically what it allows us to do is to pass a
|
||||
// memory buffer into a plugin (namely flash), and have flase draw
|
||||
// directly into the buffer.
|
||||
//
|
||||
// It may be faster if the rest of the system used offscreen image
|
||||
// surfaces, but right now offscreen surfaces are using X
|
||||
// surfaces. And because of this, we need to create a new image
|
||||
// surface and copy that to the passed gfx context.
|
||||
//
|
||||
// This is not ideal and it should not be faster than what a
|
||||
// windowless plugin can do. However, in A/B testing of flash on the
|
||||
// N900, this approach is considerably faster.
|
||||
//
|
||||
// Hopefully this API can die off in favor of a more robust plugin API.
|
||||
|
||||
nsresult
|
||||
nsPluginInstanceOwner::NativeImageDraw(gfxContext *aContext,
|
||||
NPWindow* 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;
|
||||
|
||||
NPRect 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<NPSetWindowCallbackStruct*>(mWindow->ws_info);
|
||||
ws_info->visual = 0;
|
||||
ws_info->colormap = 0;
|
||||
if (ws_info->depth != 24) {
|
||||
ws_info->depth = 24;
|
||||
doupdatewindow = PR_TRUE;
|
||||
}
|
||||
|
||||
if (doupdatewindow)
|
||||
mInstance->SetWindow(mWindow);
|
||||
|
||||
nsIntRect dirtyRect = mDirtyRect;
|
||||
|
||||
// Intersect the dirty rect with the clip rect to ensure that it lies within
|
||||
// the drawable.
|
||||
if (!dirtyRect.IntersectRect(mDirtyRect, clipRect))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
XEvent pluginEvent;
|
||||
NPImageExpose imageExpose;
|
||||
XGraphicsExposeEvent& exposeEvent = pluginEvent.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;
|
||||
|
||||
// defaults for NPImageExpose
|
||||
imageExpose.depth = 24;
|
||||
imageExpose.translateX = 1;
|
||||
imageExpose.translateY = 1;
|
||||
imageExpose.scaleX = 1;
|
||||
imageExpose.scaleY = 1;
|
||||
|
||||
// only have the plugin draw what is dirty
|
||||
imageExpose.x = mDirtyRect.x;
|
||||
imageExpose.y = mDirtyRect.y;
|
||||
imageExpose.width = mDirtyRect.width;
|
||||
imageExpose.height = mDirtyRect.height;
|
||||
|
||||
// reallocate buffer if there is a size change or if we haven't allocated one yet. We probably can do this
|
||||
// somewhere else.
|
||||
if (!mImageExposeBuffer ||
|
||||
(mImageExposeBufferSize.width * mImageExposeBufferSize.height < mWindow->width * mWindow->height)) {
|
||||
if (mImageExposeBuffer)
|
||||
free(mImageExposeBuffer);
|
||||
|
||||
mImageExposeBuffer = (unsigned char*) malloc (mWindow->width * mWindow->height * 4);
|
||||
mImageExposeBufferSize = gfxIntSize(mWindow->width, mWindow->height);
|
||||
}
|
||||
|
||||
NS_ENSURE_TRUE(mImageExposeBuffer, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
// Because we are reusing mImageExposeBuffer, there might be old bytes. The API NPImageExpose
|
||||
// expects that the buffer be zero'ed out.
|
||||
memset(mImageExposeBuffer, 0, mImageExposeBufferSize.height * mImageExposeBufferSize.width * 4);
|
||||
|
||||
nsRefPtr<gfxImageSurface> surf = new gfxImageSurface(mImageExposeBuffer,
|
||||
mImageExposeBufferSize,
|
||||
mImageExposeBufferSize.width * 4,
|
||||
gfxASurface::ImageFormatRGB24);
|
||||
NS_ENSURE_TRUE(surf, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
// Setup temporary context scaled size
|
||||
imageExpose.stride = surf->Stride();
|
||||
imageExpose.data = reinterpret_cast<char*>(surf->Data());
|
||||
imageExpose.dataSize.width = surf->Width();
|
||||
imageExpose.dataSize.height = surf->Height();
|
||||
|
||||
PRBool eventHandled = PR_FALSE;
|
||||
// Get Image surface from original context
|
||||
// Draw plugin content to temp surface
|
||||
mInstance->HandleEvent(&pluginEvent, &eventHandled);
|
||||
|
||||
if (eventHandled) {
|
||||
nsRefPtr<gfxPattern> pat = new gfxPattern(surf);
|
||||
aContext->NewPath();
|
||||
aContext->PixelSnappedRectangleAndSetPattern(gfxRect(0, 0, mWindow->width, mWindow->height), pat);
|
||||
aContext->Fill();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MOZ_WIDGET_GTK2)
|
||||
nsresult
|
||||
nsPluginInstanceOwner::Renderer::NativeDraw(GdkDrawable * drawable,
|
||||
|
@ -337,6 +337,10 @@ typedef enum {
|
||||
/* Used for negotiating event models */
|
||||
, NPPVpluginEventModel = 1001
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_PLATFORM_HILDON
|
||||
, NPPVpluginWindowlessLocalBool = 2002
|
||||
#endif
|
||||
} NPPVariable;
|
||||
|
||||
/*
|
||||
@ -379,6 +383,9 @@ typedef enum {
|
||||
#endif
|
||||
, NPNVsupportsCocoaBool = 3001 /* TRUE if the browser supports the Cocoa event model */
|
||||
#endif
|
||||
#ifdef MOZ_PLATFORM_HILDON
|
||||
, NPNVSupportsWindowlessLocal = 2002
|
||||
#endif
|
||||
} NPNVariable;
|
||||
|
||||
typedef enum {
|
||||
@ -419,6 +426,21 @@ typedef struct _NPWindow
|
||||
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
|
||||
{
|
||||
|
@ -1980,6 +1980,13 @@ _getvalue(NPP npp, NPNVariable variable, void *result)
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
#ifdef MOZ_PLATFORM_HILDON
|
||||
case NPNVSupportsWindowlessLocal: {
|
||||
*(NPBool*)result = PR_TRUE;
|
||||
return NPERR_NO_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
case NPNVpluginDrawingModel: {
|
||||
if (npp) {
|
||||
@ -2103,7 +2110,12 @@ _setvalue(NPP npp, NPPVariable variable, void *result)
|
||||
return inst->SetWindowless(bWindowless);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MOZ_PLATFORM_HILDON
|
||||
case NPPVpluginWindowlessLocalBool: {
|
||||
NPBool bWindowlessLocal = (result != nsnull);
|
||||
return inst->SetWindowlessLocal(bWindowlessLocal);
|
||||
}
|
||||
#endif
|
||||
case NPPVpluginTransparentBool: {
|
||||
NPBool bTransparent = (result != nsnull);
|
||||
return inst->SetTransparent(bTransparent);
|
||||
|
@ -881,6 +881,7 @@ nsNPAPIPluginInstance::nsNPAPIPluginInstance(NPPluginFuncs* callbacks,
|
||||
#endif
|
||||
#endif
|
||||
mWindowless(PR_FALSE),
|
||||
mWindowlessLocal(PR_FALSE),
|
||||
mTransparent(PR_FALSE),
|
||||
mStarted(PR_FALSE),
|
||||
mCached(PR_FALSE),
|
||||
@ -1382,6 +1383,14 @@ NS_IMETHODIMP nsNPAPIPluginInstance::HandleEvent(void* event, PRBool* handled)
|
||||
|
||||
NS_IMETHODIMP nsNPAPIPluginInstance::GetValueFromPlugin(NPPVariable variable, void* value)
|
||||
{
|
||||
#ifdef MOZ_PLATFORM_HILDON
|
||||
// The maemo flash plugin does not remember this. It sets the
|
||||
// value, but doesn't support the get value.
|
||||
if (variable == NPPVpluginWindowlessLocalBool) {
|
||||
*(NPBool*)value = mWindowlessLocal;
|
||||
return NS_OK;
|
||||
}
|
||||
#endif
|
||||
nsresult res = NS_OK;
|
||||
if (mCallbacks->getvalue && mStarted) {
|
||||
PluginDestructionGuard guard(this);
|
||||
@ -1421,6 +1430,12 @@ NPError nsNPAPIPluginInstance::SetWindowless(PRBool aWindowless)
|
||||
return NPERR_NO_ERROR;
|
||||
}
|
||||
|
||||
NPError nsNPAPIPluginInstance::SetWindowlessLocal(PRBool aWindowlessLocal)
|
||||
{
|
||||
mWindowlessLocal = aWindowlessLocal;
|
||||
return NPERR_NO_ERROR;
|
||||
}
|
||||
|
||||
NPError nsNPAPIPluginInstance::SetTransparent(PRBool aTransparent)
|
||||
{
|
||||
mTransparent = aTransparent;
|
||||
|
@ -86,6 +86,8 @@ public:
|
||||
|
||||
NPError SetWindowless(PRBool aWindowless);
|
||||
|
||||
NPError SetWindowlessLocal(PRBool aWindowlessLocal);
|
||||
|
||||
NPError SetTransparent(PRBool aTransparent);
|
||||
|
||||
NPError SetWantsAllNetworkStreams(PRBool aWantsAllNetworkStreams);
|
||||
@ -149,6 +151,7 @@ protected:
|
||||
// these are used to store the windowless properties
|
||||
// which the browser will later query
|
||||
PRPackedBool mWindowless;
|
||||
PRPackedBool mWindowlessLocal;
|
||||
PRPackedBool mTransparent;
|
||||
PRPackedBool mStarted;
|
||||
PRPackedBool mCached;
|
||||
|
Loading…
Reference in New Issue
Block a user