Renderer.cpp 34.2 KB
Newer Older
1
2
3

#include <cstdio>

Gargaj's avatar
Gargaj committed
4
#ifdef _WIN32
Gargaj's avatar
add SDL  
Gargaj committed
5
6
#include <windows.h>
#endif
7
8
9

#define GLEW_NO_GLU
#include "GL/glew.h"
Gargaj's avatar
Gargaj committed
10
11
12
#ifdef _WIN32
#include <GL/wGLew.h>
#endif
13
14
15
16

#define GLFW_INCLUDE_NONE
#include "GLFW/glfw3.h"

Gargaj's avatar
add SDL  
Gargaj committed
17
#include "../Renderer.h"
18
#include <string.h>
Gargaj's avatar
add SDL  
Gargaj committed
19

Gargaj's avatar
Gargaj committed
20
#include "UniConversion.h"
Gargaj's avatar
Gargaj committed
21

22
#define STB_IMAGE_IMPLEMENTATION
23
#include "stb_image.h"
24
#include "Scintilla.h"
Gargaj's avatar
Gargaj committed
25

26
27
28
29
#ifdef __APPLE__
#include "../TouchBar.h"
#endif

30
31
32
const char * shaderKeyword =
  "discard struct if else switch case default break goto return for while do continue";

ferris's avatar
ferris committed
33
const char * shaderType =
34
35
36
37
  "attribute const in inout out uniform varying invariant "
  "centroid flat smooth noperspective layout patch sample "
  "subroutine lowp mediump highp precision "
  "void float vec2 vec3 vec4 bvec2 bvec3 bvec4 ivec2 ivec3 ivec4 "
38
  "mat2 mat3 mat4 int bool "
39
40
41
42
43
  "uvec2 uvec3 uvec4 dvec2 dvec3 dvec4 "
  "sampler1D sampler2D sampler3D isampler2D isampler1D isampler3D "
  "usampler1D usampler2D usampler3D "
  "sampler1DShadow sampler2DShadow sampler1DArray sampler2DArray "
  "sampler1DArrayShadow sampler2DArrayShadow "
Gargaj's avatar
typo    
Gargaj committed
44
  "samplerCube samplerCubeShadow samplerCubeArrayShadow ";
45

ferris's avatar
ferris committed
46
const char * shaderBuiltin =
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
  "radians degrees sin cos tan asin acos atan sinh "
  "cosh tanh asinh acosh atanh pow exp log exp2 "
  "log2 sqrt inversesqrt abs sign floor trunc round "
  "roundEven ceil fract mod modf min max clamp mix "
  "step smoothstep isnan isinf floatBitsToInt floatBitsToUint "
  "intBitsToFloat uintBitsToFloat fma frexp ldexp packUnorm2x16 "
  "packUnorm4x8 packSnorm4x8 unpackUnorm2x16 unpackUnorm4x8 "
  "unpackSnorm4x8 packDouble2x32 unpackDouble2x32 length distance "
  "dot cross normalize ftransform faceforward reflect "
  "refract matrixCompMult outerProduct transpose determinant "
  "inverse lessThan lessThanEqual greaterThan greaterThanEqual "
  "equal notEqual any all not uaddCarry usubBorrow "
  "umulExtended imulExtended bitfieldExtract bitfildInsert "
  "bitfieldReverse bitCount findLSB findMSB textureSize "
  "textureQueryLOD texture textureProj textureLod textureOffset "
  "texelFetch texelFetchOffset textureProjOffset textureLodOffset "
  "textureProjLod textureProjLodOffset textureGrad textureGradOffset "
  "textureProjGrad textureProjGradOffset textureGather "
  "textureGatherOffset texture1D texture2D texture3D texture1DProj "
  "texture2DProj texture3DProj texture1DLod texture2DLod "
  "texture3DLod texture1DProjLod texture2DProjLod texture3DProjLod "
  "textureCube textureCubeLod shadow1D shadow2D shadow1DProj "
  "shadow2DProj shadow1DLod shadow2DLod shadow1DProjLod "
  "shadow2DProjLod dFdx dFdy fwidth interpolateAtCentroid "
  "interpolateAtSample interpolateAtOffset noise1 noise2 noise3 "
  "noise4 EmitStreamVertex EndStreamPrimitive EmitVertex "
  "EndPrimitive barrier "
  "gl_VertexID gl_InstanceID gl_Position gl_PointSize "
  "gl_ClipDistance gl_PrimitiveIDIn gl_InvocationID gl_PrimitiveID "
  "gl_Layer gl_PatchVerticesIn gl_TessLevelOuter gl_TessLevelInner "
  "gl_TessCoord gl_FragCoord gl_FrontFacing gl_PointCoord "
  "gl_SampleID gl_SamplePosition gl_FragColor gl_FragData "
  "gl_FragDepth gl_SampleMask gl_ClipVertex gl_FrontColor "
  "gl_BackColor gl_FrontSecondaryColor gl_BackSecondaryColor "
  "gl_TexCoord gl_FogFragCoord gl_Color gl_SecondaryColor "
  "gl_Normal gl_Vertex gl_MultiTexCoord0 gl_MultiTexCoord1 "
  "gl_MultiTexCoord2 gl_MultiTexCoord3 gl_MultiTexCoord4 "
  "gl_MultiTexCoord5 gl_MultiTexCoord6 gl_MultiTexCoord7 gl_FogCoord "
  "gl_MaxVertexAttribs gl_MaxVertexUniformComponents gl_MaxVaryingFloats "
  "gl_MaxVaryingComponents gl_MaxVertexOutputComponents "
  "gl_MaxGeometryInputComponents gl_MaxGeometryOutputComponents "
  "gl_MaxFragmentInputComponents gl_MaxVertexTextureImageUnits "
  "gl_MaxCombinedTextureImageUnits gl_MaxTextureImageUnits "
  "gl_MaxFragmentUniformComponents gl_MaxDrawBuffers gl_MaxClipDistances "
  "gl_MaxGeometryTextureImageUnits gl_MaxGeometryOutputVertices "
  "gl_MaxGeometryTotalOutputComponents gl_MaxGeometryUniformComponents "
  "gl_MaxGeometryVaryingComponents gl_MaxTessControlInputComponents "
  "gl_MaxTessControlOutputComponents gl_MaxTessControlTextureImageUnits "
  "gl_MaxTessControlUniformComponents "
  "gl_MaxTessControlTotalOutputComponents "
  "gl_MaxTessEvaluationInputComponents gl_MaxTessEvaluationOutputComponents "
  "gl_MaxTessEvaluationTextureImageUnits "
  "gl_MaxTessEvaluationUniformComponents gl_MaxTessPatchComponents "
  "gl_MaxPatchVertices gl_MaxTessGenLevel gl_MaxTextureUnits "
  "gl_MaxTextureCoords gl_MaxClipPlanes "
  "gl_DepthRange gl_ModelViewMatrix gl_ProjectionMatrix "
  "gl_ModelViewProjectionMatrix gl_TextureMatrix gl_NormalMatrix "
  "gl_ModelViewMatrixInverse gl_ProjectionMatrixInverse "
  "gl_ModelViewProjectionMatrixInverse gl_TextureMatrixInverse "
  "gl_ModelViewMatrixTranspose gl_ProjectionMatrixTranspose "
  "gl_ModelViewProjectionMatrixTranspose gl_TextureMatrixTranspose "
  "gl_ModelViewMatrixInverseTranspose gl_ProjectionMatrixInverseTranspose "
  "gl_ModelViewProjectionMatrixInverseTranspose "
  "gl_TextureMatrixInverseTranspose gl_NormalScale gl_ClipPlane "
  "gl_Point gl_FrontMaterial gl_BackMaterial gl_LightSource "
  "gl_LightModel gl_FrontLightModelProduct gl_BackLightModelProduct "
  "gl_FrontLightProduct gl_BackLightProduct gl_TextureEnvColor "
  "gl_EyePlaneS gl_EyePlaneT gl_EyePlaneR gl_EyePlaneQ "
  "gl_ObjectPlaneS gl_ObjectPlaneT gl_ObjectPlaneR gl_ObjectPlaneQ "
  "gl_Fog";

Gargaj's avatar
add SDL  
Gargaj committed
118
119
namespace Renderer
{
Marco Foco's avatar
Marco Foco committed
120
121
  const char * defaultShaderFilename = "shader.glsl";
  const char defaultShader[65536] =
ferris's avatar
ferris committed
122
    "#version 410 core\n"
Gargaj's avatar
Gargaj committed
123
124
    "\n"
    "uniform float fGlobalTime; // in seconds\n"
125
    "uniform vec2 v2Resolution; // viewport resolution (in pixels)\n"
Gargaj's avatar
Gargaj committed
126
    "\n"
127
    "uniform sampler1D texFFT; // towards 0.0 is bass / lower freq, towards 1.0 is higher / treble freq\n"
Gargaj's avatar
Gargaj committed
128
    "uniform sampler1D texFFTSmoothed; // this one has longer falloff and less harsh transients\n"
129
    "uniform sampler1D texFFTIntegrated; // this is continually increasing\n"
130
131
132
133
134
135
    "{%textures:begin%}" // leave off \n here
    "uniform sampler2D {%textures:name%};\n"
    "{%textures:end%}" // leave off \n here
    "{%midi:begin%}" // leave off \n here
    "float {%midi:name%};\n"
    "{%midi:end%}" // leave off \n here
Gargaj's avatar
Gargaj committed
136
    "\n"
137
    "layout(location = 0) out vec4 out_color; // out_color must be written in order to see anything\n"
Gargaj's avatar
Gargaj committed
138
    "\n"
139
140
141
142
143
    "vec4 plas( vec2 v, float time )\n"
    "{\n"
    "  float c = 0.5 + sin( v.x * 10.0 ) + cos( sin( time + v.y ) * 20.0 );\n"
    "  return vec4( sin(c * 0.2 + cos(time)), c * 0.15, cos( c * 0.1 + time / .4 ) * .25, 1.0 );\n"
    "}\n"
Gargaj's avatar
Gargaj committed
144
145
    "void main(void)\n"
    "{\n"
skomp's avatar
skomp committed
146
    "  vec2 uv = vec2(gl_FragCoord.x / v2Resolution.x, gl_FragCoord.y / v2Resolution.y);\n"
Gargaj's avatar
Gargaj committed
147
148
149
150
151
152
153
154
155
156
157
158
    "  uv -= 0.5;\n"
    "  uv /= vec2(v2Resolution.y / v2Resolution.x, 1);\n"
    "\n"
    "  vec2 m;\n"
    "  m.x = atan(uv.x / uv.y) / 3.14;\n"
    "  m.y = 1 / length(uv) * .2;\n"
    "  float d = m.y;\n"
    "\n"
    "  float f = texture( texFFT, d ).r * 100;\n"
    "  m.x += sin( fGlobalTime ) * 0.1;\n"
    "  m.y += fGlobalTime * 0.25;\n"
    "\n"
159
160
161
    "  vec4 t = plas( m * 3.14, fGlobalTime ) / d;\n"
    "  t = clamp( t, 0.0, 1.0 );\n"
    "  out_color = f + t;\n"
Gargaj's avatar
Gargaj committed
162
163
    "}";

164
  GLFWwindow * mWindow = NULL;
Gargaj's avatar
add SDL  
Gargaj committed
165
166
  bool run = true;

167
168
169
170
171
172
173
  GLuint theShader = 0;
  GLuint glhVertexShader = 0;
  GLuint glhFullscreenQuadVB = 0;
  GLuint glhFullscreenQuadVA = 0;
  GLuint glhGUIVB = 0;
  GLuint glhGUIVA = 0;
  GLuint glhGUIProgram = 0;
Gargaj's avatar
Gargaj committed
174

175
176
  int nWidth = 0;
  int nHeight = 0;
Gargaj's avatar
Gargaj committed
177

ferris's avatar
ferris committed
178
  void MatrixOrthoOffCenterLH(float * pout, float l, float r, float b, float t, float zn, float zf)
Gargaj's avatar
Gargaj committed
179
  {
ferris's avatar
ferris committed
180
    memset( pout, 0, sizeof(float) * 4 * 4 );
Gargaj's avatar
Gargaj committed
181
182
183
184
185
186
187
188
189
    pout[0 + 0 * 4] = 2.0f / (r - l);
    pout[1 + 1 * 4] = 2.0f / (t - b);
    pout[2 + 2 * 4] = 1.0f / (zf -zn);
    pout[3 + 0 * 4] = -1.0f -2.0f *l / (r - l);
    pout[3 + 1 * 4] = 1.0f + 2.0f * t / (b - t);
    pout[3 + 2 * 4] = zn / (zn -zf);
    pout[3 + 3 * 4] = 1.0;
  }

190
191
192
193
  int readIndex = 0;
  int writeIndex = 1;
  GLuint pbo[2];

194
  static void error_callback(int error, const char *description) {
195
196
197
198
199
200
201
202
    switch (error) {
    case GLFW_API_UNAVAILABLE:
      printf("OpenGL is unavailable: ");
      break;
    case GLFW_VERSION_UNAVAILABLE:
      printf("OpenGL 4.1 (the minimum requirement) is not available: ");
      break;
    }
203
204
205
206
207
208
    printf("%s\n", description);
  }
  void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods);
  void character_callback(GLFWwindow* window, unsigned int codepoint);
  void cursor_position_callback(GLFWwindow* window, double xpos, double ypos);
  void mouse_button_callback(GLFWwindow* window, int button, int action, int mods);
mathieu _alkama_ m's avatar
mathieu _alkama_ m committed
209
  void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
210

