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
|
/*
SCREENFillRect.c
AUTHORS:
Allen.Ingling@nyu.edu awi
mario.kleiner@tuebingen.mpg.de mk
PLATFORMS:
All.
HISTORY:
09/12/02 awi Created.
10/12/04 awi In useString: changed "SCREEN" to "Screen", and moved commas to inside [].
2/25/05 awi Relocated PsychSetGLContext() to outside condtional, it only executed for small rects.
glClearColor() now sets variable alpha, not static at 1.0 (255).
Added call to PsychUpdateAlphaBlendingFactorLazily(). Drawing now obeys settings by Screen('BlendFunction').
TO DO:
FillRect should detect when it is called without a rect argument and use glClearColor to clear the
window to the specified color because gl implementations may optinally accellerate that.
Break out the actual rendering commands into a seperate function because OpenWindow and OpenOffscreenWindow
need to call FillRect to initialize the window to the correct color.
*/
#include "Screen.h"
// If you change the useString then also change the corresponding synopsis string in ScreenSynopsis.c
static char useString[] = "Screen('FillRect', windowPtr [,color] [,rect] )";
// 1 2 3
static char synopsisString[] =
"Fill \"rect\". \"color\" is the clut index (scalar or [r g b] triplet or [r g b a] quadruple) "
"that you want to poke into each pixel; default produces white with the standard CLUT for this "
"window's pixelSize. Default \"rect\" is entire window, so you can use this function to clear "
"the window. Please note that clearing the entire window will set the background color of the "
"window to the clear color, ie., future Screen('Flip') commands will clear to the new background "
"clear color specified in Screen('FillRect').\n"
"Instead of filling one rectangle, you can also specify a list of multiple rectangles to be "
"filled - this is much faster when you need to draw many rectangles per frame. To fill n "
"rectangles, provide \"rect\" as a 4 rows by n columns matrix, each column specifying one "
"rectangle, e.g., rect(1,5)=left border of 5th rectange, rect(2,5)=top border of 5th rectangle, "
"rect(3,5)=right border of 5th rectangle, rect(4,5)=bottom border of 5th rectangle. If the "
"rectangles should have different colors, then provide \"color\" as a 3 or 4 row by n column "
"matrix, the i'th column specifiying the color of the i'th rectangle. ";
static char seeAlsoString[] = "FrameRect";
PsychError SCREENFillRect(void)
{
PsychColorType color;
PsychRectType rect;
PsychWindowRecordType *windowRecord;
double whiteValue;
psych_bool isArgThere, isScreenRect;
double *xy, *colors;
unsigned char *bytecolors;
int numRects, i, nc, mc, nrsize;
//all sub functions should have these two lines
PsychPushHelp(useString, synopsisString,seeAlsoString);
if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);};
//check for superfluous arguments
PsychErrorExit(PsychCapNumInputArgs(4)); //The maximum number of inputs
PsychErrorExit(PsychCapNumOutputArgs(0)); //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);
// Query, allocate and copy in all vectors...
numRects = 4;
nrsize = 0;
colors = NULL;
bytecolors = NULL;
// The negative position -3 means: xy coords are expected at position 3, but they are optional.
// NULL means - don't want a size's vector.
PsychPrepareRenderBatch(windowRecord, -3, &numRects, &xy, 2, &nc, &mc, &colors, &bytecolors, 0, &nrsize, NULL, FALSE);
isScreenRect=FALSE;
// Only up to one rect provided?
if (numRects <= 1) {
// Get the rect and draw it
isArgThere=PsychCopyInRectArg(kPsychUseDefaultArgPosition, FALSE, rect);
isScreenRect= (!isArgThere) || (isArgThere && PsychMatchRect(rect, windowRecord->clientrect));
if (isArgThere && IsPsychRectEmpty(rect)) return(PsychError_none);
}
// There are tons of cases where we can't use glClear() to do a fullscreen fill. E.g., it
// doesn't work on anything else than onscreen windows, doesn't work in many stereo modes
// unless imaging pipe is fully active, and doesn't work when color clamping is disabled
// by use of our own GLSL shader based workaround. If in doubt, we use a fullscreen rectangle
// blit to do the clear -- Slower and disables tons of gfx-driver optimizations like fast clears
// and framebuffer compression / Hyper-z stuff, but at least safe and well-defined:
if(isScreenRect && PsychIsOnscreenWindow(windowRecord) && !((windowRecord->defaultDrawShader != 0) && (windowRecord->defaultDrawShader == windowRecord->unclampedDrawShader)) &&
(windowRecord->stereomode < kPsychAnaglyphRGStereo || windowRecord->stereomode > kPsychAnaglyphBRStereo || (windowRecord->imagingMode > 0 && windowRecord->imagingMode != kPsychNeedFastOffscreenWindows))){
// Fullscreen rect fill which in GL is a special case which may be accelerated.
// We only use this fast-path on real onscreen windows, not on textures or
// offscreen windows.
//Get the color argument or use the default, then coerce to the form determened by the window depth.
isArgThere=PsychCopyInColorArg(2, FALSE, &color);
if(!isArgThere){
whiteValue=PsychGetWhiteValueFromWindow(windowRecord);
PsychLoadColorStruct(&color, kPsychIndexColor, whiteValue ); //index mode will coerce to any other.
}
PsychCoerceColorMode( &color);
// Disable any active shaders:
PsychSetShader(windowRecord, 0);
PsychConvertColorToDoubleVector(&color, windowRecord, windowRecord->clearColor);
PsychGLClear(windowRecord);
// Fixup possible low-level framebuffer layout changes caused by commands above this point. Needed from native 10bpc FB support to work reliably.
PsychFixupNative10BitFramebufferEnableAfterEndOfSceneMarker(windowRecord);
// Done with fast clear path.
}else{
// Subregion fill or fullscreen fill into offscreen window or texture: Draw a colored rect.
// At this point if we have a single color value, it is already set by PsychPrepareRenderBatch,
// so we can skip this: PsychSetGLColor(&color, windowRecord);
// that function has also set the proper shader, if any...
// Fullscreen or partial fill?
if (isScreenRect) {
// Fullscreen fill of a (non-)onscreen window:
// Draw a rect in the clear color:
PsychGLRect(windowRecord->clientrect);
// If this was an onscreen window which couldn't be glClear()'ed for some other reason,
// we need to set the glClearColor() in the windowRecord:
if (PsychIsOnscreenWindow(windowRecord)) {
//Get the color argument or use the default, then coerce to the form determened by the window depth.
isArgThere=PsychCopyInColorArg(2, FALSE, &color);
if(!isArgThere){
whiteValue=PsychGetWhiteValueFromWindow(windowRecord);
PsychLoadColorStruct(&color, kPsychIndexColor, whiteValue ); //index mode will coerce to any other.
}
PsychCoerceColorMode( &color);
PsychConvertColorToDoubleVector(&color, windowRecord, windowRecord->clearColor);
}
} else {
// Partial fill: Draw provided rects:
if (numRects>1) {
// Multiple rects provided: Draw the whole batch:
for (i=0; i<numRects; i++) {
// Per rect color provided?
if (nc>1) {
// Yes. Set color for this specific rect:
PsychSetArrayColor(windowRecord, i, mc, colors, bytecolors);
}
// Submit rect for drawing:
if (!IsPsychRectEmpty(rect)) PsychGLRect(&(xy[i*4]));
}
}
else {
// Single partial screen rect provided: Draw it.
PsychGLRect(rect);
}
}
}
// Mark end of drawing op. This is needed for single buffered drawing:
PsychFlushGL(windowRecord);
//All psychfunctions require this.
return(PsychError_none);
}
|