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