Mercurial > sdl-ios-xcode
comparison src/video/nds/SDL_ndsrender.c @ 2679:bc3e3e889f6d gsoc2008_nds
More NDS video driver work.
author | Darren Alton <dalton@stevens.edu> |
---|---|
date | Sun, 13 Jul 2008 04:28:54 +0000 |
parents | 3895761db26a |
children | 4135aa9c5645 |
comparison
equal
deleted
inserted
replaced
2678:3895761db26a | 2679:bc3e3e889f6d |
---|---|
77 static void NDS_DestroyRenderer(SDL_Renderer * renderer); | 77 static void NDS_DestroyRenderer(SDL_Renderer * renderer); |
78 | 78 |
79 | 79 |
80 SDL_RenderDriver NDS_RenderDriver = { | 80 SDL_RenderDriver NDS_RenderDriver = { |
81 NDS_CreateRenderer, | 81 NDS_CreateRenderer, |
82 {"nds", SDL_RENDERER_SINGLEBUFFER} | 82 { "nds", /* char* name */ |
83 /*SDL_RENDERER_ values | 83 (SDL_RENDERER_SINGLEBUFFER|SDL_RENDERER_ACCELERATED), /* u32 flags */ |
84 SINGLEBUFFER Render directly to the window, if possible | 84 (SDL_TEXTUREMODULATE_NONE), /* u32 mod_modes */ |
85 PRESENTCOPY Present uses a copy from back buffer to the front buffer | 85 (SDL_TEXTUREBLENDMODE_NONE), /* u32 blend_modes */ |
86 PRESENTFLIP2 Present uses a flip, swapping back buffer and front buffer | 86 (SDL_TEXTURESCALEMODE_NONE), /* u32 scale_modes */ |
87 PRESENTFLIP3 Present uses a flip, rotating two back buf.s and a front buf. | 87 3, /* u32 num_texture_formats */ |
88 PRESENTDISCARD Present leaves the contents of the backbuffer undefined | 88 { |
89 PRESENTVSYNC Present is synchronized with the refresh rate | 89 SDL_PIXELFORMAT_INDEX8, |
90 ACCELERATED The renderer uses hardware acceleration | 90 SDL_PIXELFORMAT_RGB555, |
91 */ | 91 SDL_PIXELFORMAT_RGB565 |
92 }, /* u32 texture_formats[20] */ | |
93 (256), /* int max_texture_width */ | |
94 (256), /* int max_texture_height */ | |
95 } | |
92 }; | 96 }; |
93 | 97 |
94 typedef struct | 98 typedef struct |
95 { | 99 { |
96 int current_screen; | 100 bg_attribute *bg; |
97 u16* fb; | 101 u8 bg_taken[4]; |
102 int sub; | |
98 } NDS_RenderData; | 103 } NDS_RenderData; |
99 | 104 |
100 typedef struct | 105 typedef struct |
101 { | 106 { |
102 enum { NDSTX_BG, NDSTX_SPR } type; | 107 enum { NDSTX_BG, NDSTX_SPR } type; |
108 int hw_index; | |
103 struct { int w, h, pitch, bpp; } dim; | 109 struct { int w, h, pitch, bpp; } dim; |
104 u16 *vram; | 110 u16 *vram; |
105 } NDS_TextureData; | 111 } NDS_TextureData; |
106 | 112 |
107 | 113 |
115 /* hack to get the proper colors until I actually get BGR555 to work right */ | 121 /* hack to get the proper colors until I actually get BGR555 to work right */ |
116 u16 Rmask = 0x7C00, Bmask = 0x001F, GAmask = 0x83E0, r, b; | 122 u16 Rmask = 0x7C00, Bmask = 0x001F, GAmask = 0x83E0, r, b; |
117 r = (c & Rmask) >> 10; | 123 r = (c & Rmask) >> 10; |
118 b = (c & Bmask) << 10; | 124 b = (c & Bmask) << 10; |
119 return (c & GAmask) | r | b; | 125 return (c & GAmask) | r | b; |
120 } | |
121 | |
122 void | |
123 sdlds_surf2vram(SDL_Surface * s) | |
124 { | |
125 if (s->w == 256) { | |
126 u16 tmpbuf[0x20000]; | |
127 int i; | |
128 | |
129 dmaCopy((u8 *) (s->pixels) + 156 * sizeof(u16), | |
130 tmpbuf, 256 * 192 * sizeof(u16)); | |
131 /* hack to fix the pixel format until I figure out why BGR doesn't work */ | |
132 for (i = 0; i < 256 * 192; ++i) { | |
133 tmpbuf[i] = sdlds_rgb2bgr(tmpbuf[i]); | |
134 } | |
135 dmaCopy(tmpbuf, VRAM_A, 256 * 192 * sizeof(u16)); | |
136 } | |
137 } | 126 } |
138 | 127 |
139 void | 128 void |
140 sdlds_print_pixfmt_info(SDL_PixelFormat * f) | 129 sdlds_print_pixfmt_info(SDL_PixelFormat * f) |
141 { | 130 { |
198 renderer->DestroyRenderer = NDS_DestroyRenderer; | 187 renderer->DestroyRenderer = NDS_DestroyRenderer; |
199 renderer->info.name = NDS_RenderDriver.info.name; | 188 renderer->info.name = NDS_RenderDriver.info.name; |
200 renderer->info.flags = 0; | 189 renderer->info.flags = 0; |
201 renderer->window = window->id; | 190 renderer->window = window->id; |
202 renderer->driverdata = data; | 191 renderer->driverdata = data; |
203 Setup_SoftwareRenderer(renderer); /* TODO: well, "TODON'T" is more like it */ | 192 renderer->CreateTexture = NDS_CreateTexture; |
204 | 193 renderer->QueryTexturePixels = NDS_QueryTexturePixels; |
205 if (flags & SDL_RENDERER_PRESENTFLIP2) { | 194 renderer->SetTexturePalette = NDS_SetTexturePalette; |
206 renderer->info.flags |= SDL_RENDERER_PRESENTFLIP2; | 195 renderer->GetTexturePalette = NDS_GetTexturePalette; |
207 n = 2; | 196 renderer->SetTextureColorMod = NDS_SetTextureColorMod; |
208 } else if (flags & SDL_RENDERER_PRESENTFLIP3) { | 197 renderer->SetTextureAlphaMod = NDS_SetTextureAlphaMod; |
209 renderer->info.flags |= SDL_RENDERER_PRESENTFLIP3; | 198 renderer->SetTextureBlendMode = NDS_SetTextureBlendMode; |
210 n = 3; | 199 renderer->SetTextureScaleMode = NDS_SetTextureScaleMode; |
211 } else { | 200 renderer->UpdateTexture = NDS_UpdateTexture; |
212 renderer->info.flags |= SDL_RENDERER_PRESENTCOPY; | 201 renderer->LockTexture = NDS_LockTexture; |
213 n = 1; | 202 renderer->UnlockTexture = NDS_UnlockTexture; |
214 } | 203 renderer->DirtyTexture = NDS_DirtyTexture; |
215 /* | 204 renderer->DestroyTexture = NDS_DestroyTexture; |
216 for (i = 0; i < n; ++i) { | 205 |
217 data->screens[i] = | 206 renderer->info.mod_modes = NDS_RenderDriver.info.mod_modes; |
218 SDL_CreateRGBSurface(0, 256, 192, bpp, Rmask, Gmask, Bmask, | 207 renderer->info.blend_modes = NDS_RenderDriver.info.blend_modes; |
219 Amask); | 208 renderer->info.scale_modes = NDS_RenderDriver.info.scale_modes; |
220 if (!data->screens[i]) { | 209 renderer->info.num_texture_formats = |
221 NDS_DestroyRenderer(renderer); | 210 NDS_RenderDriver.info.num_texture_formats; |
222 return NULL; | 211 SDL_memcpy(renderer->info.texture_formats, |
223 } | 212 NDS_RenderDriver.info.texture_formats, |
224 SDL_SetSurfacePalette(data->screens[i], display->palette); | 213 sizeof(renderer->info.texture_formats));; |
225 sdlds_print_surface_info(data->screens[i]); | 214 renderer->info.max_texture_width = NDS_RenderDriver.info.max_texture_width; |
226 }*/ | 215 renderer->info.max_texture_height = |
227 | 216 NDS_RenderDriver.info.max_texture_height; |
228 data->fb = (u16*)0x06020000; | 217 |
218 /*data->fb = (u16*)0x06020000;*/ | |
219 data->bg = &BACKGROUND; | |
220 data->bg_taken[2] = data->bg_taken[3] = 0; | |
221 data->sub = 0; | |
229 | 222 |
230 return renderer; | 223 return renderer; |
231 } | 224 } |
232 | 225 |
233 static int | 226 static int |
248 | 241 |
249 static int | 242 static int |
250 NDS_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) | 243 NDS_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) |
251 { | 244 { |
252 NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata; | 245 NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata; |
253 | 246 NDS_TextureData *txdat = NULL; |
254 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { | 247 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { |
255 SDL_SetError("Unsupported texture format"); | 248 SDL_SetError("Unsupported texture format"); |
256 return -1; | 249 return -1; |
257 } else { | 250 } else { |
258 int bpp; | 251 int bpp; |
261 if (!SDL_PixelFormatEnumToMasks | 254 if (!SDL_PixelFormatEnumToMasks |
262 (texture->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) { | 255 (texture->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) { |
263 SDL_SetError("Unknown texture format"); | 256 SDL_SetError("Unknown texture format"); |
264 return -1; | 257 return -1; |
265 } | 258 } |
266 /* TODO: appropriate checks for ABGR1555 */ | 259 /* conditional statements on w/h to place it as bg/sprite */ |
267 texture->driverdata = SDL_calloc(1, sizeof(NDS_TextureData)); | 260 /*if(texture->w <= 64 && texture->h <= 64) { |
268 /* TODO: conditional statements on w/h to place it as bg/sprite */ | 261 sprites not implemented yet. elegant, I know. |
262 } else*/ if(texture->w <= 256 && texture->h <= 256) { | |
263 int whichbg = -1; | |
264 if(!data->bg_taken[2]) { | |
265 whichbg = 2; | |
266 data->bg->bg2_rotation.xdx = 0x100; | |
267 data->bg->bg2_rotation.xdy = 0; | |
268 data->bg->bg2_rotation.ydx = 0; | |
269 data->bg->bg2_rotation.ydy = 0x100; | |
270 data->bg->bg2_rotation.centerX = 0; | |
271 data->bg->bg2_rotation.centerY = 0; | |
272 } else if(!data->bg_taken[3]) { | |
273 whichbg = 3; | |
274 data->bg->bg3_rotation.xdx = 0x100; | |
275 data->bg->bg3_rotation.xdy = 0; | |
276 data->bg->bg3_rotation.ydx = 0; | |
277 data->bg->bg3_rotation.ydy = 0x100; | |
278 data->bg->bg3_rotation.centerX = 0; | |
279 data->bg->bg3_rotation.centerY = 0; | |
280 } | |
281 if(whichbg >= 0) { | |
282 data->bg->control[whichbg] = (bpp == 8) ? | |
283 BG_BMP8_256x256 : BG_BMP16_256x256; | |
284 data->bg->scroll[whichbg].x = 0; | |
285 data->bg->scroll[whichbg].y = 0; | |
286 texture->driverdata = SDL_calloc(1, sizeof(NDS_TextureData)); | |
287 txdat = (NDS_TextureData*)texture->driverdata; | |
288 txdat->type = NDSTX_BG; | |
289 txdat->hw_index = whichbg; | |
290 txdat->dim.w = texture->w; | |
291 txdat->dim.h = texture->h; | |
292 txdat->dim.pitch = 256 * (bpp/8); | |
293 txdat->dim.bpp = bpp; | |
294 txdat->vram = (u16*)(data->sub ? | |
295 BG_BMP_RAM_SUB(whichbg) : BG_BMP_RAM(whichbg)); | |
296 } else { | |
297 SDL_SetError("Out of NDS backgrounds."); | |
298 } | |
299 } else { | |
300 SDL_SetError("Texture too big for NDS hardware."); | |
301 } | |
269 } | 302 } |
270 | 303 |
271 if (!texture->driverdata) { | 304 if (!texture->driverdata) { |
272 return -1; | 305 return -1; |
273 } | 306 } |
366 rect->x * (txdat->dim.bpp/8); | 399 rect->x * (txdat->dim.bpp/8); |
367 length = rect->w * (txdat->dim.bpp/8); | 400 length = rect->w * (txdat->dim.bpp/8); |
368 for (row = 0; row < rect->h; ++row) { | 401 for (row = 0; row < rect->h; ++row) { |
369 SDL_memcpy(dst, src, length); | 402 SDL_memcpy(dst, src, length); |
370 src += pitch; | 403 src += pitch; |
371 dst += surface->pitch; | 404 dst += txdat->dim.pitch; |
372 } | 405 } |
373 return 0; | 406 return 0; |
374 } | 407 } |
375 } | 408 } |
376 | 409 |
413 NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata; | 446 NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata; |
414 SDL_Rect real_rect = *rect; | 447 SDL_Rect real_rect = *rect; |
415 u16 color; | 448 u16 color; |
416 int i, j; | 449 int i, j; |
417 | 450 |
451 /* TODO: make a single-color sprite and stretch it. | |
418 color = RGB15(r>>3,g>>3,b>>3); | 452 color = RGB15(r>>3,g>>3,b>>3); |
419 for (i = real_rect.x; i < real_rect.x+real_rect.w; ++i) { | 453 for (i = real_rect.x; i < real_rect.x+real_rect.w; ++i) { |
420 for (j = real_rect.y; j < real_rect.y+real_rect.h; ++j) { | 454 for (j = real_rect.y; j < real_rect.y+real_rect.h; ++j) { |
421 data->fb[(j + real_rect.y) * 256 + i + real_rect.x] = | 455 data->fb[(j + real_rect.y) * 256 + i + real_rect.x] = |
422 0x8000 | color; | 456 0x8000 | color; |
423 } | 457 } |
424 } | 458 }*/ |
425 return 0; | 459 return 0; |
426 } | 460 } |
427 | 461 |
428 static int | 462 static int |
429 NDS_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, | 463 NDS_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, |
446 } else { | 480 } else { |
447 SDL_Surface *surface = (SDL_Surface *) texture->driverdata; | 481 SDL_Surface *surface = (SDL_Surface *) texture->driverdata; |
448 SDL_Surface *target = data->screens[data->current_screen]; | 482 SDL_Surface *target = data->screens[data->current_screen]; |
449 SDL_Rect real_srcrect = *srcrect; | 483 SDL_Rect real_srcrect = *srcrect; |
450 SDL_Rect real_dstrect = *dstrect; | 484 SDL_Rect real_dstrect = *dstrect; |
451 /*sdlds_print_surface_info(surface); | |
452 sdlds_print_surface_info(target); */ | |
453 sdlds_surf2vram(surface); | |
454 return SDL_LowerBlit(surface, &real_srcrect, target, &real_dstrect); | 485 return SDL_LowerBlit(surface, &real_srcrect, target, &real_dstrect); |
455 } | 486 } |
456 #endif | 487 #endif |
457 /* copy it directly to vram */ | |
458 SDL_Surface *surface = (SDL_Surface *) texture->driverdata; | |
459 sdlds_surf2vram(surface); | |
460 /* | |
461 int sx = srcrect->x, sy = srcrect->y, sw = srcrect->w, sh = srcrect->h; | |
462 int dx = dstrect->x, dy = dstrect->y, dw = dstrect->w, dh = dstrect->h; | |
463 int si, sj, di, dj; | |
464 for (sj = 0, dj = 0; sj < sh && dj < dh; ++sj, ++dj) { | |
465 for (si = 0, di = 0; si < sw && di < dw; ++si, ++di) { | |
466 data->fb[(dj + dy) * 256 + di + dx] = 0x8000 | | |
467 ((u16 *) surface->pixels)[(sj + sy) * (surface->w) + si + | |
468 sx]; | |
469 } | |
470 }*/ | |
471 return 0; | 488 return 0; |
472 } | 489 } |
473 | 490 |
474 | 491 |
475 static void | 492 static void |
477 { | 494 { |
478 NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata; | 495 NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata; |
479 /* Send the data to the display TODO */ | 496 /* Send the data to the display TODO */ |
480 | 497 |
481 /* Update the flipping chain, if any */ | 498 /* Update the flipping chain, if any */ |
482 if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP2) { | 499 if (renderer->info.flags & SDL_RENDERER_PRESENTVSYNC) { |
483 data->current_screen = (data->current_screen + 1) % 2; | 500 swiWaitForVBlank(); |
484 } else if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP3) { | |
485 data->current_screen = (data->current_screen + 1) % 3; | |
486 } | 501 } |
487 } | 502 } |
488 | 503 |
489 static void | 504 static void |
490 NDS_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture) | 505 NDS_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture) |
491 { | 506 { |
492 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { | 507 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { |
493 SDL_SetError("Unsupported texture format"); | 508 SDL_SetError("Unsupported texture format"); |
494 } else { | 509 } else { |
495 /* TODO: free anything allocated for texture */ | 510 /* free anything else allocated for texture */ |
496 /*SDL_Surface *surface = (SDL_Surface *) texture->driverdata; | 511 SDL_free(texture->driverdata); |
497 SDL_FreeSurface(surface);*/ | |
498 } | 512 } |
499 } | 513 } |
500 | 514 |
501 static void | 515 static void |
502 NDS_DestroyRenderer(SDL_Renderer * renderer) | 516 NDS_DestroyRenderer(SDL_Renderer * renderer) |
505 /*SDL_Window *window = SDL_GetWindowFromID(renderer->window); | 519 /*SDL_Window *window = SDL_GetWindowFromID(renderer->window); |
506 SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);*/ | 520 SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);*/ |
507 int i; | 521 int i; |
508 | 522 |
509 if (data) { | 523 if (data) { |
510 for (i = 0; i < SDL_arraysize(data->texture); ++i) { | 524 /* TODO: free anything relevant. */ |
525 /*for (i = 0; i < SDL_arraysize(data->texture); ++i) { | |
511 if (data->texture[i]) { | 526 if (data->texture[i]) { |
512 DestroyTexture(data->renderer, data->texture[i]); | 527 DestroyTexture(data->renderer, data->texture[i]); |
513 } | 528 } |
514 } | 529 } |
515 if (data->surface.format) { | 530 if (data->surface.format) { |
518 } | 533 } |
519 if (display->palette) { | 534 if (display->palette) { |
520 SDL_DelPaletteWatch(display->palette, DisplayPaletteChanged, | 535 SDL_DelPaletteWatch(display->palette, DisplayPaletteChanged, |
521 data); | 536 data); |
522 } | 537 } |
523 SDL_FreeDirtyRects(&data->dirty); | 538 SDL_FreeDirtyRects(&data->dirty);*/ |
524 SDL_free(data); | 539 SDL_free(data); |
525 } | 540 } |
526 SDL_free(renderer); | 541 SDL_free(renderer); |
527 } | 542 } |
528 | 543 |