src/render/direct3d/SDL_render_d3d.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 21 Jan 2012 22:22:30 -0500
changeset 6246 c70ec935a4bb
parent 6242 096d2698cc27
child 6247 b6212690f78d
permissions -rwxr-xr-x
Reorganized the render target code, moving the viewport handling to the general code and adding software implementation.
slouken@1895
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@6138
     3
  Copyright (C) 1997-2012 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"
slouken@5154
    32
slouken@5154
    33
#if SDL_VIDEO_RENDER_D3D
slouken@5154
    34
#define D3D_DEBUG_INFO
slouken@5154
    35
#include <d3d9.h>
slouken@5154
    36
#endif
slouken@1895
    37
slouken@3556
    38
#ifdef ASSEMBLE_SHADER
slouken@3556
    39
///////////////////////////////////////////////////////////////////////////
slouken@3556
    40
// ID3DXBuffer:
slouken@3556
    41
// ------------
slouken@3556
    42
// The buffer object is used by D3DX to return arbitrary size data.
slouken@3556
    43
//
slouken@3556
    44
// GetBufferPointer -
slouken@3556
    45
//    Returns a pointer to the beginning of the buffer.
slouken@3556
    46
//
slouken@3556
    47
// GetBufferSize -
slouken@3556
    48
//    Returns the size of the buffer, in bytes.
slouken@3556
    49
///////////////////////////////////////////////////////////////////////////
slouken@3556
    50
slouken@3556
    51
typedef interface ID3DXBuffer ID3DXBuffer;
slouken@3556
    52
typedef interface ID3DXBuffer *LPD3DXBUFFER;
slouken@3556
    53
slouken@3556
    54
// {8BA5FB08-5195-40e2-AC58-0D989C3A0102}
slouken@3556
    55
DEFINE_GUID(IID_ID3DXBuffer, 
slouken@3556
    56
0x8ba5fb08, 0x5195, 0x40e2, 0xac, 0x58, 0xd, 0x98, 0x9c, 0x3a, 0x1, 0x2);
slouken@3556
    57
slouken@3556
    58
#undef INTERFACE
slouken@3556
    59
#define INTERFACE ID3DXBuffer
slouken@3556
    60
slouken@3556
    61
typedef interface ID3DXBuffer {
slouken@3556
    62
    const struct ID3DXBufferVtbl FAR* lpVtbl;
slouken@3556
    63
} ID3DXBuffer;
slouken@3556
    64
typedef const struct ID3DXBufferVtbl ID3DXBufferVtbl;
slouken@3556
    65
const struct ID3DXBufferVtbl
slouken@3556
    66
{
slouken@3556
    67
    // IUnknown
slouken@3556
    68
    STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE;
slouken@3556
    69
    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
slouken@3556
    70
    STDMETHOD_(ULONG, Release)(THIS) PURE;
slouken@3556
    71
slouken@3556
    72
    // ID3DXBuffer
slouken@3556
    73
    STDMETHOD_(LPVOID, GetBufferPointer)(THIS) PURE;
slouken@3556
    74
    STDMETHOD_(DWORD, GetBufferSize)(THIS) PURE;
slouken@3556
    75
};
slouken@3556
    76
slouken@3556
    77
HRESULT WINAPI
slouken@3556
    78
    D3DXAssembleShader(
slouken@3556
    79
        LPCSTR                          pSrcData,
slouken@3556
    80
        UINT                            SrcDataLen,
slouken@3556
    81
        CONST LPVOID*                   pDefines,
slouken@3556
    82
        LPVOID                          pInclude,
slouken@3556
    83
        DWORD                           Flags,
slouken@3556
    84
        LPD3DXBUFFER*                   ppShader,
slouken@3556
    85
        LPD3DXBUFFER*                   ppErrorMsgs);
slouken@3556
    86
slouken@3556
    87
#endif /* ASSEMBLE_SHADER */
slouken@3556
    88
slouken@3556
    89
slouken@1895
    90
/* Direct3D renderer implementation */
slouken@1895
    91
slouken@1913
    92
static SDL_Renderer *D3D_CreateRenderer(SDL_Window * window, Uint32 flags);
slouken@5297
    93
static void D3D_WindowEvent(SDL_Renderer * renderer,
slouken@5297
    94
                            const SDL_WindowEvent *event);
slouken@1913
    95
static int D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
slouken@1913
    96
static int D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1913
    97
                             const SDL_Rect * rect, const void *pixels,
slouken@1913
    98
                             int pitch);
slouken@1913
    99
static int D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@5156
   100
                           const SDL_Rect * rect, void **pixels, int *pitch);
slouken@1913
   101
static void D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
slouken@6246
   102
static int D3D_SetTargetTexture(SDL_Renderer * renderer, SDL_Texture * texture);
slouken@5297
   103
static int D3D_UpdateViewport(SDL_Renderer * renderer);
slouken@5297
   104
static int D3D_RenderClear(SDL_Renderer * renderer);
slouken@3599
   105
static int D3D_RenderDrawPoints(SDL_Renderer * renderer,
slouken@3599
   106
                                const SDL_Point * points, int count);
slouken@3599
   107
static int D3D_RenderDrawLines(SDL_Renderer * renderer,
slouken@3599
   108
                               const SDL_Point * points, int count);
slouken@3599
   109
static int D3D_RenderFillRects(SDL_Renderer * renderer,
slouken@5297
   110
                               const SDL_Rect * rects, int count);
slouken@1913
   111
static int D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1985
   112
                          const SDL_Rect * srcrect, const SDL_Rect * dstrect);
slouken@3427
   113
static int D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
slouken@3480
   114
                                Uint32 format, void * pixels, int pitch);
slouken@1913
   115
static void D3D_RenderPresent(SDL_Renderer * renderer);
slouken@1913
   116
static void D3D_DestroyTexture(SDL_Renderer * renderer,
slouken@1913
   117
                               SDL_Texture * texture);
slouken@1913
   118
static void D3D_DestroyRenderer(SDL_Renderer * renderer);
slouken@1895
   119
slouken@1895
   120
slouken@1913
   121
SDL_RenderDriver D3D_RenderDriver = {
slouken@1913
   122
    D3D_CreateRenderer,
slouken@1895
   123
    {
slouken@5186
   124
     "direct3d",
slouken@6237
   125
     (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE),
slouken@5156
   126
     1,
slouken@5156
   127
     {SDL_PIXELFORMAT_ARGB8888},
slouken@1895
   128
     0,
slouken@1895
   129
     0}
slouken@1895
   130
};
slouken@1895
   131
slouken@1895
   132
typedef struct
slouken@1895
   133
{
slouken@5154
   134
    void* d3dDLL;
slouken@2973
   135
    IDirect3D9 *d3d;
slouken@1895
   136
    IDirect3DDevice9 *device;
slouken@3527
   137
    UINT adapter;
slouken@1975
   138
    D3DPRESENT_PARAMETERS pparams;
slouken@5297
   139
    SDL_bool updateSize;
slouken@1900
   140
    SDL_bool beginScene;
slouken@5484
   141
    D3DTEXTUREFILTERTYPE scaleMode;
slouken@6232
   142
    IDirect3DSurface9 *defaultRenderTarget;
slouken@6232
   143
    IDirect3DSurface9 *currentRenderTarget;
slouken@1913
   144
} D3D_RenderData;
slouken@1895
   145
slouken@1895
   146
typedef struct
slouken@1895
   147
{
slouken@1903
   148
    IDirect3DTexture9 *texture;
slouken@5484
   149
    D3DTEXTUREFILTERTYPE scaleMode;
slouken@1913
   150
} D3D_TextureData;
slouken@1895
   151
slouken@1903
   152
typedef struct
slouken@1903
   153
{
slouken@1903
   154
    float x, y, z;
slouken@1987
   155
    DWORD color;
slouken@1904
   156
    float u, v;
slouken@1903
   157
} Vertex;
slouken@1903
   158
slouken@1895
   159
static void
slouken@1900
   160
