b=494438; add optional OpenGL acceleration to ddraw surface for CE: better integration with rest of system; r=vlad

This commit is contained in:
Vladimir Vukicevic 2009-07-08 16:34:02 -07:00
Родитель ccc387da9b
Коммит 662ffbc455
9 изменённых файлов: 130 добавлений и 101 удалений

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

@ -55,13 +55,22 @@ static PRBool gDisableOptimize = PR_FALSE;
#include "gfxDDrawSurface.h"
#endif
#ifdef XP_WIN
#if defined(XP_WIN) || defined(WINCE)
#include "gfxWindowsPlatform.h"
#endif
#if defined(XP_WIN) && !defined(WINCE)
/* Whether to use the windows surface; only for desktop win32 */
#define USE_WIN_SURFACE 1
static PRUint32 gTotalDDBs = 0;
static PRUint32 gTotalDDBSize = 0;
// only use up a maximum of 64MB in DDBs
#define kMaxDDBSize (64*1024*1024)
// and don't let anything in that's bigger than 4MB
#define kMaxSingleDDBSize (4*1024*1024)
#endif
NS_IMPL_ISUPPORTS1(nsThebesImage, nsIImage)
@ -86,7 +95,7 @@ nsThebesImage::nsThebesImage()
hasCheckedOptimize = PR_TRUE;
}
#ifdef XP_WIN
#ifdef USE_WIN_SURFACE
mIsDDBSurface = PR_FALSE;
#endif
}
@ -134,14 +143,8 @@ nsThebesImage::Init(PRInt32 aWidth, PRInt32 aHeight, PRInt32 aDepth, nsMaskRequi
// For Windows, we must create the device surface first (if we're
// going to) so that the image surface can wrap it. Can't be done
// the other way around.
#ifdef XP_WIN
#ifdef USE_WIN_SURFACE
if (!mNeverUseDeviceSurface && !ShouldUseImageSurfaces()) {
#if defined(WINCE) && defined(CAIRO_HAS_DDRAW_SURFACE)
// rambo in support for ddraw surfaces
// we let OptimizeSurface take care of switching between
// optimized and not, since thebes surfaces assume width == stride
mWinSurface = nsnull;
#else
mWinSurface = new gfxWindowsSurface(gfxIntSize(mWidth, mHeight), format);
if (mWinSurface && mWinSurface->CairoStatus() == 0) {
// no error
@ -149,7 +152,6 @@ nsThebesImage::Init(PRInt32 aWidth, PRInt32 aHeight, PRInt32 aDepth, nsMaskRequi
} else {
mWinSurface = nsnull;
}
#endif
}
#endif
@ -179,7 +181,7 @@ nsThebesImage::Init(PRInt32 aWidth, PRInt32 aHeight, PRInt32 aDepth, nsMaskRequi
nsThebesImage::~nsThebesImage()
{
#ifdef XP_WIN
#ifdef USE_WIN_SURFACE
if (mIsDDBSurface) {
gTotalDDBs--;
gTotalDDBSize -= mWidth*mHeight*4;
@ -316,7 +318,7 @@ nsThebesImage::Optimize(nsIDeviceContext* aContext)
mImageSurface = nsnull;
mOptSurface = nsnull;
#ifdef XP_WIN
#ifdef USE_WIN_SURFACE
mWinSurface = nsnull;
#endif
#ifdef XP_MACOSX
@ -336,7 +338,7 @@ nsThebesImage::Optimize(nsIDeviceContext* aContext)
mOptSurface = nsnull;
#ifdef XP_WIN
#ifdef USE_WIN_SURFACE
// we need to special-case windows here, because windows has
// a distinction between DIB and DDB and we want to use DDBs as much
// as we can.
@ -389,7 +391,7 @@ nsThebesImage::Optimize(nsIDeviceContext* aContext)
if (mOptSurface) {
mImageSurface = nsnull;
#ifdef XP_WIN
#ifdef USE_WIN_SURFACE
mWinSurface = nsnull;
#endif
#ifdef XP_MACOSX
@ -437,7 +439,7 @@ nsThebesImage::LockImagePixels(PRBool aMaskPixels)
context.SetSource(mOptSurface);
context.Paint();
#ifdef XP_WIN
#ifdef USE_WIN_SURFACE
mWinSurface = nsnull;
#endif
#ifdef XP_MACOSX
@ -814,14 +816,11 @@ nsThebesImage::ShouldUseImageSurfaces()
#if defined(WINCE)
// There is no test on windows mobile to check for Gui resources.
// Allocate, until we run out of memory.
#if defined(WINCE) && defined(CAIRO_HAS_DDRAW_SURFACE)
return PR_FALSE;
#else
/* on baseline wince only use image surfaces */
return PR_TRUE;
#endif
gfxWindowsPlatform::RenderMode rmode = gfxWindowsPlatform::GetPlatform()->GetRenderMode();
return rmode != gfxWindowsPlatform::RENDER_DDRAW &&
rmode != gfxWindowsPlatform::RENDER_DDRAW_GL;
#elif defined(XP_WIN)
#elif defined(USE_WIN_SURFACE)
static const DWORD kGDIObjectsHighWaterMark = 7000;
// at 7000 GDI objects, stop allocating normal images to make sure

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

@ -105,7 +105,7 @@ public:
gfxASurface* ThebesSurface() {
if (mOptSurface)
return mOptSurface;
#if defined(XP_WIN)
#if defined(XP_WIN) && !defined(WINCE)
if (mWinSurface)
return mWinSurface;
#elif defined(XP_MACOSX)
@ -161,7 +161,7 @@ protected:
PRPackedBool mSinglePixel;
PRPackedBool mFormatChanged;
PRPackedBool mNeverUseDeviceSurface;
#ifdef XP_WIN
#if defined(XP_WIN) && !defined(WINCE)
PRPackedBool mIsDDBSurface;
#endif
@ -169,7 +169,7 @@ protected:
nsRefPtr<gfxImageSurface> mImageSurface;
nsRefPtr<gfxASurface> mOptSurface;
#if defined(XP_WIN)
#if defined(XP_WIN) && !defined(WINCE)
nsRefPtr<gfxWindowsSurface> mWinSurface;
#elif defined(XP_MACOSX)
nsRefPtr<gfxQuartzImageSurface> mQuartzSurface;

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

@ -39,6 +39,10 @@
#ifndef GFX_WINDOWS_PLATFORM_H
#define GFX_WINDOWS_PLATFORM_H
#if defined(WINCE)
#define MOZ_FT2_FONTS 1
#endif
#include "gfxFontUtils.h"
#include "gfxWindowsSurface.h"
#ifdef MOZ_FT2_FONTS
@ -68,6 +72,32 @@ public:
already_AddRefed<gfxASurface> CreateOffscreenSurface(const gfxIntSize& size,
gfxASurface::gfxImageFormat imageFormat);
enum RenderMode {
/* Use GDI and windows surfaces */
RENDER_GDI = 0,
/* Use 32bpp image surfaces and call StretchDIBits */
RENDER_IMAGE_STRETCH32,
/* Use 32bpp image surfaces, and do 32->24 conversion before calling StretchDIBits */
RENDER_IMAGE_STRETCH24,
/* Use DirectDraw on Windows CE */
RENDER_DDRAW,
/* Use 24bpp image surfaces, with final DirectDraw 16bpp blt on Windows CE */
RENDER_IMAGE_DDRAW16,
/* Use DirectDraw with OpenGL on Windows CE */
RENDER_DDRAW_GL,
/* max */
RENDER_MODE_MAX
};
RenderMode GetRenderMode() { return mRenderMode; }
void SetRenderMode(RenderMode rmode) { mRenderMode = rmode; }
nsresult GetFontList(const nsACString& aLangGroup,
const nsACString& aGenericFamily,
nsTArray<nsString>& aListOfFonts);
@ -133,6 +163,9 @@ private:
void FindFonts();
#endif
protected:
RenderMode mRenderMode;
private:
void Init();

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

@ -60,7 +60,6 @@ CPPSRCS += gfxWindowsPlatform.cpp \
$(NULL)
ifdef WINCE
DEFINES += -DMOZ_FT2_FONTS
CPPSRCS += gfxFT2Fonts.cpp \
gfxDDrawSurface.cpp \
$(NULL)

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

@ -131,16 +131,37 @@ gfxWindowsPlatform::gfxWindowsPlatform()
UpdateFontList();
gfxWindowsPlatformPrefObserver *observer = new gfxWindowsPlatformPrefObserver();
if (observer) {
nsCOMPtr<nsIPrefBranch2> pref = do_GetService(NS_PREFSERVICE_CONTRACTID);
if (pref) {
nsCOMPtr<nsIPrefBranch2> pref = do_GetService(NS_PREFSERVICE_CONTRACTID);
if (pref) {
gfxWindowsPlatformPrefObserver *observer = new gfxWindowsPlatformPrefObserver();
if (observer) {
pref->AddObserver("font.", observer, PR_FALSE);
pref->AddObserver("font.name-list.", observer, PR_FALSE);
pref->AddObserver("intl.accept_languages", observer, PR_FALSE);
// don't bother unregistering. We'll get shutdown after the pref service
} else {
delete observer;
}
}
/* Pick the default render mode differently between
* desktop, Windows Mobile, and Windows CE.
*/
#if defined(WINCE_WINDOWS_MOBILE)
mRenderMode = RENDER_IMAGE_DDRAW16;
#elif defined(WINCE)
mRenderMode = RENDER_DDRAW_GL;
#else
mRenderMode = RENDER_GDI;
#endif
PRInt32 rmode;
if (NS_SUCCEEDED(pref->GetIntPref("mozilla.widget.render-mode", &rmode))) {
if (rmode >= 0 || rmode < RENDER_MODE_MAX) {
#ifndef CAIRO_HAS_DDRAW_SURFACE
if (rmode == RENDER_DDRAW || rmode == RENDER_DDRAW_GL)
rmode = RENDER_IMAGE_STRETCH24;
#endif
mRenderMode = (RenderMode) rmode;
}
}
}
@ -155,16 +176,23 @@ already_AddRefed<gfxASurface>
gfxWindowsPlatform::CreateOffscreenSurface(const gfxIntSize& size,
gfxASurface::gfxImageFormat imageFormat)
{
#ifndef WINCE
gfxASurface *surf = new gfxWindowsSurface(size, imageFormat);
#else
gfxASurface *surf = nsnull;
#ifdef CAIRO_HAS_DDRAW_SURFACE
gfxASurface *surf = new gfxDDrawSurface(NULL, size, imageFormat);
#else
gfxASurface *surf = new gfxImageSurface(size, imageFormat);
if (mRenderMode == RENDER_DDRAW || mRenderMode == RENDER_DDRAW_GL)
surf = new gfxDDrawSurface(NULL, size, imageFormat);
#endif
#ifdef CAIRO_HAS_WIN32_SURFACE
if (mRenderMode == RENDER_GDI)
surf = new gfxWindowsSurface(size, imageFormat);
#endif
if (surf == nsnull)
surf = new gfxImageSurface(size, imageFormat);
NS_IF_ADDREF(surf);
return surf;
}

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

@ -708,19 +708,6 @@ nsWindow::StandardWindowCreate(nsIWidget *aParent,
if (NS_SUCCEEDED(prefBranch->GetBoolPref("mozilla.widget.disable-native-theme",
&temp)))
gDisableNativeTheme = temp;
PRInt32 tempint;
if (NS_SUCCEEDED(prefBranch->GetIntPref("mozilla.widget.render-mode",
&tempint)))
{
if (tempint > 0 && tempint < RENDER_MODE_MAX) {
#ifndef CAIRO_HAS_DDRAW_SURFACE
if (tempint == RENDER_DDRAW)
tempint = RENDER_IMAGE_STRETCH24;
#endif
sRenderMode = (WinRenderMode) tempint;
}
}
}
}
}

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

@ -476,7 +476,7 @@ protected:
// Graphics
HDC mPaintDC; // only set during painting
static WinRenderMode sRenderMode;
static nsAutoPtr<PRUint8> sSharedSurfaceData;
static gfxIntSize sSharedSurfaceSize;

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

@ -149,6 +149,9 @@
#ifndef RDW_NOINTERNALPAINT
#define RDW_NOINTERNALPAINT 0
#endif
#ifndef ERROR
#define ERROR 0
#endif
#endif // defined(WINCE)
/**************************************************************
@ -165,34 +168,6 @@ typedef enum
TRI_TRUE = 1
} TriStateBool;
// Rendering modes
typedef enum {
// Use GDI and windows surfaces.
RENDER_GDI = 0,
// Use 32bpp image surfaces and call StretchDIBits.
RENDER_IMAGE_STRETCH32,
// Use 32bpp image surfaces, and do 32->24 conversion before calling StretchDIBits.
RENDER_IMAGE_STRETCH24,
// Use DirectDraw on Windows CE.
RENDER_DDRAW,
// Use 24bpp image surfaces and DirectDraw 166bbp on Windows CE.
RENDER_IMAGE_DDRAW16,
// max
RENDER_MODE_MAX
} WinRenderMode;
/*
* Pick the default render mode differently between
* desktop, Windows Mobile, and Windows CE.
*/
#if defined(WINCE_WINDOWS_MOBILE)
#define DEFAULT_RENDER_MODE RENDER_IMAGE_DDRAW16
#elif defined(WINCE)
#define DEFAULT_RENDER_MODE RENDER_DDRAW
#else
#define DEFAULT_RENDER_MODE RENDER_GDI
#endif
/**************************************************************
*
* SECTION: constants
@ -278,4 +253,4 @@ struct KeyPair {
NS_ASSERTION(((s) & (WS_CHILD | WS_POPUP)) != (WS_CHILD | WS_POPUP), \
"WS_POPUP and WS_CHILD are mutually exclusive")
#endif /* WindowDefs_h__ */
#endif /* WindowDefs_h__ */

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

@ -58,6 +58,7 @@
#include "nsIRegion.h"
#include "gfxImageSurface.h"
#include "gfxWindowsSurface.h"
#include "gfxWindowsPlatform.h"
#include "nsGfxCIID.h"
#include "gfxContext.h"
#include "nsIRenderingContext.h"
@ -94,11 +95,10 @@ extern "C" {
nsAutoPtr<PRUint8> nsWindow::sSharedSurfaceData;
gfxIntSize nsWindow::sSharedSurfaceSize;
WinRenderMode nsWindow::sRenderMode = DEFAULT_RENDER_MODE;
/**************************************************************
*
* SECTION: globals variables.
* SECTION: global variables.
*
**************************************************************/
@ -125,6 +125,12 @@ static NS_DEFINE_IID(kRenderingContextCID, NS_RENDERING_CONTEXT_CID);
**************************************************************
**************************************************************/
static PRBool
IsRenderMode(gfxWindowsPlatform::RenderMode rmode)
{
return gfxWindowsPlatform::GetPlatform()->GetRenderMode() == rmode;
}
void
nsWindowGfx::AddRECTToRegion(const RECT& aRect, nsIRegion* aRegion)
{
@ -195,8 +201,7 @@ nsWindowGfx::InitDDraw()
// We do not use the cairo ddraw surface for IMAGE_DDRAW16. Instead, we
// use an 24bpp image surface, convert that to 565, then blit using ddraw.
if (nsWindow::sRenderMode != RENDER_IMAGE_DDRAW16)
{
if (!IsRenderMode(gfxWindowsPlatform::RENDER_IMAGE_DDRAW16)) {
gfxIntSize screen_size(GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
gpDDSurf = new gfxDDrawSurface(glpDD, screen_size, gfxASurface::ImageFormatRGB24);
if (!gpDDSurf) {
@ -253,7 +258,7 @@ void nsWindow::SetUpForPaint(HDC aHDC)
PRBool nsWindow::OnPaint(HDC aDC)
{
#ifdef CAIRO_HAS_DDRAW_SURFACE
if (sRenderMode == RENDER_IMAGE_DDRAW16) {
if (IsRenderMode(gfxWindowsPlatform::RENDER_IMAGE_DDRAW16)) {
return OnPaintImageDDraw16();
}
#endif
@ -363,7 +368,7 @@ PRBool nsWindow::OnPaint(HDC aDC)
#if defined(MOZ_XUL)
// don't support transparency for non-GDI rendering, for now
if (sRenderMode == RENDER_GDI && eTransparencyTransparent == mTransparencyMode) {
if (IsRenderMode(gfxWindowsPlatform::RENDER_GDI) && eTransparencyTransparent == mTransparencyMode) {
if (mTransparentSurface == nsnull)
SetupTranslucentWindowMemoryBitmap(mTransparencyMode);
targetSurface = mTransparentSurface;
@ -372,7 +377,7 @@ PRBool nsWindow::OnPaint(HDC aDC)
nsRefPtr<gfxWindowsSurface> targetSurfaceWin;
if (!targetSurface &&
sRenderMode == RENDER_GDI)
IsRenderMode(gfxWindowsPlatform::RENDER_GDI))
{
targetSurfaceWin = new gfxWindowsSurface(hDC);
targetSurface = targetSurfaceWin;
@ -381,12 +386,13 @@ PRBool nsWindow::OnPaint(HDC aDC)
#ifdef CAIRO_HAS_DDRAW_SURFACE
nsRefPtr<gfxDDrawSurface> targetSurfaceDDraw;
if (!targetSurface &&
sRenderMode == RENDER_DDRAW)
(IsRenderMode(gfxWindowsPlatform::RENDER_DDRAW) ||
IsRenderMode(gfxWindowsPlatform::RENDER_DDRAW_GL)))
{
if (!glpDD) {
if (!nsWindowGfx::InitDDraw()) {
NS_WARNING("DirectDraw init failed; falling back to RENDER_IMAGE_STRETCH24");
sRenderMode = RENDER_IMAGE_STRETCH24;
gfxWindowsPlatform::GetPlatform()->SetRenderMode(gfxWindowsPlatform::RENDER_IMAGE_STRETCH24);
goto DDRAW_FAILED;
}
}
@ -405,8 +411,8 @@ PRBool nsWindow::OnPaint(HDC aDC)
DDRAW_FAILED:
nsRefPtr<gfxImageSurface> targetSurfaceImage;
if (!targetSurface &&
(sRenderMode == RENDER_IMAGE_STRETCH32 ||
sRenderMode == RENDER_IMAGE_STRETCH24))
(IsRenderMode(gfxWindowsPlatform::RENDER_IMAGE_STRETCH32) ||
IsRenderMode(gfxWindowsPlatform::RENDER_IMAGE_STRETCH24)))
{
if (!sSharedSurfaceData) {
sSharedSurfaceSize.height = GetSystemMetrics(SM_CYSCREEN);
@ -440,7 +446,7 @@ DDRAW_FAILED:
}
if (!targetSurface) {
NS_ERROR("Invalid sRenderMode!");
NS_ERROR("Invalid RenderMode!");
return NS_ERROR_FAILURE;
}
@ -452,7 +458,7 @@ DDRAW_FAILED:
#endif
// don't need to double buffer with anything but GDI
if (sRenderMode == RENDER_GDI) {
if (IsRenderMode(gfxWindowsPlatform::RENDER_GDI)) {
# if defined(MOZ_XUL) && !defined(WINCE)
if (eTransparencyGlass == mTransparencyMode && nsUXThemeData::sHaveCompositor) {
thebesContext->PushGroup(gfxASurface::CONTENT_COLOR_ALPHA);
@ -496,7 +502,7 @@ DDRAW_FAILED:
#endif
#ifdef MOZ_XUL
if (sRenderMode == RENDER_GDI &&
if (IsRenderMode(gfxWindowsPlatform::RENDER_GDI) &&
eTransparencyTransparent == mTransparencyMode) {
// Data from offscreen drawing surface was copied to memory bitmap of transparent
// bitmap. Now it can be read from memory bitmap to apply alpha channel and after
@ -505,13 +511,15 @@ DDRAW_FAILED:
} else
#endif
if (result) {
if (sRenderMode == RENDER_GDI) {
if (IsRenderMode(gfxWindowsPlatform::RENDER_GDI)) {
// Only update if DispatchWindowEvent returned TRUE; otherwise, nothing handled
// this, and we'll just end up painting with black.
thebesContext->PopGroupToSource();
thebesContext->SetOperator(gfxContext::OPERATOR_SOURCE);
thebesContext->Paint();
} else if (sRenderMode == RENDER_DDRAW) {
} else if (IsRenderMode(gfxWindowsPlatform::RENDER_DDRAW) ||
IsRenderMode(gfxWindowsPlatform::RENDER_DDRAW_GL))
{
#ifdef CAIRO_HAS_DDRAW_SURFACE
// blit with direct draw
HRESULT hr = glpDDClipper->SetHWnd(0, mWnd);
@ -535,8 +543,8 @@ DDRAW_FAILED:
DDError("SetHWnd", hr);
#endif
#endif
} else if (sRenderMode == RENDER_IMAGE_STRETCH24 ||
sRenderMode == RENDER_IMAGE_STRETCH32)
} else if (IsRenderMode(gfxWindowsPlatform::RENDER_IMAGE_STRETCH24) ||
IsRenderMode(gfxWindowsPlatform::RENDER_IMAGE_STRETCH32))
{
gfxIntSize surfaceSize = targetSurfaceImage->GetSize();
@ -550,7 +558,7 @@ DDRAW_FAILED:
bi.biBitCount = 32;
bi.biCompression = BI_RGB;
if (sRenderMode == RENDER_IMAGE_STRETCH24) {
if (IsRenderMode(gfxWindowsPlatform::RENDER_IMAGE_STRETCH24)) {
// On Windows CE/Windows Mobile, 24bpp packed-pixel sources
// seem to be far faster to blit than 32bpp (see bug 484864).
// So, convert the bits to 24bpp by stripping out the unused
@ -901,4 +909,4 @@ cleanup:
mPainting = PR_FALSE;
return result;
}
#endif // defined(CAIRO_HAS_DDRAW_SURFACE)
#endif // defined(CAIRO_HAS_DDRAW_SURFACE)