00001 #include <assert.h>
00002 #include <stdio.h>
00003 #include <stdlib.h>
00004 #include <unistd.h>
00005 #include <time.h>
00006 #include <sys/time.h>
00007 #include <math.h>
00008 #include <signal.h>
00009 #include <memory.h>
00010 #include <SDL.h>
00011 #include "Buzz_inc.h"
00012 #include "macros.h"
00013 #include "options.h"
00014 #include "utils.h"
00015 #include "logging.h"
00016 #include "av.h"
00017 #define MAX_X 320
00018 #define MAX_Y 200
00019
00020 LOG_DEFAULT_CATEGORY(sdl);
00021
00022 #define KEYBUF_SIZE 256
00023 static int keybuf[KEYBUF_SIZE];
00024 static int keybuf_in_idx, keybuf_out_idx;
00025
00026 int av_mouse_cur_x, av_mouse_cur_y;
00027 int av_mouse_pressed_x, av_mouse_pressed_y;
00028 int av_mouse_pressed_cur;
00029 int av_mouse_pressed_latched;
00030
00031 unsigned char *screen;
00032
00033 SDL_Surface *display;
00034 SDL_Overlay *video_overlay;
00035 SDL_Overlay *news_overlay;
00036 SDL_Rect video_rect;
00037 SDL_Rect news_rect;
00038 static SDL_Surface *screen_surf;
00039 static SDL_Surface *screen_surf2x;
00040
00041 static SDL_Color pal_colors[256];
00042
00043 static struct audio_channel Channels[AV_NUM_CHANNELS];
00044
00045
00046 unsigned char pal[3 * 256];
00047
00048
00049 static struct fade_information {
00050 unsigned from;
00051 unsigned to;
00052 unsigned step;
00053 unsigned steps;
00054 unsigned force_black;
00055 int inc;
00056 unsigned end;
00057 } fade_info;
00058
00059
00060 int screen_dirty;
00061
00062 static int have_audio;
00063
00064 static int do_fading;
00065
00066 static SDL_AudioSpec audio_desired;
00067
00068 static unsigned char *dirty_tree;
00069 static unsigned dirty_tree_length;
00070 static SDL_Rect *dirty_rect_list;
00071
00072 static void
00073 alloc_dirty_tree(void)
00074 {
00075 int depth = AV_DTREE_DEPTH + 1;
00076 int ratio = 1;
00077 int bytes = 0;
00078
00079
00080 while (depth--)
00081 ratio *= 4;
00082 bytes = (1 - ratio) / (1 - 4);
00083 dirty_tree = xcalloc(bytes, 1);
00084 dirty_tree_length = bytes;
00085
00086 ratio /= 4;
00087 dirty_rect_list = xcalloc(ratio, sizeof(SDL_Rect));
00088 }
00089
00090 static int get_dirty_rect_list();
00091
00092 static void
00093 audio_callback(void *userdata, Uint8 * stream, int len)
00094 {
00095 int ch = 0;
00096
00097 for (ch = 0; ch < AV_NUM_CHANNELS; ++ch)
00098 {
00099 int pos = 0;
00100 struct audio_channel *chp = &Channels[ch];
00101
00102 if (!chp->mute && chp->volume)
00103 {
00104 struct audio_chunk *ac = chp->chunk;
00105
00106 while (ac)
00107 {
00108 int bytes =
00109 min(len - pos, (int) ac->size - (int) chp->offset);
00110
00111
00112
00113
00114
00115
00116 SDL_MixAudio(stream + pos, ac->data + chp->offset,
00117 bytes, chp->volume);
00118
00119 pos += bytes;
00120 chp->offset += bytes;
00121
00122 if (chp->offset == ac->size)
00123 {
00124 chp->offset = 0;
00125 if (!ac->loop)
00126 {
00127 ac = chp->chunk = chp->chunk->next;
00128 if (!chp->chunk)
00129 chp->chunk_tailp = &chp->chunk;
00130
00131 }
00132 }
00133
00134 if (pos == len)
00135 break;
00136
00137 }
00138 }
00139 }
00140 }
00141
00142
00143
00144
00145
00146 char
00147 AnimSoundCheck(void)
00148 {
00149
00150 av_step();
00151 if (Channels[AV_SOUND_CHANNEL].chunk)
00152 return (0);
00153 return (1);
00154 }
00155
00156 int
00157 IsChannelMute(int channel)
00158 {
00159 assert(channel >= 0 && channel < AV_NUM_CHANNELS);
00160 if (!have_audio)
00161 return 1;
00162 return Channels[channel].mute;
00163 }
00164
00165 void
00166 play(struct audio_chunk *new_chunk, int channel)
00167 {
00168 struct audio_chunk *cp;
00169 struct audio_channel *chp;
00170
00171 assert(channel >= 0 && channel < AV_NUM_CHANNELS);
00172
00173 chp = &Channels[channel];
00174
00175 if (!have_audio)
00176 return;
00177
00178 SDL_LockAudio();
00179 for (cp = chp->chunk; cp; cp = cp->next)
00180 {
00181 if (cp == new_chunk)
00182 {
00183 DEBUG1("attempt to do add duplicate chunk");
00184 av_silence(channel);
00185 break;
00186 }
00187 }
00188
00189 new_chunk->next = NULL;
00190 *chp->chunk_tailp = new_chunk;
00191 SDL_UnlockAudio();
00192 }
00193
00194 void
00195 av_silence(int channel)
00196 {
00197 int i = channel;
00198
00199 if (channel == AV_ALL_CHANNELS)
00200 {
00201 for (i = 0; i < AV_NUM_CHANNELS; ++i)
00202 av_silence(i);
00203 }
00204 else
00205 {
00206 assert(channel >= 0 && channel < AV_NUM_CHANNELS);
00207 if (Channels[channel].chunk)
00208 {
00209 SDL_LockAudio();
00210 Channels[channel].chunk = NULL;
00211 Channels[channel].chunk_tailp = &Channels[channel].chunk;
00212 Channels[channel].offset = 0;
00213 SDL_UnlockAudio();
00214 }
00215 }
00216 }
00217
00218 Uint32
00219 sdl_timer_callback(Uint32 interval, void *param)
00220 {
00221 static SDL_Event tick;
00222
00223 tick.type = SDL_USEREVENT;
00224 SDL_PushEvent(&tick);
00225 return (interval);
00226 }
00227
00228
00229
00230
00231 void
00232 av_setup(void)
00233 {
00234 unsigned video_flags = SDL_SWSURFACE;
00235
00236 #ifndef CONFIG_MACOSX
00237 char *icon_path = NULL;
00238 #endif
00239
00240 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0)
00241 {
00242 CRITICAL2("SDL_Init error: %s", SDL_GetError());
00243 exit(EXIT_FAILURE);
00244 }
00245
00246 atexit(SDL_Quit);
00247
00248 if (options.want_audio)
00249 {
00250 #ifdef CONFIG_WIN32
00251
00252
00253
00254
00255 if (!SDL_getenv("SDL_AUDIODRIVER"))
00256 {
00257 INFO1("fixing WIN32 audio driver setup");
00258 SDL_putenv("SDL_AUDIODRIVER=waveout");
00259 }
00260
00261
00262
00263
00264 #endif
00265 if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
00266 {
00267 ERROR2("audio initialization failed: %s", SDL_GetError());
00268 }
00269 else
00270 {
00271 NOTICE1("audio subsystem initialized");
00272 have_audio = 1;
00273 }
00274 }
00275 else
00276 NOTICE1("no audio");
00277
00278 if (options.want_fullscreen)
00279 {
00280 video_flags |= SDL_FULLSCREEN;
00281 NOTICE1("fullscreen mode enabled");
00282 }
00283
00284 #ifndef CONFIG_MACOSX
00285 if ((icon_path = locate_file("moon_32x32.bmp", FT_IMAGE)))
00286 {
00287 SDL_Surface *icon = SDL_LoadBMP(icon_path);
00288
00289 if (icon != NULL)
00290 SDL_WM_SetIcon(icon, NULL);
00291 else
00292 INFO2("setting icon failed: %s\n", SDL_GetError());
00293 free(icon_path);
00294 }
00295 #endif
00296
00297 #ifdef PACKAGE_BUILD
00298 SDL_WM_SetCaption(PACKAGE_NAME " " PACKAGE_VERSION " build "
00299 PACKAGE_BUILD, NULL);
00300 #else
00301 SDL_WM_SetCaption(PACKAGE_STRING, NULL);
00302 #endif
00303
00304 if ((display =
00305 SDL_SetVideoMode(MAX_X * 2, MAX_Y * 2, 24, video_flags)) == NULL)
00306 {
00307 CRITICAL2("SDL_SetVideoMode failed: %s", SDL_GetError());
00308 exit(EXIT_FAILURE);
00309 }
00310
00311 screen = xcalloc(MAX_X * MAX_Y, 1);
00312 screen_surf = SDL_CreateRGBSurfaceFrom(screen, MAX_X, MAX_Y, 8,
00313 MAX_X, 0, 0, 0, 0);
00314 if (!screen_surf)
00315 {
00316 CRITICAL2("can't create screen surface: %s", SDL_GetError());
00317 exit(EXIT_FAILURE);
00318 }
00319 screen_surf2x =
00320 SDL_CreateRGBSurface(SDL_SWSURFACE, MAX_X * 2, MAX_Y * 2, 8, ~0, ~0,
00321 ~0, 0);
00322 if (!screen_surf2x)
00323 {
00324 CRITICAL2("can't create screen_2x surface: %s", SDL_GetError());
00325 exit(EXIT_FAILURE);
00326 }
00327
00328
00329 video_overlay =
00330 SDL_CreateYUVOverlay(160, 100, SDL_YV12_OVERLAY, display);
00331 if (!video_overlay)
00332 {
00333 CRITICAL2("can't create video_overlay: %s", SDL_GetError());
00334 exit(EXIT_FAILURE);
00335 }
00336 news_overlay = SDL_CreateYUVOverlay(312, 106, SDL_YV12_OVERLAY, display);
00337
00338 if (!news_overlay)
00339 {
00340 CRITICAL2("can't create news_overlay: %s", SDL_GetError());
00341 exit(EXIT_FAILURE);
00342 }
00343
00344 fade_info.step = 1;
00345 fade_info.steps = 1;
00346 do_fading = 1;
00347
00348 alloc_dirty_tree();
00349
00350 SDL_EnableUNICODE(1);
00351 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY,
00352 SDL_DEFAULT_REPEAT_INTERVAL);
00353
00354 if (have_audio)
00355 {
00356 int i = 0;
00357
00358 audio_desired.freq = 11025;
00359 audio_desired.format = AUDIO_U8;
00360 audio_desired.channels = 1;
00361
00362 audio_desired.samples = 2048;
00363 audio_desired.callback = audio_callback;
00364
00365
00366 for (i = 0; i < AV_NUM_CHANNELS; ++i)
00367 {
00368 Channels[i].volume = AV_MAX_VOLUME;
00369 Channels[i].mute = 0;
00370 Channels[i].chunk = NULL;
00371 Channels[i].chunk_tailp = &Channels[i].chunk;
00372 Channels[i].offset = 0;
00373 }
00374
00375
00376 if (SDL_OpenAudio(&audio_desired, NULL) < 0)
00377 {
00378 ERROR2("SDL_OpenAudio error: %s", SDL_GetError());
00379 NOTICE1("disabling audio");
00380 have_audio = 0;
00381 }
00382 else
00383 SDL_PauseAudio(0);
00384 }
00385
00386 SDL_AddTimer(30, sdl_timer_callback, NULL);
00387 }
00388
00389 static void
00390 av_process_event(SDL_Event * evp)
00391 {
00392 int c;
00393
00394 switch (evp->type)
00395 {
00396 case SDL_QUIT:
00397 exit(0);
00398 break;
00399
00400 case SDL_USEREVENT:
00401 break;
00402
00403 case SDL_KEYDOWN:
00404 switch (evp->key.keysym.sym)
00405 {
00406 case SDLK_UP:
00407 c = 0x4800;
00408 break;
00409 case SDLK_DOWN:
00410 c = 0x5000;
00411 break;
00412 case SDLK_RIGHT:
00413 c = 0x4D00;
00414 break;
00415 case SDLK_LEFT:
00416 c = 0x4B00;
00417 break;
00418 case SDLK_F1:
00419 c = 0x3B00;
00420 break;
00421 case SDLK_F2:
00422 c = 0x3C00;
00423 break;
00424 case SDLK_F3:
00425 c = 0x3D00;
00426 break;
00427 default:
00428 c = evp->key.keysym.unicode;
00429 break;
00430 }
00431 if (c)
00432 {
00433 keybuf[keybuf_in_idx] = c;
00434 keybuf_in_idx = (keybuf_in_idx + 1) % KEYBUF_SIZE;
00435 }
00436 break;
00437
00438 case SDL_MOUSEBUTTONDOWN:
00439 av_mouse_pressed_cur = 1;
00440 av_mouse_pressed_latched = 1;
00441 av_mouse_pressed_x = evp->button.x;
00442 av_mouse_pressed_y = evp->button.y;
00443 TRACE4("mouseclick(%d, %d) b = %d", av_mouse_pressed_x,
00444 av_mouse_pressed_y, evp->button.button);
00445 break;
00446
00447 case SDL_MOUSEBUTTONUP:
00448 av_mouse_pressed_cur = 0;
00449
00450
00451 if (evp->button.button == SDL_BUTTON_WHEELUP
00452 || evp->button.button == SDL_BUTTON_WHEELDOWN)
00453 {
00454 SDL_Event ev;
00455 int up = evp->button.button == SDL_BUTTON_WHEELUP;
00456 SDLMod mod = SDL_GetModState();
00457 SDLKey key;
00458
00459 if (mod & KMOD_SHIFT)
00460 key = up ? SDLK_LEFT : SDLK_RIGHT;
00461 else
00462 key = up ? SDLK_UP : SDLK_DOWN;
00463
00464 ev.type = SDL_KEYDOWN;
00465 ev.key.type = SDL_KEYDOWN;
00466 ev.key.state = SDL_RELEASED;
00467 ev.key.keysym.scancode = 0;
00468 ev.key.keysym.mod = mod;
00469 ev.key.keysym.unicode = 0;
00470 ev.key.keysym.sym = key;
00471 av_process_event(&ev);
00472 }
00473 break;
00474
00475 case SDL_MOUSEMOTION:
00476 av_mouse_cur_x = evp->motion.x;
00477 av_mouse_cur_y = evp->motion.y;
00478 break;
00479
00480
00481 case SDL_KEYUP:
00482 case SDL_ACTIVEEVENT:
00483 break;
00484 default:
00485 DEBUG2("got unknown event %d", evp->type);
00486 break;
00487 }
00488 }
00489
00490
00491 void
00492 av_step(void)
00493 {
00494 SDL_Event ev;
00495
00496
00497 music_pump();
00498
00499 while (SDL_PollEvent(&ev))
00500 av_process_event(&ev);
00501 }
00502
00503
00504
00505
00506
00507
00508
00509 void
00510 av_block(void)
00511 {
00512 SDL_Event ev;
00513
00514 if (SDL_WaitEvent(&ev))
00515 {
00516 av_process_event(&ev);
00517 av_step();
00518 }
00519 }
00520
00521 int
00522 bioskey(int peek)
00523 {
00524 int c;
00525
00526 av_step();
00527
00528 if (peek)
00529 {
00530 if (keybuf_in_idx != keybuf_out_idx)
00531 return (1);
00532 return (0);
00533 }
00534
00535 if (keybuf_in_idx == keybuf_out_idx)
00536 return (0);
00537
00538 c = keybuf[keybuf_out_idx];
00539 keybuf_out_idx = (keybuf_out_idx + 1) % KEYBUF_SIZE;
00540
00541 return (c);
00542 }
00543
00544 void
00545 UpdateAudio(void)
00546 {
00547
00548 }
00549
00550 void
00551 NUpdateVoice(void)
00552 {
00553 av_step();
00554 }
00555
00556 static SDL_Surface *
00557 SDL_Scale2x(SDL_Surface * src, SDL_Surface * dst)
00558 {
00559 int x, y, bpp;
00560 uint8_t *from, *to;
00561 SDL_Rect clp;
00562 SDL_PixelFormat *pf;
00563
00564 assert(src);
00565 assert(src != dst);
00566
00567 pf = src->format;
00568
00569 if (!dst)
00570 dst = SDL_CreateRGBSurface(SDL_SWSURFACE,
00571 2 * src->w, 2 * src->h,
00572 pf->BitsPerPixel, pf->Rmask, pf->Gmask, pf->Bmask, pf->Amask);
00573
00574 if (!dst)
00575 return NULL;
00576
00577 bpp = pf->BytesPerPixel;
00578
00579 if (2 * src->h != dst->h
00580 || 2 * src->w != dst->w || bpp != dst->format->BytesPerPixel)
00581 {
00582 SDL_SetError("dst surface size or bpp mismatch (%d vs %d)",
00583 bpp, dst->format->BytesPerPixel);
00584 return NULL;
00585 }
00586
00587 if (bpp == 1)
00588 SDL_SetColors(dst, pf->palette->colors, 0, pf->palette->ncolors);
00589
00590 if (SDL_MUSTLOCK(src))
00591 SDL_LockSurface(src);
00592 if (SDL_MUSTLOCK(dst))
00593 SDL_LockSurface(dst);
00594
00595 SDL_GetClipRect(dst, &clp);
00596
00597 for (y = clp.y / 2; y < clp.y / 2 + clp.h / 2; ++y)
00598 {
00599 for (x = clp.x / 2; x < clp.x / 2 + clp.w / 2; ++x)
00600 {
00601 from = ((uint8_t *) src->pixels) + y * src->pitch + x * bpp;
00602 to = ((uint8_t *) dst->pixels) + 2 * y * dst->pitch +
00603 2 * x * bpp;
00604 switch (bpp)
00605 {
00606 #define ASSIGN do { \
00607 *(TYPE (to)) = *(TYPE from); \
00608 *(TYPE (to+bpp)) = *(TYPE from); \
00609 *(TYPE (to+dst->pitch)) = *(TYPE from); \
00610 *(TYPE (to+dst->pitch+bpp)) = *(TYPE from); \
00611 } while (0)
00612
00613 case 1:
00614 #define TYPE (uint8_t *)
00615 ASSIGN;
00616 break;
00617 #undef TYPE
00618 case 2:
00619 #define TYPE (uint16_t *)
00620 ASSIGN;
00621 break;
00622 #undef TYPE
00623 case 3:
00624 #define TYPE (uint8_t *)
00625 ASSIGN;
00626 to++;
00627 from++;
00628 ASSIGN;
00629 to++;
00630 from++;
00631 ASSIGN;
00632 to++;
00633 from++;
00634 break;
00635 #undef TYPE
00636 case 4:
00637 #define TYPE (uint32_t *)
00638 ASSIGN;
00639 break;
00640 #undef TYPE
00641 #undef ASSIGN
00642 }
00643 }
00644 }
00645
00646 if (SDL_MUSTLOCK(dst))
00647 SDL_UnlockSurface(dst);
00648 if (SDL_MUSTLOCK(src))
00649 SDL_UnlockSurface(src);
00650
00651 return dst;
00652 }
00653
00654 static void
00655 transform_palette(void)
00656 {
00657 unsigned i, j, step, steps;
00658 struct range {
00659 unsigned start, end;
00660 } ranges[] = {{0, fade_info.from}, {fade_info.to, 256}};
00661
00662 for (j = 0; j < ARRAY_LENGTH(ranges); ++j)
00663 for (i = ranges[j].start; i < ranges[j].end; ++i)
00664 {
00665 if (!fade_info.force_black)
00666 {
00667 pal_colors[i].r = pal[3 * i] * 4;
00668 pal_colors[i].g = pal[3 * i + 1] * 4;
00669 pal_colors[i].b = pal[3 * i + 2] * 4;
00670 }
00671 else
00672 {
00673 pal_colors[i].r = 0;
00674 pal_colors[i].g = 0;
00675 pal_colors[i].b = 0;
00676 }
00677 }
00678 step = fade_info.step;
00679 steps = fade_info.steps;
00680
00681 assert(steps != 0 && step <= steps);
00682 for (i = fade_info.from; i < fade_info.to; ++i)
00683 {
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693 pal_colors[i].r = pal[3 * i] * 4;
00694 pal_colors[i].r = pal_colors[i].r * step / steps;
00695 pal_colors[i].g = pal[3 * i + 1] * 4;
00696 pal_colors[i].g = pal_colors[i].g * step / steps;
00697 pal_colors[i].b = pal[3 * i + 2] * 4;
00698 pal_colors[i].b = pal_colors[i].b * step / steps;
00699 }
00700 }
00701
00702 void
00703 av_sync(void)
00704 {
00705 int num_rect = 0;
00706 SDL_Rect r;
00707
00708 #ifdef PROFILE_GRAPHICS
00709 float tot_area = 0;
00710 int i = 0;
00711 Uint32 ticks = SDL_GetTicks();
00712 #endif
00713
00714 SDL_Scale2x(screen_surf, screen_surf2x);
00715
00716 transform_palette();
00717 SDL_SetColors(screen_surf2x, pal_colors, 0, 256);
00718 SDL_BlitSurface(screen_surf2x, NULL, display, NULL);
00719 if (video_rect.h && video_rect.w)
00720 {
00721 av_need_update(&video_rect);
00722 r.h = 2 * video_rect.h;
00723 r.w = 2 * video_rect.w;
00724 r.x = 2 * video_rect.x;
00725 r.y = 2 * video_rect.y;
00726 SDL_DisplayYUVOverlay(video_overlay, &r);
00727 }
00728 if (news_rect.h && news_rect.w)
00729 {
00730 av_need_update(&news_rect);
00731 r.h = 2 * news_rect.h;
00732 r.w = 2 * news_rect.w;
00733 r.x = 2 * news_rect.x;
00734 r.y = 2 * news_rect.y;
00735 SDL_DisplayYUVOverlay(news_overlay, &r);
00736 }
00737 num_rect = get_dirty_rect_list();
00738 SDL_UpdateRects(display, num_rect, dirty_rect_list);
00739 #ifdef PROFILE_GRAPHICS
00740 for (i = 0; i < num_rect; ++i)
00741 tot_area += dirty_rect_list[i].w * dirty_rect_list[i].h;
00742 tot_area = tot_area * 100 / (2 * MAX_X) / (2 * MAX_Y);
00743 TRACE4("%3d rects (%6.2f%%) updated in ~%3ums\n",
00744 num_rect, tot_area, SDL_GetTicks() - ticks);
00745 #endif
00746 screen_dirty = 0;
00747 }
00748
00749 void
00750 MuteChannel(int channel, int mute)
00751 {
00752 int i;
00753
00754 if (channel == AV_ALL_CHANNELS)
00755 {
00756 for (i = 0; i < AV_NUM_CHANNELS; ++i)
00757 MuteChannel(i, mute);
00758 }
00759 else
00760 {
00761 assert(channel >= 0 && channel < AV_NUM_CHANNELS);
00762 Channels[channel].mute = mute;
00763 }
00764 }
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783 void
00784 av_set_fading(int type, int from, int to, int steps, int preserve)
00785 {
00786 int dir = (type == AV_FADE_IN) ? 1 : -1;
00787 unsigned st;
00788 unsigned st_end;
00789 SDL_Rect r = {0, 0, MAX_X, MAX_Y};
00790
00791 if (!do_fading)
00792 return;
00793
00794 if (!steps > 0)
00795 steps = 5;
00796 st = (type == AV_FADE_IN) ? 0 : steps;
00797 st_end = steps - st;
00798
00799 fade_info.from = from;
00800 fade_info.to = to;
00801 fade_info.steps = steps;
00802 fade_info.step = st;
00803 fade_info.force_black = !preserve;
00804 fade_info.inc = dir;
00805 fade_info.end = st_end;
00806
00807 for (;fade_info.step != fade_info.end; fade_info.step += fade_info.inc)
00808 {
00809 av_need_update(&r);
00810 av_sync();
00811 SDL_Delay(10);
00812 }
00813 av_need_update(&r);
00814 av_sync();
00815 }
00816
00817
00818 inline static int
00819 intersect_area(SDL_Rect *first, SDL_Rect *second)
00820 {
00821 int isect_h = 0, isect_w = 0;
00822 SDL_Rect *t;
00823
00824
00825
00826
00827 if (first->x > second->x)
00828 {
00829 t = first; first = second; second = t;
00830 }
00831 if (first->x + first->w < second->x)
00832 return 0;
00833 else
00834 isect_w = min(second->w, first->x + first->w - second->x);
00835
00836 if (first->y > second->y)
00837 {
00838 t = first; first = second; second = t;
00839 }
00840 if (first->y + first->h < second->y)
00841 return 0;
00842 else
00843 isect_h = min(second->h, first->y + first->h - second->y);
00844
00845 return isect_h * isect_w;
00846 }
00847
00848 static void
00849 update_rect(SDL_Rect *fill, int x, int y, int w, int h, int idx, int level)
00850 {
00851 SDL_Rect r = {x, y, w, h};
00852 int nw = w / 2;
00853 int nh = h / 2;
00854 int area = 0;
00855
00856 assert((unsigned)idx < dirty_tree_length);
00857
00858
00859 if (dirty_tree[idx])
00860 return;
00861
00862
00863 area = intersect_area(fill, &r);
00864 if (area == 0)
00865 return;
00866 else if (level == AV_DTREE_DEPTH
00867 || area > AV_DTREE_FILL_RATIO * h * w)
00868 {
00869 dirty_tree[idx] = 1;
00870 return;
00871 }
00872
00873 idx *= 4;
00874 level += 1;
00875
00876 update_rect(fill, x, y, nw, nh, idx + 1, level);
00877 update_rect(fill, x + nw, y, w - nw, nh, idx + 2, level);
00878 update_rect(fill, x, y + nh, nw, h - nh, idx + 3, level);
00879 update_rect(fill, x + nw, y + nh, w - nw, h - nh, idx + 4, level);
00880 }
00881
00882 static void
00883 fill_rect_list(SDL_Rect *arr, int *len, int x, int y, int w, int h,
00884 int idx, int level)
00885 {
00886 int nw = w / 2;
00887 int nh = h / 2;
00888
00889 if (level > AV_DTREE_DEPTH)
00890 return;
00891
00892 assert((unsigned)idx < dirty_tree_length);
00893
00894 if (dirty_tree[idx])
00895 {
00896
00897 SDL_Rect r = {2*x, 2*y, 2*w, 2*h};
00898 memcpy(&arr[(*len)++], &r, sizeof(r));
00899 return;
00900 }
00901
00902 idx *= 4;
00903 level += 1;
00904
00905 fill_rect_list(arr, len, x, y, nw, nh, idx + 1, level);
00906 fill_rect_list(arr, len, x + nw, y, w - nw, nh, idx + 2, level);
00907 fill_rect_list(arr, len, x, y + nh, nw, h - nh, idx + 3, level);
00908 fill_rect_list(arr, len, x + nw, y + nh, w - nw, h - nh, idx + 4, level);
00909 }
00910
00911 static int
00912 get_dirty_rect_list(void)
00913 {
00914 int len = 0;
00915 fill_rect_list(dirty_rect_list, &len, 0, 0, MAX_X, MAX_Y, 0, 0);
00916 memset(dirty_tree, 0, dirty_tree_length);
00917 return len;
00918 }
00919
00920
00921
00922
00923
00924 void
00925 av_need_update(SDL_Rect *r)
00926 {
00927 update_rect(r, 0, 0, MAX_X, MAX_Y, 0, 0);
00928 screen_dirty = 1;
00929 }
00930
00931
00932
00933
00934
00935
00936
00937
00938 void
00939 av_need_update_xy(int x1, int y1, int x2, int y2)
00940 {
00941 SDL_Rect r = {x1, y1, x2-x1+1, y2-y1+1};
00942 av_need_update(&r);
00943 }
00944
00945