Home | History | Annotate | Download | only in ui
      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/Rect.h>
     31 #include <ui/FramebufferNativeWindow.h>
     32 #include <ui/GraphicLog.h>
     33 
     34 #include <EGL/egl.h>
     35 
     36 #include <pixelflinger/format.h>
     37 #include <pixelflinger/pixelflinger.h>
     38 
     39 #include <hardware/hardware.h>
     40 #include <hardware/gralloc.h>
     41 
     42 #include <private/ui/android_natives_priv.h>
     43 
     44 // ----------------------------------------------------------------------------
     45 namespace android {
     46 // ----------------------------------------------------------------------------
     47 
     48 class NativeBuffer
     49     : public EGLNativeBase<
     50         android_native_buffer_t,
     51         NativeBuffer,
     52         LightRefBase<NativeBuffer> >
     53 {
     54 public:
     55     NativeBuffer(int w, int h, int f, int u) : BASE() {
     56         android_native_buffer_t::width  = w;
     57         android_native_buffer_t::height = h;
     58         android_native_buffer_t::format = f;
     59         android_native_buffer_t::usage  = u;
     60     }
     61 private:
     62     friend class LightRefBase<NativeBuffer>;
     63     ~NativeBuffer() { }; // this class cannot be overloaded
     64 };
     65 
     66 
     67 /*
     68  * This implements the (main) framebuffer management. This class is used
     69  * mostly by SurfaceFlinger, but also by command line GL application.
     70  *
     71  * In fact this is an implementation of ANativeWindow on top of
     72  * the framebuffer.
     73  *
     74  * Currently it is pretty simple, it manages only two buffers (the front and
     75  * back buffer).
     76  *
     77  */
     78 
     79 FramebufferNativeWindow::FramebufferNativeWindow()
     80     : BASE(), fbDev(0), grDev(0), mUpdateOnDemand(false)
     81 {
     82     hw_module_t const* module;
     83     if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {
     84         int stride;
     85         int err;
     86         err = framebuffer_open(module, &fbDev);
     87         LOGE_IF(err, "couldn't open framebuffer HAL (%s)", strerror(-err));
     88 
     89         err = gralloc_open(module, &grDev);
     90         LOGE_IF(err, "couldn't open gralloc HAL (%s)", strerror(-err));
     91 
     92         // bail out if we can't initialize the modules
     93         if (!fbDev || !grDev)
     94             return;
     95 
     96         mUpdateOnDemand = (fbDev->setUpdateRect != 0);
     97 
     98         // initialize the buffer FIFO
     99         mNumBuffers = 2;
    100         mNumFreeBuffers = 2;
    101         mBufferHead = mNumBuffers-1;
    102         buffers[0] = new NativeBuffer(
    103                 fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB);
    104         buffers[1] = new NativeBuffer(
    105                 fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB);
    106 
    107         err = grDev->alloc(grDev,
    108                 fbDev->width, fbDev->height, fbDev->format,
    109                 GRALLOC_USAGE_HW_FB, &buffers[0]->handle, &buffers[0]->stride);
    110 
    111         LOGE_IF(err, "fb buffer 0 allocation failed w=%d, h=%d, err=%s",
    112                 fbDev->width, fbDev->height, strerror(-err));
    113 
    114         err = grDev->alloc(grDev,
    115                 fbDev->width, fbDev->height, fbDev->format,
    116                 GRALLOC_USAGE_HW_FB, &buffers[1]->handle, &buffers[1]->stride);
    117 
    118         LOGE_IF(err, "fb buffer 1 allocation failed w=%d, h=%d, err=%s",
    119                 fbDev->width, fbDev->height, strerror(-err));
    120 
    121         const_cast<uint32_t&>(ANativeWindow::flags) = fbDev->flags;
    122         const_cast<float&>(ANativeWindow::xdpi) = fbDev->xdpi;
    123         const_cast<float&>(ANativeWindow::ydpi) = fbDev->ydpi;
    124         const_cast<int&>(ANativeWindow::minSwapInterval) =
    125             fbDev->minSwapInterval;
    126         const_cast<int&>(ANativeWindow::maxSwapInterval) =
    127             fbDev->maxSwapInterval;
    128     } else {
    129         LOGE("Couldn't get gralloc module");
    130     }
    131 
    132     ANativeWindow::setSwapInterval = setSwapInterval;
    133     ANativeWindow::dequeueBuffer = dequeueBuffer;
    134     ANativeWindow::lockBuffer = lockBuffer;
    135     ANativeWindow::queueBuffer = queueBuffer;
    136     ANativeWindow::query = query;
    137     ANativeWindow::perform = perform;
    138 }
    139 
    140 FramebufferNativeWindow::~FramebufferNativeWindow()
    141 {
    142     if (grDev) {
    143         if (buffers[0] != NULL)
    144             grDev->free(grDev, buffers[0]->handle);
    145         if (buffers[1] != NULL)
    146             grDev->free(grDev, buffers[1]->handle);
    147         gralloc_close(grDev);
    148     }
    149 
    150     if (fbDev) {
    151         framebuffer_close(fbDev);
    152     }
    153 }
    154 
    155 status_t FramebufferNativeWindow::setUpdateRectangle(const Rect& r)
    156 {
    157     if (!mUpdateOnDemand) {
    158         return INVALID_OPERATION;
    159     }
    160     return fbDev->setUpdateRect(fbDev, r.left, r.top, r.width(), r.height());
    161 }
    162 
    163 status_t FramebufferNativeWindow::compositionComplete()
    164 {
    165     if (fbDev->compositionComplete) {
    166         return fbDev->compositionComplete(fbDev);
    167     }
    168     return INVALID_OPERATION;
    169 }
    170 
    171 int FramebufferNativeWindow::setSwapInterval(
    172         ANativeWindow* window, int interval)
    173 {
    174     framebuffer_device_t* fb = getSelf(window)->fbDev;
    175     return fb->setSwapInterval(fb, interval);
    176 }
    177 
    178 // only for debugging / logging
    179 int FramebufferNativeWindow::getCurrentBufferIndex() const
    180 {
    181     Mutex::Autolock _l(mutex);
    182     const int index = mCurrentBufferIndex;
    183     return index;
    184 }
    185 
    186 int FramebufferNativeWindow::dequeueBuffer(ANativeWindow* window,
    187         android_native_buffer_t** buffer)
    188 {
    189     FramebufferNativeWindow* self = getSelf(window);
    190     Mutex::Autolock _l(self->mutex);
    191     framebuffer_device_t* fb = self->fbDev;
    192 
    193     int index = self->mBufferHead++;
    194     if (self->mBufferHead >= self->mNumBuffers)
    195         self->mBufferHead = 0;
    196 
    197     GraphicLog& logger(GraphicLog::getInstance());
    198     logger.log(GraphicLog::SF_FB_DEQUEUE_BEFORE, index);
    199 
    200     // wait for a free buffer
    201     while (!self->mNumFreeBuffers) {
    202         self->mCondition.wait(self->mutex);
    203     }
    204     // get this buffer
    205     self->mNumFreeBuffers--;
    206     self->mCurrentBufferIndex = index;
    207 
    208     *buffer = self->buffers[index].get();
    209 
    210     logger.log(GraphicLog::SF_FB_DEQUEUE_AFTER, index);
    211     return 0;
    212 }
    213 
    214 int FramebufferNativeWindow::lockBuffer(ANativeWindow* window,
    215         android_native_buffer_t* buffer)
    216 {
    217     FramebufferNativeWindow* self = getSelf(window);
    218     Mutex::Autolock _l(self->mutex);
    219 
    220     const int index = self->mCurrentBufferIndex;
    221     GraphicLog& logger(GraphicLog::getInstance());
    222     logger.log(GraphicLog::SF_FB_LOCK_BEFORE, index);
    223 
    224     // wait that the buffer we're locking is not front anymore
    225     while (self->front == buffer) {
    226         self->mCondition.wait(self->mutex);
    227     }
    228 
    229     logger.log(GraphicLog::SF_FB_LOCK_AFTER, index);
    230 
    231     return NO_ERROR;
    232 }
    233 
    234 int FramebufferNativeWindow::queueBuffer(ANativeWindow* window,
    235         android_native_buffer_t* buffer)
    236 {
    237     FramebufferNativeWindow* self = getSelf(window);
    238     Mutex::Autolock _l(self->mutex);
    239     framebuffer_device_t* fb = self->fbDev;
    240     buffer_handle_t handle = static_cast<NativeBuffer*>(buffer)->handle;
    241 
    242     const int index = self->mCurrentBufferIndex;
    243     GraphicLog& logger(GraphicLog::getInstance());
    244     logger.log(GraphicLog::SF_FB_POST_BEFORE, index);
    245 
    246     int res = fb->post(fb, handle);
    247 
    248     logger.log(GraphicLog::SF_FB_POST_AFTER, index);
    249 
    250     self->front = static_cast<NativeBuffer*>(buffer);
    251     self->mNumFreeBuffers++;
    252     self->mCondition.broadcast();
    253     return res;
    254 }
    255 
    256 int FramebufferNativeWindow::query(ANativeWindow* window,
    257         int what, int* value)
    258 {
    259     FramebufferNativeWindow* self = getSelf(window);
    260     Mutex::Autolock _l(self->mutex);
    261     framebuffer_device_t* fb = self->fbDev;
    262     switch (what) {
    263         case NATIVE_WINDOW_WIDTH:
    264             *value = fb->width;
    265             return NO_ERROR;
    266         case NATIVE_WINDOW_HEIGHT:
    267             *value = fb->height;
    268             return NO_ERROR;
    269         case NATIVE_WINDOW_FORMAT:
    270             *value = fb->format;
    271             return NO_ERROR;
    272     }
    273     *value = 0;
    274     return BAD_VALUE;
    275 }
    276 
    277 int FramebufferNativeWindow::perform(ANativeWindow* window,
    278         int operation, ...)
    279 {
    280     switch (operation) {
    281         case NATIVE_WINDOW_SET_USAGE:
    282         case NATIVE_WINDOW_CONNECT:
    283         case NATIVE_WINDOW_DISCONNECT:
    284             break;
    285         default:
    286             return NAME_NOT_FOUND;
    287     }
    288     return NO_ERROR;
    289 }
    290 
    291 // ----------------------------------------------------------------------------
    292 }; // namespace android
    293 // ----------------------------------------------------------------------------
    294 
    295 using namespace android;
    296 
    297 EGLNativeWindowType android_createDisplaySurface(void)
    298 {
    299     FramebufferNativeWindow* w;
    300     w = new FramebufferNativeWindow();
    301     if (w->getDevice() == NULL) {
    302         // get a ref so it can be destroyed when we exit this block
    303         sp<FramebufferNativeWindow> ref(w);
    304         return NULL;
    305     }
    306     return (EGLNativeWindowType)w;
    307 }
    308