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

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

factor EGL/GL and surface creation out of DisplayHardware

Change-Id: Icd85a6a4caad06f056578008af3e21666fa8b1f4
parent 3b1d2b6b
Loading
Loading
Loading
Loading
+97 −216
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@
#include <EGL/eglext.h>

#include <hardware/gralloc.h>
#include <private/gui/SharedBufferStack.h>

#include "DisplayHardware/FramebufferSurface.h"
#include "DisplayHardware/DisplayHardwareBase.h"
@@ -40,8 +41,9 @@
#include "GLExtensions.h"
#include "SurfaceFlinger.h"

// ----------------------------------------------------------------------------
using namespace android;

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

static __attribute__((noinline))
void checkGLErrors()
@@ -88,6 +90,8 @@ void checkEGLErrors(const char* token)
    }
}

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

/*
 * Initialize the display to the specified values.
 *
@@ -95,79 +99,78 @@ void checkEGLErrors(const char* token)

DisplayHardware::DisplayHardware(
        const sp<SurfaceFlinger>& flinger,
        uint32_t dpy)
    : DisplayHardwareBase(flinger, dpy),
      mFlinger(flinger), mFlags(0), mHwc(0), mSecureLayerVisible(false)
        int display,
        const sp<SurfaceTextureClient>& surface,
        EGLConfig config)
    : DisplayHardwareBase(flinger, display),
      mFlinger(flinger),
      mDisplayId(display),
      mHwc(0),
      mNativeWindow(surface),
      mFlags(0),
      mSecureLayerVisible(false)
{
    init(dpy);
    init(config);
}

DisplayHardware::~DisplayHardware()
{
    fini();
DisplayHardware::~DisplayHardware() {
}

float DisplayHardware::getDpiX() const          { return mDpiX; }
float DisplayHardware::getDpiY() const          { return mDpiY; }
float DisplayHardware::getDensity() const       { return mDensity; }
float DisplayHardware::getRefreshRate() const   { return mRefreshRate; }
int DisplayHardware::getWidth() const           { return mDisplayWidth; }
int DisplayHardware::getHeight() const          { return mDisplayHeight; }
PixelFormat DisplayHardware::getFormat() const  { return mFormat; }
uint32_t DisplayHardware::getMaxTextureSize() const { return mMaxTextureSize; }
float DisplayHardware::getDpiX() const {
    return mDpiX;
}

uint32_t DisplayHardware::getMaxViewportDims() const {
    return mMaxViewportDims[0] < mMaxViewportDims[1] ?
            mMaxViewportDims[0] : mMaxViewportDims[1];
float DisplayHardware::getDpiY() const {
    return mDpiY;
}

static status_t selectConfigForPixelFormat(
        EGLDisplay dpy,
        EGLint const* attrs,
        PixelFormat format,
        EGLConfig* outConfig)
{
    EGLConfig config = NULL;
    EGLint numConfigs = -1, n=0;
    eglGetConfigs(dpy, NULL, 0, &numConfigs);
    EGLConfig* const configs = new EGLConfig[numConfigs];
    eglChooseConfig(dpy, attrs, configs, numConfigs, &n);
    for (int i=0 ; i<n ; i++) {
        EGLint nativeVisualId = 0;
        eglGetConfigAttrib(dpy, configs[i], EGL_NATIVE_VISUAL_ID, &nativeVisualId);
        if (nativeVisualId>0 && format == nativeVisualId) {
            *outConfig = configs[i];
            delete [] configs;
            return NO_ERROR;
float DisplayHardware::getDensity() const {
    return mDensity;
}

float DisplayHardware::getRefreshRate() const {
    return mRefreshRate;
}

int DisplayHardware::getWidth() const {
    return mDisplayWidth;
}
    delete [] configs;
    return NAME_NOT_FOUND;

int DisplayHardware::getHeight() const {
    return mDisplayHeight;
}

PixelFormat DisplayHardware::getFormat() const {
    return mFormat;
}

EGLSurface DisplayHardware::getEGLSurface() const {
    return mSurface;
}

void DisplayHardware::init(uint32_t dpy)
void DisplayHardware::init(EGLConfig config)
{
    mNativeWindow = new FramebufferSurface();
    framebuffer_device_t const * fbDev = mNativeWindow->getDevice();
    if (!fbDev) {
        ALOGE("Display subsystem failed to initialize. check logs. exiting...");
        exit(0);
    ANativeWindow* const window = mNativeWindow.get();

    int concreteType;
    window->query(window, NATIVE_WINDOW_CONCRETE_TYPE, &concreteType);
    if (concreteType == NATIVE_WINDOW_FRAMEBUFFER) {
        mFramebufferSurface = static_cast<FramebufferSurface *>(mNativeWindow.get());
    }

    int format;
    ANativeWindow const * const window = mNativeWindow.get();
    window->query(window, NATIVE_WINDOW_FORMAT, &format);
    mDpiX = mNativeWindow->xdpi;
    mDpiY = mNativeWindow->ydpi;
    mRefreshRate = fbDev->fps;

    if (mDpiX == 0 || mDpiY == 0) {
        ALOGE("invalid screen resolution from fb HAL (xdpi=%f, ydpi=%f), "
               "defaulting to 160 dpi", mDpiX, mDpiY);
        mDpiX = mDpiY = 160;
    mDpiX = window->xdpi;
    mDpiY = window->ydpi;
    if (mFramebufferSurface != NULL) {
        mRefreshRate = mFramebufferSurface->getRefreshRate();
    } else {
        mRefreshRate = 60;
    }
    mRefreshPeriod = nsecs_t(1e9 / mRefreshRate);


    // TODO: Not sure if display density should handled by SF any longer
    class Density {
        static int getDensityFromProperty(char const* propName) {
            char property[PROPERTY_VALUE_MAX];
@@ -183,173 +186,52 @@ void DisplayHardware::init(uint32_t dpy)
        static int getBuildDensity()  {
            return getDensityFromProperty("ro.sf.lcd_density"); }
    };


    // The density of the device is provided by a build property
    mDensity = Density::getBuildDensity() / 160.0f;

    if (mDensity == 0) {
        // the build doesn't provide a density -- this is wrong!
        // use xdpi instead
        ALOGE("ro.sf.lcd_density must be defined as a build property");
        mDensity = mDpiX / 160.0f;
    }

    if (Density::getEmuDensity()) {
        // if "qemu.sf.lcd_density" is specified, it overrides everything
        mDpiX = mDpiY = mDensity = Density::getEmuDensity();
        mDensity /= 160.0f;
    }



    /* FIXME: this is a temporary HACK until we are able to report the refresh rate
     * properly from the HAL. The WindowManagerService now relies on this value.
    /*
     * Create our display's surface
     */
