refactor things a bit

- decouple GL and main display initialization
- ensure that each "supported" display has its own FramebufferSurface
- onScreenAcquired/Released now takes a display

Change-Id: If34a05f3dea40f6c79db77f4dde283a2580daac4
This commit is contained in:
Mathias Agopian 2012-09-13 14:09:01 -07:00
parent c8cff90d49
commit cde87a3b9d
4 changed files with 125 additions and 62 deletions

View File

@ -561,22 +561,34 @@ size_t HWComposer::getNumLayers(int32_t id) const {
mDisplayData[id].list->numHwLayers : 0;
}
int HWComposer::fbPost(buffer_handle_t buffer)
{
return mFbDev->post(mFbDev, buffer);
}
int HWComposer::fbCompositionComplete()
{
if (mFbDev->compositionComplete) {
return mFbDev->compositionComplete(mFbDev);
int HWComposer::getVisualID() const {
if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
return HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
} else {
return INVALID_OPERATION;
return mFbDev->format;
}
}
int HWComposer::fbPost(buffer_handle_t buffer) {
if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) {
return mFbDev->post(mFbDev, buffer);
}
return NO_ERROR;
}
int HWComposer::fbCompositionComplete() {
if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) {
if (mFbDev->compositionComplete) {
return mFbDev->compositionComplete(mFbDev);
} else {
return INVALID_OPERATION;
}
}
return NO_ERROR;
}
void HWComposer::fbDump(String8& result) {
if (mFbDev->common.version >= 1 && mFbDev->dump) {
if (mFbDev && mFbDev->common.version >= 1 && mFbDev->dump) {
const size_t SIZE = 4096;
char buffer[SIZE];
mFbDev->dump(mFbDev, buffer, SIZE);
@ -727,7 +739,7 @@ HWComposer::LayerListIterator HWComposer::end(int32_t id) {
void HWComposer::dump(String8& result, char* buffer, size_t SIZE,
const Vector< sp<LayerBase> >& visibleLayersSortedByZ) const {
if (mHwc) {
result.append("Hardware Composer state:\n");
result.appendFormat("Hardware Composer state (version %8x):\n", hwcApiVersion(mHwc));
result.appendFormat(" mDebugForceFakeVSync=%d\n", mDebugForceFakeVSync);
for (size_t i=0 ; i<mNumDisplays ; i++) {
const DisplayData& disp(mDisplayData[i]);

View File

@ -106,6 +106,10 @@ public:
// needed forward declarations
class LayerListIterator;
// return the visual id to be used to find a suitable EGLConfig for
// *ALL* displays.
int getVisualID() const;
// Forwarding to FB HAL for pre-HWC-1.1 code (see FramebufferSurface).
int fbPost(buffer_handle_t buffer);
int fbCompositionComplete();

View File

@ -43,6 +43,7 @@
#include <ui/GraphicBufferAllocator.h>
#include <ui/PixelFormat.h>
#include <utils/misc.h>
#include <utils/String8.h>
#include <utils/String16.h>
#include <utils/StopWatch.h>
@ -243,6 +244,16 @@ status_t SurfaceFlinger::selectConfigForPixelFormat(
eglGetConfigs(dpy, NULL, 0, &numConfigs);
EGLConfig* const configs = new EGLConfig[numConfigs];
eglChooseConfig(dpy, attrs, configs, numConfigs, &n);
if (format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
// FIXME: temporary hack until HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED
// is supported by the implementation. we can only be in this case
// if we have HWC 1.1
*outConfig = configs[0];
delete [] configs;
return NO_ERROR;
}
for (int i=0 ; i<n ; i++) {
EGLint nativeVisualId = 0;
eglGetConfigAttrib(dpy, configs[i], EGL_NATIVE_VISUAL_ID, &nativeVisualId);
@ -264,6 +275,11 @@ EGLConfig SurfaceFlinger::selectEGLConfig(EGLDisplay display, EGLint nativeVisua
status_t err;
EGLint attribs[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
// EGL_RECORDABLE_ANDROID must be last so that we can retry
// without it easily (see below)
EGL_RECORDABLE_ANDROID, EGL_TRUE,
EGL_NONE
};
@ -271,7 +287,7 @@ EGLConfig SurfaceFlinger::selectEGLConfig(EGLDisplay display, EGLint nativeVisua
if (err) {
// maybe we failed because of EGL_RECORDABLE_ANDROID
ALOGW("couldn't find an EGLConfig with EGL_RECORDABLE_ANDROID");
attribs[2] = EGL_NONE;
attribs[NELEM(attribs) - 3] = EGL_NONE;
err = selectConfigForPixelFormat(display, attribs, nativeVisualId, &config);
}
ALOGE_IF(err, "couldn't find an EGLConfig matching the screen format");
@ -297,13 +313,7 @@ EGLContext SurfaceFlinger::createGLContext(EGLDisplay display, EGLConfig config)
return ctxt;
}
void SurfaceFlinger::initializeGL(EGLDisplay display, const sp<DisplayDevice>& hw) {
EGLBoolean result = DisplayDevice::makeCurrent(display, hw, mEGLContext);
if (!result) {
ALOGE("Couldn't create a working GLES context. check logs. exiting...");
exit(0);
}
void SurfaceFlinger::initializeGL(EGLDisplay display) {
GLExtensions& extensions(GLExtensions::getInstance());
extensions.initWithGLStrings(
glGetString(GL_VENDOR),
@ -375,39 +385,45 @@ status_t SurfaceFlinger::readyToRun()
mHwc = new HWComposer(this,
*static_cast<HWComposer::EventHandler *>(this));
// Initialize the main display
// create native window to main display
sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc);
if (fbs == NULL) {
ALOGE("Display subsystem failed to initialize. check logs. exiting...");
exit(0);
}
sp<SurfaceTextureClient> stc(new SurfaceTextureClient(
static_cast<sp<ISurfaceTexture> >(fbs->getBufferQueue())));
// initialize the config and context
int format;
ANativeWindow* const anw = stc.get();
anw->query(anw, NATIVE_WINDOW_FORMAT, &format);
EGLint format = mHwc->getVisualID();
mEGLConfig = selectEGLConfig(mEGLDisplay, format);
mEGLContext = createGLContext(mEGLDisplay, mEGLConfig);
// initialize our main display hardware
// initialize our non-virtual displays
for (size_t i=0 ; i<DisplayDevice::NUM_DISPLAY_TYPES ; i++) {
mDefaultDisplays[i] = new BBinder();
mCurrentState.displays.add(mDefaultDisplays[i],
DisplayDeviceState((DisplayDevice::DisplayType)i));
DisplayDeviceState(DisplayDevice::DisplayType(i)));
}
// The main display is a bit special and always exists
//
// if we didn't add it here, it would be added automatically during the
// first transaction, however this would also create some difficulties:
//
// - there would be a race where a client could call getDisplayInfo(),
// for instance before the DisplayDevice is created.
//
// - we need a GL context current in a few places, when initializing
// OpenGL ES (see below), or creating a layer,
// or when a texture is (asynchronously) destroyed, and for that
// we need a valid surface, so it's conveniant to use the main display
// for that.
sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc);
sp<SurfaceTextureClient> stc = new SurfaceTextureClient(
static_cast< sp<ISurfaceTexture> >(fbs->getBufferQueue()));
sp<DisplayDevice> hw = new DisplayDevice(this,
DisplayDevice::DISPLAY_PRIMARY,
mDefaultDisplays[DisplayDevice::DISPLAY_PRIMARY],
anw, fbs, mEGLConfig);
stc, fbs, mEGLConfig);
mDisplays.add(mDefaultDisplays[DisplayDevice::DISPLAY_PRIMARY], hw);
// initialize OpenGL ES
initializeGL(mEGLDisplay, hw);
DisplayDevice::makeCurrent(mEGLDisplay, hw, mEGLContext);
initializeGL(mEGLDisplay);
// start the EventThread
mEventThread = new EventThread(this);
@ -416,6 +432,7 @@ status_t SurfaceFlinger::readyToRun()
// initialize our drawing state
mDrawingState = mCurrentState;
// We're now ready to accept clients...
mReadyToRunBarrier.open();
@ -1009,16 +1026,41 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
for (size_t i=0 ; i<cc ; i++) {
if (draw.indexOfKey(curr.keyAt(i)) < 0) {
const DisplayDeviceState& state(curr[i]);
if (state.surface != NULL) {
sp<SurfaceTextureClient> stc(
new SurfaceTextureClient(state.surface));
const wp<IBinder>& display(curr.keyAt(i));
sp<DisplayDevice> disp = new DisplayDevice(this,
state.type, display, stc, 0, mEGLConfig);
disp->setLayerStack(state.layerStack);
disp->setProjection(state.orientation,
sp<FramebufferSurface> fbs;
sp<SurfaceTextureClient> stc;
if (!state.isVirtualDisplay()) {
ALOGE_IF(state.surface!=NULL,
"adding a supported display, but rendering "
"surface is provided (%p), ignoring it",
state.surface.get());
// for supported (by hwc) displays we provide our
// own rendering surface
fbs = new FramebufferSurface(*mHwc);
stc = new SurfaceTextureClient(
static_cast< sp<ISurfaceTexture> >(fbs->getBufferQueue()));
} else {
if (state.surface != NULL) {
stc = new SurfaceTextureClient(state.surface);
}
}
const wp<IBinder>& display(curr.keyAt(i));
if (stc != NULL) {
sp<DisplayDevice> hw = new DisplayDevice(this,
state.type, display, stc, fbs, mEGLConfig);
hw->setLayerStack(state.layerStack);
hw->setProjection(state.orientation,
state.viewport, state.frame);
mDisplays.add(display, disp);
mDisplays.add(display, hw);
if (hw->getDisplayType() < DisplayDevice::NUM_DISPLAY_TYPES) {
// notify the system that this display is now up
// (note onScreenAcquired() is safe to call from
// here because we're in the main thread)
onScreenAcquired(hw);
}
}
}
}
@ -1753,9 +1795,7 @@ void SurfaceFlinger::onInitializeDisplays() {
d.viewport.makeInvalid();
displays.add(d);
setTransactionState(state, displays, 0);
// XXX: this should init default device to "unblank" and all other devices to "blank"
onScreenAcquired();
onScreenAcquired(getDefaultDisplayDevice());
}
void SurfaceFlinger::initializeDisplays() {
@ -1773,21 +1813,25 @@ void SurfaceFlinger::initializeDisplays() {
}
void SurfaceFlinger::onScreenAcquired() {
void SurfaceFlinger::onScreenAcquired(const sp<const DisplayDevice>& hw) {
ALOGD("Screen about to return, flinger = %p", this);
sp<const DisplayDevice> hw(getDefaultDisplayDevice()); // XXX: this should be per DisplayDevice
getHwComposer().acquire();
hw->acquireScreen();
mEventThread->onScreenAcquired();
if (hw->getDisplayType() == DisplayDevice::DISPLAY_PRIMARY) {
// FIXME: eventthread only knows about the main display right now
mEventThread->onScreenAcquired();
}
mVisibleRegionsDirty = true;
repaintEverything();
}
void SurfaceFlinger::onScreenReleased() {
void SurfaceFlinger::onScreenReleased(const sp<const DisplayDevice>& hw) {
ALOGD("About to give-up screen, flinger = %p", this);
sp<const DisplayDevice> hw(getDefaultDisplayDevice()); // XXX: this should be per DisplayDevice
if (hw->isScreenAcquired()) {
mEventThread->onScreenReleased();
if (hw->getDisplayType() == DisplayDevice::DISPLAY_PRIMARY) {
// FIXME: eventthread only knows about the main display right now
mEventThread->onScreenReleased();
}
hw->releaseScreen();
getHwComposer().release();
mVisibleRegionsDirty = true;
@ -1801,7 +1845,8 @@ void SurfaceFlinger::unblank() {
public:
MessageScreenAcquired(SurfaceFlinger* flinger) : flinger(flinger) { }
virtual bool handler() {
flinger->onScreenAcquired();
// FIXME: should this be per-display?
flinger->onScreenAcquired(flinger->getDefaultDisplayDevice());
return true;
}
};
@ -1815,7 +1860,8 @@ void SurfaceFlinger::blank() {
public:
MessageScreenReleased(SurfaceFlinger* flinger) : flinger(flinger) { }
virtual bool handler() {
flinger->onScreenReleased();
// FIXME: should this be per-display?
flinger->onScreenReleased(flinger->getDefaultDisplayDevice());
return true;
}
};

View File

@ -166,6 +166,7 @@ private:
DisplayDeviceState(DisplayDevice::DisplayType type);
bool isValid() const { return type >= 0; }
bool isMainDisplay() const { return type == DisplayDevice::DISPLAY_PRIMARY; }
bool isVirtualDisplay() const { return type >= DisplayDevice::DISPLAY_VIRTUAL; }
DisplayDevice::DisplayType type;
sp<ISurfaceTexture> surface;
uint32_t layerStack;
@ -238,9 +239,9 @@ private:
// called on the main thread in response to initializeDisplays()
void onInitializeDisplays();
// called on the main thread in response to blank()
void onScreenReleased();
void onScreenReleased(const sp<const DisplayDevice>& hw);
// called on the main thread in response to unblank()
void onScreenAcquired();
void onScreenAcquired(const sp<const DisplayDevice>& hw);
void handleMessageTransaction();
void handleMessageInvalidate();
@ -320,7 +321,7 @@ private:
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, const sp<DisplayDevice>& hw);
void initializeGL(EGLDisplay display);
uint32_t getMaxTextureSize() const;
uint32_t getMaxViewportDims() const;