Move management of the backbuffer from the viewmanager to the rendering context and make the backbuffer transient on WIN32 and GTK. bug 95952 sr=attinasi r=karnaze

This commit is contained in:
kmcclusk%netscape.com 2001-12-12 01:35:31 +00:00
Родитель 4ef2931105
Коммит f4417f337e
11 изменённых файлов: 494 добавлений и 226 удалений

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

@ -751,6 +751,35 @@ public:
//~~~
NS_IMETHOD RetrieveCurrentNativeGraphicData(PRUint32 * ngd) = 0;
/**
* Get a drawing surface used as a backbuffer.
* Depending on the platform this will either cause a backbuffer surface to be allocated
* or an existing cached backbuffer will be returned. If the backbuffer is being cached
* asking for aMaxSize which is different from a previous request may cause the platform
* to dump it's cached backbuffer and reallocate a backbuffer of a size which will allow aMaxSize
* buffer to be allocated.
*
* @param aRequestedSize size of the backbuffer area requested
* @param aMaxSize maximum size that may be requested for the backbuffer
* @param aBackbuffer drawing surface used as the backbuffer
*/
NS_IMETHOD GetBackbuffer(const nsRect &aRequestedSize, const nsRect &aMaxSize, nsDrawingSurface &aBackbuffer) = 0;
/**
* Release a drawing surface used as the backbuffer
* If the platform caches the backbuffer this call will destroy it.
*/
NS_IMETHOD ReleaseBackbuffer(void) = 0;
/**
* Destroy the drawing surface used as the backbuffer. If the platform
* does not maintain a cached backbuffer this call will do nothing.
*/
NS_IMETHOD DestroyCachedBackbuffer(void) = 0;
#ifdef MOZ_MATHML
/**
* Returns bounding metrics (in app units) of an 8-bit character string

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

@ -41,6 +41,7 @@
#include "nsIRenderingContext.h"
#include "nsPoint.h"
#include "nsSize.h"
typedef struct {
@ -115,6 +116,10 @@ public:
*/
NS_IMETHOD FillStdPolygon(const nsPoint aPoints[], PRInt32 aNumPoints) { return NS_OK; }
NS_IMETHOD GetBackbuffer(const nsRect &aRequestedSize, const nsRect &aMaxSize, nsDrawingSurface &aBackbuffer);
NS_IMETHOD ReleaseBackbuffer(void);
NS_IMETHOD DestroyCachedBackbuffer(void);
#ifdef IBMBIDI
/**
* Let the device context know whether we want text reordered with
@ -157,10 +162,67 @@ protected:
void cdelete(int i);
void cinsert(int i,int y,const nsPoint aPointArray[],PRInt32 aNumPts);
/**
* Determine if a rect's width and height will fit within a specified width and height
* @param aRect rectangle to test
* @param aWidth width to determine if the rectangle's width will fit within
* @param aHeight height to determine if the rectangles height will fit within
* @returns PR_TRUE if the rect width and height fits with aWidth, aHeight, PR_FALSE
* otherwise.
*/
PRBool RectFitsInside(const nsRect& aRect, PRInt32 aWidth, PRInt32 aHeight) const;
/**
* Determine if two rectangles width and height will fit within a specified width and height
* @param aRect1 first rectangle to test
* @param aRect1 second rectangle to test
* @param aWidth width to determine if both rectangle's width will fit within
* @param aHeight height to determine if both rectangles height will fit within
* @returns PR_TRUE if the rect1's and rect2's width and height fits with aWidth,
* aHeight, PR_FALSE otherwise.
*/
PRBool BothRectsFitInside(const nsRect& aRect1, const nsRect& aRect2, PRInt32 aWidth, PRInt32 aHeight, nsRect& aNewSize) const;
/**
* Return an offscreen surface size from a set of discrete surface sizes.
* The smallest discrete surface size that can enclose both the Maximum widget
* size (@see GetMaxWidgetBounds) and the requested size is returned.
*
* @param aMaxBackbufferSize Maximum size that may be requested for the backbuffer
* @param aRequestedSize Requested size for the offscreen.
* @param aSurfaceSize contains the surface size
*/
void CalculateDiscreteSurfaceSize(const nsRect& aMaxBackbufferSize, const nsRect& aRequestedSize, nsRect& aSize);
/**
* Get the size of the offscreen drawing surface..
*
* @param aMaxBackbufferSize Maximum size that may be requested for the backbuffer
* @param aRequestedSize Desired size for the offscreen.
* @param aSurfaceSize Offscreen adjusted to a discrete size which encloses aRequestedSize.
*/
void GetDrawingSurfaceSize(const nsRect& aMaxBackbufferSize, const nsRect& aRequestedSize, nsRect& aSurfaceSize);
/**
* Utility method used to implement NS_IMETHOD GetBackbuffer
*
* @param aRequestedSize size of the backbuffer area requested
* @param aMaxSize maximum size that may be requested for the backbuffer
* @param aBackbuffer drawing surface used as the backbuffer
* @param aCacheBackbuffer PR_TRUE then the backbuffer will be cached, if PR_FALSE it is created each time
*/
nsresult AllocateBackbuffer(const nsRect &aRequestedSize, const nsRect &aMaxSize, nsDrawingSurface &aBackbuffer, PRBool aCacheBackbuffer);
public:
protected:
nsPenMode mPenMode;
private:
static nsDrawingSurface gBackbuffer; //singleton backbuffer
static nsRect gBackbufferBounds; //backbuffer bounds
// Largest requested offscreen size if larger than a full screen.
static nsSize gLargestRequestedSize;
};

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

