Skip to content

Commit

Permalink
Implement 24bit display mode
Browse files Browse the repository at this point in the history
  • Loading branch information
simias committed Dec 10, 2015
1 parent a5fc33d commit b3e7626
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 6 deletions.
7 changes: 4 additions & 3 deletions src/gpu/mod.rs
Expand Up @@ -360,7 +360,8 @@ impl Gpu {
self.renderer.display(self.display_vram_x_start,
self.display_vram_y_start,
self.hres.width(),
self.vres.height());
self.vres.height(),
self.display_depth);
}

/// Return true if we're currently in the video blanking period
Expand Down Expand Up @@ -1424,8 +1425,8 @@ impl Gpu {

self.display_depth =
match val & 0x10 != 0 {
false => DisplayDepth::D24Bits,
true => DisplayDepth::D15Bits,
false => DisplayDepth::D15Bits,
true => DisplayDepth::D24Bits,
};

self.interlaced = val & 0x20 != 0;
Expand Down
11 changes: 9 additions & 2 deletions src/gpu/opengl/mod.rs
Expand Up @@ -12,7 +12,8 @@ use glium::program::ProgramCreationInput;
use glium::texture::{Texture2d, UncompressedFloatFormat, MipmapsOption};
use glium::texture::{Texture2dDataSource, RawImage2d, ClientFormat};

use super::{TextureDepth, BlendMode, VRAM_WIDTH_PIXELS, VRAM_HEIGHT};
use super::{TextureDepth, BlendMode, DisplayDepth};
use super::{VRAM_WIDTH_PIXELS, VRAM_HEIGHT};

/// Maximum number of vertex that can be stored in an attribute
/// buffers
Expand Down Expand Up @@ -475,7 +476,8 @@ impl Renderer {
/// Draw the buffered commands and refresh the video output.
pub fn display(&mut self,
fb_x: u16, fb_y: u16,
width: u16, height: u16) {
width: u16, height: u16,
depth: DisplayDepth) {
// Draw any pending commands
self.draw();

Expand All @@ -490,6 +492,10 @@ impl Renderer {
let uniforms = uniform! {
fb: &self.fb_out,
alpha: 1.0f32,
depth_24bpp: match depth {
DisplayDepth::D15Bits => 0,
DisplayDepth::D24Bits => 1,
},
};

/// Vertex definition for the video output program
Expand Down Expand Up @@ -556,6 +562,7 @@ impl Renderer {
let uniforms = uniform! {
fb: sampler,
alpha: 0.7f32,
depth_24bpp: 0,
};

frame.draw(&vertices,
Expand Down
51 changes: 50 additions & 1 deletion src/gpu/opengl/shaders/output_fragment.glsl
Expand Up @@ -3,11 +3,60 @@
// We're sampling from the internal framebuffer texture
uniform sampler2D fb;
uniform float alpha;
// Framebuffer sampling: 0: Normal 16bpp mode, 1: Use 24bpp mode
uniform int depth_24bpp;

in vec2 frag_fb_coord;

out vec4 frag_color;

// Take a normalized color and convert it into a 16bit 1555 ABGR
// integer in the format used internally by the Playstation GPU.
int rebuild_color(vec4 color) {
int a = int(round(color.a));
int r = int(round(color.r * 31.));
int g = int(round(color.g * 31.));
int b = int(round(color.b * 31.));

return (a << 15) | (b << 10) | (g << 5) | r;
}

void main() {
frag_color = vec4(texture(fb, frag_fb_coord).rgb, alpha);
vec3 color;

if (depth_24bpp == 0) {
// Use the regular 16bpp mode, fetch directly from the framebuffer
// texture. The alpha/mask bit is ignored here.
color = texture(fb, frag_fb_coord).rgb;
} else {
// In this mode we have to interpret the framebuffer as containing
// 24bit RGB values instead of the usual 16bits 1555.

ivec2 fb_size = textureSize(fb, 0);

int x_24 = int(frag_fb_coord.x * float(fb_size.x));
int y = int((frag_fb_coord.y * float(fb_size.y)));

// The 24bit color is stored over two 16bit pixels, convert the
// coordinates
int x_16 = (x_24 * 3) / 2;

int col0 = rebuild_color(texelFetch(fb, ivec2(x_16, y), 0));
int col1 = rebuild_color(texelFetch(fb, ivec2(x_16 + 1, y), 0));

int col = (col1 << 16) | col0;

// If we're drawing an odd 24 bit pixel we're starting in the
// middle of a 16bit cell so we need to adjust accordingly.
col >>= 8 * (x_24 & 1);

// Finally we can extract and normalize the 24bit pixel
float b = float((col >> 16) & 0xff) / 255.;
float g = float((col >> 8) & 0xff) / 255.;
float r = float(col & 0xff) / 255.;

color = vec3(r, g, b);
}

frag_color = vec4(color, alpha);
}

0 comments on commit b3e7626

Please sign in to comment.