Bug 556027: Add the ability to enable accelerated layers backends for specific top-level widgets. r=roc

This commit is contained in:
Bas Schouten 2010-03-31 05:02:58 +02:00
Родитель 3bfc202468
Коммит 34b849c1ad
6 изменённых файлов: 339 добавлений и 244 удалений

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

@ -110,8 +110,8 @@ typedef nsEventStatus (* EVENT_CALLBACK)(nsGUIEvent *event);
#endif
#define NS_IWIDGET_IID \
{ 0x42b34d98, 0x7371, 0x48e4, \
{ 0xbf, 0x85, 0x2c, 0x02, 0x0c, 0x4a, 0x8d, 0x26 } }
{ 0xf286438a, 0x6ec6, 0x4766, \
{ 0xa4, 0x76, 0x4a, 0x44, 0x80, 0x95, 0xd3, 0x1f } }
/*
* Window shadow styles
* Also used for the -moz-window-shadow CSS property
@ -1062,6 +1062,11 @@ class nsIWidget : public nsISupports {
*/
NS_IMETHOD CancelIMEComposition() = 0;
/**
* Set accelerated rendering to 'True' or 'False'
*/
NS_IMETHOD SetAcceleratedRendering(PRBool aEnabled) = 0;
/*
* Get toggled key states.
* aKeyCode should be NS_VK_CAPS_LOCK or NS_VK_NUM_LOCK or

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

@ -166,6 +166,7 @@
#include "nsWindowGfx.h"
#include "gfxWindowsPlatform.h"
#include "Layers.h"
#if !defined(WINCE)
#include "nsUXThemeConstants.h"
@ -665,6 +666,12 @@ NS_METHOD nsWindow::Destroy()
// During the destruction of all of our children, make sure we don't get deleted.
nsCOMPtr<nsIWidget> kungFuDeathGrip(this);
/**
* On windows the LayerManagerOGL destructor wants the widget to be around for
* cleanup. It also would like to have the HWND intact, so we NULL it here.
*/
mLayerManager = NULL;
// The DestroyWindow function destroys the specified window. The function sends WM_DESTROY
// and WM_NCDESTROY messages to the window to deactivate it and remove the keyboard focus
// from it. The function also destroys the window's menu, flushes the thread message queue,
@ -2900,6 +2907,30 @@ nsWindow::HasPendingInputEvent()
#endif
}
/**************************************************************
*
* SECTION: nsIWidget::GetLayerManager
*
* Get the layer manager associated with this widget.
*
**************************************************************/
mozilla::layers::LayerManager*
nsWindow::GetLayerManager()
{
nsWindow *topWindow = GetNSWindowPtr(GetTopLevelHWND(mWnd, PR_TRUE));
if (!topWindow) {
return nsBaseWidget::GetLayerManager();
}
if (topWindow->GetAcceleratedRendering() != mUseAcceleratedRendering) {
mLayerManager = NULL;
mUseAcceleratedRendering = topWindow->GetAcceleratedRendering();
}
return nsBaseWidget::GetLayerManager();
}
/**************************************************************
*
* SECTION: nsIWidget::GetThebesSurface

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

@ -163,6 +163,7 @@ public:
PRBool aDoCapture, PRBool aConsumeRollupEvent);
NS_IMETHOD GetAttention(PRInt32 aCycleCount);
virtual PRBool HasPendingInputEvent();
virtual LayerManager* GetLayerManager();
gfxASurface *GetThebesSurface();
NS_IMETHOD OnDefaultButtonLoaded(const nsIntRect &aButtonRect);
NS_IMETHOD OverrideSystemMouseScrollSpeed(PRInt32 aOriginalDelta, PRBool aIsHorizontal, PRInt32 &aOverriddenDelta);

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

@ -70,6 +70,8 @@ using mozilla::plugins::PluginInstanceParent;
#include "nsIDeviceContext.h"
#include "prmem.h"
#include "LayerManagerOGL.h"
#ifndef WINCE
#include "nsUXThemeData.h"
#include "nsUXThemeConstants.h"
@ -411,266 +413,280 @@ PRBool nsWindow::OnPaint(HDC aDC)
(PRInt32) mWnd);
#endif // WIDGET_DEBUG_OUTPUT
nsRefPtr<gfxASurface> targetSurface;
switch (GetLayerManager()->GetBackendType()) {
case LayerManager::LAYERS_BASIC:
{
nsRefPtr<gfxASurface> targetSurface;
#if defined(MOZ_XUL)
// don't support transparency for non-GDI rendering, for now
if (IsRenderMode(gfxWindowsPlatform::RENDER_GDI) && eTransparencyTransparent == mTransparencyMode) {
if (mTransparentSurface == nsnull)
SetupTranslucentWindowMemoryBitmap(mTransparencyMode);
targetSurface = mTransparentSurface;
}
// don't support transparency for non-GDI rendering, for now
if (IsRenderMode(gfxWindowsPlatform::RENDER_GDI) && eTransparencyTransparent == mTransparencyMode) {
if (mTransparentSurface == nsnull)
SetupTranslucentWindowMemoryBitmap(mTransparencyMode);
targetSurface = mTransparentSurface;
}
#endif
nsRefPtr<gfxWindowsSurface> targetSurfaceWin;
if (!targetSurface &&
IsRenderMode(gfxWindowsPlatform::RENDER_GDI))
{
targetSurfaceWin = new gfxWindowsSurface(hDC);
targetSurface = targetSurfaceWin;
}
nsRefPtr<gfxWindowsSurface> targetSurfaceWin;
if (!targetSurface &&
IsRenderMode(gfxWindowsPlatform::RENDER_GDI))
{
targetSurfaceWin = new gfxWindowsSurface(hDC);
targetSurface = targetSurfaceWin;
}
#ifdef CAIRO_HAS_D2D_SURFACE
if (!targetSurface &&
IsRenderMode(gfxWindowsPlatform::RENDER_DIRECT2D))
{
if (!mD2DWindowSurface) {
mD2DWindowSurface = new gfxD2DSurface(mWnd);
}
targetSurface = mD2DWindowSurface;
}
if (!targetSurface &&
IsRenderMode(gfxWindowsPlatform::RENDER_DIRECT2D))
{
if (!mD2DWindowSurface) {
mD2DWindowSurface = new gfxD2DSurface(mWnd);
}
targetSurface = mD2DWindowSurface;
}
#endif
#ifdef CAIRO_HAS_DDRAW_SURFACE
nsRefPtr<gfxDDrawSurface> targetSurfaceDDraw;
if (!targetSurface &&
(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");
gfxWindowsPlatform::GetPlatform()->SetRenderMode(gfxWindowsPlatform::RENDER_IMAGE_STRETCH24);
goto DDRAW_FAILED;
}
}
nsRefPtr<gfxDDrawSurface> targetSurfaceDDraw;
if (!targetSurface &&
(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");
gfxWindowsPlatform::GetPlatform()->SetRenderMode(gfxWindowsPlatform::RENDER_IMAGE_STRETCH24);
goto DDRAW_FAILED;
}
}
// create a rect that maps the window in screen space
// create a new sub-surface that aliases this one
RECT winrect;
GetClientRect(mWnd, &winrect);
MapWindowPoints(mWnd, NULL, (LPPOINT)&winrect, 2);
// create a rect that maps the window in screen space
// create a new sub-surface that aliases this one
RECT winrect;
GetClientRect(mWnd, &winrect);
MapWindowPoints(mWnd, NULL, (LPPOINT)&winrect, 2);
targetSurfaceDDraw = new gfxDDrawSurface(gpDDSurf.get(), winrect);
targetSurface = targetSurfaceDDraw;
}
targetSurfaceDDraw = new gfxDDrawSurface(gpDDSurf.get(), winrect);
targetSurface = targetSurfaceDDraw;
}
#endif
DDRAW_FAILED:
nsRefPtr<gfxImageSurface> targetSurfaceImage;
if (!targetSurface &&
(IsRenderMode(gfxWindowsPlatform::RENDER_IMAGE_STRETCH32) ||
IsRenderMode(gfxWindowsPlatform::RENDER_IMAGE_STRETCH24)))
{
gfxIntSize surfaceSize(ps.rcPaint.right - ps.rcPaint.left,
ps.rcPaint.bottom - ps.rcPaint.top);
nsRefPtr<gfxImageSurface> targetSurfaceImage;
if (!targetSurface &&
(IsRenderMode(gfxWindowsPlatform::RENDER_IMAGE_STRETCH32) ||
IsRenderMode(gfxWindowsPlatform::RENDER_IMAGE_STRETCH24)))
{
gfxIntSize surfaceSize(ps.rcPaint.right - ps.rcPaint.left,
ps.rcPaint.bottom - ps.rcPaint.top);
if (!EnsureSharedSurfaceSize(surfaceSize)) {
NS_ERROR("Couldn't allocate a shared image surface!");
return NS_ERROR_FAILURE;
}
// don't use the shared surface directly; instead, create a new one
// that just reuses its buffer.
targetSurfaceImage = new gfxImageSurface(sSharedSurfaceData.get(),
surfaceSize,
surfaceSize.width * 4,
gfxASurface::ImageFormatRGB24);
if (targetSurfaceImage && !targetSurfaceImage->CairoStatus()) {
targetSurfaceImage->SetDeviceOffset(gfxPoint(-ps.rcPaint.left, -ps.rcPaint.top));
targetSurface = targetSurfaceImage;
}
}
if (!targetSurface) {
NS_ERROR("Invalid RenderMode!");
return NS_ERROR_FAILURE;
}
nsRefPtr<gfxContext> thebesContext = new gfxContext(targetSurface);
thebesContext->SetFlag(gfxContext::FLAG_DESTINED_FOR_SCREEN);
if (IsRenderMode(gfxWindowsPlatform::RENDER_DIRECT2D)) {
const nsIntRect* r;
for (nsIntRegionRectIterator iter(event.region);
(r = iter.Next()) != nsnull;) {
thebesContext->Rectangle(gfxRect(r->x, r->y, r->width, r->height), PR_TRUE);
}
thebesContext->Clip();
}
#ifdef WINCE
thebesContext->SetFlag(gfxContext::FLAG_SIMPLIFY_OPERATORS);
#endif
// don't need to double buffer with anything but GDI
if (IsRenderMode(gfxWindowsPlatform::RENDER_GDI)) {
# if defined(MOZ_XUL) && !defined(WINCE)
if (eTransparencyGlass == mTransparencyMode && nsUXThemeData::sHaveCompositor) {
thebesContext->PushGroup(gfxASurface::CONTENT_COLOR_ALPHA);
} else if (eTransparencyTransparent == mTransparencyMode) {
// If we're rendering with translucency, we're going to be
// rendering the whole window; make sure we clear it first
thebesContext->SetOperator(gfxContext::OPERATOR_CLEAR);
thebesContext->Paint();
thebesContext->SetOperator(gfxContext::OPERATOR_OVER);
} else
#endif
{
// If we're not doing translucency, then double buffer
thebesContext->PushGroup(gfxASurface::CONTENT_COLOR);
}
}
{
AutoLayerManagerSetup setupLayerManager(this, thebesContext);
result = DispatchWindowEvent(&event, eventStatus);
}
#ifdef MOZ_XUL
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
// that displayed on the screen.
UpdateTranslucentWindow();
} else
#endif
#ifdef CAIRO_HAS_D2D_SURFACE
if (result) {
if (mD2DWindowSurface) {
mD2DWindowSurface->Present();
}
}
#endif
if (result) {
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 (IsRenderMode(gfxWindowsPlatform::RENDER_DDRAW) ||
IsRenderMode(gfxWindowsPlatform::RENDER_DDRAW_GL))
{
#ifdef CAIRO_HAS_DDRAW_SURFACE
// blit with direct draw
HRESULT hr = glpDDClipper->SetHWnd(0, mWnd);
#ifdef DEBUG
if (FAILED(hr))
DDError("SetHWnd", hr);
#endif
// blt from the affected area from the window back-buffer to the
// screen-relative coordinates of the window paint area
RECT dst_rect = ps.rcPaint;
MapWindowPoints(mWnd, NULL, (LPPOINT)&dst_rect, 2);
hr = glpDDPrimary->Blt(&dst_rect,
gpDDSurf->GetDDSurface(),
&dst_rect,
DDBLT_WAITNOTBUSY,
NULL);
#ifdef DEBUG
if (FAILED(hr))
DDError("SetHWnd", hr);
#endif
#endif
} else if (IsRenderMode(gfxWindowsPlatform::RENDER_IMAGE_STRETCH24) ||
IsRenderMode(gfxWindowsPlatform::RENDER_IMAGE_STRETCH32))
{
gfxIntSize surfaceSize = targetSurfaceImage->GetSize();
// Just blit this directly
BITMAPINFOHEADER bi;
memset(&bi, 0, sizeof(BITMAPINFOHEADER));
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = surfaceSize.width;
bi.biHeight = - surfaceSize.height;
bi.biPlanes = 1;
bi.biBitCount = 32;
bi.biCompression = BI_RGB;
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
// alpha byte. 24bpp DIBs also have scanlines that are 4-byte
// aligned though, so that must be taken into account.
int srcstride = surfaceSize.width*4;
int dststride = surfaceSize.width*3;
dststride = (dststride + 3) & ~3;
// Convert in place
for (int j = 0; j < surfaceSize.height; ++j) {
unsigned int *src = (unsigned int*) (targetSurfaceImage->Data() + j*srcstride);
unsigned int *dst = (unsigned int*) (targetSurfaceImage->Data() + j*dststride);
// go 4 pixels at a time, since each 4 pixels
// turns into 3 DWORDs when converted into BGR:
// BGRx BGRx BGRx BGRx -> BGRB GRBG RBGR
//
// However, since we're dealing with little-endian ints, this is actually:
// xRGB xrgb xRGB xrgb -> bRGB GBrg rgbR
int width_left = surfaceSize.width;
while (width_left >= 4) {
unsigned int a = *src++;
unsigned int b = *src++;
unsigned int c = *src++;
unsigned int d = *src++;
*dst++ = (a & 0x00ffffff) | (b << 24);
*dst++ = ((b & 0x00ffff00) >> 8) | (c << 16);
*dst++ = ((c & 0x00ff0000) >> 16) | (d << 8);
width_left -= 4;
if (!EnsureSharedSurfaceSize(surfaceSize)) {
NS_ERROR("Couldn't allocate a shared image surface!");
return NS_ERROR_FAILURE;
}
// then finish up whatever number of pixels are left,
// using bytes.
unsigned char *bsrc = (unsigned char*) src;
unsigned char *bdst = (unsigned char*) dst;
switch (width_left) {
case 3:
*bdst++ = *bsrc++;
*bdst++ = *bsrc++;
*bdst++ = *bsrc++;
bsrc++;
case 2:
*bdst++ = *bsrc++;
*bdst++ = *bsrc++;
*bdst++ = *bsrc++;
bsrc++;
case 1:
*bdst++ = *bsrc++;
*bdst++ = *bsrc++;
*bdst++ = *bsrc++;
bsrc++;
case 0:
break;
// don't use the shared surface directly; instead, create a new one
// that just reuses its buffer.
targetSurfaceImage = new gfxImageSurface(sSharedSurfaceData.get(),
surfaceSize,
surfaceSize.width * 4,
gfxASurface::ImageFormatRGB24);
if (targetSurfaceImage && !targetSurfaceImage->CairoStatus()) {
targetSurfaceImage->SetDeviceOffset(gfxPoint(-ps.rcPaint.left, -ps.rcPaint.top));
targetSurface = targetSurfaceImage;
}
}
bi.biBitCount = 24;
}
if (!targetSurface) {
NS_ERROR("Invalid RenderMode!");
return NS_ERROR_FAILURE;
}
StretchDIBits(hDC,
ps.rcPaint.left, ps.rcPaint.top,
surfaceSize.width, surfaceSize.height,
0, 0,
surfaceSize.width, surfaceSize.height,
targetSurfaceImage->Data(),
(BITMAPINFO*) &bi,
DIB_RGB_COLORS,
SRCCOPY);
}
nsRefPtr<gfxContext> thebesContext = new gfxContext(targetSurface);
thebesContext->SetFlag(gfxContext::FLAG_DESTINED_FOR_SCREEN);
if (IsRenderMode(gfxWindowsPlatform::RENDER_DIRECT2D)) {
const nsIntRect* r;
for (nsIntRegionRectIterator iter(event.region);
(r = iter.Next()) != nsnull;) {
thebesContext->Rectangle(gfxRect(r->x, r->y, r->width, r->height), PR_TRUE);
}
thebesContext->Clip();
}
#ifdef WINCE
thebesContext->SetFlag(gfxContext::FLAG_SIMPLIFY_OPERATORS);
#endif
// don't need to double buffer with anything but GDI
if (IsRenderMode(gfxWindowsPlatform::RENDER_GDI)) {
# if defined(MOZ_XUL) && !defined(WINCE)
if (eTransparencyGlass == mTransparencyMode && nsUXThemeData::sHaveCompositor) {
thebesContext->PushGroup(gfxASurface::CONTENT_COLOR_ALPHA);
} else if (eTransparencyTransparent == mTransparencyMode) {
// If we're rendering with translucency, we're going to be
// rendering the whole window; make sure we clear it first
thebesContext->SetOperator(gfxContext::OPERATOR_CLEAR);
thebesContext->Paint();
thebesContext->SetOperator(gfxContext::OPERATOR_OVER);
} else
#endif
{
// If we're not doing translucency, then double buffer
thebesContext->PushGroup(gfxASurface::CONTENT_COLOR);
}
}
{
AutoLayerManagerSetup setupLayerManager(this, thebesContext);
result = DispatchWindowEvent(&event, eventStatus);
}
#ifdef MOZ_XUL
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
// that displayed on the screen.
UpdateTranslucentWindow();
} else
#endif
#ifdef CAIRO_HAS_D2D_SURFACE
if (result) {
if (mD2DWindowSurface) {
mD2DWindowSurface->Present();
}
}
#endif
if (result) {
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 (IsRenderMode(gfxWindowsPlatform::RENDER_DDRAW) ||
IsRenderMode(gfxWindowsPlatform::RENDER_DDRAW_GL))
{
#ifdef CAIRO_HAS_DDRAW_SURFACE
// blit with direct draw
HRESULT hr = glpDDClipper->SetHWnd(0, mWnd);
#ifdef DEBUG
if (FAILED(hr))
DDError("SetHWnd", hr);
#endif
// blt from the affected area from the window back-buffer to the
// screen-relative coordinates of the window paint area
RECT dst_rect = ps.rcPaint;
MapWindowPoints(mWnd, NULL, (LPPOINT)&dst_rect, 2);
hr = glpDDPrimary->Blt(&dst_rect,
gpDDSurf->GetDDSurface(),
&dst_rect,
DDBLT_WAITNOTBUSY,
NULL);
#ifdef DEBUG
if (FAILED(hr))
DDError("SetHWnd", hr);
#endif
#endif
} else if (IsRenderMode(gfxWindowsPlatform::RENDER_IMAGE_STRETCH24) ||
IsRenderMode(gfxWindowsPlatform::RENDER_IMAGE_STRETCH32))
{
gfxIntSize surfaceSize = targetSurfaceImage->GetSize();
// Just blit this directly
BITMAPINFOHEADER bi;
memset(&bi, 0, sizeof(BITMAPINFOHEADER));
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = surfaceSize.width;
bi.biHeight = - surfaceSize.height;
bi.biPlanes = 1;
bi.biBitCount = 32;
bi.biCompression = BI_RGB;
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
// alpha byte. 24bpp DIBs also have scanlines that are 4-byte
// aligned though, so that must be taken into account.
int srcstride = surfaceSize.width*4;
int dststride = surfaceSize.width*3;
dststride = (dststride + 3) & ~3;
// Convert in place
for (int j = 0; j < surfaceSize.height; ++j) {
unsigned int *src = (unsigned int*) (targetSurfaceImage->Data() + j*srcstride);
unsigned int *dst = (unsigned int*) (targetSurfaceImage->Data() + j*dststride);
// go 4 pixels at a time, since each 4 pixels
// turns into 3 DWORDs when converted into BGR:
// BGRx BGRx BGRx BGRx -> BGRB GRBG RBGR
//
// However, since we're dealing with little-endian ints, this is actually:
// xRGB xrgb xRGB xrgb -> bRGB GBrg rgbR
int width_left = surfaceSize.width;
while (width_left >= 4) {
unsigned int a = *src++;
unsigned int b = *src++;
unsigned int c = *src++;
unsigned int d = *src++;
*dst++ = (a & 0x00ffffff) | (b << 24);
*dst++ = ((b & 0x00ffff00) >> 8) | (c << 16);
*dst++ = ((c & 0x00ff0000) >> 16) | (d << 8);
width_left -= 4;
}
// then finish up whatever number of pixels are left,
// using bytes.
unsigned char *bsrc = (unsigned char*) src;
unsigned char *bdst = (unsigned char*) dst;
switch (width_left) {
case 3:
*bdst++ = *bsrc++;
*bdst++ = *bsrc++;
*bdst++ = *bsrc++;
bsrc++;
case 2:
*bdst++ = *bsrc++;
*bdst++ = *bsrc++;
*bdst++ = *bsrc++;
bsrc++;
case 1:
*bdst++ = *bsrc++;
*bdst++ = *bsrc++;
*bdst++ = *bsrc++;
bsrc++;
case 0:
break;
}
}
bi.biBitCount = 24;
}
StretchDIBits(hDC,
ps.rcPaint.left, ps.rcPaint.top,
surfaceSize.width, surfaceSize.height,
0, 0,
surfaceSize.width, surfaceSize.height,
targetSurfaceImage->Data(),
(BITMAPINFO*) &bi,
DIB_RGB_COLORS,
SRCCOPY);
}
}
}
break;
case LayerManager::LAYERS_OPENGL:
static_cast<mozilla::layers::LayerManagerOGL*>(GetLayerManager())->
SetClippingRegion(event.region);
result = DispatchWindowEvent(&event, eventStatus);
break;
default:
NS_ERROR("Unknown layers backend used!");
break;
}
}

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

@ -50,6 +50,7 @@
#include "nsIPrefService.h"
#include "nsIPrefBranch2.h"
#include "BasicLayers.h"
#include "LayerManagerOGL.h"
#ifdef DEBUG
#include "nsIObserver.h"
@ -101,6 +102,7 @@ nsBaseWidget::nsBaseWidget()
, mWindowType(eWindowType_child)
, mBorderStyle(eBorderStyle_none)
, mOnDestroyCalled(PR_FALSE)
, mUseAcceleratedRendering(PR_FALSE)
, mBounds(0,0,0,0)
, mOriginalBounds(nsnull)
, mClipRectCount(0)
@ -639,6 +641,8 @@ nsBaseWidget::AutoLayerManagerSetup::AutoLayerManagerSetup(
BasicLayerManager* manager =
static_cast<BasicLayerManager*>(mWidget->GetLayerManager());
if (manager) {
NS_ASSERTION(manager->GetBackendType() == LayerManager::LAYERS_BASIC,
"AutoLayerManagerSetup instantiated for non-basic layer backend!");
manager->SetDefaultTarget(aTarget);
}
}
@ -648,6 +652,8 @@ nsBaseWidget::AutoLayerManagerSetup::~AutoLayerManagerSetup()
BasicLayerManager* manager =
static_cast<BasicLayerManager*>(mWidget->GetLayerManager());
if (manager) {
NS_ASSERTION(manager->GetBackendType() == LayerManager::LAYERS_BASIC,
"AutoLayerManagerSetup instantiated for non-basic layer backend!");
manager->SetDefaultTarget(nsnull);
}
}
@ -655,7 +661,23 @@ nsBaseWidget::AutoLayerManagerSetup::~AutoLayerManagerSetup()
LayerManager* nsBaseWidget::GetLayerManager()
{
if (!mLayerManager) {
mLayerManager = new BasicLayerManager(nsnull);
if (mUseAcceleratedRendering) {
nsRefPtr<LayerManagerOGL> layerManager =
new mozilla::layers::LayerManagerOGL(this);
/**
* XXX - On several OSes initialization is expected to fail for now.
* If we'd get a none-basic layer manager they'd crash. This is ok though
* since on those platforms it will fail. Anyone implementing new
* platforms on LayerManagerOGL should ensure their widget is able to
* deal with it though!
*/
if (layerManager->Initialize()) {
mLayerManager = layerManager;
}
}
if (!mLayerManager) {
mLayerManager = new BasicLayerManager(nsnull);
}
}
return mLayerManager;
}
@ -812,6 +834,23 @@ nsBaseWidget::ShowsResizeIndicator(nsIntRect* aResizerRect)
return PR_FALSE;
}
NS_IMETHODIMP
nsBaseWidget::SetAcceleratedRendering(PRBool aEnabled)
{
if (mUseAcceleratedRendering == aEnabled) {
return NS_OK;
}
mUseAcceleratedRendering = aEnabled;
mLayerManager = NULL;
return NS_OK;
}
PRBool
nsBaseWidget::GetAcceleratedRendering()
{
return mUseAcceleratedRendering;
}
NS_IMETHODIMP
nsBaseWidget::OverrideSystemMouseScrollSpeed(PRInt32 aOriginalDelta,
PRBool aIsHorizontal,

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

@ -135,6 +135,8 @@ public:
NS_IMETHOD SetIMEEnabled(PRUint32 aState) { return NS_ERROR_NOT_IMPLEMENTED; }
NS_IMETHOD GetIMEEnabled(PRUint32* aState) { return NS_ERROR_NOT_IMPLEMENTED; }
NS_IMETHOD CancelIMEComposition() { return NS_OK; }
NS_IMETHOD SetAcceleratedRendering(PRBool aEnabled);
virtual PRBool GetAcceleratedRendering();
NS_IMETHOD GetToggledKeyState(PRUint32 aKeyCode, PRBool* aLEDState) { return NS_ERROR_NOT_IMPLEMENTED; }
NS_IMETHOD OnIMEFocusChange(PRBool aFocus) { return NS_ERROR_NOT_IMPLEMENTED; }
NS_IMETHOD OnIMETextChange(PRUint32 aStart, PRUint32 aOldEnd, PRUint32 aNewEnd) { return NS_ERROR_NOT_IMPLEMENTED; }
@ -203,6 +205,7 @@ protected:
nsWindowType mWindowType;
nsBorderStyle mBorderStyle;
PRPackedBool mOnDestroyCalled;
PRPackedBool mUseAcceleratedRendering;
nsIntRect mBounds;
nsIntRect* mOriginalBounds;
// When this pointer is null, the widget is not clipped