src/render/direct3d/SDL_render_d3d.c
author Sam Lantinga <slouken@libsdl.org>
Tue, 23 Jul 2013 08:06:49 -0700
changeset 7502 6ff02ff3cf06
parent 7472 0ec51bd57d56
child 7505 bc709c9493e7
permissions -rw-r--r--
Updated blend semantics so blending uses the following formula:
dstRGB = (srcRGB * srcA) + (dstRGB * (1-srcA))
dstA = srcA + (dstA * (1-srcA))
This allows proper compositing semantics without requiring premultiplied alpha.

Needs full unit test coverage and bug fixes!
slouken@1895
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@6885
     3
  Copyright (C) 1997-2013 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
*/
slouken@1895
    21
#include "SDL_config.h"
slouken@1895
    22
slouken@5226
    23
#if SDL_VIDEO_RENDER_D3D && !SDL_RENDER_DISABLED
slouken@5226
    24
slouken@1895
    25
slouken@5154
    26
#include "../../core/windows/SDL_windows.h"
slouken@5154
    27
slouken@5484
    28
#include "SDL_hints.h"
slouken@5154
    29
#include "SDL_loadso.h"
slouken@5154
    30
#include "SDL_syswm.h"
slouken@5154
    31
#include "../SDL_sysrender.h"
philipp@7369
    32
#include <stdio.h>
slouken@5154
    33
slouken@5154
    34
#if SDL_VIDEO_RENDER_D3D
slouken@5154
    35
#define D3D_DEBUG_INFO
slouken@5154
    36
#include <d3d9.h>
slouken@5154
    37
#endif
slouken@1895
    38
gabomdq@6320
    39
gabomdq@6320
    40
typedef interface ID3DXMatrixStack *LPD3DXMATRIXSTACK;
gabomdq@6320
    41
typedef struct _D3DMATRIX D3DXMATRIX, *LPD3DXMATRIX;
gabomdq@6320
    42
typedef struct _D3DVECTOR D3DXVECTOR3, *LPD3DXVECTOR3;
gabomdq@6320
    43
gabomdq@6320
    44
DEFINE_GUID(IID_ID3DXMatrixStack,
gabomdq@6320
    45
0xc7885ba7, 0xf990, 0x4fe7, 0x92, 0x2d, 0x85, 0x15, 0xe4, 0x77, 0xdd, 0x85);
gabomdq@6320
    46
gabomdq@6320
    47
#undef INTERFACE
gabomdq@6320
    48
#define INTERFACE ID3DXMatrixStack
gabomdq@6320
    49
gabomdq@6320
    50
DECLARE_INTERFACE_(ID3DXMatrixStack, IUnknown)
gabomdq@6320
    51
{
gabomdq@6320
    52
    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
gabomdq@6320
    53
    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
gabomdq@6320
    54
    STDMETHOD_(ULONG,Release)(THIS) PURE;
gabomdq@6320
    55
    STDMETHOD(Pop)(THIS) PURE;
gabomdq@6320
    56
    STDMETHOD(Push)(THIS) PURE;
gabomdq@6320
    57
    STDMETHOD(LoadIdentity)(THIS) PURE;
gabomdq@6320
    58
    STDMETHOD(LoadMatrix)(THIS_ CONST D3DXMATRIX* pM ) PURE;
gabomdq@6320
    59
    STDMETHOD(MultMatrix)(THIS_ CONST D3DXMATRIX* pM ) PURE;
gabomdq@6320
    60
    STDMETHOD(MultMatrixLocal)(THIS_ CONST D3DXMATRIX* pM ) PURE;
gabomdq@6320
    61
    STDMETHOD(RotateAxis)(THIS_ CONST D3DXVECTOR3* pV, FLOAT Angle) PURE;
gabomdq@6320
    62
    STDMETHOD(RotateAxisLocal)(THIS_ CONST D3DXVECTOR3* pV, FLOAT Angle) PURE;
gabomdq@6320
    63
    STDMETHOD(RotateYawPitchRoll)(THIS_ FLOAT Yaw, FLOAT Pitch, FLOAT Roll) PURE;
gabomdq@6320
    64
    STDMETHOD(RotateYawPitchRollLocal)(THIS_ FLOAT Yaw, FLOAT Pitch, FLOAT Roll) PURE;
gabomdq@6320
    65
    STDMETHOD(Scale)(THIS_ FLOAT x, FLOAT y, FLOAT z) PURE;
gabomdq@6320
    66
    STDMETHOD(ScaleLocal)(THIS_ FLOAT x, FLOAT y, FLOAT z) PURE;
gabomdq@6320
    67
    STDMETHOD(Translate)(THIS_ FLOAT x, FLOAT y, FLOAT z ) PURE;
gabomdq@6320
    68
    STDMETHOD(TranslateLocal)(THIS_ FLOAT x, FLOAT y, FLOAT z) PURE;
gabomdq@6320
    69
    STDMETHOD_(D3DXMATRIX*, GetTop)(THIS) PURE;
gabomdq@6320
    70
};
gabomdq@6320
    71
gabomdq@6320
    72
#undef INTERFACE
gabomdq@6320
    73
gabomdq@6320
    74
#if !defined(__cplusplus) || defined(CINTERFACE)
gabomdq@6320
    75
#define ID3DXMatrixStack_QueryInterface(p,a,b)            (p)->lpVtbl->QueryInterface(p,a,b)
gabomdq@6320
    76
#define ID3DXMatrixStack_AddRef(p)                        (p)->lpVtbl->AddRef(p)
gabomdq@6320
    77
#define ID3DXMatrixStack_Release(p)                       (p)->lpVtbl->Release(p)
gabomdq@6320
    78
#define ID3DXMatrixStack_Pop(p)                           (p)->lpVtbl->Pop(p)
gabomdq@6320
    79
#define ID3DXMatrixStack_Push(p)                          (p)->lpVtbl->Push(p)
gabomdq@6320
    80
#define ID3DXMatrixStack_LoadIdentity(p)                  (p)->lpVtbl->LoadIdentity(p)
gabomdq@6320
    81
#define ID3DXMatrixStack_LoadMatrix(p,a)                  (p)->lpVtbl->LoadMatrix(p,a)
gabomdq@6320
    82
#define ID3DXMatrixStack_MultMatrix(p,a)                  (p)->lpVtbl->MultMatrix(p,a)
gabomdq@6320
    83
#define ID3DXMatrixStack_MultMatrixLocal(p,a)             (p)->lpVtbl->MultMatrixLocal(p,a)
gabomdq@6320
    84
#define ID3DXMatrixStack_RotateAxis(p,a,b)                (p)->lpVtbl->RotateAxis(p,a,b)
gabomdq@6320
    85
#define ID3DXMatrixStack_RotateAxisLocal(p,a,b)           (p)->lpVtbl->RotateAxisLocal(p,a,b)
gabomdq@6320
    86
#define ID3DXMatrixStack_RotateYawPitchRoll(p,a,b,c)      (p)->lpVtbl->RotateYawPitchRoll(p,a,b,c)
gabomdq@6320
    87
#define ID3DXMatrixStack_RotateYawPitchRollLocal(p,a,b,c) (p)->lpVtbl->RotateYawPitchRollLocal(p,a,b,c)
gabomdq@6320
    88
#define ID3DXMatrixStack_Scale(p,a,b,c)                   (p)->lpVtbl->Scale(p,a,b,c)
gabomdq@6320
    89
#define ID3DXMatrixStack_ScaleLocal(p,a,b,c)              (p)->lpVtbl->ScaleLocal(p,a,b,c)
gabomdq@6320
    90
#define ID3DXMatrixStack_Translate(p,a,b,c)               (p)->lpVtbl->Translate(p,a,b,c)
gabomdq@6320
    91
#define ID3DXMatrixStack_TranslateLocal(p,a,b,c)          (p)->lpVtbl->TranslateLocal(p,a,b,c)
gabomdq@6320
    92
#define ID3DXMatrixStack_GetTop(p)                        (p)->lpVtbl->GetTop(p)
gabomdq@6320
    93
#else
gabomdq@6320
    94
#define ID3DXMatrixStack_QueryInterface(p,a,b)            (p)->QueryInterface(a,b)
gabomdq@6320
    95
#define ID3DXMatrixStack_AddRef(p)                        (p)->AddRef()
gabomdq@6320
    96
#define ID3DXMatrixStack_Release(p)                       (p)->Release()
gabomdq@6320
    97
#define ID3DXMatrixStack_Pop(p)    (p)->Pop()
gabomdq@6320
    98
#define ID3DXMatrixStack_Push(p)    (p)->Push()
gabomdq@6320
    99
#define ID3DXMatrixStack_LoadIdentity(p)    (p)->LoadIdentity()
gabomdq@6320
   100
#define ID3DXMatrixStack_LoadMatrix(p,a)    (p)->LoadMatrix(a)
gabomdq@6320
   101
#define ID3DXMatrixStack_MultMatrix(p,a)    (p)->MultMatrix(a)
gabomdq@6320
   102
#define ID3DXMatrixStack_MultMatrixLocal(p,a)    (p)->MultMatrixLocal(a)
gabomdq@6320
   103
#define ID3DXMatrixStack_RotateAxis(p,a,b)    (p)->RotateAxis(a,b)
gabomdq@6320
   104
#define ID3DXMatrixStack_RotateAxisLocal(p,a,b)    (p)->RotateAxisLocal(a,b)
gabomdq@6320
   105
#define ID3DXMatrixStack_RotateYawPitchRoll(p,a,b,c)    (p)->RotateYawPitchRollLocal(a,b,c)
gabomdq@6320
   106
#define ID3DXMatrixStack_Scale(p,a,b,c)    (p)->Scale(a,b,c)
gabomdq@6320
   107
#define ID3DXMatrixStack_ScaleLocal(p,a,b,c)    (p)->ScaleLocal(a,b,c)
gabomdq@6320
   108
#define ID3DXMatrixStack_Translate(p,a,b,c)    (p)->Translate(a,b,c)
gabomdq@6320
   109
#define ID3DXMatrixStack_TranslateLocal(p,a,b,c)    (p)->TranslateLocal(a,b,c)
gabomdq@6320
   110
#define ID3DXMatrixStack_GetTop(p)    (p)->GetTop()
gabomdq@6320
   111
#endif
gabomdq@6320
   112
gabomdq@6320
   113
#ifdef __cplusplus
gabomdq@6320
   114
extern "C" {
gabomdq@6320
   115
#endif
gabomdq@6320
   116
gabomdq@6320
   117
HRESULT WINAPI D3DXCreateMatrixStack(DWORD flags, LPD3DXMATRIXSTACK* ppstack);
gabomdq@6320
   118
gabomdq@6320
   119
#ifdef __cplusplus
gabomdq@6320
   120
}
gabomdq@6320
   121
#endif
gabomdq@6320
   122
slouken@3556
   123
#ifdef ASSEMBLE_SHADER
slouken@7191
   124
/**************************************************************************
slouken@7191
   125
 * ID3DXBuffer:
slouken@7191
   126
 * ------------
slouken@7191
   127
 * The buffer object is used by D3DX to return arbitrary size data.
slouken@7191
   128
 *
slouken@7191
   129
 * GetBufferPointer -
slouken@7191
   130
 *    Returns a pointer to the beginning of the buffer.
slouken@7191
   131
 *
slouken@7191
   132
 * GetBufferSize -
slouken@7191
   133
 *    Returns the size of the buffer, in bytes.
slouken@7191
   134
 **************************************************************************/
slouken@3556
   135
slouken@3556
   136
typedef interface ID3DXBuffer ID3DXBuffer;
slouken@3556
   137
typedef interface ID3DXBuffer *LPD3DXBUFFER;
slouken@3556
   138
slouken@7191
   139
/* {8BA5FB08-5195-40e2-AC58-0D989C3A0102} */
slouken@7191
   140
