<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ListenerHelper.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: kz $ $Date: 2006-11-06 15:04:41 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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 for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include "ListenerHelper.h"

using com::sun::star::frame::XFrame;
using com::sun::star::frame::XDispatch;
using com::sun::star::frame::XStatusListener;
using com::sun::star::lang::XEventListener;
using com::sun::star::lang::EventObject;
using com::sun::star::uno::Reference;
using com::sun::star::uno::RuntimeException;
using com::sun::star::frame::FeatureStateEvent;

static AllListeners aListeners;

void ListenerHelper::AddListener(
    const Reference < XFrame >& xFrame,
    const Reference < XStatusListener > xControl,
    const ::rtl::OUString& aCommand )
{
    sal_uInt32 i=0;
    sal_uInt32 nSize = aListeners.size();
    for ( i=0; i<nSize; i++ )
        if ( aListeners[i].xFrame == xFrame )
            break;

    OSL_ENSURE( i<nSize, "No dispatch found for this listener!" );
    aListeners[i].aContainer[aCommand].push_back( xControl );
}

void ListenerHelper::RemoveListener(
    const Reference < XFrame >& xFrame,
    const Reference < XStatusListener > xControl,
    const ::rtl::OUString& aCommand )
{
    sal_uInt32 nSize = aListeners.size();
    for ( sal_uInt32 i=0; i<nSize; i++ )
    {
        if ( aListeners[i].xFrame == xFrame )
        {
            StatusListeners& aL = aListeners[i].aContainer[aCommand];
            StatusListeners::iterator aIter = aL.begin();
            while ( aIter != aL.end() )
            {
                if ( (*aIter) == xControl )
                {
                    aL.erase( aIter );
                    break;
                }

                aIter++;
            }
        }
    }
}

void ListenerHelper::Notify(
        const Reference < XFrame >& xFrame,
        const ::rtl::OUString& aCommand,
        FeatureStateEvent& rEvent )
{
    sal_uInt32 nSize = aListeners.size();
    for ( sal_uInt32 i=0; i<nSize; i++ )
    {
        if ( aListeners[i].xFrame == xFrame )
        {
            rEvent.Source = aListeners[i].xDispatch;
            StatusListeners& aL = aListeners[i].aContainer[aCommand];
            StatusListeners::iterator aIter = aL.begin();
            while ( aIter != aL.end() )
            {
                (*aIter)->statusChanged( rEvent );
                aIter++;
            }
        }
    }
}

com::sun::star::uno::Reference < XDispatch > ListenerHelper::GetDispatch(
        const Reference < XFrame >& xFrame,
        const ::rtl::OUString& aCommand )
{
    sal_uInt32 nSize = aListeners.size();
    for ( sal_uInt32 i=0; i<nSize; i++ )
    {
        if ( aListeners[i].xFrame == xFrame )
            return aListeners[i].xDispatch;
    }

    return Reference < XDispatch >();
}

void ListenerHelper::AddDispatch(
        const Reference < XDispatch > xDispatch,
        const Reference < XFrame >& xFrame,
        const ::rtl::OUString& aCommand )
{
    ListenerItem aItem;
    aItem.xFrame = xFrame;
    aItem.xDispatch = xDispatch;
    aListeners.push_back( aItem );
    xFrame->addEventListener( new ListenerItemEventListener( xFrame ) );
}

void SAL_CALL ListenerItemEventListener::disposing( const EventObject& aEvent) throw (RuntimeException)
{
    AllListeners::iterator aIter = aListeners.begin();
    while ( aIter != aListeners.end() )
    {
        if ( (*aIter).xFrame == mxFrame )
        {
            aListeners.erase( aIter );
            break;
        }

        aIter++;
    }
}
<commit_msg>INTEGRATION: CWS changefileheader (1.4.98); FILE MERGED 2008/03/31 15:52:51 rt 1.4.98.1: #i87441# Change license header to LPGL v3.<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: ListenerHelper.cxx,v $
 * $Revision: 1.5 $
 *
 * 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.
 *
 ************************************************************************/

#include "ListenerHelper.h"

using com::sun::star::frame::XFrame;
using com::sun::star::frame::XDispatch;
using com::sun::star::frame::XStatusListener;
using com::sun::star::lang::XEventListener;
using com::sun::star::lang::EventObject;
using com::sun::star::uno::Reference;
using com::sun::star::uno::RuntimeException;
using com::sun::star::frame::FeatureStateEvent;

static AllListeners aListeners;

void ListenerHelper::AddListener(
    const Reference < XFrame >& xFrame,
    const Reference < XStatusListener > xControl,
    const ::rtl::OUString& aCommand )
{
    sal_uInt32 i=0;
    sal_uInt32 nSize = aListeners.size();
    for ( i=0; i<nSize; i++ )
        if ( aListeners[i].xFrame == xFrame )
            break;

    OSL_ENSURE( i<nSize, "No dispatch found for this listener!" );
    aListeners[i].aContainer[aCommand].push_back( xControl );
}

void ListenerHelper::RemoveListener(
    const Reference < XFrame >& xFrame,
    const Reference < XStatusListener > xControl,
    const ::rtl::OUString& aCommand )
{
    sal_uInt32 nSize = aListeners.size();
    for ( sal_uInt32 i=0; i<nSize; i++ )
    {
        if ( aListeners[i].xFrame == xFrame )
        {
            StatusListeners& aL = aListeners[i].aContainer[aCommand];
            StatusListeners::iterator aIter = aL.begin();
            while ( aIter != aL.end() )
            {
                if ( (*aIter) == xControl )
                {
                    aL.erase( aIter );
                    break;
                }

                aIter++;
            }
        }
    }
}

void ListenerHelper::Notify(
        const Reference < XFrame >& xFrame,
        const ::rtl::OUString& aCommand,
        FeatureStateEvent& rEvent )
{
    sal_uInt32 nSize = aListeners.size();
    for ( sal_uInt32 i=0; i<nSize; i++ )
    {
        if ( aListeners[i].xFrame == xFrame )
        {
            rEvent.Source = aListeners[i].xDispatch;
            StatusListeners& aL = aListeners[i].aContainer[aCommand];
            StatusListeners::iterator aIter = aL.begin();
            while ( aIter != aL.end() )
            {
                (*aIter)->statusChanged( rEvent );
                aIter++;
            }
        }
    }
}

com::sun::star::uno::Reference < XDispatch > ListenerHelper::GetDispatch(
        const Reference < XFrame >& xFrame,
        const ::rtl::OUString& aCommand )
{
    sal_uInt32 nSize = aListeners.size();
    for ( sal_uInt32 i=0; i<nSize; i++ )
    {
        if ( aListeners[i].xFrame == xFrame )
            return aListeners[i].xDispatch;
    }

    return Reference < XDispatch >();
}

void ListenerHelper::AddDispatch(
        const Reference < XDispatch > xDispatch,
        const Reference < XFrame >& xFrame,
        const ::rtl::OUString& aCommand )
{
    ListenerItem aItem;
    aItem.xFrame = xFrame;
    aItem.xDispatch = xDispatch;
    aListeners.push_back( aItem );
    xFrame->addEventListener( new ListenerItemEventListener( xFrame ) );
}

