mirror of https://github.com/bjornbytes/lovr.git
I came in like a wrecking ball;
This commit is contained in:
parent
87c1429778
commit
7795bb9276
|
@ -256,7 +256,7 @@ int l_lovrGraphicsInit(lua_State* L) {
|
||||||
luax_registertype(L, "Shader", lovrShader);
|
luax_registertype(L, "Shader", lovrShader);
|
||||||
luax_registertype(L, "ShaderBlock", lovrShaderBlock);
|
luax_registertype(L, "ShaderBlock", lovrShaderBlock);
|
||||||
luax_registertype(L, "Texture", lovrTexture);
|
luax_registertype(L, "Texture", lovrTexture);
|
||||||
luax_extendtype(L, "Texture", "Canvas", lovrTexture, lovrCanvas);
|
luax_registertype(L, "Canvas", lovrCanvas);
|
||||||
|
|
||||||
luax_pushconf(L);
|
luax_pushconf(L);
|
||||||
|
|
||||||
|
@ -436,22 +436,10 @@ int l_lovrGraphicsSetBlendMode(lua_State* L) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int l_lovrGraphicsGetCanvas(lua_State* L) {
|
int l_lovrGraphicsGetCanvas(lua_State* L) {
|
||||||
Canvas* canvas[MAX_CANVASES];
|
return 0;
|
||||||
int count;
|
|
||||||
lovrGraphicsGetCanvas(canvas, &count);
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
luax_pushobject(L, canvas[i]);
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int l_lovrGraphicsSetCanvas(lua_State* L) {
|
int l_lovrGraphicsSetCanvas(lua_State* L) {
|
||||||
Canvas* canvas[MAX_CANVASES];
|
|
||||||
int count = MIN(lua_gettop(L), MAX_CANVASES);
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
canvas[i] = luax_checktype(L, i + 1, Canvas);
|
|
||||||
}
|
|
||||||
lovrGraphicsSetCanvas(canvas, count);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -949,37 +937,7 @@ int l_lovrGraphicsNewShaderBlock(lua_State* L) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int l_lovrGraphicsNewCanvas(lua_State* L) {
|
int l_lovrGraphicsNewCanvas(lua_State* L) {
|
||||||
int width = luaL_checkinteger(L, 1);
|
Canvas* canvas = lovrCanvasCreate();
|
||||||
int height = luaL_checkinteger(L, 2);
|
|
||||||
luaL_argcheck(L, width > 0, 1, "width must be positive");
|
|
||||||
luaL_argcheck(L, height > 0, 2, "height must be positive");
|
|
||||||
|
|
||||||
TextureFormat format = FORMAT_RGBA;
|
|
||||||
CanvasFlags flags = { .msaa = 0, .depth = true, .stencil = false, .mipmaps = true };
|
|
||||||
|
|
||||||
if (lua_istable(L, 3)) {
|
|
||||||
lua_getfield(L, 3, "format");
|
|
||||||
format = luaL_checkoption(L, -1, "rgba", TextureFormats);
|
|
||||||
lua_pop(L, 1);
|
|
||||||
|
|
||||||
lua_getfield(L, 3, "msaa");
|
|
||||||
flags.msaa = luaL_optinteger(L, -1, 0);
|
|
||||||
lua_pop(L, 1);
|
|
||||||
|
|
||||||
lua_getfield(L, 3, "depth");
|
|
||||||
flags.depth = lua_toboolean(L, -1);
|
|
||||||
lua_pop(L, 1);
|
|
||||||
|
|
||||||
lua_getfield(L, 3, "stencil");
|
|
||||||
flags.stencil = lua_toboolean(L, -1);
|
|
||||||
lua_pop(L, 1);
|
|
||||||
|
|
||||||
lua_getfield(L, 3, "mipmaps");
|
|
||||||
flags.mipmaps = lua_toboolean(L, -1);
|
|
||||||
lua_pop(L, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
Canvas* canvas = lovrCanvasCreate(width, height, format, flags);
|
|
||||||
luax_pushobject(L, canvas);
|
luax_pushobject(L, canvas);
|
||||||
lovrRelease(canvas);
|
lovrRelease(canvas);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -1,46 +1,6 @@
|
||||||
#include "api.h"
|
#include "api.h"
|
||||||
#include "graphics/graphics.h"
|
|
||||||
#include "graphics/canvas.h"
|
#include "graphics/canvas.h"
|
||||||
|
|
||||||
int l_lovrCanvasRenderTo(lua_State* L) {
|
|
||||||
Canvas* canvas = luax_checktype(L, 1, Canvas);
|
|
||||||
luaL_checktype(L, 2, LUA_TFUNCTION);
|
|
||||||
int nargs = lua_gettop(L) - 2;
|
|
||||||
|
|
||||||
Canvas* old[MAX_CANVASES];
|
|
||||||
int count;
|
|
||||||
lovrGraphicsGetCanvas(old, &count);
|
|
||||||
lovrGraphicsSetCanvas(&canvas, 1);
|
|
||||||
lua_call(L, nargs, 0);
|
|
||||||
lovrGraphicsSetCanvas(old, count);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int l_lovrCanvasGetFormat(lua_State* L) {
|
|
||||||
Canvas* canvas = luax_checktype(L, 1, Canvas);
|
|
||||||
TextureFormat format = lovrCanvasGetFormat(canvas);
|
|
||||||
lua_pushstring(L, TextureFormats[format]);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int l_lovrCanvasGetMSAA(lua_State* L) {
|
|
||||||
Canvas* canvas = luax_checktype(L, 1, Canvas);
|
|
||||||
lua_pushinteger(L, lovrCanvasGetMSAA(canvas));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int l_lovrCanvasNewTextureData(lua_State* L) {
|
|
||||||
Canvas* canvas = luax_checktype(L, 1, Canvas);
|
|
||||||
TextureData* textureData = lovrCanvasNewTextureData(canvas);
|
|
||||||
luax_pushobject(L, textureData);
|
|
||||||
lovrRelease(textureData);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const luaL_Reg lovrCanvas[] = {
|
const luaL_Reg lovrCanvas[] = {
|
||||||
{ "renderTo", l_lovrCanvasRenderTo },
|
|
||||||
{ "getFormat", l_lovrCanvasGetFormat },
|
|
||||||
{ "getMSAA", l_lovrCanvasGetMSAA },
|
|
||||||
{ "newTextureData", l_lovrCanvasNewTextureData },
|
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,25 +1,6 @@
|
||||||
#include "graphics/texture.h"
|
|
||||||
#include "data/textureData.h"
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define MAX_CANVASES 4
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int msaa;
|
|
||||||
bool depth;
|
|
||||||
bool stencil;
|
|
||||||
bool mipmaps;
|
|
||||||
} CanvasFlags;
|
|
||||||
|
|
||||||
typedef struct Canvas Canvas;
|
typedef struct Canvas Canvas;
|
||||||
|
|
||||||
bool lovrCanvasSupportsFormat(TextureFormat format);
|
Canvas* lovrCanvasCreate();
|
||||||
|
|
||||||
Canvas* lovrCanvasCreate(int width, int height, TextureFormat format, CanvasFlags flags);
|
|
||||||
void lovrCanvasDestroy(void* ref);
|
void lovrCanvasDestroy(void* ref);
|
||||||
void lovrCanvasResolve(Canvas* canvas);
|
|
||||||
TextureFormat lovrCanvasGetFormat(Canvas* canvas);
|
|
||||||
int lovrCanvasGetMSAA(Canvas* canvas);
|
|
||||||
TextureData* lovrCanvasNewTextureData(Canvas* canvas);
|
|
||||||
|
|
|
@ -34,7 +34,6 @@ void lovrGraphicsDestroy() {
|
||||||
}
|
}
|
||||||
lovrGraphicsSetShader(NULL);
|
lovrGraphicsSetShader(NULL);
|
||||||
lovrGraphicsSetFont(NULL);
|
lovrGraphicsSetFont(NULL);
|
||||||
lovrGraphicsSetCanvas(NULL, 0);
|
|
||||||
for (int i = 0; i < MAX_DEFAULT_SHADERS; i++) {
|
for (int i = 0; i < MAX_DEFAULT_SHADERS; i++) {
|
||||||
lovrRelease(state.defaultShaders[i]);
|
lovrRelease(state.defaultShaders[i]);
|
||||||
}
|
}
|
||||||
|
@ -142,9 +141,8 @@ void lovrGraphicsSetCamera(Camera* camera, bool clear) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clear) {
|
if (clear) {
|
||||||
int canvasCount = state.camera.canvas != NULL;
|
|
||||||
Color backgroundColor = lovrGraphicsGetBackgroundColor();
|
Color backgroundColor = lovrGraphicsGetBackgroundColor();
|
||||||
lovrGpuClear(&state.camera.canvas, canvasCount, &backgroundColor, &(float) { 1. }, &(int) { 0 });
|
lovrGpuClear(state.camera.canvas, &backgroundColor, &(float) { 1. }, &(int) { 0 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,7 +156,6 @@ void lovrGraphicsReset() {
|
||||||
lovrGraphicsSetCamera(NULL, false);
|
lovrGraphicsSetCamera(NULL, false);
|
||||||
lovrGraphicsSetBackgroundColor((Color) { 0, 0, 0, 1 });
|
lovrGraphicsSetBackgroundColor((Color) { 0, 0, 0, 1 });
|
||||||
lovrGraphicsSetBlendMode(BLEND_ALPHA, BLEND_ALPHA_MULTIPLY);
|
lovrGraphicsSetBlendMode(BLEND_ALPHA, BLEND_ALPHA_MULTIPLY);
|
||||||
lovrGraphicsSetCanvas(NULL, 0);
|
|
||||||
lovrGraphicsSetColor((Color) { 1, 1, 1, 1 });
|
lovrGraphicsSetColor((Color) { 1, 1, 1, 1 });
|
||||||
lovrGraphicsSetCullingEnabled(false);
|
lovrGraphicsSetCullingEnabled(false);
|
||||||
lovrGraphicsSetDefaultFilter((TextureFilter) { .mode = FILTER_TRILINEAR });
|
lovrGraphicsSetDefaultFilter((TextureFilter) { .mode = FILTER_TRILINEAR });
|
||||||
|
@ -176,17 +173,11 @@ void lovrGraphicsReset() {
|
||||||
void lovrGraphicsPushPipeline() {
|
void lovrGraphicsPushPipeline() {
|
||||||
lovrAssert(++state.pipeline < MAX_PIPELINES, "Unbalanced pipeline stack (more pushes than pops?)");
|
lovrAssert(++state.pipeline < MAX_PIPELINES, "Unbalanced pipeline stack (more pushes than pops?)");
|
||||||
memcpy(&state.pipelines[state.pipeline], &state.pipelines[state.pipeline - 1], sizeof(Pipeline));
|
memcpy(&state.pipelines[state.pipeline], &state.pipelines[state.pipeline - 1], sizeof(Pipeline));
|
||||||
for (int i = 0; i < state.pipelines[state.pipeline].canvasCount; i++) {
|
|
||||||
lovrRetain(state.pipelines[state.pipeline].canvas[i]);
|
|
||||||
}
|
|
||||||
lovrRetain(state.pipelines[state.pipeline].font);
|
lovrRetain(state.pipelines[state.pipeline].font);
|
||||||
lovrRetain(state.pipelines[state.pipeline].shader);
|
lovrRetain(state.pipelines[state.pipeline].shader);
|
||||||
}
|
}
|
||||||
|
|
||||||
void lovrGraphicsPopPipeline() {
|
void lovrGraphicsPopPipeline() {
|
||||||
for (int i = 0; i < state.pipelines[state.pipeline].canvasCount; i++) {
|
|
||||||
lovrRelease(state.pipelines[state.pipeline].canvas[i]);
|
|
||||||
}
|
|
||||||
lovrRelease(state.pipelines[state.pipeline].font);
|
lovrRelease(state.pipelines[state.pipeline].font);
|
||||||
lovrRelease(state.pipelines[state.pipeline].shader);
|
lovrRelease(state.pipelines[state.pipeline].shader);
|
||||||
lovrAssert(--state.pipeline >= 0, "Unbalanced pipeline stack (more pops than pushes?)");
|
lovrAssert(--state.pipeline >= 0, "Unbalanced pipeline stack (more pops than pushes?)");
|
||||||
|
@ -210,24 +201,6 @@ void lovrGraphicsSetBlendMode(BlendMode mode, BlendAlphaMode alphaMode) {
|
||||||
state.pipelines[state.pipeline].blendAlphaMode = alphaMode;
|
state.pipelines[state.pipeline].blendAlphaMode = alphaMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lovrGraphicsGetCanvas(Canvas** canvas, int* count) {
|
|
||||||
*count = state.pipelines[state.pipeline].canvasCount;
|
|
||||||
memcpy(canvas, state.pipelines[state.pipeline].canvas, *count);
|
|
||||||
}
|
|
||||||
|
|
||||||
void lovrGraphicsSetCanvas(Canvas** canvas, int count) {
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
lovrRetain(canvas[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < state.pipelines[state.pipeline].canvasCount; i++) {
|
|
||||||
lovrRelease(state.pipelines[state.pipeline].canvas[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(state.pipelines[state.pipeline].canvas, canvas, count * sizeof(Canvas*));
|
|
||||||
state.pipelines[state.pipeline].canvasCount = count;
|
|
||||||
}
|
|
||||||
|
|
||||||
Color lovrGraphicsGetColor() {
|
Color lovrGraphicsGetColor() {
|
||||||
return state.pipelines[state.pipeline].color;
|
return state.pipelines[state.pipeline].color;
|
||||||
}
|
}
|
||||||
|
@ -381,11 +354,7 @@ VertexPointer lovrGraphicsGetVertexPointer(uint32_t count) {
|
||||||
|
|
||||||
void lovrGraphicsClear(Color* color, float* depth, int* stencil) {
|
void lovrGraphicsClear(Color* color, float* depth, int* stencil) {
|
||||||
Pipeline* pipeline = &state.pipelines[state.pipeline];
|
Pipeline* pipeline = &state.pipelines[state.pipeline];
|
||||||
if (pipeline->canvasCount > 0) {
|
lovrGpuClear(state.camera.canvas, color, depth, stencil);
|
||||||
lovrGpuClear(pipeline->canvas, pipeline->canvasCount, color, depth, stencil);
|
|
||||||
} else {
|
|
||||||
lovrGpuClear(&state.camera.canvas, state.camera.canvas != NULL, color, depth, stencil);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void lovrGraphicsDraw(DrawOptions* draw) {
|
void lovrGraphicsDraw(DrawOptions* draw) {
|
||||||
|
|
|
@ -106,8 +106,6 @@ typedef struct {
|
||||||
Color backgroundColor;
|
Color backgroundColor;
|
||||||
BlendMode blendMode;
|
BlendMode blendMode;
|
||||||
BlendAlphaMode blendAlphaMode;
|
BlendAlphaMode blendAlphaMode;
|
||||||
Canvas* canvas[MAX_CANVASES];
|
|
||||||
int canvasCount;
|
|
||||||
Color color;
|
Color color;
|
||||||
bool culling;
|
bool culling;
|
||||||
CompareMode depthTest;
|
CompareMode depthTest;
|
||||||
|
@ -192,8 +190,6 @@ Color lovrGraphicsGetBackgroundColor();
|
||||||
void lovrGraphicsSetBackgroundColor(Color color);
|
void lovrGraphicsSetBackgroundColor(Color color);
|
||||||
void lovrGraphicsGetBlendMode(BlendMode* mode, BlendAlphaMode* alphaMode);
|
void lovrGraphicsGetBlendMode(BlendMode* mode, BlendAlphaMode* alphaMode);
|
||||||
void lovrGraphicsSetBlendMode(BlendMode mode, BlendAlphaMode alphaMode);
|
void lovrGraphicsSetBlendMode(BlendMode mode, BlendAlphaMode alphaMode);
|
||||||
void lovrGraphicsGetCanvas(Canvas** canvas, int* count);
|
|
||||||
void lovrGraphicsSetCanvas(Canvas** canvas, int count);
|
|
||||||
Color lovrGraphicsGetColor();
|
Color lovrGraphicsGetColor();
|
||||||
void lovrGraphicsSetColor(Color color);
|
void lovrGraphicsSetColor(Color color);
|
||||||
bool lovrGraphicsIsCullingEnabled();
|
bool lovrGraphicsIsCullingEnabled();
|
||||||
|
@ -252,7 +248,7 @@ typedef void (*gpuProc)(void);
|
||||||
|
|
||||||
void lovrGpuInit(bool srgb, bool singlepass, gpuProc (*getProcAddress)(const char*));
|
void lovrGpuInit(bool srgb, bool singlepass, gpuProc (*getProcAddress)(const char*));
|
||||||
void lovrGpuDestroy();
|
void lovrGpuDestroy();
|
||||||
void lovrGpuClear(Canvas** canvas, int canvasCount, Color* color, float* depth, int* stencil);
|
void lovrGpuClear(Canvas* canvas, Color* color, float* depth, int* stencil);
|
||||||
void lovrGpuDraw(DrawCommand* command);
|
void lovrGpuDraw(DrawCommand* command);
|
||||||
void lovrGpuCompute(Shader* shader, int x, int y, int z);
|
void lovrGpuCompute(Shader* shader, int x, int y, int z);
|
||||||
void lovrGpuWait(uint8_t flags);
|
void lovrGpuWait(uint8_t flags);
|
||||||
|
|
|
@ -49,8 +49,6 @@ static struct {
|
||||||
bool stencilWriting;
|
bool stencilWriting;
|
||||||
Winding winding;
|
Winding winding;
|
||||||
bool wireframe;
|
bool wireframe;
|
||||||
Canvas* canvas[MAX_CANVASES];
|
|
||||||
int canvasCount;
|
|
||||||
uint32_t framebuffer;
|
uint32_t framebuffer;
|
||||||
uint32_t indexBuffer;
|
uint32_t indexBuffer;
|
||||||
uint32_t program;
|
uint32_t program;
|
||||||
|
@ -111,13 +109,8 @@ struct Texture {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Canvas {
|
struct Canvas {
|
||||||
Texture texture;
|
Ref ref;
|
||||||
GLuint framebuffer;
|
uint32_t framebuffer;
|
||||||
GLuint resolveFramebuffer;
|
|
||||||
GLuint depthStencilBuffer;
|
|
||||||
GLuint msaaTexture;
|
|
||||||
CanvasFlags flags;
|
|
||||||
Canvas** attachments[MAX_CANVASES];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -286,16 +279,6 @@ static GLenum convertMeshDrawMode(MeshDrawMode mode) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isCanvasFormatSupported(TextureFormat format) {
|
|
||||||
switch (format) {
|
|
||||||
case FORMAT_DXT1:
|
|
||||||
case FORMAT_DXT3:
|
|
||||||
case FORMAT_DXT5:
|
|
||||||
return false;
|
|
||||||
default: return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static UniformType getUniformType(GLenum type, const char* debug) {
|
static UniformType getUniformType(GLenum type, const char* debug) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case GL_FLOAT:
|
case GL_FLOAT:
|
||||||
|
@ -448,13 +431,6 @@ static void lovrGpuCleanupIncoherentResource(void* resource, uint8_t incoherent)
|
||||||
|
|
||||||
// GPU
|
// GPU
|
||||||
|
|
||||||
static void lovrGpuBindFramebuffer(uint32_t framebuffer) {
|
|
||||||
if (state.framebuffer != framebuffer) {
|
|
||||||
state.framebuffer = framebuffer;
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void lovrGpuBindIndexBuffer(uint32_t indexBuffer) {
|
static void lovrGpuBindIndexBuffer(uint32_t indexBuffer) {
|
||||||
if (state.indexBuffer != indexBuffer) {
|
if (state.indexBuffer != indexBuffer) {
|
||||||
state.indexBuffer = indexBuffer;
|
state.indexBuffer = indexBuffer;
|
||||||
|
@ -529,13 +505,6 @@ static void lovrGpuBindVertexBuffer(uint32_t vertexBuffer) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lovrGpuSetViewport(float viewport[4]) {
|
|
||||||
if (memcmp(state.viewport, viewport, 4 * sizeof(float))) {
|
|
||||||
memcpy(state.viewport, viewport, 4 * sizeof(float));
|
|
||||||
glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void lovrGpuUseProgram(uint32_t program) {
|
static void lovrGpuUseProgram(uint32_t program) {
|
||||||
if (state.program != program) {
|
if (state.program != program) {
|
||||||
state.program = program;
|
state.program = program;
|
||||||
|
@ -590,34 +559,7 @@ void lovrGpuDestroy() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void lovrGpuClear(Canvas** canvas, int canvasCount, Color* color, float* depth, int* stencil) {
|
void lovrGpuClear(Canvas* canvas, Color* color, float* depth, int* stencil) {
|
||||||
lovrGpuBindFramebuffer(canvasCount > 0 ? canvas[0]->framebuffer : 0);
|
|
||||||
|
|
||||||
if (color) {
|
|
||||||
gammaCorrectColor(color);
|
|
||||||
float c[4] = { color->r, color->g, color->b, color->a };
|
|
||||||
glClearBufferfv(GL_COLOR, 0, c);
|
|
||||||
for (int i = 1; i < canvasCount; i++) {
|
|
||||||
glClearBufferfv(GL_COLOR, i, c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (depth) {
|
|
||||||
if (!state.depthWrite) {
|
|
||||||
state.depthWrite = true;
|
|
||||||
glDepthMask(state.depthWrite);
|
|
||||||
}
|
|
||||||
|
|
||||||
glClearBufferfv(GL_DEPTH, 0, depth);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stencil) {
|
|
||||||
glClearBufferiv(GL_STENCIL, 0, stencil);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (canvasCount > 0) {
|
|
||||||
lovrCanvasResolve(canvas[0]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void lovrGraphicsStencil(StencilAction action, int replaceValue, StencilCallback callback, void* userdata) {
|
void lovrGraphicsStencil(StencilAction action, int replaceValue, StencilCallback callback, void* userdata) {
|
||||||
|
@ -864,65 +806,14 @@ void lovrGpuDraw(DrawCommand* command) {
|
||||||
|
|
||||||
lovrShaderSetMatrices(shader, "lovrMaterialTransform", material->transform, 0, 9);
|
lovrShaderSetMatrices(shader, "lovrMaterialTransform", material->transform, 0, 9);
|
||||||
|
|
||||||
// Canvas
|
|
||||||
Canvas** canvas = pipeline->canvasCount > 0 ? pipeline->canvas : &command->camera.canvas;
|
|
||||||
int canvasCount = pipeline->canvasCount > 0 ? pipeline->canvasCount : (command->camera.canvas != NULL);
|
|
||||||
if (canvasCount != state.canvasCount || memcmp(state.canvas, canvas, canvasCount * sizeof(Canvas*))) {
|
|
||||||
if (state.canvasCount > 0) {
|
|
||||||
lovrCanvasResolve(state.canvas[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
state.canvasCount = canvasCount;
|
|
||||||
|
|
||||||
if (canvasCount > 0) {
|
|
||||||
memcpy(state.canvas, canvas, canvasCount * sizeof(Canvas*));
|
|
||||||
lovrGpuBindFramebuffer(canvas[0]->framebuffer);
|
|
||||||
|
|
||||||
GLenum buffers[MAX_CANVASES];
|
|
||||||
for (int i = 0; i < canvasCount; i++) {
|
|
||||||
buffers[i] = GL_COLOR_ATTACHMENT0 + i;
|
|
||||||
if (canvas[i]->flags.msaa > 0) {
|
|
||||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, buffers[i], GL_RENDERBUFFER, canvas[i]->msaaTexture);
|
|
||||||
} else {
|
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, buffers[i], GL_TEXTURE_2D, lovrTextureGetId((Texture*) canvas[i]), 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
glDrawBuffers(canvasCount, buffers);
|
|
||||||
|
|
||||||
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
|
||||||
lovrAssert(status == GL_FRAMEBUFFER_COMPLETE, "Unable to bind framebuffer");
|
|
||||||
} else {
|
|
||||||
lovrGpuBindFramebuffer(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We need to synchronize if any attached textures have pending writes
|
|
||||||
for (int i = 0; i < canvasCount; i++) {
|
|
||||||
if ((canvas[i]->texture.incoherent >> BARRIER_CANVAS) & 1) {
|
|
||||||
lovrGpuWait(1 << BARRIER_CANVAS);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bind attributes
|
// Bind attributes
|
||||||
lovrMeshBind(mesh, shader);
|
lovrMeshBind(mesh, shader);
|
||||||
|
|
||||||
bool stereo = pipeline->canvasCount == 0 && command->camera.stereo == true;
|
bool stereo = false;
|
||||||
int drawCount = 1 + (stereo == true && !state.singlepass);
|
int drawCount = 1 + (stereo == true && !state.singlepass);
|
||||||
|
|
||||||
// Draw (TODEW)
|
// Draw (TODEW)
|
||||||
for (int i = 0; i < drawCount; i++) {
|
for (int i = 0; i < drawCount; i++) {
|
||||||
if (pipeline->canvasCount > 0) {
|
|
||||||
int width = lovrTextureGetWidth((Texture*) pipeline->canvas[0], 0);
|
|
||||||
int height = lovrTextureGetHeight((Texture*) pipeline->canvas[0], 0);
|
|
||||||
lovrGpuSetViewport((float[4]) { 0, 0, width, height });
|
|
||||||
#ifndef EMSCRIPTEN
|
|
||||||
} else if (state.singlepass) {
|
|
||||||
glViewportArrayv(0, 2, command->camera.viewport[0]);
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
lovrGpuSetViewport(command->camera.viewport[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bind uniforms
|
// Bind uniforms
|
||||||
lovrShaderSetInts(shader, "lovrIsStereo", &(int) { stereo && state.singlepass }, 0, 1);
|
lovrShaderSetInts(shader, "lovrIsStereo", &(int) { stereo && state.singlepass }, 0, 1);
|
||||||
|
@ -1295,125 +1186,16 @@ void lovrTextureSetWrap(Texture* texture, TextureWrap wrap) {
|
||||||
|
|
||||||
// Canvas
|
// Canvas
|
||||||
|
|
||||||
Canvas* lovrCanvasCreate(int width, int height, TextureFormat format, CanvasFlags flags) {
|
Canvas* lovrCanvasCreate() {
|
||||||
lovrAssert(isCanvasFormatSupported(format), "Unsupported texture format for Canvas");
|
|
||||||
Canvas* canvas = lovrAlloc(Canvas, lovrCanvasDestroy);
|
Canvas* canvas = lovrAlloc(Canvas, lovrCanvasDestroy);
|
||||||
Texture* texture = lovrTextureCreate(TEXTURE_2D, NULL, 0, true, flags.mipmaps);
|
if (!canvas) return NULL;
|
||||||
|
|
||||||
if (!canvas || !texture) {
|
|
||||||
lovrRelease(canvas);
|
|
||||||
lovrRelease(texture);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
lovrTextureAllocate(texture, width, height, 1, format);
|
|
||||||
|
|
||||||
Ref ref = canvas->texture.ref;
|
|
||||||
canvas->texture = *texture;
|
|
||||||
canvas->texture.ref = ref;
|
|
||||||
canvas->flags = flags;
|
|
||||||
|
|
||||||
// Framebuffer
|
|
||||||
glGenFramebuffers(1, &canvas->framebuffer);
|
|
||||||
lovrGpuBindFramebuffer(canvas->framebuffer);
|
|
||||||
|
|
||||||
// Color attachment
|
|
||||||
if (flags.msaa > 0) {
|
|
||||||
GLenum internalFormat = convertTextureFormatInternal(format, lovrGraphicsIsGammaCorrect());
|
|
||||||
glGenRenderbuffers(1, &canvas->msaaTexture);
|
|
||||||
glBindRenderbuffer(GL_RENDERBUFFER, canvas->msaaTexture);
|
|
||||||
glRenderbufferStorageMultisample(GL_RENDERBUFFER, flags.msaa, internalFormat, width, height);
|
|
||||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, canvas->msaaTexture);
|
|
||||||
} else {
|
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, canvas->texture.id, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Depth/Stencil
|
|
||||||
if (flags.depth || flags.stencil) {
|
|
||||||
GLenum depthStencilFormat = flags.stencil ? GL_DEPTH24_STENCIL8 : GL_DEPTH_COMPONENT24;
|
|
||||||
glGenRenderbuffers(1, &canvas->depthStencilBuffer);
|
|
||||||
glBindRenderbuffer(GL_RENDERBUFFER, canvas->depthStencilBuffer);
|
|
||||||
if (flags.msaa > 0) {
|
|
||||||
glRenderbufferStorageMultisample(GL_RENDERBUFFER, flags.msaa, depthStencilFormat, width, height);
|
|
||||||
} else {
|
|
||||||
glRenderbufferStorage(GL_RENDERBUFFER, depthStencilFormat, width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags.depth) {
|
|
||||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, canvas->depthStencilBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags.stencil) {
|
|
||||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, canvas->depthStencilBuffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resolve framebuffer
|
|
||||||
if (flags.msaa > 0) {
|
|
||||||
glGenFramebuffers(1, &canvas->resolveFramebuffer);
|
|
||||||
lovrGpuBindFramebuffer(canvas->resolveFramebuffer);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, canvas->texture.id);
|
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, canvas->texture.id, 0);
|
|
||||||
lovrGpuBindFramebuffer(canvas->framebuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
lovrAssert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE, "Error creating Canvas");
|
|
||||||
lovrGpuClear(&canvas, 1, &(Color) { 0, 0, 0, 0 }, &(float) { 1. }, &(int) { 0 });
|
|
||||||
|
|
||||||
return canvas;
|
return canvas;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lovrCanvasDestroy(void* ref) {
|
void lovrCanvasDestroy(void* ref) {
|
||||||
Canvas* canvas = ref;
|
Canvas* canvas = ref;
|
||||||
glDeleteFramebuffers(1, &canvas->framebuffer);
|
free(ref);
|
||||||
if (canvas->resolveFramebuffer) {
|
|
||||||
glDeleteFramebuffers(1, &canvas->resolveFramebuffer);
|
|
||||||
}
|
|
||||||
if (canvas->depthStencilBuffer) {
|
|
||||||
glDeleteRenderbuffers(1, &canvas->depthStencilBuffer);
|
|
||||||
}
|
|
||||||
if (canvas->msaaTexture) {
|
|
||||||
glDeleteTextures(1, &canvas->msaaTexture);
|
|
||||||
}
|
|
||||||
lovrTextureDestroy(ref);
|
|
||||||
}
|
|
||||||
|
|
||||||
void lovrCanvasResolve(Canvas* canvas) {
|
|
||||||
if (canvas->flags.msaa > 0) {
|
|
||||||
int width = canvas->texture.width;
|
|
||||||
int height = canvas->texture.height;
|
|
||||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, canvas->framebuffer);
|
|
||||||
lovrGpuBindFramebuffer(canvas->resolveFramebuffer);
|
|
||||||
glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
|
||||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (canvas->flags.mipmaps) {
|
|
||||||
lovrGpuBindTexture(&canvas->texture, 0);
|
|
||||||
glGenerateMipmap(canvas->texture.target);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TextureFormat lovrCanvasGetFormat(Canvas* canvas) {
|
|
||||||
return canvas->texture.format;
|
|
||||||
}
|
|
||||||
|
|
||||||
int lovrCanvasGetMSAA(Canvas* canvas) {
|
|
||||||
return canvas->flags.msaa;
|
|
||||||
}
|
|
||||||
|
|
||||||
TextureData* lovrCanvasNewTextureData(Canvas* canvas) {
|
|
||||||
TextureData* textureData = lovrTextureDataGetBlank(canvas->texture.width, canvas->texture.height, 0, FORMAT_RGBA);
|
|
||||||
if (!textureData) return NULL;
|
|
||||||
|
|
||||||
if ((canvas->texture.incoherent >> BARRIER_TEXTURE) & 1) {
|
|
||||||
lovrGpuWait(1 << BARRIER_TEXTURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
lovrGpuBindFramebuffer(canvas->framebuffer);
|
|
||||||
glReadPixels(0, 0, canvas->texture.width, canvas->texture.height, GL_RGBA, GL_UNSIGNED_BYTE, textureData->blob.data);
|
|
||||||
|
|
||||||
return textureData;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shader
|
// Shader
|
||||||
|
|
|
@ -240,11 +240,7 @@ static void ensureCanvas() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int maxMSAA = lovrGraphicsGetLimits().textureMSAA;
|
state.canvas = lovrCanvasCreate();
|
||||||
int msaa = state.msaa == -1 ? maxMSAA : MIN(state.msaa, maxMSAA);
|
|
||||||
state.system->GetRecommendedRenderTargetSize(&state.renderWidth, &state.renderHeight);
|
|
||||||
CanvasFlags flags = { .msaa = msaa, .depth = true, .stencil = true, .mipmaps = false };
|
|
||||||
state.canvas = lovrCanvasCreate(state.renderWidth * 2, state.renderHeight, FORMAT_RGB, flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool openvrInit(float offset, int msaa) {
|
static bool openvrInit(float offset, int msaa) {
|
||||||
|
@ -685,12 +681,10 @@ static void openvrRenderTo(void (*callback)(void*), void* userdata) {
|
||||||
lovrGraphicsSetCamera(&camera, true);
|
lovrGraphicsSetCamera(&camera, true);
|
||||||
callback(userdata);
|
callback(userdata);
|
||||||
lovrGraphicsSetCamera(NULL, false);
|
lovrGraphicsSetCamera(NULL, false);
|
||||||
lovrGraphicsSetCanvas(NULL, 0);
|
|
||||||
lovrCanvasResolve(state.canvas);
|
|
||||||
state.isRendering = false;
|
state.isRendering = false;
|
||||||
|
|
||||||
// Submit
|
// Submit
|
||||||
uintptr_t texture = (uintptr_t) lovrTextureGetId((Texture*) state.canvas);
|
uintptr_t texture = (uintptr_t) 0; // TODO
|
||||||
EColorSpace colorSpace = lovrGraphicsIsGammaCorrect() ? EColorSpace_ColorSpace_Linear : EColorSpace_ColorSpace_Gamma;
|
EColorSpace colorSpace = lovrGraphicsIsGammaCorrect() ? EColorSpace_ColorSpace_Linear : EColorSpace_ColorSpace_Gamma;
|
||||||
Texture_t eyeTexture = { (void*) texture, ETextureType_TextureType_OpenGL, colorSpace };
|
Texture_t eyeTexture = { (void*) texture, ETextureType_TextureType_OpenGL, colorSpace };
|
||||||
VRTextureBounds_t left = { 0, 0, .5, 1. };
|
VRTextureBounds_t left = { 0, 0, .5, 1. };
|
||||||
|
@ -703,7 +697,7 @@ static void openvrRenderTo(void (*callback)(void*), void* userdata) {
|
||||||
lovrGraphicsPushPipeline();
|
lovrGraphicsPushPipeline();
|
||||||
lovrGraphicsSetColor((Color) { 1, 1, 1, 1 });
|
lovrGraphicsSetColor((Color) { 1, 1, 1, 1 });
|
||||||
lovrGraphicsSetShader(NULL);
|
lovrGraphicsSetShader(NULL);
|
||||||
lovrGraphicsFill((Texture*) state.canvas);
|
// TODO
|
||||||
lovrGraphicsPopPipeline();
|
lovrGraphicsPopPipeline();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue