/usr/share/psychtoolbox-3/PsychOpenGL/moglClutBlit.m is in psychtoolbox-3-common 3.0.14.20170103+git6-g605ff5c.dfsg1-1build1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 | function moglClutBlit(win, src, newclut)
% EXPERIMENTAL - BETA QUALITY:
%
% moglClutBlit(win, src [, newclut]) -- Blit an image into window, apply CLUT.
%
% moglClutBlit copies a texture image 'src' (either made via
% src = Screen('MakeTexture', ...) or an offscreen window created via
% src = Screen('OpenOffscreenWindow', ...)) to an onscreen window 'win'.
%
% During the copy, it applies a color lookup table (clut) to the texture,
% transforming the color indices in the input texture into RGB color
% pixels according to the color lookup table.
%
% The color lookup table contains 256 rows with 3 columns. The i'th row
% contains the Red, green and blue color values to be used when an input
% pixel with colorindex i-1 is used. Column 1 = Red component, column 2 =
% Green component, column 3 = blue component.
%
% The clut will be initialized to a gray-level ramp, i.e. index 1 =
% (0,0,0), index i+1 = (i, i, i), index 256 = (255, 255, 255).
%
% Arguments:
%
% 'src' texture handle or offscreen window handle of the image to copy.
% 'win' window handle of the target window.
% 'newclut' The new 256 rows by 3 columns clut. If you don't provide any
% clut, the clut from a previous call will be used. Initially it is a
% graylevel ramp.
%
% Usage:
% 1. Add the command "InitializeMatlabOpenGL" at the top of your script,
% before the first call to Screen('OpenWindow', ...). If you don't use any
% 3D graphics, InitializeMatlabOpenGL([], 0, 1); will be the fastest.
%
% 2. Create your color index image either as a texture, e.g., via
% src=Screen('MakeTexture', win, myimage), or create it as Offscreen window
% src=Screen('OpenOffscreenWindow', win) and draw your index colored
% stimulus into it.
%
% 3. Whenever you want to change the clut and draw the image with updated
% clut, call moglClutBlit(win, src, newclut); with newclut being the new
% color lookup table.
%
% 4. Call the Screen('Flip', ...) command to show the new image, drawn with
% the new clut.
%
% 5. At the end of your script and before you Screen('Close', win) or
% Screen('CloseAll'), call moglClutBlit() without parameters, so it can
% clean up after itself.
%
% See GLSLClutAnimDemo for an example.
%
% Note: This function requires you to use fairly recent graphics hardware
% with support for OpenGL Pixelshaders and the OpenGL shading language
% (GLSL). It won't work on old hardware. Use of cluts for 8 bit clut
% animation is deprecated. Today, most stimuli can be generated in much more
% flexible and elegant ways using PTB-3's new drawing features and OpenGL
% capabilities.
% History:
% 6.11.2006 Written (MK).
% 2.03.2008 Performance improvements (MK).
% Our handle to OpenGL:
global GL;
persistent initialized;
persistent remapshader;
persistent luttex;
persistent clut;
% First time invocation?
if isempty(initialized)
% Make sure GLSL and pixelshaders are supported on first call:
AssertGLSL;
extensions = glGetString(GL.EXTENSIONS);
if isempty(findstr(extensions, 'GL_ARB_fragment_shader'))
% No fragment shaders: This is a no go!
error('moglClutBlit: Sorry, this function does not work on your graphics hardware due to lack of sufficient support for fragment shaders.');
end
% Load our fragment shader for clut blit operations:
remapshader = LoadGLSLProgramFromFiles('ClutBlitShader.frag.txt');
glUseProgram(remapshader);
% Assign proper texture units for input image and clut:
shader_image = glGetUniformLocation(remapshader, 'Image');
shader_clut = glGetUniformLocation(remapshader, 'clut');
glUniform1i(shader_image, 0);
glUniform1i(shader_clut, 1);
glUseProgram(0);
% Build a gray-ramp as texture:
clut = uint8(zeros(1, 256*3));
for i=0:255
clut(1 + i*3 + 0)= i;
clut(1 + i*3 + 1)= i;
clut(1 + i*3 + 2)= i;
end
% Select the 2nd texture unit (unit 1) for setup:
glActiveTexture(GL.TEXTURE1);
luttex = glGenTextures(1);
glBindTexture(GL.TEXTURE_RECTANGLE_EXT, luttex);
glTexImage2D(GL.TEXTURE_RECTANGLE_EXT, 0, GL.RGBA, 256, 1, 0, GL.RGB, GL.UNSIGNED_BYTE, clut);
% Make sure we use nearest neighbour sampling:
glTexParameteri(GL.TEXTURE_RECTANGLE_EXT, GL.TEXTURE_MIN_FILTER, GL.NEAREST);
glTexParameteri(GL.TEXTURE_RECTANGLE_EXT, GL.TEXTURE_MAG_FILTER, GL.NEAREST);
% And that we clamp to edge:
glTexParameteri(GL.TEXTURE_RECTANGLE_EXT, GL.TEXTURE_WRAP_S, GL.CLAMP);
glTexParameteri(GL.TEXTURE_RECTANGLE_EXT, GL.TEXTURE_WRAP_T, GL.CLAMP);
% Default CLUT setup done: Switch back to texture unit 0:
glActiveTexture(GL.TEXTURE0);
% We are initialized:
initialized = 1;
end % of initialization.
% No arguments provided?
if nargin < 1
% This is a signal that we should shut-down and release all internal
% ressources:
glActiveTexture(GL.TEXTURE1);
glBindTexture(GL.TEXTURE_RECTANGLE_EXT, 0);
glDisable(GL.TEXTURE_RECTANGLE_EXT);
glDeleteTextures(1, luttex);
luttex=-1;
glActiveTexture(GL.TEXTURE0);
glUseProgram(0);
% Disabled for now: glDeleteProgram(remapshader);
remapshader=-1;
clear initialized;
clear clut;
return;
end
if nargin < 1 || isempty(win)
error('moglClutBlit: Handle to target onscreen window ''win'' missing!');
end
if nargin < 2 || isempty(src)
error('moglClutBlit: Handle to input image ''src'' (either texture or offscreen window) missing!');
end
% Select the 2nd texture unit (unit 1) for setup:
glActiveTexture(GL.TEXTURE1);
% Bind our clut texture to it:
glBindTexture(GL.TEXTURE_RECTANGLE_EXT, luttex);
% New clut provided?
if nargin > 2 && ~isempty(newclut)
% Yes. Update our clut texture with it.
% Size check:
if size(newclut,1)~=256 || size(newclut, 2)~=3
% Invalid or missing clut:
error('newclut of wrong size (must be 256 rows by 3 columns) provided!');
end
% Range check:
if ~isempty(find(newclut < 0)) || ~isempty(find(newclut > 255))
% Clut values out of range:
error('At least one value in newclut is not in required range 0 to 255!');
end
% Cast to integer and update our 'clut' array with new clut:
clut(1:3:end-2)= uint8(newclut(:, 1) + 0.5);
clut(2:3:end-1)= uint8(newclut(:, 2) + 0.5);
clut(3:3:end-0)= uint8(newclut(:, 3) + 0.5);
% Upload new clut:
glTexSubImage2D(GL.TEXTURE_RECTANGLE_EXT, 0, 0, 0, 256, 1, GL.RGB, GL.UNSIGNED_BYTE, clut);
end
% Switch back to texunit 0 - the primary one:
glActiveTexture(GL.TEXTURE0);
% Clut and shader are initialized. Activate shader:
%glUseProgram(remapshader);
% Perform blit with nearest neighbour filter:
%Screen('DrawTexture', win, src, [], [], 0, 0);
% New style: Needs Screen-MEX update to fix a bug in Screen before it can be used!
Screen('DrawTexture', win, src, [], [], 0, 0, [], [], remapshader);
% Disable shader:
%glUseProgram(0);
% We're done.
end
|