一.几个重要的类
1. Description
Description.cpp中主要是接收一些来自GLES20RenderEngine设置参数保存在其成员变量中,主要用到GLES 2.0的。并将数据设置到Program中。
frameworks/native/services/surfaceflinger/RenderEngine/Description.cpp
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
//这个后期可以研究一下
57 enum class TransferFunction : int {
58 LINEAR,
59 SRGB,
60 ST2084,
61 HLG, // Hybrid Log-Gamma for HDR.
62 };
//下面这两个类是允许直接访问私有成员变量的
67private:
68 friend class Program;
69 friend class ProgramCache;
2. Program
Program类中主要完成一些glsl的初始化工作,提供一些接口函数,也提供调试用的函数(dumpShader),接收Description中值设置到glsl中uniform参数。
frameworks/native/services/surfaceflinger/RenderEngine/Program.cpp
29Program::Program(const ProgramCache::Key& /*needs*/, const char* vertex, const char* fragment)
30 : mInitialized(false) {
//1. 针对glsl的编译----固定方式
31 GLuint vertexId = buildShader(vertex, GL_VERTEX_SHADER);
32 GLuint fragmentId = buildShader(fragment, GL_FRAGMENT_SHADER);
33 GLuint programId = glCreateProgram();
34 glAttachShader(programId, vertexId);
35 glAttachShader(programId, fragmentId);
//attach in 的index,见:enum { position = 0, texCoords = 1 };
36 glBindAttribLocation(programId, position, "position");
37 glBindAttribLocation(programId, texCoords, "texCoords");
38 glLinkProgram(programId);
...
56 } else {
//2.保存变量
57 mProgram = programId;
58 mVertexShader = vertexId;
59 mFragmentShader = fragmentId;
60 mInitialized = true;
//3.获取glsl中的uniform变量index
61 mProjectionMatrixLoc = glGetUniformLocation(programId, "projection");
62 mTextureMatrixLoc = glGetUniformLocation(programId, "texture");
63 mSamplerLoc = glGetUniformLocation(programId, "sampler");
64 mColorLoc = glGetUniformLocation(programId, "color");
65 mDisplayMaxLuminanceLoc = glGetUniformLocation(programId, "displayMaxLuminance");
66 mInputTransformMatrixLoc = glGetUniformLocation(programId, "inputTransformMatrix");
67 mOutputTransformMatrixLoc = glGetUniformLocation(programId, "outputTransformMatrix");
68
69 // set-up the default values for our uniforms
70 glUseProgram(programId);
//4.设置projection
71 glUniformMatrix4fv(mProjectionMatrixLoc, 1, GL_FALSE, mat4().asArray());
//5.开启顶点position属性
72 glEnableVertexAttribArray(0);
73 }
//提供一些接口函数
82void Program::use() {
83 glUseProgram(mProgram);
84}
86GLuint Program::getAttrib(const char* name) const {
87 // TODO: maybe use a local cache
88 return glGetAttribLocation(mProgram, name);
89}
91GLint Program::getUniform(const char* name) const {
92 // TODO: maybe use a local cache
93 return glGetUniformLocation(mProgram, name);
94}
//最关键的设置uniform变量的值,从Description中接收来的数据
125void Program::setUniforms(const Description& desc) {
126 // TODO: we should have a mechanism here to not always reset uniforms that
127 // didn't change for this program.
128
129 if (mSamplerLoc >= 0) {
130 glUniform1i(mSamplerLoc, 0);
131 glUniformMatrix4fv(mTextureMatrixLoc, 1, GL_FALSE, desc.mTexture.getMatrix().asArray());
132 }
133 if (mColorLoc >= 0) {
134 const float color[4] = {desc.mColor.r, desc.mColor.g, desc.mColor.b, desc.mColor.a};
135 glUniform4fv(mColorLoc, 1, color);
136 }
137 if (mInputTransformMatrixLoc >= 0) {
138 // If the input transform matrix is not identity matrix, we want to merge
139 // the saturation matrix with input transform matrix so that the saturation
140 // matrix is applied at the correct stage.
141 mat4 inputTransformMatrix = mat4(desc.mInputTransformMatrix) * desc.mSaturationMatrix;
142 glUniformMatrix4fv(mInputTransformMatrixLoc, 1, GL_FALSE, inputTransformMatrix.asArray());
143 }
144 if (mOutputTransformMatrixLoc >= 0) {
145 // The output transform matrix and color matrix can be combined as one matrix
146 // that is applied right before applying OETF.
147 mat4 outputTransformMatrix = desc.mColorMatrix * desc.mOutputTransformMatrix;
148 // If there is no input transform matrix, we want to merge the saturation
149 // matrix with output transform matrix to avoid extra matrix multiplication
150 // in shader.
151 if (mInputTransformMatrixLoc < 0) {
152 outputTransformMatrix *= desc.mSaturationMatrix;
153 }
154 glUniformMatrix4fv(mOutputTransformMatrixLoc, 1, GL_FALSE,
155 outputTransformMatrix.asArray());
156 }
157 if (mDisplayMaxLuminanceLoc >= 0) {
158 glUniform1f(mDisplayMaxLuminanceLoc, desc.mDisplayMaxLuminance);
159 }
160 // these uniforms are always present
161 glUniformMatrix4fv(mProjectionMatrixLoc, 1, GL_FALSE, desc.mProjectionMatrix.asArray());
162}
3.ProgramCache
ProgramCache 接收Description的信息,完成glsl的初始化工作入口:编译shader、set Uniform值。
frameworks/native/services/surfaceflinger/RenderEngine/ProgramCache.cpp
//有trace哦,可以抓取看看哦
17#define ATRACE_TAG ATRACE_TAG_GRAPHICS
19#include <GLES2/gl2.h>
20#include <GLES2/gl2ext.h>
23#include <utils/Trace.h>
666void ProgramCache::useProgram(const Description& description) {
667 // generate the key for the shader based on the description
//1.根据Descrption生成对应的needs
668 Key needs(computeKey(description));
669
670 // look-up the program in the cache
//2.根据needs找到之前加入的program,如果第一次的话等于nullptr
671 Program* program = mCache.valueFor(needs);
672 if (program == nullptr) {
673 // we didn't find our program, so generate one...
674 nsecs_t time = -systemTime();
//3.编译shader
675 program = generateProgram(needs);
676 mCache.add(needs, program);
677 time += systemTime();
678 //打印出的needs很有意思,可以根据位去判断哪些东西打开了
679 ALOGV(">>> generated new program: needs=%08X, time=%u ms (%zu programs)", needs.mKey,
680 uint32_t(ns2ms(time)), mCache.size());
681 }
682
683 // here we have a suitable program for this description
684 if (program->isValid()) {
//4.set Uniform值
685 program->use();
686 program->setUniforms(description);
687 }
688}
Key::TEXTURE_MASK
Key::ALPHA_MASK -> description.mColor.a
Key::BLEND_MASK -> description.mPremultipliedAlpha
Key::OPACITY_MASK -> description.mOpaque
Key::INPUT_TRANSFORM_MATRIX_MASK -> description.hasInputTransformMatrix
Key::OUTPUT_TRANSFORM_MATRIX_MASK,
Key::Y410_BT2020_MASK -> description.mY410BT2020
Key::INPUT_TF_MASK -> description.mInputTransferFunction
Key::OUTPUT_TF_MASK -> description.mOutputTransferFunction
下面这个函数主要是生成对应的glsl:
653Program* ProgramCache::generateProgram(const Key& needs) {
654 ATRACE_CALL();
655
656 // vertex shader
657 String8 vs = generateVertexShader(needs);
658
659 // fragment shader
660 String8 fs = generateFragmentShader(needs);
661
662 Program* program = new Program(needs, vs.string(), fs.string());
663 return program;
664}
最后我们看下vs和fs的结果呢!
vs如下:
//1.只有开启纹理才会有(TEXTURE_2D、TEXTURE_EXT )
"attribute vec4 texCoords;"
//1.只有开启纹理才会有(TEXTURE_2D、TEXTURE_EXT )
"varying vec2 outTexCoords;"
//通用部分
"attribute vec4 position;"
"uniform mat4 projection;"
"uniform mat4 texture;"
"void main(void) {"
"gl_Position = projection * position;"
//2.只有开启纹理才会有(TEXTURE_2D、TEXTURE_EXT )
"outTexCoords = (texture * texCoords).st;"
"}"
上面1、2两处会首先根据Description中mTextureEnabled判断是否开启纹理,如果开启的话开启的是TEXTURE_2D还是TEXTURE_EXT,会根据mTexture.getTextureTarget来决定
fs如下:
//1.如果是TEXTURE_EXT的话需要加上,后面我会讨论这种方式的纹理优势
"#extension GL_OES_EGL_image_external : require"
"precision mediump float;"
//2.以下两句为开启TEXTURE_EXT的:
"uniform samplerExternalOES sampler;"
"varying vec2 outTexCoords;"
//3.以下两句为开启2D:
"uniform sampler2D sampler;"
"varying vec2 outTexCoords;"
//4.当没有开启纹理(2D、OES)或者color拥有a通道(a<1)的话:
"uniform vec4 color;"
//5.以下的为开启Y410BT2020,之后研究:
R"__SHADER__(
vec3 convertY410BT2020(const vec3 color) {
const vec3 offset = vec3(0.0625, 0.5, 0.5);
const mat3 transform = mat3(
vec3(1.1678, 1.1678, 1.1678),
vec3( 0.0, -0.1878, 2.1481),
vec3(1.6836, -0.6523, 0.0));
// Y is in G, U is in R, and V is in B
return clamp(transform * (color.grb - offset), 0.0, 1.0);
}
)__SHADER__"
//6.以下为开启transformMatrix或者inputTransformMatrix和outputTransformMatrix不一
致时开启
//1)根据inputTransformMatrix和outputTransformMatrix决定
"uniform float displayMaxLuminance;
//2)以下为拥有inputTransformMatrix:
"uniform mat4 inputTransformMatrix;"
R"__SHADER__(
highp vec3 InputTransform(const highp vec3 color) {
return vec3(inputTransformMatrix * vec4(color, 1.0));
}
//3)拥有outputTransformMatrix:
R"__SHADER__(
highp vec3 InputTransform(const highp vec3 color) {
return color;
}
)__SHADER__";
"void main(void) {"
//7.开启纹理:
"gl_FragColor = texture2D(sampler, outTexCoords);"
//1)开启Y410BT2020:
"gl_FragColor.rgb = convertY410BT2020(gl_FragColor.rgb);"
//8.没有开启纹理:
"gl_FragColor.rgb = color.rgb;";
"gl_FragColor.a = 1.0;"
//9.根据mOpaque判断
"gl_FragColor.a = 1.0;
//10.alpha通道<1
//1)Premultiplied:每个通道乘以alpha
"gl_FragColor *= color.a;"
//2) 否则的话:
"gl_FragColor.a *= color.a;"
//11.存在inputTransform:
"gl_FragColor.rgb = gl_FragColor.rgb / (gl_FragColor.a + 0.0019);"
"gl_FragColor.rgb = OETF(OutputTransform(OOTF(InputTransform(EOTF(gl_FragColor.rgb)))));"
"gl_FragColor.rgb = gl_FragColor.rgb * (gl_FragColor.a + 0.0019);"
"}"
ProgramCache::primeCache函数在sf::init阶段调用,初始化mCache,向其中设置多种组合的Key,还用于处理Wide Color。
二.研究下上面特殊的key
1.Texture
Description::disableTexture
1.GLES20RenderEngine::setupLayerBlending,根据第三个参数判断
1)ColorLayer::onDraw ->disable
2)BufferLayer::drawWithOpenGL ->enable Texture
2.GLES20RenderEngine::disableTexturing
1)SurfaceFlinger::renderScreenImplLocked
2)BufferLayer::onDraw ->draw完成后的关闭texture
3.GLES20RenderEngine::setupFillWithColor
1)RenderEngine::fillRegionWithColor
a.SurfaceFlinger::doDebugFlashRegions
b.SurfaceFlinger::drawWormhole
2)Layer::clearWithOpenGL
a.BufferLayer::onDraw
b.SurfaceFlinger::doComposeSurfaces
Description::setTexture
以下1和2,2选1,互斥:
- GLES20RenderEngine::setupLayerTexturing
1) BufferLayer::onDraw - GLES20RenderEngine::setupLayerBlackedOut ->Texture::TEXTURE_2D
1) BufferLayer::onDraw :仅在buffer的Usage包含GRALLOC_USAGE_PROTECTED或者layer flags包含layer_state_t::eLayerSecure同时renderArea不为secure(LayerRenderArea为false,DisplayDeviceArea为true,因为为主屏)
那么我们看下texture时怎么绑定的呢?
BufferLayer::BufferLayer() {
...
mFlinger->getRenderEngine().genTextures(1, &mTextureName);
mTexture.init(Texture::TEXTURE_EXTERNAL, mTextureName);
...
}
161void BufferLayer::onDraw(){
...
205 if (!blackOutLayer) {
206 // TODO: we could be more subtle with isFixedSize()
207 const bool useFiltering = getFiltering() || needsFiltering(renderArea) || isFixedSize();
208
209 // Query the texture matrix given our current filtering mode.
210 float textureMatrix[16];
211 mConsumer->setFilteringEnabled(useFiltering);
212 mConsumer->getTransformMatrix(textureMatrix);
...
242 // Set things up for texturing.
243 mTexture.setDimensions(getBE().compositionInfo.mBuffer->getWidth(),
244 getBE().compositionInfo.mBuffer->getHeight());
245 mTexture.setFiltering(useFiltering);
246 mTexture.setMatrix(textureMatrix);
247
248 engine.setupLayerTexturing(mTexture);
249 } else {
250 engine.setupLayerBlackedOut();
251 }
252 drawWithOpenGL(renderArea, useIdentityTransform);
253 engine.disableTexturing();
254}
2.mY410BT2020
在BufferLayer的drawWithOpenGL时通过isHdrY410函数判断是否将mY410BT2020置true。
818bool BufferLayer::isHdrY410() const {
819 // pixel format is HDR Y410 masquerading as RGBA_1010102
820 return (mCurrentDataSpace == ui::Dataspace::BT2020_ITU_PQ &&
821 mConsumer->getCurrentApi() == NATIVE_WINDOW_API_MEDIA &&
822 getBE().compositionInfo.mBuffer->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102);
823}
3.mPremultipliedAlpha、mOpaque
1) GLES20RenderEngine::setupLayerBlending
210void GLES20RenderEngine::setupLayerBlending(bool premultipliedAlpha, bool opaque,
211 bool disableTexture, const half4& color) {
212 mState.setPremultipliedAlpha(premultipliedAlpha);
213 mState.setOpaque(opaque);
214 mState.setColor(color);
215
216 if (disableTexture) {
217 mState.disableTexture();
218 }
219
220 if (color.a < 1.0f || !opaque) {
221 glEnable(GL_BLEND);
222 glBlendFunc(premultipliedAlpha ? GL_ONE : GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
223 } else {
224 glDisable(GL_BLEND);
225 }
226}
在new一个layer的时候构造函数中就会将mPremultipliedAlpha初始化为true;而在BufferLayer构造中会根据flag重新更改:
if (flags & ISurfaceComposerClient::eNonPremultiplied) mPremultipliedAlpha = false;
那么mOpaque获取通过下面的函数:
691bool BufferLayer::isOpaque(const Layer::State& s) const {
692 // if we don't have a buffer or sidebandStream yet, we're translucent regardless of the
693 // layer's opaque flag.
694 if ((getBE().compositionInfo.hwc.sidebandStream == nullptr) && (getBE().compositionInfo.mBuffer == nullptr)) {
695 return false;
696 }
697
698 // if the layer has the opaque flag, then we're always opaque,
699 // otherwise we use the current buffer's format.
700 return ((s.flags & layer_state_t::eLayerOpaque) != 0) || mCurrentOpacity;
701}
相反ColorLayer中mPremultipliedAlpha值取决于父类Layer,即true,mOpaque为false。
2) GLES20RenderEngine::setupFillWithColor
306void GLES20RenderEngine::setupFillWithColor(float r, float g, float b, float a) {
307 mState.setPremultipliedAlpha(true);
308 mState.setOpaque(false);
309 mState.setColor(half4(r, g, b, a));
310 mState.disableTexture();
311 glDisable(GL_BLEND);
312}
mPremultipliedAlpha = true 直接为true
mOpaque = false直接为false
4.mColor
和mPremultipliedAlpha、mOpaque一样,在setupLayerBlending 和setupFillWithColor中设置。
BufferLayer & ColorLayer:
1883half4 Layer::getColor() const {
1884 const half4 color(getDrawingState().color);
1885 return half4(color.r, color.g, color.b, getAlpha());
1886}
那么在setupFillWithColor时会直接指定颜色主动设置,无需再get。
1)Layer::clearWithOpenGL
BufferLayer在draw的时候如果存在hole,那么会将color置为黑色(0,0,0,1)
Layer::clearWithOpenGL
在doComposerSurface时也会将颜色调整:
3003 if (layer->getClearClientTarget(hwcId) && !firstLayer &&
3004 layer->isOpaque(state) && (state.color.a == 1.0f)
3005 && hasClientComposition) {
3006 // never clear the very first layer since we're
3007 // guaranteed the FB is already cleared
3008 layer->clearWithOpenGL(renderArea);
3009 }
2)RenderEngine::fillRegionWithColor
doDebugFlashRegions:
engine.fillRegionWithColor(dirtyRegion, height, 1, 0, 1, 1);
3048void SurfaceFlinger::drawWormhole(const sp<const DisplayDevice>& displayDevice, const Region& region) const {
3049 const int32_t height = displayDevice->getHeight();
3050 auto& engine(getRenderEngine());
3051 engine.fillRegionWithColor(region, height, 0, 0, 0, 0);
3052}