Actual source code: openglops.c
petsc-3.7.3 2016-08-01
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: PetscDrawUtilitySetCmap(NULL,256-PETSC_DRAW_BASIC_COLORS,rcolor+PETSC_DRAW_BASIC_COLORS,gcolor+PETSC_DRAW_BASIC_COLORS,bcolor+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: PETSC_INTERN 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: PetscDrawClear(draw);
427: PetscDrawDestroy(&draw->popup);
428: glutDestroyWindow(win->win);
429: PetscFree(draw->data);
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: int view;
526: } PetscDraw_OpenGL;
528: static GLKView *globalGLKView[10] = {0,0,0,0,0,0,0,0,0,0};
529: static int globalGLKViewUsed[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 [globalGLKView[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: [globalGLKView[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: [globalGLKView[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: globalGLKViewUsed[win->view] = 0;
632: PetscFree(draw->data);
633: return(0);
634: return(0);
635: }
638: static PetscErrorCode PetscDrawFlush_OpenGL(PetscDraw draw)
639: {
640: PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
642: GLenum err;
643: glFlush();
644: err = glGetError();
645: if (err != GL_NO_ERROR) {
646: NSLog(@"GL error detected glFlush()");
647: SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unable to flush OpenGL Error Code %d",err);
648: }
649: [globalGLKView[win->view] display];
650: NSLog(@"Completed display in PetscDrawFlush()");
651: return 0;
652: }
655: static PetscErrorCode PetscDrawStringGetSize_OpenGL(PetscDraw draw,PetscReal *x,PetscReal *y)
656: {
657: float w = .02;
658: if (x) *x = w*(draw->coor_xr - draw->coor_xl)/(draw->port_xr - draw->port_xl);
659: if (y) *y = (13./8.0)*w*(draw->coor_yr - draw->coor_yl)/(draw->port_yr - draw->port_yl);
660: return 0;
661: }
664: static PetscErrorCode PetscDrawResizeWindow_OpenGL(PetscDraw draw,int w,int h)
665: {
666: return 0;
667: }
670: static PetscErrorCode PetscDrawCheckResizedWindow_OpenGL(PetscDraw draw)
671: {
672: return 0;
673: }
676: static PetscErrorCode PetscDrawGetMouseButton_OpenGL(PetscDraw draw,PetscDrawButton *button,PetscReal *x_user,PetscReal *y_user,PetscReal *x_phys,PetscReal *y_phys)
677: {
678: return 0;
679: }
680: #endif
682: /* -----------------------------------------------------------------------*/
686: PetscErrorCode PetscDrawClear_OpenGL_Base(PetscDraw draw)
687: {
688: PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
689: PetscErrorCode ierr;
690: float xl,yl,xr,yr;
691: GLfloat vertices[12];
692: GLfloat colors[18];
693: GLuint positionBufferObject;
694: GLuint colorBufferObject;
695: GLenum err;
698: OpenGLWindow(win);
699: xl = -1.0 + 2.0*((draw)->port_xl);
700: xr = -1.0 + 2.0*((draw)->port_xr);
701: yl = -1.0 + 2.0*((draw)->port_yl);
702: yr = -1.0 + 2.0*((draw)->port_yr);
704: vertices[0] = xl;
705: vertices[1] = yl;
706: vertices[2] = xr;
707: vertices[3] = yl;
708: vertices[4] = xl;
709: vertices[5] = yr;
711: vertices[6] = xl;
712: vertices[7] = yr;
713: vertices[8] = xr;
714: vertices[9] = yr;
715: vertices[10] = xr;
716: vertices[11] = yl;
718: colors[0] = 1.0; colors[1] = 1.0; colors[2] = 1.0;
719: colors[3] = 1.0; colors[4] = 1.0; colors[5] = 1.0;
720: colors[6] = 1.0; colors[7] = 1.0; colors[8] = 1.0;
722: colors[9] = 1.0; colors[10] = 1.0; colors[11] = 1.0;
723: colors[12] = 1.0; colors[13] = 1.0; colors[14] = 1.0;
724: colors[15] = 1.0; colors[16] = 1.0; colors[17] = 1.0;
726: glGenBuffers(1, &positionBufferObject);
727: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
728: glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
729: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
730: glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
731: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
732: glEnableVertexAttribArray(0);
733: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
734: glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
735: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
737: glGenBuffers(1, &colorBufferObject);
738: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
739: glBindBuffer(GL_ARRAY_BUFFER, colorBufferObject);
740: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
741: glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
742: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
743: glEnableVertexAttribArray(1);
744: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
745: glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
746: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
748: glDrawArrays(GL_TRIANGLES, 0, 6);
749: glDisableVertexAttribArray(0);
750: glDisableVertexAttribArray(1);
751: glDeleteBuffers(1, &positionBufferObject);
752: glDeleteBuffers(1, &colorBufferObject);
753: PetscDrawFlush(draw);
754: return(0);
755: }
759: static PetscErrorCode PetscDrawPoint_OpenGL(PetscDraw draw,PetscReal xl,PetscReal yl,int cl)
760: {
761: PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
762: GLfloat vertices[2],colors[3];
763: PetscErrorCode ierr;
764: GLuint positionBufferObject;
765: GLuint colorBufferObject;
766: GLenum err;
769: vertices[0] = XTRANS(draw,xl);
770: vertices[1] = YTRANS(draw,yl);
771: colors[0] = rcolor[cl]/255.0; colors[1] = gcolor[cl]/255.0; colors[2] = bcolor[cl]/255.0;
773: OpenGLWindow(win);
774: glGenBuffers(1, &positionBufferObject);
775: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
776: glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
777: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
778: glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
779: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
780: glEnableVertexAttribArray(0);
781: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
782: glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
783: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
785: glGenBuffers(1, &colorBufferObject);
786: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
787: glBindBuffer(GL_ARRAY_BUFFER, colorBufferObject);
788: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
789: glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
790: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
791: glEnableVertexAttribArray(1);
792: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
793: glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
794: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
796: glDrawArrays(GL_POINTS, 0, 2);
797: glDisableVertexAttribArray(0);
798: glDisableVertexAttribArray(1);
799: glDeleteBuffers(1, &positionBufferObject);
800: glDeleteBuffers(1, &colorBufferObject);
801: return(0);
802: }
806: static PetscErrorCode PetscDrawLine_OpenGL(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int cl)
807: {
808: PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
809: GLfloat linevertices[4],colors[6];
810: PetscErrorCode ierr;
811: GLenum err;
812: GLuint positionBufferObject;
813: GLuint colorBufferObject;
817: linevertices[0] = XTRANS(draw,xl);
818: linevertices[2] = XTRANS(draw,xr);
819: linevertices[1] = YTRANS(draw,yl);
820: linevertices[3] = YTRANS(draw,yr);
821: if (linevertices[0] == linevertices[2] && linevertices[1] == linevertices[3]) return(0);
822: colors[0] = rcolor[cl]/255.0; colors[1] = gcolor[cl]/255.0; colors[2] = bcolor[cl]/255.0;
823: colors[3] = rcolor[cl]/255.0; colors[4] = gcolor[cl]/255.0; colors[5] = bcolor[cl]/255.0;
825: OpenGLWindow(win);
826: /* http://arcsynthesis.org/gltut/Basics/Tutorial%2001.html */
827: glGenBuffers(1, &positionBufferObject);
828: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
829: glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
830: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
831: glBufferData(GL_ARRAY_BUFFER, sizeof(linevertices), linevertices, GL_STATIC_DRAW);
832: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
833: glEnableVertexAttribArray(0);
834: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
835: glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
836: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
838: glGenBuffers(1, &colorBufferObject);
839: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
840: glBindBuffer(GL_ARRAY_BUFFER, colorBufferObject);
841: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
842: glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
843: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
844: glEnableVertexAttribArray(1);
845: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
846: glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
847: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
849: glDrawArrays(GL_LINES, 0, 2);
850: glDisableVertexAttribArray(0);
851: glDisableVertexAttribArray(1);
852: glDeleteBuffers(1, &positionBufferObject);
853: glDeleteBuffers(1, &colorBufferObject);
854: return(0);
855: }
859: 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)
860: {
861: PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
862: PetscErrorCode ierr;
863: GLfloat vertices[6],colors[9];
864: GLenum err;
865: GLuint positionBufferObject;
866: GLuint colorBufferObject;
869: vertices[0] = XTRANS(draw,X1);
870: vertices[1] = YTRANS(draw,Y_1);
871: vertices[2] = XTRANS(draw,X2);
872: vertices[3] = YTRANS(draw,Y2);
873: vertices[4] = XTRANS(draw,X3);
874: vertices[5] = YTRANS(draw,Y3);
875: colors[0] = rcolor[c1]/255.0; colors[1] = gcolor[c1]/255.0; colors[2] = bcolor[c1]/255.0;
876: colors[3] = rcolor[c2]/255.0; colors[4] = gcolor[c2]/255.0; colors[5] = bcolor[c2]/255.0;
877: colors[6] = rcolor[c3]/255.0; colors[7] = gcolor[c3]/255.0; colors[8] = bcolor[c3]/255.0;
879: OpenGLWindow(win);
880: glGenBuffers(1, &positionBufferObject);
881: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
882: glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
883: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
884: glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
885: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
886: glEnableVertexAttribArray(0);
887: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
888: glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
889: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
891: glGenBuffers(1, &colorBufferObject);
892: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
893: glBindBuffer(GL_ARRAY_BUFFER, colorBufferObject);
894: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
895: glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
896: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
897: glEnableVertexAttribArray(1);
898: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
899: glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
900: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
902: glDrawArrays(GL_TRIANGLES, 0, 3);
903: glDisableVertexAttribArray(0);
904: glDisableVertexAttribArray(1);
905: glDeleteBuffers(1, &positionBufferObject);
906: glDeleteBuffers(1, &colorBufferObject);
907: return(0);
908: }
912: static PetscErrorCode PetscDrawRectangle_OpenGL(PetscDraw draw,PetscReal Xl,PetscReal Yl,PetscReal Xr,PetscReal Yr,int c1,int c2,int c3,int c4)
913: {
914: PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
915: PetscErrorCode ierr;
916: GLfloat vertices[12],colors[18];
917: float x1,y_1,x2,y2;
918: GLuint positionBufferObject;
919: GLuint colorBufferObject;
920: GLenum err;
923: x1 = XTRANS(draw,Xl);
924: y_1 = YTRANS(draw,Yl);
925: x2 = XTRANS(draw,Xr);
926: y2 = YTRANS(draw,Yr);
928: OpenGLWindow(win);
930: vertices[0] = x1; colors[0] = rcolor[c1]/255.0; colors[1] = gcolor[c1]/255.0; colors[2] = bcolor[c1]/255.0;
931: vertices[1] = y_1;
932: vertices[2] = x2;colors[3] = rcolor[c2]/255.0; colors[4] = gcolor[c2]/255.0; colors[5] = bcolor[c2]/255.0;
933: vertices[3] = y_1;
934: vertices[4] = x1;colors[6] = rcolor[c4]/255.0; colors[7] = gcolor[c4]/255.0; colors[8] = bcolor[c4]/255.0;
935: vertices[5] = y2;
937: vertices[6] = x1;colors[9] = rcolor[c4]/255.0; colors[10] = gcolor[c4]/255.0; colors[11] = bcolor[c4]/255.0;
938: vertices[7] = y2;
939: vertices[8] = x2;colors[12] = rcolor[c3]/255.0; colors[13] = gcolor[c3]/255.0; colors[14] = bcolor[c3]/255.0;
940: vertices[9] = y2;
941: vertices[10] = x2;colors[15] = rcolor[c2]/255.0; colors[16] = gcolor[c2]/255.0; colors[17] = bcolor[c2]/255.0;
942: vertices[11] = y_1;
944: glGenBuffers(1, &positionBufferObject);
945: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
946: glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
947: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
948: glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
949: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
950: glEnableVertexAttribArray(0);
951: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
952: glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
953: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
955: glGenBuffers(1, &colorBufferObject);
956: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
957: glBindBuffer(GL_ARRAY_BUFFER, colorBufferObject);
958: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
959: glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
960: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
961: glEnableVertexAttribArray(1);
962: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
963: glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
964: err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
966: glDrawArrays(GL_TRIANGLES, 0, 6);
967: glDisableVertexAttribArray(0);
968: glDisableVertexAttribArray(1);
969: glDeleteBuffers(1, &positionBufferObject);
970: glDeleteBuffers(1, &colorBufferObject);
971: return(0);
972: }
977: static PetscErrorCode PetscDrawPause_OpenGL(PetscDraw draw)
978: {
982: if (draw->pause > 0) PetscSleep(draw->pause);
983: else if (draw->pause == -1) {
984: PetscDrawButton button = PETSC_BUTTON_NONE;
985: PetscDrawGetMouseButton(draw,&button,0,0,0,0);
986: if (button == PETSC_BUTTON_CENTER) draw->pause = 0;
987: }
988: return(0);
989: }
992: static struct _PetscDrawOps DvOps = { 0,
993: PetscDrawFlush_OpenGL,
994: PetscDrawLine_OpenGL,
995: 0,
996: 0,
997: PetscDrawPoint_OpenGL,
998: 0,
999: PetscDrawString_OpenGL,
1000: PetscDrawStringVertical_OpenGL,
1001: 0, /* PetscDrawStringSetSize_OpenGL,*/
1002: PetscDrawStringGetSize_OpenGL,
1003: 0, /* PetscDrawSetViewport_OpenGL,*/
1004: PetscDrawClear_OpenGL,
1005: PetscDrawRectangle_OpenGL,
1006: PetscDrawTriangle_OpenGL,
1007: 0, /* PetscDrawEllipse_OpenGL,*/
1008: PetscDrawGetMouseButton_OpenGL,
1009: PetscDrawPause_OpenGL,
1010: 0,
1011: 0,
1012: PetscDrawGetPopup_OpenGL,
1013: PetscDrawSetTitle_OpenGL,
1014: PetscDrawCheckResizedWindow_OpenGL,
1015: PetscDrawResizeWindow_OpenGL,
1016: PetscDrawDestroy_OpenGL,
1017: 0,
1018: 0, /* PetscDrawGetSingleton_OpenGL,*/
1019: 0, /* PetscDrawRestoreSingleton_OpenGL,*/
1020: 0,
1021: 0,
1022: 0,
1023: PetscDrawLine_OpenGL};
1025: #if defined(PETSC_HAVE_GLUT)
1026: /* callbacks required by GLUT */
1027: static void display(void) {;}
1028: static void reshape(int width, int height)
1029: {
1030: glViewport(0, 0, width, height);
1031: resized = PETSC_TRUE;
1032: }
1033: static void mouse(int button, int state,int x, int y)
1034: {
1035: if (state == GLUT_UP) {
1036: Mouse.button = button;
1037: Mouse.x = x;
1038: Mouse.y = y;
1039: }
1040: }
1044: PETSC_EXTERN PetscErrorCode PetscDrawCreate_GLUT(PetscDraw draw)
1045: {
1046: PetscDraw_OpenGL *win;
1047: PetscErrorCode ierr;
1048: PetscInt xywh[4],osize = 4;
1049: int x = draw->x,y = draw->y,w = draw->w,h = draw->h;
1050: static int xavailable = 0,yavailable = 0,xmax = 0,ymax = 0,ybottom = 0;
1051: static PetscBool initialized = PETSC_FALSE;
1052: int argc;
1053: char **argv;
1056: if (!initialized) {
1057: PetscGetArgs(&argc,&argv);
1058: glutInit(&argc, argv);
1059: glutInitDisplayMode(GLUT_RGBA /* | GLUT_DOUBLE */| GLUT_DEPTH);
1060: InitializeColors();
1061: }
1063: /*
1064: Initialize the display size
1065: */
1066: if (!xmax) {
1067: xmax = glutGet(GLUT_SCREEN_WIDTH);
1068: ymax = glutGet(GLUT_SCREEN_HEIGHT);
1069: }
1071: if (w == PETSC_DECIDE) w = draw->w = 300;
1072: if (h == PETSC_DECIDE) h = draw->h = 300;
1073: switch (w) {
1074: case PETSC_DRAW_FULL_SIZE: w = draw->w = xmax - 10; break;
1075: case PETSC_DRAW_HALF_SIZE: w = draw->w = (xmax - 20)/2; break;
1076: case PETSC_DRAW_THIRD_SIZE: w = draw->w = (xmax - 30)/3; break;
1077: case PETSC_DRAW_QUARTER_SIZE: w = draw->w = (xmax - 40)/4; break;
1078: }
1079: switch (h) {
1080: case PETSC_DRAW_FULL_SIZE: h = draw->h = ymax - 10; break;
1081: case PETSC_DRAW_HALF_SIZE: h = draw->h = (ymax - 20)/2; break;
1082: case PETSC_DRAW_THIRD_SIZE: h = draw->h = (ymax - 30)/3; break;
1083: case PETSC_DRAW_QUARTER_SIZE: h = draw->h = (ymax - 40)/4; break;
1084: }
1086: /* allow user to set location and size of window */
1087: xywh[0] = x; xywh[1] = y; xywh[2] = w; xywh[3] = h;
1088: PetscOptionsGetIntArray(NULL,"-geometry",xywh,&osize,NULL);
1089: x = (int) xywh[0]; y = (int) xywh[1]; w = (int) xywh[2]; h = (int) xywh[3];
1092: if (draw->x == PETSC_DECIDE || draw->y == PETSC_DECIDE) {
1093: /*
1094: PETSc tries to place windows starting in the upper left corner and
1095: moving across to the right.
1097: --------------------------------------------
1098: | Region used so far +xavailable,yavailable |
1099: | + |
1100: | + |
1101: |++++++++++++++++++++++ybottom |
1102: | |
1103: | |
1104: |--------------------------------------------|
1105: */
1106: /* First: can we add it to the right? */
1107: if (xavailable+w+10 <= xmax) {
1108: x = xavailable;
1109: y = yavailable;
1110: ybottom = PetscMax(ybottom,y + h + 30);
1111: } else {
1112: /* No, so add it below on the left */
1113: xavailable = 0;
1114: x = 0;
1115: yavailable = ybottom;
1116: y = ybottom;
1117: ybottom = ybottom + h + 30;
1118: }
1119: }
1120: /* update available region */
1121: xavailable = PetscMax(xavailable,x + w + 10);
1122: if (xavailable >= xmax) {
1123: xavailable = 0;
1124: yavailable = yavailable + h + 30;
1125: ybottom = yavailable;
1126: }
1127: if (yavailable >= ymax) {
1128: y = 0;
1129: yavailable = 0;
1130: ybottom = 0;
1131: }
1133: PetscMemcpy(draw->ops,&DvOps,sizeof(DvOps));
1135: /* actually create and open the window */
1136: PetscNew(&win);
1137: PetscLogObjectMemory((PetscObject)draw,sizeof(PetscDraw_OpenGL));
1139: if (x < 0 || y < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative corner of window");
1140: if (w <= 0 || h <= 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative window width or height");
1142: win->x = x;
1143: win->y = y;
1144: win->w = w;
1145: win->h = h;
1147: glutInitWindowSize(w, h);
1148: glutInitWindowPosition(x,y);
1149: win->win = glutCreateWindow(draw->title);
1150: glutDisplayFunc(display);
1151: glutReshapeFunc(reshape);
1152: Mouse.button = -1;
1153: Mouse.x = -1;
1154: Mouse.y = -1;
1155: glutMouseFunc(mouse);
1157: glClearColor(1.0,1.0,1.0,1.0);
1159: draw->data = win;
1160: glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1161: InitializeShader();
1163: PetscDrawClear(draw);
1164: resized = PETSC_FALSE; /* opening the window triggers OpenGL call to reshape so need to cancel that resized flag */
1165: glutCheckLoop();
1166: return(0);
1167: }
1171: /*@C
1172: PetscDrawOpenGLUT - Opens an OpenGL window based on GLUT for use with the PetscDraw routines.
1174: Collective on MPI_Comm
1176: Input Parameters:
1177: + comm - the communicator that will share X-window
1178: . display - the X display on which to open,or null for the local machine
1179: . title - the title to put in the title bar,or null for no title
1180: . x,y - the screen coordinates of the upper left corner of window
1181: may use PETSC_DECIDE for these two arguments, then PETSc places the
1182: window
1183: - w, h - the screen width and height in pixels, or PETSC_DRAW_HALF_SIZE, PETSC_DRAW_FULL_SIZE,
1184: or PETSC_DRAW_THIRD_SIZE or PETSC_DRAW_QUARTER_SIZE
1186: Output Parameters:
1187: . draw - the drawing context.
1189: Options Database Keys:
1190: + -nox - Disables all x-windows output
1191: . -draw_pause <pause> - Sets time (in seconds) that the
1192: program pauses after PetscDrawPause() has been called
1193: (0 is default, -1 implies until user input).
1194: . -draw_cmap <name> - Sets the colormap to use.
1195: . -draw_cmap_reverse - Reverses the colormap.
1196: - -draw_cmap_brighten - Brighten (0 < beta < 1) or darken (-1 < beta < 0) the colormap.
1198: Level: beginner
1200: Note:
1201: When finished with the drawing context, it should be destroyed
1202: with PetscDrawDestroy().
1204: Note for Fortran Programmers:
1205: Whenever indicating null character data in a Fortran code,
1206: NULL_CHARACTER must be employed; using NULL is not
1207: correct for character data! Thus, NULL_CHARACTER can be
1208: used for the display and title input parameters.
1210: Concepts: OpenGL^drawing to
1212: .seealso: PetscDrawFlush(), PetscDrawDestroy(), PetscDrawOpenX(), PetscDrawCreate()
1213: @*/
1214: PetscErrorCode PetscDrawOpenGLUT(MPI_Comm comm,const char display[],const char title[],int x,int y,int w,int h,PetscDraw *draw)
1215: {
1219: PetscDrawCreate(comm,display,title,x,y,w,h,draw);
1220: PetscDrawSetType(*draw,PETSC_DRAW_GLUT);
1221: return(0);
1222: }
1224: #elif defined(PETSC_HAVE_OPENGLES)
1228: PetscErrorCode PetscDrawOpenGLESRegisterGLKView(GLKView *view)
1229: {
1230: PetscInt i;
1233: for (i=0; i<10; i++) {
1234: if (view == globalGLKView[i]) return(0); /* already registered */
1235: if (!globalGLKView[i]) {
1236: globalGLKView[i] = view;
1237: return(0);
1238: }
1239: }
1240: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Out of GLKView slots");
1241: return(0);
1242: }
1246: PETSC_EXTERN PetscErrorCode PetscDrawCreate_OpenGLES(PetscDraw draw)
1247: {
1248: PetscDraw_OpenGL *win;
1249: PetscErrorCode ierr;
1250: static PetscBool initialized = PETSC_FALSE;
1251: PetscInt i;
1254: NSLog(@"Beginning PetscDrawCreate_OpenGLES()");
1256: PetscMemcpy(draw->ops,&DvOps,sizeof(DvOps));
1257: PetscNew(&win);
1258: PetscLogObjectMemory((PetscObject)draw,sizeof(PetscDraw_OpenGL));
1260: draw->data = win;
1261: win->view = -1;
1262: for (i=0; i<10; i++) {
1263: if (!globalGLKViewUsed[i]) {
1264: win->view = i;
1265: win->w = globalGLKView[win->view].frame.size.width;
1266: win->h = globalGLKView[win->view].frame.size.height;
1267: [globalGLKView[win->view] bindDrawable];
1268: globalGLKViewUsed[i] = 1;
1269: break;
1270: }
1271: }
1272: if (win->view == -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Requested more OpenGL ES windows then provided with PetscDrawOpenGLRegisterGLKView()");
1274: if (!initialized) {
1275: initialized = PETSC_TRUE;
1276: InitializeColors();
1277: }
1278: InitializeShader();
1280: PetscDrawClear(draw);
1281: NSLog(@"Ending PetscDrawCreate_OpenGLES()");
1282: return(0);
1283: }
1285: #endif