File: WindowBank.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 (601 lines) | stat: -rw-r--r-- 22,579 bytes parent folder | download | duplicates (3)
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
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
/*
 *        PsychToolbox3/Source/Common/WindowBank.c
 *
 *        AUTHORS:
 *
 *              Allen.Ingling@nyu.edu        awi
 *              mario.kleiner.de@gmail.com      mk
 *
 *        PLATFORMS:
 *
 *                All
 *
 *        HISTORY:
 *
 *                07/18/02  awi         Wrote it. This is a second attempt.  The first
 *                                      attempted to maintain state with static
 *                                      variables internal to functions. Much too
 *                                      awkward for prototyping purposes.
 *                07/22/05  mk          Windowbank array is allocated and resized dynamically now, so no limit to maximum
 *                                      number of windows anymore.
 *
 *        DESCRIPTION:
 *
 *                WindowBank contains functions for storing records of open
 *                onscreen and offscreen windows.
 *
 *                See WindowHelpers for convenience functions which access the fields
 *                of records defined in WindowBank.h
*/

#include "Screen.h"

/* ------------------------------------------------------------------
 *        Declare static persistant variables local to WindwBank.c variables.
 */

// MK: windowRecordArrayWINBANK is allocated in InitWindowBank(), released in CloseWindowBank(),
// and dynamically resized in PsychCreateWindowArrayRecord(), if necessary to accomodate more windows.
// We resize in chunks of PSYCH_ALLOC_WINDOW_RECORDS_INC window slots to avoid/reduce possible memory-
// fragmentation and make allocation efficient. This approach is better than using linked-lists, because
// it is easier to implement and still allows access to each windowRecord in constant time via array-lookup,
// avoiding increasing access-delays that would happen with long linked lists.
static PsychWindowRecordType **windowRecordArrayWINBANK=NULL;
static PsychScreenRecordType *screenRecordArrayWINBANK[PSYCH_ALLOC_SCREEN_RECORDS];
static int numWindowRecordsWINBANK = 0;

// MK: See InitWindowBank() for initial setup of variables below...
static int PSYCH_MAX_WINDOWS = 0; // Maximum number of onscreen-/offscreen-windows/textures...
static int PSYCH_LAST_WINDOW = 0; // the highest possible window index
static int PSYCH_ALLOC_WINDOW_RECORDS = 0; //current length of dynamic array allocated to hold window pointers.

#define PSYCH_ALLOC_WINDOW_RECORDS_INC 4096  // Increment when extending the window bank...

//Local function prototypes
PsychWindowIndexType FindEmptyWindowIndex(void);

//    Window accessor functions for the outside world.

/*
 *        PsychFindScreenWindowFromScreenNumber()
 *
 *        Walk down the list of onscreen windows looking for the window open on the specified screen and and set *winRec to point to its window recored if we find one.
 *        Otherwise set *winRec to NULL. If screenNumber is kPsychUnaffiliatedWindow, we return the first onscreen window we find, regardless of screen.
 */

void PsychFindScreenWindowFromScreenNumber(int screenNumber, PsychWindowRecordType **winRec)
{
    int i, numWindows;
    PsychWindowRecordType **windowArray;

    *winRec=NULL;
    PsychCreateVolatileWindowRecordPointerList(&numWindows, &windowArray);
    for (i=0;i<numWindows;i++) {
        if (PsychIsOnscreenWindow(windowArray[i])) {
            if ((windowArray[i]->screenNumber == screenNumber) || (screenNumber == kPsychUnaffiliatedWindow)) {
                *winRec=windowArray[i];
                break;
            }
        }
    }
    PsychDestroyVolatileWindowRecordPointerList(windowArray);
}

/*
 *        Initialize list of window record pointers.
 */
