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