void SAL_CALL ListenerItemEventListener::disposing( const EventObject& aEvent) throw (RuntimeException)
{
    AllListeners::iterator aIter = aListeners.begin();
    while ( aIter != aListeners.end() )
    {
        if ( (*aIter).xFrame == mxFrame )
        {
            aListeners.erase( aIter );
            break;
        }

        aIter++;
    }
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkXRenderWindow.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1998 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include <math.h>
#include <stdlib.h>
#include <iostream.h>
#include "vtkXRenderWindow.h"
#include "vtkXRenderWindowInteractor.h"

vtkXRenderWindow::vtkXRenderWindow()
{
  vtkDebugMacro(<< "vtkXRenderWindow::vtkXRenderWindow");
  this->DisplayId = (Display *)NULL;
  this->WindowId = (Window)NULL;
  this->ParentId = (Window)NULL;
  this->NextWindowId = (Window)NULL;
  this->ColorMap = (Colormap)NULL;
  this->ScreenSize[0] = 0;
  this->ScreenSize[1] = 0;
  this->OwnDisplay = 0;
}

vtkXRenderWindow::~vtkXRenderWindow()
{
  vtkDebugMacro(<< "vtkXRenderWindow::~vtkXRenderWindow");
  if (this->DisplayId)
    {
    XSync(this->DisplayId,0);
    }
  // if we create the display, we'll delete it
  if (this->OwnDisplay && this->DisplayId)
    {
    XCloseDisplay(this->DisplayId);
    this->DisplayId = NULL;
    }
}

int vtkXRenderWindowFoundMatch;

Bool vtkXRenderWindowPredProc(Display *vtkNotUsed(disp), XEvent *event,
			      char *arg)
{
  Window win = (Window)arg;

  if ((((XAnyEvent *)event)->window == win) &&
      ((event->type == ButtonPress)))
    vtkXRenderWindowFoundMatch = 1;

  return 0;

}

void *vtkXRenderWindow::GetGenericContext()
{
  static GC gc = (GC) NULL;

  if (!gc) gc = XCreateGC(this->DisplayId, this->WindowId, 0, 0);

  return (void *) gc;

}

int vtkXRenderWindow::GetEventPending()
{
  XEvent report;

  vtkXRenderWindowFoundMatch = 0;
  XCheckIfEvent(this->DisplayId, &report, vtkXRenderWindowPredProc,
		(char *)this->WindowId);
  return vtkXRenderWindowFoundMatch;
}

// Get the size of the screen in pixels
int *vtkXRenderWindow::GetScreenSize()
{
  // get the default display connection
  if (!this->DisplayId)
    {
    this->DisplayId = XOpenDisplay((char *)NULL);
    if (this->DisplayId == NULL)
      {
      vtkErrorMacro(<< "bad X server connection.\n");
      }
    else
      {
      this->OwnDisplay = 1;
      }
    }

  this->ScreenSize[0] =
    DisplayWidth(this->DisplayId, DefaultScreen(this->DisplayId));
  this->ScreenSize[1] =
    DisplayHeight(this->DisplayId, DefaultScreen(this->DisplayId));

  return this->ScreenSize;
}

// Get the current size of the window in pixels.
int *vtkXRenderWindow::GetSize(void)
{
  XWindowAttributes attribs;

  // if we aren't mapped then just return the ivar
  if (!this->Mapped)
    {
    return(this->Size);
    }

  //  Find the current window size
  XGetWindowAttributes(this->DisplayId,
		       this->WindowId, &attribs);

  this->Size[0] = attribs.width;
  this->Size[1] = attribs.height;

  return this->Size;
}

// Get the position in screen coordinates (pixels) of the window.
int *vtkXRenderWindow::GetPosition(void)
{
  XWindowAttributes attribs;
  int x,y;
  Window child;

  // if we aren't mapped then just return the ivar
  if (!this->Mapped)
    {
    return(this->Position);
    }

  //  Find the current window size
  XGetWindowAttributes(this->DisplayId, this->WindowId, &attribs);
  x = attribs.x;
  y = attribs.y;

  XTranslateCoordinates(this->DisplayId,this->WindowId,
		 RootWindowOfScreen(ScreenOfDisplay(this->DisplayId,0)),
			x,y,&this->Position[0],&this->Position[1],&child);

  return this->Position;
}

// Get this RenderWindow's X display id.
Display *vtkXRenderWindow::GetDisplayId()
{
  vtkDebugMacro(<< "Returning DisplayId of " << (void *)this->DisplayId << "\n");

  return this->DisplayId;
}

// Get this RenderWindow's parent X window id.
Window vtkXRenderWindow::GetParentId()
{
  vtkDebugMacro(<< "Returning ParentId of " << (void *)this->ParentId << "\n");
  return this->ParentId;
}

// Get this RenderWindow's X window id.
Window vtkXRenderWindow::GetWindowId()
{
  vtkDebugMacro(<< "Returning WindowId of " << (void *)this->WindowId << "\n");
  return this->WindowId;
}

// Move the window to a new position on the display.
void vtkXRenderWindow::SetPosition(int x, int y)
{
  // if we aren't mapped then just set the ivars
  if (!this->Mapped)
    {
    if ((this->Position[0] != x)||(this->Position[1] != y))
      {
      this->Modified();
      }
    this->Position[0] = x;
    this->Position[1] = y;
    return;
    }

  XMoveResizeWindow(this->DisplayId,this->WindowId,x,y,
                    this->Size[0], this->Size[1]);
  XSync(this->DisplayId,False);
}

// Sets the parent of the window that WILL BE created.
void vtkXRenderWindow::SetParentId(Window arg)
{
  if (this->ParentId)
    {
    vtkErrorMacro("ParentId is already set.");
    return;
    }

  vtkDebugMacro(<< "Setting ParentId to " << (void *)arg << "\n");

  this->ParentId = arg;
}

// Set this RenderWindow's X window id to a pre-existing window.
void vtkXRenderWindow::SetWindowId(Window arg)
{
  vtkDebugMacro(<< "Setting WindowId to " << (void *)arg << "\n");

  this->WindowId = arg;
}

// Set this RenderWindow's X window id to a pre-existing window.
void vtkXRenderWindow::SetWindowInfo(char *info)
{
  int tmp;

  // get the default display connection
  if (!this->DisplayId)
    {
    this->DisplayId = XOpenDisplay((char *)NULL);
    if (this->DisplayId == NULL)
      {
      vtkErrorMacro(<< "bad X server connection.\n");
      }
    else
      {
      this->OwnDisplay = 1;
      }
    }

  sscanf(info,"%i",&tmp);

  this->WindowId = tmp;
  vtkDebugMacro(<< "Setting WindowId to " << (void *)this->WindowId<< "\n");
}

void vtkXRenderWindow::SetWindowId(void *arg)
{
  this->SetWindowId((Window)arg);
}
void vtkXRenderWindow::SetParentId(void *arg)
{
  this->SetParentId((Window)arg);
}

void vtkXRenderWindow::SetWindowName(char * name)
{
  XTextProperty win_name_text_prop;

  vtkRenderWindow::SetWindowName( name );

  if (this->Mapped)
    {
    if( XStringListToTextProperty( &name, 1, &win_name_text_prop ) == 0 )
      {
      vtkWarningMacro(<< "Can't rename window");
      return;
      }

    XSetWMName( this->DisplayId, this->WindowId, &win_name_text_prop );
    XSetWMIconName( this->DisplayId, this->WindowId, &win_name_text_prop );
    }
}

// Specify the X window id to use if a WindowRemap is done.
void vtkXRenderWindow::SetNextWindowId(Window arg)
{
  vtkDebugMacro(<< "Setting NextWindowId to " << (void *)arg << "\n");

  this->NextWindowId = arg;
}

// Set the X display id for this RenderWindow to use to a pre-existing
// X display id.
void vtkXRenderWindow::SetDisplayId(Display  *arg)
{
  vtkDebugMacro(<< "Setting DisplayId to " << (void *)arg << "\n");

  this->DisplayId = arg;
  this->OwnDisplay = 0;
}
void vtkXRenderWindow::SetDisplayId(void *arg)
{
  this->SetDisplayId((Display *)arg);
  this->OwnDisplay = 0;
}

void vtkXRenderWindow::PrintSelf(ostream& os, vtkIndent indent)
{
  this->vtkRenderWindow::PrintSelf(os,indent);

  os << indent << "Color Map: " << this->ColorMap << "\n";
  os << indent << "Display Id: " << this->GetDisplayId() << "\n";
  os << indent << "Next Window Id: " << this->NextWindowId << "\n";
  os << indent << "Window Id: " << this->GetWindowId() << "\n";
}
<commit_msg>ERR: memory leak in SetWindowName repaired.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkXRenderWindow.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1998 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include <math.h>
#include <stdlib.h>
#include <iostream.h>
#include "vtkXRenderWindow.h"
#include "vtkXRenderWindowInteractor.h"

vtkXRenderWindow::vtkXRenderWindow()
{
  vtkDebugMacro(<< "vtkXRenderWindow::vtkXRenderWindow");
  this->DisplayId = (Display *)NULL;
  this->WindowId = (Window)NULL;
  this->ParentId = (Window)NULL;
  this->NextWindowId = (Window)NULL;
  this->ColorMap = (Colormap)NULL;
  this->ScreenSize[0] = 0;
  this->ScreenSize[1] = 0;
  this->OwnDisplay = 0;
}

vtkXRenderWindow::~vtkXRenderWindow()
{
  vtkDebugMacro(<< "vtkXRenderWindow::~vtkXRenderWindow");
  if (this->DisplayId)
    {
    XSync(this->DisplayId,0);
    }
  // if we create the display, we'll delete it
  if (this->OwnDisplay && this->DisplayId)
    {
    XCloseDisplay(this->DisplayId);
    this->DisplayId = NULL;
    }
}

int vtkXRenderWindowFoundMatch;

Bool vtkXRenderWindowPredProc(Display *vtkNotUsed(disp), XEvent *event,
			      char *arg)
{
  Window win = (Window)arg;

  if ((((XAnyEvent *)event)->window == win) &&
      ((event->type == ButtonPress)))
    vtkXRenderWindowFoundMatch = 1;

  return 0;

}

void *vtkXRenderWindow::GetGenericContext()
{
  static GC gc = (GC) NULL;

  if (!gc) gc = XCreateGC(this->DisplayId, this->WindowId, 0, 0);

  return (void *) gc;

}

int vtkXRenderWindow::GetEventPending()
{
  XEvent report;

  vtkXRenderWindowFoundMatch = 0;
  XCheckIfEvent(this->DisplayId, &report, vtkXRenderWindowPredProc,
		(char *)this->WindowId);
  return vtkXRenderWindowFoundMatch;
}

// Get the size of the screen in pixels
int *vtkXRenderWindow::GetScreenSize()
{
  // get the default display connection
  if (!this->DisplayId)
    {
    this->DisplayId = XOpenDisplay((char *)NULL);
    if (this->DisplayId == NULL)
      {
      vtkErrorMacro(<< "bad X server connection.\n");
      }
    else
      {
      this->OwnDisplay = 1;
      }
    }

  this->ScreenSize[0] =
    DisplayWidth(this->DisplayId, DefaultScreen(this->DisplayId));
  this->ScreenSize[1] =
    DisplayHeight(this->DisplayId, DefaultScreen(this->DisplayId));

  return this->ScreenSize;
}

// Get the current size of the window in pixels.
int *vtkXRenderWindow::GetSize(void)
{
  XWindowAttributes attribs;

  // if we aren't mapped then just return the ivar
  if (!this->Mapped)
    {
    return(this->Size);
    }

  //  Find the current window size
  XGetWindowAttributes(this->DisplayId,
		       this->WindowId, &attribs);

  this->Size[0] = attribs.width;
  this->Size[1] = attribs.height;

  return this->Size;
}

// Get the position in screen coordinates (pixels) of the window.
int *vtkXRenderWindow::GetPosition(void)
{
  XWindowAttributes attribs;
  int x,y;
  Window child;

  // if we aren't mapped then just return the ivar
  if (!this->Mapped)
    {
    return(this->Position);
    }

  //  Find the current window size
  XGetWindowAttributes(this->DisplayId, this->WindowId, &attribs);
  x = attribs.x;
  y = attribs.y;

  XTranslateCoordinates(this->DisplayId,this->WindowId,
		 RootWindowOfScreen(ScreenOfDisplay(this->DisplayId,0)),
			x,y,&this->Position[0],&this->Position[1],&child);

  return this->Position;
}

// Get this RenderWindow's X display id.
Display *vtkXRenderWindow::GetDisplayId()
{
  vtkDebugMacro(<< "Returning DisplayId of " << (void *)this->DisplayId << "\n");

  return this->DisplayId;
}

// Get this RenderWindow's parent X window id.
Window vtkXRenderWindow::GetParentId()
{
  vtkDebugMacro(<< "Returning ParentId of " << (void *)this->ParentId << "\n");
  return this->ParentId;
}

// Get this RenderWindow's X window id.
Window vtkXRenderWindow::GetWindowId()
{
  vtkDebugMacro(<< "Returning WindowId of " << (void *)this->WindowId << "\n");
  return this->WindowId;
}

// Move the window to a new position on the display.
void vtkXRenderWindow::SetPosition(int x, int y)
{
  // if we aren't mapped then just set the ivars
  if (!this->Mapped)
    {
    if ((this->Position[0] != x)||(this->Position[1] != y))
      {
      this->Modified();
      }
    this->Position[0] = x;
    this->Position[1] = y;
    return;
    }

  XMoveResizeWindow(this->DisplayId,this->WindowId,x,y,
                    this->Size[0], this->Size[1]);
  XSync(this->DisplayId,False);
}

// Sets the parent of the window that WILL BE created.
void vtkXRenderWindow::SetParentId(Window arg)
{
  if (this->ParentId)
    {
    vtkErrorMacro("ParentId is already set.");
    return;
    }

  vtkDebugMacro(<< "Setting ParentId to " << (void *)arg << "\n");

  this->ParentId = arg;
}

// Set this RenderWindow's X window id to a pre-existing window.
void vtkXRenderWindow::SetWindowId(Window arg)
{
  vtkDebugMacro(<< "Setting WindowId to " << (void *)arg << "\n");

  this->WindowId = arg;
}

// Set this RenderWindow's X window id to a pre-existing window.
void vtkXRenderWindow::SetWindowInfo(char *info)
{
  int tmp;

  // get the default display connection
  if (!this->DisplayId)
    {
    this->DisplayId = XOpenDisplay((char *)NULL);
    if (this->DisplayId == NULL)
      {
      vtkErrorMacro(<< "bad X server connection.\n");
      }
    else
      {
      this->OwnDisplay = 1;
      }
    }

  sscanf(info,"%i",&tmp);

  this->WindowId = tmp;
  vtkDebugMacro(<< "Setting WindowId to " << (void *)this->WindowId<< "\n");
}

void vtkXRenderWindow::SetWindowId(void *arg)
{
  this->SetWindowId((Window)arg);
}
void vtkXRenderWindow::SetParentId(void *arg)
{
  this->SetParentId((Window)arg);
}

void vtkXRenderWindow::SetWindowName(char * name)
{
  XTextProperty win_name_text_prop;

  vtkRenderWindow::SetWindowName( name );

  if (this->Mapped)
    {
    if( XStringListToTextProperty( &name, 1, &win_name_text_prop ) == 0 )
      {
      XFree (win_name_text_prop.value);
      vtkWarningMacro(<< "Can't rename window");
      return;
      }

    XSetWMName( this->DisplayId, this->WindowId, &win_name_text_prop );
    XSetWMIconName( this->DisplayId, this->WindowId, &win_name_text_prop );
    XFree (win_name_text_prop.value);
    }
}

// Specify the X window id to use if a WindowRemap is done.
void vtkXRenderWindow::SetNextWindowId(Window arg)
{
  vtkDebugMacro(<< "Setting NextWindowId to " << (void *)arg << "\n");

  this->NextWindowId = arg;
}

// Set the X display id for this RenderWindow to use to a pre-existing
// X display id.
void vtkXRenderWindow::SetDisplayId(Display  *arg)
{
  vtkDebugMacro(<< "Setting DisplayId to " << (void *)arg << "\n");

  this->DisplayId = arg;
  this->OwnDisplay = 0;
}
void vtkXRenderWindow::SetDisplayId(void *arg)
{
  this->SetDisplayId((Display *)arg);
  this->OwnDisplay = 0;
}

void vtkXRenderWindow::PrintSelf(ostream& os, vtkIndent indent)
{
  this->vtkRenderWindow::PrintSelf(os,indent);

  os << indent << "Color Map: " << this->ColorMap << "\n";
  os << indent << "Display Id: " << this->GetDisplayId() << "\n";
  os << indent << "Next Window Id: " << this->NextWindowId << "\n";
  os << indent << "Window Id: " << this->GetWindowId() << "\n";
}
<|endoftext|>


<commit_before>#include "workerCL.hpp"

#define __CL_DEFINE_EXCEPTIONS
#include <CL/cl.hpp>

#include <vector>
#include <string>
#include <iostream>

#include "log.hpp"
#include "reads.hpp"

using namespace std;

WorkerCL::WorkerCL(size_t platform_id, size_t device_id){
	/* GPU environment preparation */

	//Get platforms (drivers) list and keep the one to be use
	vector<cl::Platform> all_platforms;
	cl::Platform::get(&all_platforms);
	if(!all_platforms.size()){
		//No platform ? Send error
		string error = "OPENCL: no platforms found.";
		throw(error);
	}
	m_platform = all_platforms[platform_id];

	//Get devices list and keep the one to use
	vector<cl::Device> devices;
	m_platform.getDevices(CL_DEVICE_TYPE_ALL, &devices);
	if(device_id >= devices.size()){
		string error = "OPENCL: no device of id "+to_string(device_id)+
			" on platform "+to_string(platform_id)+" ("+to_string(devices.size())+" devices)";
		throw(error);
	}
	m_device = devices[device_id];

	//Create context
	m_context = cl::Context({m_device});

	//initialize commands queue
	m_commandqueue = cl::CommandQueue(m_context, m_device);

	//Build kernel sources
	m_program = cl::Program(m_context, kernel_cmp_2_contigs);
	if(m_program.build({m_device}) != CL_SUCCESS){
		string error = "Error building: ";
		error += m_program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(m_device);
		throw(error);
	}

	//Make the kernel
	m_kernel = cl::Kernel(m_program, "cmp_2_contigs");

}

WorkerCL::~WorkerCL(){
}

void WorkerCL::run(const Contigs& contigs, size_t work_group_size){
	/*
	Create the string containing all contigs sequences
	and store the list of contigs size (in same orders)
	to be able to retrieve contigs. Size is store in
	an uint64_t (ulong) to be sure it is 64bits as cl_ulong
	*/

	//Get list of contigs size, the total length of the
	//contigs concatenation and the longuest contig size
	uint64_t nbContigs = contigs.get_nbContigs();
	uint64_t ultraSequenceSize = 0;
	uint64_t longuest_contig_size = 0;
	vector<uint64_t> contigs_size (nbContigs, 0);
	for(uint64_t i=0; i < nbContigs; i++){
		contigs_size[i] = contigs.get_sizeContig(i);
		ultraSequenceSize += contigs_size[i];
		if(contigs_size[i] > longuest_contig_size){longuest_contig_size = contigs_size[i];}
	}

	//Prepare GPU for the run
	cl::Event ev;
		//infos buffer (64bits): number of contigs, size of the ultrasequence, size of longuest contig
		//buffer only accepts non-dynamics arrays (even of size 1)
	uint64_t infos[3] = {nbContigs, ultraSequenceSize, longuest_contig_size};
	cl::Buffer buf_infos (m_context, CL_MEM_READ_ONLY, sizeof(uint64_t));
	m_commandqueue.enqueueWriteBuffer(buf_infos, CL_TRUE, 0, sizeof(uint64_t), &infos);
	m_kernel.setArg(0, buf_infos); //update kernel

		//Prepare the buffer for the results matrix (it will be 1D so an id of {x,y} is id=x+y*x_size)
		//The size of the buffer = char * x_size * y_size. Note: x_size == y_size == nb_contigs
	unsigned int scores_size = sizeof(char)*nbContigs*nbContigs;
	cl::Buffer buf_scores (m_context, CL_MEM_WRITE_ONLY, scores_size);
	m_kernel.setArg(1, buf_scores);

		//sequences sizes (array of 64bits) buffer
	cl::Buffer buf_sizes (m_context, CL_MEM_READ_ONLY, sizeof(uint64_t)*nbContigs);
	m_commandqueue.enqueueWriteBuffer(buf_sizes, CL_TRUE, 0, sizeof(uint64_t)*nbContigs, &contigs_size[0]);
	m_kernel.setArg(2, buf_sizes);

		//ultrasequence, get each contigs sequence and add it in ultrasequence
	char* ultraSequence = new char[ultraSequenceSize];
	uint64_t i = 0;
	for(uint64_t c=0; c < nbContigs; c++){
		string seq = contigs.get_seqContig(c);
		for(size_t j=0; j < seq.size(); j++){
				ultraSequence[i] = seq[j];
				i++;
		}
	}
	cout << "UltraSequence:" << endl;
	cout << ultraSequence << endl;

	cl::Buffer buf_ultraseq (m_context, CL_MEM_READ_ONLY, sizeof(char)*ultraSequenceSize);
	m_commandqueue.enqueueWriteBuffer(buf_ultraseq, CL_TRUE, 0, sizeof(char)*ultraSequenceSize, ultraSequence);
	m_kernel.setArg(3, buf_ultraseq);

	delete ultraSequence; //Clean  the memory
	ultraSequence = nullptr;

		//buffer for work items : they need 2 arrays for need2a and 2 array for each sequences. These arrays are of size of longuest contig.
		/*
			Each work item need its own array (for each arrays) allocated on local.
			So a local array (of a work group) contains all concatenated array of the work items of the same group.
			This local array have a size of longuest_contig_size*work_group_size number of elements.
		*/

	//Run the kernel and wait the end
	m_commandqueue.enqueueNDRangeKernel(m_kernel,cl::NullRange, cl::NDRange(nbContigs, nbContigs), cl::NullRange, NULL, &ev);
	ev.wait();

	//Get the score matrix: get the buffer into a 1D array then convert de 2D vectors array
	char* scores_1D = new char[nbContigs*nbContigs];
	m_commandqueue.enqueueReadBuffer(buf_scores, CL_TRUE, 0, scores_size, scores_1D);
	vector< vector<char> > scores = vector< vector<char> >(nbContigs, vector<char>(nbContigs, 0));
	for(size_t j=0; j<nbContigs; j++){
		for(size_t i=0; i<nbContigs; i++){
			scores[i][j] = scores_1D[i+nbContigs*j];
		}
	}

	//TEST: display scores
	cerr << "Seqs" << flush;
	for(size_t i=0; i < nbContigs; i++){cerr << "\t" << i << flush;}
	cerr << endl;
	for(size_t j=0; j < nbContigs; j++){
		string t = to_string(j);
		for(size_t i=0; i < nbContigs; i++){
			t += "\t"+to_string(scores[i][j]);
		}
		cerr << t << endl;
	}

	//Clean the memory
	delete scores_1D;
	scores_1D = nullptr;
}

void WorkerCL::list_infos(Log& output){
	string txt;

	//Get platforms
	txt = "\n\t[Platforms list]";
	output.write(txt);
	vector<cl::Platform> platforms;
	cl::Platform::get(&platforms);
	if(!platforms.size()){
		txt = "No platform detected";
		output.write(txt);
		return;
	}
	txt = "platform_id\tplatform_name\tplatform_profile\tplatform_vendor\tplatform_version";
	output.write(txt);
	for(size_t i=0; i < platforms.size(); i++){
		cl::Platform& p = platforms[i];
		txt = to_string(i);
		txt += "\t" + p.getInfo<CL_PLATFORM_NAME>();
		txt += "\t" + p.getInfo<CL_PLATFORM_PROFILE>();
		txt += "\t" + p.getInfo<CL_PLATFORM_VENDOR>();
		txt += "\t" + p.getInfo<CL_PLATFORM_VERSION>();
		//txt += "\t" + p.getInfo<CL_PLATFORM_EXTENSIONS>();
		output.write(txt);
	}

	//Get devices
	txt = "\n\t[Devices list]";
	output.write(txt);
	txt = "platform_id\tdevice_id\tdevice_name\tdevice_vendor\tdevice_profile\tdevice_version\tdevice_globalmem\tdevice_localmem\tdevice_maxgroupsize\tdriver_version\topencl_c_version";
	output.write(txt);
	for(size_t p = 0; p < platforms.size(); p++){
		vector<cl::Device> devices;
		platforms[p].getDevices(CL_DEVICE_TYPE_ALL, &devices);
		for(size_t d = 0; d < devices.size(); d++){
			cl::Device& device = devices[d];
			txt = to_string(p)+"\t"+to_string(d);
			txt += "\t" + device.getInfo<CL_DEVICE_NAME>();
			txt += "\t" + device.getInfo<CL_DEVICE_VENDOR>();
			txt += "\t" + device.getInfo<CL_DEVICE_PROFILE>();
			txt += "\t" + device.getInfo<CL_DEVICE_VERSION>();
			txt += "\t" + to_string(device.getInfo<CL_DEVICE_GLOBAL_MEM_SIZE>())+"B";
			txt += "\t" + to_string(device.getInfo<CL_DEVICE_LOCAL_MEM_SIZE>())+"B";
			txt += "\t" + to_string(device.getInfo<CL_DEVICE_MAX_WORK_GROUP_SIZE>());
			txt += "\t" + device.getInfo<CL_DRIVER_VERSION>();
			txt += "\t" + device.getInfo<CL_DEVICE_OPENCL_C_VERSION>();
			output.write(txt);
		}
	}
}

/*
Les balises 'R"CLCODE(' et ')CLCODE'   (du type R"NAME( ... )NAME") servent à définir un
string litéral brut. C'est utile pour avoir un string sur plusieurs ligne, comme un code,
et cela évite d'avoir à ouvrir puis fermer les guillemets à chaque ligne.
*/

string WorkerCL::kernel_cmp_2_contigs = R"CLCODE(
	kernel void cmp_2_contigs(global unsigned long *infos, global char *scores, global unsigned long *seqs_sizes, global char *ultraseq){
		int seq1_id = get_global_id(0);
		int seq2_id = get_global_id(1);

		//Get the position of the seqs in the ultraseq
		unsigned long seq1_begin = 0;
		unsigned long seq2_begin = 0;
		unsigned long i=0;
		while(i < seq1_id || i < seq2_id){
			if(i < seq1_id){seq1_begin += seqs_sizes[i];}
			if(i < seq2_id){seq2_begin += seqs_sizes[i];}
			i++;
		}
		//Get the sizes and the end pos of the seqs
		unsigned long seq1_size = seqs_sizes[seq1_id];
		unsigned long seq2_size = seqs_sizes[seq2_id];
		unsigned long seq1_end= seq1_begin + seq1_size - 1;
		unsigned long seq2_end= seq2_begin + seq1_size - 1;

		//Test if same seq : =1 else =0
		scores[seq1_id + infos[0]*seq2_id] = 0;
		if(seq1_size == seq2_size){
			bool same = true;
			for(unsigned int i=0; i < seq1_size; i++){
				if(ultraseq[seq1_begin+i] != ultraseq[seq2_begin+i]){
					same = false;
					i = seq1_size;
				}
			}
			if(same){scores[seq1_id+infos[0]*seq2_id]=1;}
		}

	}
)CLCODE";
<commit_msg>Use ptr to access the sequences (instead of copying them in private/local). It's a test to the further implementation of local buffers manipulations<commit_after>#include "workerCL.hpp"

