#ifdef __APPLE__ #include #endif namespace ruby { class pVideoQtOpenGL { public: QWidget *parent; QVBoxLayout *layout; class RubyGLWidget : public QGLWidget { public: GLuint texture; unsigned textureWidth, textureHeight; uint32_t *buffer; unsigned rasterWidth, rasterHeight; bool synchronize; unsigned filter; void resize(unsigned width, unsigned height) { if(width > textureWidth || height > textureHeight) { textureWidth = max(width, textureWidth); textureHeight = max(height, textureHeight); if(buffer) { delete[] buffer; glDeleteTextures(1, &texture); } buffer = new uint32_t[textureWidth * textureHeight]; glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); glPixelStorei(GL_UNPACK_ROW_LENGTH, textureWidth); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, textureWidth, textureHeight, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, buffer); } } void updateSynchronization() { #ifdef __APPLE__ makeCurrent(); CGLContextObj context = CGLGetCurrentContext(); GLint value = synchronize; //0 = draw immediately (no vsync), 1 = draw once per frame (vsync) CGLSetParameter(context, kCGLCPSwapInterval, &value); #endif } void paintGL() { unsigned outputWidth = width(); unsigned outputHeight = height(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, outputWidth, 0, outputHeight, -1.0, 1.0); glViewport(0, 0, outputWidth, outputHeight); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (filter == Video::FilterPoint) ? GL_NEAREST : GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (filter == Video::FilterPoint) ? GL_NEAREST : GL_LINEAR); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, rasterWidth, rasterHeight, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, buffer); double w = (double)rasterWidth / (double)textureWidth; double h = (double)rasterHeight / (double)textureHeight; unsigned u = outputWidth; unsigned v = outputHeight; 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(); } void initializeGL() { format().setDoubleBuffer(true); texture = 0; textureWidth = 0; textureHeight = 0; buffer = 0; resize(rasterWidth = 256, rasterHeight = 256); 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); glClearColor(0.0, 0.0, 0.0, 0.0); } } *widget; bool cap(const string& name) { if(name == Video::Synchronize) return true; if(name == Video::Filter) return true; if(name == "QWidget") return true; return false; } any get(const string& name) { if(name == Video::Synchronize) return widget->synchronize; if(name == Video::Filter) return widget->filter; if(name == "QWidget") return parent; return false; } bool set(const string& name, const any& value) { if(name == Video::Synchronize) { widget->synchronize = any_cast(value); widget->updateSynchronization(); return true; } if(name == Video::Filter) { widget->filter = any_cast(value); return true; } if(name == "QWidget") { parent = any_cast(value); return true; } return false; } bool lock(uint32_t *&data, unsigned &pitch, unsigned width, unsigned height) { widget->resize(width, height); widget->rasterWidth = width; widget->rasterHeight = height; pitch = widget->textureWidth * sizeof(uint32_t); return data = widget->buffer; } void unlock() { } void clear() { memset(widget->buffer, 0, widget->textureWidth * widget->textureHeight * sizeof(uint32_t)); widget->updateGL(); } void refresh() { widget->updateGL(); } bool init() { layout = new QVBoxLayout; layout->setMargin(0); widget = new RubyGLWidget; widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); layout->addWidget(widget); parent->setLayout(layout); return true; } void term() { } }; DeclareVideo(QtOpenGL) };