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

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"
                     20: #include "dimension.h"
                     21: #include "paths.h"
                     22: #include "screen.h"
                     23: #include "control.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:  */
                    116: void blitDimension(SDL_Texture* tex) {
1.1.1.2 ! root      117: #if ND_STEP
        !           118:     Uint32* src = (Uint32*)&ND_vram[0];
        !           119: #else
        !           120:     Uint32* src = (Uint32*)&ND_vram[16];
        !           121: #endif
1.1       root      122:     void*   pixels;
                    123:     int     d;
                    124:     Uint32  format;
                    125:     SDL_QueryTexture(tex, &format, &d, &d, &d);
                    126:     SDL_LockTexture(tex, NULL, &pixels, &d);
                    127:     Uint32* dst = (Uint32*)pixels;
                    128:     if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
1.1.1.2 ! root      129:         /* Add big-endian accelerated blit loops as needed here */
1.1       root      130:         switch (format) {
                    131:             default: {
                    132:                 /* fallback to SDL_MapRGB */
                    133:                 SDL_PixelFormat* pformat = SDL_AllocFormat(format);
1.1.1.2 ! root      134:                 for(int y = NeXT_SCRN_HEIGHT; --y >= 0;) {
        !           135:                     for(int x = NeXT_SCRN_WIDTH; --x >= 0;) {
1.1       root      136:                         Uint32 v = *src++;
                    137:                         *dst++   = SDL_MapRGB(pformat, (v >> 24) & 0xFF, (v>>16) & 0xFF, (v>>8) & 0xFF);
                    138:                     }
1.1.1.2 ! root      139:                     src += 32;
1.1       root      140:                 }
                    141:                 SDL_FreeFormat(pformat);
                    142:                 break;
                    143:             }
                    144:         }
                    145:     } else {
1.1.1.2 ! root      146:         /* Add little-endian accelerated blit loops as needed here */
1.1       root      147:         switch (format) {
                    148:             case SDL_PIXELFORMAT_ARGB8888:
1.1.1.2 ! root      149:                 for(int y = NeXT_SCRN_HEIGHT; --y >= 0;) {
        !           150:                     for(int x = NeXT_SCRN_WIDTH; --x >= 0;) {
1.1       root      151:                         // Uint32 LE: AABBGGRR
                    152:                         // Target:    AARRGGBB
                    153:                         Uint32 v = *src++;
                    154:                         *dst++   = (v & 0xFF000000) | ((v<<16) &0x00FF0000) | (v &0x0000FF00) | ((v>>16) &0x000000FF);
                    155:                     }
1.1.1.2 ! root      156:                     src += 32;
1.1       root      157:                 }
                    158:                 break;
                    159:             default: {
                    160:                 /* fallback to SDL_MapRGB */
                    161:                 SDL_PixelFormat* pformat = SDL_AllocFormat(format);
1.1.1.2 ! root      162:                 for(int y = NeXT_SCRN_HEIGHT; --y >= 0;) {
        !           163:                     for(int x = NeXT_SCRN_WIDTH; --x >= 0;) {
1.1       root      164:                         Uint32 v = SDL_Swap32(*src++);
                    165:                         *dst++   = SDL_MapRGB(pformat, (v >> 24) & 0xFF, (v>>16) & 0xFF, (v>>8) & 0xFF);
                    166:                     }
1.1.1.2 ! root      167:                     src += 32;
1.1       root      168:                 }
                    169:                 SDL_FreeFormat(pformat);
                    170:                 break;
                    171:             }
                    172:         }
                    173:     }
                    174:     SDL_UnlockTexture(tex);
                    175: }
                    176: 
                    177: /*
                    178:  Blit NeXT framebuffer to texture.
                    179:  */
                    180: static void blitScreen(SDL_Texture* tex) {
                    181:     if (ConfigureParams.Screen.nMonitorType==MONITOR_TYPE_DIMENSION) {
                    182:         blitDimension(tex);
                    183:         return;
                    184:     }
                    185:     if(ConfigureParams.System.bColor) {
                    186:         blitColor(tex);
                    187:     } else {
                    188:         blitBW(tex);
                    189:     }
                    190: }
                    191: 
                    192: /*
1.1.1.2 ! root      193:  Initializes SDL graphics and then enters repaint loop.
        !           194:  Loop: Blits the NeXT framebuffer to the fbTexture, blends with the GUI surface and
1.1       root      195:  shows it.
                    196:  */
                    197: static int repainter(void* unused) {
                    198:     int width;
                    199:     int height;
                    200: 
1.1.1.2 ! root      201:     SDL_SetThreadPriority(SDL_THREAD_PRIORITY_NORMAL);
1.1       root      202:     SDL_GetWindowSize(sdlWindow, &width, &height);
                    203:     
1.1.1.2 ! root      204:     statusBar.x = 0;
        !           205:     statusBar.y = NeXT_SCRN_HEIGHT;
        !           206:     statusBar.w = width;
        !           207:     statusBar.h = height - NeXT_SCRN_HEIGHT;
        !           208:     
1.1       root      209:     SDL_Texture*  uiTexture;
                    210:     SDL_Texture*  fbTexture;
                    211:     
                    212:     Uint32 r, g, b, a;
                    213:     
                    214:     sdlRenderer = SDL_CreateRenderer(sdlWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
                    215:     SDL_RenderSetLogicalSize(sdlRenderer, width, height);
1.1.1.2 ! root      216:     
1.1       root      217:     uiTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_UNKNOWN, SDL_TEXTUREACCESS_STREAMING, width, height);
                    218:     SDL_SetTextureBlendMode(uiTexture, SDL_BLENDMODE_BLEND);
                    219:     
                    220:     fbTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_UNKNOWN, SDL_TEXTUREACCESS_STREAMING, width, height);
                    221:     SDL_SetTextureBlendMode(fbTexture, SDL_BLENDMODE_NONE);
                    222:     
                    223:     Uint32 format;
                    224:     int    d;
                    225:     SDL_QueryTexture(uiTexture, &format, &d, &d, &d);
                    226:     SDL_PixelFormatEnumToMasks(format, &d, &r, &g, &b, &a);
                    227:     mask = g | a;