D3D_SetError(const char *prefix, HRESULT result)
slouken@1900
   161
{
slouken@1900
   162
    const char *error;
slouken@1900
   163
slouken@1900
   164
    switch (result) {
slouken@1900
   165
    case D3DERR_WRONGTEXTUREFORMAT:
slouken@1900
   166
        error = "WRONGTEXTUREFORMAT";
slouken@1900
   167
        break;
slouken@1900
   168
    case D3DERR_UNSUPPORTEDCOLOROPERATION:
slouken@1900
   169
        error = "UNSUPPORTEDCOLOROPERATION";
slouken@1900
   170
        break;
slouken@1900
   171
    case D3DERR_UNSUPPORTEDCOLORARG:
slouken@1900
   172
        error = "UNSUPPORTEDCOLORARG";
slouken@1900
   173
        break;
slouken@1900
   174
    case D3DERR_UNSUPPORTEDALPHAOPERATION:
slouken@1900
   175
        error = "UNSUPPORTEDALPHAOPERATION";
slouken@1900
   176
        break;
slouken@1900
   177
    case D3DERR_UNSUPPORTEDALPHAARG:
slouken@1900
   178
        error = "UNSUPPORTEDALPHAARG";
slouken@1900
   179
        break;
slouken@1900
   180
    case D3DERR_TOOMANYOPERATIONS:
slouken@1900
   181
        error = "TOOMANYOPERATIONS";
slouken@1900
   182
        break;
slouken@1900
   183
    case D3DERR_CONFLICTINGTEXTUREFILTER:
slouken@1900
   184
        error = "CONFLICTINGTEXTUREFILTER";
slouken@1900
   185
        break;
slouken@1900
   186
    case D3DERR_UNSUPPORTEDFACTORVALUE:
slouken@1900
   187
        error = "UNSUPPORTEDFACTORVALUE";
slouken@1900
   188
        break;
slouken@1900
   189
    case D3DERR_CONFLICTINGRENDERSTATE:
slouken@1900
   190
        error = "CONFLICTINGRENDERSTATE";
slouken@1900
   191
        break;
slouken@1900
   192
    case D3DERR_UNSUPPORTEDTEXTUREFILTER:
slouken@1900
   193
        error = "UNSUPPORTEDTEXTUREFILTER";
slouken@1900
   194
        break;
slouken@1900
   195
    case D3DERR_CONFLICTINGTEXTUREPALETTE:
slouken@1900
   196
        error = "CONFLICTINGTEXTUREPALETTE";
slouken@1900
   197
        break;
slouken@1900
   198
    case D3DERR_DRIVERINTERNALERROR:
slouken@1900
   199
        error = "DRIVERINTERNALERROR";
slouken@1900
   200
        break;
slouken@1900
   201
    case D3DERR_NOTFOUND:
slouken@1900
   202
        error = "NOTFOUND";
slouken@1900
   203
        break;
slouken@1900
   204
    case D3DERR_MOREDATA:
slouken@1900
   205
        error = "MOREDATA";
slouken@1900
   206
        break;
slouken@1900
   207
    case D3DERR_DEVICELOST:
slouken@1900
   208
        error = "DEVICELOST";
slouken@1900
   209
        break;
slouken@1900
   210
    case D3DERR_DEVICENOTRESET:
slouken@1900
   211
        error = "DEVICENOTRESET";
slouken@1900
   212
        break;
slouken@1900
   213
    case D3DERR_NOTAVAILABLE:
slouken@1900
   214
        error = "NOTAVAILABLE";
slouken@1900
   215
        break;
slouken@1900
   216
    case D3DERR_OUTOFVIDEOMEMORY:
slouken@1900
   217
        error = "OUTOFVIDEOMEMORY";
slouken@1900
   218
        break;
slouken@1900
   219
    case D3DERR_INVALIDDEVICE:
slouken@1900
   220
        error = "INVALIDDEVICE";
slouken@1900
   221
        break;
slouken@1900
   222
    case D3DERR_INVALIDCALL:
slouken@1900
   223
        error = "INVALIDCALL";
slouken@1900
   224
        break;
slouken@1900
   225
    case D3DERR_DRIVERINVALIDCALL:
slouken@1900
   226
        error = "DRIVERINVALIDCALL";
slouken@1900
   227
        break;
slouken@1900
   228
    case D3DERR_WASSTILLDRAWING:
slouken@1900
   229
        error = "WASSTILLDRAWING";
slouken@1900
   230
        break;
slouken@1900
   231
    default:
slouken@1900
   232
        error = "UNKNOWN";
slouken@1900
   233
        break;
slouken@1900
   234
    }
slouken@1900
   235
    SDL_SetError("%s: %s", prefix, error);
slouken@1900
   236
}
slouken@1900
   237
slouken@1903
   238
static D3DFORMAT
slouken@1903
   239
PixelFormatToD3DFMT(Uint32 format)
slouken@1895
   240
{
slouken@1903
   241
    switch (format) {
slouken@1965
   242
    case SDL_PIXELFORMAT_RGB565:
slouken@1903
   243
        return D3DFMT_R5G6B5;
slouken@1965
   244
    case SDL_PIXELFORMAT_RGB888:
slouken@1903
   245
        return D3DFMT_X8R8G8B8;
slouken@1965
   246
    case SDL_PIXELFORMAT_ARGB8888:
slouken@1903
   247
        return D3DFMT_A8R8G8B8;
slouken@1903
   248
    default:
slouken@1903
   249
        return D3DFMT_UNKNOWN;
slouken@1903
   250
    }
slouken@1895
   251
}
slouken@1895
   252
slouken@5156
   253
static Uint32
slouken@5156
   254
D3DFMTToPixelFormat(D3DFORMAT format)
slouken@2973
   255
{
slouken@5156
   256
    switch (format) {
slouken@5156
   257
    case D3DFMT_R5G6B5:
slouken@5156
   258
        return SDL_PIXELFORMAT_RGB565;
slouken@5156
   259
    case D3DFMT_X8R8G8B8:
slouken@5156
   260
        return SDL_PIXELFORMAT_RGB888;
slouken@5156
   261
    case D3DFMT_A8R8G8B8:
slouken@5156
   262
        return SDL_PIXELFORMAT_ARGB8888;
slouken@5156
   263
    default:
slouken@5156
   264
        return SDL_PIXELFORMAT_UNKNOWN;
slouken@2973
   265
    }
slouken@1895
   266
}
slouken@1895
   267
slouken@5297
   268
static int
slouken@5297
   269
D3D_Reset(SDL_Renderer * renderer)
slouken@5297
   270
{
slouken@5297
   271
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@5297
   272
    HRESULT result;
slouken@5297
   273
slouken@5297
   274
    result = IDirect3DDevice9_Reset(data->device, &data->pparams);
slouken@5297
   275
    if (FAILED(result)) {
slouken@5297
   276
        if (result == D3DERR_DEVICELOST) {
slouken@5297
   277
            /* Don't worry about it, we'll reset later... */
slouken@5297
   278
            return 0;
slouken@5297
   279
        } else {
slouken@5297
   280
            D3D_SetError("Reset()", result);
slouken@5297
   281
            return -1;
slouken@5297
   282
        }
slouken@5297
   283
    }
slouken@5297
   284
    IDirect3DDevice9_SetVertexShader(data->device, NULL);
slouken@5297
   285
    IDirect3DDevice9_SetFVF(data->device,
slouken@5297
   286
                            D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1);
slouken@5297
   287
    IDirect3DDevice9_SetRenderState(data->device, D3DRS_CULLMODE,
slouken@5297
   288
                                    D3DCULL_NONE);
slouken@5297
   289
    IDirect3DDevice9_SetRenderState(data->device, D3DRS_LIGHTING, FALSE);
slouken@5297
   290
    return 0;
slouken@5297
   291
}
slouken@5297
   292
slouken@5297
   293
static int
slouken@5297
   294
D3D_ActivateRenderer(SDL_Renderer * renderer)
slouken@5297
   295
{
slouken@5297
   296
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@5297
   297
    HRESULT result;
slouken@5297
   298
slouken@5297
   299
    if (data->updateSize) {
slouken@5297
   300
        SDL_Window *window = renderer->window;
slouken@5297
   301
        int w, h;
slouken@5297
   302
slouken@5297
   303
        SDL_GetWindowSize(window, &w, &h);
slouken@5297
   304
        data->pparams.BackBufferWidth = w;
slouken@5297
   305
        data->pparams.BackBufferHeight = h;
slouken@5297
   306
        if (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) {
slouken@5297
   307
            data->pparams.BackBufferFormat =
slouken@5297
   308
                PixelFormatToD3DFMT(SDL_GetWindowPixelFormat(window));
slouken@5297
   309
        } else {
slouken@5297
   310
            data->pparams.BackBufferFormat = D3DFMT_UNKNOWN;
slouken@5297
   311
        }
slouken@5297
   312
        if (D3D_Reset(renderer) < 0) {
slouken@5297
   313
            return -1;
slouken@5297
   314
        }
slouken@5297
   315
        D3D_UpdateViewport(renderer);
slouken@5297
   316
slouken@5297
   317
        data->updateSize = SDL_FALSE;
slouken@5297
   318
    }
slouken@5297
   319
    if (data->beginScene) {
slouken@5297
   320
        result = IDirect3DDevice9_BeginScene(data->device);
slouken@5297
   321
        if (result == D3DERR_DEVICELOST) {
slouken@5297
   322
            if (D3D_Reset(renderer) < 0) {
slouken@5297
   323
                return -1;
slouken@5297
   324
            }
slouken@5297
   325
            result = IDirect3DDevice9_BeginScene(data->device);
slouken@5297
   326
        }
slouken@5297
   327
        if (FAILED(result)) {
slouken@5297
   328
            D3D_SetError("BeginScene()", result);
slouken@5297
   329
            return -1;
slouken@5297
   330
        }
slouken@5297
   331
        data->beginScene = SDL_FALSE;
slouken@5297
   332
    }
slouken@5297
   333
    return 0;
slouken@5297
   334
}
slouken@5297
   335
