src/video/win32/SDL_d3drender.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 03 Jan 2009 05:42:18 +0000
changeset 2973 ab0c00f1b070
parent 2972 0a4b70368372
child 2990 502adab079a4
permissions -rw-r--r--
Improved Direct3D YUV texture support
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@1895
    29
/* Direct3D renderer implementation */
slouken@1895
    30
slouken@2786
    31
#if 1                           /* This takes more memory but you won't lose your texture data */
slouken@2932
    32
#define D3DPOOL_SDL    D3DPOOL_MANAGED
slouken@2783
    33
#define SDL_MEMORY_POOL_MANAGED
slouken@2783
    34
#else
slouken@2932
    35
#define D3DPOOL_SDL    D3DPOOL_DEFAULT
slouken@2783
    36
#define SDL_MEMORY_POOL_DEFAULT
slouken@2783
    37
#endif
slouken@2783
    38
slouken@1913
    39
static SDL_Renderer *D3D_CreateRenderer(SDL_Window * window, Uint32 flags);
slouken@1975
    40
static int D3D_DisplayModeChanged(SDL_Renderer * renderer);
slouken@1913
    41
static int D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
slouken@2973
    42
static int D3D_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture, void **pixels, int *pitch);
slouken@1913
    43
static int D3D_SetTexturePalette(SDL_Renderer * renderer,
slouken@1913
    44
                                 SDL_Texture * texture,
slouken@1913
    45
                                 const SDL_Color * colors, int firstcolor,
slouken@1913
    46
                                 int ncolors);
slouken@1913
    47
static int D3D_GetTexturePalette(SDL_Renderer * renderer,
slouken@1913
    48
                                 SDL_Texture * texture, SDL_Color * colors,
slouken@1913
    49
                                 int firstcolor, int ncolors);
slouken@1985
    50
static int D3D_SetTextureColorMod(SDL_Renderer * renderer,
slouken@1985
    51
                                  SDL_Texture * texture);
slouken@1985
    52
static int D3D_SetTextureAlphaMod(SDL_Renderer * renderer,
slouken@1985
    53
                                  SDL_Texture * texture);
slouken@1985
    54
static int D3D_SetTextureBlendMode(SDL_Renderer * renderer,
slouken@1985
    55
                                   SDL_Texture * texture);
slouken@1985
    56
static int D3D_SetTextureScaleMode(SDL_Renderer * renderer,
slouken@1985
    57
                                   SDL_Texture * texture);
slouken@1913
    58
static int D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1913
    59
                             const SDL_Rect * rect, const void *pixels,
slouken@1913
    60
                             int pitch);
slouken@1913
    61
static int D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1913
    62
                           const SDL_Rect * rect, int markDirty,
slouken@1913
    63
                           void **pixels, int *pitch);
slouken@1913
    64
static void D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
slouken@1913
    65
static void D3D_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1913
    66
                             int numrects, const SDL_Rect * rects);
slouken@2932
    67
static int D3D_RenderPoint(SDL_Renderer * renderer, int x, int y);
slouken@2932
    68
static int D3D_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2,
slouken@2932
    69
                          int y2);
slouken@2919
    70
static int D3D_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect);
slouken@1913
    71
static int D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1985
    72
                          const SDL_Rect * srcrect, const SDL_Rect * dstrect);
slouken@1913
    73
static void D3D_RenderPresent(SDL_Renderer * renderer);
slouken@1913
    74
static void D3D_DestroyTexture(SDL_Renderer * renderer,
slouken@1913
    75
                               SDL_Texture * texture);
slouken@1913
    76
static void D3D_DestroyRenderer(SDL_Renderer * renderer);
slouken@1895
    77
slouken@1895
    78
slouken@1913
    79
SDL_RenderDriver D3D_RenderDriver = {
slouken@1913
    80
    D3D_CreateRenderer,
slouken@1895
    81
    {
slouken@1895
    82
     "d3d",
slouken@1965
    83
     (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY |
slouken@1975
    84
      SDL_RENDERER_PRESENTFLIP2 | SDL_RENDERER_PRESENTFLIP3 |
slouken@1965
    85
      SDL_RENDERER_PRESENTDISCARD | SDL_RENDERER_PRESENTVSYNC |
slouken@1965
    86
      SDL_RENDERER_ACCELERATED),
slouken@1985
    87
     (SDL_TEXTUREMODULATE_NONE | SDL_TEXTUREMODULATE_COLOR |
slouken@1985
    88
      SDL_TEXTUREMODULATE_ALPHA),
slouken@2884
    89
     (SDL_BLENDMODE_NONE | SDL_BLENDMODE_MASK |
slouken@2884
    90
      SDL_BLENDMODE_BLEND | SDL_BLENDMODE_ADD | SDL_BLENDMODE_MOD),
slouken@1965
    91
     (SDL_TEXTURESCALEMODE_NONE | SDL_TEXTURESCALEMODE_FAST |
slouken@1965
    92
      SDL_TEXTURESCALEMODE_SLOW | SDL_TEXTURESCALEMODE_BEST),
slouken@2972
    93
     0,
slouken@2972
    94
     {0},
slouken@1895
    95
     0,
slouken@1895
    96
     0}
slouken@1895
    97
};
slouken@1895
    98
slouken@1895
    99
typedef struct
slouken@1895
   100
{
slouken@2973
   101
    IDirect3D9 *d3d;
slouken@1895
   102
    IDirect3DDevice9 *device;
slouken@1975
   103
    D3DPRESENT_PARAMETERS pparams;
slouken@1900
   104
    SDL_bool beginScene;
slouken@1913
   105
} D3D_RenderData;
slouken@1895
   106
slouken@1895
   107
typedef struct
slouken@1895
   108
{
slouken@2973
   109
    SDL_SW_YUVTexture *yuv;
slouken@2973
   110
    Uint32 format;
slouken@1903
   111
    IDirect3DTexture9 *texture;
slouken@1913
   112
} D3D_TextureData;
slouken@1895
   113
slouken@1903
   114
typedef struct
slouken@1903
   115
{
slouken@1903
   116
    float x, y, z;
slouken@1904
   117
    float rhw;
slouken@1987
   118
    DWORD color;
slouken@1904
   119
    float u, v;
slouken@1903
   120
} Vertex;
slouken@1903
   121
slouken@1895
   122
static void
slouken@1900
   123