#ifndef REFRESH_RATE
    mRefreshRate = fbDev->fps;
#else
    mRefreshRate = REFRESH_RATE;
#warning "refresh rate set via makefile to REFRESH_RATE"
#endif

    mRefreshPeriod = nsecs_t(1e9 / mRefreshRate);

    EGLint w, h, dummy;
    EGLint numConfigs=0;
    EGLSurface surface;
    EGLContext context;
    EGLBoolean result;
    status_t err;

    // initialize EGL
    EGLint attribs[] = {
            EGL_SURFACE_TYPE,           EGL_WINDOW_BIT,
            EGL_RECORDABLE_ANDROID,     EGL_TRUE,
            EGL_NONE
    };

    // TODO: all the extensions below should be queried through
    // eglGetProcAddress().

    EGLint w, h;
    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    eglInitialize(display, NULL, NULL);
    eglGetConfigs(display, NULL, 0, &numConfigs);

    EGLConfig config = NULL;
    err = selectConfigForPixelFormat(display, attribs, format, &config);
    if (err) {
        // maybe we failed because of EGL_RECORDABLE_ANDROID
        ALOGW("couldn't find an EGLConfig with EGL_RECORDABLE_ANDROID");
        attribs[2] = EGL_NONE;
        err = selectConfigForPixelFormat(display, attribs, format, &config);
    }

    ALOGE_IF(err, "couldn't find an EGLConfig matching the screen format");
    
    EGLint r,g,b,a;
    eglGetConfigAttrib(display, config, EGL_RED_SIZE,   &r);
    eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &g);
    eglGetConfigAttrib(display, config, EGL_BLUE_SIZE,  &b);
    eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &a);

    if (mNativeWindow->isUpdateOnDemand()) {
        mFlags |= PARTIAL_UPDATES;
    }
    
    if (eglGetConfigAttrib(display, config, EGL_CONFIG_CAVEAT, &dummy) == EGL_TRUE) {
        if (dummy == EGL_SLOW_CONFIG)
            mFlags |= SLOW_CONFIG;
    }

    /*
     * Create our main surface
     */

    surface = eglCreateWindowSurface(display, config, mNativeWindow.get(), NULL);
    surface = eglCreateWindowSurface(display, config, window, NULL);
    eglQuerySurface(display, surface, EGL_WIDTH,  &mDisplayWidth);
    eglQuerySurface(display, surface, EGL_HEIGHT, &mDisplayHeight);

    if (mFlags & PARTIAL_UPDATES) {
    if (mFramebufferSurface != NULL) {
        if (mFramebufferSurface->isUpdateOnDemand()) {
            mFlags |= PARTIAL_UPDATES;
            // if we have partial updates, we definitely don't need to
            // preserve the backbuffer, which may be costly.
            eglSurfaceAttrib(display, surface,
                    EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED);
        }

    /*
     * Create our OpenGL ES context
     */
    
    EGLint contextAttributes[] = {
#ifdef EGL_IMG_context_priority
#ifdef HAS_CONTEXT_PRIORITY
#warning "using EGL_IMG_context_priority"
        EGL_CONTEXT_PRIORITY_LEVEL_IMG, EGL_CONTEXT_PRIORITY_HIGH_IMG,
#endif
#endif
        EGL_NONE, EGL_NONE
    };
    context = eglCreateContext(display, config, NULL, contextAttributes);
    }

    mDisplay = display;
    mConfig  = config;
    mSurface = surface;
    mContext = context;
    mFormat  = fbDev->format;
    mFormat  = format;
    mPageFlipCount = 0;

    /*
     * Gather OpenGL ES extensions
     */

    result = eglMakeCurrent(display, surface, surface, context);
    if (!result) {
        ALOGE("Couldn't create a working GLES context. check logs. exiting...");
        exit(0);
    }

    GLExtensions& extensions(GLExtensions::getInstance());
    extensions.initWithGLStrings(
            glGetString(GL_VENDOR),
            glGetString(GL_RENDERER),
            glGetString(GL_VERSION),
            glGetString(GL_EXTENSIONS),
            eglQueryString(display, EGL_VENDOR),
            eglQueryString(display, EGL_VERSION),
            eglQueryString(display, EGL_EXTENSIONS));

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

    ALOGI("EGL informations:");
    ALOGI("# of configs : %d", numConfigs);
    ALOGI("vendor    : %s", extensions.getEglVendor());
    ALOGI("version   : %s", extensions.getEglVersion());
    ALOGI("extensions: %s", extensions.getEglExtension());
    ALOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported");
    ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config);

    ALOGI("OpenGL informations:");
    ALOGI("vendor    : %s", extensions.getVendor());
    ALOGI("renderer  : %s", extensions.getRenderer());
    ALOGI("version   : %s", extensions.getVersion());
    ALOGI("extensions: %s", extensions.getExtension());
    ALOGI("GL_MAX_TEXTURE_SIZE = %d", mMaxTextureSize);
    ALOGI("GL_MAX_VIEWPORT_DIMS = %d x %d", mMaxViewportDims[0], mMaxViewportDims[1]);
    ALOGI("flags = %08x", mFlags);

    // Unbind the context from this thread
    eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);


    // initialize the H/W composer
    mHwc = new HWComposer(mFlinger, *this, mRefreshPeriod);
    if (mHwc->initCheck() == NO_ERROR) {
        mHwc->setFrameBuffer(mDisplay, mSurface);
    }


    // initialize the display orientation transform.
    // it's a constant that should come from the display driver.
    int displayOrientation = ISurfaceComposer::eOrientationDefault;
