comparison src/video/dummy/SDL_nullrender.c @ 1908:e079dafea2bf

Implemented fully featured dummy renderer
author Sam Lantinga <slouken@libsdl.org>
date Sat, 15 Jul 2006 19:29:42 +0000
parents 06c27a737b7a
children 8d384b647307
comparison
equal deleted inserted replaced
1907:06c27a737b7a 1908:e079dafea2bf
21 */ 21 */
22 #include "SDL_config.h" 22 #include "SDL_config.h"
23 23
24 #include "SDL_video.h" 24 #include "SDL_video.h"
25 #include "../SDL_sysvideo.h" 25 #include "../SDL_sysvideo.h"
26 #include "../SDL_yuv_sw_c.h"
26 27
27 28
28 /* SDL surface based renderer implementation */ 29 /* SDL surface based renderer implementation */
29 30
30 static SDL_Renderer *SDL_DUMMY_CreateRenderer(SDL_Window * window, 31 static SDL_Renderer *SDL_DUMMY_CreateRenderer(SDL_Window * window, Uint32 flags);
31 Uint32 flags);
32 static int SDL_DUMMY_CreateTexture(SDL_Renderer * renderer, 32 static int SDL_DUMMY_CreateTexture(SDL_Renderer * renderer,
33 SDL_Texture * texture); 33 SDL_Texture * texture);
34 static int SDL_DUMMY_QueryTexturePixels(SDL_Renderer * renderer,
35 SDL_Texture * texture, void **pixels,
36 int *pitch);
37 static int SDL_DUMMY_SetTexturePalette(SDL_Renderer * renderer,
38 SDL_Texture * texture,
39 const SDL_Color * colors, int firstcolor,
40 int ncolors);
41 static int SDL_DUMMY_GetTexturePalette(SDL_Renderer * renderer,
42 SDL_Texture * texture, SDL_Color * colors,
43 int firstcolor, int ncolors);
44 static int SDL_DUMMY_UpdateTexture(SDL_Renderer * renderer,
45 SDL_Texture * texture, const SDL_Rect * rect,
46 const void *pixels, int pitch);
47 static int SDL_DUMMY_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
48 const SDL_Rect * rect, int markDirty,
49 void **pixels, int *pitch);
50 static void SDL_DUMMY_UnlockTexture(SDL_Renderer * renderer,
51 SDL_Texture * texture);
52 static void SDL_DUMMY_DirtyTexture(SDL_Renderer * renderer,
53 SDL_Texture * texture, int numrects,
54 const SDL_Rect * rects);
55 static void SDL_DUMMY_SelectRenderTexture(SDL_Renderer * renderer,
56 SDL_Texture * texture);
57 static int SDL_DUMMY_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect,
58 Uint32 color);
59 static int SDL_DUMMY_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
60 const SDL_Rect * srcrect,
61 const SDL_Rect * dstrect, int blendMode,
62 int scaleMode);
63 static int SDL_DUMMY_RenderReadPixels(SDL_Renderer * renderer,
64 const SDL_Rect * rect, void *pixels,
65 int pitch);
66 static int SDL_DUMMY_RenderWritePixels(SDL_Renderer * renderer,
67 const SDL_Rect * rect, const void *pixels,
68 int pitch);
34 static void SDL_DUMMY_RenderPresent(SDL_Renderer * renderer); 69 static void SDL_DUMMY_RenderPresent(SDL_Renderer * renderer);
70 static void SDL_DUMMY_DestroyTexture(SDL_Renderer * renderer,
71 SDL_Texture * texture);
35 static void SDL_DUMMY_DestroyRenderer(SDL_Renderer * renderer); 72 static void SDL_DUMMY_DestroyRenderer(SDL_Renderer * renderer);
36 73
37 74
38 SDL_RenderDriver SDL_DUMMY_RenderDriver = { 75 SDL_RenderDriver SDL_DUMMY_RenderDriver = {
39 SDL_DUMMY_CreateRenderer, 76 SDL_DUMMY_CreateRenderer,
40 { 77 {
41 "dummy", 78 "dummy",
42 (SDL_Renderer_PresentDiscard | SDL_Renderer_PresentCopy), 79 (SDL_Renderer_SingleBuffer | SDL_Renderer_PresentCopy |
43 SDL_TextureBlendMode_None, 80 SDL_Renderer_PresentFlip2 | SDL_Renderer_PresentFlip3 |
44 SDL_TextureScaleMode_None, 81 SDL_Renderer_PresentDiscard),
45 0, 82 (SDL_TextureBlendMode_None | SDL_TextureBlendMode_Mask |
46 {0}, 83 SDL_TextureBlendMode_Blend),
84 (SDL_TextureScaleMode_None | SDL_TextureScaleMode_Fast),
85 11,
86 {
87 SDL_PixelFormat_Index8,
88 SDL_PixelFormat_RGB555,
89 SDL_PixelFormat_RGB565,
90 SDL_PixelFormat_RGB888,
91 SDL_PixelFormat_BGR888,
92 SDL_PixelFormat_ARGB8888,
93 SDL_PixelFormat_RGBA8888,
94 SDL_PixelFormat_ABGR8888,
95 SDL_PixelFormat_BGRA8888,
96 SDL_PixelFormat_YUY2,
97 SDL_PixelFormat_UYVY},
47 0, 98 0,
48 0} 99 0}
49 }; 100 };
50 101
51 typedef struct 102 typedef struct
52 { 103 {
53 SDL_Surface *surface; 104 int current_screen;
105 SDL_Surface *screens[3];
54 } SDL_DUMMY_RenderData; 106 } SDL_DUMMY_RenderData;
55 107
56 SDL_Renderer * 108 SDL_Renderer *
57 SDL_DUMMY_CreateRenderer(SDL_Window * window, Uint32 flags) 109 SDL_DUMMY_CreateRenderer(SDL_Window * window, Uint32 flags)
58 { 110 {
59 SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window); 111 SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
60 SDL_DisplayMode *displayMode = &display->current_mode; 112 SDL_DisplayMode *displayMode = &display->current_mode;
61 SDL_Renderer *renderer; 113 SDL_Renderer *renderer;
62 SDL_DUMMY_RenderData *data; 114 SDL_DUMMY_RenderData *data;
115 int i, n;
63 int bpp; 116 int bpp;
64 Uint32 Rmask, Gmask, Bmask, Amask; 117 Uint32 Rmask, Gmask, Bmask, Amask;
65 118
66 if (!SDL_PixelFormatEnumToMasks 119 if (!SDL_PixelFormatEnumToMasks
67 (displayMode->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) { 120 (displayMode->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
68 SDL_SetError("Unknown display format"); 121 SDL_SetError("Unknown display format");
69 return NULL; 122 return NULL;
70 } 123 }
71 124
72 renderer = (SDL_Renderer *) SDL_malloc(sizeof(*renderer)); 125 renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
73 if (!renderer) { 126 if (!renderer) {
74 SDL_OutOfMemory(); 127 SDL_OutOfMemory();
75 return NULL; 128 return NULL;
76 } 129 }
77 SDL_zerop(renderer);
78 130
79 data = (SDL_DUMMY_RenderData *) SDL_malloc(sizeof(*data)); 131 data = (SDL_DUMMY_RenderData *) SDL_malloc(sizeof(*data));
80 if (!data) { 132 if (!data) {
81 SDL_DUMMY_DestroyRenderer(renderer); 133 SDL_DUMMY_DestroyRenderer(renderer);
82 SDL_OutOfMemory(); 134 SDL_OutOfMemory();
83 return NULL; 135 return NULL;
84 } 136 }
85 SDL_zerop(data); 137 SDL_zerop(data);
86 138
139 renderer->CreateTexture = SDL_DUMMY_CreateTexture;
140 renderer->QueryTexturePixels = SDL_DUMMY_QueryTexturePixels;
141 renderer->SetTexturePalette = SDL_DUMMY_SetTexturePalette;
142 renderer->GetTexturePalette = SDL_DUMMY_GetTexturePalette;
143 renderer->UpdateTexture = SDL_DUMMY_UpdateTexture;
144 renderer->LockTexture = SDL_DUMMY_LockTexture;
145 renderer->UnlockTexture = SDL_DUMMY_UnlockTexture;
146 renderer->DirtyTexture = SDL_DUMMY_DirtyTexture;
147 renderer->RenderFill = SDL_DUMMY_RenderFill;
148 renderer->RenderCopy = SDL_DUMMY_RenderCopy;
87 renderer->RenderPresent = SDL_DUMMY_RenderPresent; 149 renderer->RenderPresent = SDL_DUMMY_RenderPresent;
150 renderer->DestroyTexture = SDL_DUMMY_DestroyTexture;
88 renderer->DestroyRenderer = SDL_DUMMY_DestroyRenderer; 151 renderer->DestroyRenderer = SDL_DUMMY_DestroyRenderer;
89 renderer->info = SDL_DUMMY_RenderDriver.info; 152 renderer->info = SDL_DUMMY_RenderDriver.info;
90 renderer->window = window->id; 153 renderer->window = window->id;
91 renderer->driverdata = data; 154 renderer->driverdata = data;
92 155
93 data->surface = 156 renderer->info.flags = 0;
94 SDL_CreateRGBSurface(0, window->w, window->h, bpp, Rmask, Gmask, 157
95 Bmask, Amask); 158 if (flags & SDL_Renderer_PresentFlip2) {
96 if (!data->surface) { 159 renderer->info.flags |= SDL_Renderer_PresentFlip2;
97 SDL_DUMMY_DestroyRenderer(renderer); 160 n = 2;
98 return NULL; 161 } else if (flags & SDL_Renderer_PresentFlip3) {
99 } 162 renderer->info.flags |= SDL_Renderer_PresentFlip3;
100 SDL_SetSurfacePalette(data->surface, display->palette); 163 n = 3;
164 } else {
165 renderer->info.flags |= SDL_Renderer_PresentCopy;
166 n = 1;
167 }
168 for (i = 0; i < n; ++i) {
169 data->screens[i] =
170 SDL_CreateRGBSurface(0, window->w, window->h, bpp, Rmask, Gmask,
171 Bmask, Amask);
172 if (!data->screens[i]) {
173 SDL_DUMMY_DestroyRenderer(renderer);
174 return NULL;
175 }
176 SDL_SetSurfacePalette(data->screens[i], display->palette);
177 }
178 data->current_screen = 0;
101 179
102 return renderer; 180 return renderer;
103 } 181 }
104 182
105 void 183 static int
184 SDL_DUMMY_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
185 {
186 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
187 texture->driverdata = SDL_SW_CreateYUVTexture(texture);
188 } else {
189 int bpp;
190 Uint32 Rmask, Gmask, Bmask, Amask;
191
192 if (!SDL_PixelFormatEnumToMasks
193 (texture->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
194 SDL_SetError("Unknown texture format");
195 return -1;
196 }
197
198 texture->driverdata = SDL_CreateRGBSurface(0, texture->w, texture->h, bpp, Rmask, Gmask, Bmask, Amask);
199 }
200
201 if (!texture->driverdata) {
202 return -1;
203 }
204 return 0;
205 }
206
207 static int
208 SDL_DUMMY_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture,
209 void **pixels, int *pitch)
210 {
211 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
212 return SDL_SW_QueryYUVTexturePixels((SDL_SW_YUVTexture *) texture->driverdata, pixels, pitch);
213 } else {
214 SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
215
216 *pixels = surface->pixels;
217 *pitch = surface->pitch;
218 return 0;
219 }
220 }
221
222 static int
223 SDL_DUMMY_SetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
224 const SDL_Color * colors, int firstcolor,
225 int ncolors)
226 {
227 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
228 SDL_SetError("YUV textures don't have a palette");
229 return -1;
230 } else {
231 SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
232
233 return SDL_SetPaletteColors(surface->format->palette, colors,
234 firstcolor, ncolors);
235 }
236 }
237
238 static int
239 SDL_DUMMY_GetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
240 SDL_Color * colors, int firstcolor, int ncolors)
241 {
242 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
243 SDL_SetError("YUV textures don't have a palette");
244 return -1;
245 } else {
246 SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
247
248 SDL_memcpy(colors, &surface->format->palette->colors[firstcolor],
249 ncolors * sizeof(*colors));
250 return 0;
251 }
252 }
253
254 static int
255 SDL_DUMMY_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
256 const SDL_Rect * rect, const void *pixels, int pitch)
257 {
258 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
259 return SDL_SW_UpdateYUVTexture((SDL_SW_YUVTexture *) texture->
260 driverdata, rect, pixels, pitch);
261 } else {
262 SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
263 Uint8 *src, *dst;
264 int row;
265 size_t length;
266
267 src = (Uint8 *) pixels;
268 dst =
269 (Uint8 *) surface->pixels + rect->y * surface->pitch +
270 rect->x * surface->format->BytesPerPixel;
271 length = rect->w * surface->format->BytesPerPixel;
272 for (row = 0; row < rect->h; ++row) {
273 SDL_memcpy(dst, src, length);
274 src += pitch;
275 dst += surface->pitch;
276 }
277 return 0;
278 }
279 }
280
281 static int
282 SDL_DUMMY_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
283 const SDL_Rect * rect, int markDirty, void **pixels,
284 int *pitch)
285 {
286 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
287 return SDL_SW_LockYUVTexture((SDL_SW_YUVTexture *) texture->
288 driverdata, rect, markDirty, pixels,
289 pitch);
290 } else {
291 SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
292
293 *pixels =
294 (void *) ((Uint8 *) surface->pixels + rect->y * surface->pitch +
295 rect->x * surface->format->BytesPerPixel);
296 *pitch = surface->pitch;
297 return 0;
298 }
299 }
300
301 static void
302 SDL_DUMMY_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
303 {
304 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
305 SDL_SW_UnlockYUVTexture((SDL_SW_YUVTexture *) texture->driverdata);
306 }
307 }
308
309 static void
310 SDL_DUMMY_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
311 int numrects, const SDL_Rect * rects)
312 {
313 }
314
315 static int
316 SDL_DUMMY_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect,
317 Uint32 color)
318 {
319 SDL_DUMMY_RenderData *data = (SDL_DUMMY_RenderData *) renderer->driverdata;
320 SDL_Surface *target = data->screens[data->current_screen];
321 SDL_Rect real_rect = *rect;
322 Uint8 r, g, b, a;
323
324 a = (Uint8) ((color >> 24) & 0xFF);
325 r = (Uint8) ((color >> 16) & 0xFF);
326 g = (Uint8) ((color >> 8) & 0xFF);
327 b = (Uint8) (color & 0xFF);
328 color = SDL_MapRGBA(target->format, r, g, b, a);
329
330 return SDL_FillRect(target, &real_rect, color);
331 }
332
333 static int
334 SDL_DUMMY_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
335 const SDL_Rect * srcrect, const SDL_Rect * dstrect,
336 int blendMode, int scaleMode)
337 {
338 SDL_DUMMY_RenderData *data = (SDL_DUMMY_RenderData *) renderer->driverdata;
339 SDL_Window *window = SDL_GetWindowFromID(renderer->window);
340 SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
341
342 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
343 SDL_Surface *target = data->screens[data->current_screen];
344 void *pixels =
345 (Uint8 *) target->pixels + dstrect->y * target->pitch +
346 dstrect->x * target->format->BytesPerPixel;
347 return SDL_SW_CopyYUVToRGB((SDL_SW_YUVTexture *) texture->driverdata,
348 srcrect, display->current_mode.format,
349 dstrect->w, dstrect->h, pixels,
350 target->pitch);
351 } else {
352 SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
353 SDL_Surface *target = data->screens[data->current_screen];
354 SDL_Rect real_srcrect = *srcrect;
355 SDL_Rect real_dstrect = *dstrect;
356
357 if (blendMode &
358 (SDL_TextureBlendMode_Mask | SDL_TextureBlendMode_Blend)) {
359 SDL_SetAlpha(surface, SDL_SRCALPHA, 0);
360 } else {
361 SDL_SetAlpha(surface, 0, 0);
362 }
363 if (scaleMode != SDL_TextureScaleMode_None &&
364 (srcrect->w != dstrect->w || srcrect->h != dstrect->h)) {
365 return SDL_SoftStretch(surface, &real_srcrect, target, &real_dstrect);
366 } else {
367 return SDL_LowerBlit(surface, &real_srcrect, target, &real_dstrect);
368 }
369 }
370 }
371
372 static void
106 SDL_DUMMY_RenderPresent(SDL_Renderer * renderer) 373 SDL_DUMMY_RenderPresent(SDL_Renderer * renderer)
107 { 374 {
108 static int frame_number; 375 static int frame_number;
109 SDL_DUMMY_RenderData *data = 376 SDL_DUMMY_RenderData *data = (SDL_DUMMY_RenderData *) renderer->driverdata;
110 (SDL_DUMMY_RenderData *) renderer->driverdata; 377
111 SDL_Surface *surface = data->surface; 378 /* Send the data to the display */
112
113 if (SDL_getenv("SDL_VIDEO_DUMMY_SAVE_FRAMES")) { 379 if (SDL_getenv("SDL_VIDEO_DUMMY_SAVE_FRAMES")) {
114 char file[128]; 380 char file[128];
115 SDL_snprintf(file, sizeof(file), "SDL_window%d-%8.8d.bmp", 381 SDL_snprintf(file, sizeof(file), "SDL_window%d-%8.8d.bmp",
116 renderer->window, ++frame_number); 382 renderer->window, ++frame_number);
117 SDL_SaveBMP(surface, file); 383 SDL_SaveBMP(data->screens[data->current_screen], file);
118 } 384 }
119 } 385
120 386 /* Update the flipping chain, if any */
121 void 387 if (renderer->info.flags & SDL_Renderer_PresentFlip2) {
388 data->current_screen = (data->current_screen + 1) % 2;
389 } else if (renderer->info.flags & SDL_Renderer_PresentFlip3) {
390 data->current_screen = (data->current_screen + 1) % 3;
391 }
392 }
393
394 static void
395 SDL_DUMMY_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
396 {
397 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
398 SDL_SW_DestroyYUVTexture((SDL_SW_YUVTexture *) texture->driverdata);
399 } else {
400 SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
401
402 SDL_FreeSurface(surface);
403 }
404 }
405
406 static void
122 SDL_DUMMY_DestroyRenderer(SDL_Renderer * renderer) 407 SDL_DUMMY_DestroyRenderer(SDL_Renderer * renderer)
123 { 408 {
124 SDL_DUMMY_RenderData *data = 409 SDL_DUMMY_RenderData *data = (SDL_DUMMY_RenderData *) renderer->driverdata;
125 (SDL_DUMMY_RenderData *) renderer->driverdata; 410 int i;
126 411
127 if (data) { 412 if (data) {
128 if (data->surface) { 413 for (i = 0; i < SDL_arraysize(data->screens); ++i) {
129 data->surface->format->palette = NULL; 414 if (data->screens[i]) {
130 SDL_FreeSurface(data->surface); 415 SDL_FreeSurface(data->screens[i]);
416 }
131 } 417 }
132 SDL_free(data); 418 SDL_free(data);
133 } 419 }
134 SDL_free(renderer); 420 SDL_free(renderer);
135 } 421 }