widget/gonk/Framebuffer.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim: set sw=2 ts=8 et ft=cpp : */
     3 /* Copyright 2012 Mozilla Foundation and Mozilla contributors
     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  */
    18 #include <fcntl.h>
    19 #include <linux/fb.h>
    20 #include <linux/kd.h>
    21 #include <stdio.h>
    22 #include <stdlib.h>
    23 #include <sys/ioctl.h>
    24 #include <sys/mman.h>
    25 #include <sys/types.h>
    26 #include <unistd.h>
    28 #include <vector>
    30 #include "android/log.h"
    32 #include "Framebuffer.h"
    33 #include "gfxContext.h"
    34 #include "gfxImageSurface.h"
    35 #include "gfxUtils.h"
    36 #include "mozilla/FileUtils.h"
    37 #include "nsTArray.h"
    38 #include "nsRegion.h"
    40 #define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args)
    42 using namespace std;
    44 namespace mozilla {
    46 namespace Framebuffer {
    48 static int sFd = -1;
    49 static size_t sMappedSize;
    50 static struct fb_var_screeninfo sVi;
    51 static size_t sActiveBuffer;
    52 typedef vector<nsRefPtr<gfxImageSurface> > BufferVector;
    53 BufferVector* sBuffers;
    54 static gfxIntSize *sScreenSize = nullptr;
    56 BufferVector& Buffers() { return *sBuffers; }
    58 bool
    59 SetGraphicsMode()
    60 {
    61     ScopedClose fd(open("/dev/tty0", O_RDWR | O_SYNC));
    62     if (0 > fd.get()) {
    63         // This is non-fatal; post-Cupcake kernels don't have tty0.
    64         LOG("No /dev/tty0?");
    65     } else if (ioctl(fd.get(), KDSETMODE, (void*) KD_GRAPHICS)) {
    66         LOG("Error setting graphics mode on /dev/tty0");
    67         return false;
    68     }
    69     return true;
    70 }
    72 bool
    73 Open()
    74 {
    75     if (0 <= sFd)
    76         return true;
    78     if (!SetGraphicsMode())
    79         return false;
    81     ScopedClose fd(open("/dev/graphics/fb0", O_RDWR));
    82     if (0 > fd.get()) {
    83         LOG("Error opening framebuffer device");
    84         return false;
    85     }
    87     struct fb_fix_screeninfo fi;
    88     if (0 > ioctl(fd.get(), FBIOGET_FSCREENINFO, &fi)) {
    89         LOG("Error getting fixed screeninfo");
    90         return false;
    91     }
    93     if (0 > ioctl(fd.get(), FBIOGET_VSCREENINFO, &sVi)) {
    94         LOG("Error getting variable screeninfo");
    95         return false;
    96     }
    98     sMappedSize = fi.smem_len;
    99     void* mem = mmap(0, sMappedSize, PROT_READ | PROT_WRITE, MAP_SHARED,
   100                      fd.rwget(), 0);
   101     if (MAP_FAILED == mem) {
   102         LOG("Error mmap'ing framebuffer");
   103         return false;
   104     }
   106     sFd = fd.get();
   107     fd.forget();
   109     // The android porting doc requires a /dev/graphics/fb0 device
   110     // that's double buffered with r5g6b5 format.  Hence the
   111     // hard-coded numbers here.
   112     gfxImageFormat format = gfxImageFormat::RGB16_565;
   113     if (!sScreenSize) {
   114         sScreenSize = new gfxIntSize(sVi.xres, sVi.yres);
   115     }
   116     long stride = fi.line_length;
   117     size_t numFrameBytes = stride * sScreenSize->height;
   119     sBuffers = new BufferVector(2);
   120     unsigned char* data = static_cast<unsigned char*>(mem);
   121     for (size_t i = 0; i < 2; ++i, data += numFrameBytes) {
   122       memset(data, 0, numFrameBytes);
   123       Buffers()[i] = new gfxImageSurface(data, *sScreenSize, stride, format);
   124     }
   126     // Clear the framebuffer to a known state.
   127     Present(nsIntRect());
   129     return true;
   130 }
   132 bool
   133 GetSize(nsIntSize *aScreenSize) {
   134     // If the framebuffer has been opened, we should always have the size.
   135     if (sScreenSize) {
   136         *aScreenSize = *sScreenSize;
   137         return true;
   138     }
   140     ScopedClose fd(open("/dev/graphics/fb0", O_RDWR));
   141     if (0 > fd.get()) {
   142         LOG("Error opening framebuffer device");
   143         return false;
   144     }
   146     if (0 > ioctl(fd.get(), FBIOGET_VSCREENINFO, &sVi)) {
   147         LOG("Error getting variable screeninfo");
   148         return false;
   149     }
   151     sScreenSize = new gfxIntSize(sVi.xres, sVi.yres);
   152     *aScreenSize = *sScreenSize;
   153     return true;
   154 }
   156 void
   157 Close()
   158 {
   159     if (0 > sFd)
   160         return;
   162     munmap(Buffers()[0]->Data(), sMappedSize);
   163     delete sBuffers;
   164     sBuffers = nullptr;
   165     delete sScreenSize;
   166     sScreenSize = nullptr;
   168     close(sFd);
   169     sFd = -1;
   170 }
   172 gfxASurface*
   173 BackBuffer()
   174 {
   175     return Buffers()[!sActiveBuffer];
   176 }
   178 static gfxASurface*
   179 FrontBuffer()
   180 {
   181     return Buffers()[sActiveBuffer];
   182 }
   184 void
   185 Present(const nsIntRegion& aUpdated)
   186 {
   187     sActiveBuffer = !sActiveBuffer;
   189     sVi.yres_virtual = sVi.yres * 2;
   190     sVi.yoffset = sActiveBuffer * sVi.yres;
   191     sVi.bits_per_pixel = 16;
   192     if (ioctl(sFd, FBIOPUT_VSCREENINFO, &sVi) < 0) {
   193         LOG("Error presenting front buffer");
   194     }
   196     nsRefPtr<gfxContext> ctx = new gfxContext(BackBuffer());
   197     gfxUtils::PathFromRegion(ctx, aUpdated);
   198     ctx->Clip();
   199     ctx->SetSource(FrontBuffer());
   200     ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
   201     ctx->Paint(1.0);
   202 }
   204 } // namespace Framebuffer
   206 } // namespace mozilla

mercurial