Gargaj's avatar
add SDL  
Gargaj committed
211
212
  bool Open( RENDERER_SETTINGS * settings )
  {
213
214
    glfwSetErrorCallback(error_callback);
    theShader = 0;
mathieu _alkama_ m's avatar
mathieu _alkama_ m committed
215
216
217
218
219
    
#ifdef __APPLE__
    glfwInitHint(GLFW_COCOA_CHDIR_RESOURCES, GLFW_FALSE);
#endif

220
    if(!glfwInit())
Gargaj's avatar
add SDL  
Gargaj committed
221
    {
222
      printf("[Renderer] GLFW init failed\n");
Gargaj's avatar
add SDL  
Gargaj committed
223
224
      return false;
    }
mathieu _alkama_ m's avatar
mathieu _alkama_ m committed
225
    printf("[GLFW] Version String: %s\n", glfwGetVersionString());
Gargaj's avatar
add SDL  
Gargaj committed
226

227
228
    nWidth = settings->nWidth;
    nHeight = settings->nHeight;
Gargaj's avatar
add SDL  
Gargaj committed
229

230
231
232
233
234
235
    glfwWindowHint(GLFW_RED_BITS, 8);
    glfwWindowHint(GLFW_GREEN_BITS, 8);
    glfwWindowHint(GLFW_BLUE_BITS, 8);
    glfwWindowHint(GLFW_ALPHA_BITS, 8);
    glfwWindowHint(GLFW_DEPTH_BITS, 24);
    glfwWindowHint(GLFW_STENCIL_BITS, 8);
Gargaj's avatar
add SDL  
Gargaj committed
236

mathieu _alkama_ m's avatar
mathieu _alkama_ m committed
237
    glfwWindowHint(GLFW_DOUBLEBUFFER, GLFW_TRUE);
Gargaj's avatar
Gargaj committed
238

239
240
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
mathieu _alkama_ m's avatar
mathieu _alkama_ m committed
241
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
242
243
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

mathieu _alkama_ m's avatar
mathieu _alkama_ m committed
244
245
246
247
248
#ifdef __APPLE__
    glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_FALSE);
    glfwWindowHint(GLFW_COCOA_GRAPHICS_SWITCHING, GLFW_FALSE);
#endif

249
    // TODO: change in case of resize support
mathieu _alkama_ m's avatar
mathieu _alkama_ m committed
250
    glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
251

252
253
254
    // Prevent fullscreen window minimize on focus loss
    glfwWindowHint(GLFW_AUTO_ICONIFY, GL_FALSE);

255
    GLFWmonitor *monitor = settings->windowMode == RENDERER_WINDOWMODE_FULLSCREEN ? glfwGetPrimaryMonitor() : NULL;
Gargaj's avatar
Gargaj committed
256

257
    mWindow = glfwCreateWindow(nWidth, nHeight, "BONZOMATIC - GLFW edition", monitor, NULL);
Gargaj's avatar
Gargaj committed
258
    if (!mWindow)
Gargaj's avatar
Gargaj committed
259
    {
260
261
      printf("[GLFW] Window creation failed\n");
      glfwTerminate();
Gargaj's avatar
add SDL  
Gargaj committed
262
      return false;
Gargaj's avatar
Gargaj committed
263
    }
Gargaj's avatar
add SDL  
Gargaj committed
264

265
266
267
268
269
#ifdef __APPLE__
#ifdef BONZOMATIC_ENABLE_TOUCHBAR
    ShowTouchBar(mWindow);
#endif
#endif
270
      
271
    glfwMakeContextCurrent(mWindow);
Gargaj's avatar
add SDL  
Gargaj committed
272

273
274
275
276
277
    // TODO: here add text callbacks
    glfwSetKeyCallback(mWindow, key_callback);
    glfwSetCharCallback(mWindow, character_callback);
    glfwSetCursorPosCallback(mWindow, cursor_position_callback);
    glfwSetMouseButtonCallback(mWindow, mouse_button_callback);
mathieu _alkama_ m's avatar
mathieu _alkama_ m committed
278
    glfwSetScrollCallback(mWindow, scroll_callback);
Gargaj's avatar
Gargaj committed
279

ferris's avatar
ferris committed
280
    glewExperimental = GL_TRUE;
281
282
    GLenum err = glewInit();
    if (GLEW_OK != err)
Gargaj's avatar
Gargaj committed
283
    {
284
285
286
        printf("[GLFW] glewInit failed: %s\n", glewGetErrorString(err));
        glfwTerminate();
        return false;
Gargaj's avatar
Gargaj committed
287
    }
288
    printf("[GLFW] Using GLEW %s\n", glewGetString(GLEW_VERSION));
289
    glGetError(); // reset glew error
Gargaj's avatar
Gargaj committed
290

291
292
    glfwSwapInterval(1);

293
#ifdef _WIN32
Gargaj's avatar
Gargaj committed
294
295
    if (settings->bVsync)
      wglSwapIntervalEXT(1);
296
#endif
Gargaj's avatar
Gargaj committed
297

mathieu _alkama_ m's avatar
mathieu _alkama_ m committed
298
299
    printf("[GLFW] OpenGL Version %s, GLSL %s\n", glGetString(GL_VERSION), glGetString(GL_SHADING_LANGUAGE_VERSION));
    
300
    // Now, since OpenGL is behaving a lot in fullscreen modes, lets collect the real obtained size!
mathieu _alkama_ m's avatar
mathieu _alkama_ m committed
301
    printf("[GLFW] Requested framebuffer size: %d x %d\n", nWidth, nHeight);
302
303
304
305
306
307
308
    int fbWidth = 1;
    int fbHeight = 1;
    glfwGetFramebufferSize(mWindow, &fbWidth, &fbHeight);
    nWidth = settings->nWidth = fbWidth;
    nHeight = settings->nHeight = fbHeight;
    printf("[GLFW] Obtained framebuffer size: %d x %d\n", fbWidth, fbHeight);
    
ferris's avatar
ferris committed
309
    static float pFullscreenQuadVertices[] =
Gargaj's avatar
Gargaj committed
310
311
312
313
314
315
316
317
318
319
    {
      -1.0, -1.0,  0.5, 0.0, 0.0,
      -1.0,  1.0,  0.5, 0.0, 1.0,
       1.0, -1.0,  0.5, 1.0, 0.0,
       1.0,  1.0,  0.5, 1.0, 1.0,
    };

    glGenBuffers( 1, &glhFullscreenQuadVB );
    glBindBuffer( GL_ARRAY_BUFFER, glhFullscreenQuadVB );
    glBufferData( GL_ARRAY_BUFFER, sizeof(float) * 5 * 4, pFullscreenQuadVertices, GL_STATIC_DRAW );
320
    glBindBuffer( GL_ARRAY_BUFFER, 0 );
Gargaj's avatar
Gargaj committed
321
322
323
324
325

    glGenVertexArrays(1, &glhFullscreenQuadVA);

    glhVertexShader = glCreateShader( GL_VERTEX_SHADER );

Marco Foco's avatar
Marco Foco committed
326
    const char * szVertexShader =
