VirtualBox

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

Last change on this file since 28360 was 27889, checked in by vboxsync, 15 years ago

crOpenGL: more code for multiscreen support

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