Update to v093r12a release.

byuu says:

Not an official WIP (a WIP WIP? A meta-WIP?), just throwing in the new
fullscreen code, and I noticed that OpenGL colors in 30-bit mode are all
fucked up now for some strange reason. So I'm just using this snapshot
to debug the issue.
This commit is contained in:
Tim Allen
2014-01-05 20:59:17 +11:00
parent 3ce1d19f7a
commit 2b81b630cb
64 changed files with 1680 additions and 2445 deletions

View File

@@ -66,8 +66,8 @@ struct pVideoGLX : OpenGL {
if(depth > DefaultDepth(display, screen)) return false;
switch(depth) {
case 24: format = GL_RGBA8; inputFormat = GL_UNSIGNED_INT_8_8_8_8_REV; break;
case 30: format = GL_RGB10_A2; inputFormat = GL_UNSIGNED_INT_2_10_10_10_REV; break;
case 24: format = GL_RGBA8; break;
case 30: format = GL_RGB10_A2; break;
default: return false;
}

View File

@@ -2,9 +2,6 @@ void OpenGL::shader(const char* pathname) {
for(auto& program : programs) program.release();
programs.reset();
for(auto& frame : frames) glDeleteTextures(1, &frame.texture);
frames.reset();
settings.reset();
format = GL_RGBA8;
@@ -13,6 +10,7 @@ void OpenGL::shader(const char* pathname) {
absoluteWidth = 0, absoluteHeight = 0;
relativeWidth = 0, relativeHeight = 0;
unsigned historySize = 0;
if(pathname) {
auto document = Markup::Document(file::read({pathname, "manifest.bml"}));
@@ -20,27 +18,51 @@ void OpenGL::shader(const char* pathname) {
settings.insert({node.name, node.text()});
}
for(auto& node : document["input"]) {
if(node.name == "history") historySize = node.decimal();
if(node.name == "format") format = glrFormat(node.text());
if(node.name == "filter") filter = glrFilter(node.text());
if(node.name == "wrap") wrap = glrWrap(node.text());
}
for(auto& node : document["output"]) {
string text = node.text();
if(node.name == "width") {
if(text.endsWith("%")) relativeWidth = real(text.rtrim<1>("%")) / 100.0;
else absoluteWidth = decimal(text);
}
if(node.name == "height") {
if(text.endsWith("%")) relativeHeight = real(text.rtrim<1>("%")) / 100.0;
else absoluteHeight = decimal(text);
}
}
for(auto& node : document.find("program")) {
unsigned n = programs.size();
programs(n).bind(this, node, pathname);
}
bind(document, pathname);
OpenGLProgram::bind(this, document["output"], pathname);
} else {
//no shader; assign default values
history.length = 0;
history.format = GL_RGBA8;
history.filter = GL_LINEAR;
history.wrap = GL_CLAMP_TO_BORDER;
}
//changing shaders may change input format, which requires the input texture to be recreated
if(texture) { glDeleteTextures(1, &texture); texture = 0; }
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, getFormat(), getType(), buffer);
allocateHistory(historySize);
}
void OpenGL::bind(const Markup::Node& node, const string& pathname) {
history.length = node["history/frames"].decimal();
if(node["history/format"].exists()) history.format = glrFormat(node["history/format"].text());
if(node["history/filter"].exists()) history.filter = glrFilter(node["history/filter"].text());
if(node["history/wrap"].exists()) history.wrap = glrWrap(node["history/wrap"].text());
void OpenGL::allocateHistory(unsigned size) {
for(auto& frame : history) glDeleteTextures(1, &frame.texture);
history.reset();
while(size--) {
OpenGLTexture frame;
frame.filter = filter;
frame.wrap = wrap;
glGenTextures(1, &frame.texture);
glBindTexture(GL_TEXTURE_2D, frame.texture);
glTexImage2D(GL_TEXTURE_2D, 0, format, frame.width = width, frame.height = height, 0, getFormat(), getType(), buffer);
history.append(frame);
}
}
bool OpenGL::lock(uint32_t*& data, unsigned& pitch) {
@@ -64,20 +86,9 @@ void OpenGL::clear() {
void OpenGL::refresh() {
clear();
//frame[] must always contain max# of previous frames: allocate them now, so first few frames can use them
while(frames.size() < history.length) {
OpenGLTexture frame;
glGenTextures(1, &frame.texture);
glBindTexture(GL_TEXTURE_2D, frame.texture);
glTexImage2D(GL_TEXTURE_2D, 0, frame.format = history.format, frame.width = width, frame.height = height, 0, GL_BGRA, inputFormat, buffer);
frame.filter = history.filter;
frame.wrap = history.wrap;
frames.append(frame);
}
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_BGRA, inputFormat, buffer);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, getFormat(), getType(), buffer);
struct Source {
GLuint texture;
@@ -85,31 +96,29 @@ void OpenGL::refresh() {
GLuint filter, wrap;
};
vector<Source> sources;
unsigned sourceWidth = width, sourceHeight = height;
sources.prepend({texture, sourceWidth, sourceHeight, filter, wrap});
sources.prepend({texture, width, height, filter, wrap});
for(auto& p : programs) {
unsigned targetWidth = p.absoluteWidth ? p.absoluteWidth : outputWidth;
unsigned targetHeight = p.absoluteHeight ? p.absoluteHeight : outputHeight;
if(p.relativeWidth) targetWidth = sourceWidth * p.relativeWidth;
if(p.relativeHeight) targetHeight = sourceHeight * p.relativeHeight;
if(p.relativeWidth) targetWidth = sources[0].width * p.relativeWidth;
if(p.relativeHeight) targetHeight = sources[0].height * p.relativeHeight;
p.size(targetWidth, targetHeight);
glUseProgram(p.program);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, p.framebuffer);
glrUniform1i("phase", p.phase);
glrUniform1i("frameLength", frames.size());
glrUniform1i("historyLength", history.size());
glrUniform1i("sourceLength", sources.size());
glrUniform1i("pixmapLength", p.pixmaps.size());
glrUniform4f("targetSize", targetWidth, targetHeight, 1.0 / targetWidth, 1.0 / targetHeight);
glrUniform4f("outputSize", outputWidth, outputHeight, 1.0 / outputWidth, 1.0 / outputHeight);
unsigned aid = 0;
for(auto& frame : frames) {
glrUniform1i({"frame[", aid, "]"}, aid);
glrUniform4f({"frameSize[", aid, "]"}, frame.width, frame.height, 1.0 / frame.width, 1.0 / frame.height);
for(auto& frame : history) {
glrUniform1i({"history[", aid, "]"}, aid);
glrUniform4f({"historySize[", aid, "]"}, frame.width, frame.height, 1.0 / frame.width, 1.0 / frame.height);
glActiveTexture(GL_TEXTURE0 + (aid++));
glBindTexture(GL_TEXTURE_2D, frame.texture);
glrParameters(frame.filter, frame.wrap);
@@ -134,19 +143,18 @@ void OpenGL::refresh() {
}
glActiveTexture(GL_TEXTURE0);
glrParameters(p.filter, p.wrap);
p.render(sourceWidth, sourceHeight, targetWidth, targetHeight);
glrParameters(sources[0].filter, sources[0].wrap);
p.render(sources[0].width, sources[0].height, targetWidth, targetHeight);
glBindTexture(GL_TEXTURE_2D, p.texture);
p.phase = (p.phase + 1) % p.modulo;
sourceWidth = p.width, sourceHeight = p.height;
sources.prepend({p.texture, sourceWidth, sourceHeight, p.filter, p.wrap});
sources.prepend({p.texture, p.width, p.height, p.filter, p.wrap});
}
unsigned targetWidth = absoluteWidth ? absoluteWidth : outputWidth;
unsigned targetHeight = absoluteHeight ? absoluteHeight : outputHeight;
if(relativeWidth) targetWidth = sourceWidth * relativeWidth;
if(relativeHeight) targetHeight = sourceHeight * relativeHeight;
if(relativeWidth) targetWidth = sources[0].width * relativeWidth;
if(relativeHeight) targetHeight = sources[0].height * relativeHeight;
glUseProgram(program);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
@@ -155,20 +163,20 @@ void OpenGL::refresh() {
glrUniform4f("targetSize", targetWidth, targetHeight, 1.0 / targetWidth, 1.0 / targetHeight);
glrUniform4f("outputSize", outputWidth, outputHeight, 1.0 / outputWidth, 1.0 / outputHeight);
glrParameters(filter, wrap);
render(sourceWidth, sourceHeight, outputWidth, outputHeight);
glrParameters(sources[0].filter, sources[0].wrap);
render(sources[0].width, sources[0].height, outputWidth, outputHeight);
if(frames.size() > 0) {
OpenGLTexture frame = frames.take();
if(history.size() > 0) {
OpenGLTexture frame = history.takeLast();
glBindTexture(GL_TEXTURE_2D, frame.texture);
if(width == frame.width && height == frame.height) {
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_BGRA, inputFormat, buffer);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, getFormat(), getType(), buffer);
} else {
glTexImage2D(GL_TEXTURE_2D, 0, frame.format, frame.width = width, frame.height = height, 0, GL_BGRA, inputFormat, buffer);
glTexImage2D(GL_TEXTURE_2D, 0, format, frame.width = width, frame.height = height, 0, getFormat(), getType(), buffer);
}
frames.prepend(frame);
history.prepend(frame);
}
}

View File

@@ -28,6 +28,9 @@ struct OpenGLTexture {
GLuint format = GL_RGBA8;
GLuint filter = GL_LINEAR;
GLuint wrap = GL_CLAMP_TO_BORDER;
GLuint getFormat() const;
GLuint getType() const;
};
struct OpenGLSurface : OpenGLTexture {
@@ -47,7 +50,6 @@ struct OpenGLSurface : OpenGLTexture {
};
struct OpenGLProgram : OpenGLSurface {
//configuration
unsigned phase = 0; //frame counter
unsigned modulo = 0; //frame counter modulus
unsigned absoluteWidth = 0;
@@ -63,18 +65,9 @@ struct OpenGLProgram : OpenGLSurface {
struct OpenGL : OpenGLProgram {
vector<OpenGLProgram> programs;
vector<OpenGLTexture> frames;
struct History {
unsigned length = 0;
GLuint format = GL_RGBA8;
GLuint filter = GL_LINEAR;
GLuint wrap = GL_CLAMP_TO_BORDER;
} history;
GLuint inputFormat = GL_UNSIGNED_INT_8_8_8_8_REV;
vector<OpenGLTexture> history;
unsigned outputWidth = 0;
unsigned outputHeight = 0;
struct Setting {
string name;
string value;
@@ -87,7 +80,7 @@ struct OpenGL : OpenGLProgram {
set<Setting> settings;
void shader(const char* pathname);
void bind(const Markup::Node& node, const string& pathname);
void allocateHistory(unsigned size);
bool lock(uint32_t*& data, unsigned& pitch);
void clear();
void refresh();
@@ -95,6 +88,7 @@ struct OpenGL : OpenGLProgram {
void term();
};
#include "texture.hpp"
#include "surface.hpp"
#include "program.hpp"
#include "main.hpp"

View File

@@ -9,7 +9,6 @@ void OpenGLProgram::bind(OpenGL* instance, const Markup::Node& node, const strin
if(h.endsWith("%")) relativeHeight = real(h.rtrim<1>("%")) / 100.0;
else absoluteHeight = decimal(h);
if(node.name != "program") return;
format = glrFormat(node["format"].text());
program = glCreateProgram();
@@ -62,8 +61,8 @@ void OpenGLProgram::bind(OpenGL* instance, const Markup::Node& node, const strin
unsigned w = glrSize(image.width), h = glrSize(image.height);
uint32_t* buffer = new uint32_t[w * h]();
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, pixmaps(n).format, w, h, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, buffer);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, image.width, image.height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, image.data);
glTexImage2D(GL_TEXTURE_2D, 0, pixmaps(n).format, w, h, 0, pixmaps(n).getFormat(), pixmaps(n).getType(), buffer);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, image.width, image.height, getFormat(), getType(), image.data);
delete[] buffer;
}

View File

@@ -15,7 +15,7 @@ void OpenGLSurface::size(unsigned w, unsigned h) {
buffer = new uint32_t[w * h]();
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, buffer);
glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, getFormat(), getType(), buffer);
if(framebuffer) {
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);

View File

@@ -0,0 +1,12 @@
GLuint OpenGLTexture::getFormat() const {
if(format == GL_R32I) return GL_RED_INTEGER;
if(format == GL_R32UI) return GL_RED_INTEGER;
return GL_BGRA;
}
GLuint OpenGLTexture::getType() const {
if(format == GL_R32I) return GL_UNSIGNED_INT;
if(format == GL_R32UI) return GL_UNSIGNED_INT;
if(format == GL_RGB10_A2) return GL_UNSIGNED_INT_2_10_10_10_REV;
return GL_UNSIGNED_INT_8_8_8_8_REV;
}

View File

@@ -4,6 +4,8 @@ static unsigned glrSize(unsigned size) {
}
static GLuint glrFormat(const string& format) {
if(format == "r32i" ) return GL_R32I;
if(format == "r32ui" ) return GL_R32UI;
if(format == "rgba8" ) return GL_RGBA8;
if(format == "rgb10a2") return GL_RGB10_A2;
if(format == "rgba12" ) return GL_RGBA12;

View File

@@ -4,33 +4,45 @@
namespace ruby {
struct pVideoXShm {
struct {
Display* display;
struct Device {
Display* display = nullptr;
int screen;
Visual *visual;
int depth;
Visual* visual = nullptr;
Window window;
XShmSegmentInfo shmInfo;
XImage* image;
uint32_t* buffer;
XImage* image = nullptr;
uint32_t* buffer = nullptr;
unsigned width, height;
} device;
struct {
struct Settings {
uintptr_t handle;
unsigned depth = 24;
uint32_t* buffer;
uint32_t* buffer = nullptr;
unsigned width, height;
} settings;
struct Color {
unsigned depth;
unsigned shift;
unsigned idepth;
unsigned ishift;
} red, green, blue;
bool cap(const string& name) {
if(name == Video::Handle) return true;
if(name == Video::Depth) return true;
return false;
}
any get(const string& name) {
if(name == Video::Handle) return settings.handle;
if(name == Video::Depth) return settings.depth;
return false;
}
bool set(const string& name, const any& value) {
@@ -38,6 +50,9 @@ struct pVideoXShm {
settings.handle = any_cast<uintptr_t>(value);
return true;
}
if(name == Video::Depth) {
return setDepth(any_cast<unsigned>(value));
}
return false;
}
@@ -66,7 +81,7 @@ struct pVideoXShm {
if(settings.buffer == nullptr) return;
size();
float xRatio = (float)settings.width / (float)device.width;
float xRatio = (float)settings.width / (float)device.width;
float yRatio = (float)settings.height / (float)device.height;
float yStep = 0;
for(unsigned y = 0; y < device.height; y++) {
@@ -77,7 +92,12 @@ struct pVideoXShm {
for(unsigned x = 0; x < device.width; x++) {
uint32_t color = sp[(unsigned)xStep];
xStep += xRatio;
*dp++ = ((color >> 20) & 0x000003ff) | ((color) & 0x000ffc00) | ((color << 20) & 0x3ff00000);
unsigned r = (color >> red.ishift ) & ((1 << red.idepth ) - 1);
unsigned g = (color >> green.ishift) & ((1 << green.idepth) - 1);
unsigned b = (color >> blue.ishift ) & ((1 << blue.idepth ) - 1);
*dp++ = image::normalize(r, red.idepth, red.depth ) << red.shift
| image::normalize(g, green.idepth, green.depth) << green.shift
| image::normalize(b, blue.idepth, blue.depth ) << blue.shift;
}
}
@@ -93,15 +113,36 @@ struct pVideoXShm {
bool init() {
device.display = XOpenDisplay(0);
device.screen = DefaultScreen(device.display);
device.visual = DefaultVisual(device.display, device.screen);
device.depth = DefaultDepth(device.display, device.screen);
XSetWindowAttributes attributes;
attributes.border_pixel = 0;
XWindowAttributes getAttributes;
XGetWindowAttributes(device.display, (Window)settings.handle, &getAttributes);
device.depth = getAttributes.depth;
device.visual = getAttributes.visual;
unsigned visualID = XVisualIDFromVisual(device.visual);
XVisualInfo visualTemplate = {0};
visualTemplate.screen = device.screen;
visualTemplate.depth = device.depth;
int visualsMatched = 0;
XVisualInfo* visualList = XGetVisualInfo(device.display, VisualScreenMask | VisualDepthMask, &visualTemplate, &visualsMatched);
for(unsigned n = 0; n < visualsMatched; n++) {
auto& v = visualList[n];
if(v.visualid == visualID) {
red.depth = bit::count(v.red_mask), red.shift = bit::first(v.red_mask);
green.depth = bit::count(v.green_mask), green.shift = bit::first(v.green_mask);
blue.depth = bit::count(v.blue_mask), blue.shift = bit::first(v.blue_mask);
break;
}
}
XFree(visualList);
setDepth(settings.depth);
XSetWindowAttributes setAttributes = {0};
setAttributes.border_pixel = 0;
device.window = XCreateWindow(device.display, (Window)settings.handle,
0, 0, 256, 256,
0, device.depth, InputOutput, device.visual,
CWBorderPixel, &attributes
0, 0, 256, 256, 0,
getAttributes.depth, InputOutput, getAttributes.visual,
CWBorderPixel, &setAttributes
);
XSetWindowBackground(device.display, device.window, 0);
XMapWindow(device.display, device.window);
@@ -118,12 +159,8 @@ struct pVideoXShm {
void term() {
free();
}
pVideoXShm() {
device.buffer = nullptr;
settings.buffer = nullptr;
if(device.display) { XCloseDisplay(device.display); device.display = nullptr; }
}
~pVideoXShm() {
@@ -131,6 +168,26 @@ struct pVideoXShm {
}
//internal:
bool setDepth(unsigned depth) {
if(depth == 24) {
settings.depth = 24;
red.idepth = 8, red.ishift = 16;
green.idepth = 8, green.ishift = 8;
blue.idepth = 8, blue.ishift = 0;
return true;
}
if(depth == 30) {
settings.depth = 30;
red.idepth = 10, red.ishift = 20;
green.idepth = 10, green.ishift = 10;
blue.idepth = 10, blue.ishift = 0;
return true;
}
return false;
}
bool size() {
XWindowAttributes windowAttributes;
XGetWindowAttributes(device.display, settings.handle, &windowAttributes);