src/render/direct3d11/SDL_render_d3d11.cpp
author David Ludwig <dludwig@pobox.com>
Wed, 25 Dec 2013 14:17:49 -0500
changeset 8560 5e14c111f2f9
parent 8559 9429f36bca22
child 8561 c10e5bfa6459
permissions -rw-r--r--
WinRT: renamed d3d11-internal struct, SDL_VertexShaderConstants, to just VertexShaderConstants

This is primarily to keep naming consistent with other shader-bound structs.
dludwig@8400
     1
/*
dludwig@8400
     2
  Simple DirectMedia Layer
dludwig@8400
     3
  Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
dludwig@8400
     4
dludwig@8400
     5
  This software is provided 'as-is', without any express or implied
dludwig@8400
     6
  warranty.  In no event will the authors be held liable for any damages
dludwig@8400
     7
  arising from the use of this software.
dludwig@8400
     8
dludwig@8400
     9
  Permission is granted to anyone to use this software for any purpose,
dludwig@8400
    10
  including commercial applications, and to alter it and redistribute it
dludwig@8400
    11
  freely, subject to the following restrictions:
dludwig@8400
    12
dludwig@8400
    13
  1. The origin of this software must not be misrepresented; you must not
dludwig@8400
    14
     claim that you wrote the original software. If you use this software
dludwig@8400
    15
     in a product, an acknowledgment in the product documentation would be
dludwig@8400
    16
     appreciated but is not required.
dludwig@8400
    17
  2. Altered source versions must be plainly marked as such, and must not be
dludwig@8400
    18
     misrepresented as being the original software.
dludwig@8400
    19
  3. This notice may not be removed or altered from any source distribution.
dludwig@8400
    20
*/
dludwig@8400
    21
dludwig@8400
    22
#include "SDL_config.h"
dludwig@8400
    23
dludwig@8400
    24
#if SDL_VIDEO_RENDER_D3D11 && !SDL_RENDER_DISABLED
dludwig@8400
    25
dludwig@8463
    26
#ifdef __WINRT__
dludwig@8463
    27
#include <windows.ui.core.h>
dludwig@8463
    28
#include <windows.foundation.h>
dludwig@8505
    29
dludwig@8505
    30
#if WINAPI_FAMILY == WINAPI_FAMILY_APP
dludwig@8505
    31
#include <windows.ui.xaml.media.dxinterop.h>
dludwig@8505
    32
#endif
dludwig@8505
    33
dludwig@8463
    34
#endif
dludwig@8463
    35
dludwig@8400
    36
extern "C" {
dludwig@8400
    37
#include "../../core/windows/SDL_windows.h"
dludwig@8533
    38
#include "SDL_hints.h"
dludwig@8400
    39
//#include "SDL_loadso.h"
dludwig@8410
    40
#include "SDL_system.h"
dludwig@8400
    41
#include "SDL_syswm.h"
dludwig@8400
    42
#include "../SDL_sysrender.h"
dludwig@8433
    43
#include "SDL_log.h"
dludwig@8433
    44
#include "../../video/SDL_sysvideo.h"
dludwig@8400
    45
//#include "stdio.h"
dludwig@8400
    46
}
dludwig@8400
    47
dludwig@8410
    48
#include <fstream>
dludwig@8410
    49
#include <string>
dludwig@8410
    50
#include <vector>
dludwig@8410
    51
dludwig@8559
    52
#include <D3D11_1.h>
dludwig@8559
    53
#include <DirectXMath.h>
dludwig@8559
    54
#include <wrl/client.h>
dludwig@8559
    55
dludwig@8400
    56
dludwig@8410
    57
using namespace DirectX;
dludwig@8410
    58
using namespace Microsoft::WRL;
dludwig@8410
    59
using namespace std;
dludwig@8410
    60
dludwig@8412
    61
#ifdef __WINRT__
dludwig@8412
    62
using namespace Windows::Graphics::Display;
dludwig@8412
    63
using namespace Windows::UI::Core;
dludwig@8412
    64
#endif
dludwig@8412
    65
dludwig@8540
    66
/* Texture sampling types */
dludwig@8540
    67
static const D3D11_FILTER SDL_D3D11_NEAREST_PIXEL_FILTER = D3D11_FILTER_MIN_MAG_MIP_POINT;
dludwig@8540
    68
static const D3D11_FILTER SDL_D3D11_LINEAR_FILTER = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
dludwig@8540
    69
dludwig@8559
    70
/* Vertex shader, common values */
dludwig@8560
    71
struct VertexShaderConstants
dludwig@8559
    72
{
dludwig@8559
    73
    DirectX::XMFLOAT4X4 model;
dludwig@8559
    74
    DirectX::XMFLOAT4X4 view;
dludwig@8559
    75
    DirectX::XMFLOAT4X4 projection;
dludwig@8559
    76
};
dludwig@8559
    77
dludwig@8559
    78
/* Per-vertex data */
dludwig@8559
    79
struct VertexPositionColor
dludwig@8559
    80
{
dludwig@8559
    81
    DirectX::XMFLOAT3 pos;
dludwig@8559
    82
    DirectX::XMFLOAT2 tex;
dludwig@8559
    83
    DirectX::XMFLOAT4 color;
dludwig@8559
    84
};
dludwig@8559
    85
dludwig@8559
    86
/* Per-texture data */
dludwig@8559
    87
typedef struct
dludwig@8559
    88
{
dludwig@8559
    89
    Microsoft::WRL::ComPtr<ID3D11Texture2D> mainTexture;
dludwig@8559
    90
    Microsoft::WRL::ComPtr<ID3D11ShaderResourceView> mainTextureResourceView;
dludwig@8559
    91
    Microsoft::WRL::ComPtr<ID3D11RenderTargetView> mainTextureRenderTargetView;
dludwig@8559
    92
    SDL_PixelFormat * pixelFormat;
dludwig@8559
    93
    Microsoft::WRL::ComPtr<ID3D11Texture2D> stagingTexture;
dludwig@8559
    94
    DirectX::XMINT2 lockedTexturePosition;
dludwig@8559
    95
    D3D11_FILTER scaleMode;
dludwig@8559
    96
} D3D11_TextureData;
dludwig@8559
    97
dludwig@8559
    98
/* Private renderer data */
dludwig@8559
    99
typedef struct
dludwig@8559
   100
{
dludwig@8559
   101
    Microsoft::WRL::ComPtr<ID3D11Device1> d3dDevice;
dludwig@8559
   102
    Microsoft::WRL::ComPtr<ID3D11DeviceContext1> d3dContext;
dludwig@8559
   103
    Microsoft::WRL::ComPtr<IDXGISwapChain1> swapChain;
dludwig@8559
   104
    Microsoft::WRL::ComPtr<ID3D11RenderTargetView> mainRenderTargetView;
dludwig@8559
   105
    Microsoft::WRL::ComPtr<ID3D11RenderTargetView> currentOffscreenRenderTargetView;
dludwig@8559
   106
    Microsoft::WRL::ComPtr<ID3D11InputLayout> inputLayout;
dludwig@8559
   107
    Microsoft::WRL::ComPtr<ID3D11Buffer> vertexBuffer;
dludwig@8559
   108
    Microsoft::WRL::ComPtr<ID3D11VertexShader> vertexShader;
dludwig@8559
   109
    Microsoft::WRL::ComPtr<ID3D11PixelShader> texturePixelShader;
dludwig@8559
   110
    Microsoft::WRL::ComPtr<ID3D11PixelShader> colorPixelShader;
dludwig@8559
   111
    Microsoft::WRL::ComPtr<ID3D11BlendState> blendModeBlend;
dludwig@8559
   112
    Microsoft::WRL::ComPtr<ID3D11BlendState> blendModeAdd;
dludwig@8559
   113
    Microsoft::WRL::ComPtr<ID3D11BlendState> blendModeMod;
dludwig@8559
   114
    Microsoft::WRL::ComPtr<ID3D11SamplerState> nearestPixelSampler;
dludwig@8559
   115
    Microsoft::WRL::ComPtr<ID3D11SamplerState> linearSampler;
dludwig@8559
   116
    Microsoft::WRL::ComPtr<ID3D11RasterizerState> mainRasterizer;
dludwig@8559
   117
    D3D_FEATURE_LEVEL featureLevel;
dludwig@8559
   118
dludwig@8559
   119
    // Vertex buffer constants:
dludwig@8560
   120
    VertexShaderConstants vertexShaderConstantsData;
dludwig@8559
   121
    Microsoft::WRL::ComPtr<ID3D11Buffer> vertexShaderConstants;
dludwig@8559
   122
dludwig@8559
   123
    // Cached renderer properties.
dludwig@8559
   124
    DirectX::XMFLOAT2 windowSizeInDIPs;
dludwig@8559
   125
    DirectX::XMFLOAT2 renderTargetSize;
dludwig@8559
   126
    Windows::Graphics::Display::DisplayOrientations orientation;
dludwig@8559
   127
dludwig@8559
   128
    // Transform used for display orientation.
dludwig@8559
   129
    DirectX::XMFLOAT4X4 orientationTransform3D;
dludwig@8559
   130
} D3D11_RenderData;
dludwig@8559
   131
dludwig@8559
   132
dludwig@8410
   133
/* Direct3D 11.1 renderer implementation */
dludwig@8400
   134
static SDL_Renderer *D3D11_CreateRenderer(SDL_Window * window, Uint32 flags);
dludwig@8415
   135
static void D3D11_WindowEvent(SDL_Renderer * renderer,
dludwig@8415
   136
                            const SDL_WindowEvent *event);
dludwig@8416
   137
static int D3D11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
dludwig@8416
   138
static int D3D11_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
dludwig@8459
   139
                             const SDL_Rect * rect, const void *srcPixels,
dludwig@8459
   140
                             int srcPitch);
dludwig@8451
   141
static int D3D11_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
dludwig@8451
   142
                             const SDL_Rect * rect, void **pixels, int *pitch);
dludwig@8451
   143
static void D3D11_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
dludwig@8459
   144
static int D3D11_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture);
dludwig@8400
   145
static int D3D11_UpdateViewport(SDL_Renderer * renderer);
dludwig@8482
   146
static int D3D11_UpdateClipRect(SDL_Renderer * renderer);
dludwig@8416
   147
static int D3D11_RenderClear(SDL_Renderer * renderer);
dludwig@8450
   148
static int D3D11_RenderDrawPoints(SDL_Renderer * renderer,
dludwig@8450
   149
                                  const SDL_FPoint * points, int count);
dludwig@8449
   150
static int D3D11_RenderDrawLines(SDL_Renderer * renderer,
dludwig@8449
   151
                                 const SDL_FPoint * points, int count);
dludwig@8429
   152
static int D3D11_RenderFillRects(SDL_Renderer * renderer,
dludwig@8429
   153
                                 const SDL_FRect * rects, int count);
dludwig@8416
   154
static int D3D11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
dludwig@8416
   155
                            const SDL_Rect * srcrect, const SDL_FRect * dstrect);
dludwig@8455
   156
static int D3D11_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
dludwig@8455
   157
                              const SDL_Rect * srcrect, const SDL_FRect * dstrect,
dludwig@8455
   158
                              const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip);
dludwig@8454
   159
static int D3D11_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
dludwig@8454
   160
                                  Uint32 format, void * pixels, int pitch);
dludwig@8401
   161
static void D3D11_RenderPresent(SDL_Renderer * renderer);
dludwig@8416
   162
static void D3D11_DestroyTexture(SDL_Renderer * renderer,
dludwig@8416
   163
                                 SDL_Texture * texture);
dludwig@8413
   164
static void D3D11_DestroyRenderer(SDL_Renderer * renderer);
dludwig@8400
   165
dludwig@8410
   166
/* Direct3D 11.1 Internal Functions */
dludwig@8412
   167
HRESULT D3D11_CreateDeviceResources(SDL_Renderer * renderer);
dludwig@8413
   168
HRESULT D3D11_CreateWindowSizeDependentResources(SDL_Renderer * renderer);
dludwig@8414
   169
HRESULT D3D11_UpdateForWindowSizeChange(SDL_Renderer * renderer);
dludwig@8414
   170
HRESULT D3D11_HandleDeviceLost(SDL_Renderer * renderer);
dludwig@8400
   171
dludwig@8442
   172
extern "C" SDL_RenderDriver D3D11_RenderDriver = {
dludwig@8400
   173
    D3D11_CreateRenderer,
dludwig@8400
   174
    {
dludwig@8442
   175
        "direct3d 11.1",
dludwig@8459
   176
        (
dludwig@8459
   177
            SDL_RENDERER_ACCELERATED |
dludwig@8459
   178
            SDL_RENDERER_PRESENTVSYNC |
dludwig@8459
   179
            SDL_RENDERER_TARGETTEXTURE
dludwig@8459
   180
        ),                          // flags.  see SDL_RendererFlags
dludwig@8442
   181
        2,                          // num_texture_formats
dludwig@8442
   182
        {                           // texture_formats
dludwig@8442
   183
            SDL_PIXELFORMAT_RGB888,
dludwig@8442
   184
            SDL_PIXELFORMAT_ARGB8888
dludwig@8442
   185
        },
dludwig@8446
   186
        0,                          // max_texture_width: will be filled in later
dludwig@8446
   187
        0                           // max_texture_height: will be filled in later
dludwig@8442
   188
    }
dludwig@8442
   189
};
dludwig@8442
   190
dludwig@8400
   191
dludwig@8454
   192
static Uint32
dludwig@8454
   193
DXGIFormatToSDLPixelFormat(DXGI_FORMAT dxgiFormat) {
dludwig@8454
   194
    switch (dxgiFormat) {
dludwig@8454
   195
        case DXGI_FORMAT_B8G8R8A8_UNORM:
dludwig@8454
   196
            return SDL_PIXELFORMAT_ARGB8888;
dludwig@8454
   197
        case DXGI_FORMAT_B8G8R8X8_UNORM:
dludwig@8454
   198
            return SDL_PIXELFORMAT_RGB888;
dludwig@8454
   199
        default:
dludwig@8454
   200
            return SDL_PIXELFORMAT_UNKNOWN;
dludwig@8454
   201
    }
dludwig@8454
   202
}
dludwig@8454
   203
dludwig@8454
   204
static DXGI_FORMAT
dludwig@8454
   205
SDLPixelFormatToDXGIFormat(Uint32 sdlFormat)
dludwig@8454
   206
{
dludwig@8454
   207
    switch (sdlFormat) {
dludwig@8454
   208
        case SDL_PIXELFORMAT_ARGB8888:
dludwig@8454
   209
            return DXGI_FORMAT_B8G8R8A8_UNORM;
dludwig@8454
   210
        case SDL_PIXELFORMAT_RGB888:
dludwig@8454
   211
            return DXGI_FORMAT_B8G8R8X8_UNORM;
dludwig@8454
   212
        default:
dludwig@8454
   213
            return DXGI_FORMAT_UNKNOWN;
dludwig@8454
   214
    }
dludwig@8454
   215
}
dludwig@8454
   216
dludwig@8454
   217
dludwig@8400
   218
//typedef struct
dludwig@8400
   219
//{
dludwig@8400
   220
//    float x, y, z;
dludwig@8400
   221
//    DWORD color;
dludwig@8400
   222
//    float u, v;
dludwig@8400
   223
//} Vertex;
dludwig@8400
   224
dludwig@8400
   225
SDL_Renderer *
dludwig@8400
   226
