DisplayDevice.cpp revision 076b1cc3a9b90aa5b381a1ed268ca0b548444c9b
1/* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <stdlib.h> 18#include <stdio.h> 19#include <string.h> 20#include <math.h> 21 22#include <cutils/properties.h> 23 24#include <utils/RefBase.h> 25#include <utils/Log.h> 26 27#include <ui/PixelFormat.h> 28#include <ui/EGLNativeWindowSurface.h> 29 30#include <GLES/gl.h> 31#include <EGL/egl.h> 32#include <EGL/eglext.h> 33#include <EGL/android_natives.h> 34 35#include <pixelflinger/pixelflinger.h> 36 37#include "DisplayHardware/DisplayHardware.h" 38 39#include <hardware/copybit.h> 40#include <hardware/overlay.h> 41#include <hardware/gralloc.h> 42 43using namespace android; 44 45static __attribute__((noinline)) 46const char *egl_strerror(EGLint err) 47{ 48 switch (err){ 49 case EGL_SUCCESS: return "EGL_SUCCESS"; 50 case EGL_NOT_INITIALIZED: return "EGL_NOT_INITIALIZED"; 51 case EGL_BAD_ACCESS: return "EGL_BAD_ACCESS"; 52 case EGL_BAD_ALLOC: return "EGL_BAD_ALLOC"; 53 case EGL_BAD_ATTRIBUTE: return "EGL_BAD_ATTRIBUTE"; 54 case EGL_BAD_CONFIG: return "EGL_BAD_CONFIG"; 55 case EGL_BAD_CONTEXT: return "EGL_BAD_CONTEXT"; 56 case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE"; 57 case EGL_BAD_DISPLAY: return "EGL_BAD_DISPLAY"; 58 case EGL_BAD_MATCH: return "EGL_BAD_MATCH"; 59 case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP"; 60 case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW"; 61 case EGL_BAD_PARAMETER: return "EGL_BAD_PARAMETER"; 62 case EGL_BAD_SURFACE: return "EGL_BAD_SURFACE"; 63 case EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST"; 64 default: return "UNKNOWN"; 65 } 66} 67 68static __attribute__((noinline)) 69void checkGLErrors() 70{ 71 GLenum error = glGetError(); 72 if (error != GL_NO_ERROR) 73 LOGE("GL error 0x%04x", int(error)); 74} 75 76static __attribute__((noinline)) 77void checkEGLErrors(const char* token) 78{ 79 EGLint error = eglGetError(); 80 // GLESonGL seems to be returning 0 when there is no errors? 81 if (error && error != EGL_SUCCESS) 82 LOGE("%s error 0x%04x (%s)", 83 token, int(error), egl_strerror(error)); 84} 85 86 87/* 88 * Initialize the display to the specified values. 89 * 90 */ 91 92DisplayHardware::DisplayHardware( 93 const sp<SurfaceFlinger>& flinger, 94 uint32_t dpy) 95 : DisplayHardwareBase(flinger, dpy) 96{ 97 init(dpy); 98} 99 100DisplayHardware::~DisplayHardware() 101{ 102 fini(); 103} 104 105float DisplayHardware::getDpiX() const { return mDpiX; } 106float DisplayHardware::getDpiY() const { return mDpiY; } 107float DisplayHardware::getDensity() const { return mDensity; } 108float DisplayHardware::getRefreshRate() const { return mRefreshRate; } 109int DisplayHardware::getWidth() const { return mWidth; } 110int DisplayHardware::getHeight() const { return mHeight; } 111PixelFormat DisplayHardware::getFormat() const { return mFormat; } 112 113void DisplayHardware::init(uint32_t dpy) 114{ 115 hw_module_t const* module; 116 117 mNativeWindow = new FramebufferNativeWindow(); 118 119 mOverlayEngine = NULL; 120 if (hw_get_module(OVERLAY_HARDWARE_MODULE_ID, &module) == 0) { 121 overlay_control_open(module, &mOverlayEngine); 122 } 123 124 framebuffer_device_t const * fbDev = mNativeWindow->getDevice(); 125 126 PixelFormatInfo fbFormatInfo; 127 getPixelFormatInfo(PixelFormat(fbDev->format), &fbFormatInfo); 128 129 // initialize EGL 130 const EGLint attribs[] = { 131 EGL_BUFFER_SIZE, fbFormatInfo.bitsPerPixel, 132 EGL_DEPTH_SIZE, 0, 133 EGL_NONE 134 }; 135 EGLint w, h, dummy; 136 EGLint numConfigs=0, n=0; 137 EGLSurface surface; 138 EGLContext context; 139 mFlags = 0; 140 141 // TODO: all the extensions below should be queried through 142 // eglGetProcAddress(). 143 144 EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); 145 eglInitialize(display, NULL, NULL); 146 eglGetConfigs(display, NULL, 0, &numConfigs); 147 148 // Get all the "potential match" configs... 149 EGLConfig* const configs = new EGLConfig[numConfigs]; 150 eglChooseConfig(display, attribs, configs, numConfigs, &n); 151 LOGE_IF(n<=0, "no EGLConfig available!"); 152 EGLConfig config = configs[0]; 153 if (n > 1) { 154 // if there is more than one candidate, go through the list 155 // and pick one that matches our framebuffer format 156 int fbSzA = fbFormatInfo.getSize(PixelFormatInfo::INDEX_ALPHA); 157 int fbSzR = fbFormatInfo.getSize(PixelFormatInfo::INDEX_RED); 158 int fbSzG = fbFormatInfo.getSize(PixelFormatInfo::INDEX_GREEN); 159 int fbSzB = fbFormatInfo.getSize(PixelFormatInfo::INDEX_BLUE); 160 for (int i=0 ; i<n ; i++) { 161 EGLint r,g,b,a; 162 eglGetConfigAttrib(display, configs[i], EGL_RED_SIZE, &r); 163 eglGetConfigAttrib(display, configs[i], EGL_GREEN_SIZE, &g); 164 eglGetConfigAttrib(display, configs[i], EGL_BLUE_SIZE, &b); 165 eglGetConfigAttrib(display, configs[i], EGL_ALPHA_SIZE, &a); 166 if (fbSzA == a && fbSzR == r && fbSzG == g && fbSzB == b) { 167 config = configs[i]; 168 } 169 } 170 } 171 delete [] configs; 172 173 /* 174 * Gather EGL extensions 175 */ 176 177 const char* const egl_extensions = eglQueryString( 178 display, EGL_EXTENSIONS); 179 180 LOGI("EGL informations:"); 181 LOGI("# of configs : %d", numConfigs); 182 LOGI("vendor : %s", eglQueryString(display, EGL_VENDOR)); 183 LOGI("version : %s", eglQueryString(display, EGL_VERSION)); 184 LOGI("extensions: %s", egl_extensions); 185 LOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported"); 186 187 // TODO: get the real "update_on_demand" behavior (probably should be HAL module) 188 // FIXME: mFlags |= UPDATE_ON_DEMAND; 189 190 if (eglGetConfigAttrib(display, config, EGL_CONFIG_CAVEAT, &dummy) == EGL_TRUE) { 191 if (dummy == EGL_SLOW_CONFIG) 192 mFlags |= SLOW_CONFIG; 193 } 194 195 /* 196 * Create our main surface 197 */ 198 199 200 surface = eglCreateWindowSurface(display, config, mNativeWindow.get(), NULL); 201 checkEGLErrors("eglCreateDisplaySurfaceANDROID"); 202 203 204 if (eglQuerySurface(display, surface, EGL_SWAP_BEHAVIOR, &dummy) == EGL_TRUE) { 205 if (dummy == EGL_BUFFER_PRESERVED) { 206 mFlags |= BUFFER_PRESERVED; 207 } 208 } 209 210 mDpiX = mNativeWindow->xdpi; 211 mDpiX = mNativeWindow->ydpi; 212 mRefreshRate = mNativeWindow->getDevice()->fps; 213 214 char property[PROPERTY_VALUE_MAX]; 215 if (property_get("ro.sf.lcd_density", property, NULL) <= 0) { 216 LOGW("ro.sf.lcd_density not defined, using 160 dpi by default."); 217 strcpy(property, "160"); 218 } 219 mDensity = atoi(property) * (1.0f/160.0f); 220 221 222 /* 223 * Create our OpenGL ES context 224 */ 225 226 context = eglCreateContext(display, config, NULL, NULL); 227 //checkEGLErrors("eglCreateContext"); 228 229 eglQuerySurface(display, surface, EGL_WIDTH, &mWidth); 230 eglQuerySurface(display, surface, EGL_HEIGHT, &mHeight); 231 232 233 /* 234 * Gather OpenGL ES extensions 235 */ 236 237 eglMakeCurrent(display, surface, surface, context); 238 const char* const gl_extensions = (const char*)glGetString(GL_EXTENSIONS); 239 LOGI("OpenGL informations:"); 240 LOGI("vendor : %s", glGetString(GL_VENDOR)); 241 LOGI("renderer : %s", glGetString(GL_RENDERER)); 242 LOGI("version : %s", glGetString(GL_VERSION)); 243 LOGI("extensions: %s", gl_extensions); 244 245 if (strstr(gl_extensions, "GL_ARB_texture_non_power_of_two")) { 246 mFlags |= NPOT_EXTENSION; 247 } 248 if (strstr(gl_extensions, "GL_OES_draw_texture")) { 249 mFlags |= DRAW_TEXTURE_EXTENSION; 250 } 251 if (strstr( gl_extensions, "GL_OES_EGL_image") && 252 (strstr(egl_extensions, "KHR_image_base") || 253 strstr(egl_extensions, "EGL_KHR_image")) && 254 strstr(egl_extensions, "EGL_ANDROID_image_native_buffer")) { 255 mFlags |= DIRECT_TEXTURE; 256 } 257 258 // Unbind the context from this thread 259 eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 260 261 mDisplay = display; 262 mConfig = config; 263 mSurface = surface; 264 mContext = context; 265 mFormat = fbDev->format; 266 mPageFlipCount = 0; 267} 268 269/* 270 * Clean up. Throw out our local state. 271 * 272 * (It's entirely possible we'll never get here, since this is meant 273 * for real hardware, which doesn't restart.) 274 */ 275 276void DisplayHardware::fini() 277{ 278 eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 279 eglTerminate(mDisplay); 280 overlay_control_close(mOverlayEngine); 281} 282 283void DisplayHardware::releaseScreen() const 284{ 285 DisplayHardwareBase::releaseScreen(); 286} 287 288void DisplayHardware::acquireScreen() const 289{ 290 DisplayHardwareBase::acquireScreen(); 291} 292 293uint32_t DisplayHardware::getPageFlipCount() const { 294 return mPageFlipCount; 295} 296 297/* 298 * "Flip" the front and back buffers. 299 */ 300 301void DisplayHardware::flip(const Region& dirty) const 302{ 303 checkGLErrors(); 304 305 EGLDisplay dpy = mDisplay; 306 EGLSurface surface = mSurface; 307 308 Region newDirty(dirty); 309 newDirty.andSelf(Rect(mWidth, mHeight)); 310 311 if (mFlags & BUFFER_PRESERVED) { 312 mDirty = newDirty; 313 } 314 315 const Rect& b(newDirty.bounds()); 316 mNativeWindow->android_native_window_t::setSwapRectangle( 317 mNativeWindow.get(), b.left, b.top, b.width(), b.height()); 318 319 mPageFlipCount++; 320 eglSwapBuffers(dpy, surface); 321 checkEGLErrors("eglSwapBuffers"); 322 323 // for debugging 324 //glClearColor(1,0,0,0); 325 //glClear(GL_COLOR_BUFFER_BIT); 326} 327 328uint32_t DisplayHardware::getFlags() const 329{ 330 return mFlags; 331} 332 333void DisplayHardware::makeCurrent() const 334{ 335 eglMakeCurrent(mDisplay, mSurface, mSurface, mContext); 336} 337 338void DisplayHardware::copyFrontToImage(const copybit_image_t& front) const { 339 // FIXME: we need to get rid of this 340} 341 342void DisplayHardware::copyBackToImage(const copybit_image_t& front) const { 343 // FIXME: we need to get rid of this 344} 345