src/video/windows/SDL_d3drender.c
author Sam Lantinga <slouken@libsdl.org>
Tue, 01 Feb 2011 12:19:46 -0800
changeset 5142 c8e049de174c
parent 5141 31e7f523ab3d
child 5148 5429daf5e3f9
permissions -rw-r--r--
Making the API simpler, the renderer present semantics are always having a backbuffer and then discarding it. This is best for hardware accelerated rendering.
slouken@1895
     1
/*
slouken@1895
     2
    SDL - Simple DirectMedia Layer
slouken@3697
     3
    Copyright (C) 1997-2010 Sam Lantinga
slouken@1895
     4
slouken@1895
     5
    This library is free software; you can redistribute it and/or
slouken@1895
     6
    modify it under the terms of the GNU Lesser General Public
slouken@1895
     7
    License as published by the Free Software Foundation; either
slouken@1895
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@1895
     9
slouken@1895
    10
    This library is distributed in the hope that it will be useful,
slouken@1895
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@1895
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@1895
    13
    Lesser General Public License for more details.
slouken@1895
    14
slouken@1895
    15
    You should have received a copy of the GNU Lesser General Public
slouken@1895
    16
    License along with this library; if not, write to the Free Software
slouken@1895
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@1895
    18
slouken@1895
    19
    Sam Lantinga
slouken@1895
    20
    slouken@libsdl.org
slouken@1895
    21
*/
slouken@1895
    22
#include "SDL_config.h"
slouken@1895
    23
slouken@1895
    24
#if SDL_VIDEO_RENDER_D3D
slouken@1895
    25
slouken@5062
    26
#include "SDL_windowsvideo.h"
slouken@2973
    27
#include "../SDL_yuv_sw_c.h"
slouken@1895
    28
slouken@3556
    29
#ifdef ASSEMBLE_SHADER
slouken@3556
    30
///////////////////////////////////////////////////////////////////////////
slouken@3556
    31
// ID3DXBuffer:
slouken@3556
    32
// ------------
slouken@3556
    33
// The buffer object is used by D3DX to return arbitrary size data.
slouken@3556
    34
//
slouken@3556
    35
// GetBufferPointer -
slouken@3556
    36
//    Returns a pointer to the beginning of the buffer.
slouken@3556
    37
//
slouken@3556
    38
// GetBufferSize -
slouken@3556
    39
//    Returns the size of the buffer, in bytes.
slouken@3556
    40
///////////////////////////////////////////////////////////////////////////
slouken@3556
    41
slouken@3556
    42
typedef interface ID3DXBuffer ID3DXBuffer;
slouken@3556
    43
typedef interface ID3DXBuffer *LPD3DXBUFFER;
slouken@3556
    44
slouken@3556
    45
// {8BA5FB08-5195-40e2-AC58-0D989C3A0102}
slouken@3556
    46
DEFINE_GUID(IID_ID3DXBuffer, 
slouken@3556
    47
0x8ba5fb08, 0x5195, 0x40e2, 0xac, 0x58, 0xd, 0x98, 0x9c, 0x3a, 0x1, 0x2);
slouken@3556
    48
slouken@3556
    49
#undef INTERFACE
slouken@3556
    50
#define INTERFACE ID3DXBuffer
slouken@3556
    51
slouken@3556
    52
typedef interface ID3DXBuffer {
slouken@3556
    53
    const struct ID3DXBufferVtbl FAR* lpVtbl;
slouken@3556
    54
} ID3DXBuffer;
slouken@3556
    55
typedef const struct ID3DXBufferVtbl ID3DXBufferVtbl;
slouken@3556
    56
const struct ID3DXBufferVtbl
slouken@3556
    57
{
slouken@3556
    58
    // IUnknown
slouken@3556
    59
    STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE;
slouken@3556
    60
    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
slouken@3556
    61
    STDMETHOD_(ULONG, Release)(THIS) PURE;
slouken@3556
    62
slouken@3556
    63
    // ID3DXBuffer
slouken@3556
    64
    STDMETHOD_(LPVOID, GetBufferPointer)(THIS) PURE;
slouken@3556
    65
    STDMETHOD_(DWORD, GetBufferSize)(THIS) PURE;
slouken@3556
    66
};
slouken@3556
    67
slouken@3556
    68
HRESULT WINAPI
slouken@3556
    69
    D3DXAssembleShader(
slouken@3556
    70
        LPCSTR                          pSrcData,
slouken@3556
    71
        UINT                            SrcDataLen,
slouken@3556
    72
        CONST LPVOID*                   pDefines,
slouken@3556
    73
        LPVOID                          pInclude,
slouken@3556
    74
        DWORD                           Flags,
slouken@3556
    75
        LPD3DXBUFFER*                   ppShader,
slouken@3556
    76
        LPD3DXBUFFER*                   ppErrorMsgs);
slouken@3556
    77
slouken@3556
    78
#endif /* ASSEMBLE_SHADER */
slouken@3556
    79
slouken@3556
    80
slouken@1895
    81
/* Direct3D renderer implementation */
slouken@1895
    82
slouken@2786
    83
#if 1                           /* This takes more memory but you won't lose your texture data */
slouken@2932
    84
#define D3DPOOL_SDL    D3DPOOL_MANAGED
slouken@2783
    85
#define SDL_MEMORY_POOL_MANAGED
slouken@2783
    86
#else
slouken@2932
    87
#define D3DPOOL_SDL    D3DPOOL_DEFAULT
slouken@2783
    88
#define SDL_MEMORY_POOL_DEFAULT
slouken@2783
    89
#endif
slouken@2783
    90
slouken@1913
    91
static SDL_Renderer *D3D_CreateRenderer(SDL_Window * window, Uint32 flags);
slouken@1975
    92
static int D3D_DisplayModeChanged(SDL_Renderer * renderer);
slouken@1913
    93
static int D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
slouken@2990
    94
static int D3D_QueryTexturePixels(SDL_Renderer * renderer,
slouken@2990
    95
                                  SDL_Texture * texture, void **pixels,
slouken@2990
    96
                                  int *pitch);
slouken@1913
    97
static int D3D_SetTexturePalette(SDL_Renderer * renderer,
slouken@1913
    98
                                 SDL_Texture * texture,
slouken@1913
    99
                                 const SDL_Color * colors, int firstcolor,
slouken@1913
   100
                                 int ncolors);
slouken@1913
   101
static int D3D_GetTexturePalette(SDL_Renderer * renderer,
slouken@1913
   102
                                 SDL_Texture * texture, SDL_Color * colors,
slouken@1913
   103
                                 int firstcolor, int ncolors);
slouken@1913
   104
static int D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1913
   105
                             const SDL_Rect * rect, const void *pixels,
slouken@1913
   106
                             int pitch);
slouken@1913
   107
static int D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1913
   108
                           const SDL_Rect * rect, int markDirty,
slouken@1913
   109
                           void **pixels, int *pitch);
slouken@1913
   110
static void D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
slouken@1913
   111
static void D3D_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1913
   112
                             int numrects, const SDL_Rect * rects);
slouken@3599
   113
static int D3D_RenderDrawPoints(SDL_Renderer * renderer,
slouken@3599
   114
                                const SDL_Point * points, int count);
slouken@3599
   115
static int D3D_RenderDrawLines(SDL_Renderer * renderer,
slouken@3599
   116
                               const SDL_Point * points, int count);
slouken@3599
   117
static int D3D_RenderDrawRects(SDL_Renderer * renderer,
slouken@3599
   118
                               const SDL_Rect ** rects, int count);
slouken@3599
   119
static int D3D_RenderFillRects(SDL_Renderer * renderer,
slouken@3599
   120
                               const SDL_Rect ** rects, int count);
slouken@1913
   121
static int D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1985
   122
                          const SDL_Rect * srcrect, const SDL_Rect * dstrect);
slouken@3427
   123
static int D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
slouken@3480
   124
                                Uint32 format, void * pixels, int pitch);
slouken@3480
   125
static int D3D_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect,
slouken@3480
   126
                                 Uint32 format, const void * pixels, int pitch);
slouken@1913
   127
static void D3D_RenderPresent(SDL_Renderer * renderer);
slouken@1913
   128
static void D3D_DestroyTexture(SDL_Renderer * renderer,
slouken@1913
   129
                               SDL_Texture * texture);
slouken@1913
   130
static void D3D_DestroyRenderer(SDL_Renderer * renderer);
slouken@1895
   131
slouken@1895
   132
slouken@1913
   133
SDL_RenderDriver D3D_RenderDriver = {
slouken@1913
   134
    D3D_CreateRenderer,
slouken@1895
   135
    {
slouken@1895
   136
     "d3d",
slouken@5142
   137
     (SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED),
slouken@2972
   138
     0,
slouken@2972
   139
     {0},
slouken@1895
   140
     0,
slouken@1895
   141
     0}
slouken@1895
   142
};
slouken@1895
   143
slouken@1895
   144
typedef struct
slouken@1895
   145
{
slouken@2973
   146
    IDirect3D9 *d3d;
slouken@1895
   147
    IDirect3DDevice9 *device;
slouken@3527
   148
    UINT adapter;
slouken@1975
   149
    D3DPRESENT_PARAMETERS pparams;
slouken@1900
   150
    SDL_bool beginScene;
slouken@1913
   151
} D3D_RenderData;
slouken@1895
   152
slouken@1895
   153
typedef struct
slouken@1895
   154
{
slouken@2973
   155
    SDL_SW_YUVTexture *yuv;
slouken@2973
   156
    Uint32 format;
slouken@1903
   157
    IDirect3DTexture9 *texture;
slouken@1913
   158
} D3D_TextureData;
slouken@1895
   159
slouken@1903
   160
