Bug 544250 - Implement different rendering backends for Qt mozilla port. r=jmuizelaar.

This commit is contained in:
Oleg Romashin 2010-02-19 19:46:54 -08:00
Родитель b3ac46a92d
Коммит 4b8146c17f
11 изменённых файлов: 772 добавлений и 19 удалений

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

@ -32,6 +32,10 @@ EXPORTS = gfxASurface.h \
gfxUserFontSet.h \
$(NULL)
EXPORTS += \
gfxSharedImageSurface.h \
$(NULL)
EXPORTS += gfxFontTest.h
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)

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

@ -51,6 +51,18 @@ class FontEntry;
class THEBES_API gfxQtPlatform : public gfxPlatform {
public:
enum RenderMode {
/* Use QPainter surfaces */
RENDER_QPAINTER = 0,
/* Use Xlib surface to render and wrap as QPixmap */
RENDER_XLIB,
/* Use image surfaces and XShmPutImage to QPixmap */
RENDER_SHARED_IMAGE,
/* max */
RENDER_MODE_MAX
};
gfxQtPlatform();
virtual ~gfxQtPlatform();
@ -87,6 +99,9 @@ public:
FT_Library GetFTLibrary();
RenderMode GetRenderMode() { return mRenderMode; }
void SetRenderMode(RenderMode rmode) { mRenderMode = rmode; }
protected:
static gfxFontconfigUtils *sFontconfigUtils;
@ -96,6 +111,7 @@ private:
// TODO: unify this with mPrefFonts (NB: holds families, not fonts) in gfxPlatformFontList
nsDataHashtable<nsCStringHashKey, nsTArray<nsRefPtr<gfxFontEntry> > > mPrefFonts;
RenderMode mRenderMode;
};
#endif /* GFX_PLATFORM_QT_H */

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

@ -0,0 +1,148 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Nokia Corporation code.
*
* The Initial Developer of the Original Code is Nokia Corporation.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Oleg Romashin <romaxa@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef GFX_SHARED_IMAGESURFACE_H
#define GFX_SHARED_IMAGESURFACE_H
#ifdef MOZ_X11
#ifdef HAVE_XSHM
#include "gfxASurface.h"
#include "gfxImageSurface.h"
#include "gfxPoint.h"
#include <stdlib.h>
#include <string.h>
#ifdef MOZ_WIDGET_QT
#include <QX11Info>
#endif
#ifdef MOZ_WIDGET_GTK2
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#endif
#ifdef MOZ_X11
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/XShm.h>
#endif
#include <sys/ipc.h>
#include <sys/shm.h>
class THEBES_API gfxSharedImageSurface : public gfxASurface {
public:
gfxSharedImageSurface();
~gfxSharedImageSurface();
// ImageSurface methods
gfxImageFormat Format() const { return mFormat; }
const gfxIntSize& GetSize() const { return mSize; }
int Width() const { return mSize.width; }
int Height() const { return mSize.height; }
/**
* Distance in bytes between the start of a line and the start of the
* next line.
*/
int Stride() const { return mStride; }
/**
* Returns a pointer for the image data. Users of this function can
* write to it, but must not attempt to free the buffer.
*/
unsigned char* Data() const { return mData; } // delete this data under us and die.
/**
* Returns the total size of the image data.
*/
int GetDataSize() const { return mStride*mSize.height; }
/**
* Returns a pointer for the X-image structure.
*/
XImage *image() const { return mXShmImage; }
/**
* Returns a gfxImageSurface as gfxASurface.
*/
already_AddRefed<gfxASurface> getASurface(void);
/**
* Construct an shared image surface and XImage
* @param aSize The size of the buffer
* @param aFormat Format of the data
* @see gfxImageFormat
* @param aShmId Shared Memory ID of data created outside,
* if not specified, then class will allocate own shared memory
* @display aDisplay display used for X-Image creation
* if not specified, then used system default
*
*/
bool Init(const gfxIntSize& aSize,
gfxImageFormat aFormat = ImageFormatUnknown,
int aShmId = -1,
Display *aDisplay = NULL);
private:
bool CreateInternal(int aShmid);
long ComputeStride() const;
inline bool ComputeDepth();
inline bool ComputeFormat();
unsigned int mDepth;
int mShmId;
gfxIntSize mSize;
bool mOwnsData;
unsigned char *mData;
gfxImageFormat mFormat;
long mStride;
Display *mDisp;
XShmSegmentInfo mShmInfo;
XImage *mXShmImage;
};
#endif /* HAVE_XSHM */
#endif /* MOZ_X11 */
#endif /* GFX_SHARED_IMAGESURFACE_H */

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

