// File // Prerequisites.h _________________________________________________________________________________ #pragma once #include "framework.h" #include "Win32OpenGLProject.h" #pragma region Includes & Defines #pragma region Note : constexpr /* The keyword constexpr was introduced in C++11 and improved in C++14. It means constant expression. Like const, it can be applied to variables: A compiler error is raised when any code attempts to modify the value. Unlike const, constexpr can also be applied to functions and class constructors. constexpr indicates that the value, or return value, is constant and, where possible, is computed at compile time. A constexpr integral value can be used wherever a const integer is required, such as in template arguments and array declarations. And when a value is computed at compile time instead of run time, it helps your program run faster and use less memory. To limit the complexity of compile-time constant computations, and their potential impacts on compilation time, the C++14 standard requires the types in constant expressions to be literal types.*/ #pragma endregion constexpr auto MAX_LOADSTRING = 100; /* define the screen resolution */ constexpr auto SCREEN_WIDTH = 800; constexpr auto SCREEN_HEIGHT = 400; constexpr auto BLACK_INDEX = 0; constexpr auto RED_INDEX = 13; constexpr auto GREEN_INDEX = 14; constexpr auto BLUE_INDEX = 16; constexpr auto WIDTH = 300; constexpr auto HEIGHT = 200; constexpr auto GLOBE = 1; constexpr auto CYLINDER = 2; constexpr auto CONE = 3; /* folder - DirectX_Tutorial */ #define DX11 // using directx 11 //#define OOP // using object oriented programming #define OGL // using Opengl //#define EXAMPLE // using example #define ONESOLIDBRUSH //#undef DEBUG //#undef _DEBUG #ifndef UNICODE #define UNICODE #endif #ifdef UNICODE #define SetWindowText SetWindowTextW #define _tcslen wcslen //#define _countof(array) (sizeof(array)/sizeof(array[0])) #else #define SetWindowText SetWindowTextA #define _tcslen strlen #endif #if defined( DEBUG ) || defined( _DEBUG ) #define Assert(b) if (!(b)) {OutputDebugStringA("Assert: " #b "\n");} #else #define Assert(b) #endif //DEBUG || _DEBUG /* __ImageBase represents the DOS header of the module In other words, it’s the base address of the module. And the module base address is the same as its HINSTANCE */ #ifndef HINST_THISCOMPONENT EXTERN_C IMAGE_DOS_HEADER __ImageBase; #define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase) #endif #include #include #include #include #include #include //#include #include /* The contents of are available only with C++17 or later */ //#include #include #include #include #pragma comment(lib, "User32.lib") #include #pragma comment(lib, "D3D11") //#include //#pragma comment(lib, "D3D11_1") #include #pragma comment(lib, "D2d1") #include #include #include //#include #include #pragma comment(lib, "DXGI") //#include //#include #include #pragma comment (lib, "D3D10_1") //#include ////#pragma comment (lib, "D3D10") //#include #include #include /* NuGet\Install-Package Microsoft.DXSDK.D3DX -Version 9.29.952.8 */ //#include #include #pragma comment(lib, "dcomp") /* for use with Windows::Foundation::Initialize */ #include #pragma comment(lib, "runtimeobject.lib") /* use with WIC*/ #include #pragma comment(lib, "Windowscodecs.lib") #include #include /* fpr use with PathCchRemoveFileSpec */ #include #pragma comment(lib, "Pathcch.lib") // imgui #include #include #include /* OpenGL 4.0 requires linking to opengl32.lib library. This can be done in the IDE or directly in the code. */ //#pragma comment(lib, "opengl32.lib") //#include "OpenGLLibs.h" /* Windows OpenGL program */ #include "GL/gl.h" #include "GL/glu.h" #pragma comment(lib, "glu32.lib") #include /* In Windows the gl.h header only contains the defines, functions, and function pointers for OpenGL 1.0 and OpenGL 1.1. All newer OpenGL functionality is actually implemented in the display driver for your video card in the form of extensions. You can find the names of all the extensions in the OpenGL 4.0 spec that the Khronos Group maintains on their website in the OpenGL 4.0 documentation. You can also download files such as wglext.h and glext.h which contain a large number of them as well The OpenGL Registry provides access to a header containing function pointer definitions for every extension and every core function for version 1.2 and above (since 1.1 and below are provided by Windows' gl.h). This header is called glext.h. The headers glxext.h and wglext.h are also provided, containing extensions for GLX and WGL. These headers are kept reasonably up to date with OpenGL releases. */ #include "GL/wglext.h" #include "GL/glext.h" #define EXTENSIONS_AVAILABLE #ifndef EXTENSIONS_AVAILABLE #pragma region Subset of all OpenGL4.0 Functions #pragma region Defines #define WGL_DRAW_TO_WINDOW_ARB 0x2001 #define WGL_ACCELERATION_ARB 0x2003 #define WGL_SWAP_METHOD_ARB 0x2007 #define WGL_SUPPORT_OPENGL_ARB 0x2010 #define WGL_DOUBLE_BUFFER_ARB 0x2011 #define WGL_PIXEL_TYPE_ARB 0x2013 #define WGL_COLOR_BITS_ARB 0x2014 #define WGL_DEPTH_BITS_ARB 0x2022 #define WGL_STENCIL_BITS_ARB 0x2023 #define WGL_FULL_ACCELERATION_ARB 0x2027 #define WGL_SWAP_EXCHANGE_ARB 0x2028 #define WGL_TYPE_RGBA_ARB 0x202B #define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 #define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 #define GL_ARRAY_BUFFER 0x8892 #define GL_STATIC_DRAW 0x88E4 #define GL_FRAGMENT_SHADER 0x8B30 #define GL_VERTEX_SHADER 0x8B31 #define GL_COMPILE_STATUS 0x8B81 #define GL_LINK_STATUS 0x8B82 #define GL_INFO_LOG_LENGTH 0x8B84 #define GL_TEXTURE0 0x84C0 #define GL_BGRA 0x80E1 #define GL_ELEMENT_ARRAY_BUFFER 0x8893 #pragma endregion /* Function typedefs for WGL extensions are available in wglext.h */ #pragma region TypeDefines typedef BOOL(WINAPI* PFNWGLCHOOSEPIXELFORMATARBPROC) ( HDC hdc, const int* piAttribIList, const FLOAT* pfAttribFList, UINT nMaxFormats, int* piFormats, UINT* nNumFormats); typedef HGLRC(WINAPI* PFNWGLCREATECONTEXTATTRIBSARBPROC) ( HDC hDC, HGLRC hShareContext, const int* attribList); typedef BOOL(WINAPI* PFNWGLSWAPINTERVALEXTPROC) (int interval); typedef void (APIENTRY* PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader); typedef void (APIENTRY* PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer); typedef void (APIENTRY* PFNGLBINDVERTEXARRAYPROC) (GLuint array); typedef void (APIENTRY* PFNGLBUFFERDATAPROC) ( GLenum target, ptrdiff_t size, const GLvoid* data, GLenum usage); typedef void (APIENTRY* PFNGLCOMPILESHADERPROC) (GLuint shader); typedef GLuint(APIENTRY* PFNGLCREATEPROGRAMPROC) (void); typedef GLuint(APIENTRY* PFNGLCREATESHADERPROC) (GLenum type); typedef void (APIENTRY* PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint* buffers); typedef void (APIENTRY* PFNGLDELETEPROGRAMPROC) (GLuint program); typedef void (APIENTRY* PFNGLDELETESHADERPROC) (GLuint shader); typedef void (APIENTRY* PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint* arrays); typedef void (APIENTRY* PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader); typedef void (APIENTRY* PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index); typedef void (APIENTRY* PFNGLGENBUFFERSPROC) (GLsizei n, GLuint* buffers); typedef void (APIENTRY* PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint* arrays); typedef GLint(APIENTRY* PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const char* name); typedef void (APIENTRY* PFNGLGETPROGRAMINFOLOGPROC) ( GLuint program, GLsizei bufSize, GLsizei* length, char* infoLog); typedef void (APIENTRY* PFNGLGETPROGRAMIVPROC) ( GLuint program, GLenum pname, GLint* params); typedef void (APIENTRY* PFNGLGETSHADERINFOLOGPROC) ( GLuint shader, GLsizei bufSize, GLsizei* length, char* infoLog); typedef void (APIENTRY* PFNGLGETSHADERIVPROC) ( GLuint shader, GLenum pname, GLint* params); typedef void (APIENTRY* PFNGLLINKPROGRAMPROC) (GLuint program); typedef void (APIENTRY* PFNGLSHADERSOURCEPROC) ( GLuint shader, GLsizei count, const char** string, const GLint* length); typedef void (APIENTRY* PFNGLUSEPROGRAMPROC) (GLuint program); typedef void (APIENTRY* PFNGLVERTEXATTRIBPOINTERPROC) ( GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* pointer); typedef void (APIENTRY* PFNGLBINDATTRIBLOCATIONPROC) ( GLuint program, GLuint index, const char* name); typedef GLint(APIENTRY* PFNGLGETUNIFORMLOCATIONPROC) ( GLuint program, const char* name); typedef void (APIENTRY* PFNGLUNIFORMMATRIX4FVPROC) ( GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); typedef void (APIENTRY* PFNGLACTIVETEXTUREPROC) (GLenum texture); typedef void (APIENTRY* PFNGLUNIFORM1IPROC) (GLint location, GLint v0); typedef void (APIENTRY* PFNGLGENERATEMIPMAPPROC) (GLenum target); typedef void (APIENTRY* PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index); typedef void (APIENTRY* PFNGLUNIFORM3FVPROC) ( GLint location, GLsizei count, const GLfloat* value); typedef void (APIENTRY* PFNGLUNIFORM4FVPROC) ( GLint location, GLsizei count, const GLfloat* value); #pragma endregion #pragma endregion #endif // !EXTENSIONS_AVAILABLE /*************************** D3D OPENGL **************************/ /*********************************************************************************/ //#include "CameraClass.h" //#include "D3DClass.h" //#include "FPSClass.h" ////_____________________________ //#include "GraphicsClass.h" //#include "InputClass.h" //#include "OpenGLClass.h" ////_____________________________ //#include "PositionClass.h" //#include "ShaderManagerClass.h" //#include "TerrainClass.h" //#include "TimerClass.h" //#include "UIClass.h" //#include "ZoneClass.h" /*********************************************************************************/ using namespace DirectX; using namespace DirectX::PackedVector; /* utilize using namespace directive to make the code more readable */ using namespace ABI::Windows::Foundation; using namespace std; #pragma endregion #pragma region Global Variables #pragma region Note : Static and Constant Variables /* Static variables can be defined as a class property that is used in a class and not on the class instance. This type of variable is stored in the data segment area of the memory. The value assigned to these types of variables is shared among every instance that is created in the class. We need to use the static keyword for creating any static entity like a static variable, static function, operators, properties, etc. The value of a static variable is set at the runtime of the application and serves as a global value for the whole application. Const - A constant can be defined as a variable that has a fixed defined value and remains the same throughout the program. A property of the const variable is that we cannot change or modify this value anywhere in a project once it is initialized. “static const” is basically a combination of static(a storage specifier) and const(a type qualifier). The static determines the lifetime and visibility/accessibility of the variable. This means if a variable is declared as a static variable, it will remain in the memory the whole time when the program is running, while the normal or auto variables are destroyed when the function (where the variable was defined) is over. The const is a type qualifier. A type qualifier is used to express additional info about a value through type system. When a variable is initialized using the const type qualifier, it will not accept further change in its value. So combining static and const, we can say that when a variable is initialized using static const, it will retain its value till the execution of the program and also, it will not accept any change in its value. */ #pragma endregion static int nWidth, nHeight, screenW, screenH, screenX, screenY, method, rendtarget, d3dStep, colR, colG, colB, colA, pixx, pixy, pixSizeW, pixSizeH, colModr, colModg, colModb, bitmapSize, bmpOptions, trySwapChain, swapchain, propsNum, dxgiUse, targets, dcTargetAtempts; /* CHAR and WCHAR are the data types recommended for use in a Windows program when there is a need to define an 8-bit character or a 16-bit character */ static WCHAR szTitle[MAX_LOADSTRING]; // title bar text static WCHAR szWindowClass[MAX_LOADSTRING]; // main window class name static float SCREEN_DEPTH = 1000.0f, SCREEN_NEAR = 0.1f, percentReturnValue, col, colorR, colorG, colorB, colAlpha; static bool FULL_SCREEN, VSYNC_ENABLED, DXGIFail, windowCreated, winReady, methods, result, okay, logged, fileOpened, enableOpenGL, enableD2D, enableD3D, openGLReady = true, oneBrush, multiSampling, swapChainCreated, canDraw, linearGradientBrushCreated, surfaceRendered, surfaceCreated, d2dContextCreated, dcTarget; static char dir[256], // directory / pathname buff[MAX_PATH] = {}; static PWSTR directoryPath; static string logFile, writeStr, workingDirFilepath, text, pth, str, destDir, srcDir, convStr, target; static string targetType[4] = { "Hwnd", "Bitmap", "DC", "DXGI" }; static fstream writefile; const int deviceFlag[22] = { DRIVERVERSION, HORZSIZE, VERTSIZE, HORZRES, VERTRES, BITSPIXEL, PLANES, NUMBRUSHES, NUMPENS, NUMFONTS, NUMCOLORS, CLIPCAPS, SIZEPALETTE, COLORRES, VREFRESH, SHADEBLENDCAPS, RASTERCAPS, CURVECAPS, LINECAPS, POLYGONALCAPS, TEXTCAPS, COLORMGMTCAPS }; const int gradientStopInt = 5; static int numFlags = sizeof(deviceFlag) / sizeof(int), clientW, clientH, bmpW, bmpH, test = 0, err; static int double_buffered = true, iAttributes[] = { WGL_SUPPORT_OPENGL_ARB, GL_TRUE, WGL_DRAW_TO_WINDOW_ARB, GL_TRUE, WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB, WGL_COLOR_BITS_ARB, 24, WGL_ALPHA_BITS_ARB, 8, WGL_DEPTH_BITS_ARB, 24, WGL_STENCIL_BITS_ARB, 0, WGL_DOUBLE_BUFFER_ARB, double_buffered ? GL_TRUE : GL_FALSE, /* Multisampling only works when double-buffering is enabled */ WGL_SAMPLE_BUFFERS_ARB, double_buffered ? GL_TRUE : GL_FALSE, WGL_SAMPLES_ARB, double_buffered ? 4 : 0, 0, 0 }, attributeListInt[] = { WGL_SUPPORT_OPENGL_ARB, GL_TRUE, WGL_DRAW_TO_WINDOW_ARB, GL_TRUE, WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB, WGL_COLOR_BITS_ARB, 32, WGL_DEPTH_BITS_ARB, 24, WGL_DOUBLE_BUFFER_ARB, GL_TRUE, WGL_SWAP_METHOD_ARB, WGL_SWAP_EXCHANGE_ARB, WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, WGL_STENCIL_BITS_ARB, 8, WGL_SAMPLE_BUFFERS_ARB, GL_TRUE, WGL_SAMPLES_ARB, double_buffered ? 4 : 0, 0 }, attributeList[5] = { WGL_CONTEXT_MAJOR_VERSION_ARB, 4, WGL_CONTEXT_MINOR_VERSION_ARB, 0, 0 }; static float fAttributes[2] = { 0, 0 }; static const D3D_FEATURE_LEVEL d3dFeatureLevels[7] = { D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_9_3, D3D_FEATURE_LEVEL_9_2, D3D_FEATURE_LEVEL_9_1 }; static D2D1_SIZE_U d2d1SizeU = {}; static const LPCWSTR m_title = L"Title"; static const WCHAR sc_helloWorld[] = L"Hello World!"; static WCHAR szBitmapName[] = L"IN_BITMAP"; static stringstream sS; /* gradient stop collection */ static ID2D1GradientStopCollection* pD2DGradientStopCollection = nullptr; static D2D1_GRADIENT_STOP pD2DGadientStop[gradientStopInt]; static ID2D1LinearGradientBrush* pLinearGradientBrush; static const D2D1::ColorF::Enum colorS[11] = { D2D1::ColorF::White, D2D1::ColorF::LightGray, D2D1::ColorF::Gray, D2D1::ColorF::DarkGray, D2D1::ColorF::Black, D2D1::ColorF::Red, D2D1::ColorF::Purple, D2D1::ColorF::Blue, D2D1::ColorF::Green, D2D1::ColorF::Yellow, D2D1::ColorF::Orange }; static COLORREF colors = RGB(0, 0, 0); static COLORREF colRefs[8] = { /* black - 000000, white - FFFFFF, */ RGB(0, 0, 0) , RGB(255, 255, 255) , /* red - FF0000, orange - FF6600, */ RGB(255, 0, 0) , RGB(255, 128, 0) , /* yellow - FFFF00, green - 00FF00, */ RGB(255, 255, 0) , RGB(0, 255, 0) , /* blue - 0000FF, purple - FF00FF, */ RGB(0, 0, 255) , RGB(255, 0, 255) }; const string deviceInfoStr[22]{ "The device driver version", "Width, in millimeters, of the physical screen", "Height, in millimeters, of the physical screen", "Width, in pixels, of the screen; or for printers", "Height, in raster lines, of the screen; or for printers", "Number of adjacent color bits for each pixel", "Number of color planes", "Number of device-specific brushes", "Number of device-specific pens", "Number of device-specific fonts", "Number of entries in the device's color table", "clipping capabilities of the device", "Number of entries in the system palette", "color resolution of the device, in bits per pixel", "current vertical refresh rate of device, in cycles per second", "shading and blending capabilities of the device", "raster capabilities of the device", "curve capabilities of the device", "line capabilities of the device", "polygon capabilities of the device", "text capabilities of the device", "color management capabilities of the device" }; const D3D11_INPUT_ELEMENT_DESC polygonLayout[2] = {}; const D3D11_BUFFER_DESC matrixBufferDesc = {}; static unsigned int numElements = 0; #pragma region Input Assembler (IA) Stage /* Vertex Structure */ const struct Vertex //Overloaded Vertex Structure { Vertex() {} Vertex(float x, float y, float z) : pos(x, y, z) {} XMFLOAT3 pos = {}; Vertex(const XMFLOAT3& pos) : pos(pos) { } }; /* input layout description */ const D3D11_INPUT_ELEMENT_DESC layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; static UINT numbElements = ARRAYSIZE(layout); static PAINTSTRUCT paintStruct; static HGDIOBJ originalObj; static HINSTANCE hInst; static RECT rect; static HPEN pen; /* Windows globals, defines, and prototypes */ static CHAR szAppName[] = "Win32 OpenGL Engine"; static HWND ghWnd; static HDC ghDC; static HGLRC ghRC; static bool simpleOgl, complexOgl; #define SWAPBUFFERS SwapBuffers(ghDC) #pragma endregion #pragma region Note : Enum /* "enum" enum is a user defined data type where we specify a set of values for a variable and the variable can only take one out of a small set of possible values. We use enum keyword to define an Enumeration. enum direction {East, West, North, South}dir; Here Enumeration name is direction which can only take one of the four specified values, the dir at the end of the declaration is an enum variable. */ #pragma endregion // declaring data type const enum yearlyMonths { jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec }; static yearlyMonths month; const enum weekDays { sun, mon, tues, wed, thurs, fri, sat }; static weekDays day; // a variable holds the value of constant static enum weekDays day1 = sun; /* example of use * cycle through the months of the year for (int m = jan; m < dec; m += 30) {} */ static PTSTR pstr = const_cast(L"GetProcessId"); /* Rendering Context */ //--- PRIVATE TYPES ----------------------------------- typedef vector video_context_t; typedef vector video_contexts_t; //--- PRIVATE DATA ------------------------------------ static video_contexts_t video_contexts; #pragma endregion #pragma region Global Functions static void mylog(const string& str) { if (logged) { if (!fileOpened) { /* Constant Explanation ios_base::app seek to the end of stream before each writing ios_base::binary open in binary mode ios_base::in open for reading ios_base::out open for writing ios_base::trunc discard the contents of the stream when opening ios_base::ate seek to the end of stream immediately after open */ writefile.open(logFile, std::ios_base::app); if (writefile.is_open()) { writefile << str << std::endl; /*writefile.write(str.data(), str.size());*/ } //writefile.close(); fileOpened = true; } else if (writefile.is_open()) { writefile << str << std::endl; /*writefile.write(str.data(), str.size());*/ } //writefile.close(); } else { // overwrite /* Constant Explanation ________________________________ app seek to the end of stream before each write binary open in binary mode in open for reading out open for writing trunc discard the contents of the stream when opening ate seek to the end of stream immediately after open noreplace (C++23) open in exclusive mode */ writefile.open(logFile, std::ios_base::out); if (writefile.is_open()) { writefile << "LOG" << std::endl; /*writefile.write(str.data(), str.size());*/ } writefile.close(); logged = true; } } /* copy in binary mode */ static bool copyFile(const char* SRC, const char* DEST) { std::ifstream src(SRC, std::ios::binary); std::ofstream dest(DEST, std::ios::binary); dest << src.rdbuf(); return src && dest; } static void writingString(const string& str) { writeStr = str; mylog(writeStr); } static void createLogFile() { /* set path for log file */ logFile = pth; logFile += "\\log.txt"; text = "\n "; writingString(text); text = "\t\tworkingDirFilepath " + pth; writingString(text); /*writefile.close();*/ } static bool convertLPW2stdstring( string& s, const LPWSTR pw, UINT codepage = CP_ACP) { bool res = false; char* p = 0; int bsz = 0; bsz = WideCharToMultiByte( codepage, 0, pw, -1, 0, 0, 0, 0); if (bsz > 0) { p = new char[bsz]; int rc = WideCharToMultiByte( codepage, 0, pw, -1, p, bsz, 0, 0); if (rc != 0) { p[bsz - 1] = 0; s = p; res = true; } } /*MessageBox(NULL, pw, L"PWSTR to string directory", MB_OK);*/ delete[] p; return res; } static void stringToPcwStr(const string& str) { // Initializing an object of wstring wstring temp = wstring(str.begin(), str.end()); // Applying c_str() method on temp LPCWSTR wideString = temp.c_str(); /*MessageBox(NULL, wideString, L"stringToPcwStr directory", MB_OK);*/ } static string WStringToString(const wstring& wstr, string& str) { size_t size; str.resize(wstr.length()); wcstombs_s(&size, &str[0], str.size() + 1, wstr.c_str(), wstr.size()); /* pwstr to string */ return str; } //static void getCurrentDir(const char* buff) { // /* Directory - Locate Working Directory */ // // /* conversion */ // /* length of the wchar_t string called wcstring in terms of the number // of wide characters, not the number of bytes */ // size_t newsize = strlen(buff) + 1; // // /* create a buffer large enough to contain the exact number of characters // in the original string in the new format. If you want to add more characters // to the end of the string, increase the value of newsize to increase the size // of the buffer */ // wchar_t* wcstring = new wchar_t[newsize]; // // /* Convert char* string to a wchar_t* string. */ // size_t convertedChars = 0; // mbstowcs_s(&convertedChars, wcstring, newsize, buff, _TRUNCATE); // // /*USES_CONVERSION; // TCHAR* tcString = W2T(wcstring);*/ // PWSTR pwsStr = wcstring; // // /* Retrieves the fully qualified path for the file that contains the // specified module. The module must have been loaded by the current process. // // To locate the file for a module that was loaded by another process, use // the GetModuleFileNameEx function. */ // GetModuleFileName( // /* A handle to the loaded module whose path is being requested. // If this parameter is NULL, GetModuleFileName retrieves the path of // the executable file of the current process. */ // NULL, // /* A pointer to a buffer that receives the fully qualified path of the // module. If the length of the path is less than the size that the nSize // parameter specifies, the function succeeds and the path is returned as // a null-terminated string. // // If the length of the path exceeds the size that the nSize parameter // specifies, the function succeeds and the string is truncated to nSize // characters including the terminating null character. // // The string returned will use the same format that was specified when // the module was loaded. Therefore, the path can be a long or short file // name, and can use the prefix \\?\ */ // pwsStr, // /* The size of the lpFilename buffer, in TCHARs. */ // MAX_PATH); // /* If the function succeeds, the return value is the length of the string that // is copied to the buffer, in characters, not including the terminating null // character. If the buffer is too small to hold the module name, the string is // truncated to nSize characters including the terminating null character, the // function returns nSize, and the function sets the last error to // ERROR_INSUFFICIENT_BUFFER. */ // //} static void getWorkingDir() { wchar_t* wcstring = {}; TCHAR buffer[MAX_PATH] = { 0 }; GetModuleFileName(NULL, buffer, MAX_PATH); /* directory */ wstring directory(buffer); string str1 = ""; WStringToString(directory, str1); workingDirFilepath = str1; /* Removes the last element in a path string, whether that element is a file name or a directory name. The element's leading backslash is also removed. This function differs from PathRemoveFileSpec in that it accepts paths with "\", "\?" and "\?\UNC" prefixes. */ /* Get directory or filename from a full path */ directoryPath = buffer; HRESULT res = PathCchRemoveFileSpec(directoryPath, _MAX_PATH); if (res == S_OK) { /* path / directory */ wstring filename(directory.substr(directory.length())); /* wstring to string */ string str1 = ""; WStringToString(filename, str1); workingDirFilepath = str1; ///* string to pcwstr */ //stringToPcwStr(workingDirFilepath); /* string to PWSTR - garbage */ /*LPWSTR pwstr = new wchar_t[workingDirFilepath.size() + 1]; MessageBox(NULL, pwstr, L"PWSTR directory", MB_OK);*/ /* convert string to WCHAR */ WCHAR* wcStr = reinterpret_cast(&workingDirFilepath); /* convert array to PWSTR */ /*string::size_type position = string(str).find_last_of("\\/"); return string(str).substr(0, position);*/ /* wstring to string */ WStringToString(directory, pth); /*MessageBox(NULL, directoryPath, L"directory", MB_OK);*/ /* stringstream does not work */ sS << directoryPath; sS >> pth; /* convert to char */ char* dp = reinterpret_cast(directoryPath); /* convert to basic string */ string basicstring(dp); pth = basicstring; /* convert PWDTR to string */ wcstring = directoryPath; convertLPW2stdstring(pth, wcstring); } } static void Init() { /* define variables */ // int nWidth = SCREEN_WIDTH; nHeight = SCREEN_HEIGHT; screenW = GetSystemMetrics(SM_CXSCREEN); screenH = GetSystemMetrics(SM_CYSCREEN); screenX = 0; screenY = 0; method = 1; rendtarget = 0; d3dStep = 0; colR = 0; colG = 0; colB = 0; colA = 0; pixx = 0; pixy = 0; pixSizeW = 0; pixSizeH = 0; colModr = 1; colModg = 1; colModb = 1; bitmapSize = 0; bmpOptions = 1; trySwapChain = 0; swapchain = 0; propsNum = 0; dxgiUse = 0; targets = 0; dcTargetAtempts = 0; // float colorR = 0.0f; colorG = 0.0f; colorB = 0.0f; colors = RGB(colorR, colorG, colorB); col = 0.5f; colAlpha = 0.5f; // bool FULL_SCREEN = false; VSYNC_ENABLED = true; DXGIFail = false; windowCreated = false; methods = true; result = false; okay = false; logged = false; fileOpened = false; enableOpenGL = false; enableD2D = false; enableD3D = false; winReady = false; oneBrush = true; multiSampling = false; swapChainCreated = false; canDraw = false; linearGradientBrushCreated = false; surfaceRendered = false; surfaceCreated = false; d2dContextCreated = false; dcTarget = false; // string target = ""; } static float getPercentage(const float& value, const float& input) { float returnValue = value / 100.0f * input; text = "\t\t\t value to clip " + to_string(returnValue); writingString(text); return returnValue; } #pragma endregion // File // App.h _________________________________________________________________________________ #pragma once #include "Prerequisites.h" /* functions for releasing interfaces */ template inline void App_SafeRelease( Interface** ppInterfaceToRelease) { if (*ppInterfaceToRelease != NULL) { (*ppInterfaceToRelease)->Release(); (*ppInterfaceToRelease) = NULL; } } ///* macros for error-handling and retrieving the module's base address */ //#ifndef Assert //#if defined( DEBUG ) || defined( _DEBUG ) //#define Assert(b) do {if (!(b)) {OutputDebugStringA("Assert: " #b "\n"); }} while (0) //#else //#define Assert(b) //#endif //DEBUG || _DEBUG //#endif // //#ifndef HINST_THISCOMPONENT //EXTERN_C IMAGE_DOS_HEADER __ImageBase; //#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase) //#endif class App { public: App(); ~App(); /* Register the window class and call methods for instantiating drawing resources */ HRESULT App_Initialize(); /* Process and dispatch messages */ void App_RunMessageLoop(); private: /* Get Desktop Resolution */ void App_GetDesktopResolution(); /* Initialize device-independent resources. */ HRESULT App_CreateDeviceIndependentResources(); /* Initialize device-dependent resources. */ HRESULT App_CreateDeviceResources(const HWND& hwnd); /* Create main window */ bool App_CreateMainWindow( const int& x, const int& y, const int& w, const int& h); /* Registere window class */ HRESULT App_RegisterWinClass(const HINSTANCE& hInstance); /* Draw content. */ HRESULT App_OnRender(const HWND& hwnd); /* test Drawing */ HRESULT App_Draw(const string& str); /* Resize the render target. */ HRESULT App_OnResize(const HWND& hwnd, UINT width, UINT height); /* Release device-dependent resource. */ void App_DiscardDeviceResources(); /* Releases */ void App_Release(); /* The windows procedure. */ static LRESULT CALLBACK App_WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ); HRESULT App_CreateD3D11Device(); HRESULT App_CreateSwapChain(const HWND& hWnd); HRESULT App_EnumerateGraphicsAdapters(); HRESULT App_GetVideoCardInfo(); HRESULT App_UseSwapChain(const HWND& hwnd); void App_SetUpViewport(); HRESULT App_CreateD2D1DeviceAndContext(); HRESULT App_UseD2DDeviceContext(); HRESULT App_CreateD3DTexture2D(const HWND& hwnd); HRESULT App_CreateDXGISurface(const HWND& hwnd); HRESULT App_UseDxgiSurface(const HWND& hwnd); HRESULT App_CreateBitmapFromDXGI_Surface(const HWND& hwnd); HRESULT App_CreateDXGI_SurfaceRenderTarget(const HWND& hwnd); void App_GetTargetPropertiesDPIs( const HWND& hwnd, D2D1_BITMAP_PROPERTIES1& bmpProps, D2D1_RENDER_TARGET_PROPERTIES& rtProps); HRESULT App_CreateRenderTargetResources(); HRESULT App_DrawGradientBackground(); HRESULT App_RandomizerushColors( const float& sx, const float& sy, const float& ex, const float& ey, const float& a ); HRESULT App_GetPresentFrameStats(); HRESULT App_SwapChainPresent(); HRESULT App_FactoryLock(); /* declare pointers */ HDC dc; RECT rect; HWND app_hwnd; HINSTANCE app_hinstance; LPCWSTR app_applicationName; /*ID2D1Factory* app_pDirect2dFactory;*/ ID2D1HwndRenderTarget* app_pHwndRenderTarget; ID2D1SolidColorBrush* app_rtSolidColorBrush; ID2D1SolidColorBrush* app_dcSolidColorBrush; IDXGIFactory* app_pDXGIFactory; ID2D1Factory1* app_pDirect2dFactory1, * app_pD2DFactory1; D2D1_FACTORY_TYPE factoryType; ID3D11Device* app_pD3D11Device; ID3D11DeviceContext* app_pD3D11DeviceContext; ID2D1Device* app_pD2DDevice; ID2D1Device1* app_pD2DDevice1; IDXGIAdapter* app_pDXGIAdapter; ID2D1DeviceContext* app_pD2DDeviceContext; ID2D1DeviceContext1* app_pD2DDeviceContext1; IDXGISwapChain1* app_pDXGISwapChain1; IDXGISwapChain* app_pDXGISwapChain; IDXGIFactory2* app_pDXGIFactory2; DXGI_PRESENT_PARAMETERS app_pDXGIPresentParameters; D2D1_RENDER_TARGET_PROPERTIES app_d2dRenderTargetProps; D2D1_ALPHA_MODE app_d2dAlphaMode; DXGI_ALPHA_MODE app_dxgiAlphaMode; DXGI_FORMAT app_dxgiFormat; DXGI_SCALING app_dxgiScaling; IDXGIDevice* app_pDXGIDevice; IDXGIDevice1* app_pDXGIDevice1; DXGI_MODE_DESC app_bufferDesc; DXGI_MODE_DESC* app_displayModes; IDXGIOutput* app_pDXGIOutput; DXGI_ADAPTER_DESC app_dxgiAdapterDesc; DXGI_SWAP_CHAIN_DESC1 app_pDXGISwapChainDesc; D3D11_TEXTURE2D_DESC app_pD3D11Texture2DDesc; ID3D11Texture2D* app_swapChainD3D11Texture2D; ID3D11Texture2D* app_deviceD3D11Texture2D; IDXGISurface* app_pDXGISurface; ID3D11Resource* app_pD3D11Resource; // resource render target ID3D11RenderTargetView* app_texture2dRenderTargetView; ID3D11RenderTargetView* app_resourceRenderTargetView; D3D11_VIEWPORT app_d3d11Viewport; D2D1_BITMAP_PROPERTIES1 app_pD2DBitmapProps; D2D1_RENDER_TARGET_PROPERTIES app_pD2DRenderTargetProps; ID2D1Bitmap1* app_pD2DTargetBitmap; D2D1_PIXEL_FORMAT app_pD2DPixelFormat; ID2D1RenderTarget* app_pD2DRenderTarget; ID2D1BitmapBrush* app_direct2dBitmapBrush; ID2D1LinearGradientBrush* app_LinearGradientBrush; D2D1_BITMAP_INTERPOLATION_MODE app_pD2DBitmapInterpolationMode; ID2D1Multithread* app_pD2DMultithread; UINT app_bufferCount; UINT app_pLastPresentCount; DXGI_FRAME_STATISTICS app_pDXGIFrameStats; int nX, nY; unsigned int d2dNumerator, d2dDenominator; int videoCardMemory; char videoCardDescription[128] = {}; /* Gradient brushes parameters */ float colorAlpha, startPointx, startPointy, endPointx, endPointy, cRed, cGreen, cBlue; bool lock; public: bool operator==(const App& other) const { return false; } }; // File // App.cpp _________________________________________________________________________________ #include "App.h" #pragma region Constructor & Deconstructor /* constructor initialize its members */ App::App() : rect(), dc(nullptr), app_hwnd(nullptr), app_hinstance(GetModuleHandle(nullptr)), app_applicationName(L"Win32 OpenGL Engine"), /*app_pDirect2dFactory(nullptr),*/ app_pHwndRenderTarget(nullptr), app_rtSolidColorBrush(nullptr), // render target brush app_dcSolidColorBrush(nullptr), // device context brush app_pDXGIFactory(nullptr), /*app_pDirect2dFactory1(nullptr),*/ app_pD2DFactory1(nullptr), factoryType(D2D1_FACTORY_TYPE_MULTI_THREADED), // (D2D1_FACTORY_TYPE_SINGLE_THREADED), // app_pD3D11Device(nullptr), app_pD3D11DeviceContext(nullptr), app_pD2DDevice(nullptr), app_pD2DDevice1(nullptr), app_pD2DDeviceContext(nullptr), app_pD2DDeviceContext1(nullptr), app_pDXGIAdapter(nullptr), app_pDXGIDevice(nullptr), app_pDXGIDevice1(nullptr), app_pDXGISwapChain1(nullptr), app_pDXGISwapChain(nullptr), app_pDXGIFactory2(nullptr), app_bufferDesc(), app_displayModes(), app_pDXGIOutput(nullptr), app_swapChainD3D11Texture2D(nullptr), app_deviceD3D11Texture2D(nullptr), app_pDXGISurface(nullptr), app_pD3D11Resource(nullptr), app_texture2dRenderTargetView(nullptr), app_resourceRenderTargetView(nullptr), app_d3d11Viewport(), app_pD2DTargetBitmap(nullptr), app_pD2DRenderTarget(nullptr), app_LinearGradientBrush(nullptr), app_direct2dBitmapBrush(nullptr), app_pD2DMultithread(nullptr), app_bufferCount(3), app_pLastPresentCount(0), nX(0), nY(0), d2dNumerator(0), d2dDenominator(0), videoCardMemory(0), colorAlpha(), startPointx(), startPointy(), endPointx(), endPointy(), cRed(0.0f), cGreen(0.25f), cBlue(1.0f), lock(false) { app_d2dRenderTargetProps = D2D1::RenderTargetProperties(); app_d2dAlphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED; app_dxgiAlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED; app_dxgiFormat = DXGI_FORMAT_B8G8R8A8_UNORM; app_dxgiScaling = {}; app_dxgiAdapterDesc = {}; app_pDXGIPresentParameters = {}; app_pDXGISwapChainDesc = {}; app_pD3D11Texture2DDesc = {}; app_pD2DBitmapProps = {}; app_pD2DRenderTargetProps = {}; app_pD2DPixelFormat = {}; /* Interpolate a color from the four bitmap pixels nearest to the rendering pixel */ app_pD2DBitmapInterpolationMode = D2D1_BITMAP_INTERPOLATION_MODE_LINEAR; app_pDXGIFrameStats = {}; } /* destructor releases any interfaces that are stored as class members */ App::~App() { App_SafeRelease(&app_pD2DMultithread); DeleteObject(app_direct2dBitmapBrush); DeleteObject(app_LinearGradientBrush); App_SafeRelease(&app_direct2dBitmapBrush); App_SafeRelease(&app_LinearGradientBrush); App_SafeRelease(&app_pD2DRenderTarget); App_SafeRelease(&app_pD2DTargetBitmap); App_SafeRelease(&app_texture2dRenderTargetView); App_SafeRelease(&app_resourceRenderTargetView); App_SafeRelease(&app_pD3D11Resource); App_SafeRelease(&app_pDXGISurface); App_SafeRelease(&app_deviceD3D11Texture2D); App_SafeRelease(&app_swapChainD3D11Texture2D); App_SafeRelease(&app_dcSolidColorBrush); App_SafeRelease(&app_rtSolidColorBrush); App_SafeRelease(&app_pHwndRenderTarget); /*App_SafeRelease(&app_pDirect2dFactory);*/ App_SafeRelease(&app_pDXGIOutput); App_SafeRelease(&app_pDXGISwapChain1); App_SafeRelease(&app_pDXGISwapChain); App_SafeRelease(&app_pDXGIFactory2); App_SafeRelease(&app_pDXGIAdapter); App_SafeRelease(&app_pDXGIDevice); App_SafeRelease(&app_pDXGIDevice1); App_SafeRelease(&app_pD2DDeviceContext); App_SafeRelease(&app_pD2DDeviceContext1); App_SafeRelease(&app_pD2DDevice); App_SafeRelease(&app_pD2DDevice1); App_SafeRelease(&app_pD3D11DeviceContext); App_SafeRelease(&app_pD3D11Device); App_SafeRelease(&app_pD2DFactory1); app_pD2DFactory1 = nullptr; /*App_SafeRelease(&app_pDirect2dFactory1);*/ App_SafeRelease(&app_pDXGIFactory); DeleteDC(dc); } #pragma endregion #pragma region Functions HRESULT App::App_Initialize() { HRESULT hr = S_OK; bool result = false; Init(); getWorkingDir(); createLogFile(); #pragma region write log text = "\tInitialize "; writingString(text); text = "\t\tGetDesktopResolution "; writingString(text); #pragma endregion App_GetDesktopResolution(); /* Initialize device-indpendent resources, such as the Direct2D factory */ hr = App_CreateDeviceIndependentResources(); if (SUCCEEDED(hr)) { /* Register the window class */ hr = App_RegisterWinClass(app_hinstance); if (SUCCEEDED(hr)) { /* Create the window */ /*######################################################################*/ /*---------------------------- CREATE WINDOW --------------------------*/ /*######################################################################*/ result = App_CreateMainWindow(screenX, screenY, nWidth, nHeight); if (result) { /* Create the window's device-dependent resources */ hr = App_CreateDeviceResources(app_hwnd); if (SUCCEEDED(hr)) { /*canDraw = true;*/ App_OnRender(app_hwnd); target = targetType[0]; hr = App_Draw(target); if (SUCCEEDED(hr)) { text = "\tRender Target Drawing Succeeded "; writingString(text); } } /*##################################################*/ /*-------------- D3D11 DEVICE & CONTEXT ------------*/ /*##################################################*/ text = "\tCreateD3D11Device "; writingString(text); /* Create 1) a Direct3D11 device and device context */ hr = App_CreateD3D11Device(); if (SUCCEEDED(hr)) { #pragma region write log text = "\t\tSucceeded!\n"; writingString(text); text = "AVAILABLE : D3D Device - app_pD3D11Device\n "; writingString(text); text = "\n*** D3D11Device & Contect created ***\n"; writingString(text); #pragma endregion /* Create 2) a DXGI device used to create bitmap surfaces. */ //hr = app_pD3D11Device->QueryInterface(&app_pDXGIDevice1); /* or... */ #pragma region write log text = "\tObtain DXGI device (app_pDXGIDevice1) "; writingString(text); text = "\t\tof the Direct3D11 device (app_pD3D11Device)"; writingString(text); text = "\tapp_pD3D11Device => app_pDXGIDevice1"; writingString(text); #pragma endregion /*##################################################*/ /*------------------- DXGI DEVICE ------------------*/ /*##################################################*/ /* Obtain the underlying DXGI device of the Direct3D11 device */ hr = app_pD3D11Device->QueryInterface( (IDXGIDevice1**)&app_pDXGIDevice1); if (SUCCEEDED(hr)) { text = "\t\tSucceeded!\n "; writingString(text); /* Ensure DXGI doesn't queue more than one frame at a time */ app_pDXGIDevice1->SetMaximumFrameLatency(1); /*##################################################*/ /*----------------- DXGI SWAP CHAIN ----------------*/ /*##################################################*/ text = "\tCreateSwapChain "; writingString(text); /* Create 3) a dxgi Swap Chain */ hr = App_CreateSwapChain(app_hwnd); if (SUCCEEDED(hr)) { #pragma region write log text = "\t\tSucceeded!\n "; writingString(text); text = "\tEnumerateGraphicsAdapters "; writingString(text); #pragma endregion /* Enumerate Graphics Adapters */ hr = App_EnumerateGraphicsAdapters(); if (SUCCEEDED(hr)) { #pragma region write log text = "\t\tSucceeded!\n "; writingString(text); text = "\tGetVideoCardInfo "; writingString(text); #pragma endregion /* Get Video Card Information */ hr = App_GetVideoCardInfo(); if (SUCCEEDED(hr)) { text = "\t\tSucceeded!\n "; writingString(text); } } /*##################################################*/ /*------------------ USE SWAP CHAIN ----------------*/ /*##################################################*/ /* After you create a swap chain, you will typically want to render images into it */ text = "\tUse Swap Chain "; writingString(text); hr = App_UseSwapChain(app_hwnd); if (SUCCEEDED(hr)) { text = "\t\tSucceeded!\n "; writingString(text); } } /*##################################################*/ /*--------------- D2D DEVICE & CONTEXT -------------*/ /*##################################################*/ text = "\tCreate D2D1Device And Context "; writingString(text); /* Create 4) a Direct2D device and a Direct2D device context */ hr = App_CreateD2D1DeviceAndContext(); if (SUCCEEDED(hr)) { text = "\n*** D2D1Device And Context Created ***\n "; writingString(text); d2dContextCreated = true; } } /*##################################################*/ /*----------------- D3D11 TEXTURE2D ----------------*/ /*##################################################*/ text = "\tDevice Context CreateD3DTexture2D "; writingString(text); hr = App_CreateD3DTexture2D(app_hwnd); if (SUCCEEDED(hr)) { text = "\t\tSucceeded \n "; writingString(text); text = "\tCreateDXGISurface "; writingString(text); /*##################################################*/ /*------------------- DXGI SURFACE -----------------*/ /*##################################################*/ hr = App_CreateDXGISurface(app_hwnd); if (SUCCEEDED(hr)) { text = "\t\tSucceeded \n "; writingString(text); text = "\tget the size of the back buffer "; writingString(text); /* Swap chain can get the size of the back buffer */ hr = app_pDXGISwapChain1->GetDesc1(&app_pDXGISwapChainDesc); if (SUCCEEDED(hr)) { text = "\t\tSuccess \n "; writingString(text); text = "\tCreateRenderTargetResources "; writingString(text); /* use dxgi render target*/ if (targets == 2) { //app_pD2DRenderTarget hr = App_CreateRenderTargetResources(); if (SUCCEEDED(hr)) { text = "\t\tSuccess \n "; writingString(text); } } } } } /* A device context is a device that can perform drawing operations and create device-dependent drawing resources such as brushes. You also use the device context to link a ID2D1Bitmap to a DXGI surface to use as a render target. The device context can render to different types of targets. */ if (d2dContextCreated) { /* check if format is supported by the device context */ bool res = app_pD2DDeviceContext->IsDxgiFormatSupported( app_dxgiFormat); if (res) { text = "Format is supported "; writingString(text); } else { text = "Format is not supported "; writingString(text); } if (dcTarget) { hr = App_UseD2DDeviceContext(); if (SUCCEEDED(hr)) { text = "\t\tSuccess \n "; writingString(text); } /* change color of render target solid color brush */ app_rtSolidColorBrush->SetColor( D2D1::ColorF(D2D1::ColorF::Crimson, 1.0f)); target = targetType[3]; hr = App_Draw(target); if (SUCCEEDED(hr)) { text = "\t\tSuccess \n "; writingString(text); lock = true; App_FactoryLock(); App_SwapChainPresent(); if (SUCCEEDED(hr)) { text = "\t\tPresented! \n "; writingString(text); App_GetPresentFrameStats(); /* Gets the number of times that IDXGISwapChain::Present or IDXGISwapChain1::Present1 has been called */ hr = app_pDXGISwapChain1->GetLastPresentCount( &app_pLastPresentCount); if (SUCCEEDED(hr)) { text = "\tPresent Count " + to_string(app_pLastPresentCount); writingString(text); } } lock = false; App_FactoryLock(); } } } } } } } return hr; } void App::App_GetDesktopResolution() { RECT desktop; /* Get a handle to the desktop window */ HWND hDesktop = GetDesktopWindow(); /* Get the size of screen to the variable desktop */ GetWindowRect(hDesktop, &desktop); /* The top left corner will have coordinates (0,0) The bottom right corner will have coordinates (horizontal, vertical) */ pixSizeW = desktop.right; screenW = desktop.right; pixSizeH = desktop.bottom; screenH = desktop.bottom; text = "\t\tscreenWidth " + to_string(screenW); writingString(text); text = "\t\tscreenHeight " + to_string(screenH); writingString(text); /* Set Window Size */ float hValue = 2.5f, vValue = 5.0f; percentReturnValue = getPercentage(hValue, (float)screenW); nWidth = screenW - (int)percentReturnValue; percentReturnValue = getPercentage(vValue, (float)screenH); nHeight = screenH - (int)percentReturnValue; text = "\t\twindowWidth " + to_string(nWidth); writingString(text); text = "\t\twindownHeight " + to_string(nHeight); writingString(text); /* Set Window Position */ nX = (screenW - nWidth) / 2; nY = (screenH - nHeight) / 2; text = "\t\tpositionX " + to_string(nX); writingString(text); text = "\t\tpositionY " + to_string(nY); writingString(text); } /***********************************************************************************/ /*################################# FACTORY #################################*/ /***********************************************************************************/ /* device-independent resources can last for the duration of the application */ HRESULT App::App_CreateDeviceIndependentResources() { HRESULT hr = S_OK; ////////////////////////////////////////////////////////////////// /* Step 1 - Create a DIRECT2D FACTORY */ ////////////////////////////////////////////////////////////////// #if defined(DEBUG) || defined(_DEBUG) /* The ID2D1Factory1 interface is the starting point for using Direct2D; Use an ID2D1Factory1 to create Direct2D resources.*/ /* The debug layer should never be active in the release version of an application */ /* The value D2D1_DEBUG_LEVEL_NONE(none) indicates that Direct2D does not provide any debugging output. */ D2D1_FACTORY_OPTIONS options; /* To avoid any undesired effects of optimizing compilers */ ZeroMemory(&options, sizeof(D2D1_FACTORY_OPTIONS)); /* D2D1_DEBUG_LEVEL_INFORMATION - Value: 3 Direct2D sends error messages, warnings, and additional diagnostic information that can help improve performance to the debug layer */ options.debugLevel = D2D1_DEBUG_LEVEL::D2D1_DEBUG_LEVEL_INFORMATION; /* The ID2D1Factory1 interface is the starting point for using Direct2D; use an ID2D1Factory1 to create Direct2D resources */ //text = "\tCreate D2D Factory (app_pDirect2dFactory)"; writingString(text); ///* Create a Direct2D factory */ //hr = D2D1CreateFactory( // /* Singlethreaded and Multithreaded Factories // When you create a factory, you can specify whether it is // multithreaded or singlethreaded. A singlethreaded // factory provides no serialization against any other // single threaded instance within Direct2D, so, this // mechanism provides a very large degree of scaling on the // CPU. // You can also create a multithreaded factory instance. // In this case, the factory and all derived objects can // be used from any thread and each render target can be // rendered to independently. Direct2D serializes calls to // these objects, so a single multithreaded Direct2D // instance won't scale as well on the CPU as many single // threaded instances. However, the resources can be shared // within the multithreaded instance. // Note that the qualifier "On the CPU": GPUs generally // take advantage of fine-grained parallelism more so than // CPUs. For example, multithreaded calls from the CPU // might still end up being serialized when being sent to // the GPU, however, a whole bank of pixel and vertex // shaders will run in parallel to perform the rendering */ // factoryType, // factory type - multi- or single-threaded // options, // factory options // &app_pDirect2dFactory); // d2d factory //if (SUCCEEDED(hr)) { // text = "\t\tSuccess!"; writingString(text); // text = "AVAILABLE : D2D1Factory - app_pDirect2dFactory "; writingString(text); //} text = "\tCreate D2D Factory (app_pD2DFactory1)"; writingString(text); hr = D2D1CreateFactory( factoryType, __uuidof(ID2D1Factory1), &options, (void**)&app_pD2DFactory1); if (SUCCEEDED(hr)) { text = "\t\tSuccess!"; writingString(text); text = "AVAILABLE : D2D1Factory1 - app_pD2DFactory1 "; writingString(text); } #else /* Create a Direct2D factory. */ /* ID2D1Factory is a device-independent resource for creating other Direct2D resources */ hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &app_pDirect2dFactory); #endif return hr; } HRESULT App::App_RegisterWinClass(const HINSTANCE& hInstance) { HRESULT hr = S_OK; WNDCLASSEX wcex = { sizeof(WNDCLASSEX) }; wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = App::App_WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = sizeof(LONG_PTR); wcex.hInstance = HINST_THISCOMPONENT; wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 3); wcex.lpszMenuName = NULL; wcex.hCursor = LoadCursor(NULL, IDI_APPLICATION); wcex.lpszClassName = app_applicationName; RegisterClassEx(&wcex); return hr; } bool App::App_CreateMainWindow( const int& x, const int& y, const int& w, const int& h) { bool result = false; /* In terms of using the correct DPI, to create a window at a specific size, the procedure is to first create the window hidden. Then we get the actual DPI from the HWND (which will be assigned by whichever monitor the window is created on). Then we use SetWindowPos to resize it to the correct DPI-scaled size, then we use ShowWindow to show it. */ app_hwnd = CreateWindow( app_applicationName, app_applicationName, WS_OVERLAPPEDWINDOW, nX, // CW_USEDEFAULT, // nY, // CW_USEDEFAULT, // nWidth, // 0, // nHeight, // 0, // NULL, NULL, HINST_THISCOMPONENT, this ); if (app_hwnd) { result = true; /* Since the SetWindowPos function takes its size in pixels, we obtain the window's DPI, and use it to scale the window size. */ /* For Windows 10 */ //float dpi = GetDpiForWindow(app_hwnd); /* For Windows 8.1 */ FLOAT dpiX, dpiY; HDC hDCScreen = GetDC(app_hwnd); dpiX = static_cast( GetDeviceCaps(hDCScreen, LOGPIXELSX)); dpiY = static_cast( GetDeviceCaps(hDCScreen, LOGPIXELSY)); ReleaseDC(NULL, hDCScreen); SetWindowPos( app_hwnd, NULL, nX, // NULL, // nY, // NULL, // static_cast(ceil(float(nWidth)/*640.f*/ * dpiX / 96.f)), static_cast(ceil(float(nHeight)/*480.f*/ * dpiY / 96.f)), SWP_NOMOVE); dc = GetDC(app_hwnd); ShowWindow(app_hwnd, SW_SHOWNORMAL); UpdateWindow(app_hwnd); } return result; } /* Device-dependent resources are associated with a particular rendering device, and will cease to function if that device is removed */ HRESULT App::App_CreateDeviceResources(const HWND& hwnd) { HRESULT hr = S_OK; /* Since this method will be called repeatedly, we add an if statement to check whether the render target (m_pRenderTarget) already exists */ if (!app_pHwndRenderTarget) { GetClientRect(hwnd, &rect); D2D1_SIZE_U size = D2D1::SizeU( rect.right - rect.left, rect.bottom - rect.top); /* Create a pixel format and initial its format and alphaMode fields. */ D2D1_PIXEL_FORMAT pixelFormat = D2D1::PixelFormat( app_dxgiFormat, app_d2dAlphaMode ); app_d2dRenderTargetProps.pixelFormat = pixelFormat; #if defined(DEBUG) || defined(_DEBUG) /* Create a Direct2D render target. */ hr = app_pD2DFactory1->CreateHwndRenderTarget( app_d2dRenderTargetProps, D2D1::HwndRenderTargetProperties(hwnd, size), &app_pHwndRenderTarget ); #else /* Create a Direct2D render target. */ hr = app_pDirect2dFactory->CreateHwndRenderTarget( app_d2dRenderTargetProps, D2D1::HwndRenderTargetProperties(hwnd, size), &app_pHwndRenderTarget); #endif /* When you create a render target and hardware acceleration is available, you allocate resources on the computer's GPU. By creating a render target once and retaining it as long as possible, you gain performance benefits. Your application should create render targets once and hold on to them for the life of the application or until the D2DERR_RECREATE_TARGET error is received. When you receive this error, you need to recreate the render target (and any resources it created */ if (SUCCEEDED(hr)) { text = "\t\tSucceeded!\n "; writingString(text); target = targetType[0]; text = "\trender target : " + target; writingString(text); /* Create brush. */ hr = app_pHwndRenderTarget->CreateSolidColorBrush( D2D1::ColorF(D2D1::ColorF::Black, 1.0f), &app_rtSolidColorBrush ); } } return hr; } /* This method is called every time the window is painted */ HRESULT App::App_OnRender(const HWND& hwnd) { HRESULT hr = S_OK; /* Create the window's device-dependent resources */ hr = App_CreateDeviceResources(hwnd); if (SUCCEEDED(hr)) { /* initiate drawing */ app_pHwndRenderTarget->BeginDraw(); /* Set the render target's transform to the identity matrix */ app_pHwndRenderTarget->SetTransform(D2D1::Matrix3x2F::Identity()); /* clear the window */ app_pHwndRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::Black)); /* Retrieve the size of the drawing area */ D2D1_SIZE_F rtSize = app_pHwndRenderTarget->GetSize(); /* Draw a grid background */ int width = static_cast(rtSize.width); int height = static_cast(rtSize.height); app_rtSolidColorBrush->SetColor(D2D1::ColorF(D2D1::ColorF::LightSlateGray, 1.0f)); for (int x = 0; x < width; x += 10) { app_pHwndRenderTarget->DrawLine( D2D1::Point2F(static_cast(x), 0.0f), D2D1::Point2F(static_cast(x), rtSize.height), app_rtSolidColorBrush, 0.5f ); } for (int y = 0; y < height; y += 10) { app_pHwndRenderTarget->DrawLine( D2D1::Point2F(0.0f, static_cast(y)), D2D1::Point2F(rtSize.width, static_cast(y)), app_rtSolidColorBrush, 0.5f ); } /* Draw rectangles. */ D2D1_RECT_F rectangle1 = D2D1::RectF( rtSize.width / 2 - 50.0f, rtSize.height / 2 - 50.0f, rtSize.width / 2 + 50.0f, rtSize.height / 2 + 50.0f ); D2D1_RECT_F rectangle2 = D2D1::RectF( rtSize.width / 2 - 100.0f, rtSize.height / 2 - 100.0f, rtSize.width / 2 + 100.0f, rtSize.height / 2 + 100.0f ); /* Draw a filled rectangle. */ app_pHwndRenderTarget->FillRectangle(&rectangle1, app_rtSolidColorBrush); /* Draw the outline of a rectangle. */ app_rtSolidColorBrush->SetColor(D2D1::ColorF(D2D1::ColorF::CornflowerBlue, 1.0f)); app_pHwndRenderTarget->DrawRectangle(&rectangle2, app_rtSolidColorBrush); /* The EndDraw method returns an HRESULT to indicate whether the drawing operations were successful */ hr = app_pHwndRenderTarget->EndDraw(); if (hr == D2DERR_RECREATE_TARGET) { hr = S_OK; App_DiscardDeviceResources(); } } return hr; } HRESULT App::App_Draw(const string& str) { HRESULT hr = S_OK; text = "\ttarget = " + target; writingString(text); if (str == "Hwnd") { app_rtSolidColorBrush->SetColor(D2D1::ColorF( D2D1::ColorF::Aquamarine, 1.0f)); app_pHwndRenderTarget->BeginDraw(); app_pHwndRenderTarget->DrawRectangle( D2D1::RectF( rect.left + 50.0f, rect.top + 50.0f, rect.right - 50.0f, rect.bottom - 50.0f), app_rtSolidColorBrush ); hr = app_pHwndRenderTarget->EndDraw(); } else if (str == "Bitmap") { } else if (str == "DC") { /* Draw Rectangle */ app_pD2DDeviceContext->BeginDraw(); app_pD2DDeviceContext->DrawRectangle( D2D1::RectF( rect.left + 100.0f, rect.top + 100.0f, rect.right - 100.0f, rect.bottom - 100.0f), app_dcSolidColorBrush ); hr = app_pD2DDeviceContext->EndDraw(); } else if (str == "DXGI") { app_pD2DRenderTarget->BeginDraw(); /*app_pD2DRenderTarget->DrawRectangle( D2D1::RectF( rect.left + 100.0f, rect.top + 100.0f, rect.right - 100.0f, rect.bottom - 100.0f), app_rtSolidColorBrush, 3.0f );*/ //app_pD2DRenderTarget->DrawBitmap( // /* The bitmap to render */ // app_pD2DTargetBitmap, // /* The size and position, in device-independent pixels // of the area to which the bitmap is drawn */ // D2D1::RectF( // rect.left + 100.0f, // rect.top + 100.0f, // rect.right - 100.0f, // rect.bottom - 100.0f), // /* opacity value to be applied to the bitmap */ // 1.0f, // /* mode to use if the bitmap is scaled or rotated by // the drawing operation */ // app_pD2DBitmapInterpolationMode, // /* NULL to draw the entire bitmap */ // nullptr //); hr = app_pD2DRenderTarget->EndDraw(); } return hr; } HRESULT App::App_OnResize(const HWND& hwnd, UINT width, UINT height) { HRESULT hr = S_OK; if (app_pHwndRenderTarget) { /* Note: This method can fail, but it's okay to ignore the error here, because the error will be returned again the next time EndDraw is called. */ app_pHwndRenderTarget->Resize(D2D1::SizeU(width, height)); } if (app_pDXGISwapChain1 != NULL) { /* You can use the IDXGISwapChain::ResizeBuffers method to handle window resizing. Before you call ResizeBuffers, you must release all outstanding references to the swap chain's buffers. The object that typically holds a reference to a swap chain's buffer is a render-target-view. */ app_pD3D11DeviceContext->OMSetRenderTargets(0, 0, 0); App_SafeRelease(&app_texture2dRenderTargetView); App_SafeRelease(&app_resourceRenderTargetView); app_pDXGISwapChain1->ResizeTarget(app_displayModes); /* Preserve the existing buffer count and format. Automatically choose the width and height to match the client rect for HWNDs */ hr = app_pDXGISwapChain1->ResizeBuffers( app_bufferCount, 0/*width*/, 0/*height*/, app_dxgiFormat, 0); if (SUCCEEDED(hr)) { text = "\t\tSuccessfully resized buffers "; writingString(text); hr = App_UseSwapChain(hwnd); if (SUCCEEDED(hr)) { text = "\t\tSuccessfully restored swap chain buffer references \n "; writingString(text); /* restored references to the swap chain's buffers */ } } } return hr; } void App::App_DiscardDeviceResources() { App_SafeRelease(&app_rtSolidColorBrush); App_SafeRelease(&app_dcSolidColorBrush); App_SafeRelease(&app_pHwndRenderTarget); } void App::App_Release() { DeleteObject(app_direct2dBitmapBrush); DeleteObject(app_LinearGradientBrush); App_SafeRelease(&app_direct2dBitmapBrush); App_SafeRelease(&app_LinearGradientBrush); App_SafeRelease(&app_pD2DRenderTarget); App_SafeRelease(&app_pD2DTargetBitmap); App_SafeRelease(&app_texture2dRenderTargetView); App_SafeRelease(&app_resourceRenderTargetView); App_SafeRelease(&app_pD3D11Resource); App_SafeRelease(&app_pDXGISurface); App_SafeRelease(&app_deviceD3D11Texture2D); App_SafeRelease(&app_swapChainD3D11Texture2D); App_SafeRelease(&app_dcSolidColorBrush); App_SafeRelease(&app_rtSolidColorBrush); App_SafeRelease(&app_pHwndRenderTarget); /*App_SafeRelease(&app_pDirect2dFactory);*/ App_SafeRelease(&app_pDXGIOutput); App_SafeRelease(&app_pDXGISwapChain1); App_SafeRelease(&app_pDXGISwapChain); App_SafeRelease(&app_pDXGIFactory2); App_SafeRelease(&app_pDXGIAdapter); App_SafeRelease(&app_pDXGIDevice); App_SafeRelease(&app_pDXGIDevice1); App_SafeRelease(&app_pD2DDeviceContext); App_SafeRelease(&app_pD2DDeviceContext1); App_SafeRelease(&app_pD2DDevice); App_SafeRelease(&app_pD2DDevice1); App_SafeRelease(&app_pD3D11DeviceContext); App_SafeRelease(&app_pD3D11Device); App_SafeRelease(&app_pD2DFactory1); app_pD2DFactory1 = nullptr; /*App_SafeRelease(&app_pDirect2dFactory1);*/ App_SafeRelease(&app_pDXGIFactory); if (app_hwnd) { ReleaseDC(app_hwnd, dc); } //return; } void App::App_RunMessageLoop() { MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { /* translates and dispatches messages */ TranslateMessage(&msg); DispatchMessage(&msg); } App_Release(); } LRESULT CALLBACK App::App_WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { LRESULT result = 0; if (message == WM_CREATE) { LPCREATESTRUCT pcs = (LPCREATESTRUCT)lParam; App* pApp = (App*)pcs->lpCreateParams; ::SetWindowLongPtrW( hwnd, GWLP_USERDATA, reinterpret_cast(pApp) ); result = 1; } else { App* pApp = reinterpret_cast(static_cast( ::GetWindowLongPtrW( hwnd, GWLP_USERDATA ))); bool wasHandled = false; if (pApp) { switch (message) { case WM_SIZE: { UINT width = LOWORD(lParam); UINT height = HIWORD(lParam); pApp->App_OnResize(hwnd, width, height); } result = 0; wasHandled = true; break; case WM_DISPLAYCHANGE: { InvalidateRect(hwnd, NULL, FALSE); } result = 0; wasHandled = true; break; case WM_PAINT: { if (canDraw) { pApp->App_OnRender(hwnd); } ValidateRect(hwnd, NULL); } result = 0; wasHandled = true; break; case WM_DESTROY: { PostQuitMessage(0); } result = 1; wasHandled = true; break; } } if (!wasHandled) { result = DefWindowProc(hwnd, message, wParam, lParam); } } return result; } /***********************************************************************************/ /*################################# DEVICES #################################*/ /***********************************************************************************/ HRESULT App::App_CreateD3D11Device() { HRESULT hr = S_OK; /* the ID3D11Device1 associated with the DXGI surface must support BGRA DXGI formats for the surface to work with Direct2D. To ensure this support, use the D3D11_CREATE_DEVICE_BGRA_SUPPORT flag when you call the D3D11CreateDevice1 method to create the device. */ UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; /* D3D11_CREATE_DEVICE_DEBUG Describes parameters used to create a device. requires the D3D11 SDK Layers for Windows 8.1 - Windows 8.1 SDK must be installed */ //creationFlags |= D3D11_CREATE_DEVICE_DEBUG; /*UINT flags;*/ //-----------------------------------------------------------------------// // Create Reference Driver - Step 1 .....................................// //-----------------------------------------------------------------------// /* Request a feature level that implements the features your application will need. A reference device can be successfully created for the Direct3D 11 runtime This array defines the set of DirectX hardware feature levels this app supports. The ordering is important and you should preserve it. Don't forget to declare your app's minimum required feature level in its description. All apps are assumed to support 9.1 unless otherwise stated */ D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_9_3, D3D_FEATURE_LEVEL_9_2, D3D_FEATURE_LEVEL_9_1 }; D3D_FEATURE_LEVEL featureLevel; //-----------------------------------------------------------------------// // Create Reference Driver - Step 2 .....................................// //-----------------------------------------------------------------------// #pragma region write log text = "\tCreate D3D Device (app_pD3D11Device) "; writingString(text); text = "\t\t& Device Context (app_pD3D11DeviceContext) "; writingString(text); #pragma endregion int count = 0; /* check highest level used */ for (UINT level = 0; level < ARRAYSIZE(featureLevels); level++) { ////////////////////////////////////////////////////////////////// /* Step 1a - Create a D3D11Device and a D3D11DeviceContext */ ////////////////////////////////////////////////////////////////// hr = D3D11CreateDevice( /* specify null to use the default adapter */ /* Rather than provide a DXGIAdapter, allow Direct3D to chose best adapter */ nullptr, // m_pDXGIAdapter, // /* driver type*/ D3D_DRIVER_TYPE_HARDWARE, // driverType, // /* software */ 0, /* optional: set debug and Direct2D compatibility flags */ creationFlags, //D3D11_CREATE_DEVICE_BGRA_SUPPORT,// flags, // /* list of feature levels this app can support */ featureLevels, //NULL,// featureLevels[level], // /* number of possible feature levels */ ARRAYSIZE(featureLevels), //0,// /* sdk version */ D3D11_SDK_VERSION, ///////////////////////////////////////// // Direct Composition Creation Step 1 // ///////////////////////////////////////// /* returns the Direct3D device created */ &app_pD3D11Device, /* returns feature level of device created */ &featureLevel, /* returns the device immediate context */ &app_pD3D11DeviceContext ); if (FAILED(hr)) { text = "\t\tFailed!\n "; writingString(text); } count = (int)level; break; } text = "\tD3D_FEATURE_LEVEL " + to_string(featureLevels[count]); writingString(text); return hr; } HRESULT App::App_CreateSwapChain(const HWND& hWnd) { HRESULT hr = S_OK; /* Swap Chain a chain of buffers, swapping positions each time a new frame is rendered*/ //-----------------------------------------------------------------------// // Create Reference Driver - Step 3 .....................................// //-----------------------------------------------------------------------// /* Define initial parameters for a swap chain see windows-win32-direct3ddxgi.pdf - DXGI flip model */ text = "\tDefine initial parameters for a swap chain "; writingString(text); /* Allocate a descriptor */ DXGI_SWAP_CHAIN_DESC1 swapChainDesc1 = { 0 }; ZeroMemory(&swapChainDesc1, sizeof(swapChainDesc1)); /* use automatic sizing */ swapChainDesc1.Width = 1; swapChainDesc1.Height = 1; /* Swap Chain Format (most common - B8G8R8A8_UNORM) */ swapChainDesc1.Format = app_dxgiFormat; swapChainDesc1.Stereo = false; /* don't use multi-sampling */ swapChainDesc1.SampleDesc.Count = 1; swapChainDesc1.SampleDesc.Quality = 0; swapChainDesc1.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; /* use double buffering to enable flip */ #pragma region Understanding BufferCount and FrameCount /* BufferCount is the number of buffers in the swap chain. With flip model swap chains, the operating system may lock one buffer for an entire vsync interval while it is displayed, so the number of buffers available to the application to write is actually BufferCount-1. If BufferCount = 2, then there is only one buffer to write to until the OS releases the second one at the next vsync. A consequence of this is that the frame rate cannot exceed the refresh rate. When BufferCount >= 3, there are at least 2 buffers available to the application which it can cycle between (assuming SyncInterval=0), which allows the frame rate to be unlimited. FrameCount is the maximum number of in-flight “render frames,” where a render frame is the set of resources and buffers that the GPU must perform the rendering. If FrameCount = 1, then the CPU will not build the next render frame until the previous one is completely processed. This means that FrameCount must be at least 2 for the CPU and GPU to be able to work in parallel. */ #pragma endregion swapChainDesc1.BufferCount = app_bufferCount; /* must specify the DXGI_SCALING_STRETCH value in the Scaling member of DXGI_SWAP_CHAIN_DESC1 for CreateSwapChainForComposition */ swapChainDesc1.Scaling = (hWnd != NULL) ? DXGI_SCALING::DXGI_SCALING_NONE : DXGI_SCALING::DXGI_SCALING_STRETCH; app_dxgiScaling = swapChainDesc1.Scaling; /* all apps must use this SwapEffect */ /* must specify the DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL value in the SwapEffect member of DXGI_SWAP_CHAIN_DESC1 because CreateSwapChainForComposition supports only flip presentation model */ swapChainDesc1.SwapEffect = DXGI_SWAP_EFFECT::DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; /* Enable GetFrameLatencyWaitableObject() When this flag is used, the swapchain's latency must be set with the IDXGISwapChain2::SetMaximumFrameLatency API instead of IDXGIDevice1::SetMaximumFrameLatency */ /*swapChainDesc1.Flags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT; */ swapChainDesc1.Flags = 0; if (hWnd == NULL) { swapChainDesc1.AlphaMode = app_dxgiAlphaMode; } #pragma region write log text = "\tUsing DXGI device (app_pDXGIDevice) "; writingString(text); text = "\t\tIdentify / Get physical adapter (app_pDXGIAdapter) (GPU or card) "; writingString(text); #pragma endregion /*IDXGIAdapter* pDXGIAdapter = nullptr;*/ /* Identify the physical adapter (GPU or card) this device is run on */ hr = app_pDXGIDevice1->GetAdapter(&app_pDXGIAdapter); if (SUCCEEDED(hr)) { #pragma region write log text = "\t\tSucceeded!\n "; writingString(text); text = "\tUsing DXGI adapter (app_pDXGIAdapter) "; writingString(text); text = "\t\tGet Parent - factory that created the DXGI device "; writingString(text); #pragma endregion /* Get the factory object that created the DXGI device */ hr = app_pDXGIAdapter->GetParent(IID_PPV_ARGS(&app_pDXGIFactory2)); if (SUCCEEDED(hr)) { text = "\t\tSucceeded!\n "; writingString(text); /* If window not yet created */ if (hWnd != NULL) { #pragma region write log text = "\tCreateSwapChainForHwnd (app_pDXGISwapChain1)"; writingString(text); text = "\t\tfrom DXGI factory (app_pDXGIFactory2)"; writingString(text); text = "\t\t\tusing D3D device (app_pD3D11Device)"; writingString(text); #pragma endregion /* Creates a swap chain that is associated with an HWND handle to the output window for the swap chain. */ #pragma region NOTE /* Note Do not use this method in Windows Store apps. Instead, use IDXGIFactory2::CreateSwapChainForCoreWindow. */ #pragma endregion /* Get the final swap chain for this window from the DXGI factory */ hr = app_pDXGIFactory2->CreateSwapChainForHwnd( // STEP #1 app_pD3D11Device, hWnd, &swapChainDesc1, nullptr, nullptr, &app_pDXGISwapChain1); } else // if window created { #pragma region write log text = "\tCreateSwapChain (app_pDXGISwapChain1)"; writingString(text); text = "\t\tFor D3D DirectComposition "; writingString(text); text = "\t\t\tfrom DXGI factory (app_pDXGIFactory2)"; writingString(text); text = "\t\t\t\tusing D3D device (app_pD3D11Device)"; writingString(text); #pragma endregion /* Creates a swap chain that can be used to send Direct3D content into the DirectComposition API */ hr = app_pDXGIFactory2->CreateSwapChainForComposition( // STEP #1 app_pD3D11Device, &swapChainDesc1, nullptr, &app_pDXGISwapChain1); } if (SUCCEEDED(hr)) { #pragma region write log text = "\t\tSucceeded!\n "; writingString(text); text = "\tSetMaximumFrameLatency for DXGI "; writingString(text); #pragma endregion #pragma region Maximum Frame Latency /* Latency is the time between when a frame is generated, and when it appears on screen. Therefore, to minimize latency in a display system with fixed intervals (vsyncs), frame generation must be delayed as long as possible. The maximum number of queued present operations is called the Maximum Frame Latency. When an application tries to queue an additional present after reaching this limit, Present() will block until one of the previous frames has been displayed. Any time that the render thread spends blocked on the Present function, occurs between frame generation and frame display, so it directly increases the latency of the frame being presented. This is the latency which is eliminated by the use of the “waitable object.” Conceptually, the waitable object can be thought of as a semaphore which is initialized to the Maximum Frame Latency, and signaled whenever a present is removed from the Present Queue. If an application waits for the semaphore to be signalled before rendering then the present queue is not full (so Present will not block), and the latency is eliminated. */ #pragma endregion ///* Ensure DXGI doesn't queue more than one frame at a time */ //hr = app_pDXGIDevice1->SetMaximumFrameLatency(1); /* Game Mode Vsync On 3 Buffers, 2 Frames Waitable Object, Maximum Frame Latency 2 Game mode is a balanced tradeoff between latency and throughput. */ /* Set maximum number of queued present operations to 2 */ app_pDXGIDevice1->SetMaximumFrameLatency(2); #pragma region Options /* Classic Game mode Vsync On 3 Buffers, 3 Frames Not using waitable object This implicitly happens under D3D11 with triple buffering, hence “classic.” Classic game mode prioritizes throughput. The extra frame queueing can absorb spikes better but at the expense of latency. Minimum Latency Vsync On 2 Buffers, 1 Frame Waitable Object, Maximum Frame Latency 1 The absolute minimum amount of latency without using VR-style vsync racing tricks. If the application misses vsync, the frame rate will immediately drop to ˝ refresh. CPU and GPU operate serially rather than in parallel. */ #pragma endregion //app_pDXGISwapChain1->GetFrameStatistics(&app_pDxgiFrameStats); //text = "Use swap chain to get back buffer size"; writingString(text); ///* use the swap chain to obtain the size back buffer */ //hr = app_pDXGISwapChain1->GetDesc(&swapChainDesc1); } text = "\tRelease pDXGIFactory2 (IDXGIFactory2) "; writingString(text); App_SafeRelease(&app_pDXGIFactory2); } } /* Swap chain will tell us how big the back buffer is */ int bufferSize = app_pDXGISwapChain1->GetDesc1(&swapChainDesc1); text = "\tback buffer Size " + to_string(bufferSize); writingString(text); app_pDXGISwapChainDesc = swapChainDesc1; #pragma region D3D11CreateDeviceAndSwapChain /////////////////////////////////////////////////////////////////////////////////// ///* Describe Buffer */ //DXGI_MODE_DESC bufferDesc1; //ZeroMemory(&bufferDesc1, sizeof(DXGI_MODE_DESC)); //bufferDesc1.Width = nWidth; //bufferDesc1.Height = nHeight; //bufferDesc1.RefreshRate.Numerator = 60; //bufferDesc1.RefreshRate.Denominator = 1; //bufferDesc1.Format = DXGI_FORMAT_R8G8B8A8_UNORM; //bufferDesc1.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; //bufferDesc1.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; ///* Describe SwapChain */ //DXGI_SWAP_CHAIN_DESC swapChainDesc; //ZeroMemory(&swapChainDesc, sizeof(DXGI_SWAP_CHAIN_DESC)); //swapChainDesc.SampleDesc.Count = 1; //swapChainDesc.SampleDesc.Quality = 0; //swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; //swapChainDesc.BufferCount = 1; //swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; ///* Create SwapChain */ //D3D11CreateDeviceAndSwapChain( // pDXGIAdapter, // D3D_DRIVER_TYPE_HARDWARE, // NULL, NULL, NULL, NULL, // D3D11_SDK_VERSION, // &swapChainDesc, // &m_pDXGISwapChain, // &m_pD3D11Device, // NULL, // &m_pD3D11DeviceContext //); /////////////////////////////////////////////////////////////////////////////////// #pragma endregion return hr; } HRESULT App::App_EnumerateGraphicsAdapters() { HRESULT hr = S_OK; int count = 0; UINT numModes = 0; text = "\t\tDXGI_FORMAT - DXGI_FORMAT_R8G8B8A8_UNORM "; writingString(text); DXGI_FORMAT format = app_dxgiFormat; // DXGI_FORMAT_R8G8B8A8_UNORM; //DXGI_FORMAT format = DXGI_FORMAT_R32G32B32A32_FLOAT; UINT flags = DXGI_ENUM_MODES_INTERLACED; #pragma region Get Adapter Display Modes if (app_pDXGIAdapter != nullptr) { text = "\t\tpDXGIAdapter->EnumOutputs "; writingString(text); /* enumerate the outputs for each adapter */ hr = app_pDXGIAdapter->EnumOutputs(0, &app_pDXGIOutput); if (SUCCEEDED(hr)) { text = "\t\t\tSUCCEEDED "; writingString(text); text = "\t\tapp_pDXGIOutput->GetDisplayModeList "; writingString(text); /* Get the number of elements */ hr = app_pDXGIOutput->GetDisplayModeList(format, flags/*0*/, &numModes, NULL); if (SUCCEEDED(hr)) { text = "\t\t\tSUCCEEDED "; writingString(text); text = "\t\tGet DisplayModes "; writingString(text); /* Create a list to hold all the possible display modes for this monitor/video card combination */ UINT n = numModes; text = "\t\t\t\tnumModes " + to_string(numModes); writingString(text); text = "\t\t\t\tn " + to_string(n); writingString(text); app_displayModes = new DXGI_MODE_DESC[numModes]; if (app_displayModes) { text = "\t\tapp_pDXGIOutput->GetDisplayModeList "; writingString(text); /* Get list of display modes */ hr = app_pDXGIOutput->GetDisplayModeList( format, flags/*0*/, &n, app_displayModes); /*DXGI_MODE_DESC* dm[30] = {}; for (UINT d = 0; d < numModes; d++) { dm[d] = &displayModes[d]; }*/ if (SUCCEEDED(hr)) { text = "\t\t\tSUCCEEDED "; writingString(text); /*go through all the display modes and find the one that matches the screen width and height. When a match is found store the numerator and denominator of the refresh rate for that monitor. */ for (UINT i = 0; i < numModes && i < n; i++) { /*if (dm[i]->Width == (unsigned int)screenW) {}*/ if (app_displayModes[i].Width == (unsigned int)screenW) { text = "\t\tDisplayMode Width " + to_string(app_displayModes[i].Width); writingString(text); /*if (dm[i]->Height == (unsigned int)screenH) {}*/ if (app_displayModes[i].Height == (unsigned int)screenH) { text = "\t\tDisplayMode Height " + to_string(app_displayModes[i].Height); writingString(text); d2dNumerator = app_displayModes[i].RefreshRate.Numerator; d2dDenominator = app_displayModes[i].RefreshRate.Denominator; text = "\t\tnumerator " + to_string(d2dNumerator); writingString(text); text = "\t\tdenominator " + to_string(d2dDenominator); writingString(text); } } } } else { text = "\t\t\tGetDisplayModeList failed "; writingString(text); } } } } } text = "\tDescribeBackBuffer "; writingString(text); /* Describe the BackBuffer */ ZeroMemory(&app_bufferDesc, sizeof(DXGI_MODE_DESC)); app_bufferDesc.Width = nWidth; text = "\t\tWidth " + to_string(app_bufferDesc.Width); writingString(text); app_bufferDesc.Height = nHeight; text = "\t\tHeight " + to_string(app_bufferDesc.Height); writingString(text); app_bufferDesc.RefreshRate.Numerator = d2dNumerator; text = "\t\tNumerator " + to_string(d2dNumerator); writingString(text); app_bufferDesc.RefreshRate.Denominator = d2dDenominator; text = "\t\tDenominator " + to_string(d2dDenominator); writingString(text); app_bufferDesc.Format = app_dxgiFormat; // DXGI_FORMAT_R8G8B8A8_UNORM; app_bufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; app_bufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; /* DXGI_MODE_SCALING_CENTERED, - the image is centered on the screen DXGI_MODE_SCALING_STRETCHED - stretch the image to the monitors resolution. */ text = "\tDelete displayModes "; writingString(text); /* Release the display mode list. */ delete[] app_displayModes; app_displayModes = 0; #pragma endregion //if (app_pDXGIFactory) { app_pDXGIFactory->Release(); } return hr; } HRESULT App::App_GetVideoCardInfo() { HRESULT hr = S_OK; size_t size = 0; /* Get the adapter (video card) description. */ hr = app_pDXGIAdapter->GetDesc(&app_dxgiAdapterDesc); if (SUCCEEDED(hr)) { text = "\t\tSUCCEEDED "; writingString(text); /* Store the dedicated video card memory in megabytes. */ videoCardMemory = (int)(app_dxgiAdapterDesc.DedicatedVideoMemory / 1024 / 1024); text = "\tvideo card memory " + to_string(videoCardMemory); writingString(text); /* Convert the name of the video card to a character array and store it. */ hr = wcstombs_s( &size, videoCardDescription, 128, app_dxgiAdapterDesc.Description, 128); if (FAILED(hr)) { text = "\t\t\t\t\t\tvideoCardDescription error "; writingString(text); } } text = "\tRelease pDXGIAdapter (IDXGIAdapter) "; writingString(text); App_SafeRelease(&app_pDXGIAdapter); return hr; } HRESULT App::App_UseSwapChain(const HWND& hwnd) { HRESULT hr = S_OK; ////////////////////////////////////////////////////////////////// /* 1. extract a buffer from the swap chain */ ////////////////////////////////////////////////////////////////// text = "\tGetBuffer (Texture2D backBuffer) "; writingString(text); /* Get the backbuffer for this window which is be the final 3D render target */ hr = app_pDXGISwapChain1->GetBuffer(0, IID_PPV_ARGS(&app_swapChainD3D11Texture2D)); if (SUCCEEDED(hr)) { text = "\t\tSucceeded!\n "; writingString(text); ////////////////////////////////////////////////////////////////// /* 2. create a render-target-view from that buffer */ ////////////////////////////////////////////////////////////////// text = "\tCreateRenderTargetView (app_texture2dRenderTargetView) "; writingString(text); /* Create Render Target */ hr = app_pD3D11Device->CreateRenderTargetView( app_swapChainD3D11Texture2D, NULL, &app_texture2dRenderTargetView); if (SUCCEEDED(hr)) { text = "\t\tSucceeded!\n "; writingString(text); ////////////////////////////////////////////////////////////////// /* 3. set the render-target-view on the device */ ////////////////////////////////////////////////////////////////// text = "\t Bind / Set render-target-view to D3D device "; writingString(text); /* Set Render Target */ app_pD3D11DeviceContext->OMSetRenderTargets( 1, &app_texture2dRenderTargetView, NULL); } } else { text = "\tGetBuffer (Texture2D backBuffer) "; writingString(text); /* Get BackBuffer */ hr = app_pDXGISwapChain->GetBuffer( 0, __uuidof(ID3D11Texture2D), (void**)&app_swapChainD3D11Texture2D); if (SUCCEEDED(hr)) { #pragma region write log text = "\t\tSucceeded!\n "; writingString(text); text = "\tCreateRenderTargetView (app_texture2dRenderTargetView) "; writingString(text); #pragma endregion /* Create Render Target */ app_pD3D11Device->CreateRenderTargetView( app_swapChainD3D11Texture2D, NULL, &app_texture2dRenderTargetView); text = "\t Bind / Set render-target-view to D3D device "; writingString(text); /* Set Render Target */ /* Output Merger (OM) Stage takes the pixel fragments and depth/stencil buffers & determines which pixels are actually written to the render target */ app_pD3D11DeviceContext->OMSetRenderTargets( 1, &app_texture2dRenderTargetView, NULL); } } text = "\tGetBuffer (d3dResource backBuffer) "; writingString(text); ////////////////////////////////////////////////////////////// /* 1. Access one of the swap-chain's back buffers */ ////////////////////////////////////////////////////////////// hr = app_pDXGISwapChain1->GetBuffer( 0, __uuidof(app_pD3D11Resource), reinterpret_cast(&app_pD3D11Resource)); if (SUCCEEDED(hr)) { #pragma region write log text = "\t\tSucceeded!\n "; writingString(text); text = "\tCreateRenderTargetView (app_resourceRenderTargetView) "; writingString(text); #pragma endregion /* Creates a render-target view for accessing resource data */ ////////////////////////////////////////////////////////////// /* 2. create a render-target-view from the back buffer */ ////////////////////////////////////////////////////////////// hr = app_pD3D11Device->CreateRenderTargetView( app_pD3D11Resource, NULL, &app_resourceRenderTargetView); if (SUCCEEDED(hr)) { #pragma region write log text = "\t\tSucceeded!\n "; writingString(text); text = "\tBind render target view (app_resourceRenderTargetView) "; writingString(text); text = "\t\tto the device (app_pD3D11DeviceContext) "; writingString(text); #pragma endregion /* Bind render target view to the device */ ////////////////////////////////////////////////////////////// /* 3. set the render-target-view on the D3D device */ ////////////////////////////////////////////////////////////// app_pD3D11DeviceContext->OMSetRenderTargets( 1, &app_resourceRenderTargetView, 0); } } App_SafeRelease(&app_pD3D11Resource); App_SetUpViewport(); return hr; } HRESULT App::App_CreateD2D1DeviceAndContext() { HRESULT hr = S_OK; #pragma region write log text = "\tCreate D2D device (app_pD2DDevice)"; writingString(text); text = "\t\tfor 2-D rendering"; writingString(text); text = "\tapp_pD2DFactory1 -> app_pDXGIDevice1 => app_pD2DDevice"; writingString(text); #pragma endregion /* CreateDeviceContext - Obtain the Direct2D device for 2-D rendering */ hr = app_pD2DFactory1->CreateDevice(app_pDXGIDevice1, &app_pD2DDevice); if (SUCCEEDED(hr)) { #pragma region write log text = "\t\tSucceeded!\n"; writingString(text); text = "AVAILABLE : D2D Device - app_pD2DDevice\n "; writingString(text); text = "\n*** D2D1Device created ***\n"; writingString(text); text = "\tCreate D2D Device Context (m_pD2DDeviceContext)"; writingString(text); text = "\tapp_pD2DDevice => app_pD2DDeviceContext"; writingString(text); #pragma endregion /* Get Direct2D device's corresponding device context object */ hr = app_pD2DDevice->CreateDeviceContext( D2D1_DEVICE_CONTEXT_OPTIONS_ENABLE_MULTITHREADED_OPTIMIZATIONS, &app_pD2DDeviceContext); if (SUCCEEDED(hr)) { /*hr = m_pD2DDeviceContext->QueryInterface( (ID2D1DeviceContext3**)&m_pD2DDeviceContext);*/ #pragma region write log text = "\t\tSucceeded!\n"; writingString(text); text = "AVAILABLE : D2D Device Context - app_pD2DDeviceContext\n "; writingString(text); text = "\n*** D2D1DeviceContext created ***\n"; writingString(text); #pragma endregion /* A device context is a device that can perform drawing operations and create device-dependent drawing resources such as brushes. You also use the device context to link a ID2D1Bitmap to a DXGI surface to use as a render target. The device context can render to different types of targets. */ } } return hr; } HRESULT App::App_UseD2DDeviceContext() { HRESULT hr = S_OK; /* set the Direct2D render target to D2DTargetBitmap */ app_pD2DDeviceContext->SetTarget(app_pD2DTargetBitmap); /* Create brush. */ hr = app_pD2DDeviceContext->CreateSolidColorBrush( D2D1::ColorF(D2D1::ColorF::Coral, 1.0f), &app_dcSolidColorBrush ); if (SUCCEEDED(hr)) { text = "\t\tSucceeded \n "; writingString(text); target = targetType[2]; hr = App_Draw(target); if (SUCCEEDED(hr)) { text = "\t\tDevice Context Drawing Succeeded \n "; writingString(text); lock = true; App_FactoryLock(); App_SwapChainPresent(); if (SUCCEEDED(hr)) { text = "\t\tPresented! \n "; writingString(text); App_GetPresentFrameStats(); /* Gets the number of times that IDXGISwapChain::Present or IDXGISwapChain1::Present1 has been called */ hr = app_pDXGISwapChain1->GetLastPresentCount(&app_pLastPresentCount); if (SUCCEEDED(hr)) { text = "\tPresent Count " + to_string(app_pLastPresentCount); writingString(text); } } lock = false; App_FactoryLock(); } } return hr; } HRESULT App::App_CreateD3DTexture2D(const HWND& hwnd) { HRESULT hr = S_OK; text = "\tCreate D3D11_TEXTURE2D_DESC "; writingString(text); #pragma region Using Direct2D content as a texture /* Another way to use Direct2D content with Direct3D is to use Direct2D to generate a 2-D texture and then apply that texture to a 3-D model. You do this by creating an ID3D10Texture2D, obtaining a DXGI surface from the texture, and then using the surface to create a DXGI surface render target. The ID3D10Texture2D surface must use the D3D11_BIND_RENDER_TARGET bind flag and use a DXGI format supported by DXGI surface render targets. */ #pragma endregion /* Step 1 - use a Direct3D device to create a 2-D texture @@@@@ */ #pragma region Texture2D Description //D3D11_TEXTURE2D_DESC m_pD3D11Texture2DDesc; ZeroMemory(&app_pD3D11Texture2DDesc, sizeof(app_pD3D11Texture2DDesc)); /* Texture width & height (in texels) */ app_pD3D11Texture2DDesc.Width = nWidth; app_pD3D11Texture2DDesc.Height = nHeight; text = "\t\tWidth " + to_string(app_pD3D11Texture2DDesc.Width); writingString(text); text = "\t\tHeight " + to_string(app_pD3D11Texture2DDesc.Height); writingString(text); /* Use 1 for a multisampled texture; or 0 to generate a full set of subtexture */ if (multiSampling) { app_pD3D11Texture2DDesc.MipLevels = 1; text = "\t\tMipLevels " + to_string(app_pD3D11Texture2DDesc.MipLevels); /* Structure that specifies multisampling parameters for the texture */ /* The default sampler mode, with no anti-aliasing, has a count of 1 and a quality level of 0. If multi-sample antialiasing is being used, all bound render targets and depth buffers must have the same sample counts and quality levels. */ app_pD3D11Texture2DDesc.SampleDesc.Count = 1; // number of multisamples per pixel text = "\t\tCount " + to_string(app_pD3D11Texture2DDesc.SampleDesc.Count); writingString(text); /* valid range is between zero and one less than the level returned by ID3D11Device::CheckMultisampleQualityLevels for Direct3D 11 */ app_pD3D11Texture2DDesc.SampleDesc.Quality = 0; // image quality level text = "\t\tQuality " + to_string(app_pD3D11Texture2DDesc.SampleDesc.Quality); writingString(text); } else { app_pD3D11Texture2DDesc.MipLevels = 0; text = "\t\tMipLevels " + to_string(app_pD3D11Texture2DDesc.MipLevels); /* Structure that specifies multisampling parameters for the texture */ /* The default sampler mode, with no anti-aliasing, has a count of 1 and a quality level of 0. If multi-sample antialiasing is being used, all bound render targets and depth buffers must have the same sample counts and quality levels. */ app_pD3D11Texture2DDesc.SampleDesc.Count = 1; // number of multisamples per pixel text = "\t\tCount " + to_string(app_pD3D11Texture2DDesc.SampleDesc.Count); writingString(text); /* valid range is between zero and one less than the level returned by ID3D11Device::CheckMultisampleQualityLevels for Direct3D 11 */ app_pD3D11Texture2DDesc.SampleDesc.Quality = 0; // image quality level text = "\t\tQuality " + to_string(app_pD3D11Texture2DDesc.SampleDesc.Quality); writingString(text); } text = "\t\tMipLevels " + to_string(app_pD3D11Texture2DDesc.MipLevels); writingString(text); /* Number of textures in the texture array */ app_pD3D11Texture2DDesc.ArraySize = 1; text = "\t\tArraySize " + to_string(app_pD3D11Texture2DDesc.ArraySize); /* Texture format */ /* DXGI_FORMAT_B8G8R8A8_UNORM - Value: 87 A four-component, 32-bit unsigned-normalized-integer format that supports 8 bits for each color channel and 8-bit alpha. */ app_pD3D11Texture2DDesc.Format = app_dxgiFormat; /* flags for binding to pipeline stages */ app_pD3D11Texture2DDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; /* Value that identifies how the texture is to be read from and written to. The most common value is D3D11_USAGE_DEFAULT */ app_pD3D11Texture2DDesc.Usage = D3D11_USAGE_DEFAULT; #pragma endregion /* set up the Direct2D render target bitmap linked to the swapchain. Whenever we render to this bitmap, it is directly rendered to the swap chain associated with the window. */ text = "\tUse d3d11Device to CreateTexture2D (app_deviceD3D11Texture2D) "; writingString(text); hr = app_pD3D11Device->CreateTexture2D( &app_pD3D11Texture2DDesc, NULL, &app_deviceD3D11Texture2D); return hr; } HRESULT App::App_CreateDXGISurface(const HWND& hwnd) { HRESULT hr = S_OK; if (dcTargetAtempts == 0) { text = "\t1) Use d3dTexture to obtain a DXGI surface (app_pDXGISurface) "; writingString(text); hr = app_deviceD3D11Texture2D->QueryInterface( __uuidof(IDXGISurface), (void**)&app_pDXGISurface); if (FAILED(hr)) { text = "\t\tDXGI Surface from D3D11 Texture2D FAILED! "; writingString(text); text = "\t2) Use d3dTexture to obtain a DXGI surface (app_pDXGISurface) "; writingString(text); /* Step 2 - Use the texture to obtain a DXGI surface @@@@@ */ /* retrieve the IDXGISurface interface that represents the 2D texture surface */ hr = app_deviceD3D11Texture2D->QueryInterface(&app_pDXGISurface); /* If the 2D texture has only a single MIP-map level and does not consist of an array of textures, QueryInterface succeeds and returns a pointer to the IDXGISurface interface pointer. Otherwise, QueryInterface fails and does not return the pointer to IDXGISurface. */ if (FAILED(hr)) { text = "\t\tDXGI Surface from D3D11 Texture2D FAILED! "; writingString(text); text = "\t3) Use swapChain to obtain DXGI surface (app_pDXGISurface) "; writingString(text); hr = app_swapChainD3D11Texture2D->QueryInterface( __uuidof(IDXGISurface), (void**)&app_pDXGISurface); if (FAILED(hr)) { text = "\t4) Use swapChain to obtain DXGI surface (app_pDXGISurface) "; writingString(text); hr = app_swapChainD3D11Texture2D->QueryInterface(&app_pDXGISurface); if (SUCCEEDED(hr)) { #pragma region write log text = "\t\tSucceeded! "; writingString(text); text = "AVAILABLE : DXGI Surface - app_pDXGISurface "; writingString(text); text = "\tUseDxgiSurface "; writingString(text); #pragma endregion App_UseDxgiSurface(hwnd); } else { text = "\t\tDXGI Surface from D3D11 Texture2D FAILED! "; writingString(text); } } else { #pragma region write log text = "\t\tSucceeded! "; writingString(text); text = "AVAILABLE : DXGI Surface - app_pDXGISurface "; writingString(text); text = "\tUseDxgiSurface "; writingString(text); #pragma endregion App_UseDxgiSurface(hwnd); } } if (SUCCEEDED(hr)) { #pragma region write log text = "\t\tSucceeded! "; writingString(text); text = "AVAILABLE : DXGI Surface - app_pDXGISurface "; writingString(text); text = "\tUseDxgiSurface "; writingString(text); #pragma endregion App_UseDxgiSurface(hwnd); } } else { #pragma region write log text = "\t\tSucceeded "; writingString(text); text = "AVAILABLE : DXGI Surface from d3d11 Texture2D "; writingString(text); text = "\tUseDxgiSurface "; writingString(text); #pragma endregion App_UseDxgiSurface(hwnd); } } else { ////////////////////////////////////////////////////////////////////////////// // Draw a 2-D background /* STEP #2 - Use the swap chain's GetBuffer method to obtain a DXGI surface */ ////////////////////////////////////////////////////////////////////////////// text = "\t5) Use swap chain to obtain a DXGI surface (app_pDXGISurface) "; writingString(text); /* Direct2D needs the dxgi version of the backbuffer surface pointer */ /* Use the swap chain's GetBuffer method to obtain a DXGI surface */ hr = app_pDXGISwapChain1->GetBuffer(0, __uuidof( IDXGISurface), (LPVOID*)&app_pDXGISurface); if (FAILED(hr)) { text = "\t6) Use swap chain to obtain a DXGI surface (app_pDXGISurface) "; writingString(text); /* Direct2D needs the dxgi version of the backbuffer surface pointer */ hr = app_pDXGISwapChain1->GetBuffer(0, IID_PPV_ARGS(&app_pDXGISurface)); if (SUCCEEDED(hr)) { #pragma region write log text = "\t\tSucceeded! "; writingString(text); text = "AVAILABLE : DXGI Surface - app_pDXGISurface "; writingString(text); text = "\tUseDxgiSurface "; writingString(text); #pragma endregion App_UseDxgiSurface(hwnd); } else { text = "\t\tDXGI Surface from DXGI SwapChain FAILED! "; writingString(text); } } else { #pragma region write log text = "\t\tSucceeded! "; writingString(text); text = "AVAILABLE : DXGI Surface - app_pDXGISurface "; writingString(text); text = "\tUseDxgiSurface "; writingString(text); #pragma endregion App_UseDxgiSurface(hwnd); } } App_SafeRelease(&app_swapChainD3D11Texture2D); App_SafeRelease(&app_deviceD3D11Texture2D); app_deviceD3D11Texture2D = 0; text = "RELEASED : D2D11 Texture2D - d3d11Texture2dBackBuffer "; writingString(text); return hr; } HRESULT App::App_UseDxgiSurface(const HWND& hwnd) { HRESULT hr = S_OK; if (!dcTarget) { text = "\tCreateBitmapFromDXGI_Surface "; writingString(text); /* Get a D2D surface from the DXGI back buffer to use as the D2D render target */ hr = App_CreateBitmapFromDXGI_Surface(hwnd); if (SUCCEEDED(hr)) { text = "\t\tSucceeded! "; writingString(text); dcTarget = true; target = targetType[1]; targets = 1; text = "\trender target : " + target; writingString(text); } else { dcTargetAtempts += 1; hr = App_CreateDXGISurface(hwnd); } text = "\tCreateDXGI_SurfaceRenderTarget "; writingString(text); /* Create a DXGI render target */ hr = App_CreateDXGI_SurfaceRenderTarget(hwnd); if (SUCCEEDED(hr)) { text = "\t\tSucceeded! "; writingString(text); dcTarget = true; target = targetType[3]; targets = 2; text = "\trender target : " + target; writingString(text); #pragma region NOTEs /* You can now use the DXGI surface render target to draw 2-D content to the DXGI surface */ /* Interoperability through DXGI There are two primary ways to use Direct2D and Direct3D together: 1. You can write Direct2D content to a Direct3D surface by obtaining an IDXGISurface and using it with the CreateDxgiSurfaceRenderTarget to create an ID2D1RenderTarget. You can then use the render target to add a two-dimensional interface or background to three-dimensional graphics, or use a Direct2D drawing as a texture for a three dimensional object. 2. By using CreateSharedBitmap to create an ID2D1Bitmap from an IDXGISurface, you can write a Direct3D scene to a bitmap and render it with Direct2D */ /* A DXGI surface render target is a kind of ID2D1RenderTarget. Like other Direct2D render targets, you can use it to create resources and issue drawing commands. The DXGI surface render target and the DXGI surface must use the same DXGI format. If you specify the DXGI_FORMAT_UNKOWN format when you create the render target, it will automatically use the surface's format */ /* The Differences Between Straight and Premultiplied Alpha When describing an RGBA color by using straight alpha, the alpha value of the color is stored in the alpha channel. For example, to describe a red color that is 60% opaque, use the following values: (255, 0, 0, 255 * 0.6) = (255, 0, 0, 153). The 255 value indicates full red, and 153 (which is 60 percent of 255) indicates that the color should have an opacity of 60 percent. When describing an RGBA color by using premultiplied alpha, each color is multiplied by the alpha value: (255 * 0.6, 0 * 0.6, 0 * 0.6, 255 * 0.6) = (153, 0, 0, 153). Regardless of the alpha mode of the render target, D2D1_COLOR_F values are always interpreted as straight alpha. For example, when specifying the color of an ID2D1SolidColorBrush for use with a render target that uses the premultiplied alpha mode, specify the color just as you would if the render target used straight alpha. When you paint with the brush, Direct2D translates the color to the destination format for you. */ #pragma endregion } } return hr; } HRESULT App::App_CreateDXGI_SurfaceRenderTarget(const HWND& hwnd) { HRESULT hr = S_OK; text = "\tSetup DXGI render target properties "; writingString(text); app_pD2DPixelFormat = D2D1::PixelFormat( /* The D2D1_PIXEL_FORMAT structure has two fields: format, a DXGI_FORMAT value that describes the size and arrangement of channels in each pixel, and alpha, a D2D1_ALPHA_MODE value that describes how alpha information is interpreted. */ app_dxgiFormat, app_d2dAlphaMode ); app_pD2DRenderTargetProps = D2D1::RenderTargetProperties( D2D1_RENDER_TARGET_TYPE_DEFAULT ); app_pD2DRenderTargetProps.pixelFormat = app_pD2DPixelFormat; propsNum = 2; App_GetTargetPropertiesDPIs(hwnd, app_pD2DBitmapProps, app_pD2DRenderTargetProps); text = "\tCreateDxgiSurfaceRenderTarget "; writingString(text); /* Create a Direct2D render target to draw into the surface in the swap chain */ hr = app_pD2DFactory1->CreateDxgiSurfaceRenderTarget( app_pDXGISurface, // [in] IDXGISurface &app_pD2DRenderTargetProps, // [ref] const D2D1_RENDER_TARGET_PROPERTIES &app_pD2DRenderTarget // [out] ID2D1RenderTarget ); return hr; } HRESULT App::App_CreateBitmapFromDXGI_Surface(const HWND& hwnd) { HRESULT hr = S_OK; /* Create a pixel format and initial its format and alphaMode fields */ D2D1_PIXEL_FORMAT pixelFormat = D2D1::PixelFormat( app_dxgiFormat, app_d2dAlphaMode ); /* set up the Direct2D render target bitmap linked to the swapchain. Whenever we render to this bitmap, it is directly rendered to the swap chain associated with the window. */ D2D1_BITMAP_PROPERTIES1 d2d1BitmapProperties1 = D2D1::BitmapProperties1( D2D1_BITMAP_OPTIONS::D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS::D2D1_BITMAP_OPTIONS_CANNOT_DRAW, pixelFormat, /*D2D1::PixelFormat( DXGI_FORMAT::DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE::D2D1_ALPHA_MODE_PREMULTIPLIED),*/ 0, 0, NULL ); propsNum = 1; App_GetTargetPropertiesDPIs(hwnd, d2d1BitmapProperties1, app_pD2DRenderTargetProps); #pragma region write log text = "\tUse D2DDeviceContext to... "; writingString(text); text = "\t\tCreateBitmapFromDxgiSurface (app_pD2DTargetBitmap)"; writingString(text); text = "\t\t\tfrom dxgiSurface, with bitmapProperties "; writingString(text); #pragma endregion //######################################################################// /* Writing Direct2D content to a swap chain buffer */ /* Add Direct2D content to a Direct3D scene */ /* Creates a bitmap from a DXGI surface */ //######################################################################// /* Creates a bitmap from a DXGI surface that can be set as a target surface or have additional color context information specified. Note The DXGI surface must have been created from the same Direct3D device that the Direct2D device context is associated with. */ text = "\tCreateBitmapFromDxgiSurface "; writingString(text); hr = app_pD2DDeviceContext->CreateBitmapFromDxgiSurface( app_pDXGISurface, d2d1BitmapProperties1, &app_pD2DTargetBitmap); /* The ID2D1DeviceContext::CreateBitmapFromDxgiSurface method gets a Direct2D surface from the DXGI surface. So that anything rendered to the target ID2D1Bitmap is rendered to the surface of the swap chain. */ return hr; } void App::App_GetTargetPropertiesDPIs( const HWND& hwnd, D2D1_BITMAP_PROPERTIES1& bmpProps, D2D1_RENDER_TARGET_PROPERTIES& rtProps) { /* For Windows 10 */ //unsigned int nDPI = GetDpiForWindow(hWnd); /* For Windows 8.1 */ FLOAT dpiX, dpiY; HDC hDCScreen = GetDC(hwnd); dpiX = static_cast( GetDeviceCaps(hDCScreen, LOGPIXELSX)); dpiY = static_cast( GetDeviceCaps(hDCScreen, LOGPIXELSY)); if (propsNum == 1) { bmpProps.dpiX = dpiX; bmpProps.dpiY = dpiY; app_pD2DBitmapProps = bmpProps; text = "\t\tbmpProps dpiX " + to_string(bmpProps.dpiX); writingString(text); text = "\t\tbmpProps dpiY " + to_string(bmpProps.dpiY); writingString(text); /*m_pD2DBitmapProps.dpiX = bmpProps.dpiX; m_pD2DBitmapProps.dpiY = bmpProps.dpiY;*/ } if (propsNum == 2) { rtProps.dpiX = dpiX; rtProps.dpiY = dpiY; app_pD2DRenderTargetProps = rtProps; text = "\t\ttProps dpiX " + to_string(rtProps.dpiX); writingString(text); text = "\t\ttProps dpiY " + to_string(rtProps.dpiY); writingString(text); /*m_pD2DRenderTargetProps.dpiX = rtProps.dpiX; m_pD2DRenderTargetProps.dpiY = rtProps.dpiY;*/ } propsNum = 0; ReleaseDC(NULL, hDCScreen); return; } void App::App_SetUpViewport() { /* Create a viewport to define which parts of the render target will be visible */ /* Setup the D3D11_VIEWPORT */ ZeroMemory(&app_d3d11Viewport, sizeof(D3D11_VIEWPORT)); app_d3d11Viewport.Width = (float)nWidth; app_d3d11Viewport.Height = (float)nHeight; app_d3d11Viewport.MinDepth = 0.0f; app_d3d11Viewport.MaxDepth = 1.0f; app_d3d11Viewport.TopLeftX = 0; app_d3d11Viewport.TopLeftY = 0; text = "\tUse m_pD3D11DeviceContext to set d3d11Viewport "; writingString(text); app_pD3D11DeviceContext->RSSetViewports(1, &app_d3d11Viewport); /* allows for having multiple viewports / windows */ } HRESULT App::App_CreateRenderTargetResources() { HRESULT hr = S_OK; /* A gradient stop collection is a device-dependent resource. Your application should create gradient stop collections after it initializes the render target with which the gradient stop collection will be used, and recreate the gradient stop collection whenever the render target needs recreated */ /* Create a linear gradient. */ static const D2D1_GRADIENT_STOP d2dGradientStops1[] = { { 0.f/*position*/, D2D1::ColorF(D2D1::ColorF::Black, 1.0f)}, { 1.f/*position*/, D2D1::ColorF(D2D1::ColorF::White, 0.0f) }, }; static const D2D1_GRADIENT_STOP d2dGradientStops2[] = { { 0.f/*position*/, { 0.f, 1.f, 1.f, 0.25f } }, { 1.f/*position*/, { 0.f, 0.f, 1.f, 1.f } }, }; /* create an array of gradient stops, then uses them to create an ID2D1GradientStopCollection */ //pD2DGradientStopCollection text = "\tCreate an array of gradient stops "; writingString(text); /* Create an array of gradient stops to be put in the gradient stop collection for use in the gradient brush */ pD2DGadientStop[0].color = D2D1::ColorF(D2D1::ColorF::Yellow, 1); pD2DGadientStop[0].position = 0.0f; pD2DGadientStop[1].color = D2D1::ColorF(D2D1::ColorF::ForestGreen, 1); pD2DGadientStop[1].position = 0.25f; pD2DGadientStop[2].color = D2D1::ColorF(D2D1::ColorF::SkyBlue, 1); pD2DGadientStop[2].position = 0.5f; pD2DGadientStop[3].color = D2D1::ColorF(D2D1::ColorF::Crimson, 1); pD2DGadientStop[3].position = 0.75f; pD2DGadientStop[4].color = D2D1::ColorF(D2D1::ColorF::Yellow, 1); pD2DGadientStop[4].position = 1.0f; /* randomize colors */ colorAlpha = 1; startPointx = (float)nX; startPointy = (float)nY; endPointx = (float)nWidth; endPointy = (float)nHeight; App_RandomizerushColors( startPointx, startPointy, endPointx, endPointy, colorAlpha ); text = "\tCreate the ID2D1GradientStopCollection"; writingString(text); /* Create the ID2D1GradientStopCollection from the previously declared array of D2D1_GRADIENT_STOP structs */ hr = app_pD2DRenderTarget->CreateGradientStopCollection( pD2DGadientStop, ARRAYSIZE(pD2DGadientStop), D2D1_GAMMA_2_2, D2D1_EXTEND_MODE_CLAMP, &pD2DGradientStopCollection ); /*hr = m_pD2DRenderTarget->CreateGradientStopCollection( pD2DGadientStop, ARRAYSIZE(pD2DGadientStop), &pD2DGradientStopCollection );*/ if (SUCCEEDED(hr)) { text = "\t\tSuccess!\n"; writingString(text); text = "\tCreateLinearGradientBrush"; writingString(text); hr = app_pD2DRenderTarget->CreateLinearGradientBrush( D2D1::LinearGradientBrushProperties( D2D1::Point2F((float)nX, (float)nY), D2D1::Point2F((float)nWidth, (float)nHeight) ), D2D1::BrushProperties(), pD2DGradientStopCollection, &pLinearGradientBrush ); if (SUCCEEDED(hr)) { text = "\t\tSucceeded!\n"; writingString(text); text = "AVAILABLE : Linear Gradient Brush "; writingString(text); linearGradientBrushCreated = true; } } /*m_pBackBufferGradientBrush->GetGradientStopCollection(&pD2DGradientStopCollection);*/ /*pLinearGradientBrush->GetGradientStopCollection(&pD2DGradientStopCollection); App_SafeRelease(&pD2DGradientStopCollection);*/ text = "\tDrawGradientBackground"; writingString(text); if (linearGradientBrushCreated) { hr = App_DrawGradientBackground(); if (SUCCEEDED(hr)) { text = "\t\tSucceeded!\n"; writingString(text); text = "\tDXGISwapChain1->Present"; writingString(text); lock = true; App_FactoryLock(); App_SwapChainPresent(); if (SUCCEEDED(hr)) { text = "\t\tPresented! \n "; writingString(text); App_GetPresentFrameStats(); /* Gets the number of times that IDXGISwapChain::Present or IDXGISwapChain1::Present1 has been called */ hr = app_pDXGISwapChain1->GetLastPresentCount( &app_pLastPresentCount); if (SUCCEEDED(hr)) { text = "\tPresent Count " + to_string(app_pLastPresentCount); writingString(text); } } lock = false; App_FactoryLock(); } } App_SafeRelease(&pD2DGradientStopCollection); App_SafeRelease(&pLinearGradientBrush); App_SafeRelease(&app_LinearGradientBrush); return hr; } HRESULT App::App_DrawGradientBackground() { HRESULT hr = S_OK; text = "\tGet size of d2dRenderTarget "; writingString(text); D2D1_SIZE_F targetSize = app_pD2DRenderTarget->GetSize(); text = "\tRenderTarget Width " + to_string(targetSize.width); writingString(text); text = "\tRenderTarget Height " + to_string(targetSize.height); writingString(text); text = "\tdrawing with d2dRenderTarget "; writingString(text); app_pD2DRenderTarget->BeginDraw(); pLinearGradientBrush->SetTransform(D2D1::Matrix3x2F::Scale(targetSize)); D2D1_RECT_F rect = D2D1::RectF( 0.0f, 0.0f, targetSize.width, targetSize.height); app_pD2DRenderTarget->FillRectangle(&rect, pLinearGradientBrush); hr = app_pD2DRenderTarget->EndDraw(); return hr; } HRESULT App::App_RandomizerushColors( const float& sx, const float& sy, const float& ex, const float& ey, const float& a ) { HRESULT hr = S_OK; int randNum; for (int c = 0; c < gradientStopInt; c++) { randNum = rand() % 10 + 0; pD2DGadientStop[c].color = D2D1::ColorF(colorS[randNum], a); } return hr; } HRESULT App::App_GetPresentFrameStats() { HRESULT hr = S_OK; /* To detect a glitch Gets performance statistics about the last render frame */ hr = app_pDXGISwapChain1->GetFrameStatistics( &app_pDXGIFrameStats ); if (SUCCEEDED(hr)) { /* A value that represents the running total count of times that an image was presented to the monitor since the computer booted.*/ text = "\t\tPresent Count " + to_string(app_pDXGIFrameStats.PresentCount); writingString(text); /* A value that represents the running total count of v-blanks at which the last image was presented to the monitor and that have happened since the computer booted (for windowed mode, since the swap chain was created). */ text = "\t\tPPresent Refresh Count " + to_string(app_pDXGIFrameStats.PresentRefreshCount); writingString(text); /* A value that represents the running total count of v-blanks when the scheduler last sampled the machine time by calling QueryPerformanceCounter and that have happened since the computer booted (for windowed mode, since the swap chain was created). */ text = "\t\tPSync Refresh Count " + to_string(app_pDXGIFrameStats.SyncRefreshCount); writingString(text); } return hr; } HRESULT App::App_SwapChainPresent() { HRESULT hr = S_OK; hr = app_pDXGISwapChain1->Present1( 1, 0, &app_pDXGIPresentParameters); return hr; } HRESULT App::App_FactoryLock() { HRESULT hr = S_OK; if (lock) { /* We are accessing Direct3D resources directly without Direct2D's knowledge, so we must manually acquire and apply the Direct2D factory lock. */ hr = app_pD2DFactory1->QueryInterface( /* IID_PPV_ARGS is used to retrieve an interface pointer, supplying the IID value of the requested interface automatically based on the type of the interface pointer used. This avoids a common coding error by checking the type of the value passed at compile time. */ IID_PPV_ARGS(&app_pD2DMultithread)); if (SUCCEEDED(hr)) { app_pD2DMultithread->Enter(); /* Now it is safe to make Direct3D/DXGI calls, such as IDXGISwapChain::Present */ } } else { /* It is absolutely critical that the factory lock be released upon exiting Direct3D/DXGI calls, or else any consequent Direct2D calls will be blocked. */ app_pD2DMultithread->Leave(); } return hr; } #pragma endregion // File // Main.cpp _________________________________________________________________________________ /* Win32OpenGLProject.cpp : Defines the entry point for the application */ #include "App.h" /* Use _In_ to avoid warning this instance has no annotations see Using SAL Annotations to Reduce C/C++ Code Defects Function Parameters and Return Values SAL is the Microsoft source code annotation language. By using source code annotations, you can make the intent behind your code explicit. These annotations also enable automated static analysis tools to analyze your code more accurately, with significantly fewer false positives and false negatives. */ int WINAPI WinMain( _In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow ) { /* Use HeapSetInformation to specify that the process should terminate if the heap manager detects an error in any heap used by the process. The return value is ignored, because we want to continue running in the unlikely event that HeapSetInformation fails. */ HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0); if (SUCCEEDED(CoInitialize(NULL))) { App app; if (SUCCEEDED(app.App_Initialize())) { app.App_RunMessageLoop(); } CoUninitialize(); } return 0; }