FramebufferNativeWindow.cpp revision 0926f50664c739eaee60341f8e8c694dc9a4f3eb
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// ---------------------------------------------------------------------------- 42namespace android { 43// ---------------------------------------------------------------------------- 44 45/* 46 * This implements the (main) framebuffer management. This class is used 47 * mostly by SurfaceFlinger, but also by command line GL application. 48 * 49 * In fact this is an implementation of android_native_window_t on top of 50 * the framebuffer. 51 * 52 * Currently it is pretty simple, it manages only two buffers (the front and 53 * back buffer). 54 * 55 */ 56 57FramebufferNativeWindow::FramebufferNativeWindow() 58 : BASE(), fbDev(0), grDev(0) 59{ 60 hw_module_t const* module; 61 if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) { 62 int stride; 63 framebuffer_open(module, &fbDev); 64 gralloc_open(module, &grDev); 65 int err; 66 67 68 // initialize the buffer FIFO 69 mNumBuffers = 2; 70 mNumFreeBuffers = 2; 71 mBufferHead = mNumBuffers-1; 72 buffers[0] = new NativeBuffer( 73 fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB); 74 buffers[1] = new NativeBuffer( 75 fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB); 76 77 err = grDev->alloc(grDev, 78 fbDev->width, fbDev->height, fbDev->format, 79 GRALLOC_USAGE_HW_FB, &buffers[0]->handle, &buffers[0]->stride); 80 81 LOGE_IF(err, "fb buffer 0 allocation failed w=%d, h=%d, err=%s", 82 fbDev->width, fbDev->height, strerror(-err)); 83 84 err = grDev->alloc(grDev, 85 fbDev->width, fbDev->height, fbDev->format, 86 GRALLOC_USAGE_HW_FB, &buffers[1]->handle, &buffers[1]->stride); 87 88 LOGE_IF(err, "fb buffer 1 allocation failed w=%d, h=%d, err=%s", 89 fbDev->width, fbDev->height, strerror(-err)); 90 } 91 92 uint32_t flags = fbDev->flags & SURFACE_FLAG_MAPPED; 93 94 /* 95 * FIXME: SURFACE_FLAG_PRESERVE_CONTENT 96 * how to implement this, there is no concept of preserve content in 97 * the framebuffer, which just "posts" buffer. 98 * 99 * It looks like what we need is a way to know if the posted buffer can 100 * be reused. But if so, why allocating 2 buffers?... 101 * 102 * should the lock/unlock calls take care of the copy-back? 103 * 104 * 105 * In the end, the client wants to know if the backbuffer is preserved 106 * though... it's complicated. 107 * 108 */ 109 110 //flags |= SURFACE_FLAG_PRESERVE_CONTENT; 111 112 113 const_cast<uint32_t&>(android_native_window_t::flags) = 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 134void FramebufferNativeWindow::connect(android_native_window_t* window) 135{ 136} 137 138void FramebufferNativeWindow::disconnect(android_native_window_t* window) 139{ 140} 141 142int FramebufferNativeWindow::setSwapInterval( 143 android_native_window_t* window, int interval) 144{ 145 framebuffer_device_t* fb = getSelf(window)->fbDev; 146 return fb->setSwapInterval(fb, interval); 147} 148 149void FramebufferNativeWindow::setSwapRectangle(const Rect& dirty) 150{ 151 Mutex::Autolock _l(mutex); 152 mDirty = dirty; 153} 154 155int FramebufferNativeWindow::dequeueBuffer(android_native_window_t* window, 156 android_native_buffer_t** buffer) 157{ 158 FramebufferNativeWindow* self = getSelf(window); 159 Mutex::Autolock _l(self->mutex); 160 framebuffer_device_t* fb = self->fbDev; 161 162 // wait for a free buffer 163 while (!self->mNumFreeBuffers) { 164 self->mCondition.wait(self->mutex); 165 } 166 // get this buffer 167 self->mNumFreeBuffers--; 168 int index = self->mBufferHead++; 169 if (self->mBufferHead >= self->mNumBuffers) 170 self->mBufferHead = 0; 171 172 *buffer = self->buffers[index].get(); 173 174 return 0; 175} 176 177int FramebufferNativeWindow::lockBuffer(android_native_window_t* window, 178 android_native_buffer_t* buffer) 179{ 180 FramebufferNativeWindow* self = getSelf(window); 181 Mutex::Autolock _l(self->mutex); 182 183 // wait that the buffer we're locking is not front anymore 184 while (self->front == buffer) { 185 self->mCondition.wait(self->mutex); 186 } 187 188 return NO_ERROR; 189} 190 191int FramebufferNativeWindow::queueBuffer(android_native_window_t* window, 192 android_native_buffer_t* buffer) 193{ 194 FramebufferNativeWindow* self = getSelf(window); 195 Mutex::Autolock _l(self->mutex); 196 framebuffer_device_t* fb = self->fbDev; 197 buffer_handle_t handle = static_cast<NativeBuffer*>(buffer)->handle; 198 int res = fb->post(fb, handle); 199 self->front = static_cast<NativeBuffer*>(buffer); 200 self->mNumFreeBuffers++; 201 self->mCondition.broadcast(); 202 return res; 203} 204 205// ---------------------------------------------------------------------------- 206}; // namespace android 207// ---------------------------------------------------------------------------- 208 209 210EGLNativeWindowType android_createDisplaySurface(void) 211{ 212 return new android::FramebufferNativeWindow(); 213} 214 215