File: ScreenArguments.c

package info (click to toggle)
psychtoolbox-3 3.0.19.14.dfsg1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • 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 (498 lines) | stat: -rw-r--r-- 16,231 bytes parent folder | download | duplicates (5)
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
/*
	PsychToolbox2/Source/Common/Screen/ScreenArguments.c
	
	PLATFORMS:	Windows
				MacOS9
			
	
	AUTHORS:
	Allen Ingling		awi		Allen.Ingling@nyu.edu

	HISTORY:
	09/09/02			awi		wrote it.  
        10/20/03			awi		fixed a bug in PsychCopyInColorArg where we failed to save alph value correctly in the color struct.
	11/14/06                        mk              Colors are now also accepted in uint8 format. Empty rects are no longer rejected as invalid.
	DESCRIPTION:
	
	Functions which get and put arguments used by Screen.  	
        
        TO DO
        
	Return the Window index.  Before returning it check to be sure that an argument was supplied
	and that it refers to a currently opened window.  If either is not true then exit with an 
	error.   
*/

#include "Screen.h"


psych_bool PsychCopyInWindowIndexArg(int position, psych_bool required, PsychWindowIndexType *windowIndex)
{

	double *arg;
        psych_bool isThere;
	
	if(position==kPsychUseDefaultArgPosition)
		position = kPsychDefaultNumdexArgPosition; 
        isThere=PsychAllocInDoubleArg(position,required,&arg);
        if(!isThere)
            return(FALSE);
	*windowIndex = (PsychWindowIndexType)*arg;
	if(IsWindowIndex(*windowIndex))
		return(TRUE);
	else{
		PsychErrorExitMsg(PsychError_invalidWindex,NULL);
		return(FALSE);  //only to satisfy the compiler with a return statement.
	}
}


/* 
        PsychAllocInWindowRecordArg()
        
        Lookup the window record using the window index argument. 
        
        Because this looks up the window record using its somewhat different
        from other "PsychAllocIn*Arg" functions, but we use the same naming scheme nonetheless.
        From the caller's point of view looking up a prexisting record and allocating a new
        one should be equivalent.  
*/
psych_bool PsychAllocInWindowRecordArg(int position, psych_bool required, PsychWindowRecordType **winRec)
{
	PsychWindowIndexType windowIndex;
	double arg;
	psych_bool isThere;
        
	if(position==kPsychUseDefaultArgPosition)
            position = kPsychDefaultNumdexArgPosition; 	
	isThere=PsychCopyInDoubleArg(position,required,&arg);
        if(!isThere)
            return(FALSE);
	windowIndex = (PsychWindowIndexType)arg;
	PsychErrorExit(FindWindowRecord(windowIndex, winRec));
        return(TRUE);
}


/*
    PsychCopyInScreenNumberArg()
    
    Automaticially derive the screen number from a window index if provided.
    Otherwise return the screen number if that is what is provided.
        
*/
psych_bool PsychCopyInScreenNumberArg(int position, psych_bool required, int *screenNumber)
{
	PsychNumdexType numdex;
	PsychWindowRecordType *winRec;
	double arg;
        psych_bool isThere;

	if(position==kPsychUseDefaultArgPosition)
		position = kPsychDefaultNumdexArgPosition; 	
	isThere=PsychCopyInDoubleArg(position,required,&arg);
        if(!isThere)
            return(FALSE);
	numdex = (PsychNumdexType)arg;
	if(IsWindowIndex(numdex)){ 
		//it's a window index, so get the window record and from that get the screen number.  
		FindWindowRecord((PsychWindowIndexType)numdex, &winRec);
		*screenNumber=winRec->screenNumber;
                return(TRUE);
	}else if(IsValidScreenNumber(numdex)){
		//it's a screen number, so just return it.
		*screenNumber=(int)numdex;
                return(TRUE);
	}else{
		//we were passed something that is neither a window index nor a screen number so issue an error.
		PsychErrorExitMsg(PsychError_invalidNumdex,NULL);
		return(FALSE);
	}
}