DEFINE_GUID(IID_ID3DXBuffer,
slouken@3556
   141
0x8ba5fb08, 0x5195, 0x40e2, 0xac, 0x58, 0xd, 0x98, 0x9c, 0x3a, 0x1, 0x2);
slouken@3556
   142
slouken@3556
   143
#undef INTERFACE
slouken@3556
   144
#define INTERFACE ID3DXBuffer
slouken@3556
   145
slouken@3556
   146
typedef interface ID3DXBuffer {
slouken@3556
   147
    const struct ID3DXBufferVtbl FAR* lpVtbl;
slouken@3556
   148
} ID3DXBuffer;
slouken@3556
   149
typedef const struct ID3DXBufferVtbl ID3DXBufferVtbl;
slouken@3556
   150
const struct ID3DXBufferVtbl
slouken@3556
   151
{
slouken@7191
   152
    /* IUnknown */
slouken@3556
   153
    STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE;
slouken@3556
   154
    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
slouken@3556
   155
    STDMETHOD_(ULONG, Release)(THIS) PURE;
slouken@3556
   156
slouken@7191
   157
    /* ID3DXBuffer */
slouken@3556
   158
    STDMETHOD_(LPVOID, GetBufferPointer)(THIS) PURE;
slouken@3556
   159
    STDMETHOD_(DWORD, GetBufferSize)(THIS) PURE;
slouken@3556
   160
};
slouken@3556
   161
slouken@3556
   162
HRESULT WINAPI
slouken@3556
   163
    D3DXAssembleShader(
slouken@3556
   164
        LPCSTR                          pSrcData,
slouken@3556
   165
        UINT                            SrcDataLen,
slouken@3556
   166
        CONST LPVOID*                   pDefines,
slouken@3556
   167
        LPVOID                          pInclude,
slouken@3556
   168
        DWORD                           Flags,
slouken@3556
   169
        LPD3DXBUFFER*                   ppShader,
slouken@3556
   170
        LPD3DXBUFFER*                   ppErrorMsgs);
slouken@3556
   171
slouken@3556
   172
#endif /* ASSEMBLE_SHADER */
slouken@3556
   173
slouken@3556
   174
slouken@1895
   175
/* Direct3D renderer implementation */
slouken@1895
   176
slouken@1913
   177
static SDL_Renderer *D3D_CreateRenderer(SDL_Window * window, Uint32 flags);
slouken@5297
   178
static void D3D_WindowEvent(SDL_Renderer * renderer,
slouken@5297
   179
                            const SDL_WindowEvent *event);
slouken@1913
   180
static int D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
slouken@1913
   181
static int D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1913
   182
                             const SDL_Rect * rect, const void *pixels,
slouken@1913
   183
                             int pitch);
slouken@1913
   184
static int D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@5156
   185
                           const SDL_Rect * rect, void **pixels, int *pitch);
slouken@1913
   186
static void D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
slouken@6247
   187
static int D3D_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture);
slouken@5297
   188
static int D3D_UpdateViewport(SDL_Renderer * renderer);
slouken@7141
   189
static int D3D_UpdateClipRect(SDL_Renderer * renderer);
slouken@5297
   190
static int D3D_RenderClear(SDL_Renderer * renderer);
slouken@3599
   191
static int D3D_RenderDrawPoints(SDL_Renderer * renderer,
slouken@6528
   192
                                const SDL_FPoint * points, int count);
slouken@3599
   193
static int D3D_RenderDrawLines(SDL_Renderer * renderer,
slouken@6528
   194
                               const SDL_FPoint * points, int count);
slouken@3599
   195
static int D3D_RenderFillRects(SDL_Renderer * renderer,
slouken@6528
   196
                               const SDL_FRect * rects, int count);
slouken@1913
   197
static int D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@6528
   198
                          const SDL_Rect * srcrect, const SDL_FRect * dstrect);
gabomdq@6320
   199
static int D3D_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@6528
   200
                          const SDL_Rect * srcrect, const SDL_FRect * dstrect,
slouken@6528
   201
                          const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip);
slouken@3427
   202
static int D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
slouken@3480
   203
                                Uint32 format, void * pixels, int pitch);
slouken@1913
   204
static void D3D_RenderPresent(SDL_Renderer * renderer);
slouken@1913
   205
static void D3D_DestroyTexture(SDL_Renderer * renderer,
slouken@1913
   206
                               SDL_Texture * texture);
slouken@1913
   207
static void D3D_DestroyRenderer(SDL_Renderer * renderer);
slouken@1895
   208
slouken@1895
   209
slouken@1913
   210
SDL_RenderDriver D3D_RenderDriver = {
slouken@1913
   211
    D3D_CreateRenderer,
slouken@1895
   212
    {
slouken@5186
   213
     "direct3d",
slouken@6237
   214
     (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE),
slouken@5156
   215
     1,
slouken@5156
   216
     {SDL_PIXELFORMAT_ARGB8888},
slouken@1895
   217
     0,
slouken@1895
   218
     0}
slouken@1895
   219
};
slouken@1895
   220
slouken@1895
   221
typedef struct
slouken@1895
   222
{
slouken@5154
   223
    void* d3dDLL;
slouken@2973
   224
    IDirect3D9 *d3d;
slouken@1895
   225
    IDirect3DDevice9 *device;
slouken@3527
   226
    UINT adapter;
slouken@1975
   227
    D3DPRESENT_PARAMETERS pparams;
slouken@5297
   228
    SDL_bool updateSize;
slouken@1900
   229
    SDL_bool beginScene;
slouken@7502
   230
    SDL_bool enableSeparateAlphaBlend;
slouken@5484
   231
    D3DTEXTUREFILTERTYPE scaleMode;
slouken@6232
   232
    IDirect3DSurface9 *defaultRenderTarget;
slouken@6232
   233
    IDirect3DSurface9 *currentRenderTarget;
gabomdq@6320
   234
    void* d3dxDLL;
gabomdq@6320
   235
    ID3DXMatrixStack *matrixStack;
slouken@1913
   236
} D3D_RenderData;
slouken@1895
   237
slouken@1895
   238
typedef struct
slouken@1895
   239
{
slouken@1903
   240
    IDirect3DTexture9 *texture;
slouken@5484
   241
    D3DTEXTUREFILTERTYPE scaleMode;
slouken@1913
   242
} D3D_TextureData;
slouken@1895
   243
slouken@1903
   244
typedef struct
slouken@1903
   245
{
slouken@1903
   246
    float x, y, z;
slouken@1987
   247
    DWORD color;
slouken@1904
   248
    float u, v;
slouken@1903
   249
} Vertex;
slouken@1903
   250
icculus@7037
   251
static int
slouken@1900
   252
D3D_SetError(const char *prefix, HRESULT result)
slouken@1900
   253
{
slouken@1900
   254
    const char *error;
slouken@1900
   255
slouken@1900
   256
    switch (result) {
slouken@1900
   257
    case D3DERR_WRONGTEXTUREFORMAT:
slouken@1900
   258
        error = "WRONGTEXTUREFORMAT";
slouken@1900
   259
        break;
slouken@1900
   260
    case D3DERR_UNSUPPORTEDCOLOROPERATION:
slouken@1900
   261
        error = "UNSUPPORTEDCOLOROPERATION";
slouken@1900
   262
        break;
slouken@1900
   263
    case D3DERR_UNSUPPORTEDCOLORARG:
slouken@1900
   264
        error = "UNSUPPORTEDCOLORARG";
slouken@1900
   265
        break;
slouken@1900
   266
    case D3DERR_UNSUPPORTEDALPHAOPERATION:
slouken@1900
   267
        error = "UNSUPPORTEDALPHAOPERATION";
slouken@1900
   268
        break;
slouken@1900
   269
    case D3DERR_UNSUPPORTEDALPHAARG:
slouken@1900
   270
        error = "UNSUPPORTEDALPHAARG";
slouken@1900
   271
        break;
slouken@1900
   272
    case D3DERR_TOOMANYOPERATIONS:
slouken@1900
   273
        error = "TOOMANYOPERATIONS";
slouken@1900
   274
        break;
slouken@1900
   275
    case D3DERR_CONFLICTINGTEXTUREFILTER:
slouken@1900
   276
        error = "CONFLICTINGTEXTUREFILTER";
slouken@1900
   277
        break;
slouken@1900
   278
    case D3DERR_UNSUPPORTEDFACTORVALUE:
slouken@1900
   279
        error = "UNSUPPORTEDFACTORVALUE";
slouken@1900
   280
        break;
slouken@1900
   281
    case D3DERR_CONFLICTINGRENDERSTATE:
slouken@1900
   282
        error = "CONFLICTINGRENDERSTATE";
slouken@1900
   283
        break;
slouken@1900
   284
    case D3DERR_UNSUPPORTEDTEXTUREFILTER:
slouken@1900
   285
        error = "UNSUPPORTEDTEXTUREFILTER";
slouken@1900
   286
        break;
slouken@1900
   287
    case D3DERR_CONFLICTINGTEXTUREPALETTE:
slouken@1900
   288
        error = "CONFLICTINGTEXTUREPALETTE";
slouken@1900
   289
        break;
slouken@1900
   290
    case D3DERR_DRIVERINTERNALERROR:
slouken@1900
   291
        error = "DRIVERINTERNALERROR";
slouken@1900
   292
        break;
slouken@1900
   293
    case D3DERR_NOTFOUND:
slouken@1900
   294
        error = "NOTFOUND";
slouken@1900
   295
        break;
slouken@1900
   296
    case D3DERR_MOREDATA:
slouken@1900
   297
        error = "MOREDATA";
slouken@1900
   298
        break;
slouken@1900
   299
    case D3DERR_DEVICELOST:
slouken@1900
   300
        error = "DEVICELOST";
slouken@1900
   301
        break;
slouken@1900
   302
    case D3DERR_DEVICENOTRESET:
slouken@1900
   303
        error = "DEVICENOTRESET";
slouken@1900
   304
        break;
slouken@1900
   305
    case D3DERR_NOTAVAILABLE:
slouken@1900
   306
        error = "NOTAVAILABLE";
slouken@1900
   307
        break;
slouken@1900
   308
    case D3DERR_OUTOFVIDEOMEMORY:
slouken@1900
   309
        error = "OUTOFVIDEOMEMORY";
slouken@1900
   310
        break;
slouken@1900
   311
    case D3DERR_INVALIDDEVICE:
slouken@1900
   312
        error = "INVALIDDEVICE";
slouken@1900
   313
        break;
slouken@1900
   314
    case D3DERR_INVALIDCALL:
slouken@1900
   315
        error = "INVALIDCALL";
slouken@1900
   316
        break;
slouken@1900
   317
    case D3DERR_DRIVERINVALIDCALL:
slouken@1900
   318
        error = "DRIVERINVALIDCALL";
slouken@1900
   319
        break;
slouken@1900
   320
    case D3DERR_WASSTILLDRAWING:
slouken@1900
   321
        error = "WASSTILLDRAWING";
slouken@1900
   322
        break;
slouken@1900
   323
    default:
slouken@1900
   324
        error = "UNKNOWN";
slouken@1900
   325
        break;
slouken@1900
   326
    }
icculus@7037
   327
    return SDL_SetError("%s: %s", prefix, error);
slouken@1900
   328
}
slouken@1900
   329
slouken@1903
   330
static D3DFORMAT
slouken@1903
   331
PixelFormatToD3DFMT(Uint32 format)
slouken@1895
   332
{
slouken@1903
   333
    switch (format) {
slouken@1965
   334
    case SDL_PIXELFORMAT_RGB565:
slouken@1903
   335
        return D3DFMT_R5G6B5;
slouken@1965
   336
    case SDL_PIXELFORMAT_RGB888:
slouken@1903
   337
        return D3DFMT_X8R8G8B8;
slouken@1965
   338
    case SDL_PIXELFORMAT_ARGB8888:
slouken@1903
   339
        return D3DFMT_A8R8G8B8;
slouken@1903
   340
    default:
slouken@1903
   341
        return D3DFMT_UNKNOWN;
slouken@1903
   342
    }
slouken@1895
   343
}
slouken@1895
   344
