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

Commit da8d0a5c authored by Mathias Agopian's avatar Mathias Agopian
Browse files

implement display viewport and frame

note: viewport clipping is not implemented yet

Change-Id: I7fde7c4de075d409d95c48bb20ba8ee017f6f00a
parent 493db479
Loading
Loading
Loading
Loading
+85 −16
Original line number Original line Diff line number Diff line
@@ -38,6 +38,7 @@
#include "DisplayHardware/FramebufferSurface.h"
#include "DisplayHardware/FramebufferSurface.h"
#include "DisplayHardware/HWComposer.h"
#include "DisplayHardware/HWComposer.h"


#include "clz.h"
#include "DisplayDevice.h"
#include "DisplayDevice.h"
#include "GLExtensions.h"
#include "GLExtensions.h"
#include "SurfaceFlinger.h"
#include "SurfaceFlinger.h"
@@ -84,8 +85,8 @@ DisplayDevice::DisplayDevice(
      mPageFlipCount(),
      mPageFlipCount(),
      mSecureLayerVisible(false),
      mSecureLayerVisible(false),
      mScreenAcquired(false),
      mScreenAcquired(false),
      mOrientation(),
      mLayerStack(0),
      mLayerStack(0)
      mOrientation()
{
{
    init(config);
    init(config);
}
}
@@ -139,6 +140,8 @@ void DisplayDevice::init(EGLConfig config)
    mSurface = surface;
    mSurface = surface;
    mFormat  = format;
    mFormat  = format;
    mPageFlipCount = 0;
    mPageFlipCount = 0;
    mViewport.makeInvalid();
    mFrame.makeInvalid();


    // external displays are always considered enabled
    // external displays are always considered enabled
    mScreenAcquired = (mType >= DisplayDevice::NUM_DISPLAY_TYPES);
    mScreenAcquired = (mType >= DisplayDevice::NUM_DISPLAY_TYPES);
@@ -192,13 +195,24 @@ void DisplayDevice::dump(String8& res) const
    }
    }
}
}


void DisplayDevice::makeCurrent(const sp<const DisplayDevice>& hw, EGLContext ctx) {
EGLBoolean DisplayDevice::makeCurrent(EGLDisplay dpy,
        const sp<const DisplayDevice>& hw, EGLContext ctx) {
    EGLBoolean result = EGL_TRUE;
    EGLSurface sur = eglGetCurrentSurface(EGL_DRAW);
    EGLSurface sur = eglGetCurrentSurface(EGL_DRAW);
    if (sur != hw->mSurface) {
    if (sur != hw->mSurface) {
        EGLDisplay dpy = eglGetCurrentDisplay();
        result = eglMakeCurrent(dpy, hw->mSurface, hw->mSurface, ctx);
        eglMakeCurrent(dpy, hw->mSurface, hw->mSurface, ctx);
        if (result == EGL_TRUE) {
            GLsizei w = hw->mDisplayWidth;
            GLsizei h = hw->mDisplayHeight;
            glViewport(0, 0, w, h);
            glMatrixMode(GL_PROJECTION);
            glLoadIdentity();
            // put the origin in the left-bottom corner
            glOrthof(0, w, 0, h, 0, 1); // l=0, r=w ; b=0, t=h
        }
        }
    }
    }
    return result;
}


// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------