ferris's avatar
ferris committed
327
328
329
330
      "#version 410 core\n"
      "in vec3 in_pos;\n"
      "in vec2 in_texcoord;\n"
      "out vec2 out_texcoord;\n"
Gargaj's avatar
Gargaj committed
331
332
333
334
335
      "void main()\n"
      "{\n"
      "  gl_Position = vec4( in_pos.x, in_pos.y, in_pos.z, 1.0 );\n"
      "  out_texcoord = in_texcoord;\n"
      "}";
336
    GLint nShaderSize = (GLint)strlen(szVertexShader);
Gargaj's avatar
Gargaj committed
337

Gargaj's avatar
Gargaj committed
338
    glShaderSource(glhVertexShader, 1, (const GLchar**)&szVertexShader, &nShaderSize);
Gargaj's avatar
Gargaj committed
339
340
341
342
343
344
345
346
347
    glCompileShader(glhVertexShader);

    GLint size = 0;
    GLint result = 0;
    char szErrorBuffer[5000];
    glGetShaderInfoLog(glhVertexShader, 4000, &size, szErrorBuffer);
    glGetShaderiv(glhVertexShader, GL_COMPILE_STATUS, &result);
    if (!result)
    {
ferris's avatar
ferris committed
348
      printf("[Renderer] Vertex shader compilation failed\n");
Gargaj's avatar
Gargaj committed
349
350
351
      return false;
    }

Gargaj's avatar
Gargaj committed
352
353
#define GUIQUADVB_SIZE (1024 * 6)

Marco Foco's avatar
Marco Foco committed
354
    const char * defaultGUIVertexShader =
ferris's avatar
ferris committed
355
356
357
358
359
360
361
362
      "#version 410 core\n"
      "in vec3 in_pos;\n"
      "in vec4 in_color;\n"
      "in vec2 in_texcoord;\n"
      "in float in_factor;\n"
      "out vec4 out_color;\n"
      "out vec2 out_texcoord;\n"
      "out float out_factor;\n"
Gargaj's avatar
Gargaj committed
363
364
365
366
367
      "uniform vec2 v2Offset;\n"
      "uniform mat4 matProj;\n"
      "void main()\n"
      "{\n"
      "  vec4 pos = vec4( in_pos + vec3(v2Offset,0), 1.0 );\n"
368
      "  gl_Position = pos * matProj;\n"
Gargaj's avatar
Gargaj committed
369
370
371
372
      "  out_color = in_color;\n"
      "  out_texcoord = in_texcoord;\n"
      "  out_factor = in_factor;\n"
      "}\n";
Marco Foco's avatar
Marco Foco committed
373
    const char * defaultGUIPixelShader =
ferris's avatar
ferris committed
374
      "#version 410 core\n"
Gargaj's avatar
Gargaj committed
375
      "uniform sampler2D tex;\n"
ferris's avatar
ferris committed
376
377
378
379
      "in vec4 out_color;\n"
      "in vec2 out_texcoord;\n"
      "in float out_factor;\n"
      "out vec4 frag_color;\n"
Gargaj's avatar
Gargaj committed
380
381
382
383
      "void main()\n"
      "{\n"
      "  vec4 v4Texture = out_color * texture( tex, out_texcoord );\n"
      "  vec4 v4Color = out_color;\n"
ferris's avatar
ferris committed
384
      "  frag_color = mix( v4Texture, v4Color, out_factor );\n"
Gargaj's avatar
Gargaj committed
385
386
387
388
389
      "}\n";

    glhGUIProgram = glCreateProgram();

    GLuint vshd = glCreateShader(GL_VERTEX_SHADER);
390
    nShaderSize = (GLint)strlen(defaultGUIVertexShader);
Gargaj's avatar
Gargaj committed
391
392
393
394
395
396
397

    glShaderSource(vshd, 1, (const GLchar**)&defaultGUIVertexShader, &nShaderSize);
    glCompileShader(vshd);
    glGetShaderInfoLog(vshd, 4000, &size, szErrorBuffer);
    glGetShaderiv(vshd, GL_COMPILE_STATUS, &result);
    if (!result)
    {
ferris's avatar
ferris committed
398
      printf("[Renderer] Default GUI vertex shader compilation failed\n");
Gargaj's avatar
Gargaj committed
399
400
401
402
      return false;
    }

    GLuint fshd = glCreateShader(GL_FRAGMENT_SHADER);
403
    nShaderSize = (GLint)strlen(defaultGUIPixelShader);
Gargaj's avatar
Gargaj committed
404
405
406
407
408
409
410

    glShaderSource(fshd, 1, (const GLchar**)&defaultGUIPixelShader, &nShaderSize);
    glCompileShader(fshd);
    glGetShaderInfoLog(fshd, 4000, &size, szErrorBuffer);
    glGetShaderiv(fshd, GL_COMPILE_STATUS, &result);
    if (!result)
    {
ferris's avatar
ferris committed
411
      printf("[Renderer] Default GUI pixel shader compilation failed\n");
Gargaj's avatar
Gargaj committed
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
      return false;
    }

    glAttachShader(glhGUIProgram, vshd);
    glAttachShader(glhGUIProgram, fshd);
    glLinkProgram(glhGUIProgram);
    glGetProgramiv(glhGUIProgram, GL_LINK_STATUS, &result);
    if (!result)
    {
      return false;
    }

    glGenBuffers( 1, &glhGUIVB );
    glBindBuffer( GL_ARRAY_BUFFER, glhGUIVB );

    glGenVertexArrays(1, &glhGUIVA);

429
430
431
    //create PBOs to hold the data. this allocates memory for them too
    glGenBuffers(2, pbo);
    glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo[0]);
432
    glBufferData(GL_PIXEL_PACK_BUFFER, nWidth * nHeight * sizeof(unsigned int), NULL, GL_STREAM_READ);
433
    glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo[1]);
434
    glBufferData(GL_PIXEL_PACK_BUFFER, nWidth * nHeight * sizeof(unsigned int), NULL, GL_STREAM_READ);
435
    //unbind buffers for now
436
    glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
437

438
439
    glViewport(0, 0, nWidth, nHeight);
    
Gargaj's avatar
add SDL  
Gargaj committed
440
441
442
443
    run = true;

    return true;
  }
Gargaj's avatar
Gargaj committed
444

Gargaj's avatar
Gargaj committed
445
446
  KeyEvent keyEventBuffer[512];
  int keyEventBufferCount = 0;
Gargaj's avatar
Gargaj committed
447
448
  MouseEvent mouseEventBuffer[512];
  int mouseEventBufferCount = 0;
449
  void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
