FramebufferNativeWindow.cpp revision aa8c0ff7a36b4840dcf3e72c9696b86d192c4314
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) 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 // initialize the buffer FIFO 90 mNumBuffers = 2; 91 mNumFreeBuffers = 2; 92 mBufferHead = mNumBuffers-1; 93 buffers[0] = new NativeBuffer( 94 fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB); 95 buffers[1] = new NativeBuffer( 96 fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB); 97 98 err = grDev->alloc(grDev, 99 fbDev->width, fbDev->height, fbDev->format, 100 GRALLOC_USAGE_HW_FB, &buffers[0]->handle, &buffers[0]->stride); 101 102 LOGE_IF(err, "fb buffer 0 allocation failed w=%d, h=%d, err=%s", 103 fbDev->width, fbDev->height, strerror(-err)); 104 105 err = grDev->alloc(grDev, 106 fbDev->width, fbDev->height, fbDev->format, 107 GRALLOC_USAGE_HW_FB, &buffers[1]->handle, &buffers[1]->stride); 108 109 LOGE_IF(err, "fb buffer 1 allocation failed w=%d, h=%d, err=%s", 110 fbDev->width, fbDev->height, strerror(-err)); 111 } 112 113 const_cast<uint32_t&>(android_native_window_t::flags) = fbDev->flags; 114 const_cast<float&>(android_native_window_t::xdpi) = fbDev->xdpi; 115 const_cast<float&>(android_native_window_t::ydpi) = fbDev->ydpi; 116 const_cast<int&>(android_native_window_t::minSwapInterval) = 117 fbDev->minSwapInterval; 118 const_cast<int&>(android_native_window_t::maxSwapInterval) = 119 fbDev->maxSwapInterval; 120 121 android_native_window_t::setSwapInterval = setSwapInterval; 122 android_native_window_t::dequeueBuffer = dequeueBuffer; 123 android_native_window_t::lockBuffer = lockBuffer; 124 android_native_window_t::queueBuffer = queueBuffer; 125} 126 127FramebufferNativeWindow::~FramebufferNativeWindow() { 128 grDev->free(grDev, buffers[0]->handle); 129 grDev->free(grDev, buffers[1]->handle); 130 gralloc_close(grDev); 131 framebuffer_close(fbDev); 132} 133 134int FramebufferNativeWindow::setSwapInterval( 135 android_native_window_t* window, int interval) 136{ 137 framebuffer_device_t* fb = getSelf(window)->fbDev; 138 return fb->setSwapInterval(fb, interval); 139} 140 141int FramebufferNativeWindow::dequeueBuffer(android_native_window_t* window, 142 android_native_buffer_t** buffer) 143{ 144 FramebufferNativeWindow* self = getSelf(window); 145 Mutex::Autolock _l(self->mutex); 146 framebuffer_device_t* fb = self->fbDev; 147 148 // wait for a free buffer 149 while (!self->mNumFreeBuffers) { 150 self->mCondition.wait(self->mutex); 151 } 152 // get this buffer 153 self->mNumFreeBuffers--; 154 int index = self->mBufferHead++; 155 if (self->mBufferHead >= self->mNumBuffers) 156 self->mBufferHead = 0; 157 158 *buffer = self->buffers[index].get(); 159 160 return 0; 161} 162 163int FramebufferNativeWindow::lockBuffer(android_native_window_t* window, 164 android_native_buffer_t* buffer) 165{ 166 FramebufferNativeWindow* self = getSelf(window); 167 Mutex::Autolock _l(self->mutex); 168 169 // wait that the buffer we're locking is not front anymore 170 while (self->front == buffer) { 171 self->mCondition.wait(self->mutex); 172 } 173 174 return NO_ERROR; 175} 176 177int FramebufferNativeWindow::queueBuffer(android_native_window_t* window, 178 android_native_buffer_t* buffer) 179{ 180 FramebufferNativeWindow* self = getSelf(window); 181 Mutex::Autolock _l(self->mutex); 182 framebuffer_device_t* fb = self->fbDev; 183 buffer_handle_t handle = static_cast<NativeBuffer*>(buffer)->handle; 184 int res = fb->post(fb, handle); 185 self->front = static_cast<NativeBuffer*>(buffer); 186 self->mNumFreeBuffers++; 187 self->mCondition.broadcast(); 188 return res; 189} 190 191// ---------------------------------------------------------------------------- 192}; // namespace android 193// ---------------------------------------------------------------------------- 194 195 196EGLNativeWindowType android_createDisplaySurface(void) 197{ 198 return new android::FramebufferNativeWindow(); 199} 200 201