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