src/video/win32/SDL_d3drender.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 24 Dec 2009 19:18:05 +0000
changeset 3599 0f958e527e5e
parent 3556 9c2e92de786a
child 3675 e86edac50872
permissions -rw-r--r--
Updated to compile on Windows
slouken@1895
     1
/*
slouken@1895
     2
    SDL - Simple DirectMedia Layer
slouken@2859
     3
    Copyright (C) 1997-2009 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@1895
    26
#include "SDL_win32video.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@1985
   104
static int D3D_SetTextureColorMod(SDL_Renderer * renderer,
slouken@1985
   105
                                  SDL_Texture * texture);
slouken@1985
   106
static int D3D_SetTextureAlphaMod(SDL_Renderer * renderer,
slouken@1985
   107
                                  SDL_Texture * texture);
slouken@1985
   108
static int D3D_SetTextureBlendMode(SDL_Renderer * renderer,
slouken@1985
   109
                                   SDL_Texture * texture);
slouken@1985
   110
static int D3D_SetTextureScaleMode(SDL_Renderer * renderer,
slouken@1985
   111
                                   SDL_Texture * texture);
slouken@1913
   112
static int D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1913
   113
                             const SDL_Rect * rect, const void *pixels,
slouken@1913
   114
                             int pitch);
slouken@1913
   115
static int D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1913
   116
                           const SDL_Rect * rect, int markDirty,
slouken@1913
   117
                           void **pixels, int *pitch);
slouken@1913
   118
static void D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
slouken@1913
   119
static void D3D_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1913
   120
                             int numrects, const SDL_Rect * rects);
slouken@3599
   121
static int D3D_RenderDrawPoints(SDL_Renderer * renderer,
slouken@3599
   122
                                const SDL_Point * points, int count);
slouken@3599
   123
static int D3D_RenderDrawLines(SDL_Renderer * renderer,
slouken@3599
   124
                               const SDL_Point * points, int count);
slouken@3599
   125
static int D3D_RenderDrawRects(SDL_Renderer * renderer,
slouken@3599
   126
                               const SDL_Rect ** rects, int count);
slouken@3599
   127
static int D3D_RenderFillRects(SDL_Renderer * renderer,
slouken@3599
   128
                               const SDL_Rect ** rects, int count);
slouken@1913
   129
static int D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1985
   130
                          const SDL_Rect * srcrect, const SDL_Rect * dstrect);
slouken@3427
   131
static int D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
slouken@3480
   132
                                Uint32 format, void * pixels, int pitch);
slouken@3480
   133
static int D3D_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect,
slouken@3480
   134
                                 Uint32 format, const void * pixels, int pitch);
slouken@1913
   135
static void D3D_RenderPresent(SDL_Renderer * renderer);
slouken@1913
   136
static void D3D_DestroyTexture(SDL_Renderer * renderer,
slouken@1913
   137
                               SDL_Texture * texture);
slouken@1913
   138
static void D3D_DestroyRenderer(SDL_Renderer * renderer);
slouken@1895
   139
slouken@1895
   140
slouken@1913
   141
SDL_RenderDriver D3D_RenderDriver = {
slouken@1913
   142
    D3D_CreateRenderer,
slouken@1895
   143
    {
slouken@1895
   144
     "d3d",
slouken@1965
   145
     (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY |
slouken@1975
   146
      SDL_RENDERER_PRESENTFLIP2 | SDL_RENDERER_PRESENTFLIP3 |
slouken@1965
   147
      SDL_RENDERER_PRESENTDISCARD | SDL_RENDERER_PRESENTVSYNC |
slouken@1965
   148
      SDL_RENDERER_ACCELERATED),
slouken@1985
   149
     (SDL_TEXTUREMODULATE_NONE | SDL_TEXTUREMODULATE_COLOR |
slouken@1985
   150
      SDL_TEXTUREMODULATE_ALPHA),
slouken@2884
   151
     (SDL_BLENDMODE_NONE | SDL_BLENDMODE_MASK |
slouken@2884
   152
      SDL_BLENDMODE_BLEND | SDL_BLENDMODE_ADD | SDL_BLENDMODE_MOD),
slouken@1965
   153
     (SDL_TEXTURESCALEMODE_NONE | SDL_TEXTURESCALEMODE_FAST |
slouken@1965
   154
      SDL_TEXTURESCALEMODE_SLOW | SDL_TEXTURESCALEMODE_BEST),
slouken@2972
   155
     0,
slouken@2972
   156
     {0},
slouken@1895
   157
     0,
slouken@1895
   158
     0}
slouken@1895
   159
};
slouken@1895
   160
slouken@1895
   161
typedef struct
slouken@1895
   162
{
slouken@2973
   163
    IDirect3D9 *d3d;
slouken@1895
   164
    IDirect3DDevice9 *device;
slouken@3527
   165
    UINT adapter;
slouken@1975
   166
    D3DPRESENT_PARAMETERS pparams;
slouken@3556
   167
    LPDIRECT3DPIXELSHADER9 ps_mask;
slouken@1900
   168
    SDL_bool beginScene;
slouken@1913
   169
} D3D_RenderData;
slouken@1895
   170
slouken@1895
   171
typedef struct
slouken@1895
   172
{
slouken@2973
   173
    SDL_SW_YUVTexture *yuv;
slouken@2973
   174
    Uint32 format;
slouken@1903
   175
    IDirect3DTexture9 *texture;
slouken@1913
   176
} D3D_TextureData;
slouken@1895
   177
slouken@1903
   178
typedef struct
slouken@1903
   179
{
slouken@1903
   180
    float x, y, z;
slouken@1904
   181
    float rhw;
slouken@1987
   182
    DWORD color;
slouken@1904
   183
    float u, v;
slouken@1903
   184
} Vertex;
slouken@1903
   185
slouken@1895
   186
static void
slouken@1900
   187
D3D_SetError(const char *prefix, HRESULT result)
slouken@1900
   188
{
slouken@1900
   189
    const char *error;
slouken@1900
   190
slouken@1900
   191
    switch (result) {
slouken@1900
   192
    case D3DERR_WRONGTEXTUREFORMAT:
slouken@1900
   193
        error = "WRONGTEXTUREFORMAT";
slouken@1900
   194
        break;
slouken@1900
   195
    case D3DERR_UNSUPPORTEDCOLOROPERATION:
slouken@1900
   196
        error = "UNSUPPORTEDCOLOROPERATION";
slouken@1900
   197
        break;
slouken@1900
   198
    case D3DERR_UNSUPPORTEDCOLORARG:
slouken@1900
   199
        error = "UNSUPPORTEDCOLORARG";
slouken@1900
   200
        break;
slouken@1900
   201
    case D3DERR_UNSUPPORTEDALPHAOPERATION:
slouken@1900
   202
        error = "UNSUPPORTEDALPHAOPERATION";
slouken@1900
   203
        break;
slouken@1900
   204
    case D3DERR_UNSUPPORTEDALPHAARG:
slouken@1900
   205
        error = "UNSUPPORTEDALPHAARG";
slouken@1900
   206
        break;
slouken@1900
   207
    case D3DERR_TOOMANYOPERATIONS:
slouken@1900
   208
        error = "TOOMANYOPERATIONS";
slouken@1900
   209
        break;
slouken@1900
   210
    case D3DERR_CONFLICTINGTEXTUREFILTER:
slouken@1900
   211
        error = "CONFLICTINGTEXTUREFILTER";
slouken@1900
   212
        break;
slouken@1900
   213
    case D3DERR_UNSUPPORTEDFACTORVALUE:
slouken@1900
   214
        error = "UNSUPPORTEDFACTORVALUE";
slouken@1900
   215
        break;
slouken@1900
   216
    case D3DERR_CONFLICTINGRENDERSTATE:
slouken@1900
   217
        error = "CONFLICTINGRENDERSTATE";
slouken@1900
   218
        break;
slouken@1900
   219
    case D3DERR_UNSUPPORTEDTEXTUREFILTER:
slouken@1900
   220
        error = "UNSUPPORTEDTEXTUREFILTER";
slouken@1900
   221
        break;
slouken@1900
   222
    case D3DERR_CONFLICTINGTEXTUREPALETTE:
slouken@1900
   223
        error = "CONFLICTINGTEXTUREPALETTE";
slouken@1900
   224
        break;
slouken@1900
   225
    case D3DERR_DRIVERINTERNALERROR:
slouken@1900
   226
        error = "DRIVERINTERNALERROR";
slouken@1900
   227
        break;
slouken@1900
   228
    case D3DERR_NOTFOUND:
slouken@1900
   229
        error = "NOTFOUND";
slouken@1900
   230
        break;
slouken@1900
   231
    case D3DERR_MOREDATA:
slouken@1900
   232
        error = "MOREDATA";
slouken@1900
   233
        break;
slouken@1900
   234
    case D3DERR_DEVICELOST:
slouken@1900
   235
        error = "DEVICELOST";
slouken@1900
   236
        break;
slouken@1900
   237
    case D3DERR_DEVICENOTRESET:
slouken@1900
   238
        error = "DEVICENOTRESET";
slouken@1900
   239
        break;
slouken@1900
   240
    case D3DERR_NOTAVAILABLE:
slouken@1900
   241
        error = "NOTAVAILABLE";
slouken@1900
   242
        break;
slouken@1900
   243
    case D3DERR_OUTOFVIDEOMEMORY:
slouken@1900
   244
        error = "OUTOFVIDEOMEMORY";
slouken@1900
   245
        break;
slouken@1900
   246
    case D3DERR_INVALIDDEVICE:
slouken@1900
   247
        error = "INVALIDDEVICE";
slouken@1900
   248
        break;
slouken@1900
   249
    case D3DERR_INVALIDCALL:
slouken@1900
   250
        error = "INVALIDCALL";
slouken@1900
   251
        break;
slouken@1900
   252
    case D3DERR_DRIVERINVALIDCALL:
slouken@1900
   253
        error = "DRIVERINVALIDCALL";
slouken@1900
   254
        break;
slouken@1900
   255
    case D3DERR_WASSTILLDRAWING:
slouken@1900
   256
        error = "WASSTILLDRAWING";
slouken@1900
   257
        break;
slouken@1900
   258
    default:
slouken@1900
   259
        error = "UNKNOWN";
slouken@1900
   260
        break;
slouken@1900
   261
    }
slouken@1900
   262
    SDL_SetError("%s: %s", prefix, error);
slouken@1900
   263
}
slouken@1900
   264
slouken@1903
   265
static D3DFORMAT
slouken@1903
   266
PixelFormatToD3DFMT(Uint32 format)
slouken@1895
   267
{
slouken@1903
   268
    switch (format) {
slouken@1965
   269
    case SDL_PIXELFORMAT_INDEX8:
slouken@1903
   270
        return D3DFMT_P8;
slouken@1965
   271
    case SDL_PIXELFORMAT_RGB332:
slouken@1903
   272
        return D3DFMT_R3G3B2;
slouken@1965
   273
    case SDL_PIXELFORMAT_RGB444:
slouken@1903
   274
        return D3DFMT_X4R4G4B4;
slouken@1965
   275
    case SDL_PIXELFORMAT_RGB555:
slouken@1903
   276
        return D3DFMT_X1R5G5B5;
slouken@1965
   277
    case SDL_PIXELFORMAT_ARGB4444:
slouken@1903
   278
        return D3DFMT_A4R4G4B4;
slouken@1965
   279
    case SDL_PIXELFORMAT_ARGB1555:
slouken@1903
   280
        return D3DFMT_A1R5G5B5;
slouken@1965
   281
    case SDL_PIXELFORMAT_RGB565:
slouken@1903
   282
        return D3DFMT_R5G6B5;
slouken@1965
   283
    case SDL_PIXELFORMAT_RGB888:
slouken@1903
   284
        return D3DFMT_X8R8G8B8;
slouken@1965
   285
    case SDL_PIXELFORMAT_ARGB8888:
slouken@1903
   286
        return D3DFMT_A8R8G8B8;
slouken@1965
   287
    case SDL_PIXELFORMAT_ARGB2101010:
slouken@1903
   288
        return D3DFMT_A2R10G10B10;
slouken@3495
   289
    case SDL_PIXELFORMAT_YV12:
slouken@3495
   290
        return MAKEFOURCC('Y','V','1','2');
slouken@3495
   291
    case SDL_PIXELFORMAT_IYUV:
slouken@3495
   292
        return MAKEFOURCC('I','4','2','0');
slouken@1965
   293
    case SDL_PIXELFORMAT_UYVY:
slouken@1903
   294
        return D3DFMT_UYVY;
slouken@1965
   295
    case SDL_PIXELFORMAT_YUY2:
slouken@1903
   296
        return D3DFMT_YUY2;
slouken@1903
   297
    default:
slouken@1903
   298
        return D3DFMT_UNKNOWN;
slouken@1903
   299
    }
slouken@1895
   300
}
slouken@1895
   301
slouken@3527
   302
static UINT D3D_FindAdapter(IDirect3D9 * d3d, SDL_VideoDisplay * display)
slouken@3527
   303
{
slouken@3527
   304
    SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata;
slouken@3527
   305
    UINT adapter, count;
slouken@3527
   306
slouken@3527
   307
    count = IDirect3D9_GetAdapterCount(d3d);
slouken@3527
   308
    for (adapter = 0; adapter < count; ++adapter) {
slouken@3527
   309
        HRESULT result;
slouken@3527
   310
        D3DADAPTER_IDENTIFIER9 info;
slouken@3527
   311
        char *name;
slouken@3527
   312
slouken@3527
   313
        result = IDirect3D9_GetAdapterIdentifier(d3d, adapter, 0, &info);
slouken@3527
   314
        if (FAILED(result)) {
slouken@3527
   315
            continue;
slouken@3527
   316
        }
slouken@3527
   317
        name = WIN_StringToUTF8(displaydata->DeviceName);
slouken@3527
   318
        if (SDL_strcmp(name, info.DeviceName) == 0) {
slouken@3527
   319
            SDL_free(name);
slouken@3527
   320
            return adapter;
slouken@3527
   321
        }
slouken@3527
   322
        SDL_free(name);
slouken@3527
   323
    }
slouken@3527
   324
slouken@3527
   325
    /* This should never happen, but just in case... */
