• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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