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