DisplayDevice.cpp revision b8a5560e1303cb10f5cd482af466fc04d2bdfcab
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/FramebufferNativeWindow.h> 29 30#include <GLES/gl.h> 31#include <EGL/egl.h> 32#include <EGL/eglext.h> 33 34#include <pixelflinger/pixelflinger.h> 35 36#include "DisplayHardware/DisplayHardware.h" 37 38#include <hardware/copybit.h> 39#include <hardware/overlay.h> 40#include <hardware/gralloc.h> 41 42using namespace android; 43 44static __attribute__((noinline)) 45const char *egl_strerror(EGLint err) 46{ 47 switch (err){ 48 case EGL_SUCCESS: return "EGL_SUCCESS"; 49 case EGL_NOT_INITIALIZED: return "EGL_NOT_INITIALIZED"; 50 case EGL_BAD_ACCESS: return "EGL_BAD_ACCESS"; 51 case EGL_BAD_ALLOC: return "EGL_BAD_ALLOC"; 52 case EGL_BAD_ATTRIBUTE: return "EGL_BAD_ATTRIBUTE"; 53 case EGL_BAD_CONFIG: return "EGL_BAD_CONFIG"; 54 case EGL_BAD_CONTEXT: return "EGL_BAD_CONTEXT"; 55 case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE"; 56 case EGL_BAD_DISPLAY: return "EGL_BAD_DISPLAY"; 57 case EGL_BAD_MATCH: return "EGL_BAD_MATCH"; 58 case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP"; 59 case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW"; 60 case EGL_BAD_PARAMETER: return "EGL_BAD_PARAMETER"; 61 case EGL_BAD_SURFACE: return "EGL_BAD_SURFACE"; 62 case EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST"; 63 default: return "UNKNOWN"; 64 } 65} 66 67static __attribute__((noinline)) 68void checkGLErrors() 69{ 70 GLenum error = glGetError(); 71 if (error != GL_NO_ERROR) 72 LOGE("GL error 0x%04x", int(error)); 73} 74 75static __attribute__((noinline)) 76void checkEGLErrors(const char* token) 77{ 78 EGLint error = eglGetError(); 79 // GLESonGL seems to be returning 0 when there is no errors? 80 if (error && error != EGL_SUCCESS) 81 LOGE("%s error 0x%04x (%s)", 82 token, int(error), egl_strerror(error)); 83} 84 85 86/* 87 * Initialize the display to the specified values. 88 * 89 */ 90 91DisplayHardware::DisplayHardware( 92 const sp<SurfaceFlinger>& flinger, 93 uint32_t dpy) 94 : DisplayHardwareBase(flinger, dpy) 95{ 96 init(dpy); 97} 98 99DisplayHardware::~DisplayHardware() 100{ 101 fini(); 102} 103 104float DisplayHardware::getDpiX() const { return mDpiX; } 105float DisplayHardware::getDpiY() const { return mDpiY; } 106float DisplayHardware::getDensity() const { return mDensity; } 107float DisplayHardware::getRefreshRate() const { return mRefreshRate; } 108int DisplayHardware::getWidth() const { return mWidth; } 109int DisplayHardware::getHeight() const { return mHeight; } 110PixelFormat DisplayHardware::getFormat() const { return mFormat; } 111 112void DisplayHardware::init(uint32_t dpy) 113{ 114 hw_module_t const* module; 115 116 mNativeWindow = new FramebufferNativeWindow(); 117 118 mOverlayEngine = NULL; 119 if (hw_get_module(OVERLAY_HARDWARE_MODULE_ID, &module) == 0) { 120 overlay_control_open(module, &mOverlayEngine); 121 } 122 123 framebuffer_device_t const * fbDev = mNativeWindow->getDevice(); 124 125 PixelFormatInfo fbFormatInfo; 126 getPixelFormatInfo(PixelFormat(fbDev->format), &fbFormatInfo); 127 128 // initialize EGL 129 const EGLint attribs[] = { 130 EGL_BUFFER_SIZE, fbFormatInfo.bitsPerPixel, 131 EGL_DEPTH_SIZE, 0, 132 EGL_NONE 133 }; 134 EGLint w, h, dummy; 135 EGLint numConfigs=0, n=0; 136 EGLSurface surface; 137 EGLContext context; 138 mFlags = 0; 139 140 // TODO: all the extensions below should be queried through 141 // eglGetProcAddress(). 142 143 EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); 144 eglInitialize(display, NULL, NULL); 145 eglGetConfigs(display, NULL, 0, &numConfigs); 146 147 // Get all the "potential match" configs... 148 EGLConfig* const configs = new EGLConfig[numConfigs]; 149 eglChooseConfig(display, attribs, configs, numConfigs, &n); 150 LOGE_IF(n<=0, "no EGLConfig available!"); 151 EGLConfig config = configs[0]; 152 if (n > 1) { 153 // if there is more than one candidate, go through the list 154 // and pick one that matches our framebuffer format 155 int fbSzA = fbFormatInfo.getSize(PixelFormatInfo::INDEX_ALPHA); 156 int fbSzR = fbFormatInfo.getSize(PixelFormatInfo::INDEX_RED); 157 int fbSzG = fbFormatInfo.getSize(PixelFormatInfo::INDEX_GREEN); 158 int fbSzB = fbFormatInfo.getSize(PixelFormatInfo::INDEX_BLUE); 159 for (int i=0 ; i<n ; i++) { 160 EGLint r,g,b,a; 161 eglGetConfigAttrib(display, configs[i], EGL_RED_SIZE, &r); 162 eglGetConfigAttrib(display, configs[i], EGL_GREEN_SIZE, &g); 163 eglGetConfigAttrib(display, configs[i], EGL_BLUE_SIZE, &b); 164 eglGetConfigAttrib(display, configs[i], EGL_ALPHA_SIZE, &a); 165 if (fbSzA == a && fbSzR == r && fbSzG == g && fbSzB == b) { 166 config = configs[i]; 167 break; 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 188 if (mNativeWindow->isUpdateOnDemand()) { 189 mFlags |= UPDATE_ON_DEMAND; 190 } 191 192 if (eglGetConfigAttrib(display, config, EGL_CONFIG_CAVEAT, &dummy) == EGL_TRUE) { 193 if (dummy == EGL_SLOW_CONFIG) 194 mFlags |= SLOW_CONFIG; 195 } 196 197 /* 198 * Create our main surface 199 */ 200 201 surface = eglCreateWindowSurface(display, config, mNativeWindow.get(), NULL); 202 checkEGLErrors("eglCreateWindowSurface"); 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#ifdef EGL_ANDROID_swap_rectangle 211 if (strstr(egl_extensions, "EGL_ANDROID_swap_rectangle")) { 212 mFlags |= SWAP_RECTANGLE; 213 } 214#endif 215 216 mDpiX = mNativeWindow->xdpi; 217 mDpiX = mNativeWindow->ydpi; 218 mRefreshRate = fbDev->fps; 219 220 char property[PROPERTY_VALUE_MAX]; 221 /* Read density from build-specific ro.sf.lcd_density property 222 * except if it is overriden by qemu.sf.lcd_density. 223 */ 224 if (property_get("qemu.sf.lcd_density", property, NULL) <= 0) { 225 if (property_get("ro.sf.lcd_density", property, NULL) <= 0) { 226 LOGW("ro.sf.lcd_density not defined, using 160 dpi by default."); 227 strcpy(property, "160"); 228 } 229 } 230 mDensity = atoi(property) * (1.0f/160.0f); 231 232 233 /* 234 * Create our OpenGL ES context 235 */ 236 237 context = eglCreateContext(display, config, NULL, NULL); 238 //checkEGLErrors("eglCreateContext"); 239 240 eglQuerySurface(display, surface, EGL_WIDTH, &mWidth); 241 eglQuerySurface(display, surface, EGL_HEIGHT, &mHeight); 242 243 244 /* 245 * Gather OpenGL ES extensions 246 */ 247 248 eglMakeCurrent(display, surface, surface, context); 249 const char* const gl_extensions = (const char*)glGetString(GL_EXTENSIONS); 250 LOGI("OpenGL informations:"); 251 LOGI("vendor : %s", glGetString(GL_VENDOR)); 252 LOGI("renderer : %s", glGetString(GL_RENDERER)); 253 LOGI("version : %s", glGetString(GL_VERSION)); 254 LOGI("extensions: %s", gl_extensions); 255 256 if (strstr(gl_extensions, "GL_ARB_texture_non_power_of_two")) { 257 mFlags |= NPOT_EXTENSION; 258 } 259 if (strstr(gl_extensions, "GL_OES_draw_texture")) { 260 mFlags |= DRAW_TEXTURE_EXTENSION; 261 } 262 if (strstr( gl_extensions, "GL_OES_EGL_image") && 263 (strstr(egl_extensions, "EGL_KHR_image_base") || 264 strstr(egl_extensions, "EGL_KHR_image")) && 265 strstr(egl_extensions, "EGL_ANDROID_image_native_buffer")) { 266 mFlags |= DIRECT_TEXTURE; 267 } 268 269 // Unbind the context from this thread 270 eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 271 272 mDisplay = display; 273 mConfig = config; 274 mSurface = surface; 275 mContext = context; 276 mFormat = fbDev->format; 277 mPageFlipCount = 0; 278} 279 280/* 281 * Clean up. Throw out our local state. 282 * 283 * (It's entirely possible we'll never get here, since this is meant 284 * for real hardware, which doesn't restart.) 285 */ 286 287void DisplayHardware::fini() 288{ 289 eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 290 eglTerminate(mDisplay); 291 overlay_control_close(mOverlayEngine); 292} 293 294void DisplayHardware::releaseScreen() const 295{ 296 DisplayHardwareBase::releaseScreen(); 297} 298 299void DisplayHardware::acquireScreen() const 300{ 301 DisplayHardwareBase::acquireScreen(); 302} 303 304uint32_t DisplayHardware::getPageFlipCount() const { 305 return mPageFlipCount; 306} 307 308/* 309 * "Flip" the front and back buffers. 310 */ 311 312void DisplayHardware::flip(const Region& dirty) const 313{ 314 checkGLErrors(); 315 316 EGLDisplay dpy = mDisplay; 317 EGLSurface surface = mSurface; 318 319#ifdef EGL_ANDROID_swap_rectangle 320 if (mFlags & SWAP_RECTANGLE) { 321 const Region newDirty(dirty.intersect(bounds())); 322 const Rect b(newDirty.getBounds()); 323 eglSetSwapRectangleANDROID(dpy, surface, 324 b.left, b.top, b.width(), b.height()); 325 } 326#endif 327 328 if (mFlags & UPDATE_ON_DEMAND) { 329 mNativeWindow->setUpdateRectangle(dirty.bounds()); 330 } 331 332 mPageFlipCount++; 333 eglSwapBuffers(dpy, surface); 334 checkEGLErrors("eglSwapBuffers"); 335 336 // for debugging 337 //glClearColor(1,0,0,0); 338 //glClear(GL_COLOR_BUFFER_BIT); 339} 340 341uint32_t DisplayHardware::getFlags() const 342{ 343 return mFlags; 344} 345 346void DisplayHardware::makeCurrent() const 347{ 348 eglMakeCurrent(mDisplay, mSurface, mSurface, mContext); 349} 350