typedef struct
slouken@1903
   161
{
slouken@1903
   162
    float x, y, z;
slouken@1904
   163
    float rhw;
slouken@1987
   164
    DWORD color;
slouken@1904
   165
    float u, v;
slouken@1903
   166
} Vertex;
slouken@1903
   167
slouken@1895
   168
static void
slouken@1900
   169
D3D_SetError(const char *prefix, HRESULT result)
slouken@1900
   170
{
slouken@1900
   171
    const char *error;
slouken@1900
   172
slouken@1900
   173
    switch (result) {
slouken@1900
   174
    case D3DERR_WRONGTEXTUREFORMAT:
slouken@1900
   175
        error = "WRONGTEXTUREFORMAT";
slouken@1900
   176
        break;
slouken@1900
   177
    case D3DERR_UNSUPPORTEDCOLOROPERATION:
slouken@1900
   178
        error = "UNSUPPORTEDCOLOROPERATION";
slouken@1900
   179
        break;
slouken@1900
   180
    case D3DERR_UNSUPPORTEDCOLORARG:
slouken@1900
   181
        error = "UNSUPPORTEDCOLORARG";
slouken@1900
   182
        break;
slouken@1900
   183
    case D3DERR_UNSUPPORTEDALPHAOPERATION:
slouken@1900
   184
        error = "UNSUPPORTEDALPHAOPERATION";
slouken@1900
   185
        break;
slouken@1900
   186
    case D3DERR_UNSUPPORTEDALPHAARG:
slouken@1900
   187
        error = "UNSUPPORTEDALPHAARG";
slouken@1900
   188
        break;
slouken@1900
   189
    case D3DERR_TOOMANYOPERATIONS:
slouken@1900
   190
        error = "TOOMANYOPERATIONS";
slouken@1900
   191
        break;
slouken@1900
   192
    case D3DERR_CONFLICTINGTEXTUREFILTER:
slouken@1900
   193
        error = "CONFLICTINGTEXTUREFILTER";
slouken@1900
   194
        break;
slouken@1900
   195
    case D3DERR_UNSUPPORTEDFACTORVALUE:
slouken@1900
   196
        error = "UNSUPPORTEDFACTORVALUE";
slouken@1900
   197
        break;
slouken@1900
   198
    case D3DERR_CONFLICTINGRENDERSTATE:
slouken@1900
   199
        error = "CONFLICTINGRENDERSTATE";
slouken@1900
   200
        break;
slouken@1900
   201
    case D3DERR_UNSUPPORTEDTEXTUREFILTER:
slouken@1900
   202
        error = "UNSUPPORTEDTEXTUREFILTER";
slouken@1900
   203
        break;
slouken@1900
   204
    case D3DERR_CONFLICTINGTEXTUREPALETTE:
slouken@1900
   205
        error = "CONFLICTINGTEXTUREPALETTE";
slouken@1900
   206
        break;
slouken@1900
   207
    case D3DERR_DRIVERINTERNALERROR:
slouken@1900
   208
        error = "DRIVERINTERNALERROR";
slouken@1900
   209
        break;
slouken@1900
   210
    case D3DERR_NOTFOUND:
slouken@1900
   211
        error = "NOTFOUND";
slouken@1900
   212
        break;
slouken@1900
   213
    case D3DERR_MOREDATA:
slouken@1900
   214
        error = "MOREDATA";
slouken@1900
   215
        break;
slouken@1900
   216
    case D3DERR_DEVICELOST:
slouken@1900
   217
        error = "DEVICELOST";
slouken@1900
   218
        break;
slouken@1900
   219
    case D3DERR_DEVICENOTRESET:
slouken@1900
   220
        error = "DEVICENOTRESET";
slouken@1900
   221
        break;
slouken@1900
   222
    case D3DERR_NOTAVAILABLE:
slouken@1900
   223
        error = "NOTAVAILABLE";
slouken@1900
   224
        break;
slouken@1900
   225
    case D3DERR_OUTOFVIDEOMEMORY:
slouken@1900
   226
        error = "OUTOFVIDEOMEMORY";
slouken@1900
   227
        break;
slouken@1900
   228
    case D3DERR_INVALIDDEVICE:
slouken@1900
   229
        error = "INVALIDDEVICE";
slouken@1900
   230
        break;
slouken@1900
   231
    case D3DERR_INVALIDCALL:
slouken@1900
   232
        error = "INVALIDCALL";
slouken@1900
   233
        break;
slouken@1900
   234
    case D3DERR_DRIVERINVALIDCALL:
slouken@1900
   235
        error = "DRIVERINVALIDCALL";
slouken@1900
   236
        break;
slouken@1900
   237
    case D3DERR_WASSTILLDRAWING:
slouken@1900
   238
        error = "WASSTILLDRAWING";
slouken@1900
   239
        break;
slouken@1900
   240
    default:
slouken@1900
   241
        error = "UNKNOWN";
slouken@1900
   242
        break;
slouken@1900
   243
    }
slouken@1900
   244
    SDL_SetError("%s: %s", prefix, error);
slouken@1900
   245
}
slouken@1900
   246
slouken@1903
   247
static D3DFORMAT
slouken@1903
   248
PixelFormatToD3DFMT(Uint32 format)
slouken@1895
   249
{
slouken@1903
   250
    switch (format) {
slouken@1965
   251
    case SDL_PIXELFORMAT_INDEX8:
slouken@1903
   252
        return D3DFMT_P8;
slouken@1965
   253
    case SDL_PIXELFORMAT_RGB332:
slouken@1903
   254
        return D3DFMT_R3G3B2;
slouken@1965
   255
    case SDL_PIXELFORMAT_RGB444:
slouken@1903
   256
        return D3DFMT_X4R4G4B4;
slouken@1965
   257
    case SDL_PIXELFORMAT_RGB555:
slouken@1903
   258
        return D3DFMT_X1R5G5B5;
slouken@1965
   259
    case SDL_PIXELFORMAT_ARGB4444:
slouken@1903
   260
        return D3DFMT_A4R4G4B4;
slouken@1965
   261
    case SDL_PIXELFORMAT_ARGB1555:
slouken@1903
   262
        return D3DFMT_A1R5G5B5;
slouken@1965
   263
    case SDL_PIXELFORMAT_RGB565:
slouken@1903
   264
        return D3DFMT_R5G6B5;
slouken@1965
   265
    case SDL_PIXELFORMAT_RGB888:
slouken@1903
   266
        return D3DFMT_X8R8G8B8;
slouken@1965
   267
    case SDL_PIXELFORMAT_ARGB8888:
slouken@1903
   268
        return D3DFMT_A8R8G8B8;
slouken@1965
   269
    case SDL_PIXELFORMAT_ARGB2101010:
slouken@1903
   270
        return D3DFMT_A2R10G10B10;
slouken@3495
   271
    case SDL_PIXELFORMAT_YV12:
slouken@3495
   272
        return MAKEFOURCC('Y','V','1','2');
slouken@3495
   273
    case SDL_PIXELFORMAT_IYUV:
slouken@3495
   274
        return MAKEFOURCC('I','4','2','0');
slouken@1965
   275
    case SDL_PIXELFORMAT_UYVY:
slouken@1903
   276
        return D3DFMT_UYVY;
slouken@1965
   277
    case SDL_PIXELFORMAT_YUY2:
slouken@1903
   278
        return D3DFMT_YUY2;
slouken@1903
   279
    default:
slouken@1903
   280
        return D3DFMT_UNKNOWN;
slouken@1903
   281
    }
slouken@1895
   282
}
slouken@1895
   283
slouken@3527
   284
static UINT D3D_FindAdapter(IDirect3D9 * d3d, SDL_VideoDisplay * display)
slouken@3527
   285
{
slouken@3527
   286
    SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata;
slouken@3527
   287
    UINT adapter, count;
slouken@3527
   288
slouken@3527
   289
    count = IDirect3D9_GetAdapterCount(d3d);
slouken@3527
   290
    for (adapter = 0; adapter < count; ++adapter) {
slouken@3527
   291
        HRESULT result;
slouken@3527
   292
        D3DADAPTER_IDENTIFIER9 info;
slouken@3527
   293
        char *name;
slouken@3527
   294
slouken@3527
   295
        result = IDirect3D9_GetAdapterIdentifier(d3d, adapter, 0, &info);
slouken@3527
   296
        if (FAILED(result)) {
slouken@3527
   297
            continue;
slouken@3527
   298
        }
slouken@3527
   299
        name = WIN_StringToUTF8(displaydata->DeviceName);
slouken@3527
   300
        if (SDL_strcmp(name, info.DeviceName) == 0) {
slouken@3527
   301
            SDL_free(name);
slouken@3527
   302
            return adapter;
slouken@3527
   303
        }
slouken@3527
   304
        SDL_free(name);
slouken@3527
   305
    }
slouken@3527
   306
slouken@3527
   307
    /* This should never happen, but just in case... */
slouken@3527
   308
    return D3DADAPTER_DEFAULT;
slouken@3527
   309
}
slouken@3527
   310
slouken@2973
   311
static SDL_bool
slouken@3527
   312
D3D_IsTextureFormatAvailable(IDirect3D9 * d3d, UINT adapter,
slouken@3527
   313
                             Uint32 display_format,
slouken@2990
   314
                             Uint32 texture_format)
slouken@2973
   315
{
slouken@2973
   316
    HRESULT result;
slouken@2973
   317
slouken@3527
   318
    result = IDirect3D9_CheckDeviceFormat(d3d, adapter,
slouken@2973
   319
                                          D3DDEVTYPE_HAL,
slouken@2973
   320
                                          PixelFormatToD3DFMT(display_format),
slouken@2973
   321
                                          0,
slouken@2973
   322
                                          D3DRTYPE_TEXTURE,
slouken@2990
   323
                                          PixelFormatToD3DFMT
slouken@2990
   324
                                          (texture_format));
slouken@2973
   325
    return FAILED(result) ? SDL_FALSE : SDL_TRUE;
slouken@2973
   326
}
slouken@2973
   327
