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 accel.cpp picload.cpp picexif.cpp
+ glcddc.cpp gpixmap.cpp lcd.cpp gfont.cpp accel.cpp picload.cpp picexif.cpp \
+ compositing.cpp bcm.cpp
if WITH_SDL
libenigma_gdi_a_SOURCES += sdl.cpp
#include <lib/gdi/gpixmap.h>
gAccel *gAccel::instance;
+#define BCM_ACCEL
+#ifdef ATI_ACCEL
extern int ati_accel_init(void);
extern void ati_accel_close(void);
extern void ati_accel_blit(
int dst_addr, int dst_width, int dst_height, int dst_stride,
int x, int y, int width, int height,
unsigned long color);
+#endif
+#ifdef BCM_ACCEL
+extern int bcm_accel_init(void);
+extern void bcm_accel_close(void);
+extern void bcm_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, int dwidth, int dheight);
+extern void bcm_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);
+#endif
gAccel::gAccel()
{
#ifdef ATI_ACCEL
ati_accel_init();
#endif
+#ifdef BCM_ACCEL
+ m_bcm_accel_state = bcm_accel_init();
+#endif
}
gAccel::~gAccel()
{
#ifdef ATI_ACCEL
ati_accel_close();
+#endif
+#ifdef BCM_ACCEL
+ bcm_accel_close();
#endif
instance = 0;
}
m_accel_phys_addr = phys_addr;
}
-int gAccel::blit(gSurface *dst, const gSurface *src, const ePoint &p, const eRect &area, int flags)
+int gAccel::blit(gSurface *dst, const gSurface *src, const eRect &p, const eRect &area, int flags)
{
#ifdef ATI_ACCEL
ati_accel_blit(
area.left(), area.top(), area.width(), area.height(),
p.x(), p.y());
return 0;
+#endif
+#ifdef BCM_ACCEL
+ if (!m_bcm_accel_state)
+ {
+ bcm_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(), p.width(), p.height());
+ return 0;
+ }
#endif
return -1;
}
area.left(), area.top(), area.width(), area.height(),
col);
return 0;
+#endif
+#if 0 // def BCM_ACCEL
+ bcm_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)
{
+ eDebug("accel %d bytes", size);
if ((!size) || (!m_accel_allocation))
{
eDebug("size: %d, alloc %p", size, m_accel_allocation);
size += 4095; size >>= 12;
int i;
+
+ int used = 0, free = 0, s = 0;
+ for (i=0; i < m_accel_size; ++i)
+ {
+ if (m_accel_allocation[i] == 0)
+ free++;
+ else if (m_accel_allocation[i] == -1)
+ used++;
+ else
+ {
+ used++;
+ s += m_accel_allocation[i];
+ }
+ }
+ eDebug("accel memstat: used=%d kB, free %d kB, s %d kB", used * 4, free * 4, s * 4);
for (i=0; i < m_accel_size - size; ++i)
{
break;
if (a == size)
{
- m_accel_allocation[i+a] = size;
+ m_accel_allocation[i] = size;
for (a=1; a<size; ++a)
m_accel_allocation[i+a] = -1;
addr = ((unsigned char*)m_accel_addr) + (i << 12);
return 0;
}
}
+ eDebug("accel alloc failed\n");
return -1;
}
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 blit(gSurface *dst, const gSurface *src, const eRect &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);
int m_accel_phys_addr;
int m_accel_size; // in blocks
int *m_accel_allocation;
+ int m_bcm_accel_state;
static gAccel *instance;
};
--- /dev/null
+/*
+ Interface to the Dreambox dm800/dm8000 proprietary accel interface.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <linux/fb.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+
+#define FBIO_ACCEL 0x23
+
+static unsigned int displaylist[1024];
+static int ptr;
+
+#define P(x, y) do { displaylist[ptr++] = x; displaylist[ptr++] = y; } while (0)
+#define C(x) P(x, 0)
+
+static int fb_fd;
+static int exec_list(void);
+
+int bcm_accel_init(void)
+{
+ fb_fd = open("/dev/fb/0", O_RDWR);
+ if (fb_fd < 0)
+ {
+ perror("/dev/fb/0");
+ return 1;
+ }
+ if (exec_list())
+ {
+ fprintf(stderr, "BCM accel interface not available - %m\n");
+ close(fb_fd);
+ return 1;
+ }
+ return 0;
+}
+
+void bcm_accel_close(void)
+{
+ close(fb_fd);
+}
+
+static int exec_list(void)
+{
+ int ret;
+ struct
+ {
+ void *ptr;
+ int len;
+ } l;
+
+ l.ptr = displaylist;
+ l.len = ptr;
+ ret = ioctl(fb_fd, FBIO_ACCEL, &l);
+ ptr = 0;
+ return ret;
+}
+
+void bcm_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, int dwidth, int dheight)
+{
+ C(0x43); // reset source
+ C(0x53); // reset dest
+ C(0x5b); // reset pattern
+ C(0x67); // reset blend
+ C(0x75); // reset output
+
+ P(0x0, src_addr); // set source addr
+ P(0x1, src_stride); // set source pitch
+ P(0x2, src_width); // source width
+ P(0x3, src_height); // height
+ P(0x4, 0x7e48888); // format: ARGB 8888
+
+ C(0x5); // set source surface (based on last parameters)
+
+ P(0x2e, src_x); // define rect
+ P(0x2f, src_y);
+ P(0x30, width);
+ P(0x31, height);
+
+ C(0x32); // set this rect as source rect
+
+ P(0x0, dst_addr); // prepare output surface
+ P(0x1, dst_stride);
+ P(0x2, dst_width);
+ P(0x3, dst_height);
+ P(0x4, 0x7e48888);
+
+ C(0x69); // set output surface
+
+ P(0x2e, dst_x); // prepare output rect
+ P(0x2f, dst_y);
+ P(0x30, dwidth);
+ P(0x31, dheight);
+
+ C(0x6e); // set this rect as output rect
+
+ C(0x77); // do it
+
+ exec_list();
+}
+
+void bcm_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)
+{
+// printf("unimplemented bcm_accel_fill\n");
+}
+
--- /dev/null
+#include <lib/gdi/compositing.h>
+#include <lib/gdi/grc.h>
+
+DEFINE_REF(gCompositingData);
+
+gContext::~gContext()
+{
+}
+
--- /dev/null
+#ifndef __lib_gdi_compositing_h
+#define __lib_gdi_compositing_h
+
+#include <lib/gdi/gpixmap.h>
+
+#include <vector>
+
+class gDC;
+
+struct gContext
+{
+ ePtr<gDC> m_pixmap;
+ int m_reg_int[256];
+ float m_reg_float[256];
+ ~gContext();
+};
+
+struct gCompositingElement
+{
+ std::vector<unsigned int> m_code;
+ gContext m_context;
+};
+
+class gCompositingData: public Object
+{
+DECLARE_REF(gCompositingData);
+public:
+ int execute(void); /* returns ticks until next execution */
+private:
+ std::vector<gCompositingElement> m_elements;
+ gContext m_globals;
+};
+
+#endif
static eRect emptyRect() { return eRect(0, 0, 0, 0); }
static eRect invalidRect() { return eRect(); }
+ inline void scale(int x_n, int x_d, int y_n, int y_d)
+ {
+ x1 *= x_n; x1 /= x_d;
+ x2 *= x_n; x2 /= x_d;
+ y1 *= y_n; y1 /= y_d;
+ y2 *= y_n; y2 /= y_d;
+ }
+
private:
int x1;
int y1;
}
available=fix.smem_len;
+ m_phys_mem = fix.smem_start;
eDebug("%dk video mem", available/1024);
lfb=(unsigned char*)mmap(0, available, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0);
if (!lfb)
int m_manual_blit;
int m_number_of_pages;
+ int m_phys_mem;
#ifdef SWIG
fbClass(const char *fb="/dev/fb/0");
~fbClass();
int getNumPages() { return m_number_of_pages; }
+ unsigned long getPhysAddr() { return m_phys_mem; }
+
int setOffset(int off);
int waitVSync();
void blit();
++t;
+ fb->blit();
fb->waitVSync();
break;
}
surface.data = fb->lfb;
surface.offset = 0;
- surface.data_phys = 50*1024*1024; // FIXME
+ surface.data_phys = fb->getPhysAddr();
int fb_size = surface.stride * surface.y;
}
}
+#define FIX 0x10000
-void gPixmap::blit(const gPixmap &src, ePoint pos, const gRegion &clip, int flag)
+void gPixmap::blit(const gPixmap &src, const eRect &_pos, const gRegion &clip, int flag)
{
+// eDebug("blit: -> %d.%d %d:%d -> %d.%d %d:%d, flags=%d",
+// _pos.x(), _pos.y(), _pos.width(), _pos.height(),
+// clip.extends.x(), clip.extends.y(), clip.extends.width(), clip.extends.height(),
+// flag);
+ eRect pos = _pos;
+
+// eDebug("source size: %d %d", src.size().width(), src.size().height());
+
+ if (!(flag & blitScale)) /* pos' size is valid only when scaling */
+ pos = eRect(pos.topLeft(), src.size());
+ else if (pos.size() == src.size()) /* no scaling required */
+ flag &= ~blitScale;
+
+ int scale_x = FIX, scale_y = FIX;
+
+ if (flag & blitScale)
+ {
+ ASSERT(src.size().width());
+ ASSERT(src.size().height());
+ scale_x = pos.size().width() * FIX / src.size().width();
+ scale_y = pos.size().height() * FIX / src.size().height();
+ }
+
+// eDebug("SCALE %x %x", scale_x, scale_y);
+
for (unsigned int i=0; i<clip.rects.size(); ++i)
{
- eRect area=eRect(pos, src.size());
+// eDebug("clip rect: %d %d %d %d", clip.rects[i].x(), clip.rects[i].y(), clip.rects[i].width(), clip.rects[i].height());
+ eRect area = pos; /* pos is the virtual (pre-clipping) area on the dest, which can be larger/smaller than src if scaling is enabled */
area&=clip.rects[i];
area&=eRect(ePoint(0, 0), size());
if ((area.width()<0) || (area.height()<0))
continue;
- eRect srcarea=area;
+ eRect srcarea = area;
srcarea.moveBy(-pos.x(), -pos.y());
+// eDebug("srcarea before scale: %d %d %d %d",
+// srcarea.x(), srcarea.y(), srcarea.width(), srcarea.height());
+
+ if (flag & blitScale)
+ srcarea = eRect(srcarea.x() * FIX / scale_x, srcarea.y() * FIX / scale_y, srcarea.width() * FIX / scale_x, srcarea.height() * FIX / scale_y);
+
+// eDebug("srcarea after scale: %d %d %d %d",
+// srcarea.x(), srcarea.y(), srcarea.width(), srcarea.height());
+
if ((surface->data_phys && src.surface->data_phys) && (gAccel::getInstance()))
- if (!gAccel::getInstance()->blit(surface, src.surface, area.topLeft(), srcarea, flag))
+ if (!gAccel::getInstance()->blit(surface, src.surface, area, srcarea, flag))
continue;
+ if (flag & blitScale)
+ {
+ eWarning("unimplemented: scale on non-accel surfaces");
+ continue;
+ }
+
if ((surface->bpp == 8) && (src.surface->bpp==8))
{
__u8 *srcptr=(__u8*)src.surface->data;
}
}
+#undef FIX
+
void gPixmap::mergePalette(const gPixmap &target)
{
if ((!surface->clut.colors) || (!target.surface->clut.colors))
enum
{
blitAlphaTest=1,
- blitAlphaBlend=2
+ blitAlphaBlend=2,
+ blitScale=4
};
gPixmap(gSurface *surface);
void fill(const gRegion &clip, const gColor &color);
void fill(const gRegion &clip, const gRGB &color);
- void blit(const gPixmap &src, ePoint pos, const gRegion &clip, int flags=0);
+ void blit(const gPixmap &src, const eRect &pos, const gRegion &clip, int flags=0);
void mergePalette(const gPixmap &target);
void line(const gRegion &clip, ePoint start, ePoint end, gColor color);
break;
else if (o.opcode==gOpcode::notify)
need_notify = 1;
- else if(o.dc)
+ else if (o.opcode==gOpcode::setCompositing)
+ {
+ m_compositing = o.parm.setCompositing;
+ m_compositing->Release();
+ } else if(o.dc)
{
o.dc->exec(&o);
// o.dc is a gDC* filled with grabref... so we must release it here
void gPainter::blit(gPixmap *pixmap, ePoint pos, const eRect &clip, int flags)
{
+ blitScale(pixmap, eRect(pos, eSize()), clip, flags, 0);
+}
+
+void gPainter::blitScale(gPixmap *pixmap, const eRect &position, const eRect &clip, int flags, int aflags)
+{
+ flags |= aflags;
+
if ( m_dc->islocked() )
return;
gOpcode o;
pixmap->AddRef();
o.parm.blit = new gOpcode::para::pblit;
o.parm.blit->pixmap = pixmap;
- o.parm.blit->position = pos;
o.parm.blit->clip = clip;
- o.parm.blit->flags=flags;
+ o.parm.blit->flags = flags;
+ o.parm.blit->position = position;
m_rc->submit(o);
}
-
void gPainter::setPalette(gRGB *colors, int start, int len)
{
if ( m_dc->islocked() )
m_rc->submit(o);
}
+void gPainter::setCompositing(gCompositingData *comp)
+{
+ gOpcode o;
+ o.opcode = gOpcode::setCompositing;
+ o.dc = 0;
+ o.parm.setCompositing = comp;
+ comp->AddRef(); /* will be freed in ::thread */
+ m_rc->submit(o);
+}
+
void gPainter::end()
{
if ( m_dc->islocked() )
gRegion clip;
// this code should be checked again but i'm too tired now
- o->parm.blit->position += m_current_offset;
+ o->parm.blit->position.moveBy(m_current_offset);
if (o->parm.blit->clip.valid())
{
ASSERT(m_spinner_saved);
/* save the background to restore it later. We need to negative position because we want to blit from the middle of the screen. */
- m_spinner_saved->blit(*m_pixmap, -m_spinner_pos.topLeft(), gRegion(eRect(ePoint(0, 0), m_spinner_saved->size())), 0);
+ m_spinner_saved->blit(*m_pixmap, eRect(-m_spinner_pos.topLeft(), eSize()), gRegion(eRect(ePoint(0, 0), m_spinner_saved->size())), 0);
incrementSpinner();
}
ASSERT(m_spinner_saved);
/* restore background */
- m_pixmap->blit(*m_spinner_saved, m_spinner_pos.topLeft(), gRegion(m_spinner_pos), 0);
+ m_pixmap->blit(*m_spinner_saved, eRect(m_spinner_pos.topLeft(), eSize()), gRegion(m_spinner_pos), 0);
}
void gDC::incrementSpinner()
}
#endif
- m_spinner_temp->blit(*m_spinner_saved, ePoint(0, 0), eRect(ePoint(0, 0), m_spinner_pos.size()));
+ m_spinner_temp->blit(*m_spinner_saved, eRect(0, 0, 0, 0), eRect(ePoint(0, 0), m_spinner_pos.size()));
if (m_spinner_pic[m_spinner_i])
- m_spinner_temp->blit(*m_spinner_pic[m_spinner_i], ePoint(0, 0), eRect(ePoint(0, 0), m_spinner_pos.size()), gPixmap::blitAlphaTest);
+ m_spinner_temp->blit(*m_spinner_pic[m_spinner_i], eRect(0, 0, 0, 0), eRect(ePoint(0, 0), m_spinner_pos.size()), gPixmap::blitAlphaTest);
- m_pixmap->blit(*m_spinner_temp, m_spinner_pos.topLeft(), gRegion(m_spinner_pos), 0);
+ m_pixmap->blit(*m_spinner_temp, eRect(m_spinner_pos.topLeft(), eSize()), gRegion(m_spinner_pos), 0);
m_spinner_i++;
m_spinner_i %= m_spinner_num;
}
#include <lib/gdi/gpixmap.h>
#include <lib/gdi/region.h>
#include <lib/gdi/gfont.h>
+#include <lib/gdi/compositing.h>
class eTextPara;
enableSpinner, disableSpinner, incrementSpinner,
- shutdown
+ shutdown,
+
+ setCompositing,
} opcode;
gDC *dc;
struct pblit
{
gPixmap *pixmap;
- ePoint position;
int flags;
+ eRect position;
eRect clip;
} *blit;
ePoint value;
int rel;
} *setOffset;
+
+ gCompositingData *setCompositing;
} parm;
};
void enableSpinner();
void disableSpinner();
+
+ ePtr<gCompositingData> m_compositing;
public:
gRC();
enum
{
BT_ALPHATEST = 1,
- BT_ALPHABLEND = 2
+ BT_ALPHABLEND = 2,
+ BT_SCALE = 4 /* will be automatically set by blitScale */
};
- void blit(gPixmap *pixmap, ePoint pos, const eRect &what=eRect(), int flags=0);
+ void blit(gPixmap *pixmap, ePoint pos, const eRect &clip=eRect(), int flags=0);
+ void blitScale(gPixmap *pixmap, const eRect &pos, const eRect &clip=eRect(), int flags=0, int aflags = BT_SCALE);
void setPalette(gRGB *colors, int start=0, int len=256);
void setPalette(gPixmap *source);
void waitVSync();
void flip();
void notify();
+ void setCompositing(gCompositingData *comp);
};
class gDC: public iObject
rects[i].moveBy(offset);
}
+void gRegion::scale(int x_n, int x_d, int y_n, int y_d)
+{
+ int i;
+ for (i=0; i<rects.size(); ++i)
+ rects[i].scale(x_n, x_d, y_n, y_d);
+}
+
bool valid() const { return extends.valid(); }
static gRegion invalidRegion() { return gRegion(eRect::invalidRect()); }
+
+ void scale(int x_n, int x_d, int y_n, int y_d);
};
#endif
#include <lib/gui/ewidgetdesktop.h>
ePixmap::ePixmap(eWidget *parent)
- :eWidget(parent), m_alphatest(false)
+ :eWidget(parent), m_alphatest(false), m_scale(false)
{
}
setTransparent(alphatest);
}
+void ePixmap::setScale(int scale)
+{
+ if (m_scale != scale)
+ {
+ m_scale = scale;
+ invalidate();
+ }
+}
+
void ePixmap::setPixmap(gPixmap *pixmap)
{
m_pixmap = pixmap;
flags = gPainter::BT_ALPHATEST;
else if (m_alphatest == 2)
flags = gPainter::BT_ALPHABLEND;
- painter.blit(m_pixmap, ePoint(0, 0), eRect(), flags);
+ if (m_scale)
+ painter.blitScale(m_pixmap, eRect(ePoint(0, 0), size()), eRect(), flags);
+ else
+ painter.blit(m_pixmap, ePoint(0, 0), eRect(), flags);
}
return 0;
class ePixmap: public eWidget
{
int m_alphatest;
+ int m_scale;
public:
ePixmap(eWidget *parent);
void setPixmap(ePtr<gPixmap> &pixmap);
void setPixmapFromFile(const char *filename);
void setAlphatest(int alphatest); /* 1 for alphatest, 2 for alphablend */
+ void setScale(int scale);
protected:
ePtr<gPixmap> m_pixmap;
int event(int event, void *data=0, void *data2=0);
void eSubtitleWidget::setPixmap(ePtr<gPixmap> &pixmap, gRegion changed)
{
m_pixmap = pixmap;
+
+ changed.scale(size().width(), pixmap->size().width(), size().height(), pixmap->size().height());
+
invalidate(changed);
}
eWidget::event(event, data, data2);
if (m_pixmap)
- painter.blit(m_pixmap, ePoint(0,0));
+ painter.blitScale(m_pixmap, eRect(ePoint(0, 0), size()));
else if (m_page_ok)
{
int elements = m_page.m_elements.size();
else if (m_dvb_page_ok)
{
for (std::list<eDVBSubtitleRegion>::iterator it(m_dvb_page.m_regions.begin()); it != m_dvb_page.m_regions.end(); ++it)
- painter.blit(it->m_pixmap, it->m_position);
+ {
+ /* dvb subtitles are living in their 720x576 cage... i think. check this for HD. */
+ eRect r = eRect(it->m_position, it->m_pixmap->size());
+ r.scale(size().width(), 720, size().height(), 576);
+ painter.blitScale(it->m_pixmap, r);
+ }
}
return 0;
}
m_move_start = start;
m_move_end = end;
m_active = 1;
+ m_widget->move(m_move_start);
}
createBufferForWidget(root, 0);
comp = root->m_comp_buffer[i]; /* it might have changed. */
+
+ if (!comp)
+ continue; /* WAIT, don't we need to invalidate,whatever */
/* CHECKME: don't we need to recalculate everything? after all, our buffer has changed and is likely to be cleared */
gRegion visible_before = root->m_visible_with_childs;
m_subtitle_widget = new eSubtitleWidget(parent);
m_subtitle_widget->resize(parent->size());
- eSize size = parent->size();
+ eSize size = eSize(720, 576);
if (!m_pixmap)
{
- m_pixmap = new gPixmap(size, 32);
+ m_pixmap = new gPixmap(size, 32, 1); /* allocate accel surface (if possible) */
ddvd_set_lfb(m_ddvdconfig, (unsigned char *)m_pixmap->surface->data, size.width(), size.height(), 4, size.width()*4);
run(); // start the thread
}
"off": 0,
"blend": 2,
}[value])
+ elif attrib == "scale":
+ guiObject.setScale(1)
elif attrib == "orientation": # used by eSlider
try:
guiObject.setOrientation(*