comparison src/video/win32/SDL_gdirender.c @ 3534:9d129e1d0782

Implemented RenderReadPixels() and RenderWritePixels() for GDI renderer.
author Sam Lantinga <slouken@libsdl.org>
date Mon, 07 Dec 2009 09:44:55 +0000
parents 83518f8fcd61
children b403f790df65
comparison
equal deleted inserted replaced
3533:40b9b0177e9a 3534:9d129e1d0782
65 static int GDI_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2, 65 static int GDI_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2,
66 int y2); 66 int y2);
67 static int GDI_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect); 67 static int GDI_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect);
68 static int GDI_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, 68 static int GDI_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
69 const SDL_Rect * srcrect, const SDL_Rect * dstrect); 69 const SDL_Rect * srcrect, const SDL_Rect * dstrect);
70 static int GDI_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
71 Uint32 format, void * pixels, int pitch);
72 static int GDI_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect,
73 Uint32 format, const void * pixels, int pitch);
70 static void GDI_RenderPresent(SDL_Renderer * renderer); 74 static void GDI_RenderPresent(SDL_Renderer * renderer);
71 static void GDI_DestroyTexture(SDL_Renderer * renderer, 75 static void GDI_DestroyTexture(SDL_Renderer * renderer,
72 SDL_Texture * texture); 76 SDL_Texture * texture);
73 static void GDI_DestroyRenderer(SDL_Renderer * renderer); 77 static void GDI_DestroyRenderer(SDL_Renderer * renderer);
74 78
190 renderer->SetDrawBlendMode = GDI_SetDrawBlendMode; 194 renderer->SetDrawBlendMode = GDI_SetDrawBlendMode;
191 renderer->RenderPoint = GDI_RenderPoint; 195 renderer->RenderPoint = GDI_RenderPoint;
192 renderer->RenderLine = GDI_RenderLine; 196 renderer->RenderLine = GDI_RenderLine;
193 renderer->RenderFill = GDI_RenderFill; 197 renderer->RenderFill = GDI_RenderFill;
194 renderer->RenderCopy = GDI_RenderCopy; 198 renderer->RenderCopy = GDI_RenderCopy;
199 renderer->RenderReadPixels = GDI_RenderReadPixels;
200 renderer->RenderWritePixels = GDI_RenderWritePixels;
195 renderer->RenderPresent = GDI_RenderPresent; 201 renderer->RenderPresent = GDI_RenderPresent;
196 renderer->DestroyTexture = GDI_DestroyTexture; 202 renderer->DestroyTexture = GDI_DestroyTexture;
197 renderer->DestroyRenderer = GDI_DestroyRenderer; 203 renderer->DestroyRenderer = GDI_DestroyRenderer;
198 renderer->info = GDI_RenderDriver.info; 204 renderer->info = GDI_RenderDriver.info;
199 renderer->window = window->id; 205 renderer->window = window->id;
295 data->current_hbm = 0; 301 data->current_hbm = 0;
296 302
297 return 0; 303 return 0;
298 } 304 }
299 305
300 static int 306 static HBITMAP
301 GDI_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) 307 GDI_CreateDIBSection(HDC hdc, int w, int h, int pitch, Uint32 format,
302 { 308 HPALETTE * hpal, void ** pixels)
303 GDI_RenderData *renderdata = (GDI_RenderData *) renderer->driverdata; 309 {
304 SDL_Window *window = SDL_GetWindowFromID(renderer->window); 310 int bmi_size;
305 SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window); 311 LPBITMAPINFO bmi;
306 GDI_TextureData *data; 312
307 313 bmi_size = sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD);
308 data = (GDI_TextureData *) SDL_calloc(1, sizeof(*data)); 314 bmi = (LPBITMAPINFO) SDL_calloc(1, bmi_size);
309 if (!data) { 315 if (!bmi) {
310 SDL_OutOfMemory(); 316 SDL_OutOfMemory();
311 return -1; 317 return NULL;
312 } 318 }
313 319 bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
314 texture->driverdata = data; 320 bmi->bmiHeader.biWidth = w;
315 321 bmi->bmiHeader.biHeight = -h; /* topdown bitmap */
316 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { 322 bmi->bmiHeader.biPlanes = 1;
317 data->yuv = 323 bmi->bmiHeader.biSizeImage = h * pitch;
318 SDL_SW_CreateYUVTexture(texture->format, texture->w, texture->h); 324 bmi->bmiHeader.biXPelsPerMeter = 0;
319 if (!data->yuv) { 325 bmi->bmiHeader.biYPelsPerMeter = 0;
320 return -1; 326 bmi->bmiHeader.biClrUsed = 0;
321 } 327 bmi->bmiHeader.biClrImportant = 0;
322 data->format = display->current_mode.format; 328 bmi->bmiHeader.biBitCount = SDL_BYTESPERPIXEL(format) * 8;
323 } else { 329 if (SDL_ISPIXELFORMAT_INDEXED(format)) {
324 data->format = texture->format; 330 bmi->bmiHeader.biCompression = BI_RGB;
325 } 331 if (hpal) {
326 data->pitch = (texture->w * SDL_BYTESPERPIXEL(data->format));
327
328 if (data->yuv || texture->access == SDL_TEXTUREACCESS_STREAMING
329 || texture->format != display->current_mode.format) {
330 int bmi_size;
331 LPBITMAPINFO bmi;
332
333 bmi_size = sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD);
334 bmi = (LPBITMAPINFO) SDL_calloc(1, bmi_size);
335 if (!bmi) {
336 SDL_OutOfMemory();
337 return -1;
338 }
339 bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
340 bmi->bmiHeader.biWidth = texture->w;
341 bmi->bmiHeader.biHeight = -texture->h; /* topdown bitmap */
342 bmi->bmiHeader.biPlanes = 1;
343 bmi->bmiHeader.biSizeImage = texture->h * data->pitch;
344 bmi->bmiHeader.biXPelsPerMeter = 0;
345 bmi->bmiHeader.biYPelsPerMeter = 0;
346 bmi->bmiHeader.biClrUsed = 0;
347 bmi->bmiHeader.biClrImportant = 0;
348 bmi->bmiHeader.biBitCount = SDL_BYTESPERPIXEL(data->format) * 8;
349 if (SDL_ISPIXELFORMAT_INDEXED(data->format)) {
350 int i, ncolors; 332 int i, ncolors;
351 LOGPALETTE *palette; 333 LOGPALETTE *palette;
352 334
353 bmi->bmiHeader.biCompression = BI_RGB; 335 ncolors = (1 << SDL_BITSPERPIXEL(format));
354 ncolors = (1 << SDL_BITSPERPIXEL(data->format));
355 palette = 336 palette =
356 (LOGPALETTE *) SDL_malloc(sizeof(*palette) + 337 (LOGPALETTE *) SDL_malloc(sizeof(*palette) +
357 ncolors * sizeof(PALETTEENTRY)); 338 ncolors * sizeof(PALETTEENTRY));
358 if (!palette) { 339 if (!palette) {
359 SDL_free(bmi); 340 SDL_free(bmi);
360 SDL_OutOfMemory(); 341 SDL_OutOfMemory();
361 return -1; 342 return NULL;
362 } 343 }
363 palette->palVersion = 0x300; 344 palette->palVersion = 0x300;
364 palette->palNumEntries = ncolors; 345 palette->palNumEntries = ncolors;
365 for (i = 0; i < ncolors; ++i) { 346 for (i = 0; i < ncolors; ++i) {
366 palette->palPalEntry[i].peRed = 0xFF; 347 palette->palPalEntry[i].peRed = 0xFF;
367 palette->palPalEntry[i].peGreen = 0xFF; 348 palette->palPalEntry[i].peGreen = 0xFF;
368 palette->palPalEntry[i].peBlue = 0xFF; 349 palette->palPalEntry[i].peBlue = 0xFF;
369 palette->palPalEntry[i].peFlags = 0; 350 palette->palPalEntry[i].peFlags = 0;
370 } 351 }
371 data->hpal = CreatePalette(palette); 352 *hpal = CreatePalette(palette);
372 SDL_free(palette); 353 SDL_free(palette);
373 } else { 354 }
374 int bpp; 355 } else {
375 Uint32 Rmask, Gmask, Bmask, Amask; 356 int bpp;
376 357 Uint32 Rmask, Gmask, Bmask, Amask;
377 bmi->bmiHeader.biCompression = BI_BITFIELDS; 358
378 SDL_PixelFormatEnumToMasks(data->format, &bpp, &Rmask, &Gmask, 359 bmi->bmiHeader.biCompression = BI_BITFIELDS;
379 &Bmask, &Amask); 360 SDL_PixelFormatEnumToMasks(format, &bpp, &Rmask, &Gmask, &Bmask,
380 ((Uint32 *) bmi->bmiColors)[0] = Rmask; 361 &Amask);
381 ((Uint32 *) bmi->bmiColors)[1] = Gmask; 362 ((Uint32 *) bmi->bmiColors)[0] = Rmask;
382 ((Uint32 *) bmi->bmiColors)[2] = Bmask; 363 ((Uint32 *) bmi->bmiColors)[1] = Gmask;
383 data->hpal = NULL; 364 ((Uint32 *) bmi->bmiColors)[2] = Bmask;
384 } 365 if (hpal) {
385 data->hbm = 366 *hpal = NULL;
386 CreateDIBSection(renderdata->memory_hdc, bmi, DIB_RGB_COLORS, 367 }
387 &data->pixels, NULL, 0); 368 }
388 } else { 369 return CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, pixels, NULL, 0);
389 data->hbm = 370 }
390 CreateCompatibleBitmap(renderdata->window_hdc, texture->w, 371
391 texture->h); 372 static int
392 data->pixels = NULL; 373 GDI_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
374 {
375 GDI_RenderData *renderdata = (GDI_RenderData *) renderer->driverdata;
376 SDL_Window *window = SDL_GetWindowFromID(renderer->window);
377 SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
378 GDI_TextureData *data;
379
380 data = (GDI_TextureData *) SDL_calloc(1, sizeof(*data));
381 if (!data) {
382 SDL_OutOfMemory();
383 return -1;
384 }
385
386 texture->driverdata = data;
387
388 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
389 data->yuv =
390 SDL_SW_CreateYUVTexture(texture->format, texture->w, texture->h);
391 if (!data->yuv) {
392 return -1;
393 }
394 data->format = display->current_mode.format;
395 } else {
396 data->format = texture->format;
397 }
398 data->pitch = (texture->w * SDL_BYTESPERPIXEL(data->format));
399
400 if (data->yuv || texture->access == SDL_TEXTUREACCESS_STREAMING
401 || texture->format != display->current_mode.format) {
402 data->hbm = GDI_CreateDIBSection(renderdata->memory_hdc,
403 texture->w, texture->h,
404 data->pitch, data->format,
405 &data->hpal, &data->pixels);
406 } else {
407 data->hbm = CreateCompatibleBitmap(renderdata->window_hdc,
408 texture->w, texture->h);
393 } 409 }
394 if (!data->hbm) { 410 if (!data->hbm) {
395 WIN_SetError("Couldn't create bitmap"); 411 WIN_SetError("Couldn't create bitmap");
396 return -1; 412 return -1;
397 } 413 }
819 } 835 }
820 } 836 }
821 return 0; 837 return 0;
822 } 838 }
823 839
840 static int
841 GDI_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
842 Uint32 format, void * pixels, int pitch)
843 {
844 GDI_RenderData *renderdata = (GDI_RenderData *) renderer->driverdata;
845 SDL_Window *window = SDL_GetWindowFromID(renderer->window);
846 SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
847 struct {
848 HBITMAP hbm;
849 void *pixels;
850 int pitch;
851 Uint32 format;
852 } data;
853
854 data.format = display->current_mode.format;
855 data.pitch = (rect->w * SDL_BYTESPERPIXEL(data.format));
856
857 data.hbm = GDI_CreateDIBSection(renderdata->memory_hdc, rect->w, rect->h,
858 data.pitch, data.format, NULL,
859 &data.pixels);
860 if (!data.hbm) {
861 WIN_SetError("Couldn't create bitmap");
862 return -1;
863 }
864
865 SelectObject(renderdata->memory_hdc, data.hbm);
866 if (!BitBlt(renderdata->memory_hdc, 0, 0, rect->w, rect->h,
867 renderdata->current_hdc, rect->x, rect->y, SRCCOPY)) {
868 WIN_SetError("BitBlt()");
869 DeleteObject(data.hbm);
870 return -1;
871 }
872
873 SDL_ConvertPixels(rect->w, rect->h,
874 data.format, data.pixels, data.pitch,
875 format, pixels, pitch);
876
877 DeleteObject(data.hbm);
878 return 0;
879 }
880
881 static int
882 GDI_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect,
883 Uint32 format, const void * pixels, int pitch)
884 {
885 GDI_RenderData *renderdata = (GDI_RenderData *) renderer->driverdata;
886 SDL_Window *window = SDL_GetWindowFromID(renderer->window);
887 SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
888 struct {
889 HBITMAP hbm;
890 void *pixels;
891 int pitch;
892 Uint32 format;
893 } data;
894
895 data.format = display->current_mode.format;
896 data.pitch = (rect->w * SDL_BYTESPERPIXEL(data.format));
897
898 data.hbm = GDI_CreateDIBSection(renderdata->memory_hdc, rect->w, rect->h,
899 data.pitch, data.format,
900 NULL, &data.pixels);
901 if (!data.hbm) {
902 WIN_SetError("Couldn't create bitmap");
903 return -1;
904 }
905
906 SDL_ConvertPixels(rect->w, rect->h, format, pixels, pitch,
907 data.format, data.pixels, data.pitch);
908
909 SelectObject(renderdata->memory_hdc, data.hbm);
910 if (!BitBlt(renderdata->current_hdc, rect->x, rect->y, rect->w, rect->h,
911 renderdata->memory_hdc, 0, 0, SRCCOPY)) {
912 WIN_SetError("BitBlt()");
913 DeleteObject(data.hbm);
914 return -1;
915 }
916
917 DeleteObject(data.hbm);
918 return 0;
919 }
920
824 static void 921 static void
825 GDI_RenderPresent(SDL_Renderer * renderer) 922 GDI_RenderPresent(SDL_Renderer * renderer)
826 { 923 {
827 GDI_RenderData *data = (GDI_RenderData *) renderer->driverdata; 924 GDI_RenderData *data = (GDI_RenderData *) renderer->driverdata;
828 SDL_DirtyRect *dirty; 925 SDL_DirtyRect *dirty;