D3D11_CreateRenderer(SDL_Window * window, Uint32 flags)
dludwig@8400
   227
{
dludwig@8400
   228
    SDL_Renderer *renderer;
dludwig@8400
   229
    D3D11_RenderData *data;
dludwig@8400
   230
dludwig@8400
   231
    renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
dludwig@8400
   232
    if (!renderer) {
dludwig@8400
   233
        SDL_OutOfMemory();
dludwig@8400
   234
        return NULL;
dludwig@8400
   235
    }
dludwig@8400
   236
    SDL_zerop(renderer);
dludwig@8400
   237
dludwig@8400
   238
    data = new D3D11_RenderData;    // Use the C++ 'new' operator to make sure the struct's members initialize using C++ rules
dludwig@8400
   239
    if (!data) {
dludwig@8400
   240
        SDL_OutOfMemory();
dludwig@8400
   241
        return NULL;
dludwig@8400
   242
    }
dludwig@8410
   243
    data->featureLevel = (D3D_FEATURE_LEVEL) 0;
dludwig@8412
   244
    data->windowSizeInDIPs = XMFLOAT2(0, 0);
dludwig@8412
   245
    data->renderTargetSize = XMFLOAT2(0, 0);
dludwig@8400
   246
dludwig@8415
   247
    renderer->WindowEvent = D3D11_WindowEvent;
dludwig@8416
   248
    renderer->CreateTexture = D3D11_CreateTexture;
dludwig@8416
   249
    renderer->UpdateTexture = D3D11_UpdateTexture;
dludwig@8451
   250
    renderer->LockTexture = D3D11_LockTexture;
dludwig@8451
   251
    renderer->UnlockTexture = D3D11_UnlockTexture;
dludwig@8459
   252
    renderer->SetRenderTarget = D3D11_SetRenderTarget;
dludwig@8400
   253
    renderer->UpdateViewport = D3D11_UpdateViewport;
dludwig@8482
   254
    renderer->UpdateClipRect = D3D11_UpdateClipRect;
dludwig@8416
   255
    renderer->RenderClear = D3D11_RenderClear;
dludwig@8450
   256
    renderer->RenderDrawPoints = D3D11_RenderDrawPoints;
dludwig@8449
   257
    renderer->RenderDrawLines = D3D11_RenderDrawLines;
dludwig@8429
   258
    renderer->RenderFillRects = D3D11_RenderFillRects;
dludwig@8416
   259
    renderer->RenderCopy = D3D11_RenderCopy;
dludwig@8455
   260
    renderer->RenderCopyEx = D3D11_RenderCopyEx;
dludwig@8454
   261
    renderer->RenderReadPixels = D3D11_RenderReadPixels;
dludwig@8401
   262
    renderer->RenderPresent = D3D11_RenderPresent;
dludwig@8416
   263
    renderer->DestroyTexture = D3D11_DestroyTexture;
dludwig@8413
   264
    renderer->DestroyRenderer = D3D11_DestroyRenderer;
dludwig@8400
   265
    renderer->info = D3D11_RenderDriver.info;
dludwig@8400
   266
    renderer->driverdata = data;
dludwig@8400
   267
dludwig@8413
   268
    // HACK: make sure the SDL_Renderer references the SDL_Window data now, in
dludwig@8413
   269
    // order to give init functions access to the underlying window handle:
dludwig@8413
   270
    renderer->window = window;
dludwig@8400
   271
dludwig@8413
   272
    /* Initialize Direct3D resources */
dludwig@8413
   273
    if (FAILED(D3D11_CreateDeviceResources(renderer))) {
dludwig@8413
   274
        D3D11_DestroyRenderer(renderer);
dludwig@8413
   275
        return NULL;
dludwig@8413
   276
    }
dludwig@8413
   277
    if (FAILED(D3D11_CreateWindowSizeDependentResources(renderer))) {
dludwig@8413
   278
        D3D11_DestroyRenderer(renderer);
dludwig@8413
   279
        return NULL;
dludwig@8413
   280
    }
dludwig@8400
   281
dludwig@8416
   282
    // TODO, WinRT: fill in renderer->info.texture_formats where appropriate
dludwig@8416
   283
dludwig@8400
   284
    return renderer;
dludwig@8400
   285
}
dludwig@8400
   286
dludwig@8413
   287
static void
dludwig@8413
   288
D3D11_DestroyRenderer(SDL_Renderer * renderer)
dludwig@8413
   289
{
dludwig@8413
   290
    D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
dludwig@8413
   291
    if (data) {
dludwig@8413
   292
        delete data;
dludwig@8413
   293
        data = NULL;
dludwig@8413
   294
    }
dludwig@8413
   295
}
dludwig@8413
   296
dludwig@8410
   297
static bool
dludwig@8410
   298
D3D11_ReadFileContents(const wstring & fileName, vector<char> & out)
dludwig@8410
   299
{
dludwig@8410
   300
    ifstream in(fileName, ios::in | ios::binary);
dludwig@8410
   301
    if (!in) {
dludwig@8410
   302
        return false;
dludwig@8410
   303
    }
dludwig@8410
   304
dludwig@8410
   305
    in.seekg(0, ios::end);
dludwig@8410
   306
    out.resize((size_t) in.tellg());
dludwig@8410
   307
    in.seekg(0, ios::beg);
dludwig@8410
   308
    in.read(&out[0], out.size());
dludwig@8410
   309
    return in.good();
dludwig@8410
   310
}
dludwig@8410
   311
dludwig@8410
   312
static bool
dludwig@8410
   313
D3D11_ReadShaderContents(const wstring & shaderName, vector<char> & out)
dludwig@8410
   314
{
dludwig@8410
   315
    wstring fileName;
dludwig@8410
   316
dludwig@8410
   317
#if WINAPI_FAMILY == WINAPI_FAMILY_APP
dludwig@8454
   318
    fileName = SDL_WinRTGetFSPathUNICODE(SDL_WINRT_PATH_INSTALLED_LOCATION);
dludwig@8410
   319
    fileName += L"\\SDL_VS2012_WinRT\\";
dludwig@8410
   320
#elif WINAPI_FAMILY == WINAPI_PHONE_APP
dludwig@8454
   321
    fileName = SDL_WinRTGetFSPathUNICODE(SDL_WINRT_PATH_INSTALLED_LOCATION);
dludwig@8410
   322
    fileName += L"\\";
dludwig@8410
   323
#endif
dludwig@8504
   324
    // TODO, WinRT: test Direct3D 11.1 shader loading on Win32
dludwig@8410
   325
    fileName += shaderName;
dludwig@8410
   326
    return D3D11_ReadFileContents(fileName, out);
dludwig@8410
   327
}
dludwig@8410
   328
dludwig@8429
   329
static HRESULT
dludwig@8429
   330
D3D11_LoadPixelShader(SDL_Renderer * renderer,
dludwig@8429
   331
                      const wstring & shaderName,
dludwig@8429
   332
                      ID3D11PixelShader ** shaderOutput)
dludwig@8429
   333
{
dludwig@8429
   334
    D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
dludwig@8429
   335
    HRESULT result = S_OK;
dludwig@8429
   336
    vector<char> fileData;
dludwig@8429
   337
    
dludwig@8429
   338
    if (!D3D11_ReadShaderContents(shaderName, fileData)) {
dludwig@8429
   339
        SDL_SetError("Unable to open SDL's pixel shader file.");
dludwig@8429
   340
        return E_FAIL;
dludwig@8429
   341
    }
dludwig@8429
   342
dludwig@8429
   343
    result = data->d3dDevice->CreatePixelShader(
dludwig@8429
   344
        &fileData[0],
dludwig@8429
   345
        fileData.size(),
dludwig@8429
   346
        nullptr,
dludwig@8429
   347
        shaderOutput
dludwig@8429
   348
        );
dludwig@8429
   349
    if (FAILED(result)) {
dludwig@8553
   350
        WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreatePixelShader", result);
dludwig@8429
   351
        return result;
dludwig@8429
   352
    }
dludwig@8429
   353
dludwig@8429
   354
    return S_OK;
dludwig@8429
   355
}
dludwig@8429
   356
dludwig@8431
   357
static HRESULT
dludwig@8431
   358
D3D11_CreateBlendMode(SDL_Renderer * renderer,
dludwig@8431
   359
                      BOOL enableBlending,
dludwig@8431
   360
                      D3D11_BLEND srcBlend,
dludwig@8431
   361
                      D3D11_BLEND destBlend,
dludwig@8431
   362
                      ID3D11BlendState ** blendStateOutput)
dludwig@8431
   363
{
dludwig@8431
   364
    D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
dludwig@8431
   365
    HRESULT result = S_OK;
dludwig@8431
   366
dludwig@8431
   367
    D3D11_BLEND_DESC blendDesc;
dludwig@8431
   368
    memset(&blendDesc, 0, sizeof(blendDesc));
dludwig@8431
   369
    blendDesc.AlphaToCoverageEnable = FALSE;
dludwig@8431
   370
    blendDesc.IndependentBlendEnable = FALSE;
dludwig@8431
   371
    blendDesc.RenderTarget[0].BlendEnable = enableBlending;
dludwig@8431
   372
    blendDesc.RenderTarget[0].SrcBlend = srcBlend;
dludwig@8431
   373
    blendDesc.RenderTarget[0].DestBlend = destBlend;
dludwig@8431
   374
    blendDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
dludwig@8431
   375
    blendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
dludwig@8431
   376
    blendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
dludwig@8431
   377
    blendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
dludwig@8431
   378
    blendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
dludwig@8431
   379
    result = data->d3dDevice->CreateBlendState(&blendDesc, blendStateOutput);
dludwig@8431
   380
    if (FAILED(result)) {
dludwig@8553
   381
        WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateBlendState", result);
dludwig@8431
   382
        return result;
dludwig@8431
   383
    }
dludwig@8431
   384
dludwig@8431
   385
    return S_OK;
dludwig@8431
   386
}
dludwig@8431
   387
dludwig@8414
   388
// Create resources that depend on the device.
dludwig@8410
   389
HRESULT
dludwig@8412
   390
D3D11_CreateDeviceResources(SDL_Renderer * renderer)
dludwig@8410
   391
{
dludwig@8410
   392
    D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
dludwig@8410
   393
dludwig@8410
   394
    // This flag adds support for surfaces with a different color channel ordering
dludwig@8410
   395
    // than the API default. It is required for compatibility with Direct2D.
dludwig@8410
   396
    UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
dludwig@8410
   397
dludwig@8533
   398
    // Make sure Direct3D's debugging feature gets used, if the app requests it.
dludwig@8533
   399
    const char *hint = SDL_GetHint(SDL_HINT_RENDER_DIRECT3D11_DEBUG);
dludwig@8533
   400
    if (hint) {
dludwig@8533
   401
        if (*hint == '1') {
dludwig@8533
   402
            creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
dludwig@8533
   403
        }
dludwig@8533
   404
    }
dludwig@8410
   405
dludwig@8410
   406
    // This array defines the set of DirectX hardware feature levels this app will support.
dludwig@8410
   407
    // Note the ordering should be preserved.
dludwig@8410
   408
    // Don't forget to declare your application's minimum required feature level in its
dludwig@8410
   409
    // description.  All applications are assumed to support 9.1 unless otherwise stated.
dludwig@8410
   410
    D3D_FEATURE_LEVEL featureLevels[] = 
dludwig@8410
   411
    {
dludwig@8410
   412
        D3D_FEATURE_LEVEL_11_1,
dludwig@8410
   413
        D3D_FEATURE_LEVEL_11_0,
dludwig@8410
   414
        D3D_FEATURE_LEVEL_10_1,
dludwig@8410
   415
        D3D_FEATURE_LEVEL_10_0,
dludwig@8410
   416
        D3D_FEATURE_LEVEL_9_3,
dludwig@8410
   417
        D3D_FEATURE_LEVEL_9_2,
dludwig@8410
   418
        D3D_FEATURE_LEVEL_9_1
dludwig@8410
   419
    };
dludwig@8410
   420
dludwig@8410
   421
    // Create the Direct3D 11 API device object and a corresponding context.
dludwig@8410
   422
    ComPtr<ID3D11Device> device;
dludwig@8410
   423
    ComPtr<ID3D11DeviceContext> context;
dludwig@8410
   424
    HRESULT result = S_OK;
dludwig@8410
   425
    result = D3D11CreateDevice(
dludwig@8410
   426
        nullptr, // Specify nullptr to use the default adapter.
dludwig@8410
   427
        D3D_DRIVER_TYPE_HARDWARE,
dludwig@8410
   428
        nullptr,
dludwig@8410
   429
        creationFlags, // Set set debug and Direct2D compatibility flags.
dludwig@8410
   430
        featureLevels, // List of feature levels this app can support.
dludwig@8410
   431
        ARRAYSIZE(featureLevels),
dludwig@8410
   432
        D3D11_SDK_VERSION, // Always set this to D3D11_SDK_VERSION for Windows Store apps.
dludwig@8410
   433
        &device, // Returns the Direct3D device created.
dludwig@8410
   434
        &data->featureLevel, // Returns feature level of device created.
dludwig@8410
   435
        &context // Returns the device immediate context.
dludwig@8410
   436
        );
dludwig@8410
   437
    if (FAILED(result)) {
dludwig@8553
   438
        WIN_SetErrorFromHRESULT(__FUNCTION__ ", D3D11CreateDevice", result);
dludwig@8410
   439
        return result;
dludwig@8410
   440
    }
dludwig@8410
   441
dludwig@8410
   442
    // Get the Direct3D 11.1 API device and context interfaces.
dludwig@8410
   443
    result = device.As(&(data->d3dDevice));
dludwig@8410
   444
    if (FAILED(result)) {
dludwig@8553
   445
        WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device to ID3D11Device1", result);
dludwig@8410
   446
        return result;
dludwig@8410
   447
    }
dludwig@8410
   448
dludwig@8410
   449
    result = context.As(&data->d3dContext);
dludwig@8410
   450
    if (FAILED(result)) {
dludwig@8553
   451
        WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11DeviceContext to ID3D11DeviceContext1", result);
dludwig@8410
   452
        return result;
dludwig@8410
   453
    }
dludwig@8410
   454
dludwig@8410
   455
    //
dludwig@8446
   456
    // Make note of the maximum texture size
dludwig@8446
   457
    // Max texture sizes are documented on MSDN, at:
dludwig@8446
   458
    // http://msdn.microsoft.com/en-us/library/windows/apps/ff476876.aspx
dludwig@8446
   459
    //
dludwig@8446
   460
    switch (data->d3dDevice->GetFeatureLevel()) {
dludwig@8446
   461
        case D3D_FEATURE_LEVEL_11_1:
dludwig@8446
   462
        case D3D_FEATURE_LEVEL_11_0:
dludwig@8446
   463
            renderer->info.max_texture_width = renderer->info.max_texture_height = 16384;
dludwig@8446
   464
            break;
dludwig@8446
   465
dludwig@8446
   466
        case D3D_FEATURE_LEVEL_10_1:
dludwig@8446
   467
        case D3D_FEATURE_LEVEL_10_0:
dludwig@8446
   468
            renderer->info.max_texture_width = renderer->info.max_texture_height = 8192;
dludwig@8446
   469
            break;
dludwig@8446
   470
dludwig@8446
   471
        case D3D_FEATURE_LEVEL_9_3:
dludwig@8446
   472
            renderer->info.max_texture_width = renderer->info.max_texture_height = 4096;
dludwig@8446
   473
            break;
dludwig@8446
   474
dludwig@8446
   475
        case D3D_FEATURE_LEVEL_9_2:
dludwig@8446
   476
        case D3D_FEATURE_LEVEL_9_1:
dludwig@8446
   477
            renderer->info.max_texture_width = renderer->info.max_texture_height = 2048;
dludwig@8446
   478
            break;
dludwig@8446
   479
    }
dludwig@8446
   480
dludwig@8446
   481
    //
dludwig@8410
   482
    // Load in SDL's one and only vertex shader:
dludwig@8410
   483
    //
dludwig@8429
   484
    vector<char> fileData;
dludwig@8444
   485
    if (!D3D11_ReadShaderContents(L"SDL_D3D11_VertexShader_Default.cso", fileData)) {
dludwig@8410
   486
        SDL_SetError("Unable to open SDL's vertex shader file.");
dludwig@8410
   487
        return E_FAIL;
dludwig@8410
   488
    }
dludwig@8410
   489
dludwig@8410
   490
    result = data->d3dDevice->CreateVertexShader(
dludwig@8410
   491
        &fileData[0],
dludwig@8410
   492
        fileData.size(),
dludwig@8410
   493
        nullptr,
dludwig@8410
   494
        &data->vertexShader
dludwig@8410
   495
        );
dludwig@8410
   496
    if (FAILED(result)) {
dludwig@8553
   497
        WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateVertexShader", result);
dludwig@8410
   498
        return result;
dludwig@8410
   499
    }
dludwig@8410
   500
dludwig@8410
   501
    //
dludwig@8410
   502
    // Create an input layout for SDL's vertex shader:
dludwig@8410
   503
    //
dludwig@8410
   504
    const D3D11_INPUT_ELEMENT_DESC vertexDesc[] = 
dludwig@8410
   505
    {
dludwig@8429
   506
        { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
dludwig@8410
   507
        { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
dludwig@8429
   508
        { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 20, D3D11_INPUT_PER_VERTEX_DATA, 0 },
dludwig@8410
   509
    };
dludwig@8410
   510
dludwig@8410
   511
    result = data->d3dDevice->CreateInputLayout(
dludwig@8410
   512
        vertexDesc,
dludwig@8410
   513
        ARRAYSIZE(vertexDesc),
dludwig@8410
   514
        &fileData[0],
dludwig@8410
   515
        fileData.size(),
dludwig@8410
   516
        &data->inputLayout
dludwig@8410
   517
        );
dludwig@8410
   518
    if (FAILED(result)) {
dludwig@8553
   519
        WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateInputLayout", result);
dludwig@8410
   520
        return result;
dludwig@8410
   521
    }
dludwig@8410
   522
dludwig@8410
   523
    //
dludwig@8429
   524
    // Load in SDL's pixel shaders
dludwig@8410
   525
    //
dludwig@8458
   526
    result = D3D11_LoadPixelShader(renderer, L"SDL_D3D11_PixelShader_TextureColored.cso", &data->texturePixelShader);
dludwig@8429
   527
    if (FAILED(result)) {
dludwig@8429
   528
        // D3D11_LoadPixelShader will have aleady set the SDL error
dludwig@8429
   529
        return result;
dludwig@8410
   530
    }
dludwig@8410
   531
dludwig@8429
   532
    result = D3D11_LoadPixelShader(renderer, L"SDL_D3D11_PixelShader_FixedColor.cso", &data->colorPixelShader);
dludwig@8410
   533
    if (FAILED(result)) {
dludwig@8429
   534
        // D3D11_LoadPixelShader will have aleady set the SDL error
dludwig@8410
   535
        return result;
dludwig@8410
   536
    }
dludwig@8410
   537
dludwig@8410
   538
    //
dludwig@8418
   539
    // Setup space to hold vertex shader constants:
dludwig@8418
   540
    //
dludwig@8560
   541
    CD3D11_BUFFER_DESC constantBufferDesc(sizeof(VertexShaderConstants), D3D11_BIND_CONSTANT_BUFFER);
dludwig@8418
   542
    result = data->d3dDevice->CreateBuffer(
dludwig@8418
   543
		&constantBufferDesc,
dludwig@8418
   544
		nullptr,
dludwig@8418
   545
        &data->vertexShaderConstants
dludwig@8418
   546
		);
dludwig@8418
   547
    if (FAILED(result)) {
dludwig@8553
   548
        WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateBuffer [vertex shader constants]", result);
dludwig@8418
   549
        return result;
dludwig@8418
   550
    }
dludwig@8418
   551
dludwig@8418
   552
    //
dludwig@8425
   553
    // Make sure that the vertex buffer, if already created, gets freed.
dludwig@8425
   554
    // It will be recreated later.
dludwig@8410
   555
    //
dludwig@8425
   556
    data->vertexBuffer = nullptr;
dludwig@8410
   557
dludwig@8410
   558
    //
dludwig@8540
   559
    // Create samplers to use when drawing textures:
dludwig@8410
   560
    //
dludwig@8410
   561
    D3D11_SAMPLER_DESC samplerDesc;
dludwig@8540
   562
    samplerDesc.Filter = SDL_D3D11_NEAREST_PIXEL_FILTER;
dludwig@8410
   563
    samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
dludwig@8410
   564
    samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
dludwig@8410
   565
    samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
dludwig@8410
   566
    samplerDesc.MipLODBias = 0.0f;
dludwig@8410
   567
    samplerDesc.MaxAnisotropy = 1;
dludwig@8410
   568
    samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
dludwig@8410
   569
    samplerDesc.BorderColor[0] = 0.0f;
dludwig@8410
   570
    samplerDesc.BorderColor[1] = 0.0f;
dludwig@8410
   571
    samplerDesc.BorderColor[2] = 0.0f;
dludwig@8410
   572
    samplerDesc.BorderColor[3] = 0.0f;
dludwig@8410
   573
    samplerDesc.MinLOD = 0.0f;
dludwig@8410
   574
    samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
dludwig@8410
   575
    result = data->d3dDevice->CreateSamplerState(
dludwig@8410
   576
        &samplerDesc,
dludwig@8540
   577
        &data->nearestPixelSampler
dludwig@8540
   578
        );
dludwig@8540
   579
    if (FAILED(result)) {
dludwig@8553
   580
        WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateSamplerState [nearest-pixel filter]", result);
dludwig@8540
   581
        return result;
dludwig@8540
   582
    }
dludwig@8540
   583
dludwig@8540
   584
    samplerDesc.Filter = SDL_D3D11_LINEAR_FILTER;
dludwig@8540
   585
    result = data->d3dDevice->CreateSamplerState(
dludwig@8540
   586
        &samplerDesc,
dludwig@8540
   587
        &data->linearSampler
dludwig@8410
   588
        );
dludwig@8410
   589
    if (FAILED(result)) {
dludwig@8553
   590
        WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateSamplerState [linear filter]", result);
dludwig@8410
   591
        return result;
dludwig@8410
   592
    }
dludwig@8410
   593
dludwig@8410
   594
    //
dludwig@8426
   595
    // Setup the Direct3D rasterizer
dludwig@8426
   596
    //
dludwig@8426
   597
    D3D11_RASTERIZER_DESC rasterDesc;
dludwig@8426
   598
    memset(&rasterDesc, 0, sizeof(rasterDesc));
dludwig@8426
   599
	rasterDesc.AntialiasedLineEnable = false;
dludwig@8426
   600
	rasterDesc.CullMode = D3D11_CULL_NONE;
dludwig@8426
   601
	rasterDesc.DepthBias = 0;
dludwig@8426
   602
	rasterDesc.DepthBiasClamp = 0.0f;
dludwig@8426
   603
	rasterDesc.DepthClipEnable = true;
dludwig@8426
   604
	rasterDesc.FillMode = D3D11_FILL_SOLID;
dludwig@8426
   605
	rasterDesc.FrontCounterClockwise = false;
dludwig@8426
   606
	rasterDesc.MultisampleEnable = false;
dludwig@8426
   607
	rasterDesc.ScissorEnable = false;
dludwig@8426
   608
	rasterDesc.SlopeScaledDepthBias = 0.0f;
dludwig@8426
   609
	result = data->d3dDevice->CreateRasterizerState(&rasterDesc, &data->mainRasterizer);
dludwig@8426
   610
	if (FAILED(result)) {
dludwig@8553
   611
        WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateRasterizerState", result);
dludwig@8426
   612
        return result;
dludwig@8426
   613
    }
dludwig@8426
   614
dludwig@8426
   615
    //
dludwig@8431
   616
    // Create blending states:
dludwig@8431
   617
    //
dludwig@8431
   618
    result = D3D11_CreateBlendMode(
dludwig@8431
   619
        renderer,
dludwig@8431
   620
        TRUE,
dludwig@8431
   621
        D3D11_BLEND_SRC_ALPHA,
dludwig@8431
   622
        D3D11_BLEND_INV_SRC_ALPHA,
dludwig@8431
   623
        &data->blendModeBlend);
dludwig@8431
   624
    if (FAILED(result)) {
dludwig@8431
   625
        // D3D11_CreateBlendMode will set the SDL error, if it fails
dludwig@8431
   626
        return result;
dludwig@8431
   627
    }
dludwig@8431
   628
dludwig@8431
   629
    result = D3D11_CreateBlendMode(
dludwig@8431
   630
        renderer,
dludwig@8431
   631
        TRUE,
dludwig@8431
   632
        D3D11_BLEND_SRC_ALPHA,
dludwig@8431
   633
        D3D11_BLEND_ONE,
dludwig@8431
   634
        &data->blendModeAdd);
dludwig@8431
   635
    if (FAILED(result)) {
dludwig@8431
   636
        // D3D11_CreateBlendMode will set the SDL error, if it fails
dludwig@8431
   637
        return result;
dludwig@8431
   638
    }
dludwig@8431
   639
dludwig@8431
   640
    result = D3D11_CreateBlendMode(
dludwig@8431
   641
        renderer,
dludwig@8431
   642
        TRUE,
dludwig@8431
   643
        D3D11_BLEND_ZERO,
dludwig@8431
   644
        D3D11_BLEND_SRC_COLOR,
dludwig@8431
   645
        &data->blendModeMod);
dludwig@8431
   646
    if (FAILED(result)) {
dludwig@8431
   647
        // D3D11_CreateBlendMode will set the SDL error, if it fails
dludwig@8431
   648
        return result;
dludwig@8431
   649
    }
dludwig@8431
   650
dludwig@8431
   651
    //
dludwig@8410
   652
    // All done!
dludwig@8410
   653
    //
dludwig@8410
   654
    return S_OK;
dludwig@8410
   655
}
dludwig@8410
   656
dludwig@8412
   657
#ifdef __WINRT__
dludwig@8412
   658
dludwig@8463
   659
static ABI::Windows::UI::Core::ICoreWindow *
dludwig@8412
   660
D3D11_GetCoreWindowFromSDLRenderer(SDL_Renderer * renderer)
dludwig@8412
   661
{
dludwig@8412
   662
    SDL_Window * sdlWindow = renderer->window;
dludwig@8412
   663
    if ( ! renderer->window ) {
dludwig@8412
   664
        return nullptr;
dludwig@8412
   665
    }
dludwig@8412
   666
dludwig@8412
   667
    SDL_SysWMinfo sdlWindowInfo;
dludwig@8412
   668
    SDL_VERSION(&sdlWindowInfo.version);
dludwig@8412
   669
    if ( ! SDL_GetWindowWMInfo(sdlWindow, &sdlWindowInfo) ) {
dludwig@8412
   670
        return nullptr;
dludwig@8412
   671
    }
dludwig@8412
   672
dludwig@8496
   673
    if (sdlWindowInfo.subsystem != SDL_SYSWM_WINRT) {
dludwig@8412
   674
        return nullptr;
dludwig@8412
   675
    }
dludwig@8412
   676
dludwig@8463
   677
    if ( ! sdlWindowInfo.info.winrt.window ) {
dludwig@8412
   678
        return nullptr;
dludwig@8412
   679
    }
dludwig@8412
   680
dludwig@8463
   681
    ABI::Windows::UI::Core::ICoreWindow * coreWindow = nullptr;
dludwig@8463
   682
    if (FAILED(sdlWindowInfo.info.winrt.window->QueryInterface(&coreWindow))) {
dludwig@8463
   683
        return nullptr;
dludwig@8463
   684
    }
dludwig@8463
   685
dludwig@8463
   686
    return coreWindow;
dludwig@8412
   687
}
dludwig@8412
   688
dludwig@8414
   689
// Method to convert a length in device-independent pixels (DIPs) to a length in physical pixels.
dludwig@8412
   690
static float
dludwig@8412
   691
D3D11_ConvertDipsToPixels(float dips)
dludwig@8412
   692
{
dludwig@8412
   693
    static const float dipsPerInch = 96.0f;
dludwig@8412
   694
    return floor(dips * DisplayProperties::LogicalDpi / dipsPerInch + 0.5f); // Round to nearest integer.
dludwig@8412
   695
}
dludwig@8412
   696
#endif
dludwig@8412
   697
dludwig@8505
   698
#if WINAPI_FAMILY == WINAPI_FAMILY_APP
dludwig@8505
   699
// TODO, WinRT, XAML: get the ISwapChainBackgroundPanelNative from something other than a global var
dludwig@8505
   700
extern ISwapChainBackgroundPanelNative * WINRT_GlobalSwapChainBackgroundPanelNative;
dludwig@8505
   701
#endif
dludwig@8505
   702
dludwig@8548
   703
static DXGI_MODE_ROTATION
dludwig@8548
   704
D3D11_GetRotationForOrientation(Windows::Graphics::Display::DisplayOrientations orientation)
dludwig@8548
   705
{
dludwig@8548
   706
    switch (orientation)
dludwig@8548
   707
    {
dludwig@8548
   708
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
dludwig@8548
   709
        //
dludwig@8548
   710
        // Windows Phone rotations
dludwig@8548
   711
        //
dludwig@8548
   712
        case DisplayOrientations::Landscape:
dludwig@8548
   713
            return DXGI_MODE_ROTATION_ROTATE90;
dludwig@8548
   714
        case DisplayOrientations::Portrait:
dludwig@8548
   715
            return DXGI_MODE_ROTATION_IDENTITY;
dludwig@8548
   716
        case DisplayOrientations::LandscapeFlipped:
dludwig@8548
   717
            return DXGI_MODE_ROTATION_ROTATE270;
dludwig@8548
   718
        case DisplayOrientations::PortraitFlipped:
dludwig@8548
   719
            return DXGI_MODE_ROTATION_ROTATE180;
dludwig@8548
   720
#else
dludwig@8548
   721
        //
dludwig@8548
   722
        // Non-Windows-Phone rotations (ex: Windows 8, Windows RT)
dludwig@8548
   723
        //
dludwig@8548
   724
        case DisplayOrientations::Landscape:
dludwig@8548
   725
            return DXGI_MODE_ROTATION_IDENTITY;
dludwig@8548
   726
        case DisplayOrientations::Portrait:
dludwig@8548
   727
            return DXGI_MODE_ROTATION_ROTATE270;
dludwig@8548
   728
        case DisplayOrientations::LandscapeFlipped:
dludwig@8548
   729
            return DXGI_MODE_ROTATION_ROTATE180;
dludwig@8548
   730
        case DisplayOrientations::PortraitFlipped:
dludwig@8548
   731
            return DXGI_MODE_ROTATION_ROTATE90;
dludwig@8548
   732
#endif // WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
dludwig@8548
   733
dludwig@8548
   734
        default:
dludwig@8548
   735
            return DXGI_MODE_ROTATION_UNSPECIFIED;
dludwig@8548
   736
    }
dludwig@8548
   737
}
dludwig@8505
   738
dludwig@8414
   739
// Initialize all resources that change when the window's size changes.
dludwig@8504
   740
// TODO, WinRT: get D3D11_CreateWindowSizeDependentResources working on Win32
dludwig@8412
   741
HRESULT
dludwig@8412
   742
D3D11_CreateWindowSizeDependentResources(SDL_Renderer * renderer)
dludwig@8412
   743
{
dludwig@8412
   744
    D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
dludwig@8412
   745
    HRESULT result = S_OK;
dludwig@8463
   746
    ABI::Windows::UI::Core::ICoreWindow * coreWindow = D3D11_GetCoreWindowFromSDLRenderer(renderer);
dludwig@8412
   747
dludwig@8412
   748
    // Store the window bounds so the next time we get a SizeChanged event we can
dludwig@8412
   749
    // avoid rebuilding everything if the size is identical.
dludwig@8505
   750
    ABI::Windows::Foundation::Rect nativeWindowBounds;
dludwig@8505
   751
    if (coreWindow) {
dludwig@8505
   752
        result = coreWindow->get_Bounds(&nativeWindowBounds);
dludwig@8505
   753
        if (FAILED(result)) {
dludwig@8553
   754
            WIN_SetErrorFromHRESULT(__FUNCTION__", ICoreWindow::get_Bounds [get native-window bounds]", result);
dludwig@8505
   755
            return result;
dludwig@8505
   756
        }
dludwig@8505
   757
    } else {
dludwig@8505
   758
        // TODO, WinRT, XAML: clean up window-bounds code in D3D11_CreateWindowSizeDependentResources
dludwig@8505
   759
        SDL_DisplayMode displayMode;
dludwig@8505
   760
        if (SDL_GetDesktopDisplayMode(0, &displayMode) < 0) {
dludwig@8505
   761
            SDL_SetError(__FUNCTION__", Get Window Bounds (XAML): Unable to retrieve the native window's size");
dludwig@8505
   762
            return E_FAIL;
dludwig@8505
   763
        }
dludwig@8505
   764
dludwig@8505
   765
        nativeWindowBounds.Width = (FLOAT) displayMode.w;
dludwig@8505
   766
        nativeWindowBounds.Height = (FLOAT) displayMode.h;
dludwig@8463
   767
    }
dludwig@8463
   768
dludwig@8505
   769
    // TODO, WinRT, XAML: see if window/control sizes are in DIPs, or something else.  If something else, then adjust renderer size tracking accordingly.
dludwig@8505
   770
    data->windowSizeInDIPs.x = nativeWindowBounds.Width;
dludwig@8505
   771
    data->windowSizeInDIPs.y = nativeWindowBounds.Height;
dludwig@8412
   772
dludwig@8412
   773
    // Calculate the necessary swap chain and render target size in pixels.
dludwig@8412
   774
    float windowWidth = D3D11_ConvertDipsToPixels(data->windowSizeInDIPs.x);
dludwig@8412
   775
    float windowHeight = D3D11_ConvertDipsToPixels(data->windowSizeInDIPs.y);
dludwig@8412
   776
dludwig@8412
   777
    // The width and height of the swap chain must be based on the window's
dludwig@8412
   778
    // landscape-oriented width and height. If the window is in a portrait
dludwig@8412
   779
    // orientation, the dimensions must be reversed.
dludwig@8412
   780
    data->orientation = DisplayProperties::CurrentOrientation;
dludwig@8508
   781
dludwig@8508
   782
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
dludwig@8508
   783
    const bool swapDimensions = false;
dludwig@8508
   784
#else
dludwig@8433
   785
    const bool swapDimensions =
dludwig@8412
   786
        data->orientation == DisplayOrientations::Portrait ||
dludwig@8412
   787
        data->orientation == DisplayOrientations::PortraitFlipped;
dludwig@8508
   788
#endif
dludwig@8412
   789
    data->renderTargetSize.x = swapDimensions ? windowHeight : windowWidth;
dludwig@8412
   790
    data->renderTargetSize.y = swapDimensions ? windowWidth : windowHeight;
dludwig@8412
   791
dludwig@8412
   792
    if(data->swapChain != nullptr)
dludwig@8412
   793
    {
dludwig@8412
   794
        // If the swap chain already exists, resize it.
dludwig@8412
   795
        result = data->swapChain->ResizeBuffers(
dludwig@8412
   796
            2, // Double-buffered swap chain.
dludwig@8412
   797
            static_cast<UINT>(data->renderTargetSize.x),
dludwig@8412
   798
            static_cast<UINT>(data->renderTargetSize.y),
dludwig@8412
   799
            DXGI_FORMAT_B8G8R8A8_UNORM,
dludwig@8412
   800
            0
dludwig@8412
   801
            );
dludwig@8412
   802
        if (FAILED(result)) {
dludwig@8553
   803
            WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGISwapChain1::ResizeBuffers", result);
dludwig@8412
   804
            return result;
dludwig@8412
   805
        }
dludwig@8412
   806
    }
dludwig@8412
   807
    else
dludwig@8412
   808
    {
dludwig@8505
   809
        const bool usingXAML = (coreWindow == nullptr);
dludwig@8505
   810
dludwig@8412
   811
        // Otherwise, create a new one using the same adapter as the existing Direct3D device.
dludwig@8412
   812
        DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
dludwig@8412
   813
        swapChainDesc.Width = static_cast<UINT>(data->renderTargetSize.x); // Match the size of the window.
dludwig@8412
   814
        swapChainDesc.Height = static_cast<UINT>(data->renderTargetSize.y);
dludwig@8412
   815
        swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // This is the most common swap chain format.
dludwig@8412
   816
        swapChainDesc.Stereo = false;
dludwig@8412
   817
        swapChainDesc.SampleDesc.Count = 1; // Don't use multi-sampling.
dludwig@8412
   818
        swapChainDesc.SampleDesc.Quality = 0;
dludwig@8412
   819
        swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
dludwig@8412
   820
        swapChainDesc.BufferCount = 2; // Use double-buffering to minimize latency.
dludwig@8412
   821
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
dludwig@8412
   822
        swapChainDesc.Scaling = DXGI_SCALING_STRETCH; // On phone, only stretch and aspect-ratio stretch scaling are allowed.
dludwig@8412
   823
        swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; // On phone, no swap effects are supported.
dludwig@8412
   824
#else
dludwig@8505
   825
        if (usingXAML) {
dludwig@8505
   826
            swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
dludwig@8505
   827
        } else {
dludwig@8505
   828
            swapChainDesc.Scaling = DXGI_SCALING_NONE;
dludwig@8505
   829
        }
dludwig@8412
   830
        swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // All Windows Store apps must use this SwapEffect.
dludwig@8412
   831
#endif
dludwig@8412
   832
        swapChainDesc.Flags = 0;
dludwig@8412
   833
dludwig@8555
   834
        ComPtr<IDXGIDevice1> dxgiDevice;
dludwig@8412
   835
        result = data->d3dDevice.As(&dxgiDevice);
dludwig@8412
   836
        if (FAILED(result)) {
dludwig@8553
   837
            WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1 to IDXGIDevice1", result);
dludwig@8412
   838
            return result;
dludwig@8412
   839
        }
dludwig@8412
   840
dludwig@8412
   841
        ComPtr<IDXGIAdapter> dxgiAdapter;
dludwig@8412
   842
        result = dxgiDevice->GetAdapter(&dxgiAdapter);
dludwig@8412
   843
        if (FAILED(result)) {
dludwig@8553
   844
            WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIDevice1::GetAdapter", result);
dludwig@8412
   845
            return result;
dludwig@8412
   846
        }
dludwig@8412
   847
dludwig@8412
   848
        ComPtr<IDXGIFactory2> dxgiFactory;
dludwig@8412
   849
        result = dxgiAdapter->GetParent(
dludwig@8412
   850
            __uuidof(IDXGIFactory2), 
dludwig@8412
   851
            &dxgiFactory
dludwig@8412
   852
            );
dludwig@8412
   853
        if (FAILED(result)) {
dludwig@8553
   854
            WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIAdapter::GetParent", result);
dludwig@8412
   855
            return result;
dludwig@8412
   856
        }
dludwig@8412
   857
dludwig@8505
   858
        if (usingXAML) {
dludwig@8505
   859
            result = dxgiFactory->CreateSwapChainForComposition(
dludwig@8505
   860
                data->d3dDevice.Get(),
dludwig@8505
   861
                &swapChainDesc,
dludwig@8505
   862
                nullptr,
dludwig@8505
   863
                &data->swapChain);
dludwig@8505
   864
            if (FAILED(result)) {
dludwig@8553
   865
                WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIFactory2::CreateSwapChainForComposition", result);
dludwig@8505
   866
                return result;
dludwig@8505
   867
            }
dludwig@8505
   868
dludwig@8505
   869
#if WINAPI_FAMILY == WINAPI_FAMILY_APP
dludwig@8505
   870
            result = WINRT_GlobalSwapChainBackgroundPanelNative->SetSwapChain(data->swapChain.Get());
dludwig@8505
   871
            if (FAILED(result)) {
dludwig@8505
   872
                WIN_SetErrorFromHRESULT(__FUNCTION__ ", ISwapChainBackgroundPanelNative::SetSwapChain", result);
dludwig@8505
   873
                return result;
dludwig@8505
   874
            }
dludwig@8505
   875
#else
dludwig@8505
   876
            SDL_SetError(__FUNCTION__ ", XAML support is not yet available for Windows Phone");
dludwig@8505
   877
            return E_FAIL;
dludwig@8505
   878
#endif
dludwig@8505
   879
        } else {
dludwig@8505
   880
            IUnknown * coreWindowAsIUnknown = nullptr;
dludwig@8505
   881
            result = coreWindow->QueryInterface(&coreWindowAsIUnknown);
dludwig@8505
   882
            if (FAILED(result)) {
dludwig@8553
   883
                WIN_SetErrorFromHRESULT(__FUNCTION__ ", ICoreWindow to IUnknown", result);
dludwig@8505
   884
                return result;
dludwig@8505
   885
            }
dludwig@8505
   886
dludwig@8505
   887
            result = dxgiFactory->CreateSwapChainForCoreWindow(
dludwig@8505
   888
                data->d3dDevice.Get(),
dludwig@8505
   889
                coreWindowAsIUnknown,
dludwig@8505
   890
                &swapChainDesc,
dludwig@8505
   891
                nullptr, // Allow on all displays.
dludwig@8505
   892
                &data->swapChain
dludwig@8505
   893
                );
dludwig@8505
   894
            if (FAILED(result)) {
dludwig@8553
   895
                WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIFactory2::CreateSwapChainForCoreWindow", result);
dludwig@8505
   896
                return result;
dludwig@8505
   897
            }
dludwig@8463
   898
        }
dludwig@8505
   899
        
dludwig@8412
   900
        // Ensure that DXGI does not queue more than one frame at a time. This both reduces latency and
dludwig@8412
   901
        // ensures that the application will only render after each VSync, minimizing power consumption.
dludwig@8412
   902
        result = dxgiDevice->SetMaximumFrameLatency(1);
dludwig@8412
   903
        if (FAILED(result)) {
dludwig@8553
   904
            WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIDevice1::SetMaximumFrameLatency", result);
dludwig@8412
   905
            return result;
dludwig@8412
   906
        }
dludwig@8412
   907
    }
dludwig@8412
   908
    
dludwig@8508
   909
#if WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
dludwig@8412
   910
    // Set the proper orientation for the swap chain, and generate the
dludwig@8412
   911
    // 3D matrix transformation for rendering to the rotated swap chain.
dludwig@8509
   912
    //
dludwig@8548
   913
    // To note, the call for this, IDXGISwapChain1::SetRotation, is not necessary
dludwig@8548
   914
    // on Windows Phone, nor is it supported there.  It's only needed in Windows 8/RT.
dludwig@8548
   915
    DXGI_MODE_ROTATION rotation = D3D11_GetRotationForOrientation(data->orientation);
dludwig@8412
   916
    result = data->swapChain->SetRotation(rotation);
dludwig@8412
   917
    if (FAILED(result)) {
dludwig@8553
   918
        WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGISwapChain1::SetRotation" , result);
dludwig@8412
   919
        return result;
dludwig@8412
   920
    }
dludwig@8412
   921
#endif
dludwig@8412
   922
dludwig@8412
   923
    // Create a render target view of the swap chain back buffer.
dludwig@8412
   924
    ComPtr<ID3D11Texture2D> backBuffer;
dludwig@8412
   925
    result = data->swapChain->GetBuffer(
dludwig@8412
   926
        0,
dludwig@8412
   927
        __uuidof(ID3D11Texture2D),
dludwig@8412
   928
        &backBuffer
dludwig@8412
   929
        );
dludwig@8412
   930
    if (FAILED(result)) {
dludwig@8553
   931
        WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGISwapChain1::GetBuffer [back-buffer]", result);
dludwig@8412
   932
        return result;
dludwig@8412
   933
    }
dludwig@8412
   934
dludwig@8412
   935
    result = data->d3dDevice->CreateRenderTargetView(
dludwig@8412
   936
        backBuffer.Get(),
dludwig@8412
   937
        nullptr,
dludwig@8459
   938
        &data->mainRenderTargetView
dludwig@8412
   939
        );
dludwig@8412
   940
    if (FAILED(result)) {
dludwig@8553
   941
        WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateRenderTargetView", result);
dludwig@8412
   942
        return result;
dludwig@8412
   943
    }
dludwig@8412
   944
dludwig@8432
   945
    if (D3D11_UpdateViewport(renderer) != 0) {
dludwig@8432
   946
        // D3D11_UpdateViewport will set the SDL error if it fails.
dludwig@8432
   947
        return E_FAIL;
dludwig@8432
   948
    }
dludwig@8412
   949
dludwig@8412
   950
    return S_OK;
dludwig@8412
   951
}
dludwig@8412
   952
dludwig@8415
   953
// This method is called when the window's size changes.
dludwig@8414
   954
HRESULT
dludwig@8414
   955
D3D11_UpdateForWindowSizeChange(SDL_Renderer * renderer)
dludwig@8414
   956
{
dludwig@8414
   957
    D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
dludwig@8414
   958
    HRESULT result = S_OK;
dludwig@8463
   959
    ABI::Windows::UI::Core::ICoreWindow * coreWindow = D3D11_GetCoreWindowFromSDLRenderer(renderer);
dludwig@8463
   960
    ABI::Windows::Foundation::Rect coreWindowBounds;
dludwig@8414
   961
dludwig@8463
   962
    result = coreWindow->get_Bounds(&coreWindowBounds);
dludwig@8463
   963
    if (FAILED(result)) {
dludwig@8553
   964
        WIN_SetErrorFromHRESULT(__FUNCTION__ ", ICoreWindow::get_Bounds [get window bounds]", result);
dludwig@8463
   965
        return result;
dludwig@8463
   966
    }
dludwig@8463
   967
dludwig@8463
   968
    if (coreWindowBounds.Width  != data->windowSizeInDIPs.x ||
dludwig@8463
   969
        coreWindowBounds.Height != data->windowSizeInDIPs.y ||
dludwig@8414
   970
        data->orientation != DisplayProperties::CurrentOrientation)
dludwig@8414
   971
    {
dludwig@8414
   972
        ID3D11RenderTargetView* nullViews[] = {nullptr};
dludwig@8414
   973
        data->d3dContext->OMSetRenderTargets(ARRAYSIZE(nullViews), nullViews, nullptr);
dludwig@8459
   974
        data->mainRenderTargetView = nullptr;
dludwig@8414
   975
        data->d3dContext->Flush();
dludwig@8414
   976
        result = D3D11_CreateWindowSizeDependentResources(renderer);
dludwig@8414
   977
        if (FAILED(result)) {
dludwig@8554
   978
            /* D3D11_CreateWindowSizeDependentResources will set the SDL error */
dludwig@8414
   979
            return result;
dludwig@8414
   980
        }
dludwig@8414
   981
    }
dludwig@8414
   982
dludwig@8414
   983
    return S_OK;
dludwig@8414
   984
}
dludwig@8414
   985
dludwig@8414
   986
HRESULT
dludwig@8414
   987
D3D11_HandleDeviceLost(SDL_Renderer * renderer)
dludwig@8414
   988
{
dludwig@8414
   989
    D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
dludwig@8414
   990
    HRESULT result = S_OK;
dludwig@8414
   991
dludwig@8415
   992
    // Reset these member variables to ensure that D3D11_UpdateForWindowSizeChange recreates all resources.
dludwig@8414
   993
    data->windowSizeInDIPs.x = 0;
dludwig@8414
   994
    data->windowSizeInDIPs.y = 0;
dludwig@8414
   995
    data->swapChain = nullptr;
dludwig@8414
   996
dludwig@8414
   997
    result = D3D11_CreateDeviceResources(renderer);
dludwig@8414
   998
    if (FAILED(result)) {
dludwig@8554
   999
        /* D3D11_CreateDeviceResources will set the SDL error */
dludwig@8414
  1000
        return result;
dludwig@8414
  1001
    }
dludwig@8414
  1002
dludwig@8414
  1003
    result = D3D11_UpdateForWindowSizeChange(renderer);
dludwig@8414
  1004
    if (FAILED(result)) {
dludwig@8554
  1005
        /* D3D11_UpdateForWindowSizeChange will set the SDL error */
dludwig@8414
  1006
        return result;
dludwig@8414
  1007
    }
dludwig@8414
  1008
dludwig@8414
  1009
    return S_OK;
dludwig@8414
  1010
}
dludwig@8414
  1011
dludwig@8415
  1012
static void
dludwig@8415
  1013
D3D11_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
dludwig@8415
  1014
{
dludwig@8415
  1015
    //D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
dludwig@8415
  1016
dludwig@8510
  1017
    if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED) {
dludwig@8415
  1018
        D3D11_UpdateForWindowSizeChange(renderer);
dludwig@8415
  1019
    }
dludwig@8415
  1020
}
dludwig@8415
  1021
dludwig@8540
  1022
static D3D11_FILTER
dludwig@8540
  1023
GetScaleQuality(void)
dludwig@8540
  1024
{
dludwig@8540
  1025
    const char *hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY);
dludwig@8540
  1026
    if (!hint || *hint == '0' || SDL_strcasecmp(hint, "nearest") == 0) {
dludwig@8540
  1027
        return SDL_D3D11_NEAREST_PIXEL_FILTER;
dludwig@8540
  1028
    } else /* if (*hint == '1' || SDL_strcasecmp(hint, "linear") == 0) */ {
dludwig@8540
  1029
        return SDL_D3D11_LINEAR_FILTER;
dludwig@8540
  1030
    }
dludwig@8540
  1031
}
dludwig@8540
  1032
dludwig@8416
  1033
static int
dludwig@8416
  1034
D3D11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
dludwig@8416
  1035
{
dludwig@8416
  1036
    D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
dludwig@8416
  1037
    D3D11_TextureData *textureData;
dludwig@8416
  1038
    HRESULT result;
dludwig@8454
  1039
    DXGI_FORMAT textureFormat = SDLPixelFormatToDXGIFormat(texture->format);
dludwig@8454
  1040
    if (textureFormat == SDL_PIXELFORMAT_UNKNOWN) {
dludwig@8556
  1041
        return SDL_SetError("%s, An unsupported SDL pixel format (0x%x) was specified",
dludwig@8454
  1042
            __FUNCTION__, texture->format);
dludwig@8442
  1043
    }
dludwig@8416
  1044
dludwig@8416
  1045
    textureData = new D3D11_TextureData;
dludwig@8416
  1046
    if (!textureData) {
dludwig@8416
  1047
        SDL_OutOfMemory();
dludwig@8416
  1048
        return -1;
dludwig@8416
  1049
    }
dludwig@8416
  1050
    textureData->pixelFormat = SDL_AllocFormat(texture->format);
dludwig@8451
  1051
    textureData->lockedTexturePosition = XMINT2(0, 0);
dludwig@8540
  1052
    textureData->scaleMode = GetScaleQuality();
dludwig@8416
  1053
dludwig@8416
  1054
    texture->driverdata = textureData;
dludwig@8416
  1055
dludwig@8416
  1056
    D3D11_TEXTURE2D_DESC textureDesc = {0};
dludwig@8416
  1057
    textureDesc.Width = texture->w;
dludwig@8416
  1058
    textureDesc.Height = texture->h;
dludwig@8416
  1059
    textureDesc.MipLevels = 1;
dludwig@8416
  1060
    textureDesc.ArraySize = 1;
dludwig@8442
  1061
    textureDesc.Format = textureFormat;
dludwig@8416
  1062
    textureDesc.SampleDesc.Count = 1;
dludwig@8416
  1063
    textureDesc.SampleDesc.Quality = 0;
dludwig@8416
  1064
    textureDesc.MiscFlags = 0;
dludwig@8416
  1065
dludwig@8459
  1066
    if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
dludwig@8459
  1067
        textureDesc.Usage = D3D11_USAGE_DYNAMIC;
dludwig@8459
  1068
        textureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
dludwig@8459
  1069
    } else {
dludwig@8459
  1070
        textureDesc.Usage = D3D11_USAGE_DEFAULT;
dludwig@8459
  1071
        textureDesc.CPUAccessFlags = 0;
dludwig@8459
  1072
    }
