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