FramebufferNativeWindow.cpp revision 0bc64be3f5198f8dda1ced21bbc957a1d76efbb7
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/ANativeObjectBase.h> 31#include <ui/FramebufferNativeWindow.h> 32#include <ui/Rect.h> 33 34#include <EGL/egl.h> 35 36#include <hardware/hardware.h> 37#include <hardware/gralloc.h> 38 39// ---------------------------------------------------------------------------- 40namespace android { 41// ---------------------------------------------------------------------------- 42 43class NativeBuffer 44 : public ANativeObjectBase< 45 ANativeWindowBuffer, 46 NativeBuffer, 47 LightRefBase<NativeBuffer> > 48{ 49public: 50 NativeBuffer(int w, int h, int f, int u) : BASE() { 51 ANativeWindowBuffer::width = w; 52 ANativeWindowBuffer::height = h; 53 ANativeWindowBuffer::format = f; 54 ANativeWindowBuffer::usage = u; 55 } 56private: 57 friend class LightRefBase<NativeBuffer>; 58 ~NativeBuffer() { }; // this class cannot be overloaded 59}; 60 61 62/* 63 * This implements the (main) framebuffer management. This class is used 64 * mostly by SurfaceFlinger, but also by command line GL application. 65 * 66 * In fact this is an implementation of ANativeWindow on top of 67 * the framebuffer. 68 * 69 * Currently it is pretty simple, it manages only two buffers (the front and 70 * back buffer). 71 * 72 */ 73 74FramebufferNativeWindow::FramebufferNativeWindow() 75 : BASE(), fbDev(0), grDev(0), mUpdateOnDemand(false) 76{ 77 hw_module_t const* module; 78 if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) { 79 int stride; 80 int err; 81 int i; 82 err = framebuffer_open(module, &fbDev); 83 ALOGE_IF(err, "couldn't open framebuffer HAL (%s)", strerror(-err)); 84 85 err = gralloc_open(module, &grDev); 86 ALOGE_IF(err, "couldn't open gralloc HAL (%s)", strerror(-err)); 87 88 // bail out if we can't initialize the modules 89 if (!fbDev || !grDev) 90 return; 91 92 mUpdateOnDemand = (fbDev->setUpdateRect != 0); 93 94 // initialize the buffer FIFO 95 if(fbDev->numFramebuffers >= MIN_NUM_FRAME_BUFFERS && 96 fbDev->numFramebuffers <= MAX_NUM_FRAME_BUFFERS){ 97 mNumBuffers = fbDev->numFramebuffers; 98 } else { 99 mNumBuffers = MIN_NUM_FRAME_BUFFERS; 100 } 101 mNumFreeBuffers = mNumBuffers; 102 mBufferHead = mNumBuffers-1; 103 104 /* 105 * This does not actually change the framebuffer format. It merely 106 * fakes this format to surfaceflinger so that when it creates 107 * framebuffer surfaces it will use this format. It's really a giant 108 * HACK to allow interworking with buggy gralloc+GPU driver 109 * implementations. You should *NEVER* need to set this for shipping 110 * devices. 111 */ 112#ifdef FRAMEBUFFER_FORCE_FORMAT 113 *((uint32_t *)&fbDev->format) = FRAMEBUFFER_FORCE_FORMAT; 114#endif 115 116 for (i = 0; i < mNumBuffers; i++) 117 { 118 buffers[i] = new NativeBuffer( 119 fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB); 120 } 121 122 for (i = 0; i < mNumBuffers; i++) 123 { 124 err = grDev->alloc(grDev, 125 fbDev->width, fbDev->height, fbDev->format, 126 GRALLOC_USAGE_HW_FB, &buffers[i]->handle, &buffers[i]->stride); 127 128 ALOGE_IF(err, "fb buffer %d allocation failed w=%d, h=%d, err=%s", 129 i, fbDev->width, fbDev->height, strerror(-err)); 130 131 if (err) 132 { 133 mNumBuffers = i; 134 mNumFreeBuffers = i; 135 mBufferHead = mNumBuffers-1; 136 break; 137 } 138 } 139 140 const_cast<uint32_t&>(ANativeWindow::flags) = fbDev->flags; 141 const_cast<float&>(ANativeWindow::xdpi) = fbDev->xdpi; 142 const_cast<float&>(ANativeWindow::ydpi) = fbDev->ydpi; 143 const_cast<int&>(ANativeWindow::minSwapInterval) = 144 fbDev->minSwapInterval; 145 const_cast<int&>(ANativeWindow::maxSwapInterval) = 146 fbDev->maxSwapInterval; 147 } else { 148 ALOGE("Couldn't get gralloc module"); 149 } 150 151 ANativeWindow::setSwapInterval = setSwapInterval; 152 ANativeWindow::dequeueBuffer = dequeueBuffer; 153 ANativeWindow::lockBuffer = lockBuffer; 154 ANativeWindow::queueBuffer = queueBuffer; 155 ANativeWindow::query = query; 156 ANativeWindow::perform = perform; 157} 158 159FramebufferNativeWindow::~FramebufferNativeWindow() 160{ 161 if (grDev) { 162 for(int i = 0; i < mNumBuffers; i++) { 163 if (buffers[i] != NULL) { 164 grDev->free(grDev, buffers[i]->handle); 165 } 166 } 167 gralloc_close(grDev); 168 } 169 170 if (fbDev) { 171 framebuffer_close(fbDev); 172 } 173} 174 175status_t FramebufferNativeWindow::setUpdateRectangle(const Rect& r) 176{ 177 if (!mUpdateOnDemand) { 178 return INVALID_OPERATION; 179 } 180 return fbDev->setUpdateRect(fbDev, r.left, r.top, r.width(), r.height()); 181} 182 183status_t FramebufferNativeWindow::compositionComplete() 184{ 185 if (fbDev->compositionComplete) { 186 return fbDev->compositionComplete(fbDev); 187 } 188 return INVALID_OPERATION; 189} 190 191int FramebufferNativeWindow::setSwapInterval( 192 ANativeWindow* window, int interval) 193{ 194 framebuffer_device_t* fb = getSelf(window)->fbDev; 195 return fb->setSwapInterval(fb, interval); 196} 197 198void FramebufferNativeWindow::dump(String8& result) { 199 if (fbDev->common.version >= 1 && fbDev->dump) { 200 const size_t SIZE = 4096; 201 char buffer[SIZE]; 202 203 fbDev->dump(fbDev, buffer, SIZE); 204 result.append(buffer); 205 } 206} 207 208// only for debugging / logging 209int FramebufferNativeWindow::getCurrentBufferIndex() const 210{ 211 Mutex::Autolock _l(mutex); 212 const int index = mCurrentBufferIndex; 213 return index; 214} 215 216int FramebufferNativeWindow::dequeueBuffer(ANativeWindow* window, 217 ANativeWindowBuffer** buffer) 218{ 219 FramebufferNativeWindow* self = getSelf(window); 220 Mutex::Autolock _l(self->mutex); 221 framebuffer_device_t* fb = self->fbDev; 222 223 int index = self->mBufferHead++; 224 if (self->mBufferHead >= self->mNumBuffers) 225 self->mBufferHead = 0; 226 227 // wait for a free buffer 228 while (!self->mNumFreeBuffers) { 229 self->mCondition.wait(self->mutex); 230 } 231 // get this buffer 232 self->mNumFreeBuffers--; 233 self->mCurrentBufferIndex = index; 234 235 *buffer = self->buffers[index].get(); 236 237 return 0; 238} 239 240int FramebufferNativeWindow::lockBuffer(ANativeWindow* window, 241 ANativeWindowBuffer* buffer) 242{ 243 FramebufferNativeWindow* self = getSelf(window); 244 Mutex::Autolock _l(self->mutex); 245 246 const int index = self->mCurrentBufferIndex; 247 248 // wait that the buffer we're locking is not front anymore 249 while (self->front == buffer) { 250 self->mCondition.wait(self->mutex); 251 } 252 253 return NO_ERROR; 254} 255 256int FramebufferNativeWindow::queueBuffer(ANativeWindow* window, 257 ANativeWindowBuffer* buffer) 258{ 259 FramebufferNativeWindow* self = getSelf(window); 260 Mutex::Autolock _l(self->mutex); 261 framebuffer_device_t* fb = self->fbDev; 262 buffer_handle_t handle = static_cast<NativeBuffer*>(buffer)->handle; 263 264 const int index = self->mCurrentBufferIndex; 265 int res = fb->post(fb, handle); 266 self->front = static_cast<NativeBuffer*>(buffer); 267 self->mNumFreeBuffers++; 268 self->mCondition.broadcast(); 269 return res; 270} 271 272int FramebufferNativeWindow::query(const ANativeWindow* window, 273 int what, int* value) 274{ 275 const FramebufferNativeWindow* self = getSelf(window); 276 Mutex::Autolock _l(self->mutex); 277 framebuffer_device_t* fb = self->fbDev; 278 switch (what) { 279 case NATIVE_WINDOW_WIDTH: 280 *value = fb->width; 281 return NO_ERROR; 282 case NATIVE_WINDOW_HEIGHT: 283 *value = fb->height; 284 return NO_ERROR; 285 case NATIVE_WINDOW_FORMAT: 286 *value = fb->format; 287 return NO_ERROR; 288 case NATIVE_WINDOW_CONCRETE_TYPE: 289 *value = NATIVE_WINDOW_FRAMEBUFFER; 290 return NO_ERROR; 291 case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER: 292 *value = 0; 293 return NO_ERROR; 294 case NATIVE_WINDOW_DEFAULT_WIDTH: 295 *value = fb->width; 296 return NO_ERROR; 297 case NATIVE_WINDOW_DEFAULT_HEIGHT: 298 *value = fb->height; 299 return NO_ERROR; 300 case NATIVE_WINDOW_TRANSFORM_HINT: 301 *value = 0; 302 return NO_ERROR; 303 } 304 *value = 0; 305 return BAD_VALUE; 306} 307 308int FramebufferNativeWindow::perform(ANativeWindow* window, 309 int operation, ...) 310{ 311 switch (operation) { 312 case NATIVE_WINDOW_CONNECT: 313 case NATIVE_WINDOW_DISCONNECT: 314 case NATIVE_WINDOW_SET_USAGE: 315 case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY: 316 case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS: 317 case NATIVE_WINDOW_SET_BUFFERS_FORMAT: 318 case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM: 319 case NATIVE_WINDOW_API_CONNECT: 320 case NATIVE_WINDOW_API_DISCONNECT: 321 // TODO: we should implement these 322 return NO_ERROR; 323 324 case NATIVE_WINDOW_LOCK: 325 case NATIVE_WINDOW_UNLOCK_AND_POST: 326 case NATIVE_WINDOW_SET_CROP: 327 case NATIVE_WINDOW_SET_BUFFER_COUNT: 328 case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP: 329 case NATIVE_WINDOW_SET_SCALING_MODE: 330 return INVALID_OPERATION; 331 } 332 return NAME_NOT_FOUND; 333} 334 335// ---------------------------------------------------------------------------- 336}; // namespace android 337// ---------------------------------------------------------------------------- 338 339using namespace android; 340 341EGLNativeWindowType android_createDisplaySurface(void) 342{ 343 FramebufferNativeWindow* w; 344 w = new FramebufferNativeWindow(); 345 if (w->getDevice() == NULL) { 346 // get a ref so it can be destroyed when we exit this block 347 sp<FramebufferNativeWindow> ref(w); 348 return NULL; 349 } 350 return (EGLNativeWindowType)w; 351} 352