D3D_SetError(const char *prefix, HRESULT result)
slouken@1900
   124
{
slouken@1900
   125
    const char *error;
slouken@1900
   126
slouken@1900
   127
    switch (result) {
slouken@1900
   128
    case D3DERR_WRONGTEXTUREFORMAT:
slouken@1900
   129
        error = "WRONGTEXTUREFORMAT";
slouken@1900
   130
        break;
slouken@1900
   131
    case D3DERR_UNSUPPORTEDCOLOROPERATION:
slouken@1900
   132
        error = "UNSUPPORTEDCOLOROPERATION";
slouken@1900
   133
        break;
slouken@1900
   134
    case D3DERR_UNSUPPORTEDCOLORARG:
slouken@1900
   135
        error = "UNSUPPORTEDCOLORARG";
slouken@1900
   136
        break;
slouken@1900
   137
    case D3DERR_UNSUPPORTEDALPHAOPERATION:
slouken@1900
   138
        error = "UNSUPPORTEDALPHAOPERATION";
slouken@1900
   139
        break;
slouken@1900
   140
    case D3DERR_UNSUPPORTEDALPHAARG:
slouken@1900
   141
        error = "UNSUPPORTEDALPHAARG";
slouken@1900
   142
        break;
slouken@1900
   143
    case D3DERR_TOOMANYOPERATIONS:
slouken@1900
   144
        error = "TOOMANYOPERATIONS";
slouken@1900
   145
        break;
slouken@1900
   146
    case D3DERR_CONFLICTINGTEXTUREFILTER:
slouken@1900
   147
        error = "CONFLICTINGTEXTUREFILTER";
slouken@1900
   148
        break;
slouken@1900
   149
    case D3DERR_UNSUPPORTEDFACTORVALUE:
slouken@1900
   150
        error = "UNSUPPORTEDFACTORVALUE";
slouken@1900
   151
        break;
slouken@1900
   152
    case D3DERR_CONFLICTINGRENDERSTATE:
slouken@1900
   153
        error = "CONFLICTINGRENDERSTATE";
slouken@1900
   154
        break;
slouken@1900
   155
    case D3DERR_UNSUPPORTEDTEXTUREFILTER:
slouken@1900
   156
        error = "UNSUPPORTEDTEXTUREFILTER";
slouken@1900
   157
        break;
slouken@1900
   158
    case D3DERR_CONFLICTINGTEXTUREPALETTE:
slouken@1900
   159
        error = "CONFLICTINGTEXTUREPALETTE";
slouken@1900
   160
        break;
slouken@1900
   161
    case D3DERR_DRIVERINTERNALERROR:
slouken@1900
   162
        error = "DRIVERINTERNALERROR";
slouken@1900
   163
        break;
slouken@1900
   164
    case D3DERR_NOTFOUND:
slouken@1900
   165
        error = "NOTFOUND";
slouken@1900
   166
        break;
slouken@1900
   167
    case D3DERR_MOREDATA:
slouken@1900
   168
        error = "MOREDATA";
slouken@1900
   169
        break;
slouken@1900
   170
    case D3DERR_DEVICELOST:
slouken@1900
   171
        error = "DEVICELOST";
slouken@1900
   172
        break;
slouken@1900
   173
    case D3DERR_DEVICENOTRESET:
slouken@1900
   174
        error = "DEVICENOTRESET";
slouken@1900
   175
        break;
slouken@1900
   176
    case D3DERR_NOTAVAILABLE:
slouken@1900
   177
        error = "NOTAVAILABLE";
slouken@1900
   178
        break;
slouken@1900
   179
    case D3DERR_OUTOFVIDEOMEMORY:
slouken@1900
   180
        error = "OUTOFVIDEOMEMORY";
slouken@1900
   181
        break;
slouken@1900
   182
    case D3DERR_INVALIDDEVICE:
slouken@1900
   183
        error = "INVALIDDEVICE";
slouken@1900
   184
        break;
slouken@1900
   185
    case D3DERR_INVALIDCALL:
slouken@1900
   186
        error = "INVALIDCALL";
slouken@1900
   187
        break;
slouken@1900
   188
    case D3DERR_DRIVERINVALIDCALL:
slouken@1900
   189
        error = "DRIVERINVALIDCALL";
slouken@1900
   190
        break;
slouken@1900
   191
    case D3DERR_WASSTILLDRAWING:
slouken@1900
   192
        error = "WASSTILLDRAWING";
slouken@1900
   193
        break;
slouken@1900
   194
    default:
slouken@1900
   195
        error = "UNKNOWN";
slouken@1900
   196
        break;
slouken@1900
   197
    }
slouken@1900
   198
    SDL_SetError("%s: %s", prefix, error);
slouken@1900
   199
}
slouken@1900
   200
slouken@1903
   201
static D3DFORMAT
slouken@1903
   202
PixelFormatToD3DFMT(Uint32 format)
slouken@1895
   203
{
slouken@1903
   204
    switch (format) {
slouken@1965
   205
    case SDL_PIXELFORMAT_INDEX8:
slouken@1903
   206
        return D3DFMT_P8;
slouken@1965
   207
    case SDL_PIXELFORMAT_RGB332:
slouken@1903
   208
        return D3DFMT_R3G3B2;
slouken@1965
   209
    case SDL_PIXELFORMAT_RGB444:
slouken@1903
   210
        return D3DFMT_X4R4G4B4;
slouken@1965
   211
    case SDL_PIXELFORMAT_RGB555:
slouken@1903
   212
        return D3DFMT_X1R5G5B5;
slouken@1965
   213
    case SDL_PIXELFORMAT_ARGB4444:
slouken@1903
   214
        return D3DFMT_A4R4G4B4;
slouken@1965
   215
    case SDL_PIXELFORMAT_ARGB1555:
slouken@1903
   216
        return D3DFMT_A1R5G5B5;
slouken@1965
   217
    case SDL_PIXELFORMAT_RGB565:
slouken@1903
   218
        return D3DFMT_R5G6B5;
slouken@1965
   219
    case SDL_PIXELFORMAT_RGB888:
slouken@1903
   220
        return D3DFMT_X8R8G8B8;
slouken@1965
   221
    case SDL_PIXELFORMAT_ARGB8888:
slouken@1903
   222
        return D3DFMT_A8R8G8B8;
slouken@1965
   223
    case SDL_PIXELFORMAT_ARGB2101010:
slouken@1903
   224
        return D3DFMT_A2R10G10B10;
slouken@1965
   225
    case SDL_PIXELFORMAT_UYVY:
slouken@1903
   226
        return D3DFMT_UYVY;
slouken@1965
   227
    case SDL_PIXELFORMAT_YUY2:
slouken@1903
   228
        return D3DFMT_YUY2;
slouken@1903
   229
    default:
slouken@1903
   230
        return D3DFMT_UNKNOWN;
slouken@1903
   231
    }
slouken@1895
   232
}
slouken@1895
   233
slouken@2973
   234
static SDL_bool
slouken@2973
   235
D3D_IsTextureFormatAvailable(IDirect3D9 *d3d, Uint32 display_format, Uint32 texture_format)
slouken@2973
   236
{
slouken@2973
   237
    HRESULT result;
slouken@2973
   238
slouken@2973
   239
    result = IDirect3D9_CheckDeviceFormat(d3d,
slouken@2973
   240
                                          D3DADAPTER_DEFAULT,        /* FIXME */
slouken@2973
   241
                                          D3DDEVTYPE_HAL,
slouken@2973
   242
                                          PixelFormatToD3DFMT(display_format),
slouken@2973
   243
                                          0,
slouken@2973
   244
                                          D3DRTYPE_TEXTURE,
slouken@2973
   245
                                          PixelFormatToD3DFMT(texture_format));
slouken@2973
   246
    return FAILED(result) ? SDL_FALSE : SDL_TRUE;
slouken@2973
   247
}
slouken@2973
   248
slouken@2973
   249
static void
slouken@2973
   250
UpdateYUVTextureData(SDL_Texture * texture)
slouken@2973
   251
{
slouken@2973
   252
    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
slouken@2973
   253
    SDL_Rect rect;
slouken@2973
   254
    RECT d3drect;
slouken@2973
   255
    D3DLOCKED_RECT locked;
slouken@2973
   256
    HRESULT result;
slouken@2973
   257
slouken@2973
   258
    d3drect.left = 0;
slouken@2973
   259
    d3drect.right = texture->w;
slouken@2973
   260
    d3drect.top = 0;
slouken@2973
   261
    d3drect.bottom = texture->h;
slouken@2973
   262
slouken@2973
   263
    result = IDirect3DTexture9_LockRect(data->texture, 0, &locked, &d3drect, 0);
slouken@2973
   264
    if (FAILED(result)) {
slouken@2973
   265
        return;
slouken@2973
   266
    }
slouken@2973
   267
slouken@2973
   268
    rect.x = 0;
slouken@2973
   269
    rect.y = 0;
slouken@2973
   270
    rect.w = texture->w;
slouken@2973
   271
    rect.h = texture->h;
slouken@2973
   272
    SDL_SW_CopyYUVToRGB(data->yuv, &rect, data->format, texture->w,
slouken@2973
   273
                        texture->h, locked.pBits, locked.Pitch);
slouken@2973
   274
slouken@2973
   275
    IDirect3DTexture9_UnlockRect(data->texture, 0);
slouken@2973
   276
}
slouken@2973
   277
slouken@1895
   278
void
slouken@1895
   279
