| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460 |
- #ifndef TIGR_HEADLESS
- #include "tigr_internal.h"
- #include <assert.h>
- #ifdef TIGR_GAPI_GL
- #if __linux__
- #if __ANDROID__
- #include <GLES3/gl3.h>
- #else
- #define GLX_GLXEXT_PROTOTYPES
- #include <GL/glext.h>
- #endif
- #endif
- extern const char tigr_upscale_gl_vs[], tigr_upscale_gl_fs[], tigr_default_fx_gl_fs[];
- extern const int tigr_upscale_gl_vs_size, tigr_upscale_gl_fs_size, tigr_default_fx_gl_fs_size;
- #ifdef _WIN32
- #ifdef TIGR_GAPI_GL_WIN_USE_GLEXT
- #include <glext.h>
- #include <wglext.h>
- #else // short version of glext.h and wglext.h so we don't need to depend on them
- #ifndef APIENTRY
- #define APIENTRY
- #endif
- #ifndef APIENTRYP
- #define APIENTRYP APIENTRY*
- #endif
- typedef ptrdiff_t GLsizeiptr;
- #define GL_COMPILE_STATUS 0x8B81
- #define GL_LINK_STATUS 0x8B82
- #define GL_ARRAY_BUFFER 0x8892
- #define GL_STATIC_DRAW 0x88E4
- #define GL_VERTEX_SHADER 0x8B31
- #define GL_FRAGMENT_SHADER 0x8B30
- #define GL_BGRA 0x80E1
- #define GL_TEXTURE0 0x84C0
- typedef void(APIENTRYP PFNGLGENVERTEXARRAYSPROC)(GLsizei n, GLuint* arrays);
- typedef void(APIENTRYP PFNGLGENBUFFERSARBPROC)(GLsizei n, GLuint* buffers);
- typedef void(APIENTRYP PFNGLBINDBUFFERPROC)(GLenum target, GLuint buffer);
- typedef void(APIENTRYP PFNGLBUFFERDATAPROC)(GLenum target, GLsizeiptr size, const void* data, GLenum usage);
- typedef void(APIENTRYP PFNGLBINDVERTEXARRAYPROC)(GLuint array);
- typedef void(APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC)(GLuint index);
- typedef void(APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC)(GLuint index,
- GLint size,
- GLenum type,
- GLboolean normalized,
- GLsizei stride,
- const void* pointer);
- typedef GLuint(APIENTRYP PFNGLCREATESHADERPROC)(GLenum type);
- typedef char GLchar;
- typedef void(APIENTRYP PFNGLSHADERSOURCEPROC)(GLuint shader,
- GLsizei count,
- const GLchar* const* string,
- const GLint* length);
- typedef void(APIENTRYP PFNGLCOMPILESHADERPROC)(GLuint shader);
- typedef GLuint(APIENTRYP PFNGLCREATEPROGRAMPROC)(void);
- typedef void(APIENTRYP PFNGLATTACHSHADERPROC)(GLuint program, GLuint shader);
- typedef void(APIENTRYP PFNGLLINKPROGRAMPROC)(GLuint program);
- typedef void(APIENTRYP PFNGLDELETESHADERPROC)(GLuint shader);
- typedef void(APIENTRYP PFNGLDELETEPROGRAMPROC)(GLuint program);
- typedef void(APIENTRYP PFNGLGETSHADERIVPROC)(GLuint shader, GLenum pname, GLint* params);
- typedef void(APIENTRYP PFNGLGETSHADERINFOLOGPROC)(GLuint shader, GLsizei bufSize, GLsizei* length, GLchar* infoLog);
- typedef void(APIENTRYP PFNGLGETPROGRAMIVPROC)(GLuint program, GLenum pname, GLint* params);
- typedef void(APIENTRYP PFNGLGETPROGRAMINFOLOGPROC)(GLuint program, GLsizei bufSize, GLsizei* length, GLchar* infoLog);
- typedef void(APIENTRYP PFNGLUSEPROGRAMPROC)(GLuint program);
- typedef GLint(APIENTRYP PFNGLGETUNIFORMLOCATIONPROC)(GLuint program, const GLchar* name);
- typedef void(APIENTRYP PFNGLUNIFORM4FPROC)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
- typedef void(APIENTRYP PFNGLUNIFORMMATRIX4FVPROC)(GLint location,
- GLsizei count,
- GLboolean transpose,
- const GLfloat* value);
- typedef void(APIENTRYP PFNGLACTIVETEXTUREPROC)(GLenum texture);
- #define WGL_DRAW_TO_WINDOW_ARB 0x2001
- #define WGL_SUPPORT_OPENGL_ARB 0x2010
- #define WGL_DOUBLE_BUFFER_ARB 0x2011
- #define WGL_PIXEL_TYPE_ARB 0x2013
- #define WGL_COLOR_BITS_ARB 0x2014
- #define WGL_DEPTH_BITS_ARB 0x2022
- #define WGL_STENCIL_BITS_ARB 0x2023
- #define WGL_TYPE_RGBA_ARB 0x202B
- #define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
- #define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
- typedef BOOL(WINAPI* PFNWGLCHOOSEPIXELFORMATARBPROC)(HDC hdc,
- const int* piAttribIList,
- const FLOAT* pfAttribFList,
- UINT nMaxFormats,
- int* piFormats,
- UINT* nNumFormats);
- typedef HGLRC(WINAPI* PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC hDC, HGLRC hShareContext, const int* attribList);
- #endif
- PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormat;
- PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribs;
- PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
- PFNGLGENBUFFERSARBPROC glGenBuffers;
- PFNGLBINDBUFFERPROC glBindBuffer;
- PFNGLBUFFERDATAPROC glBufferData;
- PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
- PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray;
- PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer;
- PFNGLCREATESHADERPROC glCreateShader;
- PFNGLSHADERSOURCEPROC glShaderSource;
- PFNGLCOMPILESHADERPROC glCompileShader;
- PFNGLCREATEPROGRAMPROC glCreateProgram;
- PFNGLATTACHSHADERPROC glAttachShader;
- PFNGLLINKPROGRAMPROC glLinkProgram;
- PFNGLDELETESHADERPROC glDeleteShader;
- PFNGLDELETEPROGRAMPROC glDeleteProgram;
- PFNGLGETSHADERIVPROC glGetShaderiv;
- PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog;
- PFNGLGETPROGRAMIVPROC glGetProgramiv;
- PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog;
- PFNGLUSEPROGRAMPROC glUseProgram;
- PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation;
- PFNGLUNIFORM4FPROC glUniform4f;
- PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv;
- PFNGLACTIVETEXTUREPROC glActiveTexture;
- int tigrGL11Init(Tigr* bmp) {
- int pixel_format;
- TigrInternal* win = tigrInternal(bmp);
- GLStuff* gl = &win->gl;
- PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR),
- 1,
- PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_SWAP_EXCHANGE,
- PFD_TYPE_RGBA,
- 32, // color bits
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 24, // depth
- 8, // stencil
- 0,
- PFD_MAIN_PLANE, // is it ignored ?
- 0,
- 0,
- 0,
- 0 };
- if (!(gl->dc = GetDC((HWND)bmp->handle))) {
- tigrError(bmp, "Cannot create OpenGL device context.\n");
- return -1;
- }
- if (!(pixel_format = ChoosePixelFormat(gl->dc, &pfd))) {
- tigrError(bmp, "Cannot choose OpenGL pixel format.\n");
- return -1;
- }
- if (!SetPixelFormat(gl->dc, pixel_format, &pfd)) {
- tigrError(bmp, "Cannot set OpenGL pixel format.\n");
- return -1;
- }
- if (!(gl->hglrc = wglCreateContext(gl->dc))) {
- tigrError(bmp, "Cannot create OpenGL context.\n");
- return -1;
- }
- if (!wglMakeCurrent(gl->dc, gl->hglrc)) {
- tigrError(bmp, "Cannot activate OpenGL context.\n");
- return -1;
- }
- gl->gl_legacy = 1;
- return 0;
- }
- int tigrGL33Init(Tigr* bmp) {
- int pixel_format;
- UINT num_formats;
- TigrInternal* win = tigrInternal(bmp);
- GLStuff* gl = &win->gl;
- wglChoosePixelFormat = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
- wglCreateContextAttribs = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB");
- glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC)wglGetProcAddress("glGenVertexArrays");
- glGenBuffers = (PFNGLGENBUFFERSARBPROC)wglGetProcAddress("glGenBuffers");
- glBindBuffer = (PFNGLBINDBUFFERPROC)wglGetProcAddress("glBindBuffer");
- glBufferData = (PFNGLBUFFERDATAPROC)wglGetProcAddress("glBufferData");
- glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC)wglGetProcAddress("glBindVertexArray");
- glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)wglGetProcAddress("glEnableVertexAttribArray");
- glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)wglGetProcAddress("glVertexAttribPointer");
- glCreateShader = (PFNGLCREATESHADERPROC)wglGetProcAddress("glCreateShader");
- glShaderSource = (PFNGLSHADERSOURCEPROC)wglGetProcAddress("glShaderSource");
- glCompileShader = (PFNGLCOMPILESHADERPROC)wglGetProcAddress("glCompileShader");
- glCreateProgram = (PFNGLCREATEPROGRAMPROC)wglGetProcAddress("glCreateProgram");
- glAttachShader = (PFNGLATTACHSHADERPROC)wglGetProcAddress("glAttachShader");
- glLinkProgram = (PFNGLLINKPROGRAMPROC)wglGetProcAddress("glLinkProgram");
- glDeleteShader = (PFNGLDELETESHADERPROC)wglGetProcAddress("glDeleteShader");
- glDeleteProgram = (PFNGLDELETEPROGRAMPROC)wglGetProcAddress("glDeleteProgram");
- glGetShaderiv = (PFNGLGETSHADERIVPROC)wglGetProcAddress("glGetShaderiv");
- glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)wglGetProcAddress("glGetShaderInfoLog");
- glGetProgramiv = (PFNGLGETPROGRAMIVPROC)wglGetProcAddress("glGetProgramiv");
- glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)wglGetProcAddress("glGetProgramInfoLog");
- glUseProgram = (PFNGLUSEPROGRAMPROC)wglGetProcAddress("glUseProgram");
- glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC)wglGetProcAddress("glGetUniformLocation");
- glUniform4f = (PFNGLUNIFORM4FPROC)wglGetProcAddress("glUniform4f");
- glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC)wglGetProcAddress("glUniformMatrix4fv");
- glActiveTexture = (PFNGLACTIVETEXTUREPROC)wglGetProcAddress("glActiveTexture");
- if (!wglChoosePixelFormat || !wglCreateContextAttribs) {
- tigrError(bmp, "Cannot create OpenGL context.\n");
- return -1;
- }
- const int attribList[] = { WGL_DRAW_TO_WINDOW_ARB,
- GL_TRUE,
- WGL_SUPPORT_OPENGL_ARB,
- GL_TRUE,
- WGL_DOUBLE_BUFFER_ARB,
- GL_TRUE,
- WGL_PIXEL_TYPE_ARB,
- WGL_TYPE_RGBA_ARB,
- WGL_COLOR_BITS_ARB,
- 32,
- WGL_DEPTH_BITS_ARB,
- 24,
- WGL_STENCIL_BITS_ARB,
- 8,
- 0 };
- int attribs[] = { WGL_CONTEXT_MAJOR_VERSION_ARB, 3, WGL_CONTEXT_MINOR_VERSION_ARB, 3, 0 };
- if (!wglChoosePixelFormat(gl->dc, attribList, NULL, 1, &pixel_format, &num_formats)) {
- tigrError(bmp, "Cannot choose OpenGL pixel format.\n");
- return -1;
- }
- if (!(gl->hglrc = wglCreateContextAttribs(gl->dc, gl->hglrc, attribs))) {
- tigrError(bmp, "Cannot create OpenGL context attribs.\n");
- return -1;
- }
- if (!wglMakeCurrent(gl->dc, gl->hglrc)) {
- tigrError(bmp, "Cannot activate OpenGL context.\n");
- return -1;
- }
- gl->gl_legacy = 0;
- return 0;
- }
- #endif
- void tigrCheckGLError(const char* state) {
- GLenum err = glGetError();
- if (err != GL_NO_ERROR) {
- tigrError(NULL, "got GL error %x when doing %s\n", err, state);
- }
- }
- void tigrCheckShaderErrors(GLuint object) {
- GLint success;
- GLchar info[2048];
- glGetShaderiv(object, GL_COMPILE_STATUS, &success);
- if (!success) {
- glGetShaderInfoLog(object, sizeof(info), NULL, info);
- tigrError(NULL, "shader compile error : %s\n", info);
- }
- }
- void tigrCheckProgramErrors(GLuint object) {
- GLint success;
- GLchar info[2048];
- glGetProgramiv(object, GL_LINK_STATUS, &success);
- if (!success) {
- glGetProgramInfoLog(object, sizeof(info), NULL, info);
- tigrError(NULL, "shader link error : %s\n", info);
- }
- }
- void tigrCreateShaderProgram(GLStuff* gl, const char* fxSource, int fxSize) {
- if (gl->program != 0) {
- glDeleteProgram(gl->program);
- gl->program = 0;
- }
- GLuint vs = glCreateShader(GL_VERTEX_SHADER);
- const char* vs_source = (const char*)&tigr_upscale_gl_vs;
- glShaderSource(vs, 1, &vs_source, &tigr_upscale_gl_vs_size);
- glCompileShader(vs);
- tigrCheckShaderErrors(vs);
- GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
- const char* fs_sources[] = {
- (const char*)tigr_upscale_gl_fs,
- fxSource,
- };
- const int fs_lengths[] = {
- tigr_upscale_gl_fs_size,
- fxSize,
- };
- glShaderSource(fs, 2, fs_sources, fs_lengths);
- glCompileShader(fs);
- tigrCheckShaderErrors(fs);
- gl->program = glCreateProgram();
- glAttachShader(gl->program, vs);
- glAttachShader(gl->program, fs);
- glLinkProgram(gl->program);
- tigrCheckProgramErrors(gl->program);
- glDeleteShader(vs);
- glDeleteShader(fs);
- gl->uniform_projection = glGetUniformLocation(gl->program, "projection");
- gl->uniform_model = glGetUniformLocation(gl->program, "model");
- gl->uniform_parameters = glGetUniformLocation(gl->program, "parameters");
- }
- void tigrGAPICreate(Tigr* bmp) {
- TigrInternal* win = tigrInternal(bmp);
- GLStuff* gl = &win->gl;
- GLuint VBO;
- GLfloat vertices[] = { // pos uv
- 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f
- };
- #ifdef _WIN32
- if (tigrGL11Init(bmp))
- return;
- tigrGL33Init(bmp);
- #endif
- if (!gl->gl_legacy) {
- // create vao
- glGenVertexArrays(1, &gl->vao);
- glGenBuffers(1, &VBO);
- glBindBuffer(GL_ARRAY_BUFFER, VBO);
- glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
- glBindVertexArray(gl->vao);
- glEnableVertexAttribArray(0);
- glEnableVertexAttribArray(1);
- glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), NULL);
- glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), NULL);
- // create program
- tigrCreateShaderProgram(gl, tigr_default_fx_gl_fs, tigr_default_fx_gl_fs_size);
- }
- // create textures
- if (gl->gl_legacy) {
- glEnable(GL_TEXTURE_2D);
- }
- glGenTextures(2, gl->tex);
- for (int i = 0; i < 2; ++i) {
- glBindTexture(GL_TEXTURE_2D, gl->tex[i]);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl->gl_legacy ? GL_NEAREST : GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl->gl_legacy ? GL_NEAREST : GL_LINEAR);
- glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- }
- tigrCheckGLError("initialization");
- }
- void tigrGAPIDestroy(Tigr* bmp) {
- TigrInternal* win = tigrInternal(bmp);
- GLStuff* gl = &win->gl;
- if (tigrGAPIBegin(bmp) < 0) {
- tigrError(bmp, "Cannot activate OpenGL context.\n");
- return;
- }
- if (!gl->gl_legacy) {
- glDeleteTextures(2, gl->tex);
- glDeleteProgram(gl->program);
- }
- tigrCheckGLError("destroy");
- if (tigrGAPIEnd(bmp) < 0) {
- tigrError(bmp, "Cannot deactivate OpenGL context.\n");
- return;
- }
- }
- void tigrGAPIDraw(int legacy, GLuint uniform_model, GLuint tex, Tigr* bmp, int x1, int y1, int x2, int y2) {
- glBindTexture(GL_TEXTURE_2D, tex);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, bmp->w, bmp->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, bmp->pix);
- if (!legacy) {
- float sx = (float)(x2 - x1);
- float sy = (float)(y2 - y1);
- float tx = (float)x1;
- float ty = (float)y1;
- float model[16] = { sx, 0.0f, 0.0f, 0.0f, 0.0f, sy, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, tx, ty, 0.0f, 1.0f };
- glUniformMatrix4fv(uniform_model, 1, GL_FALSE, model);
- glDrawArrays(GL_TRIANGLES, 0, 6);
- } else {
- #if !(__APPLE__ || __ANDROID__)
- glBegin(GL_QUADS);
- glTexCoord2f(1.0f, 0.0f);
- glVertex2i(x2, y1);
- glTexCoord2f(0.0f, 0.0f);
- glVertex2i(x1, y1);
- glTexCoord2f(0.0f, 1.0f);
- glVertex2i(x1, y2);
- glTexCoord2f(1.0f, 1.0f);
- glVertex2i(x2, y2);
- glEnd();
- #else
- assert(0);
- #endif
- }
- }
- void tigrGAPIPresent(Tigr* bmp, int w, int h) {
- TigrInternal* win = tigrInternal(bmp);
- GLStuff* gl = &win->gl;
- glViewport(0, 0, w, h);
- if (!gl->gl_user_opengl_rendering) {
- glClearColor(0, 0, 0, 1);
- glClear(GL_COLOR_BUFFER_BIT);
- }
- if (!gl->gl_legacy) {
- float projection[16] = { 2.0f / w, 0.0f, 0.0f, 0.0f, 0.0f, -2.0f / h, 0.0f, 0.0f,
- 0.0f, 0.0f, 1.0f, 0.0f, -1.0f, 1.0f, 0.0f, 1.0f };
- glActiveTexture(GL_TEXTURE0);
- glBindVertexArray(gl->vao);
- glUseProgram(gl->program);
- glUniformMatrix4fv(gl->uniform_projection, 1, GL_FALSE, projection);
- glUniform4f(gl->uniform_parameters, win->p1, win->p2, win->p3, win->p4);
- } else {
- #if !(__APPLE__ || __ANDROID__)
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrtho(0, w, h, 0, -1.0f, 1.0f);
- glEnable(GL_TEXTURE_2D);
- #else
- assert(0);
- #endif
- }
- if (gl->gl_user_opengl_rendering) {
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- } else {
- glDisable(GL_BLEND);
- }
- tigrGAPIDraw(gl->gl_legacy, gl->uniform_model, gl->tex[0], bmp, win->pos[0], win->pos[1], win->pos[2], win->pos[3]);
- if (win->widgetsScale > 0) {
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- tigrGAPIDraw(gl->gl_legacy, gl->uniform_model, gl->tex[1], win->widgets,
- (int)(w - win->widgets->w * win->widgetsScale), 0, w, (int)(win->widgets->h * win->widgetsScale));
- }
- tigrCheckGLError("present");
- gl->gl_user_opengl_rendering = 0;
- }
- #endif
- #endif // #ifndef TIGR_HEADLESS
|