Opaque Canvas;

This commit is contained in:
bjorn 2020-02-22 22:19:59 -08:00
parent 52d4f7e520
commit d034e8c01b
5 changed files with 104 additions and 96 deletions

View File

@ -1,67 +0,0 @@
#include "graphics/canvas.h"
#include "graphics/graphics.h"
#include "core/ref.h"
#include <stdlib.h>
const Attachment* lovrCanvasGetAttachments(Canvas* canvas, uint32_t* count) {
if (count) *count = canvas->attachmentCount;
return canvas->attachments;
}
void lovrCanvasSetAttachments(Canvas* canvas, Attachment* attachments, uint32_t count) {
lovrAssert(count > 0, "A Canvas must have at least one attached Texture");
lovrAssert(count <= MAX_CANVAS_ATTACHMENTS, "Only %d textures can be attached to a Canvas, got %d\n", MAX_CANVAS_ATTACHMENTS, count);
if (!canvas->needsAttach && count == canvas->attachmentCount && !memcmp(canvas->attachments, attachments, count * sizeof(Attachment))) {
return;
}
lovrGraphicsFlushCanvas(canvas);
for (uint32_t i = 0; i < count; i++) {
Texture* texture = attachments[i].texture;
uint32_t slice = attachments[i].slice;
uint32_t level = attachments[i].level;
uint32_t width = lovrTextureGetWidth(texture, level);
uint32_t height = lovrTextureGetHeight(texture, level);
uint32_t depth = lovrTextureGetDepth(texture, level);
uint32_t mipmaps = lovrTextureGetMipmapCount(texture);
bool hasDepthBuffer = canvas->flags.depth.enabled;
lovrAssert(slice < depth, "Invalid attachment slice (Texture has %d, got %d)", depth, slice + 1);
lovrAssert(level < mipmaps, "Invalid attachment mipmap level (Texture has %d, got %d)", mipmaps, level + 1);
lovrAssert(!hasDepthBuffer || width == canvas->width, "Texture width of %d does not match Canvas width (%d)", width, canvas->width);
lovrAssert(!hasDepthBuffer || height == canvas->height, "Texture height of %d does not match Canvas height (%d)", height, canvas->height);
#ifndef __ANDROID__ // On multiview canvases, the multisample settings can be different
lovrAssert(lovrTextureGetMSAA(texture) == canvas->flags.msaa, "Texture MSAA does not match Canvas MSAA");
#endif
lovrRetain(texture);
}
for (uint32_t i = 0; i < canvas->attachmentCount; i++) {
lovrRelease(Texture, canvas->attachments[i].texture);
}
memcpy(canvas->attachments, attachments, count * sizeof(Attachment));
canvas->attachmentCount = count;
canvas->needsAttach = true;
}
bool lovrCanvasIsStereo(Canvas* canvas) {
return canvas->flags.stereo;
}
uint32_t lovrCanvasGetWidth(Canvas* canvas) {
return canvas->width;
}
uint32_t lovrCanvasGetHeight(Canvas* canvas) {
return canvas->height;
}
uint32_t lovrCanvasGetMSAA(Canvas* canvas) {
return canvas->flags.msaa;
}
Texture* lovrCanvasGetDepthTexture(Canvas* canvas) {
return canvas->depth.texture;
}

View File

@ -1,5 +1,4 @@
#include "graphics/texture.h"
#include "graphics/opengl.h"
#pragma once
@ -25,29 +24,19 @@ typedef struct {
bool mipmaps;
} CanvasFlags;
typedef struct Canvas {
uint32_t width;
uint32_t height;
CanvasFlags flags;
Attachment attachments[MAX_CANVAS_ATTACHMENTS];
Attachment depth;
uint32_t attachmentCount;
bool needsAttach;
bool needsResolve;
GPU_CANVAS_FIELDS
} Canvas;
Canvas* lovrCanvasInit(Canvas* canvas, uint32_t width, uint32_t height, CanvasFlags flags);
Canvas* lovrCanvasInitFromHandle(Canvas* canvas, uint32_t width, uint32_t height, CanvasFlags flags, uint32_t framebuffer, uint32_t depthBuffer, uint32_t resolveBuffer, uint32_t attachmentCount, bool immortal);
#define lovrCanvasCreate(...) lovrCanvasInit(lovrAlloc(Canvas), __VA_ARGS__)
#define lovrCanvasCreateFromHandle(...) lovrCanvasInitFromHandle(lovrAlloc(Canvas), __VA_ARGS__)
typedef struct Canvas Canvas;
Canvas* lovrCanvasCreate(uint32_t width, uint32_t height, CanvasFlags flags);
Canvas* lovrCanvasCreateFromHandle(uint32_t width, uint32_t height, CanvasFlags flags, uint32_t framebuffer, uint32_t depthBuffer, uint32_t resolveBuffer, uint32_t attachmentCount, bool immortal);
void lovrCanvasDestroy(void* ref);
const Attachment* lovrCanvasGetAttachments(Canvas* canvas, uint32_t* count);
void lovrCanvasSetAttachments(Canvas* canvas, Attachment* attachments, uint32_t count);
void lovrCanvasResolve(Canvas* canvas);
bool lovrCanvasIsStereo(Canvas* canvas);
void lovrCanvasSetStereo(Canvas* canvas, bool stereo);
uint32_t lovrCanvasGetWidth(Canvas* canvas);
uint32_t lovrCanvasGetHeight(Canvas* canvas);
void lovrCanvasSetWidth(Canvas* canvas, uint32_t width);
void lovrCanvasSetHeight(Canvas* canvas, uint32_t height);
uint32_t lovrCanvasGetMSAA(Canvas* canvas);
struct Texture* lovrCanvasGetDepthTexture(Canvas* canvas);
struct TextureData* lovrCanvasNewTextureData(Canvas* canvas, uint32_t index);

View File