#define __CL_DEFINE_EXCEPTIONS
#include <CL/cl.hpp>

#include <vector>
#include <string>
#include <iostream>

#include "log.hpp"
#include "reads.hpp"

using namespace std;

WorkerCL::WorkerCL(size_t platform_id, size_t device_id){
	/* GPU environment preparation */

	//Get platforms (drivers) list and keep the one to be use
	vector<cl::Platform> all_platforms;
	cl::Platform::get(&all_platforms);
	if(!all_platforms.size()){
		//No platform ? Send error
		string error = "OPENCL: no platforms found.";
		throw(error);
	}
	m_platform = all_platforms[platform_id];

	//Get devices list and keep the one to use
	vector<cl::Device> devices;
	m_platform.getDevices(CL_DEVICE_TYPE_ALL, &devices);
	if(device_id >= devices.size()){
		string error = "OPENCL: no device of id "+to_string(device_id)+
			" on platform "+to_string(platform_id)+" ("+to_string(devices.size())+" devices)";
		throw(error);
	}
	m_device = devices[device_id];

	//Create context
	m_context = cl::Context({m_device});

	//initialize commands queue
	m_commandqueue = cl::CommandQueue(m_context, m_device);

	//Build kernel sources
	m_program = cl::Program(m_context, kernel_cmp_2_contigs);
	if(m_program.build({m_device}) != CL_SUCCESS){
		string error = "Error building: ";
		error += m_program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(m_device);
		throw(error);
	}

	//Make the kernel
	m_kernel = cl::Kernel(m_program, "cmp_2_contigs");

}

