<commit_before>/**********************************************************************
 * $Id$
 *
 * GEOS - Geometry Engine Open Source
 * http://geos.refractions.net
 *
 * Copyright (C) 2001-2002 Vivid Solutions Inc.
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Public Licence as published
 * by the Free Software Foundation.
 * See the COPYING file for more information.
 *
 **********************************************************************/

#include <geos/indexStrtree.h>
#include <geos/util.h>
#include <geos/profiler.h>

namespace geos {

static bool xComparator(Boundable *a, Boundable *b){
	return AbstractSTRtree::compareDoubles(STRtree::centreX((Envelope*)a->getBounds()), STRtree::centreX((Envelope*)b->getBounds()));
}

static bool yComparator(Boundable *a, Boundable *b){
	return AbstractSTRtree::compareDoubles(STRtree::centreY((Envelope*)a->getBounds()), STRtree::centreY((Envelope*)b->getBounds()));
}

/**
 * Constructs an STRtree with the default node capacity.
 */
STRtree::STRtree():
	AbstractSTRtree(10)
{
	//intersectsOp(new STRIntersectsOp())
}

/**
 * Constructs an STRtree with the given maximum number of child nodes that
 * a node may have
 */
STRtree::STRtree(int nodeCapacity):
	AbstractSTRtree(nodeCapacity)
{
	//intersectsOp(new STRIntersectsOp())
}

STRtree::~STRtree()
{
	//delete intersectsOp;
}

double STRtree::centreX(Envelope *e) {
	return STRtree::avg(e->getMinX(),e->getMaxX());
}

double STRtree::avg(double a, double b) {
	return (a + b) / 2.0;
}

double STRtree::centreY(Envelope *e) {
	return STRtree::avg(e->getMinY(), e->getMaxY());
}

bool
STRtree::STRIntersectsOp::intersects(const void* aBounds, const void* bBounds)
{
	return ((Envelope*)aBounds)->intersects((Envelope*)bBounds);
}

/**
 * Creates the parent level for the given child level. First, orders the items
 * by the x-values of the midpoints, and groups them into vertical slices.
 * For each slice, orders the items by the y-values of the midpoints, and
 * group them into runs of size M (the node capacity). For each run, creates
 * a new (parent) node.
 */
vector<Boundable*>*
STRtree::createParentBoundables(vector<Boundable*> *childBoundables, int newLevel)
{
	Assert::isTrue(!childBoundables->empty());
	int minLeafCount=(int) ceil((double)childBoundables->size()/(double)getNodeCapacity());

	vector<Boundable*> *sortedChildBoundables=sortBoundables(childBoundables);
	vector<vector<Boundable*>*>* verticalSlicesV = verticalSlices(sortedChildBoundables,(int)ceil(sqrt((double)minLeafCount)));
	delete sortedChildBoundables;
	vector<Boundable*> *ret;
	ret = createParentBoundablesFromVerticalSlices(verticalSlicesV, newLevel);
	for (unsigned int i=0; i<verticalSlicesV->size(); i++)
	{
		vector<Boundable *>*inner = (*verticalSlicesV)[i];
		//for (unsigned int j=0; j<inner->size(); j++)
		//{
			// some of these might be provided,
			// some of these might be created
			//delete (*inner)[j];
		//}
		delete inner;
	}
	delete verticalSlicesV;
	return ret;
}

vector<Boundable*>*
STRtree::createParentBoundablesFromVerticalSlices(vector<vector<Boundable*>*> *verticalSlices, int newLevel)
{
	Assert::isTrue(verticalSlices->size()>0);
	vector<Boundable*> *parentBoundables=new vector<Boundable*>();
	for (unsigned int i = 0; i <verticalSlices->size(); i++) {
		vector<Boundable*> *toAdd=createParentBoundablesFromVerticalSlice((*verticalSlices)[i], newLevel);
		parentBoundables->insert(parentBoundables->end(),toAdd->begin(),toAdd->end());
		delete toAdd;
	}
	return parentBoundables;
}

vector<Boundable*>*
STRtree::createParentBoundablesFromVerticalSlice(vector<Boundable*> *childBoundables, int newLevel)
{
	return AbstractSTRtree::createParentBoundables(childBoundables, newLevel);
}

/**
 * @param childBoundables Must be sorted by the x-value of
 *        the envelope midpoints
 * @return
 */
vector<vector<Boundable*>*>*
STRtree::verticalSlices(vector<Boundable*>* childBoundables, int sliceCount)
{
	int sliceCapacity = (int) ceil((double)childBoundables->size() / (double) sliceCount);
	vector<vector<Boundable*>*>* slices = new vector<vector<Boundable*>*>(sliceCount);
	unsigned int i=0;
	for (int j=0; j<sliceCount; j++) {
		(*slices)[j]=new vector<Boundable*>();
		int boundablesAddedToSlice = 0;
		while (i<childBoundables->size() && boundablesAddedToSlice < sliceCapacity)
		{
			Boundable *childBoundable=(*childBoundables)[i];
			i++;
			(*slices)[j]->push_back(childBoundable);
			boundablesAddedToSlice++;
		}
	}
	return slices;
}

STRAbstractNode::STRAbstractNode(int level):AbstractNode(level)
{
}

STRAbstractNode::~STRAbstractNode()
{
	delete (Envelope *)bounds;
}

void *
STRAbstractNode::computeBounds()
{
	Envelope* bounds=NULL;
	vector<Boundable*> *b=getChildBoundables();
	for(unsigned int i=0;i<b->size();i++) {
		Boundable* childBoundable=(*b)[i];
		if (bounds==NULL) {
			bounds=new Envelope(*(Envelope*)childBoundable->getBounds());
		} else {
			bounds->expandToInclude((Envelope*)childBoundable->getBounds());
		}
	}
	return bounds;
}

AbstractNode*
STRtree::createNode(int level)
{
	AbstractNode *an = new STRAbstractNode(level);
	nodes->push_back(an);
	return an;
}

void
STRtree::insert(const Envelope *itemEnv, void* item)
{
	if (itemEnv->isNull()) { return; }
	AbstractSTRtree::insert(itemEnv, item);
}

vector<void*>*
STRtree::query(const Envelope *searchEnv)
{
	vector<void *> *ret = AbstractSTRtree::query(searchEnv);
	return ret;
}

vector<Boundable*> *
STRtree::sortBoundables(const vector<Boundable*> *input)
{
	vector<Boundable*> *output=new vector<Boundable*>(*input);
	sort(output->begin(),output->end(),yComparator);
	return output;
}

} // namespace geos

/**********************************************************************
 * $Log$
 * Revision 1.16  2004/11/08 15:58:13  strk
 * More performance tuning.
 *
 * Revision 1.15  2004/11/04 19:08:07  strk
 * Cleanups, initializers list, profiling.
 *
 * Revision 1.14  2004/11/01 16:43:04  strk
 * Added Profiler code.
 * Temporarly patched a bug in DoubleBits (must check drawbacks).
 * Various cleanups and speedups.
 *
 * Revision 1.13  2004/07/27 16:35:46  strk
 * Geometry::getEnvelopeInternal() changed to return a const Envelope *.
 * This should reduce object copies as once computed the envelope of a
 * geometry remains the same.
 *
 * Revision 1.12  2004/07/13 08:33:53  strk
 * Added missing virtual destructor to virtual classes.
 * Fixed implicit unsigned int -> int casts
 *
 * Revision 1.11  2004/07/02 13:28:27  strk
 * Fixed all #include lines to reflect headers layout change.
 * Added client application build tips in README.
 *
 * Revision 1.10  2004/05/06 15:00:59  strk
 * Boundable destructor made virtual.
 * Added vector <AbstractNode *> *nodes member in AbstractSTRTree,
 * used to keep track of created node to cleanly delete them at
 * destruction time.
 *
 * Revision 1.9  2004/05/06 13:58:30  strk
 * leak removed from createParentBoundablesFromVerticalSlices
 *
 * Revision 1.8  2004/05/05 17:42:06  strk
 * AbstractNode destructor made virtual. AbstractNode::bounds made protected.
 * SIRAbstractNode and STRAbstractNode destructors added to get rid of
 * AbstractNode::bounds in the right way (is a void * casted to appropriate
 * Class in the subClasses).
 *
 * Revision 1.7  2004/05/03 17:15:38  strk
 * leaks on exception fixed.
 *
 * Revision 1.6  2004/05/03 16:29:21  strk
 * Added sortBoundables(const vector<Boundable *>) pure virtual in AbstractSTRtree,
 * implemented in SIRtree and STRtree. Comparator funx made static in STRtree.cpp
 * and SIRtree.cpp.
 *
 * Revision 1.5  2004/04/26 12:37:19  strk
 * Some leaks fixed.
 *
 * Revision 1.4  2004/04/05 06:35:14  ybychkov
 * "operation/distance" upgraded to JTS 1.4
 *
 * Revision 1.3  2004/03/25 02:23:55  ybychkov
 * All "index/*" packages upgraded to JTS 1.4
 *
 * Revision 1.2  2003/11/07 01:23:42  pramsey
 * Add standard CVS headers licence notices and copyrights to all cpp and h
 * files.
 *
 *
 **********************************************************************/

<commit_msg>Just another small improvement.<commit_after>/**********************************************************************
 * $Id$
 *
 * GEOS - Geometry Engine Open Source
 * http://geos.refractions.net
 *
 * Copyright (C) 2001-2002 Vivid Solutions Inc.
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Public Licence as published
 * by the Free Software Foundation.
 * See the COPYING file for more information.
 *
 **********************************************************************/

#include <geos/indexStrtree.h>
#include <geos/util.h>
#include <geos/profiler.h>

namespace geos {

static bool xComparator(Boundable *a, Boundable *b){
	return AbstractSTRtree::compareDoubles(STRtree::centreX((Envelope*)a->getBounds()), STRtree::centreX((Envelope*)b->getBounds()));
}

static bool yComparator(Boundable *a, Boundable *b){
	return AbstractSTRtree::compareDoubles(STRtree::centreY((Envelope*)a->getBounds()), STRtree::centreY((Envelope*)b->getBounds()));
}

/**
 * Constructs an STRtree with the default node capacity.
 */
STRtree::STRtree():
	AbstractSTRtree(10)
{
	//intersectsOp(new STRIntersectsOp())
}

/**
 * Constructs an STRtree with the given maximum number of child nodes that
 * a node may have
 */
STRtree::STRtree(int nodeCapacity):
	AbstractSTRtree(nodeCapacity)
{
	//intersectsOp(new STRIntersectsOp())
}

STRtree::~STRtree()
{
	//delete intersectsOp;
}

double STRtree::centreX(Envelope *e) {
	return STRtree::avg(e->getMinX(),e->getMaxX());
}

double STRtree::avg(double a, double b) {
	return (a + b) / 2.0;
}

double STRtree::centreY(Envelope *e) {
	return STRtree::avg(e->getMinY(), e->getMaxY());
}

bool
STRtree::STRIntersectsOp::intersects(const void* aBounds, const void* bBounds)
{
	return ((Envelope*)aBounds)->intersects((Envelope*)bBounds);
}

/**
 * Creates the parent level for the given child level. First, orders the items
 * by the x-values of the midpoints, and groups them into vertical slices.
 * For each slice, orders the items by the y-values of the midpoints, and
 * group them into runs of size M (the node capacity). For each run, creates
 * a new (parent) node.
 */
vector<Boundable*>*
STRtree::createParentBoundables(vector<Boundable*> *childBoundables, int newLevel)
{
	Assert::isTrue(!childBoundables->empty());
	int minLeafCount=(int) ceil((double)childBoundables->size()/(double)getNodeCapacity());

	vector<Boundable*> *sortedChildBoundables=sortBoundables(childBoundables);
	vector<vector<Boundable*>*>* verticalSlicesV = verticalSlices(sortedChildBoundables,(int)ceil(sqrt((double)minLeafCount)));
	delete sortedChildBoundables;
	vector<Boundable*> *ret;
	ret = createParentBoundablesFromVerticalSlices(verticalSlicesV, newLevel);
	for (unsigned int i=0; i<verticalSlicesV->size(); i++)
	{
		vector<Boundable *>*inner = (*verticalSlicesV)[i];
		//for (unsigned int j=0; j<inner->size(); j++)
		//{
			// some of these might be provided,
			// some of these might be created
			//delete (*inner)[j];
		//}
		delete inner;
	}
	delete verticalSlicesV;
	return ret;
}

vector<Boundable*>*
STRtree::createParentBoundablesFromVerticalSlices(vector<vector<Boundable*>*> *verticalSlices, int newLevel)
{
	Assert::isTrue(verticalSlices->size()>0);
	vector<Boundable*> *parentBoundables=new vector<Boundable*>();
	for (unsigned int i = 0; i <verticalSlices->size(); i++) {
		vector<Boundable*> *toAdd=createParentBoundablesFromVerticalSlice((*verticalSlices)[i], newLevel);
		parentBoundables->insert(parentBoundables->end(),toAdd->begin(),toAdd->end());
		delete toAdd;
	}
	return parentBoundables;
}

vector<Boundable*>*
STRtree::createParentBoundablesFromVerticalSlice(vector<Boundable*> *childBoundables, int newLevel)
{
	return AbstractSTRtree::createParentBoundables(childBoundables, newLevel);
}

/**
 * @param childBoundables Must be sorted by the x-value of
 *        the envelope midpoints
 * @return
 */
vector<vector<Boundable*>*>*
STRtree::verticalSlices(vector<Boundable*>* childBoundables, int sliceCount)
{
	int sliceCapacity = (int) ceil((double)childBoundables->size() / (double) sliceCount);
	vector<vector<Boundable*>*>* slices = new vector<vector<Boundable*>*>(sliceCount);
	unsigned int i=0;
	for (int j=0; j<sliceCount; j++) {
		(*slices)[j]=new vector<Boundable*>();
		int boundablesAddedToSlice = 0;
		while (i<childBoundables->size() && boundablesAddedToSlice < sliceCapacity)
		{
			Boundable *childBoundable=(*childBoundables)[i];
			i++;
			(*slices)[j]->push_back(childBoundable);
			boundablesAddedToSlice++;
		}
	}
	return slices;
}

STRAbstractNode::STRAbstractNode(int level):AbstractNode(level)
{
}

STRAbstractNode::~STRAbstractNode()
{
	delete (Envelope *)bounds;
}

void *
STRAbstractNode::computeBounds()
{
	Envelope* bounds=NULL;
	vector<Boundable*> *b=getChildBoundables();
	unsigned int bsize=b->size();
	if ( bsize ) bounds=new Envelope(*(Envelope*)(*b)[0]->getBounds());
	for(unsigned int i=1; i<bsize; i++) {
		Boundable* childBoundable=(*b)[i];
		bounds->expandToInclude((Envelope*)childBoundable->getBounds());
	}
	return bounds;
}

AbstractNode*
STRtree::createNode(int level)
{
	AbstractNode *an = new STRAbstractNode(level);
	nodes->push_back(an);
	return an;
}

void
STRtree::insert(const Envelope *itemEnv, void* item)
{
	if (itemEnv->isNull()) { return; }
	AbstractSTRtree::insert(itemEnv, item);
}

vector<void*>*
STRtree::query(const Envelope *searchEnv)
{
	vector<void *> *ret = AbstractSTRtree::query(searchEnv);
	return ret;
}

vector<Boundable*> *
STRtree::sortBoundables(const vector<Boundable*> *input)
{
	vector<Boundable*> *output=new vector<Boundable*>(*input);
	sort(output->begin(),output->end(),yComparator);
	return output;
}

} // namespace geos

