Skip to content

Commit

Permalink
Merge pull request #44 from UnsafePointer/fix_display_area
Browse files Browse the repository at this point in the history
Fix GPU drawing area in OpenGL renderer
  • Loading branch information
UnsafePointer authored May 10, 2020
2 parents 7513526 + 7917b6c commit 6679efe
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 26 deletions.
13 changes: 0 additions & 13 deletions glsl/screen_full_vram_vertex.glsl

This file was deleted.

17 changes: 15 additions & 2 deletions glsl/screen_vertex.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,22 @@ in vec2 frame_buffer_point;

out vec2 fragment_frame_buffer_point;

uniform bool full_framebuffer;
uniform float screen_width;
uniform float screen_height;
uniform float vram_width;
uniform float vram_height;

void main() {
gl_Position = vec4(vertex_point.x, vertex_point.y, 0.0, 1.0);
float frame_buffer_point_x = (float(frame_buffer_point.x) / 1024) - 1.0;
float frame_buffer_point_y = 1.0 - (float(frame_buffer_point.y) / 512);
float frame_buffer_point_x;
;float frame_buffer_point_y;
if (full_framebuffer) {
frame_buffer_point_x = (float(frame_buffer_point.x)) - 1.0;
frame_buffer_point_y = 1.0 - (float(frame_buffer_point.y));
} else {
frame_buffer_point_x = (float(frame_buffer_point.x) / vram_width) - 1.0;
frame_buffer_point_y = 1.0 - (float(frame_buffer_point.y) / vram_height);
}
fragment_frame_buffer_point = vec2(frame_buffer_point_x, frame_buffer_point_y);
}
3 changes: 3 additions & 0 deletions include/GPU.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ GP1(07h) - Vertical Display range (on Screen)
uint8_t horizontalResolutionFromValues(uint8_t value1, uint8_t value2) const;