1.1.1.2 ! root      228:     sdlscrn     = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32, r, g, b, a);
        !           229:     uiBuffer    = malloc(sdlscrn->h * sdlscrn->pitch);
        !           230:     uiBufferTmp = malloc(sdlscrn->h * sdlscrn->pitch);
1.1       root      231:     // clear UI with mask
                    232:     SDL_FillRect(sdlscrn, NULL, mask);
                    233:     
                    234:     /* Exit if we can not open a screen */
                    235:     if (!sdlscrn) {
                    236:         fprintf(stderr, "Could not set video mode:\n %s\n", SDL_GetError() );
                    237:         SDL_Quit();
                    238:         exit(-2);
                    239:     }
                    240:     
                    241:     if (!bInFullScreen) {
                    242:         /* re-embed the new SDL window */
                    243:         Control_ReparentWindow(width, height, bInFullScreen);
                    244:     }
                    245:     
                    246:     Statusbar_Init(sdlscrn);
                    247:     
                    248:        if (bGrabMouse) {
                    249:                SDL_SetRelativeMouseMode(SDL_TRUE);
                    250:         SDL_SetWindowGrab(sdlWindow, SDL_TRUE);
                    251:     }
                    252: 
                    253:        /* Configure some SDL stuff: */
                    254:        SDL_ShowCursor(SDL_DISABLE);
                    255:     
                    256:     /* Setup lookup tables */
                    257:     SDL_PixelFormat* pformat = SDL_AllocFormat(format);
                    258:     /* initialize BW lookup table */
                    259:     for(int i = 0; i < 0x100; i++) {
                    260:         BW2RGB[i*4+0] = bw2rgb(pformat, i>>6);
                    261:         BW2RGB[i*4+1] = bw2rgb(pformat, i>>4);
                    262:         BW2RGB[i*4+2] = bw2rgb(pformat, i>>2);
                    263:         BW2RGB[i*4+3] = bw2rgb(pformat, i>>0);
                    264:     }
                    265:     /* initialize color lookup table */
                    266:     for(int i = 0; i < 0x10000; i++)
                    267:         COL2RGB[SDL_BYTEORDER == SDL_BIG_ENDIAN ? i : SDL_Swap16(i)] = col2rgb(pformat, i);
                    268:     
                    269:     /* Initialization done -> signal */
                    270:     SDL_SemPost(initLatch);
                    271:     
