#include "qtofflinegl.h" #include #include //----------------------------------------------------------------------------- #if 0 // was _WIN32, this function not used static void swapRedBlueChannels( void *buffer, int bufferSize) // Flips The Red And Blue Bytes (WidthxHeight) { void *b = buffer; // Pointer To The Buffer #ifdef x64 int size = bufferSize; UCHAR *pix = (UCHAR *)b; while (size > 0) { UCHAR r = *pix; UCHAR b = *(pix + 2); *pix = b; *(pix + 2) = r; pix += 4; size--; } #else __asm // Assembler Code To Follow { mov ecx, bufferSize // Counter Set To Dimensions Of Our Memory Block mov ebx, b // Points ebx To Our Data (b) label: // Label Used For Looping mov al,[ebx+0] // Loads Value At ebx Into al mov ah,[ebx+2] // Loads Value At ebx+2 Into ah mov [ebx+2],al // Stores Value In al At ebx+2 mov [ebx+0],ah // Stores Value In ah At ebx add ebx,4 // Moves Through The Data By 4 Bytes dec ecx // Decreases Our Loop Counter jnz label // If Not Zero Jump Back To Label } #endif } #endif //----------------------------------------------------------------------------- #if defined(MACOSX) #if defined(powerpc) void rightRotateBits(UCHAR *buf, int bufferSize) { UINT *buffer = (UINT *)buf; UINT app; for (int i = 0; i < bufferSize; i++, buffer++) { app = *buffer; *buffer = app >> 8 | app << 24; } } #else void rightRotateBits(UCHAR *buf, int bufferSize) { UINT *buffer = (UINT *)buf; UINT app; for (int i = 0; i < bufferSize; i++, buffer++) { app = *buffer; *buffer = (app >> 16 & 0x000000ff) | (app << 16 & 0x00ff0000) | (app & 0xff00ff00); } } #endif #endif //----------------------------------------------------------------------------- //============================================================================= // QtOfflineGL : implem. offlineGL usando QT //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- QtOfflineGL::QtOfflineGL(TDimension rasterSize, std::shared_ptr shared) : TOfflineGL::Imp(rasterSize.lx, rasterSize.ly) , m_context(0) , m_oldContext(0) { createContext(rasterSize, std::move(shared)); /* makeCurrent(); glClearColor(0.0f,0.0f,0.0f,0.0f); glClear(GL_COLOR_BUFFER_BIT); doneCurrent(); */ } //----------------------------------------------------------------------------- QtOfflineGL::~QtOfflineGL() {} //----------------------------------------------------------------------------- void QtOfflineGL::createContext(TDimension rasterSize, std::shared_ptr shared) { // Imposto il formato dei Pixel (pixelFormat) /* 32, // 32-bit color depth 0, 0, 0, 0, 0, 0, // color bits ignored 8, // no alpha buffer 0, // shift bit ignored 0, // no accumulation buffer 0, 0, 0, 0, // accum bits ignored 32, // 32-bit z-buffer 32, // max stencil buffer 0, // no auxiliary buffer PFD_MAIN_PLANE, // main layer 0, // reserved 0, 0, 0 // layer masks ignored ATTENZIONE !! SU MAC IL FORMATO E' DIVERSO (casomai possiamo mettere un ifdef) SPECIFICHE MAC = depth_size 24, stencil_size 8, alpha_size 1 */ QGLFormat fmt; #if defined(_WIN32) fmt.setAlphaBufferSize(8); fmt.setAlpha(true); fmt.setRgba(true); fmt.setDepthBufferSize(32); fmt.setDepth(true); fmt.setStencilBufferSize(32); fmt.setStencil(true); fmt.setAccum(false); fmt.setPlane(0); #elif defined(MACOSX) fmt = QGLFormat::defaultFormat(); // printf("GL Version: %s\n",glGetString(GL_VERSION)); fmt.setVersion(2, 1); /* OSX10.8 では 3.2 だめかも */ #if 0 fmt.setAlphaBufferSize(8); fmt.setAlpha(true); fmt.setRgba(true); fmt.setDepthBufferSize(32); fmt.setDepth(true); fmt.setStencilBufferSize(8); fmt.setStencil(true); fmt.setAccum(false); fmt.setPlane(0); fmt.setDirectRendering(false); #endif #elif defined(LINUX) || defined(FREEBSD) fmt = QGLFormat::defaultFormat(); // printf("GL Version: %s\n",glGetString(GL_VERSION)); fmt.setVersion(2, 1); /* XXX? */ #endif QSurfaceFormat format; format.setProfile(QSurfaceFormat::CompatibilityProfile); m_surface = std::make_shared(); m_surface->setFormat(format); m_surface->create(); m_context = std::make_shared(); m_context->setFormat(format); m_context->create(); m_context->makeCurrent(m_surface.get()); QOpenGLFramebufferObjectFormat fbo_format; fbo_format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); m_fbo = std::make_shared(rasterSize.lx, rasterSize.ly, fbo_format); m_fbo->bind(); printf("create context:%p [thread:0x%x]\n", m_context.get(), (unsigned int)(size_t)QThread::currentThreadId()); // Creo il contesto OpenGL - assicurandomi che sia effettivamente creato // NOTA: Se il contesto non viene creato, di solito basta ritentare qualche // volta. } //----------------------------------------------------------------------------- void QtOfflineGL::makeCurrent() { if (m_context) { m_context->moveToThread(QThread::currentThread()); m_context->makeCurrent(m_surface.get()); } } //----------------------------------------------------------------------------- void QtOfflineGL::doneCurrent() { if (m_context) { m_context->moveToThread(0); m_context->doneCurrent(); } } //----------------------------------------------------------------------------- void QtOfflineGL::saveCurrentContext() { // m_oldContext = const_cast(QGLContext::currentContext()); } //----------------------------------------------------------------------------- void QtOfflineGL::restoreCurrentContext() { // if(m_oldContext) m_oldContext->makeCurrent(); // m_oldContext = 0; } //----------------------------------------------------------------------------- void QtOfflineGL::getRaster(TRaster32P raster) { makeCurrent(); glFlush(); int lx = raster->getLx(); int ly = raster->getLy(); raster->lock(); raster->copy(TRaster32P(lx, ly, m_fbo->width(), (TPixelRGBM32 *)m_fbo->toImage(false).bits(), false)); raster->unlock(); } // QGLPixelBuffer::hasOpenGLPbuffers() (statica) -> true se la scheda supporta i // PBuffer //============================================================================= // QtOfflineGLPBuffer : implem. offlineGL usando QT e PBuffer //----------------------------------------------------------------------------- QtOfflineGLPBuffer::QtOfflineGLPBuffer(TDimension rasterSize) : TOfflineGL::Imp(rasterSize.lx, rasterSize.ly), m_context(0) { createContext(rasterSize); makeCurrent(); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT); doneCurrent(); } //----------------------------------------------------------------------------- QtOfflineGLPBuffer::~QtOfflineGLPBuffer() {} //----------------------------------------------------------------------------- void QtOfflineGLPBuffer::createContext(TDimension rasterSize) { // Imposto il formato dei Pixel (pixelFormat) /* 32, // 32-bit color depth 0, 0, 0, 0, 0, 0, // color bits ignored 8, // no alpha buffer 0, // shift bit ignored 0, // no accumulation buffer 0, 0, 0, 0, // accum bits ignored 32, // 32-bit z-buffer 32, // max stencil buffer 0, // no auxiliary buffer PFD_MAIN_PLANE, // main layer 0, // reserved 0, 0, 0 // layer masks ignored ATTENZIONE !! SU MAC IL FORMATO E' DIVERSO (casomai possiamo mettere un ifdef) SPECIFICHE MAC = depth_size 24, stencil_size 8, alpha_size 1 */ QGLFormat fmt; #if defined(_WIN32) fmt.setAlphaBufferSize(8); fmt.setAlpha(false); fmt.setRgba(true); fmt.setDepthBufferSize(32); fmt.setDepth(true); fmt.setStencilBufferSize(32); fmt.setStencil(true); fmt.setAccum(false); fmt.setPlane(0); #elif defined(MACOSX) fmt.setAlphaBufferSize(1); fmt.setAlpha(false); fmt.setRgba(true); fmt.setDepthBufferSize(24); fmt.setDepth(true); fmt.setStencilBufferSize(8); fmt.setStencil(true); fmt.setAccum(false); fmt.setPlane(0); #elif defined(LINUX) || defined(FREEBSD) fmt.setAlphaBufferSize(1); fmt.setAlpha(false); fmt.setRgba(true); fmt.setDepthBufferSize(24); fmt.setDepth(true); fmt.setStencilBufferSize(8); fmt.setStencil(true); fmt.setAccum(false); fmt.setPlane(0); #endif // Il PixelBuffer deve essere con width ed height potenze di 2 int sizeMax = std::max(rasterSize.lx, rasterSize.ly); // trovo la potenza di 2 che "contiene" sizeMax e la utilizzo per il PBuffer int pBufferSize = 2; while (pBufferSize < sizeMax) pBufferSize *= 2; m_context = std::make_shared(QSize(pBufferSize, pBufferSize), fmt); } //----------------------------------------------------------------------------- void QtOfflineGLPBuffer::makeCurrent() { if (m_context) { m_context->makeCurrent(); } } //----------------------------------------------------------------------------- void QtOfflineGLPBuffer::doneCurrent() { if (m_context) m_context->doneCurrent(); } //----------------------------------------------------------------------------- void QtOfflineGLPBuffer::getRaster(TRaster32P raster) { makeCurrent(); glFlush(); // The image is stored using a 32-bit ARGB format (0xAARRGGBB). QImage image = m_context->toImage(); int lx = raster->getLx(), ly = raster->getLy(); static const TRaster32P emptyRaster; if (image.height() == 0 || image.width() == 0) return; // devo iniziare a leggere la Y da un certo offset // dato dalla differenza tra la y della image e la y del raster int yOffset = image.height() - ly; raster->lock(); for (int y = 0; y < ly; y++) { QRgb *inpPix = (QRgb *)image.scanLine(yOffset + y); TPixel32 *pix = raster->pixels(ly - 1 - y); TPixel32 *endPix = pix + lx; for (; pix < endPix; ++pix) { pix->m = 255; pix->r = qRed(*inpPix); pix->g = qGreen(*inpPix); pix->b = qBlue(*inpPix); inpPix++; } } raster->unlock(); }