当前位置: 首页 > news >正文

简述网站建设的基本思路百度推广是什么

简述网站建设的基本思路,百度推广是什么,网站 费用,magento 做的最牛逼的中文网站我们在工作的过程中,肯定听过分析卡顿或者冻屏问题的时候,定位到APP卡在dequeueBuffer方法里面,或者也听身边的同事老说3Buffer等信息。所以3Buffer是什么鬼?什么是BufferQueue?搞Android,你一定知道Graphic Buffer和…

我们在工作的过程中,肯定听过分析卡顿或者冻屏问题的时候,定位到APP卡在dequeueBuffer方法里面,或者也听身边的同事老说3Buffer等信息。所以3Buffer是什么鬼?

什么是BufferQueue?

搞Android,你一定知道Graphic Buffer和 Buffer Queue, 你的笔记中肯定也有下面这张Graphic Buffer的状态迁移图。

系统中有两类Buffer Queue,如下图所示:

  1. Layer背后的Buffer Queue

第一类,也是最为大家所熟知的,就是Layer背后的BufferQueue,用来连接App与SurfaceFlinger。App为Producer端,而 SurfaceFlinger 为 Consumer 端。

App 绘制时,先从 Buffer Queue 中 dequeue(调用 Producer 的 dequeueBuffer()函数)出来一块图形缓冲,绘制完成后,再把绘制好的图形缓冲 queue(调用 Producer 的 queueBuffer()函数)到 Buffer Queue 中,并通知 SurfaceFlinger来消费。SurfaceFlinger 收到通知后,从 Buffer Queue 中 acquire 一块绘制过的 Buffer,然后进行合成处理:要么进行 GPU合成,要么交给 HWC 去合成。

合成完成之后,这个块 Buffer 就恢复自由身,会被返回到 Buffer Queue 中(调用 Consumer 的 releaseBuffer()函数),以备下一次使用。

但是在Android S代码上面,谷歌对SurfaceFlinger的代码进行了重构,从个人理解是为了减少SF的负责,Android S开始强制App端创建BufferQueue,也就是强制Client端分配Buffer。

在Android S的代码中引入了一个BLASTBufferQueue.java(后面简称BBQ)这个类,ViewRootImpl.java在调用relayoutWindow函数的时候,会创建BBQ这个对象。

