src/render/direct3d/SDL_render_d3d.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 28 Aug 2017 01:42:18 -0700
changeset 11386 d5c2d689bf6d
parent 11330 6ae35c5f7f7b
child 11702 cf166abbde4a
permissions -rw-r--r--
Fixed build when Wayland is dynamically loaded
slouken@1895
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@10737
     3
  Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
slouken@1895
     4
slouken@5535
     5
  This software is provided 'as-is', without any express or implied
slouken@5535
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     7
  arising from the use of this software.
slouken@1895
     8
slouken@5535
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
    10
  including commercial applications, and to alter it and redistribute it
slouken@5535
    11
  freely, subject to the following restrictions:
slouken@1895
    12
slouken@5535
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@5535
    14
     claim that you wrote the original software. If you use this software
slouken@5535
    15
     in a product, an acknowledgment in the product documentation would be
slouken@5535
    16
     appreciated but is not required.
slouken@5535
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@5535
    18
     misrepresented as being the original software.
slouken@5535
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@1895
    20
*/
icculus@8093
    21
#include "../../SDL_internal.h"
slouken@1895
    22
slouken@8193
    23
#include "SDL_render.h"
slouken@8193
    24
#include "SDL_system.h"
slouken@8193
    25
slouken@5226
    26
#if SDL_VIDEO_RENDER_D3D && !SDL_RENDER_DISABLED
slouken@5226
    27
slouken@5154
    28
#include "../../core/windows/SDL_windows.h"
slouken@5154
    29
slouken@5484
    30
#include "SDL_hints.h"
slouken@5154
    31
#include "SDL_loadso.h"
slouken@5154
    32
#include "SDL_syswm.h"
slouken@5154
    33
#include "../SDL_sysrender.h"
slouken@8599
    34
#include "../SDL_d3dmath.h"
slouken@7762
    35
#include "../../video/windows/SDL_windowsvideo.h"
slouken@5154
    36
slouken@5154
    37
#if SDL_VIDEO_RENDER_D3D
slouken@5154
    38
#define D3D_DEBUG_INFO
slouken@5154
    39
#include <d3d9.h>
slouken@5154
    40
#endif
slouken@1895
    41
gabomdq@6320
    42
slouken@3556
    43
#ifdef ASSEMBLE_SHADER
alfred@8969
    44
#pragma comment(lib, "d3dx9.lib")
alfred@8969
    45
slouken@7191
    46
/**************************************************************************
slouken@7191
    47
 * ID3DXBuffer:
slouken@7191
    48
 * ------------
slouken@7191
    49
 * The buffer object is used by D3DX to return arbitrary size data.
slouken@7191
    50
 *
slouken@7191
    51
 * GetBufferPointer -
slouken@7191
    52
 *    Returns a pointer to the beginning of the buffer.
slouken@7191
    53
 *
slouken@7191
    54
 * GetBufferSize -
slouken@7191
    55
 *    Returns the size of the buffer, in bytes.
slouken@7191
    56
 **************************************************************************/
slouken@3556
    57
slouken@3556
    58
typedef interface ID3DXBuffer ID3DXBuffer;
slouken@3556
    59
typedef interface ID3DXBuffer *LPD3DXBUFFER;
slouken@3556
    60
slouken@7191
    61
/* {8BA5FB08-5195-40e2-AC58-0D989C3A0102} */
slouken@7191
    62
DEFINE_GUID(IID_ID3DXBuffer,
slouken@3556
    63
0x8ba5fb08, 0x5195, 0x40e2, 0xac, 0x58, 0xd, 0x98, 0x9c, 0x3a, 0x1, 0x2);
slouken@3556
    64
slouken@3556
    65
#undef INTERFACE
slouken@3556
    66
#define INTERFACE ID3DXBuffer
slouken@3556
    67
slouken@3556
    68
typedef interface ID3DXBuffer {
slouken@3556
    69
    const struct ID3DXBufferVtbl FAR* lpVtbl;
slouken@3556
    70
} ID3DXBuffer;
slouken@3556
    71
typedef const struct ID3DXBufferVtbl ID3DXBufferVtbl;
slouken@3556
    72
const struct ID3DXBufferVtbl
slouken@3556
    73
{
slouken@7191
    74
    /* IUnknown */
slouken@3556
    75
    STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE;
slouken@3556
    76
    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
slouken@3556
    77
    STDMETHOD_(ULONG, Release)(THIS) PURE;
slouken@3556
    78
slouken@7191
    79
    /* ID3DXBuffer */
slouken@3556
    80
    STDMETHOD_(LPVOID, GetBufferPointer)(THIS) PURE;
slouken@3556
    81
    STDMETHOD_(DWORD, GetBufferSize)(THIS) PURE;
slouken@3556
    82
};
slouken@3556
    83
slouken@3556
    84
HRESULT WINAPI
slouken@3556
    85
    D3DXAssembleShader(
slouken@3556
    86
        LPCSTR                          pSrcData,
slouken@3556
    87
        UINT                            SrcDataLen,
slouken@3556
    88
        CONST LPVOID*                   pDefines,
slouken@3556
    89
        LPVOID                          pInclude,
slouken@3556
    90
        DWORD                           Flags,
slouken@3556
    91
        LPD3DXBUFFER*                   ppShader,
slouken@3556
    92
        LPD3DXBUFFER*                   ppErrorMsgs);
slouken@3556
    93
slouken@7505
    94
static void PrintShaderData(LPDWORD shader_data, DWORD shader_size)
slouken@7505
    95
{
slouken@7505
    96
    OutputDebugStringA("const DWORD shader_data[] = {\n\t");
slouken@7505
    97
    {
slouken@7505
    98
        SDL_bool newline = SDL_FALSE;
slouken@7505
    99
        unsigned i;
slouken@7505
   100
        for (i = 0; i < shader_size / sizeof(DWORD); ++i) {
slouken@7505
   101
            char dword[11];
slouken@7505
   102
            if (i > 0) {
slouken@7505
   103
                if ((i%6) == 0) {
slouken@7505
   104
                    newline = SDL_TRUE;
slouken@7505
   105
                }
slouken@7505
   106
                if (newline) {
slouken@7505
   107
                    OutputDebugStringA(",\n    ");
slouken@7505
   108
                    newline = SDL_FALSE;
slouken@7505
   109
                } else {
slouken@7505
   110
                    OutputDebugStringA(", ");
slouken@7505
   111
                }
slouken@7505
   112
            }
slouken@7505
   113
            SDL_snprintf(dword, sizeof(dword), "0x%8.8x", shader_data[i]);
slouken@7505
   114
            OutputDebugStringA(dword);
slouken@7505
   115
        }
slouken@7505
   116
        OutputDebugStringA("\n};\n");
slouken@7505
   117
    }
slouken@7505
   118
}
slouken@7505
   119
slouken@3556
   120
#endif /* ASSEMBLE_SHADER */
slouken@3556
   121
slouken@3556
   122
slouken@1895
   123
/* Direct3D renderer implementation */
slouken@1895
   124
slouken@1913
   125
static SDL_Renderer *D3D_CreateRenderer(SDL_Window * window, Uint32 flags);
slouken@5297
   126
static void D3D_WindowEvent(SDL_Renderer * renderer,
slouken@5297
   127
                            const SDL_WindowEvent *event);
slouken@11282
   128
static SDL_bool D3D_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode);
slouken@1913
   129
static int D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
slouken@8792
   130
static int D3D_RecreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
slouken@1913
   131
static int D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1913
   132
                             const SDL_Rect * rect, const void *pixels,
slouken@1913
   133
                             int pitch);
slouken@7761
   134
static int D3D_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@7761
   135
                                const SDL_Rect * rect,
slouken@7761
   136
                                const Uint8 *Yplane, int Ypitch,
slouken@7761
   137
                                const Uint8 *Uplane, int Upitch,
slouken@7761
   138
                                const Uint8 *Vplane, int Vpitch);
slouken@1913
   139
static int D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@5156
   140
                           const SDL_Rect * rect, void **pixels, int *pitch);
slouken@1913
   141
static void D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
slouken@8228
   142
static int D3D_SetRenderTargetInternal(SDL_Renderer * renderer, SDL_Texture * texture);
slouken@6247
   143
static int D3D_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture);
slouken@5297
   144
static int D3D_UpdateViewport(SDL_Renderer * renderer);
slouken@7141
   145
static int D3D_UpdateClipRect(SDL_Renderer * renderer);
slouken@5297
   146
static int D3D_RenderClear(SDL_Renderer * renderer);
slouken@3599
   147
static int D3D_RenderDrawPoints(SDL_Renderer * renderer,
slouken@6528
   148
                                const SDL_FPoint * points, int count);
slouken@3599
   149
static int D3D_RenderDrawLines(SDL_Renderer * renderer,
slouken@6528
   150
                               const SDL_FPoint * points, int count);
slouken@3599
   151
static int D3D_RenderFillRects(SDL_Renderer * renderer,
slouken@6528
   152
                               const SDL_FRect * rects, int count);
slouken@1913
   153
static int D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@6528
   154
                          const SDL_Rect * srcrect, const SDL_FRect * dstrect);
gabomdq@6320
   155
static int D3D_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@6528
   156
                          const SDL_Rect * srcrect, const SDL_FRect * dstrect,
slouken@6528
   157
                          const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip);
slouken@3427
   158
static int D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
slouken@3480
   159
                                Uint32 format, void * pixels, int pitch);
slouken@1913
   160
static void D3D_RenderPresent(SDL_Renderer * renderer);
slouken@1913
   161
static void D3D_DestroyTexture(SDL_Renderer * renderer,
slouken@1913
   162
                               SDL_Texture * texture);
slouken@1913
   163
static void D3D_DestroyRenderer(SDL_Renderer * renderer);
slouken@1895
   164
slouken@1895
   165
slouken@1913
   166
SDL_RenderDriver D3D_RenderDriver = {
slouken@1913
   167
    D3D_CreateRenderer,
slouken@1895
   168
    {
slouken@5186
   169
     "direct3d",
slouken@6237
   170
     (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE),
slouken@5156
   171
     1,
slouken@5156
   172
     {SDL_PIXELFORMAT_ARGB8888},
slouken@1895
   173
     0,
slouken@1895
   174
     0}
slouken@1895
   175
};
slouken@1895
   176
slouken@1895
   177
typedef struct
slouken@1895
   178
{
slouken@5154
   179
    void* d3dDLL;
slouken@2973
   180
    IDirect3D9 *d3d;
slouken@1895
   181
    IDirect3DDevice9 *device;
slouken@3527
   182
    UINT adapter;
slouken@1975
   183
    D3DPRESENT_PARAMETERS pparams;
slouken@5297
   184
    SDL_bool updateSize;
slouken@1900
   185
    SDL_bool beginScene;
slouken@7502
   186
    SDL_bool enableSeparateAlphaBlend;
slouken@7505
   187
    D3DTEXTUREFILTERTYPE scaleMode[8];
slouken@6232
   188
    IDirect3DSurface9 *defaultRenderTarget;
slouken@6232
   189
    IDirect3DSurface9 *currentRenderTarget;
gabomdq@6320
   190
    void* d3dxDLL;
slouken@7505
   191
    LPDIRECT3DPIXELSHADER9 ps_yuv;
slouken@1913
   192
} D3D_RenderData;
slouken@1895
   193
slouken@1895
   194
typedef struct
slouken@1895
   195
{
slouken@8822
   196
    SDL_bool dirty;
slouken@9074
   197
    int w, h;
slouken@9074
   198
    DWORD usage;
slouken@9074
   199
    Uint32 format;
slouken@1903
   200
    IDirect3DTexture9 *texture;
slouken@8792
   201
    IDirect3DTexture9 *staging;
slouken@8792
   202
} D3D_TextureRep;
slouken@8792
   203
slouken@8792
   204
typedef struct
slouken@8792
   205
{
slouken@8792
   206
    D3D_TextureRep texture;
slouken@5484
   207
    D3DTEXTUREFILTERTYPE scaleMode;
slouken@7505
   208
slouken@7505
   209
    /* YV12 texture support */
slouken@7505
   210
    SDL_bool yuv;
slouken@8792
   211
    D3D_TextureRep utexture;
slouken@8792
   212
    D3D_TextureRep vtexture;
slouken@7505
   213
    Uint8 *pixels;
slouken@7505
   214
    int pitch;
slouken@7505
   215
    SDL_Rect locked_rect;
slouken@1913
   216
} D3D_TextureData;
slouken@1895
   217
slouken@1903
   218
typedef struct
slouken@1903
   219
{
slouken@1903
   220
    float x, y, z;
slouken@1987
   221
    DWORD color;
slouken@1904
   222
    float u, v;
slouken@1903
   223
} Vertex;
slouken@1903
   224
icculus@7037
   225
static int
slouken@1900
   226