Gargaj's avatar
add SDL  
Gargaj committed
450
  {
451
    if (action == GLFW_PRESS || action == GLFW_REPEAT) {
452
      if ((key==GLFW_KEY_F4 && (mods&GLFW_MOD_ALT)) || (key==GLFW_KEY_ESCAPE&&(mods&GLFW_MOD_SHIFT))) {
Gargaj's avatar
add SDL  
Gargaj committed
453
454
        run = false;
      }
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
      int sciKey = 0;
      bool bNormalKey = false;
      switch (key) {
        case GLFW_KEY_DOWN:         sciKey = SCK_DOWN;      break;
        case GLFW_KEY_UP:           sciKey = SCK_UP;        break;
        case GLFW_KEY_LEFT:         sciKey = SCK_LEFT;      break;
        case GLFW_KEY_RIGHT:        sciKey = SCK_RIGHT;     break;
        case GLFW_KEY_HOME:         sciKey = SCK_HOME;      break;
        case GLFW_KEY_END:          sciKey = SCK_END;       break;
        case GLFW_KEY_PAGE_UP:      sciKey = SCK_PRIOR;     break;
        case GLFW_KEY_PAGE_DOWN:    sciKey = SCK_NEXT;      break;
        case GLFW_KEY_DELETE:       sciKey = SCK_DELETE;    break;
        case GLFW_KEY_INSERT:       sciKey = SCK_INSERT;    break;
        case GLFW_KEY_ESCAPE:       sciKey = SCK_ESCAPE;    break;
        case GLFW_KEY_BACKSPACE:    sciKey = SCK_BACK;      break;
        case GLFW_KEY_TAB:          sciKey = SCK_TAB;       break;
        case GLFW_KEY_ENTER:        sciKey = SCK_RETURN;    break;
        case GLFW_KEY_KP_ADD:       sciKey = SCK_ADD;       break;
        case GLFW_KEY_KP_SUBTRACT:  sciKey = SCK_SUBTRACT;  break;
        case GLFW_KEY_KP_DIVIDE:    sciKey = SCK_DIVIDE;    break;
//           case GLFW_KEY_LSUPER:       sciKey = SCK_WIN;       break;
//           case GLFW_KEY_RSUPER:       sciKey = SCK_RWIN;      break;
        case GLFW_KEY_MENU:         sciKey = SCK_MENU;      break;
//           case GLFW_KEY_SLASH:        sciKey = '/';           break;
//           case GLFW_KEY_ASTERISK:     sciKey = '`';           break;
//           case GLFW_KEY_LEFTBRACKET:  sciKey = '[';           break;
//           case GLFW_KEY_BACKSLASH:    sciKey = '\\';          break;
//           case GLFW_KEY_RIGHTBRACKET: sciKey = ']';           break;
        case GLFW_KEY_F1:           sciKey = 282;           break;
        case GLFW_KEY_F2:           sciKey = 283;           break;
        case GLFW_KEY_F3:           sciKey = 284;           break;
        case GLFW_KEY_F4:           sciKey = 285;           break;
        case GLFW_KEY_F5:           sciKey = 286;           break;
        case GLFW_KEY_F6:           sciKey = 287;           break;
        case GLFW_KEY_F7:           sciKey = 288;           break;
        case GLFW_KEY_F8:           sciKey = 289;           break;
        case GLFW_KEY_F9:           sciKey = 290;           break;
        case GLFW_KEY_F10:          sciKey = 291;           break;
        case GLFW_KEY_F11:          sciKey = 292;           break;
        case GLFW_KEY_F12:          sciKey = 293;           break;
        case GLFW_KEY_LEFT_SHIFT:
        case GLFW_KEY_RIGHT_SHIFT:
        case GLFW_KEY_LEFT_ALT:
        case GLFW_KEY_RIGHT_ALT:
        case GLFW_KEY_LEFT_CONTROL:
        case GLFW_KEY_RIGHT_CONTROL:
        case GLFW_KEY_LEFT_SUPER:
        case GLFW_KEY_RIGHT_SUPER:
          sciKey = 0;
          break;
        default:
          bNormalKey = true;
          // TODO: Horrible hack to migrate from GLFW (that uses ascii maj for keys) to scintilla min keys
          if ( (key >= GLFW_KEY_A) && (key <= GLFW_KEY_Z) ) {
            sciKey = key+32;
          }
          else {
Gargaj's avatar
Gargaj committed
512
            sciKey = 0;
513
          }
514
      }
515
      if ((bNormalKey && mods) || !bNormalKey)
516
      {
517
518
519
520
521
522
        keyEventBuffer[keyEventBufferCount].ctrl  = (mods & GLFW_MOD_CONTROL) || (mods & GLFW_MOD_SUPER);
        keyEventBuffer[keyEventBufferCount].alt   = mods & GLFW_MOD_ALT;
        keyEventBuffer[keyEventBufferCount].shift = mods & GLFW_MOD_SHIFT;
        keyEventBuffer[keyEventBufferCount].scanCode = sciKey;
        keyEventBuffer[keyEventBufferCount].character = 0;
        keyEventBufferCount++;
Gargaj's avatar
add SDL  
Gargaj committed
523
524
      }
    }
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
  }
  void character_callback(GLFWwindow* window, unsigned int codepoint)
  {
    keyEventBuffer[keyEventBufferCount].ctrl  = false;
    keyEventBuffer[keyEventBufferCount].alt   = false;
    keyEventBuffer[keyEventBufferCount].shift = false;
    keyEventBuffer[keyEventBufferCount].scanCode = 0;
    // TODO: handle special things with Scintilla for UFT8 codepoints?
    keyEventBuffer[keyEventBufferCount].character = codepoint;
    keyEventBufferCount++;
  }
  void cursor_position_callback(GLFWwindow* window, double xpos, double ypos)
  {
    mouseEventBuffer[mouseEventBufferCount].eventType = MOUSEEVENTTYPE_MOVE;
    mouseEventBuffer[mouseEventBufferCount].x = xpos;
    mouseEventBuffer[mouseEventBufferCount].y = ypos;
    if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS) mouseEventBuffer[mouseEventBufferCount].button = MOUSEBUTTON_LEFT;
    mouseEventBufferCount++;
  }
  void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
  {
    if (action == GLFW_PRESS) {
      mouseEventBuffer[mouseEventBufferCount].eventType = MOUSEEVENTTYPE_DOWN;
    }
    else if (action == GLFW_RELEASE) {
      mouseEventBuffer[mouseEventBufferCount].eventType = MOUSEEVENTTYPE_UP;
    }
    double xpos, ypos;
    glfwGetCursorPos(window, &xpos, &ypos);
    mouseEventBuffer[mouseEventBufferCount].x = xpos;
    mouseEventBuffer[mouseEventBufferCount].y = ypos;
    switch(button)
    {
      case GLFW_MOUSE_BUTTON_MIDDLE: mouseEventBuffer[mouseEventBufferCount].button = MOUSEBUTTON_MIDDLE; break;
      case GLFW_MOUSE_BUTTON_RIGHT:  mouseEventBuffer[mouseEventBufferCount].button = MOUSEBUTTON_RIGHT; break;
      case GLFW_MOUSE_BUTTON_LEFT:
      default:                mouseEventBuffer[mouseEventBufferCount].button = MOUSEBUTTON_LEFT; break;
    }
    mouseEventBufferCount++;
  }
mathieu _alkama_ m's avatar
mathieu _alkama_ m committed
565
566
567
568
569
570
571
  void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
  {
    mouseEventBuffer[mouseEventBufferCount].eventType = MOUSEEVENTTYPE_SCROLL;
    mouseEventBuffer[mouseEventBufferCount].x = xoffset;
    mouseEventBuffer[mouseEventBufferCount].y = yoffset;
    mouseEventBufferCount++;
  }
572
573
574

  void StartFrame()
  {
Gargaj's avatar
add SDL  
Gargaj committed
575
576
577
578
579
    glClearColor(0.08f, 0.18f, 0.18f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
  }
  void EndFrame()
  {
580
581
582
583
    keyEventBufferCount = 0;
    mouseEventBufferCount = 0;
    glfwSwapBuffers(mWindow);
    glfwPollEvents();
Gargaj's avatar
add SDL  
Gargaj committed
584
585
586
  }
  bool WantsToQuit()
  {
587
    return glfwWindowShouldClose(mWindow) || !run;
Gargaj's avatar
add SDL  
Gargaj committed
588
589
590
  }
  void Close()
  {
591
592
    glfwDestroyWindow(mWindow);
    glfwTerminate();
Gargaj's avatar
add SDL  
Gargaj committed
593
  }
Gargaj's avatar
Gargaj committed
594
595
596

  void RenderFullscreenQuad()
  {
Gargaj's avatar
Gargaj committed
597
598
    glBindVertexArray(glhFullscreenQuadVA);

Gargaj's avatar
Gargaj committed
599
    glUseProgram(theShader);
Gargaj's avatar
Gargaj committed
600
601
602

    glBindBuffer( GL_ARRAY_BUFFER, glhFullscreenQuadVB );

603
604
605
606
607
608
    const GLint position = glGetAttribLocation( theShader, "in_pos" );
    if (position >= 0)
    {
      glVertexAttribPointer( position, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 5, (GLvoid*)(0 * sizeof(GLfloat)) );
      glEnableVertexAttribArray( position );
    }
Gargaj's avatar
Gargaj committed
609

610
611
612
613
614
615
    const GLint texcoord = glGetAttribLocation( theShader, "in_texcoord" );
    if (texcoord >= 0)
    {
      glVertexAttribPointer( texcoord, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 5, (GLvoid*)(3 * sizeof(GLfloat)) );
      glEnableVertexAttribArray( texcoord );
    }
Gargaj's avatar
Gargaj committed
616
617
618

    glBindBuffer( GL_ARRAY_BUFFER, glhFullscreenQuadVB );
    glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
619
620
621
622
623
624

    if (texcoord >= 0)
      glDisableVertexAttribArray( texcoord );

    if (position >= 0)
      glDisableVertexAttribArray( position );
Gargaj's avatar
Gargaj committed
625

626
    glUseProgram(0);
Gargaj's avatar
Gargaj committed
627
628
  }

Marco Foco's avatar
Marco Foco committed
629
  bool ReloadShader( const char * szShaderCode, int nShaderCodeSize, char * szErrorBuffer, int nErrorBufferSize )
Gargaj's avatar
Gargaj committed
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
  {
    GLuint prg = glCreateProgram();
    GLuint shd = glCreateShader(GL_FRAGMENT_SHADER);
    GLint size = 0;
    GLint result = 0;

    glShaderSource(shd, 1, (const GLchar**)&szShaderCode, &nShaderCodeSize);
    glCompileShader(shd);
    glGetShaderInfoLog(shd, nErrorBufferSize, &size, szErrorBuffer);
    glGetShaderiv(shd, GL_COMPILE_STATUS, &result);
    if (!result)
    {
      glDeleteProgram(prg);
      glDeleteShader(shd);
      return false;
    }

Gargaj's avatar
Gargaj committed
647
    glAttachShader(prg, glhVertexShader);
Gargaj's avatar
Gargaj committed
648
649
650
651
652
653
654
655
656
657
658
    glAttachShader(prg, shd);
    glLinkProgram(prg);
    glGetProgramInfoLog(prg, nErrorBufferSize - size, &size, szErrorBuffer + size);
    glGetProgramiv(prg, GL_LINK_STATUS, &result);
    if (!result)
    {
      glDeleteProgram(prg);
      glDeleteShader(shd);
      return false;
    }

Gargaj's avatar
Gargaj committed
659
660
    if (theShader)
      glDeleteProgram(theShader);
Gargaj's avatar
Gargaj committed
661
662
663
664
665
666

    theShader = prg;

    return true;
  }

Marco Foco's avatar
Marco Foco committed
667
  void SetShaderConstant( const char * szConstName, float x )
Gargaj's avatar
Gargaj committed
668
669
670
671
  {
    GLint location = glGetUniformLocation( theShader, szConstName );
    if ( location != -1 )
    {
ferris's avatar
ferris committed
672
      glProgramUniform1f( theShader, location, x );
Gargaj's avatar
Gargaj committed
673
674
675
    }
  }

Marco Foco's avatar
Marco Foco committed
676
  void SetShaderConstant( const char * szConstName, float x, float y )
Gargaj's avatar
Gargaj committed
677
678
679
680
  {
    GLint location = glGetUniformLocation( theShader, szConstName );
    if ( location != -1 )
    {
ferris's avatar
ferris committed
681
      glProgramUniform2f( theShader, location, x, y );
Gargaj's avatar
Gargaj committed
682
683
684
    }
  }

Gargaj's avatar
Gargaj committed
685
686
  struct GLTexture : public Texture
  {
687
    GLuint ID;
Gargaj's avatar
Gargaj committed
688
689
690
691
    int unit;
  };

  int textureUnit = 0;
Marco Foco's avatar
Marco Foco committed
692
  Texture * CreateRGBA8TextureFromFile( const char * szFilename )
Gargaj's avatar
Gargaj committed
693
694
695
696
  {
    int comp = 0;
    int width = 0;
    int height = 0;
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
    void * data = nullptr;
    GLenum internalFormat = GL_SRGB8_ALPHA8;
    GLenum srcFormat = GL_RGBA;
    GLenum format = GL_UNSIGNED_BYTE;
    if ( stbi_is_hdr( szFilename ) )
    {
      internalFormat = GL_RGBA32F;
      format = GL_FLOAT;
      data = stbi_loadf( szFilename, &width, &height, &comp, STBI_rgb_alpha );
    }
    else
    {
      data = stbi_load( szFilename, &width, &height, &comp, STBI_rgb_alpha );
    }
    if (!data) return NULL;
Gargaj's avatar
Gargaj committed
712
713
714
715
716
717
718
719
720
721

    GLuint glTexId = 0;
    glGenTextures( 1, &glTexId );
    glBindTexture( GL_TEXTURE_2D, glTexId );

    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

722
    glTexImage2D( GL_TEXTURE_2D, 0, internalFormat, width, height, 0, srcFormat, format, data );
Gargaj's avatar
Gargaj committed
723

724
    stbi_image_free(data);
Gargaj's avatar
Gargaj committed
725

Gargaj's avatar
Gargaj committed
726
    GLTexture * tex = new GLTexture();
Gargaj's avatar
Gargaj committed
727
728
    tex->width = width;
    tex->height = height;
729
    tex->ID = glTexId;
Gargaj's avatar
Gargaj committed
730
    tex->type = TEXTURETYPE_2D;
Gargaj's avatar
Gargaj committed
731
    tex->unit = textureUnit++;
Gargaj's avatar
Gargaj committed
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
    return tex;
  }

  Texture * Create1DR32Texture( int w )
  {
    GLuint glTexId = 0;
    glGenTextures( 1, &glTexId );
    glBindTexture( GL_TEXTURE_1D, glTexId );

    glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT );
    glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
    glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

    float * data = new float[w];
    for ( int i = 0; i < w; ++i )
Gargaj's avatar
Gargaj committed
747
      data[i] = 0.0f;
Gargaj's avatar
Gargaj committed
748
749
750
751
752
753
754

    glTexImage1D( GL_TEXTURE_1D, 0, GL_R32F, w, 0, GL_RED, GL_FLOAT, data );

    delete[] data;

    glBindTexture( GL_TEXTURE_1D, 0 );

Gargaj's avatar
Gargaj committed
755
    GLTexture * tex = new GLTexture();
Gargaj's avatar
Gargaj committed
756
757
    tex->width = w;
    tex->height = 1;
758
    tex->ID = glTexId;
Gargaj's avatar
Gargaj committed
759
    tex->type = TEXTURETYPE_1D;
Gargaj's avatar
Gargaj committed
760
    tex->unit = textureUnit++;
Gargaj's avatar
Gargaj committed
761
762
763
    return tex;
  }