Surface getOrCreateBLASTSurface() {if (!mSurfaceControl.isValid()) {return null;}Surface ret = null;if (mBlastBufferQueue == null) {mBlastBufferQueue = new BLASTBufferQueue(mTag, mSurfaceControl,mSurfaceSize.x, mSurfaceSize.y,mWindowAttributes.format);// We only return the Surface the first time, as otherwise// it hasn't changed and there is no need to update.ret = mBlastBufferQueue.createSurface();} else {mBlastBufferQueue.update(mSurfaceControl,mSurfaceSize.x, mSurfaceSize.y,mWindowAttributes.format);}return ret;
}

在BBQ对象初初始化的时候,会调用nativeCreate方法,BBQ对象会在构造方法中传入SurfaceControl对象,而这样就会和SurfaceFlinger创建了一个连接通道。SurfaceControl.java封装了很多Client调用的binder接口,而服务端是SurfaceFlinger。

通过nativeCreate本地方法,通过JNI(android_graphics_BLASTBufferQueue.cpp)的nativeCreate方法,创建了native层的BBQ。

static jlong nativeCreate(JNIEnv* env, jclass clazz, jstring jName, jlong surfaceControl,jlong width, jlong height, jint format) {String8 str8;if (jName) {const jchar* str16 = env->GetStringCritical(jName, nullptr);if (str16) {str8 = String8(reinterpret_cast<const char16_t*>(str16), env->GetStringLength(jName));env->ReleaseStringCritical(jName, str16);str16 = nullptr;}}std::string name = str8.string();sp<BLASTBufferQueue> queue =new BLASTBufferQueue(name, reinterpret_cast<SurfaceControl*>(surfaceControl), width,height, format);queue->incStrong((void*)nativeCreate);return reinterpret_cast<jlong>(queue.get());
}
BLASTBufferQueue::BLASTBufferQueue(const std::string& name, const sp<SurfaceControl>& surface,int width, int height, int32_t format): mSurfaceControl(surface),mSize(width, height),mRequestedSize(mSize),mFormat(format),mNextTransaction(nullptr) {createBufferQueue(&mProducer, &mConsumer);// since the adapter is in the client process, set dequeue timeout// explicitly so that dequeueBuffer will blockmProducer->setDequeueTimeout(std::numeric_limits<int64_t>::max());// safe default, most producers are expected to override thismProducer->setMaxDequeuedBufferCount(2);mBufferItemConsumer = new BLASTBufferItemConsumer(mConsumer,GraphicBuffer::USAGE_HW_COMPOSER |GraphicBuffer::USAGE_HW_TEXTURE,1, false);static int32_t id = 0;mName = name + "#" + std::to_string(id);auto consumerName = mName + "(BLAST Consumer)" + std::to_string(id);mQueuedBufferTrace = "QueuedBuffer - " + mName + "BLAST#" + std::to_string(id);id++;mBufferItemConsumer->setName(String8(consumerName.c_str()));mBufferItemConsumer->setFrameAvailableListener(this);mBufferItemConsumer->setBufferFreedListener(this);mBufferItemConsumer->setDefaultBufferSize(mSize.width, mSize.height);mBufferItemConsumer->setDefaultBufferFormat(convertBufferFormat(format));mBufferItemConsumer->setBlastBufferQueue(this);ComposerService::getComposerService()->getMaxAcquiredBufferCount(&mMaxAcquiredBuffers);mBufferItemConsumer->setMaxAcquiredBufferCount(mMaxAcquiredBuffers);mTransformHint = mSurfaceControl->getTransformHint();mBufferItemConsumer->setTransformHint(mTransformHint);SurfaceComposerClient::Transaction().setFlags(surface, layer_state_t::eEnableBackpressure,layer_state_t::eEnableBackpressure).setApplyToken(mApplyToken).apply();mNumAcquired = 0;mNumFrameAvailable = 0;BQA_LOGV("BLASTBufferQueue created width=%d height=%d format=%d mTransformHint=%d", width,height, format, mTransformHint);
}

从上面的代码中,createBufferQueue创建了BufferQueue,同时也创建了Graphic Buffer的生产者和消费者。其中有个代码mProducer -> setMaxDequeuedBufferCount(2),这个就和3Buffer有关系了,我们先整理下Buffer的运转过程,如图所示:

  1. App的RenderThread 调用 Producer.dequeueBuffer()在BufferQueue中拿到一个空闲的Buffer。

  1. App的RenderThread调用Producer.queueBuffer将绘制好的 Buffer 入列。注意,此时入列的 Buffer 可能还未绘制完成,即 GPU 可能还在进行绘制工作。

  1. 最终调用到 Procuder 的 Bn 端,即 SurfaceFliner 进程里的某个 Binder 线程里。在 Bn 端,会通过调用SurfaceFlinger的SetTransactionState方法,把当前的带有Buffer信息的State保存到一个TransactionQueue队列中。

  1. 当带有Buffer信息的Layer信息保存到队列中, 这个动作称作“上帧”。所以我么可以在 systrace 上看到该Layer待消费的 Buffer 数目+1。

  1. 而 Buffer Queue 的消费者就是 SurfaceFlinger,所以在下一个 Vsync信号到来后,在 SurfaceFlinger 的 handleMessageInvalidate()函数中,调用 acquireBuffer()去取 Buffer,取走之后,BufferQueue 中待消费的 Buffer 便减少一个。

  1. 因为有上帧,所以要重新进行合成,SurfaceFlinger 调用onMessageRefresh()函数去做合成,一般是 HWC 合成,直接把 Buffer 交给 HWC。合成完成后,在 postComposition()里,会调用binder接口进行通讯。

  1. App端的binder收到消息后调用releaseBuffer()释放 Buffer,如 systrace 所示,这里释放的是上一帧的 Buffer。

上面图中7个步骤就是一个buffer详细的转运过程。

  1. DisplayDevice 背后的Buffer Queue

第二类Buffer Queue是GPU合成特有的,一般在游戏APP渲染过程中会遇到,这个Buffer Queue隐藏在DisplayDevice之后,是在SurfaceFlinger为每个接入系统的显示屏创建DisplayDevice实例时创建的。

执行在SurfaceFlinger::processDisplayAdded函数中。

void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken,const DisplayDeviceState& state) {......sp<compositionengine::DisplaySurface> displaySurface;sp<IGraphicBufferProducer> producer;sp<IGraphicBufferProducer> bqProducer;sp<IGraphicBufferConsumer> bqConsumer;getFactory().createBufferQueue(&bqProducer, &bqConsumer, /*consumerIsSurfaceFlinger =*/false);......
}

