VirtualBox

source: vbox/trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_projmatrix.c@ 20175

Last change on this file since 20175 was 15532, checked in by vboxsync, 16 years ago

crOpenGL: export to OSE

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 14.6 KB
Line 
1/* Copyright (c) 2001, Stanford University
2 * All rights reserved
3 *
4 * See the file LICENSE.txt for information on redistributing this software.
5 */
6
7#include "server_dispatch.h"
8#include "server.h"
9#include "cr_error.h"
10#include "state/cr_statetypes.h"
11#include "cr_mem.h"
12#include "cr_string.h"
13
14/*
15 * This file provides implementations of the basic OpenGL matrix functions.
16 * We often need to twiddle with their operation in order to make tilesorting
17 * and non-planar projections work.
18 */
19
20
21
22/*
23 * Determine which view and projection matrices to use when in stere mode.
24 * Return 0 = left eye, 1 = right eye.
25 */
26int crServerGetCurrentEye(void)
27{
28 if (cr_server.currentEye != -1) {
29 /* current eye was specified by tilesort SPU */
30 return cr_server.currentEye;
31 }
32 else {
33 /* we have a quad-buffered window and we're watching glDrawBuffer */
34 GLenum drawBuffer = cr_server.curClient->currentCtx->buffer.drawBuffer;
35 int eye = drawBuffer == GL_BACK_RIGHT || drawBuffer == GL_FRONT_RIGHT
36 || drawBuffer == GL_RIGHT;
37 return eye;
38 }
39}
40
41
42void SERVER_DISPATCH_APIENTRY crServerDispatchLoadMatrixf( const GLfloat *m )
43{
44 const GLenum matMode = cr_server.curClient->currentCtx->transform.matrixMode;
45 const CRMuralInfo *mural = cr_server.curClient->currentMural;
46
47 crStateLoadMatrixf( m );
48
49 if (matMode == GL_PROJECTION && mural->numExtents > 0) {
50 /* we're loading a matrix onto the projection stack -- better put the base
51 * projection there first! */
52 crServerApplyBaseProjection(&(mural->extents[mural->curExtent].
53 baseProjection));
54 }
55 else if (matMode == GL_MODELVIEW && cr_server.viewOverride) {
56 int eye = crServerGetCurrentEye();
57 crServerApplyViewMatrix(&cr_server.viewMatrix[eye]);
58 }
59 else {
60 cr_server.head_spu->dispatch_table.LoadMatrixf( m );
61 }
62}
63
64
65void SERVER_DISPATCH_APIENTRY crServerDispatchLoadMatrixd( const GLdouble *m )
66{
67 const GLenum matMode = cr_server.curClient->currentCtx->transform.matrixMode;
68 const CRMuralInfo *mural = cr_server.curClient->currentMural;
69
70 crStateLoadMatrixd( m );
71
72 if (matMode == GL_PROJECTION && mural->numExtents > 0) {
73 /* we're loading a matrix onto the projection stack -- better put the base
74 * projection there first! */
75 crServerApplyBaseProjection(&(mural->extents[mural->curExtent].
76 baseProjection));
77 }
78 else if (matMode == GL_MODELVIEW && cr_server.viewOverride) {
79 int eye = crServerGetCurrentEye();
80 crServerApplyViewMatrix(&cr_server.viewMatrix[eye]);
81 }
82 else {
83 cr_server.head_spu->dispatch_table.LoadMatrixd( m );
84 }
85}
86
87
88void SERVER_DISPATCH_APIENTRY crServerDispatchMultMatrixf( const GLfloat *m )
89{
90 const GLenum matMode = cr_server.curClient->currentCtx->transform.matrixMode;
91
92 if (matMode == GL_PROJECTION && cr_server.projectionOverride) {
93 /* load the overriding projection matrix */
94 int eye = crServerGetCurrentEye();
95 crStateLoadMatrix( &cr_server.projectionMatrix[eye] );
96 }
97 else {
98 /* the usual case */
99 crStateMultMatrixf( m );
100 cr_server.head_spu->dispatch_table.MultMatrixf( m );
101 }
102}
103
104
105void SERVER_DISPATCH_APIENTRY crServerDispatchMultMatrixd( const GLdouble *m )
106{
107 const GLenum matMode = cr_server.curClient->currentCtx->transform.matrixMode;
108
109 if (matMode == GL_PROJECTION && cr_server.projectionOverride) {
110 /* load the overriding projection matrix */
111 int eye = crServerGetCurrentEye();
112 crStateLoadMatrix( &cr_server.projectionMatrix[eye] );
113 }
114 else {
115 /* the usual case */
116 crStateMultMatrixd( m );
117 cr_server.head_spu->dispatch_table.MultMatrixd( m );
118 }
119}
120
121
122
123void SERVER_DISPATCH_APIENTRY crServerDispatchLoadIdentity( void )
124{
125 const GLenum matMode = cr_server.curClient->currentCtx->transform.matrixMode;
126 const CRMuralInfo *mural = cr_server.curClient->currentMural;
127
128 crStateLoadIdentity();
129
130 if (matMode == GL_PROJECTION && mural->numExtents > 0) {
131 /* we're loading a matrix onto the projection stack -- better put the base
132 * projection there first! */
133 crServerApplyBaseProjection(&(mural->extents[mural->curExtent].
134 baseProjection));
135 }
136 else if (matMode == GL_MODELVIEW && cr_server.viewOverride) {
137 int eye = crServerGetCurrentEye();
138 crServerApplyViewMatrix(&cr_server.viewMatrix[eye]);
139 }
140 else {
141 cr_server.head_spu->dispatch_table.LoadIdentity( );
142 }
143}
144
145
146
147/*
148 * The following code is used to deal with vertex programs.
149 * Basically, vertex programs might not directly use the usual
150 * OpenGL projection matrix to project vertices from eye coords to
151 * clip coords.
152 *
153 * If you're using Cg then the vertex programs it generates will have
154 * some comments that we can scan to figure out which program parameters
155 * contain the projection matrix.
156 * In this case, look at the Cg program code for a string like
157 * "ModelViewProj". Then set the crserver's 'vertprog_projection_param'
158 * config option to this name.
159 *
160 * If you're not using Cg, you may have to tell Chromium which program
161 * parameters contain the projection matrix.
162 * In this case, look at the OpenGL appliation's vertex program code to
163 * determine which program parameters contain the projection matrix.
164 * Then set the crserver's 'vertprog_projection_param' config option to
165 * the number of the parameter which holds the first row of the matrix.
166 *
167 * Yup, this is complicated.
168 *
169 */
170
171
172static void matmul(GLfloat r[16], const GLfloat p[16], const GLfloat q[16])
173{
174 GLfloat tmp[16];
175 int i, j, k;
176 for (i = 0; i < 4; i++) {
177 for (j = 0; j < 4; j++) {
178 GLfloat dot = 0.0;
179 for (k = 0; k < 4; k++) {
180 dot += p[i+4*k] * q[k+4*j];
181 }
182 tmp[i+4*j] = dot;
183 }
184 }
185 for (i = 0; i < 16; i++)
186 r[i] = tmp[i];
187}
188
189
190static CRServerProgram *
191LookupProgram(GLuint id)
192{
193 CRServerProgram *prog = crHashtableSearch(cr_server.programTable, id);
194 if (!prog) {
195 prog = (CRServerProgram *) crAlloc(sizeof(CRServerProgram));
196 if (!prog)
197 return NULL;
198 prog->id = id;
199 prog->projParamStart = cr_server.vpProjectionMatrixParameter;
200 crHashtableAdd(cr_server.programTable, id, prog);
201 }
202 return prog;
203}
204
205
206void SERVER_DISPATCH_APIENTRY
207crServerDispatchProgramLocalParameter4fARB(GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
208{
209 if (target == GL_VERTEX_PROGRAM_ARB) {
210 CRServerProgram *prog = LookupProgram(cr_server.currentProgram);
211
212 if (prog && prog->projParamStart != -1) {
213 if (index >= (GLuint) prog->projParamStart && index <= (GLuint) prog->projParamStart + 3) {
214 /* save the parameters as rows in the matrix */
215 const int i = index - prog->projParamStart;
216 prog->projMat[4*0+i] = x;
217 prog->projMat[4*1+i] = y;
218 prog->projMat[4*2+i] = z;
219 prog->projMat[4*3+i] = w;
220 }
221
222 /* When we get the 4th row (row==3) of the projection matrix we can
223 * then pre-multiply it by the base matrix and update the program
224 * parameters with the new matrix.
225 */
226 if (index == (GLuint) (prog->projParamStart + 3)) {
227 const CRMuralInfo *mural = cr_server.curClient->currentMural;
228 const GLfloat *baseMat = (const GLfloat *) &(mural->extents[mural->curExtent].baseProjection);
229 int i;
230 GLfloat mat[16];
231
232 /* pre-mult the projection matrix by the base projection */
233 matmul(mat, baseMat, prog->projMat);
234 /* update the program parameters with the new matrix */
235 for (i = 0; i < 4; i++) {
236 cr_server.head_spu->dispatch_table.ProgramLocalParameter4fARB(target, index + i - 3, mat[4*0+i], mat[4*1+i], mat[4*2+i], mat[4*3+i]);
237 }
238 return; /* done */
239 }
240 }
241 }
242
243 /* if we get here, pass the call through unchanged */
244 cr_server.head_spu->dispatch_table.ProgramLocalParameter4fARB(target, index, x, y, z, w);
245}
246
247
248void SERVER_DISPATCH_APIENTRY
249crServerDispatchProgramLocalParameter4dARB(GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w)
250{
251 crServerDispatchProgramLocalParameter4fARB(target, index, (GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
252}
253
254
255void SERVER_DISPATCH_APIENTRY
256crServerDispatchProgramParameter4fNV(GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
257{
258 if (target == GL_VERTEX_PROGRAM_NV) {
259 CRServerProgram *prog = LookupProgram(cr_server.currentProgram);
260
261 if (prog && prog->projParamStart != -1) {
262 if (index >= (GLuint) prog->projParamStart && index <= (GLuint) prog->projParamStart + 3) {
263 /* save the parameters as rows in the matrix */
264 const int i = index - prog->projParamStart;
265 prog->projMat[4*0+i] = x;
266 prog->projMat[4*1+i] = y;
267 prog->projMat[4*2+i] = z;
268 prog->projMat[4*3+i] = w;
269 }
270
271 /* When we get the 4th row (row==3) of the projection matrix we can
272 * then pre-multiply it by the base matrix and update the program
273 * parameters with the new matrix.
274 */
275 if (index == (GLuint) (prog->projParamStart + 3)) {
276 const CRMuralInfo *mural = cr_server.curClient->currentMural;
277 const GLfloat *baseMat = (const GLfloat *) &(mural->extents[mural->curExtent].baseProjection);
278 int i;
279 GLfloat mat[16];
280
281 /* pre-mult the projection matrix by the base projection */
282 matmul(mat, baseMat, prog->projMat);
283 /* update the program parameters with the new matrix */
284 for (i = 0; i < 4; i++) {
285 cr_server.head_spu->dispatch_table.ProgramParameter4fNV(target, index + i - 3, mat[4*0+i], mat[4*1+i], mat[4*2+i], mat[4*3+i]);
286 }
287 return; /* done */
288 }
289 }
290 }
291
292 /* if we get here, pass the call through unchanged */
293 cr_server.head_spu->dispatch_table.ProgramParameter4fNV(target, index, x, y, z, w);
294}
295
296
297void SERVER_DISPATCH_APIENTRY
298crServerDispatchProgramParameter4dNV(GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w)
299{
300 crServerDispatchProgramParameter4fNV(target, index, (GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
301}
302
303
304void SERVER_DISPATCH_APIENTRY
305crServerDispatchProgramStringARB(GLenum target, GLenum format, GLsizei len, const GLvoid *string)
306{
307 if (target == GL_VERTEX_PROGRAM_ARB &&
308 cr_server.vpProjectionMatrixVariable != NULL) {
309 /* scan the program string looking for 'vertprog_projection'
310 * If the program was generated by Cg, the info we want will look
311 * something like this:
312 * #var float4x4 ModelViewProj : : c[0], 4 : 1 : 1
313 */
314 CRServerProgram *prog = LookupProgram(cr_server.currentProgram);
315 CRASSERT(prog);
316 if (prog) {
317 const char *varPos, *paramPos;
318 varPos = crStrstr((const char *) string, cr_server.vpProjectionMatrixVariable);
319 if (varPos) {
320 paramPos = crStrstr(varPos, "c[");
321 if (paramPos) {
322 char number[10];
323 int i = 0;
324 paramPos += 2; /* skip "c[" */
325 while (crIsDigit(paramPos[i])) {
326 number[i] = paramPos[i];
327 i++;
328 }
329 number[i] = 0;
330 prog->projParamStart = crStrToInt(number);
331 }
332 }
333 else {
334 crWarning("Didn't find %s parameter in vertex program string",
335 cr_server.vpProjectionMatrixVariable);
336 }
337 }
338 }
339
340 /* pass through */
341 crStateProgramStringARB(target, format, len, string);
342 cr_server.head_spu->dispatch_table.ProgramStringARB(target, format, len, string);
343}
344
345
346void SERVER_DISPATCH_APIENTRY
347crServerDispatchLoadProgramNV(GLenum target, GLuint id, GLsizei len, const GLubyte *string)
348{
349 if (target == GL_VERTEX_PROGRAM_NV &&
350 cr_server.vpProjectionMatrixVariable != NULL) {
351 /* scan the program string looking for 'vertprog_projection'
352 * If the program was generated by Cg, the info we want will look
353 * something like this:
354 * #var float4x4 ModelViewProj : : c[0], 4 : 1 : 1
355 */
356 CRServerProgram *prog = LookupProgram(id);
357 CRASSERT(prog);
358 if (prog) {
359 const char *varPos, *paramPos;
360 varPos = crStrstr((const char *) string, cr_server.vpProjectionMatrixVariable);
361 if (varPos) {
362 paramPos = crStrstr(varPos, "c[");
363 if (paramPos) {
364 char number[10];
365 int i = 0;
366 paramPos += 2; /* skip "c[" */
367 while (crIsDigit(paramPos[i])) {
368 number[i] = paramPos[i];
369 i++;
370 }
371 number[i] = 0;
372 prog->projParamStart = crStrToInt(number);
373 }
374 }
375 else {
376 crWarning("Didn't find %s parameter in vertex program string",
377 cr_server.vpProjectionMatrixVariable);
378 }
379 }
380 }
381
382 /* pass through */
383 crStateLoadProgramNV(target, id, len, string);
384 cr_server.head_spu->dispatch_table.LoadProgramNV(target, id, len, string);
385}
386
387
388void SERVER_DISPATCH_APIENTRY
389crServerDispatchBindProgramARB(GLenum target, GLuint id)
390{
391 id = crServerTranslateProgramID(id);
392
393 if (target == GL_VERTEX_PROGRAM_ARB) {
394 CRServerProgram *prog = LookupProgram(id);
395 (void) prog;
396 cr_server.currentProgram = id;
397 }
398
399 /* pass through */
400 crStateBindProgramARB(target, id);
401 cr_server.head_spu->dispatch_table.BindProgramARB(target, id);
402}
403
404
405void SERVER_DISPATCH_APIENTRY
406crServerDispatchBindProgramNV(GLenum target, GLuint id)
407{
408 if (target == GL_VERTEX_PROGRAM_NV) {
409 CRServerProgram *prog = LookupProgram(id);
410 (void) prog;
411 cr_server.currentProgram = id;
412 }
413 /* pass through */
414 crStateBindProgramNV(target, id);
415 cr_server.head_spu->dispatch_table.BindProgramNV(target, id);
416}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette