src/video/win32/SDL_dibrender.c
branchSDL-1.3
changeset 1724 6c63fc2bd986
child 1728 b1ee090d194f
equal deleted inserted replaced
1723:4bdbb9b2bd0a 1724:6c63fc2bd986
       
     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 #include "SDL_win32video.h"
       
    25 #include "../SDL_yuv_sw_c.h"
       
    26 
       
    27 /* GDI renderer implementation */
       
    28 
       
    29 static SDL_Renderer *SDL_DIB_CreateRenderer(SDL_Window * window,
       
    30                                             Uint32 flags);
       
    31 static int SDL_DIB_CreateTexture(SDL_Renderer * renderer,
       
    32                                  SDL_Texture * texture);
       
    33 static int SDL_DIB_QueryTexturePixels(SDL_Renderer * renderer,
       
    34                                       SDL_Texture * texture, void **pixels,
       
    35                                       int *pitch);
       
    36 static int SDL_DIB_SetTexturePalette(SDL_Renderer * renderer,
       
    37                                      SDL_Texture * texture,
       
    38                                      const SDL_Color * colors, int firstcolor,
       
    39                                      int ncolors);
       
    40 static int SDL_DIB_GetTexturePalette(SDL_Renderer * renderer,
       
    41                                      SDL_Texture * texture,
       
    42                                      SDL_Color * colors, int firstcolor,
       
    43                                      int ncolors);
       
    44 static int SDL_DIB_UpdateTexture(SDL_Renderer * renderer,
       
    45                                  SDL_Texture * texture, const SDL_Rect * rect,
       
    46                                  const void *pixels, int pitch);
       
    47 static int SDL_DIB_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
       
    48                                const SDL_Rect * rect, int markDirty,
       
    49                                void **pixels, int *pitch);
       
    50 static void SDL_DIB_UnlockTexture(SDL_Renderer * renderer,
       
    51                                   SDL_Texture * texture);
       
    52 static void SDL_DIB_DirtyTexture(SDL_Renderer * renderer,
       
    53                                  SDL_Texture * texture, int numrects,
       
    54                                  const SDL_Rect * rects);
       
    55 static void SDL_DIB_SelectRenderTexture(SDL_Renderer * renderer,
       
    56                                         SDL_Texture * texture);
       
    57 static int SDL_DIB_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect,
       
    58                               Uint32 color);
       
    59 static int SDL_DIB_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
       
    60                               const SDL_Rect * srcrect,
       
    61                               const SDL_Rect * dstrect, int blendMode,
       
    62                               int scaleMode);
       
    63 static int SDL_DIB_RenderReadPixels(SDL_Renderer * renderer,
       
    64                                     const SDL_Rect * rect, void *pixels,
       
    65                                     int pitch);
       
    66 static int SDL_DIB_RenderWritePixels(SDL_Renderer * renderer,
       
    67                                      const SDL_Rect * rect,
       
    68                                      const void *pixels, int pitch);
       
    69 static void SDL_DIB_RenderPresent(SDL_Renderer * renderer);
       
    70 static void SDL_DIB_DestroyTexture(SDL_Renderer * renderer,
       
    71                                    SDL_Texture * texture);
       
    72 static void SDL_DIB_DestroyRenderer(SDL_Renderer * renderer);
       
    73 
       
    74 
       
    75 SDL_RenderDriver SDL_DIB_RenderDriver = {
       
    76     SDL_DIB_CreateRenderer,
       
    77     {
       
    78      "gdi",
       
    79      (SDL_Renderer_PresentDiscard |
       
    80       SDL_Renderer_PresentCopy | SDL_Renderer_RenderTarget),
       
    81      (SDL_TextureBlendMode_None |
       
    82       SDL_TextureBlendMode_Mask | SDL_TextureBlendMode_Blend),
       
    83      (SDL_TextureScaleMode_None | SDL_TextureScaleMode_Fast),
       
    84      11,
       
    85      {
       
    86       SDL_PixelFormat_Index8,
       
    87       SDL_PixelFormat_RGB555,
       
    88       SDL_PixelFormat_RGB565,
       
    89       SDL_PixelFormat_RGB888,
       
    90       SDL_PixelFormat_BGR888,
       
    91       SDL_PixelFormat_ARGB8888,
       
    92       SDL_PixelFormat_RGBA8888,
       
    93       SDL_PixelFormat_ABGR8888,
       
    94       SDL_PixelFormat_BGRA8888,
       
    95       SDL_PixelFormat_YUY2,
       
    96       SDL_PixelFormat_UYVY},
       
    97      0,
       
    98      0}
       
    99 };
       
   100 
       
   101 typedef struct
       
   102 {
       
   103     HWND hwnd;
       
   104     HDC window_hdc;
       
   105     HDC render_hdc;
       
   106     HDC memory_hdc;
       
   107     HDC current_hdc;
       
   108     LPBITMAPINFO bmi;
       
   109     HBITMAP window_bmp;
       
   110     void *window_pixels;
       
   111     int window_pitch;
       
   112 } SDL_DIB_RenderData;
       
   113 
       
   114 typedef struct
       
   115 {
       
   116     SDL_SW_YUVTexture *yuv;
       
   117     Uint32 format;
       
   118     HPALETTE hpal;
       
   119     HBITMAP hbm;
       
   120     void *pixels;
       
   121     int pitch;
       
   122 } SDL_DIB_TextureData;
       
   123 
       
   124 static void
       
   125 UpdateYUVTextureData(SDL_Texture * texture)
       
   126 {
       
   127     SDL_DIB_TextureData *data = (SDL_DIB_TextureData *) texture->driverdata;
       
   128     SDL_Rect rect;
       
   129 
       
   130     rect.x = 0;
       
   131     rect.y = 0;
       
   132     rect.w = texture->w;
       
   133     rect.h = texture->h;
       
   134     SDL_SW_CopyYUVToRGB(data->yuv, &rect, data->format, texture->w,
       
   135                         texture->h, data->pixels, data->pitch);
       
   136 }
       
   137 
       
   138 SDL_Renderer *
       
   139 SDL_DIB_CreateRenderer(SDL_Window * window, Uint32 flags)
       
   140 {
       
   141     SDL_WindowData *windowdata = (SDL_WindowData *) window->driverdata;
       
   142     SDL_Renderer *renderer;
       
   143     SDL_DIB_RenderData *data;
       
   144     int bmi_size;
       
   145     HBITMAP hbm;
       
   146 
       
   147     renderer = (SDL_Renderer *) SDL_malloc(sizeof(*renderer));
       
   148     if (!renderer) {
       
   149         SDL_OutOfMemory();
       
   150         return NULL;
       
   151     }
       
   152     SDL_zerop(renderer);
       
   153 
       
   154     data = (SDL_DIB_RenderData *) SDL_malloc(sizeof(*data));
       
   155     if (!data) {
       
   156         SDL_DIB_DestroyRenderer(renderer);
       
   157         SDL_OutOfMemory();
       
   158         return NULL;
       
   159     }
       
   160     SDL_zerop(data);
       
   161 
       
   162     data->hwnd = windowdata->hwnd;
       
   163     data->window_hdc = GetDC(data->hwnd);
       
   164     data->render_hdc = CreateCompatibleDC(data->window_hdc);
       
   165     data->memory_hdc = CreateCompatibleDC(data->window_hdc);
       
   166     data->current_hdc = data->window_hdc;
       
   167 
       
   168     /* Fill in the compatible bitmap info */
       
   169     bmi_size = sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD);
       
   170     data->bmi = (LPBITMAPINFO) SDL_malloc(bmi_size);
       
   171     if (!data->bmi) {
       
   172         SDL_DIB_DestroyRenderer(renderer);
       
   173         SDL_OutOfMemory();
       
   174         return NULL;
       
   175     }
       
   176     SDL_memset(data->bmi, 0, bmi_size);
       
   177     data->bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
       
   178 
       
   179     hbm = CreateCompatibleBitmap(data->window_hdc, 1, 1);
       
   180     GetDIBits(data->window_hdc, hbm, 0, 1, NULL, data->bmi, DIB_RGB_COLORS);
       
   181     GetDIBits(data->window_hdc, hbm, 0, 1, NULL, data->bmi, DIB_RGB_COLORS);
       
   182     DeleteObject(hbm);
       
   183 
       
   184     renderer->CreateTexture = SDL_DIB_CreateTexture;
       
   185     renderer->QueryTexturePixels = SDL_DIB_QueryTexturePixels;
       
   186     renderer->SetTexturePalette = SDL_DIB_SetTexturePalette;
       
   187     renderer->GetTexturePalette = SDL_DIB_GetTexturePalette;
       
   188     renderer->UpdateTexture = SDL_DIB_UpdateTexture;
       
   189     renderer->LockTexture = SDL_DIB_LockTexture;
       
   190     renderer->UnlockTexture = SDL_DIB_UnlockTexture;
       
   191     renderer->DirtyTexture = SDL_DIB_DirtyTexture;
       
   192     renderer->SelectRenderTexture = SDL_DIB_SelectRenderTexture;
       
   193     renderer->RenderFill = SDL_DIB_RenderFill;
       
   194     renderer->RenderCopy = SDL_DIB_RenderCopy;
       
   195     renderer->RenderReadPixels = SDL_DIB_RenderReadPixels;
       
   196     renderer->RenderWritePixels = SDL_DIB_RenderWritePixels;
       
   197     renderer->RenderPresent = SDL_DIB_RenderPresent;
       
   198     renderer->DestroyTexture = SDL_DIB_DestroyTexture;
       
   199     renderer->DestroyRenderer = SDL_DIB_DestroyRenderer;
       
   200     renderer->info = SDL_DIB_RenderDriver.info;
       
   201     renderer->window = window->id;
       
   202     renderer->driverdata = data;
       
   203 
       
   204     renderer->info.flags = SDL_Renderer_RenderTarget;
       
   205 
       
   206     return renderer;
       
   207 }
       
   208 
       
   209 static int
       
   210 SDL_DIB_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
       
   211 {
       
   212     SDL_DIB_RenderData *renderdata =
       
   213         (SDL_DIB_RenderData *) renderer->driverdata;
       
   214     SDL_Window *window = SDL_GetWindowFromID(renderer->window);
       
   215     SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
       
   216     SDL_DIB_TextureData *data;
       
   217 
       
   218     data = (SDL_DIB_TextureData *) SDL_malloc(sizeof(*data));
       
   219     if (!data) {
       
   220         SDL_OutOfMemory();
       
   221         return -1;
       
   222     }
       
   223     SDL_zerop(data);
       
   224 
       
   225     texture->driverdata = data;
       
   226 
       
   227     if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
       
   228         if (texture->access == SDL_TextureAccess_Render) {
       
   229             SDL_SetError("Rendering to YUV format textures is not supported");
       
   230             return -1;
       
   231         }
       
   232         data->yuv = SDL_SW_CreateYUVTexture(texture);
       
   233         if (!data->yuv) {
       
   234             SDL_DIB_DestroyTexture(renderer, texture);
       
   235             return -1;
       
   236         }
       
   237         data->format = display->current_mode.format;
       
   238     } else {
       
   239         data->format = texture->format;
       
   240     }
       
   241     data->pitch = (texture->w * SDL_BYTESPERPIXEL(data->format));
       
   242 
       
   243     if (data->yuv || texture->access == SDL_TextureAccess_Local
       
   244         || texture->format != SDL_GetCurrentDisplayMode()->format) {
       
   245         int bmi_size;
       
   246         LPBITMAPINFO bmi;
       
   247 
       
   248         bmi_size = sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD);
       
   249         bmi = (LPBITMAPINFO) SDL_malloc(bmi_size);
       
   250         if (!bmi) {
       
   251             SDL_DIB_DestroyTexture(renderer, texture);
       
   252             SDL_OutOfMemory();
       
   253             return -1;
       
   254         }
       
   255         SDL_memset(bmi, 0, bmi_size);
       
   256         bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
       
   257         bmi->bmiHeader.biWidth = texture->w;
       
   258         bmi->bmiHeader.biHeight = -texture->h;  /* topdown bitmap */
       
   259         bmi->bmiHeader.biPlanes = 1;
       
   260         bmi->bmiHeader.biSizeImage = texture->h * data->pitch;
       
   261         bmi->bmiHeader.biXPelsPerMeter = 0;
       
   262         bmi->bmiHeader.biYPelsPerMeter = 0;
       
   263         bmi->bmiHeader.biClrUsed = 0;
       
   264         bmi->bmiHeader.biClrImportant = 0;
       
   265         bmi->bmiHeader.biBitCount = SDL_BYTESPERPIXEL(data->format) * 8;
       
   266         if (SDL_ISPIXELFORMAT_INDEXED(data->format)) {
       
   267             int i, ncolors;
       
   268             LOGPALETTE *palette;
       
   269 
       
   270             bmi->bmiHeader.biCompression = BI_RGB;
       
   271             ncolors = (1 << SDL_BITSPERPIXEL(data->format));
       
   272             palette =
       
   273                 (LOGPALETTE *) SDL_malloc(sizeof(*palette) +
       
   274                                           ncolors * sizeof(PALETTEENTRY));
       
   275             if (!palette) {
       
   276                 SDL_free(bmi);
       
   277                 SDL_DIB_DestroyTexture(renderer, texture);
       
   278                 SDL_OutOfMemory();
       
   279                 return -1;
       
   280             }
       
   281             palette->palVersion = 0x300;
       
   282             palette->palNumEntries = ncolors;
       
   283             for (i = 0; i < ncolors; ++i) {
       
   284                 palette->palPalEntry[i].peRed = 0xFF;
       
   285                 palette->palPalEntry[i].peGreen = 0xFF;
       
   286                 palette->palPalEntry[i].peBlue = 0xFF;
       
   287                 palette->palPalEntry[i].peFlags = 0;
       
   288             }
       
   289             data->hpal = CreatePalette(palette);
       
   290             SDL_free(palette);
       
   291         } else {
       
   292             int bpp;
       
   293             Uint32 Rmask, Gmask, Bmask, Amask;
       
   294 
       
   295             bmi->bmiHeader.biCompression = BI_BITFIELDS;
       
   296             SDL_PixelFormatEnumToMasks(data->format, &bpp, &Rmask, &Gmask,
       
   297                                        &Bmask, &Amask);
       
   298             ((Uint32 *) bmi->bmiColors)[0] = Rmask;
       
   299             ((Uint32 *) bmi->bmiColors)[1] = Gmask;
       
   300             ((Uint32 *) bmi->bmiColors)[2] = Bmask;
       
   301             data->hpal = NULL;
       
   302         }
       
   303         data->hbm =
       
   304             CreateDIBSection(renderdata->memory_hdc, bmi, DIB_RGB_COLORS,
       
   305                              &data->pixels, NULL, 0);
       
   306     } else {
       
   307         data->hbm =
       
   308             CreateCompatibleBitmap(renderdata->window_hdc, texture->w,
       
   309                                    texture->h);
       
   310         data->pixels = NULL;
       
   311     }
       
   312     if (!data->hbm) {
       
   313         SDL_DIB_DestroyTexture(renderer, texture);
       
   314         WIN_SetError("Couldn't create bitmap");
       
   315         return -1;
       
   316     }
       
   317     return 0;
       
   318 }
       
   319 
       
   320 static int
       
   321 SDL_DIB_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture,
       
   322                            void **pixels, int *pitch)
       
   323 {
       
   324     SDL_DIB_TextureData *data = (SDL_DIB_TextureData *) texture->driverdata;
       
   325 
       
   326     if (data->yuv) {
       
   327         return SDL_SW_QueryYUVTexturePixels(data->yuv, pixels, pitch);
       
   328     } else {
       
   329         *pixels = data->pixels;
       
   330         *pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
       
   331         return 0;
       
   332     }
       
   333 }
       
   334 
       
   335 static int
       
   336 SDL_DIB_SetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
       
   337                           const SDL_Color * colors, int firstcolor,
       
   338                           int ncolors)
       
   339 {
       
   340     SDL_DIB_RenderData *renderdata =
       
   341         (SDL_DIB_RenderData *) renderer->driverdata;
       
   342     SDL_DIB_TextureData *data = (SDL_DIB_TextureData *) texture->driverdata;
       
   343 
       
   344     if (data->yuv) {
       
   345         SDL_SetError("YUV textures don't have a palette");
       
   346         return -1;
       
   347     } else {
       
   348         PALETTEENTRY entries[256];
       
   349         int i;
       
   350 
       
   351         for (i = 0; i < ncolors; ++i) {
       
   352             entries[i].peRed = colors[i].r;
       
   353             entries[i].peGreen = colors[i].g;
       
   354             entries[i].peBlue = colors[i].b;
       
   355             entries[i].peFlags = 0;
       
   356         }
       
   357         if (!SetPaletteEntries(data->hpal, firstcolor, ncolors, entries)) {
       
   358             WIN_SetError("SetPaletteEntries()");
       
   359             return -1;
       
   360         }
       
   361         return 0;
       
   362     }
       
   363 }
       
   364 
       
   365 static int
       
   366 SDL_DIB_GetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
       
   367                           SDL_Color * colors, int firstcolor, int ncolors)
       
   368 {
       
   369     SDL_DIB_TextureData *data = (SDL_DIB_TextureData *) texture->driverdata;
       
   370 
       
   371     if (data->yuv) {
       
   372         SDL_SetError("YUV textures don't have a palette");
       
   373         return -1;
       
   374     } else {
       
   375         PALETTEENTRY entries[256];
       
   376         int i;
       
   377 
       
   378         if (!GetPaletteEntries(data->hpal, firstcolor, ncolors, entries)) {
       
   379             WIN_SetError("GetPaletteEntries()");
       
   380             return -1;
       
   381         }
       
   382         for (i = 0; i < ncolors; ++i) {
       
   383             colors[i].r = entries[i].peRed;
       
   384             colors[i].g = entries[i].peGreen;
       
   385             colors[i].b = entries[i].peBlue;
       
   386         }
       
   387         return 0;
       
   388     }
       
   389 }
       
   390 
       
   391 static int
       
   392 SDL_DIB_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
       
   393                       const SDL_Rect * rect, const void *pixels, int pitch)
       
   394 {
       
   395     SDL_DIB_TextureData *data = (SDL_DIB_TextureData *) texture->driverdata;
       
   396 
       
   397     if (data->yuv) {
       
   398         if (SDL_SW_UpdateYUVTexture(data->yuv, rect, pixels, pitch) < 0) {
       
   399             return -1;
       
   400         }
       
   401         UpdateYUVTextureData(texture);
       
   402         return 0;
       
   403     } else {
       
   404         SDL_DIB_RenderData *renderdata =
       
   405             (SDL_DIB_RenderData *) renderer->driverdata;
       
   406 
       
   407         if (data->pixels) {
       
   408             Uint8 *src, *dst;
       
   409             int row;
       
   410             size_t length;
       
   411 
       
   412             src = (Uint8 *) pixels;
       
   413             dst =
       
   414                 (Uint8 *) data->pixels + rect->y * data->pitch +
       
   415                 rect->x * SDL_BYTESPERPIXEL(texture->format);
       
   416             length = rect->w * SDL_BYTESPERPIXEL(texture->format);
       
   417             for (row = 0; row < rect->h; ++row) {
       
   418                 SDL_memcpy(dst, src, length);
       
   419                 src += pitch;
       
   420                 dst += data->pitch;
       
   421             }
       
   422         } else if (rect->w == texture->w && pitch == data->pitch) {
       
   423             if (!SetDIBits
       
   424                 (renderdata->window_hdc, data->hbm, rect->y, rect->h, pixels,
       
   425                  renderdata->bmi, DIB_RGB_COLORS)) {
       
   426                 WIN_SetError("SetDIBits()");
       
   427                 return -1;
       
   428             }
       
   429         } else {
       
   430             SDL_SetError
       
   431                 ("FIXME: Need to allocate temporary memory and do GetDIBits() followed by SetDIBits(), since we can only set blocks of scanlines at a time");
       
   432             return -1;
       
   433         }
       
   434         return 0;
       
   435     }
       
   436 }
       
   437 
       
   438 static int
       
   439 SDL_DIB_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
       
   440                     const SDL_Rect * rect, int markDirty, void **pixels,
       
   441                     int *pitch)
       
   442 {
       
   443     SDL_DIB_TextureData *data = (SDL_DIB_TextureData *) texture->driverdata;
       
   444 
       
   445     if (data->yuv) {
       
   446         return SDL_SW_LockYUVTexture(data->yuv, rect, markDirty, pixels,
       
   447                                      pitch);
       
   448     } else {
       
   449         GdiFlush();
       
   450         *pixels =
       
   451             (void *) ((Uint8 *) data->pixels + rect->y * data->pitch +
       
   452                       rect->x * SDL_BYTESPERPIXEL(texture->format));
       
   453         *pitch = data->pitch;
       
   454         return 0;
       
   455     }
       
   456 }
       
   457 
       
   458 static void
       
   459 SDL_DIB_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
       
   460 {
       
   461     SDL_DIB_TextureData *data = (SDL_DIB_TextureData *) texture->driverdata;
       
   462 
       
   463     if (data->yuv) {
       
   464         SDL_SW_UnlockYUVTexture(data->yuv);
       
   465         UpdateYUVTextureData(texture);
       
   466     }
       
   467 }
       
   468 
       
   469 static void
       
   470 SDL_DIB_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
       
   471                      int numrects, const SDL_Rect * rects)
       
   472 {
       
   473 }
       
   474 
       
   475 static void
       
   476 SDL_DIB_SelectRenderTexture(SDL_Renderer * renderer, SDL_Texture * texture)
       
   477 {
       
   478     SDL_DIB_RenderData *data = (SDL_DIB_RenderData *) renderer->driverdata;
       
   479 
       
   480     if (texture) {
       
   481         SDL_DIB_TextureData *texturedata =
       
   482             (SDL_DIB_TextureData *) texture->driverdata;
       
   483         SelectObject(data->render_hdc, texturedata->hbm);
       
   484         if (texturedata->hpal) {
       
   485             SelectPalette(data->render_hdc, texturedata->hpal, TRUE);
       
   486             RealizePalette(data->render_hdc);
       
   487         }
       
   488         data->current_hdc = data->render_hdc;
       
   489     } else {
       
   490         data->current_hdc = data->current_hdc;
       
   491     }
       
   492 }
       
   493 
       
   494 static int
       
   495 SDL_DIB_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect,
       
   496                    Uint32 color)
       
   497 {
       
   498     SDL_DIB_RenderData *data = (SDL_DIB_RenderData *) renderer->driverdata;
       
   499     Uint8 r, g, b;
       
   500     RECT rc;
       
   501     static HBRUSH brush;
       
   502     int status;
       
   503 
       
   504     r = (Uint8) ((color >> 16) & 0xFF);
       
   505     g = (Uint8) ((color >> 8) & 0xFF);
       
   506     b = (Uint8) (color & 0xFF);
       
   507 
       
   508     rc.left = rect->x;
       
   509     rc.top = rect->y;
       
   510     rc.right = rect->x + rect->w + 1;
       
   511     rc.bottom = rect->y + rect->h + 1;
       
   512 
       
   513     /* Should we cache the brushes? .. it looks like GDI does for us. :) */
       
   514     brush = CreateSolidBrush(RGB(r, g, b));
       
   515     SelectObject(data->current_hdc, brush);
       
   516     status = FillRect(data->current_hdc, &rc, brush);
       
   517     DeleteObject(brush);
       
   518 
       
   519     if (!status) {
       
   520         WIN_SetError("FillRect()");
       
   521         return -1;
       
   522     }
       
   523     return 0;
       
   524 }
       
   525 
       
   526 static int
       
   527 SDL_DIB_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
       
   528                    const SDL_Rect * srcrect, const SDL_Rect * dstrect,
       
   529                    int blendMode, int scaleMode)
       
   530 {
       
   531     SDL_DIB_RenderData *data = (SDL_DIB_RenderData *) renderer->driverdata;
       
   532     SDL_DIB_TextureData *texturedata =
       
   533         (SDL_DIB_TextureData *) texture->driverdata;
       
   534 
       
   535     SelectObject(data->memory_hdc, texturedata->hbm);
       
   536     if (texturedata->hpal) {
       
   537         SelectPalette(data->memory_hdc, texturedata->hpal, TRUE);
       
   538         RealizePalette(data->memory_hdc);
       
   539     }
       
   540     if (blendMode & (SDL_TextureBlendMode_Mask | SDL_TextureBlendMode_Blend)) {
       
   541         static BLENDFUNCTION blendFunc = {
       
   542             AC_SRC_OVER,
       
   543             0,
       
   544             255,
       
   545             AC_SRC_ALPHA
       
   546         };
       
   547         /* FIXME: GDI uses premultiplied alpha! */
       
   548         if (!AlphaBlend
       
   549             (data->current_hdc, dstrect->x, dstrect->y, dstrect->w,
       
   550              dstrect->h, data->memory_hdc, srcrect->x, srcrect->y, srcrect->w,
       
   551              srcrect->h, blendFunc)) {
       
   552             WIN_SetError("AlphaBlend()");
       
   553             return -1;
       
   554         }
       
   555     } else {
       
   556         if (srcrect->w == dstrect->w && srcrect->h == dstrect->h) {
       
   557             if (!BitBlt
       
   558                 (data->current_hdc, dstrect->x, dstrect->y, dstrect->w,
       
   559                  srcrect->h, data->memory_hdc, srcrect->x, srcrect->y,
       
   560                  SRCCOPY)) {
       
   561                 WIN_SetError("BitBlt()");
       
   562                 return -1;
       
   563             }
       
   564         } else {
       
   565             if (!StretchBlt
       
   566                 (data->current_hdc, dstrect->x, dstrect->y, dstrect->w,
       
   567                  srcrect->h, data->memory_hdc, srcrect->x, srcrect->y,
       
   568                  srcrect->w, srcrect->h, SRCCOPY)) {
       
   569                 WIN_SetError("StretchBlt()");
       
   570                 return -1;
       
   571             }
       
   572         }
       
   573     }
       
   574     return 0;
       
   575 }
       
   576 
       
   577 static int
       
   578 CreateWindowDIB(SDL_DIB_RenderData * data, SDL_Window * window)
       
   579 {
       
   580     data->window_pitch = window->w * (data->bmi->bmiHeader.biBitCount / 8);
       
   581     data->bmi->bmiHeader.biWidth = window->w;
       
   582     data->bmi->bmiHeader.biHeight = -window->h;
       
   583     data->bmi->bmiHeader.biSizeImage =
       
   584         window->h * (data->bmi->bmiHeader.biBitCount / 8);
       
   585     data->window_bmp =
       
   586         CreateDIBSection(data->window_hdc, data->bmi, DIB_RGB_COLORS,
       
   587                          &data->window_pixels, NULL, 0);
       
   588     if (!data->window_bmp) {
       
   589         WIN_SetError("CreateDIBSection()");
       
   590         return -1;
       
   591     }
       
   592     return 0;
       
   593 }
       
   594 
       
   595 static int
       
   596 SDL_DIB_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
       
   597                          void *pixels, int pitch)
       
   598 {
       
   599     SDL_Window *window = SDL_GetWindowFromID(renderer->window);
       
   600     SDL_DIB_RenderData *data = (SDL_DIB_RenderData *) renderer->driverdata;
       
   601 
       
   602     if (!data->window_bmp) {
       
   603         if (CreateWindowDIB(data, window) < 0) {
       
   604             return -1;
       
   605         }
       
   606     }
       
   607 
       
   608     SelectObject(data->memory_hdc, data->window_bmp);
       
   609     BitBlt(data->memory_hdc, rect->x, rect->y, rect->w, rect->h,
       
   610            data->window_hdc, rect->x, rect->y, SRCCOPY);
       
   611 
       
   612     {
       
   613         int bpp = data->bmi->bmiHeader.biBitCount / 8;
       
   614         Uint8 *src =
       
   615             (Uint8 *) data->window_pixels + rect->y * data->window_pitch +
       
   616             rect->x * bpp;
       
   617         Uint8 *dst = (Uint8 *) pixels;
       
   618         int row;
       
   619 
       
   620         for (row = 0; row < rect->h; ++row) {
       
   621             SDL_memcpy(dst, src, rect->w * bpp);
       
   622             src += data->window_pitch;
       
   623             dst += pitch;
       
   624         }
       
   625     }
       
   626 
       
   627     return 0;
       
   628 }
       
   629 
       
   630 static int
       
   631 SDL_DIB_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect,
       
   632                           const void *pixels, int pitch)
       
   633 {
       
   634     SDL_Window *window = SDL_GetWindowFromID(renderer->window);
       
   635     SDL_DIB_RenderData *data = (SDL_DIB_RenderData *) renderer->driverdata;
       
   636 
       
   637     if (!data->window_bmp) {
       
   638         if (CreateWindowDIB(data, window) < 0) {
       
   639             return -1;
       
   640         }
       
   641     }
       
   642 
       
   643     {
       
   644         int bpp = data->bmi->bmiHeader.biBitCount / 8;
       
   645         Uint8 *src = (Uint8 *) pixels;
       
   646         Uint8 *dst =
       
   647             (Uint8 *) data->window_pixels + rect->y * data->window_pitch +
       
   648             rect->x * bpp;
       
   649         int row;
       
   650 
       
   651         for (row = 0; row < rect->h; ++row) {
       
   652             SDL_memcpy(dst, src, rect->w * bpp);
       
   653             src += pitch;
       
   654             dst += data->window_pitch;
       
   655         }
       
   656     }
       
   657 
       
   658     SelectObject(data->memory_hdc, data->window_bmp);
       
   659     BitBlt(data->window_hdc, rect->x, rect->y, rect->w, rect->h,
       
   660            data->memory_hdc, rect->x, rect->y, SRCCOPY);
       
   661 
       
   662     return 0;
       
   663 }
       
   664 
       
   665 static void
       
   666 SDL_DIB_RenderPresent(SDL_Renderer * renderer)
       
   667 {
       
   668 }
       
   669 
       
   670 static void
       
   671 SDL_DIB_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
       
   672 {
       
   673     SDL_DIB_TextureData *data = (SDL_DIB_TextureData *) texture->driverdata;
       
   674 
       
   675     if (!data) {
       
   676         return;
       
   677     }
       
   678     if (data->yuv) {
       
   679         SDL_SW_DestroyYUVTexture(data->yuv);
       
   680     }
       
   681     if (data->hpal) {
       
   682         DeleteObject(data->hpal);
       
   683     }
       
   684     if (data->hbm) {
       
   685         DeleteObject(data->hbm);
       
   686     }
       
   687     SDL_free(data);
       
   688     texture->driverdata = NULL;
       
   689 }
       
   690 
       
   691 void
       
   692 SDL_DIB_DestroyRenderer(SDL_Renderer * renderer)
       
   693 {
       
   694     SDL_DIB_RenderData *data = (SDL_DIB_RenderData *) renderer->driverdata;
       
   695 
       
   696     if (data) {
       
   697         ReleaseDC(data->hwnd, data->window_hdc);
       
   698         DeleteDC(data->render_hdc);
       
   699         DeleteDC(data->memory_hdc);
       
   700         if (data->bmi) {
       
   701             SDL_free(data->bmi);
       
   702         }
       
   703         if (data->window_bmp) {
       
   704             DeleteObject(data->window_bmp);
       
   705         }
       
   706         SDL_free(data);
       
   707     }
       
   708     SDL_free(renderer);
       
   709 }
       
   710 
       
   711 /* vi: set ts=4 sw=4 expandtab: */