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

Commit 662d3134 authored by Jesse Hall's avatar Jesse Hall Committed by Gerrit Code Review
Browse files

Merge "Move EGLConfig selection to RenderEngine"

parents 7fea2361 05f8c703
Loading
Loading
Loading
Loading
+168 −3
Original line number Diff line number Diff line
@@ -29,7 +29,9 @@
namespace android {
// ---------------------------------------------------------------------------

RenderEngine* RenderEngine::create(EGLDisplay display, EGLConfig config) {
RenderEngine* RenderEngine::create(EGLDisplay display, int hwcFormat) {
    EGLConfig config = chooseEglConfig(display, hwcFormat);

    EGLint renderableType = 0;
    EGLint contextClientVersion = 0;

@@ -96,7 +98,7 @@ RenderEngine* RenderEngine::create(EGLDisplay display, EGLConfig config) {
        engine = new GLES20RenderEngine();
        break;
    }
    engine->setEGLContext(ctxt);
    engine->setEGLHandles(config, ctxt);

    ALOGI("OpenGL ES informations:");
    ALOGI("vendor    : %s", extensions.getVendor());
@@ -118,10 +120,15 @@ RenderEngine::RenderEngine() : mEGLContext(EGL_NO_CONTEXT) {
RenderEngine::~RenderEngine() {
}

void RenderEngine::setEGLContext(EGLContext ctxt) {
void RenderEngine::setEGLHandles(EGLConfig config, EGLContext ctxt) {
    mEGLConfig = config;
    mEGLContext = ctxt;
}

EGLContext RenderEngine::getEGLConfig() const {
    return mEGLConfig;
}

EGLContext RenderEngine::getEGLContext() const {
    return mEGLContext;
}
@@ -234,6 +241,164 @@ status_t RenderEngine::BindImageAsFramebuffer::getStatus() const {
    return mStatus == GL_FRAMEBUFFER_COMPLETE_OES ? NO_ERROR : BAD_VALUE;
}

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

static status_t selectConfigForAttribute(EGLDisplay dpy, EGLint const* attrs,
        EGLint attribute, EGLint wanted, 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);

    if (n) {
        if (attribute != EGL_NONE) {
            for (int i=0 ; i<n ; i++) {
                EGLint value = 0;
                eglGetConfigAttrib(dpy, configs[i], attribute, &value);
                if (wanted == value) {
                    *outConfig = configs[i];
                    delete [] configs;
                    return NO_ERROR;
                }
            }
        } else {
            // just pick the first one
            *outConfig = configs[0];
            delete [] configs;
            return NO_ERROR;
        }
    }
    delete [] configs;
    return NAME_NOT_FOUND;
}

class EGLAttributeVector {
    struct Attribute;
    class Adder;
    friend class Adder;
    KeyedVector<Attribute, EGLint> mList;
    struct Attribute {
        Attribute() {};
        Attribute(EGLint v) : v(v) { }
        EGLint v;
        bool operator < (const Attribute& other) const {
            // this places EGL_NONE at the end
            EGLint lhs(v);
            EGLint rhs(other.v);
            if (lhs == EGL_NONE) lhs = 0x7FFFFFFF;
            if (rhs == EGL_NONE) rhs = 0x7FFFFFFF;
            return lhs < rhs;
        }
    };
    class Adder {
        friend class EGLAttributeVector;
        EGLAttributeVector& v;
        EGLint attribute;
        Adder(EGLAttributeVector& v, EGLint attribute)
            : v(v), attribute(attribute) {
        }
    public:
        void operator = (EGLint value) {
            if (attribute != EGL_NONE) {
                v.mList.add(attribute, value);
            }
        }
        operator EGLint () const { return v.mList[attribute]; }
    };
public:
    EGLAttributeVector() {
        mList.add(EGL_NONE, EGL_NONE);
    }
    void remove(EGLint attribute) {
        if (attribute != EGL_NONE) {
            mList.removeItem(attribute);
        }
    }
    Adder operator [] (EGLint attribute) {
        return Adder(*this, attribute);
    }
    EGLint operator [] (EGLint attribute) const {
       return mList[attribute];
    }
    // cast-operator to (EGLint const*)
    operator EGLint const* () const { return &mList.keyAt(0).v; }
};


static status_t selectEGLConfig(EGLDisplay display, EGLint format,
    EGLint renderableType, EGLConfig* config) {
    // select our EGLConfig. It must support EGL_RECORDABLE_ANDROID if
    // it is to be used with WIFI displays
    status_t err;
    EGLint wantedAttribute;
    EGLint wantedAttributeValue;

    EGLAttributeVector attribs;
    if (renderableType) {
        attribs[EGL_RENDERABLE_TYPE]            = renderableType;
        attribs[EGL_RECORDABLE_ANDROID]         = EGL_TRUE;
        attribs[EGL_SURFACE_TYPE]               = EGL_WINDOW_BIT|EGL_PBUFFER_BIT;
        attribs[EGL_FRAMEBUFFER_TARGET_ANDROID] = EGL_TRUE;
        attribs[EGL_RED_SIZE]                   = 8;
        attribs[EGL_GREEN_SIZE]                 = 8;
        attribs[EGL_BLUE_SIZE]                  = 8;
        wantedAttribute                         = EGL_NONE;
        wantedAttributeValue                    = EGL_NONE;
    } else {
        // if no renderable type specified, fallback to a simplified query
        wantedAttribute                         = EGL_NATIVE_VISUAL_ID;
        wantedAttributeValue                    = format;
    }

    err = selectConfigForAttribute(display, attribs,
            wantedAttribute, wantedAttributeValue, config);
    if (err == NO_ERROR) {
        EGLint caveat;
        if (eglGetConfigAttrib(display, *config, EGL_CONFIG_CAVEAT, &caveat))
            ALOGW_IF(caveat == EGL_SLOW_CONFIG, "EGL_SLOW_CONFIG selected!");
    }

    return err;
}

EGLConfig RenderEngine::chooseEglConfig(EGLDisplay display, int format) {
    status_t err;
    EGLConfig config;

    // First try to get an ES2 config
    err = selectEGLConfig(display, format, EGL_OPENGL_ES2_BIT, &config);
    if (err != NO_ERROR) {
        // If ES2 fails, try ES1
        err = selectEGLConfig(display, format, EGL_OPENGL_ES_BIT, &config);
        if (err != NO_ERROR) {
            // still didn't work, probably because we're on the emulator...
            // try a simplified query
            ALOGW("no suitable EGLConfig found, trying a simpler query");
            err = selectEGLConfig(display, format, 0, &config);
            if (err != NO_ERROR) {
                // this EGL is too lame for android
                LOG_ALWAYS_FATAL("no suitable EGLConfig found, giving up");
            }
        }
    }

    // print some debugging info
    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);
    ALOGI("EGL information:");
    ALOGI("vendor    : %s", eglQueryString(display, EGL_VENDOR));
    ALOGI("version   : %s", eglQueryString(display, EGL_VERSION));
    ALOGI("extensions: %s", eglQueryString(display, EGL_EXTENSIONS));
    ALOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported");
    ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config);

    return config;
}

// ---------------------------------------------------------------------------
}; // namespace android
// ---------------------------------------------------------------------------
+6 −2
Original line number Diff line number Diff line
@@ -44,8 +44,9 @@ class RenderEngine {
    };
    static GlesVersion parseGlesVersion(const char* str);

