| Index: skia/sgl/SkBlitter.cpp
|
| ===================================================================
|
| --- skia/sgl/SkBlitter.cpp (revision 16859)
|
| +++ skia/sgl/SkBlitter.cpp (working copy)
|
| @@ -1,923 +0,0 @@
|
| -/* libs/graphics/sgl/SkBlitter.cpp
|
| -**
|
| -** Copyright 2006, The Android Open Source Project
|
| -**
|
| -** Licensed under the Apache License, Version 2.0 (the "License");
|
| -** you may not use this file except in compliance with the License.
|
| -** You may obtain a copy of the License at
|
| -**
|
| -** http://www.apache.org/licenses/LICENSE-2.0
|
| -**
|
| -** Unless required by applicable law or agreed to in writing, software
|
| -** distributed under the License is distributed on an "AS IS" BASIS,
|
| -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| -** See the License for the specific language governing permissions and
|
| -** limitations under the License.
|
| -*/
|
| -
|
| -#include "SkBlitter.h"
|
| -#include "SkAntiRun.h"
|
| -#include "SkColor.h"
|
| -#include "SkColorFilter.h"
|
| -#include "SkMask.h"
|
| -#include "SkMaskFilter.h"
|
| -#include "SkTemplatesPriv.h"
|
| -#include "SkUtils.h"
|
| -#include "SkXfermode.h"
|
| -
|
| -SkBlitter::~SkBlitter()
|
| -{
|
| -}
|
| -
|
| -const SkBitmap* SkBlitter::justAnOpaqueColor(uint32_t* value)
|
| -{
|
| - return NULL;
|
| -}
|
| -
|
| -void SkBlitter::blitH(int x, int y, int width)
|
| -{
|
| - SkASSERT(!"unimplemented");
|
| -}
|
| -
|
| -void SkBlitter::blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[])
|
| -{
|
| - SkASSERT(!"unimplemented");
|
| -}
|
| -
|
| -void SkBlitter::blitV(int x, int y, int height, SkAlpha alpha)
|
| -{
|
| - if (alpha == 255)
|
| - this->blitRect(x, y, 1, height);
|
| - else
|
| - {
|
| - int16_t runs[2];
|
| - runs[0] = 1;
|
| - runs[1] = 0;
|
| -
|
| - while (--height >= 0)
|
| - this->blitAntiH(x, y++, &alpha, runs);
|
| - }
|
| -}
|
| -
|
| -void SkBlitter::blitRect(int x, int y, int width, int height)
|
| -{
|
| - while (--height >= 0)
|
| - this->blitH(x, y++, width);
|
| -}
|
| -
|
| -//////////////////////////////////////////////////////////////////////////////
|
| -
|
| -static inline void bits_to_runs(SkBlitter* blitter, int x, int y, const uint8_t bits[],
|
| - U8CPU left_mask, int rowBytes, U8CPU right_mask)
|
| -{
|
| - int inFill = 0;
|
| - int pos = 0;
|
| -
|
| - while (--rowBytes >= 0)
|
| - {
|
| - unsigned b = *bits++ & left_mask;
|
| - if (rowBytes == 0)
|
| - b &= right_mask;
|
| -
|
| - for (unsigned test = 0x80; test != 0; test >>= 1)
|
| - {
|
| - if (b & test)
|
| - {
|
| - if (!inFill)
|
| - {
|
| - pos = x;
|
| - inFill = true;
|
| - }
|
| - }
|
| - else
|
| - {
|
| - if (inFill)
|
| - {
|
| - blitter->blitH(pos, y, x - pos);
|
| - inFill = false;
|
| - }
|
| - }
|
| - x += 1;
|
| - }
|
| - left_mask = 0xFF;
|
| - }
|
| -
|
| - // final cleanup
|
| - if (inFill)
|
| - blitter->blitH(pos, y, x - pos);
|
| -}
|
| -
|
| -void SkBlitter::blitMask(const SkMask& mask, const SkIRect& clip)
|
| -{
|
| - SkASSERT(mask.fBounds.contains(clip));
|
| -
|
| - if (mask.fFormat == SkMask::kBW_Format)
|
| - {
|
| - int cx = clip.fLeft;
|
| - int cy = clip.fTop;
|
| - int maskLeft = mask.fBounds.fLeft;
|
| - int mask_rowBytes = mask.fRowBytes;
|
| - int height = clip.height();
|
| -
|
| - const uint8_t* bits = mask.getAddr1(cx, cy);
|
| -
|
| - if (cx == maskLeft && clip.fRight == mask.fBounds.fRight)
|
| - {
|
| - while (--height >= 0)
|
| - {
|
| - bits_to_runs(this, cx, cy, bits, 0xFF, mask_rowBytes, 0xFF);
|
| - bits += mask_rowBytes;
|
| - cy += 1;
|
| - }
|
| - }
|
| - else
|
| - {
|
| - int left_edge = cx - maskLeft;
|
| - SkASSERT(left_edge >= 0);
|
| - int rite_edge = clip.fRight - maskLeft;
|
| - SkASSERT(rite_edge > left_edge);
|
| -
|
| - int left_mask = 0xFF >> (left_edge & 7);
|
| - int rite_mask = 0xFF << (8 - (rite_edge & 7));
|
| - int full_runs = (rite_edge >> 3) - ((left_edge + 7) >> 3);
|
| -
|
| - // check for empty right mask, so we don't read off the end (or go slower than we need to)
|
| - if (rite_mask == 0)
|
| - {
|
| - SkASSERT(full_runs >= 0);
|
| - full_runs -= 1;
|
| - rite_mask = 0xFF;
|
| - }
|
| - if (left_mask == 0xFF)
|
| - full_runs -= 1;
|
| -
|
| - // back up manually so we can keep in sync with our byte-aligned src
|
| - // have cx reflect our actual starting x-coord
|
| - cx -= left_edge & 7;
|
| -
|
| - if (full_runs < 0)
|
| - {
|
| - SkASSERT((left_mask & rite_mask) != 0);
|
| - while (--height >= 0)
|
| - {
|
| - bits_to_runs(this, cx, cy, bits, left_mask, 1, rite_mask);
|
| - bits += mask_rowBytes;
|
| - cy += 1;
|
| - }
|
| - }
|
| - else
|
| - {
|
| - while (--height >= 0)
|
| - {
|
| - bits_to_runs(this, cx, cy, bits, left_mask, full_runs + 2, rite_mask);
|
| - bits += mask_rowBytes;
|
| - cy += 1;
|
| - }
|
| - }
|
| - }
|
| - }
|
| - else
|
| - {
|
| - int width = clip.width();
|
| - SkAutoSTMalloc<64, int16_t> runStorage(width + 1);
|
| - int16_t* runs = runStorage.get();
|
| - const uint8_t* aa = mask.getAddr(clip.fLeft, clip.fTop);
|
| -
|
| - sk_memset16((uint16_t*)runs, 1, width);
|
| - runs[width] = 0;
|
| -
|
| - int height = clip.height();
|
| - int y = clip.fTop;
|
| - while (--height >= 0)
|
| - {
|
| - this->blitAntiH(clip.fLeft, y, aa, runs);
|
| - aa += mask.fRowBytes;
|
| - y += 1;
|
| - }
|
| - }
|
| -}
|
| -
|
| -/////////////////////// these guys are not virtual, just a helpers
|
| -
|
| -void SkBlitter::blitMaskRegion(const SkMask& mask, const SkRegion& clip) {
|
| - if (clip.quickReject(mask.fBounds)) {
|
| - return;
|
| - }
|
| -
|
| - SkRegion::Cliperator clipper(clip, mask.fBounds);
|
| -
|
| - while (!clipper.done()) {
|
| - const SkIRect& cr = clipper.rect();
|
| - this->blitMask(mask, cr);
|
| - clipper.next();
|
| - }
|
| -}
|
| -
|
| -void SkBlitter::blitRectRegion(const SkIRect& rect, const SkRegion& clip) {
|
| - SkRegion::Cliperator clipper(clip, rect);
|
| -
|
| - while (!clipper.done()) {
|
| - const SkIRect& cr = clipper.rect();
|
| - this->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height());
|
| - clipper.next();
|
| - }
|
| -}
|
| -
|
| -void SkBlitter::blitRegion(const SkRegion& clip) {
|
| - SkRegion::Iterator iter(clip);
|
| -
|
| - while (!iter.done()) {
|
| - const SkIRect& cr = iter.rect();
|
| - this->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height());
|
| - iter.next();
|
| - }
|
| -}
|
| -
|
| -///////////////////////////////////////////////////////////////////////////////////////
|
| -///////////////////////////////////////////////////////////////////////////////////////
|
| -
|
| -void SkNullBlitter::blitH(int x, int y, int width)
|
| -{
|
| -}
|
| -
|
| -void SkNullBlitter::blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[])
|
| -{
|
| -}
|
| -
|
| -void SkNullBlitter::blitV(int x, int y, int height, SkAlpha alpha)
|
| -{
|
| -}
|
| -
|
| -void SkNullBlitter::blitRect(int x, int y, int width, int height)
|
| -{
|
| -}
|
| -
|
| -void SkNullBlitter::blitMask(const SkMask& mask, const SkIRect& clip)
|
| -{
|
| -}
|
| -
|
| -const SkBitmap* SkNullBlitter::justAnOpaqueColor(uint32_t* value)
|
| -{
|
| - return NULL;
|
| -}
|
| -
|
| -///////////////////////////////////////////////////////////////////////////////////////
|
| -///////////////////////////////////////////////////////////////////////////////////////
|
| -
|
| -static int compute_anti_width(const int16_t runs[])
|
| -{
|
| - int width = 0;
|
| -
|
| - for (;;)
|
| - {
|
| - int count = runs[0];
|
| -
|
| - SkASSERT(count >= 0);
|
| - if (count == 0)
|
| - break;
|
| - width += count;
|
| - runs += count;
|
| -
|
| - SkASSERT(width < 20000);
|
| - }
|
| - return width;
|
| -}
|
| -
|
| -static inline bool y_in_rect(int y, const SkIRect& rect)
|
| -{
|
| - return (unsigned)(y - rect.fTop) < (unsigned)rect.height();
|
| -}
|
| -
|
| -static inline bool x_in_rect(int x, const SkIRect& rect)
|
| -{
|
| - return (unsigned)(x - rect.fLeft) < (unsigned)rect.width();
|
| -}
|
| -
|
| -void SkRectClipBlitter::blitH(int left, int y, int width)
|
| -{
|
| - SkASSERT(width > 0);
|
| -
|
| - if (!y_in_rect(y, fClipRect))
|
| - return;
|
| -
|
| - int right = left + width;
|
| -
|
| - if (left < fClipRect.fLeft)
|
| - left = fClipRect.fLeft;
|
| - if (right > fClipRect.fRight)
|
| - right = fClipRect.fRight;
|
| -
|
| - width = right - left;
|
| - if (width > 0)
|
| - fBlitter->blitH(left, y, width);
|
| -}
|
| -
|
| -void SkRectClipBlitter::blitAntiH(int left, int y, const SkAlpha aa[], const int16_t runs[])
|
| -{
|
| - if (!y_in_rect(y, fClipRect) || left >= fClipRect.fRight)
|
| - return;
|
| -
|
| - int x0 = left;
|
| - int x1 = left + compute_anti_width(runs);
|
| -
|
| - if (x1 <= fClipRect.fLeft)
|
| - return;
|
| -
|
| - SkASSERT(x0 < x1);
|
| - if (x0 < fClipRect.fLeft)
|
| - {
|
| - int dx = fClipRect.fLeft - x0;
|
| - SkAlphaRuns::BreakAt((int16_t*)runs, (uint8_t*)aa, dx);
|
| - runs += dx;
|
| - aa += dx;
|
| - x0 = fClipRect.fLeft;
|
| - }
|
| -
|
| - SkASSERT(x0 < x1 && runs[x1 - x0] == 0);
|
| - if (x1 > fClipRect.fRight)
|
| - {
|
| - x1 = fClipRect.fRight;
|
| - SkAlphaRuns::BreakAt((int16_t*)runs, (uint8_t*)aa, x1 - x0);
|
| - ((int16_t*)runs)[x1 - x0] = 0;
|
| - }
|
| -
|
| - SkASSERT(x0 < x1 && runs[x1 - x0] == 0);
|
| - SkASSERT(compute_anti_width(runs) == x1 - x0);
|
| -
|
| - fBlitter->blitAntiH(x0, y, aa, runs);
|
| -}
|
| -
|
| -void SkRectClipBlitter::blitV(int x, int y, int height, SkAlpha alpha)
|
| -{
|
| - SkASSERT(height > 0);
|
| -
|
| - if (!x_in_rect(x, fClipRect))
|
| - return;
|
| -
|
| - int y0 = y;
|
| - int y1 = y + height;
|
| -
|
| - if (y0 < fClipRect.fTop)
|
| - y0 = fClipRect.fTop;
|
| - if (y1 > fClipRect.fBottom)
|
| - y1 = fClipRect.fBottom;
|
| -
|
| - if (y0 < y1)
|
| - fBlitter->blitV(x, y0, y1 - y0, alpha);
|
| -}
|
| -
|
| -void SkRectClipBlitter::blitRect(int left, int y, int width, int height)
|
| -{
|
| - SkIRect r;
|
| -
|
| - r.set(left, y, left + width, y + height);
|
| - if (r.intersect(fClipRect))
|
| - fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
|
| -}
|
| -
|
| -void SkRectClipBlitter::blitMask(const SkMask& mask, const SkIRect& clip)
|
| -{
|
| - SkASSERT(mask.fBounds.contains(clip));
|
| -
|
| - SkIRect r = clip;
|
| -
|
| - if (r.intersect(fClipRect))
|
| - fBlitter->blitMask(mask, r);
|
| -}
|
| -
|
| -const SkBitmap* SkRectClipBlitter::justAnOpaqueColor(uint32_t* value)
|
| -{
|
| - return fBlitter->justAnOpaqueColor(value);
|
| -}
|
| -
|
| -///////////////////////////////////////////////////////////////////////////////////////
|
| -///////////////////////////////////////////////////////////////////////////////////////
|
| -
|
| -void SkRgnClipBlitter::blitH(int x, int y, int width)
|
| -{
|
| - SkRegion::Spanerator span(*fRgn, y, x, x + width);
|
| - int left, right;
|
| -
|
| - while (span.next(&left, &right))
|
| - {
|
| - SkASSERT(left < right);
|
| - fBlitter->blitH(left, y, right - left);
|
| - }
|
| -}
|
| -
|
| -void SkRgnClipBlitter::blitAntiH(int x, int y, const SkAlpha aa[], const int16_t runs[])
|
| -{
|
| - int width = compute_anti_width(runs);
|
| - SkRegion::Spanerator span(*fRgn, y, x, x + width);
|
| - int left, right;
|
| - SkDEBUGCODE(const SkIRect& bounds = fRgn->getBounds();)
|
| -
|
| - int prevRite = x;
|
| - while (span.next(&left, &right))
|
| - {
|
| - SkASSERT(x <= left);
|
| - SkASSERT(left < right);
|
| - SkASSERT(left >= bounds.fLeft && right <= bounds.fRight);
|
| -
|
| - SkAlphaRuns::Break((int16_t*)runs, (uint8_t*)aa, left - x, right - left);
|
| -
|
| - // now zero before left
|
| - if (left > prevRite)
|
| - {
|
| - int index = prevRite - x;
|
| - ((uint8_t*)aa)[index] = 0; // skip runs after right
|
| - ((int16_t*)runs)[index] = SkToS16(left - prevRite);
|
| - }
|
| -
|
| - prevRite = right;
|
| - }
|
| -
|
| - if (prevRite > x)
|
| - {
|
| - ((int16_t*)runs)[prevRite - x] = 0;
|
| -
|
| - if (x < 0) {
|
| - int skip = runs[0];
|
| - SkASSERT(skip >= -x);
|
| - aa += skip;
|
| - runs += skip;
|
| - x += skip;
|
| - }
|
| - fBlitter->blitAntiH(x, y, aa, runs);
|
| - }
|
| -}
|
| -
|
| -void SkRgnClipBlitter::blitV(int x, int y, int height, SkAlpha alpha)
|
| -{
|
| - SkIRect bounds;
|
| - bounds.set(x, y, x + 1, y + height);
|
| -
|
| - SkRegion::Cliperator iter(*fRgn, bounds);
|
| -
|
| - while (!iter.done())
|
| - {
|
| - const SkIRect& r = iter.rect();
|
| - SkASSERT(bounds.contains(r));
|
| -
|
| - fBlitter->blitV(x, r.fTop, r.height(), alpha);
|
| - iter.next();
|
| - }
|
| -}
|
| -
|
| -void SkRgnClipBlitter::blitRect(int x, int y, int width, int height)
|
| -{
|
| - SkIRect bounds;
|
| - bounds.set(x, y, x + width, y + height);
|
| -
|
| - SkRegion::Cliperator iter(*fRgn, bounds);
|
| -
|
| - while (!iter.done())
|
| - {
|
| - const SkIRect& r = iter.rect();
|
| - SkASSERT(bounds.contains(r));
|
| -
|
| - fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
|
| - iter.next();
|
| - }
|
| -}
|
| -
|
| -void SkRgnClipBlitter::blitMask(const SkMask& mask, const SkIRect& clip)
|
| -{
|
| - SkASSERT(mask.fBounds.contains(clip));
|
| -
|
| - SkRegion::Cliperator iter(*fRgn, clip);
|
| - const SkIRect& r = iter.rect();
|
| - SkBlitter* blitter = fBlitter;
|
| -
|
| - while (!iter.done())
|
| - {
|
| - blitter->blitMask(mask, r);
|
| - iter.next();
|
| - }
|
| -}
|
| -
|
| -const SkBitmap* SkRgnClipBlitter::justAnOpaqueColor(uint32_t* value)
|
| -{
|
| - return fBlitter->justAnOpaqueColor(value);
|
| -}
|
| -
|
| -///////////////////////////////////////////////////////////////////////////////////////
|
| -///////////////////////////////////////////////////////////////////////////////////////
|
| -
|
| -SkBlitter* SkBlitterClipper::apply(SkBlitter* blitter, const SkRegion* clip, const SkIRect* ir)
|
| -{
|
| - if (clip)
|
| - {
|
| - const SkIRect& clipR = clip->getBounds();
|
| -
|
| - if (clip->isEmpty() || (ir && !SkIRect::Intersects(clipR, *ir)))
|
| - blitter = &fNullBlitter;
|
| - else if (clip->isRect())
|
| - {
|
| - if (ir == NULL || !clipR.contains(*ir))
|
| - {
|
| - fRectBlitter.init(blitter, clipR);
|
| - blitter = &fRectBlitter;
|
| - }
|
| - }
|
| - else
|
| - {
|
| - fRgnBlitter.init(blitter, clip);
|
| - blitter = &fRgnBlitter;
|
| - }
|
| - }
|
| - return blitter;
|
| -}
|
| -
|
| -///////////////////////////////////////////////////////////////////////////////////////
|
| -///////////////////////////////////////////////////////////////////////////////////////
|
| -
|
| -#include "SkColorShader.h"
|
| -#include "SkColorPriv.h"
|
| -
|
| -class Sk3DShader : public SkShader {
|
| -public:
|
| - Sk3DShader(SkShader* proxy) : fProxy(proxy)
|
| - {
|
| - proxy->safeRef();
|
| - fMask = NULL;
|
| - }
|
| - virtual ~Sk3DShader()
|
| - {
|
| - fProxy->safeUnref();
|
| - }
|
| - void setMask(const SkMask* mask) { fMask = mask; }
|
| -
|
| - virtual bool setContext(const SkBitmap& device, const SkPaint& paint, const SkMatrix& matrix)
|
| - {
|
| - if (fProxy)
|
| - return fProxy->setContext(device, paint, matrix);
|
| - else
|
| - {
|
| - fPMColor = SkPreMultiplyColor(paint.getColor());
|
| - return this->INHERITED::setContext(device, paint, matrix);
|
| - }
|
| - }
|
| - virtual void shadeSpan(int x, int y, SkPMColor span[], int count)
|
| - {
|
| - if (fProxy)
|
| - fProxy->shadeSpan(x, y, span, count);
|
| -
|
| - if (fMask == NULL)
|
| - {
|
| - if (fProxy == NULL)
|
| - sk_memset32(span, fPMColor, count);
|
| - return;
|
| - }
|
| -
|
| - SkASSERT(fMask->fBounds.contains(x, y));
|
| - SkASSERT(fMask->fBounds.contains(x + count - 1, y));
|
| -
|
| - size_t size = fMask->computeImageSize();
|
| - const uint8_t* alpha = fMask->getAddr(x, y);
|
| - const uint8_t* mulp = alpha + size;
|
| - const uint8_t* addp = mulp + size;
|
| -
|
| - if (fProxy)
|
| - {
|
| - for (int i = 0; i < count; i++)
|
| - {
|
| - if (alpha[i])
|
| - {
|
| - SkPMColor c = span[i];
|
| - if (c)
|
| - {
|
| - unsigned a = SkGetPackedA32(c);
|
| - unsigned r = SkGetPackedR32(c);
|
| - unsigned g = SkGetPackedG32(c);
|
| - unsigned b = SkGetPackedB32(c);
|
| -
|
| - unsigned mul = SkAlpha255To256(mulp[i]);
|
| - unsigned add = addp[i];
|
| -
|
| - r = SkFastMin32(SkAlphaMul(r, mul) + add, a);
|
| - g = SkFastMin32(SkAlphaMul(g, mul) + add, a);
|
| - b = SkFastMin32(SkAlphaMul(b, mul) + add, a);
|
| -
|
| - span[i] = SkPackARGB32(a, r, g, b);
|
| - }
|
| - }
|
| - else
|
| - span[i] = 0;
|
| - }
|
| - }
|
| - else // color
|
| - {
|
| - unsigned a = SkGetPackedA32(fPMColor);
|
| - unsigned r = SkGetPackedR32(fPMColor);
|
| - unsigned g = SkGetPackedG32(fPMColor);
|
| - unsigned b = SkGetPackedB32(fPMColor);
|
| - for (int i = 0; i < count; i++)
|
| - {
|
| - if (alpha[i])
|
| - {
|
| - unsigned mul = SkAlpha255To256(mulp[i]);
|
| - unsigned add = addp[i];
|
| -
|
| - span[i] = SkPackARGB32( a,
|
| - SkFastMin32(SkAlphaMul(r, mul) + add, a),
|
| - SkFastMin32(SkAlphaMul(g, mul) + add, a),
|
| - SkFastMin32(SkAlphaMul(b, mul) + add, a));
|
| - }
|
| - else
|
| - span[i] = 0;
|
| - }
|
| - }
|
| - }
|
| -
|
| - virtual void beginSession()
|
| - {
|
| - this->INHERITED::beginSession();
|
| - if (fProxy)
|
| - fProxy->beginSession();
|
| - }
|
| -
|
| - virtual void endSession()
|
| - {
|
| - if (fProxy)
|
| - fProxy->endSession();
|
| - this->INHERITED::endSession();
|
| - }
|
| -
|
| -protected:
|
| - Sk3DShader(SkFlattenableReadBuffer& buffer) :
|
| - INHERITED(buffer)
|
| - {
|
| - fProxy = static_cast<SkShader*>(buffer.readFlattenable());
|
| - fPMColor = buffer.readU32();
|
| - fMask = NULL;
|
| - }
|
| -
|
| - virtual void flatten(SkFlattenableWriteBuffer& buffer)
|
| - {
|
| - this->INHERITED::flatten(buffer);
|
| - buffer.writeFlattenable(fProxy);
|
| - buffer.write32(fPMColor);
|
| - }
|
| -
|
| - virtual Factory getFactory()
|
| - {
|
| - return CreateProc;
|
| - }
|
| -
|
| -private:
|
| - static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer)
|
| - {
|
| - return SkNEW_ARGS(Sk3DShader, (buffer));
|
| - }
|
| -
|
| - SkShader* fProxy;
|
| - SkPMColor fPMColor;
|
| - const SkMask* fMask;
|
| -
|
| - typedef SkShader INHERITED;
|
| -};
|
| -
|
| -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);
|
| - }
|
| -
|
| - virtual void blitH(int x, int y, int width)
|
| - {
|
| - fProxy->blitH(x, y, width);
|
| - }
|
| - virtual void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[])
|
| - {
|
| - fProxy->blitAntiH(x, y, antialias, runs);
|
| - }
|
| - virtual void blitV(int x, int y, int height, SkAlpha alpha)
|
| - {
|
| - fProxy->blitV(x, y, height, alpha);
|
| - }
|
| - virtual void blitRect(int x, int y, int width, int height)
|
| - {
|
| - fProxy->blitRect(x, y, width, height);
|
| - }
|
| - virtual void blitMask(const SkMask& mask, const SkIRect& clip)
|
| - {
|
| - if (mask.fFormat == SkMask::k3D_Format)
|
| - {
|
| - f3DShader->setMask(&mask);
|
| -
|
| - ((SkMask*)&mask)->fFormat = SkMask::kA8_Format;
|
| - fProxy->blitMask(mask, clip);
|
| - ((SkMask*)&mask)->fFormat = SkMask::k3D_Format;
|
| -
|
| - f3DShader->setMask(NULL);
|
| - }
|
| - else
|
| - fProxy->blitMask(mask, clip);
|
| - }
|
| -private:
|
| - SkBlitter* fProxy;
|
| - Sk3DShader* f3DShader;
|
| - void (*fKillProc)(void*);
|
| -};
|
| -
|
| -///////////////////////////////////////////////////////////////////////////////////////
|
| -///////////////////////////////////////////////////////////////////////////////////////
|
| -
|
| -#include "SkCoreBlitters.h"
|
| -
|
| -class SkAutoRestoreShader {
|
| -public:
|
| - SkAutoRestoreShader(const SkPaint& p) : fPaint((SkPaint*)&p)
|
| - {
|
| - fShader = fPaint->getShader();
|
| - fShader->safeRef();
|
| - }
|
| - ~SkAutoRestoreShader()
|
| - {
|
| - fPaint->setShader(fShader);
|
| - fShader->safeUnref();
|
| - }
|
| -private:
|
| - SkPaint* fPaint;
|
| - SkShader* fShader;
|
| -};
|
| -
|
| -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;
|
| -};
|
| -
|
| -static void destroy_blitter(void* blitter)
|
| -{
|
| - ((SkBlitter*)blitter)->~SkBlitter();
|
| -}
|
| -
|
| -static void delete_blitter(void* blitter)
|
| -{
|
| - SkDELETE((SkBlitter*)blitter);
|
| -}
|
| -
|
| -SkBlitter* SkBlitter::Choose(const SkBitmap& device,
|
| - const SkMatrix& matrix,
|
| - const SkPaint& paint,
|
| - void* storage, size_t storageSize)
|
| -{
|
| - SkASSERT(storageSize == 0 || storage != NULL);
|
| -
|
| - SkBlitter* blitter = NULL;
|
| -
|
| - // which check, in case we're being called by a client with a dummy device
|
| - // (e.g. they have a bounder that always aborts the draw)
|
| - if (SkBitmap::kNo_Config == device.getConfig())
|
| - {
|
| - SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize);
|
| - return blitter;
|
| - }
|
| -
|
| - SkAutoRestoreShader restore(paint);
|
| - SkShader* shader = paint.getShader();
|
| -
|
| - Sk3DShader* shader3D = NULL;
|
| - if (paint.getMaskFilter() != NULL && paint.getMaskFilter()->getFormat() == SkMask::k3D_Format)
|
| - {
|
| - shader3D = SkNEW_ARGS(Sk3DShader, (shader));
|
| - ((SkPaint*)&paint)->setShader(shader3D)->unref();
|
| - shader = shader3D;
|
| - }
|
| -
|
| - SkXfermode* mode = paint.getXfermode();
|
| - if (NULL == shader && (NULL != mode || paint.getColorFilter() != NULL))
|
| - {
|
| - // xfermodes require shaders for our current set of blitters
|
| - shader = SkNEW(SkColorShader);
|
| - ((SkPaint*)&paint)->setShader(shader)->unref();
|
| - }
|
| -
|
| - if (paint.getColorFilter() != NULL)
|
| - {
|
| - SkASSERT(shader);
|
| - shader = SkNEW_ARGS(SkFilterShader, (shader, paint.getColorFilter()));
|
| - ((SkPaint*)&paint)->setShader(shader)->unref();
|
| - }
|
| -
|
| - bool doDither = paint.isDither();
|
| -
|
| - if (shader)
|
| - {
|
| - if (!shader->setContext(device, paint, matrix))
|
| - return SkNEW(SkNullBlitter);
|
| -
|
| - // disable dither if our shader is natively 16bit (no need to upsample)
|
| - if (shader->getFlags() & SkShader::kIntrinsicly16_Flag)
|
| - doDither = false;
|
| - }
|
| -
|
| - switch (device.getConfig()) {
|
| - case SkBitmap::kA1_Config:
|
| - SK_PLACEMENT_NEW_ARGS(blitter, SkA1_Blitter, storage, storageSize, (device, paint));
|
| - break;
|
| -
|
| - case SkBitmap::kA8_Config:
|
| - if (shader)
|
| - SK_PLACEMENT_NEW_ARGS(blitter, SkA8_Shader_Blitter, storage, storageSize, (device, paint));
|
| - else
|
| - SK_PLACEMENT_NEW_ARGS(blitter, SkA8_Blitter, storage, storageSize, (device, paint));
|
| - break;
|
| -
|
| - case SkBitmap::kARGB_4444_Config:
|
| - blitter = SkBlitter_ChooseD4444(device, paint, storage, storageSize);
|
| - break;
|
| -
|
| - case SkBitmap::kRGB_565_Config:
|
| - if (shader)
|
| - {
|
| - if (mode)
|
| - SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Shader_Xfermode_Blitter, storage, storageSize, (device, paint));
|
| - else if (SkShader::CanCallShadeSpan16(shader->getFlags()) && !doDither)
|
| - SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Shader16_Blitter, storage, storageSize, (device, paint));
|
| - else
|
| - SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Shader_Blitter, storage, storageSize, (device, paint));
|
| - }
|
| - else if (paint.getColor() == SK_ColorBLACK)
|
| - SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Black_Blitter, storage, storageSize, (device, paint));
|
| - else
|
| - SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Blitter, storage, storageSize, (device, paint));
|
| - break;
|
| -
|
| - case SkBitmap::kARGB_8888_Config:
|
| - if (shader)
|
| - SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Shader_Blitter, storage, storageSize, (device, paint));
|
| - else if (paint.getColor() == SK_ColorBLACK)
|
| - SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Black_Blitter, storage, storageSize, (device, paint));
|
| - else if (paint.getAlpha() == 0xFF)
|
| - SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Opaque_Blitter, storage, storageSize, (device, paint));
|
| - else
|
| - SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Blitter, storage, storageSize, (device, paint));
|
| - break;
|
| -
|
| - default:
|
| - SkASSERT(!"unsupported device config");
|
| - SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize);
|
| - }
|
| -
|
| - 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();
|
| - }
|
| - return blitter;
|
| -}
|
| -
|
| -//////////////////////////////////////////////////////////////////////////////////////////////////////
|
| -
|
| -const uint16_t gMask_0F0F = 0xF0F;
|
| -const uint32_t gMask_00FF00FF = 0xFF00FF;
|
| -
|
| -//////////////////////////////////////////////////////////////////////////////////////////////////////
|
| -
|
| -SkShaderBlitter::SkShaderBlitter(const SkBitmap& device, const SkPaint& paint)
|
| - : INHERITED(device)
|
| -{
|
| - fShader = paint.getShader();
|
| - SkASSERT(fShader);
|
| -
|
| - fShader->ref();
|
| - fShader->beginSession();
|
| -}
|
| -
|
| -SkShaderBlitter::~SkShaderBlitter()
|
| -{
|
| - fShader->endSession();
|
| - fShader->unref();
|
| -}
|
| -
|
|
|