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
|
/*
Psychtoolbox3/Source/Common/SCREENNull.c
AUTHORS:
Allen.Ingling@nyu.edu awi
PLATFORMS:
This file should build on any platform.
HISTORY:
11/26/02 awi Created.
DESCRIPTION:
Arbitrary code to be executed for debugging/testing/hacking PTB. This subfunction is not
documented or mentioned in official docs and only here for the purpose of internal testing
and as a container for quick & dirty hacks and tests by the core developers.
Therefore its syntax and semantics can change in any way, anytime without warning.
*/
#include "Screen.h"
#include "PsychGraphicsCardRegisterSpecs.h"
// Defined in PsychGraphicsHardwareHALSupport.c, but accessed here:
extern unsigned int crtcoff[kPsychMaxPossibleCrtcs];
#if PSYCH_SYSTEM == PSYCH_OSX
#include <IOKit/IOKitLib.h>
#include <sys/time.h>
#endif
static char useString[] = "[[value1], [value2] ..]=SCREEN('Null',[value1],[value2],...);";
static char synopsisString[] =
"Special test function for Psychtoolbox testing and developments. Normal users: DO NOT USE!\n"
"On Linux/OSX with AMD DCE-3 or later: FMT_CLAMP_CONTROL REG read/write. Meaningful values:\n"
"0 = Read only. 1 = Clamp to 6 bpc, 65537 = Clamp to 8 bpc, 131073 = Clamp to 10 bpc.\n";
static char seeAlsoString[] = "";
PsychError SCREENNull(void)
{
#define RADEON_D1CRTC_INTERRUPT_CONTROL 0x60DC
//#define RADEON_R500_GEN_INT_CNTL 0x100
//#define RADEON_R500_GEN_INT_STATUS 0x104
//#define RADEON_R500_GEN_INT_CNTL 0x040
//#define RADEON_R500_GEN_INT_STATUS 0x044
//#define RADEON_R500_GEN_INT_CNTL 0x200
//#define RADEON_R500_GEN_INT_STATUS 0x204
PsychWindowRecordType *windowRecord;
const char defaultString[] = "I am the default string\n";
//all sub functions should have these two lines
PsychPushHelp(useString, synopsisString, seeAlsoString);
if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);};
/*
#if PSYCH_SYSTEM == PSYCH_LINUX
unsigned int regOffset, value, hi, lo;
PsychCopyInIntegerArg(1, TRUE, (int *) ®Offset);
value = PsychOSKDReadRegister(0, regOffset, NULL);
hi = value >> 16;
lo = value & 0xffff;
if (PsychPrefStateGet_Verbosity() > 2) printf("%p :: hi = %i , lo = %i , val = %i\n", (void*) (size_t) regOffset, hi, lo, value);
PsychCopyOutDoubleArg(1, FALSE, (double) value);
PsychCopyOutDoubleArg(2, FALSE, (double) hi);
PsychCopyOutDoubleArg(3, FALSE, (double) lo);
return(PsychError_none);
#endif
*/
#if PSYCH_SYSTEM == PSYCH_WINDOWS
PsychAllocInWindowRecordArg(1, TRUE, &windowRecord);
PsychOSFlipWindowBuffers(windowRecord);
return(PsychError_none);
#endif
#if PSYCH_SYSTEM != PSYCH_WINDOWS
{
unsigned int headid = PsychScreenToCrtcId(0, 0);
unsigned int lutreg, ctlreg, value, status;
lutreg = EVERGREEN_DC_LUT_10BIT_BYPASS + crtcoff[headid];
ctlreg = EVERGREEN_GRPH_CONTROL + crtcoff[headid];
value = PsychOSKDReadRegister(0, lutreg, &status);
if (status) {
printf("PTB-ERROR: LUTReg read failed.\n");
} else {
printf("PTB-ERROR: LUTBypassReg = %x.\n", value);
}
}
return(PsychError_none);
#endif
#if 0
double tempValue;
double *array;
int i, m,n, p, numInArgs;
char *str;
PsychArgFormatType format;
// ----------- Linux DRI2/Radeon-KMS Scanline-Timestamping prototype for R500 core.
#define RADEON_D1CRTC_STATUS_POSITION 0x60a0
#define RADEON_D2CRTC_OFFSET 0x0800
#define RADEON_D2CRTC_STATUS_POSITION 0x68a0
#define RADEON_VBEAMPOSITION_BITMASK 0x1fff
#define RADEON_HBEAMPOSITION_BITSHIFT 16
#define AVIVO_D1CRTC_V_BLANK_START_END 0x6024
#define AVIVO_D1CRTC_V_TOTAL 0x6020
#define AVIVO_D1CRTC_H_TOTAL 0x6000
int crtcid = 0, verbose = 0;
PsychCopyInIntegerArg(1, FALSE, &crtcid);
PsychCopyInIntegerArg(2, FALSE, &verbose);
const int pedantic = 1;
int vbl_start, vbl_end, vbl, htotal, vtotal, dotclock;
psych_int64 linedur_ns, pixeldur_ns;
psych_bool invbl = TRUE;
int scanline, scanpixel, vblcount;
unsigned int cardId;
psych_uint32 crtco = (crtcid > 0) ? RADEON_D2CRTC_OFFSET : 0;
struct timeval raw_time;
struct timeval delta_time;
struct timeval vblank_time;
// NVidia GPU? Check OpenGL vendor string and for recognized gpu-id:
if ((strstr((char*) glGetString(GL_VENDOR), "NVIDIA")) && (PsychGetNVidiaGPUType(NULL) > 0)) {
// Yes. Test beampos queries and vblank counter:
if ((cardId = PsychGetNVidiaGPUType(NULL)) >= 0x50) {
// NV50 or later, aka GeForce-8000 or later: Same registers for
// everything shipping from NV50 up to at least NVC0 "Fermi":
// Offset between crtc's is 0x800:
crtco = (crtcid > 0) ? 0x800 : 0;
// Lower 16 bits are horizontal scanout position, upper 16 bits are always zero:
scanpixel = (PsychOSKDReadRegister(crtcid, 0x616344 + crtco, NULL)) & 0xFFFF;
// Lower 16 bits are vertical scanout position (scanline), upper 16 bits are vblank counter:
vblcount = (PsychOSKDReadRegister(crtcid, 0x616340 + crtco, NULL));
scanline = vblcount & 0xFFFF;
vblcount = (vblcount >> 16) & 0xFFFF;
if (verbose > 1 || verbose < 0) {
// printf("%i\n", (PsychOSKDReadRegister(crtcid, 0x616340 + crtco + 4 * verbose, NULL)));
long int i;
// crtc stride for CRTC control block (CRTC_VAL at offset 0xa00, stride 0x540)
crtco = (crtcid > 0) ? 0x540 : 0;
// for (i=0; i<=0xfffffc; i+=4) {
for (i=0; i<0x540; i+=4) {
// unsigned int base = 0x610000; // Display on NV50
//no unsigned int base = 0x600000;
// unsigned int base = 0x00008000;
//crtco = 0x540;
unsigned long int base = 0x610000 + 0xa00 + crtco;
vblcount = PsychOSKDReadRegister(crtcid, base + i, NULL);
unsigned int hi = vblcount >> 16;
unsigned int lo = vblcount & 0xffff;
// if ((vblcount > 0 && vblcount < 50) || (hi > 0 && hi < 50) || (hi> 750 && hi < 850) || (lo > 0 && lo < 50) || (lo> 750 && lo < 850)) {
// if (abs((int)(hi + lo) - 38) < 5) {
if (1) {
printf("%p :: hi = %i , lo = %i , val = %i\n", (void*) (base + i), hi, lo, vblcount);
}
}
// printf("%i\n", (PsychOSKDReadRegister(crtcid, 0x0068080c + crtco, NULL)));
}
// SYNC_START_TO_BLANK_END high-word in CRTC_VAL block of NV50_PDISPLAY on NV-50 encodes
// length of interval from vsync start line to vblank end line, the corrective offset we
// need to subtract from scanline position. Scanline position measures positive distance from
// vsync start line (== scanline 0).
// To low-word likely encodes hsyncstart to hblank end length.
int vbloffset = (PsychOSKDReadRegister(crtcid, 0x610000 + 0xa00 + 0xe8 + ((crtcid > 0) ? 0x540 : 0), NULL) >> 16) & 0xFFFF;
// DISPLAY_TOTAL: Encodes VTOTAL in high-word, HTOTAL in low-word:
int vtotal = (PsychOSKDReadRegister(crtcid, 0x610000 + 0xa00 + 0xf8 + ((crtcid > 0) ? 0x540 : 0), NULL) >> 16) & 0xFFFF;
printf("head %i: vbloffset = %i : vtotal = %i\n", crtcid, vbloffset, vtotal);
}
else {
// NV40 or earlier, aka GeForce-7000 or earlier: Same registers down to
// earliest NVidia cards NV04 aka RivaTNT-1:
// Offset between crtc's is 0x2000:
crtco = (crtcid > 0) ? 0x2000 : 0;
// Lower 12 bits are vertical scanout position, bit 16 is known to
// indicate "in vblank" status. All other bits are always zero:
vblcount = (PsychOSKDReadRegister(crtcid, 0x600808 + crtco, NULL));
scanline = vblcount & 0xFFF;
// Bit 4 after right-shift should indicate "in vblank", other bits
// are always zero:
vblcount = vblcount >> 12;
// No support for readout of horizontal scanout position so far:
scanpixel = 0;
}
if (verbose == 1) printf("NV-%x : CRTC %i : scanout x,y = %i , %i -- vblCount %i\n", cardId, crtcid, scanpixel, scanline, vblcount);
PsychCopyOutDoubleArg(1, FALSE, (double) scanpixel);
PsychCopyOutDoubleArg(2, FALSE, (double) scanline);
PsychCopyOutDoubleArg(3, FALSE, (double) vblcount);
// Done with NVidia GPU test:
return(PsychError_none);
}
// Must be a non-NVidia, hopefully an ATI/AMD piece, otherwise we die:
// Get basis parameters:
vbl = PsychOSKDReadRegister(crtcid, AVIVO_D1CRTC_V_BLANK_START_END + crtco, NULL);
vbl_start = vbl & RADEON_VBEAMPOSITION_BITMASK;
vbl_end = (vbl >> 16) & RADEON_VBEAMPOSITION_BITMASK;
vtotal = PsychOSKDReadRegister(crtcid, AVIVO_D1CRTC_V_TOTAL + crtco, NULL);
htotal = PsychOSKDReadRegister(crtcid, AVIVO_D1CRTC_H_TOTAL + crtco, NULL) + 1;
// Dotclock shall be 160 Mhz:
dotclock = 120 * 1e6;
// Convert line length in pixel and video dot clock to line duration
// in nanoseconds:
linedur_ns = htotal * 1e9 / dotclock;
pixeldur_ns = 1e9 / dotclock;
if (verbose > 1) printf("CRTC %i : vbl_start %i : vbl_end %i : vtotal %i : htotal %i : linedur_ns = %i\n", crtcid, vbl_start, vbl_end, vtotal, htotal, linedur_ns);
// Query current beampos:
if (pedantic) {
scanline = PsychOSKDReadRegister(crtcid, RADEON_D1CRTC_STATUS_POSITION + crtco, NULL);
scanpixel = (scanline >> RADEON_HBEAMPOSITION_BITSHIFT) & RADEON_VBEAMPOSITION_BITMASK;
scanline = scanline & RADEON_VBEAMPOSITION_BITMASK;
}
else {
scanline = PsychOSKDReadRegister(crtcid, RADEON_D1CRTC_STATUS_POSITION + crtco, NULL) & RADEON_VBEAMPOSITION_BITMASK;
}
// Query current time:
gettimeofday(&raw_time, NULL);
// In vertical blank?
if ((scanline < vbl_start) && (scanline >= vbl_end))
invbl = FALSE;
scanline = scanline - vbl_end;
if (invbl && (scanline >= vbl_end))
scanline = scanline - vtotal - 1;
// Seconds field will always be zero for any video refresh
// with a duration of less than 1 hour per frame:
delta_time.tv_sec = 0;
// Want vblank_time = raw_time - delta_time, but
// split it into cases delta_time >= 0 aka scanline >=0
// and delta_time < 0 aka scanline < 0.
// This because timeradd/sub only operate on positive 2nd
// operand:
if (scanline >= 0) {
// Convert scanline into microseconds elapsed:
delta_time.tv_usec = scanline * linedur_ns / 1000;
if (pedantic) delta_time.tv_usec = (scanline * linedur_ns + scanpixel * pixeldur_ns) / 1000;
timersub(&raw_time, &delta_time, &vblank_time);
}
else {
// Convert scanline into microseconds to go:
delta_time.tv_usec = -scanline * linedur_ns / 1000;
if (pedantic) delta_time.tv_usec = (-scanline * linedur_ns + scanpixel * pixeldur_ns) / 1000;
timeradd(&raw_time, &delta_time, &vblank_time);
}
// Map vblank_time to double value tUptime -- time in GetSecs() reference.
double tUptime;
PsychGetAdjustedPrecisionTimerSeconds(&tUptime);
tUptime = ((double) raw_time.tv_sec + ((double) raw_time.tv_usec) / 1e6) - tUptime;
tUptime = ((double) vblank_time.tv_sec + ((double) vblank_time.tv_usec) / 1e6) - tUptime;
if (verbose > 0) printf("CRTC %i : At time %i.%i secs : Scanline %i : vblank = %i.%i secs.\n", crtcid, raw_time.tv_sec, raw_time.tv_usec, scanline, vblank_time.tv_sec, vblank_time.tv_usec);
PsychCopyOutDoubleArg(1, FALSE, (double) tUptime);
// Done.
return(PsychError_none);
// ----------------------------------
char pbuf[1024];
int residualLength = 1024;
// if (infoType == 2) {
// // MMIO register Read for screenid "auxArg1", register offset "auxArg2":
// PsychCopyInDoubleArg(3, TRUE, &auxArg1);
// PsychCopyInDoubleArg(4, TRUE, &auxArg2);
// PsychCopyOutDoubleArg(1, FALSE, (double) PsychOSKDReadRegister((int) auxArg1, (unsigned int) auxArg2, NULL));
// }
//
// if (infoType == 3) {
// // MMIO register Write for screenid "auxArg1", register offset "auxArg2", to value "auxArg3":
// PsychCopyInDoubleArg(3, TRUE, &auxArg1);
// PsychCopyInDoubleArg(4, TRUE, &auxArg2);
// PsychCopyInDoubleArg(5, TRUE, &auxArg3);
// PsychOSKDWriteRegister((int) auxArg1, (unsigned int) auxArg2, (unsigned int) auxArg3, NULL);
// }
//WORKS: io_registry_entry_t myentry = IORegistryEntryFromPath(kIOMasterPortDefault, kIOServicePlane ":/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/PEGP@1/IOPCI2PCIBridge/display@0/ATY,Wormy@0/ATY_Wormy/display0/AppleBacklightDisplay");
//WORKS: io_registry_entry_t myentry = IORegistryEntryFromPath(kIOMasterPortDefault, kIOServicePlane ":/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/PEGP@1/IOPCI2PCIBridge/display@0/ATY,Wormy@0/ATY_Wormy/display0");
io_registry_entry_t myentry = IORegistryEntryFromPath(kIOMasterPortDefault, kIOServicePlane ":/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/PEGP@1/IOPCI2PCIBridge/display@0");
if (myentry == MACH_PORT_NULL) PsychErrorExitMsg(PsychError_system, "PTB-DEBUG: FAILED TO FIND IORegistryEntry!\n");
printf("GOT IORegistryEntry! >> ");
if (1) {
CFDataRef myprop = IORegistryEntryCreateCFProperty(myentry, CFSTR("AAPL00,Dither"), kCFAllocatorDefault, 0);
if (myprop == NULL) PsychErrorExitMsg(PsychError_system, "PTB-DEBUG: FAILED TO FIND AAPL00,Dither key!!\n");
m = CFDataGetLength(myprop);
printf("Amount of data stored in key 'AAPL00,Dither' is %i bytes.\nData: ", m);
psych_uint8* mypropdata = CFDataGetMutableBytePtr((CFMutableDataRef) myprop);
if (mypropdata == NULL) PsychErrorExitMsg(PsychError_system, "PTB-DEBUG: FAILED TO GET MUTABLE DATA PTR OF AAPL00,Dither key!!\n");
for (i=0; i < m; i++) printf("%x ", mypropdata[i]);
mypropdata[0] = 0x1;
// FAILS with kIOReturnUnsupported error: printf("\n COMMIT! RC is %x [kIOReturnUnsupported = %x] \n", (int) IORegistryEntrySetCFProperty(myentry, CFSTR("AAPL00,Dither"), myprop), kIOReturnUnsupported);
io_connect_t myconnect;
if (0) {
// FAILS with kIOReturnUnsupported error:
if (kIOReturnSuccess == IOServiceOpen(CGDisplayIOServicePort(CGMainDisplayID()), mach_task_self(), 0, &myconnect)) {
printf("\n COMMIT-IOSERVICE2! RC is %x [kIOReturnUnsupported = %x] \n", (int) IOConnectSetCFProperty(myconnect, CFSTR("AAPL00,Dither"), myprop), kIOReturnUnsupported);
IOServiceClose(myconnect);
}
else {
printf("\nNOCON\n");
}
}
if (1) {
kern_return_t kernResult;
io_service_t service;
io_connect_t connect;
io_iterator_t iterator;
CFDictionaryRef classToMatch;
unsigned int i;
// Setup matching criterion to find our driver in the IORegistry device tree:
//WORKS but useless for our purpose:
classToMatch = IOServiceNameMatching("ATIRadeonX1000");
//WORKS but fails to open: classToMatch = IOServiceNameMatching("ATY,Wormy");
//WORKS, IS WHAT WE NEED but fails to open: classToMatch = IOServiceNameMatching("display");
if (classToMatch == NULL) {
printf("PTB-DEBUG: IOServiceMatching() for Psychtoolbox kernel support driver returned a NULL dictionary. Kernel driver support disabled.\n");
PsychErrorExitMsg(PsychError_system, "FAIL!");
}
// This creates an io_iterator_t of all instances of our driver that exist in the I/O Registry. Each installed graphics card
// will get its own instance of a driver. The iterator allows to iterate over all instances:
kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault, classToMatch, &iterator);
if (kernResult != KERN_SUCCESS) {
printf("PTB-DEBUG: IOServiceGetMatchingServices for Psychtoolbox kernel support driver returned 0x%08x. Kernel driver support disabled.\n", kernResult);
PsychErrorExitMsg(PsychError_system, "FAIL!");
}
// In a polished final version we would want to handle the case where more than one gfx-card is attached.
// The iterator would return multiple instances of our driver and we need to decide which one to connect to.
// For now, we do not handle this case but instead just get the first item from the iterator.
service = IOIteratorNext(iterator);
// Release the io_iterator_t now that we're done with it.
IOObjectRelease(iterator);
if (service == IO_OBJECT_NULL) {
printf("PTB-INFO: Couldn't find requested IOService.\n");
PsychErrorExitMsg(PsychError_system, "FAIL!");
}
// Try in a loop to open with different connect flags i = 0 to 0xffff:
for(i=0; i< 0xffff; i++) {
kernResult = IOServiceOpen(service, mach_task_self(), i, &myconnect);
if (kIOReturnSuccess == kernResult) {
printf("\nCOOLIO!\n");
printf("\n COMMIT-IOSERVICE3! RC is %x [kIOReturnUnsupported = %x] \n", (int) IOConnectSetCFProperty(myconnect, CFSTR("AAPL00,Dither"), myprop), kIOReturnUnsupported);
IOServiceClose(myconnect);
break;
}
else {
if (kernResult != kIOReturnUnsupported) printf("\nNOCON5(%i): %x\n", i, kernResult);
}
}
if (kIOReturnSuccess != kernResult) printf("PTB-INFO: Couldn't open requested IOService.\n");
}
CFRelease(myprop);
}
if (0) {
CFStringRef myprop = IORegistryEntryCreateCFProperty(myentry, CFSTR("name"), kCFAllocatorDefault, 0);
CFStringGetCString(myprop, pbuf, 1024, kCFStringEncodingASCII);
printf("Value of 'name' is %s .\n", (char*) pbuf);
CFRelease(myprop);
// IORegistryEntrySetCFProperty(myentry, CFSTR("name"), CFSTR("funkydisplay"));
// IORegistryEntrySetCFProperty(r, CFSTR("IORequestIdle"), kCFBooleanTrue);
}
// Release registry entry:
IOObjectRelease(myentry);
return(PsychError_none);
#if PSYCH_SYSTEM == PSYCH_OSX
printf("PTB-DEBUG: Shutting down connection to PsychtoolboxKernelDriver, if any...\n");
PsychOSShutdownPsychtoolboxKernelDriverInterface();
#endif
#if PSYCH_SYSTEM == PSYCH_LINUX
printf("PTB-DEBUG: PreRADEON_R500_GEN_INT_CNTL: %x\n", PsychOSKDReadRegister(0, 0x040, NULL));
PsychOSKDWriteRegister(0, 0x040, PsychOSKDReadRegister(0, 0x040, NULL) | 0x1, NULL);
PsychWaitIntervalSeconds(0.1);
printf("PTB-DEBUG: PostRADEON_R500_GEN_INT_CNTL: %x\n", PsychOSKDReadRegister(0, 0x040, NULL));
printf("PTB-DEBUG: RADEON_R500_GEN_INT_STATUS: %x\n", PsychOSKDReadRegister(0, 0x044, NULL));
printf("PTB-DEBUG: RADEON_R500_GEN_INT_CNTL: %x\n", PsychOSKDReadRegister(0, RADEON_R500_GEN_INT_CNTL, NULL));
printf("PTB-DEBUG: RADEON_R500_GEN_INT_STATUS: %x\n", PsychOSKDReadRegister(0, RADEON_R500_GEN_INT_STATUS, NULL));
printf("PTB-DEBUG: RADEON_D1CRTC_INTERRUPT_CONTROL: %x\n", PsychOSKDReadRegister(0, RADEON_D1CRTC_INTERRUPT_CONTROL, NULL));
#endif
return(PsychError_none);
//demonstrate how we find the function and subfunction names
//printf("Psychtoolbox function: %s, subfunction %s\n", PsychGetModuleName(), PsychGetFunctionName() );
//copy all the input argument to their outputs if we have doubles, if not error.
numInArgs = PsychGetNumInputArgs();
PsychErrorExit(PsychCapNumOutputArgs(numInArgs));
/*
numOutArgs = PsychGetNumOutputArgs();
numNamedOutArgs = PsychGetNumNamedOutputArgs();
printf("number of input arguments: %d\n", numInArgs);
printf("number of output arguments: %d\n", numOutArgs);
printf("number of named output arguments: %d\n", numNamedOutArgs);
*/
//iterate over each of the supplied inputs. If the input is a two-dimensional array
//of doubles or a character array, then copy it to the output.
for(i=1;i<=numInArgs;i++){
format = PsychGetArgType(i);
switch(format){
case PsychArgType_double:
if(PsychGetArgM(i)==1 && PsychGetArgN(i)==1){
tempValue=i; //if 1x1 double then the default return value is the arg position.
PsychCopyInDoubleArg(i, FALSE, &tempValue);
PsychCopyOutDoubleArg(i, FALSE, tempValue);
}else{
PsychAllocInDoubleMatArg(i, FALSE, &m, &n, &p, &array);
PsychCopyOutDoubleMatArg(i, FALSE, m, n, p, array);
}
break;
case PsychArgType_char:
str=NULL; //This tells PsychGetCharArg() to use its own (volatile) memory.
PsychAllocInCharArg(i, FALSE, &str);
PsychCopyOutCharArg(i, FALSE, str);
break;
case PsychArgType_default:
PsychCopyOutCharArg(i, FALSE, defaultString);
break;
default:
break;
}
}
return(PsychError_none);
#endif
}
|