DOSBox-X
|
00001 #include <sys/types.h> 00002 #include <assert.h> 00003 #include <math.h> 00004 00005 #include "dosbox.h" 00006 #include "sdlmain.h" 00007 #include "vga.h" 00008 00009 using namespace std; 00010 00011 // output API below 00012 00013 void OUTPUT_SURFACE_Initialize() 00014 { 00015 // nothing to initialize (yet?) 00016 } 00017 00018 void OUTPUT_SURFACE_Select() 00019 { 00020 sdl.desktop.want_type = SCREEN_SURFACE; 00021 render.aspectOffload = false; 00022 00023 #if defined(WIN32) && !defined(C_SDL2) 00024 SDL1_hax_inhibit_WM_PAINT = 0; 00025 #endif 00026 } 00027 00028 bool OUTPUT_SURFACE_StartUpdate(Bit8u* &pixels, Bitu &pitch) 00029 { 00030 #if C_XBRZ 00031 if (sdl_xbrz.enable && sdl_xbrz.scale_on) 00032 { 00033 sdl_xbrz.renderbuf.resize(sdl.draw.width * sdl.draw.height); 00034 pixels = sdl_xbrz.renderbuf.empty() ? nullptr : reinterpret_cast<Bit8u*>(&sdl_xbrz.renderbuf[0]); 00035 pitch = sdl.draw.width * sizeof(uint32_t); 00036 } 00037 else 00038 #endif 00039 #if C_SURFACE_POSTRENDER_ASPECT 00040 if (render.aspect == ASPECT_NEAREST || render.aspect == ASPECT_BILINEAR) 00041 { 00042 sdl.aspectbuf.resize(sdl.draw.width * sdl.draw.height); 00043 pixels = sdl.aspectbuf.empty() ? nullptr : reinterpret_cast<Bit8u*>(&sdl.aspectbuf[0]); 00044 pitch = sdl.draw.width * sizeof(uint32_t); 00045 } 00046 else 00047 #endif 00048 { 00049 if (sdl.blit.surface) 00050 { 00051 if (SDL_MUSTLOCK(sdl.blit.surface) && SDL_LockSurface(sdl.blit.surface)) 00052 return false; 00053 pixels = (Bit8u *)sdl.blit.surface->pixels; 00054 pitch = sdl.blit.surface->pitch; 00055 } 00056 else 00057 { 00058 if (SDL_MUSTLOCK(sdl.surface) && SDL_LockSurface(sdl.surface)) 00059 return false; 00060 pixels = (Bit8u *)sdl.surface->pixels; 00061 pixels += sdl.clip.y * sdl.surface->pitch; 00062 pixels += sdl.clip.x * sdl.surface->format->BytesPerPixel; 00063 pitch = sdl.surface->pitch; 00064 } 00065 } 00066 00067 GFX_SDL_Overscan(); 00068 sdl.updating = true; 00069 return true; 00070 } 00071 00072 void OUTPUT_SURFACE_EndUpdate(const Bit16u *changedLines) 00073 { 00074 #if DOSBOXMENU_TYPE == DOSBOXMENU_SDLDRAW 00075 GFX_DrawSDLMenu(mainMenu, mainMenu.display_list); 00076 #endif 00077 #if C_XBRZ 00078 if (sdl_xbrz.enable && sdl_xbrz.scale_on) 00079 { 00080 const Bit32u srcWidth = sdl.draw.width; 00081 const Bit32u srcHeight = sdl.draw.height; 00082 if (sdl_xbrz.renderbuf.size() == (unsigned int)srcWidth * (unsigned int)srcHeight && srcWidth > 0 && srcHeight > 0) 00083 { 00084 // please use sdl.clip to keep screen positioning consistent with the rest of the emulator 00085 int clipWidth = sdl.clip.w; 00086 int clipHeight = sdl.clip.h; 00087 int clipX = sdl.clip.x; 00088 int clipY = sdl.clip.y; 00089 00090 // 1. xBRZ-scale render buffer into xbrz pixel buffer 00091 unsigned int xbrzWidth = 0; 00092 unsigned int xbrzHeight = 0; 00093 uint32_t* xbrzBuf; 00094 xbrzWidth = srcWidth * (unsigned int)sdl_xbrz.scale_factor; 00095 xbrzHeight = srcHeight * (unsigned int)sdl_xbrz.scale_factor; 00096 sdl_xbrz.pixbuf.resize(xbrzWidth * xbrzHeight); 00097 00098 const uint32_t* renderBuf = &sdl_xbrz.renderbuf[0]; // help VS compiler a little + support capture by value 00099 xbrzBuf = &sdl_xbrz.pixbuf[0]; 00100 xBRZ_Render(renderBuf, xbrzBuf, changedLines, (int)srcWidth, (int)srcHeight, sdl_xbrz.scale_factor); 00101 00102 // 2. nearest neighbor/bilinear scale xbrz buffer into output surface clipping area 00103 const bool mustLock = SDL_MUSTLOCK(sdl.surface); 00104 if (mustLock) SDL_LockSurface(sdl.surface); 00105 if (sdl.surface->pixels) // if locking fails, this can be nullptr, also check if we really need to draw 00106 { 00107 uint32_t* clipTrg = reinterpret_cast<uint32_t*>(static_cast<char*>(sdl.surface->pixels) + clipY * sdl.surface->pitch + (unsigned int)clipX * sizeof(uint32_t)); 00108 xBRZ_PostScale(&xbrzBuf[0], (int)xbrzWidth, (int)xbrzHeight, (int)(xbrzWidth * sizeof(uint32_t)), 00109 &clipTrg[0], clipWidth, clipHeight, sdl.surface->pitch, 00110 sdl_xbrz.postscale_bilinear, sdl_xbrz.task_granularity); 00111 } 00112 00113 if (mustLock) SDL_UnlockSurface(sdl.surface); 00114 if (!menu.hidecycles && !sdl.desktop.fullscreen) frames++; 00115 #if defined(C_SDL2) 00116 SDL_UpdateWindowSurface(sdl.window); 00117 #else 00118 SDL_Flip(sdl.surface); 00119 #endif 00120 } 00121 } 00122 else 00123 #endif /*C_XBRZ*/ 00124 #if C_SURFACE_POSTRENDER_ASPECT 00125 if (render.aspect == ASPECT_NEAREST || render.aspect == ASPECT_BILINEAR) { 00126 // here we go, adjusting source aspect ratio 00127 int clipWidth = sdl.clip.w; 00128 int clipHeight = sdl.clip.h; 00129 int clipX = sdl.clip.x; 00130 int clipY = sdl.clip.y; 00131 00132 const bool mustLock = SDL_MUSTLOCK(sdl.surface); 00133 if (mustLock) SDL_LockSurface(sdl.surface); 00134 if (sdl.surface->pixels) // if locking fails, this can be nullptr, also check if we really need to draw 00135 { 00136 uint32_t* clipTrg = reinterpret_cast<uint32_t*>(static_cast<char*>(sdl.surface->pixels) + clipY * sdl.surface->pitch + clipX * sizeof(uint32_t)); 00137 xBRZ_PostScale(&sdl.aspectbuf[0], sdl.draw.width, sdl.draw.height, sdl.draw.width * sizeof(uint32_t), 00138 &clipTrg[0], clipWidth, clipHeight, sdl.surface->pitch, 00139 (render.aspect == ASPECT_BILINEAR), C_SURFACE_POSTRENDER_ASPECT_BATCH_SIZE); 00140 } 00141 00142 if (mustLock) SDL_UnlockSurface(sdl.surface); 00143 if (!menu.hidecycles && !sdl.desktop.fullscreen) frames++; 00144 #if defined(C_SDL2) 00145 SDL_UpdateWindowSurfaceRects(sdl.window, sdl.updateRects, 1); 00146 #else 00147 SDL_Flip(sdl.surface); 00148 #endif 00149 } 00150 else 00151 #endif /*C_SURFACE_POSTRENDER_ASPECT*/ 00152 { 00153 if (SDL_MUSTLOCK(sdl.surface)) { 00154 if (sdl.blit.surface) { 00155 SDL_UnlockSurface(sdl.blit.surface); 00156 int Blit = SDL_BlitSurface(sdl.blit.surface, 0, sdl.surface, &sdl.clip); 00157 LOG(LOG_MISC, LOG_WARN)("BlitSurface returned %d", Blit); 00158 } 00159 else { 00160 SDL_UnlockSurface(sdl.surface); 00161 } 00162 if (changedLines && (changedLines[0] == sdl.draw.height)) 00163 return; 00164 if (!menu.hidecycles && !sdl.desktop.fullscreen) frames++; 00165 #if defined(C_SDL2) 00166 SDL_UpdateWindowSurface(sdl.window); 00167 #else 00168 SDL_Flip(sdl.surface); 00169 #endif 00170 } 00171 else if (sdl.must_redraw_all) { 00172 #if defined(C_SDL2) 00173 if (changedLines != NULL) SDL_UpdateWindowSurface(sdl.window); 00174 #else 00175 if (changedLines != NULL) SDL_Flip(sdl.surface); 00176 #endif 00177 } 00178 else if (changedLines) { 00179 if (changedLines[0] == sdl.draw.height) 00180 return; 00181 if (!menu.hidecycles && !sdl.desktop.fullscreen) frames++; 00182 Bitu y = 0, index = 0, rectCount = 0; 00183 while (y < sdl.draw.height) { 00184 if (!(index & 1)) { 00185 y += changedLines[index]; 00186 } 00187 else { 00188 SDL_Rect *rect = &sdl.updateRects[rectCount++]; 00189 rect->x = sdl.clip.x; 00190 rect->y = sdl.clip.y + (int)y; 00191 rect->w = (Bit16u)sdl.draw.width; 00192 rect->h = changedLines[index]; 00193 y += changedLines[index]; 00194 SDL_rect_cliptoscreen(*rect); 00195 } 00196 index++; 00197 } 00198 if (rectCount) { 00199 #if defined(C_SDL2) 00200 SDL_UpdateWindowSurfaceRects(sdl.window, sdl.updateRects, (int)rectCount); 00201 #else 00202 SDL_UpdateRects(sdl.surface, (int)rectCount, sdl.updateRects); 00203 #endif 00204 } 00205 } 00206 } 00207 } 00208 00209 void OUTPUT_SURFACE_Shutdown() 00210 { 00211 // nothing to shutdown (yet?) 00212 }