slouken@2973
   328
static void
slouken@2973
   329
UpdateYUVTextureData(SDL_Texture * texture)
slouken@2973
   330
{
slouken@2973
   331
    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
slouken@2973
   332
    SDL_Rect rect;
slouken@2973
   333
    RECT d3drect;
slouken@2973
   334
    D3DLOCKED_RECT locked;
slouken@2973
   335
    HRESULT result;
slouken@2973
   336
slouken@2973
   337
    d3drect.left = 0;
slouken@2973
   338
    d3drect.right = texture->w;
slouken@2973
   339
    d3drect.top = 0;
slouken@2973
   340
    d3drect.bottom = texture->h;
slouken@2973
   341
slouken@2990
   342
    result =
slouken@2990
   343
        IDirect3DTexture9_LockRect(data->texture, 0, &locked, &d3drect, 0);
slouken@2973
   344
    if (FAILED(result)) {
slouken@2973
   345
        return;
slouken@2973
   346
    }
slouken@2973
   347
slouken@2973
   348
    rect.x = 0;
slouken@2973
   349
    rect.y = 0;
slouken@2973
   350
    rect.w = texture->w;
slouken@2973
   351
    rect.h = texture->h;
slouken@2973
   352
    SDL_SW_CopyYUVToRGB(data->yuv, &rect, data->format, texture->w,
slouken@2973
   353
                        texture->h, locked.pBits, locked.Pitch);
slouken@2973
   354
slouken@2973
   355
    IDirect3DTexture9_UnlockRect(data->texture, 0);
slouken@2973
   356
}
slouken@2973
   357
slouken@1895
   358
void
slouken@1895
   359
D3D_AddRenderDriver(_THIS)
slouken@1895
   360
{
slouken@1895
   361
    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
slouken@2972
   362
    SDL_RendererInfo *info = &D3D_RenderDriver.info;
slouken@1895
   363
slouken@1895
   364
    if (data->d3d) {
slouken@3527
   365
        int i, j;
slouken@2972
   366
        int formats[] = {
slouken@2990
   367
            SDL_PIXELFORMAT_INDEX8,
slouken@2990
   368
            SDL_PIXELFORMAT_RGB332,
slouken@2990
   369
            SDL_PIXELFORMAT_RGB444,
slouken@2990
   370
            SDL_PIXELFORMAT_RGB555,
slouken@2990
   371
            SDL_PIXELFORMAT_ARGB4444,
slouken@2990
   372
            SDL_PIXELFORMAT_ARGB1555,
slouken@2990
   373
            SDL_PIXELFORMAT_RGB565,
slouken@2990
   374
            SDL_PIXELFORMAT_RGB888,
slouken@2990
   375
            SDL_PIXELFORMAT_ARGB8888,
slouken@2990
   376
            SDL_PIXELFORMAT_ARGB2101010,
slouken@2972
   377
        };
slouken@2972
   378
slouken@3527
   379
        for (i = 0; i < _this->num_displays; ++i) {
slouken@3527
   380
            SDL_VideoDisplay *display = &_this->displays[i];
slouken@3527
   381
            SDL_DisplayMode *mode = &display->desktop_mode;
slouken@3527
   382
            UINT adapter = D3D_FindAdapter(data->d3d, display);
slouken@3527
   383
slouken@3527
   384
            /* Get the matching D3D adapter for this display */
slouken@3527
   385
            info->num_texture_formats = 0;
slouken@3527
   386
            for (j = 0; j < SDL_arraysize(formats); ++j) {
slouken@3527
   387
                if (D3D_IsTextureFormatAvailable
slouken@3527
   388
                    (data->d3d, adapter, mode->format, formats[j])) {
slouken@3527
   389
                    info->texture_formats[info->num_texture_formats++] =
slouken@3527
   390
                        formats[j];
slouken@3527
   391
                }
slouken@2972
   392
            }
slouken@3527
   393
            info->texture_formats[info->num_texture_formats++] =
slouken@3527
   394
                SDL_PIXELFORMAT_YV12;
slouken@3527
   395
            info->texture_formats[info->num_texture_formats++] =
slouken@3527
   396
                SDL_PIXELFORMAT_IYUV;
slouken@3527
   397
            info->texture_formats[info->num_texture_formats++] =
slouken@3527
   398
                SDL_PIXELFORMAT_YUY2;
slouken@3527
   399
            info->texture_formats[info->num_texture_formats++] =
slouken@3527
   400
                SDL_PIXELFORMAT_UYVY;
slouken@3527
   401
            info->texture_formats[info->num_texture_formats++] =
slouken@3527
   402
                SDL_PIXELFORMAT_YVYU;
slouken@2972
   403
slouken@3527
   404
            SDL_AddRenderDriver(display, &D3D_RenderDriver);
slouken@3520
   405
        }
slouken@1895
   406
    }
slouken@1895
   407
}
slouken@1895
   408
slouken@1895
   409
SDL_Renderer *
slouken@1913
   410
D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
slouken@1895
   411
{
slouken@3685
   412
    SDL_VideoDisplay *display = window->display;
slouken@1895
   413
    SDL_VideoData *videodata = (SDL_VideoData *) display->device->driverdata;
slouken@1895
   414
    SDL_WindowData *windowdata = (SDL_WindowData *) window->driverdata;
slouken@1895
   415
    SDL_Renderer *renderer;
slouken@1913
   416
    D3D_RenderData *data;
slouken@1900
   417
    HRESULT result;
slouken@1900
   418
    D3DPRESENT_PARAMETERS pparams;
slouken@1907
   419
    IDirect3DSwapChain9 *chain;
slouken@1925
   420
    D3DCAPS9 caps;
slouken@1895
   421
slouken@1920
   422
    renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
slouken@1895
   423
    if (!renderer) {
slouken@1895
   424
        SDL_OutOfMemory();
slouken@1895
   425
        return NULL;
slouken@1895
   426
    }
slouken@1895
   427
slouken@1920
   428
    data = (D3D_RenderData *) SDL_calloc(1, sizeof(*data));
slouken@1895
   429
    if (!data) {
slouken@1913
   430
        D3D_DestroyRenderer(renderer);
slouken@1895
   431
        SDL_OutOfMemory();
slouken@1895
   432
        return NULL;
slouken@1895
   433
    }
slouken@2973
   434
    data->d3d = videodata->d3d;
slouken@1895
   435
slouken@4569
   436
    videodata->render = RENDER_D3D;
slouken@4569
   437
slouken@1975
   438
    renderer->DisplayModeChanged = D3D_DisplayModeChanged;
slouken@1913
   439
    renderer->CreateTexture = D3D_CreateTexture;
slouken@2973
   440
    renderer->QueryTexturePixels = D3D_QueryTexturePixels;
slouken@1913
   441
    renderer->SetTexturePalette = D3D_SetTexturePalette;
slouken@1913
   442
    renderer->GetTexturePalette = D3D_GetTexturePalette;
slouken@1913
   443
    renderer->UpdateTexture = D3D_UpdateTexture;
slouken@1913
   444
    renderer->LockTexture = D3D_LockTexture;
slouken@1913
   445
    renderer->UnlockTexture = D3D_UnlockTexture;
slouken@1913
   446
    renderer->DirtyTexture = D3D_DirtyTexture;
slouken@3599
   447
    renderer->RenderDrawPoints = D3D_RenderDrawPoints;
slouken@3599
   448
    renderer->RenderDrawLines = D3D_RenderDrawLines;
slouken@3599
   449
    renderer->RenderDrawRects = D3D_RenderDrawRects;
slouken@3675
   450
    renderer->RenderFillRects = D3D_RenderFillRects;
slouken@1913
   451
    renderer->RenderCopy = D3D_RenderCopy;
slouken@3427
   452
    renderer->RenderReadPixels = D3D_RenderReadPixels;
slouken@3480
   453
    renderer->RenderWritePixels = D3D_RenderWritePixels;
slouken@1913
   454
    renderer->RenderPresent = D3D_RenderPresent;
slouken@1913
   455
    renderer->DestroyTexture = D3D_DestroyTexture;
slouken@1913
   456
    renderer->DestroyRenderer = D3D_DestroyRenderer;
slouken@1913
   457
    renderer->info = D3D_RenderDriver.info;
slouken@3685
   458
    renderer->window = window;
slouken@1895
   459
    renderer->driverdata = data;
slouken@1895
   460
slouken@1965
   461
    renderer->info.flags = SDL_RENDERER_ACCELERATED;
slouken@1895
   462
slouken@1900
   463
    SDL_zero(pparams);
slouken@1900
   464
    pparams.BackBufferWidth = window->w;
slouken@1900
   465
    pparams.BackBufferHeight = window->h;
slouken@1903
   466
    if (window->flags & SDL_WINDOW_FULLSCREEN) {
slouken@1903
   467
        pparams.BackBufferFormat =
slouken@3519
   468
            PixelFormatToD3DFMT(window->fullscreen_mode.format);
slouken@1903
   469
    } else {
slouken@1903
   470
        pparams.BackBufferFormat = D3DFMT_UNKNOWN;
slouken@1903
   471
    }
slouken@5142
   472
    pparams.BackBufferCount = 1;
slouken@5142
   473
    pparams.SwapEffect = D3DSWAPEFFECT_DISCARD;
slouken@5142
   474
slouken@1900
   475
    if (window->flags & SDL_WINDOW_FULLSCREEN) {
slouken@1900
   476
        pparams.Windowed = FALSE;
slouken@1903
   477
        pparams.FullScreen_RefreshRateInHz =
slouken@3519
   478
            window->fullscreen_mode.refresh_rate;
slouken@1900
   479
    } else {
slouken@1900
   480
        pparams.Windowed = TRUE;
slouken@1903
   481
        pparams.FullScreen_RefreshRateInHz = 0;
slouken@1900
   482
    }
slouken@1965
   483
    if (flags & SDL_RENDERER_PRESENTVSYNC) {
slouken@1907
   484
        pparams.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
slouken@1907
   485
    } else {
slouken@1907
   486
        pparams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
slouken@1907
   487
    }
slouken@1900
   488
slouken@3527
   489
    data->adapter = D3D_FindAdapter(videodata->d3d, display);
slouken@3527
   490
    IDirect3D9_GetDeviceCaps(videodata->d3d, data->adapter,
slouken@3197
   491
                             D3DDEVTYPE_HAL, &caps);
slouken@3197
   492
slouken@3527
   493
    result = IDirect3D9_CreateDevice(videodata->d3d, data->adapter,
slouken@1900
   494
                                     D3DDEVTYPE_HAL,
slouken@1900
   495
                                     windowdata->hwnd,
slouken@3197
   496
                                     (caps.
slouken@3197
   497
                                      DevCaps &
slouken@3197
   498
                                      D3DDEVCAPS_HWTRANSFORMANDLIGHT) ?
slouken@3197
   499
                                     D3DCREATE_HARDWARE_VERTEXPROCESSING :
slouken@1900
   500
                                     D3DCREATE_SOFTWARE_VERTEXPROCESSING,
slouken@1900
   501
                                     &pparams, &data->device);
slouken@1900
   502
    if (FAILED(result)) {
slouken@1913
   503
        D3D_DestroyRenderer(renderer);
slouken@1900
   504
        D3D_SetError("CreateDevice()", result);
slouken@1900
   505
        return NULL;
slouken@1900
   506
    }
slouken@1900
   507
    data->beginScene = SDL_TRUE;
slouken@1900
   508
slouken@1907
   509
    /* Get presentation parameters to fill info */
slouken@1907
   510
    result = IDirect3DDevice9_GetSwapChain(data->device, 0, &chain);
slouken@1907
   511
    if (FAILED(result)) {
slouken@1913
   512
        D3D_DestroyRenderer(renderer);
slouken@1907
   513
        D3D_SetError("GetSwapChain()", result);
slouken@1907
   514
        return NULL;
slouken@1907
   515
    }
slouken@1907
   516
    result = IDirect3DSwapChain9_GetPresentParameters(chain, &pparams);
slouken@1907
   517
    if (FAILED(result)) {
slouken@1907
   518
        IDirect3DSwapChain9_Release(chain);
slouken@1913
   519
        D3D_DestroyRenderer(renderer);
slouken@1907
   520
        D3D_SetError("GetPresentParameters()", result);
slouken@1907
   521
        return NULL;
slouken@1907
   522
    }
slouken@1907
   523
    IDirect3DSwapChain9_Release(chain);
slouken@1907
   524
    if (pparams.PresentationInterval == D3DPRESENT_INTERVAL_ONE) {
slouken@1965
   525
        renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
slouken@1907
   526
    }
slouken@1975
   527
    data->pparams = pparams;
slouken@1907
   528
slouken@1925
   529
    IDirect3DDevice9_GetDeviceCaps(data->device, &caps);
slouken@1925
   530
    renderer->info.max_texture_width = caps.MaxTextureWidth;
slouken@1925
   531
    renderer->info.max_texture_height = caps.MaxTextureHeight;
slouken@1918
   532
slouken@1903
   533
    /* Set up parameters for rendering */
slouken@1904
   534
    IDirect3DDevice9_SetVertexShader(data->device, NULL);
slouken@1987
   535
    IDirect3DDevice9_SetFVF(data->device,
slouken@1987
   536
                            D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
slouken@1988
   537
    IDirect3DDevice9_SetRenderState(data->device, D3DRS_ZENABLE, D3DZB_FALSE);
slouken@1903
   538
    IDirect3DDevice9_SetRenderState(data->device, D3DRS_CULLMODE,
slouken@1903
   539
                                    D3DCULL_NONE);
slouken@1904
   540
    IDirect3DDevice9_SetRenderState(data->device, D3DRS_LIGHTING, FALSE);
slouken@1988
   541
    /* Enable color modulation by diffuse color */
slouken@1988
   542
    IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLOROP,
slouken@1988
   543
                                          D3DTOP_MODULATE);
slouken@1988
   544
    IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLORARG1,
slouken@1988
   545
                                          D3DTA_TEXTURE);