D3D_AddRenderDriver(_THIS)
slouken@1895
   280
{
slouken@1895
   281
    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
slouken@2972
   282
    SDL_RendererInfo *info = &D3D_RenderDriver.info;
slouken@2972
   283
    SDL_DisplayMode *mode = &SDL_CurrentDisplay.desktop_mode;
slouken@1895
   284
slouken@1895
   285
    if (data->d3d) {
slouken@2972
   286
        int i;
slouken@2972
   287
        int formats[] = {
slouken@2972
   288
          SDL_PIXELFORMAT_INDEX8,
slouken@2972
   289
          SDL_PIXELFORMAT_RGB332,
slouken@2972
   290
          SDL_PIXELFORMAT_RGB444,
slouken@2972
   291
          SDL_PIXELFORMAT_RGB555,
slouken@2972
   292
          SDL_PIXELFORMAT_ARGB4444,
slouken@2972
   293
          SDL_PIXELFORMAT_ARGB1555,
slouken@2972
   294
          SDL_PIXELFORMAT_RGB565,
slouken@2972
   295
          SDL_PIXELFORMAT_RGB888,
slouken@2972
   296
          SDL_PIXELFORMAT_ARGB8888,
slouken@2972
   297
          SDL_PIXELFORMAT_ARGB2101010,
slouken@2972
   298
        };
slouken@2972
   299
slouken@2972
   300
        for (i = 0; i < SDL_arraysize(formats); ++i) {
slouken@2973
   301
            if (D3D_IsTextureFormatAvailable(data->d3d, mode->format, formats[i])) {
slouken@2972
   302
                info->texture_formats[info->num_texture_formats++] = formats[i];
slouken@2972
   303
            }
slouken@2972
   304
        }
slouken@2973
   305
        info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_YV12;
slouken@2973
   306
        info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_IYUV;
slouken@2973
   307
        info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_YUY2;
slouken@2973
   308
        info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_UYVY;
slouken@2973
   309
        info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_YVYU;
slouken@2972
   310
slouken@1913
   311
        SDL_AddRenderDriver(0, &D3D_RenderDriver);
slouken@1895
   312
    }
slouken@1895
   313
}
slouken@1895
   314
slouken@1895
   315
SDL_Renderer *
slouken@1913
   316
D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
slouken@1895
   317
{
slouken@1895
   318
    SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
slouken@1895
   319
    SDL_VideoData *videodata = (SDL_VideoData *) display->device->driverdata;
slouken@1895
   320
    SDL_WindowData *windowdata = (SDL_WindowData *) window->driverdata;
slouken@1895
   321
    SDL_Renderer *renderer;
slouken@1913
   322
    D3D_RenderData *data;
slouken@1900
   323
    HRESULT result;
slouken@1900
   324
    D3DPRESENT_PARAMETERS pparams;
slouken@1907
   325
    IDirect3DSwapChain9 *chain;
slouken@1925
   326
    D3DCAPS9 caps;
slouken@1895
   327
slouken@1920
   328
    renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
slouken@1895
   329
    if (!renderer) {
slouken@1895
   330
        SDL_OutOfMemory();
slouken@1895
   331
        return NULL;
slouken@1895
   332
    }
slouken@1895
   333
slouken@1920
   334
    data = (D3D_RenderData *) SDL_calloc(1, sizeof(*data));
slouken@1895
   335
    if (!data) {
slouken@1913
   336
        D3D_DestroyRenderer(renderer);
slouken@1895
   337
        SDL_OutOfMemory();
slouken@1895
   338
        return NULL;
slouken@1895
   339
    }
slouken@2973
   340
    data->d3d = videodata->d3d;
slouken@1895
   341
slouken@1975
   342
    renderer->DisplayModeChanged = D3D_DisplayModeChanged;
slouken@1913
   343
    renderer->CreateTexture = D3D_CreateTexture;
slouken@2973
   344
    renderer->QueryTexturePixels = D3D_QueryTexturePixels;
slouken@1913
   345
    renderer->SetTexturePalette = D3D_SetTexturePalette;
slouken@1913
   346
    renderer->GetTexturePalette = D3D_GetTexturePalette;
slouken@1985
   347
    renderer->SetTextureColorMod = D3D_SetTextureColorMod;
slouken@1985
   348
    renderer->SetTextureAlphaMod = D3D_SetTextureAlphaMod;
slouken@1985
   349
    renderer->SetTextureBlendMode = D3D_SetTextureBlendMode;
slouken@1985
   350
    renderer->SetTextureScaleMode = D3D_SetTextureScaleMode;
slouken@1913
   351
    renderer->UpdateTexture = D3D_UpdateTexture;
slouken@1913
   352
    renderer->LockTexture = D3D_LockTexture;
slouken@1913
   353
    renderer->UnlockTexture = D3D_UnlockTexture;
slouken@1913
   354
    renderer->DirtyTexture = D3D_DirtyTexture;
slouken@2932
   355
    renderer->RenderPoint = D3D_RenderPoint;
slouken@2932
   356
    renderer->RenderLine = D3D_RenderLine;
slouken@1913
   357
    renderer->RenderFill = D3D_RenderFill;
slouken@1913
   358
    renderer->RenderCopy = D3D_RenderCopy;
slouken@1913
   359
    renderer->RenderPresent = D3D_RenderPresent;
slouken@1913
   360
    renderer->DestroyTexture = D3D_DestroyTexture;
slouken@1913
   361
    renderer->DestroyRenderer = D3D_DestroyRenderer;
slouken@1913
   362
    renderer->info = D3D_RenderDriver.info;
slouken@1895
   363
    renderer->window = window->id;
slouken@1895
   364
    renderer->driverdata = data;
slouken@1895
   365
slouken@1965
   366
    renderer->info.flags = SDL_RENDERER_ACCELERATED;
slouken@1895
   367
slouken@1900
   368
    SDL_zero(pparams);
slouken@1900
   369
    pparams.BackBufferWidth = window->w;
slouken@1900
   370
    pparams.BackBufferHeight = window->h;
slouken@1903
   371
    if (window->flags & SDL_WINDOW_FULLSCREEN) {
slouken@1903
   372
        pparams.BackBufferFormat =
slouken@1975
   373
            PixelFormatToD3DFMT(display->fullscreen_mode.format);
slouken@1903
   374
    } else {
slouken@1903
   375
        pparams.BackBufferFormat = D3DFMT_UNKNOWN;
slouken@1903
   376
    }
slouken@1965
   377
    if (flags & SDL_RENDERER_PRESENTFLIP2) {
slouken@1900
   378
        pparams.BackBufferCount = 2;
slouken@1900
   379
        pparams.SwapEffect = D3DSWAPEFFECT_FLIP;
slouken@1965
   380
    } else if (flags & SDL_RENDERER_PRESENTFLIP3) {
slouken@1900
   381
        pparams.BackBufferCount = 3;
slouken@1900
   382
        pparams.SwapEffect = D3DSWAPEFFECT_FLIP;
slouken@1965
   383
    } else if (flags & SDL_RENDERER_PRESENTCOPY) {
slouken@1900
   384
        pparams.BackBufferCount = 1;
slouken@1900
   385
        pparams.SwapEffect = D3DSWAPEFFECT_COPY;
slouken@1900
   386
    } else {
slouken@1900
   387
        pparams.BackBufferCount = 1;
slouken@1900
   388
        pparams.SwapEffect = D3DSWAPEFFECT_DISCARD;
slouken@1900
   389
    }
slouken@1900
   390
    if (window->flags & SDL_WINDOW_FULLSCREEN) {
slouken@1900
   391
        pparams.Windowed = FALSE;
slouken@1903
   392
        pparams.FullScreen_RefreshRateInHz =
slouken@1975
   393
            display->fullscreen_mode.refresh_rate;
slouken@1900
   394
    } else {
slouken@1900
   395
        pparams.Windowed = TRUE;
slouken@1903
   396
        pparams.FullScreen_RefreshRateInHz = 0;
slouken@1900
   397
    }
slouken@1965
   398
    if (flags & SDL_RENDERER_PRESENTVSYNC) {
slouken@1907
   399
        pparams.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
slouken@1907
   400
    } else {
slouken@1907
   401
        pparams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
slouken@1907
   402
    }
slouken@1900
   403
slouken@1900
   404
    result = IDirect3D9_CreateDevice(videodata->d3d, D3DADAPTER_DEFAULT,        /* FIXME */
slouken@1900
   405
                                     D3DDEVTYPE_HAL,
slouken@1900
   406
                                     windowdata->hwnd,
slouken@1900
   407
                                     D3DCREATE_SOFTWARE_VERTEXPROCESSING,
slouken@1900
   408
                                     &pparams, &data->device);
slouken@1900
   409
    if (FAILED(result)) {
slouken@1913
   410
        D3D_DestroyRenderer(renderer);
slouken@1900
   411
        D3D_SetError("CreateDevice()", result);
slouken@1900
   412
        return NULL;
slouken@1900
   413
    }
slouken@1900
   414
    data->beginScene = SDL_TRUE;
slouken@1900
   415
slouken@1907
   416
    /* Get presentation parameters to fill info */
slouken@1907
   417
    result = IDirect3DDevice9_GetSwapChain(data->device, 0, &chain);
slouken@1907
   418
    if (FAILED(result)) {
slouken@1913
   419
        D3D_DestroyRenderer(renderer);
slouken@1907
   420
        D3D_SetError("GetSwapChain()", result);
slouken@1907
   421
        return NULL;
slouken@1907
   422
    }
slouken@1907
   423
    result = IDirect3DSwapChain9_GetPresentParameters(chain, &pparams);
slouken@1907
   424
    if (FAILED(result)) {
slouken@1907
   425
        IDirect3DSwapChain9_Release(chain);
slouken@1913
   426
        D3D_DestroyRenderer(renderer);
slouken@1907
   427
        D3D_SetError("GetPresentParameters()", result);
slouken@1907
   428
        return NULL;
slouken@1907
   429
    }
slouken@1907
   430
    IDirect3DSwapChain9_Release(chain);
slouken@1907
   431
    switch (pparams.SwapEffect) {
slouken@1907
   432
    case D3DSWAPEFFECT_COPY:
slouken@1965
   433
        renderer->info.flags |= SDL_RENDERER_PRESENTCOPY;
slouken@1907
   434
        break;
slouken@1907
   435
    case D3DSWAPEFFECT_FLIP:
slouken@1907
   436
        switch (pparams.BackBufferCount) {
slouken@1907
   437
        case 2:
slouken@1965
   438
            renderer->info.flags |= SDL_RENDERER_PRESENTFLIP2;
slouken@1907
   439
            break;
slouken@1907
   440
        case 3:
slouken@1965
   441
            renderer->info.flags |= SDL_RENDERER_PRESENTFLIP3;
slouken@1907
   442
            break;
slouken@1907
   443
        }
slouken@1907
   444
        break;
slouken@1907
   445
    case D3DSWAPEFFECT_DISCARD:
slouken@1965
   446
        renderer->info.flags |= SDL_RENDERER_PRESENTDISCARD;
slouken@1907
   447
        break;
slouken@1907
   448
    }
slouken@1907
   449
    if (pparams.PresentationInterval == D3DPRESENT_INTERVAL_ONE) {
slouken@1965
   450
        renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
slouken@1907
   451
    }
slouken@1975
   452
    data->pparams = pparams;
slouken@1907
   453
slouken@1925
   454
    IDirect3DDevice9_GetDeviceCaps(data->device, &caps);
slouken@1925
   455
    renderer->info.max_texture_width = caps.MaxTextureWidth;
slouken@1925
   456
    renderer->info.max_texture_height = caps.MaxTextureHeight;
slouken@1918
   457
slouken@1903
   458
    /* Set up parameters for rendering */
slouken@1904
   459
    IDirect3DDevice9_SetVertexShader(data->device, NULL);
slouken@1987
   460
    IDirect3DDevice9_SetFVF(data->device,
slouken@1987
   461
                            D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
slouken@1988
   462
    IDirect3DDevice9_SetRenderState(data->device, D3DRS_ZENABLE, D3DZB_FALSE);
slouken@1903
   463
    IDirect3DDevice9_SetRenderState(data->device, D3DRS_CULLMODE,
slouken@1903
   464
                                    D3DCULL_NONE);
slouken@1904
   465
    IDirect3DDevice9_SetRenderState(data->device, D3DRS_LIGHTING, FALSE);
slouken@1988
   466
    /* Enable color modulation by diffuse color */
slouken@1988
   467
    IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLOROP,
slouken@1988
   468
                                          D3DTOP_MODULATE);
slouken@1988
   469
    IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLORARG1,
slouken@1988
   470
                                          D3DTA_TEXTURE);
