diff options
Diffstat (limited to 'libs/surfaceflinger')
21 files changed, 935 insertions, 253 deletions
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 5e14dc85..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..73676859 --- /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" |