Actual source code: openglops.c

petsc-3.6.1 2015-08-06
Report Typos and Errors
  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(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: /* -----------------------------------------------------------------------*/
685: static PetscErrorCode PetscDrawSynchronizedFlush_OpenGL(PetscDraw draw)
686: {

690:   /* currently on sequential support */
691:   PetscDrawFlush(draw);
692:   return(0);
693: }

697: PetscErrorCode PetscDrawClear_OpenGL_Base(PetscDraw draw)
698: {
699:   PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
700:   PetscErrorCode   ierr;
701:   float            xl,yl,xr,yr;
702:   GLfloat          vertices[12];
703:   GLfloat          colors[18];
704:   GLuint           positionBufferObject;
705:   GLuint           colorBufferObject;
706:   GLenum           err;

709:   OpenGLWindow(win);
710:   xl   = -1.0 + 2.0*((draw)->port_xl);
711:   xr   = -1.0 + 2.0*((draw)->port_xr);
712:   yl   = -1.0 + 2.0*((draw)->port_yl);
713:   yr   = -1.0 + 2.0*((draw)->port_yr);

715:   vertices[0] = xl;
716:   vertices[1] = yl;
717:   vertices[2] = xr;
718:   vertices[3] = yl;
719:   vertices[4] = xl;
720:   vertices[5] = yr;

722:   vertices[6]  = xl;
723:   vertices[7]  = yr;
724:   vertices[8]  = xr;
725:   vertices[9]  = yr;
726:   vertices[10] = xr;
727:   vertices[11] = yl;

729:   colors[0] = 1.0;  colors[1] = 1.0; colors[2] = 1.0;
730:   colors[3] = 1.0;  colors[4] = 1.0; colors[5] = 1.0;
731:   colors[6] = 1.0;  colors[7] = 1.0; colors[8] = 1.0;

733:   colors[9]  = 1.0;  colors[10] = 1.0; colors[11] = 1.0;
734:   colors[12] = 1.0;  colors[13] = 1.0; colors[14] = 1.0;
735:   colors[15] = 1.0;  colors[16] = 1.0; colors[17] = 1.0;

737:   glGenBuffers(1, &positionBufferObject);
738:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
739:   glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
740:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
741:   glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
742:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
743:   glEnableVertexAttribArray(0);
744:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
745:   glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
746:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);

748:   glGenBuffers(1, &colorBufferObject);
749:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
750:   glBindBuffer(GL_ARRAY_BUFFER, colorBufferObject);
751:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
752:   glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
753:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
754:   glEnableVertexAttribArray(1);
755:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
756:   glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
757:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);

759:   glDrawArrays(GL_TRIANGLES, 0, 6);
760:   glDisableVertexAttribArray(0);
761:   glDisableVertexAttribArray(1);
762:   glDeleteBuffers(1, &positionBufferObject);
763:   glDeleteBuffers(1, &colorBufferObject);
764:   PetscDrawFlush(draw);
765:   return(0);
766: }

770: static PetscErrorCode PetscDrawSynchronizedClear_OpenGL(PetscDraw draw)
771: {

775:   /* currently only sequential support */
776:   PetscDrawClear(draw);
777:   return(0);
778: }

782: static PetscErrorCode PetscDrawPoint_OpenGL(PetscDraw draw,PetscReal xl,PetscReal yl,int cl)
783: {
784:   PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
785:   GLfloat          vertices[2],colors[3];
786:   PetscErrorCode   ierr;
787:   GLuint           positionBufferObject;
788:   GLuint           colorBufferObject;
789:   GLenum           err;

792:   vertices[0] = XTRANS(draw,xl);
793:   vertices[1] = YTRANS(draw,yl);
794:   colors[0]   = rcolor[cl]/255.0;  colors[1] = gcolor[cl]/255.0; colors[2] = bcolor[cl]/255.0;

796:   OpenGLWindow(win);
797:   glGenBuffers(1, &positionBufferObject);
798:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
799:   glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
800:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
801:   glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
802:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
803:   glEnableVertexAttribArray(0);
804:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
805:   glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
806:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);