slouken@1988
   546
    IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLORARG2,
slouken@1988
   547
                                          D3DTA_DIFFUSE);
slouken@1988
   548
    /* Enable alpha modulation by diffuse alpha */
slouken@1988
   549
    IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAOP,
slouken@1988
   550
                                          D3DTOP_MODULATE);
slouken@1988
   551
    IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAARG1,
slouken@1988
   552
                                          D3DTA_TEXTURE);
slouken@1988
   553
    IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAARG2,
slouken@1988
   554
                                          D3DTA_DIFFUSE);
slouken@1991
   555
    /* Disable second texture stage, since we're done */
slouken@1991
   556
    IDirect3DDevice9_SetTextureStageState(data->device, 1, D3DTSS_COLOROP,
slouken@1991
   557
                                          D3DTOP_DISABLE);
slouken@1991
   558
    IDirect3DDevice9_SetTextureStageState(data->device, 1, D3DTSS_ALPHAOP,
slouken@1991
   559
                                          D3DTOP_DISABLE);
slouken@1903
   560
slouken@1895
   561
    return renderer;
slouken@1895
   562
}
slouken@1895
   563
slouken@1895
   564
static int
slouken@1975
   565
D3D_Reset(SDL_Renderer * renderer)
slouken@1975
   566
{
slouken@1975
   567
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@1975
   568
    HRESULT result;
slouken@1975
   569
slouken@1975
   570
    result = IDirect3DDevice9_Reset(data->device, &data->pparams);
slouken@1975
   571
    if (FAILED(result)) {
slouken@1975
   572
        if (result == D3DERR_DEVICELOST) {
slouken@1975
   573
            /* Don't worry about it, we'll reset later... */
slouken@1975
   574
            return 0;
slouken@1975
   575
        } else {
slouken@1975
   576
            D3D_SetError("Reset()", result);
slouken@1975
   577
            return -1;
slouken@1975
   578
        }
slouken@1975
   579
    }
slouken@1975
   580
    IDirect3DDevice9_SetVertexShader(data->device, NULL);
slouken@1987
   581
    IDirect3DDevice9_SetFVF(data->device,
slouken@1987
   582
                            D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
slouken@1975
   583
    IDirect3DDevice9_SetRenderState(data->device, D3DRS_CULLMODE,
slouken@1975
   584
                                    D3DCULL_NONE);
slouken@1975
   585
    IDirect3DDevice9_SetRenderState(data->device, D3DRS_LIGHTING, FALSE);
slouken@1975
   586
    return 0;
slouken@1975
   587
}
slouken@1975
   588
slouken@1975
   589
static int
slouken@1975
   590
D3D_DisplayModeChanged(SDL_Renderer * renderer)
slouken@1975
   591
{
slouken@1975
   592
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@3685
   593
    SDL_Window *window = renderer->window;
slouken@3685
   594
    SDL_VideoDisplay *display = window->display;
slouken@1975
   595
slouken@1975
   596
    data->pparams.BackBufferWidth = window->w;
slouken@1975
   597
    data->pparams.BackBufferHeight = window->h;
slouken@1975
   598
    if (window->flags & SDL_WINDOW_FULLSCREEN) {
slouken@1975
   599
        data->pparams.BackBufferFormat =
slouken@3519
   600
            PixelFormatToD3DFMT(window->fullscreen_mode.format);
slouken@1975
   601
    } else {
slouken@1975
   602
        data->pparams.BackBufferFormat = D3DFMT_UNKNOWN;
slouken@1975
   603
    }
slouken@1975
   604
    return D3D_Reset(renderer);
slouken@1975
   605
}
slouken@1975
   606
slouken@1975
   607
static int
slouken@1913
   608
D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1895
   609
{
slouken@1913
   610
    D3D_RenderData *renderdata = (D3D_RenderData *) renderer->driverdata;
slouken@3685
   611
    SDL_Window *window = renderer->window;
slouken@3685
   612
    SDL_VideoDisplay *display = window->display;
slouken@2973
   613
    Uint32 display_format = display->current_mode.format;
slouken@1913
   614
    D3D_TextureData *data;
slouken@1903
   615
    HRESULT result;
slouken@1895
   616
slouken@1920
   617
    data = (D3D_TextureData *) SDL_calloc(1, sizeof(*data));
slouken@1895
   618
    if (!data) {
slouken@1895
   619
        SDL_OutOfMemory();
slouken@1895
   620
        return -1;
slouken@1895
   621
    }
slouken@1895
   622
slouken@1895
   623
    texture->driverdata = data;
slouken@1895
   624
slouken@2973
   625
    if (SDL_ISPIXELFORMAT_FOURCC(texture->format) &&
slouken@2973
   626
        (texture->format != SDL_PIXELFORMAT_YUY2 ||
slouken@3527
   627
         !D3D_IsTextureFormatAvailable(renderdata->d3d, renderdata->adapter,
slouken@3527
   628
                                       display_format, texture->format))
slouken@2990
   629
        && (texture->format != SDL_PIXELFORMAT_YVYU
slouken@3527
   630
            || !D3D_IsTextureFormatAvailable(renderdata->d3d, renderdata->adapter,
slouken@3527
   631
                                             display_format, texture->format))) {
slouken@2973
   632
        data->yuv =
slouken@2973
   633
            SDL_SW_CreateYUVTexture(texture->format, texture->w, texture->h);
slouken@2973
   634
        if (!data->yuv) {
slouken@2973
   635
            return -1;
slouken@2973
   636
        }
slouken@2973
   637
        data->format = display->current_mode.format;
slouken@2973
   638
    } else {
slouken@2973
   639
        data->format = texture->format;
slouken@2973
   640
    }
slouken@2973
   641
slouken@1903
   642
    result =
slouken@1903
   643
        IDirect3DDevice9_CreateTexture(renderdata->device, texture->w,
slouken@1903
   644
                                       texture->h, 1, 0,
slouken@2973
   645
                                       PixelFormatToD3DFMT(data->format),
slouken@2783
   646
                                       D3DPOOL_SDL, &data->texture, NULL);
slouken@1903
   647
    if (FAILED(result)) {
slouken@1903
   648
        D3D_SetError("CreateTexture()", result);
slouken@1903
   649
        return -1;
slouken@1903
   650
    }
slouken@1903
   651
slouken@1895
   652
    return 0;
slouken@1895
   653
}
slouken@1895
   654
slouken@1895
   655
static int
slouken@2973
   656
D3D_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@2973
   657
                       void **pixels, int *pitch)