/**********************************************************************
 * $Log$
 * Revision 1.17  2004/11/08 18:33:47  strk
 * Just another small improvement.
 *
 * Revision 1.16  2004/11/08 15:58:13  strk
 * More performance tuning.
 *
 * Revision 1.15  2004/11/04 19:08:07  strk
 * Cleanups, initializers list, profiling.
 *
 * Revision 1.14  2004/11/01 16:43:04  strk
 * Added Profiler code.
 * Temporarly patched a bug in DoubleBits (must check drawbacks).
 * Various cleanups and speedups.
 *
 * Revision 1.13  2004/07/27 16:35:46  strk
 * Geometry::getEnvelopeInternal() changed to return a const Envelope *.
 * This should reduce object copies as once computed the envelope of a
 * geometry remains the same.
 *
 * Revision 1.12  2004/07/13 08:33:53  strk
 * Added missing virtual destructor to virtual classes.
 * Fixed implicit unsigned int -> int casts
 *
 * Revision 1.11  2004/07/02 13:28:27  strk
 * Fixed all #include lines to reflect headers layout change.
 * Added client application build tips in README.
 *
 * Revision 1.10  2004/05/06 15:00:59  strk
 * Boundable destructor made virtual.
 * Added vector <AbstractNode *> *nodes member in AbstractSTRTree,
 * used to keep track of created node to cleanly delete them at
 * destruction time.
 *
 * Revision 1.9  2004/05/06 13:58:30  strk
 * leak removed from createParentBoundablesFromVerticalSlices
 *
 * Revision 1.8  2004/05/05 17:42:06  strk
 * AbstractNode destructor made virtual. AbstractNode::bounds made protected.
 * SIRAbstractNode and STRAbstractNode destructors added to get rid of
 * AbstractNode::bounds in the right way (is a void * casted to appropriate
 * Class in the subClasses).
 *
 * Revision 1.7  2004/05/03 17:15:38  strk
 * leaks on exception fixed.
 *
 * Revision 1.6  2004/05/03 16:29:21  strk
 * Added sortBoundables(const vector<Boundable *>) pure virtual in AbstractSTRtree,
 * implemented in SIRtree and STRtree. Comparator funx made static in STRtree.cpp
 * and SIRtree.cpp.
 *
 * Revision 1.5  2004/04/26 12:37:19  strk
 * Some leaks fixed.
 *
 * Revision 1.4  2004/04/05 06:35:14  ybychkov
 * "operation/distance" upgraded to JTS 1.4
 *
 * Revision 1.3  2004/03/25 02:23:55  ybychkov
 * All "index/*" packages upgraded to JTS 1.4
 *
 * Revision 1.2  2003/11/07 01:23:42  pramsey
 * Add standard CVS headers licence notices and copyrights to all cpp and h
 * files.
 *
 *
 **********************************************************************/

<|endoftext|>


<commit_before><commit_msg>INTEGRATION: CWS residcleanup (1.24.22); FILE MERGED 2007/02/18 19:21:41 pl 1.24.22.1: #i74635# get rid of implicit global ResMgr<commit_after><|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: htmlex.hxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: rt $ $Date: 2004-08-23 08:13:35 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _SD_HTMLEX_HXX
#define _SD_HTMLEX_HXX

#ifndef _COM_SUN_STAR_BEANS_PROPERTYVALUE_HPP_
#include <com/sun/star/beans/PropertyValue.hpp>
#endif

#ifndef _XPOLY_HXX
#include <svx/xpoly.hxx>
#endif
#ifndef _SV_GDIMTF_HXX //autogen
#include <vcl/gdimtf.hxx>
#endif
#ifndef _SFXITEMSET_HXX //autogen
#include <svtools/itemset.hxx>
#endif
#ifndef _SD_RESLTN_HXX
#include "resltn.hxx"       // enum PublishingResolution
#endif
#ifndef _SV_COLRDLG_HXX
#include <svtools/colrdlg.hxx>
#endif
#ifndef _EHDL_HXX //autogen
#include <svtools/ehdl.hxx>
#endif

#include "strings.hrc"

#ifndef SD_DRAW_DOC_SHELL_HXX
#include "DrawDocShell.hxx"
#endif

#ifndef SD_WINDOW_HXX
#include "Window.hxx"
#endif

#ifndef SD_VIEW_SHELL_HXX
#include "ViewShell.hxx"
#endif

#ifndef INC_ASSCLASS
#include "assclass.hxx"
#endif

#ifndef _SD_RESID_HXX
#include "sdresid.hxx"
#endif

#ifndef _SD_PUBDLG_HXX
#include "pubdlg.hxx"
#endif

#define NUM_BUTTONS 12

#define PUB_LOWRES_WIDTH    640
#define PUB_LOWRES_HEIGHT   480
#define PUB_MEDRES_WIDTH    800
#define PUB_MEDRES_HEIGHT   600
#define PUB_HIGHRES_WIDTH   1024
#define PUB_HIGHRES_HEIGHT  768

#define HtmlButtonThemaStr = "private://gallery/hidden/HtmlExportButtons";

class List;
class SfxProgress;
class SdrOutliner;
class SdPage;
class HtmlState;
class SdrTextObj;
class SdrPage;
class SdDrawDocument;

namespace sd {
class View;
}

class HtmlErrorContext : public ErrorContext
{
private:
    USHORT  m_nResId;
    String  m_aURL1;
    String  m_aURL2;

public:
                    HtmlErrorContext(Window *pWin=0);
                    ~HtmlErrorContext() {};

    virtual BOOL    GetString( ULONG nErrId, String& rCtxStr );

    void            SetContext( USHORT nResId );
    void            SetContext( USHORT nResId, const String& rURL );
    void            SetContext( USHORT nResId, const String& rURL1, const String& rURL2 );
};

// =====================================================================
// this class exports an Impress Document as a HTML Presentation
// =====================================================================
class HtmlExport
{
    String m_aPath;

    SdDrawDocument* pDoc;
    ::sd::DrawDocShell* pDocSh;

    HtmlErrorContext m_eEC;

    HtmlPublishMode m_eMode;
    SfxProgress* mpProgress;
    bool m_bImpress;
    USHORT m_nSdPageCount;
    USHORT m_nPagesWritten;
    bool m_bContentsPage;
    INT16 m_nButtonThema;
    UINT16 m_nWidthPixel;
    UINT16 m_nHeightPixel;
    PublishingFormat m_eFormat;
    bool m_bHeader;
    bool m_bNotes;
    bool m_bFrames;
    bool m_bKiosk;
//-/    bool m_bCreated;
    String m_aIndex;
    String m_aEMail;
    String m_aAuthor;
    String m_aHomePage;
    String m_aInfo;
    INT16 m_nCompression;
    String m_aDocFileName;
    String m_aFramePage;
    String m_DocTitle;
    bool m_bDownload;

    bool m_bAutoSlide;
    UINT32  m_nSlideDuration;
    bool m_bSlideSound;
    bool m_bEndless;

    bool m_bUserAttr;           // die folgenden Farben werden fuer das <body>
    Color m_aTextColor;         // tag genutzt, wenn m_bUserAttr true ist
    Color m_aBackColor;
    Color m_aLinkColor;
    Color m_aVLinkColor;
    Color m_aALinkColor;
    Color m_aFirstPageColor;
    bool m_bDocColors;

    String   m_aHTMLExtension;
    String** m_pHTMLFiles;
    String** m_pImageFiles;
    String** m_pPageNames;
    String** m_pTextFiles;

    String m_aExportPath;           // Das Ausgabeverzeichnes bzw. die URL
    String m_aIndexUrl;
    String m_aURLPath;
    String m_aCGIPath;
    PublishingScript m_eScript;

    SdrTextObj* GetLayoutTextObject(SdrPage* pPage);

    void SetDocColors( SdPage* pPage = NULL );

    bool    CreateImagesForPresPages();
    bool    CreateHtmlTextForPresPages();
    bool    CreateHtmlForPresPages();
    bool    CreateContentPage();
    void    CreateFileNames();
    bool    CreateBitmaps();
    bool    CreateOutlinePages();
    bool    CreateFrames();
    bool    CreateNotesPages();
    bool    CreateNavBarFrames();

    bool    CreateASPScripts();
    bool    CreatePERLScripts();
    bool    CreateImageFileList();
    bool    CreateImageNumberFile();

    ULONG   CreateBitmap( ULONG nThemeId, INT16 nImage, const String& aName ) const;
    void    SmoothBitmap( BitmapEx& aBmp, Color aBackCol ) const;
    String getDocumentTitle();
    bool    SavePresentation();

    String  CreateLink( const String& aLink, const String& aText,
                        const String& aTarget = String()) const;
    String  CreateImage( const String& aImage, const String& aAltText, INT16 nWidth = -1, INT16 nHeight = -1 ) const;
    String  CreateNavBar( USHORT nSdPage, bool bIsText ) const;
    String  CreateBodyTag() const;

    String  ParagraphToHTMLString( SdrOutliner* pOutliner, ULONG nPara, const Color& rBackgroundColor );
    String  TextAttribToHTMLString( SfxItemSet* pSet, HtmlState* pState, const Color& rBackgroundColor );

    String  CreateTextForTitle( SdrOutliner* pOutliner, SdPage* pPage, const Color& rBackgroundColor );
    String  CreateTextForPage( SdrOutliner* pOutliner, SdPage* pPage, bool bHeadLine, const Color& rBackgroundColor );
    String  CreateTextForNotesPage( SdrOutliner* pOutliner, SdPage* pPage, bool bHeadLine, const Color& rBackgroundColor );

