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         ANativeWindowBuffer,
     51         NativeBuffer,
     52         LightRefBase<NativeBuffer> >
     53 {
     54 public:
     55     NativeBuffer(int w, int h, int f, int u) : BASE() {
     56         ANativeWindowBuffer::width  = w;
     57         ANativeWindowBuffer::height = h;
     58         ANativeWindowBuffer::format = f;
     59         ANativeWindowBuffer::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         int i;
     87         err = framebuffer_open(module, &fbDev);
     88         LOGE_IF(err, "couldn't open framebuffer HAL (%s)", strerror(-err));
     89 
     90         err = gralloc_open(module, &grDev);
     91         LOGE_IF(err, "couldn't open gralloc HAL (%s)", strerror(-err));
     92 
     93         // bail out if we can't initialize the modules
     94         if (!fbDev || !grDev)
     95             return;
     96 
     97         mUpdateOnDemand = (fbDev->setUpdateRect != 0);
     98 
     99         // initialize the buffer FIFO
    100         mNumBuffers = NUM_FRAME_BUFFERS;
    101         mNumFreeBuffers = NUM_FRAME_BUFFERS;
    102         mBufferHead = mNumBuffers-1;
    103 
    104         for (i = 0; i < mNumBuffers; i++)
    105         {
    106                 buffers[i] = new NativeBuffer(
    107                         fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB);
    108         }
    109 
    110         for (i = 0; i < mNumBuffers; i++)
    111         {
    112                 err = grDev->alloc(grDev,
    113                         fbDev->width, fbDev->height, fbDev->format,
    114                         GRALLOC_USAGE_HW_FB, &buffers[i]->handle, &buffers[i]->stride);
    115 
    116                 LOGE_IF(err, "fb buffer %d allocation failed w=%d, h=%d, err=%s",
    117                         i, fbDev->width, fbDev->height, strerror(-err));
    118 
    119                 if (err)
    120                 {
    121                         mNumBuffers = i;
    122                         mNumFreeBuffers = i;
    123                         mBufferHead = mNumBuffers-1;
    124                         break;
    125                 }
    126         }
    127 
    128         const_cast<uint32_t&>(ANativeWindow::flags) = fbDev->flags;
    129         const_cast<float&>(ANativeWindow::xdpi) = fbDev->xdpi;
    130         const_cast<float&>(ANativeWindow::ydpi) = fbDev->ydpi;
    131         const_cast<int&>(ANativeWindow::minSwapInterval) =
    132             fbDev->minSwapInterval;
    133         const_cast<int&>(ANativeWindow::maxSwapInterval) =
    134             fbDev->maxSwapInterval;
    135     } else {
    136         LOGE("Couldn't get gralloc module");
    137     }
    138 
    139     ANativeWindow::setSwapInterval = setSwapInterval;
    140     ANativeWindow::dequeueBuffer = dequeueBuffer;
    141     ANativeWindow::lockBuffer = lockBuffer;
    142     ANativeWindow::queueBuffer = queueBuffer;
    143     ANativeWindow::query = query;
    144     ANativeWindow::perform = perform;
    145 }
    146 
    147 FramebufferNativeWindow::~FramebufferNativeWindow()
    148 {
    149     if (grDev) {
    150         if (buffers[0] != NULL)
    151             grDev->free(grDev, buffers[0]->handle);
    152         if (buffers[1] != NULL)
    153             grDev->free(grDev, buffers[1]->handle);
    154         gralloc_close(grDev);
    155     }
    156 
    157     if (fbDev) {
    158         framebuffer_close(fbDev);
    159     }
    160 }
    161 
    162 status_t FramebufferNativeWindow::setUpdateRectangle(const Rect& r)
    163 {
    164     if (!mUpdateOnDemand) {
    165         return INVALID_OPERATION;
    166     }
    167     return fbDev->setUpdateRect(fbDev, r.left, r.top, r.width(), r.height());
    168 }
    169 
    170 status_t FramebufferNativeWindow::compositionComplete()
    171 {
    172     if (fbDev->compositionComplete) {
    173         return fbDev->compositionComplete(fbDev);
    174     }
    175     return INVALID_OPERATION;
    176 }
    177 
    178 int FramebufferNativeWindow::setSwapInterval(
    179         ANativeWindow* window, int interval)
    180 {
    181     framebuffer_device_t* fb = getSelf(window)->fbDev;
    182     return fb->setSwapInterval(fb, interval);
    183 }
    184 
    185 void FramebufferNativeWindow::dump(String8& result) {
    186     if (fbDev->common.version >= 1 && fbDev->dump) {
    187         const size_t SIZE = 4096;
    188         char buffer[SIZE];
    189 
    190         fbDev->dump(fbDev, buffer, SIZE);
    191         result.append(buffer);
    192     }
    193 }
    194 
    195 // only for debugging / logging
    196 int FramebufferNativeWindow::getCurrentBufferIndex() const
    197 {
    198     Mutex::Autolock _l(mutex);
    199     const int index = mCurrentBufferIndex;
    200     return index;
    201 }
    202 
    203 int FramebufferNativeWindow::dequeueBuffer(ANativeWindow* window,
    204         ANativeWindowBuffer** buffer)
    205 {
    206     FramebufferNativeWindow* self = getSelf(window);
    207     Mutex::Autolock _l(self->mutex);
    208     framebuffer_device_t* fb = self->fbDev;
    209 
    210     int index = self->mBufferHead++;
    211     if (self->mBufferHead >= self->mNumBuffers)
    212         self->mBufferHead = 0;
    213 
    214     GraphicLog& logger(GraphicLog::getInstance());
    215     logger.log(GraphicLog::SF_FB_DEQUEUE_BEFORE, index);
    216 
    217     // wait for a free buffer
    218     while (!self->mNumFreeBuffers) {
    219         self->mCondition.wait(self->mutex);
    220     }
    221     // get this buffer
    222     self->mNumFreeBuffers--;
    223     self->mCurrentBufferIndex = index;
    224 
    225     *buffer = self->buffers[index].get();
    226 
    227     logger.log(GraphicLog::SF_FB_DEQUEUE_AFTER, index);
    228     return 0;
    229 }
    230 
    231 int FramebufferNativeWindow::lockBuffer(ANativeWindow* window,
    232         ANativeWindowBuffer* buffer)
    233 {
    234     FramebufferNativeWindow* self = getSelf(window);
    235     Mutex::Autolock _l(self->mutex);
    236 
    237     const int index = self->mCurrentBufferIndex;
    238     GraphicLog& logger(GraphicLog::getInstance());
    239     logger.log(GraphicLog::SF_FB_LOCK_BEFORE, index);
    240 
    241     // wait that the buffer we're locking is not front anymore
    242     while (self->front == buffer) {
    243         self->mCondition.wait(self->mutex);
    244     }
    245 
    246     logger.log(GraphicLog::SF_FB_LOCK_AFTER, index);
    247 
    248     return NO_ERROR;
    249 }
    250 
    251 int FramebufferNativeWindow::queueBuffer(ANativeWindow* window,
    252         ANativeWindowBuffer* buffer)
    253 {
    254     FramebufferNativeWindow* self = getSelf(window);
    255     Mutex::Autolock _l(self->mutex);
    256     framebuffer_device_t* fb = self->fbDev;
    257     buffer_handle_t handle = static_cast<NativeBuffer*>(buffer)->handle;
    258 
    259     const int index = self->mCurrentBufferIndex;
    260     GraphicLog& logger(GraphicLog::getInstance());
    261     logger.log(GraphicLog::SF_FB_POST_BEFORE, index);
    262 
    263     int res = fb->post(fb, handle);
    264 
    265     logger.log(GraphicLog::SF_FB_POST_AFTER, index);
    266 
    267     self->front = static_cast<NativeBuffer*>(buffer);
    268     self->mNumFreeBuffers++;
    269     self->mCondition.broadcast();
    270     return res;
    271 }
    272 
    273 int FramebufferNativeWindow::query(const ANativeWindow* window,
    274         int what, int* value)
    275 {
    276     const FramebufferNativeWindow* self = getSelf(window);
    277     Mutex::Autolock _l(self->mutex);
    278     framebuffer_device_t* fb = self->fbDev;
    279     switch (what) {
    280         case NATIVE_WINDOW_WIDTH:
    281             *value = fb->width;
    282             return NO_ERROR;
    283         case NATIVE_WINDOW_HEIGHT:
    284             *value = fb->height;
    285             return NO_ERROR;
    286         case NATIVE_WINDOW_FORMAT:
    287             *value = fb->format;
    288             return NO_ERROR;
    289         case NATIVE_WINDOW_CONCRETE_TYPE:
    290             *value = NATIVE_WINDOW_FRAMEBUFFER;
    291             return NO_ERROR;
    292         case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER:
    293             *value = 0;
    294             return NO_ERROR;
    295         case NATIVE_WINDOW_DEFAULT_WIDTH:
    296             *value = fb->width;
    297             return NO_ERROR;
    298         case NATIVE_WINDOW_DEFAULT_HEIGHT:
    299             *value = fb->height;
    300             return NO_ERROR;
    301         case NATIVE_WINDOW_TRANSFORM_HINT:
    302             *value = 0;
    303             return NO_ERROR;
    304     }
    305     *value = 0;
    306     return BAD_VALUE;
    307 }
    308 
    309 int FramebufferNativeWindow::perform(ANativeWindow* window,
    310         int operation, ...)
    311 {
    312     switch (operation) {
    313         case NATIVE_WINDOW_CONNECT:
    314         case NATIVE_WINDOW_DISCONNECT:
    315         case NATIVE_WINDOW_SET_USAGE:
    316         case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY:
    317         case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS:
    318         case NATIVE_WINDOW_SET_BUFFERS_FORMAT:
    319         case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
    320         case NATIVE_WINDOW_API_CONNECT:
    321         case NATIVE_WINDOW_API_DISCONNECT:
    322             // TODO: we should implement these
    323             return NO_ERROR;
    324 
    325         case NATIVE_WINDOW_LOCK:
    326         case NATIVE_WINDOW_UNLOCK_AND_POST:
    327         case NATIVE_WINDOW_SET_CROP:
    328         case NATIVE_WINDOW_SET_BUFFER_COUNT:
    329         case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
    330         case NATIVE_WINDOW_SET_SCALING_MODE:
    331             return INVALID_OPERATION;
    332     }
    333     return NAME_NOT_FOUND;
    334 }
    335 
    336 // ----------------------------------------------------------------------------
    337 }; // namespace android
    338 // ----------------------------------------------------------------------------
    339 
    340 using namespace android;
    341 
    342 EGLNativeWindowType android_createDisplaySurface(void)
    343 {
    344     FramebufferNativeWindow* w;
    345     w = new FramebufferNativeWindow();
    346     if (w->getDevice() == NULL) {
    347         // get a ref so it can be destroyed when we exit this block
    348         sp<FramebufferNativeWindow> ref(w);
    349         return NULL;
    350     }
    351     return (EGLNativeWindowType)w;
    352 }
    353