808:   glGenBuffers(1, &colorBufferObject);
809:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
810:   glBindBuffer(GL_ARRAY_BUFFER, colorBufferObject);
811:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
812:   glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
813:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
814:   glEnableVertexAttribArray(1);
815:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
816:   glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
817:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);

819:   glDrawArrays(GL_POINTS, 0, 2);
820:   glDisableVertexAttribArray(0);
821:   glDisableVertexAttribArray(1);
822:   glDeleteBuffers(1, &positionBufferObject);
823:   glDeleteBuffers(1, &colorBufferObject);
824:   return(0);
825: }

829: static PetscErrorCode PetscDrawLine_OpenGL(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int cl)
830: {
831:   PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
832:   GLfloat          linevertices[4],colors[6];
833:   PetscErrorCode   ierr;
834:   GLenum           err;
835:   GLuint           positionBufferObject;
836:   GLuint           colorBufferObject;


840:   linevertices[0] = XTRANS(draw,xl);
841:   linevertices[2] = XTRANS(draw,xr);
842:   linevertices[1] = YTRANS(draw,yl);
843:   linevertices[3] = YTRANS(draw,yr);
844:   if (linevertices[0] == linevertices[2] && linevertices[1] == linevertices[3]) return(0);
845:   colors[0] = rcolor[cl]/255.0;  colors[1] = gcolor[cl]/255.0; colors[2] = bcolor[cl]/255.0;
846:   colors[3] = rcolor[cl]/255.0;  colors[4] = gcolor[cl]/255.0; colors[5] = bcolor[cl]/255.0;

848:   OpenGLWindow(win);
849:   /* http://arcsynthesis.org/gltut/Basics/Tutorial%2001.html */
850:   glGenBuffers(1, &positionBufferObject);
851:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
852:   glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
853:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
854:   glBufferData(GL_ARRAY_BUFFER, sizeof(linevertices), linevertices, GL_STATIC_DRAW);
855:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
856:   glEnableVertexAttribArray(0);
857:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
858:   glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
859:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);

861:   glGenBuffers(1, &colorBufferObject);
862:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
863:   glBindBuffer(GL_ARRAY_BUFFER, colorBufferObject);
864:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
865:   glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
866:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
867:   glEnableVertexAttribArray(1);
868:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
869:   glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
870:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);

872:   glDrawArrays(GL_LINES, 0, 2);
873:   glDisableVertexAttribArray(0);
874:   glDisableVertexAttribArray(1);
875:   glDeleteBuffers(1, &positionBufferObject);
876:   glDeleteBuffers(1, &colorBufferObject);
877:   return(0);
878: }

882: 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)
883: {
884:   PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
885:   PetscErrorCode   ierr;
886:   GLfloat          vertices[6],colors[9];
887:   GLenum           err;
888:   GLuint           positionBufferObject;
889:   GLuint           colorBufferObject;

892:   vertices[0] = XTRANS(draw,X1);
893:   vertices[1] = YTRANS(draw,Y_1);
894:   vertices[2] = XTRANS(draw,X2);
895:   vertices[3] = YTRANS(draw,Y2);
896:   vertices[4] = XTRANS(draw,X3);
897:   vertices[5] = YTRANS(draw,Y3);
898:   colors[0]   = rcolor[c1]/255.0;  colors[1] = gcolor[c1]/255.0; colors[2] = bcolor[c1]/255.0;
899:   colors[3]   = rcolor[c2]/255.0;  colors[4] = gcolor[c2]/255.0; colors[5] = bcolor[c2]/255.0;
900:   colors[6]   = rcolor[c3]/255.0;  colors[7] = gcolor[c3]/255.0; colors[8] = bcolor[c3]/255.0;

902:   OpenGLWindow(win);
903:   glGenBuffers(1, &positionBufferObject);
904:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
905:   glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
906:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
907:   glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
908:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
909:   glEnableVertexAttribArray(0);
910:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
911:   glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
912:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);

