factor EGL/GL and surface creation out of DisplayHardware

Change-Id: Icd85a6a4caad06f056578008af3e21666fa8b1f4
This commit is contained in:
Mathias Agopian 2012-07-12 14:25:33 -07:00
parent 3b1d2b6b2b
commit a49126087b
8 changed files with 352 additions and 298 deletions

View File

@ -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; }
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 ; 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;
}
}
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<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.
*/
#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<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);
}
}
// ----------------------------------------------------------------------------

View File

@ -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:
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<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

View File

@ -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) {

View File

@ -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;

View File

@ -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.

View File

@ -25,6 +25,7 @@
#include <GLES/gl.h>
#include <utils/RefBase.h>
#include <utils/String8.h>
#include <ui/Region.h>

View File

@ -59,6 +59,7 @@
#include "LayerScreenshot.h"
#include "SurfaceFlinger.h"
#include "DisplayHardware/FramebufferSurface.h"
#include "DisplayHardware/HWComposer.h"
#include <private/android_filesystem_config.h>
@ -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<IBinder>& 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 ; 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;
}
}
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<surface_flinger_cblk_t*>(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<<dpy;
display_cblk_t* dcblk = mServerCblk->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<surface_flinger_cblk_t*>(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<FramebufferSurface> 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<ISurfaceTexture> 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());

View File

@ -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<String16>& args, size_t& index,
@ -331,6 +345,11 @@ private:
GLuint mProtectedTexName;
nsecs_t mBootTime;
sp<EventThread> mEventThread;
GLint mMaxViewportDims[2];
GLint mMaxTextureSize;
EGLContext mEGLContext;
EGLConfig mEGLConfig;
// Can only accessed from the main thread, these members
// don't need synchronization