diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-01-09 17:51:23 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-01-09 17:51:23 -0800 |
commit | 276293246ea9cbc0a578a7697cc48930376ec0e9 (patch) | |
tree | 03804488c60dda65699333d2311c8d1842ec4b65 /libs | |
parent | e09fd9e819c23dc90bca68375645e15544861330 (diff) | |
download | frameworks_native-276293246ea9cbc0a578a7697cc48930376ec0e9.zip frameworks_native-276293246ea9cbc0a578a7697cc48930376ec0e9.tar.gz frameworks_native-276293246ea9cbc0a578a7697cc48930376ec0e9.tar.bz2 |
auto import from //branches/cupcake/...@125939
Diffstat (limited to 'libs')
30 files changed, 881 insertions, 507 deletions
diff --git a/libs/audioflinger/A2dpAudioInterface.cpp b/libs/audioflinger/A2dpAudioInterface.cpp index d54795c..b2a8e96 100644 --- a/libs/audioflinger/A2dpAudioInterface.cpp +++ b/libs/audioflinger/A2dpAudioInterface.cpp @@ -79,11 +79,6 @@ AudioStreamIn* A2dpAudioInterface::openInputStream( return NULL; } -status_t A2dpAudioInterface::standby() -{ - return 0; -} - status_t A2dpAudioInterface::setMicMute(bool state) { return 0; @@ -123,8 +118,8 @@ status_t A2dpAudioInterface::dump(int fd, const Vector<String16>& args) // ---------------------------------------------------------------------------- A2dpAudioInterface::A2dpAudioStreamOut::A2dpAudioStreamOut() : - mFd(-1), mStartCount(0), mRetryCount(0), mData(NULL), - mInitialized(false), mBufferRemaining(0) + mFd(-1), mStandby(false), mStartCount(0), mRetryCount(0), mData(NULL), + mInitialized(false) { } @@ -155,26 +150,50 @@ A2dpAudioInterface::A2dpAudioStreamOut::~A2dpAudioStreamOut() ssize_t A2dpAudioInterface::A2dpAudioStreamOut::write(const void* buffer, size_t bytes) { + status_t status = NO_INIT; + size_t remaining = bytes; + if (!mInitialized) { - int ret = a2dp_init("00:00:00:00:00:00", 44100, 2, &mData); - if (ret) - return ret; + status = a2dp_init("00:00:00:00:00:00", 44100, 2, &mData); + if (status < 0) { + LOGE("a2dp_init failed err: %d\n", status); + goto Error; + } mInitialized = true; } - size_t remaining = bytes; while (remaining > 0) { - int written = a2dp_write(mData, buffer, remaining); - remaining -= written; - buffer = ((char *)buffer) + written; + status = a2dp_write(mData, buffer, remaining); + if (status <= 0) { + LOGE("a2dp_write failed err: %d\n", status); + goto Error; + } + remaining -= status; + buffer = ((char *)buffer) + status; } + + mStandby = false; return bytes; + +Error: + // Simulate audio output timing in case of error + usleep(bytes * 1000000 / frameSize() / sampleRate()); + + return status; } status_t A2dpAudioInterface::A2dpAudioStreamOut::standby() { - return 0; + int result = 0; + + if (!mStandby) { + result = a2dp_stop(mData); + if (result == 0) + mStandby = true; + } + + return result; } status_t A2dpAudioInterface::A2dpAudioStreamOut::dump(int fd, const Vector<String16>& args) diff --git a/libs/audioflinger/A2dpAudioInterface.h b/libs/audioflinger/A2dpAudioInterface.h index 03bf933..b8119a1 100644 --- a/libs/audioflinger/A2dpAudioInterface.h +++ b/libs/audioflinger/A2dpAudioInterface.h @@ -35,7 +35,6 @@ public: A2dpAudioInterface(); virtual ~A2dpAudioInterface(); virtual status_t initCheck(); - virtual status_t standby(); virtual status_t setVoiceVolume(float volume); virtual status_t setMasterVolume(float volume); @@ -74,11 +73,11 @@ private: int channelCount, uint32_t sampleRate); virtual uint32_t sampleRate() const { return 44100; } - // must be 32-bit aligned - driver only seems to like 4800 - virtual size_t bufferSize() const { return 5120; } + // SBC codec wants a multiple of 512 + virtual size_t bufferSize() const { return 512 * 30; } virtual int channelCount() const { return 2; } virtual int format() const { return AudioSystem::PCM_16_BIT; } - virtual uint32_t latency() const { return 0; } + virtual uint32_t latency() const { return ((1000*channelCount()*bufferSize())/frameSize())/sampleRate() + 200; } virtual status_t setVolume(float volume) { return INVALID_OPERATION; } virtual ssize_t write(const void* buffer, size_t bytes); status_t standby(); @@ -86,14 +85,11 @@ private: private: int mFd; + bool mStandby; int mStartCount; int mRetryCount; void* mData; bool mInitialized; - -#define kBufferSize 50000 - char mBuffer[kBufferSize]; - int mBufferRemaining; }; Mutex mLock; diff --git a/libs/audioflinger/AudioDumpInterface.cpp b/libs/audioflinger/AudioDumpInterface.cpp index 8eee9cc..b4940cb 100644 --- a/libs/audioflinger/AudioDumpInterface.cpp +++ b/libs/audioflinger/AudioDumpInterface.cpp @@ -49,14 +49,6 @@ AudioDumpInterface::~AudioDumpInterface() } -status_t AudioDumpInterface::standby() -{ - if(mStreamOut) mStreamOut->Close(); - gFirst = true; - return mFinalInterface->standby(); -} - - AudioStreamOut* AudioDumpInterface::openOutputStream( int format, int channelCount, uint32_t sampleRate, status_t *status) { @@ -106,6 +98,14 @@ ssize_t AudioStreamOutDump::write(const void* buffer, size_t bytes) return ret; } +status_t AudioStreamOutDump::standby() +{ + Close(); + gFirst = true; + return mFinalStream->standby(); +} + + void AudioStreamOutDump::Close(void) { if(mOutFile) { diff --git a/libs/audioflinger/AudioDumpInterface.h b/libs/audioflinger/AudioDumpInterface.h index a65e56a..82b5250 100644 --- a/libs/audioflinger/AudioDumpInterface.h +++ b/libs/audioflinger/AudioDumpInterface.h @@ -40,6 +40,7 @@ public: virtual uint32_t latency() const { return mFinalStream->latency(); } virtual status_t setVolume(float volume) { return mFinalStream->setVolume(volume); } + virtual status_t standby(); virtual status_t dump(int fd, const Vector<String16>& args) { return mFinalStream->dump(fd, args); } void Close(void); @@ -54,7 +55,6 @@ class AudioDumpInterface : public AudioHardwareBase public: AudioDumpInterface(AudioHardwareInterface* hw); - virtual status_t standby(); virtual AudioStreamOut* openOutputStream( int format=0, int channelCount=0, diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp index 53b18ad..d4692ad 100644 --- a/libs/audioflinger/AudioFlinger.cpp +++ b/libs/audioflinger/AudioFlinger.cpp @@ -100,11 +100,11 @@ static bool settingsAllowed() { AudioFlinger::AudioFlinger() : BnAudioFlinger(), Thread(false), mMasterVolume(0), mMasterMute(true), mHardwareAudioMixer(0), mA2dpAudioMixer(0), - mAudioMixer(0), mAudioHardware(0), mA2dpAudioInterface(0), - mHardwareOutput(0), mA2dpOutput(0), mOutput(0), mAudioRecordThread(0), - mSampleRate(0), mFrameCount(0), mChannelCount(0), mFormat(0), - mMixBuffer(0), mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), - mStandby(false), mInWrite(false) + mAudioMixer(0), mAudioHardware(0), mA2dpAudioInterface(0), mHardwareOutput(0), + mA2dpOutput(0), mOutput(0), mRequestedOutput(0), mAudioRecordThread(0), + mSampleRate(0), mFrameCount(0), mChannelCount(0), mFormat(0), mMixBuffer(0), + mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mStandby(false), + mInWrite(false) { mHardwareStatus = AUDIO_HW_IDLE; mAudioHardware = AudioHardwareInterface::create(); @@ -116,9 +116,9 @@ AudioFlinger::AudioFlinger() mHardwareOutput = mAudioHardware->openOutputStream(AudioSystem::PCM_16_BIT, 0, 0, &status); mHardwareStatus = AUDIO_HW_IDLE; if (mHardwareOutput) { - mSampleRate = mHardwareOutput->sampleRate(); - mHardwareAudioMixer = new AudioMixer(getOutputFrameCount(mHardwareOutput), mSampleRate); - setOutput(mHardwareOutput); + mHardwareAudioMixer = new AudioMixer(getOutputFrameCount(mHardwareOutput), mHardwareOutput->sampleRate()); + mRequestedOutput = mHardwareOutput; + doSetOutput(mHardwareOutput); // FIXME - this should come from settings setMasterVolume(1.0f); @@ -159,7 +159,6 @@ AudioFlinger::AudioFlinger() } char value[PROPERTY_VALUE_MAX]; - // FIXME: What property should this be??? property_get("ro.audio.silent", value, "0"); if (atoi(value)) { LOGD("Silence is golden"); @@ -173,9 +172,8 @@ AudioFlinger::~AudioFlinger() mAudioRecordThread->exit(); mAudioRecordThread.clear(); } - delete mOutput; - delete mA2dpOutput; delete mAudioHardware; + // deleting mA2dpAudioInterface also deletes mA2dpOutput; delete mA2dpAudioInterface; delete [] mMixBuffer; delete mHardwareAudioMixer; @@ -184,26 +182,22 @@ AudioFlinger::~AudioFlinger() void AudioFlinger::setOutput(AudioStreamOut* output) { - // lock on mOutputLock to prevent threadLoop() from starving us - Mutex::Autolock _l2(mOutputLock); - - // to synchronize with threadLoop() - Mutex::Autolock _l(mLock); + mRequestedOutput = output; +} - if (mOutput != output) { - mSampleRate = output->sampleRate(); - mChannelCount = output->channelCount(); - - // FIXME - Current mixer implementation only supports stereo output - if (mChannelCount == 1) { - LOGE("Invalid audio hardware channel count"); - } - mFormat = output->format(); - mFrameCount = getOutputFrameCount(output); - - mAudioMixer = (output == mA2dpOutput ? mA2dpAudioMixer : mHardwareAudioMixer); - mOutput = output; +void AudioFlinger::doSetOutput(AudioStreamOut* output) +{ + mSampleRate = output->sampleRate(); + mChannelCount = output->channelCount(); + + // FIXME - Current mixer implementation only supports stereo output + if (mChannelCount == 1) { + LOGE("Invalid audio hardware channel count"); } + mFormat = output->format(); + mFrameCount = getOutputFrameCount(output); + mAudioMixer = (output == mA2dpOutput ? mA2dpAudioMixer : mHardwareAudioMixer); + mOutput = output; } size_t AudioFlinger::getOutputFrameCount(AudioStreamOut* output) @@ -330,21 +324,11 @@ bool AudioFlinger::threadLoop() Vector< sp<Track> > tracksToRemove; size_t enabledTracks = 0; nsecs_t standbyTime = systemTime(); - AudioMixer* mixer = 0; - size_t frameCount = 0; - int channelCount = 0; - uint32_t sampleRate = 0; - AudioStreamOut* output = 0; do { enabledTracks = 0; { // scope for the mLock - // locking briefly on the secondary mOutputLock is necessary to avoid - // having this thread starve the thread that called setOutput() - mOutputLock.lock(); - mOutputLock.unlock(); - Mutex::Autolock _l(mLock); const SortedVector< wp<Track> >& activeTracks = mActiveTracks; @@ -354,7 +338,7 @@ bool AudioFlinger::threadLoop() LOGV("Audio hardware entering standby\n"); mHardwareStatus = AUDIO_HW_STANDBY; if (!mStandby) { - mAudioHardware->standby(); + mOutput->standby(); mStandby = true; } mHardwareStatus = AUDIO_HW_IDLE; @@ -366,15 +350,16 @@ bool AudioFlinger::threadLoop() continue; } - // get active mixer and output parameter while the lock is held and keep them - // consistent till the next loop. - - mixer = audioMixer(); - frameCount = mFrameCount; - channelCount = mChannelCount; - sampleRate = mSampleRate; - output = mOutput; - + // check for change in output + if (mRequestedOutput != mOutput) { + + // put current output into standby mode + if (mOutput) mOutput->standby(); + + // change output + doSetOutput(mRequestedOutput); + } + // find out which tracks need to be processed size_t count = activeTracks.size(); for (size_t i=0 ; i<count ; i++) { @@ -386,7 +371,7 @@ bool AudioFlinger::threadLoop() // The first time a track is added we wait // for all its buffers to be filled before processing it - mixer->setActiveTrack(track->name()); + mAudioMixer->setActiveTrack(track->name()); if (cblk->framesReady() && (track->isReady() || track->isStopped()) && !track->isPaused()) { @@ -412,8 +397,8 @@ bool AudioFlinger::threadLoop() } // XXX: these things DON'T need to be done each time - mixer->setBufferProvider(track); - mixer->enable(AudioMixer::MIXING); + mAudioMixer->setBufferProvider(track); + mAudioMixer->enable(AudioMixer::MIXING); int param; if ( track->mFillingUpStatus == Track::FS_FILLED) { @@ -428,15 +413,15 @@ bool AudioFlinger::threadLoop() } else { param = AudioMixer::RAMP_VOLUME; } - mixer->setParameter(param, AudioMixer::VOLUME0, left); - mixer->setParameter(param, AudioMixer::VOLUME1, right); - mixer->setParameter( + mAudioMixer->setParameter(param, AudioMixer::VOLUME0, left); + mAudioMixer->setParameter(param, AudioMixer::VOLUME1, right); + mAudioMixer->setParameter( AudioMixer::TRACK, AudioMixer::FORMAT, track->format()); - mixer->setParameter( + mAudioMixer->setParameter( AudioMixer::TRACK, AudioMixer::CHANNEL_COUNT, track->channelCount()); - mixer->setParameter( + mAudioMixer->setParameter( AudioMixer::RESAMPLE, AudioMixer::SAMPLE_RATE, int(cblk->sampleRate)); @@ -463,7 +448,7 @@ bool AudioFlinger::threadLoop() } } // LOGV("disable(%d)", track->name()); - mixer->disable(AudioMixer::MIXING); + mAudioMixer->disable(AudioMixer::MIXING); } } @@ -475,27 +460,27 @@ bool AudioFlinger::threadLoop() mActiveTracks.remove(track); if (track->isTerminated()) { mTracks.remove(track); - mixer->deleteTrackName(track->mName); + mAudioMixer->deleteTrackName(track->mName); } } } } if (LIKELY(enabledTracks)) { // mix buffers... - mixer->process(curBuf); + mAudioMixer->process(curBuf); // output audio to hardware mLastWriteTime = systemTime(); mInWrite = true; - size_t mixBufferSize = frameCount*channelCount*sizeof(int16_t); - output->write(curBuf, mixBufferSize); + size_t mixBufferSize = mFrameCount*mChannelCount*sizeof(int16_t); + mOutput->write(curBuf, mixBufferSize); mNumWrites++; mInWrite = false; mStandby = false; nsecs_t temp = systemTime(); standbyTime = temp + kStandbyTimeInNsecs; nsecs_t delta = temp - mLastWriteTime; - nsecs_t maxPeriod = seconds(frameCount) / sampleRate * 2; + nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 2; if (delta > maxPeriod) { LOGW("write blocked for %llu msecs", ns2ms(delta)); mNumDelayedWrites++; @@ -653,6 +638,8 @@ status_t AudioFlinger::setMasterVolume(float value) status_t AudioFlinger::setRouting(int mode, uint32_t routes, uint32_t mask) { + status_t err = NO_ERROR; + // check calling permissions if (!settingsAllowed()) { return PERMISSION_DENIED; @@ -677,16 +664,20 @@ status_t AudioFlinger::setRouting(int mode, uint32_t routes, uint32_t mask) } #endif - AutoMutex lock(mHardwareLock); - mHardwareStatus = AUDIO_HW_GET_ROUTING; - uint32_t r; - uint32_t err = mAudioHardware->getRouting(mode, &r); - if (err == NO_ERROR) { - r = (r & ~mask) | (routes & mask); - mHardwareStatus = AUDIO_HW_SET_ROUTING; - err = mAudioHardware->setRouting(mode, r); + // do nothing if only A2DP routing is affected + mask &= ~AudioSystem::ROUTE_BLUETOOTH_A2DP; + if (mask) { + AutoMutex lock(mHardwareLock); + mHardwareStatus = AUDIO_HW_GET_ROUTING; + uint32_t r; + err = mAudioHardware->getRouting(mode, &r); + if (err == NO_ERROR) { + r = (r & ~mask) | (routes & mask); + mHardwareStatus = AUDIO_HW_SET_ROUTING; + err = mAudioHardware->setRouting(mode, r); + } + mHardwareStatus = AUDIO_HW_IDLE; } - mHardwareStatus = AUDIO_HW_IDLE; return err; } diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h index d9f7b49..7c84e62 100644 --- a/libs/audioflinger/AudioFlinger.h +++ b/libs/audioflinger/AudioFlinger.h @@ -150,6 +150,7 @@ private: virtual ~AudioFlinger(); void setOutput(AudioStreamOut* output); + void doSetOutput(AudioStreamOut* output); size_t getOutputFrameCount(AudioStreamOut* output); // Internal dump utilites. @@ -450,7 +451,6 @@ private: mutable Mutex mHardwareLock; mutable Mutex mLock; - mutable Mutex mOutputLock; mutable Condition mWaitWorkCV; DefaultKeyedVector< pid_t, wp<Client> > mClients; SortedVector< wp<Track> > mActiveTracks; @@ -468,6 +468,7 @@ private: AudioStreamOut* mHardwareOutput; AudioStreamOut* mA2dpOutput; AudioStreamOut* mOutput; + AudioStreamOut* mRequestedOutput; sp<AudioRecordThread> mAudioRecordThread; uint32_t mSampleRate; size_t mFrameCount; diff --git a/libs/audioflinger/AudioHardwareGeneric.cpp b/libs/audioflinger/AudioHardwareGeneric.cpp index e6a163b..e455186 100644 --- a/libs/audioflinger/AudioHardwareGeneric.cpp +++ b/libs/audioflinger/AudioHardwareGeneric.cpp @@ -61,12 +61,6 @@ status_t AudioHardwareGeneric::initCheck() return NO_INIT; } -status_t AudioHardwareGeneric::standby() -{ - // Implement: audio hardware to standby mode - return NO_ERROR; -} - AudioStreamOut* AudioHardwareGeneric::openOutputStream( int format, int channelCount, uint32_t sampleRate, status_t *status) { @@ -215,6 +209,12 @@ ssize_t AudioStreamOutGeneric::write(const void* buffer, size_t bytes) return ssize_t(::write(mFd, buffer, bytes)); } +status_t AudioStreamOutGeneric::standby() +{ + // Implement: audio hardware to standby mode + return NO_ERROR; +} + status_t AudioStreamOutGeneric::dump(int fd, const Vector<String16>& args) { const size_t SIZE = 256; diff --git a/libs/audioflinger/AudioHardwareGeneric.h b/libs/audioflinger/AudioHardwareGeneric.h index a2342cd..bc006b8 100644 --- a/libs/audioflinger/AudioHardwareGeneric.h +++ b/libs/audioflinger/AudioHardwareGeneric.h @@ -50,6 +50,7 @@ public: virtual uint32_t latency() const { return 0; } virtual status_t setVolume(float volume) { return INVALID_OPERATION; } virtual ssize_t write(const void* buffer, size_t bytes); + virtual status_t standby(); virtual status_t dump(int fd, const Vector<String16>& args); private: @@ -92,7 +93,6 @@ public: AudioHardwareGeneric(); virtual ~AudioHardwareGeneric(); virtual status_t initCheck(); - virtual status_t standby(); virtual status_t setVoiceVolume(float volume); virtual status_t setMasterVolume(float volume); diff --git a/libs/audioflinger/AudioHardwareStub.cpp b/libs/audioflinger/AudioHardwareStub.cpp index d309902..e9f3d69 100644 --- a/libs/audioflinger/AudioHardwareStub.cpp +++ b/libs/audioflinger/AudioHardwareStub.cpp @@ -41,11 +41,6 @@ status_t AudioHardwareStub::initCheck() return NO_ERROR; } -status_t AudioHardwareStub::standby() -{ - return NO_ERROR; -} - AudioStreamOut* AudioHardwareStub::openOutputStream( int format, int channelCount, uint32_t sampleRate, status_t *status) { @@ -125,6 +120,11 @@ ssize_t AudioStreamOutStub::write(const void* buffer, size_t bytes) return bytes; } +status_t AudioStreamOutStub::standby() +{ + return NO_ERROR; +} + status_t AudioStreamOutStub::dump(int fd, const Vector<String16>& args) { const size_t SIZE = 256; diff --git a/libs/audioflinger/AudioHardwareStub.h b/libs/audioflinger/AudioHardwareStub.h index 5316d60..7ec5b95 100644 --- a/libs/audioflinger/AudioHardwareStub.h +++ b/libs/audioflinger/AudioHardwareStub.h @@ -37,6 +37,7 @@ public: virtual uint32_t latency() const { return 0; } virtual status_t setVolume(float volume) { return NO_ERROR; } virtual ssize_t write(const void* buffer, size_t bytes); + virtual status_t standby(); virtual status_t dump(int fd, const Vector<String16>& args); }; @@ -59,7 +60,6 @@ public: AudioHardwareStub(); virtual ~AudioHardwareStub(); virtual status_t initCheck(); - virtual status_t standby(); virtual status_t setVoiceVolume(float volume); virtual status_t setMasterVolume(float volume); diff --git a/libs/surfaceflinger/BootAnimation.cpp b/libs/surfaceflinger/BootAnimation.cpp index e9e34c3..d18f59a 100644 --- a/libs/surfaceflinger/BootAnimation.cpp +++ b/libs/surfaceflinger/BootAnimation.cpp @@ -36,8 +36,8 @@ #include <ui/ISurfaceFlingerClient.h> #include <ui/EGLNativeWindowSurface.h> -#include <graphics/SkBitmap.h> -#include <graphics/SkImageDecoder.h> +#include <core/SkBitmap.h> +#include <images/SkImageDecoder.h> #include <GLES/egl.h> diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp index cd72179..19e32ec 100644 --- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp +++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp @@ -250,7 +250,7 @@ void DisplayHardware::init(uint32_t dpy) mOverlayEngine = NULL; if (hw_get_module(OVERLAY_HARDWARE_MODULE_ID, &module) == 0) { - overlay_open(module, &mOverlayEngine); + overlay_control_open(module, &mOverlayEngine); } } @@ -266,7 +266,7 @@ void DisplayHardware::fini() eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglTerminate(mDisplay); copybit_close(mBlitEngine); - overlay_close(mOverlayEngine); + overlay_control_close(mOverlayEngine); } void DisplayHardware::releaseScreen() const diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h index de4a2cc..df97b60 100644 --- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h +++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h @@ -26,7 +26,7 @@ #include "DisplayHardware/DisplayHardwareBase.h" -struct overlay_device_t; +struct overlay_control_device_t; struct copybit_device_t; struct copybit_image_t; struct copybit_t; @@ -78,7 +78,7 @@ public: void getDisplaySurface(GGLSurface* fb) const; EGLDisplay getEGLDisplay() const { return mDisplay; } copybit_device_t* getBlitEngine() const { return mBlitEngine; } - overlay_device_t* getOverlayEngine() const { return mOverlayEngine; } + overlay_control_device_t* getOverlayEngine() const { return mOverlayEngine; } Rect bounds() const { return Rect(mWidth, mHeight); @@ -103,7 +103,7 @@ private: mutable Region mDirty; sp<EGLDisplaySurface> mDisplaySurface; copybit_device_t* mBlitEngine; - overlay_device_t* mOverlayEngine; + overlay_control_device_t* mOverlayEngine; }; }; // namespace android diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp index 8ba0851..f65d669 100644 --- a/libs/surfaceflinger/Layer.cpp +++ b/libs/surfaceflinger/Layer.cpp @@ -316,7 +316,7 @@ uint32_t Layer::doTransaction(uint32_t flags) if (err == NO_ERROR) { const uint32_t mask = clientBackBufferIndex ? eResizeBuffer1 : eResizeBuffer0; android_atomic_and(~mask, &(lcblk->swapState)); - // since a buffer became availlable, we can let the client go... + // since a buffer became available, we can let the client go... mFlinger->scheduleBroadcast(client); mResizeTransactionDone = true; @@ -511,7 +511,7 @@ Region Layer::post(uint32_t* previousSate, bool& recomputeVisibleRegions) } mResizeTransactionDone = false; recomputeVisibleRegions = true; - invalidate = true; + this->contentDirty = true; } } diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp index af353e2..bdefba3 100644 --- a/libs/surfaceflinger/LayerBase.cpp +++ b/libs/surfaceflinger/LayerBase.cpp @@ -53,14 +53,15 @@ Vector<GLuint> LayerBase::deletedTextures; int32_t LayerBase::sIdentity = 0; LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display) - : dpy(display), invalidate(false), + : dpy(display), contentDirty(false), mFlinger(flinger), mTransformed(false), mOrientation(0), mCanUseCopyBit(false), mTransactionFlags(0), mPremultipliedAlpha(true), - mIdentity(uint32_t(android_atomic_inc(&sIdentity))) + mIdentity(uint32_t(android_atomic_inc(&sIdentity))), + mInvalidate(0) { const DisplayHardware& hw(flinger->graphicPlane(0).displayHardware()); mFlags = hw.getFlags(); @@ -205,7 +206,7 @@ uint32_t LayerBase::doTransaction(uint32_t flags) if (temp.sequence != front.sequence) { // invalidate and recompute the visible regions if needed flags |= eVisibleRegion; - this->invalidate = true; + this->contentDirty = true; } // Commit the transaction @@ -299,12 +300,22 @@ void LayerBase::lockPageFlip(bool& recomputeVisibleRegions) void LayerBase::unlockPageFlip( const Transform& planeTransform, Region& outDirtyRegion) { + if ((android_atomic_and(~1, &mInvalidate)&1) == 1) { + outDirtyRegion.orSelf(visibleRegionScreen); + } } void LayerBase::finishPageFlip() { } +void LayerBase::invalidate() +{ + if ((android_atomic_or(1, &mInvalidate)&1) == 0) { + mFlinger->signalEvent(); + } +} + void LayerBase::drawRegion(const Region& reg) const { Region::iterator iterator(reg); diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h index b3f3771..5e14dc8 100644 --- a/libs/surfaceflinger/LayerBase.h +++ b/libs/surfaceflinger/LayerBase.h @@ -75,7 +75,7 @@ public: virtual ~LayerBase(); DisplayID dpy; - mutable bool invalidate; + mutable bool contentDirty; Region visibleRegionScreen; Region transparentRegionScreen; Region coveredRegionScreen; @@ -112,18 +112,87 @@ public: Rect visibleBounds() const; void drawRegion(const Region& reg) const; + void invalidate(); + + /** + * draw - performs some global clipping optimizations + * and calls onDraw(). + * Typically this method is not overridden, instead implement onDraw() + * to perform the actual drawing. + */ virtual void draw(const Region& clip) const; + + /** + * onDraw - draws the surface. + */ virtual void onDraw(const Region& clip) const = 0; + + /** + * initStates - called just after construction + */ virtual void initStates(uint32_t w, uint32_t h, uint32_t flags); + + /** + * setSizeChanged - called when the *current* state's size is changed. + */ virtual void setSizeChanged(uint32_t w, uint32_t h); + + /** + * doTransaction - process the transaction. This is a good place to figure + * out which attributes of the surface have changed. + */ virtual uint32_t doTransaction(uint32_t transactionFlags); + + /** + * setVisibleRegion - called to set the new visible region. This gives + * a chance to update the new visible region or record the fact it changed. + */ virtual void setVisibleRegion(const Region& visibleRegion); + + /** + * setCoveredRegion - called when the covered region changes. The covered + * region correspond to any area of the surface that is covered + * (transparently or not) by another surface. + */ virtual void setCoveredRegion(const Region& coveredRegion); + + /** + * getPhysicalSize - returns the physical size of the drawing state of + * the surface. If the surface is backed by a bitmap, this is the size of + * the bitmap (as opposed to the size of the drawing state). + */ virtual Point getPhysicalSize() const; + + /** + * lockPageFlip - called each time the screen is redrawn and returns whether + * the visible regions need to be recomputed (this is a fairly heavy + * operation, so this should be set only if needed). Typically this is used + * to figure out if the content or size of a surface has changed. + */ virtual void lockPageFlip(bool& recomputeVisibleRegions); + + /** + * unlockPageFlip - called each time the screen is redrawn. updates the + * final dirty region wrt the planeTransform. + * At this point, all visible regions, surface position and size, etc... are + * correct. + */ virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion); + + /** + * finishPageFlip - called after all surfaces have drawn. + */ virtual void finishPageFlip(); + + /** + * needsBlending - true if this surface needs blending + */ virtual bool needsBlending() const { return false; } + + /** + * isSecure - true if this surface is secure, that is if it prevents a + * screenshot to be taken, + */ virtual bool isSecure() const { return false; } enum { // flags for doTransaction() @@ -162,7 +231,6 @@ protected: bool canUseCopybit() const; - SurfaceFlinger* mFlinger; uint32_t mFlags; @@ -184,7 +252,10 @@ protected: bool mPremultipliedAlpha; // only read - const uint32_t mIdentity; + const uint32_t mIdentity; + + // atomic + volatile int32_t mInvalidate; private: @@ -254,7 +325,7 @@ public: { return INVALID_OPERATION; } virtual void postBuffer(ssize_t offset) { } virtual void unregisterBuffers() { }; - virtual sp<Overlay> createOverlay( + virtual sp<OverlayRef> createOverlay( uint32_t w, uint32_t h, int32_t format) { return NULL; }; diff --git a/libs/surfaceflinger/LayerBlur.cpp b/libs/surfaceflinger/LayerBlur.cpp index e3ae7fb..efadbcf 100644 --- a/libs/surfaceflinger/LayerBlur.cpp +++ b/libs/surfaceflinger/LayerBlur.cpp @@ -71,7 +71,7 @@ uint32_t LayerBlur::doTransaction(uint32_t flags) mRefreshCache = true; mCacheDirty = true; flags |= eVisibleRegion; - this->invalidate = true; + this->contentDirty = true; } return LayerBase::doTransaction(flags); } diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp index 3861e68..700e4f5 100644 --- a/libs/surfaceflinger/LayerBuffer.cpp +++ b/libs/surfaceflinger/LayerBuffer.cpp @@ -46,7 +46,7 @@ const char* const LayerBuffer::typeID = "LayerBuffer"; LayerBuffer::LayerBuffer(SurfaceFlinger* flinger, DisplayID display, Client* client, int32_t i) : LayerBaseClient(flinger, display, client, i), - mBuffer(0), mTextureName(-1U), mInvalidate(false), mNeedsBlending(false) + mNeedsBlending(false) { } @@ -57,43 +57,333 @@ LayerBuffer::~LayerBuffer() s->disown(); mClientSurface.clear(); } +} - // this should always be called from the OpenGL thread - if (mTextureName != -1U) { - //glDeleteTextures(1, &mTextureName); - deletedTextures.add(mTextureName); - } - // to help debugging we set those to zero - mWidth = mHeight = 0; +sp<LayerBuffer::SurfaceBuffer> LayerBuffer::getClientSurface() const +{ + Mutex::Autolock _l(mLock); + return mClientSurface.promote(); } -bool LayerBuffer::needsBlending() const +sp<LayerBaseClient::Surface> LayerBuffer::getSurface() const { + sp<SurfaceBuffer> s; Mutex::Autolock _l(mLock); + s = mClientSurface.promote(); + if (s == 0) { + s = new SurfaceBuffer(clientIndex(), + const_cast<LayerBuffer *>(this)); + mClientSurface = s; + } + return s; +} + +bool LayerBuffer::needsBlending() const { return mNeedsBlending; } +void LayerBuffer::setNeedsBlending(bool blending) { + mNeedsBlending = blending; +} + +void LayerBuffer::postBuffer(ssize_t offset) +{ + sp<Source> source(getSource()); + if (source != 0) + source->postBuffer(offset); +} + +void LayerBuffer::unregisterBuffers() +{ + sp<Source> source(getSource()); + if (source != 0) + source->unregisterBuffers(); + // XXX: clear mSource +} + +uint32_t LayerBuffer::doTransaction(uint32_t flags) +{ + sp<Source> source(getSource()); + if (source != 0) + source->onTransaction(flags); + return LayerBase::doTransaction(flags); +} + +void LayerBuffer::unlockPageFlip(const Transform& planeTransform, + Region& outDirtyRegion) +{ + // this code-path must be as tight as possible, it's called each time + // the screen is composited. + sp<Source> source(getSource()); + if (source != 0) + source->onVisibilityResolved(planeTransform); + LayerBase::unlockPageFlip(planeTransform, outDirtyRegion); +} + void LayerBuffer::onDraw(const Region& clip) const { + sp<Source> source(getSource()); + if (LIKELY(source != 0)) { + source->onDraw(clip); + } else { + clearWithOpenGL(clip); + } +} + +/** + * This creates a "buffer" source for this surface + */ +status_t LayerBuffer::registerBuffers(int w, int h, int hstride, int vstride, + PixelFormat format, const sp<IMemoryHeap>& memoryHeap) +{ + Mutex::Autolock _l(mLock); + if (mSource != 0) + return INVALID_OPERATION; + + sp<BufferSource> source = new BufferSource(*this, w, h, + hstride, vstride, format, memoryHeap); + + status_t result = source->getStatus(); + if (result == NO_ERROR) { + mSource = source; + } + return result; +} + +/** + * This creates an "overlay" source for this surface + */ +sp<OverlayRef> LayerBuffer::createOverlay(uint32_t w, uint32_t h, int32_t f) +{ + sp<OverlayRef> result; + Mutex::Autolock _l(mLock); + if (mSource != 0) + return result; + + sp<OverlaySource> source = new OverlaySource(*this, &result, w, h, f); + if (result != 0) { + mSource = source; + } + return result; +} + +sp<LayerBuffer::Source> LayerBuffer::getSource() const { + Mutex::Autolock _l(mLock); + return mSource; +} + +// ============================================================================ +// LayerBuffer::SurfaceBuffer +// ============================================================================ + +LayerBuffer::SurfaceBuffer::SurfaceBuffer(SurfaceID id, LayerBuffer* owner) +: LayerBaseClient::Surface(id, owner->getIdentity()), mOwner(owner) +{ +} + +LayerBuffer::SurfaceBuffer::~SurfaceBuffer() +{ + unregisterBuffers(); + mOwner = 0; +} + +status_t LayerBuffer::SurfaceBuffer::registerBuffers( + int w, int h, int hs, int vs, + PixelFormat format, const sp<IMemoryHeap>& heap) +{ + LayerBuffer* owner(getOwner()); + if (owner) + return owner->registerBuffers(w, h, hs, vs, format, heap); + return NO_INIT; +} + +void LayerBuffer::SurfaceBuffer::postBuffer(ssize_t offset) +{ + LayerBuffer* owner(getOwner()); + if (owner) + owner->postBuffer(offset); +} + +void LayerBuffer::SurfaceBuffer::unregisterBuffers() +{ + LayerBuffer* owner(getOwner()); + if (owner) + owner->unregisterBuffers(); +} + +sp<OverlayRef> LayerBuffer::SurfaceBuffer::createOverlay( + uint32_t w, uint32_t h, int32_t format) { + sp<OverlayRef> result; + LayerBuffer* owner(getOwner()); + if (owner) + result = owner->createOverlay(w, h, format); + return result; +} + +void LayerBuffer::SurfaceBuffer::disown() +{ + Mutex::Autolock _l(mLock); + mOwner = 0; +} + +// ============================================================================ +// LayerBuffer::Buffer +// ============================================================================ + +LayerBuffer::Buffer::Buffer(const sp<IMemoryHeap>& heap, ssize_t offset, + int w, int h, int hs, int vs, int f) +: mHeap(heap) +{ + NativeBuffer& src(mNativeBuffer); + src.crop.l = 0; + src.crop.t = 0; + src.crop.r = w; + src.crop.b = h; + src.img.w = hs ?: w; + src.img.h = vs ?: h; + src.img.format = f; + src.img.offset = offset; + src.img.base = heap->base(); + src.img.fd = heap->heapID(); + // FIXME: make sure this buffer lies within the heap, in which case, set + // mHeap to null +} + +LayerBuffer::Buffer::~Buffer() +{ +} + +// ============================================================================ +// LayerBuffer::Source +// LayerBuffer::BufferSource +// LayerBuffer::OverlaySource +// ============================================================================ + +LayerBuffer::Source::Source(LayerBuffer& layer) + : mLayer(layer) +{ +} +LayerBuffer::Source::~Source() { +} +void LayerBuffer::Source::onDraw(const Region& clip) const { +} +void LayerBuffer::Source::onTransaction(uint32_t flags) { +} +void LayerBuffer::Source::onVisibilityResolved( + const Transform& planeTransform) { +} +void LayerBuffer::Source::postBuffer(ssize_t offset) { +} +void LayerBuffer::Source::unregisterBuffers() { +} + +// --------------------------------------------------------------------------- + +LayerBuffer::BufferSource::BufferSource(LayerBuffer& layer, + int w, int h, int hstride, int vstride, + PixelFormat format, const sp<IMemoryHeap>& memoryHeap) + : Source(layer), mStatus(NO_ERROR), mTextureName(-1U) +{ + if (memoryHeap == NULL) { + // this is allowed, but in this case, it is illegal to receive + // postBuffer(). The surface just erases the framebuffer with + // fully transparent pixels. + mHeap.clear(); + mWidth = w; + mHeight = h; + mLayer.setNeedsBlending(false); + return; + } + + status_t err = (memoryHeap->heapID() >= 0) ? NO_ERROR : NO_INIT; + if (err != NO_ERROR) { + mStatus = err; + return; + } + + // TODO: validate format/parameters + mHeap = memoryHeap; + mWidth = w; + mHeight = h; + mHStride = hstride; + mVStride = vstride; + mFormat = format; + PixelFormatInfo info; + getPixelFormatInfo(format, &info); + mLayer.setNeedsBlending((info.h_alpha - info.l_alpha) > 0); +} + +LayerBuffer::BufferSource::~BufferSource() +{ + if (mTextureName != -1U) { + LayerBase::deletedTextures.add(mTextureName); + } +} + +void LayerBuffer::BufferSource::postBuffer(ssize_t offset) +{ + sp<IMemoryHeap> heap; + int w, h, hs, vs, f; + { // scope for the lock + Mutex::Autolock _l(mLock); + w = mWidth; + h = mHeight; + hs= mHStride; + vs= mVStride; + f = mFormat; + heap = mHeap; + } + + sp<Buffer> buffer; + if (heap != 0) { + buffer = new LayerBuffer::Buffer(heap, offset, w, h, hs, vs, f); + if (buffer->getStatus() != NO_ERROR) + buffer.clear(); + setBuffer(buffer); + mLayer.invalidate(); + } +} + +void LayerBuffer::BufferSource::unregisterBuffers() +{ + Mutex::Autolock _l(mLock); + mHeap.clear(); + mBuffer.clear(); + mLayer.invalidate(); +} + +sp<LayerBuffer::Buffer> LayerBuffer::BufferSource::getBuffer() const +{ + Mutex::Autolock _l(mLock); + return mBuffer; +} + +void LayerBuffer::BufferSource::setBuffer(const sp<LayerBuffer::Buffer>& buffer) +{ + Mutex::Autolock _l(mLock); + mBuffer = buffer; +} + +void LayerBuffer::BufferSource::onDraw(const Region& clip) const +{ sp<Buffer> buffer(getBuffer()); if (UNLIKELY(buffer == 0)) { // nothing to do, we don't have a buffer - clearWithOpenGL(clip); + mLayer.clearWithOpenGL(clip); return; } status_t err = NO_ERROR; NativeBuffer src(buffer->getBuffer()); - const int can_use_copybit = canUseCopybit(); + const Rect& transformedBounds = mLayer.getTransformedBounds(); + const int can_use_copybit = mLayer.canUseCopybit(); if (can_use_copybit) { - //StopWatch watch("MDP"); - const int src_width = src.crop.r - src.crop.l; const int src_height = src.crop.b - src.crop.t; - int W = mTransformedBounds.width(); - int H = mTransformedBounds.height(); - if (getOrientation() & Transform::ROT_90) { + int W = transformedBounds.width(); + int H = transformedBounds.height(); + if (mLayer.getOrientation() & Transform::ROT_90) { int t(W); W=H; H=t; } @@ -104,7 +394,7 @@ void LayerBuffer::onDraw(const Region& clip) const * the requested scale factor, in which case we perform the scaling * in several passes. */ - copybit_device_t* copybit = mFlinger->getBlitEngine(); + copybit_device_t* copybit = mLayer.mFlinger->getBlitEngine(); const float min = copybit->get(copybit, COPYBIT_MINIFICATION_LIMIT); const float mag = copybit->get(copybit, COPYBIT_MAGNIFICATION_LIMIT); @@ -117,13 +407,10 @@ void LayerBuffer::onDraw(const Region& clip) const else if (src_height*mag < H) yscale = mag; if (UNLIKELY(xscale!=1.0f || yscale!=1.0f)) { - //LOGD("MDP scaling hack w=%d, h=%d, ww=%d, wh=%d, xs=%f, ys=%f", - // src_width, src_height, W, H, xscale, yscale); - if (UNLIKELY(mTemporaryDealer == 0)) { // allocate a memory-dealer for this the first time - mTemporaryDealer = mFlinger->getSurfaceHeapManager() - ->createHeap(ISurfaceComposer::eHardware); + mTemporaryDealer = mLayer.mFlinger->getSurfaceHeapManager() + ->createHeap(ISurfaceComposer::eHardware); mTempBitmap.init(mTemporaryDealer); } @@ -149,14 +436,14 @@ void LayerBuffer::onDraw(const Region& clip) const } } - const DisplayHardware& hw(graphicPlane(0).displayHardware()); + const DisplayHardware& hw(mLayer.graphicPlane(0).displayHardware()); copybit_image_t dst; hw.getDisplaySurface(&dst); const copybit_rect_t& drect - = reinterpret_cast<const copybit_rect_t&>(mTransformedBounds); - const State& s(drawingState()); + = reinterpret_cast<const copybit_rect_t&>(transformedBounds); + const State& s(mLayer.drawingState()); region_iterator it(clip); - copybit->set_parameter(copybit, COPYBIT_TRANSFORM, getOrientation()); + copybit->set_parameter(copybit, COPYBIT_TRANSFORM, mLayer.getOrientation()); copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha); copybit->set_parameter(copybit, COPYBIT_DITHER, s.flags & ISurfaceComposer::eLayerDither ? @@ -167,245 +454,115 @@ void LayerBuffer::onDraw(const Region& clip) const if (!can_use_copybit || err) { if (UNLIKELY(mTextureName == -1LU)) { - mTextureName = createTexture(); + mTextureName = mLayer.createTexture(); } GLuint w = 0; GLuint h = 0; GGLSurface t; - t.version = sizeof(GGLSurface); - t.width = src.crop.r; - t.height = src.crop.b; - t.stride = src.img.w; - t.vstride= src.img.h; - t.format = src.img.format; - t.data = (GGLubyte*)(intptr_t(src.img.base) + src.img.offset); + t.version = sizeof(GGLSurface); + t.width = src.crop.r; + t.height = src.crop.b; + t.stride = src.img.w; + t.vstride= src.img.h; + t.format = src.img.format; + t.data = (GGLubyte*)(intptr_t(src.img.base) + src.img.offset); const Region dirty(Rect(t.width, t.height)); - loadTexture(dirty, mTextureName, t, w, h); - drawWithOpenGL(clip, mTextureName, t); + mLayer.loadTexture(dirty, mTextureName, t, w, h); + mLayer.drawWithOpenGL(clip, mTextureName, t); } } -void LayerBuffer::invalidateLocked() -{ - mInvalidate = true; - mFlinger->signalEvent(); -} - -void LayerBuffer::invalidate() -{ - Mutex::Autolock _l(mLock); - invalidateLocked(); -} - -void LayerBuffer::unlockPageFlip(const Transform& planeTransform, - Region& outDirtyRegion) -{ - Mutex::Autolock _l(mLock); - if (mInvalidate) { - mInvalidate = false; - outDirtyRegion.orSelf(visibleRegionScreen); - } -} - -sp<LayerBuffer::SurfaceBuffer> LayerBuffer::getClientSurface() const -{ - Mutex::Autolock _l(mLock); - return mClientSurface.promote(); -} - -sp<LayerBaseClient::Surface> LayerBuffer::getSurface() const -{ - sp<SurfaceBuffer> s; - Mutex::Autolock _l(mLock); - s = mClientSurface.promote(); - if (s == 0) { - s = new SurfaceBuffer(clientIndex(), - const_cast<LayerBuffer *>(this)); - mClientSurface = s; - } - return s; -} - - -status_t LayerBuffer::registerBuffers(int w, int h, int hstride, int vstride, - PixelFormat format, const sp<IMemoryHeap>& memoryHeap) -{ - if (memoryHeap == NULL) { - // this is allowed, but in this case, it is illegal to receive - // postBuffer(). The surface just erases the framebuffer with - // fully transparent pixels. - mHeap.clear(); - mWidth = w; - mHeight = h; - mNeedsBlending = false; - return NO_ERROR; - } - - status_t err = (memoryHeap->heapID() >= 0) ? NO_ERROR : NO_INIT; - if (err != NO_ERROR) - return err; - - // TODO: validate format/parameters - - Mutex::Autolock _l(mLock); - mHeap = memoryHeap; - mWidth = w; - mHeight = h; - mHStride = hstride; - mVStride = vstride; - mFormat = format; - PixelFormatInfo info; - getPixelFormatInfo(format, &info); - mNeedsBlending = (info.h_alpha - info.l_alpha) > 0; - return NO_ERROR; -} - -void LayerBuffer::postBuffer(ssize_t offset) -{ - sp<IMemoryHeap> heap; - int w, h, hs, vs, f; - { // scope for the lock - Mutex::Autolock _l(mLock); - w = mWidth; - h = mHeight; - hs= mHStride; - vs= mVStride; - f = mFormat; - heap = mHeap; - } - - sp<Buffer> buffer; - if (heap != 0) { - buffer = new Buffer(heap, offset, w, h, hs, vs, f); - if (buffer->getStatus() != NO_ERROR) - buffer.clear(); - setBuffer(buffer); - invalidate(); - } -} +// --------------------------------------------------------------------------- -void LayerBuffer::unregisterBuffers() +LayerBuffer::OverlaySource::OverlaySource(LayerBuffer& layer, + sp<OverlayRef>* overlayRef, + uint32_t w, uint32_t h, int32_t format) + : Source(layer), mVisibilityChanged(false), mOverlay(0), mOverlayHandle(0) { - Mutex::Autolock _l(mLock); - mHeap.clear(); - mBuffer.clear(); - invalidateLocked(); -} + overlay_control_device_t* overlay_dev = mLayer.mFlinger->getOverlayEngine(); -sp<Overlay> LayerBuffer::createOverlay(uint32_t w, uint32_t h, int32_t format) -{ - sp<Overlay> result; - Mutex::Autolock _l(mLock); - if (mHeap != 0 || mBuffer != 0) { - // we're a push surface. error. - return result; - } - - overlay_device_t* overlay_dev = mFlinger->getOverlayEngine(); if (overlay_dev == NULL) { // overlays not supported - return result; + return; } overlay_t* overlay = overlay_dev->createOverlay(overlay_dev, w, h, format); if (overlay == NULL) { // couldn't create the overlay (no memory? no more overlays?) - return result; + return; } - - /* TODO: implement the real stuff here */ - - return result; -} - -sp<LayerBuffer::Buffer> LayerBuffer::getBuffer() const -{ - Mutex::Autolock _l(mLock); - return mBuffer; -} -void LayerBuffer::setBuffer(const sp<LayerBuffer::Buffer>& buffer) -{ - Mutex::Autolock _l(mLock); - mBuffer = buffer; -} + // enable dithering... + overlay_dev->setParameter(overlay_dev, overlay, + OVERLAY_DITHER, OVERLAY_ENABLE); -// --------------------------------------------------------------------------- + mOverlay = overlay; + mWidth = overlay->w; + mHeight = overlay->h; + mFormat = overlay->format; + mWidthStride = overlay->w_stride; + mHeightStride = overlay->h_stride; -LayerBuffer::SurfaceBuffer::SurfaceBuffer(SurfaceID id, LayerBuffer* owner) - : LayerBaseClient::Surface(id, owner->getIdentity()), mOwner(owner) -{ -} + mOverlayHandle = overlay->getHandleRef(overlay); + + // NOTE: here it's okay to acquire a reference to "this"m as long as + // the reference is not released before we leave the ctor. + sp<OverlayChanel> chanel = new OverlayChanel(this); -LayerBuffer::SurfaceBuffer::~SurfaceBuffer() -{ - unregisterBuffers(); - mOwner = 0; + *overlayRef = new OverlayRef(mOverlayHandle, chanel, + mWidth, mHeight, mFormat, mWidthStride, mHeightStride); } -status_t LayerBuffer::SurfaceBuffer::registerBuffers( - int w, int h, int hs, int vs, - PixelFormat format, const sp<IMemoryHeap>& heap) -{ - LayerBuffer* owner(getOwner()); - if (owner) - return owner->registerBuffers(w, h, hs, vs, format, heap); - return NO_INIT; +LayerBuffer::OverlaySource::~OverlaySource() +{ } -void LayerBuffer::SurfaceBuffer::postBuffer(ssize_t offset) +void LayerBuffer::OverlaySource::onTransaction(uint32_t flags) { - LayerBuffer* owner(getOwner()); - if (owner) - owner->postBuffer(offset); + const Layer::State& front(mLayer.drawingState()); + const Layer::State& temp(mLayer.currentState()); + if (temp.sequence != front.sequence) { + mVisibilityChanged = true; + } } -void LayerBuffer::SurfaceBuffer::unregisterBuffers() +void LayerBuffer::OverlaySource::onVisibilityResolved( + const Transform& planeTransform) { - LayerBuffer* owner(getOwner()); - if (owner) - owner->unregisterBuffers(); -} - -sp<Overlay> LayerBuffer::SurfaceBuffer::createOverlay( - uint32_t w, uint32_t h, int32_t format) { - sp<Overlay> result; - LayerBuffer* owner(getOwner()); - if (owner) - result = owner->createOverlay(w, h, format); - return result; + // this code-path must be as tight as possible, it's called each time + // the screen is composited. + if (UNLIKELY(mOverlay != 0)) { + if (mVisibilityChanged) { + mVisibilityChanged = false; + const Rect& bounds = mLayer.getTransformedBounds(); + int x = bounds.left; + int y = bounds.top; + int w = bounds.width(); + int h = bounds.height(); + + // we need a lock here to protect "destroy" + Mutex::Autolock _l(mLock); + if (mOverlay) { + overlay_control_device_t* overlay_dev = + mLayer.mFlinger->getOverlayEngine(); + overlay_dev->setPosition(overlay_dev, mOverlay, x,y,w,h); + overlay_dev->setParameter(overlay_dev, mOverlay, + OVERLAY_TRANSFORM, mLayer.getOrientation()); + } + } + } } -void LayerBuffer::SurfaceBuffer::disown() +void LayerBuffer::OverlaySource::serverDestroy() { + // we need a lock here to protect "onVisibilityResolved" Mutex::Autolock _l(mLock); - mOwner = 0; -} - - -// --------------------------------------------------------------------------- - -LayerBuffer::Buffer::Buffer(const sp<IMemoryHeap>& heap, ssize_t offset, - int w, int h, int hs, int vs, int f) - : mCount(0), mHeap(heap) -{ - NativeBuffer& src(mNativeBuffer); - src.crop.l = 0; - src.crop.t = 0; - src.crop.r = w; - src.crop.b = h; - src.img.w = hs ?: w; - src.img.h = vs ?: h; - src.img.format = f; - src.img.offset = offset; - src.img.base = heap->base(); - src.img.fd = heap->heapID(); - // FIXME: make sure this buffer lies within the heap, in which case, set - // mHeap to null -} - -LayerBuffer::Buffer::~Buffer() -{ + if (mOverlay) { + overlay_control_device_t* overlay_dev = + mLayer.mFlinger->getOverlayEngine(); + overlay_dev->destroyOverlay(overlay_dev, mOverlay); + mOverlay = 0; + } } // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/LayerBuffer.h b/libs/surfaceflinger/LayerBuffer.h index 3e616f2..63ec2cf 100644 --- a/libs/surfaceflinger/LayerBuffer.h +++ b/libs/surfaceflinger/LayerBuffer.h @@ -33,10 +33,24 @@ namespace android { class MemoryDealer; class Region; -class Overlay; +class OverlayRef; class LayerBuffer : public LayerBaseClient { + class Source : public LightRefBase<Source> { + public: + Source(LayerBuffer& layer); + virtual ~Source(); + virtual void onDraw(const Region& clip) const; + virtual void onTransaction(uint32_t flags); + virtual void onVisibilityResolved(const Transform& planeTransform); + virtual void postBuffer(ssize_t offset); + virtual void unregisterBuffers(); + protected: + LayerBuffer& mLayer; + }; + + public: static const uint32_t typeInfo; static const char* const typeID; @@ -51,39 +65,31 @@ public: virtual sp<LayerBaseClient::Surface> getSurface() const; virtual void onDraw(const Region& clip) const; + virtual uint32_t doTransaction(uint32_t flags); virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion); status_t registerBuffers(int w, int h, int hstride, int vstride, PixelFormat format, const sp<IMemoryHeap>& heap); void postBuffer(ssize_t offset); void unregisterBuffers(); - sp<Overlay> createOverlay(uint32_t w, uint32_t h, int32_t format); - void invalidate(); - void invalidateLocked(); + sp<OverlayRef> createOverlay(uint32_t w, uint32_t h, int32_t format); + + sp<Source> getSource() const; + void setNeedsBlending(bool blending); + const Rect& getTransformedBounds() const { + return mTransformedBounds; + } private: - - struct NativeBuffer - { + struct NativeBuffer { copybit_image_t img; copybit_rect_t crop; }; - class Buffer - { + class Buffer : public LightRefBase<Buffer> { public: Buffer(const sp<IMemoryHeap>& heap, ssize_t offset, int w, int h, int hs, int vs, int f); - inline void incStrong(void*) const { - android_atomic_inc(&mCount); - } - inline void decStrong(void*) const { - int32_t c = android_atomic_dec(&mCount); - //LOGE_IF(c<1, "Buffer::decStrong() called too many times"); - if (c == 1) { - delete this; - } - } inline status_t getStatus() const { return mHeap!=0 ? NO_ERROR : NO_INIT; } @@ -91,15 +97,87 @@ private: return mNativeBuffer; } protected: + friend class LightRefBase<Buffer>; Buffer& operator = (const Buffer& rhs); Buffer(const Buffer& rhs); ~Buffer(); - mutable volatile int32_t mCount; private: sp<IMemoryHeap> mHeap; NativeBuffer mNativeBuffer; }; + class BufferSource : public Source { + public: + BufferSource(LayerBuffer& layer, + int w, int h, int hstride, int vstride, + PixelFormat format, const sp<IMemoryHeap>& heap); + virtual ~BufferSource(); + + status_t getStatus() const { return mStatus; } + sp<Buffer> getBuffer() const; + void setBuffer(const sp<Buffer>& buffer); + + virtual void onDraw(const Region& clip) const; + virtual void postBuffer(ssize_t offset); + virtual void unregisterBuffers(); + private: + mutable Mutex mLock; + sp<IMemoryHeap> mHeap; + sp<Buffer> mBuffer; + status_t mStatus; + int mWidth; + int mHeight; + int mHStride; + int mVStride; + int mFormat; + mutable sp<MemoryDealer> mTemporaryDealer; + mutable LayerBitmap mTempBitmap; + mutable GLuint mTextureName; + }; + + class OverlaySource : public Source { + public: + OverlaySource(LayerBuffer& layer, + sp<OverlayRef>* overlayRef, + uint32_t w, uint32_t h, int32_t format); + virtual ~OverlaySource(); + virtual void onTransaction(uint32_t flags); + virtual void onVisibilityResolved(const Transform& planeTransform); + private: + void serverDestroy(); + class OverlayChanel : public BnOverlay { + mutable Mutex mLock; + sp<OverlaySource> mSource; + virtual void destroy() { + sp<OverlaySource> source; + { // scope for the lock; + Mutex::Autolock _l(mLock); + source = mSource; + mSource.clear(); + } + if (source != 0) { + source->serverDestroy(); + } + } + public: + OverlayChanel(const sp<OverlaySource>& source) + : mSource(source) { + } + }; + friend class OverlayChanel; + bool mVisibilityChanged; + + overlay_t* mOverlay; + overlay_handle_t const *mOverlayHandle; + uint32_t mWidth; + uint32_t mHeight; + int32_t mFormat; + int32_t mWidthStride; + int32_t mHeightStride; + mutable Mutex mLock; + }; + + class SurfaceBuffer : public LayerBaseClient::Surface { public: @@ -109,7 +187,7 @@ private: PixelFormat format, const sp<IMemoryHeap>& heap); virtual void postBuffer(ssize_t offset); virtual void unregisterBuffers(); - virtual sp<Overlay> createOverlay( + virtual sp<OverlayRef> createOverlay( uint32_t w, uint32_t h, int32_t format); void disown(); private: @@ -122,24 +200,14 @@ private: }; friend class SurfaceFlinger; - sp<Buffer> getBuffer() const; - void setBuffer(const sp<Buffer>& buffer); sp<SurfaceBuffer> getClientSurface() const; mutable Mutex mLock; - sp<IMemoryHeap> mHeap; - sp<Buffer> mBuffer; - int mWidth; - int mHeight; - int mHStride; - int mVStride; - int mFormat; - mutable GLuint mTextureName; + sp<Source> mSource; + bool mInvalidate; bool mNeedsBlending; mutable wp<SurfaceBuffer> mClientSurface; - mutable sp<MemoryDealer> mTemporaryDealer; - mutable LayerBitmap mTempBitmap; }; // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/LayerScreenshot.cpp b/libs/surfaceflinger/LayerScreenshot.cpp index 9b82bad..3e7132b 100644 --- a/libs/surfaceflinger/LayerScreenshot.cpp +++ b/libs/surfaceflinger/LayerScreenshot.cpp @@ -23,7 +23,7 @@ #include <utils/Errors.h> #include <utils/Log.h> -#include <graphics/SkBitmap.h> +#include <core/SkBitmap.h> #include <ui/EGLDisplaySurface.h> diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp index e8de21a..4c719e8 100644 --- a/libs/surfaceflinger/SurfaceFlinger.cpp +++ b/libs/surfaceflinger/SurfaceFlinger.cpp @@ -231,7 +231,7 @@ copybit_device_t* SurfaceFlinger::getBlitEngine() const return graphicPlane(0).displayHardware().getBlitEngine(); } -overlay_device_t* SurfaceFlinger::getOverlayEngine() const +overlay_control_device_t* SurfaceFlinger::getOverlayEngine() const { return graphicPlane(0).displayHardware().getOverlayEngine(); } @@ -773,12 +773,12 @@ void SurfaceFlinger::computeVisibleRegions( coveredRegion.andSelf(aboveCoveredLayers); // compute this layer's dirty region - if (layer->invalidate) { + if (layer->contentDirty) { // we need to invalidate the whole region dirty = visibleRegion; // as well, as the old visible region dirty.orSelf(layer->visibleRegionScreen); - layer->invalidate = false; + layer->contentDirty = false; } else { // compute the exposed region // dirty = what's visible now - what's wasn't covered before @@ -1456,7 +1456,7 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) "alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n", layer->getTypeID(), layer, s.z, layer->tx(), layer->ty(), s.w, s.h, - layer->needsBlending(), layer->invalidate, + layer->needsBlending(), layer->contentDirty, s.alpha, s.flags, s.transform[0], s.transform[1], s.transform[2], s.transform[3]); @@ -1474,22 +1474,6 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) } result.append(buffer); buffer[0] = 0; - /*** LayerBuffer ***/ - LayerBuffer* const lbuf = - LayerBase::dynamicCast<LayerBuffer*>((LayerBase*)layer); - if (lbuf) { - sp<LayerBuffer::Buffer> lbb(lbuf->getBuffer()); - if (lbb != 0) { - const LayerBuffer::NativeBuffer& nbuf(lbb->getBuffer()); - snprintf(buffer, SIZE, - " " - "mBuffer={w=%u, h=%u, f=%d, offset=%u, base=%p, fd=%d }\n", - nbuf.img.w, nbuf.img.h, nbuf.img.format, nbuf.img.offset, - nbuf.img.base, nbuf.img.fd); - } - } - result.append(buffer); - buffer[0] = 0; /*** Layer ***/ Layer* const l = LayerBase::dynamicCast<Layer*>((LayerBase*)layer); if (l) { diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/libs/surfaceflinger/SurfaceFlinger.h index 92021d0..a242f1a 100644 --- a/libs/surfaceflinger/SurfaceFlinger.h +++ b/libs/surfaceflinger/SurfaceFlinger.h @@ -180,7 +180,7 @@ public: } copybit_device_t* getBlitEngine() const; - overlay_device_t* getOverlayEngine() const; + overlay_control_device_t* getOverlayEngine() const; private: friend class BClient; @@ -382,24 +382,16 @@ private: // --------------------------------------------------------------------------- -class FreezeLock { +class FreezeLock : public LightRefBase<FreezeLock> { SurfaceFlinger* mFlinger; - mutable volatile int32_t mCount; public: FreezeLock(SurfaceFlinger* flinger) - : mFlinger(flinger), mCount(0) { + : mFlinger(flinger) { mFlinger->incFreezeCount(); } ~FreezeLock() { mFlinger->decFreezeCount(); } - inline void incStrong(void*) const { - android_atomic_inc(&mCount); - } - inline void decStrong(void*) const { - if (android_atomic_dec(&mCount) == 1) - delete this; - } }; // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/Transform.h b/libs/surfaceflinger/Transform.h index 2f617c4..0b4835e 100644 --- a/libs/surfaceflinger/Transform.h +++ b/libs/surfaceflinger/Transform.h @@ -25,7 +25,7 @@ #include <GLES/gl.h> -#include <corecg/SkMatrix.h> +#include <core/SkMatrix.h> namespace android { diff --git a/libs/ui/Camera.cpp b/libs/ui/Camera.cpp index 9527009..4a325ac 100644 --- a/libs/ui/Camera.cpp +++ b/libs/ui/Camera.cpp @@ -136,6 +136,18 @@ sp<ICamera> Camera::remote() return mCamera; } +status_t Camera::lock() +{ + if (mCamera != 0) return mCamera->lock(); + return NO_INIT; +} + +status_t Camera::unlock() +{ + if (mCamera != 0) return mCamera->unlock(); + return NO_INIT; +} + // pass the buffered ISurface to the camera service status_t Camera::setPreviewDisplay(const sp<Surface>& surface) { @@ -172,6 +184,13 @@ void Camera::stopPreview() mCamera->stopPreview(); } +// get preview state +bool Camera::previewEnabled() +{ + LOGV("previewEnabled"); + return mCamera->previewEnabled(); +} + status_t Camera::autoFocus() { LOGV("autoFocus"); diff --git a/libs/ui/ICamera.cpp b/libs/ui/ICamera.cpp index 6a2dc6b..7b0922e 100644 --- a/libs/ui/ICamera.cpp +++ b/libs/ui/ICamera.cpp @@ -35,7 +35,10 @@ enum { TAKE_PICTURE, SET_PARAMETERS, GET_PARAMETERS, - CONNECT + CONNECT, + LOCK, + UNLOCK, + PREVIEW_ENABLED }; class BpCamera: public BpInterface<ICamera> @@ -96,6 +99,16 @@ public: remote()->transact(STOP_PREVIEW, data, &reply); } + // check preview state + bool previewEnabled() + { + LOGV("previewEnabled"); + Parcel data, reply; + data.writeInterfaceToken(ICamera::getInterfaceDescriptor()); + remote()->transact(PREVIEW_ENABLED, data, &reply); + return reply.readInt32(); + } + // auto focus status_t autoFocus() { @@ -146,6 +159,20 @@ public: remote()->transact(CONNECT, data, &reply); return reply.readInt32(); } + virtual status_t lock() + { + Parcel data, reply; + data.writeInterfaceToken(ICamera::getInterfaceDescriptor()); + remote()->transact(LOCK, data, &reply); + return reply.readInt32(); + } + virtual status_t unlock() + { + Parcel data, reply; + data.writeInterfaceToken(ICamera::getInterfaceDescriptor()); + remote()->transact(UNLOCK, data, &reply); + return reply.readInt32(); + } }; IMPLEMENT_META_INTERFACE(Camera, "android.hardware.ICamera"); @@ -194,6 +221,12 @@ status_t BnCamera::onTransact( stopPreview(); return NO_ERROR; } break; + case PREVIEW_ENABLED: { + LOGV("PREVIEW_ENABLED"); + CHECK_INTERFACE(ICamera, data, reply); + reply->writeInt32(previewEnabled()); + return NO_ERROR; + } break; case AUTO_FOCUS: { LOGV("AUTO_FOCUS"); CHECK_INTERFACE(ICamera, data, reply); @@ -225,6 +258,16 @@ status_t BnCamera::onTransact( reply->writeInt32(connect(cameraClient)); return NO_ERROR; } break; + case LOCK: { + CHECK_INTERFACE(ICamera, data, reply); + reply->writeInt32(lock()); + return NO_ERROR; + } break; + case UNLOCK: { + CHECK_INTERFACE(ICamera, data, reply); + reply->writeInt32(unlock()); + return NO_ERROR; + } break; default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/ui/IOverlay.cpp b/libs/ui/IOverlay.cpp index 59d1ea0..fed47c2 100644 --- a/libs/ui/IOverlay.cpp +++ b/libs/ui/IOverlay.cpp @@ -27,7 +27,6 @@ namespace android { enum { DESTROY = IBinder::FIRST_CALL_TRANSACTION, // one-way transaction - SWAP_BUFFERS, }; class BpOverlay : public BpInterface<IOverlay> @@ -44,14 +43,6 @@ public: data.writeInterfaceToken(IOverlay::getInterfaceDescriptor()); remote()->transact(DESTROY, data, &reply, IBinder::FLAG_ONEWAY); } - - virtual ssize_t swapBuffers() - { - Parcel data, reply; - data.writeInterfaceToken(IOverlay::getInterfaceDescriptor()); - remote()->transact(SWAP_BUFFERS, data, &reply); - return reply.readInt32(); - } }; IMPLEMENT_META_INTERFACE(Overlay, "android.ui.IOverlay"); @@ -73,12 +64,6 @@ status_t BnOverlay::onTransact( destroy(); return NO_ERROR; } break; - case SWAP_BUFFERS: { - CHECK_INTERFACE(IOverlay, data, reply); - ssize_t offset = swapBuffers(); - reply->writeInt32(offset); - return NO_ERROR; - } break; default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/ui/ISurface.cpp b/libs/ui/ISurface.cpp index c1c9596..54f78fe 100644 --- a/libs/ui/ISurface.cpp +++ b/libs/ui/ISurface.cpp @@ -73,7 +73,7 @@ public: remote()->transact(UNREGISTER_BUFFERS, data, &reply); } - virtual sp<Overlay> createOverlay( + virtual sp<OverlayRef> createOverlay( uint32_t w, uint32_t h, int32_t format) { Parcel data, reply; @@ -82,7 +82,7 @@ public: data.writeInt32(h); data.writeInt32(format); remote()->transact(CREATE_OVERLAY, data, &reply); - return Overlay::readFromParcel(reply); + return OverlayRef::readFromParcel(reply); } }; @@ -128,8 +128,8 @@ status_t BnSurface::onTransact( int w = data.readInt32(); int h = data.readInt32(); int f = data.readInt32(); - sp<Overlay> o = createOverlay(w, h, w); - return Overlay::writeToParcel(reply, o); + sp<OverlayRef> o = createOverlay(w, h, w); + return OverlayRef::writeToParcel(reply, o); } break; default: return BBinder::onTransact(code, data, reply, flags); diff --git a/libs/ui/Overlay.cpp b/libs/ui/Overlay.cpp index 2267c3e..a79950c 100644 --- a/libs/ui/Overlay.cpp +++ b/libs/ui/Overlay.cpp @@ -16,86 +16,114 @@ #include <utils/IMemory.h> #include <utils/Parcel.h> +#include <utils/Errors.h> +#include <utils/MemoryHeapBase.h> #include <ui/IOverlay.h> #include <ui/Overlay.h> +#include <hardware/overlay.h> + namespace android { -Overlay::Overlay(overlay_handle_t* handle, - const sp<IOverlay>& o, const sp<IMemoryHeap>& heap, - uint32_t w, uint32_t h, int32_t f, uint32_t ws, uint32_t hs) - : mOverlay(o), mHeap(heap), mCurrentBufferOffset(0), mOverlayHandle(handle), - mWidth(w), mHeight(h), mFormat(f), mWidthStride(ws), mHeightStride(hs) +Overlay::Overlay(const sp<OverlayRef>& overlayRef) + : mOverlayRef(overlayRef), mOverlayData(0), mStatus(NO_INIT) { + mOverlayData = NULL; + hw_module_t const* module; + if (hw_get_module(OVERLAY_HARDWARE_MODULE_ID, &module) == 0) { + if (overlay_data_open(module, &mOverlayData) == NO_ERROR) { + mStatus = mOverlayData->initialize(mOverlayData, + overlayRef->mOverlayHandle); + } + } } -Overlay::Overlay(overlay_t* overlay, - const sp<IOverlay>& o, const sp<IMemoryHeap>& heap) - : mOverlay(o), mHeap(heap) -{ - mCurrentBufferOffset = 0; - mOverlayHandle = overlay->getHandleRef(overlay); - mWidth = overlay->w; - mHeight = overlay->h; - mFormat = overlay->format; - mWidthStride = overlay->w_stride; - mHeightStride = overlay->h_stride; +Overlay::~Overlay() { + if (mOverlayData) { + overlay_data_close(mOverlayData); + } } - -Overlay::~Overlay() { +overlay_buffer_t Overlay::dequeueBuffer() +{ + return mOverlayData->dequeueBuffer(mOverlayData); } -void Overlay::destroy() { - mOverlay->destroy(); +int Overlay::queueBuffer(overlay_buffer_t buffer) +{ + return mOverlayData->queueBuffer(mOverlayData, buffer); } -status_t Overlay::swapBuffers() { - ssize_t result = mOverlay->swapBuffers(); - if (result < 0) - return status_t(result); - mCurrentBufferOffset = result; - return NO_ERROR; +void* Overlay::getBufferAddress(overlay_buffer_t buffer) +{ + return mOverlayData->getBufferAddress(mOverlayData, buffer); } -overlay_handle_t const* Overlay::getHandleRef() const { - return mOverlayHandle; +void Overlay::destroy() { + mOverlayRef->mOverlayChanel->destroy(); } -size_t Overlay::getBufferOffset() const { - return mCurrentBufferOffset; +status_t Overlay::getStatus() const { + return mStatus; } -sp<IMemoryHeap> Overlay::getHeap() const { - return mHeap; +overlay_handle_t const* Overlay::getHandleRef() const { + return mOverlayRef->mOverlayHandle; } uint32_t Overlay::getWidth() const { - return mWidth; + return mOverlayRef->mWidth; } uint32_t Overlay::getHeight() const { - return mHeight; + return mOverlayRef->mHeight; } int32_t Overlay::getFormat() const { - return mFormat; + return mOverlayRef->mFormat; } int32_t Overlay::getWidthStride() const { - return mWidthStride; + return mOverlayRef->mWidthStride; } int32_t Overlay::getHeightStride() const { - return mHeightStride; + return mOverlayRef->mHeightStride; +} +// ---------------------------------------------------------------------------- + +OverlayRef::OverlayRef() + : mOverlayHandle(0), + mWidth(0), mHeight(0), mFormat(0), mWidthStride(0), mHeightStride(0), + mOwnHandle(true) +{ +} + +OverlayRef::OverlayRef(overlay_handle_t const* handle, const sp<IOverlay>& chanel, + uint32_t w, uint32_t h, int32_t f, uint32_t ws, uint32_t hs) + : mOverlayHandle(handle), mOverlayChanel(chanel), + mWidth(w), mHeight(h), mFormat(f), mWidthStride(ws), mHeightStride(hs), + mOwnHandle(false) +{ +} + +OverlayRef::~OverlayRef() +{ + if (mOwnHandle) { + /* FIXME: handles should be promoted to "real" API and be handled by + * the framework */ + for (int i=0 ; i<mOverlayHandle->numFds ; i++) { + close(mOverlayHandle->fds[i]); + } + free((void*)mOverlayHandle); + } } -sp<Overlay> Overlay::readFromParcel(const Parcel& data) { - sp<Overlay> result; +sp<OverlayRef> OverlayRef::readFromParcel(const Parcel& data) { + sp<OverlayRef> result; sp<IOverlay> overlay = IOverlay::asInterface(data.readStrongBinder()); if (overlay != NULL) { - sp<IMemoryHeap> heap = IMemoryHeap::asInterface(data.readStrongBinder()); uint32_t w = data.readInt32(); uint32_t h = data.readInt32(); uint32_t f = data.readInt32(); @@ -111,15 +139,21 @@ sp<Overlay> Overlay::readFromParcel(const Parcel& data) { handle->fds[i] = data.readFileDescriptor(); for (int i=0 ; i<numint ; i++) handle->data[i] = data.readInt32(); - result = new Overlay(handle, overlay, heap, w, h, f, ws, hs); + result = new OverlayRef(); + result->mOverlayHandle = handle; + result->mOverlayChanel = overlay; + result->mWidth = w; + result->mHeight = h; + result->mFormat = f; + result->mWidthStride = ws; + result->mHeightStride = hs; } return result; } -status_t Overlay::writeToParcel(Parcel* reply, const sp<Overlay>& o) { +status_t OverlayRef::writeToParcel(Parcel* reply, const sp<OverlayRef>& o) { if (o != NULL) { - reply->writeStrongBinder(o->mOverlay->asBinder()); - reply->writeStrongBinder(o->mHeap->asBinder()); + reply->writeStrongBinder(o->mOverlayChanel->asBinder()); reply->writeInt32(o->mWidth); reply->writeInt32(o->mHeight); reply->writeInt32(o->mFormat); diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp index 3e07f2b..26e694a 100644 --- a/libs/ui/Region.cpp +++ b/libs/ui/Region.cpp @@ -21,8 +21,6 @@ #include <utils/Debug.h> #include <utils/String8.h> #include <ui/Region.h> -#include <corecg/SkRegion.h> -#include <corecg/SkRect.h> namespace android { diff --git a/libs/utils/MemoryHeapBase.cpp b/libs/utils/MemoryHeapBase.cpp index 59963c9..8251728 100644 --- a/libs/utils/MemoryHeapBase.cpp +++ b/libs/utils/MemoryHeapBase.cpp @@ -119,19 +119,24 @@ status_t MemoryHeapBase::mapfd(int fd, size_t size) // if it didn't work, let mmap() fail. } - void* base = (uint8_t*)mmap(0, size, - PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); - if (base == MAP_FAILED) { - LOGE("mmap(fd=%d, size=%u) failed (%s)", - fd, uint32_t(size), strerror(errno)); - close(fd); - return -errno; + if ((mFlags & DONT_MAP_LOCALLY) == 0) { + void* base = (uint8_t*)mmap(0, size, + PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + if (base == MAP_FAILED) { + LOGE("mmap(fd=%d, size=%u) failed (%s)", + fd, uint32_t(size), strerror(errno)); + close(fd); + return -errno; + } + //LOGD("mmap(fd=%d, base=%p, size=%lu)", fd, base, size); + mBase = base; + mNeedUnmap = true; + } else { + mBase = 0; // not MAP_FAILED + mNeedUnmap = false; } - //LOGD("mmap(fd=%d, base=%p, size=%lu)", fd, base, size); mFD = fd; - mBase = base; mSize = size; - mNeedUnmap = true; return NO_ERROR; } |