FramebufferNativeWindow.cpp revision a74cbc06493ed941a8a54f2f1d0074f03fc9aafb
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 non-front buffer 241 while (self->mNumFreeBuffers < 2) { 242 self->mCondition.wait(self->mutex); 243 } 244 ALOG_ASSERT(self->buffers[index] != self->front); 245 246 // get this buffer 247 self->mNumFreeBuffers--; 248 self->mCurrentBufferIndex = index; 249 250 *buffer = self->buffers[index].get(); 251 *fenceFd = -1; 252 253 return 0; 254} 255 256int FramebufferNativeWindow::lockBuffer_DEPRECATED(ANativeWindow* window, 257 ANativeWindowBuffer* buffer) 258{ 259 return NO_ERROR; 260} 261 262int FramebufferNativeWindow::queueBuffer_DEPRECATED(ANativeWindow* window, 263 ANativeWindowBuffer* buffer) 264{ 265 return queueBuffer(window, buffer, -1); 266} 267 268int FramebufferNativeWindow::queueBuffer(ANativeWindow* window, 269 ANativeWindowBuffer* buffer, int fenceFd) 270{ 271 FramebufferNativeWindow* self = getSelf(window); 272 Mutex::Autolock _l(self->mutex); 273 framebuffer_device_t* fb = self->fbDev; 274 buffer_handle_t handle = static_cast<NativeBuffer*>(buffer)->handle; 275 276 sp<Fence> fence(new Fence(fenceFd)); 277 fence->wait(Fence::TIMEOUT_NEVER); 278 279 const int index = self->mCurrentBufferIndex; 280 int res = fb->post(fb, handle); 281 self->front = static_cast<NativeBuffer*>(buffer); 282 self->mNumFreeBuffers++; 283 self->mCondition.broadcast(); 284 return res; 285} 286 287int FramebufferNativeWindow::query(const ANativeWindow* window, 288 int what, int* value) 289{ 290 const FramebufferNativeWindow* self = getSelf(window); 291 Mutex::Autolock _l(self->mutex); 292 framebuffer_device_t* fb = self->fbDev; 293 switch (what) { 294 case NATIVE_WINDOW_WIDTH: 295 *value = fb->width; 296 return NO_ERROR; 297 case NATIVE_WINDOW_HEIGHT: 298 *value = fb->height; 299 return NO_ERROR; 300 case NATIVE_WINDOW_FORMAT: 301 *value = fb->format; 302 return NO_ERROR; 303 case NATIVE_WINDOW_CONCRETE_TYPE: 304 *value = NATIVE_WINDOW_FRAMEBUFFER; 305 return NO_ERROR; 306 case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER: 307 *value = 0; 308 return NO_ERROR; 309 case NATIVE_WINDOW_DEFAULT_WIDTH: 310 *value = fb->width; 311 return NO_ERROR; 312 case NATIVE_WINDOW_DEFAULT_HEIGHT: 313 *value = fb->height; 314 return NO_ERROR; 315 case NATIVE_WINDOW_TRANSFORM_HINT: 316 *value = 0; 317 return NO_ERROR; 318 } 319 *value = 0; 320 return BAD_VALUE; 321} 322 323int FramebufferNativeWindow::perform(ANativeWindow* window, 324 int operation, ...) 325{ 326 switch (operation) { 327 case NATIVE_WINDOW_CONNECT: 328 case NATIVE_WINDOW_DISCONNECT: 329 case NATIVE_WINDOW_SET_USAGE: 330 case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY: 331 case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS: 332 case NATIVE_WINDOW_SET_BUFFERS_FORMAT: 333 case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM: 334 case NATIVE_WINDOW_API_CONNECT: 335 case NATIVE_WINDOW_API_DISCONNECT: 336 // TODO: we should implement these 337 return NO_ERROR; 338 339 case NATIVE_WINDOW_LOCK: 340 case NATIVE_WINDOW_UNLOCK_AND_POST: 341 case NATIVE_WINDOW_SET_CROP: 342 case NATIVE_WINDOW_SET_BUFFER_COUNT: 343 case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP: 344 case NATIVE_WINDOW_SET_SCALING_MODE: 345 return INVALID_OPERATION; 346 } 347 return NAME_NOT_FOUND; 348} 349 350// ---------------------------------------------------------------------------- 351}; // namespace android 352// ---------------------------------------------------------------------------- 353 354using namespace android; 355 356EGLNativeWindowType android_createDisplaySurface(void) 357{ 358 FramebufferNativeWindow* w; 359 w = new FramebufferNativeWindow(); 360 if (w->getDevice() == NULL) { 361 // get a ref so it can be destroyed when we exit this block 362 sp<FramebufferNativeWindow> ref(w); 363 return NULL; 364 } 365 return (EGLNativeWindowType)w; 366} 367