1
0
mirror of https://github.com/TomHarte/CLK.git synced 2026-04-20 10:17:05 +00:00

Add some TODOs, make TextureTargets moveable.

This commit is contained in:
Thomas Harte
2026-01-30 10:38:52 -05:00
parent d31d53eb02
commit da0c99067d
5 changed files with 58 additions and 7 deletions
+14 -1
View File
@@ -17,11 +17,24 @@ namespace Outputs::Display::OpenGL {
/*!
Copies a source texture in its entirety to a destination, optionally applying
a change in brightness and a gamma adjustment.
This always copies the entirety of the source texture to the entirety of the
target surface; hence no inputs are required to the vertex program. Simply
issue a four-vertex triangle strip.
TODO: consider colour adaptations beyond mere brightness.
I want at least a 'tint' and am considering a full-on matrix application for any
combination of tint, brightness and channel remapping — e.g. imagine a
handheld console in which the native red pixels are some colour other than
pure red.
(would need support in the ScanTarget modals and therefore also a correlated
change in the other scan targets)
*/
Shader copy_shader(
API,
const GLenum source_texture_unit,
std::optional<float> brightness,
std::optional<float> brightness, // Optionally: multiply all input
std::optional<float> gamma
);
+23 -3
View File
@@ -8,6 +8,7 @@
#include "TextureTarget.hpp"
#include <algorithm>
#include <stdexcept>
using namespace Outputs::Display::OpenGL;
@@ -96,9 +97,27 @@ TextureTarget::TextureTarget(
TextureTarget::~TextureTarget() {
glDeleteFramebuffers(1, &framebuffer_);
glDeleteTextures(1, &texture_);
if(renderbuffer_) glDeleteRenderbuffers(1, &renderbuffer_);
if(drawing_vertex_array_) glDeleteVertexArrays(1, &drawing_vertex_array_);
if(drawing_array_buffer_) glDeleteBuffers(1, &drawing_array_buffer_);
glDeleteRenderbuffers(1, &renderbuffer_);
glDeleteVertexArrays(1, &drawing_vertex_array_);
glDeleteBuffers(1, &drawing_array_buffer_);
}
TextureTarget::TextureTarget(TextureTarget &&rhs) {
*this = std::move(rhs);
}
TextureTarget &TextureTarget::operator =(TextureTarget &&rhs) {
api_ = rhs.api_;
std::swap(framebuffer_, rhs.framebuffer_);
std::swap(texture_, rhs.texture_);
std::swap(renderbuffer_, rhs.renderbuffer_);
std::swap(width_, rhs.width_);
std::swap(height_, rhs.height_);
std::swap(texture_unit_, rhs.texture_unit_);
std::swap(texture_unit_, rhs.texture_unit_);
GLsizei expanded_width_ = 0, expanded_height_ = 0;
return *this;
}
void TextureTarget::bind_framebuffer() {
@@ -111,6 +130,7 @@ void TextureTarget::bind_texture() const {
test_gl(glBindTexture, GL_TEXTURE_2D, texture_);
}
// TODO: eliminate below, plus relevant local storage.
void TextureTarget::draw(const float aspect_ratio, const float colour_threshold) const {
if(!pixel_shader_) {
const char *const vertex_shader =
+7 -3
View File
@@ -37,6 +37,10 @@ public:
TextureTarget(API, GLsizei width, GLsizei height, GLenum texture_unit, GLint mag_filter, bool has_stencil_buffer);
~TextureTarget();
TextureTarget() = default;
TextureTarget(TextureTarget &&);
TextureTarget &operator =(TextureTarget &&);
/*!
Binds this target as a framebuffer and sets the @c glViewport accordingly.
*/
@@ -75,11 +79,11 @@ public:
void draw(float aspect_ratio, float colour_threshold = 0.0f) const;
private:
API api_;
API api_{};
GLuint framebuffer_ = 0, texture_ = 0, renderbuffer_ = 0;
const GLsizei width_ = 0, height_ = 0;
GLsizei width_ = 0, height_ = 0;
GLsizei expanded_width_ = 0, expanded_height_ = 0;
const GLenum texture_unit_ = 0;
GLenum texture_unit_ = 0;
mutable std::unique_ptr<Shader> pixel_shader_;
mutable GLuint drawing_vertex_array_ = 0, drawing_array_buffer_ = 0;
+3
View File
@@ -122,7 +122,10 @@ 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,
+11
View File
@@ -233,6 +233,17 @@ enum class InputDataType {
Red4Green4Blue4, // 2 bytes/pixel; low nibble in first byte is red, high nibble in second is green, low is blue.
// i.e. if it were a little endian word, 0xgb0r; or 0x0rgb big endian.
Red8Green8Blue8, // 4 bytes/pixel; first is red, second is green, third is blue, fourth is vacant.
// TODO, probably:
//
// TaggedRGBW8 — top two bits select a channel, either red, green or blue (and something else for the fourth
// option; white maybe?). Low six bits are an intensity. I'm imagining this is good for
// handheld systems with known subpixel layouts; the scan target can be fed with the subpixels.
// Correlated assumption: such systems are old enough that 6 bits of intensity is sufficient.
// If I decide to switch from 'brightness' as a final modal output property to a full-on
// matrix transform then the tag will stop meaning RGB literally and just pick a
// single channel, in which case 'white' makes sense as 'all channels'.
//
};
constexpr const char *name(const InputDataType data_type) {