factor EGL/GL and surface creation out of DisplayHardware
Change-Id: Icd85a6a4caad06f056578008af3e21666fa8b1f4
This commit is contained in:
parent
3b1d2b6b2b
commit
a49126087b
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <GLES/gl.h>
|
||||
|
||||
#include <utils/RefBase.h>
|
||||
#include <utils/String8.h>
|
||||
|
||||
#include <ui/Region.h>
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue