Merge "Fix virtual displays for HWC<=1.1" into jb-mr2-dev
This commit is contained in:
commit
5a557a61d6
@ -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
|
||||||
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
@ -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();
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user