Update to bsnes v028 01 release.

[No changelog available]
This commit is contained in:
byuu 2008-02-06 22:58:42 +00:00
parent 926ffd9695
commit 8b7219bdef
3 changed files with 106 additions and 83 deletions

View File

@ -270,8 +270,8 @@ build: $(objects)
$(strip $(cpp) $(call mkbin,../bsnes) $(objects) $(link)) $(strip $(cpp) $(call mkbin,../bsnes) $(objects) $(link))
install: install:
install -m 755 ../bsnes $(prefix)/bin/bsnes install -D -m 755 ../bsnes $(prefix)/bin/bsnes
install -m 644 data/bsnes.png $(prefix)/share/icons/bsnes.png install -D -m 644 data/bsnes.png $(prefix)/share/icons/bsnes.png
clean: clean:
-@$(call delete,obj/*.$(obj)) -@$(call delete,obj/*.$(obj))

View File

@ -1,4 +1,4 @@
#define BSNES_VERSION "0.028" #define BSNES_VERSION "0.028.01"
#define BSNES_TITLE "bsnes v" BSNES_VERSION #define BSNES_TITLE "bsnes v" BSNES_VERSION
#define BUSCORE sBus #define BUSCORE sBus

View File

@ -1,3 +1,28 @@
/*
video.glx
author: byuu
license: public domain
date: 2008-02-06
Design notes:
SGI's GLX is the X11/Xlib interface to OpenGL.
At the time of this writing, there are three relevant versions of the API: versions 1.2, 1.3 and 1.4.
Version 1.2 was released on March 4th, 1997.
Version 1.3 was released on October 19th, 1998.
Version 1.4 was released on December 16th, 2005.
Despite version 1.3 being roughly ten years old at this time, there are still many modern X11 GLX drivers
that lack full support for the specification. Most notable would be the official video drivers from ATI.
Given this, 1.4 support is pretty much hopeless to target.
Luckily, each version has been designed to be backwards compatible with the previous version. As well,
version 1.2 is wholly sufficient, albeit less convenient, to implement this video module.
Therefore, for the purpose of compatibility, this driver only uses GLX 1.2 or earlier API commands.
As well, it only uses raw Xlib API commands, so that it is compatible with any toolkit.
*/
#include <GL/gl.h> #include <GL/gl.h>
#include <GL/glx.h> #include <GL/glx.h>
@ -7,6 +32,11 @@ namespace ruby {
#include "glx.h" #include "glx.h"
//returns true once window is mapped (created and displayed onscreen)
static Bool x_wait_for_map_notify(Display *d, XEvent *e, char *arg) {
return (e->type == MapNotify) && (e->xmap.window == (Window)arg);
}
class pVideoGLX { class pVideoGLX {
public: public:
VideoGLX &self; VideoGLX &self;
@ -14,19 +44,15 @@ public:
Display *display; Display *display;
int screen; int screen;
XWindowAttributes attributes; Window xwindow;
GLXFBConfig fbconfig, *fbconfiglist;
GLXContext glxcontext; GLXContext glxcontext;
GLXWindow glxwindow; GLXWindow glxwindow;
GLuint gltexture; GLuint gltexture;
struct { struct {
int version_major, version_minor;
bool double_buffer; bool double_buffer;
unsigned buffer_size; bool is_direct;
unsigned red_size;
unsigned green_size;
unsigned blue_size;
unsigned alpha_size;
} glx; } glx;
struct { struct {
@ -74,11 +100,17 @@ public:
if(glx.double_buffer) glXSwapBuffers(display, glxwindow); if(glx.double_buffer) glXSwapBuffers(display, glxwindow);
} }
void refresh(unsigned width_, unsigned height_) { void refresh(unsigned width, unsigned height) {
XGetWindowAttributes(display, settings.handle, &attributes); //we must ensure that the child window is the same size as the parent window.
//unfortunately, we cannot hook the parent window resize event notification,
glClearColor(0.0, 0.0, 0.0, 1.0); //as we did not create the parent window, nor have any knowledge of the toolkit used.
glClear(GL_COLOR_BUFFER_BIT); //therefore, inelegant as it may be, we query each window size and resize as needed.
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_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
@ -89,24 +121,24 @@ public:
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
glLoadIdentity(); glLoadIdentity();
glOrtho(0, attributes.width, 0, attributes.height, -1.0, 1.0); glOrtho(0, parent.width, 0, parent.height, -1.0, 1.0);
glViewport(0, 0, attributes.width, attributes.height); glViewport(0, 0, parent.width, parent.height);
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glLoadIdentity(); glLoadIdentity();
glPixelStorei(GL_UNPACK_ROW_LENGTH, 1024); //length of buffer in pixels glPixelStorei(GL_UNPACK_ROW_LENGTH, 1024); //length of buffer in pixels
glTexSubImage2D(GL_TEXTURE_2D, glTexSubImage2D(GL_TEXTURE_2D,
/* mip-map level = */ 0, /* x = */ 0, /* y = */ 0, /* mip-map level = */ 0, /* x = */ 0, /* y = */ 0,
width_, height_, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, buffer); width, height, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, buffer);
//OpenGL projection sets 0,0 as *bottom-left* of screen //OpenGL projection sets 0,0 as *bottom-left* of screen.
//Therefore, below vertices flip image to support top-left source //therefore, below vertices flip image to support top-left source.
//Texture range = x1:0.0, y1:0.0, x2:1.0, y2:1.0 //texture range = x1:0.0, y1:0.0, x2:1.0, y2:1.0
//Vertex range = x1:0, y1:0, x2:width, y2:height //vertex range = x1:0, y1:0, x2:width, y2:height
double w = double(width_) / 1024.0; double w = double(width) / 1024.0;
double h = double(height_) / 1024.0; double h = double(height) / 1024.0;
int u = attributes.width; int u = parent.width;
int v = attributes.height; int v = parent.height;
glBegin(GL_TRIANGLE_STRIP); glBegin(GL_TRIANGLE_STRIP);
glTexCoord2f(0, 0); glVertex3i(0, v, 0); glTexCoord2f(0, 0); glVertex3i(0, v, 0);
glTexCoord2f(w, 0); glVertex3i(u, v, 0); glTexCoord2f(w, 0); glVertex3i(u, v, 0);
@ -119,75 +151,60 @@ public:
} }
bool init() { bool init() {
buffer = new(zeromemory) uint16_t[1024 * 1024 * 4];
//GLX requires a compatible X11 visualid to render to.
//glXChooseFBConfig often chooses visualid that is not
//compatible with target X11 window's visualid.
//Therefore, iterate all available framebuffer configurations
//to locate matching visualid.
display = XOpenDisplay(0); display = XOpenDisplay(0);
screen = DefaultScreen(display); screen = DefaultScreen(display);
XGetWindowAttributes(display, settings.handle, &attributes); glXQueryVersion(display, &glx.version_major, &glx.version_minor);
//require GLX 1.2+ API
if(glx.version_major < 1 || (glx.version_major == 1 && glx.version_minor < 2)) return false;
buffer = new(zeromemory) uint16_t[1024 * 1024 * sizeof(uint16_t)];
XWindowAttributes wa;
XGetWindowAttributes(display, settings.handle, &wa);
//let GLX determine the best Visual to use for GL output; provide a few hints
int elements = 0; int elements = 0;
fbconfig = 0; int attributelist[] = {
fbconfiglist = glXGetFBConfigs(display, screen, &elements); GLX_RGBA,
for(int i = 0; i < elements; i++) { GLX_DOUBLEBUFFER, True,
int visualid = 0; None
glXGetFBConfigAttrib(display, fbconfiglist[i], GLX_VISUAL_ID, &visualid); };
if(visualid == attributes.visual->visualid) { XVisualInfo *vi = glXChooseVisual(display, screen, attributelist);
fbconfig = fbconfiglist[i];
break;
}
}
if(!fbconfig) { //Window settings.handle has already been realized, most likely with DefaultVisual.
fprintf(stderr, "VideoGLX: failed to find compatible Visual ID\n"); //GLX requires that the GL output window has the same Visual as the GLX context.
term(); //it is not possible to change the Visual of an already realized (created) window.
return false; //therefore a new child window, using the same GLX Visual, must be created and binded to settings.handle.
} Colormap colormap = XCreateColormap(display, RootWindow(display, vi->screen), vi->visual, AllocNone);
XSetWindowAttributes swa;
swa.colormap = colormap;
swa.border_pixel = 0;
swa.event_mask = StructureNotifyMask;
xwindow = XCreateWindow(display, /* parent = */ settings.handle,
/* x = */ 0, /* y = */ 0, wa.width, wa.height,
/* border_width = */ 0, vi->depth, InputOutput, vi->visual,
CWColormap | CWBorderPixel | CWEventMask, &swa);
XMapWindow(display, xwindow);
XEvent event;
XIfEvent(display, &event, x_wait_for_map_notify, (char*)xwindow); //wait for window to appear onscreen
glxcontext = glXCreateNewContext(display, fbconfig, GLX_RGBA_TYPE, 0, false); glxcontext = glXCreateContext(display, vi, /* sharelist = */ 0, /* direct = */ GL_TRUE);
if(!glxcontext) { glXMakeCurrent(display, glxwindow = xwindow, glxcontext);
fprintf(stderr, "VideoGLX: failed to create context\n");
term();
return false;
}
glxwindow = glXCreateWindow(display, fbconfig, settings.handle, 0); //read attributes of frame buffer for later use, as requested attributes from above are not always granted
if(!glxwindow) {
fprintf(stderr, "VideoGLX: failed to create window\n");
term();
return false;
}
if(glXMakeContextCurrent(display, glxwindow, glxwindow, glxcontext) == false) {
fprintf(stderr, "VideoGLX: failed to set context\n");
term();
return false;
}
//read attributes of frame buffer for later use
int value = 0; int value = 0;
glXGetFBConfigAttrib(display, fbconfig, GLX_DOUBLEBUFFER, &value); glXGetConfig(display, vi, GLX_DOUBLEBUFFER, &value);
glx.double_buffer = value; glx.double_buffer = value;
glXGetFBConfigAttrib(display, fbconfig, GLX_BUFFER_SIZE, &value); glx.is_direct = glXIsDirect(display, glxcontext);
glx.buffer_size = value;
glXGetFBConfigAttrib(display, fbconfig, GLX_RED_SIZE, &value);
glx.red_size = value;
glXGetFBConfigAttrib(display, fbconfig, GLX_GREEN_SIZE, &value);
glx.green_size = value;
glXGetFBConfigAttrib(display, fbconfig, GLX_BLUE_SIZE, &value);
glx.blue_size = value;
glXGetFBConfigAttrib(display, fbconfig, GLX_ALPHA_SIZE, &value);
glx.alpha_size = value;
//disable unused features, enable required features //disable unused features
glDisable(GL_ALPHA_TEST);
glDisable(GL_BLEND); glDisable(GL_BLEND);
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
glDisable(GL_POLYGON_SMOOTH); glDisable(GL_POLYGON_SMOOTH);
glDisable(GL_STENCIL_TEST);
//enable useful and required features
glEnable(GL_DITHER); glEnable(GL_DITHER);
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
@ -215,15 +232,21 @@ public:
glxcontext = 0; glxcontext = 0;
} }
delete[] buffer; if(buffer) {
delete[] buffer;
buffer = 0;
}
} }
pVideoGLX(VideoGLX &self_) : self(self_) { pVideoGLX(VideoGLX &self_) : self(self_) {
settings.handle = 0; settings.handle = 0;
xwindow = 0;
glxcontext = 0; glxcontext = 0;
glxwindow = 0; glxwindow = 0;
gltexture = 0; gltexture = 0;
} }
~pVideoGLX() { term(); }
}; };
bool VideoGLX::cap(Setting setting) { return p.cap(setting); } bool VideoGLX::cap(Setting setting) { return p.cap(setting); }