void SkComposeShader::ComposeShaderContext::shadeSpan(int x, int y, SkPMColor result[], int count) {
    SkShader::Context* shaderContextA = fShaderContextA;
    SkShader::Context* shaderContextB = fShaderContextB;
    SkBlendMode        mode = static_cast<const SkComposeShader&>(fShader).fMode;
    unsigned           scale = SkAlpha255To256(this->getPaintAlpha());

    SkPMColor   tmp[TMP_COLOR_COUNT];

    SkXfermode* xfer = SkXfermode::Peek(mode);
    if (nullptr == xfer) {   // implied SRC_OVER
        // TODO: when we have a good test-case, should use SkBlitRow::Proc32
        // for these loops
        do {
            int n = count;
            if (n > TMP_COLOR_COUNT) {
                n = TMP_COLOR_COUNT;
            }

            shaderContextA->shadeSpan(x, y, result, n);
            shaderContextB->shadeSpan(x, y, tmp, n);

            if (256 == scale) {
                for (int i = 0; i < n; i++) {
                    result[i] = SkPMSrcOver(tmp[i], result[i]);
                }
            } else {
                for (int i = 0; i < n; i++) {
                    result[i] = SkAlphaMulQ(SkPMSrcOver(tmp[i], result[i]),
                                            scale);
                }
            }

            result += n;
            x += n;
            count -= n;
        } while (count > 0);
    } else {    // use mode for the composition
        do {
            int n = count;
            if (n > TMP_COLOR_COUNT) {
                n = TMP_COLOR_COUNT;
            }

            shaderContextA->shadeSpan(x, y, result, n);
            shaderContextB->shadeSpan(x, y, tmp, n);
            xfer->xfer32(result, tmp, n, nullptr);

            if (256 != scale) {
                for (int i = 0; i < n; i++) {
                    result[i] = SkAlphaMulQ(result[i], scale);
                }
            }

            result += n;
            x += n;
            count -= n;
        } while (count > 0);
    }
}
示例#2
0
DEF_TEST(Color4f_shader, reporter) {
    struct {
        sk_sp<SkShader> (*fFact)();
        bool            fSupports4f;
        float           fTolerance;
    } recs[] = {
        { make_color_sh, true,  1.0f/255   },
        // PMColor 4f gradients are interpolated in 255-multiplied values, so we need a
        // slightly relaxed tolerance to accommodate the cumulative precision deviation.
        { make_grad_sh,  true,  1.001f/255 },
        { make_image_sh, false, 1.0f/255   },
        { make_cf_sh,    true,  1.0f/255   },
    };

    SkPaint paint;
    for (const auto& rec : recs) {
        uint32_t storage[300];
        paint.setShader(rec.fFact());
        // Encourage 4f context selection. At some point we may need
        // to instantiate two separate contexts for optimal 4b/4f selection.
        const SkShader::ContextRec contextRec(paint, SkMatrix::I(), nullptr,
                                              SkShader::ContextRec::kPM4f_DstType);
        SkASSERT(paint.getShader()->contextSize(contextRec) <= sizeof(storage));
        SkShader::Context* ctx = paint.getShader()->createContext(contextRec, storage);
        if (rec.fSupports4f) {
            const int N = 100;
            SkPM4f buffer4f[N];
            ctx->shadeSpan4f(0, 0, buffer4f, N);
            SkPMColor buffer4b[N];
            ctx->shadeSpan(0, 0, buffer4b, N);
            REPORTER_ASSERT(reporter, compare_spans(buffer4f, buffer4b, N, rec.fTolerance));
        }
        ctx->~Context();
    }
}
    void onDraw(int loops, SkCanvas*) override {
        int width = fSrcSize.fWidth;
        int height = fSrcSize.fHeight;

        SkAutoTMalloc<SkPMColor> buffer4b(width*height);

        uint32_t storage[kSkBlitterContextSize];
        const SkShader::ContextRec rec(fPaint, fM, nullptr,
                                       SkShader::ContextRec::kPMColor_DstType);
        SkASSERT(fPaint.getShader()->contextSize(rec) <= sizeof(storage));
        SkShader::Context* ctx = fPaint.getShader()->createContext(rec, storage);

        int count = 100;

        for (int n = 0; n < 1000*loops; n++) {
            ctx->shadeSpan(3, 6, buffer4b, count);
        }

        ctx->~Context();
    }
示例#4
0
void SkComposeShader::ComposeShaderContext::shadeSpan(int x, int y, SkPMColor result[], int count) {
    SkShader::Context* shaderContextA = fShaderContextA;
    SkShader::Context* shaderContextB = fShaderContextB;
    SkXfermode*        mode = static_cast<const SkComposeShader&>(fShader).fMode;
    unsigned           scale = SkAlpha255To256(this->getPaintAlpha());

#ifdef SK_BUILD_FOR_ANDROID
    scale = 256;    // ugh -- maintain old bug/behavior for now
#endif

    SkPMColor   tmp[TMP_COLOR_COUNT];

    if (NULL == mode) {   // implied SRC_OVER
        // TODO: when we have a good test-case, should use SkBlitRow::Proc32
        // for these loops
        do {
            int n = count;
            if (n > TMP_COLOR_COUNT) {
                n = TMP_COLOR_COUNT;
            }

            shaderContextA->shadeSpan(x, y, result, n);
            shaderContextB->shadeSpan(x, y, tmp, n);

            if (256 == scale) {
                for (int i = 0; i < n; i++) {
                    result[i] = SkPMSrcOver(tmp[i], result[i]);
                }
            } else {
                for (int i = 0; i < n; i++) {
                    result[i] = SkAlphaMulQ(SkPMSrcOver(tmp[i], result[i]),
                                            scale);
                }
            }

            result += n;
            x += n;
            count -= n;
        } while (count > 0);
    } else {    // use mode for the composition
        do {
            int n = count;
            if (n > TMP_COLOR_COUNT) {
                n = TMP_COLOR_COUNT;
            }

            shaderContextA->shadeSpan(x, y, result, n);
            shaderContextB->shadeSpan(x, y, tmp, n);
            mode->xfer32(result, tmp, n, NULL);

            if (256 != scale) {
                for (int i = 0; i < n; i++) {
                    result[i] = SkAlphaMulQ(result[i], scale);
                }
            }

            result += n;
            x += n;
            count -= n;
        } while (count > 0);
    }
}