slouken@1895
   336
SDL_Renderer *
slouken@1913
   337
D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
slouken@1895
   338
{
slouken@1895
   339
    SDL_Renderer *renderer;
slouken@1913
   340
    D3D_RenderData *data;
slouken@5154
   341
    SDL_SysWMinfo windowinfo;
slouken@1900
   342
    HRESULT result;
slouken@1900
   343
    D3DPRESENT_PARAMETERS pparams;
slouken@1907
   344
    IDirect3DSwapChain9 *chain;
slouken@1925
   345
    D3DCAPS9 caps;
slouken@5156
   346
    Uint32 window_flags;
slouken@5156
   347
    int w, h;
slouken@5156
   348
    SDL_DisplayMode fullscreen_mode;
slouken@5297
   349
    D3DMATRIX matrix;
slouken@1895
   350
slouken@1920
   351
    renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
slouken@1895
   352
    if (!renderer) {
slouken@1895
   353
        SDL_OutOfMemory();
slouken@1895
   354
        return NULL;
slouken@1895
   355
    }
slouken@1895
   356
slouken@1920
   357
    data = (D3D_RenderData *) SDL_calloc(1, sizeof(*data));
slouken@1895
   358
    if (!data) {
slouken@5154
   359
        SDL_free(renderer);
slouken@1895
   360
        SDL_OutOfMemory();
slouken@1895
   361
        return NULL;
slouken@1895
   362
    }
slouken@1895
   363
slouken@5154
   364
    data->d3dDLL = SDL_LoadObject("D3D9.DLL");
slouken@5154
   365
    if (data->d3dDLL) {
slouken@5154
   366
        IDirect3D9 *(WINAPI * D3DCreate) (UINT SDKVersion);
slouken@4569
   367
slouken@5154
   368
        D3DCreate =
slouken@5154
   369
            (IDirect3D9 * (WINAPI *) (UINT)) SDL_LoadFunction(data->d3dDLL,
slouken@5154
   370
                                                            "Direct3DCreate9");
slouken@5154
   371
        if (D3DCreate) {
slouken@5154
   372
            data->d3d = D3DCreate(D3D_SDK_VERSION);
slouken@5154
   373
        }
slouken@5154
   374
        if (!data->d3d) {
slouken@5154
   375
            SDL_UnloadObject(data->d3dDLL);
slouken@5154
   376
            data->d3dDLL = NULL;
slouken@5154
   377
        }
slouken@5154
   378
    }
slouken@5154
   379
    if (!data->d3d) {
slouken@5154
   380
        SDL_free(renderer);
slouken@5154
   381
        SDL_free(data);
slouken@5154
   382
        SDL_SetError("Unable to create Direct3D interface");
slouken@5154
   383
        return NULL;
slouken@5154
   384
    }
slouken@5154
   385
slouken@5297
   386
    renderer->WindowEvent = D3D_WindowEvent;
slouken@1913
   387
    renderer->CreateTexture = D3D_CreateTexture;
slouken@1913
   388
    renderer->UpdateTexture = D3D_UpdateTexture;
slouken@1913
   389
    renderer->LockTexture = D3D_LockTexture;
slouken@1913
   390
    renderer->UnlockTexture = D3D_UnlockTexture;
slouken@6246
   391
    renderer->SetTargetTexture = D3D_SetTargetTexture;
slouken@5297
   392
    renderer->UpdateViewport = D3D_UpdateViewport;
slouken@5297
   393
    renderer->RenderClear = D3D_RenderClear;
slouken@3599
   394
    renderer->RenderDrawPoints = D3D_RenderDrawPoints;
slouken@3599
   395
    renderer->RenderDrawLines = D3D_RenderDrawLines;
slouken@3675
   396
    renderer->RenderFillRects = D3D_RenderFillRects;
slouken@1913
   397
    renderer->RenderCopy = D3D_RenderCopy;
slouken@3427
   398
    renderer->RenderReadPixels = D3D_RenderReadPixels;
slouken@1913
   399
    renderer->RenderPresent = D3D_RenderPresent;
slouken@1913
   400
    renderer->DestroyTexture = D3D_DestroyTexture;
slouken@1913
   401
    renderer->DestroyRenderer = D3D_DestroyRenderer;
slouken@1913
   402
    renderer->info = D3D_RenderDriver.info;
slouken@1895
   403
    renderer->driverdata = data;
slouken@1895
   404
slouken@6246
   405
    renderer->info.flags = SDL_RENDERER_ACCELERATED;
slouken@1895
   406
slouken@5154
   407
    SDL_VERSION(&windowinfo.version);
slouken@5154
   408
    SDL_GetWindowWMInfo(window, &windowinfo);
slouken@5154
   409
slouken@5156
   410
    window_flags = SDL_GetWindowFlags(window);
slouken@5156
   411
    SDL_GetWindowSize(window, &w, &h);
slouken@5156
   412
    SDL_GetWindowDisplayMode(window, &fullscreen_mode);
slouken@5156
   413
slouken@1900
   414
    SDL_zero(pparams);
slouken@5154
   415
    pparams.hDeviceWindow = windowinfo.info.win.window;
slouken@5156
   416
    pparams.BackBufferWidth = w;
slouken@5156
   417
    pparams.BackBufferHeight = h;
slouken@5156
   418
    if (window_flags & SDL_WINDOW_FULLSCREEN) {
slouken@1903
   419
        pparams.BackBufferFormat =
slouken@5156
   420
            PixelFormatToD3DFMT(fullscreen_mode.format);
slouken@1903
   421
    } else {
slouken@1903
   422
        pparams.BackBufferFormat = D3DFMT_UNKNOWN;
slouken@1903
   423
    }
slouken@5142
   424
    pparams.BackBufferCount = 1;
slouken@5142
   425
    pparams.SwapEffect = D3DSWAPEFFECT_DISCARD;
slouken@5142
   426
slouken@5156
   427
    if (window_flags & SDL_WINDOW_FULLSCREEN) {
slouken@1900
   428
        pparams.Windowed = FALSE;
slouken@1903
   429
        pparams.FullScreen_RefreshRateInHz =
slouken@5156
   430
            fullscreen_mode.refresh_rate;
slouken@1900
   431
    } else {
slouken@1900
   432
        pparams.Windowed = TRUE;
slouken@1903
   433
        pparams.FullScreen_RefreshRateInHz = 0;
slouken@1900
   434
    }
slouken@1965
   435
    if (flags & SDL_RENDERER_PRESENTVSYNC) {
slouken@1907
   436
        pparams.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
slouken@1907
   437
    } else {
slouken@1907
   438
        pparams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
slouken@1907
   439
    }
slouken@1900
   440
slouken@5154
   441
    /* FIXME: Which adapter? */
slouken@5154
   442
    data->adapter = D3DADAPTER_DEFAULT;
slouken@5154
   443
    IDirect3D9_GetDeviceCaps(data->d3d, data->adapter, D3DDEVTYPE_HAL, &caps);
slouken@3197
   444
slouken@5154
   445
    result = IDirect3D9_CreateDevice(data->d3d, data->adapter,
slouken@1900
   446
                                     D3DDEVTYPE_HAL,
slouken@5154
   447
                                     pparams.hDeviceWindow,
slouken@6115
   448
                                     D3DCREATE_FPU_PRESERVE | ((caps.
slouken@3197
   449
                                      DevCaps &
slouken@3197
   450
                                      D3DDEVCAPS_HWTRANSFORMANDLIGHT) ?
slouken@3197
   451
                                     D3DCREATE_HARDWARE_VERTEXPROCESSING :
slouken@6115
   452
                                     D3DCREATE_SOFTWARE_VERTEXPROCESSING),
slouken@1900
   453
                                     &pparams, &data->device);
slouken@1900
   454
    if (FAILED(result)) {
slouken@1913
   455
        D3D_DestroyRenderer(renderer);
slouken@1900
   456
        D3D_SetError("CreateDevice()", result);
slouken@1900
   457
        return NULL;
slouken@1900
   458
    }
slouken@1900
   459
    data->beginScene = SDL_TRUE;
slouken@5484
   460
    data->scaleMode = D3DTEXF_FORCE_DWORD;
slouken@1900
   461
slouken@1907
   462
    /* Get presentation parameters to fill info */
slouken@1907
   463
    result = IDirect3DDevice9_GetSwapChain(data->device, 0, &chain);
slouken@1907
   464
    if (FAILED(result)) {
slouken@1913
   465
        D3D_DestroyRenderer(renderer);
slouken@1907
   466
        D3D_SetError("GetSwapChain()", result);
slouken@1907
   467
        return NULL;
slouken@1907
   468
    }
slouken@1907
   469
    result = IDirect3DSwapChain9_GetPresentParameters(chain, &pparams);
slouken@1907
   470
    if (FAILED(result)) {
slouken@1907
   471
        IDirect3DSwapChain9_Release(chain);
slouken@1913
   472
        D3D_DestroyRenderer(renderer);
slouken@1907
   473
        D3D_SetError("GetPresentParameters()", result);
slouken@1907
   474
        return NULL;
slouken@1907
   475
    }
slouken@1907
   476
    IDirect3DSwapChain9_Release(chain);
slouken@1907
   477
    if (pparams.PresentationInterval == D3DPRESENT_INTERVAL_ONE) {
slouken@1965
   478
        renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
slouken@1907
   479
    }
slouken@1975
   480
    data->pparams = pparams;
slouken@1907
   481
slouken@1925
   482
    IDirect3DDevice9_GetDeviceCaps(data->device, &caps);
slouken@1925
   483
    renderer->info.max_texture_width = caps.MaxTextureWidth;
slouken@1925
   484
    renderer->info.max_texture_height = caps.MaxTextureHeight;
slouken@6246
   485
    if (caps.NumSimultaneousRTs >= 2) {
slouken@6246
   486
        renderer->info.flags |= SDL_RENDERER_TARGETTEXTURE;
slouken@6246
   487
    }
slouken@1918
   488
slouken@1903
   489
    /* Set up parameters for rendering */
slouken@1904
   490
    IDirect3DDevice9_SetVertexShader(data->device, NULL);
slouken@1987
   491
    IDirect3DDevice9_SetFVF(data->device,
slouken@5297
   492
                            D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1);
slouken@1988
   493
    IDirect3DDevice9_SetRenderState(data->device, D3DRS_ZENABLE, D3DZB_FALSE);
slouken@1903
   494
    IDirect3DDevice9_SetRenderState(data->device, D3DRS_CULLMODE,
slouken@1903
   495
                                    D3DCULL_NONE);
slouken@1904
   496
    IDirect3DDevice9_SetRenderState(data->device, D3DRS_LIGHTING, FALSE);
slouken@1988
   497
    /* Enable color modulation by diffuse color */
slouken@1988
   498
    IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLOROP,
slouken@1988
   499
                                          D3DTOP_MODULATE);
