uint32_t Layer::doTransaction(uint32_t flags) { const Layer::State& front(drawingState()); const Layer::State& temp(currentState()); const bool sizeChanged = (front.requested_w != temp.requested_w) || (front.requested_h != temp.requested_h); if (sizeChanged) { // the size changed, we need to ask our client to request a new buffer LOGD_IF(DEBUG_RESIZE, "doTransaction: " "resize (layer=%p), requested (%dx%d), drawing (%d,%d), " "scalingMode=%d", this, int(temp.requested_w), int(temp.requested_h), int(front.requested_w), int(front.requested_h), mCurrentScalingMode); if (!isFixedSize()) { // this will make sure LayerBase::doTransaction doesn't update // the drawing state's size Layer::State& editDraw(mDrawingState); editDraw.requested_w = temp.requested_w; editDraw.requested_h = temp.requested_h; } // record the new size, form this point on, when the client request // a buffer, it'll get the new size. mSurfaceTexture->setDefaultBufferSize(temp.requested_w, temp.requested_h); } return LayerBase::doTransaction(flags); }
uint32_t Layer::doTransaction(uint32_t flags) { const Layer::State& front(drawingState()); const Layer::State& temp(currentState()); const bool sizeChanged = (front.requested_w != temp.requested_w) || (front.requested_h != temp.requested_h); if (sizeChanged) { // the size changed, we need to ask our client to request a new buffer LOGD_IF(DEBUG_RESIZE, "doTransaction: " "resize (layer=%p), requested (%dx%d), drawing (%d,%d), " "scalingMode=%d", this, int(temp.requested_w), int(temp.requested_h), int(front.requested_w), int(front.requested_h), mCurrentScalingMode); if (!isFixedSize()) { // we're being resized and there is a freeze display request, // acquire a freeze lock, so that the screen stays put // until we've redrawn at the new size; this is to avoid // glitches upon orientation changes. if (mFlinger->hasFreezeRequest()) { // if the surface is hidden, don't try to acquire the // freeze lock, since hidden surfaces may never redraw if (!(front.flags & ISurfaceComposer::eLayerHidden)) { mFreezeLock = mFlinger->getFreezeLock(); } } // this will make sure LayerBase::doTransaction doesn't update // the drawing state's size Layer::State& editDraw(mDrawingState); editDraw.requested_w = temp.requested_w; editDraw.requested_h = temp.requested_h; } // record the new size, form this point on, when the client request // a buffer, it'll get the new size. mSurfaceTexture->setDefaultBufferSize(temp.requested_w, temp.requested_h); } if (temp.sequence != front.sequence) { if (temp.flags & ISurfaceComposer::eLayerHidden || temp.alpha == 0) { // this surface is now hidden, so it shouldn't hold a freeze lock // (it may never redraw, which is fine if it is hidden) mFreezeLock.clear(); } } return LayerBase::doTransaction(flags); }
void Layer::lockPageFlip(bool& recomputeVisibleRegions) { ClientRef::Access sharedClient(mUserClientRef); SharedBufferServer* lcblk(sharedClient.get()); if (!lcblk) { // client died recomputeVisibleRegions = true; return; } ssize_t buf = lcblk->retireAndLock(); if (buf == NOT_ENOUGH_DATA) { // NOTE: This is not an error, it simply means there is nothing to // retire. The buffer is locked because we will use it // for composition later in the loop return; } if (buf < NO_ERROR) { LOGE("retireAndLock() buffer index (%d) out of range", int(buf)); mPostedDirtyRegion.clear(); return; } // we retired a buffer, which becomes the new front buffer if (mBufferManager.setActiveBufferIndex(buf) < NO_ERROR) { LOGE("retireAndLock() buffer index (%d) out of range", int(buf)); mPostedDirtyRegion.clear(); return; } sp<GraphicBuffer> newFrontBuffer(getBuffer(buf)); if (newFrontBuffer != NULL) { // get the dirty region // compute the posted region const Region dirty(lcblk->getDirtyRegion(buf)); mPostedDirtyRegion = dirty.intersect( newFrontBuffer->getBounds() ); // update the layer size and release freeze-lock const Layer::State& front(drawingState()); if (newFrontBuffer->getWidth() == front.requested_w && newFrontBuffer->getHeight() == front.requested_h) { if ((front.w != front.requested_w) || (front.h != front.requested_h)) { // Here we pretend the transaction happened by updating the // current and drawing states. Drawing state is only accessed // in this thread, no need to have it locked Layer::State& editDraw(mDrawingState); editDraw.w = editDraw.requested_w; editDraw.h = editDraw.requested_h; // We also need to update the current state so that we don't // end-up doing too much work during the next transaction. // NOTE: We actually don't need hold the transaction lock here // because State::w and State::h are only accessed from // this thread Layer::State& editTemp(currentState()); editTemp.w = editDraw.w; editTemp.h = editDraw.h; // recompute visible region recomputeVisibleRegions = true; } // we now have the correct size, unfreeze the screen mFreezeLock.clear(); } // get the crop region setBufferCrop( lcblk->getCrop(buf) ); // get the transformation setBufferTransform( lcblk->getTransform(buf) ); } else { // this should not happen unless we ran out of memory while // allocating the buffer. we're hoping that things will get back // to normal the next time the app tries to draw into this buffer. // meanwhile, pretend the screen didn't update. mPostedDirtyRegion.clear(); } if (lcblk->getQueuedCount()) { // signal an event if we have more buffers waiting mFlinger->signalEvent(); } /* a buffer was posted, so we need to call reloadTexture(), which * will update our internal data structures (eg: EGLImageKHR or * texture names). we need to do this even if mPostedDirtyRegion is * empty -- it's orthogonal to the fact that a new buffer was posted, * for instance, a degenerate case could be that the user did an empty * update but repainted the buffer with appropriate content (after a * resize for instance). */ reloadTexture( mPostedDirtyRegion ); }
void Layer::lockPageFlip(bool& recomputeVisibleRegions) { if (mQueuedFrames > 0) { // Capture the old state of the layer for comparisons later const bool oldOpacity = isOpaque(); sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer; // signal another event if we have more frames pending if (android_atomic_dec(&mQueuedFrames) > 1) { mFlinger->signalEvent(); } if (mSurfaceTexture->updateTexImage() < NO_ERROR) { // something happened! recomputeVisibleRegions = true; return; } // update the active buffer mActiveBuffer = mSurfaceTexture->getCurrentBuffer(); hasmixed=false; const Rect crop(mSurfaceTexture->getCurrentCrop()); const uint32_t transform(mSurfaceTexture->getCurrentTransform()); const uint32_t scalingMode(mSurfaceTexture->getCurrentScalingMode()); if ((crop != mCurrentCrop) || (transform != mCurrentTransform) || (scalingMode != mCurrentScalingMode)) { mCurrentCrop = crop; mCurrentTransform = transform; mCurrentScalingMode = scalingMode; mFlinger->invalidateHwcGeometry(); } GLfloat textureMatrix[16]; mSurfaceTexture->getTransformMatrix(textureMatrix); if (memcmp(textureMatrix, mTextureMatrix, sizeof(textureMatrix))) { memcpy(mTextureMatrix, textureMatrix, sizeof(textureMatrix)); mFlinger->invalidateHwcGeometry(); } uint32_t bufWidth = mActiveBuffer->getWidth(); uint32_t bufHeight = mActiveBuffer->getHeight(); if (oldActiveBuffer != NULL) { if (bufWidth != uint32_t(oldActiveBuffer->width) || bufHeight != uint32_t(oldActiveBuffer->height)) { mFlinger->invalidateHwcGeometry(); } } mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format); if (oldOpacity != isOpaque()) { recomputeVisibleRegions = true; } glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // update the layer size if needed const Layer::State& front(drawingState()); // FIXME: mPostedDirtyRegion = dirty & bounds mPostedDirtyRegion.set(front.w, front.h); if ((front.w != front.requested_w) || (front.h != front.requested_h)) { // check that we received a buffer of the right size // (Take the buffer's orientation into account) if (mCurrentTransform & Transform::ROT_90) { swap(bufWidth, bufHeight); } if (isFixedSize() || (bufWidth == front.requested_w && bufHeight == front.requested_h)) { // Here we pretend the transaction happened by updating the // current and drawing states. Drawing state is only accessed // in this thread, no need to have it locked Layer::State& editDraw(mDrawingState); editDraw.w = editDraw.requested_w; editDraw.h = editDraw.requested_h; // We also need to update the current state so that we don't // end-up doing too much work during the next transaction. // NOTE: We actually don't need hold the transaction lock here // because State::w and State::h are only accessed from // this thread Layer::State& editTemp(currentState()); editTemp.w = editDraw.w; editTemp.h = editDraw.h; // recompute visible region recomputeVisibleRegions = true; } LOGD_IF(DEBUG_RESIZE, "lockPageFlip : " " (layer=%p), buffer (%ux%u, tr=%02x), " "requested (%dx%d)", this, bufWidth, bufHeight, mCurrentTransform, front.requested_w, front.requested_h); } } }