WorkerCL::~WorkerCL(){
}

void WorkerCL::run(const Contigs& contigs, size_t work_group_size){
	/*
	Create the string containing all contigs sequences
	and store the list of contigs size (in same orders)
	to be able to retrieve contigs. Size is store in
	an uint64_t (ulong) to be sure it is 64bits as cl_ulong
	*/

	//Get list of contigs size, the total length of the
	//contigs concatenation and the longuest contig size
	uint64_t nbContigs = contigs.get_nbContigs();
	uint64_t ultraSequenceSize = 0;
	uint64_t longuest_contig_size = 0;
	vector<uint64_t> contigs_size (nbContigs, 0);
	for(uint64_t i=0; i < nbContigs; i++){
		contigs_size[i] = contigs.get_sizeContig(i);
		ultraSequenceSize += contigs_size[i];
		if(contigs_size[i] > longuest_contig_size){longuest_contig_size = contigs_size[i];}
	}

	//Prepare GPU for the run
	cl::Event ev;
		//infos buffer (64bits): number of contigs, size of the ultrasequence, size of longuest contig
		//buffer only accepts non-dynamics arrays (even of size 1)
	uint64_t infos[3] = {nbContigs, ultraSequenceSize, longuest_contig_size};
	cl::Buffer buf_infos (m_context, CL_MEM_READ_ONLY, sizeof(uint64_t));
	m_commandqueue.enqueueWriteBuffer(buf_infos, CL_TRUE, 0, sizeof(uint64_t), &infos);
	m_kernel.setArg(0, buf_infos); //update kernel

		//Prepare the buffer for the results matrix (it will be 1D so an id of {x,y} is id=x+y*x_size)
		//The size of the buffer = char * x_size * y_size. Note: x_size == y_size == nb_contigs
	unsigned int scores_size = sizeof(char)*nbContigs*nbContigs;
	cl::Buffer buf_scores (m_context, CL_MEM_WRITE_ONLY, scores_size);
	m_kernel.setArg(1, buf_scores);

		//sequences sizes (array of 64bits) buffer
	cl::Buffer buf_sizes (m_context, CL_MEM_READ_ONLY, sizeof(uint64_t)*nbContigs);
	m_commandqueue.enqueueWriteBuffer(buf_sizes, CL_TRUE, 0, sizeof(uint64_t)*nbContigs, &contigs_size[0]);
	m_kernel.setArg(2, buf_sizes);

		//ultrasequence, get each contigs sequence and add it in ultrasequence
	char* ultraSequence = new char[ultraSequenceSize];
	uint64_t i = 0;
	for(uint64_t c=0; c < nbContigs; c++){
		string seq = contigs.get_seqContig(c);
		for(size_t j=0; j < seq.size(); j++){
				ultraSequence[i] = seq[j];
				i++;
		}
	}
	cout << "UltraSequence:" << endl;
	cout << ultraSequence << endl;

	cl::Buffer buf_ultraseq (m_context, CL_MEM_READ_ONLY, sizeof(char)*ultraSequenceSize);
	m_commandqueue.enqueueWriteBuffer(buf_ultraseq, CL_TRUE, 0, sizeof(char)*ultraSequenceSize, ultraSequence);
	m_kernel.setArg(3, buf_ultraseq);

	delete ultraSequence; //Clean  the memory
	ultraSequence = nullptr;

		//buffer for work items : they need 2 arrays for need2a and 2 array for each sequences. These arrays are of size of longuest contig.
		/*
			Each work item need its own array (for each arrays) allocated on local.
			So a local array (of a work group) contains all concatenated array of the work items of the same group.
			This local array have a size of longuest_contig_size*work_group_size number of elements.
		*/

	//Run the kernel and wait the end
	m_commandqueue.enqueueNDRangeKernel(m_kernel,cl::NullRange, cl::NDRange(nbContigs, nbContigs), cl::NullRange, NULL, &ev);
	ev.wait();

	//Get the score matrix: get the buffer into a 1D array then convert de 2D vectors array
	char* scores_1D = new char[nbContigs*nbContigs];
	m_commandqueue.enqueueReadBuffer(buf_scores, CL_TRUE, 0, scores_size, scores_1D);
	vector< vector<char> > scores = vector< vector<char> >(nbContigs, vector<char>(nbContigs, 0));
	for(size_t j=0; j<nbContigs; j++){
		for(size_t i=0; i<nbContigs; i++){
			scores[i][j] = scores_1D[i+nbContigs*j];
		}
	}

	//TEST: display scores
	cerr << "Seqs" << flush;
	for(size_t i=0; i < nbContigs; i++){cerr << "\t" << i << flush;}
	cerr << endl;
	for(size_t j=0; j < nbContigs; j++){
		string t = to_string(j);
		for(size_t i=0; i < nbContigs; i++){
			t += "\t"+to_string(scores[i][j]);
		}
		cerr << t << endl;
	}

	//Clean the memory
	delete scores_1D;
	scores_1D = nullptr;
}