slouken@1988
   500
    IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLORARG1,
slouken@1988
   501
                                          D3DTA_TEXTURE);
slouken@1988
   502
    IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLORARG2,
slouken@1988
   503
                                          D3DTA_DIFFUSE);
slouken@1988
   504
    /* Enable alpha modulation by diffuse alpha */
slouken@1988
   505
    IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAOP,
slouken@1988
   506
                                          D3DTOP_MODULATE);
slouken@1988
   507
    IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAARG1,
slouken@1988
   508
                                          D3DTA_TEXTURE);
slouken@1988
   509
    IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAARG2,
slouken@1988
   510
                                          D3DTA_DIFFUSE);
slouken@1991
   511
    /* Disable second texture stage, since we're done */
slouken@1991
   512
    IDirect3DDevice9_SetTextureStageState(data->device, 1, D3DTSS_COLOROP,
slouken@1991
   513
                                          D3DTOP_DISABLE);
slouken@1991
   514
    IDirect3DDevice9_SetTextureStageState(data->device, 1, D3DTSS_ALPHAOP,
slouken@1991
   515
                                          D3DTOP_DISABLE);
slouken@1903
   516
slouken@6232
   517
    /* Store the default render target */
slouken@6232
   518
    IDirect3DDevice9_GetRenderTarget(data->device, 0, &data->defaultRenderTarget );
slouken@6232
   519
    data->currentRenderTarget = NULL;
slouken@6232
   520
slouken@5297
   521
    /* Set an identity world and view matrix */
slouken@5297
   522
    matrix.m[0][0] = 1.0f;
slouken@5297
   523
    matrix.m[0][1] = 0.0f;
slouken@5297
   524
    matrix.m[0][2] = 0.0f;
slouken@5297
   525
    matrix.m[0][3] = 0.0f;
slouken@5297
   526
    matrix.m[1][0] = 0.0f;
slouken@5297
   527
    matrix.m[1][1] = 1.0f;
slouken@5297
   528
    matrix.m[1][2] = 0.0f;
slouken@5297
   529
    matrix.m[1][3] = 0.0f;
slouken@5297
   530
    matrix.m[2][0] = 0.0f;
slouken@5297
   531
    matrix.m[2][1] = 0.0f;
slouken@5297
   532
    matrix.m[2][2] = 1.0f;
slouken@5297
   533
    matrix.m[2][3] = 0.0f;
slouken@5297
   534
    matrix.m[3][0] = 0.0f;
slouken@5297
   535
    matrix.m[3][1] = 0.0f;
slouken@5297
   536
    matrix.m[3][2] = 0.0f;
slouken@5297
   537
    matrix.m[3][3] = 1.0f;
slouken@5297
   538
    IDirect3DDevice9_SetTransform(data->device, D3DTS_WORLD, &matrix);
slouken@5297
   539
    IDirect3DDevice9_SetTransform(data->device, D3DTS_VIEW, &matrix);
slouken@5297
   540
slouken@1895
   541
    return renderer;
slouken@1895
   542
}
slouken@1895
   543
slouken@5297
   544
static void
slouken@5297
   545
D3D_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
slouken@1975
   546
{
slouken@1975
   547
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@1975
   548
slouken@5297
   549
    if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED) {
slouken@5297
   550
        data->updateSize = SDL_TRUE;
slouken@1975
   551
    }
slouken@1975
   552
}
slouken@1975
   553
slouken@5484
   554
static D3DTEXTUREFILTERTYPE
slouken@5484
   555
GetScaleQuality(void)
slouken@5484
   556
{
slouken@5484
   557
    const char *hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY);
slouken@5484
   558
slouken@5484
   559
    if (!hint || *hint == '0' || SDL_strcasecmp(hint, "nearest") == 0) {
slouken@5484
   560
        return D3DTEXF_POINT;
slouken@5484
   561
    } else if (*hint == '1' || SDL_strcasecmp(hint, "linear") == 0) {
slouken@5484
   562
        return D3DTEXF_LINEAR;
slouken@5484
   563
    } else {
slouken@5484
   564
        return D3DTEXF_ANISOTROPIC;
slouken@5484
   565
    }
slouken@5484
   566
}
slouken@5484
   567
slouken@1975
   568
static int
slouken@1913
   569
D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1895
   570
{
slouken@1913
   571
    D3D_RenderData *renderdata = (D3D_RenderData *) renderer->driverdata;
slouken@3685
   572
    SDL_Window *window = renderer->window;
slouken@5154
   573
    D3DFORMAT display_format = renderdata->pparams.BackBufferFormat;
slouken@1913
   574
    D3D_TextureData *data;
slouken@5173
   575
    D3DPOOL pool;
slouken@5173
   576
    DWORD usage;
slouken@1903
   577
    HRESULT result;
slouken@1895
   578
slouken@1920
   579
    data = (D3D_TextureData *) SDL_calloc(1, sizeof(*data));
slouken@1895
   580
    if (!data) {
slouken@1895
   581
        SDL_OutOfMemory();
slouken@1895
   582
        return -1;
slouken@1895
   583
    }
slouken@5484
   584
    data->scaleMode = GetScaleQuality();
slouken@1895
   585
slouken@1895
   586
    texture->driverdata = data;
slouken@1895
   587
slouken@5173
   588
#ifdef USE_DYNAMIC_TEXTURE
slouken@5173
   589
    if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
slouken@5173
   590
        pool = D3DPOOL_DEFAULT;
slouken@5173
   591
        usage = D3DUSAGE_DYNAMIC;
slouken@5173
   592
    } else
slouken@5173
   593
#endif
slouken@6232
   594
    if (texture->access == SDL_TEXTUREACCESS_TARGET) {
slouken@6246
   595
        /* D3DPOOL_MANAGED does not work with D3DUSAGE_RENDERTARGET */
slouken@6246
   596
        pool = D3DPOOL_DEFAULT;
slouken@6232
   597
        usage = D3DUSAGE_RENDERTARGET;
slouken@6246
   598
    } else {
slouken@5173
   599
        pool = D3DPOOL_MANAGED;
slouken@5173
   600
        usage = 0;
slouken@5173
   601
    }
slouken@2973
   602
slouken@1903
   603
    result =
slouken@1903
   604
        IDirect3DDevice9_CreateTexture(renderdata->device, texture->w,
slouken@5173
   605
                                       texture->h, 1, usage,
slouken@5173
   606
                                       PixelFormatToD3DFMT(texture->format),
slouken@5173
   607
                                       pool, &data->texture, NULL);
slouken@1903
   608
    if (FAILED(result)) {
slouken@1903
   609
        D3D_SetError("CreateTexture()", result);
slouken@1903
   610
        return -1;
slouken@1903
   611
    }
