mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 14:22:01 +00:00
b=574220 add gfxXlibSurface::GetVisualAndColormap() r=vlad
This commit is contained in:
parent
7867669e48
commit
3f6b6f1333
@ -41,6 +41,8 @@
|
||||
#include "cairo.h"
|
||||
#include "cairo-xlib.h"
|
||||
#include "cairo-xlib-xrender.h"
|
||||
#include <X11/Xlibint.h> /* For XESetCloseDisplay */
|
||||
#include "nsTArray.h"
|
||||
|
||||
// Although the dimension parameters in the xCreatePixmapReq wire protocol are
|
||||
// 16-bit unsigned integers, the server's CreatePixmap returns BadAlloc if
|
||||
@ -175,6 +177,174 @@ gfxXlibSurface::DoSizeQuery()
|
||||
mSize.height = height;
|
||||
}
|
||||
|
||||
class DisplayTable {
|
||||
public:
|
||||
static PRBool GetColormapAndVisual(Screen* screen,
|
||||
XRenderPictFormat* format,
|
||||
Visual* visual, Colormap* colormap,
|
||||
Visual** visualForColormap);
|
||||
|
||||
private:
|
||||
struct ColormapEntry {
|
||||
XRenderPictFormat* mFormat;
|
||||
// The Screen is needed here because colormaps (and their visuals) may
|
||||
// only be used on one Screen, but XRenderPictFormats are not unique
|
||||
// to any one Screen.
|
||||
Screen* mScreen;
|
||||
Visual* mVisual;
|
||||
Colormap mColormap;
|
||||
};
|
||||
|
||||
class DisplayInfo {
|
||||
public:
|
||||
DisplayInfo(Display* display) : mDisplay(display) { }
|
||||
Display* mDisplay;
|
||||
nsTArray<ColormapEntry> mColormapEntries;
|
||||
};
|
||||
|
||||
// Comparator for finding the DisplayInfo
|
||||
class FindDisplay {
|
||||
public:
|
||||
PRBool Equals(const DisplayInfo& info, const Display *display) const
|
||||
{
|
||||
return info.mDisplay == display;
|
||||
}
|
||||
};
|
||||
|
||||
static int DisplayClosing(Display *display, XExtCodes* codes);
|
||||
|
||||
nsTArray<DisplayInfo> mDisplays;
|
||||
static DisplayTable* sDisplayTable;
|
||||
};
|
||||
|
||||
DisplayTable* DisplayTable::sDisplayTable;
|
||||
|
||||
// Pixmaps don't have a particular associated visual but the pixel values are
|
||||
// interpreted according to a visual/colormap pairs.
|
||||
//
|
||||
// cairo is designed for surfaces with either TrueColor visuals or the
|
||||
// default visual (which may not be true color). TrueColor visuals don't
|
||||
// really need a colormap because the visual indicates the pixel format,
|
||||
// and cairo uses the default visual with the default colormap, so cairo
|
||||
// surfaces don't need an explicit colormap.
|
||||
//
|
||||
// However, some toolkits (e.g. GDK) need a colormap even with TrueColor
|
||||
// visuals. We can create a colormap for these visuals, but it will use about
|
||||
// 20kB of memory in the server, so we use the default colormap when
|
||||
// suitable and share colormaps between surfaces. Another reason for
|
||||
// minimizing colormap turnover is that the plugin process must leak resources
|
||||
// for each new colormap id when using older GDK libraries (bug 569775).
|
||||
//
|
||||
// Only the format of the pixels is important for rendering to Pixmaps, so if
|
||||
// the format of a visual matches that of the surface, then that visual can be
|
||||
// used for rendering to the surface. Multiple visuals can match the same
|
||||
// format (but have different GLX properties), so the visual returned may
|
||||
// differ from the visual passed in. Colormaps are tied to a visual, so
|
||||
// should only be used with their visual.
|
||||
|
||||
/* static */ PRBool
|
||||
DisplayTable::GetColormapAndVisual(Screen* aScreen, XRenderPictFormat* aFormat,
|
||||
Visual* aVisual, Colormap* aColormap,
|
||||
Visual** aVisualForColormap)
|
||||
|
||||
{
|
||||
Display* display = DisplayOfScreen(aScreen);
|
||||
|
||||
// Use the default colormap if the default visual matches.
|
||||
Visual *defaultVisual = DefaultVisualOfScreen(aScreen);
|
||||
if (aVisual == defaultVisual
|
||||
|| (aFormat
|
||||
&& aFormat == XRenderFindVisualFormat(display, defaultVisual)))
|
||||
{
|
||||
*aColormap = DefaultColormapOfScreen(aScreen);
|
||||
*aVisualForColormap = defaultVisual;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
// Only supporting TrueColor non-default visuals
|
||||
if (!aVisual || aVisual->c_class != TrueColor)
|
||||
return PR_FALSE;
|
||||
|
||||
if (!sDisplayTable) {
|
||||
sDisplayTable = new DisplayTable();
|
||||
}
|
||||
|
||||
nsTArray<DisplayInfo>* displays = &sDisplayTable->mDisplays;
|
||||
PRUint32 d = displays->IndexOf(display, 0, FindDisplay());
|
||||
|
||||
if (d == displays->NoIndex) {
|
||||
d = displays->Length();
|
||||
// Register for notification of display closing, when this info
|
||||
// becomes invalid.
|
||||
XExtCodes *codes = XAddExtension(display);
|
||||
if (!codes)
|
||||
return PR_FALSE;
|
||||
|
||||
XESetCloseDisplay(display, codes->extension, DisplayClosing);
|
||||
// Add a new DisplayInfo.
|
||||
displays->AppendElement(display);
|
||||
}
|
||||
|
||||
nsTArray<ColormapEntry>* entries =
|
||||
&displays->ElementAt(d).mColormapEntries;
|
||||
|
||||
// Only a small number of formats are expected to be used, so just do a
|
||||
// simple linear search.
|
||||
for (PRUint32 i = 0; i < entries->Length(); ++i) {
|
||||
const ColormapEntry& entry = entries->ElementAt(i);
|
||||
// Only the format and screen need to match. (The visual may differ.)
|
||||
// If there is no format (e.g. no RENDER extension) then just compare
|
||||
// the visual.
|
||||
if ((aFormat && entry.mFormat == aFormat && entry.mScreen == aScreen)
|
||||
|| aVisual == entry.mVisual) {
|
||||
*aColormap = entry.mColormap;
|
||||
*aVisualForColormap = entry.mVisual;
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// No existing entry. Create a colormap and add an entry.
|
||||
Colormap colormap = XCreateColormap(display, RootWindowOfScreen(aScreen),
|
||||
aVisual, AllocNone);
|
||||
ColormapEntry* newEntry = entries->AppendElement();
|
||||
newEntry->mFormat = aFormat;
|
||||
newEntry->mScreen = aScreen;
|
||||
newEntry->mVisual = aVisual;
|
||||
newEntry->mColormap = colormap;
|
||||
|
||||
*aColormap = colormap;
|
||||
*aVisualForColormap = aVisual;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
/* static */ int
|
||||
DisplayTable::DisplayClosing(Display *display, XExtCodes* codes)
|
||||
{
|
||||
// No need to free the colormaps explicitly as they will be released when
|
||||
// the connection is closed.
|
||||
sDisplayTable->mDisplays.RemoveElement(display, FindDisplay());
|
||||
if (sDisplayTable->mDisplays.Length() == 0) {
|
||||
delete sDisplayTable;
|
||||
sDisplayTable = nsnull;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
PRBool
|
||||
gfxXlibSurface::GetColormapAndVisual(Colormap* aColormap, Visual** aVisual)
|
||||
{
|
||||
if (!mSurfaceValid)
|
||||
return PR_FALSE;
|
||||
|
||||
XRenderPictFormat* format =
|
||||
cairo_xlib_surface_get_xrender_format(CairoSurface());
|
||||
Screen* screen = cairo_xlib_surface_get_screen(CairoSurface());
|
||||
Visual* visual = cairo_xlib_surface_get_visual(CairoSurface());
|
||||
|
||||
return DisplayTable::GetColormapAndVisual(screen, format, visual,
|
||||
aColormap, aVisual);
|
||||
}
|
||||
|
||||
/* static */
|
||||
int
|
||||
gfxXlibSurface::DepthOfVisual(const Screen* screen, const Visual* visual)
|
||||
|
@ -89,6 +89,9 @@ public:
|
||||
mPixmapTaken = PR_TRUE;
|
||||
}
|
||||
|
||||
// Find a visual and colormap pair suitable for rendering to this surface.
|
||||
PRBool GetColormapAndVisual(Colormap* colormap, Visual **visual);
|
||||
|
||||
protected:
|
||||
// if TakePixmap() has been called on this
|
||||
PRBool mPixmapTaken;
|
||||
|
Loading…
Reference in New Issue
Block a user