This is an automated email from the git hooks/post-receive script.

git pushed a commit to branch master
in repository Direct3D.wiki.

View the commit online.

commit fc5a62a9c162845cdf09fc511f25bb8fb68746ce
Author: Vincent Torri <vincent.to...@gmail.com>
AuthorDate: Sat Jul 29 06:02:01 2023 -0700

    Update 'Direct3D 11 for 2D: Fill background'
---
 Direct3D-11-for-2D%3A-Fill-background.md | 541 +++++++++++++++++++++++++++++++
 1 file changed, 541 insertions(+)

diff --git a/Direct3D-11-for-2D%3A-Fill-background.md b/Direct3D-11-for-2D%3A-Fill-background.md
new file mode 100644
index 0000000..772fca3
--- /dev/null
+++ b/Direct3D-11-for-2D%3A-Fill-background.md
@@ -0,0 +1,541 @@
+# Fill window background with Direct3D 11
+
+It is time to add some Direct3D code:
+
+* a structure which will contain the necessary Direct3D variables,
+* the d3d_init() function which will create resources,
+* the d3d_shutdown() function which will release resources,
+* the d3d_resize() function which will handle window resize
+* the d3d_render() function which will set the resources of the needed pipeline stages, fill the background with a color and display the result.
+
+Note that filling the background will be useless for an EFL-based application as the background will be anyway filled with a rectangle or image. It is used only to show something in this tutorial.
+
+### Direct3D structure
+
+Here is the structure that holds the Direct3D objects:
+
+```c
+struct D3d
+{
+    /* DXGI */
+    IDXGIFactory2 *dxgi_factory;
+    IDXGISwapChain1 *dxgi_swapchain;
+    /* D3D11 */
+    ID3D11Device *d3d_device;
+#ifdef _DEBUG
+    ID3D11Debug *d3d_debug;
+#endif
+    ID3D11DeviceContext *d3d_device_ctx;
+    ID3D11RenderTargetView *d3d_render_target_view;
+    ID3D11InputLayout *d3d_input_layout;
+    ID3D11VertexShader *d3d_vertex_shader;
+    ID3D11RasterizerState *d3d_rasterizer_state;
+    ID3D11PixelShader *d3d_pixel_shader;
+    D3D11_VIEWPORT viewport;
+    unsigned int vsync : 1;
+};
+```
+
+* he DXGI factory is used to get the vertical synchronization frequency (function `d3d_refresh_rate_get()`) and to create the swap chain.
+* The D3D11 device is used to create the render target view.
+* The D3D11 device context is used to bind the Direct3D objects to the pipeline.
+* The swap chain and render target view has been briefly described above.
+* The viewport is the rectangle (in pixels) in which the 3D scene is projected.
+
+### The `d3d_init()` function
+
+The steps are:
+
+1. Create the DXGI factory.
+2. Create the D3D11 device and device context.
+3. Get the vertical synchronization frequency by calling the function d3d_refresh_rate_get(). The frequency is a rational number, meaning that it has a numerator and a denominator. If the user does not want to honor vsync, the frequency has numerator equal to 0 and denominator equal to 1.
+4. Create the DXGI swap chain. It requires some settings, mainly:
+ * the Win32 window,
+ * the size of the Win32 window,
+ * the vertical synchronization frequency,
+ * the output format, here, BGRA,
+ * the swap model, here the front and back buffers are flipped, meaning that the pointers of the front and back buffer pointers are swapped.
+ * if the scene if fullscreen or not.
+5. Create the rasterizer state.
+
+### The `d3d_shutdown()` function
+
+It just release the DXGI and D3D resources. Note that the swapchain must be set to windowed before releasing it.
+
+### The `d3d_resize()` function
+
+This function is called when the window is resized. The steps are:
+
+1. set the size of the viewport,
+2. release the render target view if any,
+3. unbind the render target from the D3D pipeline,
+4. resize the buffers of the DXGI swap chain,
+5. get the back buffer from the swap chain,
+6. create the render target view with this buffer, the rendering is done on a 2D texture,
+7. release the back buffer.
+
+### The `d3d_render()` function
+
+This function sets the D3D pipeline:
+
+1. set rasterizer state in the Rasterizer Stage (RS),
+2. set viewport in the Rasterizer Stage (RS),
+3. set the render target view in the Output Merger (OM),
+4. flip back and front buffer to display the scene created in the back buffer.
+
+### The full code
+
+For now, we do not support the fullscreen and rotation in Direct3D, it will be done later.
+
+The files `` and `` remain unchanged. The new Direct3D code is now in the `d3d_1.c` source file:
+
+```c
+/*
+ * Tutorial part 1
+ *
+ * Initialization / shutdown of D3D
+ * Handle resize
+ * Fill background with a single color
+ *
+ * Compilation:
+ *
+ * gcc -g -O2 -Wall -Wextra -o d3d_1 d3d_1.c win.c -ld3d11 -ldxgi -luuid -D_WIN32_WINNT=0x0A00
+ */
+
+#include <stdlib.h> /* calloc() free() malloc() */
+#include <stdio.h>  /* printf() fflush() */
+
+#define _DEBUG
+
+/* C API for d3d11 */
+#define COBJMACROS
+
+#include <dxgi1_3.h>     /* DXGI interface */
+#include <d3d11.h>       /* D3D11 interface */
+#include <d3dcompiler.h> /* compilation of shader */
+
+#include "win.h"
+
+#ifdef _DEBUG
+# define FCT \
+do { printf(" * %s\n", __FUNCTION__); fflush(stdout); } while (0)
+#else
+# define FCT \
+do { } while (0)
+#endif
+
+struct D3d
+{
+    /* DXGI */
+    IDXGIFactory2 *dxgi_factory;
+    IDXGISwapChain1 *dxgi_swapchain;
+    /* D3D11 */
+    ID3D11Device *d3d_device;
+#ifdef _DEBUG
+    ID3D11Debug *d3d_debug;
+#endif
+    ID3D11DeviceContext *d3d_device_ctx;
+    ID3D11RenderTargetView *d3d_render_target_view;
+    ID3D11InputLayout *d3d_input_layout;
+    ID3D11VertexShader *d3d_vertex_shader;
+    ID3D11RasterizerState *d3d_rasterizer_state;
+    ID3D11PixelShader *d3d_pixel_shader;
+    D3D11_VIEWPORT viewport;
+    unsigned int vsync : 1;
+};
+
+/************************** D3D11 **************************/
+
+static void d3d_refresh_rate_get(D3d *d3d, UINT *num, UINT *den)
+{
+    DXGI_MODE_DESC *display_mode_list = NULL; /* 28 bytes */
+    IDXGIAdapter *dxgi_adapter;
+    IDXGIOutput *dxgi_output;
+    UINT nbr_modes;
+    UINT i;
+    HRESULT res;
+
+    *num = 0U;
+    *den = 1U;
+
+    if (!d3d->vsync)
+        return;
+
+    /* adapter of primary desktop : pass 0U */
+    res = IDXGIFactory_EnumAdapters(d3d->dxgi_factory, 0U, &dxgi_adapter);
+    if (FAILED(res))
+        return;
+
+    /* output of primary desktop : pass 0U */
+    res = IDXGIAdapter_EnumOutputs(dxgi_adapter, 0U, &dxgi_output);
+    if (FAILED(res))
+        goto release_dxgi_adapter;
+
+    /* number of mode that fit the format */
+     res = IDXGIOutput_GetDisplayModeList(dxgi_output,
+                                         DXGI_FORMAT_B8G8R8A8_UNORM,
+                                         DXGI_ENUM_MODES_INTERLACED,
+                                         &nbr_modes, NULL);
+    if (FAILED(res))
+        goto release_dxgi_output;
+
+    printf("display mode list : %d\n", nbr_modes);
+    fflush(stdout);
+    display_mode_list = (DXGI_MODE_DESC *)malloc(nbr_modes * sizeof(DXGI_MODE_DESC));
+    if (!display_mode_list)
+        goto release_dxgi_output;
+
+    /* fill the mode list */
+    res = IDXGIOutput_GetDisplayModeList(dxgi_output,
+                                         DXGI_FORMAT_B8G8R8A8_UNORM,
+                                         DXGI_ENUM_MODES_INTERLACED,
+                                         &nbr_modes, display_mode_list);
+    if (FAILED(res))
+        goto free_mode_list;
+
+    for (i = 0; i < nbr_modes; i++)
+    {
+        if ((display_mode_list[i].Width == (UINT)GetSystemMetrics(SM_CXSCREEN)) &&
+            (display_mode_list[i].Height == (UINT)GetSystemMetrics(SM_CYSCREEN)))
+        {
+            *num = display_mode_list[i].RefreshRate.Numerator;
+            *den = display_mode_list[i].RefreshRate.Denominator;
+            break;
+        }
+    }
+
+#ifdef _DEBUG
+    {
+        DXGI_ADAPTER_DESC adapter_desc;
+
+        IDXGIAdapter_GetDesc(dxgi_adapter, &adapter_desc);
+        printf(" * video mem: %llu B, %llu MB\n",
+               adapter_desc.DedicatedVideoMemory,
+               adapter_desc.DedicatedVideoMemory / 1024 / 1024);
+        fflush(stdout);
+        wprintf(L" * description: %ls\n", adapter_desc.Description);
+        fflush(stdout);
+    }
+#endif
+
+  free_mode_list:
+    free(display_mode_list);
+  release_dxgi_output:
+    IDXGIOutput_Release(dxgi_output);
+  release_dxgi_adapter:
+    IDXGIFactory_Release(dxgi_adapter);
+}
+
+D3d *d3d_init(Window *win, int vsync)
+{
+    DXGI_SWAP_CHAIN_DESC1 desc_sw;
+    DXGI_SWAP_CHAIN_FULLSCREEN_DESC desc_fs;
+    D3D11_RASTERIZER_DESC desc_rs;
+    D3d *d3d;
+    RECT r;
+    HRESULT res;
+    UINT flags;
+    UINT num;
+    UINT den;
+    D3D_FEATURE_LEVEL feature_level[4];
+
+    d3d = (D3d *)calloc(1, sizeof(D3d));
+    if (!d3d)
+        return NULL;
+
+    d3d->vsync = vsync;
+    win->d3d = d3d;
+
+    /* create the DXGI factory */
+    flags = 0;
+#ifdef _DEBUG
+    flags = DXGI_CREATE_FACTORY_DEBUG;
+#endif
+    res = CreateDXGIFactory2(flags, &IID_IDXGIFactory2, (void **)&d3d->dxgi_factory);
+    if (FAILED(res))
+        goto free_d3d;
+
+    /* software engine functions are called from the main loop */
+    flags = D3D11_CREATE_DEVICE_SINGLETHREADED |
+            D3D11_CREATE_DEVICE_BGRA_SUPPORT;
+#ifdef _DEBUG
+    flags |= D3D11_CREATE_DEVICE_DEBUG;
+#endif
+
+    feature_level[0] = D3D_FEATURE_LEVEL_11_1;
+    feature_level[1] = D3D_FEATURE_LEVEL_11_0;
+    feature_level[2] = D3D_FEATURE_LEVEL_10_1;
+    feature_level[3] = D3D_FEATURE_LEVEL_10_0;
+
+    /* create device and device context with hardware support */
+    res = D3D11CreateDevice(NULL,
+                            D3D_DRIVER_TYPE_HARDWARE,
+                            NULL,
+                            flags,
+                            feature_level,
+                            3U,
+                            D3D11_SDK_VERSION,
+                            &d3d->d3d_device,
+                            NULL,
+                            &d3d->d3d_device_ctx);
+    if (FAILED(res))
+        goto release_dxgi_factory2;
+
+#ifdef _DEBUG
+    res = ID3D11Debug_QueryInterface(d3d->d3d_device, &IID_ID3D11Debug,
+                                     (void **)&d3d->d3d_debug);
+    if (FAILED(res))
+        goto release_d3d_device;
+#endif
+
+    if (!GetClientRect(win->win, &r))
+        goto release_d3d_device;
+
+    /*
+     * create the swap chain. It needs some settings...
+     * the size of the internal buffers
+     * the image format
+     * the number of back buffers (>= 2 for flip model, see SwapEffect field)
+     * vsync enabled: need refresh rate
+     */
+
+    d3d_refresh_rate_get(d3d, &num, &den);
+
+    desc_sw.Width = r.right - r.left;
+    desc_sw.Height = r.bottom - r.top;
+    desc_sw.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
+    desc_sw.Stereo = FALSE;
+    desc_sw.SampleDesc.Count = 1U;
+    desc_sw.SampleDesc.Quality = 0U;
+    desc_sw.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+    desc_sw.BufferCount = 2U;
+    desc_sw.Scaling = DXGI_SCALING_NONE;
+    desc_sw.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
+    desc_sw.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
+    desc_sw.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
+
+    desc_fs.RefreshRate.Numerator = num;
+    desc_fs.RefreshRate.Denominator = den;
+    desc_fs.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
+    desc_fs.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
+    desc_fs.Windowed = TRUE;
+
+    res = IDXGIFactory2_CreateSwapChainForHwnd(d3d->dxgi_factory,
+                                               (IUnknown *)d3d->d3d_device,
+                                               win->win,
+                                               &desc_sw,
+                                               &desc_fs,
+                                               NULL,
+                                               &d3d->dxgi_swapchain);
+    if (FAILED(res))
+        goto release_d3d_device;
+
+    /* rasterizer */
+    desc_rs.FillMode = D3D11_FILL_SOLID;
+    desc_rs.CullMode = D3D11_CULL_NONE;
+    desc_rs.FrontCounterClockwise = FALSE;
+    desc_rs.DepthBias = 0;
+    desc_rs.DepthBiasClamp = 0.0f;
+    desc_rs.SlopeScaledDepthBias = 0.0f;
+    desc_rs.DepthClipEnable = TRUE;
+    desc_rs.ScissorEnable = FALSE;
+    desc_rs.MultisampleEnable = FALSE;
+    desc_rs.AntialiasedLineEnable = FALSE;
+
+    res = ID3D11Device_CreateRasterizerState(d3d->d3d_device,
+                                             &desc_rs,
+                                             &d3d->d3d_rasterizer_state);
+    if (FAILED(res))
+        goto release_dxgi_swapchain;
+
+    return d3d;
+
+  release_dxgi_swapchain:
+    IDXGISwapChain1_SetFullscreenState(d3d->dxgi_swapchain, FALSE, NULL);
+    IDXGISwapChain1_Release(d3d->dxgi_swapchain);
+  release_d3d_device:
+#ifdef _DEBUG
+    if (d3d->d3d_debug)
+        ID3D11Debug_Release(d3d->d3d_debug);
+#endif
+    ID3D11DeviceContext_Release(d3d->d3d_device_ctx);
+    ID3D11Device_Release(d3d->d3d_device);
+  release_dxgi_factory2:
+    IDXGIFactory2_Release(d3d->dxgi_factory);
+  free_d3d:
+    free(d3d);
+
+    return NULL;
+}
+
+void d3d_shutdown(D3d *d3d)
+{
+#ifdef _DEBUG
+    ID3D11Debug *d3d_debug;
+#endif
+
+    if (!d3d)
+        return;
+
+#ifdef _DEBUG
+    d3d_debug = d3d->d3d_debug;
+#endif
+
+    ID3D11RasterizerState_Release(d3d->d3d_rasterizer_state);
+    ID3D11RenderTargetView_Release(d3d->d3d_render_target_view);
+    IDXGISwapChain1_SetFullscreenState(d3d->dxgi_swapchain, FALSE, NULL);
+    IDXGISwapChain1_Release(d3d->dxgi_swapchain);
+    ID3D11DeviceContext_Release(d3d->d3d_device_ctx);
+    ID3D11Device_Release(d3d->d3d_device);
+    IDXGIFactory2_Release(d3d->dxgi_factory);
+    free(d3d);
+
+#ifdef _DEBUG
+    ID3D11Debug_ReportLiveDeviceObjects(d3d_debug, D3D11_RLDO_DETAIL);
+    ID3D11Debug_Release(d3d_debug);
+#endif
+}
+
+void d3d_resize(D3d *d3d, int rot, UINT width, UINT height)
+{
+    D3D11_RENDER_TARGET_VIEW_DESC desc_rtv;
+    ID3D11Texture2D *back_buffer;
+    HRESULT res;
+
+    FCT;
+
+    /* unset the render target view in the output merger */
+    ID3D11DeviceContext_OMSetRenderTargets(d3d->d3d_device_ctx,
+                                           0U, NULL, NULL);
+
+    /* release the render target view */
+    if (d3d->d3d_render_target_view)
+        ID3D11RenderTargetView_Release(d3d->d3d_render_target_view);
+
+    /* resize the internal nuffers of the swapt chain to the new size */
+    res = IDXGISwapChain1_ResizeBuffers(d3d->dxgi_swapchain,
+                                        0U, /* preserve buffer count */
+                                        width, height,
+                                        DXGI_FORMAT_UNKNOWN, /* preserve format */
+                                        0U);
+    if ((res == DXGI_ERROR_DEVICE_REMOVED) ||
+        (res == DXGI_ERROR_DEVICE_RESET) ||
+        (res == DXGI_ERROR_DRIVER_INTERNAL_ERROR))
+    {
+        return;
+    }
+
+    if (FAILED(res))
+    {
+        printf("ResizeBuffers() failed\n");
+        fflush(stdout);
+        return;
+    }
+
+    /* get the internal buffer of the swap chain */
+    res = IDXGISwapChain1_GetBuffer(d3d->dxgi_swapchain, 0,
+                                    &IID_ID3D11Texture2D,
+                                    (void **)&back_buffer);
+    if (FAILED(res))
+    {
+        printf("swapchain GetBuffer() failed\n");
+        fflush(stdout);
+        return;
+    }
+
+    ZeroMemory(&desc_rtv, sizeof(D3D11_RENDER_TARGET_VIEW_DESC));
+    desc_rtv.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
+    desc_rtv.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
+
+    /* create the new render target view from this internal buffer */
+    res = ID3D11Device_CreateRenderTargetView(d3d->d3d_device,
+                                              (ID3D11Resource *)back_buffer,
+                                              &desc_rtv,
+                                              &d3d->d3d_render_target_view);
+
+    ID3D11Texture2D_Release(back_buffer);
+
+    /* update the pipeline with the new render target view */
+    ID3D11DeviceContext_OMSetRenderTargets(d3d->d3d_device_ctx,
+                                           1U, &d3d->d3d_render_target_view,
+                                           NULL);
+
+    /* set viewport, depends on size of the window */
+    d3d->viewport.TopLeftX = 0.0f;
+    d3d->viewport.TopLeftY = 0.0f;
+    d3d->viewport.Width = (float)width;
+    d3d->viewport.Height = (float)height;
+    d3d->viewport.MinDepth = 0.0f;
+    d3d->viewport.MaxDepth = 1.0f;
+
+    /* update the pipeline with the new viewport */
+    ID3D11DeviceContext_RSSetViewports(d3d->d3d_device_ctx,
+                                       1U, &d3d->viewport);
+}
+
+void d3d_scene_begin(D3d *d3d)
+{
+    (void)d3d;
+}
+
+void d3d_scene_end(void)
+{
+}
+
+void d3d_render(D3d *d3d)
+{
+    DXGI_PRESENT_PARAMETERS pp;
+    const FLOAT color[4] = { 0.10f, 0.18f, 0.24f, 1.0f };
+    HRESULT res;
+
+    FCT;
+
+    /* clear render target */
+    ID3D11DeviceContext_ClearRenderTargetView(d3d->d3d_device_ctx,
+                                              d3d->d3d_render_target_view,
+                                              color);
+
+    /*
+     * Rasterizer Stage
+     *
+     * RSSetViewports() called in the resize() callback
+     */
+    ID3D11DeviceContext_RSSetState(d3d->d3d_device_ctx,
+                                   d3d->d3d_rasterizer_state);
+
+    /* pixel shader stage */
+    ID3D11DeviceContext_PSSetShader(d3d->d3d_device_ctx,
+                                    d3d->d3d_pixel_shader,
+                                    NULL,
+                                    0);
+
+    /*
+     * Output Merger stage
+     *
+     * OMSetRenderTargets() called in the resize() callback
+     */
+
+    /*
+     * present frame, that is, flip the back buffer and the front buffer
+     * if no vsync, we present immediatly
+     */
+    pp.DirtyRectsCount = 0;
+    pp.pDirtyRects = NULL;
+    pp.pScrollRect = NULL;
+    pp.pScrollOffset = NULL;
+    res = IDXGISwapChain1_Present1(d3d->dxgi_swapchain,
+                                   d3d->vsync ? 1 : 0, 0, &pp);
+    if (res == DXGI_ERROR_DEVICE_RESET || res == DXGI_ERROR_DEVICE_REMOVED)
+    {
+        printf("device removed or lost, need to recreate everything\n");
+        fflush(stdout);
+    }
+    else if (res == DXGI_STATUS_OCCLUDED)
+    {
+        printf("window is not visible, so vsync won't work. Let's sleep a bit to reduce CPU usage\n");
+        fflush(stdout);
+    }
+}
+```
+
+When launched, you should get something like

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.

Reply via email to