void WorkerCL::list_infos(Log& output){
	string txt;

	//Get platforms
	txt = "\n\t[Platforms list]";
	output.write(txt);
	vector<cl::Platform> platforms;
	cl::Platform::get(&platforms);
	if(!platforms.size()){
		txt = "No platform detected";
		output.write(txt);
		return;
	}
	txt = "platform_id\tplatform_name\tplatform_profile\tplatform_vendor\tplatform_version";
	output.write(txt);
	for(size_t i=0; i < platforms.size(); i++){
		cl::Platform& p = platforms[i];
		txt = to_string(i);
		txt += "\t" + p.getInfo<CL_PLATFORM_NAME>();
		txt += "\t" + p.getInfo<CL_PLATFORM_PROFILE>();
		txt += "\t" + p.getInfo<CL_PLATFORM_VENDOR>();
		txt += "\t" + p.getInfo<CL_PLATFORM_VERSION>();
		//txt += "\t" + p.getInfo<CL_PLATFORM_EXTENSIONS>();
		output.write(txt);
	}

	//Get devices
	txt = "\n\t[Devices list]";
	output.write(txt);
	txt = "platform_id\tdevice_id\tdevice_name\tdevice_vendor\tdevice_profile\tdevice_version\tdevice_globalmem\tdevice_localmem\tdevice_maxgroupsize\tdriver_version\topencl_c_version";
	output.write(txt);
	for(size_t p = 0; p < platforms.size(); p++){
		vector<cl::Device> devices;
		platforms[p].getDevices(CL_DEVICE_TYPE_ALL, &devices);
		for(size_t d = 0; d < devices.size(); d++){
			cl::Device& device = devices[d];
			txt = to_string(p)+"\t"+to_string(d);
			txt += "\t" + device.getInfo<CL_DEVICE_NAME>();
			txt += "\t" + device.getInfo<CL_DEVICE_VENDOR>();
			txt += "\t" + device.getInfo<CL_DEVICE_PROFILE>();
			txt += "\t" + device.getInfo<CL_DEVICE_VERSION>();
			txt += "\t" + to_string(device.getInfo<CL_DEVICE_GLOBAL_MEM_SIZE>())+"B";
			txt += "\t" + to_string(device.getInfo<CL_DEVICE_LOCAL_MEM_SIZE>())+"B";
			txt += "\t" + to_string(device.getInfo<CL_DEVICE_MAX_WORK_GROUP_SIZE>());
			txt += "\t" + device.getInfo<CL_DRIVER_VERSION>();
			txt += "\t" + device.getInfo<CL_DEVICE_OPENCL_C_VERSION>();
			output.write(txt);
		}
	}
}

/*
Les balises 'R"CLCODE(' et ')CLCODE'   (du type R"NAME( ... )NAME") servent à définir un
string litéral brut. C'est utile pour avoir un string sur plusieurs ligne, comme un code,
et cela évite d'avoir à ouvrir puis fermer les guillemets à chaque ligne.
*/

string WorkerCL::kernel_cmp_2_contigs = R"CLCODE(
	kernel void cmp_2_contigs(global unsigned long *infos, global char *scores, global unsigned long *seqs_sizes, global char *ultraseq){
		int seq1_id = get_global_id(0);
		int seq2_id = get_global_id(1);

		/* Old way: basic memory. Work
		//Get the position of the seqs in the ultraseq
		unsigned long seq1_begin = 0;
		unsigned long seq2_begin = 0;
		unsigned long i=0;
		while(i < seq1_id || i < seq2_id){
			if(i < seq1_id){seq1_begin += seqs_sizes[i];}
			if(i < seq2_id){seq2_begin += seqs_sizes[i];}
			i++;
		}

		//Get the sizes and the end pos of the seqs
		unsigned long seq1_size = seqs_sizes[seq1_id];
		unsigned long seq2_size = seqs_sizes[seq2_id];
		unsigned long seq1_end= seq1_begin + seq1_size - 1;
		unsigned long seq2_end= seq2_begin + seq1_size - 1;

		//Test if same seq : =1 else =0
		scores[seq1_id + infos[0]*seq2_id] = 0;
		if(seq1_size == seq2_size){
			bool same = true;
			for(unsigned int i=0; i < seq1_size; i++){
				if(ultraseq[seq1_begin+i] != ultraseq[seq2_begin+i]){
					same = false;
					i = seq1_size;
				}
			}
			if(same){scores[seq1_id+infos[0]*seq2_id]=1;}
		}
		*/

		//Get the position of seqs and sizes
		global char* seq1_ptr = NULL;
		global char* seq2_ptr = NULL;
			//Calculate the begin for each item (the for boucle is on all contigs (infos[0]) but it's stop before)
		unsigned long start = 0;
		for(unsigned long i = 0; i < seq1_id; i++){start += seqs_sizes[i];}
		seq1_ptr = &ultraseq[start];
		start = 0;
		for(unsigned long i = 0; i < seq2_id; i++){start += seqs_sizes[i];}
		seq2_ptr = &ultraseq[start];
			//get sizes
		unsigned long seq1_size = seqs_sizes[seq1_id];
		unsigned long seq2_size = seqs_sizes[seq2_id];

		//Test: if same seq then =1 else =0
		scores[seq1_id + infos[0]*seq2_id] = 0;
		if(seq1_size == seq2_size){
			bool same=true;
			for(unsigned int i=0; i < seq1_size; i++){
				if(seq1_ptr[i] != seq2_ptr[i]){
					same = false;
					i = seq1_size;
				}
			}
			if(same){scores[seq1_id+infos[0]*seq2_id]=1;}
		}

	}
)CLCODE";
<|endoftext|>


<commit_before>#pragma once
#include <cstdint>

namespace haste {

using std::uint32_t;

enum class entity_type : uint32_t {
  camera = 0,
  mesh = 1,
  light = 2,
  empty = 3
};

inline uint32_t encode_material(uint32_t material_id, entity_type type) {
  return material_id << 2 | uint32_t(type);
}

inline uint32_t decode_material(uint32_t material_id) {
  return material_id >> 2;
}

inline uint32_t pack_normal(vec3 n) {
  float x = clamp((n.x + 1.0f) * 0.5f, 0.f, 1.0f) * 65534.f;
  float y = clamp((n.y + 1.0f) * 0.5f, 0.f, 1.0f) * 32766.f;
  float z = n.z < 0.0f ? 0.0f : 1.0f;
  return uint32_t(x) << 16 | uint32_t(y) << 1 | uint32_t(z);
}

inline vec3 unpack_normal(uint32_t n) {
  float x = float(n >> 16) * 3.05185094e-05f - 1.0f;
  float y = float(n << 16 >> 17) * 6.10388817e-05f - 1.0f;
  float z = sqrt(1.0f - x * x - y * y) * (float(n & 1u) - 0.5f) * 2.0f;
  return vec3(x, y, z);
}

struct SurfacePoint {
  vec3 _position;
  vec3 gnormal;
  mat3 _tangent;
  uint32_t material_id = UINT32_MAX;

  SurfacePoint() = default;

  SurfacePoint(const vec3& position, const vec3& normal, const vec3& tangent,
               uint32_t material_id) {
    _position = position;
    _tangent[0] = normalize(cross(normal, tangent));
    _tangent[1] = normal;
    _tangent[2] = tangent;
    material_id = material_id;
  }

  const vec3& position() const { return _position; }
  const vec3& normal() const { return _tangent[1]; }
  const vec3& tangent() const { return _tangent[2]; }
  const vec3& bitangent() const { return _tangent[0]; }
  const vec3 toWorld(const vec3& surface) const { return _tangent * surface; }
  const vec3 toSurface(const vec3& world) const { return world * _tangent; }

  uint32_t material_index() const { return material_id >> 2; }

  bool is_camera() const {
    return (material_id & 3u) == uint32_t(entity_type::camera);
  }
  bool is_mesh() const {
    return (material_id & 3u) == uint32_t(entity_type::mesh);
  }
  bool is_light() const {
    return (material_id & 3u) == uint32_t(entity_type::light);
  }
  bool is_present() const { return material_id != UINT32_MAX; }
};

struct Edge {
 public:
  Edge(const SurfacePoint& fst, const SurfacePoint& snd, const vec3& omega) {
    distSqInv = 1.0f / distance2(fst.position(), snd.position());
    fCosTheta = abs(dot(omega, snd.normal()));
    bCosTheta = abs(dot(omega, fst.normal()));
    fGeometry = distSqInv * fCosTheta;
    bGeometry = distSqInv * bCosTheta;
  }

  float distSqInv;
  float fCosTheta;
  float bCosTheta;
  float fGeometry;
  float bGeometry;
};
}
<commit_msg>Remove dead code from SurfacePoint.<commit_after>#pragma once
#include <cstdint>

namespace haste {

using std::uint32_t;

enum class entity_type : uint32_t {
  camera = 0,
  mesh = 1,
  light = 2,
  empty = 3
};

inline uint32_t encode_material(uint32_t material_id, entity_type type) {
  return material_id << 2 | uint32_t(type);
}

inline uint32_t decode_material(uint32_t material_id) {
  return material_id >> 2;
}

inline uint32_t pack_normal(vec3 n) {
  float x = clamp((n.x + 1.0f) * 0.5f, 0.f, 1.0f) * 65534.f;
  float y = clamp((n.y + 1.0f) * 0.5f, 0.f, 1.0f) * 32766.f;
  float z = n.z < 0.0f ? 0.0f : 1.0f;
  return uint32_t(x) << 16 | uint32_t(y) << 1 | uint32_t(z);
}

inline vec3 unpack_normal(uint32_t n) {
  float x = float(n >> 16) * 3.05185094e-05f - 1.0f;
  float y = float(n << 16 >> 17) * 6.10388817e-05f - 1.0f;
  float z = sqrt(1.0f - x * x - y * y) * (float(n & 1u) - 0.5f) * 2.0f;
  return vec3(x, y, z);
}

struct SurfacePoint {
  vec3 _position;
  vec3 gnormal;
  mat3 _tangent;
  uint32_t material_id = UINT32_MAX;

  SurfacePoint() = default;

  const vec3& position() const { return _position; }
  const vec3& normal() const { return _tangent[1]; }
  const vec3& tangent() const { return _tangent[2]; }
  const vec3& bitangent() const { return _tangent[0]; }
  const vec3 toWorld(const vec3& surface) const { return _tangent * surface; }
  const vec3 toSurface(const vec3& world) const { return world * _tangent; }

  uint32_t material_index() const { return material_id >> 2; }

  bool is_camera() const {
    return (material_id & 3u) == uint32_t(entity_type::camera);
  }
  bool is_mesh() const {
    return (material_id & 3u) == uint32_t(entity_type::mesh);
  }
  bool is_light() const {
    return (material_id & 3u) == uint32_t(entity_type::light);
  }
  bool is_present() const { return material_id != UINT32_MAX; }
};

struct Edge {
 public:
  Edge(const SurfacePoint& fst, const SurfacePoint& snd, const vec3& omega) {
    distSqInv = 1.0f / distance2(fst.position(), snd.position());
    fCosTheta = abs(dot(omega, snd.normal()));
    bCosTheta = abs(dot(omega, fst.normal()));
    fGeometry = distSqInv * fCosTheta;
    bGeometry = distSqInv * bCosTheta;
  }

  float distSqInv;
  float fCosTheta;
  float bCosTheta;
  float fGeometry;
  float bGeometry;
};
}
<|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright Leiden University Medical Center, Erasmus University Medical
 *  Center and contributors
 *
 *  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.txt
 *
 *  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 "selxDisplacementFieldNiftiToItkImageSinkComponent.h"
#include "selxCheckTemplateProperties.h"

