How can I create Direct3d 11 renderer using SDL 2.0.9 - sdl-2

In my project I must use SDL_BLENDOPERATION_MAXIMUM via SDL_ComposeCustomBlendMode() which is supported in SDL 2.0.9 by direct3d11 renderer only. I have Windows 8.1 and GeForce GTX750 Ti with updated drivers. My system should support DirectX 11 renderending.
Changing defines in SDL_config.h or SDL_config_windows.h (SDL_VIDEO_RENDER_D3D11 to 1 and SDL_VIDEO_RENDER_D3D to 0) doesn't help.
I tried to fill preprocessor difinitions with defines SDL_VIDEO_RENDER_D3D11 or WINRT according to SDL source code. But it doesn't help.
What should I do to activate direct3d11 renderer so I can use blend mode max?
My test code:
#include "SDL.h"
#include "SDL_image.h"
#include <string>
using namespace std;
int main( int argc, char *argv[] ) {
SDL_Init( SDL_INIT_VIDEO );
IMG_Init( IMG_INIT_PNG );
SDL_SetHintWithPriority( SDL_HINT_RENDER_DRIVER, "direct3d11", SDL_HINT_OVERRIDE );
SDL_Window *window = SDL_CreateWindow( "Testing", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
1200, 600, SDL_WINDOW_RESIZABLE );
SDL_Renderer *renderer = SDL_CreateRenderer( window, -1, SDL_RENDERER_ACCELERATED );
SDL_RendererInfo *rendererInfo = new SDL_RendererInfo();
SDL_RendererInfo *driverInfo = new SDL_RendererInfo();
SDL_GetRendererInfo( renderer, rendererInfo );
int drivers = SDL_GetNumRenderDrivers();
string availableDrivers = " (";
for ( int i = 0; i < drivers; ++i ) {
SDL_GetRenderDriverInfo( i, driverInfo );
string driverName = driverInfo->name;
if ( i == drivers - 1 ) {
availableDrivers += driverName;
}
else {
availableDrivers += driverName + ", ";
}
}
availableDrivers += ")";
string path = SDL_GetBasePath();
SDL_Surface *surfRed = IMG_Load( (path + "\\Red.png").c_str() );
SDL_Texture *textRed = SDL_CreateTextureFromSurface( renderer, surfRed );
SDL_FreeSurface( surfRed );
SDL_Surface *surfBlue = IMG_Load( ( path + "\\Blue.png" ).c_str() );
SDL_Texture *textBlue = SDL_CreateTextureFromSurface( renderer, surfBlue );
SDL_FreeSurface( surfBlue );
SDL_Rect destRed, destBlue;
destRed.x = 128;
destRed.y = 128;
destBlue.x = 196;
destBlue.y = 196;
SDL_QueryTexture( textRed, NULL, NULL, &destRed.w, &destRed.h );
SDL_QueryTexture( textBlue, NULL, NULL, &destBlue.w, &destBlue.h );
SDL_BlendMode blendMode = SDL_ComposeCustomBlendMode( SDL_BLENDFACTOR_ONE, SDL_BLENDFACTOR_ONE, SDL_BLENDOPERATION_MAXIMUM,
SDL_BLENDFACTOR_ONE, SDL_BLENDFACTOR_ONE, SDL_BLENDOPERATION_MAXIMUM );
SDL_SetTextureBlendMode( textRed, blendMode );
SDL_SetTextureBlendMode( textBlue, blendMode );
// SDL_SetRenderDrawBlendMode( renderer, blendMode );
string info = rendererInfo->name + availableDrivers + " " + SDL_GetError();
SDL_SetWindowTitle( window, info.c_str() );
SDL_SetRenderDrawColor( renderer, 0, 0, 0, 255 );
SDL_Event event;
bool isRunning = true;
while ( isRunning ) {
if ( SDL_PollEvent( &event ) ) {
if ( event.type == SDL_QUIT ) {
isRunning = false;
}
}
SDL_RenderClear( renderer );
SDL_RenderCopy( renderer, textRed, NULL, &destRed );
SDL_RenderCopy( renderer, textBlue, NULL, &destBlue );
SDL_RenderPresent( renderer );
}
delete driverInfo;
delete rendererInfo;
SDL_DestroyTexture( textRed );
SDL_DestroyTexture( textBlue );
SDL_DestroyRenderer( renderer );
SDL_DestroyWindow( window );
IMG_Quit();
SDL_Quit();
return 0;
}
Window title is "direct3d (direct3d, opengl, opengles2, software) This operration is not supported". It works fine when I change to SDL_BLENDOPERATION_ADD, but it's not what I want. If I uncomment renderer blend mode it doesn't help too.

Enumerate the supported renderer backends via SDL_GetNumRenderDrivers() and SDL_GetRenderDriverInfo().
Note the index of the direct3d11 driver, if it exists.
Pass index into SDL_CreateRenderer().
All together:
SDL_Init( SDL_INIT_VIDEO );
SDL_Window* window = SDL_CreateWindow( "SDL2", 0, 0, 640, 480, SDL_WINDOW_SHOWN );
SDL_Renderer* renderer = nullptr;
for( int i = 0; i < SDL_GetNumRenderDrivers(); ++i )
{
SDL_RendererInfo rendererInfo = {};
SDL_GetRenderDriverInfo( i, &rendererInfo );
if( rendererInfo.name != std::string( "direct3d11" ) )
{
continue;
}
renderer = SDL_CreateRenderer( window, i, 0 );
break;
}