slouken@5156
   345
static Uint32
slouken@5156
   346
D3DFMTToPixelFormat(D3DFORMAT format)
slouken@2973
   347
{
slouken@5156
   348
    switch (format) {
slouken@5156
   349
    case D3DFMT_R5G6B5:
slouken@5156
   350
        return SDL_PIXELFORMAT_RGB565;
slouken@5156
   351
    case D3DFMT_X8R8G8B8:
slouken@5156
   352
        return SDL_PIXELFORMAT_RGB888;
slouken@5156
   353
    case D3DFMT_A8R8G8B8:
slouken@5156
   354
        return SDL_PIXELFORMAT_ARGB8888;
slouken@5156
   355
    default:
slouken@5156
   356
        return SDL_PIXELFORMAT_UNKNOWN;
slouken@2973
   357
    }
slouken@1895
   358
}
slouken@1895
   359
slouken@5297
   360
static int
slouken@5297
   361
D3D_Reset(SDL_Renderer * renderer)
slouken@5297
   362
{
slouken@5297
   363
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@5297
   364
    HRESULT result;
slouken@5297
   365
slouken@6860
   366
    /* Release the default render target before reset */
slouken@6895
   367
    if (data->defaultRenderTarget) {
slouken@6895
   368
        IDirect3DSurface9_Release(data->defaultRenderTarget);
slouken@6895
   369
        data->defaultRenderTarget = NULL;
slouken@6895
   370
    }
slouken@6860
   371
slouken@5297
   372
    result = IDirect3DDevice9_Reset(data->device, &data->pparams);
slouken@5297
   373
    if (FAILED(result)) {
slouken@5297
   374
        if (result == D3DERR_DEVICELOST) {
slouken@5297
   375
            /* Don't worry about it, we'll reset later... */
slouken@5297
   376
            return 0;
slouken@5297
   377
        } else {
icculus@7037
   378
            return D3D_SetError("Reset()", result);
slouken@5297
   379
        }
slouken@5297
   380
    }
slouken@5297
   381
    IDirect3DDevice9_SetVertexShader(data->device, NULL);
slouken@5297
   382
    IDirect3DDevice9_SetFVF(data->device,
slouken@5297
   383
                            D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1);
slouken@5297
   384
    IDirect3DDevice9_SetRenderState(data->device, D3DRS_CULLMODE,
slouken@5297
   385
                                    D3DCULL_NONE);
slouken@5297
   386
    IDirect3DDevice9_SetRenderState(data->device, D3DRS_LIGHTING, FALSE);
slouken@6860
   387
    IDirect3DDevice9_GetRenderTarget(data->device, 0, &data->defaultRenderTarget);
yuriks@7250
   388
    data->scaleMode = D3DTEXF_FORCE_DWORD;
slouken@5297
   389
    return 0;
slouken@5297
   390
}
slouken@5297
   391
slouken@5297
   392
static int
slouken@5297
   393
D3D_ActivateRenderer(SDL_Renderer * renderer)
slouken@5297
   394
{
slouken@5297
   395
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@5297
   396
    HRESULT result;
slouken@5297
   397
slouken@5297
   398
    if (data->updateSize) {
slouken@5297
   399
        SDL_Window *window = renderer->window;
slouken@5297
   400
        int w, h;
slouken@5297
   401
slouken@5297
   402
        SDL_GetWindowSize(window, &w, &h);
slouken@5297
   403
        data->pparams.BackBufferWidth = w;
slouken@5297
   404
        data->pparams.BackBufferHeight = h;
slouken@5297
   405
        if (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) {
slouken@5297
   406
            data->pparams.BackBufferFormat =
slouken@5297
   407
                PixelFormatToD3DFMT(SDL_GetWindowPixelFormat(window));
slouken@5297
   408
        } else {
slouken@5297
   409
            data->pparams.BackBufferFormat = D3DFMT_UNKNOWN;
slouken@5297
   410
        }
slouken@5297
   411
        if (D3D_Reset(renderer) < 0) {
slouken@5297
   412
            return -1;
slouken@5297
   413
        }
slouken@5297
   414
        D3D_UpdateViewport(renderer);
slouken@5297
   415
slouken@5297
   416
        data->updateSize = SDL_FALSE;
slouken@5297
   417
    }
slouken@5297
   418
    if (data->beginScene) {
slouken@5297
   419
        result = IDirect3DDevice9_BeginScene(data->device);
slouken@5297
   420
        if (result == D3DERR_DEVICELOST) {
slouken@5297
   421
            if (D3D_Reset(renderer) < 0) {
slouken@5297
   422
                return -1;
slouken@5297
   423
            }
slouken@5297
   424
            result = IDirect3DDevice9_BeginScene(data->device);
slouken@5297
   425
        }
slouken@5297
   426
        if (FAILED(result)) {
icculus@7037
   427
            return D3D_SetError("BeginScene()", result);
slouken@5297
   428
        }
slouken@5297
   429
        data->beginScene = SDL_FALSE;
slouken@5297
   430
    }
slouken@5297
   431
    return 0;
slouken@5297
   432
}
slouken@5297
   433
slouken@1895
   434
SDL_Renderer *
slouken@1913
   435