@@ -223,10 +237,10 @@ bool DisplayDevice::getSecureLayerVisible() const {


Region DisplayDevice::getDirtyRegion(bool repaintEverything) const {
Region DisplayDevice::getDirtyRegion(bool repaintEverything) const {
    Region dirty;
    Region dirty;
    const Transform& planeTransform(mGlobalTransform);
    if (repaintEverything) {
    if (repaintEverything) {
        dirty.set(getBounds());
        dirty.set(getBounds());
    } else {
    } else {
        const Transform& planeTransform(mGlobalTransform);
        dirty = planeTransform.transform(this->dirtyRegion);
        dirty = planeTransform.transform(this->dirtyRegion);
        dirty.andSelf(getBounds());
        dirty.andSelf(getBounds());
    }
    }
@@ -284,18 +298,73 @@ status_t DisplayDevice::orientationToTransfrom(
    return NO_ERROR;
    return NO_ERROR;
}
}


status_t DisplayDevice::setOrientation(int orientation) {
void DisplayDevice::setOrientation(int orientation) {
    mOrientation = orientation;
    updateGeometryTransform();
}

void DisplayDevice::setViewport(const Rect& viewport) {
    if (viewport.isValid()) {
        mViewport = viewport;
        updateGeometryTransform();
    }
}

void DisplayDevice::setFrame(const Rect& frame) {
    if (frame.isValid()) {
        mFrame = frame;
        updateGeometryTransform();
    }
}

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

        Rect viewport(mViewport);
        Rect frame(mFrame);


    DisplayDevice::orientationToTransfrom(
        if (!frame.isValid()) {
            orientation, w, h, &mGlobalTransform);
            // the destination frame can be invalid if it has never been set,
    if (orientation & DisplayState::eOrientationSwapMask) {
            // in that case we assume the whole display frame.
        int tmp = w;
            frame = Rect(w, h);
        w = h;
        }
        h = tmp;

        if (viewport.isEmpty()) {
            // viewport can be invalid if it has never been set, in that case
            // we assume the whole display size.
            // it's also invalid to have an empty viewport, so we handle that
            // case in the same way.
            viewport = Rect(w, h);
            if (R.getOrientation() & Transform::ROT_90) {
                // viewport is always specified in the logical orientation
                // of the display (ie: post-rotation).
                swap(viewport.right, viewport.bottom);
            }
        }

        float src_width  = viewport.width();
        float src_height = viewport.height();
        float dst_width  = frame.width();
        float dst_height = frame.height();
        if (src_width != src_height || dst_width != dst_height) {
            float sx = dst_width  / src_width;
            float sy = dst_height / src_height;
            S.set(sx, 0, 0, sy);
        }
        float src_x = viewport.left;
        float src_y = viewport.top;
        float dst_x = frame.left;
        float dst_y = frame.top;
        float tx = dst_x - src_x;
        float ty = dst_y - src_y;
        S.set(tx, ty);

        // rotate first, followed by scaling
        mGlobalTransform = S * R;
    }
    }
    mOrientation = orientation;
    dirtyRegion.set(bounds());
    return NO_ERROR;
}
}
+17 −6
Original line number Original line Diff line number Diff line
@@ -93,11 +93,16 @@ public:
    bool                    getSecureLayerVisible() const;
    bool                    getSecureLayerVisible() const;
    Region                  getDirtyRegion(bool repaintEverything) const;
    Region                  getDirtyRegion(bool repaintEverything) const;


    status_t                setOrientation(int orientation);
    void                    setLayerStack(uint32_t stack);
    void                    setLayerStack(uint32_t stack);
    void                    setOrientation(int orientation);
    void                    setViewport(const Rect& viewport);
    void                    setFrame(const Rect& frame);


    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&             getFrame() const { return mFrame; }

    uint32_t                getLayerStack() const { return mLayerStack; }
    uint32_t                getLayerStack() const { return mLayerStack; }
    int32_t                 getDisplayType() const { return mType; }
    int32_t                 getDisplayType() const { return mType; }
    int32_t                 getHwcDisplayId() const { return mHwcDisplayId; }
    int32_t                 getHwcDisplayId() const { return mHwcDisplayId; }
@@ -110,7 +115,8 @@ public:
    }
    }
    inline Rect bounds() const { return getBounds(); }
    inline Rect bounds() const { return getBounds(); }


    static void makeCurrent(const sp<const DisplayDevice>& hw, EGLContext ctx);
    static EGLBoolean makeCurrent(EGLDisplay dpy,
            const sp<const DisplayDevice>& hw, EGLContext ctx);


    /* ------------------------------------------------------------------------
    /* ------------------------------------------------------------------------
     * blank / unplank management
     * blank / unplank management
@@ -170,11 +176,16 @@ private:
    /*
    /*
     * Transaction state
     * Transaction state
     */
     */
    static status_t orientationToTransfrom(int orientation, int w, int h,
    static status_t orientationToTransfrom(int orientation,
            Transform* tr);
            int w, int h, Transform* tr);
    Transform mGlobalTransform;

    int mOrientation;
    void updateGeometryTransform();

    uint32_t mLayerStack;
    uint32_t mLayerStack;
    int mOrientation;
    Rect mViewport;
    Rect mFrame;
    Transform mGlobalTransform;
};
};


}; // namespace android
}; // namespace android
+22 −24
Original line number Original line Diff line number Diff line
@@ -297,8 +297,8 @@ EGLContext SurfaceFlinger::createGLContext(EGLDisplay display, EGLConfig config)
    return ctxt;
    return ctxt;
}
}


