Annotation of previous/src/fast_screen.c, revision 1.1.1.3

1.1       root        1: /*
                      2:   Hatari - screen.c
                      3: 
                      4:   This file is distributed under the GNU Public License, version 2 or at your
                      5:   option any later version. Read the file gpl.txt for details.
                      6: 
1.1.1.2   root        7:  (SC) Simon Schubiger - most of it rewritten for Previous NeXT emulator
1.1       root        8: */
                      9: 
                     10: #include <SDL.h>
                     11: #include <SDL_endian.h>
                     12: #include <SDL_blendmode.h>
                     13: 
                     14: const char Screen_fileid[] = "Previous fast_screen.c : " __DATE__ " " __TIME__;
                     15: 
                     16: #include "main.h"
                     17: #include "configuration.h"
                     18: #include "log.h"
                     19: #include "m68000.h"
1.1.1.3 ! root       20: #include "dimension.hpp"
        !            21: #include "nd_mem.hpp"
1.1       root       22: #include "paths.h"
                     23: #include "screen.h"
                     24: #include "statusbar.h"
                     25: #include "video.h"
                     26: 
1.1.1.2   root       27: SDL_Window*   sdlWindow;
                     28: SDL_Surface*  sdlscrn = NULL;   /* The SDL screen surface */
                     29: int nScreenZoomX, nScreenZoomY; /* Zooming factors, used for scaling mouse motions */
                     30: 
                     31: /* extern for shortcuts */
                     32: volatile bool bGrabMouse    = false; /* Grab the mouse cursor in the window */
                     33: volatile bool bInFullScreen = false; /* true if in full screen */
                     34: 
                     35: static const int NeXT_SCRN_WIDTH  = 1120;
                     36: static const int NeXT_SCRN_HEIGHT = 832;
1.1       root       37: 
                     38: static SDL_Thread*   repaintThread;
1.1.1.2   root       39: static SDL_Renderer* sdlRenderer;
1.1       root       40: static SDL_sem*      initLatch;
1.1.1.2   root       41: static SDL_atomic_t  blitFB;
                     42: static SDL_atomic_t  blitUI;           /* When value == 1, the repaint thread will blit the sldscrn surface to the screen on the next redraw */
1.1       root       43: static bool          doUIblit;
                     44: static SDL_Rect      saveWindowBounds; /* Window bounds before going fullscreen. Used to restore window size & position. */
                     45: static void*         uiBuffer;         /* uiBuffer used for ui texture */
1.1.1.2   root       46: static void*         uiBufferTmp;      /* Temporary uiBuffer used by repainter */
                     47: static SDL_SpinLock  uiBufferLock;     /* Lock for concurrent access to UI buffer between m68k thread and repainter */
1.1       root       48: static Uint32        mask;             /* green screen mask for transparent UI areas */
                     49: static volatile bool doRepaint  = true; /* Repaint thread runs while true */
1.1.1.2   root       50: static SDL_Rect      statusBar;
                     51: 
