File: SCREENPreloadTextures.c

package info (click to toggle)
psychtoolbox-3 3.0.19.14.dfsg1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 86,796 kB
  • sloc: ansic: 176,245; cpp: 20,103; objc: 5,393; sh: 2,753; python: 1,397; php: 384; makefile: 193; java: 113
file content (200 lines) | stat: -rw-r--r-- 8,323 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
/*
	SCREENPreloadTextures
 
        Try to prefetch textures into the gfx-cards VRAM memory, so they
        can be drawn with minimum delay.
	
        AUTHORS:
 
		mario.kleiner@tuebingen.mpg.de                  mk		Mario Kleiner
 
	PLATFORMS:	
	
		Should compile and work on all platforms.  
 
	HISTORY:
	
		mm/dd/yy   
 
		12/04/05	mk		Created  							
		
	TO DO:
  
 */


#include "Screen.h"

// If you change the useString then also change the corresponding synopsis string in ScreenSynopsis.c
static char useString[] = "[resident [texidresident]] = Screen('PreloadTextures', windowPtr [, texids]);";
//                                                                                1          2
static char synopsisString[] = 
"Try to preload textures into VRAM to facilitate fast drawing. This method tries "
"to upload textures into the local (and fast) VRAM of your graphics hardware before "
"start of trial. This can reduce texture drawing time by avoiding the upload delay. "
"\"windowPtr\" Handle for onscreen window whose textures should be preloaded. "
"\"texids\" is a vector which contains the texture handles of all textures which "
"should be preloaded into VRAM. If no vector is given, PTB tries to preload all "
"textures into VRAM. "
"The return value 'resident' tells you, if all requested textures could be preloaded. A value of 1 "
"means full success. The 'texidresident' vector tells you for each texture, if that "
"specific texture could be preloaded. Preloading requested textures can fail if your gfx-hardware "
"has an insufficient amount of free VRAM memory. ";

static char seeAlsoString[] = "MakeTexture DrawTexture GetMovieImage";	 

