<commit_before>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights.  These rights are described in the Nokia Qt LGPL
** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qdirectfbwindowsurface.h"
#include "qdirectfbscreen.h"
#include "qdirectfbpaintengine.h"

#include <private/qwidget_p.h>
#include <qwidget.h>
#include <qwindowsystem_qws.h>
#include <qpaintdevice.h>
#include <qvarlengtharray.h>

#ifndef QT_NO_QWS_DIRECTFB

QT_BEGIN_NAMESPACE

QDirectFBWindowSurface::QDirectFBWindowSurface(DFBSurfaceFlipFlags flip, QDirectFBScreen *scr)
    : QDirectFBPaintDevice(scr)
    , sibling(0)
#ifndef QT_NO_DIRECTFB_WM
    , dfbWindow(0)
#endif
    , flipFlags(flip)
    , boundingRectFlip(scr->directFBFlags() & QDirectFBScreen::BoundingRectFlip)
{
#ifdef QT_NO_DIRECTFB_WM
    mode = Offscreen;
#endif
    setSurfaceFlags(Opaque | Buffered);
#ifdef QT_DIRECTFB_TIMING
    frames = 0;
    timer.start();
#endif
}

QDirectFBWindowSurface::QDirectFBWindowSurface(DFBSurfaceFlipFlags flip, QDirectFBScreen *scr, QWidget *widget)
    : QWSWindowSurface(widget), QDirectFBPaintDevice(scr)
    , sibling(0)
#ifndef QT_NO_DIRECTFB_WM
    , dfbWindow(0)
#endif
    , flipFlags(flip)
    , boundingRectFlip(scr->directFBFlags() & QDirectFBScreen::BoundingRectFlip)
{
#ifdef QT_NO_DIRECTFB_WM
    if (widget && widget->testAttribute(Qt::WA_PaintOnScreen)) {
        setSurfaceFlags(Opaque | RegionReserved);
        mode = Primary;
    } else {
        mode = Offscreen;
        setSurfaceFlags(Opaque | Buffered);
    }
#else
    setSurfaceFlags(Opaque | Buffered);
#endif

#ifdef QT_DIRECTFB_TIMING
    frames = 0;
    timer.start();
#endif
}

QDirectFBWindowSurface::~QDirectFBWindowSurface()
{
    releaseSurface();
    // these are not tracked by QDirectFBScreen so we don't want QDirectFBPaintDevice to release it
}

bool QDirectFBWindowSurface::isValid() const
{
    return true;
}

#ifdef QT_DIRECTFB_WM
void QDirectFBWindowSurface::raise()
{
    if (dfbWindow) {
        dfbWindow->RaiseToTop(dfbWindow);
    } else if (sibling && (!sibling->sibling || sibling->dfbWindow)) {
        sibling->raise();
    }
}

void QDirectFBWindowSurface::createWindow(const QRect &rect)
{
    IDirectFBDisplayLayer *layer = screen->dfbDisplayLayer();
    if (!layer)
        qFatal("QDirectFBWindowSurface: Unable to get primary display layer!");

    DFBWindowDescription description;
    description.caps = DWCAPS_NODECORATION|DWCAPS_DOUBLEBUFFER;
    description.flags = DWDESC_CAPS|DWDESC_SURFACE_CAPS|DWDESC_PIXELFORMAT|DWDESC_HEIGHT|DWDESC_WIDTH|DWDESC_POSX|DWDESC_POSY;

    description.posx = rect.x();
    description.posy = rect.y();
    description.width = rect.width();
    description.height = rect.height();
    description.surface_caps = DSCAPS_NONE;
    if (screen->directFBFlags() & QDirectFBScreen::VideoOnly)
        description.surface_caps |= DSCAPS_VIDEOONLY;
    const QImage::Format format = screen->pixelFormat();
    description.pixelformat = QDirectFBScreen::getSurfacePixelFormat(format);
    if (QDirectFBScreen::isPremultiplied(format))
        description.surface_caps = DSCAPS_PREMULTIPLIED;

    DFBResult result = layer->CreateWindow(layer, &description, &dfbWindow);

    if (result != DFB_OK)
        DirectFBErrorFatal("QDirectFBWindowSurface::createWindow", result);

    if (dfbSurface)
        dfbSurface->Release(dfbSurface);

    dfbWindow->GetSurface(dfbWindow, &dfbSurface);
    updateFormat();
}

static DFBResult setWindowGeometry(IDirectFBWindow *dfbWindow, const QRect &old, const QRect &rect)
{
    DFBResult result = DFB_OK;
    const bool isMove = old.isEmpty() || rect.topLeft() != old.topLeft();
    const bool isResize = rect.size() != old.size();

#if (Q_DIRECTFB_VERSION >= 0x010000)
    if (isResize && isMove) {
        result = dfbWindow->SetBounds(dfbWindow, rect.x(), rect.y(),
                                      rect.width(), rect.height());
    } else if (isResize) {
        result = dfbWindow->Resize(dfbWindow,
                                   rect.width(), rect.height());
    } else if (isMove) {
        result = dfbWindow->MoveTo(dfbWindow, rect.x(), rect.y());
    }
#else
    if (isResize) {
        result = dfbWindow->Resize(dfbWindow,
                                   rect.width(), rect.height());
    }
    if (isMove) {
        result = dfbWindow->MoveTo(dfbWindow, rect.x(), rect.y());
    }
#endif
    return result;
}
#endif // QT_NO_DIRECTFB_WM

void QDirectFBWindowSurface::setGeometry(const QRect &rect)
{
    const QRect oldRect = geometry();
    if (oldRect == rect)
        return;

    IDirectFBSurface *oldSurface = dfbSurface;
    const bool sizeChanged = oldRect.size() != rect.size();
    if (sizeChanged) {
        delete engine;
        engine = 0;
        unlockSurface();
#ifdef QT_DIRECTFB_SUBSURFACE
        releaseSubSurface();
#endif
        releaseSurface();
        Q_ASSERT(!dfbSurface);
    }

    if (rect.isNull()) {
#ifndef QT_NO_DIRECTFB_WM
        if (dfbWindow) {
            dfbWindow->Release(dfbWindow);
            dfbWindow = 0;
        }
#endif
        Q_ASSERT(!dfbSurface);
#ifdef QT_DIRECTFB_SUBSURFACE
        Q_ASSERT(!subSurface);
#endif
    } else {
#ifdef QT_DIRECTFB_WM
        if (!dfbWindow) {
            createWindow(rect);
        } else {
            setWindowGeometry(dfbWindow, oldRect, rect);
            Q_ASSERT(!sizeChanged || !dfbSurface);
            if (sizeChanged)
                dfbWindow->GetSurface(dfbWindow, &dfbSurface);
        }
#else
        IDirectFBSurface *primarySurface = screen->primarySurface();
        DFBResult result = DFB_OK;
        if (mode == Primary) {
            Q_ASSERT(primarySurface);
            if (rect == screen->region().boundingRect()) {
                dfbSurface = primarySurface;
            } else {
                const DFBRectangle r = { rect.x(), rect.y(),
                                         rect.width(), rect.height() };
                result = primarySurface->GetSubSurface(primarySurface, &r, &dfbSurface);
            }
        } else { // mode == Offscreen
            if (!dfbSurface) {
                dfbSurface = screen->createDFBSurface(rect.size(), screen->pixelFormat(), QDirectFBScreen::DontTrackSurface);
            }
        }
        if (result != DFB_OK)
            DirectFBErrorFatal("QDirectFBWindowSurface::setGeometry()", result);
#endif
    }
    if (oldSurface != dfbSurface)
        updateFormat();

    QWSWindowSurface::setGeometry(rect);
}

QByteArray QDirectFBWindowSurface::permanentState() const
{
    QByteArray state(sizeof(this), 0);
    *reinterpret_cast<const QDirectFBWindowSurface**>(state.data()) = this;
    return state;
}

void QDirectFBWindowSurface::setPermanentState(const QByteArray &state)
{
    if (state.size() == sizeof(this)) {
        sibling = *reinterpret_cast<QDirectFBWindowSurface *const*>(state.constData());
    }
}

static inline void scrollSurface(IDirectFBSurface *surface, const QRect &r, int dx, int dy)
{
    const DFBRectangle rect = { r.x(), r.y(), r.width(), r.height() };
    surface->Blit(surface, surface, &rect, r.x() + dx, r.y() + dy);
}

bool QDirectFBWindowSurface::scroll(const QRegion &region, int dx, int dy)
{
    if (!dfbSurface || !(flipFlags & DSFLIP_BLIT) || region.isEmpty())
        return false;
    dfbSurface->SetBlittingFlags(dfbSurface, DSBLIT_NOFX);
    if (region.numRects() == 1) {
        scrollSurface(dfbSurface, region.boundingRect(), dx, dy);
    } else {
        const QVector<QRect> rects = region.rects();
        const int n = rects.size();
        for (int i=0; i<n; ++i) {
            scrollSurface(dfbSurface, rects.at(i), dx, dy);
        }
    }
    return true;
}

bool QDirectFBWindowSurface::move(const QPoint &moveBy)
{
    setGeometry(geometry().translated(moveBy));
    return true;
}

// hw: XXX: copied from QWidgetPrivate::isOpaque()
inline bool isWidgetOpaque(const QWidget *w)
{
    if (w->testAttribute(Qt::WA_OpaquePaintEvent)
        || w->testAttribute(Qt::WA_PaintOnScreen))
        return true;

    const QPalette &pal = w->palette();

    if (w->autoFillBackground()) {
        const QBrush &autoFillBrush = pal.brush(w->backgroundRole());
        if (autoFillBrush.style() != Qt::NoBrush && autoFillBrush.isOpaque())
            return true;
    }

    if (!w->testAttribute(Qt::WA_NoSystemBackground)) {
        const QBrush &windowBrush = w->palette().brush(QPalette::Window);
        if (windowBrush.style() != Qt::NoBrush && windowBrush.isOpaque())
            return true;
    }

    return false;
}
void QDirectFBWindowSurface::flush(QWidget *widget, const QRegion &region,
                                   const QPoint &offset)
{
    QWidget *win = window();
    if (!win)
        return;

    QWExtra *extra = qt_widget_private(widget)->extraData();
    if (extra && extra->proxyWidget)
        return;

    // hw: make sure opacity information is updated before compositing
    const bool opaque = isWidgetOpaque(win);
    if (opaque != isOpaque()) {
        SurfaceFlags flags = surfaceFlags();
        if (opaque) {
            flags |= Opaque;
        } else {
            flags &= ~Opaque;
        }
        setSurfaceFlags(flags);
    }

#ifndef QT_NO_DIRECTFB_WM
    const quint8 winOpacity = quint8(win->windowOpacity() * 255);
    quint8 opacity;

    if (dfbWindow) {
        dfbWindow->GetOpacity(dfbWindow, &opacity);
        if (winOpacity != opacity)
            dfbWindow->SetOpacity(dfbWindow, winOpacity);
    }
#endif

    const QRect windowGeometry = QDirectFBWindowSurface::geometry();
#ifdef QT_NO_DIRECTFB_WM
    if (mode == Offscreen) {
        screen->exposeRegion(region.translated(offset + geometry().topLeft()), 0);

    } else
#endif
        screen->flipSurface(dfbSurface, flipFlags, region, offset);

#ifdef QT_DIRECTFB_TIMING
    enum { Secs = 3 };
    ++frames;
    if (timer.elapsed() >= Secs * 1000) {
        qDebug("%d fps", int(double(frames) / double(Secs)));
        frames = 0;
        timer.restart();
    }
#endif
}

void QDirectFBWindowSurface::beginPaint(const QRegion &)
{
    if (!engine) {
        engine = new QDirectFBPaintEngine(this);
    }
}

void QDirectFBWindowSurface::endPaint(const QRegion &)
{
#ifdef QT_NO_DIRECTFB_SUBSURFACE
    unlockSurface();
#endif
}

IDirectFBSurface *QDirectFBWindowSurface::directFBSurface() const
{
    if (!dfbSurface && sibling && sibling->dfbSurface)
        return sibling->dfbSurface;
    return dfbSurface;
}

IDirectFBSurface *QDirectFBWindowSurface::surfaceForWidget(const QWidget *widget, QRect *rect) const
{
    Q_ASSERT(widget);
    if (!dfbSurface) {
        if (sibling && (!sibling->sibling || sibling->dfbSurface))
            return sibling->surfaceForWidget(widget, rect);
        return 0;
    }
    QWidget *win = window();
    Q_ASSERT(win);
    if (rect) {
        if (win == widget) {
            *rect = widget->rect();
        } else {
            *rect = QRect(widget->mapTo(win, QPoint(0, 0)), widget->size());
        }
    }
    Q_ASSERT(win == widget || widget->isAncestorOf(win));
    return dfbSurface;
}

void QDirectFBWindowSurface::updateFormat()
{
    imageFormat = dfbSurface ? QDirectFBScreen::getImageFormat(dfbSurface) : QImage::Format_Invalid;
}

void QDirectFBWindowSurface::releaseSurface()
{
    if (dfbSurface) {
#ifdef QT_NO_DIRECTFB_SUBSURFACE
        if (lockFlgs)
            unlockSurface();
#endif
#ifdef QT_NO_DIRECTFB_WM
        Q_ASSERT(screen->primarySurface());
        if (dfbSurface != screen->primarySurface())
#endif

            dfbSurface->Release(dfbSurface);
        dfbSurface = 0;
    }
}

QT_END_NAMESPACE

#endif // QT_NO_QWS_DIRECTFB

<commit_msg>memset DFBWindowDescription to 0<commit_after>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights.  These rights are described in the Nokia Qt LGPL
** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qdirectfbwindowsurface.h"
#include "qdirectfbscreen.h"
#include "qdirectfbpaintengine.h"

#include <private/qwidget_p.h>
#include <qwidget.h>
#include <qwindowsystem_qws.h>
#include <qpaintdevice.h>
#include <qvarlengtharray.h>

#ifndef QT_NO_QWS_DIRECTFB

QT_BEGIN_NAMESPACE

QDirectFBWindowSurface::QDirectFBWindowSurface(DFBSurfaceFlipFlags flip, QDirectFBScreen *scr)
    : QDirectFBPaintDevice(scr)
    , sibling(0)
#ifndef QT_NO_DIRECTFB_WM
    , dfbWindow(0)
#endif
    , flipFlags(flip)
    , boundingRectFlip(scr->directFBFlags() & QDirectFBScreen::BoundingRectFlip)
{
#ifdef QT_NO_DIRECTFB_WM
    mode = Offscreen;
#endif
    setSurfaceFlags(Opaque | Buffered);
#ifdef QT_DIRECTFB_TIMING
    frames = 0;
    timer.start();
#endif
}

QDirectFBWindowSurface::QDirectFBWindowSurface(DFBSurfaceFlipFlags flip, QDirectFBScreen *scr, QWidget *widget)
    : QWSWindowSurface(widget), QDirectFBPaintDevice(scr)
    , sibling(0)
#ifndef QT_NO_DIRECTFB_WM
    , dfbWindow(0)
#endif
    , flipFlags(flip)
    , boundingRectFlip(scr->directFBFlags() & QDirectFBScreen::BoundingRectFlip)
{
#ifdef QT_NO_DIRECTFB_WM
    if (widget && widget->testAttribute(Qt::WA_PaintOnScreen)) {
        setSurfaceFlags(Opaque | RegionReserved);
        mode = Primary;
    } else {
        mode = Offscreen;
        setSurfaceFlags(Opaque | Buffered);
    }
#else
    setSurfaceFlags(Opaque | Buffered);
#endif

#ifdef QT_DIRECTFB_TIMING
    frames = 0;
    timer.start();
#endif
}

QDirectFBWindowSurface::~QDirectFBWindowSurface()
{
    releaseSurface();
    // these are not tracked by QDirectFBScreen so we don't want QDirectFBPaintDevice to release it
}

bool QDirectFBWindowSurface::isValid() const
{
    return true;
}

#ifdef QT_DIRECTFB_WM
void QDirectFBWindowSurface::raise()
{
    if (dfbWindow) {
        dfbWindow->RaiseToTop(dfbWindow);
    } else if (sibling && (!sibling->sibling || sibling->dfbWindow)) {
        sibling->raise();
    }
}

void QDirectFBWindowSurface::createWindow(const QRect &rect)
{
    IDirectFBDisplayLayer *layer = screen->dfbDisplayLayer();
    if (!layer)
        qFatal("QDirectFBWindowSurface: Unable to get primary display layer!");

    DFBWindowDescription description;
    memset(&description, 0, sizeof(DFBWindowDescription));

    description.caps = DWCAPS_NODECORATION|DWCAPS_DOUBLEBUFFER;
    description.flags = DWDESC_CAPS|DWDESC_SURFACE_CAPS|DWDESC_PIXELFORMAT|DWDESC_HEIGHT|DWDESC_WIDTH|DWDESC_POSX|DWDESC_POSY;

    description.posx = rect.x();
    description.posy = rect.y();
    description.width = rect.width();
    description.height = rect.height();
    description.surface_caps = DSCAPS_NONE;
    if (screen->directFBFlags() & QDirectFBScreen::VideoOnly)
        description.surface_caps |= DSCAPS_VIDEOONLY;
    const QImage::Format format = screen->pixelFormat();
    description.pixelformat = QDirectFBScreen::getSurfacePixelFormat(format);
    if (QDirectFBScreen::isPremultiplied(format))
        description.surface_caps = DSCAPS_PREMULTIPLIED;

    DFBResult result = layer->CreateWindow(layer, &description, &dfbWindow);

    if (result != DFB_OK)
        DirectFBErrorFatal("QDirectFBWindowSurface::createWindow", result);

    if (dfbSurface)
        dfbSurface->Release(dfbSurface);

    dfbWindow->GetSurface(dfbWindow, &dfbSurface);
    updateFormat();
}

static DFBResult setWindowGeometry(IDirectFBWindow *dfbWindow, const QRect &old, const QRect &rect)
{
    DFBResult result = DFB_OK;
    const bool isMove = old.isEmpty() || rect.topLeft() != old.topLeft();
    const bool isResize = rect.size() != old.size();

#if (Q_DIRECTFB_VERSION >= 0x010000)
    if (isResize && isMove) {
        result = dfbWindow->SetBounds(dfbWindow, rect.x(), rect.y(),
                                      rect.width(), rect.height());
    } else if (isResize) {
        result = dfbWindow->Resize(dfbWindow,
                                   rect.width(), rect.height());
    } else if (isMove) {
        result = dfbWindow->MoveTo(dfbWindow, rect.x(), rect.y());
    }
#else
    if (isResize) {
        result = dfbWindow->Resize(dfbWindow,
                                   rect.width(), rect.height());
    }
    if (isMove) {
        result = dfbWindow->MoveTo(dfbWindow, rect.x(), rect.y());
    }
#endif
    return result;
}
#endif // QT_NO_DIRECTFB_WM

void QDirectFBWindowSurface::setGeometry(const QRect &rect)
{
    const QRect oldRect = geometry();
    if (oldRect == rect)
        return;

    IDirectFBSurface *oldSurface = dfbSurface;
    const bool sizeChanged = oldRect.size() != rect.size();
    if (sizeChanged) {
        delete engine;
        engine = 0;
        unlockSurface();
#ifdef QT_DIRECTFB_SUBSURFACE
        releaseSubSurface();
#endif
        releaseSurface();
        Q_ASSERT(!dfbSurface);
    }

    if (rect.isNull()) {
#ifndef QT_NO_DIRECTFB_WM
        if (dfbWindow) {
            dfbWindow->Release(dfbWindow);
            dfbWindow = 0;
        }
#endif
        Q_ASSERT(!dfbSurface);
#ifdef QT_DIRECTFB_SUBSURFACE
        Q_ASSERT(!subSurface);
#endif
    } else {
#ifdef QT_DIRECTFB_WM
        if (!dfbWindow) {
            createWindow(rect);
        } else {
            setWindowGeometry(dfbWindow, oldRect, rect);
            Q_ASSERT(!sizeChanged || !dfbSurface);
            if (sizeChanged)
                dfbWindow->GetSurface(dfbWindow, &dfbSurface);
        }
#else
        IDirectFBSurface *primarySurface = screen->primarySurface();
        DFBResult result = DFB_OK;
        if (mode == Primary) {
            Q_ASSERT(primarySurface);
            if (rect == screen->region().boundingRect()) {
                dfbSurface = primarySurface;
            } else {
                const DFBRectangle r = { rect.x(), rect.y(),
                                         rect.width(), rect.height() };
                result = primarySurface->GetSubSurface(primarySurface, &r, &dfbSurface);
            }
        } else { // mode == Offscreen
            if (!dfbSurface) {
                dfbSurface = screen->createDFBSurface(rect.size(), screen->pixelFormat(), QDirectFBScreen::DontTrackSurface);
            }
        }
        if (result != DFB_OK)
            DirectFBErrorFatal("QDirectFBWindowSurface::setGeometry()", result);
#endif
    }
    if (oldSurface != dfbSurface)
        updateFormat();

    QWSWindowSurface::setGeometry(rect);
}

QByteArray QDirectFBWindowSurface::permanentState() const
{
    QByteArray state(sizeof(this), 0);
    *reinterpret_cast<const QDirectFBWindowSurface**>(state.data()) = this;
    return state;
}

void QDirectFBWindowSurface::setPermanentState(const QByteArray &state)
{
    if (state.size() == sizeof(this)) {
        sibling = *reinterpret_cast<QDirectFBWindowSurface *const*>(state.constData());
    }
}

static inline void scrollSurface(IDirectFBSurface *surface, const QRect &r, int dx, int dy)
{
    const DFBRectangle rect = { r.x(), r.y(), r.width(), r.height() };
    surface->Blit(surface, surface, &rect, r.x() + dx, r.y() + dy);
}

bool QDirectFBWindowSurface::scroll(const QRegion &region, int dx, int dy)
{
    if (!dfbSurface || !(flipFlags & DSFLIP_BLIT) || region.isEmpty())
        return false;
    dfbSurface->SetBlittingFlags(dfbSurface, DSBLIT_NOFX);
    if (region.numRects() == 1) {
        scrollSurface(dfbSurface, region.boundingRect(), dx, dy);
    } else {
        const QVector<QRect> rects = region.rects();
        const int n = rects.size();
        for (int i=0; i<n; ++i) {
            scrollSurface(dfbSurface, rects.at(i), dx, dy);
        }
    }
    return true;
}

bool QDirectFBWindowSurface::move(const QPoint &moveBy)
{
    setGeometry(geometry().translated(moveBy));
    return true;
}

// hw: XXX: copied from QWidgetPrivate::isOpaque()
inline bool isWidgetOpaque(const QWidget *w)
{
    if (w->testAttribute(Qt::WA_OpaquePaintEvent)
        || w->testAttribute(Qt::WA_PaintOnScreen))
        return true;

    const QPalette &pal = w->palette();

    if (w->autoFillBackground()) {
        const QBrush &autoFillBrush = pal.brush(w->backgroundRole());
        if (autoFillBrush.style() != Qt::NoBrush && autoFillBrush.isOpaque())
            return true;
    }

    if (!w->testAttribute(Qt::WA_NoSystemBackground)) {
        const QBrush &windowBrush = w->palette().brush(QPalette::Window);
        if (windowBrush.style() != Qt::NoBrush && windowBrush.isOpaque())
            return true;
    }

    return false;
}
void QDirectFBWindowSurface::flush(QWidget *widget, const QRegion &region,
                                   const QPoint &offset)
{
    QWidget *win = window();
    if (!win)
        return;

    QWExtra *extra = qt_widget_private(widget)->extraData();
    if (extra && extra->proxyWidget)
        return;

    // hw: make sure opacity information is updated before compositing
    const bool opaque = isWidgetOpaque(win);
    if (opaque != isOpaque()) {
        SurfaceFlags flags = surfaceFlags();
        if (opaque) {
            flags |= Opaque;
        } else {
            flags &= ~Opaque;
        }
        setSurfaceFlags(flags);
    }

#ifndef QT_NO_DIRECTFB_WM
    const quint8 winOpacity = quint8(win->windowOpacity() * 255);
    quint8 opacity;

    if (dfbWindow) {
        dfbWindow->GetOpacity(dfbWindow, &opacity);
        if (winOpacity != opacity)
            dfbWindow->SetOpacity(dfbWindow, winOpacity);
    }
#endif

    const QRect windowGeometry = QDirectFBWindowSurface::geometry();
#ifdef QT_NO_DIRECTFB_WM
    if (mode == Offscreen) {
        screen->exposeRegion(region.translated(offset + geometry().topLeft()), 0);

    } else
#endif
        screen->flipSurface(dfbSurface, flipFlags, region, offset);

#ifdef QT_DIRECTFB_TIMING
    enum { Secs = 3 };
    ++frames;
    if (timer.elapsed() >= Secs * 1000) {
        qDebug("%d fps", int(double(frames) / double(Secs)));
        frames = 0;
        timer.restart();
    }
#endif
}

void QDirectFBWindowSurface::beginPaint(const QRegion &)
{
    if (!engine) {
        engine = new QDirectFBPaintEngine(this);
    }
}

void QDirectFBWindowSurface::endPaint(const QRegion &)
{
#ifdef QT_NO_DIRECTFB_SUBSURFACE
    unlockSurface();
#endif
}

IDirectFBSurface *QDirectFBWindowSurface::directFBSurface() const
{
    if (!dfbSurface && sibling && sibling->dfbSurface)
        return sibling->dfbSurface;
    return dfbSurface;
}

IDirectFBSurface *QDirectFBWindowSurface::surfaceForWidget(const QWidget *widget, QRect *rect) const
{
    Q_ASSERT(widget);
    if (!dfbSurface) {
        if (sibling && (!sibling->sibling || sibling->dfbSurface))
            return sibling->surfaceForWidget(widget, rect);
        return 0;
    }
    QWidget *win = window();
    Q_ASSERT(win);
    if (rect) {
        if (win == widget) {
            *rect = widget->rect();
        } else {
            *rect = QRect(widget->mapTo(win, QPoint(0, 0)), widget->size());
        }
    }
    Q_ASSERT(win == widget || widget->isAncestorOf(win));
    return dfbSurface;
}

void QDirectFBWindowSurface::updateFormat()
{
    imageFormat = dfbSurface ? QDirectFBScreen::getImageFormat(dfbSurface) : QImage::Format_Invalid;
}

void QDirectFBWindowSurface::releaseSurface()
{
    if (dfbSurface) {
#ifdef QT_NO_DIRECTFB_SUBSURFACE
        if (lockFlgs)
            unlockSurface();
#endif
#ifdef QT_NO_DIRECTFB_WM
        Q_ASSERT(screen->primarySurface());
        if (dfbSurface != screen->primarySurface())
#endif

            dfbSurface->Release(dfbSurface);
        dfbSurface = 0;
    }
}

QT_END_NAMESPACE

#endif // QT_NO_QWS_DIRECTFB

<|endoftext|>


<commit_before>#include "leansand.h"

SDL_Window* window;
SDL_Renderer* renderer;
SDL_Texture* texture;
uint32_t* pixmap;

SDL_Event event;

LeanSandGame game;

bool quitted = false;
unsigned int currTime;
unsigned int deltaTime;

int main (int argc, char** argv) {

  // Redirect stdout / stderr to files

  std::ofstream new_cerr("stderr.txt");
  std::streambuf* old_cerr = cerr.rdbuf();
  cerr.rdbuf(new_cerr.rdbuf());

  std::ofstream new_cout("stdout.txt");
  std::streambuf* old_cout = cout.rdbuf();
  cout.rdbuf(new_cout.rdbuf());

  // TODO: do things with command-line arguments

  cout << "leansand v" VERSION << "\n";

  // Display starting time

  {
    time_t    actualTime;
    struct tm time_struct;
    char      buf[40];
    time(&actualTime);
    time_struct =  *localtime(&actualTime);
    strftime(buf, sizeof(buf), "%Y-%m-%d %X", &time_struct);
    cout << "starting at " << buf << "\n";
  }

  // Startup SDL

  SDL_Init(SDL_INIT_VIDEO);
  currTime = SDL_GetTicks();

  window = SDL_CreateWindow("leansand v" VERSION,
                            SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
                            WIDTH, HEIGHT,
                            SDL_WINDOW_OPENGL);

  if (window == NULL) {
    cerr << "Could not create a window: " << SDL_GetError() << endl;
    return EXIT_FAILURE;
  }

  renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);

  // Configure renderer

  // These let us go fullscreen later on and still render at WIDTH x HEIGHT
  SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
  SDL_RenderSetLogicalSize(renderer, WIDTH, HEIGHT);

  // Create our screen texture

  texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888,
                              SDL_TEXTUREACCESS_STREAMING, WIDTH, HEIGHT);

  try {
    pixmap = new uint32_t[WIDTH * HEIGHT];
  } catch (exception& e) {
    cerr << "Could not allocate " << WIDTH * HEIGHT << " pixels, crashing...\n";
    cerr << e.what() << endl;

    cerr.flush();
    return EXIT_FAILURE;
  }

  // Begin game loop

  while (!quitted && game.isRunning()) {

    deltaTime = SDL_GetTicks() - currTime;

    if (!game.isPaused()) {
      game.update(currTime + deltaTime, deltaTime);
      game.draw(pixmap);

      SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
      SDL_RenderClear(renderer);

      SDL_UpdateTexture(texture, NULL, pixmap, WIDTH * sizeof(uint32_t));
      SDL_RenderCopy(renderer, texture, NULL, NULL);
    }

    SDL_RenderPresent(renderer);

    while (SDL_PollEvent(&event)) {
      switch (event.type) {
        case SDL_QUIT:
          quitted = true;
          break;

        case SDL_KEYDOWN:
          game.onKeyDown( (SDL_KeyboardEvent*) &event );
          break;
      }
    }

    // Give the user 10 ms per tick to keep a nice 60 fps
    SDL_Delay((1000/TARGET_FPS) - 10);

    currTime = SDL_GetTicks();
  }

  // End game loop; the game is quitting gracefully.

  SDL_DestroyWindow(window);

  cout.flush();
  cerr.flush();

  // Reset redirected buffers

  cout.rdbuf(old_cout);
  cerr.rdbuf(old_cerr);

  // And done!
  SDL_Quit();
  return EXIT_SUCCESS;
}
<commit_msg>Add basic FPS counter, prints to console<commit_after>#include "leansand.h"

SDL_Window* window;
SDL_Renderer* renderer;
SDL_Texture* texture;
uint32_t* pixmap;

SDL_Event event;

LeanSandGame game;

#define FPS_TH 16
int lastFrames[FPS_TH];
int lastFramesPos = 0;

bool quitted = false;
unsigned int currTime;
unsigned int deltaTime;

int main (int argc, char** argv) {

  // Redirect stdout / stderr to files

  std::ofstream new_cerr("stderr.txt");
  std::streambuf* old_cerr = cerr.rdbuf();
  cerr.rdbuf(new_cerr.rdbuf());

  std::ofstream new_cout("stdout.txt");
  std::streambuf* old_cout = cout.rdbuf();
  cout.rdbuf(new_cout.rdbuf());

  // TODO: do things with command-line arguments

  cout << "leansand v" VERSION << "\n";

  // Display starting time

  {
    time_t    actualTime;
    struct tm time_struct;
    char      buf[40];
    time(&actualTime);
    time_struct =  *localtime(&actualTime);
    strftime(buf, sizeof(buf), "%Y-%m-%d %X", &time_struct);
    cout << "starting at " << buf << "\n";
  }

  // Startup SDL

  SDL_Init(SDL_INIT_VIDEO);
  currTime = SDL_GetTicks();

  window = SDL_CreateWindow("leansand v" VERSION,
                            SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
                            WIDTH, HEIGHT,
                            SDL_WINDOW_OPENGL);

  if (window == NULL) {
    cerr << "Could not create a window: " << SDL_GetError() << endl;
    return EXIT_FAILURE;
  }

  renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);

  // Configure renderer

  // These let us go fullscreen later on and still render at WIDTH x HEIGHT
  SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
  SDL_RenderSetLogicalSize(renderer, WIDTH, HEIGHT);

  // Create our screen texture

  texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888,
                              SDL_TEXTUREACCESS_STREAMING, WIDTH, HEIGHT);

  try {
    pixmap = new uint32_t[WIDTH * HEIGHT];
  } catch (exception& e) {
    cerr << "Could not allocate " << WIDTH * HEIGHT << " pixels, crashing...\n";
    cerr << e.what() << endl;

    cerr.flush();
    return EXIT_FAILURE;
  }

  // Begin game loop

  while (!quitted && game.isRunning()) {

    deltaTime = SDL_GetTicks() - currTime;

    if (!game.isPaused()) {
      game.update(currTime + deltaTime, deltaTime);
      game.draw(pixmap);

      SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
      SDL_RenderClear(renderer);

      SDL_UpdateTexture(texture, NULL, pixmap, WIDTH * sizeof(uint32_t));
      SDL_RenderCopy(renderer, texture, NULL, NULL);
    }

    SDL_RenderPresent(renderer);

    while (SDL_PollEvent(&event)) {
      switch (event.type) {
        case SDL_QUIT:
          quitted = true;
          break;

        case SDL_KEYDOWN:
          game.onKeyDown( (SDL_KeyboardEvent*) &event );
          break;
      }
    }

    // Give the user 10 ms per tick to keep a nice 60 fps
    //SDL_Delay((1000/TARGET_FPS) - 10);

    currTime = SDL_GetTicks();
    lastFrames[lastFramesPos] = SDL_GetTicks();
    lastFramesPos = (lastFramesPos + 1) % FPS_TH;
    int totalDiff = 0, i;
    for(i = lastFramesPos; i < lastFramesPos + FPS_TH - 1; i++)
      totalDiff += lastFrames[(i + 1) % FPS_TH] - lastFrames[i % FPS_TH];
      printf("FPS: %.0f, Delta: %.3f\n",FPS_TH * 1000.0f / totalDiff, totalDiff / (float)FPS_TH);

  }

  // End game loop; the game is quitting gracefully.

  SDL_DestroyWindow(window);

  cout.flush();
  cerr.flush();

  // Reset redirected buffers

  cout.rdbuf(old_cout);
  cerr.rdbuf(old_cerr);

  // And done!
  SDL_Quit();
  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qcontactsaverequest.h"
#include "qcontactrequests_p.h"

QTM_BEGIN_NAMESPACE

/*!
  \class QContactSaveRequest
  \brief The QContactSaveRequest class allows a client to asynchronously
    request that certain contacts be saved to a contacts store.

  For a QContactSaveRequest, the resultsAvailable() signal will be emitted when
  either the individual item errors (which may be retrieved by calling errorMap()), or the resultant
  contacts (which may be retrieved by calling contacts()), are updated, as well as if
  the overall operation error (which may be retrieved by calling error()) is updated.

  Please see the class documentation of QContactAbstractRequest for more information about
  the usage of request classes and ownership semantics.

  \inmodule QtContacts

  \ingroup contacts-requests
 */

/*! Constructs a new contact save request whose parent is the specified \a parent */
QContactSaveRequest::QContactSaveRequest(QObject* parent)
    : QContactAbstractRequest(new QContactSaveRequestPrivate, parent)
{
}

/*! Frees any memory used by this request */
QContactSaveRequest::~QContactSaveRequest()
{
    QContactAbstractRequestPrivate::notifyEngine(this);
}

/*!
  Sets the contact to be saved to \a contact.
  Equivalent to calling:
  \code
      setContacts(QList<QContact>() << contact);
  \endcode
 */
void QContactSaveRequest::setContact(const QContact& contact)
{
    Q_D(QContactSaveRequest);
    QMutexLocker ml(&d->m_mutex);
    d->m_contacts.clear();
    d->m_contacts.append(contact);
}

/*! Sets the list of contacts to be saved to \a contacts */
void QContactSaveRequest::setContacts(const QList<QContact>& contacts)
{
    Q_D(QContactSaveRequest);
    QMutexLocker ml(&d->m_mutex);
    d->m_contacts = contacts;
}

/*! Returns the list of contacts which will be saved if called prior to calling \c start(),
    otherwise returns the list of contacts as they were saved in the contacts store */
QList<QContact> QContactSaveRequest::contacts() const
{
    Q_D(const QContactSaveRequest);
    QMutexLocker ml(&d->m_mutex);
    return d->m_contacts;
}

/*! Returns the map of input definition list indices to errors which occurred */
QMap<int, QContactManager::Error> QContactSaveRequest::errorMap() const
{
    Q_D(const QContactSaveRequest);
    QMutexLocker ml(&d->m_mutex);
    return d->m_errors;
}

/*!
    Set the list of definitions to restrict saving to \a definitionMask.  This allows you to perform
    partial save (and remove) operations on existing contacts.

    If \a definitionMask is empty (the default), no restrictions will apply, and the passed
    in contacts will be saved as is.  Otherwise, only details whose definitions are in
    the list will be saved.  If a definition name is present in the list, but there are no
    corresponding details in the contact passed into this request, any existing details in
    the manager for that contact will be removed.

    This is useful if you've used a fetch hint to fetch a partial contact from a manager
    so that you can save changes to the details you actually fetched without removing
    the details you didn't.

    Additionally, when performing synchronization operations with other managers that don't
    support the full range of details, you can restrict the update operation to only those
    details so that you don't lose the extra details that are supported in this manager.

    \note Some managers do not support partial updates natively, in which case the QtContacts
    framework will emulate the functionality (fetching the whole contact, applying the
    new restricted details, and saving the contact back).
*/
void QContactSaveRequest::setDefinitionMask(const QStringList &definitionMask)
{
    Q_D(QContactSaveRequest);
    QMutexLocker ml(&d->m_mutex);
    d->m_definitionMask = definitionMask;
}

/*!
    Returns the list of definitions that this request will operate on.

    If the list is empty, the request will operate on all details.
 */
QStringList QContactSaveRequest::definitionMask() const
{
    Q_D(const QContactSaveRequest);
    QMutexLocker ml(&d->m_mutex);
    return d->m_definitionMask;
}

#include "moc_qcontactsaverequest.cpp"

QTM_END_NAMESPACE
<commit_msg>Doc tweak.<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qcontactsaverequest.h"
#include "qcontactrequests_p.h"

QTM_BEGIN_NAMESPACE

/*!
  \class QContactSaveRequest
  \brief The QContactSaveRequest class allows a client to asynchronously
    request that certain contacts be saved to a contacts store.

  For a QContactSaveRequest, the resultsAvailable() signal will be emitted when
  either the individual item errors (which may be retrieved by calling errorMap()), or the resultant
  contacts (which may be retrieved by calling contacts()), are updated, as well as if
  the overall operation error (which may be retrieved by calling error()) is updated.

  Please see the class documentation of QContactAbstractRequest for more information about
  the usage of request classes and ownership semantics.

  \inmodule QtContacts

  \ingroup contacts-requests
 */

/*! Constructs a new contact save request whose parent is the specified \a parent */
QContactSaveRequest::QContactSaveRequest(QObject* parent)
    : QContactAbstractRequest(new QContactSaveRequestPrivate, parent)
{
}

/*! Frees any memory used by this request */
QContactSaveRequest::~QContactSaveRequest()
{
    QContactAbstractRequestPrivate::notifyEngine(this);
}

/*!
  Sets the contact to be saved to \a contact.
  Equivalent to calling:
  \code
      setContacts(QList<QContact>() << contact);
  \endcode
 */
void QContactSaveRequest::setContact(const QContact& contact)
{
    Q_D(QContactSaveRequest);
    QMutexLocker ml(&d->m_mutex);
    d->m_contacts.clear();
    d->m_contacts.append(contact);
}

/*! Sets the list of contacts to be saved to \a contacts */
void QContactSaveRequest::setContacts(const QList<QContact>& contacts)
{
    Q_D(QContactSaveRequest);
    QMutexLocker ml(&d->m_mutex);
    d->m_contacts = contacts;
}

/*! Returns the list of contacts which will be saved if called prior to calling \c start(),
    otherwise returns the list of contacts with their ids set appropriately (successfully
    saved new contacts will have an id assigned).
*/
QList<QContact> QContactSaveRequest::contacts() const
{
    Q_D(const QContactSaveRequest);
    QMutexLocker ml(&d->m_mutex);
    return d->m_contacts;
}

/*! Returns the map of input contact list indices to errors which occurred */
QMap<int, QContactManager::Error> QContactSaveRequest::errorMap() const
{
    Q_D(const QContactSaveRequest);
    QMutexLocker ml(&d->m_mutex);
    return d->m_errors;
}

/*!
    Set the list of definitions to restrict saving to \a definitionMask.  This allows you to perform
    partial save (and remove) operations on existing contacts.

    If \a definitionMask is empty (the default), no restrictions will apply, and the passed
    in contacts will be saved as is.  Otherwise, only details whose definitions are in
    the list will be saved.  If a definition name is present in the list, but there are no
    corresponding details in the contact passed into this request, any existing details in
    the manager for that contact will be removed.

    This is useful if you've used a fetch hint to fetch a partial contact from a manager
    so that you can save changes to the details you actually fetched without removing
    the details you didn't.

    Additionally, when performing synchronization operations with other managers that don't
    support the full range of details, you can restrict the update operation to only those
    details so that you don't lose the extra details that are supported in this manager.

    \note Some managers do not support partial updates natively, in which case the QtContacts
    framework will emulate the functionality (fetching the whole contact, applying the
    new restricted details, and saving the contact back).
*/
void QContactSaveRequest::setDefinitionMask(const QStringList &definitionMask)
{
    Q_D(QContactSaveRequest);
    QMutexLocker ml(&d->m_mutex);
    d->m_definitionMask = definitionMask;
}

/*!
    Returns the list of definitions that this request will operate on.

    If the list is empty, the request will operate on all details.
 */
QStringList QContactSaveRequest::definitionMask() const
{
    Q_D(const QContactSaveRequest);
    QMutexLocker ml(&d->m_mutex);
    return d->m_definitionMask;
}

#include "moc_qcontactsaverequest.cpp"

QTM_END_NAMESPACE
<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <sstream>

#include "mangling.hpp"
#include "VisitorUtils.hpp"
#include "GetTypeVisitor.hpp"

using namespace eddic;

std::string eddic::mangle(Type type){
    if(type.base() == BaseType::INT){
        return type.isArray() ? "AI" : "I";
    } else if(type.base() == BaseType::STRING){
        return type.isArray() ? "AS" : "S";
    }

    assert(false); //Type not handled
}

std::string eddic::mangle(const std::string& functionName, const std::vector<ParameterType>& types){
    if(functionName == "main"){
        return functionName;
    }

    std::ostringstream ss;

    ss << "_F";
    ss << functionName.length();
    ss << functionName;

    for(const ParameterType& t : types){
        ss << mangle(t.paramType);
    }

    return ss.str();
}

std::string eddic::mangle(const std::string& functionName, const std::vector<ast::Value>& values){
    if(functionName == "main"){
        return functionName;
    }

    std::ostringstream ss;

    ss << "_F";
    ss << functionName.length();
    ss << functionName;

    GetTypeVisitor visitor;

    for(auto& value : values){
        Type type = visit(visitor, value);
        ss << mangle(type);
    }

    return ss.str();
}
<commit_msg>Handle bools when mangling<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <sstream>

#include "mangling.hpp"
#include "VisitorUtils.hpp"
#include "GetTypeVisitor.hpp"

using namespace eddic;

std::string eddic::mangle(Type type){
    if(type.base() == BaseType::INT){
        return type.isArray() ? "AI" : "I";
    } else if(type.base() == BaseType::STRING){
        return type.isArray() ? "AS" : "S";
    } else if(type.base() == BaseType::BOOL){
        return type.isArray() ? "AB" : "B";
    }

    assert(false); //Type not handled
}

std::string eddic::mangle(const std::string& functionName, const std::vector<ParameterType>& types){
    if(functionName == "main"){
        return functionName;
    }

    std::ostringstream ss;

    ss << "_F";
    ss << functionName.length();
    ss << functionName;

    for(const ParameterType& t : types){
        ss << mangle(t.paramType);
    }

    return ss.str();
}

std::string eddic::mangle(const std::string& functionName, const std::vector<ast::Value>& values){
    if(functionName == "main"){
        return functionName;
    }

    std::ostringstream ss;

    ss << "_F";
    ss << functionName.length();
    ss << functionName;

    GetTypeVisitor visitor;

    for(auto& value : values){
        Type type = visit(visitor, value);
        ss << mangle(type);
    }

    return ss.str();
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: viewobjectcontactofsdrmediaobj.hxx,v $
 * $Revision: 1.8 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _SDR_CONTACT_VIEWOBJECTCONTACTOFSDRMEDIAOBJ_HXX
#define _SDR_CONTACT_VIEWOBJECTCONTACTOFSDRMEDIAOBJ_HXX

#include <svx/sdr/contact/viewobjectcontact.hxx>

namespace avmedia { class MediaItem; }
class Window;

namespace sdr
{
    namespace contact
    {
        class SdrMediaWindow;

        class ViewObjectContactOfSdrMediaObj : public ViewObjectContact
        {
        public:

            ViewObjectContactOfSdrMediaObj( ObjectContact& rObjectContact,
                                            ViewContact& rViewContact,
                                            const ::avmedia::MediaItem& rMediaItem );

            // The destructor. When PrepareDelete() was not called before (see there)
            // warnings will be generated in debug version if there are still contacts
            // existing.
            virtual ~ViewObjectContactOfSdrMediaObj();

        public:

            Window* getWindow() const;

            bool    hasPreferredSize() const;
            Size    getPreferredSize() const;

            void    updateMediaItem( ::avmedia::MediaItem& rItem ) const;
            void    executeMediaItem( const ::avmedia::MediaItem& rItem );

            // #i72701#
            void checkMediaWindowPosition(DisplayInfo& rDisplayInfo) const;

        protected:

            // Prepare deletion of this object. This needs to be called always
            // before really deleting this objects. This is necessary since in a c++
            // destructor no virtual function calls are allowed. To avoid this problem,
            // it is required to first call PrepareDelete().
            virtual void PrepareDelete();

            // Paint this object. This is before evtl. SubObjects get painted. This method
            // needs to set the flag mbIsPainted and to set the
            // maPaintedRectangle member. This information is later used for invalidates
            // and repaints.
            virtual void PaintObject(DisplayInfo& rDisplayInfo);

        private:

            ::sdr::contact::SdrMediaWindow* mpMediaWindow;
        };
    } // end of namespace contact
} // end of namespace sdr

//////////////////////////////////////////////////////////////////////////////

#endif // _SDR_CONTACT_VIEWOBJECTCONTACTOFSDRMEDIAOBJ_HXX
<commit_msg>INTEGRATION: CWS aw033 (1.4.14); FILE MERGED 2008/07/10 12:58:59 aw 1.4.14.11: #i39532# XOutputDevice removed, PrepareDelete removed 2008/05/14 13:59:02 aw 1.4.14.10: RESYNC: (1.7-1.8); FILE MERGED 2008/01/22 12:29:07 aw 1.4.14.9: adaptions and 1st stripping 2007/08/09 17:14:48 aw 1.4.14.8: RESYNC: (1.6-1.7); FILE MERGED 2007/07/06 13:42:27 aw 1.4.14.7: #i39532# moved from Primitive2DReference to Primitive2DSequence where possible to avoid extra-group primitive creations and deeper hierarchies as necessary 2007/03/20 13:54:17 aw 1.4.14.6: RESYNC: (1.5-1.6); FILE MERGED 2007/03/06 12:39:12 aw 1.4.14.5: #i39532# 2006/11/28 18:19:48 aw 1.4.14.4: RESYNC: (1.4-1.5); FILE MERGED 2006/10/19 10:53:47 aw 1.4.14.3: #i39532# primitive 2006/08/09 17:05:51 aw 1.4.14.2: #i39532# 2006/05/12 12:44:11 aw 1.4.14.1: code changes for primitive support<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: viewobjectcontactofsdrmediaobj.hxx,v $
 * $Revision: 1.9 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _SDR_CONTACT_VIEWOBJECTCONTACTOFSDRMEDIAOBJ_HXX
#define _SDR_CONTACT_VIEWOBJECTCONTACTOFSDRMEDIAOBJ_HXX

#include <svx/sdr/contact/viewobjectcontactofsdrobj.hxx>
#include <svx/sdr/contact/viewobjectcontact.hxx>

namespace avmedia { class MediaItem; }
class Window;

namespace sdr
{
    namespace contact
    {
        class SdrMediaWindow;

        class ViewObjectContactOfSdrMediaObj : public ViewObjectContactOfSdrObj
        {
        public:

            ViewObjectContactOfSdrMediaObj( ObjectContact& rObjectContact,
                                            ViewContact& rViewContact,
                                            const ::avmedia::MediaItem& rMediaItem );
            virtual ~ViewObjectContactOfSdrMediaObj();

        public:

            Window* getWindow() const;

            bool    hasPreferredSize() const;
            Size    getPreferredSize() const;

            void    updateMediaItem( ::avmedia::MediaItem& rItem ) const;
            void    executeMediaItem( const ::avmedia::MediaItem& rItem );

        private:

            ::sdr::contact::SdrMediaWindow* mpMediaWindow;

            //////////////////////////////////////////////////////////////////////////////
            // primitive stuff
        public:
            // process this primitive: ask for isPrimitiveVisible() and take necessary actions
            // to give useful data to the processor in DisplayInfo. Eventually also
            // recursively travel a existing hierarchy, e.g. for group objects
            virtual drawinglayer::primitive2d::Primitive2DSequence getPrimitive2DSequenceHierarchy(DisplayInfo& rDisplayInfo) const;
        };
    } // end of namespace contact
} // end of namespace sdr

//////////////////////////////////////////////////////////////////////////////

#endif // _SDR_CONTACT_VIEWOBJECTCONTACTOFSDRMEDIAOBJ_HXX
<|endoftext|>


<commit_before>/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/compiler/xla/service/gpu/fusion_bitcast_lift.h"
#include "tensorflow/compiler/xla/service/hlo_casting_utils.h"
#include "tensorflow/compiler/xla/service/hlo_instructions.h"
#include "tensorflow/compiler/xla/shape_util.h"
#include "tensorflow/core/platform/errors.h"

namespace xla {
namespace gpu {

// Returns true if all instructions are supported operations.
static bool AreInstructionSupported(HloComputation* comp) {
  for (HloInstruction* instr : comp->instructions()) {
    bool supported =
        HloInstruction::IsOpElementwise(instr->opcode()) ||
        instr->opcode() == HloOpcode::kConstant ||
        // We only support reduction when they are at the root or when
        // in a MOF, at the end. This should always be true for now,
        // but if we implement reduction epilog fusion in the future,
        // this optimization need to be updated. So disable it just for
        // future safety.
        (instr->opcode() == HloOpcode::kReduce &&
         (comp->root_instruction() == instr ||
          (instr->users().size() == 1 &&
           instr->users()[0]->opcode() == HloOpcode::kTuple))) ||
        instr->opcode() == HloOpcode::kTuple ||
        instr->opcode() == HloOpcode::kParameter ||
        (instr->opcode() == HloOpcode::kBitcast &&
         instr->shape().rank() < instr->operand(0)->shape().rank()) ||
        (instr->opcode() == HloOpcode::kBroadcast &&
         (instr->dimensions().empty() ||       // scalar broadcasting
          (instr->dimensions().size() == 1 &&  // row broadcasting
           instr->dimensions()[0] == (instr->shape().rank() - 1))));
    if (!supported) {
      VLOG(2) << "NOT SUPPORTED: " << instr->ToString();
      return false;
    }
  }
  return true;
}

StatusOr<bool> FusionBitcastLift::Run(HloModule* module) {
  XLA_VLOG_LINES(2, "FusionBitcastLift::Run(), before:\n" + module->ToString());
  bool changed = false;
  for (HloComputation* comp : module->MakeNonfusionComputations()) {
    // Copy the instruction list as we modify the HloComputation.
    std::vector<HloInstruction*> comp_instruction(comp->instructions().begin(),
                                                  comp->instructions().end());
    for (HloInstruction* instr : comp_instruction) {
      // 1) Is this a fusion that we want to modify.
      if (auto* fusion = DynCast<HloFusionInstruction>(instr)) {
        // 1.1) We only support kInput fusion and some operations.
        if (fusion->fusion_kind() != HloInstruction::FusionKind::kInput ||
            !AreInstructionSupported(
                fusion->fused_instructions_computation())) {
          continue;
        }
        // 1.2) Check if there is a bitcast that we lift. Currently
        //      we do not lift(merge) bitcast above(with) broadcast.
        if (!std::any_of(fusion->fused_instructions().begin(),
                         fusion->fused_instructions().end(),
                         [](HloInstruction* inner) {
              return inner->opcode() == HloOpcode::kBitcast &&
                  inner->operand(0)->opcode() != HloOpcode::kBroadcast;
                         })) {
          continue;
        }

        // 1.3) Check that all the bitcast have the same shape pattern.
        //      Multiple bitcast pattern isn't supported/tested.
        HloInstruction* bitcast = nullptr;
        bool same_shape_pattern = true;
        for (HloInstruction* fused_instr : fusion->fused_instructions()) {
          if (fused_instr->opcode() == HloOpcode::kBitcast &&
              fused_instr->shape().rank() <
              fused_instr->operand(0)->shape().rank()) {
            if (bitcast != nullptr &&
                (!ShapeUtil::Equal(fused_instr->shape(), bitcast->shape()) ||
                 !ShapeUtil::Equal(bitcast->operand(0)->shape(),
                                   fused_instr->operand(0)->shape()))) {
              same_shape_pattern = false;
              break;
            }
            bitcast = fused_instr;
          }
        }
        if (bitcast == nullptr || !same_shape_pattern) {
          VLOG(2) << "NOT SUPPORTED: Multiple rank-reducing bitcast pattern.";
          continue;
        }

        // 2) Now that we have found a fusion that we want to modify,
        //    create the new fusion. We do so by:
        //    a) Cloning the old fusion.
        //    b) Recursively walk the graph from the root and lift the
        //       bitcast up across one instruction at a time.
        std::unique_ptr<HloInstruction> cloned_fusion =
          fusion->Clone("bitcast");
        // The following stack and set always contain the same data.
        // The stack is used for the order of traversal.
        // The set is used only as an optimization to search in the set.
        std::vector<HloInstruction*> stack(
            {cloned_fusion->fused_expression_root()});
        absl::flat_hash_set<HloInstruction*> set(
            {cloned_fusion->fused_expression_root()});
        bool clone_changed = false;
        while (!stack.empty()) {
          HloInstruction* i = stack.back();
          stack.pop_back();
          set.erase(i);
          if (i->opcode() == HloOpcode::kTuple) {
            stack.insert(stack.end(), i->operands().begin(),
                         i->operands().end());
            set.insert(i->operands().begin(),
                       i->operands().end());
            VLOG(3) << "kTuple: " << i->ToString();
          } else if (i->opcode() == HloOpcode::kParameter &&
                     absl::c_all_of(i->users(), [](HloInstruction* u) {
                         return u->opcode() == HloOpcode::kBitcast;
                       })) {
            VLOG(3) << "kParameter: " << i->ToString();
            // Replace the parameter inside the fusion.
            Shape new_shape = i->users()[0]->shape();
            int64 parameter_number = i->parameter_number();
            string name = i->name();
            auto n = HloInstruction::CreateParameter(parameter_number,
                                                     new_shape, name);
            HloInstruction* new_parameter =
              i->parent()->ReplaceParameter(parameter_number,
                                            std::move(n));
            // Remove the old inner bitcast.
            auto old_users = new_parameter->users();
            for (HloInstruction* param_user : old_users) {
              DCHECK(param_user->opcode() == HloOpcode::kBitcast)
                << "Expected a bitcast";
              TF_RETURN_IF_ERROR(param_user->parent()->ReplaceInstructionWithDifferentShape(
                  param_user, new_parameter));
            }
            // Replace the corresponding fusion operands with a new bitcast.
            HloInstruction* old_outer_parameter =
              cloned_fusion->mutable_operand(parameter_number);
            HloInstruction* new_op =
              old_outer_parameter->parent()->AddInstruction(
                    HloInstruction::CreateBitcast(new_shape,
                                                  old_outer_parameter));
            TF_RETURN_IF_ERROR(cloned_fusion->ReplaceOperandWithDifferentShape(
                parameter_number, new_op));
            clone_changed = true;
            changed = true;
          } else if (i->opcode() == HloOpcode::kBroadcast) {
            VLOG(3) << "kBroadcast: " << i->ToString();
            // For now, do nothing. Later we can merge the broadcast
            // and the bitcast, but this doesn't bring benefit in my
            // current case.
            if (set.count(i->mutable_operand(0)) == 0) {
              stack.push_back(i->mutable_operand(0));
              set.insert(i->mutable_operand(0));
            }
          } else if (i->opcode() == HloOpcode::kConstant &&
                     !i->users().empty() &&
                     absl::c_all_of(i->users(), [](HloInstruction* u) {
                         return u->opcode() == HloOpcode::kBitcast;
                       })) {
            VLOG(3) << "kConstant: " << i->ToString();
            Shape new_shape = i->users()[0]->shape();
            TF_RETURN_IF_ERROR(i->parent()->ReplaceWithNewInstruction(
                i, i->CloneWithNewOperands(new_shape, {})));
          } else if (!i->users().empty() &&
                     absl::c_all_of(i->users(), [](HloInstruction* u) {
                         return u->opcode() == HloOpcode::kBitcast;
                       })) {
            VLOG(3) << "All User bitcast: " << i->ToString();
            // All users are bitcast, so lift the bitcast.
            Shape new_shape = i->users()[0]->shape();
            std::vector<HloInstruction*> new_operands;
            for (HloInstruction* opnd : i->operands()) {
              Shape dtyped_new_shape = ShapeUtil::ChangeElementType(
                  new_shape, opnd->shape().element_type());
              HloInstruction* new_opnd = opnd->parent()->AddInstruction(
                  HloInstruction::CreateBitcast(dtyped_new_shape, opnd));
              new_operands.push_back(new_opnd);
              // Handle the operand right before the inserted bitcast now.
              if (set.count(opnd) == 0) {
                stack.push_back(opnd);
                set.insert(opnd);
              }
            }
            Shape dtyped_new_shape = ShapeUtil::ChangeElementType(
                new_shape, i->shape().element_type());
            HloInstruction* cloned_i = i->parent()->AddInstruction(
                i->CloneWithNewOperands(dtyped_new_shape, new_operands));
            // Replace the old bitcasts with the new instruction to
            // remove it.
            // Copy the vector as it will be modified while we iterate on it.
            const std::vector<HloInstruction*> users = i->users();
            for (HloInstruction* user: users) {
              TF_RETURN_IF_ERROR(i->parent()->ReplaceInstructionWithDifferentShape(
                  user, cloned_i));
            }
            clone_changed = true;
            changed = true;
          } else {
            VLOG(3) << "Else: " << i->ToString();
            for(auto* opnd : i->operands()) {
              if (set.count(opnd) == 0) {
                stack.push_back(opnd);
                set.insert(opnd);
              }
            }
          }
        }  // while
        DCHECK(clone_changed) << "We should have changed the fusion!";
        if (clone_changed) {
          // 3) Replace the old fusion with the new fusion.
          TF_RETURN_IF_ERROR(fusion->parent()->ReplaceWithNewInstruction(
              fusion, std::move(cloned_fusion)));
        }
      }  // if fusion
    }
  }
  XLA_VLOG_LINES(2, "FusionBitcastLift::Run(), after:\n" + module->ToString());
  return changed;
}

}  // namespace gpu
}  // namespace xla
<commit_msg>Do not try to lift the bitcast if there is no operand. This also fix the kConstant case, but the kConstant manual handling simplify the graph.<commit_after>/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/compiler/xla/service/gpu/fusion_bitcast_lift.h"
#include "tensorflow/compiler/xla/service/hlo_casting_utils.h"
#include "tensorflow/compiler/xla/service/hlo_instructions.h"
#include "tensorflow/compiler/xla/shape_util.h"
#include "tensorflow/core/platform/errors.h"

namespace xla {
namespace gpu {

// Returns true if all instructions are supported operations.
static bool AreInstructionSupported(HloComputation* comp) {
  for (HloInstruction* instr : comp->instructions()) {
    bool supported =
        HloInstruction::IsOpElementwise(instr->opcode()) ||
        instr->opcode() == HloOpcode::kConstant ||
        // We only support reduction when they are at the root or when
        // in a MOF, at the end. This should always be true for now,
        // but if we implement reduction epilog fusion in the future,
        // this optimization need to be updated. So disable it just for
        // future safety.
        (instr->opcode() == HloOpcode::kReduce &&
         (comp->root_instruction() == instr ||
          (instr->users().size() == 1 &&
           instr->users()[0]->opcode() == HloOpcode::kTuple))) ||
        instr->opcode() == HloOpcode::kTuple ||
        instr->opcode() == HloOpcode::kParameter ||
        (instr->opcode() == HloOpcode::kBitcast &&
         instr->shape().rank() < instr->operand(0)->shape().rank()) ||
        (instr->opcode() == HloOpcode::kBroadcast &&
         (instr->dimensions().empty() ||       // scalar broadcasting
          (instr->dimensions().size() == 1 &&  // row broadcasting
           instr->dimensions()[0] == (instr->shape().rank() - 1))));
    if (!supported) {
      VLOG(2) << "NOT SUPPORTED: " << instr->ToString();
      return false;
    }
  }
  return true;
}

StatusOr<bool> FusionBitcastLift::Run(HloModule* module) {
  XLA_VLOG_LINES(2, "FusionBitcastLift::Run(), before:\n" + module->ToString());
  bool changed = false;
  for (HloComputation* comp : module->MakeNonfusionComputations()) {
    // Copy the instruction list as we modify the HloComputation.
    std::vector<HloInstruction*> comp_instruction(comp->instructions().begin(),
                                                  comp->instructions().end());
    for (HloInstruction* instr : comp_instruction) {
      // 1) Is this a fusion that we want to modify.
      if (auto* fusion = DynCast<HloFusionInstruction>(instr)) {
        // 1.1) We only support kInput fusion and some operations.
        if (fusion->fusion_kind() != HloInstruction::FusionKind::kInput ||
            !AreInstructionSupported(
                fusion->fused_instructions_computation())) {
          continue;
        }
        // 1.2) Check if there is a bitcast that we lift. Currently
        //      we do not lift(merge) bitcast above(with) broadcast.
        if (!std::any_of(fusion->fused_instructions().begin(),
                         fusion->fused_instructions().end(),
                         [](HloInstruction* inner) {
              return inner->opcode() == HloOpcode::kBitcast &&
                  inner->operand(0)->opcode() != HloOpcode::kBroadcast;
                         })) {
          continue;
        }

        // 1.3) Check that all the bitcast have the same shape pattern.
        //      Multiple bitcast pattern isn't supported/tested.
        HloInstruction* bitcast = nullptr;
        bool same_shape_pattern = true;
        for (HloInstruction* fused_instr : fusion->fused_instructions()) {
          if (fused_instr->opcode() == HloOpcode::kBitcast &&
              fused_instr->shape().rank() <
              fused_instr->operand(0)->shape().rank()) {
            if (bitcast != nullptr &&
                (!ShapeUtil::Equal(fused_instr->shape(), bitcast->shape()) ||
                 !ShapeUtil::Equal(bitcast->operand(0)->shape(),
                                   fused_instr->operand(0)->shape()))) {
              same_shape_pattern = false;
              break;
            }
            bitcast = fused_instr;
          }
        }
        if (bitcast == nullptr || !same_shape_pattern) {
          VLOG(2) << "NOT SUPPORTED: Multiple rank-reducing bitcast pattern.";
          continue;
        }

        // 2) Now that we have found a fusion that we want to modify,
        //    create the new fusion. We do so by:
        //    a) Cloning the old fusion.
        //    b) Recursively walk the graph from the root and lift the
        //       bitcast up across one instruction at a time.
        std::unique_ptr<HloInstruction> cloned_fusion =
          fusion->Clone("bitcast");
        // The following stack and set always contain the same data.
        // The stack is used for the order of traversal.
        // The set is used only as an optimization to search in the set.
        std::vector<HloInstruction*> stack(
            {cloned_fusion->fused_expression_root()});
        absl::flat_hash_set<HloInstruction*> set(
            {cloned_fusion->fused_expression_root()});
        bool clone_changed = false;
        while (!stack.empty()) {
          HloInstruction* i = stack.back();
          stack.pop_back();
          set.erase(i);
          if (i->opcode() == HloOpcode::kTuple) {
            stack.insert(stack.end(), i->operands().begin(),
                         i->operands().end());
            set.insert(i->operands().begin(),
                       i->operands().end());
            VLOG(3) << "kTuple: " << i->ToString();
          } else if (i->opcode() == HloOpcode::kParameter &&
                     absl::c_all_of(i->users(), [](HloInstruction* u) {
                         return u->opcode() == HloOpcode::kBitcast;
                       })) {
            VLOG(3) << "kParameter: " << i->ToString();
            // Replace the parameter inside the fusion.
            Shape new_shape = i->users()[0]->shape();
            int64 parameter_number = i->parameter_number();
            string name = i->name();
            auto n = HloInstruction::CreateParameter(parameter_number,
                                                     new_shape, name);
            HloInstruction* new_parameter =
              i->parent()->ReplaceParameter(parameter_number,
                                            std::move(n));
            // Remove the old inner bitcast.
            auto old_users = new_parameter->users();
            for (HloInstruction* param_user : old_users) {
              DCHECK(param_user->opcode() == HloOpcode::kBitcast)
                << "Expected a bitcast";
              TF_RETURN_IF_ERROR(param_user->parent()->ReplaceInstructionWithDifferentShape(
                  param_user, new_parameter));
            }
            // Replace the corresponding fusion operands with a new bitcast.
            HloInstruction* old_outer_parameter =
              cloned_fusion->mutable_operand(parameter_number);
            HloInstruction* new_op =
              old_outer_parameter->parent()->AddInstruction(
                    HloInstruction::CreateBitcast(new_shape,
                                                  old_outer_parameter));
            TF_RETURN_IF_ERROR(cloned_fusion->ReplaceOperandWithDifferentShape(
                parameter_number, new_op));
            clone_changed = true;
            changed = true;
          } else if (i->opcode() == HloOpcode::kBroadcast) {
            VLOG(3) << "kBroadcast: " << i->ToString();
            // For now, do nothing. Later we can merge the broadcast
            // and the bitcast, but this doesn't bring benefit in my
            // current case.
            if (set.count(i->mutable_operand(0)) == 0) {
              stack.push_back(i->mutable_operand(0));
              set.insert(i->mutable_operand(0));
            }
          } else if (i->opcode() == HloOpcode::kConstant &&
                     !i->users().empty() &&
                     absl::c_all_of(i->users(), [](HloInstruction* u) {
                         return u->opcode() == HloOpcode::kBitcast;
                       })) {
            // Handling this case is optional for correctness, but
            // handling it clean up the graph.
            VLOG(3) << "kConstant: " << i->ToString();
            Shape new_shape = i->users()[0]->shape();
            TF_RETURN_IF_ERROR(i->parent()->ReplaceWithNewInstruction(
                i, i->CloneWithNewOperands(new_shape, {})));
          } else if (!i->users().empty() &&
                     // If 0 operands, we can't lift the bitcast.  It
                     // must be handled manually as kConstant and
                     // kParameter.
                     i->operands().size() > 0 &&
                     absl::c_all_of(i->users(), [](HloInstruction* u) {
                         return u->opcode() == HloOpcode::kBitcast;
                       })) {
            VLOG(3) << "All User bitcast: " << i->ToString();
            // All users are bitcast, so lift the bitcast.
            Shape new_shape = i->users()[0]->shape();
            std::vector<HloInstruction*> new_operands;
            for (HloInstruction* opnd : i->operands()) {
              Shape dtyped_new_shape = ShapeUtil::ChangeElementType(
                  new_shape, opnd->shape().element_type());
              HloInstruction* new_opnd = opnd->parent()->AddInstruction(
                  HloInstruction::CreateBitcast(dtyped_new_shape, opnd));
              new_operands.push_back(new_opnd);
              // Handle the operand right before the inserted bitcast now.
              if (set.count(opnd) == 0) {
                stack.push_back(opnd);
                set.insert(opnd);
              }
            }
            Shape dtyped_new_shape = ShapeUtil::ChangeElementType(
                new_shape, i->shape().element_type());
            HloInstruction* cloned_i = i->parent()->AddInstruction(
                i->CloneWithNewOperands(dtyped_new_shape, new_operands));
            // Replace the old bitcasts with the new instruction to
            // remove it.
            // Copy the vector as it will be modified while we iterate on it.
            const std::vector<HloInstruction*> users = i->users();
            for (HloInstruction* user: users) {
              TF_RETURN_IF_ERROR(i->parent()->ReplaceInstructionWithDifferentShape(
                  user, cloned_i));
            }
            clone_changed = true;
            changed = true;
          } else {
            VLOG(3) << "Else: " << i->ToString();
            for(auto* opnd : i->operands()) {
              if (set.count(opnd) == 0) {
                stack.push_back(opnd);
                set.insert(opnd);
              }
            }
          }
        }  // while
        DCHECK(clone_changed) << "We should have changed the fusion!";
        if (clone_changed) {
          // 3) Replace the old fusion with the new fusion.
          TF_RETURN_IF_ERROR(fusion->parent()->ReplaceWithNewInstruction(
              fusion, std::move(cloned_fusion)));
        }
      }  // if fusion
    }
  }
  XLA_VLOG_LINES(2, "FusionBitcastLift::Run(), after:\n" + module->ToString());
  return changed;
}

}  // namespace gpu
}  // namespace xla
<|endoftext|>


<commit_before>#pragma once

#include "constants.hpp"
#include <glob/glob.hpp>
#include <pqrs/filesystem.hpp>
#include <string_view>

namespace krbn {
namespace filesystem_utility {
inline void mkdir_tmp_directory(void) {
  pqrs::filesystem::create_directory_with_intermediate_directories(
      constants::get_tmp_directory(),
      0755);

  // Reset owner and permission just in case.

  chown(constants::get_tmp_directory(), 0, 0);
  chmod(constants::get_tmp_directory(), 0755);
}

inline void mkdir_rootonly_directory(void) {
  mkdir_tmp_directory();

  pqrs::filesystem::create_directory_with_intermediate_directories(
      constants::get_rootonly_directory(),
      0700);

  // Reset owner and permission just in case.

  chown(constants::get_rootonly_directory().c_str(), 0, 0);
  chmod(constants::get_rootonly_directory().c_str(), 0700);
}

inline void remove_files_by_glob(const std::string_view& pattern) {
  for (auto path : glob::glob(pattern.data())) {
    logger::get_logger()->info("Remove {0}", path.c_str());

    std::error_code error_code;
    std::filesystem::remove(path, error_code);
  }
}
} // namespace filesystem_utility
} // namespace krbn
<commit_msg>Update #include<commit_after>#pragma once

#include "constants.hpp"
#include "logger.hpp"
#include <glob/glob.hpp>
#include <pqrs/filesystem.hpp>
#include <string_view>

namespace krbn {
namespace filesystem_utility {
inline void mkdir_tmp_directory(void) {
  pqrs::filesystem::create_directory_with_intermediate_directories(
      constants::get_tmp_directory(),
      0755);

  // Reset owner and permission just in case.

  chown(constants::get_tmp_directory(), 0, 0);
  chmod(constants::get_tmp_directory(), 0755);
}

inline void mkdir_rootonly_directory(void) {
  mkdir_tmp_directory();

  pqrs::filesystem::create_directory_with_intermediate_directories(
      constants::get_rootonly_directory(),
      0700);

  // Reset owner and permission just in case.

  chown(constants::get_rootonly_directory().c_str(), 0, 0);
  chmod(constants::get_rootonly_directory().c_str(), 0700);
}

inline void remove_files_by_glob(const std::string_view& pattern) {
  for (auto path : glob::glob(pattern.data())) {
    logger::get_logger()->info("Remove {0}", path.c_str());

    std::error_code error_code;
    std::filesystem::remove(path, error_code);
  }
}
} // namespace filesystem_utility
} // namespace krbn
<|endoftext|>