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 // In this array, the index of each Blender equals the value of the first
34 // entry. For instance, gBlends[1] == gBlends[SkXfermode::kSrc_Mode]
35 const Blender kBlends[] = {
36 { SkXfermode::kClear_Mode, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA },
37 { SkXfermode::kSrc_Mode, GL_ONE, GL_ZERO },
38 { SkXfermode::kDst_Mode, GL_ZERO, GL_ONE },
39 { SkXfermode::kSrcOver_Mode, GL_ONE, GL_ONE_MINUS_SRC_ALPHA },
40 { SkXfermode::kDstOver_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE },
41 { SkXfermode::kSrcIn_Mode, GL_DST_ALPHA, GL_ZERO },
42 { SkXfermode::kDstIn_Mode, GL_ZERO, GL_SRC_ALPHA },
43 { SkXfermode::kSrcOut_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ZERO },
44 { SkXfermode::kDstOut_Mode, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA },
45 { SkXfermode::kSrcATop_Mode, GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
46 { SkXfermode::kDstATop_Mode, GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA },
47 { SkXfermode::kXor_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
48 { SkXfermode::kPlus_Mode, GL_ONE, GL_ONE },
49 { SkXfermode::kModulate_Mode, GL_ZERO, GL_SRC_COLOR },
50 { SkXfermode::kScreen_Mode, GL_ONE, GL_ONE_MINUS_SRC_COLOR }
51 };
52
53 // This array contains the swapped version of each SkXfermode. For instance
54 // this array's SrcOver blending mode is actually DstOver. You can refer to
55 // createLayer() for more information on the purpose of this array.
56 const Blender kBlendsSwap[] = {
57 { SkXfermode::kClear_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ZERO },
58 { SkXfermode::kSrc_Mode, GL_ZERO, GL_ONE },
59 { SkXfermode::kDst_Mode, GL_ONE, GL_ZERO },
60 { SkXfermode::kSrcOver_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE },
61 { SkXfermode::kDstOver_Mode, GL_ONE, GL_ONE_MINUS_SRC_ALPHA },
62 { SkXfermode::kSrcIn_Mode, GL_ZERO, GL_SRC_ALPHA },
63 { SkXfermode::kDstIn_Mode, GL_DST_ALPHA, GL_ZERO },
64 { SkXfermode::kSrcOut_Mode, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA },
65 { SkXfermode::kDstOut_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ZERO },
66 { SkXfermode::kSrcATop_Mode, GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA },
67 { SkXfermode::kDstATop_Mode, GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
68 { SkXfermode::kXor_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
69 { SkXfermode::kPlus_Mode, GL_ONE, GL_ONE },
70 { SkXfermode::kModulate_Mode, GL_DST_COLOR, GL_ZERO },
71 { SkXfermode::kScreen_Mode, GL_ONE_MINUS_DST_COLOR, GL_ONE }
72 };
73
Blend()74 Blend::Blend()
75 : mEnabled(false)
76 , mSrcMode(GL_ZERO)
77 , mDstMode(GL_ZERO) {
78 // gl blending off by default
79 }
80
enable(SkXfermode::Mode mode,ModeOrderSwap modeUsage)81 void Blend::enable(SkXfermode::Mode mode, ModeOrderSwap modeUsage) {
82 GLenum srcMode;
83 GLenum dstMode;
84 getFactors(mode, modeUsage, &srcMode, &dstMode);
85 setFactors(srcMode, dstMode);
86 }
87
disable()88 void Blend::disable() {
89 if (mEnabled) {
90 glDisable(GL_BLEND);
91 mEnabled = false;
92 }
93 }
94
invalidate()95 void Blend::invalidate() {
96 syncEnabled();
97 mSrcMode = mDstMode = GL_ZERO;
98 }
99
syncEnabled()100 void Blend::syncEnabled() {
101 if (mEnabled) {
102 glEnable(GL_BLEND);
103 } else {
104 glDisable(GL_BLEND);
105 }
106 }
107
getFactors(SkXfermode::Mode mode,ModeOrderSwap modeUsage,GLenum * outSrc,GLenum * outDst)108 void Blend::getFactors(SkXfermode::Mode mode, ModeOrderSwap modeUsage, GLenum* outSrc, GLenum* outDst) {
109 *outSrc = (modeUsage == ModeOrderSwap::Swap) ? kBlendsSwap[mode].src : kBlends[mode].src;
110 *outDst = (modeUsage == ModeOrderSwap::Swap) ? kBlendsSwap[mode].dst : kBlends[mode].dst;
111 }
112
setFactors(GLenum srcMode,GLenum dstMode)113 void Blend::setFactors(GLenum srcMode, GLenum dstMode) {
114 if (srcMode == GL_ZERO && dstMode == GL_ZERO) {
115 disable();
116 } else {
117 if (!mEnabled) {
118 glEnable(GL_BLEND);
119 mEnabled = true;
120 }
121
122 if (srcMode != mSrcMode || dstMode != mDstMode) {
123 glBlendFunc(srcMode, dstMode);
124 mSrcMode = srcMode;
125 mDstMode = dstMode;
126 }
127 }
128 }
129
dump()130 void Blend::dump() {
131 ALOGD("Blend: enabled %d, func src %d, dst %d", mEnabled, mSrcMode, mDstMode);
132 }
133
134 } /* namespace uirenderer */
135 } /* namespace android */
136
137