slouken@1988
   471
    IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLORARG2,
slouken@1988
   472
                                          D3DTA_DIFFUSE);
slouken@1988
   473
    /* Enable alpha modulation by diffuse alpha */
slouken@1988
   474
    IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAOP,
slouken@1988
   475
                                          D3DTOP_MODULATE);
slouken@1988
   476
    IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAARG1,
slouken@1988
   477
                                          D3DTA_TEXTURE);
slouken@1988
   478
    IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAARG2,
slouken@1988
   479
                                          D3DTA_DIFFUSE);
slouken@1991
   480
    /* Disable second texture stage, since we're done */
slouken@1991
   481
    IDirect3DDevice9_SetTextureStageState(data->device, 1, D3DTSS_COLOROP,
slouken@1991
   482
                                          D3DTOP_DISABLE);
slouken@1991
   483
    IDirect3DDevice9_SetTextureStageState(data->device, 1, D3DTSS_ALPHAOP,
slouken@1991
   484
                                          D3DTOP_DISABLE);
slouken@1903
   485
slouken@1895
   486
    return renderer;
slouken@1895
   487
}
slouken@1895
   488
slouken@1895
   489
static int
slouken@1975
   490
D3D_Reset(SDL_Renderer * renderer)
slouken@1975
   491
{
slouken@1975
   492
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@1975
   493
    HRESULT result;
slouken@1975
   494
slouken@1975
   495
    result = IDirect3DDevice9_Reset(data->device, &data->pparams);
slouken@1975
   496
    if (FAILED(result)) {
slouken@1975
   497
        if (result == D3DERR_DEVICELOST) {
slouken@1975
   498
            /* Don't worry about it, we'll reset later... */
slouken@1975
   499
            return 0;
slouken@1975
   500
        } else {
slouken@1975
   501
            D3D_SetError("Reset()", result);
slouken@1975
   502
            return -1;
slouken@1975
   503
        }
slouken@1975
   504
    }
slouken@1975
   505
    IDirect3DDevice9_SetVertexShader(data->device, NULL);
slouken@1987
   506
    IDirect3DDevice9_SetFVF(data->device,
slouken@1987
   507
                            D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
slouken@1975
   508
    IDirect3DDevice9_SetRenderState(data->device, D3DRS_CULLMODE,
slouken@1975
   509
                                    D3DCULL_NONE);
slouken@1975
   510
    IDirect3DDevice9_SetRenderState(data->device, D3DRS_LIGHTING, FALSE);
slouken@1975
   511
    return 0;
slouken@1975
   512
}
slouken@1975
   513
slouken@1975
   514
static int
slouken@1975
   515
D3D_DisplayModeChanged(SDL_Renderer * renderer)
slouken@1975
   516
{
slouken@1975
   517
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@1975
   518
    SDL_Window *window = SDL_GetWindowFromID(renderer->window);
slouken@1975
   519
    SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
slouken@1975
   520
slouken@1975
   521
    data->pparams.BackBufferWidth = window->w;
slouken@1975
   522
    data->pparams.BackBufferHeight = window->h;
slouken@1975
   523
    if (window->flags & SDL_WINDOW_FULLSCREEN) {
slouken@1975
   524
        data->pparams.BackBufferFormat =
slouken@1975
   525
            PixelFormatToD3DFMT(display->fullscreen_mode.format);
slouken@1975
   526
    } else {
slouken@1975
   527
        data->pparams.BackBufferFormat = D3DFMT_UNKNOWN;
slouken@1975
   528
    }
slouken@1975
   529
    return D3D_Reset(renderer);
slouken@1975
   530
}
slouken@1975
   531
slouken@1975
   532
static int
slouken@1913
   533
D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1895
   534
{
slouken@1913
   535
    D3D_RenderData *renderdata = (D3D_RenderData *) renderer->driverdata;
slouken@1895
   536
    SDL_Window *window = SDL_GetWindowFromID(renderer->window);
slouken@1895
   537
    SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
slouken@2973
   538
    Uint32 display_format = display->current_mode.format;
slouken@1913
   539
    D3D_TextureData *data;
slouken@1903
   540
    HRESULT result;
slouken@1895
   541
slouken@1920
   542
    data = (D3D_TextureData *) SDL_calloc(1, sizeof(*data));
slouken@1895
   543
    if (!data) {
slouken@1895
   544
        SDL_OutOfMemory();
slouken@1895
   545
        return -1;
slouken@1895
   546
    }
slouken@1895
   547
slouken@1895
   548
    texture->driverdata = data;
slouken@1895
   549
slouken@2973
   550
    if (SDL_ISPIXELFORMAT_FOURCC(texture->format) &&
slouken@2973
   551
        (texture->format != SDL_PIXELFORMAT_YUY2 ||
slouken@2973
   552
         !D3D_IsTextureFormatAvailable(renderdata->d3d, display_format, texture->format)) &&
slouken@2973
   553
        (texture->format != SDL_PIXELFORMAT_YVYU ||
slouken@2973
   554
         !D3D_IsTextureFormatAvailable(renderdata->d3d, display_format, texture->format))) {
slouken@2973
   555
        data->yuv =
slouken@2973
   556
            SDL_SW_CreateYUVTexture(texture->format, texture->w, texture->h);
slouken@2973
   557
        if (!data->yuv) {
slouken@2973
   558
            return -1;
slouken@2973
   559
        }
slouken@2973
   560
        data->format = display->current_mode.format;
slouken@2973
   561
    } else {
slouken@2973
   562
        data->format = texture->format;
slouken@2973
   563
    }
slouken@2973
   564
slouken@1903
   565
    result =
slouken@1903
   566
        IDirect3DDevice9_CreateTexture(renderdata->device, texture->w,
slouken@1903
   567
                                       texture->h, 1, 0,
slouken@2973
   568
                                       PixelFormatToD3DFMT(data->format),
slouken@2783
   569
                                       D3DPOOL_SDL, &data->texture, NULL);
slouken@1903
   570
    if (FAILED(result)) {
slouken@1903
   571
        D3D_SetError("CreateTexture()", result);
slouken@1903
   572
        return -1;
slouken@1903
   573
    }
slouken@1903
   574
slouken@1895
   575
    return 0;
slouken@1895
   576
}
slouken@1895
   577
slouken@1895
   578
static int
slouken@2973
   579
D3D_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@2973
   580
                       void **pixels, int *pitch)
