Refactor GL extension code;

This commit is contained in:
bjorn 2017-06-10 16:25:46 -07:00
parent 265a81c411
commit 613b1ea67f
6 changed files with 59 additions and 54 deletions

View File

@ -52,7 +52,7 @@ Font* lovrFontCreate(FontData* fontData) {
font->texture = lovrTextureCreate(textureData);
lovrTextureSetWrap(font->texture, WRAP_CLAMP, WRAP_CLAMP);
if (GLAD_GL_VERSION_3_0) {
if (lovrGraphicsIsSupported(FEATURE_SWIZZLE)) {
int swizzle[4] = { GL_RED, GL_RED, GL_RED, GL_GREEN };
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle);
}
@ -292,11 +292,7 @@ void lovrFontAddGlyph(Font* font, Glyph* glyph) {
// Paste glyph into texture
lovrGraphicsBindTexture(font->texture);
if (GLAD_GL_VERSION_3_0 || GLAD_GL_ARB_texture_rg || GLAD_GL_EXT_texture_rg) {
glTexSubImage2D(GL_TEXTURE_2D, 0, atlas->x, atlas->y, glyph->w, glyph->h, GL_RG, GL_UNSIGNED_BYTE, glyph->data);
} else {
glTexSubImage2D(GL_TEXTURE_2D, 0, atlas->x, atlas->y, glyph->w, glyph->h, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, glyph->data);
}
glTexSubImage2D(GL_TEXTURE_2D, 0, atlas->x, atlas->y, glyph->w, glyph->h, lovrTextureGetGLFormat(FORMAT_RG), GL_UNSIGNED_BYTE, glyph->data);
// Advance atlas cursor
atlas->x += glyph->w + atlas->padding;

View File

@ -26,8 +26,10 @@ static void onCloseWindow(GLFWwindow* window) {
void lovrGraphicsInit() {
#ifdef EMSCRIPTEN
#define loadGLLoader gladLoadGLES2Loader
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
#else
#define loadGLLoader gladLoadGLLoader
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
@ -36,29 +38,22 @@ void lovrGraphicsInit() {
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
#endif
// Create window
const char* title = lovrFilesystemGetIdentity();
title = title ? title : "LÖVR";
state.window = glfwCreateWindow(800, 600, title, NULL, NULL);
state.window = glfwCreateWindow(800, 600, title ? title : "LÖVR", NULL, NULL);
if (!state.window) {
glfwTerminate();
error("Could not create window");
}
// Initialize all the things
glfwMakeContextCurrent(state.window);
glfwSetWindowCloseCallback(state.window, onCloseWindow);
#ifdef EMSCRIPTEN
gladLoadGLES2Loader((GLADloadproc) glfwGetProcAddress);
#else
gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
#endif
glfwSetTime(0);
loadGLLoader((GLADloadproc) glfwGetProcAddress);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
if (GLAD_GL_VERSION_3_0) {
glfwSwapInterval(0);
glEnable(GL_LINE_SMOOTH);
@ -71,7 +66,7 @@ void lovrGraphicsInit() {
state.activeTexture = NULL;
glGenBuffers(1, &state.shapeBuffer);
glGenBuffers(1, &state.shapeIndexBuffer);
if (GLAD_GL_VERSION_3_0) {
if (lovrGraphicsIsSupported(FEATURE_VAO)) {
glGenVertexArrays(1, &state.shapeArray);
}
vec_init(&state.shapeData);
@ -89,6 +84,7 @@ void lovrGraphicsInit() {
state.defaultTexture = lovrTextureCreate(lovrTextureDataGetBlank(1, 1, 0xff, FORMAT_RGBA));
// System Limits
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &state.maxTextureSize);
if (GLAD_GL_VERSION_2_0) {
float pointSizes[2];
glGetFloatv(GL_POINT_SIZE_RANGE, pointSizes);
@ -99,8 +95,6 @@ void lovrGraphicsInit() {
state.maxTextureMSAA = 1;
}
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &state.maxTextureSize);
// State
state.depthTest = -1;
lovrGraphicsReset();
@ -123,7 +117,7 @@ void lovrGraphicsDestroy() {
lovrRelease(&state.defaultTexture->ref);
glDeleteBuffers(1, &state.shapeBuffer);
glDeleteBuffers(1, &state.shapeIndexBuffer);
if (GLAD_GL_VERSION_3_0) {
if (lovrGraphicsIsSupported(FEATURE_VAO)) {
glDeleteVertexArrays(1, &state.shapeArray);
}
vec_deinit(&state.shapeData);
@ -227,7 +221,7 @@ void lovrGraphicsSetBlendMode(BlendMode mode, BlendAlphaMode alphaMode) {
break;
case BLEND_LIGHTEN:
if (GLAD_GL_VERSION_2_0 || GLAD_GL_EXT_blend_minmax) {
if (lovrGraphicsIsSupported(FEATURE_LIGHTEN)) {
glBlendEquation(GL_MAX);
glBlendFuncSeparate(srcRGB, GL_ZERO, GL_ONE, GL_ZERO);
} else {
@ -236,7 +230,7 @@ void lovrGraphicsSetBlendMode(BlendMode mode, BlendAlphaMode alphaMode) {
break;
case BLEND_DARKEN:
if (GLAD_GL_VERSION_2_0 || GLAD_GL_EXT_blend_minmax) {
if (lovrGraphicsIsSupported(FEATURE_LIGHTEN)) {
glBlendEquation(GL_MIN);
glBlendFuncSeparate(srcRGB, GL_ZERO, GL_ONE, GL_ZERO);
} else {
@ -397,7 +391,7 @@ float lovrGraphicsGetPointSize() {
}
void lovrGraphicsSetPointSize(float size) {
if (GLAD_GL_VERSION_2_0) {
if (lovrGraphicsIsSupported(FEATURE_POINT_SIZE)) {
state.pointSize = size;
glPointSize(size);
}
@ -446,7 +440,7 @@ int lovrGraphicsIsWireframe() {
}
void lovrGraphicsSetWireframe(int wireframe) {
if (GLAD_GL_VERSION_3_0 && state.isWireframe != wireframe) {
if (lovrGraphicsIsSupported(FEATURE_WIREFRAME) && state.isWireframe != wireframe) {
state.isWireframe = wireframe;
glPolygonMode(GL_FRONT_AND_BACK, wireframe ? GL_LINE : GL_FILL);
}
@ -473,6 +467,20 @@ float lovrGraphicsGetSystemLimit(GraphicsLimit limit) {
}
}
int lovrGraphicsIsSupported(GraphicsFeature feature) {
switch (feature) {
case FEATURE_LIGHTEN: return GLAD_GL_VERSION_2_0 || GLAD_GL_EXT_blend_minmax;
case FEATURE_MAPPED_BUFFERS: return GLAD_GL_VERSION_3_0 || GLAD_GL_ARB_map_buffer_range;
case FEATURE_POINT_SIZE: return GLAD_GL_VERSION_2_0;
case FEATURE_SHADER_INTS: return GLAD_GL_VERSION_2_0;
case FEATURE_SWIZZLE: return GLAD_GL_VERSION_3_0;
case FEATURE_TEXTURE_RG: return GLAD_GL_VERSION_3_0 || GLAD_GL_ARB_texture_rg || GLAD_GL_EXT_texture_rg;
case FEATURE_TEXTURE_FANCY_WRAPS: return !GLAD_GL_ES_VERSION_2_0;
case FEATURE_VAO: return GLAD_GL_VERSION_3_0;
case FEATURE_WIREFRAME: return GLAD_GL_VERSION_3_0;
}
}
void lovrGraphicsPushCanvas() {
if (++state.canvas >= MAX_CANVASES) {
error("Canvas overflow");
@ -553,7 +561,7 @@ void lovrGraphicsDrawPrimitive(GLenum mode, int hasNormals, int hasTexCoords, in
int strideBytes = stride * sizeof(float);
lovrGraphicsPrepare();
if (GLAD_GL_VERSION_3_0) {
if (lovrGraphicsIsSupported(FEATURE_VAO)) {
glBindVertexArray(state.shapeArray);
}
glBindBuffer(GL_ARRAY_BUFFER, state.shapeBuffer);
@ -584,7 +592,7 @@ void lovrGraphicsDrawPrimitive(GLenum mode, int hasNormals, int hasTexCoords, in
glDrawArrays(mode, 0, state.shapeData.length / stride);
}
if (GLAD_GL_VERSION_3_0) {
if (lovrGraphicsIsSupported(FEATURE_VAO)) {
glBindVertexArray(0);
}
}

View File

@ -55,6 +55,18 @@ typedef enum {
LIMIT_TEXTURE_MSAA
} GraphicsLimit;
typedef enum {
FEATURE_LIGHTEN,
FEATURE_MAPPED_BUFFERS,
FEATURE_POINT_SIZE,
FEATURE_SHADER_INTS,
FEATURE_SWIZZLE,
FEATURE_TEXTURE_RG,
FEATURE_TEXTURE_FANCY_WRAPS,
FEATURE_VAO,
FEATURE_WIREFRAME
} GraphicsFeature;
typedef struct {
int x;
int y;
@ -150,6 +162,7 @@ void lovrGraphicsSetWireframe(int wireframe);
int lovrGraphicsGetWidth();
int lovrGraphicsGetHeight();
float lovrGraphicsGetSystemLimit(GraphicsLimit limit);
int lovrGraphicsIsSupported(GraphicsFeature feature);
void lovrGraphicsPushCanvas();
void lovrGraphicsPopCanvas();
void lovrGraphicsSetViewport(int x, int y, int w, int h);

View File

@ -5,7 +5,7 @@
static void lovrMeshBindAttributes(Mesh* mesh) {
Shader* shader = lovrGraphicsGetShader();
if (!shader || (shader == mesh->lastShader && !mesh->attributesDirty && GLAD_GL_VERSION_3_0)) {
if (!shader || (shader == mesh->lastShader && !mesh->attributesDirty && lovrGraphicsIsSupported(FEATURE_VAO))) {
return;
}
@ -23,7 +23,7 @@ static void lovrMeshBindAttributes(Mesh* mesh) {
glEnableVertexAttribArray(location);
if (attribute.type == MESH_INT) {
if (GLAD_GL_ES_VERSION_2_0) {
if (lovrGraphicsIsSupported(FEATURE_SHADER_INTS)) {
error("Integer attributes are not supported on this platform.");
} else {
glVertexAttribIPointer(location, attribute.count, attribute.type, mesh->stride, (void*) offset);
@ -92,11 +92,11 @@ Mesh* lovrMeshCreate(int count, MeshFormat* format, MeshDrawMode drawMode, MeshU
glGenBuffers(1, &mesh->ibo);
glBindBuffer(GL_ARRAY_BUFFER, mesh->vbo);
glBufferData(GL_ARRAY_BUFFER, mesh->count * mesh->stride, NULL, mesh->usage);
if (GLAD_GL_VERSION_3_0) {
if (lovrGraphicsIsSupported(FEATURE_VAO)) {
glGenVertexArrays(1, &mesh->vao);
}
if (!GLAD_GL_VERSION_3_0 && !GL_ARB_map_buffer_range) {
if (!lovrGraphicsIsSupported(FEATURE_MAPPED_BUFFERS)) {
mesh->data = malloc(mesh->count * mesh->stride);
}
@ -110,7 +110,7 @@ void lovrMeshDestroy(const Ref* ref) {
}
glDeleteBuffers(1, &mesh->vbo);
glDeleteBuffers(1, &mesh->ibo);
if (GLAD_GL_VERSION_3_0) {
if (lovrGraphicsIsSupported(FEATURE_VAO)) {
glDeleteVertexArrays(1, &mesh->vao);
}
vec_deinit(&mesh->map);
@ -131,7 +131,7 @@ void lovrMeshDraw(Mesh* mesh, mat4 transform) {
lovrGraphicsBindTexture(mesh->texture);
lovrGraphicsPrepare();
if (GLAD_GL_VERSION_3_0) {
if (lovrGraphicsIsSupported(FEATURE_VAO)) {
glBindVertexArray(mesh->vao);
}
@ -266,7 +266,7 @@ void lovrMeshSetTexture(Mesh* mesh, Texture* texture) {
}
void* lovrMeshMap(Mesh* mesh, int start, int count) {
if (!GLAD_GL_VERSION_3_0 && !GLAD_GL_ARB_map_buffer_range) {
if (!lovrGraphicsIsSupported(FEATURE_MAPPED_BUFFERS)) {
mesh->isMapped = 1;
mesh->mapStart = start;
mesh->mapCount = count;
@ -287,7 +287,7 @@ void* lovrMeshMap(Mesh* mesh, int start, int count) {
}
void lovrMeshUnmap(Mesh* mesh) {
if (!GLAD_GL_VERSION_3_0 && !GLAD_GL_ARB_map_buffer_range) {
if (!lovrGraphicsIsSupported(FEATURE_MAPPED_BUFFERS)) {
mesh->isMapped = 0;
int start = mesh->mapStart * mesh->stride;
int count = mesh->mapCount * mesh->stride;

View File

@ -5,27 +5,13 @@
#include <stdlib.h>
#include <stdio.h>
static GLenum getGLFormat(TextureFormat format) {
GLenum lovrTextureGetGLFormat(TextureFormat format) {
switch (format) {
case FORMAT_RED:
if (GLAD_GL_VERSION_3_0 || GLAD_GL_ARB_texture_rg || GLAD_GL_EXT_texture_rg) {
return GL_RED;
} else {
return GL_LUMINANCE;
}
case FORMAT_RG:
if (GLAD_GL_VERSION_3_0 || GLAD_GL_ARB_texture_rg || GLAD_GL_EXT_texture_rg) {
return GL_RG;
} else {
return GL_LUMINANCE_ALPHA;
}
case FORMAT_RED: return lovrGraphicsIsSupported(FEATURE_TEXTURE_RG) ? GL_RED : GL_LUMINANCE;
case FORMAT_RG: return lovrGraphicsIsSupported(FEATURE_TEXTURE_RG) ? GL_RG : GL_LUMINANCE_ALPHA;
case FORMAT_RGB: return GL_RGB;
case FORMAT_RGBA: return GL_RGBA;
}
return 0;
}
Texture* lovrTextureCreate(TextureData* textureData) {
@ -158,7 +144,7 @@ void lovrTextureRefresh(Texture* texture) {
TextureData* textureData = texture->textureData;
int w = textureData->width;
int h = textureData->height;
GLenum format = getGLFormat(textureData->format);
GLenum format = lovrTextureGetGLFormat(textureData->format);
lovrGraphicsBindTexture(texture);
glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format, GL_UNSIGNED_BYTE, textureData->data);
}
@ -190,7 +176,7 @@ void lovrTextureGetWrap(Texture* texture, WrapMode* horizontal, WrapMode* vertic
}
void lovrTextureSetWrap(Texture* texture, WrapMode horizontal, WrapMode vertical) {
if (GLAD_GL_ES_VERSION_2_0) {
if (!lovrGraphicsIsSupported(FEATURE_TEXTURE_FANCY_WRAPS)) {
horizontal = vertical = WRAP_CLAMP;
}

View File

@ -37,6 +37,8 @@ typedef struct {
int msaa;
} Texture;
GLenum lovrTextureGetGLFormat(TextureFormat format);
Texture* lovrTextureCreate(TextureData* textureData);
Texture* lovrTextureCreateWithFramebuffer(TextureData* textureData, TextureProjection projection, int msaa);
void lovrTextureDestroy(const Ref* ref);