    EGLConfig mEGLConfig;
    EGLContext mEGLContext;
    void setEGLContext(EGLContext ctxt);
    void setEGLHandles(EGLConfig config, EGLContext ctxt);

    virtual void bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName, uint32_t* fbName, uint32_t* status) = 0;
    virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName) = 0;
@@ -55,7 +56,9 @@ protected:
    virtual ~RenderEngine() = 0;

public:
    static RenderEngine* create(EGLDisplay display, EGLConfig config);
    static RenderEngine* create(EGLDisplay display, int hwcFormat);

    static EGLConfig chooseEglConfig(EGLDisplay display, int format);

    // dump the extension strings. always call the base class.
    virtual void dump(String8& result);
@@ -107,6 +110,7 @@ public:
    virtual size_t getMaxTextureSize() const = 0;
    virtual size_t getMaxViewportDims() const = 0;

    EGLConfig getEGLConfig() const;
    EGLContext getEGLContext() const;
};

+4 −166
Original line number Diff line number Diff line
@@ -318,128 +318,6 @@ void SurfaceFlinger::deleteTextureAsync(uint32_t texture) {
    postMessageAsync(new MessageDestroyGLTexture(getRenderEngine(), texture));
}

status_t SurfaceFlinger::selectConfigForAttribute(
        EGLDisplay dpy,
        EGLint const* attrs,
        EGLint attribute, EGLint wanted,
        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);

    if (n) {
        if (attribute != EGL_NONE) {
            for (int i=0 ; i<n ; i++) {
                EGLint value = 0;
                eglGetConfigAttrib(dpy, configs[i], attribute, &value);
                if (wanted == value) {
                    *outConfig = configs[i];
                    delete [] configs;
                    return NO_ERROR;
                }
            }
        } else {
            // just pick the first one
            *outConfig = configs[0];
            delete [] configs;
            return NO_ERROR;
        }
    }
    delete [] configs;
    return NAME_NOT_FOUND;
}