Marco Foco's avatar
Marco Foco committed
764
  void SetShaderTexture( const char * szTextureName, Texture * tex )
Gargaj's avatar
Gargaj committed
765
  {
766
767
768
    if (!tex)
      return;

Gargaj's avatar
Gargaj committed
769
770
771
    GLint location = glGetUniformLocation( theShader, szTextureName );
    if ( location != -1 )
    {
ferris's avatar
ferris committed
772
      glProgramUniform1i( theShader, location, ((GLTexture*)tex)->unit );
Gargaj's avatar
Gargaj committed
773
      glActiveTexture( GL_TEXTURE0 + ((GLTexture*)tex)->unit );
Gargaj's avatar
Gargaj committed
774
775
      switch( tex->type)
      {
776
777
        case TEXTURETYPE_1D: glBindTexture( GL_TEXTURE_1D, ((GLTexture*)tex)->ID ); break;
        case TEXTURETYPE_2D: glBindTexture( GL_TEXTURE_2D, ((GLTexture*)tex)->ID ); break;
Gargaj's avatar
Gargaj committed
778
779
780
781
782
783
      }
    }
  }

  bool UpdateR32Texture( Texture * tex, float * data )
  {
Gargaj's avatar
Gargaj committed
784
    glActiveTexture( GL_TEXTURE0 + ((GLTexture*)tex)->unit );
785
    glBindTexture( GL_TEXTURE_1D, ((GLTexture*)tex)->ID );
Gargaj's avatar
Gargaj committed
786
787
788
789
790
    glTexSubImage1D( GL_TEXTURE_1D, 0, 0, tex->width, GL_RED, GL_FLOAT, data );

    return true;
  }

Marco Foco's avatar
Marco Foco committed
791
  Texture * CreateA8TextureFromData( int w, int h, const unsigned char * data )
Gargaj's avatar
Gargaj committed
792
793
794
795
  {
    GLuint glTexId = 0;
    glGenTextures(1, &glTexId);
    glBindTexture(GL_TEXTURE_2D, glTexId);
796
797
798
799
    unsigned int * p32bitData = new unsigned int[ w * h ];
    for(int i=0; i<w*h; i++) p32bitData[i] = (data[i] << 24) | 0xFFFFFF;
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, p32bitData);
    delete[] p32bitData;
ferris's avatar
ferris committed
800

Gargaj's avatar
Gargaj committed
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

    GLTexture * tex = new GLTexture();
    tex->width = w;
    tex->height = h;
    tex->ID = glTexId;
    tex->type = TEXTURETYPE_2D;
    tex->unit = 0; // this is always 0 cos we're not using shaders here
    return tex;
  }

  void ReleaseTexture( Texture * tex )
  {
    glDeleteTextures(1, &((GLTexture*)tex)->ID );
  }

Gargaj's avatar
Gargaj committed
817
818
819
820
821
822
823
  //////////////////////////////////////////////////////////////////////////
  // text rendering

  int nDrawCallCount = 0;
  Texture * lastTexture = NULL;
  void StartTextRendering()
  {
Gargaj's avatar
Gargaj committed
824
825
826
827
828
    glUseProgram(glhGUIProgram);
    glBindVertexArray(glhGUIVA);

    glEnable( GL_BLEND );
    glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
Gargaj's avatar
Gargaj committed
829
830
831
832
833
834
835
836
837
  }

  int bufferPointer = 0;
  unsigned char buffer[GUIQUADVB_SIZE * sizeof(float) * 7];
  bool lastModeIsQuad = true;
  void __FlushRenderCache()
  {
    if (!bufferPointer) return;

Gargaj's avatar
Gargaj committed
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
    glBindBuffer( GL_ARRAY_BUFFER, glhGUIVB );
    glBufferData( GL_ARRAY_BUFFER, sizeof(float) * 7 * bufferPointer, buffer, GL_DYNAMIC_DRAW );

    GLuint position = glGetAttribLocation( glhGUIProgram, "in_pos" );
    glVertexAttribPointer( position, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 7, (GLvoid*)(0 * sizeof(GLfloat)) );
    glEnableVertexAttribArray( position );

    GLuint color = glGetAttribLocation( glhGUIProgram, "in_color" );
    glVertexAttribPointer( color, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(float) * 7, (GLvoid*)(3 * sizeof(GLfloat)) );
    glEnableVertexAttribArray( color );

    GLuint texcoord = glGetAttribLocation( glhGUIProgram, "in_texcoord" );
    glVertexAttribPointer( texcoord, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 7, (GLvoid*)(4 * sizeof(GLfloat)) );
    glEnableVertexAttribArray( texcoord );

    GLuint factor = glGetAttribLocation( glhGUIProgram, "in_factor" );
    glVertexAttribPointer( factor, 1, GL_FLOAT, GL_FALSE, sizeof(float) * 7, (GLvoid*)(6 * sizeof(GLfloat)) );
    glEnableVertexAttribArray( factor );

    if (lastModeIsQuad)
    {
      glDrawArrays( GL_TRIANGLES, 0, bufferPointer );
    }
    else
    {
      glDrawArrays( GL_LINES, 0, bufferPointer );
    }
Gargaj's avatar
Gargaj committed
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881

    bufferPointer = 0;
  }
  void __WriteVertexToBuffer( const Vertex & v )
  {
    if (bufferPointer >= GUIQUADVB_SIZE)
    {
      __FlushRenderCache();
    }

    float * f = (float*)(buffer + bufferPointer * sizeof(float) * 7);
    *(f++) = v.x;
    *(f++) = v.y;
    *(f++) = 0.0;
    *(unsigned int *)(f++) = v.c;
    *(f++) = v.u;
    *(f++) = v.v;
Gargaj's avatar
Gargaj committed
882
    *(f++) = lastTexture ? 0.0f : 1.0f;
Gargaj's avatar
Gargaj committed
883
884
    bufferPointer++;
  }