    String  CreateHTMLCircleArea( ULONG nRadius, ULONG nCenterX,
                                  ULONG nCenterY, const String& rHRef ) const;
    String  CreateHTMLPolygonArea( const XPolyPolygon& rXPolyPoly,
                                   Size aShift, double fFactor,
                                   const String& rHRef ) const;
    String  CreateHTMLRectArea( const Rectangle& rRect,
                                const String& rHRef ) const;

    String  CreatePageURL( USHORT nPgNum );

    String InsertSound( const String& rSoundFile );
    bool CopyFile( const String& rSourceFile, const String& rDestPath );
    bool CopyScript( const String& rPath, const String& rSource, const String& rDest, bool bUnix = false );

    void InitProgress( USHORT nProgrCount );
    void ResetProgress();

    String WriteMetaCharset() const;

    void InitExportParameters( const com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >& rParams);
    void ExportHtml();
    void ExportKiosk();
    void ExportWebCast();

    List aSpecialObjects;
    void HideSpecialObjects( SdPage* pPage );
    void ShowSpecialObjects();

    bool WriteHtml( const String& rFileName, bool bAddExtension, const String& rHtmlData );
    String GetButtonName( USHORT nButton ) const;

 public:
     HtmlExport( rtl::OUString aPath, const com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >& rParams, SdDrawDocument* pExpDoc, ::sd::DrawDocShell* pDocShell );
    virtual ~HtmlExport();

    static String   ColorToHTMLString( Color aColor );
    static String   StringToHTMLString( const String& rString );
    static String   StringToURL( const String& rURL );
};

#endif // _SD_HTMLEX_HXX
<commit_msg>INTEGRATION: CWS impress30 (1.7.146); FILE MERGED 2005/01/20 13:44:51 cl 1.7.146.1: #b4752338# give warning when overwriting files<commit_after>/*************************************************************************
 *
 *  $RCSfile: htmlex.hxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: rt $ $Date: 2005-01-28 15:38:49 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _SD_HTMLEX_HXX
#define _SD_HTMLEX_HXX

#ifndef _COM_SUN_STAR_BEANS_PROPERTYVALUE_HPP_
#include <com/sun/star/beans/PropertyValue.hpp>
#endif
#ifndef _COM_SUN_STAR_UCB_XSIMPLEFILEACCESS_HPP_
#include <com/sun/star/ucb/XSimpleFileAccess.hpp>
#endif

#ifndef _XPOLY_HXX
#include <svx/xpoly.hxx>
#endif
#ifndef _SV_GDIMTF_HXX //autogen
#include <vcl/gdimtf.hxx>
#endif
#ifndef _SFXITEMSET_HXX //autogen
#include <svtools/itemset.hxx>
#endif
#ifndef _SD_RESLTN_HXX
#include "resltn.hxx"       // enum PublishingResolution
#endif
#ifndef _SV_COLRDLG_HXX
#include <svtools/colrdlg.hxx>
#endif
#ifndef _EHDL_HXX //autogen
#include <svtools/ehdl.hxx>
#endif

#include "strings.hrc"

#ifndef SD_DRAW_DOC_SHELL_HXX
#include "DrawDocShell.hxx"
#endif

#ifndef SD_WINDOW_HXX
#include "Window.hxx"
#endif

#ifndef SD_VIEW_SHELL_HXX
#include "ViewShell.hxx"
#endif

#ifndef INC_ASSCLASS
#include "assclass.hxx"
#endif

#ifndef _SD_RESID_HXX
#include "sdresid.hxx"
#endif

#ifndef _SD_PUBDLG_HXX
#include "pubdlg.hxx"
#endif

#define NUM_BUTTONS 12

#define PUB_LOWRES_WIDTH    640
#define PUB_LOWRES_HEIGHT   480
#define PUB_MEDRES_WIDTH    800
#define PUB_MEDRES_HEIGHT   600
#define PUB_HIGHRES_WIDTH   1024
#define PUB_HIGHRES_HEIGHT  768

#define HtmlButtonThemaStr = "private://gallery/hidden/HtmlExportButtons";

class List;
class SfxProgress;
class SdrOutliner;
class SdPage;
class HtmlState;
class SdrTextObj;
class SdrPage;
class SdDrawDocument;

namespace sd {
class View;
}

class HtmlErrorContext : public ErrorContext
{
private:
    USHORT  m_nResId;
    String  m_aURL1;
    String  m_aURL2;

public:
                    HtmlErrorContext(Window *pWin=0);
                    ~HtmlErrorContext() {};

    virtual BOOL    GetString( ULONG nErrId, String& rCtxStr );

    void            SetContext( USHORT nResId );
    void            SetContext( USHORT nResId, const String& rURL );
    void            SetContext( USHORT nResId, const String& rURL1, const String& rURL2 );
};

// =====================================================================
// this class exports an Impress Document as a HTML Presentation
// =====================================================================
class HtmlExport
{
    String m_aPath;

    SdDrawDocument* pDoc;
    ::sd::DrawDocShell* pDocSh;

    HtmlErrorContext m_eEC;

    HtmlPublishMode m_eMode;
    SfxProgress* mpProgress;
    bool m_bImpress;
    USHORT m_nSdPageCount;
    USHORT m_nPagesWritten;
    bool m_bContentsPage;
    INT16 m_nButtonThema;
    UINT16 m_nWidthPixel;
    UINT16 m_nHeightPixel;
    PublishingFormat m_eFormat;
    bool m_bHeader;
    bool m_bNotes;
    bool m_bFrames;
    bool m_bKiosk;
//-/    bool m_bCreated;
    String m_aIndex;
    String m_aEMail;
    String m_aAuthor;
    String m_aHomePage;
    String m_aInfo;
    INT16 m_nCompression;
    String m_aDocFileName;
    String m_aFramePage;
    String m_DocTitle;
    bool m_bDownload;

    bool m_bAutoSlide;
    UINT32  m_nSlideDuration;
    bool m_bSlideSound;
    bool m_bEndless;

    bool m_bUserAttr;           // die folgenden Farben werden fuer das <body>
    Color m_aTextColor;         // tag genutzt, wenn m_bUserAttr true ist
    Color m_aBackColor;
    Color m_aLinkColor;
    Color m_aVLinkColor;
    Color m_aALinkColor;
    Color m_aFirstPageColor;
    bool m_bDocColors;

    String   m_aHTMLExtension;
    String** m_pHTMLFiles;
    String** m_pImageFiles;
    String** m_pPageNames;
    String** m_pTextFiles;

    String m_aExportPath;           // Das Ausgabeverzeichnes bzw. die URL
    String m_aIndexUrl;
    String m_aURLPath;
    String m_aCGIPath;
    PublishingScript m_eScript;

    SdrTextObj* GetLayoutTextObject(SdrPage* pPage);

    void SetDocColors( SdPage* pPage = NULL );

    bool    CreateImagesForPresPages();
    bool    CreateHtmlTextForPresPages();
    bool    CreateHtmlForPresPages();
    bool    CreateContentPage();
    void    CreateFileNames();
    bool    CreateBitmaps();
    bool    CreateOutlinePages();
    bool    CreateFrames();
    bool    CreateNotesPages();
    bool    CreateNavBarFrames();

    bool    CreateASPScripts();
    bool    CreatePERLScripts();
    bool    CreateImageFileList();
    bool    CreateImageNumberFile();

    bool    checkForExistingFiles();
    bool    checkFileExists( ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XSimpleFileAccess >& xFileAccess, String const & aFileName );

    ULONG   CreateBitmap( ULONG nThemeId, INT16 nImage, const String& aName ) const;
    void    SmoothBitmap( BitmapEx& aBmp, Color aBackCol ) const;
    String getDocumentTitle();
    bool    SavePresentation();

    String  CreateLink( const String& aLink, const String& aText,
                        const String& aTarget = String()) const;
    String  CreateImage( const String& aImage, const String& aAltText, INT16 nWidth = -1, INT16 nHeight = -1 ) const;
    String  CreateNavBar( USHORT nSdPage, bool bIsText ) const;
    String  CreateBodyTag() const;

    String  ParagraphToHTMLString( SdrOutliner* pOutliner, ULONG nPara, const Color& rBackgroundColor );
    String  TextAttribToHTMLString( SfxItemSet* pSet, HtmlState* pState, const Color& rBackgroundColor );

    String  CreateTextForTitle( SdrOutliner* pOutliner, SdPage* pPage, const Color& rBackgroundColor );
    String  CreateTextForPage( SdrOutliner* pOutliner, SdPage* pPage, bool bHeadLine, const Color& rBackgroundColor );
    String  CreateTextForNotesPage( SdrOutliner* pOutliner, SdPage* pPage, bool bHeadLine, const Color& rBackgroundColor );

    String  CreateHTMLCircleArea( ULONG nRadius, ULONG nCenterX,
                                  ULONG nCenterY, const String& rHRef ) const;
    String  CreateHTMLPolygonArea( const XPolyPolygon& rXPolyPoly,
                                   Size aShift, double fFactor,
                                   const String& rHRef ) const;
    String  CreateHTMLRectArea( const Rectangle& rRect,
                                const String& rHRef ) const;

    String  CreatePageURL( USHORT nPgNum );

    String InsertSound( const String& rSoundFile );
    bool CopyFile( const String& rSourceFile, const String& rDestPath );
    bool CopyScript( const String& rPath, const String& rSource, const String& rDest, bool bUnix = false );

    void InitProgress( USHORT nProgrCount );
    void ResetProgress();

    String WriteMetaCharset() const;

    void InitExportParameters( const com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >& rParams);
    void ExportHtml();
    void ExportKiosk();
    void ExportWebCast();

    List aSpecialObjects;
    void HideSpecialObjects( SdPage* pPage );
    void ShowSpecialObjects();

    bool WriteHtml( const String& rFileName, bool bAddExtension, const String& rHtmlData );
    String GetButtonName( USHORT nButton ) const;

 public:
     HtmlExport( rtl::OUString aPath, const com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >& rParams, SdDrawDocument* pExpDoc, ::sd::DrawDocShell* pDocShell );
    virtual ~HtmlExport();

    static String   ColorToHTMLString( Color aColor );
    static String   StringToHTMLString( const String& rString );
    static String   StringToURL( const String& rURL );
};

#endif // _SD_HTMLEX_HXX
<|endoftext|>


<commit_before>//===-- RuntimeDyldCOFF.cpp - Run-time dynamic linker for MC-JIT -*- C++ -*-==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Implementation of COFF support for the MC-JIT runtime dynamic linker.
//
//===----------------------------------------------------------------------===//

#include "RuntimeDyldCOFF.h"
#include "Targets/RuntimeDyldCOFFX86_64.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Object/ObjectFile.h"

using namespace llvm;
using namespace llvm::object;

#define DEBUG_TYPE "dyld"

namespace {

class LoadedCOFFObjectInfo
    : public RuntimeDyld::LoadedObjectInfoHelper<LoadedCOFFObjectInfo> {
public:
  LoadedCOFFObjectInfo(RuntimeDyldImpl &RTDyld, unsigned BeginIdx,
                       unsigned EndIdx)
      : LoadedObjectInfoHelper(RTDyld, BeginIdx, EndIdx) {}

  OwningBinary<ObjectFile>
  getObjectForDebug(const ObjectFile &Obj) const override {
    return OwningBinary<ObjectFile>();
  }
};
}

namespace llvm {

std::unique_ptr<RuntimeDyldCOFF>
llvm::RuntimeDyldCOFF::create(Triple::ArchType Arch,
                              RuntimeDyld::MemoryManager &MemMgr,
                              RuntimeDyld::SymbolResolver &Resolver) {
  switch (Arch) {
  default:
    llvm_unreachable("Unsupported target for RuntimeDyldCOFF.");
    break;
  case Triple::x86_64:
    return make_unique<RuntimeDyldCOFFX86_64>(MemMgr, Resolver);
  }
}

std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
RuntimeDyldCOFF::loadObject(const object::ObjectFile &O) {
  unsigned SectionStartIdx, SectionEndIdx;
  std::tie(SectionStartIdx, SectionEndIdx) = loadObjectImpl(O);
  return llvm::make_unique<LoadedCOFFObjectInfo>(*this, SectionStartIdx,
                                                 SectionEndIdx);
}

uint64_t RuntimeDyldCOFF::getSymbolOffset(const SymbolRef &Sym) {
  uint64_t Address;
  if (Sym.getAddress(Address))
    return UnknownAddress;

  if (Address == UnknownAddress)
    return UnknownAddress;

  const ObjectFile *Obj = Sym.getObject();
  section_iterator SecI(Obj->section_end());
  if (Sym.getSection(SecI))
    return UnknownAddress;

  if (SecI == Obj->section_end())
    return UnknownAddress;

  uint64_t SectionAddress = SecI->getAddress();
  return Address - SectionAddress;
}

bool RuntimeDyldCOFF::isCompatibleFile(const object::ObjectFile &Obj) const {
  return Obj.isCOFF();
}

} // namespace llvm
<commit_msg>Use Symbol.getValue to simplify RuntimeDyldCOFF::getSymbolOffset. NFC.<commit_after>//===-- RuntimeDyldCOFF.cpp - Run-time dynamic linker for MC-JIT -*- C++ -*-==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Implementation of COFF support for the MC-JIT runtime dynamic linker.
//
//===----------------------------------------------------------------------===//

