FramebufferSurface.cpp revision a49126087b4494f4ef50873f3a3f6727265f6621
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#include <stdlib.h> 19#include <stdio.h> 20#include <string.h> 21#include <errno.h> 22 23#include <cutils/log.h> 24 25#include <utils/String8.h> 26 27#include <ui/Rect.h> 28 29#include <EGL/egl.h> 30 31#include <hardware/hardware.h> 32#include <gui/SurfaceTextureClient.h> 33#include <ui/GraphicBuffer.h> 34 35#include "DisplayHardware/FramebufferSurface.h" 36 37// ---------------------------------------------------------------------------- 38namespace android { 39// ---------------------------------------------------------------------------- 40 41sp<FramebufferSurface> FramebufferSurface::create() { 42 sp<FramebufferSurface> result = new FramebufferSurface(); 43 if (result->fbDev == NULL) { 44 result = NULL; 45 } 46 return result; 47} 48 49// ---------------------------------------------------------------------------- 50 51/* 52 * This implements the (main) framebuffer management. This class is used 53 * mostly by SurfaceFlinger, but also by command line GL application. 54 * 55 */ 56 57FramebufferSurface::FramebufferSurface() 58 : SurfaceTextureClient(), 59 fbDev(0), mCurrentBufferIndex(-1), mUpdateOnDemand(false) 60{ 61 hw_module_t const* module; 62 if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) { 63 int stride; 64 int err; 65 int i; 66 err = framebuffer_open(module, &fbDev); 67 ALOGE_IF(err, "couldn't open framebuffer HAL (%s)", strerror(-err)); 68 69 // bail out if we can't initialize the modules 70 if (!fbDev) 71 return; 72 73 mUpdateOnDemand = (fbDev->setUpdateRect != 0); 74 75 const_cast<uint32_t&>(ANativeWindow::flags) = fbDev->flags; 76 const_cast<int&>(ANativeWindow::minSwapInterval) = fbDev->minSwapInterval; 77 const_cast<int&>(ANativeWindow::maxSwapInterval) = fbDev->maxSwapInterval; 78 79 if (fbDev->xdpi == 0 || fbDev->ydpi == 0) { 80 ALOGE("invalid screen resolution from fb HAL (xdpi=%f, ydpi=%f), " 81 "defaulting to 160 dpi", fbDev->xdpi, fbDev->ydpi); 82 const_cast<float&>(ANativeWindow::xdpi) = 160; 83 const_cast<float&>(ANativeWindow::ydpi) = 160; 84 } else { 85 const_cast<float&>(ANativeWindow::xdpi) = fbDev->xdpi; 86 const_cast<float&>(ANativeWindow::ydpi) = fbDev->ydpi; 87 } 88 89 } else { 90 ALOGE("Couldn't get gralloc module"); 91 } 92 93 class GraphicBufferAlloc : public BnGraphicBufferAlloc { 94 public: 95 GraphicBufferAlloc() { }; 96 virtual ~GraphicBufferAlloc() { }; 97 virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h, 98 PixelFormat format, uint32_t usage, status_t* error) { 99 sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h, format, usage)); 100 return graphicBuffer; 101 } 102 }; 103 104 mBufferQueue = new BufferQueue(true, NUM_FRAME_BUFFERS, new GraphicBufferAlloc()); 105 mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_HW_FB|GRALLOC_USAGE_HW_RENDER|GRALLOC_USAGE_HW_COMPOSER); 106 mBufferQueue->setDefaultBufferFormat(fbDev->format); 107 mBufferQueue->setDefaultBufferSize(fbDev->width, fbDev->height); 108 mBufferQueue->setSynchronousMode(true); 109 mBufferQueue->setBufferCountServer(NUM_FRAME_BUFFERS); 110 setISurfaceTexture(mBufferQueue); 111} 112 113void FramebufferSurface::onFirstRef() { 114 class Listener : public BufferQueue::ConsumerListener { 115 const wp<FramebufferSurface> that; 116 virtual ~Listener() { } 117 virtual void onBuffersReleased() { } 118 void onFrameAvailable() { 119 sp<FramebufferSurface> self = that.promote(); 120 if (self != NULL) { 121 BufferQueue::BufferItem item; 122 status_t err = self->mBufferQueue->acquireBuffer(&item); 123 if (err == 0) { 124 if (item.mGraphicBuffer != 0) { 125 self->mBuffers[item.mBuf] = item.mGraphicBuffer; 126 } 127 if (item.mFence.get()) { 128 err = item.mFence->wait(Fence::TIMEOUT_NEVER); 129 if (err) { 130 ALOGE("failed waiting for buffer's fence: %d", err); 131 self->mBufferQueue->releaseBuffer(item.mBuf, 132 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, 133 item.mFence); 134 return; 135 } 136 } 137 self->fbDev->post(self->fbDev, self->mBuffers[item.mBuf]->handle); 138 if (self->mCurrentBufferIndex >= 0) { 139 self->mBufferQueue->releaseBuffer(self->mCurrentBufferIndex, 140 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE); 141 } 142 self->mCurrentBufferIndex = item.mBuf; 143 } 144 } 145 } 146 public: 147 Listener(const sp<FramebufferSurface>& that) : that(that) { } 148 }; 149 150 mBufferQueue->setConsumerName(String8("FramebufferSurface")); 151 mBufferQueue->consumerConnect(new Listener(this)); 152} 153 154FramebufferSurface::~FramebufferSurface() { 155 if (fbDev) { 156 framebuffer_close(fbDev); 157 } 158} 159 160float FramebufferSurface::getRefreshRate() const { 161 /* FIXME: REFRESH_RATE is a temporary HACK until we are able to report the 162 * refresh rate properly from the HAL. The WindowManagerService now relies 163 * on this value. 164 */ 165#ifndef REFRESH_RATE 166 return fbDev->fps; 167#else 168 return REFRESH_RATE; 169#warning "refresh rate set via makefile to REFRESH_RATE" 170#endif 171} 172 173status_t FramebufferSurface::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 FramebufferSurface::compositionComplete() 182{ 183 if (fbDev->compositionComplete) { 184 return fbDev->compositionComplete(fbDev); 185 } 186 return INVALID_OPERATION; 187} 188 189void FramebufferSurface::dump(String8& result) { 190 if (fbDev->common.version >= 1 && fbDev->dump) { 191 const size_t SIZE = 4096; 192 char buffer[SIZE]; 193 194 fbDev->dump(fbDev, buffer, SIZE); 195 result.append(buffer); 196 } 197} 198 199int FramebufferSurface::query(int what, int* value) const { 200 Mutex::Autolock _l(mLock); 201 framebuffer_device_t* fb = fbDev; 202 switch (what) { 203 case NATIVE_WINDOW_DEFAULT_WIDTH: 204 case NATIVE_WINDOW_WIDTH: 205 *value = fb->width; 206 return NO_ERROR; 207 case NATIVE_WINDOW_DEFAULT_HEIGHT: 208 case NATIVE_WINDOW_HEIGHT: 209 *value = fb->height; 210 return NO_ERROR; 211 case NATIVE_WINDOW_FORMAT: 212 *value = fb->format; 213 return NO_ERROR; 214 case NATIVE_WINDOW_CONCRETE_TYPE: 215 *value = NATIVE_WINDOW_FRAMEBUFFER; 216 return NO_ERROR; 217 case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER: 218 *value = 0; 219 return NO_ERROR; 220 case NATIVE_WINDOW_TRANSFORM_HINT: 221 *value = 0; 222 return NO_ERROR; 223 } 224 return SurfaceTextureClient::query(what, value); 225} 226 227// ---------------------------------------------------------------------------- 228}; // namespace android 229// ---------------------------------------------------------------------------- 230