D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
slouken@1895
   436
{
slouken@1895
   437
    SDL_Renderer *renderer;
slouken@1913
   438
    D3D_RenderData *data;
slouken@5154
   439
    SDL_SysWMinfo windowinfo;
slouken@1900
   440
    HRESULT result;
slouken@1900
   441
    D3DPRESENT_PARAMETERS pparams;
slouken@1907
   442
    IDirect3DSwapChain9 *chain;
slouken@1925
   443
    D3DCAPS9 caps;
slouken@5156
   444
    Uint32 window_flags;
slouken@5156
   445
    int w, h;
slouken@5156
   446
    SDL_DisplayMode fullscreen_mode;
slouken@5297
   447
    D3DMATRIX matrix;
gabomdq@6320
   448
    int d3dxVersion;
slouken@7191
   449
    char d3dxDLLFile[50];
slouken@1895
   450
slouken@1920
   451
    renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
slouken@1895
   452
    if (!renderer) {
slouken@1895
   453
        SDL_OutOfMemory();
slouken@1895
   454
        return NULL;
slouken@1895
   455
    }
slouken@1895
   456
slouken@1920
   457
    data = (D3D_RenderData *) SDL_calloc(1, sizeof(*data));
slouken@1895
   458
    if (!data) {
slouken@5154
   459
        SDL_free(renderer);
slouken@1895
   460
        SDL_OutOfMemory();
slouken@1895
   461
        return NULL;
slouken@1895
   462
    }
slouken@1895
   463
slouken@5154
   464
    data->d3dDLL = SDL_LoadObject("D3D9.DLL");
slouken@5154
   465
    if (data->d3dDLL) {
slouken@5154
   466
        IDirect3D9 *(WINAPI * D3DCreate) (UINT SDKVersion);
slouken@4569
   467
slouken@5154
   468
        D3DCreate =
slouken@5154
   469
            (IDirect3D9 * (WINAPI *) (UINT)) SDL_LoadFunction(data->d3dDLL,
slouken@5154
   470
                                                            "Direct3DCreate9");
slouken@5154
   471
        if (D3DCreate) {
slouken@5154
   472
            data->d3d = D3DCreate(D3D_SDK_VERSION);
slouken@5154
   473
        }
slouken@5154
   474
        if (!data->d3d) {
slouken@5154
   475
            SDL_UnloadObject(data->d3dDLL);
slouken@5154
   476
            data->d3dDLL = NULL;
slouken@5154
   477
        }
gabomdq@6320
   478
gabomdq@6320
   479
        for (d3dxVersion=50;d3dxVersion>0;d3dxVersion--) {
slouken@6971
   480
            LPTSTR dllName;
slouken@6971
   481
            SDL_snprintf(d3dxDLLFile, sizeof(d3dxDLLFile), "D3DX9_%02d.dll", d3dxVersion);
slouken@6971
   482
            dllName = WIN_UTF8ToString(d3dxDLLFile);
slouken@6971
   483
            data->d3dxDLL = (void *)LoadLibrary(dllName); /* not using SDL_LoadObject() as we want silently fail - no error message */
slouken@6971
   484
            SDL_free(dllName);
gabomdq@6320
   485
            if (data->d3dxDLL) {
gabomdq@6320
   486
                HRESULT (WINAPI *D3DXCreateMatrixStack) (DWORD Flags, LPD3DXMATRIXSTACK*  ppStack);
gabomdq@6320
   487
                D3DXCreateMatrixStack = (HRESULT (WINAPI *) (DWORD, LPD3DXMATRIXSTACK*)) SDL_LoadFunction(data->d3dxDLL, "D3DXCreateMatrixStack");
gabomdq@6320
   488
                if (D3DXCreateMatrixStack) {
gabomdq@6320
   489
                    D3DXCreateMatrixStack(0, &data->matrixStack);
gabomdq@6320
   490
                    break;
gabomdq@6320
   491
                }
gabomdq@6320
   492
            }
gabomdq@6320
   493
        }
gabomdq@6320
   494
gabomdq@6320
   495
        if (!data->matrixStack) {
gabomdq@6320
   496
            if (data->d3dxDLL) SDL_UnloadObject(data->d3dxDLL);
gabomdq@6320
   497
        }
slouken@5154
   498
    }
gabomdq@6320
   499
gabomdq@6320
   500
slouken@7191
   501
gabomdq@6320
   502
    if (!data->d3d || !data->matrixStack) {
slouken@5154
   503
        SDL_free(renderer);
slouken@5154
   504
        SDL_free(data);
slouken@5154
   505
        SDL_SetError("Unable to create Direct3D interface");
slouken@5154
   506
        return NULL;
slouken@5154
   507
    }
slouken@5154
   508
slouken@5297
   509
    renderer->WindowEvent = D3D_WindowEvent;
slouken@1913
   510
    renderer->CreateTexture = D3D_CreateTexture;
slouken@1913
   511
    renderer->UpdateTexture = D3D_UpdateTexture;
slouken@1913
   512
    renderer->LockTexture = D3D_LockTexture;
slouken@1913
   513
    renderer->UnlockTexture = D3D_UnlockTexture;
slouken@6247
   514
    renderer->SetRenderTarget = D3D_SetRenderTarget;
slouken@5297
   515
    renderer->UpdateViewport = D3D_UpdateViewport;
slouken@7141
   516
    renderer->UpdateClipRect = D3D_UpdateClipRect;
slouken@5297
   517
    renderer->RenderClear = D3D_RenderClear;
slouken@3599
   518
    renderer->RenderDrawPoints = D3D_RenderDrawPoints;
slouken@3599
   519
    renderer->RenderDrawLines = D3D_RenderDrawLines;
slouken@3675
   520
    renderer->RenderFillRects = D3D_RenderFillRects;
slouken@1913
   521
    renderer->RenderCopy = D3D_RenderCopy;
gabomdq@6320
   522
    renderer->RenderCopyEx = D3D_RenderCopyEx;
slouken@3427
   523
    renderer->RenderReadPixels = D3D_RenderReadPixels;
slouken@1913
   524
    renderer->RenderPresent = D3D_RenderPresent;
slouken@1913
   525
    renderer->DestroyTexture = D3D_DestroyTexture;
slouken@1913
   526
    renderer->DestroyRenderer = D3D_DestroyRenderer;
slouken@1913
   527
    renderer->info = D3D_RenderDriver.info;
slouken@1895
   528
    renderer->driverdata = data;
slouken@1895
   529
slouken@6246
   530
    renderer->info.flags = SDL_RENDERER_ACCELERATED;
slouken@1895
   531
slouken@5154
   532
    SDL_VERSION(&windowinfo.version);
slouken@5154
   533
    SDL_GetWindowWMInfo(window, &windowinfo);
slouken@5154
   534
slouken@5156
   535
    window_flags = SDL_GetWindowFlags(window);
slouken@5156
   536
    SDL_GetWindowSize(window, &w, &h);
slouken@5156
   537
    SDL_GetWindowDisplayMode(window, &fullscreen_mode);
slouken@5156
   538
slouken@1900
   539
    SDL_zero(pparams);
slouken@5154
   540
    pparams.hDeviceWindow = windowinfo.info.win.window;
slouken@5156
   541
    pparams.BackBufferWidth = w;
slouken@5156
   542
    pparams.BackBufferHeight = h;
slouken@5156
   543
    if (window_flags & SDL_WINDOW_FULLSCREEN) {
slouken@1903
   544
        pparams.BackBufferFormat =
slouken@5156
   545
            PixelFormatToD3DFMT(fullscreen_mode.format);
slouken@1903
   546
    } else {
slouken@1903
   547
        pparams.BackBufferFormat = D3DFMT_UNKNOWN;
slouken@1903
   548
    }
slouken@5142
   549
    pparams.BackBufferCount = 1;
slouken@5142
   550
    pparams.SwapEffect = D3DSWAPEFFECT_DISCARD;
slouken@5142
   551
slouken@5156
   552
    if (window_flags & SDL_WINDOW_FULLSCREEN) {
slouken@7191
   553
        if ( ( window_flags & SDL_WINDOW_FULLSCREEN_DESKTOP ) == SDL_WINDOW_FULLSCREEN_DESKTOP )  {
slouken@7191
   554
            pparams.Windowed = TRUE;
slouken@7191
   555
            pparams.FullScreen_RefreshRateInHz = 0;
slouken@7191
   556
        } else {
slouken@1900
   557
        pparams.Windowed = FALSE;
slouken@1903
   558
        pparams.FullScreen_RefreshRateInHz =
slouken@5156
   559
            fullscreen_mode.refresh_rate;
slouken@7191
   560
        }
slouken@1900
   561
    } else {
slouken@1900
   562
        pparams.Windowed = TRUE;
slouken@1903
   563
        pparams.FullScreen_RefreshRateInHz = 0;
slouken@1900
   564
    }
slouken@1965
   565
    if (flags & SDL_RENDERER_PRESENTVSYNC) {
slouken@1907
   566
        pparams.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
slouken@1907
   567
    } else {
slouken@1907
   568
        pparams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
slouken@1907
   569
    }
slouken@1900
   570
slouken@5154
   571
    /* FIXME: Which adapter? */
slouken@5154
   572
    data->adapter = D3DADAPTER_DEFAULT;
slouken@5154
   573
    IDirect3D9_GetDeviceCaps(data->d3d, data->adapter, D3DDEVTYPE_HAL, &caps);
slouken@3197
   574
slouken@5154
   575
    result = IDirect3D9_CreateDevice(data->d3d, data->adapter,
slouken@1900
   576
                                     D3DDEVTYPE_HAL,
slouken@5154
   577
                                     pparams.hDeviceWindow,
slouken@6115
   578
                                     D3DCREATE_FPU_PRESERVE | ((caps.
slouken@3197
   579
                                      DevCaps &
slouken@3197
   580
                                      D3DDEVCAPS_HWTRANSFORMANDLIGHT) ?
slouken@3197
   581
                                     D3DCREATE_HARDWARE_VERTEXPROCESSING :
slouken@6115
   582
                                     D3DCREATE_SOFTWARE_VERTEXPROCESSING),
slouken@1900
   583
                                     &pparams, &data->device);
slouken@1900
   584
    if (FAILED(result)) {
slouken@1913
   585
        D3D_DestroyRenderer(renderer);
slouken@1900
   586
        D3D_SetError("CreateDevice()", result);
slouken@1900
   587
        return NULL;
slouken@1900
   588
    }
slouken@1900
   589
    data->beginScene = SDL_TRUE;
slouken@5484
   590
    data->scaleMode = D3DTEXF_FORCE_DWORD;
slouken@1900
   591
slouken@1907
   592
    /* Get presentation parameters to fill info */
slouken@1907
   593
    result = IDirect3DDevice9_GetSwapChain(data->device, 0, &chain);
slouken@1907
   594
    if (FAILED(result)) {
slouken@1913
   595
        D3D_DestroyRenderer(renderer);
slouken@1907
   596
        D3D_SetError("GetSwapChain()", result);
slouken@1907
   597
        return NULL;
slouken@1907
   598
    }
slouken@1907
   599
    result = IDirect3DSwapChain9_GetPresentParameters(chain, &pparams);
slouken@1907
   600
    if (FAILED(result)) {
slouken@1907
   601
        IDirect3DSwapChain9_Release(chain);
slouken@1913
   602
        D3D_DestroyRenderer(renderer);
slouken@1907
   603
        D3D_SetError("GetPresentParameters()", result);
slouken@1907
   604
        return NULL;
slouken@1907
   605
    }
slouken@1907
   606
    IDirect3DSwapChain9_Release(chain);
slouken@1907
   607
    if (pparams.PresentationInterval == D3DPRESENT_INTERVAL_ONE) {
slouken@1965
   608
        renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
slouken@1907
   609
    }
slouken@1975
   610
    data->pparams = pparams;
slouken@1907
   611
slouken@1925
   612
    IDirect3DDevice9_GetDeviceCaps(data->device, &caps);
slouken@1925
   613
    renderer->info.max_texture_width = caps.MaxTextureWidth;
slouken@1925
   614
    renderer->info.max_texture_height = caps.MaxTextureHeight;
slouken@6246
   615
    if (caps.NumSimultaneousRTs >= 2) {
slouken@6246
   616
        renderer->info.flags |= SDL_RENDERER_TARGETTEXTURE;
slouken@6246
   617
    }
slouken@1918
   618
slouken@7502
   619
    if (caps.PrimitiveMiscCaps & D3DPMISCCAPS_SEPARATEALPHABLEND) {
slouken@7502
   620
        data->enableSeparateAlphaBlend = SDL_TRUE;
slouken@7502
   621
    }
slouken@7502
   622
slouken@1903
   623
    /* Set up parameters for rendering */
slouken@1904
   624
    IDirect3DDevice9_SetVertexShader(data->device, NULL);
slouken@1987
   625
    IDirect3DDevice9_SetFVF(data->device,
slouken@5297
   626
                            D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1);
slouken@1988
   627
    IDirect3DDevice9_SetRenderState(data->device, D3DRS_ZENABLE, D3DZB_FALSE);
slouken@1903
   628
    IDirect3DDevice9_SetRenderState(data->device, D3DRS_CULLMODE,
slouken@1903
   629
                                    D3DCULL_NONE);
slouken@1904
   630
    IDirect3DDevice9_SetRenderState(data->device, D3DRS_LIGHTING, FALSE);
slouken@1988
   631
    /* Enable color modulation by diffuse color */
slouken@1988
   632
    IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLOROP,
slouken@1988
   633
                                          D3DTOP_MODULATE);
slouken@1988
   634
    IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLORARG1,
slouken@1988
   635
                                          D3DTA_TEXTURE);
slouken@1988
   636
    IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLORARG2,
slouken@1988
   637
                                          D3DTA_DIFFUSE);
slouken@1988
   638
    /* Enable alpha modulation by diffuse alpha */
slouken@1988
   639
    IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAOP,
slouken@1988
   640
                                          D3DTOP_MODULATE);
slouken@1988
   641
    IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAARG1,
slouken@1988
   642
                                          D3DTA_TEXTURE);
slouken@1988
   643
    IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAARG2,
slouken@1988
   644
                                          D3DTA_DIFFUSE);
slouken@7502
   645
    /* Enable separate alpha blend function, if possible */
slouken@7502
   646
    if (data->enableSeparateAlphaBlend) {
slouken@7502
   647
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
slouken@7502
   648
    }
slouken@1991
   649
    /* Disable second texture stage, since we're done */
slouken@1991
   650
    IDirect3DDevice9_SetTextureStageState(data->device, 1, D3DTSS_COLOROP,
slouken@1991
   651
                                          D3DTOP_DISABLE);
slouken@1991
   652
    IDirect3DDevice9_SetTextureStageState(data->device, 1, D3DTSS_ALPHAOP,
slouken@1991
   653
                                          D3DTOP_DISABLE);
slouken@1903
   654
slouken@6232
   655
    /* Store the default render target */
slouken@6232
   656
    IDirect3DDevice9_GetRenderTarget(data->device, 0, &data->defaultRenderTarget );
slouken@6232
   657
    data->currentRenderTarget = NULL;
slouken@6232
   658
slouken@5297
   659
    /* Set an identity world and view matrix */
slouken@5297
   660
    matrix.m[0][0] = 1.0f;
slouken@5297
   661
    matrix.m[0][1] = 0.0f;
slouken@5297
   662
    matrix.m[0][2] = 0.0f;
slouken@5297
   663
    matrix.m[0][3] = 0.0f;
slouken@5297
   664
    matrix.m[1][0] = 0.0f;
slouken@5297
   665
    matrix.m[1][1] = 1.0f;
slouken@5297
   666
    matrix.m[1][2] = 0.0f;
slouken@5297
   667
    matrix.m[1][3] = 0.0f;
slouken@5297
   668
    matrix.m[2][0] = 0.0f;
slouken@5297
   669
    matrix.m[2][1] = 0.0f;
slouken@5297
   670
    matrix.m[2][2] = 1.0f;
slouken@5297
   671
    matrix.m[2][3] = 0.0f;
slouken@5297
   672
    matrix.m[3][0] = 0.0f;
slouken@5297
   673
    matrix.m[3][1] = 0.0f;
slouken@5297
   674
    matrix.m[3][2] = 0.0f;
slouken@5297
   675
    matrix.m[3][3] = 1.0f;
slouken@5297
   676
    IDirect3DDevice9_SetTransform(data->device, D3DTS_WORLD, &matrix);
slouken@5297
   677
    IDirect3DDevice9_SetTransform(data->device, D3DTS_VIEW, &matrix);
slouken@5297
   678
slouken@1895
   679
    return renderer;
slouken@1895
   680
}
slouken@1895
   681
slouken@5297
   682
static void
slouken@5297
   683
D3D_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
slouken@1975
   684
{
slouken@1975
   685
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@1975
   686
slouken@5297
   687
    if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED) {
slouken@5297
   688
        data->updateSize = SDL_TRUE;
slouken@1975
   689
    }
slouken@1975
   690
}
slouken@1975
   691
slouken@5484
   692
static D3DTEXTUREFILTERTYPE
slouken@5484
   693
GetScaleQuality(void)
slouken@5484
   694
{
slouken@5484
   695
    const char *hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY);
slouken@5484
   696
slouken@5484
   697
    if (!hint || *hint == '0' || SDL_strcasecmp(hint, "nearest") == 0) {
slouken@5484
   698
        return D3DTEXF_POINT;
slouken@5484
   699
    } else if (*hint == '1' || SDL_strcasecmp(hint, "linear") == 0) {
slouken@5484
   700
        return D3DTEXF_LINEAR;
slouken@5484
   701
    } else {
slouken@5484
   702
        return D3DTEXF_ANISOTROPIC;
slouken@5484
   703
    }
slouken@5484
   704
}
slouken@5484
   705
slouken@1975
   706
static int
slouken@1913
   707
D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1895
   708
{
icculus@6404
   709
    D3D_RenderData *renderdata = (D3D_RenderData *) renderer->driverdata;
slouken@1913
   710
    D3D_TextureData *data;
slouken@5173
   711
    D3DPOOL pool;
slouken@5173
   712
    DWORD usage;
slouken@1903
   713
    HRESULT result;
slouken@1895
   714
slouken@1920
   715
    data = (D3D_TextureData *) SDL_calloc(1, sizeof(*data));
slouken@1895
   716
    if (!data) {
icculus@7037
   717
        return SDL_OutOfMemory();
slouken@1895
   718
    }
slouken@5484
   719
    data->scaleMode = GetScaleQuality();
slouken@1895
   720
slouken@1895
   721
    texture->driverdata = data;
slouken@1895
   722
slouken@5173
   723
#ifdef USE_DYNAMIC_TEXTURE
slouken@5173
   724
    if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
slouken@5173
   725
        pool = D3DPOOL_DEFAULT;
slouken@5173
   726
        usage = D3DUSAGE_DYNAMIC;
slouken@5173
   727
    } else