slouken@3527
   326
    return D3DADAPTER_DEFAULT;
slouken@3527
   327
}
slouken@3527
   328
slouken@2973
   329
static SDL_bool
slouken@3527
   330
D3D_IsTextureFormatAvailable(IDirect3D9 * d3d, UINT adapter,
slouken@3527
   331
                             Uint32 display_format,
slouken@2990
   332
                             Uint32 texture_format)
slouken@2973
   333
{
slouken@2973
   334
    HRESULT result;
slouken@2973
   335
slouken@3527
   336
    result = IDirect3D9_CheckDeviceFormat(d3d, adapter,
slouken@2973
   337
                                          D3DDEVTYPE_HAL,
slouken@2973
   338
                                          PixelFormatToD3DFMT(display_format),
slouken@2973
   339
                                          0,
slouken@2973
   340
                                          D3DRTYPE_TEXTURE,
slouken@2990
   341
                                          PixelFormatToD3DFMT
slouken@2990
   342
                                          (texture_format));
slouken@2973
   343
    return FAILED(result) ? SDL_FALSE : SDL_TRUE;
slouken@2973
   344
}
slouken@2973
   345
slouken@2973
   346
static void
slouken@2973
   347
UpdateYUVTextureData(SDL_Texture * texture)
slouken@2973
   348
{
slouken@2973
   349
    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
slouken@2973
   350
    SDL_Rect rect;
slouken@2973
   351
    RECT d3drect;
slouken@2973
   352
    D3DLOCKED_RECT locked;
slouken@2973
   353
    HRESULT result;
slouken@2973
   354
slouken@2973
   355
    d3drect.left = 0;
slouken@2973
   356
    d3drect.right = texture->w;
slouken@2973
   357
    d3drect.top = 0;
slouken@2973
   358
    d3drect.bottom = texture->h;
slouken@2973
   359
slouken@2990
   360
    result =
slouken@2990
   361
        IDirect3DTexture9_LockRect(data->texture, 0, &locked, &d3drect, 0);
slouken@2973
   362
    if (FAILED(result)) {
slouken@2973
   363
        return;
slouken@2973
   364
    }
slouken@2973
   365
slouken@2973
   366
    rect.x = 0;
slouken@2973
   367
    rect.y = 0;
slouken@2973
   368
    rect.w = texture->w;
slouken@2973
   369
    rect.h = texture->h;
slouken@2973
   370
    SDL_SW_CopyYUVToRGB(data->yuv, &rect, data->format, texture->w,
slouken@2973
   371
                        texture->h, locked.pBits, locked.Pitch);
slouken@2973
   372
slouken@2973
   373
    IDirect3DTexture9_UnlockRect(data->texture, 0);
slouken@2973
   374
}
slouken@2973
   375
slouken@1895
   376
void
slouken@1895
   377
D3D_AddRenderDriver(_THIS)
slouken@1895
   378
{
slouken@1895
   379
    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
slouken@2972
   380
    SDL_RendererInfo *info = &D3D_RenderDriver.info;
slouken@1895
   381
slouken@1895
   382
    if (data->d3d) {
slouken@3527
   383
        int i, j;
slouken@2972
   384
        int formats[] = {
slouken@2990
   385
            SDL_PIXELFORMAT_INDEX8,
slouken@2990
   386
            SDL_PIXELFORMAT_RGB332,
slouken@2990
   387
            SDL_PIXELFORMAT_RGB444,
slouken@2990
   388
            SDL_PIXELFORMAT_RGB555,
slouken@2990
   389
            SDL_PIXELFORMAT_ARGB4444,
slouken@2990
   390
            SDL_PIXELFORMAT_ARGB1555,
slouken@2990
   391
            SDL_PIXELFORMAT_RGB565,
slouken@2990
   392
            SDL_PIXELFORMAT_RGB888,
slouken@2990
   393
            SDL_PIXELFORMAT_ARGB8888,
slouken@2990
   394
            SDL_PIXELFORMAT_ARGB2101010,
slouken@2972
   395
        };
slouken@2972
   396
slouken@3527
   397
        for (i = 0; i < _this->num_displays; ++i) {
slouken@3527
   398
            SDL_VideoDisplay *display = &_this->displays[i];
slouken@3527
   399
            SDL_DisplayMode *mode = &display->desktop_mode;
slouken@3527
   400
            UINT adapter = D3D_FindAdapter(data->d3d, display);
slouken@3527
   401
slouken@3527
   402
            /* Get the matching D3D adapter for this display */
slouken@3527
   403
            info->num_texture_formats = 0;
slouken@3527
   404
            for (j = 0; j < SDL_arraysize(formats); ++j) {
slouken@3527
   405
                if (D3D_IsTextureFormatAvailable
slouken@3527
   406
                    (data->d3d, adapter, mode->format, formats[j])) {
slouken@3527
   407
                    info->texture_formats[info->num_texture_formats++] =
slouken@3527
   408
                        formats[j];
slouken@3527
   409
                }
slouken@2972
   410
            }
slouken@3527
   411
            info->texture_formats[info->num_texture_formats++] =
slouken@3527
   412
                SDL_PIXELFORMAT_YV12;
slouken@3527
   413
            info->texture_formats[info->num_texture_formats++] =
slouken@3527
   414
                SDL_PIXELFORMAT_IYUV;
slouken@3527
   415
            info->texture_formats[info->num_texture_formats++] =
slouken@3527
   416
                SDL_PIXELFORMAT_YUY2;
slouken@3527
   417
            info->texture_formats[info->num_texture_formats++] =
slouken@3527
   418
                SDL_PIXELFORMAT_UYVY;
slouken@3527
   419
            info->texture_formats[info->num_texture_formats++] =
slouken@3527
   420
                SDL_PIXELFORMAT_YVYU;
slouken@2972
   421
slouken@3527
   422
            SDL_AddRenderDriver(display, &D3D_RenderDriver);
slouken@3520
   423
        }
slouken@1895
   424
    }
slouken@1895
   425
}
slouken@1895
   426
slouken@1895
   427
SDL_Renderer *
slouken@1913
   428
D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
slouken@1895
   429
{
slouken@1895
   430
    SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
slouken@1895
   431
    SDL_VideoData *videodata = (SDL_VideoData *) display->device->driverdata;
slouken@1895
   432
    SDL_WindowData *windowdata = (SDL_WindowData *) window->driverdata;
slouken@1895
   433
    SDL_Renderer *renderer;
slouken@1913
   434
    D3D_RenderData *data;
slouken@1900
   435
    HRESULT result;
slouken@1900
   436
    D3DPRESENT_PARAMETERS pparams;
slouken@1907
   437
    IDirect3DSwapChain9 *chain;
slouken@1925
   438
    D3DCAPS9 caps;
slouken@1895
   439
slouken@1920
   440
    renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
slouken@1895
   441
    if (!renderer) {
slouken@1895
   442
        SDL_OutOfMemory();
slouken@1895
   443
        return NULL;
slouken@1895
   444
    }
slouken@1895
   445
slouken@1920
   446
    data = (D3D_RenderData *) SDL_calloc(1, sizeof(*data));
slouken@1895
   447
    if (!data) {
slouken@1913
   448
        D3D_DestroyRenderer(renderer);
slouken@1895
   449
        SDL_OutOfMemory();
slouken@1895
   450
        return NULL;
slouken@1895
   451
    }
slouken@2973
   452
    data->d3d = videodata->d3d;
slouken@1895
   453
slouken@1975
   454
    renderer->DisplayModeChanged = D3D_DisplayModeChanged;
slouken@1913
   455
    renderer->CreateTexture = D3D_CreateTexture;
slouken@2973
   456
    renderer->QueryTexturePixels = D3D_QueryTexturePixels;
slouken@1913
   457
    renderer->SetTexturePalette = D3D_SetTexturePalette;
slouken@1913
   458
    renderer->GetTexturePalette = D3D_GetTexturePalette;
slouken@1985
   459
    renderer->SetTextureColorMod = D3D_SetTextureColorMod;
slouken@1985
   460
    renderer->SetTextureAlphaMod = D3D_SetTextureAlphaMod;
slouken@1985
   461
    renderer->SetTextureBlendMode = D3D_SetTextureBlendMode;
slouken@1985
   462
    renderer->SetTextureScaleMode = D3D_SetTextureScaleMode;
slouken@1913
   463
    renderer->UpdateTexture = D3D_UpdateTexture;
slouken@1913
   464
    renderer->LockTexture = D3D_LockTexture;
slouken@1913
   465
    renderer->UnlockTexture = D3D_UnlockTexture;
slouken@1913
   466
    renderer->DirtyTexture = D3D_DirtyTexture;
slouken@3599
   467
    renderer->RenderDrawPoints = D3D_RenderDrawPoints;
slouken@3599
   468
    renderer->RenderDrawLines = D3D_RenderDrawLines;
slouken@3599
   469
    renderer->RenderDrawRects = D3D_RenderDrawRects;
slouken@1913
   470
    renderer->RenderCopy = D3D_RenderCopy;
slouken@3427
   471
    renderer->RenderReadPixels = D3D_RenderReadPixels;
slouken@3480
   472
    renderer->RenderWritePixels = D3D_RenderWritePixels;
slouken@1913
   473
    renderer->RenderPresent = D3D_RenderPresent;
slouken@1913
   474
    renderer->DestroyTexture = D3D_DestroyTexture;
slouken@1913
   475
    renderer->DestroyRenderer = D3D_DestroyRenderer;
slouken@1913
   476
    renderer->info = D3D_RenderDriver.info;
slouken@1895
   477
    renderer->window = window->id;
slouken@1895
   478
    renderer->driverdata = data;
slouken@1895
   479
slouken@1965
   480
    renderer->info.flags = SDL_RENDERER_ACCELERATED;
slouken@1895
   481
slouken@1900
   482
    SDL_zero(pparams);
slouken@1900
   483
    pparams.BackBufferWidth = window->w;
slouken@1900
   484
    pparams.BackBufferHeight = window->h;
slouken@1903
   485
    if (window->flags & SDL_WINDOW_FULLSCREEN) {
slouken@1903
   486
        pparams.BackBufferFormat =
slouken@3519
   487
            PixelFormatToD3DFMT(window->fullscreen_mode.format);
slouken@1903
   488
    } else {
slouken@1903
   489
        pparams.BackBufferFormat = D3DFMT_UNKNOWN;
slouken@1903
   490
    }
slouken@1965
   491
    if (flags & SDL_RENDERER_PRESENTFLIP2) {
slouken@1900
   492
        pparams.BackBufferCount = 2;
slouken@1900
   493
        pparams.SwapEffect = D3DSWAPEFFECT_FLIP;
slouken@1965
   494
    } else if (flags & SDL_RENDERER_PRESENTFLIP3) {
slouken@1900
   495
        pparams.BackBufferCount = 3;
slouken@1900
   496
        pparams.SwapEffect = D3DSWAPEFFECT_FLIP;
slouken@1965
   497
    } else if (flags & SDL_RENDERER_PRESENTCOPY) {
slouken@1900
   498
        pparams.BackBufferCount = 1;
slouken@1900
   499
        pparams.SwapEffect = D3DSWAPEFFECT_COPY;
slouken@1900
   500
    } else {
slouken@1900
   501
        pparams.BackBufferCount = 1;
slouken@1900
   502
        pparams.SwapEffect = D3DSWAPEFFECT_DISCARD;
slouken@1900
   503
    }
slouken@1900
   504
    if (window->flags & SDL_WINDOW_FULLSCREEN) {
slouken@1900
   505
        pparams.Windowed = FALSE;
slouken@1903
   506
        pparams.FullScreen_RefreshRateInHz =
slouken@3519
   507
            window->fullscreen_mode.refresh_rate;
slouken@1900
   508
    } else {
slouken@1900
   509
        pparams.Windowed = TRUE;
slouken@1903
   510
        pparams.FullScreen_RefreshRateInHz = 0;
slouken@1900
   511
    }
slouken@1965
   512
    if (flags & SDL_RENDERER_PRESENTVSYNC) {
slouken@1907
   513
        pparams.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
slouken@1907
   514
    } else {
slouken@1907
   515
        pparams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
slouken@1907
   516
    }
slouken@1900
   517
slouken@3527
   518
    data->adapter = D3D_FindAdapter(videodata->d3d, display);
slouken@3527
   519
    IDirect3D9_GetDeviceCaps(videodata->d3d, data->adapter,
slouken@3197
   520
                             D3DDEVTYPE_HAL, &caps);
slouken@3197
   521
slouken@3527
   522
    result = IDirect3D9_CreateDevice(videodata->d3d, data->adapter,
slouken@1900
   523
                                     D3DDEVTYPE_HAL,
slouken@1900
   524
                                     windowdata->hwnd,
slouken@3197
   525
                                     (caps.
slouken@3197
   526
                                      DevCaps &
slouken@3197
   527
                                      D3DDEVCAPS_HWTRANSFORMANDLIGHT) ?
slouken@3197
   528
                                     D3DCREATE_HARDWARE_VERTEXPROCESSING :
slouken@1900
   529
                                     D3DCREATE_SOFTWARE_VERTEXPROCESSING,
slouken@1900
   530
                                     &pparams, &data->device);
slouken@1900
   531
    if (FAILED(result)) {
slouken@1913
   532
        D3D_DestroyRenderer(renderer);
slouken@1900
   533
        D3D_SetError("CreateDevice()", result);
slouken@1900
   534
        return NULL;
slouken@1900
   535
    }
slouken@1900
   536
    data->beginScene = SDL_TRUE;
slouken@1900
   537
slouken@1907
   538
    /* Get presentation parameters to fill info */
slouken@1907
   539
    result = IDirect3DDevice9_GetSwapChain(data->device, 0, &chain);
slouken@1907
   540
    if (FAILED(result)) {
slouken@1913
   541
        D3D_DestroyRenderer(renderer);
slouken@1907
   542
        D3D_SetError("GetSwapChain()", result);
slouken@1907
   543
        return NULL;
slouken@1907
   544
    }
slouken@1907
   545
    result = IDirect3DSwapChain9_GetPresentParameters(chain, &pparams);
slouken@1907
   546
    if (FAILED(result)) {
slouken@1907
   547
        IDirect3DSwapChain9_Release(chain);
slouken@1913
   548
        D3D_DestroyRenderer(renderer);
slouken@1907
   549
        D3D_SetError("GetPresentParameters()", result);
slouken@1907
   550
        return NULL;
slouken@1907
   551
    }
slouken@1907
   552
    IDirect3DSwapChain9_Release(chain);
slouken@1907
   553
    switch (pparams.SwapEffect) {
slouken@1907
   554
    case D3DSWAPEFFECT_COPY:
slouken@1965
   555
        renderer->info.flags |= SDL_RENDERER_PRESENTCOPY;
slouken@1907
   556
        break;
slouken@1907
   557
    case D3DSWAPEFFECT_FLIP:
slouken@1907
   558
        switch (pparams.BackBufferCount) {
slouken@1907
   559
        case 2:
slouken@1965
   560
            renderer->info.flags |= SDL_RENDERER_PRESENTFLIP2;
slouken@1907
   561
            break;
slouken@1907
   562
        case 3:
slouken@1965
   563
            renderer->info.flags |= SDL_RENDERER_PRESENTFLIP3;
slouken@1907
   564
            break;
slouken@1907
   565
        }
slouken@1907
   566
        break;
slouken@1907
   567
    case D3DSWAPEFFECT_DISCARD:
slouken@1965
   568
        renderer->info.flags |= SDL_RENDERER_PRESENTDISCARD;
slouken@1907
   569
        break;
slouken@1907
   570
    }
slouken@1907
   571
    if (pparams.PresentationInterval == D3DPRESENT_INTERVAL_ONE) {
slouken@1965
   572
        renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
slouken@1907
   573
    }
slouken@1975
   574
    data->pparams = pparams;
slouken@1907
   575
slouken@1925
   576
    IDirect3DDevice9_GetDeviceCaps(data->device, &caps);
slouken@1925
   577
    renderer->info.max_texture_width = caps.MaxTextureWidth;
slouken@1925
   578
    renderer->info.max_texture_height = caps.MaxTextureHeight;
slouken@1918
   579
slouken@1903
   580
    /* Set up parameters for rendering */
slouken@1904
   581
    IDirect3DDevice9_SetVertexShader(data->device, NULL);
slouken@1987
   582
    IDirect3DDevice9_SetFVF(data->device,
slouken@1987
   583
                            D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
slouken@1988
   584
    IDirect3DDevice9_SetRenderState(data->device, D3DRS_ZENABLE, D3DZB_FALSE);
slouken@1903
   585
    IDirect3DDevice9_SetRenderState(data->device, D3DRS_CULLMODE,
slouken@1903
   586
                                    D3DCULL_NONE);
slouken@1904
   587
    IDirect3DDevice9_SetRenderState(data->device, D3DRS_LIGHTING, FALSE);
slouken@1988
   588
    /* Enable color modulation by diffuse color */
slouken@1988
   589
    IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLOROP,
slouken@1988
   590
                                          D3DTOP_MODULATE);
slouken@1988
   591
    IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLORARG1,
slouken@1988
   592
                                          D3DTA_TEXTURE);
slouken@1988
   593
    IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLORARG2,
slouken@1988
   594
                                          D3DTA_DIFFUSE);
slouken@1988
   595
    /* Enable alpha modulation by diffuse alpha */
slouken@1988
   596
    IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAOP,
slouken@1988
   597
                                          D3DTOP_MODULATE);
slouken@1988
   598
    IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAARG1,
slouken@1988
   599
                                          D3DTA_TEXTURE);
slouken@1988
   600
    IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAARG2,
slouken@1988
   601
                                          D3DTA_DIFFUSE);
slouken@1991
   602
    /* Disable second texture stage, since we're done */
slouken@1991
   603
    IDirect3DDevice9_SetTextureStageState(data->device, 1, D3DTSS_COLOROP,
slouken@1991
   604
                                          D3DTOP_DISABLE);
slouken@1991
   605
    IDirect3DDevice9_SetTextureStageState(data->device, 1, D3DTSS_ALPHAOP,
slouken@1991
   606
                                          D3DTOP_DISABLE);
slouken@1903
   607
slouken@3556
   608
    {
slouken@3556
   609
#ifdef ASSEMBLE_SHADER
slouken@3556
   610
        const char *shader_text =
slouken@3556
   611
"ps_1_1\n"
slouken@3556
   612
"def c0, 0, 0, 0, 0.496\n"
slouken@3556
   613
"def c1, 0, 0, 0, 1\n"
slouken@3556
   614
"def c2, 0, 0, 0, -1\n"
slouken@3556
   615
"tex t0\n"
slouken@3556
   616
"mul r1, t0, v0\n"
slouken@3556
   617
"add r0, r1, c0\n"
slouken@3556
   618
"cnd r0, r0.a, c1, c2\n"
slouken@3556
   619
"add r0, r0, r1\n";
slouken@3556
   620
        LPD3DXBUFFER pCode;         // buffer with the assembled shader code
slouken@3556
   621
        LPD3DXBUFFER pErrorMsgs;    // buffer with error messages
slouken@3556
   622
        LPDWORD shader_data;
slouken@3556
   623
        DWORD   shader_size;
slouken@3556
   624
        result = D3DXAssembleShader( shader_text, SDL_strlen(shader_text), NULL, NULL, 0, &pCode, &pErrorMsgs );
slouken@3556
   625
        if (FAILED(result)) {
slouken@3556
   626
            D3D_SetError("D3DXAssembleShader()", result);
slouken@3556
   627
        }
slouken@3556
   628
        shader_data = (DWORD*)pCode->lpVtbl->GetBufferPointer(pCode);
slouken@3556
   629
        shader_size = pCode->lpVtbl->GetBufferSize(pCode);
slouken@3556
   630
#else
slouken@3556
   631
        const DWORD shader_data[] = {
slouken@3556
   632
            0xffff0101,0x00000051,0xa00f0000,0x00000000,0x00000000,0x00000000,
slouken@3556
   633
            0x3efdf3b6,0x00000051,0xa00f0001,0x00000000,0x00000000,0x00000000,
slouken@3556
   634
            0x3f800000,0x00000051,0xa00f0002,0x00000000,0x00000000,0x00000000,
slouken@3556
   635
            0xbf800000,0x00000042,0xb00f0000,0x00000005,0x800f0001,0xb0e40000,
slouken@3556
   636
            0x90e40000,0x00000002,0x800f0000,0x80e40001,0xa0e40000,0x00000050,
slouken@3556
   637
            0x800f0000,0x80ff0000,0xa0e40001,0xa0e40002,0x00000002,0x800f0000,
slouken@3556
   638
            0x80e40000,0x80e40001,0x0000ffff
slouken@3556
   639
        };
slouken@3556
   640
#endif
slouken@3556
   641
        result = IDirect3DDevice9_CreatePixelShader(data->device, shader_data, &data->ps_mask);
slouken@3556
   642
        if (FAILED(result)) {
slouken@3556
   643
            D3D_SetError("CreatePixelShader()", result);
slouken@3556
   644
        }
slouken@3556
   645
    }
slouken@3556
   646
slouken@1895
   647
    return renderer;
slouken@1895
   648
}
slouken@1895
   649
slouken@1895
   650
static int
slouken@1975
   651
D3D_Reset(SDL_Renderer * renderer)
slouken@1975
   652
{
slouken@1975
   653
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@1975
   654
    HRESULT result;
slouken@1975
   655
slouken@1975
   656
    result = IDirect3DDevice9_Reset(data->device, &data->pparams);
slouken@1975
   657
    if (FAILED(result)) {
slouken@1975
   658
        if (result == D3DERR_DEVICELOST) {
slouken@1975
   659
            /* Don't worry about it, we'll reset later... */
slouken@1975
   660
            return 0;
slouken@1975
   661
        } else {
slouken@1975
   662
            D3D_SetError("Reset()", result);
slouken@1975
   663
            return -1;
slouken@1975
   664
        }
slouken@1975
   665
    }
slouken@1975
   666
    IDirect3DDevice9_SetVertexShader(data->device, NULL);
slouken@1987
   667
    IDirect3DDevice9_SetFVF(data->device,
slouken@1987
   668
                            D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
slouken@1975
   669
    IDirect3DDevice9_SetRenderState(data->device, D3DRS_CULLMODE,
slouken@1975
   670
                                    D3DCULL_NONE);
slouken@1975
   671
    IDirect3DDevice9_SetRenderState(data->device, D3DRS_LIGHTING, FALSE);
slouken@1975
   672
    return 0;
slouken@1975
   673
}
slouken@1975
   674
slouken@1975
   675
static int
slouken@1975
   676
D3D_DisplayModeChanged(SDL_Renderer * renderer)
slouken@1975
   677
{
slouken@1975
   678
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@1975
   679
    SDL_Window *window = SDL_GetWindowFromID(renderer->window);
slouken@1975
   680
    SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
slouken@1975
   681
slouken@1975
   682
    data->pparams.BackBufferWidth = window->w;
slouken@1975
   683
    data->pparams.BackBufferHeight = window->h;
slouken@1975
   684
    if (window->flags & SDL_WINDOW_FULLSCREEN) {
slouken@1975
   685
        data->pparams.BackBufferFormat =
slouken@3519
   686
            PixelFormatToD3DFMT(window->fullscreen_mode.format);
slouken@1975
   687
    } else {
slouken@1975
   688
        data->pparams.BackBufferFormat = D3DFMT_UNKNOWN;
slouken@1975
   689
    }
slouken@1975
   690
    return D3D_Reset(renderer);
slouken@1975
   691
}
slouken@1975
   692
slouken@1975
   693
static int
slouken@1913
   694
D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1895
   695
{
slouken@1913
   696
    D3D_RenderData *renderdata = (D3D_RenderData *) renderer->driverdata;
slouken@1895
   697
    SDL_Window *window = SDL_GetWindowFromID(renderer->window);
slouken@1895
   698
    SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
slouken@2973
   699
    Uint32 display_format = display->current_mode.format;
slouken@1913
   700
    D3D_TextureData *data;
slouken@1903
   701
    HRESULT result;
slouken@1895
   702
slouken@1920
   703
    data = (D3D_TextureData *) SDL_calloc(1, sizeof(*data));
slouken@1895
   704
    if (!data) {
slouken@1895
   705
        SDL_OutOfMemory();
slouken@1895
   706
        return -1;
slouken@1895
   707
    }
slouken@1895
   708
slouken@1895
   709
    texture->driverdata = data;
slouken@1895
   710
slouken@2973
   711
    if (SDL_ISPIXELFORMAT_FOURCC(texture->format) &&
slouken@2973
   712
        (texture->format != SDL_PIXELFORMAT_YUY2 ||
slouken@3527
   713
         !D3D_IsTextureFormatAvailable(renderdata->d3d, renderdata->adapter,
slouken@3527
   714
                                       display_format, texture->format))
slouken@2990
   715
        && (texture->format != SDL_PIXELFORMAT_YVYU
slouken@3527
   716
            || !D3D_IsTextureFormatAvailable(renderdata->d3d, renderdata->adapter,
slouken@3527
   717
                                             display_format, texture->format))) {
slouken@2973
   718
        data->yuv =
slouken@2973
   719
            SDL_SW_CreateYUVTexture(texture->format, texture->w, texture->h);
slouken@2973
   720
        if (!data->yuv) {
slouken@2973
   721
            return -1;
slouken@2973
   722
        }
slouken@2973
   723
        data->format = display->current_mode.format;
slouken@2973
   724
    } else {
slouken@2973
   725
        data->format = texture->format;
slouken@2973
   726
    }
slouken@2973
   727
slouken@1903
   728
    result =
slouken@1903
   729
        IDirect3DDevice9_CreateTexture(renderdata->device, texture->w,
slouken@1903
   730
                                       texture->h, 1, 0,
slouken@2973
   731
                                       PixelFormatToD3DFMT(data->format),
slouken@2783
   732
                                       D3DPOOL_SDL, &data->texture, NULL);
slouken@1903
   733
    if (FAILED(result)) {
slouken@1903
   734
        D3D_SetError("CreateTexture()", result);
slouken@1903
   735
        return -1;
slouken@1903
   736
    }
slouken@1903
   737
slouken@1895
   738
    return 0;
slouken@1895
   739
}
slouken@1895
   740
slouken@1895
   741
static int
slouken@2973
   742
D3D_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@2973
   743
                       void **pixels, int *pitch)
slouken@2973
   744
{
slouken@2973
   745
    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
slouken@2973
   746
slouken@2973
   747
    if (data->yuv) {
slouken@2973
   748
        return SDL_SW_QueryYUVTexturePixels(data->yuv, pixels, pitch);
slouken@2973
   749
    } else {
slouken@2973
   750
        /* D3D textures don't have their pixels hanging out */
slouken@2973
   751
        return -1;
slouken@2973
   752
    }
slouken@2973
   753
}
slouken@2973
   754
slouken@2973
   755
static int
slouken@1913
   756
D3D_SetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1913
   757
                      const SDL_Color * colors, int firstcolor, int ncolors)
slouken@1895
   758
{
slouken@1913
   759
    D3D_RenderData *renderdata = (D3D_RenderData *) renderer->driverdata;
slouken@1913
   760
    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
slouken@1895
   761
slouken@1903
   762
    return 0;
slouken@1895
   763
}
slouken@1895
   764
slouken@1895
   765
static int
slouken@1913
   766
D3D_GetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1913
   767
                      SDL_Color * colors, int firstcolor, int ncolors)
slouken@1895
   768
{
slouken@1913
   769
    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
slouken@1895
   770
slouken@1903
   771
    return 0;
slouken@1895
   772
}
slouken@1895
   773
slouken@1895
   774
static int
slouken@1985
   775
D3D_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1985
   776
{
slouken@1987
   777
    return 0;
slouken@1985
   778
}
slouken@1985
   779
slouken@1985
   780
static int
slouken@1985
   781
D3D_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1985
   782
{
slouken@1987
   783
    return 0;
slouken@1985
   784
}
slouken@1985
   785
slouken@1985
   786
static int
slouken@1985
   787
D3D_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1985
   788
{
slouken@1985
   789
    switch (texture->blendMode) {
slouken@2884
   790
    case SDL_BLENDMODE_NONE:
slouken@2884
   791
    case SDL_BLENDMODE_MASK:
slouken@2884
   792
    case SDL_BLENDMODE_BLEND:
slouken@2884
   793
    case SDL_BLENDMODE_ADD:
slouken@2884
   794
    case SDL_BLENDMODE_MOD:
slouken@1985
   795
        return 0;
slouken@1985
   796
    default:
slouken@1985
   797
        SDL_Unsupported();
slouken@2884
   798
        texture->blendMode = SDL_BLENDMODE_NONE;
slouken@1985
   799
        return -1;
slouken@1985
   800
    }
slouken@1985
   801
}
slouken@1985
   802
slouken@1985
   803
static int
slouken@1985
   804
D3D_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1985
   805
{
slouken@1985
   806
    switch (texture->scaleMode) {
slouken@1985
   807
    case SDL_TEXTURESCALEMODE_NONE:
slouken@1985
   808
    case SDL_TEXTURESCALEMODE_FAST:
slouken@1985
   809
    case SDL_TEXTURESCALEMODE_SLOW:
slouken@1985
   810
    case SDL_TEXTURESCALEMODE_BEST:
slouken@1985
   811
        return 0;
slouken@1985
   812
    default:
slouken@1985
   813
        SDL_Unsupported();
slouken@1985
   814
        texture->scaleMode = SDL_TEXTURESCALEMODE_NONE;
slouken@1985
   815
        return -1;
slouken@1985
   816
    }
slouken@1985
   817
    return 0;
slouken@1985
   818
}
slouken@1985
   819
slouken@1985
   820
static int
slouken@1913
   821
D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1913
   822
                  const SDL_Rect * rect, const void *pixels, int pitch)
slouken@1895
   823
{
slouken@1913
   824
    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
slouken@1913
   825
    D3D_RenderData *renderdata = (D3D_RenderData *) renderer->driverdata;
slouken@1895
   826
slouken@2973
   827
    if (data->yuv) {
slouken@2973
   828
        if (SDL_SW_UpdateYUVTexture(data->yuv, rect, pixels, pitch) < 0) {
slouken@2973
   829
            return -1;
slouken@2973
   830
        }
slouken@2973
   831
        UpdateYUVTextureData(texture);
slouken@2973
   832
        return 0;
slouken@2973
   833
    } else {
slouken@2973
   834
#ifdef SDL_MEMORY_POOL_DEFAULT
slouken@2973
   835
        IDirect3DTexture9 *temp;
slouken@2973
   836
        RECT d3drect;
slouken@2973
   837
        D3DLOCKED_RECT locked;
slouken@2973
   838
        const Uint8 *src;
slouken@2973
   839
        Uint8 *dst;
slouken@2973
   840
        int row, length;
slouken@2973
   841
        HRESULT result;
slouken@2973
   842
slouken@2973
   843
        result =
slouken@2973
   844
            IDirect3DDevice9_CreateTexture(renderdata->device, texture->w,
slouken@2973
   845
                                           texture->h, 1, 0,
slouken@3013
   846
                                           PixelFormatToD3DFMT(texture->
slouken@3013
   847
                                                               format),
slouken@2973
   848
                                           D3DPOOL_SYSTEMMEM, &temp, NULL);
slouken@2973
   849
        if (FAILED(result)) {
slouken@2973
   850
            D3D_SetError("CreateTexture()", result);
slouken@2973
   851
            return -1;
slouken@2973
   852
        }
slouken@2973
   853
slouken@2973
   854
        d3drect.left = rect->x;
slouken@2973
   855
        d3drect.right = rect->x + rect->w;
slouken@2973
   856
        d3drect.top = rect->y;
slouken@2973
   857
        d3drect.bottom = rect->y + rect->h;
slouken@2973
   858
slouken@2973
   859
        result = IDirect3DTexture9_LockRect(temp, 0, &locked, &d3drect, 0);
slouken@2973
   860
        if (FAILED(result)) {
slouken@2973
   861
            IDirect3DTexture9_Release(temp);
slouken@2973
   862
            D3D_SetError("LockRect()", result);
slouken@2973
   863
            return -1;
slouken@2973
   864
        }
slouken@2973
   865
slouken@2973
   866
        src = pixels;
slouken@2973
   867
        dst = locked.pBits;
slouken@2973
   868
        length = rect->w * SDL_BYTESPERPIXEL(texture->format);
slouken@2973
   869
        for (row = 0; row < rect->h; ++row) {
slouken@2973
   870
            SDL_memcpy(dst, src, length);
slouken@2973
   871
            src += pitch;
slouken@2973
   872
            dst += locked.Pitch;
slouken@2973
   873
        }
slouken@2973
   874
        IDirect3DTexture9_UnlockRect(temp, 0);
slouken@2973
   875
slouken@2973
   876
        result =
slouken@2973
   877
            IDirect3DDevice9_UpdateTexture(renderdata->device,
slouken@2973
   878
                                           (IDirect3DBaseTexture9 *) temp,
slouken@2973
   879
                                           (IDirect3DBaseTexture9 *)
slouken@2973
   880
                                           data->texture);
slouken@2973
   881
        IDirect3DTexture9_Release(temp);
slouken@2973
   882
        if (FAILED(result)) {
slouken@2973
   883
            D3D_SetError("UpdateTexture()", result);
slouken@2973
   884
            return -1;
slouken@2973
   885
        }
slouken@2973
   886
#else
slouken@2973
   887
        RECT d3drect;
slouken@2973
   888
        D3DLOCKED_RECT locked;
slouken@2973
   889
        const Uint8 *src;
slouken@2973
   890
        Uint8 *dst;
slouken@2973
   891
        int row, length;
slouken@2973
   892
        HRESULT result;
slouken@2973
   893
slouken@2973
   894
        d3drect.left = rect->x;
slouken@2973
   895
        d3drect.right = rect->x + rect->w;
slouken@2973
   896
        d3drect.top = rect->y;
slouken@2973
   897
        d3drect.bottom = rect->y + rect->h;
slouken@2973
   898
slouken@2973
   899
        result =
slouken@2990
   900
            IDirect3DTexture9_LockRect(data->texture, 0, &locked, &d3drect,
slouken@2990
   901
                                       0);
slouken@2973
   902
        if (FAILED(result)) {
slouken@2973
   903
            D3D_SetError("LockRect()", result);
slouken@2973
   904
            return -1;
slouken@2973
   905
        }
slouken@2973
   906
slouken@2973
   907
        src = pixels;
slouken@2973
   908
        dst = locked.pBits;
slouken@2973
   909
        length = rect->w * SDL_BYTESPERPIXEL(texture->format);
slouken@2973
   910
        for (row = 0; row < rect->h; ++row) {
slouken@2973
   911
            SDL_memcpy(dst, src, length);
slouken@2973
   912
            src += pitch;
slouken@2973
   913
            dst += locked.Pitch;
slouken@2973
   914
        }
slouken@2973
   915
        IDirect3DTexture9_UnlockRect(data->texture, 0);
slouken@2973
   916
#endif // SDL_MEMORY_POOL_DEFAULT
slouken@2973
   917
slouken@2973
   918
        return 0;
slouken@1903
   919
    }
slouken@1895
   920
}
slouken@1895
   921
slouken@1895
   922
static int
slouken@1913
   923
D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1913
   924
                const SDL_Rect * rect, int markDirty, void **pixels,
slouken@1913
   925
                int *pitch)
slouken@1895
   926
{
slouken@1913
   927
    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
slouken@1895
   928
slouken@2973
   929
    if (data->yuv) {
slouken@2973
   930
        return SDL_SW_LockYUVTexture(data->yuv, rect, markDirty, pixels,
slouken@2973
   931
                                     pitch);
slouken@2973
   932
    } else {
slouken@2973
   933
        RECT d3drect;
slouken@2973
   934
        D3DLOCKED_RECT locked;
slouken@2973
   935
        HRESULT result;
slouken@1903
   936
slouken@2973
   937
        d3drect.left = rect->x;
slouken@2973
   938
        d3drect.right = rect->x + rect->w;
slouken@2973
   939
        d3drect.top = rect->y;
slouken@2973
   940
        d3drect.bottom = rect->y + rect->h;
slouken@2973
   941
slouken@2973
   942
        result =
slouken@2973
   943
            IDirect3DTexture9_LockRect(data->texture, 0, &locked, &d3drect,
slouken@2990
   944
                                       markDirty ? 0 :
slouken@2990
   945
                                       D3DLOCK_NO_DIRTY_UPDATE);
slouken@2973
   946
        if (FAILED(result)) {
slouken@2973
   947
            D3D_SetError("LockRect()", result);
slouken@2973
   948
            return -1;
slouken@2973
   949
        }
slouken@2973
   950
        *pixels = locked.pBits;
slouken@2973
   951
        *pitch = locked.Pitch;
slouken@2973
   952
        return 0;
slouken@1903
   953
    }
slouken@1895
   954
}
slouken@1895
   955
slouken@1895
   956
static void
slouken@1913
   957
