diff options
Diffstat (limited to 'libs/surfaceflinger/DisplayHardware')
3 files changed, 136 insertions, 148 deletions
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 @@ PixelFormat DisplayHardware::getFormat() const { return mFormat; } 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 @@ void DisplayHardware::init(uint32_t dpy) EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); eglInitialize(display, NULL, NULL); eglGetConfigs(display, NULL, 0, &numConfigs); - eglChooseConfig(display, attribs, &config, 1, &n); + + 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 @@ void DisplayHardware::init(uint32_t dpy) 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 @@ void DisplayHardware::init(uint32_t dpy) * 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; - } - 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; + + 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; + } } - 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); + + mDpiX = mNativeWindow->xdpi; + mDpiY = mNativeWindow->ydpi; + mRefreshRate = fbDev->fps; - char property[PROPERTY_VALUE_MAX]; /* 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 @@ void DisplayHardware::init(uint32_t dpy) */ 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 @@ void DisplayHardware::init(uint32_t dpy) 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 @@ void DisplayHardware::init(uint32_t dpy) mConfig = config; mSurface = surface; mContext = context; - mFormat = GGL_PIXEL_FORMAT_RGB_565; - - hw_module_t const* module; - - mBlitEngine = NULL; - if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) { - copybit_open(module, &mBlitEngine); - } - - mOverlayEngine = NULL; - if (hw_get_module(OVERLAY_HARDWARE_MODULE_ID, &module) == 0) { - overlay_control_open(module, &mOverlayEngine); - } + mFormat = fbDev->format; + mPageFlipCount = 0; } /* @@ -270,7 +289,6 @@ void DisplayHardware::fini() { eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglTerminate(mDisplay); - copybit_close(mBlitEngine); overlay_control_close(mOverlayEngine); } @@ -284,33 +302,13 @@ void DisplayHardware::acquireScreen() const DisplayHardwareBase::acquireScreen(); } -void DisplayHardware::getDisplaySurface(copybit_image_t* img) const -{ - img->w = mDisplaySurface->stride; - img->h = mDisplaySurface->height; - img->format = mDisplaySurface->format; - img->offset = mDisplaySurface->offset; - img->base = (void*)mDisplaySurface->base; - img->fd = mDisplaySurface->fd; -} - -void DisplayHardware::getDisplaySurface(GGLSurface* fb) const -{ - fb->version= sizeof(GGLSurface); - fb->width = mDisplaySurface->width; - fb->height = mDisplaySurface->height; - fb->stride = mDisplaySurface->stride; - fb->format = mDisplaySurface->format; - fb->data = (GGLubyte*)mDisplaySurface->base + mDisplaySurface->offset; -} - uint32_t DisplayHardware::getPageFlipCount() const { - return mDisplaySurface->getPageFlipCount(); + return mPageFlipCount; } -/* - * "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 @@ void DisplayHardware::flip(const Region& dirty) const EGLDisplay dpy = mDisplay; EGLSurface surface = mSurface; - Region newDirty(dirty); - newDirty.andSelf(Rect(mWidth, mHeight)); - - if (mFlags & BUFFER_PRESERVED) { - const Region copyback(mDirty.subtract(newDirty)); - mDirty = newDirty; - mDisplaySurface->copyFrontToBack(copyback); - } - - if (mFlags & SWAP_RECTANGLE_EXTENSION) { - 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 @@ void DisplayHardware::makeCurrent() const { eglMakeCurrent(mDisplay, mSurface, mSurface, mContext); } - -void DisplayHardware::copyFrontToImage(const copybit_image_t& front) const { - mDisplaySurface->copyFrontToImage(front); -} - -void DisplayHardware::copyBackToImage(const copybit_image_t& front) const { - mDisplaySurface->copyBackToImage(front); -} diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h index 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 @@ public: void makeCurrent() const; uint32_t getPageFlipCount() const; - void getDisplaySurface(copybit_image_t* img) const; - void getDisplaySurface(GGLSurface* fb) const; EGLDisplay getEGLDisplay() const { return mDisplay; } - copybit_device_t* getBlitEngine() const { return mBlitEngine; } overlay_control_device_t* getOverlayEngine() const { return mOverlayEngine; } - void copyFrontToImage(const copybit_image_t& front) const; - void copyBackToImage(const copybit_image_t& front) const; - + status_t compositionComplete() const; + Rect bounds() const { return Rect(mWidth, mHeight); } @@ -102,9 +103,9 @@ private: int mHeight; PixelFormat mFormat; uint32_t mFlags; - mutable Region mDirty; - sp<EGLDisplaySurface> mDisplaySurface; - copybit_device_t* mBlitEngine; + mutable uint32_t mPageFlipCount; + + sp<FramebufferNativeWindow> mNativeWindow; overlay_control_device_t* mOverlayEngine; }; diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp index f75e5c2..1d09f84 100644 --- a/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp +++ b/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp @@ -14,8 +14,6 @@ * limitations under the License. */ -#define LOG_TAG "SurfaceFlinger" - #include <assert.h> #include <errno.h> #include <stdlib.h> |