Route framebuffer texture copies through GL backend
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
#include "node_progress_bar.h"
|
||||
#include "paint_renderer/compositor.h"
|
||||
#include "renderer_gl/opengl_capabilities.h"
|
||||
#include "util.h"
|
||||
#include <thread>
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
@@ -564,8 +565,7 @@ glm::vec4 Canvas::stroke_draw_samples(
|
||||
glm::ivec2 tex_sz = glm::clamp(glm::ceil(bb_sz) + pad * 2.f, { 0, 0 }, (glm::vec2)(glm::ivec2(m_width, m_height) - tex_pos));
|
||||
if (copy_stroke_destination)
|
||||
{
|
||||
glCopyTexSubImage2D(texture_2d_target(), 0, tex_pos.x, tex_pos.y,
|
||||
tex_pos.x, tex_pos.y, tex_sz.x, tex_sz.y);
|
||||
copy_framebuffer_to_texture_2d(tex_pos.x, tex_pos.y, tex_pos.x, tex_pos.y, tex_sz.x, tex_sz.y);
|
||||
}
|
||||
|
||||
if (P.size() == 4)
|
||||
@@ -835,7 +835,7 @@ void Canvas::stroke_draw()
|
||||
glm::vec2 sz = glm::min(m_size, zw(b) + pad) - o;
|
||||
m_tex[i].bind();
|
||||
if (sz.x > 0 && sz.y > 0)
|
||||
glCopyTexSubImage2D(texture_2d_target(), 0, o.x, o.y, o.x, o.y, sz.x, sz.y);
|
||||
copy_framebuffer_to_texture_2d(o.x, o.y, o.x, o.y, sz.x, sz.y);
|
||||
}
|
||||
m_brush_shape.draw_fill();
|
||||
m_tmp[i].unbindFramebuffer();
|
||||
@@ -1050,7 +1050,7 @@ void Canvas::stroke_commit()
|
||||
// copy to tmp2 for layer blending
|
||||
set_active_texture_unit(0);
|
||||
m_tex2[i].bind();
|
||||
glCopyTexSubImage2D(texture_2d_target(), 0, 0, 0, 0, 0, m_width, m_height);
|
||||
copy_framebuffer_to_texture_2d(0, 0, 0, 0, m_width, m_height);
|
||||
m_tex2[i].unbind();
|
||||
|
||||
m_tmp[i].bindTexture();
|
||||
@@ -1161,7 +1161,7 @@ void Canvas::stroke_commit()
|
||||
ShaderManager::u_int(kShaderUniform::TexBG, 0);
|
||||
set_active_texture_unit(0);
|
||||
m_tex2[i].bind();
|
||||
glCopyTexSubImage2D(texture_2d_target(), 0, 0, 0, 0, 0, m_width, m_height);
|
||||
copy_framebuffer_to_texture_2d(0, 0, 0, 0, m_width, m_height);
|
||||
m_plane.draw_fill();
|
||||
|
||||
m_layers[m_current_layer_idx]->rtt(i).unbindFramebuffer();
|
||||
@@ -1390,7 +1390,7 @@ void Canvas::draw_merge(bool draw_checkerboard, std::array<bool, 6> faces /*= SI
|
||||
{
|
||||
set_active_texture_unit(2);
|
||||
m_merge_tex.bind();
|
||||
glCopyTexSubImage2D(texture_2d_target(), 0, 0, 0, 0, 0, m_width, m_height);
|
||||
copy_framebuffer_to_texture_2d(0, 0, 0, 0, m_width, m_height);
|
||||
}
|
||||
|
||||
m_plane.draw_fill();
|
||||
@@ -1407,7 +1407,7 @@ void Canvas::draw_merge(bool draw_checkerboard, std::array<bool, 6> faces /*= SI
|
||||
|
||||
set_active_texture_unit(2);
|
||||
m_merge_tex.bind();
|
||||
glCopyTexSubImage2D(texture_2d_target(), 0, 0, 0, 0, 0, m_width, m_height);
|
||||
copy_framebuffer_to_texture_2d(0, 0, 0, 0, m_width, m_height);
|
||||
|
||||
// draw the grid behind the layers using a temporary copy
|
||||
if (use_blend)
|
||||
@@ -1593,7 +1593,7 @@ void Canvas::layer_merge(int source_idx, int dest_idx) // m_layer index
|
||||
// copy to tmp2 for layer blending
|
||||
set_active_texture_unit(0);
|
||||
m_tex2[i].bind();
|
||||
glCopyTexSubImage2D(texture_2d_target(), 0, 0, 0, 0, 0, m_width, m_height);
|
||||
copy_framebuffer_to_texture_2d(0, 0, 0, 0, m_width, m_height);
|
||||
m_tex2[i].unbind();
|
||||
|
||||
m_sampler.bind(0);
|
||||
@@ -2920,7 +2920,7 @@ Image Canvas::thumbnail_generate(int w, int h)
|
||||
if (copy_layer_destination)
|
||||
{
|
||||
set_active_texture_unit(2);
|
||||
glCopyTexSubImage2D(texture_2d_target(), 0, 0, 0, 0, 0, w, h);
|
||||
copy_framebuffer_to_texture_2d(0, 0, 0, 0, w, h);
|
||||
}
|
||||
ShaderManager::u_int(kShaderUniform::BlendMode, m_layers[layer_index]->m_blend_mode);
|
||||
ShaderManager::u_float(kShaderUniform::Alpha, m_layers[layer_index]->m_opacity);
|
||||
@@ -2939,7 +2939,7 @@ Image Canvas::thumbnail_generate(int w, int h)
|
||||
set_active_texture_unit(0);
|
||||
blendtex.bind();
|
||||
// copy the content of the fb before drawing the grid
|
||||
glCopyTexSubImage2D(texture_2d_target(), 0, 0, 0, 0, 0, w, h);
|
||||
copy_framebuffer_to_texture_2d(0, 0, 0, 0, w, h);
|
||||
|
||||
// draw the grid
|
||||
ShaderManager::use(kShader::Checkerboard);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "app.h"
|
||||
#include "renderer_gl/opengl_capabilities.h"
|
||||
#include "rtt.h"
|
||||
#include "util.h"
|
||||
|
||||
uint32_t Layer::s_count = 0;
|
||||
|
||||
@@ -89,7 +90,7 @@ Texture2D Layer::gen_equirect(glm::ivec2 size /*= { 0, 0 }*/)
|
||||
Canvas::I->m_plane.draw_fill();
|
||||
|
||||
ret.bind();
|
||||
glCopyTexSubImage2D(pp::renderer::gl::texture_2d_target(), 0, 0, 0, 0, 0, latlong.getWidth(), latlong.getHeight());
|
||||
copy_framebuffer_to_texture_2d(0, 0, 0, 0, latlong.getWidth(), latlong.getHeight());
|
||||
|
||||
latlong.unbindFramebuffer();
|
||||
|
||||
|
||||
@@ -1252,9 +1252,13 @@ void CanvasModeTransform::enter(kCanvasMode prev)
|
||||
Canvas::I->m_layers[Canvas::I->m_current_layer_idx]->rtt(plane).bindFramebuffer();
|
||||
m_tex[plane].create(bb_sz.x, bb_sz.y);
|
||||
m_tex[plane].bind();
|
||||
glCopyTexSubImage2D(
|
||||
pp::renderer::gl::texture_2d_target(),
|
||||
0, 0, 0, bb_min.x, bb_min.y, bb_sz.x, bb_sz.y);
|
||||
copy_framebuffer_to_texture_2d(
|
||||
0,
|
||||
0,
|
||||
static_cast<int>(bb_min.x),
|
||||
static_cast<int>(bb_min.y),
|
||||
static_cast<int>(bb_sz.x),
|
||||
static_cast<int>(bb_sz.y));
|
||||
m_tex[plane].unbind();
|
||||
Canvas::I->m_layers[Canvas::I->m_current_layer_idx]->rtt(plane).unbindFramebuffer();
|
||||
});
|
||||
@@ -1433,9 +1437,13 @@ void CanvasModeTransform::leave(kCanvasMode next)
|
||||
// copy fb content to texture for blending
|
||||
set_active_texture_unit(0);
|
||||
Canvas::I->m_tex2[i].bind();
|
||||
glCopyTexSubImage2D(
|
||||
pp::renderer::gl::texture_2d_target(),
|
||||
0, bb_min.x, bb_min.y, bb_min.x, bb_min.y, bb_sz.x, bb_sz.y);
|
||||
copy_framebuffer_to_texture_2d(
|
||||
static_cast<int>(bb_min.x),
|
||||
static_cast<int>(bb_min.y),
|
||||
static_cast<int>(bb_min.x),
|
||||
static_cast<int>(bb_min.y),
|
||||
static_cast<int>(bb_sz.x),
|
||||
static_cast<int>(bb_sz.y));
|
||||
// slot for m_tex
|
||||
set_active_texture_unit(1);
|
||||
for (int j = 0; j < 6; j++)
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "paint_renderer/compositor.h"
|
||||
#include "settings.h"
|
||||
#include "renderer_gl/opengl_capabilities.h"
|
||||
#include "util.h"
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -523,8 +524,13 @@ void NodeCanvas::draw()
|
||||
{
|
||||
set_active_texture_unit(2);
|
||||
m_blender_bg.bind();
|
||||
glCopyTexSubImage2D(pp::renderer::gl::texture_2d_target(), 0, 0, 0, 0, 0,
|
||||
m_blender_bg.size().x, m_blender_bg.size().y);
|
||||
copy_framebuffer_to_texture_2d(
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
m_blender_bg.size().x,
|
||||
m_blender_bg.size().y);
|
||||
}
|
||||
|
||||
m_face_plane.draw_fill();
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "app.h"
|
||||
#include "paint_renderer/compositor.h"
|
||||
#include "renderer_gl/opengl_capabilities.h"
|
||||
#include "util.h"
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
|
||||
@@ -208,8 +209,7 @@ glm::vec4 NodeStrokePreview::stroke_draw_samples(
|
||||
if (copy_stroke_destination)
|
||||
{
|
||||
// this is also used by the mixer
|
||||
glCopyTexSubImage2D(pp::renderer::gl::texture_2d_target(), 0, tex_pos.x, tex_pos.y,
|
||||
tex_pos.x, tex_pos.y, tex_sz.x, tex_sz.y);
|
||||
copy_framebuffer_to_texture_2d(tex_pos.x, tex_pos.y, tex_pos.x, tex_pos.y, tex_sz.x, tex_sz.y);
|
||||
}
|
||||
|
||||
if (P.size() == 4)
|
||||
@@ -432,9 +432,7 @@ void NodeStrokePreview::draw_stroke_immediate()
|
||||
// copy raw stroke to tex
|
||||
glActiveTexture(pp::renderer::gl::active_texture_unit(1U));
|
||||
m_tex_dual.bind();
|
||||
glCopyTexSubImage2D(
|
||||
pp::renderer::gl::texture_2d_target(),
|
||||
0,
|
||||
copy_framebuffer_to_texture_2d(
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
@@ -453,9 +451,7 @@ void NodeStrokePreview::draw_stroke_immediate()
|
||||
m_plane.draw_fill();
|
||||
//m_rtt.clear({ .3f, .3f, .3f, 1.f });
|
||||
m_tex_background.bind();
|
||||
glCopyTexSubImage2D(
|
||||
pp::renderer::gl::texture_2d_target(),
|
||||
0,
|
||||
copy_framebuffer_to_texture_2d(
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
@@ -508,9 +504,7 @@ void NodeStrokePreview::draw_stroke_immediate()
|
||||
// copy raw stroke to tex
|
||||
glActiveTexture(pp::renderer::gl::active_texture_unit(1U));
|
||||
m_tex.bind();
|
||||
glCopyTexSubImage2D(
|
||||
pp::renderer::gl::texture_2d_target(),
|
||||
0,
|
||||
copy_framebuffer_to_texture_2d(
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
@@ -564,9 +558,7 @@ void NodeStrokePreview::draw_stroke_immediate()
|
||||
|
||||
// copy the result to the actual preview
|
||||
m_tex_preview.bind();
|
||||
glCopyTexSubImage2D(
|
||||
pp::renderer::gl::texture_2d_target(),
|
||||
0,
|
||||
copy_framebuffer_to_texture_2d(
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
|
||||
@@ -748,6 +748,36 @@ pp::foundation::Status update_opengl_texture_2d(
|
||||
return pp::foundation::Status::success();
|
||||
}
|
||||
|
||||
pp::foundation::Status copy_opengl_framebuffer_to_texture_2d(
|
||||
OpenGlTexture2DFramebufferCopy copy,
|
||||
OpenGlTexture2DFramebufferCopyDispatch dispatch) noexcept
|
||||
{
|
||||
if (dispatch.copy_tex_sub_image_2d == nullptr) {
|
||||
return pp::foundation::Status::invalid_argument(
|
||||
"OpenGL framebuffer-to-texture copy dispatch callback must not be null");
|
||||
}
|
||||
|
||||
if (copy.width < 0 || copy.height < 0) {
|
||||
return pp::foundation::Status::invalid_argument(
|
||||
"OpenGL framebuffer-to-texture copy dimensions are invalid");
|
||||
}
|
||||
|
||||
if (copy.width == 0 || copy.height == 0) {
|
||||
return pp::foundation::Status::success();
|
||||
}
|
||||
|
||||
dispatch.copy_tex_sub_image_2d(
|
||||
texture_2d_target(),
|
||||
copy.level,
|
||||
copy.destination_x,
|
||||
copy.destination_y,
|
||||
copy.source_x,
|
||||
copy.source_y,
|
||||
copy.width,
|
||||
copy.height);
|
||||
return pp::foundation::Status::success();
|
||||
}
|
||||
|
||||
pp::foundation::Status generate_opengl_texture_2d_mipmaps(
|
||||
std::uint32_t texture_id,
|
||||
OpenGlTexture2DMipmapDispatch dispatch) noexcept
|
||||
|
||||
@@ -149,6 +149,16 @@ struct OpenGlTexture2DUpdate {
|
||||
const void* data = nullptr;
|
||||
};
|
||||
|
||||
struct OpenGlTexture2DFramebufferCopy {
|
||||
std::int32_t level = 0;
|
||||
std::int32_t destination_x = 0;
|
||||
std::int32_t destination_y = 0;
|
||||
std::int32_t source_x = 0;
|
||||
std::int32_t source_y = 0;
|
||||
std::int32_t width = 0;
|
||||
std::int32_t height = 0;
|
||||
};
|
||||
|
||||
struct OpenGlTexture2DReadback {
|
||||
std::uint32_t texture_id = 0;
|
||||
std::int32_t width = 0;
|
||||
@@ -426,6 +436,15 @@ using OpenGlTexSubImage2DFn = void (*)(
|
||||
std::uint32_t pixel_format,
|
||||
std::uint32_t component_type,
|
||||
const void* data) noexcept;
|
||||
using OpenGlCopyTexSubImage2DFn = void (*)(
|
||||
std::uint32_t target,
|
||||
std::int32_t level,
|
||||
std::int32_t destination_x,
|
||||
std::int32_t destination_y,
|
||||
std::int32_t source_x,
|
||||
std::int32_t source_y,
|
||||
std::int32_t width,
|
||||
std::int32_t height) noexcept;
|
||||
using OpenGlGenerateMipmapFn = void (*)(std::uint32_t target) noexcept;
|
||||
using OpenGlFramebufferTexture2DFn = void (*)(
|
||||
std::uint32_t target,
|
||||
@@ -582,6 +601,10 @@ struct OpenGlTexture2DUpdateDispatch {
|
||||
OpenGlTexSubImage2DFn tex_sub_image_2d = nullptr;
|
||||
};
|
||||
|
||||
struct OpenGlTexture2DFramebufferCopyDispatch {
|
||||
OpenGlCopyTexSubImage2DFn copy_tex_sub_image_2d = nullptr;
|
||||
};
|
||||
|
||||
struct OpenGlTexture2DMipmapDispatch {
|
||||
OpenGlBindTextureFn bind_texture = nullptr;
|
||||
OpenGlGenerateMipmapFn generate_mipmap = nullptr;
|
||||
@@ -820,6 +843,9 @@ struct OpenGlMeshDeleteDispatch {
|
||||
[[nodiscard]] pp::foundation::Status update_opengl_texture_2d(
|
||||
OpenGlTexture2DUpdate update,
|
||||
OpenGlTexture2DUpdateDispatch dispatch) noexcept;
|
||||
[[nodiscard]] pp::foundation::Status copy_opengl_framebuffer_to_texture_2d(
|
||||
OpenGlTexture2DFramebufferCopy copy,
|
||||
OpenGlTexture2DFramebufferCopyDispatch dispatch) noexcept;
|
||||
[[nodiscard]] pp::foundation::Status generate_opengl_texture_2d_mipmaps(
|
||||
std::uint32_t texture_id,
|
||||
OpenGlTexture2DMipmapDispatch dispatch) noexcept;
|
||||
|
||||
50
src/util.cpp
50
src/util.cpp
@@ -67,6 +67,27 @@ void bind_opengl_sampler(std::uint32_t unit, std::uint32_t sampler) noexcept
|
||||
glBindSampler(static_cast<GLuint>(unit), static_cast<GLuint>(sampler));
|
||||
}
|
||||
|
||||
void copy_opengl_tex_sub_image_2d(
|
||||
std::uint32_t target,
|
||||
std::int32_t level,
|
||||
std::int32_t destination_x,
|
||||
std::int32_t destination_y,
|
||||
std::int32_t source_x,
|
||||
std::int32_t source_y,
|
||||
std::int32_t width,
|
||||
std::int32_t height) noexcept
|
||||
{
|
||||
glCopyTexSubImage2D(
|
||||
static_cast<GLenum>(target),
|
||||
static_cast<GLint>(level),
|
||||
static_cast<GLint>(destination_x),
|
||||
static_cast<GLint>(destination_y),
|
||||
static_cast<GLint>(source_x),
|
||||
static_cast<GLint>(source_y),
|
||||
static_cast<GLsizei>(width),
|
||||
static_cast<GLsizei>(height));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<>
|
||||
@@ -719,6 +740,35 @@ void check_OpenGLError(const char* stmt, const char* fname, int line)
|
||||
}
|
||||
}
|
||||
|
||||
bool copy_framebuffer_to_texture_2d(
|
||||
int destination_x,
|
||||
int destination_y,
|
||||
int source_x,
|
||||
int source_y,
|
||||
int width,
|
||||
int height,
|
||||
int level) noexcept
|
||||
{
|
||||
const auto status = pp::renderer::gl::copy_opengl_framebuffer_to_texture_2d(
|
||||
pp::renderer::gl::OpenGlTexture2DFramebufferCopy {
|
||||
.level = level,
|
||||
.destination_x = destination_x,
|
||||
.destination_y = destination_y,
|
||||
.source_x = source_x,
|
||||
.source_y = source_y,
|
||||
.width = width,
|
||||
.height = height,
|
||||
},
|
||||
pp::renderer::gl::OpenGlTexture2DFramebufferCopyDispatch {
|
||||
.copy_tex_sub_image_2d = copy_opengl_tex_sub_image_2d,
|
||||
});
|
||||
if (!status.ok()) {
|
||||
LOG("OpenGL framebuffer-to-texture copy failed: %s", status.message);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t curl_data_handler(void *contents, size_t size, size_t nmemb, void *userp)
|
||||
{
|
||||
auto buffer = reinterpret_cast<std::string*>(userp);
|
||||
|
||||
@@ -201,6 +201,14 @@ std::string str_replace(const std::string& string, const std::string& search, co
|
||||
size_t curl_data_handler(void *contents, size_t size, size_t nmemb, void *userp);
|
||||
size_t curl_data_write(void *ptr, size_t size, size_t nmemb, FILE *stream);
|
||||
void check_OpenGLError(const char* stmt, const char* fname, int line);
|
||||
bool copy_framebuffer_to_texture_2d(
|
||||
int destination_x,
|
||||
int destination_y,
|
||||
int source_x,
|
||||
int source_y,
|
||||
int width,
|
||||
int height,
|
||||
int level = 0) noexcept;
|
||||
inline glm::vec2 xy(const glm::vec4& v) { return glm::vec2(v.x, v.y); }
|
||||
inline glm::vec3 xyz(const glm::vec4& v) { return glm::vec3(v.x, v.y, v.z); }
|
||||
inline glm::vec2 zw(const glm::vec4& v) { return glm::vec2(v.z, v.w); }
|
||||
|
||||
Reference in New Issue
Block a user