2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2009 Sam Lantinga
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "SDL_config.h"
24 #include "SDL_video.h"
25 #include "SDL_sysvideo.h"
26 #include "SDL_cursor_c.h"
28 #include "SDL_RLEaccel_c.h"
29 #include "SDL_pixels_c.h"
30 #include "SDL_leaks.h"
35 * Create an empty RGB surface of the appropriate depth
37 SDL_Surface * SDL_CreateRGBSurface (Uint32 flags,
38 int width, int height, int depth,
39 Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
41 SDL_VideoDevice *video = current_video;
42 SDL_VideoDevice *this = current_video;
46 /* Make sure the size requested doesn't overflow our datatypes */
47 /* Next time I write a library like SDL, I'll use int for size. :) */
48 if ( width >= 16384 || height >= 65536 ) {
49 SDL_SetError("Width or height is too large");
53 /* Check to see if we desire the surface in video memory */
55 screen = SDL_PublicSurface;
59 if ( screen && ((screen->flags&SDL_HWSURFACE) == SDL_HWSURFACE) ) {
60 if ( (flags&(SDL_SRCCOLORKEY|SDL_SRCALPHA)) != 0 ) {
61 flags |= SDL_HWSURFACE;
63 if ( (flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) {
64 if ( ! current_video->info.blit_hw_CC ) {
65 flags &= ~SDL_HWSURFACE;
68 if ( (flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
69 if ( ! current_video->info.blit_hw_A ) {
70 flags &= ~SDL_HWSURFACE;
74 flags &= ~SDL_HWSURFACE;
77 /* Allocate the surface */
78 surface = (SDL_Surface *)SDL_malloc(sizeof(*surface));
79 if ( surface == NULL ) {
83 surface->flags = SDL_SWSURFACE;
84 if ( (flags & SDL_HWSURFACE) == SDL_HWSURFACE ) {
85 if ((Amask) && (video->displayformatalphapixel))
87 depth = video->displayformatalphapixel->BitsPerPixel;
88 Rmask = video->displayformatalphapixel->Rmask;
89 Gmask = video->displayformatalphapixel->Gmask;
90 Bmask = video->displayformatalphapixel->Bmask;
91 Amask = video->displayformatalphapixel->Amask;
95 depth = screen->format->BitsPerPixel;
96 Rmask = screen->format->Rmask;
97 Gmask = screen->format->Gmask;
98 Bmask = screen->format->Bmask;
99 Amask = screen->format->Amask;
102 surface->format = SDL_AllocFormat(depth, Rmask, Gmask, Bmask, Amask);
103 if ( surface->format == NULL ) {
108 surface->flags |= SDL_SRCALPHA;
112 surface->pitch = SDL_CalculatePitch(surface);
113 surface->pixels = NULL;
115 surface->hwdata = NULL;
118 surface->unused1 = 0;
119 SDL_SetClipRect(surface, NULL);
120 SDL_FormatChanged(surface);
123 if ( ((flags&SDL_HWSURFACE) == SDL_SWSURFACE) ||
124 (video->AllocHWSurface(this, surface) < 0) ) {
125 if ( surface->w && surface->h ) {
126 surface->pixels = SDL_malloc(surface->h*surface->pitch);
127 if ( surface->pixels == NULL ) {
128 SDL_FreeSurface(surface);
132 /* This is important for bitmaps */
133 SDL_memset(surface->pixels, 0, surface->h*surface->pitch);
137 /* Allocate an empty mapping */
138 surface->map = SDL_AllocBlitMap();
139 if ( surface->map == NULL ) {
140 SDL_FreeSurface(surface);
144 /* The surface is ready to go */
145 surface->refcount = 1;
147 ++surfaces_allocated;
152 * Create an RGB surface from an existing memory buffer
154 SDL_Surface * SDL_CreateRGBSurfaceFrom (void *pixels,
155 int width, int height, int depth, int pitch,
156 Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
158 SDL_Surface *surface;
160 surface = SDL_CreateRGBSurface(SDL_SWSURFACE, 0, 0, depth,
161 Rmask, Gmask, Bmask, Amask);
162 if ( surface != NULL ) {
163 surface->flags |= SDL_PREALLOC;
164 surface->pixels = pixels;
167 surface->pitch = pitch;
168 SDL_SetClipRect(surface, NULL);
173 * Set the color key in a blittable surface
175 int SDL_SetColorKey (SDL_Surface *surface, Uint32 flag, Uint32 key)
177 /* Sanity check the flag as it gets passed in */
178 if ( flag & SDL_SRCCOLORKEY ) {
179 if ( flag & (SDL_RLEACCEL|SDL_RLEACCELOK) ) {
180 flag = (SDL_SRCCOLORKEY | SDL_RLEACCELOK);
182 flag = SDL_SRCCOLORKEY;
188 /* Optimize away operations that don't change anything */
189 if ( (flag == (surface->flags & (SDL_SRCCOLORKEY|SDL_RLEACCELOK))) &&
190 (key == surface->format->colorkey) ) {
194 /* UnRLE surfaces before we change the colorkey */
195 if ( surface->flags & SDL_RLEACCEL ) {
196 SDL_UnRLESurface(surface, 1);
200 SDL_VideoDevice *video = current_video;
201 SDL_VideoDevice *this = current_video;
204 surface->flags |= SDL_SRCCOLORKEY;
205 surface->format->colorkey = key;
206 if ( (surface->flags & SDL_HWACCEL) == SDL_HWACCEL ) {
207 if ( (video->SetHWColorKey == NULL) ||
208 (video->SetHWColorKey(this, surface, key) < 0) ) {
209 surface->flags &= ~SDL_HWACCEL;
212 if ( flag & SDL_RLEACCELOK ) {
213 surface->flags |= SDL_RLEACCELOK;
215 surface->flags &= ~SDL_RLEACCELOK;
218 surface->flags &= ~(SDL_SRCCOLORKEY|SDL_RLEACCELOK);
219 surface->format->colorkey = 0;
221 SDL_InvalidateMap(surface->map);
224 /* This function sets the alpha channel of a surface */
225 int SDL_SetAlpha (SDL_Surface *surface, Uint32 flag, Uint8 value)
227 Uint32 oldflags = surface->flags;
228 Uint32 oldalpha = surface->format->alpha;
230 /* Sanity check the flag as it gets passed in */
231 if ( flag & SDL_SRCALPHA ) {
232 if ( flag & (SDL_RLEACCEL|SDL_RLEACCELOK) ) {
233 flag = (SDL_SRCALPHA | SDL_RLEACCELOK);
241 /* Optimize away operations that don't change anything */
242 if ( (flag == (surface->flags & (SDL_SRCALPHA|SDL_RLEACCELOK))) &&
243 (!flag || value == oldalpha) ) {
247 if(!(flag & SDL_RLEACCELOK) && (surface->flags & SDL_RLEACCEL))
248 SDL_UnRLESurface(surface, 1);
251 SDL_VideoDevice *video = current_video;
252 SDL_VideoDevice *this = current_video;
254 surface->flags |= SDL_SRCALPHA;
255 surface->format->alpha = value;
256 if ( (surface->flags & SDL_HWACCEL) == SDL_HWACCEL ) {
257 if ( (video->SetHWAlpha == NULL) ||
258 (video->SetHWAlpha(this, surface, value) < 0) ) {
259 surface->flags &= ~SDL_HWACCEL;
262 if ( flag & SDL_RLEACCELOK ) {
263 surface->flags |= SDL_RLEACCELOK;
265 surface->flags &= ~SDL_RLEACCELOK;
268 surface->flags &= ~SDL_SRCALPHA;
269 surface->format->alpha = SDL_ALPHA_OPAQUE;
272 * The representation for software surfaces is independent of
273 * per-surface alpha, so no need to invalidate the blit mapping
274 * if just the alpha value was changed. (If either is 255, we still
275 * need to invalidate.)
277 if((surface->flags & SDL_HWACCEL) == SDL_HWACCEL
278 || oldflags != surface->flags
279 || (((oldalpha + 1) ^ (value + 1)) & 0x100))
280 SDL_InvalidateMap(surface->map);
283 int SDL_SetAlphaChannel(SDL_Surface *surface, Uint8 value)
289 if ( (surface->format->Amask != 0xFF000000) &&
290 (surface->format->Amask != 0x000000FF) ) {
291 SDL_SetError("Unsupported surface alpha mask format");
295 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
296 if ( surface->format->Amask == 0xFF000000 ) {
302 if ( surface->format->Amask == 0xFF000000 ) {
307 #endif /* Byte ordering */
309 /* Quickly set the alpha channel of an RGBA or ARGB surface */
310 if ( SDL_MUSTLOCK(surface) ) {
311 if ( SDL_LockSurface(surface) < 0 ) {
318 buf = (Uint8 *)surface->pixels + row * surface->pitch + offset;
324 if ( SDL_MUSTLOCK(surface) ) {
325 SDL_UnlockSurface(surface);
331 * A function to calculate the intersection of two rectangles:
332 * return true if the rectangles intersect, false otherwise
335 SDL_bool SDL_IntersectRect(const SDL_Rect *A, const SDL_Rect *B, SDL_Rect *intersection)
337 int Amin, Amax, Bmin, Bmax;
339 /* Horizontal intersection */
346 intersection->x = Amin;
349 intersection->w = Amax - Amin > 0 ? Amax - Amin : 0;
351 /* Vertical intersection */
358 intersection->y = Amin;
361 intersection->h = Amax - Amin > 0 ? Amax - Amin : 0;
363 return (intersection->w && intersection->h);
366 * Set the clipping rectangle for a blittable surface
368 SDL_bool SDL_SetClipRect(SDL_Surface *surface, const SDL_Rect *rect)
372 /* Don't do anything if there's no surface to act on */
377 /* Set up the full surface rectangle */
380 full_rect.w = surface->w;
381 full_rect.h = surface->h;
383 /* Set the clipping rectangle */
385 surface->clip_rect = full_rect;
388 return SDL_IntersectRect(rect, &full_rect, &surface->clip_rect);
390 void SDL_GetClipRect(SDL_Surface *surface, SDL_Rect *rect)
392 if ( surface && rect ) {
393 *rect = surface->clip_rect;
397 * Set up a blit between two surfaces -- split into three parts:
398 * The upper part, SDL_UpperBlit(), performs clipping and rectangle
399 * verification. The lower part is a pointer to a low level
400 * accelerated blitting function.
402 * These parts are separated out and each used internally by this
403 * library in the optimimum places. They are exported so that if
404 * you know exactly what you are doing, you can optimize your code
405 * by calling the one(s) you need.
407 int SDL_LowerBlit (SDL_Surface *src, SDL_Rect *srcrect,
408 SDL_Surface *dst, SDL_Rect *dstrect)
414 /* Check to make sure the blit mapping is valid */
415 if ( (src->map->dst != dst) ||
416 (src->map->dst->format_version != src->map->format_version) ) {
417 if ( SDL_MapSurface(src, dst) < 0 ) {
422 /* Figure out which blitter to use */
423 if ( (src->flags & SDL_HWACCEL) == SDL_HWACCEL ) {
424 if ( src == SDL_VideoSurface ) {
425 hw_srcrect = *srcrect;
426 hw_srcrect.x += current_video->offset_x;
427 hw_srcrect.y += current_video->offset_y;
428 srcrect = &hw_srcrect;
430 if ( dst == SDL_VideoSurface ) {
431 hw_dstrect = *dstrect;
432 hw_dstrect.x += current_video->offset_x;
433 hw_dstrect.y += current_video->offset_y;
434 dstrect = &hw_dstrect;
436 do_blit = src->map->hw_blit;
438 do_blit = src->map->sw_blit;
440 return(do_blit(src, srcrect, dst, dstrect));
444 int SDL_UpperBlit (SDL_Surface *src, SDL_Rect *srcrect,
445 SDL_Surface *dst, SDL_Rect *dstrect)
448 int srcx, srcy, w, h;
450 /* Make sure the surfaces aren't locked */
451 if ( ! src || ! dst ) {
452 SDL_SetError("SDL_UpperBlit: passed a NULL surface");
455 if ( src->locked || dst->locked ) {
456 SDL_SetError("Surfaces must not be locked during blit");
460 /* If the destination rectangle is NULL, use the entire dest surface */
461 if ( dstrect == NULL ) {
462 fulldst.x = fulldst.y = 0;
466 /* clip the source rectangle to the source surface */
477 maxw = src->w - srcx;
488 maxh = src->h - srcy;
498 /* clip the destination rectangle against the clip rectangle */
500 SDL_Rect *clip = &dst->clip_rect;
503 dx = clip->x - dstrect->x;
509 dx = dstrect->x + w - clip->x - clip->w;
513 dy = clip->y - dstrect->y;
519 dy = dstrect->y + h - clip->y - clip->h;
528 sr.w = dstrect->w = w;
529 sr.h = dstrect->h = h;
530 return SDL_LowerBlit(src, &sr, dst, dstrect);
532 dstrect->w = dstrect->h = 0;
536 static int SDL_FillRect1(SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color)
538 /* FIXME: We have to worry about packing order.. *sigh* */
539 SDL_SetError("1-bpp rect fill not yet implemented");
543 static int SDL_FillRect4(SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color)
545 /* FIXME: We have to worry about packing order.. *sigh* */
546 SDL_SetError("4-bpp rect fill not yet implemented");
551 * This function performs a fast fill of the given rectangle with 'color'
553 int SDL_FillRect(SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color)
555 SDL_VideoDevice *video = current_video;
556 SDL_VideoDevice *this = current_video;
560 /* This function doesn't work on surfaces < 8 bpp */
561 if ( dst->format->BitsPerPixel < 8 ) {
562 switch(dst->format->BitsPerPixel) {
564 return SDL_FillRect1(dst, dstrect, color);
567 return SDL_FillRect4(dst, dstrect, color);
570 SDL_SetError("Fill rect on unsupported surface format");
576 /* If 'dstrect' == NULL, then fill the whole surface */
578 /* Perform clipping */
579 if ( !SDL_IntersectRect(dstrect, &dst->clip_rect, dstrect) ) {
583 dstrect = &dst->clip_rect;
586 /* Check for hardware acceleration */
587 if ( ((dst->flags & SDL_HWSURFACE) == SDL_HWSURFACE) &&
588 video->info.blit_fill ) {
590 if ( dst == SDL_VideoSurface ) {
592 hw_rect.x += current_video->offset_x;
593 hw_rect.y += current_video->offset_y;
596 return(video->FillHWRect(this, dst, dstrect, color));
599 /* Perform software fill */
600 if ( SDL_LockSurface(dst) != 0 ) {
603 row = (Uint8 *)dst->pixels+dstrect->y*dst->pitch+
604 dstrect->x*dst->format->BytesPerPixel;
605 if ( dst->format->palette || (color == 0) ) {
606 x = dstrect->w*dst->format->BytesPerPixel;
607 if ( !color && !((uintptr_t)row&3) && !(x&3) && !(dst->pitch&3) ) {
609 for ( y=dstrect->h; y; --y ) {
610 SDL_memset4(row, 0, n);
616 * SDL_memset() on PPC (both glibc and codewarrior) uses
617 * the dcbz (Data Cache Block Zero) instruction, which
618 * causes an alignment exception if the destination is
619 * uncachable, so only use it on software surfaces
621 if((dst->flags & SDL_HWSURFACE) == SDL_HWSURFACE) {
622 if(dstrect->w >= 8) {
624 * 64-bit stores are probably most
625 * efficient to uncached video memory
628 SDL_memset(&fill, color, (sizeof fill));
629 for(y = dstrect->h; y; y--) {
635 while((unsigned long)d
636 & (sizeof(double) - 1)) {
640 nn = n / (sizeof(double) * 4);
642 ((double *)d)[0] = f;
643 ((double *)d)[1] = f;
644 ((double *)d)[2] = f;
645 ((double *)d)[3] = f;
646 d += 4*sizeof(double);
649 n &= ~(sizeof(double) * 4 - 1);
650 nn = n / sizeof(double);
656 n &= ~(sizeof(double) - 1);
665 for(y = dstrect->h; y; y--) {
677 #endif /* __powerpc__ */
679 for(y = dstrect->h; y; y--) {
680 SDL_memset(row, color, x);
686 switch (dst->format->BytesPerPixel) {
688 for ( y=dstrect->h; y; --y ) {
689 Uint16 *pixels = (Uint16 *)row;
690 Uint16 c = (Uint16)color;
691 Uint32 cc = (Uint32)c << 16 | c;
693 if((uintptr_t)pixels & 3) {
698 SDL_memset4(pixels, cc, n >> 1);
706 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
709 for ( y=dstrect->h; y; --y ) {
711 for ( x=dstrect->w; x; --x ) {
712 SDL_memcpy(pixels, &color, 3);
720 for(y = dstrect->h; y; --y) {
721 SDL_memset4(row, color, dstrect->w);
727 SDL_UnlockSurface(dst);
734 * Lock a surface to directly access the pixels
736 int SDL_LockSurface (SDL_Surface *surface)
738 if ( ! surface->locked ) {
739 /* Perform the lock */
740 if ( surface->flags & (SDL_HWSURFACE|SDL_ASYNCBLIT) ) {
741 SDL_VideoDevice *video = current_video;
742 SDL_VideoDevice *this = current_video;
743 if ( video->LockHWSurface(this, surface) < 0 ) {
747 if ( surface->flags & SDL_RLEACCEL ) {
748 SDL_UnRLESurface(surface, 1);
749 surface->flags |= SDL_RLEACCEL; /* save accel'd state */
751 /* This needs to be done here in case pixels changes value */
752 surface->pixels = (Uint8 *)surface->pixels + surface->offset;
755 /* Increment the surface lock count, for recursive locks */
762 * Unlock a previously locked surface
764 void SDL_UnlockSurface (SDL_Surface *surface)
766 /* Only perform an unlock if we are locked */
767 if ( ! surface->locked || (--surface->locked > 0) ) {
771 /* Perform the unlock */
772 surface->pixels = (Uint8 *)surface->pixels - surface->offset;
774 /* Unlock hardware or accelerated surfaces */
775 if ( surface->flags & (SDL_HWSURFACE|SDL_ASYNCBLIT) ) {
776 SDL_VideoDevice *video = current_video;
777 SDL_VideoDevice *this = current_video;
778 video->UnlockHWSurface(this, surface);
780 /* Update RLE encoded surface with new data */
781 if ( (surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) {
782 surface->flags &= ~SDL_RLEACCEL; /* stop lying */
783 SDL_RLESurface(surface);
789 * Convert a surface into the specified pixel format.
791 SDL_Surface * SDL_ConvertSurface (SDL_Surface *surface,
792 SDL_PixelFormat *format, Uint32 flags)
794 SDL_Surface *convert;
797 Uint32 surface_flags;
800 /* Check for empty destination palette! (results in empty image) */
801 if ( format->palette != NULL ) {
803 for ( i=0; i<format->palette->ncolors; ++i ) {
804 if ( (format->palette->colors[i].r != 0) ||
805 (format->palette->colors[i].g != 0) ||
806 (format->palette->colors[i].b != 0) )
809 if ( i == format->palette->ncolors ) {
810 SDL_SetError("Empty destination palette");
815 /* Only create hw surfaces with alpha channel if hw alpha blits
817 if(format->Amask != 0 && (flags & SDL_HWSURFACE)) {
818 const SDL_VideoInfo *vi = SDL_GetVideoInfo();
819 if(!vi || !vi->blit_hw_A)
820 flags &= ~SDL_HWSURFACE;
823 /* Create a new surface with the desired format */
824 convert = SDL_CreateRGBSurface(flags,
825 surface->w, surface->h, format->BitsPerPixel,
826 format->Rmask, format->Gmask, format->Bmask, format->Amask);
827 if ( convert == NULL ) {
831 /* Copy the palette if any */
832 if ( format->palette && convert->format->palette ) {
833 SDL_memcpy(convert->format->palette->colors,
834 format->palette->colors,
835 format->palette->ncolors*sizeof(SDL_Color));
836 convert->format->palette->ncolors = format->palette->ncolors;
839 /* Save the original surface color key and alpha */
840 surface_flags = surface->flags;
841 if ( (surface_flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) {
842 /* Convert colourkeyed surfaces to RGBA if requested */
843 if((flags & SDL_SRCCOLORKEY) != SDL_SRCCOLORKEY
845 surface_flags &= ~SDL_SRCCOLORKEY;
847 colorkey = surface->format->colorkey;
848 SDL_SetColorKey(surface, 0, 0);
851 if ( (surface_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
852 /* Copy over the alpha channel to RGBA if requested */
853 if ( format->Amask ) {
854 surface->flags &= ~SDL_SRCALPHA;
856 alpha = surface->format->alpha;
857 SDL_SetAlpha(surface, 0, 0);
861 /* Copy over the image data */
864 bounds.w = surface->w;
865 bounds.h = surface->h;
866 SDL_LowerBlit(surface, &bounds, convert, &bounds);
868 /* Clean up the original surface, and update converted surface */
869 if ( convert != NULL ) {
870 SDL_SetClipRect(convert, &surface->clip_rect);
872 if ( (surface_flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) {
873 Uint32 cflags = surface_flags&(SDL_SRCCOLORKEY|SDL_RLEACCELOK);
874 if ( convert != NULL ) {
875 Uint8 keyR, keyG, keyB;
877 SDL_GetRGB(colorkey,surface->format,&keyR,&keyG,&keyB);
878 SDL_SetColorKey(convert, cflags|(flags&SDL_RLEACCELOK),
879 SDL_MapRGB(convert->format, keyR, keyG, keyB));
881 SDL_SetColorKey(surface, cflags, colorkey);
883 if ( (surface_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
884 Uint32 aflags = surface_flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
885 if ( convert != NULL ) {
886 SDL_SetAlpha(convert, aflags|(flags&SDL_RLEACCELOK),
889 if ( format->Amask ) {
890 surface->flags |= SDL_SRCALPHA;
892 SDL_SetAlpha(surface, aflags, alpha);
896 /* We're ready to go! */
901 * Free a surface created by the above function.
903 void SDL_FreeSurface (SDL_Surface *surface)
905 /* Free anything that's not NULL, and not the screen surface */
906 if ((surface == NULL) ||
908 ((surface == SDL_ShadowSurface)||(surface == SDL_VideoSurface)))) {
911 if ( --surface->refcount > 0 ) {
914 while ( surface->locked > 0 ) {
915 SDL_UnlockSurface(surface);
917 if ( (surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) {
918 SDL_UnRLESurface(surface, 0);
920 if ( surface->format ) {
921 SDL_FreeFormat(surface->format);
922 surface->format = NULL;
924 if ( surface->map != NULL ) {
925 SDL_FreeBlitMap(surface->map);
928 if ( surface->hwdata ) {
929 SDL_VideoDevice *video = current_video;
930 SDL_VideoDevice *this = current_video;
931 video->FreeHWSurface(this, surface);
933 if ( surface->pixels &&
934 ((surface->flags & SDL_PREALLOC) != SDL_PREALLOC) ) {
935 SDL_free(surface->pixels);
939 --surfaces_allocated;