Renderer.cpp 32.3 KB
Newer Older
Gargaj's avatar
Gargaj committed
1
#ifdef _WIN32
Gargaj's avatar
add SDL    
Gargaj committed
2
3
#include <windows.h>
#endif
4
5
6

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

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

Gargaj's avatar
add SDL    
Gargaj committed
14
#include "../Renderer.h"
15
#include <string.h>
Gargaj's avatar
add SDL    
Gargaj committed
16

Gargaj's avatar
Gargaj committed
17
#include "UniConversion.h"
Gargaj's avatar
Gargaj committed
18

19
#define STB_IMAGE_IMPLEMENTATION
20
#include "stb_image.h"
21
#include "Scintilla.h"
Gargaj's avatar
Gargaj committed
22

23
24
25
const char * shaderKeyword =
  "discard struct if else switch case default break goto return for while do continue";

ferris's avatar
ferris committed
26
const char * shaderType =
27
28
29
30
31
32
33
34
35
  "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 "
  "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
36
  "samplerCube samplerCubeShadow samplerCubeArrayShadow ";
37

ferris's avatar
ferris committed
38
const char * shaderBuiltin =
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
  "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
110
111
namespace Renderer
{
112
  char * defaultShaderFilename = "shader.glsl";
ferris's avatar
ferris committed
113
114
  char defaultShader[65536] =
    "#version 410 core\n"
Gargaj's avatar
Gargaj committed
115
116
    "\n"
    "uniform float fGlobalTime; // in seconds\n"
117
    "uniform vec2 v2Resolution; // viewport resolution (in pixels)\n"
Gargaj's avatar
Gargaj committed
118
    "\n"
119
    "uniform sampler1D texFFT; // towards 0.0 is bass / lower freq, towards 1.0 is higher / treble freq\n"
Gargaj's avatar
Gargaj committed
120
    "uniform sampler1D texFFTSmoothed; // this one has longer falloff and less harsh transients\n"
121
    "uniform sampler1D texFFTIntegrated; // this is continually increasing\n"
122
123
124
125
126
127
    "{%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
128
    "\n"
129
    "layout(location = 0) out vec4 out_color; // out_color must be written in order to see anything\n"
Gargaj's avatar
Gargaj committed
130
    "\n"
131
132
133
134
135
    "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
136
137
    "void main(void)\n"
    "{\n"
skomp's avatar
skomp committed
138
    "  vec2 uv = vec2(gl_FragCoord.x / v2Resolution.x, gl_FragCoord.y / v2Resolution.y);\n"
Gargaj's avatar
Gargaj committed
139
140
141
142
143
144
145
146
147
148
149
150
    "  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"
151
152
153
    "  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
154
155
    "}";

156
  GLFWwindow * mWindow = NULL;
Gargaj's avatar
add SDL    
Gargaj committed
157
158
  bool run = true;

159
160
161
162
163
164
165
  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
166

167
168
  int nWidth = 0;
  int nHeight = 0;
Gargaj's avatar
Gargaj committed
169

ferris's avatar
ferris committed
170
  void MatrixOrthoOffCenterLH(float * pout, float l, float r, float b, float t, float zn, float zf)
Gargaj's avatar
Gargaj committed
171
  {
ferris's avatar
ferris committed
172
    memset( pout, 0, sizeof(float) * 4 * 4 );
Gargaj's avatar
Gargaj committed
173
174
175
176
177
178
179
180
181
    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;
  }

182
183
184
185
  int readIndex = 0;
  int writeIndex = 1;
  GLuint pbo[2];

186
187
188
189
190
191
192
  static void error_callback(int error, const char *description) {
    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
193
  void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
194

Gargaj's avatar
add SDL    
Gargaj committed
195
196
  bool Open( RENDERER_SETTINGS * settings )
  {
197
198
199
    glfwSetErrorCallback(error_callback);
    theShader = 0;
    if(!glfwInit())
Gargaj's avatar
add SDL    
Gargaj committed
200
    {
201
      printf("[Renderer] GLFW init failed\n");
Gargaj's avatar
add SDL    
Gargaj committed
202
203
204
      return false;
    }

205
206
    nWidth = settings->nWidth;
    nHeight = settings->nHeight;
Gargaj's avatar
add SDL    
Gargaj committed
207

208
209
210
211
212
213
    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
214

215
    glfwWindowHint(GLFW_DOUBLEBUFFER, GL_TRUE);
Gargaj's avatar
Gargaj committed
216

217
218
219
220
221
222
223
224
225
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    // TODO: change in case of resize support
    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);

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

227
    mWindow = glfwCreateWindow(nWidth, nHeight, "BONZOMATIC - GLFW edition", monitor, NULL);
Gargaj's avatar
Gargaj committed
228
    if (!mWindow)
Gargaj's avatar
Gargaj committed
229
    {
230
231
      printf("[GLFW] Window creation failed\n");
      glfwTerminate();
Gargaj's avatar
add SDL    
Gargaj committed
232
      return false;
Gargaj's avatar
Gargaj committed
233
    }
Gargaj's avatar
add SDL    
Gargaj committed
234

235
    glfwMakeContextCurrent(mWindow);
Gargaj's avatar
add SDL    
Gargaj committed
236

237
238
239
240
241
    // 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
242
    glfwSetScrollCallback(mWindow, scroll_callback);
Gargaj's avatar
Gargaj committed
243

ferris's avatar
ferris committed
244
    glewExperimental = GL_TRUE;
245
246
    GLenum err = glewInit();
    if (GLEW_OK != err)
Gargaj's avatar
Gargaj committed
247
    {
248
249
250
        printf("[GLFW] glewInit failed: %s\n", glewGetErrorString(err));
        glfwTerminate();
        return false;
Gargaj's avatar
Gargaj committed
251
    }
252
    printf("[GLFW] Using GLEW %s\n", glewGetString(GLEW_VERSION));
Gargaj's avatar
Gargaj committed
253
    GLenum i = glGetError(); // reset glew error
Gargaj's avatar
Gargaj committed
254

255
256
    glfwSwapInterval(1);

257
#ifdef _WIN32
Gargaj's avatar
Gargaj committed
258
259
    if (settings->bVsync)
      wglSwapIntervalEXT(1);
260
#endif
Gargaj's avatar
Gargaj committed
261

ferris's avatar
ferris committed
262
    static float pFullscreenQuadVertices[] =
Gargaj's avatar
Gargaj committed
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
    {
      -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 );
    glBindBuffer( GL_ARRAY_BUFFER, NULL );

    glGenVertexArrays(1, &glhFullscreenQuadVA);

    glhVertexShader = glCreateShader( GL_VERTEX_SHADER );

    char * szVertexShader =
ferris's avatar
ferris committed
280
281
282
283
      "#version 410 core\n"
      "in vec3 in_pos;\n"
      "in vec2 in_texcoord;\n"
      "out vec2 out_texcoord;\n"
Gargaj's avatar
Gargaj committed
284
285
286
287
288
      "void main()\n"
      "{\n"
      "  gl_Position = vec4( in_pos.x, in_pos.y, in_pos.z, 1.0 );\n"
      "  out_texcoord = in_texcoord;\n"
      "}";
Gargaj's avatar
Gargaj committed
289
    GLint nShaderSize = strlen(szVertexShader);
Gargaj's avatar
Gargaj committed
290

Gargaj's avatar
Gargaj committed
291
    glShaderSource(glhVertexShader, 1, (const GLchar**)&szVertexShader, &nShaderSize);
Gargaj's avatar
Gargaj committed
292
293
294
295
296
297
298
299
300
    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
301
      printf("[Renderer] Vertex shader compilation failed\n");
Gargaj's avatar
Gargaj committed
302
303
304
      return false;
    }

Gargaj's avatar
Gargaj committed
305
306
#define GUIQUADVB_SIZE (1024 * 6)

ferris's avatar
ferris committed
307
    char * defaultGUIVertexShader =
ferris's avatar
ferris committed
308
309
310
311
312
313
314
315
      "#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
316
317
318
319
320
      "uniform vec2 v2Offset;\n"
      "uniform mat4 matProj;\n"
      "void main()\n"
      "{\n"
      "  vec4 pos = vec4( in_pos + vec3(v2Offset,0), 1.0 );\n"
321
      "  gl_Position = pos * matProj;\n"
Gargaj's avatar
Gargaj committed
322
323
324
325
      "  out_color = in_color;\n"
      "  out_texcoord = in_texcoord;\n"
      "  out_factor = in_factor;\n"
      "}\n";
ferris's avatar
ferris committed
326
    char * defaultGUIPixelShader =
ferris's avatar
ferris committed
327
      "#version 410 core\n"
Gargaj's avatar
Gargaj committed
328
      "uniform sampler2D tex;\n"
ferris's avatar
ferris committed
329
330
331
332
      "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
333
334
335
336
      "void main()\n"
      "{\n"
      "  vec4 v4Texture = out_color * texture( tex, out_texcoord );\n"
      "  vec4 v4Color = out_color;\n"
ferris's avatar
ferris committed
337
      "  frag_color = mix( v4Texture, v4Color, out_factor );\n"
Gargaj's avatar
Gargaj committed
338
339
340
341
342
343
344
345
346
347
348
349
350
      "}\n";

