diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-02-10 15:44:00 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-02-10 15:44:00 -0800 |
commit | a6938bab1f6fa76ae98ebbe44f4e534e05fa0993 (patch) | |
tree | bc5a1f806bd06db8abb197e80be9ead3644c0bcc /libs | |
parent | e41dd756db5184519f4dacbf4d95b333822605c7 (diff) | |
download | frameworks_native-a6938bab1f6fa76ae98ebbe44f4e534e05fa0993.zip frameworks_native-a6938bab1f6fa76ae98ebbe44f4e534e05fa0993.tar.gz frameworks_native-a6938bab1f6fa76ae98ebbe44f4e534e05fa0993.tar.bz2 |
auto import from //branches/cupcake/...@130745
Diffstat (limited to 'libs')
38 files changed, 1502 insertions, 392 deletions
diff --git a/libs/audioflinger/A2dpAudioInterface.cpp b/libs/audioflinger/A2dpAudioInterface.cpp index c8c8431..3c18036 100644 --- a/libs/audioflinger/A2dpAudioInterface.cpp +++ b/libs/audioflinger/A2dpAudioInterface.cpp @@ -99,6 +99,10 @@ status_t A2dpAudioInterface::setParameter(const char *key, const char *value) if (strcmp(key, "a2dp_sink_address") == 0) { return mOutput->setAddress(value); } + if (strcmp(key, "bluetooth_enabled") == 0 && + strcmp(value, "false") == 0) { + return mOutput->close(); + } return 0; } @@ -154,8 +158,7 @@ status_t A2dpAudioInterface::A2dpAudioStreamOut::set( A2dpAudioInterface::A2dpAudioStreamOut::~A2dpAudioStreamOut() { - if (mData) - a2dp_cleanup(mData); + close(); } ssize_t A2dpAudioInterface::A2dpAudioStreamOut::write(const void* buffer, size_t bytes) @@ -186,7 +189,8 @@ ssize_t A2dpAudioInterface::A2dpAudioStreamOut::write(const void* buffer, size_t return bytes; -Error: +Error: + close(); // Simulate audio output timing in case of error usleep(bytes * 1000000 / frameSize() / sampleRate()); @@ -213,17 +217,22 @@ status_t A2dpAudioInterface::A2dpAudioStreamOut::setAddress(const char* address) if (strcmp(address, mA2dpAddress)) { strcpy(mA2dpAddress, address); - - if (mInitialized) { - a2dp_cleanup(mData); - mData = NULL; - mInitialized = false; - } + close(); } return NO_ERROR; } +status_t A2dpAudioInterface::A2dpAudioStreamOut::close() +{ + if (mData) { + a2dp_cleanup(mData); + mData = NULL; + mInitialized = false; + } + return NO_ERROR; +} + status_t A2dpAudioInterface::A2dpAudioStreamOut::dump(int fd, const Vector<String16>& args) { return NO_ERROR; diff --git a/libs/audioflinger/A2dpAudioInterface.h b/libs/audioflinger/A2dpAudioInterface.h index 2197d0e..38ba684 100644 --- a/libs/audioflinger/A2dpAudioInterface.h +++ b/libs/audioflinger/A2dpAudioInterface.h @@ -77,10 +77,11 @@ private: virtual size_t bufferSize() const { return 512 * 20; } virtual int channelCount() const { return 2; } virtual int format() const { return AudioSystem::PCM_16_BIT; } - virtual uint32_t latency() const { return ((1000*channelCount()*bufferSize())/frameSize())/sampleRate() + 200; } + virtual uint32_t latency() const { return ((1000*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(); + status_t close(); virtual status_t dump(int fd, const Vector<String16>& args); private: diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp index c330bc8..017a298 100644 --- a/libs/audioflinger/AudioFlinger.cpp +++ b/libs/audioflinger/AudioFlinger.cpp @@ -183,6 +183,7 @@ AudioFlinger::~AudioFlinger() void AudioFlinger::setOutput(AudioStreamOut* output) { mRequestedOutput = output; + mWaitWorkCV.broadcast(); } void AudioFlinger::doSetOutput(AudioStreamOut* output) @@ -198,6 +199,7 @@ void AudioFlinger::doSetOutput(AudioStreamOut* output) mFrameCount = getOutputFrameCount(output); mAudioMixer = (output == mA2dpOutput ? mA2dpAudioMixer : mHardwareAudioMixer); mOutput = output; + notifyOutputChange_l(); } size_t AudioFlinger::getOutputFrameCount(AudioStreamOut* output) @@ -211,6 +213,8 @@ bool AudioFlinger::streamDisablesA2dp(int streamType) return (streamType == AudioTrack::SYSTEM || streamType == AudioTrack::RING || streamType == AudioTrack::ALARM || + streamType == AudioTrack::VOICE_CALL || + streamType == AudioTrack::BLUETOOTH_SCO || streamType == AudioTrack::NOTIFICATION); } @@ -344,7 +348,8 @@ bool AudioFlinger::threadLoop() int16_t* curBuf = mMixBuffer; Vector< sp<Track> > tracksToRemove; size_t enabledTracks = 0; - nsecs_t standbyTime = systemTime(); + nsecs_t standbyTime = systemTime(); + nsecs_t outputSwitchStandbyTime = 0; do { enabledTracks = 0; @@ -362,6 +367,11 @@ bool AudioFlinger::threadLoop() mOutput->standby(); mStandby = true; } + if (outputSwitchStandbyTime) { + AudioStreamOut *output = (mOutput == mHardwareOutput) ? mA2dpOutput : mHardwareOutput; + output->standby(); + outputSwitchStandbyTime = 0; + } mHardwareStatus = AUDIO_HW_IDLE; // we're about to wait, flush the binder command buffer IPCThreadState::self()->flushCommands(); @@ -375,11 +385,18 @@ bool AudioFlinger::threadLoop() if (mRequestedOutput != mOutput) { // put current output into standby mode - if (mOutput) mOutput->standby(); + if (mOutput) { + outputSwitchStandbyTime = systemTime() + milliseconds(mOutput->latency()); + } // change output doSetOutput(mRequestedOutput); } + if (outputSwitchStandbyTime && systemTime() > outputSwitchStandbyTime) { + AudioStreamOut *output = (mOutput == mHardwareOutput) ? mA2dpOutput : mHardwareOutput; + output->standby(); + outputSwitchStandbyTime = 0; + } // find out which tracks need to be processed size_t count = activeTracks.size(); @@ -481,7 +498,7 @@ bool AudioFlinger::threadLoop() removeActiveTrack(track); if (track->isTerminated()) { mTracks.remove(track); - mAudioMixer->deleteTrackName(track->mName); + deleteTrackName(track->mName); } } } @@ -512,7 +529,7 @@ bool AudioFlinger::threadLoop() // active tracks were late. Sleep a little bit to give // them another chance. If we're too late, the audio // hardware will zero-fill for us. - LOGV("no buffers - usleep(%lu)", sleepTime); +// LOGV("no buffers - usleep(%lu)", sleepTime); usleep(sleepTime); if (sleepTime < kMaxBufferRecoveryInUsecs) { sleepTime += kBufferRecoveryInUsecs; @@ -802,12 +819,14 @@ status_t AudioFlinger::setStreamVolume(int stream, float value) mStreamTypes[stream].volume = value; status_t ret = NO_ERROR; - if (stream == AudioTrack::VOICE_CALL) { + if (stream == AudioTrack::VOICE_CALL || + stream == AudioTrack::BLUETOOTH_SCO) { AutoMutex lock(mHardwareLock); mHardwareStatus = AUDIO_SET_VOICE_VOLUME; ret = mAudioHardware->setVoiceVolume(value); mHardwareStatus = AUDIO_HW_IDLE; } + return ret; } @@ -821,7 +840,20 @@ status_t AudioFlinger::setStreamMute(int stream, bool muted) if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) { return BAD_VALUE; } +#ifdef WITH_A2DP + if (stream == AudioTrack::MUSIC) + { + AutoMutex lock(&mLock); + if (mA2dpDisableCount > 0) + mMusicMuteSaved = muted; + else + mStreamTypes[stream].mute = muted; + } else { + mStreamTypes[stream].mute = muted; + } +#else mStreamTypes[stream].mute = muted; +#endif return NO_ERROR; } @@ -838,6 +870,12 @@ bool AudioFlinger::streamMute(int stream) const if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) { return true; } +#ifdef WITH_A2DP + if (stream == AudioTrack::MUSIC && mA2dpDisableCount > 0) + { + return mMusicMuteSaved; + } +#endif return mStreamTypes[stream].mute; } @@ -869,6 +907,59 @@ status_t AudioFlinger::setParameter(const char* key, const char* value) return result; } + +void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client) +{ + Mutex::Autolock _l(mLock); + + sp<IBinder> binder = client->asBinder(); + if (mNotificationClients.indexOf(binder) < 0) { + LOGV("Adding notification client %p", binder.get()); + binder->linkToDeath(this); + mNotificationClients.add(binder); + } +} + + +size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, int format, int channelCount) +{ + return mAudioHardware->getInputBufferSize(sampleRate, format, channelCount); +} + +void AudioFlinger::wakeUp() +{ + mWaitWorkCV.broadcast(); +} + +void AudioFlinger::binderDied(const wp<IBinder>& who) { + Mutex::Autolock _l(mLock); + + IBinder *binder = who.unsafe_get(); + + if (binder != NULL) { + int index = mNotificationClients.indexOf(binder); + if (index >= 0) { + LOGV("Removing notification client %p", binder); + mNotificationClients.removeAt(index); + } + } +} + +// must be called with mLock held +void AudioFlinger::notifyOutputChange_l() +{ + size_t size = mNotificationClients.size(); + uint32_t latency = mOutput->latency(); + for (size_t i = 0; i < size; i++) { + sp<IBinder> binder = mNotificationClients.itemAt(i).promote(); + if (binder != NULL) { + LOGV("Notifying output change to client %p", binder.get()); + sp<IAudioFlingerClient> client = interface_cast<IAudioFlingerClient> (binder); + client->audioOutputChanged(mFrameCount, mSampleRate, latency); + } + } +} + void AudioFlinger::removeClient(pid_t pid) { Mutex::Autolock _l(mLock); @@ -920,7 +1011,7 @@ void AudioFlinger::remove_track_l(wp<Track> track, int name) if (t!=NULL) { t->reset(); } - audioMixer()->deleteTrackName(name); + deleteTrackName(name); removeActiveTrack(track); mWaitWorkCV.broadcast(); } @@ -938,7 +1029,7 @@ void AudioFlinger::destroyTrack(const sp<Track>& track) if (mActiveTracks.indexOf(track) < 0) { LOGV("remove track (%d) and delete from mixer", track->name()); mTracks.remove(track); - audioMixer()->deleteTrackName(keep->name()); + deleteTrackName(keep->name()); } } @@ -953,9 +1044,11 @@ void AudioFlinger::addActiveTrack(const wp<Track>& t) if (mA2dpDisableCount++ == 0 && isA2dpEnabled()) { setA2dpEnabled(false); mA2dpSuppressed = true; - LOGD("mA2dpSuppressed = true\n"); + mMusicMuteSaved = mStreamTypes[AudioTrack::MUSIC].mute; + mStreamTypes[AudioTrack::MUSIC].mute = true; + LOGV("mA2dpSuppressed = true, track %d\n", track->name()); } - LOGD("mA2dpDisableCount incremented to %d\n", mA2dpDisableCount); + LOGV("mA2dpDisableCount incremented to %d, track %d\n", mA2dpDisableCount, track->name()); } #endif } @@ -969,17 +1062,45 @@ void AudioFlinger::removeActiveTrack(const wp<Track>& t) if (streamDisablesA2dp(track->type())) { if (mA2dpDisableCount > 0) { mA2dpDisableCount--; + LOGV("mA2dpDisableCount decremented to %d, track %d\n", mA2dpDisableCount, track->name()); if (mA2dpDisableCount == 0 && mA2dpSuppressed) { setA2dpEnabled(true); mA2dpSuppressed = false; - } - LOGD("mA2dpDisableCount decremented to %d\n", mA2dpDisableCount); + mStreamTypes[AudioTrack::MUSIC].mute = mMusicMuteSaved; + LOGV("mA2dpSuppressed = false, track %d\n", track->name()); + } } else LOGE("mA2dpDisableCount is already zero"); } #endif } +int AudioFlinger::getTrackName() +{ + // Both mixers must have the same set of track used to avoid mismatches when + // switching from A2DP output to hardware output + int a2DpName; + int hwName; +#ifdef WITH_A2DP + a2DpName = mA2dpAudioMixer->getTrackName(); +#endif + hwName = mHardwareAudioMixer->getTrackName(); + + LOGW_IF((a2DpName != hwName), "getTrackName track name mismatch! A2DP %d, HW %d", a2DpName, hwName); + + return hwName; +} + +void AudioFlinger::deleteTrackName(int name) +{ + // Both mixers must have the same set of track used to avoid mismatches when + // switching from A2DP output to hardware output + mHardwareAudioMixer->deleteTrackName(name); +#ifdef WITH_A2DP + mA2dpAudioMixer->deleteTrackName(name); +#endif +} + // ---------------------------------------------------------------------------- AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid) @@ -1022,7 +1143,8 @@ AudioFlinger::TrackBase::TrackBase( mFormat(format), mFlags(0) { - mName = audioFlinger->audioMixer()->getTrackName(); + mName = audioFlinger->getTrackName(); + LOGV("TrackBase contructor name %d, calling thread %d", mName, IPCThreadState::self()->getCallingPid()); if (mName < 0) { LOGE("no more track names availlable"); return; @@ -1237,14 +1359,14 @@ bool AudioFlinger::Track::isReady() const { status_t AudioFlinger::Track::start() { - LOGV("start(%d)", mName); + LOGV("start(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid()); mAudioFlinger->addTrack(this); return NO_ERROR; } void AudioFlinger::Track::stop() { - LOGV("stop(%d)", mName); + LOGV("stop(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid()); Mutex::Autolock _l(mAudioFlinger->mLock); if (mState > STOPPED) { mState = STOPPED; @@ -1258,7 +1380,7 @@ void AudioFlinger::Track::stop() void AudioFlinger::Track::pause() { - LOGV("pause(%d)", mName); + LOGV("pause(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid()); Mutex::Autolock _l(mAudioFlinger->mLock); if (mState == ACTIVE || mState == RESUMING) { mState = PAUSING; @@ -1485,7 +1607,7 @@ AudioFlinger::RecordTrack::RecordTrack( AudioFlinger::RecordTrack::~RecordTrack() { - mAudioFlinger->audioMixer()->deleteTrackName(mName); + mAudioFlinger->deleteTrackName(mName); } status_t AudioFlinger::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer) diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h index 9ab362a..38fa001 100644 --- a/libs/audioflinger/AudioFlinger.h +++ b/libs/audioflinger/AudioFlinger.h @@ -22,6 +22,7 @@ #include <sys/types.h> #include <media/IAudioFlinger.h> +#include <media/IAudioFlingerClient.h> #include <media/IAudioTrack.h> #include <media/IAudioRecord.h> #include <media/AudioTrack.h> @@ -54,7 +55,7 @@ class AudioBuffer; static const nsecs_t kStandbyTimeInNsecs = seconds(3); -class AudioFlinger : public BnAudioFlinger, protected Thread +class AudioFlinger : public BnAudioFlinger, protected Thread, public IBinder::DeathRecipient { public: static void instantiate(); @@ -109,6 +110,15 @@ public: virtual status_t setParameter(const char* key, const char* value); + virtual void registerClient(const sp<IAudioFlingerClient>& client); + + virtual size_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount); + + virtual void wakeUp(); + + // IBinder::DeathRecipient + virtual void binderDied(const wp<IBinder>& who); + enum hardware_call_state { AUDIO_HW_IDLE = 0, AUDIO_HW_INIT, @@ -314,7 +324,7 @@ private: virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer); bool isMuted() const { - return mMute; + return (mMute || mAudioFlinger->mStreamTypes[mStreamType].mute); } bool isPausing() const { @@ -382,6 +392,8 @@ private: void destroyTrack(const sp<Track>& track); void addActiveTrack(const wp<Track>& track); void removeActiveTrack(const wp<Track>& track); + int getTrackName(); + void deleteTrackName(int name); AudioMixer* audioMixer() { return mAudioMixer; @@ -460,6 +472,8 @@ private: status_t startRecord(RecordTrack* recordTrack); void stopRecord(RecordTrack* recordTrack); + void notifyOutputChange_l(); + mutable Mutex mHardwareLock; mutable Mutex mLock; mutable Condition mWaitWorkCV; @@ -494,6 +508,8 @@ private: bool mInWrite; int mA2dpDisableCount; bool mA2dpSuppressed; + bool mMusicMuteSaved; + SortedVector< wp<IBinder> > mNotificationClients; }; // ---------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/Android.mk b/libs/surfaceflinger/Android.mk index d14cebf..53ba3bc 100644 --- a/libs/surfaceflinger/Android.mk +++ b/libs/surfaceflinger/Android.mk @@ -15,7 +15,9 @@ LOCAL_SRC_FILES:= \ LayerBlur.cpp \ LayerBitmap.cpp \ LayerDim.cpp \ + LayerOrientationAnim.cpp \ LayerScreenshot.cpp \ + OrientationAnimation.cpp \ RFBServer.cpp \ SurfaceFlinger.cpp \ Tokenizer.cpp \ @@ -38,7 +40,8 @@ LOCAL_SHARED_LIBRARIES := \ libcorecg \ libsgl \ libpixelflinger \ - libGLES_CM + libEGL \ + libGLESv1_CM LOCAL_C_INCLUDES := \ $(call include-path-for, corecg graphics) diff --git a/libs/surfaceflinger/BootAnimation.cpp b/libs/surfaceflinger/BootAnimation.cpp index d18f59a..2b30336 100644 --- a/libs/surfaceflinger/BootAnimation.cpp +++ b/libs/surfaceflinger/BootAnimation.cpp @@ -39,7 +39,9 @@ #include <core/SkBitmap.h> #include <images/SkImageDecoder.h> -#include <GLES/egl.h> +#include <GLES/gl.h> +#include <GLES/glext.h> +#include <EGL/eglext.h> #include "BootAnimation.h" @@ -47,32 +49,28 @@ namespace android { // --------------------------------------------------------------------------- -BootAnimation::BootAnimation(const sp<ISurfaceComposer>& composer) -: Thread(false) -{ +BootAnimation::BootAnimation(const sp<ISurfaceComposer>& composer) : + Thread(false) { mSession = SurfaceComposerClient::clientForConnection( composer->createConnection()->asBinder()); } -BootAnimation::~BootAnimation() -{ +BootAnimation::~BootAnimation() { } -void BootAnimation::onFirstRef() -{ +void BootAnimation::onFirstRef() { run("BootAnimation", PRIORITY_DISPLAY); } -const sp<SurfaceComposerClient>& BootAnimation::session() const -{ +const sp<SurfaceComposerClient>& BootAnimation::session() const { return mSession; } -status_t BootAnimation::initTexture( - Texture* texture, AssetManager& assets, const char* name) -{ +status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets, + const char* name) { Asset* asset = assets.open(name, Asset::ACCESS_BUFFER); - if (!asset) return NO_INIT; + if (!asset) + return NO_INIT; SkBitmap bitmap; SkImageDecoder::DecodeMemory(asset->getBuffer(false), asset->getLength(), &bitmap, SkBitmap::kNo_Config, SkImageDecoder::kDecodePixels_Mode); @@ -84,32 +82,32 @@ status_t BootAnimation::initTexture( bitmap.lockPixels(); const int w = bitmap.width(); - const int h = bitmap.height(); + const int h = bitmap.height(); const void* p = bitmap.getPixels(); - + GLint crop[4] = { 0, h, w, -h }; texture->w = w; texture->h = h; glGenTextures(1, &texture->name); glBindTexture(GL_TEXTURE_2D, texture->name); - - switch(bitmap.getConfig()) { + + switch (bitmap.getConfig()) { case SkBitmap::kA8_Config: - glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, - GL_ALPHA, GL_UNSIGNED_BYTE, p); + glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_ALPHA, + GL_UNSIGNED_BYTE, p); break; case SkBitmap::kARGB_4444_Config: - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, - GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, p); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, + GL_UNSIGNED_SHORT_4_4_4_4, p); break; case SkBitmap::kARGB_8888_Config: - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, - GL_RGBA, GL_UNSIGNED_BYTE, p); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, + GL_UNSIGNED_BYTE, p); break; case SkBitmap::kRGB_565_Config: - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, - GL_RGB, GL_UNSIGNED_SHORT_5_6_5, p); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, + GL_UNSIGNED_SHORT_5_6_5, p); break; default: break; @@ -123,8 +121,7 @@ status_t BootAnimation::initTexture( return NO_ERROR; } -status_t BootAnimation::readyToRun() -{ +status_t BootAnimation::readyToRun() { mAssets.addDefaultAssets(); DisplayInfo dinfo; @@ -133,32 +130,27 @@ status_t BootAnimation::readyToRun() return -1; // create the native surface - sp<Surface> s = session()->createSurface(getpid(), 0, - dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565); + sp<Surface> s = session()->createSurface(getpid(), 0, dinfo.w, dinfo.h, + PIXEL_FORMAT_RGB_565); session()->openTransaction(); s->setLayer(0x40000000); session()->closeTransaction(); // initialize opengl and egl - const EGLint attribs[] = { - EGL_RED_SIZE, 5, - EGL_GREEN_SIZE, 6, - EGL_BLUE_SIZE, 5, - EGL_DEPTH_SIZE, 0, - EGL_NONE - }; + const EGLint attribs[] = { EGL_RED_SIZE, 5, EGL_GREEN_SIZE, 6, + EGL_BLUE_SIZE, 5, EGL_DEPTH_SIZE, 0, EGL_NONE }; EGLint w, h, dummy; EGLint numConfigs; EGLConfig config; EGLSurface surface; EGLContext context; EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); - eglInitialize(display, NULL, NULL); eglChooseConfig(display, attribs, &config, 1, &numConfigs); - surface = eglCreateWindowSurface( - display, config, new EGLNativeWindowSurface(s), NULL); - + mNativeWindowSurface = new EGLNativeWindowSurface(s); + surface = eglCreateWindowSurface(display, config, + mNativeWindowSurface.get(), NULL); + context = eglCreateContext(display, config, NULL, NULL); eglQuerySurface(display, surface, EGL_WIDTH, &w); eglQuerySurface(display, surface, EGL_HEIGHT, &h); @@ -167,7 +159,7 @@ status_t BootAnimation::readyToRun() mContext = context; mSurface = surface; mWidth = w; - mHeight= h; + mHeight = h; mFlingerSurface = s; // initialize GL @@ -180,25 +172,21 @@ status_t BootAnimation::readyToRun() return NO_ERROR; } -void BootAnimation::requestExit() -{ +void BootAnimation::requestExit() { mBarrier.open(); Thread::requestExit(); } -bool BootAnimation::threadLoop() -{ +bool BootAnimation::threadLoop() { bool r = android(); - eglMakeCurrent(mDisplay, 0, 0, 0); - eglDestroyContext(mDisplay, mContext); + eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + eglDestroyContext(mDisplay, mContext); eglDestroySurface(mDisplay, mSurface); - eglTerminate(mDisplay); + mNativeWindowSurface.clear(); return r; } - -bool BootAnimation::android() -{ +bool BootAnimation::android() { initTexture(&mAndroid[0], mAssets, "images/android_320x480.png"); initTexture(&mAndroid[1], mAssets, "images/boot_robot.png"); initTexture(&mAndroid[2], mAssets, "images/boot_robot_glow.png"); @@ -219,9 +207,9 @@ bool BootAnimation::android() glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); const int steps = 8; - for (int i=1 ; i<steps ; i++) { + for (int i = 1; i < steps; i++) { float fade = i / float(steps); - glColor4f(1, 1, 1, fade*fade); + glColor4f(1, 1, 1, fade * fade); glClear(GL_COLOR_BUFFER_BIT); glDrawTexiOES(0, 0, 0, mAndroid[0].w, mAndroid[0].h); eglSwapBuffers(mDisplay, mSurface); @@ -232,79 +220,73 @@ bool BootAnimation::android() glDisable(GL_BLEND); glDrawTexiOES(0, 0, 0, mAndroid[0].w, mAndroid[0].h); eglSwapBuffers(mDisplay, mSurface); - - + // update rect for the robot const int x = mWidth - mAndroid[1].w - 33; - const int y = (mHeight - mAndroid[1].h)/2 - 1; - const Rect updateRect(x, y, x+mAndroid[1].w, y+mAndroid[1].h); + const int y = (mHeight - mAndroid[1].h) / 2 - 1; + const Rect updateRect(x, y, x + mAndroid[1].w, y + mAndroid[1].h); // draw and update only what we need - eglSwapRectangleANDROID(mDisplay, mSurface, - updateRect.left, updateRect.top, - updateRect.width(), updateRect.height()); + mNativeWindowSurface->setSwapRectangle(updateRect.left, + updateRect.top, updateRect.width(), updateRect.height()); glEnable(GL_SCISSOR_TEST); - glScissor(updateRect.left, mHeight-updateRect.bottom, - updateRect.width(), updateRect.height()); + glScissor(updateRect.left, mHeight - updateRect.bottom, updateRect.width(), + updateRect.height()); const nsecs_t startTime = systemTime(); - do - { + do { // glow speed and shape nsecs_t time = systemTime() - startTime; - float t = ((4.0f/(360.0f*us2ns(16667))) * time); + float t = ((4.0f / (360.0f * us2ns(16667))) * time); t = t - floorf(t); - const float fade = 0.5f + 0.5f*sinf(t * 2*M_PI); + const float fade = 0.5f + 0.5f * sinf(t * 2 * M_PI); // fade the glow in and out glDisable(GL_BLEND); glBindTexture(GL_TEXTURE_2D, mAndroid[2].name); glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glColor4f(fade, fade, fade, fade); - glDrawTexiOES(updateRect.left, mHeight-updateRect.bottom, 0, + glDrawTexiOES(updateRect.left, mHeight - updateRect.bottom, 0, updateRect.width(), updateRect.height()); // draw the robot glEnable(GL_BLEND); glBindTexture(GL_TEXTURE_2D, mAndroid[1].name); glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - glDrawTexiOES(updateRect.left, mHeight-updateRect.bottom, 0, + glDrawTexiOES(updateRect.left, mHeight - updateRect.bottom, 0, updateRect.width(), updateRect.height()); // make sure sleep a lot to not take too much CPU away from // the boot process. With this "glow" animation there is no // visible difference. - usleep(16667*4); + usleep(16667 * 4); eglSwapBuffers(mDisplay, mSurface); } while (!exitPending()); - - + glDeleteTextures(1, &mAndroid[0].name); glDeleteTextures(1, &mAndroid[1].name); glDeleteTextures(1, &mAndroid[2].name); return false; } - -bool BootAnimation::cylon() -{ +bool BootAnimation::cylon() { // initialize the textures... - initTexture(&mLeftTrail, mAssets, "images/cylon_left.png"); + initTexture(&mLeftTrail, mAssets, "images/cylon_left.png"); initTexture(&mRightTrail, mAssets, "images/cylon_right.png"); initTexture(&mBrightSpot, mAssets, "images/cylon_dot.png"); int w = mWidth; int h = mHeight; - const Point c(w/2 , h/2); + const Point c(w / 2, h / 2); const GLint amplitude = 60; - const int scx = c.x - amplitude - mBrightSpot.w/2; - const int scy = c.y - mBrightSpot.h/2; - const int scw = amplitude*2 + mBrightSpot.w; + const int scx = c.x - amplitude - mBrightSpot.w / 2; + const int scy = c.y - mBrightSpot.h / 2; + const int scw = amplitude * 2 + mBrightSpot.w; const int sch = mBrightSpot.h; - const Rect updateRect(scx, h-scy-sch, scx+scw, h-scy); + const Rect updateRect(scx, h - scy - sch, scx + scw, h - scy); // erase screen glDisable(GL_SCISSOR_TEST); @@ -314,33 +296,29 @@ bool BootAnimation::cylon() glClear(GL_COLOR_BUFFER_BIT); - eglSwapRectangleANDROID(mDisplay, mSurface, - updateRect.left, updateRect.top, - updateRect.width(), updateRect.height()); + mNativeWindowSurface->setSwapRectangle(updateRect.left, + updateRect.top, updateRect.width(), updateRect.height()); glEnable(GL_SCISSOR_TEST); glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - // clear the screen to white Point p; float t = 0; float alpha = 1.0f; const nsecs_t startTime = systemTime(); nsecs_t fadeTime = 0; - - do - { + + do { // Set scissor in interesting area - glScissor(scx, scy, scw, sch); + glScissor(scx, scy, scw, sch); // erase screen glClear(GL_COLOR_BUFFER_BIT); - // compute wave - const float a = (t * 2*M_PI) - M_PI/2; + const float a = (t * 2 * M_PI) - M_PI / 2; const float sn = sinf(a); const float cs = cosf(a); GLint x = GLint(amplitude * sn); @@ -350,50 +328,50 @@ bool BootAnimation::cylon() if (derivative > 0) { // vanishing trail... - p.x = (-amplitude + c.x) - mBrightSpot.w/2; - p.y = c.y-mLeftTrail.h/2; - float fade = 2.0f*(0.5f-t); + p.x = (-amplitude + c.x) - mBrightSpot.w / 2; + p.y = c.y - mLeftTrail.h / 2; + float fade = 2.0f * (0.5f - t); //fade *= fade; glColor4f(fade, fade, fade, fade); glBindTexture(GL_TEXTURE_2D, mLeftTrail.name); glDrawTexiOES(p.x, p.y, 0, mLeftTrail.w, mLeftTrail.h); // trail... - p.x = (x + c.x) - (mRightTrail.w + mBrightSpot.w/2) + 16; - p.y = c.y-mRightTrail.h/2; - fade = t<0.25f ? t*4.0f : 1.0f; + p.x = (x + c.x) - (mRightTrail.w + mBrightSpot.w / 2) + 16; + p.y = c.y - mRightTrail.h / 2; + fade = t < 0.25f ? t * 4.0f : 1.0f; fade *= fade; glColor4f(fade, fade, fade, fade); glBindTexture(GL_TEXTURE_2D, mRightTrail.name); glDrawTexiOES(p.x, p.y, 0, mRightTrail.w, mRightTrail.h); - } else { + } else { // vanishing trail.. - p.x = (amplitude + c.x) - (mRightTrail.w + mBrightSpot.w/2) + 16; - p.y = c.y-mRightTrail.h/2; - float fade = 2.0f*(0.5f-(t-0.5f)); + p.x = (amplitude + c.x) - (mRightTrail.w + mBrightSpot.w / 2) + 16; + p.y = c.y - mRightTrail.h / 2; + float fade = 2.0f * (0.5f - (t - 0.5f)); //fade *= fade; glColor4f(fade, fade, fade, fade); glBindTexture(GL_TEXTURE_2D, mRightTrail.name); glDrawTexiOES(p.x, p.y, 0, mRightTrail.w, mRightTrail.h); // trail... - p.x = (x + c.x) - mBrightSpot.w/2; - p.y = c.y-mLeftTrail.h/2; - fade = t<0.5f+0.25f ? (t-0.5f)*4.0f : 1.0f; + p.x = (x + c.x) - mBrightSpot.w / 2; + p.y = c.y - mLeftTrail.h / 2; + fade = t < 0.5f + 0.25f ? (t - 0.5f) * 4.0f : 1.0f; fade *= fade; glColor4f(fade, fade, fade, fade); glBindTexture(GL_TEXTURE_2D, mLeftTrail.name); glDrawTexiOES(p.x, p.y, 0, mLeftTrail.w, mLeftTrail.h); } - const Point p( x + c.x-mBrightSpot.w/2, c.y-mBrightSpot.h/2 ); + const Point p(x + c.x - mBrightSpot.w / 2, c.y - mBrightSpot.h / 2); glBindTexture(GL_TEXTURE_2D, mBrightSpot.name); - glColor4f(1,0.5,0.5,1); + glColor4f(1, 0.5, 0.5, 1); glDrawTexiOES(p.x, p.y, 0, mBrightSpot.w, mBrightSpot.h); // update animation nsecs_t time = systemTime() - startTime; - t = ((4.0f/(360.0f*us2ns(16667))) * time); + t = ((4.0f / (360.0f * us2ns(16667))) * time); t = t - floorf(t); eglSwapBuffers(mDisplay, mSurface); @@ -406,7 +384,7 @@ bool BootAnimation::cylon() alpha = 1.0f - ((float(time) * 6.0f) / float(s2ns(1))); session()->openTransaction(); - mFlingerSurface->setAlpha(alpha*alpha); + mFlingerSurface->setAlpha(alpha * alpha); session()->closeTransaction(); } } while (alpha > 0); @@ -421,4 +399,5 @@ bool BootAnimation::cylon() // --------------------------------------------------------------------------- -}; // namespace android +} +; // namespace android diff --git a/libs/surfaceflinger/BootAnimation.h b/libs/surfaceflinger/BootAnimation.h index a4a6d49..b20cea0 100644 --- a/libs/surfaceflinger/BootAnimation.h +++ b/libs/surfaceflinger/BootAnimation.h @@ -26,7 +26,8 @@ #include <ui/ISurfaceComposer.h> #include <ui/SurfaceComposerClient.h> -#include <GLES/egl.h> +#include <EGL/egl.h> +#include <GLES/gl.h> #include "Barrier.h" @@ -35,6 +36,7 @@ class SkBitmap; namespace android { class AssetManager; +class EGLNativeWindowSurface; // --------------------------------------------------------------------------- @@ -74,6 +76,7 @@ private: EGLDisplay mContext; EGLDisplay mSurface; sp<Surface> mFlingerSurface; + sp<EGLNativeWindowSurface> mNativeWindowSurface; Barrier mBarrier; }; diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp index 92588fa..f14d7e9 100644 --- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp +++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp @@ -21,14 +21,16 @@ #include <string.h> #include <math.h> -#include <GLES/egl.h> - #include <cutils/properties.h> #include <utils/Log.h> #include <ui/EGLDisplaySurface.h> +#include <GLES/gl.h> +#include <EGL/eglext.h> + + #include "DisplayHardware/DisplayHardware.h" #include <hardware/copybit.h> @@ -136,26 +138,19 @@ void DisplayHardware::init(uint32_t dpy) const char* const egl_extensions = eglQueryString( display, EGL_EXTENSIONS); - const char* egl_extensions_config = egl_extensions; - - if (strstr(egl_extensions, "EGL_ANDROID_query_string_config")) { - egl_extensions_config = eglQueryStringConfigANDROID( - display, config, EGL_EXTENSIONS); - } - LOGI("EGL informations:"); LOGI("# of configs : %d", numConfigs); LOGI("vendor : %s", eglQueryString(display, EGL_VENDOR)); LOGI("version : %s", eglQueryString(display, EGL_VERSION)); LOGI("extensions: %s", egl_extensions); - LOGI("ext/config: %s", egl_extensions_config); LOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported"); - if (strstr(egl_extensions_config, "EGL_ANDROID_swap_rectangle")) { - mFlags |= SWAP_RECTANGLE_EXTENSION; - // TODO: get the real "update_on_demand" behavior - mFlags |= UPDATE_ON_DEMAND; - } + // TODO: get this from the devfb driver (probably should be HAL module) + mFlags |= SWAP_RECTANGLE_EXTENSION; + + // TODO: get the real "update_on_demand" behavior (probably should be HAL module) + mFlags |= UPDATE_ON_DEMAND; + if (eglGetConfigAttrib(display, config, EGL_CONFIG_CAVEAT, &dummy) == EGL_TRUE) { if (dummy == EGL_SLOW_CONFIG) mFlags |= SLOW_CONFIG; @@ -173,9 +168,6 @@ void DisplayHardware::init(uint32_t dpy) if (eglQuerySurface(display, surface, EGL_SWAP_BEHAVIOR, &dummy) == EGL_TRUE) { if (dummy == EGL_BUFFER_PRESERVED) { mFlags |= BUFFER_PRESERVED; - if (strstr(egl_extensions_config, "EGL_ANDROID_copy_front_to_back")) { - mFlags |= COPY_BACK_EXTENSION; - } } } @@ -330,8 +322,7 @@ void DisplayHardware::flip(const Region& dirty) const if (mFlags & SWAP_RECTANGLE_EXTENSION) { const Rect& b(newDirty.bounds()); - eglSwapRectangleANDROID( - dpy, surface, + mDisplaySurface->setSwapRectangle( b.left, b.top, b.width(), b.height()); } @@ -352,3 +343,11 @@ void DisplayHardware::makeCurrent() const { eglMakeCurrent(mDisplay, mSurface, mSurface, mContext); } + +void DisplayHardware::copyFrontToImage(const copybit_image_t& front) const { + mDisplaySurface->copyFrontToImage(front); +} + +void DisplayHardware::copyBackToImage(const copybit_image_t& front) const { + mDisplaySurface->copyBackToImage(front); +} diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h index df97b60..550a4d1 100644 --- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h +++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h @@ -22,7 +22,7 @@ #include <ui/PixelFormat.h> #include <ui/Region.h> -#include <GLES/egl.h> +#include <EGL/egl.h> #include "DisplayHardware/DisplayHardwareBase.h" @@ -39,7 +39,6 @@ class DisplayHardware : public DisplayHardwareBase { public: enum { - COPY_BACK_EXTENSION = 0x00000001, DIRECT_TEXTURE = 0x00000002, SWAP_RECTANGLE_EXTENSION= 0x00000004, COPY_BITS_EXTENSION = 0x00000008, @@ -80,6 +79,9 @@ public: copybit_device_t* getBlitEngine() const { return mBlitEngine; } overlay_control_device_t* getOverlayEngine() const { return mOverlayEngine; } + void copyFrontToImage(const copybit_image_t& front) const; + void copyBackToImage(const copybit_image_t& front) const; + Rect bounds() const { return Rect(mWidth, mHeight); } diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp index f65d669..31e63ef 100644 --- a/libs/surfaceflinger/Layer.cpp +++ b/libs/surfaceflinger/Layer.cpp @@ -186,9 +186,7 @@ void Layer::onDraw(const Region& clip) const copybit_device_t* copybit = mFlinger->getBlitEngine(); copybit->set_parameter(copybit, COPYBIT_TRANSFORM, getOrientation()); copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha); - copybit->set_parameter(copybit, COPYBIT_DITHER, - s.flags & ISurfaceComposer::eLayerDither ? - COPYBIT_ENABLE : COPYBIT_DISABLE); + copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE); region_iterator it(clip); err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it); diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp index bdefba3..9277a64 100644 --- a/libs/surfaceflinger/LayerBase.cpp +++ b/libs/surfaceflinger/LayerBase.cpp @@ -23,6 +23,9 @@ #include <utils/Errors.h> #include <utils/Log.h> +#include <GLES/gl.h> +#include <GLES/glext.h> + #include "clz.h" #include "LayerBase.h" #include "LayerBlur.h" @@ -111,6 +114,12 @@ void LayerBase::commitTransaction(bool skipSize) { mDrawingState.h = h; } } +void LayerBase::forceVisibilityTransaction() { + // this can be called without SurfaceFlinger.mStateLock, but if we + // can atomically increment the sequence number, it doesn't matter. + android_atomic_inc(&mCurrentState.sequence); + requestTransaction(); +} bool LayerBase::requestTransaction() { int32_t old = setTransactionFlags(eTransactionNeeded); return ((old & eTransactionNeeded) == 0); @@ -220,10 +229,15 @@ Point LayerBase::getPhysicalSize() const return Point(front.w, front.h); } +Transform LayerBase::getDrawingStateTransform() const +{ + return drawingState().transform; +} + void LayerBase::validateVisibility(const Transform& planeTransform) { const Layer::State& s(drawingState()); - const Transform tr(planeTransform * s.transform); + const Transform tr(planeTransform * getDrawingStateTransform()); const bool transformed = tr.transformed(); const Point size(getPhysicalSize()); @@ -350,6 +364,10 @@ void LayerBase::draw(const Region& inClip) const return; } } + + // reset GL state + glEnable(GL_SCISSOR_TEST); + onDraw(clip); /* @@ -391,6 +409,7 @@ void LayerBase::clearWithOpenGL(const Region& clip) const Rect r; Region::iterator iterator(clip); if (iterator) { + glEnable(GL_SCISSOR_TEST); glVertexPointer(2, GL_FIXED, 0, mVertices); while (iterator.iterate(&r)) { const GLint sy = fbHeight - (r.top + r.height()); diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h index 5e14dc8..2377a14 100644 --- a/libs/surfaceflinger/LayerBase.h +++ b/libs/surfaceflinger/LayerBase.h @@ -86,8 +86,8 @@ public: uint32_t z; uint8_t alpha; uint8_t flags; - uint8_t sequence; // changes when visible regions can change - uint8_t reserved; + uint8_t reserved[2]; + int32_t sequence; // changes when visible regions can change uint32_t tint; Transform transform; Region transparentRegion; @@ -104,11 +104,11 @@ public: void commitTransaction(bool skipSize); bool requestTransaction(); - + void forceVisibilityTransaction(); + uint32_t getTransactionFlags(uint32_t flags); uint32_t setTransactionFlags(uint32_t flags); - void validateVisibility(const Transform& globalTransform); Rect visibleBounds() const; void drawRegion(const Region& reg) const; @@ -162,7 +162,19 @@ public: * the bitmap (as opposed to the size of the drawing state). */ virtual Point getPhysicalSize() const; - + + /** + * validateVisibility - cache a bunch of things + */ + virtual void validateVisibility(const Transform& globalTransform); + + /** + * getDrawingStateTransform - returns the drawing state's transform. + * This is used in validateVisibility() and can be use to override or + * modify the transform (if so make sure to trigger a transaction). + */ + virtual Transform getDrawingStateTransform() const; + /** * lockPageFlip - called each time the screen is redrawn and returns whether * the visible regions need to be recomputed (this is a fairly heavy @@ -320,8 +332,7 @@ public: *params = mParams; } - virtual status_t registerBuffers(int w, int h, int hstride, int vstride, - PixelFormat format, const sp<IMemoryHeap>& heap) + virtual status_t registerBuffers(const ISurface::BufferHeap& buffers) { return INVALID_OPERATION; } virtual void postBuffer(ssize_t offset) { } virtual void unregisterBuffers() { }; diff --git a/libs/surfaceflinger/LayerBitmap.cpp b/libs/surfaceflinger/LayerBitmap.cpp index 7c98857..e844350 100644 --- a/libs/surfaceflinger/LayerBitmap.cpp +++ b/libs/surfaceflinger/LayerBitmap.cpp @@ -69,18 +69,15 @@ status_t LayerBitmap::setBits(uint32_t w, uint32_t h, uint32_t alignment, return NO_ERROR; } + PixelFormatInfo info; + getPixelFormatInfo(format, &info); + uint32_t allocFlags = MemoryDealer::PAGE_ALIGNED; const uint32_t align = 4; // must match GL_UNPACK_ALIGNMENT - const uint32_t Bpp = bytesPerPixel(format); + const uint32_t Bpp = info.bytesPerPixel; uint32_t stride = (w + (alignment-1)) & ~(alignment-1); stride = ((stride * Bpp + (align-1)) & ~(align-1)) / Bpp; - size_t size = stride * h * Bpp; - if (format == PIXEL_FORMAT_YCbCr_422_SP || - format == PIXEL_FORMAT_YCbCr_420_SP) { - // in YUV planar, bitsPerPixel is for the Y plane - size = (size * bitsPerPixel(format)) / 8; - } - + size_t size = info.getScanlineSize(stride) * h; if (allocFlags & MemoryDealer::PAGE_ALIGNED) { size_t pagesize = getpagesize(); size = (size + (pagesize-1)) & ~(pagesize-1); diff --git a/libs/surfaceflinger/LayerBitmap.h b/libs/surfaceflinger/LayerBitmap.h index 4c2eb50..9ad64c4 100644 --- a/libs/surfaceflinger/LayerBitmap.h +++ b/libs/surfaceflinger/LayerBitmap.h @@ -70,9 +70,6 @@ public: void getBitmapSurface(copybit_image_t* img) const; private: - LayerBitmap(const LayerBitmap& rhs); - LayerBitmap& operator = (const LayerBitmap& rhs); - sp<MemoryDealer> mAllocator; sp<IMemory> mBitsMemory; uint32_t mAllocFlags; diff --git a/libs/surfaceflinger/LayerBlur.cpp b/libs/surfaceflinger/LayerBlur.cpp index efadbcf..d3e456f 100644 --- a/libs/surfaceflinger/LayerBlur.cpp +++ b/libs/surfaceflinger/LayerBlur.cpp @@ -23,6 +23,9 @@ #include <utils/Errors.h> #include <utils/Log.h> +#include <GLES/gl.h> +#include <GLES/glext.h> + #include "BlurFilter.h" #include "LayerBlur.h" #include "SurfaceFlinger.h" diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp index c9cebf4..fc0a603 100644 --- a/libs/surfaceflinger/LayerBuffer.cpp +++ b/libs/surfaceflinger/LayerBuffer.cpp @@ -25,6 +25,9 @@ #include <utils/Log.h> #include <utils/StopWatch.h> +#include <utils/IPCThreadState.h> +#include <utils/IServiceManager.h> + #include <ui/PixelFormat.h> #include <ui/EGLDisplaySurface.h> @@ -100,6 +103,15 @@ void LayerBuffer::unregisterBuffers() source->unregisterBuffers(); } +Transform LayerBuffer::getDrawingStateTransform() const +{ + Transform tr(LayerBaseClient::getDrawingStateTransform()); + sp<Source> source(getSource()); + if (source != 0) + source->updateTransform(&tr); + return tr; +} + uint32_t LayerBuffer::doTransaction(uint32_t flags) { sp<Source> source(getSource()); @@ -132,15 +144,13 @@ void LayerBuffer::onDraw(const Region& clip) const /** * 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) +status_t LayerBuffer::registerBuffers(const ISurface::BufferHeap& buffers) { Mutex::Autolock _l(mLock); if (mSource != 0) return INVALID_OPERATION; - sp<BufferSource> source = new BufferSource(*this, w, h, - hstride, vstride, format, memoryHeap); + sp<BufferSource> source = new BufferSource(*this, buffers); status_t result = source->getStatus(); if (result == NO_ERROR) { @@ -194,13 +204,39 @@ LayerBuffer::SurfaceBuffer::~SurfaceBuffer() mOwner = 0; } -status_t LayerBuffer::SurfaceBuffer::registerBuffers( - int w, int h, int hs, int vs, - PixelFormat format, const sp<IMemoryHeap>& heap) +status_t LayerBuffer::SurfaceBuffer::onTransact( + uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) +{ + switch (code) { + case REGISTER_BUFFERS: + case UNREGISTER_BUFFERS: + case CREATE_OVERLAY: + { + // codes that require permission check + IPCThreadState* ipc = IPCThreadState::self(); + const int pid = ipc->getCallingPid(); + const int self_pid = getpid(); + if (LIKELY(pid != self_pid)) { + // we're called from a different process, do the real check + if (!checkCallingPermission( + String16("android.permission.ACCESS_SURFACE_FLINGER"))) + { + const int uid = ipc->getCallingUid(); + LOGE("Permission Denial: " + "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid); + return PERMISSION_DENIED; + } + } + } + } + return LayerBaseClient::Surface::onTransact(code, data, reply, flags); +} + +status_t LayerBuffer::SurfaceBuffer::registerBuffers(const ISurface::BufferHeap& buffers) { LayerBuffer* owner(getOwner()); if (owner) - return owner->registerBuffers(w, h, hs, vs, format, heap); + return owner->registerBuffers(buffers); return NO_INIT; } @@ -237,23 +273,20 @@ void LayerBuffer::SurfaceBuffer::disown() // LayerBuffer::Buffer // ============================================================================ -LayerBuffer::Buffer::Buffer(const sp<IMemoryHeap>& heap, ssize_t offset, - int w, int h, int hs, int vs, int f) -: mHeap(heap) +LayerBuffer::Buffer::Buffer(const ISurface::BufferHeap& buffers, ssize_t offset) + : mBufferHeap(buffers) { 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.crop.r = buffers.w; + src.crop.b = buffers.h; + src.img.w = buffers.hor_stride ?: buffers.w; + src.img.h = buffers.ver_stride ?: buffers.h; + src.img.format = buffers.format; 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 + src.img.base = buffers.heap->base(); + src.img.fd = buffers.heap->heapID(); } LayerBuffer::Buffer::~Buffer() @@ -283,41 +316,53 @@ void LayerBuffer::Source::postBuffer(ssize_t offset) { } void LayerBuffer::Source::unregisterBuffers() { } +void LayerBuffer::Source::updateTransform(Transform* tr) const { +} // --------------------------------------------------------------------------- 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) + const ISurface::BufferHeap& buffers) + : Source(layer), mStatus(NO_ERROR), + mBufferSize(0), mTextureName(-1U) { - if (memoryHeap == NULL) { + if (buffers.heap == 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; + mBufferHeap = buffers; mLayer.setNeedsBlending(false); return; } - status_t err = (memoryHeap->heapID() >= 0) ? NO_ERROR : NO_INIT; + status_t err = (buffers.heap->heapID() >= 0) ? NO_ERROR : NO_INIT; if (err != NO_ERROR) { + LOGE("LayerBuffer::BufferSource: invalid heap (%s)", strerror(err)); 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); + err = getPixelFormatInfo(buffers.format, &info); + if (err != NO_ERROR) { + LOGE("LayerBuffer::BufferSource: invalid format %d (%s)", + buffers.format, strerror(err)); + mStatus = err; + return; + } + + if (buffers.hor_stride<0 || buffers.ver_stride<0) { + LOGE("LayerBuffer::BufferSource: invalid parameters " + "(w=%d, h=%d, xs=%d, ys=%d)", + buffers.w, buffers.h, buffers.hor_stride, buffers.ver_stride); + mStatus = BAD_VALUE; + return; + } + + mBufferHeap = buffers; + mLayer.setNeedsBlending((info.h_alpha - info.l_alpha) > 0); + mBufferSize = info.getScanlineSize(buffers.hor_stride)*buffers.ver_stride; + mLayer.forceVisibilityTransaction(); } LayerBuffer::BufferSource::~BufferSource() @@ -329,21 +374,24 @@ LayerBuffer::BufferSource::~BufferSource() void LayerBuffer::BufferSource::postBuffer(ssize_t offset) { - sp<IMemoryHeap> heap; - int w, h, hs, vs, f; + ISurface::BufferHeap buffers; { // scope for the lock Mutex::Autolock _l(mLock); - w = mWidth; - h = mHeight; - hs= mHStride; - vs= mVStride; - f = mFormat; - heap = mHeap; + buffers = mBufferHeap; + if (buffers.heap != 0) { + const size_t memorySize = buffers.heap->getSize(); + if ((size_t(offset) + mBufferSize) > memorySize) { + LOGE("LayerBuffer::BufferSource::postBuffer() " + "invalid buffer (offset=%d, size=%d, heap-size=%d", + int(offset), int(mBufferSize), int(memorySize)); + return; + } + } } sp<Buffer> buffer; - if (heap != 0) { - buffer = new LayerBuffer::Buffer(heap, offset, w, h, hs, vs, f); + if (buffers.heap != 0) { + buffer = new LayerBuffer::Buffer(buffers, offset); if (buffer->getStatus() != NO_ERROR) buffer.clear(); setBuffer(buffer); @@ -354,7 +402,7 @@ void LayerBuffer::BufferSource::postBuffer(ssize_t offset) void LayerBuffer::BufferSource::unregisterBuffers() { Mutex::Autolock _l(mLock); - mHeap.clear(); + mBufferHeap.heap.clear(); mBuffer.clear(); mLayer.invalidate(); } @@ -371,6 +419,17 @@ void LayerBuffer::BufferSource::setBuffer(const sp<LayerBuffer::Buffer>& buffer) mBuffer = buffer; } +void LayerBuffer::BufferSource::updateTransform(Transform* tr) const +{ + uint32_t bufTransform = mBufferHeap.transform; + // TODO: handle all transforms + if (bufTransform == ISurface::BufferHeap::ROT_90) { + Transform rot90; + rot90.set(0, -1, 1, 0); + *tr = (*tr) * rot90; + } +} + void LayerBuffer::BufferSource::onDraw(const Region& clip) const { sp<Buffer> buffer(getBuffer()); @@ -452,11 +511,13 @@ void LayerBuffer::BufferSource::onDraw(const Region& clip) const region_iterator it(clip); 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 ? - COPYBIT_ENABLE : COPYBIT_DISABLE); + copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE); + err = copybit->stretch(copybit, &dst, &src.img, &drect, &src.crop, &it); + if (err != NO_ERROR) { + LOGE("copybit failed (%s)", strerror(err)); + } } if (!can_use_copybit || err) { diff --git a/libs/surfaceflinger/LayerBuffer.h b/libs/surfaceflinger/LayerBuffer.h index 6e3d49f..5532532 100644 --- a/libs/surfaceflinger/LayerBuffer.h +++ b/libs/surfaceflinger/LayerBuffer.h @@ -22,7 +22,7 @@ #include <utils/IMemory.h> #include <private/ui/LayerState.h> -#include <GLES/eglnatives.h> +#include <EGL/eglnatives.h> #include "LayerBase.h" #include "LayerBitmap.h" @@ -46,6 +46,7 @@ class LayerBuffer : public LayerBaseClient virtual void onVisibilityResolved(const Transform& planeTransform); virtual void postBuffer(ssize_t offset); virtual void unregisterBuffers(); + virtual void updateTransform(Transform* tr) const; protected: LayerBuffer& mLayer; }; @@ -67,9 +68,9 @@ public: virtual void onDraw(const Region& clip) const; virtual uint32_t doTransaction(uint32_t flags); virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion); + virtual Transform getDrawingStateTransform() const; - status_t registerBuffers(int w, int h, int hstride, int vstride, - PixelFormat format, const sp<IMemoryHeap>& heap); + status_t registerBuffers(const ISurface::BufferHeap& buffers); void postBuffer(ssize_t offset); void unregisterBuffers(); sp<OverlayRef> createOverlay(uint32_t w, uint32_t h, int32_t format); @@ -89,10 +90,9 @@ private: class Buffer : public LightRefBase<Buffer> { public: - Buffer(const sp<IMemoryHeap>& heap, ssize_t offset, - int w, int h, int hs, int vs, int f); + Buffer(const ISurface::BufferHeap& buffers, ssize_t offset); inline status_t getStatus() const { - return mHeap!=0 ? NO_ERROR : NO_INIT; + return mBufferHeap.heap!=0 ? NO_ERROR : NO_INIT; } inline const NativeBuffer& getBuffer() const { return mNativeBuffer; @@ -103,34 +103,29 @@ private: Buffer(const Buffer& rhs); ~Buffer(); private: - sp<IMemoryHeap> mHeap; - NativeBuffer mNativeBuffer; + ISurface::BufferHeap mBufferHeap; + NativeBuffer mNativeBuffer; }; class BufferSource : public Source { public: - BufferSource(LayerBuffer& layer, - int w, int h, int hstride, int vstride, - PixelFormat format, const sp<IMemoryHeap>& heap); + BufferSource(LayerBuffer& layer, const ISurface::BufferHeap& buffers); virtual ~BufferSource(); status_t getStatus() const { return mStatus; } sp<Buffer> getBuffer() const; void setBuffer(const sp<Buffer>& buffer); + virtual void updateTransform(Transform* tr) const; 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; + ISurface::BufferHeap mBufferHeap; + size_t mBufferSize; mutable sp<MemoryDealer> mTemporaryDealer; mutable LayerBitmap mTempBitmap; mutable GLuint mTextureName; @@ -186,8 +181,9 @@ private: public: SurfaceBuffer(SurfaceID id, LayerBuffer* owner); virtual ~SurfaceBuffer(); - virtual status_t registerBuffers(int w, int h, int hstride, int vstride, - PixelFormat format, const sp<IMemoryHeap>& heap); + virtual status_t onTransact( + uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); + virtual status_t registerBuffers(const ISurface::BufferHeap& buffers); virtual void postBuffer(ssize_t offset); virtual void unregisterBuffers(); virtual sp<OverlayRef> createOverlay( diff --git a/libs/surfaceflinger/LayerOrientationAnim.cpp b/libs/surfaceflinger/LayerOrientationAnim.cpp new file mode 100644 index 0000000..46b3b19 --- /dev/null +++ b/libs/surfaceflinger/LayerOrientationAnim.cpp @@ -0,0 +1,287 @@ +/* + * Copyright (C) 2007 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. + */ + +#define LOG_TAG "SurfaceFlinger" + +#include <stdlib.h> +#include <stdint.h> +#include <sys/types.h> + +#include <utils/Errors.h> +#include <utils/Log.h> + +#include <core/SkBitmap.h> + +#include <ui/EGLDisplaySurface.h> + +#include "LayerBase.h" +#include "LayerOrientationAnim.h" +#include "SurfaceFlinger.h" +#include "DisplayHardware/DisplayHardware.h" +#include "OrientationAnimation.h" + +namespace android { +// --------------------------------------------------------------------------- + +const uint32_t LayerOrientationAnim::typeInfo = LayerBase::typeInfo | 0x80; +const char* const LayerOrientationAnim::typeID = "LayerOrientationAnim"; + +// --------------------------------------------------------------------------- + +LayerOrientationAnim::LayerOrientationAnim( + SurfaceFlinger* flinger, DisplayID display, + OrientationAnimation* anim, + const LayerBitmap& bitmap, + const LayerBitmap& bitmapIn) + : LayerBase(flinger, display), mAnim(anim), + mBitmap(bitmap), mBitmapIn(bitmapIn), + mTextureName(-1), mTextureNameIn(-1) +{ + mStartTime = systemTime(); + mFinishTime = 0; + mOrientationCompleted = false; + mFirstRedraw = false; + mLastNormalizedTime = 0; + mLastScale = 0; + mNeedsBlending = false; +} + +LayerOrientationAnim::~LayerOrientationAnim() +{ + if (mTextureName != -1U) { + LayerBase::deletedTextures.add(mTextureName); + } + if (mTextureNameIn != -1U) { + LayerBase::deletedTextures.add(mTextureNameIn); + } +} + +bool LayerOrientationAnim::needsBlending() const +{ + return mNeedsBlending; +} + +Point LayerOrientationAnim::getPhysicalSize() const +{ + const GraphicPlane& plane(graphicPlane(0)); + const DisplayHardware& hw(plane.displayHardware()); + return Point(hw.getWidth(), hw.getHeight()); +} + +void LayerOrientationAnim::validateVisibility(const Transform&) +{ + const Layer::State& s(drawingState()); + const Transform tr(getDrawingStateTransform()); + const Point size(getPhysicalSize()); + uint32_t w = size.x; + uint32_t h = size.y; + mTransformedBounds = tr.makeBounds(w, h); + mLeft = tr.tx(); + mTop = tr.ty(); + transparentRegionScreen.clear(); + mTransformed = true; + mCanUseCopyBit = false; + copybit_device_t* copybit = mFlinger->getBlitEngine(); + if (copybit) { + mCanUseCopyBit = true; + } +} + +void LayerOrientationAnim::onOrientationCompleted() +{ + mFinishTime = systemTime(); + mOrientationCompleted = true; + mFirstRedraw = true; + mNeedsBlending = true; + mFlinger->invalidateLayerVisibility(this); +} + +void LayerOrientationAnim::onDraw(const Region& clip) const +{ + // Animation... + const float MIN_SCALE = 0.5f; + const float DURATION = ms2ns(200); + const float BOUNCES_PER_SECOND = 1.618f; + const float BOUNCES_AMPLITUDE = 1.0f/32.0f; + + const nsecs_t now = systemTime(); + float scale, alpha; + + if (mOrientationCompleted) { + if (mFirstRedraw) { + mFirstRedraw = false; + + // make a copy of what's on screen + copybit_image_t image; + mBitmapIn.getBitmapSurface(&image); + const DisplayHardware& hw(graphicPlane(0).displayHardware()); + hw.copyBackToImage(image); + + // and erase the screen for this round + glDisable(GL_BLEND); + glDisable(GL_DITHER); + glDisable(GL_SCISSOR_TEST); + glClearColor(0,0,0,0); + glClear(GL_COLOR_BUFFER_BIT); + + // FIXME: code below is gross + mNeedsBlending = false; + LayerOrientationAnim* self(const_cast<LayerOrientationAnim*>(this)); + mFlinger->invalidateLayerVisibility(self); + } + + // make sure pick-up where we left off + const float duration = DURATION * mLastNormalizedTime; + const float normalizedTime = (float(now - mFinishTime) / duration); + if (normalizedTime <= 1.0f) { + const float squaredTime = normalizedTime*normalizedTime; + scale = (1.0f - mLastScale)*squaredTime + mLastScale; + alpha = (1.0f - normalizedTime); + alpha *= alpha; + alpha *= alpha; + } else { + mAnim->onAnimationFinished(); + scale = 1.0f; + alpha = 0.0f; + } + } else { + const float normalizedTime = float(now - mStartTime) / DURATION; + if (normalizedTime <= 1.0f) { + mLastNormalizedTime = normalizedTime; + const float squaredTime = normalizedTime*normalizedTime; + scale = (MIN_SCALE-1.0f)*squaredTime + 1.0f; + alpha = 1.0f; + } else { + mLastNormalizedTime = 1.0f; + const float to_seconds = DURATION / seconds(1); + const float phi = BOUNCES_PER_SECOND * + (((normalizedTime - 1.0f) * to_seconds)*M_PI*2); + scale = MIN_SCALE + BOUNCES_AMPLITUDE * (1.0f - cosf(phi)); + alpha = 1.0f; + } + mLastScale = scale; + } + drawScaled(scale, alpha); +} + +void LayerOrientationAnim::drawScaled(float f, float alpha) const +{ + copybit_image_t dst; + const GraphicPlane& plane(graphicPlane(0)); + const DisplayHardware& hw(plane.displayHardware()); + hw.getDisplaySurface(&dst); + + // clear screen + // TODO: with update on demand, we may be able + // to not erase the screen at all during the animation + if (!mOrientationCompleted) { + glDisable(GL_BLEND); + glDisable(GL_DITHER); + glDisable(GL_SCISSOR_TEST); + glClearColor(0,0,0,0); + glClear(GL_COLOR_BUFFER_BIT); + } + + const int w = dst.w*f; + const int h = dst.h*f; + const int xc = uint32_t(dst.w-w)/2; + const int yc = uint32_t(dst.h-h)/2; + const copybit_rect_t drect = { xc, yc, xc+w, yc+h }; + + copybit_image_t src; + mBitmap.getBitmapSurface(&src); + const copybit_rect_t srect = { 0, 0, src.w, src.h }; + + int err = NO_ERROR; + const int can_use_copybit = canUseCopybit(); + if (can_use_copybit) { + copybit_device_t* copybit = mFlinger->getBlitEngine(); + copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0); + copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE); + + if (alpha < 1.0f) { + copybit_image_t srcIn; + mBitmapIn.getBitmapSurface(&srcIn); + region_iterator it(Region(Rect( drect.l, drect.t, drect.r, drect.b ))); + copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF); + err = copybit->stretch(copybit, &dst, &srcIn, &drect, &srect, &it); + } + + if (!err && alpha > 0.0f) { + region_iterator it(Region(Rect( drect.l, drect.t, drect.r, drect.b ))); + copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, int(alpha*255)); + err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it); + } + LOGE_IF(err != NO_ERROR, "copybit failed (%s)", strerror(err)); + } + if (!can_use_copybit || err) { + GGLSurface t; + t.version = sizeof(GGLSurface); + t.width = src.w; + t.height = src.h; + t.stride = src.w; + t.vstride= src.h; + t.format = src.format; + t.data = (GGLubyte*)(intptr_t(src.base) + src.offset); + + Transform tr; + tr.set(f,0,0,f); + tr.set(xc, yc); + + // FIXME: we should not access mVertices and mDrawingState like that, + // but since we control the animation, we know it's going to work okay. + // eventually we'd need a more formal way of doing things like this. + LayerOrientationAnim& self(const_cast<LayerOrientationAnim&>(*this)); + tr.transform(self.mVertices[0], 0, 0); + tr.transform(self.mVertices[1], 0, src.h); + tr.transform(self.mVertices[2], src.w, src.h); + tr.transform(self.mVertices[3], src.w, 0); + if (!(mFlags & DisplayHardware::SLOW_CONFIG)) { + // Too slow to do this in software + self.mDrawingState.flags |= ISurfaceComposer::eLayerFilter; + } + + if (alpha < 1.0f) { + copybit_image_t src; + mBitmapIn.getBitmapSurface(&src); + t.data = (GGLubyte*)(intptr_t(src.base) + src.offset); + if (UNLIKELY(mTextureNameIn == -1LU)) { + mTextureNameIn = createTexture(); + GLuint w=0, h=0; + const Region dirty(Rect(t.width, t.height)); + loadTexture(dirty, mTextureNameIn, t, w, h); + } + self.mDrawingState.alpha = 255; + const Region clip(Rect( drect.l, drect.t, drect.r, drect.b )); + drawWithOpenGL(clip, mTextureName, t); + } + + t.data = (GGLubyte*)(intptr_t(src.base) + src.offset); + if (UNLIKELY(mTextureName == -1LU)) { + mTextureName = createTexture(); + GLuint w=0, h=0; + const Region dirty(Rect(t.width, t.height)); + loadTexture(dirty, mTextureName, t, w, h); + } + self.mDrawingState.alpha = int(alpha*255); + const Region clip(Rect( drect.l, drect.t, drect.r, drect.b )); + drawWithOpenGL(clip, mTextureName, t); + } +} + +// --------------------------------------------------------------------------- + +}; // namespace android diff --git a/libs/surfaceflinger/LayerOrientationAnim.h b/libs/surfaceflinger/LayerOrientationAnim.h new file mode 100644 index 0000000..7367685 --- /dev/null +++ b/libs/surfaceflinger/LayerOrientationAnim.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2007 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_LAYER_ORIENTATION_ANIM_H +#define ANDROID_LAYER_ORIENTATION_ANIM_H + +#include <stdint.h> +#include <sys/types.h> +#include <utils/threads.h> +#include <utils/Parcel.h> + +#include "LayerBase.h" +#include "LayerBitmap.h" + +namespace android { + +// --------------------------------------------------------------------------- +class OrientationAnimation; + +class LayerOrientationAnim : public LayerBase +{ +public: + static const uint32_t typeInfo; + static const char* const typeID; + virtual char const* getTypeID() const { return typeID; } + virtual uint32_t getTypeInfo() const { return typeInfo; } + + LayerOrientationAnim(SurfaceFlinger* flinger, DisplayID display, + OrientationAnimation* anim, + const LayerBitmap& zoomOut, + const LayerBitmap& zoomIn); + virtual ~LayerOrientationAnim(); + + void onOrientationCompleted(); + + virtual void onDraw(const Region& clip) const; + virtual Point getPhysicalSize() const; + virtual void validateVisibility(const Transform& globalTransform); + virtual bool needsBlending() const; + virtual bool isSecure() const { return false; } +private: + void drawScaled(float scale, float alpha) const; + + OrientationAnimation* mAnim; + LayerBitmap mBitmap; + LayerBitmap mBitmapIn; + nsecs_t mStartTime; + nsecs_t mFinishTime; + bool mOrientationCompleted; + mutable bool mFirstRedraw; + mutable float mLastNormalizedTime; + mutable float mLastScale; + mutable GLuint mTextureName; + mutable GLuint mTextureNameIn; + mutable bool mNeedsBlending; +}; + +// --------------------------------------------------------------------------- + +}; // namespace android + +#endif // ANDROID_LAYER_ORIENTATION_ANIM_H diff --git a/libs/surfaceflinger/LayerScreenshot.cpp b/libs/surfaceflinger/LayerScreenshot.cpp index 3e7132b..40c47b0 100644 --- a/libs/surfaceflinger/LayerScreenshot.cpp +++ b/libs/surfaceflinger/LayerScreenshot.cpp @@ -35,7 +35,7 @@ namespace android { // --------------------------------------------------------------------------- -const uint32_t LayerScreenshot::typeInfo = LayerBase::typeInfo | 0x20; +const uint32_t LayerScreenshot::typeInfo = LayerBase::typeInfo | 0x40; const char* const LayerScreenshot::typeID = "LayerScreenshot"; // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/OrientationAnimation.cpp b/libs/surfaceflinger/OrientationAnimation.cpp new file mode 100644 index 0000000..f6f1326 --- /dev/null +++ b/libs/surfaceflinger/OrientationAnimation.cpp @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2007 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. + */ + +#define LOG_TAG "SurfaceFlinger" + +#include <stdint.h> +#include <sys/types.h> +#include <limits.h> + +#include "LayerOrientationAnim.h" +#include "OrientationAnimation.h" +#include "SurfaceFlinger.h" +#include "VRamHeap.h" + +#include "DisplayHardware/DisplayHardware.h" + +namespace android { + +// --------------------------------------------------------------------------- + +OrientationAnimation::OrientationAnimation(const sp<SurfaceFlinger>& flinger) + : mFlinger(flinger), mLayerOrientationAnim(NULL), mState(DONE) +{ + // allocate a memory-dealer for this the first time + mTemporaryDealer = mFlinger->getSurfaceHeapManager()->createHeap( + ISurfaceComposer::eHardware); +} + +OrientationAnimation::~OrientationAnimation() +{ +} + +void OrientationAnimation::onOrientationChanged() +{ + if (mState == DONE) + mState = PREPARE; +} + +void OrientationAnimation::onAnimationFinished() +{ + if (mState != DONE) + mState = FINISH; +} + +bool OrientationAnimation::run_impl() +{ + bool skip_frame; + switch (mState) { + default: + case DONE: + skip_frame = done(); + break; + case PREPARE: + skip_frame = prepare(); + break; + case PHASE1: + skip_frame = phase1(); + break; + case PHASE2: + skip_frame = phase2(); + break; + case FINISH: + skip_frame = finished(); + break; + } + return skip_frame; +} + +bool OrientationAnimation::done() +{ + if (mFlinger->isFrozen()) { + // we are not allowed to draw, but pause a bit to make sure + // apps don't end up using the whole CPU, if they depend on + // surfaceflinger for synchronization. + usleep(8333); // 8.3ms ~ 120fps + return true; + } + return false; +} + +bool OrientationAnimation::prepare() +{ + mState = PHASE1; + + const GraphicPlane& plane(mFlinger->graphicPlane(0)); + const DisplayHardware& hw(plane.displayHardware()); + const uint32_t w = hw.getWidth(); + const uint32_t h = hw.getHeight(); + + LayerBitmap bitmap; + bitmap.init(mTemporaryDealer); + bitmap.setBits(w, h, 1, hw.getFormat()); + + LayerBitmap bitmapIn; + bitmapIn.init(mTemporaryDealer); + bitmapIn.setBits(w, h, 1, hw.getFormat()); + + copybit_image_t front; + bitmap.getBitmapSurface(&front); + hw.copyFrontToImage(front); + + LayerOrientationAnim* l = new LayerOrientationAnim( + mFlinger.get(), 0, this, bitmap, bitmapIn); + l->initStates(w, h, 0); + l->setLayer(INT_MAX-1); + mFlinger->addLayer(l); + mLayerOrientationAnim = l; + return true; +} + +bool OrientationAnimation::phase1() +{ + if (mFlinger->isFrozen() == false) { + // start phase 2 + mState = PHASE2; + mLayerOrientationAnim->onOrientationCompleted(); + mLayerOrientationAnim->invalidate(); + return true; + + } + mLayerOrientationAnim->invalidate(); + return false; +} + +bool OrientationAnimation::phase2() +{ + // do the 2nd phase of the animation + mLayerOrientationAnim->invalidate(); + return false; +} + +bool OrientationAnimation::finished() +{ + mState = DONE; + mFlinger->removeLayer(mLayerOrientationAnim); + mLayerOrientationAnim = NULL; + return true; +} + +// --------------------------------------------------------------------------- + +}; // namespace android diff --git a/libs/surfaceflinger/OrientationAnimation.h b/libs/surfaceflinger/OrientationAnimation.h new file mode 100644 index 0000000..ba33fce --- /dev/null +++ b/libs/surfaceflinger/OrientationAnimation.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2007 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_ORIENTATION_ANIMATION_H +#define ANDROID_ORIENTATION_ANIMATION_H + +#include <stdint.h> +#include <sys/types.h> + +#include "SurfaceFlinger.h" + +namespace android { + +// --------------------------------------------------------------------------- + +class SurfaceFlinger; +class MemoryDealer; +class LayerOrientationAnim; + +class OrientationAnimation +{ +public: + OrientationAnimation(const sp<SurfaceFlinger>& flinger); + virtual ~OrientationAnimation(); + + void onOrientationChanged(); + void onAnimationFinished(); + inline bool run() { + if (LIKELY(mState == DONE)) + return false; + return run_impl(); + } + +private: + enum { + DONE = 0, + PREPARE, + PHASE1, + PHASE2, + FINISH + }; + + bool run_impl(); + bool done(); + bool prepare(); + bool phase1(); + bool phase2(); + bool finished(); + + sp<SurfaceFlinger> mFlinger; + sp<MemoryDealer> mTemporaryDealer; + LayerOrientationAnim* mLayerOrientationAnim; + int mState; +}; + +// --------------------------------------------------------------------------- + +}; // namespace android + +#endif // ANDROID_ORIENTATION_ANIMATION_H diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp index 4c719e8..4e457c9 100644 --- a/libs/surfaceflinger/SurfaceFlinger.cpp +++ b/libs/surfaceflinger/SurfaceFlinger.cpp @@ -52,7 +52,9 @@ #include "LayerBuffer.h" #include "LayerDim.h" #include "LayerBitmap.h" +#include "LayerOrientationAnim.h" #include "LayerScreenshot.h" +#include "OrientationAnimation.h" #include "SurfaceFlinger.h" #include "RFBServer.h" #include "VRamHeap.h" @@ -224,6 +226,7 @@ void SurfaceFlinger::init() SurfaceFlinger::~SurfaceFlinger() { glDeleteTextures(1, &mWormholeTexName); + delete mOrientationAnimation; } copybit_device_t* SurfaceFlinger::getBlitEngine() const @@ -447,6 +450,8 @@ status_t SurfaceFlinger::readyToRun() * We're now ready to accept clients... */ + mOrientationAnimation = new OrientationAnimation(this); + // start CPU gauge display if (mDebugCpu) mCpuGauge = new CPUGauge(this, ms2ns(500)); @@ -471,8 +476,8 @@ void SurfaceFlinger::waitForEvent() { // wait for something to do if (UNLIKELY(isFrozen())) { - // wait 2 seconds - int err = mSyncObject.wait(ms2ns(3000)); + // wait 5 seconds + int err = mSyncObject.wait(ms2ns(5000)); if (err != NO_ERROR) { if (isFrozen()) { // we timed out and are still frozen @@ -555,11 +560,8 @@ bool SurfaceFlinger::threadLoop() void SurfaceFlinger::postFramebuffer() { - if (UNLIKELY(isFrozen())) { - // we are not allowed to draw, but pause a bit to make sure - // apps don't end up using the whole CPU, if they depend on - // surfaceflinger for synchronization. - usleep(8333); // 8.3ms ~ 120fps + const bool skip = mOrientationAnimation->run(); + if (UNLIKELY(skip)) { return; } @@ -684,6 +686,8 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) mVisibleRegionsDirty = true; mDirtyRegion.set(hw.bounds()); + + mOrientationAnimation->onOrientationChanged(); } if (mCurrentState.freezeDisplay != mDrawingState.freezeDisplay) { @@ -874,19 +878,9 @@ void SurfaceFlinger::handleRepaint() uint32_t flags = hw.getFlags(); if (flags & DisplayHardware::BUFFER_PRESERVED) { - if (flags & DisplayHardware::COPY_BACK_EXTENSION) { - // yay. nothing to do here. - } else { - if (flags & DisplayHardware::UPDATE_ON_DEMAND) { - // we need to fully redraw the part that will be updated - mDirtyRegion.set(mInvalidRegion.bounds()); - } else { - // TODO: we only need te redraw the part that had been drawn - // the round before and is not drawn now - } - } + // here we assume DisplayHardware::flip()'s implementation + // performs the copy-back optimization. } else { - // COPY_BACK_EXTENSION makes no sense here if (flags & DisplayHardware::UPDATE_ON_DEMAND) { // we need to fully redraw the part that will be updated mDirtyRegion.set(mInvalidRegion.bounds()); @@ -1076,6 +1070,29 @@ void SurfaceFlinger::debugShowFPS() const // XXX: mFPS has the value we want } +status_t SurfaceFlinger::addLayer(LayerBase* layer) +{ + Mutex::Autolock _l(mStateLock); + addLayer_l(layer); + setTransactionFlags(eTransactionNeeded|eTraversalNeeded); + return NO_ERROR; +} + +status_t SurfaceFlinger::removeLayer(LayerBase* layer) +{ + Mutex::Autolock _l(mStateLock); + removeLayer_l(layer); + setTransactionFlags(eTransactionNeeded); + return NO_ERROR; +} + +status_t SurfaceFlinger::invalidateLayerVisibility(LayerBase* layer) +{ + layer->forceVisibilityTransaction(); + setTransactionFlags(eTraversalNeeded); + return NO_ERROR; +} + status_t SurfaceFlinger::addLayer_l(LayerBase* layer) { ssize_t i = mCurrentState.layersSortedByZ.add( diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/libs/surfaceflinger/SurfaceFlinger.h index a242f1a..8e5fd88 100644 --- a/libs/surfaceflinger/SurfaceFlinger.h +++ b/libs/surfaceflinger/SurfaceFlinger.h @@ -35,11 +35,11 @@ #include <private/ui/LayerState.h> #include <private/ui/SurfaceFlingerSynchro.h> +#include "Barrier.h" +#include "BootAnimation.h" +#include "CPUGauge.h" #include "Layer.h" #include "Tokenizer.h" -#include "CPUGauge.h" -#include "BootAnimation.h" -#include "Barrier.h" struct copybit_device_t; struct overlay_device_t; @@ -48,16 +48,18 @@ namespace android { // --------------------------------------------------------------------------- -class BClient; class Client; +class BClient; class DisplayHardware; +class FreezeLock; class GPUHardwareInterface; class IGPUCallback; class Layer; class LayerBuffer; +class LayerOrientationAnim; +class OrientationAnimation; class RFBServer; class SurfaceHeapManager; -class FreezeLock; typedef int32_t ClientID; @@ -181,7 +183,12 @@ public: copybit_device_t* getBlitEngine() const; overlay_control_device_t* getOverlayEngine() const; + + status_t removeLayer(LayerBase* layer); + status_t addLayer(LayerBase* layer); + status_t invalidateLayerVisibility(LayerBase* layer); + private: friend class BClient; friend class LayerBase; @@ -352,6 +359,8 @@ private: bool mFreezeDisplay; int32_t mFreezeCount; nsecs_t mFreezeDisplayTime; + friend class OrientationAnimation; + OrientationAnimation* mOrientationAnimation; // access protected by mDebugLock mutable Mutex mDebugLock; diff --git a/libs/surfaceflinger/VRamHeap.cpp b/libs/surfaceflinger/VRamHeap.cpp index 77bc576..0ccd71f 100644 --- a/libs/surfaceflinger/VRamHeap.cpp +++ b/libs/surfaceflinger/VRamHeap.cpp @@ -35,8 +35,6 @@ #include <utils/MemoryHeapPmem.h> #include <utils/MemoryHeapBase.h> -#include <GLES/eglnatives.h> - #include "GPUHardware/GPUHardware.h" #include "SurfaceFlinger.h" #include "VRamHeap.h" diff --git a/libs/ui/Camera.cpp b/libs/ui/Camera.cpp index 50c6008..6c60b85 100644 --- a/libs/ui/Camera.cpp +++ b/libs/ui/Camera.cpp @@ -84,8 +84,10 @@ void Camera::init() mRawCallbackCookie = 0; mJpegCallback = 0; mJpegCallbackCookie = 0; - mFrameCallback = 0; - mFrameCallbackCookie = 0; + mPreviewCallback = 0; + mPreviewCallbackCookie = 0; + mRecordingCallback = 0; + mRecordingCallbackCookie = 0; mErrorCallback = 0; mErrorCallbackCookie = 0; mAutoFocusCallback = 0; @@ -184,6 +186,15 @@ status_t Camera::startPreview() return c->startPreview(); } +// start recording mode, must call setPreviewDisplay first +status_t Camera::startRecording() +{ + LOGV("startRecording"); + sp <ICamera> c = mCamera; + if (c == 0) return NO_INIT; + return c->startRecording(); +} + // stop preview mode void Camera::stopPreview() { @@ -193,6 +204,24 @@ void Camera::stopPreview() c->stopPreview(); } +// stop recording mode +void Camera::stopRecording() +{ + LOGV("stopRecording"); + sp <ICamera> c = mCamera; + if (c == 0) return; + c->stopRecording(); +} + +// release a recording frame +void Camera::releaseRecordingFrame(const sp<IMemory>& mem) +{ + LOGV("releaseRecordingFrame"); + sp <ICamera> c = mCamera; + if (c == 0) return; + c->releaseRecordingFrame(mem); +} + // get preview state bool Camera::previewEnabled() { @@ -202,6 +231,15 @@ bool Camera::previewEnabled() return c->previewEnabled(); } +// get recording state +bool Camera::recordingEnabled() +{ + LOGV("recordingEnabled"); + sp <ICamera> c = mCamera; + if (c == 0) return false; + return c->recordingEnabled(); +} + status_t Camera::autoFocus() { LOGV("autoFocus"); @@ -266,14 +304,21 @@ void Camera::setJpegCallback(frame_callback cb, void *cookie) mJpegCallbackCookie = cookie; } -void Camera::setFrameCallback(frame_callback cb, void *cookie, int frame_callback_flag) +void Camera::setPreviewCallback(frame_callback cb, void *cookie, int flag) { - LOGV("setFrameCallback"); - mFrameCallback = cb; - mFrameCallbackCookie = cookie; + LOGV("setPreviewCallback"); + mPreviewCallback = cb; + mPreviewCallbackCookie = cookie; sp <ICamera> c = mCamera; if (c == 0) return; - mCamera->setFrameCallbackFlag(frame_callback_flag); + mCamera->setPreviewCallbackFlag(flag); +} + +void Camera::setRecordingCallback(frame_callback cb, void *cookie) +{ + LOGV("setRecordingCallback"); + mRecordingCallback = cb; + mRecordingCallbackCookie = cookie; } void Camera::setErrorCallback(error_callback cb, void *cookie) @@ -316,12 +361,21 @@ void Camera::jpegCallback(const sp<IMemory>& picture) } } -// callback from camera service when video frame is ready -void Camera::frameCallback(const sp<IMemory>& frame) +// callback from camera service when preview frame is ready +void Camera::previewCallback(const sp<IMemory>& frame) { LOGV("frameCallback"); - if (mFrameCallback) { - mFrameCallback(frame, mFrameCallbackCookie); + if (mPreviewCallback) { + mPreviewCallback(frame, mPreviewCallbackCookie); + } +} + +// callback from camera service when a recording frame is ready +void Camera::recordingCallback(const sp<IMemory>& frame) +{ + LOGV("recordingCallback"); + if (mRecordingCallback) { + mRecordingCallback(frame, mRecordingCallbackCookie); } } diff --git a/libs/ui/CameraParameters.cpp b/libs/ui/CameraParameters.cpp index 7ca77bb..6c25836 100644 --- a/libs/ui/CameraParameters.cpp +++ b/libs/ui/CameraParameters.cpp @@ -24,6 +24,9 @@ namespace android { +static const char* portrait = "portrait"; +static const char* landscape = "landscape"; + CameraParameters::CameraParameters() : mMap() { @@ -182,6 +185,23 @@ void CameraParameters::setPreviewFormat(const char *format) set("preview-format", format); } +int CameraParameters::getOrientation() const +{ + const char* orientation = get("orientation"); + if (orientation && !strcmp(orientation, portrait)) + return CAMERA_ORIENTATION_PORTRAIT; + return CAMERA_ORIENTATION_LANDSCAPE; +} + +void CameraParameters::setOrientation(int orientation) +{ + if (orientation == CAMERA_ORIENTATION_PORTRAIT) { + set("preview-format", portrait); + } else { + set("preview-format", landscape); + } +} + const char *CameraParameters::getPreviewFormat() const { return get("preview-format"); diff --git a/libs/ui/EGLDisplaySurface.cpp b/libs/ui/EGLDisplaySurface.cpp index 44258a8..d06c98b 100644 --- a/libs/ui/EGLDisplaySurface.cpp +++ b/libs/ui/EGLDisplaySurface.cpp @@ -42,7 +42,7 @@ #include <linux/msm_mdp.h> #endif -#include <GLES/egl.h> +#include <EGL/egl.h> #include <pixelflinger/format.h> @@ -71,8 +71,6 @@ EGLDisplaySurface::EGLDisplaySurface() egl_native_window_t::incRef = &EGLDisplaySurface::hook_incRef; egl_native_window_t::decRef = &EGLDisplaySurface::hook_decRef; egl_native_window_t::swapBuffers = &EGLDisplaySurface::hook_swapBuffers; - egl_native_window_t::setSwapRectangle = &EGLDisplaySurface::hook_setSwapRectangle; - egl_native_window_t::nextBuffer = &EGLDisplaySurface::hook_nextBuffer; egl_native_window_t::connect = 0; egl_native_window_t::disconnect = 0; @@ -136,15 +134,6 @@ uint32_t EGLDisplaySurface::hook_swapBuffers(NativeWindowType window) { EGLDisplaySurface* that = static_cast<EGLDisplaySurface*>(window); return that->swapBuffers(); } -uint32_t EGLDisplaySurface::hook_nextBuffer(NativeWindowType window) { - EGLDisplaySurface* that = static_cast<EGLDisplaySurface*>(window); - return that->nextBuffer(); -} -void EGLDisplaySurface::hook_setSwapRectangle(NativeWindowType window, - int l, int t, int w, int h) { - EGLDisplaySurface* that = static_cast<EGLDisplaySurface*>(window); - that->setSwapRectangle(l, t, w, h); -} void EGLDisplaySurface::setSwapRectangle(int l, int t, int w, int h) { @@ -249,15 +238,6 @@ int32_t EGLDisplaySurface::getPageFlipCount() const return mPageFlipCount; } -uint32_t EGLDisplaySurface::nextBuffer() -{ - // update the address of the buffer to draw to next - const GGLSurface& buffer = mFb[mIndex]; - egl_native_window_t::offset = - intptr_t(buffer.data) - egl_native_window_t::base; - return 0; -} - void EGLDisplaySurface::copyFrontToBack(const Region& copyback) { #if HAVE_ANDROID_OS @@ -318,6 +298,59 @@ void EGLDisplaySurface::copyFrontToBack(const Region& copyback) } } +void EGLDisplaySurface::copyFrontToImage(const copybit_image_t& dst) +{ +#if HAVE_ANDROID_OS + if (mBlitEngine) { + copybit_image_t src = { + w: egl_native_window_t::stride, + h: egl_native_window_t::height, + format: egl_native_window_t::format, + offset: mFb[mIndex].data - mFb[0].data, + base: (void*)egl_native_window_t::base, + fd: egl_native_window_t::fd + }; + region_iterator it(Region(Rect( + egl_native_window_t::width, egl_native_window_t::height))); + mBlitEngine->blit(mBlitEngine, &dst, &src, &it); + } else +#endif + { + uint8_t* const screen_src = mFb[ mIndex].data; + const size_t bpp = bytesPerPixel(egl_native_window_t::format); + const size_t bpr = egl_native_window_t::stride * bpp; + memcpy((char*)dst.base + dst.offset, screen_src, + bpr*egl_native_window_t::height); + } +} + +void EGLDisplaySurface::copyBackToImage(const copybit_image_t& dst) +{ +#if HAVE_ANDROID_OS + if (mBlitEngine) { + copybit_image_t src = { + w: egl_native_window_t::stride, + h: egl_native_window_t::height, + format: egl_native_window_t::format, + offset: mFb[1-mIndex].data - mFb[0].data, + base: (void*)egl_native_window_t::base, + fd: egl_native_window_t::fd + }; + region_iterator it(Region(Rect( + egl_native_window_t::width, egl_native_window_t::height))); + mBlitEngine->blit(mBlitEngine, &dst, &src, &it); + } else +#endif + { + uint8_t* const screen_src = mFb[1-mIndex].data; + const size_t bpp = bytesPerPixel(egl_native_window_t::format); + const size_t bpr = egl_native_window_t::stride * bpp; + memcpy((char*)dst.base + dst.offset, screen_src, + bpr*egl_native_window_t::height); + } +} + + status_t EGLDisplaySurface::mapFrameBuffer() { char const * const device_template[] = { diff --git a/libs/ui/EGLNativeWindowSurface.cpp b/libs/ui/EGLNativeWindowSurface.cpp index d55fb70..f1071cf 100644 --- a/libs/ui/EGLNativeWindowSurface.cpp +++ b/libs/ui/EGLNativeWindowSurface.cpp @@ -28,7 +28,7 @@ #include <ui/DisplayInfo.h> #include <ui/Rect.h> -#include <GLES/egl.h> +#include <EGL/egl.h> #include <pixelflinger/format.h> @@ -48,8 +48,6 @@ EGLNativeWindowSurface::EGLNativeWindowSurface(const sp<Surface>& surface) egl_native_window_t::incRef = &EGLNativeWindowSurface::hook_incRef; egl_native_window_t::decRef = &EGLNativeWindowSurface::hook_decRef; egl_native_window_t::swapBuffers = &EGLNativeWindowSurface::hook_swapBuffers; - egl_native_window_t::nextBuffer = &EGLNativeWindowSurface::hook_nextBuffer; - egl_native_window_t::setSwapRectangle = &EGLNativeWindowSurface::hook_setSwapRectangle; egl_native_window_t::connect = &EGLNativeWindowSurface::hook_connect; egl_native_window_t::disconnect = &EGLNativeWindowSurface::hook_disconnect; @@ -98,18 +96,6 @@ uint32_t EGLNativeWindowSurface::hook_swapBuffers(NativeWindowType window) return that->swapBuffers(); } -uint32_t EGLNativeWindowSurface::hook_nextBuffer(NativeWindowType window) -{ - EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window); - return that->nextBuffer(); -} - -void EGLNativeWindowSurface::hook_setSwapRectangle(NativeWindowType window, int l, int t, int w, int h) -{ - EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window); - that->setSwapRectangle(l, t, w, h); -} - void EGLNativeWindowSurface::setSwapRectangle(int l, int t, int w, int h) { mSurface->setSwapRectangle(Rect(l, t, l+w, t+h)); @@ -138,17 +124,6 @@ uint32_t EGLNativeWindowSurface::swapBuffers() return 0; } -uint32_t EGLNativeWindowSurface::nextBuffer() -{ - const sp<Surface>& surface(mSurface); - Surface::SurfaceInfo info; - surface->nextBuffer(&info); - // update the address of the buffer to draw to next - egl_native_window_t::base = intptr_t(info.base); - egl_native_window_t::offset = intptr_t(info.bits) - intptr_t(info.base); - return 0; -} - void EGLNativeWindowSurface::connect() { if (!mConnected) { diff --git a/libs/ui/EventHub.cpp b/libs/ui/EventHub.cpp index 700aa3a..3b29b09 100644 --- a/libs/ui/EventHub.cpp +++ b/libs/ui/EventHub.cpp @@ -71,10 +71,11 @@ static inline int max(int v1, int v2) EventHub::device_t::device_t(int32_t _id, const char* _path) : id(_id), path(_path), classes(0) - , layoutMap(new KeyLayoutMap()), next(NULL) { + , keyBitmask(NULL), layoutMap(new KeyLayoutMap()), next(NULL) { } EventHub::device_t::~device_t() { + delete [] keyBitmask; delete layoutMap; } @@ -403,6 +404,36 @@ bool EventHub::openPlatformInput(void) return true; } +/* + * Inspect the known devices to determine whether physical keys exist for the given + * framework-domain key codes. + */ +bool EventHub::hasKeys(size_t numCodes, int32_t* keyCodes, uint8_t* outFlags) { + for (size_t codeIndex = 0; codeIndex < numCodes; codeIndex++) { + outFlags[codeIndex] = 0; + + // check each available hardware device for support for this keycode + Vector<int32_t> scanCodes; + for (int n = 0; (n < mFDCount) && (outFlags[codeIndex] == 0); n++) { + if (mDevices[n]) { + status_t err = mDevices[n]->layoutMap->findScancodes(keyCodes[codeIndex], &scanCodes); + if (!err) { + // check the possible scan codes identified by the layout map against the + // map of codes actually emitted by the driver + for (size_t sc = 0; sc < scanCodes.size(); sc++) { + if (test_bit(scanCodes[sc], mDevices[n]->keyBitmask)) { + outFlags[codeIndex] = 1; + break; + } + } + } + } + } + } + + return true; +} + // ---------------------------------------------------------------------------- int EventHub::open_device(const char *deviceName) @@ -527,6 +558,16 @@ int EventHub::open_device(const char *deviceName) break; } } + if ((device->classes & CLASS_KEYBOARD) != 0) { + device->keyBitmask = new uint8_t[(KEY_MAX+1)/8]; + if (device->keyBitmask != NULL) { + memcpy(device->keyBitmask, key_bitmask, sizeof(key_bitmask)); + } else { + delete device; + LOGE("out of memory allocating key bitmask"); + return -1; + } + } } if (test_bit(BTN_MOUSE, key_bitmask)) { uint8_t rel_bitmask[(REL_MAX+1)/8]; diff --git a/libs/ui/ICamera.cpp b/libs/ui/ICamera.cpp index 7b0922e..ab0fef1 100644 --- a/libs/ui/ICamera.cpp +++ b/libs/ui/ICamera.cpp @@ -28,7 +28,7 @@ namespace android { enum { DISCONNECT = IBinder::FIRST_CALL_TRANSACTION, SET_PREVIEW_DISPLAY, - SET_FRAME_CALLBACK_FLAG, + SET_PREVIEW_CALLBACK_FLAG, START_PREVIEW, STOP_PREVIEW, AUTO_FOCUS, @@ -38,7 +38,11 @@ enum { CONNECT, LOCK, UNLOCK, - PREVIEW_ENABLED + PREVIEW_ENABLED, + START_RECORDING, + STOP_RECORDING, + RECORDING_ENABLED, + RELEASE_RECORDING_FRAME, }; class BpCamera: public BpInterface<ICamera> @@ -69,15 +73,15 @@ public: return reply.readInt32(); } - // set the frame callback flag to affect how the received frames from - // preview are handled. - void setFrameCallbackFlag(int frame_callback_flag) + // set the preview callback flag to affect how the received frames from + // preview are handled. See Camera.h for details. + void setPreviewCallbackFlag(int flag) { - LOGV("setFrameCallbackFlag(%d)", frame_callback_flag); + LOGV("setPreviewCallbackFlag(%d)", flag); Parcel data, reply; data.writeInterfaceToken(ICamera::getInterfaceDescriptor()); - data.writeInt32(frame_callback_flag); - remote()->transact(SET_FRAME_CALLBACK_FLAG, data, &reply); + data.writeInt32(flag); + remote()->transact(SET_PREVIEW_CALLBACK_FLAG, data, &reply); } // start preview mode, must call setPreviewDisplay first @@ -90,6 +94,16 @@ public: return reply.readInt32(); } + // start recording mode, must call setPreviewDisplay first + status_t startRecording() + { + LOGV("startRecording"); + Parcel data, reply; + data.writeInterfaceToken(ICamera::getInterfaceDescriptor()); + remote()->transact(START_RECORDING, data, &reply); + return reply.readInt32(); + } + // stop preview mode void stopPreview() { @@ -99,6 +113,24 @@ public: remote()->transact(STOP_PREVIEW, data, &reply); } + // stop recording mode + void stopRecording() + { + LOGV("stopRecording"); + Parcel data, reply; + data.writeInterfaceToken(ICamera::getInterfaceDescriptor()); + remote()->transact(STOP_RECORDING, data, &reply); + } + + void releaseRecordingFrame(const sp<IMemory>& mem) + { + LOGV("releaseRecordingFrame"); + Parcel data, reply; + data.writeInterfaceToken(ICamera::getInterfaceDescriptor()); + data.writeStrongBinder(mem->asBinder()); + remote()->transact(RELEASE_RECORDING_FRAME, data, &reply); + } + // check preview state bool previewEnabled() { @@ -109,6 +141,16 @@ public: return reply.readInt32(); } + // check recording state + bool recordingEnabled() + { + LOGV("recordingEnabled"); + Parcel data, reply; + data.writeInterfaceToken(ICamera::getInterfaceDescriptor()); + remote()->transact(RECORDING_ENABLED, data, &reply); + return reply.readInt32(); + } + // auto focus status_t autoFocus() { @@ -202,11 +244,11 @@ status_t BnCamera::onTransact( reply->writeInt32(setPreviewDisplay(surface)); return NO_ERROR; } break; - case SET_FRAME_CALLBACK_FLAG: { - LOGV("SET_FRAME_CALLBACK_TYPE"); + case SET_PREVIEW_CALLBACK_FLAG: { + LOGV("SET_PREVIEW_CALLBACK_TYPE"); CHECK_INTERFACE(ICamera, data, reply); - int frame_callback_flag = data.readInt32(); - setFrameCallbackFlag(frame_callback_flag); + int callback_flag = data.readInt32(); + setPreviewCallbackFlag(callback_flag); return NO_ERROR; } break; case START_PREVIEW: { @@ -215,18 +257,43 @@ status_t BnCamera::onTransact( reply->writeInt32(startPreview()); return NO_ERROR; } break; + case START_RECORDING: { + LOGV("START_RECORDING"); + CHECK_INTERFACE(ICamera, data, reply); + reply->writeInt32(startRecording()); + return NO_ERROR; + } break; case STOP_PREVIEW: { LOGV("STOP_PREVIEW"); CHECK_INTERFACE(ICamera, data, reply); stopPreview(); return NO_ERROR; } break; + case STOP_RECORDING: { + LOGV("STOP_RECORDING"); + CHECK_INTERFACE(ICamera, data, reply); + stopRecording(); + return NO_ERROR; + } break; + case RELEASE_RECORDING_FRAME: { + LOGV("RELEASE_RECORDING_FRAME"); + CHECK_INTERFACE(ICamera, data, reply); + sp<IMemory> mem = interface_cast<IMemory>(data.readStrongBinder()); + releaseRecordingFrame(mem); + return NO_ERROR; + } break; case PREVIEW_ENABLED: { LOGV("PREVIEW_ENABLED"); CHECK_INTERFACE(ICamera, data, reply); reply->writeInt32(previewEnabled()); return NO_ERROR; } break; + case RECORDING_ENABLED: { + LOGV("RECORDING_ENABLED"); + CHECK_INTERFACE(ICamera, data, reply); + reply->writeInt32(recordingEnabled()); + return NO_ERROR; + } break; case AUTO_FOCUS: { LOGV("AUTO_FOCUS"); CHECK_INTERFACE(ICamera, data, reply); diff --git a/libs/ui/ICameraClient.cpp b/libs/ui/ICameraClient.cpp index c5d6d52..4bec9d2 100644 --- a/libs/ui/ICameraClient.cpp +++ b/libs/ui/ICameraClient.cpp @@ -28,9 +28,10 @@ enum { SHUTTER_CALLBACK = IBinder::FIRST_CALL_TRANSACTION, RAW_CALLBACK, JPEG_CALLBACK, - FRAME_CALLBACK, + PREVIEW_CALLBACK, ERROR_CALLBACK, - AUTOFOCUS_CALLBACK + AUTOFOCUS_CALLBACK, + RECORDING_CALLBACK, }; class BpCameraClient: public BpInterface<ICameraClient> @@ -70,14 +71,24 @@ public: remote()->transact(JPEG_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY); } - // callback from camera service to app with video frame data - void frameCallback(const sp<IMemory>& frame) + // callback from camera service to app with preview frame data + void previewCallback(const sp<IMemory>& frame) { - LOGV("frameCallback"); + LOGV("previewCallback"); Parcel data, reply; data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor()); data.writeStrongBinder(frame->asBinder()); - remote()->transact(FRAME_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY); + remote()->transact(PREVIEW_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY); + } + + // callback from camera service to app with recording frame data + void recordingCallback(const sp<IMemory>& frame) + { + LOGV("recordingCallback"); + Parcel data, reply; + data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor()); + data.writeStrongBinder(frame->asBinder()); + remote()->transact(RECORDING_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY); } // callback from camera service to app to report error @@ -135,11 +146,18 @@ status_t BnCameraClient::onTransact( jpegCallback(picture); return NO_ERROR; } break; - case FRAME_CALLBACK: { - LOGV("FRAME_CALLBACK"); + case PREVIEW_CALLBACK: { + LOGV("PREVIEW_CALLBACK"); + CHECK_INTERFACE(ICameraClient, data, reply); + sp<IMemory> frame = interface_cast<IMemory>(data.readStrongBinder()); + previewCallback(frame); + return NO_ERROR; + } break; + case RECORDING_CALLBACK: { + LOGV("RECORDING_CALLBACK"); CHECK_INTERFACE(ICameraClient, data, reply); sp<IMemory> frame = interface_cast<IMemory>(data.readStrongBinder()); - frameCallback(frame); + recordingCallback(frame); return NO_ERROR; } break; case ERROR_CALLBACK: { diff --git a/libs/ui/ISurface.cpp b/libs/ui/ISurface.cpp index 6f3cd47..abd3634 100644 --- a/libs/ui/ISurface.cpp +++ b/libs/ui/ISurface.cpp @@ -27,12 +27,33 @@ namespace android { -enum { - REGISTER_BUFFERS = IBinder::FIRST_CALL_TRANSACTION, - UNREGISTER_BUFFERS, - POST_BUFFER, // one-way transaction - CREATE_OVERLAY, -}; +ISurface::BufferHeap::BufferHeap() + : w(0), h(0), hor_stride(0), ver_stride(0), format(0), + transform(0), flags(0) +{ +} + +ISurface::BufferHeap::BufferHeap(uint32_t w, uint32_t h, + int32_t hor_stride, int32_t ver_stride, + PixelFormat format, const sp<IMemoryHeap>& heap) + : w(w), h(h), hor_stride(hor_stride), ver_stride(ver_stride), + format(format), heap(heap) +{ +} + +ISurface::BufferHeap::BufferHeap(uint32_t w, uint32_t h, + int32_t hor_stride, int32_t ver_stride, + PixelFormat format, uint32_t transform, uint32_t flags, + const sp<IMemoryHeap>& heap) + : w(w), h(h), hor_stride(hor_stride), ver_stride(ver_stride), + format(format), transform(transform), flags(flags), heap(heap) +{ +} + + +ISurface::BufferHeap::~BufferHeap() +{ +} class BpSurface : public BpInterface<ISurface> { @@ -42,17 +63,18 @@ public: { } - virtual status_t registerBuffers(int w, int h, int hstride, int vstride, - PixelFormat format, const sp<IMemoryHeap>& heap) + virtual status_t registerBuffers(const BufferHeap& buffers) { Parcel data, reply; data.writeInterfaceToken(ISurface::getInterfaceDescriptor()); - data.writeInt32(w); - data.writeInt32(h); - data.writeInt32(hstride); - data.writeInt32(vstride); - data.writeInt32(format); - data.writeStrongBinder(heap->asBinder()); + data.writeInt32(buffers.w); + data.writeInt32(buffers.h); + data.writeInt32(buffers.hor_stride); + data.writeInt32(buffers.ver_stride); + data.writeInt32(buffers.format); + data.writeInt32(buffers.transform); + data.writeInt32(buffers.flags); + data.writeStrongBinder(buffers.heap->asBinder()); remote()->transact(REGISTER_BUFFERS, data, &reply); status_t result = reply.readInt32(); return result; @@ -102,13 +124,16 @@ status_t BnSurface::onTransact( switch(code) { case REGISTER_BUFFERS: { CHECK_INTERFACE(ISurface, data, reply); - int w = data.readInt32(); - int h = data.readInt32(); - int hs= data.readInt32(); - int vs= data.readInt32(); - PixelFormat f = data.readInt32(); - sp<IMemoryHeap> heap(interface_cast<IMemoryHeap>(data.readStrongBinder())); - status_t err = registerBuffers(w,h,hs,vs,f,heap); + BufferHeap buffer; + buffer.w = data.readInt32(); + buffer.h = data.readInt32(); + buffer.hor_stride = data.readInt32(); + buffer.ver_stride= data.readInt32(); + buffer.format = data.readInt32(); + buffer.transform = data.readInt32(); + buffer.flags = data.readInt32(); + buffer.heap = interface_cast<IMemoryHeap>(data.readStrongBinder()); + status_t err = registerBuffers(buffer); reply->writeInt32(err); return NO_ERROR; } break; diff --git a/libs/ui/Overlay.cpp b/libs/ui/Overlay.cpp index c8e6168..b236edc 100644 --- a/libs/ui/Overlay.cpp +++ b/libs/ui/Overlay.cpp @@ -59,6 +59,12 @@ status_t Overlay::queueBuffer(overlay_buffer_t buffer) return mOverlayData->queueBuffer(mOverlayData, buffer); } +int32_t Overlay::getBufferCount() const +{ + if (mStatus != NO_ERROR) return mStatus; + return mOverlayData->getBufferCount(mOverlayData); +} + void* Overlay::getBufferAddress(overlay_buffer_t buffer) { if (mStatus != NO_ERROR) return NULL; diff --git a/libs/ui/PixelFormat.cpp b/libs/ui/PixelFormat.cpp index 605c8ae..b65ed97 100644 --- a/libs/ui/PixelFormat.cpp +++ b/libs/ui/PixelFormat.cpp @@ -19,6 +19,18 @@ namespace android { +size_t PixelFormatInfo::getScanlineSize(unsigned int width) const +{ + size_t size; + if ((components >= 6) && (components <= 8)) { + // YCbCr formats are differents. + size = (width * bitsPerPixel)>>3; + } else { + size = width * bytesPerPixel; + } + return size; +} + ssize_t bytesPerPixel(PixelFormat format) { PixelFormatInfo info; @@ -47,7 +59,25 @@ status_t getPixelFormatInfo(PixelFormat format, PixelFormatInfo* info) if (!valid) { return BAD_INDEX; } - + + #define COMPONENT(name) \ + case GGL_##name: info->components = PixelFormatInfo::name; break; + + switch (i->components) { + COMPONENT(ALPHA) + COMPONENT(RGB) + COMPONENT(RGBA) + COMPONENT(LUMINANCE) + COMPONENT(LUMINANCE_ALPHA) + COMPONENT(Y_CB_CR_SP) + COMPONENT(Y_CB_CR_P) + COMPONENT(Y_CB_CR_I) + default: + return BAD_INDEX; + } + + #undef COMPONENT + info->format = format; info->bytesPerPixel = i->size; info->bitsPerPixel = i->bitsPerPixel; @@ -59,6 +89,7 @@ status_t getPixelFormatInfo(PixelFormat format, PixelFormatInfo* info) info->l_green = i->gl; info->h_blue = i->bh; info->l_blue = i->bl; + return NO_ERROR; } diff --git a/libs/utils/Parcel.cpp b/libs/utils/Parcel.cpp index 0eba0b0..0f4b647 100644 --- a/libs/utils/Parcel.cpp +++ b/libs/utils/Parcel.cpp @@ -658,15 +658,20 @@ status_t Parcel::writeNativeHandle(const native_handle& handle) status_t err; err = writeInt32(handle.numFds); if (err != NO_ERROR) return err; - + err = writeInt32(handle.numInts); if (err != NO_ERROR) return err; - + for (int i=0 ; err==NO_ERROR && i<handle.numFds ; i++) err = writeDupFileDescriptor(handle.data[i]); - + + if (err != NO_ERROR) { + LOGD("write native handle, write dup fd failed"); + return err; + } + err = write(handle.data + handle.numFds, sizeof(int)*handle.numInts); - + return err; } @@ -947,7 +952,7 @@ native_handle* Parcel::readNativeHandle(native_handle* (*alloc)(void*, int, int) } for (int i=0 ; err==NO_ERROR && i<numFds ; i++) { - h->data[i] = readFileDescriptor(); + h->data[i] = dup(readFileDescriptor()); if (h->data[i] < 0) err = BAD_VALUE; } diff --git a/libs/utils/ResourceTypes.cpp b/libs/utils/ResourceTypes.cpp index 5a09fb4..71e7cd7 100644 --- a/libs/utils/ResourceTypes.cpp +++ b/libs/utils/ResourceTypes.cpp @@ -1736,7 +1736,7 @@ bool ResTable::getResourceName(uint32_t resID, resource_name* outName) const } ssize_t ResTable::getResource(uint32_t resID, Res_value* outValue, bool mayBeBag, - uint32_t* outSpecFlags) const + uint32_t* outSpecFlags, ResTable_config* outConfig) const { if (mError != NO_ERROR) { return mError; @@ -1809,7 +1809,7 @@ ssize_t ResTable::getResource(uint32_t resID, Res_value* outValue, bool mayBeBag (const Res_value*)(((const uint8_t*)type) + offset); ResTable_config thisConfig; thisConfig.copyFromDtoH(type->config); - + if (outSpecFlags != NULL) { if (typeClass->typeSpecFlags != NULL) { *outSpecFlags |= dtohl(typeClass->typeSpecFlags[e]); @@ -1834,6 +1834,9 @@ ssize_t ResTable::getResource(uint32_t resID, Res_value* outValue, bool mayBeBag outValue->res0 = bestValue->res0; outValue->dataType = bestValue->dataType; outValue->data = dtohl(bestValue->data); + if (outConfig != NULL) { + *outConfig = bestItem; + } TABLE_NOISY(size_t len; printf("Found value: pkg=%d, type=%d, str=%s, int=%d\n", bestPackage->header->index, @@ -3484,7 +3487,7 @@ ssize_t ResTable::getEntry( ResTable_config thisConfig; thisConfig.copyFromDtoH(thisType->config); - + TABLE_GETENTRY(LOGI("Match entry 0x%x in type 0x%x (sz 0x%x): imsi:%d/%d=%d/%d lang:%c%c=%c%c cnt:%c%c=%c%c " "orien:%d=%d touch:%d=%d density:%d=%d key:%d=%d inp:%d=%d nav:%d=%d w:%d=%d h:%d=%d\n", entryIndex, typeIndex+1, dtohl(thisType->config.size), diff --git a/libs/utils/String8.cpp b/libs/utils/String8.cpp index ab843f6..c50d343 100644 --- a/libs/utils/String8.cpp +++ b/libs/utils/String8.cpp @@ -317,8 +317,10 @@ status_t String8::real_append(const char* other, size_t otherLen) ->editResize(myLen+otherLen+1); if (buf) { char* str = (char*)buf->data(); - memcpy(str+myLen, other, otherLen+1); mString = str; + str += myLen; + memcpy(str, other, otherLen); + str[otherLen] = '\0'; return NO_ERROR; } return NO_MEMORY; |