这个函数是为DisplaySurface创建BufferQueue, createBufferQueue函数是指向BufferQueue::createBufferQueue,传入的第三个参数 consumerIsSurfaceFlinger 为false,表示BufferQueue的消费者不是SurfaceFlinger。

void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken,const DisplayDeviceState& state) {......if (state.isVirtual()) {const auto displayId = VirtualDisplayId::tryCast(compositionDisplay->getId());LOG_FATAL_IF(!displayId);auto surface = sp<VirtualDisplaySurface>::make(getHwComposer(), *displayId, state.surface,bqProducer, bqConsumer, state.displayName);displaySurface = surface;producer = std::move(surface);} else {ALOGE_IF(state.surface != nullptr,"adding a supported display, but rendering ""surface is provided (%p), ignoring it",state.surface.get());const auto displayId = PhysicalDisplayId::tryCast(compositionDisplay->getId());LOG_FATAL_IF(!displayId);displaySurface =sp<FramebufferSurface>::make(getHwComposer(), *displayId, bqConsumer,state.physical->activeMode->getSize(),ui::Size(maxGraphicsWidth, maxGraphicsHeight));producer = bqProducer;}......
}

除了虚拟盘,主屏或者外屏采用FrameBufferSurface,继承自ConsumerBase,把BufferQueueConsumer封装到FrameBufferSurface里面。

  1. Buffer共享

  1. Buffer分配

  1. Buffer同步:fence

后面三个点的内容还在整理中,等整理完毕,再同步到这章内容中。

http://www.zhongyajixie.com/news/34970.html

相关文章:

  • 织梦做的网站打不开网页阿里指数数据分析平台
  • 苏州做网站推广找推网
  • 长沙营销型网站建设制作seo排名优化是什么意思
  • 怎样做禁毒网站的试卷惠州网络推广平台
  • 做seo网站不用域名百度网址
  • dw做网站简单吗企业营销型网站有哪些
  • 温江 网站建设竞价外包
  • 新闻网站内容建设措施如何建立个人网址
  • j建设网站湖南靠谱的关键词优化哪家好
  • 盘锦做网站公司网站制作基本流程
  • 用二级域名做的网站算新站吗清远新闻最新
  • 网站建设行业 前景怎么免费建个人网站
  • wordpress在线播放avi黑帽seo技术
  • 徐州网站建设方案东莞百度seo电话
  • 沈阳盘古网络做网站做的好么螺蛳粉营销策划方案
  • 做泥网站谷歌seo是什么意思
  • 前端做的比较好的网站模板网站
  • 做网站要不要买服务器个人网站制作软件
  • 中商外贸网站seo排名优化seo
  • 做网站卖东西赚钱湖南正规seo优化
  • 先做网站装修还是先买虚拟主机哪个浏览器不屏蔽网站
  • 深圳网络推广seo软件惠州seo关键词推广
  • 潍坊做外贸网站建设智能优化网站
  • 个人域名做邮箱网站手机百度一下
  • 重庆网站制作的网站域名停靠
  • 企业官网网站建设网络推广合作协议
  • 怎样发掘网站建设的客户360收录提交入口网址
  • 网站建设的大公司推广链接点击器
  • 凡科网站怎么做外链抖音搜索优化
  • 企业网站开发流程简述安徽seo