slouken@2973
   658
{
slouken@2973
   659
    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
slouken@2973
   660
slouken@2973
   661
    if (data->yuv) {
slouken@2973
   662
        return SDL_SW_QueryYUVTexturePixels(data->yuv, pixels, pitch);
slouken@2973
   663
    } else {
slouken@2973
   664
        /* D3D textures don't have their pixels hanging out */
slouken@2973
   665
        return -1;
slouken@2973
   666
    }
slouken@2973
   667
}
slouken@2973
   668
slouken@2973
   669
static int
slouken@1913
   670
D3D_SetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1913
   671
                      const SDL_Color * colors, int firstcolor, int ncolors)
slouken@1895
   672
{
slouken@1913
   673
    D3D_RenderData *renderdata = (D3D_RenderData *) renderer->driverdata;
slouken@1913
   674
    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
slouken@1895
   675
slouken@1903
   676
    return 0;
slouken@1895
   677
}
slouken@1895
   678
slouken@1895
   679
static int
slouken@1913
   680
D3D_GetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1913
   681
                      SDL_Color * colors, int firstcolor, int ncolors)
slouken@1895
   682
{
slouken@1913
   683
    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
slouken@1895
   684
slouken@1903
   685
    return 0;
slouken@1895
   686
}
slouken@1895
   687
slouken@1895
   688
static int
slouken@1913
   689
D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1913
   690
                  const SDL_Rect * rect, const void *pixels, int pitch)
slouken@1895
   691
{
slouken@1913
   692
    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
slouken@1913
   693
    D3D_RenderData *renderdata = (D3D_RenderData *) renderer->driverdata;
slouken@1895
   694
slouken@2973
   695
    if (data->yuv) {
slouken@2973
   696
        if (SDL_SW_UpdateYUVTexture(data->yuv, rect, pixels, pitch) < 0) {
slouken@2973
   697
            return -1;
slouken@2973
   698
        }
slouken@2973
   699
        UpdateYUVTextureData(texture);
slouken@2973
   700
        return 0;
slouken@2973
   701
    } else {
slouken@2973
   702
#ifdef SDL_MEMORY_POOL_DEFAULT
slouken@2973
   703
        IDirect3DTexture9 *temp;
slouken@2973
   704
        RECT d3drect;
slouken@2973
   705
        D3DLOCKED_RECT locked;
slouken@2973
   706
        const Uint8 *src;
slouken@2973
   707
        Uint8 *dst;
slouken@2973
   708
        int row, length;
slouken@2973
   709
        HRESULT result;
slouken@2973
   710
slouken@2973
   711
        result =
slouken@2973
   712
            IDirect3DDevice9_CreateTexture(renderdata->device, texture->w,
slouken@2973
   713
                                           texture->h, 1, 0,
slouken@3013
   714
                                           PixelFormatToD3DFMT(texture->
slouken@3013
   715
                                                               format),
slouken@2973
   716
                                           D3DPOOL_SYSTEMMEM, &temp, NULL);
slouken@2973
   717
        if (FAILED(result)) {
slouken@2973
   718
            D3D_SetError("CreateTexture()", result);
slouken@2973
   719
            return -1;
slouken@2973
   720
        }
slouken@2973
   721
slouken@2973
   722
        d3drect.left = rect->x;
slouken@2973
   723
        d3drect.right = rect->x + rect->w;
slouken@2973
   724
        d3drect.top = rect->y;
slouken@2973
   725
        d3drect.bottom = rect->y + rect->h;
slouken@2973
   726
slouken@2973
   727
        result = IDirect3DTexture9_LockRect(temp, 0, &locked, &d3drect, 0);
slouken@2973
   728
        if (FAILED(result)) {
slouken@2973
   729
            IDirect3DTexture9_Release(temp);
slouken@2973
   730
            D3D_SetError("LockRect()", result);
slouken@2973
   731
            return -1;
slouken@2973
   732
        }
slouken@2973
   733
slouken@2973
   734
        src = pixels;
slouken@2973
   735
        dst = locked.pBits;
slouken@2973
   736
        length = rect->w * SDL_BYTESPERPIXEL(texture->format);
slouken@2973
   737
        for (row = 0; row < rect->h; ++row) {
slouken@2973
   738
            SDL_memcpy(dst, src, length);
slouken@2973
   739
            src += pitch;
slouken@2973
   740
            dst += locked.Pitch;
slouken@2973
   741
        }
slouken@2973
   742
        IDirect3DTexture9_UnlockRect(temp, 0);
slouken@2973
   743
slouken@2973
   744
        result =
slouken@2973
   745
            IDirect3DDevice9_UpdateTexture(renderdata->device,
slouken@2973
   746
                                           (IDirect3DBaseTexture9 *) temp,
slouken@2973
   747
                                           (IDirect3DBaseTexture9 *)
slouken@2973
   748
                                           data->texture);
slouken@2973
   749
        IDirect3DTexture9_Release(temp);
slouken@2973
   750
        if (FAILED(result)) {
slouken@2973
   751
            D3D_SetError("UpdateTexture()", result);
slouken@2973
   752
            return -1;
slouken@2973
   753
        }
slouken@2973
   754
#else
slouken@2973
   755
        RECT d3drect;
slouken@2973
   756
        D3DLOCKED_RECT locked;
slouken@2973
   757
        const Uint8 *src;
slouken@2973
   758
        Uint8 *dst;
slouken@2973
   759
        int row, length;
slouken@2973
   760
        HRESULT result;
slouken@2973
   761
slouken@2973
   762
        d3drect.left = rect->x;
slouken@2973
   763
        d3drect.right = rect->x + rect->w;
slouken@2973
   764
        d3drect.top = rect->y;
slouken@2973
   765
        d3drect.bottom = rect->y + rect->h;
slouken@2973
   766
slouken@2973
   767
        result =
slouken@2990
   768
            IDirect3DTexture9_LockRect(data->texture, 0, &locked, &d3drect,
slouken@2990
   769
                                       0);
slouken@2973
   770
        if (FAILED(result)) {
slouken@2973
   771
            D3D_SetError("LockRect()", result);
slouken@2973
   772
            return -1;
slouken@2973
   773
        }
slouken@2973
   774
slouken@2973
   775
        src = pixels;
slouken@2973
   776
        dst = locked.pBits;
slouken@2973
   777
        length = rect->w * SDL_BYTESPERPIXEL(texture->format);
slouken@2973
   778
        for (row = 0; row < rect->h; ++row) {
slouken@2973
   779
            SDL_memcpy(dst, src, length);
slouken@2973
   780
            src += pitch;
slouken@2973
   781
            dst += locked.Pitch;
slouken@2973
   782
        }
slouken@2973
   783
        IDirect3DTexture9_UnlockRect(data->texture, 0);
slouken@2973
   784
#endif // SDL_MEMORY_POOL_DEFAULT
slouken@2973
   785
slouken@2973
   786
        return 0;
slouken@1903
   787
    }
slouken@1895
   788
}
slouken@1895
   789
slouken@1895
   790
static int
slouken@1913
   791
D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1913
   792
                const SDL_Rect * rect, int markDirty, void **pixels,
slouken@1913
   793
                int *pitch)
slouken@1895
   794
{
slouken@1913
   795
    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
slouken@1895
   796
slouken@2973
   797
    if (data->yuv) {
slouken@2973
   798
        return SDL_SW_LockYUVTexture(data->yuv, rect, markDirty, pixels,
slouken@2973
   799
                                     pitch);
slouken@2973
   800
    } else {
slouken@2973
   801
        RECT d3drect;
slouken@2973
   802
        D3DLOCKED_RECT locked;
slouken@2973
   803
        HRESULT result;
slouken@1903
   804
slouken@2973
   805
        d3drect.left = rect->x;
slouken@2973
   806
        d3drect.right = rect->x + rect->w;
slouken@2973
   807
        d3drect.top = rect->y;
slouken@2973
   808
        d3drect.bottom = rect->y + rect->h;
slouken@2973
   809
slouken@2973
   810
        result =
slouken@2973
   811
            IDirect3DTexture9_LockRect(data->texture, 0, &locked, &d3drect,
slouken@2990
   812
                                       markDirty ? 0 :
slouken@2990
   813
                                       D3DLOCK_NO_DIRTY_UPDATE);
slouken@2973
   814
        if (FAILED(result)) {
slouken@2973
   815
            D3D_SetError("LockRect()", result);
slouken@2973
   816
            return -1;
slouken@2973
   817
        }
slouken@2973
   818
        *pixels = locked.pBits;
slouken@2973
   819
        *pitch = locked.Pitch;
slouken@2973
   820
        return 0;
slouken@1903
   821
    }
slouken@1895
   822
}
slouken@1895
   823
