Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 88138291 authored by Mathias Agopian's avatar Mathias Agopian Committed by Android Git Automerger
Browse files

am f59d2f90: Merge changes I0e90b3f3,Ib7769bde,I4c25f34f,I1ec6400a into jb-mr2-dev

* commit 'f59d2f90':
  implement display projection clipping in h/w composer
  refactor the crop region for hwc is calculated/set
  apply the projection's viewport to the visibleregion passed to hwc
  set correct crop rectangle in LayerBase::setCrop
parents 54a1faa7 f59d2f90
Loading
Loading
Loading
Loading
+62 −63
Original line number Original line Diff line number Diff line
@@ -287,7 +287,8 @@ void DisplayDevice::setVisibleLayersSortedByZ(const Vector< sp<LayerBase> >& lay
    mSecureLayerVisible = false;
    mSecureLayerVisible = false;
    size_t count = layers.size();
    size_t count = layers.size();
    for (size_t i=0 ; i<count ; i++) {
    for (size_t i=0 ; i<count ; i++) {
        if (layers[i]->isSecure()) {
        const sp<LayerBase>& layer(layers[i]);
        if (layer->isSecure()) {
            mSecureLayerVisible = true;
            mSecureLayerVisible = true;
        }
        }
    }
    }
@@ -365,23 +366,15 @@ status_t DisplayDevice::orientationToTransfrom(
}
}


void DisplayDevice::setProjection(int orientation,
void DisplayDevice::setProjection(int orientation,
        const Rect& viewport, const Rect& frame) {
        const Rect& newViewport, const Rect& newFrame) {
    mOrientation = orientation;
    Rect viewport(newViewport);
    mViewport = viewport;
    Rect frame(newFrame);
    mFrame = frame;
    updateGeometryTransform();
}


void DisplayDevice::updateGeometryTransform() {
    const int w = mDisplayWidth;
    int w = mDisplayWidth;
    const int h = mDisplayHeight;
    int h = mDisplayHeight;
    Transform TL, TP, R, S;
    if (DisplayDevice::orientationToTransfrom(
            mOrientation, w, h, &R) == NO_ERROR) {
        dirtyRegion.set(bounds());


        Rect viewport(mViewport);
    Transform R;
        Rect frame(mFrame);
    DisplayDevice::orientationToTransfrom(orientation, w, h, &R);


    if (!frame.isValid()) {
    if (!frame.isValid()) {
        // the destination frame can be invalid if it has never been set,
        // the destination frame can be invalid if it has never been set,
@@ -402,6 +395,9 @@ void DisplayDevice::updateGeometryTransform() {
        }
        }
    }
    }


    dirtyRegion.set(getBounds());

    Transform TL, TP, S;
    float src_width  = viewport.width();
    float src_width  = viewport.width();
    float src_height = viewport.height();
    float src_height = viewport.height();
    float dst_width  = frame.width();
    float dst_width  = frame.width();
@@ -428,11 +424,14 @@ void DisplayDevice::updateGeometryTransform() {
    mNeedsFiltering = (!mGlobalTransform.preserveRects() ||
    mNeedsFiltering = (!mGlobalTransform.preserveRects() ||
            (type >= Transform::SCALE));
            (type >= Transform::SCALE));


        mScissor = mGlobalTransform.transform(mViewport);
    mScissor = mGlobalTransform.transform(viewport);
    if (mScissor.isEmpty()) {
    if (mScissor.isEmpty()) {
        mScissor.set(getBounds());
        mScissor.set(getBounds());
    }
    }
    }

    mOrientation = orientation;
    mViewport = viewport;
    mFrame = frame;
}
}


