123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406 |
- // Copyright (C) 2002-2007 Nikolaus Gebhardt
- // Copyright (C) 2007-2012 Christian Stehno
- // This file is part of the "Irrlicht Engine".
- // For conditions of distribution and use, see copyright notice in irrlicht.h
- #include "CIrrDeviceFB.h"
- #ifdef _IRR_COMPILE_WITH_FB_DEVICE_
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/ioctl.h>
- #include <fcntl.h>
- #include <sys/mman.h>
- #include <sys/utsname.h>
- #include <time.h>
- #include <errno.h>
- #include "IEventReceiver.h"
- #include "os.h"
- #include "CTimer.h"
- #include "irrString.h"
- #include "Keycodes.h"
- #include "COSOperator.h"
- #include "CColorConverter.h"
- #include "SIrrCreationParameters.h"
- #include <linux/input.h>
- namespace irr
- {
- //! constructor
- CIrrDeviceFB::CIrrDeviceFB(const SIrrlichtCreationParameters& params)
- : CIrrDeviceStub(params), Framebuffer(-1), EventDevice(-1), SoftwareImage(0),
- Pitch(0), FBColorFormat(video::ECF_A8R8G8B8), Close(false)
- {
- #ifdef _DEBUG
- setDebugName("CIrrDeviceFB");
- #endif
- // print version, distribution etc.
- // thx to LynxLuna for pointing me to the uname function
- core::stringc linuxversion;
- struct utsname FBInfo;
- uname(&FBInfo);
- linuxversion += FBInfo.sysname;
- linuxversion += " ";
- linuxversion += FBInfo.release;
- linuxversion += " ";
- linuxversion += FBInfo.version;
- linuxversion += " ";
- linuxversion += FBInfo.machine;
- Operator = new COSOperator(linuxversion);
- os::Printer::log(linuxversion.c_str(), ELL_INFORMATION);
- // create window
- if (params.DriverType != video::EDT_NULL)
- {
- // create the window, only if we do not use the null device
- if (!createWindow(params.WindowSize, params.Bits))
- return;
- }
- // create cursor control
- CursorControl = new CCursorControl(this, params.DriverType == video::EDT_NULL);
- // create driver
- createDriver();
- if (!VideoDriver)
- return;
- createGUIAndScene();
- }
- //! destructor
- CIrrDeviceFB::~CIrrDeviceFB()
- {
- if (SoftwareImage)
- munmap(SoftwareImage, CreationParams.WindowSize.Height*Pitch);
- // go back to previous format
- if (ioctl(Framebuffer, FBIOPUT_VSCREENINFO, &oldscreeninfo) <0)
- perror("Restoring old fb mode");
- if (KeyboardDevice != -1)
- if (ioctl(KeyboardDevice, KDSETMODE, &KeyboardMode) <0)
- perror("Restoring keyboard mode");
- if (EventDevice != -1)
- close(EventDevice);
- if (KeyboardDevice != -1)
- close(KeyboardDevice);
- if (Framebuffer != -1)
- close(Framebuffer);
- }
- bool CIrrDeviceFB::createWindow(const core::dimension2d<u32>& windowSize, u32 bits)
- {
- char buf[256];
- CreationParams.WindowSize.Width = windowSize.Width;
- CreationParams.WindowSize.Height = windowSize.Height;
- KeyboardDevice = open("/dev/tty", O_RDWR);
- if (KeyboardDevice == -1)
- perror("Open keyboard");
- if (ioctl(KeyboardDevice, KDGETMODE, &KeyboardMode) <0)
- perror("Read keyboard mode");
- if (ioctl(KeyboardDevice, KDSETMODE, KD_GRAPHICS) <0)
- perror("Set keyboard mode");
- Framebuffer=open("/dev/fb/0", O_RDWR);
- if (Framebuffer == -1)
- {
- Framebuffer=open("/dev/fb0", O_RDWR);
- if (Framebuffer == -1)
- {
- perror("Open framebuffer");
- return false;
- }
- }
- EventDevice = open("/dev/input/event0", O_RDONLY | O_NONBLOCK);
- if (EventDevice == -1)
- perror("Open event device");
- // make format settings
- ioctl(Framebuffer, FBIOGET_FSCREENINFO, &fbfixscreeninfo);
- ioctl(Framebuffer, FBIOGET_VSCREENINFO, &oldscreeninfo);
- snprintf(buf, 256, "Original resolution: %d x %d\nARGB%d%d%d%d\n",oldscreeninfo.xres,oldscreeninfo.yres,
- oldscreeninfo.transp.length,oldscreeninfo.red.length,oldscreeninfo.green.length,oldscreeninfo.blue.length);
- os::Printer::log(buf);
- memcpy(&fbscreeninfo, &oldscreeninfo, sizeof(struct fb_var_screeninfo));
- if (CreationParams.DriverType != video::EDT_NULL)
- {
- fbscreeninfo.xres = fbscreeninfo.xres_virtual = CreationParams.WindowSize.Width;
- fbscreeninfo.yres = fbscreeninfo.yres_virtual = CreationParams.WindowSize.Height;
- fbscreeninfo.bits_per_pixel = 16;
- fbscreeninfo.red.offset = 10;
- fbscreeninfo.red.length = 5;
- fbscreeninfo.green.offset = 5;
- fbscreeninfo.green.length = 5;
- fbscreeninfo.blue.offset = 0;
- fbscreeninfo.blue.length = 5;
- fbscreeninfo.transp.offset = 15;
- fbscreeninfo.transp.length = 1;
- ioctl(Framebuffer, FBIOPUT_VSCREENINFO, &fbscreeninfo);
- ioctl(Framebuffer, FBIOGET_VSCREENINFO, &fbscreeninfo);
- snprintf(buf, 256, "New resolution: %d x %d (%d x %d)\nARGB%d%d%d%d\n",fbscreeninfo.xres,fbscreeninfo.yres,fbscreeninfo.xres_virtual,fbscreeninfo.yres_virtual,
- fbscreeninfo.transp.length,fbscreeninfo.red.length,fbscreeninfo.green.length,fbscreeninfo.blue.length);
- os::Printer::log(buf);
- CreationParams.WindowSize.Width = fbscreeninfo.xres;
- CreationParams.WindowSize.Height = fbscreeninfo.yres;
- CreationParams.Bits = fbscreeninfo.bits_per_pixel;
- Pitch = fbfixscreeninfo.line_length;
- if (fbscreeninfo.bits_per_pixel == 16)
- {
- if (fbscreeninfo.transp.length == 0)
- FBColorFormat = video::ECF_R5G6B5;
- else
- FBColorFormat = video::ECF_A1R5G5B5;
- }
- else
- {
- if (fbscreeninfo.transp.length == 0)
- FBColorFormat = video::ECF_R8G8B8;
- else
- FBColorFormat = video::ECF_A8R8G8B8;
- }
- if (MAP_FAILED==(SoftwareImage=(u8*)mmap(0, CreationParams.WindowSize.Height*Pitch, PROT_READ|PROT_WRITE, MAP_SHARED, Framebuffer, 0)))
- {
- perror("mmap render target");
- return false;
- }
- }
- return true;
- }
- //! create the driver
- void CIrrDeviceFB::createDriver()
- {
- switch(CreationParams.DriverType)
- {
- case video::EDT_SOFTWARE:
- #ifdef _IRR_COMPILE_WITH_SOFTWARE_
- VideoDriver = video::createSoftwareDriver(CreationParams.WindowSize, CreationParams.Fullscreen, FileSystem, this);
- #else
- os::Printer::log("No Software driver support compiled in.", ELL_WARNING);
- #endif
- break;
-
- case video::EDT_BURNINGSVIDEO:
- #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_
- VideoDriver = video::createBurningVideoDriver(CreationParams, FileSystem, this);
- #else
- os::Printer::log("Burning's video driver was not compiled in.", ELL_WARNING);
- #endif
- break;
- case video::EDT_OPENGL:
- case video::EDT_DIRECT3D8:
- case video::EDT_DIRECT3D9:
- os::Printer::log("This driver is not available in FB. Try Software renderer.",
- ELL_WARNING);
- break;
- default:
- VideoDriver = video::createNullDriver(FileSystem, CreationParams.WindowSize);
- break;
- }
- }
- //! runs the device. Returns false if device wants to be deleted
- bool CIrrDeviceFB::run()
- {
- os::Timer::tick();
- struct input_event ev;
- if (EventDevice>=0)
- {
- if ((read(EventDevice, &ev, sizeof(input_event)) < 0) &&
- errno != EAGAIN)
- perror("Read input event");
- if (ev.type == EV_KEY)
- {
- irr::SEvent irrevent;
- irrevent.EventType = irr::EET_KEY_INPUT_EVENT;
- irrevent.KeyInput.PressedDown = true;
-
- switch (ev.code)
- {
- case KEY_RIGHTCTRL:
- case KEY_LEFTCTRL:
- irrevent.KeyInput.Control = true;
- break;
- case KEY_RIGHTSHIFT:
- case KEY_LEFTSHIFT:
- irrevent.KeyInput.Shift = true;
- break;
- case KEY_ESC:
- irrevent.KeyInput.Key = (EKEY_CODE)0x1B;
- break;
- case KEY_SPACE:
- irrevent.KeyInput.Key = (EKEY_CODE)0x20;
- break;
- case KEY_UP:
- irrevent.KeyInput.Key = (EKEY_CODE)0x26;
- break;
- case KEY_LEFT:
- irrevent.KeyInput.Key = (EKEY_CODE)0x25;
- break;
- case KEY_RIGHT:
- irrevent.KeyInput.Key = (EKEY_CODE)0x27;
- break;
- case KEY_DOWN:
- irrevent.KeyInput.Key = (EKEY_CODE)0x28;
- break;
- default:
- irrevent.KeyInput.Key = (EKEY_CODE)0;
- break;
- }
- postEventFromUser(irrevent);
- }
- }
- return !Close;
- }
- //! Pause the current process for the minimum time allowed only to allow other processes to execute
- void CIrrDeviceFB::yield()
- {
- struct timespec ts = {0,0};
- nanosleep(&ts, NULL);
- }
- //! Pause execution and let other processes to run for a specified amount of time.
- void CIrrDeviceFB::sleep(u32 timeMs, bool pauseTimer=false)
- {
- bool wasStopped = Timer ? Timer->isStopped() : true;
-
- struct timespec ts;
- ts.tv_sec = (time_t) (timeMs / 1000);
- ts.tv_nsec = (long) (timeMs % 1000) * 1000000;
- if (pauseTimer && !wasStopped)
- Timer->stop();
- nanosleep(&ts, NULL);
- if (pauseTimer && !wasStopped)
- Timer->start();
- }
- //! presents a surface in the client area
- bool CIrrDeviceFB::present(video::IImage* image, void* windowId, core::rect<s32>* src )
- {
- // this is only necessary for software drivers.
- if (CreationParams.DriverType != video::EDT_SOFTWARE && CreationParams.DriverType != video::EDT_BURNINGSVIDEO)
- return false;
- if (!SoftwareImage)
- return false;
- u8* destData = SoftwareImage;
- u32 srcwidth = (u32)image->getDimension().Width;
- u32 srcheight = (u32)image->getDimension().Height;
- // clip images
- srcheight = core::min_(srcheight, CreationParams.WindowSize.Height);
- srcwidth = core::min_(srcwidth, CreationParams.WindowSize.Width);
- u8* srcdata = (u8*)image->lock();
- for (u32 y=0; y<srcheight; ++y)
- {
- video::CColorConverter::convert_viaFormat(srcdata, image->getColorFormat(), srcwidth, destData, FBColorFormat);
- srcdata+=image->getPitch();
- destData+=Pitch;
- }
- image->unlock();
- msync(SoftwareImage,CreationParams.WindowSize.Width*CreationParams.WindowSize.Height,MS_ASYNC);
- return true;
- }
- //! notifies the device that it should close itself
- void CIrrDeviceFB::closeDevice()
- {
- Close = true;
- }
- //! returns if window is active. if not, nothing need to be drawn
- bool CIrrDeviceFB::isWindowActive() const
- {
- return true;
- }
- //! returns if window has focus
- bool CIrrDeviceFB::isWindowFocused() const
- {
- return true;
- }
- //! returns if window is minimized
- bool CIrrDeviceFB::isWindowMinimized() const
- {
- return false;
- }
- //! sets the caption of the window
- void CIrrDeviceFB::setWindowCaption(const wchar_t* text)
- {
- }
- //! Sets if the window should be resizeable in windowed mode.
- void CIrrDeviceFB::setResizable(bool resize)
- {
- }
- //! Minimizes window
- void CIrrDeviceFB::minimizeWindow()
- {
- }
- //! Maximizes window
- void CIrrDeviceFB::maximizeWindow()
- {
- }
- //! Restores original window size
- void CIrrDeviceFB::restoreWindow()
- {
- }
- //! Returns the type of this device
- E_DEVICE_TYPE CIrrDeviceFB::getType() const
- {
- return EIDT_FRAMEBUFFER;
- }
- } // end namespace irr
- #endif // _IRR_USE_FB_DEVICE_
|