slouken@1895
   824
static void
slouken@1913
   825
D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1895
   826
{
slouken@1913
   827
    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
slouken@1895
   828
slouken@2973
   829
    if (data->yuv) {
slouken@2973
   830
        SDL_SW_UnlockYUVTexture(data->yuv);
slouken@2973
   831
        UpdateYUVTextureData(texture);
slouken@2973
   832
    } else {
slouken@2973
   833
        IDirect3DTexture9_UnlockRect(data->texture, 0);
slouken@2973
   834
    }
slouken@1895
   835
}
slouken@1895
   836
slouken@1895
   837
static void
slouken@1913
   838
D3D_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture, int numrects,
slouken@1913
   839
                 const SDL_Rect * rects)
slouken@1895
   840
{
slouken@1913
   841
    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
slouken@1903
   842
    RECT d3drect;
slouken@1903
   843
    int i;
slouken@1903
   844
slouken@1903
   845
    for (i = 0; i < numrects; ++i) {
slouken@1903
   846
        const SDL_Rect *rect = &rects[i];
slouken@1903
   847
slouken@1903
   848
        d3drect.left = rect->x;
slouken@1903
   849
        d3drect.right = rect->x + rect->w;
slouken@1903
   850
        d3drect.top = rect->y;
slouken@1903
   851
        d3drect.bottom = rect->y + rect->h;
slouken@1903
   852
slouken@1903
   853
        IDirect3DTexture9_AddDirtyRect(data->texture, &d3drect);
slouken@1903
   854
    }
slouken@1895
   855
}
slouken@1895
   856
slouken@2932
   857
static void
slouken@2933
   858
D3D_SetBlendMode(D3D_RenderData * data, int blendMode)
slouken@2932
   859
{
slouken@2932
   860
    switch (blendMode) {
slouken@2932
   861
    case SDL_BLENDMODE_NONE:
slouken@2932
   862
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
slouken@2932
   863
                                        FALSE);
slouken@2932
   864
        break;
slouken@2932
   865
    case SDL_BLENDMODE_BLEND:
slouken@2932
   866
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
slouken@2932
   867
                                        TRUE);
slouken@2932
   868
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
slouken@2932
   869
                                        D3DBLEND_SRCALPHA);
slouken@2932
   870
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
slouken@2932
   871
                                        D3DBLEND_INVSRCALPHA);
slouken@2932
   872
        break;
slouken@2932
   873
    case SDL_BLENDMODE_ADD:
slouken@2932
   874
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
slouken@2932
   875
                                        TRUE);
slouken@2932
   876
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
slouken@2932
   877
                                        D3DBLEND_SRCALPHA);
slouken@2932
   878
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
slouken@2932
   879
                                        D3DBLEND_ONE);
slouken@2932
   880
        break;
slouken@2932
   881
    }
slouken@2932
   882
}
slouken@2932
   883
slouken@1895
   884
static int
slouken@3599
   885
D3D_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points,
slouken@3599
   886
                     int count)
slouken@1895
   887
{
slouken@1913
   888
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@2932
   889
    DWORD color;
slouken@3536
   890
    Vertex *vertices;
slouken@3536
   891
    int i;
slouken@1900
   892
    HRESULT result;
slouken@1895
   893
slouken@1900
   894
    if (data->beginScene) {
slouken@1900
   895
        IDirect3DDevice9_BeginScene(data->device);
slouken@1900
   896
        data->beginScene = SDL_FALSE;
slouken@1900
   897
    }
slouken@1895
   898
slouken@2932
   899
    D3D_SetBlendMode(data, renderer->blendMode);
slouken@2932
   900
slouken@2933
   901
    result =
slouken@2933
   902
        IDirect3DDevice9_SetTexture(data->device, 0,
slouken@2933
   903
                                    (IDirect3DBaseTexture9 *) 0);
slouken@2932
   904
    if (FAILED(result)) {
slouken@2932
   905
        D3D_SetError("SetTexture()", result);
slouken@2932
   906
        return -1;
slouken@2932
   907
    }
slouken@3536
   908
slouken@3536
   909
    color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
slouken@3536
   910
slouken@3536
   911
    vertices = SDL_stack_alloc(Vertex, count);
slouken@3536
   912
    for (i = 0; i < count; ++i) {
slouken@3536
   913
        vertices[i].x = (float) points[i].x;
slouken@3536
   914
        vertices[i].y = (float) points[i].y;
slouken@3536
   915
        vertices[i].z = 0.0f;
slouken@3536
   916
        vertices[i].rhw = 1.0f;
slouken@3536
   917
        vertices[i].color = color;
slouken@3536
   918
        vertices[i].u = 0.0f;
slouken@3536
   919
        vertices[i].v = 0.0f;
slouken@3536
   920
    }
slouken@1903
   921
    result =
slouken@3536
   922
        IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_POINTLIST, count,
slouken@2932
   923
                                         vertices, sizeof(*vertices));
slouken@3536
   924
    SDL_stack_free(vertices);
slouken@1900
   925
    if (FAILED(result)) {
slouken@2932
   926
        D3D_SetError("DrawPrimitiveUP()", result);
slouken@2932
   927
        return -1;
slouken@2932
   928
    }
slouken@2932
   929
    return 0;
slouken@2932
   930
}
slouken@2932
   931
slouken@2932
   932
static int
slouken@3599
   933
D3D_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points,
slouken@3599
   934
                    int count)
slouken@2932
   935
{
slouken@2932
   936
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@2932
   937
    DWORD color;
slouken@3536
   938
    Vertex *vertices;
slouken@3536
   939
    int i;
slouken@2932
   940
    HRESULT result;
slouken@2932
   941
slouken@2932
   942
    if (data->beginScene) {
slouken@2932
   943
        IDirect3DDevice9_BeginScene(data->device);
slouken@2932
   944
        data->beginScene = SDL_FALSE;
slouken@2932
   945
    }
slouken@2932
   946
slouken@2932
   947
    D3D_SetBlendMode(data, renderer->blendMode);
slouken@2932
   948
slouken@2933
   949
    result =
slouken@2933
   950
        IDirect3DDevice9_SetTexture(data->device, 0,
slouken@2933
   951
                                    (IDirect3DBaseTexture9 *) 0);
slouken@2932
   952
    if (FAILED(result)) {
slouken@2932
   953
        D3D_SetError("SetTexture()", result);
slouken@2932
   954
        return -1;
slouken@2932
   955
    }
slouken@3536
   956
slouken@3536
   957
    color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
slouken@3536
   958
slouken@3536
   959
    vertices = SDL_stack_alloc(Vertex, count);
slouken@3536
   960
    for (i = 0; i < count; ++i) {
slouken@3536
   961
        vertices[i].x = (float) points[i].x;
slouken@3536
   962
        vertices[i].y = (float) points[i].y;
slouken@3536
   963
        vertices[i].z = 0.0f;
slouken@3536
   964
        vertices[i].rhw = 1.0f;
slouken@3536
   965
        vertices[i].color = color;
slouken@3536
   966
        vertices[i].u = 0.0f;
slouken@3536
   967
        vertices[i].v = 0.0f;
slouken@3536
   968
    }
slouken@2932
   969
    result =
slouken@3551
   970
        IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_LINESTRIP, count-1,
slouken@2932
   971
                                         vertices, sizeof(*vertices));
slouken@3551
   972
slouken@3551
   973
    /* DirectX 9 has the same line rasterization semantics as GDI,
slouken@3551
   974
       so we need to close the endpoint of the line */
slouken@3551
   975
    if (points[0].x != points[count-1].x || points[0].y != points[count-1].y) {
slouken@3551
   976
        vertices[0].x = (float) points[count-1].x;
slouken@3551
   977
        vertices[0].y = (float) points[count-1].y;
slouken@3551
   978
        result = IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_POINTLIST, 1, vertices, sizeof(*vertices));
slouken@3551
   979
    }
slouken@3551
   980
slouken@3536
   981
    SDL_stack_free(vertices);
slouken@2932
   982
    if (FAILED(result)) {
slouken@2932
   983
        D3D_SetError("DrawPrimitiveUP()", result);
slouken@2932
   984
        return -1;
slouken@2932
   985
    }
slouken@2932
   986
    return 0;
slouken@2932
   987
}
slouken@2932
   988
slouken@2932
   989
static int
slouken@3599
   990
D3D_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects,
slouken@3599
   991
                    int count)
