Пример #1
0
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);
}
Пример #2
0
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);
}
Пример #3
0
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 );
}
Пример #4
0
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);
        }
    }
}