D3D_SetError(const char *prefix, HRESULT result)
slouken@1900
   227
{
slouken@1900
   228
    const char *error;
slouken@1900
   229
slouken@1900
   230
    switch (result) {
slouken@1900
   231
    case D3DERR_WRONGTEXTUREFORMAT:
slouken@1900
   232
        error = "WRONGTEXTUREFORMAT";
slouken@1900
   233
        break;
slouken@1900
   234
    case D3DERR_UNSUPPORTEDCOLOROPERATION:
slouken@1900
   235
        error = "UNSUPPORTEDCOLOROPERATION";
slouken@1900
   236
        break;
slouken@1900
   237
    case D3DERR_UNSUPPORTEDCOLORARG:
slouken@1900
   238
        error = "UNSUPPORTEDCOLORARG";
slouken@1900
   239
        break;
slouken@1900
   240
    case D3DERR_UNSUPPORTEDALPHAOPERATION:
slouken@1900
   241
        error = "UNSUPPORTEDALPHAOPERATION";
slouken@1900
   242
        break;
slouken@1900
   243
    case D3DERR_UNSUPPORTEDALPHAARG:
slouken@1900
   244
        error = "UNSUPPORTEDALPHAARG";
slouken@1900
   245
        break;
slouken@1900
   246
    case D3DERR_TOOMANYOPERATIONS:
slouken@1900
   247
        error = "TOOMANYOPERATIONS";
slouken@1900
   248
        break;
slouken@1900
   249
    case D3DERR_CONFLICTINGTEXTUREFILTER:
slouken@1900
   250
        error = "CONFLICTINGTEXTUREFILTER";
slouken@1900
   251
        break;
slouken@1900
   252
    case D3DERR_UNSUPPORTEDFACTORVALUE:
slouken@1900
   253
        error = "UNSUPPORTEDFACTORVALUE";
slouken@1900
   254
        break;
slouken@1900
   255
    case D3DERR_CONFLICTINGRENDERSTATE:
slouken@1900
   256
        error = "CONFLICTINGRENDERSTATE";
slouken@1900
   257
        break;
slouken@1900
   258
    case D3DERR_UNSUPPORTEDTEXTUREFILTER:
slouken@1900
   259
        error = "UNSUPPORTEDTEXTUREFILTER";
slouken@1900
   260
        break;
slouken@1900
   261
    case D3DERR_CONFLICTINGTEXTUREPALETTE:
slouken@1900
   262
        error = "CONFLICTINGTEXTUREPALETTE";
slouken@1900
   263
        break;
slouken@1900
   264
    case D3DERR_DRIVERINTERNALERROR:
slouken@1900
   265
        error = "DRIVERINTERNALERROR";
slouken@1900
   266
        break;
slouken@1900
   267
    case D3DERR_NOTFOUND:
slouken@1900
   268
        error = "NOTFOUND";
slouken@1900
   269
        break;
slouken@1900
   270
    case D3DERR_MOREDATA:
slouken@1900
   271
        error = "MOREDATA";
slouken@1900
   272
        break;
slouken@1900
   273
    case D3DERR_DEVICELOST:
slouken@1900
   274
        error = "DEVICELOST";
slouken@1900
   275
        break;
slouken@1900
   276
    case D3DERR_DEVICENOTRESET:
slouken@1900
   277
        error = "DEVICENOTRESET";
slouken@1900
   278
        break;
slouken@1900
   279
    case D3DERR_NOTAVAILABLE:
slouken@1900
   280
        error = "NOTAVAILABLE";
slouken@1900
   281
        break;
slouken@1900
   282
    case D3DERR_OUTOFVIDEOMEMORY:
slouken@1900
   283
        error = "OUTOFVIDEOMEMORY";
slouken@1900
   284
        break;
slouken@1900
   285
    case D3DERR_INVALIDDEVICE:
slouken@1900
   286
        error = "INVALIDDEVICE";
slouken@1900
   287
        break;
slouken@1900
   288
    case D3DERR_INVALIDCALL:
slouken@1900
   289
        error = "INVALIDCALL";
slouken@1900
   290
        break;
slouken@1900
   291
    case D3DERR_DRIVERINVALIDCALL:
slouken@1900
   292
        error = "DRIVERINVALIDCALL";
slouken@1900
   293
        break;
slouken@1900
   294
    case D3DERR_WASSTILLDRAWING:
slouken@1900
   295
        error = "WASSTILLDRAWING";
slouken@1900
   296
        break;
slouken@1900
   297
    default:
slouken@1900
   298
        error = "UNKNOWN";
slouken@1900
   299
        break;
slouken@1900
   300
    }
icculus@7037
   301
    return SDL_SetError("%s: %s", prefix, error);
slouken@1900
   302
}
slouken@1900
   303
slouken@1903
   304
static D3DFORMAT
slouken@1903
   305
PixelFormatToD3DFMT(Uint32 format)
slouken@1895
   306
{
slouken@1903
   307
    switch (format) {
slouken@1965
   308
    case SDL_PIXELFORMAT_RGB565:
slouken@1903
   309
        return D3DFMT_R5G6B5;
slouken@1965
   310
    case SDL_PIXELFORMAT_RGB888:
slouken@1903
   311
        return D3DFMT_X8R8G8B8;
slouken@1965
   312
    case SDL_PIXELFORMAT_ARGB8888:
slouken@1903
   313
        return D3DFMT_A8R8G8B8;
slouken@7505
   314
    case SDL_PIXELFORMAT_YV12:
slouken@7505
   315
    case SDL_PIXELFORMAT_IYUV:
slouken@7505
   316
        return D3DFMT_L8;
slouken@1903
   317
    default:
slouken@1903
   318
        return D3DFMT_UNKNOWN;
slouken@1903
   319
    }
slouken@1895
   320
}
slouken@1895
   321
slouken@5156
   322
static Uint32
slouken@5156
   323
D3DFMTToPixelFormat(D3DFORMAT format)
slouken@2973
   324
{
slouken@5156
   325
    switch (format) {
slouken@5156
   326
    case D3DFMT_R5G6B5:
slouken@5156
   327
        return SDL_PIXELFORMAT_RGB565;
slouken@5156
   328
    case D3DFMT_X8R8G8B8:
slouken@5156
   329
        return SDL_PIXELFORMAT_RGB888;
slouken@5156
   330
    case D3DFMT_A8R8G8B8:
slouken@5156
   331
        return SDL_PIXELFORMAT_ARGB8888;
slouken@5156
   332
    default:
slouken@5156
   333
        return SDL_PIXELFORMAT_UNKNOWN;
slouken@2973
   334
    }
slouken@1895
   335
}
slouken@1895
   336
slouken@7648
   337
static void
slouken@7648
   338
D3D_InitRenderState(D3D_RenderData *data)
slouken@7648
   339
{
slouken@7651
   340
    D3DMATRIX matrix;
slouken@7651
   341
slouken@7651
   342
    IDirect3DDevice9 *device = data->device;
slouken@7648
   343
slouken@7648
   344
    IDirect3DDevice9_SetVertexShader(device, NULL);
slouken@7648
   345
    IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1);
slouken@7648
   346
    IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_FALSE);
slouken@7648
   347
    IDirect3DDevice9_SetRenderState(device, D3DRS_CULLMODE, D3DCULL_NONE);
slouken@7648
   348
    IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
slouken@7648
   349
slouken@7648
   350
    /* Enable color modulation by diffuse color */
slouken@7648
   351
    IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP,
slouken@7648
   352
                                          D3DTOP_MODULATE);
slouken@7648
   353
    IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1,
slouken@7648
   354
                                          D3DTA_TEXTURE);
slouken@7648
   355
    IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG2,
slouken@7648
   356
                                          D3DTA_DIFFUSE);
slouken@7648
   357
slouken@7648
   358
    /* Enable alpha modulation by diffuse alpha */
slouken@7648
   359
    IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_ALPHAOP,
slouken@7648
   360
                                          D3DTOP_MODULATE);
slouken@7648
   361
    IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_ALPHAARG1,
slouken@7648
   362
                                          D3DTA_TEXTURE);
slouken@7648
   363
    IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_ALPHAARG2,
slouken@7648
   364
                                          D3DTA_DIFFUSE);
slouken@7648
   365
slouken@7648
   366
    /* Enable separate alpha blend function, if possible */
slouken@7648
   367
    if (data->enableSeparateAlphaBlend) {
slouken@7648
   368
        IDirect3DDevice9_SetRenderState(device, D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
slouken@7648
   369
    }
slouken@7648
   370
slouken@7648
   371
    /* Disable second texture stage, since we're done */
slouken@7648
   372
    IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP,
slouken@7648
   373
                                          D3DTOP_DISABLE);
slouken@7648
   374
    IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_ALPHAOP,
slouken@7648
   375
                                          D3DTOP_DISABLE);
slouken@7648
   376
slouken@7648
   377
    /* Set an identity world and view matrix */
slouken@7648
   378
    matrix.m[0][0] = 1.0f;
slouken@7648
   379
    matrix.m[0][1] = 0.0f;
slouken@7648
   380
    matrix.m[0][2] = 0.0f;
slouken@7648
   381
    matrix.m[0][3] = 0.0f;
slouken@7648
   382
    matrix.m[1][0] = 0.0f;
slouken@7648
   383
    matrix.m[1][1] = 1.0f;
slouken@7648
   384
    matrix.m[1][2] = 0.0f;
slouken@7648
   385
    matrix.m[1][3] = 0.0f;
slouken@7648
   386
    matrix.m[2][0] = 0.0f;
slouken@7648
   387
    matrix.m[2][1] = 0.0f;
slouken@7648
   388
    matrix.m[2][2] = 1.0f;
slouken@7648
   389
    matrix.m[2][3] = 0.0f;
slouken@7648
   390
    matrix.m[3][0] = 0.0f;
slouken@7648
   391
    matrix.m[3][1] = 0.0f;
slouken@7648
   392
    matrix.m[3][2] = 0.0f;
slouken@7648
   393
    matrix.m[3][3] = 1.0f;
slouken@7648
   394
    IDirect3DDevice9_SetTransform(device, D3DTS_WORLD, &matrix);
slouken@7648
   395
    IDirect3DDevice9_SetTransform(device, D3DTS_VIEW, &matrix);
slouken@7648
   396
slouken@7648
   397
    /* Reset our current scale mode */
slouken@7648
   398
    SDL_memset(data->scaleMode, 0xFF, sizeof(data->scaleMode));
slouken@7648
   399
slouken@7648
   400
    /* Start the render with beginScene */
slouken@7648
   401
    data->beginScene = SDL_TRUE;
slouken@7648
   402
}
slouken@7648
   403
slouken@5297
   404
static int
slouken@5297
   405
D3D_Reset(SDL_Renderer * renderer)
slouken@5297
   406
{
slouken@5297
   407
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@5297
   408
    HRESULT result;
slouken@8207
   409
    SDL_Texture *texture;
slouken@5297
   410
slouken@6860
   411
    /* Release the default render target before reset */
slouken@6895
   412
    if (data->defaultRenderTarget) {
slouken@6895
   413
        IDirect3DSurface9_Release(data->defaultRenderTarget);
slouken@6895
   414
        data->defaultRenderTarget = NULL;
slouken@6895
   415
    }
slouken@8224
   416
    if (data->currentRenderTarget != NULL) {
slouken@8224
   417
        IDirect3DSurface9_Release(data->currentRenderTarget);
slouken@8224
   418
        data->currentRenderTarget = NULL;
slouken@8224
   419
    }
slouken@6860
   420
slouken@8207
   421
    /* Release application render targets */
slouken@8207
   422
    for (texture = renderer->textures; texture; texture = texture->next) {
slouken@8207
   423
        if (texture->access == SDL_TEXTUREACCESS_TARGET) {
slouken@8207
   424
            D3D_DestroyTexture(renderer, texture);
slouken@8792
   425
        } else {
slouken@8792
   426
            D3D_RecreateTexture(renderer, texture);
slouken@8207
   427
        }
slouken@8207
   428
    }
slouken@8207
   429
slouken@5297
   430
    result = IDirect3DDevice9_Reset(data->device, &data->pparams);
slouken@5297
   431
    if (FAILED(result)) {
slouken@5297
   432
        if (result == D3DERR_DEVICELOST) {
slouken@5297
   433
            /* Don't worry about it, we'll reset later... */
slouken@5297
   434
            return 0;
slouken@5297
   435
        } else {
icculus@7037
   436
            return D3D_SetError("Reset()", result);
slouken@5297
   437
        }
slouken@5297
   438
    }
slouken@7648
   439
slouken@8207
   440
    /* Allocate application render targets */
slouken@8207
   441
    for (texture = renderer->textures; texture; texture = texture->next) {
slouken@8207
   442
        if (texture->access == SDL_TEXTUREACCESS_TARGET) {
slouken@8207
   443
            D3D_CreateTexture(renderer, texture);
slouken@8207
   444
        }
slouken@8207
   445
    }
slouken@8207
   446
slouken@6860
   447
    IDirect3DDevice9_GetRenderTarget(data->device, 0, &data->defaultRenderTarget);
slouken@7648
   448
    D3D_InitRenderState(data);
slouken@8228
   449
    D3D_SetRenderTargetInternal(renderer, renderer->target);
slouken@7586
   450
    D3D_UpdateViewport(renderer);
slouken@8207
   451
slouken@8207
   452
    /* Let the application know that render targets were reset */
slouken@8207
   453
    {
slouken@8207
   454
        SDL_Event event;
slouken@8207
   455
        event.type = SDL_RENDER_TARGETS_RESET;
slouken@8207
   456
        SDL_PushEvent(&event);
slouken@8207
   457
    }
slouken@8207
   458
slouken@5297
   459
    return 0;
slouken@5297
   460
}
slouken@5297
   461
slouken@5297
   462
static int
slouken@5297
   463
