00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "global.hpp"
00021
00022 #include <stdio.h>
00023 #include <iostream>
00024 #include <vector>
00025
00026 #include "events.hpp"
00027 #include "font.hpp"
00028 #include "image.hpp"
00029 #include "log.hpp"
00030 #include "preferences_display.hpp"
00031 #include "video.hpp"
00032
00033 #define LOG_DP LOG_STREAM(info, display)
00034 #define ERR_DP LOG_STREAM(err, display)
00035
00036 #define TEST_VIDEO_ON 0
00037
00038 #if (TEST_VIDEO_ON==1)
00039
00040 #include <stdlib.h>
00041
00042
00043 int main( int argc, char** argv )
00044 {
00045 if( argc != 4 ) {
00046 printf( "usage: %s x-res y-res bitperpixel\n", argv[0] );
00047 return 1;
00048 }
00049 SDL_Init(SDL_INIT_VIDEO);
00050 CVideo video;
00051
00052 printf( "args: %s, %s, %s\n", argv[1], argv[2], argv[3] );
00053
00054 printf( "(%d,%d,%d)\n", strtoul(argv[1],0,10), strtoul(argv[2],0,10),
00055 strtoul(argv[3],0,10) );
00056
00057 if( video.setMode( strtoul(argv[1],0,10), strtoul(argv[2],0,10),
00058 strtoul(argv[3],0,10), FULL_SCREEN ) ) {
00059 printf( "video mode possible\n" );
00060 } else printf( "video mode NOT possible\n" );
00061 printf( "%d, %d, %d\n", video.getx(), video.gety(),
00062 video.getBitsPerPixel() );
00063
00064 for( int s = 0; s < 50; s++ ) {
00065 video.lock();
00066 for( int i = 0; i < video.getx(); i++ )
00067 video.setPixel( i, 90, 255, 0, 0 );
00068 if( s%10==0)
00069 printf( "frame %d\n", s );
00070 video.unlock();
00071 video.update( 0, 90, video.getx(), 1 );
00072 }
00073 return 0;
00074 }
00075
00076 #endif
00077
00078 namespace {
00079 bool fullScreen = false;
00080 int disallow_resize = 0;
00081 }
00082 void resize_monitor::process(events::pump_info &info) {
00083 if(info.resize_dimensions.first >= min_allowed_width
00084 && info.resize_dimensions.second >= min_allowed_height
00085 && disallow_resize == 0) {
00086 preferences::set_resolution(info.resize_dimensions);
00087 }
00088 }
00089
00090 resize_lock::resize_lock()
00091 {
00092 ++disallow_resize;
00093 }
00094
00095 resize_lock::~resize_lock()
00096 {
00097 --disallow_resize;
00098 }
00099
00100 static unsigned int get_flags(unsigned int flags)
00101 {
00102
00103
00104 #if !(defined(_WIN32) || defined(__APPLE__) || defined(__AMIGAOS4__))
00105 flags |= SDL_HWSURFACE;
00106 #endif
00107 if((flags&SDL_FULLSCREEN) == 0)
00108 flags |= SDL_RESIZABLE;
00109
00110 return flags;
00111 }
00112
00113 namespace {
00114 std::vector<SDL_Rect> update_rects;
00115 bool update_all = false;
00116 }
00117
00118 static bool rect_contains(const SDL_Rect& a, const SDL_Rect& b) {
00119 return a.x <= b.x && a.y <= b.y && a.x+a.w >= b.x+b.w && a.y+a.h >= b.y+b.h;
00120 }
00121
00122 static void clear_updates()
00123 {
00124 update_all = false;
00125 update_rects.clear();
00126 }
00127
00128 namespace {
00129
00130 surface frameBuffer = NULL;
00131
00132 }
00133
00134 bool non_interactive()
00135 {
00136 return SDL_GetVideoSurface() == NULL;
00137 }
00138
00139 surface display_format_alpha(surface surf)
00140 {
00141 if(SDL_GetVideoSurface() != NULL)
00142 return SDL_DisplayFormatAlpha(surf);
00143 else if(frameBuffer != NULL)
00144 return SDL_ConvertSurface(surf,frameBuffer->format,0);
00145 else
00146 return NULL;
00147 }
00148
00149 surface get_video_surface()
00150 {
00151 return frameBuffer;
00152 }
00153
00154 SDL_Rect screen_area()
00155 {
00156 const SDL_Rect res = {0,0,frameBuffer->w,frameBuffer->h};
00157 return res;
00158 }
00159
00160 void update_rect(size_t x, size_t y, size_t w, size_t h)
00161 {
00162 const SDL_Rect rect = {x,y,w,h};
00163 update_rect(rect);
00164 }
00165
00166 void update_rect(const SDL_Rect& rect_value)
00167 {
00168 if(update_all)
00169 return;
00170
00171 SDL_Rect rect = rect_value;
00172
00173 surface const fb = SDL_GetVideoSurface();
00174 if(fb != NULL) {
00175 if(rect.x < 0) {
00176 if(rect.x*-1 >= int(rect.w))
00177 return;
00178
00179 rect.w += rect.x;
00180 rect.x = 0;
00181 }
00182
00183 if(rect.y < 0) {
00184 if(rect.y*-1 >= int(rect.h))
00185 return;
00186
00187 rect.h += rect.y;
00188 rect.y = 0;
00189 }
00190
00191 if(rect.x + rect.w > fb->w) {
00192 rect.w = fb->w - rect.x;
00193 }
00194
00195 if(rect.y + rect.h > fb->h) {
00196 rect.h = fb->h - rect.y;
00197 }
00198
00199 if(rect.x >= fb->w) {
00200 return;
00201 }
00202
00203 if(rect.y >= fb->h) {
00204 return;
00205 }
00206 }
00207
00208 for(std::vector<SDL_Rect>::iterator i = update_rects.begin();
00209 i != update_rects.end(); ++i) {
00210 if(rect_contains(*i,rect)) {
00211 return;
00212 }
00213
00214 if(rect_contains(rect,*i)) {
00215 *i = rect;
00216 for(++i; i != update_rects.end(); ++i) {
00217 if(rect_contains(rect,*i)) {
00218 i->w = 0;
00219 }
00220 }
00221
00222 return;
00223 }
00224 }
00225
00226 update_rects.push_back(rect);
00227 }
00228
00229 void update_whole_screen()
00230 {
00231 update_all = true;
00232 }
00233 CVideo::CVideo() : bpp(0), fake_screen(false), help_string_(0), updatesLocked_(0)
00234 {
00235 const int res = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE);
00236
00237 if(res < 0) {
00238 ERR_DP << "Could not initialize SDL: " << SDL_GetError() << "\n";
00239 throw CVideo::error();
00240 }
00241 }
00242
00243 CVideo::CVideo( int x, int y, int bits_per_pixel, int flags)
00244 : bpp(0), fake_screen(false), help_string_(0), updatesLocked_(0)
00245 {
00246 const int res = SDL_Init( SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE);
00247 if(res < 0) {
00248 ERR_DP << "Could not initialize SDL: " << SDL_GetError() << "\n";
00249 throw CVideo::error();
00250 }
00251
00252 const int mode_res = setMode( x, y, bits_per_pixel, flags );
00253 if (mode_res == 0) {
00254 ERR_DP << "Could not set Video Mode\n";
00255 throw CVideo::error();
00256 }
00257 }
00258
00259 CVideo::~CVideo()
00260 {
00261 LOG_DP << "calling SDL_Quit()\n";
00262 SDL_Quit();
00263 LOG_DP << "called SDL_Quit()\n";
00264 }
00265
00266 void CVideo::blit_surface(int x, int y, surface surf, SDL_Rect* srcrect, SDL_Rect* clip_rect)
00267 {
00268 const surface target(getSurface());
00269 SDL_Rect dst = {x,y,0,0};
00270
00271 if(clip_rect != NULL) {
00272 const clip_rect_setter clip_setter(target,*clip_rect);
00273 SDL_BlitSurface(surf,srcrect,target,&dst);
00274 } else {
00275 SDL_BlitSurface(surf,srcrect,target,&dst);
00276 }
00277 }
00278
00279 void CVideo::make_fake()
00280 {
00281 fake_screen = true;
00282 frameBuffer = SDL_CreateRGBSurface(SDL_SWSURFACE,16,16,24,0xFF0000,0xFF00,0xFF,0);
00283 image::set_pixel_format(frameBuffer->format);
00284 }
00285
00286 int CVideo::modePossible( int x, int y, int bits_per_pixel, int flags )
00287 {
00288 return SDL_VideoModeOK( x, y, bits_per_pixel, get_flags(flags) );
00289 }
00290
00291 int CVideo::setMode( int x, int y, int bits_per_pixel, int flags )
00292 {
00293 update_rects.clear();
00294 if (fake_screen) return 0;
00295 mode_changed_ = true;
00296
00297 flags = get_flags(flags);
00298 const int res = SDL_VideoModeOK( x, y, bits_per_pixel, flags );
00299
00300 if( res == 0 )
00301 return 0;
00302
00303 fullScreen = (flags & FULL_SCREEN) != 0;
00304 frameBuffer = SDL_SetVideoMode( x, y, bits_per_pixel, flags );
00305
00306 if( frameBuffer != NULL ) {
00307 image::set_pixel_format(frameBuffer->format);
00308 return bits_per_pixel;
00309 } else return 0;
00310 }
00311
00312 bool CVideo::modeChanged()
00313 {
00314 bool ret = mode_changed_;
00315 mode_changed_ = false;
00316 return ret;
00317 }
00318
00319 int CVideo::setGamma(float gamma)
00320 {
00321 SDL_SetGamma(gamma, gamma, gamma);
00322
00323 return 0;
00324 }
00325
00326 int CVideo::getx() const
00327 {
00328 return frameBuffer->w;
00329 }
00330
00331 int CVideo::gety() const
00332 {
00333 return frameBuffer->h;
00334 }
00335
00336 int CVideo::getBitsPerPixel()
00337 {
00338 return frameBuffer->format->BitsPerPixel;
00339 }
00340
00341 int CVideo::getBytesPerPixel()
00342 {
00343 return frameBuffer->format->BytesPerPixel;
00344 }
00345
00346 int CVideo::getRedMask()
00347 {
00348 return frameBuffer->format->Rmask;
00349 }
00350
00351 int CVideo::getGreenMask()
00352 {
00353 return frameBuffer->format->Gmask;
00354 }
00355
00356 int CVideo::getBlueMask()
00357 {
00358 return frameBuffer->format->Bmask;
00359 }
00360
00361 void CVideo::flip()
00362 {
00363 if(fake_screen)
00364 return;
00365
00366 if(update_all) {
00367 ::SDL_Flip(frameBuffer);
00368 } else if(update_rects.empty() == false) {
00369 size_t sum = 0;
00370 for(size_t n = 0; n != update_rects.size(); ++n) {
00371 sum += update_rects[n].w*update_rects[n].h;
00372 }
00373
00374 const size_t redraw_whole_screen_threshold = 80;
00375 if(sum > ((getx()*gety())*redraw_whole_screen_threshold)/100) {
00376 ::SDL_Flip(frameBuffer);
00377 } else {
00378 SDL_UpdateRects(frameBuffer,update_rects.size(),&update_rects[0]);
00379 }
00380 }
00381
00382 clear_updates();
00383 }
00384
00385 void CVideo::lock_updates(bool value)
00386 {
00387 if(value == true)
00388 ++updatesLocked_;
00389 else
00390 --updatesLocked_;
00391 }
00392
00393 bool CVideo::update_locked() const
00394 {
00395 return updatesLocked_ > 0;
00396 }
00397
00398 void CVideo::lock()
00399 {
00400 if( SDL_MUSTLOCK(frameBuffer) )
00401 SDL_LockSurface( frameBuffer );
00402 }
00403
00404 void CVideo::unlock()
00405 {
00406 if( SDL_MUSTLOCK(frameBuffer) )
00407 SDL_UnlockSurface( frameBuffer );
00408 }
00409
00410 int CVideo::mustLock()
00411 {
00412 return SDL_MUSTLOCK(frameBuffer);
00413 }
00414
00415 surface CVideo::getSurface( void )
00416 {
00417 return frameBuffer;
00418 }
00419
00420 bool CVideo::isFullScreen() const { return fullScreen; }
00421
00422 void CVideo::setBpp( int bpp )
00423 {
00424 this->bpp = bpp;
00425 }
00426
00427 int CVideo::getBpp( void )
00428 {
00429 return bpp;
00430 }
00431
00432 int CVideo::set_help_string(const std::string& str)
00433 {
00434 font::remove_floating_label(help_string_);
00435
00436 const SDL_Color colour = {0x0,0x00,0x00,0x77};
00437
00438 #ifdef USE_TINY_GUI
00439 int size = font::SIZE_NORMAL;
00440 #else
00441 int size = font::SIZE_LARGE;
00442 #endif
00443
00444 while(size > 0) {
00445 if(font::line_width(str, size) > getx()) {
00446 size--;
00447 } else {
00448 break;
00449 }
00450 }
00451
00452 #ifdef USE_TINY_GUI
00453 const int border = 2;
00454 #else
00455 const int border = 5;
00456 #endif
00457
00458 help_string_ = font::add_floating_label(str,size,font::NORMAL_COLOUR,getx()/2,gety(),0.0,0.0,-1,screen_area(),font::CENTER_ALIGN,&colour,border);
00459 const SDL_Rect& rect = font::get_floating_label_rect(help_string_);
00460 font::move_floating_label(help_string_,0.0,-double(rect.h));
00461 return help_string_;
00462 }
00463
00464 void CVideo::clear_help_string(int handle)
00465 {
00466 if(handle == help_string_) {
00467 font::remove_floating_label(handle);
00468 help_string_ = 0;
00469 }
00470 }
00471
00472 void CVideo::clear_all_help_strings()
00473 {
00474 clear_help_string(help_string_);
00475 }