namespace selx
{
template< int Dimensionality, class TPixel >
DisplacementFieldNiftiToItkImageSinkComponent< Dimensionality, TPixel >::DisplacementFieldNiftiToItkImageSinkComponent( const std::string & name, LoggerImpl & logger ) :
  Superclass( name, logger ), m_NetworkBuilderOutputImage( nullptr ), m_DisplacementFieldInterface( nullptr ), m_ImageDomainInterface( nullptr )
{
  m_MiniPipelineOutputImage = ItkDisplacementFieldType::New(); // this is just an empty image for we have a SmartPointer we can pass around downstream. The actual image data will be grafted into this image.
  m_ImportFilter            = ImportFilterType::New();
}

template< int Dimensionality, class TPixel >
DisplacementFieldNiftiToItkImageSinkComponent< Dimensionality, TPixel >::~DisplacementFieldNiftiToItkImageSinkComponent()
{
}

template< int Dimensionality, class TPixel >
int
DisplacementFieldNiftiToItkImageSinkComponent< Dimensionality, TPixel >::Accept( typename NiftiDisplacementFieldInterfaceType::Pointer other )
{
  // Store pointer to the m_WarpedImageInterface for getting the result image after in has been generated (registration).
  // TODO: sanity check that m_WarpedImageInterface was Null to detect if Set was called more than once erroneously.
  this->m_DisplacementFieldInterface = other;
  return 0;
}

template< int Dimensionality, class TPixel >
int
DisplacementFieldNiftiToItkImageSinkComponent< Dimensionality, TPixel >::Accept( typename ItkImageDomainInterfaceType::Pointer other )
{
  // Store pointer to the m_ImageDomainInterface for getting the result image after in has been generated (registration).
  // TODO: sanity check that m_ImageDomainInterface was Null to detect if Set was called more than once erroneously.
  m_MiniPipelineOutputImage->SetRegions( other->GetItkImageDomainFixed()->GetLargestPossibleRegion() );
  //this->m_ImageDomainInterface = other;
  return 0;
}

template< int Dimensionality, class TPixel >
void
DisplacementFieldNiftiToItkImageSinkComponent< Dimensionality, TPixel >::SetMiniPipelineOutput( itk::DataObject::Pointer NetworkBuilderOutput )
{
  /** Tries to cast the NetworkBuilderOutput to an image (data object) and stores the result.
  *  The resulting output image will be grafted into when the sink component is connected to an other component.
  * */
  //
  /*
  this->m_NetworkBuilderOutputImage = dynamic_cast< ItkImageType * >(NetworkBuilderOutput.GetPointer());
  if (this->m_NetworkBuilderOutputImage == nullptr)
  {
    throw std::runtime_error("DisplacementFieldNiftiToItkImageSinkComponent cannot cast the NetworkBuilder's Output to the required type");
  }
  this->m_MiniPipelineOutputImage = this->m_NetworkBuilderOutputImage;
  */
}

template< int Dimensionality, class TPixel >
typename itk::DataObject::Pointer
DisplacementFieldNiftiToItkImageSinkComponent< Dimensionality, TPixel >::GetMiniPipelineOutput()
{
  return this->m_MiniPipelineOutputImage.GetPointer();
}

template< int Dimensionality, class TPixel >
typename AnyFileWriter::Pointer
DisplacementFieldNiftiToItkImageSinkComponent< Dimensionality, TPixel >::GetOutputFileWriter()
{
  // Instanstiate an image file writer, decorated such that it can be implicitly cast to an AnyFileWriterType
  return DecoratedWriterType::New().GetPointer();
}

template< int Dimensionality, class TPixel >
typename itk::DataObject::Pointer
DisplacementFieldNiftiToItkImageSinkComponent< Dimensionality, TPixel >::GetInitializedOutput()
{
  return ItkDisplacementFieldType::New().GetPointer();
}

template< int Dimensionality, class TPixel >
void
DisplacementFieldNiftiToItkImageSinkComponent< Dimensionality, TPixel >::Update()
{
  auto displacementFieldNiftiImage = this->m_DisplacementFieldInterface->GetDisplacementFieldNiftiImage();
  displacementFieldNiftiImage->scl_slope = -1;
  //auto region = m_MiniPipelineOutputImage->GetOutput()->GetRegion();
  // auto  other->GetItkImageDomainFixed()->GetLargestPossibleRegion()
  /*float *dispPtrX = static_cast<float *>(displacementFieldNiftiImage->data);
  float *dispPtrY = static_cast<float *>(&dispPtrX[displacementFieldNiftiImage->nvox]);
  float *dispPtrZ = static_cast<float *>(&dispPtrY[displacementFieldNiftiImage->nvox]);
  for (int v = 0; v < displacementFieldNiftiImage->nvox; v++) {
	  dispPtrX[v] *= -1.f;
	  dispPtrY[v] *= -1.f;
  }
  */
  auto displacementFieldItkImage   = NiftiToItkImage< ItkDisplacementFieldType, TPixel >::Convert( displacementFieldNiftiImage );
  //auto displacementFieldItkImage = NiftiToItkImage< itk::Image< TPixel, Dimensionality >, TPixel >::Convert(displacementFieldNiftiImage);
  this->m_MiniPipelineOutputImage->Graft( displacementFieldItkImage );
}

template< int Dimensionality, class TPixel >
bool
DisplacementFieldNiftiToItkImageSinkComponent< Dimensionality, TPixel >::MeetsCriterion( const ComponentBase::CriterionType & criterion )
{
  bool hasUndefinedCriteria( false );
  bool meetsCriteria( false );
  auto status = CheckTemplateProperties( this->TemplateProperties(), criterion );
  if( status == CriterionStatus::Satisfied )
  {
    return true;
  }
  else if( status == CriterionStatus::Failed )
  {
    return false;
  } // else: CriterionStatus::Unknown

  return meetsCriteria;
}
} //end namespace selx
<commit_msg>DOC: small comment on niftyreg displacement fields<commit_after>/*=========================================================================
 *
 *  Copyright Leiden University Medical Center, Erasmus University Medical
 *  Center and contributors
 *
 *  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.txt
 *
 *  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 "selxDisplacementFieldNiftiToItkImageSinkComponent.h"
#include "selxCheckTemplateProperties.h"

namespace selx
{
template< int Dimensionality, class TPixel >
DisplacementFieldNiftiToItkImageSinkComponent< Dimensionality, TPixel >::DisplacementFieldNiftiToItkImageSinkComponent( const std::string & name, LoggerImpl & logger ) :
  Superclass( name, logger ), m_NetworkBuilderOutputImage( nullptr ), m_DisplacementFieldInterface( nullptr ), m_ImageDomainInterface( nullptr )
{
  m_MiniPipelineOutputImage = ItkDisplacementFieldType::New(); // this is just an empty image for we have a SmartPointer we can pass around downstream. The actual image data will be grafted into this image.
  m_ImportFilter            = ImportFilterType::New();
}

template< int Dimensionality, class TPixel >
DisplacementFieldNiftiToItkImageSinkComponent< Dimensionality, TPixel >::~DisplacementFieldNiftiToItkImageSinkComponent()
{
}

template< int Dimensionality, class TPixel >
int
DisplacementFieldNiftiToItkImageSinkComponent< Dimensionality, TPixel >::Accept( typename NiftiDisplacementFieldInterfaceType::Pointer other )
{
  // Store pointer to the m_WarpedImageInterface for getting the result image after in has been generated (registration).
  // TODO: sanity check that m_WarpedImageInterface was Null to detect if Set was called more than once erroneously.
  this->m_DisplacementFieldInterface = other;
  return 0;
}

template< int Dimensionality, class TPixel >
int
DisplacementFieldNiftiToItkImageSinkComponent< Dimensionality, TPixel >::Accept( typename ItkImageDomainInterfaceType::Pointer other )
{
  // Store pointer to the m_ImageDomainInterface for getting the result image after in has been generated (registration).
  // TODO: sanity check that m_ImageDomainInterface was Null to detect if Set was called more than once erroneously.
  m_MiniPipelineOutputImage->SetRegions( other->GetItkImageDomainFixed()->GetLargestPossibleRegion() );
  //this->m_ImageDomainInterface = other;
  return 0;
}

template< int Dimensionality, class TPixel >
void
DisplacementFieldNiftiToItkImageSinkComponent< Dimensionality, TPixel >::SetMiniPipelineOutput( itk::DataObject::Pointer NetworkBuilderOutput )
{
  /** Tries to cast the NetworkBuilderOutput to an image (data object) and stores the result.
  *  The resulting output image will be grafted into when the sink component is connected to an other component.
  * */
  //
  /*
  this->m_NetworkBuilderOutputImage = dynamic_cast< ItkImageType * >(NetworkBuilderOutput.GetPointer());
  if (this->m_NetworkBuilderOutputImage == nullptr)
  {
    throw std::runtime_error("DisplacementFieldNiftiToItkImageSinkComponent cannot cast the NetworkBuilder's Output to the required type");
  }
  this->m_MiniPipelineOutputImage = this->m_NetworkBuilderOutputImage;
  */
}

template< int Dimensionality, class TPixel >
typename itk::DataObject::Pointer
DisplacementFieldNiftiToItkImageSinkComponent< Dimensionality, TPixel >::GetMiniPipelineOutput()
{
  return this->m_MiniPipelineOutputImage.GetPointer();
}

template< int Dimensionality, class TPixel >
typename AnyFileWriter::Pointer
DisplacementFieldNiftiToItkImageSinkComponent< Dimensionality, TPixel >::GetOutputFileWriter()
{
  // Instanstiate an image file writer, decorated such that it can be implicitly cast to an AnyFileWriterType
  return DecoratedWriterType::New().GetPointer();
}

template< int Dimensionality, class TPixel >
typename itk::DataObject::Pointer
DisplacementFieldNiftiToItkImageSinkComponent< Dimensionality, TPixel >::GetInitializedOutput()
{
  return ItkDisplacementFieldType::New().GetPointer();
}

template< int Dimensionality, class TPixel >
void
DisplacementFieldNiftiToItkImageSinkComponent< Dimensionality, TPixel >::Update()
{
  auto displacementFieldNiftiImage = this->m_DisplacementFieldInterface->GetDisplacementFieldNiftiImage();
  // For some reason the displacement vectors in niftyreg have opposite sign than in itk. A quick fix is to set the slope from 1 to -1.
  // TODO: 1) NiftiToItkImage should handle this generically for displacement fields. 2) nifti images can have an intent_code = DISPVECT, which seem applicable here. However, the intent_code = VECTOR, currently.
  displacementFieldNiftiImage->scl_slope = -1;
  auto displacementFieldItkImage   = NiftiToItkImage< ItkDisplacementFieldType, TPixel >::Convert( displacementFieldNiftiImage );
  this->m_MiniPipelineOutputImage->Graft( displacementFieldItkImage );
}