1.1.1.2 ! root      272:     /* Start with framebuffer blit enabled */
        !           273:     SDL_AtomicSet(&blitFB, 1);
        !           274:     
1.1       root      275:     /* Enter repaint loop */
                    276:     while(doRepaint) {
1.1.1.2 ! root      277:         bool updateFB = false;
        !           278:         bool updateUI = false;
1.1       root      279:         
1.1.1.2 ! root      280:         if (SDL_AtomicGet(&blitFB)) {
        !           281:             // Blit the NeXT framebuffer to textrue
        !           282:             blitScreen(fbTexture);
        !           283:             updateFB = true;
        !           284:         }
1.1       root      285:         
                    286:         // Copy UI surface to texture
1.1.1.2 ! root      287:         SDL_AtomicLock(&uiBufferLock);
1.1       root      288:         if(SDL_AtomicSet(&blitUI, 0)) {
1.1.1.2 ! root      289:             // update full UI texture
        !           290:             memcpy(uiBufferTmp, uiBuffer, sdlscrn->h * sdlscrn->pitch);
        !           291:             updateUI = true;
        !           292:         }
        !           293:         SDL_AtomicUnlock(&uiBufferLock);
        !           294:         
        !           295:         if(updateUI) {
        !           296:             SDL_UpdateTexture(uiTexture, NULL,       uiBufferTmp, sdlscrn->pitch);
1.1       root      297:         }
                    298:         
1.1.1.2 ! root      299:         // Update and render UI texture
        !           300:         if (updateFB || updateUI) {
        !           301:             SDL_RenderClear(sdlRenderer);
        !           302:             // Render NeXT framebuffer texture
        !           303:             SDL_RenderCopy(sdlRenderer, fbTexture, NULL, NULL);
        !           304:             SDL_RenderCopy(sdlRenderer, uiTexture, NULL, NULL);
        !           305:             // SDL_RenderPresent sleeps until next VSYNC because of SDL_RENDERER_PRESENTVSYNC in ScreenInit
        !           306:             SDL_RenderPresent(sdlRenderer);
        !           307:         } else {
        !           308:             host_sleep_ms(10);
        !           309:         }
1.1       root      310:     }
                    311:     return 0;
                    312: }
                    313: 
                    314: /*-----------------------------------------------------------------------*/
                    315: /**
1.1.1.2 ! root      316:  * Pause Screen, pauses or resumes drawing of NeXT framebuffer
        !           317:  */
        !           318: void Screen_Pause(bool pause) {
        !           319:     if (pause) {
        !           320:         SDL_AtomicSet(&blitFB, 0);
        !           321:     } else {
        !           322:         SDL_AtomicSet(&blitFB, 1);
        !           323:     }
        !           324: }
        !           325: 
        !           326: /*-----------------------------------------------------------------------*/
        !           327: /**
        !           328:  * Init Screen, creates window and starts repaint thread
1.1       root      329:  */
                    330: void Screen_Init(void) {
                    331:     /* Set initial window resolution */
                    332:     bInFullScreen = ConfigureParams.Screen.bFullScreen;
                    333:     nScreenZoomX  = 1;
                    334:     nScreenZoomY  = 1;
                    335: 
1.1.1.2 ! root      336:     int width  = NeXT_SCRN_WIDTH;
        !           337:     int height = NeXT_SCRN_HEIGHT;
        !           338:     
        !           339:     /* Statusbar height */
1.1       root      340:     height += Statusbar_SetHeight(width, height);
                    341:     
                    342:     if (bInFullScreen) {
                    343:         /* unhide the WM window for fullscreen */
                    344:         Control_ReparentWindow(width, height, bInFullScreen);
                    345:     }
                    346:     
                    347:     /* Set new video mode */
                    348:     SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
                    349:     
1.1.1.2 ! root      350:     fprintf(stderr, "SDL screen request: %d x %d (%s)\n", width, height, bInFullScreen ? "fullscreen" : "windowed");
1.1       root      351:     
                    352:     int x = SDL_WINDOWPOS_UNDEFINED;
                    353:     if(ConfigureParams.Screen.nMonitorType == MONITOR_TYPE_DUAL) {
                    354:         for(int i = 0; i < SDL_GetNumVideoDisplays(); i++) {
                    355:             SDL_Rect r;
                    356:             SDL_GetDisplayBounds(i, &r);
                    357:             if(r.w >= width * 2) {
                    358:                 x = r.x + width + ((r.w - width * 2) / 2);
                    359:                 break;
                    360:             }
                    361:             if(r.x >= 0 && SDL_GetNumVideoDisplays() == 1) x = r.x + 8;
                    362:         }
                    363:     }
                    364:     sdlWindow  = SDL_CreateWindow(PROG_NAME, x, SDL_WINDOWPOS_UNDEFINED, width, height, 0);
                    365:     if (!sdlWindow) {
                    366:         fprintf(stderr,"Failed to create window: %s!\n", SDL_GetError());
                    367:         exit(-1);
                    368:     }
                    369: 
                    370:     initLatch     = SDL_CreateSemaphore(0);
                    371:     repaintThread = SDL_CreateThread(repainter, "[Previous] screen repaint", NULL);
                    372:     SDL_SemWait(initLatch);
                    373: }
                    374: 
