mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-01-03 23:30:02 +01:00
252 lines
6.7 KiB
C++
252 lines
6.7 KiB
C++
#pragma once
|
|
|
|
#include "common.h"
|
|
#include "image.h"
|
|
#include "pixel_settings.hpp"
|
|
|
|
#include "Utilities/geometry.h"
|
|
|
|
namespace gl
|
|
{
|
|
enum class buffers
|
|
{
|
|
none = 0,
|
|
color = GL_COLOR_BUFFER_BIT,
|
|
depth = GL_DEPTH_BUFFER_BIT,
|
|
stencil = GL_STENCIL_BUFFER_BIT,
|
|
|
|
color_depth = color | depth,
|
|
color_depth_stencil = color | depth | stencil,
|
|
color_stencil = color | stencil,
|
|
|
|
depth_stencil = depth | stencil
|
|
};
|
|
|
|
enum class indices_type
|
|
{
|
|
ubyte = GL_UNSIGNED_BYTE,
|
|
ushort = GL_UNSIGNED_SHORT,
|
|
uint = GL_UNSIGNED_INT
|
|
};
|
|
|
|
class vao;
|
|
|
|
class fbo
|
|
{
|
|
GLuint m_id = GL_NONE;
|
|
size2i m_size;
|
|
|
|
protected:
|
|
std::unordered_map<GLenum, GLuint> m_resource_bindings;
|
|
|
|
public:
|
|
fbo() = default;
|
|
|
|
fbo(GLuint id)
|
|
{
|
|
set_id(id);
|
|
}
|
|
|
|
~fbo()
|
|
{
|
|
if (created())
|
|
remove();
|
|
}
|
|
|
|
class save_binding_state
|
|
{
|
|
GLint m_last_binding;
|
|
bool reset = true;
|
|
|
|
public:
|
|
save_binding_state(const fbo& new_binding)
|
|
{
|
|
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &m_last_binding);
|
|
|
|
if (m_last_binding + 0u != new_binding.id())
|
|
new_binding.bind();
|
|
else
|
|
reset = false;
|
|
}
|
|
|
|
~save_binding_state()
|
|
{
|
|
if (reset)
|
|
glBindFramebuffer(GL_FRAMEBUFFER, m_last_binding);
|
|
}
|
|
};
|
|
|
|
class attachment
|
|
{
|
|
public:
|
|
enum class type
|
|
{
|
|
color = GL_COLOR_ATTACHMENT0,
|
|
depth = GL_DEPTH_ATTACHMENT,
|
|
stencil = GL_STENCIL_ATTACHMENT,
|
|
depth_stencil = GL_DEPTH_STENCIL_ATTACHMENT
|
|
};
|
|
|
|
protected:
|
|
GLuint m_id = GL_NONE;
|
|
fbo& m_parent;
|
|
|
|
attachment(fbo& parent)
|
|
: m_parent(parent)
|
|
{}
|
|
|
|
public:
|
|
attachment(fbo& parent, type type)
|
|
: m_id(static_cast<int>(type))
|
|
, m_parent(parent)
|
|
{
|
|
}
|
|
|
|
void set_id(uint id)
|
|
{
|
|
m_id = id;
|
|
}
|
|
|
|
uint id() const
|
|
{
|
|
return m_id;
|
|
}
|
|
|
|
GLuint resource_id() const
|
|
{
|
|
const auto found = m_parent.m_resource_bindings.find(m_id);
|
|
if (found != m_parent.m_resource_bindings.end())
|
|
{
|
|
return found->second;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void operator = (const texture& rhs)
|
|
{
|
|
ensure(rhs.get_target() == texture::target::texture2D ||
|
|
rhs.get_target() == texture::target::texture2DMS);
|
|
|
|
m_parent.m_resource_bindings[m_id] = rhs.id();
|
|
DSA_CALL2(NamedFramebufferTexture, m_parent.id(), m_id, rhs.id(), 0);
|
|
}
|
|
|
|
void operator = (const GLuint rhs)
|
|
{
|
|
m_parent.m_resource_bindings[m_id] = rhs;
|
|
DSA_CALL2(NamedFramebufferTexture, m_parent.id(), m_id, rhs, 0);
|
|
}
|
|
};
|
|
|
|
class indexed_attachment : public attachment
|
|
{
|
|
public:
|
|
indexed_attachment(fbo& parent, type type) : attachment(parent, type)
|
|
{
|
|
}
|
|
|
|
attachment operator[](int index) const
|
|
{
|
|
return{ m_parent, type(id() + index) };
|
|
}
|
|
|
|
std::vector<attachment> range(int from, int count) const
|
|
{
|
|
std::vector<attachment> result;
|
|
|
|
for (int i = from; i < from + count; ++i)
|
|
result.push_back((*this)[i]);
|
|
|
|
return result;
|
|
}
|
|
|
|
using attachment::operator =;
|
|
};
|
|
|
|
struct null_attachment : public attachment
|
|
{
|
|
null_attachment(fbo& parent)
|
|
: attachment(parent)
|
|
{}
|
|
};
|
|
|
|
indexed_attachment color{ *this, attachment::type::color };
|
|
attachment depth{ *this, attachment::type::depth };
|
|
attachment stencil{ *this, attachment::type::stencil };
|
|
attachment depth_stencil{ *this, attachment::type::depth_stencil };
|
|
null_attachment no_color{ *this };
|
|
|
|
enum class target
|
|
{
|
|
read_frame_buffer = GL_READ_FRAMEBUFFER,
|
|
draw_frame_buffer = GL_DRAW_FRAMEBUFFER
|
|
};
|
|
|
|
enum class swapchain_buffer
|
|
{
|
|
back = GL_BACK,
|
|
front = GL_FRONT
|
|
};
|
|
|
|
void create();
|
|
void bind() const;
|
|
void blit(const fbo& dst, areai src_area, areai dst_area, buffers buffers_ = buffers::color, filter filter_ = filter::nearest) const;
|
|
void bind_as(target target_) const;
|
|
void remove();
|
|
bool created() const;
|
|
bool check() const;
|
|
|
|
void recreate();
|
|
void draw_buffer(const attachment& buffer) const;
|
|
void draw_buffer(swapchain_buffer buffer) const;
|
|
void draw_buffers(const std::initializer_list<attachment>& indexes) const;
|
|
|
|
void read_buffer(const attachment& buffer) const;
|
|
void read_buffer(swapchain_buffer buffer) const;
|
|
|
|
void draw_arrays(GLenum mode, GLsizei count, GLint first = 0) const;
|
|
void draw_arrays(const buffer& buffer, GLenum mode, GLsizei count, GLint first = 0) const;
|
|
void draw_arrays(const vao& buffer, GLenum mode, GLsizei count, GLint first = 0) const;
|
|
|
|
void draw_elements(GLenum mode, GLsizei count, indices_type type, const GLvoid* indices) const;
|
|
void draw_elements(const buffer& buffer, GLenum mode, GLsizei count, indices_type type, const GLvoid* indices) const;
|
|
void draw_elements(GLenum mode, GLsizei count, indices_type type, const buffer& indices, usz indices_buffer_offset = 0) const;
|
|
void draw_elements(const buffer& buffer_, GLenum mode, GLsizei count, indices_type type, const buffer& indices, usz indices_buffer_offset = 0) const;
|
|
void draw_elements(GLenum mode, GLsizei count, const GLubyte* indices) const;
|
|
void draw_elements(const buffer& buffer, GLenum mode, GLsizei count, const GLubyte* indices) const;
|
|
void draw_elements(GLenum mode, GLsizei count, const GLushort* indices) const;
|
|
void draw_elements(const buffer& buffer, GLenum mode, GLsizei count, const GLushort* indices) const;
|
|
void draw_elements(GLenum mode, GLsizei count, const GLuint* indices) const;
|
|
void draw_elements(const buffer& buffer, GLenum mode, GLsizei count, const GLuint* indices) const;
|
|
|
|
void clear(buffers buffers_) const;
|
|
|
|
void copy_from(const void* pixels, const sizei& size, gl::texture::format format_, gl::texture::type type_, class pixel_unpack_settings pixel_settings = pixel_unpack_settings()) const;
|
|
void copy_from(const buffer& buf, const sizei& size, gl::texture::format format_, gl::texture::type type_, class pixel_unpack_settings pixel_settings = pixel_unpack_settings()) const;
|
|
|
|
void copy_to(void* pixels, coordi coord, gl::texture::format format_, gl::texture::type type_, class pixel_pack_settings pixel_settings = pixel_pack_settings()) const;
|
|
void copy_to(const buffer& buf, coordi coord, gl::texture::format format_, gl::texture::type type_, class pixel_pack_settings pixel_settings = pixel_pack_settings()) const;
|
|
|
|
static fbo get_bound_draw_buffer();
|
|
static fbo get_bound_read_buffer();
|
|
static fbo get_bound_buffer();
|
|
|
|
GLuint id() const;
|
|
void set_id(GLuint id);
|
|
|
|
void set_extents(const size2i& extents);
|
|
size2i get_extents() const;
|
|
|
|
bool matches(const std::array<GLuint, 4>& color_targets, GLuint depth_stencil_target) const;
|
|
bool references_any(const std::vector<GLuint>& resources) const;
|
|
|
|
explicit operator bool() const
|
|
{
|
|
return created();
|
|
}
|
|
};
|
|
|
|
extern const fbo screen;
|
|
}
|