PsychError InitWindowBank(void)
{
    PsychWindowIndexType i;

    PSYCH_ALLOC_WINDOW_RECORDS=PSYCH_ALLOC_WINDOW_RECORDS_INC; // Initial length of array allocated to hold window pointers.

    // MK: Allocate an initial windowbank of default size PSYCH_ALLOC_WINDOW_RECORDS:
    windowRecordArrayWINBANK=malloc(PSYCH_ALLOC_WINDOW_RECORDS * sizeof(PsychWindowRecordType*));
    if (windowRecordArrayWINBANK==NULL) {
        // Out of memory!
        return(PsychError_outofMemory);
    }

    PSYCH_MAX_WINDOWS=PSYCH_ALLOC_WINDOW_RECORDS-10;
    PSYCH_LAST_WINDOW=PSYCH_ALLOC_WINDOW_RECORDS-1; //the highest possible window index

    // Initialize with NULL-Ptrs:
    for(i=PSYCH_FIRST_WINDOW;i<=PSYCH_LAST_WINDOW;i++)
        windowRecordArrayWINBANK[i] = NULL;

    return(PsychError_none); //no error
}

/*
 *        Free storage for window records.  All windows should be
 *        close first.
 */
PsychError CloseWindowBank(void)
{
    PsychWindowIndexType i;

    for (i = PSYCH_FIRST_WINDOW; i <= PSYCH_LAST_WINDOW; i++) {
        if (windowRecordArrayWINBANK[i] != NULL)
            free(windowRecordArrayWINBANK[i]);
    }

    // Release the array of pointers itself:
    free(windowRecordArrayWINBANK);

    windowRecordArrayWINBANK=NULL;
    PSYCH_MAX_WINDOWS=0;
    PSYCH_LAST_WINDOW=0;
    PSYCH_ALLOC_WINDOW_RECORDS=0;

    return(PsychError_none);
}

/*
 *        Count the number of windows of the specified type.
 */
int PsychCountOpenWindows(PsychWindowType winType)
{
    int i, total=0;

    for (i = PSYCH_FIRST_WINDOW; i <= PSYCH_LAST_WINDOW; i++) {
        if (windowRecordArrayWINBANK[i]) {
            if (winType==kPsychAnyWindow)
                ++total;
            else if (windowRecordArrayWINBANK[i]->windowType==winType)
                ++total;
        }
    }
    return(total);
}

/*
 * PsychIsLastOnscreenWindow() - Is this the last open onscreen window?
 */
psych_bool PsychIsLastOnscreenWindow(PsychWindowRecordType *windowRecord)
{
    if (!PsychIsOnscreenWindow(windowRecord))
        return(FALSE);

    if (PsychCountOpenWindows(kPsychDoubleBufferOnscreen) + PsychCountOpenWindows(kPsychSingleBufferOnscreen) > 1)
        return(FALSE);
    else
        return(TRUE);
}

/*
 *        PsychIsLastOnscreenWindowOnScreen()
 *
 *        Is this the last open onscreen window for the associated screen?
 */
psych_bool PsychIsLastOnscreenWindowOnScreen(PsychWindowRecordType *windowRecord)
{
    int i;

    if (!PsychIsOnscreenWindow(windowRecord))
        return(FALSE);

    for(i = PSYCH_FIRST_WINDOW; i <= PSYCH_LAST_WINDOW; i++) {
        if (windowRecordArrayWINBANK[i]) {
            if (windowRecordArrayWINBANK[i]->screenNumber == windowRecord->screenNumber &&
                windowRecordArrayWINBANK[i]->windowIndex != windowRecord->windowIndex &&
                PsychIsOnscreenWindow(windowRecordArrayWINBANK[i]))
                return(FALSE);
        }
    }

    return(TRUE);
}

/*
 *        Allocate and return an empty window record
 */
