From: Felix Domke Date: Wed, 31 Aug 2005 03:03:49 +0000 (+0000) Subject: - add double buffering, flip, sync grc opcode, add render-idle-notify.\n - add ... X-Git-Tag: 2.6.0~5663 X-Git-Url: https://git.cweiske.de/enigma2.git/commitdiff_plain/54b9e2790954b623c99823ab64782d4e39c128bf?ds=sidebyside - add double buffering, flip, sync grc opcode, add render-idle-notify.\n - add (disabled by default) accel hooks. --- diff --git a/lib/gdi/Makefile.am b/lib/gdi/Makefile.am index c3fc6556..d5f7d97e 100644 --- a/lib/gdi/Makefile.am +++ b/lib/gdi/Makefile.am @@ -1,8 +1,11 @@ INCLUDES = \ - -I$(top_srcdir)/include + -I$(top_srcdir)/include -I$(top_srcdir)/lib/gdi/ati noinst_LIBRARIES = libenigma_gdi.a libenigma_gdi_a_SOURCES = \ region.cpp grc.cpp epng.cpp erect.cpp fb.cpp font.cpp font_arabic.cpp gfbdc.cpp \ - glcddc.cpp gpixmap.cpp lcd.cpp gfont.cpp + glcddc.cpp gpixmap.cpp lcd.cpp gfont.cpp accel.cpp + + +# ati/2dablt.cpp ati/2dcore.cpp ati/ati_core.cpp ati/test.cpp ati/2dutil.cpp diff --git a/lib/gdi/accel.cpp b/lib/gdi/accel.cpp new file mode 100644 index 00000000..dcc5db04 --- /dev/null +++ b/lib/gdi/accel.cpp @@ -0,0 +1,134 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +gAccel *gAccel::instance; + +extern int ati_accel_init(void); +extern void ati_accel_close(void); +extern void ati_accel_blit( + int src_addr, int src_width, int src_height, int src_stride, + int dst_addr, int dst_width, int dst_height, int dst_stride, + int src_x, int src_y, int width, int height, + int dst_x, int dst_y); +extern void ati_accel_fill( + int dst_addr, int dst_width, int dst_height, int dst_stride, + int x, int y, int width, int height, + unsigned long color); + +gAccel::gAccel() +{ + m_accel_addr = 0; + m_accel_phys_addr = 0; + m_accel_size = 0; + m_accel_allocation = 0; + instance = this; + +#ifdef ATI_ACCEL + ati_accel_init(); +#endif +} + +gAccel::~gAccel() +{ +#ifdef ATI_ACCEL + ati_accel_close(); +#endif + instance = 0; +} + +gAccel *gAccel::getInstance() +{ + return instance; +} + +void gAccel::setAccelMemorySpace(void *addr, int phys_addr, int size) +{ + if (m_accel_allocation) + delete[] m_accel_allocation; + + m_accel_size = size >> 12; + + m_accel_allocation = new int[m_accel_size]; + memset(m_accel_allocation, 0, sizeof(int)*m_accel_size); + + m_accel_addr = addr; + m_accel_phys_addr = phys_addr; +} + +int gAccel::blit(gSurface *dst, const gSurface *src, const ePoint &p, const eRect &area, int flags) +{ +#ifdef ATI_ACCEL + ati_accel_blit( + src->data_phys, src->x, src->y, src->stride, + dst->data_phys, dst->x, dst->y, dst->stride, + area.left(), area.top(), area.width(), area.height(), + p.x(), p.y()); + return 0; +#endif + return -1; +} + +int gAccel::fill(gSurface *dst, const eRect &area, unsigned long col) +{ +#ifdef ATI_ACCEL + ati_accel_fill( + dst->data_phys, dst->x, dst->y, dst->stride, + area.left(), area.top(), area.width(), area.height(), + col); + return 0; +#endif + return -1; +} + +int gAccel::accelAlloc(void *&addr, int &phys_addr, int size) +{ + if ((!size) || (!m_accel_allocation)) + { + eDebug("size: %d, alloc %p", m_accel_allocation); + addr = 0; + phys_addr = 0; + return -1; + } + + size += 4095; size >>= 12; + int i; + + for (i=0; i < m_accel_size - size; ++i) + { + int a; + for (a=0; a>= 12; + + int size = m_accel_allocation[phys_addr]; + + ASSERT(size > 0); + + while (size--) + m_accel_allocation[phys_addr++] = 0; +} + +eAutoInitP0 init_gAccel(eAutoInitNumbers::graphic-2, "graphics acceleration manager"); diff --git a/lib/gdi/accel.h b/lib/gdi/accel.h new file mode 100644 index 00000000..63d3bf30 --- /dev/null +++ b/lib/gdi/accel.h @@ -0,0 +1,31 @@ +#ifndef __lib_gdi_accel_h +#define __lib_gdi_accel_h + +struct gSurface; +class eRect; +class ePoint; + +class gAccel +{ +public: + static gAccel* getInstance(); + gAccel(); + ~gAccel(); + + void setAccelMemorySpace(void *addr, int phys_addr, int size); + + int blit(gSurface *dst, const gSurface *src, const ePoint &p, const eRect &area, int flags); + int fill(gSurface *dst, const eRect &area, unsigned long col); + + int accelAlloc(void *&addr, int &phys_addr, int size); + void accelFree(int phys_addr); +private: + void *m_accel_addr; + int m_accel_phys_addr; + int m_accel_size; // in blocks + int *m_accel_allocation; + + static gAccel *instance; +}; + +#endif diff --git a/lib/gdi/gfbdc.cpp b/lib/gdi/gfbdc.cpp index 8dc0a7d2..08b4586a 100644 --- a/lib/gdi/gfbdc.cpp +++ b/lib/gdi/gfbdc.cpp @@ -4,6 +4,10 @@ #include #include +#include + +#include + gFBDC *gFBDC::instance; gFBDC::gFBDC() @@ -26,8 +30,34 @@ gFBDC::gFBDC() surface.bypp = 4; surface.stride = fb->Stride(); surface.data = fb->lfb; - surface.clut.colors=256; - surface.clut.data=new gRGB[surface.clut.colors]; + surface.offset = 0; + + surface.data_phys = 50*1024*1024; // FIXME + + surface_back.type = 0; + surface_back.x = 720; + surface_back.y = 576; + surface_back.bpp = 32; + surface_back.bypp = 4; + surface_back.stride = fb->Stride(); + surface_back.offset = surface.y; + + int fb_size = surface.stride * surface.y; + + surface_back.data = fb->lfb + fb_size; + surface_back.data_phys = surface.data_phys + fb_size; + + fb_size *= 2; + + eDebug("%dkB available for acceleration surfaces.", (fb->Available() - fb_size)/1024); + + if (gAccel::getInstance()) + gAccel::getInstance()->setAccelMemorySpace(fb->lfb + fb_size, surface.data_phys + fb_size, fb->Available() - fb_size); + + surface.clut.colors = 256; + surface.clut.data = new gRGB[surface.clut.colors]; + + surface_back.clut = surface.clut; m_pixmap = new gPixmap(&surface); @@ -38,6 +68,8 @@ gFBDC::gFBDC() gFBDC::~gFBDC() { delete fb; + + delete[] surface.clut.data; instance=0; } @@ -91,8 +123,6 @@ void gFBDC::setPalette() fb->CMAP()->green[i]=ramp[surface.clut.data[i].g]<<8; fb->CMAP()->blue[i]=ramp[surface.clut.data[i].b]<<8; fb->CMAP()->transp[i]=rampalpha[surface.clut.data[i].a]<<8; - if (!fb->CMAP()->red[i]) - fb->CMAP()->red[i]=0x100; } fb->PutCMAP(); } @@ -107,6 +137,29 @@ void gFBDC::exec(gOpcode *o) setPalette(); break; } + case gOpcode::flip: + { + gSurface s(surface); + surface = surface_back; + surface_back = s; + + fb->setOffset(surface_back.offset); + break; + } + case gOpcode::waitVSync: + { + static timeval l; + timeval now; + gettimeofday(&now, 0); + + int diff = (now.tv_sec - l.tv_sec) * 1000 + (now.tv_usec - l.tv_usec) / 1000; + eDebug("%d ms latency (%d fps)", diff, 1000 / diff ?: 1); + + l = now; + + fb->waitVSync(); + break; + } default: gDC::exec(o); break; @@ -161,4 +214,3 @@ void gFBDC::reloadSettings() #ifndef SDLDC eAutoInitPtr init_gFBDC(eAutoInitNumbers::graphic-1, "GFBDC"); #endif - diff --git a/lib/gdi/gfbdc.h b/lib/gdi/gfbdc.h index dd03032e..b8ba4c7f 100644 --- a/lib/gdi/gfbdc.h +++ b/lib/gdi/gfbdc.h @@ -14,7 +14,7 @@ class gFBDC: public gDC int brightness, gamma, alpha; void calcRamp(); void setPalette(); - gSurface surface; + gSurface surface, surface_back; public: void reloadSettings(); void setAlpha(int alpha); diff --git a/lib/gdi/gpixmap.cpp b/lib/gdi/gpixmap.cpp index f0f04d69..a551984f 100644 --- a/lib/gdi/gpixmap.cpp +++ b/lib/gdi/gpixmap.cpp @@ -1,5 +1,6 @@ #include #include +#include gLookup::gLookup() :size(0), lookup(0) @@ -48,41 +49,79 @@ void gLookup::build(int _size, const gPalette &pal, const gRGB &start, const gRG } } -gSurface::~gSurface() +gSurface::gSurface() { + x = 0; + y = 0; + bpp = 0; + bypp = 0; + stride = 0; + data = 0; + data_phys = 0; + clut.colors = 0; + clut.data = 0; + type = 0; } -gSurfaceSystem::gSurfaceSystem(eSize size, int _bpp) +gSurface::gSurface(eSize size, int _bpp, int accel) { - x=size.width(); - y=size.height(); - bpp=_bpp; + x = size.width(); + y = size.height(); + bpp = _bpp; + switch (bpp) { case 8: - bypp=1; + bypp = 1; break; case 15: case 16: - bypp=2; + bypp = 2; break; case 24: // never use 24bit mode case 32: - bypp=4; + bypp = 4; break; default: - bypp=(bpp+7)/8; + bypp = (bpp+7)/8; + } + + stride = x*bypp; + + data = 0; + data_phys = 0; + + if (accel) + { + stride += 63; + stride &=~63; + + if (gAccel::getInstance()) + eDebug("accel memory: %d", gAccel::getInstance()->accelAlloc(data, data_phys, y * stride)); + else + eDebug("no accel available"); } - stride=x*bypp; - clut.colors=0; - clut.data=0; - data=malloc(x*y*bypp); + + clut.colors = 0; + clut.data = 0; + + if (!data) + data = malloc(y * stride); + + type = 1; } -gSurfaceSystem::~gSurfaceSystem() +gSurface::~gSurface() { - free(data); - delete[] clut.data; + if (type) + { + if (data_phys) + gAccel::getInstance()->accelFree(data_phys); + else + free(data); + + delete[] clut.data; + } } gPixmap *gPixmap::lock() @@ -104,26 +143,34 @@ void gPixmap::fill(const gRegion ®ion, const gColor &color) const eRect &area = region.rects[i]; if ((area.height()<=0) || (area.width()<=0)) continue; + if (surface->bpp == 8) { for (int y=area.top(); ydata)+y*surface->stride+area.left(), color.color, area.width()); } else if (surface->bpp == 32) + { + __u32 col; + + if (surface->clut.data && color < surface->clut.colors) + col=(surface->clut.data[color].a<<24)|(surface->clut.data[color].r<<16)|(surface->clut.data[color].g<<8)|(surface->clut.data[color].b); + else + col=0x10101*color; + + col^=0xFF000000; + + if (surface->data_phys && gAccel::getInstance()) + if (!gAccel::getInstance()->fill(surface, area, col)) + continue; + for (int y=area.top(); ydata)+y*surface->stride+area.left()*surface->bypp); int x=area.width(); - __u32 col; - - if (surface->clut.data && color < surface->clut.colors) - col=(surface->clut.data[color].a<<24)|(surface->clut.data[color].r<<16)|(surface->clut.data[color].g<<8)|(surface->clut.data[color].b); - else - col=0x10101*color; - col^=0xFF000000; while (x--) *dst++=col; } - else + } else eWarning("couldn't fill %d bpp", surface->bpp); } } @@ -141,6 +188,10 @@ void gPixmap::blit(const gPixmap &src, ePoint pos, const gRegion &clip, int flag eRect srcarea=area; srcarea.moveBy(-pos.x(), -pos.y()); + if ((surface->data_phys && src.surface->data_phys) && (gAccel::getInstance())) + if (!gAccel::getInstance()->blit(surface, src.surface, area.topLeft(), srcarea, flag)) + continue; + if ((surface->bpp == 8) && (src.surface->bpp==8)) { __u8 *srcptr=(__u8*)src.surface->data; @@ -171,6 +222,64 @@ void gPixmap::blit(const gPixmap &src, ePoint pos, const gRegion &clip, int flag srcptr+=src.surface->stride; dstptr+=surface->stride; } + } else if ((surface->bpp == 32) && (src.surface->bpp==32)) + { + __u32 *srcptr=(__u32*)src.surface->data; + __u32 *dstptr=(__u32*)surface->data; + + srcptr+=srcarea.left()+srcarea.top()*src.surface->stride/4; + dstptr+=area.left()+area.top()*surface->stride/4; + for (int y=0; ybypp); + srcptr+=src.surface->stride/4; + dstptr+=surface->stride/4; + } } else if ((surface->bpp == 32) && (src.surface->bpp==8)) { __u8 *srcptr=(__u8*)src.surface->data; @@ -397,8 +506,8 @@ gPixmap::gPixmap(gSurface *surface): surface(surface) { } -gPixmap::gPixmap(eSize size, int bpp) +gPixmap::gPixmap(eSize size, int bpp, int accel) { - surface = new gSurfaceSystem(size, bpp); + surface = new gSurface(size, bpp, accel); } diff --git a/lib/gdi/gpixmap.h b/lib/gdi/gpixmap.h index bd7c61a0..8ea12574 100644 --- a/lib/gdi/gpixmap.h +++ b/lib/gdi/gpixmap.h @@ -88,13 +88,12 @@ struct gSurface gPalette clut; void *data; - virtual ~gSurface(); -}; + int data_phys; + int offset; // only for backbuffers -struct gSurfaceSystem: gSurface -{ - gSurfaceSystem(eSize size, int bpp); - ~gSurfaceSystem(); + gSurface(); + gSurface(eSize size, int bpp, int accel); + ~gSurface(); }; class gPixmap: public iObject @@ -127,7 +126,7 @@ public: eSize size() const { return eSize(surface->x, surface->y); } gPixmap(gSurface *surface); - gPixmap(eSize, int bpp); + gPixmap(eSize, int bpp, int accel = 0); virtual ~gPixmap(); }; diff --git a/lib/gdi/grc.cpp b/lib/gdi/grc.cpp index 756ed9b7..99fe0859 100644 --- a/lib/gdi/grc.cpp +++ b/lib/gdi/grc.cpp @@ -22,17 +22,18 @@ void *gRC::thread_wrapper(void *ptr) gRC *gRC::instance=0; -gRC::gRC(): queue(2048), queuelock(MAXSIZE) +gRC::gRC(): queue(2048), m_notify_pump(eApp, 0), queuelock(MAXSIZE) { ASSERT(!instance); instance=this; queuelock.lock(MAXSIZE); + CONNECT(m_notify_pump.recv_msg, gRC::recv_notify); #ifndef SYNC_PAINT int res = pthread_create(&the_thread, 0, thread_wrapper, this); if (res) eFatal("RC thread couldn't be created"); else - eDebug("RC thread createted successfully"); + eDebug("RC thread created successfully"); #endif } @@ -64,7 +65,11 @@ void *gRC::thread() gOpcode& o(queue.current()); if (o.opcode==gOpcode::shutdown) break; - o.dc->exec(&o); + if (o.opcode==gOpcode::notify) + { + m_notify_pump.send(1); + } else + o.dc->exec(&o); o.dc->Release(); queue.dequeue(); } @@ -74,6 +79,11 @@ void *gRC::thread() return 0; } +void gRC::recv_notify(const int &i) +{ + notify(); +} + gRC *gRC::getInstance() { return instance; @@ -218,7 +228,7 @@ void gPainter::blit(gPixmap *pixmap, ePoint pos, const eRect &clip, int flags) o.parm.blit->pixmap = pixmap; o.parm.blit->position = pos; o.parm.blit->clip = clip; - o.flags=flags; + o.parm.blit->flags=flags; m_rc->submit(o); } @@ -337,6 +347,30 @@ void gPainter::flush() m_rc->submit(o); } +void gPainter::waitVSync() +{ + gOpcode o; + o.opcode = gOpcode::waitVSync; + o.dc = m_dc.grabRef(); + m_rc->submit(o); +} + +void gPainter::flip() +{ + gOpcode o; + o.opcode = gOpcode::flip; + o.dc = m_dc.grabRef(); + m_rc->submit(o); +} + +void gPainter::notify() +{ + gOpcode o; + o.opcode = gOpcode::notify; + o.dc = m_dc.grabRef(); + m_rc->submit(o); +} + void gPainter::end() { } @@ -500,6 +534,10 @@ void gDC::exec(gOpcode *o) m_current_offset = o->parm.setOffset->value; delete o->parm.setOffset; break; + case gOpcode::waitVSync: + break; + case gOpcode::flip: + break; case gOpcode::flush: break; default: @@ -522,4 +560,3 @@ gRGB gDC::getRGB(gColor col) DEFINE_REF(gDC); eAutoInitPtr init_grc(eAutoInitNumbers::graphic, "gRC"); - diff --git a/lib/gdi/grc.h b/lib/gdi/grc.h index 53bf7f09..82243483 100644 --- a/lib/gdi/grc.h +++ b/lib/gdi/grc.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -50,6 +51,10 @@ struct gOpcode flush, + waitVSync, + flip, + notify, + end,shutdown } opcode; @@ -128,15 +133,14 @@ struct gOpcode int rel; } *setOffset; } parm; - - int flags; }; /* gRC is the singleton which controls the fifo and dispatches commands */ -class gRC: public iObject +class gRC: public iObject, public Object { DECLARE_REF(gRC); private: + friend class gPainter; static gRC *instance; static void *thread_wrapper(void *ptr); @@ -144,6 +148,9 @@ private: void *thread(); queueRingBuffer queue; + + eFixedMessagePump m_notify_pump; + void recv_notify(const int &i); public: eLock queuelock; gRC(); @@ -164,6 +171,8 @@ public: } } + Signal0 notify; + static gRC *getInstance(); }; @@ -229,6 +238,10 @@ public: void clippop(); void flush(); + + void waitVSync(); + void flip(); + void notify(); }; class gDC: public iObject