#include "RuntimeDyldCOFF.h"
#include "Targets/RuntimeDyldCOFFX86_64.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Object/ObjectFile.h"

using namespace llvm;
using namespace llvm::object;

#define DEBUG_TYPE "dyld"

namespace {

class LoadedCOFFObjectInfo
    : public RuntimeDyld::LoadedObjectInfoHelper<LoadedCOFFObjectInfo> {
public:
  LoadedCOFFObjectInfo(RuntimeDyldImpl &RTDyld, unsigned BeginIdx,
                       unsigned EndIdx)
      : LoadedObjectInfoHelper(RTDyld, BeginIdx, EndIdx) {}

  OwningBinary<ObjectFile>
  getObjectForDebug(const ObjectFile &Obj) const override {
    return OwningBinary<ObjectFile>();
  }
};
}

namespace llvm {

std::unique_ptr<RuntimeDyldCOFF>
llvm::RuntimeDyldCOFF::create(Triple::ArchType Arch,
                              RuntimeDyld::MemoryManager &MemMgr,
                              RuntimeDyld::SymbolResolver &Resolver) {
  switch (Arch) {
  default:
    llvm_unreachable("Unsupported target for RuntimeDyldCOFF.");
    break;
  case Triple::x86_64:
    return make_unique<RuntimeDyldCOFFX86_64>(MemMgr, Resolver);
  }
}

std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
RuntimeDyldCOFF::loadObject(const object::ObjectFile &O) {
  unsigned SectionStartIdx, SectionEndIdx;
  std::tie(SectionStartIdx, SectionEndIdx) = loadObjectImpl(O);
  return llvm::make_unique<LoadedCOFFObjectInfo>(*this, SectionStartIdx,
                                                 SectionEndIdx);
}

uint64_t RuntimeDyldCOFF::getSymbolOffset(const SymbolRef &Sym) {
  // The value in a relocatable COFF object is the offset.
  return Sym.getValue();
}

bool RuntimeDyldCOFF::isCompatibleFile(const object::ObjectFile &Obj) const {
  return Obj.isCOFF();
}

} // namespace llvm
<|endoftext|>


<commit_before><commit_msg>coverity#735844 Dereference after null check<commit_after><|endoftext|>


<commit_before>//===--- BugReducerTester.cpp ---------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
///
/// \file
///
/// This pass is a testing pass for sil-bug-reducer. It asserts when it visits a
/// function that calls a function specified by an llvm::cl::opt.
///
//===----------------------------------------------------------------------===//

#include "swift/SIL/SILBuilder.h"
#include "swift/SIL/SILFunction.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SIL/SILLocation.h"
#include "swift/SIL/SILUndef.h"
#include "swift/SILOptimizer/PassManager/Passes.h"
#include "swift/SILOptimizer/PassManager/Transforms.h"
#include "llvm/Support/CommandLine.h"

using namespace swift;

static llvm::cl::opt<std::string> FunctionTarget(
    "bug-reducer-tester-target-func",
    llvm::cl::desc("Function that when called by an apply should cause "
                   "BugReducerTester to blow up or miscompile if the pass "
                   "visits the apply"));

namespace {
enum class FailureKind {
  OptimizerCrasher,
  RuntimeMiscompile,
  RuntimeCrasher,
  None
};
} // end anonymous namespace

static llvm::cl::opt<FailureKind> TargetFailureKind(
    "bug-reducer-tester-failure-kind",
    llvm::cl::desc("The type of failure to perform"),
    llvm::cl::values(
        clEnumValN(FailureKind::OptimizerCrasher, "opt-crasher",
                   "Crash the optimizer when we see the specified apply"),
        clEnumValN(FailureKind::RuntimeMiscompile, "miscompile",
                   "Delete the target function call to cause a runtime "
                   "miscompile that is not a crasher"),
        clEnumValN(FailureKind::RuntimeCrasher, "runtime-crasher",
                   "Delete the target function call to cause a runtime "
                   "miscompile that is not a crasher"),
        clEnumValEnd),
    llvm::cl::init(FailureKind::None));

namespace {

class BugReducerTester : public SILFunctionTransform {

  // We only want to cause 1 miscompile.
  bool CausedError = false;
  StringRef RuntimeCrasherFunctionName = "bug_reducer_runtime_crasher_func";

  SILFunction *getRuntimeCrasherFunction() {
    assert(TargetFailureKind == FailureKind::RuntimeCrasher);
    llvm::SmallVector<SILResultInfo, 1> ResultInfoArray;
    auto EmptyTupleCanType = getFunction()
                                 ->getModule()
                                 .Types.getEmptyTupleType()
                                 .getSwiftRValueType();
    ResultInfoArray.push_back(
        SILResultInfo(EmptyTupleCanType, ResultConvention::Unowned));
    auto FuncType = SILFunctionType::get(
        nullptr, SILFunctionType::ExtInfo(SILFunctionType::Representation::Thin,
                                          false /*isPseudoGeneric*/),
        ParameterConvention::Direct_Unowned, ArrayRef<SILParameterInfo>(),
        ResultInfoArray, None, getFunction()->getModule().getASTContext());

    SILFunction *F = getFunction()->getModule().getOrCreateSharedFunction(
        RegularLocation::getAutoGeneratedLocation(), RuntimeCrasherFunctionName,
        FuncType, IsBare, IsNotTransparent, IsFragile, IsNotThunk);
    if (F->isDefinition())
      return F;

    // Create a new block.
    SILBasicBlock *BB = F->createBasicBlock();

    // Insert a builtin int trap. Then return F.
    SILBuilder B(BB);
    B.createBuiltinTrap(RegularLocation::getAutoGeneratedLocation());
    B.createUnreachable(ArtificialUnreachableLocation());
    return F;
  }

  void run() override {
    // If we don't have a target function or we already caused a miscompile,
    // just return.
    if (FunctionTarget.empty() || CausedError)
      return;
    assert(TargetFailureKind != FailureKind::None);
    SILModule &M = getFunction()->getModule();
    for (auto &BB : *getFunction()) {
      for (auto &II : BB) {
        auto *Apply = dyn_cast<ApplyInst>(&II);
        if (!Apply)
          continue;
        auto *FRI = dyn_cast<FunctionRefInst>(Apply->getCallee());
        if (!FRI ||
            !FRI->getReferencedFunction()->getName().equals(FunctionTarget))
          continue;

        // Ok, we found the Apply that we want! If we are asked to crash, crash
        // here.
        if (TargetFailureKind == FailureKind::OptimizerCrasher)
          llvm_unreachable("Found the target!");

        // Otherwise, if we are asked to perform a runtime time miscompile,
        // delete the apply target.
        if (TargetFailureKind == FailureKind::RuntimeMiscompile) {
          Apply->replaceAllUsesWith(SILUndef::get(Apply->getType(), M));
          Apply->eraseFromParent();

          // Mark that we found the miscompile and return so we do not try to
          // visit any more instructions in this function.
          CausedError = true;
          return;
        }

        assert(TargetFailureKind == FailureKind::RuntimeCrasher);
        // Finally, if we reach this point we are being asked to replace the
        // given apply with a new apply that calls the crasher func.
        auto Loc = RegularLocation::getAutoGeneratedLocation();
        SILFunction *RuntimeCrasherFunc = getRuntimeCrasherFunction();
        llvm::dbgs() << "Runtime Crasher Func!\n";
        RuntimeCrasherFunc->dump();
        SILBuilder B(Apply->getIterator());
        B.createApply(Loc, B.createFunctionRef(Loc, RuntimeCrasherFunc),
                      RuntimeCrasherFunc->getLoweredType(),
                      M.Types.getEmptyTupleType(), ArrayRef<Substitution>(),
                      ArrayRef<SILValue>(), false /*NoThrow*/);

        Apply->replaceAllUsesWith(SILUndef::get(Apply->getType(), M));
        Apply->eraseFromParent();

        CausedError = true;
        return;
      }
    }
  }

  StringRef getName() override { return "Bug Reducer Tester"; }
};

} // end anonymous namespace

SILTransform *swift::createBugReducerTester() { return new BugReducerTester(); }
<commit_msg>Update for clang r283671: remove use of clEnumValEnd.<commit_after>//===--- BugReducerTester.cpp ---------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
///
/// \file
///
/// This pass is a testing pass for sil-bug-reducer. It asserts when it visits a
/// function that calls a function specified by an llvm::cl::opt.
///
//===----------------------------------------------------------------------===//

#include "swift/SIL/SILBuilder.h"
#include "swift/SIL/SILFunction.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SIL/SILLocation.h"
#include "swift/SIL/SILUndef.h"
#include "swift/SILOptimizer/PassManager/Passes.h"
#include "swift/SILOptimizer/PassManager/Transforms.h"
#include "llvm/Support/CommandLine.h"

using namespace swift;

static llvm::cl::opt<std::string> FunctionTarget(
    "bug-reducer-tester-target-func",
    llvm::cl::desc("Function that when called by an apply should cause "
                   "BugReducerTester to blow up or miscompile if the pass "
                   "visits the apply"));

namespace {
enum class FailureKind {
  OptimizerCrasher,
  RuntimeMiscompile,
  RuntimeCrasher,
  None
};
} // end anonymous namespace

static llvm::cl::opt<FailureKind> TargetFailureKind(
    "bug-reducer-tester-failure-kind",
    llvm::cl::desc("The type of failure to perform"),
    llvm::cl::values(
        clEnumValN(FailureKind::OptimizerCrasher, "opt-crasher",
                   "Crash the optimizer when we see the specified apply"),
        clEnumValN(FailureKind::RuntimeMiscompile, "miscompile",
                   "Delete the target function call to cause a runtime "
                   "miscompile that is not a crasher"),
        clEnumValN(FailureKind::RuntimeCrasher, "runtime-crasher",
                   "Delete the target function call to cause a runtime "
                   "miscompile that is not a crasher")),
    llvm::cl::init(FailureKind::None));

namespace {

class BugReducerTester : public SILFunctionTransform {

  // We only want to cause 1 miscompile.
  bool CausedError = false;
  StringRef RuntimeCrasherFunctionName = "bug_reducer_runtime_crasher_func";

  SILFunction *getRuntimeCrasherFunction() {
    assert(TargetFailureKind == FailureKind::RuntimeCrasher);
    llvm::SmallVector<SILResultInfo, 1> ResultInfoArray;
    auto EmptyTupleCanType = getFunction()
                                 ->getModule()
                                 .Types.getEmptyTupleType()
                                 .getSwiftRValueType();
    ResultInfoArray.push_back(
        SILResultInfo(EmptyTupleCanType, ResultConvention::Unowned));
    auto FuncType = SILFunctionType::get(
        nullptr, SILFunctionType::ExtInfo(SILFunctionType::Representation::Thin,
                                          false /*isPseudoGeneric*/),
        ParameterConvention::Direct_Unowned, ArrayRef<SILParameterInfo>(),
        ResultInfoArray, None, getFunction()->getModule().getASTContext());

    SILFunction *F = getFunction()->getModule().getOrCreateSharedFunction(
        RegularLocation::getAutoGeneratedLocation(), RuntimeCrasherFunctionName,
        FuncType, IsBare, IsNotTransparent, IsFragile, IsNotThunk);
    if (F->isDefinition())
      return F;

    // Create a new block.
    SILBasicBlock *BB = F->createBasicBlock();

    // Insert a builtin int trap. Then return F.
    SILBuilder B(BB);
    B.createBuiltinTrap(RegularLocation::getAutoGeneratedLocation());
    B.createUnreachable(ArtificialUnreachableLocation());
    return F;
  }

