aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
authorGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2014-03-07 03:24:41 +0000
committerGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2014-03-07 03:24:41 +0000
commita5572e5bb2a2bbeeb59de0741c2527869d365a0c (patch)
treedcc5ca5a5f15d9cb45e7b4a4681900fb9c41a90d /src/core
parent1d328e46179b12149aec48ccdcf39bd853bb3ec5 (diff)
Add a class to allocate small objects w/o extra calls to new.
Add SkSmallAllocator, a template for allocating small (as defined by the instantiation) objects without extra calls to new. Add a helper macro to make using it simple. Remove SkTemplatesPriv.h, whose behavior is replaced by SkSmallAllocator. The old SK_PLACEMENT_NEW had the following drawbacks: - Easily confused with SkNEW_PLACEMENT. - Requires passing around lots of void*s along with the storageSize. - Requires using a separate class for deleting it. - We had multiple ways Auto objects for deleting in different places. - It always did a straight heap allocation on Windows, meaning Windows did not get any advantages from the confusing code. The new SkSmallAllocator simplifies things: - It is clear about what it does. - It takes care of the deletion in one place that is automatically handled. Further, the new class can be used to create more than one object. This is in preparation for BUG=skia:1976, for which we would like to create a new object without extra heap allocations. The plan is to create both the blitter and the new object on the stack using the SkSmallAllocator. Add a new test for SkSmallAllocator. SkShader.h: Move the private version of CreateBitmapShader to SkBitmapProcShader (which already has the implementation) and remove the friend class (which was only used to call this private function). This allows SkSmallAllocator to reside in the private src/ directory. SkBitmapProcShader: Move CreateBitmapShader and the macro for the storage size here. With the macro in a (private) header, the (private) headers with function declarations (which now depend on the storage size used) can see the macro. Use SkSmallAllocator in CreateBitmapShader. Change the macro to kBlitterStorageByteCount, since SkSmallAllocator takes a byte count as its template parameter. SkBlitter: Use the SkSmallAllocator. Remove Sk3DShader::fKillProc and SkAutoCallProc. Both of their behaviors have been moved into SkSmallAllocator (SkAutoCallProc was unnecessary anyway, because the only time we ever used it we also called detach(), so its auto behavior never happened). Create the Sk3DShader on the stack, if there's room. Remove the helper version of Choose, which was unused. SmallAllocatorTest: Test for the new class. The rest: Use SkSmallAllocator. BUG=skia:1976 R=reed@google.com, mtklein@google.com Author: scroggo@google.com Review URL: https://codereview.chromium.org/179343005 git-svn-id: http://skia.googlecode.com/svn/trunk@13696 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/core')
-rw-r--r--src/core/SkBitmapProcShader.cpp27
-rw-r--r--src/core/SkBitmapProcShader.h11
-rw-r--r--src/core/SkBlitter.cpp104
-rw-r--r--src/core/SkBlitter.h15
-rw-r--r--src/core/SkBlitter_RGB16.cpp25
-rw-r--r--src/core/SkBlitter_Sprite.cpp17
-rw-r--r--src/core/SkCoreBlitters.h8
-rw-r--r--src/core/SkDraw.cpp65
-rw-r--r--src/core/SkShader.cpp10
-rw-r--r--src/core/SkSmallAllocator.h148
-rw-r--r--src/core/SkSpriteBlitter.h9
-rw-r--r--src/core/SkSpriteBlitter_ARGB32.cpp22
-rw-r--r--src/core/SkSpriteBlitter_RGB16.cpp38
-rw-r--r--src/core/SkTemplatesPriv.h76
14 files changed, 290 insertions, 285 deletions
diff --git a/src/core/SkBitmapProcShader.cpp b/src/core/SkBitmapProcShader.cpp
index 74b9e86669..55a772ec10 100644
--- a/src/core/SkBitmapProcShader.cpp
+++ b/src/core/SkBitmapProcShader.cpp
@@ -294,8 +294,6 @@ static bool canUseColorShader(const SkBitmap& bm, SkColor* color) {
return false;
}
-#include "SkTemplatesPriv.h"
-
static bool bitmapIsTooBig(const SkBitmap& bm) {
// SkBitmapProcShader stores bitmap coordinates in a 16bit buffer, as it
// communicates between its matrix-proc and its sampler-proc. Until we can
@@ -306,20 +304,29 @@ static bool bitmapIsTooBig(const SkBitmap& bm) {
return bm.width() > maxSize || bm.height() > maxSize;
}
-SkShader* SkShader::CreateBitmapShader(const SkBitmap& src,
- TileMode tmx, TileMode tmy,
- void* storage, size_t storageSize) {
+SkShader* CreateBitmapShader(const SkBitmap& src, SkShader::TileMode tmx,
+ SkShader::TileMode tmy, SkTBlitterAllocator* allocator) {
SkShader* shader;
SkColor color;
if (src.isNull() || bitmapIsTooBig(src)) {
- SK_PLACEMENT_NEW(shader, SkEmptyShader, storage, storageSize);
+ if (NULL == allocator) {
+ shader = SkNEW(SkEmptyShader);
+ } else {
+ shader = allocator->createT<SkEmptyShader>();
+ }
}
else if (canUseColorShader(src, &color)) {
- SK_PLACEMENT_NEW_ARGS(shader, SkColorShader, storage, storageSize,
- (color));
+ if (NULL == allocator) {
+ shader = SkNEW_ARGS(SkColorShader, (color));
+ } else {
+ shader = allocator->createT<SkColorShader>(color);
+ }
} else {
- SK_PLACEMENT_NEW_ARGS(shader, SkBitmapProcShader, storage,
- storageSize, (src, tmx, tmy));
+ if (NULL == allocator) {
+ shader = SkNEW_ARGS(SkBitmapProcShader, (src, tmx, tmy));
+ } else {
+ shader = allocator->createT<SkBitmapProcShader>(src, tmx, tmy);
+ }
}
return shader;
}
diff --git a/src/core/SkBitmapProcShader.h b/src/core/SkBitmapProcShader.h
index b7e60f1ca1..7a4ddb45ab 100644
--- a/src/core/SkBitmapProcShader.h
+++ b/src/core/SkBitmapProcShader.h
@@ -12,6 +12,7 @@
#include "SkShader.h"
#include "SkBitmapProcState.h"
+#include "SkSmallAllocator.h"
class SkBitmapProcShader : public SkShader {
public:
@@ -48,4 +49,14 @@ private:
typedef SkShader INHERITED;
};
+// Commonly used allocator. It currently is only used to allocate up to 2 objects. The total
+// bytes requested is calculated using one of our large shaders plus the size of an Sk3DBlitter
+// in SkDraw.cpp
+typedef SkSmallAllocator<2, sizeof(SkBitmapProcShader) + sizeof(void*) * 2> SkTBlitterAllocator;
+
+// If alloc is non-NULL, it will be used to allocate the returned SkShader, and MUST outlive
+// the SkShader.
+SkShader* CreateBitmapShader(const SkBitmap& src, SkShader::TileMode, SkShader::TileMode,
+ SkTBlitterAllocator* alloc);
+
#endif
diff --git a/src/core/SkBlitter.cpp b/src/core/SkBlitter.cpp
index 98325c0245..f925eaa7b2 100644
--- a/src/core/SkBlitter.cpp
+++ b/src/core/SkBlitter.cpp
@@ -11,16 +11,16 @@
#include "SkAntiRun.h"
#include "SkColor.h"
#include "SkColorFilter.h"
+#include "SkCoreBlitters.h"
#include "SkFilterShader.h"
#include "SkReadBuffer.h"
#include "SkWriteBuffer.h"
#include "SkMask.h"
#include "SkMaskFilter.h"
-#include "SkTemplatesPriv.h"
+#include "SkString.h"
#include "SkTLazy.h"
#include "SkUtils.h"
#include "SkXfermode.h"
-#include "SkString.h"
SkBlitter::~SkBlitter() {}
@@ -705,15 +705,10 @@ private:
class Sk3DBlitter : public SkBlitter {
public:
- Sk3DBlitter(SkBlitter* proxy, Sk3DShader* shader, void (*killProc)(void*))
- : fProxy(proxy), f3DShader(shader), fKillProc(killProc) {
- shader->ref();
- }
-
- virtual ~Sk3DBlitter() {
- f3DShader->unref();
- fKillProc(fProxy);
- }
+ Sk3DBlitter(SkBlitter* proxy, Sk3DShader* shader)
+ : fProxy(proxy)
+ , f3DShader(SkRef(shader))
+ {}
virtual void blitH(int x, int y, int width) {
fProxy->blitH(x, y, width);
@@ -747,50 +742,15 @@ public:
}
private:
- SkBlitter* fProxy;
- Sk3DShader* f3DShader;
- void (*fKillProc)(void*);
+ // fProxy is unowned. It will be deleted by SkSmallAllocator.
+ SkBlitter* fProxy;
+ SkAutoTUnref<Sk3DShader> f3DShader;
};
///////////////////////////////////////////////////////////////////////////////
#include "SkCoreBlitters.h"
-class SkAutoCallProc {
-public:
- typedef void (*Proc)(void*);
-
- SkAutoCallProc(void* obj, Proc proc)
- : fObj(obj), fProc(proc) {}
-
- ~SkAutoCallProc() {
- if (fObj && fProc) {
- fProc(fObj);
- }
- }
-
- void* get() const { return fObj; }
-
- void* detach() {
- void* obj = fObj;
- fObj = NULL;
- return obj;
- }
-
-private:
- void* fObj;
- Proc fProc;
-};
-#define SkAutoCallProc(...) SK_REQUIRE_LOCAL_VAR(SkAutoCallProc)
-
-static void destroy_blitter(void* blitter) {
- ((SkBlitter*)blitter)->~SkBlitter();
-}
-
-static void delete_blitter(void* blitter) {
- SkDELETE((SkBlitter*)blitter);
-}
-
static bool just_solid_color(const SkPaint& paint) {
if (paint.getAlpha() == 0xFF && paint.getColorFilter() == NULL) {
SkShader* shader = paint.getShader();
@@ -852,9 +812,9 @@ static XferInterp interpret_xfermode(const SkPaint& paint, SkXfermode* xfer,
SkBlitter* SkBlitter::Choose(const SkBitmap& device,
const SkMatrix& matrix,
const SkPaint& origPaint,
- void* storage, size_t storageSize,
+ SkTBlitterAllocator* allocator,
bool drawCoverage) {
- SkASSERT(storageSize == 0 || storage != NULL);
+ SkASSERT(allocator != NULL);
SkBlitter* blitter = NULL;
@@ -862,7 +822,7 @@ SkBlitter* SkBlitter::Choose(const SkBitmap& device,
// (e.g. they have a bounder that always aborts the draw)
if (kUnknown_SkColorType == device.colorType() ||
(drawCoverage && (kAlpha_8_SkColorType != device.colorType()))) {
- SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize);
+ blitter = allocator->createT<SkNullBlitter>();
return blitter;
}
@@ -887,9 +847,10 @@ SkBlitter* SkBlitter::Choose(const SkBitmap& device,
mode = NULL;
paint.writable()->setXfermode(NULL);
break;
- case kSkipDrawing_XferInterp:
- SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize);
+ case kSkipDrawing_XferInterp:{
+ blitter = allocator->createT<SkNullBlitter>();
return blitter;
+ }
default:
break;
}
@@ -940,7 +901,7 @@ SkBlitter* SkBlitter::Choose(const SkBitmap& device,
* not fail) in its destructor.
*/
if (shader && !shader->setContext(device, *paint, matrix)) {
- SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize);
+ blitter = allocator->createT<SkNullBlitter>();
return blitter;
}
@@ -950,49 +911,40 @@ SkBlitter* SkBlitter::Choose(const SkBitmap& device,
if (drawCoverage) {
SkASSERT(NULL == shader);
SkASSERT(NULL == paint->getXfermode());
- SK_PLACEMENT_NEW_ARGS(blitter, SkA8_Coverage_Blitter,
- storage, storageSize, (device, *paint));
+ blitter = allocator->createT<SkA8_Coverage_Blitter>(device, *paint);
} else if (shader) {
- SK_PLACEMENT_NEW_ARGS(blitter, SkA8_Shader_Blitter,
- storage, storageSize, (device, *paint));
+ blitter = allocator->createT<SkA8_Shader_Blitter>(device, *paint);
} else {
- SK_PLACEMENT_NEW_ARGS(blitter, SkA8_Blitter,
- storage, storageSize, (device, *paint));
+ blitter = allocator->createT<SkA8_Blitter>(device, *paint);
}
break;
case kRGB_565_SkColorType:
- blitter = SkBlitter_ChooseD565(device, *paint, storage, storageSize);
+ blitter = SkBlitter_ChooseD565(device, *paint, allocator);
break;
case kPMColor_SkColorType:
if (shader) {
- SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Shader_Blitter,
- storage, storageSize, (device, *paint));
+ blitter = allocator->createT<SkARGB32_Shader_Blitter>(device, *paint);
} else if (paint->getColor() == SK_ColorBLACK) {
- SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Black_Blitter,
- storage, storageSize, (device, *paint));
+ blitter = allocator->createT<SkARGB32_Black_Blitter>(device, *paint);
} else if (paint->getAlpha() == 0xFF) {
- SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Opaque_Blitter,
- storage, storageSize, (device, *paint));
+ blitter = allocator->createT<SkARGB32_Opaque_Blitter>(device, *paint);
} else {
- SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Blitter,
- storage, storageSize, (device, *paint));
+ blitter = allocator->createT<SkARGB32_Blitter>(device, *paint);
}
break;
default:
SkDEBUGFAIL("unsupported device config");
- SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize);
+ blitter = allocator->createT<SkNullBlitter>();
break;
}
if (shader3D) {
- void (*proc)(void*) = ((void*)storage == (void*)blitter) ? destroy_blitter : delete_blitter;
- SkAutoCallProc tmp(blitter, proc);
-
- blitter = SkNEW_ARGS(Sk3DBlitter, (blitter, shader3D, proc));
- (void)tmp.detach();
+ SkBlitter* innerBlitter = blitter;
+ // innerBlitter was allocated by allocator, which will delete it.
+ blitter = allocator->createT<Sk3DBlitter>(innerBlitter, shader3D);
}
return blitter;
}
diff --git a/src/core/SkBlitter.h b/src/core/SkBlitter.h
index b659fe4735..d19a34badc 100644
--- a/src/core/SkBlitter.h
+++ b/src/core/SkBlitter.h
@@ -11,11 +11,14 @@
#define SkBlitter_DEFINED
#include "SkBitmap.h"
+#include "SkBitmapProcShader.h"
+#include "SkMask.h"
#include "SkMatrix.h"
#include "SkPaint.h"
#include "SkRefCnt.h"
#include "SkRegion.h"
-#include "SkMask.h"
+#include "SkShader.h"
+#include "SkSmallAllocator.h"
/** SkBlitter and its subclasses are responsible for actually writing pixels
into memory. Besides efficiency, they handle clipping and antialiasing.
@@ -69,21 +72,15 @@ public:
*/
static SkBlitter* Choose(const SkBitmap& device,
const SkMatrix& matrix,
- const SkPaint& paint) {
- return Choose(device, matrix, paint, NULL, 0);
- }
-
- static SkBlitter* Choose(const SkBitmap& device,
- const SkMatrix& matrix,
const SkPaint& paint,
- void* storage, size_t storageSize,
+ SkTBlitterAllocator*,
bool drawCoverage = false);
static SkBlitter* ChooseSprite(const SkBitmap& device,
const SkPaint&,
const SkBitmap& src,
int left, int top,
- void* storage, size_t storageSize);
+ SkTBlitterAllocator*);
///@}
private:
diff --git a/src/core/SkBlitter_RGB16.cpp b/src/core/SkBlitter_RGB16.cpp
index 256cbc6936..b01800b51f 100644
--- a/src/core/SkBlitter_RGB16.cpp
+++ b/src/core/SkBlitter_RGB16.cpp
@@ -12,7 +12,6 @@
#include "SkColorPriv.h"
#include "SkDither.h"
#include "SkShader.h"
-#include "SkTemplatesPriv.h"
#include "SkUtils.h"
#include "SkXfermode.h"
@@ -1013,7 +1012,9 @@ void SkRGB16_Shader_Xfermode_Blitter::blitAntiH(int x, int y,
///////////////////////////////////////////////////////////////////////////////
SkBlitter* SkBlitter_ChooseD565(const SkBitmap& device, const SkPaint& paint,
- void* storage, size_t storageSize) {
+ SkTBlitterAllocator* allocator) {
+ SkASSERT(allocator != NULL);
+
SkBlitter* blitter;
SkShader* shader = paint.getShader();
SkXfermode* mode = paint.getXfermode();
@@ -1023,31 +1024,25 @@ SkBlitter* SkBlitter_ChooseD565(const SkBitmap& device, const SkPaint& paint,
if (shader) {
if (mode) {
- SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Shader_Xfermode_Blitter,
- storage, storageSize, (device, paint));
+ blitter = allocator->createT<SkRGB16_Shader_Xfermode_Blitter>(device, paint);
} else if (shader->canCallShadeSpan16()) {
- SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Shader16_Blitter,
- storage, storageSize, (device, paint));
+ blitter = allocator->createT<SkRGB16_Shader16_Blitter>(device, paint);
} else {
- SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Shader_Blitter,
- storage, storageSize, (device, paint));
+ blitter = allocator->createT<SkRGB16_Shader_Blitter>(device, paint);
}
} else {
// no shader, no xfermode, (and we always ignore colorfilter)
SkColor color = paint.getColor();
if (0 == SkColorGetA(color)) {
- SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize);
+ blitter = allocator->createT<SkNullBlitter>();
#ifdef USE_BLACK_BLITTER
} else if (SK_ColorBLACK == color) {
- SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Black_Blitter, storage,
- storageSize, (device, paint));
+ blitter = allocator->createT<SkRGB16_Black_Blitter>(device, paint);
#endif
} else if (0xFF == SkColorGetA(color)) {
- SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Opaque_Blitter, storage,
- storageSize, (device, paint));
+ blitter = allocator->createT<SkRGB16_Opaque_Blitter>(device, paint);
} else {
- SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Blitter, storage,
- storageSize, (device, paint));
+ blitter = allocator->createT<SkRGB16_Blitter>(device, paint);
}
}
diff --git a/src/core/SkBlitter_Sprite.cpp b/src/core/SkBlitter_Sprite.cpp
index 86251ff59f..e15e2fcde4 100644
--- a/src/core/SkBlitter_Sprite.cpp
+++ b/src/core/SkBlitter_Sprite.cpp
@@ -1,4 +1,3 @@
-
/*
* Copyright 2006 The Android Open Source Project
*
@@ -6,7 +5,7 @@
* found in the LICENSE file.
*/
-
+#include "SkSmallAllocator.h"
#include "SkSpriteBlitter.h"
SkSpriteBlitter::SkSpriteBlitter(const SkBitmap& source)
@@ -49,11 +48,8 @@ void SkSpriteBlitter::blitMask(const SkMask&, const SkIRect& clip) {
// returning null means the caller will call SkBlitter::Choose() and
// have wrapped the source bitmap inside a shader
-SkBlitter* SkBlitter::ChooseSprite( const SkBitmap& device,
- const SkPaint& paint,
- const SkBitmap& source,
- int left, int top,
- void* storage, size_t storageSize) {
+SkBlitter* SkBlitter::ChooseSprite(const SkBitmap& device, const SkPaint& paint,
+ const SkBitmap& source, int left, int top, SkTBlitterAllocator* allocator) {
/* We currently ignore antialiasing and filtertype, meaning we will take our
special blitters regardless of these settings. Ignoring filtertype seems fine
since by definition there is no scale in the matrix. Ignoring antialiasing is
@@ -63,17 +59,16 @@ SkBlitter* SkBlitter::ChooseSprite( const SkBitmap& device,
paint and return null if it is set, forcing the client to take the slow shader case
(which does respect soft edges).
*/
+ SkASSERT(allocator != NULL);
SkSpriteBlitter* blitter;
switch (device.colorType()) {
case kRGB_565_SkColorType:
- blitter = SkSpriteBlitter::ChooseD16(source, paint, storage,
- storageSize);
+ blitter = SkSpriteBlitter::ChooseD16(source, paint, allocator);
break;
case kPMColor_SkColorType:
- blitter = SkSpriteBlitter::ChooseD32(source, paint, storage,
- storageSize);
+ blitter = SkSpriteBlitter::ChooseD32(source, paint, allocator);
break;
default:
blitter = NULL;
diff --git a/src/core/SkCoreBlitters.h b/src/core/SkCoreBlitters.h
index 1605a5273d..285184050b 100644
--- a/src/core/SkCoreBlitters.h
+++ b/src/core/SkCoreBlitters.h
@@ -8,8 +8,11 @@
#ifndef SkCoreBlitters_DEFINED
#define SkCoreBlitters_DEFINED
+#include "SkBitmapProcShader.h"
#include "SkBlitter.h"
#include "SkBlitRow.h"
+#include "SkShader.h"
+#include "SkSmallAllocator.h"
class SkRasterBlitter : public SkBlitter {
public:
@@ -175,8 +178,7 @@ private:
SkBlitter::Choose(...)
*/
-extern SkBlitter* SkBlitter_ChooseD565(const SkBitmap& device,
- const SkPaint& paint,
- void* storage, size_t storageSize);
+SkBlitter* SkBlitter_ChooseD565(const SkBitmap& device, const SkPaint& paint,
+ SkTBlitterAllocator* allocator);
#endif
diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp
index 175abb6844..05b06453db 100644
--- a/src/core/SkDraw.cpp
+++ b/src/core/SkDraw.cpp
@@ -21,9 +21,9 @@
#include "SkRRect.h"
#include "SkScan.h"
#include "SkShader.h"
+#include "SkSmallAllocator.h"
#include "SkString.h"
#include "SkStroke.h"
-#include "SkTemplatesPriv.h"
#include "SkTLazy.h"
#include "SkUtils.h"
@@ -32,9 +32,9 @@
#include "SkDrawProcs.h"
#include "SkMatrixUtils.h"
+
//#define TRACE_BITMAP_DRAWS
-#define kBlitterStorageLongCount (sizeof(SkBitmapProcShader) >> 2)
/** Helper for allocating small blitters on the stack.
*/
@@ -45,16 +45,8 @@ public:
}
SkAutoBlitterChoose(const SkBitmap& device, const SkMatrix& matrix,
const SkPaint& paint, bool drawCoverage = false) {
- fBlitter = SkBlitter::Choose(device, matrix, paint,
- fStorage, sizeof(fStorage), drawCoverage);
- }
-
- ~SkAutoBlitterChoose() {
- if ((void*)fBlitter == (void*)fStorage) {
- fBlitter->~SkBlitter();
- } else {
- SkDELETE(fBlitter);
- }
+ fBlitter = SkBlitter::Choose(device, matrix, paint, &fAllocator,
+ drawCoverage);
}
SkBlitter* operator->() { return fBlitter; }
@@ -63,13 +55,13 @@ public:
void choose(const SkBitmap& device, const SkMatrix& matrix,
const SkPaint& paint) {
SkASSERT(!fBlitter);
- fBlitter = SkBlitter::Choose(device, matrix, paint,
- fStorage, sizeof(fStorage));
+ fBlitter = SkBlitter::Choose(device, matrix, paint, &fAllocator);
}
private:
- SkBlitter* fBlitter;
- uint32_t fStorage[kBlitterStorageLongCount];
+ // Owned by fAllocator, which will handle the delete.
+ SkBlitter* fBlitter;
+ SkTBlitterAllocator fAllocator;
};
#define SkAutoBlitterChoose(...) SK_REQUIRE_LOCAL_VAR(SkAutoBlitterChoose)
@@ -82,34 +74,29 @@ class SkAutoBitmapShaderInstall : SkNoncopyable {
public:
SkAutoBitmapShaderInstall(const SkBitmap& src, const SkPaint& paint)
: fPaint(paint) /* makes a copy of the paint */ {
- fPaint.setShader(SkShader::CreateBitmapShader(src,
- SkShader::kClamp_TileMode, SkShader::kClamp_TileMode,
- fStorage, sizeof(fStorage)));
+ fPaint.setShader(CreateBitmapShader(src, SkShader::kClamp_TileMode,
+ SkShader::kClamp_TileMode,
+ &fAllocator));
// we deliberately left the shader with an owner-count of 2
SkASSERT(2 == fPaint.getShader()->getRefCnt());
}
~SkAutoBitmapShaderInstall() {
- SkShader* shader = fPaint.getShader();
- // since we manually destroy shader, we insist that owners == 2
- SkASSERT(2 == shader->getRefCnt());
+ // since fAllocator will destroy shader, we insist that owners == 2
+ SkASSERT(2 == fPaint.getShader()->getRefCnt());
fPaint.setShader(NULL); // unref the shader by 1
- // now destroy to take care of the 2nd owner-count
- if ((void*)shader == (void*)fStorage) {
- shader->~SkShader();
- } else {
- SkDELETE(shader);
- }
}
// return the new paint that has the shader applied
const SkPaint& paintWithShader() const { return fPaint; }
private:
- SkPaint fPaint; // copy of caller's paint (which we then modify)
- uint32_t fStorage[kBlitterStorageLongCount];
+ // copy of caller's paint (which we then modify)
+ SkPaint fPaint;
+ // Stores the shader.
+ SkTBlitterAllocator fAllocator;
};
#define SkAutoBitmapShaderInstall(...) SK_REQUIRE_LOCAL_VAR(SkAutoBitmapShaderInstall)
@@ -1323,12 +1310,11 @@ void SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix,
int ix = SkScalarRoundToInt(matrix.getTranslateX());
int iy = SkScalarRoundToInt(matrix.getTranslateY());
if (clipHandlesSprite(*fRC, ix, iy, bitmap)) {
- uint32_t storage[kBlitterStorageLongCount];
- SkBlitter* blitter = SkBlitter::ChooseSprite(*fBitmap, paint, bitmap,
- ix, iy, storage, sizeof(storage));
+ SkTBlitterAllocator allocator;
+ // blitter will be owned by the allocator.
+ SkBlitter* blitter = SkBlitter::ChooseSprite(*fBitmap, paint, bitmap,
+ ix, iy, &allocator);
if (blitter) {
- SkAutoTPlacementDelete<SkBlitter> ad(blitter, storage);
-
SkIRect ir;
ir.set(ix, iy, ix + bitmap.width(), iy + bitmap.height());
@@ -1378,13 +1364,12 @@ void SkDraw::drawSprite(const SkBitmap& bitmap, int x, int y,
paint.setStyle(SkPaint::kFill_Style);
if (NULL == paint.getColorFilter() && clipHandlesSprite(*fRC, x, y, bitmap)) {
- uint32_t storage[kBlitterStorageLongCount];
- SkBlitter* blitter = SkBlitter::ChooseSprite(*fBitmap, paint, bitmap,
- x, y, storage, sizeof(storage));
+ SkTBlitterAllocator allocator;
+ // blitter will be owned by the allocator.
+ SkBlitter* blitter = SkBlitter::ChooseSprite(*fBitmap, paint, bitmap,
+ x, y, &allocator);
if (blitter) {
- SkAutoTPlacementDelete<SkBlitter> ad(blitter, storage);
-
if (fBounder && !fBounder->doIRect(bounds)) {
return;
}
diff --git a/src/core/SkShader.cpp b/src/core/SkShader.cpp
index 47889f0d09..b06e0c26ff 100644
--- a/src/core/SkShader.cpp
+++ b/src/core/SkShader.cpp
@@ -5,13 +5,13 @@
* found in the LICENSE file.
*/
-
+#include "SkBitmapProcShader.h"
+#include "SkReadBuffer.h"
+#include "SkMallocPixelRef.h"
+#include "SkPaint.h"
#include "SkScalar.h"
#include "SkShader.h"
-#include "SkReadBuffer.h"
#include "SkWriteBuffer.h"
-#include "SkPaint.h"
-#include "SkMallocPixelRef.h"
SkShader::SkShader() {
fLocalMatrix.reset();
@@ -176,7 +176,7 @@ GrEffectRef* SkShader::asNewEffect(GrContext*, const SkPaint&) const {
SkShader* SkShader::CreateBitmapShader(const SkBitmap& src,
TileMode tmx, TileMode tmy) {
- return SkShader::CreateBitmapShader(src, tmx, tmy, NULL, 0);
+ return ::CreateBitmapShader(src, tmx, tmy, NULL);
}
#ifdef SK_DEVELOPER
diff --git a/src/core/SkSmallAllocator.h b/src/core/SkSmallAllocator.h
new file mode 100644
index 0000000000..d5ebf3b7d4
--- /dev/null
+++ b/src/core/SkSmallAllocator.h
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2014 Google, Inc
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSmallAllocator_DEFINED
+#define SkSmallAllocator_DEFINED
+
+#include "SkTDArray.h"
+#include "SkTypes.h"
+
+// Used by SkSmallAllocator to call the destructor for objects it has
+// allocated.
+template<typename T> void destroyT(void* ptr) {
+ static_cast<T*>(ptr)->~T();
+}
+
+/*
+ * Template class for allocating small objects without additional heap memory
+ * allocations. kMaxObjects is a hard limit on the number of objects that can
+ * be allocated using this class. After that, attempts to create more objects
+ * with this class will assert and return NULL.
+ * kTotalBytes is the total number of bytes provided for storage for all
+ * objects created by this allocator. If an object to be created is larger
+ * than the storage (minus storage already used), it will be allocated on the
+ * heap. This class's destructor will handle calling the destructor for each
+ * object it allocated and freeing its memory.
+ */
+template<uint32_t kMaxObjects, size_t kTotalBytes>
+class SkSmallAllocator : public SkNoncopyable {
+public:
+ SkSmallAllocator()
+ : fStorageUsed(0)
+ , fNumObjects(0)
+ {}
+
+ ~SkSmallAllocator() {
+ // Destruct in reverse order, in case an earlier object points to a
+ // later object.
+ while (fNumObjects > 0) {
+ fNumObjects--;
+ Rec* rec = &fRecs[fNumObjects];
+ rec->fKillProc(rec->fObj);
+ // Safe to do if fObj is in fStorage, since fHeapStorage will
+ // point to NULL.
+ sk_free(rec->fHeapStorage);
+ }
+ }
+
+ /*
+ * Create a new object of type T. Its lifetime will be handled by this
+ * SkSmallAllocator.
+ * Each version behaves the same but takes a different number of
+ * arguments.
+ * Note: If kMaxObjects have been created by this SkSmallAllocator, NULL
+ * will be returned.
+ */
+ template<typename T>
+ T* createT() {
+ void* buf = this->reserveT<T>();
+ if (NULL == buf) {
+ return NULL;
+ }
+ SkNEW_PLACEMENT(buf, T);
+ return static_cast<T*>(buf);
+ }
+
+ template<typename T, typename A1> T* createT(const A1& a1) {
+ void* buf = this->reserveT<T>();
+ if (NULL == buf) {
+ return NULL;
+ }
+ SkNEW_PLACEMENT_ARGS(buf, T, (a1));
+ return static_cast<T*>(buf);
+ }
+
+ template<typename T, typename A1, typename A2>
+ T* createT(const A1& a1, const A2& a2) {
+ void* buf = this->reserveT<T>();
+ if (NULL == buf) {
+ return NULL;
+ }
+ SkNEW_PLACEMENT_ARGS(buf, T, (a1, a2));
+ return static_cast<T*>(buf);
+ }
+
+ template<typename T, typename A1, typename A2, typename A3>
+ T* createT(const A1& a1, const A2& a2, const A3& a3) {
+ void* buf = this->reserveT<T>();
+ if (NULL == buf) {
+ return NULL;
+ }
+ SkNEW_PLACEMENT_ARGS(buf, T, (a1, a2, a3));
+ return static_cast<T*>(buf);
+ }
+
+private:
+ /*
+ * Helper function to provide space for one T. The space will be in
+ * fStorage if there is room, or on the heap otherwise. Either way, this
+ * class will call ~T() in its destructor and free the heap allocation if
+ * necessary.
+ */
+ template<typename T> void* reserveT() {
+ SkASSERT(fNumObjects < kMaxObjects);
+ if (kMaxObjects == fNumObjects) {
+ return NULL;
+ }
+ const size_t storageRemaining = SkAlign4(kTotalBytes) - fStorageUsed;
+ const size_t storageRequired = SkAlign4(sizeof(T));
+ Rec* rec = &fRecs[fNumObjects];
+ if (storageRequired > storageRemaining) {
+ // Allocate on the heap. Ideally we want to avoid this situation,
+ // but we're not sure we can catch all callers, so handle it but
+ // assert false in debug mode.
+ SkASSERT(false);
+ rec->fHeapStorage = sk_malloc_throw(storageRequired);
+ rec->fObj = static_cast<void*>(rec->fHeapStorage);
+ } else {
+ // There is space in fStorage.
+ rec->fHeapStorage = NULL;
+ SkASSERT(SkIsAlign4(fStorageUsed));
+ rec->fObj = static_cast<void*>(fStorage + (fStorageUsed / 4));
+ fStorageUsed += storageRequired;
+ }
+ rec->fKillProc = destroyT<T>;
+ fNumObjects++;
+ return rec->fObj;
+ }
+
+private:
+ struct Rec {
+ void* fObj;
+ void* fHeapStorage;
+ void (*fKillProc)(void*);
+ };
+
+ // Number of bytes used so far.
+ size_t fStorageUsed;
+ // Pad the storage size to be 4-byte aligned.
+ uint32_t fStorage[SkAlign4(kTotalBytes) >> 2];
+ uint32_t fNumObjects;
+ Rec fRecs[kMaxObjects];
+};
+
+#endif // SkSmallAllocator_DEFINED
diff --git a/src/core/SkSpriteBlitter.h b/src/core/SkSpriteBlitter.h
index ae79afe1d8..f69a55a2a0 100644
--- a/src/core/SkSpriteBlitter.h
+++ b/src/core/SkSpriteBlitter.h
@@ -10,8 +10,11 @@
#ifndef SkSpriteBlitter_DEFINED
#define SkSpriteBlitter_DEFINED
-#include "SkBlitter.h"
#include "SkBitmap.h"
+#include "SkBitmapProcShader.h"
+#include "SkBlitter.h"
+#include "SkShader.h"
+#include "SkSmallAllocator.h"
class SkPaint;
@@ -32,9 +35,9 @@ public:
#endif
static SkSpriteBlitter* ChooseD16(const SkBitmap& source, const SkPaint&,
- void* storage, size_t storageSize);
+ SkTBlitterAllocator*);
static SkSpriteBlitter* ChooseD32(const SkBitmap& source, const SkPaint&,
- void* storage, size_t storageSize);
+ SkTBlitterAllocator*);
protected:
const SkBitmap* fDevice;
diff --git a/src/core/SkSpriteBlitter_ARGB32.cpp b/src/core/SkSpriteBlitter_ARGB32.cpp
index 3e8612dda3..b05e5033e4 100644
--- a/src/core/SkSpriteBlitter_ARGB32.cpp
+++ b/src/core/SkSpriteBlitter_ARGB32.cpp
@@ -263,11 +263,10 @@ public:
///////////////////////////////////////////////////////////////////////////////
-#include "SkTemplatesPriv.h"
+SkSpriteBlitter* SkSpriteBlitter::ChooseD32(const SkBitmap& source, const SkPaint& paint,
+ SkTBlitterAllocator* allocator) {
+ SkASSERT(allocator != NULL);
-SkSpriteBlitter* SkSpriteBlitter::ChooseD32(const SkBitmap& source,
- const SkPaint& paint,
- void* storage, size_t storageSize) {
if (paint.getMaskFilter() != NULL) {
return NULL;
}
@@ -283,27 +282,22 @@ SkSpriteBlitter* SkSpriteBlitter::ChooseD32(const SkBitmap& source,
return NULL; // we only have opaque sprites
}
if (xfermode || filter) {
- SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D32_S4444_XferFilter,
- storage, storageSize, (source, paint));
+ blitter = allocator->createT<Sprite_D32_S4444_XferFilter>(source, paint);
} else if (source.isOpaque()) {
- SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D32_S4444_Opaque,
- storage, storageSize, (source));
+ blitter = allocator->createT<Sprite_D32_S4444_Opaque>(source);
} else {
- SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D32_S4444,
- storage, storageSize, (source));
+ blitter = allocator->createT<Sprite_D32_S4444>(source);
}
break;
case kPMColor_SkColorType:
if (xfermode || filter) {
if (255 == alpha) {
// this can handle xfermode or filter, but not alpha
- SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D32_S32A_XferFilter,
- storage, storageSize, (source, paint));
+ blitter = allocator->createT<Sprite_D32_S32A_XferFilter>(source, paint);
}
} else {
// this can handle alpha, but not xfermode or filter
- SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D32_S32,
- storage, storageSize, (source, alpha));
+ blitter = allocator->createT<Sprite_D32_S32>(source, alpha);
}
break;
default:
diff --git a/src/core/SkSpriteBlitter_RGB16.cpp b/src/core/SkSpriteBlitter_RGB16.cpp
index 7428c8a74a..74c1961dbd 100644
--- a/src/core/SkSpriteBlitter_RGB16.cpp
+++ b/src/core/SkSpriteBlitter_RGB16.cpp
@@ -306,11 +306,11 @@ private:
///////////////////////////////////////////////////////////////////////////////
-#include "SkTemplatesPriv.h"
+SkSpriteBlitter* SkSpriteBlitter::ChooseD16(const SkBitmap& source, const SkPaint& paint,
+ SkTBlitterAllocator* allocator) {
+
+ SkASSERT(allocator != NULL);
-SkSpriteBlitter* SkSpriteBlitter::ChooseD16(const SkBitmap& source,
- const SkPaint& paint,
- void* storage, size_t storageSize) {
if (paint.getMaskFilter() != NULL) { // may add cases for this
return NULL;
}
@@ -325,26 +325,22 @@ SkSpriteBlitter* SkSpriteBlitter::ChooseD16(const SkBitmap& source,
unsigned alpha = paint.getAlpha();
switch (source.colorType()) {
- case kPMColor_SkColorType:
- SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S32_BlitRowProc,
- storage, storageSize, (source));
+ case kPMColor_SkColorType: {
+ blitter = allocator->createT<Sprite_D16_S32_BlitRowProc>(source);
break;
+ }
case kARGB_4444_SkColorType:
if (255 == alpha) {
- SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S4444_Opaque,
- storage, storageSize, (source));
+ blitter = allocator->createT<Sprite_D16_S4444_Opaque>(source);
} else {
- SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S4444_Blend,
- storage, storageSize, (source, alpha >> 4));
+ blitter = allocator->createT<Sprite_D16_S4444_Blend>(source, alpha >> 4);
}
break;
case kRGB_565_SkColorType:
if (255 == alpha) {
- SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S16_Opaque,
- storage, storageSize, (source));
+ blitter = allocator->createT<Sprite_D16_S16_Opaque>(source);
} else {
- SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S16_Blend,
- storage, storageSize, (source, alpha));
+ blitter = allocator->createT<Sprite_D16_S16_Blend>(source, alpha);
}
break;
case kIndex_8_SkColorType:
@@ -354,19 +350,15 @@ SkSpriteBlitter* SkSpriteBlitter::ChooseD16(const SkBitmap& source,
}
if (source.isOpaque()) {
if (255 == alpha) {
- SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_SIndex8_Opaque,
- storage, storageSize, (source));
+ blitter = allocator->createT<Sprite_D16_SIndex8_Opaque>(source);
} else {
- SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_SIndex8_Blend,
- storage, storageSize, (source, alpha));
+ blitter = allocator->createT<Sprite_D16_SIndex8_Blend>(source, alpha);
}
} else {
if (255 == alpha) {
- SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_SIndex8A_Opaque,
- storage, storageSize, (source));
+ blitter = allocator->createT<Sprite_D16_SIndex8A_Opaque>(source);
} else {
- SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_SIndex8A_Blend,
- storage, storageSize, (source, alpha));
+ blitter = allocator->createT<Sprite_D16_SIndex8A_Blend>(source, alpha);
}
}
break;
diff --git a/src/core/SkTemplatesPriv.h b/src/core/SkTemplatesPriv.h
deleted file mode 100644
index 79ae609335..0000000000
--- a/src/core/SkTemplatesPriv.h
+++ /dev/null
@@ -1,76 +0,0 @@
-
-/*
- * Copyright 2006 The Android Open Source Project
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-
-#ifndef SkTemplatesPriv_DEFINED
-#define SkTemplatesPriv_DEFINED
-
-#include "SkTemplates.h"
-
-////////////////////////////////////////////////////////////////////////////////
-
-#ifdef SK_BUILD_FOR_WIN32
- #define SK_PLACEMENT_NEW(result, classname, storage, storageSize) \
- result = SkNEW(classname)
-
- #define SK_PLACEMENT_NEW_ARGS(result, classname, storage, storageSize, args) \
- result = SkNEW_ARGS(classname, args)
-#else
- #include <new>
- #define SK_PLACEMENT_NEW(result, classname, storage, storagesize) \
- do { \
- if (storagesize) \
- { \
- SkASSERT(storageSize >= sizeof(classname)); \
- result = new(storage) classname; \
- } \
- else \
- result = SkNEW(classname); \
- } while (0)
-
- #define SK_PLACEMENT_NEW_ARGS(result, classname, storage, storagesize, args) \
- do { \
- if (storagesize) \
- { \
- SkASSERT(storageSize >= sizeof(classname)); \
- result = new(storage) classname args; \
- } \
- else \
- result = SkNEW_ARGS(classname, args); \
- } while (0)
-#endif
-
-////////////////////////////////////////////////////////////////////////////////
-
-template <class T> class SkAutoTPlacementDelete {
-public:
- SkAutoTPlacementDelete(T* obj, void* storage) : fObj(obj), fStorage(storage)
- {
- }
- ~SkAutoTPlacementDelete()
- {
- if (fObj)
- {
- if (fObj == fStorage)
- fObj->~T();
- else
- delete fObj;
- }
- }
- T* detach()
- {
- T* obj = fObj;
- fObj = NULL;
- return obj;
- }
-private:
- T* fObj;
- void* fStorage;
-};
-
-#endif