/**
 * @fn Resize (int w, int h)
 *
 * @brief Resizes the render target, creates new textures and views 
 *
 * @param w - New resource width
 *
 * @param h - New resource height
 */
void CDXRenderTarget::Resize(int resW, int resH)
{
    HRESULT hr;

    SAFE_RELEASE(m_pSRV);
    SAFE_RELEASE(m_pRTV);
    SAFE_RELEASE(m_pTexture);
    SAFE_RELEASE(m_pTextureCPU); 
    
    // Save the new values
    m_width = resW;
    m_height = resH;

    // Get the device
    ID3D10Device *pDev = DXUTGetD3D10Device();

    // Create the texture here
    CD3D10_TEXTURE2D_DESC desc(m_fmt, resW, resH, 1, 1);
    desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
    desc.Usage     = D3D10_USAGE_DEFAULT;
    hr = pDev->CreateTexture2D(&desc, NULL, &m_pTexture);
    assert(hr == S_OK);

    // Create the CPU version of the texture here
    CD3D10_TEXTURE2D_DESC descCPU(m_fmt, resW, resH, 1, 1);
    descCPU.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
    descCPU.Usage          = D3D10_USAGE_DYNAMIC;
    hr = pDev->CreateTexture2D(&descCPU, NULL, &m_pTextureCPU);
    assert(hr == S_OK);

    // Create the shader resource view
    D3D10_SHADER_RESOURCE_VIEW_DESC resDesc;
    resDesc.Format = m_fmt;
    resDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D;
    resDesc.Texture2D.MipLevels = 1;
    resDesc.Texture2D.MostDetailedMip = 0;
    hr = pDev->CreateShaderResourceView(m_pTexture, &resDesc, &m_pSRV);
    assert(hr == S_OK);

    // Create the render target view
    D3D10_RENDER_TARGET_VIEW_DESC rtDesc;
    rtDesc.Format = m_fmt;
    rtDesc.ViewDimension = D3D10_RTV_DIMENSION_TEXTURE2D;
    rtDesc.Texture2D.MipSlice = 0;
    
    hr = pDev->CreateRenderTargetView(m_pTexture, &rtDesc, &m_pRTV);
    assert(hr == S_OK);

} // End of resize()
Exemple #2
0
bool
TextureClientD3D11::AllocateForSurface(gfx::IntSize aSize, TextureAllocationFlags aFlags)
{
  mSize = aSize;
  ID3D10Device* device = gfxWindowsPlatform::GetPlatform()->GetD3D10Device();

  CD3D10_TEXTURE2D_DESC newDesc(DXGI_FORMAT_B8G8R8A8_UNORM,
                                aSize.width, aSize.height, 1, 1,
                                D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE);

  newDesc.MiscFlags = D3D10_RESOURCE_MISC_SHARED_KEYEDMUTEX;

  HRESULT hr = device->CreateTexture2D(&newDesc, nullptr, byRef(mTexture));

  if (FAILED(hr)) {
    LOGD3D11("Error creating texture for client!");
    return false;
  }

  // Defer clearing to the next time we lock to avoid an extra (expensive) lock.
  mNeedsClear = aFlags & ALLOC_CLEAR_BUFFER;
  mNeedsClearWhite = aFlags & ALLOC_CLEAR_BUFFER_WHITE;

  return true;
}
static bool grabFrameD3D10(IDXGISwapChain *swap)
{
  ID3D10Device *device = 0;
  ID3D10Texture2D *tex = 0, *captureTex = 0;

  if (FAILED(swap->GetBuffer(0, IID_ID3D10Texture2D, (void**)&tex)))
    return false;

  D3D10_TEXTURE2D_DESC desc;
  tex->GetDevice(&device);
  tex->GetDesc(&desc);

  // re-creating the capture staging texture each frame is definitely not the most efficient
  // way to handle things, but it frees me of all kind of resource management trouble, so
  // here goes...
  desc.MipLevels = 1;
  desc.ArraySize = 1;
  desc.SampleDesc.Count = 1;
  desc.SampleDesc.Quality = 0;
  desc.Usage = D3D10_USAGE_STAGING;
  desc.BindFlags = 0;
  desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ;
  desc.MiscFlags = 0;

  if(FAILED(device->CreateTexture2D(&desc,0,&captureTex)))
    printLog("video/d3d10: couldn't create staging texture for gpu->cpu download!\n");
  else
    setCaptureResolution(desc.Width,desc.Height);

  if(device)
    device->CopySubresourceRegion(captureTex,0,0,0,0,tex,0,0);

  D3D10_MAPPED_TEXTURE2D mapped;
  bool grabOk = false;

  if(captureTex && SUCCEEDED(captureTex->Map(0,D3D10_MAP_READ,0,&mapped)))
  {
    switch(desc.Format)
    {
    case DXGI_FORMAT_R8G8B8A8_UNORM:
      blitAndFlipRGBAToCaptureData((unsigned char *) mapped.pData,mapped.RowPitch);
      grabOk = true;
      break;

    default:
      printLog("video/d3d10: unsupported backbuffer format, can't grab pixels!\n");
      break;
    }

    captureTex->Unmap(0);
  }

  tex->Release();
  if(captureTex) captureTex->Release();
  if(device) device->Release();

  return grabOk;
}
void
TextureClientD3D11::Unlock()
{
  MOZ_ASSERT(mIsLocked, "Unlocked called while the texture is not locked!");
  if (!mIsLocked) {
    return;
  }

  if (mDrawTarget) {
    // see the comment on TextureClient::BorrowDrawTarget.
    // This DrawTarget is internal to the TextureClient and is only exposed to the
    // outside world between Lock() and Unlock(). This assertion checks that no outside
    // reference remains by the time Unlock() is called.
    MOZ_ASSERT(mDrawTarget->refCount() == 1);
    mDrawTarget->Flush();
  }

  if (mReadbackSink && mTexture10) {
    ID3D10Device* device = gfxWindowsPlatform::GetPlatform()->GetD3D10Device();

    D3D10_TEXTURE2D_DESC desc;
    mTexture10->GetDesc(&desc);
    desc.BindFlags = 0;
    desc.Usage = D3D10_USAGE_STAGING;
    desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ;
    desc.MiscFlags = 0;

    RefPtr<ID3D10Texture2D> tex;
    HRESULT hr = device->CreateTexture2D(&desc, nullptr, byRef(tex));

    if (FAILED(hr)) {
      gfxCriticalError(CriticalLog::DefaultOptions(Factory::ReasonableSurfaceSize(mSize))) << "[D3D11] CreateTexture2D failure " << mSize << " Code: " << gfx::hexa(hr);
      return;
    }

    if (SUCCEEDED(hr)) {
      device->CopyResource(tex, mTexture10);

      gfxWindowsPlatform::GetPlatform()->GetReadbackManager()->PostTask(tex, mReadbackSink);
    } else {
      mReadbackSink->ProcessReadback(nullptr);
    }
  }

  // The DrawTarget is created only once, and is only usable between calls
  // to Lock and Unlock.
  if (mTexture) {
    UnlockD3DTexture(mTexture.get());
  } else {
    UnlockD3DTexture(mTexture10.get());
  }
  mIsLocked = false;
}
Exemple #5
0
bool
DeprecatedTextureClientD3D11::EnsureAllocated(gfx::IntSize aSize,
        gfxContentType aType)
{
    D3D10_TEXTURE2D_DESC desc;

    if (mTexture) {
        mTexture->GetDesc(&desc);

        if (desc.Width == aSize.width && desc.Height == aSize.height) {
            return true;
        }

        mTexture = nullptr;
        mSurface = nullptr;
        ClearDT();
    }

    mSize = aSize;

    ID3D10Device* device = gfxWindowsPlatform::GetPlatform()->GetD3D10Device();

    CD3D10_TEXTURE2D_DESC newDesc(DXGI_FORMAT_B8G8R8A8_UNORM,
                                  aSize.width, aSize.height, 1, 1,
                                  D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE);

    newDesc.MiscFlags = D3D10_RESOURCE_MISC_SHARED_KEYEDMUTEX;

    HRESULT hr = device->CreateTexture2D(&newDesc, nullptr, byRef(mTexture));

    if (FAILED(hr)) {
        LOGD3D11("Error creating texture for client!");
        return false;
    }

    RefPtr<IDXGIResource> resource;
    mTexture->QueryInterface((IDXGIResource**)byRef(resource));

    HANDLE sharedHandle;
    hr = resource->GetSharedHandle(&sharedHandle);

    if (FAILED(hr)) {
        LOGD3D11("Error getting shared handle for texture.");
        return false;
    }

    mDescriptor = SurfaceDescriptorD3D10((WindowsHandle)sharedHandle,
                                         aType == GFX_CONTENT_COLOR_ALPHA);

    mContentType = aType;
    return true;
}
Exemple #6
0
void D10State::newTexture(unsigned int w, unsigned int h) {
	HRESULT hr;

	ods("D3D10: newTexture %d %d", w, h);

	if (pTexture) {
		pTexture->Release();
		pTexture = NULL;
	}
	if (pSRView) {
		pSRView->Release();
		pSRView = NULL;
	}

	D3D10_TEXTURE2D_DESC desc;
	ZeroMemory(&desc, sizeof(desc));

	desc.Width = w;
	desc.Height = h;
	desc.MipLevels = desc.ArraySize = 1;
	desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
	desc.SampleDesc.Count = 1;
	desc.Usage = D3D10_USAGE_DYNAMIC;
	desc.BindFlags = D3D10_BIND_SHADER_RESOURCE;
	desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
	hr = pDevice->CreateTexture2D(&desc, NULL, &pTexture);

	if (FAILED(hr)) {
		pTexture = NULL;
		ods("D3D10: Failed to create texture.");
		return;
	}

	D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc;
	ZeroMemory(&srvDesc, sizeof(srvDesc));
	srvDesc.Format = desc.Format;
	srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D;
	srvDesc.Texture2D.MostDetailedMip = 0;
	srvDesc.Texture2D.MipLevels = desc.MipLevels;

	hr = pDevice->CreateShaderResourceView(pTexture, &srvDesc, &pSRView);
	if (FAILED(hr)) {
		pSRView = NULL;
		pTexture->Release();
		pTexture = NULL;
		ods("D3D10: Failed to create resource view.");
		return;
	}
}
Exemple #7
0
void D3D10Texture::Allocate(UINT Width, UINT Height, bool ConstructMipmaps, DXGI_FORMAT Format, const Bitmap &Bmp)
{
    FreeMemory();
    PersistentAssert(_GD != NULL, "D3D10Texture::Allocate on unassociated texture");
    ID3D10Device* Device = _GD->CastD3D10().GetDevice();

    D3D10_TEXTURE2D_DESC TextureDesc;
    TextureDesc.Width = Width;
    TextureDesc.Height = Height;
    TextureDesc.MipLevels = 0;
    if(!ConstructMipmaps)
    {
        TextureDesc.MipLevels = 1;
    }
    TextureDesc.ArraySize = 1;
    TextureDesc.Format = Format;
    TextureDesc.SampleDesc.Count = 1;
    TextureDesc.SampleDesc.Quality = 0;
    TextureDesc.Usage = D3D10_USAGE_DEFAULT;
    TextureDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE | D3D10_BIND_RENDER_TARGET;
    TextureDesc.CPUAccessFlags = 0;
    TextureDesc.MiscFlags = D3D10_RESOURCE_MISC_GENERATE_MIPS;

    D3D10_SUBRESOURCE_DATA Data[12];
    for(UINT Index = 0; Index < 12; Index++)
    {
        Data[Index].pSysMem = &(Bmp[0][0]);
        Data[Index].SysMemPitch = Bmp.Width() * sizeof(RGBColor);
    }

    HRESULT hr = Device->CreateTexture2D(&TextureDesc, Data, &_Texture);
    PersistentAssert(SUCCEEDED(hr), "CreateTexture2D failed");

    _Texture->GetDesc(&TextureDesc);

    D3D10_SHADER_RESOURCE_VIEW_DESC ViewDesc;
    ViewDesc.Format = Format;
    ViewDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D;
    ViewDesc.Texture2D.MostDetailedMip = 0;
    ViewDesc.Texture2D.MipLevels = TextureDesc.MipLevels;

    hr = Device->CreateShaderResourceView(_Texture, &ViewDesc, &_View);
    PersistentAssert(SUCCEEDED(hr), "CreateShaderResourceView failed");

    Device->GenerateMips(_View);
}
		Texture2D::Texture2D(Texture2D_Desc& desc, Renderer* pRender)
		{
			HRESULT hr;
			ID3D10Device* pDevice = pRender->GetDevice();

			V(pDevice->CreateTexture2D(
				&desc,		//[in]   const D3D10_TEXTURE2D_DESC *pDesc,
				NULL,		//[in]   const D3D10_SUBRESOURCE_DATA *pInitialData,
				&_ptr		//[out]  ID3D10Texture2D **ppTexture2D
				));

			if (SUCCEEDED(hr)) {
				_width = (float)desc.Width;
				_height = (float)desc.Height;
				_invW = 1.0f / _width;
				_invH = 1.0f / _height;

				D3D10_SHADER_RESOURCE_VIEW_DESC resourceViewDesc;
				resourceViewDesc.Format = desc.Format;
				resourceViewDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D;
				resourceViewDesc.Texture2D.MostDetailedMip = 0;
				resourceViewDesc.Texture2D.MipLevels = desc.MipLevels;

				ID3D10ShaderResourceView* pResourceView;
				V(pDevice->CreateShaderResourceView(
					(ID3D10Resource *)_ptr,		//[in]   ID3D10Resource *pResource,
					&resourceViewDesc,			//[in]   const D3D10_SHADER_RESOURCE_VIEW_DESC *pDesc,
					&pResourceView				//[out]  ID3D10ShaderResourceView **ppSRView
					));
				if (SUCCEEDED(hr)) {
					_ResourceView = pResourceView;
				}
			}
			else {
				_ptr = NULL;
				_width = 0;
				_height = 0;
				_invW = 0;
				_invH = 0;
			}
		}