slouken@1903
   612
slouken@1895
   613
    return 0;
slouken@1895
   614
}
slouken@1895
   615
slouken@1895
   616
static int
slouken@1913
   617
D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1913
   618
                  const SDL_Rect * rect, const void *pixels, int pitch)
slouken@1895
   619
{
slouken@1913
   620
    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
slouken@1913
   621
    D3D_RenderData *renderdata = (D3D_RenderData *) renderer->driverdata;
slouken@5156
   622
    RECT d3drect;
slouken@5156
   623
    D3DLOCKED_RECT locked;
slouken@5156
   624
    const Uint8 *src;
slouken@5156
   625
    Uint8 *dst;
slouken@5156
   626
    int row, length;
slouken@5156
   627
    HRESULT result;
slouken@2973
   628
slouken@5173
   629
#ifdef USE_DYNAMIC_TEXTURE
slouken@5173
   630
    if (texture->access == SDL_TEXTUREACCESS_STREAMING &&
slouken@5173
   631
        rect->x == 0 && rect->y == 0 &&
slouken@5173
   632
        rect->w == texture->w && rect->h == texture->h) {
slouken@5194
   633
        result = IDirect3DTexture9_LockRect(data->texture, 0, &locked, NULL, D3DLOCK_DISCARD);
slouken@5173
   634
    } else
slouken@5173
   635
#endif
slouken@5173
   636
    {
slouken@5173
   637
        d3drect.left = rect->x;
slouken@5173
   638
        d3drect.right = rect->x + rect->w;
slouken@5173
   639
        d3drect.top = rect->y;
slouken@5173
   640
        d3drect.bottom = rect->y + rect->h;
slouken@5194
   641
        result = IDirect3DTexture9_LockRect(data->texture, 0, &locked, &d3drect, 0);
slouken@5156
   642
    }
slouken@2973
   643
slouken@5156
   644
    if (FAILED(result)) {
slouken@5156
   645
        D3D_SetError("LockRect()", result);
slouken@5156
   646
        return -1;
slouken@5156
   647
    }
slouken@2973
   648
slouken@5156
   649
    src = pixels;
slouken@5156
   650
    dst = locked.pBits;
slouken@5156
   651
    length = rect->w * SDL_BYTESPERPIXEL(texture->format);
slouken@5173
   652
    if (length == pitch && length == locked.Pitch) {
slouken@5173
   653
        SDL_memcpy(dst, src, length*rect->h);
slouken@5173
   654
    } else {
slouken@5173
   655
        for (row = 0; row < rect->h; ++row) {
slouken@5173
   656
            SDL_memcpy(dst, src, length);
slouken@5173
   657
            src += pitch;
slouken@5173
   658
            dst += locked.Pitch;
slouken@5173
   659
        }
slouken@5156
   660
    }
slouken@5156
   661
    IDirect3DTexture9_UnlockRect(data->texture, 0);
slouken@2973
   662
slouken@5156
   663
    return 0;
slouken@1895
   664
}
slouken@1895
   665
slouken@1895
   666
static int
slouken@1913
   667
D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@5156
   668
                const SDL_Rect * rect, void **pixels, int *pitch)
slouken@1895
   669
{
slouken@1913
   670
    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
slouken@5156
   671
    RECT d3drect;
slouken@5156
   672
    D3DLOCKED_RECT locked;
slouken@5156
   673
    HRESULT result;
slouken@1895
   674
slouken@5156
   675
    d3drect.left = rect->x;
slouken@5156
   676
    d3drect.right = rect->x + rect->w;
slouken@5156
   677
    d3drect.top = rect->y;
slouken@5156
   678
    d3drect.bottom = rect->y + rect->h;
slouken@1903
   679
slouken@5156
   680
    result = IDirect3DTexture9_LockRect(data->texture, 0, &locked, &d3drect, 0);
slouken@5156
   681
    if (FAILED(result)) {
slouken@5156
   682
        D3D_SetError("LockRect()", result);
slouken@5156
   683
        return -1;
slouken@1903
   684
    }
slouken@5156
   685
    *pixels = locked.pBits;
slouken@5156
   686
    *pitch = locked.Pitch;
slouken@5156
   687
    return 0;
slouken@1895
   688
}
slouken@1895
   689
slouken@1895
   690
static void
slouken@1913
   691
D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1895
   692
{
slouken@1913
   693
    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
slouken@1895
   694
slouken@5156
   695
    IDirect3DTexture9_UnlockRect(data->texture, 0);
slouken@1895
   696
}
slouken@1895
   697
slouken@5297
   698
static int
slouken@5297
   699
D3D_UpdateViewport(SDL_Renderer * renderer)
slouken@5224
   700
{
slouken@5224
   701
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@5297
   702
    D3DVIEWPORT9 viewport;
slouken@5297
   703
    D3DMATRIX matrix;
slouken@5224
   704
slouken@5297
   705
    /* Set the viewport */
slouken@5297
   706
    viewport.X = renderer->viewport.x;
slouken@5297
   707
    viewport.Y = renderer->viewport.y;
slouken@5297
   708
    viewport.Width = renderer->viewport.w;
slouken@5297
   709
    viewport.Height = renderer->viewport.h;
slouken@5297
   710
    viewport.MinZ = 0.0f;
slouken@5297
   711
    viewport.MaxZ = 1.0f;
slouken@5297
   712
    IDirect3DDevice9_SetViewport(data->device, &viewport);
slouken@5224
   713
slouken@5297
   714
    /* Set an orthographic projection matrix */
slouken@5297
   715
    matrix.m[0][0] = 2.0f / renderer->viewport.w;
slouken@5297
   716
    matrix.m[0][1] = 0.0f;
slouken@5297
   717
    matrix.m[0][2] = 0.0f;
slouken@5297
   718
    matrix.m[0][3] = 0.0f;
slouken@5297
   719
    matrix.m[1][0] = 0.0f;
slouken@5297
   720
    matrix.m[1][1] = -2.0f / renderer->viewport.h;
slouken@5297
   721
    matrix.m[1][2] = 0.0f;
slouken@5297
   722
    matrix.m[1][3] = 0.0f;
slouken@5297
   723
    matrix.m[2][0] = 0.0f;
slouken@5297
   724
    matrix.m[2][1] = 0.0f;
slouken@5297
   725
    matrix.m[2][2] = 1.0f;
slouken@5297
   726
    matrix.m[2][3] = 0.0f;
slouken@5297
   727
    matrix.m[3][0] = -1.0f;
slouken@5297
   728
    matrix.m[3][1] = 1.0f;
slouken@5297
   729
    matrix.m[3][2] = 0.0f;
slouken@5297
   730
    matrix.m[3][3] = 1.0f;
slouken@5297
   731
    IDirect3DDevice9_SetTransform(data->device, D3DTS_PROJECTION, &matrix);
slouken@5297
   732
slouken@5297
   733
    return 0;
slouken@5297
   734
}
slouken@5297
   735
slouken@5297
   736
static int
slouken@6246
   737
