DOSBox-X
|
00001 00002 // Tell Mac OS X to shut up about deprecated OpenGL calls 00003 #ifndef GL_SILENCE_DEPRECATION 00004 #define GL_SILENCE_DEPRECATION 00005 #endif 00006 00007 #include <sys/types.h> 00008 #include <assert.h> 00009 #include <math.h> 00010 00011 #include "dosbox.h" 00012 #include <output/output_opengl.h> 00013 00014 #include <algorithm> 00015 00016 #include "sdlmain.h" 00017 00018 using namespace std; 00019 00020 bool setSizeButNotResize(); 00021 00022 #if C_OPENGL 00023 PFNGLGENBUFFERSARBPROC glGenBuffersARB = NULL; 00024 PFNGLBINDBUFFERARBPROC glBindBufferARB = NULL; 00025 PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB = NULL; 00026 PFNGLBUFFERDATAARBPROC glBufferDataARB = NULL; 00027 PFNGLMAPBUFFERARBPROC glMapBufferARB = NULL; 00028 PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB = NULL; 00029 00030 #if C_OPENGL && DOSBOXMENU_TYPE == DOSBOXMENU_SDLDRAW 00031 extern unsigned int SDLDrawGenFontTextureUnitPerRow; 00032 extern unsigned int SDLDrawGenFontTextureRows; 00033 extern unsigned int SDLDrawGenFontTextureWidth; 00034 extern unsigned int SDLDrawGenFontTextureHeight; 00035 extern GLuint SDLDrawGenFontTexture; 00036 extern bool SDLDrawGenFontTextureInit; 00037 #endif 00038 00039 SDL_OpenGL sdl_opengl; 00040 00041 int Voodoo_OGL_GetWidth(); 00042 int Voodoo_OGL_GetHeight(); 00043 bool Voodoo_OGL_Active(); 00044 00045 static SDL_Surface* SetupSurfaceScaledOpenGL(Bit32u sdl_flags, Bit32u bpp) 00046 { 00047 Bit16u fixedWidth; 00048 Bit16u fixedHeight; 00049 Bit16u windowWidth; 00050 Bit16u windowHeight; 00051 00052 retry: 00053 #if defined(C_SDL2) 00054 if (sdl.desktop.prevent_fullscreen) /* 3Dfx openGL do not allow resize */ 00055 sdl_flags &= ~((unsigned int)SDL_WINDOW_RESIZABLE); 00056 if (sdl.desktop.want_type == SCREEN_OPENGL) 00057 sdl_flags |= (unsigned int)SDL_WINDOW_OPENGL; 00058 #else 00059 if (sdl.desktop.prevent_fullscreen) /* 3Dfx openGL do not allow resize */ 00060 sdl_flags &= ~((unsigned int)SDL_RESIZABLE); 00061 if (sdl.desktop.want_type == SCREEN_OPENGL) 00062 sdl_flags |= (unsigned int)SDL_OPENGL; 00063 #endif 00064 00065 if (sdl.desktop.fullscreen) 00066 { 00067 fixedWidth = sdl.desktop.full.fixed ? sdl.desktop.full.width : 0; 00068 fixedHeight = sdl.desktop.full.fixed ? sdl.desktop.full.height : 0; 00069 #if defined(C_SDL2) 00070 sdl_flags |= (unsigned int)(SDL_WINDOW_FULLSCREEN); 00071 #else 00072 sdl_flags |= (unsigned int)(SDL_FULLSCREEN | SDL_HWSURFACE); 00073 #endif 00074 } 00075 else 00076 { 00077 fixedWidth = sdl.desktop.window.width; 00078 fixedHeight = sdl.desktop.window.height; 00079 #if !defined(C_SDL2) 00080 sdl_flags |= (unsigned int)SDL_HWSURFACE; 00081 #endif 00082 } 00083 00084 if (fixedWidth == 0 || fixedHeight == 0) 00085 { 00086 Bitu consider_height = menu.maxwindow ? currentWindowHeight : 0; 00087 Bitu consider_width = menu.maxwindow ? currentWindowWidth : 0; 00088 int final_height = (int)max(consider_height, userResizeWindowHeight); 00089 int final_width = (int)max(consider_width, userResizeWindowWidth); 00090 00091 fixedWidth = final_width; 00092 fixedHeight = final_height; 00093 } 00094 00095 #if DOSBOXMENU_TYPE == DOSBOXMENU_SDLDRAW 00096 /* scale the menu bar if the window is large enough */ 00097 { 00098 int cw = fixedWidth, ch = fixedHeight; 00099 int scale = 1; 00100 00101 if (cw == 0) 00102 cw = (Bit16u)(sdl.draw.width*sdl.draw.scalex); 00103 if (ch == 0) 00104 ch = (Bit16u)(sdl.draw.height*sdl.draw.scaley); 00105 00106 while ((cw / scale) >= (640 * 2) && (ch / scale) >= (400 * 2)) 00107 scale++; 00108 00109 LOG_MSG("menuScale=%d", scale); 00110 mainMenu.setScale((unsigned int)scale); 00111 00112 if (mainMenu.isVisible() && !sdl.desktop.fullscreen) 00113 fixedHeight -= mainMenu.menuBox.h; 00114 } 00115 #endif 00116 00117 sdl.clip.x = 0; sdl.clip.y = 0; 00118 if (Voodoo_OGL_GetWidth() != 0 && Voodoo_OGL_GetHeight() != 0 && Voodoo_OGL_Active() && sdl.desktop.prevent_fullscreen) 00119 { 00120 /* 3Dfx openGL do not allow resize */ 00121 sdl.clip.w = windowWidth = (Bit16u)Voodoo_OGL_GetWidth(); 00122 sdl.clip.h = windowHeight = (Bit16u)Voodoo_OGL_GetHeight(); 00123 } 00124 else if (fixedWidth && fixedHeight) 00125 { 00126 sdl.clip.w = windowWidth = fixedWidth; 00127 sdl.clip.h = windowHeight = fixedHeight; 00128 if (render.aspect) aspectCorrectFitClip(sdl.clip.w, sdl.clip.h, sdl.clip.x, sdl.clip.y, fixedWidth, fixedHeight); 00129 } 00130 else 00131 { 00132 windowWidth = (Bit16u)(sdl.draw.width * sdl.draw.scalex); 00133 windowHeight = (Bit16u)(sdl.draw.height * sdl.draw.scaley); 00134 if (render.aspect) aspectCorrectExtend(windowWidth, windowHeight); 00135 sdl.clip.w = windowWidth; sdl.clip.h = windowHeight; 00136 } 00137 00138 LOG(LOG_MISC, LOG_DEBUG)("GFX_SetSize OpenGL window=%ux%u clip=x,y,w,h=%d,%d,%d,%d", 00139 (unsigned int)windowWidth, 00140 (unsigned int)windowHeight, 00141 (unsigned int)sdl.clip.x, 00142 (unsigned int)sdl.clip.y, 00143 (unsigned int)sdl.clip.w, 00144 (unsigned int)sdl.clip.h); 00145 00146 #if DOSBOXMENU_TYPE == DOSBOXMENU_SDLDRAW 00147 if (mainMenu.isVisible() && !sdl.desktop.fullscreen) 00148 { 00149 windowHeight += mainMenu.menuBox.h; 00150 sdl.clip.y += mainMenu.menuBox.h; 00151 } 00152 #endif 00153 00154 #if defined(C_SDL2) 00155 (void)bpp; // unused param 00156 sdl.surface = NULL; 00157 sdl.window = GFX_SetSDLWindowMode(windowWidth, windowHeight, (sdl_flags & SDL_WINDOW_OPENGL) ? SCREEN_OPENGL : SCREEN_SURFACE); 00158 if (sdl.window != NULL) sdl.surface = SDL_GetWindowSurface(sdl.window); 00159 #else 00160 sdl.surface = SDL_SetVideoMode(windowWidth, windowHeight, (int)bpp, (unsigned int)sdl_flags | (unsigned int)(setSizeButNotResize() ? SDL_HAX_NORESIZEWINDOW : 0)); 00161 #endif 00162 if (sdl.surface == NULL && sdl.desktop.fullscreen) { 00163 LOG_MSG("Fullscreen not supported: %s", SDL_GetError()); 00164 sdl.desktop.fullscreen = false; 00165 #if defined(C_SDL2) 00166 sdl_flags &= ~SDL_WINDOW_FULLSCREEN; 00167 #else 00168 sdl_flags &= ~SDL_FULLSCREEN; 00169 #endif 00170 GFX_CaptureMouse(); 00171 goto retry; 00172 } 00173 00174 sdl.deferred_resize = false; 00175 sdl.must_redraw_all = true; 00176 00177 /* There seems to be a problem with MesaGL in Linux/X11 where 00178 * the first swap buffer we do is misplaced according to the 00179 * previous window size. 00180 * 00181 * NTS: This seems to have been fixed, which is why this is 00182 * commented out. I guess not calling GFX_SetSize() 00183 * with a 0x0 widthxheight helps! */ 00184 // sdl.gfx_force_redraw_count = 2; 00185 00186 UpdateWindowDimensions(); 00187 GFX_LogSDLState(); 00188 00189 #if DOSBOXMENU_TYPE == DOSBOXMENU_SDLDRAW 00190 mainMenu.screenWidth = (size_t)(sdl.surface->w); 00191 mainMenu.screenHeight = (size_t)(sdl.surface->h); 00192 mainMenu.updateRect(); 00193 mainMenu.setRedraw(); 00194 #endif 00195 00196 return sdl.surface; 00197 } 00198 00199 // output API below 00200 00201 void OUTPUT_OPENGL_Initialize() 00202 { 00203 memset(&sdl_opengl, 0, sizeof(sdl_opengl)); 00204 } 00205 00206 void OUTPUT_OPENGL_Select() 00207 { 00208 sdl.desktop.want_type = SCREEN_OPENGL; 00209 render.aspectOffload = true; 00210 00211 #if defined(WIN32) && !defined(C_SDL2) 00212 SDL1_hax_inhibit_WM_PAINT = 0; 00213 #endif 00214 } 00215 00216 Bitu OUTPUT_OPENGL_GetBestMode(Bitu flags) 00217 { 00218 if (!(flags & GFX_CAN_32)) return 0; // OpenGL requires 32-bit output mode 00219 flags |= GFX_SCALING; 00220 flags &= ~(GFX_CAN_8 | GFX_CAN_15 | GFX_CAN_16); 00221 return flags; 00222 } 00223 00224 Bitu OUTPUT_OPENGL_SetSize() 00225 { 00226 Bitu retFlags = 0; 00227 00228 /* NTS: Apparently calling glFinish/glFlush before setup causes a segfault within 00229 * the OpenGL library on Mac OS X. */ 00230 if (sdl_opengl.inited) 00231 { 00232 glFinish(); 00233 glFlush(); 00234 } 00235 00236 if (sdl_opengl.pixel_buffer_object) 00237 { 00238 glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, 0); 00239 if (sdl_opengl.buffer) glDeleteBuffersARB(1, &sdl_opengl.buffer); 00240 } 00241 else if (sdl_opengl.framebuf) 00242 { 00243 free(sdl_opengl.framebuf); 00244 } 00245 sdl_opengl.framebuf = 0; 00246 00247 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); 00248 #if !defined(C_SDL2) 00249 # if SDL_VERSION_ATLEAST(1, 2, 11) 00250 { 00251 Section_prop* sec = static_cast<Section_prop*>(control->GetSection("vsync")); 00252 00253 if (sec) 00254 SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, (!strcmp(sec->Get_string("vsyncmode"), "host")) ? 1 : 0); 00255 } 00256 # endif 00257 #endif 00258 00259 #if defined(C_SDL2) 00260 SetupSurfaceScaledOpenGL(SDL_WINDOW_RESIZABLE, 0); 00261 #else 00262 SetupSurfaceScaledOpenGL(SDL_RESIZABLE, 0); 00263 #endif 00264 if (!sdl.surface || sdl.surface->format->BitsPerPixel < 15) 00265 { 00266 LOG_MSG("SDL:OPENGL:Can't open drawing surface, are you running in 16bpp(or higher) mode?"); 00267 return 0; 00268 } 00269 00270 glFinish(); 00271 glFlush(); 00272 00273 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &sdl_opengl.max_texsize); 00274 00275 Bitu adjTexWidth = sdl.draw.width; 00276 Bitu adjTexHeight = sdl.draw.height; 00277 #if C_XBRZ 00278 // we do the same as with Direct3D: precreate pixel buffer adjusted for xBRZ 00279 if (sdl_xbrz.enable && xBRZ_SetScaleParameters((int)adjTexWidth, (int)adjTexHeight, (int)sdl.clip.w, (int)sdl.clip.h)) 00280 { 00281 adjTexWidth = adjTexWidth * (unsigned int)sdl_xbrz.scale_factor; 00282 adjTexHeight = adjTexHeight * (unsigned int)sdl_xbrz.scale_factor; 00283 } 00284 #endif 00285 00286 int texsize = 2 << int_log2((int)(adjTexWidth > adjTexHeight ? adjTexWidth : adjTexHeight)); 00287 if (texsize > sdl_opengl.max_texsize) 00288 { 00289 LOG_MSG("SDL:OPENGL:No support for texturesize of %d (max size is %d), falling back to surface", texsize, sdl_opengl.max_texsize); 00290 return 0; 00291 } 00292 00293 /* Create the texture and display list */ 00294 if (sdl_opengl.pixel_buffer_object) 00295 { 00296 glGenBuffersARB(1, &sdl_opengl.buffer); 00297 glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, sdl_opengl.buffer); 00298 glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_EXT, (int)(adjTexWidth*adjTexHeight * 4), NULL, GL_STREAM_DRAW_ARB); 00299 glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, 0); 00300 } 00301 else 00302 { 00303 sdl_opengl.framebuf = calloc(adjTexWidth*adjTexHeight, 4); //32 bit color 00304 } 00305 sdl_opengl.pitch = adjTexWidth * 4; 00306 00307 glBindTexture(GL_TEXTURE_2D, 0); 00308 00309 #if DOSBOXMENU_TYPE == DOSBOXMENU_SDLDRAW 00310 if (SDLDrawGenFontTextureInit) 00311 { 00312 glDeleteTextures(1, &SDLDrawGenFontTexture); 00313 SDLDrawGenFontTexture = (GLuint)(~0UL); 00314 SDLDrawGenFontTextureInit = 0; 00315 } 00316 #endif 00317 00318 glViewport(0, 0, sdl.surface->w, sdl.surface->h); 00319 glDeleteTextures(1, &sdl_opengl.texture); 00320 glGenTextures(1, &sdl_opengl.texture); 00321 glBindTexture(GL_TEXTURE_2D, sdl_opengl.texture); 00322 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 00323 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, 0); 00324 00325 // No borders 00326 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); 00327 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); 00328 00329 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, sdl_opengl.bilinear ? GL_LINEAR : GL_NEAREST); 00330 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, sdl_opengl.bilinear ? GL_LINEAR : GL_NEAREST); 00331 00332 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, texsize, texsize, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, 0); 00333 00334 // NTS: I'm told that nVidia hardware seems to triple buffer despite our 00335 // request to double buffer (according to @pixelmusement), therefore 00336 // the next 3 frames, instead of 2, need to be cleared. 00337 sdl_opengl.menudraw_countdown = 3; // two GL buffers with possible triple buffering behind our back 00338 sdl_opengl.clear_countdown = 3; // two GL buffers with possible triple buffering behind our back 00339 00340 glClearColor(0.0, 0.0, 0.0, 1.0); 00341 glClear(GL_COLOR_BUFFER_BIT); 00342 // SDL_GL_SwapBuffers(); 00343 // glClear(GL_COLOR_BUFFER_BIT); 00344 glShadeModel(GL_FLAT); 00345 glBlendFunc(GL_ONE, GL_ZERO); 00346 glDisable(GL_DEPTH_TEST); 00347 glDisable(GL_LIGHTING); 00348 glDisable(GL_BLEND); 00349 glDisable(GL_CULL_FACE); 00350 glDisable(GL_ALPHA_TEST); 00351 glDisable(GL_FOG); 00352 glDisable(GL_SCISSOR_TEST); 00353 glDisable(GL_STENCIL_TEST); 00354 glEnable(GL_TEXTURE_2D); 00355 00356 glMatrixMode(GL_MODELVIEW); 00357 glLoadIdentity(); 00358 00359 glMatrixMode(GL_PROJECTION); 00360 glLoadIdentity(); 00361 glOrtho(0, sdl.surface->w, sdl.surface->h, 0, -1, 1); 00362 00363 glMatrixMode(GL_TEXTURE); 00364 glLoadIdentity(); 00365 glScaled(1.0 / texsize, 1.0 / texsize, 1.0); 00366 00367 // if (glIsList(sdl_opengl.displaylist)) 00368 // glDeleteLists(sdl_opengl.displaylist, 1); 00369 // sdl_opengl.displaylist = glGenLists(1); 00370 sdl_opengl.displaylist = 1; 00371 00372 glNewList(sdl_opengl.displaylist, GL_COMPILE); 00373 glBindTexture(GL_TEXTURE_2D, sdl_opengl.texture); 00374 00375 glBegin(GL_QUADS); 00376 00377 glTexCoord2i(0, 0); glVertex2i((GLint)sdl.clip.x, (GLint)sdl.clip.y); // lower left 00378 glTexCoord2i((GLint)adjTexWidth, 0); glVertex2i((GLint)sdl.clip.x + (GLint)sdl.clip.w, (GLint)sdl.clip.y); // lower right 00379 glTexCoord2i((GLint)adjTexWidth, (GLint)adjTexHeight); glVertex2i((GLint)sdl.clip.x + (GLint)sdl.clip.w, (GLint)sdl.clip.y + (GLint)sdl.clip.h); // upper right 00380 glTexCoord2i(0, (GLint)adjTexHeight); glVertex2i((GLint)sdl.clip.x, (GLint)sdl.clip.y + (GLint)sdl.clip.h); // upper left 00381 00382 glEnd(); 00383 glEndList(); 00384 00385 glBindTexture(GL_TEXTURE_2D, 0); 00386 00387 #if DOSBOXMENU_TYPE == DOSBOXMENU_SDLDRAW 00388 void GFX_DrawSDLMenu(DOSBoxMenu &menu, DOSBoxMenu::displaylist &dl); 00389 mainMenu.setRedraw(); 00390 GFX_DrawSDLMenu(mainMenu, mainMenu.display_list); 00391 00392 // FIXME: Why do we have to reinitialize the font texture? 00393 // if (!SDLDrawGenFontTextureInit) { 00394 GLuint err = 0; 00395 00396 glGetError(); /* read and discard last error */ 00397 00398 SDLDrawGenFontTexture = (GLuint)(~0UL); 00399 glGenTextures(1, &SDLDrawGenFontTexture); 00400 if (SDLDrawGenFontTexture == (GLuint)(~0UL) || (err = glGetError()) != 0) 00401 { 00402 LOG_MSG("WARNING: Unable to make font texture. id=%llu err=%lu", 00403 (unsigned long long)SDLDrawGenFontTexture, (unsigned long)err); 00404 } 00405 else 00406 { 00407 LOG_MSG("font texture id=%lu will make %u x %u", 00408 (unsigned long)SDLDrawGenFontTexture, 00409 (unsigned int)SDLDrawGenFontTextureWidth, 00410 (unsigned int)SDLDrawGenFontTextureHeight); 00411 00412 SDLDrawGenFontTextureInit = 1; 00413 00414 glBindTexture(GL_TEXTURE_2D, SDLDrawGenFontTexture); 00415 00416 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 00417 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, 0); 00418 00419 // No borders 00420 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); 00421 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); 00422 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 00423 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 00424 00425 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, (int)SDLDrawGenFontTextureWidth, (int)SDLDrawGenFontTextureHeight, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, 0); 00426 00427 /* load the font */ 00428 { 00429 extern Bit8u int10_font_16[256 * 16]; 00430 00431 uint32_t tmp[8 * 16]; 00432 unsigned int x, y, c; 00433 00434 for (c = 0; c < 256; c++) 00435 { 00436 unsigned char *bmp = int10_font_16 + (c * 16); 00437 for (y = 0; y < 16; y++) 00438 { 00439 for (x = 0; x < 8; x++) 00440 { 00441 tmp[(y * 8) + x] = (bmp[y] & (0x80 >> x)) ? 0xFFFFFFFFUL : 0x00000000UL; 00442 } 00443 } 00444 00445 glTexSubImage2D(GL_TEXTURE_2D, /*level*/0, /*x*/(int)((c % 16) * 8), /*y*/(int)((c / 16) * 16), 00446 8, 16, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV, (void*)tmp); 00447 } 00448 } 00449 00450 glBindTexture(GL_TEXTURE_2D, 0); 00451 } 00452 // } 00453 #endif 00454 00455 glFinish(); 00456 glFlush(); 00457 00458 sdl_opengl.inited = true; 00459 retFlags = GFX_CAN_32 | GFX_SCALING; 00460 00461 if (sdl_opengl.pixel_buffer_object) 00462 retFlags |= GFX_HARDWARE; 00463 00464 return retFlags; 00465 } 00466 00467 bool OUTPUT_OPENGL_StartUpdate(Bit8u* &pixels, Bitu &pitch) 00468 { 00469 #if C_XBRZ 00470 if (sdl_xbrz.enable && sdl_xbrz.scale_on) 00471 { 00472 sdl_xbrz.renderbuf.resize(sdl.draw.width * sdl.draw.height); 00473 pixels = sdl_xbrz.renderbuf.empty() ? nullptr : reinterpret_cast<Bit8u*>(&sdl_xbrz.renderbuf[0]); 00474 pitch = sdl.draw.width * sizeof(uint32_t); 00475 } 00476 else 00477 #endif 00478 { 00479 if (sdl_opengl.pixel_buffer_object) 00480 { 00481 glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, sdl_opengl.buffer); 00482 pixels = (Bit8u *)glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, GL_WRITE_ONLY); 00483 } 00484 else 00485 { 00486 pixels = (Bit8u *)sdl_opengl.framebuf; 00487 } 00488 pitch = sdl_opengl.pitch; 00489 } 00490 00491 sdl.updating = true; 00492 return true; 00493 } 00494 00495 void OUTPUT_OPENGL_EndUpdate(const Bit16u *changedLines) 00496 { 00497 if (!(sdl.must_redraw_all && changedLines == NULL)) 00498 { 00499 if (sdl_opengl.clear_countdown > 0) 00500 { 00501 sdl_opengl.clear_countdown--; 00502 glClearColor(0.0, 0.0, 0.0, 1.0); 00503 glClear(GL_COLOR_BUFFER_BIT); 00504 } 00505 00506 if (sdl_opengl.menudraw_countdown > 0) 00507 { 00508 sdl_opengl.menudraw_countdown--; 00509 #if DOSBOXMENU_TYPE == DOSBOXMENU_SDLDRAW 00510 mainMenu.setRedraw(); 00511 GFX_DrawSDLMenu(mainMenu, mainMenu.display_list); 00512 #endif 00513 } 00514 00515 #if C_XBRZ 00516 if (sdl_xbrz.enable && sdl_xbrz.scale_on) 00517 { 00518 // OpenGL pixel buffer is precreated for direct xBRZ output, while xBRZ render buffer is used for rendering 00519 const Bit32u srcWidth = sdl.draw.width; 00520 const Bit32u srcHeight = sdl.draw.height; 00521 00522 if (sdl_xbrz.renderbuf.size() == (unsigned int)srcWidth * (unsigned int)srcHeight && srcWidth > 0 && srcHeight > 0) 00523 { 00524 // we assume render buffer is *not* scaled! 00525 const uint32_t* renderBuf = &sdl_xbrz.renderbuf[0]; // help VS compiler a little + support capture by value 00526 uint32_t* trgTex; 00527 if (sdl_opengl.pixel_buffer_object) 00528 { 00529 glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, sdl_opengl.buffer); 00530 trgTex = (uint32_t *)glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, GL_WRITE_ONLY); 00531 } 00532 else 00533 { 00534 trgTex = reinterpret_cast<uint32_t*>(static_cast<void*>(sdl_opengl.framebuf)); 00535 } 00536 00537 if (trgTex) 00538 xBRZ_Render(renderBuf, trgTex, changedLines, (int)srcWidth, (int)srcHeight, sdl_xbrz.scale_factor); 00539 } 00540 00541 // and here we go repeating some stuff with xBRZ related modifications 00542 if (sdl_opengl.pixel_buffer_object) 00543 { 00544 glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT); 00545 glBindTexture(GL_TEXTURE_2D, sdl_opengl.texture); 00546 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 00547 (int)(sdl.draw.width * (unsigned int)sdl_xbrz.scale_factor), (int)(sdl.draw.height * (unsigned int)sdl_xbrz.scale_factor), GL_BGRA_EXT, 00548 #if defined (MACOSX) && !defined(C_SDL2) 00549 // needed for proper looking graphics on macOS 10.12, 10.13 00550 GL_UNSIGNED_INT_8_8_8_8, 00551 #else 00552 GL_UNSIGNED_INT_8_8_8_8_REV, 00553 #endif 00554 0); 00555 glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, 0); 00556 } 00557 else 00558 { 00559 glBindTexture(GL_TEXTURE_2D, sdl_opengl.texture); 00560 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 00561 (int)(sdl.draw.width * (unsigned int)sdl_xbrz.scale_factor), (int)(sdl.draw.height * (unsigned int)sdl_xbrz.scale_factor), GL_BGRA_EXT, 00562 #if defined (MACOSX) && !defined(C_SDL2) 00563 // needed for proper looking graphics on macOS 10.12, 10.13 00564 GL_UNSIGNED_INT_8_8_8_8, 00565 #else 00566 // works on Linux 00567 GL_UNSIGNED_INT_8_8_8_8_REV, 00568 #endif 00569 (Bit8u *)sdl_opengl.framebuf); 00570 } 00571 glCallList(sdl_opengl.displaylist); 00572 SDL_GL_SwapBuffers(); 00573 } 00574 else 00575 #endif /*C_XBRZ*/ 00576 if (sdl_opengl.pixel_buffer_object) 00577 { 00578 if (changedLines && (changedLines[0] == sdl.draw.height)) 00579 return; 00580 00581 glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT); 00582 glBindTexture(GL_TEXTURE_2D, sdl_opengl.texture); 00583 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 00584 (int)sdl.draw.width, (int)sdl.draw.height, GL_BGRA_EXT, 00585 #if defined (MACOSX) 00586 // needed for proper looking graphics on macOS 10.12, 10.13 00587 GL_UNSIGNED_INT_8_8_8_8, 00588 #else 00589 // works on Linux 00590 GL_UNSIGNED_INT_8_8_8_8_REV, 00591 #endif 00592 (void*)0); 00593 glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, 0); 00594 glCallList(sdl_opengl.displaylist); 00595 SDL_GL_SwapBuffers(); 00596 } 00597 else if (changedLines) 00598 { 00599 if (changedLines[0] == sdl.draw.height) 00600 return; 00601 00602 Bitu y = 0, index = 0; 00603 glBindTexture(GL_TEXTURE_2D, sdl_opengl.texture); 00604 while (y < sdl.draw.height) 00605 { 00606 if (!(index & 1)) 00607 { 00608 y += changedLines[index]; 00609 } 00610 else 00611 { 00612 Bit8u *pixels = (Bit8u *)sdl_opengl.framebuf + y * sdl_opengl.pitch; 00613 Bitu height = changedLines[index]; 00614 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, (int)y, 00615 (int)sdl.draw.width, (int)height, GL_BGRA_EXT, 00616 #if defined (MACOSX) && !defined(C_SDL2) 00617 // needed for proper looking graphics on macOS 10.12, 10.13 00618 GL_UNSIGNED_INT_8_8_8_8, 00619 #else 00620 // works on Linux 00621 GL_UNSIGNED_INT_8_8_8_8_REV, 00622 #endif 00623 (void*)pixels); 00624 y += height; 00625 } 00626 index++; 00627 } 00628 glCallList(sdl_opengl.displaylist); 00629 00630 #if 0 /* DEBUG Prove to me that you're drawing the damn texture */ 00631 glBindTexture(GL_TEXTURE_2D, SDLDrawGenFontTexture); 00632 00633 glPushMatrix(); 00634 00635 glMatrixMode(GL_TEXTURE); 00636 glLoadIdentity(); 00637 glScaled(1.0 / SDLDrawGenFontTextureWidth, 1.0 / SDLDrawGenFontTextureHeight, 1.0); 00638 00639 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 00640 glEnable(GL_ALPHA_TEST); 00641 glEnable(GL_BLEND); 00642 00643 glBegin(GL_QUADS); 00644 00645 glTexCoord2i(0, 0); glVertex2i(0, 0); // lower left 00646 glTexCoord2i(SDLDrawGenFontTextureWidth, 0); glVertex2i(SDLDrawGenFontTextureWidth, 0); // lower right 00647 glTexCoord2i(SDLDrawGenFontTextureWidth, SDLDrawGenFontTextureHeight); glVertex2i(SDLDrawGenFontTextureWidth, SDLDrawGenFontTextureHeight); // upper right 00648 glTexCoord2i(0, SDLDrawGenFontTextureHeight); glVertex2i(0, SDLDrawGenFontTextureHeight); // upper left 00649 00650 glEnd(); 00651 00652 glBlendFunc(GL_ONE, GL_ZERO); 00653 glDisable(GL_ALPHA_TEST); 00654 glEnable(GL_TEXTURE_2D); 00655 00656 glPopMatrix(); 00657 00658 glBindTexture(GL_TEXTURE_2D, sdl_opengl.texture); 00659 #endif 00660 00661 SDL_GL_SwapBuffers(); 00662 } 00663 00664 if (!menu.hidecycles && !sdl.desktop.fullscreen) frames++; 00665 } 00666 } 00667 00668 void OUTPUT_OPENGL_Shutdown() 00669 { 00670 // nothing to shutdown (yet?) 00671 } 00672 00673 #endif