diff options
Diffstat (limited to 'libs/surfaceflinger')
36 files changed, 2176 insertions, 1772 deletions
diff --git a/libs/surfaceflinger/Android.mk b/libs/surfaceflinger/Android.mk index a5698f2..16936e3 100644 --- a/libs/surfaceflinger/Android.mk +++ b/libs/surfaceflinger/Android.mk @@ -5,23 +5,21 @@ LOCAL_SRC_FILES:= \ clz.cpp.arm \ DisplayHardware/DisplayHardware.cpp \ DisplayHardware/DisplayHardwareBase.cpp \ - GPUHardware/GPUHardware.cpp \ BlurFilter.cpp.arm \ - CPUGauge.cpp \ + BufferAllocator.cpp \ Layer.cpp \ LayerBase.cpp \ LayerBuffer.cpp \ LayerBlur.cpp \ LayerBitmap.cpp \ LayerDim.cpp \ - LayerOrientationAnim.cpp \ - LayerOrientationAnimRotate.cpp \ - OrientationAnimation.cpp \ + MessageQueue.cpp \ SurfaceFlinger.cpp \ Tokenizer.cpp \ - Transform.cpp \ - VRamHeap.cpp + Transform.cpp +LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\" +LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES # need "-lrt" on Linux simulator to pick up clock_gettime ifeq ($(TARGET_SIMULATOR),true) diff --git a/libs/surfaceflinger/BufferAllocator.cpp b/libs/surfaceflinger/BufferAllocator.cpp new file mode 100644 index 0000000..cee8b64 --- /dev/null +++ b/libs/surfaceflinger/BufferAllocator.cpp @@ -0,0 +1,118 @@ +/* +** +** Copyright 2009, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#include <sys/mman.h> +#include <cutils/ashmem.h> +#include <cutils/log.h> + +#include <utils/Singleton.h> +#include <utils/String8.h> + +#include "BufferAllocator.h" + + +namespace android { +// --------------------------------------------------------------------------- + +ANDROID_SINGLETON_STATIC_INSTANCE( BufferAllocator ) + +Mutex BufferAllocator::sLock; +KeyedVector<buffer_handle_t, BufferAllocator::alloc_rec_t> BufferAllocator::sAllocList; + +BufferAllocator::BufferAllocator() + : mAllocDev(0) +{ + hw_module_t const* module; + int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module); + LOGE_IF(err, "FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID); + if (err == 0) { + gralloc_open(module, &mAllocDev); + } +} + +BufferAllocator::~BufferAllocator() +{ + gralloc_close(mAllocDev); +} + +void BufferAllocator::dump(String8& result) const +{ + Mutex::Autolock _l(sLock); + KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList); + size_t total = 0; + const size_t SIZE = 512; + char buffer[SIZE]; + snprintf(buffer, SIZE, "Allocated buffers:\n"); + result.append(buffer); + const size_t c = list.size(); + for (size_t i=0 ; i<c ; i++) { + const alloc_rec_t& rec(list.valueAt(i)); + snprintf(buffer, SIZE, "%10p: %7.2f KiB | %4u x %4u | %2d | 0x%08x\n", + list.keyAt(i), rec.size/1024.0f, + rec.w, rec.h, rec.format, rec.usage); + result.append(buffer); + total += rec.size; + } + snprintf(buffer, SIZE, "Total allocated: %.2f KB\n", total/1024.0f); + result.append(buffer); +} + +status_t BufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat format, + int usage, buffer_handle_t* handle, int32_t* stride) +{ + Mutex::Autolock _l(mLock); + + // we have a h/w allocator and h/w buffer is requested + status_t err = mAllocDev->alloc(mAllocDev, + w, h, format, usage, handle, stride); + LOGW_IF(err, "alloc(%u, %u, %d, %08x, ...) failed %d (%s)", + w, h, format, usage, err, strerror(-err)); + + if (err == NO_ERROR) { + Mutex::Autolock _l(sLock); + KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList); + alloc_rec_t rec; + rec.w = w; + rec.h = h; + rec.format = format; + rec.usage = usage; + rec.vaddr = 0; + rec.size = h * stride[0] * bytesPerPixel(format); + list.add(*handle, rec); + } + + return err; +} + +status_t BufferAllocator::free(buffer_handle_t handle) +{ + Mutex::Autolock _l(mLock); + + status_t err = mAllocDev->free(mAllocDev, handle); + LOGW_IF(err, "free(...) failed %d (%s)", err, strerror(-err)); + + if (err == NO_ERROR) { + Mutex::Autolock _l(sLock); + KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList); + list.removeItem(handle); + } + + return err; +} + +// --------------------------------------------------------------------------- +}; // namespace android diff --git a/libs/surfaceflinger/BufferAllocator.h b/libs/surfaceflinger/BufferAllocator.h new file mode 100644 index 0000000..a279ded --- /dev/null +++ b/libs/surfaceflinger/BufferAllocator.h @@ -0,0 +1,96 @@ +/* +** +** Copyright 2009, 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_BUFFER_ALLOCATOR_H +#define ANDROID_BUFFER_ALLOCATOR_H + +#include <stdint.h> + +#include <cutils/native_handle.h> + +#include <utils/Errors.h> +#include <utils/KeyedVector.h> +#include <utils/threads.h> +#include <utils/Singleton.h> + +#include <ui/PixelFormat.h> + +#include <hardware/gralloc.h> + + +namespace android { +// --------------------------------------------------------------------------- + +class String8; + +class BufferAllocator : public Singleton<BufferAllocator> +{ +public: + enum { + USAGE_SW_READ_NEVER = GRALLOC_USAGE_SW_READ_NEVER, + USAGE_SW_READ_RARELY = GRALLOC_USAGE_SW_READ_RARELY, + USAGE_SW_READ_OFTEN = GRALLOC_USAGE_SW_READ_OFTEN, + USAGE_SW_READ_MASK = GRALLOC_USAGE_SW_READ_MASK, + + USAGE_SW_WRITE_NEVER = GRALLOC_USAGE_SW_WRITE_NEVER, + USAGE_SW_WRITE_RARELY = GRALLOC_USAGE_SW_WRITE_RARELY, + USAGE_SW_WRITE_OFTEN = GRALLOC_USAGE_SW_WRITE_OFTEN, + USAGE_SW_WRITE_MASK = GRALLOC_USAGE_SW_WRITE_MASK, + + USAGE_SOFTWARE_MASK = USAGE_SW_READ_MASK|USAGE_SW_WRITE_MASK, + + USAGE_HW_TEXTURE = GRALLOC_USAGE_HW_TEXTURE, + USAGE_HW_RENDER = GRALLOC_USAGE_HW_RENDER, + USAGE_HW_2D = GRALLOC_USAGE_HW_2D, + USAGE_HW_MASK = GRALLOC_USAGE_HW_MASK + }; + + static inline BufferAllocator& get() { return getInstance(); } + + + status_t alloc(uint32_t w, uint32_t h, PixelFormat format, int usage, + buffer_handle_t* handle, int32_t* stride); + + status_t free(buffer_handle_t handle); + + void dump(String8& res) const; + +private: + struct alloc_rec_t { + uint32_t w; + uint32_t h; + PixelFormat format; + uint32_t usage; + void* vaddr; + size_t size; + }; + + static Mutex sLock; + static KeyedVector<buffer_handle_t, alloc_rec_t> sAllocList; + + friend class Singleton<BufferAllocator>; + BufferAllocator(); + ~BufferAllocator(); + + mutable Mutex mLock; + alloc_device_t *mAllocDev; +}; + +// --------------------------------------------------------------------------- +}; // namespace android + +#endif // ANDROID_BUFFER_ALLOCATOR_H diff --git a/libs/surfaceflinger/CPUGauge.cpp b/libs/surfaceflinger/CPUGauge.cpp deleted file mode 100644 index 74a9270..0000000 --- a/libs/surfaceflinger/CPUGauge.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/* - * 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 "CPUGauge" - -#include <stdint.h> -#include <limits.h> -#include <sys/types.h> -#include <math.h> - -#include <utils/threads.h> -#include <utils/Errors.h> -#include <utils/Log.h> - -#include <ui/PixelFormat.h> -#include <ui/Rect.h> -#include <ui/Region.h> -#include <ui/DisplayInfo.h> -#include <ui/ISurfaceComposer.h> -#include <ui/ISurfaceFlingerClient.h> - -#include <pixelflinger/pixelflinger.h> - -#include "CPUGauge.h" - -namespace android { - -CPUGauge::CPUGauge( const sp<ISurfaceComposer>& composer, - nsecs_t interval, - int clock, - int refclock) - : Thread(false), - mInterval(interval), mClock(clock), mRefClock(refclock), - mReferenceTime(0), - mReferenceWorkingTime(0), mCpuUsage(0), - mRefIdleTime(0), mIdleTime(0) -{ - mFd = fopen("/proc/stat", "r"); - setvbuf(mFd, NULL, _IONBF, 0); - - mSession = SurfaceComposerClient::clientForConnection( - composer->createConnection()->asBinder()); -} - -CPUGauge::~CPUGauge() -{ - fclose(mFd); -} - -const sp<SurfaceComposerClient>& CPUGauge::session() const -{ - return mSession; -} - -void CPUGauge::onFirstRef() -{ - run("CPU Gauge"); -} - -status_t CPUGauge::readyToRun() -{ - LOGI("Starting CPU gauge..."); - return NO_ERROR; -} - -bool CPUGauge::threadLoop() -{ - DisplayInfo dinfo; - session()->getDisplayInfo(0, &dinfo); - sp<Surface> s(session()->createSurface(getpid(), 0, dinfo.w, 4, PIXEL_FORMAT_OPAQUE)); - session()->openTransaction(); - s->setLayer(INT_MAX); - session()->closeTransaction(); - - static const GGLfixed colors[4][4] = { - { 0x00000, 0x10000, 0x00000, 0x10000 }, - { 0x10000, 0x10000, 0x00000, 0x10000 }, - { 0x10000, 0x00000, 0x00000, 0x10000 }, - { 0x00000, 0x00000, 0x00000, 0x10000 }, - }; - - GGLContext* gl; - gglInit(&gl); - gl->activeTexture(gl, 0); - gl->disable(gl, GGL_TEXTURE_2D); - gl->disable(gl, GGL_BLEND); - - const int w = dinfo.w; - - while(!exitPending()) - { - mLock.lock(); - const float cpuUsage = this->cpuUsage(); - const float totalCpuUsage = 1.0f - idle(); - mLock.unlock(); - - Surface::SurfaceInfo info; - s->lock(&info); - GGLSurface fb; - fb.version = sizeof(GGLSurface); - fb.width = info.w; - fb.height = info.h; - fb.stride = info.w; - fb.format = info.format; - fb.data = (GGLubyte*)info.bits; - - gl->colorBuffer(gl, &fb); - gl->color4xv(gl, colors[3]); - gl->recti(gl, 0, 0, w, 4); - gl->color4xv(gl, colors[2]); // red - gl->recti(gl, 0, 0, int(totalCpuUsage*w), 2); - gl->color4xv(gl, colors[0]); // green - gl->recti(gl, 0, 2, int(cpuUsage*w), 4); - - s->unlockAndPost(); - - usleep(ns2us(mInterval)); - } - - gglUninit(gl); - return false; -} - -void CPUGauge::sample() -{ - if (mLock.tryLock() == NO_ERROR) { - const nsecs_t now = systemTime(mRefClock); - const nsecs_t referenceTime = now-mReferenceTime; - if (referenceTime >= mInterval) { - const float reftime = 1.0f / referenceTime; - const nsecs_t nowWorkingTime = systemTime(mClock); - - char buf[256]; - fgets(buf, 256, mFd); - rewind(mFd); - char *str = buf+5; - char const * const usermode = strsep(&str, " "); (void)usermode; - char const * const usernice = strsep(&str, " "); (void)usernice; - char const * const systemmode = strsep(&str, " ");(void)systemmode; - char const * const idle = strsep(&str, " "); - const nsecs_t nowIdleTime = atoi(idle) * 10000000LL; - mIdleTime = float(nowIdleTime - mRefIdleTime) * reftime; - mRefIdleTime = nowIdleTime; - - const nsecs_t workingTime = nowWorkingTime - mReferenceWorkingTime; - const float newCpuUsage = float(workingTime) * reftime; - if (mCpuUsage != newCpuUsage) { - mCpuUsage = newCpuUsage; - mReferenceWorkingTime = nowWorkingTime; - mReferenceTime = now; - } - } - mLock.unlock(); - } -} - - -}; // namespace android diff --git a/libs/surfaceflinger/CPUGauge.h b/libs/surfaceflinger/CPUGauge.h deleted file mode 100644 index 5bb53c0..0000000 --- a/libs/surfaceflinger/CPUGauge.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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_CPUGAUGE_H -#define ANDROID_CPUGAUGE_H - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <stdint.h> -#include <sys/types.h> - -#include <utils/Timers.h> - -#include <ui/SurfaceComposerClient.h> - -namespace android { - -class CPUGauge : public Thread -{ -public: - CPUGauge( const sp<ISurfaceComposer>& composer, - nsecs_t interval=s2ns(1), - int clock=SYSTEM_TIME_THREAD, - int refclock=SYSTEM_TIME_MONOTONIC); - - ~CPUGauge(); - - const sp<SurfaceComposerClient>& session() const; - - void sample(); - - inline float cpuUsage() const { return mCpuUsage; } - inline float idle() const { return mIdleTime; } - -private: - virtual void onFirstRef(); - virtual status_t readyToRun(); - virtual bool threadLoop(); - - Mutex mLock; - - sp<SurfaceComposerClient> mSession; - - const nsecs_t mInterval; - const int mClock; - const int mRefClock; - - nsecs_t mReferenceTime; - nsecs_t mReferenceWorkingTime; - float mCpuUsage; - nsecs_t mRefIdleTime; - float mIdleTime; - FILE* mFd; -}; - - -}; // namespace android - -#endif // ANDROID_CPUGAUGE_H diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp index f14d7e9..25e351c 100644 --- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp +++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp @@ -14,8 +14,6 @@ * limitations under the License. */ -#define LOG_TAG "SurfaceFlinger" - #include <stdlib.h> #include <stdio.h> #include <string.h> @@ -23,18 +21,23 @@ #include <cutils/properties.h> +#include <utils/RefBase.h> #include <utils/Log.h> -#include <ui/EGLDisplaySurface.h> +#include <ui/PixelFormat.h> +#include <ui/FramebufferNativeWindow.h> #include <GLES/gl.h> +#include <EGL/egl.h> #include <EGL/eglext.h> +#include <pixelflinger/pixelflinger.h> #include "DisplayHardware/DisplayHardware.h" #include <hardware/copybit.h> #include <hardware/overlay.h> +#include <hardware/gralloc.h> using namespace android; @@ -108,17 +111,28 @@ PixelFormat DisplayHardware::getFormat() const { return mFormat; } void DisplayHardware::init(uint32_t dpy) { + hw_module_t const* module; + + mNativeWindow = new FramebufferNativeWindow(); + + mOverlayEngine = NULL; + if (hw_get_module(OVERLAY_HARDWARE_MODULE_ID, &module) == 0) { + overlay_control_open(module, &mOverlayEngine); + } + + framebuffer_device_t const * fbDev = mNativeWindow->getDevice(); + + PixelFormatInfo fbFormatInfo; + getPixelFormatInfo(PixelFormat(fbDev->format), &fbFormatInfo); + // initialize EGL const EGLint attribs[] = { - EGL_RED_SIZE, 5, - EGL_GREEN_SIZE, 6, - EGL_BLUE_SIZE, 5, + EGL_BUFFER_SIZE, fbFormatInfo.bitsPerPixel, EGL_DEPTH_SIZE, 0, EGL_NONE }; EGLint w, h, dummy; - EGLint numConfigs, n; - EGLConfig config; + EGLint numConfigs=0, n=0; EGLSurface surface; EGLContext context; mFlags = 0; @@ -129,7 +143,31 @@ void DisplayHardware::init(uint32_t dpy) EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); eglInitialize(display, NULL, NULL); eglGetConfigs(display, NULL, 0, &numConfigs); - eglChooseConfig(display, attribs, &config, 1, &n); + + // Get all the "potential match" configs... + EGLConfig* const configs = new EGLConfig[numConfigs]; + eglChooseConfig(display, attribs, configs, numConfigs, &n); + LOGE_IF(n<=0, "no EGLConfig available!"); + EGLConfig config = configs[0]; + if (n > 1) { + // if there is more than one candidate, go through the list + // and pick one that matches our framebuffer format + int fbSzA = fbFormatInfo.getSize(PixelFormatInfo::INDEX_ALPHA); + int fbSzR = fbFormatInfo.getSize(PixelFormatInfo::INDEX_RED); + int fbSzG = fbFormatInfo.getSize(PixelFormatInfo::INDEX_GREEN); + int fbSzB = fbFormatInfo.getSize(PixelFormatInfo::INDEX_BLUE); + for (int i=0 ; i<n ; i++) { + EGLint r,g,b,a; + eglGetConfigAttrib(display, configs[i], EGL_RED_SIZE, &r); + eglGetConfigAttrib(display, configs[i], EGL_GREEN_SIZE, &g); + eglGetConfigAttrib(display, configs[i], EGL_BLUE_SIZE, &b); + eglGetConfigAttrib(display, configs[i], EGL_ALPHA_SIZE, &a); + if (fbSzA == a && fbSzR == r && fbSzG == g && fbSzB == b) { + config = configs[i]; + } + } + } + delete [] configs; /* * Gather EGL extensions @@ -145,12 +183,11 @@ void DisplayHardware::init(uint32_t dpy) LOGI("extensions: %s", egl_extensions); LOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported"); - // 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 (mNativeWindow->isUpdateOnDemand()) { + mFlags |= UPDATE_ON_DEMAND; + } + if (eglGetConfigAttrib(display, config, EGL_CONFIG_CAVEAT, &dummy) == EGL_TRUE) { if (dummy == EGL_SLOW_CONFIG) mFlags |= SLOW_CONFIG; @@ -160,33 +197,22 @@ void DisplayHardware::init(uint32_t dpy) * Create our main surface */ - mDisplaySurface = new EGLDisplaySurface(); - - surface = eglCreateWindowSurface(display, config, mDisplaySurface.get(), NULL); - //checkEGLErrors("eglCreateDisplaySurfaceANDROID"); + surface = eglCreateWindowSurface(display, config, mNativeWindow.get(), NULL); + checkEGLErrors("eglCreateDisplaySurfaceANDROID"); if (eglQuerySurface(display, surface, EGL_SWAP_BEHAVIOR, &dummy) == EGL_TRUE) { if (dummy == EGL_BUFFER_PRESERVED) { mFlags |= BUFFER_PRESERVED; } } - - GLint value = EGL_UNKNOWN; - eglQuerySurface(display, surface, EGL_HORIZONTAL_RESOLUTION, &value); - if (value == EGL_UNKNOWN) { - mDpiX = 160.0f; - } else { - mDpiX = 25.4f * float(value)/EGL_DISPLAY_SCALING; - } - value = EGL_UNKNOWN; - eglQuerySurface(display, surface, EGL_VERTICAL_RESOLUTION, &value); - if (value == EGL_UNKNOWN) { - mDpiY = 160.0f; - } else { - mDpiY = 25.4f * float(value)/EGL_DISPLAY_SCALING; + + if (strstr(egl_extensions, "EGL_ANDROID_swap_rectangle")) { + mFlags |= SWAP_RECTANGLE; } - mRefreshRate = 60.f; // TODO: get the real refresh rate - + + mDpiX = mNativeWindow->xdpi; + mDpiX = mNativeWindow->ydpi; + mRefreshRate = fbDev->fps; char property[PROPERTY_VALUE_MAX]; if (property_get("ro.sf.lcd_density", property, NULL) <= 0) { @@ -225,7 +251,10 @@ void DisplayHardware::init(uint32_t dpy) if (strstr(gl_extensions, "GL_OES_draw_texture")) { mFlags |= DRAW_TEXTURE_EXTENSION; } - if (strstr(gl_extensions, "GL_ANDROID_direct_texture")) { + if (strstr( gl_extensions, "GL_OES_EGL_image") && + (strstr(egl_extensions, "EGL_KHR_image_base") || + strstr(egl_extensions, "EGL_KHR_image")) && + strstr(egl_extensions, "EGL_ANDROID_image_native_buffer")) { mFlags |= DIRECT_TEXTURE; } @@ -236,19 +265,8 @@ void DisplayHardware::init(uint32_t dpy) mConfig = config; mSurface = surface; mContext = context; - mFormat = GGL_PIXEL_FORMAT_RGB_565; - - hw_module_t const* module; - - mBlitEngine = NULL; - if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) { - copybit_open(module, &mBlitEngine); - } - - mOverlayEngine = NULL; - if (hw_get_module(OVERLAY_HARDWARE_MODULE_ID, &module) == 0) { - overlay_control_open(module, &mOverlayEngine); - } + mFormat = fbDev->format; + mPageFlipCount = 0; } /* @@ -262,7 +280,6 @@ void DisplayHardware::fini() { eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglTerminate(mDisplay); - copybit_close(mBlitEngine); overlay_control_close(mOverlayEngine); } @@ -276,28 +293,8 @@ void DisplayHardware::acquireScreen() const DisplayHardwareBase::acquireScreen(); } -void DisplayHardware::getDisplaySurface(copybit_image_t* img) const -{ - img->w = mDisplaySurface->stride; - img->h = mDisplaySurface->height; - img->format = mDisplaySurface->format; - img->offset = mDisplaySurface->offset; - img->base = (void*)mDisplaySurface->base; - img->fd = mDisplaySurface->fd; -} - -void DisplayHardware::getDisplaySurface(GGLSurface* fb) const -{ - fb->version= sizeof(GGLSurface); - fb->width = mDisplaySurface->width; - fb->height = mDisplaySurface->height; - fb->stride = mDisplaySurface->stride; - fb->format = mDisplaySurface->format; - fb->data = (GGLubyte*)mDisplaySurface->base + mDisplaySurface->offset; -} - uint32_t DisplayHardware::getPageFlipCount() const { - return mDisplaySurface->getPageFlipCount(); + return mPageFlipCount; } /* @@ -311,21 +308,19 @@ void DisplayHardware::flip(const Region& dirty) const EGLDisplay dpy = mDisplay; EGLSurface surface = mSurface; - Region newDirty(dirty); - newDirty.andSelf(Rect(mWidth, mHeight)); - - if (mFlags & BUFFER_PRESERVED) { - const Region copyback(mDirty.subtract(newDirty)); - mDirty = newDirty; - mDisplaySurface->copyFrontToBack(copyback); - } - - if (mFlags & SWAP_RECTANGLE_EXTENSION) { + if (mFlags & SWAP_RECTANGLE) { + Region newDirty(dirty); + newDirty.andSelf(Rect(mWidth, mHeight)); const Rect& b(newDirty.bounds()); - mDisplaySurface->setSwapRectangle( + eglSetSwapRectangleANDROID(dpy, surface, b.left, b.top, b.width(), b.height()); - } + } + if (mFlags & UPDATE_ON_DEMAND) { + mNativeWindow->setUpdateRectangle(dirty.bounds()); + } + + mPageFlipCount++; eglSwapBuffers(dpy, surface); checkEGLErrors("eglSwapBuffers"); @@ -345,9 +340,9 @@ void DisplayHardware::makeCurrent() const } void DisplayHardware::copyFrontToImage(const copybit_image_t& front) const { - mDisplaySurface->copyFrontToImage(front); + // FIXME: we need to get rid of this } void DisplayHardware::copyBackToImage(const copybit_image_t& front) const { - mDisplaySurface->copyBackToImage(front); + // FIXME: we need to get rid of this } diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h index 550a4d1..c3dbff1 100644 --- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h +++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h @@ -22,31 +22,35 @@ #include <ui/PixelFormat.h> #include <ui/Region.h> +#include <GLES/gl.h> +#include <GLES/glext.h> #include <EGL/egl.h> +#include <EGL/eglext.h> + +#include <pixelflinger/pixelflinger.h> #include "DisplayHardware/DisplayHardwareBase.h" struct overlay_control_device_t; -struct copybit_device_t; +struct framebuffer_device_t; struct copybit_image_t; -struct copybit_t; namespace android { -class EGLDisplaySurface; +class FramebufferNativeWindow; class DisplayHardware : public DisplayHardwareBase { public: enum { DIRECT_TEXTURE = 0x00000002, - SWAP_RECTANGLE_EXTENSION= 0x00000004, COPY_BITS_EXTENSION = 0x00000008, NPOT_EXTENSION = 0x00000100, DRAW_TEXTURE_EXTENSION = 0x00000200, BUFFER_PRESERVED = 0x00010000, UPDATE_ON_DEMAND = 0x00020000, // video driver feature SLOW_CONFIG = 0x00040000, // software + SWAP_RECTANGLE = 0x00080000, }; DisplayHardware( @@ -73,10 +77,7 @@ public: void makeCurrent() const; uint32_t getPageFlipCount() const; - void getDisplaySurface(copybit_image_t* img) const; - void getDisplaySurface(GGLSurface* fb) const; EGLDisplay getEGLDisplay() const { return mDisplay; } - copybit_device_t* getBlitEngine() const { return mBlitEngine; } overlay_control_device_t* getOverlayEngine() const { return mOverlayEngine; } void copyFrontToImage(const copybit_image_t& front) const; @@ -102,9 +103,9 @@ private: int mHeight; PixelFormat mFormat; uint32_t mFlags; - mutable Region mDirty; - sp<EGLDisplaySurface> mDisplaySurface; - copybit_device_t* mBlitEngine; + mutable uint32_t mPageFlipCount; + + sp<FramebufferNativeWindow> mNativeWindow; overlay_control_device_t* mOverlayEngine; }; diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp index f75e5c2..1d09f84 100644 --- a/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp +++ b/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp @@ -14,8 +14,6 @@ * limitations under the License. */ -#define LOG_TAG "SurfaceFlinger" - #include <assert.h> #include <errno.h> #include <stdlib.h> diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp index 96395a8..5b260c4 100644 --- a/libs/surfaceflinger/Layer.cpp +++ b/libs/surfaceflinger/Layer.cpp @@ -14,26 +14,24 @@ * limitations under the License. */ -#define LOG_TAG "SurfaceFlinger" - #include <stdlib.h> #include <stdint.h> #include <sys/types.h> #include <cutils/properties.h> +#include <cutils/native_handle.h> #include <utils/Errors.h> #include <utils/Log.h> #include <utils/StopWatch.h> #include <ui/PixelFormat.h> -#include <ui/EGLDisplaySurface.h> +#include <ui/Surface.h> #include "clz.h" #include "Layer.h" #include "LayerBitmap.h" #include "SurfaceFlinger.h" -#include "VRamHeap.h" #include "DisplayHardware/DisplayHardware.h" @@ -54,8 +52,7 @@ Layer::Layer(SurfaceFlinger* flinger, DisplayID display, Client* c, int32_t i) mSecure(false), mFrontBufferIndex(1), mNeedsBlending(true), - mResizeTransactionDone(false), - mTextureName(-1U), mTextureWidth(0), mTextureHeight(0) + mResizeTransactionDone(false) { // no OpenGL operation is possible here, since we might not be // in the OpenGL thread. @@ -63,11 +60,22 @@ Layer::Layer(SurfaceFlinger* flinger, DisplayID display, Client* c, int32_t i) Layer::~Layer() { - client->free(clientIndex()); - // this should always be called from the OpenGL thread - if (mTextureName != -1U) { - //glDeleteTextures(1, &mTextureName); - deletedTextures.add(mTextureName); + destroy(); + // the actual buffers will be destroyed here +} + +void Layer::destroy() +{ + for (int i=0 ; i<NUM_BUFFERS ; i++) { + if (mTextures[i].name != -1U) { + glDeleteTextures(1, &mTextures[i].name); + mTextures[i].name = -1U; + } + if (mTextures[i].image != EGL_NO_IMAGE_KHR) { + EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay()); + eglDestroyImageKHR(dpy, mTextures[i].image); + mTextures[i].image = EGL_NO_IMAGE_KHR; + } } } @@ -79,11 +87,19 @@ void Layer::initStates(uint32_t w, uint32_t h, uint32_t flags) lcblk->flags |= eNoCopyBack; } -sp<LayerBaseClient::Surface> Layer::getSurface() const +sp<LayerBaseClient::Surface> Layer::createSurface() const { return mSurface; } +status_t Layer::ditch() +{ + // the layer is not on screen anymore. free as much resources as possible + mSurface.clear(); + destroy(); + return NO_ERROR; +} + status_t Layer::setBuffers( Client* client, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) @@ -92,71 +108,115 @@ status_t Layer::setBuffers( Client* client, status_t err = getPixelFormatInfo(format, &info); if (err) return err; - // TODO: if eHardware is explicitly requested, we should fail - // on systems where we can't allocate memory that can be used with - // DMA engines for instance. - - // FIXME: we always ask for hardware for now (this should come from copybit) - flags |= ISurfaceComposer::eHardware; + uint32_t bufferFlags = 0; + if (flags & ISurfaceComposer::eGPU) + bufferFlags |= Buffer::GPU; - const uint32_t memory_flags = flags & - (ISurfaceComposer::eGPU | - ISurfaceComposer::eHardware | - ISurfaceComposer::eSecure); - - // pixel-alignment. the final alignment may be bigger because - // we always force a 4-byte aligned bpr. - uint32_t alignment = 1; + if (flags & ISurfaceComposer::eSecure) + bufferFlags |= Buffer::SECURE; - if ((flags & ISurfaceComposer::eGPU) && (mFlinger->getGPU() != 0)) { - // FIXME: this value should come from the h/w - alignment = 8; + /* FIXME we need this code for msm7201A + if (bufferFlags & Buffer::GPU) { // FIXME: this is msm7201A specific, as its GPU only supports // BGRA_8888. if (format == PIXEL_FORMAT_RGBA_8888) { format = PIXEL_FORMAT_BGRA_8888; } } + */ - mSecure = (flags & ISurfaceComposer::eSecure) ? true : false; + mSecure = (bufferFlags & Buffer::SECURE) ? true : false; mNeedsBlending = (info.h_alpha - info.l_alpha) > 0; - sp<MemoryDealer> allocators[2]; for (int i=0 ; i<2 ; i++) { - allocators[i] = client->createAllocator(memory_flags); - if (allocators[i] == 0) - return NO_MEMORY; - mBuffers[i].init(allocators[i]); - int err = mBuffers[i].setBits(w, h, alignment, format, LayerBitmap::SECURE_BITS); - if (err != NO_ERROR) + err = mBuffers[i].init(lcblk->surface + i, w, h, format, bufferFlags); + if (err != NO_ERROR) { return err; - mBuffers[i].clear(); // clear the bits for security - mBuffers[i].getInfo(lcblk->surface + i); + } } - - mSurface = new Surface(clientIndex(), - allocators[0]->getMemoryHeap(), - allocators[1]->getMemoryHeap(), - mIdentity); - + mSurface = new SurfaceLayer(mFlinger, clientIndex(), this); return NO_ERROR; } void Layer::reloadTexture(const Region& dirty) { - if (UNLIKELY(mTextureName == -1U)) { - // create the texture name the first time - // can't do that in the ctor, because it runs in another thread. - mTextureName = createTexture(); + const sp<Buffer>& buffer(frontBuffer().getBuffer()); + if (LIKELY(mFlags & DisplayHardware::DIRECT_TEXTURE)) { + int index = mFrontBufferIndex; + if (LIKELY(!mTextures[index].dirty)) { + glBindTexture(GL_TEXTURE_2D, mTextures[index].name); + } else { + // we need to recreate the texture + EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay()); + + // create the new texture name if needed + if (UNLIKELY(mTextures[index].name == -1U)) { + mTextures[index].name = createTexture(); + } else { + glBindTexture(GL_TEXTURE_2D, mTextures[index].name); + } + + // free the previous image + if (mTextures[index].image != EGL_NO_IMAGE_KHR) { + eglDestroyImageKHR(dpy, mTextures[index].image); + mTextures[index].image = EGL_NO_IMAGE_KHR; + } + + // construct an EGL_NATIVE_BUFFER_ANDROID + android_native_buffer_t* clientBuf = buffer->getNativeBuffer(); + + // create the new EGLImageKHR + const EGLint attrs[] = { + EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, + EGL_NONE, EGL_NONE + }; + mTextures[index].image = eglCreateImageKHR( + dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, + (EGLClientBuffer)clientBuf, attrs); + + LOGE_IF(mTextures[index].image == EGL_NO_IMAGE_KHR, + "eglCreateImageKHR() failed. err=0x%4x", + eglGetError()); + + if (mTextures[index].image != EGL_NO_IMAGE_KHR) { + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, + (GLeglImageOES)mTextures[index].image); + GLint error = glGetError(); + if (UNLIKELY(error != GL_NO_ERROR)) { + // this failed, for instance, because we don't support + // NPOT. + // FIXME: do something! + mFlags &= ~DisplayHardware::DIRECT_TEXTURE; + } else { + // Everything went okay! + mTextures[index].dirty = false; + } + } + } + } else { + GGLSurface t; + status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_RARELY); + LOGE_IF(res, "error %d (%s) locking buffer %p", + res, strerror(res), buffer.get()); + if (res == NO_ERROR) { + if (UNLIKELY(mTextures[0].name == -1U)) { + mTextures[0].name = createTexture(); + } + loadTexture(dirty, mTextures[0].name, t, + mTextures[0].width, mTextures[0].height); + buffer->unlock(); + } } - const GGLSurface& t(frontBuffer().surface()); - loadTexture(dirty, mTextureName, t, mTextureWidth, mTextureHeight); } void Layer::onDraw(const Region& clip) const { - if (UNLIKELY(mTextureName == -1LU)) { - //LOGW("Layer %p doesn't have a texture", this); + const int index = (mFlags & DisplayHardware::DIRECT_TEXTURE) ? + mFrontBufferIndex : 0; + GLuint textureName = mTextures[index].name; + + if (UNLIKELY(textureName == -1LU)) { + LOGW("Layer %p doesn't have a texture", this); // the texture has not been created yet, this Layer has // in fact never been drawn into. this happens frequently with // SurfaceView. @@ -164,63 +224,65 @@ void Layer::onDraw(const Region& clip) const return; } - const DisplayHardware& hw(graphicPlane(0).displayHardware()); - const LayerBitmap& front(frontBuffer()); - const GGLSurface& t(front.surface()); - - status_t err = NO_ERROR; - const int can_use_copybit = canUseCopybit(); - if (can_use_copybit) { - // StopWatch watch("copybit"); - const State& s(drawingState()); - - copybit_image_t dst; - hw.getDisplaySurface(&dst); - const copybit_rect_t& drect - = reinterpret_cast<const copybit_rect_t&>(mTransformedBounds); - - copybit_image_t src; - front.getBitmapSurface(&src); - copybit_rect_t srect = { 0, 0, t.width, t.height }; - - 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); - - region_iterator it(clip); - err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it); - } - - if (!can_use_copybit || err) { - drawWithOpenGL(clip, mTextureName, t); - } + GGLSurface t; + sp<const Buffer> buffer(frontBuffer().getBuffer()); + drawWithOpenGL(clip, textureName, buffer); } -status_t Layer::reallocateBuffer(int32_t index, uint32_t w, uint32_t h) +sp<SurfaceBuffer> Layer::peekBuffer() { + /* + * This is called from the client's Surface::lock(), after it locked + * the surface successfully. We're therefore guaranteed that the + * back-buffer is not in use by ourselves. + * Of course, we need to validate all this, which is not trivial. + * + * FIXME: A resize could happen at any time here. What to do about this? + * - resize() form post() + * - resize() from doTransaction() + * + * We'll probably need an internal lock for this. + * + * + * TODO: We need to make sure that post() doesn't swap + * the buffers under us. + */ + + // it's okay to read swapState for the purpose of figuring out the + // backbuffer index, which cannot change (since the app has locked it). + const uint32_t state = lcblk->swapState; + const int32_t backBufferIndex = layer_cblk_t::backBuffer(state); + + // get rid of the EGL image, since we shouldn't need it anymore + // (note that we're in a different thread than where it is being used) + if (mTextures[backBufferIndex].image != EGL_NO_IMAGE_KHR) { + EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay()); + eglDestroyImageKHR(dpy, mTextures[backBufferIndex].image); + mTextures[backBufferIndex].image = EGL_NO_IMAGE_KHR; + } + + LayerBitmap& layerBitmap(mBuffers[backBufferIndex]); + sp<SurfaceBuffer> buffer = layerBitmap.allocate(); + LOGD_IF(DEBUG_RESIZE, - "reallocateBuffer (layer=%p), " - "requested (%dx%d), " - "index=%d, (%dx%d), (%dx%d)", - this, - int(w), int(h), - int(index), - int(mBuffers[0].width()), int(mBuffers[0].height()), - int(mBuffers[1].width()), int(mBuffers[1].height())); - - status_t err = mBuffers[index].resize(w, h); - if (err == NO_ERROR) { - mBuffers[index].getInfo(lcblk->surface + index); + "Layer::getBuffer(this=%p), index=%d, (%d,%d), (%d,%d)", + this, backBufferIndex, + layerBitmap.getWidth(), + layerBitmap.getHeight(), + layerBitmap.getBuffer()->getWidth(), + layerBitmap.getBuffer()->getHeight()); + + if (UNLIKELY(buffer == 0)) { + // XXX: what to do, what to do? } else { - LOGE("resizing buffer %d to (%u,%u) failed [%08x] %s", - index, w, h, err, strerror(err)); - // XXX: what to do, what to do? We could try to free some - // hidden surfaces, instead of killing this one? + // texture is now dirty... + mTextures[backBufferIndex].dirty = true; + // ... so it the visible region (because we consider the surface's + // buffer size for visibility calculations) + forceVisibilityTransaction(); + mFlinger->setTransactionFlags(eTraversalNeeded); } - return err; + return buffer; } uint32_t Layer::doTransaction(uint32_t flags) @@ -232,7 +294,7 @@ uint32_t Layer::doTransaction(uint32_t flags) // that the size changed back to its previous value before the buffer // was resized (in the eLocked case below), in which case, we still // need to execute the code below so the clients have a chance to be - // release. resze() deals with the fact that the size can be the same. + // release. resize() deals with the fact that the size can be the same. /* * Various states we could be in... @@ -276,8 +338,8 @@ uint32_t Layer::doTransaction(uint32_t flags) int(temp.w), int(temp.h), int(drawingState().w), int(drawingState().h), int(clientBackBufferIndex), - int(mBuffers[0].width()), int(mBuffers[0].height()), - int(mBuffers[1].width()), int(mBuffers[1].height())); + int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()), + int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight())); // if we get there we're pretty screwed. the only reasonable // thing to do is to pretend we should do the resize since // backbufferChanged is set (this also will give a chance to @@ -299,8 +361,8 @@ uint32_t Layer::doTransaction(uint32_t flags) int(temp.w), int(temp.h), int(drawingState().w), int(drawingState().h), int(clientBackBufferIndex), - int(mBuffers[0].width()), int(mBuffers[0].height()), - int(mBuffers[1].width()), int(mBuffers[1].height())); + int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()), + int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight())); if (state & eLocked) { // if the buffer is locked, we can't resize anything because @@ -314,7 +376,8 @@ uint32_t Layer::doTransaction(uint32_t flags) status_t err = resize(clientBackBufferIndex, temp.w, temp.h, "transaction"); if (err == NO_ERROR) { - const uint32_t mask = clientBackBufferIndex ? eResizeBuffer1 : eResizeBuffer0; + const uint32_t mask = clientBackBufferIndex ? + eResizeBuffer1 : eResizeBuffer0; android_atomic_and(~mask, &(lcblk->swapState)); // since a buffer became available, we can let the client go... mFlinger->scheduleBroadcast(client); @@ -353,14 +416,15 @@ status_t Layer::resize( { /* * handle resize (backbuffer and frontbuffer reallocation) + * this is called from post() or from doTransaction() */ const LayerBitmap& clientBackBuffer(mBuffers[clientBackBufferIndex]); // if the new (transaction) size is != from the the backbuffer // then we need to reallocate the backbuffer - bool backbufferChanged = (clientBackBuffer.width() != width) || - (clientBackBuffer.height() != height); + bool backbufferChanged = (clientBackBuffer.getWidth() != width) || + (clientBackBuffer.getHeight() != height); LOGD_IF(!backbufferChanged, "(%s) eResizeRequested (layer=%p), but size not changed: " @@ -372,18 +436,28 @@ status_t Layer::resize( int(currentState().w), int(currentState().h), long(lcblk->swapState), int(clientBackBufferIndex), - int(mBuffers[0].width()), int(mBuffers[0].height()), - int(mBuffers[1].width()), int(mBuffers[1].height())); + int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()), + int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight())); // this can happen when changing the size back and forth quickly status_t err = NO_ERROR; if (backbufferChanged) { - err = reallocateBuffer(clientBackBufferIndex, width, height); - } - if (UNLIKELY(err != NO_ERROR)) { - // couldn't reallocate the surface - android_atomic_write(eInvalidSurface, &lcblk->swapState); - memset(lcblk->surface+clientBackBufferIndex, 0, sizeof(surface_info_t)); + + LOGD_IF(DEBUG_RESIZE, + "resize (layer=%p), requested (%dx%d), " + "index=%d, (%dx%d), (%dx%d)", + this, int(width), int(height), int(clientBackBufferIndex), + int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()), + int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight())); + + err = mBuffers[clientBackBufferIndex].setSize(width, height); + if (UNLIKELY(err != NO_ERROR)) { + // This really should never happen + LOGE("resizing buffer %d to (%u,%u) failed [%08x] %s", + clientBackBufferIndex, width, height, err, strerror(err)); + // couldn't reallocate the surface + android_atomic_write(eInvalidSurface, &lcblk->swapState); + } } return err; } @@ -457,15 +531,21 @@ Region Layer::post(uint32_t* previousSate, bool& recomputeVisibleRegions) } while(android_atomic_cmpxchg(oldValue, newValue, &(lcblk->swapState))); *previousSate = oldValue; - + const int32_t index = (newValue & eIndex) ^ 1; mFrontBufferIndex = index; + /* NOTE: it's safe to set this flag here because this is only touched + * from LayerBitmap::allocate(), which by construction cannot happen + * while we're in post(). + */ + lcblk->surface[index].flags &= ~surface_info_t::eBufferDirty; + // ... post the new front-buffer Region dirty(lcblk->region + index); - dirty.andSelf(frontBuffer().bounds()); + dirty.andSelf(frontBuffer().getBounds()); - //LOGI("Did post oldValue=%08lx, newValue=%08lx, mFrontBufferIndex=%u\n", + //LOGD("Did post oldValue=%08lx, newValue=%08lx, mFrontBufferIndex=%u\n", // oldValue, newValue, mFrontBufferIndex); //dirty.dump("dirty"); @@ -476,8 +556,8 @@ Region Layer::post(uint32_t* previousSate, bool& recomputeVisibleRegions) "index=%d, (%dx%d), (%dx%d)", this, newValue, int(1-index), - int(mBuffers[0].width()), int(mBuffers[0].height()), - int(mBuffers[1].width()), int(mBuffers[1].height())); + int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()), + int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight())); // here, we just posted the surface and we have resolved // the front/back buffer indices. The client is blocked, so @@ -522,8 +602,8 @@ Region Layer::post(uint32_t* previousSate, bool& recomputeVisibleRegions) Point Layer::getPhysicalSize() const { - const LayerBitmap& front(frontBuffer()); - return Point(front.width(), front.height()); + sp<const Buffer> front(frontBuffer().getBuffer()); + return Point(front->getWidth(), front->getHeight()); } void Layer::unlockPageFlip( @@ -561,6 +641,27 @@ void Layer::finishPageFlip() mFlinger->scheduleBroadcast(client); } +// --------------------------------------------------------------------------- + +Layer::SurfaceLayer::SurfaceLayer(const sp<SurfaceFlinger>& flinger, + SurfaceID id, const sp<Layer>& owner) + : Surface(flinger, id, owner->getIdentity(), owner) +{ +} + +Layer::SurfaceLayer::~SurfaceLayer() +{ +} + +sp<SurfaceBuffer> Layer::SurfaceLayer::getBuffer() +{ + sp<SurfaceBuffer> buffer = 0; + sp<Layer> owner(getOwner()); + if (owner != 0) { + buffer = owner->peekBuffer(); + } + return buffer; +} // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/Layer.h b/libs/surfaceflinger/Layer.h index 2867f2b..e16d9f4 100644 --- a/libs/surfaceflinger/Layer.h +++ b/libs/surfaceflinger/Layer.h @@ -27,6 +27,11 @@ #include <pixelflinger/pixelflinger.h> +#include <EGL/egl.h> +#include <EGL/eglext.h> +#include <GLES/gl.h> +#include <GLES/glext.h> + #include "LayerBitmap.h" #include "LayerBase.h" #include "Transform.h" @@ -42,6 +47,8 @@ class FreezeLock; // --------------------------------------------------------------------------- +const int NUM_BUFFERS = 2; + class Layer : public LayerBaseClient { public: @@ -56,7 +63,7 @@ public: virtual ~Layer(); inline PixelFormat pixelFormat() const { - return frontBuffer().pixelFormat(); + return frontBuffer().getPixelFormat(); } status_t setBuffers( Client* client, @@ -73,8 +80,8 @@ public: virtual void finishPageFlip(); virtual bool needsBlending() const { return mNeedsBlending; } virtual bool isSecure() const { return mSecure; } - virtual GLuint getTextureName() const { return mTextureName; } - virtual sp<Surface> getSurface() const; + virtual sp<Surface> createSurface() const; + virtual status_t ditch(); const LayerBitmap& getBuffer(int i) const { return mBuffers[i]; } LayerBitmap& getBuffer(int i) { return mBuffers[i]; } @@ -96,21 +103,46 @@ private: status_t resize(int32_t index, uint32_t w, uint32_t h, const char* what); Region post(uint32_t* oldState, bool& recomputeVisibleRegions); - status_t reallocateBuffer(int32_t index, uint32_t w, uint32_t h); - + sp<SurfaceBuffer> peekBuffer(); + void destroy(); + + + class SurfaceLayer : public LayerBaseClient::Surface + { + public: + SurfaceLayer(const sp<SurfaceFlinger>& flinger, + SurfaceID id, const sp<Layer>& owner); + ~SurfaceLayer(); + + private: + virtual sp<SurfaceBuffer> getBuffer(); + + sp<Layer> getOwner() const { + return static_cast<Layer*>(Surface::getOwner().get()); + } + }; + friend class SurfaceLayer; + + struct Texture { + Texture() : name(-1U), width(0), height(0), image(EGL_NO_IMAGE_KHR), + dirty(true) { } + GLuint name; + GLuint width; + GLuint height; + EGLImageKHR image; + bool dirty; + }; + sp<Surface> mSurface; bool mSecure; - LayerBitmap mBuffers[2]; + LayerBitmap mBuffers[NUM_BUFFERS]; + Texture mTextures[NUM_BUFFERS]; int32_t mFrontBufferIndex; bool mNeedsBlending; bool mResizeTransactionDone; Region mPostedDirtyRegion; sp<FreezeLock> mFreezeLock; - - GLuint mTextureName; - GLuint mTextureWidth; - GLuint mTextureHeight; }; // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp index 0cf53f7..c678711 100644 --- a/libs/surfaceflinger/LayerBase.cpp +++ b/libs/surfaceflinger/LayerBase.cpp @@ -14,14 +14,14 @@ * 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 <binder/IPCThreadState.h> +#include <binder/IServiceManager.h> #include <GLES/gl.h> #include <GLES/glext.h> @@ -53,8 +53,6 @@ const char* const LayerBaseClient::typeID = "LayerBaseClient"; // --------------------------------------------------------------------------- -Vector<GLuint> LayerBase::deletedTextures; - int32_t LayerBase::sIdentity = 0; LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display) @@ -62,7 +60,6 @@ LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display) mFlinger(flinger), mTransformed(false), mOrientation(0), - mCanUseCopyBit(false), mTransactionFlags(0), mPremultipliedAlpha(true), mIdentity(uint32_t(android_atomic_inc(&sIdentity))), @@ -265,43 +262,6 @@ void LayerBase::validateVisibility(const Transform& planeTransform) mTransformed = transformed; mLeft = tr.tx(); mTop = tr.ty(); - - // see if we can/should use 2D h/w with the new configuration - mCanUseCopyBit = false; - copybit_device_t* copybit = mFlinger->getBlitEngine(); - if (copybit) { - const int step = copybit->get(copybit, COPYBIT_ROTATION_STEP_DEG); - const int scaleBits = copybit->get(copybit, COPYBIT_SCALING_FRAC_BITS); - mCanUseCopyBit = true; - if ((mOrientation < 0) && (step > 1)) { - // arbitrary orientations not supported - mCanUseCopyBit = false; - } else if ((mOrientation > 0) && (step > 90)) { - // 90 deg rotations not supported - mCanUseCopyBit = false; - } else if ((tr.getType() & SkMatrix::kScale_Mask) && (scaleBits < 12)) { - // arbitrary scaling not supported - mCanUseCopyBit = false; - } -#if HONOR_PREMULTIPLIED_ALPHA - else if (needsBlending() && mPremultipliedAlpha) { - // pre-multiplied alpha not supported - mCanUseCopyBit = false; - } -#endif - else { - // here, we determined we can use copybit - if (tr.getType() & SkMatrix::kScale_Mask) { - // and we have scaling - if (!transparentRegionScreen.isRect()) { - // we punt because blending is cheap (h/w) and the region is - // complex, which may causes artifacts when copying - // scaled content - transparentRegionScreen.clear(); - } - } - } - } } void LayerBase::lockPageFlip(bool& recomputeVisibleRegions) @@ -329,8 +289,9 @@ void LayerBase::invalidate() void LayerBase::drawRegion(const Region& reg) const { - Region::iterator iterator(reg); - if (iterator) { + Region::const_iterator it = reg.begin(); + Region::const_iterator const end = reg.end(); + if (it != end) { Rect r; const DisplayHardware& hw(graphicPlane(0).displayHardware()); const int32_t fbWidth = hw.getWidth(); @@ -338,7 +299,8 @@ void LayerBase::drawRegion(const Region& reg) const const GLshort vertices[][2] = { { 0, 0 }, { fbWidth, 0 }, { fbWidth, fbHeight }, { 0, fbHeight } }; glVertexPointer(2, GL_SHORT, 0, vertices); - while (iterator.iterate(&r)) { + while (it != end) { + const Rect& r = *it++; const GLint sy = fbHeight - (r.top + r.height()); glScissor(r.left, sy, r.width(), r.height()); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); @@ -403,12 +365,14 @@ void LayerBase::clearWithOpenGL(const Region& clip) const glDisable(GL_TEXTURE_2D); glDisable(GL_BLEND); glDisable(GL_DITHER); - Rect r; - Region::iterator iterator(clip); - if (iterator) { + + Region::const_iterator it = clip.begin(); + Region::const_iterator const end = clip.end(); + if (it != end) { glEnable(GL_SCISSOR_TEST); glVertexPointer(2, GL_FIXED, 0, mVertices); - while (iterator.iterate(&r)) { + while (it != end) { + const Rect& r = *it++; const GLint sy = fbHeight - (r.top + r.height()); glScissor(r.left, sy, r.width(), r.height()); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); @@ -417,12 +381,14 @@ void LayerBase::clearWithOpenGL(const Region& clip) const } void LayerBase::drawWithOpenGL(const Region& clip, - GLint textureName, const GGLSurface& t, int transform) const + GLint textureName, const sp<const Buffer>& buffer, int transform) const { const DisplayHardware& hw(graphicPlane(0).displayHardware()); const uint32_t fbHeight = hw.getHeight(); const State& s(drawingState()); - + const uint32_t width = buffer->width; + const uint32_t height = buffer->height; + // bind our texture validateTexture(textureName); glEnable(GL_TEXTURE_2D); @@ -472,8 +438,9 @@ void LayerBase::drawWithOpenGL(const Region& clip, || !(mFlags & DisplayHardware::DRAW_TEXTURE_EXTENSION) )) { //StopWatch watch("GL transformed"); - Region::iterator iterator(clip); - if (iterator) { + Region::const_iterator it = clip.begin(); + Region::const_iterator const end = clip.end(); + if (it != end) { // always use high-quality filtering with fast configurations bool fast = !(mFlags & DisplayHardware::SLOW_CONFIG); if (!fast && s.flags & ISurfaceComposer::eLayerFilter) { @@ -497,14 +464,14 @@ void LayerBase::drawWithOpenGL(const Region& clip, if (!(mFlags & DisplayHardware::NPOT_EXTENSION)) { // find the smallest power-of-two that will accommodate our surface - GLuint tw = 1 << (31 - clz(t.width)); - GLuint th = 1 << (31 - clz(t.height)); - if (tw < t.width) tw <<= 1; - if (th < t.height) th <<= 1; + GLuint tw = 1 << (31 - clz(width)); + GLuint th = 1 << (31 - clz(height)); + if (tw < width) tw <<= 1; + if (th < height) th <<= 1; // this divide should be relatively fast because it's // a power-of-two (optimized path in libgcc) - GLfloat ws = GLfloat(t.width) /tw; - GLfloat hs = GLfloat(t.height)/th; + GLfloat ws = GLfloat(width) /tw; + GLfloat hs = GLfloat(height)/th; glScalef(ws, hs, 1.0f); } @@ -512,8 +479,8 @@ void LayerBase::drawWithOpenGL(const Region& clip, glVertexPointer(2, GL_FIXED, 0, mVertices); glTexCoordPointer(2, GL_FIXED, 0, texCoords); - Rect r; - while (iterator.iterate(&r)) { + while (it != end) { + const Rect& r = *it++; const GLint sy = fbHeight - (r.top + r.height()); glScissor(r.left, sy, r.width(), r.height()); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); @@ -526,18 +493,19 @@ void LayerBase::drawWithOpenGL(const Region& clip, glDisableClientState(GL_TEXTURE_COORD_ARRAY); } } else { - Region::iterator iterator(clip); - if (iterator) { - Rect r; - GLint crop[4] = { 0, t.height, t.width, -t.height }; + Region::const_iterator it = clip.begin(); + Region::const_iterator const end = clip.end(); + if (it != end) { + GLint crop[4] = { 0, height, width, -height }; glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop); int x = tx(); int y = ty(); - y = fbHeight - (y + t.height); - while (iterator.iterate(&r)) { + y = fbHeight - (y + height); + while (it != end) { + const Rect& r = *it++; const GLint sy = fbHeight - (r.top + r.height()); glScissor(r.left, sy, r.width(), r.height()); - glDrawTexiOES(x, y, 0, t.width, t.height); + glDrawTexiOES(x, y, 0, width, height); } } } @@ -565,8 +533,7 @@ void LayerBase::loadTexture(const Region& dirty, /* * In OpenGL ES we can't specify a stride with glTexImage2D (however, - * GL_UNPACK_ALIGNMENT is 4, which in essence allows a limited form of - * stride). + * GL_UNPACK_ALIGNMENT is a limited form of stride). * So if the stride here isn't representable with GL_UNPACK_ALIGNMENT, we * need to do something reasonable (here creating a bigger texture). * @@ -579,9 +546,11 @@ void LayerBase::loadTexture(const Region& dirty, * * This should never be a problem with POT textures */ - - tw += (((t.stride - tw) * bytesPerPixel(t.format)) / 4); - + + int unpack = __builtin_ctz(t.stride * bytesPerPixel(t.format)); + unpack = 1 << ((unpack > 3) ? 3 : unpack); + glPixelStorei(GL_UNPACK_ALIGNMENT, unpack); + /* * round to POT if needed */ @@ -594,106 +563,78 @@ void LayerBase::loadTexture(const Region& dirty, texture_h = 1 << (31 - clz(t.height)); if (texture_w < t.width) texture_w <<= 1; if (texture_h < t.height) texture_h <<= 1; - if (texture_w != tw || texture_h != th) { - // we can't use DIRECT_TEXTURE since we changed the size - // of the texture - flags &= ~DisplayHardware::DIRECT_TEXTURE; - } } - - if (flags & DisplayHardware::DIRECT_TEXTURE) { - // here we're guaranteed that texture_{w|h} == t{w|h} - if (t.format == GGL_PIXEL_FORMAT_RGB_565) { - glTexImage2D(GL_DIRECT_TEXTURE_2D_QUALCOMM, 0, - GL_RGB, tw, th, 0, - GL_RGB, GL_UNSIGNED_SHORT_5_6_5, t.data); - } else if (t.format == GGL_PIXEL_FORMAT_RGBA_4444) { - glTexImage2D(GL_DIRECT_TEXTURE_2D_QUALCOMM, 0, - GL_RGBA, tw, th, 0, - GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, t.data); - } else if (t.format == GGL_PIXEL_FORMAT_RGBA_8888) { - glTexImage2D(GL_DIRECT_TEXTURE_2D_QUALCOMM, 0, - GL_RGBA, tw, th, 0, - GL_RGBA, GL_UNSIGNED_BYTE, t.data); - } else if (t.format == GGL_PIXEL_FORMAT_BGRA_8888) { - // TODO: add GL_BGRA extension - } else { - // oops, we don't handle this format, try the regular path - goto regular; - } - textureWidth = tw; - textureHeight = th; - } else { + regular: - Rect bounds(dirty.bounds()); - GLvoid* data = 0; - if (texture_w!=textureWidth || texture_h!=textureHeight) { - // texture size changed, we need to create a new one - - if (!textureWidth || !textureHeight) { - // this is the first time, load the whole texture - if (texture_w==tw && texture_h==th) { - // we can do it one pass - data = t.data; - } else { - // we have to create the texture first because it - // doesn't match the size of the buffer - bounds.set(Rect(tw, th)); - } - } - - if (t.format == GGL_PIXEL_FORMAT_RGB_565) { - glTexImage2D(GL_TEXTURE_2D, 0, - GL_RGB, texture_w, texture_h, 0, - GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data); - } else if (t.format == GGL_PIXEL_FORMAT_RGBA_4444) { - glTexImage2D(GL_TEXTURE_2D, 0, - GL_RGBA, texture_w, texture_h, 0, - GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, data); - } else if (t.format == GGL_PIXEL_FORMAT_RGBA_8888) { - glTexImage2D(GL_TEXTURE_2D, 0, - GL_RGBA, texture_w, texture_h, 0, - GL_RGBA, GL_UNSIGNED_BYTE, data); - } else if ( t.format == GGL_PIXEL_FORMAT_YCbCr_422_SP || - t.format == GGL_PIXEL_FORMAT_YCbCr_420_SP) { - // just show the Y plane of YUV buffers + Rect bounds(dirty.bounds()); + GLvoid* data = 0; + if (texture_w!=textureWidth || texture_h!=textureHeight) { + // texture size changed, we need to create a new one + + if (!textureWidth || !textureHeight) { + // this is the first time, load the whole texture + if (texture_w==tw && texture_h==th) { + // we can do it one pass data = t.data; - glTexImage2D(GL_TEXTURE_2D, 0, - GL_LUMINANCE, texture_w, texture_h, 0, - GL_LUMINANCE, GL_UNSIGNED_BYTE, data); } else { - // oops, we don't handle this format! - LOGE("layer %p, texture=%d, using format %d, which is not " - "supported by the GL", this, textureName, t.format); - textureName = -1; + // we have to create the texture first because it + // doesn't match the size of the buffer + bounds.set(Rect(tw, th)); } - textureWidth = texture_w; - textureHeight = texture_h; } - if (!data && textureName>=0) { - if (t.format == GGL_PIXEL_FORMAT_RGB_565) { - glTexSubImage2D(GL_TEXTURE_2D, 0, - 0, bounds.top, t.width, bounds.height(), - GL_RGB, GL_UNSIGNED_SHORT_5_6_5, - t.data + bounds.top*t.width*2); - } else if (t.format == GGL_PIXEL_FORMAT_RGBA_4444) { - glTexSubImage2D(GL_TEXTURE_2D, 0, - 0, bounds.top, t.width, bounds.height(), - GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, - t.data + bounds.top*t.width*2); - } else if (t.format == GGL_PIXEL_FORMAT_RGBA_8888) { - glTexSubImage2D(GL_TEXTURE_2D, 0, - 0, bounds.top, t.width, bounds.height(), - GL_RGBA, GL_UNSIGNED_BYTE, - t.data + bounds.top*t.width*4); - } + + if (t.format == GGL_PIXEL_FORMAT_RGB_565) { + glTexImage2D(GL_TEXTURE_2D, 0, + GL_RGB, texture_w, texture_h, 0, + GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data); + } else if (t.format == GGL_PIXEL_FORMAT_RGBA_4444) { + glTexImage2D(GL_TEXTURE_2D, 0, + GL_RGBA, texture_w, texture_h, 0, + GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, data); + } else if (t.format == GGL_PIXEL_FORMAT_RGBA_8888) { + glTexImage2D(GL_TEXTURE_2D, 0, + GL_RGBA, texture_w, texture_h, 0, + GL_RGBA, GL_UNSIGNED_BYTE, data); + } else if ( t.format == GGL_PIXEL_FORMAT_YCbCr_422_SP || + t.format == GGL_PIXEL_FORMAT_YCbCr_420_SP) { + // just show the Y plane of YUV buffers + glTexImage2D(GL_TEXTURE_2D, 0, + GL_LUMINANCE, texture_w, texture_h, 0, + GL_LUMINANCE, GL_UNSIGNED_BYTE, data); + } else { + // oops, we don't handle this format! + LOGE("layer %p, texture=%d, using format %d, which is not " + "supported by the GL", this, textureName, t.format); + textureName = -1; + } + textureWidth = texture_w; + textureHeight = texture_h; + } + if (!data && textureName>=0) { + if (t.format == GGL_PIXEL_FORMAT_RGB_565) { + glTexSubImage2D(GL_TEXTURE_2D, 0, + 0, bounds.top, t.width, bounds.height(), + GL_RGB, GL_UNSIGNED_SHORT_5_6_5, + t.data + bounds.top*t.stride*2); + } else if (t.format == GGL_PIXEL_FORMAT_RGBA_4444) { + glTexSubImage2D(GL_TEXTURE_2D, 0, + 0, bounds.top, t.width, bounds.height(), + GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, + t.data + bounds.top*t.stride*2); + } else if (t.format == GGL_PIXEL_FORMAT_RGBA_8888) { + glTexSubImage2D(GL_TEXTURE_2D, 0, + 0, bounds.top, t.width, bounds.height(), + GL_RGBA, GL_UNSIGNED_BYTE, + t.data + bounds.top*t.stride*4); + } else if ( t.format == GGL_PIXEL_FORMAT_YCbCr_422_SP || + t.format == GGL_PIXEL_FORMAT_YCbCr_420_SP) { + // just show the Y plane of YUV buffers + glTexSubImage2D(GL_TEXTURE_2D, 0, + 0, bounds.top, t.width, bounds.height(), + GL_LUMINANCE, GL_UNSIGNED_BYTE, + t.data + bounds.top*t.stride); } } -} - -bool LayerBase::canUseCopybit() const -{ - return mCanUseCopyBit; } // --------------------------------------------------------------------------- @@ -704,9 +645,12 @@ LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, DisplayID display, lcblk( c ? &(c->ctrlblk->layers[i]) : 0 ), mIndex(i) { - if (client) { - client->bindLayer(this, i); +} +void LayerBaseClient::onFirstRef() +{ + if (client) { + client->bindLayer(this, mIndex); // Initialize this layer's control block memset(this->lcblk, 0, sizeof(layer_cblk_t)); this->lcblk->identity = mIdentity; @@ -729,11 +673,113 @@ int32_t LayerBaseClient::serverIndex() const { return 0xFFFF0000 | mIndex; } -sp<LayerBaseClient::Surface> LayerBaseClient::getSurface() const +sp<LayerBaseClient::Surface> LayerBaseClient::getSurface() +{ + sp<Surface> s; + Mutex::Autolock _l(mLock); + s = mClientSurface.promote(); + if (s == 0) { + s = createSurface(); + mClientSurface = s; + } + return s; +} + +sp<LayerBaseClient::Surface> LayerBaseClient::createSurface() const +{ + return new Surface(mFlinger, clientIndex(), mIdentity, + const_cast<LayerBaseClient *>(this)); +} + +// --------------------------------------------------------------------------- + +LayerBaseClient::Surface::Surface( + const sp<SurfaceFlinger>& flinger, + SurfaceID id, int identity, + const sp<LayerBaseClient>& owner) + : mFlinger(flinger), mToken(id), mIdentity(identity), mOwner(owner) +{ +} + + +LayerBaseClient::Surface::~Surface() +{ + /* + * This is a good place to clean-up all client resources + */ + + // destroy client resources + sp<LayerBaseClient> layer = getOwner(); + if (layer != 0) { + mFlinger->destroySurface(layer); + } +} + +sp<LayerBaseClient> LayerBaseClient::Surface::getOwner() const { + sp<LayerBaseClient> owner(mOwner.promote()); + return owner; +} + + +void LayerBaseClient::Surface::getSurfaceData( + ISurfaceFlingerClient::surface_data_t* params) const +{ + params->token = mToken; + params->identity = mIdentity; +} + +status_t LayerBaseClient::Surface::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 BnSurface::onTransact(code, data, reply, flags); +} + +sp<SurfaceBuffer> LayerBaseClient::Surface::getBuffer() { - return new Surface(clientIndex(), mIdentity); + return NULL; +} + +status_t LayerBaseClient::Surface::registerBuffers( + const ISurface::BufferHeap& buffers) +{ + return INVALID_OPERATION; } +void LayerBaseClient::Surface::postBuffer(ssize_t offset) +{ +} + +void LayerBaseClient::Surface::unregisterBuffers() +{ +} + +sp<OverlayRef> LayerBaseClient::Surface::createOverlay( + uint32_t w, uint32_t h, int32_t format) +{ + return NULL; +}; // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h index a020f44..509dedd 100644 --- a/libs/surfaceflinger/LayerBase.h +++ b/libs/surfaceflinger/LayerBase.h @@ -22,6 +22,8 @@ #include <private/ui/LayerState.h> +#include <utils/RefBase.h> + #include <ui/Region.h> #include <ui/Overlay.h> @@ -37,10 +39,12 @@ class SurfaceFlinger; class DisplayHardware; class GraphicPlane; class Client; +class SurfaceBuffer; +class Buffer; // --------------------------------------------------------------------------- -class LayerBase +class LayerBase : public RefBase { // poor man's dynamic_cast below template<typename T> @@ -69,10 +73,7 @@ public: } - static Vector<GLuint> deletedTextures; - LayerBase(SurfaceFlinger* flinger, DisplayID display); - virtual ~LayerBase(); DisplayID dpy; mutable bool contentDirty; @@ -201,21 +202,29 @@ public: /** * isSecure - true if this surface is secure, that is if it prevents - * screenshots or vns servers. + * screenshots or VNC servers. */ virtual bool isSecure() const { return false; } - enum { // flags for doTransaction() - eVisibleRegion = 0x00000002, - eRestartTransaction = 0x00000008 - }; + /** signal this layer that it's not needed any longer. called from the + * main thread */ + virtual status_t ditch() { return NO_ERROR; } + + + + enum { // flags for doTransaction() + eVisibleRegion = 0x00000002, + eRestartTransaction = 0x00000008 + }; inline const State& drawingState() const { return mDrawingState; } inline const State& currentState() const { return mCurrentState; } inline State& currentState() { return mCurrentState; } - static int compareCurrentStateZ(LayerBase*const* layerA, LayerBase*const* layerB) { + static int compareCurrentStateZ( + sp<LayerBase> const * layerA, + sp<LayerBase> const * layerB) { return layerA[0]->currentState().z - layerB[0]->currentState().z; } @@ -231,7 +240,7 @@ protected: void drawWithOpenGL(const Region& clip, GLint textureName, - const GGLSurface& surface, + const sp<const Buffer>& buffer, int transform = 0) const; void clearWithOpenGL(const Region& clip) const; @@ -240,9 +249,7 @@ protected: GLint textureName, const GGLSurface& t, GLuint& textureWidth, GLuint& textureHeight) const; - bool canUseCopybit() const; - - SurfaceFlinger* mFlinger; + sp<SurfaceFlinger> mFlinger; uint32_t mFlags; // cached during validateVisibility() @@ -250,7 +257,6 @@ protected: int32_t mOrientation; GLfixed mVertices[4][2]; Rect mTransformedBounds; - bool mCanUseCopyBit; int mLeft; int mTop; @@ -269,9 +275,13 @@ protected: volatile int32_t mInvalidate; +protected: + virtual ~LayerBase(); + private: - void validateTexture(GLint textureName) const; - static int32_t sIdentity; + LayerBase(const LayerBase& rhs); + void validateTexture(GLint textureName) const; + static int32_t sIdentity; }; @@ -289,64 +299,58 @@ public: LayerBaseClient(SurfaceFlinger* flinger, DisplayID display, Client* client, int32_t i); virtual ~LayerBaseClient(); - + virtual void onFirstRef(); Client* const client; layer_cblk_t* const lcblk; + inline uint32_t getIdentity() const { return mIdentity; } inline int32_t clientIndex() const { return mIndex; } int32_t serverIndex() const; - virtual sp<Surface> getSurface() const; - uint32_t getIdentity() const { return mIdentity; } + sp<Surface> getSurface(); + virtual sp<Surface> createSurface() const; + class Surface : public BnSurface { public: - Surface(SurfaceID id, int identity) { - mParams.token = id; - mParams.identity = identity; - } - Surface(SurfaceID id, - const sp<IMemoryHeap>& heap0, - const sp<IMemoryHeap>& heap1, - int identity) - { - mParams.token = id; - mParams.identity = identity; - mParams.heap[0] = heap0; - mParams.heap[1] = heap1; - } - virtual ~Surface() { - // TODO: We now have a point here were we can clean-up the - // client's mess. - // This is also where surface id should be recycled. - //LOGD("Surface %d, heaps={%p, %p} destroyed", - // mId, mHeap[0].get(), mHeap[1].get()); - } - + virtual void getSurfaceData( - ISurfaceFlingerClient::surface_data_t* params) const { - *params = mParams; - } - - virtual status_t registerBuffers(const ISurface::BufferHeap& buffers) - { return INVALID_OPERATION; } - virtual void postBuffer(ssize_t offset) { } - virtual void unregisterBuffers() { }; - virtual sp<OverlayRef> createOverlay( - uint32_t w, uint32_t h, int32_t format) { - return NULL; - }; + ISurfaceFlingerClient::surface_data_t* params) const; + + protected: + Surface(const sp<SurfaceFlinger>& flinger, + SurfaceID id, int identity, + const sp<LayerBaseClient>& owner); + virtual ~Surface(); + virtual status_t onTransact(uint32_t code, const Parcel& data, + Parcel* reply, uint32_t flags); + sp<LayerBaseClient> getOwner() const; private: - ISurfaceFlingerClient::surface_data_t mParams; + virtual sp<SurfaceBuffer> getBuffer(); + virtual status_t registerBuffers(const ISurface::BufferHeap& buffers); + virtual void postBuffer(ssize_t offset); + virtual void unregisterBuffers(); + virtual sp<OverlayRef> createOverlay(uint32_t w, uint32_t h, + int32_t format); + + protected: + friend class LayerBaseClient; + sp<SurfaceFlinger> mFlinger; + int32_t mToken; + int32_t mIdentity; + wp<LayerBaseClient> mOwner; }; -private: - int32_t mIndex; + friend class Surface; +private: + int32_t mIndex; + mutable Mutex mLock; + mutable wp<Surface> mClientSurface; }; // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/LayerBitmap.cpp b/libs/surfaceflinger/LayerBitmap.cpp index eb3c3e5..a368ca9 100644 --- a/libs/surfaceflinger/LayerBitmap.cpp +++ b/libs/surfaceflinger/LayerBitmap.cpp @@ -14,172 +14,190 @@ * limitations under the License. */ -#define LOG_TAG "SurfaceFlinger" - #include <stdlib.h> #include <stdint.h> #include <sys/types.h> -#include <cutils/memory.h> #include <utils/Errors.h> #include <utils/Log.h> #include <binder/MemoryDealer.h> +#include <binder/MemoryBase.h> #include <binder/IMemory.h> + #include <ui/PixelFormat.h> +#include <ui/Surface.h> #include <pixelflinger/pixelflinger.h> +#include "BufferAllocator.h" #include "LayerBitmap.h" #include "SurfaceFlinger.h" -#include "VRamHeap.h" namespace android { -// --------------------------------------------------------------------------- +// =========================================================================== +// Buffer and implementation of android_native_buffer_t +// =========================================================================== -LayerBitmap::LayerBitmap() - : mAllocFlags(0), mOffset(0), mSize(-1U), mAlignment(2) +Buffer::Buffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) + : SurfaceBuffer(), mInitCheck(NO_INIT), mFlags(flags), + mVStride(0) { - memset(&mSurface, 0, sizeof(mSurface)); + this->format = format; + if (w>0 && h>0) { + mInitCheck = initSize(w, h); + } } -LayerBitmap::~LayerBitmap() +Buffer::~Buffer() { - mSurface.data = 0; + if (handle) { + BufferAllocator& allocator(BufferAllocator::get()); + allocator.free(handle); + } } -status_t LayerBitmap::init(const sp<MemoryDealer>& allocator) -{ - if (mAllocator != NULL) - return BAD_VALUE; - mAllocator = allocator; - return NO_ERROR; +status_t Buffer::initCheck() const { + return mInitCheck; } -status_t LayerBitmap::setBits(uint32_t w, uint32_t h, uint32_t alignment, - PixelFormat format, uint32_t flags) +android_native_buffer_t* Buffer::getNativeBuffer() const { - const sp<MemoryDealer>& allocator(mAllocator); - if (allocator == NULL) - return NO_INIT; - - if (UNLIKELY(w == mSurface.width && h == mSurface.height && - format == mSurface.format)) - { // same format and size, do nothing. - 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 = info.bytesPerPixel; - uint32_t stride = (w + (alignment-1)) & ~(alignment-1); - stride = ((stride * Bpp + (align-1)) & ~(align-1)) / Bpp; - size_t size = info.getScanlineSize(stride) * h; - if (allocFlags & MemoryDealer::PAGE_ALIGNED) { - size_t pagesize = getpagesize(); - size = (size + (pagesize-1)) & ~(pagesize-1); - } + return static_cast<android_native_buffer_t*>(const_cast<Buffer*>(this)); +} - /* FIXME: we should be able to have a h/v stride because the user of the - * surface might have stride limitation (for instance h/w codecs often do) +status_t Buffer::initSize(uint32_t w, uint32_t h) +{ + status_t err = NO_ERROR; + + BufferAllocator& allocator = BufferAllocator::get(); + + /* + * buffers used for software rendering, but h/w composition + * are allocated with SW_READ_OFTEN | SW_WRITE_OFTEN | HW_TEXTURE + * + * buffers used for h/w rendering and h/w composition + * are allocated with HW_RENDER | HW_TEXTURE + * + * buffers used with h/w rendering and either NPOT or no egl_image_ext + * are allocated with SW_READ_RARELY | HW_RENDER + * */ - int32_t vstride = 0; - - mAlignment = alignment; - mAllocFlags = allocFlags; - mOffset = 0; - if (mSize != size) { - // would be nice to have a reallocate() api - mBitsMemory.clear(); // free-memory - mBitsMemory = allocator->allocate(size, allocFlags); - mSize = size; + + if (mFlags & Buffer::SECURE) { + // secure buffer, don't store it into the GPU + usage = BufferAllocator::USAGE_SW_READ_OFTEN | + BufferAllocator::USAGE_SW_WRITE_OFTEN; } else { - // don't erase memory if we didn't have to reallocate - flags &= ~SECURE_BITS; - } - if (mBitsMemory != 0) { - mOffset = mBitsMemory->offset(); - mSurface.data = static_cast<GGLubyte*>(mBitsMemory->pointer()); - mSurface.version = sizeof(GGLSurface); - mSurface.width = w; - mSurface.height = h; - mSurface.stride = stride; - mSurface.vstride = vstride; - mSurface.format = format; - if (flags & SECURE_BITS) - clear(); + if (mFlags & Buffer::GPU) { + // the client wants to do GL rendering + usage = BufferAllocator::USAGE_HW_RENDER | + BufferAllocator::USAGE_HW_TEXTURE; + } else { + // software rendering-client, h/w composition + usage = BufferAllocator::USAGE_SW_READ_OFTEN | + BufferAllocator::USAGE_SW_WRITE_OFTEN | + BufferAllocator::USAGE_HW_TEXTURE; + } } - if (mBitsMemory==0 || mSurface.data==0) { - LOGE("not enough memory for layer bitmap " - "size=%u (w=%d, h=%d, stride=%d, format=%d)", - size, int(w), int(h), int(stride), int(format)); - allocator->dump("LayerBitmap"); - mSurface.data = 0; - mSize = -1U; - return NO_MEMORY; + err = allocator.alloc(w, h, format, usage, &handle, &stride); + + if (err == NO_ERROR) { + if (err == NO_ERROR) { + width = w; + height = h; + mVStride = 0; + } } - return NO_ERROR; + + return err; } -void LayerBitmap::clear() +status_t Buffer::lock(GGLSurface* sur, uint32_t usage) { - // NOTE: this memset should not be necessary, at least for - // opaque surface. However, for security reasons it's better to keep it - // (in the case of pmem, it's possible that the memory contains old - // data) - if (mSurface.data) { - memset(mSurface.data, 0, mSize); - //if (bytesPerPixel(mSurface.format) == 4) { - // android_memset32((uint32_t*)mSurface.data, 0xFF0000FF, mSize); - //} else { - // android_memset16((uint16_t*)mSurface.data, 0xF800, mSize); - //} + void* vaddr; + status_t res = SurfaceBuffer::lock(usage, &vaddr); + if (res == NO_ERROR && sur) { + sur->version = sizeof(GGLSurface); + sur->width = width; + sur->height = height; + sur->stride = stride; + sur->format = format; + sur->vstride = mVStride; + sur->data = static_cast<GGLubyte*>(vaddr); } + return res; } -status_t LayerBitmap::getInfo(surface_info_t* info) const + + +// =========================================================================== +// LayerBitmap +// =========================================================================== + + +LayerBitmap::LayerBitmap() + : mInfo(0), mWidth(0), mHeight(0) +{ +} + +LayerBitmap::~LayerBitmap() { - if (mSurface.data == 0) { - memset(info, 0, sizeof(surface_info_t)); - info->bits_offset = NO_MEMORY; - return NO_MEMORY; - } - info->w = uint16_t(width()); - info->h = uint16_t(height()); - info->stride= uint16_t(stride()); - info->bpr = uint16_t(stride() * bytesPerPixel(pixelFormat())); - info->format= uint8_t(pixelFormat()); - info->flags = surface_info_t::eBufferDirty; - info->bits_offset = ssize_t(mOffset); - return NO_ERROR; } -status_t LayerBitmap::resize(uint32_t w, uint32_t h) +status_t LayerBitmap::init(surface_info_t* info, + uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) { - int err = setBits(w, h, mAlignment, pixelFormat(), SECURE_BITS); - return err; + if (info == NULL) + return BAD_VALUE; + + mFormat = format; + mFlags = flags; + mWidth = w; + mHeight = h; + + mInfo = info; + memset(info, 0, sizeof(surface_info_t)); + info->flags = surface_info_t::eNeedNewBuffer; + + // init the buffer, but don't trigger an allocation + mBuffer = new Buffer(0, 0, format, flags); + return NO_ERROR; } -size_t LayerBitmap::size() const +status_t LayerBitmap::setSize(uint32_t w, uint32_t h) { - return mSize; + Mutex::Autolock _l(mLock); + if ((w != mWidth) || (h != mHeight)) { + mWidth = w; + mHeight = h; + // this will signal the client that it needs to asks us for a new buffer + mInfo->flags = surface_info_t::eNeedNewBuffer; + } + return NO_ERROR; } -void LayerBitmap::getBitmapSurface(copybit_image_t* img) const +sp<Buffer> LayerBitmap::allocate() { - const sp<IMemoryHeap>& mh(getAllocator()->getMemoryHeap()); - void* sbase = mh->base(); - const GGLSurface& t(surface()); - img->w = t.stride ?: t.width; - img->h = t.vstride ?: t.height; - img->format = t.format; - img->offset = intptr_t(t.data) - intptr_t(sbase); - img->base = sbase; - img->fd = mh->heapID(); + Mutex::Autolock _l(mLock); + sp<Buffer> buffer(mBuffer); + const uint32_t w = mWidth; + const uint32_t h = mHeight; + if (w != buffer->getWidth() || h != buffer->getHeight()) { + surface_info_t* info = mInfo; + buffer = new Buffer(w, h, mFormat, mFlags); + status_t err = buffer->initCheck(); + if (LIKELY(err == NO_ERROR)) { + info->flags = surface_info_t::eBufferDirty; + info->status = NO_ERROR; + } else { + memset(info, 0, sizeof(surface_info_t)); + info->status = NO_MEMORY; + } + mBuffer = buffer; + } + return buffer; } // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/LayerBitmap.h b/libs/surfaceflinger/LayerBitmap.h index 9ad64c4..824e0f2 100644 --- a/libs/surfaceflinger/LayerBitmap.h +++ b/libs/surfaceflinger/LayerBitmap.h @@ -20,63 +20,114 @@ #include <stdint.h> #include <sys/types.h> +#include <hardware/gralloc.h> + #include <utils/Atomic.h> + #include <ui/PixelFormat.h> #include <ui/Rect.h> -#include <private/ui/SharedState.h> +#include <ui/Surface.h> + #include <pixelflinger/pixelflinger.h> +#include <private/ui/SharedState.h> +#include <private/ui/SurfaceBuffer.h> + class copybit_image_t; +struct android_native_buffer_t; namespace android { // --------------------------------------------------------------------------- - class IMemory; class MemoryDealer; class LayerBitmap; -// --------------------------------------------------------------------------- +// =========================================================================== +// Buffer +// =========================================================================== -class LayerBitmap +class NativeBuffer; + +class Buffer : public SurfaceBuffer { public: - enum { - // erase memory to ensure security when necessary - SECURE_BITS = 0x00000001 + DONT_CLEAR = 0x00000001, + GPU = 0x00000002, + SECURE = 0x00000004 }; - LayerBitmap(); - ~LayerBitmap(); - status_t init(const sp<MemoryDealer>& allocator); + // creates w * h buffer + Buffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags = 0); + + // return status + status_t initCheck() const; + + uint32_t getWidth() const { return width; } + uint32_t getHeight() const { return height; } + uint32_t getStride() const { return stride; } + uint32_t getUsage() const { return usage; } + PixelFormat getPixelFormat() const { return format; } + Rect getBounds() const { return Rect(width, height); } + + status_t lock(GGLSurface* surface, uint32_t usage); + + android_native_buffer_t* getNativeBuffer() const; + +private: + friend class LightRefBase<Buffer>; + Buffer(const Buffer& rhs); + virtual ~Buffer(); + Buffer& operator = (const Buffer& rhs); + const Buffer& operator = (const Buffer& rhs) const; + + status_t initSize(uint32_t w, uint32_t h); + + ssize_t mInitCheck; + uint32_t mFlags; + uint32_t mVStride; +}; + +// =========================================================================== +// LayerBitmap +// =========================================================================== + +class LayerBitmap +{ +public: + enum { + DONT_CLEAR = Buffer::DONT_CLEAR, + GPU = Buffer::GPU, + SECURE = Buffer::SECURE + }; + LayerBitmap(); + ~LayerBitmap(); - status_t setBits(uint32_t w, uint32_t h, uint32_t alignment, - PixelFormat format, uint32_t flags = 0); - void clear(); + status_t init(surface_info_t* info, + uint32_t w, uint32_t h, PixelFormat format, uint32_t flags = 0); - status_t getInfo(surface_info_t* info) const; - status_t resize(uint32_t w, uint32_t h); + status_t setSize(uint32_t w, uint32_t h); - const GGLSurface& surface() const { return mSurface; } - Rect bounds() const { return Rect(width(), height()); } - uint32_t width() const { return surface().width; } - uint32_t height() const { return surface().height; } - uint32_t stride() const { return surface().stride; } - PixelFormat pixelFormat() const { return surface().format; } - void* serverBits() const { return surface().data; } - size_t size() const; - const sp<MemoryDealer>& getAllocator() const { return mAllocator; } - void getBitmapSurface(copybit_image_t* img) const; + sp<Buffer> allocate(); + sp<const Buffer> getBuffer() const { return mBuffer; } + sp<Buffer> getBuffer() { return mBuffer; } + + uint32_t getWidth() const { return mWidth; } + uint32_t getHeight() const { return mHeight; } + PixelFormat getPixelFormat() const { return mBuffer->getPixelFormat(); } + Rect getBounds() const { return mBuffer->getBounds(); } + private: - sp<MemoryDealer> mAllocator; - sp<IMemory> mBitsMemory; - uint32_t mAllocFlags; - ssize_t mOffset; - GGLSurface mSurface; - size_t mSize; - uint32_t mAlignment; + surface_info_t* mInfo; + sp<Buffer> mBuffer; + uint32_t mWidth; + uint32_t mHeight; + PixelFormat mFormat; + uint32_t mFlags; + // protects setSize() and allocate() + mutable Mutex mLock; }; }; // namespace android diff --git a/libs/surfaceflinger/LayerBlur.cpp b/libs/surfaceflinger/LayerBlur.cpp index d3e456f..3d22e3a 100644 --- a/libs/surfaceflinger/LayerBlur.cpp +++ b/libs/surfaceflinger/LayerBlur.cpp @@ -14,8 +14,6 @@ * limitations under the License. */ -#define LOG_TAG "SurfaceFlinger" - #include <stdlib.h> #include <stdint.h> #include <sys/types.h> @@ -49,8 +47,7 @@ LayerBlur::LayerBlur(SurfaceFlinger* flinger, DisplayID display, LayerBlur::~LayerBlur() { if (mTextureName != -1U) { - //glDeleteTextures(1, &mTextureName); - deletedTextures.add(mTextureName); + glDeleteTextures(1, &mTextureName); } } @@ -139,8 +136,9 @@ void LayerBlur::onDraw(const Region& clip) const glGenTextures(1, &mTextureName); } - Region::iterator iterator(clip); - if (iterator) { + Region::const_iterator it = clip.begin(); + Region::const_iterator const end = clip.end(); + if (it != end) { glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, mTextureName); @@ -201,27 +199,25 @@ void LayerBlur::onDraw(const Region& clip) const glEnableClientState(GL_TEXTURE_COORD_ARRAY); glVertexPointer(2, GL_FIXED, 0, mVertices); glTexCoordPointer(2, GL_FIXED, 0, mVertices); - Rect r; - while (iterator.iterate(&r)) { + while (it != end) { + const Rect& r = *it++; const GLint sy = fbHeight - (r.top + r.height()); glScissor(r.left, sy, r.width(), r.height()); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } } else { - Region::iterator iterator(clip); - if (iterator) { - // NOTE: this is marginally faster with the software gl, because - // glReadPixels() reads the fb bottom-to-top, however we'll - // skip all the jaccobian computations. - Rect r; - GLint crop[4] = { 0, 0, w, h }; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop); - y = fbHeight - (y + h); - while (iterator.iterate(&r)) { - const GLint sy = fbHeight - (r.top + r.height()); - glScissor(r.left, sy, r.width(), r.height()); - glDrawTexiOES(x, y, 0, w, h); - } + // NOTE: this is marginally faster with the software gl, because + // glReadPixels() reads the fb bottom-to-top, however we'll + // skip all the jaccobian computations. + Rect r; + GLint crop[4] = { 0, 0, w, h }; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop); + y = fbHeight - (y + h); + while (it != end) { + const Rect& r = *it++; + const GLint sy = fbHeight - (r.top + r.height()); + glScissor(r.left, sy, r.width(), r.height()); + glDrawTexiOES(x, y, 0, w, h); } } } diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp index bac544a..8be91c9 100644 --- a/libs/surfaceflinger/LayerBuffer.cpp +++ b/libs/surfaceflinger/LayerBuffer.cpp @@ -14,8 +14,6 @@ * limitations under the License. */ -#define LOG_TAG "SurfaceFlinger" - #include <stdlib.h> #include <stdint.h> #include <math.h> @@ -25,15 +23,10 @@ #include <utils/Log.h> #include <utils/StopWatch.h> -#include <binder/IPCThreadState.h> -#include <binder/IServiceManager.h> - #include <ui/PixelFormat.h> -#include <ui/EGLDisplaySurface.h> #include "LayerBuffer.h" #include "SurfaceFlinger.h" -#include "VRamHeap.h" #include "DisplayHardware/DisplayHardware.h" @@ -55,30 +48,23 @@ LayerBuffer::LayerBuffer(SurfaceFlinger* flinger, DisplayID display, LayerBuffer::~LayerBuffer() { - sp<SurfaceBuffer> s(getClientSurface()); - if (s != 0) { - s->disown(); - mClientSurface.clear(); - } } -sp<LayerBuffer::SurfaceBuffer> LayerBuffer::getClientSurface() const +void LayerBuffer::onFirstRef() { - Mutex::Autolock _l(mLock); - return mClientSurface.promote(); + mSurface = new SurfaceBuffer(mFlinger, clientIndex(), + const_cast<LayerBuffer *>(this)); } -sp<LayerBaseClient::Surface> LayerBuffer::getSurface() const +sp<LayerBaseClient::Surface> LayerBuffer::createSurface() const { - sp<SurfaceBuffer> s; - Mutex::Autolock _l(mLock); - s = mClientSurface.promote(); - if (s == 0) { - s = new SurfaceBuffer(clientIndex(), - const_cast<LayerBuffer *>(this)); - mClientSurface = s; - } - return s; + return mSurface; +} + +status_t LayerBuffer::ditch() +{ + mSurface.clear(); + return NO_ERROR; } bool LayerBuffer::needsBlending() const { @@ -192,82 +178,49 @@ sp<LayerBuffer::Source> LayerBuffer::clearSource() { // LayerBuffer::SurfaceBuffer // ============================================================================ -LayerBuffer::SurfaceBuffer::SurfaceBuffer(SurfaceID id, LayerBuffer* owner) -: LayerBaseClient::Surface(id, owner->getIdentity()), mOwner(owner) +LayerBuffer::SurfaceBuffer::SurfaceBuffer(const sp<SurfaceFlinger>& flinger, + SurfaceID id, const sp<LayerBuffer>& owner) + : LayerBaseClient::Surface(flinger, id, owner->getIdentity(), owner) { } LayerBuffer::SurfaceBuffer::~SurfaceBuffer() { unregisterBuffers(); - mOwner = 0; -} - -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) +status_t LayerBuffer::SurfaceBuffer::registerBuffers( + const ISurface::BufferHeap& buffers) { - LayerBuffer* owner(getOwner()); - if (owner) + sp<LayerBuffer> owner(getOwner()); + if (owner != 0) return owner->registerBuffers(buffers); return NO_INIT; } void LayerBuffer::SurfaceBuffer::postBuffer(ssize_t offset) { - LayerBuffer* owner(getOwner()); - if (owner) + sp<LayerBuffer> owner(getOwner()); + if (owner != 0) owner->postBuffer(offset); } void LayerBuffer::SurfaceBuffer::unregisterBuffers() { - LayerBuffer* owner(getOwner()); - if (owner) + sp<LayerBuffer> owner(getOwner()); + if (owner != 0) owner->unregisterBuffers(); } sp<OverlayRef> LayerBuffer::SurfaceBuffer::createOverlay( uint32_t w, uint32_t h, int32_t format) { sp<OverlayRef> result; - LayerBuffer* owner(getOwner()); - if (owner) + sp<LayerBuffer> owner(getOwner()); + if (owner != 0) result = owner->createOverlay(w, h, format); return result; } -void LayerBuffer::SurfaceBuffer::disown() -{ - Mutex::Autolock _l(mLock); - mOwner = 0; -} - // ============================================================================ // LayerBuffer::Buffer // ============================================================================ @@ -369,7 +322,7 @@ LayerBuffer::BufferSource::BufferSource(LayerBuffer& layer, LayerBuffer::BufferSource::~BufferSource() { if (mTextureName != -1U) { - LayerBase::deletedTextures.add(mTextureName); + glDeleteTextures(1, &mTextureName); } } @@ -427,125 +380,37 @@ bool LayerBuffer::BufferSource::transformed() const void LayerBuffer::BufferSource::onDraw(const Region& clip) const { - sp<Buffer> buffer(getBuffer()); + // FIXME: we should get a native buffer here + /* + sp<Buffer> ourBbuffer(getBuffer()); if (UNLIKELY(buffer == 0)) { // nothing to do, we don't have a buffer mLayer.clearWithOpenGL(clip); return; } - status_t err = NO_ERROR; - NativeBuffer src(buffer->getBuffer()); - const Rect& transformedBounds = mLayer.getTransformedBounds(); - const int can_use_copybit = mLayer.canUseCopybit(); - - if (can_use_copybit) { - const int src_width = src.crop.r - src.crop.l; - const int src_height = src.crop.b - src.crop.t; - int W = transformedBounds.width(); - int H = transformedBounds.height(); - if (mLayer.getOrientation() & Transform::ROT_90) { - int t(W); W=H; H=t; - } - - /* With LayerBuffer, it is likely that we'll have to rescale the - * surface, because this is often used for video playback or - * camera-preview. Since we want these operation as fast as possible - * we make sure we can use the 2D H/W even if it doesn't support - * the requested scale factor, in which case we perform the scaling - * in several passes. */ - - copybit_device_t* copybit = mLayer.mFlinger->getBlitEngine(); - const float min = copybit->get(copybit, COPYBIT_MINIFICATION_LIMIT); - const float mag = copybit->get(copybit, COPYBIT_MAGNIFICATION_LIMIT); - - float xscale = 1.0f; - if (src_width > W*min) xscale = 1.0f / min; - else if (src_width*mag < W) xscale = mag; - - float yscale = 1.0f; - if (src_height > H*min) yscale = 1.0f / min; - else if (src_height*mag < H) yscale = mag; - - if (UNLIKELY(xscale!=1.0f || yscale!=1.0f)) { - if (UNLIKELY(mTemporaryDealer == 0)) { - // allocate a memory-dealer for this the first time - mTemporaryDealer = mLayer.mFlinger->getSurfaceHeapManager() - ->createHeap(ISurfaceComposer::eHardware); - mTempBitmap.init(mTemporaryDealer); - } - - const int tmp_w = floorf(src_width * xscale); - const int tmp_h = floorf(src_height * yscale); - err = mTempBitmap.setBits(tmp_w, tmp_h, 1, src.img.format); - - if (LIKELY(err == NO_ERROR)) { - NativeBuffer tmp; - mTempBitmap.getBitmapSurface(&tmp.img); - tmp.crop.l = 0; - tmp.crop.t = 0; - tmp.crop.r = tmp.img.w; - tmp.crop.b = tmp.img.h; - - region_iterator tmp_it(Region(Rect(tmp.crop.r, tmp.crop.b))); - copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0); - copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF); - copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE); - err = copybit->stretch(copybit, - &tmp.img, &src.img, &tmp.crop, &src.crop, &tmp_it); - src = tmp; - } - } - - const DisplayHardware& hw(mLayer.graphicPlane(0).displayHardware()); - copybit_image_t dst; - hw.getDisplaySurface(&dst); - const copybit_rect_t& drect - = reinterpret_cast<const copybit_rect_t&>(transformedBounds); - const State& s(mLayer.drawingState()); - region_iterator it(clip); - - // pick the right orientation for this buffer - int orientation = mLayer.getOrientation(); - if (UNLIKELY(mBufferHeap.transform)) { - Transform rot90; - GraphicPlane::orientationToTransfrom( - ISurfaceComposer::eOrientation90, 0, 0, &rot90); - const Transform& planeTransform(mLayer.graphicPlane(0).transform()); - const Layer::State& s(mLayer.drawingState()); - Transform tr(planeTransform * s.transform * rot90); - orientation = tr.getOrientation(); - } - - copybit->set_parameter(copybit, COPYBIT_TRANSFORM, orientation); - copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha); - 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)); - } + // FIXME: We should model this after the overlay stuff + if (UNLIKELY(mTextureName == -1LU)) { + mTextureName = mLayer.createTexture(); } - if (!can_use_copybit || err) { - if (UNLIKELY(mTextureName == -1LU)) { - mTextureName = mLayer.createTexture(); - } + // FIXME: Use EGLImage extension for this + + + + GGLSurface t; + status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_RARELY); + if (res == NO_ERROR) { GLuint w = 0; GLuint h = 0; - GGLSurface t; - t.version = sizeof(GGLSurface); - t.width = src.crop.r; - t.height = src.crop.b; - t.stride = src.img.w; - t.vstride= src.img.h; - t.format = src.img.format; - t.data = (GGLubyte*)(intptr_t(src.img.base) + src.img.offset); - const Region dirty(Rect(t.width, t.height)); + const Region dirty(Rect(buffer->width, buffer->height)); mLayer.loadTexture(dirty, mTextureName, t, w, h); - mLayer.drawWithOpenGL(clip, mTextureName, t, mBufferHeap.transform); + buffer->unlock(); + } + if (res == NO_ERROR) { + mLayer.drawWithOpenGL(clip, mTextureName, buffer, mBufferHeap.transform); } + */ } diff --git a/libs/surfaceflinger/LayerBuffer.h b/libs/surfaceflinger/LayerBuffer.h index f74d6a1..22af43e 100644 --- a/libs/surfaceflinger/LayerBuffer.h +++ b/libs/surfaceflinger/LayerBuffer.h @@ -22,7 +22,6 @@ #include <binder/IMemory.h> #include <private/ui/LayerState.h> -#include <EGL/eglnatives.h> #include "LayerBase.h" #include "LayerBitmap.h" @@ -51,7 +50,6 @@ class LayerBuffer : public LayerBaseClient LayerBuffer& mLayer; }; - public: static const uint32_t typeInfo; static const char* const typeID; @@ -62,9 +60,11 @@ public: Client* client, int32_t i); virtual ~LayerBuffer(); + virtual void onFirstRef(); virtual bool needsBlending() const; - virtual sp<LayerBaseClient::Surface> getSurface() const; + virtual sp<LayerBaseClient::Surface> createSurface() const; + virtual status_t ditch(); virtual void onDraw(const Region& clip) const; virtual uint32_t doTransaction(uint32_t flags); virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion); @@ -126,8 +126,7 @@ private: status_t mStatus; ISurface::BufferHeap mBufferHeap; size_t mBufferSize; - mutable sp<MemoryDealer> mTemporaryDealer; - mutable LayerBitmap mTempBitmap; + mutable sp<android::Buffer> mTempBitmap; mutable GLuint mTextureName; }; @@ -179,34 +178,27 @@ private: class SurfaceBuffer : public LayerBaseClient::Surface { public: - SurfaceBuffer(SurfaceID id, LayerBuffer* owner); + SurfaceBuffer(const sp<SurfaceFlinger>& flinger, + SurfaceID id, const sp<LayerBuffer>& owner); virtual ~SurfaceBuffer(); - 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( uint32_t w, uint32_t h, int32_t format); - void disown(); private: - LayerBuffer* getOwner() const { - Mutex::Autolock _l(mLock); - return mOwner; + sp<LayerBuffer> getOwner() const { + return static_cast<LayerBuffer*>(Surface::getOwner().get()); } - mutable Mutex mLock; - LayerBuffer* mOwner; }; - - friend class SurfaceFlinger; - sp<SurfaceBuffer> getClientSurface() const; - + mutable Mutex mLock; sp<Source> mSource; - + sp<Surface> mSurface; bool mInvalidate; bool mNeedsBlending; - mutable wp<SurfaceBuffer> mClientSurface; }; // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/LayerDim.cpp b/libs/surfaceflinger/LayerDim.cpp index 0c347cc..c1e8ad6 100644 --- a/libs/surfaceflinger/LayerDim.cpp +++ b/libs/surfaceflinger/LayerDim.cpp @@ -14,8 +14,6 @@ * limitations under the License. */ -#define LOG_TAG "SurfaceFlinger" - #include <stdlib.h> #include <stdint.h> #include <sys/types.h> @@ -25,7 +23,6 @@ #include "LayerDim.h" #include "SurfaceFlinger.h" -#include "VRamHeap.h" #include "DisplayHardware/DisplayHardware.h" namespace android { @@ -33,8 +30,6 @@ namespace android { const uint32_t LayerDim::typeInfo = LayerBaseClient::typeInfo | 0x10; const char* const LayerDim::typeID = "LayerDim"; -sp<MemoryDealer> LayerDim::mDimmerDealer; -LayerBitmap LayerDim::mDimmerBitmap; // --------------------------------------------------------------------------- @@ -46,14 +41,6 @@ LayerDim::LayerDim(SurfaceFlinger* flinger, DisplayID display, void LayerDim::initDimmer(SurfaceFlinger* flinger, uint32_t w, uint32_t h) { - // must only be called once. - mDimmerDealer = flinger->getSurfaceHeapManager() - ->createHeap(ISurfaceComposer::eHardware); - if (mDimmerDealer != 0) { - mDimmerBitmap.init(mDimmerDealer); - mDimmerBitmap.setBits(w, h, 1, PIXEL_FORMAT_RGB_565); - mDimmerBitmap.clear(); - } } LayerDim::~LayerDim() @@ -62,48 +49,26 @@ LayerDim::~LayerDim() void LayerDim::onDraw(const Region& clip) const { + // FIXME: on some h/w (like msm7K, it will be faster to use a texture) + const State& s(drawingState()); - - Region::iterator iterator(clip); - if (s.alpha>0 && iterator) { + Region::const_iterator it = clip.begin(); + Region::const_iterator const end = clip.end(); + if (s.alpha>0 && (it != end)) { const DisplayHardware& hw(graphicPlane(0).displayHardware()); - - status_t err = NO_ERROR; - const int can_use_copybit = canUseCopybit(); - if (can_use_copybit) { - // StopWatch watch("copybit"); - copybit_image_t dst; - hw.getDisplaySurface(&dst); - const copybit_rect_t& drect - = reinterpret_cast<const copybit_rect_t&>(mTransformedBounds); - - copybit_image_t src; - mDimmerBitmap.getBitmapSurface(&src); - const copybit_rect_t& srect(drect); - - copybit_device_t* copybit = mFlinger->getBlitEngine(); - copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0); - copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha); - copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE); - region_iterator it(clip); - err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it); - } - - if (!can_use_copybit || err) { - const GGLfixed alpha = (s.alpha << 16)/255; - const uint32_t fbHeight = hw.getHeight(); - glDisable(GL_TEXTURE_2D); - glDisable(GL_DITHER); - glEnable(GL_BLEND); - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - glColor4x(0, 0, 0, alpha); - glVertexPointer(2, GL_FIXED, 0, mVertices); - Rect r; - while (iterator.iterate(&r)) { - const GLint sy = fbHeight - (r.top + r.height()); - glScissor(r.left, sy, r.width(), r.height()); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - } + const GGLfixed alpha = (s.alpha << 16)/255; + const uint32_t fbHeight = hw.getHeight(); + glDisable(GL_TEXTURE_2D); + glDisable(GL_DITHER); + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + glColor4x(0, 0, 0, alpha); + glVertexPointer(2, GL_FIXED, 0, mVertices); + while (it != end) { + const Rect& r = *it++; + const GLint sy = fbHeight - (r.top + r.height()); + glScissor(r.left, sy, r.width(), r.height()); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } } } diff --git a/libs/surfaceflinger/LayerDim.h b/libs/surfaceflinger/LayerDim.h index 3e37a47..0d5bb98 100644 --- a/libs/surfaceflinger/LayerDim.h +++ b/libs/surfaceflinger/LayerDim.h @@ -44,10 +44,6 @@ public: virtual bool isSecure() const { return false; } static void initDimmer(SurfaceFlinger* flinger, uint32_t w, uint32_t h); - -private: - static sp<MemoryDealer> mDimmerDealer; - static LayerBitmap mDimmerBitmap; }; // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/LayerScreenshot.cpp b/libs/surfaceflinger/LayerScreenshot.cpp deleted file mode 100644 index fb7b585..0000000 --- a/libs/surfaceflinger/LayerScreenshot.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/* - * 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 "LayerScreenshot.h" -#include "SurfaceFlinger.h" -#include "DisplayHardware/DisplayHardware.h" - -namespace android { -// --------------------------------------------------------------------------- - -const uint32_t LayerScreenshot::typeInfo = LayerBase::typeInfo | 0x20; -const char* const LayerScreenshot::typeID = "LayerScreenshot"; - -// --------------------------------------------------------------------------- - -LayerScreenshot::LayerScreenshot(SurfaceFlinger* flinger, DisplayID display) - : LayerBase(flinger, display), mReply(0) -{ -} - -LayerScreenshot::~LayerScreenshot() -{ -} - -void LayerScreenshot::onDraw(const Region& clip) const -{ - const DisplayHardware& hw(graphicPlane(0).displayHardware()); - copybit_image_t dst; - hw.getDisplaySurface(&dst); - if (dst.base != 0) { - uint8_t const* src = (uint8_t const*)(intptr_t(dst.base) + dst.offset); - const int fbWidth = dst.w; - const int fbHeight = dst.h; - const int fbFormat = dst.format; - - int x = mTransformedBounds.left; - int y = mTransformedBounds.top; - int w = mTransformedBounds.width(); - int h = mTransformedBounds.height(); - Parcel* const reply = mReply; - if (reply) { - const size_t Bpp = bytesPerPixel(fbFormat); - const size_t size = w * h * Bpp; - int32_t cfg = SkBitmap::kNo_Config; - switch (fbFormat) { - case PIXEL_FORMAT_RGBA_4444: cfg = SkBitmap::kARGB_4444_Config; break; - case PIXEL_FORMAT_RGBA_8888: cfg = SkBitmap::kARGB_8888_Config; break; - case PIXEL_FORMAT_RGB_565: cfg = SkBitmap::kRGB_565_Config; break; - case PIXEL_FORMAT_A_8: cfg = SkBitmap::kA8_Config; break; - } - reply->writeInt32(0); - reply->writeInt32(cfg); - reply->writeInt32(w); - reply->writeInt32(h); - reply->writeInt32(w * Bpp); - void* data = reply->writeInplace(size); - if (data) { - uint8_t* d = (uint8_t*)data; - uint8_t const* s = src + (x + y*fbWidth) * Bpp; - if (w == fbWidth) { - memcpy(d, s, w*h*Bpp); - } else { - for (int y=0 ; y<h ; y++) { - memcpy(d, s, w*Bpp); - d += w*Bpp; - s += fbWidth*Bpp; - } - } - } - } - } - mCV.broadcast(); -} - -void LayerScreenshot::takeScreenshot(Mutex& lock, Parcel* reply) -{ - mReply = reply; - mCV.wait(lock); -} - -// --------------------------------------------------------------------------- - -}; // namespace android diff --git a/libs/surfaceflinger/MessageQueue.cpp b/libs/surfaceflinger/MessageQueue.cpp new file mode 100644 index 0000000..a027e2b --- /dev/null +++ b/libs/surfaceflinger/MessageQueue.cpp @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdint.h> +#include <errno.h> +#include <sys/types.h> + +#include <utils/threads.h> +#include <utils/Timers.h> +#include <utils/Log.h> +#include <binder/IPCThreadState.h> + +#include "MessageQueue.h" + +namespace android { + +// --------------------------------------------------------------------------- + +void MessageList::insert(const sp<MessageBase>& node) +{ + LIST::iterator cur(mList.begin()); + LIST::iterator end(mList.end()); + while (cur != end) { + if (*node < **cur) { + mList.insert(cur, node); + return; + } + ++cur; + } + mList.insert(++end, node); +} + +void MessageList::remove(MessageList::LIST::iterator pos) +{ + mList.erase(pos); +} + +// --------------------------------------------------------------------------- + +MessageQueue::MessageQueue() +{ + mInvalidateMessage = new MessageBase(INVALIDATE); +} + +MessageQueue::~MessageQueue() +{ +} + +MessageList::value_type MessageQueue::waitMessage(nsecs_t timeout) +{ + MessageList::value_type result; + + bool again; + do { + const nsecs_t timeoutTime = systemTime() + timeout; + while (true) { + Mutex::Autolock _l(mLock); + nsecs_t now = systemTime(); + nsecs_t nextEventTime = -1; + + // invalidate messages are always handled first + if (mInvalidate) { + mInvalidate = false; + mInvalidateMessage->when = now; + result = mInvalidateMessage; + break; + } + + LIST::iterator cur(mMessages.begin()); + if (cur != mMessages.end()) { + result = *cur; + } + + if (result != 0) { + if (result->when <= now) { + // there is a message to deliver + mMessages.remove(cur); + break; + } + if (timeout>=0 && timeoutTime < now) { + // we timed-out, return a NULL message + result = 0; + break; + } + nextEventTime = result->when; + result = 0; + } + + if (timeout >= 0 && nextEventTime > 0) { + if (nextEventTime > timeoutTime) { + nextEventTime = timeoutTime; + } + } + + if (nextEventTime >= 0) { + //LOGD("nextEventTime = %lld ms", nextEventTime); + if (nextEventTime > 0) { + // we're about to wait, flush the binder command buffer + IPCThreadState::self()->flushCommands(); + mCondition.wait(mLock, nextEventTime); + } + } else { + //LOGD("going to wait"); + // we're about to wait, flush the binder command buffer + IPCThreadState::self()->flushCommands(); + mCondition.wait(mLock); + } + } + // here we're not holding the lock anymore + + if (result == 0) + break; + + again = result->handler(); + if (again) { + // the message has been processed. release our reference to it + // without holding the lock. + result = 0; + } + + } while (again); + + return result; +} + +status_t MessageQueue::postMessage( + const MessageList::value_type& message, nsecs_t relTime, uint32_t flags) +{ + return queueMessage(message, relTime, flags); +} + +status_t MessageQueue::invalidate() { + Mutex::Autolock _l(mLock); + mInvalidate = true; + mCondition.signal(); + return NO_ERROR; +} + +status_t MessageQueue::queueMessage( + const MessageList::value_type& message, nsecs_t relTime, uint32_t flags) +{ + Mutex::Autolock _l(mLock); + message->when = systemTime() + relTime; + mMessages.insert(message); + + //LOGD("MessageQueue::queueMessage time = %lld ms", message->when); + //dumpLocked(message); + + mCondition.signal(); + return NO_ERROR; +} + +void MessageQueue::dump(const MessageList::value_type& message) +{ + Mutex::Autolock _l(mLock); + dumpLocked(message); +} + +void MessageQueue::dumpLocked(const MessageList::value_type& message) +{ + LIST::const_iterator cur(mMessages.begin()); + LIST::const_iterator end(mMessages.end()); + int c = 0; + while (cur != end) { + const char tick = (*cur == message) ? '>' : ' '; + LOGD("%c %d: msg{.what=%08x, when=%lld}", + tick, c, (*cur)->what, (*cur)->when); + ++cur; + c++; + } +} + +// --------------------------------------------------------------------------- + +}; // namespace android diff --git a/libs/surfaceflinger/MessageQueue.h b/libs/surfaceflinger/MessageQueue.h new file mode 100644 index 0000000..dc8138d --- /dev/null +++ b/libs/surfaceflinger/MessageQueue.h @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2009 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_MESSAGE_QUEUE_H +#define ANDROID_MESSAGE_QUEUE_H + +#include <stdint.h> +#include <errno.h> +#include <sys/types.h> + +#include <utils/threads.h> +#include <utils/Timers.h> +#include <utils/List.h> + + +namespace android { + +// --------------------------------------------------------------------------- + +class MessageBase; + +class MessageList +{ + List< sp<MessageBase> > mList; + typedef List< sp<MessageBase> > LIST; +public: + typedef sp<MessageBase> value_type; + inline LIST::iterator begin() { return mList.begin(); } + inline LIST::const_iterator begin() const { return mList.begin(); } + inline LIST::iterator end() { return mList.end(); } + inline LIST::const_iterator end() const { return mList.end(); } + inline bool isEmpty() const { return mList.empty(); } + void insert(const sp<MessageBase>& node); + void remove(LIST::iterator pos); +}; + +// ============================================================================ + +class MessageBase : + public LightRefBase<MessageBase> +{ +public: + nsecs_t when; + uint32_t what; + int32_t arg0; + + MessageBase() : when(0), what(0), arg0(0) { } + MessageBase(uint32_t what, int32_t arg0=0) + : when(0), what(what), arg0(arg0) { } + + // return true if message has a handler + virtual bool handler() { return false; } + +protected: + virtual ~MessageBase() { } + +private: + friend class LightRefBase<MessageBase>; +}; + +inline bool operator < (const MessageBase& lhs, const MessageBase& rhs) { + return lhs.when < rhs.when; +} + +// --------------------------------------------------------------------------- + +class MessageQueue +{ + typedef List< sp<MessageBase> > LIST; +public: + + // this is a work-around the multichar constant warning. A macro would + // work too, but would pollute the namespace. + template <int a, int b, int c, int d> + struct WHAT { + static const uint32_t Value = + (uint32_t(a&0xff)<<24)|(uint32_t(b&0xff)<<16)| + (uint32_t(c&0xff)<<8)|uint32_t(d&0xff); + }; + + MessageQueue(); + ~MessageQueue(); + + // pre-defined messages + enum { + INVALIDATE = WHAT<'_','p','d','t'>::Value + }; + + MessageList::value_type waitMessage(nsecs_t timeout = -1); + + status_t postMessage(const MessageList::value_type& message, + nsecs_t reltime=0, uint32_t flags = 0); + + status_t invalidate(); + + void dump(const MessageList::value_type& message); + +private: + status_t queueMessage(const MessageList::value_type& message, + nsecs_t reltime, uint32_t flags); + void dumpLocked(const MessageList::value_type& message); + + Mutex mLock; + Condition mCondition; + MessageList mMessages; + bool mInvalidate; + MessageList::value_type mInvalidateMessage; +}; + +// --------------------------------------------------------------------------- + +}; // namespace android + +#endif /* ANDROID_MESSAGE_QUEUE_H */ diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp index efaf016..70f34a1 100644 --- a/libs/surfaceflinger/SurfaceFlinger.cpp +++ b/libs/surfaceflinger/SurfaceFlinger.cpp @@ -14,8 +14,6 @@ * limitations under the License. */ -#define LOG_TAG "SurfaceFlinger" - #include <stdlib.h> #include <stdio.h> #include <stdint.h> @@ -41,26 +39,20 @@ #include <ui/PixelFormat.h> #include <ui/DisplayInfo.h> -#include <ui/EGLDisplaySurface.h> #include <pixelflinger/pixelflinger.h> #include <GLES/gl.h> #include "clz.h" -#include "CPUGauge.h" +#include "BufferAllocator.h" #include "Layer.h" #include "LayerBlur.h" #include "LayerBuffer.h" #include "LayerDim.h" #include "LayerBitmap.h" -#include "LayerOrientationAnim.h" -#include "OrientationAnimation.h" #include "SurfaceFlinger.h" -#include "VRamHeap.h" #include "DisplayHardware/DisplayHardware.h" -#include "GPUHardware/GPUHardware.h" - /* ideally AID_GRAPHICS would be in a semi-public header * or there would be a way to map a user/group name to its id @@ -94,30 +86,30 @@ SurfaceFlinger::LayerVector::LayerVector(const SurfaceFlinger::LayerVector& rhs) } ssize_t SurfaceFlinger::LayerVector::indexOf( - LayerBase* key, size_t guess) const + const sp<LayerBase>& key, size_t guess) const { if (guess<size() && lookup.keyAt(guess) == key) return guess; const ssize_t i = lookup.indexOfKey(key); if (i>=0) { const size_t idx = lookup.valueAt(i); - LOG_ASSERT(layers[idx]==key, + LOGE_IF(layers[idx]!=key, "LayerVector[%p]: layers[%d]=%p, key=%p", - this, int(idx), layers[idx], key); + this, int(idx), layers[idx].get(), key.get()); return idx; } return i; } ssize_t SurfaceFlinger::LayerVector::add( - LayerBase* layer, - Vector<LayerBase*>::compar_t cmp) + const sp<LayerBase>& layer, + Vector< sp<LayerBase> >::compar_t cmp) { size_t count = layers.size(); ssize_t l = 0; ssize_t h = count-1; ssize_t mid; - LayerBase* const* a = layers.array(); + sp<LayerBase> const* a = layers.array(); while (l <= h) { mid = l + (h - l)/2; const int c = cmp(a+mid, &layer); @@ -140,14 +132,14 @@ ssize_t SurfaceFlinger::LayerVector::add( return order; } -ssize_t SurfaceFlinger::LayerVector::remove(LayerBase* layer) +ssize_t SurfaceFlinger::LayerVector::remove(const sp<LayerBase>& layer) { const ssize_t keyIndex = lookup.indexOfKey(layer); if (keyIndex >= 0) { const size_t index = lookup.valueAt(keyIndex); - LOG_ASSERT(layers[index]==layer, + LOGE_IF(layers[index]!=layer, "LayerVector[%p]: layers[%u]=%p, layer=%p", - this, int(index), layers[index], layer); + this, int(index), layers[index].get(), layer.get()); layers.removeItemsAt(index); lookup.removeItemsAt(keyIndex); const size_t count = lookup.size(); @@ -162,8 +154,8 @@ ssize_t SurfaceFlinger::LayerVector::remove(LayerBase* layer) } ssize_t SurfaceFlinger::LayerVector::reorder( - LayerBase* layer, - Vector<LayerBase*>::compar_t cmp) + const sp<LayerBase>& layer, + Vector< sp<LayerBase> >::compar_t cmp) { // XXX: it's a little lame. but oh well... ssize_t err = remove(layer); @@ -181,6 +173,7 @@ SurfaceFlinger::SurfaceFlinger() : BnSurfaceComposer(), Thread(false), mTransactionFlags(0), mTransactionCount(0), + mLayersRemoved(false), mBootTime(systemTime()), mLastScheduledBroadcast(NULL), mVisibleRegionsDirty(false), @@ -189,11 +182,7 @@ SurfaceFlinger::SurfaceFlinger() mFreezeCount(0), mFreezeDisplayTime(0), mDebugRegion(0), - mDebugCpu(0), - mDebugFps(0), mDebugBackground(0), - mSyncObject(), - mDeplayedTransactionPending(0), mConsoleSignals(0), mSecureFrameBuffer(0) { @@ -208,28 +197,16 @@ void SurfaceFlinger::init() char value[PROPERTY_VALUE_MAX]; property_get("debug.sf.showupdates", value, "0"); mDebugRegion = atoi(value); - property_get("debug.sf.showcpu", value, "0"); - mDebugCpu = atoi(value); property_get("debug.sf.showbackground", value, "0"); mDebugBackground = atoi(value); - property_get("debug.sf.showfps", value, "0"); - mDebugFps = atoi(value); LOGI_IF(mDebugRegion, "showupdates enabled"); - LOGI_IF(mDebugCpu, "showcpu enabled"); LOGI_IF(mDebugBackground, "showbackground enabled"); - LOGI_IF(mDebugFps, "showfps enabled"); } SurfaceFlinger::~SurfaceFlinger() { glDeleteTextures(1, &mWormholeTexName); - delete mOrientationAnimation; -} - -copybit_device_t* SurfaceFlinger::getBlitEngine() const -{ - return graphicPlane(0).displayHardware().getBlitEngine(); } overlay_control_device_t* SurfaceFlinger::getOverlayEngine() const @@ -242,26 +219,6 @@ sp<IMemory> SurfaceFlinger::getCblk() const return mServerCblkMemory; } -status_t SurfaceFlinger::requestGPU(const sp<IGPUCallback>& callback, - gpu_info_t* gpu) -{ - if (mGPU == 0) - return INVALID_OPERATION; - - IPCThreadState* ipc = IPCThreadState::self(); - const int pid = ipc->getCallingPid(); - status_t err = mGPU->request(pid, callback, gpu); - return err; -} - -status_t SurfaceFlinger::revokeGPU() -{ - if (mGPU == 0) - return INVALID_OPERATION; - - return mGPU->friendlyRevoke(); -} - sp<ISurfaceFlingerClient> SurfaceFlinger::createConnection() { Mutex::Autolock _l(mStateLock); @@ -289,11 +246,13 @@ void SurfaceFlinger::destroyConnection(ClientID cid) Client* const client = mClientsMap.valueFor(cid); if (client) { // free all the layers this client owns - const Vector<LayerBaseClient*>& layers = client->getLayers(); + const Vector< wp<LayerBaseClient> >& layers = client->getLayers(); const size_t count = layers.size(); for (size_t i=0 ; i<count ; i++) { - LayerBaseClient* const layer = layers[i]; - removeLayer_l(layer); + sp<LayerBaseClient> layer(layers[i].promote()); + if (layer != 0) { + removeLayer_l(layer); + } } // the resources associated with this client will be freed @@ -345,9 +304,6 @@ static inline uint16_t pack565(int r, int g, int b) { return (r<<11)|(g<<5)|b; } -// this is defined in libGLES_CM.so -extern ISurfaceComposer* GLES_localSurfaceManager; - status_t SurfaceFlinger::readyToRun() { LOGI( "SurfaceFlinger's main thread ready to run. " @@ -364,17 +320,6 @@ status_t SurfaceFlinger::readyToRun() LOGE_IF(mServerCblk==0, "can't get to shared control block's address"); new(mServerCblk) surface_flinger_cblk_t; - // get a reference to the GPU if we have one - mGPU = GPUFactory::getGPU(); - - // create the surface Heap manager, which manages the heaps - // (be it in RAM or VRAM) where surfaces are allocated - // We give 8 MB per client. - mSurfaceHeapManager = new SurfaceHeapManager(this, 8 << 20); - - - GLES_localSurfaceManager = static_cast<ISurfaceComposer*>(this); - // we only support one display currently int dpy = 0; @@ -451,13 +396,6 @@ 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)); - - // start boot animation property_set("ctl.start", "bootanim"); @@ -472,45 +410,53 @@ status_t SurfaceFlinger::readyToRun() void SurfaceFlinger::waitForEvent() { - // wait for something to do - if (UNLIKELY(isFrozen())) { - // wait 5 seconds - const nsecs_t freezeDisplayTimeout = ms2ns(5000); - const nsecs_t now = systemTime(); - if (mFreezeDisplayTime == 0) { - mFreezeDisplayTime = now; + while (true) { + nsecs_t timeout = -1; + if (UNLIKELY(isFrozen())) { + // wait 5 seconds + const nsecs_t freezeDisplayTimeout = ms2ns(5000); + const nsecs_t now = systemTime(); + if (mFreezeDisplayTime == 0) { + mFreezeDisplayTime = now; + } + nsecs_t waitTime = freezeDisplayTimeout - (now - mFreezeDisplayTime); + timeout = waitTime>0 ? waitTime : 0; } - nsecs_t waitTime = freezeDisplayTimeout - (now - mFreezeDisplayTime); - int err = (waitTime > 0) ? mSyncObject.wait(waitTime) : TIMED_OUT; - if (err != NO_ERROR) { + + MessageList::value_type msg = mEventQueue.waitMessage(timeout); + if (msg != 0) { + mFreezeDisplayTime = 0; + switch (msg->what) { + case MessageQueue::INVALIDATE: + // invalidate message, just return to the main loop + return; + } + } else { + // we timed out if (isFrozen()) { // we timed out and are still frozen LOGW("timeout expired mFreezeDisplay=%d, mFreezeCount=%d", mFreezeDisplay, mFreezeCount); mFreezeCount = 0; mFreezeDisplay = false; + return; } } - } else { - mFreezeDisplayTime = 0; - mSyncObject.wait(); } } void SurfaceFlinger::signalEvent() { - mSyncObject.open(); + mEventQueue.invalidate(); } void SurfaceFlinger::signal() const { - mSyncObject.open(); + // this is the IPC call + const_cast<SurfaceFlinger*>(this)->signalEvent(); } void SurfaceFlinger::signalDelayedEvent(nsecs_t delay) { - if (android_atomic_or(1, &mDeplayedTransactionPending) == 0) { - sp<DelayedTransaction> delayedEvent(new DelayedTransaction(this, delay)); - delayedEvent->run("DelayedeEvent", PRIORITY_URGENT_DISPLAY); - } + mEventQueue.postMessage( new MessageBase(MessageQueue::INVALIDATE), delay); } // ---------------------------------------------------------------------------- @@ -549,11 +495,6 @@ bool SurfaceFlinger::threadLoop() unlockClients(); executeScheduledBroadcasts(); - // sample the cpu gauge - if (UNLIKELY(mDebugCpu)) { - handleDebugCpu(); - } - postFramebuffer(); } else { // pretend we did the post @@ -566,28 +507,18 @@ bool SurfaceFlinger::threadLoop() void SurfaceFlinger::postFramebuffer() { - const bool skip = mOrientationAnimation->run(); - if (UNLIKELY(skip)) { + if (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; } if (!mInvalidRegion.isEmpty()) { const DisplayHardware& hw(graphicPlane(0).displayHardware()); - - if (UNLIKELY(mDebugFps)) { - debugShowFPS(); - } - hw.flip(mInvalidRegion); - mInvalidRegion.clear(); - - if (Layer::deletedTextures.size()) { - glDeleteTextures( - Layer::deletedTextures.size(), - Layer::deletedTextures.array()); - Layer::deletedTextures.clear(); - } } } @@ -602,15 +533,13 @@ void SurfaceFlinger::handleConsoleEvents() } if (mDeferReleaseConsole && hw.canDraw()) { - // We got the release signal before the aquire signal + // We got the release signal before the acquire signal mDeferReleaseConsole = false; - revokeGPU(); hw.releaseScreen(); } if (what & eConsoleReleased) { if (hw.canDraw()) { - revokeGPU(); hw.releaseScreen(); } else { mDeferReleaseConsole = true; @@ -635,7 +564,7 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) const bool layersNeedTransaction = transactionFlags & eTraversalNeeded; if (layersNeedTransaction) { for (size_t i=0 ; i<count ; i++) { - LayerBase* const layer = currentLayers[i]; + const sp<LayerBase>& layer = currentLayers[i]; uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded); if (!trFlags) continue; @@ -682,7 +611,6 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) mVisibleRegionsDirty = true; mDirtyRegion.set(hw.bounds()); mFreezeDisplayTime = 0; - mOrientationAnimation->onOrientationChanged(type); } if (mCurrentState.freezeDisplay != mDrawingState.freezeDisplay) { @@ -690,17 +618,26 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) mFreezeDisplay = mCurrentState.freezeDisplay; } - // some layers might have been removed, so - // we need to update the regions they're exposing. - size_t c = mRemovedLayers.size(); - if (c) { + if (currentLayers.size() > mDrawingState.layersSortedByZ.size()) { + // layers have been added mVisibleRegionsDirty = true; } - const LayerVector& currentLayers = mCurrentState.layersSortedByZ; - if (currentLayers.size() > mDrawingState.layersSortedByZ.size()) { - // layers have been added + // some layers might have been removed, so + // we need to update the regions they're exposing. + if (mLayersRemoved) { mVisibleRegionsDirty = true; + const LayerVector& previousLayers(mDrawingState.layersSortedByZ); + const ssize_t count = previousLayers.size(); + for (ssize_t i=0 ; i<count ; i++) { + const sp<LayerBase>& layer(previousLayers[i]); + if (currentLayers.indexOf( layer ) < 0) { + // this layer is not visible anymore + // FIXME: would be better to call without the lock held + //LOGD("ditching layer %p", layer.get()); + layer->ditch(); + } + } } // get rid of all resources we don't need anymore @@ -730,7 +667,7 @@ void SurfaceFlinger::computeVisibleRegions( size_t i = currentLayers.size(); while (i--) { - LayerBase* const layer = currentLayers[i]; + const sp<LayerBase>& layer = currentLayers[i]; layer->validateVisibility(planeTransform); // start with the whole surface at its current location @@ -782,7 +719,7 @@ void SurfaceFlinger::computeVisibleRegions( // accumulate to the screen dirty region dirtyRegion.orSelf(dirty); - // updade aboveOpaqueLayers/aboveCoveredLayers for next (lower) layer + // Update aboveOpaqueLayers/aboveCoveredLayers for next (lower) layer aboveOpaqueLayers.orSelf(opaqueRegion); aboveCoveredLayers.orSelf(bounds); @@ -790,7 +727,7 @@ void SurfaceFlinger::computeVisibleRegions( layer->setVisibleRegion(visibleRegion); layer->setCoveredRegion(coveredRegion); - // If a secure layer is partially visible, lockdown the screen! + // If a secure layer is partially visible, lock down the screen! if (layer->isSecure() && !visibleRegion.isEmpty()) { secureFrameBuffer = true; } @@ -830,9 +767,9 @@ bool SurfaceFlinger::lockPageFlip(const LayerVector& currentLayers) { bool recomputeVisibleRegions = false; size_t count = currentLayers.size(); - LayerBase* const* layers = currentLayers.array(); + sp<LayerBase> const* layers = currentLayers.array(); for (size_t i=0 ; i<count ; i++) { - LayerBase* const layer = layers[i]; + const sp<LayerBase>& layer = layers[i]; layer->lockPageFlip(recomputeVisibleRegions); } return recomputeVisibleRegions; @@ -843,9 +780,9 @@ void SurfaceFlinger::unlockPageFlip(const LayerVector& currentLayers) const GraphicPlane& plane(graphicPlane(0)); const Transform& planeTransform(plane.transform()); size_t count = currentLayers.size(); - LayerBase* const* layers = currentLayers.array(); + sp<LayerBase> const* layers = currentLayers.array(); for (size_t i=0 ; i<count ; i++) { - LayerBase* const layer = layers[i]; + const sp<LayerBase>& layer = layers[i]; layer->unlockPageFlip(planeTransform, mDirtyRegion); } } @@ -865,12 +802,14 @@ void SurfaceFlinger::handleRepaint() mInvalidRegion.orSelf(mDirtyRegion); uint32_t flags = hw.getFlags(); - if (flags & DisplayHardware::BUFFER_PRESERVED) { - // here we assume DisplayHardware::flip()'s implementation - // performs the copy-back optimization. + if ((flags & DisplayHardware::SWAP_RECTANGLE) || + (flags & DisplayHardware::BUFFER_PRESERVED)) + { + // we can redraw only what's dirty } else { if (flags & DisplayHardware::UPDATE_ON_DEMAND) { - // we need to fully redraw the part that will be updated + // we need to redraw the rectangle that will be updated + // (pushed to the framebuffer). mDirtyRegion.set(mInvalidRegion.bounds()); } else { // we need to redraw everything @@ -896,9 +835,9 @@ void SurfaceFlinger::composeSurfaces(const Region& dirty) const SurfaceFlinger& flinger(*this); const LayerVector& drawingLayers(mDrawingState.layersSortedByZ); const size_t count = drawingLayers.size(); - LayerBase const* const* const layers = drawingLayers.array(); + sp<LayerBase> const* const layers = drawingLayers.array(); for (size_t i=0 ; i<count ; ++i) { - LayerBase const * const layer = layers[i]; + const sp<LayerBase>& layer = layers[i]; const Region& visibleRegion(layer->visibleRegionScreen); if (!visibleRegion.isEmpty()) { const Region clip(dirty.intersect(visibleRegion)); @@ -913,9 +852,9 @@ void SurfaceFlinger::unlockClients() { const LayerVector& drawingLayers(mDrawingState.layersSortedByZ); const size_t count = drawingLayers.size(); - LayerBase* const* const layers = drawingLayers.array(); + sp<LayerBase> const* const layers = drawingLayers.array(); for (size_t i=0 ; i<count ; ++i) { - LayerBase* const layer = layers[i]; + const sp<LayerBase>& layer = layers[i]; layer->finishPageFlip(); } } @@ -948,32 +887,35 @@ void SurfaceFlinger::executeScheduledBroadcasts() mLastScheduledBroadcast = 0; } -void SurfaceFlinger::handleDebugCpu() -{ - Mutex::Autolock _l(mDebugLock); - if (mCpuGauge != 0) - mCpuGauge->sample(); -} - void SurfaceFlinger::debugFlashRegions() { - if (UNLIKELY(!mDirtyRegion.isRect())) { - // TODO: do this only if we don't have preserving - // swapBuffer. If we don't have update-on-demand, - // redraw everything. - composeSurfaces(Region(mDirtyRegion.bounds())); - } + const DisplayHardware& hw(graphicPlane(0).displayHardware()); + const uint32_t flags = hw.getFlags(); + if (!((flags & DisplayHardware::SWAP_RECTANGLE) || + (flags & DisplayHardware::BUFFER_PRESERVED))) { + const Region repaint((flags & DisplayHardware::UPDATE_ON_DEMAND) ? + mDirtyRegion.bounds() : hw.bounds()); + composeSurfaces(repaint); + } + glDisable(GL_TEXTURE_2D); glDisable(GL_BLEND); glDisable(GL_DITHER); glDisable(GL_SCISSOR_TEST); - glColor4x(0x10000, 0, 0x10000, 0x10000); + static int toggle = 0; + toggle = 1 - toggle; + if (toggle) { + glColor4x(0x10000, 0, 0x10000, 0x10000); + } else { + glColor4x(0x10000, 0x10000, 0, 0x10000); + } - Rect r; - Region::iterator iterator(mDirtyRegion); - while (iterator.iterate(&r)) { + Region::const_iterator it = mDirtyRegion.begin(); + Region::const_iterator const end = mDirtyRegion.end(); + while (it != end) { + const Rect& r = *it++; GLfloat vertices[][2] = { { r.left, r.top }, { r.left, r.bottom }, @@ -983,8 +925,7 @@ void SurfaceFlinger::debugFlashRegions() glVertexPointer(2, GL_FLOAT, 0, vertices); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } - - const DisplayHardware& hw(graphicPlane(0).displayHardware()); + hw.flip(mDirtyRegion.merge(mInvalidRegion)); mInvalidRegion.clear(); @@ -1010,9 +951,10 @@ void SurfaceFlinger::drawWormhole() const if (LIKELY(!mDebugBackground)) { glClearColorx(0,0,0,0); - Rect r; - Region::iterator iterator(region); - while (iterator.iterate(&r)) { + Region::const_iterator it = region.begin(); + Region::const_iterator const end = region.end(); + while (it != end) { + const Rect& r = *it++; const GLint sy = height - (r.top + r.height()); glScissor(r.left, sy, r.width(), r.height()); glClear(GL_COLOR_BUFFER_BIT); @@ -1030,9 +972,10 @@ void SurfaceFlinger::drawWormhole() const glMatrixMode(GL_TEXTURE); glLoadIdentity(); glScalef(width*(1.0f/32.0f), height*(1.0f/32.0f), 1); - Rect r; - Region::iterator iterator(region); - while (iterator.iterate(&r)) { + Region::const_iterator it = region.begin(); + Region::const_iterator const end = region.end(); + while (it != end) { + const Rect& r = *it++; const GLint sy = height - (r.top + r.height()); glScissor(r.left, sy, r.width(), r.height()); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); @@ -1058,7 +1001,7 @@ void SurfaceFlinger::debugShowFPS() const // XXX: mFPS has the value we want } -status_t SurfaceFlinger::addLayer(LayerBase* layer) +status_t SurfaceFlinger::addLayer(const sp<LayerBase>& layer) { Mutex::Autolock _l(mStateLock); addLayer_l(layer); @@ -1066,7 +1009,7 @@ status_t SurfaceFlinger::addLayer(LayerBase* layer) return NO_ERROR; } -status_t SurfaceFlinger::removeLayer(LayerBase* layer) +status_t SurfaceFlinger::removeLayer(const sp<LayerBase>& layer) { Mutex::Autolock _l(mStateLock); removeLayer_l(layer); @@ -1074,48 +1017,60 @@ status_t SurfaceFlinger::removeLayer(LayerBase* layer) return NO_ERROR; } -status_t SurfaceFlinger::invalidateLayerVisibility(LayerBase* layer) +status_t SurfaceFlinger::invalidateLayerVisibility(const sp<LayerBase>& layer) { layer->forceVisibilityTransaction(); setTransactionFlags(eTraversalNeeded); return NO_ERROR; } -status_t SurfaceFlinger::addLayer_l(LayerBase* layer) +status_t SurfaceFlinger::addLayer_l(const sp<LayerBase>& layer) { ssize_t i = mCurrentState.layersSortedByZ.add( layer, &LayerBase::compareCurrentStateZ); - LayerBaseClient* lbc = LayerBase::dynamicCast<LayerBaseClient*>(layer); - if (lbc) { + sp<LayerBaseClient> lbc = LayerBase::dynamicCast< LayerBaseClient* >(layer.get()); + if (lbc != 0) { mLayerMap.add(lbc->serverIndex(), lbc); } - mRemovedLayers.remove(layer); return NO_ERROR; } -status_t SurfaceFlinger::removeLayer_l(LayerBase* layerBase) +status_t SurfaceFlinger::removeLayer_l(const sp<LayerBase>& layerBase) { ssize_t index = mCurrentState.layersSortedByZ.remove(layerBase); if (index >= 0) { - mRemovedLayers.add(layerBase); - LayerBaseClient* layer = LayerBase::dynamicCast<LayerBaseClient*>(layerBase); - if (layer) { + mLayersRemoved = true; + sp<LayerBaseClient> layer = + LayerBase::dynamicCast< LayerBaseClient* >(layerBase.get()); + if (layer != 0) { mLayerMap.removeItem(layer->serverIndex()); } return NO_ERROR; } // it's possible that we don't find a layer, because it might // have been destroyed already -- this is not technically an error - // from the user because there is a race between destroySurface, - // destroyclient and destroySurface-from-a-transaction. + // from the user because there is a race between BClient::destroySurface(), + // ~BClient() and destroySurface-from-a-transaction. return (index == NAME_NOT_FOUND) ? status_t(NO_ERROR) : index; } +status_t SurfaceFlinger::purgatorizeLayer_l(const sp<LayerBase>& layerBase) +{ + // First add the layer to the purgatory list, which makes sure it won't + // go away, then remove it from the main list (through a transaction). + ssize_t err = removeLayer_l(layerBase); + if (err >= 0) { + mLayerPurgatory.add(layerBase); + } + return (err == NAME_NOT_FOUND) ? status_t(NO_ERROR) : err; +} + + void SurfaceFlinger::free_resources_l() { // Destroy layers that were removed - destroy_all_removed_layers_l(); - + mLayersRemoved = false; + // free resources associated with disconnected clients SortedVector<Client*>& scheduledBroadcasts(mScheduledBroadcasts); Vector<Client*>& disconnectedClients(mDisconnectedClients); @@ -1135,22 +1090,6 @@ void SurfaceFlinger::free_resources_l() disconnectedClients.clear(); } -void SurfaceFlinger::destroy_all_removed_layers_l() -{ - size_t c = mRemovedLayers.size(); - while (c--) { - LayerBase* const removed_layer = mRemovedLayers[c]; - - LOGE_IF(mCurrentState.layersSortedByZ.indexOf(removed_layer) >= 0, - "layer %p removed but still in the current state list", - removed_layer); - - delete removed_layer; - } - mRemovedLayers.clear(); -} - - uint32_t SurfaceFlinger::getTransactionFlags(uint32_t flags) { return android_atomic_and(~flags, &mTransactionFlags) & flags; @@ -1191,7 +1130,7 @@ status_t SurfaceFlinger::freezeDisplay(DisplayID dpy, uint32_t flags) setTransactionFlags(eTransactionNeeded); // flags is intended to communicate some sort of animation behavior - // (for instance fadding) + // (for instance fading) return NO_ERROR; } @@ -1205,7 +1144,7 @@ status_t SurfaceFlinger::unfreezeDisplay(DisplayID dpy, uint32_t flags) setTransactionFlags(eTransactionNeeded); // flags is intended to communicate some sort of animation behavior - // (for instance fadding) + // (for instance fading) return NO_ERROR; } @@ -1234,7 +1173,7 @@ sp<ISurface> SurfaceFlinger::createSurface(ClientID clientId, int pid, DisplayID d, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) { - LayerBaseClient* layer = 0; + sp<LayerBaseClient> layer; sp<LayerBaseClient::Surface> surfaceHandle; Mutex::Autolock _l(mStateLock); Client* const c = mClientsMap.valueFor(clientId); @@ -1266,7 +1205,7 @@ sp<ISurface> SurfaceFlinger::createSurface(ClientID clientId, int pid, break; } - if (layer) { + if (layer != 0) { setTransactionFlags(eTransactionNeeded); surfaceHandle = layer->getSurface(); if (surfaceHandle != 0) @@ -1276,7 +1215,7 @@ sp<ISurface> SurfaceFlinger::createSurface(ClientID clientId, int pid, return surfaceHandle; } -LayerBaseClient* SurfaceFlinger::createNormalSurfaceLocked( +sp<LayerBaseClient> SurfaceFlinger::createNormalSurfaceLocked( Client* client, DisplayID display, int32_t id, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) { @@ -1291,57 +1230,92 @@ LayerBaseClient* SurfaceFlinger::createNormalSurfaceLocked( break; } - Layer* layer = new Layer(this, display, client, id); + sp<Layer> layer = new Layer(this, display, client, id); status_t err = layer->setBuffers(client, w, h, format, flags); if (LIKELY(err == NO_ERROR)) { layer->initStates(w, h, flags); addLayer_l(layer); } else { LOGE("createNormalSurfaceLocked() failed (%s)", strerror(-err)); - delete layer; - return 0; + layer.clear(); } return layer; } -LayerBaseClient* SurfaceFlinger::createBlurSurfaceLocked( +sp<LayerBaseClient> SurfaceFlinger::createBlurSurfaceLocked( Client* client, DisplayID display, int32_t id, uint32_t w, uint32_t h, uint32_t flags) { - LayerBlur* layer = new LayerBlur(this, display, client, id); + sp<LayerBlur> layer = new LayerBlur(this, display, client, id); layer->initStates(w, h, flags); addLayer_l(layer); return layer; } -LayerBaseClient* SurfaceFlinger::createDimSurfaceLocked( +sp<LayerBaseClient> SurfaceFlinger::createDimSurfaceLocked( Client* client, DisplayID display, int32_t id, uint32_t w, uint32_t h, uint32_t flags) { - LayerDim* layer = new LayerDim(this, display, client, id); + sp<LayerDim> layer = new LayerDim(this, display, client, id); layer->initStates(w, h, flags); addLayer_l(layer); return layer; } -LayerBaseClient* SurfaceFlinger::createPushBuffersSurfaceLocked( +sp<LayerBaseClient> SurfaceFlinger::createPushBuffersSurfaceLocked( Client* client, DisplayID display, int32_t id, uint32_t w, uint32_t h, uint32_t flags) { - LayerBuffer* layer = new LayerBuffer(this, display, client, id); + sp<LayerBuffer> layer = new LayerBuffer(this, display, client, id); layer->initStates(w, h, flags); addLayer_l(layer); return layer; } -status_t SurfaceFlinger::destroySurface(SurfaceID index) +status_t SurfaceFlinger::removeSurface(SurfaceID index) { + /* + * called by the window manager, when a surface should be marked for + * destruction. + * + * The surface is removed from the current and drawing lists, but placed + * in the purgatory queue, so it's not destroyed right-away (we need + * to wait for all client's references to go away first). + */ + Mutex::Autolock _l(mStateLock); - LayerBaseClient* const layer = getLayerUser_l(index); - status_t err = removeLayer_l(layer); - if (err < 0) - return err; - setTransactionFlags(eTransactionNeeded); + sp<LayerBaseClient> layer = getLayerUser_l(index); + status_t err = purgatorizeLayer_l(layer); + if (err == NO_ERROR) { + setTransactionFlags(eTransactionNeeded); + } + return err; +} + +status_t SurfaceFlinger::destroySurface(const sp<LayerBaseClient>& layer) +{ + /* + * called by ~ISurface() when all references are gone + * + * the surface must be removed from purgatory from the main thread + * since its dtor must run from there (b/c of OpenGL ES). + */ + + class MessageDestroySurface : public MessageBase { + SurfaceFlinger* flinger; + sp<LayerBaseClient> layer; + public: + MessageDestroySurface( + SurfaceFlinger* flinger, const sp<LayerBaseClient>& layer) + : flinger(flinger), layer(layer) { } + virtual bool handler() { + Mutex::Autolock _l(flinger->mStateLock); + ssize_t idx = flinger->mLayerPurgatory.remove(layer); + LOGE_IF(idx<0, "layer=%p is not in the purgatory list", layer.get()); + return true; + } + }; + mEventQueue.postMessage( new MessageDestroySurface(this, layer) ); return NO_ERROR; } @@ -1355,8 +1329,8 @@ status_t SurfaceFlinger::setClientState( cid <<= 16; for (int i=0 ; i<count ; i++) { const layer_state_t& s = states[i]; - LayerBaseClient* layer = getLayerUser_l(s.surface | cid); - if (layer) { + const sp<LayerBaseClient>& layer = getLayerUser_l(s.surface | cid); + if (layer != 0) { const uint32_t what = s.what; // check if it has been destroyed first if (what & eDestroyed) { @@ -1408,9 +1382,10 @@ status_t SurfaceFlinger::setClientState( return NO_ERROR; } -LayerBaseClient* SurfaceFlinger::getLayerUser_l(SurfaceID s) const +sp<LayerBaseClient> SurfaceFlinger::getLayerUser_l(SurfaceID s) const { - return mLayerMap.valueFor(s); + sp<LayerBaseClient> layer = mLayerMap.valueFor(s); + return layer; } void SurfaceFlinger::screenReleased(int dpy) @@ -1453,7 +1428,7 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) const size_t count = currentLayers.size(); for (size_t i=0 ; i<count ; i++) { /*** LayerBase ***/ - LayerBase const * const layer = currentLayers[i]; + const sp<LayerBase>& layer = currentLayers[i]; const Layer::State& s = layer->drawingState(); snprintf(buffer, SIZE, "+ %s %p\n" @@ -1461,7 +1436,7 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) "z=%9d, pos=(%4d,%4d), size=(%4d,%4d), " "needsBlending=%1d, invalidate=%1d, " "alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n", - layer->getTypeID(), layer, + layer->getTypeID(), layer.get(), s.z, layer->tx(), layer->ty(), s.w, s.h, layer->needsBlending(), layer->contentDirty, s.alpha, s.flags, @@ -1470,9 +1445,9 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) result.append(buffer); buffer[0] = 0; /*** LayerBaseClient ***/ - LayerBaseClient* const lbc = - LayerBase::dynamicCast<LayerBaseClient*>((LayerBase*)layer); - if (lbc) { + sp<LayerBaseClient> lbc = + LayerBase::dynamicCast< LayerBaseClient* >(layer.get()); + if (lbc != 0) { snprintf(buffer, SIZE, " " "id=0x%08x, client=0x%08x, identity=%u\n", @@ -1482,18 +1457,20 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) result.append(buffer); buffer[0] = 0; /*** Layer ***/ - Layer* const l = LayerBase::dynamicCast<Layer*>((LayerBase*)layer); - if (l) { + sp<Layer> l = LayerBase::dynamicCast< Layer* >(layer.get()); + if (l != 0) { const LayerBitmap& buf0(l->getBuffer(0)); const LayerBitmap& buf1(l->getBuffer(1)); snprintf(buffer, SIZE, " " - "format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u], mTextureName=%d," + "format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u]," " freezeLock=%p, swapState=0x%08x\n", l->pixelFormat(), - buf0.width(), buf0.height(), buf0.stride(), - buf1.width(), buf1.height(), buf1.stride(), - l->getTextureName(), l->getFreezeLock().get(), + buf0.getWidth(), buf0.getHeight(), + buf0.getBuffer()->getStride(), + buf1.getWidth(), buf1.getHeight(), + buf1.getBuffer()->getStride(), + l->getFreezeLock().get(), l->lcblk->swapState); } result.append(buffer); @@ -1510,19 +1487,8 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) mCurrentState.orientation, hw.canDraw()); result.append(buffer); - sp<AllocatorInterface> allocator; - if (mGPU != 0) { - snprintf(buffer, SIZE, " GPU owner: %d\n", mGPU->getOwner()); - result.append(buffer); - allocator = mGPU->getAllocator(); - if (allocator != 0) { - allocator->dump(result, "GPU Allocator"); - } - } - allocator = mSurfaceHeapManager->getAllocator(NATIVE_MEMORY_TYPE_PMEM); - if (allocator != 0) { - allocator->dump(result, "PMEM Allocator"); - } + const BufferAllocator& alloc(BufferAllocator::get()); + alloc.dump(result); } write(fd, result.string(), result.size()); return NO_ERROR; @@ -1539,7 +1505,6 @@ status_t SurfaceFlinger::onTransact( case FREEZE_DISPLAY: case UNFREEZE_DISPLAY: case BOOT_FINISHED: - case REVOKE_GPU: { // codes that require permission check IPCThreadState* ipc = IPCThreadState::self(); @@ -1572,24 +1537,9 @@ status_t SurfaceFlinger::onTransact( } int n; switch (code) { - case 1000: // SHOW_CPU - n = data.readInt32(); - mDebugCpu = n ? 1 : 0; - if (mDebugCpu) { - if (mCpuGauge == 0) { - mCpuGauge = new CPUGauge(this, ms2ns(500)); - } - } else { - if (mCpuGauge != 0) { - mCpuGauge->requestExitAndWait(); - Mutex::Autolock _l(mDebugLock); - mCpuGauge.clear(); - } - } + case 1000: // SHOW_CPU, NOT SUPPORTED ANYMORE return NO_ERROR; - case 1001: // SHOW_FPS - n = data.readInt32(); - mDebugFps = n ? 1 : 0; + case 1001: // SHOW_FPS, NOT SUPPORTED ANYMORE return NO_ERROR; case 1002: // SHOW_UPDATES n = data.readInt32(); @@ -1606,21 +1556,11 @@ status_t SurfaceFlinger::onTransact( signalEvent(); } return NO_ERROR; - case 1005: // ask GPU revoke - if (mGPU != 0) { - mGPU->friendlyRevoke(); - } - return NO_ERROR; - case 1006: // revoke GPU - if (mGPU != 0) { - mGPU->unconditionalRevoke(); - } - return NO_ERROR; case 1007: // set mFreezeCount mFreezeCount = data.readInt32(); return NO_ERROR; case 1010: // interrogate. - reply->writeInt32(mDebugCpu); + reply->writeInt32(0); reply->writeInt32(0); reply->writeInt32(mDebugRegion); reply->writeInt32(mDebugBackground); @@ -1644,7 +1584,6 @@ status_t SurfaceFlinger::onTransact( Client::Client(ClientID clientID, const sp<SurfaceFlinger>& flinger) : ctrlblk(0), cid(clientID), mPid(0), mBitmap(0), mFlinger(flinger) { - mSharedHeapAllocator = getSurfaceHeapManager()->createHeap(); const int pgsize = getpagesize(); const int cblksize=((sizeof(per_client_cblk_t)+(pgsize-1))&~(pgsize-1)); mCblkHeap = new MemoryDealer(cblksize); @@ -1664,10 +1603,6 @@ Client::~Client() { } } -const sp<SurfaceHeapManager>& Client::getSurfaceHeapManager() const { - return mFlinger->getSurfaceHeapManager(); -} - int32_t Client::generateId(int pid) { const uint32_t i = clz( ~mBitmap ); @@ -1679,13 +1614,15 @@ int32_t Client::generateId(int pid) mBitmap |= 1<<(31-i); return i; } -status_t Client::bindLayer(LayerBaseClient* layer, int32_t id) + +status_t Client::bindLayer(const sp<LayerBaseClient>& layer, int32_t id) { ssize_t idx = mInUse.indexOf(id); if (idx < 0) return NAME_NOT_FOUND; return mLayers.insertAt(layer, idx); } + void Client::free(int32_t id) { ssize_t idx = mInUse.remove(uint8_t(id)); @@ -1695,27 +1632,18 @@ void Client::free(int32_t id) } } -sp<MemoryDealer> Client::createAllocator(uint32_t flags) -{ - sp<MemoryDealer> allocator; - allocator = getSurfaceHeapManager()->createHeap( - flags, getClientPid(), mSharedHeapAllocator); - return allocator; -} - bool Client::isValid(int32_t i) const { return (uint32_t(i)<NUM_LAYERS_MAX) && (mBitmap & (1<<(31-i))); } -const uint8_t* Client::inUseArray() const { - return mInUse.array(); -} -size_t Client::numActiveLayers() const { - return mInUse.size(); -} -LayerBaseClient* Client::getLayerUser(int32_t i) const { + +sp<LayerBaseClient> Client::getLayerUser(int32_t i) const { + sp<LayerBaseClient> lbc; ssize_t idx = mInUse.indexOf(uint8_t(i)); - if (idx<0) return 0; - return mLayers[idx]; + if (idx >= 0) { + lbc = mLayers[idx].promote(); + LOGE_IF(lbc==0, "getLayerUser(i=%d), idx=%d is dead", int(i), int(idx)); + } + return lbc; } void Client::dump(const char* what) @@ -1752,7 +1680,7 @@ sp<ISurface> BClient::createSurface( status_t BClient::destroySurface(SurfaceID sid) { sid |= (mId << 16); // add the client-part to id - return mFlinger->destroySurface(sid); + return mFlinger->removeSurface(sid); } status_t BClient::setState(int32_t count, const layer_state_t* states) @@ -1852,6 +1780,10 @@ const Transform& GraphicPlane::transform() const { return mGlobalTransform; } +EGLDisplay GraphicPlane::getEGLDisplay() const { + return mHw->getEGLDisplay(); +} + // --------------------------------------------------------------------------- }; // namespace android diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/libs/surfaceflinger/SurfaceFlinger.h index 126bce8..6bbb21f 100644 --- a/libs/surfaceflinger/SurfaceFlinger.h +++ b/libs/surfaceflinger/SurfaceFlinger.h @@ -26,6 +26,7 @@ #include <utils/Atomic.h> #include <utils/Errors.h> #include <binder/MemoryDealer.h> +#include <utils/RefBase.h> #include <ui/PixelFormat.h> #include <ui/ISurfaceComposer.h> @@ -33,13 +34,13 @@ #include <private/ui/SharedState.h> #include <private/ui/LayerState.h> -#include <private/ui/SurfaceFlingerSynchro.h> #include "Barrier.h" -#include "CPUGauge.h" #include "Layer.h" #include "Tokenizer.h" +#include "MessageQueue.h" + struct copybit_device_t; struct overlay_device_t; @@ -51,13 +52,8 @@ class Client; class BClient; class DisplayHardware; class FreezeLock; -class GPUHardwareInterface; -class IGPUCallback; class Layer; class LayerBuffer; -class LayerOrientationAnim; -class OrientationAnimation; -class SurfaceHeapManager; typedef int32_t ClientID; @@ -74,17 +70,13 @@ public: int32_t generateId(int pid); void free(int32_t id); - status_t bindLayer(LayerBaseClient* layer, int32_t id); - sp<MemoryDealer> createAllocator(uint32_t memory_type); + status_t bindLayer(const sp<LayerBaseClient>& layer, int32_t id); inline bool isValid(int32_t i) const; - inline const uint8_t* inUseArray() const; - inline size_t numActiveLayers() const; - LayerBaseClient* getLayerUser(int32_t i) const; - const Vector<LayerBaseClient*>& getLayers() const { return mLayers; } + sp<LayerBaseClient> getLayerUser(int32_t i) const; + const Vector< wp<LayerBaseClient> >& getLayers() const { return mLayers; } const sp<IMemory>& controlBlockMemory() const { return mCblkMemory; } void dump(const char* what); - const sp<SurfaceHeapManager>& getSurfaceHeapManager() const; // pointer to this client's control block per_client_cblk_t* ctrlblk; @@ -94,15 +86,13 @@ public: private: int getClientPid() const { return mPid; } - int mPid; - uint32_t mBitmap; - SortedVector<uint8_t> mInUse; - Vector<LayerBaseClient*> mLayers; - sp<MemoryDealer> mCblkHeap; - sp<SurfaceFlinger> mFlinger; - sp<MemoryDealer> mSharedHeapAllocator; - sp<MemoryDealer> mPMemAllocator; - sp<IMemory> mCblkMemory; + int mPid; + uint32_t mBitmap; + SortedVector<uint8_t> mInUse; + Vector< wp<LayerBaseClient> > mLayers; + sp<MemoryDealer> mCblkHeap; + sp<SurfaceFlinger> mFlinger; + sp<IMemory> mCblkMemory; }; // --------------------------------------------------------------------------- @@ -125,6 +115,8 @@ public: const DisplayHardware& displayHardware() const; const Transform& transform() const; + EGLDisplay getEGLDisplay() const; + private: GraphicPlane(const GraphicPlane&); GraphicPlane operator = (const GraphicPlane&); @@ -168,28 +160,16 @@ public: virtual status_t unfreezeDisplay(DisplayID dpy, uint32_t flags); virtual int setOrientation(DisplayID dpy, int orientation, uint32_t flags); virtual void signal() const; - virtual status_t requestGPU(const sp<IGPUCallback>& callback, - gpu_info_t* gpu); - virtual status_t revokeGPU(); void screenReleased(DisplayID dpy); void screenAcquired(DisplayID dpy); - const sp<SurfaceHeapManager>& getSurfaceHeapManager() const { - return mSurfaceHeapManager; - } - - const sp<GPUHardwareInterface>& getGPU() const { - return mGPU; - } - - 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); + status_t removeLayer(const sp<LayerBase>& layer); + status_t addLayer(const sp<LayerBase>& layer); + status_t invalidateLayerVisibility(const sp<LayerBase>& layer); private: friend class BClient; @@ -204,20 +184,26 @@ private: DisplayID display, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags); - LayerBaseClient* createNormalSurfaceLocked(Client* client, DisplayID display, - int32_t id, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags); + sp<LayerBaseClient> createNormalSurfaceLocked( + Client* client, DisplayID display, + int32_t id, uint32_t w, uint32_t h, + PixelFormat format, uint32_t flags); - LayerBaseClient* createBlurSurfaceLocked(Client* client, DisplayID display, + sp<LayerBaseClient> createBlurSurfaceLocked( + Client* client, DisplayID display, int32_t id, uint32_t w, uint32_t h, uint32_t flags); - LayerBaseClient* createDimSurfaceLocked(Client* client, DisplayID display, + sp<LayerBaseClient> createDimSurfaceLocked( + Client* client, DisplayID display, int32_t id, uint32_t w, uint32_t h, uint32_t flags); - LayerBaseClient* createPushBuffersSurfaceLocked(Client* client, DisplayID display, + sp<LayerBaseClient> createPushBuffersSurfaceLocked( + Client* client, DisplayID display, int32_t id, uint32_t w, uint32_t h, uint32_t flags); - status_t destroySurface(SurfaceID surface_id); - status_t setClientState(ClientID cid, int32_t count, const layer_state_t* states); + status_t removeSurface(SurfaceID surface_id); + status_t destroySurface(const sp<LayerBaseClient>& layer); + status_t setClientState(ClientID cid, int32_t count, const layer_state_t* states); class LayerVector { @@ -225,15 +211,15 @@ private: inline LayerVector() { } LayerVector(const LayerVector&); inline size_t size() const { return layers.size(); } - inline LayerBase*const* array() const { return layers.array(); } - ssize_t add(LayerBase*, Vector<LayerBase*>::compar_t); - ssize_t remove(LayerBase*); - ssize_t reorder(LayerBase*, Vector<LayerBase*>::compar_t); - ssize_t indexOf(LayerBase* key, size_t guess=0) const; - inline LayerBase* operator [] (size_t i) const { return layers[i]; } + inline sp<LayerBase> const* array() const { return layers.array(); } + ssize_t add(const sp<LayerBase>&, Vector< sp<LayerBase> >::compar_t); + ssize_t remove(const sp<LayerBase>&); + ssize_t reorder(const sp<LayerBase>&, Vector< sp<LayerBase> >::compar_t); + ssize_t indexOf(const sp<LayerBase>& key, size_t guess=0) const; + inline sp<LayerBase> operator [] (size_t i) const { return layers[i]; } private: - KeyedVector<LayerBase*, size_t> lookup; - Vector<LayerBase*> layers; + KeyedVector< sp<LayerBase> , size_t> lookup; + Vector< sp<LayerBase> > layers; }; struct State { @@ -247,25 +233,6 @@ private: uint8_t freezeDisplay; }; - class DelayedTransaction : public Thread - { - friend class SurfaceFlinger; - sp<SurfaceFlinger> mFlinger; - nsecs_t mDelay; - public: - DelayedTransaction(const sp<SurfaceFlinger>& flinger, nsecs_t delay) - : Thread(false), mFlinger(flinger), mDelay(delay) { - } - virtual bool threadLoop() { - usleep(mDelay / 1000); - if (android_atomic_and(~1, - &mFlinger->mDeplayedTransactionPending) == 1) { - mFlinger->signalEvent(); - } - return false; - } - }; - virtual bool threadLoop(); virtual status_t readyToRun(); virtual void onFirstRef(); @@ -289,7 +256,6 @@ private: bool lockPageFlip(const LayerVector& currentLayers); void unlockPageFlip(const LayerVector& currentLayers); void handleRepaint(); - void handleDebugCpu(); void scheduleBroadcast(Client* client); void executeScheduledBroadcasts(); void postFramebuffer(); @@ -298,10 +264,10 @@ private: void destroyConnection(ClientID cid); - LayerBaseClient* getLayerUser_l(SurfaceID index) const; - status_t addLayer_l(LayerBase* layer); - status_t removeLayer_l(LayerBase* layer); - void destroy_all_removed_layers_l(); + sp<LayerBaseClient> getLayerUser_l(SurfaceID index) const; + status_t addLayer_l(const sp<LayerBase>& layer); + status_t removeLayer_l(const sp<LayerBase>& layer); + status_t purgatorizeLayer_l(const sp<LayerBase>& layer); void free_resources_l(); uint32_t getTransactionFlags(uint32_t flags); @@ -323,6 +289,11 @@ private: void debugShowFPS() const; void drawWormhole() const; + + mutable MessageQueue mEventQueue; + + + // access must be protected by mStateLock mutable Mutex mStateLock; State mCurrentState; @@ -330,21 +301,21 @@ private: volatile int32_t mTransactionFlags; volatile int32_t mTransactionCount; Condition mTransactionCV; + SortedVector< sp<LayerBase> > mLayerPurgatory; + // protected by mStateLock (but we could use another lock) Tokenizer mTokens; DefaultKeyedVector<ClientID, Client*> mClientsMap; - DefaultKeyedVector<SurfaceID, LayerBaseClient*> mLayerMap; + DefaultKeyedVector<SurfaceID, sp<LayerBaseClient> > mLayerMap; GraphicPlane mGraphicPlanes[1]; - SortedVector<LayerBase*> mRemovedLayers; + bool mLayersRemoved; Vector<Client*> mDisconnectedClients; // constant members (no synchronization needed for access) sp<MemoryDealer> mServerHeap; sp<IMemory> mServerCblkMemory; surface_flinger_cblk_t* mServerCblk; - sp<SurfaceHeapManager> mSurfaceHeapManager; - sp<GPUHardwareInterface> mGPU; GLuint mWormholeTexName; nsecs_t mBootTime; @@ -360,23 +331,13 @@ private: bool mFreezeDisplay; int32_t mFreezeCount; nsecs_t mFreezeDisplayTime; - friend class OrientationAnimation; - OrientationAnimation* mOrientationAnimation; - - // access protected by mDebugLock - mutable Mutex mDebugLock; - sp<CPUGauge> mCpuGauge; // don't use a lock for these, we don't care int mDebugRegion; - int mDebugCpu; - int mDebugFps; int mDebugBackground; // these are thread safe mutable Barrier mReadyToRunBarrier; - mutable SurfaceFlingerSynchro mSyncObject; - volatile int32_t mDeplayedTransactionPending; // atomic variables enum { diff --git a/libs/surfaceflinger/Tokenizer.cpp b/libs/surfaceflinger/Tokenizer.cpp index ef51d6a..be3a239 100644 --- a/libs/surfaceflinger/Tokenizer.cpp +++ b/libs/surfaceflinger/Tokenizer.cpp @@ -162,9 +162,10 @@ void Tokenizer::dump() const { const run_t* ranges = mRanges.array(); const size_t c = mRanges.size(); - printf("Tokenizer (%p, size = %lu)\n", this, c); + printf("Tokenizer (%p, size = %d)\n", this, int(c)); for (size_t i=0 ; i<c ; i++) { - printf("%lu: (%u, %u)\n", i, ranges[i].first, ranges[i].length); + printf("%u: (%u, %u)\n", i, + uint32_t(ranges[i].first), uint32_t(ranges[i].length)); } } diff --git a/libs/surfaceflinger/Transform.cpp b/libs/surfaceflinger/Transform.cpp index e8b0f45..1501536 100644 --- a/libs/surfaceflinger/Transform.cpp +++ b/libs/surfaceflinger/Transform.cpp @@ -177,10 +177,10 @@ Region Transform::transform(const Region& reg) const Region out; if (UNLIKELY(transformed())) { if (LIKELY(preserveRects())) { - Rect r; - Region::iterator iterator(reg); - while (iterator.iterate(&r)) { - out.orSelf(transform(r)); + Region::const_iterator it = reg.begin(); + Region::const_iterator const end = reg.end(); + while (it != end) { + out.orSelf(transform(*it++)); } } else { out.set(transform(reg.bounds())); diff --git a/libs/surfaceflinger/LayerOrientationAnim.cpp b/libs/surfaceflinger/purgatory/LayerOrientationAnim.cpp index 3e4035e..41c42d1 100644 --- a/libs/surfaceflinger/LayerOrientationAnim.cpp +++ b/libs/surfaceflinger/purgatory/LayerOrientationAnim.cpp @@ -24,10 +24,6 @@ #include <utils/Log.h> #include <utils/StopWatch.h> -#include <core/SkBitmap.h> - -#include <ui/EGLDisplaySurface.h> - #include "BlurFilter.h" #include "LayerBase.h" #include "LayerOrientationAnim.h" @@ -57,8 +53,8 @@ const float DIM_TARGET = 0.40f; LayerOrientationAnim::LayerOrientationAnim( SurfaceFlinger* flinger, DisplayID display, OrientationAnimation* anim, - const LayerBitmap& bitmapIn, - const LayerBitmap& bitmapOut) + const sp<Buffer>& bitmapIn, + const sp<Buffer>& bitmapOut) : LayerOrientationAnimBase(flinger, display), mAnim(anim), mBitmapIn(bitmapIn), mBitmapOut(bitmapOut), mTextureName(-1), mTextureNameIn(-1) @@ -77,10 +73,10 @@ LayerOrientationAnim::LayerOrientationAnim( LayerOrientationAnim::~LayerOrientationAnim() { if (mTextureName != -1U) { - LayerBase::deletedTextures.add(mTextureName); + glDeleteTextures(1, &mTextureName); } if (mTextureNameIn != -1U) { - LayerBase::deletedTextures.add(mTextureNameIn); + glDeleteTextures(1, &mTextureNameIn); } } @@ -108,11 +104,6 @@ void LayerOrientationAnim::validateVisibility(const Transform&) mTop = tr.ty(); transparentRegionScreen.clear(); mTransformed = true; - mCanUseCopyBit = false; - copybit_device_t* copybit = mFlinger->getBlitEngine(); - if (copybit) { - mCanUseCopyBit = true; - } } void LayerOrientationAnim::onOrientationCompleted() @@ -135,7 +126,7 @@ void LayerOrientationAnim::onDraw(const Region& clip) const // make a copy of what's on screen copybit_image_t image; - mBitmapOut.getBitmapSurface(&image); + mBitmapOut->getBitmapSurface(&image); const DisplayHardware& hw(graphicPlane(0).displayHardware()); hw.copyBackToImage(image); @@ -194,7 +185,7 @@ void LayerOrientationAnim::drawScaled(float scale, float alphaIn, float alphaOut copybit_image_t dst; const GraphicPlane& plane(graphicPlane(0)); const DisplayHardware& hw(plane.displayHardware()); - hw.getDisplaySurface(&dst); + //hw.getDisplaySurface(&dst); // clear screen // TODO: with update on demand, we may be able @@ -212,10 +203,10 @@ void LayerOrientationAnim::drawScaled(float scale, float alphaIn, float alphaOut } copybit_image_t src; - mBitmapIn.getBitmapSurface(&src); + mBitmapIn->getBitmapSurface(&src); copybit_image_t srcOut; - mBitmapOut.getBitmapSurface(&srcOut); + mBitmapOut->getBitmapSurface(&srcOut); const int w = dst.w*scale; const int h = dst.h*scale; @@ -225,78 +216,54 @@ void LayerOrientationAnim::drawScaled(float scale, float alphaIn, float alphaOut const copybit_rect_t srect = { 0, 0, src.w, src.h }; const Region reg(Rect( drect.l, drect.t, drect.r, drect.b )); - 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 (alphaIn > 0) { - region_iterator it(reg); - copybit->set_parameter(copybit, COPYBIT_BLUR, COPYBIT_ENABLE); - copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, int(alphaIn*255)); - err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it); - } + 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); - if (!err && alphaOut > 0.0f) { - region_iterator it(reg); - copybit->set_parameter(copybit, COPYBIT_BLUR, COPYBIT_DISABLE); - copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, int(alphaOut*255)); - err = copybit->stretch(copybit, &dst, &srcOut, &drect, &srect, &it); - } - LOGE_IF(err != NO_ERROR, "copybit failed (%s)", strerror(err)); + Transform tr; + tr.set(scale,0,0,scale); + 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 (!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(scale,0,0,scale); - 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 (alphaIn > 0.0f) { - 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 = int(alphaIn*255); - drawWithOpenGL(reg, mTextureNameIn, t); + if (alphaIn > 0.0f) { + 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 = int(alphaIn*255); + drawWithOpenGL(reg, mTextureNameIn, t); + } - if (alphaOut > 0.0f) { - t.data = (GGLubyte*)(intptr_t(srcOut.base) + srcOut.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(alphaOut*255); - drawWithOpenGL(reg, mTextureName, t); + if (alphaOut > 0.0f) { + t.data = (GGLubyte*)(intptr_t(srcOut.base) + srcOut.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(alphaOut*255); + drawWithOpenGL(reg, mTextureName, t); } } diff --git a/libs/surfaceflinger/LayerOrientationAnim.h b/libs/surfaceflinger/purgatory/LayerOrientationAnim.h index e86156d..a1a2654 100644 --- a/libs/surfaceflinger/LayerOrientationAnim.h +++ b/libs/surfaceflinger/purgatory/LayerOrientationAnim.h @@ -52,8 +52,8 @@ public: LayerOrientationAnim(SurfaceFlinger* flinger, DisplayID display, OrientationAnimation* anim, - const LayerBitmap& bitmapIn, - const LayerBitmap& bitmapOut); + const sp<Buffer>& bitmapIn, + const sp<Buffer>& bitmapOut); virtual ~LayerOrientationAnim(); void onOrientationCompleted(); @@ -90,8 +90,8 @@ private: }; OrientationAnimation* mAnim; - LayerBitmap mBitmapIn; - LayerBitmap mBitmapOut; + sp<Buffer> mBitmapIn; + sp<Buffer> mBitmapOut; nsecs_t mStartTime; nsecs_t mFinishTime; bool mOrientationCompleted; diff --git a/libs/surfaceflinger/LayerOrientationAnimRotate.cpp b/libs/surfaceflinger/purgatory/LayerOrientationAnimRotate.cpp index 89ffb19..dc6b632 100644 --- a/libs/surfaceflinger/LayerOrientationAnimRotate.cpp +++ b/libs/surfaceflinger/purgatory/LayerOrientationAnimRotate.cpp @@ -23,10 +23,6 @@ #include <utils/Errors.h> #include <utils/Log.h> -#include <core/SkBitmap.h> - -#include <ui/EGLDisplaySurface.h> - #include "LayerBase.h" #include "LayerOrientationAnim.h" #include "LayerOrientationAnimRotate.h" @@ -51,10 +47,10 @@ const float BOUNCES_AMPLITUDE = (5.0f/180.f) * M_PI; LayerOrientationAnimRotate::LayerOrientationAnimRotate( SurfaceFlinger* flinger, DisplayID display, OrientationAnimation* anim, - const LayerBitmap& bitmap, - const LayerBitmap& bitmapIn) + const sp<Buffer>& bitmapIn, + const sp<Buffer>& bitmapOut) : LayerOrientationAnimBase(flinger, display), mAnim(anim), - mBitmap(bitmap), mBitmapIn(bitmapIn), + mBitmapIn(bitmapIn), mBitmapOut(bitmapOut), mTextureName(-1), mTextureNameIn(-1) { mStartTime = systemTime(); @@ -72,10 +68,10 @@ LayerOrientationAnimRotate::LayerOrientationAnimRotate( LayerOrientationAnimRotate::~LayerOrientationAnimRotate() { if (mTextureName != -1U) { - LayerBase::deletedTextures.add(mTextureName); + glDeleteTextures(1, &mTextureName); } if (mTextureNameIn != -1U) { - LayerBase::deletedTextures.add(mTextureNameIn); + glDeleteTextures(1, &mTextureNameIn); } } @@ -103,7 +99,6 @@ void LayerOrientationAnimRotate::validateVisibility(const Transform&) mTop = tr.ty(); transparentRegionScreen.clear(); mTransformed = true; - mCanUseCopyBit = false; } void LayerOrientationAnimRotate::onOrientationCompleted() @@ -126,7 +121,7 @@ void LayerOrientationAnimRotate::onDraw(const Region& clip) const if (mFirstRedraw) { // make a copy of what's on screen copybit_image_t image; - mBitmapIn.getBitmapSurface(&image); + mBitmapIn->getBitmapSurface(&image); const DisplayHardware& hw(graphicPlane(0).displayHardware()); hw.copyBackToImage(image); @@ -185,7 +180,7 @@ void LayerOrientationAnimRotate::drawScaled(float f, float s, float alpha) const copybit_image_t dst; const GraphicPlane& plane(graphicPlane(0)); const DisplayHardware& hw(plane.displayHardware()); - hw.getDisplaySurface(&dst); + //hw.getDisplaySurface(&dst); // clear screen // TODO: with update on demand, we may be able @@ -200,7 +195,7 @@ void LayerOrientationAnimRotate::drawScaled(float f, float s, float alpha) const const int h = dst.h; copybit_image_t src; - mBitmap.getBitmapSurface(&src); + mBitmapIn->getBitmapSurface(&src); const copybit_rect_t srect = { 0, 0, src.w, src.h }; @@ -255,7 +250,7 @@ void LayerOrientationAnimRotate::drawScaled(float f, float s, float alpha) const tr.transform(self.mVertices[3], src.w, 0); copybit_image_t src; - mBitmapIn.getBitmapSurface(&src); + mBitmapIn->getBitmapSurface(&src); t.data = (GGLubyte*)(intptr_t(src.base) + src.offset); if (UNLIKELY(mTextureNameIn == -1LU)) { mTextureNameIn = createTexture(); diff --git a/libs/surfaceflinger/LayerOrientationAnimRotate.h b/libs/surfaceflinger/purgatory/LayerOrientationAnimRotate.h index 3296f45..a88eec0 100644 --- a/libs/surfaceflinger/LayerOrientationAnimRotate.h +++ b/libs/surfaceflinger/purgatory/LayerOrientationAnimRotate.h @@ -40,8 +40,8 @@ public: LayerOrientationAnimRotate(SurfaceFlinger* flinger, DisplayID display, OrientationAnimation* anim, - const LayerBitmap& zoomOut, - const LayerBitmap& zoomIn); + const sp<Buffer>& bitmapIn, + const sp<Buffer>& bitmapOut); virtual ~LayerOrientationAnimRotate(); void onOrientationCompleted(); @@ -55,8 +55,8 @@ private: void drawScaled(float angle, float scale, float alpha) const; OrientationAnimation* mAnim; - LayerBitmap mBitmap; - LayerBitmap mBitmapIn; + sp<Buffer> mBitmapIn; + sp<Buffer> mBitmapOut; nsecs_t mStartTime; nsecs_t mFinishTime; bool mOrientationCompleted; diff --git a/libs/surfaceflinger/OrientationAnimation.cpp b/libs/surfaceflinger/purgatory/OrientationAnimation.cpp index 70eec8d..a6c9c28 100644 --- a/libs/surfaceflinger/OrientationAnimation.cpp +++ b/libs/surfaceflinger/purgatory/OrientationAnimation.cpp @@ -14,8 +14,6 @@ * limitations under the License. */ -#define LOG_TAG "SurfaceFlinger" - #include <stdint.h> #include <sys/types.h> #include <limits.h> @@ -24,7 +22,6 @@ #include "LayerOrientationAnimRotate.h" #include "OrientationAnimation.h" #include "SurfaceFlinger.h" -#include "VRamHeap.h" #include "DisplayHardware/DisplayHardware.h" @@ -35,9 +32,6 @@ 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() @@ -98,19 +92,14 @@ bool OrientationAnimation::prepare() 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()); + sp<Buffer> bitmap = new Buffer(w, h, hw.getFormat()); + sp<Buffer> bitmapIn = new Buffer(w, h, hw.getFormat()); copybit_image_t front; - bitmap.getBitmapSurface(&front); - hw.copyFrontToImage(front); + bitmap->getBitmapSurface(&front); + hw.copyFrontToImage(front); // FIXME: we need an extension to do this - LayerOrientationAnimBase* l; + sp<LayerOrientationAnimBase> l; if (mType & 0x80) { l = new LayerOrientationAnimRotate( @@ -152,7 +141,7 @@ bool OrientationAnimation::finished() { mState = DONE; mFlinger->removeLayer(mLayerOrientationAnim); - mLayerOrientationAnim = NULL; + mLayerOrientationAnim.clear(); return true; } diff --git a/libs/surfaceflinger/OrientationAnimation.h b/libs/surfaceflinger/purgatory/OrientationAnimation.h index cafa38d..8ba6621 100644 --- a/libs/surfaceflinger/OrientationAnimation.h +++ b/libs/surfaceflinger/purgatory/OrientationAnimation.h @@ -72,8 +72,7 @@ private: bool finished(); sp<SurfaceFlinger> mFlinger; - sp<MemoryDealer> mTemporaryDealer; - LayerOrientationAnimBase* mLayerOrientationAnim; + sp< LayerOrientationAnimBase > mLayerOrientationAnim; int mState; uint32_t mType; }; diff --git a/libs/surfaceflinger/purgatory/VRamHeap.cpp b/libs/surfaceflinger/purgatory/VRamHeap.cpp new file mode 100644 index 0000000..f3ed790 --- /dev/null +++ b/libs/surfaceflinger/purgatory/VRamHeap.cpp @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <stdint.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <math.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> + +#include <cutils/log.h> +#include <cutils/properties.h> + +#include <utils/MemoryDealer.h> +#include <utils/MemoryBase.h> +#include <utils/MemoryHeapPmem.h> +#include <utils/MemoryHeapBase.h> + +#include "GPUHardware/GPUHardware.h" +#include "SurfaceFlinger.h" +#include "VRamHeap.h" + +#if HAVE_ANDROID_OS +#include <linux/android_pmem.h> +#endif + + +namespace android { + +// --------------------------------------------------------------------------- + +/* + * Amount of memory we reserve for surface, per client in PMEM + * (PMEM is used for 2D acceleration) + * 8 MB of address space per client should be enough. + */ +static const int PMEM_SIZE = int(8 * 1024 * 1024); + +int SurfaceHeapManager::global_pmem_heap = 0; + +// --------------------------------------------------------------------------- + +SurfaceHeapManager::SurfaceHeapManager(const sp<SurfaceFlinger>& flinger, + size_t clientHeapSize) + : mFlinger(flinger), mClientHeapSize(clientHeapSize) +{ + SurfaceHeapManager::global_pmem_heap = 1; +} + +SurfaceHeapManager::~SurfaceHeapManager() +{ +} + +void SurfaceHeapManager::onFirstRef() +{ + if (global_pmem_heap) { + const char* device = "/dev/pmem"; + mPMemHeap = new PMemHeap(device, PMEM_SIZE); + if (mPMemHeap->base() == MAP_FAILED) { + mPMemHeap.clear(); + global_pmem_heap = 0; + } + } +} + +sp<MemoryDealer> SurfaceHeapManager::createHeap( + uint32_t flags, + pid_t client_pid, + const sp<MemoryDealer>& defaultAllocator) +{ + sp<MemoryDealer> dealer; + + if (flags & ISurfaceComposer::eGPU) { + // don't grant GPU memory if GPU is disabled + char value[PROPERTY_VALUE_MAX]; + property_get("debug.egl.hw", value, "1"); + if (atoi(value) == 0) { + flags &= ~ISurfaceComposer::eGPU; + } + } + + if (flags & ISurfaceComposer::eGPU) { + // FIXME: this is msm7201A specific, where gpu surfaces may not be secure + if (!(flags & ISurfaceComposer::eSecure)) { + // if GPU doesn't work, we try eHardware + flags |= ISurfaceComposer::eHardware; + // asked for GPU memory, try that first + dealer = mFlinger->getGPU()->request(client_pid); + } + } + + if (dealer == NULL) { + if (defaultAllocator != NULL) + // if a default allocator is given, use that + dealer = defaultAllocator; + } + + if (dealer == NULL) { + // always try h/w accelerated memory first + if (global_pmem_heap) { + const sp<PMemHeap>& heap(mPMemHeap); + if (dealer == NULL && heap != NULL) { + dealer = new MemoryDealer( + heap->createClientHeap(), + heap->getAllocator()); + } + } + } + + if (dealer == NULL) { + // return the ashmem allocator (software rendering) + dealer = new MemoryDealer(mClientHeapSize, 0, "SFNativeHeap"); + } + return dealer; +} + +sp<SimpleBestFitAllocator> SurfaceHeapManager::getAllocator(int type) const +{ + Mutex::Autolock _l(mLock); + sp<SimpleBestFitAllocator> allocator; + + // this is only used for debugging + switch (type) { + case NATIVE_MEMORY_TYPE_PMEM: + if (mPMemHeap != 0) { + allocator = mPMemHeap->getAllocator(); + } + break; + } + return allocator; +} + +// --------------------------------------------------------------------------- + +PMemHeap::PMemHeap(const char* const device, size_t size, size_t reserved) + : MemoryHeapBase(device, size) +{ + //LOGD("%s, %p, mFD=%d", __PRETTY_FUNCTION__, this, heapID()); + if (base() != MAP_FAILED) { + //LOGD("%s, %u bytes", device, virtualSize()); + if (reserved == 0) + reserved = virtualSize(); + mAllocator = new SimpleBestFitAllocator(reserved); + } +} + +PMemHeap::~PMemHeap() { + //LOGD("%s, %p, mFD=%d", __PRETTY_FUNCTION__, this, heapID()); +} + +sp<MemoryHeapPmem> PMemHeap::createClientHeap() { + sp<MemoryHeapBase> parentHeap(this); + return new MemoryHeapPmem(parentHeap); +} + +// --------------------------------------------------------------------------- +}; // namespace android diff --git a/libs/surfaceflinger/purgatory/VRamHeap.h b/libs/surfaceflinger/purgatory/VRamHeap.h new file mode 100644 index 0000000..9140167 --- /dev/null +++ b/libs/surfaceflinger/purgatory/VRamHeap.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2008 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_VRAM_HEAP_H +#define ANDROID_VRAM_HEAP_H + +#include <stdint.h> +#include <sys/types.h> +#include <utils/MemoryDealer.h> + +namespace android { + +// --------------------------------------------------------------------------- + +class PMemHeap; +class MemoryHeapPmem; +class SurfaceFlinger; + +// --------------------------------------------------------------------------- + +class SurfaceHeapManager : public RefBase +{ +public: + SurfaceHeapManager(const sp<SurfaceFlinger>& flinger, size_t clientHeapSize); + virtual ~SurfaceHeapManager(); + virtual void onFirstRef(); + /* use ISurfaceComposer flags eGPU|eHArdware|eSecure */ + sp<MemoryDealer> createHeap(uint32_t flags=0, pid_t client_pid = 0, + const sp<MemoryDealer>& defaultAllocator = 0); + + // used for debugging only... + sp<SimpleBestFitAllocator> getAllocator(int type) const; + +private: + sp<PMemHeap> getHeap(int type) const; + + sp<SurfaceFlinger> mFlinger; + mutable Mutex mLock; + size_t mClientHeapSize; + sp<PMemHeap> mPMemHeap; + static int global_pmem_heap; +}; + +// --------------------------------------------------------------------------- + +class PMemHeap : public MemoryHeapBase +{ +public: + PMemHeap(const char* const vram, + size_t size=0, size_t reserved=0); + virtual ~PMemHeap(); + + virtual const sp<SimpleBestFitAllocator>& getAllocator() const { + return mAllocator; + } + virtual sp<MemoryHeapPmem> createClientHeap(); + +private: + sp<SimpleBestFitAllocator> mAllocator; +}; + +// --------------------------------------------------------------------------- +}; // namespace android + +#endif // ANDROID_VRAM_HEAP_H diff --git a/libs/surfaceflinger/tests/resize/Android.mk b/libs/surfaceflinger/tests/resize/Android.mk new file mode 100644 index 0000000..ef1532f --- /dev/null +++ b/libs/surfaceflinger/tests/resize/Android.mk @@ -0,0 +1,16 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + resize.cpp + +LOCAL_SHARED_LIBRARIES := \ + libcutils \ + libutils \ + libui + +LOCAL_MODULE:= test-resize + +LOCAL_MODULE_TAGS := tests + +include $(BUILD_EXECUTABLE) diff --git a/libs/surfaceflinger/tests/resize/resize.cpp b/libs/surfaceflinger/tests/resize/resize.cpp new file mode 100644 index 0000000..21c6ab6 --- /dev/null +++ b/libs/surfaceflinger/tests/resize/resize.cpp @@ -0,0 +1,60 @@ +#include <cutils/memory.h> + +#include <utils/IPCThreadState.h> +#include <utils/ProcessState.h> +#include <utils/IServiceManager.h> +#include <utils/Log.h> + +#include <ui/Surface.h> +#include <ui/ISurface.h> +#include <ui/Overlay.h> +#include <ui/SurfaceComposerClient.h> + +using namespace android; + +namespace android { +class Test { +public: + static const sp<ISurface>& getISurface(const sp<Surface>& s) { + return s->getISurface(); + } +}; +}; + +int main(int argc, char** argv) +{ + // set up the thread-pool + sp<ProcessState> proc(ProcessState::self()); + ProcessState::self()->startThreadPool(); + + // create a client to surfaceflinger + sp<SurfaceComposerClient> client = new SurfaceComposerClient(); + + // create pushbuffer surface + sp<Surface> surface = client->createSurface(getpid(), 0, 160, 240, + PIXEL_FORMAT_RGB_565); + + + client->openTransaction(); + surface->setLayer(100000); + client->closeTransaction(); + + Surface::SurfaceInfo info; + surface->lock(&info); + ssize_t bpr = info.s * bytesPerPixel(info.format); + android_memset16((uint16_t*)info.bits, 0xF800, bpr*info.h); + surface->unlockAndPost(); + + surface->lock(&info); + android_memset16((uint16_t*)info.bits, 0x07E0, bpr*info.h); + surface->unlockAndPost(); + + client->openTransaction(); + surface->setSize(320, 240); + client->closeTransaction(); + + + IPCThreadState::self()->joinThreadPool(); + + return 0; +} |