@@ -378,6 +260,20 @@ void DisplayHardware::init(uint32_t dpy)
        mLogicalDisplayHeight = h;
    }
    DisplayHardware::setOrientation(ISurfaceComposer::eOrientationDefault);

    // initialize the shared control block
    surface_flinger_cblk_t* const scblk = mFlinger->getControlBlock();
    scblk->connected |= 1 << mDisplayId;
    display_cblk_t* dcblk = &scblk->displays[mDisplayId];
    memset(dcblk, 0, sizeof(display_cblk_t));
    dcblk->w = w; // XXX: plane.getWidth();
    dcblk->h = h; // XXX: plane.getHeight();
    dcblk->format = format;
    dcblk->orientation = ISurfaceComposer::eOrientationDefault;
    dcblk->xdpi = mDpiX;
    dcblk->ydpi = mDpiY;
    dcblk->fps = mRefreshRate;
    dcblk->density = mDensity;
}

void DisplayHardware::setVSyncHandler(const sp<VSyncHandler>& handler) {
@@ -411,19 +307,6 @@ HWComposer& DisplayHardware::getHwComposer() const {
    return *mHwc;
}

/*
 * Clean up.  Throw out our local state.
 *
 * (It's entirely possible we'll never get here, since this is meant
 * for real hardware, which doesn't restart.)
 */

void DisplayHardware::fini()
{
    eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
    eglTerminate(mDisplay);
}

void DisplayHardware::releaseScreen() const
{
    DisplayHardwareBase::releaseScreen();
@@ -458,7 +341,10 @@ nsecs_t DisplayHardware::getRefreshPeriod() const {
}

status_t DisplayHardware::compositionComplete() const {
    return mNativeWindow->compositionComplete();
    if (mFramebufferSurface == NULL) {
        return NO_ERROR;
    }
    return mFramebufferSurface->compositionComplete();
}

void DisplayHardware::flip(const Region& dirty) const
@@ -478,7 +364,9 @@ void DisplayHardware::flip(const Region& dirty) const
#endif
    
    if (mFlags & PARTIAL_UPDATES) {
        mNativeWindow->setUpdateRectangle(dirty.getBounds());
        if (mFramebufferSurface != NULL) {
            mFramebufferSurface->setUpdateRectangle(dirty.getBounds());
        }
    }
    
    mPageFlipCount++;
@@ -489,10 +377,6 @@ void DisplayHardware::flip(const Region& dirty) const
        eglSwapBuffers(dpy, surface);
    }
    checkEGLErrors("eglSwapBuffers");

    // for debugging
    //glClearColor(1,0,0,0);
    //glClear(GL_COLOR_BUFFER_BIT);
}

