OpenGL ES 应用: SurfaceFlinger

一.几个重要的类

1. Description

Description.cpp中主要是接收一些来自GLES20RenderEngine设置参数保存在其成员变量中,主要用到GLES 2.0的。并将数据设置到Program中。

frameworks/native/services/surfaceflinger/RenderEngine/Description.cpp
#include 
#include 
//这个后期可以研究一下
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 
20#include 
23#include 

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,互斥:

  1. GLES20RenderEngine::setupLayerTexturing
    1) BufferLayer::onDraw
  2. 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& 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}

你可能感兴趣的:(OpenGL ES 应用: SurfaceFlinger)