blob: 6cfb190f2aaeae59813330251b0d38eec1136a28 [file] [log] [blame]
Mathias Agopian3e876012012-06-07 17:52:54 -07001/*
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 }
Jesse Hallb42b1ac2012-06-28 14:27:53 -0700109 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 }
Mathias Agopian3e876012012-06-07 17:52:54 -0700119 self->fbDev->post(self->fbDev, self->mBuffers[item.mBuf]->handle);
120 if (self->mCurrentBufferIndex >= 0) {
121 self->mBufferQueue->releaseBuffer(self->mCurrentBufferIndex,
Jesse Hallef194142012-06-14 14:45:17 -0700122 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE);
Mathias Agopian3e876012012-06-07 17:52:54 -0700123 }
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// ----------------------------------------------------------------------------