slouken@2973
   581
{
slouken@2973
   582
    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
slouken@2973
   583
slouken@2973
   584
    if (data->yuv) {
slouken@2973
   585
        return SDL_SW_QueryYUVTexturePixels(data->yuv, pixels, pitch);
slouken@2973
   586
    } else {
slouken@2973
   587
        /* D3D textures don't have their pixels hanging out */
slouken@2973
   588
        return -1;
slouken@2973
   589
    }
slouken@2973
   590
}
slouken@2973
   591
slouken@2973
   592
static int
slouken@1913
   593
D3D_SetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1913
   594
                      const SDL_Color * colors, int firstcolor, int ncolors)
slouken@1895
   595
{
slouken@1913
   596
    D3D_RenderData *renderdata = (D3D_RenderData *) renderer->driverdata;
slouken@1913
   597
    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
slouken@1895
   598
slouken@1903
   599
    return 0;
slouken@1895
   600
}
slouken@1895
   601
slouken@1895
   602
static int
slouken@1913
   603
D3D_GetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1913
   604
                      SDL_Color * colors, int firstcolor, int ncolors)
slouken@1895
   605
{
slouken@1913
   606
    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
slouken@1895
   607
slouken@1903
   608
    return 0;
slouken@1895
   609
}
slouken@1895
   610
slouken@1895
   611
static int
slouken@1985
   612
D3D_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1985
   613
{
slouken@1987
   614
    return 0;
slouken@1985
   615
}
slouken@1985
   616
slouken@1985
   617
static int
slouken@1985
   618
D3D_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1985
   619
{
slouken@1987
   620
    return 0;
slouken@1985
   621
}
slouken@1985
   622
slouken@1985
   623
static int
slouken@1985
   624
D3D_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1985
   625
{
slouken@1985
   626
    switch (texture->blendMode) {
slouken@2884
   627
    case SDL_BLENDMODE_NONE:
slouken@2884
   628
    case SDL_BLENDMODE_MASK:
slouken@2884
   629
    case SDL_BLENDMODE_BLEND:
slouken@2884
   630
    case SDL_BLENDMODE_ADD:
slouken@2884
   631
    case SDL_BLENDMODE_MOD:
slouken@1985
   632
        return 0;
slouken@1985
   633
    default:
slouken@1985
   634
        SDL_Unsupported();
slouken@2884
   635
        texture->blendMode = SDL_BLENDMODE_NONE;
slouken@1985
   636
        return -1;
slouken@1985
   637
    }
slouken@1985
   638
}
slouken@1985
   639
slouken@1985
   640
static int
slouken@1985
   641
D3D_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1985
   642
{
slouken@1985
   643
    switch (texture->scaleMode) {
slouken@1985
   644
    case SDL_TEXTURESCALEMODE_NONE:
slouken@1985
   645
    case SDL_TEXTURESCALEMODE_FAST:
slouken@1985
   646
    case SDL_TEXTURESCALEMODE_SLOW:
slouken@1985
   647
    case SDL_TEXTURESCALEMODE_BEST:
slouken@1985
   648
        return 0;
slouken@1985
   649
    default:
slouken@1985
   650
        SDL_Unsupported();
slouken@1985
   651
        texture->scaleMode = SDL_TEXTURESCALEMODE_NONE;
slouken@1985
   652
        return -1;
slouken@1985
   653
    }
slouken@1985
   654
    return 0;
slouken@1985
   655
}
slouken@1985
   656
slouken@1985
   657
static int
slouken@1913
   658
D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1913
   659
                  const SDL_Rect * rect, const void *pixels, int pitch)
slouken@1895
   660
{
slouken@1913
   661
    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
slouken@1913
   662
    D3D_RenderData *renderdata = (D3D_RenderData *) renderer->driverdata;
slouken@1895
   663
slouken@2973
   664
    if (data->yuv) {
slouken@2973
   665
        if (SDL_SW_UpdateYUVTexture(data->yuv, rect, pixels, pitch) < 0) {
slouken@2973
   666
            return -1;
slouken@2973
   667
        }
slouken@2973
   668
        UpdateYUVTextureData(texture);
slouken@2973
   669
        return 0;
slouken@2973
   670
    } else {
slouken@2973
   671
#ifdef SDL_MEMORY_POOL_DEFAULT
slouken@2973
   672
        IDirect3DTexture9 *temp;
slouken@2973
   673
        RECT d3drect;
slouken@2973
   674
        D3DLOCKED_RECT locked;
slouken@2973
   675
        const Uint8 *src;
slouken@2973
   676
        Uint8 *dst;
slouken@2973
   677
        int row, length;
slouken@2973
   678
        HRESULT result;
slouken@2973
   679
slouken@2973
   680
        result =
slouken@2973
   681
            IDirect3DDevice9_CreateTexture(renderdata->device, texture->w,
slouken@2973
   682
                                           texture->h, 1, 0,
slouken@2973
   683
                                           PixelFormatToD3DFMT(texture->format),
slouken@2973
   684
                                           D3DPOOL_SYSTEMMEM, &temp, NULL);
slouken@2973
   685
        if (FAILED(result)) {
slouken@2973
   686
            D3D_SetError("CreateTexture()", result);
slouken@2973
   687
            return -1;
slouken@2973
   688
        }
slouken@2973
   689
slouken@2973
   690
        d3drect.left = rect->x;
slouken@2973
   691
        d3drect.right = rect->x + rect->w;
slouken@2973
   692
        d3drect.top = rect->y;
slouken@2973
   693
        d3drect.bottom = rect->y + rect->h;
slouken@2973
   694
slouken@2973
   695
        result = IDirect3DTexture9_LockRect(temp, 0, &locked, &d3drect, 0);
slouken@2973
   696
        if (FAILED(result)) {
slouken@2973
   697
            IDirect3DTexture9_Release(temp);
slouken@2973
   698
            D3D_SetError("LockRect()", result);
slouken@2973
   699
            return -1;
slouken@2973
   700
        }
slouken@2973
   701
slouken@2973
   702
        src = pixels;
slouken@2973
   703
        dst = locked.pBits;
slouken@2973
   704
        length = rect->w * SDL_BYTESPERPIXEL(texture->format);
slouken@2973
   705
        for (row = 0; row < rect->h; ++row) {
slouken@2973
   706
            SDL_memcpy(dst, src, length);
slouken@2973
   707
            src += pitch;
slouken@2973
   708
            dst += locked.Pitch;
slouken@2973
   709
        }
slouken@2973
   710
        IDirect3DTexture9_UnlockRect(temp, 0);
slouken@2973
   711
slouken@2973
   712
        result =
slouken@2973
   713
            IDirect3DDevice9_UpdateTexture(renderdata->device,
slouken@2973
   714
                                           (IDirect3DBaseTexture9 *) temp,
slouken@2973
   715
                                           (IDirect3DBaseTexture9 *)
slouken@2973
   716
                                           data->texture);
slouken@2973
   717
        IDirect3DTexture9_Release(temp);
slouken@2973
   718
        if (FAILED(result)) {
slouken@2973
   719
            D3D_SetError("UpdateTexture()", result);
slouken@2973
   720
            return -1;
slouken@2973
   721
        }
slouken@2973
   722
#else
slouken@2973
   723
        RECT d3drect;
slouken@2973
   724
        D3DLOCKED_RECT locked;
slouken@2973
   725
        const Uint8 *src;
slouken@2973
   726
        Uint8 *dst;
slouken@2973
   727
        int row, length;
slouken@2973
   728
        HRESULT result;
slouken@2973
   729
slouken@2973
   730
        d3drect.left = rect->x;
slouken@2973
   731
        d3drect.right = rect->x + rect->w;
slouken@2973
   732
        d3drect.top = rect->y;
slouken@2973
   733
        d3drect.bottom = rect->y + rect->h;
slouken@2973
   734
slouken@2973
   735
        result =
slouken@2973
   736
            IDirect3DTexture9_LockRect(data->texture, 0, &locked, &d3drect, 0);
slouken@2973
   737
        if (FAILED(result)) {
slouken@2973
   738
            D3D_SetError("LockRect()", result);
slouken@2973
   739
            return -1;
slouken@2973
   740
        }
slouken@2973
   741
slouken@2973
   742
        src = pixels;
slouken@2973
   743
        dst = locked.pBits;
slouken@2973
   744
        length = rect->w * SDL_BYTESPERPIXEL(texture->format);
slouken@2973
   745
        for (row = 0; row < rect->h; ++row) {
slouken@2973
   746
            SDL_memcpy(dst, src, length);
slouken@2973
   747
            src += pitch;
slouken@2973
   748
            dst += locked.Pitch;
slouken@2973
   749
        }
slouken@2973
   750
        IDirect3DTexture9_UnlockRect(data->texture, 0);
slouken@2973
   751
#endif // SDL_MEMORY_POOL_DEFAULT
slouken@2973
   752
slouken@2973
   753
        return 0;
slouken@1903
   754
    }
slouken@1895
   755
}
slouken@1895
   756