914:   glGenBuffers(1, &colorBufferObject);
915:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
916:   glBindBuffer(GL_ARRAY_BUFFER, colorBufferObject);
917:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
918:   glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
919:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
920:   glEnableVertexAttribArray(1);
921:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
922:   glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
923:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);

925:   glDrawArrays(GL_TRIANGLES, 0, 3);
926:   glDisableVertexAttribArray(0);
927:   glDisableVertexAttribArray(1);
928:   glDeleteBuffers(1, &positionBufferObject);
929:   glDeleteBuffers(1, &colorBufferObject);
930:   return(0);
931: }

935: static PetscErrorCode PetscDrawRectangle_OpenGL(PetscDraw draw,PetscReal Xl,PetscReal Yl,PetscReal Xr,PetscReal Yr,int c1,int c2,int c3,int c4)
936: {
937:   PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
938:   PetscErrorCode   ierr;
939:   GLfloat          vertices[12],colors[18];
940:   float            x1,y_1,x2,y2;
941:   GLuint           positionBufferObject;
942:   GLuint           colorBufferObject;
943:   GLenum           err;

946:   x1  = XTRANS(draw,Xl);
947:   y_1 = YTRANS(draw,Yl);
948:   x2  = XTRANS(draw,Xr);
949:   y2  = YTRANS(draw,Yr);

951:   OpenGLWindow(win);

953:   vertices[0] = x1; colors[0] = rcolor[c1]/255.0;  colors[1] = gcolor[c1]/255.0; colors[2] = bcolor[c1]/255.0;
954:   vertices[1] = y_1;
955:   vertices[2] = x2;colors[3] = rcolor[c2]/255.0;  colors[4] = gcolor[c2]/255.0; colors[5] = bcolor[c2]/255.0;
956:   vertices[3] = y_1;
957:   vertices[4] = x1;colors[6] = rcolor[c4]/255.0;  colors[7] = gcolor[c4]/255.0; colors[8] = bcolor[c4]/255.0;
958:   vertices[5] = y2;

960:   vertices[6]  = x1;colors[9] = rcolor[c4]/255.0;  colors[10] = gcolor[c4]/255.0; colors[11] = bcolor[c4]/255.0;
961:   vertices[7]  = y2;
962:   vertices[8]  = x2;colors[12] = rcolor[c3]/255.0;  colors[13] = gcolor[c3]/255.0; colors[14] = bcolor[c3]/255.0;
963:   vertices[9]  = y2;
964:   vertices[10] = x2;colors[15] = rcolor[c2]/255.0;  colors[16] = gcolor[c2]/255.0; colors[17] = bcolor[c2]/255.0;
965:   vertices[11] = y_1;

967:   glGenBuffers(1, &positionBufferObject);
968:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
969:   glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
970:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
971:   glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
972:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
973:   glEnableVertexAttribArray(0);
974:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
975:   glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
976:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);

978:   glGenBuffers(1, &colorBufferObject);
979:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
980:   glBindBuffer(GL_ARRAY_BUFFER, colorBufferObject);
981:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
982:   glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
983:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
984:   glEnableVertexAttribArray(1);
985:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
986:   glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
987:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);

989:   glDrawArrays(GL_TRIANGLES, 0, 6);
990:   glDisableVertexAttribArray(0);
991:   glDisableVertexAttribArray(1);
992:   glDeleteBuffers(1, &positionBufferObject);
993:   glDeleteBuffers(1, &colorBufferObject);
994:   return(0);
995: }


1000: static PetscErrorCode PetscDrawPause_OpenGL(PetscDraw draw)
1001: {

1005:   if (draw->pause > 0) PetscSleep(draw->pause);
1006:   else if (draw->pause == -1) {
1007:     PetscDrawButton button;
1008:     PetscMPIInt     rank;
1009:     MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);
1010:     if (!rank) {
1011:       PetscDrawGetMouseButton(draw,&button,0,0,0,0);
1012:       if (button == PETSC_BUTTON_CENTER) draw->pause = 0;
1013:     }
1014:     MPI_Bcast(&draw->pause,1,MPI_INT,0,PetscObjectComm((PetscObject)draw));
1015:   }
1016:   return(0);
1017: }