@ -2047,3 +2047,16 @@ NS_IMETHODIMP nsRenderingContextGTK::DrawScaledImage(imgIContainer *aImage, cons
UpdateGC();
return nsRenderingContextImpl::DrawScaledImage(aImage, aSrcRect, aDestRect);
}
NS_IMETHODIMP nsRenderingContextGTK::GetBackbuffer(const nsRect &aRequestedSize, const nsRect &aMaxSize, nsDrawingSurface &aBackbuffer)
{
// Do not cache the backbuffer. On GTK it is more efficient to allocate
// the backbuffer as needed and it doesn't cause a performance hit. @see bug 95952
return AllocateBackbuffer(aRequestedSize, aMaxSize, aBackbuffer, PR_FALSE);
}
NS_IMETHODIMP nsRenderingContextGTK::ReleaseBackbuffer(void) {
// Do not cache the backbuffer. On GTK it is more efficient to allocate
// the backbuffer as needed and it doesn't cause a performance hit. @see bug 95952
return DestroyCachedBackbuffer();
}

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

@ -188,6 +188,9 @@ public:
NS_IMETHOD DrawImage(imgIContainer *aImage, const nsRect * aSrcRect, const nsPoint * aDestPoint);
NS_IMETHOD DrawScaledImage(imgIContainer *aImage, const nsRect * aSrcRect, const nsRect * aDestRect);
NS_IMETHOD GetBackbuffer(const nsRect &aRequestedSize, const nsRect &aMaxSize, nsDrawingSurface &aBackbuffer);
NS_IMETHOD ReleaseBackbuffer(void);
#ifdef MOZ_MATHML
/**
* Returns metrics (in app units) of an 8-bit character string

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

@ -45,6 +45,10 @@
const nsPoint *gPts;
nsDrawingSurface nsRenderingContextImpl::gBackbuffer = nsnull;
nsRect nsRenderingContextImpl::gBackbufferBounds = nsRect(0, 0, 0, 0);
nsSize nsRenderingContextImpl::gLargestRequestedSize = nsSize(0, 0);
// comparison routines for qsort
PRInt32 PR_CALLBACK compare_ind(const void *u,const void *v){return gPts[(PRInt32)*((PRInt32*)u)].y <= gPts[(PRInt32)*((PRInt32*)v)].y ? -1 : 1;}
PRInt32 PR_CALLBACK compare_active(const void *u,const void *v){return ((Edge*)u)->x <= ((Edge*)v)->x ? -1 : 1;}
@ -451,6 +455,173 @@ PRInt32 flag = NS_COPYBITS_TO_BACK_BUFFER | NS_COPYBITS_XFORM_DEST_VALUES;
}
}
NS_IMETHODIMP nsRenderingContextImpl::GetBackbuffer(const nsRect &aRequestedSize, const nsRect &aMaxSize, nsDrawingSurface &aBackbuffer)
{
// Default implementation assumes the backbuffer will be cached.
// If the platform implementation does not require the backbuffer to
// be cached override this method and make the following call instead:
// AllocateBackbuffer(aRequestedSize, aMaxSize, aBackbuffer, PR_FALSE);
return AllocateBackbuffer(aRequestedSize, aMaxSize, aBackbuffer, PR_TRUE);
}
nsresult nsRenderingContextImpl::AllocateBackbuffer(const nsRect &aRequestedSize, const nsRect &aMaxSize, nsDrawingSurface &aBackbuffer, PRBool aCacheBackbuffer)
{
nsRect newBounds;
nsresult rv = NS_OK;
if (! aCacheBackbuffer) {
newBounds = aRequestedSize;
} else {
GetDrawingSurfaceSize(aMaxSize, aRequestedSize, newBounds);
}
if ((nsnull == gBackbuffer)
|| (gBackbufferBounds.width != newBounds.width)
|| (gBackbufferBounds.height != newBounds.height))
{
if (gBackbuffer) {
//destroy existing DS
DestroyDrawingSurface(gBackbuffer);
gBackbuffer = nsnull;
}
rv = CreateDrawingSurface(&newBounds, 0, gBackbuffer);
// printf("Allocating a new drawing surface %d %d\n", newBounds.width, newBounds.height);
if (NS_SUCCEEDED(rv)) {
gBackbufferBounds = newBounds;
SelectOffScreenDrawingSurface(gBackbuffer);
} else {
gBackbufferBounds.SetRect(0,0,0,0);
gBackbuffer = nsnull;
}
} else {
SelectOffScreenDrawingSurface(gBackbuffer);
float p2t;
nsCOMPtr<nsIDeviceContext> dx;
GetDeviceContext(*getter_AddRefs(dx));
dx->GetDevUnitsToAppUnits(p2t);
nsRect bounds = aRequestedSize;
bounds *= p2t;
PRBool clipEmpty;
SetClipRect(bounds, nsClipCombine_kReplace, clipEmpty);
}
aBackbuffer = gBackbuffer;
return rv;
}
NS_IMETHODIMP nsRenderingContextImpl::ReleaseBackbuffer(void)
{
// If the platform does not require the backbuffer to be cached
// override this method and call DestroyCachedBackbuffer
return NS_OK;
}
NS_IMETHODIMP nsRenderingContextImpl::DestroyCachedBackbuffer(void)
{
if (gBackbuffer) {
DestroyDrawingSurface(gBackbuffer);
gBackbuffer = nsnull;
}
return NS_OK;
}
PRBool nsRenderingContextImpl::RectFitsInside(const nsRect& aRect, PRInt32 aWidth, PRInt32 aHeight) const
{
if (aRect.width > aWidth)
return (PR_FALSE);
if (aRect.height > aHeight)
return (PR_FALSE);
return PR_TRUE;
}
PRBool nsRenderingContextImpl::BothRectsFitInside(const nsRect& aRect1, const nsRect& aRect2, PRInt32 aWidth, PRInt32 aHeight, nsRect& aNewSize) const
{
if (PR_FALSE == RectFitsInside(aRect1, aWidth, aHeight)) {
return PR_FALSE;
}
if (PR_FALSE == RectFitsInside(aRect2, aWidth, aHeight)) {
return PR_FALSE;
}
aNewSize.width = aWidth;
aNewSize.height = aHeight;
return PR_TRUE;
}
void nsRenderingContextImpl::GetDrawingSurfaceSize(const nsRect& aMaxBackbufferSize, const nsRect& aRequestedSize, nsRect& aNewSize)
{
CalculateDiscreteSurfaceSize(aMaxBackbufferSize, aRequestedSize, aNewSize);
aNewSize.MoveTo(aRequestedSize.x, aRequestedSize.y);
}
void nsRenderingContextImpl::CalculateDiscreteSurfaceSize(const nsRect& aMaxBackbufferSize, const nsRect& aRequestedSize, nsRect& aSurfaceSize)
{
// Get the height and width of the screen
PRInt32 height;
PRInt32 width;
nsCOMPtr<nsIDeviceContext> dx;
GetDeviceContext(*getter_AddRefs(dx));
dx->GetDeviceSurfaceDimensions(width, height);
float devUnits;
dx->GetDevUnitsToAppUnits(devUnits);
PRInt32 screenHeight = NSToIntRound(float( height) / devUnits );
PRInt32 screenWidth = NSToIntRound(float( width) / devUnits );
// These tests must go from smallest rectangle to largest rectangle.
// 1/8 screen
if (BothRectsFitInside(aRequestedSize, aMaxBackbufferSize, screenWidth / 8, screenHeight / 8, aSurfaceSize)) {
return;
}
// 1/4 screen
if (BothRectsFitInside(aRequestedSize, aMaxBackbufferSize, screenWidth / 4, screenHeight / 4, aSurfaceSize)) {
return;
}
// 1/2 screen
if (BothRectsFitInside(aRequestedSize, aMaxBackbufferSize, screenWidth / 2, screenHeight / 2, aSurfaceSize)) {
return;
}
// 3/4 screen
if (BothRectsFitInside(aRequestedSize, aMaxBackbufferSize, (screenWidth * 3) / 4, (screenHeight * 3) / 4, aSurfaceSize)) {
return;
}
// 3/4 screen width full screen height
if (BothRectsFitInside(aRequestedSize, aMaxBackbufferSize, (screenWidth * 3) / 4, screenHeight, aSurfaceSize)) {
return;
}
// Full screen
if (BothRectsFitInside(aRequestedSize, aMaxBackbufferSize, screenWidth, screenHeight, aSurfaceSize)) {
return;
}
// Bigger than Full Screen use the largest request every made.
if (BothRectsFitInside(aRequestedSize, aMaxBackbufferSize, gLargestRequestedSize.width, gLargestRequestedSize.height, aSurfaceSize)) {
return;
} else {
gLargestRequestedSize.width = PR_MAX(aRequestedSize.width, aMaxBackbufferSize.width);
gLargestRequestedSize.height = PR_MAX(aRequestedSize.height, aMaxBackbufferSize.height);
aSurfaceSize.width = gLargestRequestedSize.width;
aSurfaceSize.height = gLargestRequestedSize.height;
// printf("Expanding the largested requested size to %d %d\n", gLargestRequestedSize.width, gLargestRequestedSize.height);
}
}
#ifdef IBMBIDI
/**
* Let the device context know whether we want text reordered with

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

@ -45,6 +45,10 @@
const nsPoint *gPts;
nsDrawingSurface nsRenderingContextImpl::gBackbuffer = nsnull;
nsRect nsRenderingContextImpl::gBackbufferBounds = nsRect(0, 0, 0, 0);
nsSize nsRenderingContextImpl::gLargestRequestedSize = nsSize(0, 0);
// comparison routines for qsort
PRInt32 PR_CALLBACK compare_ind(const void *u,const void *v){return gPts[(PRInt32)*((PRInt32*)u)].y <= gPts[(PRInt32)*((PRInt32*)v)].y ? -1 : 1;}
PRInt32 PR_CALLBACK compare_active(const void *u,const void *v){return ((Edge*)u)->x <= ((Edge*)v)->x ? -1 : 1;}
@ -451,6 +455,173 @@ PRInt32 flag = NS_COPYBITS_TO_BACK_BUFFER | NS_COPYBITS_XFORM_DEST_VALUES;
}
}
NS_IMETHODIMP nsRenderingContextImpl::GetBackbuffer(const nsRect &aRequestedSize, const nsRect &aMaxSize, nsDrawingSurface &aBackbuffer)
{
// Default implementation assumes the backbuffer will be cached.
// If the platform implementation does not require the backbuffer to
// be cached override this method and make the following call instead:
// AllocateBackbuffer(aRequestedSize, aMaxSize, aBackbuffer, PR_FALSE);
return AllocateBackbuffer(aRequestedSize, aMaxSize, aBackbuffer, PR_TRUE);
}
nsresult nsRenderingContextImpl::AllocateBackbuffer(const nsRect &aRequestedSize, const nsRect &aMaxSize, nsDrawingSurface &aBackbuffer, PRBool aCacheBackbuffer)
{
nsRect newBounds;
nsresult rv = NS_OK;
if (! aCacheBackbuffer) {
newBounds = aRequestedSize;
} else {
GetDrawingSurfaceSize(aMaxSize, aRequestedSize, newBounds);
}
if ((nsnull == gBackbuffer)
|| (gBackbufferBounds.width != newBounds.width)
|| (gBackbufferBounds.height != newBounds.height))
{
if (gBackbuffer) {
//destroy existing DS
DestroyDrawingSurface(gBackbuffer);
gBackbuffer = nsnull;
}
rv = CreateDrawingSurface(&newBounds, 0, gBackbuffer);
// printf("Allocating a new drawing surface %d %d\n", newBounds.width, newBounds.height);
if (NS_SUCCEEDED(rv)) {
gBackbufferBounds = newBounds;
SelectOffScreenDrawingSurface(gBackbuffer);
} else {
gBackbufferBounds.SetRect(0,0,0,0);
gBackbuffer = nsnull;
}
} else {
SelectOffScreenDrawingSurface(gBackbuffer);
float p2t;
nsCOMPtr<nsIDeviceContext> dx;
GetDeviceContext(*getter_AddRefs(dx));
dx->GetDevUnitsToAppUnits(p2t);
nsRect bounds = aRequestedSize;
bounds *= p2t;
PRBool clipEmpty;
SetClipRect(bounds, nsClipCombine_kReplace, clipEmpty);
}
aBackbuffer = gBackbuffer;
return rv;
}
NS_IMETHODIMP nsRenderingContextImpl::ReleaseBackbuffer(void)
{
// If the platform does not require the backbuffer to be cached
// override this method and call DestroyCachedBackbuffer
return NS_OK;
}
NS_IMETHODIMP nsRenderingContextImpl::DestroyCachedBackbuffer(void)
{
if (gBackbuffer) {
DestroyDrawingSurface(gBackbuffer);
gBackbuffer = nsnull;
}
return NS_OK;
}
PRBool nsRenderingContextImpl::RectFitsInside(const nsRect& aRect, PRInt32 aWidth, PRInt32 aHeight) const
{
if (aRect.width > aWidth)
return (PR_FALSE);
if (aRect.height > aHeight)
return (PR_FALSE);
return PR_TRUE;
}
PRBool nsRenderingContextImpl::BothRectsFitInside(const nsRect& aRect1, const nsRect& aRect2, PRInt32 aWidth, PRInt32 aHeight, nsRect& aNewSize) const
{
if (PR_FALSE == RectFitsInside(aRect1, aWidth, aHeight)) {
return PR_FALSE;
}
if (PR_FALSE == RectFitsInside(aRect2, aWidth, aHeight)) {
return PR_FALSE;
}
aNewSize.width = aWidth;
aNewSize.height = aHeight;
return PR_TRUE;
}
void nsRenderingContextImpl::GetDrawingSurfaceSize(const nsRect& aMaxBackbufferSize, const nsRect& aRequestedSize, nsRect& aNewSize)
{
CalculateDiscreteSurfaceSize(aMaxBackbufferSize, aRequestedSize, aNewSize);
aNewSize.MoveTo(aRequestedSize.x, aRequestedSize.y);
}
void nsRenderingContextImpl::CalculateDiscreteSurfaceSize(const nsRect& aMaxBackbufferSize, const nsRect& aRequestedSize, nsRect& aSurfaceSize)
{
// Get the height and width of the screen
PRInt32 height;
PRInt32 width;
nsCOMPtr<nsIDeviceContext> dx;
GetDeviceContext(*getter_AddRefs(dx));
dx->GetDeviceSurfaceDimensions(width, height);
float devUnits;
dx->GetDevUnitsToAppUnits(devUnits);
PRInt32 screenHeight = NSToIntRound(float( height) / devUnits );
PRInt32 screenWidth = NSToIntRound(float( width) / devUnits );
// These tests must go from smallest rectangle to largest rectangle.
// 1/8 screen
if (BothRectsFitInside(aRequestedSize, aMaxBackbufferSize, screenWidth / 8, screenHeight / 8, aSurfaceSize)) {
return;
}
// 1/4 screen
if (BothRectsFitInside(aRequestedSize, aMaxBackbufferSize, screenWidth / 4, screenHeight / 4, aSurfaceSize)) {
return;
}
// 1/2 screen
if (BothRectsFitInside(aRequestedSize, aMaxBackbufferSize, screenWidth / 2, screenHeight / 2, aSurfaceSize)) {
return;
}
// 3/4 screen
if (BothRectsFitInside(aRequestedSize, aMaxBackbufferSize, (screenWidth * 3) / 4, (screenHeight * 3) / 4, aSurfaceSize)) {
return;
}
// 3/4 screen width full screen height
if (BothRectsFitInside(aRequestedSize, aMaxBackbufferSize, (screenWidth * 3) / 4, screenHeight, aSurfaceSize)) {
return;
}
// Full screen
if (BothRectsFitInside(aRequestedSize, aMaxBackbufferSize, screenWidth, screenHeight, aSurfaceSize)) {
return;
}
// Bigger than Full Screen use the largest request every made.
if (BothRectsFitInside(aRequestedSize, aMaxBackbufferSize, gLargestRequestedSize.width, gLargestRequestedSize.height, aSurfaceSize)) {
return;
} else {
gLargestRequestedSize.width = PR_MAX(aRequestedSize.width, aMaxBackbufferSize.width);
gLargestRequestedSize.height = PR_MAX(aRequestedSize.height, aMaxBackbufferSize.height);
aSurfaceSize.width = gLargestRequestedSize.width;
aSurfaceSize.height = gLargestRequestedSize.height;
// printf("Expanding the largested requested size to %d %d\n", gLargestRequestedSize.width, gLargestRequestedSize.height);
}
}
#ifdef IBMBIDI
/**
* Let the device context know whether we want text reordered with

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

@ -2988,6 +2988,22 @@ nsRenderingContextWin::ConditionRect(nsRect& aSrcRect, RECT& aDestRect)
: (aSrcRect.x+aSrcRect.width);
}
NS_IMETHODIMP
nsRenderingContextWin::GetBackbuffer(const nsRect &aRequestedSize, const nsRect &aMaxSize, nsDrawingSurface &aBackbuffer)
{
// Do not cache the backbuffer. On WIN32 it is faster to get allocate
// the backbuffer as needed. @see bug 95952
return AllocateBackbuffer(aRequestedSize, aMaxSize, aBackbuffer, PR_FALSE);
}
NS_IMETHODIMP
nsRenderingContextWin::ReleaseBackbuffer(void) {
// Destroy the backbuffer. Do not cache it. On WIN32 it is faster to get allocate
// the backbuffer as needed. @see bug 95952
return DestroyCachedBackbuffer();
}
#ifdef IBMBIDI
/**
* Let the device context know whether we want text reordered with

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

@ -192,6 +192,10 @@ public:
// nsIRenderingContextWin
NS_IMETHOD CreateDrawingSurface(HDC aDC, nsDrawingSurface &aSurface);
NS_IMETHOD GetBackbuffer(const nsRect &aRequestedSize, const nsRect &aMaxSize, nsDrawingSurface &aBackbuffer);
NS_IMETHOD ReleaseBackbuffer(void);
#ifdef MOZ_MATHML
NS_IMETHOD
GetBoundingMetrics(const char* aString,

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

@ -275,21 +275,15 @@ nsViewManager::PostInvalidateEvent()
}
PRInt32 nsViewManager::mVMCount = 0;
nsDrawingSurface nsViewManager::mDrawingSurface = nsnull;
nsRect nsViewManager::mDSBounds = nsRect(0, 0, 0, 0);
nsIRenderingContext* nsViewManager::gCleanupContext = nsnull;
nsDrawingSurface nsViewManager::gOffScreen = nsnull;
nsDrawingSurface nsViewManager::gBlack = nsnull;
nsDrawingSurface nsViewManager::gWhite = nsnull;
nsSize nsViewManager::gOffScreenSize = nsSize(0, 0);
nsSize nsViewManager::gLargestRequestedSize = nsSize(0, 0);
// Weakly held references to all of the view managers
nsVoidArray* nsViewManager::gViewManagers = nsnull;
PRUint32 nsViewManager::gLastUserEventTime = 0;
PRBool nsViewManager::gTransitoryBackbuffer = PR_FALSE;
nsViewManager::nsViewManager()
{
@ -357,8 +351,8 @@ nsViewManager::~nsViewManager()
// viewmanager is typically destroyed during XPCOM shutdown.
if (gCleanupContext) {
if (nsnull != mDrawingSurface)
gCleanupContext->DestroyDrawingSurface(mDrawingSurface);
gCleanupContext->DestroyCachedBackbuffer();
if (nsnull != gOffScreen)
gCleanupContext->DestroyDrawingSurface(gOffScreen);
@ -373,7 +367,6 @@ nsViewManager::~nsViewManager()
NS_ASSERTION(PR_FALSE, "Cleanup of drawing surfaces + offscreen buffer failed");
}
mDrawingSurface = nsnull;
gOffScreen = nsnull;
gWhite = nsnull;
gBlack = nsnull;
@ -487,11 +480,6 @@ NS_IMETHODIMP nsViewManager::Init(nsIDeviceContext* aContext)
NS_ASSERTION(nsnull != mEventQueue, "event queue is null");
}
nsCOMPtr<nsIPref> prefs(do_GetService(NS_PREF_CONTRACTID));
if (prefs) {
prefs->GetBoolPref("layout.transitory.backbuffer", &gTransitoryBackbuffer);
}
return rv;
}
@ -664,13 +652,19 @@ void nsViewManager::Refresh(nsView *aView, nsIRenderingContext *aContext, nsIReg
}
if (aUpdateFlags & NS_VMREFRESH_DOUBLE_BUFFER)
{
nsCOMPtr<nsIWidget> widget;
aView->GetWidget(*getter_AddRefs(widget));
widget->GetClientBounds(wrect);
wrect.x = wrect.y = 0;
ds = GetDrawingSurface(*localcx, wrect);
{
nsCOMPtr<nsIWidget> widget;
aView->GetWidget(*getter_AddRefs(widget));
widget->GetClientBounds(wrect);
wrect.x = wrect.y = 0;
nsRect maxWidgetSize;
GetMaxWidgetBounds(maxWidgetSize);
if NS_FAILED(localcx->GetBackbuffer(wrect, maxWidgetSize, ds)) {
//Failed to get backbuffer so turn off double buffering
aUpdateFlags &= ~NS_VMREFRESH_DOUBLE_BUFFER;
}
}
nsRect viewRect;
aView->GetBounds(viewRect);
@ -721,11 +715,7 @@ void nsViewManager::Refresh(nsView *aView, nsIRenderingContext *aContext, nsIReg
mRecursiveRefreshPending = PR_FALSE;
}
if ((gTransitoryBackbuffer) && (mDrawingSurface)) {
//Destroy backbuffer drawing surface
localcx->DestroyDrawingSurface(mDrawingSurface);
mDrawingSurface = nsnull;
}
localcx->ReleaseBackbuffer();
#ifdef NS_VM_PERF_METRICS
MOZ_TIMER_DEBUGLOG(("Stop: nsViewManager::Refresh(region), this=%p\n", this));
@ -1830,13 +1820,13 @@ NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent, nsEventStatus *aS
case NS_DISPLAYCHANGED:
// Reset the offscreens width and height
// so it will be reallocated the next time it needs to
// draw. It needs to be reallocated because it's depth
// has changed. @see bugzilla bug 6061
//Destroy the cached backbuffer to force a new backbuffer
//be constructed with the appropriate display depth.
//@see bugzilla bug 6061
*aStatus = nsEventStatus_eConsumeDoDefault;
mDSBounds.width = 0;
mDSBounds.height = 0;
if (gCleanupContext) {
gCleanupContext->DestroyCachedBackbuffer();
}
break;
@ -2502,164 +2492,16 @@ void nsViewManager::GetMaxWidgetBounds(nsRect& aMaxWidgetBounds) const
// printf("WIDGET BOUNDS %d %d\n", aMaxWidgetBounds.width, aMaxWidgetBounds.height);
}
PRBool nsViewManager::RectFitsInside(nsRect& aRect, PRInt32 aWidth, PRInt32 aHeight) const
{
if (aRect.width > aWidth)
return (PR_FALSE);
if (aRect.height > aHeight)
return (PR_FALSE);
return PR_TRUE;
}
PRBool nsViewManager::BothRectsFitInside(nsRect& aRect1, nsRect& aRect2, PRInt32 aWidth, PRInt32 aHeight, nsRect& aNewSize) const
{
if (PR_FALSE == RectFitsInside(aRect1, aWidth, aHeight)) {
return PR_FALSE;
}
if (PR_FALSE == RectFitsInside(aRect2, aWidth, aHeight)) {
return PR_FALSE;
}
aNewSize.width = aWidth;
aNewSize.height = aHeight;
return PR_TRUE;
}
void nsViewManager::CalculateDiscreteSurfaceSize(nsRect& aRequestedSize, nsRect& aSurfaceSize) const
{
nsRect aMaxWidgetSize;
GetMaxWidgetBounds(aMaxWidgetSize);
// Get the height and width of the screen
PRInt32 height;
PRInt32 width;
NS_ASSERTION(mContext != nsnull, "The device context is null");
mContext->GetDeviceSurfaceDimensions(width, height);
float devUnits;
mContext->GetDevUnitsToAppUnits(devUnits);
PRInt32 screenHeight = NSToIntRound(float( height) / devUnits );
PRInt32 screenWidth = NSToIntRound(float( width) / devUnits );
// These tests must go from smallest rectangle to largest rectangle.
// 1/8 screen
if (BothRectsFitInside(aRequestedSize, aMaxWidgetSize, screenWidth / 8, screenHeight / 8, aSurfaceSize)) {
return;
}
// 1/4 screen
if (BothRectsFitInside(aRequestedSize, aMaxWidgetSize, screenWidth / 4, screenHeight / 4, aSurfaceSize)) {
return;
}
// 1/2 screen
if (BothRectsFitInside(aRequestedSize, aMaxWidgetSize, screenWidth / 2, screenHeight / 2, aSurfaceSize)) {
return;
}
// 3/4 screen
if (BothRectsFitInside(aRequestedSize, aMaxWidgetSize, (screenWidth * 3) / 4, (screenHeight * 3) / 4, aSurfaceSize)) {
return;
}
// 3/4 screen width full screen height
if (BothRectsFitInside(aRequestedSize, aMaxWidgetSize, (screenWidth * 3) / 4, screenHeight, aSurfaceSize)) {
return;
}
// Full screen
if (BothRectsFitInside(aRequestedSize, aMaxWidgetSize, screenWidth, screenHeight, aSurfaceSize)) {
return;
}
// Bigger than Full Screen use the largest request every made.
if (BothRectsFitInside(aRequestedSize, aMaxWidgetSize, gLargestRequestedSize.width, gLargestRequestedSize.height, aSurfaceSize)) {
return;
} else {
gLargestRequestedSize.width = PR_MAX(aRequestedSize.width, aMaxWidgetSize.width);
gLargestRequestedSize.height = PR_MAX(aRequestedSize.height, aMaxWidgetSize.height);
aSurfaceSize.width = gLargestRequestedSize.width;
aSurfaceSize.height = gLargestRequestedSize.height;
// printf("Expanding the largested requested size to %d %d\n", gLargestRequestedSize.width, gLargestRequestedSize.height);
}
}
void nsViewManager::GetDrawingSurfaceSize(nsRect& aRequestedSize, nsRect& aNewSize) const
{
CalculateDiscreteSurfaceSize(aRequestedSize, aNewSize);
aNewSize.MoveTo(aRequestedSize.x, aRequestedSize.y);
}
PRInt32 nsViewManager::GetViewManagerCount()
{
return mVMCount;
}
const nsVoidArray* nsViewManager::GetViewManagerArray()
{
return gViewManagers;
}
nsDrawingSurface nsViewManager::GetDrawingSurface(nsIRenderingContext &aContext, nsRect& aBounds)
{
nsRect newBounds;
if (gTransitoryBackbuffer) {
newBounds = aBounds;
} else {
GetDrawingSurfaceSize(aBounds, newBounds);
}
if ((nsnull == mDrawingSurface)
|| (mDSBounds.width != newBounds.width)
|| (mDSBounds.height != newBounds.height))
{
if (mDrawingSurface) {
//destroy existing DS
aContext.DestroyDrawingSurface(mDrawingSurface);
mDrawingSurface = nsnull;
}
nsresult rv = aContext.CreateDrawingSurface(&newBounds, 0, mDrawingSurface);
// printf("Allocating a new drawing surface %d %d\n", newBounds.width, newBounds.height);
if (NS_SUCCEEDED(rv)) {
mDSBounds = newBounds;
aContext.SelectOffScreenDrawingSurface(mDrawingSurface);
} else {
mDSBounds.SetRect(0,0,0,0);
mDrawingSurface = nsnull;
}
} else {
aContext.SelectOffScreenDrawingSurface(mDrawingSurface);
float p2t;
mContext->GetDevUnitsToAppUnits(p2t);
nsRect bounds = aBounds;
bounds *= p2t;
PRBool clipEmpty;
aContext.SetClipRect(bounds, nsClipCombine_kReplace, clipEmpty);
// This is not be needed. Only the part of the offscreen that has been
// rendered to should be displayed so there no need to
// clear it out.
//nscolor col = NS_RGB(255,255,255);
//aContext.SetColor(col);
//aContext.FillRect(bounds);
}
return mDrawingSurface;
}
NS_IMETHODIMP nsViewManager::ShowQuality(PRBool aShow)
{
if (nsnull != mRootScrollable)

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

@ -212,8 +212,6 @@ public:
NS_IMETHOD SetRootScrollableView(nsIScrollableView *aScrollable);
NS_IMETHOD GetRootScrollableView(nsIScrollableView **aScrollable);
nsDrawingSurface GetDrawingSurface(nsIRenderingContext &aContext, nsRect& aBounds);
NS_IMETHOD Display(nsIView *aView, nscoord aX, nscoord aY, const nsRect& aClipRect);
NS_IMETHOD AddCompositeListener(nsICompositeListener *aListener);
@ -352,45 +350,6 @@ private:
*/
void GetMaxWidgetBounds(nsRect& aMaxWidgetBounds) const;
/**
* Determine if a rect's width and height will fit within a specified width and height
* @param aRect rectangle to test
* @param aWidth width to determine if the rectangle's width will fit within
* @param aHeight height to determine if the rectangles height will fit within
* @returns PR_TRUE if the rect width and height fits with aWidth, aHeight, PR_FALSE
* otherwise.
*/
PRBool RectFitsInside(nsRect& aRect, PRInt32 aWidth, PRInt32 aHeight) const;
/**
* Determine if two rectangles width and height will fit within a specified width and height
* @param aRect1 first rectangle to test
* @param aRect1 second rectangle to test
* @param aWidth width to determine if both rectangle's width will fit within
* @param aHeight height to determine if both rectangles height will fit within
* @returns PR_TRUE if the rect1's and rect2's width and height fits with aWidth,
* aHeight, PR_FALSE otherwise.
*/
PRBool BothRectsFitInside(nsRect& aRect1, nsRect& aRect2, PRInt32 aWidth, PRInt32 aHeight, nsRect& aNewSize) const;
/**
* Return an offscreen surface size from a set of discrete surface sizes.
* The smallest discrete surface size that can enclose both the Maximum widget
* size (@see GetMaxWidgetBounds) and the requested size is returned.
*
* @param aRequestedSize Requested size for the offscreen.
* @param aSurfaceSize contains the surface size
*/
void CalculateDiscreteSurfaceSize(nsRect& aRequestedSize, nsRect& aSize) const;
/**
* Get the size of the offscreen drawing surface..
*
* @param aRequestedSize Desired size for the offscreen.
* @param aSurfaceSize Offscreen adjusted to a discrete size which encloses aRequestedSize.
*/
void GetDrawingSurfaceSize(nsRect& aRequestedSize, nsRect& aSurfaceSize) const;
public: // NOT in nsIViewManager, so private to the view module
nsView* GetRootView() const { return mRootView; }
nsView* GetMouseEventGrabber() const { return mMouseGrabber; }
@ -423,8 +382,6 @@ private:
//from here to public should be static and locked... MMP
static PRInt32 mVMCount; //number of viewmanagers
static nsDrawingSurface mDrawingSurface; //single drawing surface
static nsRect mDSBounds; //for all VMs
//blending buffers
static nsDrawingSurface gOffScreen;
@ -435,12 +392,8 @@ private:
//Rendering context used to cleanup the blending buffers
static nsIRenderingContext* gCleanupContext;
// Largest requested offscreen size if larger than a full screen.
static nsSize gLargestRequestedSize;
//list of view managers
static nsVoidArray *gViewManagers;
static PRBool gTransitoryBackbuffer;
//compositor regions
nsIRegion *mOpaqueRgn;

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

@ -737,6 +737,10 @@ void
nsWindow::DoPaint (PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight,
nsIRegion *aClipRegion)
{
//Don't dispatch paint event if widget's height or width is 0
if ((mBounds.width == 0) || (mBounds.height == 0)) {
return;
}
#ifdef NS_DEBUG
if (this == debugWidget) {