Blend.cpp revision 44eb2c00861098dd3e2950d923646814b4cc57c2
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 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 122