热点新闻
显示框架之SurfaceFlinger GPU合成
2024-10-19 05:59  浏览:2596  搜索引擎搜索“富博农业网”
温馨提示:信息一旦丢失不一定找得到,请务必收藏信息以备急用!本站所有信息均是注册会员发布如遇到侵权请联系文章中的联系方式或客服删除!
联系我时,请说明是在富博农业网看到的信息,谢谢。
展会发布 展会网站大全 报名观展合作 软文发布

对于不支持device合成的layer,SurfaceFlinger会采用GPU来合成,然后与device合成的layer在hwc进行同步再送给屏幕。
在SurfaceFlinger启动的时候就已经搭建好了EGL环境,具体如下:

文件:frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp void SurfaceFlinger::init() { ALOGI( "SurfaceFlinger's main thread ready to run. " "Initializing graphics H/W..."); Mutex::Autolock _l(mStateLock); // Get a RenderEngine for the given display / config (can't fail) // TODO(b/77156734): We need to stop casting and use HAL types when possible. // Sending maxframeBufferAcquiredBuffers as the cache size is tightly tuned to single-display. // 创建RenderEngine对象 mCompositionEngine->setRenderEngine(renderengine::RenderEngine::create( renderengine::RenderEngineCreationArgs::Builder() .setPixelFormat(static_cast<int32_t>(defaultCompositionPixelFormat)) .setImageCacheSize(maxframeBufferAcquiredBuffers) .setUseColorManagerment(useColorManagement) .setEnableProtectedContext(enable_protected_contents(false)) .setPrecacheToneMapperShaderOnly(false) .setSupportsBackgroundBlur(mSupportsBlur) .setContextPriority(useContextPriority ? renderengine::RenderEngine::ContextPriority::HIGH : renderengine::RenderEngine::ContextPriority::MEDIUM) .build())); 文件:frameworks/native/libs/renderengine/RenderEngine.cpp std::unique_ptr<impl::RenderEngine> RenderEngine::create(const RenderEngineCreationArgs& args) { char prop[PROPERTY_VALUE_MAX]; // 如果PROPERTY_DEBUG_RENDERENGINE_BACKEND 属性不设,则默认是gles类型 property_get(PROPERTY_DEBUG_RENDERENGINE_BACKEND, prop, "gles"); if (strcmp(prop, "gles") == 0) { ALOGD("RenderEngine GLES Backend"); // 创建GLESRenderEngine对象 return renderengine::gl::GLESRenderEngine::create(args); } ALOGE("UNKNOWN BackendType: %s, create GLES RenderEngine.", prop); return renderengine::gl::GLESRenderEngine::create(args); } 文件:frameworks/native/libs/renderengine/gl/GLESRenderEngine.cpp std::unique_ptr<GLESRenderEngine> GLESRenderEngine::create(const RenderEngineCreationArgs& args) { // initialize EGL for the default display // 获得EGLDisplay EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); if (!eglInitialize(display, nullptr, nullptr)) { LOG_ALWAYS_FATAL("failed to initialize EGL"); } // 查询EGL版本信息 const auto eglVersion = eglQueryStringImplementationANDROID(display, EGL_VERSION); if (!eglVersion) { checkGlError(__FUNCTION__, __LINE__); LOG_ALWAYS_FATAL("eglQueryStringImplementationANDROID(EGL_VERSION) failed"); } //查询EGL支持哪些拓展 const auto eglExtensions = eglQueryStringImplementationANDROID(display, EGL_EXTENSIONS); if (!eglExtensions) { checkGlError(__FUNCTION__, __LINE__); LOG_ALWAYS_FATAL("eglQueryStringImplementationANDROID(EGL_EXTENSIONS) failed"); } //根据支持的拓展设置属性,目前来看所有的属性都为true GLExtensions& extensions = GLExtensions::getInstance(); extensions.initWithEGLStrings(eglVersion, eglExtensions); // The code assumes that ES2 or later is available if this extension is // supported. EGLConfig config = EGL_NO_CONFIG; if (!extensions.hasNoConfigContext()) { config = chooseEglConfig(display, args.pixelFormat, true); } bool useContextPriority = extensions.hasContextPriority() && args.contextPriority == ContextPriority::HIGH; EGLContext protectedContext = EGL_NO_CONTEXT; if (args.enableProtectedContext && extensions.hasProtectedContent()) { protectedContext = createEglContext(display, config, nullptr, useContextPriority, Protection::PROTECTED); ALOGE_IF(protectedContext == EGL_NO_CONTEXT, "Can't create protected context"); } // 创建非protect的EglContext EGLContext ctxt = createEglContext(display, config, protectedContext, useContextPriority, Protection::UNPROTECTED); LOG_ALWAYS_FATAL_IF(ctxt == EGL_NO_CONTEXT, "EGLContext creation failed"); EGLSurface dummy = EGL_NO_SURFACE; // 支持该属性,不走if逻辑 if (!extensions.hasSurfacelessContext()) { dummy = createDummyEglPbufferSurface(display, config, args.pixelFormat, Protection::UNPROTECTED); LOG_ALWAYS_FATAL_IF(dummy == EGL_NO_SURFACE, "can't create dummy pbuffer"); } // eglMakeCurrent 将 EGLDisplay和EglContext 绑定 EGLBoolean success = eglMakeCurrent(display, dummy, dummy, ctxt); LOG_ALWAYS_FATAL_IF(!success, "can't make dummy pbuffer current"); ... std::unique_ptr<GLESRenderEngine> engine; switch (version) { case GLES_VERSION_1_0: case GLES_VERSION_1_1: LOG_ALWAYS_FATAL("SurfaceFlinger requires OpenGL ES 2.0 minimum to run."); break; case GLES_VERSION_2_0: case GLES_VERSION_3_0: // GLESRenderEngine 初始化 engine = std::make_unique<GLESRenderEngine>(args, display, config, ctxt, dummy, protectedContext, protectedDummy); break; } ... } GLESRenderEngine::GLESRenderEngine(const RenderEngineCreationArgs& args, EGLDisplay display, EGLConfig config, EGLContext ctxt, EGLSurface dummy, EGLContext protectedContext, EGLSurface protectedDummy) : renderengine::impl::RenderEngine(args), mEGLDisplay(display), mEGLConfig(config), mEGLContext(ctxt), mDummySurface(dummy), mProtectedEGLContext(protectedContext), mProtectedDummySurface(protectedDummy), mVpWidth(0), mVpHeight(0), mframebufferImageCacheSize(args.imageCacheSize), mUseColorManagement(args.useColorManagement) { // 查询可支持最大的纹理尺寸和视图大小 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize); glGetIntegerv(GL_MAX_VIEWPORT_DIMS, mMaxViewportDims); //像素数据按4字节对齐 glPixelStorei(GL_UNPACK_ALIGNMENT, 4); glPixelStorei(GL_PACK_ALIGNMENT, 4); ... // 色彩空间相关设置,遇到具体场景再分析 if (mUseColorManagement) { const ColorSpace srgb(ColorSpace::sRGB()); const ColorSpace displayP3(ColorSpace::DisplayP3()); const ColorSpace bt2020(ColorSpace::BT2020()); // no chromatic adaptation needed since all color spaces use D65 for their white points. mSrgbToXyz = mat4(srgb.getRGBtoXYZ()); mDisplayP3ToXyz = mat4(displayP3.getRGBtoXYZ()); mBt2020ToXyz = mat4(bt2020.getRGBtoXYZ()); mXyzToSrgb = mat4(srgb.getXYZtoRGB()); mXyzToDisplayP3 = mat4(displayP3.getXYZtoRGB()); mXyzToBt2020 = mat4(bt2020.getXYZtoRGB()); // Compute sRGB to Display P3 and BT2020 transform matrix. // NOTE: For now, we are limiting output wide color space support to // Display-P3 and BT2020 only. mSrgbToDisplayP3 = mXyzToDisplayP3 * mSrgbToXyz; mSrgbToBt2020 = mXyzToBt2020 * mSrgbToXyz; // Compute Display P3 to sRGB and BT2020 transform matrix. mDisplayP3ToSrgb = mXyzToSrgb * mDisplayP3ToXyz; mDisplayP3ToBt2020 = mXyzToBt2020 * mDisplayP3ToXyz; // Compute BT2020 to sRGB and Display P3 transform matrix mBt2020ToSrgb = mXyzToSrgb * mBt2020ToXyz; mBt2020ToDisplayP3 = mXyzToDisplayP3 * mBt2020ToXyz; } ... // 涉及到有模糊的layer,具体场景再分析 if (args.supportsBackgroundBlur) { mBlurFilter = new BlurFilter(*this); checkErrors("BlurFilter creation"); } // 创建ImageManager 线程,这个线程是管理输入的mEGLImage mImageManager = std::make_unique<ImageManager>(this); mImageManager->initThread(); //创建GLframebuffer mDrawingBuffer = createframebuffer(); ... } 文件:frameworks/native/libs/renderengine/gl/GLframebuffer.cpp // 创建了一个纹理ID mTextureName,和 fb ID mframebufferName GLframebuffer::GLframebuffer(GLESRenderEngine& engine) : mEngine(engine), mEGLDisplay(engine.getEGLDisplay()), mEGLImage(EGL_NO_IMAGE_KHR) { glGenTextures(1, &mTextureName); glGenframebuffers(1, &mframebufferName); }

启动之初就搭建好了EGL环境,并将当前线程与context绑定,为后面使用gl命令做好准备,然后创建了ImageManager 线程,这个线程是管理输入Buffer的EGLImage,然后创建了GLframeBuffer,用来操作输出的buffer。
来看下输入的纹理,在创建BufferQueueLayer时就已经对各个layer创建了纹理ID,为后面走GPU合成做准备。

文件:frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp status_t SurfaceFlinger::createBufferQueueLayer(const sp<Client>& client, std::string name, uint32_t w, uint32_t h, uint32_t flags, Layermetadata metadata, PixelFormat& format, sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer) { ... args.textureName = getNewTexture(); ... } uint32_t SurfaceFlinger::getNewTexture() { { std::lock_guard lock(mTexturePoolMutex); if (!mTexturePool.empty()) { uint32_t name = mTexturePool.back(); mTexturePool.pop_back(); ATRACE_INT("TexturePoolSize", mTexturePool.size()); return name; } // The pool was too small, so increase it for the future ++mTexturePoolSize; } // The pool was empty, so we need to get a new texture name directly using a // blocking call to the main thread // 每个layer,调用glGenTextures 生成纹理ID,schedule运行在sf主线程 return schedule([this] { uint32_t name = 0; getRenderEngine().genTextures(1, &name); return name; }) .get(); }

回到composeSurfaces这个函数,看下走GPU合成的逻辑。

文件:frameworks/native/services/surfaceflinger/CompositionEngine/src/Output.cpp std::optional<base::unique_fd> Output::composeSurfaces( const Region& debugRegion, const compositionengine::CompositionRefreshArgs& refreshArgs) { ... base::unique_fd fd; sp<GraphicBuffer> buf; // If we aren't doing client composition on this output, but do have a // flipClientTarget request for this frame on this output, we still need to // dequeue a buffer. if (hasClientComposition || outputState.flipClientTarget) { // dequeueBuffer一块Buffer,这块Buffer作为输出 buf = mRenderSurface->dequeueBuffer(&fd); if (buf == nullptr) { ALOGW("Dequeuing buffer for display [%s] failed, bailing out of " "client composition for this frame", mName.c_str()); return {}; } } base::unique_fd readyFence; // GPU合成时不返回 if (!hasClientComposition) { setExpensiveRenderingExpected(false); return readyFence; } ALOGV("hasClientComposition"); // 设置clientCompositionDisplay,这个是display相关参数 renderengine::DisplaySettings clientCompositionDisplay; clientCompositionDisplay.physicalDisplay = outputState.destinationClip; clientCompositionDisplay.clip = outputState.sourceClip; clientCompositionDisplay.orientation = outputState.orientation; clientCompositionDisplay.outputDataspace = mDisplayColorProfile->hasWideColorGamut() ? outputState.dataspace : ui::Dataspace::UNKNOWN; clientCompositionDisplay.maxLuminance = mDisplayColorProfile->getHdrCapabilities().getDesiredMaxLuminance(); // Compute the global color transform matrix. if (!outputState.usesDeviceComposition && !getSkipColorTransform()) { clientCompositionDisplay.colorTransform = outputState.colorTransformMatrix; } // Note: Updated by generateClientCompositionRequests clientCompositionDisplay.clearRegion = Region::INVALID_REGION; // Generate the client composition requests for the layers on this output. // 设置clientCompositionLayers , 这个是layer的相关参数 std::vector<LayerFE::LayerSettings> clientCompositionLayers = generateClientCompositionRequests(supportsProtectedContent, clientCompositionDisplay.clearRegion, clientCompositionDisplay.outputDataspace); appendRegionFlashRequests(debugRegion, clientCompositionLayers); // Check if the client composition requests were rendered into the provided graphic buffer. If // so, we can reuse the buffer and avoid client composition. // 如果cache里有相同的Buffer,则不需要重复draw一次 if (mClientCompositionRequestCache) { if (mClientCompositionRequestCache->exists(buf->getId(), clientCompositionDisplay, clientCompositionLayers)) { outputCompositionState.reusedClientComposition = true; setExpensiveRenderingExpected(false); return readyFence; } mClientCompositionRequestCache->add(buf->getId(), clientCompositionDisplay, clientCompositionLayers); } // We boost GPU frequency here because there will be color spaces conversion // or complex GPU shaders and it's expensive. We boost the GPU frequency so that // GPU composition can finish in time. We must reset GPU frequency afterwards, // because high frequency consumes extra battery. // 针对有模糊layer和有复杂颜色空间转换的场景,给GPU进行提频 const bool expensiveBlurs = refreshArgs.blursAreExpensive && mLayerRequestingBackgroundBlur != nullptr; const bool expensiveRenderingExpected = clientCompositionDisplay.outputDataspace == ui::Dataspace::DISPLAY_P3 || expensiveBlurs; if (expensiveRenderingExpected) { setExpensiveRenderingExpected(true); } // 将clientCompositionLayers 里面的内容插入到clientCompositionLayerPointers,实质内容相同 std::vector<const renderengine::LayerSettings*> clientCompositionLayerPointers; clientCompositionLayerPointers.reserve(clientCompositionLayers.size()); std::transform(clientCompositionLayers.begin(), clientCompositionLayers.end(), std::back_inserter(clientCompositionLayerPointers), [](LayerFE::LayerSettings& settings) -> renderengine::LayerSettings* { return &settings; }); const nsecs_t renderEngineStart = systemTime(); // GPU合成,主要逻辑在drawLayers里面 status_t status = renderEngine.drawLayers(clientCompositionDisplay, clientCompositionLayerPointers, buf->getNativeBuffer(), true, std::move(fd), &readyFence); ... }

输入的Buffer是通过BufferLayer的prepareClientComposition 函数设到RenderEngine里面的。

文件:frameworks/native/services/surfaceflinger/BufferLayer.cpp std::optional<compositionengine::LayerFE::LayerSettings> BufferLayer::prepareClientComposition( compositionengine::LayerFE::ClientCompositionTargetSettings& targetSettings) { ATRACE_CALL(); std::optional<compositionengine::LayerFE::LayerSettings> result = Layer::prepareClientComposition(targetSettings); ... const State& s(getDrawingState()); // 应用queue过来的Buffer layer.source.buffer.buffer = mBufferInfo.mBuffer; layer.source.buffer.isOpaque = isOpaque(s); // acquire fence layer.source.buffer.fence = mBufferInfo.mFence; // 创建BufferQueueLayer时创建的texture ID layer.source.buffer.textureName = mTextureName; ... }

至此,SurfaceFlinger调到RenderEngine里面,SurfaceFlinger的display和outputlayer的信息传到了RenderEngine,这些都是GPU合成需要的信息,然后来看下drawLayers的流程。

文件:frameworks/native/libs/renderengine/gl/GLESRenderEngine.cpp status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, const std::vector<const LayerSettings*>& layers, ANativeWindowBuffer* const buffer, const bool useframebufferCache, base::unique_fd&& bufferFence, base::unique_fd* drawFence) { ATRACE_CALL(); if (layers.empty()) { ALOGV("Drawing empty layer stack"); return NO_ERROR; } // 要等前一帧的release fence if (bufferFence.get() >= 0) { // Duplicate the fence for passing to waitFence. base::unique_fd bufferFenceDup(dup(bufferFence.get())); if (bufferFenceDup < 0 || !waitFence(std::move(bufferFenceDup))) { ATRACE_NAME("Waiting before draw"); sync_wait(bufferFence.get(), -1); } } if (buffer == nullptr) { ALOGE("No output buffer provided. Aborting GPU composition."); return BAD_VALUE; } std::unique_ptr<BindNativeBufferAsframebuffer> fbo; ... if (blurLayersSize == 0) { // 将dequeue出来的buffer绑定到FB上面,作为fbo fbo = std::make_unique<BindNativeBufferAsframebuffer>(*this, buffer, useframebufferCache); 文件:frameworks/native/libs/renderengine/gl/include/renderengine/RenderEngine.h class BindNativeBufferAsframebuffer { public: BindNativeBufferAsframebuffer(RenderEngine& engine, ANativeWindowBuffer* buffer, const bool useframebufferCache) : mEngine(engine), mframebuffer(mEngine.getframebufferForDrawing()), mStatus(NO_ERROR) { mStatus = mframebuffer->setNativeWindowBuffer(buffer, mEngine.isProtected(), useframebufferCache) ? mEngine.bindframeBuffer(mframebuffer) : NO_MEMORY; } ~BindNativeBufferAsframebuffer() { mframebuffer->setNativeWindowBuffer(nullptr, false, true); mEngine.unbindframeBuffer(mframebuffer); } status_t getStatus() const { return mStatus; } private: RenderEngine& mEngine; framebuffer* mframebuffer; status_t mStatus; }; 文件: frameworks/native/libs/renderengine/gl/GLframebuffer.cpp bool GLframebuffer::setNativeWindowBuffer(ANativeWindowBuffer* nativeBuffer, bool isProtected, const bool useframebufferCache) { ATRACE_CALL(); if (mEGLImage != EGL_NO_IMAGE_KHR) { if (!usingframebufferCache) { eglDestroyImageKHR(mEGLDisplay, mEGLImage); DEBUG_EGL_IMAGE_TRACKER_DESTROY(); } mEGLImage = EGL_NO_IMAGE_KHR; mBufferWidth = 0; mBufferHeight = 0; } if (nativeBuffer) { mEGLImage = mEngine.createframebufferImageIfNeeded(nativeBuffer, isProtected, useframebufferCache); if (mEGLImage == EGL_NO_IMAGE_KHR) { return false; } usingframebufferCache = useframebufferCache; mBufferWidth = nativeBuffer->width; mBufferHeight = nativeBuffer->height; } return true; } 文件:frameworks/native/libs/renderengine/gl/GLESRenderEngine.cpp GLImageKHR GLESRenderEngine::createframebufferImageIfNeeded(ANativeWindowBuffer* nativeBuffer, bool isProtected, bool useframebufferCache) { // buffer类型转换,将ANativeWindowBuffer 转换成 GraphicsBuffer sp<GraphicBuffer> graphicBuffer = GraphicBuffer::from(nativeBuffer); //使用cache,如果有一样的image,就直接返回 if (useframebufferCache) { std::lock_guard<std::mutex> lock(mframebufferImageCacheMutex); for (const auto& image : mframebufferImageCache) { if (image.first == graphicBuffer->getId()) { return image.second; } } } EGLint attributes[] = { isProtected ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE, isProtected ? EGL_TRUE : EGL_NONE, EGL_NONE, }; // 将dequeue出来的buffer作为参数创建 EGLImage EGLImageKHR image = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, nativeBuffer, attributes); if (useframebufferCache) { if (image != EGL_NO_IMAGE_KHR) { std::lock_guard<std::mutex> lock(mframebufferImageCacheMutex); if (mframebufferImageCache.size() >= mframebufferImageCacheSize) { EGLImageKHR expired = mframebufferImageCache.front().second; mframebufferImageCache.pop_front(); eglDestroyImageKHR(mEGLDisplay, expired); DEBUG_EGL_IMAGE_TRACKER_DESTROY(); } // 把image放到mframebufferImageCache 里面 mframebufferImageCache.push_back({graphicBuffer->getId(), image}); } } if (image != EGL_NO_IMAGE_KHR) { DEBUG_EGL_IMAGE_TRACKER_CREATE(); } return image; } status_t GLESRenderEngine::bindframeBuffer(framebuffer* framebuffer) { ATRACE_CALL(); GLframebuffer* glframebuffer = static_cast<GLframebuffer*>(framebuffer); // 上一步创建的EGLImage EGLImageKHR eglImage = glframebuffer->getEGLImage(); // 创建RenderEngine 时就已经创建好的 texture id和 fb id uint32_t textureName = glframebuffer->getTextureName(); uint32_t framebufferName = glframebuffer->getframebufferName(); // Bind the texture and turn our EGLImage into a texture // 绑定texture,后面的操作将作用在这上面 glBindTexture(GL_TEXTURE_2D, textureName); // 根据EGLImage 创建一个 2D texture glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)eglImage); // Bind the framebuffer to render into glBindframebuffer(GL_frameBUFFER, framebufferName); // 将纹理附着在帧缓存上面,渲染到farmeBuffer glframebufferTexture2D(GL_frameBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureName, 0); uint32_t glStatus = glCheckframebufferStatus(GL_frameBUFFER); ALOGE_IF(glStatus != GL_frameBUFFER_COMPLETE_OES, "glCheckframebufferStatusOES error %d", glStatus); return glStatus == GL_frameBUFFER_COMPLETE_OES ? NO_ERROR : BAD_VALUE; }

首先将dequeue出来的buffer通过eglCreateImageKHR做成image,然后通过glEGLImageTargetTexture2DOES根据image创建一个2D的纹理,再通过glframebufferTexture2D把纹理附着在帧缓存上面。setViewportAndProjection 设置视图和投影矩阵。

文件:frameworks/native/libs/renderengine/gl/GLESRenderEngine.cpp status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, const std::vector<const LayerSettings*>& layers, ANativeWindowBuffer* const buffer, const bool useframebufferCache, base::unique_fd&& bufferFence, base::unique_fd* drawFence) { ... // 设置顶点和纹理坐标的size Mesh mesh = Mesh::Builder() .setPrimitive(Mesh::TRIANGLE_FAN) .setVertices(4 , 2 ) .setTexCoords(2 ) .setCropCoords(2 ) .build(); for (auto const layer : layers) { //遍历outputlayer ... //获取layer的大小 const FloatRect bounds = layer->geometry.boundaries; Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>()); // 设置顶点的坐标,逆时针方向 position[0] = vec2(bounds.left, bounds.top); position[1] = vec2(bounds.left, bounds.bottom); position[2] = vec2(bounds.right, bounds.bottom); position[3] = vec2(bounds.right, bounds.top); //设置crop的坐标 setupLayerCropping(*layer, mesh); // 设置颜色矩阵 setColorTransform(display.colorTransform * layer->colorTransform); ... // Buffer相关设置 if (layer->source.buffer.buffer != nullptr) { disableTexture = false; isOpaque = layer->source.buffer.isOpaque; // layer的buffer,理解为输入的buffer sp<GraphicBuffer> gBuf = layer->source.buffer.buffer; // textureName是创建BufferQueuelayer时生成的,用来标识这个layer, // fence是acquire fence bindExternalTextureBuffer(layer->source.buffer.textureName, gBuf, layer->source.buffer.fence); ... // 设置纹理坐标,也是逆时针 renderengine::Mesh::VertexArray<vec2> texCoords(mesh.getTexCoordArray<vec2>()); texCoords[0] = vec2(0.0, 0.0); texCoords[1] = vec2(0.0, 1.0); texCoords[2] = vec2(1.0, 1.0); texCoords[3] = vec2(1.0, 0.0); // 设置纹理的参数,glTexParameteri setupLayerTexturing(texture); } status_t GLESRenderEngine::bindExternalTextureBuffer(uint32_t texName, const sp<GraphicBuffer>& buffer, const sp<Fence>& bufferFence) { if (buffer == nullptr) { return BAD_VALUE; } ATRACE_CALL(); bool found = false; { // 在ImageCache里面找有没有相同的buffer std::lock_guard<std::mutex> lock(mRenderingMutex); auto cachedImage = mImageCache.find(buffer->getId()); found = (cachedImage != mImageCache.end()); } // If we couldn't find the image in the cache at this time, then either // SurfaceFlinger messed up registering the buffer ahead of time or we got // backed up creating other EGLImages. if (!found) { //如果ImageCache里面没有则需要重新创建一个EGLImage,创建输入的EGLImage是在ImageManager线程里面,利用notify唤醒机制 status_t cacheResult = mImageManager->cache(buffer); if (cacheResult != NO_ERROR) { return cacheResult; } } ... // 把EGLImage转换成纹理,类型为GL_TEXTURE_EXTERNAL_OES bindExternalTextureImage(texName, *cachedImage->second); mTextureView.insert_or_assign(texName, buffer->getId()); } } void GLESRenderEngine::bindExternalTextureImage(uint32_t texName, const Image& image) { ATRACE_CALL(); const GLImage& glImage = static_cast<const GLImage&>(image); const GLenum target = GL_TEXTURE_EXTERNAL_OES; //绑定纹理,纹理ID为texName glBindTexture(target, texName); if (glImage.getEGLImage() != EGL_NO_IMAGE_KHR) { // 把EGLImage转换成纹理,纹理ID为texName glEGLImageTargetTexture2DOES(target, static_cast<GLeglImageOES>(glImage.getEGLImage())); } }

至此,将输入和输出的Buffer都生成了纹理对应,以及设置了纹理的坐标和顶点的坐标,接下来就要使用shader进行绘制了。

文件:frameworks/native/libs/renderengine/gl/GLESRenderEngine.cpp void GLESRenderEngine::drawMesh(const Mesh& mesh) { ATRACE_CALL(); if (mesh.getTexCoordsSize()) { //开启顶点着色器属性,,目的是能在顶点着色器中访问顶点的属性数据 glEnableVertexAttribArray(Program::texCoords); // 给顶点着色器传纹理的坐标 glVertexAttribPointer(Program::texCoords, mesh.getTexCoordsSize(), GL_FLOAT, GL_FALSE, mesh.getByteStride(), mesh.getTexCoords()); } //给顶点着色器传顶点的坐标 glVertexAttribPointer(Program::position, mesh.getVertexSize(), GL_FLOAT, GL_FALSE, mesh.getByteStride(), mesh.getPositions()); ... // 创建顶点和片段着色器,将顶点属性设和一些常量参数设到shader里面 ProgramCache::getInstance().useProgram(mInProtectedContext ? mProtectedEGLContext : mEGLContext, managedState); ... // 调GPU去draw glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount()); ... } 文件:frameworks/native/libs/renderengine/gl/ProgramCache.cpp void ProgramCache::useProgram(EGLContext context, const Description& description) { //设置key值,根据不同的key值创建不同的shader Key needs(computeKey(description)); // look-up the program in the cache auto& cache = mCaches[context]; auto it = cache.find(needs); if (it == cache.end()) { // we didn't find our program, so generate one... nsecs_t time = systemTime(); // 如果cache里面没有相同的program则重新创建一个 it = cache.emplace(needs, generateProgram(needs)).first; time = systemTime() - time; ALOGV(">>> generated new program for context %p: needs=%08X, time=%u ms (%zu programs)", context, needs.mKey, uint32_t(ns2ms(time)), cache.size()); } // here we have a suitable program for this description std::unique_ptr<Program>& program = it->second; if (program->isValid()) { program->use(); program->setUniforms(description); } } std::unique_ptr<Program> ProgramCache::generateProgram(const Key& needs) { ATRACE_CALL(); // 创建顶点着色器 String8 vs = generateVertexShader(needs); // 创建片段着色器 String8 fs = generateFragmentShader(needs); // 链接和编译着色器 return std::make_unique<Program>(needs, vs.string(), fs.string()); } String8 ProgramCache::generateVertexShader(const Key& needs) { Formatter vs; if (needs.hasTextureCoords()) { // attribute属性通过glVertexAttribPointer设置,varying 表示输出给片段着色器的数据 vs << "attribute vec4 texCoords;" << "varying vec2 outTexCoords;"; } ... vs << "attribute vec4 position;" << "uniform mat4 projection;" << "uniform mat4 texture;" << "void main(void) {" << indent << "gl_Position = projection * position;"; if (needs.hasTextureCoords()) { vs << "outTexCoords = (texture * texCoords).st;"; } ... return vs.getString(); } String8 ProgramCache::generateFragmentShader(const Key& needs) { Formatter fs; if (needs.getTextureTarget() == Key::TEXTURE_EXT) { fs << "#extension GL_OES_EGL_image_external : require"; } // default precision is required-ish in fragment shaders fs << "precision mediump float;"; if (needs.getTextureTarget() == Key::TEXTURE_EXT) { fs << "uniform samplerExternalOES sampler;"; } else if (needs.getTextureTarget() == Key::TEXTURE_2D) { fs << "uniform sampler2D sampler;"; } if (needs.hasTextureCoords()) { fs << "varying vec2 outTexCoords;"; } ... fs << "void main(void) {" << indent; ... if (needs.isTexturing()) { // 输出像素的颜色值 fs << "gl_FragColor = texture2D(sampler, outTexCoords);" ... } 文件: frameworks/native/libs/renderengine/gl/Program.cpp Program::Program(const ProgramCache::Key& , const char* vertex, const char* fragment) : mInitialized(false) { // 编译顶点和片段着色器 GLuint vertexId = buildShader(vertex, GL_VERTEX_SHADER); GLuint fragmentId = buildShader(fragment, GL_FRAGMENT_SHADER); // 创建programID GLuint programId = glCreateProgram(); // 将顶点和片段着色器链接到programe glAttachShader(programId, vertexId); glAttachShader(programId, fragmentId); // 将着色器里面的属性和自定义的属性变量绑定 glBindAttribLocation(programId, position, "position"); glBindAttribLocation(programId, texCoords, "texCoords"); glBindAttribLocation(programId, cropCoords, "cropCoords"); glBindAttribLocation(programId, shadowColor, "shadowColor"); glBindAttribLocation(programId, shadowParams, "shadowParams"); gllinkProgram(programId); GLint status; glGetProgramiv(programId, GL_link_STATUS, &status); ... mProgram = programId; mVertexShader = vertexId; mFragmentShader = fragmentId; mInitialized = true; //获得着色器里面uniform变量的位置 mProjectionMatrixLoc = glGetUniformLocation(programId, "projection"); mTextureMatrixLoc = glGetUniformLocation(programId, "texture"); ... // set-up the default values for our uniforms glUseProgram(programId); glUniformMatrix4fv(mProjectionMatrixLoc, 1, GL_FALSE, mat4().asArray()); glEnableVertexAttribArray(0); } void Program::use() { // Program生效 glUseProgram(mProgram); } void Program::setUniforms(const Description& desc) { // TODO: we should have a mechanism here to not always reset uniforms that // didn't change for this program. // 根据uniform的位置,给uniform变量设置,设到shader里面 if (mSamplerLoc >= 0) { glUniform1i(mSamplerLoc, 0); glUniformMatrix4fv(mTextureMatrixLoc, 1, GL_FALSE, desc.texture.getMatrix().asArray()); } ... glUniformMatrix4fv(mProjectionMatrixLoc, 1, GL_FALSE, desc.projectionMatrix.asArray()); }

最后调用glDrawArrays,使用GPU来绘制,可见对于GPU来说,输入都是一幅幅纹理,然后在着色器里面控制最后pixel的位置坐标和颜色值。
使用GPU绘制往往伴随着一个acquire fence,看下acquire fence的生。

文件: frameworks/native/libs/renderengine/gl/GLESRenderEngine.cpp base::unique_fd GLESRenderEngine::flush() { ATRACE_CALL(); if (!GLExtensions::getInstance().hasNativeFenceSync()) { return base::unique_fd(); } // 创建一个EGLSync对象,用来标识GPU是否绘制完 EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr); if (sync == EGL_NO_SYNC_KHR) { ALOGW("failed to create EGL native fence sync: %#x", eglGetError()); return base::unique_fd(); } // native fence fd will not be populated until flush() is done. // 将gl command命令全部刷给GPU glFlush(); // get the fence fd //获得android 使用的fence fd base::unique_fd fenceFd(eglDupNativeFenceFDANDROID(mEGLDisplay, sync)); eglDestroySyncKHR(mEGLDisplay, sync); if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) { ALOGW("failed to dup EGL native fence sync: %#x", eglGetError()); } // only trace if we have a valid fence, as current usage falls back to // calling finish() if the fence fd is invalid. if (CC_UNLIKELY(mTraceGpuCompletion && mFlushTracer) && fenceFd.get() >= 0) { mFlushTracer->queueSync(eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_FENCE_KHR, nullptr)); } return fenceFd; }

到这里,CPU将命令全部给到GPU了,然后GPU自己去draw,CPU继续往下运行。
回到finishframe 函数,获得GPU合成的fence后,会执行queueBuffer操作。

文件:frameworks/native/services/surfaceflinger/CompositionEngine/src/Output.cpp void Output::finishframe(const compositionengine::CompositionRefreshArgs& refreshArgs) { ATRACE_CALL(); ALOGV(__FUNCTION__); if (!getState().isEnabled) { return; } // Repaint the framebuffer (if needed), getting the optional fence for when // the composition completes. auto optReadyFence = composeSurfaces(Region::INVALID_REGION, refreshArgs); if (!optReadyFence) { return; } // swap buffers (presentation) mRenderSurface->queueBuffer(std::move(*optReadyFence)); } 文件:frameworks/native/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp void RenderSurface::queueBuffer(base::unique_fd readyFence) { auto& state = mDisplay.getState(); ... if (mGraphicBuffer == nullptr) { ALOGE("No buffer is ready for display [%s]", mDisplay.getName().c_str()); } else { status_t result = // mGraphicBuffer->getNativeBuffer() 是GPU输出的Buffer,可以理解为GPU将内容合成到该Buffer上 mNativeWindow->queueBuffer(mNativeWindow.get(), mGraphicBuffer->getNativeBuffer(), dup(readyFence)); if (result != NO_ERROR) { ALOGE("Error when queueing buffer for display [%s]: %d", mDisplay.getName().c_str(), result); // We risk blocking on dequeueBuffer if the primary display failed // to queue up its buffer, so crash here. if (!mDisplay.isVirtual()) { LOG_ALWAYS_FATAL("ANativeWindow::queueBuffer failed with error: %d", result); } else { mNativeWindow->cancelBuffer(mNativeWindow.get(), mGraphicBuffer->getNativeBuffer(), dup(readyFence)); } } mGraphicBuffer = nullptr; } } // 消费Buffer status_t result = mDisplaySurface->advanceframe(); if (result != NO_ERROR) { ALOGE("[%s] failed pushing new frame to HWC: %d", mDisplay.getName().c_str(), result); } } 文件:frameworks/native/services/surfaceflinger/DisplayHardware/framebufferSurface.cpp status_t framebufferSurface::advanceframe() { uint32_t slot = 0; sp<GraphicBuffer> buf; sp<Fence> acquireFence(Fence::NO_FENCE); Dataspace dataspace = Dataspace::UNKNOWN; // 消费这块Buffer status_t result = nextBuffer(slot, buf, acquireFence, dataspace); mDataSpace = dataspace; if (result != NO_ERROR) { ALOGE("error latching next framebufferSurface buffer: %s (%d)", strerror(-result), result); } return result; } status_t framebufferSurface::nextBuffer(uint32_t& outSlot, sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence, Dataspace& outDataspace) { Mutex::Autolock lock(mMutex); BufferItem item; // acquire Buffer status_t err = acquireBufferLocked(&item, 0); ... if (mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT && item.mSlot != mCurrentBufferSlot) { mHasPendingRelease = true; mPreviousBufferSlot = mCurrentBufferSlot; mPreviousBuffer = mCurrentBuffer; } //更新当前的Buffer和fence信息 mCurrentBufferSlot = item.mSlot; mCurrentBuffer = mSlots[mCurrentBufferSlot].mGraphicBuffer; mCurrentFence = item.mFence; outFence = item.mFence; mHwcBufferCache.getHwcBuffer(mCurrentBufferSlot, mCurrentBuffer, &outSlot, &outBuffer); outDataspace = static_cast<Dataspace>(item.mDataSpace); // 将GPU输出的Buffer和fence给到hwc status_t result = mHwc.setClientTarget(mDisplayId, outSlot, outFence, outBuffer, outDataspace); if (result != NO_ERROR) { ALOGE("error posting framebuffer: %d", result); return result; } return NO_ERROR; }

GPU合成的Buffer通过setClientTarget 设给hwc,有GPU合成的layer需要先validate再present,所以还需要再present一次,逻辑在postframebuffer 里面。

文件:frameworks/native/services/surfaceflinger/CompositionEngine/src/Output.cpp void Output::postframebuffer() { ATRACE_CALL(); ALOGV(__FUNCTION__); ... auto frame = presentAndGetframeFences(); mRenderSurface->onPresentDisplayCompleted(); ... } 文件:frameworks/native/services/surfaceflinger/DisplayHardware/HWComposer.cpp status_t HWComposer::presentAndGetReleaseFences(DisplayId displayId) { ATRACE_CALL(); RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); auto& displayData = mDisplayData[displayId]; auto& hwcDisplay = displayData.hwcDisplay; ... // GPU合成时执行present,返回present fence auto error = hwcDisplay->present(&displayData.lastPresentFence); RETURN_IF_HWC_ERROR_FOR("present", error, displayId, UNKNOWN_ERROR); std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences; // 从hwc里面获得release fence error = hwcDisplay->getReleaseFences(&releaseFences); RETURN_IF_HWC_ERROR_FOR("getReleaseFences", error, displayId, UNKNOWN_ERROR); displayData.releaseFences = std::move(releaseFences); return NO_ERROR; } 文件: frameworks/native/services/surfaceflinger/DisplayHardware/framebufferSurface.cpp void framebufferSurface::onframeCommitted() { if (mHasPendingRelease) { sp<Fence> fence = mHwc.getPresentFence(mDisplayId); if (fence->isValid()) { // 更新BufferSlot的 fence status_t result = addReleaseFence(mPreviousBufferSlot, mPreviousBuffer, fence); ALOGE_IF(result != NO_ERROR, "onframeCommitted: failed to add the" " fence: %s (%d)", strerror(-result), result); } // 释放之前的Buffer status_t result = releaseBufferLocked(mPreviousBufferSlot, mPreviousBuffer); ALOGE_IF(result != NO_ERROR, "onframeCommitted: error releasing buffer:" " %s (%d)", strerror(-result), result); mPreviousBuffer.clear(); mHasPendingRelease = false; } }

至此GPU合成的layer通过present调到hwc,hwc再执行commit上屏,其中有一些fence同步的代码,就先不分析了。

发布人:88ab****    IP:124.223.189***     举报/删稿
展会推荐
让朕来说2句
评论
收藏
点赞
转发