From: Felix Domke Date: Fri, 21 Dec 2007 01:50:02 +0000 (+0000) Subject: add 'layers' (in buffered mode, which is not working at the moment). X-Git-Tag: 2.6.0~1644 X-Git-Url: https://git.cweiske.de/enigma2.git/commitdiff_plain/87b1a41106c4561a400536558d10dc703b3f81f4?hp=a77b04e93ff947170098f105d9780cea501fd84d;ds=sidebyside add 'layers' (in buffered mode, which is not working at the moment). --- diff --git a/lib/gui/ewidget.cpp b/lib/gui/ewidget.cpp index e75c75c1..a302cbc6 100644 --- a/lib/gui/ewidget.cpp +++ b/lib/gui/ewidget.cpp @@ -6,6 +6,7 @@ extern void dumpRegion(const gRegion ®ion); eWidget::eWidget(eWidget *parent): m_animation(this), m_parent(parent ? parent->child() : 0) { m_vis = 0; + m_layer = 0; m_desktop = 0; m_have_background_color = 0; m_z_position = 0; @@ -82,16 +83,20 @@ void eWidget::invalidate(const gRegion ®ion) return; eWidget *root = this; ePoint abspos = position(); + int target_layer = m_layer; + while (root && !root->m_desktop) { root = root->m_parent; assert(root); + if (root->m_layer != -1) + target_layer = root->m_layer; abspos += root->position(); } res.moveBy(abspos); // eDebug("region to invalidate:"); // dumpRegion(res); - root->m_desktop->invalidate(res); + root->m_desktop->invalidate(res, this, target_layer); } void eWidget::show() @@ -106,6 +111,8 @@ void eWidget::show() /* TODO: optimize here to only recalc what's required. possibly merge with hide. */ eWidget *root = this; ePoint abspos = position(); + int target_layer = m_layer; + while (root && !root->m_desktop) { root = root->m_parent; @@ -118,6 +125,8 @@ void eWidget::show() /* assert(root); */ return; } + if (root->m_layer != -1) + target_layer = root->m_layer; abspos += root->position(); } @@ -125,7 +134,7 @@ void eWidget::show() gRegion abs = m_visible_with_childs; abs.moveBy(abspos); - root->m_desktop->invalidate(abs); + root->m_desktop->invalidate(abs, this, target_layer); } void eWidget::hide() @@ -255,7 +264,7 @@ void eWidget::insertIntoParent() } } -void eWidget::doPaint(gPainter &painter, const gRegion &r) +void eWidget::doPaint(gPainter &painter, const gRegion &r, int layer) { if (m_visible_with_childs.empty()) return; @@ -264,17 +273,20 @@ void eWidget::doPaint(gPainter &painter, const gRegion &r) region.moveBy(-position()); painter.moveOffset(position()); /* check if there's anything for us to paint */ - region &= m_visible_region; - if (!region.empty()) + if (layer == m_layer) { - painter.resetClip(region); - event(evtPaint, ®ion, &painter); + region &= m_visible_region; + if (!region.empty()) + { + painter.resetClip(region); + event(evtPaint, ®ion, &painter); + } } childs.moveBy(-position()); /* walk all childs */ for (ePtrList::iterator i(m_childs.begin()); i != m_childs.end(); ++i) - i->doPaint(painter, childs); + i->doPaint(painter, childs, layer); painter.moveOffset(-position()); } diff --git a/lib/gui/ewidget.h b/lib/gui/ewidget.h index a028006c..7ddbbc57 100644 --- a/lib/gui/ewidget.h +++ b/lib/gui/ewidget.h @@ -6,6 +6,8 @@ #include /* for eWindowStyle */ #include +#define MAX_LAYER 16 + class eWidgetDesktop;class eWidgetDesktop; class eWidget @@ -62,6 +64,8 @@ private: int m_vis; + int m_layer; + ePtrList m_childs; ePoint m_position; eSize m_size; @@ -72,7 +76,7 @@ private: ePtr m_style; void insertIntoParent(); - void doPaint(gPainter &painter, const gRegion ®ion); + void doPaint(gPainter &painter, const gRegion ®ion, int layer); void recalcClipRegionsWhenVisible(); void parentRemoved(); @@ -90,7 +94,7 @@ public: // all in local space! gRegion m_clip_region, m_visible_region, m_visible_with_childs; - struct eWidgetDesktopCompBuffer *m_comp_buffer; + struct eWidgetDesktopCompBuffer *m_comp_buffer[MAX_LAYER]; enum eWidgetEvent { diff --git a/lib/gui/ewidgetdesktop.cpp b/lib/gui/ewidgetdesktop.cpp index 78c9fbcf..09c0fa1b 100644 --- a/lib/gui/ewidgetdesktop.cpp +++ b/lib/gui/ewidgetdesktop.cpp @@ -29,27 +29,34 @@ void eWidgetDesktop::addRootWidget(eWidget *root) root->m_desktop = this; /* the creation will be postponed. */ - root->m_comp_buffer = 0; + for (int i = 0; i < MAX_LAYER; ++i) + root->m_comp_buffer[i] = 0; } void eWidgetDesktop::removeRootWidget(eWidget *root) { if (m_comp_mode == cmBuffered) - removeBufferForWidget(root); + { + for (int i = 0; i < MAX_LAYER; ++i) + removeBufferForWidget(root, i); + } m_root.remove(root); } int eWidgetDesktop::movedWidget(eWidget *root) { - if ((m_comp_mode == cmBuffered) && (root->m_comp_buffer)) + if (m_comp_mode != cmBuffered) + return -1; /* native move not supported */ + + for (int i = 0; i < MAX_LAYER; ++i) { - root->m_comp_buffer->m_position = root->position(); + if (root->m_comp_buffer[i]) + root->m_comp_buffer[i]->m_position = root->position(); // redrawComposition(0); - return 0; } - - return -1; + + return 0; /* native move ok */ } void eWidgetDesktop::calcWidgetClipRegion(eWidget *widget, gRegion &parent_visible) @@ -124,60 +131,98 @@ void eWidgetDesktop::recalcClipRegions(eWidget *root) if (!root->m_vis & eWidget::wVisShow) { clearVisibility(root); - removeBufferForWidget(root); + for (int i = 0; i < MAX_LAYER; ++i) + removeBufferForWidget(root, i); return; } - if ((!root->m_comp_buffer) || (root->size() != root->m_comp_buffer->m_screen_size)) - createBufferForWidget(root); - eWidgetDesktopCompBuffer *comp = root->m_comp_buffer; + for (int i = 0; i < MAX_LAYER; ++i) + { + eWidgetDesktopCompBuffer *comp = root->m_comp_buffer[i]; - gRegion visible_before = root->m_visible_with_childs; - - comp->m_background_region = gRegion(eRect(comp->m_position, comp->m_screen_size)); - - gRegion visible_new = root->m_visible_with_childs - visible_before; - gRegion visible_lost = visible_before - root->m_visible_with_childs; - visible_new.moveBy(root->position()); - visible_lost.moveBy(root->position()); - - /* this sucks, obviously. */ - invalidate(visible_new); - invalidate(visible_lost); - - calcWidgetClipRegion(root, comp->m_background_region); + /* TODO: layers might not be required to have the screen size, for memory reasons. */ + if ((i == 0 && !comp) || (comp && (root->size() != comp->m_screen_size))) + createBufferForWidget(root, 0); + + comp = root->m_comp_buffer[i]; /* it might have changed. */ + + /* 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; + + comp->m_background_region = gRegion(eRect(comp->m_position, comp->m_screen_size)); + + gRegion visible_new = root->m_visible_with_childs - visible_before; + gRegion visible_lost = visible_before - root->m_visible_with_childs; + visible_new.moveBy(root->position()); + visible_lost.moveBy(root->position()); + + invalidate(visible_new, root, i); + invalidate(visible_lost, root, i); + + calcWidgetClipRegion(root, comp->m_background_region); + } + } +} + +void eWidgetDesktop::invalidateWidgetLayer(const gRegion ®ion, const eWidget *widget, int layer) +{ + if (m_comp_mode == cmImmediate) + { + invalidate(region); + return; } + eWidgetDesktopCompBuffer *comp = widget->m_comp_buffer[layer]; + if (comp) + comp->m_dirty_region |= region; } -void eWidgetDesktop::invalidate(const gRegion ®ion) +void eWidgetDesktop::invalidateWidget(const gRegion ®ion, const eWidget *widget, int layer) +{ + if (m_comp_mode == cmImmediate) + { + invalidate(region); + return; + } + + if (!(widget->m_vis & eWidget::wVisShow)) + return; + + gRegion mregion = region; + if (layer == -1) + for (int layer = 0; layer < MAX_LAYER; ++layer) + invalidateWidgetLayer(mregion, widget, layer); + else + invalidateWidgetLayer(mregion, widget, layer); +} + +void eWidgetDesktop::invalidate(const gRegion ®ion, const eWidget *widget, int layer) { if (region.empty()) return; - + if (m_timer && !m_require_redraw) m_timer->start(0, 1); // start singleshot redraw timer - + m_require_redraw = 1; - + if (m_comp_mode == cmImmediate) + { + /* in immediate mode, we don't care for widget and layer, we use the topmost. */ m_screen.m_dirty_region |= region; - else - for (ePtrList::iterator i(m_root.begin()); i != m_root.end(); ++i) - { - if (!(i->m_vis & eWidget::wVisShow)) - continue; - - eWidgetDesktopCompBuffer *comp = i->m_comp_buffer; - - gRegion mregion = region; - comp->m_dirty_region |= mregion; - } + } else + { + if (!widget) + for (ePtrList::iterator i(m_root.begin()); i != m_root.end(); ++i) + invalidateWidget(region, i); + else + invalidateWidget(region, widget, layer); + } } void eWidgetDesktop::setBackgroundColor(eWidgetDesktopCompBuffer *comp, gRGB col) { comp->m_background_color = col; - + /* if there's something visible from the background, redraw it with the new color. */ if (comp->m_dc && comp->m_background_region.valid() && !comp->m_background_region.empty()) { @@ -195,7 +240,11 @@ void eWidgetDesktop::setBackgroundColor(gRGB col) if (m_comp_mode == cmBuffered) for (ePtrList::iterator i(m_root.begin()); i != m_root.end(); ++i) - setBackgroundColor(i->m_comp_buffer, col); + { + for (int l = 0; l < MAX_LAYER; ++l) + if (i->m_comp_buffer[l]) + setBackgroundColor(i->m_comp_buffer[l], l ? gRGB(0, 0, 0, 0) : col); /* all layers above 0 will have a transparent background */ + } } void eWidgetDesktop::setPalette(gPixmap &pm) @@ -211,15 +260,23 @@ void eWidgetDesktop::setPalette(gPixmap &pm) { for (ePtrList::iterator i(m_root.begin()); i != m_root.end(); ++i) { - ASSERT(i->m_comp_buffer->m_dc); - gPainter painter(i->m_comp_buffer->m_dc); - painter.setPalette(&pm); + for (int l = 0; l < MAX_LAYER; ++l) + { + if (!i->m_comp_buffer[l]) + continue; + ASSERT(i->m_comp_buffer[l]->m_dc); + gPainter painter(i->m_comp_buffer[l]->m_dc); + painter.setPalette(&pm); + } } } } void eWidgetDesktop::paintBackground(eWidgetDesktopCompBuffer *comp) { + if (!comp) + return; + comp->m_dirty_region &= comp->m_background_region; gPainter painter(comp->m_dc); @@ -231,32 +288,44 @@ void eWidgetDesktop::paintBackground(eWidgetDesktopCompBuffer *comp) comp->m_dirty_region = gRegion(); } + +void eWidgetDesktop::paintLayer(eWidget *widget, int layer) +{ + eWidgetDesktopCompBuffer *comp = (m_comp_mode == cmImmediate) ? &m_screen : widget->m_comp_buffer[layer]; + if (m_comp_mode == cmImmediate) + ASSERT(layer == 0); + if (!comp) + return; + gPainter painter(comp->m_dc); + painter.moveOffset(-comp->m_position); + widget->doPaint(painter, comp->m_dirty_region, layer); + painter.resetOffset(); +} + void eWidgetDesktop::paint() { m_require_redraw = 0; - + /* walk all root windows. */ for (ePtrList::iterator i(m_root.begin()); i != m_root.end(); ++i) { - eWidgetDesktopCompBuffer *comp = (m_comp_mode == cmImmediate) ? &m_screen : i->m_comp_buffer; - + if (!(i->m_vis & eWidget::wVisShow)) continue; - - { - gPainter painter(comp->m_dc); - painter.moveOffset(-comp->m_position); - i->doPaint(painter, comp->m_dirty_region); - painter.resetOffset(); - } - if (m_comp_mode != cmImmediate) - paintBackground(comp); + if (m_comp_mode == cmImmediate) + paintLayer(i, 0); + else + for (int l = 0; l < MAX_LAYER; ++l) + { + paintLayer(i, l); + paintBackground(i->m_comp_buffer[l]); + } } - + if (m_comp_mode == cmImmediate) paintBackground(&m_screen); - + if (m_comp_mode == cmBuffered) { // redrawComposition(0); @@ -323,10 +392,11 @@ void eWidgetDesktop::setCompositionMode(int mode) if (mode == cmBuffered) for (ePtrList::iterator i(m_root.begin()); i != m_root.end(); ++i) - createBufferForWidget(*i); + createBufferForWidget(*i, 0); else for (ePtrList::iterator i(m_root.begin()); i != m_root.end(); ++i) - removeBufferForWidget(*i); + for (int l = 0; l < MAX_LAYER; ++l) + removeBufferForWidget(*i, l); } eWidgetDesktop::eWidgetDesktop(eSize size): m_mainloop(0), m_timer(0) @@ -352,40 +422,39 @@ eWidgetDesktop::~eWidgetDesktop() setCompositionMode(-1); } -void eWidgetDesktop::createBufferForWidget(eWidget *widget) +void eWidgetDesktop::createBufferForWidget(eWidget *widget, int layer) { - removeBufferForWidget(widget); - - eWidgetDesktopCompBuffer *comp = widget->m_comp_buffer = new eWidgetDesktopCompBuffer; - - eDebug("create buffer for widget, %d x %d\n", widget->size().width(), widget->size().height()); - + removeBufferForWidget(widget, layer); + + eWidgetDesktopCompBuffer *comp = widget->m_comp_buffer[layer] = new eWidgetDesktopCompBuffer; + + eDebug("create buffer for widget layer %d, %d x %d\n", layer, widget->size().width(), widget->size().height()); + eRect bbox = eRect(widget->position(), widget->size()); comp->m_position = bbox.topLeft(); comp->m_dirty_region = gRegion(eRect(ePoint(0, 0), bbox.size())); comp->m_screen_size = bbox.size(); /* TODO: configurable bit depth. */ - + /* clone palette. FIXME. */ ePtr pm = new gPixmap(comp->m_screen_size, 32, 1), pm_screen; pm->surface->clut.data = new gRGB[256]; pm->surface->clut.colors = 256; pm->surface->clut.start = 0; - - + m_screen.m_dc->getPixmap(pm_screen); - + memcpy(pm->surface->clut.data, pm_screen->surface->clut.data, 256 * sizeof(gRGB)); comp->m_dc = new gDC(pm); } -void eWidgetDesktop::removeBufferForWidget(eWidget *widget) +void eWidgetDesktop::removeBufferForWidget(eWidget *widget, int layer) { - if (widget->m_comp_buffer) + if (widget->m_comp_buffer[layer]) { - delete widget->m_comp_buffer; - widget->m_comp_buffer = 0; + delete widget->m_comp_buffer[layer]; + widget->m_comp_buffer[layer] = 0; } } @@ -405,10 +474,14 @@ void eWidgetDesktop::redrawComposition(int notified) { if (!i->isVisible()) continue; - ePtr pm; - ASSERT(i->m_comp_buffer); - i->m_comp_buffer->m_dc->getPixmap(pm); - p.blit(pm, i->m_comp_buffer->m_position, eRect(), gPixmap::blitAlphaBlend); + for (int layer = 0; layer < MAX_LAYER; ++layer) + { + ePtr pm; + if (!i->m_comp_buffer[layer]) + continue; + i->m_comp_buffer[layer]->m_dc->getPixmap(pm); + p.blit(pm, i->m_comp_buffer[layer]->m_position, eRect(), gPixmap::blitAlphaBlend); + } } // flip activates on next vsync. diff --git a/lib/gui/ewidgetdesktop.h b/lib/gui/ewidgetdesktop.h index 7237df96..7a0a36a7 100644 --- a/lib/gui/ewidgetdesktop.h +++ b/lib/gui/ewidgetdesktop.h @@ -44,7 +44,10 @@ public: void recalcClipRegions(eWidget *root); - void invalidate(const gRegion ®ion); + void invalidateWidgetLayer(const gRegion ®ion, const eWidget *widget, int layer); + void invalidateWidget(const gRegion ®ion, const eWidget *widget, int layer = -1); + void invalidate(const gRegion ®ion, const eWidget *widget = 0, int layer = -1); + void paintLayer(eWidget *widget, int layer); void paint(); void setDC(gDC *dc); @@ -80,8 +83,8 @@ private: eWidgetDesktopCompBuffer m_screen; - void createBufferForWidget(eWidget *widget); - void removeBufferForWidget(eWidget *widget); + void createBufferForWidget(eWidget *widget, int layer); + void removeBufferForWidget(eWidget *widget, int layer); void redrawComposition(int notifed); void notify();