Bug 521257 - Support NPImageExpose on Maemo/Hildon only. r=roc

This commit is contained in:
Doug Turner 2009-10-26 22:18:35 -07:00
Родитель b5f3112586
Коммит cc4f335fc9
5 изменённых файлов: 247 добавлений и 4 удалений

Просмотреть файл

@ -139,6 +139,8 @@
#include "gfxWindowsSurface.h" #include "gfxWindowsSurface.h"
#endif #endif
#include "gfxImageSurface.h"
// accessibility support // accessibility support
#ifdef ACCESSIBILITY #ifdef ACCESSIBILITY
#include "nsIAccessibilityService.h" #include "nsIAccessibilityService.h"
@ -169,7 +171,6 @@ enum { XKeyPress = KeyPress };
#endif #endif
#ifdef MOZ_PLATFORM_HILDON #ifdef MOZ_PLATFORM_HILDON
#define MOZ_POST_VISIBILITY_EVENTS 1
#define MOZ_COMPOSITED_PLUGINS 1 #define MOZ_COMPOSITED_PLUGINS 1
#endif #endif
@ -543,7 +544,19 @@ private:
const nsIntRect& mDirtyRect; const nsIntRect& mDirtyRect;
}; };
#endif #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 // Mac specific code to fix up port position and clip
@ -2383,6 +2396,10 @@ nsPluginInstanceOwner::nsPluginInstanceOwner()
mLastPoint = nsIntPoint(0,0); mLastPoint = nsIntPoint(0,0);
#endif #endif
#ifdef MOZ_PLATFORM_HILDON
mImageExposeBuffer = nsnull;
mImageExposeBufferSize = gfxIntSize(0,0);
#endif
PR_LOG(nsObjectFrameLM, PR_LOG_DEBUG, PR_LOG(nsObjectFrameLM, PR_LOG_DEBUG,
("nsPluginInstanceOwner %p created\n", this)); ("nsPluginInstanceOwner %p created\n", this));
} }
@ -2436,6 +2453,13 @@ nsPluginInstanceOwner::~nsPluginInstanceOwner()
if (mInstance) { if (mInstance) {
mInstance->InvalidateOwner(); mInstance->InvalidateOwner();
} }
#ifdef MOZ_PLATFORM_HILDON
if (mImageExposeBuffer)
free(mImageExposeBuffer);
mImageExposeBuffer = nsnull;
#endif
} }
/* /*
@ -3228,7 +3252,7 @@ nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays()
mNumCachedAttrs++; 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" // possible values - "opaque", "transparent", "windowed"
nsAdoptingCString wmodeType = nsContentUtils::GetCharPref("plugins.force.wmode"); nsAdoptingCString wmodeType = nsContentUtils::GetCharPref("plugins.force.wmode");
if (!wmodeType.IsEmpty()) if (!wmodeType.IsEmpty())
@ -4762,7 +4786,6 @@ void nsPluginInstanceOwner::Paint(gfxContext* aContext,
NPWindow* window; NPWindow* window;
GetWindow(window); GetWindow(window);
Renderer renderer(window, mInstance, pluginSize, pluginDirtyRect);
PRUint32 rendererFlags = PRUint32 rendererFlags =
Renderer::DRAW_SUPPORTS_OFFSET | Renderer::DRAW_SUPPORTS_OFFSET |
Renderer::DRAW_SUPPORTS_CLIP_RECT | Renderer::DRAW_SUPPORTS_CLIP_RECT |
@ -4778,6 +4801,16 @@ void nsPluginInstanceOwner::Paint(gfxContext* aContext,
gfxContextAutoSaveRestore autoSR(aContext); gfxContextAutoSaveRestore autoSR(aContext);
aContext->Translate(pluginRect.pos); 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, renderer.Draw(aContext, window->width, window->height,
rendererFlags, nsnull); rendererFlags, nsnull);
} }
@ -4799,6 +4832,164 @@ DepthOfVisual(const Screen* screen, const Visual* visual)
} }
#endif #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) #if defined(MOZ_WIDGET_GTK2)
nsresult nsresult
nsPluginInstanceOwner::Renderer::NativeDraw(GdkDrawable * drawable, nsPluginInstanceOwner::Renderer::NativeDraw(GdkDrawable * drawable,

Просмотреть файл

@ -337,6 +337,10 @@ typedef enum {
/* Used for negotiating event models */ /* Used for negotiating event models */
, NPPVpluginEventModel = 1001 , NPPVpluginEventModel = 1001
#endif #endif
#ifdef MOZ_PLATFORM_HILDON
, NPPVpluginWindowlessLocalBool = 2002
#endif
} NPPVariable; } NPPVariable;
/* /*
@ -379,6 +383,9 @@ typedef enum {
#endif #endif
, NPNVsupportsCocoaBool = 3001 /* TRUE if the browser supports the Cocoa event model */ , NPNVsupportsCocoaBool = 3001 /* TRUE if the browser supports the Cocoa event model */
#endif #endif
#ifdef MOZ_PLATFORM_HILDON
, NPNVSupportsWindowlessLocal = 2002
#endif
} NPNVariable; } NPNVariable;
typedef enum { typedef enum {
@ -419,6 +426,21 @@ typedef struct _NPWindow
NPWindowType type; /* Is this a window or a drawable? */ NPWindowType type; /* Is this a window or a drawable? */
} NPWindow; } 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 typedef struct _NPFullPrint
{ {

Просмотреть файл

@ -1980,6 +1980,13 @@ _getvalue(NPP npp, NPNVariable variable, void *result)
return NPERR_GENERIC_ERROR; return NPERR_GENERIC_ERROR;
} }
#ifdef MOZ_PLATFORM_HILDON
case NPNVSupportsWindowlessLocal: {
*(NPBool*)result = PR_TRUE;
return NPERR_NO_ERROR;
}
#endif
#ifdef XP_MACOSX #ifdef XP_MACOSX
case NPNVpluginDrawingModel: { case NPNVpluginDrawingModel: {
if (npp) { if (npp) {
@ -2103,7 +2110,12 @@ _setvalue(NPP npp, NPPVariable variable, void *result)
return inst->SetWindowless(bWindowless); return inst->SetWindowless(bWindowless);
#endif #endif
} }
#ifdef MOZ_PLATFORM_HILDON
case NPPVpluginWindowlessLocalBool: {
NPBool bWindowlessLocal = (result != nsnull);
return inst->SetWindowlessLocal(bWindowlessLocal);
}
#endif
case NPPVpluginTransparentBool: { case NPPVpluginTransparentBool: {
NPBool bTransparent = (result != nsnull); NPBool bTransparent = (result != nsnull);
return inst->SetTransparent(bTransparent); return inst->SetTransparent(bTransparent);

Просмотреть файл

@ -881,6 +881,7 @@ nsNPAPIPluginInstance::nsNPAPIPluginInstance(NPPluginFuncs* callbacks,
#endif #endif
#endif #endif
mWindowless(PR_FALSE), mWindowless(PR_FALSE),
mWindowlessLocal(PR_FALSE),
mTransparent(PR_FALSE), mTransparent(PR_FALSE),
mStarted(PR_FALSE), mStarted(PR_FALSE),
mCached(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) 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; nsresult res = NS_OK;
if (mCallbacks->getvalue && mStarted) { if (mCallbacks->getvalue && mStarted) {
PluginDestructionGuard guard(this); PluginDestructionGuard guard(this);
@ -1421,6 +1430,12 @@ NPError nsNPAPIPluginInstance::SetWindowless(PRBool aWindowless)
return NPERR_NO_ERROR; return NPERR_NO_ERROR;
} }
NPError nsNPAPIPluginInstance::SetWindowlessLocal(PRBool aWindowlessLocal)
{
mWindowlessLocal = aWindowlessLocal;
return NPERR_NO_ERROR;
}
NPError nsNPAPIPluginInstance::SetTransparent(PRBool aTransparent) NPError nsNPAPIPluginInstance::SetTransparent(PRBool aTransparent)
{ {
mTransparent = aTransparent; mTransparent = aTransparent;

Просмотреть файл

@ -86,6 +86,8 @@ public:
NPError SetWindowless(PRBool aWindowless); NPError SetWindowless(PRBool aWindowless);
NPError SetWindowlessLocal(PRBool aWindowlessLocal);
NPError SetTransparent(PRBool aTransparent); NPError SetTransparent(PRBool aTransparent);
NPError SetWantsAllNetworkStreams(PRBool aWantsAllNetworkStreams); NPError SetWantsAllNetworkStreams(PRBool aWantsAllNetworkStreams);
@ -149,6 +151,7 @@ protected:
// these are used to store the windowless properties // these are used to store the windowless properties
// which the browser will later query // which the browser will later query
PRPackedBool mWindowless; PRPackedBool mWindowless;
PRPackedBool mWindowlessLocal;
PRPackedBool mTransparent; PRPackedBool mTransparent;
PRPackedBool mStarted; PRPackedBool mStarted;
PRPackedBool mCached; PRPackedBool mCached;