зеркало из https://github.com/mozilla/gecko-dev.git
Bug 708154: Add a fallback non-GL rendering patch to the gonk widget backend and add support for the qemu touch device. r=kmachulis,gal pending-r=mwu
This commit is contained in:
Родитель
2e8e3cc006
Коммит
b2adf684c7
|
@ -0,0 +1,185 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: sw=2 ts=8 et ft=cpp : */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at:
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Chris Jones <jones.chris.g@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/kd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "android/log.h"
|
||||
|
||||
#include "Framebuffer.h"
|
||||
#include "gfxImageSurface.h"
|
||||
#include "mozilla/FileUtils.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args)
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace Framebuffer {
|
||||
|
||||
static int sFd = -1;
|
||||
static size_t sMappedSize;
|
||||
static struct fb_var_screeninfo sVi;
|
||||
static size_t sActiveBuffer;
|
||||
typedef vector<nsRefPtr<gfxImageSurface> > BufferVector;
|
||||
BufferVector* sBuffers;
|
||||
|
||||
BufferVector& Buffers() { return *sBuffers; }
|
||||
|
||||
bool
|
||||
SetGraphicsMode()
|
||||
{
|
||||
ScopedClose fd(open("/dev/tty0", O_RDWR | O_SYNC));
|
||||
if (0 > fd.mFd) {
|
||||
// This is non-fatal; post-Cupcake kernels don't have tty0.
|
||||
LOG("No /dev/tty0?");
|
||||
} else if (ioctl(fd.mFd, KDSETMODE, (void*) KD_GRAPHICS)) {
|
||||
LOG("Error setting graphics mode on /dev/tty0");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
Open(nsIntSize* aScreenSize)
|
||||
{
|
||||
if (0 <= sFd)
|
||||
return true;
|
||||
|
||||
if (!SetGraphicsMode())
|
||||
return false;
|
||||
|
||||
ScopedClose fd(open("/dev/graphics/fb0", O_RDWR));
|
||||
if (0 > fd.mFd) {
|
||||
LOG("Error opening framebuffer device");
|
||||
return false;
|
||||
}
|
||||
|
||||
struct fb_fix_screeninfo fi;
|
||||
if (0 > ioctl(fd.mFd, FBIOGET_FSCREENINFO, &fi)) {
|
||||
LOG("Error getting fixed screeninfo");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (0 > ioctl(fd.mFd, FBIOGET_VSCREENINFO, &sVi)) {
|
||||
LOG("Error getting variable screeninfo");
|
||||
return false;
|
||||
}
|
||||
|
||||
sMappedSize = fi.smem_len;
|
||||
void* mem = mmap(0, sMappedSize, PROT_READ | PROT_WRITE, MAP_SHARED,
|
||||
fd.mFd, 0);
|
||||
if (MAP_FAILED == mem) {
|
||||
LOG("Error mmap'ing framebuffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
sFd = fd.mFd;
|
||||
fd.mFd = -1;
|
||||
|
||||
// The android porting doc requires a /dev/graphics/fb0 device
|
||||
// that's double buffered with r5g6b5 format. Hence the
|
||||
// hard-coded numbers here.
|
||||
gfxASurface::gfxImageFormat format = gfxASurface::ImageFormatRGB16_565;
|
||||
int bytesPerPixel = gfxASurface::BytePerPixelFromFormat(format);
|
||||
gfxIntSize size(sVi.xres, sVi.yres);
|
||||
long stride = size.width * bytesPerPixel;
|
||||
size_t numFrameBytes = stride * size.height;
|
||||
|
||||
sBuffers = new BufferVector(2);
|
||||
unsigned char* data = static_cast<unsigned char*>(mem);
|
||||
for (size_t i = 0; i < 2; ++i, data += numFrameBytes) {
|
||||
memset(data, 0, numFrameBytes);
|
||||
Buffers()[i] = new gfxImageSurface(data, size, stride, format);
|
||||
}
|
||||
|
||||
// Clear the framebuffer to a known state.
|
||||
Present();
|
||||
|
||||
*aScreenSize = size;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
Close()
|
||||
{
|
||||
if (0 > sFd)
|
||||
return;
|
||||
|
||||
munmap(Buffers()[0]->Data(), sMappedSize);
|
||||
delete sBuffers;
|
||||
sBuffers = NULL;
|
||||
|
||||
close(sFd);
|
||||
sFd = -1;
|
||||
}
|
||||
|
||||
gfxASurface*
|
||||
BackBuffer()
|
||||
{
|
||||
return Buffers()[!sActiveBuffer];
|
||||
}
|
||||
|
||||
void
|
||||
Present()
|
||||
{
|
||||
sActiveBuffer = !sActiveBuffer;
|
||||
|
||||
sVi.yres_virtual = sVi.yres * 2;
|
||||
sVi.yoffset = sActiveBuffer * sVi.yres;
|
||||
sVi.bits_per_pixel = 16;
|
||||
if (ioctl(sFd, FBIOPUT_VSCREENINFO, &sVi) < 0) {
|
||||
LOG("Error presenting front buffer");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Framebuffer
|
||||
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,79 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: sw=2 ts=8 et ft=cpp : */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at:
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Chris Jones <jones.chris.g@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class gfxASurface;
|
||||
class nsIntSize;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace Framebuffer {
|
||||
|
||||
//
|
||||
// The general usage of Framebuffer is
|
||||
//
|
||||
// -- in initialization code --
|
||||
// Open();
|
||||
//
|
||||
// -- ready to paint next frame --
|
||||
// nsRefPtr<gfxASurface> backBuffer = BackBuffer();
|
||||
// // ...
|
||||
// Paint(backBuffer);
|
||||
// // ...
|
||||
// Present();
|
||||
//
|
||||
|
||||
// Return true if the fbdev was successfully opened, along with the
|
||||
// dimensions of the screen. If this fails, the result of all further
|
||||
// calls is undefined. Open() is idempotent.
|
||||
bool Open(nsIntSize* aScreenSize);
|
||||
|
||||
// After Close(), the result of all further calls is undefined.
|
||||
// Close() is idempotent, and Open() can be called again after
|
||||
// Close().
|
||||
void Close();
|
||||
|
||||
// Return the buffer to be drawn into, that will be the next frame.
|
||||
gfxASurface* BackBuffer();
|
||||
|
||||
// Swap the front buffer for the back buffer.
|
||||
void Present();
|
||||
|
||||
} // namespace Framebuffer
|
||||
|
||||
} // namespace mozilla
|
|
@ -52,6 +52,7 @@ LIBXUL_LIBRARY = 1
|
|||
|
||||
|
||||
CPPSRCS = \
|
||||
Framebuffer.cpp \
|
||||
nsAppShell.cpp \
|
||||
nsWidgetFactory.cpp \
|
||||
nsWindow.cpp \
|
||||
|
|
|
@ -62,6 +62,9 @@
|
|||
#ifndef ABS_MT_TOUCH_MAJOR
|
||||
// Taken from include/linux/input.h
|
||||
// XXX update the bionic input.h so we don't have to do this!
|
||||
#define ABS_X 0x00
|
||||
#define ABS_Y 0x01
|
||||
// ...
|
||||
#define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */
|
||||
#define ABS_MT_TOUCH_MINOR 0x31 /* Minor axis (omit if circular) */
|
||||
#define ABS_MT_WIDTH_MAJOR 0x32 /* Major axis of approaching ellipse */
|
||||
|
@ -136,6 +139,87 @@ sendMouseEvent(PRUint32 msg, struct timeval *time, int x, int y)
|
|||
//LOG("Dispatched type %d at %dx%d", msg, x, y);
|
||||
}
|
||||
|
||||
static nsEventStatus
|
||||
sendKeyEventWithMsg(PRUint32 keyCode,
|
||||
PRUint32 msg,
|
||||
const timeval &time,
|
||||
PRUint32 flags)
|
||||
{
|
||||
nsKeyEvent event(true, msg, NULL);
|
||||
event.keyCode = keyCode;
|
||||
event.time = timevalToMS(time);
|
||||
event.flags |= flags;
|
||||
return nsWindow::DispatchInputEvent(event);
|
||||
}
|
||||
|
||||
static void
|
||||
sendKeyEvent(PRUint32 keyCode, bool down, const timeval &time)
|
||||
{
|
||||
nsEventStatus status =
|
||||
sendKeyEventWithMsg(keyCode, down ? NS_KEY_DOWN : NS_KEY_UP, time, 0);
|
||||
if (down) {
|
||||
sendKeyEventWithMsg(keyCode, NS_KEY_PRESS, time,
|
||||
status == nsEventStatus_eConsumeNoDefault ?
|
||||
NS_EVENT_FLAG_NO_DEFAULT : 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sendSpecialKeyEvent(nsIAtom *command, const timeval &time)
|
||||
{
|
||||
nsCommandEvent event(true, nsGkAtoms::onAppCommand, command, NULL);
|
||||
event.time = timevalToMS(time);
|
||||
nsWindow::DispatchInputEvent(event);
|
||||
}
|
||||
|
||||
static void
|
||||
maybeSendKeyEvent(const input_event& e)
|
||||
{
|
||||
if (e.type != EV_KEY) {
|
||||
LOG("Got unknown key event type. type 0x%04x code 0x%04x value %d",
|
||||
e.type, e.code, e.value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.value != 0 && e.value != 1) {
|
||||
LOG("Got unknown key event value. type 0x%04x code 0x%04x value %d",
|
||||
e.type, e.code, e.value);
|
||||
return;
|
||||
}
|
||||
|
||||
bool pressed = e.value == 1;
|
||||
switch (e.code) {
|
||||
case KEY_BACK:
|
||||
sendKeyEvent(NS_VK_ESCAPE, pressed, e.time);
|
||||
break;
|
||||
case KEY_MENU:
|
||||
if (!pressed)
|
||||
sendSpecialKeyEvent(nsGkAtoms::Menu, e.time);
|
||||
break;
|
||||
case KEY_SEARCH:
|
||||
if (pressed)
|
||||
sendSpecialKeyEvent(nsGkAtoms::Search, e.time);
|
||||
break;
|
||||
case KEY_HOME:
|
||||
sendKeyEvent(NS_VK_HOME, pressed, e.time);
|
||||
break;
|
||||
case KEY_POWER:
|
||||
sendKeyEvent(NS_VK_SLEEP, pressed, e.time);
|
||||
break;
|
||||
case KEY_VOLUMEUP:
|
||||
if (pressed)
|
||||
sendSpecialKeyEvent(nsGkAtoms::VolumeUp, e.time);
|
||||
break;
|
||||
case KEY_VOLUMEDOWN:
|
||||
if (pressed)
|
||||
sendSpecialKeyEvent(nsGkAtoms::VolumeDown, e.time);
|
||||
break;
|
||||
default:
|
||||
LOG("Got unknown key event code. type 0x%04x code 0x%04x value %d",
|
||||
e.type, e.code, e.value);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
multitouchHandler(int fd, FdHandler *data)
|
||||
{
|
||||
|
@ -217,37 +301,64 @@ multitouchHandler(int fd, FdHandler *data)
|
|||
}
|
||||
}
|
||||
|
||||
static nsEventStatus
|
||||
sendKeyEventWithMsg(PRUint32 keyCode,
|
||||
PRUint32 msg,
|
||||
const timeval &time,
|
||||
PRUint32 flags)
|
||||
{
|
||||
nsKeyEvent event(true, msg, NULL);
|
||||
event.keyCode = keyCode;
|
||||
event.time = timevalToMS(time);
|
||||
event.flags |= flags;
|
||||
return nsWindow::DispatchInputEvent(event);
|
||||
}
|
||||
|
||||
static void
|
||||
sendKeyEvent(PRUint32 keyCode, bool down, const timeval &time)
|
||||
singleTouchHandler(int fd, FdHandler *data)
|
||||
{
|
||||
nsEventStatus status =
|
||||
sendKeyEventWithMsg(keyCode, down ? NS_KEY_DOWN : NS_KEY_UP, time, 0);
|
||||
if (down) {
|
||||
sendKeyEventWithMsg(keyCode, NS_KEY_PRESS, time,
|
||||
status == nsEventStatus_eConsumeNoDefault ?
|
||||
NS_EVENT_FLAG_NO_DEFAULT : 0);
|
||||
// The Linux's input documentation (Documentation/input/input.txt)
|
||||
// says that we'll always read a multiple of sizeof(input_event) bytes here.
|
||||
input_event events[16];
|
||||
int event_count = read(fd, events, sizeof(events));
|
||||
if (event_count < 0) {
|
||||
LOG("Error reading in singleTouchHandler");
|
||||
return;
|
||||
}
|
||||
}
|
||||
MOZ_ASSERT(event_count % sizeof(input_event) == 0);
|
||||
|
||||
static void
|
||||
sendSpecialKeyEvent(nsIAtom *command, const timeval &time)
|
||||
{
|
||||
nsCommandEvent event(true, nsGkAtoms::onAppCommand, command, NULL);
|
||||
event.time = timevalToMS(time);
|
||||
nsWindow::DispatchInputEvent(event);
|
||||
event_count /= sizeof(struct input_event);
|
||||
|
||||
for (int i = 0; i < event_count; i++) {
|
||||
input_event *event = &events[i];
|
||||
|
||||
if (event->type == EV_KEY) {
|
||||
switch (event->code) {
|
||||
case BTN_TOUCH:
|
||||
data->mtDown = event->value;
|
||||
break;
|
||||
default:
|
||||
maybeSendKeyEvent(*event);
|
||||
}
|
||||
}
|
||||
else if (event->type == EV_ABS) {
|
||||
switch (event->code) {
|
||||
case ABS_X:
|
||||
data->mtX = event->value;
|
||||
break;
|
||||
case ABS_Y:
|
||||
data->mtY = event->value;
|
||||
break;
|
||||
default:
|
||||
LOG("Got unknown st abs event type 0x%04x with code 0x%04x and value %d",
|
||||
event->type, event->code, event->value);
|
||||
}
|
||||
} else if (event->type == EV_SYN) {
|
||||
if (data->mtState == FdHandler::MT_START) {
|
||||
MOZ_ASSERT(data->mtDown);
|
||||
sendMouseEvent(NS_MOUSE_BUTTON_DOWN, &event->time,
|
||||
data->mtX, data->mtY);
|
||||
data->mtState = FdHandler::MT_COLLECT;
|
||||
} else if (data->mtDown) {
|
||||
MOZ_ASSERT(data->mtDown);
|
||||
sendMouseEvent(NS_MOUSE_MOVE, &event->time,
|
||||
data->mtX, data->mtY);
|
||||
} else {
|
||||
MOZ_ASSERT(!data->mtDown);
|
||||
sendMouseEvent(NS_MOUSE_BUTTON_UP, &event->time,
|
||||
data->mtX, data->mtY);
|
||||
data->mtDown = false;
|
||||
data->mtState = FdHandler::MT_START;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -269,50 +380,7 @@ keyHandler(int fd, FdHandler *data)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (e.type != EV_KEY) {
|
||||
LOG("Got unknown key event type. type 0x%04x code 0x%04x value %d",
|
||||
e.type, e.code, e.value);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (e.value != 0 && e.value != 1) {
|
||||
LOG("Got unknown key event value. type 0x%04x code 0x%04x value %d",
|
||||
e.type, e.code, e.value);
|
||||
continue;
|
||||
}
|
||||
|
||||
bool pressed = e.value == 1;
|
||||
const char* upOrDown = pressed ? "pressed" : "released";
|
||||
switch (e.code) {
|
||||
case KEY_BACK:
|
||||
sendKeyEvent(NS_VK_ESCAPE, pressed, e.time);
|
||||
break;
|
||||
case KEY_MENU:
|
||||
if (!pressed)
|
||||
sendSpecialKeyEvent(nsGkAtoms::Menu, e.time);
|
||||
break;
|
||||
case KEY_SEARCH:
|
||||
if (pressed)
|
||||
sendSpecialKeyEvent(nsGkAtoms::Search, e.time);
|
||||
break;
|
||||
case KEY_HOME:
|
||||
sendKeyEvent(NS_VK_HOME, pressed, e.time);
|
||||
break;
|
||||
case KEY_POWER:
|
||||
sendKeyEvent(NS_VK_SLEEP, pressed, e.time);
|
||||
break;
|
||||
case KEY_VOLUMEUP:
|
||||
if (pressed)
|
||||
sendSpecialKeyEvent(nsGkAtoms::VolumeUp, e.time);
|
||||
break;
|
||||
case KEY_VOLUMEDOWN:
|
||||
if (pressed)
|
||||
sendSpecialKeyEvent(nsGkAtoms::VolumeDown, e.time);
|
||||
break;
|
||||
default:
|
||||
LOG("Got unknown key event code. type 0x%04x code 0x%04x value %d",
|
||||
e.type, e.code, e.value);
|
||||
}
|
||||
maybeSendKeyEvent(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -378,8 +446,12 @@ nsAppShell::Init()
|
|||
if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(flags)), flags) >= 0 &&
|
||||
BITSET(ABS_MT_POSITION_X, flags)) {
|
||||
|
||||
LOG("Found absolute input device");
|
||||
LOG("Found multitouch input device");
|
||||
handlerFunc = multitouchHandler;
|
||||
} else if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(flags)), flags) >= 0 &&
|
||||
BITSET(ABS_X, flags)) {
|
||||
LOG("Found single touch input device");
|
||||
handlerFunc = singleTouchHandler;
|
||||
} else if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(flags)), flags) >= 0) {
|
||||
LOG("Found key input device");
|
||||
handlerFunc = keyHandler;
|
||||
|
|
|
@ -35,24 +35,27 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
|
||||
#include "android/log.h"
|
||||
#include "ui/FramebufferNativeWindow.h"
|
||||
|
||||
#include "Framebuffer.h"
|
||||
#include "gfxContext.h"
|
||||
#include "gfxUtils.h"
|
||||
#include "GLContextProvider.h"
|
||||
#include "LayerManagerOGL.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsAppShell.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsWindow.h"
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
#include "ui/FramebufferNativeWindow.h"
|
||||
|
||||
#include "LayerManagerOGL.h"
|
||||
#include "GLContextProvider.h"
|
||||
|
||||
#include "android/log.h"
|
||||
|
||||
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args)
|
||||
|
||||
#define IS_TOPLEVEL() (mWindowType == eWindowType_toplevel || mWindowType == eWindowType_dialog)
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::gl;
|
||||
using namespace mozilla::layers;
|
||||
using namespace mozilla::widget;
|
||||
|
@ -64,13 +67,29 @@ static nsTArray<nsWindow *> sTopWindows;
|
|||
static nsWindow *gWindowToRedraw = nsnull;
|
||||
static nsWindow *gFocusedWindow = nsnull;
|
||||
static android::FramebufferNativeWindow *gNativeWindow = nsnull;
|
||||
static bool sFramebufferOpen;
|
||||
|
||||
nsWindow::nsWindow()
|
||||
{
|
||||
if (!sGLContext) {
|
||||
if (!sGLContext && !sFramebufferOpen) {
|
||||
// We (apparently) don't have a way to tell if allocating the
|
||||
// fbs succeeded or failed.
|
||||
gNativeWindow = new android::FramebufferNativeWindow();
|
||||
sGLContext = GLContextProvider::CreateForWindow(this);
|
||||
// CreateForWindow sets up gScreenBounds
|
||||
if (!sGLContext) {
|
||||
LOG("Failed to create GL context for fb, trying /dev/fb0");
|
||||
|
||||
// We can't delete gNativeWindow.
|
||||
|
||||
nsIntSize screenSize;
|
||||
sFramebufferOpen = Framebuffer::Open(&screenSize);
|
||||
gScreenBounds = nsIntRect(nsIntPoint(0, 0), screenSize);
|
||||
if (!sFramebufferOpen) {
|
||||
LOG("Failed to mmap fb(?!?), aborting ...");
|
||||
NS_RUNTIMEABORT("Can't open GL context and can't fall back on /dev/fb0 ...");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,14 +100,40 @@ nsWindow::~nsWindow()
|
|||
void
|
||||
nsWindow::DoDraw(void)
|
||||
{
|
||||
if (!gWindowToRedraw)
|
||||
if (!gWindowToRedraw) {
|
||||
LOG(" no window to draw, bailing");
|
||||
return;
|
||||
}
|
||||
|
||||
nsPaintEvent event(true, NS_PAINT, gWindowToRedraw);
|
||||
event.region = gScreenBounds;
|
||||
static_cast<LayerManagerOGL*>(gWindowToRedraw->GetLayerManager(nsnull))->
|
||||
SetClippingRegion(nsIntRegion(gScreenBounds));
|
||||
gWindowToRedraw->mEventCallback(&event);
|
||||
|
||||
LayerManager* lm = gWindowToRedraw->GetLayerManager();
|
||||
if (LayerManager::LAYERS_OPENGL == lm->GetBackendType()) {
|
||||
static_cast<LayerManagerOGL*>(lm)->
|
||||
SetClippingRegion(nsIntRegion(gScreenBounds));
|
||||
gWindowToRedraw->mEventCallback(&event);
|
||||
} else if (LayerManager::LAYERS_BASIC == lm->GetBackendType()) {
|
||||
MOZ_ASSERT(sFramebufferOpen);
|
||||
|
||||
nsRefPtr<gfxASurface> backBuffer = Framebuffer::BackBuffer();
|
||||
{
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(backBuffer);
|
||||
ctx->NewPath();
|
||||
gfxUtils::PathFromRegion(ctx, event.region);
|
||||
ctx->Clip();
|
||||
|
||||
// No double-buffering needed.
|
||||
AutoLayerManagerSetup setupLayerManager(
|
||||
gWindowToRedraw, ctx, BasicLayerManager::BUFFER_NONE);
|
||||
gWindowToRedraw->mEventCallback(&event);
|
||||
}
|
||||
backBuffer->Flush();
|
||||
|
||||
Framebuffer::Present();
|
||||
} else {
|
||||
NS_RUNTIMEABORT("Unexpected layer manager type");
|
||||
}
|
||||
}
|
||||
|
||||
nsEventStatus
|
||||
|
@ -243,8 +288,10 @@ nsWindow::Invalidate(const nsIntRect &aRect,
|
|||
nsWindow *parent = mParent;
|
||||
while (parent && parent != sTopWindows[0])
|
||||
parent = parent->mParent;
|
||||
if (parent != sTopWindows[0])
|
||||
if (parent != sTopWindows[0]) {
|
||||
LOG(" parent isn't top window, bailing");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
gWindowToRedraw = this;
|
||||
gDrawRequest = true;
|
||||
|
@ -337,19 +384,18 @@ nsWindow::GetLayerManager(PLayersChild* aShadowManager,
|
|||
return nsnull;
|
||||
}
|
||||
|
||||
if (!sGLContext) {
|
||||
LOG(" -- no GLContext\n");
|
||||
return nsnull;
|
||||
if (sGLContext) {
|
||||
nsRefPtr<LayerManagerOGL> layerManager = new LayerManagerOGL(this);
|
||||
|
||||
if (layerManager->Initialize(sGLContext))
|
||||
mLayerManager = layerManager;
|
||||
else
|
||||
LOG("Could not create OGL LayerManager");
|
||||
} else {
|
||||
MOZ_ASSERT(sFramebufferOpen);
|
||||
mLayerManager = new BasicShadowLayerManager(this);
|
||||
}
|
||||
|
||||
nsRefPtr<LayerManagerOGL> layerManager =
|
||||
new LayerManagerOGL(this);
|
||||
|
||||
if (layerManager->Initialize(sGLContext))
|
||||
mLayerManager = layerManager;
|
||||
else
|
||||
LOG("Could not create LayerManager");
|
||||
|
||||
return mLayerManager;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче