1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/widget/gonk/Framebuffer.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,206 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set sw=2 ts=8 et ft=cpp : */ 1.6 +/* Copyright 2012 Mozilla Foundation and Mozilla contributors 1.7 + * 1.8 + * Licensed under the Apache License, Version 2.0 (the "License"); 1.9 + * you may not use this file except in compliance with the License. 1.10 + * You may obtain a copy of the License at 1.11 + * 1.12 + * http://www.apache.org/licenses/LICENSE-2.0 1.13 + * 1.14 + * Unless required by applicable law or agreed to in writing, software 1.15 + * distributed under the License is distributed on an "AS IS" BASIS, 1.16 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1.17 + * See the License for the specific language governing permissions and 1.18 + * limitations under the License. 1.19 + */ 1.20 + 1.21 +#include <fcntl.h> 1.22 +#include <linux/fb.h> 1.23 +#include <linux/kd.h> 1.24 +#include <stdio.h> 1.25 +#include <stdlib.h> 1.26 +#include <sys/ioctl.h> 1.27 +#include <sys/mman.h> 1.28 +#include <sys/types.h> 1.29 +#include <unistd.h> 1.30 + 1.31 +#include <vector> 1.32 + 1.33 +#include "android/log.h" 1.34 + 1.35 +#include "Framebuffer.h" 1.36 +#include "gfxContext.h" 1.37 +#include "gfxImageSurface.h" 1.38 +#include "gfxUtils.h" 1.39 +#include "mozilla/FileUtils.h" 1.40 +#include "nsTArray.h" 1.41 +#include "nsRegion.h" 1.42 + 1.43 +#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args) 1.44 + 1.45 +using namespace std; 1.46 + 1.47 +namespace mozilla { 1.48 + 1.49 +namespace Framebuffer { 1.50 + 1.51 +static int sFd = -1; 1.52 +static size_t sMappedSize; 1.53 +static struct fb_var_screeninfo sVi; 1.54 +static size_t sActiveBuffer; 1.55 +typedef vector<nsRefPtr<gfxImageSurface> > BufferVector; 1.56 +BufferVector* sBuffers; 1.57 +static gfxIntSize *sScreenSize = nullptr; 1.58 + 1.59 +BufferVector& Buffers() { return *sBuffers; } 1.60 + 1.61 +bool 1.62 +SetGraphicsMode() 1.63 +{ 1.64 + ScopedClose fd(open("/dev/tty0", O_RDWR | O_SYNC)); 1.65 + if (0 > fd.get()) { 1.66 + // This is non-fatal; post-Cupcake kernels don't have tty0. 1.67 + LOG("No /dev/tty0?"); 1.68 + } else if (ioctl(fd.get(), KDSETMODE, (void*) KD_GRAPHICS)) { 1.69 + LOG("Error setting graphics mode on /dev/tty0"); 1.70 + return false; 1.71 + } 1.72 + return true; 1.73 +} 1.74 + 1.75 +bool 1.76 +Open() 1.77 +{ 1.78 + if (0 <= sFd) 1.79 + return true; 1.80 + 1.81 + if (!SetGraphicsMode()) 1.82 + return false; 1.83 + 1.84 + ScopedClose fd(open("/dev/graphics/fb0", O_RDWR)); 1.85 + if (0 > fd.get()) { 1.86 + LOG("Error opening framebuffer device"); 1.87 + return false; 1.88 + } 1.89 + 1.90 + struct fb_fix_screeninfo fi; 1.91 + if (0 > ioctl(fd.get(), FBIOGET_FSCREENINFO, &fi)) { 1.92 + LOG("Error getting fixed screeninfo"); 1.93 + return false; 1.94 + } 1.95 + 1.96 + if (0 > ioctl(fd.get(), FBIOGET_VSCREENINFO, &sVi)) { 1.97 + LOG("Error getting variable screeninfo"); 1.98 + return false; 1.99 + } 1.100 + 1.101 + sMappedSize = fi.smem_len; 1.102 + void* mem = mmap(0, sMappedSize, PROT_READ | PROT_WRITE, MAP_SHARED, 1.103 + fd.rwget(), 0); 1.104 + if (MAP_FAILED == mem) { 1.105 + LOG("Error mmap'ing framebuffer"); 1.106 + return false; 1.107 + } 1.108 + 1.109 + sFd = fd.get(); 1.110 + fd.forget(); 1.111 + 1.112 + // The android porting doc requires a /dev/graphics/fb0 device 1.113 + // that's double buffered with r5g6b5 format. Hence the 1.114 + // hard-coded numbers here. 1.115 + gfxImageFormat format = gfxImageFormat::RGB16_565; 1.116 + if (!sScreenSize) { 1.117 + sScreenSize = new gfxIntSize(sVi.xres, sVi.yres); 1.118 + } 1.119 + long stride = fi.line_length; 1.120 + size_t numFrameBytes = stride * sScreenSize->height; 1.121 + 1.122 + sBuffers = new BufferVector(2); 1.123 + unsigned char* data = static_cast<unsigned char*>(mem); 1.124 + for (size_t i = 0; i < 2; ++i, data += numFrameBytes) { 1.125 + memset(data, 0, numFrameBytes); 1.126 + Buffers()[i] = new gfxImageSurface(data, *sScreenSize, stride, format); 1.127 + } 1.128 + 1.129 + // Clear the framebuffer to a known state. 1.130 + Present(nsIntRect()); 1.131 + 1.132 + return true; 1.133 +} 1.134 + 1.135 +bool 1.136 +GetSize(nsIntSize *aScreenSize) { 1.137 + // If the framebuffer has been opened, we should always have the size. 1.138 + if (sScreenSize) { 1.139 + *aScreenSize = *sScreenSize; 1.140 + return true; 1.141 + } 1.142 + 1.143 + ScopedClose fd(open("/dev/graphics/fb0", O_RDWR)); 1.144 + if (0 > fd.get()) { 1.145 + LOG("Error opening framebuffer device"); 1.146 + return false; 1.147 + } 1.148 + 1.149 + if (0 > ioctl(fd.get(), FBIOGET_VSCREENINFO, &sVi)) { 1.150 + LOG("Error getting variable screeninfo"); 1.151 + return false; 1.152 + } 1.153 + 1.154 + sScreenSize = new gfxIntSize(sVi.xres, sVi.yres); 1.155 + *aScreenSize = *sScreenSize; 1.156 + return true; 1.157 +} 1.158 + 1.159 +void 1.160 +Close() 1.161 +{ 1.162 + if (0 > sFd) 1.163 + return; 1.164 + 1.165 + munmap(Buffers()[0]->Data(), sMappedSize); 1.166 + delete sBuffers; 1.167 + sBuffers = nullptr; 1.168 + delete sScreenSize; 1.169 + sScreenSize = nullptr; 1.170 + 1.171 + close(sFd); 1.172 + sFd = -1; 1.173 +} 1.174 + 1.175 +gfxASurface* 1.176 +BackBuffer() 1.177 +{ 1.178 + return Buffers()[!sActiveBuffer]; 1.179 +} 1.180 + 1.181 +static gfxASurface* 1.182 +FrontBuffer() 1.183 +{ 1.184 + return Buffers()[sActiveBuffer]; 1.185 +} 1.186 + 1.187 +void 1.188 +Present(const nsIntRegion& aUpdated) 1.189 +{ 1.190 + sActiveBuffer = !sActiveBuffer; 1.191 + 1.192 + sVi.yres_virtual = sVi.yres * 2; 1.193 + sVi.yoffset = sActiveBuffer * sVi.yres; 1.194 + sVi.bits_per_pixel = 16; 1.195 + if (ioctl(sFd, FBIOPUT_VSCREENINFO, &sVi) < 0) { 1.196 + LOG("Error presenting front buffer"); 1.197 + } 1.198 + 1.199 + nsRefPtr<gfxContext> ctx = new gfxContext(BackBuffer()); 1.200 + gfxUtils::PathFromRegion(ctx, aUpdated); 1.201 + ctx->Clip(); 1.202 + ctx->SetSource(FrontBuffer()); 1.203 + ctx->SetOperator(gfxContext::OPERATOR_SOURCE); 1.204 + ctx->Paint(1.0); 1.205 +} 1.206 + 1.207 +} // namespace Framebuffer 1.208 + 1.209 +} // namespace mozilla