Fullscreen modes in Ubuntu (SDL + OpenGL)
我在Ubuntu上的全屏行为有些奇怪的问题。窗口模式可以正常工作,但"假"(
在Windows上,"假"全屏模式会改变视频模式,并且我们看到窗口的内容延伸到整个显示器。"真实"全屏模式占用桌面的大小。在这种模式下,我在左上角绘制窗口的内容,并将多余的区域留空。
在Ubuntu上,"假"全屏模式会更改视频模式,并且窗口的内容会拉伸到整个显示器,但是只绘制了一部分。它要么是顶部(占显示的90%以上),要么是底部(占显示的10%以下)。未绘制的部分是黑色的,或者包含在应用程序被声明之前在屏幕上绘制的内容。有时应用程序不会在退出时更改视频模式。即使只绘制底部,光标也被锁定在顶部内部。
"真实"全屏模式要么全黑,要么在显示屏中央显示窗口内容。内容移至顶部,该区域周围的所有内容均为黑色(背景颜色并非如此)。在此模式下,光标锁定在该区域内。
如果我在运行时更改全屏模式,则行为会有所不同-绘制区域(也是锁定光标的区域)可以在任何地方,不仅在"假"模式下位于顶部/底部,在"真实"位置居中。
-
Windows上的"假"全屏模式:
(800x600窗口的内容绘制在角落,其他区域为空) -
Ubuntu上的"假"全屏模式:
(800x600视频模式,但看不到整个区域。不过,您可以看到gedit的一部分。) -
Ubuntu上的"真实"全屏模式:
(位于中心的800x600区域,但图像移到顶部(红色正方形表示在角落)
我手动使用OpenGL而不是SDL在屏幕上绘制。我写了一个小例子来说明问题。它会创建一个800x600的窗口,并在其中心绘制一个蓝色三角形。在屏幕的一角绘制绿色正方形,在窗口的一角绘制红色正方形(这些正方形可以在同一位置,因此绿色正方形更大,在其顶部绘制红色正方形)。可以分别使用" 1"," 2"或" 3"键进入窗口化,"伪造"或"真实"全屏模式。退出键关闭应用程序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | #include <SDL.h> #include <GL/gl.h> #define FULLSCREEN 0 #define WIDTH 800 #define HEIGHT 600 //fullscreen: // 0 - windowed mode, // 1 -"fake" fullscreen mode, // 2 -"real" fullscreen mode int real_width; int real_height; //screen width & height - to draw green square that shows us actual screen size void set_viewport(SDL_Window* window); void draw(SDL_Window* window); int main(int argc, char* argv[]) { SDL_Init(SDL_INIT_VIDEO); int position; #if FULLSCREEN == 0 position = SDL_WINDOWPOS_CENTERED; #else position = 0; #endif //the only thing I've found - some guy said it works //if window is in (0,0) while entering fullscreen //well, it's not, but I've kept it int flags = SDL_WINDOW_OPENGL; #if FULLSCREEN == 1 flags |= SDL_WINDOW_FULLSCREEN; #elif FULLSCREEN == 2 flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; #endif SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_Window* window = SDL_CreateWindow( "", position, position, /* centered/(0,0) */ WIDTH, HEIGHT, /* request 800x600 window */ flags /* needed mode */ ); //setup GL SDL_GLContext glcontext = SDL_GL_CreateContext(window); glShadeModel(GL_SMOOTH); glCullFace(GL_BACK); glFrontFace(GL_CCW); glEnable(GL_CULL_FACE); //viewport and projection set_viewport(window); draw(window); bool done = false; while(!done) { draw(window); SDL_Event event; while(SDL_PollEvent(&event)) { switch(event.type) { case SDL_QUIT: done = true; break; case SDL_KEYDOWN: if(event.key.keysym.scancode == SDL_SCANCODE_ESCAPE) done = true; else if(event.key.keysym.scancode == SDL_SCANCODE_1) { SDL_SetWindowFullscreen(window, 0); set_viewport(window); } else if(event.key.keysym.scancode == SDL_SCANCODE_2) { SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN); set_viewport(window); } else if(event.key.keysym.scancode == SDL_SCANCODE_3) { SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP); set_viewport(window); } break; } } } SDL_GL_DeleteContext(glcontext); SDL_DestroyWindow(window); SDL_Quit(); return 0; } void set_viewport(SDL_Window* window) { SDL_GetWindowSize(window, &real_width, &real_height); glClearColor(1, 1, 1, 1); glViewport(0, 0, real_width, real_height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, real_width, real_height, 0, -1, 0); } void draw_triangle(); void draw_square(int x, int y, float side); void draw(SDL_Window* window) { glClear(GL_COLOR_BUFFER_BIT); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //triangle on while background glClearColor(1, 1, 1, 1); draw_triangle(); //green square at screen corner glColor3f(0, 1, 0); draw_square(real_width, real_height, 20); //red square at window corner glColor3f(1, 0, 0); draw_square(WIDTH, HEIGHT, 10); SDL_GL_SwapWindow(window); } void draw_triangle() { const float w = 460; const float h = 400; float colorBuffer[9] = { 0, 0.43f, 0.85f /*#006dd9*/, 0, 0.22f, 0.43f /*#00376e*/, 0, 0.43f, 0.85f /*#006dd9*/ }; float vertexBuffer[9] = { 0, 0, 0, w/2, h, 0, w, 0, 0 }; glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glTranslatef((WIDTH-w)/2,(HEIGHT-h)/2,0); glColorPointer(3, GL_FLOAT, 0, colorBuffer); glVertexPointer(3, GL_FLOAT, 0, vertexBuffer); glDrawArrays(GL_TRIANGLE_FAN, 0, 3); glTranslatef(-(WIDTH-w)/2,-(HEIGHT-h)/2,0); glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); } void draw_square(int x, int y, float side) { float vertexBuffer[12] = { 0, 0, 0, /*top left*/ 0, side, 0, /*bottom left*/ side, side, 0, /*bottom right*/ side, 0, 0 /*top right*/ }; glEnableClientState(GL_VERTEX_ARRAY); glTranslatef(x-side/2, y-side/2, 0); glVertexPointer(3, GL_FLOAT, 0, vertexBuffer); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); glTranslatef(-x+side/2, -y+side/2, 0); glDisableClientState(GL_VERTEX_ARRAY); } |
模式更改非常有用,尤其是在多显示器环境中。
尝试使用无边界,桌面大小的窗口:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | #include <GL/glew.h> #include <SDL2/SDL.h> // use border state as proxy for fullscreenedness SDL_Rect ToggleFakeFullscreen( SDL_Window* window, const SDL_Rect& oldBounds ) { if( SDL_GetWindowFlags( window ) & SDL_WINDOW_BORDERLESS ) { SDL_SetWindowBordered( window, SDL_TRUE ); SDL_SetWindowSize( window, oldBounds.w, oldBounds.h ); SDL_SetWindowPosition( window, oldBounds.x, oldBounds.y ); return oldBounds; } else { SDL_Rect curBounds; SDL_GetWindowPosition( window, &curBounds.x, &curBounds.y ); SDL_GetWindowSize( window, &curBounds.w, &curBounds.h ); int idx = SDL_GetWindowDisplayIndex( window ); SDL_Rect bounds; SDL_GetDisplayBounds( idx, &bounds ); SDL_SetWindowBordered( window, SDL_FALSE ); SDL_SetWindowPosition( window, bounds.x, bounds.y ); SDL_SetWindowSize( window, bounds.w, bounds.h ); return curBounds; } } int main( int argc, char **argv ) { if( SDL_Init( SDL_INIT_EVERYTHING ) < 0 ) return -1; SDL_Window* window = SDL_CreateWindow ( "Test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL ); if( NULL == window ) return -1; SDL_GLContext ctx = SDL_GL_CreateContext( window ); if( GLEW_OK != glewInit() ) return -1; SDL_Rect curBounds; bool running = true; while( running ) { SDL_Event ev; while( SDL_WaitEventTimeout( &ev, 16 ) ) { if( ev.type == SDL_QUIT ) running = false; if( ev.type == SDL_KEYUP && ev.key.keysym.sym == SDLK_ESCAPE ) running = false; if( ev.type == SDL_KEYUP && ev.key.keysym.sym == SDLK_f ) curBounds = ToggleFakeFullscreen( window, curBounds ); } int w, h; SDL_GetWindowSize( window, &w, &h ); glViewport( 0, 0, w, h ); glClearColor( 0, 0, 0, 1 ); glClear( GL_COLOR_BUFFER_BIT ); glMatrixMode( GL_PROJECTION ); glLoadIdentity(); glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); glColor3ub( 255, 0, 0 ); glBegin( GL_TRIANGLES ); glVertex2i( -1, -1 ); glVertex2i( 1, -1 ); glVertex2i( 0, 1 ); glEnd(); SDL_GL_SwapWindow( window ); } SDL_GL_DeleteContext( ctx ); SDL_DestroyWindow( window ); SDL_Quit(); return 0; } |
点击