slouken@5173
   728
#endif
slouken@6232
   729
    if (texture->access == SDL_TEXTUREACCESS_TARGET) {
slouken@6246
   730
        /* D3DPOOL_MANAGED does not work with D3DUSAGE_RENDERTARGET */
slouken@6246
   731
        pool = D3DPOOL_DEFAULT;
slouken@6232
   732
        usage = D3DUSAGE_RENDERTARGET;
slouken@6246
   733
    } else {
slouken@5173
   734
        pool = D3DPOOL_MANAGED;
slouken@5173
   735
        usage = 0;
slouken@5173
   736
    }
slouken@2973
   737
slouken@1903
   738
    result =
slouken@1903
   739
        IDirect3DDevice9_CreateTexture(renderdata->device, texture->w,
slouken@5173
   740
                                       texture->h, 1, usage,
slouken@5173
   741
                                       PixelFormatToD3DFMT(texture->format),
slouken@5173
   742
                                       pool, &data->texture, NULL);
slouken@1903
   743
    if (FAILED(result)) {
icculus@7037
   744
        return D3D_SetError("CreateTexture()", result);
slouken@1903
   745
    }
slouken@1903
   746
slouken@1895
   747
    return 0;
slouken@1895
   748
}
slouken@1895
   749
slouken@1895
   750
static int
slouken@1913
   751
D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1913
   752
                  const SDL_Rect * rect, const void *pixels, int pitch)
slouken@1895
   753
{
slouken@1913
   754
    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
slouken@5156
   755
    RECT d3drect;
slouken@5156
   756
    D3DLOCKED_RECT locked;
slouken@5156
   757
    const Uint8 *src;
slouken@5156
   758
    Uint8 *dst;
slouken@5156
   759
    int row, length;
slouken@5156
   760
    HRESULT result;
slouken@2973
   761
slouken@5173
   762
#ifdef USE_DYNAMIC_TEXTURE
slouken@5173
   763
    if (texture->access == SDL_TEXTUREACCESS_STREAMING &&
slouken@5173
   764
        rect->x == 0 && rect->y == 0 &&
slouken@5173
   765
        rect->w == texture->w && rect->h == texture->h) {
slouken@5194
   766
        result = IDirect3DTexture9_LockRect(data->texture, 0, &locked, NULL, D3DLOCK_DISCARD);
slouken@5173
   767
    } else
slouken@5173
   768
#endif
slouken@5173
   769
    {
slouken@5173
   770
        d3drect.left = rect->x;
slouken@5173
   771
        d3drect.right = rect->x + rect->w;
slouken@5173
   772
        d3drect.top = rect->y;
slouken@5173
   773
        d3drect.bottom = rect->y + rect->h;
slouken@5194
   774
        result = IDirect3DTexture9_LockRect(data->texture, 0, &locked, &d3drect, 0);
slouken@5156
   775
    }
slouken@2973
   776
slouken@5156
   777
    if (FAILED(result)) {
icculus@7037
   778
        return D3D_SetError("LockRect()", result);
slouken@5156
   779
    }
slouken@2973
   780
slouken@5156
   781
    src = pixels;
slouken@5156
   782
    dst = locked.pBits;
slouken@5156
   783
    length = rect->w * SDL_BYTESPERPIXEL(texture->format);
slouken@5173
   784
    if (length == pitch && length == locked.Pitch) {
slouken@5173
   785
        SDL_memcpy(dst, src, length*rect->h);
slouken@5173
   786
    } else {
slouken@5173
   787
        for (row = 0; row < rect->h; ++row) {
slouken@5173
   788
            SDL_memcpy(dst, src, length);
slouken@5173
   789
            src += pitch;
slouken@5173
   790
            dst += locked.Pitch;
slouken@5173
   791
        }
slouken@5156
   792
    }
slouken@5156
   793
    IDirect3DTexture9_UnlockRect(data->texture, 0);
slouken@2973
   794
slouken@5156
   795
    return 0;
slouken@1895
   796
}
slouken@1895
   797
slouken@1895
   798
static int
slouken@1913
   799
D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@5156
   800
                const SDL_Rect * rect, void **pixels, int *pitch)
slouken@1895
   801
{
slouken@1913
   802
    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
slouken@5156
   803
    RECT d3drect;
slouken@5156
   804
    D3DLOCKED_RECT locked;
slouken@5156
   805
    HRESULT result;
slouken@1895
   806
slouken@5156
   807
    d3drect.left = rect->x;
slouken@5156
   808
    d3drect.right = rect->x + rect->w;
slouken@5156
   809
    d3drect.top = rect->y;
slouken@5156
   810
    d3drect.bottom = rect->y + rect->h;
slouken@1903
   811
slouken@5156
   812
    result = IDirect3DTexture9_LockRect(data->texture, 0, &locked, &d3drect, 0);
slouken@5156
   813
    if (FAILED(result)) {
icculus@7037
   814
        return D3D_SetError("LockRect()", result);
slouken@1903
   815
    }
slouken@5156
   816
    *pixels = locked.pBits;
slouken@5156
   817
    *pitch = locked.Pitch;
slouken@5156
   818
    return 0;
slouken@1895
   819
}
slouken@1895
   820
slouken@1895
   821
static void
slouken@1913
   822
D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1895
   823
{
slouken@1913
   824
    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
slouken@1895
   825
slouken@5156
   826
    IDirect3DTexture9_UnlockRect(data->texture, 0);
slouken@1895
   827
}
slouken@1895
   828
slouken@5297
   829
static int
slouken@7141
   830
D3D_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@7141
   831
{
slouken@7141
   832
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@7141
   833
    D3D_TextureData *texturedata;
slouken@7141
   834
    HRESULT result;
slouken@7141
   835
slouken@7141
   836
    D3D_ActivateRenderer(renderer);
slouken@7141
   837
slouken@7141
   838
    /* Release the previous render target if it wasn't the default one */
slouken@7141
   839
    if (data->currentRenderTarget != NULL) {
slouken@7141
   840
        IDirect3DSurface9_Release(data->currentRenderTarget);
slouken@7141
   841
        data->currentRenderTarget = NULL;
slouken@7141
   842
    }
slouken@7141
   843
slouken@7141
   844
    if (texture == NULL) {
slouken@7141
   845
        IDirect3DDevice9_SetRenderTarget(data->device, 0, data->defaultRenderTarget);
slouken@7141
   846
        return 0;
slouken@7141
   847
    }
slouken@7141
   848
slouken@7141
   849
    texturedata = (D3D_TextureData *) texture->driverdata;
slouken@7141
   850
    result = IDirect3DTexture9_GetSurfaceLevel(texturedata->texture, 0, &data->currentRenderTarget);
slouken@7141
   851
    if(FAILED(result)) {
slouken@7141
   852
        return D3D_SetError("GetSurfaceLevel()", result);
slouken@7141
   853
    }
slouken@7141
   854
    result = IDirect3DDevice9_SetRenderTarget(data->device, 0, data->currentRenderTarget);
slouken@7141
   855
    if(FAILED(result)) {
slouken@7141
   856
        return D3D_SetError("SetRenderTarget()", result);
slouken@7141
   857
    }
slouken@7141
   858
slouken@7141
   859
    return 0;
slouken@7141
   860
}
slouken@7141
   861
slouken@7141
   862
static int
slouken@5297
   863
D3D_UpdateViewport(SDL_Renderer * renderer)
slouken@5224
   864
{
slouken@5224
   865
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@5297
   866
    D3DVIEWPORT9 viewport;
slouken@5297
   867
    D3DMATRIX matrix;
slouken@5224
   868
slouken@5297
   869
    /* Set the viewport */
slouken@5297
   870
    viewport.X = renderer->viewport.x;
slouken@5297
   871
    viewport.Y = renderer->viewport.y;
slouken@5297
   872
    viewport.Width = renderer->viewport.w;
slouken@5297
   873
    viewport.Height = renderer->viewport.h;
slouken@5297
   874
    viewport.MinZ = 0.0f;
slouken@5297
   875
    viewport.MaxZ = 1.0f;
slouken@5297
   876
    IDirect3DDevice9_SetViewport(data->device, &viewport);
slouken@5224
   877
slouken@5297
   878
    /* Set an orthographic projection matrix */
slouken@7239
   879
    if (renderer->viewport.w && renderer->viewport.h) {
slouken@7239
   880
        matrix.m[0][0] = 2.0f / renderer->viewport.w;
slouken@7239
   881
        matrix.m[0][1] = 0.0f;
slouken@7239
   882
        matrix.m[0][2] = 0.0f;
slouken@7239
   883
        matrix.m[0][3] = 0.0f;
slouken@7239
   884
        matrix.m[1][0] = 0.0f;
slouken@7239
   885
        matrix.m[1][1] = -2.0f / renderer->viewport.h;
slouken@7239
   886
        matrix.m[1][2] = 0.0f;
slouken@7239
   887
        matrix.m[1][3] = 0.0f;
slouken@7239
   888
        matrix.m[2][0] = 0.0f;
slouken@7239
   889
        matrix.m[2][1] = 0.0f;
slouken@7239
   890
        matrix.m[2][2] = 1.0f;
slouken@7239
   891
        matrix.m[2][3] = 0.0f;
slouken@7239
   892
        matrix.m[3][0] = -1.0f;
slouken@7239
   893
        matrix.m[3][1] = 1.0f;
slouken@7239
   894
        matrix.m[3][2] = 0.0f;
slouken@7239
   895
        matrix.m[3][3] = 1.0f;
slouken@7239
   896
        IDirect3DDevice9_SetTransform(data->device, D3DTS_PROJECTION, &matrix);
slouken@7239
   897
    }
slouken@5297
   898
slouken@5297
   899
    return 0;
slouken@5297
   900
}
slouken@5297
   901
slouken@5297
   902
static int
slouken@7141
   903
D3D_UpdateClipRect(SDL_Renderer * renderer)
slouken@6246
   904
{
slouken@7141
   905
    const SDL_Rect *rect = &renderer->clip_rect;
slouken@6246
   906
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@7141
   907
    RECT r;
slouken@6246
   908
    HRESULT result;
slouken@6246
   909
slouken@7141
   910
    if (!SDL_RectEmpty(rect)) {
slouken@7141
   911
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_SCISSORTESTENABLE, TRUE);
slouken@7141
   912
        r.left = rect->x;
slouken@7141
   913
        r.top = rect->y;
slouken@7472
   914
        r.right = rect->x + rect->w;
slouken@7141
   915
        r.bottom = rect->y + rect->h;
slouken@6246
   916
slouken@7141
   917
        result = IDirect3DDevice9_SetScissorRect(data->device, &r);
slouken@7141
   918
        if (result != D3D_OK) {
slouken@7141
   919
            D3D_SetError("SetScissor()", result);
slouken@7141
   920
            return -1;
slouken@7141
   921
        }
slouken@7141
   922
    } else {
slouken@7141
   923
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_SCISSORTESTENABLE, FALSE);
slouken@6246
   924
    }
slouken@6246
   925
    return 0;
slouken@6246
   926
}
slouken@6246
   927
slouken@6246
   928
static int
slouken@5297
   929
