Merge "Fix virtual displays for HWC<=1.1" into jb-mr2-dev

This commit is contained in:
Jesse Hall 2013-03-25 22:37:03 +00:00 committed by Android (Google) Code Review
commit 5a557a61d6
5 changed files with 86 additions and 70 deletions

View File

@ -70,12 +70,13 @@ void checkGLErrors()
DisplayDevice::DisplayDevice( DisplayDevice::DisplayDevice(
const sp<SurfaceFlinger>& flinger, const sp<SurfaceFlinger>& flinger,
DisplayType type, DisplayType type,
int32_t hwcId,
bool isSecure, bool isSecure,
const wp<IBinder>& displayToken, const wp<IBinder>& displayToken,
const sp<DisplaySurface>& displaySurface, const sp<DisplaySurface>& displaySurface,
EGLConfig config) EGLConfig config)
: mFlinger(flinger), : mFlinger(flinger),
mType(type), mHwcDisplayId(-1), mType(type), mHwcDisplayId(hwcId),
mDisplayToken(displayToken), mDisplayToken(displayToken),
mDisplaySurface(displaySurface), mDisplaySurface(displaySurface),
mDisplay(EGL_NO_DISPLAY), mDisplay(EGL_NO_DISPLAY),
@ -91,7 +92,48 @@ DisplayDevice::DisplayDevice(
mOrientation() mOrientation()
{ {
mNativeWindow = new Surface(mDisplaySurface->getIGraphicBufferProducer()); mNativeWindow = new Surface(mDisplaySurface->getIGraphicBufferProducer());
init(config); ANativeWindow* const window = mNativeWindow.get();
int format;
window->query(window, NATIVE_WINDOW_FORMAT, &format);
/*
* Create our display's surface
*/
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);
mDisplay = display;
mSurface = surface;
mFormat = format;
mPageFlipCount = 0;
mViewport.makeInvalid();
mFrame.makeInvalid();
// virtual displays are always considered enabled
mScreenAcquired = (mType >= DisplayDevice::DISPLAY_VIRTUAL);
// Name the display. The name will be replaced shortly if the display
// was created with createDisplay().
switch (mType) {
case DISPLAY_PRIMARY:
mDisplayName = "Built-in Screen";
break;
case DISPLAY_EXTERNAL:
mDisplayName = "HDMI Screen";
break;
default:
mDisplayName = "Virtual Screen"; // e.g. Overlay #n
break;
}
// initialize the display orientation transform.
setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
} }
DisplayDevice::~DisplayDevice() { DisplayDevice::~DisplayDevice() {
@ -121,55 +163,6 @@ EGLSurface DisplayDevice::getEGLSurface() const {
return mSurface; return mSurface;
} }
void DisplayDevice::init(EGLConfig config)
{
ANativeWindow* const window = mNativeWindow.get();
int format;
window->query(window, NATIVE_WINDOW_FORMAT, &format);
/*
* Create our display's surface
*/
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);
mDisplay = display;
mSurface = surface;
mFormat = format;
mPageFlipCount = 0;
mViewport.makeInvalid();
mFrame.makeInvalid();
// external displays are always considered enabled
mScreenAcquired = (mType >= DisplayDevice::NUM_DISPLAY_TYPES);
// get an h/w composer ID
mHwcDisplayId = mFlinger->allocateHwcDisplayId(mType);
// Name the display. The name will be replaced shortly if the display
// was created with createDisplay().
switch (mType) {
case DISPLAY_PRIMARY:
mDisplayName = "Built-in Screen";
break;
case DISPLAY_EXTERNAL:
mDisplayName = "HDMI Screen";
break;
default:
mDisplayName = "Virtual Screen"; // e.g. Overlay #n
break;
}
// initialize the display orientation transform.
setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
}
void DisplayDevice::setDisplayName(const String8& displayName) { void DisplayDevice::setDisplayName(const String8& displayName) {
if (!displayName.isEmpty()) { if (!displayName.isEmpty()) {
// never override the name with an empty name // never override the name with an empty name

View File

@ -72,6 +72,7 @@ public:
DisplayDevice( DisplayDevice(
const sp<SurfaceFlinger>& flinger, const sp<SurfaceFlinger>& flinger,
DisplayType type, DisplayType type,
int32_t hwcId, // negative for non-HWC-composited displays
bool isSecure, bool isSecure,
const wp<IBinder>& displayToken, const wp<IBinder>& displayToken,
const sp<DisplaySurface>& displaySurface, const sp<DisplaySurface>& displaySurface,
@ -152,8 +153,6 @@ public:
void dump(String8& result, char* buffer, size_t SIZE) const; void dump(String8& result, char* buffer, size_t SIZE) const;
private: private:
void init(EGLConfig config);
/* /*
* Constants, set during initialization * Constants, set during initialization
*/ */

View File

@ -21,24 +21,30 @@
namespace android { namespace android {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int disp, VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int32_t dispId,
const sp<IGraphicBufferProducer>& sink, const String8& name) const sp<IGraphicBufferProducer>& sink, const String8& name)
: mHwc(hwc), : mHwc(hwc),
mDisplayId(disp), mDisplayId(dispId),
mSource(new BufferQueueInterposer(sink, name)),
mName(name) mName(name)
{} {
if (mDisplayId >= 0) {
mInterposer = new BufferQueueInterposer(sink, name);
mSourceProducer = mInterposer;
} else {
mSourceProducer = sink;
}
}
VirtualDisplaySurface::~VirtualDisplaySurface() { VirtualDisplaySurface::~VirtualDisplaySurface() {
if (mAcquiredBuffer != NULL) { if (mAcquiredBuffer != NULL) {
status_t result = mSource->releaseBuffer(Fence::NO_FENCE); status_t result = mInterposer->releaseBuffer(Fence::NO_FENCE);
ALOGE_IF(result != NO_ERROR, "VirtualDisplaySurface \"%s\": " ALOGE_IF(result != NO_ERROR, "VirtualDisplaySurface \"%s\": "
"failed to release buffer: %d", mName.string(), result); "failed to release buffer: %d", mName.string(), result);
} }
} }
sp<IGraphicBufferProducer> VirtualDisplaySurface::getIGraphicBufferProducer() const { sp<IGraphicBufferProducer> VirtualDisplaySurface::getIGraphicBufferProducer() const {
return mSource; return mSourceProducer;
} }
status_t VirtualDisplaySurface::compositionComplete() { status_t VirtualDisplaySurface::compositionComplete() {
@ -46,6 +52,9 @@ status_t VirtualDisplaySurface::compositionComplete() {
} }
status_t VirtualDisplaySurface::advanceFrame() { status_t VirtualDisplaySurface::advanceFrame() {
if (mInterposer == NULL)
return NO_ERROR;
Mutex::Autolock lock(mMutex); Mutex::Autolock lock(mMutex);
status_t result = NO_ERROR; status_t result = NO_ERROR;
@ -57,12 +66,12 @@ status_t VirtualDisplaySurface::advanceFrame() {
} }
sp<Fence> fence; sp<Fence> fence;
result = mSource->acquireBuffer(&mAcquiredBuffer, &fence); result = mInterposer->acquireBuffer(&mAcquiredBuffer, &fence);
if (result == BufferQueueInterposer::NO_BUFFER_AVAILABLE) { if (result == BufferQueueInterposer::NO_BUFFER_AVAILABLE) {
result = mSource->pullEmptyBuffer(); result = mInterposer->pullEmptyBuffer();
if (result != NO_ERROR) if (result != NO_ERROR)
return result; return result;
result = mSource->acquireBuffer(&mAcquiredBuffer, &fence); result = mInterposer->acquireBuffer(&mAcquiredBuffer, &fence);
} }
if (result != NO_ERROR) if (result != NO_ERROR)
return result; return result;
@ -71,6 +80,9 @@ status_t VirtualDisplaySurface::advanceFrame() {
} }
void VirtualDisplaySurface::onFrameCommitted() { void VirtualDisplaySurface::onFrameCommitted() {
if (mInterposer == NULL)
return;
Mutex::Autolock lock(mMutex); Mutex::Autolock lock(mMutex);
if (mAcquiredBuffer != NULL) { if (mAcquiredBuffer != NULL) {
// fbFence signals when reads from the framebuffer are finished // fbFence signals when reads from the framebuffer are finished
@ -85,7 +97,7 @@ void VirtualDisplaySurface::onFrameCommitted() {
String8::format("HWC done: %.21s", mName.string()), String8::format("HWC done: %.21s", mName.string()),
fbFence, outFence); fbFence, outFence);
status_t result = mSource->releaseBuffer(fence); status_t result = mInterposer->releaseBuffer(fence);
ALOGE_IF(result != NO_ERROR, "VirtualDisplaySurface \"%s\": " ALOGE_IF(result != NO_ERROR, "VirtualDisplaySurface \"%s\": "
"failed to release buffer: %d", mName.string(), result); "failed to release buffer: %d", mName.string(), result);
mAcquiredBuffer.clear(); mAcquiredBuffer.clear();

View File

@ -45,12 +45,18 @@ class HWComposer;
* eglSwapBuffers doesn't immediately dequeue a buffer for the next frame, * eglSwapBuffers doesn't immediately dequeue a buffer for the next frame,
* since we can't rely on being able to dequeue more than one buffer at a time. * since we can't rely on being able to dequeue more than one buffer at a time.
* *
* This class also has a passthrough mode, where it doesn't use a
* BufferQueueInterposer and never sends buffers to HWC. Instead, OpenGL ES
* output buffers are queued directly to the virtual display sink; this class
* is inactive after construction. This mode is used when the HWC doesn't
* support compositing for virtual displays.
*
* TODO(jessehall): Add a libgui test that ensures that EGL/GLES do lazy * TODO(jessehall): Add a libgui test that ensures that EGL/GLES do lazy
* dequeBuffers; we've wanted to require that for other reasons anyway. * dequeBuffers; we've wanted to require that for other reasons anyway.
*/ */
class VirtualDisplaySurface : public DisplaySurface { class VirtualDisplaySurface : public DisplaySurface {
public: public:
VirtualDisplaySurface(HWComposer& hwc, int disp, VirtualDisplaySurface(HWComposer& hwc, int32_t dispId,
const sp<IGraphicBufferProducer>& sink, const sp<IGraphicBufferProducer>& sink,
const String8& name); const String8& name);
@ -66,10 +72,14 @@ private:
// immutable after construction // immutable after construction
HWComposer& mHwc; HWComposer& mHwc;
int mDisplayId; int32_t mDisplayId;
sp<BufferQueueInterposer> mSource;
String8 mName; String8 mName;
// with HWC support, both of these point to the same object.
// otherwise, mInterposer is NULL and mSourceProducer is the sink.
sp<BufferQueueInterposer> mInterposer;
sp<IGraphicBufferProducer> mSourceProducer;
// mutable, must be synchronized with mMutex // mutable, must be synchronized with mMutex
Mutex mMutex; Mutex mMutex;
sp<GraphicBuffer> mAcquiredBuffer; sp<GraphicBuffer> mAcquiredBuffer;

View File

@ -510,7 +510,8 @@ status_t SurfaceFlinger::readyToRun()
wp<IBinder> token = mBuiltinDisplays[i]; wp<IBinder> token = mBuiltinDisplays[i];
sp<DisplayDevice> hw = new DisplayDevice(this, sp<DisplayDevice> hw = new DisplayDevice(this,
type, isSecure, token, new FramebufferSurface(*mHwc, i), type, allocateHwcDisplayId(type), isSecure, token,
new FramebufferSurface(*mHwc, i),
mEGLConfig); mEGLConfig);
if (i > DisplayDevice::DISPLAY_PRIMARY) { if (i > DisplayDevice::DISPLAY_PRIMARY) {
// FIXME: currently we don't get blank/unblank requests // FIXME: currently we don't get blank/unblank requests
@ -1149,10 +1150,11 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
const DisplayDeviceState& state(curr[i]); const DisplayDeviceState& state(curr[i]);
sp<DisplaySurface> dispSurface; sp<DisplaySurface> dispSurface;
int32_t hwcDisplayId = allocateHwcDisplayId(state.type);
if (state.isVirtualDisplay()) { if (state.isVirtualDisplay()) {
if (state.surface != NULL) { if (state.surface != NULL) {
dispSurface = new VirtualDisplaySurface( dispSurface = new VirtualDisplaySurface(
*mHwc, state.type, state.surface, *mHwc, hwcDisplayId, state.surface,
state.displayName); state.displayName);
} }
} else { } else {
@ -1169,8 +1171,8 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
const wp<IBinder>& display(curr.keyAt(i)); const wp<IBinder>& display(curr.keyAt(i));
if (dispSurface != NULL) { if (dispSurface != NULL) {
sp<DisplayDevice> hw = new DisplayDevice(this, sp<DisplayDevice> hw = new DisplayDevice(this,
state.type, state.isSecure, display, state.type, hwcDisplayId, state.isSecure,
dispSurface, mEGLConfig); display, dispSurface, mEGLConfig);
hw->setLayerStack(state.layerStack); hw->setLayerStack(state.layerStack);
hw->setProjection(state.orientation, hw->setProjection(state.orientation,
state.viewport, state.frame); state.viewport, state.frame);