Update to v095r03 release and icarus 20151107.

byuu says:

Note: you will need the new icarus (and please use the "no manifest"
system) to run GBA games with this WIP.

Changelog:
- fixed caching of r(d) to pass armwrestler tests [Jonas Quinn]
- DMA to/from GBA BIOS should fail [Cydrak]
- fixed sign-extend and rotate on ldrs instructions [Cydrak]
- fixed 8-bit SRAM reading/writing [byuu]
- refactored GBA/cartridge
  - cartridge/rom,ram.type is now cartridge/mrom,sram,eeprom,flash
  - things won't crash horribly if you specify a RAM size larger than
    the largest legal size in the manifest
  - specialized MROM / SRAM classes replace all the shared read/write
    functions that didn't work right anyway
- there's a new ruby/video.glx2 driver, which is not enabled by default
  - use this if you are running Linux/BSD, but don't have OpenGL 3.2 yet
  - I'm not going to support OpenGL2 on Windows/OS X, because these OSes
    don't ship ancient video card drivers
- probably more. What am I, clairvoyant? :P

For endrift's tests, this gets us to 1348/1552 memory and 1016/1260
timing. Overall, this puts us back in second place. Only no$ is ahead
on memory, but bgba is even more ahead on timing.
This commit is contained in:
Tim Allen
2015-11-08 20:09:18 +11:00
parent b42ab2fcb3
commit 0fe55e3f5b
32 changed files with 607 additions and 280 deletions

View File