Note that what you are setting with SDL_VIDEO_RENDER_D3D and friends are compile time definitions for building SDL with D3D support.
To do this at runtime:
Sometime after SDL_Init() and before creating your window/renderer set a hint for it.
// returns true on success or false on failure
SDL_SetHint(SDL_HINT_RENDER_DRIVER, "direct3d11");
However, this will only work on Windows, and I believe d3d is already the default renderer for windows. If your version of windows supports d3d11 that is what SDL should use. I strongly suspect you already have a d3d11 renderer and your problem is with how you instantiate or use your custom blend mode.
To verify you have a d3d11 renderer:
SDL_RendererInfo info;
SDL_GetRendererInfo(renderer, &info);
printf("%s", info.name);
To create a custom blend mode with SDL_BLENDOPERATION_MAXIMUM
SDL_BlendMode blender = SDL_ComposeCustomBlendMode(SDL_BLENDFACTOR_SRC_ALPHA, // change this to suit your needs
SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA, // change this to suit your needs
SDL_BLENDOPERATION_MAXIMUM,
SDL_BLENDFACTOR_ONE, // change this to suit your needs
SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA, // change this to suit your needs
SDL_BLENDOPERATION_MAXIMUM);
SDL_SetTextureBlendMode(texture, blender); // blender is your custom mode
SDL_SetRenderDrawBlendMode(renderer, blender); // blender is your custom mode
I cant imagine the above blender is actually the combination of factors/operations you want, but you didn't post your actual code to work off.

Related

Is there a way to let the printer handling multiple copies when printing using gdi plus?

I'm printing using the hDC I get from the print dialog and was wondering if there's a way to let the printer/printer driver/OS handle multiple copies and collation settings? I can of course print the pages multiple times, but that doesn't feel like the right way to go about this...
This is roughly what my code looks like now:
ULONG_PTR gdiplusToken = 0;
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
Gdiplus::GdiplusStartup( &gdiplusToken, &gdiplusStartupInput, NULL );
DOCINFO documentInfo;
memset( &documentInfo, 0, sizeof( documentInfo ) );
documentInfo.cbSize = sizeof( documentInfo );
theDocumentInfo.lpszDocName = mDocumentName;
HDC printerHDC = printDialogData.hDC; // printDialogData is PRINTDLG struct from PrintDlg
::StartDoc( printerHDC, &documentInfo );
for( int page = 0; page < numberOfPages; ++ page )
{
::StartPage( printerHDC );
// print the page
::EndPage( printerHDC );
}
::EndDoc( printerHDC );
::DeleteDC( printerHDC );
Gdiplus::GdiplusShutdown( gdiplusToken );

Direct2D draws nothing on a "hardware mode" render target

I 'm trying to use Direct2D on a render target created by Direct3D according to this MSDN document. The idea not to use a HWND render buffer is for the application to be able to switch targets easily, so I can e.g. render to a bitmap the static painting and use direct commands for any runtime-dependent painting. The code to create the interfaces is the following:
bool CreateD2DC(HWND hh)
{
D2D& d = *this;
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
};
auto de = D3D_DRIVER_TYPE_HARDWARE;
if (IsCurrentSessionRemoteable())
de = D3D_DRIVER_TYPE_SOFTWARE;
D3D_FEATURE_LEVEL m_featureLevel;
D3D11CreateDevice(
nullptr, // specify null to use the default adapter
de,
0,
D3D11_CREATE_DEVICE_BGRA_SUPPORT, // optionally set debug and Direct2D compatibility flags
featureLevels, // list of feature levels this app can support
ARRAYSIZE(featureLevels), // number of possible feature levels
D3D11_SDK_VERSION,
&d.device, // returns the Direct3D device created
&m_featureLevel, // returns feature level of device created
&d.context // returns the device immediate context
);
if (!d.device)
return 0;
d.dxgiDevice = d.device;
if (!d.dxgiDevice)
return 0;
D2D1_CREATION_PROPERTIES dp;
dp.threadingMode = D2D1_THREADING_MODE::D2D1_THREADING_MODE_SINGLE_THREADED;
dp.debugLevel = D2D1_DEBUG_LEVEL::D2D1_DEBUG_LEVEL_NONE;
dp.options = D2D1_DEVICE_CONTEXT_OPTIONS::D2D1_DEVICE_CONTEXT_OPTIONS_NONE;
D2D1CreateDevice(d.dxgiDevice, dp, &d.m_d2dDevice);
if (!d.m_d2dDevice)
return 0;
d.m_d2dDevice->CreateDeviceContext(
D2D1_DEVICE_CONTEXT_OPTIONS_NONE,
&d.m_d2dContext);
if (!d.m_d2dContext)
return 0;
// Allocate a descriptor.
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 };
swapChainDesc.Width = 0; // use automatic sizing
swapChainDesc.Height = 0;
swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // this is the most common swapchain format
swapChainDesc.Stereo = false;
swapChainDesc.SampleDesc.Count = 1; // don't use multi-sampling
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.BufferCount = 2; // use double buffering to enable flip
swapChainDesc.Scaling = DXGI_SCALING_NONE;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // all apps must use this SwapEffect
swapChainDesc.Flags = 0;
d.dxgiDevice->GetAdapter(&d.dxgiAdapter);
if (!d.dxgiAdapter)
return 0;
// Get the factory object that created the DXGI device.
d.dxgiAdapter->GetParent(IID_PPV_ARGS(&d.dxgiFactory));
if (!d.dxgiFactory)
return 0;
d.dxgiFactory->CreateSwapChainForHwnd(
d.device,
hh, &swapChainDesc,
nullptr, // allow on all displays
nullptr, // allow on all displays
&d.m_swapChain);
if (!d.m_swapChain)
return 0;
d.dxgiDevice->SetMaximumFrameLatency(1);
d.m_swapChain->GetBuffer(0, IID_PPV_ARGS(&d.backBuffer));
if (!d.backBuffer)
return 0;
// Now we set up the Direct2D render target bitmap linked to the swapchain.
D2D1_BITMAP_PROPERTIES1 bitmapProperties;
bitmapProperties.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
bitmapProperties.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
bitmapProperties.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
bitmapProperties.dpiX = 96;
bitmapProperties.dpiY = 96;
bitmapProperties.colorContext = 0;
// Direct2D needs the dxgi version of the backbuffer surface pointer.
d.m_swapChain->GetBuffer(0, IID_PPV_ARGS(&d.dxgiBackBuffer));
if (!d.dxgiBackBuffer)
return 0;
// Get a D2D surface from the DXGI back buffer to use as the D2D render target.
d.m_d2dContext->CreateBitmapFromDxgiSurface(
d.dxgiBackBuffer,
&bitmapProperties,
&d.m_d2dTargetBitmap);
if (!d.m_d2dTargetBitmap)
return 0;
// Now we can set the Direct2D render target.
d.m_d2dContext->SetTarget(d.m_d2dTargetBitmap);
return true;
}
The problem is this code:
auto de = D3D_DRIVER_TYPE_HARDWARE;
When used, Direct2D writes nothing although EndDraw() returns S_OK. If I use D3D_DRIVER_TYPE_SOFTWARE, everything works correctly.
What am I doing wrong?