D3D_RenderClear(SDL_Renderer * renderer)
slouken@5297
   930
{
slouken@5297
   931
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@5297
   932
    DWORD color;
slouken@5297
   933
    HRESULT result;
slouken@5297
   934
slouken@5297
   935
    if (D3D_ActivateRenderer(renderer) < 0) {
slouken@5297
   936
        return -1;
slouken@5224
   937
    }
slouken@5297
   938
slouken@5297
   939
    color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
slouken@5297
   940
slouken@5299
   941
    /* Don't reset the viewport if we don't have to! */
slouken@5299
   942
    if (!renderer->viewport.x && !renderer->viewport.y &&
slouken@5299
   943
        renderer->viewport.w == data->pparams.BackBufferWidth &&
slouken@5299
   944
        renderer->viewport.h == data->pparams.BackBufferHeight) {
slouken@5299
   945
        result = IDirect3DDevice9_Clear(data->device, 0, NULL, D3DCLEAR_TARGET, color, 0.0f, 0);
slouken@5299
   946
    } else {
slouken@5299
   947
        D3DVIEWPORT9 viewport;
slouken@5297
   948
slouken@5299
   949
        /* Clear is defined to clear the entire render target */
slouken@5299
   950
        viewport.X = 0;
slouken@5299
   951
        viewport.Y = 0;
slouken@5299
   952
        viewport.Width = data->pparams.BackBufferWidth;
slouken@5299
   953
        viewport.Height = data->pparams.BackBufferHeight;
slouken@5299
   954
        viewport.MinZ = 0.0f;
slouken@5299
   955
        viewport.MaxZ = 1.0f;
slouken@5299
   956
        IDirect3DDevice9_SetViewport(data->device, &viewport);
slouken@5299
   957
slouken@5299
   958
        result = IDirect3DDevice9_Clear(data->device, 0, NULL, D3DCLEAR_TARGET, color, 0.0f, 0);
slouken@5299
   959
slouken@5299
   960
        /* Reset the viewport */
slouken@5299
   961
        viewport.X = renderer->viewport.x;
slouken@5299
   962
        viewport.Y = renderer->viewport.y;
slouken@5299
   963
        viewport.Width = renderer->viewport.w;
slouken@5299
   964
        viewport.Height = renderer->viewport.h;
slouken@5299
   965
        viewport.MinZ = 0.0f;
slouken@5299
   966
        viewport.MaxZ = 1.0f;
slouken@5299
   967
        IDirect3DDevice9_SetViewport(data->device, &viewport);
slouken@5299
   968
    }
slouken@5297
   969
slouken@5297
   970
    if (FAILED(result)) {
icculus@7037
   971
        return D3D_SetError("Clear()", result);
slouken@5297
   972
    }
slouken@5297
   973
    return 0;
slouken@5224
   974
}
slouken@5224
   975
slouken@5224
   976
static void
slouken@2933
   977
D3D_SetBlendMode(D3D_RenderData * data, int blendMode)
slouken@2932
   978
{
slouken@2932
   979
    switch (blendMode) {
slouken@2932
   980
    case SDL_BLENDMODE_NONE:
slouken@2932
   981
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
slouken@2932
   982
                                        FALSE);
slouken@2932
   983
        break;
slouken@2932
   984
    case SDL_BLENDMODE_BLEND:
slouken@2932
   985
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
slouken@2932
   986
                                        TRUE);
slouken@2932
   987
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
slouken@2932
   988
                                        D3DBLEND_SRCALPHA);
slouken@2932
   989
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
slouken@2932
   990
                                        D3DBLEND_INVSRCALPHA);
slouken@7502
   991
        if (data->enableSeparateAlphaBlend) {
slouken@7502
   992
            IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLENDALPHA,
slouken@7502
   993
                                            D3DBLEND_ONE);
slouken@7502
   994
            IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLENDALPHA,
slouken@7502
   995
                                            D3DBLEND_INVSRCALPHA);
slouken@7502
   996
        }
slouken@2932
   997
        break;
slouken@2932
   998
    case SDL_BLENDMODE_ADD:
slouken@2932
   999
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
slouken@2932
  1000
                                        TRUE);
slouken@2932
  1001
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
slouken@2932
  1002
                                        D3DBLEND_SRCALPHA);
slouken@2932
  1003
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
slouken@2932
  1004
                                        D3DBLEND_ONE);
slouken@7502
  1005
        if (data->enableSeparateAlphaBlend) {
slouken@7502
  1006
            IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLENDALPHA,
slouken@7502
  1007
                                            D3DBLEND_ZERO);
slouken@7502
  1008
            IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLENDALPHA,
slouken@7502
  1009
                                            D3DBLEND_ONE);
slouken@7502
  1010
        }
slouken@2932
  1011
        break;
slouken@5184
  1012
    case SDL_BLENDMODE_MOD:
slouken@5184
  1013
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
slouken@5184
  1014
                                        TRUE);
slouken@5184
  1015
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
slouken@5184
  1016
                                        D3DBLEND_ZERO);
slouken@5184
  1017
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
slouken@5184
  1018
                                        D3DBLEND_SRCCOLOR);
slouken@7502
  1019
        if (data->enableSeparateAlphaBlend) {
slouken@7502
  1020
            IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLENDALPHA,
slouken@7502
  1021
                                            D3DBLEND_ZERO);
slouken@7502
  1022
            IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLENDALPHA,
slouken@7502
  1023
                                            D3DBLEND_ONE);
slouken@7502
  1024
        }
slouken@5184
  1025
        break;
slouken@2932
  1026
    }
slouken@2932
  1027
}
slouken@2932
  1028
slouken@1895
  1029
static int
slouken@6528
  1030
D3D_RenderDrawPoints(SDL_Renderer * renderer, const SDL_FPoint * points,
slouken@3599
  1031
                     int count)
slouken@1895
  1032
{
slouken@1913
  1033
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@2932
  1034
    DWORD color;
slouken@3536
  1035
    Vertex *vertices;
slouken@3536
  1036
    int i;
slouken@1900
  1037
    HRESULT result;
slouken@1895
  1038
slouken@5297
  1039
    if (D3D_ActivateRenderer(renderer) < 0) {
slouken@5297
  1040
        return -1;
slouken@1900
  1041
    }
slouken@1895
  1042
slouken@2932
  1043
    D3D_SetBlendMode(data, renderer->blendMode);
slouken@2932
  1044
slouken@2933
  1045
    result =
slouken@2933
  1046
        IDirect3DDevice9_SetTexture(data->device, 0,
slouken@2933
  1047
                                    (IDirect3DBaseTexture9 *) 0);
slouken@2932
  1048
    if (FAILED(result)) {
icculus@7037
  1049
        return D3D_SetError("SetTexture()", result);
slouken@2932
  1050
    }
slouken@3536
  1051
slouken@3536
  1052
    color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
slouken@3536
  1053
slouken@3536
  1054
    vertices = SDL_stack_alloc(Vertex, count);
slouken@3536
  1055
    for (i = 0; i < count; ++i) {
slouken@6528
  1056
        vertices[i].x = points[i].x;
slouken@6528
  1057
        vertices[i].y = points[i].y;
slouken@3536
  1058
        vertices[i].z = 0.0f;
slouken@3536
  1059
        vertices[i].color = color;
slouken@3536
  1060
        vertices[i].u = 0.0f;
slouken@3536
  1061
        vertices[i].v = 0.0f;
slouken@3536
  1062
    }
slouken@1903
  1063
    result =
slouken@3536
  1064
        IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_POINTLIST, count,
slouken@2932
  1065
                                         vertices, sizeof(*vertices));
slouken@3536
  1066
    SDL_stack_free(vertices);
slouken@1900
  1067
    if (FAILED(result)) {
icculus@7037
  1068
        return D3D_SetError("DrawPrimitiveUP()", result);
slouken@2932
  1069
    }
slouken@2932
  1070
    return 0;
slouken@2932
  1071
}
slouken@2932
  1072
slouken@2932
  1073
static int
slouken@6528
  1074
D3D_RenderDrawLines(SDL_Renderer * renderer, const SDL_FPoint * points,
slouken@3599
  1075
                    int count)
slouken@2932
  1076
{
slouken@2932
  1077
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@2932
  1078
    DWORD color;
slouken@3536
  1079
    Vertex *vertices;
slouken@3536
  1080
    int i;
slouken@2932
  1081
    HRESULT result;
slouken@2932
  1082
slouken@5297
  1083
    if (D3D_ActivateRenderer(renderer) < 0) {
slouken@5297
  1084
        return -1;
slouken@2932
  1085
    }
slouken@2932
  1086
slouken@2932
  1087
    D3D_SetBlendMode(data, renderer->blendMode);
slouken@2932
  1088
slouken@2933
  1089
    result =
slouken@2933
  1090
        IDirect3DDevice9_SetTexture(data->device, 0,
slouken@2933
  1091
                                    (IDirect3DBaseTexture9 *) 0);
slouken@2932
  1092
    if (FAILED(result)) {
icculus@7037
  1093
        return D3D_SetError("SetTexture()", result);
slouken@2932
  1094
    }
slouken@3536
  1095
slouken@3536
  1096
    color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
slouken@3536
  1097
slouken@3536
  1098
    vertices = SDL_stack_alloc(Vertex, count);
slouken@3536
  1099
    for (i = 0; i < count; ++i) {
slouken@6528
  1100
        vertices[i].x = points[i].x;
slouken@6528
  1101
        vertices[i].y = points[i].y;
slouken@3536
  1102
        vertices[i].z = 0.0f;
slouken@3536
  1103
        vertices[i].color = color;
slouken@3536
  1104
        vertices[i].u = 0.0f;
slouken@3536
  1105
        vertices[i].v = 0.0f;
slouken@3536
  1106
    }
slouken@2932
  1107
    result =
slouken@3551
  1108
        IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_LINESTRIP, count-1,
slouken@2932
  1109
                                         vertices, sizeof(*vertices));
slouken@3551
  1110
slouken@3551
  1111
    /* DirectX 9 has the same line rasterization semantics as GDI,
slouken@3551
  1112
       so we need to close the endpoint of the line */
slouken@6076
  1113
    if (count == 2 ||
slouken@6076
  1114
        points[0].x != points[count-1].x || points[0].y != points[count-1].y) {
slouken@6528
  1115
        vertices[0].x = points[count-1].x;
slouken@6528
  1116
        vertices[0].y = points[count-1].y;
slouken@3551
  1117
        result = IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_POINTLIST, 1, vertices, sizeof(*vertices));
slouken@3551
  1118
    }
slouken@3551
  1119
slouken@3536
  1120
    SDL_stack_free(vertices);
slouken@2932
  1121
    if (FAILED(result)) {
icculus@7037
  1122
        return D3D_SetError("DrawPrimitiveUP()", result);
slouken@2932
  1123
    }
slouken@2932
  1124
    return 0;
slouken@2932
  1125
}
slouken@2932
  1126
slouken@2932
  1127
static int
slouken@6528
  1128
D3D_RenderFillRects(SDL_Renderer * renderer, const SDL_FRect * rects,
slouken@3599
  1129
                    int count)