Exemple #9
0
bool CGutFontUniCodeDX10::CreateTexture(int w, int h)
{
	m_iTextureW = w;
	m_iTextureH = h;

	ID3D10Device *pDevice = GutGetGraphicsDeviceDX10();
	//
	{
		D3D10_TEXTURE2D_DESC desc;
		ZeroMemory( &desc, sizeof(desc) );

		desc.Width =  w;
		desc.Height =  h;
		desc.MipLevels = 1;
		desc.ArraySize = 1;
		desc.SampleDesc.Count = 1;
		desc.Format = DXGI_FORMAT_A8_UNORM;
		desc.Usage = D3D10_USAGE_DEFAULT;
		desc.BindFlags = D3D10_BIND_SHADER_RESOURCE;

		pDevice->CreateTexture2D( &desc, NULL, &m_pFontTexture2D );
	}
	//
	{
		D3D10_SHADER_RESOURCE_VIEW_DESC desc;
		ZeroMemory(&desc, sizeof(desc));

		desc.Format = DXGI_FORMAT_A8_UNORM;
		desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D;
		desc.Texture2D.MostDetailedMip = 0;
		desc.Texture2D.MipLevels = 1;

		pDevice->CreateShaderResourceView(m_pFontTexture2D, &desc, &m_pFontTexture);
	}

	return true;
}
// Detour function that replaces the IDXGISwapChain::Present() API
DllExport HRESULT __stdcall
hook_DXGISwapChainPresent(
		IDXGISwapChain * This,
		UINT SyncInterval,
		UINT Flags
	)
{
	static int frame_interval;
	static LARGE_INTEGER initialTv, captureTv, freq;
	static int capture_initialized = 0;
	//
	int i;
	struct pooldata *data;
	struct vsource_frame *frame;
	//
	DXGI_SWAP_CHAIN_DESC pDESC;
	HRESULT hr = pDXGISwapChainPresent(This, SyncInterval, Flags);	
		
	if(resolution_retrieved == 0) {
		if(DXGI_get_resolution(This) >= 0) {
			resolution_retrieved = 1;
		}
		return hr;
	}
	
	if(vsource_initialized == 0) {
		ga_error("video source not initialized.\n");
		return hr;
	}
	
	This->GetDesc(&pDESC);
	pDXGI_FORMAT = pDESC.BufferDesc.Format;   // extract screen format for sws_scale
	
	if(pDESC.BufferDesc.Width != game_width
	|| pDESC.BufferDesc.Height != game_height) {
		ga_error("game width/height mismatched (%dx%d) != (%dx%d)\n",
			pDESC.BufferDesc.Width, pDESC.BufferDesc.Height,
			game_width, game_height);
		return hr;
	}
	
	//
	if (enable_server_rate_control && ga_hook_video_rate_control() < 0)
		return hr;
	
	if (dx_version == dx_none) {
		//bool check_result = FALSE;
		if (check_dx_device_version(This, IID_ID3D10Device)) {
			dx_version = dx_10;
			ga_error("[DXGISwapChain] DirectX 10\n");
		} else if (check_dx_device_version(This, IID_ID3D10Device1)) {
			dx_version = dx_10_1;
			ga_error("[DXGISwapChain] DirectX 10.1\n");
		} else if (check_dx_device_version(This, IID_ID3D11Device)) {
			dx_version = dx_11;
			ga_error("[DXGISwapChain] DirectX 11\n");
		}
	}
	
	if (capture_initialized == 0) {
		frame_interval = 1000000/video_fps; // in the unif of us
		frame_interval++;
		QueryPerformanceFrequency(&freq);
		QueryPerformanceCounter(&initialTv);
		capture_initialized = 1;
	} else {
		QueryPerformanceCounter(&captureTv);
	}

	hr = 0;

	// d3d10 / d3d10.1
	if (dx_version == dx_10 || dx_version == dx_10_1) {
		
		void *ppDevice;	
		ID3D10Device *pDevice;
		//IUnknown *pDevice;

		if (dx_version == dx_10) {
			This->GetDevice(IID_ID3D10Device, &ppDevice);
			pDevice = (ID3D10Device *)ppDevice;
		} else if (dx_version == dx_10_1) {
			This->GetDevice(IID_ID3D10Device1, &ppDevice);
			pDevice = (ID3D10Device1 *)ppDevice;
		} else {
			OutputDebugString("Invalid DirectX version in IDXGISwapChain::Present");
			return hr;
		}

		ID3D10RenderTargetView *pRTV = NULL;
		ID3D10Resource *pSrcResource = NULL;
		pDevice->OMGetRenderTargets(1, &pRTV, NULL);
		pRTV->GetResource(&pSrcResource);

		ID3D10Texture2D* pSrcBuffer = (ID3D10Texture2D *)pSrcResource;
		ID3D10Texture2D* pDstBuffer = NULL;

		D3D10_TEXTURE2D_DESC desc;
		pSrcBuffer->GetDesc(&desc);
		desc.BindFlags = 0;
		desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ;
		desc.Usage = D3D10_USAGE_STAGING;

		hr = pDevice->CreateTexture2D(&desc, NULL, &pDstBuffer);
		if (FAILED(hr)) {
			OutputDebugString("Failed to create texture2D");
			//assert(exp_state == exp_none);
		}

		pDevice->CopyResource(pDstBuffer, pSrcBuffer);

		D3D10_MAPPED_TEXTURE2D mapped_screen;
		hr = pDstBuffer->Map(0, D3D10_MAP_READ, 0, &mapped_screen);
		if (FAILED(hr)) {
			OutputDebugString("Failed to map from DstBuffer");
			//assert(exp_state == exp_none);
		}

		// copy image 
		do {
			unsigned char *src, *dst;
			data = g_pipe[0]->allocate_data();
			frame = (struct vsource_frame*) data->ptr;
			frame->pixelformat = PIX_FMT_BGRA;
			frame->realwidth = desc.Width;
			frame->realheight = desc.Height;
			frame->realstride = desc.Width<<2;
			frame->realsize = frame->realwidth * frame->realstride;
			frame->linesize[0] = frame->realstride;//frame->stride;
			//
			src = (unsigned char*) mapped_screen.pData;
			dst = (unsigned char*) frame->imgbuf;
			for (i = 0; i < encoder_height; i++) {				
				CopyMemory(dst, src, frame->realstride/*frame->stride*/);
				src += mapped_screen.RowPitch;
				dst += frame->realstride;//frame->stride;
			}
			frame->imgpts = pcdiff_us(captureTv, initialTv, freq)/frame_interval;
		} while(0);
	
		// duplicate from channel 0 to other channels
		for(i = 1; i < SOURCES; i++) {
			int j;
			struct pooldata *dupdata;
			struct vsource_frame *dupframe;
			dupdata = g_pipe[i]->allocate_data();
			dupframe = (struct vsource_frame*) dupdata->ptr;
			//
			vsource_dup_frame(frame, dupframe);
			//
			g_pipe[i]->store_data(dupdata);
			g_pipe[i]->notify_all();
		}
		g_pipe[0]->store_data(data);
		g_pipe[0]->notify_all();
		
		pDstBuffer->Unmap(0);

		pDevice->Release();
		pSrcResource->Release();
		pSrcBuffer->Release();
		pRTV->Release();
		pDstBuffer->Release();

	// d11
	} else if (dx_version == dx_11) {
		void *ppDevice;	
		This->GetDevice(IID_ID3D11Device, &ppDevice);
		ID3D11Device *pDevice = (ID3D11Device*) ppDevice;

		This->GetDevice(IID_ID3D11DeviceContext, &ppDevice);
		ID3D11DeviceContext *pDeviceContext = (ID3D11DeviceContext *) ppDevice;
		
		ID3D11RenderTargetView *pRTV = NULL;
		ID3D11Resource *pSrcResource = NULL;
		pDeviceContext->OMGetRenderTargets(1, &pRTV, NULL);
		pRTV->GetResource(&pSrcResource);
	
		ID3D11Texture2D *pSrcBuffer = (ID3D11Texture2D *)pSrcResource;
		ID3D11Texture2D *pDstBuffer = NULL;
		
		D3D11_TEXTURE2D_DESC desc;
		pSrcBuffer->GetDesc(&desc);
		desc.BindFlags = 0;
		desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
		desc.Usage = D3D11_USAGE_STAGING;

		hr = pDevice->CreateTexture2D(&desc, NULL, &pDstBuffer);
		if (FAILED(hr)) {
			OutputDebugString("Failed to create buffer");
			//assert(exp_state == exp_none);
		}
		pDeviceContext->CopyResource(pDstBuffer, pSrcBuffer);

		D3D11_MAPPED_SUBRESOURCE mapped_screen;
		hr = pDeviceContext->Map(pDstBuffer, 0, D3D11_MAP_READ, 0, &mapped_screen);
		if (FAILED(hr)) {
			OutputDebugString("Failed to map from DeviceContext");
			//assert(exp_state == exp_none);
		}
		
		// copy image 
		do {
			unsigned char *src, *dst;
			data = g_pipe[0]->allocate_data();
			frame = (struct vsource_frame*) data->ptr;
			frame->pixelformat = PIX_FMT_BGRA;
			frame->realwidth = desc.Width;
			frame->realheight = desc.Height;
			frame->realstride = desc.Width<<2;
			frame->realsize = frame->realwidth * frame->realstride;
			frame->linesize[0] = frame->realstride;//frame->stride;
			//
			src = (unsigned char*) mapped_screen.pData;
			dst = (unsigned char*) frame->imgbuf;
			for (i = 0; i < encoder_height; i++) {				
				CopyMemory(dst, src, frame->realstride/*frame->stride*/);
				src += mapped_screen.RowPitch;
				dst += frame->realstride;//frame->stride;
			}
			frame->imgpts = pcdiff_us(captureTv, initialTv, freq)/frame_interval;
		} while(0);
	
		// duplicate from channel 0 to other channels
		for(i = 1; i < SOURCES; i++) {
			int j;
			struct pooldata *dupdata;
			struct vsource_frame *dupframe;
			dupdata = g_pipe[i]->allocate_data();
			dupframe = (struct vsource_frame*) dupdata->ptr;
			//
			vsource_dup_frame(frame, dupframe);
			//
			g_pipe[i]->store_data(dupdata);
			g_pipe[i]->notify_all();
		}
		g_pipe[0]->store_data(data);
		g_pipe[0]->notify_all();

		pDeviceContext->Unmap(pDstBuffer, 0);

		pDevice->Release();
		pDeviceContext->Release();
		pSrcResource->Release();
		pSrcBuffer->Release();
		pRTV->Release();
		pDstBuffer->Release();
	}

	return hr;
}
void D3D10Grab(ID3D10Texture2D* pBackBuffer) {

    D3D10_TEXTURE2D_DESC tex_desc;
    pBackBuffer->GetDesc(&tex_desc);

    ID3D10Device *pDev;
    pBackBuffer->GetDevice(&pDev);

    ID3D10Texture2D * pTexture;
    D3D10_MAPPED_TEXTURE2D mappedTexture;
    tex_desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ;
    tex_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    tex_desc.ArraySize = 1;
    tex_desc.MipLevels = 1;
    tex_desc.BindFlags = 0;
    tex_desc.SampleDesc.Count = 1;
    tex_desc.SampleDesc.Quality = 0;
    tex_desc.Usage = D3D10_USAGE_STAGING;
    tex_desc.MiscFlags = 0;

    HRESULT hr = pDev->CreateTexture2D(&tex_desc, NULL, &pTexture);
#ifdef DEBUG
    reportLog(EVENTLOG_INFORMATION_TYPE, L"pDev->CreateTexture2D 0x%x", hr);
#endif
    pDev->CopyResource(pTexture, pBackBuffer);
    D3D10_BOX box = {0, 0, tex_desc.Width, tex_desc.Height, 0, 1};
    pDev->CopySubresourceRegion(pTexture, 0, 0, 0, 0, pBackBuffer, 0, &box);

    DxgiFrameGrabber *dxgiFrameGrabber = DxgiFrameGrabber::getInstance();
    IPCContext *ipcContext = dxgiFrameGrabber->m_ipcContext;
    Logger *logger = dxgiFrameGrabber->m_logger;

    if (S_OK != (hr = pTexture->Map(D3D10CalcSubresource(0, 0, 1), D3D10_MAP_READ, 0, &mappedTexture))) {
        logger->reportLogError(L"d3d10 couldn't map texture, hresult = 0x%x", hr);
        goto end;
    }

    ipcContext->m_memDesc.width = tex_desc.Width;
    ipcContext->m_memDesc.height = tex_desc.Height;
    ipcContext->m_memDesc.rowPitch = mappedTexture.RowPitch;
    ipcContext->m_memDesc.format = BufferFormatAbgr;
    ipcContext->m_memDesc.frameId++;

//    reportLog(EVENTLOG_INFORMATION_TYPE, L"d3d10 texture description. width: %u, height: %u, pitch: %u", tex_desc.Width, tex_desc.Height, mappedTexture.RowPitch);

    DWORD errorcode;
    if (WAIT_OBJECT_0 == (errorcode = WaitForSingleObject(ipcContext->m_hMutex, 0))) {
        //            __asm__("int $3");
//        reportLog(EVENTLOG_INFORMATION_TYPE, L"d3d10 writing description to mem mapped file");
        memcpy(ipcContext->m_pMemMap, &ipcContext->m_memDesc, sizeof (ipcContext->m_memDesc));
//        reportLog(EVENTLOG_INFORMATION_TYPE, L"d3d10 writing data to mem mapped file");
        PVOID pMemDataMap = incPtr(ipcContext->m_pMemMap, sizeof (ipcContext->m_memDesc));
        if (mappedTexture.RowPitch == tex_desc.Width * 4) {
            memcpy(pMemDataMap, mappedTexture.pData, tex_desc.Width * tex_desc.Height * 4);
        } else {
            UINT cleanOffset = 0, pitchOffset = 0, i = 0;
            while (i < tex_desc.Height) {
                memcpy(incPtr(pMemDataMap, cleanOffset), incPtr(mappedTexture.pData, pitchOffset), tex_desc.Width * 4);
                cleanOffset += tex_desc.Width * 4;
                pitchOffset += mappedTexture.RowPitch;
                i++;
            }
        }
        ReleaseMutex(ipcContext->m_hMutex);
        SetEvent(ipcContext->m_hFrameGrabbedEvent);
    } else {
        logger->reportLogError(L"d3d10 couldn't wait mutex. errocode = 0x%x", errorcode);
    }

    pTexture->Unmap(D3D10CalcSubresource(0, 0, 1));

end:
    pTexture->Release();
    pDev->Release();
}