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

--HG--
extra : rebase_source : d42def8318eb068571f0a5db515593d7f99a56c0
This commit is contained in:
Oleg Romashin 2010-05-11 13:31:56 -04:00
parent 9cbb1c5d7b
commit fef66108af
3 changed files with 57 additions and 89 deletions

View File

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

View File

@ -40,6 +40,7 @@
#include <QX11Info>
#include <QApplication>
#include <QDesktopWidget>
#include <QPaintEngine>
#include "gfxQtPlatform.h"
@ -78,8 +79,11 @@
#include "nsIPrefBranch.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;
static cairo_user_data_key_t cairo_qt_pixmap_key;
static void do_qt_pixmap_unref (void *data)
@ -140,11 +144,16 @@ gfxQtPlatform::gfxQtPlatform()
mRenderMode = RENDER_QPAINTER;
break;
case 1:
mRenderMode = RENDER_SHARED_IMAGE;
mRenderMode = RENDER_BUFFERED;
break;
default:
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()
@ -190,7 +199,8 @@ gfxQtPlatform::CreateOffscreenSurface(const gfxIntSize& size,
return newSurface.forget();
}
if (mRenderMode == RENDER_SHARED_IMAGE) {
if (mRenderMode == RENDER_BUFFERED &&
sDefaultQtPaintEngineType != QPaintEngine::X11) {
newSurface = new gfxImageSurface(size, imageFormat);
return newSurface.forget();
}

View File

@ -94,7 +94,7 @@
#include "gfxXlibSurface.h"
#include "gfxQPainterSurface.h"
#include "gfxContext.h"
#include "gfxSharedImageSurface.h"
#include "gfxImageSurface.h"
#include "nsIDOMSimpleGestureEvent.h" //Gesture support
@ -105,9 +105,8 @@ PRBool gDisableNativeTheme = PR_FALSE;
static QPixmap *gBufferPixmap = nsnull;
static int gBufferPixmapUsageCount = 0;
// Buffered shared image + pixmap
static gfxSharedImageSurface *gBufferImage = nsnull;
static gfxSharedImageSurface *gBufferImageTemp = nsnull;
// Buffered image + pixmap
static gfxImageSurface *gBufferImage = nsnull;
static gfxIntSize gBufferMaxSize(0, 0);
/* For PrepareNativeWidget */
@ -217,15 +216,12 @@ _depth_to_gfximage_format(PRInt32 aDepth)
}
static inline QImage::Format
_depth_to_qformat(PRInt32 aDepth)
_gfximage_to_qformat(gfxASurface::gfxImageFormat aFormat)
{
switch (aDepth) {
case 32:
switch (aFormat) {
case gfxASurface::ImageFormatARGB32:
case gfxASurface::ImageFormatRGB24:
return QImage::Format_ARGB32;
case 24:
return QImage::Format_RGB32;
case 16:
return QImage::Format_RGB16;
default:
return QImage::Format_Invalid;
}
@ -235,10 +231,8 @@ static void
FreeOffScreenBuffers(void)
{
delete gBufferImage;
delete gBufferImageTemp;
delete gBufferPixmap;
gBufferImage = nsnull;
gBufferImageTemp = nsnull;
gBufferPixmap = nsnull;
}
@ -256,50 +250,22 @@ UpdateOffScreenBuffers(QPaintEngine::Type aType, int aDepth, QSize aSize)
gBufferMaxSize.width = PR_MAX(gBufferMaxSize.width, size.width);
gBufferMaxSize.height = PR_MAX(gBufferMaxSize.height, size.height);
// For Qt X11 engine better to use QPixmap as offscreen buffer
if (aType == QPaintEngine::X11) {
gBufferPixmap = new QPixmap(gBufferMaxSize.width, gBufferMaxSize.height);
if (!gBufferPixmap)
return false;
return true;
}
// Check if system depth has related gfxImage format
gfxASurface::gfxImageFormat format =
_depth_to_gfximage_format(aDepth);
PRBool depthFormatInCompatible = (format == gfxASurface::ImageFormatUnknown);
// In raster backend we don't care about incompatible mode, and will paint in
// default RGB24 format... Raster engine will convert it to target color depth
if (depthFormatInCompatible && aType == QPaintEngine::Raster) {
depthFormatInCompatible = PR_FALSE;
// Use fallback RGB24 format, Qt will do conversion for us
if (format == gfxASurface::ImageFormatUnknown)
format = gfxASurface::ImageFormatRGB24;
}
gBufferImage = new gfxSharedImageSurface();
if (!gBufferImage) {
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;
}
// For non-X11 qt paint engine we use image surface as offscreen buffer
gBufferImage = new gfxImageSurface(gBufferMaxSize, format);
return true;
}
@ -998,6 +964,20 @@ nsWindow::GetAttention(PRInt32 aCycleCount)
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
nsWindow::DoPaint(QPainter* aPainter, const QStyleOptionGraphicsItem* aOption)
{
@ -1025,15 +1005,20 @@ nsWindow::DoPaint(QPainter* aPainter, const QStyleOptionGraphicsItem* aOption)
gfxQtPlatform::RenderMode renderMode = gfxQtPlatform::GetPlatform()->GetRenderMode();
QPaintEngine::Type paintEngineType = aPainter->paintEngine()->type();
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())))
return nsEventStatus_eIgnore;
nsRefPtr<gfxASurface> targetSurface = nsnull;
if (renderMode == gfxQtPlatform::RENDER_SHARED_IMAGE) {
targetSurface = gBufferImageTemp ? gBufferImageTemp->getASurface()
: gBufferImage->getASurface();
if (paintEngineType == QPaintEngine::X11) {
targetSurface = GetSurfaceForQPixmap(gBufferPixmap);
}
else if (paintEngineType == QPaintEngine::Raster) {
NS_ADDREF(targetSurface = gBufferImage);
}
} else if (renderMode == gfxQtPlatform::RENDER_QPAINTER) {
targetSurface = new gfxQPainterSurface(aPainter);
}
@ -1044,7 +1029,7 @@ nsWindow::DoPaint(QPainter* aPainter, const QStyleOptionGraphicsItem* aOption)
nsRefPtr<gfxContext> ctx = new gfxContext(targetSurface);
// 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()));
nsPaintEvent event(PR_TRUE, NS_PAINT, this);
@ -1070,36 +1055,9 @@ nsWindow::DoPaint(QPainter* aPainter, const QStyleOptionGraphicsItem* aOption)
LOGDRAW(("[%p] draw done\n", this));
// Handle not direct painting mode
if (renderMode == gfxQtPlatform::RENDER_SHARED_IMAGE) {
// Handle buffered painting mode
if (renderMode == gfxQtPlatform::RENDER_BUFFERED) {
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
aPainter->drawPixmap(QPoint(rect.x, rect.y), *gBufferPixmap,
QRect(0, 0, rect.width, rect.height));
@ -1110,7 +1068,7 @@ nsWindow::DoPaint(QPainter* aPainter, const QStyleOptionGraphicsItem* aOption)
gBufferImage->Width(),
gBufferImage->Height(),
gBufferImage->Stride(),
_depth_to_qformat(gBufferImage->Depth()));
_gfximage_to_qformat(gBufferImage->Format()));
aPainter->drawImage(QPoint(rect.x, rect.y), img,
QRect(0, 0, rect.width, rect.height));
}