src/video/windows/SDL_ceddrawrender.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 31 Jan 2011 22:44:43 -0800
changeset 5138 da10636e5eca
parent 5062 e8916fe9cfc8
permissions -rw-r--r--
Making the API simpler, scaling is always defined as linear interpolation and should be supported as much as possible on all renderers.
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2010 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21     
    22     Stefan Klug
    23     klug.stefan@gmx.de
    24 */
    25 #include "SDL_config.h"
    26 
    27 #if SDL_VIDEO_RENDER_DDRAW
    28 
    29 #include "SDL_windowsvideo.h"
    30 #include "../SDL_yuv_sw_c.h"
    31 
    32 #if 0
    33 #define DDRAW_LOG(...) printf(__VA_ARGS__)
    34 #else
    35 #define DDRAW_LOG(...)
    36 #endif
    37 
    38 
    39 /* DirectDraw renderer implementation */
    40 
    41 static SDL_Renderer *DDRAW_CreateRenderer(SDL_Window * window, Uint32 flags);
    42 static int DDRAW_DisplayModeChanged(SDL_Renderer * renderer);
    43 static int DDRAW_CreateTexture(SDL_Renderer * renderer,
    44                                SDL_Texture * texture);
    45 static int DDRAW_QueryTexturePixels(SDL_Renderer * renderer,
    46                                     SDL_Texture * texture, void **pixels,
    47                                     int *pitch);
    48 static int DDRAW_SetTextureColorMod(SDL_Renderer * renderer,
    49                                     SDL_Texture * texture);
    50 static int DDRAW_SetTextureAlphaMod(SDL_Renderer * renderer,
    51                                     SDL_Texture * texture);
    52 static int DDRAW_SetTextureBlendMode(SDL_Renderer * renderer,
    53                                      SDL_Texture * texture);
    54 static int DDRAW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
    55                                const SDL_Rect * rect, const void *pixels,
    56                                int pitch);
    57 static int DDRAW_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
    58                              const SDL_Rect * rect, int markDirty,
    59                              void **pixels, int *pitch);
    60 static void DDRAW_UnlockTexture(SDL_Renderer * renderer,
    61                                 SDL_Texture * texture);
    62 static void DDRAW_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
    63                                int numrects, const SDL_Rect * rects);
    64 static int DDRAW_RenderPoint(SDL_Renderer * renderer, int x, int y);
    65 static int DDRAW_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2,
    66                             int y2);
    67 static int DDRAW_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect);
    68 static int DDRAW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
    69                             const SDL_Rect * srcrect,
    70                             const SDL_Rect * dstrect);
    71 static void DDRAW_RenderPresent(SDL_Renderer * renderer);
    72 static void DDRAW_DestroyTexture(SDL_Renderer * renderer,
    73                                  SDL_Texture * texture);
    74 static void DDRAW_DestroyRenderer(SDL_Renderer * renderer);
    75 
    76 
    77 SDL_RenderDriver DDRAW_RenderDriver = {
    78     DDRAW_CreateRenderer,
    79     {
    80      "ddraw",
    81      (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY |
    82       SDL_RENDERER_PRESENTFLIP2 | SDL_RENDERER_PRESENTFLIP3 |
    83       SDL_RENDERER_PRESENTDISCARD | SDL_RENDERER_ACCELERATED),
    84      (SDL_TEXTUREMODULATE_NONE),
    85      (SDL_BLENDMODE_NONE),
    86      0,
    87      {0},
    88      0,
    89      0}
    90 };
    91 
    92 typedef struct
    93 {
    94     IDirectDraw *ddraw;
    95     IDirectDrawSurface *primary;
    96 } DDRAW_RenderData;
    97 
    98 typedef struct
    99 {
   100     RECT lock;
   101     IDirectDrawSurface *surface;
   102 } DDRAW_TextureData;
   103 
   104 
   105 static void
   106 DDRAW_SetError(const char *prefix, HRESULT result)
   107 {
   108     const char *error;
   109 
   110     switch (result) {
   111     case DDERR_CANTCREATEDC:
   112         error = "CANTCREATEDC";
   113         break;
   114     case DDERR_CANTLOCKSURFACE:
   115         error = "CANTLOCKSURFACE";
   116         break;
   117     case DDERR_CLIPPERISUSINGHWND:
   118         error = "CLIPPERISUSINGHWND";
   119         break;
   120     case DDERR_COLORKEYNOTSET:
   121         error = "COLORKEYNOTSET";
   122         break;
   123     case DDERR_CURRENTLYNOTAVAIL:
   124         error = "CURRENTLYNOTAVAIL";
   125         break;
   126     case DDERR_DCALREADYCREATED:
   127         error = "DCALREADYCREATED";
   128         break;
   129     case DDERR_DEVICEDOESNTOWNSURFACE:
   130         error = "DEVICEDOESNTOWNSURFACE";
   131         break;
   132     case DDERR_DIRECTDRAWALREADYCREATED:
   133         error = "DIRECTDRAWALREADYCREATED";
   134         break;
   135     case DDERR_EXCLUSIVEMODEALREADYSET:
   136         error = "EXCLUSIVEMODEALREADYSET";
   137         break;
   138     case DDERR_GENERIC:
   139         error = "GENERIC";
   140         break;
   141     case DDERR_HEIGHTALIGN:
   142         error = "HEIGHTALIGN";
   143         break;
   144     case DDERR_IMPLICITLYCREATED:
   145         error = "IMPLICITLYCREATED";
   146         break;
   147     case DDERR_INCOMPATIBLEPRIMARY:
   148         error = "INCOMPATIBLEPRIMARY";
   149         break;
   150     case DDERR_INVALIDCAPS:
   151         error = "INVALIDCAPS";
   152         break;
   153     case DDERR_INVALIDCLIPLIST:
   154         error = "INVALIDCLIPLIST";
   155         break;
   156     case DDERR_INVALIDMODE:
   157         error = "INVALIDMODE";
   158         break;
   159     case DDERR_INVALIDOBJECT:
   160         error = "INVALIDOBJECT";
   161         break;
   162     case DDERR_INVALIDPARAMS:
   163         error = "INVALIDPARAMS";
   164         break;
   165     case DDERR_INVALIDPIXELFORMAT:
   166         error = "INVALIDPIXELFORMAT";
   167         break;
   168     case DDERR_INVALIDPOSITION:
   169         error = "INVALIDPOSITION";
   170         break;
   171     case DDERR_INVALIDRECT:
   172         error = "INVALIDRECT";
   173         break;
   174     case DDERR_LOCKEDSURFACES:
   175         error = "LOCKEDSURFACES";
   176         break;
   177     case DDERR_MOREDATA:
   178         error = "MOREDATA";
   179         break;
   180     case DDERR_NOALPHAHW:
   181         error = "NOALPHAHW";
   182         break;
   183     case DDERR_NOBLTHW:
   184         error = "NOBLTHW";
   185         break;
   186     case DDERR_NOCLIPLIST:
   187         error = "NOCLIPLIST";
   188         break;
   189     case DDERR_NOCLIPPERATTACHED:
   190         error = "NOCLIPPERATTACHED";
   191         break;
   192     case DDERR_NOCOLORCONVHW:
   193         error = "NOCOLORCONVHW";
   194         break;
   195     case DDERR_NOCOLORKEYHW:
   196         error = "NOCOLORKEYHW";
   197         break;
   198     case DDERR_NOCOOPERATIVELEVELSET:
   199         error = "NOCOOPERATIVELEVELSET";
   200         break;
   201     case DDERR_NODC:
   202         error = "NODC";
   203         break;
   204     case DDERR_NOFLIPHW:
   205         error = "NOFLIPHW";
   206         break;
   207     case DDERR_NOOVERLAYDEST:
   208         error = "NOOVERLAYDEST";
   209         break;
   210     case DDERR_NOOVERLAYHW:
   211         error = "NOOVERLAYHW";
   212         break;
   213     case DDERR_NOPALETTEATTACHED:
   214         error = "NOPALETTEATTACHED";
   215         break;
   216     case DDERR_NOPALETTEHW:
   217         error = "NOPALETTEHW";
   218         break;
   219     case DDERR_NORASTEROPHW:
   220         error = "NORASTEROPHW";
   221         break;
   222     case DDERR_NOSTRETCHHW:
   223         error = "NOSTRETCHHW";
   224         break;
   225     case DDERR_NOTAOVERLAYSURFACE:
   226         error = "NOTAOVERLAYSURFACE";
   227         break;
   228     case DDERR_NOTFLIPPABLE:
   229         error = "NOTFLIPPABLE";
   230         break;
   231     case DDERR_NOTFOUND:
   232         error = "NOTFOUND";
   233         break;
   234     case DDERR_NOTLOCKED:
   235         error = "NOTLOCKED";
   236         break;
   237     case DDERR_NOTPALETTIZED:
   238         error = "NOTPALETTIZED";
   239         break;
   240     case DDERR_NOVSYNCHW:
   241         error = "NOVSYNCHW";
   242         break;
   243     case DDERR_NOZOVERLAYHW:
   244         error = "NOZOVERLAYHW";
   245         break;
   246     case DDERR_OUTOFCAPS:
   247         error = "OUTOFCAPS";
   248         break;
   249     case DDERR_OUTOFMEMORY:
   250         error = "OUTOFMEMORY";
   251         break;
   252     case DDERR_OUTOFVIDEOMEMORY:
   253         error = "OUTOFVIDEOMEMORY";
   254         break;
   255     case DDERR_OVERLAPPINGRECTS:
   256         error = "OVERLAPPINGRECTS";
   257         break;
   258     case DDERR_OVERLAYNOTVISIBLE:
   259         error = "OVERLAYNOTVISIBLE";
   260         break;
   261     case DDERR_PALETTEBUSY:
   262         error = "PALETTEBUSY";
   263         break;
   264     case DDERR_PRIMARYSURFACEALREADYEXISTS:
   265         error = "PRIMARYSURFACEALREADYEXISTS";
   266         break;
   267     case DDERR_REGIONTOOSMALL:
   268         error = "REGIONTOOSMALL";
   269         break;
   270     case DDERR_SURFACEBUSY:
   271         error = "SURFACEBUSY";
   272         break;
   273     case DDERR_SURFACELOST:
   274         error = "SURFACELOST";
   275         break;
   276     case DDERR_TOOBIGHEIGHT:
   277         error = "TOOBIGHEIGHT";
   278         break;
   279     case DDERR_TOOBIGSIZE:
   280         error = "TOOBIGSIZE";
   281         break;
   282     case DDERR_TOOBIGWIDTH:
   283         error = "TOOBIGWIDTH";
   284         break;
   285     case DDERR_UNSUPPORTED:
   286         error = "UNSUPPORTED";
   287         break;
   288     case DDERR_UNSUPPORTEDFORMAT:
   289         error = "UNSUPPORTEDFORMAT";
   290         break;
   291     case DDERR_VERTICALBLANKINPROGRESS:
   292         error = "VERTICALBLANKINPROGRESS";
   293         break;
   294     case DDERR_VIDEONOTACTIVE:
   295         error = "VIDEONOTACTIVE";
   296         break;
   297     case DDERR_WASSTILLDRAWING:
   298         error = "WASSTILLDRAWING";
   299         break;
   300     case DDERR_WRONGMODE:
   301         error = "WRONGMODE";
   302         break;
   303     default:
   304         error = "UNKNOWN";
   305         break;
   306     }
   307     SDL_SetError("%s: %s", prefix, error);
   308 }
   309 
   310 static SDL_bool
   311 PixelFormatToDDPIXELFORMAT(Uint32 format, LPDDPIXELFORMAT dst)
   312 {
   313     SDL_zerop(dst);
   314     dst->dwSize = sizeof(*dst);
   315 
   316     if (SDL_ISPIXELFORMAT_FOURCC(format)) {
   317         dst->dwFlags = DDPF_FOURCC;
   318         dst->dwFourCC = format;
   319     } else if (SDL_ISPIXELFORMAT_INDEXED(format)) {
   320         SDL_SetError("Indexed pixelformats are not supported.");
   321         return SDL_FALSE;
   322     } else {
   323         int bpp;
   324         Uint32 Rmask, Gmask, Bmask, Amask;
   325         if (!SDL_PixelFormatEnumToMasks
   326             (format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
   327             SDL_SetError("pixelformat not supported");
   328             return SDL_FALSE;
   329         }
   330 
   331         if (!Rmask && !Gmask && !Bmask) {
   332             dst->dwFlags = DDPF_ALPHA;
   333             dst->dwAlphaBitDepth = bpp;
   334         } else {
   335             dst->dwFlags = DDPF_RGB;
   336             dst->dwRGBBitCount = bpp;
   337             dst->dwRBitMask = Rmask;
   338             dst->dwGBitMask = Gmask;
   339             dst->dwBBitMask = Bmask;
   340 
   341             if (Amask) {
   342                 dst->dwFlags |= DDPF_ALPHAPIXELS;
   343                 dst->dwRGBAlphaBitMask = Amask;
   344             }
   345         }
   346     }
   347 
   348     return SDL_TRUE;
   349 }
   350 
   351 static SDL_bool
   352 DDRAW_IsTextureFormatAvailable(IDirectDraw * ddraw, Uint32 display_format,
   353                                Uint32 texture_format)
   354 {
   355     int bpp;
   356     Uint32 Rmask, Gmask, Bmask, Amask;
   357 
   358     if (SDL_ISPIXELFORMAT_FOURCC(texture_format)) {
   359         //TODO I don't expect DDRAW to support all 4CC formats, but I don't know which ones
   360         return SDL_TRUE;
   361     }
   362     //These are only basic checks
   363     if (SDL_ISPIXELFORMAT_INDEXED(texture_format)) {
   364         return SDL_FALSE;
   365     }
   366 
   367     if (!SDL_PixelFormatEnumToMasks
   368         (texture_format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
   369         return SDL_FALSE;
   370     }
   371 
   372     switch (bpp) {
   373     case 4:
   374     case 8:
   375     case 16:
   376     case 24:
   377     case 32:
   378         break;
   379     default:
   380         return SDL_FALSE;
   381     }
   382 
   383     return SDL_TRUE;
   384 }
   385 
   386 void
   387 DDRAW_AddRenderDriver(_THIS)
   388 {
   389     SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
   390     SDL_RendererInfo *info = &DDRAW_RenderDriver.info;
   391     SDL_DisplayMode *mode = &SDL_CurrentDisplay->desktop_mode;
   392 
   393     if (data->ddraw) {
   394         int i;
   395         int formats[] = {
   396             SDL_PIXELFORMAT_INDEX8,
   397             SDL_PIXELFORMAT_RGB332,
   398             SDL_PIXELFORMAT_RGB444,
   399             SDL_PIXELFORMAT_RGB555,
   400             SDL_PIXELFORMAT_ARGB4444,
   401             SDL_PIXELFORMAT_ARGB1555,
   402             SDL_PIXELFORMAT_RGB565,
   403             SDL_PIXELFORMAT_RGB888,
   404             SDL_PIXELFORMAT_ARGB8888,
   405             SDL_PIXELFORMAT_ARGB2101010,
   406         };
   407 
   408         for (i = 0; i < SDL_arraysize(formats); ++i) {
   409             if (DDRAW_IsTextureFormatAvailable
   410                 (data->ddraw, mode->format, formats[i])) {
   411                 info->texture_formats[info->num_texture_formats++] =
   412                     formats[i];
   413             }
   414         }
   415 
   416         //TODO the fourcc formats should get fetched from IDirectDraw::GetFourCCCodes
   417         info->texture_formats[info->num_texture_formats++] =
   418             SDL_PIXELFORMAT_YV12;
   419         info->texture_formats[info->num_texture_formats++] =
   420             SDL_PIXELFORMAT_IYUV;
   421         info->texture_formats[info->num_texture_formats++] =
   422             SDL_PIXELFORMAT_YUY2;
   423         info->texture_formats[info->num_texture_formats++] =
   424             SDL_PIXELFORMAT_UYVY;
   425         info->texture_formats[info->num_texture_formats++] =
   426             SDL_PIXELFORMAT_YVYU;
   427 
   428         for (i = 0; i < _this->num_displays; ++i)
   429             SDL_AddRenderDriver(&_this->displays[i], &DDRAW_RenderDriver);
   430         }
   431     }
   432 }
   433 
   434 SDL_Renderer *
   435 DDRAW_CreateRenderer(SDL_Window * window, Uint32 flags)
   436 {
   437     SDL_VideoDisplay *display = window->display;
   438     SDL_VideoData *videodata = (SDL_VideoData *) display->device->driverdata;
   439     SDL_WindowData *windowdata = (SDL_WindowData *) window->driverdata;
   440     SDL_Renderer *renderer;
   441     DDRAW_RenderData *data;
   442     HRESULT result;
   443     DDSURFACEDESC ddsd;
   444 
   445     renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
   446     if (!renderer) {
   447         SDL_OutOfMemory();
   448         return NULL;
   449     }
   450 
   451     data = (DDRAW_RenderData *) SDL_calloc(1, sizeof(*data));
   452     if (!data) {
   453         DDRAW_DestroyRenderer(renderer);
   454         SDL_OutOfMemory();
   455         return NULL;
   456     }
   457     data->ddraw = videodata->ddraw;
   458 
   459     videodata->render = RENDER_DDRAW;
   460 
   461     renderer->DisplayModeChanged = DDRAW_DisplayModeChanged;
   462     renderer->CreateTexture = DDRAW_CreateTexture;
   463     renderer->QueryTexturePixels = DDRAW_QueryTexturePixels;
   464 
   465     renderer->SetTextureColorMod = DDRAW_SetTextureColorMod;
   466     renderer->SetTextureAlphaMod = DDRAW_SetTextureAlphaMod;
   467     renderer->SetTextureBlendMode = DDRAW_SetTextureBlendMode;
   468     renderer->UpdateTexture = DDRAW_UpdateTexture;
   469     renderer->LockTexture = DDRAW_LockTexture;
   470     renderer->UnlockTexture = DDRAW_UnlockTexture;
   471     renderer->DirtyTexture = DDRAW_DirtyTexture;
   472     renderer->RenderPoint = DDRAW_RenderPoint;
   473     renderer->RenderLine = DDRAW_RenderLine;
   474     renderer->RenderFill = DDRAW_RenderFill;
   475     renderer->RenderCopy = DDRAW_RenderCopy;
   476     renderer->RenderPresent = DDRAW_RenderPresent;
   477     renderer->DestroyTexture = DDRAW_DestroyTexture;
   478     renderer->DestroyRenderer = DDRAW_DestroyRenderer;
   479     renderer->info = DDRAW_RenderDriver.info;
   480     renderer->window = window;
   481     renderer->driverdata = data;
   482 
   483     renderer->info.flags = SDL_RENDERER_ACCELERATED;
   484 
   485     SDL_zero(ddsd);
   486     ddsd.dwSize = sizeof(ddsd);
   487     ddsd.dwFlags = DDSD_CAPS;
   488 
   489     if (window->flags & SDL_WINDOW_FULLSCREEN) {
   490         ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
   491     } else {
   492         //TODO handle non fullscreen
   493         SDL_SetError("DirectDraw renderer has only fullscreen implemented");
   494         DDRAW_DestroyRenderer(renderer);
   495         return NULL;
   496     }
   497 
   498     if (flags & SDL_RENDERER_PRESENTFLIP2) {
   499         ddsd.dwFlags |= DDSD_BACKBUFFERCOUNT;
   500         ddsd.dwBackBufferCount = 2;
   501     } else if (flags & SDL_RENDERER_PRESENTFLIP3) {
   502         ddsd.dwFlags |= DDSD_BACKBUFFERCOUNT;
   503         ddsd.dwBackBufferCount = 3;
   504     } else if (flags & SDL_RENDERER_PRESENTCOPY) {
   505         //TODO what is the best approximation to this mode
   506     } else {
   507 
   508     }
   509 
   510     if (flags & SDL_RENDERER_PRESENTVSYNC) {
   511         SDL_SetError("DirectDraw renderer with v-sync is not implemented");
   512         DDRAW_DestroyRenderer(renderer);
   513         return NULL;
   514     }
   515 
   516     result =
   517         data->ddraw->lpVtbl->SetCooperativeLevel(data->ddraw,
   518                                                  windowdata->hwnd,
   519                                                  DDSCL_NORMAL);
   520     if (result != DD_OK) {
   521         DDRAW_SetError("CreateDevice()", result);
   522         DDRAW_DestroyRenderer(renderer);
   523         return NULL;
   524     }
   525 
   526     result =
   527         data->ddraw->lpVtbl->CreateSurface(data->ddraw, &ddsd, &data->primary,
   528                                            NULL);
   529     if (result != DD_OK) {
   530         DDRAW_SetError("CreateDevice()", result);
   531         DDRAW_DestroyRenderer(renderer);
   532         return NULL;
   533     }
   534 
   535     return renderer;
   536 }
   537 
   538 static int
   539 DDRAW_Reset(SDL_Renderer * renderer)
   540 {
   541     //TODO implement
   542     /*D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
   543        HRESULT result;
   544 
   545        result = IDirect3DDevice9_Reset(data->device, &data->pparams);
   546        if (FAILED(result)) {
   547        if (result == D3DERR_DEVICELOST) {
   548        /* Don't worry about it, we'll reset later... *
   549        return 0;
   550        } else {
   551        D3D_SetError("Reset()", result);
   552        return -1;
   553        }
   554        }
   555        IDirect3DDevice9_SetVertexShader(data->device, NULL);
   556        IDirect3DDevice9_SetFVF(data->device,
   557        D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
   558        IDirect3DDevice9_SetRenderState(data->device, D3DRS_CULLMODE,
   559        D3DCULL_NONE);
   560        IDirect3DDevice9_SetRenderState(data->device, D3DRS_LIGHTING, FALSE); */
   561     return 0;
   562 }
   563 
   564 static int
   565 DDRAW_DisplayModeChanged(SDL_Renderer * renderer)
   566 {
   567     //TODO implement
   568     /*D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
   569        SDL_Window *window = renderer->window;
   570        SDL_VideoDisplay *display = window->display;
   571 
   572        data->pparams.BackBufferWidth = window->w;
   573        data->pparams.BackBufferHeight = window->h;
   574        if (window->flags & SDL_WINDOW_FULLSCREEN) {
   575        data->pparams.BackBufferFormat =
   576        PixelFormatToD3DFMT(display->fullscreen_mode.format);
   577        } else {
   578        data->pparams.BackBufferFormat = D3DFMT_UNKNOWN;
   579        }
   580        return D3D_Reset(renderer); */
   581     return 0;
   582 }
   583 
   584 static int
   585 DDRAW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   586 {
   587     DDRAW_RenderData *renderdata = (DDRAW_RenderData *) renderer->driverdata;
   588     SDL_Window *window = renderer->window;
   589     SDL_VideoDisplay *display = window->display;
   590     Uint32 display_format = display->current_mode.format;
   591     DDRAW_TextureData *data;
   592     DDSURFACEDESC ddsd;
   593     HRESULT result;
   594 
   595     data = (DDRAW_TextureData *) SDL_calloc(1, sizeof(*data));
   596     if (!data) {
   597         SDL_OutOfMemory();
   598         return -1;
   599     }
   600 
   601     SDL_zero(ddsd);
   602     ddsd.dwSize = sizeof(ddsd);
   603     ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_HEIGHT | DDSD_WIDTH;
   604     ddsd.dwWidth = texture->w;
   605     ddsd.dwHeight = texture->h;
   606 
   607 
   608     if (!PixelFormatToDDPIXELFORMAT(texture->format, &ddsd.ddpfPixelFormat)) {
   609         SDL_free(data);
   610         return -1;
   611     }
   612 
   613     texture->driverdata = data;
   614 
   615     result =
   616         renderdata->ddraw->lpVtbl->CreateSurface(renderdata->ddraw, &ddsd,
   617                                                  &data->surface, NULL);
   618     if (result != DD_OK) {
   619         SDL_free(data);
   620         DDRAW_SetError("CreateTexture", result);
   621         return -1;
   622     }
   623 
   624     return 0;
   625 }
   626 
   627 static int
   628 DDRAW_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture,
   629                          void **pixels, int *pitch)
   630 {
   631     //TODO implement
   632     SDL_SetError("QueryTexturePixels is not implemented");
   633     return -1;
   634 }
   635 
   636 static int
   637 DDRAW_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
   638 {
   639     return 0;
   640 }
   641 
   642 static int
   643 DDRAW_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture)
   644 {
   645     return 0;
   646 }
   647 
   648 static int
   649 DDRAW_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
   650 {
   651     switch (texture->blendMode) {
   652     case SDL_BLENDMODE_NONE:
   653         return 0;
   654     default:
   655         SDL_Unsupported();
   656         texture->blendMode = SDL_BLENDMODE_NONE;
   657         return -1;
   658     }
   659 }
   660 
   661 static int
   662 DDRAW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   663                     const SDL_Rect * rect, const void *pixels, int pitch)
   664 {
   665     DDRAW_TextureData *data = (DDRAW_TextureData *) texture->driverdata;
   666 
   667     //TODO implement
   668     SDL_SetError("UpdateTexture is not implemented");
   669     return 0;
   670 }
   671 
   672 static int
   673 DDRAW_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   674                   const SDL_Rect * rect, int markDirty, void **pixels,
   675                   int *pitch)
   676 {
   677     DDRAW_TextureData *data = (DDRAW_TextureData *) texture->driverdata;
   678     HRESULT result;
   679     DDSURFACEDESC ddsd;
   680 
   681     SDL_zero(ddsd);
   682     ddsd.dwSize = sizeof(ddsd);
   683 
   684     /**
   685      * On a Axim x51v locking a subrect returns the startaddress of the whole surface,
   686      * wheras on my ASUS MyPal 696 the startaddress of the locked area is returned,
   687      * thats why I always lock the whole surface and calculate the pixels pointer by hand.
   688      * This shouldn't be a speed problem, as multiple locks aren't available on DDraw Mobile
   689      * see http://msdn.microsoft.com/en-us/library/ms858221.aspx
   690      */
   691 
   692     result = data->surface->lpVtbl->Lock(data->surface, NULL, &ddsd, 0, NULL);
   693     if (result != DD_OK) {
   694         DDRAW_SetError("LockRect()", result);
   695         return -1;
   696     }
   697 
   698     *pixels = ddsd.lpSurface + rect->y * ddsd.lPitch + rect->x * ddsd.lXPitch;
   699     *pitch = ddsd.lPitch;
   700     return 0;
   701 }
   702 
   703 static void
   704 DDRAW_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   705 {
   706     DDRAW_TextureData *data = (DDRAW_TextureData *) texture->driverdata;
   707 
   708     data->surface->lpVtbl->Unlock(data->surface, NULL);
   709 }
   710 
   711 static void
   712 DDRAW_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   713                    int numrects, const SDL_Rect * rects)
   714 {
   715 }
   716 
   717 static void
   718 DDRAW_SetBlendMode(DDRAW_RenderData * data, int blendMode)
   719 {
   720     switch (blendMode) {
   721 
   722     }
   723 }
   724 
   725 static int
   726 DDRAW_RenderPoint(SDL_Renderer * renderer, int x, int y)
   727 {
   728     return -1;
   729 }
   730 
   731 static int
   732 DDRAW_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2, int y2)
   733 {
   734     return -1;
   735 }
   736 
   737 static int
   738 DDRAW_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect)
   739 {
   740     return -1;
   741 }
   742 
   743 static int
   744 DDRAW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
   745                  const SDL_Rect * srcrect, const SDL_Rect * dstrect)
   746 {
   747     DDRAW_RenderData *data = (DDRAW_RenderData *) renderer->driverdata;
   748     DDRAW_TextureData *texturedata =
   749         (DDRAW_TextureData *) texture->driverdata;
   750     HRESULT result;
   751     RECT srcr;
   752     RECT dstr;
   753     DDBLTFX bltfx;
   754 
   755     srcr.left = srcrect->x;
   756     srcr.top = srcrect->y;
   757     srcr.right = srcrect->x + srcrect->w;
   758     srcr.bottom = srcrect->y + srcrect->h;
   759 
   760     dstr.left = dstrect->x;
   761     dstr.top = dstrect->y;
   762     dstr.right = dstrect->x + dstrect->w;
   763     dstr.bottom = dstrect->y + dstrect->h;
   764 
   765     SDL_zero(bltfx);
   766     bltfx.dwSize = sizeof(bltfx);
   767     bltfx.dwROP = SRCCOPY;
   768 
   769     data->primary->lpVtbl->Blt(data->primary, &dstr, texturedata->surface,
   770                                &srcr, DDBLT_ROP, &bltfx);
   771 
   772     return 0;
   773 }
   774 
   775 static void
   776 DDRAW_RenderPresent(SDL_Renderer * renderer)
   777 {
   778     DDRAW_RenderData *data = (DDRAW_RenderData *) renderer->driverdata;
   779     HRESULT result;
   780 
   781     return;
   782 
   783     result =
   784         data->primary->lpVtbl->Flip(data->primary, NULL, DDFLIP_INTERVAL1);
   785     if (result != DD_OK) {
   786         DDRAW_SetError("Present()", result);
   787     }
   788 }
   789 
   790 static void
   791 DDRAW_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   792 {
   793     DDRAW_TextureData *data = (DDRAW_TextureData *) texture->driverdata;
   794 
   795     if (!data) {
   796         return;
   797     }
   798 
   799     data->surface->lpVtbl->Release(data->surface);
   800     SDL_free(data);
   801     texture->driverdata = NULL;
   802 }
   803 
   804 static void
   805 DDRAW_DestroyRenderer(SDL_Renderer * renderer)
   806 {
   807     DDRAW_RenderData *data = (DDRAW_RenderData *) renderer->driverdata;
   808 
   809     if (data) {
   810         data->primary->lpVtbl->Release(data->primary);
   811         SDL_free(data);
   812     }
   813     SDL_free(renderer);
   814 }
   815 
   816 #endif /* SDL_VIDEO_RENDER_DDRAW */
   817 
   818 /* vi: set ts=4 sw=4 expandtab: */