1.1       root       52: 
                     53: static Uint32 BW2RGB[0x400];
                     54: static Uint32 COL2RGB[0x10000];
                     55: 
                     56: static Uint32 bw2rgb(SDL_PixelFormat* format, int bw) {
                     57:     switch(bw & 3) {
                     58:         case 3:  return SDL_MapRGB(format, 0,   0,   0);
                     59:         case 2:  return SDL_MapRGB(format, 85,  85,  85);
                     60:         case 1:  return SDL_MapRGB(format, 170, 170, 170);
                     61:         case 0:  return SDL_MapRGB(format, 255, 255, 255);
                     62:         default: return 0;
                     63:     }
                     64: }
                     65: 
                     66: static Uint32 col2rgb(SDL_PixelFormat* format, int col) {
                     67:     int r = col & 0xF000; r >>= 12; r |= r << 4;
                     68:     int g = col & 0x0F00; g >>= 8;  g |= g << 4;
                     69:     int b = col & 0x00F0; b >>= 4;  b |= b << 4;
                     70:     return SDL_MapRGB(format, r,   g,   b);
                     71: }
                     72: 
                     73: /*
                     74:  BW format is 2bit per pixel
                     75:  */
                     76: static void blitBW(SDL_Texture* tex) {
                     77:     void* pixels;
                     78:     int   d;
1.1.1.2   root       79:     int   pitch = (NeXT_SCRN_WIDTH + (ConfigureParams.System.bTurbo ? 0 : 32)) / 4;
1.1       root       80:     SDL_LockTexture(tex, NULL, &pixels, &d);
                     81:     Uint32* dst = (Uint32*)pixels;
1.1.1.2   root       82:     for(int y = 0; y < NeXT_SCRN_HEIGHT; y++) {
1.1       root       83:         int src     = y * pitch;
1.1.1.2   root       84:         for(int x = 0; x < NeXT_SCRN_WIDTH/4; x++, src++) {
1.1       root       85:             int idx = NEXTVideo[src] * 4;
                     86:             *dst++  = BW2RGB[idx+0];
                     87:             *dst++  = BW2RGB[idx+1];
                     88:             *dst++  = BW2RGB[idx+2];
                     89:             *dst++  = BW2RGB[idx+3];
                     90:         }
                     91:     }
                     92:     SDL_UnlockTexture(tex);
                     93: }
                     94: 
                     95: /*
                     96:  Color format is 4bit per pixel, big-endian: RGBx
                     97:  */
                     98: static void blitColor(SDL_Texture* tex) {
                     99:     void* pixels;
                    100:     int   d;
1.1.1.2   root      101:     int pitch = NeXT_SCRN_WIDTH + (ConfigureParams.System.bTurbo ? 0 : 32);
1.1       root      102:     SDL_LockTexture(tex, NULL, &pixels, &d);
                    103:     Uint32* dst = (Uint32*)pixels;
1.1.1.2   root      104:     for(int y = 0; y < NeXT_SCRN_HEIGHT; y++) {
1.1       root      105:         Uint16* src = (Uint16*)NEXTColorVideo + (y*pitch);
1.1.1.2   root      106:         for(int x = 0; x < NeXT_SCRN_WIDTH; x++) {
1.1       root      107:             *dst++ = COL2RGB[*src++];
                    108:         }
                    109:     }
                    110:     SDL_UnlockTexture(tex);
                    111: }
                    112: 
                    113: /*
1.1.1.2   root      114:  Dimension format is 8bit per pixel, big-endian: RRGGBBAA
1.1       root      115:  */
1.1.1.3 ! root      116: void blitDimension(Uint32* vram, SDL_Texture* tex) {
1.1.1.2   root      117: #if ND_STEP
1.1.1.3 ! root      118:     Uint32* src = &vram[0];
1.1.1.2   root      119: #else
1.1.1.3 ! root      120:     Uint32* src = &vram[16];
1.1.1.2   root      121: #endif
1.1       root      122:     int     d;
                    123:     Uint32  format;
                    124:     SDL_QueryTexture(tex, &format, &d, &d, &d);
                    125:     if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
1.1.1.2   root      126:         /* Add big-endian accelerated blit loops as needed here */
1.1       root      127:         switch (format) {
                    128:             default: {
1.1.1.3 ! root      129:                 void*   pixels;
        !           130:                 SDL_LockTexture(tex, NULL, &pixels, &d);
        !           131:                 Uint32* dst = (Uint32*)pixels;
        !           132: 
1.1       root      133:                 /* fallback to SDL_MapRGB */
                    134:                 SDL_PixelFormat* pformat = SDL_AllocFormat(format);
1.1.1.2   root      135:                 for(int y = NeXT_SCRN_HEIGHT; --y >= 0;) {
                    136:                     for(int x = NeXT_SCRN_WIDTH; --x >= 0;) {
1.1       root      137:                         Uint32 v = *src++;
1.1.1.3 ! root      138:                         *dst++   = SDL_MapRGB(pformat, (v >> 8) & 0xFF, (v>>16) & 0xFF, (v>>24) & 0xFF);
1.1       root      139:                     }
1.1.1.2   root      140:                     src += 32;
1.1       root      141:                 }
                    142:                 SDL_FreeFormat(pformat);
1.1.1.3 ! root      143:                 SDL_UnlockTexture(tex);
1.1       root      144:                 break;
                    145:             }
                    146:         }
                    147:     } else {
1.1.1.2   root      148:         /* Add little-endian accelerated blit loops as needed here */
1.1       root      149:         switch (format) {
1.1.1.3 ! root      150:             case SDL_PIXELFORMAT_ARGB8888: {
        !           151:                 SDL_UpdateTexture(tex, NULL, src, (NeXT_SCRN_WIDTH+32)*4);
1.1       root      152:                 break;
1.1.1.3 ! root      153:             }
1.1       root      154:             default: {
1.1.1.3 ! root      155:                 void*   pixels;
        !           156:                 SDL_LockTexture(tex, NULL, &pixels, &d);
        !           157:                 Uint32* dst = (Uint32*)pixels;
        !           158: 
1.1       root      159:                 /* fallback to SDL_MapRGB */
                    160:                 SDL_PixelFormat* pformat = SDL_AllocFormat(format);
1.1.1.2   root      161:                 for(int y = NeXT_SCRN_HEIGHT; --y >= 0;) {
                    162:                     for(int x = NeXT_SCRN_WIDTH; --x >= 0;) {
1.1.1.3 ! root      163:                         Uint32 v = *src++;
        !           164:                         *dst++   = SDL_MapRGB(pformat, (v >> 16) & 0xFF, (v>>8) & 0xFF, (v>>0) & 0xFF);
1.1       root      165:                     }
1.1.1.2   root      166:                     src += 32;
1.1       root      167:                 }
                    168:                 SDL_FreeFormat(pformat);
1.1.1.3 ! root      169:                 SDL_UnlockTexture(tex);
1.1       root      170:                 break;
                    171:             }
                    172:         }
                    173:     }
                    174: }
                    175: 
                    176: /*
                    177:  Blit NeXT framebuffer to texture.
                    178:  */
                    179: static void blitScreen(SDL_Texture* tex) {
                    180:     if (ConfigureParams.Screen.nMonitorType==MONITOR_TYPE_DIMENSION) {
1.1.1.3 ! root      181:         Uint32* vram = nd_vram_for_slot(ND_SLOT(ConfigureParams.Screen.nMonitorNum));
        !           182:         if(vram)
        !           183:             blitDimension(vram, tex);
1.1       root      184:         return;
                    185:     }
                    186:     if(ConfigureParams.System.bColor) {
                    187:         blitColor(tex);
                    188:     } else {
                    189:         blitBW(tex);
                    190:     }
                    191: }
                    192: 
                    193: /*
1.1.1.2   root      194:  Initializes SDL graphics and then enters repaint loop.
                    195:  Loop: Blits the NeXT framebuffer to the fbTexture, blends with the GUI surface and
1.1       root      196:  shows it.
                    197:  */
                    198: static int repainter(void* unused) {
                    199:     int width;
                    200:     int height;
                    201: 
1.1.1.2   root      202:     SDL_SetThreadPriority(SDL_THREAD_PRIORITY_NORMAL);
1.1       root      203:     SDL_GetWindowSize(sdlWindow, &width, &height);
                    204:     
1.1.1.2   root      205:     statusBar.x = 0;
                    206:     statusBar.y = NeXT_SCRN_HEIGHT;
                    207:     statusBar.w = width;
                    208:     statusBar.h = height - NeXT_SCRN_HEIGHT;
                    209:     
1.1       root      210:     SDL_Texture*  uiTexture;
                    211:     SDL_Texture*  fbTexture;
                    212:     
                    213:     Uint32 r, g, b, a;
                    214:     
                    215:     sdlRenderer = SDL_CreateRenderer(sdlWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
                    216:     SDL_RenderSetLogicalSize(sdlRenderer, width, height);
1.1.1.2   root      217:     
1.1       root      218:     uiTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_UNKNOWN, SDL_TEXTUREACCESS_STREAMING, width, height);
                    219:     SDL_SetTextureBlendMode(uiTexture, SDL_BLENDMODE_BLEND);
                    220:     
                    221:     fbTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_UNKNOWN, SDL_TEXTUREACCESS_STREAMING, width, height);
                    222:     SDL_SetTextureBlendMode(fbTexture, SDL_BLENDMODE_NONE);
                    223:     
                    224:     Uint32 format;
                    225:     int    d;
                    226:     SDL_QueryTexture(uiTexture, &format, &d, &d, &d);
                    227:     SDL_PixelFormatEnumToMasks(format, &d, &r, &g, &b, &a);
                    228:     mask = g | a;