D3D_ActivateRenderer(SDL_Renderer * renderer)
slouken@5297
   464
{
slouken@5297
   465
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@5297
   466
    HRESULT result;
slouken@5297
   467
slouken@5297
   468
    if (data->updateSize) {
slouken@5297
   469
        SDL_Window *window = renderer->window;
slouken@5297
   470
        int w, h;
slouken@8823
   471
        Uint32 window_flags = SDL_GetWindowFlags(window);
slouken@5297
   472
slouken@5297
   473
        SDL_GetWindowSize(window, &w, &h);
slouken@5297
   474
        data->pparams.BackBufferWidth = w;
slouken@5297
   475
        data->pparams.BackBufferHeight = h;
slouken@8823
   476
        if (window_flags & SDL_WINDOW_FULLSCREEN && (window_flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP) {
slouken@8823
   477
            SDL_DisplayMode fullscreen_mode;
slouken@8823
   478
            SDL_GetWindowDisplayMode(window, &fullscreen_mode);
slouken@8823
   479
            data->pparams.Windowed = FALSE;
slouken@8823
   480
            data->pparams.BackBufferFormat = PixelFormatToD3DFMT(fullscreen_mode.format);
slouken@8823
   481
            data->pparams.FullScreen_RefreshRateInHz = fullscreen_mode.refresh_rate;
slouken@5297
   482
        } else {
slouken@8823
   483
            data->pparams.Windowed = TRUE;
slouken@5297
   484
            data->pparams.BackBufferFormat = D3DFMT_UNKNOWN;
slouken@8823
   485
            data->pparams.FullScreen_RefreshRateInHz = 0;
slouken@5297
   486
        }
slouken@5297
   487
        if (D3D_Reset(renderer) < 0) {
slouken@5297
   488
            return -1;
slouken@5297
   489
        }
slouken@5297
   490
slouken@5297
   491
        data->updateSize = SDL_FALSE;
slouken@5297
   492
    }
slouken@5297
   493
    if (data->beginScene) {
slouken@5297
   494
        result = IDirect3DDevice9_BeginScene(data->device);
slouken@5297
   495
        if (result == D3DERR_DEVICELOST) {
slouken@5297
   496
            if (D3D_Reset(renderer) < 0) {
slouken@5297
   497
                return -1;
slouken@5297
   498
            }
slouken@5297
   499
            result = IDirect3DDevice9_BeginScene(data->device);
slouken@5297
   500
        }
slouken@5297
   501
        if (FAILED(result)) {
icculus@7037
   502
            return D3D_SetError("BeginScene()", result);
slouken@5297
   503
        }
slouken@5297
   504
        data->beginScene = SDL_FALSE;
slouken@5297
   505
    }
slouken@5297
   506
    return 0;
slouken@5297
   507
}
slouken@5297
   508
slouken@1895
   509
SDL_Renderer *
slouken@1913
   510
D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
slouken@1895
   511
{
slouken@1895
   512
    SDL_Renderer *renderer;
slouken@1913
   513
    D3D_RenderData *data;
slouken@5154
   514
    SDL_SysWMinfo windowinfo;
slouken@1900
   515
    HRESULT result;
slouken@1900
   516
    D3DPRESENT_PARAMETERS pparams;
slouken@1907
   517
    IDirect3DSwapChain9 *chain;
slouken@1925
   518
    D3DCAPS9 caps;
slouken@7877
   519
    DWORD device_flags;
slouken@5156
   520
    Uint32 window_flags;
slouken@5156
   521
    int w, h;
slouken@5156
   522
    SDL_DisplayMode fullscreen_mode;
slouken@7877
   523
    int displayIndex;
slouken@1895
   524
slouken@1920
   525
    renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
slouken@1895
   526
    if (!renderer) {
slouken@1895
   527
        SDL_OutOfMemory();
slouken@1895
   528
        return NULL;
slouken@1895
   529
    }
slouken@1895
   530
slouken@1920
   531
    data = (D3D_RenderData *) SDL_calloc(1, sizeof(*data));
slouken@1895
   532
    if (!data) {
slouken@5154
   533
        SDL_free(renderer);
slouken@1895
   534
        SDL_OutOfMemory();
slouken@1895
   535
        return NULL;
slouken@1895
   536
    }
slouken@5154
   537
slouken@8599
   538
    if (!D3D_LoadDLL(&data->d3dDLL, &data->d3d)) {
slouken@5154
   539
        SDL_free(renderer);
slouken@5154
   540
        SDL_free(data);
slouken@5154
   541
        SDL_SetError("Unable to create Direct3D interface");
slouken@5154
   542
        return NULL;
slouken@5154
   543
    }
slouken@4569
   544
slouken@5297
   545
    renderer->WindowEvent = D3D_WindowEvent;
slouken@11282
   546
    renderer->SupportsBlendMode = D3D_SupportsBlendMode;
slouken@1913
   547
    renderer->CreateTexture = D3D_CreateTexture;
slouken@1913
   548
    renderer->UpdateTexture = D3D_UpdateTexture;
slouken@7877
   549
    renderer->UpdateTextureYUV = D3D_UpdateTextureYUV;
slouken@1913
   550
    renderer->LockTexture = D3D_LockTexture;
slouken@1913
   551
    renderer->UnlockTexture = D3D_UnlockTexture;
slouken@6247
   552
    renderer->SetRenderTarget = D3D_SetRenderTarget;
slouken@5297
   553
    renderer->UpdateViewport = D3D_UpdateViewport;
slouken@7141
   554
    renderer->UpdateClipRect = D3D_UpdateClipRect;
slouken@5297
   555
    renderer->RenderClear = D3D_RenderClear;
slouken@3599
   556
    renderer->RenderDrawPoints = D3D_RenderDrawPoints;
slouken@3599
   557
    renderer->RenderDrawLines = D3D_RenderDrawLines;
slouken@3675
   558
    renderer->RenderFillRects = D3D_RenderFillRects;
slouken@1913
   559
    renderer->RenderCopy = D3D_RenderCopy;
gabomdq@6320
   560
    renderer->RenderCopyEx = D3D_RenderCopyEx;
slouken@3427
   561
    renderer->RenderReadPixels = D3D_RenderReadPixels;
slouken@1913
   562
    renderer->RenderPresent = D3D_RenderPresent;
slouken@1913
   563
    renderer->DestroyTexture = D3D_DestroyTexture;
slouken@1913
   564
    renderer->DestroyRenderer = D3D_DestroyRenderer;
slouken@1913
   565
    renderer->info = D3D_RenderDriver.info;
slouken@8590
   566
    renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
slouken@1895
   567
    renderer->driverdata = data;
slouken@1895
   568
slouken@5154
   569
    SDL_VERSION(&windowinfo.version);
slouken@5154
   570
    SDL_GetWindowWMInfo(window, &windowinfo);
slouken@5154
   571
slouken@5156
   572
    window_flags = SDL_GetWindowFlags(window);
slouken@5156
   573
    SDL_GetWindowSize(window, &w, &h);
slouken@5156
   574
    SDL_GetWindowDisplayMode(window, &fullscreen_mode);
slouken@5156
   575
slouken@1900
   576
    SDL_zero(pparams);
slouken@5154
   577
    pparams.hDeviceWindow = windowinfo.info.win.window;
slouken@5156
   578
    pparams.BackBufferWidth = w;
slouken@5156
   579
    pparams.BackBufferHeight = h;
slouken@5142
   580
    pparams.BackBufferCount = 1;
slouken@5142
   581
    pparams.SwapEffect = D3DSWAPEFFECT_DISCARD;
slouken@5142
   582
slouken@8823
   583
    if (window_flags & SDL_WINDOW_FULLSCREEN && (window_flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP) {
slouken@8823
   584
        pparams.Windowed = FALSE;
slouken@8823
   585
        pparams.BackBufferFormat = PixelFormatToD3DFMT(fullscreen_mode.format);
slouken@8823
   586
        pparams.FullScreen_RefreshRateInHz = fullscreen_mode.refresh_rate;
slouken@1900
   587
    } else {
slouken@1900
   588
        pparams.Windowed = TRUE;
slouken@8823
   589
        pparams.BackBufferFormat = D3DFMT_UNKNOWN;
slouken@1903
   590
        pparams.FullScreen_RefreshRateInHz = 0;
slouken@1900
   591
    }
slouken@1965
   592
    if (flags & SDL_RENDERER_PRESENTVSYNC) {
slouken@1907
   593
        pparams.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
slouken@1907
   594
    } else {
slouken@1907
   595
        pparams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
slouken@1907
   596
    }
slouken@1900
   597
slouken@7742
   598
    /* Get the adapter for the display that the window is on */
slouken@8207
   599
    displayIndex = SDL_GetWindowDisplayIndex(window);
slouken@8207
   600
    data->adapter = SDL_Direct3D9GetAdapterIndex(displayIndex);
slouken@7742
   601
slouken@5154
   602
    IDirect3D9_GetDeviceCaps(data->d3d, data->adapter, D3DDEVTYPE_HAL, &caps);
slouken@3197
   603
slouken@7877
   604
    device_flags = D3DCREATE_FPU_PRESERVE;
slouken@7877
   605
    if (caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) {
slouken@7877
   606
        device_flags |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
slouken@7877
   607
    } else {
slouken@7877
   608
        device_flags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
slouken@7877
   609
    }
slouken@7764
   610
slouken@10499
   611
    if (SDL_GetHintBoolean(SDL_HINT_RENDER_DIRECT3D_THREADSAFE, SDL_FALSE)) {
slouken@7877
   612
        device_flags |= D3DCREATE_MULTITHREADED;
slouken@7877
   613
    }
slouken@7764
   614
slouken@5154
   615
    result = IDirect3D9_CreateDevice(data->d3d, data->adapter,
slouken@1900
   616
                                     D3DDEVTYPE_HAL,
slouken@5154
   617
                                     pparams.hDeviceWindow,
slouken@7764
   618
                                     device_flags,
slouken@1900
   619
                                     &pparams, &data->device);
slouken@1900
   620
    if (FAILED(result)) {
slouken@1913
   621
        D3D_DestroyRenderer(renderer);
slouken@1900
   622
        D3D_SetError("CreateDevice()", result);
slouken@1900
   623
        return NULL;
slouken@1900
   624
    }
slouken@1900
   625
slouken@1907
   626
    /* Get presentation parameters to fill info */
slouken@1907
   627
    result = IDirect3DDevice9_GetSwapChain(data->device, 0, &chain);
slouken@1907
   628
    if (FAILED(result)) {
slouken@1913
   629
        D3D_DestroyRenderer(renderer);
slouken@1907
   630
        D3D_SetError("GetSwapChain()", result);
slouken@1907
   631
        return NULL;
slouken@1907
   632
    }
slouken@1907
   633
    result = IDirect3DSwapChain9_GetPresentParameters(chain, &pparams);
slouken@1907
   634
    if (FAILED(result)) {
slouken@1907
   635
        IDirect3DSwapChain9_Release(chain);
slouken@1913
   636
        D3D_DestroyRenderer(renderer);
slouken@1907
   637
        D3D_SetError("GetPresentParameters()", result);
slouken@1907
   638
        return NULL;
slouken@1907
   639
    }
slouken@1907
   640
    IDirect3DSwapChain9_Release(chain);
slouken@1907
   641
    if (pparams.PresentationInterval == D3DPRESENT_INTERVAL_ONE) {
slouken@1965
   642
        renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
slouken@1907
   643
    }
slouken@1975
   644
    data->pparams = pparams;
slouken@1907
   645
slouken@1925
   646
    IDirect3DDevice9_GetDeviceCaps(data->device, &caps);
slouken@1925
   647
    renderer->info.max_texture_width = caps.MaxTextureWidth;
slouken@1925
   648
    renderer->info.max_texture_height = caps.MaxTextureHeight;
slouken@6246
   649
    if (caps.NumSimultaneousRTs >= 2) {
slouken@6246
   650
        renderer->info.flags |= SDL_RENDERER_TARGETTEXTURE;
slouken@6246
   651
    }
slouken@1918
   652
slouken@7502
   653
    if (caps.PrimitiveMiscCaps & D3DPMISCCAPS_SEPARATEALPHABLEND) {
slouken@7502
   654
        data->enableSeparateAlphaBlend = SDL_TRUE;
slouken@7502
   655
    }
slouken@7502
   656
slouken@6232
   657
    /* Store the default render target */
slouken@8822
   658
    IDirect3DDevice9_GetRenderTarget(data->device, 0, &data->defaultRenderTarget);
slouken@6232
   659
    data->currentRenderTarget = NULL;
slouken@6232
   660
slouken@7648
   661
    /* Set up parameters for rendering */
slouken@7648
   662
    D3D_InitRenderState(data);
slouken@5297
   663
slouken@7505
   664
    if (caps.MaxSimultaneousTextures >= 3)
slouken@7505
   665
    {
slouken@7505
   666
#ifdef ASSEMBLE_SHADER
slouken@7505
   667
        /* This shader was created by running the following HLSL through the fxc compiler
slouken@7505
   668
           and then tuning the generated assembly.
slouken@7505
   669
slouken@7505
   670
           fxc /T fx_4_0 /O3 /Gfa /Fc yuv.fxc yuv.fx
slouken@7505
   671
slouken@7505
   672
           --- yuv.fx ---
slouken@7505
   673
           Texture2D g_txY;
slouken@7505
   674
           Texture2D g_txU;
slouken@7505
   675
           Texture2D g_txV;
slouken@7505
   676
slouken@7505
   677
           SamplerState samLinear
slouken@7505
   678
           {
slouken@7505
   679
               Filter = ANISOTROPIC;
slouken@7505
   680
               AddressU = Clamp;
slouken@7505
   681
               AddressV = Clamp;
slouken@7505
   682
               MaxAnisotropy = 1;
slouken@7505
   683
           };
slouken@7505
   684
slouken@7505
   685
           struct VS_OUTPUT
slouken@7505
   686
           {
slouken@7505
   687
                float2 TextureUV  : TEXCOORD0;
slouken@7505
   688
           };
slouken@7505
   689
slouken@7505
   690
           struct PS_OUTPUT
slouken@7505
   691
           {
slouken@7505
   692
                float4 RGBAColor : SV_Target;
slouken@7505
   693
           };
slouken@7505
   694
slouken@7505
   695
           PS_OUTPUT YUV420( VS_OUTPUT In ) 
slouken@7505
   696
           {
alfred@8969
   697
               const float3 offset = {-0.0627451017, -0.501960814, -0.501960814};
slouken@7505
   698
               const float3 Rcoeff = {1.164,  0.000,  1.596};
slouken@7505
   699
               const float3 Gcoeff = {1.164, -0.391, -0.813};
slouken@7505
   700
               const float3 Bcoeff = {1.164,  2.018,  0.000};
slouken@7505
   701
slouken@7505
   702
               PS_OUTPUT Output;
slouken@7505
   703
               float2 TextureUV = In.TextureUV;
slouken@7505
   704
slouken@7505
   705
               float3 yuv;
slouken@7505
   706
               yuv.x = g_txY.Sample( samLinear, TextureUV ).r;
slouken@7505
   707
               yuv.y = g_txU.Sample( samLinear, TextureUV ).r;
slouken@7505
   708
               yuv.z = g_txV.Sample( samLinear, TextureUV ).r;
slouken@7505
   709
slouken@7505
   710
               yuv += offset;
slouken@7505
   711
               Output.RGBAColor.r = dot(yuv, Rcoeff);
slouken@7505
   712
               Output.RGBAColor.g = dot(yuv, Gcoeff);
slouken@7505
   713
               Output.RGBAColor.b = dot(yuv, Bcoeff);
slouken@7505
   714
               Output.RGBAColor.a = 1.0f;
slouken@7505
   715
slouken@7505
   716
               return Output;
slouken@7505
   717
           }
slouken@7505
   718
slouken@7505
   719
           technique10 RenderYUV420
slouken@7505
   720
           {
slouken@7505
   721
               pass P0
slouken@7505
   722
               {
slouken@7505
   723
                    SetPixelShader( CompileShader( ps_4_0_level_9_0, YUV420() ) );
slouken@7505
   724
               }
slouken@7505
   725
           }
slouken@7505
   726
        */
slouken@7505
   727
        const char *shader_text =
slouken@7505
   728
            "ps_2_0\n"
alfred@8969
   729
            "def c0, -0.0627451017, -0.501960814, -0.501960814, 1\n"
slouken@7505
   730
            "def c1, 1.16400003, 0, 1.59599996, 0\n"
slouken@7505
   731
            "def c2, 1.16400003, -0.391000003, -0.813000023, 0\n"
slouken@7505
   732
            "def c3, 1.16400003, 2.01799989, 0, 0\n"
slouken@7505
   733
            "dcl t0.xy\n"
slouken@7505
   734
            "dcl v0.xyzw\n"
slouken@7505
   735
            "dcl_2d s0\n"
slouken@7505
   736
            "dcl_2d s1\n"
slouken@7505
   737
            "dcl_2d s2\n"
slouken@7505
   738
            "texld r0, t0, s0\n"
slouken@7505
   739
            "texld r1, t0, s1\n"
slouken@7505
   740
            "texld r2, t0, s2\n"
slouken@7505
   741
            "mov r0.y, r1.x\n"
slouken@7505
   742
            "mov r0.z, r2.x\n"
slouken@7505
   743
            "add r0.xyz, r0, c0\n"
slouken@7505
   744
            "dp3 r1.x, r0, c1\n"
slouken@7505
   745
            "dp3 r1.y, r0, c2\n"
slouken@7505
   746
            "dp2add r1.z, r0, c3, c3.z\n"   /* Logically this is "dp3 r1.z, r0, c3" but the optimizer did its magic */
slouken@7505
   747
            "mov r1.w, c0.w\n"
slouken@7505
   748
            "mul r0, r1, v0\n"              /* Not in the HLSL, multiply by vertex color */
slouken@7505
   749
            "mov oC0, r0\n"
slouken@7505
   750
        ;
slouken@7505
   751
        LPD3DXBUFFER pCode;
slouken@7505
   752
        LPD3DXBUFFER pErrorMsgs;
slouken@7505
   753
        LPDWORD shader_data = NULL;
slouken@7505
   754
        DWORD   shader_size = 0;
slouken@7505
   755
        result = D3DXAssembleShader(shader_text, SDL_strlen(shader_text), NULL, NULL, 0, &pCode, &pErrorMsgs);
slouken@7505
   756
        if (!FAILED(result)) {
slouken@7505
   757
            shader_data = (DWORD*)pCode->lpVtbl->GetBufferPointer(pCode);
slouken@7505
   758
            shader_size = pCode->lpVtbl->GetBufferSize(pCode);
slouken@7505
   759
            PrintShaderData(shader_data, shader_size);
slouken@7505
   760
        } else {
slouken@7505
   761
            const char *error = (const char *)pErrorMsgs->lpVtbl->GetBufferPointer(pErrorMsgs);
slouken@7505
   762
            SDL_SetError("Couldn't assemble shader: %s", error);
slouken@7505
   763
        }
slouken@11330
   764
        if (shader_data != NULL)
slouken@7505
   765
#else
slouken@7505
   766
        const DWORD shader_data[] = {
alfred@8969
   767
            0xffff0200, 0x05000051, 0xa00f0000, 0xbd808081, 0xbf008081, 0xbf008081,
slouken@7505
   768
            0x3f800000, 0x05000051, 0xa00f0001, 0x3f94fdf4, 0x00000000, 0x3fcc49ba,
slouken@7505
   769
            0x00000000, 0x05000051, 0xa00f0002, 0x3f94fdf4, 0xbec83127, 0xbf5020c5,
slouken@7505
   770
            0x00000000, 0x05000051, 0xa00f0003, 0x3f94fdf4, 0x400126e9, 0x00000000,
slouken@7505
   771
            0x00000000, 0x0200001f, 0x80000000, 0xb0030000, 0x0200001f, 0x80000000,
slouken@7505
   772
            0x900f0000, 0x0200001f, 0x90000000, 0xa00f0800, 0x0200001f, 0x90000000,
slouken@7505
   773
            0xa00f0801, 0x0200001f, 0x90000000, 0xa00f0802, 0x03000042, 0x800f0000,
slouken@7505
   774
            0xb0e40000, 0xa0e40800, 0x03000042, 0x800f0001, 0xb0e40000, 0xa0e40801,
slouken@7505
   775
            0x03000042, 0x800f0002, 0xb0e40000, 0xa0e40802, 0x02000001, 0x80020000,
slouken@7505
   776
            0x80000001, 0x02000001, 0x80040000, 0x80000002, 0x03000002, 0x80070000,
slouken@7505
   777
            0x80e40000, 0xa0e40000, 0x03000008, 0x80010001, 0x80e40000, 0xa0e40001,
slouken@7505
   778
            0x03000008, 0x80020001, 0x80e40000, 0xa0e40002, 0x0400005a, 0x80040001,
slouken@7505
   779
            0x80e40000, 0xa0e40003, 0xa0aa0003, 0x02000001, 0x80080001, 0xa0ff0000,
slouken@7505
   780
            0x03000005, 0x800f0000, 0x80e40001, 0x90e40000, 0x02000001, 0x800f0800,
slouken@7505
   781
            0x80e40000, 0x0000ffff
slouken@7505
   782
        };
slouken@7505
   783
#endif
slouken@11330
   784
        {
slouken@7505
   785
            result = IDirect3DDevice9_CreatePixelShader(data->device, shader_data, &data->ps_yuv);
slouken@7505
   786
            if (!FAILED(result)) {
slouken@7505
   787
                renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_YV12;
slouken@7505
   788
                renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_IYUV;
slouken@7505
   789
            } else {
slouken@7505
   790
                D3D_SetError("CreatePixelShader()", result);
slouken@7505
   791
            }
slouken@7505
   792
        }
slouken@7505
   793
    }
slouken@7505
   794
slouken@1895
   795
    return renderer;
slouken@1895
   796
}
slouken@1895
   797
slouken@5297
   798
static void
slouken@5297
   799
D3D_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
slouken@1975
   800
{
slouken@1975
   801
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@1975
   802
slouken@5297
   803
    if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED) {
slouken@5297
   804
        data->updateSize = SDL_TRUE;
slouken@1975
   805
    }
slouken@1975
   806
}
slouken@1975
   807
slouken@11282
   808
static D3DBLEND GetBlendFunc(SDL_BlendFactor factor)
slouken@11282
   809
{
slouken@11282
   810
    switch (factor) {
slouken@11282
   811
    case SDL_BLENDFACTOR_ZERO:
slouken@11282
   812
        return D3DBLEND_ZERO;
slouken@11282
   813
    case SDL_BLENDFACTOR_ONE:
slouken@11282
   814
        return D3DBLEND_ONE;
slouken@11282
   815
    case SDL_BLENDFACTOR_SRC_COLOR:
slouken@11282
   816
        return D3DBLEND_SRCCOLOR;
slouken@11282
   817
    case SDL_BLENDFACTOR_ONE_MINUS_SRC_COLOR:
slouken@11282
   818
        return D3DBLEND_INVSRCCOLOR;
slouken@11282
   819
    case SDL_BLENDFACTOR_SRC_ALPHA:
slouken@11282
   820
        return D3DBLEND_SRCALPHA;
slouken@11282
   821
    case SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA:
slouken@11282
   822
        return D3DBLEND_INVSRCALPHA;
slouken@11282
   823
    case SDL_BLENDFACTOR_DST_COLOR:
slouken@11282
   824
        return D3DBLEND_DESTCOLOR;
slouken@11282
   825
    case SDL_BLENDFACTOR_ONE_MINUS_DST_COLOR:
slouken@11282
   826
        return D3DBLEND_INVDESTCOLOR;
slouken@11282
   827
    case SDL_BLENDFACTOR_DST_ALPHA:
slouken@11282
   828
        return D3DBLEND_DESTALPHA;
slouken@11282
   829
    case SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA:
slouken@11282
   830
        return D3DBLEND_INVDESTALPHA;
slouken@11282
   831
    default:
slouken@11282
   832
        return (D3DBLEND)0;
slouken@11282
   833
    }
slouken@11282
   834
}
slouken@11282
   835
slouken@11282
   836
static SDL_bool
slouken@11282
   837
D3D_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode)
slouken@11282
   838
{
slouken@11282
   839
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@11282
   840
    SDL_BlendFactor srcColorFactor = SDL_GetBlendModeSrcColorFactor(blendMode);
slouken@11282
   841
    SDL_BlendFactor srcAlphaFactor = SDL_GetBlendModeSrcAlphaFactor(blendMode);
slouken@11282
   842
    SDL_BlendOperation colorOperation = SDL_GetBlendModeColorOperation(blendMode);
slouken@11282
   843
    SDL_BlendFactor dstColorFactor = SDL_GetBlendModeDstColorFactor(blendMode);
slouken@11282
   844
    SDL_BlendFactor dstAlphaFactor = SDL_GetBlendModeDstAlphaFactor(blendMode);
slouken@11282
   845
    SDL_BlendOperation alphaOperation = SDL_GetBlendModeAlphaOperation(blendMode);
slouken@11282
   846
slouken@11282
   847
    if (!GetBlendFunc(srcColorFactor) || !GetBlendFunc(srcAlphaFactor) ||
slouken@11282
   848
        !GetBlendFunc(dstColorFactor) || !GetBlendFunc(dstAlphaFactor)) {
slouken@11282
   849
        return SDL_FALSE;
slouken@11282
   850
    }
slouken@11282
   851
    if ((srcColorFactor != srcAlphaFactor || dstColorFactor != dstAlphaFactor) && !data->enableSeparateAlphaBlend) {
slouken@11282
   852
        return SDL_FALSE;
slouken@11282
   853
    }
slouken@11282
   854
    if (colorOperation != SDL_BLENDOPERATION_ADD || alphaOperation != SDL_BLENDOPERATION_ADD) {
slouken@11282
   855
        return SDL_FALSE;
slouken@11282
   856
    }
slouken@11282
   857
    return SDL_TRUE;
slouken@11282
   858
}
slouken@11282
   859
