/* -*- 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/. */
// Surfaces use refcounting that's tied to the cairo surface refcnt, to avoid // refcount mismatch issues.
nsrefcnt gfxASurface::AddRef(void) { if (mSurfaceValid) { if (mFloatingRefs) { // eat a floating ref
mFloatingRefs--;
} else {
cairo_surface_reference(mSurface);
}
return (nsrefcnt)cairo_surface_get_reference_count(mSurface);
} // the surface isn't valid, but we still need to refcount // the gfxASurface return ++mFloatingRefs;
}
nsrefcnt gfxASurface::Release(void) { if (mSurfaceValid) {
NS_ASSERTION(
mFloatingRefs == 0, "gfxASurface::Release with floating refs still hanging around!");
// Note that there is a destructor set on user data for mSurface, // which will delete this gfxASurface wrapper when the surface's refcount // goes out of scope.
nsrefcnt refcnt = (nsrefcnt)cairo_surface_get_reference_count(mSurface);
cairo_surface_destroy(mSurface);
// |this| may not be valid any more, don't use it!
/* Do we already have a wrapper for this surface? */
result = GetSurfaceWrapper(csurf); if (result) { // fprintf(stderr, "Existing wrapper for %p -> %p\n", csurf, result); return result.forget();
}
/* No wrapper; figure out the surface type and create it */
cairo_surface_type_t stype = cairo_surface_get_type(csurf);
if (stype == CAIRO_SURFACE_TYPE_IMAGE) {
result = new gfxImageSurface(csurf);
} #ifdef CAIRO_HAS_WIN32_SURFACE elseif (stype == CAIRO_SURFACE_TYPE_WIN32 ||
stype == CAIRO_SURFACE_TYPE_WIN32_PRINTING) {
result = new gfxWindowsSurface(csurf);
} #endif #ifdef MOZ_X11 elseif (stype == CAIRO_SURFACE_TYPE_XLIB) {
result = new gfxXlibSurface(csurf);
} #endif #ifdef CAIRO_HAS_QUARTZ_SURFACE elseif (stype == CAIRO_SURFACE_TYPE_QUARTZ) {
result = new gfxQuartzSurface(csurf, aSize);
} #endif else {
result = new gfxUnknownSurface(csurf, aSize);
}
// fprintf(stderr, "New wrapper for %p -> %p\n", csurf, result);
return result.forget();
}
void gfxASurface::Init(cairo_surface_t* surface, bool existingSurface) {
SetSurfaceWrapper(surface, this);
MOZ_ASSERT(surface, "surface should be a valid pointer");
mSurface = surface;
mSurfaceValid = !cairo_surface_status(surface); if (!mSurfaceValid) {
gfxWarning() << "ASurface Init failed with Cairo status "
<< cairo_surface_status(surface) << " on " << hexa(surface);
}
gfxContentType gfxASurface::ContentFromFormat(gfxImageFormat format) { switch (format) { case SurfaceFormat::A8R8G8B8_UINT32: return gfxContentType::COLOR_ALPHA; case SurfaceFormat::X8R8G8B8_UINT32: case SurfaceFormat::R5G6B5_UINT16: return gfxContentType::COLOR; case SurfaceFormat::A8: return gfxContentType::ALPHA;
case SurfaceFormat::UNKNOWN: default: return gfxContentType::COLOR;
}
}
int32_t gfxASurface::BytePerPixelFromFormat(gfxImageFormat format) { switch (format) { case SurfaceFormat::A8R8G8B8_UINT32: case SurfaceFormat::X8R8G8B8_UINT32: return 4; case SurfaceFormat::R5G6B5_UINT16: return 2; case SurfaceFormat::A8: return 1; default:
NS_WARNING("Unknown byte per pixel value for Image format");
} return 0;
}
/** Memory reporting **/
staticconstchar* sDefaultSurfaceDescription = "Memory used by gfx surface of the given type.";
staticconst SurfaceMemoryReporterAttrs sSurfaceMemoryReporterAttrs[] = {
{"gfx-surface-image", nullptr},
{"gfx-surface-pdf", nullptr},
{"gfx-surface-ps", nullptr},
{"gfx-surface-xlib", "Memory used by xlib surfaces to store pixmaps. This memory lives in " "the X server's process rather than in this application, so the bytes " "accounted for here aren't counted in vsize, resident, explicit, or any " "of " "the other measurements on this page."},
{"gfx-surface-xcb", nullptr},
{"gfx-surface-glitz???", nullptr}, // should never be used
{"gfx-surface-quartz", nullptr},
{"gfx-surface-win32", nullptr},
{"gfx-surface-beos", nullptr},
{"gfx-surface-directfb???", nullptr}, // should never be used
{"gfx-surface-svg", nullptr},
{"gfx-surface-os2", nullptr},
{"gfx-surface-win32printing", nullptr},
{"gfx-surface-quartzimage", nullptr},
{"gfx-surface-script", nullptr},
{"gfx-surface-qpainter", nullptr},
{"gfx-surface-recording", nullptr},
{"gfx-surface-vg", nullptr},
{"gfx-surface-gl", nullptr},
{"gfx-surface-drm", nullptr},
{"gfx-surface-tee", nullptr},
{"gfx-surface-xml", nullptr},
{"gfx-surface-skia", nullptr},
{"gfx-surface-subsurface", nullptr},
};
static_assert(std::size(sSurfaceMemoryReporterAttrs) ==
size_t(gfxSurfaceType::Max), "sSurfaceMemoryReporterAttrs exceeds max capacity");
static_assert(uint32_t(CAIRO_SURFACE_TYPE_SKIA) ==
uint32_t(gfxSurfaceType::Skia), "CAIRO_SURFACE_TYPE_SKIA not equal to gfxSurfaceType::Skia");
/* Surface size memory reporting */
class SurfaceMemoryReporter final : public nsIMemoryReporter {
~SurfaceMemoryReporter() = default;
// We can touch this array on several different threads, and we don't // want to introduce memory barriers when recording the memory used. To // assure dynamic race checkers like TSan that this is OK, we use // relaxed memory ordering here. static Atomic<size_t, Relaxed>
sSurfaceMemoryUsed[size_t(gfxSurfaceType::Max)];
public: staticvoid AdjustUsedMemory(gfxSurfaceType aType, int32_t aBytes) { // A read-modify-write operation like += would require a memory barrier // here, which would defeat the purpose of using relaxed memory // ordering. So separate out the read and write operations.
sSurfaceMemoryUsed[size_t(aType)] =
sSurfaceMemoryUsed[size_t(aType)] + aBytes;
};
// This memory reporter is sometimes allocated on the compositor thread, // but always released on the main thread, so its refcounting needs to be // threadsafe.
NS_DECL_THREADSAFE_ISUPPORTS
NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData, bool aAnonymize) override { const size_t len = std::size(sSurfaceMemoryReporterAttrs); for (size_t i = 0; i < len; i++) {
int64_t amount = sSurfaceMemoryUsed[i];
if (amount != 0) { constchar* path = sSurfaceMemoryReporterAttrs[i].path; constchar* desc = sSurfaceMemoryReporterAttrs[i].description; if (!desc) {
desc = sDefaultSurfaceDescription;
}
/* static */
uint8_t gfxASurface::BytesPerPixel(gfxImageFormat aImageFormat) { switch (aImageFormat) { case SurfaceFormat::A8R8G8B8_UINT32: return 4; case SurfaceFormat::X8R8G8B8_UINT32: return 4; case SurfaceFormat::R5G6B5_UINT16: return 2; case SurfaceFormat::A8: return 1; case SurfaceFormat::UNKNOWN: default:
MOZ_ASSERT_UNREACHABLE("Not really sure what you want me to say here"); 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.