GL2D.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. #include "StdInc.h"
  2. #include <SDL.h>
  3. #include <SDL_video.h>
  4. #include "SDL_syswm.h"
  5. #include <SDL_opengl.h>
  6. #include "GL2D.h"
  7. namespace GL2D
  8. {
  9. // Variables initialized by initVideo, updated by setScreenRes:
  10. static SDL_SysWMinfo wmInfo;
  11. ui32 screenWidth = 0, screenHeight = 0; // Screen/Window size
  12. // OpenGL 1.3 functions pointers
  13. PFNGLACTIVETEXTUREPROC glActiveTexture;
  14. // OpenGL 2.0 functions pointers
  15. PFNGLCREATEPROGRAMPROC glCreateProgram;
  16. PFNGLCREATESHADERPROC glCreateShader;
  17. PFNGLDELETESHADERPROC glDeleteShader;
  18. PFNGLSHADERSOURCEPROC glShaderSource;
  19. PFNGLCOMPILESHADERPROC glCompileShader;
  20. PFNGLGETSHADERIVPROC glGetShaderiv;
  21. PFNGLATTACHSHADERPROC glAttachShader;
  22. PFNGLLINKPROGRAMPROC glLinkProgram;
  23. PFNGLGETPROGRAMIVPROC glGetProgramiv;
  24. PFNGLUSEPROGRAMPROC glUseProgram;
  25. PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation;
  26. PFNGLUNIFORM1IPROC glUniform1i;
  27. PFNGLUNIFORM2IPROC glUniform2i;
  28. PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog;
  29. PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog;
  30. // Shaders' sources
  31. static const char frag_palette_bitmap[] = (
  32. "uniform usampler2DRect bitmap;"
  33. "uniform sampler1D palette;"
  34. "uniform ivec2 coordOffs;"
  35. "layout (origin_upper_left) in vec4 gl_FragCoord;"
  36. "void main(){"
  37. "gl_FragColor = texelFetch(palette, int(texelFetch(bitmap, ivec2(gl_FragCoord.xy) - coordOffs).r), 0);"
  38. "}"
  39. );
  40. // Programs' handlers
  41. static GLuint currentProgram = 0;
  42. static GLuint colorizeProgram = 0;
  43. static GLuint paletteBitmapProgram = 0;
  44. // Uniforms handlers
  45. static GLint coord_uniform = -1;
  46. // Print out the information log for a shader object
  47. void printInfoLog(PFNGLGETPROGRAMINFOLOGPROC logFunc, GLuint object, GLint status)
  48. {
  49. if (logFunc != nullptr)
  50. {
  51. GLsizei infoLogLength = 0;
  52. GLchar infoLog[1024];
  53. logFunc(object, sizeof(infoLog)-1, &infoLogLength, infoLog);
  54. if (infoLogLength > 0) (status ? tlog0 : tlog1) << infoLog;
  55. }
  56. }
  57. GLuint makeShaderProgram(const char * frg_src)
  58. {
  59. // Creating a fragment shader object
  60. GLuint shader_object = glCreateShader(GL_FRAGMENT_SHADER);
  61. if (shader_object == 0) return 0;
  62. glShaderSource(shader_object, 1, &frg_src, nullptr); // assigning the shader source
  63. glCompileShader(shader_object); // Compiling the shader
  64. GLint ret;
  65. glGetShaderiv(shader_object, GL_COMPILE_STATUS, &ret);
  66. printInfoLog(glGetShaderInfoLog, shader_object, ret);
  67. if (ret == GL_TRUE)
  68. {
  69. GLuint program_object = glCreateProgram(); // Creating a program object
  70. glAttachShader(program_object, shader_object); // Attaching the shader into program
  71. // Link the shaders into a complete GLSL program.
  72. glLinkProgram(program_object);
  73. glGetProgramiv(shader_object, GL_LINK_STATUS, &ret);
  74. printInfoLog(glGetProgramInfoLog, program_object, ret);
  75. if (ret == GL_TRUE) return program_object;
  76. }
  77. glDeleteShader(shader_object);
  78. return 0;
  79. }
  80. void initVideo(ui32 w, ui32 h, bool fullscreen)
  81. {
  82. SDL_VERSION(&wmInfo.version);
  83. SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
  84. if (!setScreenRes(w, h, fullscreen))
  85. {
  86. throw std::runtime_error("Video mode setting failed\n");
  87. }
  88. glClearColor(0, 0, 0, 0); // Black Background
  89. glClear(GL_COLOR_BUFFER_BIT);
  90. SDL_GL_SwapBuffers();
  91. // Dynamic-linked OpenGL 1.3 and 2.0 functions - required to 2D rendeing
  92. if ( (glActiveTexture = (PFNGLACTIVETEXTUREPROC) SDL_GL_GetProcAddress("glActiveTexture")) == nullptr
  93. || (glCreateProgram = (PFNGLCREATEPROGRAMPROC) SDL_GL_GetProcAddress("glCreateProgram")) == nullptr
  94. || (glCreateShader = (PFNGLCREATESHADERPROC) SDL_GL_GetProcAddress("glCreateShader")) == nullptr
  95. || (glDeleteShader = (PFNGLDELETESHADERPROC) SDL_GL_GetProcAddress("glDeleteShader")) == nullptr
  96. || (glShaderSource = (PFNGLSHADERSOURCEPROC) SDL_GL_GetProcAddress("glShaderSource")) == nullptr
  97. || (glCompileShader = (PFNGLCOMPILESHADERPROC) SDL_GL_GetProcAddress("glCompileShader")) == nullptr
  98. || (glGetShaderiv = (PFNGLGETSHADERIVPROC) SDL_GL_GetProcAddress("glGetShaderiv")) == nullptr
  99. || (glAttachShader = (PFNGLATTACHSHADERPROC) SDL_GL_GetProcAddress("glAttachShader")) == nullptr
  100. || (glLinkProgram = (PFNGLLINKPROGRAMPROC) SDL_GL_GetProcAddress("glLinkProgram")) == nullptr
  101. || (glGetProgramiv = (PFNGLGETPROGRAMIVPROC) SDL_GL_GetProcAddress("glGetProgramiv")) == nullptr
  102. || (glUseProgram = (PFNGLUSEPROGRAMPROC) SDL_GL_GetProcAddress("glUseProgram")) == nullptr
  103. || (glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC) SDL_GL_GetProcAddress("glGetUniformLocation")) == nullptr
  104. || (glUniform1i = (PFNGLUNIFORM1IPROC) SDL_GL_GetProcAddress("glUniform1i")) == nullptr
  105. || (glUniform2i = (PFNGLUNIFORM2IPROC) SDL_GL_GetProcAddress("glUniform2i")) == nullptr
  106. )
  107. {
  108. tlog1 << "Error: OpenGL2 Extenstions are not available\n";
  109. tlog1 << "SDL says: " << SDL_GetError() << std::endl;
  110. throw std::runtime_error("OpenGL2 Extenstions are not available\n");
  111. }
  112. glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC) SDL_GL_GetProcAddress("glGetProgramInfoLog"); // not required
  113. glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC) SDL_GL_GetProcAddress("glGetShaderInfoLog"); // not required
  114. glDisable(GL_DEPTH_TEST);
  115. glDisable(GL_LIGHTING);
  116. glDisable(GL_DITHER);
  117. glDisable(GL_TEXTURE_2D);
  118. glEnable(GL_TEXTURE_RECTANGLE);
  119. glEnable(GL_BLEND);
  120. glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
  121. paletteBitmapProgram = makeShaderProgram(frag_palette_bitmap);
  122. if (paletteBitmapProgram == 0)
  123. {
  124. throw std::runtime_error("OpenGL shader for palleted bitmaps is not compiled\n");
  125. }
  126. GLint bitmap_uniform = glGetUniformLocation(paletteBitmapProgram, "bitmap");
  127. GLint palette_uniform = glGetUniformLocation(paletteBitmapProgram, "palette");
  128. coord_uniform = glGetUniformLocation(paletteBitmapProgram, "coordOffs");
  129. glUseProgram(currentProgram = paletteBitmapProgram);
  130. glUniform1i(bitmap_uniform, 0);
  131. glUniform1i(palette_uniform, 1);
  132. #ifdef _WIN32
  133. wglMakeCurrent(NULL, NULL);
  134. #endif
  135. }
  136. void attachToCurrentThread()
  137. {
  138. #ifdef _WIN32
  139. HDC hdc = GetDC(wmInfo.window);
  140. wglMakeCurrent(hdc, wmInfo.hglrc);
  141. #endif
  142. }
  143. bool setScreenRes(ui32 w, ui32 h, bool fullscreen)
  144. {
  145. // Try to use the best screen depth for the display
  146. int suggestedBpp = SDL_VideoModeOK(w, h, 32, SDL_OPENGL | SDL_ANYFORMAT | (fullscreen?SDL_FULLSCREEN:0));
  147. if(suggestedBpp == 0)
  148. {
  149. tlog1 << "Error: SDL says that " << w << "x" << h << " resolution is not available!\n";
  150. return false;
  151. }
  152. if(suggestedBpp != 32)
  153. {
  154. tlog2 << "Note: SDL suggests to use " << suggestedBpp << " bpp instead of 32 bpp\n";
  155. }
  156. if(SDL_SetVideoMode(w, h, suggestedBpp, SDL_OPENGL | SDL_ANYFORMAT | (fullscreen?SDL_FULLSCREEN:0)) == NULL)
  157. {
  158. tlog1 << "Error: Video mode setting failed (" << w << "x" << h << "x" << suggestedBpp << "bpp)\n";
  159. return false;
  160. }
  161. screenWidth = w; screenHeight = h;
  162. int getwm = SDL_GetWMInfo(&wmInfo);
  163. if(getwm != 1)
  164. {
  165. tlog2 << "Something went wrong, getwm=" << getwm << std::endl;
  166. tlog2 << "SDL says: " << SDL_GetError() << std::endl;
  167. return false;
  168. }
  169. glViewport(0, 0, w, h);
  170. glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
  171. glLoadIdentity(); // Reset The Projection Matrix
  172. glOrtho(0, w, h, 0, 0, 1);
  173. glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
  174. glLoadIdentity(); // Reset The Modelview Matrix
  175. glTranslatef(0.375, 0.375, 0); // Displacement trick for exact pixelization
  176. return true;
  177. }
  178. void assignTexture(ui32 slot, ui32 type, ui32 handle)
  179. {
  180. glActiveTexture(slot);
  181. glBindTexture(type, handle);
  182. }
  183. void useNoShader()
  184. {
  185. if (currentProgram != 0) {
  186. glUseProgram(currentProgram = 0);
  187. }
  188. }
  189. void useColorizeShader(const float cm[4][4])
  190. {
  191. if (currentProgram != colorizeProgram) {
  192. glUseProgram(currentProgram = colorizeProgram);
  193. }
  194. }
  195. void usePaletteBitmapShader(si32 x, si32 y)
  196. {
  197. if (currentProgram != paletteBitmapProgram) {
  198. glUseProgram(currentProgram = paletteBitmapProgram);
  199. }
  200. glUniform2i(coord_uniform, x, y);
  201. }
  202. void usePaletteBitmapShader(si32 x, si32 y, const float cm[4][4])
  203. {
  204. if (currentProgram != paletteBitmapProgram) {
  205. glUseProgram(currentProgram = paletteBitmapProgram);
  206. }
  207. glUniform2i(coord_uniform, x, y);
  208. }
  209. }