Add DisplaySurface abstraction

DisplayDevice now has a DisplaySurface instead of using
FramebufferSurface directly. FramebufferSurface implements
DisplaySurface, and so does the new VirtualDisplaySurface class.
DisplayDevice now always has a surface, not just for virtual displays.

In this change VirtualDisplaySurface is just a stub; buffers still go
directly from GLES to the final consumer.

Bug: 8384764
Change-Id: I57cb668edbc6c37bfebda90b9222d435bf589f37
This commit is contained in:
Jesse Hall 2013-03-14 14:29:29 -07:00
parent 4c00cc1114
commit 99c7dbb249
10 changed files with 292 additions and 101 deletions

View File

@ -2,22 +2,22 @@ LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS) include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \ LOCAL_SRC_FILES:= \
Client.cpp \ Client.cpp \
DisplayDevice.cpp \ DisplayDevice.cpp \
EventThread.cpp \ EventThread.cpp \
FrameTracker.cpp \ FrameTracker.cpp \
Layer.cpp \ GLExtensions.cpp \
LayerDim.cpp \ Layer.cpp \
DisplayHardware/FramebufferSurface.cpp \ LayerDim.cpp \
DisplayHardware/HWComposer.cpp \ MessageQueue.cpp \
DisplayHardware/PowerHAL.cpp \ SurfaceFlinger.cpp \
GLExtensions.cpp \ SurfaceFlingerConsumer.cpp \
MessageQueue.cpp \ SurfaceTextureLayer.cpp \
SurfaceFlinger.cpp \ Transform.cpp \
SurfaceFlingerConsumer.cpp \ DisplayHardware/FramebufferSurface.cpp \
SurfaceTextureLayer.cpp \ DisplayHardware/HWComposer.cpp \
Transform.cpp \ DisplayHardware/PowerHAL.cpp \
DisplayHardware/VirtualDisplaySurface.cpp \
LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\" LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\"
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES

View File