class EGLAttributeVector {
    struct Attribute;
    class Adder;
    friend class Adder;
    KeyedVector<Attribute, EGLint> mList;
    struct Attribute {
        Attribute() {};
        Attribute(EGLint v) : v(v) { }
        EGLint v;
        bool operator < (const Attribute& other) const {
            // this places EGL_NONE at the end
            EGLint lhs(v);
            EGLint rhs(other.v);
            if (lhs == EGL_NONE) lhs = 0x7FFFFFFF;
            if (rhs == EGL_NONE) rhs = 0x7FFFFFFF;
            return lhs < rhs;
        }
    };
    class Adder {
        friend class EGLAttributeVector;
        EGLAttributeVector& v;
        EGLint attribute;
        Adder(EGLAttributeVector& v, EGLint attribute)
            : v(v), attribute(attribute) {
        }
    public:
        void operator = (EGLint value) {
            if (attribute != EGL_NONE) {
                v.mList.add(attribute, value);
            }
        }
        operator EGLint () const { return v.mList[attribute]; }
    };
public:
    EGLAttributeVector() {
        mList.add(EGL_NONE, EGL_NONE);
    }
    void remove(EGLint attribute) {
        if (attribute != EGL_NONE) {
            mList.removeItem(attribute);
        }
    }
    Adder operator [] (EGLint attribute) {
        return Adder(*this, attribute);
    }
    EGLint operator [] (EGLint attribute) const {
       return mList[attribute];
    }
    // cast-operator to (EGLint const*)
    operator EGLint const* () const { return &mList.keyAt(0).v; }
};

status_t SurfaceFlinger::selectEGLConfig(EGLDisplay display, EGLint nativeVisualId,
    EGLint renderableType, EGLConfig* config) {
    // select our EGLConfig. It must support EGL_RECORDABLE_ANDROID if
    // it is to be used with WIFI displays
    status_t err;
    EGLint wantedAttribute;
    EGLint wantedAttributeValue;

    EGLAttributeVector attribs;
    if (renderableType) {
        attribs[EGL_RENDERABLE_TYPE]            = renderableType;
        attribs[EGL_RECORDABLE_ANDROID]         = EGL_TRUE;
        attribs[EGL_SURFACE_TYPE]               = EGL_WINDOW_BIT|EGL_PBUFFER_BIT;
        attribs[EGL_FRAMEBUFFER_TARGET_ANDROID] = EGL_TRUE;
        attribs[EGL_RED_SIZE]                   = 8;
        attribs[EGL_GREEN_SIZE]                 = 8;
        attribs[EGL_BLUE_SIZE]                  = 8;
        wantedAttribute                         = EGL_NONE;
        wantedAttributeValue                    = EGL_NONE;

    } else {
        // if no renderable type specified, fallback to a simplified query
        wantedAttribute                         = EGL_NATIVE_VISUAL_ID;
        wantedAttributeValue                    = nativeVisualId;
    }

    err = selectConfigForAttribute(display, attribs, wantedAttribute,
        wantedAttributeValue, config);
    if (err == NO_ERROR) {
        EGLint caveat;
        if (eglGetConfigAttrib(display, *config, EGL_CONFIG_CAVEAT, &caveat))
            ALOGW_IF(caveat == EGL_SLOW_CONFIG, "EGL_SLOW_CONFIG selected!");
    }
    return err;
}

class DispSyncSource : public VSyncSource, private DispSync::Callback {
public:
    DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync) :