D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1895
   958
{
slouken@1913
   959
    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
slouken@1895
   960
slouken@2973
   961
    if (data->yuv) {
slouken@2973
   962
        SDL_SW_UnlockYUVTexture(data->yuv);
slouken@2973
   963
        UpdateYUVTextureData(texture);
slouken@2973
   964
    } else {
slouken@2973
   965
        IDirect3DTexture9_UnlockRect(data->texture, 0);
slouken@2973
   966
    }
slouken@1895
   967
}
slouken@1895
   968
slouken@1895
   969
static void
slouken@1913
   970
D3D_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture, int numrects,
slouken@1913
   971
                 const SDL_Rect * rects)
slouken@1895
   972
{
slouken@1913
   973
    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
slouken@1903
   974
    RECT d3drect;
slouken@1903
   975
    int i;
slouken@1903
   976
slouken@1903
   977
    for (i = 0; i < numrects; ++i) {
slouken@1903
   978
        const SDL_Rect *rect = &rects[i];
slouken@1903
   979
slouken@1903
   980
        d3drect.left = rect->x;
slouken@1903
   981
        d3drect.right = rect->x + rect->w;
slouken@1903
   982
        d3drect.top = rect->y;
slouken@1903
   983
        d3drect.bottom = rect->y + rect->h;
slouken@1903
   984
slouken@1903
   985
        IDirect3DTexture9_AddDirtyRect(data->texture, &d3drect);
slouken@1903
   986
    }
slouken@1895
   987
}
slouken@1895
   988
slouken@2932
   989
static void
slouken@2933
   990
D3D_SetBlendMode(D3D_RenderData * data, int blendMode)
slouken@2932
   991
{
slouken@2932
   992
    switch (blendMode) {
slouken@2932
   993
    case SDL_BLENDMODE_NONE:
slouken@2932
   994
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
slouken@2932
   995
                                        FALSE);
slouken@2932
   996
        break;
slouken@2932
   997
    case SDL_BLENDMODE_MASK:
slouken@2932
   998
    case SDL_BLENDMODE_BLEND:
slouken@2932
   999
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
slouken@2932
  1000
                                        TRUE);
slouken@2932
  1001
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
slouken@2932
  1002
                                        D3DBLEND_SRCALPHA);
slouken@2932
  1003
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
slouken@2932
  1004
                                        D3DBLEND_INVSRCALPHA);
slouken@2932
  1005
        break;
slouken@2932
  1006
    case SDL_BLENDMODE_ADD:
slouken@2932
  1007
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
slouken@2932
  1008
                                        TRUE);
slouken@2932
  1009
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
slouken@2932
  1010
                                        D3DBLEND_SRCALPHA);
slouken@2932
  1011
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
slouken@2932
  1012
                                        D3DBLEND_ONE);
slouken@2932
  1013
        break;
slouken@2932
  1014
    case SDL_BLENDMODE_MOD:
slouken@2932
  1015
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
slouken@2932
  1016
                                        TRUE);
slouken@2932
  1017
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
slouken@2932
  1018
                                        D3DBLEND_ZERO);
slouken@2932
  1019
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
slouken@2932
  1020
                                        D3DBLEND_SRCCOLOR);
slouken@2932
  1021
        break;
slouken@2932
  1022
    }
slouken@2932
  1023
}
slouken@2932
  1024
slouken@1895
  1025
static int
slouken@3599
  1026
D3D_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points,
slouken@3599
  1027
                     int count)
slouken@1895
  1028
{
slouken@1913
  1029
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@2932
  1030
    DWORD color;
slouken@3536
  1031
    Vertex *vertices;
slouken@3536
  1032
    int i;
slouken@1900
  1033
    HRESULT result;
slouken@1895
  1034
slouken@1900
  1035
    if (data->beginScene) {
slouken@1900
  1036
        IDirect3DDevice9_BeginScene(data->device);
slouken@1900
  1037
        data->beginScene = SDL_FALSE;
slouken@1900
  1038
    }
slouken@1895
  1039
slouken@2932
  1040
    D3D_SetBlendMode(data, renderer->blendMode);
slouken@2932
  1041
slouken@2933
  1042
    result =
slouken@2933
  1043
        IDirect3DDevice9_SetTexture(data->device, 0,
slouken@2933
  1044
                                    (IDirect3DBaseTexture9 *) 0);
slouken@2932
  1045
    if (FAILED(result)) {
slouken@2932
  1046
        D3D_SetError("SetTexture()", result);
slouken@2932
  1047
        return -1;
slouken@2932
  1048
    }
slouken@3536
  1049
slouken@3536
  1050
    color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
slouken@3536
  1051
slouken@3536
  1052
    vertices = SDL_stack_alloc(Vertex, count);
slouken@3536
  1053
    for (i = 0; i < count; ++i) {
slouken@3536
  1054
        vertices[i].x = (float) points[i].x;
slouken@3536
  1055
        vertices[i].y = (float) points[i].y;
slouken@3536
  1056
        vertices[i].z = 0.0f;
slouken@3536
  1057
        vertices[i].rhw = 1.0f;
slouken@3536
  1058
        vertices[i].color = color;
slouken@3536
  1059
        vertices[i].u = 0.0f;
slouken@3536
  1060
        vertices[i].v = 0.0f;
slouken@3536
  1061
    }
slouken@1903
  1062
    result =
slouken@3536
  1063
        IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_POINTLIST, count,
slouken@2932
  1064
                                         vertices, sizeof(*vertices));
slouken@3536
  1065
    SDL_stack_free(vertices);
slouken@1900
  1066
    if (FAILED(result)) {
slouken@2932
  1067
        D3D_SetError("DrawPrimitiveUP()", result);
slouken@2932
  1068
        return -1;
slouken@2932
  1069
    }
slouken@2932
  1070
    return 0;
slouken@2932
  1071
}
slouken@2932
  1072
slouken@2932
  1073
static int
slouken@3599
  1074
D3D_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points,
slouken@3599
  1075
                    int count)
slouken@2932
  1076
{
slouken@2932
  1077
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@2932
  1078
    DWORD color;
slouken@3536
  1079
    Vertex *vertices;
slouken@3536
  1080
    int i;
slouken@2932
  1081
    HRESULT result;
slouken@2932
  1082
slouken@2932
  1083
    if (data->beginScene) {
slouken@2932
  1084
        IDirect3DDevice9_BeginScene(data->device);
slouken@2932
  1085
        data->beginScene = SDL_FALSE;
slouken@2932
  1086
    }
slouken@2932
  1087
slouken@2932
  1088
    D3D_SetBlendMode(data, renderer->blendMode);
slouken@2932
  1089
slouken@2933
  1090
    result =
slouken@2933
  1091
        IDirect3DDevice9_SetTexture(data->device, 0,
slouken@2933
  1092
                                    (IDirect3DBaseTexture9 *) 0);
slouken@2932
  1093
    if (FAILED(result)) {
slouken@2932
  1094
        D3D_SetError("SetTexture()", result);
slouken@2932
  1095
        return -1;
slouken@2932
  1096
    }
slouken@3536
  1097
slouken@3536
  1098
    color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
slouken@3536
  1099
slouken@3536
  1100
    vertices = SDL_stack_alloc(Vertex, count);
slouken@3536
  1101
    for (i = 0; i < count; ++i) {
slouken@3536
  1102
        vertices[i].x = (float) points[i].x;
slouken@3536
  1103
        vertices[i].y = (float) points[i].y;
slouken@3536
  1104
        vertices[i].z = 0.0f;
slouken@3536
  1105
        vertices[i].rhw = 1.0f;
slouken@3536
  1106
        vertices[i].color = color;
slouken@3536
  1107
        vertices[i].u = 0.0f;
slouken@3536
  1108
        vertices[i].v = 0.0f;
slouken@3536
  1109
    }
slouken@2932
  1110
    result =
slouken@3551
  1111
        IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_LINESTRIP, count-1,
slouken@2932
  1112
                                         vertices, sizeof(*vertices));
slouken@3551
  1113
slouken@3551
  1114
    /* DirectX 9 has the same line rasterization semantics as GDI,
slouken@3551
  1115
       so we need to close the endpoint of the line */
slouken@3551
  1116
    if (points[0].x != points[count-1].x || points[0].y != points[count-1].y) {
slouken@3551
  1117
        vertices[0].x = (float) points[count-1].x;
slouken@3551
  1118
        vertices[0].y = (float) points[count-1].y;
slouken@3551
  1119
        result = IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_POINTLIST, 1, vertices, sizeof(*vertices));
slouken@3551
  1120
    }
slouken@3551
  1121
slouken@3536
  1122
    SDL_stack_free(vertices);
slouken@2932
  1123
    if (FAILED(result)) {
slouken@2932
  1124
        D3D_SetError("DrawPrimitiveUP()", result);
slouken@2932
  1125
        return -1;
slouken@2932
  1126
    }
slouken@2932
  1127
    return 0;
slouken@2932
  1128
}
slouken@2932
  1129
slouken@2932
  1130
static int
slouken@3599
  1131
D3D_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects,
slouken@3599
  1132
                    int count)