/*
    PsychCopyInScreenNumberOrUnaffiliatedArg()
    
    Like PsychCopyInScreenNumberArg but we will also accept -1 to indicate no particular screen.
        
*/
psych_bool PsychCopyInScreenNumberOrUnaffiliatedArg(int position, psych_bool required, int *screenNumber)
{
	PsychNumdexType numdex;
	PsychWindowRecordType *winRec;
	double arg;
        psych_bool isThere;

	if(position==kPsychUseDefaultArgPosition)
		position = kPsychDefaultNumdexArgPosition; 	
	isThere=PsychCopyInDoubleArg(position,required,&arg);
        if(!isThere)
            return(FALSE);
	numdex = (PsychNumdexType)arg;
	if(IsWindowIndex(numdex)){ 
		//it's a window index, so get the window record and from that get the screen number.  
		FindWindowRecord((PsychWindowIndexType)numdex, &winRec);
		*screenNumber=winRec->screenNumber;
                return(TRUE);
	}else if(IsValidScreenNumberOrUnaffiliated(numdex)){
		//it's a screen number, so just return it.
		*screenNumber=(int)numdex;
                return(TRUE);
	}else{
		//we were passed something that is neither a window index nor the token meaning unaffiliated window nor a screen number so issue an error.
		PsychErrorExitMsg(PsychError_invalidNumdex,NULL);
		return(FALSE);
	}
}


/*
    PsychAllocInScreenNumberArg()
    
    This automaticially derives the screen number from a window index if that is what is passed.
    
    Write PsychCopyInRawScreenNumberArg for cases where we might not want to do that. 
*/
psych_bool PsychAllocInScreenRecordArg(int position, psych_bool required, PsychScreenRecordType **screenRecord)
{
	int screenNumber;
        psych_bool isThere;
	
	if(position==kPsychUseDefaultArgPosition)
		position = kPsychDefaultNumdexArgPosition; 
        isThere=PsychCopyInScreenNumberArg(position, required, &screenNumber);
        if(!isThere)
            return(FALSE);
	PsychErrorExitMsg(FindScreenRecord(screenNumber, screenRecord),NULL);
	return(TRUE);	
}

		
psych_bool PsychIsWindowIndexArg(int position)
{
	PsychNumdexType numdex;
	double arg;

	if(position==kPsychUseDefaultArgPosition)
		position =kPsychDefaultNumdexArgPosition; 	
	if(!PsychCopyInDoubleArg(position,FALSE,&arg))
            return(FALSE);
	numdex = (PsychNumdexType)arg;
	return(IsWindowIndex(numdex));
	
}

/*
	PsychIsScreenNumberOrUnaffiliatedArg()
	
	Returns true iff the argument in the specified position is either a window argumen or one of the key values
	which means not to associate a window with any particular display.  For now that value is -1 but  within
	the PTB environment we could also alow NaN because that makes more sense than -1.
*/
psych_bool PsychIsScreenNumberOrUnaffiliatedArg(int position)
{
	PsychNumdexType numdex;
	double arg;

	if(position==kPsychUseDefaultArgPosition)
		position = kPsychDefaultNumdexArgPosition; 	
	if(!PsychCopyInDoubleArg(position,FALSE,&arg))
            return(FALSE);
	numdex = (PsychNumdexType)arg;
	return(IsValidScreenNumber(numdex) || numdex==kPsychUnaffiliatedWindow);
	
}

/*
	PsychIsUnaffiliatedScreenNumberArg()
	
	Returns true iff the argument in the specified position indicatesnot to associate a window with any particular
	display.  For now that value is -1 but  within the PTB environment we could also alow NaN because that makes 
	more sense than -1.
*/
psych_bool PsychIsUnaffiliatedScreenNumberArg(int position)
{
	PsychNumdexType numdex;
	double arg;

	if(position==kPsychUseDefaultArgPosition)
		position = kPsychDefaultNumdexArgPosition; 	
	if(!PsychCopyInDoubleArg(position,FALSE,&arg))
            return(FALSE);
	numdex = (PsychNumdexType)arg;  //cast is to int.  We should get rid of this obfuscatory numdex type. 
	return(numdex==kPsychUnaffiliatedWindow);
	
}



psych_bool PsychIsScreenNumberArg(int position)
{
	PsychNumdexType numdex;
	double arg;

	if(position==kPsychUseDefaultArgPosition)
		position = kPsychDefaultNumdexArgPosition; 	
	if(!PsychCopyInDoubleArg(position,kPsychArgAnything,&arg))
            return(FALSE);
	numdex = (PsychNumdexType)arg;
	return(IsValidScreenNumber(numdex));
	
}



/* put and get color and rect specifiers directly from arguments

-Naming scheme:
	-Outputing return arguments:
		- "PsychAllocOut*Arg" : allocate and set a pointer to volatile memory to be filled with returned information by the caller.
		- "PsychCopyOut*Arg : accept a pointer to ouput values and fill in the return matrix memory with the values.
	-Reading input arguments:
		- "PsychAllocIn*Arg" : set a pointer to volatile memory allocated by "PsychAllocIn*Arg" and holding the input value.
		- "PsychCopyIn*Arg" : accept a pointer to memory and fill in that memory with the input argument values.     
		
*/