uint32_t DisplayHardware::getFlags() const
@@ -500,14 +384,11 @@ uint32_t DisplayHardware::getFlags() const
    return mFlags;
}

void DisplayHardware::makeCurrent() const
{
    eglMakeCurrent(mDisplay, mSurface, mSurface, mContext);
}

void DisplayHardware::dump(String8& res) const
{
    mNativeWindow->dump(res);
    if (mFramebufferSurface != NULL) {
        mFramebufferSurface->dump(res);
    }
}

// ----------------------------------------------------------------------------
+26 −22
Original line number Diff line number Diff line
@@ -27,7 +27,6 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>

#include "GLExtensions.h"
#include "Transform.h"

#include "DisplayHardware/DisplayHardwareBase.h"
@@ -37,6 +36,7 @@
namespace android {

class FramebufferSurface;
class SurfaceTextureClient;

class DisplayHardware :
    public DisplayHardwareBase,
@@ -52,15 +52,15 @@ public:
    };

    enum {
        COPY_BITS_EXTENSION         = 0x00000008,
        PARTIAL_UPDATES             = 0x00020000,   // video driver feature
        SLOW_CONFIG                 = 0x00040000,   // software
        SWAP_RECTANGLE              = 0x00080000,
    };

    DisplayHardware(
            const sp<SurfaceFlinger>& flinger,
            uint32_t displayIndex);
            int dpy,
            const sp<SurfaceTextureClient>& surface,
            EGLConfig config);

    virtual ~DisplayHardware();