void PsychCreateWindowRecord(PsychWindowRecordType **winRec)
{
    PsychWindowRecordType **tmpwindowRecordArrayWINBANK=NULL;
    PsychWindowIndexType i;

    //check for space
    if(numWindowRecordsWINBANK==PSYCH_MAX_WINDOWS) {
        // Windowbank - array is full! We reallocate it, extending it
        // by PSYCH_ALLOC_WINDOW_RECORDS_INC additional slots for additional windows.
        tmpwindowRecordArrayWINBANK=realloc(windowRecordArrayWINBANK, (PSYCH_ALLOC_WINDOW_RECORDS + PSYCH_ALLOC_WINDOW_RECORDS_INC) * sizeof(PsychWindowRecordType*));
        if (tmpwindowRecordArrayWINBANK==NULL) {
            // realloc() failed due to out-of-memory!
            PsychErrorExit(PsychError_outofMemory);   //out of memory
        }

        // Success! Update limits and initialize new slots:
        windowRecordArrayWINBANK = tmpwindowRecordArrayWINBANK;
        PSYCH_ALLOC_WINDOW_RECORDS+=PSYCH_ALLOC_WINDOW_RECORDS_INC;
        PSYCH_MAX_WINDOWS+=PSYCH_ALLOC_WINDOW_RECORDS_INC;
        // Initialize new slots with NULL-Ptrs:
        i=PSYCH_LAST_WINDOW + 1;
        PSYCH_LAST_WINDOW+=PSYCH_ALLOC_WINDOW_RECORDS_INC;
        for(;i<=PSYCH_LAST_WINDOW;i++) windowRecordArrayWINBANK[i] = NULL;
        // Ready for addition of new windows.
    }

    // Allocate storage, zero-init it:
    if ((*winRec = (PsychWindowRecordType *) calloc(1, sizeof(PsychWindowRecordType))) == NULL)
        PsychErrorExit(PsychError_outofMemory);   //out of memory

    //increment counts
    ++numWindowRecordsWINBANK;

    //store the record at a free pointer index and set the records field to the index.
    (*winRec)->windowIndex = FindEmptyWindowIndex();
    windowRecordArrayWINBANK[(*winRec)->windowIndex] = *winRec;

    //set a flag to indicate that the contents of the window record are not completely valid.
    (*winRec)->isValid=FALSE;

    // Set window type to kPsychNoWindow to signal that the window doesn't yet exist.
    // Although the windowRecord is partially initialized, there's no Windowsystem onscreen
    // window associated with this and the OpenGL context isn't there either. This is important
    // for error-handling. Windows of type kPsychNoWindow are ignored by the OpenGL and Window system
    // cleanup routine PsychCloseWindow()...
    (*winRec)->windowType = kPsychNoWindow;

    // Assign default number of color channels: 4 is a good number (RGBA), but this
    // gets overwritten in appropriate places...
    (*winRec)->nrchannels=4;

    // Initialize all imaging pipeline related fields to safe defaults:
    PsychInitImagingPipelineDefaultsForWindowRecord(*winRec);

    //Intialize the text settings field within the window record to default values which should be (but are not yet) specified in Psychtoolbox preferences.
    PsychInitTextRecordSettings(&((*winRec)->textAttributes));

    // Init text 2D affine transform matrix to identity transformation:
    (*winRec)->text2DMatrix[0][0] = 1;
    (*winRec)->text2DMatrix[0][1] = 0;
    (*winRec)->text2DMatrix[1][0] = 0;
    (*winRec)->text2DMatrix[1][1] = 1;
    (*winRec)->text2DMatrix[0][2] = 0;
    (*winRec)->text2DMatrix[1][2] = 0;

    //Initialize the fields about textures.
    PsychInitWindowRecordTextureFields(*winRec);

    //Initialize the fields used to store alpha blending factors as set by glBlendFunc()
    PsychInitWindowRecordAlphaBlendingFactors(*winRec);

    //Initialize line stipple values
    (*winRec)->stipplePattern=0xAAAA;        //alternating pixels stipple pattern
    (*winRec)->stippleFactor=1;
    (*winRec)->stippleEnabled=FALSE;

    // Set GL color buffer writemask glColorMask to "all enabled":
    (*winRec)->colorMask[0] = GL_TRUE;
    (*winRec)->colorMask[1] = GL_TRUE;
    (*winRec)->colorMask[2] = GL_TRUE;
    (*winRec)->colorMask[3] = GL_TRUE;

    // Initialize stereo settings:
    (*winRec)->stereomode=0;
    (*winRec)->stereodrawbuffer=2;              // No stero drawbuffer selected at window open time.
    (*winRec)->slaveWindow=NULL;                // No slave window attached.
    (*winRec)->parentWindow=NULL;               // No parent window attached.
    (*winRec)->targetFlipFieldType=-1;          // Don't care if flipping should only happen in even or odd video refresh frames.
    (*winRec)->auxbuffer_dirty[0]=FALSE;        // AUX-Buffers clean on startup.
    (*winRec)->auxbuffer_dirty[1]=FALSE;

    // Initialize gamma table pointers for deferred loading:
    (*winRec)->inRedTable = NULL;
    (*winRec)->inGreenTable = NULL;
    (*winRec)->inBlueTable = NULL;
    (*winRec)->loadGammaTableOnNextFlip = 0;

    // No override projection matrices:
    (*winRec)->proj = NULL;

    // Set cached display list handles for drawing functions to "uninitialized":
    (*winRec)->fillOvalDisplayList = 0;
    (*winRec)->frameOvalDisplayList = 0;

    // No special flags set by default:
    (*winRec)->specialflags = 0;
    // No capabilities setup yet:
    (*winRec)->gfxcaps = 0;

    // No aux param vector set by default:
    (*winRec)->auxShaderParams = NULL;
    (*winRec)->auxShaderParamsCount = 0;

    // Reset memory accounting info for this windowRecord:
    (*winRec)->surfaceSizeBytes = 0;

    // NULL out flipinfo struct:
    (*winRec)->flipInfo = NULL;

    // Init our shader handles to zero -- Off by default:
    (*winRec)->unclampedDrawShader = 0;
    (*winRec)->defaultDrawShader = 0;

    // Set surface addresses to zero:
    (*winRec)->gpu_preflip_Surfaces[0] = 0;
    (*winRec)->gpu_preflip_Surfaces[1] = 0;

    // Bits per color component value: Initialize to 8 bits per channel. This is true for all
    // standard textures, offscreen- and onscreen windows. Only FBO backed drawables can start
    // off with 16 bpc (float/fixed) or 32 bpc float, or get upgraded to such resolutions. Such
    // upgrades always happen in a maketexture function or FBO creation function.
    // This will be later replaced by true bitdepths for onscreen windows, e.g., to account for
    // 10 bit native framebuffers on latest GPUs:
    (*winRec)->bpc = 8;

    // Sync of doublebuffer-swaps to vertical retrace signal starts off as disabled:
    (*winRec)->vSynced = FALSE;

    // Default to unknown maximum supported texture size:
    (*winRec)->maxTextureSize = 0;

    // No GPU core id assigned yet:
    (*winRec)->gpuCoreId[0] = 0;
    (*winRec)->gpuRenderTimeQuery = 0;
    (*winRec)->gpuRenderTime = 0.0;

    // No swap group or barrier assigned:
    (*winRec)->swapGroup = 0;
    (*winRec)->swapBarrier = 0;

    // Zero-init OpenML timing values:
    (*winRec)->reference_ust = 0;
    (*winRec)->reference_msc = 0;
    (*winRec)->reference_sbc = 0;
    (*winRec)->osbuiltin_swaptime = 0.0;
    (*winRec)->target_sbc = 0;
    (*winRec)->lastSwaptarget_msc = 0;

    // ...and other timing values:
    (*winRec)->postflip_vbltimestamp = -1.0;

    // Init to zero default:
    (*winRec)->VBL_Startline = 0;
    (*winRec)->VBL_Endline = 0;

    // One-Time setup of some parameters needed for userspace OpenGL context at first real bind:
    (*winRec)->needsViewportSetup = TRUE;

    // HDR scaling factors for SDR -> HDR or HDR normalized -> HDR mapping:
    // These default to good values for standard SDR/LDR windows, so both LDR and HDR content
    // can be scaled to display in a reasonable way on a SDR display device. These defaults
    // will get overriden in HDR mode by PsychHDR() during HDR window setup, and may get
    // overriden for SDR windows as appropriate for tone-mapping, but these defaults should
    // be good as a starter:
    (*winRec)->maxSDRToHDRScaleFactor = 1.0;      // SDR content: Set default 1.0 for standard SDR/LDR window. Iow. no need to map.
    (*winRec)->normalizedToHDRScaleFactor = 20.0; // HDR content: Set default for mapping 0 - 500 nits into standard SDR/LDR window range 0 - 1.

    return;
}