slouken@3599
  1133
{
slouken@3599
  1134
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@3599
  1135
    DWORD color;
slouken@3599
  1136
    int i;
slouken@3599
  1137
    Vertex vertices[5];
slouken@3599
  1138
    HRESULT result;
slouken@3599
  1139
slouken@3599
  1140
    if (data->beginScene) {
slouken@3599
  1141
        IDirect3DDevice9_BeginScene(data->device);
slouken@3599
  1142
        data->beginScene = SDL_FALSE;
slouken@3599
  1143
    }
slouken@3599
  1144
slouken@3599
  1145
    D3D_SetBlendMode(data, renderer->blendMode);
slouken@3599
  1146
slouken@3599
  1147
    result =
slouken@3599
  1148
        IDirect3DDevice9_SetTexture(data->device, 0,
slouken@3599
  1149
                                    (IDirect3DBaseTexture9 *) 0);
slouken@3599
  1150
    if (FAILED(result)) {
slouken@3599
  1151
        D3D_SetError("SetTexture()", result);
slouken@3599
  1152
        return -1;
slouken@3599
  1153
    }
slouken@3599
  1154
slouken@3599
  1155
    color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
slouken@3599
  1156
slouken@3599
  1157
    for (i = 0; i < SDL_arraysize(vertices); ++i) {
slouken@3599
  1158
        vertices[i].z = 0.0f;
slouken@3599
  1159
        vertices[i].rhw = 1.0f;
slouken@3599
  1160
        vertices[i].color = color;
slouken@3599
  1161
        vertices[i].u = 0.0f;
slouken@3599
  1162
        vertices[i].v = 0.0f;
slouken@3599
  1163
    }
slouken@3599
  1164
slouken@3599
  1165
    for (i = 0; i < count; ++i) {
slouken@3599
  1166
        const SDL_Rect *rect = rects[i];
slouken@3599
  1167
slouken@3599
  1168
        vertices[0].x = (float) rect->x;
slouken@3599
  1169
        vertices[0].y = (float) rect->y;
slouken@3599
  1170
slouken@3599
  1171
        vertices[1].x = (float) rect->x+rect->w-1;
slouken@3599
  1172
        vertices[1].y = (float) rect->y;
slouken@3599
  1173
slouken@3599
  1174
        vertices[2].x = (float) rect->x+rect->w-1;
slouken@3599
  1175
        vertices[2].y = (float) rect->y+rect->h-1;
slouken@3599
  1176
slouken@3599
  1177
        vertices[3].x = (float) rect->x;
slouken@3599
  1178
        vertices[3].y = (float) rect->y+rect->h-1;
slouken@3599
  1179
slouken@3599
  1180
        vertices[4].x = (float) rect->x;
slouken@3599
  1181
        vertices[4].y = (float) rect->y;
slouken@3599
  1182
slouken@3599
  1183
        result =
slouken@3599
  1184
            IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_LINESTRIP, 4,
slouken@3599
  1185
                                             vertices, sizeof(*vertices));
slouken@3599
  1186
slouken@3599
  1187
        if (FAILED(result)) {
slouken@3599
  1188
            D3D_SetError("DrawPrimitiveUP()", result);
slouken@3599
  1189
            return -1;
slouken@3599
  1190
        }
slouken@3599
  1191
    }
slouken@3599
  1192
    return 0;
slouken@3599
  1193
}
slouken@3599
  1194
slouken@3599
  1195
static int
slouken@3599
  1196
D3D_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects,
slouken@3599
  1197
                    int count)
slouken@2932
  1198
{
slouken@2932
  1199
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@3536
  1200
    DWORD color;
slouken@3536
  1201
    int i;
slouken@2932
  1202
    float minx, miny, maxx, maxy;
slouken@2932
  1203
    Vertex vertices[4];
slouken@2932
  1204
    HRESULT result;
slouken@2932
  1205
slouken@2932
  1206
    if (data->beginScene) {
slouken@2932
  1207
        IDirect3DDevice9_BeginScene(data->device);
slouken@2932
  1208
        data->beginScene = SDL_FALSE;
slouken@2932
  1209
    }
slouken@2932
  1210
slouken@2932
  1211
    D3D_SetBlendMode(data, renderer->blendMode);
slouken@2932
  1212
slouken@2933
  1213
    result =
slouken@2933
  1214
        IDirect3DDevice9_SetTexture(data->device, 0,
slouken@2933
  1215
                                    (IDirect3DBaseTexture9 *) 0);
slouken@2932
  1216
    if (FAILED(result)) {
slouken@2932
  1217
        D3D_SetError("SetTexture()", result);
slouken@2932
  1218
        return -1;
slouken@2932
  1219
    }
slouken@3536
  1220
slouken@3536
  1221
    color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
slouken@3536
  1222
slouken@3536
  1223
    for (i = 0; i < count; ++i) {
slouken@3536
  1224
        const SDL_Rect *rect = rects[i];
slouken@3536
  1225
slouken@3536
  1226
        minx = (float) rect->x;
slouken@3536
  1227
        miny = (float) rect->y;
slouken@3536
  1228
        maxx = (float) rect->x + rect->w;
slouken@3536
  1229
        maxy = (float) rect->y + rect->h;
slouken@3536
  1230
slouken@3536
  1231
        vertices[0].x = minx;
slouken@3536
  1232
        vertices[0].y = miny;
slouken@3536
  1233
        vertices[0].z = 0.0f;
slouken@3536
  1234
        vertices[0].rhw = 1.0f;
slouken@3536
  1235
        vertices[0].color = color;
slouken@3536
  1236
        vertices[0].u = 0.0f;
slouken@3536
  1237
        vertices[0].v = 0.0f;
slouken@3536
  1238
slouken@3536
  1239
        vertices[1].x = maxx;
slouken@3536
  1240
        vertices[1].y = miny;
slouken@3536
  1241
        vertices[1].z = 0.0f;
slouken@3536
  1242
        vertices[1].rhw = 1.0f;
slouken@3536
  1243
        vertices[1].color = color;
slouken@3536
  1244
        vertices[1].u = 0.0f;
slouken@3536
  1245
        vertices[1].v = 0.0f;
slouken@3536
  1246
slouken@3536
  1247
        vertices[2].x = maxx;
slouken@3536
  1248
        vertices[2].y = maxy;
slouken@3536
  1249
        vertices[2].z = 0.0f;
slouken@3536
  1250
        vertices[2].rhw = 1.0f;
slouken@3536
  1251
        vertices[2].color = color;
slouken@3536
  1252
        vertices[2].u = 0.0f;
slouken@3536
  1253
        vertices[2].v = 0.0f;
slouken@3536
  1254
slouken@3536
  1255
        vertices[3].x = minx;
slouken@3536
  1256
        vertices[3].y = maxy;
slouken@3536
  1257
        vertices[3].z = 0.0f;
slouken@3536
  1258
        vertices[3].rhw = 1.0f;
slouken@3536
  1259
        vertices[3].color = color;
slouken@3536
  1260
        vertices[3].u = 0.0f;
slouken@3536
  1261
        vertices[3].v = 0.0f;
slouken@3536
  1262
slouken@3536
  1263
        result =
slouken@3536
  1264
            IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN,
slouken@3536
  1265
                                             2, vertices, sizeof(*vertices));
slouken@3536
  1266
        if (FAILED(result)) {
slouken@3536
  1267
            D3D_SetError("DrawPrimitiveUP()", result);
slouken@3536
  1268
            return -1;
slouken@3536
  1269
        }
slouken@1900
  1270
    }
slouken@1895
  1271
    return 0;
slouken@1895
  1272
}
slouken@1895
  1273
slouken@1895
  1274
static int
slouken@1913
  1275
D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1985
  1276
               const SDL_Rect * srcrect, const SDL_Rect * dstrect)
slouken@1895
  1277
{
slouken@1913
  1278
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@1913
  1279
    D3D_TextureData *texturedata = (D3D_TextureData *) texture->driverdata;
slouken@3556
  1280
    LPDIRECT3DPIXELSHADER9 shader = NULL;
slouken@1903
  1281
    float minx, miny, maxx, maxy;
slouken@1904
  1282
    float minu, maxu, minv, maxv;
slouken@1987
  1283
    DWORD color;
slouken@1903
  1284
    Vertex vertices[4];
slouken@1903
  1285
    HRESULT result;
slouken@1895
  1286
slouken@1900
  1287
    if (data->beginScene) {
slouken@1900
  1288
        IDirect3DDevice9_BeginScene(data->device);
slouken@1900
  1289
        data->beginScene = SDL_FALSE;
slouken@1900
  1290
    }
slouken@1903
  1291
slouken@3279
  1292
    minx = (float) dstrect->x - 0.5f;
slouken@3279
  1293
    miny = (float) dstrect->y - 0.5f;
slouken@3279
  1294
    maxx = (float) dstrect->x + dstrect->w - 0.5f;
slouken@3279
  1295
    maxy = (float) dstrect->y + dstrect->h - 0.5f;
slouken@1903
  1296
slouken@1904
  1297
    minu = (float) srcrect->x / texture->w;
slouken@1904
  1298
    maxu = (float) (srcrect->x + srcrect->w) / texture->w;
slouken@1904
  1299
    minv = (float) srcrect->y / texture->h;
slouken@1904
  1300
    maxv = (float) (srcrect->y + srcrect->h) / texture->h;
slouken@1903
  1301
slouken@1987
  1302
    color = D3DCOLOR_ARGB(texture->a, texture->r, texture->g, texture->b);
slouken@1987
  1303
slouken@1903
  1304
    vertices[0].x = minx;
slouken@1903
  1305
    vertices[0].y = miny;
slouken@1903
  1306
    vertices[0].z = 0.0f;
slouken@1904
  1307
    vertices[0].rhw = 1.0f;
slouken@1987
  1308
    vertices[0].color = color;
slouken@1904
  1309
    vertices[0].u = minu;
slouken@1904
  1310
    vertices[0].v = minv;
slouken@1904
  1311
slouken@1903
  1312
    vertices[1].x = maxx;
slouken@1903
  1313
    vertices[1].y = miny;
slouken@1903
  1314
    vertices[1].z = 0.0f;
slouken@1904
  1315
    vertices[1].rhw = 1.0f;
slouken@1987
  1316
    vertices[1].color = color;
slouken@1904
  1317
    vertices[1].u = maxu;
slouken@1904
  1318
    vertices[1].v = minv;
slouken@1904
  1319
slouken@1903
  1320
    vertices[2].x = maxx;
slouken@1903
  1321
    vertices[2].y = maxy;
slouken@1903
  1322
    vertices[2].z = 0.0f;
slouken@1904
  1323
    vertices[2].rhw = 1.0f;
slouken@1987
  1324
    vertices[2].color = color;
slouken@1904
  1325
    vertices[2].u = maxu;
slouken@1904
  1326
    vertices[2].v = maxv;
slouken@1904
  1327
slouken@1903
  1328
    vertices[3].x = minx;
slouken@1903
  1329
    vertices[3].y = maxy;
slouken@1903
  1330
    vertices[3].z = 0.0f;
slouken@1904
  1331
    vertices[3].rhw = 1.0f;
slouken@1987
  1332
    vertices[3].color = color;
slouken@1904
  1333
    vertices[3].u = minu;
slouken@1904
  1334
    vertices[3].v = maxv;
slouken@1903
  1335
slouken@2932
  1336
    D3D_SetBlendMode(data, texture->blendMode);
slouken@1916
  1337
slouken@3556
  1338
    if (texture->blendMode == SDL_BLENDMODE_MASK) {
slouken@3556
  1339
        shader = data->ps_mask;
slouken@3556
  1340
    }
slouken@3556
  1341
slouken@1985
  1342
    switch (texture->scaleMode) {
slouken@1965
  1343
    case SDL_TEXTURESCALEMODE_NONE:
slouken@1965
  1344
    case SDL_TEXTURESCALEMODE_FAST:
slouken@1917
  1345
        IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MINFILTER,
slouken@1917
  1346
                                         D3DTEXF_POINT);
slouken@1917
  1347
        IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MAGFILTER,
slouken@1917
  1348
                                         D3DTEXF_POINT);
