/*
Framebuffer acceleration hardware abstraction functions.
This implements stuff needed by the GL Framebuffer.
Not really accelerated ;-)
(C) 2017 Stefan Seyfried
License: GPL
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#ifdef HAVE_CONFIG_H
#include
#endif
#include
#include
#include
#include
#include
#include
#include
extern GLFramebuffer *glfb;
#include
#include
#include
#define LOGTAG "[fb_glfb] "
CFbAccelGLFB::CFbAccelGLFB()
{
fb_name = "GL ramebuffer";
}
void CFbAccelGLFB::init(const char *)
{
fd = -1;
if (!glfb) {
fprintf(stderr, LOGTAG "init: GL Framebuffer is not set up? we are doomed...\n");
return;
}
screeninfo = glfb->getScreenInfo();
stride = 4 * screeninfo.xres;
swidth = screeninfo.xres;
available = glfb->getOSDBuffer()->size(); /* allocated in glfb constructor */
lbb = lfb = reinterpret_cast(glfb->getOSDBuffer()->data());
memset(lfb, 0, available);
setMode(720, 576, 8 * sizeof(fb_pixel_t));
blit_thread = false;
/* Windows Colors */
int tr = 0xff;
paletteSetColor(0x1, 0x010101, tr);
paletteSetColor(0x2, 0x800000, tr);
paletteSetColor(0x3, 0x008000, tr);
paletteSetColor(0x4, 0x808000, tr);
paletteSetColor(0x5, 0x000080, tr);
paletteSetColor(0x6, 0x800080, tr);
paletteSetColor(0x7, 0x008080, tr);
paletteSetColor(0x8, 0xA0A0A0, tr);
paletteSetColor(0x9, 0x505050, tr);
paletteSetColor(0xA, 0xFF0000, tr);
paletteSetColor(0xB, 0x00FF00, tr);
paletteSetColor(0xC, 0xFFFF00, tr);
paletteSetColor(0xD, 0x0000FF, tr);
paletteSetColor(0xE, 0xFF00FF, tr);
paletteSetColor(0xF, 0x00FFFF, tr);
paletteSetColor(0x10, 0xFFFFFF, tr);
paletteSetColor(0x11, 0x000000, tr);
paletteSetColor(COL_BACKGROUND, 0x000000, 0x0);
paletteSet();
useBackground(false);
m_transparent = m_transparent_default;
/* start the autoblit-thread (run() function) */
OpenThreads::Thread::start();
};
CFbAccelGLFB::~CFbAccelGLFB()
{
if (blit_thread)
{
blit_thread = false;
blit(); /* wakes up the thread */
OpenThreads::Thread::join();
}
}
void CFbAccelGLFB::blit2FB(void *fbbuff, uint32_t width, uint32_t height, uint32_t xoff, uint32_t yoff, uint32_t xp, uint32_t yp, bool transp)
{
CFrameBuffer::blit2FB(fbbuff, width, height, xoff, yoff, xp, yp, transp);
blit();
}
#define BLIT_INTERVAL_MIN 40
#define BLIT_INTERVAL_MAX 250
void CFbAccelGLFB::run()
{
printf(LOGTAG "run start\n");
int64_t last_blit = 0;
blit_pending = false;
blit_thread = true;
blit_mutex.lock();
set_threadname("glfb::autoblit");
while (blit_thread) {
blit_cond.wait(&blit_mutex, blit_pending ? BLIT_INTERVAL_MIN : BLIT_INTERVAL_MAX);
int64_t now = time_monotonic_ms();
if (now - last_blit < BLIT_INTERVAL_MIN)
{
blit_pending = true;
//printf(LOGTAG "run: skipped, time %" PRId64 "\n", now - last_blit);
}
else
{
blit_pending = false;
blit_mutex.unlock();
_blit();
blit_mutex.lock();
last_blit = now;
}
}
blit_mutex.unlock();
printf(LOGTAG "run end\n");
}
void CFbAccelGLFB::blit()
{
//printf(LOGTAG "blit\n");
blit_mutex.lock();
blit_cond.signal();
blit_mutex.unlock();
}
void CFbAccelGLFB::_blit()
{
if (glfb)
glfb->blit();
}
/* wrong name... */
int CFbAccelGLFB::setMode(unsigned int, unsigned int, unsigned int)
{
xRes = screeninfo.xres;
yRes = screeninfo.yres;
bpp = screeninfo.bits_per_pixel;
int needmem = stride * yRes * 2;
if (available >= needmem)
{
backbuffer = lfb + swidth * yRes;
return 0;
}
fprintf(stderr, LOGTAG " not enough FB memory (have %d, need %d)\n", available, needmem);
backbuffer = lfb; /* will not work well, but avoid crashes */
return 0;
}
fb_pixel_t * CFbAccelGLFB::getBackBufferPointer() const
{
return backbuffer;
}