Gargaj's avatar
Gargaj committed
885
886
  void BindTexture( Texture * tex )
  {
Gargaj's avatar
Gargaj committed
887
888
889
890
891
892
    if (lastTexture != tex)
    {
      lastTexture = tex;
      if (tex)
      {
        __FlushRenderCache();
Gargaj's avatar
Gargaj committed
893
894
895
896

        GLint location = glGetUniformLocation( glhGUIProgram, "tex" );
        if ( location != -1 )
        {
ferris's avatar
ferris committed
897
          glProgramUniform1i( glhGUIProgram, location, ((GLTexture*)tex)->unit );
Gargaj's avatar
Gargaj committed
898
899
900
901
902
903
904
905
          glActiveTexture( GL_TEXTURE0 + ((GLTexture*)tex)->unit );
          switch( tex->type)
          {
            case TEXTURETYPE_1D: glBindTexture( GL_TEXTURE_1D, ((GLTexture*)tex)->ID ); break;
            case TEXTURETYPE_2D: glBindTexture( GL_TEXTURE_2D, ((GLTexture*)tex)->ID ); break;
          }
        }

Gargaj's avatar
Gargaj committed
906
907
      }
    }
Gargaj's avatar
Gargaj committed
908
909
  }

910
  void RenderQuad( const Vertex & a, const Vertex & b, const Vertex & c, const Vertex & d )
Gargaj's avatar
Gargaj committed
911
  {
Gargaj's avatar
Gargaj committed
912
913
914
915
916
917
918
919
920
921
922
    if (!lastModeIsQuad)
    {
      __FlushRenderCache();
      lastModeIsQuad = true;
    }
    __WriteVertexToBuffer(a);
    __WriteVertexToBuffer(b);
    __WriteVertexToBuffer(d);
    __WriteVertexToBuffer(b);
    __WriteVertexToBuffer(c);
    __WriteVertexToBuffer(d);
Gargaj's avatar
Gargaj committed
923
924
  }

925
  void RenderLine( const Vertex & a, const Vertex & b )
Gargaj's avatar
Gargaj committed
926
  {
Gargaj's avatar
Gargaj committed
927
928
929
930
931
932
933
    if (lastModeIsQuad)
    {
      __FlushRenderCache();
      lastModeIsQuad = false;
    }
    __WriteVertexToBuffer(a);
    __WriteVertexToBuffer(b);
Gargaj's avatar
Gargaj committed
934
935
  }

Gargaj's avatar
Gargaj committed
936
937
938
  void SetTextRenderingViewport( Scintilla::PRectangle rect )
  {
    __FlushRenderCache();
Gargaj's avatar
Gargaj committed
939
940
941
942
943
944
945

    float pGUIMatrix[16];
    MatrixOrthoOffCenterLH( pGUIMatrix, 0.0f, (float)nWidth, (float)nHeight, 0.0f, -1.0f, 1.0f );

    GLint location = glGetUniformLocation( glhGUIProgram, "matProj" );
    if ( location != -1 )
    {
ferris's avatar
ferris committed
946
       glProgramUniformMatrix4fv( glhGUIProgram, location, 1, GL_FALSE, pGUIMatrix );
Gargaj's avatar
Gargaj committed
947
948
949
950
951
    }

    location = glGetUniformLocation( glhGUIProgram, "v2Offset" );
    if ( location != -1 )
    {
ferris's avatar
ferris committed
952
      glProgramUniform2f( glhGUIProgram, location, rect.left, rect.top );
Gargaj's avatar
Gargaj committed
953
954
    }

Gargaj's avatar
Gargaj committed
955
956
    glEnable(GL_SCISSOR_TEST);
    glScissor(rect.left, nHeight - rect.bottom, rect.right - rect.left, rect.bottom - rect.top);
Gargaj's avatar
Gargaj committed
957
958
959
960
  }
  void EndTextRendering()
  {
    __FlushRenderCache();
Gargaj's avatar
Gargaj committed
961
962
963
964
965
966
967
968
969
970
971
972
973
974

    glBindBuffer( GL_ARRAY_BUFFER, glhFullscreenQuadVB );
    glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );

    GLuint position = glGetAttribLocation( glhGUIProgram, "in_pos" );
    GLuint color = glGetAttribLocation( glhGUIProgram, "in_color" );
    GLuint texcoord = glGetAttribLocation( glhGUIProgram, "in_texcoord" );
    GLuint factor = glGetAttribLocation( glhGUIProgram, "in_factor" );

    glDisableVertexAttribArray( factor );
    glDisableVertexAttribArray( texcoord );
    glDisableVertexAttribArray( color );
    glDisableVertexAttribArray( position );

975
    glUseProgram(0);
Gargaj's avatar
Gargaj committed
976

Gargaj's avatar
Gargaj committed
977
978
    glDisable(GL_BLEND);
    glDisable(GL_SCISSOR_TEST);
Gargaj's avatar
Gargaj committed
979
980
  }

981
982
983
984
985
986
987
988
  //////////////////////////////////////////////////////////////////////////

  bool GrabFrame( void * pPixelBuffer )
  {
    writeIndex = (writeIndex + 1) % 2;
    readIndex = (readIndex + 1) % 2;

    glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo[writeIndex]);
989
    glReadPixels(0, 0, nWidth, nHeight, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
990
991
    glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo[readIndex]);
    unsigned char * downsampleData = (unsigned char *)glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
ferris's avatar
ferris committed
992
    if (downsampleData)
993
    {
994
995
996
997
998
999
1000
1001
      unsigned char * src = downsampleData;
      unsigned char * dst = (unsigned char*)pPixelBuffer + nWidth * (nHeight - 1) * sizeof(unsigned int);
      for (int i=0; i<nHeight; i++)
      {
        memcpy( dst, src, sizeof(unsigned int) * nWidth );
        src += sizeof(unsigned int) * nWidth;
        dst -= sizeof(unsigned int) * nWidth;
      }
1002
1003
      glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
    }
1004
    glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
1005
1006
1007

    return true;
  }
Gargaj's avatar
Gargaj committed
1008

1009
}