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