Annotation of previous_trunk/src/fast_screen.c, revision 1.1

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

unix.superglobalmegacorp.com

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