eclair snapshot
diff --git a/libs/surfaceflinger/Android.mk b/libs/surfaceflinger/Android.mk
index ec5aa3f..eb51c22 100644
--- a/libs/surfaceflinger/Android.mk
+++ b/libs/surfaceflinger/Android.mk
@@ -5,44 +5,50 @@
clz.cpp.arm \
DisplayHardware/DisplayHardware.cpp \
DisplayHardware/DisplayHardwareBase.cpp \
- GPUHardware/GPUHardware.cpp \
BlurFilter.cpp.arm \
- CPUGauge.cpp \
Layer.cpp \
LayerBase.cpp \
LayerBuffer.cpp \
LayerBlur.cpp \
- LayerBitmap.cpp \
LayerDim.cpp \
- LayerOrientationAnim.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
+
+ifeq ($(TARGET_BOARD_PLATFORM), msm7k)
+ LOCAL_CFLAGS += -DDIM_WITH_TEXTURE
+endif
+ifeq ($(TARGET_BOARD_PLATFORM), qsd8k)
+ LOCAL_CFLAGS += -DDIM_WITH_TEXTURE
+endif
# need "-lrt" on Linux simulator to pick up clock_gettime
ifeq ($(TARGET_SIMULATOR),true)
ifeq ($(HOST_OS),linux)
- LOCAL_LDLIBS += -lrt
+ LOCAL_LDLIBS += -lrt -lpthread
endif
endif
LOCAL_SHARED_LIBRARIES := \
+ libcutils \
+ libpixelflinger \
libhardware \
libutils \
- libcutils \
- libui \
- libcorecg \
- libsgl \
- libpixelflinger \
+ libskia \
libEGL \
- libGLESv1_CM
+ libGLESv1_CM \
+ libbinder \
+ libui
LOCAL_C_INCLUDES := \
$(call include-path-for, corecg graphics)
+LOCAL_C_INCLUDES += hardware/libhardware/modules/gralloc
+
LOCAL_MODULE:= libsurfaceflinger
include $(BUILD_SHARED_LIBRARY)
diff --git a/libs/surfaceflinger/BlurFilter.cpp b/libs/surfaceflinger/BlurFilter.cpp
index 5dc0ba0..1ffbd5b 100644
--- a/libs/surfaceflinger/BlurFilter.cpp
+++ b/libs/surfaceflinger/BlurFilter.cpp
@@ -111,6 +111,50 @@
}
};
+template <int FACTOR = 0>
+struct BlurColor888X
+{
+ typedef uint32_t type;
+ int r, g, b;
+ inline BlurColor888X() { }
+ inline BlurColor888X(uint32_t v) {
+ v = BLUR_RGBA_TO_HOST(v);
+ r = v & 0xFF;
+ g = (v >> 8) & 0xFF;
+ b = (v >> 16) & 0xFF;
+ }
+ inline void clear() { r=g=b=0; }
+ inline uint32_t to(int shift, int last, int dither) const {
+ int R = r;
+ int G = g;
+ int B = b;
+ if (UNLIKELY(last)) {
+ if (FACTOR>0) {
+ int L = (R+G+G+B)>>2;
+ R += ((L - R) * FACTOR) >> 8;
+ G += ((L - G) * FACTOR) >> 8;
+ B += ((L - B) * FACTOR) >> 8;
+ }
+ }
+ R >>= shift;
+ G >>= shift;
+ B >>= shift;
+ return BLUR_HOST_TO_RGBA((0xFF<<24) | (B<<16) | (G<<8) | R);
+ }
+ inline BlurColor888X& operator += (const BlurColor888X& rhs) {
+ r += rhs.r;
+ g += rhs.g;
+ b += rhs.b;
+ return *this;
+ }
+ inline BlurColor888X& operator -= (const BlurColor888X& rhs) {
+ r -= rhs.r;
+ g -= rhs.g;
+ b -= rhs.b;
+ return *this;
+ }
+};
+
struct BlurGray565
{
typedef uint16_t type;
@@ -316,7 +360,13 @@
int kernelSizeUser,
int repeat)
{
- return blurFilter< BlurColor565<0x80> >(image, image, kernelSizeUser, repeat);
+ status_t err = BAD_VALUE;
+ if (image->format == GGL_PIXEL_FORMAT_RGB_565) {
+ err = blurFilter< BlurColor565<0x80> >(image, image, kernelSizeUser, repeat);
+ } else if (image->format == GGL_PIXEL_FORMAT_RGBX_8888) {
+ err = blurFilter< BlurColor888X<0x80> >(image, image, kernelSizeUser, repeat);
+ }
+ return err;
}
} // namespace android
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 ab02fa0..1abfd68 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,63 +21,50 @@
#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 <ui/EGLUtils.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;
-static __attribute__((noinline))
-const char *egl_strerror(EGLint err)
-{
- switch (err){
- case EGL_SUCCESS: return "EGL_SUCCESS";
- case EGL_NOT_INITIALIZED: return "EGL_NOT_INITIALIZED";
- case EGL_BAD_ACCESS: return "EGL_BAD_ACCESS";
- case EGL_BAD_ALLOC: return "EGL_BAD_ALLOC";
- case EGL_BAD_ATTRIBUTE: return "EGL_BAD_ATTRIBUTE";
- case EGL_BAD_CONFIG: return "EGL_BAD_CONFIG";
- case EGL_BAD_CONTEXT: return "EGL_BAD_CONTEXT";
- case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE";
- case EGL_BAD_DISPLAY: return "EGL_BAD_DISPLAY";
- case EGL_BAD_MATCH: return "EGL_BAD_MATCH";
- case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP";
- case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW";
- case EGL_BAD_PARAMETER: return "EGL_BAD_PARAMETER";
- case EGL_BAD_SURFACE: return "EGL_BAD_SURFACE";
- case EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST";
- default: return "UNKNOWN";
- }
-}
static __attribute__((noinline))
void checkGLErrors()
{
- GLenum error = glGetError();
- if (error != GL_NO_ERROR)
+ do {
+ // there could be more than one error flag
+ GLenum error = glGetError();
+ if (error == GL_NO_ERROR)
+ break;
LOGE("GL error 0x%04x", int(error));
+ } while(true);
}
static __attribute__((noinline))
void checkEGLErrors(const char* token)
{
EGLint error = eglGetError();
- // GLESonGL seems to be returning 0 when there is no errors?
- if (error && error != EGL_SUCCESS)
- LOGE("%s error 0x%04x (%s)",
- token, int(error), egl_strerror(error));
+ if (error && error != EGL_SUCCESS) {
+ LOGE("%s: EGL error 0x%04x (%s)",
+ token, int(error), EGLUtils::strerror(error));
+ }
}
-
/*
* Initialize the display to the specified values.
*
@@ -108,20 +93,37 @@
void DisplayHardware::init(uint32_t dpy)
{
+ mNativeWindow = new FramebufferNativeWindow();
+ framebuffer_device_t const * fbDev = mNativeWindow->getDevice();
+
+ mOverlayEngine = NULL;
+ hw_module_t const* module;
+ if (hw_get_module(OVERLAY_HARDWARE_MODULE_ID, &module) == 0) {
+ overlay_control_open(module, &mOverlayEngine);
+ }
+
// initialize EGL
- const EGLint attribs[] = {
- EGL_RED_SIZE, 5,
- EGL_GREEN_SIZE, 6,
- EGL_BLUE_SIZE, 5,
- EGL_DEPTH_SIZE, 0,
+ EGLint attribs[] = {
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_NONE, 0,
EGL_NONE
};
+
+ // debug: disable h/w rendering
+ char property[PROPERTY_VALUE_MAX];
+ if (property_get("debug.sf.hw", property, NULL) > 0) {
+ if (atoi(property) == 0) {
+ LOGW("H/W composition disabled");
+ attribs[2] = EGL_CONFIG_CAVEAT;
+ attribs[3] = EGL_SLOW_CONFIG;
+ }
+ }
+
EGLint w, h, dummy;
- EGLint numConfigs, n;
- EGLConfig config;
+ EGLint numConfigs=0;
EGLSurface surface;
EGLContext context;
- mFlags = 0;
+ mFlags = CACHED_BUFFERS;
// TODO: all the extensions below should be queried through
// eglGetProcAddress().
@@ -129,7 +131,17 @@
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(display, NULL, NULL);
eglGetConfigs(display, NULL, 0, &numConfigs);
- eglChooseConfig(display, attribs, &config, 1, &n);
+
+ EGLConfig config;
+ status_t err = EGLUtils::selectConfigForNativeWindow(
+ display, attribs, mNativeWindow.get(), &config);
+ LOGE_IF(err, "couldn't find an EGLConfig matching the screen format");
+
+ EGLint r,g,b,a;
+ eglGetConfigAttrib(display, config, EGL_RED_SIZE, &r);
+ eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &g);
+ eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &b);
+ eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &a);
/*
* Gather EGL extensions
@@ -144,13 +156,13 @@
LOGI("version : %s", eglQueryString(display, EGL_VERSION));
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;
+ LOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config);
- // TODO: get the real "update_on_demand" behavior (probably should be HAL module)
- mFlags |= UPDATE_ON_DEMAND;
+ if (mNativeWindow->isUpdateOnDemand()) {
+ mFlags |= PARTIAL_UPDATES;
+ }
+
if (eglGetConfigAttrib(display, config, EGL_CONFIG_CAVEAT, &dummy) == EGL_TRUE) {
if (dummy == EGL_SLOW_CONFIG)
mFlags |= SLOW_CONFIG;
@@ -160,37 +172,48 @@
* Create our main surface
*/
- mDisplaySurface = new EGLDisplaySurface();
+ surface = eglCreateWindowSurface(display, config, mNativeWindow.get(), NULL);
- surface = eglCreateWindowSurface(display, config, mDisplaySurface.get(), NULL);
- //checkEGLErrors("eglCreateDisplaySurfaceANDROID");
+ if (mFlags & PARTIAL_UPDATES) {
+ // if we have partial updates, we definitely don't need to
+ // preserve the backbuffer, which may be costly.
+ eglSurfaceAttrib(display, surface,
+ EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED);
+ }
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;
+
+ eglQuerySurface(display, surface, EGL_WIDTH, &mWidth);
+ eglQuerySurface(display, surface, EGL_HEIGHT, &mHeight);
+
+#ifdef EGL_ANDROID_swap_rectangle
+ if (strstr(egl_extensions, "EGL_ANDROID_swap_rectangle")) {
+ if (eglSetSwapRectangleANDROID(display, surface,
+ 0, 0, mWidth, mHeight) == EGL_TRUE) {
+ // This could fail if this extension is not supported by this
+ // specific surface (of config)
+ mFlags |= SWAP_RECTANGLE;
+ }
}
- 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;
- }
- mRefreshRate = 60.f; // TODO: get the real refresh rate
+ // when we have the choice between PARTIAL_UPDATES and SWAP_RECTANGLE
+ // choose PARTIAL_UPDATES, which should be more efficient
+ if (mFlags & PARTIAL_UPDATES)
+ mFlags &= ~SWAP_RECTANGLE;
+#endif
+
+ LOGI("flags : %08x", mFlags);
- char property[PROPERTY_VALUE_MAX];
+ mDpiX = mNativeWindow->xdpi;
+ mDpiY = mNativeWindow->ydpi;
+ mRefreshRate = fbDev->fps;
+
/* Read density from build-specific ro.sf.lcd_density property
- * except if it is overriden by qemu.sf.lcd_density.
+ * except if it is overridden by qemu.sf.lcd_density.
*/
if (property_get("qemu.sf.lcd_density", property, NULL) <= 0) {
if (property_get("ro.sf.lcd_density", property, NULL) <= 0) {
@@ -209,11 +232,6 @@
*/
context = eglCreateContext(display, config, NULL, NULL);
- //checkEGLErrors("eglCreateContext");
-
- eglQuerySurface(display, surface, EGL_WIDTH, &mWidth);
- eglQuerySurface(display, surface, EGL_HEIGHT, &mHeight);
-
/*
* Gather OpenGL ES extensions
@@ -221,21 +239,33 @@
eglMakeCurrent(display, surface, surface, context);
const char* const gl_extensions = (const char*)glGetString(GL_EXTENSIONS);
+ const char* const gl_renderer = (const char*)glGetString(GL_RENDERER);
LOGI("OpenGL informations:");
LOGI("vendor : %s", glGetString(GL_VENDOR));
- LOGI("renderer : %s", glGetString(GL_RENDERER));
+ LOGI("renderer : %s", gl_renderer);
LOGI("version : %s", glGetString(GL_VERSION));
LOGI("extensions: %s", gl_extensions);
+ if (strstr(gl_renderer, "PowerVR SGX 530")) {
+ LOGD("Assuming uncached graphics buffers.");
+ mFlags &= ~CACHED_BUFFERS;
+ }
if (strstr(gl_extensions, "GL_ARB_texture_non_power_of_two")) {
mFlags |= NPOT_EXTENSION;
}
if (strstr(gl_extensions, "GL_OES_draw_texture")) {
mFlags |= DRAW_TEXTURE_EXTENSION;
}
- if (strstr(gl_extensions, "GL_ANDROID_direct_texture")) {
+#ifdef EGL_ANDROID_image_native_buffer
+ 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;
}
+#else
+#warning "EGL_ANDROID_image_native_buffer not supported"
+#endif
// Unbind the context from this thread
eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
@@ -244,19 +274,8 @@
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;
}
/*
@@ -270,7 +289,6 @@
{
eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglTerminate(mDisplay);
- copybit_close(mBlitEngine);
overlay_control_close(mOverlayEngine);
}
@@ -284,33 +302,13 @@
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;
}
-/*
- * "Flip" the front and back buffers.
- */
+status_t DisplayHardware::compositionComplete() const {
+ return mNativeWindow->compositionComplete();
+}
void DisplayHardware::flip(const Region& dirty) const
{
@@ -319,21 +317,20 @@
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) {
- const Rect& b(newDirty.bounds());
- mDisplaySurface->setSwapRectangle(
+#ifdef EGL_ANDROID_swap_rectangle
+ if (mFlags & SWAP_RECTANGLE) {
+ const Region newDirty(dirty.intersect(bounds()));
+ const Rect b(newDirty.getBounds());
+ eglSetSwapRectangleANDROID(dpy, surface,
b.left, b.top, b.width(), b.height());
+ }
+#endif
+
+ if (mFlags & PARTIAL_UPDATES) {
+ mNativeWindow->setUpdateRectangle(dirty.getBounds());
}
-
+
+ mPageFlipCount++;
eglSwapBuffers(dpy, surface);
checkEGLErrors("eglSwapBuffers");
@@ -351,11 +348,3 @@
{
eglMakeCurrent(mDisplay, mSurface, mSurface, mContext);
}
-
-void DisplayHardware::copyFrontToImage(const copybit_image_t& front) const {
- mDisplaySurface->copyFrontToImage(front);
-}
-
-void DisplayHardware::copyBackToImage(const copybit_image_t& front) const {
- mDisplaySurface->copyBackToImage(front);
-}
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h
index 550a4d1..6914d0c 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h
@@ -22,31 +22,36 @@
#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
+ PARTIAL_UPDATES = 0x00020000, // video driver feature
SLOW_CONFIG = 0x00040000, // software
+ SWAP_RECTANGLE = 0x00080000,
+ CACHED_BUFFERS = 0x00100000
};
DisplayHardware(
@@ -73,15 +78,11 @@
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;
- void copyBackToImage(const copybit_image_t& front) const;
-
+ status_t compositionComplete() const;
+
Rect bounds() const {
return Rect(mWidth, mHeight);
}
@@ -102,9 +103,9 @@
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/GPUHardware/GPUHardware.cpp b/libs/surfaceflinger/GPUHardware/GPUHardware.cpp
deleted file mode 100644
index 7168bf2..0000000
--- a/libs/surfaceflinger/GPUHardware/GPUHardware.cpp
+++ /dev/null
@@ -1,585 +0,0 @@
-/*
- * 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.
- */
-
-#define LOG_TAG "SurfaceFlinger"
-
-#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/IBinder.h>
-#include <utils/MemoryDealer.h>
-#include <utils/MemoryBase.h>
-#include <utils/MemoryHeapPmem.h>
-#include <utils/MemoryHeapBase.h>
-#include <utils/IPCThreadState.h>
-#include <utils/StopWatch.h>
-
-#include <ui/ISurfaceComposer.h>
-
-#include "VRamHeap.h"
-#include "GPUHardware.h"
-
-#if HAVE_ANDROID_OS
-#include <linux/android_pmem.h>
-#endif
-
-#include "GPUHardware/GPUHardware.h"
-
-
-/*
- * Manage the GPU. This implementation is very specific to the G1.
- * There are no abstraction here.
- *
- * All this code will soon go-away and be replaced by a new architecture
- * for managing graphics accelerators.
- *
- * In the meantime, it is conceptually possible to instantiate a
- * GPUHardwareInterface for another GPU (see GPUFactory at the bottom
- * of this file); practically... doubtful.
- *
- */
-
-namespace android {
-
-// ---------------------------------------------------------------------------
-
-class GPUClientHeap;
-class GPUAreaHeap;
-
-class GPUHardware : public GPUHardwareInterface, public IBinder::DeathRecipient
-{
-public:
- static const int GPU_RESERVED_SIZE;
- static const int GPUR_SIZE;
-
- GPUHardware();
- virtual ~GPUHardware();
-
- virtual void revoke(int pid);
- virtual sp<MemoryDealer> request(int pid);
- virtual status_t request(int pid,
- const sp<IGPUCallback>& callback,
- ISurfaceComposer::gpu_info_t* gpu);
-
- virtual status_t friendlyRevoke();
- virtual void unconditionalRevoke();
-
- virtual pid_t getOwner() const { return mOwner; }
-
- // used for debugging only...
- virtual sp<SimpleBestFitAllocator> getAllocator() const;
-
-private:
-
-
- enum {
- NO_OWNER = -1,
- };
-
- struct GPUArea {
- sp<GPUAreaHeap> heap;
- sp<MemoryHeapPmem> clientHeap;
- sp<IMemory> map();
- };
-
- struct Client {
- pid_t pid;
- GPUArea smi;
- GPUArea ebi;
- GPUArea reg;
- void createClientHeaps();
- void revokeAllHeaps();
- };
-
- Client& getClientLocked(pid_t pid);
- status_t requestLocked(int pid);
- void releaseLocked();
- void takeBackGPULocked();
- void registerCallbackLocked(const sp<IGPUCallback>& callback,
- Client& client);
-
- virtual void binderDied(const wp<IBinder>& who);
-
- mutable Mutex mLock;
- sp<GPUAreaHeap> mSMIHeap;
- sp<GPUAreaHeap> mEBIHeap;
- sp<GPUAreaHeap> mREGHeap;
-
- KeyedVector<pid_t, Client> mClients;
- DefaultKeyedVector< wp<IBinder>, pid_t > mRegisteredClients;
-
- pid_t mOwner;
-
- sp<MemoryDealer> mCurrentAllocator;
- sp<IGPUCallback> mCallback;
-
- sp<SimpleBestFitAllocator> mAllocator;
-
- Condition mCondition;
-};
-
-// size reserved for GPU surfaces
-// 1200 KB fits exactly:
-// - two 320*480 16-bits double-buffered surfaces
-// - one 320*480 32-bits double-buffered surface
-// - one 320*240 16-bits double-buffered, 4x anti-aliased surface
-const int GPUHardware::GPU_RESERVED_SIZE = 1200 * 1024;
-const int GPUHardware::GPUR_SIZE = 1 * 1024 * 1024;
-
-// ---------------------------------------------------------------------------
-
-/*
- * GPUHandle is a special IMemory given to the client. It represents their
- * handle to the GPU. Once they give it up, they loose GPU access, or if
- * they explicitly revoke their access through the binder code 1000.
- * In both cases, this triggers a callback to revoke()
- * first, and then actually powers down the chip.
- *
- * In the case of a misbehaving app, GPUHardware can ask for an immediate
- * release of the GPU to the target process which should answer by calling
- * code 1000 on GPUHandle. If it doesn't in a timely manner, the GPU will
- * be revoked from under their feet.
- *
- * We should never hold a strong reference on GPUHandle. In practice this
- * shouldn't be a big issue though because clients should use code 1000 and
- * not rely on the dtor being called.
- *
- */
-
-class GPUClientHeap : public MemoryHeapPmem
-{
-public:
- GPUClientHeap(const wp<GPUHardware>& gpu,
- const sp<MemoryHeapBase>& heap)
- : MemoryHeapPmem(heap), mGPU(gpu) { }
-protected:
- wp<GPUHardware> mGPU;
-};
-
-class GPUAreaHeap : public MemoryHeapBase
-{
-public:
- GPUAreaHeap(const wp<GPUHardware>& gpu,
- const char* const vram, size_t size=0, size_t reserved=0)
- : MemoryHeapBase(vram, size), mGPU(gpu) {
- if (base() != MAP_FAILED) {
- if (reserved == 0)
- reserved = virtualSize();
- mAllocator = new SimpleBestFitAllocator(reserved);
- }
- }
- virtual sp<MemoryHeapPmem> createClientHeap() {
- sp<MemoryHeapBase> parentHeap(this);
- return new GPUClientHeap(mGPU, parentHeap);
- }
- virtual const sp<SimpleBestFitAllocator>& getAllocator() const {
- return mAllocator;
- }
-private:
- sp<SimpleBestFitAllocator> mAllocator;
-protected:
- wp<GPUHardware> mGPU;
-};
-
-class GPURegisterHeap : public GPUAreaHeap
-{
-public:
- GPURegisterHeap(const sp<GPUHardware>& gpu)
- : GPUAreaHeap(gpu, "/dev/hw3d", GPUHardware::GPUR_SIZE) { }
- virtual sp<MemoryHeapPmem> createClientHeap() {
- sp<MemoryHeapBase> parentHeap(this);
- return new MemoryHeapRegs(mGPU, parentHeap);
- }
-private:
- class MemoryHeapRegs : public GPUClientHeap {
- public:
- MemoryHeapRegs(const wp<GPUHardware>& gpu,
- const sp<MemoryHeapBase>& heap)
- : GPUClientHeap(gpu, heap) { }
- sp<MemoryHeapPmem::MemoryPmem> createMemory(size_t offset, size_t size);
- virtual void revoke();
- private:
- class GPUHandle : public MemoryHeapPmem::MemoryPmem {
- public:
- GPUHandle(const sp<GPUHardware>& gpu,
- const sp<MemoryHeapPmem>& heap)
- : MemoryHeapPmem::MemoryPmem(heap),
- mGPU(gpu), mOwner(gpu->getOwner()) { }
- virtual ~GPUHandle();
- virtual sp<IMemoryHeap> getMemory(
- ssize_t* offset, size_t* size) const;
- virtual void revoke() { };
- virtual status_t onTransact(
- uint32_t code, const Parcel& data,
- Parcel* reply, uint32_t flags);
- private:
- void revokeNotification();
- wp<GPUHardware> mGPU;
- pid_t mOwner;
- };
- };
-};
-
-GPURegisterHeap::MemoryHeapRegs::GPUHandle::~GPUHandle() {
- //LOGD("GPUHandle %p released, revoking GPU", this);
- revokeNotification();
-}
-void GPURegisterHeap::MemoryHeapRegs::GPUHandle::revokeNotification() {
- sp<GPUHardware> hw(mGPU.promote());
- if (hw != 0) {
- hw->revoke(mOwner);
- }
-}
-sp<IMemoryHeap> GPURegisterHeap::MemoryHeapRegs::GPUHandle::getMemory(
- ssize_t* offset, size_t* size) const
-{
- sp<MemoryHeapPmem> heap = getHeap();
- if (offset) *offset = 0;
- if (size) *size = heap !=0 ? heap->virtualSize() : 0;
- return heap;
-}
-status_t GPURegisterHeap::MemoryHeapRegs::GPUHandle::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
- status_t err = BnMemory::onTransact(code, data, reply, flags);
- if (err == UNKNOWN_TRANSACTION && code == 1000) {
- int callingPid = IPCThreadState::self()->getCallingPid();
- //LOGD("pid %d voluntarily revoking gpu", callingPid);
- if (callingPid == mOwner) {
- revokeNotification();
- // we've revoked the GPU, don't do it again later when we
- // are destroyed.
- mGPU.clear();
- } else {
- LOGW("%d revoking someone else's gpu? (owner=%d)",
- callingPid, mOwner);
- }
- err = NO_ERROR;
- }
- return err;
-}
-
-// ---------------------------------------------------------------------------
-
-
-sp<MemoryHeapPmem::MemoryPmem> GPURegisterHeap::MemoryHeapRegs::createMemory(
- size_t offset, size_t size)
-{
- sp<GPUHandle> memory;
- sp<GPUHardware> gpu = mGPU.promote();
- if (heapID()>0 && gpu!=0) {
-#if HAVE_ANDROID_OS
- /* this is where the GPU is powered on and the registers are mapped
- * in the client */
- //LOGD("ioctl(HW3D_GRANT_GPU)");
- int err = ioctl(heapID(), HW3D_GRANT_GPU, base());
- if (err) {
- // it can happen if the master heap has been closed already
- // in which case the GPU already is revoked (app crash for
- // instance).
- LOGW("HW3D_GRANT_GPU failed (%s), mFD=%d, base=%p",
- strerror(errno), heapID(), base());
- }
- memory = new GPUHandle(gpu, this);
-#endif
- }
- return memory;
-}
-
-void GPURegisterHeap::MemoryHeapRegs::revoke()
-{
- MemoryHeapPmem::revoke();
-#if HAVE_ANDROID_OS
- if (heapID() > 0) {
- //LOGD("ioctl(HW3D_REVOKE_GPU)");
- int err = ioctl(heapID(), HW3D_REVOKE_GPU, base());
- LOGE_IF(err, "HW3D_REVOKE_GPU failed (%s), mFD=%d, base=%p",
- strerror(errno), heapID(), base());
- }
-#endif
-}
-
-/*****************************************************************************/
-
-GPUHardware::GPUHardware()
- : mOwner(NO_OWNER)
-{
-}
-
-GPUHardware::~GPUHardware()
-{
-}
-
-status_t GPUHardware::requestLocked(int pid)
-{
- const int self_pid = getpid();
- if (pid == self_pid) {
- // can't use GPU from surfaceflinger's process
- return PERMISSION_DENIED;
- }
-
- if (mOwner != pid) {
- if (mREGHeap != 0) {
- if (mOwner != NO_OWNER) {
- // someone already has the gpu.
- takeBackGPULocked();
- releaseLocked();
- }
- } else {
- // first time, initialize the stuff.
- if (mSMIHeap == 0)
- mSMIHeap = new GPUAreaHeap(this, "/dev/pmem_gpu0");
- if (mEBIHeap == 0)
- mEBIHeap = new GPUAreaHeap(this,
- "/dev/pmem_gpu1", 0, GPU_RESERVED_SIZE);
- mREGHeap = new GPURegisterHeap(this);
- mAllocator = mEBIHeap->getAllocator();
- if (mAllocator == NULL) {
- // something went terribly wrong.
- mSMIHeap.clear();
- mEBIHeap.clear();
- mREGHeap.clear();
- return INVALID_OPERATION;
- }
- }
- Client& client = getClientLocked(pid);
- mCurrentAllocator = new MemoryDealer(client.ebi.clientHeap, mAllocator);
- mOwner = pid;
- }
- return NO_ERROR;
-}
-
-sp<MemoryDealer> GPUHardware::request(int pid)
-{
- sp<MemoryDealer> dealer;
- Mutex::Autolock _l(mLock);
- Client* client;
- LOGD("pid %d requesting gpu surface (current owner = %d)", pid, mOwner);
- if (requestLocked(pid) == NO_ERROR) {
- dealer = mCurrentAllocator;
- LOGD_IF(dealer!=0, "gpu surface granted to pid %d", mOwner);
- }
- return dealer;
-}
-
-status_t GPUHardware::request(int pid, const sp<IGPUCallback>& callback,
- ISurfaceComposer::gpu_info_t* gpu)
-{
- if (callback == 0)
- return BAD_VALUE;
-
- sp<IMemory> gpuHandle;
- LOGD("pid %d requesting gpu core (owner = %d)", pid, mOwner);
- Mutex::Autolock _l(mLock);
- status_t err = requestLocked(pid);
- if (err == NO_ERROR) {
- // it's guaranteed to be there, be construction
- Client& client = mClients.editValueFor(pid);
- registerCallbackLocked(callback, client);
- gpu->count = 2;
- gpu->regions[0].region = client.smi.map();
- gpu->regions[1].region = client.ebi.map();
- gpu->regs = client.reg.map();
- gpu->regions[0].reserved = 0;
- gpu->regions[1].reserved = GPU_RESERVED_SIZE;
- if (gpu->regs != 0) {
- //LOGD("gpu core granted to pid %d, handle base=%p",
- // mOwner, gpu->regs->pointer());
- }
- mCallback = callback;
- } else {
- LOGW("couldn't grant gpu core to pid %d", pid);
- }
- return err;
-}
-
-void GPUHardware::revoke(int pid)
-{
- Mutex::Autolock _l(mLock);
- if (mOwner > 0) {
- if (pid != mOwner) {
- LOGW("GPU owned by %d, revoke from %d", mOwner, pid);
- return;
- }
- //LOGD("revoke pid=%d, owner=%d", pid, mOwner);
- // mOwner could be <0 if the same process acquired the GPU
- // several times without releasing it first.
- mCondition.signal();
- releaseLocked();
- }
-}
-
-status_t GPUHardware::friendlyRevoke()
-{
- Mutex::Autolock _l(mLock);
- //LOGD("friendlyRevoke owner=%d", mOwner);
- takeBackGPULocked();
- releaseLocked();
- return NO_ERROR;
-}
-
-void GPUHardware::takeBackGPULocked()
-{
- sp<IGPUCallback> callback = mCallback;
- mCallback.clear();
- if (callback != 0) {
- callback->gpuLost(); // one-way
- mCondition.waitRelative(mLock, ms2ns(250));
- }
-}
-
-void GPUHardware::releaseLocked()
-{
- //LOGD("revoking gpu from pid %d", mOwner);
- if (mOwner != NO_OWNER) {
- // this may fail because the client might have died, and have
- // been removed from the list.
- ssize_t index = mClients.indexOfKey(mOwner);
- if (index >= 0) {
- Client& client(mClients.editValueAt(index));
- client.revokeAllHeaps();
- }
- mOwner = NO_OWNER;
- mCurrentAllocator.clear();
- mCallback.clear();
- }
-}
-
-GPUHardware::Client& GPUHardware::getClientLocked(pid_t pid)
-{
- ssize_t index = mClients.indexOfKey(pid);
- if (index < 0) {
- Client client;
- client.pid = pid;
- client.smi.heap = mSMIHeap;
- client.ebi.heap = mEBIHeap;
- client.reg.heap = mREGHeap;
- index = mClients.add(pid, client);
- }
- Client& client(mClients.editValueAt(index));
- client.createClientHeaps();
- return client;
-}
-
-// ----------------------------------------------------------------------------
-// for debugging / testing ...
-
-sp<SimpleBestFitAllocator> GPUHardware::getAllocator() const {
- Mutex::Autolock _l(mLock);
- return mAllocator;
-}
-
-void GPUHardware::unconditionalRevoke()
-{
- Mutex::Autolock _l(mLock);
- releaseLocked();
-}
-
-// ---------------------------------------------------------------------------
-
-sp<IMemory> GPUHardware::GPUArea::map() {
- sp<IMemory> memory;
- if (clientHeap != 0 && heap != 0) {
- memory = clientHeap->mapMemory(0, heap->virtualSize());
- }
- return memory;
-}
-
-void GPUHardware::Client::createClientHeaps()
-{
- if (smi.clientHeap == 0)
- smi.clientHeap = smi.heap->createClientHeap();
- if (ebi.clientHeap == 0)
- ebi.clientHeap = ebi.heap->createClientHeap();
- if (reg.clientHeap == 0)
- reg.clientHeap = reg.heap->createClientHeap();
-}
-
-void GPUHardware::Client::revokeAllHeaps()
-{
- if (smi.clientHeap != 0)
- smi.clientHeap->revoke();
- if (ebi.clientHeap != 0)
- ebi.clientHeap->revoke();
- if (reg.clientHeap != 0)
- reg.clientHeap->revoke();
-}
-
-void GPUHardware::registerCallbackLocked(const sp<IGPUCallback>& callback,
- Client& client)
-{
- sp<IBinder> binder = callback->asBinder();
- if (mRegisteredClients.add(binder, client.pid) >= 0) {
- binder->linkToDeath(this);
- }
-}
-
-void GPUHardware::binderDied(const wp<IBinder>& who)
-{
- Mutex::Autolock _l(mLock);
- pid_t pid = mRegisteredClients.valueFor(who);
- if (pid != 0) {
- ssize_t index = mClients.indexOfKey(pid);
- if (index >= 0) {
- //LOGD("*** removing client at %d", index);
- Client& client(mClients.editValueAt(index));
- client.revokeAllHeaps(); // not really needed in theory
- mClients.removeItemsAt(index);
- if (mClients.size() == 0) {
- //LOGD("*** was last client closing everything");
- mCallback.clear();
- mAllocator.clear();
- mCurrentAllocator.clear();
- mSMIHeap.clear();
- mREGHeap.clear();
-
- // NOTE: we cannot clear the EBI heap because surfaceflinger
- // itself may be using it, since this is where surfaces
- // are allocated. if we're in the middle of compositing
- // a surface (even if its process just died), we cannot
- // rip the heap under our feet.
-
- mOwner = NO_OWNER;
- }
- }
- }
-}
-
-// ---------------------------------------------------------------------------
-
-sp<GPUHardwareInterface> GPUFactory::getGPU()
-{
- sp<GPUHardwareInterface> gpu;
- if (access("/dev/hw3d", F_OK) == 0) {
- gpu = new GPUHardware();
- }
- return gpu;
-}
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
diff --git a/libs/surfaceflinger/GPUHardware/GPUHardware.h b/libs/surfaceflinger/GPUHardware/GPUHardware.h
deleted file mode 100644
index 3354528..0000000
--- a/libs/surfaceflinger/GPUHardware/GPUHardware.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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_GPU_HARDWARE_H
-#define ANDROID_GPU_HARDWARE_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/RefBase.h>
-#include <utils/threads.h>
-#include <utils/KeyedVector.h>
-
-#include <ui/ISurfaceComposer.h>
-
-namespace android {
-
-// ---------------------------------------------------------------------------
-
-class IGPUCallback;
-
-class GPUHardwareInterface : public virtual RefBase
-{
-public:
- virtual void revoke(int pid) = 0;
- virtual sp<MemoryDealer> request(int pid) = 0;
- virtual status_t request(int pid, const sp<IGPUCallback>& callback,
- ISurfaceComposer::gpu_info_t* gpu) = 0;
-
- virtual status_t friendlyRevoke() = 0;
-
- // used for debugging only...
- virtual sp<SimpleBestFitAllocator> getAllocator() const = 0;
- virtual pid_t getOwner() const = 0;
- virtual void unconditionalRevoke() = 0;
-};
-
-// ---------------------------------------------------------------------------
-
-class GPUFactory
-{
-public:
- // the gpu factory
- static sp<GPUHardwareInterface> getGPU();
-};
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_GPU_HARDWARE_H
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index 96395a8..f5a5a0b 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/GraphicBuffer.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"
@@ -49,178 +47,330 @@
// ---------------------------------------------------------------------------
-Layer::Layer(SurfaceFlinger* flinger, DisplayID display, Client* c, int32_t i)
+Layer::Layer(SurfaceFlinger* flinger, DisplayID display,
+ const sp<Client>& c, int32_t i)
: LayerBaseClient(flinger, display, c, i),
mSecure(false),
- mFrontBufferIndex(1),
+ mNoEGLImageForSwBuffers(false),
mNeedsBlending(true),
- mResizeTransactionDone(false),
- mTextureName(-1U), mTextureWidth(0), mTextureHeight(0)
+ mNeedsDithering(false)
{
// no OpenGL operation is possible here, since we might not be
// in the OpenGL thread.
+ mFrontBufferIndex = lcblk->getFrontBuffer();
}
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::initStates(uint32_t w, uint32_t h, uint32_t flags)
+void Layer::destroy()
{
- LayerBase::initStates(w,h,flags);
-
- if (flags & ISurfaceComposer::eDestroyBackbuffer)
- lcblk->flags |= eNoCopyBack;
+ for (size_t 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;
+ }
+ Mutex::Autolock _l(mLock);
+ mBuffers[i].clear();
+ mWidth = mHeight = 0;
+ }
+ mSurface.clear();
}
-sp<LayerBaseClient::Surface> Layer::getSurface() const
+sp<LayerBaseClient::Surface> Layer::createSurface() const
{
return mSurface;
}
-status_t Layer::setBuffers( Client* client,
- uint32_t w, uint32_t h,
+status_t Layer::ditch()
+{
+ // the layer is not on screen anymore. free as much resources as possible
+ destroy();
+ return NO_ERROR;
+}
+
+status_t Layer::setBuffers( uint32_t w, uint32_t h,
PixelFormat format, uint32_t flags)
{
+ // this surfaces pixel format
PixelFormatInfo info;
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.
+ // the display's pixel format
+ const DisplayHardware& hw(graphicPlane(0).displayHardware());
+ PixelFormatInfo displayInfo;
+ getPixelFormatInfo(hw.getFormat(), &displayInfo);
+ const uint32_t hwFlags = hw.getFlags();
- // FIXME: we always ask for hardware for now (this should come from copybit)
- flags |= ISurfaceComposer::eHardware;
-
- 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::eGPU) && (mFlinger->getGPU() != 0)) {
- // FIXME: this value should come from the h/w
- alignment = 8;
- // FIXME: this is msm7201A specific, as its GPU only supports
- // BGRA_8888.
- if (format == PIXEL_FORMAT_RGBA_8888) {
- format = PIXEL_FORMAT_BGRA_8888;
- }
- }
-
+ mFormat = format;
+ mWidth = w;
+ mHeight = h;
mSecure = (flags & ISurfaceComposer::eSecure) ? 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)
- return err;
- mBuffers[i].clear(); // clear the bits for security
- mBuffers[i].getInfo(lcblk->surface + i);
+ mNoEGLImageForSwBuffers = !(hwFlags & DisplayHardware::CACHED_BUFFERS);
+
+ // we use the red index
+ int displayRedSize = displayInfo.getSize(PixelFormatInfo::INDEX_RED);
+ int layerRedsize = info.getSize(PixelFormatInfo::INDEX_RED);
+ mNeedsDithering = layerRedsize > displayRedSize;
+
+ for (size_t i=0 ; i<NUM_BUFFERS ; i++) {
+ mBuffers[i] = new GraphicBuffer();
}
-
- 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 GGLSurface& t(frontBuffer().surface());
- loadTexture(dirty, mTextureName, t, mTextureWidth, mTextureHeight);
-}
+ Mutex::Autolock _l(mLock);
+ sp<GraphicBuffer> buffer(getFrontBufferLocked());
+ int index = mFrontBufferIndex;
+ // create the new texture name if needed
+ if (UNLIKELY(mTextures[index].name == -1U)) {
+ mTextures[index].name = createTexture();
+ mTextures[index].width = 0;
+ mTextures[index].height = 0;
+ }
+
+#ifdef EGL_ANDROID_image_native_buffer
+ if (mFlags & DisplayHardware::DIRECT_TEXTURE) {
+ if (buffer->usage & GraphicBuffer::USAGE_HW_TEXTURE) {
+ if (mTextures[index].dirty) {
+ initializeEglImage(buffer, &mTextures[index]);
+ }
+ } else {
+ if (mHybridBuffer==0 || (mHybridBuffer->width != buffer->width ||
+ mHybridBuffer->height != buffer->height)) {
+ mHybridBuffer.clear();
+ mHybridBuffer = new GraphicBuffer(
+ buffer->width, buffer->height, buffer->format,
+ GraphicBuffer::USAGE_SW_WRITE_OFTEN |
+ GraphicBuffer::USAGE_HW_TEXTURE);
+ initializeEglImage(
+ mHybridBuffer, &mTextures[0]);
+ }
+
+ GGLSurface t;
+ status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_OFTEN);
+ LOGE_IF(res, "error %d (%s) locking buffer %p",
+ res, strerror(res), buffer.get());
+ if (res == NO_ERROR) {
+ Texture* const texture(&mTextures[0]);
+
+ glBindTexture(GL_TEXTURE_2D, texture->name);
+
+ sp<GraphicBuffer> buf(mHybridBuffer);
+ void* vaddr;
+ res = buf->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN, &vaddr);
+ if (res == NO_ERROR) {
+ int bpp = 0;
+ switch (t.format) {
+ case GGL_PIXEL_FORMAT_RGB_565:
+ case GGL_PIXEL_FORMAT_RGBA_4444:
+ bpp = 2;
+ break;
+ case GGL_PIXEL_FORMAT_RGBA_8888:
+ case GGL_PIXEL_FORMAT_RGBX_8888:
+ bpp = 4;
+ break;
+ case GGL_PIXEL_FORMAT_YCbCr_422_SP:
+ case GGL_PIXEL_FORMAT_YCbCr_420_SP:
+ // just show the Y plane of YUV buffers
+ bpp = 1;
+ break;
+ default:
+ // oops, we don't handle this format!
+ LOGE("layer %p, texture=%d, using format %d, which is not "
+ "supported by the GL", this, texture->name, t.format);
+ }
+ if (bpp) {
+ const Rect bounds(dirty.getBounds());
+ size_t src_stride = t.stride;
+ size_t dst_stride = buf->stride;
+ if (src_stride == dst_stride &&
+ bounds.width() == t.width &&
+ bounds.height() == t.height)
+ {
+ memcpy(vaddr, t.data, t.height * t.stride * bpp);
+ } else {
+ GLubyte const * src = t.data +
+ (bounds.left + bounds.top * src_stride) * bpp;
+ GLubyte * dst = (GLubyte *)vaddr +
+ (bounds.left + bounds.top * dst_stride) * bpp;
+ const size_t length = bounds.width() * bpp;
+ size_t h = bounds.height();
+ src_stride *= bpp;
+ dst_stride *= bpp;
+ while (h--) {
+ memcpy(dst, src, length);
+ dst += dst_stride;
+ src += src_stride;
+ }
+ }
+ }
+ buf->unlock();
+ }
+ buffer->unlock();
+ }
+ }
+ } else
+#endif
+ {
+ for (size_t i=0 ; i<NUM_BUFFERS ; i++) {
+ mTextures[i].image = EGL_NO_IMAGE_KHR;
+ }
+ GGLSurface t;
+ status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_OFTEN);
+ LOGE_IF(res, "error %d (%s) locking buffer %p",
+ res, strerror(res), buffer.get());
+ if (res == NO_ERROR) {
+ loadTexture(&mTextures[0], dirty, t);
+ buffer->unlock();
+ }
+ }
+}
void Layer::onDraw(const Region& clip) const
{
- if (UNLIKELY(mTextureName == -1LU)) {
- //LOGW("Layer %p doesn't have a texture", this);
+ int index = mFrontBufferIndex;
+ if (mTextures[index].image == EGL_NO_IMAGE_KHR)
+ index = 0;
+ GLuint textureName = mTextures[index].name;
+ if (UNLIKELY(textureName == -1LU)) {
// the texture has not been created yet, this Layer has
// in fact never been drawn into. this happens frequently with
// SurfaceView.
clearWithOpenGL(clip);
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);
- }
+ drawWithOpenGL(clip, mTextures[index]);
}
-status_t Layer::reallocateBuffer(int32_t index, uint32_t w, uint32_t h)
+sp<GraphicBuffer> Layer::requestBuffer(int index, int usage)
{
- 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()));
+ sp<GraphicBuffer> buffer;
- status_t err = mBuffers[index].resize(w, h);
- if (err == NO_ERROR) {
- mBuffers[index].getInfo(lcblk->surface + index);
- } 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?
+ // this ensures our client doesn't go away while we're accessing
+ // the shared area.
+ sp<Client> ourClient(client.promote());
+ if (ourClient == 0) {
+ // oops, the client is already gone
+ return buffer;
}
- return err;
+
+ /*
+ * This is called from the client's Surface::dequeue(). This can happen
+ * at any time, especially while we're in the middle of using the
+ * buffer 'index' as our front buffer.
+ *
+ * Make sure the buffer we're resizing is not the front buffer and has been
+ * dequeued. Once this condition is asserted, we are guaranteed that this
+ * buffer cannot become the front buffer under our feet, since we're called
+ * from Surface::dequeue()
+ */
+ status_t err = lcblk->assertReallocate(index);
+ LOGE_IF(err, "assertReallocate(%d) failed (%s)", index, strerror(-err));
+ if (err != NO_ERROR) {
+ // the surface may have died
+ return buffer;
+ }
+
+ uint32_t w, h;
+ { // scope for the lock
+ Mutex::Autolock _l(mLock);
+ w = mWidth;
+ h = mHeight;
+ buffer = mBuffers[index];
+
+ // destroy() could have been called before we get here, we log it
+ // because it's uncommon, and the code below should handle it
+ LOGW_IF(buffer==0,
+ "mBuffers[%d] is null (mWidth=%d, mHeight=%d)",
+ index, w, h);
+
+ mBuffers[index].clear();
+ }
+
+ const uint32_t effectiveUsage = getEffectiveUsage(usage);
+ if (buffer!=0 && buffer->getStrongCount() == 1) {
+ err = buffer->reallocate(w, h, mFormat, effectiveUsage);
+ } else {
+ // here we have to reallocate a new buffer because we could have a
+ // client in our process with a reference to it (eg: status bar),
+ // and we can't release the handle under its feet.
+ buffer.clear();
+ buffer = new GraphicBuffer(w, h, mFormat, effectiveUsage);
+ err = buffer->initCheck();
+ }
+
+ if (err || buffer->handle == 0) {
+ LOGE_IF(err || buffer->handle == 0,
+ "Layer::requestBuffer(this=%p), index=%d, w=%d, h=%d failed (%s)",
+ this, index, w, h, strerror(-err));
+ } else {
+ LOGD_IF(DEBUG_RESIZE,
+ "Layer::requestBuffer(this=%p), index=%d, w=%d, h=%d, handle=%p",
+ this, index, w, h, buffer->handle);
+ }
+
+ if (err == NO_ERROR && buffer->handle != 0) {
+ Mutex::Autolock _l(mLock);
+ if (mWidth && mHeight) {
+ // and we have new buffer
+ mBuffers[index] = buffer;
+ // texture is now dirty...
+ mTextures[index].dirty = true;
+ } else {
+ // oops we got killed while we were allocating the buffer
+ buffer.clear();
+ }
+ }
+ return buffer;
+}
+
+uint32_t Layer::getEffectiveUsage(uint32_t usage) const
+{
+ /*
+ * 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
+ *
+ */
+
+ if (mSecure) {
+ // secure buffer, don't store it into the GPU
+ usage = GraphicBuffer::USAGE_SW_READ_OFTEN |
+ GraphicBuffer::USAGE_SW_WRITE_OFTEN;
+ } else {
+ // it's allowed to modify the usage flags here, but generally
+ // the requested flags should be honored.
+ if (mNoEGLImageForSwBuffers) {
+ if (usage & GraphicBuffer::USAGE_HW_MASK) {
+ // request EGLImage for h/w buffers only
+ usage |= GraphicBuffer::USAGE_HW_TEXTURE;
+ }
+ } else {
+ // request EGLImage for all buffers
+ usage |= GraphicBuffer::USAGE_HW_TEXTURE;
+ }
+ }
+ return usage;
}
uint32_t Layer::doTransaction(uint32_t flags)
@@ -228,113 +378,44 @@
const Layer::State& front(drawingState());
const Layer::State& temp(currentState());
- // the test front.{w|h} != temp.{w|h} is not enough because it is possible
- // 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.
-
- /*
- * Various states we could be in...
-
- resize = state & eResizeRequested;
- if (backbufferChanged) {
- if (resize == 0) {
- // ERROR, the resized buffer doesn't have its resize flag set
- } else if (resize == mask) {
- // ERROR one of the buffer has already been resized
- } else if (resize == mask ^ eResizeRequested) {
- // ERROR, the resized buffer doesn't have its resize flag set
- } else if (resize == eResizeRequested) {
- // OK, Normal case, proceed with resize
- }
- } else {
- if (resize == 0) {
- // OK, nothing special, do nothing
- } else if (resize == mask) {
- // restarted transaction, do nothing
- } else if (resize == mask ^ eResizeRequested) {
- // restarted transaction, do nothing
- } else if (resize == eResizeRequested) {
- // OK, size reset to previous value, proceed with resize
- }
- }
- */
-
- // Index of the back buffer
- const bool backbufferChanged = (front.w != temp.w) || (front.h != temp.h);
- const uint32_t state = lcblk->swapState;
- const int32_t clientBackBufferIndex = layer_cblk_t::backBuffer(state);
- const uint32_t mask = clientBackBufferIndex ? eResizeBuffer1 : eResizeBuffer0;
- uint32_t resizeFlags = state & eResizeRequested;
-
- if (UNLIKELY(backbufferChanged && (resizeFlags != eResizeRequested))) {
- LOGE( "backbuffer size changed, but both resize flags are not set! "
- "(layer=%p), state=%08x, requested (%dx%d), drawing (%d,%d), "
- "index=%d, (%dx%d), (%dx%d)",
- this, state,
- 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()));
- // 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
- // client to get unblocked)
- resizeFlags = eResizeRequested;
- }
-
- if (resizeFlags == eResizeRequested) {
- // NOTE: asserting that clientBackBufferIndex!=mFrontBufferIndex
- // here, would be wrong and misleading because by this point
- // mFrontBufferIndex has not been updated yet.
-
+ if ((front.requested_w != temp.requested_w) ||
+ (front.requested_h != temp.requested_h)) {
+ // the size changed, we need to ask our client to request a new buffer
LOGD_IF(DEBUG_RESIZE,
- "resize (layer=%p), state=%08x, "
- "requested (%dx%d), "
- "drawing (%d,%d), "
- "index=%d, (%dx%d), (%dx%d)",
- this, state,
- 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()));
+ "resize (layer=%p), requested (%dx%d), "
+ "drawing (%d,%d), (%dx%d), (%dx%d)",
+ this,
+ int(temp.requested_w), int(temp.requested_h),
+ int(front.requested_w), int(front.requested_h),
+ 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
- // - the backbuffer is currently in use by the user
- // - the front buffer is being shown
- // We just act as if the transaction didn't happen and we
- // reschedule it later...
- flags |= eRestartTransaction;
- } else {
- // This buffer needs to be resized
- status_t err =
- resize(clientBackBufferIndex, temp.w, temp.h, "transaction");
- if (err == NO_ERROR) {
- 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);
- mResizeTransactionDone = true;
-
- // we're being resized and there is a freeze display request,
- // acquire a freeze lock, so that the screen stays put
- // until we've redrawn at the new size; this is to avoid
- // glitches upon orientation changes.
- if (mFlinger->hasFreezeRequest()) {
- // if the surface is hidden, don't try to acquire the
- // freeze lock, since hidden surfaces may never redraw
- if (!(front.flags & ISurfaceComposer::eLayerHidden)) {
- mFreezeLock = mFlinger->getFreezeLock();
- }
- }
+ // we're being resized and there is a freeze display request,
+ // acquire a freeze lock, so that the screen stays put
+ // until we've redrawn at the new size; this is to avoid
+ // glitches upon orientation changes.
+ if (mFlinger->hasFreezeRequest()) {
+ // if the surface is hidden, don't try to acquire the
+ // freeze lock, since hidden surfaces may never redraw
+ if (!(front.flags & ISurfaceComposer::eLayerHidden)) {
+ mFreezeLock = mFlinger->getFreezeLock();
}
}
+
+ // this will make sure LayerBase::doTransaction doesn't update
+ // the drawing state's size
+ Layer::State& editDraw(mDrawingState);
+ editDraw.requested_w = temp.requested_w;
+ editDraw.requested_h = temp.requested_h;
+
+ // record the new size, form this point on, when the client request a
+ // buffer, it'll get the new size.
+ setDrawingSize(temp.requested_w, temp.requested_h);
+
+ // all buffers need reallocation
+ lcblk->reallocate();
}
-
+
if (temp.sequence != front.sequence) {
if (temp.flags & ISurfaceComposer::eLayerHidden || temp.alpha == 0) {
// this surface is now hidden, so it shouldn't hold a freeze lock
@@ -346,54 +427,10 @@
return LayerBase::doTransaction(flags);
}
-status_t Layer::resize(
- int32_t clientBackBufferIndex,
- uint32_t width, uint32_t height,
- const char* what)
-{
- /*
- * handle resize (backbuffer and frontbuffer reallocation)
- */
-
- 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);
-
- LOGD_IF(!backbufferChanged,
- "(%s) eResizeRequested (layer=%p), but size not changed: "
- "requested (%dx%d), drawing (%d,%d), current (%d,%d),"
- "state=%08lx, index=%d, (%dx%d), (%dx%d)",
- what, this,
- int(width), int(height),
- int(drawingState().w), int(drawingState().h),
- 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()));
-
- // 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));
- }
- return err;
-}
-
-void Layer::setSizeChanged(uint32_t w, uint32_t h)
-{
- LOGD_IF(DEBUG_RESIZE,
- "setSizeChanged w=%d, h=%d (old: w=%d, h=%d)",
- w, h, mCurrentState.w, mCurrentState.h);
- android_atomic_or(eResizeRequested, &(lcblk->swapState));
+void Layer::setDrawingSize(uint32_t w, uint32_t h) {
+ Mutex::Autolock _l(mLock);
+ mWidth = w;
+ mHeight = h;
}
// ----------------------------------------------------------------------------
@@ -402,128 +439,61 @@
void Layer::lockPageFlip(bool& recomputeVisibleRegions)
{
- uint32_t state = android_atomic_or(eBusy, &(lcblk->swapState));
- // preemptively block the client, because he might set
- // eFlipRequested at any time and want to use this buffer
- // for the next frame. This will be unset below if it
- // turns out we didn't need it.
-
- uint32_t mask = eInvalidSurface | eFlipRequested | eResizeRequested;
- if (!(state & mask))
- return;
-
- if (UNLIKELY(state & eInvalidSurface)) {
- // if eInvalidSurface is set, this means the surface
- // became invalid during a transaction (NO_MEMORY for instance)
- mFlinger->scheduleBroadcast(client);
+ ssize_t buf = lcblk->retireAndLock();
+ if (buf < NO_ERROR) {
+ //LOGW("nothing to retire (%s)", strerror(-buf));
+ // NOTE: here the buffer is locked because we will used
+ // for composition later in the loop
return;
}
+
+ // we retired a buffer, which becomes the new front buffer
+ mFrontBufferIndex = buf;
- if (UNLIKELY(state & eFlipRequested)) {
- uint32_t oldState;
- mPostedDirtyRegion = post(&oldState, recomputeVisibleRegions);
- if (oldState & eNextFlipPending) {
- // Process another round (we know at least a buffer
- // is ready for that client).
- mFlinger->signalEvent();
- }
- }
-}
+ // get the dirty region
+ sp<GraphicBuffer> newFrontBuffer(getBuffer(buf));
+ const Region dirty(lcblk->getDirtyRegion(buf));
+ mPostedDirtyRegion = dirty.intersect( newFrontBuffer->getBounds() );
-Region Layer::post(uint32_t* previousSate, bool& recomputeVisibleRegions)
-{
- // atomically swap buffers and (re)set eFlipRequested
- int32_t oldValue, newValue;
- layer_cblk_t * const lcblk = this->lcblk;
- do {
- oldValue = lcblk->swapState;
- // get the current value
+ const Layer::State& front(drawingState());
+ if (newFrontBuffer->getWidth() == front.requested_w &&
+ newFrontBuffer->getHeight() == front.requested_h)
+ {
+ if ((front.w != front.requested_w) ||
+ (front.h != front.requested_h))
+ {
+ // Here we pretend the transaction happened by updating the
+ // current and drawing states. Drawing state is only accessed
+ // in this thread, no need to have it locked
+ Layer::State& editDraw(mDrawingState);
+ editDraw.w = editDraw.requested_w;
+ editDraw.h = editDraw.requested_h;
- LOG_ASSERT(oldValue&eFlipRequested,
- "eFlipRequested not set, yet we're flipping! (state=0x%08lx)",
- long(oldValue));
+ // We also need to update the current state so that we don't
+ // end-up doing too much work during the next transaction.
+ // NOTE: We actually don't need hold the transaction lock here
+ // because State::w and State::h are only accessed from
+ // this thread
+ Layer::State& editTemp(currentState());
+ editTemp.w = editDraw.w;
+ editTemp.h = editDraw.h;
- newValue = (oldValue ^ eIndex);
- // swap buffers
-
- newValue &= ~(eFlipRequested | eNextFlipPending);
- // clear eFlipRequested and eNextFlipPending
-
- if (oldValue & eNextFlipPending)
- newValue |= eFlipRequested;
- // if eNextFlipPending is set (second buffer already has something
- // in it) we need to reset eFlipRequested because the client
- // might never do it
-
- } while(android_atomic_cmpxchg(oldValue, newValue, &(lcblk->swapState)));
- *previousSate = oldValue;
-
- const int32_t index = (newValue & eIndex) ^ 1;
- mFrontBufferIndex = index;
-
- // ... post the new front-buffer
- Region dirty(lcblk->region + index);
- dirty.andSelf(frontBuffer().bounds());
-
- //LOGI("Did post oldValue=%08lx, newValue=%08lx, mFrontBufferIndex=%u\n",
- // oldValue, newValue, mFrontBufferIndex);
- //dirty.dump("dirty");
-
- if (UNLIKELY(oldValue & eResizeRequested)) {
-
- LOGD_IF(DEBUG_RESIZE,
- "post (layer=%p), state=%08x, "
- "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()));
-
- // here, we just posted the surface and we have resolved
- // the front/back buffer indices. The client is blocked, so
- // it cannot start using the new backbuffer.
-
- // If the backbuffer was resized in THIS round, we actually cannot
- // resize the frontbuffer because it has *just* been drawn (and we
- // would have nothing to draw). In this case we just skip the resize
- // it'll happen after the next page flip or during the next
- // transaction.
-
- const uint32_t mask = (1-index) ? eResizeBuffer1 : eResizeBuffer0;
- if (mResizeTransactionDone && (newValue & mask)) {
- // Resize the layer's second buffer only if the transaction
- // happened. It may not have happened yet if eResizeRequested
- // was set immediately after the "transactionRequested" test,
- // in which case the drawing state's size would be wrong.
- mFreezeLock.clear();
- const Layer::State& s(drawingState());
- if (resize(1-index, s.w, s.h, "post") == NO_ERROR) {
- do {
- oldValue = lcblk->swapState;
- if ((oldValue & eResizeRequested) == eResizeRequested) {
- // ugh, another resize was requested since we processed
- // the first buffer, don't free the client, and let
- // the next transaction handle everything.
- break;
- }
- newValue = oldValue & ~mask;
- } while(android_atomic_cmpxchg(oldValue, newValue, &(lcblk->swapState)));
- }
- mResizeTransactionDone = false;
+ // recompute visible region
recomputeVisibleRegions = true;
- this->contentDirty = true;
}
+
+ // we now have the correct size, unfreeze the screen
+ mFreezeLock.clear();
}
- reloadTexture(dirty);
+ if (lcblk->getQueuedCount()) {
+ // signal an event if we have more buffers waiting
+ mFlinger->signalEvent();
+ }
- return dirty;
-}
-
-Point Layer::getPhysicalSize() const
-{
- const LayerBitmap& front(frontBuffer());
- return Point(front.width(), front.height());
+ if (!mPostedDirtyRegion.isEmpty()) {
+ reloadTexture( mPostedDirtyRegion );
+ }
}
void Layer::unlockPageFlip(
@@ -544,23 +514,42 @@
// is in screen space as well).
dirtyRegion.andSelf(visibleRegionScreen);
outDirtyRegion.orSelf(dirtyRegion);
-
- // client could be blocked, so signal them so they get a
- // chance to reevaluate their condition.
- mFlinger->scheduleBroadcast(client);
}
}
void Layer::finishPageFlip()
{
- if (LIKELY(!(lcblk->swapState & eInvalidSurface))) {
- LOGE_IF(!(lcblk->swapState & eBusy),
- "layer %p wasn't locked!", this);
- android_atomic_and(~eBusy, &(lcblk->swapState));
- }
- mFlinger->scheduleBroadcast(client);
+ status_t err = lcblk->unlock( mFrontBufferIndex );
+ LOGE_IF(err!=NO_ERROR,
+ "layer %p, buffer=%d wasn't locked!",
+ this, mFrontBufferIndex);
}
+// ---------------------------------------------------------------------------
+
+Layer::SurfaceLayer::SurfaceLayer(const sp<SurfaceFlinger>& flinger,
+ SurfaceID id, const sp<Layer>& owner)
+ : Surface(flinger, id, owner->getIdentity(), owner)
+{
+}
+
+Layer::SurfaceLayer::~SurfaceLayer()
+{
+}
+
+sp<GraphicBuffer> Layer::SurfaceLayer::requestBuffer(int index, int usage)
+{
+ sp<GraphicBuffer> buffer;
+ sp<Layer> owner(getOwner());
+ if (owner != 0) {
+ LOGE_IF(uint32_t(index)>=NUM_BUFFERS,
+ "getBuffer() index (%d) out of range", index);
+ if (uint32_t(index) < NUM_BUFFERS) {
+ buffer = owner->requestBuffer(index, usage);
+ }
+ }
+ return buffer;
+}
// ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/Layer.h b/libs/surfaceflinger/Layer.h
index 2867f2b..1310ecc 100644
--- a/libs/surfaceflinger/Layer.h
+++ b/libs/surfaceflinger/Layer.h
@@ -20,14 +20,15 @@
#include <stdint.h>
#include <sys/types.h>
+#include <ui/GraphicBuffer.h>
#include <ui/PixelFormat.h>
-
-#include <private/ui/SharedState.h>
-#include <private/ui/LayerState.h>
-
#include <pixelflinger/pixelflinger.h>
-#include "LayerBitmap.h"
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
#include "LayerBase.h"
#include "Transform.h"
@@ -36,12 +37,12 @@
// ---------------------------------------------------------------------------
class Client;
-class LayerBitmap;
-class MemoryDealer;
class FreezeLock;
// ---------------------------------------------------------------------------
+const size_t NUM_BUFFERS = 2;
+
class Layer : public LayerBaseClient
{
public:
@@ -49,68 +50,79 @@
static const char* const typeID;
virtual char const* getTypeID() const { return typeID; }
virtual uint32_t getTypeInfo() const { return typeInfo; }
-
+
Layer(SurfaceFlinger* flinger, DisplayID display,
- Client* c, int32_t i);
+ const sp<Client>& client, int32_t i);
virtual ~Layer();
- inline PixelFormat pixelFormat() const {
- return frontBuffer().pixelFormat();
- }
+ status_t setBuffers(uint32_t w, uint32_t h,
+ PixelFormat format, uint32_t flags=0);
- status_t setBuffers( Client* client,
- uint32_t w, uint32_t h,
- PixelFormat format, uint32_t flags=0);
+ void setDrawingSize(uint32_t w, uint32_t h);
virtual void onDraw(const Region& clip) const;
- virtual void initStates(uint32_t w, uint32_t h, uint32_t flags);
- virtual void setSizeChanged(uint32_t w, uint32_t h);
virtual uint32_t doTransaction(uint32_t transactionFlags);
- virtual Point getPhysicalSize() const;
virtual void lockPageFlip(bool& recomputeVisibleRegions);
virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion);
virtual void finishPageFlip();
virtual bool needsBlending() const { return mNeedsBlending; }
+ virtual bool needsDithering() const { return mNeedsDithering; }
virtual bool isSecure() const { return mSecure; }
- virtual GLuint getTextureName() const { return mTextureName; }
- virtual sp<Surface> getSurface() const;
-
- const LayerBitmap& getBuffer(int i) const { return mBuffers[i]; }
- LayerBitmap& getBuffer(int i) { return mBuffers[i]; }
-
+ virtual sp<Surface> createSurface() const;
+ virtual status_t ditch();
+
// only for debugging
- const sp<FreezeLock>& getFreezeLock() const { return mFreezeLock; }
+ inline sp<GraphicBuffer> getBuffer(int i) { return mBuffers[i]; }
+ // only for debugging
+ inline const sp<FreezeLock>& getFreezeLock() const { return mFreezeLock; }
+ // only for debugging
+ inline PixelFormat pixelFormat() const { return mFormat; }
private:
- inline const LayerBitmap&
- frontBuffer() const { return getBuffer(mFrontBufferIndex); }
- inline LayerBitmap&
- frontBuffer() { return getBuffer(mFrontBufferIndex); }
- inline const LayerBitmap&
- backBuffer() const { return getBuffer(1-mFrontBufferIndex); }
- inline LayerBitmap&
- backBuffer() { return getBuffer(1-mFrontBufferIndex); }
-
+ inline sp<GraphicBuffer> getFrontBufferLocked() {
+ return mBuffers[mFrontBufferIndex];
+ }
+
void reloadTexture(const Region& dirty);
- 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);
+ uint32_t getEffectiveUsage(uint32_t usage) const;
+ sp<GraphicBuffer> requestBuffer(int index, int usage);
+ void destroy();
+
+ class SurfaceLayer : public LayerBaseClient::Surface {
+ public:
+ SurfaceLayer(const sp<SurfaceFlinger>& flinger,
+ SurfaceID id, const sp<Layer>& owner);
+ ~SurfaceLayer();
+ private:
+ virtual sp<GraphicBuffer> requestBuffer(int index, int usage);
+ sp<Layer> getOwner() const {
+ return static_cast<Layer*>(Surface::getOwner().get());
+ }
+ };
+ friend class SurfaceLayer;
+
sp<Surface> mSurface;
bool mSecure;
- LayerBitmap mBuffers[2];
+ bool mNoEGLImageForSwBuffers;
int32_t mFrontBufferIndex;
bool mNeedsBlending;
- bool mResizeTransactionDone;
+ bool mNeedsDithering;
Region mPostedDirtyRegion;
sp<FreezeLock> mFreezeLock;
+ PixelFormat mFormat;
- GLuint mTextureName;
- GLuint mTextureWidth;
- GLuint mTextureHeight;
+ // protected by mLock
+ sp<GraphicBuffer> mBuffers[NUM_BUFFERS];
+ Texture mTextures[NUM_BUFFERS];
+ sp<GraphicBuffer> mHybridBuffer;
+ uint32_t mWidth;
+ uint32_t mHeight;
+
+ mutable Mutex mLock;
};
// ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp
index 0cf53f7..8003d22 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>
@@ -30,17 +30,10 @@
#include "clz.h"
#include "LayerBase.h"
-#include "LayerBlur.h"
#include "SurfaceFlinger.h"
#include "DisplayHardware/DisplayHardware.h"
-// We don't honor the premultiplied alpha flags, which means that
-// premultiplied surface may be composed using a non-premultiplied
-// equation. We do this because it may be a lot faster on some hardware
-// The correct value is HONOR_PREMULTIPLIED_ALPHA = 1
-#define HONOR_PREMULTIPLIED_ALPHA 0
-
namespace android {
// ---------------------------------------------------------------------------
@@ -53,19 +46,14 @@
// ---------------------------------------------------------------------------
-Vector<GLuint> LayerBase::deletedTextures;
-
-int32_t LayerBase::sIdentity = 0;
-
LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display)
: dpy(display), contentDirty(false),
mFlinger(flinger),
mTransformed(false),
+ mUseLinearFiltering(false),
mOrientation(0),
- mCanUseCopyBit(false),
mTransactionFlags(0),
mPremultipliedAlpha(true),
- mIdentity(uint32_t(android_atomic_inc(&sIdentity))),
mInvalidate(0)
{
const DisplayHardware& hw(flinger->graphicPlane(0).displayHardware());
@@ -95,26 +83,22 @@
if (flags & ISurfaceComposer::eNonPremultiplied)
mPremultipliedAlpha = false;
- mCurrentState.z = 0;
- mCurrentState.w = w;
- mCurrentState.h = h;
- mCurrentState.alpha = 0xFF;
- mCurrentState.flags = layerFlags;
- mCurrentState.sequence = 0;
+ mCurrentState.z = 0;
+ mCurrentState.w = w;
+ mCurrentState.h = h;
+ mCurrentState.requested_w = w;
+ mCurrentState.requested_h = h;
+ mCurrentState.alpha = 0xFF;
+ mCurrentState.flags = layerFlags;
+ mCurrentState.sequence = 0;
mCurrentState.transform.set(0, 0);
// drawing state & current state are identical
mDrawingState = mCurrentState;
}
-void LayerBase::commitTransaction(bool skipSize) {
- const uint32_t w = mDrawingState.w;
- const uint32_t h = mDrawingState.h;
+void LayerBase::commitTransaction() {
mDrawingState = mCurrentState;
- if (skipSize) {
- mDrawingState.w = w;
- mDrawingState.h = h;
- }
}
void LayerBase::forceVisibilityTransaction() {
// this can be called without SurfaceFlinger.mStateLock, but if we
@@ -133,9 +117,6 @@
return android_atomic_or(flags, &mTransactionFlags);
}
-void LayerBase::setSizeChanged(uint32_t w, uint32_t h) {
-}
-
bool LayerBase::setPosition(int32_t x, int32_t y) {
if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y)
return false;
@@ -153,11 +134,10 @@
return true;
}
bool LayerBase::setSize(uint32_t w, uint32_t h) {
- if (mCurrentState.w == w && mCurrentState.h == h)
+ if (mCurrentState.requested_w == w && mCurrentState.requested_h == h)
return false;
- setSizeChanged(w, h);
- mCurrentState.w = w;
- mCurrentState.h = h;
+ mCurrentState.requested_w = w;
+ mCurrentState.requested_h = h;
requestTransaction();
return true;
}
@@ -214,21 +194,39 @@
const Layer::State& front(drawingState());
const Layer::State& temp(currentState());
+ if ((front.requested_w != temp.requested_w) ||
+ (front.requested_h != temp.requested_h)) {
+ // resize the layer, set the physical size to the requested size
+ Layer::State& editTemp(currentState());
+ editTemp.w = temp.requested_w;
+ editTemp.h = temp.requested_h;
+ }
+
+ if ((front.w != temp.w) || (front.h != temp.h)) {
+ // invalidate and recompute the visible regions if needed
+ flags |= Layer::eVisibleRegion;
+ this->contentDirty = true;
+ }
+
if (temp.sequence != front.sequence) {
// invalidate and recompute the visible regions if needed
flags |= eVisibleRegion;
this->contentDirty = true;
- }
-
- // Commit the transaction
- commitTransaction(flags & eRestartTransaction);
- return flags;
-}
-Point LayerBase::getPhysicalSize() const
-{
- const Layer::State& front(drawingState());
- return Point(front.w, front.h);
+ const bool linearFiltering = mUseLinearFiltering;
+ mUseLinearFiltering = false;
+ if (!(mFlags & DisplayHardware::SLOW_CONFIG)) {
+ // we may use linear filtering, if the matrix scales us
+ const uint8_t type = temp.transform.getType();
+ if (!temp.transform.preserveRects() || (type >= Transform::SCALE)) {
+ mUseLinearFiltering = true;
+ }
+ }
+ }
+
+ // Commit the transaction
+ commitTransaction();
+ return flags;
}
void LayerBase::validateVisibility(const Transform& planeTransform)
@@ -237,9 +235,8 @@
const Transform tr(planeTransform * s.transform);
const bool transformed = tr.transformed();
- const Point size(getPhysicalSize());
- uint32_t w = size.x;
- uint32_t h = size.y;
+ uint32_t w = s.w;
+ uint32_t h = s.h;
tr.transform(mVertices[0], 0, 0);
tr.transform(mVertices[1], 0, h);
tr.transform(mVertices[2], w, h);
@@ -265,43 +262,6 @@
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::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 @@
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);
@@ -385,55 +347,52 @@
glBindTexture(GL_TEXTURE_2D, textureName);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- if (mFlags & DisplayHardware::SLOW_CONFIG) {
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- } else {
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- }
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
return textureName;
}
+void LayerBase::clearWithOpenGL(const Region& clip, GLclampx red,
+ GLclampx green, GLclampx blue,
+ GLclampx alpha) const
+{
+ const DisplayHardware& hw(graphicPlane(0).displayHardware());
+ const uint32_t fbHeight = hw.getHeight();
+ glColor4x(red,green,blue,alpha);
+ glDisable(GL_TEXTURE_2D);
+ glDisable(GL_BLEND);
+ glDisable(GL_DITHER);
+
+ Region::const_iterator it = clip.begin();
+ Region::const_iterator const end = clip.end();
+ glEnable(GL_SCISSOR_TEST);
+ 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);
+ }
+}
+
void LayerBase::clearWithOpenGL(const Region& clip) const
{
- const DisplayHardware& hw(graphicPlane(0).displayHardware());
- const uint32_t fbHeight = hw.getHeight();
- glColor4x(0,0,0,0);
- glDisable(GL_TEXTURE_2D);
- glDisable(GL_BLEND);
- glDisable(GL_DITHER);
- Rect r;
- Region::iterator iterator(clip);
- if (iterator) {
- glEnable(GL_SCISSOR_TEST);
- glVertexPointer(2, GL_FIXED, 0, mVertices);
- while (iterator.iterate(&r)) {
- const GLint sy = fbHeight - (r.top + r.height());
- glScissor(r.left, sy, r.width(), r.height());
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
- }
- }
+ clearWithOpenGL(clip,0,0,0,0);
}
-void LayerBase::drawWithOpenGL(const Region& clip,
- GLint textureName, const GGLSurface& t, int transform) const
+void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const
{
const DisplayHardware& hw(graphicPlane(0).displayHardware());
const uint32_t fbHeight = hw.getHeight();
const State& s(drawingState());
-
+
// bind our texture
- validateTexture(textureName);
+ validateTexture(texture.name);
+ uint32_t width = texture.width;
+ uint32_t height = texture.height;
+
glEnable(GL_TEXTURE_2D);
- // Dithering...
- if (s.flags & ISurfaceComposer::eLayerDither) {
- glEnable(GL_DITHER);
- } else {
- glDisable(GL_DITHER);
- }
-
if (UNLIKELY(s.alpha < 0xFF)) {
// We have an alpha-modulation. We need to modulate all
// texture components by alpha because we're always using
@@ -468,77 +427,55 @@
}
}
+ Region::const_iterator it = clip.begin();
+ Region::const_iterator const end = clip.end();
if (UNLIKELY(transformed()
|| !(mFlags & DisplayHardware::DRAW_TEXTURE_EXTENSION) ))
{
//StopWatch watch("GL transformed");
- Region::iterator iterator(clip);
- if (iterator) {
- // always use high-quality filtering with fast configurations
- bool fast = !(mFlags & DisplayHardware::SLOW_CONFIG);
- if (!fast && s.flags & ISurfaceComposer::eLayerFilter) {
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- }
- const GLfixed texCoords[4][2] = {
- { 0, 0 },
- { 0, 0x10000 },
- { 0x10000, 0x10000 },
- { 0x10000, 0 }
- };
+ const GLfixed texCoords[4][2] = {
+ { 0, 0 },
+ { 0, 0x10000 },
+ { 0x10000, 0x10000 },
+ { 0x10000, 0 }
+ };
- glMatrixMode(GL_TEXTURE);
- glLoadIdentity();
-
- if (transform == HAL_TRANSFORM_ROT_90) {
- glTranslatef(0, 1, 0);
- glRotatef(-90, 0, 0, 1);
- }
+ glMatrixMode(GL_TEXTURE);
+ glLoadIdentity();
- 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;
- // 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;
- glScalef(ws, hs, 1.0f);
- }
-
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glVertexPointer(2, GL_FIXED, 0, mVertices);
- glTexCoordPointer(2, GL_FIXED, 0, texCoords);
-
- 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);
- }
-
- if (!fast && s.flags & ISurfaceComposer::eLayerFilter) {
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- }
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ // the texture's source is rotated
+ if (texture.transform == HAL_TRANSFORM_ROT_90) {
+ // TODO: handle the other orientations
+ glTranslatef(0, 1, 0);
+ glRotatef(-90, 0, 0, 1);
}
+
+ if (texture.NPOTAdjust) {
+ glScalef(texture.wScale, texture.hScale, 1.0f);
+ }
+
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glVertexPointer(2, GL_FIXED, 0, mVertices);
+ glTexCoordPointer(2, GL_FIXED, 0, texCoords);
+
+ 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);
+ }
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
} else {
- Region::iterator iterator(clip);
- if (iterator) {
- Rect r;
- GLint crop[4] = { 0, t.height, t.width, -t.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)) {
- const GLint sy = fbHeight - (r.top + r.height());
- glScissor(r.left, sy, r.width(), r.height());
- glDrawTexiOES(x, y, 0, t.width, t.height);
- }
+ 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 + 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, width, height);
}
}
}
@@ -548,25 +485,34 @@
glBindTexture(GL_TEXTURE_2D, textureName);
// TODO: reload the texture if needed
// this is currently done in loadTexture() below
+ if (mUseLinearFiltering) {
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ } else {
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ }
+
+ if (needsDithering()) {
+ glEnable(GL_DITHER);
+ } else {
+ glDisable(GL_DITHER);
+ }
}
-void LayerBase::loadTexture(const Region& dirty,
- GLint textureName, const GGLSurface& t,
- GLuint& textureWidth, GLuint& textureHeight) const
+void LayerBase::loadTexture(Texture* texture,
+ const Region& dirty, const GGLSurface& t) const
{
- // TODO: defer the actual texture reload until LayerBase::validateTexture
- // is called.
+ if (texture->name == -1U) {
+ // uh?
+ return;
+ }
- uint32_t flags = mFlags;
- glBindTexture(GL_TEXTURE_2D, textureName);
-
- GLuint tw = t.width;
- GLuint th = t.height;
+ glBindTexture(GL_TEXTURE_2D, texture->name);
/*
* 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,161 +525,294 @@
*
* 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
*/
+ if (!(mFlags & DisplayHardware::NPOT_EXTENSION)) {
+ texture->NPOTAdjust = true;
+ }
- GLuint texture_w = tw;
- GLuint texture_h = th;
- if (!(flags & DisplayHardware::NPOT_EXTENSION)) {
+ if (texture->NPOTAdjust) {
// find the smallest power-of-two that will accommodate our surface
- texture_w = 1 << (31 - clz(t.width));
- 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;
+ texture->potWidth = 1 << (31 - clz(t.width));
+ texture->potHeight = 1 << (31 - clz(t.height));
+ if (texture->potWidth < t.width) texture->potWidth <<= 1;
+ if (texture->potHeight < t.height) texture->potHeight <<= 1;
+ texture->wScale = float(t.width) / texture->potWidth;
+ texture->hScale = float(t.height) / texture->potHeight;
} 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
+ texture->potWidth = t.width;
+ texture->potHeight = t.height;
+ }
- 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
- 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;
- }
- textureWidth = texture_w;
- textureHeight = texture_h;
+ Rect bounds(dirty.bounds());
+ GLvoid* data = 0;
+ if (texture->width != t.width || texture->height != t.height) {
+ texture->width = t.width;
+ texture->height = t.height;
+
+ // texture size changed, we need to create a new one
+ bounds.set(Rect(t.width, t.height));
+ if (t.width == texture->potWidth &&
+ t.height == texture->potHeight) {
+ // we can do it one pass
+ data = t.data;
}
- 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->potWidth, texture->potHeight, 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->potWidth, texture->potHeight, 0,
+ GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, data);
+ } else if (t.format == GGL_PIXEL_FORMAT_RGBA_8888 ||
+ t.format == GGL_PIXEL_FORMAT_RGBX_8888) {
+ glTexImage2D(GL_TEXTURE_2D, 0,
+ GL_RGBA, texture->potWidth, texture->potHeight, 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->potWidth, texture->potHeight, 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, texture->name, t.format);
+ }
+ }
+ if (!data) {
+ 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 ||
+ t.format == GGL_PIXEL_FORMAT_RGBX_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
+status_t LayerBase::initializeEglImage(
+ const sp<GraphicBuffer>& buffer, Texture* texture)
{
- return mCanUseCopyBit;
+ status_t err = NO_ERROR;
+
+ // we need to recreate the texture
+ EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
+
+ // free the previous image
+ if (texture->image != EGL_NO_IMAGE_KHR) {
+ eglDestroyImageKHR(dpy, texture->image);
+ texture->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
+ };
+ texture->image = eglCreateImageKHR(
+ dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
+ (EGLClientBuffer)clientBuf, attrs);
+
+ LOGE_IF(texture->image == EGL_NO_IMAGE_KHR,
+ "eglCreateImageKHR() failed. err=0x%4x",
+ eglGetError());
+
+ if (texture->image != EGL_NO_IMAGE_KHR) {
+ glBindTexture(GL_TEXTURE_2D, texture->name);
+ glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,
+ (GLeglImageOES)texture->image);
+ GLint error = glGetError();
+ if (UNLIKELY(error != GL_NO_ERROR)) {
+ // this failed, for instance, because we don't support NPOT.
+ // FIXME: do something!
+ LOGE("layer=%p, glEGLImageTargetTexture2DOES(%p) "
+ "failed err=0x%04x",
+ this, texture->image, error);
+ mFlags &= ~DisplayHardware::DIRECT_TEXTURE;
+ err = INVALID_OPERATION;
+ } else {
+ // Everything went okay!
+ texture->NPOTAdjust = false;
+ texture->dirty = false;
+ texture->width = clientBuf->width;
+ texture->height = clientBuf->height;
+ }
+ } else {
+ err = INVALID_OPERATION;
+ }
+ return err;
}
+
// ---------------------------------------------------------------------------
-LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
- Client* c, int32_t i)
- : LayerBase(flinger, display), client(c),
- lcblk( c ? &(c->ctrlblk->layers[i]) : 0 ),
- mIndex(i)
-{
- if (client) {
- client->bindLayer(this, i);
+int32_t LayerBaseClient::sIdentity = 0;
- // Initialize this layer's control block
- memset(this->lcblk, 0, sizeof(layer_cblk_t));
- this->lcblk->identity = mIdentity;
- Region::writeEmpty(&(this->lcblk->region[0]), sizeof(flat_region_t));
- Region::writeEmpty(&(this->lcblk->region[1]), sizeof(flat_region_t));
+LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
+ const sp<Client>& client, int32_t i)
+ : LayerBase(flinger, display), lcblk(NULL), client(client),
+ mIndex(i), mIdentity(uint32_t(android_atomic_inc(&sIdentity)))
+{
+ lcblk = new SharedBufferServer(
+ client->ctrlblk, i, NUM_BUFFERS,
+ mIdentity);
+}
+
+void LayerBaseClient::onFirstRef()
+{
+ sp<Client> client(this->client.promote());
+ if (client != 0) {
+ client->bindLayer(this, mIndex);
}
}
LayerBaseClient::~LayerBaseClient()
{
- if (client) {
+ sp<Client> client(this->client.promote());
+ if (client != 0) {
client->free(mIndex);
}
+ delete lcblk;
}
-int32_t LayerBaseClient::serverIndex() const {
- if (client) {
+int32_t LayerBaseClient::serverIndex() const
+{
+ sp<Client> client(this->client.promote());
+ if (client != 0) {
return (client->cid<<16)|mIndex;
}
return 0xFFFF0000 | mIndex;
}
-sp<LayerBaseClient::Surface> LayerBaseClient::getSurface() const
+sp<LayerBaseClient::Surface> LayerBaseClient::getSurface()
{
- return new Surface(clientIndex(), mIdentity);
+ 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));
+}
+
+// called with SurfaceFlinger::mStateLock as soon as the layer is entered
+// in the purgatory list
+void LayerBaseClient::onRemoved()
+{
+ // wake up the condition
+ lcblk->setStatus(NO_INIT);
+}
+
+// ---------------------------------------------------------------------------
+
+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;
+}
+
+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:
+ {
+ if (!mFlinger->mAccessSurfaceFlinger.checkCalling()) {
+ IPCThreadState* ipc = IPCThreadState::self();
+ const int pid = ipc->getCallingPid();
+ 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<GraphicBuffer> LayerBaseClient::Surface::requestBuffer(int index, int usage)
+{
+ 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..ed07b3f 100644
--- a/libs/surfaceflinger/LayerBase.h
+++ b/libs/surfaceflinger/LayerBase.h
@@ -20,8 +20,14 @@
#include <stdint.h>
#include <sys/types.h>
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include <private/ui/SharedBufferStack.h>
#include <private/ui/LayerState.h>
+#include <utils/RefBase.h>
+
#include <ui/Region.h>
#include <ui/Overlay.h>
@@ -33,14 +39,15 @@
// ---------------------------------------------------------------------------
-class SurfaceFlinger;
class DisplayHardware;
-class GraphicPlane;
class Client;
+class GraphicBuffer;
+class GraphicPlane;
+class SurfaceFlinger;
// ---------------------------------------------------------------------------
-class LayerBase
+class LayerBase : public RefBase
{
// poor man's dynamic_cast below
template<typename T>
@@ -69,10 +76,7 @@
}
- static Vector<GLuint> deletedTextures;
-
LayerBase(SurfaceFlinger* flinger, DisplayID display);
- virtual ~LayerBase();
DisplayID dpy;
mutable bool contentDirty;
@@ -83,6 +87,8 @@
struct State {
uint32_t w;
uint32_t h;
+ uint32_t requested_w;
+ uint32_t requested_h;
uint32_t z;
uint8_t alpha;
uint8_t flags;
@@ -102,7 +108,7 @@
bool setTransparentRegionHint(const Region& opaque);
bool setFlags(uint8_t flags, uint8_t mask);
- void commitTransaction(bool skipSize);
+ void commitTransaction();
bool requestTransaction();
void forceVisibilityTransaction();
@@ -133,11 +139,6 @@
virtual void initStates(uint32_t w, uint32_t h, uint32_t flags);
/**
- * setSizeChanged - called when the *current* state's size is changed.
- */
- virtual void setSizeChanged(uint32_t w, uint32_t h);
-
- /**
* doTransaction - process the transaction. This is a good place to figure
* out which attributes of the surface have changed.
*/
@@ -157,13 +158,6 @@
virtual void setCoveredRegion(const Region& coveredRegion);
/**
- * getPhysicalSize - returns the physical size of the drawing state of
- * the surface. If the surface is backed by a bitmap, this is the size of
- * the bitmap (as opposed to the size of the drawing state).
- */
- virtual Point getPhysicalSize() const;
-
- /**
* validateVisibility - cache a bunch of things
*/
virtual void validateVisibility(const Transform& globalTransform);
@@ -195,27 +189,42 @@
virtual bool needsBlending() const { return false; }
/**
+ * needsDithering - true if this surface needs dithering
+ */
+ virtual bool needsDithering() const { return false; }
+
+ /**
* transformed -- true is this surface needs a to be transformed
*/
virtual bool transformed() const { return mTransformed; }
/**
* 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
- };
+ /** Called from the main thread, when the surface is removed from the
+ * draw list */
+ virtual status_t ditch() { return NO_ERROR; }
+
+ /** called with the state lock when the surface is removed from the
+ * current list */
+ virtual void onRemoved() { };
+
+
+ enum { // flags for doTransaction()
+ eVisibleRegion = 0x00000002,
+ };
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;
}
@@ -229,28 +238,42 @@
GLuint createTexture() const;
- void drawWithOpenGL(const Region& clip,
- GLint textureName,
- const GGLSurface& surface,
- int transform = 0) const;
+ struct Texture {
+ Texture() : name(-1U), width(0), height(0),
+ image(EGL_NO_IMAGE_KHR), transform(0),
+ NPOTAdjust(false), dirty(true) { }
+ GLuint name;
+ GLuint width;
+ GLuint height;
+ GLuint potWidth;
+ GLuint potHeight;
+ GLfloat wScale;
+ GLfloat hScale;
+ EGLImageKHR image;
+ uint32_t transform;
+ bool NPOTAdjust;
+ bool dirty;
+ };
+ void clearWithOpenGL(const Region& clip, GLclampx r, GLclampx g,
+ GLclampx b, GLclampx alpha) const;
void clearWithOpenGL(const Region& clip) const;
+ void drawWithOpenGL(const Region& clip, const Texture& texture) const;
+ void loadTexture(Texture* texture,
+ const Region& dirty, const GGLSurface& t) const;
+ status_t initializeEglImage(
+ const sp<GraphicBuffer>& buffer, Texture* texture);
- void loadTexture(const Region& dirty,
- GLint textureName, const GGLSurface& t,
- GLuint& textureWidth, GLuint& textureHeight) const;
-
- bool canUseCopybit() const;
- SurfaceFlinger* mFlinger;
+ sp<SurfaceFlinger> mFlinger;
uint32_t mFlags;
// cached during validateVisibility()
bool mTransformed;
+ bool mUseLinearFiltering;
int32_t mOrientation;
GLfixed mVertices[4][2];
Rect mTransformedBounds;
- bool mCanUseCopyBit;
int mLeft;
int mTop;
@@ -262,16 +285,16 @@
// don't change, don't need a lock
bool mPremultipliedAlpha;
- // only read
- const uint32_t mIdentity;
-
// atomic
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;
};
@@ -286,67 +309,67 @@
virtual char const* getTypeID() const { return typeID; }
virtual uint32_t getTypeInfo() const { return typeInfo; }
+ // lcblk is (almost) only accessed from the main SF thread, in the places
+ // where it's not, a reference to Client must be held
+ SharedBufferServer* lcblk;
+
LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
- Client* client, int32_t i);
+ const sp<Client>& client, int32_t i);
virtual ~LayerBaseClient();
+ virtual void onFirstRef();
+ const wp<Client> client;
- 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;
+
+ virtual void onRemoved();
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;
- };
+ int32_t getToken() const { return mToken; }
+ int32_t getIdentity() const { return mIdentity; }
+
+ 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<GraphicBuffer> requestBuffer(int index, int usage);
+ 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;
+ // only read
+ const uint32_t mIdentity;
+ static int32_t sIdentity;
};
// ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/LayerBitmap.cpp b/libs/surfaceflinger/LayerBitmap.cpp
deleted file mode 100644
index 397ddc8..0000000
--- a/libs/surfaceflinger/LayerBitmap.cpp
+++ /dev/null
@@ -1,187 +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 <cutils/memory.h>
-#include <utils/Errors.h>
-#include <utils/Log.h>
-#include <utils/MemoryDealer.h>
-#include <utils/IMemory.h>
-#include <ui/PixelFormat.h>
-#include <pixelflinger/pixelflinger.h>
-
-#include "LayerBitmap.h"
-#include "SurfaceFlinger.h"
-#include "VRamHeap.h"
-
-
-namespace android {
-
-// ---------------------------------------------------------------------------
-
-LayerBitmap::LayerBitmap()
- : mAllocFlags(0), mOffset(0), mSize(-1U), mAlignment(2)
-{
- memset(&mSurface, 0, sizeof(mSurface));
-}
-
-LayerBitmap::~LayerBitmap()
-{
- mSurface.data = 0;
-}
-
-status_t LayerBitmap::init(const sp<MemoryDealer>& allocator)
-{
- if (mAllocator != NULL)
- return BAD_VALUE;
- mAllocator = allocator;
- return NO_ERROR;
-}
-
-status_t LayerBitmap::setBits(uint32_t w, uint32_t h, uint32_t alignment,
- PixelFormat format, uint32_t flags)
-{
- 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);
- }
-
- /* 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)
- */
- 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;
- } 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 (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;
- }
- return NO_ERROR;
-}
-
-void LayerBitmap::clear()
-{
- // 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);
- //}
- }
-}
-
-status_t LayerBitmap::getInfo(surface_info_t* info) const
-{
- 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)
-{
- int err = setBits(w, h, mAlignment, pixelFormat(), SECURE_BITS);
- return err;
-}
-
-size_t LayerBitmap::size() const
-{
- return mSize;
-}
-
-void LayerBitmap::getBitmapSurface(copybit_image_t* img) const
-{
- 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();
-}
-
-// ---------------------------------------------------------------------------
-
-}; // namespace android
diff --git a/libs/surfaceflinger/LayerBitmap.h b/libs/surfaceflinger/LayerBitmap.h
deleted file mode 100644
index 9ad64c4..0000000
--- a/libs/surfaceflinger/LayerBitmap.h
+++ /dev/null
@@ -1,84 +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_LAYER_BITMAP_H
-#define ANDROID_LAYER_BITMAP_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/Atomic.h>
-#include <ui/PixelFormat.h>
-#include <ui/Rect.h>
-#include <private/ui/SharedState.h>
-#include <pixelflinger/pixelflinger.h>
-
-class copybit_image_t;
-
-namespace android {
-
-// ---------------------------------------------------------------------------
-
-class IMemory;
-class MemoryDealer;
-class LayerBitmap;
-
-// ---------------------------------------------------------------------------
-
-class LayerBitmap
-{
-public:
-
- enum {
- // erase memory to ensure security when necessary
- SECURE_BITS = 0x00000001
- };
-
- LayerBitmap();
- ~LayerBitmap();
- status_t init(const sp<MemoryDealer>& allocator);
-
- status_t setBits(uint32_t w, uint32_t h, uint32_t alignment,
- PixelFormat format, uint32_t flags = 0);
- void clear();
-
- status_t getInfo(surface_info_t* info) const;
- status_t resize(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;
-
-private:
- sp<MemoryDealer> mAllocator;
- sp<IMemory> mBitsMemory;
- uint32_t mAllocFlags;
- ssize_t mOffset;
- GGLSurface mSurface;
- size_t mSize;
- uint32_t mAlignment;
-};
-
-}; // namespace android
-
-#endif // ANDROID_LAYER_BITMAP_H
diff --git a/libs/surfaceflinger/LayerBlur.cpp b/libs/surfaceflinger/LayerBlur.cpp
index d3e456f..5fd7904 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>
@@ -26,6 +24,7 @@
#include <GLES/gl.h>
#include <GLES/glext.h>
+#include "clz.h"
#include "BlurFilter.h"
#include "LayerBlur.h"
#include "SurfaceFlinger.h"
@@ -40,17 +39,18 @@
// ---------------------------------------------------------------------------
LayerBlur::LayerBlur(SurfaceFlinger* flinger, DisplayID display,
- Client* client, int32_t i)
- : LayerBaseClient(flinger, display, client, i), mCacheDirty(true),
- mRefreshCache(true), mCacheAge(0), mTextureName(-1U)
+ const sp<Client>& client, int32_t i)
+ : LayerBaseClient(flinger, display, client, i), mCacheDirty(true),
+ mRefreshCache(true), mCacheAge(0), mTextureName(-1U),
+ mWidthScale(1.0f), mHeightScale(1.0f),
+ mBlurFormat(GGL_PIXEL_FORMAT_RGB_565)
{
}
LayerBlur::~LayerBlur()
{
if (mTextureName != -1U) {
- //glDeleteTextures(1, &mTextureName);
- deletedTextures.add(mTextureName);
+ glDeleteTextures(1, &mTextureName);
}
}
@@ -137,44 +137,73 @@
// create the texture name the first time
// can't do that in the ctor, because it runs in another thread.
glGenTextures(1, &mTextureName);
+ glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES, &mReadFormat);
+ glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE_OES, &mReadType);
+ if (mReadFormat != GL_RGB || mReadType != GL_UNSIGNED_SHORT_5_6_5) {
+ mReadFormat = GL_RGBA;
+ mReadType = GL_UNSIGNED_BYTE;
+ mBlurFormat = GGL_PIXEL_FORMAT_RGBX_8888;
+ }
}
- 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);
-
+
if (mRefreshCache) {
mRefreshCache = false;
mAutoRefreshPending = false;
-
- // allocate enough memory for 4-bytes (2 pixels) aligned data
- const int32_t s = (w + 1) & ~1;
- uint16_t* const pixels = (uint16_t*)malloc(s*h*2);
+
+ int32_t pixelSize = 4;
+ int32_t s = w;
+ if (mReadType == GL_UNSIGNED_SHORT_5_6_5) {
+ // allocate enough memory for 4-bytes (2 pixels) aligned data
+ s = (w + 1) & ~1;
+ pixelSize = 2;
+ }
+
+ uint16_t* const pixels = (uint16_t*)malloc(s*h*pixelSize);
// This reads the frame-buffer, so a h/w GL would have to
// finish() its rendering first. we don't want to do that
// too often. Read data is 4-bytes aligned.
- glReadPixels(X, Y, w, h, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);
-
+ glReadPixels(X, Y, w, h, mReadFormat, mReadType, pixels);
+
// blur that texture.
GGLSurface bl;
bl.version = sizeof(GGLSurface);
bl.width = w;
bl.height = h;
bl.stride = s;
- bl.format = GGL_PIXEL_FORMAT_RGB_565;
+ bl.format = mBlurFormat;
bl.data = (GGLubyte*)pixels;
blurFilter(&bl, 8, 2);
-
- // NOTE: this works only because we have POT. we'd have to round the
- // texture size up, otherwise.
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0,
- GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);
+
+ if (mFlags & (DisplayHardware::NPOT_EXTENSION)) {
+ glTexImage2D(GL_TEXTURE_2D, 0, mReadFormat, w, h, 0,
+ mReadFormat, mReadType, pixels);
+ mWidthScale = 1.0f / w;
+ mHeightScale =-1.0f / h;
+ mYOffset = 0;
+ } else {
+ GLuint tw = 1 << (31 - clz(w));
+ GLuint th = 1 << (31 - clz(h));
+ if (tw < GLuint(w)) tw <<= 1;
+ if (th < GLuint(h)) th <<= 1;
+ glTexImage2D(GL_TEXTURE_2D, 0, mReadFormat, tw, th, 0,
+ mReadFormat, mReadType, NULL);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h,
+ mReadFormat, mReadType, pixels);
+ mWidthScale = 1.0f / tw;
+ mHeightScale =-1.0f / th;
+ mYOffset = th-h;
+ }
free((void*)pixels);
}
-
+
const State& s = drawingState();
if (UNLIKELY(s.alpha < 0xFF)) {
const GGLfixed alpha = (s.alpha << 16)/255;
@@ -186,7 +215,12 @@
glDisable(GL_BLEND);
}
- glDisable(GL_DITHER);
+ if (mFlags & DisplayHardware::SLOW_CONFIG) {
+ glDisable(GL_DITHER);
+ } else {
+ glEnable(GL_DITHER);
+ }
+
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@@ -196,37 +230,34 @@
// This is a very rare scenario.
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
- glScalef(1.0f/w, -1.0f/h, 1);
- glTranslatef(-x, -y, 0);
+ glScalef(mWidthScale, mHeightScale, 1);
+ glTranslatef(-x, mYOffset - y, 0);
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);
}
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
} 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);
}
}
}
-
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
// ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/LayerBlur.h b/libs/surfaceflinger/LayerBlur.h
index 24b1156..2e9d7c6 100644
--- a/libs/surfaceflinger/LayerBlur.h
+++ b/libs/surfaceflinger/LayerBlur.h
@@ -39,7 +39,7 @@
virtual uint32_t getTypeInfo() const { return typeInfo; }
LayerBlur(SurfaceFlinger* flinger, DisplayID display,
- Client* client, int32_t i);
+ const sp<Client>& client, int32_t i);
virtual ~LayerBlur();
virtual void onDraw(const Region& clip) const;
@@ -56,6 +56,12 @@
mutable bool mAutoRefreshPending;
nsecs_t mCacheAge;
mutable GLuint mTextureName;
+ mutable GLfloat mWidthScale;
+ mutable GLfloat mHeightScale;
+ mutable GLfloat mYOffset;
+ mutable GLint mReadFormat;
+ mutable GLint mReadType;
+ mutable uint32_t mBlurFormat;
};
// ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp
index 00fab70..a36304c 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,29 +23,28 @@
#include <utils/Log.h>
#include <utils/StopWatch.h>
-#include <utils/IPCThreadState.h>
-#include <utils/IServiceManager.h>
-
+#include <ui/GraphicBuffer.h>
#include <ui/PixelFormat.h>
-#include <ui/EGLDisplaySurface.h>
+#include <ui/FramebufferNativeWindow.h>
+
+#include <hardware/copybit.h>
#include "LayerBuffer.h"
#include "SurfaceFlinger.h"
-#include "VRamHeap.h"
#include "DisplayHardware/DisplayHardware.h"
-
namespace android {
// ---------------------------------------------------------------------------
const uint32_t LayerBuffer::typeInfo = LayerBaseClient::typeInfo | 0x20;
const char* const LayerBuffer::typeID = "LayerBuffer";
+gralloc_module_t const* LayerBuffer::sGrallocModule = 0;
// ---------------------------------------------------------------------------
LayerBuffer::LayerBuffer(SurfaceFlinger* flinger, DisplayID display,
- Client* client, int32_t i)
+ const sp<Client>& client, int32_t i)
: LayerBaseClient(flinger, display, client, i),
mNeedsBlending(false)
{
@@ -55,30 +52,34 @@
LayerBuffer::~LayerBuffer()
{
- sp<SurfaceBuffer> s(getClientSurface());
- if (s != 0) {
- s->disown();
- mClientSurface.clear();
+}
+
+void LayerBuffer::onFirstRef()
+{
+ LayerBaseClient::onFirstRef();
+ mSurface = new SurfaceLayerBuffer(mFlinger, clientIndex(),
+ const_cast<LayerBuffer *>(this));
+
+ hw_module_t const* module = (hw_module_t const*)sGrallocModule;
+ if (!module) {
+ // NOTE: technically there is a race here, but it shouldn't
+ // cause any problem since hw_get_module() always returns
+ // the same value.
+ if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {
+ sGrallocModule = (gralloc_module_t const *)module;
+ }
}
}
-sp<LayerBuffer::SurfaceBuffer> LayerBuffer::getClientSurface() const
+sp<LayerBaseClient::Surface> LayerBuffer::createSurface() const
{
- Mutex::Autolock _l(mLock);
- return mClientSurface.promote();
+ return mSurface;
}
-sp<LayerBaseClient::Surface> LayerBuffer::getSurface() const
+status_t LayerBuffer::ditch()
{
- 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;
+ mSurface.clear();
+ return NO_ERROR;
}
bool LayerBuffer::needsBlending() const {
@@ -140,6 +141,14 @@
return false;
}
+void LayerBuffer::serverDestroy()
+{
+ sp<Source> source(clearSource());
+ if (source != 0) {
+ source->destroy();
+ }
+}
+
/**
* This creates a "buffer" source for this surface
*/
@@ -189,85 +198,52 @@
}
// ============================================================================
-// LayerBuffer::SurfaceBuffer
+// LayerBuffer::SurfaceLayerBuffer
// ============================================================================
-LayerBuffer::SurfaceBuffer::SurfaceBuffer(SurfaceID id, LayerBuffer* owner)
-: LayerBaseClient::Surface(id, owner->getIdentity()), mOwner(owner)
+LayerBuffer::SurfaceLayerBuffer::SurfaceLayerBuffer(const sp<SurfaceFlinger>& flinger,
+ SurfaceID id, const sp<LayerBuffer>& owner)
+ : LayerBaseClient::Surface(flinger, id, owner->getIdentity(), owner)
{
}
-LayerBuffer::SurfaceBuffer::~SurfaceBuffer()
+LayerBuffer::SurfaceLayerBuffer::~SurfaceLayerBuffer()
{
unregisterBuffers();
- mOwner = 0;
}
-status_t LayerBuffer::SurfaceBuffer::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+status_t LayerBuffer::SurfaceLayerBuffer::registerBuffers(
+ const ISurface::BufferHeap& buffers)
{
- switch (code) {
- case REGISTER_BUFFERS:
- case UNREGISTER_BUFFERS:
- case CREATE_OVERLAY:
- {
- // codes that require permission check
- IPCThreadState* ipc = IPCThreadState::self();
- const int pid = ipc->getCallingPid();
- const int self_pid = getpid();
- if (LIKELY(pid != self_pid)) {
- // we're called from a different process, do the real check
- if (!checkCallingPermission(
- String16("android.permission.ACCESS_SURFACE_FLINGER")))
- {
- const int uid = ipc->getCallingUid();
- LOGE("Permission Denial: "
- "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
- return PERMISSION_DENIED;
- }
- }
- }
- }
- return LayerBaseClient::Surface::onTransact(code, data, reply, flags);
-}
-
-status_t LayerBuffer::SurfaceBuffer::registerBuffers(const ISurface::BufferHeap& buffers)
-{
- LayerBuffer* owner(getOwner());
- if (owner)
+ sp<LayerBuffer> owner(getOwner());
+ if (owner != 0)
return owner->registerBuffers(buffers);
return NO_INIT;
}
-void LayerBuffer::SurfaceBuffer::postBuffer(ssize_t offset)
+void LayerBuffer::SurfaceLayerBuffer::postBuffer(ssize_t offset)
{
- LayerBuffer* owner(getOwner());
- if (owner)
+ sp<LayerBuffer> owner(getOwner());
+ if (owner != 0)
owner->postBuffer(offset);
}
-void LayerBuffer::SurfaceBuffer::unregisterBuffers()
+void LayerBuffer::SurfaceLayerBuffer::unregisterBuffers()
{
- LayerBuffer* owner(getOwner());
- if (owner)
+ sp<LayerBuffer> owner(getOwner());
+ if (owner != 0)
owner->unregisterBuffers();
}
-sp<OverlayRef> LayerBuffer::SurfaceBuffer::createOverlay(
+sp<OverlayRef> LayerBuffer::SurfaceLayerBuffer::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
// ============================================================================
@@ -276,20 +252,36 @@
: mBufferHeap(buffers)
{
NativeBuffer& src(mNativeBuffer);
- src.crop.l = 0;
- src.crop.t = 0;
- src.crop.r = buffers.w;
- src.crop.b = buffers.h;
- src.img.w = buffers.hor_stride ?: buffers.w;
- src.img.h = buffers.ver_stride ?: buffers.h;
- src.img.format = buffers.format;
- src.img.offset = offset;
- src.img.base = buffers.heap->base();
- src.img.fd = buffers.heap->heapID();
+ src.img.handle = 0;
+
+ gralloc_module_t const * module = LayerBuffer::getGrallocModule();
+ if (module && module->perform) {
+ int err = module->perform(module,
+ GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER,
+ buffers.heap->heapID(), buffers.heap->getSize(),
+ offset, buffers.heap->base(),
+ &src.img.handle);
+
+ if (err == NO_ERROR) {
+ src.crop.l = 0;
+ src.crop.t = 0;
+ src.crop.r = buffers.w;
+ src.crop.b = buffers.h;
+
+ src.img.w = buffers.hor_stride ?: buffers.w;
+ src.img.h = buffers.ver_stride ?: buffers.h;
+ src.img.format = buffers.format;
+ src.img.base = (void*)(intptr_t(buffers.heap->base()) + offset);
+ }
+ }
}
LayerBuffer::Buffer::~Buffer()
{
+ NativeBuffer& src(mNativeBuffer);
+ if (src.img.handle) {
+ native_handle_delete(src.img.handle);
+ }
}
// ============================================================================
@@ -323,8 +315,7 @@
LayerBuffer::BufferSource::BufferSource(LayerBuffer& layer,
const ISurface::BufferHeap& buffers)
- : Source(layer), mStatus(NO_ERROR),
- mBufferSize(0), mTextureName(-1U)
+ : Source(layer), mStatus(NO_ERROR), mBufferSize(0)
{
if (buffers.heap == NULL) {
// this is allowed, but in this case, it is illegal to receive
@@ -363,13 +354,16 @@
mLayer.setNeedsBlending((info.h_alpha - info.l_alpha) > 0);
mBufferSize = info.getScanlineSize(buffers.hor_stride)*buffers.ver_stride;
mLayer.forceVisibilityTransaction();
-
}
LayerBuffer::BufferSource::~BufferSource()
{
- if (mTextureName != -1U) {
- LayerBase::deletedTextures.add(mTextureName);
+ if (mTexture.name != -1U) {
+ glDeleteTextures(1, &mTexture.name);
+ }
+ if (mTexture.image != EGL_NO_IMAGE_KHR) {
+ EGLDisplay dpy(mLayer.mFlinger->graphicPlane(0).getEGLDisplay());
+ eglDestroyImageKHR(dpy, mTexture.image);
}
}
@@ -377,7 +371,7 @@
{
ISurface::BufferHeap buffers;
{ // scope for the lock
- Mutex::Autolock _l(mLock);
+ Mutex::Autolock _l(mBufferSourceLock);
buffers = mBufferHeap;
if (buffers.heap != 0) {
const size_t memorySize = buffers.heap->getSize();
@@ -402,7 +396,7 @@
void LayerBuffer::BufferSource::unregisterBuffers()
{
- Mutex::Autolock _l(mLock);
+ Mutex::Autolock _l(mBufferSourceLock);
mBufferHeap.heap.clear();
mBuffer.clear();
mLayer.invalidate();
@@ -410,13 +404,13 @@
sp<LayerBuffer::Buffer> LayerBuffer::BufferSource::getBuffer() const
{
- Mutex::Autolock _l(mLock);
+ Mutex::Autolock _l(mBufferSourceLock);
return mBuffer;
}
void LayerBuffer::BufferSource::setBuffer(const sp<LayerBuffer::Buffer>& buffer)
{
- Mutex::Autolock _l(mLock);
+ Mutex::Autolock _l(mBufferSourceLock);
mBuffer = buffer;
}
@@ -427,113 +421,40 @@
void LayerBuffer::BufferSource::onDraw(const Region& clip) const
{
- sp<Buffer> buffer(getBuffer());
- if (UNLIKELY(buffer == 0)) {
+ sp<Buffer> ourBuffer(getBuffer());
+ if (UNLIKELY(ourBuffer == 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();
+ NativeBuffer src(ourBuffer->getBuffer());
+ const Rect transformedBounds(mLayer.getTransformedBounds());
- 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));
- }
+ if (UNLIKELY(mTexture.name == -1LU)) {
+ mTexture.name = mLayer.createTexture();
}
- if (!can_use_copybit || err) {
- if (UNLIKELY(mTextureName == -1LU)) {
- mTextureName = mLayer.createTexture();
- }
- GLuint w = 0;
- GLuint h = 0;
+#if defined(EGL_ANDROID_image_native_buffer)
+ if (mLayer.mFlags & DisplayHardware::DIRECT_TEXTURE) {
+ // NOTE: Assume the buffer is allocated with the proper USAGE flags
+ sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(
+ src.crop.r, src.crop.b, src.img.format,
+ GraphicBuffer::USAGE_HW_TEXTURE,
+ src.img.w, src.img.handle, false);
+
+ graphicBuffer->setVerticalStride(src.img.h);
+
+ err = mLayer.initializeEglImage(graphicBuffer, &mTexture);
+ }
+#endif
+ else {
+ err = INVALID_OPERATION;
+ }
+
+ if (err != NO_ERROR) {
+ // slower fallback
GGLSurface t;
t.version = sizeof(GGLSurface);
t.width = src.crop.r;
@@ -541,13 +462,14 @@
t.stride = src.img.w;
t.vstride= src.img.h;
t.format = src.img.format;
- t.data = (GGLubyte*)(intptr_t(src.img.base) + src.img.offset);
+ t.data = (GGLubyte*)src.img.base;
const Region dirty(Rect(t.width, t.height));
- mLayer.loadTexture(dirty, mTextureName, t, w, h);
- mLayer.drawWithOpenGL(clip, mTextureName, t, mBufferHeap.transform);
+ mLayer.loadTexture(&mTexture, dirty, t);
}
-}
+ mTexture.transform = mBufferHeap.transform;
+ mLayer.drawWithOpenGL(clip, mTexture);
+}
// ---------------------------------------------------------------------------
@@ -580,15 +502,15 @@
mFormat = overlay->format;
mWidthStride = overlay->w_stride;
mHeightStride = overlay->h_stride;
+ mInitialized = false;
mOverlayHandle = overlay->getHandleRef(overlay);
- // NOTE: here it's okay to acquire a reference to "this"m as long as
- // the reference is not released before we leave the ctor.
- sp<OverlayChannel> channel = new OverlayChannel(this);
+ sp<OverlayChannel> channel = new OverlayChannel( &layer );
*overlayRef = new OverlayRef(mOverlayHandle, channel,
mWidth, mHeight, mFormat, mWidthStride, mHeightStride);
+ mLayer.mFlinger->signalEvent();
}
LayerBuffer::OverlaySource::~OverlaySource()
@@ -599,6 +521,15 @@
}
}
+void LayerBuffer::OverlaySource::onDraw(const Region& clip) const
+{
+ // this would be where the color-key would be set, should we need it.
+ GLclampx red = 0;
+ GLclampx green = 0;
+ GLclampx blue = 0;
+ mLayer.clearWithOpenGL(clip, red, green, blue, 0);
+}
+
void LayerBuffer::OverlaySource::onTransaction(uint32_t flags)
{
const Layer::State& front(mLayer.drawingState());
@@ -614,37 +545,33 @@
// this code-path must be as tight as possible, it's called each time
// the screen is composited.
if (UNLIKELY(mOverlay != 0)) {
- if (mVisibilityChanged) {
+ if (mVisibilityChanged || !mInitialized) {
mVisibilityChanged = false;
- const Rect& bounds = mLayer.getTransformedBounds();
+ mInitialized = true;
+ const Rect bounds(mLayer.getTransformedBounds());
int x = bounds.left;
int y = bounds.top;
int w = bounds.width();
int h = bounds.height();
// we need a lock here to protect "destroy"
- Mutex::Autolock _l(mLock);
+ Mutex::Autolock _l(mOverlaySourceLock);
if (mOverlay) {
overlay_control_device_t* overlay_dev = mOverlayDevice;
overlay_dev->setPosition(overlay_dev, mOverlay, x,y,w,h);
- overlay_dev->setParameter(overlay_dev, mOverlay,
+ overlay_dev->setParameter(overlay_dev, mOverlay,
OVERLAY_TRANSFORM, mLayer.getOrientation());
+ overlay_dev->commit(overlay_dev, mOverlay);
}
}
}
}
-void LayerBuffer::OverlaySource::serverDestroy()
-{
- mLayer.clearSource();
- destroyOverlay();
-}
-
-void LayerBuffer::OverlaySource::destroyOverlay()
+void LayerBuffer::OverlaySource::destroy()
{
// we need a lock here to protect "onVisibilityResolved"
- Mutex::Autolock _l(mLock);
- if (mOverlay) {
+ Mutex::Autolock _l(mOverlaySourceLock);
+ if (mOverlay && mOverlayDevice) {
overlay_control_device_t* overlay_dev = mOverlayDevice;
overlay_dev->destroyOverlay(overlay_dev, mOverlay);
mOverlay = 0;
diff --git a/libs/surfaceflinger/LayerBuffer.h b/libs/surfaceflinger/LayerBuffer.h
index 2dc77f1..47482f4 100644
--- a/libs/surfaceflinger/LayerBuffer.h
+++ b/libs/surfaceflinger/LayerBuffer.h
@@ -20,21 +20,20 @@
#include <stdint.h>
#include <sys/types.h>
-#include <utils/IMemory.h>
-#include <private/ui/LayerState.h>
-#include <EGL/eglnatives.h>
-
#include "LayerBase.h"
-#include "LayerBitmap.h"
+
+struct copybit_device_t;
namespace android {
// ---------------------------------------------------------------------------
-class MemoryDealer;
+class Buffer;
class Region;
class OverlayRef;
+// ---------------------------------------------------------------------------
+
class LayerBuffer : public LayerBaseClient
{
class Source : public LightRefBase<Source> {
@@ -47,11 +46,11 @@
virtual void postBuffer(ssize_t offset);
virtual void unregisterBuffers();
virtual bool transformed() const;
+ virtual void destroy() { }
protected:
LayerBuffer& mLayer;
};
-
public:
static const uint32_t typeInfo;
static const char* const typeID;
@@ -59,12 +58,14 @@
virtual uint32_t getTypeInfo() const { return typeInfo; }
LayerBuffer(SurfaceFlinger* flinger, DisplayID display,
- Client* client, int32_t i);
+ const sp<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);
@@ -78,16 +79,23 @@
sp<Source> getSource() const;
sp<Source> clearSource();
void setNeedsBlending(bool blending);
- const Rect& getTransformedBounds() const {
+ Rect getTransformedBounds() const {
return mTransformedBounds;
}
+ void serverDestroy();
+
private:
struct NativeBuffer {
copybit_image_t img;
copybit_rect_t crop;
};
+ static gralloc_module_t const* sGrallocModule;
+ static gralloc_module_t const* getGrallocModule() {
+ return sGrallocModule;
+ }
+
class Buffer : public LightRefBase<Buffer> {
public:
Buffer(const ISurface::BufferHeap& buffers, ssize_t offset);
@@ -120,15 +128,15 @@
virtual void postBuffer(ssize_t offset);
virtual void unregisterBuffers();
virtual bool transformed() const;
+ virtual void destroy() { }
private:
- mutable Mutex mLock;
- sp<Buffer> mBuffer;
- status_t mStatus;
- ISurface::BufferHeap mBufferHeap;
- size_t mBufferSize;
- mutable sp<MemoryDealer> mTemporaryDealer;
- mutable LayerBitmap mTempBitmap;
- mutable GLuint mTextureName;
+ mutable Mutex mBufferSourceLock;
+ sp<Buffer> mBuffer;
+ status_t mStatus;
+ ISurface::BufferHeap mBufferHeap;
+ size_t mBufferSize;
+ mutable sp<GraphicBuffer> mTempBitmap;
+ mutable LayerBase::Texture mTexture;
};
class OverlaySource : public Source {
@@ -137,30 +145,26 @@
sp<OverlayRef>* overlayRef,
uint32_t w, uint32_t h, int32_t format);
virtual ~OverlaySource();
+ virtual void onDraw(const Region& clip) const;
virtual void onTransaction(uint32_t flags);
virtual void onVisibilityResolved(const Transform& planeTransform);
+ virtual void destroy();
private:
- void serverDestroy();
- void destroyOverlay();
+
class OverlayChannel : public BnOverlay {
- mutable Mutex mLock;
- sp<OverlaySource> mSource;
+ wp<LayerBuffer> mLayer;
virtual void destroy() {
- sp<OverlaySource> source;
- { // scope for the lock;
- Mutex::Autolock _l(mLock);
- source = mSource;
- mSource.clear();
- }
- if (source != 0) {
- source->serverDestroy();
+ sp<LayerBuffer> layer(mLayer.promote());
+ if (layer != 0) {
+ layer->serverDestroy();
}
}
public:
- OverlayChannel(const sp<OverlaySource>& source)
- : mSource(source) {
+ OverlayChannel(const sp<LayerBuffer>& layer)
+ : mLayer(layer) {
}
};
+
friend class OverlayChannel;
bool mVisibilityChanged;
@@ -172,41 +176,35 @@
int32_t mFormat;
int32_t mWidthStride;
int32_t mHeightStride;
- mutable Mutex mLock;
+ mutable Mutex mOverlaySourceLock;
+ bool mInitialized;
};
- class SurfaceBuffer : public LayerBaseClient::Surface
+ class SurfaceLayerBuffer : public LayerBaseClient::Surface
{
public:
- SurfaceBuffer(SurfaceID id, LayerBuffer* owner);
- virtual ~SurfaceBuffer();
- virtual status_t onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
+ SurfaceLayerBuffer(const sp<SurfaceFlinger>& flinger,
+ SurfaceID id, const sp<LayerBuffer>& owner);
+ virtual ~SurfaceLayerBuffer();
+
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..fd61e30 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>
@@ -23,9 +21,10 @@
#include <utils/Errors.h>
#include <utils/Log.h>
+#include <ui/GraphicBuffer.h>
+
#include "LayerDim.h"
#include "SurfaceFlinger.h"
-#include "VRamHeap.h"
#include "DisplayHardware/DisplayHardware.h"
namespace android {
@@ -33,27 +32,76 @@
const uint32_t LayerDim::typeInfo = LayerBaseClient::typeInfo | 0x10;
const char* const LayerDim::typeID = "LayerDim";
-sp<MemoryDealer> LayerDim::mDimmerDealer;
-LayerBitmap LayerDim::mDimmerBitmap;
+
+bool LayerDim::sUseTexture;
+GLuint LayerDim::sTexId;
+EGLImageKHR LayerDim::sImage;
+int32_t LayerDim::sWidth;
+int32_t LayerDim::sHeight;
// ---------------------------------------------------------------------------
LayerDim::LayerDim(SurfaceFlinger* flinger, DisplayID display,
- Client* client, int32_t i)
- : LayerBaseClient(flinger, display, client, i)
+ const sp<Client>& client, int32_t i)
+ : LayerBaseClient(flinger, display, client, i)
{
}
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();
+ sTexId = -1;
+ sImage = EGL_NO_IMAGE_KHR;
+ sWidth = w;
+ sHeight = h;
+ sUseTexture = false;
+
+#if defined(DIM_WITH_TEXTURE) && defined(EGL_ANDROID_image_native_buffer)
+
+#warning "using a texture to implement LayerDim"
+
+ /* On some h/w like msm7K, it is faster to use a texture because the
+ * software renderer will defer to copybit, for this to work we need to
+ * use an EGLImage texture so copybit can actually make use of it.
+ * This burns a full-screen worth of graphic memory.
+ */
+
+ const DisplayHardware& hw(flinger->graphicPlane(0).displayHardware());
+ uint32_t flags = hw.getFlags();
+
+ if (LIKELY(flags & DisplayHardware::DIRECT_TEXTURE)) {
+ sp<GraphicBuffer> buffer = new GraphicBuffer(w, h, PIXEL_FORMAT_RGB_565,
+ GraphicBuffer::USAGE_SW_WRITE_OFTEN |
+ GraphicBuffer::USAGE_HW_TEXTURE);
+
+ android_native_buffer_t* clientBuf = buffer->getNativeBuffer();
+
+ glGenTextures(1, &sTexId);
+ glBindTexture(GL_TEXTURE_2D, sTexId);
+
+ EGLDisplay dpy = eglGetCurrentDisplay();
+ sImage = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
+ EGL_NATIVE_BUFFER_ANDROID, (EGLClientBuffer)clientBuf, 0);
+ if (sImage == EGL_NO_IMAGE_KHR) {
+ LOGE("eglCreateImageKHR() failed. err=0x%4x", eglGetError());
+ return;
+ }
+
+ glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)sImage);
+ GLint error = glGetError();
+ if (error != GL_NO_ERROR) {
+ eglDestroyImageKHR(dpy, sImage);
+ LOGE("glEGLImageTargetTexture2DOES() failed. err=0x%4x", error);
+ return;
+ }
+
+ // initialize the texture with zeros
+ GGLSurface t;
+ buffer->lock(&t, GRALLOC_USAGE_SW_WRITE_OFTEN);
+ memset(t.data, 0, t.stride * t.height * 2);
+ buffer->unlock();
+ sUseTexture = true;
}
+#endif
}
LayerDim::~LayerDim()
@@ -63,49 +111,56 @@
void LayerDim::onDraw(const Region& clip) const
{
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);
+ const GGLfixed alpha = (s.alpha << 16)/255;
+ const uint32_t fbHeight = hw.getHeight();
+ glDisable(GL_DITHER);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ glColor4x(0, 0, 0, alpha);
+
+#if defined(DIM_WITH_TEXTURE) && defined(EGL_ANDROID_image_native_buffer)
+ if (sUseTexture) {
+ glBindTexture(GL_TEXTURE_2D, sTexId);
+ glEnable(GL_TEXTURE_2D);
+ glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+ const GLshort texCoords[4][2] = {
+ { 0, 0 },
+ { 0, 1 },
+ { 1, 1 },
+ { 1, 0 }
+ };
+ glMatrixMode(GL_TEXTURE);
+ glLoadIdentity();
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(2, GL_SHORT, 0, texCoords);
+ } else
+#endif
+ {
+ glDisable(GL_TEXTURE_2D);
}
- 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);
- }
+ GLshort w = sWidth;
+ GLshort h = sHeight;
+ const GLshort vertices[4][2] = {
+ { 0, 0 },
+ { 0, h },
+ { w, h },
+ { w, 0 }
+ };
+ glVertexPointer(2, GL_SHORT, 0, vertices);
+
+ 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);
}
}
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
// ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/LayerDim.h b/libs/surfaceflinger/LayerDim.h
index 3e37a47..d4672a1 100644
--- a/libs/surfaceflinger/LayerDim.h
+++ b/libs/surfaceflinger/LayerDim.h
@@ -20,15 +20,22 @@
#include <stdint.h>
#include <sys/types.h>
-#include "LayerBase.h"
-#include "LayerBitmap.h"
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
-namespace android {
+#include "LayerBase.h"
// ---------------------------------------------------------------------------
+namespace android {
+
class LayerDim : public LayerBaseClient
{
+ static bool sUseTexture;
+ static GLuint sTexId;
+ static EGLImageKHR sImage;
+ static int32_t sWidth;
+ static int32_t sHeight;
public:
static const uint32_t typeInfo;
static const char* const typeID;
@@ -36,7 +43,7 @@
virtual uint32_t getTypeInfo() const { return typeInfo; }
LayerDim(SurfaceFlinger* flinger, DisplayID display,
- Client* client, int32_t i);
+ const sp<Client>& client, int32_t i);
virtual ~LayerDim();
virtual void onDraw(const Region& clip) const;
@@ -44,10 +51,6 @@
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/LayerOrientationAnim.cpp b/libs/surfaceflinger/LayerOrientationAnim.cpp
deleted file mode 100644
index 79e5328..0000000
--- a/libs/surfaceflinger/LayerOrientationAnim.cpp
+++ /dev/null
@@ -1,206 +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 <utils/StopWatch.h>
-
-#include <core/SkBitmap.h>
-
-#include <ui/EGLDisplaySurface.h>
-
-#include "BlurFilter.h"
-#include "LayerBase.h"
-#include "LayerOrientationAnim.h"
-#include "SurfaceFlinger.h"
-#include "DisplayHardware/DisplayHardware.h"
-#include "OrientationAnimation.h"
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-const uint32_t LayerOrientationAnim::typeInfo = LayerBase::typeInfo | 0x80;
-const char* const LayerOrientationAnim::typeID = "LayerOrientationAnim";
-
-// ---------------------------------------------------------------------------
-
-// Animation...
-const float DURATION = ms2ns(200);
-const float BOUNCES_PER_SECOND = 0.5f;
-const float DIM_TARGET = 0.40f;
-#define INTERPOLATED_TIME(_t) (_t)
-
-// ---------------------------------------------------------------------------
-
-LayerOrientationAnim::LayerOrientationAnim(
- SurfaceFlinger* flinger, DisplayID display,
- OrientationAnimation* anim,
- const LayerBitmap& bitmapIn,
- const LayerBitmap& bitmapOut)
- : LayerOrientationAnimBase(flinger, display), mAnim(anim),
- mBitmapIn(bitmapIn), mBitmapOut(bitmapOut),
- mTextureName(-1), mTextureNameIn(-1)
-{
- // blur that texture.
- mOrientationCompleted = false;
- mNeedsBlending = false;
-}
-
-LayerOrientationAnim::~LayerOrientationAnim()
-{
- if (mTextureName != -1U) {
- LayerBase::deletedTextures.add(mTextureName);
- }
- if (mTextureNameIn != -1U) {
- LayerBase::deletedTextures.add(mTextureNameIn);
- }
-}
-
-bool LayerOrientationAnim::needsBlending() const
-{
- return mNeedsBlending;
-}
-
-Point LayerOrientationAnim::getPhysicalSize() const
-{
- const GraphicPlane& plane(graphicPlane(0));
- const DisplayHardware& hw(plane.displayHardware());
- return Point(hw.getWidth(), hw.getHeight());
-}
-
-void LayerOrientationAnim::validateVisibility(const Transform&)
-{
- const Layer::State& s(drawingState());
- const Transform tr(s.transform);
- const Point size(getPhysicalSize());
- uint32_t w = size.x;
- uint32_t h = size.y;
- mTransformedBounds = tr.makeBounds(w, h);
- mLeft = tr.tx();
- mTop = tr.ty();
- transparentRegionScreen.clear();
- mTransformed = true;
- mCanUseCopyBit = false;
- copybit_device_t* copybit = mFlinger->getBlitEngine();
- if (copybit) {
- mCanUseCopyBit = true;
- }
-}
-
-void LayerOrientationAnim::onOrientationCompleted()
-{
- mAnim->onAnimationFinished();
-}
-
-void LayerOrientationAnim::onDraw(const Region& clip) const
-{
- float alphaIn = DIM_TARGET;
-
- // clear screen
- // TODO: with update on demand, we may be able
- // to not erase the screen at all during the animation
- if (!mOrientationCompleted) {
- glDisable(GL_BLEND);
- glDisable(GL_DITHER);
- glDisable(GL_SCISSOR_TEST);
- glClearColor(0,0,0,0);
- glClear(GL_COLOR_BUFFER_BIT);
- }
-
- copybit_image_t dst;
- const GraphicPlane& plane(graphicPlane(0));
- const DisplayHardware& hw(plane.displayHardware());
- hw.getDisplaySurface(&dst);
-
- copybit_image_t src;
- mBitmapIn.getBitmapSurface(&src);
-
- copybit_image_t srcOut;
- mBitmapOut.getBitmapSurface(&srcOut);
-
- const int w = dst.w;
- const int h = dst.h;
- const int xc = uint32_t(dst.w-w)/2;
- const int yc = uint32_t(dst.h-h)/2;
- const copybit_rect_t drect = { xc, yc, xc+w, yc+h };
- 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);
- copybit->set_parameter(copybit, COPYBIT_BLUR, COPYBIT_DISABLE);
- }
- LOGE_IF(err != NO_ERROR, "copybit failed (%s)", strerror(err));
- }
- if (!can_use_copybit || err) {
- GGLSurface t;
- t.version = sizeof(GGLSurface);
- t.width = src.w;
- t.height = src.h;
- t.stride = src.w;
- t.vstride= src.h;
- t.format = src.format;
- t.data = (GGLubyte*)(intptr_t(src.base) + src.offset);
-
- Transform tr;
- tr.set(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);
- }
- }
-}
-
-// ---------------------------------------------------------------------------
-
-}; // namespace android
diff --git a/libs/surfaceflinger/LayerOrientationAnim.h b/libs/surfaceflinger/LayerOrientationAnim.h
deleted file mode 100644
index 12b6f1c..0000000
--- a/libs/surfaceflinger/LayerOrientationAnim.h
+++ /dev/null
@@ -1,80 +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_LAYER_ORIENTATION_ANIM_H
-#define ANDROID_LAYER_ORIENTATION_ANIM_H
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <utils/threads.h>
-#include <utils/Parcel.h>
-
-#include "LayerBase.h"
-#include "LayerBitmap.h"
-
-namespace android {
-
-// ---------------------------------------------------------------------------
-class OrientationAnimation;
-
-
-class LayerOrientationAnimBase : public LayerBase
-{
-public:
- LayerOrientationAnimBase(SurfaceFlinger* flinger, DisplayID display)
- : LayerBase(flinger, display) {
- }
- virtual void onOrientationCompleted() = 0;
-};
-
-// ---------------------------------------------------------------------------
-
-class LayerOrientationAnim : public LayerOrientationAnimBase
-{
-public:
- static const uint32_t typeInfo;
- static const char* const typeID;
- virtual char const* getTypeID() const { return typeID; }
- virtual uint32_t getTypeInfo() const { return typeInfo; }
-
- LayerOrientationAnim(SurfaceFlinger* flinger, DisplayID display,
- OrientationAnimation* anim,
- const LayerBitmap& bitmapIn,
- const LayerBitmap& bitmapOut);
- virtual ~LayerOrientationAnim();
-
- void onOrientationCompleted();
-
- virtual void onDraw(const Region& clip) const;
- virtual Point getPhysicalSize() const;
- virtual void validateVisibility(const Transform& globalTransform);
- virtual bool needsBlending() const;
- virtual bool isSecure() const { return false; }
-private:
- OrientationAnimation* mAnim;
- LayerBitmap mBitmapIn;
- LayerBitmap mBitmapOut;
- bool mOrientationCompleted;
- mutable GLuint mTextureName;
- mutable GLuint mTextureNameIn;
- mutable bool mNeedsBlending;
-};
-
-// ---------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_LAYER_ORIENTATION_ANIM_H
diff --git a/libs/surfaceflinger/MessageQueue.cpp b/libs/surfaceflinger/MessageQueue.cpp
new file mode 100644
index 0000000..b43d801
--- /dev/null
+++ b/libs/surfaceflinger/MessageQueue.cpp
@@ -0,0 +1,192 @@
+/*
+ * 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()
+ : mInvalidate(false)
+{
+ 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();
+ const nsecs_t reltime = nextEventTime - systemTime();
+ if (reltime > 0) {
+ mCondition.waitRelative(mLock, reltime);
+ }
+ }
+ } 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/OrientationAnimation.cpp b/libs/surfaceflinger/OrientationAnimation.cpp
deleted file mode 100644
index 12c0eef..0000000
--- a/libs/surfaceflinger/OrientationAnimation.cpp
+++ /dev/null
@@ -1,155 +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 <stdint.h>
-#include <sys/types.h>
-#include <limits.h>
-
-#include "LayerOrientationAnim.h"
-#include "OrientationAnimation.h"
-#include "SurfaceFlinger.h"
-#include "VRamHeap.h"
-
-#include "DisplayHardware/DisplayHardware.h"
-
-namespace android {
-
-// ---------------------------------------------------------------------------
-
-OrientationAnimation::OrientationAnimation(const sp<SurfaceFlinger>& flinger)
- : mFlinger(flinger), mLayerOrientationAnim(NULL), mState(DONE)
-{
- // allocate a memory-dealer for this the first time
- mTemporaryDealer = mFlinger->getSurfaceHeapManager()->createHeap(
- ISurfaceComposer::eHardware);
-}
-
-OrientationAnimation::~OrientationAnimation()
-{
-}
-
-void OrientationAnimation::onOrientationChanged(uint32_t type)
-{
- if (mState == DONE) {
- mType = type;
- if (!(type & ISurfaceComposer::eOrientationAnimationDisable)) {
- mState = PREPARE;
- }
- }
-}
-
-void OrientationAnimation::onAnimationFinished()
-{
- if (mState != DONE)
- mState = FINISH;
-}
-
-bool OrientationAnimation::run_impl()
-{
- bool skip_frame;
- switch (mState) {
- default:
- case DONE:
- skip_frame = done();
- break;
- case PREPARE:
- skip_frame = prepare();
- break;
- case PHASE1:
- skip_frame = phase1();
- break;
- case PHASE2:
- skip_frame = phase2();
- break;
- case FINISH:
- skip_frame = finished();
- break;
- }
- return skip_frame;
-}
-
-bool OrientationAnimation::done()
-{
- return done_impl();
-}
-
-bool OrientationAnimation::prepare()
-{
- mState = PHASE1;
-
- const GraphicPlane& plane(mFlinger->graphicPlane(0));
- const DisplayHardware& hw(plane.displayHardware());
- const uint32_t w = hw.getWidth();
- const uint32_t h = hw.getHeight();
-
- LayerBitmap bitmap;
- bitmap.init(mTemporaryDealer);
- bitmap.setBits(w, h, 1, hw.getFormat());
-
- LayerBitmap bitmapIn;
- bitmapIn.init(mTemporaryDealer);
- bitmapIn.setBits(w, h, 1, hw.getFormat());
-
- copybit_image_t front;
- bitmap.getBitmapSurface(&front);
- hw.copyFrontToImage(front);
-
- LayerOrientationAnimBase* l;
-
- l = new LayerOrientationAnim(
- mFlinger.get(), 0, this, bitmap, bitmapIn);
-
- l->initStates(w, h, 0);
- l->setLayer(INT_MAX-1);
- mFlinger->addLayer(l);
- mLayerOrientationAnim = l;
- return true;
-}
-
-bool OrientationAnimation::phase1()
-{
- if (mFlinger->isFrozen() == false) {
- // start phase 2
- mState = PHASE2;
- mLayerOrientationAnim->onOrientationCompleted();
- mLayerOrientationAnim->invalidate();
- return true;
-
- }
- //mLayerOrientationAnim->invalidate();
- return false;
-}
-
-bool OrientationAnimation::phase2()
-{
- // do the 2nd phase of the animation
- mLayerOrientationAnim->invalidate();
- return false;
-}
-
-bool OrientationAnimation::finished()
-{
- mState = DONE;
- mFlinger->removeLayer(mLayerOrientationAnim);
- mLayerOrientationAnim = NULL;
- return true;
-}
-
-// ---------------------------------------------------------------------------
-
-}; // namespace android
diff --git a/libs/surfaceflinger/OrientationAnimation.h b/libs/surfaceflinger/OrientationAnimation.h
deleted file mode 100644
index cafa38d..0000000
--- a/libs/surfaceflinger/OrientationAnimation.h
+++ /dev/null
@@ -1,85 +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_ORIENTATION_ANIMATION_H
-#define ANDROID_ORIENTATION_ANIMATION_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include "SurfaceFlinger.h"
-
-namespace android {
-
-// ---------------------------------------------------------------------------
-
-class SurfaceFlinger;
-class MemoryDealer;
-class LayerOrientationAnim;
-
-class OrientationAnimation
-{
-public:
- OrientationAnimation(const sp<SurfaceFlinger>& flinger);
- virtual ~OrientationAnimation();
-
- void onOrientationChanged(uint32_t type);
- void onAnimationFinished();
- inline bool run() {
- if (LIKELY(mState == DONE))
- return done_impl();
- return run_impl();
- }
-
-private:
- enum {
- DONE = 0,
- PREPARE,
- PHASE1,
- PHASE2,
- FINISH
- };
-
- bool run_impl();
- inline bool done_impl() {
- if (mFlinger->isFrozen()) {
- // we are not allowed to draw, but pause a bit to make sure
- // apps don't end up using the whole CPU, if they depend on
- // surfaceflinger for synchronization.
- usleep(8333); // 8.3ms ~ 120fps
- return true;
- }
- return false;
- }
-
- bool done();
- bool prepare();
- bool phase1();
- bool phase2();
- bool finished();
-
- sp<SurfaceFlinger> mFlinger;
- sp<MemoryDealer> mTemporaryDealer;
- LayerOrientationAnimBase* mLayerOrientationAnim;
- int mState;
- uint32_t mType;
-};
-
-// ---------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_ORIENTATION_ANIMATION_H
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp
index 97dfecc..9694cf1 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>
@@ -23,6 +21,7 @@
#include <fcntl.h>
#include <errno.h>
#include <math.h>
+#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
@@ -30,36 +29,29 @@
#include <cutils/log.h>
#include <cutils/properties.h>
-#include <utils/IPCThreadState.h>
-#include <utils/IServiceManager.h>
-#include <utils/MemoryDealer.h>
-#include <utils/MemoryBase.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/MemoryHeapBase.h>
+
#include <utils/String8.h>
#include <utils/String16.h>
#include <utils/StopWatch.h>
+#include <ui/GraphicBufferAllocator.h>
#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 "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
@@ -93,30 +85,30 @@
}
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);
@@ -139,14 +131,14 @@
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();
@@ -161,8 +153,8 @@
}
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);
@@ -180,19 +172,24 @@
: BnSurfaceComposer(), Thread(false),
mTransactionFlags(0),
mTransactionCount(0),
+ mResizeTransationPending(false),
+ mLayersRemoved(false),
mBootTime(systemTime()),
- mLastScheduledBroadcast(NULL),
+ mHardwareTest("android.permission.HARDWARE_TEST"),
+ mAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER"),
+ mDump("android.permission.DUMP"),
mVisibleRegionsDirty(false),
mDeferReleaseConsole(false),
mFreezeDisplay(false),
mFreezeCount(0),
mFreezeDisplayTime(0),
mDebugRegion(0),
- mDebugCpu(0),
- mDebugFps(0),
mDebugBackground(0),
- mSyncObject(),
- mDeplayedTransactionPending(0),
+ mDebugInSwapBuffers(0),
+ mLastSwapBufferTime(0),
+ mDebugInTransaction(0),
+ mLastTransactionTime(0),
+ mBootFinished(false),
mConsoleSignals(0),
mSecureFrameBuffer(0)
{
@@ -207,28 +204,16 @@
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
@@ -236,29 +221,9 @@
return graphicPlane(0).displayHardware().getOverlayEngine();
}
-sp<IMemory> SurfaceFlinger::getCblk() const
+sp<IMemoryHeap> 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();
+ return mServerHeap;
}
sp<ISurfaceFlingerClient> SurfaceFlinger::createConnection()
@@ -266,33 +231,34 @@
Mutex::Autolock _l(mStateLock);
uint32_t token = mTokens.acquire();
- Client* client = new Client(token, this);
- if ((client == 0) || (client->ctrlblk == 0)) {
+ sp<Client> client = new Client(token, this);
+ if (client->ctrlblk == 0) {
mTokens.release(token);
return 0;
}
status_t err = mClientsMap.add(token, client);
if (err < 0) {
- delete client;
mTokens.release(token);
return 0;
}
sp<BClient> bclient =
- new BClient(this, token, client->controlBlockMemory());
+ new BClient(this, token, client->getControlBlockMemory());
return bclient;
}
void SurfaceFlinger::destroyConnection(ClientID cid)
{
Mutex::Autolock _l(mStateLock);
- Client* const client = mClientsMap.valueFor(cid);
- if (client) {
+ sp<Client> client = mClientsMap.valueFor(cid);
+ if (client != 0) {
// free all the layers this client owns
- const Vector<LayerBaseClient*>& layers = client->getLayers();
+ 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) {
+ purgatorizeLayer_l(layer);
+ }
}
// the resources associated with this client will be freed
@@ -328,6 +294,7 @@
const nsecs_t now = systemTime();
const nsecs_t duration = now - mBootTime;
LOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );
+ mBootFinished = true;
property_set("ctl.stop", "bootanim");
}
@@ -339,41 +306,15 @@
mReadyToRunBarrier.wait();
}
-
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. "
"Initializing graphics H/W...");
- // create the shared control-block
- mServerHeap = new MemoryDealer(4096, MemoryDealer::READ_ONLY);
- LOGE_IF(mServerHeap==0, "can't create shared memory dealer");
-
- mServerCblkMemory = mServerHeap->allocate(4096);
- LOGE_IF(mServerCblkMemory==0, "can't create shared control block");
-
- mServerCblk = static_cast<surface_flinger_cblk_t *>(mServerCblkMemory->pointer());
- 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;
@@ -384,6 +325,16 @@
plane.setDisplayHardware(hw);
}
+ // create the shared control-block
+ mServerHeap = new MemoryHeapBase(4096,
+ MemoryHeapBase::READ_ONLY, "SurfaceFlinger read-only heap");
+ LOGE_IF(mServerHeap==0, "can't create shared memory dealer");
+
+ mServerCblk = static_cast<surface_flinger_cblk_t*>(mServerHeap->getBase());
+ LOGE_IF(mServerCblk==0, "can't get to shared control block's address");
+
+ new(mServerCblk) surface_flinger_cblk_t;
+
// initialize primary screen
// (other display should be initialized in the same manner, but
// asynchronously, as they could come and go. None of this is supported
@@ -450,13 +401,6 @@
* 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");
@@ -471,45 +415,53 @@
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);
}
// ----------------------------------------------------------------------------
@@ -540,24 +492,20 @@
handlePageFlip();
const DisplayHardware& hw(graphicPlane(0).displayHardware());
- if (LIKELY(hw.canDraw())) {
+ if (LIKELY(hw.canDraw() && !isFrozen())) {
// repaint the framebuffer (if needed)
handleRepaint();
+ // inform the h/w that we're done compositing
+ hw.compositionComplete();
+
// release the clients before we flip ('cause flip might block)
unlockClients();
- executeScheduledBroadcasts();
-
- // sample the cpu gauge
- if (UNLIKELY(mDebugCpu)) {
- handleDebugCpu();
- }
postFramebuffer();
} else {
// pretend we did the post
unlockClients();
- executeScheduledBroadcasts();
usleep(16667); // 60 fps period
}
return true;
@@ -565,28 +513,14 @@
void SurfaceFlinger::postFramebuffer()
{
- const bool skip = mOrientationAnimation->run();
- if (UNLIKELY(skip)) {
- return;
- }
-
if (!mInvalidRegion.isEmpty()) {
const DisplayHardware& hw(graphicPlane(0).displayHardware());
-
- if (UNLIKELY(mDebugFps)) {
- debugShowFPS();
- }
-
+ const nsecs_t now = systemTime();
+ mDebugInSwapBuffers = now;
hw.flip(mInvalidRegion);
-
+ mLastSwapBufferTime = systemTime() - now;
+ mDebugInSwapBuffers = 0;
mInvalidRegion.clear();
-
- if (Layer::deletedTextures.size()) {
- glDeleteTextures(
- Layer::deletedTextures.size(),
- Layer::deletedTextures.array());
- Layer::deletedTextures.clear();
- }
}
}
@@ -601,15 +535,13 @@
}
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;
@@ -621,9 +553,31 @@
void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
{
- Mutex::Autolock _l(mStateLock);
+ Vector< sp<LayerBase> > ditchedLayers;
- const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
+ { // scope for the lock
+ Mutex::Autolock _l(mStateLock);
+ const nsecs_t now = systemTime();
+ mDebugInTransaction = now;
+ handleTransactionLocked(transactionFlags, ditchedLayers);
+ mLastTransactionTime = systemTime() - now;
+ mDebugInTransaction = 0;
+ }
+
+ // do this without lock held
+ const size_t count = ditchedLayers.size();
+ for (size_t i=0 ; i<count ; i++) {
+ if (ditchedLayers[i] != 0) {
+ //LOGD("ditching layer %p", ditchedLayers[i].get());
+ ditchedLayers[i]->ditch();
+ }
+ }
+}
+
+void SurfaceFlinger::handleTransactionLocked(
+ uint32_t transactionFlags, Vector< sp<LayerBase> >& ditchedLayers)
+{
+ const LayerVector& currentLayers(mCurrentState.layersSortedByZ);
const size_t count = currentLayers.size();
/*
@@ -634,19 +588,13 @@
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;
const uint32_t flags = layer->doTransaction(0);
if (flags & Layer::eVisibleRegion)
mVisibleRegionsDirty = true;
-
- if (flags & Layer::eRestartTransaction) {
- // restart the transaction, but back-off a little
- layer->setTransactionFlags(eTransactionNeeded);
- setTransactionFlags(eTraversalNeeded, ms2ns(8));
- }
}
}
@@ -681,7 +629,6 @@
mVisibleRegionsDirty = true;
mDirtyRegion.set(hw.bounds());
mFreezeDisplayTime = 0;
- mOrientationAnimation->onOrientationChanged(type);
}
if (mCurrentState.freezeDisplay != mDrawingState.freezeDisplay) {
@@ -689,24 +636,28 @@
mFreezeDisplay = mCurrentState.freezeDisplay;
}
- // some layers might have been removed, so
- // we need to update the regions they're exposing.
- const SortedVector<LayerBase*>& removedLayers(mRemovedLayers);
- size_t c = removedLayers.size();
- if (c) {
- mVisibleRegionsDirty = true;
- while (c--) {
- mDirtyRegionRemovedLayer.orSelf(
- removedLayers[c]->visibleRegionScreen);
- }
- }
-
- const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
if (currentLayers.size() > mDrawingState.layersSortedByZ.size()) {
// layers have been added
mVisibleRegionsDirty = true;
}
+ // some layers might have been removed, so
+ // we need to update the regions they're exposing.
+ if (mLayersRemoved) {
+ mLayersRemoved = false;
+ mVisibleRegionsDirty = true;
+ const LayerVector& previousLayers(mDrawingState.layersSortedByZ);
+ const size_t count = previousLayers.size();
+ for (size_t i=0 ; i<count ; i++) {
+ const sp<LayerBase>& layer(previousLayers[i]);
+ if (currentLayers.indexOf( layer ) < 0) {
+ // this layer is not visible anymore
+ ditchedLayers.add(layer);
+ mDirtyRegionRemovedLayer.orSelf(layer->visibleRegionScreen);
+ }
+ }
+ }
+
// get rid of all resources we don't need anymore
// (layers and clients)
free_resources_l();
@@ -734,7 +685,7 @@
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
@@ -785,7 +736,7 @@
// 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(visibleRegion);
@@ -811,7 +762,8 @@
void SurfaceFlinger::commitTransaction()
{
mDrawingState = mCurrentState;
- mTransactionCV.signal();
+ mResizeTransationPending = false;
+ mTransactionCV.broadcast();
}
void SurfaceFlinger::handlePageFlip()
@@ -837,9 +789,9 @@
{
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;
@@ -850,37 +802,58 @@
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);
}
}
+
void SurfaceFlinger::handleRepaint()
{
- // set the frame buffer
- const DisplayHardware& hw(graphicPlane(0).displayHardware());
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
+ // compute the invalid region
+ mInvalidRegion.orSelf(mDirtyRegion);
+ if (mInvalidRegion.isEmpty()) {
+ // nothing to do
+ return;
+ }
if (UNLIKELY(mDebugRegion)) {
debugFlashRegions();
}
- // compute the invalid region
- mInvalidRegion.orSelf(mDirtyRegion);
+ // set the frame buffer
+ const DisplayHardware& hw(graphicPlane(0).displayHardware());
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
uint32_t flags = hw.getFlags();
- if (flags & DisplayHardware::BUFFER_PRESERVED) {
- // here we assume DisplayHardware::flip()'s implementation
- // performs the copy-back optimization.
- } else {
- if (flags & DisplayHardware::UPDATE_ON_DEMAND) {
- // we need to fully redraw the part that will be updated
+ if ((flags & DisplayHardware::SWAP_RECTANGLE) ||
+ (flags & DisplayHardware::BUFFER_PRESERVED))
+ {
+ // we can redraw only what's dirty, but since SWAP_RECTANGLE only
+ // takes a rectangle, we must make sure to update that whole
+ // rectangle in that case
+ if (flags & DisplayHardware::SWAP_RECTANGLE) {
+ // FIXME: we really should be able to pass a region to
+ // SWAP_RECTANGLE so that we don't have to redraw all this.
mDirtyRegion.set(mInvalidRegion.bounds());
} else {
- // we need to redraw everything
+ // in the BUFFER_PRESERVED case, obviously, we can update only
+ // what's needed and nothing more.
+ // NOTE: this is NOT a common case, as preserving the backbuffer
+ // is costly and usually involves copying the whole update back.
+ }
+ } else {
+ if (flags & DisplayHardware::PARTIAL_UPDATES) {
+ // We need to redraw the rectangle that will be updated
+ // (pushed to the framebuffer).
+ // This is needed because PARTIAL_UPDATES only takes one
+ // rectangle instead of a region (see DisplayHardware::flip())
+ mDirtyRegion.set(mInvalidRegion.bounds());
+ } else {
+ // we need to redraw everything (the whole screen)
mDirtyRegion.set(hw.bounds());
mInvalidRegion = mDirtyRegion;
}
@@ -903,9 +876,9 @@
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));
@@ -920,67 +893,42 @@
{
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();
}
}
-void SurfaceFlinger::scheduleBroadcast(Client* client)
-{
- if (mLastScheduledBroadcast != client) {
- mLastScheduledBroadcast = client;
- mScheduledBroadcasts.add(client);
- }
-}
-
-void SurfaceFlinger::executeScheduledBroadcasts()
-{
- SortedVector<Client*>& list = mScheduledBroadcasts;
- size_t count = list.size();
- while (count--) {
- per_client_cblk_t* const cblk = list[count]->ctrlblk;
- if (cblk->lock.tryLock() == NO_ERROR) {
- cblk->cv.broadcast();
- list.removeAt(count);
- cblk->lock.unlock();
- } else {
- // schedule another round
- LOGW("executeScheduledBroadcasts() skipped, "
- "contention on the client. We'll try again later...");
- signalDelayedEvent(ms2ns(4));
- }
- }
- 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::PARTIAL_UPDATES) ?
+ 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 },
@@ -990,10 +938,12 @@
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();
+
+ if (mInvalidRegion.isEmpty()) {
+ mDirtyRegion.dump("mDirtyRegion");
+ mInvalidRegion.dump("mInvalidRegion");
+ }
+ hw.flip(mInvalidRegion);
if (mDebugRegion > 1)
usleep(mDebugRegion * 1000);
@@ -1017,9 +967,10 @@
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);
@@ -1037,9 +988,10 @@
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);
@@ -1065,7 +1017,7 @@
// 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);
@@ -1073,91 +1025,77 @@
return NO_ERROR;
}
-status_t SurfaceFlinger::removeLayer(LayerBase* layer)
+status_t SurfaceFlinger::removeLayer(const sp<LayerBase>& layer)
{
Mutex::Autolock _l(mStateLock);
- removeLayer_l(layer);
- setTransactionFlags(eTransactionNeeded);
- return NO_ERROR;
+ status_t err = purgatorizeLayer_l(layer);
+ if (err == NO_ERROR)
+ setTransactionFlags(eTransactionNeeded);
+ return err;
}
-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)
{
+ if (layer == 0)
+ return BAD_VALUE;
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;
}
+ return status_t(index);
+}
+
+status_t SurfaceFlinger::purgatorizeLayer_l(const sp<LayerBase>& layerBase)
+{
+ // remove the layer from the main list (through a transaction).
+ ssize_t err = removeLayer_l(layerBase);
+
+ layerBase->onRemoved();
+
// 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.
- return (index == NAME_NOT_FOUND) ? status_t(NO_ERROR) : index;
+ // from the user because there is a race between BClient::destroySurface(),
+ // ~BClient() and ~ISurface().
+ 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();
-
// free resources associated with disconnected clients
- SortedVector<Client*>& scheduledBroadcasts(mScheduledBroadcasts);
- Vector<Client*>& disconnectedClients(mDisconnectedClients);
+ Vector< sp<Client> >& disconnectedClients(mDisconnectedClients);
const size_t count = disconnectedClients.size();
for (size_t i=0 ; i<count ; i++) {
- Client* client = disconnectedClients[i];
- // if this client is the scheduled broadcast list,
- // remove it from there (and we don't need to signal it
- // since it is dead).
- int32_t index = scheduledBroadcasts.indexOf(client);
- if (index >= 0) {
- scheduledBroadcasts.removeItemsAt(index);
- }
+ sp<Client> client = disconnectedClients[i];
mTokens.release(client->cid);
- delete client;
}
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;
@@ -1185,6 +1123,20 @@
{
if (android_atomic_dec(&mTransactionCount) == 1) {
signalEvent();
+
+ // if there is a transaction with a resize, wait for it to
+ // take effect before returning.
+ Mutex::Autolock _l(mStateLock);
+ while (mResizeTransationPending) {
+ status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
+ if (CC_UNLIKELY(err != NO_ERROR)) {
+ // just in case something goes wrong in SF, return to the
+ // called after a few seconds.
+ LOGW_IF(err == TIMED_OUT, "closeGlobalTransaction timed out!");
+ mResizeTransationPending = false;
+ break;
+ }
+ }
}
}
@@ -1198,7 +1150,7 @@
setTransactionFlags(eTransactionNeeded);
// flags is intended to communicate some sort of animation behavior
- // (for instance fadding)
+ // (for instance fading)
return NO_ERROR;
}
@@ -1212,7 +1164,7 @@
setTransactionFlags(eTransactionNeeded);
// flags is intended to communicate some sort of animation behavior
- // (for instance fadding)
+ // (for instance fading)
return NO_ERROR;
}
@@ -1241,7 +1193,7 @@
DisplayID d, uint32_t w, uint32_t h, PixelFormat format,
uint32_t flags)
{
- LayerBaseClient* layer = 0;
+ sp<LayerBaseClient> layer;
sp<LayerBaseClient::Surface> surfaceHandle;
if (int32_t(w|h) < 0) {
@@ -1251,14 +1203,14 @@
}
Mutex::Autolock _l(mStateLock);
- Client* const c = mClientsMap.valueFor(clientId);
- if (UNLIKELY(!c)) {
+ sp<Client> client = mClientsMap.valueFor(clientId);
+ if (UNLIKELY(client == 0)) {
LOGE("createSurface() failed, client not found (id=%d)", clientId);
return surfaceHandle;
}
//LOGD("createSurface for pid %d (%d x %d)", pid, w, h);
- int32_t id = c->generateId(pid);
+ int32_t id = client->generateId(pid);
if (uint32_t(id) >= NUM_LAYERS_MAX) {
LOGE("createSurface() failed, generateId = %d", id);
return surfaceHandle;
@@ -1267,32 +1219,40 @@
switch (flags & eFXSurfaceMask) {
case eFXSurfaceNormal:
if (UNLIKELY(flags & ePushBuffers)) {
- layer = createPushBuffersSurfaceLocked(c, d, id, w, h, flags);
+ layer = createPushBuffersSurfaceLocked(client, d, id,
+ w, h, flags);
} else {
- layer = createNormalSurfaceLocked(c, d, id, w, h, format, flags);
+ layer = createNormalSurfaceLocked(client, d, id,
+ w, h, flags, format);
}
break;
case eFXSurfaceBlur:
- layer = createBlurSurfaceLocked(c, d, id, w, h, flags);
+ layer = createBlurSurfaceLocked(client, d, id, w, h, flags);
break;
case eFXSurfaceDim:
- layer = createDimSurfaceLocked(c, d, id, w, h, flags);
+ layer = createDimSurfaceLocked(client, d, id, w, h, flags);
break;
}
- if (layer) {
+ if (layer != 0) {
setTransactionFlags(eTransactionNeeded);
surfaceHandle = layer->getSurface();
- if (surfaceHandle != 0)
- surfaceHandle->getSurfaceData(params);
+ if (surfaceHandle != 0) {
+ params->token = surfaceHandle->getToken();
+ params->identity = surfaceHandle->getIdentity();
+ params->width = w;
+ params->height = h;
+ params->format = format;
+ }
}
return surfaceHandle;
}
-LayerBaseClient* SurfaceFlinger::createNormalSurfaceLocked(
- Client* client, DisplayID display,
- int32_t id, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags)
+sp<LayerBaseClient> SurfaceFlinger::createNormalSurfaceLocked(
+ const sp<Client>& client, DisplayID display,
+ int32_t id, uint32_t w, uint32_t h, uint32_t flags,
+ PixelFormat& format)
{
// initialize the surfaces
switch (format) { // TODO: take h/w into account
@@ -1305,57 +1265,102 @@
break;
}
- Layer* layer = new Layer(this, display, client, id);
- status_t err = layer->setBuffers(client, w, h, format, flags);
+ sp<Layer> layer = new Layer(this, display, client, id);
+ status_t err = layer->setBuffers(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(
- Client* client, DisplayID display,
+sp<LayerBaseClient> SurfaceFlinger::createBlurSurfaceLocked(
+ const sp<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(
- Client* client, DisplayID display,
+sp<LayerBaseClient> SurfaceFlinger::createDimSurfaceLocked(
+ const sp<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(
- Client* client, DisplayID display,
+sp<LayerBaseClient> SurfaceFlinger::createPushBuffersSurfaceLocked(
+ const sp<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).
+ */
+
+ status_t err = NAME_NOT_FOUND;
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);
+ if (layer != 0) {
+ 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
+
+ class MessageDestroySurface : public MessageBase {
+ SurfaceFlinger* flinger;
+ sp<LayerBaseClient> layer;
+ public:
+ MessageDestroySurface(
+ SurfaceFlinger* flinger, const sp<LayerBaseClient>& layer)
+ : flinger(flinger), layer(layer) { }
+ virtual bool handler() {
+ sp<LayerBaseClient> l(layer);
+ layer.clear(); // clear it outside of the lock;
+ Mutex::Autolock _l(flinger->mStateLock);
+ /*
+ * remove the layer from the current list -- chances are that it's
+ * not in the list anyway, because it should have been removed
+ * already upon request of the client (eg: window manager).
+ * However, a buggy client could have not done that.
+ * Since we know we don't have any more clients, we don't need
+ * to use the purgatory.
+ */
+ status_t err = flinger->removeLayer_l(l);
+ LOGE_IF(err<0 && err != NAME_NOT_FOUND,
+ "error removing layer=%p (%s)", l.get(), strerror(-err));
+ return true;
+ }
+ };
+
+ mEventQueue.postMessage( new MessageDestroySurface(this, layer) );
return NO_ERROR;
}
@@ -1369,18 +1374,9 @@
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) {
+ 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) {
- if (removeLayer_l(layer) == NO_ERROR) {
- flags |= eTransactionNeeded;
- // we skip everything else... well, no, not really
- // we skip ONLY that transaction.
- continue;
- }
- }
if (what & ePositionChanged) {
if (layer->setPosition(s.x, s.y))
flags |= eTraversalNeeded;
@@ -1395,8 +1391,10 @@
}
}
if (what & eSizeChanged) {
- if (layer->setSize(s.w, s.h))
+ if (layer->setSize(s.w, s.h)) {
flags |= eTraversalNeeded;
+ mResizeTransationPending = true;
+ }
}
if (what & eAlphaChanged) {
if (layer->setAlpha(uint8_t(255.0f*s.alpha+0.5f)))
@@ -1422,9 +1420,10 @@
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)
@@ -1446,20 +1445,40 @@
const size_t SIZE = 1024;
char buffer[SIZE];
String8 result;
- if (checkCallingPermission(
- String16("android.permission.DUMP")) == false)
- { // not allowed
+ if (!mDump.checkCalling()) {
snprintf(buffer, SIZE, "Permission Denial: "
"can't dump SurfaceFlinger from pid=%d, uid=%d\n",
IPCThreadState::self()->getCallingPid(),
IPCThreadState::self()->getCallingUid());
result.append(buffer);
} else {
- Mutex::Autolock _l(mStateLock);
+
+ // figure out if we're stuck somewhere
+ const nsecs_t now = systemTime();
+ const nsecs_t inSwapBuffers(mDebugInSwapBuffers);
+ const nsecs_t inTransaction(mDebugInTransaction);
+ nsecs_t inSwapBuffersDuration = (inSwapBuffers) ? now-inSwapBuffers : 0;
+ nsecs_t inTransactionDuration = (inTransaction) ? now-inTransaction : 0;
+
+ // Try to get the main lock, but don't insist if we can't
+ // (this would indicate SF is stuck, but we want to be able to
+ // print something in dumpsys).
+ int retry = 3;
+ while (mStateLock.tryLock()<0 && --retry>=0) {
+ usleep(1000000);
+ }
+ const bool locked(retry >= 0);
+ if (!locked) {
+ snprintf(buffer, SIZE,
+ "SurfaceFlinger appears to be unresponsive, "
+ "dumping anyways (no locks held)\n");
+ result.append(buffer);
+ }
+
size_t s = mClientsMap.size();
char name[64];
for (size_t i=0 ; i<s ; i++) {
- Client* client = mClientsMap.valueAt(i);
+ sp<Client> client = mClientsMap.valueAt(i);
sprintf(name, " Client (id=0x%08x)", client->cid);
client->dump(name);
}
@@ -1467,51 +1486,66 @@
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"
" "
"z=%9d, pos=(%4d,%4d), size=(%4d,%4d), "
- "needsBlending=%1d, invalidate=%1d, "
+ "needsBlending=%1d, needsDithering=%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,
+ layer->needsBlending(), layer->needsDithering(),
+ layer->contentDirty,
s.alpha, s.flags,
s.transform[0], s.transform[1],
s.transform[2], s.transform[3]);
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) {
+ sp<Client> client(lbc->client.promote());
snprintf(buffer, SIZE,
" "
"id=0x%08x, client=0x%08x, identity=%u\n",
- lbc->clientIndex(), lbc->client ? lbc->client->cid : 0,
+ lbc->clientIndex(), client.get() ? client->cid : 0,
lbc->getIdentity());
+
+ result.append(buffer);
+ buffer[0] = 0;
}
- result.append(buffer);
- buffer[0] = 0;
/*** Layer ***/
- Layer* const l = LayerBase::dynamicCast<Layer*>((LayerBase*)layer);
- if (l) {
- const LayerBitmap& buf0(l->getBuffer(0));
- const LayerBitmap& buf1(l->getBuffer(1));
+ sp<Layer> l = LayerBase::dynamicCast< Layer* >(layer.get());
+ if (l != 0) {
+ SharedBufferStack::Statistics stats = l->lcblk->getStats();
+ result.append( l->lcblk->dump(" ") );
+ sp<const GraphicBuffer> buf0(l->getBuffer(0));
+ sp<const GraphicBuffer> buf1(l->getBuffer(1));
+ uint32_t w0=0, h0=0, s0=0;
+ uint32_t w1=0, h1=0, s1=0;
+ if (buf0 != 0) {
+ w0 = buf0->getWidth();
+ h0 = buf0->getHeight();
+ s0 = buf0->getStride();
+ }
+ if (buf1 != 0) {
+ w1 = buf1->getWidth();
+ h1 = buf1->getHeight();
+ s1 = buf1->getStride();
+ }
snprintf(buffer, SIZE,
" "
- "format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u], mTextureName=%d,"
- " freezeLock=%p, swapState=0x%08x\n",
+ "format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u],"
+ " freezeLock=%p, dq-q-time=%u us\n",
l->pixelFormat(),
- buf0.width(), buf0.height(), buf0.stride(),
- buf1.width(), buf1.height(), buf1.stride(),
- l->getTextureName(), l->getFreezeLock().get(),
- l->lcblk->swapState);
+ w0, h0, s0, w1, h1, s1,
+ l->getFreezeLock().get(), stats.totalTime);
+ result.append(buffer);
+ buffer[0] = 0;
}
- result.append(buffer);
- buffer[0] = 0;
s.transparentRegion.dump(result, "transparentRegion");
layer->transparentRegionScreen.dump(result, "transparentRegionScreen");
layer->visibleRegionScreen.dump(result, "visibleRegionScreen");
@@ -1523,19 +1557,28 @@
mFreezeDisplay?"yes":"no", mFreezeCount,
mCurrentState.orientation, hw.canDraw());
result.append(buffer);
-
- sp<AllocatorInterface> allocator;
- if (mGPU != 0) {
- snprintf(buffer, SIZE, " GPU owner: %d\n", mGPU->getOwner());
+ snprintf(buffer, SIZE,
+ " last eglSwapBuffers() time: %f us\n"
+ " last transaction time : %f us\n",
+ mLastSwapBufferTime/1000.0, mLastTransactionTime/1000.0);
+ result.append(buffer);
+ if (inSwapBuffersDuration || !locked) {
+ snprintf(buffer, SIZE, " eglSwapBuffers time: %f us\n",
+ inSwapBuffersDuration/1000.0);
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");
+ if (inTransactionDuration || !locked) {
+ snprintf(buffer, SIZE, " transaction time: %f us\n",
+ inTransactionDuration/1000.0);
+ result.append(buffer);
+ }
+ snprintf(buffer, SIZE, " client count: %d\n", mClientsMap.size());
+ result.append(buffer);
+ const GraphicBufferAllocator& alloc(GraphicBufferAllocator::get());
+ alloc.dump(result);
+
+ if (locked) {
+ mStateLock.unlock();
}
}
write(fd, result.string(), result.size());
@@ -1553,57 +1596,34 @@
case FREEZE_DISPLAY:
case UNFREEZE_DISPLAY:
case BOOT_FINISHED:
- case REVOKE_GPU:
{
// codes that require permission check
IPCThreadState* ipc = IPCThreadState::self();
const int pid = ipc->getCallingPid();
const int uid = ipc->getCallingUid();
- const int self_pid = getpid();
- if (UNLIKELY(pid != self_pid && uid != AID_GRAPHICS)) {
- // we're called from a different process, do the real check
- if (!checkCallingPermission(
- String16("android.permission.ACCESS_SURFACE_FLINGER")))
- {
- LOGE("Permission Denial: "
- "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
- return PERMISSION_DENIED;
- }
+ if ((uid != AID_GRAPHICS) && !mAccessSurfaceFlinger.check(pid, uid)) {
+ LOGE("Permission Denial: "
+ "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
+ return PERMISSION_DENIED;
}
}
}
-
status_t err = BnSurfaceComposer::onTransact(code, data, reply, flags);
if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {
- // HARDWARE_TEST stuff...
- if (UNLIKELY(checkCallingPermission(
- String16("android.permission.HARDWARE_TEST")) == false))
- { // not allowed
- LOGE("Permission Denial: pid=%d, uid=%d\n",
- IPCThreadState::self()->getCallingPid(),
- IPCThreadState::self()->getCallingUid());
+ CHECK_INTERFACE(ISurfaceComposer, data, reply);
+ if (UNLIKELY(!mHardwareTest.checkCalling())) {
+ IPCThreadState* ipc = IPCThreadState::self();
+ const int pid = ipc->getCallingPid();
+ const int uid = ipc->getCallingUid();
+ LOGE("Permission Denial: "
+ "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
return PERMISSION_DENIED;
}
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();
@@ -1618,23 +1638,17 @@
const DisplayHardware& hw(graphicPlane(0).displayHardware());
mDirtyRegion.set(hw.bounds()); // careful that's not thread-safe
signalEvent();
+ return NO_ERROR;
}
- return NO_ERROR;
- case 1005: // ask GPU revoke
- if (mGPU != 0) {
- mGPU->friendlyRevoke();
- }
+ case 1005:{ // force transaction
+ setTransactionFlags(eTransactionNeeded|eTraversalNeeded);
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);
@@ -1658,30 +1672,24 @@
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);
- mCblkMemory = mCblkHeap->allocate(cblksize);
- if (mCblkMemory != 0) {
- ctrlblk = static_cast<per_client_cblk_t *>(mCblkMemory->pointer());
- if (ctrlblk) { // construct the shared structure in-place.
- new(ctrlblk) per_client_cblk_t;
- }
+ const int cblksize = ((sizeof(SharedClient)+(pgsize-1))&~(pgsize-1));
+
+ mCblkHeap = new MemoryHeapBase(cblksize, 0,
+ "SurfaceFlinger Client control-block");
+
+ ctrlblk = static_cast<SharedClient *>(mCblkHeap->getBase());
+ if (ctrlblk) { // construct the shared structure in-place.
+ new(ctrlblk) SharedClient;
}
}
Client::~Client() {
if (ctrlblk) {
- const int pgsize = getpagesize();
- ctrlblk->~per_client_cblk_t(); // destroy our shared-structure.
+ ctrlblk->~SharedClient(); // destroy our shared-structure.
}
}
-const sp<SurfaceHeapManager>& Client::getSurfaceHeapManager() const {
- return mFlinger->getSurfaceHeapManager();
-}
-
int32_t Client::generateId(int pid)
{
const uint32_t i = clz( ~mBitmap );
@@ -1693,13 +1701,15 @@
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));
@@ -1709,27 +1719,18 @@
}
}
-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)
@@ -1741,7 +1742,7 @@
#pragma mark -
#endif
-BClient::BClient(SurfaceFlinger *flinger, ClientID cid, const sp<IMemory>& cblk)
+BClient::BClient(SurfaceFlinger *flinger, ClientID cid, const sp<IMemoryHeap>& cblk)
: mId(cid), mFlinger(flinger), mCblk(cblk)
{
}
@@ -1751,8 +1752,8 @@
mFlinger->destroyConnection(mId);
}
-void BClient::getControlBlocks(sp<IMemory>* ctrl) const {
- *ctrl = mCblk;
+sp<IMemoryHeap> BClient::getControlBlock() const {
+ return mCblk;
}
sp<ISurface> BClient::createSurface(
@@ -1766,7 +1767,7 @@
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)
@@ -1866,6 +1867,10 @@
return mGlobalTransform;
}
+EGLDisplay GraphicPlane::getEGLDisplay() const {
+ return mHw->getEGLDisplay();
+}
+
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/libs/surfaceflinger/SurfaceFlinger.h
index 0d63e1d..f9bfe6c 100644
--- a/libs/surfaceflinger/SurfaceFlinger.h
+++ b/libs/surfaceflinger/SurfaceFlinger.h
@@ -25,21 +25,24 @@
#include <utils/threads.h>
#include <utils/Atomic.h>
#include <utils/Errors.h>
-#include <utils/MemoryDealer.h>
+#include <utils/RefBase.h>
+
+#include <binder/IMemory.h>
+#include <binder/Permission.h>
#include <ui/PixelFormat.h>
#include <ui/ISurfaceComposer.h>
#include <ui/ISurfaceFlingerClient.h>
-#include <private/ui/SharedState.h>
+#include <private/ui/SharedBufferStack.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 +54,8 @@
class BClient;
class DisplayHardware;
class FreezeLock;
-class GPUHardwareInterface;
-class IGPUCallback;
class Layer;
class LayerBuffer;
-class LayerOrientationAnim;
-class OrientationAnimation;
-class SurfaceHeapManager;
typedef int32_t ClientID;
@@ -66,7 +64,7 @@
// ---------------------------------------------------------------------------
-class Client
+class Client : public RefBase
{
public:
Client(ClientID cid, const sp<SurfaceFlinger>& flinger);
@@ -74,35 +72,34 @@
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; }
- const sp<IMemory>& controlBlockMemory() const { return mCblkMemory; }
+ sp<LayerBaseClient> getLayerUser(int32_t i) const;
void dump(const char* what);
- const sp<SurfaceHeapManager>& getSurfaceHeapManager() const;
+
+ const Vector< wp<LayerBaseClient> >& getLayers() const {
+ return mLayers;
+ }
+
+ const sp<IMemoryHeap>& getControlBlockMemory() const {
+ return mCblkHeap;
+ }
// pointer to this client's control block
- per_client_cblk_t* ctrlblk;
+ SharedClient* ctrlblk;
ClientID cid;
private:
- int getClientPid() const { return mPid; }
+ 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<IMemoryHeap> mCblkHeap;
+ sp<SurfaceFlinger> mFlinger;
};
// ---------------------------------------------------------------------------
@@ -125,6 +122,8 @@
const DisplayHardware& displayHardware() const;
const Transform& transform() const;
+ EGLDisplay getEGLDisplay() const;
+
private:
GraphicPlane(const GraphicPlane&);
GraphicPlane operator = (const GraphicPlane&);
@@ -160,7 +159,7 @@
// ISurfaceComposer interface
virtual sp<ISurfaceFlingerClient> createConnection();
- virtual sp<IMemory> getCblk() const;
+ virtual sp<IMemoryHeap> getCblk() const;
virtual void bootFinished();
virtual void openGlobalTransaction();
virtual void closeGlobalTransaction();
@@ -168,56 +167,52 @@
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;
friend class LayerBase;
friend class LayerBuffer;
friend class LayerBaseClient;
+ friend class LayerBaseClient::Surface;
friend class Layer;
friend class LayerBlur;
+ friend class LayerDim;
sp<ISurface> createSurface(ClientID client, int pid,
ISurfaceFlingerClient::surface_data_t* params,
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(
+ const sp<Client>& client, DisplayID display,
+ int32_t id, uint32_t w, uint32_t h, uint32_t flags,
+ PixelFormat& format);
- LayerBaseClient* createBlurSurfaceLocked(Client* client, DisplayID display,
+ sp<LayerBaseClient> createBlurSurfaceLocked(
+ const sp<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(
+ const sp<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(
+ const sp<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 +220,15 @@
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,38 +242,26 @@
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();
+public: // hack to work around gcc 4.0.3 bug
const GraphicPlane& graphicPlane(int dpy) const;
GraphicPlane& graphicPlane(int dpy);
+private:
void waitForEvent();
+public: // hack to work around gcc 4.0.3 bug
void signalEvent();
+private:
void signalDelayedEvent(nsecs_t delay);
void handleConsoleEvents();
void handleTransaction(uint32_t transactionFlags);
+ void handleTransactionLocked(
+ uint32_t transactionFlags,
+ Vector< sp<LayerBase> >& ditchedLayers);
void computeVisibleRegions(
LayerVector& currentLayers,
@@ -289,19 +272,16 @@
bool lockPageFlip(const LayerVector& currentLayers);
void unlockPageFlip(const LayerVector& currentLayers);
void handleRepaint();
- void handleDebugCpu();
- void scheduleBroadcast(Client* client);
- void executeScheduledBroadcasts();
void postFramebuffer();
void composeSurfaces(const Region& dirty);
void unlockClients();
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);
@@ -315,7 +295,7 @@
inline void decFreezeCount() { if (mFreezeCount > 0) mFreezeCount--; }
inline bool hasFreezeRequest() const { return mFreezeDisplay; }
inline bool isFrozen() const {
- return mFreezeDisplay || mFreezeCount>0;
+ return (mFreezeDisplay || mFreezeCount>0) && mBootFinished;
}
@@ -323,6 +303,11 @@
void debugShowFPS() const;
void drawWormhole() const;
+
+ mutable MessageQueue mEventQueue;
+
+
+
// access must be protected by mStateLock
mutable Mutex mStateLock;
State mCurrentState;
@@ -330,23 +315,24 @@
volatile int32_t mTransactionFlags;
volatile int32_t mTransactionCount;
Condition mTransactionCV;
-
+ bool mResizeTransationPending;
+
// protected by mStateLock (but we could use another lock)
Tokenizer mTokens;
- DefaultKeyedVector<ClientID, Client*> mClientsMap;
- DefaultKeyedVector<SurfaceID, LayerBaseClient*> mLayerMap;
+ DefaultKeyedVector<ClientID, sp<Client> > mClientsMap;
+ DefaultKeyedVector<SurfaceID, sp<LayerBaseClient> > mLayerMap;
GraphicPlane mGraphicPlanes[1];
- SortedVector<LayerBase*> mRemovedLayers;
- Vector<Client*> mDisconnectedClients;
+ bool mLayersRemoved;
+ Vector< sp<Client> > mDisconnectedClients;
// constant members (no synchronization needed for access)
- sp<MemoryDealer> mServerHeap;
- sp<IMemory> mServerCblkMemory;
+ sp<IMemoryHeap> mServerHeap;
surface_flinger_cblk_t* mServerCblk;
- sp<SurfaceHeapManager> mSurfaceHeapManager;
- sp<GPUHardwareInterface> mGPU;
GLuint mWormholeTexName;
nsecs_t mBootTime;
+ Permission mHardwareTest;
+ Permission mAccessSurfaceFlinger;
+ Permission mDump;
// Can only accessed from the main thread, these members
// don't need synchronization
@@ -354,30 +340,23 @@
Region mDirtyRegionRemovedLayer;
Region mInvalidRegion;
Region mWormholeRegion;
- Client* mLastScheduledBroadcast;
- SortedVector<Client*> mScheduledBroadcasts;
bool mVisibleRegionsDirty;
bool mDeferReleaseConsole;
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;
+ volatile nsecs_t mDebugInSwapBuffers;
+ nsecs_t mLastSwapBufferTime;
+ volatile nsecs_t mDebugInTransaction;
+ nsecs_t mLastTransactionTime;
+ bool mBootFinished;
// these are thread safe
mutable Barrier mReadyToRunBarrier;
- mutable SurfaceFlingerSynchro mSyncObject;
- volatile int32_t mDeplayedTransactionPending;
// atomic variables
enum {
@@ -410,11 +389,11 @@
{
public:
BClient(SurfaceFlinger *flinger, ClientID cid,
- const sp<IMemory>& cblk);
+ const sp<IMemoryHeap>& cblk);
~BClient();
// ISurfaceFlingerClient interface
- virtual void getControlBlocks(sp<IMemory>* ctrl) const;
+ virtual sp<IMemoryHeap> getControlBlock() const;
virtual sp<ISurface> createSurface(
surface_data_t* params, int pid,
@@ -427,7 +406,7 @@
private:
ClientID mId;
SurfaceFlinger* mFlinger;
- sp<IMemory> mCblk;
+ sp<IMemoryHeap> mCblk;
};
// ---------------------------------------------------------------------------
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 @@
{
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 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/Transform.h b/libs/surfaceflinger/Transform.h
index 4c4528e..78f5c19 100644
--- a/libs/surfaceflinger/Transform.h
+++ b/libs/surfaceflinger/Transform.h
@@ -50,6 +50,14 @@
ROT_INVALID = 0x80000000
};
+ enum type_mask {
+ IDENTITY = 0,
+ TRANSLATE = 0x1,
+ SCALE = 0x2,
+ AFFINE = 0x4,
+ PERSPECTIVE = 0x8
+ };
+
bool transformed() const;
int32_t getOrientation() const;
bool preserveRects() const;
diff --git a/libs/surfaceflinger/VRamHeap.cpp b/libs/surfaceflinger/VRamHeap.cpp
deleted file mode 100644
index 5f633bd..0000000
--- a/libs/surfaceflinger/VRamHeap.cpp
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * 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.
- */
-
-#define LOG_TAG "SurfaceFlinger"
-
-#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 <EGL/eglnatives.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) && (mFlinger->getGPU() != 0)) {
- // 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/VRamHeap.h b/libs/surfaceflinger/VRamHeap.h
deleted file mode 100644
index 9140167..0000000
--- a/libs/surfaceflinger/VRamHeap.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * 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/overlays/overlays.cpp b/libs/surfaceflinger/tests/overlays/overlays.cpp
index f3c046f..0b9322e 100644
--- a/libs/surfaceflinger/tests/overlays/overlays.cpp
+++ b/libs/surfaceflinger/tests/overlays/overlays.cpp
@@ -1,6 +1,6 @@
-#include <utils/IPCThreadState.h>
-#include <utils/ProcessState.h>
-#include <utils/IServiceManager.h>
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
#include <utils/Log.h>
#include <ui/Surface.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;
+}