1.1.1.2   root      229:     sdlscrn     = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32, r, g, b, a);
                    230:     uiBuffer    = malloc(sdlscrn->h * sdlscrn->pitch);
                    231:     uiBufferTmp = malloc(sdlscrn->h * sdlscrn->pitch);
1.1       root      232:     // clear UI with mask
                    233:     SDL_FillRect(sdlscrn, NULL, mask);
                    234:     
                    235:     /* Exit if we can not open a screen */
                    236:     if (!sdlscrn) {
                    237:         fprintf(stderr, "Could not set video mode:\n %s\n", SDL_GetError() );
                    238:         SDL_Quit();
                    239:         exit(-2);
                    240:     }
                    241:     
                    242:     Statusbar_Init(sdlscrn);
                    243:     
                    244:        if (bGrabMouse) {
                    245:                SDL_SetRelativeMouseMode(SDL_TRUE);
                    246:         SDL_SetWindowGrab(sdlWindow, SDL_TRUE);
                    247:     }
                    248: 
                    249:        /* Configure some SDL stuff: */
                    250:        SDL_ShowCursor(SDL_DISABLE);
                    251:     
                    252:     /* Setup lookup tables */
                    253:     SDL_PixelFormat* pformat = SDL_AllocFormat(format);
                    254:     /* initialize BW lookup table */
                    255:     for(int i = 0; i < 0x100; i++) {
                    256:         BW2RGB[i*4+0] = bw2rgb(pformat, i>>6);
                    257:         BW2RGB[i*4+1] = bw2rgb(pformat, i>>4);
                    258:         BW2RGB[i*4+2] = bw2rgb(pformat, i>>2);
                    259:         BW2RGB[i*4+3] = bw2rgb(pformat, i>>0);
                    260:     }
                    261:     /* initialize color lookup table */
                    262:     for(int i = 0; i < 0x10000; i++)
                    263:         COL2RGB[SDL_BYTEORDER == SDL_BIG_ENDIAN ? i : SDL_Swap16(i)] = col2rgb(pformat, i);
                    264:     
                    265:     /* Initialization done -> signal */
                    266:     SDL_SemPost(initLatch);
                    267:     
