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. */