Mercurial > sdl-ios-xcode
comparison src/video/SDL_video.c @ 1670:eef792d31de8 SDL-1.3
Work in progress. :)
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Wed, 07 Jun 2006 16:10:28 +0000 |
parents | 9857d21967bb |
children | 8e754b82cecc |
comparison
equal
deleted
inserted
replaced
1669:9857d21967bb | 1670:eef792d31de8 |
---|---|
229 } | 229 } |
230 return -1; | 230 return -1; |
231 } | 231 } |
232 _this = video; | 232 _this = video; |
233 _this->name = bootstrap[i]->name; | 233 _this->name = bootstrap[i]->name; |
234 _this->next_window_id = 1; | 234 _this->next_object_id = 1; |
235 | 235 |
236 | 236 |
237 /* Set some very sane GL defaults */ | 237 /* Set some very sane GL defaults */ |
238 _this->gl_config.driver_loaded = 0; | 238 _this->gl_config.driver_loaded = 0; |
239 _this->gl_config.dll_handle = NULL; | 239 _this->gl_config.dll_handle = NULL; |
266 SDL_SetError("The video driver did not add any displays"); | 266 SDL_SetError("The video driver did not add any displays"); |
267 SDL_VideoQuit(); | 267 SDL_VideoQuit(); |
268 return (-1); | 268 return (-1); |
269 } | 269 } |
270 | 270 |
271 /* Temporarily here for backwards compatibility */ | |
272 { | |
273 int bpp; | |
274 Uint32 Rmask, Gmask, Bmask, Amask; | |
275 | |
276 SDL_PixelFormatEnumToMasks(SDL_GetDesktopDisplayMode()->format, &bpp, | |
277 &Rmask, &Gmask, &Bmask, &Amask); | |
278 _this->info.vfmt = SDL_AllocFormat(bpp, Rmask, Gmask, Bmask, Amask); | |
279 } | |
280 | |
281 /* Sort the video modes */ | 271 /* Sort the video modes */ |
282 for (i = 0; i < _this->num_displays; ++i) { | 272 for (i = 0; i < _this->num_displays; ++i) { |
283 SDL_qsort(_this->displays[i].display_modes, | 273 SDL_qsort(_this->displays[i].display_modes, |
284 _this->displays[i].num_display_modes, | 274 _this->displays[i].num_display_modes, |
285 sizeof(SDL_DisplayMode), cmpmodes); | 275 sizeof(SDL_DisplayMode), cmpmodes); |
309 SDL_GetVideoDevice() | 299 SDL_GetVideoDevice() |
310 { | 300 { |
311 return _this; | 301 return _this; |
312 } | 302 } |
313 | 303 |
314 const SDL_VideoInfo * | |
315 SDL_GetVideoInfo(void) | |
316 { | |
317 if (!_this) { | |
318 return NULL; | |
319 } | |
320 return &_this->info; | |
321 } | |
322 | |
323 void | 304 void |
324 SDL_AddBasicVideoDisplay(const SDL_DisplayMode * desktop_mode) | 305 SDL_AddBasicVideoDisplay(const SDL_DisplayMode * desktop_mode) |
325 { | 306 { |
326 SDL_VideoDisplay display; | 307 SDL_VideoDisplay display; |
327 | 308 |
328 SDL_zero(display); | 309 SDL_zero(display); |
329 if (desktop_mode) { | 310 if (desktop_mode) { |
330 display.desktop_mode = *desktop_mode; | 311 display.desktop_mode = *desktop_mode; |
331 } | 312 } |
332 display.current_mode = display.desktop_mode; | 313 display.current_mode = display.desktop_mode; |
333 display.max_windows = 1; | |
334 | 314 |
335 SDL_AddVideoDisplay(&display); | 315 SDL_AddVideoDisplay(&display); |
336 } | 316 } |
337 | 317 |
338 void | 318 void |
376 } | 356 } |
377 return _this->current_display; | 357 return _this->current_display; |
378 } | 358 } |
379 | 359 |
380 void | 360 void |
381 SDL_AddDisplayMode(int display, const SDL_DisplayMode * mode) | 361 SDL_AddDisplayMode(int displayIndex, const SDL_DisplayMode * mode) |
382 { | 362 { |
363 SDL_VideoDisplay *display = &_this->displays[displayIndex]; | |
383 SDL_DisplayMode *modes; | 364 SDL_DisplayMode *modes; |
384 int i, nmodes; | 365 int i, nmodes; |
385 | 366 |
386 /* Make sure we don't already have the mode in the list */ | 367 /* Make sure we don't already have the mode in the list */ |
387 modes = SDL_CurrentDisplay.display_modes; | 368 modes = display->display_modes; |
388 nmodes = SDL_CurrentDisplay.num_display_modes; | 369 nmodes = display->num_display_modes; |
389 for (i = 0; i < nmodes; ++i) { | 370 for (i = 0; i < nmodes; ++i) { |
390 if (SDL_memcmp(mode, &modes[i], sizeof(*mode)) == 0) { | 371 if (SDL_memcmp(mode, &modes[i], sizeof(*mode)) == 0) { |
391 return; | 372 return; |
392 } | 373 } |
393 } | 374 } |
394 | 375 |
395 /* Go ahead and add the new mode */ | 376 /* Go ahead and add the new mode */ |
396 modes = SDL_realloc(modes, (nmodes + 1) * sizeof(*mode)); | 377 modes = SDL_realloc(modes, (nmodes + 1) * sizeof(*mode)); |
397 if (modes) { | 378 if (modes) { |
398 SDL_CurrentDisplay.display_modes = modes; | 379 display->display_modes = modes; |
399 modes[nmodes] = *mode; | 380 modes[nmodes] = *mode; |
400 SDL_CurrentDisplay.num_display_modes++; | 381 display->num_display_modes++; |
401 } | 382 } |
402 } | 383 } |
403 | 384 |
404 int | 385 int |
405 SDL_GetNumDisplayModes() | 386 SDL_GetNumDisplayModes() |
413 const SDL_DisplayMode * | 394 const SDL_DisplayMode * |
414 SDL_GetDisplayMode(int index) | 395 SDL_GetDisplayMode(int index) |
415 { | 396 { |
416 if (index < 0 || index >= SDL_GetNumDisplayModes()) { | 397 if (index < 0 || index >= SDL_GetNumDisplayModes()) { |
417 SDL_SetError("index must be in the range of 0 - %d", | 398 SDL_SetError("index must be in the range of 0 - %d", |
418 SDL_GetNumDisplayModes()); | 399 SDL_GetNumDisplayModes() - 1); |
419 return NULL; | 400 return NULL; |
420 } | 401 } |
421 return &SDL_CurrentDisplay.display_modes[index]; | 402 return &SDL_CurrentDisplay.display_modes[index]; |
422 } | 403 } |
423 | 404 |
564 /* See if there's anything left to do */ | 545 /* See if there's anything left to do */ |
565 if (SDL_memcmp | 546 if (SDL_memcmp |
566 (&display_mode, SDL_GetCurrentDisplayMode(), | 547 (&display_mode, SDL_GetCurrentDisplayMode(), |
567 sizeof(display_mode)) == 0) { | 548 sizeof(display_mode)) == 0) { |
568 return 0; | 549 return 0; |
569 } | |
570 | |
571 /* Free any previous window surfaces */ | |
572 for (i = 0; i < display->num_windows; ++i) { | |
573 SDL_Window *window = &display->windows[i]; | |
574 if (window->shadow) { | |
575 SDL_FreeSurface(window->shadow); | |
576 window->shadow = NULL; | |
577 } | |
578 if (window->surface) { | |
579 SDL_FreeSurface(window->surface); | |
580 window->surface = NULL; | |
581 } | |
582 } | 550 } |
583 | 551 |
584 return _this->SetDisplayMode(_this, &display_mode); | 552 return _this->SetDisplayMode(_this, &display_mode); |
585 } | 553 } |
586 | 554 |
603 SDL_SetError("Video subsystem has not been initialized"); | 571 SDL_SetError("Video subsystem has not been initialized"); |
604 return 0; | 572 return 0; |
605 } | 573 } |
606 | 574 |
607 SDL_zero(window); | 575 SDL_zero(window); |
608 window.id = _this->next_window_id++; | 576 window.id = _this->next_object_id++; |
609 window.title = title ? SDL_strdup(title) : NULL; | 577 window.title = title ? SDL_strdup(title) : NULL; |
610 window.x = x; | 578 window.x = x; |
611 window.y = y; | 579 window.y = y; |
612 window.w = w; | 580 window.w = w; |
613 window.h = h; | 581 window.h = h; |
651 SDL_SetError("Video subsystem has not been initialized"); | 619 SDL_SetError("Video subsystem has not been initialized"); |
652 return (0); | 620 return (0); |
653 } | 621 } |
654 | 622 |
655 SDL_zero(window); | 623 SDL_zero(window); |
656 window.id = _this->next_window_id++; | 624 window.id = _this->next_object_id++; |
657 | 625 |
658 if (!_this->CreateWindowFrom || | 626 if (!_this->CreateWindowFrom || |
659 _this->CreateWindowFrom(_this, &window, data) < 0) { | 627 _this->CreateWindowFrom(_this, &window, data) < 0) { |
660 return 0; | 628 return 0; |
661 } | 629 } |
698 } | 666 } |
699 } | 667 } |
700 } | 668 } |
701 return NULL; | 669 return NULL; |
702 } | 670 } |
703 | |
704 SDL_Window * | |
705 SDL_GetWindowFromSurface(SDL_Surface * surface) | |
706 { | |
707 int i, j; | |
708 | |
709 if (!_this || !surface) { | |
710 return NULL; | |
711 } | |
712 | |
713 for (i = 0; i < _this->num_displays; ++i) { | |
714 SDL_VideoDisplay *display = &_this->displays[i]; | |
715 for (j = 0; j < display->num_windows; ++j) { | |
716 SDL_Window *window = &display->windows[j]; | |
717 if (surface == window->surface || surface == window->shadow) { | |
718 return window; | |
719 } | |
720 } | |
721 } | |
722 return NULL; | |
723 } | |
724 | |
725 | 671 |
726 Uint32 | 672 Uint32 |
727 SDL_GetWindowFlags(SDL_WindowID windowID) | 673 SDL_GetWindowFlags(SDL_WindowID windowID) |
728 { | 674 { |
729 SDL_Window *window = SDL_GetWindowFromID(windowID); | 675 SDL_Window *window = SDL_GetWindowFromID(windowID); |
996 } | 942 } |
997 if (window->flags & SDL_WINDOW_INPUT_GRABBED) { | 943 if (window->flags & SDL_WINDOW_INPUT_GRABBED) { |
998 window->flags &= ~SDL_WINDOW_INPUT_GRABBED; | 944 window->flags &= ~SDL_WINDOW_INPUT_GRABBED; |
999 _this->SetWindowGrab(_this, window); | 945 _this->SetWindowGrab(_this, window); |
1000 } | 946 } |
1001 if (window->shadow) { | 947 if (window->renderer) { |
1002 SDL_FreeSurface(window->shadow); | 948 SDL_DestroyRenderer(window->id); |
1003 } | |
1004 if (window->surface) { | |
1005 SDL_FreeSurface(window->surface); | |
1006 } | 949 } |
1007 if (_this->DestroyWindow) { | 950 if (_this->DestroyWindow) { |
1008 _this->DestroyWindow(_this, window); | 951 _this->DestroyWindow(_this, window); |
1009 } | 952 } |
1010 if (window->title) { | 953 if (window->title) { |
1022 return; | 965 return; |
1023 } | 966 } |
1024 } | 967 } |
1025 } | 968 } |
1026 | 969 |
1027 SDL_Surface * | 970 void |
1028 SDL_CreateWindowSurface(SDL_WindowID windowID, Uint32 format, Uint32 flags) | 971 SDL_AddRenderDriver(int displayIndex, const SDL_RenderDriver * driver) |
1029 { | 972 { |
1030 SDL_Window *window = SDL_GetWindowFromID(windowID); | 973 SDL_VideoDisplay *display = &_this->displays[displayIndex]; |
1031 Uint32 black; | 974 SDL_RenderDriver *render_drivers; |
1032 SDL_Surface *surface; | 975 |
976 render_drivers = | |
977 SDL_realloc(display->render_drivers, | |
978 (display->num_render_drivers + | |
979 1) * sizeof(*render_drivers)); | |
980 if (render_drivers) { | |
981 render_drivers[display->num_render_drivers] = *driver; | |
982 display->render_drivers = render_drivers; | |
983 display->num_render_drivers++; | |
984 } | |
985 } | |
986 | |
987 int | |
988 SDL_GetNumRenderers(void) | |
989 { | |
990 if (_this) { | |
991 return SDL_CurrentDisplay.num_render_drivers; | |
992 } | |
993 return 0; | |
994 } | |
995 | |
996 int | |
997 SDL_GetRendererInfo(int index, SDL_RendererInfo * info) | |
998 { | |
999 if (index < 0 || index >= SDL_GetNumRenderers()) { | |
1000 SDL_SetError("index must be in the range of 0 - %d", | |
1001 SDL_GetNumRenderers() - 1); | |
1002 return -1; | |
1003 } | |
1004 *info = SDL_CurrentDisplay.render_drivers[index].info; | |
1005 return 0; | |
1006 } | |
1007 | |
1008 int | |
1009 SDL_CreateRenderer(SDL_WindowID windowID, int index, Uint32 flags) | |
1010 { | |
1011 SDL_Window *window = SDL_GetWindowFromID(windowID); | |
1033 | 1012 |
1034 if (!window) { | 1013 if (!window) { |
1014 return 0; | |
1015 } | |
1016 | |
1017 if (index < 0) { | |
1018 int n = SDL_GetNumRenderers(); | |
1019 for (index = 0; index < n; ++index) { | |
1020 if ((SDL_CurrentDisplay.render_drivers[index].info. | |
1021 flags & flags) == flags) { | |
1022 break; | |
1023 } | |
1024 } | |
1025 if (index == n) { | |
1026 SDL_SetError("Couldn't find matching render driver"); | |
1027 return -1; | |
1028 } | |
1029 } | |
1030 | |
1031 if (index >= SDL_GetNumRenderers()) { | |
1032 SDL_SetError("index must be -1 or in the range of 0 - %d", | |
1033 SDL_GetNumRenderers() - 1); | |
1034 return -1; | |
1035 } | |
1036 | |
1037 /* Free any existing renderer */ | |
1038 SDL_DestroyRenderer(windowID); | |
1039 | |
1040 /* Create a new renderer instance */ | |
1041 window->renderer = | |
1042 SDL_CurrentDisplay.render_drivers[index].CreateRenderer(window, | |
1043 flags); | |
1044 if (!window->renderer) { | |
1045 return -1; | |
1046 } | |
1047 SDL_CurrentDisplay.current_renderer = window->renderer; | |
1048 | |
1049 return 0; | |
1050 } | |
1051 | |
1052 int | |
1053 SDL_SelectRenderer(SDL_WindowID windowID) | |
1054 { | |
1055 SDL_Window *window = SDL_GetWindowFromID(windowID); | |
1056 | |
1057 if (!window || !window->renderer) { | |
1058 return -1; | |
1059 } | |
1060 SDL_CurrentDisplay.current_renderer = window->renderer; | |
1061 return 0; | |
1062 } | |
1063 | |
1064 SDL_TextureID | |
1065 SDL_CreateTexture(Uint32 format, int access, int w, int h) | |
1066 { | |
1067 SDL_Renderer *renderer; | |
1068 SDL_Texture *texture; | |
1069 | |
1070 if (!_this) { | |
1071 return 0; | |
1072 } | |
1073 | |
1074 renderer = SDL_CurrentDisplay.current_renderer; | |
1075 if (!renderer || !renderer->CreateTexture) { | |
1076 return 0; | |
1077 } | |
1078 | |
1079 texture = (SDL_Texture *) SDL_malloc(sizeof(*texture)); | |
1080 if (!texture) { | |
1081 SDL_OutOfMemory(); | |
1082 return 0; | |
1083 } | |
1084 | |
1085 SDL_zerop(texture); | |
1086 texture->id = _this->next_object_id++; | |
1087 texture->format = format; | |
1088 texture->access = access; | |
1089 texture->w = w; | |
1090 texture->h = h; | |
1091 texture->renderer = renderer; | |
1092 | |
1093 if (renderer->CreateTexture(texture) < 0) { | |
1094 SDL_free(texture); | |
1095 return 0; | |
1096 } | |
1097 } | |
1098 | |
1099 SDL_TextureID | |
1100 SDL_CreateTextureFromSurface(Uint32 format, int access, SDL_Surface * surface) | |
1101 { | |
1102 SDL_TextureID textureID; | |
1103 Uint32 surface_flags = surface->flags; | |
1104 SDL_PixelFormat *fmt = surface->format; | |
1105 Uint32 colorkey; | |
1106 Uint8 alpha; | |
1107 SDL_Rect bounds; | |
1108 SDL_Surface dst; | |
1109 int bpp; | |
1110 Uint32 Rmask, Gmask, Bmask, Amask; | |
1111 | |
1112 if (!surface) { | |
1113 SDL_SetError("SDL_CreateTextureFromSurface() passed NULL surface"); | |
1114 return 0; | |
1115 } | |
1116 | |
1117 if (format) { | |
1118 if (!SDL_PixelFormatEnumToMasks | |
1119 (format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) { | |
1120 SDL_SetError("Unknown pixel format"); | |
1121 return 0; | |
1122 } | |
1123 } else { | |
1124 bpp = fmt->BitsPerPixel; | |
1125 Rmask = fmt->Rmask; | |
1126 Gmask = fmt->Gmask; | |
1127 Bmask = fmt->Bmask; | |
1128 Amask = fmt->Amask; | |
1129 format = SDL_MasksToPixelFormatEnum(bpp, Rmask, Gmask, Bmask, Amask); | |
1130 if (!format) { | |
1131 SDL_SetError("Unknown pixel format"); | |
1132 return 0; | |
1133 } | |
1134 } | |
1135 | |
1136 textureID = SDL_CreateTexture(format, access, surface->w, surface->h); | |
1137 if (!textureID) { | |
1138 return 0; | |
1139 } | |
1140 | |
1141 /* Set up a destination surface for the texture update */ | |
1142 SDL_zero(dst); | |
1143 dst.format = SDL_AllocFormat(bpp, Rmask, Gmask, Bmask, Amask); | |
1144 if (!dst.format) { | |
1145 SDL_DestroyTexture(textureID); | |
1146 return 0; | |
1147 } | |
1148 dst.w = surface->w; | |
1149 dst.h = surface->h; | |
1150 if (SDL_LockTexture(textureID, NULL, 1, &dst.pixels, &dst.pitch) == 0) { | |
1151 dst.flags |= SDL_PREALLOC; | |
1152 } else { | |
1153 dst.pitch = SDL_CalculatePitch(&dst); | |
1154 dst.pixels = SDL_malloc(dst.h * dst.pitch); | |
1155 if (!dst.pixels) { | |
1156 SDL_DestroyTexture(textureID); | |
1157 SDL_FreeFormat(dst.format); | |
1158 SDL_OutOfMemory(); | |
1159 return 0; | |
1160 } | |
1161 } | |
1162 | |
1163 /* Copy the palette if any */ | |
1164 if (fmt->palette && dst.format->palette) { | |
1165 SDL_SetTexturePalette(textureID, fmt->palette->colors, 0, | |
1166 fmt->palette->ncolors); | |
1167 | |
1168 SDL_memcpy(dst.format->palette->colors, | |
1169 fmt->palette->colors, | |
1170 fmt->palette->ncolors * sizeof(SDL_Color)); | |
1171 dst.format->palette->ncolors = fmt->palette->ncolors; | |
1172 } | |
1173 | |
1174 /* Make the texture transparent if the surface has colorkey */ | |
1175 if (surface_flags & SDL_SRCCOLORKEY) { | |
1176 int row; | |
1177 int length = dst.w * dst.format->BytesPerPixel; | |
1178 Uint8 *p = (Uint8 *) dst.pixels; | |
1179 for (row = 0; row < dst.h; ++row) { | |
1180 SDL_memset(p, 0, length); | |
1181 p += dst.pitch; | |
1182 } | |
1183 } | |
1184 | |
1185 /* Copy over the alpha channel */ | |
1186 if (surface_flags & SDL_SRCALPHA) { | |
1187 if (fmt->Amask) { | |
1188 surface->flags &= ~SDL_SRCALPHA; | |
1189 } else { | |
1190 /* FIXME: Need to make sure the texture has an alpha channel | |
1191 * and copy 'alpha' into the texture alpha channel. | |
1192 */ | |
1193 alpha = surface->format->alpha; | |
1194 SDL_SetAlpha(surface, 0, 0); | |
1195 } | |
1196 } | |
1197 | |
1198 /* Copy over the image data */ | |
1199 bounds.x = 0; | |
1200 bounds.y = 0; | |
1201 bounds.w = surface->w; | |
1202 bounds.h = surface->h; | |
1203 SDL_LowerBlit(surface, &bounds, &dst, &bounds); | |
1204 | |
1205 /* Clean up the original surface */ | |
1206 if ((surface_flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) { | |
1207 Uint32 cflags = surface_flags & (SDL_SRCCOLORKEY | SDL_RLEACCELOK); | |
1208 SDL_SetColorKey(surface, cflags, colorkey); | |
1209 } | |
1210 if ((surface_flags & SDL_SRCALPHA) == SDL_SRCALPHA) { | |
1211 Uint32 aflags = surface_flags & (SDL_SRCALPHA | SDL_RLEACCELOK); | |
1212 if (fmt->Amask) { | |
1213 surface->flags |= SDL_SRCALPHA; | |
1214 } else { | |
1215 SDL_SetAlpha(surface, aflags, alpha); | |
1216 } | |
1217 } | |
1218 | |
1219 /* Update the texture */ | |
1220 if (dst.flags & SDL_PREALLOC) { | |
1221 SDL_UnlockTexture(textureID); | |
1222 } else { | |
1223 SDL_UpdateTexture(textureID, NULL, dst.pixels, dst.pitch); | |
1224 SDL_free(dst.pixels); | |
1225 } | |
1226 SDL_FreeFormat(dst.format); | |
1227 | |
1228 return textureID; | |
1229 } | |
1230 | |
1231 static __inline__ SDL_Texture * | |
1232 SDL_GetTextureFromID(SDL_TextureID textureID) | |
1233 { | |
1234 int hash; | |
1235 SDL_Texture *texture; | |
1236 | |
1237 if (!_this) { | |
1035 return NULL; | 1238 return NULL; |
1036 } | 1239 } |
1037 | 1240 |
1038 if (!_this->CreateWindowSurface) { | 1241 hash = (textureID % SDL_arraysize(SDL_CurrentDisplay.textures)); |
1039 return NULL; | 1242 for (texture = SDL_CurrentDisplay.textures[hash]; texture; |
1040 } | 1243 texture = texture->next) { |
1041 | 1244 if (texture->id == textureID) { |
1042 if (!window->surface) { | 1245 return texture; |
1043 _this->CreateWindowSurface(_this, window, flags); | 1246 } |
1044 if (!window->surface) { | 1247 } |
1045 return NULL; | 1248 return NULL; |
1046 } | 1249 } |
1047 window->surface->flags |= SDL_SCREEN_SURFACE; | 1250 |
1048 | 1251 int |
1049 /* If we have a palettized surface, create a default palette */ | 1252 SDL_QueryTexture(SDL_TextureID textureID, Uint32 * format, int *access, |
1050 if (window->surface->format->palette) { | 1253 int *w, int *h) |
1051 SDL_Color colors[256]; | 1254 { |
1052 SDL_PixelFormat *vf = window->surface->format; | 1255 SDL_Texture *texture = SDL_GetTextureFromID(textureID); |
1053 SDL_DitherColors(colors, vf->BitsPerPixel); | 1256 |
1054 SDL_SetColors(window->surface, colors, 0, vf->palette->ncolors); | 1257 if (!texture) { |
1055 } | 1258 return -1; |
1056 } | 1259 } |
1057 surface = window->surface; | 1260 |
1058 | 1261 if (format) { |
1059 if (window->shadow) { | 1262 *format = texture->format; |
1060 SDL_FreeSurface(window->shadow); | 1263 } |
1061 window->shadow = NULL; | 1264 if (access) { |
1062 } | 1265 *access = texture->access; |
1063 | 1266 } |
1064 /* Create a shadow surface if necessary */ | 1267 if (w) { |
1065 if ((!(flags & SDL_ANYFORMAT) | 1268 *w = texture->w; |
1066 && (format != SDL_GetCurrentDisplayMode()->format)) | 1269 } |
1067 || ((flags & SDL_HWPALETTE) | 1270 if (h) { |
1068 && !(window->surface->flags & SDL_HWPALETTE))) { | 1271 *h = texture->h; |
1069 int bpp; | 1272 } |
1070 Uint32 Rmask, Gmask, Bmask, Amask; | 1273 return 0; |
1071 | 1274 } |
1072 SDL_PixelFormatEnumToMasks(format, &bpp, &Amask, &Gmask, &Bmask, | 1275 |
1073 &Amask); | 1276 int |
1074 window->shadow = | 1277 SDL_UpdateTexture(SDL_TextureID textureID, SDL_Rect * rect, |
1075 SDL_CreateRGBSurface(SDL_SWSURFACE, surface->w, surface->h, bpp, | 1278 const void *pixels, int pitch) |
1076 Rmask, Gmask, Bmask, Amask); | 1279 { |
1077 if (window->shadow == NULL) { | 1280 SDL_Texture *texture = SDL_GetTextureFromID(textureID); |
1078 return NULL; | 1281 SDL_Renderer *renderer; |
1079 } | 1282 |
1080 window->shadow->flags |= SDL_SHADOW_SURFACE; | 1283 if (!texture) { |
1081 | 1284 return -1; |
1082 surface = window->shadow; | 1285 } |
1083 | 1286 |
1084 /* 8-bit shadow surfaces report that they have exclusive palette */ | 1287 renderer = texture->renderer; |
1085 if (surface->format->palette) { | 1288 if (!renderer->UpdateTexture) { |
1086 surface->flags |= SDL_HWPALETTE; | 1289 return -1; |
1087 if (format == SDL_GetCurrentDisplayMode()->format) { | 1290 } |
1088 SDL_memcpy(surface->format->palette->colors, | 1291 return renderer->UpdateTexture(texture, rect, pixels, pitch); |
1089 window->surface->format->palette->colors, | 1292 } |
1090 window->surface->format->palette->ncolors * | 1293 |
1091 sizeof(SDL_Color)); | 1294 int |
1295 SDL_LockTexture(SDL_TextureID textureID, SDL_Rect * rect, int markDirty, | |
1296 void **pixels, int *pitch) | |
1297 { | |
1298 SDL_Texture *texture = SDL_GetTextureFromID(textureID); | |
1299 SDL_Renderer *renderer; | |
1300 | |
1301 if (!texture) { | |
1302 return -1; | |
1303 } | |
1304 | |
1305 renderer = texture->renderer; | |
1306 if (!renderer->LockTexture) { | |
1307 return -1; | |
1308 } | |
1309 return renderer->LockTexture(texture, rect, markDirty, pixels, pitch); | |
1310 } | |
1311 | |
1312 void | |
1313 SDL_UnlockTexture(SDL_TextureID textureID) | |
1314 { | |
1315 SDL_Texture *texture = SDL_GetTextureFromID(textureID); | |
1316 SDL_Renderer *renderer; | |
1317 | |
1318 if (!texture) { | |
1319 return; | |
1320 } | |
1321 | |
1322 renderer = texture->renderer; | |
1323 if (!renderer->UnlockTexture) { | |
1324 return; | |
1325 } | |
1326 return renderer->UnlockTexture(texture); | |
1327 } | |
1328 | |
1329 void | |
1330 SDL_DirtyTexture(SDL_TextureID textureID, int numrects, SDL_Rect * rects) | |
1331 { | |
1332 SDL_Texture *texture = SDL_GetTextureFromID(textureID); | |
1333 SDL_Renderer *renderer; | |
1334 | |
1335 if (!texture) { | |
1336 return; | |
1337 } | |
1338 | |
1339 renderer = texture->renderer; | |
1340 if (!renderer->DirtyTexture) { | |
1341 return; | |
1342 } | |
1343 renderer->DirtyTexture(texture, numrects, rects); | |
1344 } | |
1345 | |
1346 void | |
1347 SDL_SelectRenderTexture(SDL_TextureID textureID) | |
1348 { | |
1349 SDL_Texture *texture = SDL_GetTextureFromID(textureID); | |
1350 SDL_Renderer *renderer; | |
1351 | |
1352 if (!texture || texture->access != SDL_TextureAccess_Render) { | |
1353 return; | |
1354 } | |
1355 renderer = texture->renderer; | |
1356 if (!renderer->SelectRenderTexture) { | |
1357 return; | |
1358 } | |
1359 renderer->SelectRenderTexture(texture); | |
1360 } | |
1361 | |
1362 int | |
1363 SDL_RenderFill(SDL_Rect * rect, Uint32 color) | |
1364 { | |
1365 SDL_Renderer *renderer; | |
1366 | |
1367 if (!_this) { | |
1368 return -1; | |
1369 } | |
1370 | |
1371 renderer = SDL_CurrentDisplay.current_renderer; | |
1372 if (!renderer || !renderer->RenderFill) { | |
1373 return -1; | |
1374 } | |
1375 | |
1376 renderer->RenderFill(rect, color); | |
1377 } | |
1378 | |
1379 int | |
1380 SDL_RenderCopy(SDL_TextureID textureID, SDL_Rect * srcrect, | |
1381 SDL_Rect * dstrect, int blendMode, int scaleMode) | |
1382 { | |
1383 SDL_Texture *texture = SDL_GetTextureFromID(textureID); | |
1384 SDL_Renderer *renderer; | |
1385 | |
1386 if (!texture || texture->renderer != SDL_CurrentDisplay.current_renderer) { | |
1387 return; | |
1388 } | |
1389 | |
1390 renderer = SDL_CurrentDisplay.current_renderer; | |
1391 if (!renderer || !renderer->RenderCopy) { | |
1392 return -1; | |
1393 } | |
1394 | |
1395 return renderer->RenderCopy(texture, srcrect, dstrect, blendMode, | |
1396 scaleMode); | |
1397 } | |
1398 | |
1399 int | |
1400 SDL_RenderReadPixels(SDL_Rect * rect, void *pixels, int pitch) | |
1401 { | |
1402 SDL_Renderer *renderer; | |
1403 | |
1404 if (!_this) { | |
1405 return -1; | |
1406 } | |
1407 | |
1408 renderer = SDL_CurrentDisplay.current_renderer; | |
1409 if (!renderer || !renderer->RenderReadPixels) { | |
1410 return -1; | |
1411 } | |
1412 | |
1413 return renderer->RenderReadPixels(rect, pixels, pitch); | |
1414 } | |
1415 | |
1416 int | |
1417 SDL_RenderWritePixels(SDL_Rect * rect, const void *pixels, int pitch) | |
1418 { | |
1419 SDL_Renderer *renderer; | |
1420 | |
1421 if (!_this) { | |
1422 return -1; | |
1423 } | |
1424 | |
1425 renderer = SDL_CurrentDisplay.current_renderer; | |
1426 if (!renderer || !renderer->RenderWritePixels) { | |
1427 return -1; | |
1428 } | |
1429 | |
1430 return renderer->RenderWritePixels(rect, pixels, pitch); | |
1431 } | |
1432 | |
1433 void | |
1434 SDL_RenderPresent(void) | |
1435 { | |
1436 SDL_Renderer *renderer; | |
1437 | |
1438 if (!_this) { | |
1439 return; | |
1440 } | |
1441 | |
1442 renderer = SDL_CurrentDisplay.current_renderer; | |
1443 if (!renderer || !renderer->RenderPresent) { | |
1444 return; | |
1445 } | |
1446 | |
1447 renderer->RenderPresent(); | |
1448 } | |
1449 | |
1450 void | |
1451 SDL_DestroyTexture(SDL_TextureID textureID) | |
1452 { | |
1453 int hash; | |
1454 SDL_Texture *prev, *texture; | |
1455 SDL_Renderer *renderer; | |
1456 | |
1457 if (!_this) { | |
1458 return; | |
1459 } | |
1460 | |
1461 /* Look up the texture in the hash table */ | |
1462 hash = (textureID % SDL_arraysize(SDL_CurrentDisplay.textures)); | |
1463 prev = NULL; | |
1464 for (texture = SDL_CurrentDisplay.textures[hash]; texture; | |
1465 prev = texture, texture = texture->next) { | |
1466 if (texture->id == textureID) { | |
1467 break; | |
1468 } | |
1469 } | |
1470 if (!texture) { | |
1471 return; | |
1472 } | |
1473 | |
1474 /* Unlink the texture from the list */ | |
1475 if (prev) { | |
1476 prev->next = texture->next; | |
1477 } else { | |
1478 SDL_CurrentDisplay.textures[hash] = texture->next; | |
1479 } | |
1480 | |
1481 /* Free the texture */ | |
1482 renderer = texture->renderer; | |
1483 renderer->DestroyTexture(texture); | |
1484 SDL_free(texture); | |
1485 } | |
1486 | |
1487 void | |
1488 SDL_DestroyRenderer(SDL_WindowID windowID) | |
1489 { | |
1490 SDL_Window *window = SDL_GetWindowFromID(windowID); | |
1491 SDL_Renderer *renderer; | |
1492 int i; | |
1493 | |
1494 if (!window) { | |
1495 return; | |
1496 } | |
1497 | |
1498 renderer = window->renderer; | |
1499 if (!renderer) { | |
1500 return; | |
1501 } | |
1502 | |
1503 /* Free existing textures for this renderer */ | |
1504 for (i = 0; i < SDL_arraysize(SDL_CurrentDisplay.textures); ++i) { | |
1505 SDL_Texture *texture; | |
1506 SDL_Texture *prev = NULL; | |
1507 SDL_Texture *next; | |
1508 for (texture = SDL_CurrentDisplay.textures[i]; texture; | |
1509 texture = next) { | |
1510 next = texture->next; | |
1511 if (texture->renderer == renderer) { | |
1512 if (prev) { | |
1513 prev->next = next; | |
1514 } else { | |
1515 SDL_CurrentDisplay.textures[i] = next; | |
1516 } | |
1517 renderer->DestroyTexture(texture); | |
1518 SDL_free(texture); | |
1092 } else { | 1519 } else { |
1093 SDL_DitherColors(surface->format->palette->colors, bpp); | 1520 prev = texture; |
1094 } | 1521 } |
1095 } | 1522 } |
1096 } | 1523 } |
1097 | 1524 |
1098 /* Clear the surface for display */ | 1525 /* Free the renderer instance */ |
1099 { | 1526 renderer->DestroyRenderer(renderer); |
1100 Uint32 black = SDL_MapRGB(surface->format, 0, 0, 0); | 1527 |
1101 SDL_FillRect(surface, NULL, black); | 1528 /* Clear references */ |
1102 if (surface->flags & SDL_DOUBLEBUF) { | 1529 window->renderer = NULL; |
1103 SDL_Flip(surface); | 1530 if (SDL_CurrentDisplay.current_renderer == renderer) { |
1104 SDL_FillRect(surface, NULL, black); | 1531 SDL_CurrentDisplay.current_renderer = NULL; |
1105 } | 1532 } |
1106 SDL_Flip(surface); | |
1107 } | |
1108 | |
1109 return surface; | |
1110 } | |
1111 | |
1112 /* | |
1113 * Convert a surface into the video pixel format. | |
1114 */ | |
1115 SDL_Surface * | |
1116 SDL_DisplayFormat(SDL_Surface * surface) | |
1117 { | |
1118 Uint32 flags; | |
1119 | |
1120 if (!SDL_PublicSurface) { | |
1121 SDL_SetError("No video mode has been set"); | |
1122 return (NULL); | |
1123 } | |
1124 /* Set the flags appropriate for copying to display surface */ | |
1125 if (((SDL_PublicSurface->flags & SDL_HWSURFACE) == SDL_HWSURFACE) | |
1126 && _this->info.blit_hw) | |
1127 flags = SDL_HWSURFACE; | |
1128 else | |
1129 flags = SDL_SWSURFACE; | |
1130 #ifdef AUTORLE_DISPLAYFORMAT | |
1131 flags |= (surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA)); | |
1132 flags |= SDL_RLEACCELOK; | |
1133 #else | |
1134 flags |= | |
1135 surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA | SDL_RLEACCELOK); | |
1136 #endif | |
1137 return (SDL_ConvertSurface(surface, SDL_PublicSurface->format, flags)); | |
1138 } | |
1139 | |
1140 /* | |
1141 * Convert a surface into a format that's suitable for blitting to | |
1142 * the screen, but including an alpha channel. | |
1143 */ | |
1144 SDL_Surface * | |
1145 SDL_DisplayFormatAlpha(SDL_Surface * surface) | |
1146 { | |
1147 SDL_PixelFormat *vf; | |
1148 SDL_PixelFormat *format; | |
1149 SDL_Surface *converted; | |
1150 Uint32 flags; | |
1151 /* default to ARGB8888 */ | |
1152 Uint32 amask = 0xff000000; | |
1153 Uint32 rmask = 0x00ff0000; | |
1154 Uint32 gmask = 0x0000ff00; | |
1155 Uint32 bmask = 0x000000ff; | |
1156 | |
1157 if (!SDL_PublicSurface) { | |
1158 SDL_SetError("No video mode has been set"); | |
1159 return (NULL); | |
1160 } | |
1161 vf = SDL_PublicSurface->format; | |
1162 | |
1163 switch (vf->BytesPerPixel) { | |
1164 case 2: | |
1165 /* For XGY5[56]5, use, AXGY8888, where {X, Y} = {R, B}. | |
1166 For anything else (like ARGB4444) it doesn't matter | |
1167 since we have no special code for it anyway */ | |
1168 if ((vf->Rmask == 0x1f) && | |
1169 (vf->Bmask == 0xf800 || vf->Bmask == 0x7c00)) { | |
1170 rmask = 0xff; | |
1171 bmask = 0xff0000; | |
1172 } | |
1173 break; | |
1174 | |
1175 case 3: | |
1176 case 4: | |
1177 /* Keep the video format, as long as the high 8 bits are | |
1178 unused or alpha */ | |
1179 if ((vf->Rmask == 0xff) && (vf->Bmask == 0xff0000)) { | |
1180 rmask = 0xff; | |
1181 bmask = 0xff0000; | |
1182 } | |
1183 break; | |
1184 | |
1185 default: | |
1186 /* We have no other optimised formats right now. When/if a new | |
1187 optimised alpha format is written, add the converter here */ | |
1188 break; | |
1189 } | |
1190 format = SDL_AllocFormat(32, rmask, gmask, bmask, amask); | |
1191 flags = SDL_PublicSurface->flags & SDL_HWSURFACE; | |
1192 flags |= surface->flags & (SDL_SRCALPHA | SDL_RLEACCELOK); | |
1193 converted = SDL_ConvertSurface(surface, format, flags); | |
1194 SDL_FreeFormat(format); | |
1195 return (converted); | |
1196 } | |
1197 | |
1198 /* | |
1199 * Update a specific portion of the physical screen | |
1200 */ | |
1201 void | |
1202 SDL_UpdateRect(SDL_Surface * screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h) | |
1203 { | |
1204 if (screen) { | |
1205 SDL_Rect rect; | |
1206 | |
1207 /* Perform some checking */ | |
1208 if (w == 0) | |
1209 w = screen->w; | |
1210 if (h == 0) | |
1211 h = screen->h; | |
1212 if ((int) (x + w) > screen->w) | |
1213 return; | |
1214 if ((int) (y + h) > screen->h) | |
1215 return; | |
1216 | |
1217 /* Fill the rectangle */ | |
1218 rect.x = (Sint16) x; | |
1219 rect.y = (Sint16) y; | |
1220 rect.w = (Uint16) w; | |
1221 rect.h = (Uint16) h; | |
1222 SDL_UpdateRects(screen, 1, &rect); | |
1223 } | |
1224 } | |
1225 void | |
1226 SDL_UpdateRects(SDL_Surface * screen, int numrects, SDL_Rect * rects) | |
1227 { | |
1228 int i; | |
1229 SDL_Window *window; | |
1230 | |
1231 /* Find the window corresponding to this surface */ | |
1232 window = SDL_GetWindowFromSurface(screen); | |
1233 if (!window) { | |
1234 SDL_SetError("Couldn't find window associated with surface"); | |
1235 return; | |
1236 } | |
1237 | |
1238 if (screen->flags & SDL_SHADOW_SURFACE) { | |
1239 if (SHOULD_DRAWCURSOR(SDL_cursorstate)) { | |
1240 SDL_LockCursor(); | |
1241 SDL_DrawCursor(screen); | |
1242 for (i = 0; i < numrects; ++i) { | |
1243 SDL_LowerBlit(screen, &rects[i], window->surface, &rects[i]); | |
1244 } | |
1245 SDL_EraseCursor(screen); | |
1246 SDL_UnlockCursor(); | |
1247 } else { | |
1248 for (i = 0; i < numrects; ++i) { | |
1249 SDL_LowerBlit(screen, &rects[i], window->surface, &rects[i]); | |
1250 } | |
1251 } | |
1252 | |
1253 /* Fall through to video surface update */ | |
1254 screen = window->surface; | |
1255 } | |
1256 if ((screen->flags & SDL_SCREEN_SURFACE) && _this->UpdateWindowSurface) { | |
1257 /* Update the video surface */ | |
1258 if (screen->offset) { | |
1259 int offset_y = screen->offset / screen->pitch; | |
1260 int offset_x = screen->offset % screen->pitch; | |
1261 for (i = 0; i < numrects; ++i) { | |
1262 rects[i].x += offset_x; | |
1263 rects[i].y += offset_y; | |
1264 } | |
1265 _this->UpdateWindowSurface(_this, window, numrects, rects); | |
1266 for (i = 0; i < numrects; ++i) { | |
1267 rects[i].x -= offset_x; | |
1268 rects[i].y -= offset_y; | |
1269 } | |
1270 } else { | |
1271 _this->UpdateWindowSurface(_this, window, numrects, rects); | |
1272 } | |
1273 } | |
1274 } | |
1275 | |
1276 /* | |
1277 * Performs hardware double buffering, if possible, or a full update if not. | |
1278 */ | |
1279 int | |
1280 SDL_Flip(SDL_Surface * screen) | |
1281 { | |
1282 SDL_Window *window; | |
1283 | |
1284 /* Find the window corresponding to this surface */ | |
1285 window = SDL_GetWindowFromSurface(screen); | |
1286 if (!window) { | |
1287 SDL_SetError("Couldn't find window associated with surface"); | |
1288 return; | |
1289 } | |
1290 | |
1291 /* Copy the shadow surface to the video surface */ | |
1292 if (screen->flags & SDL_SHADOW_SURFACE) { | |
1293 SDL_Rect rect; | |
1294 | |
1295 rect.x = 0; | |
1296 rect.y = 0; | |
1297 rect.w = screen->w; | |
1298 rect.h = screen->h; | |
1299 if (SHOULD_DRAWCURSOR(SDL_cursorstate)) { | |
1300 SDL_LockCursor(); | |
1301 SDL_DrawCursor(screen); | |
1302 SDL_LowerBlit(screen, &rect, window->surface, &rect); | |
1303 SDL_EraseCursor(screen); | |
1304 SDL_UnlockCursor(); | |
1305 } else { | |
1306 SDL_LowerBlit(screen, &rect, window->surface, &rect); | |
1307 } | |
1308 | |
1309 /* Fall through to video surface update */ | |
1310 screen = window->surface; | |
1311 } | |
1312 if (screen->flags & SDL_DOUBLEBUF) { | |
1313 _this->FlipWindowSurface(_this, window); | |
1314 } else { | |
1315 SDL_UpdateRect(screen, 0, 0, 0, 0); | |
1316 } | |
1317 return (0); | |
1318 } | |
1319 | |
1320 int | |
1321 SDL_SetColors(SDL_Surface * screen, SDL_Color * colors, int firstcolor, | |
1322 int ncolors) | |
1323 { | |
1324 SDL_Window *window = NULL; | |
1325 SDL_Palette *pal; | |
1326 int gotall; | |
1327 int palsize; | |
1328 | |
1329 /* Verify the parameters */ | |
1330 pal = screen->format->palette; | |
1331 if (!pal) { | |
1332 return 0; /* not a palettized surface */ | |
1333 } | |
1334 gotall = 1; | |
1335 palsize = 1 << screen->format->BitsPerPixel; | |
1336 if (ncolors > (palsize - firstcolor)) { | |
1337 ncolors = (palsize - firstcolor); | |
1338 gotall = 0; | |
1339 } | |
1340 | |
1341 if (colors != (pal->colors + firstcolor)) { | |
1342 SDL_memcpy(pal->colors + firstcolor, colors, | |
1343 ncolors * sizeof(*colors)); | |
1344 } | |
1345 SDL_FormatChanged(screen); | |
1346 | |
1347 if (screen->flags & (SDL_SHADOW_SURFACE | SDL_SCREEN_SURFACE)) { | |
1348 window = SDL_GetWindowFromSurface(screen); | |
1349 if (!window) { | |
1350 return 0; | |
1351 } | |
1352 } | |
1353 | |
1354 if (screen->flags & SDL_SHADOW_SURFACE) { | |
1355 SDL_Palette *vidpal; | |
1356 | |
1357 vidpal = window->surface->format->palette; | |
1358 if (vidpal && vidpal->ncolors == pal->ncolors) { | |
1359 /* This is a shadow surface, and the physical | |
1360 * framebuffer is also indexed. Propagate the | |
1361 * changes to its logical palette so that | |
1362 * updates are always identity blits | |
1363 */ | |
1364 SDL_memcpy(vidpal->colors + firstcolor, colors, | |
1365 ncolors * sizeof(*colors)); | |
1366 } | |
1367 if (window->surface->flags & SDL_HWPALETTE) { | |
1368 /* Set the physical palette */ | |
1369 screen = window->surface; | |
1370 } else { | |
1371 SDL_UpdateRect(screen, 0, 0, 0, 0); | |
1372 } | |
1373 } | |
1374 | |
1375 if (screen->flags & SDL_SCREEN_SURFACE) { | |
1376 if (_this->SetWindowColors) { | |
1377 gotall = | |
1378 _this->SetWindowColors(_this, window, firstcolor, ncolors, | |
1379 colors); | |
1380 if (!gotall) { | |
1381 /* The video flags shouldn't have SDL_HWPALETTE, and | |
1382 the video driver is responsible for copying back the | |
1383 correct colors into the video surface palette. | |
1384 */ | |
1385 ; | |
1386 } | |
1387 } | |
1388 SDL_CursorPaletteChanged(); | |
1389 } | |
1390 | |
1391 return gotall; | |
1392 } | 1533 } |
1393 | 1534 |
1394 void | 1535 void |
1395 SDL_VideoQuit(void) | 1536 SDL_VideoQuit(void) |
1396 { | 1537 { |
1414 } | 1555 } |
1415 if (display->windows) { | 1556 if (display->windows) { |
1416 SDL_free(display->windows); | 1557 SDL_free(display->windows); |
1417 display->windows = NULL; | 1558 display->windows = NULL; |
1418 } | 1559 } |
1560 SDL_free(display->info.vfmt); | |
1419 } | 1561 } |
1420 _this->VideoQuit(_this); | 1562 _this->VideoQuit(_this); |
1421 if (_this->displays) { | 1563 if (_this->displays) { |
1422 SDL_free(_this->displays); | 1564 SDL_free(_this->displays); |
1423 } | 1565 } |
1424 SDL_free(_this->info.vfmt); | |
1425 _this->free(_this); | 1566 _this->free(_this); |
1426 _this = NULL; | 1567 _this = NULL; |
1427 } | 1568 } |
1428 | 1569 |
1429 /* Load the GL driver library */ | 1570 /* Load the GL driver library */ |
1547 | 1688 |
1548 /* Perform a GL buffer swap on the current GL context */ | 1689 /* Perform a GL buffer swap on the current GL context */ |
1549 void | 1690 void |
1550 SDL_GL_SwapBuffers(void) | 1691 SDL_GL_SwapBuffers(void) |
1551 { | 1692 { |
1552 if (SDL_VideoSurface->flags & SDL_INTERNALOPENGL) { | 1693 // FIXME: Track the current window context - do we provide N contexts, and match them to M windows, or is there a one-to-one mapping? |
1553 _this->GL_SwapBuffers(_this); | 1694 _this->GL_SwapBuffers(_this); |
1554 } else { | |
1555 SDL_SetError("OpenGL video mode has not been set"); | |
1556 } | |
1557 } | 1695 } |
1558 | 1696 |
1559 #if 0 // FIXME | 1697 #if 0 // FIXME |
1560 /* Utility function used by SDL_WM_SetIcon(); | 1698 /* Utility function used by SDL_WM_SetIcon(); |
1561 * flags & 1 for color key, flags & 2 for alpha channel. */ | 1699 * flags & 1 for color key, flags & 2 for alpha channel. */ |