@ -35,7 +35,7 @@
#include <hardware/gralloc.h> #include <hardware/gralloc.h>
#include "DisplayHardware/FramebufferSurface.h" #include "DisplayHardware/DisplaySurface.h"
#include "DisplayHardware/HWComposer.h" #include "DisplayHardware/HWComposer.h"
#include "clz.h" #include "clz.h"
@ -72,14 +72,12 @@ DisplayDevice::DisplayDevice(
DisplayType type, DisplayType type,
bool isSecure, bool isSecure,
const wp<IBinder>& displayToken, const wp<IBinder>& displayToken,
const sp<ANativeWindow>& nativeWindow, const sp<DisplaySurface>& displaySurface,
const sp<FramebufferSurface>& framebufferSurface,
EGLConfig config) EGLConfig config)
: mFlinger(flinger), : mFlinger(flinger),
mType(type), mHwcDisplayId(-1), mType(type), mHwcDisplayId(-1),
mDisplayToken(displayToken), mDisplayToken(displayToken),
mNativeWindow(nativeWindow), mDisplaySurface(displaySurface),
mFramebufferSurface(framebufferSurface),
mDisplay(EGL_NO_DISPLAY), mDisplay(EGL_NO_DISPLAY),
mSurface(EGL_NO_SURFACE), mSurface(EGL_NO_SURFACE),
mContext(EGL_NO_CONTEXT), mContext(EGL_NO_CONTEXT),
@ -92,6 +90,7 @@ DisplayDevice::DisplayDevice(
mLayerStack(NO_LAYER_STACK), mLayerStack(NO_LAYER_STACK),
mOrientation() mOrientation()
{ {
mNativeWindow = new Surface(mDisplaySurface->getIGraphicBufferProducer());
init(config); init(config);
} }
@ -183,10 +182,7 @@ uint32_t DisplayDevice::getPageFlipCount() const {
} }
status_t DisplayDevice::compositionComplete() const { status_t DisplayDevice::compositionComplete() const {
if (mFramebufferSurface == NULL) { return mDisplaySurface->compositionComplete();
return NO_ERROR;
}
return mFramebufferSurface->compositionComplete();
} }
void DisplayDevice::flip(const Region& dirty) const void DisplayDevice::flip(const Region& dirty) const
@ -209,45 +205,38 @@ void DisplayDevice::flip(const Region& dirty) const
} }
void DisplayDevice::swapBuffers(HWComposer& hwc) const { void DisplayDevice::swapBuffers(HWComposer& hwc) const {
EGLBoolean success = EGL_TRUE; // We need to call eglSwapBuffers() unless:
if (hwc.initCheck() != NO_ERROR) { // (a) there was no GLES composition this frame, or
// no HWC, we call eglSwapBuffers() // (b) we're using a legacy HWC with no framebuffer target support (in
success = eglSwapBuffers(mDisplay, mSurface); // which case HWComposer::commit() handles things).
} else { if (hwc.initCheck() != NO_ERROR ||
// We have a valid HWC, but not all displays can use it, in particular (hwc.hasGlesComposition(mHwcDisplayId) &&
// the virtual displays are on their own. hwc.supportsFramebufferTarget())) {
// TODO: HWC 1.2 will allow virtual displays EGLBoolean success = eglSwapBuffers(mDisplay, mSurface);
if (mType >= DisplayDevice::DISPLAY_VIRTUAL) { if (!success) {
// always call eglSwapBuffers() for virtual displays EGLint error = eglGetError();
success = eglSwapBuffers(mDisplay, mSurface); if (error == EGL_CONTEXT_LOST ||
} else if (hwc.supportsFramebufferTarget()) { mType == DisplayDevice::DISPLAY_PRIMARY) {
// as of hwc 1.1 we always call eglSwapBuffers if we have some LOG_ALWAYS_FATAL("eglSwapBuffers(%p, %p) failed with 0x%08x",
// GLES layers mDisplay, mSurface, error);
if (hwc.hasGlesComposition(mType)) { } else {
success = eglSwapBuffers(mDisplay, mSurface); ALOGE("eglSwapBuffers(%p, %p) failed with 0x%08x",
mDisplay, mSurface, error);
} }
} else {
// HWC doesn't have the framebuffer target, we don't call
// eglSwapBuffers(), since this is handled by HWComposer::commit().
} }
} }
if (!success) { status_t result = mDisplaySurface->advanceFrame();
EGLint error = eglGetError(); if (result != NO_ERROR) {
if (error == EGL_CONTEXT_LOST || ALOGE("[%s] failed pushing new frame to HWC: %d",
mType == DisplayDevice::DISPLAY_PRIMARY) { mDisplayName.string(), result);
LOG_ALWAYS_FATAL("eglSwapBuffers(%p, %p) failed with 0x%08x",
mDisplay, mSurface, error);
}
} }
} }
void DisplayDevice::onSwapBuffersCompleted(HWComposer& hwc) const { void DisplayDevice::onSwapBuffersCompleted(HWComposer& hwc) const {
if (hwc.initCheck() == NO_ERROR) { if (hwc.initCheck() == NO_ERROR) {
if (mFramebufferSurface != NULL) { int fd = hwc.getAndResetReleaseFenceFd(mType);
int fd = hwc.getAndResetReleaseFenceFd(mType); mDisplaySurface->setReleaseFenceFd(fd);
mFramebufferSurface->setReleaseFenceFd(fd);
}
} }
} }
@ -455,9 +444,7 @@ void DisplayDevice::dump(String8& result, char* buffer, size_t SIZE) const {
result.append(buffer); result.append(buffer);
String8 fbtargetDump; String8 surfaceDump;
if (mFramebufferSurface != NULL) { mDisplaySurface->dump(surfaceDump);
mFramebufferSurface->dump(fbtargetDump); result.append(surfaceDump);
result.append(fbtargetDump);
}
} }

View File

