Merge "glgen stubs to fix bad methods in gles20 bindings"
diff --git a/include/utils/SystemClock.h b/include/utils/SystemClock.h
index 7c319be..d75264c 100644
--- a/include/utils/SystemClock.h
+++ b/include/utils/SystemClock.h
@@ -25,6 +25,7 @@
int setCurrentTimeMillis(int64_t millis);
int64_t uptimeMillis();
int64_t elapsedRealtime();
+int64_t elapsedRealtimeNano();
}; // namespace android
diff --git a/include/utils/Timers.h b/include/utils/Timers.h
index 8b4d322..92f66c9 100644
--- a/include/utils/Timers.h
+++ b/include/utils/Timers.h
@@ -78,9 +78,10 @@
SYSTEM_TIME_REALTIME = 0, // system-wide realtime clock
SYSTEM_TIME_MONOTONIC = 1, // monotonic time since unspecified starting point
SYSTEM_TIME_PROCESS = 2, // high-resolution per-process clock
- SYSTEM_TIME_THREAD = 3 // high-resolution per-thread clock
+ SYSTEM_TIME_THREAD = 3, // high-resolution per-thread clock
+ SYSTEM_TIME_BOOTTIME = 4 // same as SYSTEM_TIME_MONOTONIC, but including CPU suspend time
};
-
+
// return the system-time according to the specified clock
#ifdef __cplusplus
nsecs_t systemTime(int clock = SYSTEM_TIME_MONOTONIC);
diff --git a/libs/utils/SystemClock.cpp b/libs/utils/SystemClock.cpp
index 8b8ac10..53e0626 100644
--- a/libs/utils/SystemClock.cpp
+++ b/libs/utils/SystemClock.cpp
@@ -106,7 +106,22 @@
*/
int64_t elapsedRealtime()
{
+ return nanoseconds_to_milliseconds(elapsedRealtimeNano());
+}
+
+/*
+ * native public static long elapsedRealtimeNano();
+ */
+int64_t elapsedRealtimeNano()
+{
#ifdef HAVE_ANDROID_OS
+ struct timespec ts;
+ int result = clock_gettime(CLOCK_BOOTTIME, &ts);
+ if (result == 0) {
+ return seconds_to_nanoseconds(ts.tv_sec) + ts.tv_nsec;
+ }
+
+ // CLOCK_BOOTTIME doesn't exist, fallback to /dev/alarm
static int s_fd = -1;
if (s_fd == -1) {
@@ -114,25 +129,20 @@
if (android_atomic_cmpxchg(-1, fd, &s_fd)) {
close(fd);
}
+ result = ioctl(s_fd,
+ ANDROID_ALARM_GET_TIME(ANDROID_ALARM_ELAPSED_REALTIME), &ts);
}
- struct timespec ts;
- int result = ioctl(s_fd,
- ANDROID_ALARM_GET_TIME(ANDROID_ALARM_ELAPSED_REALTIME), &ts);
-
if (result == 0) {
- int64_t when = seconds_to_nanoseconds(ts.tv_sec) + ts.tv_nsec;
- return (int64_t) nanoseconds_to_milliseconds(when);
- } else {
- // XXX: there was an error, probably because the driver didn't
- // exist ... this should return
- // a real error, like an exception!
- int64_t when = systemTime(SYSTEM_TIME_MONOTONIC);
- return (int64_t) nanoseconds_to_milliseconds(when);
+ return seconds_to_nanoseconds(ts.tv_sec) + ts.tv_nsec;
}
+
+ // XXX: there was an error, probably because the driver didn't
+ // exist ... this should return
+ // a real error, like an exception!
+ return systemTime(SYSTEM_TIME_MONOTONIC);
#else
- int64_t when = systemTime(SYSTEM_TIME_MONOTONIC);
- return (int64_t) nanoseconds_to_milliseconds(when);
+ return systemTime(SYSTEM_TIME_MONOTONIC);
#endif
}
diff --git a/libs/utils/Timers.cpp b/libs/utils/Timers.cpp
index 64b4701..d4f8516 100644
--- a/libs/utils/Timers.cpp
+++ b/libs/utils/Timers.cpp
@@ -39,7 +39,8 @@
CLOCK_REALTIME,
CLOCK_MONOTONIC,
CLOCK_PROCESS_CPUTIME_ID,
- CLOCK_THREAD_CPUTIME_ID
+ CLOCK_THREAD_CPUTIME_ID,
+ CLOCK_BOOTTIME
};
struct timespec t;
t.tv_sec = t.tv_nsec = 0;
diff --git a/opengl/specs/EGL_ANDROID_fence_sync.txt b/opengl/specs/EGL_ANDROID_fence_sync.txt
index bb618c9..316ee1c 100644
--- a/opengl/specs/EGL_ANDROID_fence_sync.txt
+++ b/opengl/specs/EGL_ANDROID_fence_sync.txt
@@ -20,7 +20,7 @@
Version
- Version 1, May 29, 2012
+ Version 2, July 23, 2012
Number
@@ -48,7 +48,9 @@
New Procedures and Functions
- None.
+ EGLint eglDupAndroidFenceFDANDROID(
+ EGLDisplay dpy,
+ EGLSyncKHR);
New Tokens
@@ -58,9 +60,14 @@
EGL_SYNC_ANDROID_FENCE_ANDROID 0x3144
- Accepted by the <attribute> parameter of eglGetSyncAttribKHR:
+ Accepted by the <attrib_list> parameter of eglCreateSyncKHR:
- EGL_SYNC_FENCE_FD_ANDROID 0x3145
+ EGL_SYNC_ANDROID_FENCE_FD_ANDROID 0x3145
+
+ Accepted by the <attrib_list> parameter of eglCreateSyncKHR, and returned
+ by eglDupAndroidFenceFDANDROID in the event of an error:
+
+ EGL_NO_ANDROID_FENCE_ANDROID -1
Returned in <value> when eglGetSyncAttribKHR is called with <attribute>
EGL_SYNC_CONDITION_KHR:
@@ -73,43 +80,45 @@
Objects), added by KHR_fence_sync
"If <type> is EGL_SYNC_ANDROID_FENCE_ANDROID, an EGL Android fence sync
- object is created. In this case the EGL_SYNC_FENCE_FD_ANDROID attribute may
- optionally be specified. If this attribute is specified, it must be set to
- a file descriptor that refers to a native Android fence object.
+ object is created. In this case the EGL_SYNC_ANDROID_FENCE_FD_ANDROID
+ attribute may optionally be specified. If this attribute is specified, it
+ must be set to either a file descriptor that refers to a native Android
+ fence object or to the value EGL_NO_ANDROID_FENCE_ANDROID.
The default values for the EGL Android fence sync object attributes are as
follows:
- Attribute Name Initial Attribute Value(s)
- --------------- --------------------------
- EGL_SYNC_TYPE_KHR EGL_SYNC_ANDROID_FENCE_ANDROID
- EGL_SYNC_STATUS_KHR EGL_UNSIGNALED_KHR
- EGL_SYNC_CONDITION_KHR EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR
+ Attribute Name Initial Attribute Value(s)
+ --------------- --------------------------
+ EGL_SYNC_TYPE_KHR EGL_SYNC_ANDROID_FENCE_ANDROID
+ EGL_SYNC_STATUS_KHR EGL_UNSIGNALED_KHR
+ EGL_SYNC_CONDITION_KHR EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR
+ EGL_SYNC_ANDROID_FENCE_FD_ANDROID EGL_NO_ANDROID_FENCE_ANDROID
- Upon creation of an EGL Android fence sync object, the
- EGL_SYNC_FENCE_FD_ANDROID attribute is set to a newly generated file
- descriptor that refers to a native Android fence object. If the
- EGL_SYNC_FENCE_FD_ANDROID attribute is specified in the eglCreateSyncKHR
- call then the generated file descriptor refers to the same native Android
- fence object as the file descriptor passed to eglCreateSyncKHR. Note,
- however, that the value of the sync object attribute is *not* the same file
- descriptor as the one passed to eglCreateSyncKHR - it simply refers to the
- same underlying native Android fence object. Additionally, if the
- EGL_SYNC_FENCE_FD_ANDROID attribute is specified then the
- EGL_SYNC_CONDITION_KHR attribute is set to
- EGL_SYNC_ANDROID_FENCE_SIGNALED_ANDROID and the EGL_SYNC_STATUS_KHR
+ If the EGL_SYNC_ANDROID_FENCE_FD_ANDROID attribute is not
+ EGL_NO_ANDROID_FENCE_ANDROID then the EGL_SYNC_CONDITION_KHR attribute is
+ set to EGL_SYNC_ANDROID_FENCE_SIGNALED_ANDROID and the EGL_SYNC_STATUS_KHR
attribute is set to reflect the signal status of the native Android fence
- object."
+ object. Additionally, the EGL implementation assumes ownership of the file
+ descriptor, so the caller must not use it after calling eglCreateSyncKHR."
Modify Section 3.8.1 (Sync Objects), added by KHR_fence_sync, starting at
the seventh paragraph
"When a fence sync object is created or when an EGL Android fence sync
- object is created without specifying the EGL_SYNC_FENCE_FD_ANDROID
- attribute, eglCreateSyncKHR also inserts a fence command into the command
- stream of the bound client API's current context (i.e., the context
- returned by eglGetCurrentContext), and associates it with the newly created
- sync object.
+ object is created with the EGL_SYNC_ANDROID_FENCE_FD_ANDROID attribute set
+ to EGL_NO_ANDROID_FENCE_ANDROID, eglCreateSyncKHR also inserts a fence
+ command into the command stream of the bound client API's current context
+ (i.e., the context returned by eglGetCurrentContext), and associates it
+ with the newly created sync object.
+
+ After associating the fence command with an EGL Android fence sync object,
+ the next Flush() operation performed by the current client API causes a
+ new native Android fence object to be created, and the
+ EGL_SYNC_ANDROID_FENCE_ANDROID attribute of the EGL Android fence object
+ is set to a file descriptor that refers to the new native Android fence
+ object. This new native Android fence object is signaled when the EGL
+ Android fence sync object is signaled.
When the condition of the sync object is satisfied by the fence command,
the sync is signaled by the associated client API context, causing any
@@ -124,7 +133,8 @@
state is affected by execution of the fence command.
The EGL_SYNC_ANDROID_FENCE_SIGNALED_ANDROID condition is satisfied by the
- signaling of the native Android fence object. When this happens any
+ signaling of the native Android fence object referred to by the
+ EGL_SYNC_ANDROID_FENCE_FD_ANDROID attribute. When this happens any
eglClientWaitSyncKHR commands blocking on <sync> unblock."
Modify the list of eglCreateSyncKHR errors in Section 3.8.1 (Sync Objects),
@@ -140,7 +150,7 @@
empty (containing only EGL_NONE), EGL_NO_SYNC_KHR is returned and an
EGL_BAD_ATTRIBUTE error is generated.
* If <type> is EGL_SYNC_ANDROID_FENCE_ANDROID and <attrib_list> contains
- an attribute other than EGL_SYNC_FENCE_FD_ANDROID, EGL_NO_SYNC_KHR is
+ an attribute other than EGL_SYNC_ANDROID_FENCE_FD_ANDROID, EGL_NO_SYNC_KHR is
returned and an EGL_BAD_ATTRIBUTE error is generated.
* If <type> is not a supported type of sync object,
EGL_NO_SYNC_KHR is returned and an EGL_BAD_ATTRIBUTE error is
@@ -162,14 +172,12 @@
Modify table 3.cc in Section 3.8.1 (Sync Objects), added by KHR_fence_sync
"
- Attribute Description Supported Sync Objects
- ----------------- ----------------------- ----------------------
- EGL_SYNC_TYPE_KHR Type of the sync object All
- EGL_SYNC_STATUS_KHR Status of the sync object All
- EGL_SYNC_CONDITION_KHR Signaling condition EGL_SYNC_FENCE_KHR and
- EGL_SYNC_ANDROID_FENCE_ANDROID only
- EGL_SYNC_FENCE_FD_ANDROID Native Android fence EGL_SYNC_ANDROID_FENCE_ANDROID only
- object file descriptor
+ Attribute Description Supported Sync Objects
+ ----------------- ----------------------- ----------------------
+ EGL_SYNC_TYPE_KHR Type of the sync object All
+ EGL_SYNC_STATUS_KHR Status of the sync object All
+ EGL_SYNC_CONDITION_KHR Signaling condition EGL_SYNC_FENCE_KHR and
+ EGL_SYNC_ANDROID_FENCE_ANDROID only
"
Modify the second paragraph description of eglDestroySyncKHR in Section
@@ -177,9 +185,34 @@
"If no errors are generated, EGL_TRUE is returned, and <sync> will no
longer be the handle of a valid sync object. Additionally, if <sync> is an
- EGL Android fence sync object then the file descriptor stored in the
- EGL_SYNC_FENCE_FD_ANDROID attribute is closed and is no longer a valid file
- descriptor."
+ EGL Android fence sync object and the EGL_SYNC_ANDROID_FENCE_FD_ANDROID
+ attribute is not EGL_NO_ANDROID_FENCE_ANDROID then that file descriptor is
+ closed."
+
+ Add the following after the last paragraph of Section 3.8.1 (Sync
+ Objects), added by KHR_fence_sync
+
+ The command
+
+ EGLint eglDupAndroidFenceFDANDROID(
+ EGLdisplay dpy,
+ EGLSyncKHR sync);
+
+ duplicates the file descriptor stored in the
+ EGL_SYNC_ANDROID_FENCE_FD_ANDROID attribute of an EGL Android fence sync
+ object and returns the new file descriptor.
+
+ Errors
+ ------
+
+ * If <sync> is not a valid sync object for <dpy>,
+ EGL_NO_ANDROID_FENCE_ANDROID is returned and an EGL_BAD_PARAMETER
+ error is generated.
+ * If the EGL_SYNC_ANDROID_FENCE_FD_ANDROID attribute of <sync> is
+ EGL_NO_ANDROID_FENCE_ANDROID, EGL_NO_ANDROID_FENCE_ANDROID is returned
+ and an EGL_BAD_PARAMETER error is generated.
+ * If <dpy> does not match the display passed to eglCreateSyncKHR
+ when <sync> was created, the behaviour is undefined."
Issues
@@ -198,16 +231,38 @@
2. Who is responsible for dup'ing the Android fence file descriptors?
- RESOLVED: The recipient of a file descriptor is responsible for dup'ing it
- if it wishes to maintain a reference to the Android fence object.
+ RESOLVED: Whenever a file descriptor is passed into or returned from an
+ EGL call in this extension, ownership of that file descriptor is
+ transfered. The recipient of the file descriptor must close it when it is
+ no longer needed, and the provider of the file descriptor must dup it
+ before providing it if they require continued use of the native Android
+ fence.
- This means that when eglCreateSyncKHR is called with an existing file
- descriptor, the EGL implementation must dup it. On the other hand, when
- eglGetSyncAttribKHR is called to query the file descriptor, it is the
- responsibility of the caller to dup the file descriptor if it wishes to
- maintain a reference that will outlast the EGLSyncKHR object.
+ 3. Can the EGL_SYNC_ANDROID_FENCE_FD_ANDROID attribute be queried?
+
+ RESOLVED: No.
+
+ Returning the file descriptor owned by the EGL implementation would
+ violate the file descriptor ownership rule described in issue #2. Having
+ eglGetSyncAttribKHR return a different (dup'd) file descriptor each time
+ it's called seems wrong, so a new function was added to explicitly dup the
+ file descriptor.
+
+ That said, the attribute is useful both as a way to pass an existing file
+ descriptor to eglCreateSyncKHR and as a way to describe the subsequent
+ behavior of EGL Android fence sync objects, so it is left as an attribute
+ for which the value cannot be queried.
Revision History
+#2 (Jamie Gennis, July 23, 2012)
+ - Changed the file descriptor ownership transferring behavior.
+ - Added the eglDupAndroidFenceFDANDROID function.
+ - Removed EGL_SYNC_ANDROID_FENCE_FD_ANDROID from the table of gettable
+ attributes.
+ - Added language specifying that a native Android fence is created at the
+ flush following the creation of an EGL Android fence sync object that is
+ not passed an existing native fence.
+
#1 (Jamie Gennis, May 29, 2012)
- Initial draft.
diff --git a/services/surfaceflinger/DisplayHardware.cpp b/services/surfaceflinger/DisplayHardware.cpp
index eb64c9f..af33a89 100644
--- a/services/surfaceflinger/DisplayHardware.cpp
+++ b/services/surfaceflinger/DisplayHardware.cpp
@@ -31,6 +31,7 @@
#include <EGL/eglext.h>
#include <hardware/gralloc.h>
+#include <private/gui/SharedBufferStack.h>
#include "DisplayHardware/FramebufferSurface.h"
#include "DisplayHardware/DisplayHardwareBase.h"
@@ -40,8 +41,9 @@
#include "GLExtensions.h"
#include "SurfaceFlinger.h"
+// ----------------------------------------------------------------------------
using namespace android;
-
+// ----------------------------------------------------------------------------
static __attribute__((noinline))
void checkGLErrors()
@@ -88,6 +90,8 @@
}
}
+// ----------------------------------------------------------------------------
+
/*
* Initialize the display to the specified values.
*
@@ -95,79 +99,78 @@
DisplayHardware::DisplayHardware(
const sp<SurfaceFlinger>& flinger,
- uint32_t dpy)
- : DisplayHardwareBase(flinger, dpy),
- mFlinger(flinger), mFlags(0), mHwc(0)
+ int display,
+ const sp<SurfaceTextureClient>& surface,
+ EGLConfig config)
+ : DisplayHardwareBase(flinger, display),
+ mFlinger(flinger),
+ mDisplayId(display),
+ mHwc(0),
+ mNativeWindow(surface),
+ mFlags(0),
+ mSecureLayerVisible(false)
{
- init(dpy);
+ init(config);
}
-DisplayHardware::~DisplayHardware()
-{
- fini();
+DisplayHardware::~DisplayHardware() {
}
-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 mDisplayWidth; }
-int DisplayHardware::getHeight() const { return mDisplayHeight; }
-PixelFormat DisplayHardware::getFormat() const { return mFormat; }
-uint32_t DisplayHardware::getMaxTextureSize() const { return mMaxTextureSize; }
-
-uint32_t DisplayHardware::getMaxViewportDims() const {
- return mMaxViewportDims[0] < mMaxViewportDims[1] ?
- mMaxViewportDims[0] : mMaxViewportDims[1];
+float DisplayHardware::getDpiX() const {
+ return mDpiX;
}
-static status_t selectConfigForPixelFormat(
- EGLDisplay dpy,
- EGLint const* attrs,
- PixelFormat format,
- EGLConfig* outConfig)
-{
- EGLConfig config = NULL;
- EGLint numConfigs = -1, n=0;
- eglGetConfigs(dpy, NULL, 0, &numConfigs);
- EGLConfig* const configs = new EGLConfig[numConfigs];
- eglChooseConfig(dpy, attrs, configs, numConfigs, &n);
- for (int i=0 ; i<n ; i++) {
- EGLint nativeVisualId = 0;
- eglGetConfigAttrib(dpy, configs[i], EGL_NATIVE_VISUAL_ID, &nativeVisualId);
- if (nativeVisualId>0 && format == nativeVisualId) {
- *outConfig = configs[i];
- delete [] configs;
- return NO_ERROR;
- }
- }
- delete [] configs;
- return NAME_NOT_FOUND;
+float DisplayHardware::getDpiY() const {
+ return mDpiY;
}
+float DisplayHardware::getDensity() const {
+ return mDensity;
+}
-void DisplayHardware::init(uint32_t dpy)
+float DisplayHardware::getRefreshRate() const {
+ return mRefreshRate;
+}
+
+int DisplayHardware::getWidth() const {
+ return mDisplayWidth;
+}
+
+int DisplayHardware::getHeight() const {
+ return mDisplayHeight;
+}
+
+PixelFormat DisplayHardware::getFormat() const {
+ return mFormat;
+}
+
+EGLSurface DisplayHardware::getEGLSurface() const {
+ return mSurface;
+}
+
+void DisplayHardware::init(EGLConfig config)
{
- mNativeWindow = new FramebufferSurface();
- framebuffer_device_t const * fbDev = mNativeWindow->getDevice();
- if (!fbDev) {
- ALOGE("Display subsystem failed to initialize. check logs. exiting...");
- exit(0);
+ ANativeWindow* const window = mNativeWindow.get();
+
+ int concreteType;
+ window->query(window, NATIVE_WINDOW_CONCRETE_TYPE, &concreteType);
+ if (concreteType == NATIVE_WINDOW_FRAMEBUFFER) {
+ mFramebufferSurface = static_cast<FramebufferSurface *>(mNativeWindow.get());
}
int format;
- ANativeWindow const * const window = mNativeWindow.get();
window->query(window, NATIVE_WINDOW_FORMAT, &format);
- mDpiX = mNativeWindow->xdpi;
- mDpiY = mNativeWindow->ydpi;
- mRefreshRate = fbDev->fps;
-
- if (mDpiX == 0 || mDpiY == 0) {
- ALOGE("invalid screen resolution from fb HAL (xdpi=%f, ydpi=%f), "
- "defaulting to 160 dpi", mDpiX, mDpiY);
- mDpiX = mDpiY = 160;
+ mDpiX = window->xdpi;
+ mDpiY = window->ydpi;
+ if (mFramebufferSurface != NULL) {
+ mRefreshRate = mFramebufferSurface->getRefreshRate();
+ } else {
+ mRefreshRate = 60;
}
+ mRefreshPeriod = nsecs_t(1e9 / mRefreshRate);
+
+ // TODO: Not sure if display density should handled by SF any longer
class Density {
static int getDensityFromProperty(char const* propName) {
char property[PROPERTY_VALUE_MAX];
@@ -183,173 +186,52 @@
static int getBuildDensity() {
return getDensityFromProperty("ro.sf.lcd_density"); }
};
-
-
// The density of the device is provided by a build property
mDensity = Density::getBuildDensity() / 160.0f;
-
if (mDensity == 0) {
// the build doesn't provide a density -- this is wrong!
// use xdpi instead
ALOGE("ro.sf.lcd_density must be defined as a build property");
mDensity = mDpiX / 160.0f;
}
-
if (Density::getEmuDensity()) {
// if "qemu.sf.lcd_density" is specified, it overrides everything
mDpiX = mDpiY = mDensity = Density::getEmuDensity();
mDensity /= 160.0f;
}
-
-
- /* FIXME: this is a temporary HACK until we are able to report the refresh rate
- * properly from the HAL. The WindowManagerService now relies on this value.
- */
-#ifndef REFRESH_RATE
- mRefreshRate = fbDev->fps;
-#else
- mRefreshRate = REFRESH_RATE;
-#warning "refresh rate set via makefile to REFRESH_RATE"
-#endif
-
- mRefreshPeriod = nsecs_t(1e9 / mRefreshRate);
-
- EGLint w, h, dummy;
- EGLint numConfigs=0;
- EGLSurface surface;
- EGLContext context;
- EGLBoolean result;
- status_t err;
-
- // initialize EGL
- EGLint attribs[] = {
- EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
- EGL_RECORDABLE_ANDROID, EGL_TRUE,
- EGL_NONE
- };
-
- // 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);
-
- EGLConfig config = NULL;
- err = selectConfigForPixelFormat(display, attribs, format, &config);
- if (err) {
- // maybe we failed because of EGL_RECORDABLE_ANDROID
- ALOGW("couldn't find an EGLConfig with EGL_RECORDABLE_ANDROID");
- attribs[2] = EGL_NONE;
- err = selectConfigForPixelFormat(display, attribs, format, &config);
- }
-
- ALOGE_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);
-
- if (mNativeWindow->isUpdateOnDemand()) {
- mFlags |= PARTIAL_UPDATES;
- }
-
- if (eglGetConfigAttrib(display, config, EGL_CONFIG_CAVEAT, &dummy) == EGL_TRUE) {
- if (dummy == EGL_SLOW_CONFIG)
- mFlags |= SLOW_CONFIG;
- }
-
/*
- * Create our main surface
+ * Create our display's surface
*/
- surface = eglCreateWindowSurface(display, config, mNativeWindow.get(), NULL);
+ EGLSurface surface;
+ EGLint w, h;
+ EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ surface = eglCreateWindowSurface(display, config, window, NULL);
eglQuerySurface(display, surface, EGL_WIDTH, &mDisplayWidth);
eglQuerySurface(display, surface, EGL_HEIGHT, &mDisplayHeight);
- 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 (mFramebufferSurface != NULL) {
+ if (mFramebufferSurface->isUpdateOnDemand()) {
+ 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);
+ }
}
- /*
- * Create our OpenGL ES context
- */
-
- EGLint contextAttributes[] = {
-#ifdef EGL_IMG_context_priority
-#ifdef HAS_CONTEXT_PRIORITY
-#warning "using EGL_IMG_context_priority"
- EGL_CONTEXT_PRIORITY_LEVEL_IMG, EGL_CONTEXT_PRIORITY_HIGH_IMG,
-#endif
-#endif
- EGL_NONE, EGL_NONE
- };
- context = eglCreateContext(display, config, NULL, contextAttributes);
-
mDisplay = display;
- mConfig = config;
mSurface = surface;
- mContext = context;
- mFormat = fbDev->format;
+ mFormat = format;
mPageFlipCount = 0;
- /*
- * Gather OpenGL ES extensions
- */
-
- result = eglMakeCurrent(display, surface, surface, context);
- if (!result) {
- ALOGE("Couldn't create a working GLES context. check logs. exiting...");
- exit(0);
- }
-
- GLExtensions& extensions(GLExtensions::getInstance());
- extensions.initWithGLStrings(
- glGetString(GL_VENDOR),
- glGetString(GL_RENDERER),
- glGetString(GL_VERSION),
- glGetString(GL_EXTENSIONS),
- eglQueryString(display, EGL_VENDOR),
- eglQueryString(display, EGL_VERSION),
- eglQueryString(display, EGL_EXTENSIONS));
-
- glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
- glGetIntegerv(GL_MAX_VIEWPORT_DIMS, mMaxViewportDims);
-
- ALOGI("EGL informations:");
- ALOGI("# of configs : %d", numConfigs);
- ALOGI("vendor : %s", extensions.getEglVendor());
- ALOGI("version : %s", extensions.getEglVersion());
- ALOGI("extensions: %s", extensions.getEglExtension());
- ALOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported");
- ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config);
-
- ALOGI("OpenGL informations:");
- ALOGI("vendor : %s", extensions.getVendor());
- ALOGI("renderer : %s", extensions.getRenderer());
- ALOGI("version : %s", extensions.getVersion());
- ALOGI("extensions: %s", extensions.getExtension());
- ALOGI("GL_MAX_TEXTURE_SIZE = %d", mMaxTextureSize);
- ALOGI("GL_MAX_VIEWPORT_DIMS = %d x %d", mMaxViewportDims[0], mMaxViewportDims[1]);
- ALOGI("flags = %08x", mFlags);
-
- // Unbind the context from this thread
- eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-
-
// initialize the H/W composer
mHwc = new HWComposer(mFlinger, *this, mRefreshPeriod);
if (mHwc->initCheck() == NO_ERROR) {
mHwc->setFrameBuffer(mDisplay, mSurface);
}
-
// initialize the display orientation transform.
// it's a constant that should come from the display driver.
int displayOrientation = ISurfaceComposer::eOrientationDefault;
@@ -378,6 +260,20 @@
mLogicalDisplayHeight = h;
}
DisplayHardware::setOrientation(ISurfaceComposer::eOrientationDefault);
+
+ // initialize the shared control block
+ surface_flinger_cblk_t* const scblk = mFlinger->getControlBlock();
+ scblk->connected |= 1 << mDisplayId;
+ display_cblk_t* dcblk = &scblk->displays[mDisplayId];
+ memset(dcblk, 0, sizeof(display_cblk_t));
+ dcblk->w = w; // XXX: plane.getWidth();
+ dcblk->h = h; // XXX: plane.getHeight();
+ dcblk->format = format;
+ dcblk->orientation = ISurfaceComposer::eOrientationDefault;
+ dcblk->xdpi = mDpiX;
+ dcblk->ydpi = mDpiY;
+ dcblk->fps = mRefreshRate;
+ dcblk->density = mDensity;
}
void DisplayHardware::setVSyncHandler(const sp<VSyncHandler>& handler) {
@@ -411,19 +307,6 @@
return *mHwc;
}
-/*
- * 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);
-}
-
void DisplayHardware::releaseScreen() const
{
DisplayHardwareBase::releaseScreen();
@@ -458,7 +341,10 @@
}
status_t DisplayHardware::compositionComplete() const {
- return mNativeWindow->compositionComplete();
+ if (mFramebufferSurface == NULL) {
+ return NO_ERROR;
+ }
+ return mFramebufferSurface->compositionComplete();
}
void DisplayHardware::flip(const Region& dirty) const
@@ -478,7 +364,9 @@
#endif
if (mFlags & PARTIAL_UPDATES) {
- mNativeWindow->setUpdateRectangle(dirty.getBounds());
+ if (mFramebufferSurface != NULL) {
+ mFramebufferSurface->setUpdateRectangle(dirty.getBounds());
+ }
}
mPageFlipCount++;
@@ -489,10 +377,6 @@
eglSwapBuffers(dpy, surface);
}
checkEGLErrors("eglSwapBuffers");
-
- // for debugging
- //glClearColor(1,0,0,0);
- //glClear(GL_COLOR_BUFFER_BIT);
}
uint32_t DisplayHardware::getFlags() const
@@ -500,14 +384,31 @@
return mFlags;
}
-void DisplayHardware::makeCurrent() const
-{
- eglMakeCurrent(mDisplay, mSurface, mSurface, mContext);
-}
-
void DisplayHardware::dump(String8& res) const
{
- mNativeWindow->dump(res);
+ if (mFramebufferSurface != NULL) {
+ mFramebufferSurface->dump(res);
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+void DisplayHardware::setVisibleLayersSortedByZ(const Vector< sp<LayerBase> >& layers) {
+ mVisibleLayersSortedByZ = layers;
+ size_t count = layers.size();
+ for (size_t i=0 ; i<count ; i++) {
+ if (layers[i]->isSecure()) {
+ mSecureLayerVisible = true;
+ }
+ }
+}
+
+Vector< sp<LayerBase> > DisplayHardware::getVisibleLayersSortedByZ() const {
+ return mVisibleLayersSortedByZ;
+}
+
+bool DisplayHardware::getSecureLayerVisible() const {
+ return mSecureLayerVisible;
}
// ----------------------------------------------------------------------------
diff --git a/services/surfaceflinger/DisplayHardware.h b/services/surfaceflinger/DisplayHardware.h
index 3da9f16..029c3da 100644
--- a/services/surfaceflinger/DisplayHardware.h
+++ b/services/surfaceflinger/DisplayHardware.h
@@ -27,7 +27,6 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
-#include "GLExtensions.h"
#include "Transform.h"
#include "DisplayHardware/DisplayHardwareBase.h"
@@ -37,6 +36,7 @@
namespace android {
class FramebufferSurface;
+class SurfaceTextureClient;
class DisplayHardware :
public DisplayHardwareBase,
@@ -52,15 +52,15 @@
};
enum {
- COPY_BITS_EXTENSION = 0x00000008,
PARTIAL_UPDATES = 0x00020000, // video driver feature
- SLOW_CONFIG = 0x00040000, // software
SWAP_RECTANGLE = 0x00080000,
};
DisplayHardware(
const sp<SurfaceFlinger>& flinger,
- uint32_t displayIndex);
+ int dpy,
+ const sp<SurfaceTextureClient>& surface,
+ EGLConfig config);
virtual ~DisplayHardware();
@@ -79,11 +79,14 @@
int getHeight() const;
PixelFormat getFormat() const;
uint32_t getFlags() const;
- uint32_t getMaxTextureSize() const;
- uint32_t getMaxViewportDims() const;
nsecs_t getRefreshPeriod() const;
nsecs_t getRefreshTimestamp() const;
- void makeCurrent() const;
+
+ EGLSurface getEGLSurface() const;
+
+ void setVisibleLayersSortedByZ(const Vector< sp<LayerBase> >& layers);
+ Vector< sp<LayerBase> > getVisibleLayersSortedByZ() const;
+ bool getSecureLayerVisible() const;
status_t setOrientation(int orientation);
int getOrientation() const { return mOrientation; }
@@ -102,7 +105,6 @@
uint32_t getPageFlipCount() const;
EGLDisplay getEGLDisplay() const { return mDisplay; }
- EGLConfig getEGLConfig() const { return mConfig; }
void dump(String8& res) const;
@@ -117,15 +119,26 @@
inline Rect bounds() const { return getBounds(); }
private:
- virtual void onVSyncReceived(int dpy, nsecs_t timestamp);
- void init(uint32_t displayIndex);
- void fini();
+ void init(EGLConfig config);
+ virtual void onVSyncReceived(int dpy, nsecs_t timestamp);
+
+ /*
+ * Constants, set during initialization
+ */
sp<SurfaceFlinger> mFlinger;
+ int mDisplayId;
+ HWComposer* mHwc;
+ PowerHAL mPowerHAL;
+ // ANativeWindow this display is rendering into
+ sp<SurfaceTextureClient> mNativeWindow;
+ // set if mNativeWindow is a FramebufferSurface
+ sp<FramebufferSurface> mFramebufferSurface;
+
+
EGLDisplay mDisplay;
EGLSurface mSurface;
EGLContext mContext;
- EGLConfig mConfig;
float mDpiX;
float mDpiY;
float mRefreshRate;
@@ -135,15 +148,19 @@
PixelFormat mFormat;
uint32_t mFlags;
mutable uint32_t mPageFlipCount;
- GLint mMaxViewportDims[2];
- GLint mMaxTextureSize;
nsecs_t mRefreshPeriod;
mutable nsecs_t mLastHwVSync;
- // constant once set
- HWComposer* mHwc;
- PowerHAL mPowerHAL;
+
+ /*
+ * Can only accessed from the main thread, these members
+ * don't need synchronization.
+ */
+ // list of visible layers on that display
+ Vector< sp<LayerBase> > mVisibleLayersSortedByZ;
+ // Whether we have a visible secure layer on this display
+ bool mSecureLayerVisible;
// this used to be in GraphicPlane
@@ -157,13 +174,12 @@
int mUserDisplayWidth;
int mUserDisplayHeight;
-
mutable Mutex mLock;
- // protected by mLock
+ /*
+ * protected by mLock
+ */
wp<VSyncHandler> mVSyncHandler;
-
- sp<FramebufferSurface> mNativeWindow;
};
}; // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 6cfb190..7695e7f 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -38,6 +38,15 @@
namespace android {
// ----------------------------------------------------------------------------
+sp<FramebufferSurface> FramebufferSurface::create() {
+ sp<FramebufferSurface> result = new FramebufferSurface();
+ if (result->fbDev == NULL) {
+ result = NULL;
+ }
+ return result;
+}
+
+// ----------------------------------------------------------------------------
/*
* This implements the (main) framebuffer management. This class is used
@@ -64,10 +73,19 @@
mUpdateOnDemand = (fbDev->setUpdateRect != 0);
const_cast<uint32_t&>(ANativeWindow::flags) = fbDev->flags;
- const_cast<float&>(ANativeWindow::xdpi) = fbDev->xdpi;
- const_cast<float&>(ANativeWindow::ydpi) = fbDev->ydpi;
const_cast<int&>(ANativeWindow::minSwapInterval) = fbDev->minSwapInterval;
const_cast<int&>(ANativeWindow::maxSwapInterval) = fbDev->maxSwapInterval;
+
+ if (fbDev->xdpi == 0 || fbDev->ydpi == 0) {
+ ALOGE("invalid screen resolution from fb HAL (xdpi=%f, ydpi=%f), "
+ "defaulting to 160 dpi", fbDev->xdpi, fbDev->ydpi);
+ const_cast<float&>(ANativeWindow::xdpi) = 160;
+ const_cast<float&>(ANativeWindow::ydpi) = 160;
+ } else {
+ const_cast<float&>(ANativeWindow::xdpi) = fbDev->xdpi;
+ const_cast<float&>(ANativeWindow::ydpi) = fbDev->ydpi;
+ }
+
} else {
ALOGE("Couldn't get gralloc module");
}
@@ -139,6 +157,19 @@
}
}
+float FramebufferSurface::getRefreshRate() const {
+ /* FIXME: REFRESH_RATE is a temporary HACK until we are able to report the
+ * refresh rate properly from the HAL. The WindowManagerService now relies
+ * on this value.
+ */
+#ifndef REFRESH_RATE
+ return fbDev->fps;
+#else
+ return REFRESH_RATE;
+#warning "refresh rate set via makefile to REFRESH_RATE"
+#endif
+}
+
status_t FramebufferSurface::setUpdateRectangle(const Rect& r)
{
if (!mUpdateOnDemand) {
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
index 5b4fd01..672bfbb 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
@@ -37,11 +37,11 @@
class FramebufferSurface : public SurfaceTextureClient {
public:
- FramebufferSurface();
- virtual void onFirstRef();
+ static sp<FramebufferSurface> create();
- framebuffer_device_t const * getDevice() const { return fbDev; }
+ // TODO: this should be coming from HWC
+ float getRefreshRate() const;
bool isUpdateOnDemand() const { return mUpdateOnDemand; }
status_t setUpdateRectangle(const Rect& updateRect);
@@ -49,7 +49,11 @@
void dump(String8& result);
+protected:
+ virtual void onFirstRef();
+
private:
+ FramebufferSurface();
virtual ~FramebufferSurface(); // this class cannot be overloaded
virtual int query(int what, int* value) const;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index a09b5c7..b2f2683 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -182,11 +182,8 @@
return err;
}
- // the display's pixel format
- // XXX: we shouldn't rely on the DisplayHardware to do this
- const DisplayHardware& hw(mFlinger->getDefaultDisplayHardware());
uint32_t const maxSurfaceDims = min(
- hw.getMaxTextureSize(), hw.getMaxViewportDims());
+ mFlinger->getMaxTextureSize(), mFlinger->getMaxViewportDims());
// never allow a surface larger than what our underlying GL implementation
// can handle.
diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h
index d227b2d..c689297 100644
--- a/services/surfaceflinger/LayerBase.h
+++ b/services/surfaceflinger/LayerBase.h
@@ -25,6 +25,7 @@
#include <GLES/gl.h>
#include <utils/RefBase.h>
+#include <utils/String8.h>
#include <ui/Region.h>
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 6c900be..840222c 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -59,6 +59,7 @@
#include "LayerScreenshot.h"
#include "SurfaceFlinger.h"
+#include "DisplayHardware/FramebufferSurface.h"
#include "DisplayHardware/HWComposer.h"
#include <private/android_filesystem_config.h>
@@ -98,7 +99,6 @@
mDebugInTransaction(0),
mLastTransactionTime(0),
mBootFinished(false),
- mSecureFrameBuffer(0),
mExternalDisplaySurface(EGL_NO_SURFACE)
{
init();
@@ -142,6 +142,9 @@
SurfaceFlinger::~SurfaceFlinger()
{
glDeleteTextures(1, &mWormholeTexName);
+ EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglTerminate(display);
}
void SurfaceFlinger::binderDied(const wp<IBinder>& who)
@@ -198,59 +201,95 @@
property_set("service.bootanim.exit", "1");
}
-static inline uint16_t pack565(int r, int g, int b) {
- return (r<<11)|(g<<5)|b;
+status_t SurfaceFlinger::selectConfigForPixelFormat(
+ EGLDisplay dpy,
+ EGLint const* attrs,
+ PixelFormat format,
+ EGLConfig* outConfig)
+{
+ EGLConfig config = NULL;
+ EGLint numConfigs = -1, n=0;
+ eglGetConfigs(dpy, NULL, 0, &numConfigs);
+ EGLConfig* const configs = new EGLConfig[numConfigs];
+ eglChooseConfig(dpy, attrs, configs, numConfigs, &n);
+ for (int i=0 ; i<n ; i++) {
+ EGLint nativeVisualId = 0;
+ eglGetConfigAttrib(dpy, configs[i], EGL_NATIVE_VISUAL_ID, &nativeVisualId);
+ if (nativeVisualId>0 && format == nativeVisualId) {
+ *outConfig = configs[i];
+ delete [] configs;
+ return NO_ERROR;
+ }
+ }
+ delete [] configs;
+ return NAME_NOT_FOUND;
}
-status_t SurfaceFlinger::readyToRun()
-{
- ALOGI( "SurfaceFlinger's main thread ready to run. "
- "Initializing graphics H/W...");
+EGLConfig SurfaceFlinger::selectEGLConfig(EGLDisplay display, EGLint nativeVisualId) {
+ // select our EGLConfig. It must support EGL_RECORDABLE_ANDROID if
+ // it is to be used with WIFI displays
+ EGLConfig config;
+ EGLint dummy;
+ status_t err;
+ EGLint attribs[] = {
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_RECORDABLE_ANDROID, EGL_TRUE,
+ EGL_NONE
+ };
+ err = selectConfigForPixelFormat(display, attribs, nativeVisualId, &config);
+ if (err) {
+ // maybe we failed because of EGL_RECORDABLE_ANDROID
+ ALOGW("couldn't find an EGLConfig with EGL_RECORDABLE_ANDROID");
+ attribs[2] = EGL_NONE;
+ err = selectConfigForPixelFormat(display, attribs, nativeVisualId, &config);
+ }
+ ALOGE_IF(err, "couldn't find an EGLConfig matching the screen format");
+ if (eglGetConfigAttrib(display, config, EGL_CONFIG_CAVEAT, &dummy) == EGL_TRUE) {
+ ALOGW_IF(dummy == EGL_SLOW_CONFIG, "EGL_SLOW_CONFIG selected!");
+ }
+ return config;
+}
- // we only support one display currently
- int dpy = 0;
+EGLContext SurfaceFlinger::createGLContext(EGLDisplay display, EGLConfig config) {
+ // Also create our EGLContext
+ EGLint contextAttributes[] = {
+#ifdef EGL_IMG_context_priority
+#ifdef HAS_CONTEXT_PRIORITY
+#warning "using EGL_IMG_context_priority"
+ EGL_CONTEXT_PRIORITY_LEVEL_IMG, EGL_CONTEXT_PRIORITY_HIGH_IMG,
+#endif
+#endif
+ EGL_NONE, EGL_NONE
+ };
+ EGLContext ctxt = eglCreateContext(display, config, NULL, contextAttributes);
+ ALOGE_IF(ctxt==EGL_NO_CONTEXT, "EGLContext creation failed");
+ return ctxt;
+}
- {
- // initialize the main display
- // TODO: initialize all displays
- DisplayHardware* const hw = new DisplayHardware(this, dpy);
- mDisplayHardwares[0] = hw;
+void SurfaceFlinger::initializeGL(EGLDisplay display, EGLSurface surface) {
+ EGLBoolean result = eglMakeCurrent(display, surface, surface, mEGLContext);
+ if (!result) {
+ ALOGE("Couldn't create a working GLES context. check logs. exiting...");
+ exit(0);
}
- // create the shared control-block
- mServerHeap = new MemoryHeapBase(4096,
- MemoryHeapBase::READ_ONLY, "SurfaceFlinger read-only heap");
- ALOGE_IF(mServerHeap==0, "can't create shared memory dealer");
+ GLExtensions& extensions(GLExtensions::getInstance());
+ extensions.initWithGLStrings(
+ glGetString(GL_VENDOR),
+ glGetString(GL_RENDERER),
+ glGetString(GL_VERSION),
+ glGetString(GL_EXTENSIONS),
+ eglQueryString(display, EGL_VENDOR),
+ eglQueryString(display, EGL_VERSION),
+ eglQueryString(display, EGL_EXTENSIONS));
- mServerCblk = static_cast<surface_flinger_cblk_t*>(mServerHeap->getBase());
- ALOGE_IF(mServerCblk==0, "can't get to shared control block's address");
+ EGLint w, h;
+ eglQuerySurface(display, surface, EGL_WIDTH, &w);
+ eglQuerySurface(display, surface, EGL_HEIGHT, &h);
- new(mServerCblk) surface_flinger_cblk_t;
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
+ glGetIntegerv(GL_MAX_VIEWPORT_DIMS, mMaxViewportDims);
- // 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
- // yet).
- const DisplayHardware& hw(getDefaultDisplayHardware());
- const uint32_t w = hw.getWidth();
- const uint32_t h = hw.getHeight();
- const uint32_t f = hw.getFormat();
- hw.makeCurrent();
-
- // initialize the shared control block
- mServerCblk->connected |= 1<<dpy;
- display_cblk_t* dcblk = mServerCblk->displays + dpy;
- memset(dcblk, 0, sizeof(display_cblk_t));
- dcblk->w = w; // XXX: plane.getWidth();
- dcblk->h = h; // XXX: plane.getHeight();
- dcblk->format = f;
- dcblk->orientation = ISurfaceComposer::eOrientationDefault;
- dcblk->xdpi = hw.getDpiX();
- dcblk->ydpi = hw.getDpiY();
- dcblk->fps = hw.getRefreshRate();
- dcblk->density = hw.getDensity();
-
- // Initialize OpenGL|ES
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glPixelStorei(GL_PACK_ALIGNMENT, 4);
glEnableClientState(GL_VERTEX_ARRAY);
@@ -258,6 +297,12 @@
glDisable(GL_DITHER);
glDisable(GL_CULL_FACE);
+ struct pack565 {
+ inline uint16_t operator() (int r, int g, int b) const {
+ return (r<<11)|(g<<5)|b;
+ }
+ } pack565;
+
const uint16_t g0 = pack565(0x0F,0x1F,0x0F);
const uint16_t g1 = pack565(0x17,0x2f,0x17);
const uint16_t wormholeTexData[4] = { g0, g1, g1, g0 };
@@ -286,15 +331,77 @@
// put the origin in the left-bottom corner
glOrthof(0, w, 0, h, 0, 1); // l=0, r=w ; b=0, t=h
+ // print some debugging info
+ EGLint r,g,b,a;
+ eglGetConfigAttrib(display, mEGLConfig, EGL_RED_SIZE, &r);
+ eglGetConfigAttrib(display, mEGLConfig, EGL_GREEN_SIZE, &g);
+ eglGetConfigAttrib(display, mEGLConfig, EGL_BLUE_SIZE, &b);
+ eglGetConfigAttrib(display, mEGLConfig, EGL_ALPHA_SIZE, &a);
+ ALOGI("EGL informations:");
+ ALOGI("vendor : %s", extensions.getEglVendor());
+ ALOGI("version : %s", extensions.getEglVersion());
+ ALOGI("extensions: %s", extensions.getEglExtension());
+ ALOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported");
+ ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, mEGLConfig);
+ ALOGI("OpenGL ES informations:");
+ ALOGI("vendor : %s", extensions.getVendor());
+ ALOGI("renderer : %s", extensions.getRenderer());
+ ALOGI("version : %s", extensions.getVersion());
+ ALOGI("extensions: %s", extensions.getExtension());
+ ALOGI("GL_MAX_TEXTURE_SIZE = %d", mMaxTextureSize);
+ ALOGI("GL_MAX_VIEWPORT_DIMS = %d x %d", mMaxViewportDims[0], mMaxViewportDims[1]);
+}
+
+surface_flinger_cblk_t* SurfaceFlinger::getControlBlock() const {
+ return mServerCblk;
+}
+
+status_t SurfaceFlinger::readyToRun()
+{
+ ALOGI( "SurfaceFlinger's main thread ready to run. "
+ "Initializing graphics H/W...");
+
+ // create the shared control-block
+ mServerHeap = new MemoryHeapBase(4096,
+ MemoryHeapBase::READ_ONLY, "SurfaceFlinger read-only heap");
+ ALOGE_IF(mServerHeap==0, "can't create shared memory dealer");
+ mServerCblk = static_cast<surface_flinger_cblk_t*>(mServerHeap->getBase());
+ ALOGE_IF(mServerCblk==0, "can't get to shared control block's address");
+ new(mServerCblk) surface_flinger_cblk_t;
+
+
+ // initialize EGL
+ EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ eglInitialize(display, NULL, NULL);
+
+ // Initialize the main display
+ // create native window to main display
+ sp<FramebufferSurface> anw = FramebufferSurface::create();
+ ANativeWindow* const window = anw.get();
+ if (!window) {
+ ALOGE("Display subsystem failed to initialize. check logs. exiting...");
+ exit(0);
+ }
+
+ // initialize the config and context
+ int format;
+ window->query(window, NATIVE_WINDOW_FORMAT, &format);
+ mEGLConfig = selectEGLConfig(display, format);
+ mEGLContext = createGLContext(display, mEGLConfig);
+
+ // initialize our main display hardware
+ DisplayHardware* const hw = new DisplayHardware(this, 0, anw, mEGLConfig);
+ mDisplayHardwares[0] = hw;
+
+ // initialize OpenGL ES
+ EGLSurface surface = hw->getEGLSurface();
+ initializeGL(display, surface);
// start the EventThread
mEventThread = new EventThread(this);
mEventQueue.setEventThread(mEventThread);
- /*
- * We're now ready to accept clients...
- */
-
+ // We're now ready to accept clients...
mReadyToRunBarrier.open();
// start boot animation
@@ -309,6 +416,15 @@
property_set("ctl.start", "bootanim");
}
+uint32_t SurfaceFlinger::getMaxTextureSize() const {
+ return mMaxTextureSize;
+}
+
+uint32_t SurfaceFlinger::getMaxViewportDims() const {
+ return mMaxViewportDims[0] < mMaxViewportDims[1] ?
+ mMaxViewportDims[0] : mMaxViewportDims[1];
+}
+
// ----------------------------------------------------------------------------
bool SurfaceFlinger::authenticateSurfaceTexture(
@@ -367,7 +483,7 @@
if (display != NULL) {
stc = new SurfaceTextureClient(display);
result = eglCreateWindowSurface(hw.getEGLDisplay(),
- hw.getEGLConfig(), (EGLNativeWindowType)stc.get(), NULL);
+ mEGLConfig, (EGLNativeWindowType)stc.get(), NULL);
ALOGE_IF(result == EGL_NO_SURFACE,
"eglCreateWindowSurface failed (ISurfaceTexture=%p)",
display.get());
@@ -465,6 +581,40 @@
void SurfaceFlinger::handleMessageRefresh() {
handleRefresh();
+ if (mVisibleRegionsDirty) {
+ Region opaqueRegion;
+ Region dirtyRegion;
+ const LayerVector& currentLayers(mDrawingState.layersSortedByZ);
+ computeVisibleRegions(currentLayers, dirtyRegion, opaqueRegion);
+ mDirtyRegion.orSelf(dirtyRegion);
+
+ /*
+ * rebuild the visible layer list per screen
+ */
+
+ // TODO: iterate through all displays
+ DisplayHardware& hw(const_cast<DisplayHardware&>(getDisplayHardware(0)));
+
+ Vector< sp<LayerBase> > layersSortedByZ;
+ const size_t count = currentLayers.size();
+ for (size_t i=0 ; i<count ; i++) {
+ if (!currentLayers[i]->visibleRegion.isEmpty()) {
+ // TODO: also check that this layer is associated to this display
+ layersSortedByZ.add(currentLayers[i]);
+ }
+ }
+ hw.setVisibleLayersSortedByZ(layersSortedByZ);
+
+
+ // FIXME: mWormholeRegion needs to be calculated per screen
+ //const DisplayHardware& hw(getDefaultDisplayHardware()); // XXX: we can't keep that here
+ mWormholeRegion = Region(hw.getBounds()).subtract(
+ hw.getTransform().transform(opaqueRegion) );
+ mVisibleRegionsDirty = false;
+ invalidateHwcGeometry();
+ }
+
+
// XXX: dirtyRegion should be per screen, we should check all of them
if (mDirtyRegion.isEmpty()) {
return;
@@ -515,7 +665,8 @@
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
- const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
+
+ const Vector< sp<LayerBase> >& layers( hw.getVisibleLayersSortedByZ() );
const size_t count = layers.size();
for (size_t i=0 ; i<count ; ++i) {
const sp<LayerBase>& layer(layers[i]);
@@ -546,7 +697,8 @@
const DisplayHardware& hw(getDefaultDisplayHardware());
HWComposer& hwc(hw.getHwComposer());
- size_t numLayers = mVisibleLayersSortedByZ.size();
+ const Vector< sp<LayerBase> >& layers(hw.getVisibleLayersSortedByZ());
+ size_t numLayers = layers.size();
const nsecs_t now = systemTime();
mDebugInSwapBuffers = now;
@@ -555,7 +707,7 @@
const HWComposer::LayerListIterator end = hwc.end();
for (size_t i = 0; cur != end && i < numLayers; ++i, ++cur) {
if (cur->getCompositionType() == HWC_OVERLAY) {
- mVisibleLayersSortedByZ[i]->setAcquireFence(*cur);
+ layers[i]->setAcquireFence(*cur);
} else {
cur->setAcquireFenceFd(-1);
}
@@ -568,11 +720,11 @@
HWComposer::LayerListIterator cur = hwc.begin();
const HWComposer::LayerListIterator end = hwc.end();
for (size_t i = 0; cur != end && i < numLayers; ++i, ++cur) {
- mVisibleLayersSortedByZ[i]->onLayerDisplayed(&*cur);
+ layers[i]->onLayerDisplayed(&*cur);
}
} else {
for (size_t i = 0; i < numLayers; i++) {
- mVisibleLayersSortedByZ[i]->onLayerDisplayed(NULL);
+ layers[i]->onLayerDisplayed(NULL);
}
}
@@ -713,7 +865,7 @@
Region aboveCoveredLayers;
Region dirty;
- bool secureFrameBuffer = false;
+ dirtyRegion.clear();
size_t i = currentLayers.size();
while (i--) {
@@ -823,14 +975,8 @@
// Store the visible region is screen space
layer->setVisibleRegion(visibleRegion);
layer->setCoveredRegion(coveredRegion);
-
- // If a secure layer is partially visible, lock-down the screen!
- if (layer->isSecure() && !visibleRegion.isEmpty()) {
- secureFrameBuffer = true;
- }
}
- mSecureFrameBuffer = secureFrameBuffer;
opaqueRegion = aboveOpaqueLayers;
}
@@ -849,30 +995,7 @@
dirtyRegion.orSelf( layer->latchBuffer(visibleRegions) );
}
- if (visibleRegions || mVisibleRegionsDirty) {
- Region opaqueRegion;
- computeVisibleRegions(currentLayers, dirtyRegion, opaqueRegion);
-
- /*
- * rebuild the visible layer list
- */
-
- // XXX: mVisibleLayersSortedByZ should be per-screen
- const size_t count = currentLayers.size();
- mVisibleLayersSortedByZ.clear();
- mVisibleLayersSortedByZ.setCapacity(count);
- for (size_t i=0 ; i<count ; i++) {
- if (!currentLayers[i]->visibleRegion.isEmpty())
- mVisibleLayersSortedByZ.add(currentLayers[i]);
- }
-
- // FIXME: mWormholeRegion needs to be calculated per screen
- const DisplayHardware& hw(getDefaultDisplayHardware()); // XXX: we can't keep that here
- mWormholeRegion = Region(hw.getBounds()).subtract(
- hw.getTransform().transform(opaqueRegion) );
- mVisibleRegionsDirty = false;
- invalidateHwcGeometry();
- }
+ mVisibleRegionsDirty |= visibleRegions;
return dirtyRegion;
}
@@ -904,7 +1027,7 @@
mHwWorkListDirty = false;
HWComposer& hwc(hw.getHwComposer());
if (hwc.initCheck() == NO_ERROR) {
- const Vector< sp<LayerBase> >& currentLayers(mVisibleLayersSortedByZ);
+ const Vector< sp<LayerBase> >& currentLayers(hw.getVisibleLayersSortedByZ());
const size_t count = currentLayers.size();
hwc.createWorkList(count);
@@ -971,7 +1094,7 @@
return;
}
- const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
+ const Vector< sp<LayerBase> >& layers(hw.getVisibleLayersSortedByZ());
size_t count = layers.size();
ALOGE_IF(hwc.getNumLayers() != count,
@@ -1025,25 +1148,29 @@
* and then, render the layers targeted at the framebuffer
*/
- const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
+ const Vector< sp<LayerBase> >& layers(hw.getVisibleLayersSortedByZ());
const size_t count = layers.size();
const Transform& tr = hw.getTransform();
- for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
+ for (size_t i=0 ; i<count ; ++i) {
const sp<LayerBase>& layer(layers[i]);
const Region clip(dirty.intersect(tr.transform(layer->visibleRegion)));
if (!clip.isEmpty()) {
- if (cur->getCompositionType() == HWC_OVERLAY) {
+ if (cur != end && cur->getCompositionType() == HWC_OVERLAY) {
if (i && (cur->getHints() & HWC_HINT_CLEAR_FB)
&& layer->isOpaque()) {
// never clear the very first layer since we're
// guaranteed the FB is already cleared
layer->clearWithOpenGL(hw, clip);
}
+ ++cur;
continue;
}
// render the layer
layer->draw(hw, clip);
}
+ if (cur != end) {
+ ++cur;
+ }
}
}
}
@@ -1741,7 +1868,7 @@
hwc.initCheck()==NO_ERROR ? "present" : "not present",
(mDebugDisableHWC || mDebugRegion) ? "disabled" : "enabled");
result.append(buffer);
- hwc.dump(result, buffer, SIZE, mVisibleLayersSortedByZ);
+ hwc.dump(result, buffer, SIZE, hw.getVisibleLayersSortedByZ());
/*
* Dump gralloc state
@@ -1931,7 +2058,7 @@
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
- const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
+ const Vector< sp<LayerBase> >& layers(hw.getVisibleLayersSortedByZ());
const size_t count = layers.size();
for (size_t i=0 ; i<count ; ++i) {
const sp<LayerBase>& layer(layers[i]);
@@ -2428,19 +2555,27 @@
status_t result = PERMISSION_DENIED;
// only one display supported for now
- if (CC_UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT))
+ if (CC_UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT)) {
return BAD_VALUE;
+ }
- if (!GLExtensions::getInstance().haveFramebufferObject())
+ if (!GLExtensions::getInstance().haveFramebufferObject()) {
return INVALID_OPERATION;
+ }
// get screen geometry
const DisplayHardware& hw(getDisplayHardware(dpy));
const uint32_t hw_w = hw.getWidth();
const uint32_t hw_h = hw.getHeight();
- if ((sw > hw_w) || (sh > hw_h))
+ // if we have secure windows on this display, never allow the screen capture
+ if (hw.getSecureLayerVisible()) {
+ return PERMISSION_DENIED;
+ }
+
+ if ((sw > hw_w) || (sh > hw_h)) {
return BAD_VALUE;
+ }
sw = (!sw) ? hw_w : sw;
sh = (!sh) ? hw_h : sh;
@@ -2579,14 +2714,8 @@
}
virtual bool handler() {
Mutex::Autolock _l(flinger->mStateLock);
-
- // if we have secure windows, never allow the screen capture
- if (flinger->mSecureFrameBuffer)
- return true;
-
result = flinger->captureScreenImplLocked(dpy,
heap, w, h, f, sw, sh, minLayerZ, maxLayerZ);
-
return true;
}
};
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 91cc6a5..4af31fb 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -148,6 +148,8 @@
GLuint getProtectedTexName() const { return mProtectedTexName; }
+ surface_flinger_cblk_t* getControlBlock() const;
+
class MessageDestroyGLTexture : public MessageBase {
GLuint texture;
@@ -294,6 +296,18 @@
void debugFlashRegions(const DisplayHardware& hw);
void drawWormhole() const;
+ uint32_t getMaxTextureSize() const;
+ uint32_t getMaxViewportDims() const;
+
+ static status_t selectConfigForPixelFormat(
+ EGLDisplay dpy,
+ EGLint const* attrs,
+ PixelFormat format,
+ EGLConfig* outConfig);
+ static EGLConfig selectEGLConfig(EGLDisplay disp, EGLint visualId);
+ static EGLContext createGLContext(EGLDisplay disp, EGLConfig config);
+ void initializeGL(EGLDisplay display, EGLSurface surface);
+
void startBootAnim();
void listLayersLocked(const Vector<String16>& args, size_t& index,
@@ -331,6 +345,11 @@
GLuint mProtectedTexName;
nsecs_t mBootTime;
sp<EventThread> mEventThread;
+ GLint mMaxViewportDims[2];
+ GLint mMaxTextureSize;
+ EGLContext mEGLContext;
+ EGLConfig mEGLConfig;
+
// Can only accessed from the main thread, these members
// don't need synchronization
@@ -342,7 +361,6 @@
bool mVisibleRegionsDirty;
bool mHwWorkListDirty;
int32_t mElectronBeamAnimationMode;
- Vector< sp<LayerBase> > mVisibleLayersSortedByZ;
// don't use a lock for these, we don't care
@@ -364,9 +382,6 @@
mutable Mutex mDestroyedLayerLock;
Vector<LayerBase const *> mDestroyedLayers;
- // only written in the main thread, only read in other threads
- volatile int32_t mSecureFrameBuffer;
-
EGLSurface getExternalDisplaySurface() const;
sp<SurfaceTextureClient> mExternalDisplayNativeWindow;