FramebufferSurface.cpp revision 3e87601170141229d661df93e2f59e1ced73474b
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 41 42/* 43 * This implements the (main) framebuffer management. This class is used 44 * mostly by SurfaceFlinger, but also by command line GL application. 45 * 46 */ 47 48FramebufferSurface::FramebufferSurface() 49 : SurfaceTextureClient(), 50 fbDev(0), mCurrentBufferIndex(-1), mUpdateOnDemand(false) 51{ 52 hw_module_t const* module; 53 if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) { 54 int stride; 55 int err; 56 int i; 57 err = framebuffer_open(module, &fbDev); 58 ALOGE_IF(err, "couldn't open framebuffer HAL (%s)", strerror(-err)); 59 60 // bail out if we can't initialize the modules 61 if (!fbDev) 62 return; 63 64 mUpdateOnDemand = (fbDev->setUpdateRect != 0); 65 66 const_cast<uint32_t&>(ANativeWindow::flags) = fbDev->flags; 67 const_cast<float&>(ANativeWindow::xdpi) = fbDev->xdpi; 68 const_cast<float&>(ANativeWindow::ydpi) = fbDev->ydpi; 69 const_cast<int&>(ANativeWindow::minSwapInterval) = fbDev->minSwapInterval; 70 const_cast<int&>(ANativeWindow::maxSwapInterval) = fbDev->maxSwapInterval; 71 } else { 72 ALOGE("Couldn't get gralloc module"); 73 } 74 75 class GraphicBufferAlloc : public BnGraphicBufferAlloc { 76 public: 77 GraphicBufferAlloc() { }; 78 virtual ~GraphicBufferAlloc() { }; 79 virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h, 80 PixelFormat format, uint32_t usage, status_t* error) { 81 sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h, format, usage)); 82 return graphicBuffer; 83 } 84 }; 85 86 mBufferQueue = new BufferQueue(true, NUM_FRAME_BUFFERS, new GraphicBufferAlloc()); 87 mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_HW_FB|GRALLOC_USAGE_HW_RENDER|GRALLOC_USAGE_HW_COMPOSER); 88 mBufferQueue->setDefaultBufferFormat(fbDev->format); 89 mBufferQueue->setDefaultBufferSize(fbDev->width, fbDev->height); 90 mBufferQueue->setSynchronousMode(true); 91 mBufferQueue->setBufferCountServer(NUM_FRAME_BUFFERS); 92 setISurfaceTexture(mBufferQueue); 93} 94 95void FramebufferSurface::onFirstRef() { 96 class Listener : public BufferQueue::ConsumerListener { 97 const wp<FramebufferSurface> that; 98 virtual ~Listener() { } 99 virtual void onBuffersReleased() { } 100 void onFrameAvailable() { 101 sp<FramebufferSurface> self = that.promote(); 102 if (self != NULL) { 103 BufferQueue::BufferItem item; 104 status_t err = self->mBufferQueue->acquireBuffer(&item); 105 if (err == 0) { 106 if (item.mGraphicBuffer != 0) { 107 self->mBuffers[item.mBuf] = item.mGraphicBuffer; 108 } 109 self->fbDev->post(self->fbDev, self->mBuffers[item.mBuf]->handle); 110 if (self->mCurrentBufferIndex >= 0) { 111 self->mBufferQueue->releaseBuffer(self->mCurrentBufferIndex, 112 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR); 113 } 114 self->mCurrentBufferIndex = item.mBuf; 115 } 116 } 117 } 118 public: 119 Listener(const sp<FramebufferSurface>& that) : that(that) { } 120 }; 121 122 mBufferQueue->setConsumerName(String8("FramebufferSurface")); 123 mBufferQueue->consumerConnect(new Listener(this)); 124} 125 126FramebufferSurface::~FramebufferSurface() { 127 if (fbDev) { 128 framebuffer_close(fbDev); 129 } 130} 131 132status_t FramebufferSurface::setUpdateRectangle(const Rect& r) 133{ 134 if (!mUpdateOnDemand) { 135 return INVALID_OPERATION; 136 } 137 return fbDev->setUpdateRect(fbDev, r.left, r.top, r.width(), r.height()); 138} 139 140status_t FramebufferSurface::compositionComplete() 141{ 142 if (fbDev->compositionComplete) { 143 return fbDev->compositionComplete(fbDev); 144 } 145 return INVALID_OPERATION; 146} 147 148void FramebufferSurface::dump(String8& result) { 149 if (fbDev->common.version >= 1 && fbDev->dump) { 150 const size_t SIZE = 4096; 151 char buffer[SIZE]; 152 153 fbDev->dump(fbDev, buffer, SIZE); 154 result.append(buffer); 155 } 156} 157 158int FramebufferSurface::query(int what, int* value) const { 159 Mutex::Autolock _l(mLock); 160 framebuffer_device_t* fb = fbDev; 161 switch (what) { 162 case NATIVE_WINDOW_DEFAULT_WIDTH: 163 case NATIVE_WINDOW_WIDTH: 164 *value = fb->width; 165 return NO_ERROR; 166 case NATIVE_WINDOW_DEFAULT_HEIGHT: 167 case NATIVE_WINDOW_HEIGHT: 168 *value = fb->height; 169 return NO_ERROR; 170 case NATIVE_WINDOW_FORMAT: 171 *value = fb->format; 172 return NO_ERROR; 173 case NATIVE_WINDOW_CONCRETE_TYPE: 174 *value = NATIVE_WINDOW_FRAMEBUFFER; 175 return NO_ERROR; 176 case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER: 177 *value = 0; 178 return NO_ERROR; 179 case NATIVE_WINDOW_TRANSFORM_HINT: 180 *value = 0; 181 return NO_ERROR; 182 } 183 return SurfaceTextureClient::query(what, value); 184} 185 186// ---------------------------------------------------------------------------- 187}; // namespace android 188// ---------------------------------------------------------------------------- 189