@ -37,7 +37,7 @@ struct ANativeWindow;
namespace android { namespace android {
class DisplayInfo; class DisplayInfo;
class FramebufferSurface; class DisplaySurface;
class Layer; class Layer;
class SurfaceFlinger; class SurfaceFlinger;
class HWComposer; class HWComposer;
@ -74,8 +74,7 @@ public:
DisplayType type, DisplayType type,
bool isSecure, bool isSecure,
const wp<IBinder>& displayToken, const wp<IBinder>& displayToken,
const sp<ANativeWindow>& nativeWindow, const sp<DisplaySurface>& displaySurface,
const sp<FramebufferSurface>& framebufferSurface,
EGLConfig config); EGLConfig config);
~DisplayDevice(); ~DisplayDevice();
@ -165,9 +164,7 @@ private:
// ANativeWindow this display is rendering into // ANativeWindow this display is rendering into
sp<ANativeWindow> mNativeWindow; sp<ANativeWindow> mNativeWindow;
sp<DisplaySurface> mDisplaySurface;
// set if mNativeWindow is a FramebufferSurface
sp<FramebufferSurface> mFramebufferSurface;
EGLDisplay mDisplay; EGLDisplay mDisplay;
EGLSurface mSurface; EGLSurface mSurface;

View File

@ -0,0 +1,68 @@
/*
* Copyright 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_SF_DISPLAY_SURFACE_H
#define ANDROID_SF_DISPLAY_SURFACE_H
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <utils/StrongPointer.h>
// ---------------------------------------------------------------------------
namespace android {
// ---------------------------------------------------------------------------
class IGraphicBufferProducer;
class String8;
class DisplaySurface : public virtual RefBase {
public:
virtual sp<IGraphicBufferProducer> getIGraphicBufferProducer() const = 0;
// Should be called when composition rendering is complete for a frame (but
// eglSwapBuffers hasn't necessarily been called). Required by certain
// older drivers for synchronization.
// TODO: Remove this when we drop support for HWC 1.0.
virtual status_t compositionComplete() = 0;
// Inform the surface that GLES composition is complete for this frame, and
// the surface should make sure that HWComposer has the correct buffer for
// this frame. Some implementations may only push a new buffer to
// HWComposer if GLES composition took place, others need to push a new
// buffer on every frame.
virtual status_t advanceFrame() = 0;
// setReleaseFenceFd stores a fence file descriptor that will signal when
// the current buffer is no longer being read. This fence will be returned
// to the producer when the current buffer is released by updateTexImage().
// Multiple fences can be set for a given buffer; they will be merged into
// a single union fence. The GLConsumer will close the file descriptor
// when finished with it.
virtual status_t setReleaseFenceFd(int fenceFd) = 0;
virtual void dump(String8& result) const = 0;
protected:
DisplaySurface() {}
virtual ~DisplaySurface() {}
};
// ---------------------------------------------------------------------------
} // namespace android
// ---------------------------------------------------------------------------
#endif // ANDROID_SF_DISPLAY_SURFACE_H

View File

@ -68,6 +68,17 @@ FramebufferSurface::FramebufferSurface(HWComposer& hwc, int disp) :
mBufferQueue->setDefaultMaxBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS); mBufferQueue->setDefaultMaxBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS);
} }
sp<IGraphicBufferProducer> FramebufferSurface::getIGraphicBufferProducer() const {
return getBufferQueue();
}
status_t FramebufferSurface::advanceFrame() {
// Once we remove FB HAL support, we can call nextBuffer() from here
// instead of using onFrameAvailable(). No real benefit, except it'll be
// more like VirtualDisplaySurface.
return NO_ERROR;
}
status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence) { status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence) {
Mutex::Autolock lock(mMutex); Mutex::Autolock lock(mMutex);
@ -147,7 +158,23 @@ status_t FramebufferSurface::compositionComplete()
return mHwc.fbCompositionComplete(); return mHwc.fbCompositionComplete();
} }
void FramebufferSurface::dump(String8& result) { // Since DisplaySurface and ConsumerBase both have a method with this
// signature, results will vary based on the static pointer type the caller is
// using:
// void dump(FrameBufferSurface* fbs, String8& s) {
// // calls FramebufferSurface::dump()
// fbs->dump(s);
//
// // calls ConsumerBase::dump() since it is non-virtual
// static_cast<ConsumerBase*>(fbs)->dump(s);
//
// // calls FramebufferSurface::dump() since it is virtual
// static_cast<DisplaySurface*>(fbs)->dump(s);
// }
// To make sure that all of these end up doing the same thing, we just redirect
// to ConsumerBase::dump() here. It will take the internal lock, and then call
// virtual dumpLocked(), which is where the real work happens.
void FramebufferSurface::dump(String8& result) const {
ConsumerBase::dump(result); ConsumerBase::dump(result);
} }

View File

@ -22,6 +22,8 @@
#include <gui/ConsumerBase.h> #include <gui/ConsumerBase.h>
#include "DisplaySurface.h"
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
namespace android { namespace android {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -32,23 +34,20 @@ class HWComposer;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
class FramebufferSurface : public ConsumerBase { class FramebufferSurface : public ConsumerBase,
public DisplaySurface {
public: public:
FramebufferSurface(HWComposer& hwc, int disp); FramebufferSurface(HWComposer& hwc, int disp);
status_t compositionComplete(); virtual sp<IGraphicBufferProducer> getIGraphicBufferProducer() const;
// TODO(jessehall): This overrides the non-virtual ConsumerBase version. virtual status_t compositionComplete();
// Will rework slightly in a following change. virtual status_t advanceFrame();
void dump(String8& result); virtual status_t setReleaseFenceFd(int fenceFd);
// setReleaseFenceFd stores a fence file descriptor that will signal when the // Implementation of DisplaySurface::dump(). Note that ConsumerBase also
// current buffer is no longer being read. This fence will be returned to // has a non-virtual dump() with the same signature.
// the producer when the current buffer is released by updateTexImage(). virtual void dump(String8& result) const;
// Multiple fences can be set for a given buffer; they will be merged into
// a single union fence. The GLConsumer will close the file descriptor
// when finished with it.
status_t setReleaseFenceFd(int fenceFd);
private: private:
virtual ~FramebufferSurface() { }; // this class cannot be overloaded virtual ~FramebufferSurface() { }; // this class cannot be overloaded

View File

@ -617,14 +617,14 @@ status_t HWComposer::prepare() {
} }
bool HWComposer::hasHwcComposition(int32_t id) const { bool HWComposer::hasHwcComposition(int32_t id) const {
if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) if (!mHwc || uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
return false; return false;
return mDisplayData[id].hasOvComp; return mDisplayData[id].hasOvComp;
} }
bool HWComposer::hasGlesComposition(int32_t id) const { bool HWComposer::hasGlesComposition(int32_t id) const {
if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) if (!mHwc || uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
return false; return true;
return mDisplayData[id].hasFbComp; return mDisplayData[id].hasFbComp;
} }

View File

@ -0,0 +1,60 @@
/*
* Copyright 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <gui/IGraphicBufferProducer.h>
#include "VirtualDisplaySurface.h"
// ---------------------------------------------------------------------------
namespace android {
// ---------------------------------------------------------------------------
VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int disp,
const sp<IGraphicBufferProducer>& sink, const String8& name)
: mHwc(hwc),
mDisplayId(disp),
mSink(sink),
mName(name)
{}
VirtualDisplaySurface::~VirtualDisplaySurface() {
}
sp<IGraphicBufferProducer> VirtualDisplaySurface::getIGraphicBufferProducer() const {
return mSink;
}
status_t VirtualDisplaySurface::compositionComplete() {
return NO_ERROR;
}
status_t VirtualDisplaySurface::advanceFrame() {
return NO_ERROR;
}
status_t VirtualDisplaySurface::setReleaseFenceFd(int fenceFd) {
if (fenceFd >= 0) {
ALOGW("[%s] unexpected release fence", mName.string());
close(fenceFd);
}
return NO_ERROR;
}
void VirtualDisplaySurface::dump(String8& result) const {
}
// ---------------------------------------------------------------------------
} // namespace android
// ---------------------------------------------------------------------------

View File

@ -0,0 +1,57 @@
/*
* Copyright 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H
#define ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H
#include <utils/String8.h>
#include "DisplaySurface.h"
// ---------------------------------------------------------------------------
namespace android {
// ---------------------------------------------------------------------------
class HWComposer;
class VirtualDisplaySurface : public DisplaySurface {
public:
VirtualDisplaySurface(HWComposer& hwc, int disp,
const sp<IGraphicBufferProducer>& sink,
const String8& name);
virtual sp<IGraphicBufferProducer> getIGraphicBufferProducer() const;
virtual status_t compositionComplete();
virtual status_t advanceFrame();
virtual status_t setReleaseFenceFd(int fenceFd);
virtual void dump(String8& result) const;
private:
virtual ~VirtualDisplaySurface();
// immutable after construction
HWComposer& mHwc;
int mDisplayId;
sp<IGraphicBufferProducer> mSink;
String8 mName;
};
// ---------------------------------------------------------------------------
} // namespace android
// ---------------------------------------------------------------------------
#endif // ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H

View File

@ -66,6 +66,7 @@
#include "DisplayHardware/FramebufferSurface.h" #include "DisplayHardware/FramebufferSurface.h"
#include "DisplayHardware/HWComposer.h" #include "DisplayHardware/HWComposer.h"
#include "DisplayHardware/VirtualDisplaySurface.h"
#define EGL_VERSION_HW_ANDROID 0x3143 #define EGL_VERSION_HW_ANDROID 0x3143
@ -501,11 +502,9 @@ status_t SurfaceFlinger::readyToRun()
createBuiltinDisplayLocked(type); createBuiltinDisplayLocked(type);
wp<IBinder> token = mBuiltinDisplays[i]; wp<IBinder> token = mBuiltinDisplays[i];
sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i);
sp<Surface> stc = new Surface(
static_cast< sp<IGraphicBufferProducer> >(fbs->getBufferQueue()));
sp<DisplayDevice> hw = new DisplayDevice(this, sp<DisplayDevice> hw = new DisplayDevice(this,
type, isSecure, token, stc, fbs, mEGLConfig); type, isSecure, token, new FramebufferSurface(*mHwc, i),
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
// for displays other than the main display, so we always // for displays other than the main display, so we always
@ -1174,10 +1173,14 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
if (draw.indexOfKey(curr.keyAt(i)) < 0) { if (draw.indexOfKey(curr.keyAt(i)) < 0) {
const DisplayDeviceState& state(curr[i]); const DisplayDeviceState& state(curr[i]);
sp<FramebufferSurface> fbs; sp<DisplaySurface> dispSurface;
sp<Surface> stc; if (state.isVirtualDisplay()) {
if (!state.isVirtualDisplay()) { if (state.surface != NULL) {
dispSurface = new VirtualDisplaySurface(
*mHwc, state.type, state.surface,
state.displayName);
}
} else {
ALOGE_IF(state.surface!=NULL, ALOGE_IF(state.surface!=NULL,
"adding a supported display, but rendering " "adding a supported display, but rendering "
"surface is provided (%p), ignoring it", "surface is provided (%p), ignoring it",
@ -1185,21 +1188,14 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
// for supported (by hwc) displays we provide our // for supported (by hwc) displays we provide our
// own rendering surface // own rendering surface
fbs = new FramebufferSurface(*mHwc, state.type); dispSurface = new FramebufferSurface(*mHwc, state.type);
stc = new Surface(
static_cast< sp<IGraphicBufferProducer> >(
fbs->getBufferQueue()));
} else {
if (state.surface != NULL) {
stc = new Surface(state.surface);
}
} }
const wp<IBinder>& display(curr.keyAt(i)); const wp<IBinder>& display(curr.keyAt(i));
if (stc != NULL) { if (dispSurface != NULL) {
sp<DisplayDevice> hw = new DisplayDevice(this, sp<DisplayDevice> hw = new DisplayDevice(this,
state.type, state.isSecure, display, stc, fbs, state.type, state.isSecure, display,
mEGLConfig); 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);