diff --git a/services/surfaceflinger/DisplayHardware.cpp b/services/surfaceflinger/DisplayHardware.cpp index fdde15aa8..af33a8959 100644 --- a/services/surfaceflinger/DisplayHardware.cpp +++ b/services/surfaceflinger/DisplayHardware.cpp @@ -31,6 +31,7 @@ #include #include +#include #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& flinger, - uint32_t dpy) - : DisplayHardwareBase(flinger, dpy), - mFlinger(flinger), mFlags(0), mHwc(0), mSecureLayerVisible(false) + int display, + const sp& 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; } - -uint32_t DisplayHardware::getMaxViewportDims() const { - return mMaxViewportDims[0] < mMaxViewportDims[1] ? - mMaxViewportDims[0] : mMaxViewportDims[1]; +float DisplayHardware::getDpiX() const { + return mDpiX; } -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 ; i0 && format == nativeVisualId) { - *outConfig = configs[i]; - delete [] configs; - return NO_ERROR; - } - } - delete [] configs; - return NAME_NOT_FOUND; +float DisplayHardware::getDpiY() const { + return mDpiY; } +float DisplayHardware::getDensity() const { + return mDensity; +} -void DisplayHardware::init(uint32_t dpy) +float DisplayHardware::getRefreshRate() const { + return mRefreshRate; +} + +int DisplayHardware::getWidth() const { + return mDisplayWidth; +} + +int DisplayHardware::getHeight() const { + return mDisplayHeight; +} + +PixelFormat DisplayHardware::getFormat() const { + return mFormat; +} + +EGLSurface DisplayHardware::getEGLSurface() const { + return mSurface; +} + +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(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. - */ -#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(). - - 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 + * Create our display's surface */ - surface = eglCreateWindowSurface(display, config, mNativeWindow.get(), NULL); + EGLSurface surface; + EGLint w, h; + EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + surface = eglCreateWindowSurface(display, config, window, NULL); eglQuerySurface(display, surface, EGL_WIDTH, &mDisplayWidth); eglQuerySurface(display, surface, EGL_HEIGHT, &mDisplayHeight); - if (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); + 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& 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); + } } // ---------------------------------------------------------------------------- diff --git a/services/surfaceflinger/DisplayHardware.h b/services/surfaceflinger/DisplayHardware.h index 86500a68b..029c3da09 100644 --- a/services/surfaceflinger/DisplayHardware.h +++ b/services/surfaceflinger/DisplayHardware.h @@ -27,7 +27,6 @@ #include #include -#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& flinger, - uint32_t displayIndex); + int dpy, + const sp& 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 >& layers); Vector< sp > 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: - virtual void onVSyncReceived(int dpy, nsecs_t timestamp); - void init(uint32_t displayIndex); - void fini(); + void init(EGLConfig config); + virtual void onVSyncReceived(int dpy, nsecs_t timestamp); + + /* + * Constants, set during initialization + */ sp mFlinger; + int mDisplayId; + HWComposer* mHwc; + PowerHAL mPowerHAL; + // ANativeWindow this display is rendering into + sp mNativeWindow; + // set if mNativeWindow is a FramebufferSurface + sp 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 > 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 mVSyncHandler; - - sp mNativeWindow; }; }; // namespace android diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp index 6cfb190f2..7695e7fd0 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp @@ -38,6 +38,15 @@ namespace android { // ---------------------------------------------------------------------------- +sp FramebufferSurface::create() { + sp 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(ANativeWindow::flags) = fbDev->flags; - const_cast(ANativeWindow::xdpi) = fbDev->xdpi; - const_cast(ANativeWindow::ydpi) = fbDev->ydpi; const_cast(ANativeWindow::minSwapInterval) = fbDev->minSwapInterval; const_cast(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(ANativeWindow::xdpi) = 160; + const_cast(ANativeWindow::ydpi) = 160; + } else { + const_cast(ANativeWindow::xdpi) = fbDev->xdpi; + const_cast(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) { diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h index 5b4fd01b0..672bfbb7d 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h @@ -37,11 +37,11 @@ class String8; class FramebufferSurface : public SurfaceTextureClient { public: - FramebufferSurface(); - virtual void onFirstRef(); + static sp 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; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index a09b5c7bf..b2f26831b 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -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. diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h index d227b2d39..c689297b8 100644 --- a/services/surfaceflinger/LayerBase.h +++ b/services/surfaceflinger/LayerBase.h @@ -25,6 +25,7 @@ #include #include +#include #include diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 46a711d6b..29ec1a7b7 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -59,6 +59,7 @@ #include "LayerScreenshot.h" #include "SurfaceFlinger.h" +#include "DisplayHardware/FramebufferSurface.h" #include "DisplayHardware/HWComposer.h" #include @@ -141,6 +142,9 @@ void SurfaceFlinger::onFirstRef() SurfaceFlinger::~SurfaceFlinger() { glDeleteTextures(1, &mWormholeTexName); + EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + eglTerminate(display); } void SurfaceFlinger::binderDied(const wp& who) @@ -197,59 +201,95 @@ void SurfaceFlinger::bootFinished() property_set("service.bootanim.exit", "1"); } -static inline uint16_t pack565(int r, int g, int b) { - return (r<<11)|(g<<5)|b; +status_t SurfaceFlinger::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 ; i0 && format == nativeVisualId) { + *outConfig = configs[i]; + delete [] configs; + return NO_ERROR; + } + } + delete [] configs; + return NAME_NOT_FOUND; } -status_t SurfaceFlinger::readyToRun() -{ - ALOGI( "SurfaceFlinger's main thread ready to run. " - "Initializing graphics H/W..."); +EGLConfig SurfaceFlinger::selectEGLConfig(EGLDisplay display, EGLint nativeVisualId) { + // select our EGLConfig. It must support EGL_RECORDABLE_ANDROID if + // it is to be used with WIFI displays + EGLConfig config; + EGLint dummy; + status_t err; + EGLint attribs[] = { + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RECORDABLE_ANDROID, EGL_TRUE, + EGL_NONE + }; + err = selectConfigForPixelFormat(display, attribs, nativeVisualId, &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, nativeVisualId, &config); + } + ALOGE_IF(err, "couldn't find an EGLConfig matching the screen format"); + if (eglGetConfigAttrib(display, config, EGL_CONFIG_CAVEAT, &dummy) == EGL_TRUE) { + ALOGW_IF(dummy == EGL_SLOW_CONFIG, "EGL_SLOW_CONFIG selected!"); + } + return config; +} - // we only support one display currently - int dpy = 0; +EGLContext SurfaceFlinger::createGLContext(EGLDisplay display, EGLConfig config) { + // Also create our EGLContext + 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 + }; + EGLContext ctxt = eglCreateContext(display, config, NULL, contextAttributes); + ALOGE_IF(ctxt==EGL_NO_CONTEXT, "EGLContext creation failed"); + return ctxt; +} - { - // initialize the main display - // TODO: initialize all displays - DisplayHardware* const hw = new DisplayHardware(this, dpy); - mDisplayHardwares[0] = hw; +void SurfaceFlinger::initializeGL(EGLDisplay display, EGLSurface surface) { + EGLBoolean result = eglMakeCurrent(display, surface, surface, mEGLContext); + if (!result) { + ALOGE("Couldn't create a working GLES context. check logs. exiting..."); + exit(0); } - // create the shared control-block - mServerHeap = new MemoryHeapBase(4096, - MemoryHeapBase::READ_ONLY, "SurfaceFlinger read-only heap"); - ALOGE_IF(mServerHeap==0, "can't create shared memory dealer"); + 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)); - mServerCblk = static_cast(mServerHeap->getBase()); - ALOGE_IF(mServerCblk==0, "can't get to shared control block's address"); + EGLint w, h; + eglQuerySurface(display, surface, EGL_WIDTH, &w); + eglQuerySurface(display, surface, EGL_HEIGHT, &h); - new(mServerCblk) surface_flinger_cblk_t; + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize); + glGetIntegerv(GL_MAX_VIEWPORT_DIMS, mMaxViewportDims); - // initialize primary screen - // (other display should be initialized in the same manner, but - // asynchronously, as they could come and go. None of this is supported - // yet). - const DisplayHardware& hw(getDefaultDisplayHardware()); - const uint32_t w = hw.getWidth(); - const uint32_t h = hw.getHeight(); - const uint32_t f = hw.getFormat(); - hw.makeCurrent(); - - // initialize the shared control block - mServerCblk->connected |= 1<displays + dpy; - memset(dcblk, 0, sizeof(display_cblk_t)); - dcblk->w = w; // XXX: plane.getWidth(); - dcblk->h = h; // XXX: plane.getHeight(); - dcblk->format = f; - dcblk->orientation = ISurfaceComposer::eOrientationDefault; - dcblk->xdpi = hw.getDpiX(); - dcblk->ydpi = hw.getDpiY(); - dcblk->fps = hw.getRefreshRate(); - dcblk->density = hw.getDensity(); - - // Initialize OpenGL|ES glPixelStorei(GL_UNPACK_ALIGNMENT, 4); glPixelStorei(GL_PACK_ALIGNMENT, 4); glEnableClientState(GL_VERTEX_ARRAY); @@ -257,6 +297,12 @@ status_t SurfaceFlinger::readyToRun() glDisable(GL_DITHER); glDisable(GL_CULL_FACE); + struct pack565 { + inline uint16_t operator() (int r, int g, int b) const { + return (r<<11)|(g<<5)|b; + } + } pack565; + const uint16_t g0 = pack565(0x0F,0x1F,0x0F); const uint16_t g1 = pack565(0x17,0x2f,0x17); const uint16_t wormholeTexData[4] = { g0, g1, g1, g0 }; @@ -285,15 +331,77 @@ status_t SurfaceFlinger::readyToRun() // 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 + EGLint r,g,b,a; + eglGetConfigAttrib(display, mEGLConfig, EGL_RED_SIZE, &r); + eglGetConfigAttrib(display, mEGLConfig, EGL_GREEN_SIZE, &g); + eglGetConfigAttrib(display, mEGLConfig, EGL_BLUE_SIZE, &b); + eglGetConfigAttrib(display, mEGLConfig, EGL_ALPHA_SIZE, &a); + ALOGI("EGL informations:"); + 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, mEGLConfig); + ALOGI("OpenGL ES 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]); +} + +surface_flinger_cblk_t* SurfaceFlinger::getControlBlock() const { + return mServerCblk; +} + +status_t SurfaceFlinger::readyToRun() +{ + ALOGI( "SurfaceFlinger's main thread ready to run. " + "Initializing graphics H/W..."); + + // create the shared control-block + mServerHeap = new MemoryHeapBase(4096, + MemoryHeapBase::READ_ONLY, "SurfaceFlinger read-only heap"); + ALOGE_IF(mServerHeap==0, "can't create shared memory dealer"); + mServerCblk = static_cast(mServerHeap->getBase()); + ALOGE_IF(mServerCblk==0, "can't get to shared control block's address"); + new(mServerCblk) surface_flinger_cblk_t; + + + // initialize EGL + EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + eglInitialize(display, NULL, NULL); + + // Initialize the main display + // create native window to main display + sp anw = FramebufferSurface::create(); + ANativeWindow* const window = anw.get(); + if (!window) { + ALOGE("Display subsystem failed to initialize. check logs. exiting..."); + exit(0); + } + + // initialize the config and context + int format; + window->query(window, NATIVE_WINDOW_FORMAT, &format); + mEGLConfig = selectEGLConfig(display, format); + mEGLContext = createGLContext(display, mEGLConfig); + + // initialize our main display hardware + DisplayHardware* const hw = new DisplayHardware(this, 0, anw, mEGLConfig); + mDisplayHardwares[0] = hw; + + // initialize OpenGL ES + EGLSurface surface = hw->getEGLSurface(); + initializeGL(display, surface); // start the EventThread mEventThread = new EventThread(this); mEventQueue.setEventThread(mEventThread); - /* - * We're now ready to accept clients... - */ - + // We're now ready to accept clients... mReadyToRunBarrier.open(); // start boot animation @@ -308,6 +416,15 @@ void SurfaceFlinger::startBootAnim() { property_set("ctl.start", "bootanim"); } +uint32_t SurfaceFlinger::getMaxTextureSize() const { + return mMaxTextureSize; +} + +uint32_t SurfaceFlinger::getMaxViewportDims() const { + return mMaxViewportDims[0] < mMaxViewportDims[1] ? + mMaxViewportDims[0] : mMaxViewportDims[1]; +} + // ---------------------------------------------------------------------------- bool SurfaceFlinger::authenticateSurfaceTexture( @@ -366,7 +483,7 @@ void SurfaceFlinger::connectDisplay(const sp display) { if (display != NULL) { stc = new SurfaceTextureClient(display); result = eglCreateWindowSurface(hw.getEGLDisplay(), - hw.getEGLConfig(), (EGLNativeWindowType)stc.get(), NULL); + mEGLConfig, (EGLNativeWindowType)stc.get(), NULL); ALOGE_IF(result == EGL_NO_SURFACE, "eglCreateWindowSurface failed (ISurfaceTexture=%p)", display.get()); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 7642e3dd5..4af31fb6c 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -148,6 +148,8 @@ public: GLuint getProtectedTexName() const { return mProtectedTexName; } + surface_flinger_cblk_t* getControlBlock() const; + class MessageDestroyGLTexture : public MessageBase { GLuint texture; @@ -294,6 +296,18 @@ private: void debugFlashRegions(const DisplayHardware& hw); void drawWormhole() const; + uint32_t getMaxTextureSize() const; + uint32_t getMaxViewportDims() const; + + static status_t selectConfigForPixelFormat( + EGLDisplay dpy, + EGLint const* attrs, + PixelFormat format, + EGLConfig* outConfig); + static EGLConfig selectEGLConfig(EGLDisplay disp, EGLint visualId); + static EGLContext createGLContext(EGLDisplay disp, EGLConfig config); + void initializeGL(EGLDisplay display, EGLSurface surface); + void startBootAnim(); void listLayersLocked(const Vector& args, size_t& index, @@ -331,6 +345,11 @@ private: GLuint mProtectedTexName; nsecs_t mBootTime; sp mEventThread; + GLint mMaxViewportDims[2]; + GLint mMaxTextureSize; + EGLContext mEGLContext; + EGLConfig mEGLConfig; + // Can only accessed from the main thread, these members // don't need synchronization