D3D_SetTargetTexture(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@6246
   738
{
slouken@6246
   739
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@6246
   740
    D3D_TextureData *texturedata;
slouken@6246
   741
    HRESULT result;
slouken@6246
   742
slouken@6246
   743
    D3D_ActivateRenderer(renderer);
slouken@6246
   744
slouken@6246
   745
    /* Release the previous render target if it wasn't the default one */
slouken@6246
   746
    if (data->currentRenderTarget != NULL) {
slouken@6246
   747
        IDirect3DSurface9_Release(data->currentRenderTarget);
slouken@6246
   748
        data->currentRenderTarget = NULL;
slouken@6246
   749
    }
slouken@6246
   750
slouken@6246
   751
    if (texture == NULL) {
slouken@6246
   752
        IDirect3DDevice9_SetRenderTarget(data->device, 0, data->defaultRenderTarget);
slouken@6246
   753
        return 0;
slouken@6246
   754
    }
slouken@6246
   755
slouken@6246
   756
    texturedata = (D3D_TextureData *) texture->driverdata;
slouken@6246
   757
    result = IDirect3DTexture9_GetSurfaceLevel(texturedata->texture, 0, &data->currentRenderTarget);
slouken@6246
   758
    if(FAILED(result)) {
slouken@6246
   759
        D3D_SetError("GetSurfaceLevel()", result);
slouken@6246
   760
        return -1;
slouken@6246
   761
    }
slouken@6246
   762
    result = IDirect3DDevice9_SetRenderTarget(data->device, 0, data->currentRenderTarget);
slouken@6246
   763
    if(FAILED(result)) {
slouken@6246
   764
        D3D_SetError("SetRenderTarget()", result);
slouken@6246
   765
        return -1;
slouken@6246
   766
    }
slouken@6246
   767
slouken@6246
   768
    return 0;
slouken@6246
   769
}
slouken@6246
   770
slouken@6246
   771
static int
slouken@5297
   772
D3D_RenderClear(SDL_Renderer * renderer)
slouken@5297
   773
{
slouken@5297
   774
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@5297
   775
    DWORD color;
slouken@5297
   776
    HRESULT result;
slouken@5297
   777
slouken@5297
   778
    if (D3D_ActivateRenderer(renderer) < 0) {
slouken@5297
   779
        return -1;
slouken@5224
   780
    }
slouken@5297
   781
slouken@5297
   782
    color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
slouken@5297
   783
slouken@5299
   784
    /* Don't reset the viewport if we don't have to! */
slouken@5299
   785
    if (!renderer->viewport.x && !renderer->viewport.y &&
slouken@5299
   786
        renderer->viewport.w == data->pparams.BackBufferWidth &&
slouken@5299
   787
        renderer->viewport.h == data->pparams.BackBufferHeight) {
slouken@5299
   788
        result = IDirect3DDevice9_Clear(data->device, 0, NULL, D3DCLEAR_TARGET, color, 0.0f, 0);
slouken@5299
   789
    } else {
slouken@5299
   790
        D3DVIEWPORT9 viewport;
slouken@5297
   791
slouken@5299
   792
        /* Clear is defined to clear the entire render target */
slouken@5299
   793
        viewport.X = 0;
slouken@5299
   794
        viewport.Y = 0;
slouken@5299
   795
        viewport.Width = data->pparams.BackBufferWidth;
slouken@5299
   796
        viewport.Height = data->pparams.BackBufferHeight;
slouken@5299
   797
        viewport.MinZ = 0.0f;
slouken@5299
   798
        viewport.MaxZ = 1.0f;
slouken@5299
   799
        IDirect3DDevice9_SetViewport(data->device, &viewport);
slouken@5299
   800
slouken@5299
   801
        result = IDirect3DDevice9_Clear(data->device, 0, NULL, D3DCLEAR_TARGET, color, 0.0f, 0);
slouken@5299
   802
slouken@5299
   803
        /* Reset the viewport */
slouken@5299
   804
        viewport.X = renderer->viewport.x;
slouken@5299
   805
        viewport.Y = renderer->viewport.y;
slouken@5299
   806
        viewport.Width = renderer->viewport.w;
slouken@5299
   807
        viewport.Height = renderer->viewport.h;
slouken@5299
   808
        viewport.MinZ = 0.0f;
slouken@5299
   809
        viewport.MaxZ = 1.0f;
slouken@5299
   810
        IDirect3DDevice9_SetViewport(data->device, &viewport);
slouken@5299
   811
    }
slouken@5297
   812
slouken@5297
   813
    if (FAILED(result)) {
slouken@5297
   814
        D3D_SetError("Clear()", result);
slouken@5297
   815
        return -1;
slouken@5297
   816
    }
slouken@5297
   817
    return 0;
slouken@5224
   818
}
slouken@5224
   819
slouken@5224
   820
static void
slouken@2933
   821
D3D_SetBlendMode(D3D_RenderData * data, int blendMode)
slouken@2932
   822
{
slouken@2932
   823
    switch (blendMode) {
slouken@2932
   824
    case SDL_BLENDMODE_NONE:
slouken@2932
   825
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
slouken@2932
   826
                                        FALSE);
slouken@2932
   827
        break;
slouken@2932
   828
    case SDL_BLENDMODE_BLEND:
slouken@2932
   829
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
slouken@2932
   830
                                        TRUE);
slouken@2932
   831
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
slouken@2932
   832
                                        D3DBLEND_SRCALPHA);
slouken@2932
   833
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
slouken@2932
   834
                                        D3DBLEND_INVSRCALPHA);
slouken@2932
   835
        break;
slouken@2932
   836
    case SDL_BLENDMODE_ADD:
slouken@2932
   837
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
slouken@2932
   838
                                        TRUE);
slouken@2932
   839
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
slouken@2932
   840
                                        D3DBLEND_SRCALPHA);
slouken@2932
   841
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
slouken@2932
   842
                                        D3DBLEND_ONE);
slouken@2932
   843
        break;
slouken@5184
   844
    case SDL_BLENDMODE_MOD:
slouken@5184
   845
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
slouken@5184
   846
                                        TRUE);
slouken@5184
   847
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
slouken@5184
   848
                                        D3DBLEND_ZERO);
slouken@5184
   849
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
slouken@5184
   850
                                        D3DBLEND_SRCCOLOR);
slouken@5184
   851
        break;
slouken@2932
   852
    }
slouken@2932
   853
}
slouken@2932
   854
slouken@1895
   855
static int
slouken@3599
   856
D3D_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points,
slouken@3599
   857
                     int count)
slouken@1895
   858
{
slouken@1913
   859
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@2932
   860
    DWORD color;
slouken@3536
   861
    Vertex *vertices;
slouken@3536
   862
    int i;
slouken@1900
   863
    HRESULT result;
slouken@1895
   864
slouken@5297
   865
    if (D3D_ActivateRenderer(renderer) < 0) {
slouken@5297
   866
        return -1;
slouken@1900
   867
    }
slouken@1895
   868
slouken@2932
   869
    D3D_SetBlendMode(data, renderer->blendMode);
slouken@2932
   870
slouken@2933
   871
    result =
slouken@2933
   872
        IDirect3DDevice9_SetTexture(data->device, 0,
slouken@2933
   873
                                    (IDirect3DBaseTexture9 *) 0);
slouken@2932
   874
    if (FAILED(result)) {
slouken@2932
   875
        D3D_SetError("SetTexture()", result);
slouken@2932
   876
        return -1;
slouken@2932
   877
    }
slouken@3536
   878
slouken@3536
   879
    color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
slouken@3536
   880
slouken@3536
   881
    vertices = SDL_stack_alloc(Vertex, count);
slouken@3536
   882
    for (i = 0; i < count; ++i) {
slouken@3536
   883
        vertices[i].x = (float) points[i].x;
slouken@3536
   884
        vertices[i].y = (float) points[i].y;
slouken@3536
   885
        vertices[i].z = 0.0f;
slouken@3536
   886
        vertices[i].color = color;
slouken@3536
   887
        vertices[i].u = 0.0f;
slouken@3536
   888
        vertices[i].v = 0.0f;
slouken@3536
   889
    }
slouken@1903
   890
    result =
slouken@3536
   891
        IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_POINTLIST, count,
slouken@2932
   892
                                         vertices, sizeof(*vertices));
slouken@3536
   893
    SDL_stack_free(vertices);
slouken@1900
   894
    if (FAILED(result)) {
slouken@2932
   895
        D3D_SetError("DrawPrimitiveUP()", result);
slouken@2932
   896
        return -1;
slouken@2932
   897
    }
slouken@2932
   898
    return 0;
slouken@2932
   899
}
slouken@2932
   900
slouken@2932
   901
static int
slouken@3599
   902
D3D_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points,
slouken@3599
   903
                    int count)
slouken@2932
   904
{
slouken@2932
   905
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@2932
   906
    DWORD color;
slouken@3536
   907
    Vertex *vertices;
slouken@3536
   908
    int i;
slouken@2932
   909
    HRESULT result;
slouken@2932
   910
slouken@5297
   911
    if (D3D_ActivateRenderer(renderer) < 0) {
slouken@5297
   912
        return -1;
slouken@2932
   913
    }
slouken@2932
   914
slouken@2932
   915
    D3D_SetBlendMode(data, renderer->blendMode);
slouken@2932
   916
slouken@2933
   917
    result =
slouken@2933
   918
        IDirect3DDevice9_SetTexture(data->device, 0,
slouken@2933
   919
                                    (IDirect3DBaseTexture9 *) 0);
slouken@2932
   920
    if (FAILED(result)) {
slouken@2932
   921
        D3D_SetError("SetTexture()", result);
slouken@2932
   922
        return -1;
slouken@2932
   923
    }
slouken@3536
   924
slouken@3536
   925
    color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
slouken@3536
   926
slouken@3536
   927
    vertices = SDL_stack_alloc(Vertex, count);
slouken@3536
   928
    for (i = 0; i < count; ++i) {
slouken@3536
   929
        vertices[i].x = (float) points[i].x;
slouken@3536
   930
        vertices[i].y = (float) points[i].y;
slouken@3536
   931
        vertices[i].z = 0.0f;
slouken@3536
   932
        vertices[i].color = color;
slouken@3536
   933
        vertices[i].u = 0.0f;
slouken@3536
   934
        vertices[i].v = 0.0f;
slouken@3536
   935
    }
slouken@2932
   936
    result =
slouken@3551
   937
        IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_LINESTRIP, count-1,
slouken@2932
   938
                                         vertices, sizeof(*vertices));
slouken@3551
   939
slouken@3551
   940
    /* DirectX 9 has the same line rasterization semantics as GDI,
slouken@3551
   941
       so we need to close the endpoint of the line */