1020: static struct _PetscDrawOps DvOps = { 0,
1021:                                       PetscDrawFlush_OpenGL,
1022:                                       PetscDrawLine_OpenGL,
1023:                                       0,
1024:                                       0,
1025:                                       PetscDrawPoint_OpenGL,
1026:                                       0,
1027:                                       PetscDrawString_OpenGL,
1028:                                       PetscDrawStringVertical_OpenGL,
1029:                                       0, /* PetscDrawStringSetSize_OpenGL,*/
1030:                                       PetscDrawStringGetSize_OpenGL,
1031:                                       0, /* PetscDrawSetViewport_OpenGL,*/
1032:                                       PetscDrawClear_OpenGL,
1033:                                       PetscDrawSynchronizedFlush_OpenGL,
1034:                                       PetscDrawRectangle_OpenGL,
1035:                                       PetscDrawTriangle_OpenGL,
1036:                                       0, /* PetscDrawEllipse_OpenGL,*/
1037:                                       PetscDrawGetMouseButton_OpenGL,
1038:                                       PetscDrawPause_OpenGL,
1039:                                       PetscDrawSynchronizedClear_OpenGL,
1040:                                       0,
1041:                                       0,
1042:                                       PetscDrawGetPopup_OpenGL,
1043:                                       PetscDrawSetTitle_OpenGL,
1044:                                       PetscDrawCheckResizedWindow_OpenGL,
1045:                                       PetscDrawResizeWindow_OpenGL,
1046:                                       PetscDrawDestroy_OpenGL,
1047:                                       0,
1048:                                       0, /* PetscDrawGetSingleton_OpenGL,*/
1049:                                       0, /* PetscDrawRestoreSingleton_OpenGL,*/
1050:                                       0,
1051:                                       0,
1052:                                       0,
1053:                                       PetscDrawLine_OpenGL};

1055: #if defined(PETSC_HAVE_GLUT)
1056: /* callbacks required by GLUT */
1057: static void display(void) {;}
1058: static void reshape(int width, int height)
1059: {
1060:   glViewport(0, 0, width, height);
1061:   resized = PETSC_TRUE;
1062: }
1063: static void mouse(int button, int state,int x, int y)
1064: {
1065:   if (state == GLUT_UP) {
1066:     Mouse.button = button;
1067:     Mouse.x      = x;
1068:     Mouse.y      = y;
1069:   }
1070: }