@@ -79,12 +79,10 @@ public:
    int         getHeight() const;
    PixelFormat getFormat() const;
    uint32_t    getFlags() const;
    uint32_t    getMaxTextureSize() const;
    uint32_t    getMaxViewportDims() const;
    nsecs_t     getRefreshPeriod() const;
    nsecs_t     getRefreshTimestamp() const;
    void        makeCurrent() const;

    EGLSurface  getEGLSurface() const;

    void                    setVisibleLayersSortedByZ(const Vector< sp<LayerBase> >& layers);
    Vector< sp<LayerBase> > getVisibleLayersSortedByZ() const;
@@ -107,7 +105,6 @@ public:

    uint32_t getPageFlipCount() const;
    EGLDisplay getEGLDisplay() const { return mDisplay; }
    EGLConfig getEGLConfig() const { return mConfig; }

    void dump(String8& res) const;

@@ -122,15 +119,26 @@ public:
    inline Rect bounds() const { return getBounds(); }

private:
    void init(EGLConfig config);

    virtual void onVSyncReceived(int dpy, nsecs_t timestamp);
    void init(uint32_t displayIndex);
    void fini();

    /*
     *  Constants, set during initialization
     */
    sp<SurfaceFlinger> mFlinger;
    int mDisplayId;
    HWComposer* mHwc;
    PowerHAL mPowerHAL;
    // ANativeWindow this display is rendering into
    sp<SurfaceTextureClient> mNativeWindow;
    // set if mNativeWindow is a FramebufferSurface
    sp<FramebufferSurface> mFramebufferSurface;


    EGLDisplay      mDisplay;
    EGLSurface      mSurface;
    EGLContext      mContext;
    EGLConfig       mConfig;
    float           mDpiX;
    float           mDpiY;
    float           mRefreshRate;
@@ -140,18 +148,15 @@ private:
    PixelFormat     mFormat;
    uint32_t        mFlags;
    mutable uint32_t mPageFlipCount;
    GLint           mMaxViewportDims[2];
    GLint           mMaxTextureSize;

    nsecs_t         mRefreshPeriod;
    mutable nsecs_t mLastHwVSync;

    // constant once set
    HWComposer*     mHwc;
    PowerHAL        mPowerHAL;

    // Can only accessed from the main thread, these members
    // don't need synchronization
    /*
     * Can only accessed from the main thread, these members
     * don't need synchronization.
     */
    // list of visible layers on that display
    Vector< sp<LayerBase> > mVisibleLayersSortedByZ;
    // Whether we have a visible secure layer on this display