slouken@5484
   860
static D3DTEXTUREFILTERTYPE
slouken@5484
   861
GetScaleQuality(void)
slouken@5484
   862
{
slouken@5484
   863
    const char *hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY);
slouken@5484
   864
slouken@5484
   865
    if (!hint || *hint == '0' || SDL_strcasecmp(hint, "nearest") == 0) {
slouken@5484
   866
        return D3DTEXF_POINT;
gabomdq@7678
   867
    } else /* if (*hint == '1' || SDL_strcasecmp(hint, "linear") == 0) */ {
slouken@5484
   868
        return D3DTEXF_LINEAR;
slouken@5484
   869
    }
slouken@5484
   870
}
slouken@5484
   871
slouken@1975
   872
static int
slouken@8792
   873
D3D_CreateTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, DWORD usage, Uint32 format, int w, int h)
slouken@1895
   874
{
slouken@1903
   875
    HRESULT result;
slouken@1895
   876
slouken@8822
   877
    texture->dirty = SDL_FALSE;
slouken@9074
   878
    texture->w = w;
slouken@9074
   879
    texture->h = h;
slouken@9074
   880
    texture->usage = usage;
slouken@9074
   881
    texture->format = format;
slouken@8822
   882
slouken@8792
   883
    result = IDirect3DDevice9_CreateTexture(device, w, h, 1, usage,
slouken@8792
   884
        PixelFormatToD3DFMT(format),
slouken@8792
   885
        D3DPOOL_DEFAULT, &texture->texture, NULL);
slouken@8792
   886
    if (FAILED(result)) {
slouken@8792
   887
        return D3D_SetError("CreateTexture(D3DPOOL_DEFAULT)", result);
slouken@5173
   888
    }
slouken@9074
   889
    return 0;
slouken@9074
   890
}
slouken@2973
   891
slouken@9074
   892
slouken@9074
   893
static int
slouken@9074
   894
D3D_CreateStagingTexture(IDirect3DDevice9 *device, D3D_TextureRep *texture)
slouken@9074
   895
{
slouken@9074
   896
    HRESULT result;
slouken@9074
   897
slouken@9074
   898
    if (texture->staging == NULL) {
slouken@9702
   899
        result = IDirect3DDevice9_CreateTexture(device, texture->w, texture->h, 1, 0,
slouken@9074
   900
            PixelFormatToD3DFMT(texture->format),
slouken@8792
   901
            D3DPOOL_SYSTEMMEM, &texture->staging, NULL);
slouken@7505
   902
        if (FAILED(result)) {
slouken@8792
   903
            return D3D_SetError("CreateTexture(D3DPOOL_SYSTEMMEM)", result);
slouken@7505
   904
        }
slouken@7505
   905
    }
slouken@7505
   906
    return 0;
slouken@7505
   907
}
slouken@7505
   908
slouken@7505
   909
static int
slouken@8822
   910
D3D_BindTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, DWORD sampler)
slouken@8792
   911
{
slouken@8792
   912
    HRESULT result;
slouken@8792
   913
slouken@8822
   914
    if (texture->dirty && texture->staging) {
slouken@8822
   915
        if (!texture->texture) {
slouken@9074
   916
            result = IDirect3DDevice9_CreateTexture(device, texture->w, texture->h, 1, texture->usage,
slouken@9074
   917
                PixelFormatToD3DFMT(texture->format), D3DPOOL_DEFAULT, &texture->texture, NULL);
slouken@8822
   918
            if (FAILED(result)) {
slouken@8822
   919
                return D3D_SetError("CreateTexture(D3DPOOL_DEFAULT)", result);
slouken@8822
   920
            }
slouken@8822
   921
        }
slouken@8822
   922
slouken@8822
   923
        result = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)texture->staging, (IDirect3DBaseTexture9 *)texture->texture);
slouken@8822
   924
        if (FAILED(result)) {
slouken@8822
   925
            return D3D_SetError("UpdateTexture()", result);
slouken@8822
   926
        }
slouken@8822
   927
        texture->dirty = SDL_FALSE;
slouken@8822
   928
    }
slouken@8822
   929
    result = IDirect3DDevice9_SetTexture(device, sampler, (IDirect3DBaseTexture9 *)texture->texture);
slouken@8792
   930
    if (FAILED(result)) {
slouken@8822
   931
        return D3D_SetError("SetTexture()", result);
slouken@8792
   932
    }
slouken@8822
   933
    return 0;
slouken@8822
   934
}
slouken@8792
   935
slouken@8822
   936
static int
slouken@8822
   937
D3D_RecreateTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, Uint32 format, int w, int h)
slouken@8822
   938
{
slouken@8822
   939
    if (texture->texture) {
slouken@8822
   940
        IDirect3DTexture9_Release(texture->texture);
slouken@8822
   941
        texture->texture = NULL;
slouken@8792
   942
    }
slouken@9074
   943
    if (texture->staging) {
slouken@9074
   944
        IDirect3DTexture9_AddDirtyRect(texture->staging, NULL);
slouken@9074
   945
        texture->dirty = SDL_TRUE;
slouken@9074
   946
    }
slouken@8792
   947
    return 0;
slouken@8792
   948
}
slouken@8792
   949
slouken@8792
   950
static int
slouken@8792
   951
D3D_UpdateTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, Uint32 format, int x, int y, int w, int h, const void *pixels, int pitch)
slouken@7505
   952
{
slouken@7505
   953
    RECT d3drect;
slouken@7505
   954
    D3DLOCKED_RECT locked;
slouken@7505
   955
    const Uint8 *src;
slouken@7505
   956
    Uint8 *dst;
slouken@7505
   957
    int row, length;
slouken@7505
   958
    HRESULT result;
slouken@7505
   959
slouken@9074
   960
    if (D3D_CreateStagingTexture(device, texture) < 0) {
slouken@9074
   961
        return -1;
slouken@9074
   962
    }
slouken@9074
   963
slouken@8792
   964
    d3drect.left = x;
slouken@8792
   965
    d3drect.right = x + w;
slouken@8792
   966
    d3drect.top = y;
slouken@8792
   967
    d3drect.bottom = y + h;
slouken@9074
   968
    
slouken@8792
   969
    result = IDirect3DTexture9_LockRect(texture->staging, 0, &locked, &d3drect, 0);
slouken@7505
   970
    if (FAILED(result)) {
slouken@7505
   971
        return D3D_SetError("LockRect()", result);
slouken@7505
   972
    }
slouken@7505
   973
slouken@7505
   974
    src = (const Uint8 *)pixels;
slouken@7505
   975
    dst = locked.pBits;
slouken@7505
   976
    length = w * SDL_BYTESPERPIXEL(format);
slouken@7505
   977
    if (length == pitch && length == locked.Pitch) {
slouken@7505
   978
        SDL_memcpy(dst, src, length*h);
slouken@7505
   979
    } else {
slouken@8255
   980
        if (length > pitch) {
slouken@8255
   981
            length = pitch;
slouken@8255
   982
        }
slouken@8255
   983
        if (length > locked.Pitch) {
slouken@8255
   984
            length = locked.Pitch;
slouken@8255
   985
        }
slouken@7505
   986
        for (row = 0; row < h; ++row) {
slouken@7505
   987
            SDL_memcpy(dst, src, length);
slouken@7505
   988
            src += pitch;
slouken@7505
   989
            dst += locked.Pitch;
slouken@7505
   990
        }
slouken@7505
   991
    }
slouken@8822
   992
    result = IDirect3DTexture9_UnlockRect(texture->staging, 0);
slouken@8822
   993
    if (FAILED(result)) {
slouken@8822
   994
        return D3D_SetError("UnlockRect()", result);
slouken@8822
   995
    }
slouken@8822
   996
    texture->dirty = SDL_TRUE;
slouken@8792
   997
slouken@8792
   998
    return 0;
slouken@8792
   999
}
slouken@8792
  1000
