Allow for resizing of Virtual Displays.

Modify SurfaceFlinger to use VirtualDisplaySurface in all cases when a virtual
display is used. Add functionality in VirtualDisplaySurface to resize the
buffers aquired in the QueueBufferOutput. Add transaction support in
SurfaceFlinger for resize. Add the modification of the size in DisplayDevice.

Change-Id: Iae7e3556dc06fd18d470adbbd76f7255f6e6dd6b
Tested: None
This commit is contained in:
Michael Lentine 2014-07-18 15:34:25 -07:00
parent 1f6078aef7
commit 47e45405d1
8 changed files with 87 additions and 20 deletions

View File

@ -81,6 +81,8 @@ status_t DisplayState::write(Parcel& output) const {
output.writeInt32(orientation); output.writeInt32(orientation);
output.write(viewport); output.write(viewport);
output.write(frame); output.write(frame);
output.writeInt32(width);
output.writeInt32(height);
return NO_ERROR; return NO_ERROR;
} }
@ -92,6 +94,8 @@ status_t DisplayState::read(const Parcel& input) {
orientation = input.readInt32(); orientation = input.readInt32();
input.read(viewport); input.read(viewport);
input.read(frame); input.read(frame);
width = input.readInt32();
height = input.readInt32();
return NO_ERROR; return NO_ERROR;
} }

View File

