uint32_t LayerBase::doTransaction(uint32_t flags) { const Layer::State& front(drawingState()); const Layer::State& temp(currentState()); // always set active to requested, unless we're asked not to // this is used by Layer, which special cases resizes. if (flags & eDontUpdateGeometryState) { } else { Layer::State& editTemp(currentState()); editTemp.active = temp.requested; } if (front.active != temp.active) { // invalidate and recompute the visible regions if needed flags |= Layer::eVisibleRegion; } if (temp.sequence != front.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 = temp.transform.getType(); mNeedsFiltering = (!temp.transform.preserveRects() || (type >= Transform::SCALE)); } // Commit the transaction commitTransaction(); return flags; }
uint32_t LayerBase::doTransaction(uint32_t flags) { const Layer::State& front(drawingState()); const Layer::State& temp(currentState()); if ((front.requested_w != temp.requested_w) || (front.requested_h != temp.requested_h)) { // resize the layer, set the physical size to the requested size Layer::State& editTemp(currentState()); editTemp.w = temp.requested_w; editTemp.h = temp.requested_h; } if ((front.w != temp.w) || (front.h != temp.h)) { // invalidate and recompute the visible regions if needed flags |= Layer::eVisibleRegion; } if (temp.sequence != front.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 = temp.transform.getType(); mNeedsFiltering = (!temp.transform.preserveRects() || (type >= Transform::SCALE)); } // Commit the transaction commitTransaction(); return 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); } } }