@ -34,6 +34,10 @@ CPPSRCS = \
gfxUserFontSet.cpp \
$(NULL)
CPPSRCS += \
gfxSharedImageSurface.cpp \
$(NULL)
EXTRA_DSO_LDOPTS += \
$(MOZ_CAIRO_LIBS) \
$(MOZ_UNICHARUTIL_LIBS) \

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

@ -58,12 +58,20 @@
#include "nsMathUtils.h"
#include "nsTArray.h"
#ifdef MOZ_X11
#include "gfxXlibSurface.h"
#endif
#include "qcms.h"
#include <ft2build.h>
#include FT_FREETYPE_H
#include "nsIPrefBranch.h"
#include "nsIPrefService.h"
#define DEFAULT_RENDER_MODE RENDER_SHARED_IMAGE
gfxFontconfigUtils *gfxQtPlatform::sFontconfigUtils = nsnull;
static cairo_user_data_key_t cairo_qt_pixmap_key;
static void do_qt_pixmap_unref (void *data)
@ -99,6 +107,36 @@ gfxQtPlatform::gfxQtPlatform()
gPrefFonts->Init(100);
gCodepointsWithNoFonts = new gfxSparseBitSet();
UpdateFontList();
nsresult rv;
PRInt32 ival;
// 0 - default gfxQPainterSurface
// 1 - gfxXlibSurface
// 2 - gfxImageSurface
nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
if (prefs) {
rv = prefs->GetIntPref("mozilla.widget-qt.render-mode", &ival);
if (NS_FAILED(rv))
ival = DEFAULT_RENDER_MODE;
}
const char *envTypeOverride = getenv("MOZ_QT_RENDER_TYPE");
if (envTypeOverride)
ival = atoi(envTypeOverride);
switch (ival) {
case 0:
mRenderMode = RENDER_QPAINTER;
break;
case 1:
mRenderMode = RENDER_XLIB;
break;
case 2:
mRenderMode = RENDER_SHARED_IMAGE;
break;
default:
mRenderMode = RENDER_QPAINTER;
}
}
gfxQtPlatform::~gfxQtPlatform()
@ -134,8 +172,53 @@ already_AddRefed<gfxASurface>
gfxQtPlatform::CreateOffscreenSurface(const gfxIntSize& size,
gfxASurface::gfxImageFormat imageFormat)
{
nsRefPtr<gfxASurface> newSurface =
new gfxQPainterSurface (size, gfxASurface::ContentFromFormat(imageFormat));
nsRefPtr<gfxASurface> newSurface = nsnull;
if (mRenderMode == RENDER_QPAINTER) {
newSurface = new gfxQPainterSurface(size, gfxASurface::ContentFromFormat(imageFormat));
return newSurface.forget();
}
if (mRenderMode == RENDER_SHARED_IMAGE) {
newSurface = new gfxImageSurface(size, imageFormat);
return newSurface.forget();
}
#ifdef MOZ_X11
int xrenderFormatID = -1;
switch (imageFormat) {
case gfxASurface::ImageFormatARGB32:
xrenderFormatID = PictStandardARGB32;
break;
case gfxASurface::ImageFormatRGB24:
xrenderFormatID = PictStandardRGB24;
break;
case gfxASurface::ImageFormatA8:
xrenderFormatID = PictStandardA8;
break;
case gfxASurface::ImageFormatA1:
xrenderFormatID = PictStandardA1;
break;
default:
return nsnull;
}
// XXX we really need a different interface here, something that passes
// in more context, including the display and/or target surface type that
// we should try to match
XRenderPictFormat* xrenderFormat =
XRenderFindStandardFormat(QX11Info().display(), xrenderFormatID);
newSurface = new gfxXlibSurface((Display*)QX11Info().display(),
xrenderFormat,
size);
#endif
if (newSurface) {
gfxContext ctx(newSurface);
ctx.SetOperator(gfxContext::OPERATOR_CLEAR);
ctx.Paint();
}
return newSurface.forget();
}

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

