src/video/win32/SDL_d3drender.c
author Sam Lantinga <slouken@libsdl.org>
Fri, 14 Jul 2006 07:41:16 +0000
changeset 1904 1a713f9d1f71
parent 1903 f132024010be
child 1905 36d52b1f0504
permissions -rw-r--r--
Yay! D3D renderer works!
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2006 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 
    28 /* Direct3D renderer implementation */
    29 
    30 static SDL_Renderer *SDL_D3D_CreateRenderer(SDL_Window * window,
    31                                             Uint32 flags);
    32 static int SDL_D3D_CreateTexture(SDL_Renderer * renderer,
    33                                  SDL_Texture * texture);
    34 static int SDL_D3D_SetTexturePalette(SDL_Renderer * renderer,
    35                                      SDL_Texture * texture,
    36                                      const SDL_Color * colors, int firstcolor,
    37                                      int ncolors);
    38 static int SDL_D3D_GetTexturePalette(SDL_Renderer * renderer,
    39                                      SDL_Texture * texture,
    40                                      SDL_Color * colors, int firstcolor,
    41                                      int ncolors);
    42 static int SDL_D3D_UpdateTexture(SDL_Renderer * renderer,
    43                                  SDL_Texture * texture, const SDL_Rect * rect,
    44                                  const void *pixels, int pitch);
    45 static int SDL_D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
    46                                const SDL_Rect * rect, int markDirty,
    47                                void **pixels, int *pitch);
    48 static void SDL_D3D_UnlockTexture(SDL_Renderer * renderer,
    49                                   SDL_Texture * texture);
    50 static void SDL_D3D_DirtyTexture(SDL_Renderer * renderer,
    51                                  SDL_Texture * texture, int numrects,
    52                                  const SDL_Rect * rects);
    53 static void SDL_D3D_SelectRenderTexture(SDL_Renderer * renderer,
    54                                         SDL_Texture * texture);
    55 static int SDL_D3D_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect,
    56                               Uint32 color);
    57 static int SDL_D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
    58                               const SDL_Rect * srcrect,
    59                               const SDL_Rect * dstrect, int blendMode,
    60                               int scaleMode);
    61 static int SDL_D3D_RenderReadPixels(SDL_Renderer * renderer,
    62                                     const SDL_Rect * rect, void *pixels,
    63                                     int pitch);
    64 static int SDL_D3D_RenderWritePixels(SDL_Renderer * renderer,
    65                                      const SDL_Rect * rect,
    66                                      const void *pixels, int pitch);
    67 static void SDL_D3D_RenderPresent(SDL_Renderer * renderer);
    68 static void SDL_D3D_DestroyTexture(SDL_Renderer * renderer,
    69                                    SDL_Texture * texture);
    70 static void SDL_D3D_DestroyRenderer(SDL_Renderer * renderer);
    71 
    72 
    73 SDL_RenderDriver SDL_D3D_RenderDriver = {
    74     SDL_D3D_CreateRenderer,
    75     {
    76      "d3d",
    77      (                          //SDL_Renderer_Minimal |
    78          SDL_Renderer_SingleBuffer | SDL_Renderer_PresentCopy |
    79          SDL_Renderer_PresentFlip2 | SDL_Renderer_PresentFlip3 |
    80          SDL_Renderer_PresentDiscard | SDL_Renderer_RenderTarget),
    81      (SDL_TextureBlendMode_None |
    82       SDL_TextureBlendMode_Mask | SDL_TextureBlendMode_Blend),
    83      (SDL_TextureScaleMode_None | SDL_TextureScaleMode_Fast),
    84      12,
    85      {
    86       SDL_PixelFormat_Index8,
    87       SDL_PixelFormat_RGB332,
    88       SDL_PixelFormat_RGB444,
    89       SDL_PixelFormat_RGB555,
    90       SDL_PixelFormat_ARGB4444,
    91       SDL_PixelFormat_ARGB1555,
    92       SDL_PixelFormat_RGB565,
    93       SDL_PixelFormat_RGB888,
    94       SDL_PixelFormat_ARGB8888,
    95       SDL_PixelFormat_ARGB2101010,
    96       SDL_PixelFormat_UYVY,
    97       SDL_PixelFormat_YUY2},
    98      0,
    99      0}
   100 };
   101 
   102 typedef struct
   103 {
   104     IDirect3DDevice9 *device;
   105     SDL_bool beginScene;
   106 } SDL_D3D_RenderData;
   107 
   108 typedef struct
   109 {
   110     IDirect3DTexture9 *texture;
   111 } SDL_D3D_TextureData;
   112 
   113 typedef struct
   114 {
   115     float x, y, z;
   116     float rhw;
   117     float u, v;
   118 } Vertex;
   119 
   120 static void
   121 D3D_SetError(const char *prefix, HRESULT result)
   122 {
   123     const char *error;
   124 
   125     switch (result) {
   126     case D3DERR_WRONGTEXTUREFORMAT:
   127         error = "WRONGTEXTUREFORMAT";
   128         break;
   129     case D3DERR_UNSUPPORTEDCOLOROPERATION:
   130         error = "UNSUPPORTEDCOLOROPERATION";
   131         break;
   132     case D3DERR_UNSUPPORTEDCOLORARG:
   133         error = "UNSUPPORTEDCOLORARG";
   134         break;
   135     case D3DERR_UNSUPPORTEDALPHAOPERATION:
   136         error = "UNSUPPORTEDALPHAOPERATION";
   137         break;
   138     case D3DERR_UNSUPPORTEDALPHAARG:
   139         error = "UNSUPPORTEDALPHAARG";
   140         break;
   141     case D3DERR_TOOMANYOPERATIONS:
   142         error = "TOOMANYOPERATIONS";
   143         break;
   144     case D3DERR_CONFLICTINGTEXTUREFILTER:
   145         error = "CONFLICTINGTEXTUREFILTER";
   146         break;
   147     case D3DERR_UNSUPPORTEDFACTORVALUE:
   148         error = "UNSUPPORTEDFACTORVALUE";
   149         break;
   150     case D3DERR_CONFLICTINGRENDERSTATE:
   151         error = "CONFLICTINGRENDERSTATE";
   152         break;
   153     case D3DERR_UNSUPPORTEDTEXTUREFILTER:
   154         error = "UNSUPPORTEDTEXTUREFILTER";
   155         break;
   156     case D3DERR_CONFLICTINGTEXTUREPALETTE:
   157         error = "CONFLICTINGTEXTUREPALETTE";
   158         break;
   159     case D3DERR_DRIVERINTERNALERROR:
   160         error = "DRIVERINTERNALERROR";
   161         break;
   162     case D3DERR_NOTFOUND:
   163         error = "NOTFOUND";
   164         break;
   165     case D3DERR_MOREDATA:
   166         error = "MOREDATA";
   167         break;
   168     case D3DERR_DEVICELOST:
   169         error = "DEVICELOST";
   170         break;
   171     case D3DERR_DEVICENOTRESET:
   172         error = "DEVICENOTRESET";
   173         break;
   174     case D3DERR_NOTAVAILABLE:
   175         error = "NOTAVAILABLE";
   176         break;
   177     case D3DERR_OUTOFVIDEOMEMORY:
   178         error = "OUTOFVIDEOMEMORY";
   179         break;
   180     case D3DERR_INVALIDDEVICE:
   181         error = "INVALIDDEVICE";
   182         break;
   183     case D3DERR_INVALIDCALL:
   184         error = "INVALIDCALL";
   185         break;
   186     case D3DERR_DRIVERINVALIDCALL:
   187         error = "DRIVERINVALIDCALL";
   188         break;
   189     case D3DERR_WASSTILLDRAWING:
   190         error = "WASSTILLDRAWING";
   191         break;
   192     default:
   193         error = "UNKNOWN";
   194         break;
   195     }
   196     SDL_SetError("%s: %s", prefix, error);
   197 }
   198 
   199 static D3DFORMAT
   200 PixelFormatToD3DFMT(Uint32 format)
   201 {
   202     switch (format) {
   203     case SDL_PixelFormat_Index8:
   204         return D3DFMT_P8;
   205     case SDL_PixelFormat_RGB332:
   206         return D3DFMT_R3G3B2;
   207     case SDL_PixelFormat_RGB444:
   208         return D3DFMT_X4R4G4B4;
   209     case SDL_PixelFormat_RGB555:
   210         return D3DFMT_X1R5G5B5;
   211     case SDL_PixelFormat_ARGB4444:
   212         return D3DFMT_A4R4G4B4;
   213     case SDL_PixelFormat_ARGB1555:
   214         return D3DFMT_A1R5G5B5;
   215     case SDL_PixelFormat_RGB565:
   216         return D3DFMT_R5G6B5;
   217     case SDL_PixelFormat_RGB888:
   218         return D3DFMT_X8R8G8B8;
   219     case SDL_PixelFormat_ARGB8888:
   220         return D3DFMT_A8R8G8B8;
   221     case SDL_PixelFormat_ARGB2101010:
   222         return D3DFMT_A2R10G10B10;
   223     case SDL_PixelFormat_UYVY:
   224         return D3DFMT_UYVY;
   225     case SDL_PixelFormat_YUY2:
   226         return D3DFMT_YUY2;
   227     default:
   228         return D3DFMT_UNKNOWN;
   229     }
   230 }
   231 
   232 void
   233 D3D_AddRenderDriver(_THIS)
   234 {
   235     SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
   236 
   237     if (data->d3d) {
   238         SDL_AddRenderDriver(0, &SDL_D3D_RenderDriver);
   239     }
   240 }
   241 
   242 SDL_Renderer *
   243 SDL_D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
   244 {
   245     SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
   246     SDL_VideoData *videodata = (SDL_VideoData *) display->device->driverdata;
   247     SDL_WindowData *windowdata = (SDL_WindowData *) window->driverdata;
   248     SDL_Renderer *renderer;
   249     SDL_D3D_RenderData *data;
   250     HRESULT result;
   251     D3DPRESENT_PARAMETERS pparams;
   252 
   253     renderer = (SDL_Renderer *) SDL_malloc(sizeof(*renderer));
   254     if (!renderer) {
   255         SDL_OutOfMemory();
   256         return NULL;
   257     }
   258     SDL_zerop(renderer);
   259 
   260     data = (SDL_D3D_RenderData *) SDL_malloc(sizeof(*data));
   261     if (!data) {
   262         SDL_D3D_DestroyRenderer(renderer);
   263         SDL_OutOfMemory();
   264         return NULL;
   265     }
   266     SDL_zerop(data);
   267 
   268     renderer->CreateTexture = SDL_D3D_CreateTexture;
   269     renderer->SetTexturePalette = SDL_D3D_SetTexturePalette;
   270     renderer->GetTexturePalette = SDL_D3D_GetTexturePalette;
   271     renderer->UpdateTexture = SDL_D3D_UpdateTexture;
   272     renderer->LockTexture = SDL_D3D_LockTexture;
   273     renderer->UnlockTexture = SDL_D3D_UnlockTexture;
   274     renderer->DirtyTexture = SDL_D3D_DirtyTexture;
   275     renderer->SelectRenderTexture = SDL_D3D_SelectRenderTexture;
   276     renderer->RenderFill = SDL_D3D_RenderFill;
   277     renderer->RenderCopy = SDL_D3D_RenderCopy;
   278     renderer->RenderReadPixels = SDL_D3D_RenderReadPixels;
   279     renderer->RenderWritePixels = SDL_D3D_RenderWritePixels;
   280     renderer->RenderPresent = SDL_D3D_RenderPresent;
   281     renderer->DestroyTexture = SDL_D3D_DestroyTexture;
   282     renderer->DestroyRenderer = SDL_D3D_DestroyRenderer;
   283     renderer->info = SDL_D3D_RenderDriver.info;
   284     renderer->window = window->id;
   285     renderer->driverdata = data;
   286 
   287     renderer->info.flags = SDL_Renderer_RenderTarget;
   288 
   289     SDL_zero(pparams);
   290     pparams.BackBufferWidth = window->w;
   291     pparams.BackBufferHeight = window->h;
   292     if (window->flags & SDL_WINDOW_FULLSCREEN) {
   293         pparams.BackBufferFormat =
   294             PixelFormatToD3DFMT(display->fullscreen_mode->format);
   295     } else {
   296         pparams.BackBufferFormat = D3DFMT_UNKNOWN;
   297     }
   298     if (flags & SDL_Renderer_PresentFlip2) {
   299         pparams.BackBufferCount = 2;
   300         pparams.SwapEffect = D3DSWAPEFFECT_FLIP;
   301     } else if (flags & SDL_Renderer_PresentFlip3) {
   302         pparams.BackBufferCount = 3;
   303         pparams.SwapEffect = D3DSWAPEFFECT_FLIP;
   304     } else if (flags & SDL_Renderer_PresentCopy) {
   305         pparams.BackBufferCount = 1;
   306         pparams.SwapEffect = D3DSWAPEFFECT_COPY;
   307     } else {
   308         pparams.BackBufferCount = 1;
   309         pparams.SwapEffect = D3DSWAPEFFECT_DISCARD;
   310     }
   311     if (window->flags & SDL_WINDOW_FULLSCREEN) {
   312         pparams.Windowed = FALSE;
   313         pparams.FullScreen_RefreshRateInHz =
   314             display->fullscreen_mode->refresh_rate;
   315     } else {
   316         pparams.Windowed = TRUE;
   317         pparams.FullScreen_RefreshRateInHz = 0;
   318     }
   319     pparams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
   320 
   321     result = IDirect3D9_CreateDevice(videodata->d3d, D3DADAPTER_DEFAULT,        /* FIXME */
   322                                      D3DDEVTYPE_HAL,
   323                                      windowdata->hwnd,
   324                                      D3DCREATE_SOFTWARE_VERTEXPROCESSING,
   325                                      &pparams, &data->device);
   326     if (FAILED(result)) {
   327         SDL_D3D_DestroyRenderer(renderer);
   328         D3D_SetError("CreateDevice()", result);
   329         return NULL;
   330     }
   331     data->beginScene = SDL_TRUE;
   332 
   333     /* Set up parameters for rendering */
   334     IDirect3DDevice9_SetVertexShader(data->device, NULL);
   335     IDirect3DDevice9_SetFVF(data->device, D3DFVF_XYZRHW | D3DFVF_TEX1);
   336     IDirect3DDevice9_SetRenderState(data->device, D3DRS_CULLMODE,
   337                                     D3DCULL_NONE);
   338     IDirect3DDevice9_SetRenderState(data->device, D3DRS_LIGHTING, FALSE);
   339     IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
   340                                     TRUE);
   341     IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
   342                                     D3DBLEND_SRCALPHA);
   343     IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
   344                                     D3DBLEND_INVSRCALPHA);
   345 
   346     return renderer;
   347 }
   348 
   349 static int
   350 SDL_D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   351 {
   352     SDL_D3D_RenderData *renderdata =
   353         (SDL_D3D_RenderData *) renderer->driverdata;
   354     SDL_Window *window = SDL_GetWindowFromID(renderer->window);
   355     SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
   356     SDL_D3D_TextureData *data;
   357     D3DPOOL pool;
   358     HRESULT result;
   359 
   360     data = (SDL_D3D_TextureData *) SDL_malloc(sizeof(*data));
   361     if (!data) {
   362         SDL_OutOfMemory();
   363         return -1;
   364     }
   365     SDL_zerop(data);
   366 
   367     texture->driverdata = data;
   368 
   369     if (texture->access == SDL_TextureAccess_Local) {
   370         pool = D3DPOOL_MANAGED;
   371     } else {
   372         pool = D3DPOOL_DEFAULT;
   373     }
   374     result =
   375         IDirect3DDevice9_CreateTexture(renderdata->device, texture->w,
   376                                        texture->h, 1, 0,
   377                                        PixelFormatToD3DFMT(texture->format),
   378                                        pool, &data->texture, NULL);
   379     if (FAILED(result)) {
   380         SDL_free(data);
   381         D3D_SetError("CreateTexture()", result);
   382         return -1;
   383     }
   384 
   385     return 0;
   386 }
   387 
   388 static int
   389 SDL_D3D_SetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
   390                           const SDL_Color * colors, int firstcolor,
   391                           int ncolors)
   392 {
   393     SDL_D3D_RenderData *renderdata =
   394         (SDL_D3D_RenderData *) renderer->driverdata;
   395     SDL_D3D_TextureData *data = (SDL_D3D_TextureData *) texture->driverdata;
   396 
   397     return 0;
   398 }
   399 
   400 static int
   401 SDL_D3D_GetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
   402                           SDL_Color * colors, int firstcolor, int ncolors)
   403 {
   404     SDL_D3D_TextureData *data = (SDL_D3D_TextureData *) texture->driverdata;
   405 
   406     return 0;
   407 }
   408 
   409 static int
   410 SDL_D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   411                       const SDL_Rect * rect, const void *pixels, int pitch)
   412 {
   413     SDL_D3D_TextureData *data = (SDL_D3D_TextureData *) texture->driverdata;
   414     SDL_D3D_RenderData *renderdata =
   415         (SDL_D3D_RenderData *) renderer->driverdata;
   416     IDirect3DTexture9 *temp;
   417     RECT d3drect;
   418     D3DLOCKED_RECT locked;
   419     const Uint8 *src;
   420     Uint8 *dst;
   421     int row, length;
   422     HRESULT result;
   423 
   424     result =
   425         IDirect3DDevice9_CreateTexture(renderdata->device, texture->w,
   426                                        texture->h, 1, 0,
   427                                        PixelFormatToD3DFMT(texture->format),
   428                                        D3DPOOL_SYSTEMMEM, &temp, NULL);
   429     if (FAILED(result)) {
   430         D3D_SetError("CreateTexture()", result);
   431         return -1;
   432     }
   433 
   434     d3drect.left = rect->x;
   435     d3drect.right = rect->x + rect->w;
   436     d3drect.top = rect->y;
   437     d3drect.bottom = rect->y + rect->h;
   438 
   439     result = IDirect3DTexture9_LockRect(temp, 0, &locked, &d3drect, 0);
   440     if (FAILED(result)) {
   441         IDirect3DTexture9_Release(temp);
   442         D3D_SetError("LockRect()", result);
   443         return -1;
   444     }
   445 
   446     src = pixels;
   447     dst = locked.pBits;
   448     length = rect->w * SDL_BYTESPERPIXEL(texture->format);
   449     for (row = 0; row < rect->h; ++row) {
   450         SDL_memcpy(dst, src, length);
   451         src += pitch;
   452         dst += locked.Pitch;
   453     }
   454     IDirect3DTexture9_UnlockRect(temp, 0);
   455 
   456     result =
   457         IDirect3DDevice9_UpdateTexture(renderdata->device,
   458                                        (IDirect3DBaseTexture9 *) temp,
   459                                        (IDirect3DBaseTexture9 *) data->
   460                                        texture);
   461     IDirect3DTexture9_Release(temp);
   462     if (FAILED(result)) {
   463         D3D_SetError("UpdateTexture()", result);
   464         return -1;
   465     }
   466     return 0;
   467 }
   468 
   469 static int
   470 SDL_D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   471                     const SDL_Rect * rect, int markDirty, void **pixels,
   472                     int *pitch)
   473 {
   474     SDL_D3D_TextureData *data = (SDL_D3D_TextureData *) texture->driverdata;
   475     RECT d3drect;
   476     D3DLOCKED_RECT locked;
   477     HRESULT result;
   478 
   479     if (texture->access != SDL_TextureAccess_Local) {
   480         SDL_SetError("Can't lock remote video memory");
   481         return -1;
   482     }
   483 
   484     d3drect.left = rect->x;
   485     d3drect.right = rect->x + rect->w;
   486     d3drect.top = rect->y;
   487     d3drect.bottom = rect->y + rect->h;
   488 
   489     result =
   490         IDirect3DTexture9_LockRect(data->texture, 0, &locked, &d3drect,
   491                                    markDirty ? 0 : D3DLOCK_NO_DIRTY_UPDATE);
   492     if (FAILED(result)) {
   493         D3D_SetError("LockRect()", result);
   494         return -1;
   495     }
   496     *pixels = locked.pBits;
   497     *pitch = locked.Pitch;
   498     return 0;
   499 }
   500 
   501 static void
   502 SDL_D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   503 {
   504     SDL_D3D_TextureData *data = (SDL_D3D_TextureData *) texture->driverdata;
   505 
   506     IDirect3DTexture9_UnlockRect(data->texture, 0);
   507 }
   508 
   509 static void
   510 SDL_D3D_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   511                      int numrects, const SDL_Rect * rects)
   512 {
   513     SDL_D3D_TextureData *data = (SDL_D3D_TextureData *) texture->driverdata;
   514     RECT d3drect;
   515     int i;
   516 
   517     for (i = 0; i < numrects; ++i) {
   518         const SDL_Rect *rect = &rects[i];
   519 
   520         d3drect.left = rect->x;
   521         d3drect.right = rect->x + rect->w;
   522         d3drect.top = rect->y;
   523         d3drect.bottom = rect->y + rect->h;
   524 
   525         IDirect3DTexture9_AddDirtyRect(data->texture, &d3drect);
   526     }
   527 }
   528 
   529 static void
   530 SDL_D3D_SelectRenderTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   531 {
   532     SDL_D3D_RenderData *data = (SDL_D3D_RenderData *) renderer->driverdata;
   533 }
   534 
   535 static int
   536 SDL_D3D_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect,
   537                    Uint32 color)
   538 {
   539     SDL_D3D_RenderData *data = (SDL_D3D_RenderData *) renderer->driverdata;
   540     D3DRECT d3drect;
   541     HRESULT result;
   542 
   543     if (data->beginScene) {
   544         IDirect3DDevice9_BeginScene(data->device);
   545         data->beginScene = SDL_FALSE;
   546     }
   547 
   548     d3drect.x1 = rect->x;
   549     d3drect.x2 = rect->x + rect->w;
   550     d3drect.y1 = rect->y;
   551     d3drect.y2 = rect->y + rect->h;
   552 
   553     result =
   554         IDirect3DDevice9_Clear(data->device, 1, &d3drect, D3DCLEAR_TARGET,
   555                                (D3DCOLOR) color, 1.0f, 0);
   556     if (FAILED(result)) {
   557         D3D_SetError("Clear()", result);
   558         return -1;
   559     }
   560     return 0;
   561 }
   562 
   563 static int
   564 SDL_D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
   565                    const SDL_Rect * srcrect, const SDL_Rect * dstrect,
   566                    int blendMode, int scaleMode)
   567 {
   568     SDL_D3D_RenderData *data = (SDL_D3D_RenderData *) renderer->driverdata;
   569     SDL_D3D_TextureData *texturedata =
   570         (SDL_D3D_TextureData *) texture->driverdata;
   571     float minx, miny, maxx, maxy;
   572     float minu, maxu, minv, maxv;
   573     Vertex vertices[4];
   574     HRESULT result;
   575 
   576     if (data->beginScene) {
   577         IDirect3DDevice9_BeginScene(data->device);
   578         data->beginScene = SDL_FALSE;
   579     }
   580 
   581     minx = (float) dstrect->x - 0.5f;
   582     miny = (float) dstrect->y - 0.5f;
   583     maxx = (float) dstrect->x + dstrect->w - 0.5f;
   584     maxy = (float) dstrect->y + dstrect->h - 0.5f;
   585 
   586     minu = (float) srcrect->x / texture->w;
   587     maxu = (float) (srcrect->x + srcrect->w) / texture->w;
   588     minv = (float) srcrect->y / texture->h;
   589     maxv = (float) (srcrect->y + srcrect->h) / texture->h;
   590 
   591     vertices[0].x = minx;
   592     vertices[0].y = miny;
   593     vertices[0].z = 0.0f;
   594     vertices[0].rhw = 1.0f;
   595     vertices[0].u = minu;
   596     vertices[0].v = minv;
   597 
   598     vertices[1].x = maxx;
   599     vertices[1].y = miny;
   600     vertices[1].z = 0.0f;
   601     vertices[1].rhw = 1.0f;
   602     vertices[1].u = maxu;
   603     vertices[1].v = minv;
   604 
   605     vertices[2].x = maxx;
   606     vertices[2].y = maxy;
   607     vertices[2].z = 0.0f;
   608     vertices[2].rhw = 1.0f;
   609     vertices[2].u = maxu;
   610     vertices[2].v = maxv;
   611 
   612     vertices[3].x = minx;
   613     vertices[3].y = maxy;
   614     vertices[3].z = 0.0f;
   615     vertices[3].rhw = 1.0f;
   616     vertices[3].u = minu;
   617     vertices[3].v = maxv;
   618 
   619     result =
   620         IDirect3DDevice9_SetTexture(data->device, 0,
   621                                     (IDirect3DBaseTexture9 *) texturedata->
   622                                     texture);
   623     if (FAILED(result)) {
   624         D3D_SetError("SetTexture()", result);
   625         return -1;
   626     }
   627     result =
   628         IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN, 2,
   629                                          vertices, sizeof(*vertices));
   630     if (FAILED(result)) {
   631         D3D_SetError("DrawPrimitiveUP()", result);
   632         return -1;
   633     }
   634     return 0;
   635 }
   636 
   637 static int
   638 SDL_D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
   639                          void *pixels, int pitch)
   640 {
   641     SDL_D3D_RenderData *data = (SDL_D3D_RenderData *) renderer->driverdata;
   642 
   643     return 0;
   644 }
   645 
   646 static int
   647 SDL_D3D_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect,
   648                           const void *pixels, int pitch)
   649 {
   650     SDL_D3D_RenderData *data = (SDL_D3D_RenderData *) renderer->driverdata;
   651 
   652     return 0;
   653 }
   654 
   655 static void
   656 SDL_D3D_RenderPresent(SDL_Renderer * renderer)
   657 {
   658     SDL_D3D_RenderData *data = (SDL_D3D_RenderData *) renderer->driverdata;
   659     HRESULT result;
   660 
   661     if (!data->beginScene) {
   662         IDirect3DDevice9_EndScene(data->device);
   663         data->beginScene = SDL_TRUE;
   664     }
   665 
   666     result = IDirect3DDevice9_Present(data->device, NULL, NULL, NULL, NULL);
   667     if (FAILED(result)) {
   668         D3D_SetError("Present()", result);
   669     }
   670 }
   671 
   672 static void
   673 SDL_D3D_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   674 {
   675     SDL_D3D_TextureData *data = (SDL_D3D_TextureData *) texture->driverdata;
   676 
   677     if (!data) {
   678         return;
   679     }
   680     if (data->texture) {
   681         IDirect3DTexture9_Release(data->texture);
   682     }
   683     SDL_free(data);
   684     texture->driverdata = NULL;
   685 }
   686 
   687 void
   688 SDL_D3D_DestroyRenderer(SDL_Renderer * renderer)
   689 {
   690     SDL_D3D_RenderData *data = (SDL_D3D_RenderData *) renderer->driverdata;
   691 
   692     if (data) {
   693         if (data->device) {
   694             IDirect3DDevice9_Release(data->device);
   695         }
   696         SDL_free(data);
   697     }
   698     SDL_free(renderer);
   699 }
   700 
   701 #endif /* SDL_VIDEO_RENDER_D3D */
   702 
   703 /* vi: set ts=4 sw=4 expandtab: */