зеркало из https://github.com/mozilla/pjs.git
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:
Родитель
4ef2931105
Коммит
f4417f337e
|
@ -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) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче