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)
LOCAL_SRC_FILES:= \
Client.cpp \
DisplayDevice.cpp \
EventThread.cpp \
FrameTracker.cpp \
Layer.cpp \
LayerDim.cpp \
DisplayHardware/FramebufferSurface.cpp \
DisplayHardware/HWComposer.cpp \
DisplayHardware/PowerHAL.cpp \
GLExtensions.cpp \
MessageQueue.cpp \
SurfaceFlinger.cpp \
SurfaceFlingerConsumer.cpp \
SurfaceTextureLayer.cpp \
Transform.cpp \
Client.cpp \
DisplayDevice.cpp \
EventThread.cpp \
FrameTracker.cpp \
GLExtensions.cpp \
Layer.cpp \
LayerDim.cpp \
MessageQueue.cpp \
SurfaceFlinger.cpp \
SurfaceFlingerConsumer.cpp \
SurfaceTextureLayer.cpp \
Transform.cpp \
DisplayHardware/FramebufferSurface.cpp \
DisplayHardware/HWComposer.cpp \
DisplayHardware/PowerHAL.cpp \
DisplayHardware/VirtualDisplaySurface.cpp \
LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\"
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES

View File

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

View File

@ -37,7 +37,7 @@ struct ANativeWindow;
namespace android {
class DisplayInfo;
class FramebufferSurface;
class DisplaySurface;
class Layer;
class SurfaceFlinger;
class HWComposer;
@ -74,8 +74,7 @@ public:
DisplayType type,
bool isSecure,
const wp<IBinder>& displayToken,
const sp<ANativeWindow>& nativeWindow,
const sp<FramebufferSurface>& framebufferSurface,
const sp<DisplaySurface>& displaySurface,
EGLConfig config);
~DisplayDevice();
@ -165,9 +164,7 @@ private:
// ANativeWindow this display is rendering into
sp<ANativeWindow> mNativeWindow;
// set if mNativeWindow is a FramebufferSurface
sp<FramebufferSurface> mFramebufferSurface;
sp<DisplaySurface> mDisplaySurface;
EGLDisplay mDisplay;
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);
}
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) {
Mutex::Autolock lock(mMutex);
@ -147,7 +158,23 @@ status_t FramebufferSurface::compositionComplete()
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);
}

View File

@ -22,6 +22,8 @@
#include <gui/ConsumerBase.h>
#include "DisplaySurface.h"
// ---------------------------------------------------------------------------
namespace android {
// ---------------------------------------------------------------------------
@ -32,23 +34,20 @@ class HWComposer;
// ---------------------------------------------------------------------------
class FramebufferSurface : public ConsumerBase {
class FramebufferSurface : public ConsumerBase,
public DisplaySurface {
public:
FramebufferSurface(HWComposer& hwc, int disp);
status_t compositionComplete();
virtual sp<IGraphicBufferProducer> getIGraphicBufferProducer() const;
// TODO(jessehall): This overrides the non-virtual ConsumerBase version.
// Will rework slightly in a following change.
void dump(String8& result);
virtual status_t compositionComplete();
virtual status_t advanceFrame();
virtual status_t setReleaseFenceFd(int fenceFd);
// 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.
status_t setReleaseFenceFd(int fenceFd);
// Implementation of DisplaySurface::dump(). Note that ConsumerBase also
// has a non-virtual dump() with the same signature.
virtual void dump(String8& result) const;
private:
virtual ~FramebufferSurface() { }; // this class cannot be overloaded

View File

@ -617,14 +617,14 @@ status_t HWComposer::prepare() {
}
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 mDisplayData[id].hasOvComp;
}
bool HWComposer::hasGlesComposition(int32_t id) const {
if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
return false;
if (!mHwc || uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
return true;
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/HWComposer.h"
#include "DisplayHardware/VirtualDisplaySurface.h"
#define EGL_VERSION_HW_ANDROID 0x3143
@ -501,11 +502,9 @@ status_t SurfaceFlinger::readyToRun()
createBuiltinDisplayLocked(type);
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,
type, isSecure, token, stc, fbs, mEGLConfig);
type, isSecure, token, new FramebufferSurface(*mHwc, i),
mEGLConfig);
if (i > DisplayDevice::DISPLAY_PRIMARY) {
// FIXME: currently we don't get blank/unblank requests
// 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) {
const DisplayDeviceState& state(curr[i]);
sp<FramebufferSurface> fbs;
sp<Surface> stc;
if (!state.isVirtualDisplay()) {
sp<DisplaySurface> dispSurface;
if (state.isVirtualDisplay()) {
if (state.surface != NULL) {
dispSurface = new VirtualDisplaySurface(
*mHwc, state.type, state.surface,
state.displayName);
}
} else {
ALOGE_IF(state.surface!=NULL,
"adding a supported display, but rendering "
"surface is provided (%p), ignoring it",
@ -1185,21 +1188,14 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
// for supported (by hwc) displays we provide our
// own rendering surface
fbs = new FramebufferSurface(*mHwc, state.type);
stc = new Surface(
static_cast< sp<IGraphicBufferProducer> >(
fbs->getBufferQueue()));
} else {
if (state.surface != NULL) {
stc = new Surface(state.surface);
}
dispSurface = new FramebufferSurface(*mHwc, state.type);
}
const wp<IBinder>& display(curr.keyAt(i));
if (stc != NULL) {
if (dispSurface != NULL) {
sp<DisplayDevice> hw = new DisplayDevice(this,
state.type, state.isSecure, display, stc, fbs,
mEGLConfig);
state.type, state.isSecure, display,
dispSurface, mEGLConfig);
hw->setLayerStack(state.layerStack);
hw->setProjection(state.orientation,
state.viewport, state.frame);