@@ -521,51 +399,12 @@ void SurfaceFlinger::init() {
    mHwc = new HWComposer(this,
            *static_cast<HWComposer::EventHandler *>(this));

    // First try to get an ES2 config
    err = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(), EGL_OPENGL_ES2_BIT,
            &mEGLConfig);

    if (err != NO_ERROR) {
        // If ES2 fails, try ES1
        err = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(),
                EGL_OPENGL_ES_BIT, &mEGLConfig);
    }

    if (err != NO_ERROR) {
        // still didn't work, probably because we're on the emulator...
        // try a simplified query
        ALOGW("no suitable EGLConfig found, trying a simpler query");
        err = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(), 0, &mEGLConfig);
    }

    if (err != NO_ERROR) {
        // this EGL is too lame for android
        LOG_ALWAYS_FATAL("no suitable EGLConfig found, giving up");
    }

    // print some debugging info
    EGLint r,g,b,a;
    eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_RED_SIZE,   &r);
    eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_GREEN_SIZE, &g);
    eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_BLUE_SIZE,  &b);
    eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_ALPHA_SIZE, &a);
    ALOGI("EGL informations:");
    ALOGI("vendor    : %s", eglQueryString(mEGLDisplay, EGL_VENDOR));
    ALOGI("version   : %s", eglQueryString(mEGLDisplay, EGL_VERSION));
    ALOGI("extensions: %s", eglQueryString(mEGLDisplay, EGL_EXTENSIONS));
    ALOGI("Client API: %s", eglQueryString(mEGLDisplay, EGL_CLIENT_APIS)?:"Not Supported");
    ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, mEGLConfig);

    // get a RenderEngine for the given display / config (can't fail)
    mRenderEngine = RenderEngine::create(mEGLDisplay, mEGLConfig);
    mRenderEngine = RenderEngine::create(mEGLDisplay, mHwc->getVisualID());

    // retrieve the EGL context that was selected/created
    mEGLContext = mRenderEngine->getEGLContext();

    // figure out which format we got
    eglGetConfigAttrib(mEGLDisplay, mEGLConfig,
            EGL_NATIVE_VISUAL_ID, &mEGLNativeVisualId);

    LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,
            "couldn't create EGLContext");

@@ -584,7 +423,7 @@ void SurfaceFlinger::init() {
            sp<DisplayDevice> hw = new DisplayDevice(this,
                    type, allocateHwcDisplayId(type), isSecure, token,
                    fbs, bq,
                    mEGLConfig);
                    mRenderEngine->getEGLConfig());
            if (i > DisplayDevice::DISPLAY_PRIMARY) {
                // FIXME: currently we don't get blank/unblank requests
                // for displays other than the main display, so we always
@@ -1347,7 +1186,8 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
                    if (dispSurface != NULL) {
                        sp<DisplayDevice> hw = new DisplayDevice(this,
                                state.type, hwcDisplayId, state.isSecure,
                                display, dispSurface, producer, mEGLConfig);
                                display, dispSurface, producer,
                                mRenderEngine->getEGLConfig());
                        hw->setLayerStack(state.layerStack);
                        hw->setProjection(state.orientation,
                                state.viewport, state.frame);
@@ -2544,7 +2384,6 @@ void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index,
            "  refresh-rate              : %f fps\n"
            "  x-dpi                     : %f\n"
            "  y-dpi                     : %f\n"
            "  EGL_NATIVE_VISUAL_ID      : %d\n"
            "  gpu_to_cpu_unsupported    : %d\n"
            ,
            mLastSwapBufferTime/1000.0,
@@ -2553,7 +2392,6 @@ void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index,
            1e9 / hwc.getRefreshPeriod(HWC_DISPLAY_PRIMARY),
            hwc.getDpiX(HWC_DISPLAY_PRIMARY),
            hwc.getDpiY(HWC_DISPLAY_PRIMARY),
            mEGLNativeVisualId,
            !mGpuToCpuSupported);

    result.appendFormat("  eglSwapBuffers time: %f us\n",
+0 −6
Original line number Diff line number Diff line
@@ -317,10 +317,6 @@ private:
    /* ------------------------------------------------------------------------
     * EGL
     */
    static status_t selectConfigForAttribute(EGLDisplay dpy,
        EGLint const* attrs, EGLint attribute, EGLint value, EGLConfig* outConfig);
    static status_t selectEGLConfig(EGLDisplay disp, EGLint visualId,
        EGLint renderableType, EGLConfig* config);
    size_t getMaxTextureSize() const;
    size_t getMaxViewportDims() const;

@@ -431,9 +427,7 @@ private:
    sp<EventThread> mSFEventThread;
    sp<EventControlThread> mEventControlThread;
    EGLContext mEGLContext;
    EGLConfig mEGLConfig;
    EGLDisplay mEGLDisplay;
    EGLint mEGLNativeVisualId;
    sp<IBinder> mBuiltinDisplays[DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES];

    // Can only accessed from the main thread, these members