void render();
void updateDrawingArea();
public:
GPU(LogLevel logLevel, std::unique_ptr<Window> &mainWindow, std::unique_ptr<InterruptController> &interruptController, std::unique_ptr<DebugInfoRenderer> &debugInfoRenderer);
~GPU();
Expand All @@ -279,5 +280,7 @@ GP1(07h) - Vertical Display range (on Screen)
void step(uint32_t cycles);
Dimensions getResolution();
Point getDisplayAreaStart();
Dimensions getDrawingAreaSize();
Point getDrawingAreaTopLeft();
void toggleRenderPolygonOneByOne();
};
5 changes: 5 additions & 0 deletions include/Renderer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,14 @@ class Renderer {
bool resizeToFitFramebuffer;
Point displayAreaStart;
Dimensions screenResolution;
Point drawingAreaTopLeft;
Dimensions drawingAreaSize;
bool renderPolygonOneByOne;

void checkRenderPolygonOneByOne();
void checkForceDraw(unsigned int verticesToRender, GLenum newMode);
void forceDraw();
void applyScissor();
public:
Renderer(std::unique_ptr<Window> &mainWindow, GPU *gpu);
~Renderer();
Expand All @@ -53,5 +57,6 @@ class Renderer {
void resetMainWindow();
void setDisplayAreaSart(Point point);
void setScreenResolution(Dimensions dimensions);
void setDrawingArea(Point topLeft, Dimensions size);
void toggleRenderPolygonOneByOne();
};
19 changes: 19 additions & 0 deletions src/GPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,13 @@ void GPU::render() {
renderer->updateWindowTitle(title.str());
}

void GPU::updateDrawingArea() {
Point topLeft = getDrawingAreaTopLeft();
Dimensions size = getDrawingAreaSize();
logger.logMessage("Updating renderer drawing area with top left: x=%d, y=%d and size: w=%d, h=%d", topLeft.x, topLeft.y, size.width, size.height);
renderer->setDrawingArea(topLeft, size);
}

Dimensions GPU::getResolution() {
uint32_t verticalResolution = 240;
if (this->verticalResolution == VerticalResolution::Y480) {
Expand Down Expand Up @@ -662,6 +669,16 @@ Point GPU::getDisplayAreaStart() {
return { (int16_t)displayVRAMStartX, (int16_t)displayVRAMStartY };
}

Dimensions GPU::getDrawingAreaSize() {
uint32_t width = drawingAreaRight - drawingAreaLeft;
uint32_t height = drawingAreaBottom - drawingAreaTop;
return { (uint32_t)width, (uint32_t)height };
}

Point GPU::getDrawingAreaTopLeft() {
return { (int16_t)drawingAreaLeft, (int16_t)drawingAreaTop };
}

void GPU::toggleRenderPolygonOneByOne() {
renderer->toggleRenderPolygonOneByOne();
}
Expand Down Expand Up @@ -861,6 +878,7 @@ void GPU::operationGp0SetDrawingAreaTopLeft() {
uint32_t value = gp0InstructionBuffer[0];
drawingAreaTop = ((value >> 10) & 0x3ff);
drawingAreaLeft = (value & 0x3ff);
updateDrawingArea();
logger.logMessage("GP0(E3h) - Set Drawing Area top left: %d, %d", drawingAreaTop, drawingAreaLeft);
}

Expand All @@ -877,6 +895,7 @@ void GPU::operationGp0SetDrawingAreaBottomRight() {
uint32_t value = gp0InstructionBuffer[0];
drawingAreaBottom = ((value >> 10) & 0x3ff);
drawingAreaRight = (value & 0x3ff);
updateDrawingArea();
logger.logMessage("GP0(E3h) - Set Drawing Area bottom right: %d, %d", drawingAreaBottom, drawingAreaRight);
}

Expand Down
71 changes: 60 additions & 11 deletions src/Renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

using namespace std;

Renderer::Renderer(std::unique_ptr<Window> &mainWindow, GPU *gpu) : logger(LogLevel::NoLog), mainWindow(mainWindow), mode(GL_TRIANGLES), displayAreaStart(), screenResolution({}), renderPolygonOneByOne(false) {
Renderer::Renderer(std::unique_ptr<Window> &mainWindow, GPU *gpu) : logger(LogLevel::NoLog), mainWindow(mainWindow), mode(GL_TRIANGLES), displayAreaStart(), screenResolution({}), drawingAreaTopLeft(), drawingAreaSize({}), renderPolygonOneByOne(false) {
ConfigurationManager *configurationManager = ConfigurationManager::getInstance();
resizeToFitFramebuffer = configurationManager->shouldResizeWindowToFitFramebuffer();

Expand All @@ -26,21 +26,30 @@ Renderer::Renderer(std::unique_ptr<Window> &mainWindow, GPU *gpu) : logger(LogLe
offsetUniform = program->findProgramUniform("offset");
glUniform2i(offsetUniform, 0, 0);

// TODO: Use a single vertex shader
Dimensions screenDimensions = mainWindow->getDimensions();

string screenVertexFile = "./glsl/screen_vertex.glsl";
if (resizeToFitFramebuffer) {
screenVertexFile = "./glsl/screen_full_vram_vertex.glsl";
}
screenRendererProgram = make_unique<RendererProgram>(screenVertexFile, "./glsl/screen_fragment.glsl");
screenRendererProgram->useProgram();
GLuint screenWidthUniform = screenRendererProgram->findProgramUniform("screen_width");
glUniform1f(screenWidthUniform, screenDimensions.width);
GLuint screenHeightUniform = screenRendererProgram->findProgramUniform("screen_height");
glUniform1f(screenHeightUniform, screenDimensions.height);
GLuint vramWidthUniform = screenRendererProgram->findProgramUniform("vram_width");
glUniform1f(vramWidthUniform, VRAM_WIDTH);
GLuint vramHeightUniform = screenRendererProgram->findProgramUniform("vram_height");
glUniform1f(vramHeightUniform, VRAM_HEIGHT);
GLuint fullFramebufferUniform = screenRendererProgram->findProgramUniform("full_framebuffer");
glUniform1f(fullFramebufferUniform, resizeToFitFramebuffer);

screenBuffer = make_unique<RendererBuffer<Pixel>>(screenRendererProgram, RENDERER_BUFFER_SIZE);

// TODO: handle resolution for other targets
loadImageTexture = make_unique<Texture>(((GLsizei) VRAM_WIDTH), ((GLsizei) VRAM_HEIGHT));

Dimensions screenDimensions = mainWindow->getDimensions();
screenTexture = make_unique<Texture>(((GLsizei) screenDimensions.width), ((GLsizei) screenDimensions.height));
RendererDebugger *rendererDebugger = RendererDebugger::getInstance();

rendererDebugger->checkForOpenGLErrors();

displayAreaStart = gpu->getDisplayAreaStart();
Expand All @@ -66,14 +75,41 @@ void Renderer::checkForceDraw(unsigned int verticesToRender, GLenum newMode) {
verticesToRenderTotal = 6;
}
if (buffer->remainingCapacity() < verticesToRenderTotal) {
renderFrame();
forceDraw();
}
if (mode != newMode) {
renderFrame();
forceDraw();
}
return;
}

void Renderer::forceDraw() {
loadImageTexture->bind(GL_TEXTURE0);
Framebuffer framebuffer = Framebuffer(screenTexture);
buffer->draw(mode);
}

void Renderer::applyScissor() {
// TODO: there must be a better way of doing this
// Scissor test is specified in window coordinates, but we get PlayStation screen buffer
// from the GPU commands, so we need to translate between coordinate systems. The problem here
// is that we need to handle different modes: full framebuffer and display area cropped.
Dimensions windowSize = mainWindow->getDimensions();

// Conveniently the width is the same for both modes, so nothing to do here
GLsizei width = drawingAreaSize.width;
GLint x = drawingAreaTopLeft.x;

GLsizei height = ((float)drawingAreaSize.height / VRAM_HEIGHT * windowSize.height);
GLint y = windowSize.height - height - ((float)drawingAreaTopLeft.y / VRAM_HEIGHT * windowSize.height);

if (resizeToFitFramebuffer) {
height = drawingAreaSize.height;
y = VRAM_HEIGHT - height - drawingAreaTopLeft.y;
}
glScissor(x, y, width, height);
}

void Renderer::pushLine(std::vector<Vertex> vertices) {
unsigned int size = vertices.size();
if (size < 2) {
Expand Down Expand Up @@ -124,12 +160,23 @@ void Renderer::setScreenResolution(Dimensions dimensions) {
screenResolution = dimensions;
}

void Renderer::setDrawingArea(Point topLeft, Dimensions size) {
forceDraw();

drawingAreaTopLeft = topLeft;
drawingAreaSize = size;

applyScissor();
}

void Renderer::toggleRenderPolygonOneByOne() {
renderPolygonOneByOne = !renderPolygonOneByOne;
}

void Renderer::prepareFrame() {
resetMainWindow();
applyScissor();
glEnable(GL_SCISSOR_TEST);
loadImageTexture->bind(GL_TEXTURE0);
}

Expand All @@ -143,6 +190,7 @@ void Renderer::renderFrame() {
void Renderer::finalizeFrame() {
buffer->draw(mode);
screenTexture->bind(GL_TEXTURE0);
glDisable(GL_SCISSOR_TEST);
vector<Pixel> pixels;
if (resizeToFitFramebuffer) {
pixels = {
Expand All @@ -159,6 +207,7 @@ void Renderer::finalizeFrame() {
Pixel(1.0f, 1.0f, displayAreaStart.x + screenResolution.width, displayAreaStart.y),
};
}

screenBuffer->addData(pixels);
screenBuffer->draw(GL_TRIANGLE_STRIP);
RendererDebugger *rendererDebugger = RendererDebugger::getInstance();
Expand All @@ -171,9 +220,7 @@ void Renderer::updateWindowTitle(string title) {
}

void Renderer::setDrawingOffset(int16_t x, int16_t y) {
loadImageTexture->bind(GL_TEXTURE0);
Framebuffer framebuffer = Framebuffer(screenTexture);
buffer->draw(mode);
forceDraw();
glUniform2i(offsetUniform, ((GLint)x), ((GLint)y));
}

Expand All @@ -185,8 +232,10 @@ void Renderer::loadImage(std::unique_ptr<GPUImageBuffer> &imageBuffer) {
tie(width, height) = imageBuffer->resolution();
vector<Point> data = { {(GLshort)x, (GLshort)y}, {(GLshort)(x + width), (GLshort)y}, {(GLshort)x, (GLshort)(y + height)}, {(GLshort)(x + width), (GLshort)(y + height)} };
textureBuffer->addData(data);
glDisable(GL_SCISSOR_TEST);
Framebuffer framebuffer = Framebuffer(screenTexture);
textureBuffer->draw(GL_TRIANGLE_STRIP);
glEnable(GL_SCISSOR_TEST);
RendererDebugger *rendererDebugger = RendererDebugger::getInstance();
rendererDebugger->checkForOpenGLErrors();
}

0 comments on commit 6679efe

Please sign in to comment.