Executable not running in windows except when using terminal

I'm using the SDL_TFF library and it compiles, but the executable doesn't run directly, except when I run it from the terminal. If I comment out the SDL_TFF code it runs normally.
Does anyone know what could be causing this problem?
Edit:
#include <stdio.h>
#include <SDL.h>
#include <SDL_ttf.h> //version 2.0.12
TTF_Font* Font;
SDL_DisplayMode Desktop_Display_Mode;
SDL_Window* Window;
SDL_Surface* Window_surface;
SDL_Renderer* Renderer;
bool load_font()
{
//Font = TTF_OpenFont("fonts\\NotoSans-Bold.ttf", 16);
Font = TTF_OpenFont("fonts\\NotoSansCJKjp-Bold.otf", 18);
if (Font == NULL)
{
SDL_LogCritical(
SDL_LOG_CATEGORY_APPLICATION,
"Count not load font! TTF_Error: %s\n", TTF_GetError()
);
return false;
}
return true;
}
bool initialize()
{
// Initialize SDL Library
if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
{
SDL_LogCritical(
SDL_LOG_CATEGORY_APPLICATION,
"SDL could not initialize! SDL_Error: %s\n", SDL_GetError()
);
return false;
}
// Initialize SDL_ttf library
if (TTF_Init() != 0)
{
SDL_LogCritical(
SDL_LOG_CATEGORY_APPLICATION,
"SDL_ttf could not initialize! TTF_Error: %s\n", TTF_GetError()
);
return false;
}
// Load Font ---------------------------------------------------------------
if ( !load_font() )
{
return false;
}
// Get Desktop Display Mode
if (SDL_GetDesktopDisplayMode(0, &Desktop_Display_Mode) != 0)
{
SDL_LogCritical(
SDL_LOG_CATEGORY_APPLICATION,
"SDL could not get Desktop Display Mode! SDL_Error: %s\n",
SDL_GetError()
);
return false;
}
// Create Window
Window = SDL_CreateWindow(
"SDL Test",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
Desktop_Display_Mode.w, Desktop_Display_Mode.h,
SDL_WINDOW_BORDERLESS //Flags
);
if( Window == NULL )
{
SDL_LogCritical(
SDL_LOG_CATEGORY_APPLICATION,
"Window could not be created! SDL_Error: %s\n",
SDL_GetError()
);
return false;
}
Renderer = SDL_CreateRenderer( Window, -1,
SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC
);
if ( Renderer == NULL )
{
SDL_LogCritical(
SDL_LOG_CATEGORY_APPLICATION,
"Renderer could not be created! SDL_Error: %s\n",
SDL_GetError()
);
return false;
}
return true;
}
bool clear_screen()
{
if ( SDL_SetRenderDrawColor( Renderer, 0x00, 0x00, 0x00, 0xFF ) != 0 )
{
SDL_LogCritical(
SDL_LOG_CATEGORY_APPLICATION,
"Could not set render draw color! SDL_Error: %s\n",
SDL_GetError()
);
return false;
}
if ( SDL_RenderClear( Renderer ) != 0 )
{
SDL_LogCritical(
SDL_LOG_CATEGORY_APPLICATION,
"Could not clear the renderer! SDL_Error: %s\n",
SDL_GetError()
);
return false;
}
return true;
}
int main( int argc, char* args[] )
{
SDL_Log("Started.");
bool running = initialize();
SDL_Color text_color = {255, 255, 255};
const char* text_string;
text_string = "A journey of a thousand miles begins with a single step.\n こんにちは";
SDL_Rect text_dest;
text_dest.x = 100;
text_dest.y = 100;
text_dest.w = 0;
text_dest.h = 0;
if ( TTF_SizeUTF8(Font, text_string, &text_dest.w, &text_dest.h) != 0)
{
SDL_LogCritical(
SDL_LOG_CATEGORY_APPLICATION,
"Unable to get text size! TTF_Error: %s\n", TTF_GetError()
);
running = false;
}
SDL_Surface* text_surface = NULL;
text_surface = TTF_RenderUTF8_Solid(
Font,
text_string,
text_color
);
if ( text_surface == NULL )
{
SDL_LogCritical(
SDL_LOG_CATEGORY_APPLICATION,
"Unable to render text! SDL_Error: %s\n",
TTF_GetError()
);
running = false;
}
SDL_Texture* text_texture = NULL;
text_texture = SDL_CreateTextureFromSurface( Renderer, text_surface );
if ( text_texture == NULL )
{
SDL_LogCritical(
SDL_LOG_CATEGORY_APPLICATION,
"Unable to render text! SDL_Error: %s\n",
TTF_GetError()
);
running = false;
}
// MAIN LOOP ===============================================================
SDL_Event event;
while (running)
{
// Clear the screen
if ( !clear_screen() )
{
break;
}
// Check for events
if (SDL_PollEvent( &event))
{
// Check for the quit event
if (event.type == SDL_QUIT)
{
SDL_Log("Quit.");
break;
}
}
// Apply the text
if ( SDL_RenderCopy( Renderer, text_texture, NULL, &text_dest ) != 0 )
{
SDL_LogCritical(
SDL_LOG_CATEGORY_APPLICATION,
"Unable to draw text! SDL_Error: %s\n",
SDL_GetError()
);
break;
}
//Update Window
SDL_RenderPresent( Renderer );
}
//Destroy Window
SDL_DestroyWindow( Window );
SDL_DestroyRenderer( Renderer);
//Quit SDL subsystems
TTF_Quit();
SDL_Quit();
SDL_Log("Ended.");
return 0;
}
Edit2: I tested more thorougly and it seems that the function TTF_OpenFont() is causing the problem. As long as I don't call that function the exe will run normally.
SOLVED!
It was the way I was executing the program from command line: "\bin\myprog.exe"
Thus the relative filepath was incorrect because "\bin\fonts..." did not exist. As I have not implemented SDL_LogSetOutputFunction to write logs to a file and std out is apparently suppressed I could not see that I must have been getting error messages indicating that the file was not being loaded.