1.1.1.2   root      268:     /* Start with framebuffer blit enabled */
                    269:     SDL_AtomicSet(&blitFB, 1);
                    270:     
1.1       root      271:     /* Enter repaint loop */
                    272:     while(doRepaint) {
1.1.1.2   root      273:         bool updateFB = false;
                    274:         bool updateUI = false;
1.1       root      275:         
1.1.1.2   root      276:         if (SDL_AtomicGet(&blitFB)) {
                    277:             // Blit the NeXT framebuffer to textrue
                    278:             blitScreen(fbTexture);
                    279:             updateFB = true;
                    280:         }
1.1       root      281:         
                    282:         // Copy UI surface to texture
1.1.1.2   root      283:         SDL_AtomicLock(&uiBufferLock);
1.1       root      284:         if(SDL_AtomicSet(&blitUI, 0)) {
1.1.1.2   root      285:             // update full UI texture
                    286:             memcpy(uiBufferTmp, uiBuffer, sdlscrn->h * sdlscrn->pitch);
                    287:             updateUI = true;
                    288:         }
                    289:         SDL_AtomicUnlock(&uiBufferLock);
                    290:         
                    291:         if(updateUI) {
                    292:             SDL_UpdateTexture(uiTexture, NULL,       uiBufferTmp, sdlscrn->pitch);
1.1       root      293:         }
                    294:         
1.1.1.2   root      295:         // Update and render UI texture
                    296:         if (updateFB || updateUI) {
                    297:             SDL_RenderClear(sdlRenderer);
                    298:             // Render NeXT framebuffer texture
                    299:             SDL_RenderCopy(sdlRenderer, fbTexture, NULL, NULL);
                    300:             SDL_RenderCopy(sdlRenderer, uiTexture, NULL, NULL);
                    301:             // SDL_RenderPresent sleeps until next VSYNC because of SDL_RENDERER_PRESENTVSYNC in ScreenInit
                    302:             SDL_RenderPresent(sdlRenderer);
                    303:         } else {
                    304:             host_sleep_ms(10);
                    305:         }
1.1       root      306:     }
                    307:     return 0;
                    308: }
                    309: 
                    310: /*-----------------------------------------------------------------------*/
                    311: /**
1.1.1.2   root      312:  * Pause Screen, pauses or resumes drawing of NeXT framebuffer
                    313:  */
                    314: void Screen_Pause(bool pause) {
                    315:     if (pause) {
                    316:         SDL_AtomicSet(&blitFB, 0);
                    317:     } else {
                    318:         SDL_AtomicSet(&blitFB, 1);
                    319:     }
                    320: }
                    321: 
                    322: /*-----------------------------------------------------------------------*/
                    323: /**
                    324:  * Init Screen, creates window and starts repaint thread
1.1       root      325:  */
                    326: void Screen_Init(void) {
                    327:     /* Set initial window resolution */
                    328:     bInFullScreen = ConfigureParams.Screen.bFullScreen;
                    329:     nScreenZoomX  = 1;
                    330:     nScreenZoomY  = 1;
                    331: 
1.1.1.2   root      332:     int width  = NeXT_SCRN_WIDTH;
                    333:     int height = NeXT_SCRN_HEIGHT;
                    334:     
                    335:     /* Statusbar height */
1.1       root      336:     height += Statusbar_SetHeight(width, height);
                    337:     
                    338:     /* Set new video mode */
                    339:     SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
                    340:     
1.1.1.2   root      341:     fprintf(stderr, "SDL screen request: %d x %d (%s)\n", width, height, bInFullScreen ? "fullscreen" : "windowed");
1.1       root      342:     
                    343:     int x = SDL_WINDOWPOS_UNDEFINED;
                    344:     if(ConfigureParams.Screen.nMonitorType == MONITOR_TYPE_DUAL) {
                    345:         for(int i = 0; i < SDL_GetNumVideoDisplays(); i++) {
                    346:             SDL_Rect r;
                    347:             SDL_GetDisplayBounds(i, &r);
                    348:             if(r.w >= width * 2) {
                    349:                 x = r.x + width + ((r.w - width * 2) / 2);
                    350:                 break;
                    351:             }
                    352:             if(r.x >= 0 && SDL_GetNumVideoDisplays() == 1) x = r.x + 8;
                    353:         }
                    354:     }
                    355:     sdlWindow  = SDL_CreateWindow(PROG_NAME, x, SDL_WINDOWPOS_UNDEFINED, width, height, 0);
                    356:     if (!sdlWindow) {
                    357:         fprintf(stderr,"Failed to create window: %s!\n", SDL_GetError());
                    358:         exit(-1);
                    359:     }
                    360: 
                    361:     initLatch     = SDL_CreateSemaphore(0);
                    362:     repaintThread = SDL_CreateThread(repainter, "[Previous] screen repaint", NULL);
                    363:     SDL_SemWait(initLatch);
                    364: }
                    365: 