void DisplayDevice::dump(String8& result, char* buffer, size_t SIZE) const {
void DisplayDevice::dump(String8& result, char* buffer, size_t SIZE) const {
+2 −4
Original line number Original line Diff line number Diff line
@@ -105,8 +105,8 @@ public:


    int                     getOrientation() const { return mOrientation; }
    int                     getOrientation() const { return mOrientation; }
    const Transform&        getTransform() const { return mGlobalTransform; }
    const Transform&        getTransform() const { return mGlobalTransform; }
    const Rect&             getViewport() const { return mViewport; }
    const Rect              getViewport() const { return mViewport; }
    const Rect&             getFrame() const { return mFrame; }
    const Rect              getFrame() const { return mFrame; }
    const Rect&             getScissor() const { return mScissor; }
    const Rect&             getScissor() const { return mScissor; }
    bool                    needsFiltering() const { return mNeedsFiltering; }
    bool                    needsFiltering() const { return mNeedsFiltering; }


@@ -197,8 +197,6 @@ private:
    static status_t orientationToTransfrom(int orientation,
    static status_t orientationToTransfrom(int orientation,
            int w, int h, Transform* tr);
            int w, int h, Transform* tr);


    void updateGeometryTransform();

    uint32_t mLayerStack;
    uint32_t mLayerStack;
    int mOrientation;
    int mOrientation;
    // user-provided visible area of the layer stack
    // user-provided visible area of the layer stack
+12 −35
Original line number Original line Diff line number Diff line
@@ -19,7 +19,6 @@
#include <stdlib.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/types.h>
#include <math.h>


#include <cutils/compiler.h>
#include <cutils/compiler.h>
#include <cutils/native_handle.h>
#include <cutils/native_handle.h>
@@ -200,46 +199,25 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h,
    return NO_ERROR;
    return NO_ERROR;
}
}


Rect Layer::computeBufferCrop() const {
Rect Layer::getContentCrop() const {
    // Start with the SurfaceFlingerConsumer's buffer crop...
    // this is the crop rectangle that applies to the buffer
    // itself (as opposed to the window)
    Rect crop;
    Rect crop;
    if (!mCurrentCrop.isEmpty()) {
    if (!mCurrentCrop.isEmpty()) {
        // if the buffer crop is defined, we use that
        crop = mCurrentCrop;
        crop = mCurrentCrop;
    } else if (mActiveBuffer != NULL) {
    } else if (mActiveBuffer != NULL) {
        crop = Rect(mActiveBuffer->getWidth(), mActiveBuffer->getHeight());
        // otherwise we use the whole buffer
        crop = mActiveBuffer->getBounds();
    } else {
    } else {
        // if we don't have a buffer yet, we use an empty/invalid crop
        crop.makeInvalid();
        crop.makeInvalid();
        return crop;
    }
    }

    return crop;
    // ... then reduce that in the same proportions as the window crop reduces
    // the window size.
    const State& s(drawingState());
    if (!s.active.crop.isEmpty()) {
        // Transform the window crop to match the buffer coordinate system,
        // which means using the inverse of the current transform set on the
        // SurfaceFlingerConsumer.
        uint32_t invTransform = mCurrentTransform;
        int winWidth = s.active.w;
        int winHeight = s.active.h;
        if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
            invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
                    NATIVE_WINDOW_TRANSFORM_FLIP_H;
            winWidth = s.active.h;
            winHeight = s.active.w;
        }
        Rect winCrop = s.active.crop.transform(invTransform,
                s.active.w, s.active.h);

        float xScale = float(crop.width()) / float(winWidth);
        float yScale = float(crop.height()) / float(winHeight);
        crop.left += int(ceilf(float(winCrop.left) * xScale));
        crop.top += int(ceilf(float(winCrop.top) * yScale));
        crop.right -= int(ceilf(float(winWidth - winCrop.right) * xScale));
        crop.bottom -= int(ceilf(float(winHeight - winCrop.bottom) * yScale));
}
}


    return crop;
uint32_t Layer::getContentTransform() const {
    return mCurrentTransform;
}
}


void Layer::setGeometry(
void Layer::setGeometry(
@@ -278,7 +256,6 @@ void Layer::setGeometry(
    } else {
    } else {
        layer.setTransform(finalTransform);
        layer.setTransform(finalTransform);
    }
    }
    layer.setCrop(computeBufferCrop());
}
}


