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