slouken@8792
  1001
static void
slouken@8792
  1002
D3D_DestroyTextureRep(D3D_TextureRep *texture)
slouken@8792
  1003
{
slouken@8792
  1004
    if (texture->texture) {
slouken@8792
  1005
        IDirect3DTexture9_Release(texture->texture);
slouken@8792
  1006
        texture->texture = NULL;
slouken@8792
  1007
    }
slouken@8792
  1008
    if (texture->staging) {
slouken@8792
  1009
        IDirect3DTexture9_Release(texture->staging);
slouken@8792
  1010
        texture->staging = NULL;
slouken@8792
  1011
    }
slouken@8792
  1012
}
slouken@8792
  1013
slouken@8792
  1014
static int
slouken@8792
  1015
D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@8792
  1016
{
slouken@8792
  1017
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@8792
  1018
    D3D_TextureData *texturedata;
slouken@8792
  1019
    DWORD usage;
slouken@8792
  1020
slouken@8792
  1021
    texturedata = (D3D_TextureData *) SDL_calloc(1, sizeof(*texturedata));
slouken@8792
  1022
    if (!texturedata) {
slouken@8792
  1023
        return SDL_OutOfMemory();
slouken@8792
  1024
    }
slouken@8792
  1025
    texturedata->scaleMode = GetScaleQuality();
slouken@8792
  1026
slouken@8792
  1027
    texture->driverdata = texturedata;
slouken@7505
  1028
slouken@8792
  1029
    if (texture->access == SDL_TEXTUREACCESS_TARGET) {
slouken@8792
  1030
        usage = D3DUSAGE_RENDERTARGET;
slouken@8792
  1031
    } else {
slouken@8792
  1032
        usage = 0;
slouken@8792
  1033
    }
slouken@8792
  1034
slouken@8792
  1035
    if (D3D_CreateTextureRep(data->device, &texturedata->texture, usage, texture->format, texture->w, texture->h) < 0) {
slouken@8792
  1036
        return -1;
slouken@8792
  1037
    }
slouken@8792
  1038
slouken@8792
  1039
    if (texture->format == SDL_PIXELFORMAT_YV12 ||
slouken@8792
  1040
        texture->format == SDL_PIXELFORMAT_IYUV) {
slouken@8792
  1041
        texturedata->yuv = SDL_TRUE;
slouken@8792
  1042
slouken@8792
  1043
        if (D3D_CreateTextureRep(data->device, &texturedata->utexture, usage, texture->format, texture->w / 2, texture->h / 2) < 0) {
slouken@8792
  1044
            return -1;
slouken@8792
  1045
        }
slouken@8792
  1046
slouken@8792
  1047
        if (D3D_CreateTextureRep(data->device, &texturedata->vtexture, usage, texture->format, texture->w / 2, texture->h / 2) < 0) {
slouken@8792
  1048
            return -1;
slouken@8792
  1049
        }
slouken@8792
  1050
    }
slouken@8792
  1051
    return 0;
slouken@8792
  1052
}
slouken@8792
  1053
slouken@8792
  1054
static int
slouken@8792
  1055
D3D_RecreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@8792
  1056
{
slouken@8792
  1057
    D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata;
slouken@8792
  1058
    D3D_TextureData *texturedata = (D3D_TextureData *)texture->driverdata;
slouken@8792
  1059
dludwig@10183
  1060
    if (!texturedata) {
dludwig@10183
  1061
        return 0;
dludwig@10183
  1062
    }
dludwig@10183
  1063
slouken@8792
  1064
    if (D3D_RecreateTextureRep(data->device, &texturedata->texture, texture->format, texture->w, texture->h) < 0) {
slouken@8792
  1065
        return -1;
slouken@8792
  1066
    }
slouken@8792
  1067
slouken@8792
  1068
    if (texturedata->yuv) {
slouken@8792
  1069
        if (D3D_RecreateTextureRep(data->device, &texturedata->utexture, texture->format, texture->w / 2, texture->h / 2) < 0) {
slouken@8792
  1070
            return -1;
slouken@8792
  1071
        }
slouken@8792
  1072
slouken@8792
  1073
        if (D3D_RecreateTextureRep(data->device, &texturedata->vtexture, texture->format, texture->w / 2, texture->h / 2) < 0) {
slouken@8792
  1074
            return -1;
slouken@8792
  1075
        }
slouken@8792
  1076
    }
slouken@1903
  1077
    return 0;
slouken@1895
  1078
}
slouken@1895
  1079
slouken@1895
  1080
static int
slouken@1913
  1081
D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1913
  1082
                  const SDL_Rect * rect, const void *pixels, int pitch)
slouken@1895
  1083
{
slouken@8792
  1084
    D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata;
slouken@8792
  1085
    D3D_TextureData *texturedata = (D3D_TextureData *) texture->driverdata;
slouken@1903
  1086
slouken@8792
  1087
    if (!texturedata) {
slouken@8208
  1088
        SDL_SetError("Texture is not currently available");
slouken@8208
  1089
        return -1;
slouken@8208
  1090
    }
slouken@8208
  1091
slouken@8792
  1092
    if (D3D_UpdateTextureRep(data->device, &texturedata->texture, texture->format, rect->x, rect->y, rect->w, rect->h, pixels, pitch) < 0) {
slouken@7505
  1093
        return -1;
slouken@5156
  1094
    }
slouken@2783
  1095
slouken@8792
  1096
    if (texturedata->yuv) {
slouken@7505
  1097
        /* Skip to the correct offset into the next texture */
slouken@7505
  1098
        pixels = (const void*)((const Uint8*)pixels + rect->h * pitch);
slouken@7505
  1099
slouken@8792
  1100
        if (D3D_UpdateTextureRep(data->device, texture->format == SDL_PIXELFORMAT_YV12 ? &texturedata->vtexture : &texturedata->utexture, texture->format, rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, pixels, pitch / 2) < 0) {
slouken@7505
  1101
            return -1;
slouken@7505
  1102
        }
slouken@7505
  1103
slouken@7505
  1104
        /* Skip to the correct offset into the next texture */
slouken@7505
  1105
        pixels = (const void*)((const Uint8*)pixels + (rect->h * pitch)/4);
slouken@8792
  1106
        if (D3D_UpdateTextureRep(data->device, texture->format == SDL_PIXELFORMAT_YV12 ? &texturedata->utexture : &texturedata->vtexture, texture->format, rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, pixels, pitch / 2) < 0) {
slouken@7505
  1107
            return -1;
slouken@5173
  1108
        }
slouken@5156
  1109
    }
slouken@5156
  1110
    return 0;
slouken@2783
  1111
}
slouken@1895
  1112
slouken@1895
  1113
static int
slouken@7761
  1114
D3D_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@7761
  1115
                     const SDL_Rect * rect,
slouken@7761
  1116
                     const Uint8 *Yplane, int Ypitch,
slouken@7761
  1117
                     const Uint8 *Uplane, int Upitch,
slouken@7761
  1118
                     const Uint8 *Vplane, int Vpitch)
slouken@7761
  1119
{
slouken@8792
  1120
    D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata;
slouken@8792
  1121
    D3D_TextureData *texturedata = (D3D_TextureData *) texture->driverdata;
slouken@7761
  1122
slouken@8792
  1123
    if (!texturedata) {
slouken@8208
  1124
        SDL_SetError("Texture is not currently available");
slouken@8208
  1125
        return -1;
slouken@8208
  1126
    }
slouken@8208
  1127
slouken@8792
  1128
    if (D3D_UpdateTextureRep(data->device, &texturedata->texture, texture->format, rect->x, rect->y, rect->w, rect->h, Yplane, Ypitch) < 0) {
slouken@7877
  1129
        return -1;
slouken@7877
  1130
    }
slouken@8792
  1131
    if (D3D_UpdateTextureRep(data->device, &texturedata->utexture, texture->format, rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, Uplane, Upitch) < 0) {
slouken@7877
  1132
        return -1;
slouken@7877
  1133
    }
slouken@8792
  1134
    if (D3D_UpdateTextureRep(data->device, &texturedata->vtexture, texture->format, rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, Vplane, Vpitch) < 0) {
slouken@7877
  1135
        return -1;
slouken@7877
  1136
    }
slouken@7877
  1137
    return 0;
slouken@7761
  1138
}
slouken@7761
  1139
slouken@7761
  1140
static int
slouken@1913
  1141
D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@5156
  1142
                const SDL_Rect * rect, void **pixels, int *pitch)
slouken@1895
  1143
{
slouken@9074
  1144
    D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata;
slouken@8792
  1145
    D3D_TextureData *texturedata = (D3D_TextureData *)texture->driverdata;
slouken@9074
  1146
    IDirect3DDevice9 *device = data->device;
slouken@1895
  1147
slouken@8792
  1148
    if (!texturedata) {
slouken@8208
  1149
        SDL_SetError("Texture is not currently available");
slouken@8208
  1150
        return -1;
slouken@8208
  1151
    }
slouken@8208
  1152
slouken@8792
  1153
    texturedata->locked_rect = *rect;
slouken@8792
  1154
slouken@8792
  1155
    if (texturedata->yuv) {
gabomdq@7663
  1156
        /* It's more efficient to upload directly... */
slouken@8792
  1157
        if (!texturedata->pixels) {
slouken@8792
  1158
            texturedata->pitch = texture->w;
slouken@8792
  1159
            texturedata->pixels = (Uint8 *)SDL_malloc((texture->h * texturedata->pitch * 3) / 2);
slouken@8792
  1160
            if (!texturedata->pixels) {
slouken@7505
  1161
                return SDL_OutOfMemory();
slouken@7505
  1162
            }
slouken@7505
  1163
        }
slouken@7505
  1164
        *pixels =
slouken@8792
  1165
            (void *) ((Uint8 *) texturedata->pixels + rect->y * texturedata->pitch +
slouken@7505
  1166
                      rect->x * SDL_BYTESPERPIXEL(texture->format));
slouken@8792
  1167
        *pitch = texturedata->pitch;
slouken@7505
  1168
    } else {
slouken@8792
  1169
        RECT d3drect;
slouken@8792
  1170
        D3DLOCKED_RECT locked;
slouken@8792
  1171
        HRESULT result;
slouken@8792
  1172
slouken@9074
  1173
        if (D3D_CreateStagingTexture(device, &texturedata->texture) < 0) {
slouken@9074
  1174
            return -1;
slouken@9074
  1175
        }
slouken@9074
  1176
slouken@7505
  1177
        d3drect.left = rect->x;
slouken@7505
  1178
        d3drect.right = rect->x + rect->w;
slouken@7505
  1179
        d3drect.top = rect->y;
slouken@7505
  1180
        d3drect.bottom = rect->y + rect->h;
slouken@1903
  1181
slouken@8792
  1182
        result = IDirect3DTexture9_LockRect(texturedata->texture.staging, 0, &locked, &d3drect, 0);
slouken@7505
  1183
        if (FAILED(result)) {
slouken@7505
  1184
            return D3D_SetError("LockRect()", result);
slouken@7505
  1185
        }
slouken@7505
  1186
        *pixels = locked.pBits;
slouken@7505
  1187
        *pitch = locked.Pitch;
slouken@1903
  1188
    }
slouken@5156
  1189
    return 0;
slouken@1895
  1190
}
slouken@1895
  1191
slouken@1895
  1192
static void
slouken@1913
  1193
D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1895
  1194
{
slouken@8976
  1195
    /*D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata;*/
slouken@8792
  1196
    D3D_TextureData *texturedata = (D3D_TextureData *)texture->driverdata;
slouken@1895
  1197
slouken@8792
  1198
    if (!texturedata) {
slouken@8208
  1199
        return;
slouken@8208
  1200
    }
slouken@8208
  1201
slouken@8792
  1202
    if (texturedata->yuv) {
slouken@8792
  1203
        const SDL_Rect *rect = &texturedata->locked_rect;
slouken@7505
  1204
        void *pixels =
slouken@8792
  1205
            (void *) ((Uint8 *) texturedata->pixels + rect->y * texturedata->pitch +
slouken@7505
  1206
                      rect->x * SDL_BYTESPERPIXEL(texture->format));
slouken@8792
  1207
        D3D_UpdateTexture(renderer, texture, rect, pixels, texturedata->pitch);
slouken@7505
  1208
    } else {
slouken@8792
  1209
        IDirect3DTexture9_UnlockRect(texturedata->texture.staging, 0);
slouken@8822
  1210
        texturedata->texture.dirty = SDL_TRUE;
slouken@8822
  1211
   }
slouken@1895
  1212
}
slouken@1895
  1213
slouken@5297
  1214
static int
slouken@8228
  1215
