mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 03:44:02 +02:00
Creating the Framebuffer class and the companion Swapbuffer
This commit is contained in:
parent
4ad5a6c138
commit
69484ad00b
3 changed files with 463 additions and 0 deletions
|
@ -34,6 +34,7 @@ typedef glm::mat3 Mat3;
|
|||
typedef glm::vec4 Vec4;
|
||||
typedef glm::vec3 Vec3;
|
||||
typedef glm::vec2 Vec2;
|
||||
typedef glm::ivec2 Vec2i;
|
||||
|
||||
// Description of a scalar type
|
||||
enum Type {
|
||||
|
|
267
libraries/gpu/src/gpu/Framebuffer.cpp
Executable file
267
libraries/gpu/src/gpu/Framebuffer.cpp
Executable file
|
@ -0,0 +1,267 @@
|
|||
//
|
||||
// Framebuffer.cpp
|
||||
// libraries/gpu/src/gpu
|
||||
//
|
||||
// Created by Sam Gateau on 4/12/2015.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "Framebuffer.h"
|
||||
#include <math.h>
|
||||
#include <QDebug>
|
||||
|
||||
using namespace gpu;
|
||||
|
||||
Framebuffer::Framebuffer()
|
||||
{
|
||||
}
|
||||
|
||||
Framebuffer::~Framebuffer()
|
||||
{
|
||||
}
|
||||
|
||||
Framebuffer* Framebuffer::create() {
|
||||
auto framebuffer = new Framebuffer();
|
||||
framebuffer->_renderBuffers.resize(MAX_NUM_RENDER_BUFFERS);
|
||||
framebuffer->_renderBuffersSubresource.resize(MAX_NUM_RENDER_BUFFERS, 0);
|
||||
return framebuffer;
|
||||
}
|
||||
|
||||
Framebuffer* Framebuffer::create( const Format& colorBufferFormat, const Format& depthStencilBufferFormat, uint16 width, uint16 height, uint16 numSamples) {
|
||||
auto framebuffer = Framebuffer::create();
|
||||
|
||||
auto colorTexture = TexturePointer(Texture::create2D(colorBufferFormat, width, height));
|
||||
auto depthTexture = TexturePointer(Texture::create2D(depthStencilBufferFormat, width, height));
|
||||
|
||||
framebuffer->setRenderBuffer(0, colorTexture);
|
||||
framebuffer->setDepthStencilBuffer(depthTexture);
|
||||
|
||||
return framebuffer;
|
||||
}
|
||||
|
||||
|
||||
bool Framebuffer::isSwapchain() const {
|
||||
return _swapchain != 0;
|
||||
}
|
||||
|
||||
uint32 Framebuffer::getFrameCount() const {
|
||||
if (_swapchain) {
|
||||
return _swapchain->getFrameCount();
|
||||
} else {
|
||||
return _frameCount;
|
||||
}
|
||||
}
|
||||
|
||||
bool Framebuffer::isEmpty() const {
|
||||
return (_buffersMask == 0);
|
||||
}
|
||||
|
||||
bool Framebuffer::validateTargetCompatibility(const Texture& texture, uint32 subresource) const {
|
||||
if (texture.getType() == Texture::TEX_1D) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isEmpty()) {
|
||||
return true;
|
||||
} else {
|
||||
if ((texture.getWidth() == getWidth()) &&
|
||||
(texture.getHeight() == getHeight()) &&
|
||||
(texture.getNumSamples() == getNumSamples())) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Framebuffer::updateSize(const TexturePointer& texture) {
|
||||
if (!isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (texture) {
|
||||
_width = texture->getWidth();
|
||||
_height = texture->getHeight();
|
||||
_numSamples = texture->getNumSamples();
|
||||
} else {
|
||||
_width = _height = _numSamples = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Framebuffer::resize(uint16 width, uint16 height, uint16 numSamples) {
|
||||
if (width && height && numSamples && !isEmpty() && !isSwapchain()) {
|
||||
if ((width != _width) || (height != _height) || (numSamples != _numSamples)) {
|
||||
for (uint32 i = 0; i < _renderBuffers.size(); ++i) {
|
||||
if (_renderBuffers[i]) {
|
||||
_renderBuffers[i]->resize2D(width, height, numSamples);
|
||||
_numSamples = _renderBuffers[i]->getNumSamples();
|
||||
}
|
||||
}
|
||||
|
||||
if (_depthStencilBuffer) {
|
||||
_depthStencilBuffer->resize2D(width, height, numSamples);
|
||||
_numSamples = _depthStencilBuffer->getNumSamples();
|
||||
}
|
||||
|
||||
_width = width;
|
||||
_height = height;
|
||||
// _numSamples = numSamples;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint16 Framebuffer::getWidth() const {
|
||||
if (isSwapchain()) {
|
||||
return getSwapchain()->getWidth();
|
||||
} else {
|
||||
return _width;
|
||||
}
|
||||
}
|
||||
|
||||
uint16 Framebuffer::getHeight() const {
|
||||
if (isSwapchain()) {
|
||||
return getSwapchain()->getHeight();
|
||||
} else {
|
||||
return _height;
|
||||
}
|
||||
}
|
||||
|
||||
uint16 Framebuffer::getNumSamples() const {
|
||||
if (isSwapchain()) {
|
||||
return getSwapchain()->getNumSamples();
|
||||
} else {
|
||||
return _numSamples;
|
||||
}
|
||||
}
|
||||
|
||||
// Render buffers
|
||||
int Framebuffer::setRenderBuffer(uint32 slot, const TexturePointer& texture, uint32 subresource) {
|
||||
if (isSwapchain()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Check for the slot
|
||||
if (slot >= getMaxNumRenderBuffers()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Check for the compatibility of size
|
||||
if (texture) {
|
||||
if (!validateTargetCompatibility(*texture, subresource)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// everything works, assign
|
||||
// dereference the previously used buffer if exists
|
||||
if (_renderBuffers[slot]) {
|
||||
_renderBuffers[slot].reset();
|
||||
_renderBuffersSubresource[slot] = 0;
|
||||
}
|
||||
|
||||
updateSize(texture);
|
||||
|
||||
// assign the new one
|
||||
_renderBuffers[slot] = texture;
|
||||
|
||||
// Assign the subresource
|
||||
_renderBuffersSubresource[slot] = subresource;
|
||||
|
||||
// update the mask
|
||||
int mask = (1<<slot);
|
||||
_buffersMask = (_buffersMask & ~(mask));
|
||||
if (texture) {
|
||||
_buffersMask |= mask;
|
||||
}
|
||||
|
||||
return slot;
|
||||
}
|
||||
|
||||
void Framebuffer::removeRenderBuffers() {
|
||||
if (isSwapchain()) {
|
||||
return;
|
||||
}
|
||||
|
||||
_buffersMask = _buffersMask & BUFFER_DEPTHSTENCIL;
|
||||
|
||||
for (auto renderBuffer : _renderBuffers) {
|
||||
renderBuffer.reset();
|
||||
}
|
||||
|
||||
updateSize(TexturePointer(nullptr));
|
||||
}
|
||||
|
||||
|
||||
uint32 Framebuffer::getNumRenderBuffers() const {
|
||||
uint32 nb = 0;
|
||||
for (auto i : _renderBuffers) {
|
||||
nb += (!i);
|
||||
}
|
||||
return nb;
|
||||
}
|
||||
|
||||
TexturePointer Framebuffer::getRenderBuffer(uint32 slot) const {
|
||||
if (!isSwapchain() && (slot < getMaxNumRenderBuffers())) {
|
||||
return _renderBuffers[slot];
|
||||
} else {
|
||||
return TexturePointer();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
uint32 Framebuffer::getRenderBufferSubresource(uint32 slot) const {
|
||||
if (!isSwapchain() && (slot < getMaxNumRenderBuffers())) {
|
||||
return _renderBuffersSubresource[slot];
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool Framebuffer::setDepthStencilBuffer(const TexturePointer& texture, uint32 subresource) {
|
||||
if (isSwapchain()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for the compatibility of size
|
||||
if (texture) {
|
||||
if (!validateTargetCompatibility(*texture)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Checks ok, assign
|
||||
_depthStencilBuffer.reset();
|
||||
_depthStencilBufferSubresource = 0;
|
||||
|
||||
updateSize(texture);
|
||||
|
||||
// assign the new one
|
||||
_depthStencilBuffer = texture;
|
||||
_depthStencilBufferSubresource = subresource;
|
||||
|
||||
_buffersMask = ( _buffersMask & ~BUFFER_DEPTHSTENCIL);
|
||||
if (texture) {
|
||||
_buffersMask |= BUFFER_DEPTHSTENCIL;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TexturePointer Framebuffer::getDepthStencilBuffer() const {
|
||||
if (isSwapchain()) {
|
||||
return TexturePointer();
|
||||
} else {
|
||||
return _depthStencilBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 Framebuffer::getDepthStencilBufferSubresource() const {
|
||||
if (isSwapchain()) {
|
||||
return 0;
|
||||
} else {
|
||||
return _depthStencilBufferSubresource;
|
||||
}
|
||||
}
|
195
libraries/gpu/src/gpu/Framebuffer.h
Executable file
195
libraries/gpu/src/gpu/Framebuffer.h
Executable file
|
@ -0,0 +1,195 @@
|
|||
//
|
||||
// Framebuffer.h
|
||||
// libraries/gpu/src/gpu
|
||||
//
|
||||
// Created by Sam Gateau on 4/12/2015.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
#ifndef hifi_gpu_Framebuffer_h
|
||||
#define hifi_gpu_Framebuffer_h
|
||||
|
||||
#include "Texture.h"
|
||||
#include <memory>
|
||||
|
||||
namespace gpu {
|
||||
|
||||
typedef Element Format;
|
||||
|
||||
class Viewport {
|
||||
public:
|
||||
int32 width = 1;
|
||||
int32 height = 1;
|
||||
int32 top = 0;
|
||||
int32 left = 0;
|
||||
float zmin = 0.f;
|
||||
float zmax = 1.f;
|
||||
|
||||
Viewport() {}
|
||||
Viewport(int32 w, int32 h, int32 t = 0, int32 l = 0, float zin = 0.f, float zax = 1.f):
|
||||
width(w),
|
||||
height(h),
|
||||
top(t),
|
||||
left(l),
|
||||
zmin(zin),
|
||||
zmax(zax)
|
||||
{}
|
||||
Viewport(const Vec2i& wh, const Vec2i& tl = Vec2i(0), const Vec2& zrange = Vec2(0.f, 1.f)):
|
||||
width(wh.x),
|
||||
height(wh.y),
|
||||
top(tl.x),
|
||||
left(tl.y),
|
||||
zmin(zrange.x),
|
||||
zmax(zrange.y)
|
||||
{}
|
||||
~Viewport() {}
|
||||
};
|
||||
|
||||
class Swapchain {
|
||||
public:
|
||||
// Properties
|
||||
uint16 getWidth() const { return _width; }
|
||||
uint16 getHeight() const { return _height; }
|
||||
uint16 getNumSamples() const { return _numSamples; }
|
||||
|
||||
bool hasDepthStencil() const { return _hasDepthStencil; }
|
||||
bool isFullscreen() const { return _isFullscreen; }
|
||||
|
||||
uint32 getSwapInterval() const { return _swapInterval; }
|
||||
|
||||
bool isStereo() const { return _isStereo; }
|
||||
|
||||
uint32 getFrameCount() const { return _frameCount; }
|
||||
|
||||
// Pure interface
|
||||
void setSwapInterval(uint32 interval);
|
||||
|
||||
void resize(uint16 width, uint16 height);
|
||||
void setFullscreen(bool fullscreen);
|
||||
|
||||
Swapchain() {}
|
||||
Swapchain(const Swapchain& swapchain) {}
|
||||
virtual ~Swapchain() {}
|
||||
|
||||
protected:
|
||||
mutable uint32 _frameCount = 0;
|
||||
|
||||
Format _colorFormat;
|
||||
uint16 _width = 1;
|
||||
uint16 _height = 1;
|
||||
uint16 _numSamples = 1;
|
||||
uint16 _swapInterval = 0;
|
||||
|
||||
bool _hasDepthStencil = false;
|
||||
bool _isFullscreen = false;
|
||||
bool _isStereo = false;
|
||||
|
||||
// Non exposed
|
||||
|
||||
friend class Framebuffer;
|
||||
};
|
||||
typedef std::shared_ptr<Swapchain> SwapchainPointer;
|
||||
|
||||
|
||||
class Framebuffer {
|
||||
public:
|
||||
enum BufferMask {
|
||||
BUFFER_COLOR0 = 1,
|
||||
BUFFER_COLOR1 = 2,
|
||||
BUFFER_COLOR2 = 4,
|
||||
BUFFER_COLOR3 = 8,
|
||||
BUFFER_COLOR4 = 16,
|
||||
BUFFER_COLOR5 = 32,
|
||||
BUFFER_COLOR6 = 64,
|
||||
BUFFER_COLOR7 = 128,
|
||||
BUFFER_COLORS = 0x000000FF,
|
||||
|
||||
BUFFER_DEPTH = 0x40000000,
|
||||
BUFFER_STENCIL = 0x80000000,
|
||||
BUFFER_DEPTHSTENCIL = 0xC0000000,
|
||||
};
|
||||
|
||||
~Framebuffer();
|
||||
|
||||
static Framebuffer* create(const SwapchainPointer& swapchain);
|
||||
static Framebuffer* create();
|
||||
static Framebuffer* create(const Format& colorBufferFormat, const Format& depthStencilBufferFormat, uint16 width, uint16 height, uint16 samples );
|
||||
|
||||
bool isSwapchain() const;
|
||||
SwapchainPointer getSwapchain() const { return _swapchain; }
|
||||
|
||||
uint32 getFrameCount() const;
|
||||
|
||||
// Render buffers
|
||||
int32 setRenderBuffer(uint32 slot, const TexturePointer& texture, uint32 subresource = 0);
|
||||
void removeRenderBuffers();
|
||||
uint32 getNumRenderBuffers() const;
|
||||
|
||||
TexturePointer getRenderBuffer(uint32 slot) const;
|
||||
uint32 getRenderBufferSubresource(uint32 slot) const;
|
||||
|
||||
bool setDepthStencilBuffer(const TexturePointer& texture, uint32 subresource = 0);
|
||||
TexturePointer getDepthStencilBuffer() const;
|
||||
uint32 getDepthStencilBufferSubresource() const;
|
||||
|
||||
// Properties
|
||||
uint32 getBuffersMask() const { return _buffersMask; }
|
||||
bool isEmpty() const;
|
||||
|
||||
bool validateTargetCompatibility(const Texture& texture, uint32 subresource = 0) const;
|
||||
|
||||
uint16 getWidth() const;
|
||||
uint16 getHeight() const;
|
||||
uint16 getNumSamples() const;
|
||||
|
||||
float getAspectRatio() const { return getWidth() / (float) getHeight() ; }
|
||||
|
||||
// If not a swapchain canvas, resize can resize all the render buffers and depth stencil attached in one call
|
||||
void resize( uint16 width, uint16 height, uint16 samples = 1 );
|
||||
|
||||
static const uint32 MAX_NUM_RENDER_BUFFERS = 8;
|
||||
static uint32 getMaxNumRenderBuffers() { return MAX_NUM_RENDER_BUFFERS; }
|
||||
|
||||
// Get viewport covering the ful Canvas
|
||||
Viewport getViewport() const { return Viewport(getWidth(), getHeight(), 0, 0); }
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
Viewport _viewport;
|
||||
|
||||
uint16 _width;
|
||||
uint16 _height;
|
||||
uint16 _numSamples;
|
||||
|
||||
uint32 _buffersMask;
|
||||
|
||||
uint32 _frameCount;
|
||||
|
||||
SwapchainPointer _swapchain;
|
||||
|
||||
Textures _renderBuffers;
|
||||
std::vector<uint32> _renderBuffersSubresource;
|
||||
|
||||
TexturePointer _depthStencilBuffer;
|
||||
uint32 _depthStencilBufferSubresource;
|
||||
|
||||
|
||||
void updateSize(const TexturePointer& texture);
|
||||
|
||||
// Non exposed
|
||||
Framebuffer(const Framebuffer& framebuffer) {}
|
||||
Framebuffer();
|
||||
|
||||
// This shouldn't be used by anything else than the Backend class with the proper casting.
|
||||
mutable GPUObject* _gpuObject = NULL;
|
||||
void setGPUObject(GPUObject* gpuObject) const { _gpuObject = gpuObject; }
|
||||
GPUObject* getGPUObject() const { return _gpuObject; }
|
||||
friend class Backend;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue