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 }