dludwig@8459
  1073
dludwig@8459
  1074
    if (texture->access == SDL_TEXTUREACCESS_TARGET) {
dludwig@8459
  1075
        textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
dludwig@8459
  1076
    } else {
dludwig@8459
  1077
        textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
dludwig@8459
  1078
    }
dludwig@8459
  1079
dludwig@8452
  1080
#if 0
dludwig@8452
  1081
    // Fill the texture with a non-black color, for debugging purposes:
dludwig@8416
  1082
    const int numPixels = textureDesc.Width * textureDesc.Height;
dludwig@8452
  1083
    const int pixelSizeInBytes = textureData->pixelFormat->BytesPerPixel;
dludwig@8416
  1084
    std::vector<uint8> initialTexturePixels(numPixels * pixelSizeInBytes, 0x00);
dludwig@8452
  1085
    for (int i = 0; i < (numPixels * pixelSizeInBytes); i += pixelSizeInBytes) {
dludwig@8452
  1086
        initialTexturePixels[i+0] = 0xff;
dludwig@8452
  1087
        initialTexturePixels[i+1] = 0xff;
dludwig@8452
  1088
        initialTexturePixels[i+2] = 0x00;
dludwig@8452
  1089
        initialTexturePixels[i+3] = 0xff;
dludwig@8452
  1090
    }
dludwig@8416
  1091
    D3D11_SUBRESOURCE_DATA initialTextureData = {0};
dludwig@8416
  1092
    initialTextureData.pSysMem = (void *)&(initialTexturePixels[0]);
dludwig@8416
  1093
    initialTextureData.SysMemPitch = textureDesc.Width * pixelSizeInBytes;
dludwig@8416
  1094
    initialTextureData.SysMemSlicePitch = numPixels * pixelSizeInBytes;
dludwig@8452
  1095
#endif
dludwig@8452
  1096
dludwig@8416
  1097
    result = rendererData->d3dDevice->CreateTexture2D(
dludwig@8416
  1098
        &textureDesc,
dludwig@8452
  1099
        NULL,   // &initialTextureData,
dludwig@8416
  1100
        &textureData->mainTexture
dludwig@8416
  1101
        );
dludwig@8416
  1102
    if (FAILED(result)) {
dludwig@8416
  1103
        D3D11_DestroyTexture(renderer, texture);
dludwig@8553
  1104
        WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateTexture2D", result);
dludwig@8416
  1105
        return -1;
dludwig@8416
  1106
    }
dludwig@8416
  1107
dludwig@8459
  1108
    if (texture->access & SDL_TEXTUREACCESS_TARGET) {
dludwig@8459
  1109
        D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc;
dludwig@8459
  1110
        renderTargetViewDesc.Format = textureDesc.Format;
dludwig@8459
  1111
        renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
dludwig@8459
  1112
        renderTargetViewDesc.Texture2D.MipSlice = 0;
dludwig@8459
  1113
dludwig@8459
  1114
        result = rendererData->d3dDevice->CreateRenderTargetView(
dludwig@8459
  1115
            textureData->mainTexture.Get(),
dludwig@8459
  1116
            &renderTargetViewDesc,
dludwig@8459
  1117
            &textureData->mainTextureRenderTargetView);
dludwig@8459
  1118
        if (FAILED(result)) {
dludwig@8459
  1119
            D3D11_DestroyTexture(renderer, texture);
dludwig@8553
  1120
            WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateRenderTargetView", result);
dludwig@8459
  1121
            return -1;
dludwig@8459
  1122
        }
dludwig@8459
  1123
    }
dludwig@8459
  1124
dludwig@8416
  1125
    D3D11_SHADER_RESOURCE_VIEW_DESC resourceViewDesc;
dludwig@8416
  1126
    resourceViewDesc.Format = textureDesc.Format;
dludwig@8416
  1127
    resourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
dludwig@8416
  1128
    resourceViewDesc.Texture2D.MostDetailedMip = 0;
dludwig@8416
  1129
    resourceViewDesc.Texture2D.MipLevels = textureDesc.MipLevels;
dludwig@8416
  1130
    result = rendererData->d3dDevice->CreateShaderResourceView(
dludwig@8416
  1131
        textureData->mainTexture.Get(),
dludwig@8416
  1132
        &resourceViewDesc,
dludwig@8416
  1133
        &textureData->mainTextureResourceView
dludwig@8416
  1134
        );
dludwig@8416
  1135
    if (FAILED(result)) {
dludwig@8416
  1136
        D3D11_DestroyTexture(renderer, texture);
dludwig@8553
  1137
        WIN_SetErrorFromHRESULT(__FUNCTION__ "ID3D11Device1::CreateShaderResourceView", result);
dludwig@8416
  1138
        return -1;
dludwig@8416
  1139
    }
dludwig@8416
  1140
dludwig@8416
  1141
    return 0;
dludwig@8416
  1142
}
dludwig@8416
  1143
dludwig@8416
  1144
static void
dludwig@8416
  1145
D3D11_DestroyTexture(SDL_Renderer * renderer,
dludwig@8416
  1146
                     SDL_Texture * texture)
dludwig@8416
  1147
{
dludwig@8416
  1148
    D3D11_TextureData *textureData = (D3D11_TextureData *) texture->driverdata;
dludwig@8416
  1149
dludwig@8416
  1150
    if (textureData) {
dludwig@8416
  1151
        if (textureData->pixelFormat) {
dludwig@8416
  1152
            SDL_FreeFormat(textureData->pixelFormat);
dludwig@8416
  1153
            textureData->pixelFormat = NULL;
dludwig@8416
  1154
        }
dludwig@8416
  1155
dludwig@8416
  1156
        delete textureData;
dludwig@8416
  1157
        texture->driverdata = NULL;
dludwig@8416
  1158
    }
dludwig@8416
  1159
}
dludwig@8416
  1160
dludwig@8416
  1161
static int
dludwig@8416
  1162
D3D11_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
dludwig@8459
  1163
                    const SDL_Rect * rect, const void * srcPixels,
dludwig@8459
  1164
                    int srcPitch)
dludwig@8416
  1165
{
dludwig@8459
  1166
    // Lock the texture, retrieving a buffer to write pixel data to:
dludwig@8459
  1167
    void * destPixels = NULL;
dludwig@8459
  1168
    int destPitch = 0;
dludwig@8459
  1169
    if (D3D11_LockTexture(renderer, texture, rect, &destPixels, &destPitch) != 0) {
dludwig@8459
  1170
        // An error is already set.  Attach some info to it, then return to
dludwig@8459
  1171
        // the caller.
dludwig@8459
  1172
        std::string errorMessage = string(__FUNCTION__ ", Lock Texture Failed: ") + SDL_GetError();
dludwig@8556
  1173
        return SDL_SetError(errorMessage.c_str());
dludwig@8416
  1174
    }
dludwig@8416
  1175
dludwig@8416
  1176
    // Copy pixel data to the locked texture's memory:
dludwig@8416
  1177
    for (int y = 0; y < rect->h; ++y) {
dludwig@8416
  1178
        memcpy(
dludwig@8459
  1179
            ((Uint8 *)destPixels) + (destPitch * y),
dludwig@8459
  1180
            ((Uint8 *)srcPixels) + (srcPitch * y),
dludwig@8459
  1181
            srcPitch
dludwig@8416
  1182
            );
dludwig@8416
  1183
    }
dludwig@8416
  1184
dludwig@8459
  1185
    // Commit the texture's memory back to Direct3D:
dludwig@8459
  1186
    D3D11_UnlockTexture(renderer, texture);
dludwig@8416
  1187
dludwig@8459
  1188
    // Return to the caller:
dludwig@8416
  1189
    return 0;
dludwig@8416
  1190
}
dludwig@8416
  1191
dludwig@8400
  1192
static int
dludwig@8451
  1193
D3D11_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
dludwig@8451
  1194
                  const SDL_Rect * rect, void **pixels, int *pitch)
dludwig@8451
  1195
{
dludwig@8451
  1196
    D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
dludwig@8451
  1197
    D3D11_TextureData *textureData = (D3D11_TextureData *) texture->driverdata;
dludwig@8451
  1198
    HRESULT result = S_OK;
dludwig@8451
  1199
dludwig@8451
  1200
    if (textureData->stagingTexture) {
dludwig@8556
  1201
        return SDL_SetError("texture is already locked");
dludwig@8451
  1202
    }
dludwig@8451
  1203
    
dludwig@8451
  1204
    // Create a 'staging' texture, which will be used to write to a portion
dludwig@8451
  1205
    // of the main texture.  This is necessary, as Direct3D 11.1 does not
dludwig@8451
  1206
    // have the ability to write a CPU-bound pixel buffer to a rectangular
dludwig@8451
  1207
    // subrect of a texture.  Direct3D 11.1 can, however, write a pixel
dludwig@8451
  1208
    // buffer to an entire texture, hence the use of a staging texture.
dludwig@8451
  1209
    D3D11_TEXTURE2D_DESC stagingTextureDesc;
dludwig@8451
  1210
    textureData->mainTexture->GetDesc(&stagingTextureDesc);
dludwig@8451
  1211
    stagingTextureDesc.Width = rect->w;
dludwig@8451
  1212
    stagingTextureDesc.Height = rect->h;
dludwig@8451
  1213
    stagingTextureDesc.BindFlags = 0;
dludwig@8451
  1214
    stagingTextureDesc.MiscFlags = 0;
dludwig@8451
  1215
    stagingTextureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
dludwig@8451
  1216
    stagingTextureDesc.Usage = D3D11_USAGE_STAGING;
dludwig@8451
  1217
    result = rendererData->d3dDevice->CreateTexture2D(
dludwig@8451
  1218
        &stagingTextureDesc,
dludwig@8451
  1219
        NULL,
dludwig@8451
  1220
        &textureData->stagingTexture);
dludwig@8451
  1221
    if (FAILED(result)) {
dludwig@8553
  1222
        WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateTexture2D [create staging texture]", result);
dludwig@8451
  1223
        return -1;
dludwig@8451
  1224
    }
dludwig@8451
  1225
dludwig@8451
  1226
    // Get a write-only pointer to data in the staging texture:
dludwig@8451
  1227
    D3D11_MAPPED_SUBRESOURCE textureMemory = {0};
dludwig@8451
  1228
    result = rendererData->d3dContext->Map(
dludwig@8451
  1229
        textureData->stagingTexture.Get(),
dludwig@8451
  1230
        D3D11CalcSubresource(0, 0, 0),
dludwig@8451
  1231
        D3D11_MAP_WRITE,
dludwig@8451
  1232
        0,
dludwig@8451
  1233
        &textureMemory
dludwig@8451
  1234
        );
dludwig@8451
  1235
    if (FAILED(result)) {
dludwig@8553
  1236
        WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11DeviceContext1::Map [map staging texture]", result);
dludwig@8451
  1237
        textureData->stagingTexture = nullptr;
dludwig@8451
  1238
        return -1;
dludwig@8451
  1239
    }
dludwig@8451
  1240
dludwig@8451
  1241
    // Make note of where the staging texture will be written to (on a
dludwig@8451
  1242
    // call to SDL_UnlockTexture):
dludwig@8451
  1243
    textureData->lockedTexturePosition = XMINT2(rect->x, rect->y);
dludwig@8451
  1244
dludwig@8451
  1245
    // Make sure the caller has information on the texture's pixel buffer,
dludwig@8451
  1246
    // then return:
dludwig@8451
  1247
    *pixels = textureMemory.pData;
dludwig@8451
  1248
    *pitch = textureMemory.RowPitch;
dludwig@8451
  1249
    return 0;
dludwig@8451
  1250
}
dludwig@8451
  1251
dludwig@8451
  1252
static void
dludwig@8451
  1253
D3D11_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
dludwig@8451
  1254
{
dludwig@8451
  1255
    D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
dludwig@8451
  1256
    D3D11_TextureData *textureData = (D3D11_TextureData *) texture->driverdata;
dludwig@8451
  1257
dludwig@8451
  1258
    // Commit the pixel buffer's changes back to the staging texture:
dludwig@8451
  1259
    rendererData->d3dContext->Unmap(
dludwig@8451
  1260
        textureData->stagingTexture.Get(),
dludwig@8451
  1261
        0);
dludwig@8451
  1262
dludwig@8451
  1263
    // Copy the staging texture's contents back to the main texture:
dludwig@8451
  1264
    rendererData->d3dContext->CopySubresourceRegion(
dludwig@8451
  1265
        textureData->mainTexture.Get(),
dludwig@8451
  1266
        D3D11CalcSubresource(0, 0, 0),
dludwig@8451
  1267
        textureData->lockedTexturePosition.x,
dludwig@8451
  1268
        textureData->lockedTexturePosition.y,
dludwig@8451
  1269
        0,
dludwig@8451
  1270
        textureData->stagingTexture.Get(),
dludwig@8451
  1271
        D3D11CalcSubresource(0, 0, 0),
dludwig@8451
  1272
        NULL);
dludwig@8451
  1273
dludwig@8451
  1274
    // Clean up and return:
dludwig@8451
  1275
    textureData->stagingTexture = nullptr;
dludwig@8451
  1276
    textureData->lockedTexturePosition = XMINT2(0, 0);
dludwig@8451
  1277
}
dludwig@8451
  1278
dludwig@8451
  1279
static int
dludwig@8459
  1280
D3D11_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
dludwig@8459
  1281
{
dludwig@8459
  1282
    D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
dludwig@8459
  1283
dludwig@8459
  1284
    if (texture == NULL) {
dludwig@8459
  1285
        rendererData->currentOffscreenRenderTargetView = nullptr;
dludwig@8459
  1286
        return 0;
dludwig@8459
  1287
    }
dludwig@8459
  1288
dludwig@8459
  1289
    D3D11_TextureData *textureData = (D3D11_TextureData *) texture->driverdata;
dludwig@8459
  1290
dludwig@8459
  1291
    if (!textureData->mainTextureRenderTargetView) {
dludwig@8558
  1292
        return SDL_SetError("specified texture is not a render target");
dludwig@8459
  1293
    }
dludwig@8459
  1294
dludwig@8459
  1295
    rendererData->currentOffscreenRenderTargetView = textureData->mainTextureRenderTargetView;
dludwig@8459
  1296
dludwig@8459
  1297
    return 0;
dludwig@8548
  1298
}
dludwig@8459
  1299