/*
	Accept a pointer to a Psychtoolbox color specifier and fill it with the 
	color information supplied at the specified argument position in module call .
	
	The behavior depends on the value of required:
	
	1. Required = TRUE
		A. If argument is not present exit with an error PsychError_invalidColorArg.
		B. If argument is present and valid then load it into *color and return true.
	2. Required = FALSE 
		A. If argument is not present then don't touch *color and return false.
		B. If argument is present and valid then load it into *color and return true.
*/
psych_bool PsychCopyInColorArg(int position, psych_bool required, PsychColorType *color)
{
	int i,m,n,p,argSize;
	psych_bool isArg;
	double dummyColor[4];
	double *colorArgMat=NULL;
	unsigned char *colorArgMatBytes=NULL;
	
	if(position == kPsychUseDefaultArgPosition)
		position = kPsychDefaultColorArgPosition;
	isArg = PsychIsArgPresent(PsychArgIn, position);
	if(!isArg){
		if(required)
			PsychErrorExitMsg(PsychError_user, "No color argument supplied"); //1A
		else
			return(FALSE);	//2A
	}

	// Try to retrieve double-matrix:
	if (!PsychAllocInDoubleMatArg(position, kPsychArgAnything, &m, &n, &p, &colorArgMat)) {
	  // No double matrix: Try to retrieve uint8 matrix:
	  if (!PsychAllocInUnsignedByteMatArg(position, TRUE, &m, &n, &p, &colorArgMatBytes)) {
	    PsychErrorExitMsg(PsychError_user, "No color argument or invalid color argument supplied");
	  }

	  // Color as uint8 received: Convert to double.
	  if(p!=1) PsychErrorExit(PsychError_invalidColorArg);
	  argSize = m*n;
	  for(i=0; i<argSize; i++) dummyColor[i] = (double) colorArgMatBytes[i];
	  colorArgMat = (double*) (&dummyColor[0]);
	}

	if(p!=1) PsychErrorExit(PsychError_invalidColorArg);
	argSize = m*n;

	if(argSize==4){
		color->mode = kPsychRGBAColor;
		color->value.rgba.r = colorArgMat[0];
		color->value.rgba.g = colorArgMat[1];
		color->value.rgba.b = colorArgMat[2];
		color->value.rgba.a = colorArgMat[3];
                return(TRUE);	//1B, 2B	
	}if(argSize==3){
		color->mode = kPsychRGBColor;
		color->value.rgb.r = colorArgMat[0];
		color->value.rgb.g = colorArgMat[1];
		color->value.rgb.b = colorArgMat[2];
		return(TRUE);	//1B, 2B	
	}else if(argSize==1){
		color->mode = kPsychIndexColor;
		color->value.index.i = colorArgMat[0];
		return(TRUE); //1B, 2B	
	}else{ 
		PsychErrorExit(PsychError_invalidColorArg);
		return(FALSE);
	}
}


		


/*
	Accept a pointer to a Psychtoolbox color specifier and return it from the module
	call in the specified argument position. 
	
	The return value indicates whether the return argument was present.   
	
*/
psych_bool PsychCopyOutColorArg(int position, psych_bool required, PsychColorType *color, PsychWindowRecordType *windowRecord)
{
    double *colorArgMat;
    double deno;
    
    // Read denominator from windowRecord. Need to get rid of the sign, because it
    // encodes if we have color clamping enabled or not:
    deno = fabs(windowRecord->colorRange);

    if(color->mode == kPsychRGBAColor){
        if(!PsychAllocOutDoubleMatArg(position, required, 1, 4, 0, &colorArgMat))
            return(FALSE);
        colorArgMat[0] = (double)color->value.rgba.r;
        colorArgMat[1] = (double)color->value.rgba.g;
        colorArgMat[2] = (double)color->value.rgba.b;
        colorArgMat[3] = (color->value.rgba.a == DBL_MAX) ? deno : (double) color->value.rgba.a;
        return(TRUE);
    }else if(color->mode == kPsychRGBColor){
        if(!PsychAllocOutDoubleMatArg(position, required, 1, 3, 0, &colorArgMat))
            return(FALSE);
        colorArgMat[0] = (double)color->value.rgb.r;
        colorArgMat[1] = (double)color->value.rgb.g;
        colorArgMat[2] = (double)color->value.rgb.b;
        return(TRUE);
    }else if(color->mode == kPsychIndexColor){
        if(!PsychAllocOutDoubleMatArg(position, required, 1, 1, 0, &colorArgMat))
            return(FALSE);
        colorArgMat[0] = (double)color->value.index.i;
        return(TRUE);
    }
    PsychErrorExitMsg(PsychError_internal, "Unrecognized color mode");
    return(FALSE);  //make the compiler happy
}


