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