D3D_SetRenderTargetInternal(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@7141
  1216
{
slouken@7141
  1217
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@7141
  1218
    D3D_TextureData *texturedata;
slouken@9074
  1219
    D3D_TextureRep *texturerep;
slouken@7141
  1220
    HRESULT result;
slouken@9074
  1221
    IDirect3DDevice9 *device = data->device;
slouken@7141
  1222
slouken@7141
  1223
    /* Release the previous render target if it wasn't the default one */
slouken@7141
  1224
    if (data->currentRenderTarget != NULL) {
slouken@7141
  1225
        IDirect3DSurface9_Release(data->currentRenderTarget);
slouken@7141
  1226
        data->currentRenderTarget = NULL;
slouken@7141
  1227
    }
slouken@7141
  1228
slouken@7141
  1229
    if (texture == NULL) {
slouken@7141
  1230
        IDirect3DDevice9_SetRenderTarget(data->device, 0, data->defaultRenderTarget);
slouken@7141
  1231
        return 0;
slouken@7141
  1232
    }
slouken@7141
  1233
slouken@8208
  1234
    texturedata = (D3D_TextureData *)texture->driverdata;
slouken@8208
  1235
    if (!texturedata) {
slouken@8208
  1236
        SDL_SetError("Texture is not currently available");
slouken@8208
  1237
        return -1;
slouken@8208
  1238
    }
slouken@8208
  1239
slouken@9074
  1240
    /* Make sure the render target is updated if it was locked and written to */
slouken@9074
  1241
    texturerep = &texturedata->texture;
slouken@9074
  1242
    if (texturerep->dirty && texturerep->staging) {
slouken@9074
  1243
        if (!texturerep->texture) {
slouken@9074
  1244
            result = IDirect3DDevice9_CreateTexture(device, texturerep->w, texturerep->h, 1, texturerep->usage,
slouken@9074
  1245
                PixelFormatToD3DFMT(texturerep->format), D3DPOOL_DEFAULT, &texturerep->texture, NULL);
slouken@9074
  1246
            if (FAILED(result)) {
slouken@9074
  1247
                return D3D_SetError("CreateTexture(D3DPOOL_DEFAULT)", result);
slouken@9074
  1248
            }
slouken@9074
  1249
        }
slouken@9074
  1250
slouken@9074
  1251
        result = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)texturerep->staging, (IDirect3DBaseTexture9 *)texturerep->texture);
slouken@9074
  1252
        if (FAILED(result)) {
slouken@9074
  1253
            return D3D_SetError("UpdateTexture()", result);
slouken@9074
  1254
        }
slouken@9074
  1255
        texturerep->dirty = SDL_FALSE;
slouken@9074
  1256
    }
slouken@9074
  1257
slouken@8792
  1258
    result = IDirect3DTexture9_GetSurfaceLevel(texturedata->texture.texture, 0, &data->currentRenderTarget);
slouken@7141
  1259
    if(FAILED(result)) {
slouken@7141
  1260
        return D3D_SetError("GetSurfaceLevel()", result);
slouken@7141
  1261
    }
slouken@7141
  1262
    result = IDirect3DDevice9_SetRenderTarget(data->device, 0, data->currentRenderTarget);
slouken@7141
  1263
    if(FAILED(result)) {
slouken@7141
  1264
        return D3D_SetError("SetRenderTarget()", result);
slouken@7141
  1265
    }
slouken@7141
  1266
slouken@7141
  1267
    return 0;
slouken@7141
  1268
}
slouken@7141
  1269
slouken@7141
  1270
static int
slouken@8228
  1271
D3D_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@8228
  1272
{
slouken@8228
  1273
    D3D_ActivateRenderer(renderer);
slouken@8228
  1274
slouken@8228
  1275
    return D3D_SetRenderTargetInternal(renderer, texture);
slouken@8228
  1276
}
slouken@8228
  1277
slouken@8228
  1278
static int
slouken@5297
  1279
D3D_UpdateViewport(SDL_Renderer * renderer)
slouken@5224
  1280
{
slouken@5224
  1281
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@5297
  1282
    D3DVIEWPORT9 viewport;
slouken@5297
  1283
    D3DMATRIX matrix;
slouken@5224
  1284
slouken@5297
  1285
    /* Set the viewport */
slouken@5297
  1286
    viewport.X = renderer->viewport.x;
slouken@5297
  1287
    viewport.Y = renderer->viewport.y;
slouken@5297
  1288
    viewport.Width = renderer->viewport.w;
slouken@5297
  1289
    viewport.Height = renderer->viewport.h;
slouken@5297
  1290
    viewport.MinZ = 0.0f;
slouken@5297
  1291
    viewport.MaxZ = 1.0f;
slouken@5297
  1292
    IDirect3DDevice9_SetViewport(data->device, &viewport);
slouken@5297
  1293
slouken@5297
  1294
    /* Set an orthographic projection matrix */
slouken@7239
  1295
    if (renderer->viewport.w && renderer->viewport.h) {
slouken@7239
  1296
        matrix.m[0][0] = 2.0f / renderer->viewport.w;
slouken@7239
  1297
        matrix.m[0][1] = 0.0f;
slouken@7239
  1298
        matrix.m[0][2] = 0.0f;
slouken@7239
  1299
        matrix.m[0][3] = 0.0f;
slouken@7239
  1300
        matrix.m[1][0] = 0.0f;
slouken@7239
  1301
        matrix.m[1][1] = -2.0f / renderer->viewport.h;
slouken@7239
  1302
        matrix.m[1][2] = 0.0f;
slouken@7239
  1303
        matrix.m[1][3] = 0.0f;
slouken@7239
  1304
        matrix.m[2][0] = 0.0f;
slouken@7239
  1305
        matrix.m[2][1] = 0.0f;
slouken@7239
  1306
        matrix.m[2][2] = 1.0f;
slouken@7239
  1307
        matrix.m[2][3] = 0.0f;
slouken@7239
  1308
        matrix.m[3][0] = -1.0f;
slouken@7239
  1309
        matrix.m[3][1] = 1.0f;
slouken@7239
  1310
        matrix.m[3][2] = 0.0f;
slouken@7239
  1311
        matrix.m[3][3] = 1.0f;
slouken@7239
  1312
        IDirect3DDevice9_SetTransform(data->device, D3DTS_PROJECTION, &matrix);
slouken@7239
  1313
    }
slouken@5297
  1314
slouken@5297
  1315
    return 0;
slouken@5297
  1316
}
slouken@5224
  1317
slouken@5297
  1318
static int
slouken@7141
  1319
D3D_UpdateClipRect(SDL_Renderer * renderer)
slouken@6246
  1320
{
slouken@6246
  1321
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@6246
  1322
jorgenpt@8728
  1323
    if (renderer->clipping_enabled) {
jorgenpt@8728
  1324
        const SDL_Rect *rect = &renderer->clip_rect;
jorgenpt@8728
  1325
        RECT r;
jorgenpt@8728
  1326
        HRESULT result;
jorgenpt@8728
  1327
slouken@7141
  1328
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_SCISSORTESTENABLE, TRUE);
slouken@9680
  1329
        r.left = renderer->viewport.x + rect->x;
slouken@9680
  1330
        r.top = renderer->viewport.y + rect->y;
slouken@9680
  1331
        r.right = renderer->viewport.x + rect->x + rect->w;
slouken@9680
  1332
        r.bottom = renderer->viewport.y + rect->y + rect->h;
slouken@6246
  1333
slouken@7141
  1334
        result = IDirect3DDevice9_SetScissorRect(data->device, &r);
slouken@7141
  1335
        if (result != D3D_OK) {
slouken@7141
  1336
            D3D_SetError("SetScissor()", result);
slouken@7141
  1337
            return -1;
slouken@7141
  1338
        }
slouken@7141
  1339
    } else {
slouken@7141
  1340
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_SCISSORTESTENABLE, FALSE);
slouken@6246
  1341
    }
slouken@6246
  1342
    return 0;
slouken@6246
  1343
}
slouken@6246
  1344
slouken@6246
  1345
static int
slouken@5297
  1346
D3D_RenderClear(SDL_Renderer * renderer)
slouken@5297
  1347
{
slouken@5297
  1348
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@5297
  1349
    DWORD color;
slouken@5297
  1350
    HRESULT result;
slouken@7837
  1351
    int BackBufferWidth, BackBufferHeight;
slouken@5297
  1352
slouken@5297
  1353
    if (D3D_ActivateRenderer(renderer) < 0) {
slouken@5297
  1354
        return -1;
slouken@5224
  1355
    }
slouken@5297
  1356
slouken@5297
  1357
    color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
slouken@5297
  1358
slouken@7837
  1359
    if (renderer->target) {
slouken@7837
  1360
        BackBufferWidth = renderer->target->w;
slouken@7837
  1361
        BackBufferHeight = renderer->target->h;
slouken@7837
  1362
    } else {
slouken@7837
  1363
        BackBufferWidth = data->pparams.BackBufferWidth;
slouken@7837
  1364
        BackBufferHeight = data->pparams.BackBufferHeight;
slouken@7837
  1365
    }
slouken@7837
  1366
slouken@10408
  1367
    if (renderer->clipping_enabled) {
slouken@10408
  1368
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_SCISSORTESTENABLE, FALSE);
slouken@10408
  1369
    }
slouken@10408
  1370
slouken@5299
  1371
    /* Don't reset the viewport if we don't have to! */
slouken@5299
  1372
    if (!renderer->viewport.x && !renderer->viewport.y &&
slouken@7837
  1373
        renderer->viewport.w == BackBufferWidth &&
slouken@7837
  1374
        renderer->viewport.h == BackBufferHeight) {
slouken@5299
  1375
        result = IDirect3DDevice9_Clear(data->device, 0, NULL, D3DCLEAR_TARGET, color, 0.0f, 0);
slouken@5299
  1376
    } else {
slouken@5299
  1377
        D3DVIEWPORT9 viewport;
slouken@5297
  1378
slouken@5299
  1379
        /* Clear is defined to clear the entire render target */
slouken@5299
  1380
        viewport.X = 0;
slouken@5299
  1381
        viewport.Y = 0;
slouken@7837
  1382
        viewport.Width = BackBufferWidth;
slouken@7837
  1383
        viewport.Height = BackBufferHeight;
slouken@5299
  1384
        viewport.MinZ = 0.0f;
slouken@5299
  1385
        viewport.MaxZ = 1.0f;
slouken@5299
  1386
        IDirect3DDevice9_SetViewport(data->device, &viewport);
slouken@5299
  1387
slouken@5299
  1388
        result = IDirect3DDevice9_Clear(data->device, 0, NULL, D3DCLEAR_TARGET, color, 0.0f, 0);
slouken@5299
  1389
slouken@5299
  1390
        /* Reset the viewport */
slouken@5299
  1391
        viewport.X = renderer->viewport.x;
slouken@5299
  1392
        viewport.Y = renderer->viewport.y;
slouken@5299
  1393
        viewport.Width = renderer->viewport.w;
slouken@5299
  1394
        viewport.Height = renderer->viewport.h;
slouken@5299
  1395
        viewport.MinZ = 0.0f;
slouken@5299
  1396
        viewport.MaxZ = 1.0f;
slouken@5299
  1397
        IDirect3DDevice9_SetViewport(data->device, &viewport);
slouken@5299
  1398
    }
slouken@5297
  1399
slouken@10408
  1400
    if (renderer->clipping_enabled) {
slouken@10408
  1401
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_SCISSORTESTENABLE, TRUE);
slouken@10408
  1402
    }
slouken@10408
  1403
slouken@5297
  1404
    if (FAILED(result)) {
icculus@7037
  1405
        return D3D_SetError("Clear()", result);
slouken@5297
  1406
    }
slouken@5297
  1407
    return 0;
slouken@5224
  1408
}
slouken@5224
  1409
slouken@5224
  1410
static void
slouken@11282
  1411
D3D_SetBlendMode(D3D_RenderData * data, SDL_BlendMode blendMode)
slouken@2932
  1412
{
slouken@11282
  1413
    if (blendMode == SDL_BLENDMODE_NONE) {
slouken@11282
  1414
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE, FALSE);
slouken@11282
  1415
    } else {
slouken@11282
  1416
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE, TRUE);
slouken@2932
  1417
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
slouken@11282
  1418
                                        GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blendMode)));
slouken@2932
  1419
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
slouken@11282
  1420
                                        GetBlendFunc(SDL_GetBlendModeDstColorFactor(blendMode)));
slouken@7502
  1421
        if (data->enableSeparateAlphaBlend) {
slouken@7502
  1422
            IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLENDALPHA,
slouken@11282
  1423
                                            GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blendMode)));
slouken@7502
  1424
            IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLENDALPHA,
slouken@11282
  1425
                                            GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blendMode)));
slouken@7502
  1426
        }
slouken@2932
  1427
    }
slouken@2932
  1428
}
slouken@2932
  1429
slouken@1895
  1430
static int
slouken@6528
  1431
D3D_RenderDrawPoints(SDL_Renderer * renderer, const SDL_FPoint * points,
slouken@3599
  1432
                     int count)
slouken@1895
  1433
{
slouken@1913
  1434
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@2932
  1435
    DWORD color;
slouken@3536
  1436
    Vertex *vertices;
slouken@3536
  1437
    int i;
slouken@2932
  1438
    HRESULT result;
slouken@2932
  1439
slouken@5297
  1440
    if (D3D_ActivateRenderer(renderer) < 0) {
slouken@5297
  1441
        return -1;
slouken@2932
  1442
    }
slouken@2932
  1443
slouken@3536
  1444
    D3D_SetBlendMode(data, renderer->blendMode);
slouken@3536
  1445
slouken@3536
  1446
    result =
slouken@3536
  1447
        IDirect3DDevice9_SetTexture(data->device, 0,
slouken@3536
  1448
                                    (IDirect3DBaseTexture9 *) 0);
slouken@3536
  1449
    if (FAILED(result)) {
icculus@7037
  1450
        return D3D_SetError("SetTexture()", result);
slouken@3536
  1451
    }
slouken@3536
  1452
slouken@2932
  1453
    color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
slouken@2932
  1454
slouken@3536
  1455
    vertices = SDL_stack_alloc(Vertex, count);
slouken@3536
  1456
    for (i = 0; i < count; ++i) {
slouken@6528
  1457
        vertices[i].x = points[i].x;
slouken@6528
  1458
        vertices[i].y = points[i].y;
slouken@3536
  1459
        vertices[i].z = 0.0f;
slouken@3536
  1460
        vertices[i].color = color;
slouken@3536
  1461
        vertices[i].u = 0.0f;
slouken@3536
  1462
        vertices[i].v = 0.0f;
slouken@3536
  1463
    }
slouken@3536
  1464
    result =
slouken@3536
  1465
        IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_POINTLIST, count,
slouken@3536
  1466
                                         vertices, sizeof(*vertices));
slouken@3536
  1467
    SDL_stack_free(vertices);
slouken@3536
  1468
    if (FAILED(result)) {
icculus@7037
  1469
        return D3D_SetError("DrawPrimitiveUP()", result);
slouken@3536
  1470
    }
slouken@3536
  1471
    return 0;
slouken@3536
  1472
}
slouken@3536
  1473
slouken@3536
  1474
static int
slouken@6528
  1475
D3D_RenderDrawLines(SDL_Renderer * renderer, const SDL_FPoint * points,
slouken@3599
  1476
                    int count)
