use pixmaps for dst in sprites -- NO BITMAPS

BUG=skia:
TBR=scroggo@google.com

Review URL: https://codereview.chromium.org/1143173011
This commit is contained in:
reed 2015-06-05 06:58:22 -07:00 committed by Commit bot
parent 89d59883f3
commit cb67414454
10 changed files with 95 additions and 41 deletions

View File

@ -654,6 +654,17 @@ public:
bool extractAlpha(SkBitmap* dst, const SkPaint* paint, Allocator* allocator,
SkIPoint* offset) const;
/**
* If the pixels are available from this bitmap (w/o locking) return true, and fill out the
* specified pixmap (if not null). If the pixels are not available (either because there are
* none, or becuase accessing them would require locking or other machinary) return false and
* ignore the pixmap parameter.
*
* Note: if this returns true, the results (in the pixmap) are only valid until the bitmap
* is changed in anyway, in which case the results are invalid.
*/
bool peekPixels(SkPixmap*) const;
SkDEBUGCODE(void validate() const;)
class Allocator : public SkRefCnt {

View File

@ -1388,6 +1388,16 @@ bool SkBitmap::requestLock(SkAutoPixmapUnlock* result) const {
return false;
}
bool SkBitmap::peekPixels(SkPixmap* pmap) const {
if (fPixels) {
if (pmap) {
pmap->reset(fInfo, fPixels, fRowBytes, fColorTable);
}
return true;
}
return false;
}
///////////////////////////////////////////////////////////////////////////////
#ifdef SK_DEBUG

View File

@ -128,7 +128,7 @@ public:
SkTBlitterAllocator*,
bool drawCoverage = false);
static SkBlitter* ChooseSprite(const SkBitmap& device,
static SkBlitter* ChooseSprite(const SkPixmap& dst,
const SkPaint&,
const SkPixmap& src,
int left, int top,

View File

@ -10,8 +10,8 @@
SkSpriteBlitter::SkSpriteBlitter(const SkPixmap& source) : fSource(source) {}
void SkSpriteBlitter::setup(const SkBitmap& device, int left, int top, const SkPaint& paint) {
fDevice = &device;
void SkSpriteBlitter::setup(const SkPixmap& dst, int left, int top, const SkPaint& paint) {
fDst = dst;
fLeft = left;
fTop = top;
fPaint = &paint;
@ -40,7 +40,7 @@ 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,
SkBlitter* SkBlitter::ChooseSprite(const SkPixmap& dst, const SkPaint& paint,
const SkPixmap& 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
@ -55,7 +55,7 @@ SkBlitter* SkBlitter::ChooseSprite(const SkBitmap& device, const SkPaint& paint,
SkSpriteBlitter* blitter;
switch (device.colorType()) {
switch (dst.colorType()) {
case kRGB_565_SkColorType:
blitter = SkSpriteBlitter::ChooseD16(source, paint, allocator);
break;
@ -68,7 +68,7 @@ SkBlitter* SkBlitter::ChooseSprite(const SkBitmap& device, const SkPaint& paint,
}
if (blitter) {
blitter->setup(device, left, top, paint);
blitter->setup(dst, left, top, paint);
}
return blitter;
}

View File

@ -1280,9 +1280,13 @@ void SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix,
int ix = SkScalarRoundToInt(matrix.getTranslateX());
int iy = SkScalarRoundToInt(matrix.getTranslateY());
if (clipHandlesSprite(*fRC, ix, iy, pmap)) {
SkPixmap dstPM;
if (!fBitmap->peekPixels(&dstPM)) {
return;
}
SkTBlitterAllocator allocator;
// blitter will be owned by the allocator.
SkBlitter* blitter = SkBlitter::ChooseSprite(*fBitmap, paint, pmap, ix, iy, &allocator);
SkBlitter* blitter = SkBlitter::ChooseSprite(dstPM, paint, pmap, ix, iy, &allocator);
if (blitter) {
SkScan::FillIRect(SkIRect::MakeXYWH(ix, iy, pmap.width(), pmap.height()),
*fRC, blitter);
@ -1337,9 +1341,13 @@ void SkDraw::drawSprite(const SkBitmap& bitmap, int x, int y, const SkPaint& ori
const SkPixmap& pmap = unlocker.pixmap();
if (NULL == paint.getColorFilter() && clipHandlesSprite(*fRC, x, y, pmap)) {
SkPixmap dstPM;
if (!fBitmap->peekPixels(&dstPM)) {
return;
}
SkTBlitterAllocator allocator;
// blitter will be owned by the allocator.
SkBlitter* blitter = SkBlitter::ChooseSprite(*fBitmap, paint, pmap, x, y, &allocator);
SkBlitter* blitter = SkBlitter::ChooseSprite(dstPM, paint, pmap, x, y, &allocator);
if (blitter) {
SkScan::FillIRect(bounds, *fRC, blitter);
return;

View File

@ -8,9 +8,8 @@
#ifndef SkSpriteBlitter_DEFINED
#define SkSpriteBlitter_DEFINED
#include "SkBitmap.h"
#include "SkBitmapProcShader.h"
#include "SkBlitter.h"
#include "SkPixmap.h"
#include "SkShader.h"
#include "SkSmallAllocator.h"
@ -20,7 +19,7 @@ class SkSpriteBlitter : public SkBlitter {
public:
SkSpriteBlitter(const SkPixmap& source);
virtual void setup(const SkBitmap& device, int left, int top, const SkPaint&);
virtual void setup(const SkPixmap& dst, int left, int top, const SkPaint&);
#ifdef SK_DEBUG
void blitH(int x, int y, int width) override;
@ -33,7 +32,7 @@ public:
static SkSpriteBlitter* ChooseD32(const SkPixmap& source, const SkPaint&, SkTBlitterAllocator*);
protected:
const SkBitmap* fDevice;
SkPixmap fDst;
const SkPixmap fSource;
int fLeft, fTop;
const SkPaint* fPaint;

View File

@ -15,12 +15,12 @@ public:
SkASSERT(width > 0 && height > 0);
int srcX = x - fLeft;
int srcY = y - fTop;
SkSPRITE_DST_TYPE* SK_RESTRICT dst =fDevice->SkSPRITE_DST_GETADDR(x, y);
SkSPRITE_DST_TYPE* SK_RESTRICT dst =fDst.SkSPRITE_DST_GETADDR(x, y);
const SkSPRITE_SRC_TYPE* SK_RESTRICT src = fSource.SkSPRITE_SRC_GETADDR(srcX, srcY);
size_t dstRB = fDevice->rowBytes();
size_t dstRB = fDst.rowBytes();
size_t srcRB = fSource.rowBytes();
SkDEBUGCODE((void)fDevice->SkSPRITE_DST_GETADDR(x + width - 1, y + height - 1);)
SkDEBUGCODE((void)fDst.SkSPRITE_DST_GETADDR(x + width - 1, y + height - 1);)
SkDEBUGCODE((void)fSource.SkSPRITE_SRC_GETADDR(srcX + width - 1, srcY + height - 1);)
SkSPRITE_PREAMBLE(fSource, srcX, srcY);

View File

@ -36,9 +36,9 @@ public:
void blitRect(int x, int y, int width, int height) override {
SkASSERT(width > 0 && height > 0);
uint32_t* SK_RESTRICT dst = fDevice->getAddr32(x, y);
uint32_t* SK_RESTRICT dst = fDst.writable_addr32(x, y);
const uint32_t* SK_RESTRICT src = fSource.addr32(x - fLeft, y - fTop);
size_t dstRB = fDevice->rowBytes();
size_t dstRB = fDst.rowBytes();
size_t srcRB = fSource.rowBytes();
SkBlitRow::Proc32 proc = fProc32;
U8CPU alpha = fAlpha;
@ -89,10 +89,10 @@ public:
SkSafeUnref(fColorFilter);
}
void setup(const SkBitmap& device, int left, int top, const SkPaint& paint) override {
this->INHERITED::setup(device, left, top, paint);
void setup(const SkPixmap& dst, int left, int top, const SkPaint& paint) override {
this->INHERITED::setup(dst, left, top, paint);
int width = device.width();
int width = dst.width();
if (width > fBufferSize) {
fBufferSize = width;
delete[] fBuffer;
@ -121,9 +121,9 @@ public:
void blitRect(int x, int y, int width, int height) override {
SkASSERT(width > 0 && height > 0);
uint32_t* SK_RESTRICT dst = fDevice->getAddr32(x, y);
uint32_t* SK_RESTRICT dst = fDst.writable_addr32(x, y);
const uint32_t* SK_RESTRICT src = fSource.addr32(x - fLeft, y - fTop);
size_t dstRB = fDevice->rowBytes();
size_t dstRB = fDst.rowBytes();
size_t srcRB = fSource.rowBytes();
SkColorFilter* colorFilter = fColorFilter;
SkXfermode* xfermode = fXfermode;
@ -167,9 +167,9 @@ public:
void blitRect(int x, int y, int width, int height) override {
SkASSERT(width > 0 && height > 0);
SkPMColor* SK_RESTRICT dst = fDevice->getAddr32(x, y);
SkPMColor* SK_RESTRICT dst = fDst.writable_addr32(x, y);
const SkPMColor16* SK_RESTRICT src = fSource.addr16(x - fLeft, y - fTop);
size_t dstRB = fDevice->rowBytes();
size_t dstRB = fDst.rowBytes();
size_t srcRB = fSource.rowBytes();
SkPMColor* SK_RESTRICT buffer = fBuffer;
SkColorFilter* colorFilter = fColorFilter;
@ -213,9 +213,9 @@ public:
void blitRect(int x, int y, int width, int height) override {
SkASSERT(width > 0 && height > 0);
SkPMColor* SK_RESTRICT dst = fDevice->getAddr32(x, y);
SkPMColor* SK_RESTRICT dst = fDst.writable_addr32(x, y);
const SkPMColor16* SK_RESTRICT src = fSource.addr16(x - fLeft, y - fTop);
size_t dstRB = fDevice->rowBytes();
size_t dstRB = fDst.rowBytes();
size_t srcRB = fSource.rowBytes();
do {
@ -241,9 +241,9 @@ public:
void blitRect(int x, int y, int width, int height) override {
SkASSERT(width > 0 && height > 0);
SkPMColor* SK_RESTRICT dst = fDevice->getAddr32(x, y);
SkPMColor* SK_RESTRICT dst = fDst.writable_addr32(x, y);
const SkPMColor16* SK_RESTRICT src = fSource.addr16(x - fLeft, y - fTop);
size_t dstRB = fDevice->rowBytes();
size_t dstRB = fDst.rowBytes();
size_t srcRB = fSource.rowBytes();
do {

View File

@ -51,9 +51,9 @@ public:
// overrides
void blitRect(int x, int y, int width, int height) override {
uint16_t* SK_RESTRICT dst = fDevice->getAddr16(x, y);
uint16_t* SK_RESTRICT dst = fDst.writable_addr16(x, y);
const uint16_t* SK_RESTRICT src = fSource.addr16(x - fLeft, y - fTop);
size_t dstRB = fDevice->rowBytes();
size_t dstRB = fDst.rowBytes();
size_t srcRB = fSource.rowBytes();
while (--height >= 0) {
@ -76,7 +76,7 @@ public:
#define SkSPRITE_INIT fSrcAlpha = alpha;
#define SkSPRITE_DST_TYPE uint16_t
#define SkSPRITE_SRC_TYPE uint16_t
#define SkSPRITE_DST_GETADDR getAddr16
#define SkSPRITE_DST_GETADDR writable_addr16
#define SkSPRITE_SRC_GETADDR addr16
#define SkSPRITE_PREAMBLE(srcBM, x, y) int scale = SkAlpha255To256(fSrcAlpha);
#define SkSPRITE_BLIT_PIXEL(dst, src) D16_S16_Blend_Pixel(dst, src, scale)
@ -98,7 +98,7 @@ public:
#define SkSPRITE_INIT
#define SkSPRITE_DST_TYPE uint16_t
#define SkSPRITE_SRC_TYPE SkPMColor16
#define SkSPRITE_DST_GETADDR getAddr16
#define SkSPRITE_DST_GETADDR writable_addr16
#define SkSPRITE_SRC_GETADDR addr16
#define SkSPRITE_PREAMBLE(srcBM, x, y)
#define SkSPRITE_BLIT_PIXEL(dst, src) D16_S4444_Opaque(dst, src)
@ -119,7 +119,7 @@ public:
#define SkSPRITE_INIT fSrcAlpha = alpha;
#define SkSPRITE_DST_TYPE uint16_t
#define SkSPRITE_SRC_TYPE uint16_t
#define SkSPRITE_DST_GETADDR getAddr16
#define SkSPRITE_DST_GETADDR writable_addr16
#define SkSPRITE_SRC_GETADDR addr16
#define SkSPRITE_PREAMBLE(srcBM, x, y) int scale = SkAlpha15To16(fSrcAlpha);
#define SkSPRITE_BLIT_PIXEL(dst, src) D16_S4444_Blend(dst, src, scale)
@ -135,7 +135,7 @@ public:
#define SkSPRITE_INIT
#define SkSPRITE_DST_TYPE uint16_t
#define SkSPRITE_SRC_TYPE uint8_t
#define SkSPRITE_DST_GETADDR getAddr16
#define SkSPRITE_DST_GETADDR writable_addr16
#define SkSPRITE_SRC_GETADDR addr8
#define SkSPRITE_PREAMBLE(srcBM, x, y) const SkPMColor* ctable = srcBM.ctable()->readColors()
#define SkSPRITE_BLIT_PIXEL(dst, src) D16_S32A_Opaque_Pixel(dst, ctable[src])
@ -149,7 +149,7 @@ public:
#define SkSPRITE_INIT fSrcAlpha = alpha;
#define SkSPRITE_DST_TYPE uint16_t
#define SkSPRITE_SRC_TYPE uint8_t
#define SkSPRITE_DST_GETADDR getAddr16
#define SkSPRITE_DST_GETADDR writable_addr16
#define SkSPRITE_SRC_GETADDR addr8
#define SkSPRITE_PREAMBLE(srcBM, x, y) const SkPMColor* ctable = srcBM.ctable()->readColors(); unsigned src_scale = SkAlpha255To256(fSrcAlpha);
#define SkSPRITE_BLIT_PIXEL(dst, src) D16_S32A_Blend_Pixel(dst, ctable[src], src_scale)
@ -227,7 +227,7 @@ static void blitrow_d16_si8(uint16_t* SK_RESTRICT dst,
#define SkSPRITE_INIT
#define SkSPRITE_DST_TYPE uint16_t
#define SkSPRITE_SRC_TYPE uint8_t
#define SkSPRITE_DST_GETADDR getAddr16
#define SkSPRITE_DST_GETADDR writable_addr16
#define SkSPRITE_SRC_GETADDR addr8
#define SkSPRITE_PREAMBLE(srcBM, x, y) const uint16_t* ctable = srcBM.ctable()->read16BitCache()
#define SkSPRITE_BLIT_PIXEL(dst, src) *dst = ctable[src]
@ -241,7 +241,7 @@ static void blitrow_d16_si8(uint16_t* SK_RESTRICT dst,
#define SkSPRITE_INIT fSrcAlpha = alpha;
#define SkSPRITE_DST_TYPE uint16_t
#define SkSPRITE_SRC_TYPE uint8_t
#define SkSPRITE_DST_GETADDR getAddr16
#define SkSPRITE_DST_GETADDR writable_addr16
#define SkSPRITE_SRC_GETADDR addr8
#define SkSPRITE_PREAMBLE(srcBM, x, y) const uint16_t* ctable = srcBM.ctable()->read16BitCache(); unsigned src_scale = SkAlpha255To256(fSrcAlpha);
#define SkSPRITE_BLIT_PIXEL(dst, src) D16_S16_Blend_Pixel(dst, ctable[src], src_scale)
@ -255,8 +255,8 @@ class Sprite_D16_S32_BlitRowProc : public SkSpriteBlitter {
public:
Sprite_D16_S32_BlitRowProc(const SkPixmap& source) : SkSpriteBlitter(source) {}
void setup(const SkBitmap& device, int left, int top, const SkPaint& paint) override {
this->INHERITED::setup(device, left, top, paint);
void setup(const SkPixmap& dst, int left, int top, const SkPaint& paint) override {
this->INHERITED::setup(dst, left, top, paint);
unsigned flags = 0;
@ -273,9 +273,9 @@ public:
}
void blitRect(int x, int y, int width, int height) override {
uint16_t* SK_RESTRICT dst = fDevice->getAddr16(x, y);
uint16_t* SK_RESTRICT dst = fDst.writable_addr16(x, y);
const SkPMColor* SK_RESTRICT src = fSource.addr32(x - fLeft, y - fTop);
size_t dstRB = fDevice->rowBytes();
size_t dstRB = fDst.rowBytes();
size_t srcRB = fSource.rowBytes();
SkBlitRow::Proc16 proc = fProc;
U8CPU alpha = fPaint->getAlpha();

View File

@ -9,6 +9,31 @@
#include "SkMallocPixelRef.h"
#include "Test.h"
static void test_peekpixels(skiatest::Reporter* reporter) {
const SkImageInfo info = SkImageInfo::MakeN32Premul(10, 10);
SkPixmap pmap;
SkBitmap bm;
// empty should return false
REPORTER_ASSERT(reporter, !bm.peekPixels(NULL));
REPORTER_ASSERT(reporter, !bm.peekPixels(&pmap));
// no pixels should return false
bm.setInfo(SkImageInfo::MakeN32Premul(10, 10));
REPORTER_ASSERT(reporter, !bm.peekPixels(NULL));
REPORTER_ASSERT(reporter, !bm.peekPixels(&pmap));
// real pixels should return true
bm.allocPixels(info);
REPORTER_ASSERT(reporter, bm.peekPixels(NULL));
REPORTER_ASSERT(reporter, bm.peekPixels(&pmap));
REPORTER_ASSERT(reporter, pmap.info() == bm.info());
REPORTER_ASSERT(reporter, pmap.addr() == bm.getPixels());
REPORTER_ASSERT(reporter, pmap.rowBytes() == bm.rowBytes());
REPORTER_ASSERT(reporter, pmap.ctable() == bm.getColorTable());
}
// https://code.google.com/p/chromium/issues/detail?id=446164
static void test_bigalloc(skiatest::Reporter* reporter) {
const int width = 0x40000001;
@ -95,4 +120,5 @@ DEF_TEST(Bitmap, reporter) {
test_bigwidth(reporter);
test_allocpixels(reporter);
test_bigalloc(reporter);
test_peekpixels(reporter);
}