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 #include <ui/EGLUtils.h> 30 31 #include <GLES/gl.h> 32 #include <EGL/egl.h> 33 #include <EGL/eglext.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 43 #include "GLExtensions.h" 44 45 using namespace android; 46 47 48 static __attribute__((noinline)) 49 void checkGLErrors() 50 { 51 do { 52 // there could be more than one error flag 53 GLenum error = glGetError(); 54 if (error == GL_NO_ERROR) 55 break; 56 LOGE("GL error 0x%04x", int(error)); 57 } while(true); 58 } 59 60 static __attribute__((noinline)) 61 void checkEGLErrors(const char* token) 62 { 63 EGLint error = eglGetError(); 64 if (error && error != EGL_SUCCESS) { 65 LOGE("%s: EGL error 0x%04x (%s)", 66 token, int(error), EGLUtils::strerror(error)); 67 } 68 } 69 70 /* 71 * Initialize the display to the specified values. 72 * 73 */ 74 75 DisplayHardware::DisplayHardware( 76 const sp<SurfaceFlinger>& flinger, 77 uint32_t dpy) 78 : DisplayHardwareBase(flinger, dpy), 79 mFlags(0) 80 { 81 init(dpy); 82 } 83 84 DisplayHardware::~DisplayHardware() 85 { 86 fini(); 87 } 88 89 float DisplayHardware::getDpiX() const { return mDpiX; } 90 float DisplayHardware::getDpiY() const { return mDpiY; } 91 float DisplayHardware::getDensity() const { return mDensity; } 92 float DisplayHardware::getRefreshRate() const { return mRefreshRate; } 93 int DisplayHardware::getWidth() const { return mWidth; } 94 int DisplayHardware::getHeight() const { return mHeight; } 95 PixelFormat DisplayHardware::getFormat() const { return mFormat; } 96 uint32_t DisplayHardware::getMaxTextureSize() const { return mMaxTextureSize; } 97 uint32_t DisplayHardware::getMaxViewportDims() const { return mMaxViewportDims; } 98 99 void DisplayHardware::init(uint32_t dpy) 100 { 101 mNativeWindow = new FramebufferNativeWindow(); 102 framebuffer_device_t const * fbDev = mNativeWindow->getDevice(); 103 mDpiX = mNativeWindow->xdpi; 104 mDpiY = mNativeWindow->ydpi; 105 mRefreshRate = fbDev->fps; 106 107 mOverlayEngine = NULL; 108 hw_module_t const* module; 109 if (hw_get_module(OVERLAY_HARDWARE_MODULE_ID, &module) == 0) { 110 overlay_control_open(module, &mOverlayEngine); 111 } 112 113 EGLint w, h, dummy; 114 EGLint numConfigs=0; 115 EGLSurface surface; 116 EGLContext context; 117 118 // initialize EGL 119 EGLint attribs[] = { 120 EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 121 EGL_NONE, 0, 122 EGL_NONE 123 }; 124 125 // debug: disable h/w rendering 126 char property[PROPERTY_VALUE_MAX]; 127 if (property_get("debug.sf.hw", property, NULL) > 0) { 128 if (atoi(property) == 0) { 129 LOGW("H/W composition disabled"); 130 attribs[2] = EGL_CONFIG_CAVEAT; 131 attribs[3] = EGL_SLOW_CONFIG; 132 } 133 } 134 135 // TODO: all the extensions below should be queried through 136 // eglGetProcAddress(). 137 138 EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); 139 eglInitialize(display, NULL, NULL); 140 eglGetConfigs(display, NULL, 0, &numConfigs); 141 142 EGLConfig config; 143 status_t err = EGLUtils::selectConfigForNativeWindow( 144 display, attribs, mNativeWindow.get(), &config); 145 LOGE_IF(err, "couldn't find an EGLConfig matching the screen format"); 146 147 EGLint r,g,b,a; 148 eglGetConfigAttrib(display, config, EGL_RED_SIZE, &r); 149 eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &g); 150 eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &b); 151 eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &a); 152 153 if (mNativeWindow->isUpdateOnDemand()) { 154 mFlags |= PARTIAL_UPDATES; 155 } 156 157 if (eglGetConfigAttrib(display, config, EGL_CONFIG_CAVEAT, &dummy) == EGL_TRUE) { 158 if (dummy == EGL_SLOW_CONFIG) 159 mFlags |= SLOW_CONFIG; 160 } 161 162 /* 163 * Create our main surface 164 */ 165 166 surface = eglCreateWindowSurface(display, config, mNativeWindow.get(), NULL); 167 eglQuerySurface(display, surface, EGL_WIDTH, &mWidth); 168 eglQuerySurface(display, surface, EGL_HEIGHT, &mHeight); 169 170 if (mFlags & PARTIAL_UPDATES) { 171 // if we have partial updates, we definitely don't need to 172 // preserve the backbuffer, which may be costly. 173 eglSurfaceAttrib(display, surface, 174 EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED); 175 } 176 177 if (eglQuerySurface(display, surface, EGL_SWAP_BEHAVIOR, &dummy) == EGL_TRUE) { 178 if (dummy == EGL_BUFFER_PRESERVED) { 179 mFlags |= BUFFER_PRESERVED; 180 } 181 } 182 183 /* Read density from build-specific ro.sf.lcd_density property 184 * except if it is overridden by qemu.sf.lcd_density. 185 */ 186 if (property_get("qemu.sf.lcd_density", property, NULL) <= 0) { 187 if (property_get("ro.sf.lcd_density", property, NULL) <= 0) { 188 LOGW("ro.sf.lcd_density not defined, using 160 dpi by default."); 189 strcpy(property, "160"); 190 } 191 } else { 192 /* for the emulator case, reset the dpi values too */ 193 mDpiX = mDpiY = atoi(property); 194 } 195 mDensity = atoi(property) * (1.0f/160.0f); 196 197 198 /* 199 * Create our OpenGL ES context 200 */ 201 202 203 EGLint contextAttributes[] = { 204 #ifdef EGL_IMG_context_priority 205 #ifdef HAS_CONTEXT_PRIORITY 206 #warning "using EGL_IMG_context_priority" 207 EGL_CONTEXT_PRIORITY_LEVEL_IMG, EGL_CONTEXT_PRIORITY_HIGH_IMG, 208 #endif 209 #endif 210 EGL_NONE, EGL_NONE 211 }; 212 context = eglCreateContext(display, config, NULL, contextAttributes); 213 214 mDisplay = display; 215 mConfig = config; 216 mSurface = surface; 217 mContext = context; 218 mFormat = fbDev->format; 219 mPageFlipCount = 0; 220 221 /* 222 * Gather OpenGL ES extensions 223 */ 224 225 eglMakeCurrent(display, surface, surface, context); 226 227 GLExtensions& extensions(GLExtensions::getInstance()); 228 extensions.initWithGLStrings( 229 glGetString(GL_VENDOR), 230 glGetString(GL_RENDERER), 231 glGetString(GL_VERSION), 232 glGetString(GL_EXTENSIONS), 233 eglQueryString(display, EGL_VENDOR), 234 eglQueryString(display, EGL_VERSION), 235 eglQueryString(display, EGL_EXTENSIONS)); 236 237 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize); 238 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, &mMaxViewportDims); 239 240 241 #ifdef EGL_ANDROID_swap_rectangle 242 if (extensions.hasExtension("EGL_ANDROID_swap_rectangle")) { 243 if (eglSetSwapRectangleANDROID(display, surface, 244 0, 0, mWidth, mHeight) == EGL_TRUE) { 245 // This could fail if this extension is not supported by this 246 // specific surface (of config) 247 mFlags |= SWAP_RECTANGLE; 248 } 249 } 250 // when we have the choice between PARTIAL_UPDATES and SWAP_RECTANGLE 251 // choose PARTIAL_UPDATES, which should be more efficient 252 if (mFlags & PARTIAL_UPDATES) 253 mFlags &= ~SWAP_RECTANGLE; 254 #endif 255 256 LOGI("EGL informations:"); 257 LOGI("# of configs : %d", numConfigs); 258 LOGI("vendor : %s", extensions.getEglVendor()); 259 LOGI("version : %s", extensions.getEglVersion()); 260 LOGI("extensions: %s", extensions.getEglExtension()); 261 LOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported"); 262 LOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config); 263 264 LOGI("OpenGL informations:"); 265 LOGI("vendor : %s", extensions.getVendor()); 266 LOGI("renderer : %s", extensions.getRenderer()); 267 LOGI("version : %s", extensions.getVersion()); 268 LOGI("extensions: %s", extensions.getExtension()); 269 LOGI("GL_MAX_TEXTURE_SIZE = %d", mMaxTextureSize); 270 LOGI("GL_MAX_VIEWPORT_DIMS = %d", mMaxViewportDims); 271 LOGI("flags = %08x", mFlags); 272 273 // Unbind the context from this thread 274 eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 275 } 276 277 /* 278 * Clean up. Throw out our local state. 279 * 280 * (It's entirely possible we'll never get here, since this is meant 281 * for real hardware, which doesn't restart.) 282 */ 283 284 void DisplayHardware::fini() 285 { 286 eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 287 eglTerminate(mDisplay); 288 overlay_control_close(mOverlayEngine); 289 } 290 291 void DisplayHardware::releaseScreen() const 292 { 293 DisplayHardwareBase::releaseScreen(); 294 } 295 296 void DisplayHardware::acquireScreen() const 297 { 298 DisplayHardwareBase::acquireScreen(); 299 } 300 301 uint32_t DisplayHardware::getPageFlipCount() const { 302 return mPageFlipCount; 303 } 304 305 status_t DisplayHardware::compositionComplete() const { 306 return mNativeWindow->compositionComplete(); 307 } 308 309 int DisplayHardware::getCurrentBufferIndex() const { 310 return mNativeWindow->getCurrentBufferIndex(); 311 } 312 313 void DisplayHardware::flip(const Region& dirty) const 314 { 315 checkGLErrors(); 316 317 EGLDisplay dpy = mDisplay; 318 EGLSurface surface = mSurface; 319 320 #ifdef EGL_ANDROID_swap_rectangle 321 if (mFlags & SWAP_RECTANGLE) { 322 const Region newDirty(dirty.intersect(bounds())); 323 const Rect b(newDirty.getBounds()); 324 eglSetSwapRectangleANDROID(dpy, surface, 325 b.left, b.top, b.width(), b.height()); 326 } 327 #endif 328 329 if (mFlags & PARTIAL_UPDATES) { 330 mNativeWindow->setUpdateRectangle(dirty.getBounds()); 331 } 332 333 mPageFlipCount++; 334 eglSwapBuffers(dpy, surface); 335 checkEGLErrors("eglSwapBuffers"); 336 337 // for debugging 338 //glClearColor(1,0,0,0); 339 //glClear(GL_COLOR_BUFFER_BIT); 340 } 341 342 status_t DisplayHardware::postBypassBuffer(const native_handle_t* handle) const 343 { 344 framebuffer_device_t *fbDev = (framebuffer_device_t *)mNativeWindow->getDevice(); 345 return fbDev->post(fbDev, handle); 346 } 347 348 uint32_t DisplayHardware::getFlags() const 349 { 350 return mFlags; 351 } 352 353 void DisplayHardware::makeCurrent() const 354 { 355 eglMakeCurrent(mDisplay, mSurface, mSurface, mContext); 356 } 357