Bug 1243072 - Make GfxTexturesReporter work again r=nical,jgilbert

This commit is contained in:
James Willcox 2016-01-26 15:03:37 -06:00
parent 880b7f8386
commit 7528f84391
8 changed files with 113 additions and 92 deletions

View File

@ -12,6 +12,7 @@
#include "mozilla/gfx/2D.h"
#include "ScopedGLHelpers.h"
#include "GLUploadHelpers.h"
#include "GfxTexturesReporter.h"
#include "TextureImageEGL.h"
#ifdef XP_MACOSX
@ -95,6 +96,16 @@ gfx::IntRect TextureImage::GetSrcTileRect() {
return GetTileRect();
}
void
TextureImage::UpdateUploadSize(size_t amount)
{
if (mUploadSize > 0) {
GfxTexturesReporter::UpdateAmount(GfxTexturesReporter::MemoryFreed, mUploadSize);
}
mUploadSize = amount;
GfxTexturesReporter::UpdateAmount(GfxTexturesReporter::MemoryAllocated, mUploadSize);
}
BasicTextureImage::~BasicTextureImage()
{
GLContext *ctx = mGLContext;
@ -162,16 +173,20 @@ BasicTextureImage::EndUpdate()
RefPtr<gfx::DataSourceSurface> updateData = updateSnapshot->GetDataSurface();
bool relative = FinishedSurfaceUpdate();
size_t uploadSize;
mTextureFormat =
UploadSurfaceToTexture(mGLContext,
updateData,
mUpdateRegion,
mTexture,
&uploadSize,
mTextureState == Created,
mUpdateOffset,
relative);
FinishedSurfaceUpload();
if (uploadSize > 0) {
UpdateUploadSize(uploadSize);
}
mUpdateDrawTarget = nullptr;
mTextureState = Valid;
@ -214,14 +229,19 @@ BasicTextureImage::DirectUpdate(gfx::DataSourceSurface* aSurf, const nsIntRegion
region = aRegion;
}
size_t uploadSize;
mTextureFormat =
UploadSurfaceToTexture(mGLContext,
aSurf,
region,
mTexture,
&uploadSize,
mTextureState == Created,
bounds.TopLeft() + IntPoint(aFrom.x, aFrom.y),
false);
if (uploadSize > 0) {
UpdateUploadSize(uploadSize);
}
mTextureState = Valid;
return true;
}
@ -273,6 +293,7 @@ TextureImage::TextureImage(const gfx::IntSize& aSize,
, mTextureFormat(gfx::SurfaceFormat::UNKNOWN)
, mFilter(Filter::GOOD)
, mFlags(aFlags)
, mUploadSize(0)
{}
BasicTextureImage::BasicTextureImage(GLuint aTexture,

View File

@ -203,6 +203,8 @@ public:
protected:
friend class GLContext;
void UpdateUploadSize(size_t amount);
/**
* After the ctor, the TextureImage is invalid. Implementations
* must allocate resources successfully before returning the new
@ -214,7 +216,9 @@ protected:
Flags aFlags = NoFlags);
// Protected destructor, to discourage deletion outside of Release():
virtual ~TextureImage() {}
virtual ~TextureImage() {
UpdateUploadSize(0);
}
virtual gfx::IntRect GetSrcTileRect();
@ -224,6 +228,7 @@ protected:
gfx::SurfaceFormat mTextureFormat;
gfx::Filter mFilter;
Flags mFlags;
size_t mUploadSize;
};
/**

View File

@ -9,6 +9,8 @@
#include "mozilla/gfx/2D.h"
#include "mozilla/gfx/Tools.h" // For BytesPerPixel
#include "nsRegion.h"
#include "GfxTexturesReporter.h"
#include "mozilla/gfx/Logging.h"
namespace mozilla {
@ -379,6 +381,51 @@ TexImage2DHelper(GLContext *gl,
}
}
static uint32_t
GetBytesPerTexel(GLenum format, GLenum type)
{
// If there is no defined format or type, we're not taking up any memory
if (!format || !type) {
return 0;
}
if (format == LOCAL_GL_DEPTH_COMPONENT) {
if (type == LOCAL_GL_UNSIGNED_SHORT)
return 2;
else if (type == LOCAL_GL_UNSIGNED_INT)
return 4;
} else if (format == LOCAL_GL_DEPTH_STENCIL) {
if (type == LOCAL_GL_UNSIGNED_INT_24_8_EXT)
return 4;
}
if (type == LOCAL_GL_UNSIGNED_BYTE || type == LOCAL_GL_FLOAT || type == LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV) {
uint32_t multiplier = type == LOCAL_GL_UNSIGNED_BYTE ? 1 : 4;
switch (format) {
case LOCAL_GL_ALPHA:
case LOCAL_GL_LUMINANCE:
return 1 * multiplier;
case LOCAL_GL_LUMINANCE_ALPHA:
return 2 * multiplier;
case LOCAL_GL_RGB:
return 3 * multiplier;
case LOCAL_GL_RGBA:
return 4 * multiplier;
default:
break;
}
} else if (type == LOCAL_GL_UNSIGNED_SHORT_4_4_4_4 ||
type == LOCAL_GL_UNSIGNED_SHORT_5_5_5_1 ||
type == LOCAL_GL_UNSIGNED_SHORT_5_6_5)
{
return 2;
}
gfxCriticalError() << "Unknown texture type " << type << " or format " << format;
MOZ_CRASH();
return 0;
}
SurfaceFormat
UploadImageDataToTexture(GLContext* gl,
unsigned char* aData,
@ -386,6 +433,7 @@ UploadImageDataToTexture(GLContext* gl,
SurfaceFormat aFormat,
const nsIntRegion& aDstRegion,
GLuint& aTexture,
size_t* aOutUploadSize,
bool aOverwrite,
bool aPixelBuffer,
GLenum aTextureUnit,
@ -505,6 +553,10 @@ UploadImageDataToTexture(GLContext* gl,
// Top left point of the region's bounding rectangle.
IntPoint topLeft = paintRegion.GetBounds().TopLeft();
if (aOutUploadSize) {
*aOutUploadSize = 0;
}
for (auto iter = paintRegion.RectIter(); !iter.Done(); iter.Next()) {
const IntRect& rect = iter.Get();
// The inital data pointer is at the top left point of the region's
@ -544,6 +596,11 @@ UploadImageDataToTexture(GLContext* gl,
rectData);
}
if (aOutUploadSize && !textureInited) {
uint32_t texelSize = GetBytesPerTexel(internalFormat, type);
size_t numTexels = size_t(rect.width) * size_t(rect.height);
*aOutUploadSize += texelSize * numTexels;
}
}
return surfaceFormat;
@ -551,9 +608,10 @@ UploadImageDataToTexture(GLContext* gl,
SurfaceFormat
UploadSurfaceToTexture(GLContext* gl,
DataSourceSurface *aSurface,
DataSourceSurface* aSurface,
const nsIntRegion& aDstRegion,
GLuint& aTexture,
size_t* aOutUploadSize,
bool aOverwrite,
const gfx::IntPoint& aSrcPoint,
bool aPixelBuffer,
@ -565,8 +623,8 @@ UploadSurfaceToTexture(GLContext* gl,
SurfaceFormat format = aSurface->GetFormat();
data += DataOffset(aSrcPoint, stride, format);
return UploadImageDataToTexture(gl, data, stride, format,
aDstRegion, aTexture, aOverwrite,
aPixelBuffer, aTextureUnit,
aDstRegion, aTexture, aOutUploadSize,
aOverwrite, aPixelBuffer, aTextureUnit,
aTextureTarget);
}

View File

@ -40,6 +40,7 @@ class GLContext;
* \param aData Image data to upload.
* \param aDstRegion Region of texture to upload to.
* \param aTexture Texture to use, or 0 to have one created for you.
* \param aOutUploadSize if set, the number of bytes the texture requires will be returned here
* \param aOverwrite Over an existing texture with a new one.
* \param aSrcPoint Offset into aSrc where the region's bound's
* TopLeft() sits.
@ -59,6 +60,7 @@ UploadImageDataToTexture(GLContext* gl,
gfx::SurfaceFormat aFormat,
const nsIntRegion& aDstRegion,
GLuint& aTexture,
size_t* aOutUploadSize = nullptr,
bool aOverwrite = false,
bool aPixelBuffer = false,
GLenum aTextureUnit = LOCAL_GL_TEXTURE0,
@ -72,6 +74,7 @@ UploadSurfaceToTexture(GLContext* gl,
gfx::DataSourceSurface *aSurface,
const nsIntRegion& aDstRegion,
GLuint& aTexture,
size_t* aOutUploadSize = nullptr,
bool aOverwrite = false,
const gfx::IntPoint& aSrcPoint = gfx::IntPoint(0, 0),
bool aPixelBuffer = false,

View File

@ -5,95 +5,22 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "GfxTexturesReporter.h"
#include "GLDefs.h"
using namespace mozilla;
using namespace mozilla::gl;
NS_IMPL_ISUPPORTS(GfxTexturesReporter, nsIMemoryReporter)
Atomic<int32_t> GfxTexturesReporter::sAmount(0);
Atomic<int32_t> GfxTexturesReporter::sTileWasteAmount(0);
static uint32_t
GetBitsPerTexel(GLenum format, GLenum type)
{
// If there is no defined format or type, we're not taking up any memory
if (!format || !type) {
return 0;
}
if (format == LOCAL_GL_DEPTH_COMPONENT) {
if (type == LOCAL_GL_UNSIGNED_SHORT)
return 2*8;
else if (type == LOCAL_GL_UNSIGNED_INT)
return 4*8;
} else if (format == LOCAL_GL_DEPTH_STENCIL) {
if (type == LOCAL_GL_UNSIGNED_INT_24_8_EXT)
return 4*8;
}
if (type == LOCAL_GL_UNSIGNED_BYTE || type == LOCAL_GL_FLOAT) {
uint32_t multiplier = type == LOCAL_GL_FLOAT ? 32 : 8;
switch (format) {
case LOCAL_GL_ALPHA:
case LOCAL_GL_LUMINANCE:
return 1 * multiplier;
case LOCAL_GL_LUMINANCE_ALPHA:
return 2 * multiplier;
case LOCAL_GL_RGB:
return 3 * multiplier;
case LOCAL_GL_RGBA:
return 4 * multiplier;
case LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1:
case LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1:
return 2;
case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
case LOCAL_GL_ATC_RGB:
case LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1:
case LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1:
case LOCAL_GL_ETC1_RGB8_OES:
case LOCAL_GL_COMPRESSED_RGB8_ETC2:
case LOCAL_GL_COMPRESSED_SRGB8_ETC2:
case LOCAL_GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
case LOCAL_GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
case LOCAL_GL_COMPRESSED_R11_EAC:
case LOCAL_GL_COMPRESSED_SIGNED_R11_EAC:
return 4;
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
case LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA:
case LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA:
case LOCAL_GL_COMPRESSED_RGBA8_ETC2_EAC:
case LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
case LOCAL_GL_COMPRESSED_RG11_EAC:
case LOCAL_GL_COMPRESSED_SIGNED_RG11_EAC:
return 8;
default:
break;
}
} else if (type == LOCAL_GL_UNSIGNED_SHORT_4_4_4_4 ||
type == LOCAL_GL_UNSIGNED_SHORT_5_5_5_1 ||
type == LOCAL_GL_UNSIGNED_SHORT_5_6_5)
{
return 2*8;
}
MOZ_ASSERT(false);
return 0;
}
Atomic<size_t> GfxTexturesReporter::sAmount(0);
Atomic<size_t> GfxTexturesReporter::sTileWasteAmount(0);
/* static */ void
GfxTexturesReporter::UpdateAmount(MemoryUse action, GLenum format,
GLenum type, int32_t tileWidth,
int32_t tileHeight)
GfxTexturesReporter::UpdateAmount(MemoryUse action, size_t amount)
{
int64_t bitsPerTexel = GetBitsPerTexel(format, type);
int64_t bytes = int64_t(tileWidth) * int64_t(tileHeight) * bitsPerTexel/8;
if (action == MemoryFreed) {
sAmount -= bytes;
MOZ_RELEASE_ASSERT(amount <= sAmount);
sAmount -= amount;
} else {
sAmount += bytes;
sAmount += amount;
}
}

View File

@ -41,10 +41,9 @@ public:
// When memory is used/freed for tile textures, call this method to update
// the value reported by this memory reporter.
static void UpdateAmount(MemoryUse action, GLenum format, GLenum type,
int32_t tileWidth, int32_t tileHeight);
static void UpdateAmount(MemoryUse action, size_t amount);
static void UpdateWasteAmount(int32_t delta) {
static void UpdateWasteAmount(size_t delta) {
sTileWasteAmount += delta;
}
@ -52,17 +51,17 @@ public:
nsISupports* aData, bool aAnonymize) override
{
MOZ_COLLECT_REPORT("gfx-tiles-waste", KIND_OTHER, UNITS_BYTES,
sTileWasteAmount,
int64_t(sTileWasteAmount),
"Memory lost due to tiles extending past content boundaries");
return MOZ_COLLECT_REPORT(
"gfx-textures", KIND_OTHER, UNITS_BYTES, sAmount,
"gfx-textures", KIND_OTHER, UNITS_BYTES, int64_t(sAmount),
"Memory used for storing GL textures.");
}
private:
static Atomic<int32_t> sAmount;
static Atomic<size_t> sAmount;
// Count the amount of memory lost to tile waste
static Atomic<int32_t> sTileWasteAmount;
static Atomic<size_t> sTileWasteAmount;
};
class GfxTextureWasteTracker {

View File

@ -207,14 +207,19 @@ TextureImageEGL::DirectUpdate(gfx::DataSourceSurface* aSurf, const nsIntRegion&
region = aRegion;
}
size_t uploadSize = 0;
mTextureFormat =
UploadSurfaceToTexture(mGLContext,
aSurf,
region,
mTexture,
&uploadSize,
mTextureState == Created,
bounds.TopLeft() + gfx::IntPoint(aFrom.x, aFrom.y),
false);
if (uploadSize > 0) {
UpdateUploadSize(uploadSize);
}
mTextureState = Valid;
return true;

View File

@ -53,6 +53,7 @@
#include "Layers.h"
#include "ClientLayerManager.h"
#include "mozilla/layers/LayerManagerComposite.h"
#include "GfxTexturesReporter.h"
#include "GLTextureImage.h"
#include "GLContextProvider.h"
#include "GLContextCGL.h"
@ -2984,11 +2985,13 @@ RectTextureImage::EndUpdate(bool aKeepSurface)
data += srcPoint.y * stride + srcPoint.x * bpp;
UploadImageDataToTexture(mGLContext, data, stride, format,
updateRegion.ToUnknownRegion(), mTexture,
updateRegion.ToUnknownRegion(), mTexture, nullptr,
overwriteTexture, /* aPixelBuffer = */ false,
LOCAL_GL_TEXTURE0,
LOCAL_GL_TEXTURE_RECTANGLE_ARB);
if (!aKeepSurface) {
mUpdateDrawTarget = nullptr;
mUpdateDrawTargetData = nullptr;