[PyQt] max texture size for QGLWidget.bindTexture?

Brian Parma freecode at cox.net
Wed Sep 10 02:11:47 BST 2008


David Boddie wrote:
> On Tue Sep 9 00:28:49 BST 2008, Brian Parma wrote:
>
>   
>> Thanks for the response, that's a good find, although I'm trying to
>> figure out how to interpret the result.  On my laptop it returns 2048,
>> but how does that translate into resolution?  I thought it was memory
>> size at first, but changing formats from RGB8 to RGB4 doesn't let me use
>> larger textures.  Right now I take a screen cap which is 1024 x 768, and
>> I then scale it down with QPixmap.scaledToWidth.  I've been playing with
>> the width to try and find the limit, and it seems to be between 650 and
>> 700 pixels wide.
>>     
>
> OK, so it won't even show the full width of 1024 pixels? It sounds like it
> isn't just a problem with the texture not having dimensions that aren't a
> power of 2 because 1024 would obviously be fine.
>
> I would imagine that this is an OpenGL problem rather than a Qt problem, but
> you would have to try using native/Python arrays rather than a QPixmap to
> test that theory. It might be worth creating a small test program that
> illustrates this problem and posting on the PyOpenGL mailing list:
>
>   http://sourceforge.net/mail/?group_id=5988
>
> It could be the case that your hardware/driver has problems with textures
> larger than a certain size, even though it claims to support them. Can you
> say what platform, hardware and driver you are using?
>
> David
> _______________________________________________
> PyQt mailing list    PyQt at riverbankcomputing.com
> http://www.riverbankcomputing.com/mailman/listinfo/pyqt
> ------------------------------------------------------------------------
Ok, so I stripped down the program a little to make it into something of 
a demonstration of the problem. 
I'm running this on an Asus s5n laptop with XP Pro (SP3).  The graphics 
controller is an "Intel 82852/82855 GM/GME" 6.14.10.3865. (yea it's a 
little old)
PyQt 4.4.3, PyOpenGL 3.0.0b5

I haven't tried using OpenGL's texture loading functions, I'm not real 
experienced with OpenGL programming (this is my first gl program) so I 
have just been using PyQt4's QGLWidget's bindTexture, and passing it a 
QPixmap.scaled. 

In the program, I made it so pressing 'S' will prompt for a new width to 
scale too, entering 640 works fine, but anything above that causes the 
weird behavior (on this computer).  What is really strange is that 
scaling the image to 641 looks the same as scaling it to 1024, and it 
doesn't change again until you scale over 1024.


-------------- next part --------------
from __future__ import division
from PyQt4.QtCore import QPointF, QRectF, SIGNAL, Qt, QTimer, QPoint
from PyQt4.QtGui import QWidget, QApplication, QPushButton, QPainter, QPixmap, QColor, QImage, QInputDialog
from PyQt4.QtOpenGL import QGLWidget
from OpenGL.GL import *
from OpenGL.GLU import gluPerspective
import sys

class testGL(QGLWidget):
    DIR_RIGHT, DIR_UP, DIR_LEFT, DIR_DOWN = 0, 1, 2, 3
    MODE_SLIDE,  MODE_SPIN = 0, 1
    coords = (( ( -1, +1, +1 ), ( -1, -1, +1 ), ( +1, -1, +1 ), ( +1, +1, +1 ) ),
                      ( ( +1, +1, +1 ), ( +1, -1, +1 ), ( +1, -1, -1 ), ( +1, +1, -1 ) ),
                      ( ( +1, +1, -1 ), ( +1, -1, -1 ), ( -1, -1, -1 ), ( -1, +1, -1 ) ),
                      ( ( -1, +1, -1 ), ( -1, -1, -1 ), ( -1, -1, +1 ), ( -1, +1, +1 ) ),
                      ( ( -1, +1, -1 ), ( -1, +1, +1 ), ( +1, +1, +1 ), ( +1, +1, -1 ) ),
                      ( ( -1, -1, +1 ), ( -1, -1, -1 ), ( +1, -1, -1 ), ( +1, -1, +1 ) ),
                      ( ( -1, +1, 0 ), ( -1, -1, 0 ), ( +1, -1, 0 ), ( +1, +1, 0) ),)
    tcoords = ((0, 1), (0, 0), (1, 0), (1, 1))
    def __init__(self, parent, shared, style, cb=None):
        QGLWidget.__init__(self, parent, shared, style)
        self.textures = [0, 0, 0, 0, 0, 0, 0]
        self.RM = None
        self.dx, self.dy, self.dz = 0, 0, 0
        self.ang = 4 / 16.0
        self.glists = []
        self.mode = testGL.MODE_SPIN
        self.h, self.w = 1, 1
        self.sc = 1.0 # scale
        self.ortho = False
        self.callback = cb
        
        
        
    
    def translate(self, dx, dy, dz=0):
        self.dx = (self.dx + dx/self.w*2*self.sc)
        self.dy = (self.dy + dy/self.h*2*self.sc)
        self.dz = (self.dz + dz/self.h*2*self.sc)
        self.updateGL()

    def rotate(self, dx, dy):
        dx = dx*self.ang
        dy = dy*self.ang
        glLoadIdentity()
        
        glRotatef(dx, 0.0, 1.0, 0.0)
        glRotatef(dy, 1.0, 0.0, 0.0)
        glMultMatrixf(self.RM)
        self.RM = glGetFloatv(GL_MODELVIEW_MATRIX)
        self.updateGL()
       
    def initializeGL(self):
        glEnable(GL_TEXTURE_2D)
        glEnable(GL_CULL_FACE)
        glEnable(GL_DEPTH_TEST)
        self.context().setTextureCacheLimit(131072) # 128 megs
        print glGetIntegerv(GL_MAX_TEXTURE_SIZE)
        sc = self.sc
        
        glLoadIdentity()
        self.RM = glGetFloatv(GL_MODELVIEW_MATRIX)

        lst = glGenLists(2)
        self.glist = [lst, lst+1]
        
        # list 1
        glNewList(self.glist[0], GL_COMPILE)
        glBegin(GL_QUADS)
        
        dz = ((0, 0), (-2, 0), (2, 0), (0, -2), (0, 2))
        for i in range(5):
            for j in range(4):
                glTexCoord2d(self.tcoords[j][0], self.tcoords[j][1])
                glVertex3d(sc*(self.coords[0][j][0] + dz[i][0]), 
                                sc*(self.coords[0][j][1] + dz[i][1]), sc*self.coords[0][j][2])
        
        glEnd()
        glEndList()
        
        # list 2
        #sc = 1.0
        glNewList(self.glist[1], GL_COMPILE)
        glBegin(GL_QUADS)
        
        for i in range(6):
            for j in range(4):
                glTexCoord2d(self.tcoords[j][0], self.tcoords[j][1])
                glVertex3d(sc*self.coords[i][j][0], 
                                sc*self.coords[i][j][1], sc*self.coords[i][j][2])
                                
        glEnd()
        glEndList()
        

        
    def paintGL(self):
#        self.qglClearColor(QColor('white'))
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        glLoadIdentity()
        
        # Object
        glPushMatrix()
        if self.textures[0]:
            glBindTexture(GL_TEXTURE_2D, self.textures[0])
        glTranslated(0.0, 0.0,  -1.0 - 2.0*self.sc) # put into view
        glTranslated(self.dx, self.dy,self.dz)
        glMultMatrixf(self.RM)                  # Rotation
        glCallList(self.glist[self.mode])
        glPopMatrix()
        
        
    def resizeGL(self, width, height):
        self.w, self.h = width, height
        glViewport(0, 0, width, height)
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        sc = self.sc
        r = width/height
        if self.ortho:
            glOrtho(-sc*r, +sc*r, -sc, +sc, -50, 50)
        else:            
            gluPerspective(53.13, r, 1.0, 100.0)
        glMatrixMode(GL_MODELVIEW)
        
    def mousePressEvent(self, event):
        self.cpos = QPointF(event.pos())
        self.button = event.button()
        
    def mouseMoveEvent(self, event):      
        dx = event.x() - self.cpos.x()
        dy = event.y() - self.cpos.y()
        
        if self.button == Qt.RightButton:
            self.translate(dx, -dy)
        elif self.button == Qt.MidButton:
            self.translate(0, 0, -dy)
        else:
            self.rotate(dx, dy)
        self.cpos = QPointF(event.pos())

    def keyPressEvent(self, event):
        if (event.key() == Qt.Key_Escape) or (event.key() == Qt.Key_Q):
            self.close()

        if event.key() == Qt.Key_T: # toggle mode
            if self.mode == testGL.MODE_SLIDE:
                self.mode = testGL.MODE_SPIN
            else:
                self.mode = testGL.MODE_SLIDE                
            self.updateGL()
            
        if event.key() == Qt.Key_V: # toggle ortho
            self.ortho = not self.ortho
            self.resizeGL(self.w,self.h)
            self.updateGL()
            
        if event.key() == Qt.Key_R: # reset position
            glLoadIdentity()
            self.RM = glGetFloatv(GL_MODELVIEW_MATRIX)
            self.dx,self.dy,self.dz = 0,0,0
            self.updateGL()
            
        if event.key() == Qt.Key_S: # rescale
            sz,ok = QInputDialog.getInteger(self,"Input Width","Width:",640,10,5000,1)
            if ok:
                print 'resize to w: %d' % sz
                self.callback(sz)
                self.updateGL()
class test:
    def __init__(self):
        
        self.pix = testGL(None, None, Qt.FramelessWindowHint, self.getScreen)
        self.pix.resize(600, 400)
        self.pix.move(QPoint(0, 0))
        self.pix.show()
        self.getScreen()

        
    def getScreen(self, sz=640):
        self.pm = QPixmap.grabWindow(QApplication.desktop().winId())   
        if self.pix.textures[0]:
            self.pix.deleteTexture(self.pix.textures[0])
        
        self.pix.textures[0] = self.pix.bindTexture(self.pm.scaledToWidth(sz,Qt.FastTransformation),GL_TEXTURE_2D,GL_RGB8)
        
    


if __name__ == '__main__':
    app = QApplication(sys.argv)
    tc = test()
    
    app.exec_()


More information about the PyQt mailing list