cairo: first attempt at surface manager/surface cache.

This commit is contained in:
vladimir%pobox.com 2004-08-19 18:56:03 +00:00
Родитель 88003e6d39
Коммит 8c17eb9986
9 изменённых файлов: 246 добавлений и 157 удалений

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

@ -75,6 +75,7 @@ CPPSRCS = \
nsCairoScreenManager.cpp \
nsCairoDrawingSurface.cpp \
nsCairoGfxFactory.cpp \
nsCairoSurfaceManager.cpp \
nsCairoBlender.cpp \
nsFontMetricsUtils.cpp \
nsFontMetricsXft.cpp \

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

@ -73,21 +73,16 @@ nsCairoBlender::Blend(PRInt32 aSX, PRInt32 aSY, PRInt32 aWidth, PRInt32 aHeight,
cairo_t *cairo = cairo_create();
cairo_set_target_surface(cairo, dst_surf);
cairo_pattern_t *src_pat = cairo_pattern_create_for_surface (src_surf);
cairo_matrix_t *mat = cairo_matrix_create();
cairo_matrix_translate (mat, aDX - aSX, aDY - aSY);
cairo_pattern_set_matrix (src_pat, mat);
cairo_set_pattern (cairo, src_pat);
cairo_set_alpha (cairo, (double) aSrcOpacity);
cairo_rectangle (cairo, aDX, aDY, aWidth, aHeight);
cairo_fill (cairo);
cairo_clip (cairo);
cairo_matrix_destroy (mat);
cairo_pattern_destroy (src_pat);
cairo_destroy(cairo);
PRUint32 srcWidth, srcHeight;
aSrc->GetDimensions(&srcWidth, &srcHeight);
cairo_translate (cairo, double(aDX - aSX), double(aDY - aSY));
cairo_show_surface (cairo, src_surf, srcWidth, srcHeight);
cairo_destroy (cairo);
return NS_OK;
}

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

@ -39,6 +39,7 @@
#include "nsCairoDeviceContext.h"
#include "nsCairoRenderingContext.h"
#include "nsCairoSurfaceManager.h"
#include "nsCOMPtr.h"
#include "nsIView.h"
@ -105,6 +106,8 @@ nsCairoDeviceContext::nsCairoDeviceContext()
mZoom = 1.0f;
mTextZoom = 1.0f;
mSurfaceManager = nsnull;
#ifdef MOZ_ENABLE_XLIB
mXlibRgbHandle = xxlib_find_handle(XXLIBRGB_DEFAULT_HANDLE);
#endif
@ -112,6 +115,7 @@ nsCairoDeviceContext::nsCairoDeviceContext()
nsCairoDeviceContext::~nsCairoDeviceContext()
{
delete mSurfaceManager;
}
int
@ -155,6 +159,8 @@ nsCairoDeviceContext::Init(nsNativeWidget aWidget)
mWidth = -1;
mHeight = -1;
mSurfaceManager = new nsCairoSurfaceManager();
return NS_OK;
}

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