void SurfaceFlinger::initializeGL(EGLDisplay display, EGLSurface surface) {
void SurfaceFlinger::initializeGL(EGLDisplay display, const sp<DisplayDevice>& hw) {
    EGLBoolean result = eglMakeCurrent(display, surface, surface, mEGLContext);
    EGLBoolean result = DisplayDevice::makeCurrent(display, hw, mEGLContext);
    if (!result) {
    if (!result) {
        ALOGE("Couldn't create a working GLES context. check logs. exiting...");
        ALOGE("Couldn't create a working GLES context. check logs. exiting...");
        exit(0);
        exit(0);
@@ -314,10 +314,6 @@ void SurfaceFlinger::initializeGL(EGLDisplay display, EGLSurface surface) {
            eglQueryString(display, EGL_VERSION),
            eglQueryString(display, EGL_VERSION),
            eglQueryString(display, EGL_EXTENSIONS));
            eglQueryString(display, EGL_EXTENSIONS));


    EGLint w, h;
    eglQuerySurface(display, surface, EGL_WIDTH,  &w);
    eglQuerySurface(display, surface, EGL_HEIGHT, &h);

    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
    glGetIntegerv(GL_MAX_VIEWPORT_DIMS, mMaxViewportDims);
    glGetIntegerv(GL_MAX_VIEWPORT_DIMS, mMaxViewportDims);


@@ -344,12 +340,6 @@ void SurfaceFlinger::initializeGL(EGLDisplay display, EGLSurface surface) {
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0,
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0,
            GL_RGB, GL_UNSIGNED_SHORT_5_6_5, protTexData);
            GL_RGB, GL_UNSIGNED_SHORT_5_6_5, protTexData);


    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    // put the origin in the left-bottom corner
    glOrthof(0, w, 0, h, 0, 1); // l=0, r=w ; b=0, t=h

    // print some debugging info
    // print some debugging info
    EGLint r,g,b,a;
    EGLint r,g,b,a;
    eglGetConfigAttrib(display, mEGLConfig, EGL_RED_SIZE,   &r);
    eglGetConfigAttrib(display, mEGLConfig, EGL_RED_SIZE,   &r);
@@ -412,8 +402,7 @@ status_t SurfaceFlinger::readyToRun()
    mDisplays.add(mDefaultDisplays[DisplayDevice::DISPLAY_PRIMARY], hw);
    mDisplays.add(mDefaultDisplays[DisplayDevice::DISPLAY_PRIMARY], hw);


    //  initialize OpenGL ES
    //  initialize OpenGL ES
    EGLSurface surface = hw->getEGLSurface();
    initializeGL(mEGLDisplay, hw);
    initializeGL(mEGLDisplay, surface);


    // start the EventThread
    // start the EventThread
    mEventThread = new EventThread(this);
    mEventThread = new EventThread(this);
@@ -863,7 +852,7 @@ void SurfaceFlinger::postFramebuffer()
        // FIXME: EGL spec says:
        // FIXME: EGL spec says:
        //   "surface must be bound to the calling thread's current context,
        //   "surface must be bound to the calling thread's current context,
        //    for the current rendering API."
        //    for the current rendering API."
        DisplayDevice::makeCurrent(getDefaultDisplayDevice(), mEGLContext);
        DisplayDevice::makeCurrent(mEGLDisplay, getDefaultDisplayDevice(), mEGLContext);
        hwc.commit();
        hwc.commit();
    }
    }


@@ -983,11 +972,14 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
                        if (state.layerStack != draw[i].layerStack) {
                        if (state.layerStack != draw[i].layerStack) {
                            disp->setLayerStack(state.layerStack);
                            disp->setLayerStack(state.layerStack);
                        }
                        }
                        if (state.orientation != draw[i].orientation ||
                        if (state.orientation != draw[i].orientation) {
                                state.viewport != draw[i].viewport ||
                                state.frame != draw[i].frame) {
                            disp->setOrientation(state.orientation);
                            disp->setOrientation(state.orientation);
                            // TODO: take viewport and frame into account
                        }
                        if (state.viewport != draw[i].viewport) {
                            disp->setViewport(state.viewport);
                        }
                        if (state.frame != draw[i].frame) {
                            disp->setFrame(state.frame);
                        }
                        }
                    }
                    }
                }
                }
