src/render/direct3d/SDL_render_d3d.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 29 Dec 2011 05:18:16 -0500
changeset 6115 d4621a7e0faa
parent 6076 e69b1bd26e0b
child 6138 4c64952a58fb
permissions -rw-r--r--
Fixed bug 1338 - Direct3D renderer should set D3DCREATE_FPU_PRESERVE for not behaving vastly different on doubles (causes 3rd party lib crashes!)

Jonas Thiem 2011-11-29 12:28:02 PST
Direct3D renderer should set D3DCREATE_FPU_PRESERVE for not behaving vastly
different to OpenGL/software rendering on doubles and break some libraries
really badly.

Most notable affected example: Lua, which does the most unpredictable things
which are really almost impossible to debug/find out for beginners who never
heard this culprit exists.

Since I believe all renderers should behave the same on that doubles simply
work as expected in a program, this should really be changed! (also this wasted
a few days of my life wondering why everything in my program was so broken)
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 #include "SDL_config.h"
    22 
    23 #if SDL_VIDEO_RENDER_D3D && !SDL_RENDER_DISABLED
    24 
    25 
    26 #include "../../core/windows/SDL_windows.h"
    27 
    28 #include "SDL_hints.h"
    29 #include "SDL_loadso.h"
    30 #include "SDL_syswm.h"
    31 #include "../SDL_sysrender.h"
    32 
    33 #if SDL_VIDEO_RENDER_D3D
    34 #define D3D_DEBUG_INFO
    35 #include <d3d9.h>
    36 #endif
    37 
    38 #ifdef ASSEMBLE_SHADER
    39 ///////////////////////////////////////////////////////////////////////////
    40 // ID3DXBuffer:
    41 // ------------
    42 // The buffer object is used by D3DX to return arbitrary size data.
    43 //
    44 // GetBufferPointer -
    45 //    Returns a pointer to the beginning of the buffer.
    46 //
    47 // GetBufferSize -
    48 //    Returns the size of the buffer, in bytes.
    49 ///////////////////////////////////////////////////////////////////////////
    50 
    51 typedef interface ID3DXBuffer ID3DXBuffer;
    52 typedef interface ID3DXBuffer *LPD3DXBUFFER;
    53 
    54 // {8BA5FB08-5195-40e2-AC58-0D989C3A0102}
    55 DEFINE_GUID(IID_ID3DXBuffer, 
    56 0x8ba5fb08, 0x5195, 0x40e2, 0xac, 0x58, 0xd, 0x98, 0x9c, 0x3a, 0x1, 0x2);
    57 
    58 #undef INTERFACE
    59 #define INTERFACE ID3DXBuffer
    60 
    61 typedef interface ID3DXBuffer {
    62     const struct ID3DXBufferVtbl FAR* lpVtbl;
    63 } ID3DXBuffer;
    64 typedef const struct ID3DXBufferVtbl ID3DXBufferVtbl;
    65 const struct ID3DXBufferVtbl
    66 {
    67     // IUnknown
    68     STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE;
    69     STDMETHOD_(ULONG, AddRef)(THIS) PURE;
    70     STDMETHOD_(ULONG, Release)(THIS) PURE;
    71 
    72     // ID3DXBuffer
    73     STDMETHOD_(LPVOID, GetBufferPointer)(THIS) PURE;
    74     STDMETHOD_(DWORD, GetBufferSize)(THIS) PURE;
    75 };
    76 
    77 HRESULT WINAPI
    78     D3DXAssembleShader(
    79         LPCSTR                          pSrcData,
    80         UINT                            SrcDataLen,
    81         CONST LPVOID*                   pDefines,
    82         LPVOID                          pInclude,
    83         DWORD                           Flags,
    84         LPD3DXBUFFER*                   ppShader,
    85         LPD3DXBUFFER*                   ppErrorMsgs);
    86 
    87 #endif /* ASSEMBLE_SHADER */
    88 
    89 
    90 /* Direct3D renderer implementation */
    91 
    92 static SDL_Renderer *D3D_CreateRenderer(SDL_Window * window, Uint32 flags);
    93 static void D3D_WindowEvent(SDL_Renderer * renderer,
    94                             const SDL_WindowEvent *event);
    95 static int D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
    96 static int D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
    97                              const SDL_Rect * rect, const void *pixels,
    98                              int pitch);
    99 static int D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   100                            const SDL_Rect * rect, void **pixels, int *pitch);
   101 static void D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
   102 static int D3D_UpdateViewport(SDL_Renderer * renderer);
   103 static int D3D_RenderClear(SDL_Renderer * renderer);
   104 static int D3D_RenderDrawPoints(SDL_Renderer * renderer,
   105                                 const SDL_Point * points, int count);
   106 static int D3D_RenderDrawLines(SDL_Renderer * renderer,
   107                                const SDL_Point * points, int count);
   108 static int D3D_RenderFillRects(SDL_Renderer * renderer,
   109                                const SDL_Rect * rects, int count);
   110 static int D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
   111                           const SDL_Rect * srcrect, const SDL_Rect * dstrect);
   112 static int D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
   113                                 Uint32 format, void * pixels, int pitch);
   114 static void D3D_RenderPresent(SDL_Renderer * renderer);
   115 static void D3D_DestroyTexture(SDL_Renderer * renderer,
   116                                SDL_Texture * texture);
   117 static void D3D_DestroyRenderer(SDL_Renderer * renderer);
   118 
   119 
   120 SDL_RenderDriver D3D_RenderDriver = {
   121     D3D_CreateRenderer,
   122     {
   123      "direct3d",
   124      (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC),
   125      1,
   126      {SDL_PIXELFORMAT_ARGB8888},
   127      0,
   128      0}
   129 };
   130 
   131 typedef struct
   132 {
   133     void* d3dDLL;
   134     IDirect3D9 *d3d;
   135     IDirect3DDevice9 *device;
   136     UINT adapter;
   137     D3DPRESENT_PARAMETERS pparams;
   138     SDL_bool updateSize;
   139     SDL_bool beginScene;
   140     D3DTEXTUREFILTERTYPE scaleMode;
   141 } D3D_RenderData;
   142 
   143 typedef struct
   144 {
   145     IDirect3DTexture9 *texture;
   146     D3DTEXTUREFILTERTYPE scaleMode;
   147 } D3D_TextureData;
   148 
   149 typedef struct
   150 {
   151     float x, y, z;
   152     DWORD color;
   153     float u, v;
   154 } Vertex;
   155 
   156 static void
   157 D3D_SetError(const char *prefix, HRESULT result)
   158 {
   159     const char *error;
   160 
   161     switch (result) {
   162     case D3DERR_WRONGTEXTUREFORMAT:
   163         error = "WRONGTEXTUREFORMAT";
   164         break;
   165     case D3DERR_UNSUPPORTEDCOLOROPERATION:
   166         error = "UNSUPPORTEDCOLOROPERATION";
   167         break;
   168     case D3DERR_UNSUPPORTEDCOLORARG:
   169         error = "UNSUPPORTEDCOLORARG";
   170         break;
   171     case D3DERR_UNSUPPORTEDALPHAOPERATION:
   172         error = "UNSUPPORTEDALPHAOPERATION";
   173         break;
   174     case D3DERR_UNSUPPORTEDALPHAARG:
   175         error = "UNSUPPORTEDALPHAARG";
   176         break;
   177     case D3DERR_TOOMANYOPERATIONS:
   178         error = "TOOMANYOPERATIONS";
   179         break;
   180     case D3DERR_CONFLICTINGTEXTUREFILTER:
   181         error = "CONFLICTINGTEXTUREFILTER";
   182         break;
   183     case D3DERR_UNSUPPORTEDFACTORVALUE:
   184         error = "UNSUPPORTEDFACTORVALUE";
   185         break;
   186     case D3DERR_CONFLICTINGRENDERSTATE:
   187         error = "CONFLICTINGRENDERSTATE";
   188         break;
   189     case D3DERR_UNSUPPORTEDTEXTUREFILTER:
   190         error = "UNSUPPORTEDTEXTUREFILTER";
   191         break;
   192     case D3DERR_CONFLICTINGTEXTUREPALETTE:
   193         error = "CONFLICTINGTEXTUREPALETTE";
   194         break;
   195     case D3DERR_DRIVERINTERNALERROR:
   196         error = "DRIVERINTERNALERROR";
   197         break;
   198     case D3DERR_NOTFOUND:
   199         error = "NOTFOUND";
   200         break;
   201     case D3DERR_MOREDATA:
   202         error = "MOREDATA";
   203         break;
   204     case D3DERR_DEVICELOST:
   205         error = "DEVICELOST";
   206         break;
   207     case D3DERR_DEVICENOTRESET:
   208         error = "DEVICENOTRESET";
   209         break;
   210     case D3DERR_NOTAVAILABLE:
   211         error = "NOTAVAILABLE";
   212         break;
   213     case D3DERR_OUTOFVIDEOMEMORY:
   214         error = "OUTOFVIDEOMEMORY";
   215         break;
   216     case D3DERR_INVALIDDEVICE:
   217         error = "INVALIDDEVICE";
   218         break;
   219     case D3DERR_INVALIDCALL:
   220         error = "INVALIDCALL";
   221         break;
   222     case D3DERR_DRIVERINVALIDCALL:
   223         error = "DRIVERINVALIDCALL";
   224         break;
   225     case D3DERR_WASSTILLDRAWING:
   226         error = "WASSTILLDRAWING";
   227         break;
   228     default:
   229         error = "UNKNOWN";
   230         break;
   231     }
   232     SDL_SetError("%s: %s", prefix, error);
   233 }
   234 
   235 static D3DFORMAT
   236 PixelFormatToD3DFMT(Uint32 format)
   237 {
   238     switch (format) {
   239     case SDL_PIXELFORMAT_RGB565:
   240         return D3DFMT_R5G6B5;
   241     case SDL_PIXELFORMAT_RGB888:
   242         return D3DFMT_X8R8G8B8;
   243     case SDL_PIXELFORMAT_ARGB8888:
   244         return D3DFMT_A8R8G8B8;
   245     default:
   246         return D3DFMT_UNKNOWN;
   247     }
   248 }
   249 
   250 static Uint32
   251 D3DFMTToPixelFormat(D3DFORMAT format)
   252 {
   253     switch (format) {
   254     case D3DFMT_R5G6B5:
   255         return SDL_PIXELFORMAT_RGB565;
   256     case D3DFMT_X8R8G8B8:
   257         return SDL_PIXELFORMAT_RGB888;
   258     case D3DFMT_A8R8G8B8:
   259         return SDL_PIXELFORMAT_ARGB8888;
   260     default:
   261         return SDL_PIXELFORMAT_UNKNOWN;
   262     }
   263 }
   264 
   265 static int
   266 D3D_Reset(SDL_Renderer * renderer)
   267 {
   268     D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
   269     HRESULT result;
   270 
   271     result = IDirect3DDevice9_Reset(data->device, &data->pparams);
   272     if (FAILED(result)) {
   273         if (result == D3DERR_DEVICELOST) {
   274             /* Don't worry about it, we'll reset later... */
   275             return 0;
   276         } else {
   277             D3D_SetError("Reset()", result);
   278             return -1;
   279         }
   280     }
   281     IDirect3DDevice9_SetVertexShader(data->device, NULL);
   282     IDirect3DDevice9_SetFVF(data->device,
   283                             D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1);
   284     IDirect3DDevice9_SetRenderState(data->device, D3DRS_CULLMODE,
   285                                     D3DCULL_NONE);
   286     IDirect3DDevice9_SetRenderState(data->device, D3DRS_LIGHTING, FALSE);
   287     return 0;
   288 }
   289 
   290 static int
   291 D3D_ActivateRenderer(SDL_Renderer * renderer)
   292 {
   293     D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
   294     HRESULT result;
   295 
   296     if (data->updateSize) {
   297         SDL_Window *window = renderer->window;
   298         int w, h;
   299 
   300         SDL_GetWindowSize(window, &w, &h);
   301         data->pparams.BackBufferWidth = w;
   302         data->pparams.BackBufferHeight = h;
   303         if (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) {
   304             data->pparams.BackBufferFormat =
   305                 PixelFormatToD3DFMT(SDL_GetWindowPixelFormat(window));
   306         } else {
   307             data->pparams.BackBufferFormat = D3DFMT_UNKNOWN;
   308         }
   309         if (D3D_Reset(renderer) < 0) {
   310             return -1;
   311         }
   312         D3D_UpdateViewport(renderer);
   313 
   314         data->updateSize = SDL_FALSE;
   315     }
   316     if (data->beginScene) {
   317         result = IDirect3DDevice9_BeginScene(data->device);
   318         if (result == D3DERR_DEVICELOST) {
   319             if (D3D_Reset(renderer) < 0) {
   320                 return -1;
   321             }
   322             result = IDirect3DDevice9_BeginScene(data->device);
   323         }
   324         if (FAILED(result)) {
   325             D3D_SetError("BeginScene()", result);
   326             return -1;
   327         }
   328         data->beginScene = SDL_FALSE;
   329     }
   330     return 0;
   331 }
   332 
   333 SDL_Renderer *
   334 D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
   335 {
   336     SDL_Renderer *renderer;
   337     D3D_RenderData *data;
   338     SDL_SysWMinfo windowinfo;
   339     HRESULT result;
   340     D3DPRESENT_PARAMETERS pparams;
   341     IDirect3DSwapChain9 *chain;
   342     D3DCAPS9 caps;
   343     Uint32 window_flags;
   344     int w, h;
   345     SDL_DisplayMode fullscreen_mode;
   346     D3DMATRIX matrix;
   347 
   348     renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
   349     if (!renderer) {
   350         SDL_OutOfMemory();
   351         return NULL;
   352     }
   353 
   354     data = (D3D_RenderData *) SDL_calloc(1, sizeof(*data));
   355     if (!data) {
   356         SDL_free(renderer);
   357         SDL_OutOfMemory();
   358         return NULL;
   359     }
   360 
   361     data->d3dDLL = SDL_LoadObject("D3D9.DLL");
   362     if (data->d3dDLL) {
   363         IDirect3D9 *(WINAPI * D3DCreate) (UINT SDKVersion);
   364 
   365         D3DCreate =
   366             (IDirect3D9 * (WINAPI *) (UINT)) SDL_LoadFunction(data->d3dDLL,
   367                                                             "Direct3DCreate9");
   368         if (D3DCreate) {
   369             data->d3d = D3DCreate(D3D_SDK_VERSION);
   370         }
   371         if (!data->d3d) {
   372             SDL_UnloadObject(data->d3dDLL);
   373             data->d3dDLL = NULL;
   374         }
   375     }
   376     if (!data->d3d) {
   377         SDL_free(renderer);
   378         SDL_free(data);
   379         SDL_SetError("Unable to create Direct3D interface");
   380         return NULL;
   381     }
   382 
   383     renderer->WindowEvent = D3D_WindowEvent;
   384     renderer->CreateTexture = D3D_CreateTexture;
   385     renderer->UpdateTexture = D3D_UpdateTexture;
   386     renderer->LockTexture = D3D_LockTexture;
   387     renderer->UnlockTexture = D3D_UnlockTexture;
   388     renderer->UpdateViewport = D3D_UpdateViewport;
   389     renderer->RenderClear = D3D_RenderClear;
   390     renderer->RenderDrawPoints = D3D_RenderDrawPoints;
   391     renderer->RenderDrawLines = D3D_RenderDrawLines;
   392     renderer->RenderFillRects = D3D_RenderFillRects;
   393     renderer->RenderCopy = D3D_RenderCopy;
   394     renderer->RenderReadPixels = D3D_RenderReadPixels;
   395     renderer->RenderPresent = D3D_RenderPresent;
   396     renderer->DestroyTexture = D3D_DestroyTexture;
   397     renderer->DestroyRenderer = D3D_DestroyRenderer;
   398     renderer->info = D3D_RenderDriver.info;
   399     renderer->driverdata = data;
   400 
   401     renderer->info.flags = SDL_RENDERER_ACCELERATED;
   402 
   403     SDL_VERSION(&windowinfo.version);
   404     SDL_GetWindowWMInfo(window, &windowinfo);
   405 
   406     window_flags = SDL_GetWindowFlags(window);
   407     SDL_GetWindowSize(window, &w, &h);
   408     SDL_GetWindowDisplayMode(window, &fullscreen_mode);
   409 
   410     SDL_zero(pparams);
   411     pparams.hDeviceWindow = windowinfo.info.win.window;
   412     pparams.BackBufferWidth = w;
   413     pparams.BackBufferHeight = h;
   414     if (window_flags & SDL_WINDOW_FULLSCREEN) {
   415         pparams.BackBufferFormat =
   416             PixelFormatToD3DFMT(fullscreen_mode.format);
   417     } else {
   418         pparams.BackBufferFormat = D3DFMT_UNKNOWN;
   419     }
   420     pparams.BackBufferCount = 1;
   421     pparams.SwapEffect = D3DSWAPEFFECT_DISCARD;
   422 
   423     if (window_flags & SDL_WINDOW_FULLSCREEN) {
   424         pparams.Windowed = FALSE;
   425         pparams.FullScreen_RefreshRateInHz =
   426             fullscreen_mode.refresh_rate;
   427     } else {
   428         pparams.Windowed = TRUE;
   429         pparams.FullScreen_RefreshRateInHz = 0;
   430     }
   431     if (flags & SDL_RENDERER_PRESENTVSYNC) {
   432         pparams.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
   433     } else {
   434         pparams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
   435     }
   436 
   437     /* FIXME: Which adapter? */
   438     data->adapter = D3DADAPTER_DEFAULT;
   439     IDirect3D9_GetDeviceCaps(data->d3d, data->adapter, D3DDEVTYPE_HAL, &caps);
   440 
   441     result = IDirect3D9_CreateDevice(data->d3d, data->adapter,
   442                                      D3DDEVTYPE_HAL,
   443                                      pparams.hDeviceWindow,
   444                                      D3DCREATE_FPU_PRESERVE | ((caps.
   445                                       DevCaps &
   446                                       D3DDEVCAPS_HWTRANSFORMANDLIGHT) ?
   447                                      D3DCREATE_HARDWARE_VERTEXPROCESSING :
   448                                      D3DCREATE_SOFTWARE_VERTEXPROCESSING),
   449                                      &pparams, &data->device);
   450     if (FAILED(result)) {
   451         D3D_DestroyRenderer(renderer);
   452         D3D_SetError("CreateDevice()", result);
   453         return NULL;
   454     }
   455     data->beginScene = SDL_TRUE;
   456     data->scaleMode = D3DTEXF_FORCE_DWORD;
   457 
   458     /* Get presentation parameters to fill info */
   459     result = IDirect3DDevice9_GetSwapChain(data->device, 0, &chain);
   460     if (FAILED(result)) {
   461         D3D_DestroyRenderer(renderer);
   462         D3D_SetError("GetSwapChain()", result);
   463         return NULL;
   464     }
   465     result = IDirect3DSwapChain9_GetPresentParameters(chain, &pparams);
   466     if (FAILED(result)) {
   467         IDirect3DSwapChain9_Release(chain);
   468         D3D_DestroyRenderer(renderer);
   469         D3D_SetError("GetPresentParameters()", result);
   470         return NULL;
   471     }
   472     IDirect3DSwapChain9_Release(chain);
   473     if (pparams.PresentationInterval == D3DPRESENT_INTERVAL_ONE) {
   474         renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
   475     }
   476     data->pparams = pparams;
   477 
   478     IDirect3DDevice9_GetDeviceCaps(data->device, &caps);
   479     renderer->info.max_texture_width = caps.MaxTextureWidth;
   480     renderer->info.max_texture_height = caps.MaxTextureHeight;
   481 
   482     /* Set up parameters for rendering */
   483     IDirect3DDevice9_SetVertexShader(data->device, NULL);
   484     IDirect3DDevice9_SetFVF(data->device,
   485                             D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1);
   486     IDirect3DDevice9_SetRenderState(data->device, D3DRS_ZENABLE, D3DZB_FALSE);
   487     IDirect3DDevice9_SetRenderState(data->device, D3DRS_CULLMODE,
   488                                     D3DCULL_NONE);
   489     IDirect3DDevice9_SetRenderState(data->device, D3DRS_LIGHTING, FALSE);
   490     /* Enable color modulation by diffuse color */
   491     IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLOROP,
   492                                           D3DTOP_MODULATE);
   493     IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLORARG1,
   494                                           D3DTA_TEXTURE);
   495     IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLORARG2,
   496                                           D3DTA_DIFFUSE);
   497     /* Enable alpha modulation by diffuse alpha */
   498     IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAOP,
   499                                           D3DTOP_MODULATE);
   500     IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAARG1,
   501                                           D3DTA_TEXTURE);
   502     IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAARG2,
   503                                           D3DTA_DIFFUSE);
   504     /* Disable second texture stage, since we're done */
   505     IDirect3DDevice9_SetTextureStageState(data->device, 1, D3DTSS_COLOROP,
   506                                           D3DTOP_DISABLE);
   507     IDirect3DDevice9_SetTextureStageState(data->device, 1, D3DTSS_ALPHAOP,
   508                                           D3DTOP_DISABLE);
   509 
   510     /* Set an identity world and view matrix */
   511     matrix.m[0][0] = 1.0f;
   512     matrix.m[0][1] = 0.0f;
   513     matrix.m[0][2] = 0.0f;
   514     matrix.m[0][3] = 0.0f;
   515     matrix.m[1][0] = 0.0f;
   516     matrix.m[1][1] = 1.0f;
   517     matrix.m[1][2] = 0.0f;
   518     matrix.m[1][3] = 0.0f;
   519     matrix.m[2][0] = 0.0f;
   520     matrix.m[2][1] = 0.0f;
   521     matrix.m[2][2] = 1.0f;
   522     matrix.m[2][3] = 0.0f;
   523     matrix.m[3][0] = 0.0f;
   524     matrix.m[3][1] = 0.0f;
   525     matrix.m[3][2] = 0.0f;
   526     matrix.m[3][3] = 1.0f;
   527     IDirect3DDevice9_SetTransform(data->device, D3DTS_WORLD, &matrix);
   528     IDirect3DDevice9_SetTransform(data->device, D3DTS_VIEW, &matrix);
   529 
   530     return renderer;
   531 }
   532 
   533 static void
   534 D3D_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
   535 {
   536     D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
   537 
   538     if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED) {
   539         data->updateSize = SDL_TRUE;
   540     }
   541 }
   542 
   543 static D3DTEXTUREFILTERTYPE
   544 GetScaleQuality(void)
   545 {
   546     const char *hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY);
   547 
   548     if (!hint || *hint == '0' || SDL_strcasecmp(hint, "nearest") == 0) {
   549         return D3DTEXF_POINT;
   550     } else if (*hint == '1' || SDL_strcasecmp(hint, "linear") == 0) {
   551         return D3DTEXF_LINEAR;
   552     } else {
   553         return D3DTEXF_ANISOTROPIC;
   554     }
   555 }
   556 
   557 static int
   558 D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   559 {
   560     D3D_RenderData *renderdata = (D3D_RenderData *) renderer->driverdata;
   561     SDL_Window *window = renderer->window;
   562     D3DFORMAT display_format = renderdata->pparams.BackBufferFormat;
   563     D3D_TextureData *data;
   564     D3DPOOL pool;
   565     DWORD usage;
   566     HRESULT result;
   567 
   568     data = (D3D_TextureData *) SDL_calloc(1, sizeof(*data));
   569     if (!data) {
   570         SDL_OutOfMemory();
   571         return -1;
   572     }
   573     data->scaleMode = GetScaleQuality();
   574 
   575     texture->driverdata = data;
   576 
   577 #ifdef USE_DYNAMIC_TEXTURE
   578     if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
   579         pool = D3DPOOL_DEFAULT;
   580         usage = D3DUSAGE_DYNAMIC;
   581     } else
   582 #endif
   583     {
   584         pool = D3DPOOL_MANAGED;
   585         usage = 0;
   586     }
   587 
   588     result =
   589         IDirect3DDevice9_CreateTexture(renderdata->device, texture->w,
   590                                        texture->h, 1, usage,
   591                                        PixelFormatToD3DFMT(texture->format),
   592                                        pool, &data->texture, NULL);
   593     if (FAILED(result)) {
   594         D3D_SetError("CreateTexture()", result);
   595         return -1;
   596     }
   597 
   598     return 0;
   599 }
   600 
   601 static int
   602 D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   603                   const SDL_Rect * rect, const void *pixels, int pitch)
   604 {
   605     D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
   606     D3D_RenderData *renderdata = (D3D_RenderData *) renderer->driverdata;
   607     RECT d3drect;
   608     D3DLOCKED_RECT locked;
   609     const Uint8 *src;
   610     Uint8 *dst;
   611     int row, length;
   612     HRESULT result;
   613 
   614 #ifdef USE_DYNAMIC_TEXTURE
   615     if (texture->access == SDL_TEXTUREACCESS_STREAMING &&
   616         rect->x == 0 && rect->y == 0 &&
   617         rect->w == texture->w && rect->h == texture->h) {
   618         result = IDirect3DTexture9_LockRect(data->texture, 0, &locked, NULL, D3DLOCK_DISCARD);
   619     } else
   620 #endif
   621     {
   622         d3drect.left = rect->x;
   623         d3drect.right = rect->x + rect->w;
   624         d3drect.top = rect->y;
   625         d3drect.bottom = rect->y + rect->h;
   626         result = IDirect3DTexture9_LockRect(data->texture, 0, &locked, &d3drect, 0);
   627     }
   628 
   629     if (FAILED(result)) {
   630         D3D_SetError("LockRect()", result);
   631         return -1;
   632     }
   633 
   634     src = pixels;
   635     dst = locked.pBits;
   636     length = rect->w * SDL_BYTESPERPIXEL(texture->format);
   637     if (length == pitch && length == locked.Pitch) {
   638         SDL_memcpy(dst, src, length*rect->h);
   639     } else {
   640         for (row = 0; row < rect->h; ++row) {
   641             SDL_memcpy(dst, src, length);
   642             src += pitch;
   643             dst += locked.Pitch;
   644         }
   645     }
   646     IDirect3DTexture9_UnlockRect(data->texture, 0);
   647 
   648     return 0;
   649 }
   650 
   651 static int
   652 D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   653                 const SDL_Rect * rect, void **pixels, int *pitch)
   654 {
   655     D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
   656     RECT d3drect;
   657     D3DLOCKED_RECT locked;
   658     HRESULT result;
   659 
   660     d3drect.left = rect->x;
   661     d3drect.right = rect->x + rect->w;
   662     d3drect.top = rect->y;
   663     d3drect.bottom = rect->y + rect->h;
   664 
   665     result = IDirect3DTexture9_LockRect(data->texture, 0, &locked, &d3drect, 0);
   666     if (FAILED(result)) {
   667         D3D_SetError("LockRect()", result);
   668         return -1;
   669     }
   670     *pixels = locked.pBits;
   671     *pitch = locked.Pitch;
   672     return 0;
   673 }
   674 
   675 static void
   676 D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   677 {
   678     D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
   679 
   680     IDirect3DTexture9_UnlockRect(data->texture, 0);
   681 }
   682 
   683 static int
   684 D3D_UpdateViewport(SDL_Renderer * renderer)
   685 {
   686     D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
   687     D3DVIEWPORT9 viewport;
   688     D3DMATRIX matrix;
   689 
   690     /* Set the viewport */
   691     viewport.X = renderer->viewport.x;
   692     viewport.Y = renderer->viewport.y;
   693     viewport.Width = renderer->viewport.w;
   694     viewport.Height = renderer->viewport.h;
   695     viewport.MinZ = 0.0f;
   696     viewport.MaxZ = 1.0f;
   697     IDirect3DDevice9_SetViewport(data->device, &viewport);
   698 
   699     /* Set an orthographic projection matrix */
   700     matrix.m[0][0] = 2.0f / renderer->viewport.w;
   701     matrix.m[0][1] = 0.0f;
   702     matrix.m[0][2] = 0.0f;
   703     matrix.m[0][3] = 0.0f;
   704     matrix.m[1][0] = 0.0f;
   705     matrix.m[1][1] = -2.0f / renderer->viewport.h;
   706     matrix.m[1][2] = 0.0f;
   707     matrix.m[1][3] = 0.0f;
   708     matrix.m[2][0] = 0.0f;
   709     matrix.m[2][1] = 0.0f;
   710     matrix.m[2][2] = 1.0f;
   711     matrix.m[2][3] = 0.0f;
   712     matrix.m[3][0] = -1.0f;
   713     matrix.m[3][1] = 1.0f;
   714     matrix.m[3][2] = 0.0f;
   715     matrix.m[3][3] = 1.0f;
   716     IDirect3DDevice9_SetTransform(data->device, D3DTS_PROJECTION, &matrix);
   717 
   718     return 0;
   719 }
   720 
   721 static int
   722 D3D_RenderClear(SDL_Renderer * renderer)
   723 {
   724     D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
   725     DWORD color;
   726     HRESULT result;
   727 
   728     if (D3D_ActivateRenderer(renderer) < 0) {
   729         return -1;
   730     }
   731 
   732     color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
   733 
   734     /* Don't reset the viewport if we don't have to! */
   735     if (!renderer->viewport.x && !renderer->viewport.y &&
   736         renderer->viewport.w == data->pparams.BackBufferWidth &&
   737         renderer->viewport.h == data->pparams.BackBufferHeight) {
   738         result = IDirect3DDevice9_Clear(data->device, 0, NULL, D3DCLEAR_TARGET, color, 0.0f, 0);
   739     } else {
   740         D3DVIEWPORT9 viewport;
   741 
   742         /* Clear is defined to clear the entire render target */
   743         viewport.X = 0;
   744         viewport.Y = 0;
   745         viewport.Width = data->pparams.BackBufferWidth;
   746         viewport.Height = data->pparams.BackBufferHeight;
   747         viewport.MinZ = 0.0f;
   748         viewport.MaxZ = 1.0f;
   749         IDirect3DDevice9_SetViewport(data->device, &viewport);
   750 
   751         result = IDirect3DDevice9_Clear(data->device, 0, NULL, D3DCLEAR_TARGET, color, 0.0f, 0);
   752 
   753         /* Reset the viewport */
   754         viewport.X = renderer->viewport.x;
   755         viewport.Y = renderer->viewport.y;
   756         viewport.Width = renderer->viewport.w;
   757         viewport.Height = renderer->viewport.h;
   758         viewport.MinZ = 0.0f;
   759         viewport.MaxZ = 1.0f;
   760         IDirect3DDevice9_SetViewport(data->device, &viewport);
   761     }
   762 
   763     if (FAILED(result)) {
   764         D3D_SetError("Clear()", result);
   765         return -1;
   766     }
   767     return 0;
   768 }
   769 
   770 static void
   771 D3D_SetBlendMode(D3D_RenderData * data, int blendMode)
   772 {
   773     switch (blendMode) {
   774     case SDL_BLENDMODE_NONE:
   775         IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
   776                                         FALSE);
   777         break;
   778     case SDL_BLENDMODE_BLEND:
   779         IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
   780                                         TRUE);
   781         IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
   782                                         D3DBLEND_SRCALPHA);
   783         IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
   784                                         D3DBLEND_INVSRCALPHA);
   785         break;
   786     case SDL_BLENDMODE_ADD:
   787         IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
   788                                         TRUE);
   789         IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
   790                                         D3DBLEND_SRCALPHA);
   791         IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
   792                                         D3DBLEND_ONE);
   793         break;
   794     case SDL_BLENDMODE_MOD:
   795         IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
   796                                         TRUE);
   797         IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
   798                                         D3DBLEND_ZERO);
   799         IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
   800                                         D3DBLEND_SRCCOLOR);
   801         break;
   802     }
   803 }
   804 
   805 static int
   806 D3D_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points,
   807                      int count)
   808 {
   809     D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
   810     DWORD color;
   811     Vertex *vertices;
   812     int i;
   813     HRESULT result;
   814 
   815     if (D3D_ActivateRenderer(renderer) < 0) {
   816         return -1;
   817     }
   818 
   819     D3D_SetBlendMode(data, renderer->blendMode);
   820 
   821     result =
   822         IDirect3DDevice9_SetTexture(data->device, 0,
   823                                     (IDirect3DBaseTexture9 *) 0);
   824     if (FAILED(result)) {
   825         D3D_SetError("SetTexture()", result);
   826         return -1;
   827     }
   828 
   829     color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
   830 
   831     vertices = SDL_stack_alloc(Vertex, count);
   832     for (i = 0; i < count; ++i) {
   833         vertices[i].x = (float) points[i].x;
   834         vertices[i].y = (float) points[i].y;
   835         vertices[i].z = 0.0f;
   836         vertices[i].color = color;
   837         vertices[i].u = 0.0f;
   838         vertices[i].v = 0.0f;
   839     }
   840     result =
   841         IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_POINTLIST, count,
   842                                          vertices, sizeof(*vertices));
   843     SDL_stack_free(vertices);
   844     if (FAILED(result)) {
   845         D3D_SetError("DrawPrimitiveUP()", result);
   846         return -1;
   847     }
   848     return 0;
   849 }
   850 
   851 static int
   852 D3D_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points,
   853                     int count)
   854 {
   855     D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
   856     DWORD color;
   857     Vertex *vertices;
   858     int i;
   859     HRESULT result;
   860 
   861     if (D3D_ActivateRenderer(renderer) < 0) {
   862         return -1;
   863     }
   864 
   865     D3D_SetBlendMode(data, renderer->blendMode);
   866 
   867     result =
   868         IDirect3DDevice9_SetTexture(data->device, 0,
   869                                     (IDirect3DBaseTexture9 *) 0);
   870     if (FAILED(result)) {
   871         D3D_SetError("SetTexture()", result);
   872         return -1;
   873     }
   874 
   875     color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
   876 
   877     vertices = SDL_stack_alloc(Vertex, count);
   878     for (i = 0; i < count; ++i) {
   879         vertices[i].x = (float) points[i].x;
   880         vertices[i].y = (float) points[i].y;
   881         vertices[i].z = 0.0f;
   882         vertices[i].color = color;
   883         vertices[i].u = 0.0f;
   884         vertices[i].v = 0.0f;
   885     }
   886     result =
   887         IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_LINESTRIP, count-1,
   888                                          vertices, sizeof(*vertices));
   889 
   890     /* DirectX 9 has the same line rasterization semantics as GDI,
   891        so we need to close the endpoint of the line */
   892     if (count == 2 ||
   893         points[0].x != points[count-1].x || points[0].y != points[count-1].y) {
   894         vertices[0].x = (float) points[count-1].x;
   895         vertices[0].y = (float) points[count-1].y;
   896         result = IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_POINTLIST, 1, vertices, sizeof(*vertices));
   897     }
   898 
   899     SDL_stack_free(vertices);
   900     if (FAILED(result)) {
   901         D3D_SetError("DrawPrimitiveUP()", result);
   902         return -1;
   903     }
   904     return 0;
   905 }
   906 
   907 static int
   908 D3D_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect * rects,
   909                     int count)
   910 {
   911     D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
   912     DWORD color;
   913     int i;
   914     float minx, miny, maxx, maxy;
   915     Vertex vertices[4];
   916     HRESULT result;
   917 
   918     if (D3D_ActivateRenderer(renderer) < 0) {
   919         return -1;
   920     }
   921 
   922     D3D_SetBlendMode(data, renderer->blendMode);
   923 
   924     result =
   925         IDirect3DDevice9_SetTexture(data->device, 0,
   926                                     (IDirect3DBaseTexture9 *) 0);
   927     if (FAILED(result)) {
   928         D3D_SetError("SetTexture()", result);
   929         return -1;
   930     }
   931 
   932     color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
   933 
   934     for (i = 0; i < count; ++i) {
   935         const SDL_Rect *rect = &rects[i];
   936 
   937         minx = (float) rect->x;
   938         miny = (float) rect->y;
   939         maxx = (float) rect->x + rect->w;
   940         maxy = (float) rect->y + rect->h;
   941 
   942         vertices[0].x = minx;
   943         vertices[0].y = miny;
   944         vertices[0].z = 0.0f;
   945         vertices[0].color = color;
   946         vertices[0].u = 0.0f;
   947         vertices[0].v = 0.0f;
   948 
   949         vertices[1].x = maxx;
   950         vertices[1].y = miny;
   951         vertices[1].z = 0.0f;
   952         vertices[1].color = color;
   953         vertices[1].u = 0.0f;
   954         vertices[1].v = 0.0f;
   955 
   956         vertices[2].x = maxx;
   957         vertices[2].y = maxy;
   958         vertices[2].z = 0.0f;
   959         vertices[2].color = color;
   960         vertices[2].u = 0.0f;
   961         vertices[2].v = 0.0f;
   962 
   963         vertices[3].x = minx;
   964         vertices[3].y = maxy;
   965         vertices[3].z = 0.0f;
   966         vertices[3].color = color;
   967         vertices[3].u = 0.0f;
   968         vertices[3].v = 0.0f;
   969 
   970         result =
   971             IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN,
   972                                              2, vertices, sizeof(*vertices));
   973         if (FAILED(result)) {
   974             D3D_SetError("DrawPrimitiveUP()", result);
   975             return -1;
   976         }
   977     }
   978     return 0;
   979 }
   980 
   981 static int
   982 D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
   983                const SDL_Rect * srcrect, const SDL_Rect * dstrect)
   984 {
   985     D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
   986     D3D_TextureData *texturedata = (D3D_TextureData *) texture->driverdata;
   987     LPDIRECT3DPIXELSHADER9 shader = NULL;
   988     float minx, miny, maxx, maxy;
   989     float minu, maxu, minv, maxv;
   990     DWORD color;
   991     Vertex vertices[4];
   992     HRESULT result;
   993 
   994     if (D3D_ActivateRenderer(renderer) < 0) {
   995         return -1;
   996     }
   997 
   998     minx = (float) dstrect->x - 0.5f;
   999     miny = (float) dstrect->y - 0.5f;
  1000     maxx = (float) dstrect->x + dstrect->w - 0.5f;
  1001     maxy = (float) dstrect->y + dstrect->h - 0.5f;
  1002 
  1003     minu = (float) srcrect->x / texture->w;
  1004     maxu = (float) (srcrect->x + srcrect->w) / texture->w;
  1005     minv = (float) srcrect->y / texture->h;
  1006     maxv = (float) (srcrect->y + srcrect->h) / texture->h;
  1007 
  1008     color = D3DCOLOR_ARGB(texture->a, texture->r, texture->g, texture->b);
  1009 
  1010     vertices[0].x = minx;
  1011     vertices[0].y = miny;
  1012     vertices[0].z = 0.0f;
  1013     vertices[0].color = color;
  1014     vertices[0].u = minu;
  1015     vertices[0].v = minv;
  1016 
  1017     vertices[1].x = maxx;
  1018     vertices[1].y = miny;
  1019     vertices[1].z = 0.0f;
  1020     vertices[1].color = color;
  1021     vertices[1].u = maxu;
  1022     vertices[1].v = minv;
  1023 
  1024     vertices[2].x = maxx;
  1025     vertices[2].y = maxy;
  1026     vertices[2].z = 0.0f;
  1027     vertices[2].color = color;
  1028     vertices[2].u = maxu;
  1029     vertices[2].v = maxv;
  1030 
  1031     vertices[3].x = minx;
  1032     vertices[3].y = maxy;
  1033     vertices[3].z = 0.0f;
  1034     vertices[3].color = color;
  1035     vertices[3].u = minu;
  1036     vertices[3].v = maxv;
  1037 
  1038     D3D_SetBlendMode(data, texture->blendMode);
  1039 
  1040     if (texturedata->scaleMode != data->scaleMode) {
  1041         IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MINFILTER,
  1042                                          texturedata->scaleMode);
  1043         IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MAGFILTER,
  1044                                          texturedata->scaleMode);
  1045         data->scaleMode = texturedata->scaleMode;
  1046     }
  1047 
  1048     result =
  1049         IDirect3DDevice9_SetTexture(data->device, 0, (IDirect3DBaseTexture9 *)
  1050                                     texturedata->texture);
  1051     if (FAILED(result)) {
  1052         D3D_SetError("SetTexture()", result);
  1053         return -1;
  1054     }
  1055     if (shader) {
  1056         result = IDirect3DDevice9_SetPixelShader(data->device, shader);
  1057         if (FAILED(result)) {
  1058             D3D_SetError("SetShader()", result);
  1059             return -1;
  1060         }
  1061     }
  1062     result =
  1063         IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN, 2,
  1064                                          vertices, sizeof(*vertices));
  1065     if (FAILED(result)) {
  1066         D3D_SetError("DrawPrimitiveUP()", result);
  1067         return -1;
  1068     }
  1069     if (shader) {
  1070         result = IDirect3DDevice9_SetPixelShader(data->device, NULL);
  1071         if (FAILED(result)) {
  1072             D3D_SetError("SetShader()", result);
  1073             return -1;
  1074         }
  1075     }
  1076     return 0;
  1077 }
  1078 
  1079 static int
  1080 D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
  1081                      Uint32 format, void * pixels, int pitch)
  1082 {
  1083     D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
  1084     D3DSURFACE_DESC desc;
  1085     LPDIRECT3DSURFACE9 backBuffer;
  1086     LPDIRECT3DSURFACE9 surface;
  1087     RECT d3drect;
  1088     D3DLOCKED_RECT locked;
  1089     HRESULT result;
  1090 
  1091     result = IDirect3DDevice9_GetBackBuffer(data->device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuffer);
  1092     if (FAILED(result)) {
  1093         D3D_SetError("GetBackBuffer()", result);
  1094         return -1;
  1095     }
  1096 
  1097     result = IDirect3DSurface9_GetDesc(backBuffer, &desc);
  1098     if (FAILED(result)) {
  1099         D3D_SetError("GetDesc()", result);
  1100         IDirect3DSurface9_Release(backBuffer);
  1101         return -1;
  1102     }
  1103 
  1104     result = IDirect3DDevice9_CreateOffscreenPlainSurface(data->device, desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surface, NULL);
  1105     if (FAILED(result)) {
  1106         D3D_SetError("CreateOffscreenPlainSurface()", result);
  1107         IDirect3DSurface9_Release(backBuffer);
  1108         return -1;
  1109     }
  1110 
  1111     result = IDirect3DDevice9_GetRenderTargetData(data->device, backBuffer, surface);
  1112     if (FAILED(result)) {
  1113         D3D_SetError("GetRenderTargetData()", result);
  1114         IDirect3DSurface9_Release(surface);
  1115         IDirect3DSurface9_Release(backBuffer);
  1116         return -1;
  1117     }
  1118 
  1119     d3drect.left = rect->x;
  1120     d3drect.right = rect->x + rect->w;
  1121     d3drect.top = rect->y;
  1122     d3drect.bottom = rect->y + rect->h;
  1123 
  1124     result = IDirect3DSurface9_LockRect(surface, &locked, &d3drect, D3DLOCK_READONLY);
  1125     if (FAILED(result)) {
  1126         D3D_SetError("LockRect()", result);
  1127         IDirect3DSurface9_Release(surface);
  1128         IDirect3DSurface9_Release(backBuffer);
  1129         return -1;
  1130     }
  1131 
  1132     SDL_ConvertPixels(rect->w, rect->h,
  1133                       D3DFMTToPixelFormat(desc.Format), locked.pBits, locked.Pitch,
  1134                       format, pixels, pitch);
  1135 
  1136     IDirect3DSurface9_UnlockRect(surface);
  1137 
  1138     IDirect3DSurface9_Release(surface);
  1139     IDirect3DSurface9_Release(backBuffer);
  1140 
  1141     return 0;
  1142 }
  1143 
  1144 static void
  1145 D3D_RenderPresent(SDL_Renderer * renderer)
  1146 {
  1147     D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
  1148     HRESULT result;
  1149 
  1150     if (!data->beginScene) {
  1151         IDirect3DDevice9_EndScene(data->device);
  1152         data->beginScene = SDL_TRUE;
  1153     }
  1154 
  1155     result = IDirect3DDevice9_TestCooperativeLevel(data->device);
  1156     if (result == D3DERR_DEVICELOST) {
  1157         /* We'll reset later */
  1158         return;
  1159     }
  1160     if (result == D3DERR_DEVICENOTRESET) {
  1161         D3D_Reset(renderer);
  1162     }
  1163     result = IDirect3DDevice9_Present(data->device, NULL, NULL, NULL, NULL);
  1164     if (FAILED(result)) {
  1165         D3D_SetError("Present()", result);
  1166     }
  1167 }
  1168 
  1169 static void
  1170 D3D_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
  1171 {
  1172     D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
  1173 
  1174     if (!data) {
  1175         return;
  1176     }
  1177     if (data->texture) {
  1178         IDirect3DTexture9_Release(data->texture);
  1179     }
  1180     SDL_free(data);
  1181     texture->driverdata = NULL;
  1182 }
  1183 
  1184 static void
  1185 D3D_DestroyRenderer(SDL_Renderer * renderer)
  1186 {
  1187     D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
  1188 
  1189     if (data) {
  1190         if (data->device) {
  1191             IDirect3DDevice9_Release(data->device);
  1192         }
  1193         if (data->d3d) {
  1194             IDirect3D9_Release(data->d3d);
  1195             SDL_UnloadObject(data->d3dDLL);
  1196         }
  1197         SDL_free(data);
  1198     }
  1199     SDL_free(renderer);
  1200 }
  1201 
  1202 #endif /* SDL_VIDEO_RENDER_D3D && !SDL_RENDER_DISABLED */
  1203 
  1204 /* vi: set ts=4 sw=4 expandtab: */