@ -48,6 +48,8 @@
#include "xlibrgb.h"
#endif
class nsCairoSurfaceManager;
class nsCairoDeviceContext : public DeviceContextImpl
{
public:
@ -108,6 +110,8 @@ public:
Drawable GetXPixmapParentDrawable();
#endif
nsCairoSurfaceManager *GetSurfaceManager() { return mSurfaceManager; }
private:
nsNativeWidget mWidget;
@ -118,6 +122,8 @@ private:
PRInt32 mWidth;
PRInt32 mHeight;
nsCairoSurfaceManager *mSurfaceManager;
#if defined(MOZ_ENABLE_GTK2) || defined(MOZ_ENABLE_XLIB)
Drawable mPixmapParentDrawable;
#endif

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

@ -53,7 +53,7 @@
NS_IMPL_ISUPPORTS1(nsCairoDrawingSurface, nsIDrawingSurface)
nsCairoDrawingSurface::nsCairoDrawingSurface()
: mSurface(nsnull), mImageSurface(nsnull)
: mSurface(nsnull), mImageSurface(nsnull), mDC(nsnull), mNativeWidget(nsnull)
{
#if defined(MOZ_ENABLE_GTK2) || defined(MOZ_ENABLE_XLIB)
mPixmap = 0;
@ -161,26 +161,33 @@ nsresult
nsCairoDrawingSurface::Init (nsCairoDeviceContext *aDC, nsIWidget *aWidget)
{
nsNativeWidget nativeWidget = aWidget->GetNativeData(NS_NATIVE_WIDGET);
fprintf (stderr, "++++ [%p] Creating DRAWABLE (0x%08x) surface\n", this, nativeWidget);
return Init (aDC, nativeWidget);
}
nsresult
nsCairoDrawingSurface::Init (nsCairoDeviceContext *aDC, nsNativeWidget aNativeWidget)
{
fprintf (stderr, "++++ [%p] Creating DRAWABLE (0x%08x) surface\n", this, aNativeWidget);
mDC = aDC;
#ifdef MOZ_ENABLE_GTK2
mDrawable = GDK_DRAWABLE_XID(GDK_DRAWABLE(nativeWidget));
NS_ASSERTION (GDK_IS_WINDOW(nativeWidget), "unsupported native widget type!");
mNativeWidget = aNativeWidget;
mDrawable = GDK_DRAWABLE_XID(GDK_DRAWABLE(aNativeWidget));
NS_ASSERTION (GDK_IS_WINDOW(aNativeWidget), "unsupported native widget type!");
mSurface = cairo_xlib_surface_create
(GDK_WINDOW_XDISPLAY(GDK_DRAWABLE(nativeWidget)),
GDK_WINDOW_XWINDOW(GDK_DRAWABLE(nativeWidget)),
GDK_VISUAL_XVISUAL(gdk_drawable_get_visual(GDK_DRAWABLE(nativeWidget))),
(GDK_WINDOW_XDISPLAY(GDK_DRAWABLE(aNativeWidget)),
GDK_WINDOW_XWINDOW(GDK_DRAWABLE(aNativeWidget)),
GDK_VISUAL_XVISUAL(gdk_drawable_get_visual(GDK_DRAWABLE(aNativeWidget))),
CAIRO_FORMAT_ARGB32, // I hope!
GDK_COLORMAP_XCOLORMAP(gdk_drawable_get_colormap(GDK_DRAWABLE(nativeWidget))));
GDK_COLORMAP_XCOLORMAP(gdk_drawable_get_colormap(GDK_DRAWABLE(aNativeWidget))));
Window root_ignore;
int x_ignore, y_ignore;
unsigned int bwidth_ignore, width, height, depth;
XGetGeometry(GDK_WINDOW_XDISPLAY(GDK_DRAWABLE(nativeWidget)),
GDK_WINDOW_XWINDOW(GDK_DRAWABLE(nativeWidget)),
XGetGeometry(GDK_WINDOW_XDISPLAY(GDK_DRAWABLE(aNativeWidget)),
GDK_WINDOW_XWINDOW(GDK_DRAWABLE(aNativeWidget)),
&root_ignore, &x_ignore, &y_ignore,
&width, &height,
&bwidth_ignore, &depth);

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

@ -1,120 +0,0 @@
/* -*- Mode: C++; tab-width: 4; 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 mozilla.org code.
*
* The Initial Developer of the Original Code is
* Vladimir Vukicevic <vladimir@pobox.com>
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
*
* 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 NPL, 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 NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef NSCAIRODRAWINGSURFACE__H__
#define NSCAIRODRAWINGSURFACE__H__
#include "nsCOMPtr.h"
#include "nsIDrawingSurface.h"
#include "nsIRegion.h"
#include <cairo.h>
#if defined(MOZ_ENABLE_GTK2)
#include <gdk/gdkx.h>
#include <X11/extensions/XShm.h>
#endif
class nsIWidget;
class nsCairoDeviceContext;
#ifdef MOZ_ENABLE_XFT
typedef struct _XftDraw XftDraw;
#endif
class nsCairoDrawingSurface : public nsIDrawingSurface
{
public:
nsCairoDrawingSurface ();
virtual ~nsCairoDrawingSurface ();
// create a image surface if aFastAccess == TRUE, otherwise create
// a fast server pixmap
nsresult Init (nsCairoDeviceContext *aDC, PRUint32 aWidth, PRUint32 aHeight, PRBool aFastAccess);
// create a fast drawing surface for a native widget
nsresult Init (nsCairoDeviceContext *aDC, nsIWidget *aWidget);
// nsISupports interface
NS_DECL_ISUPPORTS
// nsIDrawingSurface interface
NS_IMETHOD Lock(PRInt32 aX, PRInt32 aY, PRUint32 aWidth, PRUint32 aHeight,
void **aBits, PRInt32 *aStride, PRInt32 *aWidthBytes,
PRUint32 aFlags);
NS_IMETHOD Unlock(void);
NS_IMETHOD GetDimensions(PRUint32 *aWidth, PRUint32 *aHeight);
NS_IMETHOD IsOffscreen(PRBool *aOffScreen);
NS_IMETHOD IsPixelAddressable(PRBool *aAddressable);
NS_IMETHOD GetPixelFormat(nsPixelFormat *aFormat);
/* utility functions */
cairo_surface_t *GetCairoSurface(void) { return mSurface; }
PRInt32 GetDepth() { /* XXX */ return 24; }
#ifdef MOZ_ENABLE_XFT
XftDraw *GetXftDraw(void);
void GetLastXftClip(nsIRegion **aLastRegion);
void SetLastXftClip(nsIRegion *aLastRegion);
#endif /* MOZ_ENABLE_XFT */
private:
cairo_surface_t *mSurface, *mImageSurface;
nsCairoDeviceContext *mDC;
#if defined(MOZ_ENABLE_GTK2) || defined(MOZ_ENABLE_XLIB)
Display *mXDisplay;
Drawable mDrawable;
Pixmap mPixmap;
XShmSegmentInfo mShmInfo;
#endif
#ifdef MOZ_ENABLE_XFT
XftDraw *mXftDraw;
nsCOMPtr<nsIRegion> mLastXftClip;
#endif
PRUint32 mLockFlags;
PRBool mFastAccess;
PRUint32 mWidth, mHeight;
};
#endif /* NSCAIRODRAWINGSURFACE__H__ */

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

@ -36,6 +36,7 @@
#include "nsCairoRenderingContext.h"
#include "nsCairoDeviceContext.h"
#include "nsCairoSurfaceManager.h"
#include "nsRect.h"
#include "nsString.h"
@ -87,17 +88,13 @@ nsCairoRenderingContext::Init(nsIDeviceContext* aContext, nsIWidget *aWidget)
mDeviceContext = aContext;
mWidget = aWidget;
mDrawingSurface = new nsCairoDrawingSurface();
mDrawingSurface->Init (cairoDC, aWidget);
nsCOMPtr<nsIDrawingSurface> ids;
cairoDC->GetSurfaceManager()->GetDrawingSurfaceForWidget (cairoDC, aWidget, getter_AddRefs(ids));
mDrawingSurface = ((nsCairoDrawingSurface*) (ids.get()));
mCairo = cairo_create ();
cairo_set_target_surface (mCairo, mDrawingSurface->GetCairoSurface());
mClipRegion = new nsCairoRegion();
cairo_select_font (mCairo, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
return (CommonInit());
}
@ -114,16 +111,14 @@ nsCairoRenderingContext::Init(nsIDeviceContext* aContext, nsIDrawingSurface *aSu
mCairo = cairo_create ();
cairo_set_target_surface (mCairo, mDrawingSurface->GetCairoSurface());
mClipRegion = new nsCairoRegion();
cairo_select_font (mCairo, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
return (CommonInit());
}
NS_IMETHODIMP
nsCairoRenderingContext::CommonInit(void)
{
mClipRegion = new nsCairoRegion();
float app2dev;
app2dev = mDeviceContext->AppUnitsToDevUnits();
Scale(app2dev, app2dev);
@ -767,7 +762,15 @@ nsCairoRenderingContext::CopyOffScreenBits(nsIDrawingSurface *aSrcSurf,
cairo_transform_distance (mCairo, &dw, &dh);
}
fprintf (stderr, "***** --> %g,%g [%d,%d] -> %g,%g %gx%g\n", sx, sy, srcWidth, srcHeight, dx, dy, dw, dh);
cairo_save (mCairo);
cairo_init_clip (mCairo);
cairo_set_rgb_color (mCairo, 0.0, 0.0, 1.0);
cairo_set_alpha (mCairo, 0.5);
cairo_rectangle(mCairo, dx, dy, dw, dh);
cairo_fill(mCairo);
// args are in pixels!!
cairo_identity_matrix (mCairo);
@ -779,7 +782,7 @@ nsCairoRenderingContext::CopyOffScreenBits(nsIDrawingSurface *aSrcSurf,
cairo_scale(mCairo, dw / double(srcWidth), dh / double(srcHeight));
cairo_translate(mCairo, dx - sx, dy - sy);
cairo_show_surface(mCairo, src, srcWidth, srcHeight);
// cairo_show_surface(mCairo, src, srcWidth, srcHeight);
cairo_restore (mCairo);
@ -796,8 +799,8 @@ nsCairoRenderingContext::RetrieveCurrentNativeGraphicData(PRUint32 * ngd)
NS_IMETHODIMP
nsCairoRenderingContext::UseBackbuffer(PRBool* aUseBackbuffer)
{
// *aUseBackbuffer = PR_FALSE;
*aUseBackbuffer = PR_TRUE;
*aUseBackbuffer = PR_FALSE;
// *aUseBackbuffer = PR_TRUE;
return NS_OK;
}

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

@ -0,0 +1,120 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is mozilla.org.
* Portions created by the Initial Developer are
* Copyright (C) 2004 the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@pavlov.net>
* Vladimir Vukicevic <vladimir@pobox.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.
*/
#include "nsIWidget.h"
#include "nsCairoSurfaceManager.h"
#include "nsCairoDrawingSurface.h"
nsCairoSurfaceManager::nsCairoSurfaceManager()
{
}
nsCairoSurfaceManager::~nsCairoSurfaceManager()
{
FlushCachedSurfaces();
}
NS_IMETHODIMP
nsCairoSurfaceManager::FlushCachedSurfaces()
{
for (WidgetToSurfaceMap::iterator iter = mSurfaceMap.begin();
iter != mSurfaceMap.end();
iter++)
{
nsCairoDrawingSurface *surf = (iter->second);
NS_RELEASE(surf);
}
mSurfaceMap.clear();
return NS_OK;
}
NS_IMETHODIMP
nsCairoSurfaceManager::GetDrawingSurfaceForWidget (nsCairoDeviceContext *aDC,
nsIWidget *aWidget,
nsIDrawingSurface **aSurface)
{
nsNativeWidget nativeWidget = aWidget->GetNativeData(NS_NATIVE_WIDGET);
return GetDrawingSurfaceForNativeWidget (aDC, nativeWidget, aSurface);
}
NS_IMETHODIMP
nsCairoSurfaceManager::GetDrawingSurfaceForNativeWidget (nsCairoDeviceContext *aDC,
nsNativeWidget aWidget,
nsIDrawingSurface **aSurface)
{
nsCairoDrawingSurface *surf = nsnull;
WidgetToSurfaceMap::iterator iter = mSurfaceMap.find(aWidget);
/* cached? */
if (iter == mSurfaceMap.end()) {
/* nope. */
surf = new nsCairoDrawingSurface();
NS_ADDREF(surf); // our own reference for map
surf->Init (aDC, aWidget);
mSurfaceMap.insert(WidgetToSurfaceMap::value_type (aWidget, surf));
} else {
surf = (iter->second);
}
*aSurface = surf;
NS_ADDREF(*aSurface);
return NS_OK;
}
NS_IMETHODIMP
nsCairoSurfaceManager::ReleaseSurface (nsIDrawingSurface *aSurface)
{
nsCairoDrawingSurface *cds = NS_STATIC_CAST(nsCairoDrawingSurface*, aSurface);
nsNativeWidget nw = cds->GetNativeWidget();
WidgetToSurfaceMap::iterator iter = mSurfaceMap.find(nw);
if (iter == mSurfaceMap.end()) {
// ?!
return NS_OK;
}
PRUint32 refcnt;
NS_RELEASE2(cds, refcnt);
if (refcnt == 0) {
mSurfaceMap.erase (iter);
}
}

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

@ -0,0 +1,71 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is mozilla.org.
* Portions created by the Initial Developer are
* Copyright (C) 2004 the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@pavlov.net>
* Vladimir Vukicevic <vladimir@pobox.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.
*/
#ifndef _NS_CAIROSURFACEMANAGER_H_
#define _NS_CAIROSURFACEMANAGER_H_
#include "gfxCore.h"
#include <cairo.h>
// someone who knows nsTHashTable can fix this
#include <map>
class nsIDrawingSurface;
class nsCairoDrawingSurface;
class nsCairoDeviceContext;
class nsIWidget;
class nsCairoSurfaceManager
{
public:
nsCairoSurfaceManager();
~nsCairoSurfaceManager();
NS_IMETHOD GetDrawingSurfaceForWidget (nsCairoDeviceContext *aDC, nsIWidget *aWidget, nsIDrawingSurface **aSurface);
NS_IMETHOD GetDrawingSurfaceForNativeWidget (nsCairoDeviceContext *aDC, nsNativeWidget aWidget, nsIDrawingSurface **aSurface);
NS_IMETHOD ReleaseSurface (nsIDrawingSurface *aSurface);
// get rid of all cached surfaces
NS_IMETHOD FlushCachedSurfaces ();
private:
typedef std::map<nsNativeWidget, nsCairoDrawingSurface*> WidgetToSurfaceMap;
WidgetToSurfaceMap mSurfaceMap;
};
#endif /* _NS_CAIROSURFACEMANAGER_H_ */