Bug 561772 - Simplify Qt rendering modes and remove dependency from gfxSharedImageSurface. r=joe.

This commit is contained in:
Oleg Romashin
2010-05-11 13:31:56 -04:00
parent 356f0c1782
commit 065bfe6daf
3 changed files with 57 additions and 89 deletions

View File

@@ -58,8 +58,8 @@ public:
enum RenderMode { enum RenderMode {
/* Use QPainter surfaces */ /* Use QPainter surfaces */
RENDER_QPAINTER = 0, RENDER_QPAINTER = 0,
/* Use image surfaces and XShmPutImage to QPixmap */ /* Use offscreen buffer for rendering with image or xlib gfx backend */
RENDER_SHARED_IMAGE, RENDER_BUFFERED,
/* max */ /* max */
RENDER_MODE_MAX RENDER_MODE_MAX
}; };

View File

@@ -40,6 +40,7 @@
#include <QX11Info> #include <QX11Info>
#include <QApplication> #include <QApplication>
#include <QDesktopWidget> #include <QDesktopWidget>
#include <QPaintEngine>
#include "gfxQtPlatform.h" #include "gfxQtPlatform.h"
@@ -78,8 +79,11 @@
#include "nsIPrefBranch.h" #include "nsIPrefBranch.h"
#include "nsIPrefService.h" #include "nsIPrefService.h"
#define DEFAULT_RENDER_MODE RENDER_SHARED_IMAGE // Because the QPainter backend has some problems with glyphs rendering
// it is better to use image or xlib cairo backends by default
#define DEFAULT_RENDER_MODE RENDER_BUFFERED
static QPaintEngine::Type sDefaultQtPaintEngineType = QPaintEngine::X11;
gfxFontconfigUtils *gfxQtPlatform::sFontconfigUtils = nsnull; gfxFontconfigUtils *gfxQtPlatform::sFontconfigUtils = nsnull;
static cairo_user_data_key_t cairo_qt_pixmap_key; static cairo_user_data_key_t cairo_qt_pixmap_key;
static void do_qt_pixmap_unref (void *data) static void do_qt_pixmap_unref (void *data)
@@ -140,11 +144,16 @@ gfxQtPlatform::gfxQtPlatform()
mRenderMode = RENDER_QPAINTER; mRenderMode = RENDER_QPAINTER;
break; break;
case 1: case 1:
mRenderMode = RENDER_SHARED_IMAGE; mRenderMode = RENDER_BUFFERED;
break; break;
default: default:
mRenderMode = RENDER_QPAINTER; mRenderMode = RENDER_QPAINTER;
} }
// Qt doesn't provide a public API to detect the graphicssystem type. We hack
// around this by checking what type of graphicssystem a test QPixmap uses.
QPixmap pixmap(1, 1);
sDefaultQtPaintEngineType = pixmap.paintEngine()->type();
} }
gfxQtPlatform::~gfxQtPlatform() gfxQtPlatform::~gfxQtPlatform()
@@ -190,7 +199,8 @@ gfxQtPlatform::CreateOffscreenSurface(const gfxIntSize& size,
return newSurface.forget(); return newSurface.forget();
} }
if (mRenderMode == RENDER_SHARED_IMAGE) { if (mRenderMode == RENDER_BUFFERED &&
sDefaultQtPaintEngineType != QPaintEngine::X11) {
newSurface = new gfxImageSurface(size, imageFormat); newSurface = new gfxImageSurface(size, imageFormat);
return newSurface.forget(); return newSurface.forget();
} }

View File

