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