@ -102,6 +102,7 @@ DisplayDevice::DisplayDevice(
if (mType >= DisplayDevice::DISPLAY_VIRTUAL) if (mType >= DisplayDevice::DISPLAY_VIRTUAL)
window->setSwapInterval(window, 0); window->setSwapInterval(window, 0);
mConfig = config;
mDisplay = display; mDisplay = display;
mSurface = surface; mSurface = surface;
mFormat = format; mFormat = format;
@ -397,6 +398,22 @@ status_t DisplayDevice::orientationToTransfrom(
return NO_ERROR; return NO_ERROR;
} }
void DisplayDevice::setDisplaySize(const int newWidth, const int newHeight) {
dirtyRegion.set(getBounds());
mDisplaySurface->resizeBuffers(newWidth, newHeight);
ANativeWindow* const window = mNativeWindow.get();
mSurface = eglCreateWindowSurface(mDisplay, mConfig, window, NULL);
eglQuerySurface(mDisplay, mSurface, EGL_WIDTH, &mDisplayWidth);
eglQuerySurface(mDisplay, mSurface, EGL_HEIGHT, &mDisplayHeight);
LOG_FATAL_IF(mDisplayWidth != newWidth,
"Unable to set new width to %d", newWidth);
LOG_FATAL_IF(mDisplayHeight != newHeight,
"Unable to set new height to %d", newHeight);
}
void DisplayDevice::setProjection(int orientation, void DisplayDevice::setProjection(int orientation,
const Rect& newViewport, const Rect& newFrame) { const Rect& newViewport, const Rect& newFrame) {
Rect viewport(newViewport); Rect viewport(newViewport);

View File

@ -109,6 +109,7 @@ public:
Region getDirtyRegion(bool repaintEverything) const; Region getDirtyRegion(bool repaintEverything) const;
void setLayerStack(uint32_t stack); void setLayerStack(uint32_t stack);
void setDisplaySize(const int newWidth, const int newHeight);
void setProjection(int orientation, const Rect& viewport, const Rect& frame); void setProjection(int orientation, const Rect& viewport, const Rect& frame);
int getOrientation() const { return mOrientation; } int getOrientation() const { return mOrientation; }
@ -181,6 +182,7 @@ private:
sp<ANativeWindow> mNativeWindow; sp<ANativeWindow> mNativeWindow;
sp<DisplaySurface> mDisplaySurface; sp<DisplaySurface> mDisplaySurface;
EGLConfig mConfig;
EGLDisplay mDisplay; EGLDisplay mDisplay;
EGLSurface mSurface; EGLSurface mSurface;
int mDisplayWidth; int mDisplayWidth;

View File

@ -72,6 +72,8 @@ public:
virtual void dump(String8& result) const = 0; virtual void dump(String8& result) const = 0;
virtual void resizeBuffers(const uint32_t w, const uint32_t h) = 0;
protected: protected:
DisplaySurface() {} DisplaySurface() {}
virtual ~DisplaySurface() {} virtual ~DisplaySurface() {}

View File

@ -49,6 +49,10 @@ public:
// has a non-virtual dump() with the same signature. // has a non-virtual dump() with the same signature.
virtual void dump(String8& result) const; virtual void dump(String8& result) const;
// Cannot resize a buffers in a FramebufferSurface. Only works with virtual
// displays.
virtual void resizeBuffers(const uint32_t /*w*/, const uint32_t /*h*/) { };
private: private:
virtual ~FramebufferSurface() { }; // this class cannot be overloaded virtual ~FramebufferSurface() { }; // this class cannot be overloaded

View File

@ -68,6 +68,8 @@ VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int32_t dispId,
int sinkWidth, sinkHeight; int sinkWidth, sinkHeight;
sink->query(NATIVE_WINDOW_WIDTH, &sinkWidth); sink->query(NATIVE_WINDOW_WIDTH, &sinkWidth);
sink->query(NATIVE_WINDOW_HEIGHT, &sinkHeight); sink->query(NATIVE_WINDOW_HEIGHT, &sinkHeight);
mSinkBufferWidth = sinkWidth;
mSinkBufferHeight = sinkHeight;
// Pick the buffer format to request from the sink when not rendering to it // Pick the buffer format to request from the sink when not rendering to it
// with GLES. If the consumer needs CPU access, use the default format // with GLES. If the consumer needs CPU access, use the default format
@ -104,10 +106,6 @@ status_t VirtualDisplaySurface::beginFrame(bool mustRecompose) {
"Unexpected beginFrame() in %s state", dbgStateStr()); "Unexpected beginFrame() in %s state", dbgStateStr());
mDbgState = DBG_STATE_BEGUN; mDbgState = DBG_STATE_BEGUN;
uint32_t transformHint, numPendingBuffers;
mQueueBufferOutput.deflate(&mSinkBufferWidth, &mSinkBufferHeight,
&transformHint, &numPendingBuffers);
return refreshOutputBuffer(); return refreshOutputBuffer();
} }
@ -259,8 +257,20 @@ void VirtualDisplaySurface::onFrameCommitted() {
void VirtualDisplaySurface::dump(String8& /* result */) const { void VirtualDisplaySurface::dump(String8& /* result */) const {
} }
void VirtualDisplaySurface::resizeBuffers(const uint32_t w, const uint32_t h) {
uint32_t tmpW, tmpH, transformHint, numPendingBuffers;
mQueueBufferOutput.deflate(&tmpW, &tmpH, &transformHint, &numPendingBuffers);
mQueueBufferOutput.inflate(w, h, transformHint, numPendingBuffers);
mSinkBufferWidth = w;
mSinkBufferHeight = h;
}
status_t VirtualDisplaySurface::requestBuffer(int pslot, status_t VirtualDisplaySurface::requestBuffer(int pslot,
sp<GraphicBuffer>* outBuf) { sp<GraphicBuffer>* outBuf) {
if (mDisplayId < 0)
return mSource[SOURCE_SINK]->requestBuffer(pslot, outBuf);
VDS_LOGW_IF(mDbgState != DBG_STATE_GLES, VDS_LOGW_IF(mDbgState != DBG_STATE_GLES,
"Unexpected requestBuffer pslot=%d in %s state", "Unexpected requestBuffer pslot=%d in %s state",
pslot, dbgStateStr()); pslot, dbgStateStr());
@ -275,6 +285,7 @@ status_t VirtualDisplaySurface::setBufferCount(int bufferCount) {
status_t VirtualDisplaySurface::dequeueBuffer(Source source, status_t VirtualDisplaySurface::dequeueBuffer(Source source,
uint32_t format, uint32_t usage, int* sslot, sp<Fence>* fence) { uint32_t format, uint32_t usage, int* sslot, sp<Fence>* fence) {
LOG_FATAL_IF(mDisplayId < 0, "mDisplayId=%d but should not be < 0.", mDisplayId);
// Don't let a slow consumer block us // Don't let a slow consumer block us
bool async = (source == SOURCE_SINK); bool async = (source == SOURCE_SINK);
@ -319,6 +330,9 @@ status_t VirtualDisplaySurface::dequeueBuffer(Source source,
status_t VirtualDisplaySurface::dequeueBuffer(int* pslot, sp<Fence>* fence, bool async, status_t VirtualDisplaySurface::dequeueBuffer(int* pslot, sp<Fence>* fence, bool async,
uint32_t w, uint32_t h, uint32_t format, uint32_t usage) { uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
if (mDisplayId < 0)
return mSource[SOURCE_SINK]->dequeueBuffer(pslot, fence, async, w, h, format, usage);
VDS_LOGW_IF(mDbgState != DBG_STATE_PREPARED, VDS_LOGW_IF(mDbgState != DBG_STATE_PREPARED,
"Unexpected dequeueBuffer() in %s state", dbgStateStr()); "Unexpected dequeueBuffer() in %s state", dbgStateStr());
mDbgState = DBG_STATE_GLES; mDbgState = DBG_STATE_GLES;
@ -399,6 +413,9 @@ status_t VirtualDisplaySurface::attachBuffer(int* /* outSlot */,
status_t VirtualDisplaySurface::queueBuffer(int pslot, status_t VirtualDisplaySurface::queueBuffer(int pslot,
const QueueBufferInput& input, QueueBufferOutput* output) { const QueueBufferInput& input, QueueBufferOutput* output) {
if (mDisplayId < 0)
return mSource[SOURCE_SINK]->queueBuffer(pslot, input, output);
VDS_LOGW_IF(mDbgState != DBG_STATE_GLES, VDS_LOGW_IF(mDbgState != DBG_STATE_GLES,
"Unexpected queueBuffer(pslot=%d) in %s state", pslot, "Unexpected queueBuffer(pslot=%d) in %s state", pslot,
dbgStateStr()); dbgStateStr());
@ -452,6 +469,9 @@ status_t VirtualDisplaySurface::queueBuffer(int pslot,
} }
void VirtualDisplaySurface::cancelBuffer(int pslot, const sp<Fence>& fence) { void VirtualDisplaySurface::cancelBuffer(int pslot, const sp<Fence>& fence) {
if (mDisplayId < 0)
return mSource[SOURCE_SINK]->cancelBuffer(mapProducer2SourceSlot(source, pslot), fence);
VDS_LOGW_IF(mDbgState != DBG_STATE_GLES, VDS_LOGW_IF(mDbgState != DBG_STATE_GLES,
"Unexpected cancelBuffer(pslot=%d) in %s state", pslot, "Unexpected cancelBuffer(pslot=%d) in %s state", pslot,
dbgStateStr()); dbgStateStr());
@ -462,7 +482,17 @@ void VirtualDisplaySurface::cancelBuffer(int pslot, const sp<Fence>& fence) {
} }
int VirtualDisplaySurface::query(int what, int* value) { int VirtualDisplaySurface::query(int what, int* value) {
return mSource[SOURCE_SINK]->query(what, value); switch (what) {
case NATIVE_WINDOW_WIDTH:
*value = mSinkBufferWidth;
break;
case NATIVE_WINDOW_HEIGHT:
*value = mSinkBufferHeight;
break;
default:
return mSource[SOURCE_SINK]->query(what, value);
}
return NO_ERROR;
} }
status_t VirtualDisplaySurface::connect(const sp<IProducerListener>& listener, status_t VirtualDisplaySurface::connect(const sp<IProducerListener>& listener,
@ -501,8 +531,6 @@ void VirtualDisplaySurface::updateQueueBufferOutput(
void VirtualDisplaySurface::resetPerFrameState() { void VirtualDisplaySurface::resetPerFrameState() {
mCompositionType = COMPOSITION_UNKNOWN; mCompositionType = COMPOSITION_UNKNOWN;
mSinkBufferWidth = 0;
mSinkBufferHeight = 0;
mFbFence = Fence::NO_FENCE; mFbFence = Fence::NO_FENCE;
mOutputFence = Fence::NO_FENCE; mOutputFence = Fence::NO_FENCE;
mOutputProducerSlot = -1; mOutputProducerSlot = -1;

View File

@ -87,6 +87,7 @@ public:
virtual status_t advanceFrame(); virtual status_t advanceFrame();
virtual void onFrameCommitted(); virtual void onFrameCommitted();
virtual void dump(String8& result) const; virtual void dump(String8& result) const;
virtual void resizeBuffers(const uint32_t w, const uint32_t h);
private: private:
enum Source {SOURCE_SINK = 0, SOURCE_SCRATCH = 1}; enum Source {SOURCE_SINK = 0, SOURCE_SCRATCH = 1};
@ -168,6 +169,10 @@ private:
// to the sink, we have to return the previous version. // to the sink, we have to return the previous version.
QueueBufferOutput mQueueBufferOutput; QueueBufferOutput mQueueBufferOutput;
// Details of the current sink buffer. These become valid when a buffer is
// dequeued from the sink, and are used when queueing the buffer.
uint32_t mSinkBufferWidth, mSinkBufferHeight;
// //
// Intra-frame state // Intra-frame state
// //
@ -176,10 +181,6 @@ private:
// Valid after prepareFrame(), cleared in onFrameCommitted. // Valid after prepareFrame(), cleared in onFrameCommitted.
CompositionType mCompositionType; CompositionType mCompositionType;
// Details of the current sink buffer. These become valid when a buffer is
// dequeued from the sink, and are used when queueing the buffer.
uint32_t mSinkBufferWidth, mSinkBufferHeight;
// mFbFence is the fence HWC should wait for before reading the framebuffer // mFbFence is the fence HWC should wait for before reading the framebuffer
// target buffer. // target buffer.
sp<Fence> mFbFence; sp<Fence> mFbFence;

View File

@ -1258,6 +1258,9 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
disp->setProjection(state.orientation, disp->setProjection(state.orientation,
state.viewport, state.frame); state.viewport, state.frame);
} }
if (state.width != draw[i].width || state.height != draw[i].height) {
disp->setDisplaySize(state.width, state.height);
}
} }
} }
} }
@ -1288,13 +1291,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
bqProducer, bqConsumer, state.displayName); bqProducer, bqConsumer, state.displayName);
dispSurface = vds; dispSurface = vds;
if (hwcDisplayId >= 0) { producer = vds;
producer = vds;
} else {
// There won't be any interaction with HWC for this virtual display,
// so the GLES driver can pass buffers directly to the sink.
producer = state.surface;
}
} }
} else { } else {
ALOGE_IF(state.surface!=NULL, ALOGE_IF(state.surface!=NULL,
@ -1992,6 +1989,16 @@ uint32_t SurfaceFlinger::setDisplayStateLocked(const DisplayState& s)
flags |= eDisplayTransactionNeeded; flags |= eDisplayTransactionNeeded;
} }
} }
if (what & DisplayState::eDisplaySizeChanged) {
if (disp.width != s.width) {
disp.width = s.width;
flags |= eDisplayTransactionNeeded;
}
if (disp.height != s.height) {
disp.height = s.height;
flags |= eDisplayTransactionNeeded;
}
}
} }
return flags; return flags;
} }
@ -2178,6 +2185,8 @@ void SurfaceFlinger::onInitializeDisplays() {
d.orientation = DisplayState::eOrientationDefault; d.orientation = DisplayState::eOrientationDefault;
d.frame.makeInvalid(); d.frame.makeInvalid();
d.viewport.makeInvalid(); d.viewport.makeInvalid();
d.width = 0;
d.height = 0;
displays.add(d); displays.add(d);
setTransactionState(state, displays, 0); setTransactionState(state, displays, 0);
setPowerModeInternal(getDisplayDevice(d.token), HWC_POWER_MODE_NORMAL); setPowerModeInternal(getDisplayDevice(d.token), HWC_POWER_MODE_NORMAL);
@ -3206,11 +3215,11 @@ int SurfaceFlinger::LayerVector::do_compare(const void* lhs,
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
SurfaceFlinger::DisplayDeviceState::DisplayDeviceState() SurfaceFlinger::DisplayDeviceState::DisplayDeviceState()
: type(DisplayDevice::DISPLAY_ID_INVALID) { : type(DisplayDevice::DISPLAY_ID_INVALID), width(0), height(0) {
} }
SurfaceFlinger::DisplayDeviceState::DisplayDeviceState(DisplayDevice::DisplayType type) SurfaceFlinger::DisplayDeviceState::DisplayDeviceState(DisplayDevice::DisplayType type)
: type(type), layerStack(DisplayDevice::NO_LAYER_STACK), orientation(0) { : type(type), layerStack(DisplayDevice::NO_LAYER_STACK), orientation(0), width(0), height(0) {
viewport.makeInvalid(); viewport.makeInvalid();
frame.makeInvalid(); frame.makeInvalid();
} }