1
0
mirror of https://github.com/TomHarte/CLK.git synced 2026-03-13 19:16:40 +00:00

Use a Texture.

This commit is contained in:
Thomas Harte
2026-01-30 22:22:52 -05:00
parent 93a0e42921
commit 85e190835f
4 changed files with 99 additions and 75 deletions

View File

@@ -10,7 +10,30 @@
using namespace Outputs::Display::OpenGL;
namespace {
constexpr GLint internal_format_for_depth(const std::size_t depth) {
switch(depth) {
default: return GL_FALSE;
case 1: return GL_R8UI;
case 2: return GL_RG8UI;
case 3: return GL_RGB8UI;
case 4: return GL_RGBA8UI;
}
}
constexpr GLenum format_for_depth(const std::size_t depth) {
switch(depth) {
default: return GL_FALSE;
case 1: return GL_RED_INTEGER;
case 2: return GL_RG_INTEGER;
case 3: return GL_RGB_INTEGER;
case 4: return GL_RGBA_INTEGER;
}
}
}
Texture::Texture(
const size_t channels,
const GLenum texture_unit,
const GLint mag_filter,
const GLint min_filter,
@@ -29,11 +52,11 @@ Texture::Texture(
glTexImage2D,
GL_TEXTURE_2D,
0,
GL_RGBA,
internal_format_for_depth(channels),
GLsizei(width_),
GLsizei(height_),
0,
GL_RGBA,
format_for_depth(channels),
GL_UNSIGNED_BYTE,
nullptr
);

View File

@@ -15,12 +15,19 @@ namespace Outputs::Display::OpenGL {
/*!
Holds a texture of size @c width and @c height, which is bound to @c texture_unit.
Textures are always four-channel with byte values per channel. Both clamp directions are set to `GL_CLAMP_TO_EDGE`.
The magnification and minification filters as specified are attached.
Textures are always a single byte per channel. Both clamp directions are set to `GL_CLAMP_TO_EDGE`.
The magnification and minification filters are as specified.
*/
class Texture {
public:
Texture(GLenum texture_unit, GLint mag_filter, GLint min_filter, GLsizei width, GLsizei height);
Texture(
size_t channels,
GLenum texture_unit,
GLint mag_filter,
GLint min_filter,
GLsizei width,
GLsizei height
);
~Texture();
Texture() = default;
@@ -35,6 +42,10 @@ public:
*/
void bind();
bool empty() const {
return texture_ == 0;
}
private:
GLenum texture_unit_ = GL_TEXTURE0;
GLuint texture_ = 0;

View File

@@ -99,8 +99,6 @@ ScanTarget::ScanTarget(const API api, const GLuint target_framebuffer, const flo
// and specify GL_MAP_PERSISTENT_BIT. Then map the buffer now, and let the client
// write straight into it.
test_gl(glGenTextures, 1, &write_area_texture_name_);
test_gl(glBlendFunc, GL_SRC_ALPHA, GL_CONSTANT_COLOR);
test_gl(glBlendColor, 0.4f, 0.4f, 0.4f, 1.0f);
@@ -109,53 +107,52 @@ ScanTarget::ScanTarget(const API api, const GLuint target_framebuffer, const flo
// TEST CODE. NOCOMMIT.
const auto buffer_width = FilterGenerator::SuggestedBufferWidth;
const float sample_multiplier =
FilterGenerator::suggested_sample_multiplier(227.5f, 1320);
VertexArray va(scan_buffer_);
for(auto &pair: {
std::make_pair(InputDataType::Luminance1, DisplayType::CompositeColour),
std::make_pair(InputDataType::Luminance8, DisplayType::CompositeColour),
std::make_pair(InputDataType::PhaseLinkedLuminance8, DisplayType::CompositeColour),
std::make_pair(InputDataType::Luminance8Phase8, DisplayType::SVideo),
std::make_pair(InputDataType::Luminance8Phase8, DisplayType::CompositeColour),
std::make_pair(InputDataType::Red1Green1Blue1, DisplayType::RGB),
std::make_pair(InputDataType::Red1Green1Blue1, DisplayType::SVideo),
std::make_pair(InputDataType::Red1Green1Blue1, DisplayType::CompositeColour),
std::make_pair(InputDataType::Red2Green2Blue2, DisplayType::RGB),
std::make_pair(InputDataType::Red2Green2Blue2, DisplayType::SVideo),
std::make_pair(InputDataType::Red2Green2Blue2, DisplayType::CompositeColour),
std::make_pair(InputDataType::Red4Green4Blue4, DisplayType::RGB),
std::make_pair(InputDataType::Red4Green4Blue4, DisplayType::SVideo),
std::make_pair(InputDataType::Red4Green4Blue4, DisplayType::CompositeColour),
std::make_pair(InputDataType::Red8Green8Blue8, DisplayType::RGB),
std::make_pair(InputDataType::Red8Green8Blue8, DisplayType::SVideo),
std::make_pair(InputDataType::Red8Green8Blue8, DisplayType::CompositeColour),
}) {
OpenGL::composition_shader(
api,
pair.first,
pair.second,
ColourSpace::YIQ,
sample_multiplier,
BufferingScanTarget::WriteAreaWidth, BufferingScanTarget::WriteAreaHeight,
buffer_width, 2048, // TODO: substitute real composition buffer sizes.
va,
GL_TEXTURE0
).bind();
}
// const auto buffer_width = FilterGenerator::SuggestedBufferWidth;
// const float sample_multiplier =
// FilterGenerator::suggested_sample_multiplier(227.5f, 1320);
//
// VertexArray va(scan_buffer_);
// for(auto &pair: {
// std::make_pair(InputDataType::Luminance1, DisplayType::CompositeColour),
// std::make_pair(InputDataType::Luminance8, DisplayType::CompositeColour),
// std::make_pair(InputDataType::PhaseLinkedLuminance8, DisplayType::CompositeColour),
//
// std::make_pair(InputDataType::Luminance8Phase8, DisplayType::SVideo),
// std::make_pair(InputDataType::Luminance8Phase8, DisplayType::CompositeColour),
//
// std::make_pair(InputDataType::Red1Green1Blue1, DisplayType::RGB),
// std::make_pair(InputDataType::Red1Green1Blue1, DisplayType::SVideo),
// std::make_pair(InputDataType::Red1Green1Blue1, DisplayType::CompositeColour),
//
// std::make_pair(InputDataType::Red2Green2Blue2, DisplayType::RGB),
// std::make_pair(InputDataType::Red2Green2Blue2, DisplayType::SVideo),
// std::make_pair(InputDataType::Red2Green2Blue2, DisplayType::CompositeColour),
//
// std::make_pair(InputDataType::Red4Green4Blue4, DisplayType::RGB),
// std::make_pair(InputDataType::Red4Green4Blue4, DisplayType::SVideo),
// std::make_pair(InputDataType::Red4Green4Blue4, DisplayType::CompositeColour),
//
// std::make_pair(InputDataType::Red8Green8Blue8, DisplayType::RGB),
// std::make_pair(InputDataType::Red8Green8Blue8, DisplayType::SVideo),
// std::make_pair(InputDataType::Red8Green8Blue8, DisplayType::CompositeColour),
// }) {
// OpenGL::composition_shader(
// api,
// pair.first,
// pair.second,
// ColourSpace::YIQ,
// sample_multiplier,
// BufferingScanTarget::WriteAreaWidth, BufferingScanTarget::WriteAreaHeight,
// buffer_width, 2048, // TODO: substitute real composition buffer sizes.
// va,
// GL_TEXTURE0
// ).bind();
// }
}
ScanTarget::~ScanTarget() {
perform([&] {
glDeleteBuffers(1, &scan_buffer_name_);
glDeleteTextures(1, &write_area_texture_name_);
glDeleteVertexArrays(1, &scan_vertex_array_);
});
}
@@ -352,28 +349,19 @@ void ScanTarget::update(int, int output_height) {
// Submit texture.
if(area.start.write_area_x != area.end.write_area_x || area.start.write_area_y != area.end.write_area_y) {
test_gl(glActiveTexture, SourceDataTextureUnit);
test_gl(glBindTexture, GL_TEXTURE_2D, write_area_texture_name_);
// Create storage for the texture if it doesn't yet exist; this was deferred until here
// because the pixel format wasn't initially known.
if(!texture_exists_) {
test_gl(glTexParameteri, GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
test_gl(glTexParameteri, GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
test_gl(glTexParameteri, GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
test_gl(glTexParameteri, GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
test_gl(glTexImage2D,
GL_TEXTURE_2D,
0,
internalFormatForDepth(write_area_data_size()),
if(source_texture_.empty()) {
source_texture_ = Texture(
write_area_data_size(),
SourceDataTextureUnit,
GL_NEAREST,
GL_NEAREST,
WriteAreaWidth,
WriteAreaHeight,
0,
formatForDepth(write_area_data_size()),
GL_UNSIGNED_BYTE,
nullptr);
texture_exists_ = true;
WriteAreaHeight
);
}
source_texture_.bind();
if(area.end.write_area_y >= area.start.write_area_y) {
// Submit the direct region from the submit pointer to the read pointer.

View File

@@ -15,6 +15,7 @@
#include "API.hpp"
#include "OpenGL.hpp"
#include "Primitives/Rectangle.hpp"
#include "Primitives/Texture.hpp"
#include "Primitives/TextureTarget.hpp"
#include "Primitives/VertexArray.hpp"
@@ -94,9 +95,6 @@ private:
GLuint scan_buffer_name_ = 0, scan_vertex_array_ = 0;
GLuint line_buffer_name_ = 0, line_vertex_array_ = 0;
GLuint write_area_texture_name_ = 0;
bool texture_exists_ = false;
// Receives scan target modals.
std::optional<ScanTarget::Modals> existing_modals_;
void setup_pipeline();
@@ -122,11 +120,6 @@ private:
std::unique_ptr<Shader> output_shader_;
std::unique_ptr<Shader> qam_separation_shader_;
VertexArray scans_;
TextureTarget composition_buffer_;
Shader composition_shader_;
Shader copy_shader_;
/*!
Produces a shader that composes fragment of the input stream to a single buffer,
normalising the data into one of four forms: RGB, 8-bit luminance,
@@ -160,6 +153,15 @@ private:
std::array<Scan, LineBufferHeight*5> scan_buffer_;
std::array<Line, LineBufferHeight> line_buffer_;
std::array<LineMetadata, LineBufferHeight> line_metadata_buffer_;
//
// NEW PIPELINE. Starts here.
//
Texture source_texture_;
VertexArray scans_;
TextureTarget composition_buffer_;
Shader composition_shader_;
Shader copy_shader_;
};
}