/*
 *        Free the window record memory and set the corresponding window array entry to null.
 *        Its up to the calling function to close the window FIRST.
 */
PsychError FreeWindowRecordFromIndex(PsychWindowIndexType windex)
{
    if (windex < PSYCH_FIRST_SCREEN)
        return(PsychError_scumberNotWindex); //I was passed a screen number, not a window index

    if (windex <= PSYCH_LAST_SCREEN)
        return(PsychError_scumberNotWindex); //I was passed a screen number, not a window pointer

    if(windowRecordArrayWINBANK[windex] ==NULL)
        return(PsychError_invalidWindex);    //window does not exist

    // Release temporary gamma tables, if any:
    free(windowRecordArrayWINBANK[windex]->inRedTable);
    free(windowRecordArrayWINBANK[windex]->inGreenTable);
    free(windowRecordArrayWINBANK[windex]->inBlueTable);

    // Release override projection matrices if any:
    free(windowRecordArrayWINBANK[windex]->proj);

    free(windowRecordArrayWINBANK[windex]);
    windowRecordArrayWINBANK[windex] = NULL;
    --numWindowRecordsWINBANK;
    return(PsychError_none);
}

/*
 *        Free the window record memory and set the corresponding window array entry to null.
 *        Its up to the calling function to close the window FIRST.
 */