slouken@3599
   992
{
slouken@3599
   993
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@3599
   994
    DWORD color;
slouken@3599
   995
    int i;
slouken@3599
   996
    Vertex vertices[5];
slouken@3599
   997
    HRESULT result;
slouken@3599
   998
slouken@3599
   999
    if (data->beginScene) {
slouken@3599
  1000
        IDirect3DDevice9_BeginScene(data->device);
slouken@3599
  1001
        data->beginScene = SDL_FALSE;
slouken@3599
  1002
    }
slouken@3599
  1003
slouken@3599
  1004
    D3D_SetBlendMode(data, renderer->blendMode);
slouken@3599
  1005
slouken@3599
  1006
    result =
slouken@3599
  1007
        IDirect3DDevice9_SetTexture(data->device, 0,
slouken@3599
  1008
                                    (IDirect3DBaseTexture9 *) 0);
slouken@3599
  1009
    if (FAILED(result)) {
slouken@3599
  1010
        D3D_SetError("SetTexture()", result);
slouken@3599
  1011
        return -1;
slouken@3599
  1012
    }
slouken@3599
  1013
slouken@3599
  1014
    color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
slouken@3599
  1015
slouken@3599
  1016
    for (i = 0; i < SDL_arraysize(vertices); ++i) {
slouken@3599
  1017
        vertices[i].z = 0.0f;
slouken@3599
  1018
        vertices[i].rhw = 1.0f;
slouken@3599
  1019
        vertices[i].color = color;
slouken@3599
  1020
        vertices[i].u = 0.0f;
slouken@3599
  1021
        vertices[i].v = 0.0f;
slouken@3599
  1022
    }
slouken@3599
  1023
slouken@3599
  1024
    for (i = 0; i < count; ++i) {
slouken@3599
  1025
        const SDL_Rect *rect = rects[i];
slouken@3599
  1026
slouken@3599
  1027
        vertices[0].x = (float) rect->x;
slouken@3599
  1028
        vertices[0].y = (float) rect->y;
slouken@3599
  1029
slouken@3599
  1030
        vertices[1].x = (float) rect->x+rect->w-1;
slouken@3599
  1031
        vertices[1].y = (float) rect->y;
slouken@3599
  1032
slouken@3599
  1033
        vertices[2].x = (float) rect->x+rect->w-1;
slouken@3599
  1034
        vertices[2].y = (float) rect->y+rect->h-1;
slouken@3599
  1035
slouken@3599
  1036
        vertices[3].x = (float) rect->x;
slouken@3599
  1037
        vertices[3].y = (float) rect->y+rect->h-1;
slouken@3599
  1038
slouken@3599
  1039
        vertices[4].x = (float) rect->x;
slouken@3599
  1040
        vertices[4].y = (float) rect->y;
slouken@3599
  1041
slouken@3599
  1042
        result =
slouken@3599
  1043
            IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_LINESTRIP, 4,
slouken@3599
  1044
                                             vertices, sizeof(*vertices));
slouken@3599
  1045
slouken@3599
  1046
        if (FAILED(result)) {
slouken@3599
  1047
            D3D_SetError("DrawPrimitiveUP()", result);
slouken@3599
  1048
            return -1;
slouken@3599
  1049
        }
slouken@3599
  1050
    }
slouken@3599
  1051
    return 0;
slouken@3599
  1052
}
slouken@3599
  1053
slouken@3599
  1054
static int
slouken@3599
  1055
D3D_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects,
slouken@3599
  1056
                    int count)
slouken@2932
  1057
{
slouken@2932
  1058
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@3536
  1059
    DWORD color;
slouken@3536
  1060
    int i;
slouken@2932
  1061
    float minx, miny, maxx, maxy;
slouken@2932
  1062
    Vertex vertices[4];
slouken@2932
  1063
    HRESULT result;
slouken@2932
  1064
slouken@2932
  1065
    if (data->beginScene) {
slouken@2932
  1066
        IDirect3DDevice9_BeginScene(data->device);
slouken@2932
  1067
        data->beginScene = SDL_FALSE;
slouken@2932
  1068
    }
slouken@2932
  1069
slouken@2932
  1070
    D3D_SetBlendMode(data, renderer->blendMode);
slouken@2932
  1071
slouken@2933
  1072
    result =
slouken@2933
  1073
        IDirect3DDevice9_SetTexture(data->device, 0,
slouken@2933
  1074
                                    (IDirect3DBaseTexture9 *) 0);
slouken@2932
  1075
    if (FAILED(result)) {
slouken@2932
  1076
        D3D_SetError("SetTexture()", result);
slouken@2932
  1077
        return -1;
slouken@2932
  1078
    }
slouken@3536
  1079
slouken@3536
  1080
    color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
slouken@3536
  1081
slouken@3536
  1082
    for (i = 0; i < count; ++i) {
slouken@3536
  1083
        const SDL_Rect *rect = rects[i];
slouken@3536
  1084
slouken@3536
  1085
        minx = (float) rect->x;
slouken@3536
  1086
        miny = (float) rect->y;
slouken@3536
  1087
        maxx = (float) rect->x + rect->w;
slouken@3536
  1088
        maxy = (float) rect->y + rect->h;
slouken@3536
  1089
slouken@3536
  1090
        vertices[0].x = minx;
slouken@3536
  1091
        vertices[0].y = miny;
slouken@3536
  1092
        vertices[0].z = 0.0f;
slouken@3536
  1093
        vertices[0].rhw = 1.0f;
slouken@3536
  1094
        vertices[0].color = color;
slouken@3536
  1095
        vertices[0].u = 0.0f;
slouken@3536
  1096
        vertices[0].v = 0.0f;
slouken@3536
  1097
slouken@3536
  1098
        vertices[1].x = maxx;
slouken@3536
  1099
        vertices[1].y = miny;
slouken@3536
  1100
        vertices[1].z = 0.0f;
slouken@3536
  1101
        vertices[1].rhw = 1.0f;
slouken@3536
  1102
        vertices[1].color = color;
slouken@3536
  1103
        vertices[1].u = 0.0f;
slouken@3536
  1104
        vertices[1].v = 0.0f;
slouken@3536
  1105
slouken@3536
  1106
        vertices[2].x = maxx;
slouken@3536
  1107
        vertices[2].y = maxy;
slouken@3536
  1108
        vertices[2].z = 0.0f;
slouken@3536
  1109
        vertices[2].rhw = 1.0f;
slouken@3536
  1110
        vertices[2].color = color;
slouken@3536
  1111
        vertices[2].u = 0.0f;
slouken@3536
  1112
        vertices[2].v = 0.0f;
slouken@3536
  1113
slouken@3536
  1114
        vertices[3].x = minx;
slouken@3536
  1115
        vertices[3].y = maxy;
slouken@3536
  1116
        vertices[3].z = 0.0f;
slouken@3536
  1117
        vertices[3].rhw = 1.0f;
slouken@3536
  1118
        vertices[3].color = color;
slouken@3536
  1119
        vertices[3].u = 0.0f;
slouken@3536
  1120
        vertices[3].v = 0.0f;
slouken@3536
  1121
slouken@3536
  1122
        result =
slouken@3536
  1123
            IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN,
slouken@3536
  1124
                                             2, vertices, sizeof(*vertices));
slouken@3536
  1125
        if (FAILED(result)) {
slouken@3536
  1126
            D3D_SetError("DrawPrimitiveUP()", result);
slouken@3536
  1127
            return -1;
slouken@3536
  1128
        }
slouken@1900
  1129
    }
slouken@1895
  1130
    return 0;
slouken@1895
  1131
}
slouken@1895
  1132
slouken@1895
  1133
static int
slouken@1913
  1134
D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1985
  1135
               const SDL_Rect * srcrect, const SDL_Rect * dstrect)
slouken@1895
  1136
{
slouken@1913
  1137
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@1913
  1138
    D3D_TextureData *texturedata = (D3D_TextureData *) texture->driverdata;
slouken@3556
  1139
    LPDIRECT3DPIXELSHADER9 shader = NULL;
slouken@1903
  1140
    float minx, miny, maxx, maxy;
slouken@1904
  1141
    float minu, maxu, minv, maxv;
slouken@1987
  1142
    DWORD color;
slouken@1903
  1143
    Vertex vertices[4];
slouken@1903
  1144
    HRESULT result;
slouken@1895
  1145
slouken@1900
  1146
    if (data->beginScene) {
slouken@1900
  1147
        IDirect3DDevice9_BeginScene(data->device);
slouken@1900
  1148
        data->beginScene = SDL_FALSE;
slouken@1900
  1149
    }
slouken@1903
  1150
slouken@3279
  1151
    minx = (float) dstrect->x - 0.5f;
slouken@3279
  1152
    miny = (float) dstrect->y - 0.5f;
slouken@3279
  1153
    maxx = (float) dstrect->x + dstrect->w - 0.5f;
slouken@3279
  1154
    maxy = (float) dstrect->y + dstrect->h - 0.5f;
slouken@1903
  1155
slouken@1904
  1156
    minu = (float) srcrect->x / texture->w;
slouken@1904
  1157
    maxu = (float) (srcrect->x + srcrect->w) / texture->w;
slouken@1904
  1158
    minv = (float) srcrect->y / texture->h;
slouken@1904
  1159
    maxv = (float) (srcrect->y + srcrect->h) / texture->h;
slouken@1903
  1160
slouken@1987
  1161
    color = D3DCOLOR_ARGB(texture->a, texture->r, texture->g, texture->b);
slouken@1987
  1162
slouken@1903
  1163
    vertices[0].x = minx;
slouken@1903
  1164
    vertices[0].y = miny;
slouken@1903
  1165
    vertices[0].z = 0.0f;
slouken@1904
  1166
    vertices[0].rhw = 1.0f;
slouken@1987
  1167
    vertices[0].color = color;
slouken@1904
  1168
    vertices[0].u = minu;
slouken@1904
  1169
    vertices[0].v = minv;
slouken@1904
  1170
slouken@1903
  1171
    vertices[1].x = maxx;
slouken@1903
  1172
    vertices[1].y = miny;
slouken@1903
  1173
    vertices[1].z = 0.0f;
slouken@1904
  1174
    vertices[1].rhw = 1.0f;
slouken@1987
  1175
    vertices[1].color = color;
slouken@1904
  1176
    vertices[1].u = maxu;
slouken@1904
  1177
    vertices[1].v = minv;
slouken@1904
  1178
slouken@1903
  1179
    vertices[2].x = maxx;
slouken@1903
  1180
    vertices[2].y = maxy;
slouken@1903
  1181
    vertices[2].z = 0.0f;
slouken@1904
  1182
    vertices[2].rhw = 1.0f;
slouken@1987
  1183
    vertices[2].color = color;
slouken@1904
  1184
    vertices[2].u = maxu;
slouken@1904
  1185
    vertices[2].v = maxv;
slouken@1904
  1186
slouken@1903
  1187
    vertices[3].x = minx;
slouken@1903
  1188
    vertices[3].y = maxy;
slouken@1903
  1189
    vertices[3].z = 0.0f;
slouken@1904
  1190
    vertices[3].rhw = 1.0f;
slouken@1987
  1191
    vertices[3].color = color;
slouken@1904
  1192
    vertices[3].u = minu;
slouken@1904
  1193
    vertices[3].v = maxv;
slouken@1903
  1194
slouken@2932
  1195
    D3D_SetBlendMode(data, texture->blendMode);
slouken@1916
  1196
slouken@5138
  1197
    IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MINFILTER,
slouken@5138
  1198
                                     D3DTEXF_LINEAR);