void Layer::setPerFrameData(const sp<const DisplayDevice>& hw,
void Layer::setPerFrameData(const sp<const DisplayDevice>& hw,
+3 −1
Original line number Original line Diff line number Diff line
@@ -103,6 +103,9 @@ public:
    // the current orientation of the display device.
    // the current orientation of the display device.
    virtual void updateTransformHint(const sp<const DisplayDevice>& hw) const;
    virtual void updateTransformHint(const sp<const DisplayDevice>& hw) const;


    virtual Rect getContentCrop() const;
    virtual uint32_t getContentTransform() const;

protected:
protected:
    virtual void onFirstRef();
    virtual void onFirstRef();
    virtual void dump(String8& result, char* scratch, size_t size) const;
    virtual void dump(String8& result, char* scratch, size_t size) const;
@@ -115,7 +118,6 @@ private:


    uint32_t getEffectiveUsage(uint32_t usage) const;
    uint32_t getEffectiveUsage(uint32_t usage) const;
    bool isCropped() const;
    bool isCropped() const;
    Rect computeBufferCrop() const;
    static bool getOpacityForFormat(uint32_t format);
    static bool getOpacityForFormat(uint32_t format);


    // Interface implementation for SurfaceFlingerConsumer::FrameAvailableListener
    // Interface implementation for SurfaceFlingerConsumer::FrameAvailableListener
+107 −12
Original line number Original line Diff line number Diff line
@@ -17,6 +17,7 @@
#include <stdlib.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/types.h>
#include <math.h>


#include <utils/Errors.h>
#include <utils/Errors.h>
#include <utils/Log.h>
#include <utils/Log.h>
@@ -259,7 +260,7 @@ Rect LayerBase::computeBounds() const {
    if (!s.active.crop.isEmpty()) {
    if (!s.active.crop.isEmpty()) {
        win.intersect(s.active.crop, &win);
        win.intersect(s.active.crop, &win);
    }
    }
    return s.transform.transform(win);
    return win;
}
}


Region LayerBase::latchBuffer(bool& recomputeVisibleRegions) {
Region LayerBase::latchBuffer(bool& recomputeVisibleRegions) {
@@ -267,6 +268,83 @@ Region LayerBase::latchBuffer(bool& recomputeVisibleRegions) {
    return result;
    return result;
}
}



Rect LayerBase::getContentCrop() const {
    // regular layers just use their active area as the content crop
    const State& s(drawingState());
    return Rect(s.active.w, s.active.h);
}

uint32_t LayerBase::getContentTransform() const {
    // regular layers don't have a content transform
    return 0;
}

Rect LayerBase::computeCrop(const sp<const DisplayDevice>& hw) const {
    /*
     * The way we compute the crop (aka. texture coordinates when we have a
     * Layer) produces a different output from the GL code in
     * drawWithOpenGL() due to HWC being limited to integers. The difference
     * can be large if getContentTransform() contains a large scale factor.
     * See comments in drawWithOpenGL() for more details.
     */

    // the content crop is the area of the content that gets scaled to the
    // layer's size.
    Rect crop(getContentCrop());

    // the active.crop is the area of the window that gets cropped, but not
    // scaled in any ways.
    const State& s(drawingState());

    // apply the projection's clipping to the window crop in
    // layerstack space, and convert-back to layer space.
    // if there are no window scaling (or content scaling) involved,
    // this operation will map to full pixels in the buffer.
    // NOTE: should we revert to GL composition if a scaling is involved
    // since it cannot be represented in the HWC API?
    Rect activeCrop(s.transform.transform(s.active.crop));
    activeCrop.intersect(hw->getViewport(), &activeCrop);
    activeCrop = s.transform.inverse().transform(activeCrop);

    // paranoia: make sure the window-crop is constrained in the
    // window's bounds
    activeCrop.intersect(Rect(s.active.w, s.active.h), &activeCrop);

    if (!activeCrop.isEmpty()) {
        // Transform the window crop to match the buffer coordinate system,
        // which means using the inverse of the current transform set on the
        // SurfaceFlingerConsumer.
        uint32_t invTransform = getContentTransform();
        int winWidth = s.active.w;
        int winHeight = s.active.h;
        if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
            invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
                    NATIVE_WINDOW_TRANSFORM_FLIP_H;
            winWidth = s.active.h;
            winHeight = s.active.w;
        }
        const Rect winCrop = activeCrop.transform(
                invTransform, s.active.w, s.active.h);

        // the code below essentially performs a scaled intersection
        // of crop and winCrop
        float xScale = float(crop.width()) / float(winWidth);
        float yScale = float(crop.height()) / float(winHeight);

        int insetL = int(ceilf( winCrop.left                * xScale));
        int insetT = int(ceilf( winCrop.top                 * yScale));
        int insetR = int(ceilf((winWidth  - winCrop.right ) * xScale));
        int insetB = int(ceilf((winHeight - winCrop.bottom) * yScale));

        crop.left   += insetL;
        crop.top    += insetT;
        crop.right  -= insetR;
        crop.bottom -= insetB;
    }
    return crop;
}

void LayerBase::setGeometry(
void LayerBase::setGeometry(
    const sp<const DisplayDevice>& hw,
    const sp<const DisplayDevice>& hw,
        HWComposer::HWCLayerInterface& layer)
        HWComposer::HWCLayerInterface& layer)
@@ -289,13 +367,15 @@ void LayerBase::setGeometry(
                HWC_BLENDING_COVERAGE);
                HWC_BLENDING_COVERAGE);
    }
    }


    const Transform& tr = hw->getTransform();
    Rect transformedBounds(computeBounds());
    transformedBounds = tr.transform(transformedBounds);


    // scaling is already applied in transformedBounds
    // apply the layer's transform, followed by the display's global transform
    layer.setFrame(transformedBounds);
    // here we're guaranteed that the layer's transform preserves rects
    layer.setCrop(transformedBounds.getBounds());

    Rect frame(s.transform.transform(computeBounds()));
    frame.intersect(hw->getViewport(), &frame);
    const Transform& tr(hw->getTransform());
    layer.setFrame(tr.transform(frame));
    layer.setCrop(computeCrop(hw));
}
}