@ -168,8 +168,8 @@ static void onCloseWindow(void) {
static void onResizeWindow(int width, int height) {
state.width = width;
state.height = height;
state.defaultCanvas->width = width;
state.defaultCanvas->height = height;
lovrCanvasSetWidth(state.defaultCanvas, width);
lovrCanvasSetHeight(state.defaultCanvas, height);
}
static void* lovrGraphicsMapBuffer(StreamType type, uint32_t count) {
@ -303,13 +303,13 @@ void lovrGraphicsSetCamera(Camera* camera, bool clear) {
mat4_perspective(state.camera.projection[0], .01f, 100.f, 67.f * (float) M_PI / 180.f, (float) state.width / state.height);
mat4_perspective(state.camera.projection[1], .01f, 100.f, 67.f * (float) M_PI / 180.f, (float) state.width / state.height);
state.camera.canvas = state.defaultCanvas;
state.camera.canvas->flags.stereo = false;
lovrCanvasSetStereo(state.camera.canvas, false);
} else {
state.camera = *camera;
if (!state.camera.canvas) {
state.camera.canvas = state.defaultCanvas;
state.camera.canvas->flags.stereo = camera->stereo;
lovrCanvasSetStereo(state.camera.canvas, camera->stereo);
}
}

View File

@ -65,6 +65,21 @@ struct Texture {
uint8_t incoherent;
};
struct Canvas {
uint32_t framebuffer;
uint32_t resolveBuffer;
uint32_t depthBuffer;
uint32_t width;
uint32_t height;
CanvasFlags flags;
Attachment attachments[MAX_CANVAS_ATTACHMENTS];
Attachment depth;
uint32_t attachmentCount;
bool needsAttach;
bool needsResolve;
bool immortal;
};
typedef enum {
BARRIER_BLOCK,
BARRIER_UNIFORM_TEXTURE,
@ -1765,7 +1780,8 @@ void lovrTextureSetWrap(Texture* texture, TextureWrap wrap) {
// Canvas
Canvas* lovrCanvasInit(Canvas* canvas, uint32_t width, uint32_t height, CanvasFlags flags) {
Canvas* lovrCanvasCreate(uint32_t width, uint32_t height, CanvasFlags flags) {
Canvas* canvas = lovrAlloc(Canvas);
if (flags.stereo && state.singlepass != MULTIVIEW) {
width *= 2;
}
@ -1809,7 +1825,8 @@ Canvas* lovrCanvasInit(Canvas* canvas, uint32_t width, uint32_t height, CanvasFl
return canvas;
}
Canvas* lovrCanvasInitFromHandle(Canvas* canvas, uint32_t width, uint32_t height, CanvasFlags flags, uint32_t framebuffer, uint32_t depthBuffer, uint32_t resolveBuffer, uint32_t attachmentCount, bool immortal) {
Canvas* lovrCanvasCreateFromHandle(uint32_t width, uint32_t height, CanvasFlags flags, uint32_t framebuffer, uint32_t depthBuffer, uint32_t resolveBuffer, uint32_t attachmentCount, bool immortal) {
Canvas* canvas = lovrAlloc(Canvas);
canvas->framebuffer = framebuffer;
canvas->depthBuffer = depthBuffer;
canvas->resolveBuffer = resolveBuffer;
@ -1904,6 +1921,81 @@ TextureData* lovrCanvasNewTextureData(Canvas* canvas, uint32_t index) {
return textureData;
}
const Attachment* lovrCanvasGetAttachments(Canvas* canvas, uint32_t* count) {
if (count) *count = canvas->attachmentCount;
return canvas->attachments;
}
void lovrCanvasSetAttachments(Canvas* canvas, Attachment* attachments, uint32_t count) {
lovrAssert(count > 0, "A Canvas must have at least one attached Texture");
lovrAssert(count <= MAX_CANVAS_ATTACHMENTS, "Only %d textures can be attached to a Canvas, got %d\n", MAX_CANVAS_ATTACHMENTS, count);
if (!canvas->needsAttach && count == canvas->attachmentCount && !memcmp(canvas->attachments, attachments, count * sizeof(Attachment))) {
return;
}
lovrGraphicsFlushCanvas(canvas);
for (uint32_t i = 0; i < count; i++) {
Texture* texture = attachments[i].texture;
uint32_t slice = attachments[i].slice;
uint32_t level = attachments[i].level;
uint32_t width = lovrTextureGetWidth(texture, level);
uint32_t height = lovrTextureGetHeight(texture, level);
uint32_t depth = lovrTextureGetDepth(texture, level);
uint32_t mipmaps = lovrTextureGetMipmapCount(texture);
bool hasDepthBuffer = canvas->flags.depth.enabled;
lovrAssert(slice < depth, "Invalid attachment slice (Texture has %d, got %d)", depth, slice + 1);
lovrAssert(level < mipmaps, "Invalid attachment mipmap level (Texture has %d, got %d)", mipmaps, level + 1);
lovrAssert(!hasDepthBuffer || width == canvas->width, "Texture width of %d does not match Canvas width (%d)", width, canvas->width);
lovrAssert(!hasDepthBuffer || height == canvas->height, "Texture height of %d does not match Canvas height (%d)", height, canvas->height);
#ifndef __ANDROID__ // On multiview canvases, the multisample settings can be different
lovrAssert(lovrTextureGetMSAA(texture) == canvas->flags.msaa, "Texture MSAA does not match Canvas MSAA");
#endif
lovrRetain(texture);
}
for (uint32_t i = 0; i < canvas->attachmentCount; i++) {
lovrRelease(Texture, canvas->attachments[i].texture);
}
memcpy(canvas->attachments, attachments, count * sizeof(Attachment));
canvas->attachmentCount = count;
canvas->needsAttach = true;
}
bool lovrCanvasIsStereo(Canvas* canvas) {
return canvas->flags.stereo;
}
void lovrCanvasSetStereo(Canvas* canvas, bool stereo) {
canvas->flags.stereo = stereo;
}
uint32_t lovrCanvasGetWidth(Canvas* canvas) {
return canvas->width;
}
uint32_t lovrCanvasGetHeight(Canvas* canvas) {
return canvas->height;
}
void lovrCanvasSetWidth(Canvas* canvas, uint32_t width) {
canvas->width = width;
}
void lovrCanvasSetHeight(Canvas* canvas, uint32_t height) {
canvas->height = height;
}
uint32_t lovrCanvasGetMSAA(Canvas* canvas) {
return canvas->flags.msaa;
}
Texture* lovrCanvasGetDepthTexture(Canvas* canvas) {
return canvas->depth.texture;
}
// Buffer
Buffer* lovrBufferCreate(size_t size, void* data, BufferType type, BufferUsage usage, bool readable) {

View File

@ -11,12 +11,6 @@
#pragma once
#define GPU_CANVAS_FIELDS \
bool immortal; \
uint32_t framebuffer; \
uint32_t resolveBuffer; \
uint32_t depthBuffer;
#define GPU_MESH_FIELDS \
uint32_t vao; \
uint32_t ibo;