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