- add double buffering, flip, sync grc opcode, add render-idle-notify.\n - add ...
authorFelix Domke <tmbinc@elitedvb.net>
Wed, 31 Aug 2005 03:03:49 +0000 (03:03 +0000)
committerFelix Domke <tmbinc@elitedvb.net>
Wed, 31 Aug 2005 03:03:49 +0000 (03:03 +0000)
lib/gdi/Makefile.am
lib/gdi/accel.cpp [new file with mode: 0644]
lib/gdi/accel.h [new file with mode: 0644]
lib/gdi/gfbdc.cpp
lib/gdi/gfbdc.h
lib/gdi/gpixmap.cpp
lib/gdi/gpixmap.h
lib/gdi/grc.cpp
lib/gdi/grc.h

index c3fc6556fd89f38712255d3586d0ba8c46da531e..d5f7d97ebbf19cfeb62ece8cff318633aadc35b3 100644 (file)
@@ -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 (file)
index 0000000..dcc5db0
--- /dev/null
@@ -0,0 +1,134 @@
+#include <lib/base/init.h>
+#include <lib/base/init_num.h>
+#include <lib/gdi/accel.h>
+#include <lib/base/eerror.h>
+#include <lib/gdi/esize.h>
+#include <lib/gdi/epoint.h>
+#include <lib/gdi/erect.h>
+#include <lib/gdi/gpixmap.h>
+
+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<size; ++a)
+                       if (m_accel_allocation[i+a])
+                               break;
+               if (a == size)
+               {
+                       m_accel_allocation[i+a] = size;
+                       for (a=1; a<size; ++a)
+                               m_accel_allocation[i+a] = -1;
+                       addr = ((unsigned char*)m_accel_addr) + (i << 12);
+                       phys_addr = m_accel_phys_addr + (i << 12);
+                       return 0;
+               }
+       }
+       return -1;
+}
+
+void gAccel::accelFree(int phys_addr)
+{
+       phys_addr -= m_accel_phys_addr;
+       phys_addr >>= 12;
+       
+       int size = m_accel_allocation[phys_addr];
+       
+       ASSERT(size > 0);
+       
+       while (size--)
+               m_accel_allocation[phys_addr++] = 0;
+}
+
+eAutoInitP0<gAccel> init_gAccel(eAutoInitNumbers::graphic-2, "graphics acceleration manager");
diff --git a/lib/gdi/accel.h b/lib/gdi/accel.h
new file mode 100644 (file)
index 0000000..63d3bf3
--- /dev/null
@@ -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
index 8dc0a7d2431c27c2cb109e4403cc4d58704316da..08b4586a6077952059e419a793e556831c6e9037 100644 (file)
@@ -4,6 +4,10 @@
 #include <lib/base/init_num.h>
 #include <lib/base/econfig.h>
 
+#include <lib/gdi/accel.h>
+
+#include <time.h>
+
 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<gFBDC> init_gFBDC(eAutoInitNumbers::graphic-1, "GFBDC");
 #endif
-
index dd03032ef78d9f5be0cc568654f3298a2bbcb043..b8ba4c7f35a6f41c38e2964a92e0ebb3bb6c2869 100644 (file)
@@ -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);
index f0f04d69237e618848ba27e69fa897dbebd98581..a551984f592d85814c83448a860a048e8d100ce0 100644 (file)
@@ -1,5 +1,6 @@
 #include <lib/gdi/gpixmap.h>
 #include <lib/gdi/region.h>
+#include <lib/gdi/accel.h>
 
 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 &region, 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(); y<area.bottom(); y++)
                                memset(((__u8*)surface->data)+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(); y<area.bottom(); y++)
                        {
                                __u32 *dst=(__u32*)(((__u8*)surface->data)+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; y<area.height(); y++)
+                       {
+                               if (flag & blitAlphaTest)
+                               {
+                                       int width=area.width();
+                                       unsigned long *src=(unsigned long*)srcptr;
+                                       unsigned long *dst=(unsigned long*)dstptr;
+
+                                       while (width--)
+                                       {
+                                               if (!((*src)&0xFF000000))
+                                               {
+                                                       src++;
+                                                       dst++;
+                                               } else
+                                                       *dst++=*src++;
+                                       }
+                               } else if (flag & blitAlphaBlend)
+                               {
+                                       // uh oh. this is only until hardware accel is working.
+                                       
+                                       int width=area.width();
+                                                       // ARGB color space!
+                                       unsigned char *src=(unsigned char*)srcptr;
+                                       unsigned char *dst=(unsigned char*)dstptr;
+
+#define BLEND(x, y, a) (y + ((x-y) * a)/256)
+                                       while (width--)
+                                       {
+                                               unsigned char sa = src[3];
+                                               unsigned char sr = src[2];
+                                               unsigned char sg = src[1];
+                                               unsigned char sb = src[0];
+
+                                               unsigned char da = dst[3];
+                                               unsigned char dr = dst[2];
+                                               unsigned char dg = dst[1];
+                                               unsigned char db = dst[0];
+                                               
+                                               dst[3] = BLEND(0xFF, da, sa);
+                                               dst[2] = BLEND(sr, dr, sa);
+                                               dst[1] = BLEND(sg, dg, sa);
+                                               dst[0] = BLEND(sb, db, sa);
+                                               
+                                               src += 4; dst += 4;
+                                       }
+                               } else
+                                       memcpy(dstptr, srcptr, area.width()*surface->bypp);
+                               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);
 }
 
index bd7c61a0f780eae6de221d65bff3c29d4a5d3f66..8ea125741cc6e9b93d301ae242f83057774a0028 100644 (file)
@@ -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();
 };
 
index 756ed9b7e724e1a3e2eb50d1905dc0f539f28673..99fe085916a5ca298332a586e81cc7763834368e 100644 (file)
@@ -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<gRC> init_grc(eAutoInitNumbers::graphic, "gRC");
-
index 53bf7f09c11fbb4737efbc6f15e70f748cb76943..8224348332440c19fd5f29bfa51609b4809e1448 100644 (file)
@@ -14,6 +14,7 @@
 #include <string>
 #include <lib/base/ringbuffer.h>
 #include <lib/base/elock.h>
+#include <lib/base/message.h>
 #include <lib/gdi/erect.h>
 #include <lib/gdi/gpixmap.h>
 #include <lib/gdi/region.h>
@@ -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<gOpcode> queue;
+       
+       eFixedMessagePump<int> m_notify_pump;
+       void recv_notify(const int &i);
 public:
        eLock queuelock;
        gRC();
@@ -164,6 +171,8 @@ public:
                }
        }
 
+       Signal0<void> notify;
+
        static gRC *getInstance();
 };
 
@@ -229,6 +238,10 @@ public:
        void clippop();
 
        void flush();
+       
+       void waitVSync();
+       void flip();
+       void notify();
 };
 
 class gDC: public iObject