1.1.1.2 ! root      375: void nd_sdl_destroy(void);
1.1       root      376: 
                    377: /*-----------------------------------------------------------------------*/
                    378: /**
                    379:  * Free screen bitmap and allocated resources
                    380:  */
                    381: void Screen_UnInit(void) {
                    382:     doRepaint = false; // stop repaint thread
                    383:     int s;
                    384:     SDL_WaitThread(repaintThread, &s);
                    385:     nd_sdl_destroy();
                    386: }
                    387: 
                    388: /*-----------------------------------------------------------------------*/
                    389: /**
                    390:  * Enter Full screen mode
                    391:  */
                    392: void Screen_EnterFullScreen(void) {
                    393:        bool bWasRunning;
                    394: 
                    395:        if (!bInFullScreen) {
                    396:                /* Hold things... */
                    397:                bWasRunning = Main_PauseEmulation(false);
                    398:                bInFullScreen = true;
                    399: 
                    400:         SDL_GetWindowPosition(sdlWindow, &saveWindowBounds.x, &saveWindowBounds.y);
                    401:         SDL_GetWindowSize(sdlWindow, &saveWindowBounds.w, &saveWindowBounds.h);
                    402:         SDL_SetWindowFullscreen(sdlWindow, SDL_WINDOW_FULLSCREEN_DESKTOP);
                    403:                SDL_Delay(20);                  /* To give monitor time to change to new resolution */
                    404:                
                    405:                if (bWasRunning) {
                    406:                        /* And off we go... */
                    407:                        Main_UnPauseEmulation();
                    408:                }
                    409:                SDL_SetRelativeMouseMode(SDL_TRUE);
                    410:         SDL_SetWindowGrab(sdlWindow, SDL_TRUE);
                    411:        }
                    412: }
                    413: 
                    414: /*-----------------------------------------------------------------------*/
                    415: /**
                    416:  * Return from Full screen mode back to a window
                    417:  */
                    418: void Screen_ReturnFromFullScreen(void) {
                    419:        bool bWasRunning;
                    420: 
                    421:        if (bInFullScreen) {
                    422:                /* Hold things... */
                    423:                bWasRunning = Main_PauseEmulation(false);
                    424:                bInFullScreen = false;
                    425: 
                    426:         SDL_SetWindowFullscreen(sdlWindow, 0);
                    427:                SDL_Delay(20);                /* To give monitor time to switch resolution */
                    428:         SDL_SetWindowPosition(sdlWindow, saveWindowBounds.x, saveWindowBounds.y);
                    429:         SDL_SetWindowSize(sdlWindow, saveWindowBounds.w, saveWindowBounds.h);
                    430:         
                    431:                if (bWasRunning) {
                    432:                        /* And off we go... */
                    433:                        Main_UnPauseEmulation();
                    434:                }
                    435: 
                    436:                if (!bGrabMouse) {
                    437:                        /* Un-grab mouse pointer in windowed mode */
                    438:                        SDL_SetRelativeMouseMode(SDL_FALSE);
                    439:             SDL_SetWindowGrab(sdlWindow, SDL_FALSE);
                    440:                }
                    441:        }
                    442: }
                    443: 
                    444: /*-----------------------------------------------------------------------*/
                    445: /**
1.1.1.2 ! root      446:  * Force things associated with changing between fullscreen/windowed
1.1       root      447:  */
                    448: void Screen_ModeChanged(void) {
                    449:        if (!sdlscrn) {
                    450:                /* screen not yet initialized */
                    451:                return;
                    452:        }
                    453:        if (bInFullScreen || bGrabMouse) {
                    454:                SDL_SetRelativeMouseMode(SDL_TRUE);
                    455:         SDL_SetWindowGrab(sdlWindow, SDL_TRUE);
                    456:        } else {
                    457:                SDL_SetRelativeMouseMode(SDL_FALSE);
                    458:         SDL_SetWindowGrab(sdlWindow, SDL_FALSE);
                    459:     }
                    460: }
                    461: 