slouken@3536
  1477
{
slouken@3536
  1478
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@3536
  1479
    DWORD color;
slouken@3536
  1480
    Vertex *vertices;
slouken@3536
  1481
    int i;
slouken@3536
  1482
    HRESULT result;
slouken@3536
  1483
slouken@5297
  1484
    if (D3D_ActivateRenderer(renderer) < 0) {
slouken@5297
  1485
        return -1;
slouken@3536
  1486
    }
slouken@2932
  1487
slouken@2932
  1488
    D3D_SetBlendMode(data, renderer->blendMode);
slouken@2932
  1489
slouken@2933
  1490
    result =
slouken@2933
  1491
        IDirect3DDevice9_SetTexture(data->device, 0,
slouken@2933
  1492
                                    (IDirect3DBaseTexture9 *) 0);
slouken@2932
  1493
    if (FAILED(result)) {
icculus@7037
  1494
        return D3D_SetError("SetTexture()", result);
slouken@2932
  1495
    }
slouken@3536
  1496
slouken@3536
  1497
    color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
slouken@3536
  1498
slouken@3536
  1499
    vertices = SDL_stack_alloc(Vertex, count);
slouken@3536
  1500
    for (i = 0; i < count; ++i) {
slouken@6528
  1501
        vertices[i].x = points[i].x;
slouken@6528
  1502
        vertices[i].y = points[i].y;
slouken@3536
  1503
        vertices[i].z = 0.0f;
slouken@3536
  1504
        vertices[i].color = color;
slouken@3536
  1505
        vertices[i].u = 0.0f;
slouken@3536
  1506
        vertices[i].v = 0.0f;
slouken@3536
  1507
    }
slouken@2932
  1508
    result =
slouken@3551
  1509
        IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_LINESTRIP, count-1,
slouken@2932
  1510
                                         vertices, sizeof(*vertices));
slouken@3551
  1511
slouken@3551
  1512
    /* DirectX 9 has the same line rasterization semantics as GDI,
slouken@3551
  1513
       so we need to close the endpoint of the line */
slouken@6076
  1514
    if (count == 2 ||
slouken@6076
  1515
        points[0].x != points[count-1].x || points[0].y != points[count-1].y) {
slouken@6528
  1516
        vertices[0].x = points[count-1].x;
slouken@6528
  1517
        vertices[0].y = points[count-1].y;
slouken@3551
  1518
        result = IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_POINTLIST, 1, vertices, sizeof(*vertices));
slouken@3551
  1519
    }
slouken@3551
  1520
slouken@3536
  1521
    SDL_stack_free(vertices);
slouken@2932
  1522
    if (FAILED(result)) {
icculus@7037
  1523
        return D3D_SetError("DrawPrimitiveUP()", result);
slouken@2932
  1524
    }
slouken@2932
  1525
    return 0;
slouken@2932
  1526
}
slouken@2932
  1527
slouken@2932
  1528
static int
slouken@6528
  1529
D3D_RenderFillRects(SDL_Renderer * renderer, const SDL_FRect * rects,
slouken@3599
  1530
                    int count)
slouken@2932
  1531
{
slouken@2932
  1532
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@2932
  1533
    DWORD color;
slouken@3536
  1534
    int i;
slouken@3536
  1535
    float minx, miny, maxx, maxy;
slouken@3536
  1536
    Vertex vertices[4];
slouken@1900
  1537
    HRESULT result;
slouken@1900
  1538
slouken@5297
  1539
    if (D3D_ActivateRenderer(renderer) < 0) {
slouken@5297
  1540
        return -1;
slouken@1900
  1541
    }
slouken@1895
  1542
slouken@2932
  1543
    D3D_SetBlendMode(data, renderer->blendMode);
slouken@2932
  1544
slouken@2933
  1545
    result =
slouken@2933
  1546
        IDirect3DDevice9_SetTexture(data->device, 0,
slouken@2933
  1547
                                    (IDirect3DBaseTexture9 *) 0);
slouken@2932
  1548
    if (FAILED(result)) {
icculus@7037
  1549
        return D3D_SetError("SetTexture()", result);
slouken@2932
  1550
    }
slouken@2932
  1551
slouken@2932
  1552
    color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
slouken@2932
  1553
slouken@3536
  1554
    for (i = 0; i < count; ++i) {
slouken@6528
  1555
        const SDL_FRect *rect = &rects[i];
slouken@3536
  1556
slouken@6528
  1557
        minx = rect->x;
slouken@6528
  1558
        miny = rect->y;
slouken@6528
  1559
        maxx = rect->x + rect->w;
slouken@6528
  1560
        maxy = rect->y + rect->h;
slouken@2932
  1561
slouken@3536
  1562
        vertices[0].x = minx;
slouken@3536
  1563
        vertices[0].y = miny;
slouken@3536
  1564
        vertices[0].z = 0.0f;
slouken@3536
  1565
        vertices[0].color = color;
slouken@3536
  1566
        vertices[0].u = 0.0f;
slouken@3536
  1567
        vertices[0].v = 0.0f;
slouken@2932
  1568
slouken@3536
  1569
        vertices[1].x = maxx;
slouken@3536
  1570
        vertices[1].y = miny;
slouken@3536
  1571
        vertices[1].z = 0.0f;
slouken@3536
  1572
        vertices[1].color = color;
slouken@3536
  1573
        vertices[1].u = 0.0f;
slouken@3536
  1574
        vertices[1].v = 0.0f;
slouken@2932
  1575
slouken@3536
  1576
        vertices[2].x = maxx;
slouken@3536
  1577
        vertices[2].y = maxy;
slouken@3536
  1578
        vertices[2].z = 0.0f;
slouken@3536
  1579
        vertices[2].color = color;
slouken@3536
  1580
        vertices[2].u = 0.0f;
slouken@3536
  1581
        vertices[2].v = 0.0f;
slouken@2932
  1582
slouken@3536
  1583
        vertices[3].x = minx;
slouken@3536
  1584
        vertices[3].y = maxy;
slouken@3536
  1585
        vertices[3].z = 0.0f;
slouken@3536
  1586
        vertices[3].color = color;
slouken@3536
  1587
        vertices[3].u = 0.0f;
slouken@3536
  1588
        vertices[3].v = 0.0f;
slouken@3536
  1589
slouken@3536
  1590
        result =
slouken@3536
  1591
            IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN,
slouken@3536
  1592
                                             2, vertices, sizeof(*vertices));
slouken@3536
  1593
        if (FAILED(result)) {
icculus@7037
  1594
            return D3D_SetError("DrawPrimitiveUP()", result);
slouken@3536
  1595
        }
slouken@1900
  1596
    }
slouken@1895
  1597
    return 0;
slouken@1895
  1598
}
slouken@1895
  1599
slouken@7505
  1600
static void
slouken@7505
  1601
D3D_UpdateTextureScaleMode(D3D_RenderData *data, D3D_TextureData *texturedata, unsigned index)
slouken@7505
  1602
{
slouken@7505
  1603
    if (texturedata->scaleMode != data->scaleMode[index]) {
slouken@7505
  1604
        IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MINFILTER,
slouken@7505
  1605
                                         texturedata->scaleMode);
slouken@7505
  1606
        IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MAGFILTER,
slouken@7505
  1607
                                         texturedata->scaleMode);
slouken@7505
  1608
        data->scaleMode[index] = texturedata->scaleMode;
slouken@7505
  1609
    }
slouken@7505
  1610
}
slouken@7505
  1611
slouken@1895
  1612
static int
slouken@1913
  1613
D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@6528
  1614
               const SDL_Rect * srcrect, const SDL_FRect * dstrect)
slouken@1895
  1615
{
slouken@1913
  1616
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@8208
  1617
    D3D_TextureData *texturedata;
slouken@3556
  1618
    LPDIRECT3DPIXELSHADER9 shader = NULL;
slouken@1903
  1619
    float minx, miny, maxx, maxy;
slouken@1904
  1620
    float minu, maxu, minv, maxv;
slouken@1987
  1621
    DWORD color;
slouken@1903
  1622
    Vertex vertices[4];
slouken@1903
  1623
    HRESULT result;
slouken@1895
  1624
slouken@5297
  1625
    if (D3D_ActivateRenderer(renderer) < 0) {
slouken@5297
  1626
        return -1;
slouken@1900
  1627
    }
slouken@1903
  1628
slouken@8208
  1629
    texturedata = (D3D_TextureData *)texture->driverdata;
slouken@8208
  1630
    if (!texturedata) {
slouken@8208
  1631
        SDL_SetError("Texture is not currently available");
slouken@8208
  1632
        return -1;
slouken@8208
  1633
    }
slouken@8208
  1634
slouken@6528
  1635
    minx = dstrect->x - 0.5f;
slouken@6528
  1636
    miny = dstrect->y - 0.5f;
slouken@6528
  1637
    maxx = dstrect->x + dstrect->w - 0.5f;
slouken@6528
  1638
    maxy = dstrect->y + dstrect->h - 0.5f;
slouken@1903
  1639
slouken@1904
  1640
    minu = (float) srcrect->x / texture->w;
slouken@1904
  1641
    maxu = (float) (srcrect->x + srcrect->w) / texture->w;
slouken@1904
  1642
    minv = (float) srcrect->y / texture->h;
slouken@1904
  1643
    maxv = (float) (srcrect->y + srcrect->h) / texture->h;
slouken@1903
  1644
slouken@1987
  1645
    color = D3DCOLOR_ARGB(texture->a, texture->r, texture->g, texture->b);
slouken@1987
  1646
slouken@1903
  1647
    vertices[0].x = minx;
slouken@1903
  1648
    vertices[0].y = miny;
slouken@1903
  1649
    vertices[0].z = 0.0f;
slouken@1987
  1650
    vertices[0].color = color;
slouken@1904
  1651
    vertices[0].u = minu;
slouken@1904
  1652
    vertices[0].v = minv;
slouken@1904
  1653
slouken@1903
  1654
    vertices[1].x = maxx;
slouken@1903
  1655
    vertices[1].y = miny;
slouken@1903
  1656
    vertices[1].z = 0.0f;
slouken@1987
  1657
    vertices[1].color = color;
slouken@1904
  1658
    vertices[1].u = maxu;
slouken@1904
  1659
    vertices[1].v = minv;
slouken@1904
  1660
slouken@1903
  1661
    vertices[2].x = maxx;
slouken@1903
  1662
    vertices[2].y = maxy;
slouken@1903
  1663
    vertices[2].z = 0.0f;
slouken@1987
  1664
    vertices[2].color = color;
slouken@1904
  1665
    vertices[2].u = maxu;
slouken@1904
  1666
    vertices[2].v = maxv;
slouken@1904
  1667
slouken@1903
  1668
    vertices[3].x = minx;
slouken@1903
  1669
    vertices[3].y = maxy;
slouken@1903
  1670
    vertices[3].z = 0.0f;
slouken@1987
  1671
    vertices[3].color = color;
slouken@1904
  1672
    vertices[3].u = minu;
slouken@1904
  1673
    vertices[3].v = maxv;
slouken@1903
  1674
slouken@2932
  1675
    D3D_SetBlendMode(data, texture->blendMode);
slouken@1916
  1676
slouken@7505
  1677
    D3D_UpdateTextureScaleMode(data, texturedata, 0);
slouken@1917
  1678
slouken@8822
  1679
    if (D3D_BindTextureRep(data->device, &texturedata->texture, 0) < 0) {
slouken@8822
  1680
        return -1;
slouken@1903
  1681
    }
slouken@7505
  1682
slouken@7505
  1683
    if (texturedata->yuv) {
slouken@7505
  1684
        shader = data->ps_yuv;
slouken@7505
  1685
slouken@7505
  1686
        D3D_UpdateTextureScaleMode(data, texturedata, 1);
slouken@7505
  1687
        D3D_UpdateTextureScaleMode(data, texturedata, 2);
slouken@7505
  1688
slouken@8822
  1689
        if (D3D_BindTextureRep(data->device, &texturedata->utexture, 1) < 0) {
slouken@8822
  1690
            return -1;
slouken@7505
  1691
        }
slouken@8822
  1692
        if (D3D_BindTextureRep(data->device, &texturedata->vtexture, 2) < 0) {
slouken@8822
  1693
            return -1;
slouken@7505
  1694
        }
slouken@7505
  1695
    }
slouken@7505
  1696
slouken@3556
  1697
    if (shader) {
slouken@3556
  1698
        result = IDirect3DDevice9_SetPixelShader(data->device, shader);
slouken@3556
  1699
        if (FAILED(result)) {
icculus@7037
  1700
            return D3D_SetError("SetShader()", result);
slouken@3556
  1701
        }
slouken@3556
  1702
    }
slouken@1903
  1703
    result =
slouken@1903
  1704
        IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN, 2,
slouken@1903
  1705
                                         vertices, sizeof(*vertices));
slouken@1903
  1706
    if (FAILED(result)) {
icculus@7037
  1707
        return D3D_SetError("DrawPrimitiveUP()", result);
slouken@1903
  1708
    }
slouken@3556
  1709
    if (shader) {
slouken@3556
  1710
        result = IDirect3DDevice9_SetPixelShader(data->device, NULL);
slouken@3556
  1711
        if (FAILED(result)) {
icculus@7037
  1712
            return D3D_SetError("SetShader()", result);
slouken@3556
  1713
        }
slouken@3556
  1714
    }
slouken@1895
  1715
    return 0;
slouken@1895
  1716
}
slouken@1895
  1717
gabomdq@6320
  1718
gabomdq@6320
  1719
static int
gabomdq@6320
  1720
D3D_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@6528
  1721
               const SDL_Rect * srcrect, const SDL_FRect * dstrect,
slouken@6528
  1722
               const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip)
