///////////////////////////////////////////////////////////////////////////
//
//  CSensorDdi::PostDataEvent
//
//  This method is called to post a new data event to the class extension.
//
//  Parameters:
//      SensorId - the SensorId with event
//      pDataValues - data values to post
//
//  Return Value:
//      status
//
///////////////////////////////////////////////////////////////////////////
HRESULT CSensorDdi::PostDataEvent(_In_ LPWSTR SensorId, _In_ IPortableDeviceValues* pDataValues)
{
    ComPtr<IPortableDeviceValuesCollection> spCollection;
    HRESULT hr = CoCreateInstance(
        CLSID_PortableDeviceValuesCollection,
        NULL,
        CLSCTX_INPROC_SERVER,
        IID_PPV_ARGS(&spCollection));

    if (SUCCEEDED(hr))
    {
        hr = spCollection->Add(pDataValues);

        if (SUCCEEDED(hr))
        {
            hr = m_spClassExtension->PostEvent(SensorId, spCollection.Get());
        }
    }

    if (FAILED(hr))
    {
        Trace(TRACE_LEVEL_ERROR, "Failed to post data event, %!HRESULT!", hr);
    }

    return hr;
}
bool ff::OptimizeSprites(ISpriteList *pSprites, DXGI_FORMAT format, size_t nMipMapLevels, ISpriteList **ppOptimizedSprites)
{
	assertRetVal(pSprites && ppOptimizedSprites, false);

	// Create the return value
	ComPtr<ISpriteList> pNewSprites;
	assertRetVal(CreateSpriteList(pSprites->GetDevice(), &pNewSprites), false);

	// Cache all the sprites
	Vector<OptimizedSpriteInfo> sprites;
	sprites.Reserve(pSprites->GetCount());

	for (size_t i = 0; i < pSprites->GetCount(); i++)
	{
		OptimizedSpriteInfo sprite(pSprites->Get(i), i);
		sprites.Push(sprite);
	}

	// Sort the sprites by size
	if (!sprites.IsEmpty())
	{
		qsort(sprites.Data(), sprites.Size(), sizeof(OptimizedSpriteInfo), CompareSpriteInfo);
	}

	// Figure out how many textures to create
	Vector<OptimizedTextureInfo> textureInfos;
	Vector<ComPtr<IGraphTexture>> textures;
	Vector<ComPtr<IGraphTexture>> finalTextures;
	Vector<std::shared_ptr<DirectX::ScratchImage>> alphaTextures;

	assertRetVal(ComputeOptimizedSprites(sprites, textureInfos), false);
	assertRetVal(CreateOptimizedTextures(format, pSprites->GetDevice(), textureInfos, textures), false);

	if (!sprites.IsEmpty())
	{
		qsort(sprites.Data(), sprites.Size(), sizeof(OptimizedSpriteInfo), CompareSpriteInfoIndex);
	}

	assertRetVal(CopyOptimizedSprites(sprites, textures), false);
	assertRetVal(ConvertOptimizedTextures(format, nMipMapLevels, textures, finalTextures, alphaTextures), false);

	// Create final sprites
	for (size_t i = 0; i < sprites.Size(); i++)
	{
		OptimizedSpriteInfo &sprite = sprites[i];
		const SpriteData &data = sprite._sprite->GetSpriteData();
		SpriteType type = UpdateSpriteType(sprite, *alphaTextures[sprite._destTexture]);

		assertRetVal(pNewSprites->Add(
			finalTextures[sprite._destTexture],
			data._name,
			sprite._destRect.ToFloat(),
			sprite._srcHandle,
			sprite._srcScale,
			type), false);
	}

	*ppOptimizedSprites = pNewSprites.Detach();
	return true;
}
 virtual RegisteredEvent AddSurfaceContentsLostCallback(IEventHandler<IInspectable*>* value) override
 {
     return SurfaceContentsLostEventSource->Add(value);
 }