Mercurial > sdl-ios-xcode
comparison src/video/SDL_surface.c @ 1683:396a35389351 SDL-1.3
Finished palettized display handling.
Added support for surface palette sharing.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sat, 17 Jun 2006 06:45:14 +0000 |
parents | 7ae8018b2e5d |
children | a1ebb17f9c52 |
comparison
equal
deleted
inserted
replaced
1682:7ae8018b2e5d | 1683:396a35389351 |
---|---|
45 /* FIXME!! */ | 45 /* FIXME!! */ |
46 /* Make sure the size requested doesn't overflow our datatypes */ | 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. :) */ | 47 /* Next time I write a library like SDL, I'll use int for size. :) */ |
48 if (width >= 16384 || height >= 65536) { | 48 if (width >= 16384 || height >= 65536) { |
49 SDL_SetError("Width or height is too large"); | 49 SDL_SetError("Width or height is too large"); |
50 return (NULL); | 50 return NULL; |
51 } | 51 } |
52 | 52 |
53 /* Allocate the surface */ | 53 /* Allocate the surface */ |
54 surface = (SDL_Surface *) SDL_malloc(sizeof(*surface)); | 54 surface = (SDL_Surface *) SDL_malloc(sizeof(*surface)); |
55 if (surface == NULL) { | 55 if (surface == NULL) { |
56 SDL_OutOfMemory(); | 56 SDL_OutOfMemory(); |
57 return (NULL); | 57 return NULL; |
58 } | 58 } |
59 surface->flags = 0; | 59 SDL_zerop(surface); |
60 | |
60 surface->format = SDL_AllocFormat(depth, Rmask, Gmask, Bmask, Amask); | 61 surface->format = SDL_AllocFormat(depth, Rmask, Gmask, Bmask, Amask); |
61 if (surface->format == NULL) { | 62 if (!surface->format) { |
62 SDL_free(surface); | 63 SDL_FreeSurface(surface); |
63 return (NULL); | 64 return NULL; |
64 } | 65 } |
65 if (Amask) { | 66 if (Amask) { |
66 surface->flags |= SDL_SRCALPHA; | 67 surface->flags |= SDL_SRCALPHA; |
67 } | 68 } |
68 surface->w = width; | 69 surface->w = width; |
69 surface->h = height; | 70 surface->h = height; |
70 surface->pitch = SDL_CalculatePitch(surface); | 71 surface->pitch = SDL_CalculatePitch(surface); |
71 surface->pixels = NULL; | |
72 surface->locked = 0; | |
73 surface->map = NULL; | |
74 SDL_SetClipRect(surface, NULL); | 72 SDL_SetClipRect(surface, NULL); |
75 SDL_FormatChanged(surface); | 73 |
74 if (surface->format->BitsPerPixel <= 8) { | |
75 SDL_Palette *palette = | |
76 SDL_AllocPalette((1 << surface->format->BitsPerPixel)); | |
77 if (!palette) { | |
78 SDL_FreeSurface(surface); | |
79 return NULL; | |
80 } | |
81 if (Rmask || Bmask || Gmask) { | |
82 const SDL_PixelFormat *format = surface->format; | |
83 | |
84 /* create palette according to masks */ | |
85 int i; | |
86 int Rm = 0, Gm = 0, Bm = 0; | |
87 int Rw = 0, Gw = 0, Bw = 0; | |
88 | |
89 if (Rmask) { | |
90 Rw = 8 - format->Rloss; | |
91 for (i = format->Rloss; i > 0; i -= Rw) | |
92 Rm |= 1 << i; | |
93 } | |
94 if (Gmask) { | |
95 Gw = 8 - format->Gloss; | |
96 for (i = format->Gloss; i > 0; i -= Gw) | |
97 Gm |= 1 << i; | |
98 } | |
99 if (Bmask) { | |
100 Bw = 8 - format->Bloss; | |
101 for (i = format->Bloss; i > 0; i -= Bw) | |
102 Bm |= 1 << i; | |
103 } | |
104 for (i = 0; i < palette->ncolors; ++i) { | |
105 int r, g, b; | |
106 r = (i & Rmask) >> format->Rshift; | |
107 r = (r << format->Rloss) | ((r * Rm) >> Rw); | |
108 palette->colors[i].r = r; | |
109 | |
110 g = (i & Gmask) >> format->Gshift; | |
111 g = (g << format->Gloss) | ((g * Gm) >> Gw); | |
112 palette->colors[i].g = g; | |
113 | |
114 b = (i & Bmask) >> format->Bshift; | |
115 b = (b << format->Bloss) | ((b * Bm) >> Bw); | |
116 palette->colors[i].b = b; | |
117 } | |
118 } else if (palette->ncolors == 2) { | |
119 /* Create a black and white bitmap palette */ | |
120 palette->colors[0].r = 0xFF; | |
121 palette->colors[0].g = 0xFF; | |
122 palette->colors[0].b = 0xFF; | |
123 palette->colors[1].r = 0x00; | |
124 palette->colors[1].g = 0x00; | |
125 palette->colors[1].b = 0x00; | |
126 } | |
127 SDL_SetSurfacePalette(surface, palette); | |
128 SDL_FreePalette(palette); | |
129 } | |
76 | 130 |
77 /* Get the pixels */ | 131 /* Get the pixels */ |
78 if (surface->w && surface->h) { | 132 if (surface->w && surface->h) { |
79 surface->pixels = SDL_malloc(surface->h * surface->pitch); | 133 surface->pixels = SDL_malloc(surface->h * surface->pitch); |
80 if (surface->pixels == NULL) { | 134 if (!surface->pixels) { |
81 SDL_FreeSurface(surface); | 135 SDL_FreeSurface(surface); |
82 SDL_OutOfMemory(); | 136 SDL_OutOfMemory(); |
83 return NULL; | 137 return NULL; |
84 } | 138 } |
85 /* This is important for bitmaps */ | 139 /* This is important for bitmaps */ |
86 SDL_memset(surface->pixels, 0, surface->h * surface->pitch); | 140 SDL_memset(surface->pixels, 0, surface->h * surface->pitch); |
87 } | 141 } |
88 | 142 |
89 /* Allocate an empty mapping */ | 143 /* Allocate an empty mapping */ |
90 surface->map = SDL_AllocBlitMap(); | 144 surface->map = SDL_AllocBlitMap(); |
91 if (surface->map == NULL) { | 145 if (!surface->map) { |
92 SDL_FreeSurface(surface); | 146 SDL_FreeSurface(surface); |
93 return (NULL); | 147 return NULL; |
94 } | 148 } |
149 SDL_FormatChanged(surface); | |
95 | 150 |
96 /* The surface is ready to go */ | 151 /* The surface is ready to go */ |
97 surface->refcount = 1; | 152 surface->refcount = 1; |
98 #ifdef CHECK_LEAKS | 153 #ifdef CHECK_LEAKS |
99 ++surfaces_allocated; | 154 ++surfaces_allocated; |
100 #endif | 155 #endif |
101 return (surface); | 156 return surface; |
102 } | 157 } |
103 | 158 |
104 /* | 159 /* |
105 * Create an RGB surface from an existing memory buffer | 160 * Create an RGB surface from an existing memory buffer |
106 */ | 161 */ |
155 SDL_CreateRGBSurface(0, 0, 0, bpp, Rmask, Gmask, Bmask, Amask); | 210 SDL_CreateRGBSurface(0, 0, 0, bpp, Rmask, Gmask, Bmask, Amask); |
156 if (surface) { | 211 if (surface) { |
157 surface->flags |= SDL_HWSURFACE; | 212 surface->flags |= SDL_HWSURFACE; |
158 surface->w = w; | 213 surface->w = w; |
159 surface->h = h; | 214 surface->h = h; |
160 surface->lock_data = (void *) textureID; | |
161 SDL_SetClipRect(surface, NULL); | 215 SDL_SetClipRect(surface, NULL); |
162 } | 216 } |
163 } | 217 } |
218 if (surface) { | |
219 surface->textureID = textureID; | |
220 } | |
164 | 221 |
165 return surface; | 222 return surface; |
166 } | 223 } |
167 | 224 |
168 /* | 225 static int |
169 * Set the palette in a blittable surface | 226 SDL_SurfacePaletteChanged(void *userdata, SDL_Palette * palette) |
170 */ | 227 { |
228 SDL_Surface *surface = (SDL_Surface *) userdata; | |
229 | |
230 if (surface->textureID) { | |
231 if (SDL_SetTexturePalette | |
232 (surface->textureID, palette->colors, 0, palette->ncolors) < 0) { | |
233 SDL_GetTexturePalette(surface->textureID, palette->colors, 0, | |
234 palette->ncolors); | |
235 return -1; | |
236 } | |
237 } | |
238 SDL_FormatChanged(surface); | |
239 | |
240 return 0; | |
241 } | |
242 | |
171 int | 243 int |
172 SDL_SetColors(SDL_Surface * surface, const SDL_Color * colors, int firstcolor, | 244 SDL_SetSurfacePalette(SDL_Surface * surface, SDL_Palette * palette) |
173 int ncolors) | 245 { |
174 { | 246 if (!surface || !surface->format) { |
175 SDL_Palette *pal; | 247 SDL_SetError("SDL_SetSurfacePalette() passed a NULL surface"); |
176 int gotall; | 248 return -1; |
177 int palsize; | 249 } |
178 | 250 |
179 /* Verify the parameters */ | 251 if (palette && palette->ncolors != (1 << surface->format->BitsPerPixel)) { |
180 pal = surface->format->palette; | 252 SDL_SetError |
181 if (!pal) { | 253 ("SDL_SetSurfacePalette() passed a palette that doesn't match the surface format"); |
182 return 0; /* not a palettized surface */ | 254 return -1; |
183 } | 255 } |
184 gotall = 1; | 256 |
185 palsize = 1 << surface->format->BitsPerPixel; | 257 if (surface->format->palette == palette) { |
186 if (ncolors > (palsize - firstcolor)) { | 258 return 0; |
187 ncolors = (palsize - firstcolor); | 259 } |
188 gotall = 0; | 260 |
189 } | 261 if (surface->format->palette) { |
190 | 262 SDL_DelPaletteWatch(surface->format->palette, |
191 if (colors != (pal->colors + firstcolor)) { | 263 SDL_SurfacePaletteChanged, surface); |
192 SDL_memcpy(pal->colors + firstcolor, colors, | 264 } |
193 ncolors * sizeof(*colors)); | 265 |
194 } | 266 surface->format->palette = palette; |
195 SDL_FormatChanged(surface); | 267 |
196 | 268 if (surface->format->palette) { |
197 if (surface->flags & (SDL_SHADOW_SURFACE | SDL_SCREEN_SURFACE)) { | 269 SDL_AddPaletteWatch(surface->format->palette, |
198 gotall &= SDL_SetScreenColors(surface, colors, firstcolor, ncolors); | 270 SDL_SurfacePaletteChanged, surface); |
199 } | 271 } |
200 return gotall; | 272 return 0; |
201 } | 273 } |
202 | 274 |
203 /* | 275 /* |
204 * Set the color key in a blittable surface | 276 * Set the color key in a blittable surface |
205 */ | 277 */ |
727 { | 799 { |
728 if (!surface->locked) { | 800 if (!surface->locked) { |
729 /* Perform the lock */ | 801 /* Perform the lock */ |
730 if (surface->flags & SDL_HWSURFACE) { | 802 if (surface->flags & SDL_HWSURFACE) { |
731 if (SDL_LockTexture | 803 if (SDL_LockTexture |
732 ((SDL_TextureID) surface->lock_data, NULL, 1, | 804 (surface->textureID, NULL, 1, &surface->pixels, |
733 &surface->pixels, &surface->pitch) < 0) { | 805 &surface->pitch) < 0) { |
734 return (-1); | 806 return (-1); |
735 } | 807 } |
736 } | 808 } |
737 if (surface->flags & SDL_RLEACCEL) { | 809 if (surface->flags & SDL_RLEACCEL) { |
738 SDL_UnRLESurface(surface, 1); | 810 SDL_UnRLESurface(surface, 1); |
758 return; | 830 return; |
759 } | 831 } |
760 | 832 |
761 /* Unlock hardware or accelerated surfaces */ | 833 /* Unlock hardware or accelerated surfaces */ |
762 if (surface->flags & SDL_HWSURFACE) { | 834 if (surface->flags & SDL_HWSURFACE) { |
763 SDL_UnlockTexture((SDL_TextureID) surface->lock_data); | 835 SDL_UnlockTexture(surface->textureID); |
764 } else { | 836 } |
765 /* Update RLE encoded surface with new data */ | 837 |
766 if ((surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL) { | 838 /* Update RLE encoded surface with new data */ |
767 surface->flags &= ~SDL_RLEACCEL; /* stop lying */ | 839 if ((surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL) { |
768 SDL_RLESurface(surface); | 840 surface->flags &= ~SDL_RLEACCEL; /* stop lying */ |
769 } | 841 SDL_RLESurface(surface); |
770 } | 842 } |
771 } | 843 } |
772 | 844 |
773 /* | 845 /* |
774 * Convert a surface into the specified pixel format. | 846 * Convert a surface into the specified pixel format. |
892 } | 964 } |
893 if (surface->flags & SDL_RLEACCEL) { | 965 if (surface->flags & SDL_RLEACCEL) { |
894 SDL_UnRLESurface(surface, 0); | 966 SDL_UnRLESurface(surface, 0); |
895 } | 967 } |
896 if (surface->format) { | 968 if (surface->format) { |
969 SDL_SetSurfacePalette(surface, NULL); | |
897 SDL_FreeFormat(surface->format); | 970 SDL_FreeFormat(surface->format); |
898 surface->format = NULL; | 971 surface->format = NULL; |
899 } | 972 } |
900 if (surface->map != NULL) { | 973 if (surface->map != NULL) { |
901 SDL_FreeBlitMap(surface->map); | 974 SDL_FreeBlitMap(surface->map); |
902 surface->map = NULL; | 975 surface->map = NULL; |
903 } | 976 } |
904 /* Should we destroy the texture too? | 977 /* Should we destroy the texture too? |
905 if (surface->flags & SDL_HWSURFACE) { | 978 if (surface->textureID) { |
906 SDL_DestroyTexture((SDL_TextureID)surface->lock_data); | 979 SDL_DestroyTexture(surface->textureID); |
907 } | 980 } |
908 */ | 981 */ |
909 if (surface->pixels && ((surface->flags & SDL_PREALLOC) != SDL_PREALLOC)) { | 982 if (surface->pixels && ((surface->flags & SDL_PREALLOC) != SDL_PREALLOC)) { |
910 SDL_free(surface->pixels); | 983 SDL_free(surface->pixels); |
911 } | 984 } |