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