@ -0,0 +1,240 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Nokia Corporation code.
*
* The Initial Developer of the Original Code is Nokia Corporation.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Oleg Romashin <romaxa@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "gfxSharedImageSurface.h"
#include <stdio.h>
#ifdef MOZ_X11
#ifdef HAVE_XSHM
gfxSharedImageSurface::gfxSharedImageSurface()
: mDepth(0),
mShmId(0),
mOwnsData(true),
mData(NULL),
mStride(0),
mXShmImage(NULL)
{
memset(&mShmInfo, 0, sizeof(XShmSegmentInfo));
}
gfxSharedImageSurface::~gfxSharedImageSurface()
{
// Finish all pending XServer operations
if (mDisp) {
XSync(mDisp, False);
XShmDetach(mDisp, &mShmInfo);
}
if (mData)
shmdt(mData);
if (mXShmImage)
XDestroyImage(mXShmImage);
}
already_AddRefed<gfxASurface>
gfxSharedImageSurface::getASurface(void)
{
NS_ENSURE_TRUE(mData, NULL);
gfxASurface::gfxImageFormat imageFormat = gfxASurface::ImageFormatRGB24;
if (mDepth == 32)
imageFormat = gfxASurface::ImageFormatARGB32;
gfxASurface* result = new gfxImageSurface(mData, mSize, mStride, imageFormat);
NS_IF_ADDREF(result);
return result;
}
#ifdef MOZ_WIDGET_QT
static unsigned int
getSystemDepth()
{
return QX11Info::appDepth();
}
static Display*
getSystemDisplay()
{
return QX11Info::display();
}
#endif
#ifdef MOZ_WIDGET_GTK2
static unsigned int
getSystemDepth()
{
return gdk_visual_get_system()->depth;
}
static Display*
getSystemDisplay()
{
return GDK_DISPLAY();
}
#endif
bool
gfxSharedImageSurface::Init(const gfxIntSize& aSize,
gfxImageFormat aFormat,
int aShmId,
Display *aDisplay)
{
mSize = aSize;
if (aFormat != ImageFormatUnknown) {
mFormat = aFormat;
if (!ComputeDepth())
return false;
} else {
mDepth = getSystemDepth();
if (!ComputeFormat())
NS_WARNING("Will work with system depth");
}
mDisp = aDisplay ? aDisplay : getSystemDisplay();
if (!mDisp)
return false;
return CreateInternal(aShmId);
}
bool
gfxSharedImageSurface::CreateInternal(int aShmid)
{
memset(&mShmInfo, 0, sizeof(mShmInfo));
mStride = ComputeStride();
if (aShmid != -1) {
mShmId = aShmid;
mOwnsData = false;
} else
mShmId = shmget(IPC_PRIVATE, GetDataSize(), IPC_CREAT | 0777);
if (mShmId == -1)
return false;
void *data = shmat(mShmId, 0, 0);
shmctl(mShmId, IPC_RMID, 0);
if (data == (void *)-1)
return false;
mData = (unsigned char *)data;
mXShmImage = XShmCreateImage(mDisp, NULL,
mDepth, ZPixmap,
NULL, &mShmInfo,
mSize.width,
mSize.height);
if (!mXShmImage)
return false;
mShmInfo.shmid = mShmId;
if (mStride != mXShmImage->bytes_per_line) {
NS_WARNING("XStride and gfxSharedImageSurface calculated stride does not match");
return false;
}
mShmInfo.shmaddr = mXShmImage->data = (char*)data;
mShmInfo.readOnly = False;
if (!XShmAttach(mDisp, &mShmInfo))
return false;
return true;
}
bool
gfxSharedImageSurface::ComputeFormat()
{
if (mDepth == 32)
mFormat = ImageFormatARGB32;
if (mDepth == 24)
mFormat = ImageFormatRGB24;
else {
NS_WARNING("Unknown depth specified to gfxSharedImageSurface!");
mFormat = ImageFormatUnknown;
return false;
}
return true;
}
bool
gfxSharedImageSurface::ComputeDepth()
{
mDepth = 0;
if (mFormat == ImageFormatARGB32)
mDepth = 32;
else if (mFormat == ImageFormatRGB24)
mDepth = 24;
else {
NS_WARNING("Unknown format specified to gfxSharedImageSurface!");
return false;
}
return true;
}
long
gfxSharedImageSurface::ComputeStride() const
{
long stride;
if (mDepth == 16)
stride = mSize.width * 2;
else if (mFormat == ImageFormatARGB32)
stride = mSize.width * 4;
else if (mFormat == ImageFormatRGB24)
stride = mSize.width * 4;
else if (mFormat == ImageFormatA8)
stride = mSize.width;
else if (mFormat == ImageFormatA1) {
stride = (mSize.width + 7) / 8;
} else {
NS_WARNING("Unknown format specified to gfxImageSurface!");
stride = mSize.width * 4;
}
stride = ((stride + 3) / 4) * 4;
return stride;
}
#endif /* HAVE_XSHM */
#endif /* MOZ_X11 */

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

