FramebufferSurface.cpp revision b42b1ac1587aebda5e2f334d95b620271fafba4e
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                    if (item.mFence.get()) {
110                        err = item.mFence->wait(Fence::TIMEOUT_NEVER);
111                        if (err) {
112                            ALOGE("failed waiting for buffer's fence: %d", err);
113                            self->mBufferQueue->releaseBuffer(item.mBuf,
114                                    EGL_NO_DISPLAY, EGL_NO_SYNC_KHR,
115                                    item.mFence);
116                            return;
117                        }
118                    }
119                    self->fbDev->post(self->fbDev, self->mBuffers[item.mBuf]->handle);
120                    if (self->mCurrentBufferIndex >= 0) {
121                        self->mBufferQueue->releaseBuffer(self->mCurrentBufferIndex,
122                                EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE);
123                    }
124                    self->mCurrentBufferIndex = item.mBuf;
125                }
126            }
127        }
128    public:
129        Listener(const sp<FramebufferSurface>& that) : that(that) { }
130    };
131
132    mBufferQueue->setConsumerName(String8("FramebufferSurface"));
133    mBufferQueue->consumerConnect(new Listener(this));
134}
135
136FramebufferSurface::~FramebufferSurface() {
137    if (fbDev) {
138        framebuffer_close(fbDev);
139    }
140}
141
142status_t FramebufferSurface::setUpdateRectangle(const Rect& r)
143{
144    if (!mUpdateOnDemand) {
145        return INVALID_OPERATION;
146    }
147    return fbDev->setUpdateRect(fbDev, r.left, r.top, r.width(), r.height());
148}
149
150status_t FramebufferSurface::compositionComplete()
151{
152    if (fbDev->compositionComplete) {
153        return fbDev->compositionComplete(fbDev);
154    }
155    return INVALID_OPERATION;
156}
157
158void FramebufferSurface::dump(String8& result) {
159    if (fbDev->common.version >= 1 && fbDev->dump) {
160        const size_t SIZE = 4096;
161        char buffer[SIZE];
162
163        fbDev->dump(fbDev, buffer, SIZE);
164        result.append(buffer);
165    }
166}
167
168int FramebufferSurface::query(int what, int* value) const {
169    Mutex::Autolock _l(mLock);
170    framebuffer_device_t* fb = fbDev;
171    switch (what) {
172        case NATIVE_WINDOW_DEFAULT_WIDTH:
173        case NATIVE_WINDOW_WIDTH:
174            *value = fb->width;
175            return NO_ERROR;
176        case NATIVE_WINDOW_DEFAULT_HEIGHT:
177        case NATIVE_WINDOW_HEIGHT:
178            *value = fb->height;
179            return NO_ERROR;
180        case NATIVE_WINDOW_FORMAT:
181            *value = fb->format;
182            return NO_ERROR;
183        case NATIVE_WINDOW_CONCRETE_TYPE:
184            *value = NATIVE_WINDOW_FRAMEBUFFER;
185            return NO_ERROR;
186        case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER:
187            *value = 0;
188            return NO_ERROR;
189        case NATIVE_WINDOW_TRANSFORM_HINT:
190            *value = 0;
191            return NO_ERROR;
192    }
193    return SurfaceTextureClient::query(what, value);
194}
195
196// ----------------------------------------------------------------------------
197}; // namespace android
198// ----------------------------------------------------------------------------
199