1.1.1.2 ! root      462: 
1.1       root      463: /*-----------------------------------------------------------------------*/
                    464: /**
1.1.1.2 ! root      465:  * Draw screen to window/full-screen - (SC) Just status bar updates. Screen redraw is done in repaint thread.
1.1       root      466:  */
1.1.1.2 ! root      467: 
        !           468: static bool shieldStatusBarUpdate;
        !           469: 
        !           470: static void statusBarUpdate(void) {
        !           471:     if(shieldStatusBarUpdate) return;
        !           472:     SDL_LockSurface(sdlscrn);
        !           473:     SDL_AtomicLock(&uiBufferLock);
        !           474:     memcpy(&((Uint8*)uiBuffer)[statusBar.y*sdlscrn->pitch], &((Uint8*)sdlscrn->pixels)[statusBar.y*sdlscrn->pitch], statusBar.h * sdlscrn->pitch);
        !           475:     SDL_AtomicSet(&blitUI, 1);
        !           476:     SDL_AtomicUnlock(&uiBufferLock);
        !           477:     SDL_UnlockSurface(sdlscrn);
        !           478: }
        !           479: 
        !           480: bool Update_StatusBar(void) {
        !           481:     shieldStatusBarUpdate = true;
1.1       root      482:     Statusbar_OverlayBackup(sdlscrn);
                    483:     Statusbar_Update(sdlscrn);
1.1.1.2 ! root      484:     shieldStatusBarUpdate = false;
1.1       root      485: 
1.1.1.2 ! root      486:     statusBarUpdate();
        !           487:     
1.1       root      488:     return !bQuitProgram;
                    489: }
                    490: 
1.1.1.2 ! root      491: /*
        !           492:  Copy UI SDL surface to uiBuffer and replace mask pixels with transparent pixels for
        !           493:  UI blending with framebuffer texture.
        !           494: */
        !           495: static void uiUpdate(void) {
1.1       root      496:     SDL_LockSurface(sdlscrn);
                    497:     int     count = sdlscrn->w * sdlscrn->h;
                    498:     Uint32* dst   = (Uint32*)uiBuffer;
                    499:     Uint32* src   = (Uint32*)sdlscrn->pixels;
                    500:     SDL_AtomicLock(&uiBufferLock);
                    501:     // poor man's green-screen - would be nice if SDL had more blending modes...
                    502:     for(int i = count; --i >= 0; src++)
                    503:         *dst++ = *src == mask ? 0 : *src;
1.1.1.2 ! root      504:     SDL_AtomicSet(&blitUI, 1);
1.1       root      505:     SDL_AtomicUnlock(&uiBufferLock);
                    506:     SDL_UnlockSurface(sdlscrn);
                    507: }
                    508: 
                    509: void SDL_UpdateRects(SDL_Surface *screen, int numrects, SDL_Rect *rects) {
                    510:     while(numrects--) {
1.1.1.2 ! root      511:         if(rects->y < NeXT_SCRN_HEIGHT) {
1.1       root      512:             uiUpdate();
                    513:             doUIblit = true;
                    514:         } else {
                    515:             if(doUIblit) {
                    516:                 uiUpdate();
                    517:                 doUIblit = false;
                    518:             } else {
1.1.1.2 ! root      519:                 statusBarUpdate();
1.1       root      520:             }
                    521:         }
                    522:     }
                    523: }
                    524: 
                    525: void SDL_UpdateRect(SDL_Surface *screen, Sint32 x, Sint32 y, Sint32 w, Sint32 h) {
                    526:     SDL_Rect rect = { x, y, w, h };
                    527:     SDL_UpdateRects(screen, 1, &rect);
                    528: }

unix.superglobalmegacorp.com

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