slouken@1917
  1349
        break;
slouken@1965
  1350
    case SDL_TEXTURESCALEMODE_SLOW:
slouken@1917
  1351
        IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MINFILTER,
slouken@1917
  1352
                                         D3DTEXF_LINEAR);
slouken@1917
  1353
        IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MAGFILTER,
slouken@1917
  1354
                                         D3DTEXF_LINEAR);
slouken@1917
  1355
        break;
slouken@1965
  1356
    case SDL_TEXTURESCALEMODE_BEST:
slouken@1917
  1357
        IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MINFILTER,
slouken@1917
  1358
                                         D3DTEXF_GAUSSIANQUAD);
slouken@1917
  1359
        IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MAGFILTER,
slouken@1917
  1360
                                         D3DTEXF_GAUSSIANQUAD);
slouken@1917
  1361
        break;
slouken@1917
  1362
    }
slouken@1917
  1363
slouken@1903
  1364
    result =
slouken@2735
  1365
        IDirect3DDevice9_SetTexture(data->device, 0, (IDirect3DBaseTexture9 *)
slouken@2735
  1366
                                    texturedata->texture);
slouken@1903
  1367
    if (FAILED(result)) {
slouken@1903
  1368
        D3D_SetError("SetTexture()", result);
slouken@1903
  1369
        return -1;
slouken@1903
  1370
    }
slouken@3556
  1371
    if (shader) {
slouken@3556
  1372
        result = IDirect3DDevice9_SetPixelShader(data->device, shader);
slouken@3556
  1373
        if (FAILED(result)) {
slouken@3556
  1374
            D3D_SetError("SetShader()", result);
slouken@3556
  1375
            return -1;
slouken@3556
  1376
        }
slouken@3556
  1377
    }
slouken@1903
  1378
    result =
slouken@1903
  1379
        IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN, 2,
slouken@1903
  1380
                                         vertices, sizeof(*vertices));
slouken@1903
  1381
    if (FAILED(result)) {
slouken@1903
  1382
        D3D_SetError("DrawPrimitiveUP()", result);
slouken@1903
  1383
        return -1;
slouken@1903
  1384
    }
slouken@3556
  1385
    if (shader) {
slouken@3556
  1386
        result = IDirect3DDevice9_SetPixelShader(data->device, NULL);
slouken@3556
  1387
        if (FAILED(result)) {
slouken@3556
  1388
            D3D_SetError("SetShader()", result);
slouken@3556
  1389
            return -1;
slouken@3556
  1390
        }
slouken@3556
  1391
    }
slouken@1895
  1392
    return 0;
slouken@1895
  1393
}
slouken@1895
  1394
slouken@3427
  1395
static int
slouken@3427
  1396
D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
slouken@3480
  1397
                     Uint32 format, void * pixels, int pitch)
slouken@3427
  1398
{
slouken@3549
  1399
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@3549
  1400
    SDL_Window *window = SDL_GetWindowFromID(renderer->window);
slouken@3549
  1401
    SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
slouken@3549
  1402
    D3DSURFACE_DESC desc;
slouken@3549
  1403
    LPDIRECT3DSURFACE9 backBuffer;
slouken@3549
  1404
    LPDIRECT3DSURFACE9 surface;
slouken@3549
  1405
    RECT d3drect;
slouken@3549
  1406
    D3DLOCKED_RECT locked;
slouken@3549
  1407
    HRESULT result;
slouken@3427
  1408
slouken@3549
  1409
    result = IDirect3DDevice9_GetBackBuffer(data->device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuffer);
slouken@3549
  1410
    if (FAILED(result)) {
slouken@3549
  1411
        D3D_SetError("GetBackBuffer()", result);
slouken@3549
  1412
        return -1;
slouken@3549
  1413
    }
slouken@3427
  1414
slouken@3549
  1415
    result = IDirect3DSurface9_GetDesc(backBuffer, &desc);
slouken@3549
  1416
    if (FAILED(result)) {
slouken@3549
  1417
        D3D_SetError("GetDesc()", result);
slouken@3549
  1418
        IDirect3DSurface9_Release(backBuffer);
slouken@3549
  1419
        return -1;
slouken@3549
  1420
    }
slouken@3427
  1421
slouken@3549
  1422
    result = IDirect3DDevice9_CreateOffscreenPlainSurface(data->device, desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surface, NULL);
slouken@3549
  1423
    if (FAILED(result)) {
slouken@3549
  1424
        D3D_SetError("CreateOffscreenPlainSurface()", result);
slouken@3549
  1425
        IDirect3DSurface9_Release(backBuffer);
slouken@3549
  1426
        return -1;
slouken@3549
  1427
    }
slouken@3427
  1428
slouken@3549
  1429
    result = IDirect3DDevice9_GetRenderTargetData(data->device, backBuffer, surface);
slouken@3549
  1430
    if (FAILED(result)) {
slouken@3549
  1431
        D3D_SetError("GetRenderTargetData()", result);
slouken@3549
  1432
        IDirect3DSurface9_Release(surface);
slouken@3549
  1433
        IDirect3DSurface9_Release(backBuffer);
slouken@3549
  1434
        return -1;
slouken@3549
  1435
    }
slouken@3427
  1436
slouken@3549
  1437
    d3drect.left = rect->x;
slouken@3549
  1438
    d3drect.right = rect->x + rect->w;
slouken@3549
  1439
    d3drect.top = rect->y;
slouken@3549
  1440
    d3drect.bottom = rect->y + rect->h;
slouken@3427
  1441
slouken@3549
  1442
    result = IDirect3DSurface9_LockRect(surface, &locked, &d3drect, D3DLOCK_READONLY);
slouken@3549
  1443
    if (FAILED(result)) {
slouken@3549
  1444
        D3D_SetError("LockRect()", result);
slouken@3549
  1445
        IDirect3DSurface9_Release(surface);
slouken@3549
  1446
        IDirect3DSurface9_Release(backBuffer);
slouken@3549
  1447
        return -1;
slouken@3549
  1448
    }
slouken@3427
  1449
slouken@3549
  1450
    SDL_ConvertPixels(rect->w, rect->h,
slouken@3549
  1451
                      display->current_mode.format, locked.pBits, locked.Pitch,
slouken@3549
  1452
                      format, pixels, pitch);
slouken@3549
  1453
slouken@3549
  1454
    IDirect3DSurface9_UnlockRect(surface);
slouken@3549
  1455
slouken@3549
  1456
    IDirect3DSurface9_Release(surface);
slouken@3549
  1457
    IDirect3DSurface9_Release(backBuffer);
slouken@3549
  1458
slouken@3549
  1459
    return 0;
slouken@3427
  1460
}
slouken@3427
  1461
slouken@3480
  1462
static int
slouken@3480
  1463
D3D_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect,
slouken@3480
  1464
                      Uint32 format, const void * pixels, int pitch)
slouken@3480
  1465
{
slouken@3480
  1466
    /* Work in progress */
slouken@3553
  1467
    SDL_Unsupported();
slouken@3480
  1468
    return -1;
slouken@3480
  1469
}
slouken@3480
  1470
slouken@1895
  1471
static void
slouken@1913
  1472
D3D_RenderPresent(SDL_Renderer * renderer)
slouken@1895
  1473
{
slouken@1913
  1474
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@1900
  1475
    HRESULT result;
slouken@1900
  1476
slouken@1900
  1477
    if (!data->beginScene) {
slouken@1900
  1478
        IDirect3DDevice9_EndScene(data->device);
slouken@1900
  1479
        data->beginScene = SDL_TRUE;
slouken@1900
  1480
    }
slouken@1900
  1481
slouken@1975
  1482
    result = IDirect3DDevice9_TestCooperativeLevel(data->device);
slouken@1975
  1483
    if (result == D3DERR_DEVICELOST) {
slouken@1975
  1484
        /* We'll reset later */
slouken@1975
  1485
        return;
slouken@1975
  1486
    }
slouken@1975
  1487
    if (result == D3DERR_DEVICENOTRESET) {
slouken@1975
  1488
        D3D_Reset(renderer);
slouken@1975
  1489
    }
slouken@1900
  1490
    result = IDirect3DDevice9_Present(data->device, NULL, NULL, NULL, NULL);
slouken@1900
  1491
    if (FAILED(result)) {
slouken@1900
  1492
        D3D_SetError("Present()", result);
slouken@1900
  1493
    }
slouken@1895
  1494
}
slouken@1895
  1495
slouken@1895
  1496
static void
slouken@1913
  1497
D3D_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1895
  1498
{
slouken@1913
  1499
    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
slouken@1895
  1500
slouken@1895
  1501
    if (!data) {
slouken@1895
  1502
        return;
slouken@1895
  1503
    }
slouken@2973
  1504
    if (data->yuv) {
slouken@2973
  1505
        SDL_SW_DestroyYUVTexture(data->yuv);
slouken@2973
  1506
    }
slouken@1903
  1507
    if (data->texture) {
slouken@1903
  1508
        IDirect3DTexture9_Release(data->texture);
slouken@1903
  1509
    }
slouken@1895
  1510
    SDL_free(data);
slouken@1895
  1511
    texture->driverdata = NULL;
slouken@1895
  1512
}
slouken@1895
  1513
slouken@1975
  1514
static void
slouken@1913
  1515
D3D_DestroyRenderer(SDL_Renderer * renderer)
slouken@1895
  1516
{
slouken@1913
  1517
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@1895
  1518
slouken@1895
  1519
    if (data) {
slouken@1900
  1520
        if (data->device) {
slouken@1900
  1521
            IDirect3DDevice9_Release(data->device);
slouken@1900
  1522
        }
slouken@1895
  1523
        SDL_free(data);
slouken@1895
  1524
    }
slouken@1895
  1525
    SDL_free(renderer);
slouken@1895
  1526
}
slouken@1895
  1527
slouken@1895
  1528
#endif /* SDL_VIDEO_RENDER_D3D */
slouken@1895
  1529
slouken@1895
  1530
/* vi: set ts=4 sw=4 expandtab: */