Implemented RenderReadPixels() and RenderWritePixels() for GDI renderer.
authorSam Lantinga <slouken@libsdl.org>
Mon, 07 Dec 2009 09:44:55 +0000
changeset 35349d129e1d0782
parent 3533 40b9b0177e9a
child 3535 b403f790df65
Implemented RenderReadPixels() and RenderWritePixels() for GDI renderer.
src/video/win32/SDL_gdirender.c
     1.1 --- a/src/video/win32/SDL_gdirender.c	Mon Dec 07 08:02:20 2009 +0000
     1.2 +++ b/src/video/win32/SDL_gdirender.c	Mon Dec 07 09:44:55 2009 +0000
     1.3 @@ -67,6 +67,10 @@
     1.4  static int GDI_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect);
     1.5  static int GDI_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
     1.6                            const SDL_Rect * srcrect, const SDL_Rect * dstrect);
     1.7 +static int GDI_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
     1.8 +                                Uint32 format, void * pixels, int pitch);
     1.9 +static int GDI_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect,
    1.10 +                                 Uint32 format, const void * pixels, int pitch);
    1.11  static void GDI_RenderPresent(SDL_Renderer * renderer);
    1.12  static void GDI_DestroyTexture(SDL_Renderer * renderer,
    1.13                                 SDL_Texture * texture);
    1.14 @@ -192,6 +196,8 @@
    1.15      renderer->RenderLine = GDI_RenderLine;
    1.16      renderer->RenderFill = GDI_RenderFill;
    1.17      renderer->RenderCopy = GDI_RenderCopy;
    1.18 +    renderer->RenderReadPixels = GDI_RenderReadPixels;
    1.19 +    renderer->RenderWritePixels = GDI_RenderWritePixels;
    1.20      renderer->RenderPresent = GDI_RenderPresent;
    1.21      renderer->DestroyTexture = GDI_DestroyTexture;
    1.22      renderer->DestroyRenderer = GDI_DestroyRenderer;
    1.23 @@ -297,6 +303,72 @@
    1.24      return 0;
    1.25  }
    1.26  
    1.27 +static HBITMAP
    1.28 +GDI_CreateDIBSection(HDC hdc, int w, int h, int pitch, Uint32 format,
    1.29 +                     HPALETTE * hpal, void ** pixels)
    1.30 +{
    1.31 +    int bmi_size;
    1.32 +    LPBITMAPINFO bmi;
    1.33 +
    1.34 +    bmi_size = sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD);
    1.35 +    bmi = (LPBITMAPINFO) SDL_calloc(1, bmi_size);
    1.36 +    if (!bmi) {
    1.37 +        SDL_OutOfMemory();
    1.38 +        return NULL;
    1.39 +    }
    1.40 +    bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    1.41 +    bmi->bmiHeader.biWidth = w;
    1.42 +    bmi->bmiHeader.biHeight = -h;  /* topdown bitmap */
    1.43 +    bmi->bmiHeader.biPlanes = 1;
    1.44 +    bmi->bmiHeader.biSizeImage = h * pitch;
    1.45 +    bmi->bmiHeader.biXPelsPerMeter = 0;
    1.46 +    bmi->bmiHeader.biYPelsPerMeter = 0;
    1.47 +    bmi->bmiHeader.biClrUsed = 0;
    1.48 +    bmi->bmiHeader.biClrImportant = 0;
    1.49 +    bmi->bmiHeader.biBitCount = SDL_BYTESPERPIXEL(format) * 8;
    1.50 +    if (SDL_ISPIXELFORMAT_INDEXED(format)) {
    1.51 +        bmi->bmiHeader.biCompression = BI_RGB;
    1.52 +        if (hpal) {
    1.53 +            int i, ncolors;
    1.54 +            LOGPALETTE *palette;
    1.55 +
    1.56 +            ncolors = (1 << SDL_BITSPERPIXEL(format));
    1.57 +            palette =
    1.58 +                (LOGPALETTE *) SDL_malloc(sizeof(*palette) +
    1.59 +                                          ncolors * sizeof(PALETTEENTRY));
    1.60 +            if (!palette) {
    1.61 +                SDL_free(bmi);
    1.62 +                SDL_OutOfMemory();
    1.63 +                return NULL;
    1.64 +            }
    1.65 +            palette->palVersion = 0x300;
    1.66 +            palette->palNumEntries = ncolors;
    1.67 +            for (i = 0; i < ncolors; ++i) {
    1.68 +                palette->palPalEntry[i].peRed = 0xFF;
    1.69 +                palette->palPalEntry[i].peGreen = 0xFF;
    1.70 +                palette->palPalEntry[i].peBlue = 0xFF;
    1.71 +                palette->palPalEntry[i].peFlags = 0;
    1.72 +            }
    1.73 +            *hpal = CreatePalette(palette);
    1.74 +            SDL_free(palette);
    1.75 +        }
    1.76 +    } else {
    1.77 +        int bpp;
    1.78 +        Uint32 Rmask, Gmask, Bmask, Amask;
    1.79 +
    1.80 +        bmi->bmiHeader.biCompression = BI_BITFIELDS;
    1.81 +        SDL_PixelFormatEnumToMasks(format, &bpp, &Rmask, &Gmask, &Bmask,
    1.82 +                                   &Amask);
    1.83 +        ((Uint32 *) bmi->bmiColors)[0] = Rmask;
    1.84 +        ((Uint32 *) bmi->bmiColors)[1] = Gmask;
    1.85 +        ((Uint32 *) bmi->bmiColors)[2] = Bmask;
    1.86 +        if (hpal) {
    1.87 +            *hpal = NULL;
    1.88 +        }
    1.89 +    }
    1.90 +    return CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, pixels, NULL, 0);
    1.91 +}
    1.92 +
    1.93  static int
    1.94  GDI_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
    1.95  {
    1.96 @@ -327,69 +399,13 @@
    1.97  
    1.98      if (data->yuv || texture->access == SDL_TEXTUREACCESS_STREAMING
    1.99          || texture->format != display->current_mode.format) {
   1.100 -        int bmi_size;
   1.101 -        LPBITMAPINFO bmi;
   1.102 -
   1.103 -        bmi_size = sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD);
   1.104 -        bmi = (LPBITMAPINFO) SDL_calloc(1, bmi_size);
   1.105 -        if (!bmi) {
   1.106 -            SDL_OutOfMemory();
   1.107 -            return -1;
   1.108 -        }
   1.109 -        bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
   1.110 -        bmi->bmiHeader.biWidth = texture->w;
   1.111 -        bmi->bmiHeader.biHeight = -texture->h;  /* topdown bitmap */
   1.112 -        bmi->bmiHeader.biPlanes = 1;
   1.113 -        bmi->bmiHeader.biSizeImage = texture->h * data->pitch;
   1.114 -        bmi->bmiHeader.biXPelsPerMeter = 0;
   1.115 -        bmi->bmiHeader.biYPelsPerMeter = 0;
   1.116 -        bmi->bmiHeader.biClrUsed = 0;
   1.117 -        bmi->bmiHeader.biClrImportant = 0;
   1.118 -        bmi->bmiHeader.biBitCount = SDL_BYTESPERPIXEL(data->format) * 8;
   1.119 -        if (SDL_ISPIXELFORMAT_INDEXED(data->format)) {
   1.120 -            int i, ncolors;
   1.121 -            LOGPALETTE *palette;
   1.122 -
   1.123 -            bmi->bmiHeader.biCompression = BI_RGB;
   1.124 -            ncolors = (1 << SDL_BITSPERPIXEL(data->format));
   1.125 -            palette =
   1.126 -                (LOGPALETTE *) SDL_malloc(sizeof(*palette) +
   1.127 -                                          ncolors * sizeof(PALETTEENTRY));
   1.128 -            if (!palette) {
   1.129 -                SDL_free(bmi);
   1.130 -                SDL_OutOfMemory();
   1.131 -                return -1;
   1.132 -            }
   1.133 -            palette->palVersion = 0x300;
   1.134 -            palette->palNumEntries = ncolors;
   1.135 -            for (i = 0; i < ncolors; ++i) {
   1.136 -                palette->palPalEntry[i].peRed = 0xFF;
   1.137 -                palette->palPalEntry[i].peGreen = 0xFF;
   1.138 -                palette->palPalEntry[i].peBlue = 0xFF;
   1.139 -                palette->palPalEntry[i].peFlags = 0;
   1.140 -            }
   1.141 -            data->hpal = CreatePalette(palette);
   1.142 -            SDL_free(palette);
   1.143 -        } else {
   1.144 -            int bpp;
   1.145 -            Uint32 Rmask, Gmask, Bmask, Amask;
   1.146 -
   1.147 -            bmi->bmiHeader.biCompression = BI_BITFIELDS;
   1.148 -            SDL_PixelFormatEnumToMasks(data->format, &bpp, &Rmask, &Gmask,
   1.149 -                                       &Bmask, &Amask);
   1.150 -            ((Uint32 *) bmi->bmiColors)[0] = Rmask;
   1.151 -            ((Uint32 *) bmi->bmiColors)[1] = Gmask;
   1.152 -            ((Uint32 *) bmi->bmiColors)[2] = Bmask;
   1.153 -            data->hpal = NULL;
   1.154 -        }
   1.155 -        data->hbm =
   1.156 -            CreateDIBSection(renderdata->memory_hdc, bmi, DIB_RGB_COLORS,
   1.157 -                             &data->pixels, NULL, 0);
   1.158 +        data->hbm = GDI_CreateDIBSection(renderdata->memory_hdc,
   1.159 +                                         texture->w, texture->h,
   1.160 +                                         data->pitch, data->format,
   1.161 +                                         &data->hpal, &data->pixels);
   1.162      } else {
   1.163 -        data->hbm =
   1.164 -            CreateCompatibleBitmap(renderdata->window_hdc, texture->w,
   1.165 -                                   texture->h);
   1.166 -        data->pixels = NULL;
   1.167 +        data->hbm = CreateCompatibleBitmap(renderdata->window_hdc,
   1.168 +                                           texture->w, texture->h);
   1.169      }
   1.170      if (!data->hbm) {
   1.171          WIN_SetError("Couldn't create bitmap");
   1.172 @@ -821,6 +837,87 @@
   1.173      return 0;
   1.174  }
   1.175  
   1.176 +static int
   1.177 +GDI_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
   1.178 +                     Uint32 format, void * pixels, int pitch)
   1.179 +{
   1.180 +    GDI_RenderData *renderdata = (GDI_RenderData *) renderer->driverdata;
   1.181 +    SDL_Window *window = SDL_GetWindowFromID(renderer->window);
   1.182 +    SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
   1.183 +    struct {
   1.184 +        HBITMAP hbm;
   1.185 +        void *pixels;
   1.186 +        int pitch;
   1.187 +        Uint32 format;
   1.188 +    } data;
   1.189 +
   1.190 +    data.format = display->current_mode.format;
   1.191 +    data.pitch = (rect->w * SDL_BYTESPERPIXEL(data.format));
   1.192 +
   1.193 +    data.hbm = GDI_CreateDIBSection(renderdata->memory_hdc, rect->w, rect->h,
   1.194 +                                    data.pitch, data.format, NULL,
   1.195 +                                    &data.pixels);
   1.196 +    if (!data.hbm) {
   1.197 +        WIN_SetError("Couldn't create bitmap");
   1.198 +        return -1;
   1.199 +    }
   1.200 +
   1.201 +    SelectObject(renderdata->memory_hdc, data.hbm);
   1.202 +    if (!BitBlt(renderdata->memory_hdc, 0, 0, rect->w, rect->h,
   1.203 +                renderdata->current_hdc, rect->x, rect->y, SRCCOPY)) {
   1.204 +        WIN_SetError("BitBlt()");
   1.205 +        DeleteObject(data.hbm);
   1.206 +        return -1;
   1.207 +    }
   1.208 +
   1.209 +    SDL_ConvertPixels(rect->w, rect->h,
   1.210 +                      data.format, data.pixels, data.pitch,
   1.211 +                      format, pixels, pitch);
   1.212 +
   1.213 +    DeleteObject(data.hbm);
   1.214 +    return 0;
   1.215 +}
   1.216 +
   1.217 +static int
   1.218 +GDI_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect,
   1.219 +                      Uint32 format, const void * pixels, int pitch)
   1.220 +{
   1.221 +    GDI_RenderData *renderdata = (GDI_RenderData *) renderer->driverdata;
   1.222 +    SDL_Window *window = SDL_GetWindowFromID(renderer->window);
   1.223 +    SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
   1.224 +    struct {
   1.225 +        HBITMAP hbm;
   1.226 +        void *pixels;
   1.227 +        int pitch;
   1.228 +        Uint32 format;
   1.229 +    } data;
   1.230 +
   1.231 +    data.format = display->current_mode.format;
   1.232 +    data.pitch = (rect->w * SDL_BYTESPERPIXEL(data.format));
   1.233 +
   1.234 +    data.hbm = GDI_CreateDIBSection(renderdata->memory_hdc, rect->w, rect->h,
   1.235 +                                    data.pitch, data.format,
   1.236 +                                    NULL, &data.pixels);
   1.237 +    if (!data.hbm) {
   1.238 +        WIN_SetError("Couldn't create bitmap");
   1.239 +        return -1;
   1.240 +    }
   1.241 +
   1.242 +    SDL_ConvertPixels(rect->w, rect->h, format, pixels, pitch,
   1.243 +                      data.format, data.pixels, data.pitch);
   1.244 +
   1.245 +    SelectObject(renderdata->memory_hdc, data.hbm);
   1.246 +    if (!BitBlt(renderdata->current_hdc, rect->x, rect->y, rect->w, rect->h,
   1.247 +                renderdata->memory_hdc, 0, 0, SRCCOPY)) {
   1.248 +        WIN_SetError("BitBlt()");
   1.249 +        DeleteObject(data.hbm);
   1.250 +        return -1;
   1.251 +    }
   1.252 +
   1.253 +    DeleteObject(data.hbm);
   1.254 +    return 0;
   1.255 +}
   1.256 +
   1.257  static void
   1.258  GDI_RenderPresent(SDL_Renderer * renderer)
   1.259  {