/*
	Accept a pointer to a Psychtoolbox rect specifier and fill it with the rect
	information supplied at the specified argument position in module call.
	
	The behavior depends on the value of required:
	
	1. Required = TRUE
		A. If argument is not present exit with an error PsychError_invalidColorArg.
		B. If argument is present and valid then load it into *rect and return true.
	2. Required = FALSE 
		A. If argument is not present then don't touch *color and return false.
		B. If argument is present and valid then load it into *rect and return true.

*/
psych_bool PsychCopyInRectArg(int position, psych_bool required, PsychRectType rect)
{
	int m,n,p,argSize;
	psych_bool isArg;
	double *rectArgMat=NULL;
	
	if(position == kPsychUseDefaultArgPosition)
		position = kPsychDefaultRectArgPosition;
	isArg = PsychIsArgPresent(PsychArgIn, position);
	if(!isArg){
		if(required)
			PsychErrorExitMsg(PsychError_user, "Required rect argument missing."); //1A
		else
			return(FALSE);	//2A
	}
	PsychAllocInDoubleMatArg(position, TRUE, &m, &n, &p, &rectArgMat);
	if(p!=1)
		PsychErrorExitMsg(PsychError_invalidRectArg, ">2 D array passed as rect");
	argSize = m*n;
	if(argSize!=4)
		PsychErrorExitMsg(PsychError_invalidRectArg, "rect argument not 4 elements in size");
	memcpy(rect,rectArgMat,sizeof(PsychRectType));
	if(!ValidatePsychRect(rect)){
		PsychErrorExitMsg(PsychError_invalidRectArg, "impossible rect values given");
		return(FALSE);
	}		
	return(TRUE); //1B, 2B
}

/*
	Accept a pointer to a Psychtoolbox rect specifier and return it from the module
	call in the specified argument position. 
	
	The return value indicates whether the return argument was present. 
	
	We could add a PsychAllocRectArg statement also.    
	
*/
psych_bool PsychCopyOutRectArg(int position, psych_bool required, PsychRectType rect)
{
	double *rectArgMat;
	
	if(!PsychAllocOutDoubleMatArg(position, required, 1, 4, 0, &rectArgMat))
		return(FALSE); //optional argument was omitted
	memcpy(rectArgMat,rect,sizeof(PsychRectType));
	return(TRUE);
}

psych_bool PsychAllocOutRectArg(int position, psych_bool required, const double **rect)
{
	double *rectArg;
	
	if(!PsychAllocOutDoubleMatArg(position, required, 1, 4, 0, &rectArg))
		return(FALSE); //optional argument was omitted
	*rect=rectArg;
	return(TRUE);
}

/*
    PsychCopyInSingleDepthArg()
    
    The depth argument must already be allocated and initialized. For reading a 1x1 matrix holding a depth.  
    Use PsychCopyInMultiDepthArg() for reading in lists of depths.
*/

psych_bool PsychCopyInSingleDepthArg(int position, psych_bool required, PsychDepthType *depth)
{
    double *depthArray;
    int m,n,p;
    
    
    position= kPsychUseDefaultArgPosition ?  kPsychDefaultDepthArgPosition : position;
    if(!PsychAllocInDoubleMatArg(position, required, &m, &n, &p, &depthArray))  //shouldn't this check the dimensions of the matrix ? 
        return(FALSE);
    if(m!=1 || n!=1 || p!=1)
        PsychErrorExitMsg(PsychError_invalidDepthArg, "1x1 depth argument expected");
    PsychAddValueToDepthStruct((int) depthArray[0], depth); 
    return(TRUE);
}


psych_bool	PsychCopyInDepthValueArg(int position, psych_bool required, int *depth)
{
    psych_bool	isThere;
    double	value;
    
    if((isThere=PsychCopyInDoubleArg(position,required, &value))){
        *depth=(int)value; 
        if(!(*depth==8 || *depth==16 || *depth==24 || *depth == 32 || *depth == 30))
            PsychErrorExitMsg(PsychError_invalidDepthArg, "Illegal depth value");
    }
    return(isThere);

}



psych_bool PsychCopyOutDepthArg(int position, psych_bool required, PsychDepthType *depths)
{
    double *depthsArray;
    int i;
    
    if(!PsychAllocOutDoubleMatArg(position, required, 1, PsychGetNumDepthsFromStruct(depths), 0, &depthsArray))
        return(FALSE); //optional argument was omitted 
    for(i=0;i<PsychGetNumDepthsFromStruct(depths);i++)
        depthsArray[i]=(double)PsychGetValueFromDepthStruct(i,depths);
    return(TRUE);
}