gabomdq@6320
  1723
{
gabomdq@6320
  1724
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@8208
  1725
    D3D_TextureData *texturedata;
gabomdq@6320
  1726
    LPDIRECT3DPIXELSHADER9 shader = NULL;
gabomdq@6320
  1727
    float minx, miny, maxx, maxy;
gabomdq@6320
  1728
    float minu, maxu, minv, maxv;
gabomdq@6320
  1729
    float centerx, centery;
gabomdq@6320
  1730
    DWORD color;
gabomdq@6320
  1731
    Vertex vertices[4];
slouken@8599
  1732
    Float4X4 modelMatrix;
gabomdq@6320
  1733
    HRESULT result;
gabomdq@6320
  1734
gabomdq@6320
  1735
    if (D3D_ActivateRenderer(renderer) < 0) {
gabomdq@6320
  1736
        return -1;
gabomdq@6320
  1737
    }
gabomdq@6320
  1738
slouken@8208
  1739
    texturedata = (D3D_TextureData *)texture->driverdata;
slouken@8208
  1740
    if (!texturedata) {
slouken@8208
  1741
        SDL_SetError("Texture is not currently available");
slouken@8208
  1742
        return -1;
slouken@8208
  1743
    }
slouken@8208
  1744
slouken@6528
  1745
    centerx = center->x;
slouken@6528
  1746
    centery = center->y;
gabomdq@6320
  1747
slouken@10584
  1748
    minx = -centerx;
slouken@10584
  1749
    maxx = dstrect->w - centerx;
slouken@10584
  1750
    miny = -centery;
slouken@10584
  1751
    maxy = dstrect->h - centery;
gabomdq@6320
  1752
gabomdq@6320
  1753
    minu = (float) srcrect->x / texture->w;
gabomdq@6320
  1754
    maxu = (float) (srcrect->x + srcrect->w) / texture->w;
gabomdq@6320
  1755
    minv = (float) srcrect->y / texture->h;
gabomdq@6320
  1756
    maxv = (float) (srcrect->y + srcrect->h) / texture->h;
gabomdq@6320
  1757
slouken@10584
  1758
    if (flip & SDL_FLIP_HORIZONTAL) {
slouken@10584
  1759
        float tmp = maxu;
slouken@10584
  1760
        maxu = minu;
slouken@10584
  1761
        minu = tmp;
slouken@10584
  1762
    }
slouken@10584
  1763
    if (flip & SDL_FLIP_VERTICAL) {
slouken@10584
  1764
        float tmp = maxv;
slouken@10584
  1765
        maxv = minv;
slouken@10584
  1766
        minv = tmp;
slouken@10584
  1767
    }
slouken@10584
  1768
gabomdq@6320
  1769
    color = D3DCOLOR_ARGB(texture->a, texture->r, texture->g, texture->b);
gabomdq@6320
  1770
gabomdq@6320
  1771
    vertices[0].x = minx;
gabomdq@6320
  1772
    vertices[0].y = miny;
gabomdq@6320
  1773
    vertices[0].z = 0.0f;
gabomdq@6320
  1774
    vertices[0].color = color;
gabomdq@6320
  1775
    vertices[0].u = minu;
gabomdq@6320
  1776
    vertices[0].v = minv;
gabomdq@6320
  1777
gabomdq@6320
  1778
    vertices[1].x = maxx;
gabomdq@6320
  1779
    vertices[1].y = miny;
gabomdq@6320
  1780
    vertices[1].z = 0.0f;
gabomdq@6320
  1781
    vertices[1].color = color;
gabomdq@6320
  1782
    vertices[1].u = maxu;
gabomdq@6320
  1783
    vertices[1].v = minv;
gabomdq@6320
  1784
gabomdq@6320
  1785
    vertices[2].x = maxx;
gabomdq@6320
  1786
    vertices[2].y = maxy;
gabomdq@6320
  1787
    vertices[2].z = 0.0f;
gabomdq@6320
  1788
    vertices[2].color = color;
gabomdq@6320
  1789
    vertices[2].u = maxu;
gabomdq@6320
  1790
    vertices[2].v = maxv;
gabomdq@6320
  1791
gabomdq@6320
  1792
    vertices[3].x = minx;
gabomdq@6320
  1793
    vertices[3].y = maxy;
gabomdq@6320
  1794
    vertices[3].z = 0.0f;
gabomdq@6320
  1795
    vertices[3].color = color;
gabomdq@6320
  1796
    vertices[3].u = minu;
gabomdq@6320
  1797
    vertices[3].v = maxv;
gabomdq@6320
  1798
gabomdq@6320
  1799
    D3D_SetBlendMode(data, texture->blendMode);
gabomdq@6320
  1800
slouken@7191
  1801
    /* Rotate and translate */
slouken@8599
  1802
    modelMatrix = MatrixMultiply(
slouken@8599
  1803
            MatrixRotationZ((float)(M_PI * (float) angle / 180.0f)),
slouken@10584
  1804
            MatrixTranslation(dstrect->x + center->x - 0.5f, dstrect->y + center->y - 0.5f, 0));
slouken@8599
  1805
    IDirect3DDevice9_SetTransform(data->device, D3DTS_VIEW, (D3DMATRIX*)&modelMatrix);
gabomdq@6320
  1806
slouken@7505
  1807
    D3D_UpdateTextureScaleMode(data, texturedata, 0);
gabomdq@6320
  1808
slouken@8822
  1809
    if (D3D_BindTextureRep(data->device, &texturedata->texture, 0) < 0) {
slouken@8822
  1810
        return -1;
gabomdq@6320
  1811
    }
slouken@7505
  1812
slouken@7505
  1813
    if (texturedata->yuv) {
slouken@7505
  1814
        shader = data->ps_yuv;
slouken@7505
  1815
slouken@7505
  1816
        D3D_UpdateTextureScaleMode(data, texturedata, 1);
slouken@7505
  1817
        D3D_UpdateTextureScaleMode(data, texturedata, 2);
slouken@8822
  1818
        
slouken@8822
  1819
        if (D3D_BindTextureRep(data->device, &texturedata->utexture, 1) < 0) {
slouken@8822
  1820
            return -1;
slouken@7505
  1821
        }
slouken@8822
  1822
        if (D3D_BindTextureRep(data->device, &texturedata->vtexture, 2) < 0) {
slouken@8822
  1823
            return -1;
slouken@7505
  1824
        }
slouken@7505
  1825
    }
slouken@7505
  1826
gabomdq@6320
  1827
    if (shader) {
gabomdq@6320
  1828
        result = IDirect3DDevice9_SetPixelShader(data->device, shader);
gabomdq@6320
  1829
        if (FAILED(result)) {
icculus@7037
  1830
            return D3D_SetError("SetShader()", result);
gabomdq@6320
  1831
        }
gabomdq@6320
  1832
    }
gabomdq@6320
  1833
    result =
gabomdq@6320
  1834
        IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN, 2,
gabomdq@6320
  1835
                                         vertices, sizeof(*vertices));
gabomdq@6320
  1836
    if (FAILED(result)) {
icculus@7037
  1837
        return D3D_SetError("DrawPrimitiveUP()", result);
gabomdq@6320
  1838
    }
gabomdq@6320
  1839
    if (shader) {
gabomdq@6320
  1840
        result = IDirect3DDevice9_SetPixelShader(data->device, NULL);
gabomdq@6320
  1841
        if (FAILED(result)) {
icculus@7037
  1842
            return D3D_SetError("SetShader()", result);
gabomdq@6320
  1843
        }
gabomdq@6320
  1844
    }
slouken@8599
  1845
slouken@8599
  1846
    modelMatrix = MatrixIdentity();
slouken@8599
  1847
    IDirect3DDevice9_SetTransform(data->device, D3DTS_VIEW, (D3DMATRIX*)&modelMatrix);
gabomdq@6320
  1848
    return 0;
gabomdq@6320
  1849
}
gabomdq@6320
  1850
slouken@3427
  1851
static int
slouken@3427
  1852
D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
slouken@3480
  1853
                     Uint32 format, void * pixels, int pitch)
slouken@3427
  1854
{
slouken@3549
  1855
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@3549
  1856
    D3DSURFACE_DESC desc;
slouken@3427
  1857
    LPDIRECT3DSURFACE9 backBuffer;
slouken@3549
  1858
    LPDIRECT3DSURFACE9 surface;
slouken@3549
  1859
    RECT d3drect;
slouken@3549
  1860
    D3DLOCKED_RECT locked;
slouken@3549
  1861
    HRESULT result;
slouken@3549
  1862
slouken@9085
  1863
    if (data->currentRenderTarget) {
slouken@9085
  1864
        backBuffer = data->currentRenderTarget;
slouken@9085
  1865
    } else {
slouken@9085
  1866
        backBuffer = data->defaultRenderTarget;
slouken@3549
  1867
    }
slouken@3427
  1868
slouken@3549
  1869
    result = IDirect3DSurface9_GetDesc(backBuffer, &desc);
slouken@3549
  1870
    if (FAILED(result)) {
slouken@3549
  1871
        IDirect3DSurface9_Release(backBuffer);
icculus@7037
  1872
        return D3D_SetError("GetDesc()", result);
slouken@3549
  1873
    }
slouken@3549
  1874
slouken@3549
  1875
    result = IDirect3DDevice9_CreateOffscreenPlainSurface(data->device, desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surface, NULL);
slouken@3549
  1876
    if (FAILED(result)) {
slouken@3549
  1877
        IDirect3DSurface9_Release(backBuffer);
icculus@7037
  1878
        return D3D_SetError("CreateOffscreenPlainSurface()", result);
slouken@3549
  1879
    }
slouken@3427
  1880
slouken@3549
  1881
    result = IDirect3DDevice9_GetRenderTargetData(data->device, backBuffer, surface);
slouken@3549
  1882
    if (FAILED(result)) {
slouken@3549
  1883
        IDirect3DSurface9_Release(surface);
slouken@3549
  1884
        IDirect3DSurface9_Release(backBuffer);
icculus@7037
  1885
        return D3D_SetError("GetRenderTargetData()", result);
slouken@3549
  1886
    }
slouken@3427
  1887
slouken@3549
  1888
    d3drect.left = rect->x;
slouken@3549
  1889
    d3drect.right = rect->x + rect->w;
slouken@3549
  1890
    d3drect.top = rect->y;
slouken@3549
  1891
    d3drect.bottom = rect->y + rect->h;
slouken@3427
  1892
slouken@3549
  1893
    result = IDirect3DSurface9_LockRect(surface, &locked, &d3drect, D3DLOCK_READONLY);
slouken@3549
  1894
    if (FAILED(result)) {
slouken@3549
  1895
        IDirect3DSurface9_Release(surface);
slouken@3549
  1896
        IDirect3DSurface9_Release(backBuffer);
icculus@7037
  1897
        return D3D_SetError("LockRect()", result);
slouken@3549
  1898
    }
slouken@3427
  1899
slouken@3549
  1900
    SDL_ConvertPixels(rect->w, rect->h,
slouken@5156
  1901
                      D3DFMTToPixelFormat(desc.Format), locked.pBits, locked.Pitch,
slouken@3549
  1902
                      format, pixels, pitch);
slouken@3549
  1903
slouken@3549
  1904
    IDirect3DSurface9_UnlockRect(surface);
slouken@3549
  1905
slouken@3549
  1906
    IDirect3DSurface9_Release(surface);
slouken@3549
  1907
slouken@3549
  1908
    return 0;
slouken@3427
  1909
}
slouken@3427
  1910
slouken@1895
  1911
static void
slouken@1913
  1912
D3D_RenderPresent(SDL_Renderer * renderer)
slouken@1895
  1913
{
slouken@1913
  1914
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@1900
  1915
    HRESULT result;
slouken@1900
  1916
slouken@1900
  1917
    if (!data->beginScene) {
slouken@1900
  1918
        IDirect3DDevice9_EndScene(data->device);
slouken@1900
  1919
        data->beginScene = SDL_TRUE;
slouken@1900
  1920
    }
slouken@1900
  1921
slouken@1975
  1922
    result = IDirect3DDevice9_TestCooperativeLevel(data->device);
slouken@1975
  1923
    if (result == D3DERR_DEVICELOST) {
slouken@1975
  1924
        /* We'll reset later */
slouken@1975
  1925
        return;
slouken@1975
  1926
    }
slouken@1975
  1927
    if (result == D3DERR_DEVICENOTRESET) {
slouken@1975
  1928
        D3D_Reset(renderer);
slouken@1975
  1929
    }
slouken@1900
  1930
    result = IDirect3DDevice9_Present(data->device, NULL, NULL, NULL, NULL);
slouken@1900
  1931
    if (FAILED(result)) {
slouken@1900
  1932
        D3D_SetError("Present()", result);
slouken@1900
  1933
    }
slouken@1895
  1934
}
slouken@1895
  1935
slouken@1895
  1936
static void
slouken@1913
  1937
D3D_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1895
  1938
{
slouken@1913
  1939
    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
slouken@1895
  1940
slouken@1895
  1941
    if (!data) {
slouken@1895
  1942
        return;
slouken@1895
  1943
    }
slouken@8792
  1944
    D3D_DestroyTextureRep(&data->texture);
slouken@8792
  1945
    D3D_DestroyTextureRep(&data->utexture);
slouken@8792
  1946
    D3D_DestroyTextureRep(&data->vtexture);
slouken@7719
  1947
    SDL_free(data->pixels);
slouken@1895
  1948
    SDL_free(data);
slouken@1895
  1949
    texture->driverdata = NULL;
slouken@1895
  1950
}
slouken@1895
  1951
slouken@1975
  1952
static void
slouken@1913
  1953
D3D_DestroyRenderer(SDL_Renderer * renderer)
slouken@1895
  1954
{
slouken@1913
  1955
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@1895
  1956
slouken@1895
  1957
    if (data) {
slouken@7191
  1958
        /* Release the render target */
slouken@6895
  1959
        if (data->defaultRenderTarget) {
slouken@6895
  1960
            IDirect3DSurface9_Release(data->defaultRenderTarget);
slouken@6895
  1961
            data->defaultRenderTarget = NULL;
slouken@6895
  1962
        }
slouken@6232
  1963
        if (data->currentRenderTarget != NULL) {
slouken@6232
  1964
            IDirect3DSurface9_Release(data->currentRenderTarget);
slouken@6232
  1965
            data->currentRenderTarget = NULL;
slouken@6232
  1966
        }
icculus@7658
  1967
        if (data->ps_yuv) {
icculus@7658
  1968
            IDirect3DPixelShader9_Release(data->ps_yuv);
icculus@7658
  1969
        }
slouken@1900
  1970
        if (data->device) {
slouken@1900
  1971
            IDirect3DDevice9_Release(data->device);
slouken@1900
  1972
        }
slouken@5154
  1973
        if (data->d3d) {
slouken@5154
  1974
            IDirect3D9_Release(data->d3d);
slouken@5154
  1975
            SDL_UnloadObject(data->d3dDLL);
slouken@5154
  1976
        }
slouken@1895
  1977
        SDL_free(data);
slouken@1895
  1978
    }
slouken@1895
  1979
    SDL_free(renderer);
slouken@1895
  1980
}
icculus@8130
  1981
#endif /* SDL_VIDEO_RENDER_D3D && !SDL_RENDER_DISABLED */
slouken@1895
  1982
icculus@8131
  1983
#ifdef __WIN32__
icculus@8131
  1984
/* This function needs to always exist on Windows, for the Dynamic API. */
slouken@7763
  1985
IDirect3DDevice9 *
slouken@7765
  1986
SDL_RenderGetD3D9Device(SDL_Renderer * renderer)
slouken@7763
  1987
{
icculus@8130
  1988
    IDirect3DDevice9 *device = NULL;
icculus@8130
  1989
icculus@8130
  1990
#if SDL_VIDEO_RENDER_D3D && !SDL_RENDER_DISABLED
slouken@7877
  1991
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@7763
  1992
philipp@8778
  1993
    /* Make sure that this is a D3D renderer */
slouken@7877
  1994
    if (renderer->DestroyRenderer != D3D_DestroyRenderer) {
slouken@7877
  1995
        SDL_SetError("Renderer is not a D3D renderer");
slouken@7877
  1996
        return NULL;
slouken@7877
  1997
    }
slouken@7766
  1998
slouken@7877
  1999
    device = data->device;
slouken@7877
  2000
    if (device) {
slouken@8207
  2001
        IDirect3DDevice9_AddRef(device);
slouken@7877
  2002
    }
icculus@8130
  2003
#endif /* SDL_VIDEO_RENDER_D3D && !SDL_RENDER_DISABLED */
icculus@8130
  2004
slouken@7877
  2005
    return device;
slouken@7763
  2006
}
slouken@8193
  2007
#endif /* __WIN32__ */
slouken@7763
  2008
slouken@1895
  2009
/* vi: set ts=4 sw=4 expandtab: */