add support hwc 1.1
Bug: 7124069 Change-Id: I53d705105c4ad8954d3f50ee4f4c8b7ec936b871
This commit is contained in:
parent
cde87a3b9d
commit
da27af9832
|
@ -183,6 +183,32 @@ void DisplayDevice::flip(const Region& dirty) const
|
|||
mPageFlipCount++;
|
||||
}
|
||||
|
||||
void DisplayDevice::swapBuffers(HWComposer& hwc) const {
|
||||
if (hwc.initCheck() != NO_ERROR) {
|
||||
// no HWC, we call eglSwapBuffers()
|
||||
eglSwapBuffers(mDisplay, mSurface);
|
||||
} else {
|
||||
if (hwc.hasGlesComposition(mType)) {
|
||||
if (hwc.supportsFramebufferTarget() ||
|
||||
mType >= DisplayDevice::DISPLAY_VIRTUAL) {
|
||||
// as of hwc 1.1 we always call eglSwapBuffers, however,
|
||||
// on older versions of HWC, we need to call it only on
|
||||
// virtual displays
|
||||
eglSwapBuffers(mDisplay, mSurface);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DisplayDevice::onSwapBuffersCompleted(HWComposer& hwc) const {
|
||||
if (hwc.initCheck() == NO_ERROR) {
|
||||
if (hwc.supportsFramebufferTarget()) {
|
||||
int fd = hwc.getAndResetReleaseFenceFd(mType);
|
||||
mFramebufferSurface->setReleaseFenceFd(fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t DisplayDevice::getFlags() const
|
||||
{
|
||||
return mFlags;
|
||||
|
|
|
@ -40,6 +40,7 @@ class DisplayInfo;
|
|||
class FramebufferSurface;
|
||||
class LayerBase;
|
||||
class SurfaceFlinger;
|
||||
class HWComposer;
|
||||
|
||||
class DisplayDevice : public LightRefBase<DisplayDevice>
|
||||
{
|
||||
|
@ -106,8 +107,12 @@ public:
|
|||
int32_t getHwcDisplayId() const { return mHwcDisplayId; }
|
||||
const wp<IBinder>& getDisplayToken() const { return mDisplayToken; }
|
||||
|
||||
void swapBuffers(HWComposer& hwc) const;
|
||||
status_t compositionComplete() const;
|
||||
|
||||
// called after h/w composer has completed its set() call
|
||||
void onSwapBuffersCompleted(HWComposer& hwc) const;
|
||||
|
||||
Rect getBounds() const {
|
||||
return Rect(mDisplayWidth, mDisplayHeight);
|
||||
}
|
||||
|
|
|
@ -74,15 +74,13 @@ FramebufferSurface::FramebufferSurface(HWComposer& hwc) :
|
|||
mBufferQueue->setDefaultMaxBufferCount(NUM_FRAME_BUFFERS);
|
||||
}
|
||||
|
||||
status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>* buffer) {
|
||||
status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence) {
|
||||
Mutex::Autolock lock(mMutex);
|
||||
|
||||
BufferQueue::BufferItem item;
|
||||
status_t err = acquireBufferLocked(&item);
|
||||
if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
|
||||
if (buffer != NULL) {
|
||||
*buffer = mCurrentBuffer;
|
||||
}
|
||||
outBuffer = mCurrentBuffer;
|
||||
return NO_ERROR;
|
||||
} else if (err != NO_ERROR) {
|
||||
ALOGE("error acquiring buffer: %s (%d)", strerror(-err), err);
|
||||
|
@ -107,32 +105,24 @@ status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>* buffer) {
|
|||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
mCurrentBufferSlot = item.mBuf;
|
||||
mCurrentBuffer = mSlots[mCurrentBufferSlot].mGraphicBuffer;
|
||||
if (item.mFence != NULL) {
|
||||
item.mFence->wait(Fence::TIMEOUT_NEVER);
|
||||
}
|
||||
|
||||
if (buffer != NULL) {
|
||||
*buffer = mCurrentBuffer;
|
||||
}
|
||||
|
||||
outFence = item.mFence;
|
||||
outBuffer = mCurrentBuffer;
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
// Overrides ConsumerBase::onFrameAvailable(), does not call base class impl.
|
||||
void FramebufferSurface::onFrameAvailable() {
|
||||
// XXX: The following code is here temporarily as part of the transition
|
||||
// away from the framebuffer HAL.
|
||||
sp<GraphicBuffer> buf;
|
||||
status_t err = nextBuffer(&buf);
|
||||
sp<Fence> acquireFence;
|
||||
status_t err = nextBuffer(buf, acquireFence);
|
||||
if (err != NO_ERROR) {
|
||||
ALOGE("error latching next FramebufferSurface buffer: %s (%d)",
|
||||
ALOGE("error latching nnext FramebufferSurface buffer: %s (%d)",
|
||||
strerror(-err), err);
|
||||
return;
|
||||
}
|
||||
err = mHwc.fbPost(buf->handle);
|
||||
err = mHwc.fbPost(0, acquireFence, buf); // FIXME: use real display id
|
||||
if (err != NO_ERROR) {
|
||||
ALOGE("error posting framebuffer: %d", err);
|
||||
}
|
||||
|
@ -145,6 +135,19 @@ void FramebufferSurface::freeBufferLocked(int slotIndex) {
|
|||
}
|
||||
}
|
||||
|
||||
status_t FramebufferSurface::setReleaseFenceFd(int fenceFd) {
|
||||
status_t err = NO_ERROR;
|
||||
if (fenceFd >= 0) {
|
||||
sp<Fence> fence(new Fence(fenceFd));
|
||||
if (mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT) {
|
||||
status_t err = addReleaseFence(mCurrentBufferSlot, fence);
|
||||
ALOGE_IF(err, "setReleaseFenceFd: failed to add the fence: %s (%d)",
|
||||
strerror(-err), err);
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
status_t FramebufferSurface::setUpdateRectangle(const Rect& r)
|
||||
{
|
||||
return INVALID_OPERATION;
|
||||
|
|
|
@ -44,10 +44,13 @@ public:
|
|||
|
||||
virtual void dump(String8& result);
|
||||
|
||||
// nextBuffer waits for and then latches the next buffer from the
|
||||
// BufferQueue and releases the previously latched buffer to the
|
||||
// BufferQueue. The new buffer is returned in the 'buffer' argument.
|
||||
status_t nextBuffer(sp<GraphicBuffer>* buffer);
|
||||
// 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 SurfaceTexture will close the file descriptor
|
||||
// when finished with it.
|
||||
status_t setReleaseFenceFd(int fenceFd);
|
||||
|
||||
private:
|
||||
virtual ~FramebufferSurface() { }; // this class cannot be overloaded
|
||||
|
@ -55,6 +58,11 @@ private:
|
|||
virtual void onFrameAvailable();
|
||||
virtual void freeBufferLocked(int slotIndex);
|
||||
|
||||
// nextBuffer waits for and then latches the next buffer from the
|
||||
// BufferQueue and releases the previously latched buffer to the
|
||||
// BufferQueue. The new buffer is returned in the 'buffer' argument.
|
||||
status_t nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence);
|
||||
|
||||
// mCurrentBufferIndex is the slot index of the current buffer or
|
||||
// INVALID_BUFFER_SLOT to indicate that either there is no current buffer
|
||||
// or the buffer is not associated with a slot.
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <sys/types.h>
|
||||
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/misc.h>
|
||||
#include <utils/String8.h>
|
||||
#include <utils/Thread.h>
|
||||
#include <utils/Trace.h>
|
||||
|
@ -43,6 +44,7 @@
|
|||
#include "LayerBase.h"
|
||||
#include "HWComposer.h"
|
||||
#include "SurfaceFlinger.h"
|
||||
#include <utils/CallStack.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
|
@ -111,6 +113,14 @@ HWComposer::HWComposer(
|
|||
loadFbHalModule();
|
||||
loadHwcModule();
|
||||
|
||||
if (mFbDev && mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
|
||||
// close FB HAL if we don't needed it.
|
||||
// FIXME: this is temporary until we're not forced to open FB HAL
|
||||
// before HWC.
|
||||
framebuffer_close(mFbDev);
|
||||
mFbDev = NULL;
|
||||
}
|
||||
|
||||
// If we have no HWC, or a pre-1.1 HWC, an FB dev is mandatory.
|
||||
if ((!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
|
||||
&& !mFbDev) {
|
||||
|
@ -310,7 +320,7 @@ static const uint32_t DISPLAY_ATTRIBUTES[] = {
|
|||
#define ANDROID_DENSITY_XHIGH 320
|
||||
|
||||
void HWComposer::queryDisplayProperties(int disp) {
|
||||
ALOG_ASSERT(mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1));
|
||||
LOG_ALWAYS_FATAL_IF(!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1));
|
||||
|
||||
// use zero as default value for unspecified attributes
|
||||
int32_t values[NUM_DISPLAY_ATTRIBUTES - 1];
|
||||
|
@ -319,7 +329,11 @@ void HWComposer::queryDisplayProperties(int disp) {
|
|||
uint32_t config;
|
||||
size_t numConfigs = 1;
|
||||
status_t err = mHwc->getDisplayConfigs(mHwc, disp, &config, &numConfigs);
|
||||
LOG_ALWAYS_FATAL_IF(err, "getDisplayAttributes failed (%s)", strerror(-err));
|
||||
|
||||
if (err == NO_ERROR) {
|
||||
ALOGD("config=%d, numConfigs=%d, NUM_DISPLAY_ATTRIBUTES=%d",
|
||||
config, numConfigs, NUM_DISPLAY_ATTRIBUTES);
|
||||
mHwc->getDisplayAttributes(mHwc, disp, config, DISPLAY_ATTRIBUTES,
|
||||
values);
|
||||
}
|
||||
|
@ -343,8 +357,8 @@ void HWComposer::queryDisplayProperties(int disp) {
|
|||
mDisplayData[disp].ydpi = values[i] / 1000.0f;
|
||||
break;
|
||||
default:
|
||||
ALOG_ASSERT(false, "unknown display attribute %#x",
|
||||
DISPLAY_ATTRIBUTES[i]);
|
||||
ALOG_ASSERT(false, "unknown display attribute[%d] %#x",
|
||||
i, DISPLAY_ATTRIBUTES[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -439,13 +453,35 @@ status_t HWComposer::createWorkList(int32_t id, size_t numLayers) {
|
|||
|
||||
if (mHwc) {
|
||||
DisplayData& disp(mDisplayData[id]);
|
||||
if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
|
||||
// we need space for the HWC_FRAMEBUFFER_TARGET
|
||||
numLayers++;
|
||||
}
|
||||
if (disp.capacity < numLayers || disp.list == NULL) {
|
||||
const size_t size = sizeof(hwc_display_contents_1_t)
|
||||
size_t size = sizeof(hwc_display_contents_1_t)
|
||||
+ numLayers * sizeof(hwc_layer_1_t);
|
||||
free(disp.list);
|
||||
disp.list = (hwc_display_contents_1_t*)malloc(size);
|
||||
disp.capacity = numLayers;
|
||||
}
|
||||
if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
|
||||
disp.framebufferTarget = &disp.list->hwLayers[numLayers - 1];
|
||||
memset(disp.framebufferTarget, 0, sizeof(hwc_layer_1_t));
|
||||
const hwc_rect_t r = { 0, 0, disp.width, disp.height };
|
||||
disp.framebufferTarget->compositionType = HWC_FRAMEBUFFER_TARGET;
|
||||
disp.framebufferTarget->hints = 0;
|
||||
disp.framebufferTarget->flags = 0;
|
||||
disp.framebufferTarget->handle = disp.fbTargetHandle;
|
||||
disp.framebufferTarget->transform = 0;
|
||||
disp.framebufferTarget->blending = HWC_BLENDING_PREMULT;
|
||||
disp.framebufferTarget->sourceCrop = r;
|
||||
disp.framebufferTarget->displayFrame = r;
|
||||
disp.framebufferTarget->visibleRegionScreen.numRects = 1;
|
||||
disp.framebufferTarget->visibleRegionScreen.rects =
|
||||
&disp.framebufferTarget->displayFrame;
|
||||
disp.framebufferTarget->acquireFenceFd = -1;
|
||||
disp.framebufferTarget->releaseFenceFd = -1;
|
||||
}
|
||||
disp.list->retireFenceFd = -1;
|
||||
disp.list->flags = HWC_GEOMETRY_CHANGED;
|
||||
disp.list->numHwLayers = numLayers;
|
||||
|
@ -453,9 +489,46 @@ status_t HWComposer::createWorkList(int32_t id, size_t numLayers) {
|
|||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t HWComposer::setFramebufferTarget(int32_t id,
|
||||
const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buf) {
|
||||
if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {
|
||||
return BAD_INDEX;
|
||||
}
|
||||
DisplayData& disp(mDisplayData[id]);
|
||||
if (!disp.framebufferTarget) {
|
||||
// this should never happen, but apparently eglCreateWindowSurface()
|
||||
// triggers a SurfaceTextureClient::queueBuffer() on some
|
||||
// devices (!?) -- log and ignore.
|
||||
ALOGE("HWComposer: framebufferTarget is null");
|
||||
CallStack stack;
|
||||
stack.update();
|
||||
stack.dump("");
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
int acquireFenceFd = -1;
|
||||
if (acquireFence != NULL) {
|
||||
acquireFenceFd = acquireFence->dup();
|
||||
}
|
||||
|
||||
// ALOGD("fbPost: handle=%p, fence=%d", buf->handle, acquireFenceFd);
|
||||
disp.fbTargetHandle = buf->handle;
|
||||
disp.framebufferTarget->handle = disp.fbTargetHandle;
|
||||
disp.framebufferTarget->acquireFenceFd = acquireFenceFd;
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t HWComposer::prepare() {
|
||||
for (size_t i=0 ; i<mNumDisplays ; i++) {
|
||||
mLists[i] = mDisplayData[i].list;
|
||||
DisplayData& disp(mDisplayData[i]);
|
||||
if (disp.framebufferTarget) {
|
||||
// make sure to reset the type to HWC_FRAMEBUFFER_TARGET
|
||||
// DO NOT reset the handle field to NULL, because it's possible
|
||||
// that we have nothing to redraw (eg: eglSwapBuffers() not called)
|
||||
// in which case, we should continue to use the same buffer.
|
||||
disp.framebufferTarget->compositionType = HWC_FRAMEBUFFER_TARGET;
|
||||
}
|
||||
mLists[i] = disp.list;
|
||||
if (mLists[i]) {
|
||||
if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_2)) {
|
||||
mLists[i]->outbuf = NULL;
|
||||
|
@ -472,6 +545,8 @@ status_t HWComposer::prepare() {
|
|||
}
|
||||
|
||||
int err = mHwc->prepare(mHwc, mNumDisplays, mLists);
|
||||
ALOGE_IF(err, "HWComposer: prepare failed (%s)", strerror(-err));
|
||||
|
||||
if (err == NO_ERROR) {
|
||||
// here we're just making sure that "skip" layers are set
|
||||
// to HWC_FRAMEBUFFER and we're also counting how many layers
|
||||
|
@ -483,6 +558,10 @@ status_t HWComposer::prepare() {
|
|||
if (disp.list) {
|
||||
for (size_t i=0 ; i<disp.list->numHwLayers ; i++) {
|
||||
hwc_layer_1_t& l = disp.list->hwLayers[i];
|
||||
|
||||
//ALOGD("prepare: %d, type=%d, handle=%p",
|
||||
// i, l.compositionType, l.handle);
|
||||
|
||||
if (l.flags & HWC_SKIP_LAYER) {
|
||||
l.compositionType = HWC_FRAMEBUFFER;
|
||||
}
|
||||
|
@ -511,6 +590,21 @@ bool HWComposer::hasGlesComposition(int32_t id) const {
|
|||
return mDisplayData[id].hasFbComp;
|
||||
}
|
||||
|
||||
int HWComposer::getAndResetReleaseFenceFd(int32_t id) {
|
||||
if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
|
||||
return BAD_INDEX;
|
||||
|
||||
int fd = INVALID_OPERATION;
|
||||
if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
|
||||
const DisplayData& disp(mDisplayData[id]);
|
||||
if (disp.framebufferTarget) {
|
||||
fd = disp.framebufferTarget->releaseFenceFd;
|
||||
disp.framebufferTarget->releaseFenceFd = -1;
|
||||
}
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
status_t HWComposer::commit() {
|
||||
int err = NO_ERROR;
|
||||
if (mHwc) {
|
||||
|
@ -553,38 +647,43 @@ status_t HWComposer::acquire() const {
|
|||
return NO_ERROR;
|
||||
}
|
||||
|
||||
size_t HWComposer::getNumLayers(int32_t id) const {
|
||||
if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {
|
||||
return 0;
|
||||
}
|
||||
return (mHwc && mDisplayData[id].list) ?
|
||||
mDisplayData[id].list->numHwLayers : 0;
|
||||
}
|
||||
|
||||
int HWComposer::getVisualID() const {
|
||||
if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
|
||||
return HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
|
||||
// FIXME: temporary hack until HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED
|
||||
// is supported by the implementation. we can only be in this case
|
||||
// if we have HWC 1.1
|
||||
return HAL_PIXEL_FORMAT_RGBA_8888;
|
||||
//return HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
|
||||
} else {
|
||||
return mFbDev->format;
|
||||
}
|
||||
}
|
||||
|
||||
int HWComposer::fbPost(buffer_handle_t buffer) {
|
||||
if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) {
|
||||
return mFbDev->post(mFbDev, buffer);
|
||||
bool HWComposer::supportsFramebufferTarget() const {
|
||||
return (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1));
|
||||
}
|
||||
|
||||
int HWComposer::fbPost(int32_t id,
|
||||
const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buffer) {
|
||||
if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
|
||||
return setFramebufferTarget(id, acquireFence, buffer);
|
||||
} else {
|
||||
if (acquireFence != NULL) {
|
||||
acquireFence->wait(Fence::TIMEOUT_NEVER);
|
||||
}
|
||||
return mFbDev->post(mFbDev, buffer->handle);
|
||||
}
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
int HWComposer::fbCompositionComplete() {
|
||||
if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) {
|
||||
if (mFbDev->compositionComplete) {
|
||||
return mFbDev->compositionComplete(mFbDev);
|
||||
} else {
|
||||
return INVALID_OPERATION;
|
||||
}
|
||||
if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
|
||||
return NO_ERROR;
|
||||
|
||||
if (mFbDev->compositionComplete) {
|
||||
return mFbDev->compositionComplete(mFbDev);
|
||||
} else {
|
||||
return INVALID_OPERATION;
|
||||
}
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
void HWComposer::fbDump(String8& result) {
|
||||
|
@ -596,7 +695,6 @@ void HWComposer::fbDump(String8& result) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Helper template to implement a concrete HWCLayer
|
||||
* This holds the pointer to the concrete hwc layer type
|
||||
|
@ -733,7 +831,22 @@ HWComposer::LayerListIterator HWComposer::begin(int32_t id) {
|
|||
* returns an iterator on the end of the layer list
|
||||
*/
|
||||
HWComposer::LayerListIterator HWComposer::end(int32_t id) {
|
||||
return getLayerIterator(id, getNumLayers(id));
|
||||
size_t numLayers = 0;
|
||||
if (uint32_t(id) <= 31 && mAllocatedDisplayIDs.hasBit(id)) {
|
||||
const DisplayData& disp(mDisplayData[id]);
|
||||
if (mHwc && disp.list) {
|
||||
numLayers = disp.list->numHwLayers;
|
||||
if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
|
||||
// with HWC 1.1, the last layer is always the HWC_FRAMEBUFFER_TARGET,
|
||||
// which we ignore when iterating through the layer list.
|
||||
ALOGE_IF(!numLayers, "mDisplayData[%d].list->numHwLayers is 0", id);
|
||||
if (numLayers) {
|
||||
numLayers--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return getLayerIterator(id, numLayers);
|
||||
}
|
||||
|
||||
void HWComposer::dump(String8& result, char* buffer, size_t SIZE,
|
||||
|
@ -747,27 +860,47 @@ void HWComposer::dump(String8& result, char* buffer, size_t SIZE,
|
|||
result.appendFormat(" id=%d, numHwLayers=%u, flags=%08x\n",
|
||||
i, disp.list->numHwLayers, disp.list->flags);
|
||||
result.append(
|
||||
" type | handle | hints | flags | tr | blend | format | source crop | frame name \n"
|
||||
"----------+----------+----------+----------+----+-------+----------+---------------------------+--------------------------------\n");
|
||||
// " ________ | ________ | ________ | ________ | __ | _____ | ________ | [_____,_____,_____,_____] | [_____,_____,_____,_____]
|
||||
" type | handle | hints | flags | tr | blend | format | source crop | frame name \n"
|
||||
"------------+----------+----------+----------+----+-------+----------+---------------------------+--------------------------------\n");
|
||||
// " __________ | ________ | ________ | ________ | __ | _____ | ________ | [_____,_____,_____,_____] | [_____,_____,_____,_____]
|
||||
for (size_t i=0 ; i<disp.list->numHwLayers ; i++) {
|
||||
const hwc_layer_1_t&l = disp.list->hwLayers[i];
|
||||
const sp<LayerBase> layer(visibleLayersSortedByZ[i]);
|
||||
int32_t format = -1;
|
||||
if (layer->getLayer() != NULL) {
|
||||
const sp<GraphicBuffer>& buffer(
|
||||
String8 name("unknown");
|
||||
if (i < visibleLayersSortedByZ.size()) {
|
||||
const sp<LayerBase>& layer(visibleLayersSortedByZ[i]);
|
||||
if (layer->getLayer() != NULL) {
|
||||
const sp<GraphicBuffer>& buffer(
|
||||
layer->getLayer()->getActiveBuffer());
|
||||
if (buffer != NULL) {
|
||||
format = buffer->getPixelFormat();
|
||||
if (buffer != NULL) {
|
||||
format = buffer->getPixelFormat();
|
||||
}
|
||||
}
|
||||
name = layer->getName();
|
||||
}
|
||||
|
||||
int type = l.compositionType;
|
||||
if (type == HWC_FRAMEBUFFER_TARGET) {
|
||||
name = "HWC_FRAMEBUFFER_TARGET";
|
||||
format = disp.format;
|
||||
}
|
||||
|
||||
static char const* compositionTypeName[] = {
|
||||
"GLES",
|
||||
"HWC",
|
||||
"BACKGROUND",
|
||||
"FB TARGET",
|
||||
"UNKNOWN"};
|
||||
if (type >= NELEM(compositionTypeName))
|
||||
type = NELEM(compositionTypeName) - 1;
|
||||
|
||||
result.appendFormat(
|
||||
" %8s | %08x | %08x | %08x | %02x | %05x | %08x | [%5d,%5d,%5d,%5d] | [%5d,%5d,%5d,%5d] %s\n",
|
||||
l.compositionType ? "OVERLAY" : "FB",
|
||||
" %10s | %08x | %08x | %08x | %02x | %05x | %08x | [%5d,%5d,%5d,%5d] | [%5d,%5d,%5d,%5d] %s\n",
|
||||
compositionTypeName[type],
|
||||
intptr_t(l.handle), l.hints, l.flags, l.transform, l.blending, format,
|
||||
l.sourceCrop.left, l.sourceCrop.top, l.sourceCrop.right, l.sourceCrop.bottom,
|
||||
l.displayFrame.left, l.displayFrame.top, l.displayFrame.right, l.displayFrame.bottom,
|
||||
layer->getName().string());
|
||||
name.string());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ extern "C" int clock_nanosleep(clockid_t clock_id, int flags,
|
|||
|
||||
struct hwc_composer_device_1;
|
||||
struct hwc_display_contents_1;
|
||||
struct hwc_layer_1;
|
||||
struct hwc_procs;
|
||||
struct framebuffer_device_t;
|
||||
|
||||
|
@ -43,6 +44,7 @@ namespace android {
|
|||
// ---------------------------------------------------------------------------
|
||||
|
||||
class GraphicBuffer;
|
||||
class Fence;
|
||||
class LayerBase;
|
||||
class Region;
|
||||
class String8;
|
||||
|
@ -97,12 +99,18 @@ public:
|
|||
// create a work list for numLayers layer. sets HWC_GEOMETRY_CHANGED.
|
||||
status_t createWorkList(int32_t id, size_t numLayers);
|
||||
|
||||
bool supportsFramebufferTarget() const;
|
||||
|
||||
// does this display have layers handled by HWC
|
||||
bool hasHwcComposition(int32_t id) const;
|
||||
|
||||
// does this display have layers handled by GLES
|
||||
bool hasGlesComposition(int32_t id) const;
|
||||
|
||||
// get the releaseFence file descriptor for the given display
|
||||
// the release fence is only valid after commit()
|
||||
int getAndResetReleaseFenceFd(int32_t id);
|
||||
|
||||
// needed forward declarations
|
||||
class LayerListIterator;
|
||||
|
||||
|
@ -111,7 +119,7 @@ public:
|
|||
int getVisualID() const;
|
||||
|
||||
// Forwarding to FB HAL for pre-HWC-1.1 code (see FramebufferSurface).
|
||||
int fbPost(buffer_handle_t buffer);
|
||||
int fbPost(int32_t id, const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buf);
|
||||
int fbCompositionComplete();
|
||||
void fbDump(String8& result);
|
||||
|
||||
|
@ -253,7 +261,6 @@ private:
|
|||
void loadFbHalModule();
|
||||
|
||||
LayerListIterator getLayerIterator(int32_t id, size_t index);
|
||||
size_t getNumLayers(int32_t id) const;
|
||||
|
||||
struct cb_context;
|
||||
|
||||
|
@ -269,10 +276,15 @@ private:
|
|||
|
||||
void queryDisplayProperties(int disp);
|
||||
|
||||
status_t setFramebufferTarget(int32_t id,
|
||||
const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buf);
|
||||
|
||||
|
||||
struct DisplayData {
|
||||
DisplayData() : xdpi(0), ydpi(0), refresh(0),
|
||||
hasFbComp(false), hasOvComp(false),
|
||||
capacity(0), list(NULL) { }
|
||||
capacity(0), list(NULL),
|
||||
framebufferTarget(NULL), fbTargetHandle(NULL) { }
|
||||
~DisplayData() {
|
||||
free(list);
|
||||
}
|
||||
|
@ -286,6 +298,8 @@ private:
|
|||
bool hasOvComp;
|
||||
size_t capacity;
|
||||
hwc_display_contents_1* list;
|
||||
hwc_layer_1* framebufferTarget;
|
||||
buffer_handle_t fbTargetHandle;
|
||||
};
|
||||
|
||||
sp<SurfaceFlinger> mFlinger;
|
||||
|
|
|
@ -523,6 +523,10 @@ void Layer::onPostComposition() {
|
|||
}
|
||||
}
|
||||
|
||||
bool Layer::isVisible() const {
|
||||
return LayerBaseClient::isVisible() && (mActiveBuffer != NULL);
|
||||
}
|
||||
|
||||
Region Layer::latchBuffer(bool& recomputeVisibleRegions)
|
||||
{
|
||||
ATRACE_CALL();
|
||||
|
|
|
@ -82,6 +82,7 @@ public:
|
|||
virtual void onRemoved();
|
||||
virtual sp<Layer> getLayer() const { return const_cast<Layer*>(this); }
|
||||
virtual void setName(const String8& name);
|
||||
virtual bool isVisible() const;
|
||||
|
||||
// LayerBaseClient interface
|
||||
virtual wp<IBinder> getSurfaceTextureBinder() const;
|
||||
|
|
|
@ -321,6 +321,11 @@ bool LayerBase::getFiltering() const
|
|||
return mFiltering;
|
||||
}
|
||||
|
||||
bool LayerBase::isVisible() const {
|
||||
const Layer::State& s(mDrawingState);
|
||||
return !(s.flags & layer_state_t::eLayerHidden) && s.alpha;
|
||||
}
|
||||
|
||||
void LayerBase::draw(const sp<const DisplayDevice>& hw, const Region& clip) const
|
||||
{
|
||||
onDraw(hw, clip);
|
||||
|
|
|
@ -211,6 +211,11 @@ public:
|
|||
*/
|
||||
virtual bool isProtected() const { return false; }
|
||||
|
||||
/*
|
||||
* isVisible - true if this layer is visibile, false otherwise
|
||||
*/
|
||||
virtual bool isVisible() const;
|
||||
|
||||
/** called with the state lock when the surface is removed from the
|
||||
* current list */
|
||||
virtual void onRemoved() { }
|
||||
|
|
|
@ -245,15 +245,6 @@ status_t SurfaceFlinger::selectConfigForPixelFormat(
|
|||
EGLConfig* const configs = new EGLConfig[numConfigs];
|
||||
eglChooseConfig(dpy, attrs, configs, numConfigs, &n);
|
||||
|
||||
if (format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
|
||||
// FIXME: temporary hack until HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED
|
||||
// is supported by the implementation. we can only be in this case
|
||||
// if we have HWC 1.1
|
||||
*outConfig = configs[0];
|
||||
delete [] configs;
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
for (int i=0 ; i<n ; i++) {
|
||||
EGLint nativeVisualId = 0;
|
||||
eglGetConfigAttrib(dpy, configs[i], EGL_NATIVE_VISUAL_ID, &nativeVisualId);
|
||||
|
@ -273,6 +264,7 @@ EGLConfig SurfaceFlinger::selectEGLConfig(EGLDisplay display, EGLint nativeVisua
|
|||
EGLConfig config;
|
||||
EGLint dummy;
|
||||
status_t err;
|
||||
|
||||
EGLint attribs[] = {
|
||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
||||
EGL_RED_SIZE, 8,
|
||||
|
@ -390,6 +382,9 @@ status_t SurfaceFlinger::readyToRun()
|
|||
mEGLConfig = selectEGLConfig(mEGLDisplay, format);
|
||||
mEGLContext = createGLContext(mEGLDisplay, mEGLConfig);
|
||||
|
||||
LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,
|
||||
"couldn't create EGLContext");
|
||||
|
||||
// initialize our non-virtual displays
|
||||
for (size_t i=0 ; i<DisplayDevice::NUM_DISPLAY_TYPES ; i++) {
|
||||
mDefaultDisplays[i] = new BBinder();
|
||||
|
@ -725,10 +720,7 @@ void SurfaceFlinger::doDebugFlashRegions()
|
|||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
}
|
||||
hw->compositionComplete();
|
||||
// FIXME
|
||||
if (hw->getDisplayType() >= DisplayDevice::DISPLAY_VIRTUAL) {
|
||||
eglSwapBuffers(mEGLDisplay, hw->getEGLSurface());
|
||||
}
|
||||
hw->swapBuffers(getHwComposer());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -885,6 +877,7 @@ void SurfaceFlinger::postFramebuffer()
|
|||
for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
|
||||
sp<const DisplayDevice> hw(mDisplays[dpy]);
|
||||
const Vector< sp<LayerBase> >& currentLayers(hw->getVisibleLayersSortedByZ());
|
||||
hw->onSwapBuffersCompleted(hwc);
|
||||
const size_t count = currentLayers.size();
|
||||
int32_t id = hw->getHwcDisplayId();
|
||||
if (id >=0 && hwc.initCheck() == NO_ERROR) {
|
||||
|
@ -1160,7 +1153,7 @@ void SurfaceFlinger::computeVisibleRegions(
|
|||
|
||||
|
||||
// handle hidden surfaces by setting the visible region to empty
|
||||
if (CC_LIKELY(!(s.flags & layer_state_t::eLayerHidden) && s.alpha)) {
|
||||
if (CC_LIKELY(layer->isVisible())) {
|
||||
const bool translucent = !layer->isOpaque();
|
||||
Rect bounds(layer->computeBounds());
|
||||
visibleRegion.set(bounds);
|
||||
|
@ -1308,20 +1301,11 @@ void SurfaceFlinger::doDisplayComposition(const sp<const DisplayDevice>& hw,
|
|||
|
||||
doComposeSurfaces(hw, dirtyRegion);
|
||||
|
||||
// FIXME: we need to call eglSwapBuffers() on displays that have
|
||||
// GL composition and only on those.
|
||||
// however, currently hwc.commit() already does that for the main
|
||||
// display (if there is a hwc) and never for the other ones
|
||||
if (hw->getDisplayType() >= DisplayDevice::DISPLAY_VIRTUAL ||
|
||||
getHwComposer().initCheck() != NO_ERROR) {
|
||||
// FIXME: EGL spec says:
|
||||
// "surface must be bound to the calling thread's current context,
|
||||
// for the current rendering API."
|
||||
eglSwapBuffers(mEGLDisplay, hw->getEGLSurface());
|
||||
}
|
||||
|
||||
// update the swap region and clear the dirty region
|
||||
hw->swapRegion.orSelf(dirtyRegion);
|
||||
|
||||
// swap buffers (presentation)
|
||||
hw->swapBuffers(getHwComposer());
|
||||
}
|
||||
|
||||
void SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const Region& dirty)
|
||||
|
@ -1388,6 +1372,12 @@ void SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const
|
|||
layer->draw(hw, clip);
|
||||
break;
|
||||
}
|
||||
case HWC_FRAMEBUFFER_TARGET: {
|
||||
// this should not happen as the iterator shouldn't
|
||||
// let us get there.
|
||||
ALOGW("HWC_FRAMEBUFFER_TARGET found in hwc list (index=%d)", i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
layer->setAcquireFence(hw, *cur);
|
||||
|
|
Loading…
Reference in New Issue