  void run() override {
    // If we don't have a target function or we already caused a miscompile,
    // just return.
    if (FunctionTarget.empty() || CausedError)
      return;
    assert(TargetFailureKind != FailureKind::None);
    SILModule &M = getFunction()->getModule();
    for (auto &BB : *getFunction()) {
      for (auto &II : BB) {
        auto *Apply = dyn_cast<ApplyInst>(&II);
        if (!Apply)
          continue;
        auto *FRI = dyn_cast<FunctionRefInst>(Apply->getCallee());
        if (!FRI ||
            !FRI->getReferencedFunction()->getName().equals(FunctionTarget))
          continue;

        // Ok, we found the Apply that we want! If we are asked to crash, crash
        // here.
        if (TargetFailureKind == FailureKind::OptimizerCrasher)
          llvm_unreachable("Found the target!");

        // Otherwise, if we are asked to perform a runtime time miscompile,
        // delete the apply target.
        if (TargetFailureKind == FailureKind::RuntimeMiscompile) {
          Apply->replaceAllUsesWith(SILUndef::get(Apply->getType(), M));
          Apply->eraseFromParent();

          // Mark that we found the miscompile and return so we do not try to
          // visit any more instructions in this function.
          CausedError = true;
          return;
        }

        assert(TargetFailureKind == FailureKind::RuntimeCrasher);
        // Finally, if we reach this point we are being asked to replace the
        // given apply with a new apply that calls the crasher func.
        auto Loc = RegularLocation::getAutoGeneratedLocation();
        SILFunction *RuntimeCrasherFunc = getRuntimeCrasherFunction();
        llvm::dbgs() << "Runtime Crasher Func!\n";
        RuntimeCrasherFunc->dump();
        SILBuilder B(Apply->getIterator());
        B.createApply(Loc, B.createFunctionRef(Loc, RuntimeCrasherFunc),
                      RuntimeCrasherFunc->getLoweredType(),
                      M.Types.getEmptyTupleType(), ArrayRef<Substitution>(),
                      ArrayRef<SILValue>(), false /*NoThrow*/);

        Apply->replaceAllUsesWith(SILUndef::get(Apply->getType(), M));
        Apply->eraseFromParent();

        CausedError = true;
        return;
      }
    }
  }

  StringRef getName() override { return "Bug Reducer Tester"; }
};

} // end anonymous namespace

SILTransform *swift::createBugReducerTester() { return new BugReducerTester(); }
<|endoftext|>


<commit_before><commit_msg>option to disable grpc over http<commit_after><|endoftext|>


<commit_before><commit_msg>SSLConfig struct CertAndStatus is not initializing all its members.<commit_after><|endoftext|>


<commit_before>/*
* Vulkan framebuffer class
*
* Copyright (C) 2016 by Sascha Willems - www.saschawillems.de
*
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
*/

#pragma once

#include <algorithm>
#include <iterator>
#include <vector>
#include "vulkan/vulkan.h"
#include "vulkandevice.hpp"
#include "vulkantools.h"

namespace vk
{
	/**
	* @brief Encapsulates a single frame buffer attachment
	*/
	struct FramebufferAttachment
	{
		VkImage image;
		VkDeviceMemory memory;
		VkImageView view;
		VkFormat format;
		VkImageSubresourceRange subresourceRange;
		VkAttachmentDescription description;
		VkImageLayout initialLayout;

		/**
		* @brief Returns true if the attachment has a depth component
		*/
		bool hasDepth()
		{
			std::vector<VkFormat> formats =
			{
				VK_FORMAT_D16_UNORM,
				VK_FORMAT_X8_D24_UNORM_PACK32,
				VK_FORMAT_D32_SFLOAT,
				VK_FORMAT_D16_UNORM_S8_UINT,
				VK_FORMAT_D24_UNORM_S8_UINT,
				VK_FORMAT_D32_SFLOAT_S8_UINT,
			};
			return std::find(formats.begin(), formats.end(), format) != std::end(formats);
		}

		/**
		* @brief Returns true if the attachment has a stencil component
		*/
		bool hasStencil()
		{
			std::vector<VkFormat> formats =
			{
				VK_FORMAT_S8_UINT,
				VK_FORMAT_D16_UNORM_S8_UINT,
				VK_FORMAT_D24_UNORM_S8_UINT,
				VK_FORMAT_D32_SFLOAT_S8_UINT,
			};
			return std::find(formats.begin(), formats.end(), format) != std::end(formats);
		}

		/**
		* @brief Returns true if the attachment is a depth and/or stencil attachment
		*/
		bool isDepthStencil()
		{
			return(hasDepth() || hasStencil());
		}

	};

	/**
	* @brief Describes the attributes of an attachment to be created
	*/
	struct AttachmentCreateInfo
	{
		uint32_t width, height;
		uint32_t layerCount;
		VkFormat format;
		VkImageUsageFlags usage;
	};

	/**
	* @brief Encaspulates a complete Vulkan framebuffer with an arbitrary number and combination of attachments
	*/
	struct Framebuffer
	{
	private:
		vk::VulkanDevice *vulkanDevice;
	public:
		uint32_t width, height;
		VkFramebuffer framebuffer;
		VkRenderPass renderPass;
		VkSampler sampler;
		std::vector<vk::FramebufferAttachment> attachments;

		/**
		* Default constructor
		*
		* @param vulkanDevice Pointer to a valid VulkanDevice
		*/
		Framebuffer(vk::VulkanDevice *vulkanDevice)
		{
			assert(vulkanDevice);
			this->vulkanDevice = vulkanDevice;
		}

		/**
		* Destroy and free Vulkan resources used for the framebuffer and all of it's attachments
		*/
		~Framebuffer()
		{
			assert(vulkanDevice);
			for (auto attachment : attachments)
			{
				vkDestroyImage(vulkanDevice->device, attachment.image, nullptr);
				vkDestroyImageView(vulkanDevice->device, attachment.view, nullptr);
				vkFreeMemory(vulkanDevice->device, attachment.memory, nullptr);
			}
			vkDestroySampler(vulkanDevice->device, sampler, nullptr);
			vkDestroyRenderPass(vulkanDevice->device, renderPass, nullptr);
			vkDestroyFramebuffer(vulkanDevice->device, framebuffer, nullptr);
		}