1.1.1.2   root      366: void nd_sdl_destroy(void);
1.1       root      367: 
                    368: /*-----------------------------------------------------------------------*/
                    369: /**
                    370:  * Free screen bitmap and allocated resources
                    371:  */
                    372: void Screen_UnInit(void) {
                    373:     doRepaint = false; // stop repaint thread
                    374:     int s;
                    375:     SDL_WaitThread(repaintThread, &s);
                    376:     nd_sdl_destroy();
                    377: }
                    378: 
                    379: /*-----------------------------------------------------------------------*/
                    380: /**
                    381:  * Enter Full screen mode
                    382:  */
                    383: void Screen_EnterFullScreen(void) {
                    384:        bool bWasRunning;
                    385: 
                    386:        if (!bInFullScreen) {
                    387:                /* Hold things... */
                    388:                bWasRunning = Main_PauseEmulation(false);
                    389:                bInFullScreen = true;
                    390: 
                    391:         SDL_GetWindowPosition(sdlWindow, &saveWindowBounds.x, &saveWindowBounds.y);
                    392:         SDL_GetWindowSize(sdlWindow, &saveWindowBounds.w, &saveWindowBounds.h);
                    393:         SDL_SetWindowFullscreen(sdlWindow, SDL_WINDOW_FULLSCREEN_DESKTOP);
                    394:                SDL_Delay(20);                  /* To give monitor time to change to new resolution */
                    395:                
                    396:                if (bWasRunning) {
                    397:                        /* And off we go... */
                    398:                        Main_UnPauseEmulation();
                    399:                }
                    400:                SDL_SetRelativeMouseMode(SDL_TRUE);
                    401:         SDL_SetWindowGrab(sdlWindow, SDL_TRUE);
                    402:        }
                    403: }
                    404: 
                    405: /*-----------------------------------------------------------------------*/
                    406: /**
                    407:  * Return from Full screen mode back to a window
                    408:  */
                    409: void Screen_ReturnFromFullScreen(void) {
                    410:        bool bWasRunning;
                    411: 
                    412:        if (bInFullScreen) {
                    413:                /* Hold things... */
                    414:                bWasRunning = Main_PauseEmulation(false);
                    415:                bInFullScreen = false;
                    416: 
                    417:         SDL_SetWindowFullscreen(sdlWindow, 0);
                    418:                SDL_Delay(20);                /* To give monitor time to switch resolution */
                    419:         SDL_SetWindowPosition(sdlWindow, saveWindowBounds.x, saveWindowBounds.y);
                    420:         SDL_SetWindowSize(sdlWindow, saveWindowBounds.w, saveWindowBounds.h);
                    421:         
                    422:                if (bWasRunning) {
                    423:                        /* And off we go... */
                    424:                        Main_UnPauseEmulation();
                    425:                }
                    426: 
                    427:                if (!bGrabMouse) {
                    428:                        /* Un-grab mouse pointer in windowed mode */
                    429:                        SDL_SetRelativeMouseMode(SDL_FALSE);
                    430:             SDL_SetWindowGrab(sdlWindow, SDL_FALSE);
                    431:                }
                    432:        }
                    433: }
                    434: 
                    435: /*-----------------------------------------------------------------------*/
                    436: /**
1.1.1.2   root      437:  * Force things associated with changing between fullscreen/windowed
1.1       root      438:  */
                    439: void Screen_ModeChanged(void) {
                    440:        if (!sdlscrn) {
                    441:                /* screen not yet initialized */
                    442:                return;
                    443:        }
                    444:        if (bInFullScreen || bGrabMouse) {
                    445:                SDL_SetRelativeMouseMode(SDL_TRUE);
                    446:         SDL_SetWindowGrab(sdlWindow, SDL_TRUE);
                    447:        } else {
                    448:                SDL_SetRelativeMouseMode(SDL_FALSE);
                    449:         SDL_SetWindowGrab(sdlWindow, SDL_FALSE);
                    450:     }
                    451: }
                    452: 
