blob: 789f6ccf3d3e105804a84552c06e2cb6bd47a8d6 [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) {
Chris Craik03188872015-02-02 18:39:33 -080082 GLenum srcMode;
83 GLenum dstMode;
84 getFactors(mode, swapSrcDst, &srcMode, &dstMode);
85 setFactors(srcMode, dstMode);
Chris Craik44eb2c02015-01-29 09:45:09 -080086}
87
88void Blend::disable() {
89 if (mEnabled) {
90 glDisable(GL_BLEND);
91 mEnabled = false;
92 }
93}
94
95void Blend::invalidate() {
96 syncEnabled();
97 mSrcMode = mDstMode = GL_ZERO;
98}
99
100void Blend::syncEnabled() {
101 if (mEnabled) {
102 glEnable(GL_BLEND);
103 } else {
104 glDisable(GL_BLEND);
105 }
106}
107
Chris Craik03188872015-02-02 18:39:33 -0800108void Blend::getFactors(SkXfermode::Mode mode, bool swapSrcDst, GLenum* outSrc, GLenum* outDst) {
109 *outSrc = swapSrcDst ? kBlendsSwap[mode].src : kBlends[mode].src;
110 *outDst = swapSrcDst ? kBlendsSwap[mode].dst : kBlends[mode].dst;
111}
112
113void 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
Chris Craik0519c812015-02-11 13:17:06 -0800122 if (srcMode != mSrcMode || dstMode != mDstMode) {
Chris Craik03188872015-02-02 18:39:33 -0800123 glBlendFunc(srcMode, dstMode);
124 mSrcMode = srcMode;
125 mDstMode = dstMode;
126 }
127 }
128}
129
Chris Craik117bdbc2015-02-05 10:12:38 -0800130void Blend::dump() {
131 ALOGD("Blend: enabled %d, func src %d, dst %d", mEnabled, mSrcMode, mDstMode);
132}
133
Chris Craik44eb2c02015-01-29 09:45:09 -0800134} /* namespace uirenderer */
135} /* namespace android */
136