显示框架之SurfaceFlinger GPU合成
对于不支持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(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 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::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, /*logConfig*/ 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 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(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(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, std::string name,
uint32_t w, uint32_t h, uint32_t flags,
LayerMetadata metadata, PixelFormat& format,
sp* handle,
sp* gbp,
sp* 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 Output::composeSurfaces(
const Region& debugRegion, const compositionengine::CompositionRefreshArgs& refreshArgs) {
...
base::unique_fd fd;
sp 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 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 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(), /*useFramebufferCache=*/true,
std::move(fd), &readyFence);
...
}
输入的Buffer是通过BufferLayer的prepareClientComposition 函数设到RenderEngine里面的。
文件:frameworks/native/services/surfaceflinger/BufferLayer.cpp
std::optional BufferLayer::prepareClientComposition(
compositionengine::LayerFE::ClientCompositionTargetSettings& targetSettings) {
ATRACE_CALL();
std::optional 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& 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 fbo;
...
if (blurLayersSize == 0) {
// 将dequeue出来的buffer绑定到FB上面,作为fbo
fbo = std::make_unique(*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, /*arbitrary*/ 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::from(nativeBuffer);
//使用cache,如果有一样的image,就直接返回
if (useFramebufferCache) {
std::lock_guard 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 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(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& 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 /* count */, 2 /* size */)
.setTexCoords(2 /* size */)
.setCropCoords(2 /* size */)
.build();
for (auto const layer : layers) {
//遍历outputlayer
...
//获取layer的大小
const FloatRect bounds = layer->geometry.boundaries;
Mesh::VertexArray position(mesh.getPositionArray());
// 设置顶点的坐标,逆时针方向
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 gBuf = layer->source.buffer.buffer;
// textureName是创建BufferQueuelayer时生成的,用来标识这个layer,
// fence是acquire fence
bindExternalTextureBuffer(layer->source.buffer.textureName, gBuf,
layer->source.buffer.fence);
...
// 设置纹理坐标,也是逆时针
renderengine::Mesh::VertexArray texCoords(mesh.getTexCoordArray());
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& buffer,
const sp& bufferFence) {
if (buffer == nullptr) {
return BAD_VALUE;
}
ATRACE_CALL();
bool found = false;
{
// 在ImageCache里面找有没有相同的buffer
std::lock_guard 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(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(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 = it->second;
if (program->isValid()) {
program->use();
program->setUniforms(description);
}
}
std::unique_ptr ProgramCache::generateProgram(const Key& needs) {
ATRACE_CALL();
// 创建顶点着色器
String8 vs = generateVertexShader(needs);
// 创建片段着色器
String8 fs = generateFragmentShader(needs);
// 链接和编译着色器
return std::make_unique(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& /*needs*/, 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 buf;
sp 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& outBuffer, sp& 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(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> 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 = 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同步的代码,就先不分析了。
共有 0 条评论