dludwig@8459
  1300
static int
dludwig@8400
  1301
D3D11_UpdateViewport(SDL_Renderer * renderer)
dludwig@8400
  1302
{
dludwig@8432
  1303
    D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
dludwig@8432
  1304
dludwig@8432
  1305
    if (renderer->viewport.w == 0 || renderer->viewport.h == 0) {
dludwig@8432
  1306
        // If the viewport is empty, assume that it is because
dludwig@8432
  1307
        // SDL_CreateRenderer is calling it, and will call it again later
dludwig@8432
  1308
        // with a non-empty viewport.
dludwig@8432
  1309
        return 0;
dludwig@8432
  1310
    }
dludwig@8432
  1311
dludwig@8548
  1312
    // Make sure the SDL viewport gets rotated to that of the physical display's orientation.
dludwig@8548
  1313
    // Keep in mind here that the Y-axis will be been inverted (from Direct3D's
dludwig@8548
  1314
    // default coordinate system) so rotations will be done in the opposite
dludwig@8548
  1315
    // direction of the DXGI_MODE_ROTATION enumeration.
dludwig@8548
  1316
    switch (D3D11_GetRotationForOrientation(data->orientation))
dludwig@8432
  1317
    {
dludwig@8548
  1318
        case DXGI_MODE_ROTATION_IDENTITY:
dludwig@8548
  1319
            XMStoreFloat4x4(&data->vertexShaderConstantsData.projection, XMMatrixIdentity());
dludwig@8548
  1320
            break;
dludwig@8548
  1321
        case DXGI_MODE_ROTATION_ROTATE270:
dludwig@8548
  1322
            XMStoreFloat4x4(&data->vertexShaderConstantsData.projection, XMMatrixRotationZ(XM_PIDIV2));
dludwig@8548
  1323
            break;
dludwig@8548
  1324
        case DXGI_MODE_ROTATION_ROTATE180:
dludwig@8548
  1325
            XMStoreFloat4x4(&data->vertexShaderConstantsData.projection, XMMatrixRotationZ(XM_PI));
dludwig@8548
  1326
            break;
dludwig@8548
  1327
        case DXGI_MODE_ROTATION_ROTATE90:
dludwig@8510
  1328
            XMStoreFloat4x4(&data->vertexShaderConstantsData.projection, XMMatrixRotationZ(-XM_PIDIV2));
dludwig@8432
  1329
            break;
dludwig@8432
  1330
        default:
dludwig@8556
  1331
            return SDL_SetError("An unknown DisplayOrientation is being used");
dludwig@8432
  1332
    }
dludwig@8432
  1333
dludwig@8432
  1334
    //
dludwig@8432
  1335
    // Update the view matrix
dludwig@8432
  1336
    //
dludwig@8433
  1337
    float viewportWidth = (float) renderer->viewport.w;
dludwig@8433
  1338
    float viewportHeight = (float) renderer->viewport.h;
dludwig@8433
  1339
    XMStoreFloat4x4(&data->vertexShaderConstantsData.view,
dludwig@8432
  1340
        XMMatrixMultiply(
dludwig@8433
  1341
            XMMatrixScaling(2.0f / viewportWidth, 2.0f / viewportHeight, 1.0f),
dludwig@8432
  1342
            XMMatrixMultiply(
dludwig@8432
  1343
                XMMatrixTranslation(-1, -1, 0),
dludwig@8432
  1344
                XMMatrixRotationX(XM_PI)
dludwig@8432
  1345
                )));
dludwig@8434
  1346
#if 0
dludwig@8434
  1347
    data->vertexShaderConstantsData.view = XMMatrixIdentity();
dludwig@8434
  1348
#endif
dludwig@8433
  1349
dludwig@8433
  1350
    //
dludwig@8456
  1351
    // Reset the model matrix
dludwig@8456
  1352
    //
dludwig@8456
  1353
    XMStoreFloat4x4(&data->vertexShaderConstantsData.model, XMMatrixIdentity());
dludwig@8456
  1354
dludwig@8456
  1355
    //
dludwig@8433
  1356
    // Update the Direct3D viewport, which seems to be aligned to the
dludwig@8510
  1357
    // swap buffer's coordinate space, which is always in either
dludwig@8510
  1358
    // a landscape mode, for all Windows 8/RT devices, or a portrait mode,
dludwig@8510
  1359
    // for Windows Phone devices.
dludwig@8433
  1360
    //
dludwig@8433
  1361
    SDL_FRect orientationAlignedViewport;
dludwig@8548
  1362
dludwig@8508
  1363
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
dludwig@8510
  1364
    const bool swapDimensions =
dludwig@8510
  1365
        data->orientation == DisplayOrientations::Landscape ||
dludwig@8510
  1366
        data->orientation == DisplayOrientations::LandscapeFlipped;
dludwig@8508
  1367
#else
dludwig@8433
  1368
    const bool swapDimensions =
dludwig@8433
  1369
        data->orientation == DisplayOrientations::Portrait ||
dludwig@8433
  1370
        data->orientation == DisplayOrientations::PortraitFlipped;
dludwig@8508
  1371
#endif
dludwig@8433
  1372
    if (swapDimensions) {
dludwig@8433
  1373
        orientationAlignedViewport.x = (float) renderer->viewport.y;
dludwig@8433
  1374
        orientationAlignedViewport.y = (float) renderer->viewport.x;
dludwig@8433
  1375
        orientationAlignedViewport.w = (float) renderer->viewport.h;
dludwig@8433
  1376
        orientationAlignedViewport.h = (float) renderer->viewport.w;
dludwig@8433
  1377
    } else {
dludwig@8433
  1378
        orientationAlignedViewport.x = (float) renderer->viewport.x;
dludwig@8433
  1379
        orientationAlignedViewport.y = (float) renderer->viewport.y;
dludwig@8433
  1380
        orientationAlignedViewport.w = (float) renderer->viewport.w;
dludwig@8433
  1381
        orientationAlignedViewport.h = (float) renderer->viewport.h;
dludwig@8433
  1382
    }
dludwig@8504
  1383
    // TODO, WinRT: get custom viewports working with non-Landscape modes (Portrait, PortraitFlipped, and LandscapeFlipped)
dludwig@8432
  1384
dludwig@8432
  1385
    D3D11_VIEWPORT viewport;
dludwig@8432
  1386
    memset(&viewport, 0, sizeof(viewport));
dludwig@8433
  1387
    viewport.TopLeftX = orientationAlignedViewport.x;
dludwig@8433
  1388
    viewport.TopLeftY = orientationAlignedViewport.y;
dludwig@8433
  1389
    viewport.Width = orientationAlignedViewport.w;
dludwig@8433
  1390
    viewport.Height = orientationAlignedViewport.h;
dludwig@8432
  1391
    viewport.MinDepth = 0.0f;
dludwig@8432
  1392
    viewport.MaxDepth = 1.0f;
dludwig@8432
  1393
    data->d3dContext->RSSetViewports(1, &viewport);
dludwig@8432
  1394
dludwig@8433
  1395
#if 0
dludwig@8433
  1396
    SDL_Log("%s, oav={%.0f,%.0f,%.0f,%.0f}, rend={%.0f,%.0f}\n",
dludwig@8433
  1397
        __FUNCTION__,
dludwig@8433
  1398
        orientationAlignedViewport.x,
dludwig@8433
  1399
        orientationAlignedViewport.y,
dludwig@8433
  1400
        orientationAlignedViewport.w,
dludwig@8433
  1401
        orientationAlignedViewport.h,
dludwig@8433
  1402
        data->renderTargetSize.x,
dludwig@8433
  1403
        data->renderTargetSize.y);
dludwig@8433
  1404
#endif
dludwig@8433
  1405
dludwig@8400
  1406
    return 0;
dludwig@8400
  1407
}
dludwig@8400
  1408
dludwig@8482
  1409
static int
dludwig@8482
  1410
D3D11_UpdateClipRect(SDL_Renderer * renderer)
dludwig@8482
  1411
{
dludwig@8482
  1412
    // TODO, WinRT: implement D3D11_UpdateClipRect
dludwig@8482
  1413
    return 0;
dludwig@8482
  1414
}
dludwig@8482
  1415
dludwig@8459
  1416
static ComPtr<ID3D11RenderTargetView> &
dludwig@8459
  1417
D3D11_GetCurrentRenderTargetView(SDL_Renderer * renderer)
dludwig@8459
  1418
{
dludwig@8459
  1419
    D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
dludwig@8459
  1420
    if (data->currentOffscreenRenderTargetView) {
dludwig@8459
  1421
        return data->currentOffscreenRenderTargetView;
dludwig@8459
  1422
    } else {
dludwig@8459
  1423
        return data->mainRenderTargetView;
dludwig@8459
  1424
    }
dludwig@8459
  1425
}
dludwig@8459
  1426
dludwig@8416
  1427
static int
dludwig@8416
  1428
D3D11_RenderClear(SDL_Renderer * renderer)
dludwig@8416
  1429
{
dludwig@8416
  1430
    D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
dludwig@8416
  1431
    const float colorRGBA[] = {
dludwig@8423
  1432
        (renderer->r / 255.0f),
dludwig@8423
  1433
        (renderer->g / 255.0f),
dludwig@8423
  1434
        (renderer->b / 255.0f),
dludwig@8423
  1435
        (renderer->a / 255.0f)
dludwig@8416
  1436
    };
dludwig@8416
  1437
    data->d3dContext->ClearRenderTargetView(
dludwig@8459
  1438
        D3D11_GetCurrentRenderTargetView(renderer).Get(),
dludwig@8416
  1439
        colorRGBA
dludwig@8416
  1440
        );
dludwig@8416
  1441
    return 0;
dludwig@8416
  1442
}
dludwig@8416
  1443
dludwig@8429
  1444
static int
dludwig@8429
  1445
D3D11_UpdateVertexBuffer(SDL_Renderer *renderer,
dludwig@8550
  1446
                         const void * vertexData, size_t dataSizeInBytes)
dludwig@8416
  1447
{
dludwig@8416
  1448
    D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
dludwig@8425
  1449
    HRESULT result = S_OK;
dludwig@8449
  1450
    D3D11_BUFFER_DESC vertexBufferDesc;
dludwig@8449
  1451
dludwig@8449
  1452
    if (rendererData->vertexBuffer) {
dludwig@8449
  1453
        rendererData->vertexBuffer->GetDesc(&vertexBufferDesc);
dludwig@8449
  1454
    } else {
dludwig@8449
  1455
        memset(&vertexBufferDesc, 0, sizeof(vertexBufferDesc));
dludwig@8449
  1456
    }
dludwig@8449
  1457
dludwig@8449
  1458
    if (vertexBufferDesc.ByteWidth >= dataSizeInBytes) {
dludwig@8550
  1459
        D3D11_MAPPED_SUBRESOURCE mappedResource;
dludwig@8550
  1460
        ZeroMemory(&mappedResource, sizeof(D3D11_MAPPED_SUBRESOURCE));
dludwig@8550
  1461
        result = rendererData->d3dContext->Map(rendererData->vertexBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
dludwig@8550
  1462
        if (FAILED(result)) {
dludwig@8553
  1463
            WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11DeviceContext1::Map [vertex buffer]", result);
dludwig@8550
  1464
            return -1;
dludwig@8550
  1465
        }
dludwig@8550
  1466
        memcpy(mappedResource.pData, vertexData, dataSizeInBytes);
dludwig@8550
  1467
        rendererData->d3dContext->Unmap(rendererData->vertexBuffer.Get(), 0);
dludwig@8425
  1468
    } else {
dludwig@8449
  1469
        vertexBufferDesc.ByteWidth = dataSizeInBytes;
dludwig@8550
  1470
        vertexBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
dludwig@8449
  1471
        vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
dludwig@8550
  1472
        vertexBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
dludwig@8449
  1473
dludwig@8425
  1474
        D3D11_SUBRESOURCE_DATA vertexBufferData = {0};
dludwig@8429
  1475
        vertexBufferData.pSysMem = vertexData;
dludwig@8425
  1476
        vertexBufferData.SysMemPitch = 0;
dludwig@8425
  1477
        vertexBufferData.SysMemSlicePitch = 0;
dludwig@8449
  1478
dludwig@8425
  1479
        result = rendererData->d3dDevice->CreateBuffer(
dludwig@8425
  1480
            &vertexBufferDesc,
dludwig@8425
  1481
            &vertexBufferData,
dludwig@8425
  1482
            &rendererData->vertexBuffer
dludwig@8425
  1483
            );
dludwig@8425
  1484
        if (FAILED(result)) {
dludwig@8553
  1485
            WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateBuffer [vertex buffer]", result);
dludwig@8425
  1486
            return -1;
dludwig@8425
  1487
        }
dludwig@8425
  1488
    }
dludwig@8425
  1489
dludwig@8416
  1490
    UINT stride = sizeof(VertexPositionColor);
dludwig@8416
  1491
    UINT offset = 0;
dludwig@8416
  1492
    rendererData->d3dContext->IASetVertexBuffers(
dludwig@8416
  1493
        0,
dludwig@8416
  1494
        1,
dludwig@8416
  1495
        rendererData->vertexBuffer.GetAddressOf(),
dludwig@8416
  1496
        &stride,
dludwig@8416
  1497
        &offset
dludwig@8429
  1498
        );
dludwig@8429
  1499
dludwig@8429
  1500
    return 0;
dludwig@8429
  1501
}
dludwig@8429
  1502
dludwig@8429
  1503
static void
dludwig@8429
  1504
D3D11_RenderStartDrawOp(SDL_Renderer * renderer)
dludwig@8429
  1505
{
dludwig@8429
  1506
    D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
dludwig@8429
  1507
dludwig@8429
  1508
    rendererData->d3dContext->OMSetRenderTargets(
dludwig@8429
  1509
        1,
dludwig@8459
  1510
        D3D11_GetCurrentRenderTargetView(renderer).GetAddressOf(),
dludwig@8429
  1511
        nullptr
dludwig@8416
  1512
        );
dludwig@8442
  1513
}
dludwig@8431
  1514
dludwig@8442
  1515
static void
dludwig@8442
  1516
D3D11_RenderSetBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode)
dludwig@8442
  1517
{
dludwig@8442
  1518
    D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
dludwig@8442
  1519
    switch (blendMode) {
dludwig@8431
  1520
        case SDL_BLENDMODE_BLEND:
dludwig@8431
  1521
            rendererData->d3dContext->OMSetBlendState(rendererData->blendModeBlend.Get(), 0, 0xFFFFFFFF);
dludwig@8431
  1522
            break;
dludwig@8431
  1523
        case SDL_BLENDMODE_ADD:
dludwig@8431
  1524
            rendererData->d3dContext->OMSetBlendState(rendererData->blendModeAdd.Get(), 0, 0xFFFFFFFF);
dludwig@8431
  1525
            break;
dludwig@8431
  1526
        case SDL_BLENDMODE_MOD:
dludwig@8431
  1527
            rendererData->d3dContext->OMSetBlendState(rendererData->blendModeMod.Get(), 0, 0xFFFFFFFF);
dludwig@8431
  1528
            break;
dludwig@8431
  1529
        case SDL_BLENDMODE_NONE:
dludwig@8431
  1530
            rendererData->d3dContext->OMSetBlendState(NULL, 0, 0xFFFFFFFF);
dludwig@8431
  1531
            break;
dludwig@8431
  1532
    }
dludwig@8429
  1533
}
dludwig@8429
  1534
dludwig@8429
  1535
static void
dludwig@8429
  1536
D3D11_SetPixelShader(SDL_Renderer * renderer,
dludwig@8429
  1537
                     ID3D11PixelShader * shader,
dludwig@8429
  1538
                     ID3D11ShaderResourceView * shaderResource,
dludwig@8429
  1539
                     ID3D11SamplerState * sampler)
dludwig@8429
  1540
{
dludwig@8429
  1541
    D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
dludwig@8429
  1542
    rendererData->d3dContext->PSSetShader(shader, nullptr, 0);
dludwig@8429
  1543
    rendererData->d3dContext->PSSetShaderResources(0, 1, &shaderResource);
dludwig@8429
  1544
    rendererData->d3dContext->PSSetSamplers(0, 1, &sampler);
dludwig@8429
  1545
}
dludwig@8429
  1546