    glhGUIProgram = glCreateProgram();

    GLuint vshd = glCreateShader(GL_VERTEX_SHADER);
    nShaderSize = strlen(defaultGUIVertexShader);

    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
351
      printf("[Renderer] Default GUI vertex shader compilation failed\n");
Gargaj's avatar
Gargaj committed
352
353
354
355
356
357
358
359
360
361
362
363
      return false;
    }

    GLuint fshd = glCreateShader(GL_FRAGMENT_SHADER);
    nShaderSize = strlen(defaultGUIPixelShader);

    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
364
      printf("[Renderer] Default GUI pixel shader compilation failed\n");
Gargaj's avatar
Gargaj committed
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
      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);

382
383
384
385
386
387
388
389
390
    //create PBOs to hold the data. this allocates memory for them too
    glGenBuffers(2, pbo);
    glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo[0]);
    glBufferData(GL_PIXEL_PACK_BUFFER, settings->nWidth * settings->nHeight * sizeof(unsigned int), NULL, GL_STREAM_READ);
    glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo[1]);
    glBufferData(GL_PIXEL_PACK_BUFFER, settings->nWidth * settings->nHeight * sizeof(unsigned int), NULL, GL_STREAM_READ);
    //unbind buffers for now
    glBindBuffer(GL_PIXEL_PACK_BUFFER, NULL);

Gargaj's avatar
add SDL    
Gargaj committed
391
392
393
394
    run = true;

    return true;
  }
Gargaj's avatar
Gargaj committed
395

Gargaj's avatar
Gargaj committed
396
397
  KeyEvent keyEventBuffer[512];
  int keyEventBufferCount = 0;
Gargaj's avatar
Gargaj committed
398
399
  MouseEvent mouseEventBuffer[512];
  int mouseEventBufferCount = 0;
400
  void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
Gargaj's avatar
add SDL    
Gargaj committed
401
  {
402
403
    if (action == GLFW_PRESS || action == GLFW_REPEAT) {
      if ((key==GLFW_KEY_F4) && (mods&GLFW_MOD_ALT)) {
Gargaj's avatar
add SDL    
Gargaj committed
404
405
        run = false;
      }
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
      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
463
            sciKey = 0;
464
          }
465
      }
466
      if ((bNormalKey && mods) || !bNormalKey)
467
      {
468
469
470
471
472
473
        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
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
512
513
514
515
  }
  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
516
517
518
519
520
521
522
  void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
  {
    mouseEventBuffer[mouseEventBufferCount].eventType = MOUSEEVENTTYPE_SCROLL;
    mouseEventBuffer[mouseEventBufferCount].x = xoffset;
    mouseEventBuffer[mouseEventBufferCount].y = yoffset;
    mouseEventBufferCount++;
  }