1074: PETSC_EXTERN PetscErrorCode PetscDrawCreate_GLUT(PetscDraw draw)
1075: {
1076:   PetscDraw_OpenGL *win;
1077:   PetscErrorCode   ierr;
1078:   PetscInt         xywh[4],osize = 4;
1079:   int              x = draw->x,y = draw->y,w = draw->w,h = draw->h;
1080:   static int       xavailable = 0,yavailable = 0,xmax = 0,ymax = 0,ybottom = 0;
1081:   static PetscBool initialized = PETSC_FALSE;
1082:   int              argc;
1083:   char             **argv;

1086:   if (!initialized) {
1087:     PetscGetArgs(&argc,&argv);
1088:     glutInit(&argc, argv);
1089:     glutInitDisplayMode(GLUT_RGBA /* | GLUT_DOUBLE */| GLUT_DEPTH);
1090:     InitializeColors();
1091:   }

1093:   /*
1094:       Initialize the display size
1095:   */
1096:   if (!xmax) {
1097:     xmax = glutGet(GLUT_SCREEN_WIDTH);
1098:     ymax = glutGet(GLUT_SCREEN_HEIGHT);
1099:   }

1101:   if (w == PETSC_DECIDE) w = draw->w = 300;
1102:   if (h == PETSC_DECIDE) h = draw->h = 300;
1103:   switch (w) {
1104:   case PETSC_DRAW_FULL_SIZE: w = draw->w = xmax - 10; break;
1105:   case PETSC_DRAW_HALF_SIZE: w = draw->w = (xmax - 20)/2; break;
1106:   case PETSC_DRAW_THIRD_SIZE: w = draw->w = (xmax - 30)/3; break;
1107:   case PETSC_DRAW_QUARTER_SIZE: w = draw->w = (xmax - 40)/4; break;
1108:   }
1109:   switch (h) {
1110:   case PETSC_DRAW_FULL_SIZE: h = draw->h = ymax - 10; break;
1111:   case PETSC_DRAW_HALF_SIZE: h = draw->h = (ymax - 20)/2; break;
1112:   case PETSC_DRAW_THIRD_SIZE: h = draw->h = (ymax - 30)/3; break;
1113:   case PETSC_DRAW_QUARTER_SIZE: h = draw->h = (ymax - 40)/4; break;
1114:   }

1116:   /* allow user to set location and size of window */
1117:   xywh[0] = x; xywh[1] = y; xywh[2] = w; xywh[3] = h;
1118:   PetscOptionsGetIntArray(NULL,"-geometry",xywh,&osize,NULL);
1119:   x       = (int) xywh[0]; y = (int) xywh[1]; w = (int) xywh[2]; h = (int) xywh[3];


1122:   if (draw->x == PETSC_DECIDE || draw->y == PETSC_DECIDE) {
1123:     /*
1124:        PETSc tries to place windows starting in the upper left corner and
1125:        moving across to the right.

1127:               --------------------------------------------
1128:               |  Region used so far +xavailable,yavailable |
1129:               |                     +                      |
1130:               |                     +                      |
1131:               |++++++++++++++++++++++ybottom               |
1132:               |                                            |
1133:               |                                            |
1134:               |--------------------------------------------|
1135:     */
1136:     /*  First: can we add it to the right? */
1137:     if (xavailable+w+10 <= xmax) {
1138:       x       = xavailable;
1139:       y       = yavailable;
1140:       ybottom = PetscMax(ybottom,y + h + 30);
1141:     } else {
1142:       /* No, so add it below on the left */
1143:       xavailable = 0;
1144:       x          = 0;
1145:       yavailable = ybottom;
1146:       y          = ybottom;
1147:       ybottom    = ybottom + h + 30;
1148:     }
1149:   }
1150:   /* update available region */
1151:   xavailable = PetscMax(xavailable,x + w + 10);
1152:   if (xavailable >= xmax) {
1153:     xavailable = 0;
1154:     yavailable = yavailable + h + 30;
1155:     ybottom    = yavailable;
1156:   }
1157:   if (yavailable >= ymax) {
1158:     y          = 0;
1159:     yavailable = 0;
1160:     ybottom    = 0;
1161:   }

1163:   PetscMemcpy(draw->ops,&DvOps,sizeof(DvOps));

1165:   /* actually create and open the window */
1166:   PetscNew(&win);
1167:   PetscLogObjectMemory((PetscObject)draw,sizeof(PetscDraw_OpenGL));

1169:   if (x < 0 || y < 0)   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative corner of window");
1170:   if (w <= 0 || h <= 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative window width or height");

1172:   win->x = x;
1173:   win->y = y;
1174:   win->w = w;
1175:   win->h = h;

1177:   glutInitWindowSize(w, h);
1178:   glutInitWindowPosition(x,y);
1179:   win->win = glutCreateWindow(draw->title);
1180:   glutDisplayFunc(display);
1181:   glutReshapeFunc(reshape);
1182:   Mouse.button = -1;
1183:   Mouse.x      = -1;
1184:   Mouse.y      = -1;
1185:   glutMouseFunc(mouse);

1187:   glClearColor(1.0,1.0,1.0,1.0);

1189:   draw->data = win;
1190:   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1191:   InitializeShader();

1193:   PetscDrawClear(draw);
1194:   resized = PETSC_FALSE; /* opening the window triggers OpenGL call to reshape so need to cancel that resized flag */
1195:   glutCheckLoop();
1196:   return(0);
1197: }

1201: /*@C
1202:    PetscDrawOpenGLUT - Opens an OpenGL window based on GLUT for use with the PetscDraw routines.

1204:    Collective on MPI_Comm

1206:    Input Parameters:
1207: +  comm - the communicator that will share X-window
1208: .  display - the X display on which to open,or null for the local machine
1209: .  title - the title to put in the title bar,or null for no title
1210: .  x,y - the screen coordinates of the upper left corner of window
1211:           may use PETSC_DECIDE for these two arguments, then PETSc places the
1212:           window
1213: -  w, h - the screen width and height in pixels,  or PETSC_DRAW_HALF_SIZE, PETSC_DRAW_FULL_SIZE,
1214:           or PETSC_DRAW_THIRD_SIZE or PETSC_DRAW_QUARTER_SIZE

1216:    Output Parameters:
1217: .  draw - the drawing context.

1219:    Options Database Keys:
1220: +  -nox - Disables all x-windows output
1221: .  -draw_pause <pause> - Sets time (in seconds) that the
1222:        program pauses after PetscDrawPause() has been called
1223:        (0 is default, -1 implies until user input).

1225:    Level: beginner

1227:    Note:
1228:    When finished with the drawing context, it should be destroyed
1229:    with PetscDrawDestroy().

1231:    Note for Fortran Programmers:
1232:    Whenever indicating null character data in a Fortran code,
1233:    NULL_CHARACTER must be employed; using NULL is not
1234:    correct for character data!  Thus, NULL_CHARACTER can be
1235:    used for the display and title input parameters.

1237:    Concepts: OpenGL^drawing to

1239: .seealso: PetscDrawSynchronizedFlush(), PetscDrawDestroy(), PetscDrawOpenX(), PetscDrawCreate()
1240: @*/
1241: PetscErrorCode  PetscDrawOpenGLUT(MPI_Comm comm,const char display[],const char title[],int x,int y,int w,int h,PetscDraw *draw)
1242: {

1246:   PetscDrawCreate(comm,display,title,x,y,w,h,draw);
1247:   PetscDrawSetType(*draw,PETSC_DRAW_GLUT);
1248:   return(0);
1249: }

1251: #elif defined(PETSC_HAVE_OPENGLES)

1255: PetscErrorCode  PetscDrawOpenGLESRegisterGLKView(GLKView *view)
1256: {
1257:   PetscInt i;

1260:   for (i=0; i<10; i++) {
1261:     if (view == globalGLKView[i]) return(0);  /* already registered */
1262:     if (!globalGLKView[i]) {
1263:       globalGLKView[i] = view;
1264:       return(0);
1265:     }
1266:   }
1267:   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Out of GLKView slots");
1268:   return(0);
1269: }

1273: PETSC_EXTERN PetscErrorCode PetscDrawCreate_OpenGLES(PetscDraw draw)
1274: {
1275:   PetscDraw_OpenGL *win;
1276:   PetscErrorCode   ierr;
1277:   static PetscBool initialized = PETSC_FALSE;
1278:   PetscInt         i;

1281:   NSLog(@"Beginning PetscDrawCreate_OpenGLES()");

1283:   PetscMemcpy(draw->ops,&DvOps,sizeof(DvOps));
1284:   PetscNew(&win);
1285:   PetscLogObjectMemory((PetscObject)draw,sizeof(PetscDraw_OpenGL));

1287:   draw->data = win;
1288:   win->view  = -1;
1289:   for (i=0; i<10; i++) {
1290:     if (!globalGLKViewUsed[i]) {
1291:       win->view = i;
1292:       win->w    = globalGLKView[win->view].frame.size.width;
1293:       win->h    = globalGLKView[win->view].frame.size.height;
1294:       [globalGLKView[win->view] bindDrawable];
1295:       globalGLKViewUsed[i] = 1;
1296:       break;
1297:     }
1298:   }
1299:   if (win->view == -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Requested more OpenGL ES windows then provided with PetscDrawOpenGLRegisterGLKView()");

1301:   if (!initialized) {
1302:     initialized = PETSC_TRUE;
1303:     InitializeColors();
1304:   }
1305:   InitializeShader();

1307:   PetscDrawClear(draw);
1308:   NSLog(@"Ending PetscDrawCreate_OpenGLES()");
1309:   return(0);
1310: }

1312: #endif