slouken@6076
   942
    if (count == 2 ||
slouken@6076
   943
        points[0].x != points[count-1].x || points[0].y != points[count-1].y) {
slouken@3551
   944
        vertices[0].x = (float) points[count-1].x;
slouken@3551
   945
        vertices[0].y = (float) points[count-1].y;
slouken@3551
   946
        result = IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_POINTLIST, 1, vertices, sizeof(*vertices));
slouken@3551
   947
    }
slouken@3551
   948
slouken@3536
   949
    SDL_stack_free(vertices);
slouken@2932
   950
    if (FAILED(result)) {
slouken@2932
   951
        D3D_SetError("DrawPrimitiveUP()", result);
slouken@2932
   952
        return -1;
slouken@2932
   953
    }
slouken@2932
   954
    return 0;
slouken@2932
   955
}
slouken@2932
   956
slouken@2932
   957
static int
slouken@5297
   958
D3D_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect * rects,
slouken@3599
   959
                    int count)
slouken@2932
   960
{
slouken@2932
   961
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@3536
   962
    DWORD color;
slouken@3536
   963
    int i;
slouken@2932
   964
    float minx, miny, maxx, maxy;
slouken@2932
   965
    Vertex vertices[4];
slouken@2932
   966
    HRESULT result;
slouken@2932
   967
slouken@5297
   968
    if (D3D_ActivateRenderer(renderer) < 0) {
slouken@5297
   969
        return -1;
slouken@2932
   970
    }
slouken@2932
   971
slouken@2932
   972
    D3D_SetBlendMode(data, renderer->blendMode);
slouken@2932
   973
slouken@2933
   974
    result =
slouken@2933
   975
        IDirect3DDevice9_SetTexture(data->device, 0,
slouken@2933
   976
                                    (IDirect3DBaseTexture9 *) 0);
slouken@2932
   977
    if (FAILED(result)) {
slouken@2932
   978
        D3D_SetError("SetTexture()", result);
slouken@2932
   979
        return -1;
slouken@2932
   980
    }
slouken@3536
   981
slouken@3536
   982
    color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
slouken@3536
   983
slouken@3536
   984
    for (i = 0; i < count; ++i) {
slouken@5297
   985
        const SDL_Rect *rect = &rects[i];
slouken@3536
   986
slouken@3536
   987
        minx = (float) rect->x;
slouken@3536
   988
        miny = (float) rect->y;
slouken@3536
   989
        maxx = (float) rect->x + rect->w;
slouken@3536
   990
        maxy = (float) rect->y + rect->h;
slouken@3536
   991
slouken@3536
   992
        vertices[0].x = minx;
slouken@3536
   993
        vertices[0].y = miny;
slouken@3536
   994
        vertices[0].z = 0.0f;
slouken@3536
   995
        vertices[0].color = color;
slouken@3536
   996
        vertices[0].u = 0.0f;
slouken@3536
   997
        vertices[0].v = 0.0f;
slouken@3536
   998
slouken@3536
   999
        vertices[1].x = maxx;
slouken@3536
  1000
        vertices[1].y = miny;
slouken@3536
  1001
        vertices[1].z = 0.0f;
slouken@3536
  1002
        vertices[1].color = color;
slouken@3536
  1003
        vertices[1].u = 0.0f;
slouken@3536
  1004
        vertices[1].v = 0.0f;
slouken@3536
  1005
slouken@3536
  1006
        vertices[2].x = maxx;
slouken@3536
  1007
        vertices[2].y = maxy;
slouken@3536
  1008
        vertices[2].z = 0.0f;
slouken@3536
  1009
        vertices[2].color = color;
slouken@3536
  1010
        vertices[2].u = 0.0f;
slouken@3536
  1011
        vertices[2].v = 0.0f;
slouken@3536
  1012
slouken@3536
  1013
        vertices[3].x = minx;
slouken@3536
  1014
        vertices[3].y = maxy;
slouken@3536
  1015
        vertices[3].z = 0.0f;
slouken@3536
  1016
        vertices[3].color = color;
slouken@3536
  1017
        vertices[3].u = 0.0f;
slouken@3536
  1018
        vertices[3].v = 0.0f;
slouken@3536
  1019
slouken@3536
  1020
        result =
slouken@3536
  1021
            IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN,
slouken@3536
  1022
                                             2, vertices, sizeof(*vertices));
slouken@3536
  1023
        if (FAILED(result)) {
slouken@3536
  1024
            D3D_SetError("DrawPrimitiveUP()", result);
slouken@3536
  1025
            return -1;
slouken@3536
  1026
        }
slouken@1900
  1027
    }
slouken@1895
  1028
    return 0;
slouken@1895
  1029
}
slouken@1895
  1030
slouken@1895
  1031
static int
slouken@1913
  1032
D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1985
  1033
               const SDL_Rect * srcrect, const SDL_Rect * dstrect)
slouken@1895
  1034
{
slouken@1913
  1035
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@1913
  1036
    D3D_TextureData *texturedata = (D3D_TextureData *) texture->driverdata;
slouken@3556
  1037
    LPDIRECT3DPIXELSHADER9 shader = NULL;
slouken@1903
  1038
    float minx, miny, maxx, maxy;
slouken@1904
  1039
    float minu, maxu, minv, maxv;
slouken@1987
  1040
    DWORD color;
slouken@1903
  1041
    Vertex vertices[4];
slouken@1903
  1042
    HRESULT result;
slouken@1895
  1043
slouken@5297
  1044
    if (D3D_ActivateRenderer(renderer) < 0) {
slouken@5297
  1045
        return -1;
slouken@1900
  1046
    }
slouken@1903
  1047
slouken@3279
  1048
    minx = (float) dstrect->x - 0.5f;
slouken@3279
  1049
    miny = (float) dstrect->y - 0.5f;
slouken@3279
  1050
    maxx = (float) dstrect->x + dstrect->w - 0.5f;
slouken@3279
  1051
    maxy = (float) dstrect->y + dstrect->h - 0.5f;
slouken@1903
  1052
slouken@1904
  1053
    minu = (float) srcrect->x / texture->w;
slouken@1904
  1054
    maxu = (float) (srcrect->x + srcrect->w) / texture->w;
slouken@1904
  1055
    minv = (float) srcrect->y / texture->h;
slouken@1904
  1056
    maxv = (float) (srcrect->y + srcrect->h) / texture->h;
slouken@1903
  1057
slouken@1987
  1058
    color = D3DCOLOR_ARGB(texture->a, texture->r, texture->g, texture->b);
slouken@1987
  1059
slouken@1903
  1060
    vertices[0].x = minx;
slouken@1903
  1061
    vertices[0].y = miny;
slouken@1903
  1062
    vertices[0].z = 0.0f;
slouken@1987
  1063
    vertices[0].color = color;
slouken@1904
  1064
    vertices[0].u = minu;
slouken@1904
  1065
    vertices[0].v = minv;
slouken@1904
  1066
slouken@1903
  1067
    vertices[1].x = maxx;
slouken@1903
  1068
    vertices[1].y = miny;
slouken@1903
  1069
    vertices[1].z = 0.0f;
slouken@1987
  1070
    vertices[1].color = color;
slouken@1904
  1071
    vertices[1].u = maxu;
slouken@1904
  1072
    vertices[1].v = minv;
slouken@1904
  1073
slouken@1903
  1074
    vertices[2].x = maxx;
slouken@1903
  1075
    vertices[2].y = maxy;
slouken@1903
  1076
    vertices[2].z = 0.0f;
slouken@1987
  1077
    vertices[2].color = color;
slouken@1904
  1078
    vertices[2].u = maxu;
slouken@1904
  1079
    vertices[2].v = maxv;
slouken@1904
  1080
slouken@1903
  1081
    vertices[3].x = minx;
slouken@1903
  1082
    vertices[3].y = maxy;
slouken@1903
  1083
    vertices[3].z = 0.0f;
slouken@1987
  1084
    vertices[3].color = color;
slouken@1904
  1085
    vertices[3].u = minu;
slouken@1904
  1086
    vertices[3].v = maxv;
slouken@1903
  1087
slouken@2932
  1088
    D3D_SetBlendMode(data, texture->blendMode);
slouken@1916
  1089
slouken@5484
  1090
    if (texturedata->scaleMode != data->scaleMode) {
slouken@5484
  1091
        IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MINFILTER,
slouken@5484
  1092
                                         texturedata->scaleMode);
slouken@5484
  1093
        IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MAGFILTER,
slouken@5484
  1094
                                         texturedata->scaleMode);
slouken@5484
  1095
        data->scaleMode = texturedata->scaleMode;
slouken@5484
  1096
    }
slouken@1917
  1097
slouken@1903
  1098
    result =
slouken@2735
  1099
        IDirect3DDevice9_SetTexture(data->device, 0, (IDirect3DBaseTexture9 *)
slouken@2735
  1100
                                    texturedata->texture);
