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
--- /dev/null
+#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");
--- /dev/null
+#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
#include <lib/base/init_num.h>
#include <lib/base/econfig.h>
+#include <lib/gdi/accel.h>
+
+#include <time.h>
+
gFBDC *gFBDC::instance;
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);
gFBDC::~gFBDC()
{
delete fb;
+
+ delete[] surface.clut.data;
instance=0;
}
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();
}
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;
#ifndef SDLDC
eAutoInitPtr<gFBDC> init_gFBDC(eAutoInitNumbers::graphic-1, "GFBDC");
#endif
-
int brightness, gamma, alpha;
void calcRamp();
void setPalette();
- gSurface surface;
+ gSurface surface, surface_back;
public:
void reloadSettings();
void setAlpha(int alpha);
#include <lib/gdi/gpixmap.h>
#include <lib/gdi/region.h>
+#include <lib/gdi/accel.h>
gLookup::gLookup()
:size(0), lookup(0)
}
}
-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()
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);
}
}
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;
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;
{
}
-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);
}
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
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();
};
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
}
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();
}
return 0;
}
+void gRC::recv_notify(const int &i)
+{
+ notify();
+}
+
gRC *gRC::getInstance()
{
return instance;
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);
}
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()
{
}
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:
DEFINE_REF(gDC);
eAutoInitPtr<gRC> init_grc(eAutoInitNumbers::graphic, "gRC");
-
#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>
flush,
+ waitVSync,
+ flip,
+ notify,
+
end,shutdown
} opcode;
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);
void *thread();
queueRingBuffer<gOpcode> queue;
+
+ eFixedMessagePump<int> m_notify_pump;
+ void recv_notify(const int &i);
public:
eLock queuelock;
gRC();
}
}
+ Signal0<void> notify;
+
static gRC *getInstance();
};
void clippop();
void flush();
+
+ void waitVSync();
+ void flip();
+ void notify();
};
class gDC: public iObject