diff options
Diffstat (limited to 'services/surfaceflinger/DisplayHardware')
9 files changed, 434 insertions, 232 deletions
diff --git a/services/surfaceflinger/DisplayHardware/DisplaySurface.h b/services/surfaceflinger/DisplayHardware/DisplaySurface.h new file mode 100644 index 0000000..2eca3cb --- /dev/null +++ b/services/surfaceflinger/DisplayHardware/DisplaySurface.h @@ -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. + // + // advanceFrame must be followed by a call to onFrameCommitted before + // advanceFrame may be called again. + virtual status_t advanceFrame() = 0; + + // onFrameCommitted is called after the frame has been committed to the + // hardware composer. The surface collects the release fence for this + // frame's buffer. + virtual void onFrameCommitted() = 0; + + virtual void dump(String8& result) const = 0; + +protected: + DisplaySurface() {} + virtual ~DisplaySurface() {} +}; + +// --------------------------------------------------------------------------- +} // namespace android +// --------------------------------------------------------------------------- + +#endif // ANDROID_SF_DISPLAY_SURFACE_H + diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp index 6c86a53..54a3ce8 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp @@ -29,12 +29,12 @@ #include <EGL/egl.h> #include <hardware/hardware.h> -#include <gui/SurfaceTextureClient.h> +#include <gui/Surface.h> +#include <gui/GraphicBufferAlloc.h> #include <ui/GraphicBuffer.h> -#include "DisplayHardware/FramebufferSurface.h" -#include "DisplayHardware/GraphicBufferAlloc.h" -#include "DisplayHardware/HWComposer.h" +#include "FramebufferSurface.h" +#include "HWComposer.h" #ifndef NUM_FRAMEBUFFER_SURFACE_BUFFERS #define NUM_FRAMEBUFFER_SURFACE_BUFFERS (2) @@ -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); @@ -129,22 +140,14 @@ 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); - } +void FramebufferSurface::onFrameCommitted() { + sp<Fence> fence = mHwc.getAndResetReleaseFence(mDisplayType); + if (fence->isValid() && + 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; } status_t FramebufferSurface::compositionComplete() @@ -152,11 +155,33 @@ status_t FramebufferSurface::compositionComplete() return mHwc.fbCompositionComplete(); } -void FramebufferSurface::dump(String8& result) { - mHwc.fbDump(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); } +void FramebufferSurface::dumpLocked(String8& result, const char* prefix, + char* buffer, size_t SIZE) const +{ + mHwc.fbDump(result); + ConsumerBase::dumpLocked(result, prefix, buffer, SIZE); +} + // ---------------------------------------------------------------------------- }; // namespace android // ---------------------------------------------------------------------------- diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h index 6336345..2fde789 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h @@ -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); - bool isUpdateOnDemand() const { return false; } - status_t setUpdateRectangle(const Rect& updateRect); - status_t compositionComplete(); + virtual sp<IGraphicBufferProducer> getIGraphicBufferProducer() const; - virtual void dump(String8& result); + virtual status_t compositionComplete(); + virtual status_t advanceFrame(); + virtual void onFrameCommitted(); - // 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); + // 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 @@ -56,6 +55,9 @@ private: virtual void onFrameAvailable(); virtual void freeBufferLocked(int slotIndex); + virtual void dumpLocked(String8& result, const char* prefix, + char* buffer, size_t SIZE) const; + // 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. diff --git a/services/surfaceflinger/DisplayHardware/GraphicBufferAlloc.cpp b/services/surfaceflinger/DisplayHardware/GraphicBufferAlloc.cpp deleted file mode 100644 index 965ff01..0000000 --- a/services/surfaceflinger/DisplayHardware/GraphicBufferAlloc.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - ** - ** Copyright 2012 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 <cutils/log.h> - -#include <ui/GraphicBuffer.h> - -#include "DisplayHardware/GraphicBufferAlloc.h" - -// ---------------------------------------------------------------------------- -namespace android { -// ---------------------------------------------------------------------------- - -GraphicBufferAlloc::GraphicBufferAlloc() { -} - -GraphicBufferAlloc::~GraphicBufferAlloc() { -} - -sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t w, uint32_t h, - PixelFormat format, uint32_t usage, status_t* error) { - sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h, format, usage)); - status_t err = graphicBuffer->initCheck(); - *error = err; - if (err != 0 || graphicBuffer->handle == 0) { - if (err == NO_MEMORY) { - GraphicBuffer::dumpAllocationsToSystemLog(); - } - ALOGE("GraphicBufferAlloc::createGraphicBuffer(w=%d, h=%d) " - "failed (%s), handle=%p", - w, h, strerror(-err), graphicBuffer->handle); - return 0; - } - return graphicBuffer; -} - -// ---------------------------------------------------------------------------- -}; // namespace android -// ---------------------------------------------------------------------------- diff --git a/services/surfaceflinger/DisplayHardware/GraphicBufferAlloc.h b/services/surfaceflinger/DisplayHardware/GraphicBufferAlloc.h deleted file mode 100644 index b08750c..0000000 --- a/services/surfaceflinger/DisplayHardware/GraphicBufferAlloc.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2012 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_GRAPHIC_BUFFER_ALLOC_H -#define ANDROID_SF_GRAPHIC_BUFFER_ALLOC_H - -#include <stdint.h> -#include <sys/types.h> - -#include <gui/IGraphicBufferAlloc.h> -#include <ui/PixelFormat.h> -#include <utils/Errors.h> - -namespace android { -// --------------------------------------------------------------------------- - -class GraphicBuffer; - -class GraphicBufferAlloc : public BnGraphicBufferAlloc { -public: - GraphicBufferAlloc(); - virtual ~GraphicBufferAlloc(); - virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h, - PixelFormat format, uint32_t usage, status_t* error); -}; - - -// --------------------------------------------------------------------------- -}; // namespace android - -#endif // ANDROID_SF_GRAPHIC_BUFFER_ALLOC_H diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 068fdcd..a9afbe5 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -25,6 +25,7 @@ #include <string.h> #include <sys/types.h> +#include <utils/CallStack.h> #include <utils/Errors.h> #include <utils/misc.h> #include <utils/String8.h> @@ -37,19 +38,27 @@ #include <hardware/hardware.h> #include <hardware/hwcomposer.h> +#include <android/configuration.h> + #include <cutils/log.h> #include <cutils/properties.h> -#include "Layer.h" // needed only for debugging -#include "LayerBase.h" #include "HWComposer.h" -#include "SurfaceFlinger.h" -#include <utils/CallStack.h> + +#include "../Layer.h" // needed only for debugging +#include "../SurfaceFlinger.h" namespace android { +// This is not a real HWC version. It's used for in-development features that +// haven't been committed to a specific real HWC version. +#define HWC_DEVICE_API_VERSION_1_EXP HARDWARE_DEVICE_API_VERSION_2(1, 0xFF, HWC_HEADER_VERSION) + #define MIN_HWC_HEADER_VERSION HWC_HEADER_VERSION +#define NUM_PHYSICAL_DISPLAYS HWC_NUM_DISPLAY_TYPES +#define VIRTUAL_DISPLAY_ID_BASE HWC_NUM_DISPLAY_TYPES + static uint32_t hwcApiVersion(const hwc_composer_device_1_t* hwc) { uint32_t hwcVersion = hwc->common.version; return hwcVersion & HARDWARE_API_VERSION_2_MAJ_MIN_MASK; @@ -100,7 +109,7 @@ HWComposer::HWComposer( bool needVSyncThread = true; // Note: some devices may insist that the FB HAL be opened before HWC. - loadFbHalModule(); + int fberr = loadFbHalModule(); loadHwcModule(); if (mFbDev && mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) { @@ -114,12 +123,13 @@ HWComposer::HWComposer( // 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) { - ALOGE("ERROR: failed to open framebuffer, aborting"); + ALOGE("ERROR: failed to open framebuffer (%s), aborting", + strerror(-fberr)); abort(); } // these display IDs are always reserved - for (size_t i=0 ; i<HWC_NUM_DISPLAY_TYPES ; i++) { + for (size_t i=0 ; i<NUM_PHYSICAL_DISPLAYS ; i++) { mAllocatedDisplayIDs.markBit(i); } @@ -146,12 +156,12 @@ HWComposer::HWComposer( // the number of displays we actually have depends on the // hw composer version - if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_2)) { - // 1.2 adds support for virtual displays + if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_EXP)) { + // 1.?? adds support for virtual displays mNumDisplays = MAX_DISPLAYS; } else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) { // 1.1 adds support for multiple displays - mNumDisplays = HWC_NUM_DISPLAY_TYPES; + mNumDisplays = NUM_PHYSICAL_DISPLAYS; } else { mNumDisplays = 1; } @@ -179,7 +189,7 @@ HWComposer::HWComposer( } } else if (mHwc) { // here we're guaranteed to have at least HWC 1.1 - for (size_t i =0 ; i<HWC_NUM_DISPLAY_TYPES ; i++) { + for (size_t i =0 ; i<NUM_PHYSICAL_DISPLAYS ; i++) { queryDisplayProperties(i); } } @@ -235,20 +245,17 @@ void HWComposer::loadHwcModule() } // Load and prepare the FB HAL, which uses the gralloc module. Sets mFbDev. -void HWComposer::loadFbHalModule() +int HWComposer::loadFbHalModule() { hw_module_t const* module; - if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) != 0) { + int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module); + if (err != 0) { ALOGE("%s module not found", GRALLOC_HARDWARE_MODULE_ID); - return; + return err; } - int err = framebuffer_open(module, &mFbDev); - if (err) { - ALOGE("framebuffer_open failed (%s)", strerror(-err)); - return; - } + return framebuffer_open(module, &mFbDev); } status_t HWComposer::initCheck() const { @@ -287,7 +294,7 @@ void HWComposer::vsync(int disp, int64_t timestamp) { } void HWComposer::hotplug(int disp, int connected) { - if (disp == HWC_DISPLAY_PRIMARY || disp >= HWC_NUM_DISPLAY_TYPES) { + if (disp == HWC_DISPLAY_PRIMARY || disp >= VIRTUAL_DISPLAY_ID_BASE) { ALOGE("hotplug event received for invalid display: disp=%d connected=%d", disp, connected); return; @@ -296,6 +303,11 @@ void HWComposer::hotplug(int disp, int connected) { mEventHandler.onHotplugReceived(disp, bool(connected)); } +static float getDefaultDensity(uint32_t height) { + if (height >= 1080) return ACONFIGURATION_DENSITY_XHIGH; + else return ACONFIGURATION_DENSITY_TV; +} + static const uint32_t DISPLAY_ATTRIBUTES[] = { HWC_DISPLAY_VSYNC_PERIOD, HWC_DISPLAY_WIDTH, @@ -306,10 +318,6 @@ static const uint32_t DISPLAY_ATTRIBUTES[] = { }; #define NUM_DISPLAY_ATTRIBUTES (sizeof(DISPLAY_ATTRIBUTES) / sizeof(DISPLAY_ATTRIBUTES)[0]) -// http://developer.android.com/reference/android/util/DisplayMetrics.html -#define ANDROID_DENSITY_TV 213 -#define ANDROID_DENSITY_XHIGH 320 - status_t HWComposer::queryDisplayProperties(int disp) { LOG_ALWAYS_FATAL_IF(!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)); @@ -363,15 +371,23 @@ status_t HWComposer::queryDisplayProperties(int disp) { mDisplayData[disp].format = HAL_PIXEL_FORMAT_RGBA_8888; mDisplayData[disp].connected = true; if (mDisplayData[disp].xdpi == 0.0f || mDisplayData[disp].ydpi == 0.0f) { - // is there anything smarter we can do? - if (h >= 1080) { - mDisplayData[disp].xdpi = ANDROID_DENSITY_XHIGH; - mDisplayData[disp].ydpi = ANDROID_DENSITY_XHIGH; - } else { - mDisplayData[disp].xdpi = ANDROID_DENSITY_TV; - mDisplayData[disp].ydpi = ANDROID_DENSITY_TV; - } + float dpi = getDefaultDensity(h); + mDisplayData[disp].xdpi = dpi; + mDisplayData[disp].ydpi = dpi; + } + return NO_ERROR; +} + +status_t HWComposer::setVirtualDisplayProperties(int32_t id, + uint32_t w, uint32_t h, uint32_t format) { + if (id < VIRTUAL_DISPLAY_ID_BASE || id >= int32_t(mNumDisplays) || + !mAllocatedDisplayIDs.hasBit(id)) { + return BAD_INDEX; } + mDisplayData[id].width = w; + mDisplayData[id].height = h; + mDisplayData[id].format = format; + mDisplayData[id].xdpi = mDisplayData[id].ydpi = getDefaultDensity(h); return NO_ERROR; } @@ -381,11 +397,12 @@ int32_t HWComposer::allocateDisplayId() { } int32_t id = mAllocatedDisplayIDs.firstUnmarkedBit(); mAllocatedDisplayIDs.markBit(id); + mDisplayData[id].connected = true; return id; } status_t HWComposer::freeDisplayId(int32_t id) { - if (id < HWC_NUM_DISPLAY_TYPES) { + if (id < NUM_PHYSICAL_DISPLAYS) { // cannot free the reserved IDs return BAD_VALUE; } @@ -393,6 +410,7 @@ status_t HWComposer::freeDisplayId(int32_t id) { return BAD_INDEX; } mAllocatedDisplayIDs.clearBit(id); + mDisplayData[id].connected = false; return NO_ERROR; } @@ -409,6 +427,10 @@ nsecs_t HWComposer::getRefreshTimestamp(int disp) const { return now - ((now - mLastHwVSync) % mDisplayData[disp].refresh); } +sp<Fence> HWComposer::getDisplayFence(int disp) const { + return mDisplayData[disp].lastDisplayFence; +} + uint32_t HWComposer::getWidth(int disp) const { return mDisplayData[disp].width; } @@ -494,7 +516,7 @@ status_t HWComposer::createWorkList(int32_t id, size_t 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 }; + const hwc_rect_t r = { 0, 0, (int) disp.width, (int) disp.height }; disp.framebufferTarget->compositionType = HWC_FRAMEBUFFER_TARGET; disp.framebufferTarget->hints = 0; disp.framebufferTarget->flags = 0; @@ -508,6 +530,7 @@ status_t HWComposer::createWorkList(int32_t id, size_t numLayers) { &disp.framebufferTarget->displayFrame; disp.framebufferTarget->acquireFenceFd = -1; disp.framebufferTarget->releaseFenceFd = -1; + disp.framebufferTarget->planeAlpha = 0xFF; } disp.list->retireFenceFd = -1; disp.list->flags = HWC_GEOMETRY_CHANGED; @@ -524,7 +547,7 @@ status_t HWComposer::setFramebufferTarget(int32_t id, DisplayData& disp(mDisplayData[id]); if (!disp.framebufferTarget) { // this should never happen, but apparently eglCreateWindowSurface() - // triggers a SurfaceTextureClient::queueBuffer() on some + // triggers a Surface::queueBuffer() on some // devices (!?) -- log and ignore. ALOGE("HWComposer: framebufferTarget is null"); // CallStack stack; @@ -534,7 +557,7 @@ status_t HWComposer::setFramebufferTarget(int32_t id, } int acquireFenceFd = -1; - if (acquireFence != NULL) { + if (acquireFence->isValid()) { acquireFenceFd = acquireFence->dup(); } @@ -562,7 +585,7 @@ status_t HWComposer::prepare() { } mLists[i] = disp.list; if (mLists[i]) { - if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_2)) { + if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_EXP)) { mLists[i]->outbuf = NULL; mLists[i]->outbufAcquireFenceFd = -1; } else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) { @@ -611,20 +634,20 @@ 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; } -int HWComposer::getAndResetReleaseFenceFd(int32_t id) { +sp<Fence> HWComposer::getAndResetReleaseFence(int32_t id) { if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) - return BAD_INDEX; + return Fence::NO_FENCE; int fd = INVALID_OPERATION; if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) { @@ -635,7 +658,7 @@ int HWComposer::getAndResetReleaseFenceFd(int32_t id) { disp.framebufferTarget->releaseFenceFd = -1; } } - return fd; + return fd >= 0 ? new Fence(fd) : Fence::NO_FENCE; } status_t HWComposer::commit() { @@ -649,13 +672,24 @@ status_t HWComposer::commit() { mLists[0]->sur = eglGetCurrentSurface(EGL_DRAW); } + for (size_t i=VIRTUAL_DISPLAY_ID_BASE; i<mNumDisplays; i++) { + DisplayData& disp(mDisplayData[i]); + if (disp.outbufHandle) { + mLists[i]->outbuf = disp.outbufHandle; + mLists[i]->outbufAcquireFenceFd = + disp.outbufAcquireFence->dup(); + } + } + err = mHwc->set(mHwc, mNumDisplays, mLists); for (size_t i=0 ; i<mNumDisplays ; i++) { DisplayData& disp(mDisplayData[i]); + disp.lastDisplayFence = disp.lastRetireFence; + disp.lastRetireFence = Fence::NO_FENCE; if (disp.list) { if (disp.list->retireFenceFd != -1) { - close(disp.list->retireFenceFd); + disp.lastRetireFence = new Fence(disp.list->retireFenceFd); disp.list->retireFenceFd = -1; } disp.list->flags &= ~HWC_GEOMETRY_CHANGED; @@ -666,7 +700,7 @@ status_t HWComposer::commit() { } status_t HWComposer::release(int disp) { - LOG_FATAL_IF(disp >= HWC_NUM_DISPLAY_TYPES); + LOG_FATAL_IF(disp >= VIRTUAL_DISPLAY_ID_BASE); if (mHwc) { eventControl(disp, HWC_EVENT_VSYNC, 0); return (status_t)mHwc->blank(mHwc, disp, 1); @@ -675,7 +709,7 @@ status_t HWComposer::release(int disp) { } status_t HWComposer::acquire(int disp) { - LOG_FATAL_IF(disp >= HWC_NUM_DISPLAY_TYPES); + LOG_FATAL_IF(disp >= VIRTUAL_DISPLAY_ID_BASE); if (mHwc) { return (status_t)mHwc->blank(mHwc, disp, 0); } @@ -684,17 +718,15 @@ status_t HWComposer::acquire(int disp) { void HWComposer::disconnectDisplay(int disp) { LOG_ALWAYS_FATAL_IF(disp < 0 || disp == HWC_DISPLAY_PRIMARY); - if (disp >= HWC_NUM_DISPLAY_TYPES) { - // nothing to do for these yet - return; - } DisplayData& dd(mDisplayData[disp]); - if (dd.list != NULL) { - free(dd.list); - dd.list = NULL; - dd.framebufferTarget = NULL; // points into dd.list - dd.fbTargetHandle = NULL; - } + free(dd.list); + dd.list = NULL; + dd.framebufferTarget = NULL; // points into dd.list + dd.fbTargetHandle = NULL; + dd.outbufHandle = NULL; + dd.lastRetireFence = Fence::NO_FENCE; + dd.lastDisplayFence = Fence::NO_FENCE; + dd.outbufAcquireFence = Fence::NO_FENCE; } int HWComposer::getVisualID() const { @@ -718,9 +750,7 @@ int HWComposer::fbPost(int32_t id, if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) { return setFramebufferTarget(id, acquireFence, buffer); } else { - if (acquireFence != NULL) { - acquireFence->waitForever(1000, "HWComposer::fbPost"); - } + acquireFence->waitForever("HWComposer::fbPost"); return mFbDev->post(mFbDev, buffer->handle); } } @@ -745,6 +775,25 @@ void HWComposer::fbDump(String8& result) { } } +status_t HWComposer::setOutputBuffer(int32_t id, const sp<Fence>& acquireFence, + const sp<GraphicBuffer>& buf) { + if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) + return BAD_INDEX; + if (id < VIRTUAL_DISPLAY_ID_BASE) + return INVALID_OPERATION; + + DisplayData& disp(mDisplayData[id]); + disp.outbufHandle = buf->handle; + disp.outbufAcquireFence = acquireFence; + return NO_ERROR; +} + +sp<Fence> HWComposer::getLastRetireFence(int32_t id) { + if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) + return Fence::NO_FENCE; + return mDisplayData[id].lastRetireFence; +} + /* * Helper template to implement a concrete HWCLayer * This holds the pointer to the concrete hwc layer type @@ -775,9 +824,10 @@ private: * This implements the HWCLayer side of HWCIterableLayer. */ class HWCLayerVersion1 : public Iterable<HWCLayerVersion1, hwc_layer_1_t> { + struct hwc_composer_device_1* mHwc; public: - HWCLayerVersion1(hwc_layer_1_t* layer) - : Iterable<HWCLayerVersion1, hwc_layer_1_t>(layer) { } + HWCLayerVersion1(struct hwc_composer_device_1* hwc, hwc_layer_1_t* layer) + : Iterable<HWCLayerVersion1, hwc_layer_1_t>(layer), mHwc(hwc) { } virtual int32_t getCompositionType() const { return getLayer()->compositionType; @@ -785,10 +835,10 @@ public: virtual uint32_t getHints() const { return getLayer()->hints; } - virtual int getAndResetReleaseFenceFd() { + virtual sp<Fence> getAndResetReleaseFence() { int fd = getLayer()->releaseFenceFd; getLayer()->releaseFenceFd = -1; - return fd; + return fd >= 0 ? new Fence(fd) : Fence::NO_FENCE; } virtual void setAcquireFenceFd(int fenceFd) { getLayer()->acquireFenceFd = fenceFd; @@ -796,17 +846,28 @@ public: virtual void setPerFrameDefaultState() { //getLayer()->compositionType = HWC_FRAMEBUFFER; } + virtual void setPlaneAlpha(uint8_t alpha) { + if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_2)) { + getLayer()->planeAlpha = alpha; + } else { + if (alpha < 0xFF) { + getLayer()->flags |= HWC_SKIP_LAYER; + } + } + } virtual void setDefaultState() { - getLayer()->compositionType = HWC_FRAMEBUFFER; - getLayer()->hints = 0; - getLayer()->flags = HWC_SKIP_LAYER; - getLayer()->handle = 0; - getLayer()->transform = 0; - getLayer()->blending = HWC_BLENDING_NONE; - getLayer()->visibleRegionScreen.numRects = 0; - getLayer()->visibleRegionScreen.rects = NULL; - getLayer()->acquireFenceFd = -1; - getLayer()->releaseFenceFd = -1; + hwc_layer_1_t* const l = getLayer(); + l->compositionType = HWC_FRAMEBUFFER; + l->hints = 0; + l->flags = HWC_SKIP_LAYER; + l->handle = 0; + l->transform = 0; + l->blending = HWC_BLENDING_NONE; + l->visibleRegionScreen.numRects = 0; + l->visibleRegionScreen.rects = NULL; + l->acquireFenceFd = -1; + l->releaseFenceFd = -1; + l->planeAlpha = 0xFF; } virtual void setSkip(bool skip) { if (skip) { @@ -869,7 +930,7 @@ HWComposer::LayerListIterator HWComposer::getLayerIterator(int32_t id, size_t in if (!mHwc || !disp.list || index > disp.list->numHwLayers) { return LayerListIterator(); } - return LayerListIterator(new HWCLayerVersion1(disp.list->hwLayers), index); + return LayerListIterator(new HWCLayerVersion1(mHwc, disp.list->hwLayers), index); } /* @@ -907,17 +968,17 @@ void HWComposer::dump(String8& result, char* buffer, size_t SIZE) const { result.appendFormat(" mDebugForceFakeVSync=%d\n", mDebugForceFakeVSync); for (size_t i=0 ; i<mNumDisplays ; i++) { const DisplayData& disp(mDisplayData[i]); + if (!disp.connected) + continue; - const Vector< sp<LayerBase> >& visibleLayersSortedByZ = + const Vector< sp<Layer> >& visibleLayersSortedByZ = mFlinger->getLayerSortedByZForHwcDisplay(i); - if (disp.connected) { - result.appendFormat( - " Display[%d] : %ux%u, xdpi=%f, ydpi=%f, refresh=%lld\n", - i, disp.width, disp.height, disp.xdpi, disp.ydpi, disp.refresh); - } + result.appendFormat( + " Display[%d] : %ux%u, xdpi=%f, ydpi=%f, refresh=%lld\n", + i, disp.width, disp.height, disp.xdpi, disp.ydpi, disp.refresh); - if (disp.list && disp.connected) { + if (disp.list) { result.appendFormat( " numHwLayers=%u, flags=%08x\n", disp.list->numHwLayers, disp.list->flags); @@ -932,13 +993,11 @@ void HWComposer::dump(String8& result, char* buffer, size_t SIZE) const { 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(); - } + const sp<Layer>& layer(visibleLayersSortedByZ[i]); + const sp<GraphicBuffer>& buffer( + layer->getActiveBuffer()); + if (buffer != NULL) { + format = buffer->getPixelFormat(); } name = layer->getName(); } @@ -1032,5 +1091,22 @@ bool HWComposer::VSyncThread::threadLoop() { return true; } +HWComposer::DisplayData::DisplayData() +: width(0), height(0), format(0), + xdpi(0.0f), ydpi(0.0f), + refresh(0), + connected(false), + hasFbComp(false), hasOvComp(false), + capacity(0), list(NULL), + framebufferTarget(NULL), fbTargetHandle(0), + lastRetireFence(Fence::NO_FENCE), lastDisplayFence(Fence::NO_FENCE), + outbufHandle(NULL), outbufAcquireFence(Fence::NO_FENCE), + events(0) +{} + +HWComposer::DisplayData::~DisplayData() { + free(list); +} + // --------------------------------------------------------------------------- }; // namespace android diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index 7c67407..604de38 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -22,13 +22,15 @@ #include <hardware/hwcomposer_defs.h> +#include <ui/Fence.h> + +#include <utils/BitSet.h> #include <utils/Condition.h> #include <utils/Mutex.h> #include <utils/StrongPointer.h> #include <utils/Thread.h> #include <utils/Timers.h> #include <utils/Vector.h> -#include <utils/BitSet.h> extern "C" int clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *request, @@ -45,7 +47,6 @@ namespace android { class GraphicBuffer; class Fence; -class LayerBase; class Region; class String8; class SurfaceFlinger; @@ -111,9 +112,9 @@ public: // does this display have layers handled by GLES bool hasGlesComposition(int32_t id) const; - // get the releaseFence file descriptor for the given display + // get the releaseFence file descriptor for a display's framebuffer layer. // the release fence is only valid after commit() - int getAndResetReleaseFenceFd(int32_t id); + sp<Fence> getAndResetReleaseFence(int32_t id); // needed forward declarations class LayerListIterator; @@ -127,6 +128,17 @@ public: int fbCompositionComplete(); void fbDump(String8& result); + // Set the output buffer and acquire fence for a virtual display. + // Returns INVALID_OPERATION if id is not a virtual display. + status_t setOutputBuffer(int32_t id, const sp<Fence>& acquireFence, + const sp<GraphicBuffer>& buf); + + // Get the retire fence for the last committed frame. This fence will + // signal when the h/w composer is completely finished with the frame. + // For physical displays, it is no longer being displayed. For virtual + // displays, writes to the output buffer are complete. + sp<Fence> getLastRetireFence(int32_t id); + /* * Interface to hardware composer's layers functionality. * This abstracts the HAL interface to layers which can evolve in @@ -140,8 +152,7 @@ public: public: virtual int32_t getCompositionType() const = 0; virtual uint32_t getHints() const = 0; - virtual int getAndResetReleaseFenceFd() = 0; - virtual void setPerFrameDefaultState() = 0; + virtual sp<Fence> getAndResetReleaseFence() = 0; virtual void setDefaultState() = 0; virtual void setSkip(bool skip) = 0; virtual void setBlending(uint32_t blending) = 0; @@ -151,6 +162,7 @@ public: virtual void setVisibleRegionScreen(const Region& reg) = 0; virtual void setBuffer(const sp<GraphicBuffer>& buffer) = 0; virtual void setAcquireFenceFd(int fenceFd) = 0; + virtual void setPlaneAlpha(uint8_t alpha) = 0; virtual void onDisplayed() = 0; }; @@ -233,6 +245,7 @@ public: // HWC_DISPLAY_PRIMARY). nsecs_t getRefreshPeriod(int disp) const; nsecs_t getRefreshTimestamp(int disp) const; + sp<Fence> getDisplayFence(int disp) const; uint32_t getWidth(int disp) const; uint32_t getHeight(int disp) const; uint32_t getFormat(int disp) const; @@ -240,6 +253,9 @@ public: float getDpiY(int disp) const; bool isConnected(int disp) const; + status_t setVirtualDisplayProperties(int32_t id, uint32_t w, uint32_t h, + uint32_t format); + // this class is only used to fake the VSync event on systems that don't // have it. class VSyncThread : public Thread { @@ -263,7 +279,7 @@ public: private: void loadHwcModule(); - void loadFbHalModule(); + int loadFbHalModule(); LayerListIterator getLayerIterator(int32_t id, size_t index); @@ -286,13 +302,8 @@ private: struct DisplayData { - DisplayData() : xdpi(0), ydpi(0), refresh(0), - connected(false), hasFbComp(false), hasOvComp(false), - capacity(0), list(NULL), - framebufferTarget(NULL), fbTargetHandle(NULL), events(0) { } - ~DisplayData() { - free(list); - } + DisplayData(); + ~DisplayData(); uint32_t width; uint32_t height; uint32_t format; // pixel format from FB hal, for pre-hwc-1.1 @@ -306,6 +317,12 @@ private: hwc_display_contents_1* list; hwc_layer_1* framebufferTarget; buffer_handle_t fbTargetHandle; + sp<Fence> lastRetireFence; // signals when the last set op retires + sp<Fence> lastDisplayFence; // signals when the last set op takes + // effect on screen + buffer_handle_t outbufHandle; + sp<Fence> outbufAcquireFence; + // protected by mEventControlLock int32_t events; }; diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp new file mode 100644 index 0000000..2838b23 --- /dev/null +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp @@ -0,0 +1,56 @@ +/* + * 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 "VirtualDisplaySurface.h" + +#include <cutils/log.h> +#include <gui/IGraphicBufferProducer.h> + +// --------------------------------------------------------------------------- +namespace android { +// --------------------------------------------------------------------------- + +VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int32_t dispId, + const sp<IGraphicBufferProducer>& sink, const String8& name) +: mSink(sink) +{ + LOG_ALWAYS_FATAL_IF(dispId >= 0); +} + +VirtualDisplaySurface::~VirtualDisplaySurface() { +} + +sp<IGraphicBufferProducer> VirtualDisplaySurface::getIGraphicBufferProducer() const { + return mSink; +} + +status_t VirtualDisplaySurface::compositionComplete() { + return NO_ERROR; +} + +status_t VirtualDisplaySurface::advanceFrame() { + return NO_ERROR; +} + +void VirtualDisplaySurface::onFrameCommitted() { +} + +void VirtualDisplaySurface::dump(String8& result) const { +} + +// --------------------------------------------------------------------------- +} // namespace android +// --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h new file mode 100644 index 0000000..f321795 --- /dev/null +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h @@ -0,0 +1,55 @@ +/* + * 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 "DisplaySurface.h" + +// --------------------------------------------------------------------------- +namespace android { +// --------------------------------------------------------------------------- + +class HWComposer; + +/* This DisplaySurface implementation is a stub used for developing HWC + * virtual display support. It is currently just a passthrough. + */ +class VirtualDisplaySurface : public DisplaySurface { +public: + VirtualDisplaySurface(HWComposer& hwc, int32_t dispId, + const sp<IGraphicBufferProducer>& sink, + const String8& name); + + virtual sp<IGraphicBufferProducer> getIGraphicBufferProducer() const; + + virtual status_t compositionComplete(); + virtual status_t advanceFrame(); + virtual void onFrameCommitted(); + virtual void dump(String8& result) const; + +private: + virtual ~VirtualDisplaySurface(); + + sp<IGraphicBufferProducer> mSink; +}; + +// --------------------------------------------------------------------------- +} // namespace android +// --------------------------------------------------------------------------- + +#endif // ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H + |