FramebufferNativeWindow.cpp revision cb6b9041647b4f080324742eee5ce709960ff610
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 29#include <ui/SurfaceComposerClient.h> 30#include <ui/Rect.h> 31#include <ui/FramebufferNativeWindow.h> 32 33#include <EGL/egl.h> 34 35#include <pixelflinger/format.h> 36#include <pixelflinger/pixelflinger.h> 37 38#include <hardware/hardware.h> 39#include <hardware/gralloc.h> 40 41#include <private/ui/android_natives_priv.h> 42 43// ---------------------------------------------------------------------------- 44namespace android { 45// ---------------------------------------------------------------------------- 46 47class NativeBuffer 48 : public EGLNativeBase< 49 android_native_buffer_t, 50 NativeBuffer, 51 LightRefBase<NativeBuffer> > 52{ 53public: 54 NativeBuffer(int w, int h, int f, int u) : BASE() { 55 android_native_buffer_t::width = w; 56 android_native_buffer_t::height = h; 57 android_native_buffer_t::format = f; 58 android_native_buffer_t::usage = u; 59 } 60private: 61 friend class LightRefBase<NativeBuffer>; 62 ~NativeBuffer() { }; // this class cannot be overloaded 63}; 64 65 66/* 67 * This implements the (main) framebuffer management. This class is used 68 * mostly by SurfaceFlinger, but also by command line GL application. 69 * 70 * In fact this is an implementation of android_native_window_t on top of 71 * the framebuffer. 72 * 73 * Currently it is pretty simple, it manages only two buffers (the front and 74 * back buffer). 75 * 76 */ 77 78FramebufferNativeWindow::FramebufferNativeWindow() 79 : BASE(), fbDev(0), grDev(0), mUpdateOnDemand(false) 80{ 81 hw_module_t const* module; 82 if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) { 83 int stride; 84 framebuffer_open(module, &fbDev); 85 gralloc_open(module, &grDev); 86 int err; 87 88 89 mUpdateOnDemand = (fbDev->setUpdateRect != 0); 90 91 // initialize the buffer FIFO 92 mNumBuffers = 2; 93 mNumFreeBuffers = 2; 94 mBufferHead = mNumBuffers-1; 95 buffers[0] = new NativeBuffer( 96 fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB); 97 buffers[1] = new NativeBuffer( 98 fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB); 99 100 err = grDev->alloc(grDev, 101 fbDev->width, fbDev->height, fbDev->format, 102 GRALLOC_USAGE_HW_FB, &buffers[0]->handle, &buffers[0]->stride); 103 104 LOGE_IF(err, "fb buffer 0 allocation failed w=%d, h=%d, err=%s", 105 fbDev->width, fbDev->height, strerror(-err)); 106 107 err = grDev->alloc(grDev, 108 fbDev->width, fbDev->height, fbDev->format, 109 GRALLOC_USAGE_HW_FB, &buffers[1]->handle, &buffers[1]->stride); 110 111 LOGE_IF(err, "fb buffer 1 allocation failed w=%d, h=%d, err=%s", 112 fbDev->width, fbDev->height, strerror(-err)); 113 } 114 115 const_cast<uint32_t&>(android_native_window_t::flags) = fbDev->flags; 116 const_cast<float&>(android_native_window_t::xdpi) = fbDev->xdpi; 117 const_cast<float&>(android_native_window_t::ydpi) = fbDev->ydpi; 118 const_cast<int&>(android_native_window_t::minSwapInterval) = 119 fbDev->minSwapInterval; 120 const_cast<int&>(android_native_window_t::maxSwapInterval) = 121 fbDev->maxSwapInterval; 122 123 android_native_window_t::setSwapInterval = setSwapInterval; 124 android_native_window_t::dequeueBuffer = dequeueBuffer; 125 android_native_window_t::lockBuffer = lockBuffer; 126 android_native_window_t::queueBuffer = queueBuffer; 127 android_native_window_t::query = query; 128} 129 130FramebufferNativeWindow::~FramebufferNativeWindow() { 131 grDev->free(grDev, buffers[0]->handle); 132 grDev->free(grDev, buffers[1]->handle); 133 gralloc_close(grDev); 134 framebuffer_close(fbDev); 135} 136 137status_t FramebufferNativeWindow::setUpdateRectangle(const Rect& r) 138{ 139 if (!mUpdateOnDemand) { 140 return INVALID_OPERATION; 141 } 142 return fbDev->setUpdateRect(fbDev, r.left, r.top, r.width(), r.height()); 143} 144 145int FramebufferNativeWindow::setSwapInterval( 146 android_native_window_t* window, int interval) 147{ 148 framebuffer_device_t* fb = getSelf(window)->fbDev; 149 return fb->setSwapInterval(fb, interval); 150} 151 152int FramebufferNativeWindow::dequeueBuffer(android_native_window_t* window, 153 android_native_buffer_t** buffer) 154{ 155 FramebufferNativeWindow* self = getSelf(window); 156 Mutex::Autolock _l(self->mutex); 157 framebuffer_device_t* fb = self->fbDev; 158 159 // wait for a free buffer 160 while (!self->mNumFreeBuffers) { 161 self->mCondition.wait(self->mutex); 162 } 163 // get this buffer 164 self->mNumFreeBuffers--; 165 int index = self->mBufferHead++; 166 if (self->mBufferHead >= self->mNumBuffers) 167 self->mBufferHead = 0; 168 169 *buffer = self->buffers[index].get(); 170 171 return 0; 172} 173 174int FramebufferNativeWindow::lockBuffer(android_native_window_t* window, 175 android_native_buffer_t* buffer) 176{ 177 FramebufferNativeWindow* self = getSelf(window); 178 Mutex::Autolock _l(self->mutex); 179 180 // wait that the buffer we're locking is not front anymore 181 while (self->front == buffer) { 182 self->mCondition.wait(self->mutex); 183 } 184 185 return NO_ERROR; 186} 187 188int FramebufferNativeWindow::queueBuffer(android_native_window_t* window, 189 android_native_buffer_t* buffer) 190{ 191 FramebufferNativeWindow* self = getSelf(window); 192 Mutex::Autolock _l(self->mutex); 193 framebuffer_device_t* fb = self->fbDev; 194 buffer_handle_t handle = static_cast<NativeBuffer*>(buffer)->handle; 195 int res = fb->post(fb, handle); 196 self->front = static_cast<NativeBuffer*>(buffer); 197 self->mNumFreeBuffers++; 198 self->mCondition.broadcast(); 199 return res; 200} 201 202int FramebufferNativeWindow::query(android_native_window_t* window, 203 int what, int* value) 204{ 205 FramebufferNativeWindow* self = getSelf(window); 206 Mutex::Autolock _l(self->mutex); 207 framebuffer_device_t* fb = self->fbDev; 208 switch (what) { 209 case NATIVE_WINDOW_WIDTH: 210 *value = fb->width; 211 return NO_ERROR; 212 case NATIVE_WINDOW_HEIGHT: 213 *value = fb->height; 214 return NO_ERROR; 215 } 216 return BAD_VALUE; 217} 218 219// ---------------------------------------------------------------------------- 220}; // namespace android 221// ---------------------------------------------------------------------------- 222 223 224EGLNativeWindowType android_createDisplaySurface(void) 225{ 226 return new android::FramebufferNativeWindow(); 227} 228 229