template< int Dimensionality, class TPixel >
bool
DisplacementFieldNiftiToItkImageSinkComponent< Dimensionality, TPixel >::MeetsCriterion( const ComponentBase::CriterionType & criterion )
{
  bool hasUndefinedCriteria( false );
  bool meetsCriteria( false );
  auto status = CheckTemplateProperties( this->TemplateProperties(), criterion );
  if( status == CriterionStatus::Satisfied )
  {
    return true;
  }
  else if( status == CriterionStatus::Failed )
  {
    return false;
  } // else: CriterionStatus::Unknown

  return meetsCriteria;
}
} //end namespace selx
<|endoftext|>


<commit_before>/* Copyright 2016 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/core/distributed_runtime/rpc/grpc_tensor_coding.h"

#include "grpcpp/support/byte_buffer.h"
#include "grpcpp/support/slice.h"
#include "absl/flags/flag.h"
#include "tensorflow/core/common_runtime/dma_helper.h"
#include "tensorflow/core/framework/tensor.h"
#include "tensorflow/core/framework/tensor.pb.h"
#include "tensorflow/core/framework/tensor_reference.h"
#include "tensorflow/core/framework/tensor_shape.pb.h"
#include "tensorflow/core/lib/gtl/inlined_vector.h"
#include "tensorflow/core/lib/io/proto_encode_helper.h"
#include "tensorflow/core/platform/env.h"
#include "tensorflow/core/protobuf/worker.pb.h"

// (Omitted internal-only flag)

namespace tensorflow {
namespace grpc {

void EncodeRecvTensorResponseToByteBuffer(const RecvTensorResponse& proto,
                                          ::grpc::ByteBuffer* result) {
  ::grpc::Slice slice(proto.ByteSizeLong());
  proto.SerializeWithCachedSizesToArray(
      const_cast<uint8*>(reinterpret_cast<const uint8*>(slice.begin())));
  ::grpc::ByteBuffer tmp(&slice, 1);
  result->Swap(&tmp);
}

// We generate a RecvTensorResponse protocol buffer encoding into "*result",
// but where possible, we share the underlying Tensor buffer for "val", to
// avoid an extra copy.
//
// We hand-encode the protocol buffer data in the following order, as follows:
//
// Let R be a RecvTensorResponse object we want to encode, logically
// constructed by filling in data from "is_dead" and "val" and filling
// in a few other fields as well.
//
// (Letters here are used in the code to refer back to which part of the
//  encoding the code is generating).
//
// A:   <protocol buffer encoding of fields except R.tensor()>
// B1:  <tag encoding for RecvTensorResponse::tensor>
// B2:  <varint32 length of R.tensor() sub message>
// C:   <protocol buffer encoding of R.tensor() except for
//          R.tensor().tensor_content()>
// D1:  <tag encoding for TensorProto::tensor_content>
// D2:  <varint32 length of R.tensor().tensor_content() data>
// E:   <actual data for val's representation>
//
// If the tensor data is up to "kLargeTensorBytes", then A
// through E will all be encoded into "*result" in a single grpc::Slice.
//
// If the tensor data is larger than "kLargeTensorBytes", then A through
// D2 will be encoded in one grpc::Slice, and E will be encoded in a second
// grpc::Slice that points to the backing store for the tensor data, to avoid
// copying the tensor data (and the grpc::Slice setup will be arrange so as
// to dereference the underlying tensor data buffer when it is no longer
// needed in the "*result" ByteBuffer).
static int VarLengthEncodingSize(uint32 tag, size_t bytes) {
  return core::VarintLength(tag << 3) + core::VarintLength(bytes) + bytes;
}

// Returns an upper bound in bytes of the protocol buffer encoding of
// the "skeleton" of "val" (all the data needed for dtype and the shape,
// but not the actual contents of "val").
static int SkeletonEncodingSizeUpperBound(const Tensor& val) {
  static const int kVarintMax64 = 10;  // Max length of varint64 encoding
  const int ndims = val.shape().dims();
  return (2 * kVarintMax64) +           // dtype
         (ndims * (4 * kVarintMax64));  // Shape: 4 varints per dim
}

// Encode the skeleton for "val" (the encoded TensorProto contents
// (dtype and shape, but not the actual data) into "*e".  The backing
// store for "*e" must be of appropriate size to hold this encoding.
static void EncodeSkeleton(const Tensor& val, io::ProtoEncodeHelper* e) {
  // Encode val.dtype()
  e->WriteUint64(TensorProto::kDtypeFieldNumber, val.dtype());

  // Compute length of val.shape() proto encoding
  const int ndims = val.shape().dims();
  int tensor_shape_bytes = 0;
  for (int d = 0; d < ndims; d++) {
    int64 dim_size = val.shape().dim_size(d);
    tensor_shape_bytes +=
        2 +  // TensorShapeProto dim tag + varintlength of submessage
        1 +  // TensorShapeProto_Dim::kSizeFieldNumber
        core::VarintLength(dim_size);
  }

  if (tensor_shape_bytes > 0) {
    e->WriteVarlengthBeginning(TensorProto::kTensorShapeFieldNumber,
                               tensor_shape_bytes);
    // Encode val.shape()
    for (int d = 0; d < ndims; d++) {
      int64 dim_size = val.shape().dim_size(d);
      int64 dim_varlen = 1 +  // TensorShapeProto_Dim::kSizeFieldNumber
                         core::VarintLength(dim_size);
      e->WriteVarlengthBeginning(TensorShapeProto::kDimFieldNumber, dim_varlen);
      e->WriteUint64(TensorShapeProto_Dim::kSizeFieldNumber, dim_size);
    }
  }

#ifndef NDEBUG
  {
    // Debug-mode only check to make sure the encoding above is
    // identical to the auto-generated protocol buffer encoding.
    TensorProto skeleton;
    skeleton.set_dtype(val.dtype());
    val.shape().AsProto(skeleton.mutable_tensor_shape());
    string tensor_except_contents;  // tensor() field except contents
    skeleton.AppendToString(&tensor_except_contents);
    TensorProto skeleton2;
    skeleton2.ParseFromString(string(e->data(), e->size()));
    string out;
    skeleton.AppendToString(&out);
    DCHECK_EQ(tensor_except_contents, out) << skeleton.DebugString() << " vs\n"
                                           << skeleton2.DebugString();
  }
#endif
}

void EncodeTensorToByteBuffer(bool is_dead, const Tensor& val, bool require_ack,
                              ::grpc::ByteBuffer* result) {
  const int kLargeTensorBytes = 1024;
  const int64 kProtoBufLimitBytes = 1LL << 31;

  if (val.TotalBytes() > kProtoBufLimitBytes) {
    size_t exceeded_bytes = val.TotalBytes() - kProtoBufLimitBytes;
    LOG(FATAL) << "Cannot encode a Tensor that exceeds the 2GB protobuf limit. "
                  "Exceeded bytes: "
               << exceeded_bytes;
  }

  RecvTensorResponse response;
  if (is_dead) {
    response.set_is_dead(is_dead);
  }
  response.set_require_ack(require_ack);
  response.set_send_start_micros(Env::Default()->NowMicros());
  if (!DataTypeCanUseMemcpy(val.dtype())) {
    // Straightforward but slow path for complicated kinds of tensor data
    // TODO(jeff,sanjay): If this becomes an issue, we could
    // go directly from val -> ByteBuffer, with some effort.
    val.AsProtoTensorContent(response.mutable_tensor());

    // Encode full protocol buffer to a ByteBuffer
    EncodeRecvTensorResponseToByteBuffer(response, result);
  } else {
    // skeleton is the encoded TensorProto contents (dtype and shape), but
    // not the actual data
    gtl::InlinedVector<char, 128> skeleton(SkeletonEncodingSizeUpperBound(val));
    io::ProtoEncodeHelper e_skeleton(skeleton.data(), skeleton.size());
    EncodeSkeleton(val, &e_skeleton);

    StringPiece tdata = val.tensor_data();
    uint32 overall_tensor_proto_bytesize =
        (e_skeleton.size() +
         VarLengthEncodingSize(TensorProto::kTensorContentFieldNumber,
                               tdata.size()));
    string header;  // All of RecvTensorResponse except the tensor() field
    response.AppendToString(&header);

    size_t expected_size =
        (header.size() +
         VarLengthEncodingSize(RecvTensorResponse::kTensorFieldNumber,
                               overall_tensor_proto_bytesize));
    // If "share_tensor_slice_memory == false", we copy the tensor data to
    // the end of the buffer we are preparing that holds the rest of the
    // RecvTensorResponse protocol buffer.
    //
    // If "share_tensor_slice_memory == true", we arrange to share the
    // backing store of the data by creating a slice that also points to the
    // backing store, with appropriate reference counts to keep the
    // backing store alive as needed.
    //
    // We enable this behavior if the tensor is large.
    bool share_tensor_slice_memory = (tdata.size() > kLargeTensorBytes);

    // (Omitted internal-only conditional)

    size_t encoder_size = expected_size - tdata.size();

    // Encode all but the actual "tdata", but including the tag and
    // varlength header for the "tdata"
    gtl::InlinedVector<char, 1024> space(encoder_size);
    io::ProtoEncodeHelper e(space.data(), space.size());
    // (A)
    e.WriteRawBytes(header);

    // (B1) & (B2)
    e.WriteVarlengthBeginning(RecvTensorResponse::kTensorFieldNumber,
                              overall_tensor_proto_bytesize);
    // (C)
    e.WriteRawBytes(StringPiece(e_skeleton.data(), e_skeleton.size()));
    // (D1) & (D2)
    e.WriteVarlengthBeginning(TensorProto::kTensorContentFieldNumber,
                              tdata.size());

    // All but the tensor backing store are serialized now

    // Now allocate memory and put into the ByteBuffer
    ::grpc::Slice slices[2];
    int num_slices = 0;
    {
      size_t slice_len =
          e.size() + (share_tensor_slice_memory ? 0 : tdata.size());
      slices[0] = ::grpc::Slice(slice_len);
      memcpy(const_cast<uint8_t*>(slices[0].begin()), e.data(), e.size());
      if (!share_tensor_slice_memory) {
        // (E)
        memcpy(const_cast<uint8_t*>(slices[0].begin()) + e.size(), tdata.data(),
               tdata.size());
      }
      num_slices += 1;
    }

    if (share_tensor_slice_memory) {
      // (E) Encode tensor data, but by sharing backing store
      const TensorBuffer* buf = DMAHelper::buffer(&val);
      buf->Ref();
      slices[1] = ::grpc::Slice(
          const_cast<void*>(static_cast<const void*>(tdata.data())),
          tdata.size(),
          [](void* backing) { static_cast<TensorBuffer*>(backing)->Unref(); },
          const_cast<TensorBuffer*>(buf));
      num_slices += 1;
    }
    size_t total_bytes = 0;
    for (int i = 0; i < num_slices; i++) {
      total_bytes += slices[i].size();
    }
    CHECK_EQ(total_bytes, expected_size);

    ::grpc::ByteBuffer tmp(&slices[0], num_slices);
    result->Swap(&tmp);
  }
}

}  // namespace grpc
}  // namespace tensorflow
<commit_msg>Remove unused flag<commit_after>/* Copyright 2016 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/core/distributed_runtime/rpc/grpc_tensor_coding.h"

#include "grpcpp/support/byte_buffer.h"
#include "grpcpp/support/slice.h"
#include "tensorflow/core/common_runtime/dma_helper.h"
#include "tensorflow/core/framework/tensor.h"
#include "tensorflow/core/framework/tensor.pb.h"
#include "tensorflow/core/framework/tensor_reference.h"
#include "tensorflow/core/framework/tensor_shape.pb.h"
#include "tensorflow/core/lib/gtl/inlined_vector.h"
#include "tensorflow/core/lib/io/proto_encode_helper.h"
#include "tensorflow/core/platform/env.h"
#include "tensorflow/core/protobuf/worker.pb.h"

namespace tensorflow {
namespace grpc {

void EncodeRecvTensorResponseToByteBuffer(const RecvTensorResponse& proto,
                                          ::grpc::ByteBuffer* result) {
  ::grpc::Slice slice(proto.ByteSizeLong());
  proto.SerializeWithCachedSizesToArray(
      const_cast<uint8*>(reinterpret_cast<const uint8*>(slice.begin())));
  ::grpc::ByteBuffer tmp(&slice, 1);
  result->Swap(&tmp);
}

// We generate a RecvTensorResponse protocol buffer encoding into "*result",
// but where possible, we share the underlying Tensor buffer for "val", to
// avoid an extra copy.
//
// We hand-encode the protocol buffer data in the following order, as follows:
//
// Let R be a RecvTensorResponse object we want to encode, logically
// constructed by filling in data from "is_dead" and "val" and filling
// in a few other fields as well.
//
// (Letters here are used in the code to refer back to which part of the
//  encoding the code is generating).
//
// A:   <protocol buffer encoding of fields except R.tensor()>
// B1:  <tag encoding for RecvTensorResponse::tensor>
// B2:  <varint32 length of R.tensor() sub message>
// C:   <protocol buffer encoding of R.tensor() except for
//          R.tensor().tensor_content()>
// D1:  <tag encoding for TensorProto::tensor_content>
// D2:  <varint32 length of R.tensor().tensor_content() data>
// E:   <actual data for val's representation>
//
// If the tensor data is up to "kLargeTensorBytes", then A
// through E will all be encoded into "*result" in a single grpc::Slice.
//
// If the tensor data is larger than "kLargeTensorBytes", then A through
// D2 will be encoded in one grpc::Slice, and E will be encoded in a second
// grpc::Slice that points to the backing store for the tensor data, to avoid
// copying the tensor data (and the grpc::Slice setup will be arrange so as
// to dereference the underlying tensor data buffer when it is no longer
// needed in the "*result" ByteBuffer).
static int VarLengthEncodingSize(uint32 tag, size_t bytes) {
  return core::VarintLength(tag << 3) + core::VarintLength(bytes) + bytes;
}

// Returns an upper bound in bytes of the protocol buffer encoding of
// the "skeleton" of "val" (all the data needed for dtype and the shape,
// but not the actual contents of "val").
static int SkeletonEncodingSizeUpperBound(const Tensor& val) {
  static const int kVarintMax64 = 10;  // Max length of varint64 encoding
  const int ndims = val.shape().dims();
  return (2 * kVarintMax64) +           // dtype
         (ndims * (4 * kVarintMax64));  // Shape: 4 varints per dim
}

// Encode the skeleton for "val" (the encoded TensorProto contents
// (dtype and shape, but not the actual data) into "*e".  The backing
// store for "*e" must be of appropriate size to hold this encoding.
static void EncodeSkeleton(const Tensor& val, io::ProtoEncodeHelper* e) {
  // Encode val.dtype()
  e->WriteUint64(TensorProto::kDtypeFieldNumber, val.dtype());

  // Compute length of val.shape() proto encoding
  const int ndims = val.shape().dims();
  int tensor_shape_bytes = 0;
  for (int d = 0; d < ndims; d++) {
    int64 dim_size = val.shape().dim_size(d);
    tensor_shape_bytes +=
        2 +  // TensorShapeProto dim tag + varintlength of submessage
        1 +  // TensorShapeProto_Dim::kSizeFieldNumber
        core::VarintLength(dim_size);
  }

  if (tensor_shape_bytes > 0) {
    e->WriteVarlengthBeginning(TensorProto::kTensorShapeFieldNumber,
                               tensor_shape_bytes);
    // Encode val.shape()
    for (int d = 0; d < ndims; d++) {
      int64 dim_size = val.shape().dim_size(d);
      int64 dim_varlen = 1 +  // TensorShapeProto_Dim::kSizeFieldNumber
                         core::VarintLength(dim_size);
      e->WriteVarlengthBeginning(TensorShapeProto::kDimFieldNumber, dim_varlen);
      e->WriteUint64(TensorShapeProto_Dim::kSizeFieldNumber, dim_size);
    }
  }

#ifndef NDEBUG
  {
    // Debug-mode only check to make sure the encoding above is
    // identical to the auto-generated protocol buffer encoding.
    TensorProto skeleton;
    skeleton.set_dtype(val.dtype());
    val.shape().AsProto(skeleton.mutable_tensor_shape());
    string tensor_except_contents;  // tensor() field except contents
    skeleton.AppendToString(&tensor_except_contents);
    TensorProto skeleton2;
    skeleton2.ParseFromString(string(e->data(), e->size()));
    string out;
    skeleton.AppendToString(&out);
    DCHECK_EQ(tensor_except_contents, out) << skeleton.DebugString() << " vs\n"
                                           << skeleton2.DebugString();
  }
#endif
}

void EncodeTensorToByteBuffer(bool is_dead, const Tensor& val, bool require_ack,
                              ::grpc::ByteBuffer* result) {
  const int kLargeTensorBytes = 1024;
  const int64 kProtoBufLimitBytes = 1LL << 31;

  if (val.TotalBytes() > kProtoBufLimitBytes) {
    size_t exceeded_bytes = val.TotalBytes() - kProtoBufLimitBytes;
    LOG(FATAL) << "Cannot encode a Tensor that exceeds the 2GB protobuf limit. "
                  "Exceeded bytes: "
               << exceeded_bytes;
  }

  RecvTensorResponse response;
  if (is_dead) {
    response.set_is_dead(is_dead);
  }
  response.set_require_ack(require_ack);
  response.set_send_start_micros(Env::Default()->NowMicros());
  if (!DataTypeCanUseMemcpy(val.dtype())) {
    // Straightforward but slow path for complicated kinds of tensor data
    // TODO(jeff,sanjay): If this becomes an issue, we could
    // go directly from val -> ByteBuffer, with some effort.
    val.AsProtoTensorContent(response.mutable_tensor());

    // Encode full protocol buffer to a ByteBuffer
    EncodeRecvTensorResponseToByteBuffer(response, result);
  } else {
    // skeleton is the encoded TensorProto contents (dtype and shape), but
    // not the actual data
    gtl::InlinedVector<char, 128> skeleton(SkeletonEncodingSizeUpperBound(val));
    io::ProtoEncodeHelper e_skeleton(skeleton.data(), skeleton.size());
    EncodeSkeleton(val, &e_skeleton);

    StringPiece tdata = val.tensor_data();
    uint32 overall_tensor_proto_bytesize =
        (e_skeleton.size() +
         VarLengthEncodingSize(TensorProto::kTensorContentFieldNumber,
                               tdata.size()));
    string header;  // All of RecvTensorResponse except the tensor() field
    response.AppendToString(&header);

    size_t expected_size =
        (header.size() +
         VarLengthEncodingSize(RecvTensorResponse::kTensorFieldNumber,
                               overall_tensor_proto_bytesize));
    // If "share_tensor_slice_memory == false", we copy the tensor data to
    // the end of the buffer we are preparing that holds the rest of the
    // RecvTensorResponse protocol buffer.
    //
    // If "share_tensor_slice_memory == true", we arrange to share the
    // backing store of the data by creating a slice that also points to the
    // backing store, with appropriate reference counts to keep the
    // backing store alive as needed.
    //
    // We enable this behavior if the tensor is large.
    bool share_tensor_slice_memory = (tdata.size() > kLargeTensorBytes);

    size_t encoder_size = expected_size - tdata.size();

    // Encode all but the actual "tdata", but including the tag and
    // varlength header for the "tdata"
    gtl::InlinedVector<char, 1024> space(encoder_size);
    io::ProtoEncodeHelper e(space.data(), space.size());
    // (A)
    e.WriteRawBytes(header);

    // (B1) & (B2)
    e.WriteVarlengthBeginning(RecvTensorResponse::kTensorFieldNumber,
                              overall_tensor_proto_bytesize);
    // (C)
    e.WriteRawBytes(StringPiece(e_skeleton.data(), e_skeleton.size()));
    // (D1) & (D2)
    e.WriteVarlengthBeginning(TensorProto::kTensorContentFieldNumber,
                              tdata.size());

    // All but the tensor backing store are serialized now

    // Now allocate memory and put into the ByteBuffer
    ::grpc::Slice slices[2];
    int num_slices = 0;
    {
      size_t slice_len =
          e.size() + (share_tensor_slice_memory ? 0 : tdata.size());
      slices[0] = ::grpc::Slice(slice_len);
      memcpy(const_cast<uint8_t*>(slices[0].begin()), e.data(), e.size());
      if (!share_tensor_slice_memory) {
        // (E)
        memcpy(const_cast<uint8_t*>(slices[0].begin()) + e.size(), tdata.data(),
               tdata.size());
      }
      num_slices += 1;
    }

    if (share_tensor_slice_memory) {
      // (E) Encode tensor data, but by sharing backing store
      const TensorBuffer* buf = DMAHelper::buffer(&val);
      buf->Ref();
      slices[1] = ::grpc::Slice(
          const_cast<void*>(static_cast<const void*>(tdata.data())),
          tdata.size(),
          [](void* backing) { static_cast<TensorBuffer*>(backing)->Unref(); },
          const_cast<TensorBuffer*>(buf));
      num_slices += 1;
    }
    size_t total_bytes = 0;
    for (int i = 0; i < num_slices; i++) {
      total_bytes += slices[i].size();
    }
    CHECK_EQ(total_bytes, expected_size);

    ::grpc::ByteBuffer tmp(&slices[0], num_slices);
    result->Swap(&tmp);
  }
}

}  // namespace grpc
}  // namespace tensorflow
<|endoftext|>