2008-12-17 15:59:43 +00:00
|
|
|
/*
|
2011-07-28 14:26:00 +00:00
|
|
|
* Copyright 2006 The Android Open Source Project
|
2008-12-17 15:59:43 +00:00
|
|
|
*
|
2011-07-28 14:26:00 +00:00
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
2008-12-17 15:59:43 +00:00
|
|
|
*/
|
|
|
|
|
2017-06-06 14:41:18 +00:00
|
|
|
#include "SkBlendModePriv.h"
|
2008-12-17 15:59:43 +00:00
|
|
|
#include "SkColorPriv.h"
|
2012-08-07 21:35:13 +00:00
|
|
|
#include "SkMathPriv.h"
|
2016-05-05 23:05:56 +00:00
|
|
|
#include "SkOnce.h"
|
2015-07-31 18:50:27 +00:00
|
|
|
#include "SkOpts.h"
|
2017-06-13 09:57:47 +00:00
|
|
|
#include "SkPM4f.h"
|
2016-07-25 18:00:47 +00:00
|
|
|
#include "SkRasterPipeline.h"
|
2014-03-28 20:04:11 +00:00
|
|
|
#include "SkReadBuffer.h"
|
2013-01-22 14:32:09 +00:00
|
|
|
#include "SkString.h"
|
2014-03-28 20:04:11 +00:00
|
|
|
#include "SkWriteBuffer.h"
|
2017-06-13 09:57:47 +00:00
|
|
|
#include "SkXfermodePriv.h"
|
2013-10-17 16:29:34 +00:00
|
|
|
|
2016-06-09 15:01:03 +00:00
|
|
|
#if SK_SUPPORT_GPU
|
|
|
|
#include "GrFragmentProcessor.h"
|
|
|
|
#include "effects/GrCustomXfermode.h"
|
|
|
|
#include "effects/GrPorterDuffXferProcessor.h"
|
|
|
|
#include "effects/GrXfermodeFragmentProcessor.h"
|
|
|
|
#endif
|
|
|
|
|
2017-06-13 09:57:47 +00:00
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
2013-03-05 16:23:59 +00:00
|
|
|
|
2017-06-13 09:57:47 +00:00
|
|
|
class SkProcCoeffXfermode : public SkXfermode {
|
|
|
|
public:
|
|
|
|
SkProcCoeffXfermode(SkBlendMode mode) : fMode(mode) {}
|
2013-03-05 16:23:59 +00:00
|
|
|
|
2017-06-13 09:57:47 +00:00
|
|
|
void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
|
|
|
|
const SkAlpha aa[]) const override {
|
|
|
|
SkASSERT(dst && src && count >= 0);
|
2013-03-05 16:23:59 +00:00
|
|
|
|
2017-06-13 09:57:47 +00:00
|
|
|
bool needs_swap = (kN32_SkColorType == kBGRA_8888_SkColorType) &&
|
|
|
|
SkBlendMode_CaresAboutRBOrder(fMode);
|
2013-03-05 16:23:59 +00:00
|
|
|
|
2017-06-13 09:57:47 +00:00
|
|
|
SkRasterPipeline_<256> p;
|
2013-03-05 16:23:59 +00:00
|
|
|
|
2017-06-13 09:57:47 +00:00
|
|
|
p.append(SkRasterPipeline::load_8888, &dst);
|
|
|
|
if (needs_swap) {
|
|
|
|
p.append(SkRasterPipeline::swap_rb);
|
|
|
|
}
|
|
|
|
p.append(SkRasterPipeline::move_src_dst);
|
|
|
|
p.append(SkRasterPipeline::load_8888, &src);
|
|
|
|
if (needs_swap) {
|
|
|
|
p.append(SkRasterPipeline::swap_rb);
|
2013-03-05 16:23:59 +00:00
|
|
|
}
|
|
|
|
|
2017-06-13 09:57:47 +00:00
|
|
|
SkBlendMode_AppendStagesNoClamp(fMode, &p);
|
|
|
|
if (aa) {
|
|
|
|
p.append(SkRasterPipeline::lerp_u8, &aa);
|
|
|
|
}
|
|
|
|
SkBlendMode_AppendClampIfNeeded(fMode, &p);
|
2013-03-05 16:23:59 +00:00
|
|
|
|
2017-06-13 09:57:47 +00:00
|
|
|
if (needs_swap) {
|
|
|
|
p.append(SkRasterPipeline::swap_rb);
|
|
|
|
}
|
|
|
|
p.append(SkRasterPipeline::store_8888, &dst);
|
|
|
|
p.run(0, 0, count);
|
2013-03-05 16:23:59 +00:00
|
|
|
}
|
|
|
|
|
2017-06-13 09:57:47 +00:00
|
|
|
private:
|
|
|
|
const SkBlendMode fMode;
|
2016-02-09 19:59:24 +00:00
|
|
|
|
2017-06-13 09:57:47 +00:00
|
|
|
typedef SkXfermode INHERITED;
|
2011-02-08 19:28:07 +00:00
|
|
|
};
|
|
|
|
|
2017-06-08 03:05:45 +00:00
|
|
|
const char* SkBlendMode_Name(SkBlendMode mode) {
|
|
|
|
SkASSERT((unsigned) mode <= (unsigned)SkBlendMode::kLastMode);
|
2013-04-01 12:51:34 +00:00
|
|
|
const char* gModeStrings[] = {
|
2013-01-22 14:32:09 +00:00
|
|
|
"Clear", "Src", "Dst", "SrcOver", "DstOver", "SrcIn", "DstIn",
|
|
|
|
"SrcOut", "DstOut", "SrcATop", "DstATop", "Xor", "Plus",
|
2013-01-30 21:36:11 +00:00
|
|
|
"Modulate", "Screen", "Overlay", "Darken", "Lighten", "ColorDodge",
|
2013-04-01 12:51:34 +00:00
|
|
|
"ColorBurn", "HardLight", "SoftLight", "Difference", "Exclusion",
|
|
|
|
"Multiply", "Hue", "Saturation", "Color", "Luminosity"
|
2013-01-22 14:32:09 +00:00
|
|
|
};
|
2017-06-08 03:05:45 +00:00
|
|
|
return gModeStrings[(int)mode];
|
|
|
|
static_assert(SK_ARRAY_COUNT(gModeStrings) == (size_t)SkBlendMode::kLastMode + 1, "mode_count");
|
2016-11-15 21:44:34 +00:00
|
|
|
}
|
|
|
|
|
2016-10-28 19:42:34 +00:00
|
|
|
sk_sp<SkXfermode> SkXfermode::Make(SkBlendMode mode) {
|
|
|
|
if ((unsigned)mode > (unsigned)SkBlendMode::kLastMode) {
|
2013-10-04 16:52:55 +00:00
|
|
|
// report error
|
2015-08-27 14:41:13 +00:00
|
|
|
return nullptr;
|
2013-10-04 16:52:55 +00:00
|
|
|
}
|
2011-04-13 21:12:04 +00:00
|
|
|
|
2015-08-27 14:41:13 +00:00
|
|
|
// Skia's "default" mode is srcover. nullptr in SkPaint is interpreted as srcover
|
|
|
|
// so we can just return nullptr from the factory.
|
2016-10-28 19:42:34 +00:00
|
|
|
if (SkBlendMode::kSrcOver == mode) {
|
2015-08-27 14:41:13 +00:00
|
|
|
return nullptr;
|
2013-10-04 16:52:55 +00:00
|
|
|
}
|
|
|
|
|
2016-10-28 19:42:34 +00:00
|
|
|
const int COUNT_BLENDMODES = (int)SkBlendMode::kLastMode + 1;
|
2016-05-05 23:05:56 +00:00
|
|
|
|
2016-10-28 19:42:34 +00:00
|
|
|
static SkOnce once[COUNT_BLENDMODES];
|
|
|
|
static SkXfermode* cached[COUNT_BLENDMODES];
|
2016-05-05 23:05:56 +00:00
|
|
|
|
2016-10-28 19:42:34 +00:00
|
|
|
once[(int)mode]([mode] {
|
2017-06-12 02:14:14 +00:00
|
|
|
if (auto xfermode = SkOpts::create_xfermode(mode)) {
|
2016-10-28 19:42:34 +00:00
|
|
|
cached[(int)mode] = xfermode;
|
2016-05-05 23:05:56 +00:00
|
|
|
} else {
|
2017-06-13 09:57:47 +00:00
|
|
|
cached[(int)mode] = new SkProcCoeffXfermode(mode);
|
2015-09-09 16:09:53 +00:00
|
|
|
}
|
2016-05-05 23:05:56 +00:00
|
|
|
});
|
2016-10-28 19:42:34 +00:00
|
|
|
return sk_ref_sp(cached[(int)mode]);
|
2008-12-17 15:59:43 +00:00
|
|
|
}
|
|
|
|
|
2016-10-06 00:33:02 +00:00
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
bool SkXfermode::IsOpaque(SkBlendMode mode, SrcColorOpacity opacityType) {
|
2017-06-06 14:41:18 +00:00
|
|
|
SkBlendModeCoeff src, dst;
|
|
|
|
if (!SkBlendMode_AsCoeff(mode, &src, &dst)) {
|
|
|
|
return false;
|
|
|
|
}
|
2016-10-06 00:33:02 +00:00
|
|
|
|
2017-06-06 14:41:18 +00:00
|
|
|
switch (src) {
|
|
|
|
case SkBlendModeCoeff::kDA:
|
|
|
|
case SkBlendModeCoeff::kDC:
|
|
|
|
case SkBlendModeCoeff::kIDA:
|
|
|
|
case SkBlendModeCoeff::kIDC:
|
2016-10-06 00:33:02 +00:00
|
|
|
return false;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2017-06-06 14:41:18 +00:00
|
|
|
switch (dst) {
|
|
|
|
case SkBlendModeCoeff::kZero:
|
2016-10-06 00:33:02 +00:00
|
|
|
return true;
|
2017-06-06 14:41:18 +00:00
|
|
|
case SkBlendModeCoeff::kISA:
|
2016-10-06 00:33:02 +00:00
|
|
|
return kOpaque_SrcColorOpacity == opacityType;
|
2017-06-06 14:41:18 +00:00
|
|
|
case SkBlendModeCoeff::kSA:
|
2016-10-06 00:33:02 +00:00
|
|
|
return kTransparentBlack_SrcColorOpacity == opacityType ||
|
|
|
|
kTransparentAlpha_SrcColorOpacity == opacityType;
|
2017-06-06 14:41:18 +00:00
|
|
|
case SkBlendModeCoeff::kSC:
|
2016-10-06 00:33:02 +00:00
|
|
|
return kTransparentBlack_SrcColorOpacity == opacityType;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if SK_SUPPORT_GPU
|
2017-01-09 16:46:10 +00:00
|
|
|
const GrXPFactory* SkBlendMode_AsXPFactory(SkBlendMode mode) {
|
2017-06-06 14:41:18 +00:00
|
|
|
if (SkBlendMode_AsCoeff(mode, nullptr, nullptr)) {
|
2017-01-09 16:46:10 +00:00
|
|
|
const GrXPFactory* result = GrPorterDuffXPFactory::Get(mode);
|
2016-10-06 00:33:02 +00:00
|
|
|
SkASSERT(result);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2016-10-28 19:42:34 +00:00
|
|
|
SkASSERT(GrCustomXfermode::IsSupportedMode(mode));
|
2017-01-09 16:46:10 +00:00
|
|
|
return GrCustomXfermode::Get(mode);
|
2016-10-06 00:33:02 +00:00
|
|
|
}
|
|
|
|
#endif
|
2016-10-26 19:32:26 +00:00
|
|
|
|