зеркало из https://github.com/mozilla/pjs.git
Bug 606910 - RENDER_DIRECT mode for Qt widget (xshmPutImage). r=dougt a=blocking-fennec
--HG-- extra : rebase_source : 6ea776ea7e0b282d6b61d5e5fa570460e84f90be
This commit is contained in:
Родитель
6d4b7edaf4
Коммит
35d0416872
|
@ -81,7 +81,11 @@
|
|||
|
||||
// Because the QPainter backend has some problems with glyphs rendering
|
||||
// it is better to use image or xlib cairo backends by default
|
||||
#if (MOZ_PLATFORM_MAEMO == 6)
|
||||
#define DEFAULT_RENDER_MODE RENDER_BUFFERED
|
||||
#else
|
||||
#define DEFAULT_RENDER_MODE RENDER_DIRECT
|
||||
#endif
|
||||
|
||||
static QPaintEngine::Type sDefaultQtPaintEngineType = QPaintEngine::X11;
|
||||
gfxFontconfigUtils *gfxQtPlatform::sFontconfigUtils = nsnull;
|
||||
|
@ -146,6 +150,9 @@ gfxQtPlatform::gfxQtPlatform()
|
|||
case 1:
|
||||
mRenderMode = RENDER_BUFFERED;
|
||||
break;
|
||||
case 2:
|
||||
mRenderMode = RENDER_DIRECT;
|
||||
break;
|
||||
default:
|
||||
mRenderMode = RENDER_QPAINTER;
|
||||
}
|
||||
|
@ -207,7 +214,7 @@ gfxQtPlatform::CreateOffscreenSurface(const gfxIntSize& size,
|
|||
}
|
||||
#endif
|
||||
|
||||
if (mRenderMode == RENDER_BUFFERED &&
|
||||
if ((mRenderMode == RENDER_BUFFERED || mRenderMode == RENDER_DIRECT) &&
|
||||
sDefaultQtPaintEngineType != QPaintEngine::X11) {
|
||||
newSurface = new gfxImageSurface(size, imageFormat);
|
||||
return newSurface.forget();
|
||||
|
|
|
@ -60,6 +60,8 @@ public:
|
|||
RENDER_QPAINTER = 0,
|
||||
/* Use offscreen buffer for rendering with image or xlib gfx backend */
|
||||
RENDER_BUFFERED,
|
||||
/* Direct rendering to Widget surface */
|
||||
RENDER_DIRECT,
|
||||
/* max */
|
||||
RENDER_MODE_MAX
|
||||
};
|
||||
|
|
|
@ -135,6 +135,8 @@ extern "C" {
|
|||
#include "gfxXlibSurface.h"
|
||||
#endif
|
||||
|
||||
#include "nsShmImage.h"
|
||||
|
||||
#ifdef MOZ_DFB
|
||||
extern "C" {
|
||||
#ifdef MOZ_DIRECT_DEBUG
|
||||
|
@ -286,16 +288,6 @@ UpdateLastInputEventTime()
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef MOZ_HAVE_SHMIMAGE
|
||||
// If XShm isn't available to our client, we'll try XShm once, fail,
|
||||
// set this to false and then never try again.
|
||||
static PRBool gShmAvailable = PR_TRUE;
|
||||
static PRBool UseShm()
|
||||
{
|
||||
return gfxPlatformGtk::UseClientSideRendering() && gShmAvailable;
|
||||
}
|
||||
#endif
|
||||
|
||||
// this is the last window that had a drag event happen on it.
|
||||
nsWindow *nsWindow::mLastDragMotionWindow = NULL;
|
||||
PRBool nsWindow::sIsDraggingOutOf = PR_FALSE;
|
||||
|
@ -389,159 +381,6 @@ protected:
|
|||
pixman_region32& get() { return *this; }
|
||||
};
|
||||
|
||||
|
||||
#ifdef MOZ_HAVE_SHMIMAGE
|
||||
|
||||
using mozilla::ipc::SharedMemorySysV;
|
||||
|
||||
class nsShmImage {
|
||||
NS_INLINE_DECL_REFCOUNTING(nsShmImage)
|
||||
|
||||
public:
|
||||
typedef gfxASurface::gfxImageFormat Format;
|
||||
|
||||
static already_AddRefed<nsShmImage>
|
||||
Create(const gfxIntSize& aSize, Visual* aVisual, unsigned int aDepth);
|
||||
|
||||
~nsShmImage() {
|
||||
if (mImage) {
|
||||
if (mXAttached) {
|
||||
XShmDetach(gdk_x11_get_default_xdisplay(), &mInfo);
|
||||
}
|
||||
XDestroyImage(mImage);
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<gfxASurface> AsSurface();
|
||||
|
||||
void Put(GdkWindow* aWindow, GdkRectangle* aRects, GdkRectangle* aEnd);
|
||||
|
||||
gfxIntSize Size() const { return mSize; }
|
||||
|
||||
private:
|
||||
nsShmImage()
|
||||
: mImage(nsnull)
|
||||
, mXAttached(PR_FALSE)
|
||||
{ mInfo.shmid = SharedMemorySysV::NULLHandle(); }
|
||||
|
||||
nsRefPtr<SharedMemorySysV> mSegment;
|
||||
XImage* mImage;
|
||||
XShmSegmentInfo mInfo;
|
||||
gfxIntSize mSize;
|
||||
Format mFormat;
|
||||
PRPackedBool mXAttached;
|
||||
};
|
||||
|
||||
already_AddRefed<nsShmImage>
|
||||
nsShmImage::Create(const gfxIntSize& aSize,
|
||||
Visual* aVisual, unsigned int aDepth)
|
||||
{
|
||||
Display* dpy = gdk_x11_get_default_xdisplay();
|
||||
|
||||
nsRefPtr<nsShmImage> shm = new nsShmImage();
|
||||
shm->mImage = XShmCreateImage(dpy, aVisual, aDepth,
|
||||
ZPixmap, nsnull,
|
||||
&(shm->mInfo),
|
||||
aSize.width, aSize.height);
|
||||
if (!shm->mImage) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
size_t size = shm->mImage->bytes_per_line * shm->mImage->height;
|
||||
shm->mSegment = new SharedMemorySysV();
|
||||
if (!shm->mSegment->Create(size) || !shm->mSegment->Map(size)) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
shm->mInfo.shmid = shm->mSegment->GetHandle();
|
||||
shm->mInfo.shmaddr =
|
||||
shm->mImage->data = static_cast<char*>(shm->mSegment->memory());
|
||||
shm->mInfo.readOnly = False;
|
||||
|
||||
gdk_error_trap_push();
|
||||
Status attachOk = XShmAttach(dpy, &shm->mInfo);
|
||||
gint xerror = gdk_error_trap_pop();
|
||||
|
||||
if (!attachOk || xerror) {
|
||||
// Assume XShm isn't available, and don't attempt to use it
|
||||
// again.
|
||||
gShmAvailable = PR_FALSE;
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
shm->mXAttached = PR_TRUE;
|
||||
shm->mSize = aSize;
|
||||
switch (shm->mImage->depth) {
|
||||
case 24:
|
||||
shm->mFormat = gfxASurface::ImageFormatRGB24; break;
|
||||
case 16:
|
||||
shm->mFormat = gfxASurface::ImageFormatRGB16_565; break;
|
||||
default:
|
||||
NS_WARNING("Unsupported XShm Image depth!");
|
||||
gShmAvailable = PR_FALSE;
|
||||
return nsnull;
|
||||
}
|
||||
return shm.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<gfxASurface>
|
||||
nsShmImage::AsSurface()
|
||||
{
|
||||
return nsRefPtr<gfxASurface>(
|
||||
new gfxImageSurface(static_cast<unsigned char*>(mSegment->memory()),
|
||||
mSize,
|
||||
mImage->bytes_per_line,
|
||||
mFormat)
|
||||
).forget();
|
||||
}
|
||||
|
||||
void
|
||||
nsShmImage::Put(GdkWindow* aWindow, GdkRectangle* aRects, GdkRectangle* aEnd)
|
||||
{
|
||||
GdkDrawable* gd;
|
||||
gint dx, dy;
|
||||
gdk_window_get_internal_paint_info(aWindow, &gd, &dx, &dy);
|
||||
|
||||
Display* dpy = gdk_x11_get_default_xdisplay();
|
||||
Drawable d = GDK_DRAWABLE_XID(gd);
|
||||
|
||||
GC gc = XCreateGC(dpy, d, 0, nsnull);
|
||||
for (GdkRectangle* r = aRects; r < aEnd; r++) {
|
||||
XShmPutImage(dpy, d, gc, mImage,
|
||||
r->x, r->y,
|
||||
r->x - dx, r->y - dy,
|
||||
r->width, r->height,
|
||||
False);
|
||||
}
|
||||
XFreeGC(dpy, gc);
|
||||
|
||||
// FIXME/bug 597336: we need to ensure that the shm image isn't
|
||||
// scribbled over before all its pending XShmPutImage()s complete.
|
||||
// However, XSync() is an unnecessarily heavyweight
|
||||
// synchronization mechanism; other options are possible. If this
|
||||
// XSync is shown to hurt responsiveness, we need to explore the
|
||||
// other options.
|
||||
XSync(dpy, False);
|
||||
}
|
||||
|
||||
static already_AddRefed<gfxASurface>
|
||||
EnsureShmImage(const gfxIntSize& aSize, Visual* aVisual, unsigned int aDepth,
|
||||
nsRefPtr<nsShmImage>& aImage)
|
||||
{
|
||||
if (!aImage || aImage->Size() != aSize) {
|
||||
// Because we XSync() after XShmAttach() to trap errors, we
|
||||
// know that the X server has the old image's memory mapped
|
||||
// into its address space, so it's OK to destroy the old image
|
||||
// here even if there are outstanding Puts. The Detach is
|
||||
// ordered after the Puts.
|
||||
aImage = nsShmImage::Create(aSize, aVisual, aDepth);
|
||||
}
|
||||
return !aImage ? nsnull : aImage->AsSurface();
|
||||
}
|
||||
|
||||
#endif // defined(MOZ_X11) && defined(MOZ_HAVE_SHAREDMEMORYSYSV)
|
||||
|
||||
|
||||
nsWindow::nsWindow()
|
||||
{
|
||||
mIsTopLevel = PR_FALSE;
|
||||
|
@ -2346,7 +2185,7 @@ nsWindow::OnExposeEvent(GtkWidget *aWidget, GdkEventExpose *aEvent)
|
|||
layerBuffering = BasicLayerManager::BUFFER_NONE;
|
||||
ctx->PushGroup(gfxASurface::CONTENT_COLOR_ALPHA);
|
||||
#ifdef MOZ_HAVE_SHMIMAGE
|
||||
} else if (UseShm()) {
|
||||
} else if (nsShmImage::UseShm()) {
|
||||
// We're using an xshm mapping as a back buffer.
|
||||
layerBuffering = BasicLayerManager::BUFFER_NONE;
|
||||
#endif // MOZ_HAVE_SHMIMAGE
|
||||
|
@ -2405,7 +2244,7 @@ nsWindow::OnExposeEvent(GtkWidget *aWidget, GdkEventExpose *aEvent)
|
|||
}
|
||||
}
|
||||
# ifdef MOZ_HAVE_SHMIMAGE
|
||||
if (UseShm() && NS_LIKELY(!mIsDestroyed)) {
|
||||
if (nsShmImage::UseShm() && NS_LIKELY(!mIsDestroyed)) {
|
||||
mShmImage->Put(mGdkWindow, rects, r_end);
|
||||
}
|
||||
# endif // MOZ_HAVE_SHMIMAGE
|
||||
|
@ -6706,13 +6545,14 @@ nsWindow::GetThebesSurface()
|
|||
|
||||
# ifdef MOZ_HAVE_SHMIMAGE
|
||||
PRBool usingShm = PR_FALSE;
|
||||
if (UseShm()) {
|
||||
if (nsShmImage::UseShm()) {
|
||||
// EnsureShmImage() is a dangerous interface, but we guarantee
|
||||
// that the thebes surface and the shmimage have the same
|
||||
// lifetime
|
||||
mThebesSurface = EnsureShmImage(size,
|
||||
visual, gdk_drawable_get_depth(d),
|
||||
mShmImage);
|
||||
mThebesSurface =
|
||||
nsShmImage::EnsureShmImage(size,
|
||||
visual, gdk_drawable_get_depth(d),
|
||||
mShmImage);
|
||||
usingShm = mThebesSurface != nsnull;
|
||||
}
|
||||
if (!usingShm)
|
||||
|
|
|
@ -103,6 +103,8 @@ ifneq (qt,$(MOZ_WIDGET_TOOLKIT))
|
|||
INACTIVE_COMPONENT = 1
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
CXXFLAGS += $(MOZ_QT_CFLAGS) $(GLIB_CFLAGS) $(MOZ_CAIRO_CFLAGS)
|
||||
|
@ -131,4 +133,5 @@ LOCAL_INCLUDES += \
|
|||
$(NULL)
|
||||
ifdef MOZ_X11
|
||||
INCLUDES += -I$(srcdir)/../shared/x11
|
||||
INCLUDES += -I$(srcdir)/../shared
|
||||
endif
|
||||
|
|
|
@ -92,7 +92,7 @@ MozQWidget::~MozQWidget()
|
|||
|
||||
void MozQWidget::paint(QPainter* aPainter, const QStyleOptionGraphicsItem* aOption, QWidget* aWidget /*= 0*/)
|
||||
{
|
||||
mReceiver->DoPaint(aPainter, aOption);
|
||||
mReceiver->DoPaint(aPainter, aOption, aWidget);
|
||||
}
|
||||
|
||||
void MozQWidget::activate()
|
||||
|
|
|
@ -128,11 +128,22 @@ static const float GESTURES_BLOCK_MOUSE_FOR = 200;
|
|||
#include "Layers.h"
|
||||
#include "LayerManagerOGL.h"
|
||||
|
||||
#include "nsShmImage.h"
|
||||
extern "C" {
|
||||
#include "pixman.h"
|
||||
}
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
// imported in nsWidgetFactory.cpp
|
||||
PRBool gDisableNativeTheme = PR_FALSE;
|
||||
|
||||
// Cached offscreen surface
|
||||
static nsRefPtr<gfxASurface> gBufferSurface;
|
||||
#ifdef MOZ_HAVE_SHMIMAGE
|
||||
// If we're using xshm rendering, mThebesSurface wraps gShmImage
|
||||
nsRefPtr<nsShmImage> gShmImage;
|
||||
#endif
|
||||
|
||||
static int gBufferPixmapUsageCount = 0;
|
||||
static gfxIntSize gBufferMaxSize(0, 0);
|
||||
|
@ -268,7 +279,7 @@ _gfximage_to_qformat(gfxASurface::gfxImageFormat aFormat)
|
|||
}
|
||||
|
||||
static bool
|
||||
UpdateOffScreenBuffers(int aDepth, QSize aSize)
|
||||
UpdateOffScreenBuffers(int aDepth, QSize aSize, QWidget* aWidget = nsnull)
|
||||
{
|
||||
gfxIntSize size(aSize.width(), aSize.height());
|
||||
if (gBufferSurface) {
|
||||
|
@ -290,8 +301,22 @@ UpdateOffScreenBuffers(int aDepth, QSize aSize)
|
|||
if (format == gfxASurface::ImageFormatUnknown)
|
||||
format = gfxASurface::ImageFormatRGB24;
|
||||
|
||||
#ifdef MOZ_HAVE_SHMIMAGE
|
||||
if (aWidget) {
|
||||
if (gfxPlatform::GetPlatform()->ScreenReferenceSurface()->GetType() ==
|
||||
gfxASurface::SurfaceTypeImage) {
|
||||
gShmImage = nsShmImage::Create(gBufferMaxSize,
|
||||
(Visual*)aWidget->x11Info().visual(),
|
||||
aDepth);
|
||||
gBufferSurface = gShmImage->AsSurface();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
gBufferSurface = gfxPlatform::GetPlatform()->
|
||||
CreateOffscreenSurface(gBufferMaxSize, gfxASurface::ContentFromFormat(format));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -343,6 +368,9 @@ nsWindow::Destroy(void)
|
|||
--gBufferPixmapUsageCount == 0) {
|
||||
|
||||
gBufferSurface = nsnull;
|
||||
#ifdef MOZ_HAVE_SHMIMAGE
|
||||
gShmImage = nsnull;
|
||||
#endif
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIWidget> rollupWidget = do_QueryReferent(gRollupWindow);
|
||||
|
@ -941,8 +969,23 @@ nsWindow::GetAttention(PRInt32 aCycleCount)
|
|||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
#ifdef MOZ_X11
|
||||
static already_AddRefed<gfxASurface>
|
||||
GetSurfaceForQWidget(QWidget* 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)
|
||||
nsWindow::DoPaint(QPainter* aPainter, const QStyleOptionGraphicsItem* aOption, QWidget* aWidget)
|
||||
{
|
||||
if (mIsDestroyed) {
|
||||
LOG(("Expose event on destroyed window [%p] window %p\n",
|
||||
|
@ -993,6 +1036,11 @@ nsWindow::DoPaint(QPainter* aPainter, const QStyleOptionGraphicsItem* aOption)
|
|||
} else if (renderMode == gfxQtPlatform::RENDER_QPAINTER) {
|
||||
targetSurface = new gfxQPainterSurface(aPainter);
|
||||
#endif
|
||||
} else if (renderMode == gfxQtPlatform::RENDER_DIRECT) {
|
||||
if (!UpdateOffScreenBuffers(depth, aWidget->size(), aWidget)) {
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
targetSurface = gBufferSurface;
|
||||
}
|
||||
|
||||
if (NS_UNLIKELY(!targetSurface))
|
||||
|
@ -1001,17 +1049,30 @@ 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_BUFFERED)
|
||||
if (renderMode == gfxQtPlatform::RENDER_BUFFERED) {
|
||||
ctx->Translate(gfxPoint(-r.x(), -r.y()));
|
||||
}
|
||||
else if (renderMode == gfxQtPlatform::RENDER_DIRECT) {
|
||||
// This is needed for rotate transformation on Meego
|
||||
// This will work very slow if pixman does not handle rotation very well
|
||||
gfxMatrix matr(aPainter->transform().m11(),
|
||||
aPainter->transform().m12(),
|
||||
aPainter->transform().m21(),
|
||||
aPainter->transform().m22(),
|
||||
aPainter->transform().dx(),
|
||||
aPainter->transform().dy());
|
||||
ctx->SetMatrix(matr);
|
||||
NS_ASSERTION(PIXMAN_VERSION < PIXMAN_VERSION_ENCODE(0, 21, 2) && aPainter->transform().isRotating(), "Old pixman and rotate transform, it is going to be slow");
|
||||
}
|
||||
|
||||
nsPaintEvent event(PR_TRUE, NS_PAINT, this);
|
||||
event.refPoint.x = r.x();
|
||||
event.refPoint.y = r.y();
|
||||
event.refPoint.x = rect.x;
|
||||
event.refPoint.y = rect.y;
|
||||
event.region = nsIntRegion(rect);
|
||||
{
|
||||
AutoLayerManagerSetup
|
||||
setupLayerManager(this, ctx, BasicLayerManager::BUFFER_NONE);
|
||||
status = DispatchEvent(&event);
|
||||
AutoLayerManagerSetup
|
||||
setupLayerManager(this, ctx, BasicLayerManager::BUFFER_NONE);
|
||||
status = DispatchEvent(&event);
|
||||
}
|
||||
|
||||
// DispatchEvent can Destroy us (bug 378273), avoid doing any paint
|
||||
|
@ -1047,6 +1108,30 @@ nsWindow::DoPaint(QPainter* aPainter, const QStyleOptionGraphicsItem* aOption)
|
|||
aPainter->drawImage(QPoint(rect.x, rect.y), img,
|
||||
QRect(0, 0, rect.width, rect.height));
|
||||
}
|
||||
} else if (renderMode == gfxQtPlatform::RENDER_DIRECT) {
|
||||
QRect trans = aPainter->transform().mapRect(r).toRect();
|
||||
if (gBufferSurface->GetType() == gfxASurface::SurfaceTypeXlib) {
|
||||
nsRefPtr<gfxASurface> widgetSurface = GetSurfaceForQWidget(aWidget);
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(widgetSurface);
|
||||
ctx->SetSource(gBufferSurface);
|
||||
ctx->Rectangle(gfxRect(trans.x(), trans.y(), trans.width(), trans.height()), PR_TRUE);
|
||||
ctx->Clip();
|
||||
ctx->Fill();
|
||||
} else if (gBufferSurface->GetType() == gfxASurface::SurfaceTypeImage) {
|
||||
#ifdef MOZ_HAVE_SHMIMAGE
|
||||
if (gShmImage) {
|
||||
gShmImage->Put(aWidget, trans);
|
||||
} else
|
||||
#endif
|
||||
if (gBufferSurface) {
|
||||
nsRefPtr<gfxASurface> widgetSurface = GetSurfaceForQWidget(aWidget);
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(widgetSurface);
|
||||
ctx->SetSource(gBufferSurface);
|
||||
ctx->Rectangle(gfxRect(trans.x(), trans.y(), trans.width(), trans.height()), PR_TRUE);
|
||||
ctx->Clip();
|
||||
ctx->Fill();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx = nsnull;
|
||||
|
@ -2475,6 +2560,11 @@ nsWindow::createQWidget(MozQWidget *parent, nsWidgetInitData *aInitData)
|
|||
newView->setViewport(new QGLWidget());
|
||||
}
|
||||
|
||||
if (gfxQtPlatform::GetPlatform()->GetRenderMode() == gfxQtPlatform::RENDER_DIRECT) {
|
||||
// Disable double buffer and system background rendering
|
||||
newView->viewport()->setAttribute(Qt::WA_PaintOnScreen, true);
|
||||
newView->viewport()->setAttribute(Qt::WA_NoSystemBackground, true);
|
||||
}
|
||||
// Enable gestures:
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 0))
|
||||
newView->viewport()->grabGesture(Qt::PinchGesture);
|
||||
|
@ -2528,8 +2618,8 @@ nsWindow::GetThebesSurface()
|
|||
if (mThebesSurface)
|
||||
return mThebesSurface;
|
||||
|
||||
gfxQtPlatform::RenderMode renderMode = gfxQtPlatform::GetPlatform()->GetRenderMode();
|
||||
#ifdef CAIRO_HAS_QT_SURFACE
|
||||
gfxQtPlatform::RenderMode renderMode = gfxQtPlatform::GetPlatform()->GetRenderMode();
|
||||
if (renderMode == gfxQtPlatform::RENDER_QPAINTER) {
|
||||
mThebesSurface = new gfxQPainterSurface(gfxIntSize(1, 1), gfxASurface::CONTENT_COLOR);
|
||||
}
|
||||
|
|
|
@ -111,7 +111,7 @@ public:
|
|||
nsWindow();
|
||||
virtual ~nsWindow();
|
||||
|
||||
nsEventStatus DoPaint( QPainter* aPainter, const QStyleOptionGraphicsItem * aOption );
|
||||
nsEventStatus DoPaint( QPainter* aPainter, const QStyleOptionGraphicsItem * aOption, QWidget* aWidget);
|
||||
|
||||
static void ReleaseGlobals();
|
||||
|
||||
|
|
|
@ -57,12 +57,14 @@ endif
|
|||
|
||||
CPPSRCS = \
|
||||
WidgetUtils.cpp \
|
||||
nsShmImage.cpp \
|
||||
$(NULL)
|
||||
|
||||
# we don't want the shared lib, but we want to force the creation of a static lib.
|
||||
FORCE_STATIC_LIB = 1
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
CXXFLAGS += $(TK_CFLAGS)
|
||||
|
|
|
@ -0,0 +1,197 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* ***** 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 the Mozilla browser.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1999
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Chris Jones <jones.chris.g@gmail.com>
|
||||
* 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 ***** */
|
||||
|
||||
#if defined(MOZ_WIDGET_GTK2)
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdkx.h>
|
||||
#elif defined(MOZ_WIDGET_QT)
|
||||
#include <QWidget>
|
||||
#endif
|
||||
|
||||
#include "nsShmImage.h"
|
||||
#include "gfxPlatform.h"
|
||||
#include "gfxImageSurface.h"
|
||||
|
||||
#ifdef MOZ_HAVE_SHMIMAGE
|
||||
|
||||
// If XShm isn't available to our client, we'll try XShm once, fail,
|
||||
// set this to false and then never try again.
|
||||
static PRBool gShmAvailable = PR_TRUE;
|
||||
PRBool nsShmImage::UseShm()
|
||||
{
|
||||
return gfxPlatform::GetPlatform()->
|
||||
ScreenReferenceSurface()->GetType() == gfxASurface::SurfaceTypeImage
|
||||
&& gShmAvailable;
|
||||
}
|
||||
|
||||
already_AddRefed<nsShmImage>
|
||||
nsShmImage::Create(const gfxIntSize& aSize,
|
||||
Visual* aVisual, unsigned int aDepth)
|
||||
{
|
||||
Display* dpy = DISPLAY();
|
||||
|
||||
nsRefPtr<nsShmImage> shm = new nsShmImage();
|
||||
shm->mImage = XShmCreateImage(dpy, aVisual, aDepth,
|
||||
ZPixmap, nsnull,
|
||||
&(shm->mInfo),
|
||||
aSize.width, aSize.height);
|
||||
if (!shm->mImage) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
size_t size = shm->mImage->bytes_per_line * shm->mImage->height;
|
||||
shm->mSegment = new SharedMemorySysV();
|
||||
if (!shm->mSegment->Create(size) || !shm->mSegment->Map(size)) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
shm->mInfo.shmid = shm->mSegment->GetHandle();
|
||||
shm->mInfo.shmaddr =
|
||||
shm->mImage->data = static_cast<char*>(shm->mSegment->memory());
|
||||
shm->mInfo.readOnly = False;
|
||||
|
||||
int xerror = 0;
|
||||
#if defined(MOZ_WIDGET_GTK2)
|
||||
gdk_error_trap_push();
|
||||
Status attachOk = XShmAttach(dpy, &shm->mInfo);
|
||||
xerror = gdk_error_trap_pop();
|
||||
#elif defined(MOZ_WIDGET_QT)
|
||||
Status attachOk = XShmAttach(dpy, &shm->mInfo);
|
||||
#endif
|
||||
|
||||
if (!attachOk || xerror) {
|
||||
// Assume XShm isn't available, and don't attempt to use it
|
||||
// again.
|
||||
gShmAvailable = PR_FALSE;
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
shm->mXAttached = PR_TRUE;
|
||||
shm->mSize = aSize;
|
||||
switch (shm->mImage->depth) {
|
||||
case 24:
|
||||
shm->mFormat = gfxASurface::ImageFormatRGB24; break;
|
||||
case 16:
|
||||
shm->mFormat = gfxASurface::ImageFormatRGB16_565; break;
|
||||
default:
|
||||
NS_WARNING("Unsupported XShm Image depth!");
|
||||
gShmAvailable = PR_FALSE;
|
||||
return nsnull;
|
||||
}
|
||||
return shm.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<gfxASurface>
|
||||
nsShmImage::AsSurface()
|
||||
{
|
||||
return nsRefPtr<gfxASurface>(
|
||||
new gfxImageSurface(static_cast<unsigned char*>(mSegment->memory()),
|
||||
mSize,
|
||||
mImage->bytes_per_line,
|
||||
mFormat)
|
||||
).forget();
|
||||
}
|
||||
|
||||
#if defined(MOZ_WIDGET_GTK2)
|
||||
void
|
||||
nsShmImage::Put(GdkWindow* aWindow, GdkRectangle* aRects, GdkRectangle* aEnd)
|
||||
{
|
||||
GdkDrawable* gd;
|
||||
gint dx, dy;
|
||||
gdk_window_get_internal_paint_info(aWindow, &gd, &dx, &dy);
|
||||
|
||||
Display* dpy = gdk_x11_get_default_xdisplay();
|
||||
Drawable d = GDK_DRAWABLE_XID(gd);
|
||||
|
||||
GC gc = XCreateGC(dpy, d, 0, nsnull);
|
||||
for (GdkRectangle* r = aRects; r < aEnd; r++) {
|
||||
XShmPutImage(dpy, d, gc, mImage,
|
||||
r->x, r->y,
|
||||
r->x - dx, r->y - dy,
|
||||
r->width, r->height,
|
||||
False);
|
||||
}
|
||||
XFreeGC(dpy, gc);
|
||||
|
||||
#ifdef MOZ_WIDGET_GTK2
|
||||
// FIXME/bug 597336: we need to ensure that the shm image isn't
|
||||
// scribbled over before all its pending XShmPutImage()s complete.
|
||||
// However, XSync() is an unnecessarily heavyweight
|
||||
// synchronization mechanism; other options are possible. If this
|
||||
// XSync is shown to hurt responsiveness, we need to explore the
|
||||
// other options.
|
||||
XSync(dpy, False);
|
||||
#endif
|
||||
}
|
||||
#elif defined(MOZ_WIDGET_QT)
|
||||
void
|
||||
nsShmImage::Put(QWidget* aWindow, QRect& aRect)
|
||||
{
|
||||
Display* dpy = aWindow->x11Info().display();
|
||||
Drawable d = aWindow->handle();
|
||||
|
||||
GC gc = XCreateGC(dpy, d, 0, nsnull);
|
||||
// Avoid out of bounds painting
|
||||
QRect inter = aRect.intersected(aWindow->rect());
|
||||
XShmPutImage(dpy, d, gc, mImage,
|
||||
inter.x(), inter.y(),
|
||||
inter.x(), inter.y(),
|
||||
inter.width(), inter.height(),
|
||||
False);
|
||||
XFreeGC(dpy, gc);
|
||||
}
|
||||
#endif
|
||||
|
||||
already_AddRefed<gfxASurface>
|
||||
nsShmImage::EnsureShmImage(const gfxIntSize& aSize, Visual* aVisual, unsigned int aDepth,
|
||||
nsRefPtr<nsShmImage>& aImage)
|
||||
{
|
||||
if (!aImage || aImage->Size() != aSize) {
|
||||
// Because we XSync() after XShmAttach() to trap errors, we
|
||||
// know that the X server has the old image's memory mapped
|
||||
// into its address space, so it's OK to destroy the old image
|
||||
// here even if there are outstanding Puts. The Detach is
|
||||
// ordered after the Puts.
|
||||
aImage = nsShmImage::Create(aSize, aVisual, aDepth);
|
||||
}
|
||||
return !aImage ? nsnull : aImage->AsSurface();
|
||||
}
|
||||
|
||||
#endif // defined(MOZ_X11) && defined(MOZ_HAVE_SHAREDMEMORYSYSV)
|
|
@ -0,0 +1,122 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* ***** 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 the Mozilla browser.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1999
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Chris Jones <jones.chris.g@gmail.com>
|
||||
* 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 __mozilla_widget_nsShmImage_h__
|
||||
#define __mozilla_widget_nsShmImage_h__
|
||||
|
||||
#ifdef MOZ_IPC
|
||||
# include "mozilla/ipc/SharedMemorySysV.h"
|
||||
#endif
|
||||
|
||||
#if defined(MOZ_X11) && defined(MOZ_HAVE_SHAREDMEMORYSYSV)
|
||||
# define MOZ_HAVE_SHMIMAGE
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_HAVE_SHMIMAGE
|
||||
|
||||
#include "nsIWidget.h"
|
||||
#include "gfxASurface.h"
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/extensions/XShm.h>
|
||||
|
||||
#if defined(MOZ_WIDGET_GTK2)
|
||||
#define DISPLAY gdk_x11_get_default_xdisplay
|
||||
#elif defined(MOZ_WIDGET_QT)
|
||||
#include "QX11Info"
|
||||
#define DISPLAY QX11Info().display
|
||||
#endif
|
||||
|
||||
class QRect;
|
||||
class QWidget;
|
||||
|
||||
using mozilla::ipc::SharedMemorySysV;
|
||||
|
||||
class nsShmImage {
|
||||
NS_INLINE_DECL_REFCOUNTING(nsShmImage)
|
||||
|
||||
public:
|
||||
typedef gfxASurface::gfxImageFormat Format;
|
||||
|
||||
static PRBool UseShm();
|
||||
static already_AddRefed<nsShmImage>
|
||||
Create(const gfxIntSize& aSize, Visual* aVisual, unsigned int aDepth);
|
||||
static already_AddRefed<gfxASurface>
|
||||
EnsureShmImage(const gfxIntSize& aSize, Visual* aVisual, unsigned int aDepth,
|
||||
nsRefPtr<nsShmImage>& aImage);
|
||||
|
||||
~nsShmImage() {
|
||||
if (mImage) {
|
||||
XSync(DISPLAY(), False);
|
||||
if (mXAttached) {
|
||||
XShmDetach(DISPLAY(), &mInfo);
|
||||
}
|
||||
XDestroyImage(mImage);
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<gfxASurface> AsSurface();
|
||||
|
||||
#if defined(MOZ_WIDGET_GTK2)
|
||||
void Put(GdkWindow* aWindow, GdkRectangle* aRects, GdkRectangle* aEnd);
|
||||
#elif defined(MOZ_WIDGET_QT)
|
||||
void Put(QWidget* aWindow, QRect& aRect);
|
||||
#endif
|
||||
|
||||
gfxIntSize Size() const { return mSize; }
|
||||
|
||||
private:
|
||||
nsShmImage()
|
||||
: mImage(nsnull)
|
||||
, mXAttached(PR_FALSE)
|
||||
{ mInfo.shmid = SharedMemorySysV::NULLHandle(); }
|
||||
|
||||
nsRefPtr<SharedMemorySysV> mSegment;
|
||||
XImage* mImage;
|
||||
XShmSegmentInfo mInfo;
|
||||
gfxIntSize mSize;
|
||||
Format mFormat;
|
||||
PRPackedBool mXAttached;
|
||||
};
|
||||
|
||||
#endif // MOZ_HAVE_SHMIMAGE
|
||||
|
||||
#endif
|
Загрузка…
Ссылка в новой задаче