Use indirection for graphics object access;

This will make it easier to move stuff around.
This commit is contained in:
bjorn 2018-07-09 00:51:09 -07:00
parent 49e0438bd3
commit c86bb419f1
9 changed files with 77 additions and 37 deletions

View File

@ -2,16 +2,16 @@
int l_lovrTextureGetDepth(lua_State* L) {
Texture* texture = luax_checktypeof(L, 1, Texture);
lua_pushnumber(L, texture->depth);
lua_pushnumber(L, lovrTextureGetDepth(texture));
return 1;
}
int l_lovrTextureGetDimensions(lua_State* L) {
Texture* texture = luax_checktypeof(L, 1, Texture);
lua_pushinteger(L, texture->width);
lua_pushinteger(L, texture->height);
if (texture->type != TEXTURE_2D) {
lua_pushinteger(L, texture->depth);
lua_pushinteger(L, lovrTextureGetWidth(texture));
lua_pushinteger(L, lovrTextureGetHeight(texture));
if (lovrTextureGetType(texture) != TEXTURE_2D) {
lua_pushinteger(L, lovrTextureGetDepth(texture));
return 3;
}
return 2;
@ -30,7 +30,7 @@ int l_lovrTextureGetFilter(lua_State* L) {
int l_lovrTextureGetHeight(lua_State* L) {
Texture* texture = luax_checktypeof(L, 1, Texture);
lua_pushnumber(L, texture->height);
lua_pushnumber(L, lovrTextureGetHeight(texture));
return 1;
}
@ -42,7 +42,7 @@ int l_lovrTextureGetType(lua_State* L) {
int l_lovrTextureGetWidth(lua_State* L) {
Texture* texture = luax_checktypeof(L, 1, Texture);
lua_pushnumber(L, texture->width);
lua_pushnumber(L, lovrTextureGetWidth(texture));
return 1;
}
@ -51,7 +51,7 @@ int l_lovrTextureGetWrap(lua_State* L) {
TextureWrap wrap = lovrTextureGetWrap(texture);
lua_pushstring(L, WrapModes[wrap.s]);
lua_pushstring(L, WrapModes[wrap.t]);
if (texture->type == TEXTURE_CUBE) {
if (lovrTextureGetType(texture) == TEXTURE_CUBE) {
lua_pushstring(L, WrapModes[wrap.r]);
return 3;
}

View File

@ -95,6 +95,10 @@ void lovrCanvasDestroy(void* ref) {
lovrTextureDestroy(ref);
}
uint32_t lovrCanvasGetId(Canvas* canvas) {
return canvas->framebuffer;
}
void lovrCanvasResolve(Canvas* canvas) {
if (canvas->flags.msaa > 0) {
int width = canvas->texture.width;

View File

@ -11,19 +11,22 @@ typedef struct {
bool mipmaps;
} CanvasFlags;
typedef struct {
typedef struct Canvas Canvas;
struct Canvas {
Texture texture;
GLuint framebuffer;
GLuint resolveFramebuffer;
GLuint depthStencilBuffer;
GLuint msaaTexture;
CanvasFlags flags;
} Canvas;
};
bool lovrCanvasSupportsFormat(TextureFormat format);
Canvas* lovrCanvasCreate(int width, int height, TextureFormat format, CanvasFlags flags);
void lovrCanvasDestroy(void* ref);
uint32_t lovrCanvasGetId(Canvas* canvas); // FIXME temporary
void lovrCanvasResolve(Canvas* canvas);
TextureFormat lovrCanvasGetFormat(Canvas* canvas);
int lovrCanvasGetMSAA(Canvas* canvas);

View File

@ -110,7 +110,7 @@ void lovrGraphicsReset() {
void lovrGraphicsClear(bool clearColor, bool clearDepth, bool clearStencil, Color color, float depth, int stencil) {
Layer layer = state.layers[state.layer];
Canvas* canvas = state.canvasCount > 0 ? state.canvas[0] : layer.canvas;
gpuBindFramebuffer(canvas ? canvas->framebuffer : 0);
gpuBindFramebuffer(canvas ? lovrCanvasGetId(canvas) : 0);
if (clearColor) {
gammaCorrectColor(&color);
@ -297,21 +297,21 @@ void lovrGraphicsSetCanvas(Canvas** canvas, int count) {
}
for (int i = 0; i < count; i++) {
lovrRetain(&canvas[i]->texture);
lovrRetain(canvas[i]);
}
for (int i = 0; i < state.canvasCount; i++) {
lovrRelease(&state.canvas[i]->texture);
lovrRelease(state.canvas[i]);
}
if (count > 0) {
memcpy(state.canvas, canvas, count * sizeof(Canvas*));
gpuBindFramebuffer(canvas[0]->framebuffer);
gpuBindFramebuffer(lovrCanvasGetId(canvas[0]));
GLenum buffers[MAX_CANVASES];
for (int i = 0; i < count; i++) {
buffers[i] = GL_COLOR_ATTACHMENT0 + i;
glFramebufferTexture2D(GL_FRAMEBUFFER, buffers[i], GL_TEXTURE_2D, canvas[i]->texture.id, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, buffers[i], GL_TEXTURE_2D, lovrTextureGetId((Texture*) canvas[i]), 0);
}
glDrawBuffers(count, buffers);
@ -916,7 +916,7 @@ void lovrGraphicsSkybox(Texture* texture, float angle, float ax, float ay, float
1, -1, 1, 0, 0, 0, 0, 0
};
TextureType type = texture->type;
TextureType type = lovrTextureGetType(texture);
lovrAssert(type == TEXTURE_CUBE || type == TEXTURE_2D, "Only 2D and cube textures can be used as skyboxes");
MaterialTexture materialTexture = type == TEXTURE_CUBE ? TEXTURE_ENVIRONMENT_MAP : TEXTURE_DIFFUSE;
DefaultShader shader = type == TEXTURE_CUBE ? SHADER_CUBE : SHADER_PANO;
@ -1029,9 +1029,9 @@ void lovrGraphicsDraw(Mesh* mesh, mat4 transform, DefaultShader defaultShader, i
// Layer
Layer layer = state.layers[state.layer];
Canvas* canvas = state.canvasCount > 0 ? state.canvas[0] : layer.canvas;
gpuBindFramebuffer(canvas ? canvas->framebuffer : 0);
gpuBindFramebuffer(canvas ? lovrCanvasGetId(canvas) : 0);
gpuSetViewport(state.canvasCount > 0 ?
(uint32_t[4]) { 0, 0, state.canvas[0]->texture.width, state.canvas[0]->texture.height } :
(uint32_t[4]) { 0, 0, lovrTextureGetWidth((Texture*) state.canvas[0]), lovrTextureGetHeight((Texture*) state.canvas[0]) } :
layer.viewport
);
@ -1116,27 +1116,31 @@ void lovrGraphicsDraw(Mesh* mesh, mat4 transform, DefaultShader defaultShader, i
lovrShaderSetTexture(shader, lovrShaderTextureUniforms[i], &texture, 1);
}
gpuUseProgram(shader->program);
gpuUseProgram(lovrShaderGetProgram(shader));
lovrShaderBind(shader);
lovrMeshBind(mesh, shader);
size_t start = mesh->rangeStart;
GLenum glDrawMode = convertMeshDrawMode(mesh->drawMode);
if (mesh->indexCount > 0) {
size_t count = mesh->rangeCount ? mesh->rangeCount : mesh->indexCount;
GLenum indexType = mesh->indexSize == sizeof(uint16_t) ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
size_t offset = start * mesh->indexSize;
uint32_t rangeStart, rangeCount;
lovrMeshGetDrawRange(mesh, &rangeStart, &rangeCount);
uint32_t indexCount;
size_t indexSize;
lovrMeshReadIndices(mesh, &indexCount, &indexSize);
GLenum glDrawMode = convertMeshDrawMode(lovrMeshGetDrawMode(mesh));
if (indexCount > 0) {
size_t count = rangeCount ? rangeCount : indexCount;
GLenum indexType = indexSize == sizeof(uint16_t) ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
size_t offset = rangeStart * indexSize;
if (instances > 1) {
glDrawElementsInstanced(glDrawMode, count, indexType, (GLvoid*) offset, instances);
} else {
glDrawElements(glDrawMode, count, indexType, (GLvoid*) offset);
}
} else {
size_t count = mesh->rangeCount ? mesh->rangeCount : mesh->count;
size_t count = rangeCount ? rangeCount : lovrMeshGetVertexCount(mesh);
if (instances > 1) {
glDrawArraysInstanced(glDrawMode, start, count, instances);
glDrawArraysInstanced(glDrawMode, rangeStart, count, instances);
} else {
glDrawArrays(glDrawMode, start, count);
glDrawArrays(glDrawMode, rangeStart, count);
}
}
@ -1196,7 +1200,7 @@ void lovrGraphicsBindTexture(Texture* texture, GLenum type, int slot) {
lovrRelease(state.textures[slot]);
state.textures[slot] = texture;
glActiveTexture(GL_TEXTURE0 + slot);
glBindTexture(type, texture->id);
glBindTexture(type, lovrTextureGetId(texture));
}
}

View File

@ -275,6 +275,10 @@ void lovrShaderDestroy(void* ref) {
free(shader);
}
uint32_t lovrShaderGetProgram(Shader* shader) {
return shader->program;
}
void lovrShaderBind(Shader* shader) {
map_iter_t iter = map_iter(&shader->uniforms);
const char* key;

View File

@ -54,16 +54,19 @@ typedef struct {
typedef map_t(Uniform) map_uniform_t;
typedef struct {
typedef struct Shader Shader;
struct Shader {
Ref ref;
uint32_t program;
map_uniform_t uniforms;
map_int_t attributes;
} Shader;
};
Shader* lovrShaderCreate(const char* vertexSource, const char* fragmentSource);
Shader* lovrShaderCreateDefault(DefaultShader type);
void lovrShaderDestroy(void* ref);
uint32_t lovrShaderGetProgram(Shader* shader);
void lovrShaderBind(Shader* shader);
int lovrShaderGetAttributeId(Shader* shader, const char* name);
Uniform* lovrShaderGetUniform(Shader* shader, const char* name);

View File

@ -139,6 +139,22 @@ void lovrTextureDestroy(void* ref) {
free(texture);
}
GLuint lovrTextureGetId(Texture* texture) {
return texture->id;
}
int lovrTextureGetWidth(Texture* texture) {
return texture->width;
}
int lovrTextureGetHeight(Texture* texture) {
return texture->height;
}
int lovrTextureGetDepth(Texture* texture) {
return texture->depth;
}
TextureType lovrTextureGetType(Texture* texture) {
return texture->type;
}

View File

@ -36,7 +36,9 @@ typedef struct {
WrapMode r;
} TextureWrap;
typedef struct {
typedef struct Texture Texture;
struct Texture {
Ref ref;
TextureType type;
GLenum glType;
@ -50,7 +52,7 @@ typedef struct {
bool srgb;
bool mipmaps;
bool allocated;
} Texture;
};
GLenum lovrTextureFormatGetGLFormat(TextureFormat format);
GLenum lovrTextureFormatGetGLInternalFormat(TextureFormat format, bool srgb);
@ -58,6 +60,10 @@ bool lovrTextureFormatIsCompressed(TextureFormat format);
Texture* lovrTextureCreate(TextureType type, TextureData** slices, int depth, bool srgb, bool mipmaps);
void lovrTextureDestroy(void* ref);
uint32_t lovrTextureGetId(Texture* texture); // FIXME temporary
int lovrTextureGetWidth(Texture* texture);
int lovrTextureGetHeight(Texture* texture);
int lovrTextureGetDepth(Texture* texture);
TextureType lovrTextureGetType(Texture* texture);
void lovrTextureReplacePixels(Texture* texture, TextureData* data, int slice);
TextureFilter lovrTextureGetFilter(Texture* texture);

View File

@ -331,7 +331,7 @@ static bool openvrInit(float offset) {
}
static void openvrDestroy() {
lovrRelease(&state.canvas->texture);
lovrRelease(state.canvas);
for (int i = 0; i < 16; i++) {
if (state.deviceModels[i]) {
state.renderModels->FreeRenderModel(state.deviceModels[i]);
@ -694,14 +694,14 @@ static void openvrRenderTo(void (*callback)(void*), void* userdata) {
// Submit
glActiveTexture(GL_TEXTURE0);
Texture* oldTexture = lovrGraphicsGetTexture(0);
uintptr_t texture = (uintptr_t) state.canvas->texture.id;
uintptr_t texture = (uintptr_t) lovrTextureGetId((Texture*) state.canvas);
EColorSpace colorSpace = lovrGraphicsIsGammaCorrect() ? EColorSpace_ColorSpace_Linear : EColorSpace_ColorSpace_Gamma;
Texture_t eyeTexture = { (void*) texture, ETextureType_TextureType_OpenGL, colorSpace };
VRTextureBounds_t left = { 0, 0, .5, 1. };
VRTextureBounds_t right = { .5, 0, 1., 1. };
state.compositor->Submit(EVREye_Eye_Left, &eyeTexture, &left, EVRSubmitFlags_Submit_Default);
state.compositor->Submit(EVREye_Eye_Right, &eyeTexture, &right, EVRSubmitFlags_Submit_Default);
glBindTexture(GL_TEXTURE_2D, oldTexture->id);
glBindTexture(GL_TEXTURE_2D, lovrTextureGetId(oldTexture));
lovrGraphicsPopLayer();
state.isRendering = false;
@ -712,7 +712,7 @@ static void openvrRenderTo(void (*callback)(void*), void* userdata) {
Shader* lastShader = lovrGraphicsGetShader();
lovrRetain(lastShader);
lovrGraphicsSetShader(NULL);
lovrGraphicsFill(&state.canvas->texture);
lovrGraphicsFill((Texture*) state.canvas);
lovrGraphicsSetShader(lastShader);
lovrRelease(lastShader);
lovrGraphicsSetColor(oldColor);