1.1.1.2   root      453: 
1.1       root      454: /*-----------------------------------------------------------------------*/
                    455: /**
1.1.1.2   root      456:  * Draw screen to window/full-screen - (SC) Just status bar updates. Screen redraw is done in repaint thread.
1.1       root      457:  */
1.1.1.2   root      458: 
                    459: static bool shieldStatusBarUpdate;
                    460: 
                    461: static void statusBarUpdate(void) {
                    462:     if(shieldStatusBarUpdate) return;
                    463:     SDL_LockSurface(sdlscrn);
                    464:     SDL_AtomicLock(&uiBufferLock);
                    465:     memcpy(&((Uint8*)uiBuffer)[statusBar.y*sdlscrn->pitch], &((Uint8*)sdlscrn->pixels)[statusBar.y*sdlscrn->pitch], statusBar.h * sdlscrn->pitch);
                    466:     SDL_AtomicSet(&blitUI, 1);
                    467:     SDL_AtomicUnlock(&uiBufferLock);
                    468:     SDL_UnlockSurface(sdlscrn);
                    469: }
                    470: 
                    471: bool Update_StatusBar(void) {
                    472:     shieldStatusBarUpdate = true;
1.1       root      473:     Statusbar_OverlayBackup(sdlscrn);
                    474:     Statusbar_Update(sdlscrn);
1.1.1.2   root      475:     shieldStatusBarUpdate = false;
1.1       root      476: 
1.1.1.2   root      477:     statusBarUpdate();
                    478:     
1.1       root      479:     return !bQuitProgram;
                    480: }
                    481: 
