Bug 561772 - Simplify Qt rendering modes and remove dependency from gfxSharedImageSurface. r=joe.
This commit is contained in:
@@ -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
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user