@@ -43,6 +43,10 @@ using namespace ruby;
#include <ruby/video/glx.cpp>
#endif
#if defined(VIDEO_GLX2)
#include <ruby/video/glx2.cpp>
#endif
#if defined(VIDEO_SDL)
#include <ruby/video/sdl.cpp>
#endif
@@ -93,6 +97,10 @@ auto Video::create(const string& driver) -> Video* {
if(driver == "OpenGL") return new VideoGLX;
#endif
#if defined(VIDEO_GLX2)
if(driver == "OpenGL2") return new VideoGLX2;
#endif
#if defined(VIDEO_SDL)
if(driver == "SDL") return new VideoSDL;
#endif
@@ -125,6 +133,8 @@ auto Video::optimalDriver() -> string {
return "OpenGL";
#elif defined(VIDEO_GLX)
return "OpenGL";
#elif defined(VIDEO_GLX2)
return "OpenGL2";
#elif defined(VIDEO_XV)
return "X-Video";
#elif defined(VIDEO_XSHM)
@@ -153,6 +163,8 @@ auto Video::safestDriver() -> string {
return "SDL";
#elif defined(VIDEO_XV)
return "X-Video";
#elif defined(VIDEO_GLX2)
return "OpenGL2";
#elif defined(VIDEO_GLX)
return "OpenGL";
#else
@@ -187,6 +199,10 @@ auto Video::availableDrivers() -> lstring {
"OpenGL",
#endif
#if defined(VIDEO_GLX2)
"OpenGL2",
#endif
#if defined(VIDEO_XV)
"X-Video",
#endif

245
ruby/video/glx2.cpp Normal file
View File

@@ -0,0 +1,245 @@
//Xorg/GLX OpenGL 2.0 driver
//note: this is a fallback driver for use when OpenGL 3.2 is not available.
//see glx.cpp for comments on how this driver operates (they are very similar.)
struct VideoGLX2 : Video {
~VideoGLX2() { term(); }
auto (*glXSwapInterval)(signed) -> signed = nullptr;
Display* display = nullptr;
signed screen = 0;
Window xwindow = 0;
Colormap colormap = 0;
GLXContext glxcontext = nullptr;
GLXWindow glxwindow = 0;
struct {
Window handle = 0;
bool synchronize = false;
unsigned filter = 1; //linear
unsigned width = 256;
unsigned height = 256;
bool isDoubleBuffered = false;
bool isDirect = false;
} settings;
auto cap(const string& name) -> bool {
if(name == Video::Handle) return true;
if(name == Video::Synchronize) return true;
if(name == Video::Filter) return true;
return false;
}
auto get(const string& name) -> any {
if(name == Video::Handle) return (uintptr_t)settings.handle;
if(name == Video::Synchronize) return settings.synchronize;
if(name == Video::Filter) return settings.filter;
return {};
}
auto set(const string& name, const any& value) -> bool {
if(name == Video::Handle && value.is<uintptr_t>()) {
settings.handle = value.get<uintptr_t>();
return true;
}
if(name == Video::Synchronize && value.is<bool>()) {
if(settings.synchronize != value.get<bool>()) {
settings.synchronize = value.get<bool>();
if(glXSwapInterval) glXSwapInterval(settings.synchronize);
return true;
}
}
if(name == Video::Filter && value.is<unsigned>()) {
settings.filter = value.get<unsigned>();
return true;
}
return false;
}
auto lock(uint32_t*& data, unsigned& pitch, unsigned width, unsigned height) -> bool {
if(width != settings.width || height != settings.height) resize(width, height);
pitch = glwidth * sizeof(uint32_t);
return data = glbuffer;
}
auto unlock() -> void {
}
auto clear() -> void {
memory::fill(glbuffer, glwidth * glheight * sizeof(uint32_t));
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glFlush();
if(settings.isDoubleBuffered) glXSwapBuffers(display, glxwindow);
}
auto refresh() -> void {
XWindowAttributes parent, child;
XGetWindowAttributes(display, settings.handle, &parent);
XGetWindowAttributes(display, xwindow, &child);
if(child.width != parent.width || child.height != parent.height) {
XResizeWindow(display, xwindow, parent.width, parent.height);
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, settings.filter ? GL_LINEAR : GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, settings.filter ? GL_LINEAR : GL_NEAREST);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, parent.width, 0, parent.height, -1.0, 1.0);
glViewport(0, 0, parent.width, parent.height);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPixelStorei(GL_UNPACK_ROW_LENGTH, glwidth);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, settings.width, settings.height,
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, glbuffer);
double w = (double)settings.width / (double)glwidth;
double h = (double)settings.height / (double)glheight;
signed u = parent.width;
signed v = parent.height;
glBegin(GL_TRIANGLE_STRIP);
glTexCoord2f(0, 0); glVertex3i(0, v, 0);
glTexCoord2f(w, 0); glVertex3i(u, v, 0);
glTexCoord2f(0, h); glVertex3i(0, 0, 0);
glTexCoord2f(w, h); glVertex3i(u, 0, 0);
glEnd();
glFlush();
if(settings.isDoubleBuffered) glXSwapBuffers(display, glxwindow);
}
auto init() -> bool {
display = XOpenDisplay(0);
screen = DefaultScreen(display);
signed versionMajor = 0, versionMinor = 0;
glXQueryVersion(display, &versionMajor, &versionMinor);
if(versionMajor < 1 || (versionMajor == 1 && versionMinor < 2)) return false;
XWindowAttributes windowAttributes;
XGetWindowAttributes(display, settings.handle, &windowAttributes);
signed attributeList[] = {
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
GLX_RENDER_TYPE, GLX_RGBA_BIT,
GLX_DOUBLEBUFFER, True,
GLX_RED_SIZE, 8,
GLX_GREEN_SIZE, 8,
GLX_BLUE_SIZE, 8,
None
};
signed fbCount = 0;
auto fbConfig = glXChooseFBConfig(display, screen, attributeList, &fbCount);
if(fbCount == 0) return false;
auto vi = glXGetVisualFromFBConfig(display, fbConfig[0]);
colormap = XCreateColormap(display, RootWindow(display, vi->screen), vi->visual, AllocNone);
XSetWindowAttributes attributes;
attributes.colormap = colormap;
attributes.border_pixel = 0;
xwindow = XCreateWindow(display, settings.handle, 0, 0, windowAttributes.width, windowAttributes.height,
0, vi->depth, InputOutput, vi->visual, CWColormap | CWBorderPixel, &attributes);
XSetWindowBackground(display, xwindow, 0);
XMapWindow(display, xwindow);
XFlush(display);
while(XPending(display)) {
XEvent event;
XNextEvent(display, &event);
}
glxcontext = glXCreateContext(display, vi, 0, GL_TRUE);
glXMakeCurrent(display, glxwindow = xwindow, glxcontext);
glXSwapInterval = (signed (*)(signed))glGetProcAddress("glXSwapIntervalEXT");
if(!glXSwapInterval) glXSwapInterval = (signed (*)(signed))glGetProcAddress("glXSwapIntervalMESA");
if(!glXSwapInterval) glXSwapInterval = (signed (*)(signed))glGetProcAddress("glXSwapIntervalSGI");
if(glXSwapInterval) glXSwapInterval(settings.synchronize);
signed value = 0;
glXGetConfig(display, vi, GLX_DOUBLEBUFFER, &value);
settings.isDoubleBuffered = value;
settings.isDirect = glXIsDirect(display, glxcontext);
glDisable(GL_ALPHA_TEST);
glDisable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
glDisable(GL_POLYGON_SMOOTH);
glDisable(GL_STENCIL_TEST);
glEnable(GL_DITHER);
glEnable(GL_TEXTURE_2D);
resize(256, 256);
return true;
}
auto term() -> void {
if(gltexture) {
glDeleteTextures(1, &gltexture);
gltexture = 0;
}
if(glbuffer) {
delete[] glbuffer;
glbuffer = 0;
}
glwidth = 0;
glheight = 0;
if(glxcontext) {
glXDestroyContext(display, glxcontext);
glxcontext = nullptr;
}
if(xwindow) {
XUnmapWindow(display, xwindow);
xwindow = 0;
}
if(colormap) {
XFreeColormap(display, colormap);
colormap = 0;
}
if(display) {
XCloseDisplay(display);
display = nullptr;
}
}
private:
GLuint gltexture = 0;
uint32_t* glbuffer = nullptr;
unsigned glwidth = 0;
unsigned glheight = 0;
auto resize(unsigned width, unsigned height) -> void {
settings.width = width;
settings.height = height;
if(gltexture == 0) glGenTextures(1, &gltexture);
glwidth = max(glwidth, width);
glheight = max(glheight, height);
if(glbuffer) delete[] glbuffer;
glbuffer = new uint32_t[glwidth * glheight]();
glBindTexture(GL_TEXTURE_2D, gltexture);
glPixelStorei(GL_UNPACK_ROW_LENGTH, glwidth);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, glwidth, glheight, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, glbuffer);
}
};