auto import from //depot/cupcake/@135843
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
new file mode 100644
index 0000000..f14d7e9
--- /dev/null
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -0,0 +1,353 @@
+/*
+ * 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 <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#include <cutils/properties.h>
+
+#include <utils/Log.h>
+
+#include <ui/EGLDisplaySurface.h>
+
+#include <GLES/gl.h>
+#include <EGL/eglext.h>
+
+
+#include "DisplayHardware/DisplayHardware.h"
+
+#include <hardware/copybit.h>
+#include <hardware/overlay.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)
+ LOGE("GL error 0x%04x", int(error));
+}
+
+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));
+}
+
+
+/*
+ * Initialize the display to the specified values.
+ *
+ */
+
+DisplayHardware::DisplayHardware(
+ const sp<SurfaceFlinger>& flinger,
+ uint32_t dpy)
+ : DisplayHardwareBase(flinger, dpy)
+{
+ init(dpy);
+}
+
+DisplayHardware::~DisplayHardware()
+{
+ fini();
+}
+
+float DisplayHardware::getDpiX() const { return mDpiX; }
+float DisplayHardware::getDpiY() const { return mDpiY; }
+float DisplayHardware::getDensity() const { return mDensity; }
+float DisplayHardware::getRefreshRate() const { return mRefreshRate; }
+int DisplayHardware::getWidth() const { return mWidth; }
+int DisplayHardware::getHeight() const { return mHeight; }
+PixelFormat DisplayHardware::getFormat() const { return mFormat; }
+
+void DisplayHardware::init(uint32_t dpy)
+{
+ // initialize EGL
+ const EGLint attribs[] = {
+ EGL_RED_SIZE, 5,
+ EGL_GREEN_SIZE, 6,
+ EGL_BLUE_SIZE, 5,
+ EGL_DEPTH_SIZE, 0,
+ EGL_NONE
+ };
+ EGLint w, h, dummy;
+ EGLint numConfigs, n;
+ EGLConfig config;
+ EGLSurface surface;
+ EGLContext context;
+ mFlags = 0;
+
+ // TODO: all the extensions below should be queried through
+ // eglGetProcAddress().
+
+ EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ eglInitialize(display, NULL, NULL);
+ eglGetConfigs(display, NULL, 0, &numConfigs);
+ eglChooseConfig(display, attribs, &config, 1, &n);
+
+ /*
+ * Gather EGL extensions
+ */
+
+ const char* const egl_extensions = eglQueryString(
+ display, EGL_EXTENSIONS);
+
+ LOGI("EGL informations:");
+ LOGI("# of configs : %d", numConfigs);
+ LOGI("vendor : %s", eglQueryString(display, EGL_VENDOR));
+ LOGI("version : %s", eglQueryString(display, EGL_VERSION));
+ LOGI("extensions: %s", egl_extensions);
+ LOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported");
+
+ // TODO: get this from the devfb driver (probably should be HAL module)
+ mFlags |= SWAP_RECTANGLE_EXTENSION;
+
+ // TODO: get the real "update_on_demand" behavior (probably should be HAL module)
+ mFlags |= UPDATE_ON_DEMAND;
+
+ if (eglGetConfigAttrib(display, config, EGL_CONFIG_CAVEAT, &dummy) == EGL_TRUE) {
+ if (dummy == EGL_SLOW_CONFIG)
+ mFlags |= SLOW_CONFIG;
+ }
+
+ /*
+ * Create our main surface
+ */
+
+ mDisplaySurface = new EGLDisplaySurface();
+
+ surface = eglCreateWindowSurface(display, config, mDisplaySurface.get(), NULL);
+ //checkEGLErrors("eglCreateDisplaySurfaceANDROID");
+
+ if (eglQuerySurface(display, surface, EGL_SWAP_BEHAVIOR, &dummy) == EGL_TRUE) {
+ if (dummy == EGL_BUFFER_PRESERVED) {
+ mFlags |= BUFFER_PRESERVED;
+ }
+ }
+
+ GLint value = EGL_UNKNOWN;
+ eglQuerySurface(display, surface, EGL_HORIZONTAL_RESOLUTION, &value);
+ if (value == EGL_UNKNOWN) {
+ mDpiX = 160.0f;
+ } else {
+ mDpiX = 25.4f * float(value)/EGL_DISPLAY_SCALING;
+ }
+ value = EGL_UNKNOWN;
+ eglQuerySurface(display, surface, EGL_VERTICAL_RESOLUTION, &value);
+ if (value == EGL_UNKNOWN) {
+ mDpiY = 160.0f;
+ } else {
+ mDpiY = 25.4f * float(value)/EGL_DISPLAY_SCALING;
+ }
+ mRefreshRate = 60.f; // TODO: get the real refresh rate
+
+
+ char property[PROPERTY_VALUE_MAX];
+ if (property_get("ro.sf.lcd_density", property, NULL) <= 0) {
+ LOGW("ro.sf.lcd_density not defined, using 160 dpi by default.");
+ strcpy(property, "160");
+ }
+ mDensity = atoi(property) * (1.0f/160.0f);
+
+
+ /*
+ * Create our OpenGL ES context
+ */
+
+ context = eglCreateContext(display, config, NULL, NULL);
+ //checkEGLErrors("eglCreateContext");
+
+ eglQuerySurface(display, surface, EGL_WIDTH, &mWidth);
+ eglQuerySurface(display, surface, EGL_HEIGHT, &mHeight);
+
+
+ /*
+ * Gather OpenGL ES extensions
+ */
+
+ eglMakeCurrent(display, surface, surface, context);
+ const char* const gl_extensions = (const char*)glGetString(GL_EXTENSIONS);
+ LOGI("OpenGL informations:");
+ LOGI("vendor : %s", glGetString(GL_VENDOR));
+ LOGI("renderer : %s", glGetString(GL_RENDERER));
+ LOGI("version : %s", glGetString(GL_VERSION));
+ LOGI("extensions: %s", gl_extensions);
+
+ 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")) {
+ mFlags |= DIRECT_TEXTURE;
+ }
+
+ // Unbind the context from this thread
+ eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+
+ mDisplay = display;
+ 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);
+ }
+}
+
+/*
+ * Clean up. Throw out our local state.
+ *
+ * (It's entirely possible we'll never get here, since this is meant
+ * for real hardware, which doesn't restart.)
+ */
+
+void DisplayHardware::fini()
+{
+ eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglTerminate(mDisplay);
+ copybit_close(mBlitEngine);
+ overlay_control_close(mOverlayEngine);
+}
+
+void DisplayHardware::releaseScreen() const
+{
+ DisplayHardwareBase::releaseScreen();
+}
+
+void DisplayHardware::acquireScreen() const
+{
+ DisplayHardwareBase::acquireScreen();
+}
+
+void DisplayHardware::getDisplaySurface(copybit_image_t* img) const
+{
+ img->w = mDisplaySurface->stride;
+ img->h = mDisplaySurface->height;
+ img->format = mDisplaySurface->format;
+ img->offset = mDisplaySurface->offset;
+ img->base = (void*)mDisplaySurface->base;
+ img->fd = mDisplaySurface->fd;
+}
+
+void DisplayHardware::getDisplaySurface(GGLSurface* fb) const
+{
+ fb->version= sizeof(GGLSurface);
+ fb->width = mDisplaySurface->width;
+ fb->height = mDisplaySurface->height;
+ fb->stride = mDisplaySurface->stride;
+ fb->format = mDisplaySurface->format;
+ fb->data = (GGLubyte*)mDisplaySurface->base + mDisplaySurface->offset;
+}
+
+uint32_t DisplayHardware::getPageFlipCount() const {
+ return mDisplaySurface->getPageFlipCount();
+}
+
+/*
+ * "Flip" the front and back buffers.
+ */
+
+void DisplayHardware::flip(const Region& dirty) const
+{
+ checkGLErrors();
+
+ 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(
+ b.left, b.top, b.width(), b.height());
+ }
+
+ eglSwapBuffers(dpy, surface);
+ checkEGLErrors("eglSwapBuffers");
+
+ // for debugging
+ //glClearColor(1,0,0,0);
+ //glClear(GL_COLOR_BUFFER_BIT);
+}
+
+uint32_t DisplayHardware::getFlags() const
+{
+ return mFlags;
+}
+
+void DisplayHardware::makeCurrent() const
+{
+ eglMakeCurrent(mDisplay, mSurface, mSurface, mContext);
+}
+
+void DisplayHardware::copyFrontToImage(const copybit_image_t& front) const {
+ mDisplaySurface->copyFrontToImage(front);
+}
+
+void DisplayHardware::copyBackToImage(const copybit_image_t& front) const {
+ mDisplaySurface->copyBackToImage(front);
+}
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h
new file mode 100644
index 0000000..550a4d1
--- /dev/null
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h
@@ -0,0 +1,113 @@
+/*
+ * 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_DISPLAY_HARDWARE_H
+#define ANDROID_DISPLAY_HARDWARE_H
+
+#include <stdlib.h>
+
+#include <ui/PixelFormat.h>
+#include <ui/Region.h>
+
+#include <EGL/egl.h>
+
+#include "DisplayHardware/DisplayHardwareBase.h"
+
+struct overlay_control_device_t;
+struct copybit_device_t;
+struct copybit_image_t;
+struct copybit_t;
+
+namespace android {
+
+class EGLDisplaySurface;
+
+class DisplayHardware : public DisplayHardwareBase
+{
+public:
+ enum {
+ DIRECT_TEXTURE = 0x00000002,
+ SWAP_RECTANGLE_EXTENSION= 0x00000004,
+ COPY_BITS_EXTENSION = 0x00000008,
+ NPOT_EXTENSION = 0x00000100,
+ DRAW_TEXTURE_EXTENSION = 0x00000200,
+ BUFFER_PRESERVED = 0x00010000,
+ UPDATE_ON_DEMAND = 0x00020000, // video driver feature
+ SLOW_CONFIG = 0x00040000, // software
+ };
+
+ DisplayHardware(
+ const sp<SurfaceFlinger>& flinger,
+ uint32_t displayIndex);
+
+ ~DisplayHardware();
+
+ void releaseScreen() const;
+ void acquireScreen() const;
+
+ // Flip the front and back buffers if the back buffer is "dirty". Might
+ // be instantaneous, might involve copying the frame buffer around.
+ void flip(const Region& dirty) const;
+
+ float getDpiX() const;
+ float getDpiY() const;
+ float getRefreshRate() const;
+ float getDensity() const;
+ int getWidth() const;
+ int getHeight() const;
+ PixelFormat getFormat() const;
+ uint32_t getFlags() const;
+ 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;
+
+ Rect bounds() const {
+ return Rect(mWidth, mHeight);
+ }
+
+private:
+ void init(uint32_t displayIndex) __attribute__((noinline));
+ void fini() __attribute__((noinline));
+
+ EGLDisplay mDisplay;
+ EGLSurface mSurface;
+ EGLContext mContext;
+ EGLConfig mConfig;
+ float mDpiX;
+ float mDpiY;
+ float mRefreshRate;
+ float mDensity;
+ int mWidth;
+ int mHeight;
+ PixelFormat mFormat;
+ uint32_t mFlags;
+ mutable Region mDirty;
+ sp<EGLDisplaySurface> mDisplaySurface;
+ copybit_device_t* mBlitEngine;
+ overlay_control_device_t* mOverlayEngine;
+};
+
+}; // namespace android
+
+#endif // ANDROID_DISPLAY_HARDWARE_H
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp
new file mode 100644
index 0000000..f75e5c2
--- /dev/null
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp
@@ -0,0 +1,403 @@
+/*
+ * 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 <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/resource.h>
+
+#include <linux/unistd.h>
+
+#include <utils/Log.h>
+
+#include "DisplayHardware/DisplayHardwareBase.h"
+#include "SurfaceFlinger.h"
+
+// ----------------------------------------------------------------------------
+// the sim build doesn't have gettid
+
+#ifndef HAVE_GETTID
+# define gettid getpid
+#endif
+
+// ----------------------------------------------------------------------------
+namespace android {
+
+static char const * kSleepFileName = "/sys/power/wait_for_fb_sleep";
+static char const * kWakeFileName = "/sys/power/wait_for_fb_wake";
+static char const * const kOldSleepFileName = "/sys/android_power/wait_for_fb_sleep";
+static char const * const kOldWakeFileName = "/sys/android_power/wait_for_fb_wake";
+
+// This dir exists if the framebuffer console is present, either built into
+// the kernel or loaded as a module.
+static char const * const kFbconSysDir = "/sys/class/graphics/fbcon";
+
+// ----------------------------------------------------------------------------
+
+DisplayHardwareBase::DisplayEventThreadBase::DisplayEventThreadBase(
+ const sp<SurfaceFlinger>& flinger)
+ : Thread(false), mFlinger(flinger) {
+}
+
+DisplayHardwareBase::DisplayEventThreadBase::~DisplayEventThreadBase() {
+}
+
+// ----------------------------------------------------------------------------
+
+DisplayHardwareBase::DisplayEventThread::DisplayEventThread(
+ const sp<SurfaceFlinger>& flinger)
+ : DisplayEventThreadBase(flinger)
+{
+}
+
+DisplayHardwareBase::DisplayEventThread::~DisplayEventThread()
+{
+}
+
+bool DisplayHardwareBase::DisplayEventThread::threadLoop()
+{
+ int err = 0;
+ char buf;
+ int fd;
+
+ fd = open(kSleepFileName, O_RDONLY, 0);
+ do {
+ err = read(fd, &buf, 1);
+ } while (err < 0 && errno == EINTR);
+ close(fd);
+ LOGW_IF(err<0, "ANDROID_WAIT_FOR_FB_SLEEP failed (%s)", strerror(errno));
+ if (err >= 0) {
+ sp<SurfaceFlinger> flinger = mFlinger.promote();
+ LOGD("About to give-up screen, flinger = %p", flinger.get());
+ if (flinger != 0) {
+ mBarrier.close();
+ flinger->screenReleased(0);
+ mBarrier.wait();
+ }
+ }
+ fd = open(kWakeFileName, O_RDONLY, 0);
+ do {
+ err = read(fd, &buf, 1);
+ } while (err < 0 && errno == EINTR);
+ close(fd);
+ LOGW_IF(err<0, "ANDROID_WAIT_FOR_FB_WAKE failed (%s)", strerror(errno));
+ if (err >= 0) {
+ sp<SurfaceFlinger> flinger = mFlinger.promote();
+ LOGD("Screen about to return, flinger = %p", flinger.get());
+ if (flinger != 0)
+ flinger->screenAcquired(0);
+ }
+ return true;
+}
+
+status_t DisplayHardwareBase::DisplayEventThread::releaseScreen() const
+{
+ mBarrier.open();
+ return NO_ERROR;
+}
+
+status_t DisplayHardwareBase::DisplayEventThread::readyToRun()
+{
+ if (access(kSleepFileName, R_OK) || access(kWakeFileName, R_OK)) {
+ if (access(kOldSleepFileName, R_OK) || access(kOldWakeFileName, R_OK)) {
+ LOGE("Couldn't open %s or %s", kSleepFileName, kWakeFileName);
+ return NO_INIT;
+ }
+ kSleepFileName = kOldSleepFileName;
+ kWakeFileName = kOldWakeFileName;
+ }
+ return NO_ERROR;
+}
+
+status_t DisplayHardwareBase::DisplayEventThread::initCheck() const
+{
+ return (((access(kSleepFileName, R_OK) == 0 &&
+ access(kWakeFileName, R_OK) == 0) ||
+ (access(kOldSleepFileName, R_OK) == 0 &&
+ access(kOldWakeFileName, R_OK) == 0)) &&
+ access(kFbconSysDir, F_OK) != 0) ? NO_ERROR : NO_INIT;
+}
+
+// ----------------------------------------------------------------------------
+
+pid_t DisplayHardwareBase::ConsoleManagerThread::sSignalCatcherPid = 0;
+
+DisplayHardwareBase::ConsoleManagerThread::ConsoleManagerThread(
+ const sp<SurfaceFlinger>& flinger)
+ : DisplayEventThreadBase(flinger), consoleFd(-1)
+{
+ sSignalCatcherPid = 0;
+
+ // create a new console
+ char const * const ttydev = "/dev/tty0";
+ int fd = open(ttydev, O_RDWR | O_SYNC);
+ if (fd<0) {
+ LOGE("Can't open %s", ttydev);
+ this->consoleFd = -errno;
+ return;
+ }
+
+ // to make sure that we are in text mode
+ int res = ioctl(fd, KDSETMODE, (void*) KD_TEXT);
+ if (res<0) {
+ LOGE("ioctl(%d, KDSETMODE, ...) failed, res %d (%s)",
+ fd, res, strerror(errno));
+ }
+
+ // get the current console
+ struct vt_stat vs;
+ res = ioctl(fd, VT_GETSTATE, &vs);
+ if (res<0) {
+ LOGE("ioctl(%d, VT_GETSTATE, ...) failed, res %d (%s)",
+ fd, res, strerror(errno));
+ this->consoleFd = -errno;
+ return;
+ }
+
+ // switch to console 7 (which is what X normaly uses)
+ int vtnum = 7;
+ do {
+ res = ioctl(fd, VT_ACTIVATE, (void*)vtnum);
+ } while(res < 0 && errno == EINTR);
+ if (res<0) {
+ LOGE("ioctl(%d, VT_ACTIVATE, ...) failed, %d (%s) for %d",
+ fd, errno, strerror(errno), vtnum);
+ this->consoleFd = -errno;
+ return;
+ }
+
+ do {
+ res = ioctl(fd, VT_WAITACTIVE, (void*)vtnum);
+ } while(res < 0 && errno == EINTR);
+ if (res<0) {
+ LOGE("ioctl(%d, VT_WAITACTIVE, ...) failed, %d %d %s for %d",
+ fd, res, errno, strerror(errno), vtnum);
+ this->consoleFd = -errno;
+ return;
+ }
+
+ // open the new console
+ close(fd);
+ fd = open(ttydev, O_RDWR | O_SYNC);
+ if (fd<0) {
+ LOGE("Can't open new console %s", ttydev);
+ this->consoleFd = -errno;
+ return;
+ }
+
+ /* disable console line buffer, echo, ... */
+ struct termios ttyarg;
+ ioctl(fd, TCGETS , &ttyarg);
+ ttyarg.c_iflag = 0;
+ ttyarg.c_lflag = 0;
+ ioctl(fd, TCSETS , &ttyarg);
+
+ // set up signals so we're notified when the console changes
+ // we can't use SIGUSR1 because it's used by the java-vm
+ vm.mode = VT_PROCESS;
+ vm.waitv = 0;
+ vm.relsig = SIGUSR2;
+ vm.acqsig = SIGUNUSED;
+ vm.frsig = 0;
+
+ struct sigaction act;
+ sigemptyset(&act.sa_mask);
+ act.sa_handler = sigHandler;
+ act.sa_flags = 0;
+ sigaction(vm.relsig, &act, NULL);
+
+ sigemptyset(&act.sa_mask);
+ act.sa_handler = sigHandler;
+ act.sa_flags = 0;
+ sigaction(vm.acqsig, &act, NULL);
+
+ sigset_t mask;
+ sigemptyset(&mask);
+ sigaddset(&mask, vm.relsig);
+ sigaddset(&mask, vm.acqsig);
+ sigprocmask(SIG_BLOCK, &mask, NULL);
+
+ // switch to graphic mode
+ res = ioctl(fd, KDSETMODE, (void*)KD_GRAPHICS);
+ LOGW_IF(res<0,
+ "ioctl(%d, KDSETMODE, KD_GRAPHICS) failed, res %d", fd, res);
+
+ this->prev_vt_num = vs.v_active;
+ this->vt_num = vtnum;
+ this->consoleFd = fd;
+}
+
+DisplayHardwareBase::ConsoleManagerThread::~ConsoleManagerThread()
+{
+ if (this->consoleFd >= 0) {
+ int fd = this->consoleFd;
+ int prev_vt_num = this->prev_vt_num;
+ int res;
+ ioctl(fd, KDSETMODE, (void*)KD_TEXT);
+ do {
+ res = ioctl(fd, VT_ACTIVATE, (void*)prev_vt_num);
+ } while(res < 0 && errno == EINTR);
+ do {
+ res = ioctl(fd, VT_WAITACTIVE, (void*)prev_vt_num);
+ } while(res < 0 && errno == EINTR);
+ close(fd);
+ char const * const ttydev = "/dev/tty0";
+ fd = open(ttydev, O_RDWR | O_SYNC);
+ ioctl(fd, VT_DISALLOCATE, 0);
+ close(fd);
+ }
+}
+
+status_t DisplayHardwareBase::ConsoleManagerThread::readyToRun()
+{
+ if (this->consoleFd >= 0) {
+ sSignalCatcherPid = gettid();
+
+ sigset_t mask;
+ sigemptyset(&mask);
+ sigaddset(&mask, vm.relsig);
+ sigaddset(&mask, vm.acqsig);
+ sigprocmask(SIG_BLOCK, &mask, NULL);
+
+ int res = ioctl(this->consoleFd, VT_SETMODE, &vm);
+ if (res<0) {
+ LOGE("ioctl(%d, VT_SETMODE, ...) failed, %d (%s)",
+ this->consoleFd, errno, strerror(errno));
+ }
+ return NO_ERROR;
+ }
+ return this->consoleFd;
+}
+
+void DisplayHardwareBase::ConsoleManagerThread::requestExit()
+{
+ Thread::requestExit();
+ if (sSignalCatcherPid != 0) {
+ // wake the thread up
+ kill(sSignalCatcherPid, SIGINT);
+ // wait for it...
+ }
+}
+
+void DisplayHardwareBase::ConsoleManagerThread::sigHandler(int sig)
+{
+ // resend the signal to our signal catcher thread
+ LOGW("received signal %d in thread %d, resending to %d",
+ sig, gettid(), sSignalCatcherPid);
+
+ // we absolutely need the delays below because without them
+ // our main thread never gets a chance to handle the signal.
+ usleep(10000);
+ kill(sSignalCatcherPid, sig);
+ usleep(10000);
+}
+
+status_t DisplayHardwareBase::ConsoleManagerThread::releaseScreen() const
+{
+ int fd = this->consoleFd;
+ int err = ioctl(fd, VT_RELDISP, (void*)1);
+ LOGE_IF(err<0, "ioctl(%d, VT_RELDISP, 1) failed %d (%s)",
+ fd, errno, strerror(errno));
+ return (err<0) ? (-errno) : status_t(NO_ERROR);
+}
+
+bool DisplayHardwareBase::ConsoleManagerThread::threadLoop()
+{
+ sigset_t mask;
+ sigemptyset(&mask);
+ sigaddset(&mask, vm.relsig);
+ sigaddset(&mask, vm.acqsig);
+
+ int sig = 0;
+ sigwait(&mask, &sig);
+
+ if (sig == vm.relsig) {
+ sp<SurfaceFlinger> flinger = mFlinger.promote();
+ //LOGD("About to give-up screen, flinger = %p", flinger.get());
+ if (flinger != 0)
+ flinger->screenReleased(0);
+ } else if (sig == vm.acqsig) {
+ sp<SurfaceFlinger> flinger = mFlinger.promote();
+ //LOGD("Screen about to return, flinger = %p", flinger.get());
+ if (flinger != 0)
+ flinger->screenAcquired(0);
+ }
+
+ return true;
+}
+
+status_t DisplayHardwareBase::ConsoleManagerThread::initCheck() const
+{
+ return consoleFd >= 0 ? NO_ERROR : NO_INIT;
+}
+
+// ----------------------------------------------------------------------------
+
+DisplayHardwareBase::DisplayHardwareBase(const sp<SurfaceFlinger>& flinger,
+ uint32_t displayIndex)
+ : mCanDraw(true)
+{
+ mDisplayEventThread = new DisplayEventThread(flinger);
+ if (mDisplayEventThread->initCheck() != NO_ERROR) {
+ // fall-back on the console
+ mDisplayEventThread = new ConsoleManagerThread(flinger);
+ }
+}
+
+DisplayHardwareBase::~DisplayHardwareBase()
+{
+ // request exit
+ mDisplayEventThread->requestExitAndWait();
+}
+
+
+bool DisplayHardwareBase::canDraw() const
+{
+ return mCanDraw;
+}
+
+void DisplayHardwareBase::releaseScreen() const
+{
+ status_t err = mDisplayEventThread->releaseScreen();
+ if (err >= 0) {
+ //LOGD("screen given-up");
+ mCanDraw = false;
+ }
+}
+
+void DisplayHardwareBase::acquireScreen() const
+{
+ status_t err = mDisplayEventThread->acquireScreen();
+ if (err >= 0) {
+ //LOGD("screen returned");
+ mCanDraw = true;
+ }
+}
+
+}; // namespace android
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.h b/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.h
new file mode 100644
index 0000000..8369bb8
--- /dev/null
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.h
@@ -0,0 +1,96 @@
+/*
+ * 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_DISPLAY_HARDWARE_BASE_H
+#define ANDROID_DISPLAY_HARDWARE_BASE_H
+
+#include <stdint.h>
+#include <utils/RefBase.h>
+#include <utils/threads.h>
+#include <linux/kd.h>
+#include <linux/vt.h>
+#include "Barrier.h"
+
+namespace android {
+
+class SurfaceFlinger;
+
+class DisplayHardwareBase
+{
+public:
+ DisplayHardwareBase(
+ const sp<SurfaceFlinger>& flinger,
+ uint32_t displayIndex);
+
+ ~DisplayHardwareBase();
+
+ // console managment
+ void releaseScreen() const;
+ void acquireScreen() const;
+ bool canDraw() const;
+
+private:
+ class DisplayEventThreadBase : public Thread {
+ protected:
+ wp<SurfaceFlinger> mFlinger;
+ public:
+ DisplayEventThreadBase(const sp<SurfaceFlinger>& flinger);
+ virtual ~DisplayEventThreadBase();
+ virtual void onFirstRef() {
+ run("DisplayEventThread", PRIORITY_URGENT_DISPLAY);
+ }
+ virtual status_t acquireScreen() const { return NO_ERROR; };
+ virtual status_t releaseScreen() const { return NO_ERROR; };
+ virtual status_t initCheck() const = 0;
+ };
+
+ class DisplayEventThread : public DisplayEventThreadBase
+ {
+ mutable Barrier mBarrier;
+ public:
+ DisplayEventThread(const sp<SurfaceFlinger>& flinger);
+ virtual ~DisplayEventThread();
+ virtual bool threadLoop();
+ virtual status_t readyToRun();
+ virtual status_t releaseScreen() const;
+ virtual status_t initCheck() const;
+ };
+
+ class ConsoleManagerThread : public DisplayEventThreadBase
+ {
+ int consoleFd;
+ int vt_num;
+ int prev_vt_num;
+ vt_mode vm;
+ static void sigHandler(int sig);
+ static pid_t sSignalCatcherPid;
+ public:
+ ConsoleManagerThread(const sp<SurfaceFlinger>& flinger);
+ virtual ~ConsoleManagerThread();
+ virtual bool threadLoop();
+ virtual status_t readyToRun();
+ virtual void requestExit();
+ virtual status_t releaseScreen() const;
+ virtual status_t initCheck() const;
+ };
+
+ sp<DisplayEventThreadBase> mDisplayEventThread;
+ mutable int mCanDraw;
+};
+
+}; // namespace android
+
+#endif // ANDROID_DISPLAY_HARDWARE_BASE_H