blob: 3e7b72183362120c3a929979a8e56cb18539339c [file] [log] [blame]
Chris Craik44eb2c02015-01-29 09:45:09 -08001/*
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
21namespace android {
22namespace uirenderer {
23
24/**
25 * Structure mapping Skia xfermodes to OpenGL blending factors.
26 */
27struct 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]
35const 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.
56const 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
74Blend::Blend()
75 : mEnabled(false)
76 , mSrcMode(GL_ZERO)
77 , mDstMode(GL_ZERO) {
78 // gl blending off by default
79}
80
81void Blend::enable(SkXfermode::Mode mode, bool swapSrcDst) {
82 // enable
83 if (!mEnabled) {
84 glEnable(GL_BLEND);
85 mEnabled = true;
86 }
87
88 // select blend mode
89 GLenum sourceMode = swapSrcDst ? kBlendsSwap[mode].src : kBlends[mode].src;
90 GLenum destMode = swapSrcDst ? kBlendsSwap[mode].dst : kBlends[mode].dst;
91
92 if (sourceMode != mSrcMode || destMode != mSrcMode) {
93 glBlendFunc(sourceMode, destMode);
94 mSrcMode = sourceMode;
95 mDstMode = destMode;
96 }
97}
98
99void Blend::disable() {
100 if (mEnabled) {
101 glDisable(GL_BLEND);
102 mEnabled = false;
103 }
104}
105
106void Blend::invalidate() {
107 syncEnabled();
108 mSrcMode = mDstMode = GL_ZERO;
109}
110
111void Blend::syncEnabled() {
112 if (mEnabled) {
113 glEnable(GL_BLEND);
114 } else {
115 glDisable(GL_BLEND);
116 }
117}
118
119} /* namespace uirenderer */
120} /* namespace android */
121