slouken@1895
   757
static int
slouken@1913
   758
D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1913
   759
                const SDL_Rect * rect, int markDirty, void **pixels,
slouken@1913
   760
                int *pitch)
slouken@1895
   761
{
slouken@1913
   762
    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
slouken@1895
   763
slouken@2973
   764
    if (data->yuv) {
slouken@2973
   765
        return SDL_SW_LockYUVTexture(data->yuv, rect, markDirty, pixels,
slouken@2973
   766
                                     pitch);
slouken@2973
   767
    } else {
slouken@2973
   768
        RECT d3drect;
slouken@2973
   769
        D3DLOCKED_RECT locked;
slouken@2973
   770
        HRESULT result;
slouken@1903
   771
slouken@2973
   772
        d3drect.left = rect->x;
slouken@2973
   773
        d3drect.right = rect->x + rect->w;
slouken@2973
   774
        d3drect.top = rect->y;
slouken@2973
   775
        d3drect.bottom = rect->y + rect->h;
slouken@2973
   776
slouken@2973
   777
        result =
slouken@2973
   778
            IDirect3DTexture9_LockRect(data->texture, 0, &locked, &d3drect,
slouken@2973
   779
                                       markDirty ? 0 : D3DLOCK_NO_DIRTY_UPDATE);
slouken@2973
   780
        if (FAILED(result)) {
slouken@2973
   781
            D3D_SetError("LockRect()", result);
slouken@2973
   782
            return -1;
slouken@2973
   783
        }
slouken@2973
   784
        *pixels = locked.pBits;
slouken@2973
   785
        *pitch = locked.Pitch;
slouken@2973
   786
        return 0;
slouken@1903
   787
    }
slouken@1895
   788
}
slouken@1895
   789
slouken@1895
   790
static void
slouken@1913
   791
D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1895
   792
{
slouken@1913
   793
    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
slouken@1895
   794
slouken@2973
   795
    if (data->yuv) {
slouken@2973
   796
        SDL_SW_UnlockYUVTexture(data->yuv);
slouken@2973
   797
        UpdateYUVTextureData(texture);
slouken@2973
   798
    } else {
slouken@2973
   799
        IDirect3DTexture9_UnlockRect(data->texture, 0);
slouken@2973
   800
    }
slouken@1895
   801
}
slouken@1895
   802
slouken@1895
   803
static void
slouken@1913
   804
D3D_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture, int numrects,
slouken@1913
   805
                 const SDL_Rect * rects)
slouken@1895
   806
{
slouken@1913
   807
    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
slouken@1903
   808
    RECT d3drect;
slouken@1903
   809
    int i;
slouken@1903
   810
slouken@1903
   811
    for (i = 0; i < numrects; ++i) {
slouken@1903
   812
        const SDL_Rect *rect = &rects[i];
slouken@1903
   813
slouken@1903
   814
        d3drect.left = rect->x;
slouken@1903
   815
        d3drect.right = rect->x + rect->w;
slouken@1903
   816
        d3drect.top = rect->y;
slouken@1903
   817
        d3drect.bottom = rect->y + rect->h;
slouken@1903
   818
slouken@1903
   819
        IDirect3DTexture9_AddDirtyRect(data->texture, &d3drect);
slouken@1903
   820
    }
slouken@1895
   821
}
slouken@1895
   822
slouken@2932
   823
static void
slouken@2933
   824
D3D_SetBlendMode(D3D_RenderData * data, int blendMode)
slouken@2932
   825
{
slouken@2932
   826
    switch (blendMode) {
slouken@2932
   827
    case SDL_BLENDMODE_NONE:
slouken@2932
   828
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
slouken@2932
   829
                                        FALSE);
slouken@2932
   830
        break;
slouken@2932
   831
    case SDL_BLENDMODE_MASK:
slouken@2932
   832
    case SDL_BLENDMODE_BLEND:
slouken@2932
   833
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
slouken@2932
   834
                                        TRUE);
slouken@2932
   835
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
slouken@2932
   836
                                        D3DBLEND_SRCALPHA);
slouken@2932
   837
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
slouken@2932
   838
                                        D3DBLEND_INVSRCALPHA);
slouken@2932
   839
        break;
slouken@2932
   840
    case SDL_BLENDMODE_ADD:
slouken@2932
   841
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
slouken@2932
   842
                                        TRUE);
slouken@2932
   843
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
slouken@2932
   844
                                        D3DBLEND_SRCALPHA);
slouken@2932
   845
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
slouken@2932
   846
                                        D3DBLEND_ONE);
slouken@2932
   847
        break;
slouken@2932
   848
    case SDL_BLENDMODE_MOD:
slouken@2932
   849
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
slouken@2932
   850
                                        TRUE);
slouken@2932
   851
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
slouken@2932
   852
                                        D3DBLEND_ZERO);
slouken@2932
   853
        IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
slouken@2932
   854
                                        D3DBLEND_SRCCOLOR);
slouken@2932
   855
        break;
slouken@2932
   856
    }
slouken@2932
   857
}
slouken@2932
   858
slouken@1895
   859
static int
slouken@2932
   860
