Bug 815473 - Replace runtime computed sUnpremultiplyTable/sPremultiplyTable with constants. r=roc

This commit is contained in:
Ting-Yuan Huang 2012-12-16 19:20:01 -05:00
parent 8b51d4f17e
commit daa4759375
5 changed files with 38 additions and 111 deletions

View File

@ -525,8 +525,6 @@ NS_INTERFACE_MAP_END
// Initialize our static variables.
uint32_t CanvasRenderingContext2D::sNumLivingContexts = 0;
uint8_t (*CanvasRenderingContext2D::sUnpremultiplyTable)[256] = nullptr;
uint8_t (*CanvasRenderingContext2D::sPremultiplyTable)[256] = nullptr;
DrawTarget* CanvasRenderingContext2D::sErrorTarget = nullptr;
@ -551,10 +549,6 @@ CanvasRenderingContext2D::~CanvasRenderingContext2D()
}
sNumLivingContexts--;
if (!sNumLivingContexts) {
delete[] sUnpremultiplyTable;
delete[] sPremultiplyTable;
sUnpremultiplyTable = nullptr;
sPremultiplyTable = nullptr;
NS_IF_RELEASE(sErrorTarget);
}
}
@ -3325,33 +3319,6 @@ CanvasRenderingContext2D::AsyncDrawXULElement(nsIDOMXULElement* elem,
// device pixel getting/setting
//
void
CanvasRenderingContext2D::EnsureUnpremultiplyTable() {
if (sUnpremultiplyTable)
return;
// Infallably alloc the unpremultiply table.
sUnpremultiplyTable = new uint8_t[256][256];
// It's important that the array be indexed first by alpha and then by rgb
// value. When we unpremultiply a pixel, we're guaranteed to do three
// lookups with the same alpha; indexing by alpha first makes it likely that
// those three lookups will be close to one another in memory, thus
// increasing the chance of a cache hit.
// a == 0 case
for (uint32_t c = 0; c <= 255; c++) {
sUnpremultiplyTable[0][c] = c;
}
for (int a = 1; a <= 255; a++) {
for (int c = 0; c <= 255; c++) {
sUnpremultiplyTable[a][c] = (uint8_t)((c * 255) / a);
}
}
}
already_AddRefed<ImageData>
CanvasRenderingContext2D::GetImageData(JSContext* aCx, double aSx,
double aSy, double aSw,
@ -3484,9 +3451,6 @@ CanvasRenderingContext2D::GetImageDataArray(JSContext* aCx,
}
}
// make sure sUnpremultiplyTable has been created
EnsureUnpremultiplyTable();
// NOTE! dst is the same as src, and this relies on reading
// from src and advancing that ptr before writing to dst.
// NOTE! I'm not sure that it is, I think this comment might have been
@ -3508,9 +3472,9 @@ CanvasRenderingContext2D::GetImageDataArray(JSContext* aCx,
uint8_t b = *src++;
#endif
// Convert to non-premultiplied color
*dst++ = sUnpremultiplyTable[a][r];
*dst++ = sUnpremultiplyTable[a][g];
*dst++ = sUnpremultiplyTable[a][b];
*dst++ = gfxUtils::sUnpremultiplyTable[a * 256 + r];
*dst++ = gfxUtils::sUnpremultiplyTable[a * 256 + g];
*dst++ = gfxUtils::sUnpremultiplyTable[a * 256 + b];
*dst++ = a;
}
src += srcStride - (dstWriteRect.width * 4);
@ -3521,25 +3485,6 @@ CanvasRenderingContext2D::GetImageDataArray(JSContext* aCx,
return NS_OK;
}
void
CanvasRenderingContext2D::EnsurePremultiplyTable() {
if (sPremultiplyTable)
return;
// Infallably alloc the premultiply table.
sPremultiplyTable = new uint8_t[256][256];
// Like the unpremultiply table, it's important that we index the premultiply
// table with the alpha value as the first index to ensure good cache
// performance.
for (int a = 0; a <= 255; a++) {
for (int c = 0; c <= 255; c++) {
sPremultiplyTable[a][c] = (a * c + 254) / 255;
}
}
}
void
CanvasRenderingContext2D::EnsureErrorTarget()
{
@ -3662,9 +3607,6 @@ CanvasRenderingContext2D::PutImageData_explicit(int32_t x, int32_t y, uint32_t w
return NS_ERROR_FAILURE;
}
// ensure premultiply table has been created
EnsurePremultiplyTable();
uint8_t *src = aData;
uint8_t *dst = imgsurf->Data();
@ -3677,15 +3619,15 @@ CanvasRenderingContext2D::PutImageData_explicit(int32_t x, int32_t y, uint32_t w
// Convert to premultiplied color (losslessly if the input came from getImageData)
#ifdef IS_LITTLE_ENDIAN
*dst++ = sPremultiplyTable[a][b];
*dst++ = sPremultiplyTable[a][g];
*dst++ = sPremultiplyTable[a][r];
*dst++ = gfxUtils::sPremultiplyTable[a * 256 + b];
*dst++ = gfxUtils::sPremultiplyTable[a * 256 + g];
*dst++ = gfxUtils::sPremultiplyTable[a * 256 + r];
*dst++ = a;
#else
*dst++ = a;
*dst++ = sPremultiplyTable[a][r];
*dst++ = sPremultiplyTable[a][g];
*dst++ = sPremultiplyTable[a][b];
*dst++ = gfxUtils::sPremultiplyTable[a * 256 + r];
*dst++ = gfxUtils::sPremultiplyTable[a * 256 + g];
*dst++ = gfxUtils::sPremultiplyTable[a * 256 + b];
#endif
}
}

View File

@ -393,3 +393,9 @@ ifdef SOLARIS_SUNPRO_CXX
gfxAlphaRecoverySSE2.$(OBJ_SUFFIX): OS_CXXFLAGS += -xarch=sse2 -xO4
endif
endif
.PHONY: CONSTANT_TABLES
CONSTANT_TABLES:
$(PYTHON) $(srcdir)/genTables.py
gfxUtils.$(OBJ_SUFFIX): CONSTANT_TABLES

12
gfx/thebes/genTables.py Normal file
View File

@ -0,0 +1,12 @@
#!/usr/bin/python
def table_generator(f):
return ",\n".join([", ".join(["0x%2.2x" % h for h in [f(i) for i in range(r,r+16)]]) for r in range(0, 65536, 16)])
f = open("sPremultiplyTable.h", "w")
f.write(table_generator(lambda i: ((i / 256) * (i % 256) + 254) / 255) + "\n")
f.close()
f = open("sUnpremultiplyTable.h", "w")
f.write(table_generator(lambda i: (i % 256) * 255 / ((i / 256) if (i / 256) > 0 else 255) % 256) + "\n")
f.close()

View File

@ -20,49 +20,20 @@ using namespace mozilla;
using namespace mozilla::layers;
using namespace mozilla::gfx;
static uint8_t sUnpremultiplyTable[256*256];
static uint8_t sPremultiplyTable[256*256];
static bool sTablesInitialized = false;
const uint8_t gfxUtils::sPremultiplyTable[256*256] = {
#include "sPremultiplyTable.h"
};
const uint8_t gfxUtils::sUnpremultiplyTable[256*256] = {
#include "sUnpremultiplyTable.h"
};
static const uint8_t PremultiplyValue(uint8_t a, uint8_t v) {
return sPremultiplyTable[a*256+v];
return gfxUtils::sPremultiplyTable[a*256+v];
}
static const uint8_t UnpremultiplyValue(uint8_t a, uint8_t v) {
return sUnpremultiplyTable[a*256+v];
}
static void
CalculateTables()
{
// It's important that the array be indexed first by alpha and then by rgb
// value. When we unpremultiply a pixel, we're guaranteed to do three
// lookups with the same alpha; indexing by alpha first makes it likely that
// those three lookups will be close to one another in memory, thus
// increasing the chance of a cache hit.
// Unpremultiply table
// a == 0 case
for (uint32_t c = 0; c <= 255; c++) {
sUnpremultiplyTable[c] = c;
}
for (int a = 1; a <= 255; a++) {
for (int c = 0; c <= 255; c++) {
sUnpremultiplyTable[a*256+c] = (uint8_t)((c * 255) / a);
}
}
// Premultiply table
for (int a = 0; a <= 255; a++) {
for (int c = 0; c <= 255; c++) {
sPremultiplyTable[a*256+c] = (a * c + 254) / 255;
}
}
sTablesInitialized = true;
return gfxUtils::sUnpremultiplyTable[a*256+v];
}
void
@ -90,9 +61,6 @@ gfxUtils::PremultiplyImageSurface(gfxImageSurface *aSourceSurface,
return;
}
if (!sTablesInitialized)
CalculateTables();
uint8_t *src = aSourceSurface->Data();
uint8_t *dst = aDestSurface->Data();
@ -147,9 +115,6 @@ gfxUtils::UnpremultiplyImageSurface(gfxImageSurface *aSourceSurface,
return;
}
if (!sTablesInitialized)
CalculateTables();
uint8_t *src = aSourceSurface->Data();
uint8_t *dst = aDestSurface->Data();

View File

@ -125,6 +125,8 @@ public:
unsigned char* aDestBuffer,
int32_t aStride);
static const uint8_t sUnpremultiplyTable[256*256];
static const uint8_t sPremultiplyTable[256*256];
#ifdef MOZ_DUMP_PAINTING
/**
* Writes a binary PNG file.