I'm trying to understand how does Office 2013 - the part where it draws content to the screen. My findings to far:
CreateWicBitmapRenderTarget
.At this point I'm confused how Office continue. So my question is:
What are the various possible ways to copy a Wic based Render Target to the screen?
I'm pretty sure that at the end, Office is using a swap chain (probably craeted with CreateSwapChain
on Windows 7 and CreateSwapChainForHwnd
on Windows 8). I'm stepping through various "suspicous" functions such as CreateBitmapFromWicBitmap
and CreateBitmapFromDxgiSurface
) - but I don't understand the complete chain of API calls.
EDIT (answer to MooseBoys): This is NOT a general question for putting pixels on the screen. The pixels are already on one RenderTarget (A render target that was created with CreateWicBitmapRenderTarget, and then has been drawn with BeginDraw/DrawGlyphRun/EndDraw) and I now want to move those pixes to another RenderTarget (a render target on the actual screen). On the GDC world, I would look for something like BitBlt, to move pixels from one hdc to another. I wonder what is the protocol in the D2D world.
Many years later this question still has no answers, so here goes:
In the MS Office example given by OP, WIC render targets and backing bitmaps are being used primarily because WIC doesn't have the strong thread affinity of Direct2D. WIC targets and bitmaps can be created and re-sized in one thread and updated with new data in background threads (e.g., in pool tasks or long-running tasks). In contrast, Direct2D targets and bitmaps must be created, drawn, and rendered in the same thread.
Although it's possible to create and use D2D bitmaps in background threads, thread affinity means that a background D2D bitmap has to be copied into some other kind of bitmap (e.g., a WIC bitmap) before it can be accessed from another thread. To render it for display would require copying it twice: once to be able to read it from the UI thread and a second time to convert it back into another D2D bitmap that belongs to the UI context. Background D2D bitmaps rarely are worth the trouble.
WIC bitmaps allow cross-thread (cross context) access, making them much more flexible. However, WIC bitmaps cannot be directly rendered to a screen device context for display. To display a WIC bitmap you must enter a UI context and copy the WIC bitmap into a D2D bitmap, which you then may draw to the UI context target, making it ready to be presented to the device screen for display.
Here is some example code excerpted and condensed from a fast scrolling channel display that uses c#, SharpDx and Dx11.1. The device manager, swapchain and other elements were defined elsewhere, but the concept should be clear.
// Must be executed in the UI context
private void DrawWicBitmapToDisplayContext(SharpDX.WIC.Bitmap wicBitmap)
{
var context2D = deviceManager.Direct2DContext; // previously created
context2D.Transform = Matrix3x2.Identity;
// if you have multiple alternate targets for context2D overlays, select the desired one here
// Convert from Wic Bitmap to a d2d bitmap before drawing to the DXGI surface target
using(TraceBitmap_D2D1_bmp1 = SharpDX.Direct2D1.Bitmap1.FromWicBitmap(context2D, wicBitmap, traceBitmapProperties), "TraceBitmap"))
{
context2D.BeginDraw();
context2D.DrawBitmap(TraceBitmap_D2D1_bmp1, 1.0f, SharpDX.Direct2D1.InterpolationMode.HighQualityCubic);
context2D.EndDraw();
}
}
Here's example code that makes it visible on the device screen:
// Must be executed in the UI context
public void PresentToScreen()
{
var device3D = deviceManager.Direct3DDevice;
var context3D = deviceManager.Direct3DContext;
var bgColorSharpDx = SharpDX.Color.Transparent; // or as desired
// Set up the context for rendering.
// RectangleVertexBuffer contains two triangles making up a rectangle that matches the display area.
device3D.ImmediateContext.InputAssembler.SetVertexBuffers(0, rectangleVertexBufferBinding);
device3D.ImmediateContext.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
device3D.ImmediateContext.OutputMerger.SetRenderTargets(renderTargetView);
device3D.ImmediateContext.ClearRenderTargetView(renderTargetView, bgColorSharpDx);
using(var newestWicBitmap = GetNewestWicBitmapFromPool()) // double-buffering method not shown
{
DrawWicBitmapToDisplayContext(newestWicBitmap); // code is shown above
}
bool vSync = false; // don't use vSync in windowed modes (deadlocks on resize)
swapChain.Present(vSync ? 1 : 0, PresentFlags.None, new PresentParameters()); // requires DX11.1
}
Presumably an extension method DeviceContext.DrawWicBitmap() could accept WIC bitmaps and handle the conversion invisibly.