@ -257,7 +257,7 @@ EXTRA_DSO_LDOPTS += -ljprof
endif
ifdef MOZ_ENABLE_QT
EXTRA_DSO_LDOPTS += $(MOZ_QT_LDFLAGS)
EXTRA_DSO_LDOPTS += $(MOZ_QT_LDFLAGS) $(XEXT_LIBS)
endif
include $(topsrcdir)/config/rules.mk

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

@ -104,8 +104,8 @@ endif
include $(topsrcdir)/config/rules.mk
CXXFLAGS += $(MOZ_QT_CFLAGS) $(GLIB_CFLAGS)
CFLAGS += $(MOZ_QT_CFLAGS) $(GLIB_CFLAGS)
CXXFLAGS += $(MOZ_QT_CFLAGS) $(GLIB_CFLAGS) $(MOZ_CAIRO_CFLAGS)
CFLAGS += $(MOZ_QT_CFLAGS) $(GLIB_CFLAGS) $(MOZ_CAIRO_CFLAGS)
DEFINES += -D_IMPL_NS_WIDGET
#DEFINES += -DDEBUG_WIDGETS

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

@ -69,7 +69,11 @@
#include "gfxASurface.h"
#include "gfxContext.h"
#include "gfxQtPlatform.h"
#include "gfxQPainterSurface.h"
#ifdef MOZ_X11
#include "gfxXlibSurface.h"
#endif
#include "nsIRenderingContext.h"
nsNativeThemeQt::nsNativeThemeQt()
@ -93,6 +97,29 @@ static inline QRect qRectInPixels(const nsRect &aRect,
NSAppUnitsToIntPixels(aRect.height, p2a));
}
static inline QImage::Format
_qimage_from_gfximage_format (gfxASurface::gfxImageFormat aFormat)
{
switch (aFormat) {
case gfxASurface::ImageFormatARGB32:
return QImage::Format_ARGB32_Premultiplied;
case gfxASurface::ImageFormatRGB24:
return QImage::Format_RGB32;
case gfxASurface::ImageFormatA8:
return QImage::Format_Indexed8;
case gfxASurface::ImageFormatA1:
#ifdef WORDS_BIGENDIAN
return QImage::Format_Mono;
#else
return QImage::Format_MonoLSB;
#endif
default:
return QImage::Format_Invalid;
}
return QImage::Format_Mono;
}
NS_IMETHODIMP
nsNativeThemeQt::DrawWidgetBackground(nsIRenderingContext* aContext,
nsIFrame* aFrame,
@ -103,19 +130,56 @@ nsNativeThemeQt::DrawWidgetBackground(nsIRenderingContext* aContext,
gfxContext* context = aContext->ThebesContext();
nsRefPtr<gfxASurface> surface = context->CurrentSurface();
if (surface->GetType() == gfxASurface::SurfaceTypeQPainter) {
gfxQPainterSurface* qSurface = (gfxQPainterSurface*) (surface.get());
QPainter *painter = qSurface->GetQPainter();
NS_ASSERTION(painter, "Where'd my QPainter go?");
if (!painter)
return NS_ERROR_FAILURE;
return DrawWidgetBackground(painter, aContext,
aFrame, aWidgetType,
aRect, aClipRect);
}
else if (surface->GetType() == gfxASurface::SurfaceTypeImage) {
gfxImageSurface* qSurface = (gfxImageSurface*) (surface.get());
QImage tempQImage(qSurface->Data(),
qSurface->Width(),
qSurface->Height(),
qSurface->Stride(),
_qimage_from_gfximage_format(qSurface->Format()));
QPainter painter(&tempQImage);
return DrawWidgetBackground(&painter, aContext,
aFrame, aWidgetType,
aRect, aClipRect);
}
#ifdef MOZ_X11
else if (surface->GetType() == gfxASurface::SurfaceTypeXlib) {
gfxXlibSurface* qSurface = (gfxXlibSurface*) (surface.get());
QPixmap pixmap(QPixmap::fromX11Pixmap(qSurface->XDrawable()));
QPainter painter(&pixmap);
return DrawWidgetBackground(&painter, aContext,
aFrame, aWidgetType,
aRect, aClipRect);
}
#endif
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult
nsNativeThemeQt::DrawWidgetBackground(QPainter *qPainter,
nsIRenderingContext* aContext,
nsIFrame* aFrame,
PRUint8 aWidgetType,
const nsRect& aRect,
const nsRect& aClipRect)
{
gfxContext* context = aContext->ThebesContext();
nsRefPtr<gfxASurface> surface = context->CurrentSurface();
context->UpdateSurfaceClip();
if (surface->GetType() != gfxASurface::SurfaceTypeQPainter)
return NS_ERROR_NOT_IMPLEMENTED;
gfxQPainterSurface* qSurface = (gfxQPainterSurface*) (surface.get());
QPainter* qPainter = qSurface->GetQPainter();
NS_ASSERTION(qPainter, "Where'd my QPainter go?");
if (qPainter == nsnull)
return NS_OK;
QStyle* style = qApp->style();
qPainter->save();

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

@ -106,6 +106,13 @@ public:
private:
inline nsresult DrawWidgetBackground(QPainter *qPainter,
nsIRenderingContext* aContext,
nsIFrame* aFrame,
PRUint8 aWidgetType,
const nsRect& aRect,
const nsRect& aClipRect);
inline PRInt32 GetAppUnitsPerDevPixel(nsIRenderingContext* aContext){
nsCOMPtr<nsIDeviceContext> dctx = nsnull;
aContext->GetDeviceContext(*getter_AddRefs(dctx));

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

@ -89,7 +89,19 @@
#include "gfxXlibSurface.h"
#include "gfxQPainterSurface.h"
#include "gfxContext.h"
#include "gfxSharedImageSurface.h"
// Buffered Pixmap stuff
static QPixmap *gBufferPixmap = nsnull;
static int gBufferPixmapUsageCount = 0;
// Buffered shared image + pixmap
static gfxSharedImageSurface *gBufferImage = nsnull;
static gfxSharedImageSurface *gBufferImageTemp = nsnull;
PRBool gNeedColorConversion = PR_FALSE;
extern "C" {
#include "pixman.h"
}
/* For PrepareNativeWidget */
static NS_DEFINE_IID(kDeviceContextCID, NS_DEVICE_CONTEXT_CID);
@ -175,6 +187,90 @@ nsWindow::nsWindow()
mIsTransparent = PR_FALSE;
mCursor = eCursor_standard;
gBufferPixmapUsageCount++;
}
static inline gfxASurface::gfxImageFormat
_depth_to_gfximage_format(PRInt32 aDepth)
{
switch (aDepth) {
case 32:
return gfxASurface::ImageFormatARGB32;
case 24:
return gfxASurface::ImageFormatRGB24;
default:
return gfxASurface::ImageFormatUnknown;
}
}
static void
FreeOffScreenBuffers(void)
{
delete gBufferImage;
delete gBufferImageTemp;
delete gBufferPixmap;
gBufferImage = nsnull;
gBufferImageTemp = nsnull;
gBufferPixmap = nsnull;
}
static bool
UpdateOffScreenBuffers(QSize aSize, int aDepth)
{
gfxIntSize size(aSize.width(), aSize.height());
if (gBufferPixmap) {
if (gBufferPixmap->size().width() < size.width ||
gBufferPixmap->size().height() < size.height) {
FreeOffScreenBuffers();
} else
return true;
}
gBufferPixmap = new QPixmap(size.width, size.height);
if (!gBufferPixmap)
return false;
if (gfxQtPlatform::GetPlatform()->GetRenderMode() == gfxQtPlatform::RENDER_XLIB)
return true;
// Check if system depth has related gfxImage format
gfxASurface::gfxImageFormat format =
_depth_to_gfximage_format(gBufferPixmap->x11Info().depth());
gNeedColorConversion = (format == gfxASurface::ImageFormatUnknown);
gBufferImage = new gfxSharedImageSurface();
if (!gBufferImage) {
FreeOffScreenBuffers();
return false;
}
if (!gBufferImage->Init(gfxIntSize(gBufferPixmap->size().width(),
gBufferPixmap->size().height()),
_depth_to_gfximage_format(gBufferPixmap->x11Info().depth()))) {
FreeOffScreenBuffers();
return false;
}
// gfxImageSurface does not support system color depth format
// we have to paint it with temp surface and color conversion
if (!gNeedColorConversion)
return true;
gBufferImageTemp = new gfxSharedImageSurface();
if (!gBufferImageTemp) {
FreeOffScreenBuffers();
return false;
}
if (!gBufferImageTemp->Init(gfxIntSize(gBufferPixmap->size().width(),
gBufferPixmap->size().height()),
gfxASurface::ImageFormatRGB24)) {
FreeOffScreenBuffers();
return false;
}
return true;
}
nsWindow::~nsWindow()
@ -221,6 +317,12 @@ nsWindow::Destroy(void)
LOG(("nsWindow::Destroy [%p]\n", (void *)this));
mIsDestroyed = PR_TRUE;
if (gBufferPixmapUsageCount &&
--gBufferPixmapUsageCount == 0) {
FreeOffScreenBuffers();
}
nsCOMPtr<nsIWidget> rollupWidget = do_QueryReferent(gRollupWindow);
if (static_cast<nsIWidget *>(this) == rollupWidget.get()) {
if (gRollupListener)
@ -830,6 +932,20 @@ nsWindow::GetAttention(PRInt32 aCycleCount)
return NS_ERROR_NOT_IMPLEMENTED;
}
#ifdef MOZ_X11
static already_AddRefed<gfxASurface>
GetSurfaceForQWidget(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)
{
@ -857,7 +973,25 @@ nsWindow::DoPaint(QPainter* aPainter, const QStyleOptionGraphicsItem* aOption)
updateRegion->SetTo( (int)r.x(), (int)r.y(), (int)r.width(), (int)r.height() );
nsRefPtr<gfxASurface> targetSurface = new gfxQPainterSurface(aPainter);
gfxQtPlatform::RenderMode renderMode = gfxQtPlatform::GetPlatform()->GetRenderMode();
// Prepare offscreen buffers if RenderMode Xlib or Image
if (renderMode != gfxQtPlatform::RENDER_QPAINTER)
if (!UpdateOffScreenBuffers(r.size().toSize(), QX11Info().depth()))
return nsEventStatus_eIgnore;
nsRefPtr<gfxASurface> targetSurface = nsnull;
if (renderMode == gfxQtPlatform::RENDER_XLIB) {
targetSurface = GetSurfaceForQWidget(gBufferPixmap);
} else if (renderMode == gfxQtPlatform::RENDER_SHARED_IMAGE) {
targetSurface = gNeedColorConversion ? gBufferImageTemp->getASurface()
: gBufferImage->getASurface();
} else if (renderMode == gfxQtPlatform::RENDER_QPAINTER) {
targetSurface = new gfxQPainterSurface(aPainter);
}
if (NS_UNLIKELY(!targetSurface))
return nsEventStatus_eIgnore;
nsRefPtr<gfxContext> ctx = new gfxContext(targetSurface);
nsCOMPtr<nsIRenderingContext> rc;
@ -888,6 +1022,46 @@ nsWindow::DoPaint(QPainter* aPainter, const QStyleOptionGraphicsItem* aOption)
LOGDRAW(("[%p] draw done\n", this));
if (renderMode == gfxQtPlatform::RENDER_SHARED_IMAGE) {
if (gNeedColorConversion) {
pixman_image_t *src_image = NULL;
pixman_image_t *dst_image = NULL;
src_image = pixman_image_create_bits(PIXMAN_x8r8g8b8,
gBufferImageTemp->GetSize().width,
gBufferImageTemp->GetSize().height,
(uint32_t*)gBufferImageTemp->Data(),
gBufferImageTemp->Stride());
dst_image = pixman_image_create_bits(PIXMAN_r5g6b5,
gBufferImage->GetSize().width,
gBufferImage->GetSize().height,
(uint32_t*)gBufferImage->Data(),
gBufferImage->Stride());
pixman_image_composite(PIXMAN_OP_SRC,
src_image,
NULL,
dst_image,
0, 0,
0, 0,
0, 0,
gBufferImageTemp->GetSize().width,
gBufferImageTemp->GetSize().height);
pixman_image_unref(src_image);
pixman_image_unref(dst_image);
}
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, gBufferImage->GetSize().width, gBufferImage->GetSize().height,
False);
XFreeGC (disp, gc);
}
if (renderMode != gfxQtPlatform::RENDER_QPAINTER)
aPainter->drawPixmap(QPoint(0, 0), *gBufferPixmap);
ctx = nsnull;
targetSurface = nsnull;
@ -1804,8 +1978,21 @@ nsWindow::GetThebesSurface()
/* This is really a dummy surface; this is only used when doing reflow, because
* we need a RenderingContext to measure text against.
*/
if (!mThebesSurface)
mThebesSurface = new gfxQPainterSurface(gfxIntSize(5,5), gfxASurface::CONTENT_COLOR);
if (mThebesSurface)
return mThebesSurface;
gfxQtPlatform::RenderMode renderMode = gfxQtPlatform::GetPlatform()->GetRenderMode();
if (renderMode == gfxQtPlatform::RENDER_QPAINTER) {
mThebesSurface = new gfxQPainterSurface(gfxIntSize(1, 1), gfxASurface::CONTENT_COLOR);
} else if (renderMode == gfxQtPlatform::RENDER_XLIB) {
mThebesSurface = new gfxXlibSurface(QX11Info().display(),
(Visual*)QX11Info().visual(),
gfxIntSize(1, 1), QX11Info().depth());
}
if (!mThebesSurface) {
gfxASurface::gfxImageFormat imageFormat = gfxASurface::ImageFormatRGB24;
mThebesSurface = new gfxImageSurface(gfxIntSize(1, 1), imageFormat);
}
return mThebesSurface;
}