1.1.1.2   root      482: /*
                    483:  Copy UI SDL surface to uiBuffer and replace mask pixels with transparent pixels for
                    484:  UI blending with framebuffer texture.
                    485: */
                    486: static void uiUpdate(void) {
1.1       root      487:     SDL_LockSurface(sdlscrn);
                    488:     int     count = sdlscrn->w * sdlscrn->h;
                    489:     Uint32* dst   = (Uint32*)uiBuffer;
                    490:     Uint32* src   = (Uint32*)sdlscrn->pixels;
                    491:     SDL_AtomicLock(&uiBufferLock);
                    492:     // poor man's green-screen - would be nice if SDL had more blending modes...
                    493:     for(int i = count; --i >= 0; src++)
                    494:         *dst++ = *src == mask ? 0 : *src;
1.1.1.2   root      495:     SDL_AtomicSet(&blitUI, 1);
1.1       root      496:     SDL_AtomicUnlock(&uiBufferLock);
                    497:     SDL_UnlockSurface(sdlscrn);
                    498: }
                    499: 
                    500: void SDL_UpdateRects(SDL_Surface *screen, int numrects, SDL_Rect *rects) {
                    501:     while(numrects--) {
1.1.1.2   root      502:         if(rects->y < NeXT_SCRN_HEIGHT) {
1.1       root      503:             uiUpdate();
                    504:             doUIblit = true;
                    505:         } else {
                    506:             if(doUIblit) {
                    507:                 uiUpdate();
                    508:                 doUIblit = false;
                    509:             } else {
1.1.1.2   root      510:                 statusBarUpdate();
1.1       root      511:             }
                    512:         }
                    513:     }
                    514: }
                    515: 
                    516: void SDL_UpdateRect(SDL_Surface *screen, Sint32 x, Sint32 y, Sint32 w, Sint32 h) {
                    517:     SDL_Rect rect = { x, y, w, h };
                    518:     SDL_UpdateRects(screen, 1, &rect);
                    519: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.