/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include"gfxXlibSurface.h"
#include"cairo.h" #include"cairo-xlib.h" #include <X11/Xlibint.h> /* For XESetCloseDisplay */ #undef max // Xlibint.h defines this and it breaks std::max #undef min // Xlibint.h defines this and it breaks std::min #undef Data
if (relatedDrawable == X11None) {
relatedDrawable = RootWindowOfScreen(screen);
}
Display* dpy = DisplayOfScreen(screen); // X gives us a fatal error if we try to create a pixmap of width // or height 0 return XCreatePixmap(dpy, relatedDrawable, std::max(1, size.width),
std::max(1, size.height), depth);
}
void gfxXlibSurface::TakePixmap() {
NS_ASSERTION(!mPixmapTaken, "I already own the Pixmap!");
mPixmapTaken = true;
// The bit depth returned from Cairo is technically int, but this is // the last place we'd be worried about that scenario. unsignedint bitDepth = cairo_xlib_surface_get_depth(CairoSurface());
MOZ_ASSERT((bitDepth % 8) == 0, "Memory used not recorded correctly");
// Divide by 8 because surface_get_depth gives us the number of *bits* per // pixel.
gfx::IntSize size = GetSize();
CheckedInt32 totalBytes =
CheckedInt32(size.width) * CheckedInt32(size.height) * (bitDepth / 8);
// Don't do anything in the "else" case. We could add INT32_MAX, but that // would overflow the memory used counter. It would also mean we tried for // a 2G image. For now, we'll just assert,
MOZ_ASSERT(totalBytes.isValid(), "Did not expect to exceed 2Gb image"); if (totalBytes.isValid()) {
RecordMemoryUsed(totalBytes.value());
}
}
Drawable gfxXlibSurface::ReleasePixmap() {
NS_ASSERTION(mPixmapTaken, "I don't own the Pixmap!");
mPixmapTaken = false;
RecordMemoryFreed(); return mDrawable;
}
private: struct ColormapEntry { // The Screen is needed here because colormaps (and their visuals) may // only be used on one Screen
Screen* mScreen;
Visual* mVisual;
Colormap mColormap;
};
// 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.
// Use the default colormap if the default visual matches.
Visual* defaultVisual = DefaultVisualOfScreen(aScreen); if (aVisual == defaultVisual) {
*aColormap = DefaultColormapOfScreen(aScreen);
*aVisualForColormap = defaultVisual; returntrue;
}
// Only supporting TrueColor non-default visuals if (!aVisual || aVisual->c_class != TrueColor) returnfalse;
if (!sDisplayTable) {
sDisplayTable = new DisplayTable();
}
nsTArray<DisplayInfo>* displays = &sDisplayTable->mDisplays;
size_t 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) returnfalse;
XESetCloseDisplay(display, codes->extension, DisplayClosing); // Add a new DisplayInfo.
displays->AppendElement(display);
}
// Only a small number of formats are expected to be used, so just do a // simple linear search. for (uint32_t i = 0; i < entries->Length(); ++i) { const ColormapEntry& entry = entries->ElementAt(i); if (aVisual == entry.mVisual) {
*aColormap = entry.mColormap;
*aVisualForColormap = entry.mVisual; returntrue;
}
}
// No existing entry. Create a colormap and add an entry.
Colormap colormap =
XCreateColormap(display, RootWindowOfScreen(aScreen), aVisual, AllocNone);
ColormapEntry* newEntry = entries->AppendElement();
newEntry->mScreen = aScreen;
newEntry->mVisual = aVisual;
newEntry->mColormap = colormap;
/* 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 = nullptr;
} return 0;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.