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