blob: 7695e7fd03215169f62946a73c545e7643e16a26 [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
Mathias Agopiana4912602012-07-12 14:25:33 -070041sp<FramebufferSurface> FramebufferSurface::create() {
42 sp<FramebufferSurface> result = new FramebufferSurface();
43 if (result->fbDev == NULL) {
44 result = NULL;
45 }
46 return result;
47}
48
49// ----------------------------------------------------------------------------
Mathias Agopian3e876012012-06-07 17:52:54 -070050
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;
Mathias Agopian3e876012012-06-07 17:52:54 -070076 const_cast<int&>(ANativeWindow::minSwapInterval) = fbDev->minSwapInterval;
77 const_cast<int&>(ANativeWindow::maxSwapInterval) = fbDev->maxSwapInterval;
Mathias Agopiana4912602012-07-12 14:25:33 -070078
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
Mathias Agopian3e876012012-06-07 17:52:54 -070089 } 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 }
Jesse Hallb42b1ac2012-06-28 14:27:53 -0700127 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 }
Mathias Agopian3e876012012-06-07 17:52:54 -0700137 self->fbDev->post(self->fbDev, self->mBuffers[item.mBuf]->handle);
138 if (self->mCurrentBufferIndex >= 0) {
139 self->mBufferQueue->releaseBuffer(self->mCurrentBufferIndex,
Jesse Hallef194142012-06-14 14:45:17 -0700140 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE);
Mathias Agopian3e876012012-06-07 17:52:54 -0700141 }
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
Mathias Agopiana4912602012-07-12 14:25:33 -0700160float 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
Mathias Agopian3e876012012-06-07 17:52:54 -0700173status_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// ----------------------------------------------------------------------------