dludwig@8429
  1547
static void
dludwig@8429
  1548
D3D11_RenderFinishDrawOp(SDL_Renderer * renderer,
dludwig@8449
  1549
                         D3D11_PRIMITIVE_TOPOLOGY primitiveTopology,
dludwig@8449
  1550
                         UINT vertexCount)
dludwig@8429
  1551
{
dludwig@8429
  1552
    D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
dludwig@8456
  1553
dludwig@8456
  1554
    rendererData->d3dContext->UpdateSubresource(
dludwig@8456
  1555
        rendererData->vertexShaderConstants.Get(),
dludwig@8456
  1556
        0,
dludwig@8456
  1557
        NULL,
dludwig@8456
  1558
        &rendererData->vertexShaderConstantsData,
dludwig@8456
  1559
        0,
dludwig@8456
  1560
        0
dludwig@8456
  1561
        );
dludwig@8456
  1562
dludwig@8429
  1563
    rendererData->d3dContext->IASetPrimitiveTopology(primitiveTopology);
dludwig@8429
  1564
    rendererData->d3dContext->IASetInputLayout(rendererData->inputLayout.Get());
dludwig@8429
  1565
    rendererData->d3dContext->VSSetShader(rendererData->vertexShader.Get(), nullptr, 0);
dludwig@8429
  1566
    rendererData->d3dContext->VSSetConstantBuffers(0, 1, rendererData->vertexShaderConstants.GetAddressOf());
dludwig@8429
  1567
    rendererData->d3dContext->RSSetState(rendererData->mainRasterizer.Get());
dludwig@8449
  1568
    rendererData->d3dContext->Draw(vertexCount, 0);
dludwig@8449
  1569
}
dludwig@8449
  1570
dludwig@8449
  1571
static int
dludwig@8450
  1572
D3D11_RenderDrawPoints(SDL_Renderer * renderer,
dludwig@8450
  1573
                       const SDL_FPoint * points, int count)
dludwig@8450
  1574
{
dludwig@8450
  1575
    D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
dludwig@8450
  1576
    float r, g, b, a;
dludwig@8450
  1577
dludwig@8450
  1578
    r = (float)(renderer->r / 255.0f);
dludwig@8450
  1579
    g = (float)(renderer->g / 255.0f);
dludwig@8450
  1580
    b = (float)(renderer->b / 255.0f);
dludwig@8450
  1581
    a = (float)(renderer->a / 255.0f);
dludwig@8450
  1582
dludwig@8507
  1583
    VertexPositionColor * vertices = SDL_stack_alloc(VertexPositionColor, count);
dludwig@8507
  1584
    for (int i = 0; i < min(count, 128); ++i) {
dludwig@8507
  1585
        const VertexPositionColor v = {XMFLOAT3(points[i].x, points[i].y, 0.0f),  XMFLOAT2(0.0f, 0.0f), XMFLOAT4(r, g, b, a)};
dludwig@8507
  1586
        vertices[i] = v;
dludwig@8450
  1587
    }
dludwig@8450
  1588
dludwig@8450
  1589
    D3D11_RenderStartDrawOp(renderer);
dludwig@8450
  1590
    D3D11_RenderSetBlendMode(renderer, renderer->blendMode);
dludwig@8507
  1591
    if (D3D11_UpdateVertexBuffer(renderer, vertices, (unsigned int)count * sizeof(VertexPositionColor)) != 0) {
dludwig@8507
  1592
        SDL_stack_free(vertices);
dludwig@8450
  1593
        return -1;
dludwig@8450
  1594
    }
dludwig@8450
  1595
dludwig@8450
  1596
    D3D11_SetPixelShader(
dludwig@8450
  1597
        renderer,
dludwig@8450
  1598
        rendererData->colorPixelShader.Get(),
dludwig@8450
  1599
        nullptr,
dludwig@8450
  1600
        nullptr);
dludwig@8450
  1601
dludwig@8507
  1602
    D3D11_RenderFinishDrawOp(renderer, D3D11_PRIMITIVE_TOPOLOGY_POINTLIST, count);
dludwig@8507
  1603
    SDL_stack_free(vertices);
dludwig@8450
  1604
    return 0;
dludwig@8450
  1605
}
dludwig@8450
  1606
dludwig@8450
  1607
static int
dludwig@8449
  1608
D3D11_RenderDrawLines(SDL_Renderer * renderer,
dludwig@8449
  1609
                      const SDL_FPoint * points, int count)
dludwig@8449
  1610
{
dludwig@8449
  1611
    D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
dludwig@8449
  1612
    float r, g, b, a;
dludwig@8449
  1613
dludwig@8449
  1614
    r = (float)(renderer->r / 255.0f);
dludwig@8449
  1615
    g = (float)(renderer->g / 255.0f);
dludwig@8449
  1616
    b = (float)(renderer->b / 255.0f);
dludwig@8449
  1617
    a = (float)(renderer->a / 255.0f);
dludwig@8449
  1618
dludwig@8507
  1619
    VertexPositionColor * vertices = SDL_stack_alloc(VertexPositionColor, count);
dludwig@8449
  1620
    for (int i = 0; i < count; ++i) {
dludwig@8507
  1621
        const VertexPositionColor v = {XMFLOAT3(points[i].x, points[i].y, 0.0f),  XMFLOAT2(0.0f, 0.0f), XMFLOAT4(r, g, b, a)};
dludwig@8507
  1622
        vertices[i] = v;
dludwig@8449
  1623
    }
dludwig@8449
  1624
dludwig@8449
  1625
    D3D11_RenderStartDrawOp(renderer);
dludwig@8449
  1626
    D3D11_RenderSetBlendMode(renderer, renderer->blendMode);
dludwig@8526
  1627
    if (D3D11_UpdateVertexBuffer(renderer, vertices, (unsigned int)count * sizeof(VertexPositionColor)) != 0) {
dludwig@8507
  1628
        SDL_stack_free(vertices);
dludwig@8449
  1629
        return -1;
dludwig@8449
  1630
    }
dludwig@8449
  1631
dludwig@8449
  1632
    D3D11_SetPixelShader(
dludwig@8449
  1633
        renderer,
dludwig@8449
  1634
        rendererData->colorPixelShader.Get(),
dludwig@8449
  1635
        nullptr,
dludwig@8449
  1636
        nullptr);
dludwig@8449
  1637
dludwig@8507
  1638
    D3D11_RenderFinishDrawOp(renderer, D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP, count);
dludwig@8507
  1639
    SDL_stack_free(vertices);
dludwig@8449
  1640
    return 0;
dludwig@8429
  1641
}
dludwig@8429
  1642
dludwig@8429
  1643
static int
dludwig@8429
  1644
D3D11_RenderFillRects(SDL_Renderer * renderer,
dludwig@8429
  1645
                      const SDL_FRect * rects, int count)
dludwig@8429
  1646
{
dludwig@8429
  1647
    D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
dludwig@8429
  1648
    float r, g, b, a;
dludwig@8429
  1649
dludwig@8431
  1650
    r = (float)(renderer->r / 255.0f);
dludwig@8431
  1651
    g = (float)(renderer->g / 255.0f);
dludwig@8431
  1652
    b = (float)(renderer->b / 255.0f);
dludwig@8431
  1653
    a = (float)(renderer->a / 255.0f);
dludwig@8429
  1654
dludwig@8433
  1655
#if 0
dludwig@8433
  1656
    // Set up a test pattern:
dludwig@8434
  1657
    SDL_FRect _rects[] = {
dludwig@8433
  1658
        {-1.1f, 1.1f, 1.1f, -1.1f},
dludwig@8433
  1659
        {-1.0f, 1.0f, 1.0f, -1.0f},     // red
dludwig@8433
  1660
        {0.0f, 1.0f, 1.0f, -1.0f},      // green
dludwig@8433
  1661
        {-1.0f, 0.0f, 1.0f, -1.0f},     // blue
dludwig@8433
  1662
        {0.0f, 0.0f, 1.0f, -1.0f}       // white
dludwig@8433
  1663
    };
dludwig@8434
  1664
    count = sizeof(_rects) / sizeof(SDL_FRect);
dludwig@8434
  1665
#define rects _rects
dludwig@8433
  1666
#endif
dludwig@8429
  1667
dludwig@8429
  1668
    for (int i = 0; i < count; ++i) {
dludwig@8433
  1669
        D3D11_RenderStartDrawOp(renderer);
dludwig@8442
  1670
        D3D11_RenderSetBlendMode(renderer, renderer->blendMode);
dludwig@8433
  1671
dludwig@8433
  1672
#if 0
dludwig@8433
  1673
        // Set colors for the test pattern:
dludwig@8433
  1674
        a = 1.0f;
dludwig@8433
  1675
        switch (i) {
dludwig@8433
  1676
            case 0: r = 1.0f; g = 1.0f; b = 0.0f; break;
dludwig@8433
  1677
            case 1: r = 1.0f; g = 0.0f; b = 0.0f; break;
dludwig@8433
  1678
            case 2: r = 0.0f; g = 1.0f; b = 0.0f; break;
dludwig@8433
  1679
            case 3: r = 0.0f; g = 0.0f; b = 1.0f; break;
dludwig@8433
  1680
            case 4: r = 1.0f; g = 1.0f; b = 1.0f; break;
dludwig@8433
  1681
        }
dludwig@8433
  1682
#endif
dludwig@8433
  1683
dludwig@8429
  1684
        VertexPositionColor vertices[] = {
dludwig@8429
  1685
            {XMFLOAT3(rects[i].x, rects[i].y, 0.0f),                           XMFLOAT2(0.0f, 0.0f), XMFLOAT4(r, g, b, a)},
dludwig@8429
  1686
            {XMFLOAT3(rects[i].x, rects[i].y + rects[i].h, 0.0f),              XMFLOAT2(0.0f, 0.0f), XMFLOAT4(r, g, b, a)},
dludwig@8429
  1687
            {XMFLOAT3(rects[i].x + rects[i].w, rects[i].y, 0.0f),              XMFLOAT2(0.0f, 0.0f), XMFLOAT4(r, g, b, a)},
dludwig@8429
  1688
            {XMFLOAT3(rects[i].x + rects[i].w, rects[i].y + rects[i].h, 0.0f), XMFLOAT2(0.0f, 0.0f), XMFLOAT4(r, g, b, a)},
dludwig@8429
  1689
        };
dludwig@8429
  1690
        if (D3D11_UpdateVertexBuffer(renderer, vertices, sizeof(vertices)) != 0) {
dludwig@8429
  1691
            return -1;
dludwig@8429
  1692
        }
dludwig@8416
  1693
dludwig@8429
  1694
        D3D11_SetPixelShader(
dludwig@8429
  1695
            renderer,
dludwig@8429
  1696
            rendererData->colorPixelShader.Get(),
dludwig@8429
  1697
            nullptr,
dludwig@8429
  1698
            nullptr);
dludwig@8416
  1699
dludwig@8449
  1700
        D3D11_RenderFinishDrawOp(renderer, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, sizeof(vertices) / sizeof(VertexPositionColor));
dludwig@8429
  1701
    }
dludwig@8429
  1702
dludwig@8429
  1703
    return 0;
dludwig@8429
  1704
}
dludwig@8429
  1705
dludwig@8540
  1706
static ID3D11SamplerState *
dludwig@8540
  1707
D3D11_RenderGetSampler(SDL_Renderer * renderer, SDL_Texture * texture)
dludwig@8540
  1708
{
dludwig@8540
  1709
    D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
dludwig@8540
  1710
    D3D11_TextureData *textureData = (D3D11_TextureData *) texture->driverdata;
dludwig@8540
  1711
dludwig@8540
  1712
    switch (textureData->scaleMode) {
dludwig@8540
  1713
        case SDL_D3D11_NEAREST_PIXEL_FILTER:
dludwig@8540
  1714
            return rendererData->nearestPixelSampler.Get();
dludwig@8540
  1715
        case SDL_D3D11_LINEAR_FILTER:
dludwig@8540
  1716
            return rendererData->linearSampler.Get();
dludwig@8540
  1717
        default:
dludwig@8540
  1718
            return NULL;
dludwig@8540
  1719
    }
dludwig@8540
  1720
}
dludwig@8540
  1721
dludwig@8429
  1722
static int
dludwig@8429
  1723
D3D11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
dludwig@8429
  1724
                 const SDL_Rect * srcrect, const SDL_FRect * dstrect)
dludwig@8429
  1725
{
dludwig@8429
  1726
    D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
dludwig@8429
  1727
    D3D11_TextureData *textureData = (D3D11_TextureData *) texture->driverdata;
dludwig@8429
  1728
dludwig@8429
  1729
    D3D11_RenderStartDrawOp(renderer);
dludwig@8442
  1730
    D3D11_RenderSetBlendMode(renderer, texture->blendMode);
dludwig@8448
  1731
dludwig@8448
  1732
    float minu = (float) srcrect->x / texture->w;
dludwig@8448
  1733
    float maxu = (float) (srcrect->x + srcrect->w) / texture->w;
dludwig@8448
  1734
    float minv = (float) srcrect->y / texture->h;
dludwig@8448
  1735
    float maxv = (float) (srcrect->y + srcrect->h) / texture->h;
dludwig@8458
  1736
dludwig@8458
  1737
    float r = 1.0f;
dludwig@8458
  1738
    float g = 1.0f;
dludwig@8458
  1739
    float b = 1.0f;
dludwig@8458
  1740
    float a = 1.0f;
dludwig@8458
  1741
    if (texture->modMode & SDL_TEXTUREMODULATE_COLOR) {
dludwig@8458
  1742
        r = (float)(texture->r / 255.0f);
dludwig@8458
  1743
        g = (float)(texture->g / 255.0f);
dludwig@8458
  1744
        b = (float)(texture->b / 255.0f);
dludwig@8458
  1745
    }
dludwig@8458
  1746
    if (texture->modMode & SDL_TEXTUREMODULATE_ALPHA) {
dludwig@8458
  1747
        a = (float)(texture->a / 255.0f);
dludwig@8458
  1748
    }
dludwig@8416
  1749
dludwig@8429
  1750
    VertexPositionColor vertices[] = {
dludwig@8458
  1751
        {XMFLOAT3(dstrect->x, dstrect->y, 0.0f),                           XMFLOAT2(minu, minv), XMFLOAT4(r, g, b, a)},
dludwig@8458
  1752
        {XMFLOAT3(dstrect->x, dstrect->y + dstrect->h, 0.0f),              XMFLOAT2(minu, maxv), XMFLOAT4(r, g, b, a)},
dludwig@8458
  1753
        {XMFLOAT3(dstrect->x + dstrect->w, dstrect->y, 0.0f),              XMFLOAT2(maxu, minv), XMFLOAT4(r, g, b, a)},
dludwig@8458
  1754
        {XMFLOAT3(dstrect->x + dstrect->w, dstrect->y + dstrect->h, 0.0f), XMFLOAT2(maxu, maxv), XMFLOAT4(r, g, b, a)},
dludwig@8429
  1755
    };
dludwig@8429
  1756
    if (D3D11_UpdateVertexBuffer(renderer, vertices, sizeof(vertices)) != 0) {
dludwig@8429
  1757
        return -1;
dludwig@8429
  1758
    }
dludwig@8418
  1759
dludwig@8540
  1760
    ID3D11SamplerState *textureSampler = D3D11_RenderGetSampler(renderer, texture);
dludwig@8429
  1761
    D3D11_SetPixelShader(
dludwig@8429
  1762
        renderer,
dludwig@8429
  1763
        rendererData->texturePixelShader.Get(),
dludwig@8429
  1764
        textureData->mainTextureResourceView.Get(),
dludwig@8540
  1765
        textureSampler);
dludwig@8416
  1766
dludwig@8449
  1767
    D3D11_RenderFinishDrawOp(renderer, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, sizeof(vertices) / sizeof(VertexPositionColor));
dludwig@8416
  1768
dludwig@8416
  1769
    return 0;
dludwig@8416
  1770
}
dludwig@8416
  1771
dludwig@8454
  1772
static int
dludwig@8455
  1773
D3D11_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
dludwig@8455
  1774
                   const SDL_Rect * srcrect, const SDL_FRect * dstrect,
dludwig@8455
  1775
                   const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip)