523
524
525

  void StartFrame()
  {
Gargaj's avatar
add SDL    
Gargaj committed
526
527
528
529
530
    glClearColor(0.08f, 0.18f, 0.18f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
  }
  void EndFrame()
  {
531
532
533
534
    keyEventBufferCount = 0;
    mouseEventBufferCount = 0;
    glfwSwapBuffers(mWindow);
    glfwPollEvents();
Gargaj's avatar
add SDL    
Gargaj committed
535
536
537
  }
  bool WantsToQuit()
  {
538
    return glfwWindowShouldClose(mWindow) || !run;
Gargaj's avatar
add SDL    
Gargaj committed
539
540
541
  }
  void Close()
  {
542
543
    glfwDestroyWindow(mWindow);
    glfwTerminate();
Gargaj's avatar
add SDL    
Gargaj committed
544
  }
Gargaj's avatar
Gargaj committed
545
546
547

  void RenderFullscreenQuad()
  {
Gargaj's avatar
Gargaj committed
548
549
    glBindVertexArray(glhFullscreenQuadVA);

Gargaj's avatar
Gargaj committed
550
    glUseProgram(theShader);
Gargaj's avatar
Gargaj committed
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567

    glBindBuffer( GL_ARRAY_BUFFER, glhFullscreenQuadVB );

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

    GLuint texcoord = glGetAttribLocation( theShader, "in_texcoord" );
    glVertexAttribPointer( texcoord, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 5, (GLvoid*)(3 * sizeof(GLfloat)) );

    glEnableVertexAttribArray( position );
    glEnableVertexAttribArray( texcoord );
    glBindBuffer( GL_ARRAY_BUFFER, glhFullscreenQuadVB );
    glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
    glDisableVertexAttribArray( texcoord );
    glDisableVertexAttribArray( position );

    glUseProgram(NULL);
Gargaj's avatar
Gargaj committed
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
  }

  bool ReloadShader( char * szShaderCode, int nShaderCodeSize, char * szErrorBuffer, int nErrorBufferSize )
  {
    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
588
    glAttachShader(prg, glhVertexShader);
Gargaj's avatar
Gargaj committed
589
590
591
592
593
594
595
596
597
598
599
    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
600
601
    if (theShader)
      glDeleteProgram(theShader);
Gargaj's avatar
Gargaj committed
602
603
604
605
606
607
608
609
610
611
612

    theShader = prg;

    return true;
  }

  void SetShaderConstant( char * szConstName, float x )
  {
    GLint location = glGetUniformLocation( theShader, szConstName );
    if ( location != -1 )
    {
ferris's avatar
ferris committed
613
      glProgramUniform1f( theShader, location, x );
Gargaj's avatar
Gargaj committed
614
615
616
617
618
619
620
621
    }
  }

  void SetShaderConstant( char * szConstName, float x, float y )
  {
    GLint location = glGetUniformLocation( theShader, szConstName );
    if ( location != -1 )
    {
ferris's avatar
ferris committed
622
      glProgramUniform2f( theShader, location, x, y );
Gargaj's avatar
Gargaj committed
623
624
625
    }
  }

Gargaj's avatar
Gargaj committed
626
627
  struct GLTexture : public Texture
  {
628
    GLuint ID;
Gargaj's avatar
Gargaj committed
629
630
631
632
    int unit;
  };

  int textureUnit = 0;
Gargaj's avatar
Gargaj committed
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
  Texture * CreateRGBA8TextureFromFile( char * szFilename )
  {
    int comp = 0;
    int width = 0;
    int height = 0;
    unsigned char * c = stbi_load( szFilename, (int*)&width, (int*)&height, &comp, STBI_rgb_alpha );
    if (!c) return NULL;

    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 );

    GLenum internalFormat = GL_SRGB8_ALPHA8;
    GLenum srcFormat = GL_RGBA;

    glTexImage2D( GL_TEXTURE_2D, 0, internalFormat, width, height, 0, srcFormat, GL_UNSIGNED_BYTE, c );

    stbi_image_free(c);

Gargaj's avatar
Gargaj committed
657
    GLTexture * tex = new GLTexture();
Gargaj's avatar
Gargaj committed
658
659
    tex->width = width;
    tex->height = height;
660
    tex->ID = glTexId;
Gargaj's avatar
Gargaj committed
661
    tex->type = TEXTURETYPE_2D;
Gargaj's avatar
Gargaj committed
662
    tex->unit = textureUnit++;
Gargaj's avatar
Gargaj committed
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
    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
678
      data[i] = 0.0f;
Gargaj's avatar
Gargaj committed
679
680
681
682
683
684
685

    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
686
    GLTexture * tex = new GLTexture();
Gargaj's avatar
Gargaj committed
687
688
    tex->width = w;
    tex->height = 1;
689
    tex->ID = glTexId;
Gargaj's avatar
Gargaj committed
690
    tex->type = TEXTURETYPE_1D;
Gargaj's avatar
Gargaj committed
691
    tex->unit = textureUnit++;
Gargaj's avatar
Gargaj committed
692
693
694
695
696
    return tex;
  }

  void SetShaderTexture( char * szTextureName, Texture * tex )
  {
697
698
699
    if (!tex)
      return;

Gargaj's avatar
Gargaj committed
700
701
702
    GLint location = glGetUniformLocation( theShader, szTextureName );
    if ( location != -1 )
    {
ferris's avatar
ferris committed
703
      glProgramUniform1i( theShader, location, ((GLTexture*)tex)->unit );
Gargaj's avatar
Gargaj committed
704
      glActiveTexture( GL_TEXTURE0 + ((GLTexture*)tex)->unit );
Gargaj's avatar
Gargaj committed
705
706
      switch( tex->type)
      {
707
708
        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
709
710
711
712
713
714
      }
    }
  }

  bool UpdateR32Texture( Texture * tex, float * data )
  {
Gargaj's avatar
Gargaj committed
715
    glActiveTexture( GL_TEXTURE0 + ((GLTexture*)tex)->unit );
716
    glBindTexture( GL_TEXTURE_1D, ((GLTexture*)tex)->ID );
Gargaj's avatar
Gargaj committed
717
718
719
720
721
    glTexSubImage1D( GL_TEXTURE_1D, 0, 0, tex->width, GL_RED, GL_FLOAT, data );

    return true;
  }