slouken@1903
  1101
    if (FAILED(result)) {
slouken@1903
  1102
        D3D_SetError("SetTexture()", result);
slouken@1903
  1103
        return -1;
slouken@1903
  1104
    }
slouken@3556
  1105
    if (shader) {
slouken@3556
  1106
        result = IDirect3DDevice9_SetPixelShader(data->device, shader);
slouken@3556
  1107
        if (FAILED(result)) {
slouken@3556
  1108
            D3D_SetError("SetShader()", result);
slouken@3556
  1109
            return -1;
slouken@3556
  1110
        }
slouken@3556
  1111
    }
slouken@1903
  1112
    result =
slouken@1903
  1113
        IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN, 2,
slouken@1903
  1114
                                         vertices, sizeof(*vertices));
slouken@1903
  1115
    if (FAILED(result)) {
slouken@1903
  1116
        D3D_SetError("DrawPrimitiveUP()", result);
slouken@1903
  1117
        return -1;
slouken@1903
  1118
    }
slouken@3556
  1119
    if (shader) {
slouken@3556
  1120
        result = IDirect3DDevice9_SetPixelShader(data->device, NULL);
slouken@3556
  1121
        if (FAILED(result)) {
slouken@3556
  1122
            D3D_SetError("SetShader()", result);
slouken@3556
  1123
            return -1;
slouken@3556
  1124
        }
slouken@3556
  1125
    }
slouken@1895
  1126
    return 0;
slouken@1895
  1127
}
slouken@1895
  1128
slouken@3427
  1129
static int
slouken@3427
  1130
D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
slouken@3480
  1131
                     Uint32 format, void * pixels, int pitch)
slouken@3427
  1132
{
slouken@3549
  1133
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@3549
  1134
    D3DSURFACE_DESC desc;
slouken@3549
  1135
    LPDIRECT3DSURFACE9 backBuffer;
slouken@3549
  1136
    LPDIRECT3DSURFACE9 surface;
slouken@3549
  1137
    RECT d3drect;
slouken@3549
  1138
    D3DLOCKED_RECT locked;
slouken@3549
  1139
    HRESULT result;
slouken@3427
  1140
slouken@3549
  1141
    result = IDirect3DDevice9_GetBackBuffer(data->device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuffer);
slouken@3549
  1142
    if (FAILED(result)) {
slouken@3549
  1143
        D3D_SetError("GetBackBuffer()", result);
slouken@3549
  1144
        return -1;
slouken@3549
  1145
    }
slouken@3427
  1146
slouken@3549
  1147
    result = IDirect3DSurface9_GetDesc(backBuffer, &desc);
slouken@3549
  1148
    if (FAILED(result)) {
slouken@3549
  1149
        D3D_SetError("GetDesc()", result);
slouken@3549
  1150
        IDirect3DSurface9_Release(backBuffer);
slouken@3549
  1151
        return -1;
slouken@3549
  1152
    }
slouken@3427
  1153
slouken@3549
  1154
    result = IDirect3DDevice9_CreateOffscreenPlainSurface(data->device, desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surface, NULL);
slouken@3549
  1155
    if (FAILED(result)) {
slouken@3549
  1156
        D3D_SetError("CreateOffscreenPlainSurface()", result);
slouken@3549
  1157
        IDirect3DSurface9_Release(backBuffer);
slouken@3549
  1158
        return -1;
slouken@3549
  1159
    }
slouken@3427
  1160
slouken@3549
  1161
    result = IDirect3DDevice9_GetRenderTargetData(data->device, backBuffer, surface);
slouken@3549
  1162
    if (FAILED(result)) {
slouken@3549
  1163
        D3D_SetError("GetRenderTargetData()", result);
slouken@3549
  1164
        IDirect3DSurface9_Release(surface);
slouken@3549
  1165
        IDirect3DSurface9_Release(backBuffer);
slouken@3549
  1166
        return -1;
slouken@3549
  1167
    }
slouken@3427
  1168
slouken@3549
  1169
    d3drect.left = rect->x;
slouken@3549
  1170
    d3drect.right = rect->x + rect->w;
slouken@3549
  1171
    d3drect.top = rect->y;
slouken@3549
  1172
    d3drect.bottom = rect->y + rect->h;
slouken@3427
  1173
slouken@3549
  1174
    result = IDirect3DSurface9_LockRect(surface, &locked, &d3drect, D3DLOCK_READONLY);
slouken@3549
  1175
    if (FAILED(result)) {
slouken@3549
  1176
        D3D_SetError("LockRect()", result);
slouken@3549
  1177
        IDirect3DSurface9_Release(surface);
slouken@3549
  1178
        IDirect3DSurface9_Release(backBuffer);
slouken@3549
  1179
        return -1;
slouken@3549
  1180
    }
slouken@3427
  1181
slouken@3549
  1182
    SDL_ConvertPixels(rect->w, rect->h,
slouken@5156
  1183
                      D3DFMTToPixelFormat(desc.Format), locked.pBits, locked.Pitch,
slouken@3549
  1184
                      format, pixels, pitch);
slouken@3549
  1185
slouken@3549
  1186
    IDirect3DSurface9_UnlockRect(surface);
slouken@3549
  1187
slouken@3549
  1188
    IDirect3DSurface9_Release(surface);
slouken@3549
  1189
    IDirect3DSurface9_Release(backBuffer);
slouken@3549
  1190
slouken@3549
  1191
    return 0;
slouken@3427
  1192
}
slouken@3427
  1193
slouken@1895
  1194
static void
slouken@1913
  1195
D3D_RenderPresent(SDL_Renderer * renderer)
slouken@1895
  1196
{
slouken@1913
  1197
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@1900
  1198
    HRESULT result;
slouken@1900
  1199
slouken@1900
  1200
    if (!data->beginScene) {
slouken@1900
  1201
        IDirect3DDevice9_EndScene(data->device);
slouken@1900
  1202
        data->beginScene = SDL_TRUE;
slouken@1900
  1203
    }
slouken@1900
  1204
slouken@1975
  1205
    result = IDirect3DDevice9_TestCooperativeLevel(data->device);
slouken@1975
  1206
    if (result == D3DERR_DEVICELOST) {
slouken@1975
  1207
        /* We'll reset later */
slouken@1975
  1208
        return;
slouken@1975
  1209
    }
slouken@1975
  1210
    if (result == D3DERR_DEVICENOTRESET) {
slouken@1975
  1211
        D3D_Reset(renderer);
slouken@1975
  1212
    }
slouken@1900
  1213
    result = IDirect3DDevice9_Present(data->device, NULL, NULL, NULL, NULL);
slouken@1900
  1214
    if (FAILED(result)) {
slouken@1900
  1215
        D3D_SetError("Present()", result);
slouken@1900
  1216
    }
slouken@1895
  1217
}
slouken@1895
  1218
slouken@1895
  1219
static void
slouken@1913
  1220
D3D_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1895
  1221
{
slouken@1913
  1222
    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
slouken@1895
  1223
slouken@1895
  1224
    if (!data) {
slouken@1895
  1225
        return;
slouken@1895
  1226
    }
slouken@1903
  1227
    if (data->texture) {
slouken@1903
  1228
        IDirect3DTexture9_Release(data->texture);
slouken@1903
  1229
    }
slouken@1895
  1230
    SDL_free(data);
slouken@1895
  1231
    texture->driverdata = NULL;
slouken@1895
  1232
}
slouken@1895
  1233
slouken@1975
  1234
static void
slouken@1913
  1235
D3D_DestroyRenderer(SDL_Renderer * renderer)
slouken@1895
  1236
{
slouken@1913
  1237
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@1895
  1238
slouken@1895
  1239
    if (data) {
slouken@6232
  1240
        // Release the render target
slouken@6232
  1241
        IDirect3DSurface9_Release(data->defaultRenderTarget);
slouken@6232
  1242
        if (data->currentRenderTarget != NULL) {
slouken@6232
  1243
            IDirect3DSurface9_Release(data->currentRenderTarget);
slouken@6232
  1244
            data->currentRenderTarget = NULL;
slouken@6232
  1245
        }
slouken@6232
  1246
        
slouken@1900
  1247
        if (data->device) {
slouken@1900
  1248
            IDirect3DDevice9_Release(data->device);
slouken@1900
  1249
        }
slouken@5154
  1250
        if (data->d3d) {
slouken@5154
  1251
            IDirect3D9_Release(data->d3d);
slouken@5154
  1252
            SDL_UnloadObject(data->d3dDLL);
slouken@5154
  1253
        }
slouken@1895
  1254
        SDL_free(data);
slouken@1895
  1255
    }
slouken@1895
  1256
    SDL_free(renderer);
slouken@1895
  1257
}
slouken@1895
  1258
slouken@5226
  1259
#endif /* SDL_VIDEO_RENDER_D3D && !SDL_RENDER_DISABLED */
slouken@1895
  1260
slouken@1895
  1261
/* vi: set ts=4 sw=4 expandtab: */