publicvoidscheduleVsync(){ if (mReceiverPtr == 0) { Log.w(TAG, "Attempted to schedule a vertical sync pulse but the display event " + "receiver has already been disposed."); } else { nativeScheduleVsync(mReceiverPtr); } }
[->android_view_DisplayEventReceiver.cpp ]
1 2 3 4 5 6 7 8 9 10
staticvoidnativeScheduleVsync(JNIEnv* env, jclass clazz, jlong receiverPtr){ sp<NativeDisplayEventReceiver> receiver = reinterpret_cast<NativeDisplayEventReceiver*>(receiverPtr); status_t status = receiver->scheduleVsync(); if (status) { String8 message; message.appendFormat("Failed to schedule next vertical sync pulse. status=%d", status); jniThrowRuntimeException(env, message.string()); } }
boolean focusChanged = false; if (win.canReceiveKeys()) { focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS, false/*updateInputWindows*/); if (focusChanged) { imMayMove = false; } } ...... mLayersController.assignLayersLocked(displayContent.getWindowList()); // Don't do layout here, the window must call // relayout to be displayed, so we'll do it there. if (focusChanged) { mInputMonitor.setInputFocusLw(mCurrentFocus, false/*updateInputWindows*/); } mInputMonitor.updateInputWindowsLw(false/*force*/); ...... } if (reportNewConfig) { sendNewConfiguration(); } return res; }
我们知道当应用程序进程添加一个DecorView到窗口管理器时,会为当前添加的窗口创建ViewRootImpl对象,同时构造了一个W本地Binder对象,无论是窗口视图对象DecorView还是ViewRootImpl对象,都只是存在于应用程序进程中,在添加窗口过程中仅仅将该窗口的W对象传递给WMS服务,经过Binder传输后,到达WMS服务端进程后变为IWindow.Proxy代理对象,因此该函数的参数client的类型为IWindow.Proxy。参数attrs的类型为WindowManager.LayoutParams,在应用程序进程启动Activity时,handleResumeActivity()函数通过WindowManager.LayoutParams l = r.window.getAttributes();来得到应用程序窗口布局参数,由于WindowManager.LayoutParams实现了Parcelable接口,因此WindowManager.LayoutParams对象可以跨进程传输,WMS服务的addWindow函数中的attrs参数就是应用程序进程发送过来的窗口布局参数。在WindowManagerImpl的addView函数中为窗口布局参数设置了相应的token,如果是应用程序窗口,则布局参数的token设为W本地Binder对象。如果不是应用程序窗口,同时当前窗口没有父窗口,则设置token为当前窗口的IApplicationToken.Proxy代理对象,否则设置为父窗口的IApplicationToken.Proxy代理对象,由于应用程序和WMS分属于两个不同的进程空间,因此经过Binder传输后,布局参数的令牌attrs.token就转变为IWindow.Proxy或者Token。以上函数首先根据布局参数的token等信息构造一个WindowToken对象,然后在构造一个WindowState对象,并将添加的窗口信息记录到mTokenMap和mWindowMap哈希表中。
if (changedVisibility || regainedFocus) { // Toasts are presented as notifications - don't present them as windows as well boolean isToast = (mWindowAttributes == null) ? false : (mWindowAttributes.type == WindowManager.LayoutParams.TYPE_TOAST); if (!isToast) { host.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); } }
// Remember if we must report the next draw. if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) { mReportNextDraw = true; } /****************执行窗口绘制******************/ boolean cancelDraw = mAttachInfo.mTreeObserver.dispatchOnPreDraw() || !isViewVisible;
if (!cancelDraw && !newSurface) { if (mPendingTransitions != null && mPendingTransitions.size() > 0) { for (int i = 0; i < mPendingTransitions.size(); ++i) { mPendingTransitions.get(i).startChangingAnimations(); } mPendingTransitions.clear(); }
performDraw(); } else { if (isViewVisible) { // Try again scheduleTraversals(); } elseif (mPendingTransitions != null && mPendingTransitions.size() > 0) { for (int i = 0; i < mPendingTransitions.size(); ++i) { mPendingTransitions.get(i).endChangingAnimations(); } mPendingTransitions.clear(); } }
publicintrelayout(IWindow window, int seq, WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewFlags, int flags, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets, Rect outVisibleInsets, Rect outStableInsets, Rect outsets, Rect outBackdropFrame, Configuration outConfig, Surface outSurface){ int res = mService.relayoutWindow(this, window, seq, attrs, requestedWidth, requestedHeight, viewFlags, flags, outFrame, outOverscanInsets, outContentInsets, outVisibleInsets, outStableInsets, outsets, outBackdropFrame, outConfig, outSurface); return res; }
publicintrelayoutWindow(Session session, IWindow client, int seq, WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewVisibility, int flags, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets, Rect outVisibleInsets, Rect outStableInsets, Rect outOutsets, Rect outBackdropFrame, Configuration outConfig, Surface outSurface){ int result = 0; ...... if (viewVisibility == View.VISIBLE && (win.mAppToken == null || !win.mAppToken.clientHidden)) { result = relayoutVisibleWindow(outConfig, result, win, winAnimator, attrChanges, oldVisibility); try { result = createSurfaceControl(outSurface, result, win, winAnimator); } catch (Exception e) { ...... return0; } ...... } else { ...... }
...... return result; }
[->WindowManagerService.java]
1 2 3 4 5 6 7 8 9 10 11 12 13
privateintcreateSurfaceControl(Surface outSurface, int result, WindowState win, WindowStateAnimator winAnimator){ if (!win.mHasSurface) { result |= RELAYOUT_RES_SURFACE_CHANGED; } WindowSurfaceController surfaceController = winAnimator.createSurfaceLocked(); if (surfaceController != null) { surfaceController.getSurface(outSurface); } else { outSurface.release(); } return result; }
publicWindowSurfaceController(SurfaceSession s, String name, int w, int h, int format, int flags, WindowStateAnimator animator){ mAnimator = animator; mSurfaceW = w; mSurfaceH = h; ...... if (animator.mWin.isChildWindow() && animator.mWin.mSubLayer < 0 && animator.mWin.mAppToken != null) { ...... } else { mSurfaceControl = new SurfaceControl( s, name, w, h, format, flags); } }
2.12、Surface创建过程
[->SurfaceControl.java]
1 2 3 4 5 6 7
publicSurfaceControl(SurfaceSession session, String name, int w, int h, int format, int flags) throws OutOfResourcesException { ...... mNativeObject = nativeCreate(session, name, w, h, format, flags); ...... }
status_tClient::createSurface( const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp){ /* * createSurface must be called from the GL thread so that it can * have access to the GL context. */
int numStartingBuffers = getMaxBufferCountLocked(); for (int s = 0; s < numStartingBuffers; s++) { mFreeSlots.insert(s); } for (int s = numStartingBuffers; s < BufferQueueDefs::NUM_BUFFER_SLOTS; s++) { mUnusedSlots.push_front(s); } }
static jlong nativeCreateFromSurfaceControl(JNIEnv* env, jclass clazz, jlong surfaceControlNativeObj){ /* * This is used by the WindowManagerService just after constructing * a Surface and is necessary for returning the Surface reference to * the caller. At this point, we should only have a SurfaceControl. */
@Override publicvoidwriteToParcel(Parcel dest, int flags){ if (dest == null) { thrownew IllegalArgumentException("dest must not be null"); } synchronized (mLock) { // NOTE: This must be kept synchronized with the native parceling code // in frameworks/native/libs/Surface.cpp dest.writeString(mName); dest.writeInt(mIsSingleBuffered ? 1 : 0); nativeWriteToParcel(mNativeObject, dest); } if ((flags & Parcelable.PARCELABLE_WRITE_RETURN_VALUE) != 0) { release(); } }
[android_view_Surface.cpp]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
staticvoidnativeWriteToParcel(JNIEnv* env, jclass clazz, jlong nativeObject, jobject parcelObj){ Parcel* parcel = parcelForJavaObject(env, parcelObj); if (parcel == NULL) { doThrowNPE(env); return; } sp<Surface> self(reinterpret_cast<Surface *>(nativeObject)); android::view::Surface surfaceShim; if (self != nullptr) { surfaceShim.graphicBufferProducer = self->getIGraphicBufferProducer(); } // Calling code in Surface.java has already written the name of the Surface // to the Parcel surfaceShim.writeToParcel(parcel, /*nameAlreadyWritten*/true); }
publicvoidreadFromParcel(Parcel source){ if (source == null) { thrownew IllegalArgumentException("source must not be null"); }
synchronized (mLock) { // nativeReadFromParcel() will either return mNativeObject, or // create a new native Surface and return it after reducing // the reference count on mNativeObject. Either way, it is // not necessary to call nativeRelease() here. // NOTE: This must be kept synchronized with the native parceling code // in frameworks/native/libs/Surface.cpp mName = source.readString(); mIsSingleBuffered = source.readInt() != 0; setNativeObjectLocked(nativeReadFromParcel(mNativeObject, source)); } }
static jlong nativeCreateFromSurfaceControl(JNIEnv* env, jclass clazz, jlong surfaceControlNativeObj){ /* * This is used by the WindowManagerService just after constructing * a Surface and is necessary for returning the Surface reference to * the caller. At this point, we should only have a SurfaceControl. */
sp<Surface> SurfaceControl::getSurface()const { Mutex::Autolock _l(mLock); if (mSurfaceData == 0) { // This surface is always consumed by SurfaceFlinger, so the // producerControlledByApp value doesn't matter; using false. mSurfaceData = new Surface(mGraphicBufferProducer, false); } return mSurfaceData; }
privatevoidperformLayout(WindowManager.LayoutParams lp, int desiredWindowWidth, int desiredWindowHeight){ mLayoutRequested = false; mScrollMayChange = true; mInLayout = true; final View host = mView; try { host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight()); mInLayout = false; int numViewsRequestingLayout = mLayoutRequesters.size(); if (numViewsRequestingLayout > 0) { // requestLayout() was called during layout. // If no layout-request flags are set on the requesting views, there is no problem. // If some requests are still pending, then we need to clear those flags and do // a full request/measure/layout pass to handle this situation. ArrayList<View> validLayoutRequesters = getValidLayoutRequesters(mLayoutRequesters, false); if (validLayoutRequesters != null) { // Set this flag to indicate that any further requests are happening during // the second pass, which may result in posting those requests to the next // frame instead mHandlingLayoutInLayoutRequest = true;
// Process fresh layout requests, then measure and layout int numValidRequests = validLayoutRequesters.size(); for (int i = 0; i < numValidRequests; ++i) { final View view = validLayoutRequesters.get(i); Log.w("View", "requestLayout() improperly called by " + view + " during layout: running second layout pass"); view.requestLayout(); } measureHierarchy(host, lp, mView.getContext().getResources(), desiredWindowWidth, desiredWindowHeight); mInLayout = true; host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight());
mHandlingLayoutInLayoutRequest = false;
// Check the valid requests again, this time without checking/clearing the // layout flags, since requests happening during the second pass get noop'd validLayoutRequesters = getValidLayoutRequesters(mLayoutRequesters, true); if (validLayoutRequesters != null) { final ArrayList<View> finalRequesters = validLayoutRequesters; // Post second-pass requests to the next frame getRunQueue().post(new Runnable() { @Override publicvoidrun(){ int numValidRequests = finalRequesters.size(); for (int i = 0; i < numValidRequests; ++i) { final View view = finalRequesters.get(i); view.requestLayout(); } } });} } } } finally { Trace.traceEnd(Trace.TRACE_TAG_VIEW); } mInLayout = false; }
{ // scope for the lock Mutex::Autolock lock(mCallbackMutex); while (callbackTicket != mCurrentCallbackTicket) { mCallbackCondition.wait(mCallbackMutex); }
bool refreshNeeded = handleMessageTransaction(); refreshNeeded |= handleMessageInvalidate(); refreshNeeded |= mRepaintEverything; if (refreshNeeded) { // Signal a refresh if a transaction modified the window state, // a new buffer was latched, or if HWC has requested a full // repaint signalRefresh(); } break; } case MessageQueue::REFRESH: { handleMessageRefresh(); break; } } }
// Release any buffers which were replaced this frame for (auto& layer : mLayersWithQueuedFrames) { layer->releasePendingBuffer(); } mLayersWithQueuedFrames.clear(); }
if (sizeChanged) { // the size changed, we need to ask our client to request a new buffer //如果Layer的尺寸发生变化,就要改变Surface的缓冲区的尺寸 // record the new size, form this point on, when the client request // a buffer, it'll get the new size. mSurfaceFlingerConsumer->setDefaultBufferSize( c.requested.w, c.requested.h); }
const bool resizePending = (c.requested.w != c.active.w) || (c.requested.h != c.active.h); if (!isFixedSize()) { if (resizePending && mSidebandStream == NULL) { //如果Layer不是固定尺寸的类型,比较它的实际大小和要求的改变大小 flags |= eDontUpdateGeometryState; } } //如果没有eDontUpdateGeometryState标志,更新active的值为request if (flags & eDontUpdateGeometryState) { } else { Layer::State& editCurrentState(getCurrentState()); if (mFreezePositionUpdates) { float tx = c.active.transform.tx(); float ty = c.active.transform.ty(); c.active = c.requested; c.active.transform.set(tx, ty); editCurrentState.active = c.active; } else { editCurrentState.active = editCurrentState.requested; c.active = c.requested; } } // 如果当前state的active和以前的State的active不等,设置更新标志 if (s.active != c.active) { // invalidate and recompute the visible regions if needed flags |= Layer::eVisibleRegion; } //如果当前state的sequence和以前state的sequence不等,设置更新标志 if (c.sequence != s.sequence) { // invalidate and recompute the visible regions if needed flags |= eVisibleRegion; this->contentDirty = true;
// we may use linear filtering, if the matrix scales us const uint8_t type = c.active.transform.getType(); mNeedsFiltering = (!c.active.transform.preserveRects() || (type >= Transform::SCALE)); }
// If the layer is hidden, signal and clear out all local sync points so // that transactions for layers depending on this layer's frames becoming // visible are not blocked if (c.flags & layer_state_t::eLayerHidden) { Mutex::Autolock lock(mLocalSyncPointMutex); for (auto& point : mLocalSyncPoints) { point->setFrameAvailable(); } mLocalSyncPoints.clear(); }
// Commit the transaction commitTransaction(c); return flags; }
if (transactionFlags & eDisplayTransactionNeeded) { // here we take advantage of Vector's copy-on-write semantics to // improve performance by skipping the transaction entirely when // know that the lists are identical const KeyedVector< wp<IBinder>, DisplayDeviceState>& curr(mCurrentState.displays); const KeyedVector< wp<IBinder>, DisplayDeviceState>& draw(mDrawingState.displays); if (!curr.isIdenticalTo(draw)) { mVisibleRegionsDirty = true; constsize_t cc = curr.size(); size_t dc = draw.size();
// find the displays that were removed // (ie: in drawing state but not in current state) // also handle displays that changed // (ie: displays that are in both lists) for (size_t i=0 ; i<dc ; i++) { constssize_t j = curr.indexOfKey(draw.keyAt(i)); if (j < 0) { // in drawing state but not in current state if (!draw[i].isMainDisplay()) { // Call makeCurrent() on the primary display so we can // be sure that nothing associated with this display // is current. const sp<const DisplayDevice> defaultDisplay(getDefaultDisplayDevice()); defaultDisplay->makeCurrent(mEGLDisplay, mEGLContext); sp<DisplayDevice> hw(getDisplayDevice(draw.keyAt(i))); if (hw != NULL) hw->disconnect(getHwComposer()); if (draw[i].type < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) mEventThread->onHotplugReceived(draw[i].type, false); mDisplays.removeItem(draw.keyAt(i)); } else { ALOGW("trying to remove the main display"); } } else { // this display is in both lists. see if something changed. const DisplayDeviceState& state(curr[j]); const wp<IBinder>& display(curr.keyAt(j)); const sp<IBinder> state_binder = IInterface::asBinder(state.surface); const sp<IBinder> draw_binder = IInterface::asBinder(draw[i].surface); if (state_binder != draw_binder) { // changing the surface is like destroying and // recreating the DisplayDevice, so we just remove it // from the drawing state, so that it get re-added // below. sp<DisplayDevice> hw(getDisplayDevice(display)); if (hw != NULL) hw->disconnect(getHwComposer()); mDisplays.removeItem(display); mDrawingState.displays.removeItemsAt(i); dc--; i--; // at this point we must loop to the next item continue; }
// find displays that were added // (ie: in current state but not in drawing state) for (size_t i=0 ; i<cc ; i++) { if (draw.indexOfKey(curr.keyAt(i)) < 0) { const DisplayDeviceState& state(curr[i]);
int32_t hwcDisplayId = -1; if (state.isVirtualDisplay()) { // Virtual displays without a surface are dormant: // they have external state (layer stack, projection, // etc.) but no internal state (i.e. a DisplayDevice). if (state.surface != NULL) {
int width = 0; DisplayUtils* displayUtils = DisplayUtils::getInstance(); int status = state.surface->query( NATIVE_WINDOW_WIDTH, &width); ALOGE_IF(status != NO_ERROR, "Unable to query width (%d)", status); int height = 0; status = state.surface->query( NATIVE_WINDOW_HEIGHT, &height); ALOGE_IF(status != NO_ERROR, "Unable to query height (%d)", status); if (MAX_VIRTUAL_DISPLAY_DIMENSION == 0 || (width <= MAX_VIRTUAL_DISPLAY_DIMENSION && height <= MAX_VIRTUAL_DISPLAY_DIMENSION)) { int usage = 0; status = state.surface->query( NATIVE_WINDOW_CONSUMER_USAGE_BITS, &usage); ALOGW_IF(status != NO_ERROR, "Unable to query usage (%d)", status); if ( (status == NO_ERROR) && displayUtils->canAllocateHwcDisplayIdForVDS(usage)) { hwcDisplayId = allocateHwcDisplayId(state.type); } }
displayUtils->initVDSInstance(mHwc, hwcDisplayId, state.surface, dispSurface, producer, bqProducer, bqConsumer, state.displayName, state.isSecure, state.type); } } else { ALOGE_IF(state.surface!=NULL, "adding a supported display, but rendering " "surface is provided (%p), ignoring it", state.surface.get()); hwcDisplayId = allocateHwcDisplayId(state.type); // for supported (by hwc) displays we provide our // own rendering surface dispSurface = new FramebufferSurface(*mHwc, state.type, bqConsumer); producer = bqProducer; }
const wp<IBinder>& display(curr.keyAt(i)); if (dispSurface != NULL && producer != NULL) { sp<DisplayDevice> hw = new DisplayDevice(this, state.type, hwcDisplayId, mHwc->getFormat(hwcDisplayId), state.isSecure, display, dispSurface, producer, mRenderEngine->getEGLConfig()); hw->setLayerStack(state.layerStack); hw->setProjection(state.orientation, state.viewport, state.frame); hw->setDisplayName(state.displayName); // When a new display device is added update the active // config by querying HWC otherwise the default config // (config 0) will be used. if (hwcDisplayId >= DisplayDevice::DISPLAY_PRIMARY && hwcDisplayId < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) { int activeConfig = mHwc->getActiveConfig(hwcDisplayId); if (activeConfig >= 0) { hw->setActiveConfig(activeConfig); } } mDisplays.add(display, hw); if (state.isVirtualDisplay()) { if (hwcDisplayId >= 0) { mHwc->setVirtualDisplayProperties(hwcDisplayId, hw->getWidth(), hw->getHeight(), hw->getFormat()); } } else { mEventThread->onHotplugReceived(state.type, true); } } } } } }
if (transactionFlags & (eTraversalNeeded|eDisplayTransactionNeeded)) { ...... sp<const DisplayDevice> disp; uint32_t currentlayerStack = 0; for (size_t i=0; i<count; i++) { // NOTE: we rely on the fact that layers are sorted by // layerStack first (so we don't have to traverse the list // of displays for every layer). const sp<Layer>& layer(currentLayers[i]); uint32_t layerStack = layer->getDrawingState().layerStack; if (i==0 || currentlayerStack != layerStack) { currentlayerStack = layerStack; // figure out if this layerstack is mirrored // (more than one display) if so, pick the default display, // if not, pick the only display it's on. disp.clear(); for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) { sp<const DisplayDevice> hw(mDisplays[dpy]); if (hw->getLayerStack() == currentlayerStack) { if (disp == NULL) { disp = hw; } else { disp = NULL; break; } } } } if (disp == NULL) { // NOTE: TEMPORARY FIX ONLY. Real fix should cause layers to // redraw after transform hint changes. See bug 8508397.
// could be null when this layer is using a layerStack // that is not visible on any display. Also can occur at // screen off/on times. disp = getDefaultDisplayDevice(); } layer->updateTransformHint(disp); } }
const LayerVector& layers(mDrawingState.layersSortedByZ); if (currentLayers.size() > layers.size()) { // layers have been added mVisibleRegionsDirty = true; }
// some layers might have been removed, so // we need to update the regions they're exposing. if (mLayersRemoved) { mLayersRemoved = false; mVisibleRegionsDirty = true; constsize_t count = layers.size(); for (size_t i=0 ; i<count ; i++) { const sp<Layer>& layer(layers[i]); if (currentLayers.indexOf(layer) < 0) { // this layer is not visible anymore // TODO: we could traverse the tree from front to back and // compute the actual visible region // TODO: we could cache the transformed region const Layer::State& s(layer->getDrawingState()); Region visibleReg = s.active.transform.transform( Region(Rect(s.active.w, s.active.h))); invalidateLayerStack(s.layerStack, visibleReg); } } }
// Store the set of layers that need updates. This set must not change as // buffers are being latched, as this could result in a deadlock. // Example: Two producers share the same command stream and: // 1.) Layer 0 is latched // 2.) Layer 0 gets a new frame // 2.) Layer 1 gets a new frame // 3.) Layer 1 is latched. // Display is now waiting on Layer 1's frame, which is behind layer 0's // second frame. But layer 0's second frame could be waiting on display. Vector<Layer*> layersWithQueuedFrames; for (size_t i = 0, count = layers.size(); i<count ; i++) { const sp<Layer>& layer(layers[i]); if (layer->hasQueuedFrame()) { frameQueued = true; if (layer->shouldPresentNow(mPrimaryDispSync)) { layersWithQueuedFrames.push_back(layer.get()); } else { layer->useEmptyDamage(); } } else { layer->useEmptyDamage(); } } for (size_t i = 0, count = layersWithQueuedFrames.size() ; i<count ; i++) { Layer* layer = layersWithQueuedFrames[i]; const Region dirty(layer->latchBuffer(visibleRegions)); layer->useSurfaceDamage(); const Layer::State& s(layer->getDrawingState()); invalidateLayerStack(s.layerStack, dirty); }
mVisibleRegionsDirty |= visibleRegions;
// If we will need to wake up at some time in the future to deal with a // queued frame that shouldn't be displayed during this vsync period, wake // up during the next vsync period to check again. if (frameQueued && layersWithQueuedFrames.empty()) { signalLayerUpdate(); }
// Only continue with the refresh if there is actually new work to do return !layersWithQueuedFrames.empty(); }
if (mustRecompose) { mDisplays[dpy]->lastCompositionHadVisibleLayers = !empty; } } //得到系统HWComposer对象 HWComposer& hwc(getHwComposer()); if (hwc.initCheck() == NO_ERROR) { // build the h/w work list if (CC_UNLIKELY(mHwWorkListDirty)) { mHwWorkListDirty = false; for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) { sp<const DisplayDevice> hw(mDisplays[dpy]); constint32_t id = hw->getHwcDisplayId(); if (id >= 0) { const Vector< sp<Layer> >& currentLayers( hw->getVisibleLayersSortedByZ()); constsize_t count = currentLayers.size(); //根据Layer数量在HWComposer中创建hwc_layer_list_t列表 if (hwc.createWorkList(id, count) == NO_ERROR) { HWComposer::LayerListIterator cur = hwc.begin(id); const HWComposer::LayerListIterator end = hwc.end(id); for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) { const sp<Layer>& layer(currentLayers[i]); layer->setGeometry(hw, *cur); if (mDebugDisableHWC || mDebugRegion || mDaltonize || mHasColorMatrix) { cur->setSkip(true); } } } } } }
// set the per-frame data for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) { sp<const DisplayDevice> hw(mDisplays[dpy]); constint32_t id = hw->getHwcDisplayId(); if (id >= 0) { bool freezeSurfacePresent = false; isfreezeSurfacePresent(freezeSurfacePresent, hw, id); const Vector< sp<Layer> >& currentLayers( hw->getVisibleLayersSortedByZ()); constsize_t count = currentLayers.size(); HWComposer::LayerListIterator cur = hwc.begin(id); const HWComposer::LayerListIterator end = hwc.end(id); for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) { /* * update the per-frame h/w composer data for each layer * and build the transparent region of the FB */ const sp<Layer>& layer(currentLayers[i]); //将Layer的mActiveBuffer设置到HWComposer中 layer->setPerFrameData(hw, *cur); setOrientationEventControl(freezeSurfacePresent,id); } } }
// If possible, attempt to use the cursor overlay on each display. for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) { sp<const DisplayDevice> hw(mDisplays[dpy]); constint32_t id = hw->getHwcDisplayId(); if (id >= 0) { const Vector< sp<Layer> >& currentLayers( hw->getVisibleLayersSortedByZ()); constsize_t count = currentLayers.size(); HWComposer::LayerListIterator cur = hwc.begin(id); const HWComposer::LayerListIterator end = hwc.end(id); for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) { const sp<Layer>& layer(currentLayers[i]); if (layer->isPotentialCursor()) { cur->setIsCursorLayerHint(); break; } } } }
voidSurfaceFlinger::doComposition(){ ATRACE_CALL(); constbool repaintEverything = android_atomic_and(0, &mRepaintEverything); for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) { const sp<DisplayDevice>& hw(mDisplays[dpy]); if (hw->isDisplayOn()) { // transform the dirty region into this screen's coordinate space const Region dirtyRegion(hw->getDirtyRegion(repaintEverything));
// repaint the framebuffer (if needed) doDisplayComposition(hw, dirtyRegion);
hw->dirtyRegion.clear(); hw->flip(hw->swapRegion); hw->swapRegion.clear(); } // inform the h/w that we're done compositing hw->compositionComplete(); } postFramebuffer(); }
voidSurfaceFlinger::doDisplayComposition(const sp<const DisplayDevice>& hw, const Region& inDirtyRegion) { // We only need to actually compose the display if: // 1) It is being handled by hardware composer, which may need this to // keep its virtual display state machine in sync, or // 2) There is work to be done (the dirty region isn't empty) bool isHwcDisplay = hw->getHwcDisplayId() >= 0; if (!isHwcDisplay && inDirtyRegion.isEmpty()) { ALOGV("Skipping display composition"); return; }
ALOGV("doDisplayComposition");
Region dirtyRegion(inDirtyRegion);
// compute the invalid region //swapRegion设置为需要更新的区域 hw->swapRegion.orSelf(dirtyRegion);
uint32_t flags = hw->getFlags();//获得显示设备支持的更新方式标志 if (flags & DisplayDevice::SWAP_RECTANGLE) { // we can redraw only what's dirty, but since SWAP_RECTANGLE only // takes a rectangle, we must make sure to update that whole // rectangle in that case dirtyRegion.set(hw->swapRegion.bounds()); } else { if (flags & DisplayDevice::PARTIAL_UPDATES) {//支持部分更新 // We need to redraw the rectangle that will be updated // (pushed to the framebuffer). // This is needed because PARTIAL_UPDATES only takes one // rectangle instead of a region (see DisplayDevice::flip()) //将更新区域调整为整个窗口大小 dirtyRegion.set(hw->swapRegion.bounds()); } else { // we need to redraw everything (the whole screen) dirtyRegion.set(hw->bounds()); hw->swapRegion = dirtyRegion; } } //合成 if (!doComposeSurfaces(hw, dirtyRegion)) return;
// update the swap region and clear the dirty region hw->swapRegion.orSelf(dirtyRegion); //没有硬件composer的情况,输出图像 // swap buffers (presentation) hw->swapBuffers(getHwComposer()); }
constnsecs_t now = systemTime(); mDebugInSwapBuffers = now;
HWComposer& hwc(getHwComposer()); if (hwc.initCheck() == NO_ERROR) { if (!hwc.supportsFramebufferTarget()) { // EGL spec says: // "surface must be bound to the calling thread's current context, // for the current rendering API." getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext); } hwc.commit(); }
// make the default display current because the VirtualDisplayDevice code cannot // deal with dequeueBuffer() being called outside of the composition loop; however // the code below can call glFlush() which is allowed (and does in some case) call // dequeueBuffer(). getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);
for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) { sp<const DisplayDevice> hw(mDisplays[dpy]); const Vector< sp<Layer> >& currentLayers(hw->getVisibleLayersSortedByZ()); hw->onSwapBuffersCompleted(hwc); constsize_t count = currentLayers.size(); int32_t id = hw->getHwcDisplayId(); if (id >=0 && hwc.initCheck() == NO_ERROR) { HWComposer::LayerListIterator cur = hwc.begin(id); const HWComposer::LayerListIterator end = hwc.end(id); for (size_t i = 0; cur != end && i < count; ++i, ++cur) { currentLayers[i]->onLayerDisplayed(hw, &*cur); } } else { for (size_t i = 0; i < count; i++) { currentLayers[i]->onLayerDisplayed(hw, NULL); } } }
status_tHWComposer::commit(){ int err = NO_ERROR; if (mHwc) { if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) { // On version 1.0, the OpenGL ES target surface is communicated // by the (dpy, sur) fields and we are guaranteed to have only // a single display. mLists[0]->dpy = eglGetCurrentDisplay(); mLists[0]->sur = eglGetCurrentSurface(EGL_DRAW); }
for (size_t i=VIRTUAL_DISPLAY_ID_BASE; i<mNumDisplays; i++) { DisplayData& disp(mDisplayData[i]); if (disp.outbufHandle) { mLists[i]->outbuf = disp.outbufHandle; mLists[i]->outbufAcquireFenceFd = disp.outbufAcquireFence->dup(); } }