D3D_RenderPoint(SDL_Renderer * renderer, int x, int y)
slouken@1895
   861
{
slouken@1913
   862
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@2932
   863
    DWORD color;
slouken@2932
   864
    Vertex vertices[1];
slouken@1900
   865
    HRESULT result;
slouken@1895
   866
slouken@1900
   867
    if (data->beginScene) {
slouken@1900
   868
        IDirect3DDevice9_BeginScene(data->device);
slouken@1900
   869
        data->beginScene = SDL_FALSE;
slouken@1900
   870
    }
slouken@1895
   871
slouken@2932
   872
    color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
slouken@1901
   873
slouken@2932
   874
    vertices[0].x = (float) x - 0.5f;
slouken@2932
   875
    vertices[0].y = (float) y - 0.5f;
slouken@2932
   876
    vertices[0].z = 0.0f;
slouken@2932
   877
    vertices[0].rhw = 1.0f;
slouken@2932
   878
    vertices[0].color = color;
slouken@2932
   879
    vertices[0].u = 0.0f;
slouken@2932
   880
    vertices[0].v = 0.0f;
slouken@2932
   881
slouken@2932
   882
    D3D_SetBlendMode(data, renderer->blendMode);
slouken@2932
   883
slouken@2933
   884
    result =
slouken@2933
   885
        IDirect3DDevice9_SetTexture(data->device, 0,
slouken@2933
   886
                                    (IDirect3DBaseTexture9 *) 0);
slouken@2932
   887
    if (FAILED(result)) {
slouken@2932
   888
        D3D_SetError("SetTexture()", result);
slouken@2932
   889
        return -1;
slouken@2932
   890
    }
slouken@1903
   891
    result =
slouken@2932
   892
        IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_POINTLIST, 1,
slouken@2932
   893
                                         vertices, sizeof(*vertices));
slouken@1900
   894
    if (FAILED(result)) {
slouken@2932
   895
        D3D_SetError("DrawPrimitiveUP()", result);
slouken@2932
   896
        return -1;
slouken@2932
   897
    }
slouken@2932
   898
    return 0;
slouken@2932
   899
}
slouken@2932
   900
slouken@2932
   901
static int
slouken@2932
   902
D3D_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2, int y2)
slouken@2932
   903
{
slouken@2932
   904
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@2932
   905
    DWORD color;
slouken@2932
   906
    Vertex vertices[2];
slouken@2932
   907
    HRESULT result;
slouken@2932
   908
slouken@2932
   909
    if (data->beginScene) {
slouken@2932
   910
        IDirect3DDevice9_BeginScene(data->device);
slouken@2932
   911
        data->beginScene = SDL_FALSE;
slouken@2932
   912
    }
slouken@2932
   913
slouken@2932
   914
    color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
slouken@2932
   915
slouken@2932
   916
    vertices[0].x = (float) x1 - 0.5f;
slouken@2932
   917
    vertices[0].y = (float) y1 - 0.5f;
slouken@2932
   918
    vertices[0].z = 0.0f;
slouken@2932
   919
    vertices[0].rhw = 1.0f;
slouken@2932
   920
    vertices[0].color = color;
slouken@2932
   921
    vertices[0].u = 0.0f;
slouken@2932
   922
    vertices[0].v = 0.0f;
slouken@2932
   923
slouken@2932
   924
    vertices[1].x = (float) x2 - 0.5f;
slouken@2932
   925
    vertices[1].y = (float) y2 - 0.5f;
slouken@2932
   926
    vertices[1].z = 0.0f;
slouken@2932
   927
    vertices[1].rhw = 1.0f;
slouken@2932
   928
    vertices[1].color = color;
slouken@2932
   929
    vertices[1].u = 0.0f;
slouken@2932
   930
    vertices[1].v = 0.0f;
slouken@2932
   931
slouken@2932
   932
    D3D_SetBlendMode(data, renderer->blendMode);
slouken@2932
   933
slouken@2933
   934
    result =
slouken@2933
   935
        IDirect3DDevice9_SetTexture(data->device, 0,
slouken@2933
   936
                                    (IDirect3DBaseTexture9 *) 0);
slouken@2932
   937
    if (FAILED(result)) {
slouken@2932
   938
        D3D_SetError("SetTexture()", result);
slouken@2932
   939
        return -1;
slouken@2932
   940
    }
slouken@2932
   941
    result =
slouken@2932
   942
        IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_LINELIST, 1,
slouken@2932
   943
                                         vertices, sizeof(*vertices));
slouken@2932
   944
    if (FAILED(result)) {
slouken@2932
   945
        D3D_SetError("DrawPrimitiveUP()", result);
slouken@2932
   946
        return -1;
slouken@2932
   947
    }
slouken@2932
   948
    return 0;
slouken@2932
   949
}
slouken@2932
   950
slouken@2932
   951
static int
slouken@2932
   952
D3D_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect)
slouken@2932
   953
{
slouken@2932
   954
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@2932
   955
    float minx, miny, maxx, maxy;
slouken@2932
   956
    DWORD color;
slouken@2932
   957
    Vertex vertices[4];
slouken@2932
   958
    HRESULT result;
slouken@2932
   959
slouken@2932
   960
    if (data->beginScene) {
slouken@2932
   961
        IDirect3DDevice9_BeginScene(data->device);
slouken@2932
   962
        data->beginScene = SDL_FALSE;
slouken@2932
   963
    }
slouken@2932
   964
slouken@2932
   965
    minx = (float) rect->x - 0.5f;
slouken@2932
   966
    miny = (float) rect->y - 0.5f;
slouken@2932
   967
    maxx = (float) rect->x + rect->w - 0.5f;
slouken@2932
   968
    maxy = (float) rect->y + rect->h - 0.5f;
slouken@2932
   969
slouken@2932
   970
    color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
slouken@2932
   971
slouken@2932
   972
    vertices[0].x = minx;
slouken@2932
   973
    vertices[0].y = miny;
slouken@2932
   974
    vertices[0].z = 0.0f;
slouken@2932
   975
    vertices[0].rhw = 1.0f;
slouken@2932
   976
    vertices[0].color = color;
slouken@2932
   977
    vertices[0].u = 0.0f;
slouken@2932
   978
    vertices[0].v = 0.0f;
slouken@2932
   979
slouken@2932
   980
    vertices[1].x = maxx;
slouken@2932
   981
    vertices[1].y = miny;
slouken@2932
   982
    vertices[1].z = 0.0f;
slouken@2932
   983
    vertices[1].rhw = 1.0f;
slouken@2932
   984
    vertices[1].color = color;
slouken@2932
   985
    vertices[1].u = 0.0f;
slouken@2932
   986
    vertices[1].v = 0.0f;
slouken@2932
   987
slouken@2932
   988
    vertices[2].x = maxx;
slouken@2932
   989
    vertices[2].y = maxy;
slouken@2932
   990
    vertices[2].z = 0.0f;
slouken@2932
   991
    vertices[2].rhw = 1.0f;
slouken@2932
   992
    vertices[2].color = color;
slouken@2932
   993
    vertices[2].u = 0.0f;
slouken@2932
   994
    vertices[2].v = 0.0f;
slouken@2932
   995
slouken@2932
   996
    vertices[3].x = minx;
slouken@2932
   997
    vertices[3].y = maxy;
slouken@2932
   998
    vertices[3].z = 0.0f;
slouken@2932
   999
    vertices[3].rhw = 1.0f;
slouken@2932
  1000
    vertices[3].color = color;
slouken@2932
  1001
    vertices[3].u = 0.0f;
slouken@2932
  1002
    vertices[3].v = 0.0f;
slouken@2932
  1003
slouken@2932
  1004
    D3D_SetBlendMode(data, renderer->blendMode);
slouken@2932
  1005
slouken@2933
  1006
    result =
slouken@2933
  1007
        IDirect3DDevice9_SetTexture(data->device, 0,
slouken@2933
  1008
                                    (IDirect3DBaseTexture9 *) 0);
slouken@2932
  1009
    if (FAILED(result)) {
slouken@2932
  1010
        D3D_SetError("SetTexture()", result);
slouken@2932
  1011
        return -1;
slouken@2932
  1012
    }
slouken@2932
  1013
    result =
slouken@2932
  1014
        IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN, 2,
slouken@2932
  1015
                                         vertices, sizeof(*vertices));
slouken@2932
  1016
    if (FAILED(result)) {
slouken@2932
  1017
        D3D_SetError("DrawPrimitiveUP()", result);
slouken@1900
  1018
        return -1;
slouken@1900
  1019
    }
slouken@1895
  1020
    return 0;
slouken@1895
  1021
}
slouken@1895
  1022
slouken@1895
  1023
static int
slouken@1913
  1024
D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1985
  1025
               const SDL_Rect * srcrect, const SDL_Rect * dstrect)