slouken@2932
  1130
{
slouken@2932
  1131
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@3536
  1132
    DWORD color;
slouken@3536
  1133
    int i;
slouken@2932
  1134
    float minx, miny, maxx, maxy;
slouken@2932
  1135
    Vertex vertices[4];
slouken@2932
  1136
    HRESULT result;
slouken@2932
  1137
slouken@5297
  1138
    if (D3D_ActivateRenderer(renderer) < 0) {
slouken@5297
  1139
        return -1;
slouken@2932
  1140
    }
slouken@2932
  1141
slouken@2932
  1142
    D3D_SetBlendMode(data, renderer->blendMode);
slouken@2932
  1143
slouken@2933
  1144
    result =
slouken@2933
  1145
        IDirect3DDevice9_SetTexture(data->device, 0,
slouken@2933
  1146
                                    (IDirect3DBaseTexture9 *) 0);
slouken@2932
  1147
    if (FAILED(result)) {
icculus@7037
  1148
        return D3D_SetError("SetTexture()", result);
slouken@2932
  1149
    }
slouken@3536
  1150
slouken@3536
  1151
    color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
slouken@3536
  1152
slouken@3536
  1153
    for (i = 0; i < count; ++i) {
slouken@6528
  1154
        const SDL_FRect *rect = &rects[i];
slouken@3536
  1155
slouken@6528
  1156
        minx = rect->x;
slouken@6528
  1157
        miny = rect->y;
slouken@6528
  1158
        maxx = rect->x + rect->w;
slouken@6528
  1159
        maxy = rect->y + rect->h;
slouken@3536
  1160
slouken@3536
  1161
        vertices[0].x = minx;
slouken@3536
  1162
        vertices[0].y = miny;
slouken@3536
  1163
        vertices[0].z = 0.0f;
slouken@3536
  1164
        vertices[0].color = color;
slouken@3536
  1165
        vertices[0].u = 0.0f;
slouken@3536
  1166
        vertices[0].v = 0.0f;
slouken@3536
  1167
slouken@3536
  1168
        vertices[1].x = maxx;
slouken@3536
  1169
        vertices[1].y = miny;
slouken@3536
  1170
        vertices[1].z = 0.0f;
slouken@3536
  1171
        vertices[1].color = color;
slouken@3536
  1172
        vertices[1].u = 0.0f;
slouken@3536
  1173
        vertices[1].v = 0.0f;
slouken@3536
  1174
slouken@3536
  1175
        vertices[2].x = maxx;
slouken@3536
  1176
        vertices[2].y = maxy;
slouken@3536
  1177
        vertices[2].z = 0.0f;
slouken@3536
  1178
        vertices[2].color = color;
slouken@3536
  1179
        vertices[2].u = 0.0f;
slouken@3536
  1180
        vertices[2].v = 0.0f;
slouken@3536
  1181
slouken@3536
  1182
        vertices[3].x = minx;
slouken@3536
  1183
        vertices[3].y = maxy;
slouken@3536
  1184
        vertices[3].z = 0.0f;
slouken@3536
  1185
        vertices[3].color = color;
slouken@3536
  1186
        vertices[3].u = 0.0f;
slouken@3536
  1187
        vertices[3].v = 0.0f;
slouken@3536
  1188
slouken@3536
  1189
        result =
slouken@3536
  1190
            IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN,
slouken@3536
  1191
                                             2, vertices, sizeof(*vertices));
slouken@3536
  1192
        if (FAILED(result)) {
icculus@7037
  1193
            return D3D_SetError("DrawPrimitiveUP()", result);
slouken@3536
  1194
        }
slouken@1900
  1195
    }
slouken@1895
  1196
    return 0;
slouken@1895
  1197
}
slouken@1895
  1198
slouken@1895
  1199
static int
slouken@1913
  1200
D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@6528
  1201
               const SDL_Rect * srcrect, const SDL_FRect * dstrect)
slouken@1895
  1202
{
slouken@1913
  1203
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@1913
  1204
    D3D_TextureData *texturedata = (D3D_TextureData *) texture->driverdata;
slouken@3556
  1205
    LPDIRECT3DPIXELSHADER9 shader = NULL;
slouken@1903
  1206
    float minx, miny, maxx, maxy;
slouken@1904
  1207
    float minu, maxu, minv, maxv;
slouken@1987
  1208
    DWORD color;
slouken@1903
  1209
    Vertex vertices[4];
slouken@1903
  1210
    HRESULT result;
slouken@1895
  1211
slouken@5297
  1212
    if (D3D_ActivateRenderer(renderer) < 0) {
slouken@5297
  1213
        return -1;
slouken@1900
  1214
    }
slouken@1903
  1215
slouken@6528
  1216
    minx = dstrect->x - 0.5f;
slouken@6528
  1217
    miny = dstrect->y - 0.5f;
slouken@6528
  1218
    maxx = dstrect->x + dstrect->w - 0.5f;
slouken@6528
  1219
    maxy = dstrect->y + dstrect->h - 0.5f;
slouken@1903
  1220
slouken@1904
  1221
    minu = (float) srcrect->x / texture->w;
slouken@1904
  1222
    maxu = (float) (srcrect->x + srcrect->w) / texture->w;
slouken@1904
  1223
    minv = (float) srcrect->y / texture->h;
slouken@1904
  1224
    maxv = (float) (srcrect->y + srcrect->h) / texture->h;
slouken@1903
  1225
slouken@1987
  1226
    color = D3DCOLOR_ARGB(texture->a, texture->r, texture->g, texture->b);
slouken@1987
  1227
slouken@1903
  1228
    vertices[0].x = minx;
slouken@1903
  1229
    vertices[0].y = miny;
slouken@1903
  1230
    vertices[0].z = 0.0f;
slouken@1987
  1231
    vertices[0].color = color;
slouken@1904
  1232
    vertices[0].u = minu;
slouken@1904
  1233
    vertices[0].v = minv;
slouken@1904
  1234
slouken@1903
  1235
    vertices[1].x = maxx;
slouken@1903
  1236
    vertices[1].y = miny;
slouken@1903
  1237
    vertices[1].z = 0.0f;
slouken@1987
  1238
    vertices[1].color = color;
slouken@1904
  1239
    vertices[1].u = maxu;
slouken@1904
  1240
    vertices[1].v = minv;
slouken@1904
  1241
slouken@1903
  1242
    vertices[2].x = maxx;
slouken@1903
  1243
    vertices[2].y = maxy;
slouken@1903
  1244
    vertices[2].z = 0.0f;
slouken@1987
  1245
    vertices[2].color = color;
slouken@1904
  1246
    vertices[2].u = maxu;
slouken@1904
  1247
    vertices[2].v = maxv;
slouken@1904
  1248
slouken@1903
  1249
    vertices[3].x = minx;
slouken@1903
  1250
    vertices[3].y = maxy;
slouken@1903
  1251
    vertices[3].z = 0.0f;
slouken@1987
  1252
    vertices[3].color = color;
slouken@1904
  1253
    vertices[3].u = minu;
slouken@1904
  1254
    vertices[3].v = maxv;
slouken@1903
  1255
slouken@2932
  1256
    D3D_SetBlendMode(data, texture->blendMode);
slouken@1916
  1257
slouken@5484
  1258
    if (texturedata->scaleMode != data->scaleMode) {
slouken@5484
  1259
        IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MINFILTER,
slouken@5484
  1260
                                         texturedata->scaleMode);
slouken@5484
  1261
        IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MAGFILTER,
slouken@5484
  1262
                                         texturedata->scaleMode);
slouken@5484
  1263
        data->scaleMode = texturedata->scaleMode;
slouken@5484
  1264
    }
slouken@1917
  1265
slouken@1903
  1266
    result =
slouken@2735
  1267
        IDirect3DDevice9_SetTexture(data->device, 0, (IDirect3DBaseTexture9 *)
slouken@2735
  1268
                                    texturedata->texture);
slouken@1903
  1269
    if (FAILED(result)) {
icculus@7037
  1270
        return D3D_SetError("SetTexture()", result);
slouken@1903
  1271
    }
slouken@3556
  1272
    if (shader) {
slouken@3556
  1273
        result = IDirect3DDevice9_SetPixelShader(data->device, shader);
slouken@3556
  1274
        if (FAILED(result)) {
icculus@7037
  1275
            return D3D_SetError("SetShader()", result);
slouken@3556
  1276
        }
slouken@3556
  1277
    }
slouken@1903
  1278
    result =
slouken@1903
  1279
        IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN, 2,
slouken@1903
  1280
                                         vertices, sizeof(*vertices));
slouken@1903
  1281
    if (FAILED(result)) {
icculus@7037
  1282
        return D3D_SetError("DrawPrimitiveUP()", result);
slouken@1903
  1283
    }
slouken@3556
  1284
    if (shader) {
slouken@3556
  1285
        result = IDirect3DDevice9_SetPixelShader(data->device, NULL);
slouken@3556
  1286
        if (FAILED(result)) {
icculus@7037
  1287
            return D3D_SetError("SetShader()", result);
slouken@3556
  1288
        }
slouken@3556
  1289
    }
slouken@1895
  1290
    return 0;
slouken@1895
  1291
}
slouken@1895
  1292
gabomdq@6320
  1293
gabomdq@6320
  1294
static int
gabomdq@6320
  1295
D3D_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@6528
  1296
               const SDL_Rect * srcrect, const SDL_FRect * dstrect,
slouken@6528
  1297
               const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip)
gabomdq@6320
  1298
{
gabomdq@6320
  1299
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
gabomdq@6320
  1300
    D3D_TextureData *texturedata = (D3D_TextureData *) texture->driverdata;
gabomdq@6320
  1301
    LPDIRECT3DPIXELSHADER9 shader = NULL;
gabomdq@6320
  1302
    float minx, miny, maxx, maxy;
gabomdq@6320
  1303
    float minu, maxu, minv, maxv;
gabomdq@6320
  1304
    float centerx, centery;
gabomdq@6320
  1305
    DWORD color;
gabomdq@6320
  1306
    Vertex vertices[4];
gabomdq@6320
  1307
    HRESULT result;
gabomdq@6320
  1308
gabomdq@6320
  1309
    if (D3D_ActivateRenderer(renderer) < 0) {
gabomdq@6320
  1310
        return -1;
gabomdq@6320
  1311
    }
gabomdq@6320
  1312
slouken@6528
  1313
    centerx = center->x;
slouken@6528
  1314
    centery = center->y;
gabomdq@6320
  1315
gabomdq@6320
  1316
    if (flip & SDL_FLIP_HORIZONTAL) {
slouken@6528
  1317
        minx = dstrect->w - centerx - 0.5f;
slouken@6528
  1318
        maxx = -centerx - 0.5f;
gabomdq@6320
  1319
    }
gabomdq@6320
  1320
    else {
slouken@6528
  1321
        minx = -centerx - 0.5f;
slouken@6528
  1322
        maxx = dstrect->w - centerx - 0.5f;
gabomdq@6320
  1323
    }
gabomdq@6320
  1324
gabomdq@6320
  1325
    if (flip & SDL_FLIP_VERTICAL) {
slouken@6528
  1326
        miny = dstrect->h - centery - 0.5f;
slouken@6528
  1327
        maxy = -centery - 0.5f;
gabomdq@6320
  1328
    }
gabomdq@6320
  1329
    else {
slouken@6528
  1330
        miny = -centery - 0.5f;
slouken@6528
  1331
        maxy = dstrect->h - centery - 0.5f;
gabomdq@6320
  1332
    }
gabomdq@6320
  1333
gabomdq@6320
  1334
    minu = (float) srcrect->x / texture->w;
gabomdq@6320
  1335
    maxu = (float) (srcrect->x + srcrect->w) / texture->w;
gabomdq@6320
  1336
    minv = (float) srcrect->y / texture->h;
gabomdq@6320
  1337
    maxv = (float) (srcrect->y + srcrect->h) / texture->h;
gabomdq@6320
  1338
gabomdq@6320
  1339
    color = D3DCOLOR_ARGB(texture->a, texture->r, texture->g, texture->b);
gabomdq@6320
  1340
gabomdq@6320
  1341
    vertices[0].x = minx;
gabomdq@6320
  1342
    vertices[0].y = miny;
gabomdq@6320
  1343
    vertices[0].z = 0.0f;
gabomdq@6320
  1344
    vertices[0].color = color;
gabomdq@6320
  1345
    vertices[0].u = minu;
gabomdq@6320
  1346
    vertices[0].v = minv;
gabomdq@6320
  1347
gabomdq@6320
  1348
    vertices[1].x = maxx;
gabomdq@6320
  1349
    vertices[1].y = miny;
gabomdq@6320
  1350
    vertices[1].z = 0.0f;
gabomdq@6320
  1351
    vertices[1].color = color;
gabomdq@6320
  1352
    vertices[1].u = maxu;
gabomdq@6320
  1353
    vertices[1].v = minv;
gabomdq@6320
  1354
gabomdq@6320
  1355
    vertices[2].x = maxx;
gabomdq@6320
  1356
    vertices[2].y = maxy;
gabomdq@6320
  1357
    vertices[2].z = 0.0f;
gabomdq@6320
  1358
    vertices[2].color = color;
gabomdq@6320
  1359
    vertices[2].u = maxu;
gabomdq@6320
  1360
    vertices[2].v = maxv;
gabomdq@6320
  1361
gabomdq@6320
  1362
    vertices[3].x = minx;
gabomdq@6320
  1363
    vertices[3].y = maxy;
gabomdq@6320
  1364
    vertices[3].z = 0.0f;
gabomdq@6320
  1365
    vertices[3].color = color;
gabomdq@6320
  1366
    vertices[3].u = minu;
gabomdq@6320
  1367
    vertices[3].v = maxv;
gabomdq@6320
  1368
gabomdq@6320
  1369
    D3D_SetBlendMode(data, texture->blendMode);
gabomdq@6320
  1370
slouken@7191
  1371
    /* Rotate and translate */
gabomdq@6320
  1372
    ID3DXMatrixStack_Push(data->matrixStack);
gabomdq@6320
  1373
    ID3DXMatrixStack_LoadIdentity(data->matrixStack);
slouken@6332
  1374
    ID3DXMatrixStack_RotateYawPitchRoll(data->matrixStack, 0.0, 0.0, (float)(M_PI * (float) angle / 180.0f));
gabomdq@6320
  1375
    ID3DXMatrixStack_Translate(data->matrixStack, (float)dstrect->x + centerx, (float)dstrect->y + centery, (float)0.0);
gabomdq@6320
  1376
    IDirect3DDevice9_SetTransform(data->device, D3DTS_VIEW, (D3DMATRIX*)ID3DXMatrixStack_GetTop(data->matrixStack));
gabomdq@6320
  1377
gabomdq@6320
  1378
    if (texturedata->scaleMode != data->scaleMode) {
gabomdq@6320
  1379
        IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MINFILTER,
gabomdq@6320
  1380
                                         texturedata->scaleMode);
gabomdq@6320
  1381
        IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MAGFILTER,
gabomdq@6320
  1382
                                         texturedata->scaleMode);