dludwig@8455
  1776
{
dludwig@8455
  1777
    D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
dludwig@8455
  1778
    D3D11_TextureData *textureData = (D3D11_TextureData *) texture->driverdata;
dludwig@8455
  1779
dludwig@8455
  1780
    D3D11_RenderStartDrawOp(renderer);
dludwig@8455
  1781
    D3D11_RenderSetBlendMode(renderer, texture->blendMode);
dludwig@8455
  1782
dludwig@8455
  1783
    float minu = (float) srcrect->x / texture->w;
dludwig@8455
  1784
    float maxu = (float) (srcrect->x + srcrect->w) / texture->w;
dludwig@8455
  1785
    float minv = (float) srcrect->y / texture->h;
dludwig@8455
  1786
    float maxv = (float) (srcrect->y + srcrect->h) / texture->h;
dludwig@8455
  1787
dludwig@8458
  1788
    float r = 1.0f;
dludwig@8458
  1789
    float g = 1.0f;
dludwig@8458
  1790
    float b = 1.0f;
dludwig@8458
  1791
    float a = 1.0f;
dludwig@8458
  1792
    if (texture->modMode & SDL_TEXTUREMODULATE_COLOR) {
dludwig@8458
  1793
        r = (float)(texture->r / 255.0f);
dludwig@8458
  1794
        g = (float)(texture->g / 255.0f);
dludwig@8458
  1795
        b = (float)(texture->b / 255.0f);
dludwig@8458
  1796
    }
dludwig@8458
  1797
    if (texture->modMode & SDL_TEXTUREMODULATE_ALPHA) {
dludwig@8458
  1798
        a = (float)(texture->a / 255.0f);
dludwig@8458
  1799
    }
dludwig@8458
  1800
dludwig@8455
  1801
    if (flip & SDL_FLIP_HORIZONTAL) {
dludwig@8455
  1802
        float tmp = maxu;
dludwig@8455
  1803
        maxu = minu;
dludwig@8455
  1804
        minu = tmp;
dludwig@8455
  1805
    }
dludwig@8455
  1806
    if (flip & SDL_FLIP_VERTICAL) {
dludwig@8455
  1807
        float tmp = maxv;
dludwig@8455
  1808
        maxv = minv;
dludwig@8455
  1809
        minv = tmp;
dludwig@8455
  1810
    }
dludwig@8456
  1811
dludwig@8456
  1812
    XMFLOAT4X4 oldModelMatrix = rendererData->vertexShaderConstantsData.model;
dludwig@8456
  1813
    XMStoreFloat4x4(
dludwig@8456
  1814
        &rendererData->vertexShaderConstantsData.model,
dludwig@8456
  1815
        XMMatrixMultiply(
dludwig@8456
  1816
            XMMatrixRotationZ((float)(XM_PI * (float) angle / 180.0f)),
dludwig@8456
  1817
            XMMatrixTranslation(dstrect->x + center->x, dstrect->y + center->y, 0)
dludwig@8456
  1818
            ));
dludwig@8456
  1819
dludwig@8456
  1820
    const float minx = -center->x;
dludwig@8456
  1821
    const float maxx = dstrect->w - center->x;
dludwig@8456
  1822
    const float miny = -center->y;
dludwig@8456
  1823
    const float maxy = dstrect->h - center->y;
dludwig@8455
  1824
dludwig@8455
  1825
    VertexPositionColor vertices[] = {
dludwig@8458
  1826
        {XMFLOAT3(minx, miny, 0.0f), XMFLOAT2(minu, minv), XMFLOAT4(r, g, b, a)},
dludwig@8458
  1827
        {XMFLOAT3(minx, maxy, 0.0f), XMFLOAT2(minu, maxv), XMFLOAT4(r, g, b, a)},
dludwig@8458
  1828
        {XMFLOAT3(maxx, miny, 0.0f), XMFLOAT2(maxu, minv), XMFLOAT4(r, g, b, a)},
dludwig@8458
  1829
        {XMFLOAT3(maxx, maxy, 0.0f), XMFLOAT2(maxu, maxv), XMFLOAT4(r, g, b, a)},
dludwig@8455
  1830
    };
dludwig@8455
  1831
    if (D3D11_UpdateVertexBuffer(renderer, vertices, sizeof(vertices)) != 0) {
dludwig@8455
  1832
        return -1;
dludwig@8455
  1833
    }
dludwig@8455
  1834
dludwig@8540
  1835
    ID3D11SamplerState *textureSampler = D3D11_RenderGetSampler(renderer, texture);
dludwig@8455
  1836
    D3D11_SetPixelShader(
dludwig@8455
  1837
        renderer,
dludwig@8455
  1838
        rendererData->texturePixelShader.Get(),
dludwig@8455
  1839
        textureData->mainTextureResourceView.Get(),
dludwig@8540
  1840
        textureSampler);
dludwig@8455
  1841
dludwig@8455
  1842
    D3D11_RenderFinishDrawOp(renderer, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, sizeof(vertices) / sizeof(VertexPositionColor));
dludwig@8456
  1843
dludwig@8456
  1844
    rendererData->vertexShaderConstantsData.model = oldModelMatrix;
dludwig@8455
  1845
dludwig@8455
  1846
    return 0;
dludwig@8455
  1847
}
dludwig@8455
  1848
dludwig@8455
  1849
static int
dludwig@8454
  1850
D3D11_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
dludwig@8454
  1851
                       Uint32 format, void * pixels, int pitch)
dludwig@8454
  1852
{
dludwig@8454
  1853
    D3D11_RenderData * data = (D3D11_RenderData *) renderer->driverdata;
dludwig@8454
  1854
    HRESULT result = S_OK;
dludwig@8454
  1855
dludwig@8454
  1856
    // Retrieve a pointer to the back buffer:
dludwig@8454
  1857
    ComPtr<ID3D11Texture2D> backBuffer;
dludwig@8454
  1858
    result = data->swapChain->GetBuffer(
dludwig@8454
  1859
        0,
dludwig@8454
  1860
        __uuidof(ID3D11Texture2D),
dludwig@8454
  1861
        &backBuffer
dludwig@8454
  1862
        );
dludwig@8454
  1863
    if (FAILED(result)) {
dludwig@8553
  1864
        WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGISwapChain1::GetBuffer [get back buffer]", result);
dludwig@8454
  1865
        return -1;
dludwig@8454
  1866
    }
dludwig@8454
  1867
dludwig@8454
  1868
    // Create a staging texture to copy the screen's data to:
dludwig@8454
  1869
    ComPtr<ID3D11Texture2D> stagingTexture;
dludwig@8454
  1870
    D3D11_TEXTURE2D_DESC stagingTextureDesc;
dludwig@8454
  1871
    backBuffer->GetDesc(&stagingTextureDesc);
dludwig@8454
  1872
    stagingTextureDesc.Width = rect->w;
dludwig@8454
  1873
    stagingTextureDesc.Height = rect->h;
dludwig@8454
  1874
    stagingTextureDesc.BindFlags = 0;
dludwig@8454
  1875
    stagingTextureDesc.MiscFlags = 0;
dludwig@8454
  1876
    stagingTextureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
dludwig@8454
  1877
    stagingTextureDesc.Usage = D3D11_USAGE_STAGING;
dludwig@8454
  1878
    result = data->d3dDevice->CreateTexture2D(
dludwig@8454
  1879
        &stagingTextureDesc,
dludwig@8454
  1880
        NULL,
dludwig@8454
  1881
        &stagingTexture);
dludwig@8454
  1882
    if (FAILED(result)) {
dludwig@8553
  1883
        WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateTexture2D [create staging texture]", result);
dludwig@8454
  1884
        return -1;
dludwig@8454
  1885
    }
dludwig@8454
  1886
dludwig@8454
  1887
    // Copy the desired portion of the back buffer to the staging texture:
dludwig@8454
  1888
    D3D11_BOX srcBox;
dludwig@8548
  1889
    switch (D3D11_GetRotationForOrientation(data->orientation)) {
dludwig@8548
  1890
        case DXGI_MODE_ROTATION_IDENTITY:
dludwig@8548
  1891
            srcBox.left = rect->x;
dludwig@8548
  1892
            srcBox.right = rect->x + rect->w;
dludwig@8548
  1893
            srcBox.top = rect->y;
dludwig@8548
  1894
            srcBox.bottom = rect->y + rect->h;
dludwig@8548
  1895
            break;
dludwig@8548
  1896
        case DXGI_MODE_ROTATION_ROTATE270:
dludwig@8548
  1897
            srcBox.left = rect->y;
dludwig@8548
  1898
            srcBox.right = rect->y + rect->h;
dludwig@8548
  1899
            srcBox.top = renderer->viewport.w - rect->x - rect->w;
dludwig@8548
  1900
            srcBox.bottom = renderer->viewport.w - rect->x;
dludwig@8548
  1901
            break;
dludwig@8548
  1902
        case DXGI_MODE_ROTATION_ROTATE180:
dludwig@8548
  1903
            srcBox.left = renderer->viewport.w - rect->x - rect->w;
dludwig@8548
  1904
            srcBox.right = renderer->viewport.w - rect->x;
dludwig@8548
  1905
            srcBox.top = renderer->viewport.h - rect->y - rect->h;
dludwig@8548
  1906
            srcBox.bottom = renderer->viewport.h - rect->y;
dludwig@8548
  1907
            break;
dludwig@8548
  1908
        case DXGI_MODE_ROTATION_ROTATE90:
dludwig@8548
  1909
            srcBox.left = renderer->viewport.h - rect->y - rect->h;
dludwig@8548
  1910
            srcBox.right = renderer->viewport.h - rect->y;
dludwig@8548
  1911
            srcBox.top = rect->x;
dludwig@8548
  1912
            srcBox.bottom = rect->x + rect->h;
dludwig@8548
  1913
            break;
dludwig@8548
  1914
        default:
dludwig@8548
  1915
            return SDL_SetError("The physical display is in an unknown or unsupported orientation");
dludwig@8548
  1916
    }
dludwig@8454
  1917
    srcBox.front = 0;
dludwig@8454
  1918
    srcBox.back = 1;
dludwig@8454
  1919
    data->d3dContext->CopySubresourceRegion(
dludwig@8454
  1920
        stagingTexture.Get(),
dludwig@8454
  1921
        D3D11CalcSubresource(0, 0, 0),
dludwig@8454
  1922
        0, 0, 0,
dludwig@8454
  1923
        backBuffer.Get(),
dludwig@8454
  1924
        D3D11CalcSubresource(0, 0, 0),
dludwig@8454
  1925
        &srcBox);
dludwig@8454
  1926
dludwig@8454
  1927
    // Map the staging texture's data to CPU-accessible memory:
dludwig@8454
  1928
    D3D11_MAPPED_SUBRESOURCE textureMemory = {0};
dludwig@8454
  1929
    result = data->d3dContext->Map(
dludwig@8454
  1930
        stagingTexture.Get(),
dludwig@8454
  1931
        D3D11CalcSubresource(0, 0, 0),
dludwig@8454
  1932
        D3D11_MAP_READ,
dludwig@8454
  1933
        0,
dludwig@8454
  1934
        &textureMemory);
dludwig@8454
  1935
    if (FAILED(result)) {
dludwig@8553
  1936
        WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11DeviceContext1::Map [map staging texture]", result);
dludwig@8454
  1937
        return -1;
dludwig@8454
  1938
    }
dludwig@8454
  1939
dludwig@8454
  1940
    // Copy the data into the desired buffer, converting pixels to the
dludwig@8454
  1941
    // desired format at the same time:
dludwig@8454
  1942
    if (SDL_ConvertPixels(
dludwig@8454
  1943
        rect->w, rect->h,
dludwig@8454
  1944
        DXGIFormatToSDLPixelFormat(stagingTextureDesc.Format),
dludwig@8454
  1945
        textureMemory.pData,
dludwig@8454
  1946
        textureMemory.RowPitch,
dludwig@8454
  1947
        format,
dludwig@8454
  1948
        pixels,
dludwig@8454
  1949
        pitch) != 0)
dludwig@8454
  1950
    {
dludwig@8454
  1951
        // When SDL_ConvertPixels fails, it'll have already set the format.
dludwig@8454
  1952
        // Get the error message, and attach some extra data to it.
dludwig@8454
  1953
        std::string errorMessage = string(__FUNCTION__ ", Convert Pixels failed: ") + SDL_GetError();
dludwig@8556
  1954
        return SDL_SetError(errorMessage.c_str());
dludwig@8454
  1955
    }
dludwig@8454
  1956
dludwig@8454
  1957
    // Unmap the texture:
dludwig@8454
  1958
    data->d3dContext->Unmap(
dludwig@8454
  1959
        stagingTexture.Get(),
dludwig@8454
  1960
        D3D11CalcSubresource(0, 0, 0));
dludwig@8454
  1961
dludwig@8454
  1962
    // All done.  The staging texture will be cleaned up in it's container
dludwig@8454
  1963
    // ComPtr<>'s destructor.
dludwig@8454
  1964
    return 0;
dludwig@8454
  1965
}
dludwig@8454
  1966
dludwig@8401
  1967
static void
dludwig@8401
  1968
D3D11_RenderPresent(SDL_Renderer * renderer)
dludwig@8401
  1969
{
dludwig@8401
  1970
    D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
dludwig@8401
  1971
dludwig@8401
  1972
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
dludwig@8401
  1973
    // The first argument instructs DXGI to block until VSync, putting the application
dludwig@8401
  1974
    // to sleep until the next VSync. This ensures we don't waste any cycles rendering
dludwig@8401
  1975
    // frames that will never be displayed to the screen.
dludwig@8401
  1976
    HRESULT hr = data->swapChain->Present(1, 0);
dludwig@8401
  1977
#else
dludwig@8401
  1978
    // The application may optionally specify "dirty" or "scroll"
dludwig@8401
  1979
    // rects to improve efficiency in certain scenarios.
dludwig@8401
  1980
    // This option is not available on Windows Phone 8, to note.
dludwig@8401
  1981
    DXGI_PRESENT_PARAMETERS parameters = {0};
dludwig@8401
  1982
    parameters.DirtyRectsCount = 0;
dludwig@8401
  1983
    parameters.pDirtyRects = nullptr;
dludwig@8401
  1984
    parameters.pScrollRect = nullptr;
dludwig@8401
  1985
    parameters.pScrollOffset = nullptr;
dludwig@8401
  1986
    
dludwig@8401
  1987
    // The first argument instructs DXGI to block until VSync, putting the application
dludwig@8401
  1988
    // to sleep until the next VSync. This ensures we don't waste any cycles rendering
dludwig@8401
  1989
    // frames that will never be displayed to the screen.
dludwig@8401
  1990
    HRESULT hr = data->swapChain->Present1(1, 0, &parameters);
dludwig@8401
  1991
#endif
dludwig@8401
  1992
dludwig@8401
  1993
    // Discard the contents of the render target.
dludwig@8401
  1994
    // This is a valid operation only when the existing contents will be entirely
dludwig@8401
  1995
    // overwritten. If dirty or scroll rects are used, this call should be removed.
dludwig@8459
  1996
    data->d3dContext->DiscardView(data->mainRenderTargetView.Get());
dludwig@8401
  1997
dludwig@8401
  1998
    // If the device was removed either by a disconnect or a driver upgrade, we 
dludwig@8401
  1999
    // must recreate all device resources.
dludwig@8414
  2000
    //
dludwig@8414
  2001
    // TODO, WinRT: consider throwing an exception if D3D11_RenderPresent fails, especially if there is a way to salvedge debug info from users' machines
dludwig@8401
  2002
    if (hr == DXGI_ERROR_DEVICE_REMOVED)
dludwig@8401
  2003
    {
dludwig@8414
  2004
        hr = D3D11_HandleDeviceLost(renderer);
dludwig@8414
  2005
        if (FAILED(hr)) {
dludwig@8554
  2006
            /* D3D11_HandleDeviceLost will set the SDL error */
dludwig@8414
  2007
        }
dludwig@8401
  2008
    }
dludwig@8401
  2009
    else
dludwig@8401
  2010
    {
dludwig@8553
  2011
        WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11DeviceContext1::DiscardView", hr);
dludwig@8401
  2012
    }
dludwig@8401
  2013
}
dludwig@8401
  2014
dludwig@8400
  2015
#endif /* SDL_VIDEO_RENDER_D3D && !SDL_RENDER_DISABLED */
dludwig@8400
  2016
dludwig@8400
  2017
/* vi: set ts=4 sw=4 expandtab: */