@@ -169,13 +174,12 @@ private:
    int                     mUserDisplayWidth;
    int                     mUserDisplayHeight;


    mutable Mutex   mLock;

    // protected by mLock
    /*
     *  protected by mLock
     */
    wp<VSyncHandler>    mVSyncHandler;

    sp<FramebufferSurface> mNativeWindow;
};

}; // namespace android
+33 −2
Original line number Diff line number Diff line
@@ -38,6 +38,15 @@
namespace android {
// ----------------------------------------------------------------------------

sp<FramebufferSurface> FramebufferSurface::create() {
    sp<FramebufferSurface> result = new FramebufferSurface();
    if (result->fbDev == NULL) {
        result = NULL;
    }
    return result;
}

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

/*
 * This implements the (main) framebuffer management. This class is used
@@ -64,10 +73,19 @@ FramebufferSurface::FramebufferSurface()
        mUpdateOnDemand = (fbDev->setUpdateRect != 0);

        const_cast<uint32_t&>(ANativeWindow::flags) = fbDev->flags;
        const_cast<float&>(ANativeWindow::xdpi) = fbDev->xdpi;
        const_cast<float&>(ANativeWindow::ydpi) = fbDev->ydpi;
        const_cast<int&>(ANativeWindow::minSwapInterval) =  fbDev->minSwapInterval;
        const_cast<int&>(ANativeWindow::maxSwapInterval) =  fbDev->maxSwapInterval;

        if (fbDev->xdpi == 0 || fbDev->ydpi == 0) {
            ALOGE("invalid screen resolution from fb HAL (xdpi=%f, ydpi=%f), "
                   "defaulting to 160 dpi", fbDev->xdpi, fbDev->ydpi);
            const_cast<float&>(ANativeWindow::xdpi) = 160;
            const_cast<float&>(ANativeWindow::ydpi) = 160;
        } else {
            const_cast<float&>(ANativeWindow::xdpi) = fbDev->xdpi;
            const_cast<float&>(ANativeWindow::ydpi) = fbDev->ydpi;
        }

    } else {
        ALOGE("Couldn't get gralloc module");
    }
@@ -139,6 +157,19 @@ FramebufferSurface::~FramebufferSurface() {
    }
}

float FramebufferSurface::getRefreshRate() const {
    /* FIXME: REFRESH_RATE is a temporary HACK until we are able to report the
     * refresh rate properly from the HAL. The WindowManagerService now relies
     * on this value.
     */
#ifndef REFRESH_RATE
    return fbDev->fps;
#else
    return REFRESH_RATE;
#warning "refresh rate set via makefile to REFRESH_RATE"
#endif
}

status_t FramebufferSurface::setUpdateRectangle(const Rect& r)
{
    if (!mUpdateOnDemand) {
+7 −3
Original line number Diff line number Diff line
@@ -37,11 +37,11 @@ class String8;

class FramebufferSurface : public SurfaceTextureClient {
public:
    FramebufferSurface();

    virtual void onFirstRef();
    static sp<FramebufferSurface> create();

    framebuffer_device_t const * getDevice() const { return fbDev; }
    // TODO: this should be coming from HWC
    float getRefreshRate() const;

    bool isUpdateOnDemand() const { return mUpdateOnDemand; }
    status_t setUpdateRectangle(const Rect& updateRect);
@@ -49,7 +49,11 @@ public:

    void dump(String8& result);

protected:
    virtual void onFirstRef();

private:
    FramebufferSurface();
    virtual ~FramebufferSurface(); // this class cannot be overloaded
    virtual int query(int what, int* value) const;

+1 −4
Original line number Diff line number Diff line
@@ -182,11 +182,8 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h,
        return err;
    }

    // the display's pixel format
    // XXX: we shouldn't rely on the DisplayHardware to do this
    const DisplayHardware& hw(mFlinger->getDefaultDisplayHardware());
    uint32_t const maxSurfaceDims = min(
            hw.getMaxTextureSize(), hw.getMaxViewportDims());
            mFlinger->getMaxTextureSize(), mFlinger->getMaxViewportDims());

    // never allow a surface larger than what our underlying GL implementation
    // can handle.
Loading