1 /*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include <renderstate/Blend.h>
17 #include "Program.h"
18
19 #include "ShadowTessellator.h"
20
21 namespace android {
22 namespace uirenderer {
23
24 /**
25 * Structure mapping Skia xfermodes to OpenGL blending factors.
26 */
27 struct Blender {
28 SkXfermode::Mode mode;
29 GLenum src;
30 GLenum dst;
31 };
32
33 // assumptions made by lookup tables in either this file or ProgramCache
34 static_assert(0 == SkXfermode::kClear_Mode, "SkXfermode enums have changed");
35 static_assert(1 == SkXfermode::kSrc_Mode, "SkXfermode enums have changed");
36 static_assert(2 == SkXfermode::kDst_Mode, "SkXfermode enums have changed");
37 static_assert(3 == SkXfermode::kSrcOver_Mode, "SkXfermode enums have changed");
38 static_assert(4 == SkXfermode::kDstOver_Mode, "SkXfermode enums have changed");
39 static_assert(5 == SkXfermode::kSrcIn_Mode, "SkXfermode enums have changed");
40 static_assert(6 == SkXfermode::kDstIn_Mode, "SkXfermode enums have changed");
41 static_assert(7 == SkXfermode::kSrcOut_Mode, "SkXfermode enums have changed");
42 static_assert(8 == SkXfermode::kDstOut_Mode, "SkXfermode enums have changed");
43 static_assert(9 == SkXfermode::kSrcATop_Mode, "SkXfermode enums have changed");
44 static_assert(10 == SkXfermode::kDstATop_Mode, "SkXfermode enums have changed");
45 static_assert(11 == SkXfermode::kXor_Mode, "SkXfermode enums have changed");
46 static_assert(12 == SkXfermode::kPlus_Mode, "SkXfermode enums have changed");
47 static_assert(13 == SkXfermode::kModulate_Mode, "SkXfermode enums have changed");
48 static_assert(14 == SkXfermode::kScreen_Mode, "SkXfermode enums have changed");
49 static_assert(15 == SkXfermode::kOverlay_Mode, "SkXfermode enums have changed");
50 static_assert(16 == SkXfermode::kDarken_Mode, "SkXfermode enums have changed");
51 static_assert(17 == SkXfermode::kLighten_Mode, "SkXfermode enums have changed");
52
53 // In this array, the index of each Blender equals the value of the first
54 // entry. For instance, gBlends[1] == gBlends[SkXfermode::kSrc_Mode]
55 const Blender kBlends[] = {
56 { SkXfermode::kClear_Mode, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA },
57 { SkXfermode::kSrc_Mode, GL_ONE, GL_ZERO },
58 { SkXfermode::kDst_Mode, GL_ZERO, GL_ONE },
59 { SkXfermode::kSrcOver_Mode, GL_ONE, GL_ONE_MINUS_SRC_ALPHA },
60 { SkXfermode::kDstOver_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE },
61 { SkXfermode::kSrcIn_Mode, GL_DST_ALPHA, GL_ZERO },
62 { SkXfermode::kDstIn_Mode, GL_ZERO, GL_SRC_ALPHA },
63 { SkXfermode::kSrcOut_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ZERO },
64 { SkXfermode::kDstOut_Mode, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA },
65 { SkXfermode::kSrcATop_Mode, GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
66 { SkXfermode::kDstATop_Mode, GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA },
67 { SkXfermode::kXor_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
68 { SkXfermode::kPlus_Mode, GL_ONE, GL_ONE },
69 { SkXfermode::kModulate_Mode, GL_ZERO, GL_SRC_COLOR },
70 { SkXfermode::kScreen_Mode, GL_ONE, GL_ONE_MINUS_SRC_COLOR }
71 };
72
73 // This array contains the swapped version of each SkXfermode. For instance
74 // this array's SrcOver blending mode is actually DstOver. You can refer to
75 // createLayer() for more information on the purpose of this array.
76 const Blender kBlendsSwap[] = {
77 { SkXfermode::kClear_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ZERO },
78 { SkXfermode::kSrc_Mode, GL_ZERO, GL_ONE },
79 { SkXfermode::kDst_Mode, GL_ONE, GL_ZERO },
80 { SkXfermode::kSrcOver_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE },
81 { SkXfermode::kDstOver_Mode, GL_ONE, GL_ONE_MINUS_SRC_ALPHA },
82 { SkXfermode::kSrcIn_Mode, GL_ZERO, GL_SRC_ALPHA },
83 { SkXfermode::kDstIn_Mode, GL_DST_ALPHA, GL_ZERO },
84 { SkXfermode::kSrcOut_Mode, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA },
85 { SkXfermode::kDstOut_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ZERO },
86 { SkXfermode::kSrcATop_Mode, GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA },
87 { SkXfermode::kDstATop_Mode, GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
88 { SkXfermode::kXor_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
89 { SkXfermode::kPlus_Mode, GL_ONE, GL_ONE },
90 { SkXfermode::kModulate_Mode, GL_DST_COLOR, GL_ZERO },
91 { SkXfermode::kScreen_Mode, GL_ONE_MINUS_DST_COLOR, GL_ONE }
92 };
93
Blend()94 Blend::Blend()
95 : mEnabled(false)
96 , mSrcMode(GL_ZERO)
97 , mDstMode(GL_ZERO) {
98 // gl blending off by default
99 }
100
invalidate()101 void Blend::invalidate() {
102 syncEnabled();
103 mSrcMode = mDstMode = GL_ZERO;
104 }
105
syncEnabled()106 void Blend::syncEnabled() {
107 if (mEnabled) {
108 glEnable(GL_BLEND);
109 } else {
110 glDisable(GL_BLEND);
111 }
112 }
113
getFactors(SkXfermode::Mode mode,ModeOrderSwap modeUsage,GLenum * outSrc,GLenum * outDst)114 void Blend::getFactors(SkXfermode::Mode mode, ModeOrderSwap modeUsage, GLenum* outSrc, GLenum* outDst) {
115 *outSrc = (modeUsage == ModeOrderSwap::Swap) ? kBlendsSwap[mode].src : kBlends[mode].src;
116 *outDst = (modeUsage == ModeOrderSwap::Swap) ? kBlendsSwap[mode].dst : kBlends[mode].dst;
117 }
118
setFactors(GLenum srcMode,GLenum dstMode)119 void Blend::setFactors(GLenum srcMode, GLenum dstMode) {
120 if (srcMode == GL_ZERO && dstMode == GL_ZERO) {
121 // disable blending
122 if (mEnabled) {
123 glDisable(GL_BLEND);
124 mEnabled = false;
125 }
126 } else {
127 // enable blending
128 if (!mEnabled) {
129 glEnable(GL_BLEND);
130 mEnabled = true;
131 }
132
133 if (srcMode != mSrcMode || dstMode != mDstMode) {
134 glBlendFunc(srcMode, dstMode);
135 mSrcMode = srcMode;
136 mDstMode = dstMode;
137 }
138 }
139 }
140
dump()141 void Blend::dump() {
142 ALOGD("Blend: enabled %d, func src %d, dst %d", mEnabled, mSrcMode, mDstMode);
143 }
144
145 } /* namespace uirenderer */
146 } /* namespace android */
147
148