1 /* 2 ** 3 ** Copyright 2007 The Android Open Source Project 4 ** 5 ** Licensed under the Apache License Version 2.0(the "License"); 6 ** you may not use this file except in compliance with the License. 7 ** You may obtain a copy of the License at 8 ** 9 ** http://www.apache.org/licenses/LICENSE-2.0 10 ** 11 ** Unless required by applicable law or agreed to in writing software 12 ** distributed under the License is distributed on an "AS IS" BASIS 13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. 14 ** See the License for the specific language governing permissions and 15 ** limitations under the License. 16 */ 17 18 #define LOG_TAG "FramebufferNativeWindow" 19 20 #include <stdlib.h> 21 #include <stdio.h> 22 #include <string.h> 23 #include <errno.h> 24 25 #include <cutils/log.h> 26 #include <cutils/atomic.h> 27 #include <utils/threads.h> 28 #include <utils/RefBase.h> 29 30 #include <ui/Rect.h> 31 #include <ui/FramebufferNativeWindow.h> 32 #include <ui/GraphicLog.h> 33 34 #include <EGL/egl.h> 35 36 #include <pixelflinger/format.h> 37 #include <pixelflinger/pixelflinger.h> 38 39 #include <hardware/hardware.h> 40 #include <hardware/gralloc.h> 41 42 #include <private/ui/android_natives_priv.h> 43 44 // ---------------------------------------------------------------------------- 45 namespace android { 46 // ---------------------------------------------------------------------------- 47 48 class NativeBuffer 49 : public EGLNativeBase< 50 ANativeWindowBuffer, 51 NativeBuffer, 52 LightRefBase<NativeBuffer> > 53 { 54 public: 55 NativeBuffer(int w, int h, int f, int u) : BASE() { 56 ANativeWindowBuffer::width = w; 57 ANativeWindowBuffer::height = h; 58 ANativeWindowBuffer::format = f; 59 ANativeWindowBuffer::usage = u; 60 } 61 private: 62 friend class LightRefBase<NativeBuffer>; 63 ~NativeBuffer() { }; // this class cannot be overloaded 64 }; 65 66 67 /* 68 * This implements the (main) framebuffer management. This class is used 69 * mostly by SurfaceFlinger, but also by command line GL application. 70 * 71 * In fact this is an implementation of ANativeWindow on top of 72 * the framebuffer. 73 * 74 * Currently it is pretty simple, it manages only two buffers (the front and 75 * back buffer). 76 * 77 */ 78 79 FramebufferNativeWindow::FramebufferNativeWindow() 80 : BASE(), fbDev(0), grDev(0), mUpdateOnDemand(false) 81 { 82 hw_module_t const* module; 83 if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) { 84 int stride; 85 int err; 86 int i; 87 err = framebuffer_open(module, &fbDev); 88 LOGE_IF(err, "couldn't open framebuffer HAL (%s)", strerror(-err)); 89 90 err = gralloc_open(module, &grDev); 91 LOGE_IF(err, "couldn't open gralloc HAL (%s)", strerror(-err)); 92 93 // bail out if we can't initialize the modules 94 if (!fbDev || !grDev) 95 return; 96 97 mUpdateOnDemand = (fbDev->setUpdateRect != 0); 98 99 // initialize the buffer FIFO 100 mNumBuffers = NUM_FRAME_BUFFERS; 101 mNumFreeBuffers = NUM_FRAME_BUFFERS; 102 mBufferHead = mNumBuffers-1; 103 104 for (i = 0; i < mNumBuffers; i++) 105 { 106 buffers[i] = new NativeBuffer( 107 fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB); 108 } 109 110 for (i = 0; i < mNumBuffers; i++) 111 { 112 err = grDev->alloc(grDev, 113 fbDev->width, fbDev->height, fbDev->format, 114 GRALLOC_USAGE_HW_FB, &buffers[i]->handle, &buffers[i]->stride); 115 116 LOGE_IF(err, "fb buffer %d allocation failed w=%d, h=%d, err=%s", 117 i, fbDev->width, fbDev->height, strerror(-err)); 118 119 if (err) 120 { 121 mNumBuffers = i; 122 mNumFreeBuffers = i; 123 mBufferHead = mNumBuffers-1; 124 break; 125 } 126 } 127 128 const_cast<uint32_t&>(ANativeWindow::flags) = fbDev->flags; 129 const_cast<float&>(ANativeWindow::xdpi) = fbDev->xdpi; 130 const_cast<float&>(ANativeWindow::ydpi) = fbDev->ydpi; 131 const_cast<int&>(ANativeWindow::minSwapInterval) = 132 fbDev->minSwapInterval; 133 const_cast<int&>(ANativeWindow::maxSwapInterval) = 134 fbDev->maxSwapInterval; 135 } else { 136 LOGE("Couldn't get gralloc module"); 137 } 138 139 ANativeWindow::setSwapInterval = setSwapInterval; 140 ANativeWindow::dequeueBuffer = dequeueBuffer; 141 ANativeWindow::lockBuffer = lockBuffer; 142 ANativeWindow::queueBuffer = queueBuffer; 143 ANativeWindow::query = query; 144 ANativeWindow::perform = perform; 145 } 146 147 FramebufferNativeWindow::~FramebufferNativeWindow() 148 { 149 if (grDev) { 150 if (buffers[0] != NULL) 151 grDev->free(grDev, buffers[0]->handle); 152 if (buffers[1] != NULL) 153 grDev->free(grDev, buffers[1]->handle); 154 gralloc_close(grDev); 155 } 156 157 if (fbDev) { 158 framebuffer_close(fbDev); 159 } 160 } 161 162 status_t FramebufferNativeWindow::setUpdateRectangle(const Rect& r) 163 { 164 if (!mUpdateOnDemand) { 165 return INVALID_OPERATION; 166 } 167 return fbDev->setUpdateRect(fbDev, r.left, r.top, r.width(), r.height()); 168 } 169 170 status_t FramebufferNativeWindow::compositionComplete() 171 { 172 if (fbDev->compositionComplete) { 173 return fbDev->compositionComplete(fbDev); 174 } 175 return INVALID_OPERATION; 176 } 177 178 int FramebufferNativeWindow::setSwapInterval( 179 ANativeWindow* window, int interval) 180 { 181 framebuffer_device_t* fb = getSelf(window)->fbDev; 182 return fb->setSwapInterval(fb, interval); 183 } 184 185 void FramebufferNativeWindow::dump(String8& result) { 186 if (fbDev->common.version >= 1 && fbDev->dump) { 187 const size_t SIZE = 4096; 188 char buffer[SIZE]; 189 190 fbDev->dump(fbDev, buffer, SIZE); 191 result.append(buffer); 192 } 193 } 194 195 // only for debugging / logging 196 int FramebufferNativeWindow::getCurrentBufferIndex() const 197 { 198 Mutex::Autolock _l(mutex); 199 const int index = mCurrentBufferIndex; 200 return index; 201 } 202 203 int FramebufferNativeWindow::dequeueBuffer(ANativeWindow* window, 204 ANativeWindowBuffer** buffer) 205 { 206 FramebufferNativeWindow* self = getSelf(window); 207 Mutex::Autolock _l(self->mutex); 208 framebuffer_device_t* fb = self->fbDev; 209 210 int index = self->mBufferHead++; 211 if (self->mBufferHead >= self->mNumBuffers) 212 self->mBufferHead = 0; 213 214 GraphicLog& logger(GraphicLog::getInstance()); 215 logger.log(GraphicLog::SF_FB_DEQUEUE_BEFORE, index); 216 217 // wait for a free buffer 218 while (!self->mNumFreeBuffers) { 219 self->mCondition.wait(self->mutex); 220 } 221 // get this buffer 222 self->mNumFreeBuffers--; 223 self->mCurrentBufferIndex = index; 224 225 *buffer = self->buffers[index].get(); 226 227 logger.log(GraphicLog::SF_FB_DEQUEUE_AFTER, index); 228 return 0; 229 } 230 231 int FramebufferNativeWindow::lockBuffer(ANativeWindow* window, 232 ANativeWindowBuffer* buffer) 233 { 234 FramebufferNativeWindow* self = getSelf(window); 235 Mutex::Autolock _l(self->mutex); 236 237 const int index = self->mCurrentBufferIndex; 238 GraphicLog& logger(GraphicLog::getInstance()); 239 logger.log(GraphicLog::SF_FB_LOCK_BEFORE, index); 240 241 // wait that the buffer we're locking is not front anymore 242 while (self->front == buffer) { 243 self->mCondition.wait(self->mutex); 244 } 245 246 logger.log(GraphicLog::SF_FB_LOCK_AFTER, index); 247 248 return NO_ERROR; 249 } 250 251 int FramebufferNativeWindow::queueBuffer(ANativeWindow* window, 252 ANativeWindowBuffer* buffer) 253 { 254 FramebufferNativeWindow* self = getSelf(window); 255 Mutex::Autolock _l(self->mutex); 256 framebuffer_device_t* fb = self->fbDev; 257 buffer_handle_t handle = static_cast<NativeBuffer*>(buffer)->handle; 258 259 const int index = self->mCurrentBufferIndex; 260 GraphicLog& logger(GraphicLog::getInstance()); 261 logger.log(GraphicLog::SF_FB_POST_BEFORE, index); 262 263 int res = fb->post(fb, handle); 264 265 logger.log(GraphicLog::SF_FB_POST_AFTER, index); 266 267 self->front = static_cast<NativeBuffer*>(buffer); 268 self->mNumFreeBuffers++; 269 self->mCondition.broadcast(); 270 return res; 271 } 272 273 int FramebufferNativeWindow::query(const ANativeWindow* window, 274 int what, int* value) 275 { 276 const FramebufferNativeWindow* self = getSelf(window); 277 Mutex::Autolock _l(self->mutex); 278 framebuffer_device_t* fb = self->fbDev; 279 switch (what) { 280 case NATIVE_WINDOW_WIDTH: 281 *value = fb->width; 282 return NO_ERROR; 283 case NATIVE_WINDOW_HEIGHT: 284 *value = fb->height; 285 return NO_ERROR; 286 case NATIVE_WINDOW_FORMAT: 287 *value = fb->format; 288 return NO_ERROR; 289 case NATIVE_WINDOW_CONCRETE_TYPE: 290 *value = NATIVE_WINDOW_FRAMEBUFFER; 291 return NO_ERROR; 292 case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER: 293 *value = 0; 294 return NO_ERROR; 295 case NATIVE_WINDOW_DEFAULT_WIDTH: 296 *value = fb->width; 297 return NO_ERROR; 298 case NATIVE_WINDOW_DEFAULT_HEIGHT: 299 *value = fb->height; 300 return NO_ERROR; 301 case NATIVE_WINDOW_TRANSFORM_HINT: 302 *value = 0; 303 return NO_ERROR; 304 } 305 *value = 0; 306 return BAD_VALUE; 307 } 308 309 int FramebufferNativeWindow::perform(ANativeWindow* window, 310 int operation, ...) 311 { 312 switch (operation) { 313 case NATIVE_WINDOW_CONNECT: 314 case NATIVE_WINDOW_DISCONNECT: 315 case NATIVE_WINDOW_SET_USAGE: 316 case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY: 317 case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS: 318 case NATIVE_WINDOW_SET_BUFFERS_FORMAT: 319 case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM: 320 case NATIVE_WINDOW_API_CONNECT: 321 case NATIVE_WINDOW_API_DISCONNECT: 322 // TODO: we should implement these 323 return NO_ERROR; 324 325 case NATIVE_WINDOW_LOCK: 326 case NATIVE_WINDOW_UNLOCK_AND_POST: 327 case NATIVE_WINDOW_SET_CROP: 328 case NATIVE_WINDOW_SET_BUFFER_COUNT: 329 case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP: 330 case NATIVE_WINDOW_SET_SCALING_MODE: 331 return INVALID_OPERATION; 332 } 333 return NAME_NOT_FOUND; 334 } 335 336 // ---------------------------------------------------------------------------- 337 }; // namespace android 338 // ---------------------------------------------------------------------------- 339 340 using namespace android; 341 342 EGLNativeWindowType android_createDisplaySurface(void) 343 { 344 FramebufferNativeWindow* w; 345 w = new FramebufferNativeWindow(); 346 if (w->getDevice() == NULL) { 347 // get a ref so it can be destroyed when we exit this block 348 sp<FramebufferNativeWindow> ref(w); 349 return NULL; 350 } 351 return (EGLNativeWindowType)w; 352 } 353