void LayerBase::setPerFrameData(const sp<const DisplayDevice>& hw,
void LayerBase::setPerFrameData(const sp<const DisplayDevice>& hw,
@@ -303,8 +383,11 @@ void LayerBase::setPerFrameData(const sp<const DisplayDevice>& hw,
    // we have to set the visible region on every frame because
    // we have to set the visible region on every frame because
    // we currently free it during onLayerDisplayed(), which is called
    // we currently free it during onLayerDisplayed(), which is called
    // after HWComposer::commit() -- every frame.
    // after HWComposer::commit() -- every frame.
    // Apply this display's projection's viewport to the visible region
    // before giving it to the HWC HAL.
    const Transform& tr = hw->getTransform();
    const Transform& tr = hw->getTransform();
    layer.setVisibleRegionScreen(tr.transform(visibleRegion));
    Region visible = tr.transform(visibleRegion.intersect(hw->getViewport()));
    layer.setVisibleRegionScreen(visible);
}
}


void LayerBase::setAcquireFence(const sp<const DisplayDevice>& hw,
void LayerBase::setAcquireFence(const sp<const DisplayDevice>& hw,
@@ -404,10 +487,22 @@ void LayerBase::drawWithOpenGL(const sp<const DisplayDevice>& hw, const Region&
        GLfloat v;
        GLfloat v;
    };
    };


    Rect win(s.active.w, s.active.h);

    if (!s.active.crop.isEmpty()) {
    /*
        win.intersect(s.active.crop, &win);
     * NOTE: the way we compute the texture coordinates here produces
    }
     * different results than when we take the HWC path -- in the later case
     * the "source crop" is rounded to texel boundaries.
     * This can produce significantly different results when the texture
     * is scaled by a large amount.
     *
     * The GL code below is more logical (imho), and the difference with
     * HWC is due to a limitation of the HWC API to integers -- a question
     * is suspend is wether we should ignore this problem or revert to
     * GL composition when a buffer scaling is applied (maybe with some
     * minimal value)? Or, we could make GL behave like HWC -- but this feel
     * like more of a hack.
     */
    const Rect win(computeBounds());


    GLfloat left   = GLfloat(win.left)   / GLfloat(s.active.w);
    GLfloat left   = GLfloat(win.left)   / GLfloat(s.active.w);
    GLfloat top    = GLfloat(win.top)    / GLfloat(s.active.h);
    GLfloat top    = GLfloat(win.top)    / GLfloat(s.active.h);
Loading