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