@@ -94,7 +94,7 @@
#include "gfxXlibSurface.h" #include "gfxXlibSurface.h"
#include "gfxQPainterSurface.h" #include "gfxQPainterSurface.h"
#include "gfxContext.h" #include "gfxContext.h"
#include "gfxSharedImageSurface.h" #include "gfxImageSurface.h"
#include "nsIDOMSimpleGestureEvent.h" //Gesture support #include "nsIDOMSimpleGestureEvent.h" //Gesture support
@@ -105,9 +105,8 @@ PRBool gDisableNativeTheme = PR_FALSE;
static QPixmap *gBufferPixmap = nsnull; static QPixmap *gBufferPixmap = nsnull;
static int gBufferPixmapUsageCount = 0; static int gBufferPixmapUsageCount = 0;
// Buffered shared image + pixmap // Buffered image + pixmap
static gfxSharedImageSurface *gBufferImage = nsnull; static gfxImageSurface *gBufferImage = nsnull;
static gfxSharedImageSurface *gBufferImageTemp = nsnull;
static gfxIntSize gBufferMaxSize(0, 0); static gfxIntSize gBufferMaxSize(0, 0);
/* For PrepareNativeWidget */ /* For PrepareNativeWidget */
@@ -217,15 +216,12 @@ _depth_to_gfximage_format(PRInt32 aDepth)
} }
static inline QImage::Format static inline QImage::Format
_depth_to_qformat(PRInt32 aDepth) _gfximage_to_qformat(gfxASurface::gfxImageFormat aFormat)
{ {
switch (aDepth) { switch (aFormat) {
case 32: case gfxASurface::ImageFormatARGB32:
case gfxASurface::ImageFormatRGB24:
return QImage::Format_ARGB32; return QImage::Format_ARGB32;
case 24:
return QImage::Format_RGB32;
case 16:
return QImage::Format_RGB16;
default: default:
return QImage::Format_Invalid; return QImage::Format_Invalid;
} }
@@ -235,10 +231,8 @@ static void
FreeOffScreenBuffers(void) FreeOffScreenBuffers(void)
{ {
delete gBufferImage; delete gBufferImage;
delete gBufferImageTemp;
delete gBufferPixmap; delete gBufferPixmap;
gBufferImage = nsnull; gBufferImage = nsnull;
gBufferImageTemp = nsnull;
gBufferPixmap = nsnull; gBufferPixmap = nsnull;
} }
@@ -256,50 +250,22 @@ UpdateOffScreenBuffers(QPaintEngine::Type aType, int aDepth, QSize aSize)
gBufferMaxSize.width = PR_MAX(gBufferMaxSize.width, size.width); gBufferMaxSize.width = PR_MAX(gBufferMaxSize.width, size.width);
gBufferMaxSize.height = PR_MAX(gBufferMaxSize.height, size.height); gBufferMaxSize.height = PR_MAX(gBufferMaxSize.height, size.height);
// For Qt X11 engine better to use QPixmap as offscreen buffer
if (aType == QPaintEngine::X11) { if (aType == QPaintEngine::X11) {
gBufferPixmap = new QPixmap(gBufferMaxSize.width, gBufferMaxSize.height); gBufferPixmap = new QPixmap(gBufferMaxSize.width, gBufferMaxSize.height);
if (!gBufferPixmap) return true;
return false;
} }
// Check if system depth has related gfxImage format // Check if system depth has related gfxImage format
gfxASurface::gfxImageFormat format = gfxASurface::gfxImageFormat format =
_depth_to_gfximage_format(aDepth); _depth_to_gfximage_format(aDepth);
PRBool depthFormatInCompatible = (format == gfxASurface::ImageFormatUnknown);
// In raster backend we don't care about incompatible mode, and will paint in // Use fallback RGB24 format, Qt will do conversion for us
// default RGB24 format... Raster engine will convert it to target color depth if (format == gfxASurface::ImageFormatUnknown)
if (depthFormatInCompatible && aType == QPaintEngine::Raster) {
depthFormatInCompatible = PR_FALSE;
format = gfxASurface::ImageFormatRGB24; format = gfxASurface::ImageFormatRGB24;
}
gBufferImage = new gfxSharedImageSurface(); // For non-X11 qt paint engine we use image surface as offscreen buffer
if (!gBufferImage) { gBufferImage = new gfxImageSurface(gBufferMaxSize, format);
FreeOffScreenBuffers();
return false;
}
if (!gBufferImage->Init(gBufferMaxSize, format, aDepth)) {
FreeOffScreenBuffers();
return false;
}
// gfxImageSurface does not support system color depth format
// we have to paint it with temp surface and color conversion
if (!depthFormatInCompatible)
return true;
gBufferImageTemp = new gfxSharedImageSurface();
if (!gBufferImageTemp) {
FreeOffScreenBuffers();
return false;
}
if (!gBufferImageTemp->Init(gBufferMaxSize, gfxASurface::ImageFormatRGB24)) {
FreeOffScreenBuffers();
return false;
}
return true; return true;
} }
@@ -998,6 +964,20 @@ nsWindow::GetAttention(PRInt32 aCycleCount)
return NS_ERROR_NOT_IMPLEMENTED; return NS_ERROR_NOT_IMPLEMENTED;
} }
#ifdef MOZ_X11
static already_AddRefed<gfxASurface>
GetSurfaceForQPixmap(QPixmap* aDrawable)
{
gfxASurface* result =
new gfxXlibSurface(aDrawable->x11Info().display(),
aDrawable->handle(),
(Visual*)aDrawable->x11Info().visual(),
gfxIntSize(aDrawable->size().width(), aDrawable->size().height()));
NS_IF_ADDREF(result);
return result;
}
#endif
nsEventStatus nsEventStatus
nsWindow::DoPaint(QPainter* aPainter, const QStyleOptionGraphicsItem* aOption) nsWindow::DoPaint(QPainter* aPainter, const QStyleOptionGraphicsItem* aOption)
{ {
@@ -1025,15 +1005,20 @@ nsWindow::DoPaint(QPainter* aPainter, const QStyleOptionGraphicsItem* aOption)
gfxQtPlatform::RenderMode renderMode = gfxQtPlatform::GetPlatform()->GetRenderMode(); gfxQtPlatform::RenderMode renderMode = gfxQtPlatform::GetPlatform()->GetRenderMode();
QPaintEngine::Type paintEngineType = aPainter->paintEngine()->type(); QPaintEngine::Type paintEngineType = aPainter->paintEngine()->type();
int depth = aPainter->device()->depth(); int depth = aPainter->device()->depth();
// Prepare offscreen buffers if RenderMode Xlib or Image
if (renderMode == gfxQtPlatform::RENDER_SHARED_IMAGE) nsRefPtr<gfxASurface> targetSurface = nsnull;
if (renderMode == gfxQtPlatform::RENDER_BUFFERED) {
// Prepare offscreen buffers iamge or xlib, depends from paintEngineType
if (!UpdateOffScreenBuffers(paintEngineType, depth, QSize(r.width(), r.height()))) if (!UpdateOffScreenBuffers(paintEngineType, depth, QSize(r.width(), r.height())))
return nsEventStatus_eIgnore; return nsEventStatus_eIgnore;
nsRefPtr<gfxASurface> targetSurface = nsnull; if (paintEngineType == QPaintEngine::X11) {
if (renderMode == gfxQtPlatform::RENDER_SHARED_IMAGE) { targetSurface = GetSurfaceForQPixmap(gBufferPixmap);
targetSurface = gBufferImageTemp ? gBufferImageTemp->getASurface() }
: gBufferImage->getASurface(); else if (paintEngineType == QPaintEngine::Raster) {
NS_ADDREF(targetSurface = gBufferImage);
}
} else if (renderMode == gfxQtPlatform::RENDER_QPAINTER) { } else if (renderMode == gfxQtPlatform::RENDER_QPAINTER) {
targetSurface = new gfxQPainterSurface(aPainter); targetSurface = new gfxQPainterSurface(aPainter);
} }
@@ -1044,7 +1029,7 @@ nsWindow::DoPaint(QPainter* aPainter, const QStyleOptionGraphicsItem* aOption)
nsRefPtr<gfxContext> ctx = new gfxContext(targetSurface); nsRefPtr<gfxContext> ctx = new gfxContext(targetSurface);
// We will paint to 0, 0 position in offscrenn buffer // We will paint to 0, 0 position in offscrenn buffer
if (renderMode == gfxQtPlatform::RENDER_SHARED_IMAGE) if (renderMode == gfxQtPlatform::RENDER_BUFFERED)
ctx->Translate(gfxPoint(-r.x(), -r.y())); ctx->Translate(gfxPoint(-r.x(), -r.y()));
nsPaintEvent event(PR_TRUE, NS_PAINT, this); nsPaintEvent event(PR_TRUE, NS_PAINT, this);
@@ -1070,36 +1055,9 @@ nsWindow::DoPaint(QPainter* aPainter, const QStyleOptionGraphicsItem* aOption)
LOGDRAW(("[%p] draw done\n", this)); LOGDRAW(("[%p] draw done\n", this));
// Handle not direct painting mode // Handle buffered painting mode
if (renderMode == gfxQtPlatform::RENDER_SHARED_IMAGE) { if (renderMode == gfxQtPlatform::RENDER_BUFFERED) {
if (paintEngineType == QPaintEngine::X11) { if (paintEngineType == QPaintEngine::X11) {
// When Qt is working in X11 mode, then we should put our shared image to X
if (gBufferImageTemp && gBufferImage) {
// If gBufferImageTemp no null, then we have incompatible QPaintDevice color format
// Need to convert first
QImage src_img(gBufferImageTemp->Data(),
gBufferImageTemp->Width(),
gBufferImageTemp->Height(),
gBufferImageTemp->Stride(),
_depth_to_qformat(gBufferImageTemp->Depth()));
QImage dst_img(gBufferImage->Data(),
gBufferImage->Width(),
gBufferImage->Height(),
gBufferImage->Stride(),
_depth_to_qformat(gBufferImage->Depth()));
QPainter p(&dst_img);
p.drawImage(QPoint(0, 0), src_img, QRect(0, 0, rect.width, rect.height));
}
Display *disp = gBufferPixmap->x11Info().display();
XGCValues gcv;
gcv.graphics_exposures = False;
GC gc = XCreateGC(disp, gBufferPixmap->handle(), GCGraphicsExposures, &gcv);
XShmPutImage(disp, gBufferPixmap->handle(), gc, gBufferImage->image(),
0, 0, 0, 0, rect.width, rect.height,
False);
XSync(disp, False);
XFreeGC(disp, gc);
// Paint offscreen pixmap to QPainter // Paint offscreen pixmap to QPainter
aPainter->drawPixmap(QPoint(rect.x, rect.y), *gBufferPixmap, aPainter->drawPixmap(QPoint(rect.x, rect.y), *gBufferPixmap,
QRect(0, 0, rect.width, rect.height)); QRect(0, 0, rect.width, rect.height));
@@ -1110,7 +1068,7 @@ nsWindow::DoPaint(QPainter* aPainter, const QStyleOptionGraphicsItem* aOption)
gBufferImage->Width(), gBufferImage->Width(),
gBufferImage->Height(), gBufferImage->Height(),
gBufferImage->Stride(), gBufferImage->Stride(),
_depth_to_qformat(gBufferImage->Depth())); _gfximage_to_qformat(gBufferImage->Format()));
aPainter->drawImage(QPoint(rect.x, rect.y), img, aPainter->drawImage(QPoint(rect.x, rect.y), img,
QRect(0, 0, rect.width, rect.height)); QRect(0, 0, rect.width, rect.height));
} }