slouken@1895
  1026
{
slouken@1913
  1027
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@1913
  1028
    D3D_TextureData *texturedata = (D3D_TextureData *) texture->driverdata;
slouken@1903
  1029
    float minx, miny, maxx, maxy;
slouken@1904
  1030
    float minu, maxu, minv, maxv;
slouken@1987
  1031
    DWORD color;
slouken@1903
  1032
    Vertex vertices[4];
slouken@1903
  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@1903
  1039
slouken@1904
  1040
    minx = (float) dstrect->x - 0.5f;
slouken@1904
  1041
    miny = (float) dstrect->y - 0.5f;
slouken@1904
  1042
    maxx = (float) dstrect->x + dstrect->w - 0.5f;
slouken@1904
  1043
    maxy = (float) dstrect->y + dstrect->h - 0.5f;
slouken@1903
  1044
slouken@1904
  1045
    minu = (float) srcrect->x / texture->w;
slouken@1904
  1046
    maxu = (float) (srcrect->x + srcrect->w) / texture->w;
slouken@1904
  1047
    minv = (float) srcrect->y / texture->h;
slouken@1904
  1048
    maxv = (float) (srcrect->y + srcrect->h) / texture->h;
slouken@1903
  1049
slouken@1987
  1050
    color = D3DCOLOR_ARGB(texture->a, texture->r, texture->g, texture->b);
slouken@1987
  1051
slouken@1903
  1052
    vertices[0].x = minx;
slouken@1903
  1053
    vertices[0].y = miny;
slouken@1903
  1054
    vertices[0].z = 0.0f;
slouken@1904
  1055
    vertices[0].rhw = 1.0f;
slouken@1987
  1056
    vertices[0].color = color;
slouken@1904
  1057
    vertices[0].u = minu;
slouken@1904
  1058
    vertices[0].v = minv;
slouken@1904
  1059
slouken@1903
  1060
    vertices[1].x = maxx;
slouken@1903
  1061
    vertices[1].y = miny;
slouken@1903
  1062
    vertices[1].z = 0.0f;
slouken@1904
  1063
    vertices[1].rhw = 1.0f;
slouken@1987
  1064
    vertices[1].color = color;
slouken@1904
  1065
    vertices[1].u = maxu;
slouken@1904
  1066
    vertices[1].v = minv;
slouken@1904
  1067
slouken@1903
  1068
    vertices[2].x = maxx;
slouken@1903
  1069
    vertices[2].y = maxy;
slouken@1903
  1070
    vertices[2].z = 0.0f;
slouken@1904
  1071
    vertices[2].rhw = 1.0f;
slouken@1987
  1072
    vertices[2].color = color;
slouken@1904
  1073
    vertices[2].u = maxu;
slouken@1904
  1074
    vertices[2].v = maxv;
slouken@1904
  1075
slouken@1903
  1076
    vertices[3].x = minx;
slouken@1903
  1077
    vertices[3].y = maxy;
slouken@1903
  1078
    vertices[3].z = 0.0f;
slouken@1904
  1079
    vertices[3].rhw = 1.0f;
slouken@1987
  1080
    vertices[3].color = color;
slouken@1904
  1081
    vertices[3].u = minu;
slouken@1904
  1082
    vertices[3].v = maxv;
slouken@1903
  1083
slouken@2932
  1084
    D3D_SetBlendMode(data, texture->blendMode);
slouken@1916
  1085
slouken@1985
  1086
    switch (texture->scaleMode) {
slouken@1965
  1087
    case SDL_TEXTURESCALEMODE_NONE:
slouken@1965
  1088
    case SDL_TEXTURESCALEMODE_FAST:
slouken@1917
  1089
        IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MINFILTER,
slouken@1917
  1090
                                         D3DTEXF_POINT);
slouken@1917
  1091
        IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MAGFILTER,
slouken@1917
  1092
                                         D3DTEXF_POINT);
slouken@1917
  1093
        break;
slouken@1965
  1094
    case SDL_TEXTURESCALEMODE_SLOW:
slouken@1917
  1095
        IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MINFILTER,
slouken@1917
  1096
                                         D3DTEXF_LINEAR);
slouken@1917
  1097
        IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MAGFILTER,
slouken@1917
  1098
                                         D3DTEXF_LINEAR);
slouken@1917
  1099
        break;
slouken@1965
  1100
    case SDL_TEXTURESCALEMODE_BEST:
slouken@1917
  1101
        IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MINFILTER,
slouken@1917
  1102
                                         D3DTEXF_GAUSSIANQUAD);
slouken@1917
  1103
        IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MAGFILTER,
slouken@1917
  1104
                                         D3DTEXF_GAUSSIANQUAD);
slouken@1917
  1105
        break;
slouken@1917
  1106
    }
slouken@1917
  1107
slouken@1903
  1108
    result =
slouken@2735
  1109
        IDirect3DDevice9_SetTexture(data->device, 0, (IDirect3DBaseTexture9 *)
slouken@2735
  1110
                                    texturedata->texture);
slouken@1903
  1111
    if (FAILED(result)) {
slouken@1903
  1112
        D3D_SetError("SetTexture()", result);
slouken@1903
  1113
        return -1;
slouken@1903
  1114
    }
slouken@1903
  1115
    result =
slouken@1903
  1116
        IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN, 2,
slouken@1903
  1117
                                         vertices, sizeof(*vertices));
slouken@1903
  1118
    if (FAILED(result)) {
slouken@1903
  1119
        D3D_SetError("DrawPrimitiveUP()", result);
slouken@1903
  1120
        return -1;
slouken@1903
  1121
    }
slouken@1895
  1122
    return 0;
slouken@1895
  1123
}
slouken@1895
  1124
slouken@1895
  1125
static void
slouken@1913
  1126
D3D_RenderPresent(SDL_Renderer * renderer)
slouken@1895
  1127
{
slouken@1913
  1128
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@1900
  1129
    HRESULT result;
slouken@1900
  1130
slouken@1900
  1131
    if (!data->beginScene) {
slouken@1900
  1132
        IDirect3DDevice9_EndScene(data->device);
slouken@1900
  1133
        data->beginScene = SDL_TRUE;
slouken@1900
  1134
    }
slouken@1900
  1135
slouken@1975
  1136
    result = IDirect3DDevice9_TestCooperativeLevel(data->device);
slouken@1975
  1137
    if (result == D3DERR_DEVICELOST) {
slouken@1975
  1138
        /* We'll reset later */
slouken@1975
  1139
        return;
slouken@1975
  1140
    }
slouken@1975
  1141
    if (result == D3DERR_DEVICENOTRESET) {
slouken@1975
  1142
        D3D_Reset(renderer);
slouken@1975
  1143
    }
slouken@1900
  1144
    result = IDirect3DDevice9_Present(data->device, NULL, NULL, NULL, NULL);
slouken@1900
  1145
    if (FAILED(result)) {
slouken@1900
  1146
        D3D_SetError("Present()", result);
slouken@1900
  1147
    }
slouken@1895
  1148
}
slouken@1895
  1149
slouken@1895
  1150
static void
slouken@1913
  1151
D3D_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1895
  1152
{
slouken@1913
  1153
    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
slouken@1895
  1154
slouken@1895
  1155
    if (!data) {
slouken@1895
  1156
        return;
slouken@1895
  1157
    }
slouken@2973
  1158
    if (data->yuv) {
slouken@2973
  1159
        SDL_SW_DestroyYUVTexture(data->yuv);
slouken@2973
  1160
    }
slouken@1903
  1161
    if (data->texture) {
slouken@1903
  1162
        IDirect3DTexture9_Release(data->texture);
slouken@1903
  1163
    }
slouken@1895
  1164
    SDL_free(data);
slouken@1895
  1165
    texture->driverdata = NULL;
slouken@1895
  1166
}
slouken@1895
  1167
slouken@1975
  1168
static void
slouken@1913
  1169
D3D_DestroyRenderer(SDL_Renderer * renderer)
slouken@1895
  1170
{
slouken@1913
  1171
    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
slouken@1895
  1172
slouken@1895
  1173
    if (data) {
slouken@1900
  1174
        if (data->device) {
slouken@1900
  1175
            IDirect3DDevice9_Release(data->device);
slouken@1900
  1176
        }
slouken@1895
  1177
        SDL_free(data);
slouken@1895
  1178
    }
slouken@1895
  1179
    SDL_free(renderer);
slouken@1895
  1180
}
slouken@1895
  1181
slouken@1895
  1182
#endif /* SDL_VIDEO_RENDER_D3D */
slouken@1895
  1183
slouken@1895
  1184
/* vi: set ts=4 sw=4 expandtab: */