PsychError SCREENPreloadTextures(void)  
{	
	PsychWindowRecordType                   *windowRecord, *texwin;
	psych_bool                                 isArgThere;
        int                                     *texhandles;
        PsychWindowRecordType                   **windowRecordArray;        
        int                                     i, n, numWindows, myhandle; 
        double                                  *success;
        psych_bool*                                residency;
        GLuint*                                 texids;
        GLboolean*                              texresident;
        psych_bool                                 failed = false;
        GLclampf                                maxprio = 1.0f;
        GLenum                                  target;

	//all sub functions should have these two lines
	PsychPushHelp(useString, synopsisString,seeAlsoString);
	if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);};
	
	//check for superfluous arguments
	PsychErrorExit(PsychCapNumInputArgs(2));        //The maximum number of inputs
	PsychErrorExit(PsychRequireNumInputArgs(1));    //The minimum number of inputs
	PsychErrorExit(PsychCapNumOutputArgs(2));       //The maximum number of outputs
	
	//get the window record from the window record argument and get info from the window record
	PsychAllocInWindowRecordArg(1, kPsychArgRequired, &windowRecord);
		
	// Get optional texids vector:
	isArgThere = PsychIsArgPresent(PsychArgIn, 2);
        PsychAllocInIntegerListArg(2, FALSE, &n, &texhandles);
        if (n < 1) isArgThere=FALSE;
        
        // Enable this windowRecords framebuffer as current drawingtarget:
        PsychSetDrawingTarget(windowRecord);

		// Disable shader:
		PsychSetShader(windowRecord, 0);
	

        glDisable(GL_TEXTURE_2D);

	// Fetch global texturing mode:
	target=PsychGetTextureTarget(windowRecord);

        glEnable(target);
        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
        glColor4f(0, 0, 0, 0);
	// Setup identity modelview matrix:
        glMatrixMode(GL_MODELVIEW);
        glPushMatrix();
        glLoadIdentity();

        PsychCreateVolatileWindowRecordPointerList(&numWindows, &windowRecordArray);            

        // Process vector of all texids for all requested textures:
        if (!isArgThere) {
            // No handles provided: In this case, we preload all textures:
            n=0;
            for(i=0; i<numWindows; i++) {                
                if (windowRecordArray[i]->windowType==kPsychTexture) {
                    n++;
                    // Prioritize this texture:
                    glPrioritizeTextures(1, (GLuint*) &(windowRecordArray[i]->textureNumber), &maxprio);
                    // Bind this texture:
                    glBindTexture(target, windowRecordArray[i]->textureNumber);
                    // Render a single textured point, thereby enforcing a texture upload:
                    glBegin(GL_QUADS);
                    glTexCoord2f(0,0); glVertex2i(10,10);
                    glTexCoord2f(0,1); glVertex2i(10,11);
                    glTexCoord2f(1,1); glVertex2i(11,11);
                    glTexCoord2f(1,0); glVertex2i(11,10);                    
                    glEnd();
                }
            }
            
            texids = (GLuint*) PsychMallocTemp(sizeof(GLuint) * n);
            texresident = (GLboolean*) PsychMallocTemp(sizeof(GLboolean) * n);

            n=0;
            for(i=0; i<numWindows; i++) {                
                if (windowRecordArray[i]->windowType==kPsychTexture) {
                    texids[n] = (GLuint) windowRecordArray[i]->textureNumber;
                    n++;
                }
            }
        }
        else {
            // Vector with texture handles provided: Just preload them.
            texids = (GLuint*) PsychMallocTemp(sizeof(GLuint) * n);
            texresident = (GLboolean*) PsychMallocTemp(sizeof(GLboolean) * n);
            myhandle=0;
            for (i=0; i<n; i++) {
                myhandle = texhandles[i];
                texwin = NULL;
                if (IsWindowIndex(myhandle)) FindWindowRecord(myhandle, &texwin);
                if (texwin && texwin->windowType==kPsychTexture) {
                    // Prioritize this texture:
                    glPrioritizeTextures(1, (GLuint*) &(texwin->textureNumber), &maxprio);
                    // Bind this texture:
                    glBindTexture(target, texwin->textureNumber);
                    // Render a single textured point, thereby enforcing a texture upload:
                    glBegin(GL_QUADS);
                    glTexCoord2f(0,0); glVertex2i(10,10);
                    glTexCoord2f(0,1); glVertex2i(10,11);
                    glTexCoord2f(1,1); glVertex2i(11,11);
                    glTexCoord2f(1,0); glVertex2i(11,10);                    
                    glEnd();
                    texids[i] = (GLuint) texwin->textureNumber;
                }
                else {
                    // This handle is invalid or at least no texture handle:
                    printf("PTB-ERROR! Screen('PreloadTextures'): Entry %i of texture handle vector (handle %i) is not a texture handle!\n",
                           i, myhandle);
                    failed = true;
                }
            }
        }
        
        // Restore old matrix from backup copy, undoing the global translation:
        glPopMatrix();
        // Disable texture engine:
        glDisable(GL_TEXTURE_2D);
        glDisable(target);

        // Wait for prefetch completion:
        glFinish();
        
        // We don't need these anymore:
        PsychDestroyVolatileWindowRecordPointerList(windowRecordArray);
        
        if (failed) {
            PsychErrorExitMsg(PsychError_user, "At least one texture handle in texids-vector was invalid! Aborted.");
        }
        
        // Query residency state of all preloaded textures:
        success = NULL;
        PsychAllocOutDoubleArg(1, FALSE, &success);
        *success = (double) glAreTexturesResident(n, texids, texresident);
        
        // Sync pipe again, just to be safe...
        glFinish();
        
        // Count them and copy them into output vector:
        PsychAllocOutBooleanMatArg(2, FALSE, n, 1, 1, (PsychNativeBooleanType **) &residency);
        
        for (i=0; i<n; i++) {
            residency[i] = (psych_bool) ((*success) ? TRUE : texresident[i]);
        }
        
        PsychTestForGLErrors();
        
 	// Done. Our PsychMallocTemp'ed arrays will be auto-released...
	return(PsychError_none);
}