gabomdq@6320
  1383
        data->scaleMode = texturedata->scaleMode;
gabomdq@6320
  1384
    }
gabomdq@6320
  1385
gabomdq@6320
  1386
    result =
gabomdq@6320
  1387
        IDirect3DDevice9_SetTexture(data->device, 0, (IDirect3DBaseTexture9 *)
gabomdq@6320
  1388
                                    texturedata->texture);
gabomdq@6320
  1389
    if (FAILED(result)) {
icculus@7037
  1390
        return D3D_SetError("SetTexture()", result);
gabomdq@6320
  1391
    }
gabomdq@6320
  1392
    if (shader) {
gabomdq@6320
  1393
        result = IDirect3DDevice9_SetPixelShader(data->device, shader);
gabomdq@6320
  1394
        if (FAILED(result)) {
icculus@7037
  1395
            return D3D_SetError("SetShader()", result);
gabomdq@6320
  1396
        }
gabomdq@6320
  1397
    }
gabomdq@6320
  1398
    result =
gabomdq@6320
  1399
        IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN, 2,
gabomdq@6320
  1400
                                         vertices, sizeof(*vertices));
gabomdq@6320
  1401
    if (FAILED(result)) {
icculus@7037
  1402
        return D3D_SetError("DrawPrimitiveUP()", result);
gabomdq@6320
  1403
    }
gabomdq@6320
  1404
    if (shader) {
gabomdq@6320
  1405
        result = IDirect3DDevice9_SetPixelShader(data->device, NULL);
gabomdq@6320
  1406
        if (FAILED(result)) {
icculus@7037
  1407
            return D3D_SetError("SetShader()", result);
gabomdq@6320
  1408
        }
gabomdq@6320
  1409
    }
gabomdq@6320
  1410
    ID3DXMatrixStack_Pop(data->matrixStack);
gabomdq@6320
  1411
    ID3DXMatrixStack_Push(data->matrixStack);
gabomdq@6320
  1412
    ID3DXMatrixStack_LoadIdentity(data->matrixStack);
gabomdq@6320
  1413
    IDirect3DDevice9_SetTransform(data->device, D3DTS_VIEW, (D3DMATRIX*)ID3DXMatrixStack_GetTop(data->matrixStack));
gabomdq@6320
  1414
    ID3DXMatrixStack_Pop(data->matrixStack);
gabomdq@6320
  1415
    return 0;
gabomdq@6320
  1416
}
gabomdq@6320
  1417
slouken@3427
  1418
static int
slouken@3427
  1419
D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
slouken@3480
  1420
                     Uint32 format, void * pixels, int pitch)
slouken@3427
  1421
{
slouken@3549
  1422
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@3549
  1423
    D3DSURFACE_DESC desc;
slouken@3549
  1424
    LPDIRECT3DSURFACE9 backBuffer;
slouken@3549
  1425
    LPDIRECT3DSURFACE9 surface;
slouken@3549
  1426
    RECT d3drect;
slouken@3549
  1427
    D3DLOCKED_RECT locked;
slouken@3549
  1428
    HRESULT result;
slouken@3427
  1429
slouken@3549
  1430
    result = IDirect3DDevice9_GetBackBuffer(data->device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuffer);
slouken@3549
  1431
    if (FAILED(result)) {
icculus@7037
  1432
        return D3D_SetError("GetBackBuffer()", result);
slouken@3549
  1433
    }
slouken@3427
  1434
slouken@3549
  1435
    result = IDirect3DSurface9_GetDesc(backBuffer, &desc);
slouken@3549
  1436
    if (FAILED(result)) {
slouken@3549
  1437
        IDirect3DSurface9_Release(backBuffer);
icculus@7037
  1438
        return D3D_SetError("GetDesc()", result);
slouken@3549
  1439
    }
slouken@3427
  1440
slouken@3549
  1441
    result = IDirect3DDevice9_CreateOffscreenPlainSurface(data->device, desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surface, NULL);
slouken@3549
  1442
    if (FAILED(result)) {
slouken@3549
  1443
        IDirect3DSurface9_Release(backBuffer);
icculus@7037
  1444
        return D3D_SetError("CreateOffscreenPlainSurface()", result);
slouken@3549
  1445
    }
slouken@3427
  1446
slouken@3549
  1447
    result = IDirect3DDevice9_GetRenderTargetData(data->device, backBuffer, surface);
slouken@3549
  1448
    if (FAILED(result)) {
slouken@3549
  1449
        IDirect3DSurface9_Release(surface);
slouken@3549
  1450
        IDirect3DSurface9_Release(backBuffer);
icculus@7037
  1451
        return D3D_SetError("GetRenderTargetData()", result);
slouken@3549
  1452
    }
slouken@3427
  1453
slouken@3549
  1454
    d3drect.left = rect->x;
slouken@3549
  1455
    d3drect.right = rect->x + rect->w;
slouken@3549
  1456
    d3drect.top = rect->y;
slouken@3549
  1457
    d3drect.bottom = rect->y + rect->h;
slouken@3427
  1458
slouken@3549
  1459
    result = IDirect3DSurface9_LockRect(surface, &locked, &d3drect, D3DLOCK_READONLY);
slouken@3549
  1460
    if (FAILED(result)) {
slouken@3549
  1461
        IDirect3DSurface9_Release(surface);
slouken@3549
  1462
        IDirect3DSurface9_Release(backBuffer);
icculus@7037
  1463
        return D3D_SetError("LockRect()", result);
slouken@3549
  1464
    }
slouken@3427
  1465
slouken@3549
  1466
    SDL_ConvertPixels(rect->w, rect->h,
slouken@5156
  1467
                      D3DFMTToPixelFormat(desc.Format), locked.pBits, locked.Pitch,
slouken@3549
  1468
                      format, pixels, pitch);
slouken@3549
  1469
slouken@3549
  1470
    IDirect3DSurface9_UnlockRect(surface);
slouken@3549
  1471
slouken@3549
  1472
    IDirect3DSurface9_Release(surface);
slouken@3549
  1473
    IDirect3DSurface9_Release(backBuffer);
slouken@3549
  1474
slouken@3549
  1475
    return 0;
slouken@3427
  1476
}
slouken@3427
  1477
slouken@1895
  1478
static void
slouken@1913
  1479
D3D_RenderPresent(SDL_Renderer * renderer)
slouken@1895
  1480
{
slouken@1913
  1481
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@1900
  1482
    HRESULT result;
slouken@1900
  1483
slouken@1900
  1484
    if (!data->beginScene) {
slouken@1900
  1485
        IDirect3DDevice9_EndScene(data->device);
slouken@1900
  1486
        data->beginScene = SDL_TRUE;
slouken@1900
  1487
    }
slouken@1900
  1488
slouken@1975
  1489
    result = IDirect3DDevice9_TestCooperativeLevel(data->device);
slouken@1975
  1490
    if (result == D3DERR_DEVICELOST) {
slouken@1975
  1491
        /* We'll reset later */
slouken@1975
  1492
        return;
slouken@1975
  1493
    }
slouken@1975
  1494
    if (result == D3DERR_DEVICENOTRESET) {
slouken@1975
  1495
        D3D_Reset(renderer);
slouken@1975
  1496
    }
slouken@1900
  1497
    result = IDirect3DDevice9_Present(data->device, NULL, NULL, NULL, NULL);
slouken@1900
  1498
    if (FAILED(result)) {
slouken@1900
  1499
        D3D_SetError("Present()", result);
slouken@1900
  1500
    }
slouken@1895
  1501
}
slouken@1895
  1502
slouken@1895
  1503
static void
slouken@1913
  1504
D3D_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1895
  1505
{
slouken@1913
  1506
    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
slouken@1895
  1507
slouken@1895
  1508
    if (!data) {
slouken@1895
  1509
        return;
slouken@1895
  1510
    }
slouken@1903
  1511
    if (data->texture) {
slouken@1903
  1512
        IDirect3DTexture9_Release(data->texture);
slouken@1903
  1513
    }
slouken@1895
  1514
    SDL_free(data);
slouken@1895
  1515
    texture->driverdata = NULL;
slouken@1895
  1516
}
slouken@1895
  1517
slouken@1975
  1518
static void
slouken@1913
  1519
D3D_DestroyRenderer(SDL_Renderer * renderer)
slouken@1895
  1520
{
slouken@1913
  1521
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@1895
  1522
slouken@1895
  1523
    if (data) {
slouken@7191
  1524
        /* Release the render target */
slouken@6895
  1525
        if (data->defaultRenderTarget) {
slouken@6895
  1526
            IDirect3DSurface9_Release(data->defaultRenderTarget);
slouken@6895
  1527
            data->defaultRenderTarget = NULL;
slouken@6895
  1528
        }
slouken@6232
  1529
        if (data->currentRenderTarget != NULL) {
slouken@6232
  1530
            IDirect3DSurface9_Release(data->currentRenderTarget);
slouken@6232
  1531
            data->currentRenderTarget = NULL;
slouken@6232
  1532
        }
slouken@7191
  1533
slouken@1900
  1534
        if (data->device) {
slouken@1900
  1535
            IDirect3DDevice9_Release(data->device);
slouken@1900
  1536
        }
slouken@5154
  1537
        if (data->d3d) {
slouken@5154
  1538
            IDirect3D9_Release(data->d3d);
slouken@7183
  1539
            ID3DXMatrixStack_Release(data->matrixStack);
slouken@5154
  1540
            SDL_UnloadObject(data->d3dDLL);
slouken@5154
  1541
        }
slouken@1895
  1542
        SDL_free(data);
slouken@1895
  1543
    }
slouken@1895
  1544
    SDL_free(renderer);
slouken@1895
  1545
}
slouken@1895
  1546
slouken@5226
  1547
#endif /* SDL_VIDEO_RENDER_D3D && !SDL_RENDER_DISABLED */
slouken@1895
  1548
slouken@1895
  1549
/* vi: set ts=4 sw=4 expandtab: */