DirectX 11 Render to Texture Not Working

I want to render one triangle to texture and then that render to texture need to be displayed in a smaller size at top-left corner of screen with the original triangle at center of the screen.
I have developed one application but not succeeded. Please help me on this.
My code is as follows -
#include <windows.h>
#include <d3d11_1.h>
#include <d3dcompiler.h>
#include <directxmath.h>
#include <directxcolors.h>
#include "resource.h"
using namespace DirectX;
//--------------------------------------------------------------------------------------
// Structures
//--------------------------------------------------------------------------------------
struct SimpleVertex
{
XMFLOAT3 Pos;
};
//--------------------------------------------------------------------------------------
// Global Variables
//--------------------------------------------------------------------------------------
HINSTANCE g_hInst = nullptr;
HWND g_hWnd = nullptr;
D3D_DRIVER_TYPE g_driverType = D3D_DRIVER_TYPE_NULL;
D3D_FEATURE_LEVEL g_featureLevel = D3D_FEATURE_LEVEL_11_0;
ID3D11Device* g_pd3dDevice = nullptr;
ID3D11Device1* g_pd3dDevice1 = nullptr;
ID3D11DeviceContext* g_pImmediateContext = nullptr;
ID3D11DeviceContext1* g_pImmediateContext1 = nullptr;
IDXGISwapChain* g_pSwapChain = nullptr;
IDXGISwapChain1* g_pSwapChain1 = nullptr;
ID3D11RenderTargetView* g_pRenderTargetView = nullptr;
ID3D11VertexShader* g_pVertexShader = nullptr;
ID3D11PixelShader* g_pPixelShader = nullptr;
ID3D11InputLayout* g_pVertexLayout = nullptr;
ID3D11Buffer* g_pVertexBuffer = nullptr;
ID3D11Texture2D* m_renderTargetTexture=nullptr;
ID3D11RenderTargetView* m_renderTargetView=nullptr;
ID3D11ShaderResourceView* m_shaderResourceView=nullptr;
ID3D11DepthStencilView* m_depthStencilView;
ID3D11Texture2D* m_depthStencilBuffer;
ID3D11DepthStencilState* m_depthStencilState;
//--------------------------------------------------------------------------------------
// Forward declarations
//--------------------------------------------------------------------------------------
HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow );
HRESULT InitDevice();
void CleanupDevice();
LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM );
void Render();
void RenderOnTexture();
//--------------------------------------------------------------------------------------
// Entry point to the program. Initializes everything and goes into a message processing
// loop. Idle time is used to render the scene.
//--------------------------------------------------------------------------------------
int WINAPI wWinMain( _In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow )
{
UNREFERENCED_PARAMETER( hPrevInstance );
UNREFERENCED_PARAMETER( lpCmdLine );
if( FAILED( InitWindow( hInstance, nCmdShow ) ) )
return 0;
if( FAILED( InitDevice() ) )
{
CleanupDevice();
return 0;
}
// Main message loop
MSG msg = {0};
while( WM_QUIT != msg.message )
{
if( PeekMessage( &msg, nullptr, 0, 0, PM_REMOVE ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
else
{
Render();
}
}
CleanupDevice();
return ( int )msg.wParam;
}
//--------------------------------------------------------------------------------------
// Register class and create window
//--------------------------------------------------------------------------------------
HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow )
{
// Register class
WNDCLASSEX wcex;
wcex.cbSize = sizeof( WNDCLASSEX );
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon( hInstance, ( LPCTSTR )IDI_TUTORIAL1 );
wcex.hCursor = LoadCursor( nullptr, IDC_ARROW );
wcex.hbrBackground = ( HBRUSH )( COLOR_WINDOW + 1 );
wcex.lpszMenuName = nullptr;
wcex.lpszClassName = L"TutorialWindowClass";
wcex.hIconSm = LoadIcon( wcex.hInstance, ( LPCTSTR )IDI_TUTORIAL1 );
if( !RegisterClassEx( &wcex ) )
return E_FAIL;
// Create window
g_hInst = hInstance;
RECT rc = { 0, 0, 800, 600 };
AdjustWindowRect( &rc, WS_OVERLAPPEDWINDOW, FALSE );
g_hWnd = CreateWindow( L"TutorialWindowClass", L"Direct3D 11 Tutorial 2: Rendering a Triangle",
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, nullptr, nullptr, hInstance,
nullptr );
if( !g_hWnd )
return E_FAIL;
ShowWindow( g_hWnd, nCmdShow );
return S_OK;
}
//--------------------------------------------------------------------------------------
// Helper for compiling shaders with D3DCompile
//
// With VS 11, we could load up prebuilt .cso files instead...
//--------------------------------------------------------------------------------------
HRESULT CompileShaderFromFile( WCHAR* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut )
{
HRESULT hr = S_OK;
DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS;
#ifdef _DEBUG
// Set the D3DCOMPILE_DEBUG flag to embed debug information in the shaders.
// Setting this flag improves the shader debugging experience, but still allows
// the shaders to be optimized and to run exactly the way they will run in
// the release configuration of this program.
dwShaderFlags |= D3DCOMPILE_DEBUG;
// Disable optimizations to further improve shader debugging
dwShaderFlags |= D3DCOMPILE_SKIP_OPTIMIZATION;
#endif
ID3DBlob* pErrorBlob = nullptr;
hr = D3DCompileFromFile( szFileName, nullptr, nullptr, szEntryPoint, szShaderModel,
dwShaderFlags, 0, ppBlobOut, &pErrorBlob );
if( FAILED(hr) )
{
if( pErrorBlob )
{
OutputDebugStringA( reinterpret_cast<const char*>( pErrorBlob->GetBufferPointer() ) );
pErrorBlob->Release();
}
return hr;
}
if( pErrorBlob ) pErrorBlob->Release();
return S_OK;
}
//--------------------------------------------------------------------------------------
// Create Direct3D device and swap chain
//--------------------------------------------------------------------------------------
HRESULT InitDevice()
{
HRESULT hr = S_OK;
RECT rc;
GetClientRect( g_hWnd, &rc );
UINT width = rc.right - rc.left;
UINT height = rc.bottom - rc.top;
UINT createDeviceFlags = 0;
#ifdef _DEBUG
createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
D3D_DRIVER_TYPE driverTypes[] =
{
D3D_DRIVER_TYPE_HARDWARE,
D3D_DRIVER_TYPE_WARP,
D3D_DRIVER_TYPE_REFERENCE,
};
UINT numDriverTypes = ARRAYSIZE( driverTypes );
D3D_FEATURE_LEVEL featureLevels[] =
{
D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
};
UINT numFeatureLevels = ARRAYSIZE( featureLevels );
for( UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++ )
{
g_driverType = driverTypes[driverTypeIndex];
hr = D3D11CreateDevice( nullptr, g_driverType, nullptr, createDeviceFlags, featureLevels, numFeatureLevels,
D3D11_SDK_VERSION, &g_pd3dDevice, &g_featureLevel, &g_pImmediateContext );
if ( hr == E_INVALIDARG )
{
// DirectX 11.0 platforms will not recognize D3D_FEATURE_LEVEL_11_1 so we need to retry without it
hr = D3D11CreateDevice( nullptr, g_driverType, nullptr, createDeviceFlags, &featureLevels[1], numFeatureLevels - 1,
D3D11_SDK_VERSION, &g_pd3dDevice, &g_featureLevel, &g_pImmediateContext );
}
if( SUCCEEDED( hr ) )
break;
}
if( FAILED( hr ) )
return hr;
// Obtain DXGI factory from device (since we used nullptr for pAdapter above)
IDXGIFactory1* dxgiFactory = nullptr;
{
IDXGIDevice* dxgiDevice = nullptr;
hr = g_pd3dDevice->QueryInterface( __uuidof(IDXGIDevice), reinterpret_cast<void**>(&dxgiDevice) );
if (SUCCEEDED(hr))
{
IDXGIAdapter* adapter = nullptr;
hr = dxgiDevice->GetAdapter(&adapter);
if (SUCCEEDED(hr))
{
hr = adapter->GetParent( __uuidof(IDXGIFactory1), reinterpret_cast<void**>(&dxgiFactory) );
adapter->Release();
}
dxgiDevice->Release();
}
}
if (FAILED(hr))
return hr;
// Create swap chain
IDXGIFactory2* dxgiFactory2 = nullptr;
hr = dxgiFactory->QueryInterface( __uuidof(IDXGIFactory2), reinterpret_cast<void**>(&dxgiFactory2) );
if ( dxgiFactory2 )
{
// DirectX 11.1 or later
hr = g_pd3dDevice->QueryInterface( __uuidof(ID3D11Device1), reinterpret_cast<void**>(&g_pd3dDevice1) );
if (SUCCEEDED(hr))
{
(void) g_pImmediateContext->QueryInterface( __uuidof(ID3D11DeviceContext1), reinterpret_cast<void**>(&g_pImmediateContext1) );
}
DXGI_SWAP_CHAIN_DESC1 sd;
ZeroMemory(&sd, sizeof(sd));
sd.Width = width;
sd.Height = height;
sd.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.BufferCount = 1;
hr = dxgiFactory2->CreateSwapChainForHwnd( g_pd3dDevice, g_hWnd, &sd, nullptr, nullptr, &g_pSwapChain1 );
if (SUCCEEDED(hr))
{
hr = g_pSwapChain1->QueryInterface( __uuidof(IDXGISwapChain), reinterpret_cast<void**>(&g_pSwapChain) );
}
dxgiFactory2->Release();
}
else
{
// DirectX 11.0 systems
DXGI_SWAP_CHAIN_DESC sd;
ZeroMemory(&sd, sizeof(sd));
sd.BufferCount = 1;
sd.BufferDesc.Width = width;
sd.BufferDesc.Height = height;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferDesc.RefreshRate.Numerator = 60;
sd.BufferDesc.RefreshRate.Denominator = 1;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.OutputWindow = g_hWnd;
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.Windowed = TRUE;
hr = dxgiFactory->CreateSwapChain( g_pd3dDevice, &sd, &g_pSwapChain );
}
// Note this tutorial doesn't handle full-screen swapchains so we block the ALT+ENTER shortcut
dxgiFactory->MakeWindowAssociation( g_hWnd, DXGI_MWA_NO_ALT_ENTER );
dxgiFactory->Release();
if (FAILED(hr))
return hr;
// Create a render target view
ID3D11Texture2D* pBackBuffer = nullptr;
hr = g_pSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), reinterpret_cast<void**>( &pBackBuffer ) );
if( FAILED( hr ) )
return hr;
hr = g_pd3dDevice->CreateRenderTargetView( pBackBuffer, nullptr, &g_pRenderTargetView );
pBackBuffer->Release();
if( FAILED( hr ) )
return hr;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
D3D11_TEXTURE2D_DESC textureDesc;
HRESULT result;
D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc;
D3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc;
// Initialize the render target texture description.
ZeroMemory(&textureDesc, sizeof(textureDesc));
// Setup the render target texture description.
textureDesc.Width = 400/*textureWidth*/;
textureDesc.Height = 400/*textureHeight*/;
textureDesc.MipLevels = 1;
textureDesc.ArraySize = 1;
textureDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
textureDesc.SampleDesc.Count = 1;
textureDesc.Usage = D3D11_USAGE_DEFAULT;
textureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
textureDesc.CPUAccessFlags = 0;
textureDesc.MiscFlags = 0;
// Create the render target texture.
result = g_pd3dDevice->CreateTexture2D(&textureDesc, NULL, &m_renderTargetTexture);
if (FAILED(result))
{
return false;
}
// Setup the description of the render target view.
renderTargetViewDesc.Format = textureDesc.Format;
renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
renderTargetViewDesc.Texture2D.MipSlice = 0;
// Create the render target view.
result = g_pd3dDevice->CreateRenderTargetView(m_renderTargetTexture, &renderTargetViewDesc, &m_renderTargetView);
if (FAILED(result))
{
return false;
}
// Setup the description of the shader resource view.
shaderResourceViewDesc.Format = textureDesc.Format;
shaderResourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
shaderResourceViewDesc.Texture2D.MostDetailedMip = 0;
shaderResourceViewDesc.Texture2D.MipLevels = 1;
// Create the shader resource view.
result = g_pd3dDevice->CreateShaderResourceView(m_renderTargetTexture, &shaderResourceViewDesc, &m_shaderResourceView);
//D3D11_TEXTURE2D_DESC depthBufferDesc;
//D3D11_DEPTH_STENCIL_DESC depthStencilDesc;
//D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc;
//// Initialize the description of the depth buffer.
//ZeroMemory(&depthBufferDesc, sizeof(depthBufferDesc));
//// Set up the description of the depth buffer.
//depthBufferDesc.Width = 400;
//depthBufferDesc.Height = 400;
//depthBufferDesc.MipLevels = 1;
//depthBufferDesc.ArraySize = 1;
//depthBufferDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
//depthBufferDesc.SampleDesc.Count = 1;
//depthBufferDesc.SampleDesc.Quality = 0;
//depthBufferDesc.Usage = D3D11_USAGE_DEFAULT;
//depthBufferDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
//depthBufferDesc.CPUAccessFlags = 0;
//depthBufferDesc.MiscFlags = 0;
//// Create the texture for the depth buffer using the filled out description.
//result = g_pd3dDevice->CreateTexture2D(&depthBufferDesc, NULL, &m_depthStencilBuffer);
//if (FAILED(result))
//{
// return false;
//}
//// Initialize the description of the stencil state.
//ZeroMemory(&depthStencilDesc, sizeof(depthStencilDesc));
//// Set up the description of the stencil state.
//depthStencilDesc.DepthEnable = true;
//depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
//depthStencilDesc.DepthFunc = D3D11_COMPARISON_LESS;
//depthStencilDesc.StencilEnable = true;
//depthStencilDesc.StencilReadMask = 0xFF;
//depthStencilDesc.StencilWriteMask = 0xFF;
//// Stencil operations if pixel is front-facing.
//depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
//depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
//depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
//depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
//// Stencil operations if pixel is back-facing.
//depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
//depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
//depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
//depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
//// Create the depth stencil state.
//result = g_pd3dDevice->CreateDepthStencilState(&depthStencilDesc, &m_depthStencilState);
//if (FAILED(result))
//{
// return false;
//}
//// Set the depth stencil state.
//g_pImmediateContext->OMSetDepthStencilState(m_depthStencilState, 1);
//// Initialize the depth stencil view.
//ZeroMemory(&depthStencilViewDesc, sizeof(depthStencilViewDesc));
//// Set up the depth stencil view description.
//depthStencilViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
//depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
//depthStencilViewDesc.Texture2D.MipSlice = 0;
//// Create the depth stencil view.
//result = g_pd3dDevice->CreateDepthStencilView(m_depthStencilBuffer, &depthStencilViewDesc, &m_depthStencilView);
//if (FAILED(result))
//{
// return false;
//}
// Bind the render target view and depth stencil buffer to the output render pipeline.
g_pImmediateContext->OMSetRenderTargets(1, &m_renderTargetView, /*m_depthStencilView*/nullptr);
// Clear the back buffer.
g_pImmediateContext->ClearRenderTargetView(m_renderTargetView, Colors::Red);
// Clear the depth buffer.
//g_pImmediateContext->ClearDepthStencilView(depthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0);
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Setup the viewport
D3D11_VIEWPORT vp;
vp.Width = (FLOAT)width;
vp.Height = (FLOAT)height;
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
vp.TopLeftX = 0;
vp.TopLeftY = 0;
g_pImmediateContext->RSSetViewports( 1, &vp );
// Compile the vertex shader
ID3DBlob* pVSBlob = nullptr;
hr = CompileShaderFromFile( L"Tutorial02.fx", "VS", "vs_4_0", &pVSBlob );
if( FAILED( hr ) )
{
MessageBox( nullptr,
L"The FX file cannot be compiled. Please run this executable from the directory that contains the FX file.", L"Error", MB_OK );
return hr;
}
// Create the vertex shader
hr = g_pd3dDevice->CreateVertexShader( pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), nullptr, &g_pVertexShader );
if( FAILED( hr ) )
{
pVSBlob->Release();
return hr;
}
// Define the input layout
D3D11_INPUT_ELEMENT_DESC layout[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
UINT numElements = ARRAYSIZE( layout );
// Create the input layout
hr = g_pd3dDevice->CreateInputLayout( layout, numElements, pVSBlob->GetBufferPointer(),
pVSBlob->GetBufferSize(), &g_pVertexLayout );
pVSBlob->Release();
if( FAILED( hr ) )
return hr;
// Set the input layout
g_pImmediateContext->IASetInputLayout( g_pVertexLayout );
// Compile the pixel shader
ID3DBlob* pPSBlob = nullptr;
hr = CompileShaderFromFile( L"Tutorial02.fx", "PS", "ps_4_0", &pPSBlob );
if( FAILED( hr ) )
{
MessageBox( nullptr,
L"The FX file cannot be compiled. Please run this executable from the directory that contains the FX file.", L"Error", MB_OK );
return hr;
}
// Create the pixel shader
hr = g_pd3dDevice->CreatePixelShader( pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), nullptr, &g_pPixelShader );
pPSBlob->Release();
if( FAILED( hr ) )
return hr;
// Create vertex buffer
SimpleVertex vertices[] =
{
XMFLOAT3( 0.0f, 0.5f, 0.5f ),
XMFLOAT3( 0.5f, -0.5f, 0.5f ),
XMFLOAT3( -0.5f, -0.5f, 0.5f ),
};
D3D11_BUFFER_DESC bd;
ZeroMemory( &bd, sizeof(bd) );
bd.Usage = D3D11_USAGE_DEFAULT;
bd.ByteWidth = sizeof( SimpleVertex ) * 3;
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bd.CPUAccessFlags = 0;
D3D11_SUBRESOURCE_DATA InitData;
ZeroMemory( &InitData, sizeof(InitData) );
InitData.pSysMem = vertices;
hr = g_pd3dDevice->CreateBuffer( &bd, &InitData, &g_pVertexBuffer );
if( FAILED( hr ) )
return hr;
// Set vertex buffer
UINT stride = sizeof( SimpleVertex );
UINT offset = 0;
g_pImmediateContext->IASetVertexBuffers( 0, 1, &g_pVertexBuffer, &stride, &offset );
// Set primitive topology
g_pImmediateContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );
RenderOnTexture();
return S_OK;
}
//--------------------------------------------------------------------------------------
// Clean up the objects we've created
//--------------------------------------------------------------------------------------
void CleanupDevice()
{
if( g_pImmediateContext ) g_pImmediateContext->ClearState();
if( g_pVertexBuffer ) g_pVertexBuffer->Release();
if( g_pVertexLayout ) g_pVertexLayout->Release();
if( g_pVertexShader ) g_pVertexShader->Release();
if( g_pPixelShader ) g_pPixelShader->Release();
if( g_pRenderTargetView ) g_pRenderTargetView->Release();
if( g_pSwapChain1 ) g_pSwapChain1->Release();
if( g_pSwapChain ) g_pSwapChain->Release();
if( g_pImmediateContext1 ) g_pImmediateContext1->Release();
if( g_pImmediateContext ) g_pImmediateContext->Release();
if( g_pd3dDevice1 ) g_pd3dDevice1->Release();
if( g_pd3dDevice ) g_pd3dDevice->Release();
}
//--------------------------------------------------------------------------------------
// Called every time the application receives a message
//--------------------------------------------------------------------------------------
LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
PAINTSTRUCT ps;
HDC hdc;
switch( message )
{
case WM_PAINT:
hdc = BeginPaint( hWnd, &ps );
EndPaint( hWnd, &ps );
break;
case WM_DESTROY:
PostQuitMessage( 0 );
break;
// Note that this tutorial does not handle resizing (WM_SIZE) requests,
// so we created the window without the resize border.
default:
return DefWindowProc( hWnd, message, wParam, lParam );
}
return 0;
}
//--------------------------------------------------------------------------------------
// Render a frame
//--------------------------------------------------------------------------------------
void Render()
{
// Clear the back buffer
g_pImmediateContext->ClearRenderTargetView( g_pRenderTargetView, Colors::MidnightBlue );
// Render a triangle
/*g_pImmediateContext->VSSetShader( g_pVertexShader, nullptr, 0 );
g_pImmediateContext->PSSetShader( g_pPixelShader, nullptr, 0 );
g_pImmediateContext->Draw( 3, 0 );*/
g_pImmediateContext->PSSetShaderResources(0, 1, &m_shaderResourceView);
// Present the information rendered to the back buffer to the front buffer (the screen)
g_pSwapChain->Present( 0, 0 );
}
void RenderOnTexture()
{
g_pImmediateContext->VSSetShader(g_pVertexShader, nullptr, 0);
g_pImmediateContext->PSSetShader(g_pPixelShader, nullptr, 0);
g_pImmediateContext->Draw(3, 0);
g_pImmediateContext->OMSetRenderTargets(1, &g_pRenderTargetView, nullptr);
}
Your Render() function has no draw calls in it.

