Actual source code: openglops.c
petsc-3.5.4 2015-05-23
2: /*
3: Defines the operations for the OpenGL PetscDraw implementation.
5: The eventual plan is to have a window system independent portion (that only uses gl...() routines) plus
6: several implementations for different Window interfaces:
7: -- glut (implmented)
8: -- Apple IOS EAGLContext https://developer.apple.com/library/ios/#documentation/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/WorkingwithOpenGLESContexts/WorkingwithOpenGLESContexts.html#//apple_ref/doc/uid/TP40008793-CH2-SW1
9: -- Apple NSOpenGLView http://developer.apple.com/library/mac/#documentation/graphicsimaging/conceptual/OpenGL-MacProgGuide/opengl_pg_concepts/opengl_pg_concepts.html#//apple_ref/doc/uid/TP40001987-CH208-SW1
10: -- Apple CGLContextObj http://developer.apple.com/library/mac/#documentation/graphicsimaging/Reference/CGL_OpenGL/Reference/reference.html#//apple_ref/doc/uid/TP40001186
11: */
13: #include <petsc-private/drawimpl.h> /*I "petscsys.h" I*/
14: #if defined(PETSC_HAVE_OPENGLES)
15: #import <UIKit/UIKit.h>
16: #import <GLKit/GLKit.h>
17: #import <OpenGLES/EAGLDrawable.h>
18: #import <OpenGLES/ES2/gl.h>
19: #elif defined(PETSC_HAVE_GLUT)
20: #if defined(__APPLE__) || defined(MACOSX)
21: #include <AvailabilityMacros.h>
22: #include <OpenGL/gl.h>
23: #include <OpenGL/glu.h>
24: #else
25: #include <GL/gl.h>
26: #include <GL/glu.h>
27: #endif
28: #endif
31: /*
32: These macros transform from the users coordinates to the OpenGL coordinates of -1,-1 to 1,1.
33: */
34: #define XTRANS(draw,x) (-1.0 + 2.0*((draw)->port_xl + (((x - (draw)->coor_xl)*((draw)->port_xr - (draw)->port_xl))/((draw)->coor_xr - (draw)->coor_xl))))
35: #define YTRANS(draw,y) (-1.0 + 2.0*((draw)->port_yl + (((y - (draw)->coor_yl)*((draw)->port_yr - (draw)->port_yl))/((draw)->coor_yr - (draw)->coor_yl))))
37: /*
38: These macros transform from the users coordinates to pixel coordinates.
39: */
40: #define XPTRANS(draw,win,x) (int)(((win)->w)*((draw)->port_xl + (((x - (draw)->coor_xl)*((draw)->port_xr - (draw)->port_xl))/((draw)->coor_xr - (draw)->coor_xl))))
41: #define YPTRANS(draw,win,y) (int)(((win)->h)*(1.0-(draw)->port_yl - (((y - (draw)->coor_yl)*((draw)->port_yr - (draw)->port_yl))/((draw)->coor_yr - (draw)->coor_yl))))
43: static unsigned char rcolor[256],gcolor[256],bcolor[256];
46: static PetscErrorCode InitializeColors(void)
47: {
51: rcolor[PETSC_DRAW_WHITE] = 255;
52: gcolor[PETSC_DRAW_WHITE] = 255;
53: bcolor[PETSC_DRAW_WHITE] = 255;
54: rcolor[PETSC_DRAW_BLACK] = 0;
55: gcolor[PETSC_DRAW_BLACK] = 0;
56: bcolor[PETSC_DRAW_BLACK] = 0;
57: rcolor[PETSC_DRAW_RED] = 255;
58: gcolor[PETSC_DRAW_RED] = 0;
59: bcolor[PETSC_DRAW_RED] = 0;
60: rcolor[PETSC_DRAW_GREEN] = 0;
61: gcolor[PETSC_DRAW_GREEN] = 128;
62: bcolor[PETSC_DRAW_GREEN] = 0;
63: rcolor[PETSC_DRAW_CYAN] = 0;
64: gcolor[PETSC_DRAW_CYAN] = 139;
65: bcolor[PETSC_DRAW_CYAN] = 139;
66: rcolor[PETSC_DRAW_BLUE] = 0;
67: gcolor[PETSC_DRAW_BLUE] = 0;
68: bcolor[PETSC_DRAW_BLUE] = 255;
69: rcolor[PETSC_DRAW_MAGENTA] = 255;
70: gcolor[PETSC_DRAW_MAGENTA] = 0;
71: bcolor[PETSC_DRAW_MAGENTA] = 255;
72: rcolor[PETSC_DRAW_AQUAMARINE] = 127;
73: gcolor[PETSC_DRAW_AQUAMARINE] = 255;
74: bcolor[PETSC_DRAW_AQUAMARINE] = 212;
75: rcolor[PETSC_DRAW_FORESTGREEN] = 34;
76: gcolor[PETSC_DRAW_FORESTGREEN] = 139;
77: bcolor[PETSC_DRAW_FORESTGREEN] = 34;
78: rcolor[PETSC_DRAW_ORANGE] = 255;
79: gcolor[PETSC_DRAW_ORANGE] = 165;
80: bcolor[PETSC_DRAW_ORANGE] = 0;
81: rcolor[PETSC_DRAW_VIOLET] = 238;
82: gcolor[PETSC_DRAW_VIOLET] = 130;
83: bcolor[PETSC_DRAW_VIOLET] = 238;
84: rcolor[PETSC_DRAW_BROWN] = 165;
85: gcolor[PETSC_DRAW_BROWN] = 42;
86: bcolor[PETSC_DRAW_BROWN] = 42;
87: rcolor[PETSC_DRAW_PINK] = 255;
88: gcolor[PETSC_DRAW_PINK] = 192;
89: bcolor[PETSC_DRAW_PINK] = 203;
90: rcolor[PETSC_DRAW_CORAL] = 255;
91: gcolor[PETSC_DRAW_CORAL] = 127;
92: bcolor[PETSC_DRAW_CORAL] = 80;
93: rcolor[PETSC_DRAW_GRAY] = 128;
94: gcolor[PETSC_DRAW_GRAY] = 128;
95: bcolor[PETSC_DRAW_GRAY] = 128;
96: rcolor[PETSC_DRAW_YELLOW] = 255;
97: gcolor[PETSC_DRAW_YELLOW] = 255;
98: bcolor[PETSC_DRAW_YELLOW] = 0;
99: rcolor[PETSC_DRAW_GOLD] = 255;
100: gcolor[PETSC_DRAW_GOLD] = 215;
101: bcolor[PETSC_DRAW_GOLD] = 0;
102: rcolor[PETSC_DRAW_LIGHTPINK] = 255;
103: gcolor[PETSC_DRAW_LIGHTPINK] = 182;
104: bcolor[PETSC_DRAW_LIGHTPINK] = 193;
105: rcolor[PETSC_DRAW_MEDIUMTURQUOISE] = 72;
106: gcolor[PETSC_DRAW_MEDIUMTURQUOISE] = 209;
107: bcolor[PETSC_DRAW_MEDIUMTURQUOISE] = 204;
108: rcolor[PETSC_DRAW_KHAKI] = 240;
109: gcolor[PETSC_DRAW_KHAKI] = 230;
110: bcolor[PETSC_DRAW_KHAKI] = 140;
111: rcolor[PETSC_DRAW_DIMGRAY] = 105;
112: gcolor[PETSC_DRAW_DIMGRAY] = 105;
113: bcolor[PETSC_DRAW_DIMGRAY] = 105;
114: rcolor[PETSC_DRAW_YELLOWGREEN] = 54;
115: gcolor[PETSC_DRAW_YELLOWGREEN] = 205;
116: bcolor[PETSC_DRAW_YELLOWGREEN] = 50;
117: rcolor[PETSC_DRAW_SKYBLUE] = 135;
118: gcolor[PETSC_DRAW_SKYBLUE] = 206;
119: bcolor[PETSC_DRAW_SKYBLUE] = 235;
120: rcolor[PETSC_DRAW_DARKGREEN] = 0;
121: gcolor[PETSC_DRAW_DARKGREEN] = 100;
122: bcolor[PETSC_DRAW_DARKGREEN] = 0;
123: rcolor[PETSC_DRAW_NAVYBLUE] = 0;
124: gcolor[PETSC_DRAW_NAVYBLUE] = 0;
125: bcolor[PETSC_DRAW_NAVYBLUE] = 128;
126: rcolor[PETSC_DRAW_SANDYBROWN] = 244;
127: gcolor[PETSC_DRAW_SANDYBROWN] = 164;
128: bcolor[PETSC_DRAW_SANDYBROWN] = 96;
129: rcolor[PETSC_DRAW_CADETBLUE] = 95;
130: gcolor[PETSC_DRAW_CADETBLUE] = 158;
131: bcolor[PETSC_DRAW_CADETBLUE] = 160;
132: rcolor[PETSC_DRAW_POWDERBLUE] = 176;
133: gcolor[PETSC_DRAW_POWDERBLUE] = 224;
134: bcolor[PETSC_DRAW_POWDERBLUE] = 230;
135: rcolor[PETSC_DRAW_DEEPPINK] = 255;
136: gcolor[PETSC_DRAW_DEEPPINK] = 20;
137: bcolor[PETSC_DRAW_DEEPPINK] = 147;
138: rcolor[PETSC_DRAW_THISTLE] = 216;
139: gcolor[PETSC_DRAW_THISTLE] = 191;
140: bcolor[PETSC_DRAW_THISTLE] = 216;
141: rcolor[PETSC_DRAW_LIMEGREEN] = 50;
142: gcolor[PETSC_DRAW_LIMEGREEN] = 205;
143: bcolor[PETSC_DRAW_LIMEGREEN] = 50;
144: rcolor[PETSC_DRAW_LAVENDERBLUSH] = 255;
145: gcolor[PETSC_DRAW_LAVENDERBLUSH] = 240;
146: bcolor[PETSC_DRAW_LAVENDERBLUSH] = 245;
147: rcolor[PETSC_DRAW_PLUM] = 221;
148: gcolor[PETSC_DRAW_PLUM] = 160;
149: bcolor[PETSC_DRAW_PLUM] = 221;
151: PetscDrawUtilitySetCmapHue(rcolor+PETSC_DRAW_BASIC_COLORS,gcolor+PETSC_DRAW_BASIC_COLORS,bcolor+PETSC_DRAW_BASIC_COLORS,256-PETSC_DRAW_BASIC_COLORS);
152: return(0);
153: }
155: static GLuint vertexshader,fragmentshader,shaderprogram;
158: static PetscErrorCode InitializeShader(void)
159: {
160: const char *vertexsource = "attribute vec2 position;\
161: attribute vec3 color; \
162: varying vec4 vColor;\
163: void main(void)\
164: {\
165: vColor = vec4(color,0.50);\
166: gl_Position = vec4(position,0.0,1.0);\
167: }\n";
168: #if defined(PETSC_HAVE_GLUT)
169: const char *fragmentsource = "varying vec4 vColor;\
170: void main (void)\
171: {\
172: gl_FragColor = vColor; \
173: }\n";
174: #else
175: const char *fragmentsource = "precision mediump float;\
176: varying vec4 vColor;\
177: void main (void)\
178: {\
179: gl_FragColor = vColor; \
180: }\n";
181: #endif
182: int isCompiled_VS, isCompiled_FS;
183: int isLinked;
184: GLenum err;
187: /* http://www.opengl.org/wiki/OpenGL_Shading_Language */
188: /* Create an empty vertex shader handle */
189: vertexshader = glCreateShader(GL_VERTEX_SHADER);
191: /* Send the vertex shader source code to GL */
192: /* Note that the source code is NULL character terminated. */
193: /* GL will automatically detect that therefore the length info can be 0 in this case (the last parameter) */
194: glShaderSource(vertexshader, 1, (const GLchar**)&vertexsource, 0);
196: /* Compile the vertex shader */
197: glCompileShader(vertexshader);
198: glGetShaderiv(vertexshader, GL_COMPILE_STATUS, &isCompiled_VS);
199: if (isCompiled_VS == GL_FALSE) {
201: int maxLength;
202: char *vertexInfoLog;
203: glGetShaderiv(vertexshader, GL_INFO_LOG_LENGTH, &maxLength);
204: PetscMalloc1(maxLength,&vertexInfoLog);
205: glGetShaderInfoLog(vertexshader, maxLength, &maxLength, vertexInfoLog);
206: SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Failed to compile vertex shader %s",vertexInfoLog);
207: }
209: /* Create an empty fragment shader handle */
210: fragmentshader = glCreateShader(GL_FRAGMENT_SHADER);
212: /* Send the fragment shader source code to GL */
213: /* Note that the source code is NULL character terminated. */
214: /* GL will automatically detect that therefore the length info can be 0 in this case (the last parameter) */
215: glShaderSource(fragmentshader, 1, (const GLchar**)&fragmentsource, 0);
217: /* Compile the fragment shader */
218: glCompileShader(fragmentshader);
219: glGetShaderiv(fragmentshader, GL_COMPILE_STATUS, &isCompiled_FS);
220: if (isCompiled_FS == GL_FALSE) {
222: int maxLength;
223: char *fragmentInfoLog;
224: glGetShaderiv(fragmentshader, GL_INFO_LOG_LENGTH, &maxLength);
225: PetscMalloc1(maxLength,&fragmentInfoLog);
226: glGetShaderInfoLog(fragmentshader, maxLength, &maxLength, fragmentInfoLog);
227: SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Failed to compile fragment shader %s",fragmentInfoLog);
228: }
230: /* If we reached this point it means the vertex and fragment shaders compiled and are syntax error free. */
231: /* We must link them together to make a GL shader program */
232: /* GL shader programs are monolithic. It is a single piece made of 1 vertex shader and 1 fragment shader. */
233: /* Assign our program handle a "name" */
234: shaderprogram = glCreateProgram();
236: /* Attach our shaders to our program */
237: glAttachShader(shaderprogram, vertexshader);
238: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
239: glAttachShader(shaderprogram, fragmentshader);
240: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
242: glBindAttribLocation(shaderprogram,0,"position");
243: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
244: glBindAttribLocation(shaderprogram,1,"color");
245: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
247: /* Link our program */
248: /* At this stage, the vertex and fragment programs are inspected, optimized and a binary code is generated for the shader. */
249: /* The binary code is uploaded to the GPU, if there is no error. */
250: glLinkProgram(shaderprogram);
252: /* Again, we must check and make sure that it linked. If it fails, it would mean either there is a mismatch between the vertex */
253: /* and fragment shaders. It might be that you have surpassed your GPU's abilities. Perhaps too many ALU operations or */
254: /* too many texel fetch instructions or too many interpolators or dynamic loops. */
256: glGetProgramiv(shaderprogram, GL_LINK_STATUS, &isLinked);
257: if (isLinked == GL_FALSE) {
258: /*
259: char *shaderProgramInfoLog;
260: glGetProgramiv(shaderprogram, GL_INFO_LOG_LENGTH, &maxLength);
261: shaderProgramInfoLog = new char[maxLength];
262: glGetProgramInfoLog(shaderprogram, maxLength, &maxLength, shaderProgramInfoLog);
263: free(shaderProgramInfoLog);
264: */
265: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Failed to compile fragment shader");
266: }
268: /* In your rendering code, you just need to call glUseProgram, call the various glUniform** to update your uniforms */
269: /* and then render. */
270: /* Load the shader into the rendering pipeline */
271: glUseProgram(shaderprogram);
272: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
273: return(0);
274: }
278: /*
279: This is currently all wrong, there is actually a separate shader for each window
280: so they cannot be stored as global
281: */
282: static PetscErrorCode FinalizeShader(void)
283: {
285: /* When the user shuts down your program, you should deallocate all your GL resources. */
286: /* Unbind your shader. */
287: glUseProgram(0);
288: /* Let's detach */
289: glDetachShader(shaderprogram, vertexshader);
290: glDetachShader(shaderprogram, fragmentshader);
291: /* Delete the shaders */
292: glDeleteShader(vertexshader);
293: glDeleteShader(fragmentshader);
294: /* Delete the shader object */
295: glDeleteProgram(shaderprogram);
296: return(0);
297: }
299: extern PetscErrorCode PetscDrawClear_OpenGL_Base(PetscDraw);
301: #if defined(PETSC_HAVE_GLUT)
302: #include <GLUT/glut.h>
303: typedef struct {
304: int win; /* OpenGL GLUT window identifier */
305: int x,y,w,h; /* Size and location of window */
306: } PetscDraw_OpenGL;
308: static int currentwindow = -1;
309: PETSC_STATIC_INLINE PetscErrorCode OpenGLWindow(PetscDraw_OpenGL *win)
310: {
311: if (win->win == currentwindow) return 0;
312: currentwindow = win->win;
313: glutSetWindow(win->win);
314: return 0;
315: }
317: PETSC_STATIC_INLINE PetscErrorCode OpenGLString(float x,float y, const char *str,size_t len,int icolor)
318: {
319: PetscInt i;
321: glColor3ub(rcolor[icolor],gcolor[icolor],bcolor[icolor]);
322: glRasterPos2f(x, y);
323: for (i = 0; i < len; i++) glutBitmapCharacter(GLUT_BITMAP_8_BY_13, str[i]);
324: return 0;
325: }
329: PetscErrorCode PetscDrawClear_OpenGL(PetscDraw draw)
330: {
334: PetscDrawClear_OpenGL_Base(draw);
335: return(0);
336: }
340: static PetscErrorCode PetscDrawGetPopup_OpenGL(PetscDraw draw,PetscDraw *popup)
341: {
345: PetscDrawCreate(PetscObjectComm((PetscObject)draw),NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,PETSC_DECIDE,PETSC_DECIDE,popup);
346: PetscDrawSetType(*popup,((PetscObject)draw)->type_name);
348: draw->popup = *popup;
349: return(0);
350: }
354: static PetscErrorCode PetscDrawStringVertical_OpenGL(PetscDraw draw,PetscReal x,PetscReal y,int c,const char chrs[])
355: {
356: PetscErrorCode ierr;
357: float xx,yy;
358: PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
359: PetscReal tw,th;
360: size_t i,n;
363: OpenGLWindow(win);
364: PetscStrlen(chrs,&n);
365: PetscDrawStringGetSize(draw,&tw,&th);
366: xx = XTRANS(draw,x);
367: for (i=0; i<n; i++) {
368: yy = YTRANS(draw,y-th*i);
369: OpenGLString(xx,yy,chrs+i,1,c);
370: }
371: return(0);
372: }
376: static PetscErrorCode PetscDrawString_OpenGL(PetscDraw draw,PetscReal x,PetscReal y,int c,const char chrs[])
377: {
378: PetscErrorCode ierr;
379: float xx,yy;
380: size_t len;
381: PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
382: char *substr;
383: PetscToken token;
386: xx = XTRANS(draw,x);
387: yy = YTRANS(draw,y);
388: OpenGLWindow(win);
390: PetscTokenCreate(chrs,'\n',&token);
391: PetscTokenFind(token,&substr);
392: PetscStrlen(substr,&len);
393: OpenGLString(xx,yy,substr,len,c);
394: PetscTokenFind(token,&substr);
395: while (substr) {
396: yy += 16;
397: PetscStrlen(substr,&len);
398: OpenGLString(xx,yy,substr,len,c);
399: PetscTokenFind(token,&substr);
400: }
401: PetscTokenDestroy(&token);
402: return(0);
403: }
407: static PetscErrorCode PetscDrawSetTitle_OpenGL(PetscDraw draw,const char title[])
408: {
409: PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
410: PetscErrorCode ierr;
413: OpenGLWindow(win);
414: glutSetWindowTitle(title);
415: return(0);
416: }
420: static PetscErrorCode PetscDrawDestroy_OpenGL(PetscDraw draw)
421: {
422: PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
423: PetscErrorCode ierr;
426: PetscDrawSynchronizedClear(draw);
427: PetscDrawDestroy(&draw->popup);
428: glutDestroyWindow(win->win);
429: PetscFree(win);
430: return(0);
431: }
435: static PetscErrorCode PetscDrawFlush_OpenGL(PetscDraw draw)
436: {
437: PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
438: PetscErrorCode ierr;
441: OpenGLWindow(win);
442: glutCheckLoop();
443: glFinish();
444: return(0);
445: }
449: static PetscErrorCode PetscDrawStringGetSize_OpenGL(PetscDraw draw,PetscReal *x,PetscReal *y)
450: {
451: PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
452: PetscInt w;
453: PetscErrorCode ierr;
456: OpenGLWindow(win);
457: w = glutBitmapWidth(GLUT_BITMAP_8_BY_13,'W');
458: if (x) *x = w*(draw->coor_xr - draw->coor_xl)/((win->w)*(draw->port_xr - draw->port_xl));
459: if (y) *y = (13./8.0)*w*(draw->coor_yr - draw->coor_yl)/((win->h)*(draw->port_yr - draw->port_yl));
460: return(0);
461: }
465: static PetscErrorCode PetscDrawResizeWindow_OpenGL(PetscDraw draw,int w,int h)
466: {
467: PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
468: PetscErrorCode ierr;
471: OpenGLWindow(win);
472: glutReshapeWindow(w,h);
473: PetscDrawFlush(draw);
474: PetscDrawCheckResizedWindow(draw);
475: return(0);
476: }
478: static PetscBool resized = PETSC_FALSE;
482: static PetscErrorCode PetscDrawCheckResizedWindow_OpenGL(PetscDraw draw)
483: {
487: if (!resized) return(0);
488: resized = PETSC_FALSE;
489: glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
490: PetscDrawClear(draw);
491: return(0);
492: }
494: typedef struct {
495: int button,x,y;
496: } OpenGLButton;
497: static OpenGLButton Mouse;
501: static PetscErrorCode PetscDrawGetMouseButton_OpenGL(PetscDraw draw,PetscDrawButton *button,PetscReal *x_user,PetscReal *y_user,PetscReal *x_phys,PetscReal *y_phys)
502: {
503: PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
504: int px,py;
507: while (Mouse.button == -1) glutCheckLoop();
509: *button = (PetscDrawButton)(Mouse.button + 1);
510: px = Mouse.x;
511: py = Mouse.y;
512: Mouse.button = -1;
514: if (x_phys) *x_phys = ((double)px)/((double)win->w);
515: if (y_phys) *y_phys = 1.0 - ((double)py)/((double)win->h);
517: if (x_user) *x_user = draw->coor_xl + ((((double)px)/((double)win->w)-draw->port_xl))*(draw->coor_xr - draw->coor_xl)/(draw->port_xr - draw->port_xl);
518: if (y_user) *y_user = draw->coor_yl + ((1.0 - ((double)py)/((double)win->h)-draw->port_yl))*(draw->coor_yr - draw->coor_yl)/(draw->port_yr - draw->port_yl);
519: return(0);
520: }
521: #elif defined(PETSC_HAVE_OPENGLES)
522: typedef struct {
523: GLint win; /* not currently used */
524: int w,h; /* width and height in pixels */
525: GLKView *view;
526: } PetscDraw_OpenGL;
528: static GLKView *globalGLKView[10] = {0,0,0,0,0,0,0,0,0,0};
530: PETSC_STATIC_INLINE PetscErrorCode OpenGLWindow(PetscDraw_OpenGL *win)
531: {
532: return 0;
533: }
537: static PetscErrorCode PetscDrawClear_OpenGL(PetscDraw draw)
538: {
539: PetscErrorCode ierr;
540: PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
543: /* remove all UIText added to window */
544: for (UIView *view in [win->view subviews]) {[view removeFromSuperview];}
545: PetscDrawClear_OpenGL_Base(draw);
546: return(0);
547: }
551: static PetscErrorCode PetscDrawGetPopup_OpenGL(PetscDraw draw,PetscDraw *popup)
552: {
556: *popup = NULL;
557: return(0);
558: }
562: static PetscErrorCode PetscDrawString_OpenGL(PetscDraw draw,PetscReal x,PetscReal y,int c,const char chrs[])
563: {
564: PetscErrorCode ierr;
565: float xx,yy;
566: PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
567: UILabel *yourLabel;
570: OpenGLWindow(win);
571: xx = XPTRANS(draw,win,x);
572: yy = YPTRANS(draw,win,y);
573: NSLog(@"Draw string start");
574: yourLabel = [[UILabel alloc] initWithFrame:CGRectMake(xx, yy, 300, 20)];
575: [yourLabel setTextColor:[UIColor colorWithRed:rcolor[c]/255.0 green:gcolor[c]/255.0 blue:rcolor[c]/255.0 alpha:1.0]];
576: [yourLabel setText: [[NSString alloc] initWithCString:chrs encoding:NSMacOSRomanStringEncoding]];
577: [yourLabel setBackgroundColor:[UIColor clearColor]];
578: /* [yourLabel setFont:[UIFont fontWithName: @"Trebuchet MS" size: 14.0f]]; */
579: [win->view addSubview:yourLabel];
580: NSLog(@"Draw string end");
581: return(0);
582: }
584: /*
585: I don't understand the rotation. It seems to maybe rotate from the middle of the width?
587: It would be nice if the frame could be made to match the text length automatically
589: This makes src/sys/draw/examples/tests/ex3.c look good but may be terrible for other locations
590: */
593: static PetscErrorCode PetscDrawStringVertical_OpenGL(PetscDraw draw,PetscReal x,PetscReal y,int c,const char chrs[])
594: {
595: PetscErrorCode ierr;
596: float xx,yy, w = 100,h = 20;
597: PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
598: UILabel *yourLabel;
601: OpenGLWindow(win);
602: xx = XPTRANS(draw,win,x);
603: yy = YPTRANS(draw,win,y);
604: NSLog(@"Draw string vertical start");
605: yourLabel = [[UILabel alloc] initWithFrame:CGRectMake(0,0, w, h)];
606: [yourLabel setTextColor:[UIColor colorWithRed:rcolor[c]/255.0 green:gcolor[c]/255.0 blue:rcolor[c]/255.0 alpha:1.0]];
607: [yourLabel setText: [[NSString alloc] initWithCString:chrs encoding:NSMacOSRomanStringEncoding]];
608: [yourLabel setBackgroundColor:[UIColor clearColor]];
609: [yourLabel setTransform:CGAffineTransformTranslate(CGAffineTransformMakeRotation(-PETSC_PI / 2),-w/2.0-yy,-h+xx)];
610: /* [yourLabel setFont:[UIFont fontWithName: @"Trebuchet MS" size: 14.0f]]; */
611: [win->view addSubview:yourLabel];
612: NSLog(@"Draw string vertical end");
613: return(0);
614: }
618: static PetscErrorCode PetscDrawSetTitle_OpenGL(PetscDraw draw,const char title[])
619: {
620: return 0;
621: }
624: static PetscErrorCode PetscDrawDestroy_OpenGL(PetscDraw draw)
625: {
626: PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
627: PetscErrorCode ierr;
628: PetscInt i;
631: for (i=0; i<10; i++) {
632: if (!globalGLKView[i]) {
633: globalGLKView[i] = win->view;
635: PetscFree(win);
636: return(0);
637: }
638: }
639: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Could not locate available GLKView slot");
640: return(0);
641: }
644: static PetscErrorCode PetscDrawFlush_OpenGL(PetscDraw draw)
645: {
646: PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
648: GLenum err;
649: glFlush();
650: err = glGetError();
651: if (err != GL_NO_ERROR) {
652: NSLog(@"GL error detected glFlush()");
653: SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unable to flush OpenGL Error Code %d",err);
654: }
655: [win->view display];
656: NSLog(@"Completed display in PetscDrawFlush()");
657: return 0;
658: }
661: static PetscErrorCode PetscDrawStringGetSize_OpenGL(PetscDraw draw,PetscReal *x,PetscReal *y)
662: {
663: float w = .02;
664: if (x) *x = w*(draw->coor_xr - draw->coor_xl)/(draw->port_xr - draw->port_xl);
665: if (y) *y = (13./8.0)*w*(draw->coor_yr - draw->coor_yl)/(draw->port_yr - draw->port_yl);
666: return 0;
667: }
670: static PetscErrorCode PetscDrawResizeWindow_OpenGL(PetscDraw draw,int w,int h)
671: {
672: return 0;
673: }
676: static PetscErrorCode PetscDrawCheckResizedWindow_OpenGL(PetscDraw draw)
677: {
678: return 0;
679: }
682: static PetscErrorCode PetscDrawGetMouseButton_OpenGL(PetscDraw draw,PetscDrawButton *button,PetscReal *x_user,PetscReal *y_user,PetscReal *x_phys,PetscReal *y_phys)
683: {
684: return 0;
685: }
686: #endif
688: /* -----------------------------------------------------------------------*/
691: static PetscErrorCode PetscDrawSynchronizedFlush_OpenGL(PetscDraw draw)
692: {
696: /* currently on sequential support */
697: PetscDrawFlush(draw);
698: return(0);
699: }
703: PetscErrorCode PetscDrawClear_OpenGL_Base(PetscDraw draw)
704: {
705: PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
706: PetscErrorCode ierr;
707: float xl,yl,xr,yr;
708: GLfloat vertices[12];
709: GLfloat colors[18];
710: GLuint positionBufferObject;
711: GLuint colorBufferObject;
712: GLenum err;
715: OpenGLWindow(win);
716: xl = -1.0 + 2.0*((draw)->port_xl);
717: xr = -1.0 + 2.0*((draw)->port_xr);
718: yl = -1.0 + 2.0*((draw)->port_yl);
719: yr = -1.0 + 2.0*((draw)->port_yr);
721: vertices[0] = xl;
722: vertices[1] = yl;
723: vertices[2] = xr;
724: vertices[3] = yl;
725: vertices[4] = xl;
726: vertices[5] = yr;
728: vertices[6] = xl;
729: vertices[7] = yr;
730: vertices[8] = xr;
731: vertices[9] = yr;
732: vertices[10] = xr;
733: vertices[11] = yl;
735: colors[0] = 1.0; colors[1] = 1.0; colors[2] = 1.0;
736: colors[3] = 1.0; colors[4] = 1.0; colors[5] = 1.0;
737: colors[6] = 1.0; colors[7] = 1.0; colors[8] = 1.0;
739: colors[9] = 1.0; colors[10] = 1.0; colors[11] = 1.0;
740: colors[12] = 1.0; colors[13] = 1.0; colors[14] = 1.0;
741: colors[15] = 1.0; colors[16] = 1.0; colors[17] = 1.0;
743: glGenBuffers(1, &positionBufferObject);
744: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
745: glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
746: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
747: glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
748: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
749: glEnableVertexAttribArray(0);
750: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
751: glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
752: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
754: glGenBuffers(1, &colorBufferObject);
755: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
756: glBindBuffer(GL_ARRAY_BUFFER, colorBufferObject);
757: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
758: glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
759: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
760: glEnableVertexAttribArray(1);
761: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
762: glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
763: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
765: glDrawArrays(GL_TRIANGLES, 0, 6);
766: glDisableVertexAttribArray(0);
767: glDisableVertexAttribArray(1);
768: glDeleteBuffers(1, &positionBufferObject);
769: glDeleteBuffers(1, &colorBufferObject);
770: PetscDrawFlush(draw);
771: return(0);
772: }
776: static PetscErrorCode PetscDrawSynchronizedClear_OpenGL(PetscDraw draw)
777: {
781: /* currently only sequential support */
782: PetscDrawClear(draw);
783: return(0);
784: }
788: static PetscErrorCode PetscDrawPoint_OpenGL(PetscDraw draw,PetscReal xl,PetscReal yl,int cl)
789: {
790: PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
791: GLfloat vertices[2],colors[3];
792: PetscErrorCode ierr;
793: GLuint positionBufferObject;
794: GLuint colorBufferObject;
795: GLenum err;
798: vertices[0] = XTRANS(draw,xl);
799: vertices[1] = YTRANS(draw,yl);
800: colors[0] = rcolor[cl]/255.0; colors[1] = gcolor[cl]/255.0; colors[2] = bcolor[cl]/255.0;
802: OpenGLWindow(win);
803: glGenBuffers(1, &positionBufferObject);
804: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
805: glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
806: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
807: glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
808: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
809: glEnableVertexAttribArray(0);
810: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
811: glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
812: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
814: glGenBuffers(1, &colorBufferObject);
815: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
816: glBindBuffer(GL_ARRAY_BUFFER, colorBufferObject);
817: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
818: glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
819: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
820: glEnableVertexAttribArray(1);
821: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
822: glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
823: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
825: glDrawArrays(GL_POINTS, 0, 2);
826: glDisableVertexAttribArray(0);
827: glDisableVertexAttribArray(1);
828: glDeleteBuffers(1, &positionBufferObject);
829: glDeleteBuffers(1, &colorBufferObject);
830: return(0);
831: }
835: static PetscErrorCode PetscDrawLine_OpenGL(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int cl)
836: {
837: PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
838: GLfloat linevertices[4],colors[6];
839: PetscErrorCode ierr;
840: GLenum err;
841: GLuint positionBufferObject;
842: GLuint colorBufferObject;
846: linevertices[0] = XTRANS(draw,xl);
847: linevertices[2] = XTRANS(draw,xr);
848: linevertices[1] = YTRANS(draw,yl);
849: linevertices[3] = YTRANS(draw,yr);
850: if (linevertices[0] == linevertices[2] && linevertices[1] == linevertices[3]) return(0);
851: colors[0] = rcolor[cl]/255.0; colors[1] = gcolor[cl]/255.0; colors[2] = bcolor[cl]/255.0;
852: colors[3] = rcolor[cl]/255.0; colors[4] = gcolor[cl]/255.0; colors[5] = bcolor[cl]/255.0;
854: OpenGLWindow(win);
855: /* http://arcsynthesis.org/gltut/Basics/Tutorial%2001.html */
856: glGenBuffers(1, &positionBufferObject);
857: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
858: glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
859: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
860: glBufferData(GL_ARRAY_BUFFER, sizeof(linevertices), linevertices, GL_STATIC_DRAW);
861: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
862: glEnableVertexAttribArray(0);
863: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
864: glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
865: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
867: glGenBuffers(1, &colorBufferObject);
868: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
869: glBindBuffer(GL_ARRAY_BUFFER, colorBufferObject);
870: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
871: glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
872: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
873: glEnableVertexAttribArray(1);
874: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
875: glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
876: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
878: glDrawArrays(GL_LINES, 0, 2);
879: glDisableVertexAttribArray(0);
880: glDisableVertexAttribArray(1);
881: glDeleteBuffers(1, &positionBufferObject);
882: glDeleteBuffers(1, &colorBufferObject);
883: return(0);
884: }
888: static PetscErrorCode PetscDrawTriangle_OpenGL(PetscDraw draw,PetscReal X1,PetscReal Y_1,PetscReal X2,PetscReal Y2,PetscReal X3,PetscReal Y3,int c1,int c2,int c3)
889: {
890: PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
891: PetscErrorCode ierr;
892: GLfloat vertices[6],colors[9];
893: GLenum err;
894: GLuint positionBufferObject;
895: GLuint colorBufferObject;
898: vertices[0] = XTRANS(draw,X1);
899: vertices[1] = YTRANS(draw,Y_1);
900: vertices[2] = XTRANS(draw,X2);
901: vertices[3] = YTRANS(draw,Y2);
902: vertices[4] = XTRANS(draw,X3);
903: vertices[5] = YTRANS(draw,Y3);
904: colors[0] = rcolor[c1]/255.0; colors[1] = gcolor[c1]/255.0; colors[2] = bcolor[c1]/255.0;
905: colors[3] = rcolor[c2]/255.0; colors[4] = gcolor[c2]/255.0; colors[5] = bcolor[c2]/255.0;
906: colors[6] = rcolor[c3]/255.0; colors[7] = gcolor[c3]/255.0; colors[8] = bcolor[c3]/255.0;
908: OpenGLWindow(win);
909: glGenBuffers(1, &positionBufferObject);
910: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
911: glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
912: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
913: glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
914: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
915: glEnableVertexAttribArray(0);
916: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
917: glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
918: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
920: glGenBuffers(1, &colorBufferObject);
921: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
922: glBindBuffer(GL_ARRAY_BUFFER, colorBufferObject);
923: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
924: glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
925: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
926: glEnableVertexAttribArray(1);
927: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
928: glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
929: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
931: glDrawArrays(GL_TRIANGLES, 0, 3);
932: glDisableVertexAttribArray(0);
933: glDisableVertexAttribArray(1);
934: glDeleteBuffers(1, &positionBufferObject);
935: glDeleteBuffers(1, &colorBufferObject);
936: return(0);
937: }
941: static PetscErrorCode PetscDrawRectangle_OpenGL(PetscDraw draw,PetscReal Xl,PetscReal Yl,PetscReal Xr,PetscReal Yr,int c1,int c2,int c3,int c4)
942: {
943: PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
944: PetscErrorCode ierr;
945: GLfloat vertices[12],colors[18];
946: float x1,y_1,x2,y2;
947: GLuint positionBufferObject;
948: GLuint colorBufferObject;
949: GLenum err;
952: x1 = XTRANS(draw,Xl);
953: y_1 = YTRANS(draw,Yl);
954: x2 = XTRANS(draw,Xr);
955: y2 = YTRANS(draw,Yr);
957: OpenGLWindow(win);
959: vertices[0] = x1; colors[0] = rcolor[c1]/255.0; colors[1] = gcolor[c1]/255.0; colors[2] = bcolor[c1]/255.0;
960: vertices[1] = y_1;
961: vertices[2] = x2;colors[3] = rcolor[c2]/255.0; colors[4] = gcolor[c2]/255.0; colors[5] = bcolor[c2]/255.0;
962: vertices[3] = y_1;
963: vertices[4] = x1;colors[6] = rcolor[c4]/255.0; colors[7] = gcolor[c4]/255.0; colors[8] = bcolor[c4]/255.0;
964: vertices[5] = y2;
966: vertices[6] = x1;colors[9] = rcolor[c4]/255.0; colors[10] = gcolor[c4]/255.0; colors[11] = bcolor[c4]/255.0;
967: vertices[7] = y2;
968: vertices[8] = x2;colors[12] = rcolor[c3]/255.0; colors[13] = gcolor[c3]/255.0; colors[14] = bcolor[c3]/255.0;
969: vertices[9] = y2;
970: vertices[10] = x2;colors[15] = rcolor[c2]/255.0; colors[16] = gcolor[c2]/255.0; colors[17] = bcolor[c2]/255.0;
971: vertices[11] = y_1;
973: glGenBuffers(1, &positionBufferObject);
974: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
975: glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
976: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
977: glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
978: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
979: glEnableVertexAttribArray(0);
980: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
981: glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
982: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
984: glGenBuffers(1, &colorBufferObject);
985: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
986: glBindBuffer(GL_ARRAY_BUFFER, colorBufferObject);
987: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
988: glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
989: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
990: glEnableVertexAttribArray(1);
991: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
992: glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
993: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
995: glDrawArrays(GL_TRIANGLES, 0, 6);
996: glDisableVertexAttribArray(0);
997: glDisableVertexAttribArray(1);
998: glDeleteBuffers(1, &positionBufferObject);
999: glDeleteBuffers(1, &colorBufferObject);
1000: return(0);
1001: }
1006: static PetscErrorCode PetscDrawPause_OpenGL(PetscDraw draw)
1007: {
1011: if (draw->pause > 0) PetscSleep(draw->pause);
1012: else if (draw->pause == -1) {
1013: PetscDrawButton button;
1014: PetscMPIInt rank;
1015: MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);
1016: if (!rank) {
1017: PetscDrawGetMouseButton(draw,&button,0,0,0,0);
1018: if (button == PETSC_BUTTON_CENTER) draw->pause = 0;
1019: }
1020: MPI_Bcast(&draw->pause,1,MPI_INT,0,PetscObjectComm((PetscObject)draw));
1021: }
1022: return(0);
1023: }
1026: static struct _PetscDrawOps DvOps = { 0,
1027: PetscDrawFlush_OpenGL,
1028: PetscDrawLine_OpenGL,
1029: 0,
1030: 0,
1031: PetscDrawPoint_OpenGL,
1032: 0,
1033: PetscDrawString_OpenGL,
1034: PetscDrawStringVertical_OpenGL,
1035: 0, /* PetscDrawStringSetSize_OpenGL,*/
1036: PetscDrawStringGetSize_OpenGL,
1037: 0, /* PetscDrawSetViewport_OpenGL,*/
1038: PetscDrawClear_OpenGL,
1039: PetscDrawSynchronizedFlush_OpenGL,
1040: PetscDrawRectangle_OpenGL,
1041: PetscDrawTriangle_OpenGL,
1042: 0, /* PetscDrawEllipse_OpenGL,*/
1043: PetscDrawGetMouseButton_OpenGL,
1044: PetscDrawPause_OpenGL,
1045: PetscDrawSynchronizedClear_OpenGL,
1046: 0,
1047: 0,
1048: PetscDrawGetPopup_OpenGL,
1049: PetscDrawSetTitle_OpenGL,
1050: PetscDrawCheckResizedWindow_OpenGL,
1051: PetscDrawResizeWindow_OpenGL,
1052: PetscDrawDestroy_OpenGL,
1053: 0,
1054: 0, /* PetscDrawGetSingleton_OpenGL,*/
1055: 0, /* PetscDrawRestoreSingleton_OpenGL,*/
1056: 0,
1057: 0,
1058: 0,
1059: PetscDrawLine_OpenGL};
1061: #if defined(PETSC_HAVE_GLUT)
1062: /* callbacks required by GLUT */
1063: static void display(void) {;}
1064: static void reshape(int width, int height)
1065: {
1066: glViewport(0, 0, width, height);
1067: resized = PETSC_TRUE;
1068: }
1069: static void mouse(int button, int state,int x, int y)
1070: {
1071: if (state == GLUT_UP) {
1072: Mouse.button = button;
1073: Mouse.x = x;
1074: Mouse.y = y;
1075: }
1076: }
1080: PETSC_EXTERN PetscErrorCode PetscDrawCreate_GLUT(PetscDraw draw)
1081: {
1082: PetscDraw_OpenGL *win;
1083: PetscErrorCode ierr;
1084: PetscInt xywh[4],osize = 4;
1085: int x = draw->x,y = draw->y,w = draw->w,h = draw->h;
1086: static int xavailable = 0,yavailable = 0,xmax = 0,ymax = 0,ybottom = 0;
1087: static PetscBool initialized = PETSC_FALSE;
1088: int argc;
1089: char **argv;
1092: if (!initialized) {
1093: PetscGetArgs(&argc,&argv);
1094: glutInit(&argc, argv);
1095: glutInitDisplayMode(GLUT_RGBA /* | GLUT_DOUBLE */| GLUT_DEPTH);
1096: InitializeColors();
1097: }
1099: /*
1100: Initialize the display size
1101: */
1102: if (!xmax) {
1103: xmax = glutGet(GLUT_SCREEN_WIDTH);
1104: ymax = glutGet(GLUT_SCREEN_HEIGHT);
1105: }
1107: if (w == PETSC_DECIDE) w = draw->w = 300;
1108: if (h == PETSC_DECIDE) h = draw->h = 300;
1109: switch (w) {
1110: case PETSC_DRAW_FULL_SIZE: w = draw->w = xmax - 10; break;
1111: case PETSC_DRAW_HALF_SIZE: w = draw->w = (xmax - 20)/2; break;
1112: case PETSC_DRAW_THIRD_SIZE: w = draw->w = (xmax - 30)/3; break;
1113: case PETSC_DRAW_QUARTER_SIZE: w = draw->w = (xmax - 40)/4; break;
1114: }
1115: switch (h) {
1116: case PETSC_DRAW_FULL_SIZE: h = draw->h = ymax - 10; break;
1117: case PETSC_DRAW_HALF_SIZE: h = draw->h = (ymax - 20)/2; break;
1118: case PETSC_DRAW_THIRD_SIZE: h = draw->h = (ymax - 30)/3; break;
1119: case PETSC_DRAW_QUARTER_SIZE: h = draw->h = (ymax - 40)/4; break;
1120: }
1122: /* allow user to set location and size of window */
1123: xywh[0] = x; xywh[1] = y; xywh[2] = w; xywh[3] = h;
1124: PetscOptionsGetIntArray(NULL,"-geometry",xywh,&osize,NULL);
1125: x = (int) xywh[0]; y = (int) xywh[1]; w = (int) xywh[2]; h = (int) xywh[3];
1128: if (draw->x == PETSC_DECIDE || draw->y == PETSC_DECIDE) {
1129: /*
1130: PETSc tries to place windows starting in the upper left corner and
1131: moving across to the right.
1133: --------------------------------------------
1134: | Region used so far +xavailable,yavailable |
1135: | + |
1136: | + |
1137: |++++++++++++++++++++++ybottom |
1138: | |
1139: | |
1140: |--------------------------------------------|
1141: */
1142: /* First: can we add it to the right? */
1143: if (xavailable+w+10 <= xmax) {
1144: x = xavailable;
1145: y = yavailable;
1146: ybottom = PetscMax(ybottom,y + h + 30);
1147: } else {
1148: /* No, so add it below on the left */
1149: xavailable = 0;
1150: x = 0;
1151: yavailable = ybottom;
1152: y = ybottom;
1153: ybottom = ybottom + h + 30;
1154: }
1155: }
1156: /* update available region */
1157: xavailable = PetscMax(xavailable,x + w + 10);
1158: if (xavailable >= xmax) {
1159: xavailable = 0;
1160: yavailable = yavailable + h + 30;
1161: ybottom = yavailable;
1162: }
1163: if (yavailable >= ymax) {
1164: y = 0;
1165: yavailable = 0;
1166: ybottom = 0;
1167: }
1169: PetscMemcpy(draw->ops,&DvOps,sizeof(DvOps));
1171: /* actually create and open the window */
1172: PetscNew(&win);
1173: PetscLogObjectMemory((PetscObject)draw,sizeof(PetscDraw_OpenGL));
1175: if (x < 0 || y < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative corner of window");
1176: if (w <= 0 || h <= 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative window width or height");
1178: win->x = x;
1179: win->y = y;
1180: win->w = w;
1181: win->h = h;
1183: glutInitWindowSize(w, h);
1184: glutInitWindowPosition(x,y);
1185: win->win = glutCreateWindow(draw->title);
1186: glutDisplayFunc(display);
1187: glutReshapeFunc(reshape);
1188: Mouse.button = -1;
1189: Mouse.x = -1;
1190: Mouse.y = -1;
1191: glutMouseFunc(mouse);
1193: glClearColor(1.0,1.0,1.0,1.0);
1195: draw->data = win;
1196: glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1197: InitializeShader();
1199: PetscDrawClear(draw);
1200: resized = PETSC_FALSE; /* opening the window triggers OpenGL call to reshape so need to cancel that resized flag */
1201: glutCheckLoop();
1202: return(0);
1203: }
1207: /*@C
1208: PetscDrawOpenGLUT - Opens an OpenGL window based on GLUT for use with the PetscDraw routines.
1210: Collective on MPI_Comm
1212: Input Parameters:
1213: + comm - the communicator that will share X-window
1214: . display - the X display on which to open,or null for the local machine
1215: . title - the title to put in the title bar,or null for no title
1216: . x,y - the screen coordinates of the upper left corner of window
1217: may use PETSC_DECIDE for these two arguments, then PETSc places the
1218: window
1219: - w, h - the screen width and height in pixels, or PETSC_DRAW_HALF_SIZE, PETSC_DRAW_FULL_SIZE,
1220: or PETSC_DRAW_THIRD_SIZE or PETSC_DRAW_QUARTER_SIZE
1222: Output Parameters:
1223: . draw - the drawing context.
1225: Options Database Keys:
1226: + -nox - Disables all x-windows output
1227: . -draw_pause <pause> - Sets time (in seconds) that the
1228: program pauses after PetscDrawPause() has been called
1229: (0 is default, -1 implies until user input).
1231: Level: beginner
1233: Note:
1234: When finished with the drawing context, it should be destroyed
1235: with PetscDrawDestroy().
1237: Note for Fortran Programmers:
1238: Whenever indicating null character data in a Fortran code,
1239: NULL_CHARACTER must be employed; using NULL is not
1240: correct for character data! Thus, NULL_CHARACTER can be
1241: used for the display and title input parameters.
1243: Concepts: OpenGL^drawing to
1245: .seealso: PetscDrawSynchronizedFlush(), PetscDrawDestroy(), PetscDrawOpenX(), PetscDrawCreate()
1246: @*/
1247: PetscErrorCode PetscDrawOpenGLUT(MPI_Comm comm,const char display[],const char title[],int x,int y,int w,int h,PetscDraw *draw)
1248: {
1252: PetscDrawCreate(comm,display,title,x,y,w,h,draw);
1253: PetscDrawSetType(*draw,PETSC_DRAW_GLUT);
1254: return(0);
1255: }
1257: #elif defined(PETSC_HAVE_OPENGLES)
1261: PetscErrorCode PetscDrawOpenGLESRegisterGLKView(GLKView *view)
1262: {
1263: PetscInt i;
1266: for (i=0; i<10; i++) {
1267: if (view == globalGLKView[i]) return(0); /* already registered */
1268: if (!globalGLKView[i]) {
1269: globalGLKView[i] = view;
1270: return(0);
1271: }
1272: }
1273: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Out of GLKView slots");
1274: return(0);
1275: }
1279: PETSC_EXTERN PetscErrorCode PetscDrawCreate_OpenGLES(PetscDraw draw)
1280: {
1281: PetscDraw_OpenGL *win;
1282: PetscErrorCode ierr;
1283: static PetscBool initialized = PETSC_FALSE;
1284: PetscInt i;
1287: NSLog(@"Beginning PetscDrawCreate_OpenGLES()");
1289: PetscMemcpy(draw->ops,&DvOps,sizeof(DvOps));
1290: PetscNew(&win);
1291: PetscLogObjectMemory((PetscObject)draw,sizeof(PetscDraw_OpenGL));
1293: draw->data = win;
1294: for (i=0; i<10; i++) {
1295: if (globalGLKView[i]) {
1296: win->view = globalGLKView[i];
1297: win->w = win->view.frame.size.width;
1298: win->h = win->view.frame.size.height;
1299: [win->view bindDrawable];
1300: globalGLKView[i] = 0;
1301: break;
1302: }
1303: }
1304: if (!win->view) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Requested more OpenGL ES windows then provided with PetscDrawOpenGLRegisterGLKView()");
1306: if (!initialized) {
1307: initialized = PETSC_TRUE;
1308: InitializeColors();
1309: }
1310: InitializeShader();
1312: PetscDrawClear(draw);
1313: NSLog(@"Ending PetscDrawCreate_OpenGLES()");
1314: return(0);
1315: }
1317: #endif