Bug 292051: Save Windows GDI resources by shortening image's DDB life to 60s since last used. r=emaijala sr=tor a=shaver+brendan

This commit is contained in:
paper%animecity.nu 2005-05-10 00:33:57 +00:00
Родитель 231c7a2f54
Коммит 9eb15ebf33
2 изменённых файлов: 110 добавлений и 25 удалений

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

@ -41,6 +41,7 @@
#include "nsRenderingContextWin.h"
#include "nsDeviceContextWin.h"
#include "imgScaler.h"
#include "nsComponentManagerUtils.h"
static PRInt32 GetPlatform()
{
@ -91,6 +92,8 @@ nsImageWin::nsImageWin()
, mARowBytes(0)
, mImageCache(0)
, mInitialized(PR_FALSE)
, mWantsOptimization(PR_FALSE)
, mTimer(nsnull)
{
}
@ -101,6 +104,9 @@ nsImageWin::nsImageWin()
*/
nsImageWin :: ~nsImageWin()
{
if (mTimer)
mTimer->Cancel();
CleanUpDDB();
CleanUpDIB();
@ -490,6 +496,8 @@ nsImageWin::Draw(nsIRenderingContext &aContext, nsIDrawingSurface* aSurface,
PRInt32 canRaster;
((nsDrawingSurfaceWin *)aSurface)->GetTECHNOLOGY(&canRaster);
CreateDDB();
PRBool didComposite = PR_FALSE;
if (!mIsOptimized || !mHBitmap) {
DWORD rop = SRCCOPY;
@ -1002,7 +1010,9 @@ nsImageWin::ProgressiveDoubleBlit(nsIDeviceContext *aContext,
((nsDrawingSurfaceWin *)aSurface)->ReleaseDC();
return PR_FALSE;
}
CreateDDB();
nsPaletteInfo palInfo;
aContext->GetPaletteInfo(palInfo);
if (palInfo.isPaletteDevice && palInfo.palette) {
@ -1409,9 +1419,25 @@ PRBool nsImageWin::CanAlphaBlend(void)
* @update dc - 11/20/98
* @param aContext - The device context to use for the optimization
*/
nsresult
nsImageWin :: Optimize(nsIDeviceContext* aContext)
nsresult nsImageWin::Optimize(nsIDeviceContext* aContext)
{
// Do the actual optimizing when we first use the image (draw it)
// This saves on GDI resources.
mWantsOptimization = PR_TRUE;
return NS_OK;
}
// CreateDDB only if DDB is wanted
NS_IMETHODIMP nsImageWin::CreateDDB()
{
if (!mWantsOptimization || mIsOptimized) {
// Timer only exists when mIsOptimized. Push timer forwards.
if (mTimer)
mTimer->SetDelay(GFX_MS_REMOVE_DBB);
return NS_OK;
}
// we used to set a flag because a valid HDC may not be ready,
// like at startup, but now we just roll our own HDC for the given screen.
@ -1485,8 +1511,20 @@ nsImageWin :: Optimize(nsIDeviceContext* aContext)
mIsOptimized = (mHBitmap != 0);
}
}
if (mIsOptimized)
if (mIsOptimized) {
::GdiFlush();
CleanUpDIB();
if (mTimer) {
mTimer->SetDelay(GFX_MS_REMOVE_DBB);
} else {
mTimer = do_CreateInstance("@mozilla.org/timer;1");
if (mTimer)
mTimer->InitWithFuncCallback(nsImageWin::TimerCallBack, this,
GFX_MS_REMOVE_DBB,
nsITimer::TYPE_ONE_SHOT);
}
}
::SelectObject(TheHDC,oldbits);
::DeleteObject(tBitmap);
::DeleteDC(TheHDC);
@ -1495,6 +1533,22 @@ nsImageWin :: Optimize(nsIDeviceContext* aContext)
return NS_OK;
}
// Removes the DBB, restoring the imagebits if necessary
NS_IMETHODIMP nsImageWin::RemoveDDB()
{
if (!mIsOptimized && mHBitmap == nsnull)
return NS_OK;
if (!mImageBits) {
nsresult rv = ConvertDDBtoDIB();
if (NS_FAILED(rv))
return rv;
}
CleanUpDDB();
return NS_OK;
}
/** ----------------------------------------------------------------
* Calculate the number of bytes in a span for this image
@ -1541,13 +1595,6 @@ nsImageWin::CleanUpDIB()
delete mColorMap;
mColorMap = nsnull;
}
//mNumPaletteColors = -1;
//mNumBytesPixel = 0;
mSizeImage = 0;
}
/** ---------------------------------------------------
@ -1558,6 +1605,11 @@ void
nsImageWin :: CleanUpDDB()
{
if (mHBitmap != nsnull) {
if (mTimer) {
mTimer->Cancel();
mTimer = nsnull;
}
::DeleteObject(mHBitmap);
mHBitmap = nsnull;
}
@ -1617,8 +1669,7 @@ nsImageWin::PrintDDB(nsIDrawingSurface* aSurface,
*
* @return the result of the operation, if NS_OK a DIB was created.
*/
nsresult
nsImageWin::ConvertDDBtoDIB()
nsresult nsImageWin::ConvertDDBtoDIB()
{
HDC memPrDC;
@ -1628,29 +1679,31 @@ nsImageWin::ConvertDDBtoDIB()
if (!mInitialized || mHBitmap == nsnull)
return NS_ERROR_FAILURE;
// mSizeImage might be 0, so use a temporary variable and set mSizeImage
// after we succeed with creating mImageBits.
PRUint32 newImageSize = mRowBytes * mBHead->biHeight; // no compression
// Allocate the image bits
mImageBits = new unsigned char[newImageSize];
if (!mImageBits)
return NS_ERROR_FAILURE;
mSizeImage = newImageSize;
memPrDC = ::CreateDC("DISPLAY", NULL, NULL, NULL);
if (!memPrDC)
return NS_ERROR_FAILURE;
// Allocate the image bits
mImageBits = new unsigned char[mSizeImage];
if (!mImageBits) {
::DeleteDC(memPrDC);
return NS_ERROR_OUT_OF_MEMORY;
}
PRInt32 retVal =
::GetDIBits(memPrDC, mHBitmap, 0, mBHead->biHeight,
mImageBits, (LPBITMAPINFO)mBHead,
256 == mNumPaletteColors ? DIB_PAL_COLORS : DIB_RGB_COLORS);
::GdiFlush();
::DeleteDC(memPrDC);
return (retVal == 0) ? NS_ERROR_FAILURE : NS_OK;
if (retVal == 0) {
delete [] mImageBits;
mImageBits = nsnull;
return NS_ERROR_FAILURE;
}
return NS_OK;
}
@ -1983,3 +2036,20 @@ CompositeBitsInMemory(HDC aTheHDC, int aDX, int aDY, int aDWidth, int aDHeight,
::DeleteDC(memDC);
}
}
void nsImageWin::TimerCallBack(nsITimer *aTimer, void *aClosure)
{
nsImageWin *entry = NS_STATIC_CAST(nsImageWin*, aClosure);
if (!entry)
return;
if (NS_FAILED(entry->RemoveDDB())) {
// Try again later. Can't SetDelay while timer is being called, so
// create a new timer instead
entry->mTimer = do_CreateInstance("@mozilla.org/timer;1");
if (entry->mTimer)
entry->mTimer->InitWithFuncCallback(nsImageWin::TimerCallBack, entry,
GFX_MS_REMOVE_DBB,
nsITimer::TYPE_ONE_SHOT);
}
}

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

@ -40,6 +40,11 @@
#include <windows.h>
#include "nsIImage.h"
#include "nsCOMPtr.h"
#include "nsITimer.h"
// Remove DDB after 60s of non-use
#define GFX_MS_REMOVE_DBB 60000
/* for compatibility with VC++ 5 */
#if !defined(AC_SRC_OVER)
@ -156,6 +161,13 @@ public:
static PRInt32 gPlatform;
static PRInt32 gOsMajorVersion;
/** Create a DDB out of the imagebits, and destroy the imagebits
*/
NS_IMETHOD CreateDDB();
/** Removes the DBB, restoring the imagebits if necessary
*/
NS_IMETHOD RemoveDDB();
private:
/**
* Clean the device Independent bits that could be allocated by this object.
@ -252,6 +264,7 @@ private:
PRUint8 PaletteMatch(PRUint8 r, PRUint8 g, PRUint8 b);
PRPackedBool mInitialized;
PRPackedBool mWantsOptimization;
PRPackedBool mIsOptimized; // Did we convert our DIB to a HBITMAP
PRPackedBool mIsLocked; // variable to keep track of the locking
PRPackedBool mDIBTemp; // boolean to let us know if DIB was created as temp
@ -277,6 +290,8 @@ private:
static ALPHABLENDPROC gAlphaBlend; // AlphaBlend function pointer
nsCOMPtr<nsITimer> mTimer; // Timer for releasing DDB
static void TimerCallBack(nsITimer *aTimer, void *aClosure);
};
#endif