OSX programmatically invoke sound level graphic

I have an app which can change the volume under OSX. What it lacks is the visual feedback provided when one presses the sound up/down keys. Does anyone know how to programmatically invoke that behavior?
Thanks
Here's a little code from George Warner and Casey Fleser that does this trick. Think carefully that this is really the way you want to do things.
// Save as sound_up.m
// Compile: gcc -o sound_up sound_up.m -framework IOKit -framework Cocoa
#import <Cocoa/Cocoa.h>
#import <IOKit/hidsystem/IOHIDLib.h>
#import <IOKit/hidsystem/ev_keymap.h>
static io_connect_t get_event_driver(void)
{
static mach_port_t sEventDrvrRef = 0;
mach_port_t masterPort, service, iter;
kern_return_t kr;
if (!sEventDrvrRef)
{
// Get master device port
kr = IOMasterPort( bootstrap_port, &masterPort );
check( KERN_SUCCESS == kr);
kr = IOServiceGetMatchingServices( masterPort, IOServiceMatching( kIOHIDSystemClass ), &iter );
check( KERN_SUCCESS == kr);
service = IOIteratorNext( iter );
check( service );
kr = IOServiceOpen( service, mach_task_self(),
kIOHIDParamConnectType, &sEventDrvrRef );
check( KERN_SUCCESS == kr );
IOObjectRelease( service );
IOObjectRelease( iter );
}
return sEventDrvrRef;
}
static void HIDPostAuxKey( const UInt8 auxKeyCode )
{
NXEventData event;
kern_return_t kr;
IOGPoint loc = { 0, 0 };
// Key press event
UInt32 evtInfo = auxKeyCode << 16 | NX_KEYDOWN << 8;
bzero(&event, sizeof(NXEventData));
event.compound.subType = NX_SUBTYPE_AUX_CONTROL_BUTTONS;
event.compound.misc.L[0] = evtInfo;
kr = IOHIDPostEvent( get_event_driver(), NX_SYSDEFINED, loc, &event, kNXEventDataVersion, 0, FALSE );
check( KERN_SUCCESS == kr );
// Key release event
evtInfo = auxKeyCode << 16 | NX_KEYUP << 8;
bzero(&event, sizeof(NXEventData));
event.compound.subType = NX_SUBTYPE_AUX_CONTROL_BUTTONS;
event.compound.misc.L[0] = evtInfo;
kr = IOHIDPostEvent( get_event_driver(), NX_SYSDEFINED, loc, &event, kNXEventDataVersion, 0, FALSE );
check( KERN_SUCCESS == kr );
}
int main(int argc, char *argv[]) {
HIDPostAuxKey(NX_KEYTYPE_SOUND_UP);
}
Other interesting keycodes include: NX_KEYTYPE_SOUND_DOWN, NX_KEYTYPE_MUTE, NX_KEYTYPE_PLAY.
I would implement this by simulating the physical press of the up/down volume keys, and letting the OS deal with the details. Perhaps the user has disabled the visual feedback, perhaps it changes, etc. - this is the safest way of pulling it off.
Have a look at this: Simulating key press events in Mac OS X

Resources