Bug 430450 – vertical stripes in windowless plugins.

Snap to pixels and round dirty rect out. r+sr=roc
This commit is contained in:
Karl Tomlinson 2008-07-07 14:49:38 +12:00
Родитель 7eb29eb768
Коммит 97d7e0a66f
2 изменённых файлов: 98 добавлений и 43 удалений

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

@ -362,8 +362,9 @@ public:
#elif defined(XP_MACOSX)
void Paint(const nsRect& aDirtyRect);
#elif defined(MOZ_X11)
void Paint(nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect);
void Paint(gfxContext* aContext,
const gfxRect& aFrameRect,
const gfxRect& aDirtyRect);
#elif defined(XP_OS2)
void Paint(const nsRect& aDirtyRect, HPS aHPS);
#endif
@ -480,8 +481,9 @@ private:
class Renderer : public gfxXlibNativeRenderer {
public:
Renderer(nsPluginWindow* aWindow, nsIPluginInstance* aInstance,
const nsIntRect& aDirtyRect)
: mWindow(aWindow), mInstance(aInstance), mDirtyRect(aDirtyRect)
const nsIntSize& aPluginSize, const nsIntRect& aDirtyRect)
: mWindow(aWindow), mInstance(aInstance),
mPluginSize(aPluginSize), mDirtyRect(aDirtyRect)
{}
virtual nsresult NativeDraw(Display* dpy, Drawable drawable, Visual* visual,
short offsetX, short offsetY,
@ -489,13 +491,14 @@ private:
private:
nsPluginWindow* mWindow;
nsIPluginInstance* mInstance;
const nsIntSize& mPluginSize;
const nsIntRect& mDirtyRect;
};
#endif
};
#if defined(XP_WIN) || (defined(DO_DIRTY_INTERSECT) && defined(XP_MACOSX)) || defined(MOZ_X11) || defined(XP_OS2)
#if defined(XP_WIN) || (defined(DO_DIRTY_INTERSECT) && defined(XP_MACOSX)) || defined(XP_OS2)
static void ConvertAppUnitsToPixels(const nsPresContext& aPresContext, const nsRect& aTwipsRect, nsIntRect& aPixelRect);
#endif
@ -1082,23 +1085,20 @@ nsObjectFrame::DidReflow(nsPresContext* aPresContext,
return rv;
}
static void PaintPrintPlugin(nsIFrame* aFrame, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect, nsPoint aPt)
/* static */ void
nsObjectFrame::PaintPrintPlugin(nsIFrame* aFrame, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect, nsPoint aPt)
{
// FIXME - Bug 385435: Doesn't aDirtyRect need translating too?
nsIRenderingContext::AutoPushTranslation translate(aCtx, aPt.x, aPt.y);
static_cast<nsObjectFrame*>(aFrame)->PrintPlugin(*aCtx, aDirtyRect);
}
static void PaintPlugin(nsIFrame* aFrame, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect, nsPoint aPt)
/*static */ void
nsObjectFrame::PaintPlugin(nsIFrame* aFrame, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect, nsPoint aPt)
{
nsIRenderingContext::AutoPushTranslation translate(aCtx, aPt.x, aPt.y);
#ifdef MOZ_X11 // FIXME - Bug 385435: Don't others want this too!
nsRect relativeDirtyRect = aDirtyRect - aPt;
static_cast<nsObjectFrame*>(aFrame)->PaintPlugin(*aCtx, relativeDirtyRect);
#else
static_cast<nsObjectFrame*>(aFrame)->PaintPlugin(*aCtx, aDirtyRect);
#endif
static_cast<nsObjectFrame*>(aFrame)->PaintPlugin(*aCtx, aDirtyRect, aPt);
}
NS_IMETHODIMP
@ -1127,7 +1127,7 @@ nsObjectFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
nsDisplayGeneric(this, PaintPrintPlugin, "PrintPlugin"));
return aLists.Content()->AppendNewToTop(new (aBuilder)
nsDisplayGeneric(this, ::PaintPlugin, "Plugin"));
nsDisplayGeneric(this, PaintPlugin, "Plugin"));
}
void
@ -1343,12 +1343,15 @@ nsObjectFrame::PrintPlugin(nsIRenderingContext& aRenderingContext,
void
nsObjectFrame::PaintPlugin(nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect)
const nsRect& aDirtyRect, const nsPoint& aFramePt)
{
// Screen painting code
#if defined(XP_MACOSX)
// delegate all painting to the plugin instance.
if (mInstanceOwner) {
// FIXME - Bug 385435: Doesn't aDirtyRect need translating too?
nsIRenderingContext::AutoPushTranslation translate(aCtx, aPt.x, aPt.y);
if (mInstanceOwner->GetDrawingModel() == NPDrawingModelCoreGraphics) {
PRInt32 p2a = PresContext()->AppUnitsPerDevPixel();
gfxRect nativeClipRect(aDirtyRect.x, aDirtyRect.y,
@ -1398,8 +1401,15 @@ nsObjectFrame::PaintPlugin(nsIRenderingContext& aRenderingContext,
nsPluginWindow * window;
mInstanceOwner->GetWindow(window);
if (window->type == nsPluginWindowType_Drawable)
mInstanceOwner->Paint(aRenderingContext, aDirtyRect);
if (window->type == nsPluginWindowType_Drawable) {
gfxRect frameGfxRect =
PresContext()->AppUnitsToGfxUnits(nsRect(aFramePt, GetSize()));
gfxRect dirtyGfxRect =
PresContext()->AppUnitsToGfxUnits(aDirtyRect);
gfxContext* ctx = aRenderingContext.ThebesContext();
mInstanceOwner->Paint(ctx, frameGfxRect, dirtyGfxRect);
}
}
#elif defined (XP_WIN) || defined(XP_OS2)
nsCOMPtr<nsIPluginInstance> inst;
@ -1410,6 +1420,9 @@ nsObjectFrame::PaintPlugin(nsIRenderingContext& aRenderingContext,
mInstanceOwner->GetWindow(window);
if (window->type == nsPluginWindowType_Drawable) {
// FIXME - Bug 385435: Doesn't aDirtyRect need translating too?
nsIRenderingContext::AutoPushTranslation translate(aCtx, aPt.x, aPt.y);
// check if we need to call SetWindow with updated parameters
PRBool doupdatewindow = PR_FALSE;
// the offset of the DC
@ -1769,6 +1782,7 @@ private:
NS_IMPL_ISUPPORTS_INHERITED1(nsStopPluginRunnable, nsRunnable, nsITimerCallback)
#ifdef XP_WIN
static const char*
GetMIMEType(nsIPluginInstance *aPluginInstance)
{
@ -1781,6 +1795,7 @@ GetMIMEType(nsIPluginInstance *aPluginInstance)
}
return "";
}
#endif
static PRBool
MatchPluginName(nsPluginInstanceOwner *aInstanceOwner, const char *aPluginName)
@ -4052,25 +4067,52 @@ void nsPluginInstanceOwner::Paint(const nsRect& aDirtyRect, HPS aHPS)
#endif
#ifdef MOZ_X11
void nsPluginInstanceOwner::Paint(nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect)
void nsPluginInstanceOwner::Paint(gfxContext* aContext,
const gfxRect& aFrameRect,
const gfxRect& aDirtyRect)
{
if (!mInstance || !mOwner)
return;
// Align to device pixels where sensible
// to provide crisper and faster drawing.
gfxRect pluginRect = aFrameRect;
if (aContext->UserToDevicePixelSnapped(pluginRect)) {
pluginRect = aContext->DeviceToUser(pluginRect);
}
// Round out the dirty rect to plugin pixels to ensure the plugin draws
// enough pixels for interpolation to device pixels.
gfxRect dirtyRect = aDirtyRect + -pluginRect.pos;
dirtyRect.RoundOut();
// Plugins can only draw an integer number of pixels.
//
// With translation-only transformation matrices, pluginRect is already
// pixel-aligned.
//
// With more complex transformations, modifying the scales in the
// transformation matrix could retain subpixel accuracy and let the plugin
// draw a suitable number of pixels for interpolation to device pixels in
// Renderer::Draw, but such cases are not common enough to warrant the
// effort now.
nsIntSize pluginSize(NS_lround(pluginRect.size.width),
NS_lround(pluginRect.size.height));
// Determine what the plugin needs to draw.
nsIntRect pluginDirtyRect(PRInt32(dirtyRect.pos.x),
PRInt32(dirtyRect.pos.y),
PRInt32(dirtyRect.size.width),
PRInt32(dirtyRect.size.height));
if (!pluginDirtyRect.
IntersectRect(nsIntRect(0, 0, pluginSize.width, pluginSize.height),
pluginDirtyRect))
return;
nsPluginWindow* window;
GetWindow(window);
nsIntRect dirtyRectInPixels;
ConvertAppUnitsToPixels(*mOwner->PresContext(), aDirtyRect,
dirtyRectInPixels);
// Sanitize the dirty rect so we don't tell plugins that the area outside
// the plugin rectangle needs updating.
nsIntRect pluginDirtyRect;
if (!pluginDirtyRect.IntersectRect(nsIntRect(0, 0, window->width, window->height), dirtyRectInPixels))
return;
Renderer renderer(window, mInstance, pluginDirtyRect);
Renderer renderer(window, mInstance, pluginSize, pluginDirtyRect);
PRUint32 rendererFlags =
Renderer::DRAW_SUPPORTS_OFFSET |
Renderer::DRAW_SUPPORTS_CLIP_RECT |
@ -4083,9 +4125,9 @@ void nsPluginInstanceOwner::Paint(nsIRenderingContext& aRenderingContext,
if (!transparent)
rendererFlags |= Renderer::DRAW_IS_OPAQUE;
gfxContext* ctx =
static_cast<gfxContext*>
(aRenderingContext.GetNativeGraphicData(nsIRenderingContext::NATIVE_THEBES_CONTEXT));
// Renderer::Draw() draws a rectangle with top-left at the aContext origin.
gfxContextAutoSaveRestore autoSR(aContext);
aContext->Translate(pluginRect.pos);
// The display used by gfxXlibNativeRenderer will be the one for the cairo
// surface (provided that it is an Xlib surface) but the display argument
@ -4093,7 +4135,7 @@ void nsPluginInstanceOwner::Paint(nsIRenderingContext& aRenderingContext,
// _create_temp_xlib_surface -> DefaultScreen(dpy).
NPSetWindowCallbackStruct* ws_info =
static_cast<NPSetWindowCallbackStruct*>(window->ws_info);
renderer.Draw(ws_info->display, ctx, window->width, window->height,
renderer.Draw(ws_info->display, aContext, pluginSize.width, pluginSize.height,
rendererFlags, nsnull);
}
@ -4113,6 +4155,13 @@ nsPluginInstanceOwner::Renderer::NativeDraw(Display* dpy, Drawable drawable,
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 plugin top-left.
NS_ASSERTION(numClipRects <= 1, "We don't support multiple clip rectangles!");
nsPluginRect newClipRect;
if (numClipRects) {
@ -4420,7 +4469,7 @@ void nsPluginInstanceOwner::SetPluginHost(nsIPluginHost* aHost)
mPluginHost = aHost;
}
#if defined(XP_WIN) || (defined(DO_DIRTY_INTERSECT) && defined(XP_MACOSX)) || defined(MOZ_X11) || defined(XP_OS2)
#if defined(XP_WIN) || (defined(DO_DIRTY_INTERSECT) && defined(XP_MACOSX)) || defined(XP_OS2)
// convert frame coordinates from twips to pixels
static void ConvertAppUnitsToPixels(const nsPresContext& aPresContext, const nsRect& aTwipsRect, nsIntRect& aPixelRect)
{

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

@ -81,11 +81,6 @@ public:
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists);
void PrintPlugin(nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect);
void PaintPlugin(nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect);
NS_IMETHOD HandleEvent(nsPresContext* aPresContext,
nsGUIEvent* aEvent,
nsEventStatus* aEventStatus);
@ -182,6 +177,17 @@ protected:
nsPoint GetWindowOriginInPixels(PRBool aWindowless);
static void PaintPrintPlugin(nsIFrame* aFrame,
nsIRenderingContext* aRenderingContext,
const nsRect& aDirtyRect, nsPoint aPt);
static void PaintPlugin(nsIFrame* aFrame,
nsIRenderingContext* aRenderingContext,
const nsRect& aDirtyRect, nsPoint aPt);
void PrintPlugin(nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect);
void PaintPlugin(nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect, const nsPoint& aFramePt);
/**
* Makes sure that mInstanceOwner is valid and without a current plugin
* instance. Essentially, this prepares the frame to receive a new plugin.