PsychError FreeWindowRecordFromPntr(PsychWindowRecordType *winRec)
{
    PsychWindowIndexType windowIndex;

    if(winRec == NULL)
        return(PsychError_nullWinRecPntr); //passed a null window pointer

    windowIndex = winRec->windowIndex;
    return(FreeWindowRecordFromIndex(windowIndex));
}

/*
 *        Accept a window pointer or a screen number (psychIndex) and return true if its a valid screen
 *        number and false otherwise
 */
psych_bool IsValidScreenNumber(PsychNumdexType numdex)
{
    return((int)((numdex >=PSYCH_FIRST_SCREEN) && (numdex < PsychGetNumDisplays())));
}

/*
 *        IsValidScreenNumberOrUnaffiliated()
 *
 *        Accept a window pointer or a screen number (psychIndex) and return true iff its a valid screen
 *        number or is the token indicating an unaffiliated window.
 */
psych_bool IsValidScreenNumberOrUnaffiliated(PsychNumdexType numdex)
{
    return(((int)((numdex >=PSYCH_FIRST_SCREEN) && (numdex < PsychGetNumDisplays()))) || numdex == kPsychUnaffiliatedWindow);
}

/*
 *        IsScreenNumberUnaffiliated()
 *
 */
psych_bool IsScreenNumberUnaffiliated(PsychNumdexType numdex)
{
    return(numdex == kPsychUnaffiliatedWindow);
}

/*
 *        Accept a window pointer or a screen number and return true if its a valid window pointer
 *        number and false otherwise
 */
psych_bool IsWindowIndex(PsychNumdexType numdex)
{
    if(numdex<PSYCH_FIRST_WINDOW || numdex>PSYCH_LAST_WINDOW)
        return(FALSE);  //outside of index range

    //check to see if their is window record there.
    if(windowRecordArrayWINBANK[numdex] != NULL)
        return(1);

    return(0);
}

/*
 *        Accept a window index and return a pointer to the window record, which will be NULL if no
 *        window exists.  We return an error if the index is invalid.
 *
 *        This function also checks the valid flag in the window to make sure that that fields were
 *        successfully filled when the window was created.
 *
 *        All retrieval of window records should go through this function because it checks for valid
 *        windows.
 *
 */
PsychError FindWindowRecord(PsychWindowIndexType windowIndex, PsychWindowRecordType **windowRecord)
{
    // Check for valid index: Must be within bounds of our array of windowRecord pointers, and the referenced slot must be a non-NULL ptr to a windowRecord:
    // Preinit to safe default of NULL:
    *windowRecord = NULL;
    if(windowIndex<PSYCH_FIRST_WINDOW || windowIndex>PSYCH_LAST_WINDOW || ((*windowRecord = windowRecordArrayWINBANK[windowIndex]) == NULL)) return(PsychError_invalidWindex); // Invalid index!

    // It is a windowRecord: Check if it is valid, ie., has been properly initialized by PTB:
    PsychCheckIfWindowRecordIsValid(*windowRecord);  // This would, e.g., fail because of an early exit when the window was created. It is considered an internal error if this triggers.

    // Success.
    return(PsychError_none);
}


/*
 *        Accept a screen number and return the corresponding screen record
 */
