Buffer four scanlines prior to blitting. We will eventually use this
to blit four scanlines in a row in order to aggressively compress alpha masks as the information comes in. This CL is only to introduce the API and to make sure that nothing breaks in the general case. R=reed@google.com, robertphillips@google.com Author: krajcevski@google.com Review URL: https://codereview.chromium.org/387953005
This commit is contained in:
parent
b577c55a13
commit
2ec93fc1d3
@ -33,6 +33,7 @@ public:
|
|||||||
/// zero-terminated run-length encoding of spans of constant alpha values.
|
/// zero-terminated run-length encoding of spans of constant alpha values.
|
||||||
virtual void blitAntiH(int x, int y, const SkAlpha antialias[],
|
virtual void blitAntiH(int x, int y, const SkAlpha antialias[],
|
||||||
const int16_t runs[]);
|
const int16_t runs[]);
|
||||||
|
|
||||||
/// Blit a vertical run of pixels with a constant alpha value.
|
/// Blit a vertical run of pixels with a constant alpha value.
|
||||||
virtual void blitV(int x, int y, int height, SkAlpha alpha);
|
virtual void blitV(int x, int y, int height, SkAlpha alpha);
|
||||||
/// Blit a solid rectangle one or more pixels wide.
|
/// Blit a solid rectangle one or more pixels wide.
|
||||||
@ -67,6 +68,14 @@ public:
|
|||||||
virtual bool resetShaderContext(const SkShader::ContextRec&);
|
virtual bool resetShaderContext(const SkShader::ContextRec&);
|
||||||
virtual SkShader::Context* getShaderContext() const;
|
virtual SkShader::Context* getShaderContext() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Special methods for blitters that can blit more than one row at a time.
|
||||||
|
* This function returns the number of rows that this blitter could optimally
|
||||||
|
* process at a time. It is still required to support blitting one scanline
|
||||||
|
* at a time.
|
||||||
|
*/
|
||||||
|
virtual int requestRowsPreserved() const { return 1; }
|
||||||
|
|
||||||
///@name non-virtual helpers
|
///@name non-virtual helpers
|
||||||
void blitMaskRegion(const SkMask& mask, const SkRegion& clip);
|
void blitMaskRegion(const SkMask& mask, const SkRegion& clip);
|
||||||
void blitRectRegion(const SkIRect& rect, const SkRegion& clip);
|
void blitRectRegion(const SkIRect& rect, const SkRegion& clip);
|
||||||
|
@ -108,7 +108,7 @@ public:
|
|||||||
|
|
||||||
virtual ~SuperBlitter() {
|
virtual ~SuperBlitter() {
|
||||||
this->flush();
|
this->flush();
|
||||||
sk_free(fRuns.fRuns);
|
sk_free(fRunsBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Once fRuns contains a complete supersampled row, flush() blits
|
/// Once fRuns contains a complete supersampled row, flush() blits
|
||||||
@ -123,31 +123,56 @@ public:
|
|||||||
virtual void blitRect(int x, int y, int width, int height) SK_OVERRIDE;
|
virtual void blitRect(int x, int y, int width, int height) SK_OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// The next three variables are used to track a circular buffer that
|
||||||
|
// contains the values used in SkAlphaRuns. These variables should only
|
||||||
|
// ever be updated in advanceRuns(), and fRuns should always point to
|
||||||
|
// a valid SkAlphaRuns...
|
||||||
|
int fRunsToBuffer;
|
||||||
|
void* fRunsBuffer;
|
||||||
|
int fCurrentRun;
|
||||||
SkAlphaRuns fRuns;
|
SkAlphaRuns fRuns;
|
||||||
|
|
||||||
|
// extra one to store the zero at the end
|
||||||
|
int getRunsSz() const { return (fWidth + 1 + (fWidth + 2)/2) * sizeof(int16_t); }
|
||||||
|
|
||||||
|
// This function updates the fRuns variable to point to the next buffer space
|
||||||
|
// with adequate storage for a SkAlphaRuns. It mostly just advances fCurrentRun
|
||||||
|
// and resets fRuns to point to an empty scanline.
|
||||||
|
void advanceRuns() {
|
||||||
|
const size_t kRunsSz = this->getRunsSz();
|
||||||
|
fCurrentRun = (fCurrentRun + 1) % fRunsToBuffer;
|
||||||
|
fRuns.fRuns = reinterpret_cast<int16_t*>(
|
||||||
|
reinterpret_cast<uint8_t*>(fRunsBuffer) + fCurrentRun * kRunsSz);
|
||||||
|
fRuns.fAlpha = reinterpret_cast<SkAlpha*>(fRuns.fRuns + fWidth + 1);
|
||||||
|
fRuns.reset(fWidth);
|
||||||
|
}
|
||||||
|
|
||||||
int fOffsetX;
|
int fOffsetX;
|
||||||
};
|
};
|
||||||
|
|
||||||
SuperBlitter::SuperBlitter(SkBlitter* realBlitter, const SkIRect& ir,
|
SuperBlitter::SuperBlitter(SkBlitter* realBlitter, const SkIRect& ir,
|
||||||
const SkRegion& clip)
|
const SkRegion& clip)
|
||||||
: BaseSuperBlitter(realBlitter, ir, clip) {
|
: BaseSuperBlitter(realBlitter, ir, clip) {
|
||||||
const int width = fWidth;
|
fRunsToBuffer = realBlitter->requestRowsPreserved();
|
||||||
|
fRunsBuffer = sk_malloc_throw(fRunsToBuffer * this->getRunsSz());
|
||||||
|
fCurrentRun = -1;
|
||||||
|
|
||||||
// extra one to store the zero at the end
|
this->advanceRuns();
|
||||||
fRuns.fRuns = (int16_t*)sk_malloc_throw((width + 1 + (width + 2)/2) * sizeof(int16_t));
|
|
||||||
fRuns.fAlpha = (uint8_t*)(fRuns.fRuns + width + 1);
|
|
||||||
fRuns.reset(width);
|
|
||||||
|
|
||||||
fOffsetX = 0;
|
fOffsetX = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SuperBlitter::flush() {
|
void SuperBlitter::flush() {
|
||||||
if (fCurrIY >= fTop) {
|
if (fCurrIY >= fTop) {
|
||||||
|
|
||||||
|
SkASSERT(fCurrentRun < fRunsToBuffer);
|
||||||
if (!fRuns.empty()) {
|
if (!fRuns.empty()) {
|
||||||
// SkDEBUGCODE(fRuns.dump();)
|
// SkDEBUGCODE(fRuns.dump();)
|
||||||
fRealBlitter->blitAntiH(fLeft, fCurrIY, fRuns.fAlpha, fRuns.fRuns);
|
fRealBlitter->blitAntiH(fLeft, fCurrIY, fRuns.fAlpha, fRuns.fRuns);
|
||||||
fRuns.reset(fWidth);
|
this->advanceRuns();
|
||||||
fOffsetX = 0;
|
fOffsetX = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
fCurrIY = fTop - 1;
|
fCurrIY = fTop - 1;
|
||||||
SkDEBUGCODE(fCurrX = -1;)
|
SkDEBUGCODE(fCurrX = -1;)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user