Gargaj's avatar
Gargaj committed
722
723
724
725
726
  Texture * CreateA8TextureFromData( int w, int h, unsigned char * data )
  {
    GLuint glTexId = 0;
    glGenTextures(1, &glTexId);
    glBindTexture(GL_TEXTURE_2D, glTexId);
727
728
729
730
    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
731

Gargaj's avatar
Gargaj committed
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
    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
748
749
750
751
752
753
754
  //////////////////////////////////////////////////////////////////////////
  // text rendering

  int nDrawCallCount = 0;
  Texture * lastTexture = NULL;
  void StartTextRendering()
  {
Gargaj's avatar
Gargaj committed
755
756
757
758
759
    glUseProgram(glhGUIProgram);
    glBindVertexArray(glhGUIVA);

    glEnable( GL_BLEND );
    glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
Gargaj's avatar
Gargaj committed
760
761
762
763
764
765
766
767
768
  }

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

Gargaj's avatar
Gargaj committed
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
    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
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812

    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
813
    *(f++) = lastTexture ? 0.0f : 1.0f;
Gargaj's avatar
Gargaj committed
814
815
    bufferPointer++;
  }
Gargaj's avatar
Gargaj committed
816
817
  void BindTexture( Texture * tex )
  {
Gargaj's avatar
Gargaj committed
818
819
820
821
822
823
    if (lastTexture != tex)
    {
      lastTexture = tex;
      if (tex)
      {
        __FlushRenderCache();
Gargaj's avatar
Gargaj committed
824
825
826
827

        GLint location = glGetUniformLocation( glhGUIProgram, "tex" );
        if ( location != -1 )
        {
ferris's avatar
ferris committed
828
          glProgramUniform1i( glhGUIProgram, location, ((GLTexture*)tex)->unit );
Gargaj's avatar
Gargaj committed
829
830
831
832
833
834
835
836
          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
837
838
      }
    }
Gargaj's avatar
Gargaj committed
839
840
  }

841
  void RenderQuad( const Vertex & a, const Vertex & b, const Vertex & c, const Vertex & d )
Gargaj's avatar
Gargaj committed
842
  {
Gargaj's avatar
Gargaj committed
843
844
845
846
847
848
849
850
851
852
853
    if (!lastModeIsQuad)
    {
      __FlushRenderCache();
      lastModeIsQuad = true;
    }
    __WriteVertexToBuffer(a);
    __WriteVertexToBuffer(b);
    __WriteVertexToBuffer(d);
    __WriteVertexToBuffer(b);
    __WriteVertexToBuffer(c);
    __WriteVertexToBuffer(d);
Gargaj's avatar
Gargaj committed
854
855
  }

856
  void RenderLine( const Vertex & a, const Vertex & b )
Gargaj's avatar
Gargaj committed
857
  {
Gargaj's avatar
Gargaj committed
858
859
860
861
862
863
864
    if (lastModeIsQuad)
    {
      __FlushRenderCache();
      lastModeIsQuad = false;
    }
    __WriteVertexToBuffer(a);
    __WriteVertexToBuffer(b);
Gargaj's avatar
Gargaj committed
865
866
  }

Gargaj's avatar
Gargaj committed
867
868
869
  void SetTextRenderingViewport( Scintilla::PRectangle rect )
  {
    __FlushRenderCache();
Gargaj's avatar
Gargaj committed
870
871
872
873
874
875
876

    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
877
       glProgramUniformMatrix4fv( glhGUIProgram, location, 1, GL_FALSE, pGUIMatrix );
Gargaj's avatar
Gargaj committed
878
879
880
881
882
    }

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

Gargaj's avatar
Gargaj committed
886
887
    glEnable(GL_SCISSOR_TEST);
    glScissor(rect.left, nHeight - rect.bottom, rect.right - rect.left, rect.bottom - rect.top);
Gargaj's avatar
Gargaj committed
888
889
890
891
  }
  void EndTextRendering()
  {
    __FlushRenderCache();
Gargaj's avatar
Gargaj committed
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907

    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 );

    glUseProgram(NULL);

Gargaj's avatar
Gargaj committed
908
909
    glDisable(GL_BLEND);
    glDisable(GL_SCISSOR_TEST);
Gargaj's avatar
Gargaj committed
910
911
  }

912
913
914
915
916
917
918
919
  //////////////////////////////////////////////////////////////////////////

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

    glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo[writeIndex]);
920
    glReadPixels(0, 0, nWidth, nHeight, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
921
922
    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
923
    if (downsampleData)
924
    {
925
926
927
928
929
930
931
932
      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;
      }
933
934
935
936
937
938
      glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
    }
    glBindBuffer(GL_PIXEL_PACK_BUFFER, NULL);

    return true;
  }
Gargaj's avatar
Gargaj committed
939

940
}