PsychError FindScreenRecord(int screenNumber, PsychScreenRecordType **screenRecord)
{
    if(IsValidScreenNumber(screenNumber)){
        *screenRecord = screenRecordArrayWINBANK[screenNumber];
        return(PsychError_none);
    } else
        return(PsychError_invalidScumber);
}

/*
 *    PsychCreateVolatileWindowRecordPointerList()
 *
 *    Allocates memory for and returns an array holding indices of all open windows.
 *
 *    This is kind of lame. It iterates over the window list twice.
 *
 */
void PsychCreateVolatileWindowRecordPointerList(int *numWindows, PsychWindowRecordType ***pointerList)
{
    int i,j=0;
    PsychWindowRecordType **tempList;

    *numWindows=0;
    for(i=PSYCH_FIRST_WINDOW;i<=PSYCH_LAST_WINDOW;i++){
        if(windowRecordArrayWINBANK[i])
            ++(*numWindows);
    }

    tempList=(PsychWindowRecordType **)malloc(sizeof(PsychWindowRecordType *) * *numWindows);
    for(i=PSYCH_FIRST_WINDOW;i<=PSYCH_LAST_WINDOW;i++){
        if(windowRecordArrayWINBANK[i])
            tempList[j++]=windowRecordArrayWINBANK[i];
    }

    *pointerList=tempList;
}

/*
 *    PsychDestroyVolatileWindowIndexList()
 */
void PsychDestroyVolatileWindowRecordPointerList(PsychWindowRecordType **pointerList)
{
    free((void *)pointerList);
}

/* PsychAssignParentWindow()
 * Assign a specific windowRecord as the parent windowRecord of a windowRecord.
 * This sets up the "parent" pointer and copies a variety of state and settings from the
 * parent to the child, e.g., OpenGL context, device context, color clamp settings etc...,
 * i.e., it performs the one time setup of the childs properties with the parents properties.
 *
 * Usually called by all functions that create new offscreen windows or textures to assign
 * the creating onscreen window to a child offscreen window or texture or proxy.
 *
 */
void  PsychAssignParentWindow(PsychWindowRecordType *childWin, PsychWindowRecordType *parentWin)
{
    // Assign parent:
    childWin->parentWindow = parentWin;

    // Copy some state and settings from parent to child:
    memcpy(&childWin->targetSpecific, &parentWin->targetSpecific, sizeof(parentWin->targetSpecific));

    // Copy default drawing shaders from parent:
    childWin->defaultDrawShader   = parentWin->defaultDrawShader;
    childWin->unclampedDrawShader = parentWin->unclampedDrawShader;

    // Copy color range and mode from parent window:
    childWin->colorRange = parentWin->colorRange;
    childWin->applyColorRangeToDoubleInputMakeTexture = parentWin->applyColorRangeToDoubleInputMakeTexture;

    // Copy imaging mode flags from parent:
    childWin->imagingMode = parentWin->imagingMode;

    // Inherit capability bits of parents context:
    childWin->gfxcaps = parentWin->gfxcaps;
    childWin->maxTextureSize = parentWin->maxTextureSize;

    // Type of display backend and graphics api:
    childWin->glApiType = parentWin->glApiType;
    childWin->winsysType = parentWin->winsysType;

    return;
}

/* PsychGetParentWindow()
 * Return the windowRecord* of the parent window of a given window, or the windowRecord itself
 * if the window doesn't have a parent because its a top-level onscreen window, ie., it is its
 * own parent.
 */
PsychWindowRecordType* PsychGetParentWindow(PsychWindowRecordType *windowRecord)
{
    while (windowRecord->parentWindow) windowRecord = windowRecord->parentWindow;
    return(windowRecord);
}

//  ------------------------------------------------------------------
//    Accessor functions for stuff internal to WindowBank.cpp.
//

PsychWindowIndexType FindEmptyWindowIndex(void)
{
    int i;
    for(i=PSYCH_FIRST_WINDOW;i<=PSYCH_LAST_WINDOW;i++){
        if(windowRecordArrayWINBANK[i]==NULL)
            return(i);
    }

    PsychErrorExitMsg(PsychError_toomanyWin,NULL);
    return(PSYCH_INVALID_WINDEX);
}