From 3ab6585789f5d23eaa208446953883fec2efb48f Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 2 Aug 2015 14:25:21 -0400 Subject: [PATCH] Started making the format of data included in a CRTFrame less a matter of variously hard-coded magic constants. Which will allow me to separate the idea of an internal lateral position from the direct texture coordinate, avoiding precision sampling errors at the top and bottom. --- .../Mac/Clock Signal/CSCathodeRayView.m | 17 +++++-- Outputs/CRT.cpp | 48 +++++++++++-------- Outputs/CRTFrame.h | 5 ++ 3 files changed, 46 insertions(+), 24 deletions(-) diff --git a/OSBindings/Mac/Clock Signal/CSCathodeRayView.m b/OSBindings/Mac/Clock Signal/CSCathodeRayView.m index 822e89a0a..a0bc9c7ea 100644 --- a/OSBindings/Mac/Clock Signal/CSCathodeRayView.m +++ b/OSBindings/Mac/Clock Signal/CSCathodeRayView.m @@ -11,6 +11,7 @@ #import #import + @implementation CSCathodeRayView { CVDisplayLinkRef displayLink; @@ -19,6 +20,7 @@ GLuint _arrayBuffer, _vertexArray; GLint _positionAttribute; GLint _textureCoordinatesAttribute; + GLint _lateralAttribute; GLuint _textureName; CRTSize _textureSize; @@ -128,7 +130,7 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt if(crtFrame) { [self.openGLContext makeCurrentContext]; - glBufferData(GL_ARRAY_BUFFER, _crtFrame->number_of_runs * sizeof(GLushort) * 24, _crtFrame->runs, GL_DYNAMIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, _crtFrame->number_of_runs * sizeof(GLushort) * kCRTSizeOfVertex * 6, _crtFrame->runs, GL_DYNAMIC_DRAW); glBindTexture(GL_TEXTURE_2D, _textureName); @@ -156,10 +158,12 @@ const char *vertexShader = "in vec2 srcCoordinates;\n" "\n" "out vec2 srcCoordinatesVarying;\n" + "out float offsetVarying;\n" "\n" "void main (void)\n" "{\n" "srcCoordinatesVarying = vec2(srcCoordinates.x / 512.0, srcCoordinates.y / 512.0);\n" + "offsetVarying = mod(srcCoordinatesVarying.y * 512, 1.0) * 2.09435310266667 + 0.52359877566668;" "gl_Position = vec4(position.x * 2.0 - 1.0, 1.0 - position.y * 2.0 + position.x / 131.0, 0.0, 1.0);\n" "}\n"; @@ -168,12 +172,13 @@ const char *fragmentShader = "#version 150\n" "\n" "in vec2 srcCoordinatesVarying;\n" + "in float offsetVarying;" "out vec4 fragColour;\n" "uniform sampler2D texID;\n" "\n" "void main(void)\n" "{\n" - "fragColour = texture(texID, srcCoordinatesVarying) * vec4(1.0, 1.0, 1.0, sin(mod(srcCoordinatesVarying.y * 512, 1.0) * 2.09435310266667 + 0.52359877566668));\n" // vec4(1.0, 1.0, 1.0, 0.5) + "fragColour = texture(texID, srcCoordinatesVarying) * vec4(1.0, 1.0, 1.0, sin(offsetVarying));\n" // vec4(1.0, 1.0, 1.0, 0.5) "}\n"; #if defined(DEBUG) @@ -226,12 +231,16 @@ const char *fragmentShader = _positionAttribute = glGetAttribLocation(_shaderProgram, "position"); _textureCoordinatesAttribute = glGetAttribLocation(_shaderProgram, "srcCoordinates"); + _lateralAttribute = glGetAttribLocation(_shaderProgram, "lateral"); glEnableVertexAttribArray(_positionAttribute); glEnableVertexAttribArray(_textureCoordinatesAttribute); + glEnableVertexAttribArray(_lateralAttribute); - glVertexAttribPointer(_positionAttribute, 2, GL_UNSIGNED_SHORT, GL_TRUE, 4 * sizeof(GLushort), (void *)0); - glVertexAttribPointer(_textureCoordinatesAttribute, 2, GL_UNSIGNED_SHORT, GL_FALSE, 4 * sizeof(GLushort), (void *)(2 * sizeof(GLushort))); + const GLsizei vertexStride = kCRTSizeOfVertex * sizeof(GLushort); + glVertexAttribPointer(_positionAttribute, 2, GL_UNSIGNED_SHORT, GL_TRUE, vertexStride, (void *)(kCRTVertexOffsetOfPosition * sizeof(GLushort))); + glVertexAttribPointer(_textureCoordinatesAttribute, 2, GL_UNSIGNED_SHORT, GL_FALSE, vertexStride, (void *)(kCRTVertexOffsetOfTexCoord * sizeof(GLushort))); + glVertexAttribPointer(_lateralAttribute, 1, GL_UNSIGNED_SHORT, GL_FALSE, vertexStride, (void *)(kCRTVertexOffsetOfLateral * sizeof(GLushort))); glGenTextures(1, &_textureName); glBindTexture(GL_TEXTURE_2D, _textureName); diff --git a/Outputs/CRT.cpp b/Outputs/CRT.cpp index 04b94b7ca..9fd57c530 100644 --- a/Outputs/CRT.cpp +++ b/Outputs/CRT.cpp @@ -20,8 +20,8 @@ static const uint32_t kCRTFixedPointOffset = 0x08000000; void CRT::set_new_timing(int cycles_per_line, int height_of_display) { - const int syncCapacityLineChargeThreshold = 3; - const int millisecondsHorizontalRetraceTime = 7; // source: Dictionary of Video and Television Technology, p. 234 + const int syncCapacityLineChargeThreshold = 4; + const int millisecondsHorizontalRetraceTime = 10; // source: Dictionary of Video and Television Technology, p. 234 const int scanlinesVerticalRetraceTime = 7; // source: ibid _time_multiplier = (1000 + cycles_per_line - 1) / cycles_per_line; @@ -207,17 +207,23 @@ void CRT::advance_cycles(int number_of_cycles, bool hsync_requested, const bool // uint32_t *width = _widths[lengthMask]; uint32_t *width = _widths[0]; +#define position_x(v) next_run[kCRTSizeOfVertex*v + kCRTVertexOffsetOfPosition + 0] +#define position_y(v) next_run[kCRTSizeOfVertex*v + kCRTVertexOffsetOfPosition + 1] +#define tex_x(v) next_run[kCRTSizeOfVertex*v + kCRTVertexOffsetOfTexCoord + 0] +#define tex_y(v) next_run[kCRTSizeOfVertex*v + kCRTVertexOffsetOfTexCoord + 1] +#define lateral(v) next_run[kCRTSizeOfVertex*v + kCRTVertexOffsetOfLateral] + if(next_run) { // set the type, initial raster position and type of this run - next_run[0] = next_run[20] = (kCRTFixedPointOffset + _rasterPosition.x + width[0]) >> 16; - next_run[1] = next_run[21] = (kCRTFixedPointOffset + _rasterPosition.y + width[1]) >> 16; - next_run[4] = (kCRTFixedPointOffset + _rasterPosition.x - width[0]) >> 16; - next_run[5] = (kCRTFixedPointOffset + _rasterPosition.y - width[1]) >> 16; + position_x(0) = position_x(4) = (kCRTFixedPointOffset + _rasterPosition.x + width[0]) >> 16; + position_y(0) = position_y(4) = (kCRTFixedPointOffset + _rasterPosition.y + width[1]) >> 16; + position_x(1) = (kCRTFixedPointOffset + _rasterPosition.x - width[0]) >> 16; + position_y(1) = (kCRTFixedPointOffset + _rasterPosition.y - width[1]) >> 16; - next_run[2] = next_run[6] = next_run[22] = tex_x; - next_run[3] = next_run[23] = tex_y; - next_run[7] = tex_y + 1; + tex_x(0) = tex_x(1) = tex_x(4) = tex_x; + tex_y(0) = tex_y(4) = tex_y; + tex_y(1) = tex_y + 1; } // advance the raster position as dictated by current sync status @@ -234,19 +240,18 @@ void CRT::advance_cycles(int number_of_cycles, bool hsync_requested, const bool if(next_run) { // store the final raster position - next_run[8] = next_run[12] = (kCRTFixedPointOffset + _rasterPosition.x - width[0]) >> 16; - next_run[9] = next_run[13] = (kCRTFixedPointOffset + _rasterPosition.y - width[1]) >> 16; - - next_run[16] = (kCRTFixedPointOffset + _rasterPosition.x + width[0]) >> 16; - next_run[17] = (kCRTFixedPointOffset + _rasterPosition.y + width[1]) >> 16; + position_x(2) = position_x(3) = (kCRTFixedPointOffset + _rasterPosition.x - width[0]) >> 16; + position_y(2) = position_y(3) = (kCRTFixedPointOffset + _rasterPosition.y - width[1]) >> 16; + position_x(5) = (kCRTFixedPointOffset + _rasterPosition.x + width[0]) >> 16; + position_y(5) = (kCRTFixedPointOffset + _rasterPosition.y + width[1]) >> 16; // if this is a data run then advance the buffer pointer if(type == Type::Data) tex_x += next_run_length / _time_multiplier; // if this is a data or level run then store the end point - next_run[10] = next_run[14] = next_run[18] = tex_x; - next_run[11] = next_run[15] = tex_y + 1; - next_run[19] = tex_y; + tex_x(2) = tex_x(3) = tex_x(5) = tex_x; + tex_y(2) = tex_y(3) = tex_y+1; + tex_y(5) = tex_y; } // decrement the number of cycles left to run for and increment the @@ -419,13 +424,16 @@ void CRTFrameBuilder::complete() uint16_t *CRTFrameBuilder::get_next_run() { + const size_t vertices_per_run = 6; + const size_t size_of_run = kCRTSizeOfVertex * vertices_per_run; + // get a run from the allocated list, allocating more if we're about to overrun - if(frame.number_of_runs * 24 >= _all_runs.size()) + if(frame.number_of_runs * size_of_run >= _all_runs.size()) { - _all_runs.resize(_all_runs.size() + 2400); + _all_runs.resize(_all_runs.size() + size_of_run * 200); } - uint16_t *next_run = &_all_runs[frame.number_of_runs * 24]; + uint16_t *next_run = &_all_runs[frame.number_of_runs * size_of_run]; frame.number_of_runs++; return next_run; diff --git a/Outputs/CRTFrame.h b/Outputs/CRTFrame.h index 72186e924..e4938ac83 100644 --- a/Outputs/CRTFrame.h +++ b/Outputs/CRTFrame.h @@ -36,4 +36,9 @@ typedef struct { } #endif +static const int kCRTSizeOfVertex = 5; +static const int kCRTVertexOffsetOfPosition = 0; +static const int kCRTVertexOffsetOfTexCoord = 2; +static const int kCRTVertexOffsetOfLateral = 4; + #endif /* CRTFrame_h */