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 #define LOG_TAG "FramebufferNativeWindow"
19
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <errno.h>
24
25 #include <cutils/log.h>
26 #include <cutils/atomic.h>
27 #include <utils/threads.h>
28 #include <utils/RefBase.h>
29
30 #include <ui/ANativeObjectBase.h>
31 #include <ui/Fence.h>
32 #define INCLUDED_FROM_FRAMEBUFFER_NATIVE_WINDOW_CPP
33 #include <ui/FramebufferNativeWindow.h>
34 #undef INCLUDED_FROM_FRAMEBUFFER_NATIVE_WINDOW_CPP
35 #include <ui/Rect.h>
36
37 #include <EGL/egl.h>
38
39 #include <hardware/hardware.h>
40 #include <hardware/gralloc.h>
41
42 // ----------------------------------------------------------------------------
43 namespace android {
44 // ----------------------------------------------------------------------------
45
46 class NativeBuffer final
47 : public ANativeObjectBase<
48 ANativeWindowBuffer,
49 NativeBuffer,
50 LightRefBase<NativeBuffer>>
51 {
52 public:
NativeBuffer(int w,int h,int f,int u)53 NativeBuffer(int w, int h, int f, int u) : BASE() {
54 ANativeWindowBuffer::width = w;
55 ANativeWindowBuffer::height = h;
56 ANativeWindowBuffer::format = f;
57 ANativeWindowBuffer::usage = u;
58 }
59 private:
60 friend class LightRefBase<NativeBuffer>;
61 };
62
63
64 /*
65 * This implements the (main) framebuffer management. This class is used
66 * mostly by SurfaceFlinger, but also by command line GL application.
67 *
68 * In fact this is an implementation of ANativeWindow on top of
69 * the framebuffer.
70 *
71 * Currently it is pretty simple, it manages only two buffers (the front and
72 * back buffer).
73 *
74 */
75
FramebufferNativeWindow()76 FramebufferNativeWindow::FramebufferNativeWindow()
77 : BASE(), fbDev(0), grDev(0), mUpdateOnDemand(false)
78 {
79 hw_module_t const* module;
80 if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {
81 int err;
82 int i;
83 err = framebuffer_open(module, &fbDev);
84 ALOGE_IF(err, "couldn't open framebuffer HAL (%s)", strerror(-err));
85
86 err = gralloc_open(module, &grDev);
87 ALOGE_IF(err, "couldn't open gralloc HAL (%s)", strerror(-err));
88
89 // bail out if we can't initialize the modules
90 if (!fbDev || !grDev)
91 return;
92
93 mUpdateOnDemand = (fbDev->setUpdateRect != 0);
94
95 // initialize the buffer FIFO
96 if(fbDev->numFramebuffers >= MIN_NUM_FRAME_BUFFERS &&
97 fbDev->numFramebuffers <= MAX_NUM_FRAME_BUFFERS){
98 mNumBuffers = fbDev->numFramebuffers;
99 } else {
100 mNumBuffers = MIN_NUM_FRAME_BUFFERS;
101 }
102 mNumFreeBuffers = mNumBuffers;
103 mBufferHead = mNumBuffers-1;
104
105 /*
106 * This does not actually change the framebuffer format. It merely
107 * fakes this format to surfaceflinger so that when it creates
108 * framebuffer surfaces it will use this format. It's really a giant
109 * HACK to allow interworking with buggy gralloc+GPU driver
110 * implementations. You should *NEVER* need to set this for shipping
111 * devices.
112 */
113 #ifdef FRAMEBUFFER_FORCE_FORMAT
114 *((uint32_t *)&fbDev->format) = FRAMEBUFFER_FORCE_FORMAT;
115 #endif
116
117 for (i = 0; i < mNumBuffers; i++) {
118 buffers[i] = new NativeBuffer(
119 static_cast<int>(fbDev->width),
120 static_cast<int>(fbDev->height),
121 fbDev->format, GRALLOC_USAGE_HW_FB);
122 }
123
124 for (i = 0; i < mNumBuffers; i++) {
125 err = grDev->alloc(grDev,
126 static_cast<int>(fbDev->width),
127 static_cast<int>(fbDev->height),
128 fbDev->format, GRALLOC_USAGE_HW_FB,
129 &buffers[i]->handle, &buffers[i]->stride);
130
131 ALOGE_IF(err, "fb buffer %d allocation failed w=%d, h=%d, err=%s",
132 i, fbDev->width, fbDev->height, strerror(-err));
133
134 if (err) {
135 mNumBuffers = i;
136 mNumFreeBuffers = i;
137 mBufferHead = mNumBuffers-1;
138 break;
139 }
140 }
141
142 const_cast<uint32_t&>(ANativeWindow::flags) = fbDev->flags;
143 const_cast<float&>(ANativeWindow::xdpi) = fbDev->xdpi;
144 const_cast<float&>(ANativeWindow::ydpi) = fbDev->ydpi;
145 const_cast<int&>(ANativeWindow::minSwapInterval) =
146 fbDev->minSwapInterval;
147 const_cast<int&>(ANativeWindow::maxSwapInterval) =
148 fbDev->maxSwapInterval;
149 } else {
150 ALOGE("Couldn't get gralloc module");
151 }
152
153 ANativeWindow::setSwapInterval = setSwapInterval;
154 ANativeWindow::dequeueBuffer = dequeueBuffer;
155 ANativeWindow::queueBuffer = queueBuffer;
156 ANativeWindow::query = query;
157 ANativeWindow::perform = perform;
158
159 ANativeWindow::dequeueBuffer_DEPRECATED = dequeueBuffer_DEPRECATED;
160 ANativeWindow::lockBuffer_DEPRECATED = lockBuffer_DEPRECATED;
161 ANativeWindow::queueBuffer_DEPRECATED = queueBuffer_DEPRECATED;
162 }
163
~FramebufferNativeWindow()164 FramebufferNativeWindow::~FramebufferNativeWindow()
165 {
166 if (grDev) {
167 for(int i = 0; i < mNumBuffers; i++) {
168 if (buffers[i] != NULL) {
169 grDev->free(grDev, buffers[i]->handle);
170 }
171 }
172 gralloc_close(grDev);
173 }
174
175 if (fbDev) {
176 framebuffer_close(fbDev);
177 }
178 }
179
setUpdateRectangle(const Rect & r)180 status_t FramebufferNativeWindow::setUpdateRectangle(const Rect& r)
181 {
182 if (!mUpdateOnDemand) {
183 return INVALID_OPERATION;
184 }
185 return fbDev->setUpdateRect(fbDev, r.left, r.top, r.width(), r.height());
186 }
187
compositionComplete()188 status_t FramebufferNativeWindow::compositionComplete()
189 {
190 if (fbDev->compositionComplete) {
191 return fbDev->compositionComplete(fbDev);
192 }
193 return INVALID_OPERATION;
194 }
195
setSwapInterval(ANativeWindow * window,int interval)196 int FramebufferNativeWindow::setSwapInterval(
197 ANativeWindow* window, int interval)
198 {
199 framebuffer_device_t* fb = getSelf(window)->fbDev;
200 return fb->setSwapInterval(fb, interval);
201 }
202
dump(String8 & result)203 void FramebufferNativeWindow::dump(String8& result) {
204 if (fbDev->common.version >= 1 && fbDev->dump) {
205 const size_t SIZE = 4096;
206 char buffer[SIZE];
207
208 fbDev->dump(fbDev, buffer, SIZE);
209 result.append(buffer);
210 }
211 }
212
213 // only for debugging / logging
getCurrentBufferIndex() const214 int FramebufferNativeWindow::getCurrentBufferIndex() const
215 {
216 Mutex::Autolock _l(mutex);
217 const int index = mCurrentBufferIndex;
218 return index;
219 }
220
dequeueBuffer_DEPRECATED(ANativeWindow * window,ANativeWindowBuffer ** buffer)221 int FramebufferNativeWindow::dequeueBuffer_DEPRECATED(ANativeWindow* window,
222 ANativeWindowBuffer** buffer)
223 {
224 int fenceFd = -1;
225 int result = dequeueBuffer(window, buffer, &fenceFd);
226 sp<Fence> fence(new Fence(fenceFd));
227 int waitResult = fence->wait(Fence::TIMEOUT_NEVER);
228 if (waitResult != OK) {
229 ALOGE("dequeueBuffer_DEPRECATED: Fence::wait returned an "
230 "error: %d", waitResult);
231 return waitResult;
232 }
233 return result;
234 }
235
dequeueBuffer(ANativeWindow * window,ANativeWindowBuffer ** buffer,int * fenceFd)236 int FramebufferNativeWindow::dequeueBuffer(ANativeWindow* window,
237 ANativeWindowBuffer** buffer, int* fenceFd)
238 {
239 FramebufferNativeWindow* self = getSelf(window);
240 Mutex::Autolock _l(self->mutex);
241
242 int index = self->mBufferHead++;
243 if (self->mBufferHead >= self->mNumBuffers)
244 self->mBufferHead = 0;
245
246 // wait for a free non-front buffer
247 while (self->mNumFreeBuffers < 2) {
248 self->mCondition.wait(self->mutex);
249 }
250 ALOG_ASSERT(self->buffers[index] != self->front, "");
251
252 // get this buffer
253 self->mNumFreeBuffers--;
254 self->mCurrentBufferIndex = index;
255
256 *buffer = self->buffers[index].get();
257 *fenceFd = -1;
258
259 return 0;
260 }
261
lockBuffer_DEPRECATED(ANativeWindow *,ANativeWindowBuffer *)262 int FramebufferNativeWindow::lockBuffer_DEPRECATED(ANativeWindow* /*window*/,
263 ANativeWindowBuffer* /*buffer*/)
264 {
265 return NO_ERROR;
266 }
267
queueBuffer_DEPRECATED(ANativeWindow * window,ANativeWindowBuffer * buffer)268 int FramebufferNativeWindow::queueBuffer_DEPRECATED(ANativeWindow* window,
269 ANativeWindowBuffer* buffer)
270 {
271 return queueBuffer(window, buffer, -1);
272 }
273
queueBuffer(ANativeWindow * window,ANativeWindowBuffer * buffer,int fenceFd)274 int FramebufferNativeWindow::queueBuffer(ANativeWindow* window,
275 ANativeWindowBuffer* buffer, int fenceFd)
276 {
277 FramebufferNativeWindow* self = getSelf(window);
278 Mutex::Autolock _l(self->mutex);
279 framebuffer_device_t* fb = self->fbDev;
280 buffer_handle_t handle = static_cast<NativeBuffer*>(buffer)->handle;
281
282 sp<Fence> fence(new Fence(fenceFd));
283 fence->wait(Fence::TIMEOUT_NEVER);
284
285 int res = fb->post(fb, handle);
286 self->front = static_cast<NativeBuffer*>(buffer);
287 self->mNumFreeBuffers++;
288 self->mCondition.broadcast();
289 return res;
290 }
291
query(const ANativeWindow * window,int what,int * value)292 int FramebufferNativeWindow::query(const ANativeWindow* window,
293 int what, int* value)
294 {
295 const FramebufferNativeWindow* self = getSelf(window);
296 Mutex::Autolock _l(self->mutex);
297 framebuffer_device_t* fb = self->fbDev;
298 switch (what) {
299 case NATIVE_WINDOW_WIDTH:
300 *value = static_cast<int>(fb->width);
301 return NO_ERROR;
302 case NATIVE_WINDOW_HEIGHT:
303 *value = static_cast<int>(fb->height);
304 return NO_ERROR;
305 case NATIVE_WINDOW_FORMAT:
306 *value = fb->format;
307 return NO_ERROR;
308 case NATIVE_WINDOW_CONCRETE_TYPE:
309 *value = NATIVE_WINDOW_FRAMEBUFFER;
310 return NO_ERROR;
311 case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER:
312 *value = 0;
313 return NO_ERROR;
314 case NATIVE_WINDOW_DEFAULT_WIDTH:
315 *value = static_cast<int>(fb->width);
316 return NO_ERROR;
317 case NATIVE_WINDOW_DEFAULT_HEIGHT:
318 *value = static_cast<int>(fb->height);
319 return NO_ERROR;
320 case NATIVE_WINDOW_TRANSFORM_HINT:
321 *value = 0;
322 return NO_ERROR;
323 }
324 *value = 0;
325 return BAD_VALUE;
326 }
327
perform(ANativeWindow *,int operation,...)328 int FramebufferNativeWindow::perform(ANativeWindow* /*window*/,
329 int operation, ...)
330 {
331 switch (operation) {
332 case NATIVE_WINDOW_CONNECT:
333 case NATIVE_WINDOW_DISCONNECT:
334 case NATIVE_WINDOW_SET_USAGE:
335 case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY:
336 case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS:
337 case NATIVE_WINDOW_SET_BUFFERS_FORMAT:
338 case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
339 case NATIVE_WINDOW_API_CONNECT:
340 case NATIVE_WINDOW_API_DISCONNECT:
341 // TODO: we should implement these
342 return NO_ERROR;
343
344 case NATIVE_WINDOW_LOCK:
345 case NATIVE_WINDOW_UNLOCK_AND_POST:
346 case NATIVE_WINDOW_SET_CROP:
347 case NATIVE_WINDOW_SET_BUFFER_COUNT:
348 case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
349 case NATIVE_WINDOW_SET_SCALING_MODE:
350 return INVALID_OPERATION;
351 }
352 return NAME_NOT_FOUND;
353 }
354
355 // ----------------------------------------------------------------------------
356 }; // namespace android
357 // ----------------------------------------------------------------------------
358
359 using android::sp;
360 using android::FramebufferNativeWindow;
361
android_createDisplaySurface(void)362 EGLNativeWindowType android_createDisplaySurface(void)
363 {
364 FramebufferNativeWindow* w;
365 w = new FramebufferNativeWindow();
366 if (w->getDevice() == NULL) {
367 // get a ref so it can be destroyed when we exit this block
368 sp<FramebufferNativeWindow> ref(w);
369 return NULL;
370 }
371 return static_cast<EGLNativeWindowType>(w);
372 }
373