FramebufferSurface.cpp revision ef19414bd8b77a26f5751f3845be79025a8263fe
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, Fence::NO_FENCE);
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