slouken@5138
  1199
    IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MAGFILTER,
slouken@5138
  1200
                                     D3DTEXF_LINEAR);
slouken@1917
  1201
slouken@1903
  1202
    result =
slouken@2735
  1203
        IDirect3DDevice9_SetTexture(data->device, 0, (IDirect3DBaseTexture9 *)
slouken@2735
  1204
                                    texturedata->texture);
slouken@1903
  1205
    if (FAILED(result)) {
slouken@1903
  1206
        D3D_SetError("SetTexture()", result);
slouken@1903
  1207
        return -1;
slouken@1903
  1208
    }
slouken@3556
  1209
    if (shader) {
slouken@3556
  1210
        result = IDirect3DDevice9_SetPixelShader(data->device, shader);
slouken@3556
  1211
        if (FAILED(result)) {
slouken@3556
  1212
            D3D_SetError("SetShader()", result);
slouken@3556
  1213
            return -1;
slouken@3556
  1214
        }
slouken@3556
  1215
    }
slouken@1903
  1216
    result =
slouken@1903
  1217
        IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN, 2,
slouken@1903
  1218
                                         vertices, sizeof(*vertices));
slouken@1903
  1219
    if (FAILED(result)) {
slouken@1903
  1220
        D3D_SetError("DrawPrimitiveUP()", result);
slouken@1903
  1221
        return -1;
slouken@1903
  1222
    }
slouken@3556
  1223
    if (shader) {
slouken@3556
  1224
        result = IDirect3DDevice9_SetPixelShader(data->device, NULL);
slouken@3556
  1225
        if (FAILED(result)) {
slouken@3556
  1226
            D3D_SetError("SetShader()", result);
slouken@3556
  1227
            return -1;
slouken@3556
  1228
        }
slouken@3556
  1229
    }
slouken@1895
  1230
    return 0;
slouken@1895
  1231
}
slouken@1895
  1232
slouken@3427
  1233
static int
slouken@3427
  1234
D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
slouken@3480
  1235
                     Uint32 format, void * pixels, int pitch)
slouken@3427
  1236
{
slouken@3549
  1237
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@3685
  1238
    SDL_Window *window = renderer->window;
slouken@3685
  1239
    SDL_VideoDisplay *display = window->display;
slouken@3549
  1240
    D3DSURFACE_DESC desc;
slouken@3549
  1241
    LPDIRECT3DSURFACE9 backBuffer;
slouken@3549
  1242
    LPDIRECT3DSURFACE9 surface;
slouken@3549
  1243
    RECT d3drect;
slouken@3549
  1244
    D3DLOCKED_RECT locked;
slouken@3549
  1245
    HRESULT result;
slouken@3427
  1246
slouken@3549
  1247
    result = IDirect3DDevice9_GetBackBuffer(data->device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuffer);
slouken@3549
  1248
    if (FAILED(result)) {
slouken@3549
  1249
        D3D_SetError("GetBackBuffer()", result);
slouken@3549
  1250
        return -1;
slouken@3549
  1251
    }
slouken@3427
  1252
slouken@3549
  1253
    result = IDirect3DSurface9_GetDesc(backBuffer, &desc);
slouken@3549
  1254
    if (FAILED(result)) {
slouken@3549
  1255
        D3D_SetError("GetDesc()", result);
slouken@3549
  1256
        IDirect3DSurface9_Release(backBuffer);
slouken@3549
  1257
        return -1;
slouken@3549
  1258
    }
slouken@3427
  1259
slouken@3549
  1260
    result = IDirect3DDevice9_CreateOffscreenPlainSurface(data->device, desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surface, NULL);
slouken@3549
  1261
    if (FAILED(result)) {
slouken@3549
  1262
        D3D_SetError("CreateOffscreenPlainSurface()", result);
slouken@3549
  1263
        IDirect3DSurface9_Release(backBuffer);
slouken@3549
  1264
        return -1;
slouken@3549
  1265
    }
slouken@3427
  1266
slouken@3549
  1267
    result = IDirect3DDevice9_GetRenderTargetData(data->device, backBuffer, surface);
slouken@3549
  1268
    if (FAILED(result)) {
slouken@3549
  1269
        D3D_SetError("GetRenderTargetData()", result);
slouken@3549
  1270
        IDirect3DSurface9_Release(surface);
slouken@3549
  1271
        IDirect3DSurface9_Release(backBuffer);
slouken@3549
  1272
        return -1;
slouken@3549
  1273
    }
slouken@3427
  1274
slouken@3549
  1275
    d3drect.left = rect->x;
slouken@3549
  1276
    d3drect.right = rect->x + rect->w;
slouken@3549
  1277
    d3drect.top = rect->y;
slouken@3549
  1278
    d3drect.bottom = rect->y + rect->h;
slouken@3427
  1279
slouken@3549
  1280
    result = IDirect3DSurface9_LockRect(surface, &locked, &d3drect, D3DLOCK_READONLY);
slouken@3549
  1281
    if (FAILED(result)) {
slouken@3549
  1282
        D3D_SetError("LockRect()", result);
slouken@3549
  1283
        IDirect3DSurface9_Release(surface);
slouken@3549
  1284
        IDirect3DSurface9_Release(backBuffer);
slouken@3549
  1285
        return -1;
slouken@3549
  1286
    }
slouken@3427
  1287
slouken@3549
  1288
    SDL_ConvertPixels(rect->w, rect->h,
slouken@3549
  1289
                      display->current_mode.format, locked.pBits, locked.Pitch,
slouken@3549
  1290
                      format, pixels, pitch);
slouken@3549
  1291
slouken@3549
  1292
    IDirect3DSurface9_UnlockRect(surface);
slouken@3549
  1293
slouken@3549
  1294
    IDirect3DSurface9_Release(surface);
slouken@3549
  1295
    IDirect3DSurface9_Release(backBuffer);
slouken@3549
  1296
slouken@3549
  1297
    return 0;
slouken@3427
  1298
}
slouken@3427
  1299
slouken@3480
  1300
static int
slouken@3480
  1301
D3D_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect,
slouken@3480
  1302
                      Uint32 format, const void * pixels, int pitch)
slouken@3480
  1303
{
slouken@3480
  1304
    /* Work in progress */
slouken@3553
  1305
    SDL_Unsupported();
slouken@3480
  1306
    return -1;
slouken@3480
  1307
}
slouken@3480
  1308
slouken@1895
  1309
static void
slouken@1913
  1310
D3D_RenderPresent(SDL_Renderer * renderer)
slouken@1895
  1311
{
slouken@1913
  1312
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@1900
  1313
    HRESULT result;
slouken@1900
  1314
slouken@1900
  1315
    if (!data->beginScene) {
slouken@1900
  1316
        IDirect3DDevice9_EndScene(data->device);
slouken@1900
  1317
        data->beginScene = SDL_TRUE;
slouken@1900
  1318
    }
slouken@1900
  1319
slouken@1975
  1320
    result = IDirect3DDevice9_TestCooperativeLevel(data->device);
slouken@1975
  1321
    if (result == D3DERR_DEVICELOST) {
slouken@1975
  1322
        /* We'll reset later */
slouken@1975
  1323
        return;
slouken@1975
  1324
    }
slouken@1975
  1325
    if (result == D3DERR_DEVICENOTRESET) {
slouken@1975
  1326
        D3D_Reset(renderer);
slouken@1975
  1327
    }
slouken@1900
  1328
    result = IDirect3DDevice9_Present(data->device, NULL, NULL, NULL, NULL);
slouken@1900
  1329
    if (FAILED(result)) {
slouken@1900
  1330
        D3D_SetError("Present()", result);
slouken@1900
  1331
    }
slouken@1895
  1332
}
slouken@1895
  1333
slouken@1895
  1334
static void
slouken@1913
  1335
D3D_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1895
  1336
{
slouken@1913
  1337
    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
slouken@1895
  1338
slouken@1895
  1339
    if (!data) {
slouken@1895
  1340
        return;
slouken@1895
  1341
    }
slouken@2973
  1342
    if (data->yuv) {
slouken@2973
  1343
        SDL_SW_DestroyYUVTexture(data->yuv);
slouken@2973
  1344
    }
slouken@1903
  1345
    if (data->texture) {
slouken@1903
  1346
        IDirect3DTexture9_Release(data->texture);
slouken@1903
  1347
    }
slouken@1895
  1348
    SDL_free(data);
slouken@1895
  1349
    texture->driverdata = NULL;
slouken@1895
  1350
}
slouken@1895
  1351
slouken@1975
  1352
static void
slouken@1913
  1353
D3D_DestroyRenderer(SDL_Renderer * renderer)
slouken@1895
  1354
{
slouken@1913
  1355
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@1895
  1356
slouken@1895
  1357
    if (data) {
slouken@1900
  1358
        if (data->device) {
slouken@1900
  1359
            IDirect3DDevice9_Release(data->device);
slouken@1900
  1360
        }
slouken@1895
  1361
        SDL_free(data);
slouken@1895
  1362
    }
slouken@1895
  1363
    SDL_free(renderer);
slouken@1895
  1364
}
slouken@1895
  1365
slouken@1895
  1366
#endif /* SDL_VIDEO_RENDER_D3D */
slouken@1895
  1367
slouken@1895
  1368
/* vi: set ts=4 sw=4 expandtab: */