Merge "Move EGLConfig selection to RenderEngine"

This commit is contained in:
Jesse Hall 2014-01-03 18:24:30 +00:00 committed by Gerrit Code Review
commit 662d3134cb
4 changed files with 178 additions and 177 deletions

View File

@ -29,7 +29,9 @@
namespace android { 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 renderableType = 0;
EGLint contextClientVersion = 0; EGLint contextClientVersion = 0;
@ -96,7 +98,7 @@ RenderEngine* RenderEngine::create(EGLDisplay display, EGLConfig config) {
engine = new GLES20RenderEngine(); engine = new GLES20RenderEngine();
break; break;
} }
engine->setEGLContext(ctxt); engine->setEGLHandles(config, ctxt);
ALOGI("OpenGL ES informations:"); ALOGI("OpenGL ES informations:");
ALOGI("vendor : %s", extensions.getVendor()); ALOGI("vendor : %s", extensions.getVendor());
@ -118,10 +120,15 @@ RenderEngine::RenderEngine() : mEGLContext(EGL_NO_CONTEXT) {
RenderEngine::~RenderEngine() { RenderEngine::~RenderEngine() {
} }
void RenderEngine::setEGLContext(EGLContext ctxt) { void RenderEngine::setEGLHandles(EGLConfig config, EGLContext ctxt) {
mEGLConfig = config;
mEGLContext = ctxt; mEGLContext = ctxt;
} }
EGLContext RenderEngine::getEGLConfig() const {
return mEGLConfig;
}
EGLContext RenderEngine::getEGLContext() const { EGLContext RenderEngine::getEGLContext() const {
return mEGLContext; return mEGLContext;
} }
@ -234,6 +241,164 @@ status_t RenderEngine::BindImageAsFramebuffer::getStatus() const {
return mStatus == GL_FRAMEBUFFER_COMPLETE_OES ? NO_ERROR : BAD_VALUE; 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 }; // namespace android
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------

View File

@ -44,8 +44,9 @@ class RenderEngine {
}; };
static GlesVersion parseGlesVersion(const char* str); static GlesVersion parseGlesVersion(const char* str);
EGLConfig mEGLConfig;
EGLContext mEGLContext; 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 bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName, uint32_t* fbName, uint32_t* status) = 0;
virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName) = 0; virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName) = 0;
@ -55,7 +56,9 @@ protected:
virtual ~RenderEngine() = 0; virtual ~RenderEngine() = 0;
public: 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. // dump the extension strings. always call the base class.
virtual void dump(String8& result); virtual void dump(String8& result);
@ -107,6 +110,7 @@ public:
virtual size_t getMaxTextureSize() const = 0; virtual size_t getMaxTextureSize() const = 0;
virtual size_t getMaxViewportDims() const = 0; virtual size_t getMaxViewportDims() const = 0;
EGLConfig getEGLConfig() const;
EGLContext getEGLContext() const; EGLContext getEGLContext() const;
}; };

View File

@ -318,128 +318,6 @@ void SurfaceFlinger::deleteTextureAsync(uint32_t texture) {
postMessageAsync(new MessageDestroyGLTexture(getRenderEngine(), 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 { class DispSyncSource : public VSyncSource, private DispSync::Callback {
public: public:
DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync) : DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync) :
@ -521,51 +399,12 @@ void SurfaceFlinger::init() {
mHwc = new HWComposer(this, mHwc = new HWComposer(this,
*static_cast<HWComposer::EventHandler *>(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) // 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 // retrieve the EGL context that was selected/created
mEGLContext = mRenderEngine->getEGLContext(); 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, LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,
"couldn't create EGLContext"); "couldn't create EGLContext");
@ -584,7 +423,7 @@ void SurfaceFlinger::init() {
sp<DisplayDevice> hw = new DisplayDevice(this, sp<DisplayDevice> hw = new DisplayDevice(this,
type, allocateHwcDisplayId(type), isSecure, token, type, allocateHwcDisplayId(type), isSecure, token,
fbs, bq, fbs, bq,
mEGLConfig); mRenderEngine->getEGLConfig());
if (i > DisplayDevice::DISPLAY_PRIMARY) { if (i > DisplayDevice::DISPLAY_PRIMARY) {
// FIXME: currently we don't get blank/unblank requests // FIXME: currently we don't get blank/unblank requests
// for displays other than the main display, so we always // for displays other than the main display, so we always
@ -1347,7 +1186,8 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
if (dispSurface != NULL) { if (dispSurface != NULL) {
sp<DisplayDevice> hw = new DisplayDevice(this, sp<DisplayDevice> hw = new DisplayDevice(this,
state.type, hwcDisplayId, state.isSecure, state.type, hwcDisplayId, state.isSecure,
display, dispSurface, producer, mEGLConfig); display, dispSurface, producer,
mRenderEngine->getEGLConfig());
hw->setLayerStack(state.layerStack); hw->setLayerStack(state.layerStack);
hw->setProjection(state.orientation, hw->setProjection(state.orientation,
state.viewport, state.frame); state.viewport, state.frame);
@ -2544,7 +2384,6 @@ void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index,
" refresh-rate : %f fps\n" " refresh-rate : %f fps\n"
" x-dpi : %f\n" " x-dpi : %f\n"
" y-dpi : %f\n" " y-dpi : %f\n"
" EGL_NATIVE_VISUAL_ID : %d\n"
" gpu_to_cpu_unsupported : %d\n" " gpu_to_cpu_unsupported : %d\n"
, ,
mLastSwapBufferTime/1000.0, mLastSwapBufferTime/1000.0,
@ -2553,7 +2392,6 @@ void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index,
1e9 / hwc.getRefreshPeriod(HWC_DISPLAY_PRIMARY), 1e9 / hwc.getRefreshPeriod(HWC_DISPLAY_PRIMARY),
hwc.getDpiX(HWC_DISPLAY_PRIMARY), hwc.getDpiX(HWC_DISPLAY_PRIMARY),
hwc.getDpiY(HWC_DISPLAY_PRIMARY), hwc.getDpiY(HWC_DISPLAY_PRIMARY),
mEGLNativeVisualId,
!mGpuToCpuSupported); !mGpuToCpuSupported);
result.appendFormat(" eglSwapBuffers time: %f us\n", result.appendFormat(" eglSwapBuffers time: %f us\n",

View File

@ -317,10 +317,6 @@ private:
/* ------------------------------------------------------------------------ /* ------------------------------------------------------------------------
* EGL * 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 getMaxTextureSize() const;
size_t getMaxViewportDims() const; size_t getMaxViewportDims() const;
@ -431,9 +427,7 @@ private:
sp<EventThread> mSFEventThread; sp<EventThread> mSFEventThread;
sp<EventControlThread> mEventControlThread; sp<EventControlThread> mEventControlThread;
EGLContext mEGLContext; EGLContext mEGLContext;
EGLConfig mEGLConfig;
EGLDisplay mEGLDisplay; EGLDisplay mEGLDisplay;
EGLint mEGLNativeVisualId;
sp<IBinder> mBuiltinDisplays[DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES]; sp<IBinder> mBuiltinDisplays[DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES];
// Can only accessed from the main thread, these members // Can only accessed from the main thread, these members