FramebufferSurface.cpp revision b27254154642575dfb4bbfa79fbedde7d7ee23dd
1/* 2 ** 3 ** Copyright 2012 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 51class GraphicBufferAlloc : public BnGraphicBufferAlloc { 52public: 53 GraphicBufferAlloc() { }; 54 virtual ~GraphicBufferAlloc() { }; 55 virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h, 56 PixelFormat format, uint32_t usage, status_t* error) { 57 sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h, format, usage)); 58 return graphicBuffer; 59 } 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 */ 68 69FramebufferSurface::FramebufferSurface(): 70 ConsumerBase(new BufferQueue(true, new GraphicBufferAlloc())), 71 fbDev(0), 72 mCurrentBufferSlot(-1), 73 mCurrentBuffer(0) 74{ 75 hw_module_t const* module; 76 77 if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) { 78 int stride; 79 int err; 80 int i; 81 err = framebuffer_open(module, &fbDev); 82 ALOGE_IF(err, "couldn't open framebuffer HAL (%s)", strerror(-err)); 83 84 // bail out if we can't initialize the modules 85 if (!fbDev) 86 return; 87 88 mName = "FramebufferSurface"; 89 mBufferQueue->setConsumerName(mName); 90 mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_HW_FB | 91 GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_COMPOSER); 92 mBufferQueue->setDefaultBufferFormat(fbDev->format); 93 mBufferQueue->setDefaultBufferSize(fbDev->width, fbDev->height); 94 mBufferQueue->setSynchronousMode(true); 95 mBufferQueue->setDefaultMaxBufferCount(NUM_FRAME_BUFFERS); 96 } else { 97 ALOGE("Couldn't get gralloc module"); 98 } 99} 100 101status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>* buffer) { 102 Mutex::Autolock lock(mMutex); 103 104 BufferQueue::BufferItem item; 105 status_t err = acquireBufferLocked(&item); 106 if (err == BufferQueue::NO_BUFFER_AVAILABLE) { 107 if (buffer != NULL) { 108 *buffer = mCurrentBuffer; 109 } 110 return NO_ERROR; 111 } else if (err != NO_ERROR) { 112 ALOGE("error acquiring buffer: %s (%d)", strerror(-err), err); 113 return err; 114 } 115 116 // If the BufferQueue has freed and reallocated a buffer in mCurrentSlot 117 // then we may have acquired the slot we already own. If we had released 118 // our current buffer before we call acquireBuffer then that release call 119 // would have returned STALE_BUFFER_SLOT, and we would have called 120 // freeBufferLocked on that slot. Because the buffer slot has already 121 // been overwritten with the new buffer all we have to do is skip the 122 // releaseBuffer call and we should be in the same state we'd be in if we 123 // had released the old buffer first. 124 if (mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT && 125 item.mBuf != mCurrentBufferSlot) { 126 // Release the previous buffer. 127 err = releaseBufferLocked(mCurrentBufferSlot, EGL_NO_DISPLAY, 128 EGL_NO_SYNC_KHR); 129 if (err != NO_ERROR && err != BufferQueue::STALE_BUFFER_SLOT) { 130 ALOGE("error releasing buffer: %s (%d)", strerror(-err), err); 131 return err; 132 } 133 } 134 135 mCurrentBufferSlot = item.mBuf; 136 mCurrentBuffer = mSlots[mCurrentBufferSlot].mGraphicBuffer; 137 if (item.mFence != NULL) { 138 item.mFence->wait(Fence::TIMEOUT_NEVER); 139 } 140 141 if (buffer != NULL) { 142 *buffer = mCurrentBuffer; 143 } 144 145 return NO_ERROR; 146} 147 148FramebufferSurface::~FramebufferSurface() { 149 if (fbDev) { 150 framebuffer_close(fbDev); 151 } 152} 153 154void FramebufferSurface::onFrameAvailable() { 155 // XXX: The following code is here temporarily as part of the transition 156 // away from the framebuffer HAL. 157 sp<GraphicBuffer> buf; 158 status_t err = nextBuffer(&buf); 159 if (err != NO_ERROR) { 160 ALOGE("error latching next FramebufferSurface buffer: %s (%d)", 161 strerror(-err), err); 162 return; 163 } 164 err = fbDev->post(fbDev, buf->handle); 165 if (err != NO_ERROR) { 166 ALOGE("error posting framebuffer: %d", err); 167 } 168} 169 170void FramebufferSurface::freeBufferLocked(int slotIndex) { 171 ConsumerBase::freeBufferLocked(slotIndex); 172 if (slotIndex == mCurrentBufferSlot) { 173 mCurrentBufferSlot = BufferQueue::INVALID_BUFFER_SLOT; 174 } 175} 176 177status_t FramebufferSurface::setUpdateRectangle(const Rect& r) 178{ 179 return INVALID_OPERATION; 180} 181 182status_t FramebufferSurface::compositionComplete() 183{ 184 if (fbDev->compositionComplete) { 185 return fbDev->compositionComplete(fbDev); 186 } 187 return INVALID_OPERATION; 188} 189 190void FramebufferSurface::dump(String8& result) { 191 if (fbDev->common.version >= 1 && fbDev->dump) { 192 const size_t SIZE = 4096; 193 char buffer[SIZE]; 194 fbDev->dump(fbDev, buffer, SIZE); 195 result.append(buffer); 196 } 197 ConsumerBase::dump(result); 198} 199 200// ---------------------------------------------------------------------------- 201}; // namespace android 202// ---------------------------------------------------------------------------- 203