		/**
		* Add a new attachment described by createinfo to the framebuffer's attachment list
		*
		* @param createinfo Structure that specifices the framebuffer to be constructed
		* @param layoutCmd A valid and active command buffer used for the initial layout transitions
		*
		* @return Index of the new attachment
		*/
		uint32_t addAttachment(vk::AttachmentCreateInfo createinfo, VkCommandBuffer layoutCmd)
		{
			vk::FramebufferAttachment attachment;

			attachment.format = createinfo.format;

			VkImageAspectFlags aspectMask = VK_FLAGS_NONE;
			VkImageLayout imageLayout;

			// Select aspect mask and layout depending on usage

			// Color attachment
			if (createinfo.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
			{
				aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
				attachment.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
				imageLayout = (createinfo.usage & VK_IMAGE_USAGE_SAMPLED_BIT) ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
			}

			// Depth (and/or stencil) attachment
			if (createinfo.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)
			{
				if (attachment.hasDepth())
				{
					aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
				}
				if (attachment.hasStencil())
				{
					aspectMask = aspectMask | VK_IMAGE_ASPECT_STENCIL_BIT;
				}
				attachment.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
				imageLayout = (createinfo.usage & VK_IMAGE_USAGE_SAMPLED_BIT) ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
			}

			assert(aspectMask > 0);

			VkImageCreateInfo image = vkTools::initializers::imageCreateInfo();
			image.imageType = VK_IMAGE_TYPE_2D;
			image.format = createinfo.format;
			image.extent.width = createinfo.width;
			image.extent.height = createinfo.height;
			image.extent.depth = 1;
			image.mipLevels = 1;
			image.arrayLayers = createinfo.layerCount;
			image.samples = VK_SAMPLE_COUNT_1_BIT;
			image.tiling = VK_IMAGE_TILING_OPTIMAL;
			image.usage = createinfo.usage;

			VkMemoryAllocateInfo memAlloc = vkTools::initializers::memoryAllocateInfo();
			VkMemoryRequirements memReqs;

			// Create image for this attachment
			VK_CHECK_RESULT(vkCreateImage(vulkanDevice->device, &image, nullptr, &attachment.image));
			vkGetImageMemoryRequirements(vulkanDevice->device, attachment.image, &memReqs);
			memAlloc.allocationSize = memReqs.size;
			memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
			VK_CHECK_RESULT(vkAllocateMemory(vulkanDevice->device, &memAlloc, nullptr, &attachment.memory));
			VK_CHECK_RESULT(vkBindImageMemory(vulkanDevice->device, attachment.image, attachment.memory, 0));

			attachment.subresourceRange = {};
			attachment.subresourceRange.aspectMask = aspectMask;
			attachment.subresourceRange.levelCount = 1;
			attachment.subresourceRange.layerCount = createinfo.layerCount;

			// Set the initial layout to shader read instead of attachment
			// Note that the render loop has to take care of the transition from read to attachment
			vkTools::setImageLayout(
				layoutCmd,
				attachment.image,
				aspectMask,
				VK_IMAGE_LAYOUT_UNDEFINED,
				imageLayout,
				attachment.subresourceRange);

			VkImageViewCreateInfo imageView = vkTools::initializers::imageViewCreateInfo();
			imageView.viewType = (createinfo.layerCount == 1) ? VK_IMAGE_VIEW_TYPE_2D : VK_IMAGE_VIEW_TYPE_2D_ARRAY;
			imageView.format = createinfo.format;
			imageView.subresourceRange = attachment.subresourceRange;
			//todo: workaround for depth+stencil attachments
			imageView.subresourceRange.aspectMask = (attachment.hasDepth()) ? VK_IMAGE_ASPECT_DEPTH_BIT : aspectMask;
			imageView.image = attachment.image;
			VK_CHECK_RESULT(vkCreateImageView(vulkanDevice->device, &imageView, nullptr, &attachment.view));

			// Fill attachment description
			attachment.description = {};
			attachment.description.samples = VK_SAMPLE_COUNT_1_BIT;
			attachment.description.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
			attachment.description.storeOp = (createinfo.usage & VK_IMAGE_USAGE_SAMPLED_BIT) ? VK_ATTACHMENT_STORE_OP_STORE : VK_ATTACHMENT_STORE_OP_DONT_CARE;
			attachment.description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
			attachment.description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
			attachment.description.format = createinfo.format;
			if (attachment.hasDepth() || attachment.hasStencil())
			{
				attachment.description.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
				attachment.description.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
			}
			else
			{
				attachment.description.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
				attachment.description.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
			}

			attachments.push_back(attachment);

			return static_cast<uint32_t>(attachments.size() - 1);
		}

		/**
		* Creates a default sampler for sampling from any of the framebuffer attachments
		* Applications are free to create their own samplers for different use cases
		*
		* @param magFilter Magnification filter for lookups
		* @param minFilter Minification filter for lookups
		* @param adressMode Adressing mode for the U,V and W coordinates
		*
		* @return VkResult for the sampler creation
		*/
		VkResult createSampler(VkFilter magFilter, VkFilter minFilter, VkSamplerAddressMode adressMode)
		{
			VkSamplerCreateInfo samplerInfo = vkTools::initializers::samplerCreateInfo();
			samplerInfo.magFilter = magFilter;
			samplerInfo.minFilter = minFilter;
			samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
			samplerInfo.addressModeU = adressMode;
			samplerInfo.addressModeV = adressMode;
			samplerInfo.addressModeW = adressMode;
			samplerInfo.mipLodBias = 0.0f;
			samplerInfo.maxAnisotropy = 0;
			samplerInfo.minLod = 0.0f;
			samplerInfo.maxLod = 1.0f;
			samplerInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
			return vkCreateSampler(vulkanDevice->device, &samplerInfo, nullptr, &sampler);
		}

		/**
		* Creates a default render pass setup with one sub pass
		*
		* @return VK_SUCCESS if all resources have been created successfully
		*/
		VkResult createRenderPass()
		{
			std::vector<VkAttachmentDescription> attachmentDescriptions;
			for (auto& attachment : attachments)
			{
				attachmentDescriptions.push_back(attachment.description);
			};

			// Collect attachment references
			std::vector<VkAttachmentReference> colorReferences;
			VkAttachmentReference depthReference = {};
			bool hasDepth = false;
			bool hasColor = false;

			uint32_t attachmentIndex = 0;

			for (auto& attachment : attachments)
			{
				if (attachment.isDepthStencil())
				{
					// Only one depth attachment allowed
					assert(!hasDepth);
					depthReference.attachment = attachmentIndex;
					depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
					hasDepth = true;
				}
				else
				{
					colorReferences.push_back({ attachmentIndex, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL });
					hasColor = true;
				}
				attachmentIndex++;
			};

			// Default render pass setup uses only one subpass
			VkSubpassDescription subpass = {};
			subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
			if (hasColor)
			{
				subpass.pColorAttachments = colorReferences.data();
				subpass.colorAttachmentCount = static_cast<uint32_t>(colorReferences.size());
			}
			if (hasDepth)
			{
				subpass.pDepthStencilAttachment = &depthReference;
			}

			// Create render pass
			VkRenderPassCreateInfo renderPassInfo = {};
			renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
			renderPassInfo.pAttachments = attachmentDescriptions.data();
			renderPassInfo.attachmentCount = static_cast<uint32_t>(attachmentDescriptions.size());
			renderPassInfo.subpassCount = 1;
			renderPassInfo.pSubpasses = &subpass;
			VK_CHECK_RESULT(vkCreateRenderPass(vulkanDevice->device, &renderPassInfo, nullptr, &renderPass));

			std::vector<VkImageView> attachmentViews;
			for (auto attachment : attachments)
			{
				attachmentViews.push_back(attachment.view);
			}

			VkFramebufferCreateInfo framebufferInfo = {};
			framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
			framebufferInfo.renderPass = renderPass;
			framebufferInfo.pAttachments = attachmentViews.data();
			framebufferInfo.attachmentCount = static_cast<uint32_t>(attachmentViews.size());
			framebufferInfo.width = width;
			framebufferInfo.height = height;
			framebufferInfo.layers = 1;
			VK_CHECK_RESULT(vkCreateFramebuffer(vulkanDevice->device, &framebufferInfo, nullptr, &framebuffer));

			return VK_SUCCESS;
		}
	};
}<commit_msg>Set framebuffer layer depending on attachment layer count (Refs #204)<commit_after>/*
* Vulkan framebuffer class
*
* Copyright (C) 2016 by Sascha Willems - www.saschawillems.de
*
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
*/

#pragma once

#include <algorithm>
#include <iterator>
#include <vector>
#include "vulkan/vulkan.h"
#include "vulkandevice.hpp"
#include "vulkantools.h"

namespace vk
{
	/**
	* @brief Encapsulates a single frame buffer attachment
	*/
	struct FramebufferAttachment
	{
		VkImage image;
		VkDeviceMemory memory;
		VkImageView view;
		VkFormat format;
		VkImageSubresourceRange subresourceRange;
		VkAttachmentDescription description;
		VkImageLayout initialLayout;

		/**
		* @brief Returns true if the attachment has a depth component
		*/
		bool hasDepth()
		{
			std::vector<VkFormat> formats =
			{
				VK_FORMAT_D16_UNORM,
				VK_FORMAT_X8_D24_UNORM_PACK32,
				VK_FORMAT_D32_SFLOAT,
				VK_FORMAT_D16_UNORM_S8_UINT,
				VK_FORMAT_D24_UNORM_S8_UINT,
				VK_FORMAT_D32_SFLOAT_S8_UINT,
			};
			return std::find(formats.begin(), formats.end(), format) != std::end(formats);
		}

		/**
		* @brief Returns true if the attachment has a stencil component
		*/
		bool hasStencil()
		{
			std::vector<VkFormat> formats =
			{
				VK_FORMAT_S8_UINT,
				VK_FORMAT_D16_UNORM_S8_UINT,
				VK_FORMAT_D24_UNORM_S8_UINT,
				VK_FORMAT_D32_SFLOAT_S8_UINT,
			};
			return std::find(formats.begin(), formats.end(), format) != std::end(formats);
		}

		/**
		* @brief Returns true if the attachment is a depth and/or stencil attachment
		*/
		bool isDepthStencil()
		{
			return(hasDepth() || hasStencil());
		}

	};

	/**
	* @brief Describes the attributes of an attachment to be created
	*/
	struct AttachmentCreateInfo
	{
		uint32_t width, height;
		uint32_t layerCount;
		VkFormat format;
		VkImageUsageFlags usage;
	};

	/**
	* @brief Encaspulates a complete Vulkan framebuffer with an arbitrary number and combination of attachments
	*/
	struct Framebuffer
	{
	private:
		vk::VulkanDevice *vulkanDevice;
	public:
		uint32_t width, height;
		VkFramebuffer framebuffer;
		VkRenderPass renderPass;
		VkSampler sampler;
		std::vector<vk::FramebufferAttachment> attachments;

		/**
		* Default constructor
		*
		* @param vulkanDevice Pointer to a valid VulkanDevice
		*/
		Framebuffer(vk::VulkanDevice *vulkanDevice)
		{
			assert(vulkanDevice);
			this->vulkanDevice = vulkanDevice;
		}

		/**
		* Destroy and free Vulkan resources used for the framebuffer and all of it's attachments
		*/
		~Framebuffer()
		{
			assert(vulkanDevice);
			for (auto attachment : attachments)
			{
				vkDestroyImage(vulkanDevice->device, attachment.image, nullptr);
				vkDestroyImageView(vulkanDevice->device, attachment.view, nullptr);
				vkFreeMemory(vulkanDevice->device, attachment.memory, nullptr);
			}
			vkDestroySampler(vulkanDevice->device, sampler, nullptr);
			vkDestroyRenderPass(vulkanDevice->device, renderPass, nullptr);
			vkDestroyFramebuffer(vulkanDevice->device, framebuffer, nullptr);
		}

		/**
		* Add a new attachment described by createinfo to the framebuffer's attachment list
		*
		* @param createinfo Structure that specifices the framebuffer to be constructed
		* @param layoutCmd A valid and active command buffer used for the initial layout transitions
		*
		* @return Index of the new attachment
		*/
		uint32_t addAttachment(vk::AttachmentCreateInfo createinfo, VkCommandBuffer layoutCmd)
		{
			vk::FramebufferAttachment attachment;

			attachment.format = createinfo.format;

			VkImageAspectFlags aspectMask = VK_FLAGS_NONE;
			VkImageLayout imageLayout;

			// Select aspect mask and layout depending on usage

			// Color attachment
			if (createinfo.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
			{
				aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
				attachment.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
				imageLayout = (createinfo.usage & VK_IMAGE_USAGE_SAMPLED_BIT) ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
			}

			// Depth (and/or stencil) attachment
			if (createinfo.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)
			{
				if (attachment.hasDepth())
				{
					aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
				}
				if (attachment.hasStencil())
				{
					aspectMask = aspectMask | VK_IMAGE_ASPECT_STENCIL_BIT;
				}
				attachment.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
				imageLayout = (createinfo.usage & VK_IMAGE_USAGE_SAMPLED_BIT) ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
			}

			assert(aspectMask > 0);

			VkImageCreateInfo image = vkTools::initializers::imageCreateInfo();
			image.imageType = VK_IMAGE_TYPE_2D;
			image.format = createinfo.format;
			image.extent.width = createinfo.width;
			image.extent.height = createinfo.height;
			image.extent.depth = 1;
			image.mipLevels = 1;
			image.arrayLayers = createinfo.layerCount;
			image.samples = VK_SAMPLE_COUNT_1_BIT;
			image.tiling = VK_IMAGE_TILING_OPTIMAL;
			image.usage = createinfo.usage;

			VkMemoryAllocateInfo memAlloc = vkTools::initializers::memoryAllocateInfo();
			VkMemoryRequirements memReqs;

			// Create image for this attachment
			VK_CHECK_RESULT(vkCreateImage(vulkanDevice->device, &image, nullptr, &attachment.image));
			vkGetImageMemoryRequirements(vulkanDevice->device, attachment.image, &memReqs);
			memAlloc.allocationSize = memReqs.size;
			memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
			VK_CHECK_RESULT(vkAllocateMemory(vulkanDevice->device, &memAlloc, nullptr, &attachment.memory));
			VK_CHECK_RESULT(vkBindImageMemory(vulkanDevice->device, attachment.image, attachment.memory, 0));

			attachment.subresourceRange = {};
			attachment.subresourceRange.aspectMask = aspectMask;
			attachment.subresourceRange.levelCount = 1;
			attachment.subresourceRange.layerCount = createinfo.layerCount;

			// Set the initial layout to shader read instead of attachment
			// Note that the render loop has to take care of the transition from read to attachment
			vkTools::setImageLayout(
				layoutCmd,
				attachment.image,
				aspectMask,
				VK_IMAGE_LAYOUT_UNDEFINED,
				imageLayout,
				attachment.subresourceRange);

			VkImageViewCreateInfo imageView = vkTools::initializers::imageViewCreateInfo();
			imageView.viewType = (createinfo.layerCount == 1) ? VK_IMAGE_VIEW_TYPE_2D : VK_IMAGE_VIEW_TYPE_2D_ARRAY;
			imageView.format = createinfo.format;
			imageView.subresourceRange = attachment.subresourceRange;
			//todo: workaround for depth+stencil attachments
			imageView.subresourceRange.aspectMask = (attachment.hasDepth()) ? VK_IMAGE_ASPECT_DEPTH_BIT : aspectMask;
			imageView.image = attachment.image;
			VK_CHECK_RESULT(vkCreateImageView(vulkanDevice->device, &imageView, nullptr, &attachment.view));

			// Fill attachment description
			attachment.description = {};
			attachment.description.samples = VK_SAMPLE_COUNT_1_BIT;
			attachment.description.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
			attachment.description.storeOp = (createinfo.usage & VK_IMAGE_USAGE_SAMPLED_BIT) ? VK_ATTACHMENT_STORE_OP_STORE : VK_ATTACHMENT_STORE_OP_DONT_CARE;
			attachment.description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
			attachment.description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
			attachment.description.format = createinfo.format;
			if (attachment.hasDepth() || attachment.hasStencil())
			{
				attachment.description.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
				attachment.description.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
			}
			else
			{
				attachment.description.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
				attachment.description.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
			}

			attachments.push_back(attachment);

			return static_cast<uint32_t>(attachments.size() - 1);
		}

		/**
		* Creates a default sampler for sampling from any of the framebuffer attachments
		* Applications are free to create their own samplers for different use cases
		*
		* @param magFilter Magnification filter for lookups
		* @param minFilter Minification filter for lookups
		* @param adressMode Adressing mode for the U,V and W coordinates
		*
		* @return VkResult for the sampler creation
		*/
		VkResult createSampler(VkFilter magFilter, VkFilter minFilter, VkSamplerAddressMode adressMode)
		{
			VkSamplerCreateInfo samplerInfo = vkTools::initializers::samplerCreateInfo();
			samplerInfo.magFilter = magFilter;
			samplerInfo.minFilter = minFilter;
			samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
			samplerInfo.addressModeU = adressMode;
			samplerInfo.addressModeV = adressMode;
			samplerInfo.addressModeW = adressMode;
			samplerInfo.mipLodBias = 0.0f;
			samplerInfo.maxAnisotropy = 0;
			samplerInfo.minLod = 0.0f;
			samplerInfo.maxLod = 1.0f;
			samplerInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
			return vkCreateSampler(vulkanDevice->device, &samplerInfo, nullptr, &sampler);
		}

		/**
		* Creates a default render pass setup with one sub pass
		*
		* @return VK_SUCCESS if all resources have been created successfully
		*/
		VkResult createRenderPass()
		{
			std::vector<VkAttachmentDescription> attachmentDescriptions;
			for (auto& attachment : attachments)
			{
				attachmentDescriptions.push_back(attachment.description);
			};

			// Collect attachment references
			std::vector<VkAttachmentReference> colorReferences;
			VkAttachmentReference depthReference = {};
			bool hasDepth = false;
			bool hasColor = false;

			uint32_t attachmentIndex = 0;

			for (auto& attachment : attachments)
			{
				if (attachment.isDepthStencil())
				{
					// Only one depth attachment allowed
					assert(!hasDepth);
					depthReference.attachment = attachmentIndex;
					depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
					hasDepth = true;
				}
				else
				{
					colorReferences.push_back({ attachmentIndex, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL });
					hasColor = true;
				}
				attachmentIndex++;
			};

			// Default render pass setup uses only one subpass
			VkSubpassDescription subpass = {};
			subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
			if (hasColor)
			{
				subpass.pColorAttachments = colorReferences.data();
				subpass.colorAttachmentCount = static_cast<uint32_t>(colorReferences.size());
			}
			if (hasDepth)
			{
				subpass.pDepthStencilAttachment = &depthReference;
			}

			// Create render pass
			VkRenderPassCreateInfo renderPassInfo = {};
			renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
			renderPassInfo.pAttachments = attachmentDescriptions.data();
			renderPassInfo.attachmentCount = static_cast<uint32_t>(attachmentDescriptions.size());
			renderPassInfo.subpassCount = 1;
			renderPassInfo.pSubpasses = &subpass;
			VK_CHECK_RESULT(vkCreateRenderPass(vulkanDevice->device, &renderPassInfo, nullptr, &renderPass));

			std::vector<VkImageView> attachmentViews;
			for (auto attachment : attachments)
			{
				attachmentViews.push_back(attachment.view);
			}

			// Find. max number of layers across attachments
			uint32_t maxLayers = 0;
			for (auto attachment : attachments)
			{
				if (attachment.subresourceRange.layerCount > maxLayers)
				{
					maxLayers = attachment.subresourceRange.layerCount;
				}
			}

			VkFramebufferCreateInfo framebufferInfo = {};
			framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
			framebufferInfo.renderPass = renderPass;
			framebufferInfo.pAttachments = attachmentViews.data();
			framebufferInfo.attachmentCount = static_cast<uint32_t>(attachmentViews.size());
			framebufferInfo.width = width;
			framebufferInfo.height = height;
			framebufferInfo.layers = maxLayers;
			VK_CHECK_RESULT(vkCreateFramebuffer(vulkanDevice->device, &framebufferInfo, nullptr, &framebuffer));

			return VK_SUCCESS;
		}
	};
}<|endoftext|>


<commit_before>#include "mf_movie_player.h"
#include "halley/resources/resource_data.h"
#include "halley/core/api/audio_api.h"
#include "halley/core/api/video_api.h"
#include "resource_data_byte_stream.h"
#include "halley/core/graphics/texture_descriptor.h"
#include "halley/concurrency/concurrent.h"
#include "halley/core/resources/resources.h"

using namespace Halley;

/*
#include <D3D9.h>
#pragma comment(lib, "Mfuuid.lib")
#pragma comment(lib, "Mf.lib")
#pragma comment(lib, "strmiids.lib")
*/

MFMoviePlayer::MFMoviePlayer(VideoAPI& video, AudioAPI& audio, std::shared_ptr<ResourceDataStream> data)
	: MoviePlayer(video, audio)
	, data(std::move(data))
{
	init();
}

MFMoviePlayer::~MFMoviePlayer() noexcept
{
	reset();
	deInit();
}

void MFMoviePlayer::init()
{
	inputByteStream = new ResourceDataByteStream(data);
	inputByteStream->AddRef();

	IMFAttributes* attributes = nullptr;
	HRESULT hr = MFCreateAttributes(&attributes, 1);
	if (!SUCCEEDED(hr)) {
		throw Exception("Unable to create attributes", HalleyExceptions::MoviePlugin);
	}

	/*
	constexpr bool useAsync = false;
	if (useAsync) {
		sampleReceiver = new MoviePlayerSampleReceiver(*this);
		sampleReceiver->AddRef();
		attributes->SetUnknown(MF_SOURCE_READER_ASYNC_CALLBACK, sampleReceiver);
	}
	*/

	// DX11 acceleration
	IMFDXGIDeviceManager* deviceManager = nullptr;
	/*
	auto dx11Device = static_cast<IUnknown*>(getVideoAPI().getImplementationPointer("ID3D11Device"));
	if (dx11Device) {
		UINT resetToken;
		hr = MFCreateDXGIDeviceManager(&resetToken, &deviceManager);
		if (!SUCCEEDED(hr)) {
			throw Exception("Unable to create DXGI Device Manager");
		}
		hr = deviceManager->ResetDevice(dx11Device, resetToken);
		if (!SUCCEEDED(hr)) {
			throw Exception("Unable to reset DXGI Device Manager with device");
		}
		attributes->SetUnknown(MF_SOURCE_READER_D3D_MANAGER, deviceManager);
	}
	*/

	hr = MFCreateSourceReaderFromByteStream(inputByteStream, attributes, &reader);
	if (!SUCCEEDED(hr)) {
		throw Exception("Unable to create source reader", HalleyExceptions::MoviePlugin);
	}

	// Release these temporaries
	if (attributes) {
		attributes->Release();
	}
	if (deviceManager) {
		deviceManager->Release();
	}

	reader->SetStreamSelection(MF_SOURCE_READER_ALL_STREAMS, false);
	reader->SetStreamSelection(MF_SOURCE_READER_FIRST_VIDEO_STREAM, true);
	reader->SetStreamSelection(MF_SOURCE_READER_FIRST_AUDIO_STREAM, true);

	// Setup the right decoding formats
	bool hasMoreStreams = true;
	for (int streamIndex = 0; hasMoreStreams; ++streamIndex) {
		streams.emplace_back();
		auto& curStream = streams.back();

		for (int mediaTypeIndex = 0; ; ++mediaTypeIndex) {
			IMFMediaType *nativeType = nullptr;
			hr = reader->GetNativeMediaType(streamIndex, mediaTypeIndex, &nativeType);

			if (hr == MF_E_INVALIDSTREAMNUMBER) {
				hasMoreStreams = false;
				break;
			} else if (hr == MF_E_NO_MORE_TYPES) {
				break;
			} else if (SUCCEEDED(hr)) {
				GUID majorType;
				GUID subType;
				IMFMediaType *targetType = nullptr;

				try {
					hr = nativeType->GetGUID(MF_MT_MAJOR_TYPE, &majorType);
					if (!SUCCEEDED(hr)) {
						throw Exception("Unable to read major type", HalleyExceptions::MoviePlugin);
					}

					MFCreateMediaType(&targetType);
					hr = targetType->SetGUID(MF_MT_MAJOR_TYPE, majorType);
					if (!SUCCEEDED(hr)) {
						throw Exception("Unable to write major type", HalleyExceptions::MoviePlugin);
					}

					if (majorType == MFMediaType_Video) {
						UINT64 frameSize;
						nativeType->GetUINT64(MF_MT_FRAME_SIZE, &frameSize);
						auto videoSize = Vector2i(int(frameSize >> 32), int(frameSize & 0xFFFFFFFFull));
						UINT64 aspectRatioRaw;
						nativeType->GetUINT64(MF_MT_PIXEL_ASPECT_RATIO, &aspectRatioRaw);
						float par = float(aspectRatioRaw >> 32) / float(aspectRatioRaw & 0xFFFFFFFFull);

						uint32_t stride;
						hr = nativeType->GetUINT32(MF_MT_DEFAULT_STRIDE, &stride);
						if (SUCCEEDED(hr)) {
							minStride = int(stride);
						} else {
							GUID subType = GUID_NULL;
							hr = nativeType->GetGUID(MF_MT_SUBTYPE, &subType);
							if (SUCCEEDED(hr)) {
								LONG tmp;
								hr = MFGetStrideForBitmapInfoHeader(subType.Data1, videoSize.x, &tmp);
								if (SUCCEEDED(hr)) {
									minStride = int(tmp);
								}
							}
						}

						setVideoSize(videoSize);
						curStream.type = MoviePlayerStreamType::Video;
						subType = MFVideoFormat_NV12; // NV12 is the only format supported by DX accelerated decoding
					} else if (majorType == MFMediaType_Audio) {
						UINT32 sampleRate;
						UINT32 numChannels;
						nativeType->GetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, &sampleRate);
						nativeType->GetUINT32(MF_MT_AUDIO_NUM_CHANNELS, &numChannels);

						curStream.type = MoviePlayerStreamType::Audio;
						subType = MFAudioFormat_PCM;
					}

					hr = targetType->SetGUID(MF_MT_SUBTYPE, subType);
					if (!SUCCEEDED(hr)) {
						throw Exception("Unable to write subtype", HalleyExceptions::MoviePlugin);
					}

					hr = reader->SetCurrentMediaType(streamIndex, nullptr, targetType);
					if (!SUCCEEDED(hr)) {
						throw Exception("Unable to set current media type", HalleyExceptions::MoviePlugin);
					}
				} catch (...) {
					if (targetType) {
						targetType->Release();
					}
					nativeType->Release();
					throw;
				}

				targetType->Release();
				nativeType->Release();
			} else {
				throw Exception("Error reading stream info", HalleyExceptions::MoviePlugin);
			}
		}
	}

	reset();
}

void MFMoviePlayer::deInit()
{
	if (sampleReceiver) {
		sampleReceiver->Release();
		sampleReceiver = nullptr;
	}
	if (reader) {
		reader->Release();
		reader = nullptr;
	}
	if (inputByteStream) {
		inputByteStream->Release();
		inputByteStream = nullptr;
	}
}

void MFMoviePlayer::requestVideoFrame()
{
	const DWORD controlFlags = 0;
	DWORD streamIndex;
	DWORD streamFlags;
	LONGLONG timestamp;
	IMFSample* sample;
	auto hr = reader->ReadSample(MF_SOURCE_READER_FIRST_VIDEO_STREAM, controlFlags, &streamIndex, &streamFlags, &timestamp, &sample);
	onReadSample(hr, streamIndex, streamFlags, timestamp, sample);
}

void MFMoviePlayer::requestAudioFrame()
{
	const DWORD controlFlags = 0;
	DWORD streamIndex;
	DWORD streamFlags;
	LONGLONG timestamp;
	IMFSample* sample;
	auto hr = reader->ReadSample(MF_SOURCE_READER_FIRST_AUDIO_STREAM, controlFlags, &streamIndex, &streamFlags, &timestamp, &sample);
	onReadSample(hr, streamIndex, streamFlags, timestamp, sample);
}

void MFMoviePlayer::onReset()
{
	PROPVARIANT pos;
	pos.vt = VT_I8;
	pos.hVal.QuadPart = 0;
	reader->SetCurrentPosition(GUID_NULL, pos);
}

HRESULT MFMoviePlayer::onReadSample(HRESULT hr, DWORD streamIndex, DWORD streamFlags, LONGLONG timestamp, IMFSample* sample)
{
	auto& curStream = streams.at(streamIndex);
	if (streamFlags & MF_SOURCE_READERF_ENDOFSTREAM) {
		curStream.eof = true;
	}

	if (sample) {
		Time sampleTime = Time(timestamp) / 10000000.0;

		DWORD bufferCount;
		sample->GetBufferCount(&bufferCount);
		for (int i = 0; i < int(bufferCount); ++i) {
			IMFMediaBuffer* buffer;
			sample->GetBufferByIndex(i, &buffer);
			DWORD length;
			buffer->GetCurrentLength(&length);

			if (curStream.type == MoviePlayerStreamType::Video) {
				/*
				IDirect3DSurface9 *surface = nullptr;
				auto hr = MFGetService(buffer, MR_BUFFER_SERVICE, __uuidof(IDirect3DSurface9), reinterpret_cast<void**>(&surface));
				if (SUCCEEDED(hr)) {
					std::cout << Release();
				}"Got DX9 surface!\n";
				surface->Release();
				*/

				IMF2DBuffer* buffer2d = nullptr;
				hr = buffer->QueryInterface(__uuidof(IMF2DBuffer), reinterpret_cast<void**>(&buffer2d));
				if (SUCCEEDED(hr)) {
					BYTE* src;
					LONG pitch;
					buffer2d->Lock2D(&src, &pitch);
					readVideoSample(sampleTime, reinterpret_cast<gsl::byte*>(src), pitch);
					buffer2d->Unlock2D();
					buffer2d->Release();
				} else if (hr == E_NOINTERFACE) {
					BYTE* src;
					DWORD maxLen;
					DWORD curLen;
					buffer->Lock(&src, &maxLen, &curLen);
					readVideoSample(sampleTime, reinterpret_cast<gsl::byte*>(src), minStride);
					buffer->Unlock();
					buffer->Release();
				} else {
					throw Exception("Error while querying for 2D buffer: " + toString(hr), HalleyExceptions::MoviePlugin);
				}
			}

			if (curStream.type == MoviePlayerStreamType::Audio) {
				BYTE* data;
				DWORD maxLen;
				DWORD curLen;
				buffer->Lock(&data, &maxLen, &curLen);
				readAudioSample(sampleTime, gsl::as_bytes(gsl::span<const BYTE>(data, curLen)));
				buffer->Unlock();
			}

			buffer->Release();
		}

		sample->Release();
	}

	return S_OK;
}

void MFMoviePlayer::readVideoSample(Time time, const gsl::byte* data, int stride)
{
	const auto videoSize = getSize();
	const int yPlaneHeight = alignUp(videoSize.y, 16);
	const int uvPlaneHeight = alignUp(videoSize.y / 2, 16);
	const int width = alignUp(videoSize.x, 16);
	const int height = yPlaneHeight + uvPlaneHeight;

	auto srcData = gsl::span<const gsl::byte>(data, stride * height);
	Bytes myData(srcData.size_bytes());
	memcpy(myData.data(), data, myData.size());

	TextureDescriptor descriptor;
	descriptor.format = TextureFormat::Indexed;
	descriptor.pixelFormat = PixelDataFormat::Image;
	descriptor.size = Vector2i(width, height);
	descriptor.pixelData = TextureDescriptorImageData(std::move(myData), stride);

	onVideoFrameAvailable(time, std::move(descriptor));
}

void MFMoviePlayer::readAudioSample(Time time, gsl::span<const gsl::byte> data)
{
	auto src = gsl::span<const short>(reinterpret_cast<const short*>(data.data()), data.size() / sizeof(short));

	std::vector<AudioConfig::SampleFormat> samples(src.size());
	for (int i = 0; i < src.size(); ++i) {
		samples[i] = src[i] / 32768.0f;
	}

	onAudioFrameAvailable(time, samples);
}
<commit_msg>Fix UWP<commit_after>#include "mf_movie_player.h"
#include "halley/resources/resource_data.h"
#include "halley/core/api/audio_api.h"
#include "halley/core/api/video_api.h"
#include "resource_data_byte_stream.h"
#include "halley/core/graphics/texture_descriptor.h"
#include "halley/concurrency/concurrent.h"
#include "halley/core/resources/resources.h"

using namespace Halley;

/*
#include <D3D9.h>
#pragma comment(lib, "Mfuuid.lib")
#pragma comment(lib, "Mf.lib")
#pragma comment(lib, "strmiids.lib")
*/

MFMoviePlayer::MFMoviePlayer(VideoAPI& video, AudioAPI& audio, std::shared_ptr<ResourceDataStream> data)
	: MoviePlayer(video, audio)
	, data(std::move(data))
{
	init();
}

MFMoviePlayer::~MFMoviePlayer() noexcept
{
	reset();
	deInit();
}

void MFMoviePlayer::init()
{
	inputByteStream = new ResourceDataByteStream(data);
	inputByteStream->AddRef();

	IMFAttributes* attributes = nullptr;
	HRESULT hr = MFCreateAttributes(&attributes, 1);
	if (!SUCCEEDED(hr)) {
		throw Exception("Unable to create attributes", HalleyExceptions::MoviePlugin);
	}

	/*
	constexpr bool useAsync = false;
	if (useAsync) {
		sampleReceiver = new MoviePlayerSampleReceiver(*this);
		sampleReceiver->AddRef();
		attributes->SetUnknown(MF_SOURCE_READER_ASYNC_CALLBACK, sampleReceiver);
	}
	*/

	// DX11 acceleration
	IMFDXGIDeviceManager* deviceManager = nullptr;
	/*
	auto dx11Device = static_cast<IUnknown*>(getVideoAPI().getImplementationPointer("ID3D11Device"));
	if (dx11Device) {
		UINT resetToken;
		hr = MFCreateDXGIDeviceManager(&resetToken, &deviceManager);
		if (!SUCCEEDED(hr)) {
			throw Exception("Unable to create DXGI Device Manager");
		}
		hr = deviceManager->ResetDevice(dx11Device, resetToken);
		if (!SUCCEEDED(hr)) {
			throw Exception("Unable to reset DXGI Device Manager with device");
		}
		attributes->SetUnknown(MF_SOURCE_READER_D3D_MANAGER, deviceManager);
	}
	*/

	hr = MFCreateSourceReaderFromByteStream(inputByteStream, attributes, &reader);
	if (!SUCCEEDED(hr)) {
		throw Exception("Unable to create source reader", HalleyExceptions::MoviePlugin);
	}

	// Release these temporaries
	if (attributes) {
		attributes->Release();
	}
	if (deviceManager) {
		deviceManager->Release();
	}

	reader->SetStreamSelection(MF_SOURCE_READER_ALL_STREAMS, false);
	reader->SetStreamSelection(MF_SOURCE_READER_FIRST_VIDEO_STREAM, true);
	reader->SetStreamSelection(MF_SOURCE_READER_FIRST_AUDIO_STREAM, true);

	// Setup the right decoding formats
	bool hasMoreStreams = true;
	for (int streamIndex = 0; hasMoreStreams; ++streamIndex) {
		streams.emplace_back();
		auto& curStream = streams.back();

		for (int mediaTypeIndex = 0; ; ++mediaTypeIndex) {
			IMFMediaType *nativeType = nullptr;
			hr = reader->GetNativeMediaType(streamIndex, mediaTypeIndex, &nativeType);

			if (hr == MF_E_INVALIDSTREAMNUMBER) {
				hasMoreStreams = false;
				break;
			} else if (hr == MF_E_NO_MORE_TYPES) {
				break;
			} else if (SUCCEEDED(hr)) {
				GUID majorType;
				GUID subType;
				IMFMediaType *targetType = nullptr;

				try {
					hr = nativeType->GetGUID(MF_MT_MAJOR_TYPE, &majorType);
					if (!SUCCEEDED(hr)) {
						throw Exception("Unable to read major type", HalleyExceptions::MoviePlugin);
					}

					MFCreateMediaType(&targetType);
					hr = targetType->SetGUID(MF_MT_MAJOR_TYPE, majorType);
					if (!SUCCEEDED(hr)) {
						throw Exception("Unable to write major type", HalleyExceptions::MoviePlugin);
					}

					if (majorType == MFMediaType_Video) {
						UINT64 frameSize;
						nativeType->GetUINT64(MF_MT_FRAME_SIZE, &frameSize);
						auto videoSize = Vector2i(int(frameSize >> 32), int(frameSize & 0xFFFFFFFFull));
						UINT64 aspectRatioRaw;
						nativeType->GetUINT64(MF_MT_PIXEL_ASPECT_RATIO, &aspectRatioRaw);
						float par = float(aspectRatioRaw >> 32) / float(aspectRatioRaw & 0xFFFFFFFFull);

						uint32_t stride;
						hr = nativeType->GetUINT32(MF_MT_DEFAULT_STRIDE, &stride);
						if (SUCCEEDED(hr)) {
							minStride = int(stride);
						} else {
#ifndef WINDOWS_STORE
							GUID subType = GUID_NULL;
							hr = nativeType->GetGUID(MF_MT_SUBTYPE, &subType);
							if (SUCCEEDED(hr)) {
								LONG tmp;
								hr = MFGetStrideForBitmapInfoHeader(subType.Data1, videoSize.x, &tmp);
								if (SUCCEEDED(hr)) {
									minStride = int(tmp);
								}
							}
#endif
						}

						setVideoSize(videoSize);
						curStream.type = MoviePlayerStreamType::Video;
						subType = MFVideoFormat_NV12; // NV12 is the only format supported by DX accelerated decoding
					} else if (majorType == MFMediaType_Audio) {
						UINT32 sampleRate;
						UINT32 numChannels;
						nativeType->GetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, &sampleRate);
						nativeType->GetUINT32(MF_MT_AUDIO_NUM_CHANNELS, &numChannels);

						curStream.type = MoviePlayerStreamType::Audio;
						subType = MFAudioFormat_PCM;
					}

					hr = targetType->SetGUID(MF_MT_SUBTYPE, subType);
					if (!SUCCEEDED(hr)) {
						throw Exception("Unable to write subtype", HalleyExceptions::MoviePlugin);
					}

					hr = reader->SetCurrentMediaType(streamIndex, nullptr, targetType);
					if (!SUCCEEDED(hr)) {
						throw Exception("Unable to set current media type", HalleyExceptions::MoviePlugin);
					}
				} catch (...) {
					if (targetType) {
						targetType->Release();
					}
					nativeType->Release();
					throw;
				}

				targetType->Release();
				nativeType->Release();
			} else {
				throw Exception("Error reading stream info", HalleyExceptions::MoviePlugin);
			}
		}
	}

	reset();
}

void MFMoviePlayer::deInit()
{
	if (sampleReceiver) {
		sampleReceiver->Release();
		sampleReceiver = nullptr;
	}
	if (reader) {
		reader->Release();
		reader = nullptr;
	}
	if (inputByteStream) {
		inputByteStream->Release();
		inputByteStream = nullptr;
	}
}

void MFMoviePlayer::requestVideoFrame()
{
	const DWORD controlFlags = 0;
	DWORD streamIndex;
	DWORD streamFlags;
	LONGLONG timestamp;
	IMFSample* sample;
	auto hr = reader->ReadSample(MF_SOURCE_READER_FIRST_VIDEO_STREAM, controlFlags, &streamIndex, &streamFlags, &timestamp, &sample);
	onReadSample(hr, streamIndex, streamFlags, timestamp, sample);
}

void MFMoviePlayer::requestAudioFrame()
{
	const DWORD controlFlags = 0;
	DWORD streamIndex;
	DWORD streamFlags;
	LONGLONG timestamp;
	IMFSample* sample;
	auto hr = reader->ReadSample(MF_SOURCE_READER_FIRST_AUDIO_STREAM, controlFlags, &streamIndex, &streamFlags, &timestamp, &sample);
	onReadSample(hr, streamIndex, streamFlags, timestamp, sample);
}

void MFMoviePlayer::onReset()
{
	PROPVARIANT pos;
	pos.vt = VT_I8;
	pos.hVal.QuadPart = 0;
	reader->SetCurrentPosition(GUID_NULL, pos);
}

HRESULT MFMoviePlayer::onReadSample(HRESULT hr, DWORD streamIndex, DWORD streamFlags, LONGLONG timestamp, IMFSample* sample)
{
	auto& curStream = streams.at(streamIndex);
	if (streamFlags & MF_SOURCE_READERF_ENDOFSTREAM) {
		curStream.eof = true;
	}

	if (sample) {
		Time sampleTime = Time(timestamp) / 10000000.0;

		DWORD bufferCount;
		sample->GetBufferCount(&bufferCount);
		for (int i = 0; i < int(bufferCount); ++i) {
			IMFMediaBuffer* buffer;
			sample->GetBufferByIndex(i, &buffer);
			DWORD length;
			buffer->GetCurrentLength(&length);

			if (curStream.type == MoviePlayerStreamType::Video) {
				/*
				IDirect3DSurface9 *surface = nullptr;
				auto hr = MFGetService(buffer, MR_BUFFER_SERVICE, __uuidof(IDirect3DSurface9), reinterpret_cast<void**>(&surface));
				if (SUCCEEDED(hr)) {
					std::cout << Release();
				}"Got DX9 surface!\n";
				surface->Release();
				*/

				IMF2DBuffer* buffer2d = nullptr;
				hr = buffer->QueryInterface(__uuidof(IMF2DBuffer), reinterpret_cast<void**>(&buffer2d));
				if (SUCCEEDED(hr)) {
					BYTE* src;
					LONG pitch;
					buffer2d->Lock2D(&src, &pitch);
					readVideoSample(sampleTime, reinterpret_cast<gsl::byte*>(src), pitch);
					buffer2d->Unlock2D();
					buffer2d->Release();
				} else if (hr == E_NOINTERFACE) {
					BYTE* src;
					DWORD maxLen;
					DWORD curLen;
					buffer->Lock(&src, &maxLen, &curLen);
					readVideoSample(sampleTime, reinterpret_cast<gsl::byte*>(src), minStride);
					buffer->Unlock();
					buffer->Release();
				} else {
					throw Exception("Error while querying for 2D buffer: " + toString(hr), HalleyExceptions::MoviePlugin);
				}
			}

			if (curStream.type == MoviePlayerStreamType::Audio) {
				BYTE* data;
				DWORD maxLen;
				DWORD curLen;
				buffer->Lock(&data, &maxLen, &curLen);
				readAudioSample(sampleTime, gsl::as_bytes(gsl::span<const BYTE>(data, curLen)));
				buffer->Unlock();
			}

			buffer->Release();
		}

		sample->Release();
	}

	return S_OK;
}

void MFMoviePlayer::readVideoSample(Time time, const gsl::byte* data, int stride)
{
	const auto videoSize = getSize();
	const int yPlaneHeight = alignUp(videoSize.y, 16);
	const int uvPlaneHeight = alignUp(videoSize.y / 2, 16);
	const int width = alignUp(videoSize.x, 16);
	const int height = yPlaneHeight + uvPlaneHeight;

	auto srcData = gsl::span<const gsl::byte>(data, stride * height);
	Bytes myData(srcData.size_bytes());
	memcpy(myData.data(), data, myData.size());

	TextureDescriptor descriptor;
	descriptor.format = TextureFormat::Indexed;
	descriptor.pixelFormat = PixelDataFormat::Image;
	descriptor.size = Vector2i(width, height);
	descriptor.pixelData = TextureDescriptorImageData(std::move(myData), stride);

	onVideoFrameAvailable(time, std::move(descriptor));
}

void MFMoviePlayer::readAudioSample(Time time, gsl::span<const gsl::byte> data)
{
	auto src = gsl::span<const short>(reinterpret_cast<const short*>(data.data()), data.size() / sizeof(short));

	std::vector<AudioConfig::SampleFormat> samples(src.size());
	for (int i = 0; i < src.size(); ++i) {
		samples[i] = src[i] / 32768.0f;
	}

	onAudioFrameAvailable(time, samples);
}
<|endoftext|>