@@ -1006,7 +998,8 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
                                state.type, display, stc, 0, mEGLConfig);
                                state.type, display, stc, 0, mEGLConfig);
                        disp->setLayerStack(state.layerStack);
                        disp->setLayerStack(state.layerStack);
                        disp->setOrientation(state.orientation);
                        disp->setOrientation(state.orientation);
                        // TODO: take viewport and frame into account
                        disp->setViewport(state.viewport);
                        disp->setFrame(state.frame);
                        mDisplays.add(display, disp);
                        mDisplays.add(display, disp);
                    }
                    }
                }
                }
@@ -1280,7 +1273,7 @@ void SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const


    const bool hasGlesComposition = hwc.hasGlesComposition(id) || (cur==end);
    const bool hasGlesComposition = hwc.hasGlesComposition(id) || (cur==end);
    if (hasGlesComposition) {
    if (hasGlesComposition) {
        DisplayDevice::makeCurrent(hw, mEGLContext);
        DisplayDevice::makeCurrent(mEGLDisplay, hw, mEGLContext);


        // set the frame buffer
        // set the frame buffer
        glMatrixMode(GL_MODELVIEW);
        glMatrixMode(GL_MODELVIEW);
@@ -1977,15 +1970,18 @@ void SurfaceFlinger::dumpAllLocked(
        const sp<const DisplayDevice>& hw(mDisplays[dpy]);
        const sp<const DisplayDevice>& hw(mDisplays[dpy]);
        snprintf(buffer, SIZE,
        snprintf(buffer, SIZE,
                "+ DisplayDevice[%u]\n"
                "+ DisplayDevice[%u]\n"
                "   id=%x, layerStack=%u, (%4dx%4d), orient=%2d, tr=%08x, "
                "   id=%x, layerStack=%u, (%4dx%4d), orient=%2d (type=%08x), "
                "flips=%u, secure=%d, numLayers=%u\n",
                "flips=%u, secure=%d, numLayers=%u, v:[%d,%d,%d,%d], f:[%d,%d,%d,%d]\n",
                dpy,
                dpy,
                hw->getDisplayType(), hw->getLayerStack(),
                hw->getDisplayType(), hw->getLayerStack(),
                hw->getWidth(), hw->getHeight(),
                hw->getWidth(), hw->getHeight(),
                hw->getOrientation(), hw->getTransform().getType(),
                hw->getOrientation(), hw->getTransform().getType(),
                hw->getPageFlipCount(),
                hw->getPageFlipCount(),
                hw->getSecureLayerVisible(),
                hw->getSecureLayerVisible(),
                hw->getVisibleLayersSortedByZ().size());
                hw->getVisibleLayersSortedByZ().size(),
                hw->getViewport().left, hw->getViewport().top, hw->getViewport().right, hw->getViewport().bottom,
                hw->getFrame().left, hw->getFrame().top, hw->getFrame().right, hw->getFrame().bottom);

        result.append(buffer);
        result.append(buffer);
    }
    }


@@ -2488,6 +2484,8 @@ SurfaceFlinger::DisplayDeviceState::DisplayDeviceState()


SurfaceFlinger::DisplayDeviceState::DisplayDeviceState(DisplayDevice::DisplayType type)
SurfaceFlinger::DisplayDeviceState::DisplayDeviceState(DisplayDevice::DisplayType type)
    : type(type), layerStack(0), orientation(0) {
    : type(type), layerStack(0), orientation(0) {
    viewport.makeInvalid();
    frame.makeInvalid();
}
}


// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
+1 −1
Original line number Original line Diff line number Diff line
@@ -320,7 +320,7 @@ private:
        EGLint const* attrs, PixelFormat format, EGLConfig* outConfig);
        EGLint const* attrs, PixelFormat format, EGLConfig* outConfig);
    static EGLConfig selectEGLConfig(EGLDisplay disp, EGLint visualId);
    static EGLConfig selectEGLConfig(EGLDisplay disp, EGLint visualId);
    static EGLContext createGLContext(EGLDisplay disp, EGLConfig config);
    static EGLContext createGLContext(EGLDisplay disp, EGLConfig config);
    void initializeGL(EGLDisplay display, EGLSurface surface);
    void initializeGL(EGLDisplay display, const sp<DisplayDevice>& hw);
    uint32_t getMaxTextureSize() const;
    uint32_t getMaxTextureSize() const;
    uint32_t getMaxViewportDims() const;
    uint32_t getMaxViewportDims() const;