Actual source code: openglops.c

petsc-3.10.5 2019-03-28
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>
 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];
 44: static PetscErrorCode InitializeColors(void)
 45: {

 49:   rcolor[PETSC_DRAW_WHITE]           = 255;
 50:   gcolor[PETSC_DRAW_WHITE]           = 255;
 51:   bcolor[PETSC_DRAW_WHITE]           = 255;
 52:   rcolor[PETSC_DRAW_BLACK]           =   0;
 53:   gcolor[PETSC_DRAW_BLACK]           =   0;
 54:   bcolor[PETSC_DRAW_BLACK]           =   0;
 55:   rcolor[PETSC_DRAW_RED]             = 255;
 56:   gcolor[PETSC_DRAW_RED]             =   0;
 57:   bcolor[PETSC_DRAW_RED]             =   0;
 58:   rcolor[PETSC_DRAW_GREEN]           =   0;
 59:   gcolor[PETSC_DRAW_GREEN]           = 128;
 60:   bcolor[PETSC_DRAW_GREEN]           =   0;
 61:   rcolor[PETSC_DRAW_CYAN]            =   0;
 62:   gcolor[PETSC_DRAW_CYAN]            = 139;
 63:   bcolor[PETSC_DRAW_CYAN]            = 139;
 64:   rcolor[PETSC_DRAW_BLUE]            =   0;
 65:   gcolor[PETSC_DRAW_BLUE]            =   0;
 66:   bcolor[PETSC_DRAW_BLUE]            = 255;
 67:   rcolor[PETSC_DRAW_MAGENTA]         = 255;
 68:   gcolor[PETSC_DRAW_MAGENTA]         =   0;
 69:   bcolor[PETSC_DRAW_MAGENTA]         = 255;
 70:   rcolor[PETSC_DRAW_AQUAMARINE]      = 127;
 71:   gcolor[PETSC_DRAW_AQUAMARINE]      = 255;
 72:   bcolor[PETSC_DRAW_AQUAMARINE]      = 212;
 73:   rcolor[PETSC_DRAW_FORESTGREEN]     =  34;
 74:   gcolor[PETSC_DRAW_FORESTGREEN]     = 139;
 75:   bcolor[PETSC_DRAW_FORESTGREEN]     =  34;
 76:   rcolor[PETSC_DRAW_ORANGE]          = 255;
 77:   gcolor[PETSC_DRAW_ORANGE]          = 165;
 78:   bcolor[PETSC_DRAW_ORANGE]          =   0;
 79:   rcolor[PETSC_DRAW_VIOLET]          = 238;
 80:   gcolor[PETSC_DRAW_VIOLET]          = 130;
 81:   bcolor[PETSC_DRAW_VIOLET]          = 238;
 82:   rcolor[PETSC_DRAW_BROWN]           = 165;
 83:   gcolor[PETSC_DRAW_BROWN]           =  42;
 84:   bcolor[PETSC_DRAW_BROWN]           =  42;
 85:   rcolor[PETSC_DRAW_PINK]            = 255;
 86:   gcolor[PETSC_DRAW_PINK]            = 192;
 87:   bcolor[PETSC_DRAW_PINK]            = 203;
 88:   rcolor[PETSC_DRAW_CORAL]           = 255;
 89:   gcolor[PETSC_DRAW_CORAL]           = 127;
 90:   bcolor[PETSC_DRAW_CORAL]           =  80;
 91:   rcolor[PETSC_DRAW_GRAY]            = 128;
 92:   gcolor[PETSC_DRAW_GRAY]            = 128;
 93:   bcolor[PETSC_DRAW_GRAY]            = 128;
 94:   rcolor[PETSC_DRAW_YELLOW]          = 255;
 95:   gcolor[PETSC_DRAW_YELLOW]          = 255;
 96:   bcolor[PETSC_DRAW_YELLOW]          =   0;
 97:   rcolor[PETSC_DRAW_GOLD]            = 255;
 98:   gcolor[PETSC_DRAW_GOLD]            = 215;
 99:   bcolor[PETSC_DRAW_GOLD]            =   0;
100:   rcolor[PETSC_DRAW_LIGHTPINK]       = 255;
101:   gcolor[PETSC_DRAW_LIGHTPINK]       = 182;
102:   bcolor[PETSC_DRAW_LIGHTPINK]       = 193;
103:   rcolor[PETSC_DRAW_MEDIUMTURQUOISE] =  72;
104:   gcolor[PETSC_DRAW_MEDIUMTURQUOISE] = 209;
105:   bcolor[PETSC_DRAW_MEDIUMTURQUOISE] = 204;
106:   rcolor[PETSC_DRAW_KHAKI]           = 240;
107:   gcolor[PETSC_DRAW_KHAKI]           = 230;
108:   bcolor[PETSC_DRAW_KHAKI]           = 140;
109:   rcolor[PETSC_DRAW_DIMGRAY]         = 105;
110:   gcolor[PETSC_DRAW_DIMGRAY]         = 105;
111:   bcolor[PETSC_DRAW_DIMGRAY]         = 105;
112:   rcolor[PETSC_DRAW_YELLOWGREEN]     =  54;
113:   gcolor[PETSC_DRAW_YELLOWGREEN]     = 205;
114:   bcolor[PETSC_DRAW_YELLOWGREEN]     =  50;
115:   rcolor[PETSC_DRAW_SKYBLUE]         = 135;
116:   gcolor[PETSC_DRAW_SKYBLUE]         = 206;
117:   bcolor[PETSC_DRAW_SKYBLUE]         = 235;
118:   rcolor[PETSC_DRAW_DARKGREEN]       =   0;
119:   gcolor[PETSC_DRAW_DARKGREEN]       = 100;
120:   bcolor[PETSC_DRAW_DARKGREEN]       =   0;
121:   rcolor[PETSC_DRAW_NAVYBLUE]        =   0;
122:   gcolor[PETSC_DRAW_NAVYBLUE]        =   0;
123:   bcolor[PETSC_DRAW_NAVYBLUE]        = 128;
124:   rcolor[PETSC_DRAW_SANDYBROWN]      = 244;
125:   gcolor[PETSC_DRAW_SANDYBROWN]      = 164;
126:   bcolor[PETSC_DRAW_SANDYBROWN]      =  96;
127:   rcolor[PETSC_DRAW_CADETBLUE]       =  95;
128:   gcolor[PETSC_DRAW_CADETBLUE]       = 158;
129:   bcolor[PETSC_DRAW_CADETBLUE]       = 160;
130:   rcolor[PETSC_DRAW_POWDERBLUE]      = 176;
131:   gcolor[PETSC_DRAW_POWDERBLUE]      = 224;
132:   bcolor[PETSC_DRAW_POWDERBLUE]      = 230;
133:   rcolor[PETSC_DRAW_DEEPPINK]        = 255;
134:   gcolor[PETSC_DRAW_DEEPPINK]        =  20;
135:   bcolor[PETSC_DRAW_DEEPPINK]        = 147;
136:   rcolor[PETSC_DRAW_THISTLE]         = 216;
137:   gcolor[PETSC_DRAW_THISTLE]         = 191;
138:   bcolor[PETSC_DRAW_THISTLE]         = 216;
139:   rcolor[PETSC_DRAW_LIMEGREEN]       =  50;
140:   gcolor[PETSC_DRAW_LIMEGREEN]       = 205;
141:   bcolor[PETSC_DRAW_LIMEGREEN]       =  50;
142:   rcolor[PETSC_DRAW_LAVENDERBLUSH]   = 255;
143:   gcolor[PETSC_DRAW_LAVENDERBLUSH]   = 240;
144:   bcolor[PETSC_DRAW_LAVENDERBLUSH]   = 245;
145:   rcolor[PETSC_DRAW_PLUM]            = 221;
146:   gcolor[PETSC_DRAW_PLUM]            = 160;
147:   bcolor[PETSC_DRAW_PLUM]            = 221;

149:   PetscDrawUtilitySetCmap(NULL,256-PETSC_DRAW_BASIC_COLORS,rcolor+PETSC_DRAW_BASIC_COLORS,gcolor+PETSC_DRAW_BASIC_COLORS,bcolor+PETSC_DRAW_BASIC_COLORS);
150:   return(0);
151: }

153: static GLuint vertexshader,fragmentshader,shaderprogram;
154: static PetscErrorCode InitializeShader(void)
155: {
156:   const char *vertexsource = "attribute vec2 position;\
157:                               attribute vec3 color; \
158:                               varying vec4 vColor;\
159:                               void main(void)\
160:                               {\
161:                                 vColor = vec4(color,0.50);\
162:                                 gl_Position = vec4(position,0.0,1.0);\
163:                               }\n";
164: #if defined(PETSC_HAVE_GLUT)
165:   const char *fragmentsource = "varying vec4 vColor;\
166:                                 void main (void)\
167:                                 {\
168:                                   gl_FragColor = vColor; \
169:                                 }\n";
170: #else
171:   const char *fragmentsource = "precision mediump float;\
172:                                 varying vec4 vColor;\
173:                                 void main (void)\
174:                                 {\
175:                                   gl_FragColor = vColor; \
176:                                 }\n";
177: #endif
178:   int    isCompiled_VS, isCompiled_FS;
179:   int    isLinked;
180:   GLenum err;

183:   /*  http://www.opengl.org/wiki/OpenGL_Shading_Language */
184:   /* Create an empty vertex shader handle */
185:   vertexshader = glCreateShader(GL_VERTEX_SHADER);

187:   /* Send the vertex shader source code to GL */
188:   /* Note that the source code is NULL character terminated. */
189:   /* GL will automatically detect that therefore the length info can be 0 in this case (the last parameter) */
190:   glShaderSource(vertexshader, 1, (const GLchar**)&vertexsource, 0);

192:   /* Compile the vertex shader */
193:   glCompileShader(vertexshader);
194:   glGetShaderiv(vertexshader, GL_COMPILE_STATUS, &isCompiled_VS);
195:   if (isCompiled_VS == GL_FALSE) {
197:     int            maxLength;
198:     char           *vertexInfoLog;
199:     glGetShaderiv(vertexshader, GL_INFO_LOG_LENGTH, &maxLength);
200:     PetscMalloc1(maxLength,&vertexInfoLog);
201:     glGetShaderInfoLog(vertexshader, maxLength, &maxLength, vertexInfoLog);
202:     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Failed to compile vertex shader %s",vertexInfoLog);
203:   }

205:   /* Create an empty fragment shader handle */
206:   fragmentshader = glCreateShader(GL_FRAGMENT_SHADER);

208:   /* Send the fragment shader source code to GL */
209:   /* Note that the source code is NULL character terminated. */
210:   /* GL will automatically detect that therefore the length info can be 0 in this case (the last parameter) */
211:   glShaderSource(fragmentshader, 1, (const GLchar**)&fragmentsource, 0);

213:   /* Compile the fragment shader */
214:   glCompileShader(fragmentshader);
215:   glGetShaderiv(fragmentshader, GL_COMPILE_STATUS, &isCompiled_FS);
216:   if (isCompiled_FS == GL_FALSE) {
218:     int            maxLength;
219:     char           *fragmentInfoLog;
220:     glGetShaderiv(fragmentshader, GL_INFO_LOG_LENGTH, &maxLength);
221:     PetscMalloc1(maxLength,&fragmentInfoLog);
222:     glGetShaderInfoLog(fragmentshader, maxLength, &maxLength, fragmentInfoLog);
223:     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Failed to compile fragment shader %s",fragmentInfoLog);
224:   }

226:   /* If we reached this point it means the vertex and fragment shaders compiled and are syntax error free. */
227:   /* We must link them together to make a GL shader program */
228:   /* GL shader programs are monolithic. It is a single piece made of 1 vertex shader and 1 fragment shader. */
229:   /* Assign our program handle a "name" */
230:   shaderprogram = glCreateProgram();

232:   /* Attach our shaders to our program */
233:   glAttachShader(shaderprogram, vertexshader);
234:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
235:   glAttachShader(shaderprogram, fragmentshader);
236:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);

238:   glBindAttribLocation(shaderprogram,0,"position");
239:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
240:   glBindAttribLocation(shaderprogram,1,"color");
241:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);

243:   /* Link our program */
244:   /* At this stage, the vertex and fragment programs are inspected, optimized and a binary code is generated for the shader. */
245:   /* The binary code is uploaded to the GPU, if there is no error. */
246:   glLinkProgram(shaderprogram);

248:   /* Again, we must check and make sure that it linked. If it fails, it would mean either there is a mismatch between the vertex */
249:   /* and fragment shaders. It might be that you have surpassed your GPU's abilities. Perhaps too many ALU operations or */
250:   /* too many texel fetch instructions or too many interpolators or dynamic loops. */

252:   glGetProgramiv(shaderprogram, GL_LINK_STATUS, &isLinked);
253:   if (isLinked == GL_FALSE) {
254:     /*
255:     char          *shaderProgramInfoLog;
256:     glGetProgramiv(shaderprogram, GL_INFO_LOG_LENGTH, &maxLength);
257:     shaderProgramInfoLog = new char[maxLength];
258:     glGetProgramInfoLog(shaderprogram, maxLength, &maxLength, shaderProgramInfoLog);
259:     free(shaderProgramInfoLog);
260:     */
261:     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Failed to compile fragment shader");
262:   }

264:   /* In your rendering code, you just need to call glUseProgram, call the various glUniform** to update your uniforms */
265:   /* and then render. */
266:   /* Load the shader into the rendering pipeline */
267:   glUseProgram(shaderprogram);
268:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
269:   return(0);
270: }

272: /*
273:     This is currently all wrong, there is actually a separate shader for each window
274:    so they cannot be stored as global
275: */
276: static PetscErrorCode FinalizeShader(void)
277: {
279:   /* When the user shuts down your program, you should deallocate all your GL resources. */
280:   /* Unbind your shader. */
281:   glUseProgram(0);
282:   /* Let's detach */
283:   glDetachShader(shaderprogram, vertexshader);
284:   glDetachShader(shaderprogram, fragmentshader);
285:   /* Delete the shaders */
286:   glDeleteShader(vertexshader);
287:   glDeleteShader(fragmentshader);
288:   /* Delete the shader object */
289:   glDeleteProgram(shaderprogram);
290:   return(0);
291: }

293: PETSC_INTERN PetscErrorCode PetscDrawClear_OpenGL_Base(PetscDraw);

295: #if defined(PETSC_HAVE_GLUT)
296: #include <GLUT/glut.h>
297: typedef struct {
298:   int win;           /* OpenGL GLUT window identifier */
299:   int x,y,w,h;       /* Size and location of window */
300: } PetscDraw_OpenGL;

302: static int currentwindow = -1;
303: PETSC_STATIC_INLINE PetscErrorCode OpenGLWindow(PetscDraw_OpenGL *win)
304: {
305:   if (win->win == currentwindow) return 0;
306:   currentwindow = win->win;
307:   glutSetWindow(win->win);
308:   return 0;
309: }

311: PETSC_STATIC_INLINE PetscErrorCode OpenGLString(float x,float y, const char *str,size_t len,int icolor)
312: {
313:   PetscInt i;

315:   glColor3ub(rcolor[icolor],gcolor[icolor],bcolor[icolor]);
316:   glRasterPos2f(x, y);
317:   for (i = 0; i < len; i++) glutBitmapCharacter(GLUT_BITMAP_8_BY_13, str[i]);
318:   return 0;
319: }

321: PetscErrorCode PetscDrawClear_OpenGL(PetscDraw draw)
322: {

326:   PetscDrawClear_OpenGL_Base(draw);
327:   return(0);
328: }

330: static PetscErrorCode PetscDrawGetPopup_OpenGL(PetscDraw draw,PetscDraw *popup)
331: {

335:   PetscDrawCreate(PetscObjectComm((PetscObject)draw),NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,PETSC_DECIDE,PETSC_DECIDE,popup);
336:   PetscDrawSetType(*popup,((PetscObject)draw)->type_name);

338:   draw->popup = *popup;
339:   return(0);
340: }

342: static PetscErrorCode PetscDrawStringVertical_OpenGL(PetscDraw draw,PetscReal x,PetscReal y,int c,const char chrs[])
343: {
344:   PetscErrorCode   ierr;
345:   float            xx,yy;
346:   PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
347:   PetscReal        tw,th;
348:   size_t           i,n;

351:   OpenGLWindow(win);
352:   PetscStrlen(chrs,&n);
353:   PetscDrawStringGetSize(draw,&tw,&th);
354:   xx   = XTRANS(draw,x);
355:   for (i=0; i<n; i++) {
356:     yy   = YTRANS(draw,y-th*i);
357:     OpenGLString(xx,yy,chrs+i,1,c);
358:   }
359:   return(0);
360: }

362: static PetscErrorCode PetscDrawString_OpenGL(PetscDraw draw,PetscReal x,PetscReal y,int c,const char chrs[])
363: {
364:   PetscErrorCode   ierr;
365:   float            xx,yy;
366:   size_t           len;
367:   PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
368:   char             *substr;
369:   PetscToken       token;

372:   xx   = XTRANS(draw,x);
373:   yy   = YTRANS(draw,y);
374:   OpenGLWindow(win);

376:   PetscTokenCreate(chrs,'\n',&token);
377:   PetscTokenFind(token,&substr);
378:   PetscStrlen(substr,&len);
379:   OpenGLString(xx,yy,substr,len,c);
380:   PetscTokenFind(token,&substr);
381:   while (substr) {
382:     yy  += 16;
383:     PetscStrlen(substr,&len);
384:     OpenGLString(xx,yy,substr,len,c);
385:     PetscTokenFind(token,&substr);
386:   }
387:   PetscTokenDestroy(&token);
388:   return(0);
389: }

391: static PetscErrorCode PetscDrawSetTitle_OpenGL(PetscDraw draw,const char title[])
392: {
393:   PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
394:   PetscErrorCode   ierr;

397:   OpenGLWindow(win);
398:   glutSetWindowTitle(title);
399:   return(0);
400: }

402: static PetscErrorCode PetscDrawDestroy_OpenGL(PetscDraw draw)
403: {
404:   PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
405:   PetscErrorCode   ierr;

408:   PetscDrawClear(draw);
409:   PetscDrawDestroy(&draw->popup);
410:   glutDestroyWindow(win->win);
411:   PetscFree(draw->data);
412:   return(0);
413: }

415: static PetscErrorCode PetscDrawFlush_OpenGL(PetscDraw draw)
416: {
417:   PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
418:   PetscErrorCode   ierr;

421:   OpenGLWindow(win);
422:   glutCheckLoop();
423:   glFinish();
424:   return(0);
425: }

427: static PetscErrorCode PetscDrawStringGetSize_OpenGL(PetscDraw draw,PetscReal *x,PetscReal  *y)
428: {
429:   PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
430:   PetscInt         w;
431:   PetscErrorCode   ierr;

434:   OpenGLWindow(win);
435:   w    = glutBitmapWidth(GLUT_BITMAP_8_BY_13,'W');
436:   if (x) *x   = w*(draw->coor_xr - draw->coor_xl)/((win->w)*(draw->port_xr - draw->port_xl));
437:   if (y) *y   = (13./8.0)*w*(draw->coor_yr - draw->coor_yl)/((win->h)*(draw->port_yr - draw->port_yl));
438:   return(0);
439: }

441: static PetscErrorCode PetscDrawResizeWindow_OpenGL(PetscDraw draw,int w,int h)
442: {
443:   PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
444:   PetscErrorCode   ierr;

447:   OpenGLWindow(win);
448:   glutReshapeWindow(w,h);
449:   PetscDrawFlush(draw);
450:   PetscDrawCheckResizedWindow(draw);
451:   return(0);
452: }

454: static PetscBool resized = PETSC_FALSE;

456: static PetscErrorCode PetscDrawCheckResizedWindow_OpenGL(PetscDraw draw)
457: {

461:   if (!resized) return(0);
462:   resized = PETSC_FALSE;
463:   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
464:   PetscDrawClear(draw);
465:   return(0);
466: }

468: typedef struct {
469:   int button,x,y;
470: } OpenGLButton;
471: static OpenGLButton Mouse;

473: static PetscErrorCode PetscDrawGetMouseButton_OpenGL(PetscDraw draw,PetscDrawButton *button,PetscReal *x_user,PetscReal *y_user,PetscReal *x_phys,PetscReal *y_phys)
474: {
475:   PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
476:   int              px,py;

479:   while (Mouse.button == -1) glutCheckLoop();

481:   *button      = (PetscDrawButton)(Mouse.button + 1);
482:   px           = Mouse.x;
483:   py           = Mouse.y;
484:   Mouse.button = -1;

486:   if (x_phys) *x_phys = ((double)px)/((double)win->w);
487:   if (y_phys) *y_phys = 1.0 - ((double)py)/((double)win->h);

489:   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);
490:   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);
491:   return(0);
492: }
493: #elif defined(PETSC_HAVE_OPENGLES)
494: typedef struct {
495:   GLint   win;    /* not currently used */
496:   int     w,h;    /* width and height in pixels */
497:   int     view;
498: } PetscDraw_OpenGL;

500: static GLKView *globalGLKView[10] = {0,0,0,0,0,0,0,0,0,0};
501: static int     globalGLKViewUsed[10]  = {0,0,0,0,0,0,0,0,0,0};
502: PETSC_STATIC_INLINE PetscErrorCode OpenGLWindow(PetscDraw_OpenGL *win)
503: {
504:   return 0;
505: }

507: static PetscErrorCode PetscDrawClear_OpenGL(PetscDraw draw)
508: {
509:   PetscErrorCode   ierr;
510:   PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;

513:   /* remove all UIText added to window */
514:   for (UIView *view in [globalGLKView[win->view] subviews]) {[view removeFromSuperview];}
515:   PetscDrawClear_OpenGL_Base(draw);
516:   return(0);
517: }

519: static PetscErrorCode PetscDrawGetPopup_OpenGL(PetscDraw draw,PetscDraw *popup)
520: {

524:   *popup = NULL;
525:   return(0);
526: }

528: static PetscErrorCode PetscDrawString_OpenGL(PetscDraw draw,PetscReal x,PetscReal y,int c,const char chrs[])
529: {
530:   PetscErrorCode   ierr;
531:   float            xx,yy;
532:   PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
533:   UILabel          *yourLabel;

536:   OpenGLWindow(win);
537:   xx   = XPTRANS(draw,win,x);
538:   yy   = YPTRANS(draw,win,y);
539:   NSLog(@"Draw string start");
540:   yourLabel = [[UILabel alloc] initWithFrame:CGRectMake(xx, yy, 300, 20)];
541:   [yourLabel setTextColor:[UIColor colorWithRed:rcolor[c]/255.0 green:gcolor[c]/255.0 blue:rcolor[c]/255.0 alpha:1.0]];
542:   [yourLabel setText: [[NSString alloc] initWithCString:chrs encoding:NSMacOSRomanStringEncoding]];
543:   [yourLabel setBackgroundColor:[UIColor clearColor]];
544:   /* [yourLabel setFont:[UIFont fontWithName: @"Trebuchet MS" size: 14.0f]]; */
545:   [globalGLKView[win->view] addSubview:yourLabel];
546:   NSLog(@"Draw string end");
547:   return(0);
548: }

550: /*
551:    I don't understand the rotation. It seems to maybe rotate from the middle of the width?

553:    It would be nice if the frame could be made to match the text length automatically

555:    This makes src/sys/draw/examples/tests/ex3.c look good but may be terrible for other locations
556: */
557: static PetscErrorCode PetscDrawStringVertical_OpenGL(PetscDraw draw,PetscReal x,PetscReal y,int c,const char chrs[])
558: {
559:   PetscErrorCode   ierr;
560:   float            xx,yy, w = 100,h = 20;
561:   PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
562:   UILabel          *yourLabel;

565:   OpenGLWindow(win);
566:   xx   = XPTRANS(draw,win,x);
567:   yy   = YPTRANS(draw,win,y);
568:   NSLog(@"Draw string vertical start");
569:   yourLabel = [[UILabel alloc] initWithFrame:CGRectMake(0,0, w, h)];
570:   [yourLabel setTextColor:[UIColor colorWithRed:rcolor[c]/255.0 green:gcolor[c]/255.0 blue:rcolor[c]/255.0 alpha:1.0]];
571:   [yourLabel setText: [[NSString alloc] initWithCString:chrs encoding:NSMacOSRomanStringEncoding]];
572:   [yourLabel setBackgroundColor:[UIColor clearColor]];
573:   [yourLabel setTransform:CGAffineTransformTranslate(CGAffineTransformMakeRotation(-PETSC_PI / 2),-w/2.0-yy,-h+xx)];
574:   /* [yourLabel setFont:[UIFont fontWithName: @"Trebuchet MS" size: 14.0f]]; */
575:   [globalGLKView[win->view] addSubview:yourLabel];
576:   NSLog(@"Draw string vertical end");
577:   return(0);
578: }

580: static PetscErrorCode PetscDrawSetTitle_OpenGL(PetscDraw draw,const char title[])
581: {
582:   return 0;
583: }
584: static PetscErrorCode PetscDrawDestroy_OpenGL(PetscDraw draw)
585: {
586:   PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
587:   PetscErrorCode   ierr;
588:   PetscInt         i;

591:   globalGLKViewUsed[win->view] = 0;
592:   PetscFree(draw->data);
593:   return(0);
594:   return(0);
595: }
596: static PetscErrorCode PetscDrawFlush_OpenGL(PetscDraw draw)
597: {
598:   PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;

600:   GLenum err;
601:   glFlush();
602:   err = glGetError();
603:   if (err != GL_NO_ERROR) {
604:     NSLog(@"GL error detected glFlush()");
605:     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unable to flush OpenGL Error Code %d",err);
606:   }
607:   [globalGLKView[win->view] display];
608:   NSLog(@"Completed display in PetscDrawFlush()");
609:   return 0;
610: }
611: static PetscErrorCode PetscDrawStringGetSize_OpenGL(PetscDraw draw,PetscReal *x,PetscReal  *y)
612: {
613:   float w = .02;
614:   if (x) *x = w*(draw->coor_xr - draw->coor_xl)/(draw->port_xr - draw->port_xl);
615:   if (y) *y = (13./8.0)*w*(draw->coor_yr - draw->coor_yl)/(draw->port_yr - draw->port_yl);
616:   return 0;
617: }
618: static PetscErrorCode PetscDrawResizeWindow_OpenGL(PetscDraw draw,int w,int h)
619: {
620:   return 0;
621: }
622: static PetscErrorCode PetscDrawCheckResizedWindow_OpenGL(PetscDraw draw)
623: {
624:   return 0;
625: }
626: static PetscErrorCode PetscDrawGetMouseButton_OpenGL(PetscDraw draw,PetscDrawButton *button,PetscReal *x_user,PetscReal *y_user,PetscReal *x_phys,PetscReal *y_phys)
627: {
628:   return 0;
629: }
630: #endif

632: /* -----------------------------------------------------------------------*/

634: PetscErrorCode PetscDrawClear_OpenGL_Base(PetscDraw draw)
635: {
636:   PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
637:   PetscErrorCode   ierr;
638:   float            xl,yl,xr,yr;
639:   GLfloat          vertices[12];
640:   GLfloat          colors[18];
641:   GLuint           positionBufferObject;
642:   GLuint           colorBufferObject;
643:   GLenum           err;

646:   OpenGLWindow(win);
647:   xl   = -1.0 + 2.0*((draw)->port_xl);
648:   xr   = -1.0 + 2.0*((draw)->port_xr);
649:   yl   = -1.0 + 2.0*((draw)->port_yl);
650:   yr   = -1.0 + 2.0*((draw)->port_yr);

652:   vertices[0] = xl;
653:   vertices[1] = yl;
654:   vertices[2] = xr;
655:   vertices[3] = yl;
656:   vertices[4] = xl;
657:   vertices[5] = yr;

659:   vertices[6]  = xl;
660:   vertices[7]  = yr;
661:   vertices[8]  = xr;
662:   vertices[9]  = yr;
663:   vertices[10] = xr;
664:   vertices[11] = yl;

666:   colors[0] = 1.0;  colors[1] = 1.0; colors[2] = 1.0;
667:   colors[3] = 1.0;  colors[4] = 1.0; colors[5] = 1.0;
668:   colors[6] = 1.0;  colors[7] = 1.0; colors[8] = 1.0;

670:   colors[9]  = 1.0;  colors[10] = 1.0; colors[11] = 1.0;
671:   colors[12] = 1.0;  colors[13] = 1.0; colors[14] = 1.0;
672:   colors[15] = 1.0;  colors[16] = 1.0; colors[17] = 1.0;

674:   glGenBuffers(1, &positionBufferObject);
675:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
676:   glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
677:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
678:   glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
679:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
680:   glEnableVertexAttribArray(0);
681:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
682:   glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
683:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);

685:   glGenBuffers(1, &colorBufferObject);
686:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
687:   glBindBuffer(GL_ARRAY_BUFFER, colorBufferObject);
688:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
689:   glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
690:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
691:   glEnableVertexAttribArray(1);
692:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
693:   glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
694:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);

696:   glDrawArrays(GL_TRIANGLES, 0, 6);
697:   glDisableVertexAttribArray(0);
698:   glDisableVertexAttribArray(1);
699:   glDeleteBuffers(1, &positionBufferObject);
700:   glDeleteBuffers(1, &colorBufferObject);
701:   PetscDrawFlush(draw);
702:   return(0);
703: }

705: static PetscErrorCode PetscDrawPoint_OpenGL(PetscDraw draw,PetscReal xl,PetscReal yl,int cl)
706: {
707:   PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
708:   GLfloat          vertices[2],colors[3];
709:   PetscErrorCode   ierr;
710:   GLuint           positionBufferObject;
711:   GLuint           colorBufferObject;
712:   GLenum           err;

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

719:   OpenGLWindow(win);
720:   glGenBuffers(1, &positionBufferObject);
721:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
722:   glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
723:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
724:   glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
725:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
726:   glEnableVertexAttribArray(0);
727:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
728:   glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
729:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);

731:   glGenBuffers(1, &colorBufferObject);
732:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
733:   glBindBuffer(GL_ARRAY_BUFFER, colorBufferObject);
734:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
735:   glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
736:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
737:   glEnableVertexAttribArray(1);
738:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
739:   glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
740:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);

742:   glDrawArrays(GL_POINTS, 0, 2);
743:   glDisableVertexAttribArray(0);
744:   glDisableVertexAttribArray(1);
745:   glDeleteBuffers(1, &positionBufferObject);
746:   glDeleteBuffers(1, &colorBufferObject);
747:   return(0);
748: }

750: static PetscErrorCode PetscDrawLine_OpenGL(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int cl)
751: {
752:   PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
753:   GLfloat          linevertices[4],colors[6];
754:   PetscErrorCode   ierr;
755:   GLenum           err;
756:   GLuint           positionBufferObject;
757:   GLuint           colorBufferObject;


761:   linevertices[0] = XTRANS(draw,xl);
762:   linevertices[2] = XTRANS(draw,xr);
763:   linevertices[1] = YTRANS(draw,yl);
764:   linevertices[3] = YTRANS(draw,yr);
765:   if (linevertices[0] == linevertices[2] && linevertices[1] == linevertices[3]) return(0);
766:   colors[0] = rcolor[cl]/255.0;  colors[1] = gcolor[cl]/255.0; colors[2] = bcolor[cl]/255.0;
767:   colors[3] = rcolor[cl]/255.0;  colors[4] = gcolor[cl]/255.0; colors[5] = bcolor[cl]/255.0;

769:   OpenGLWindow(win);
770:   /* http://arcsynthesis.org/gltut/Basics/Tutorial%2001.html */
771:   glGenBuffers(1, &positionBufferObject);
772:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
773:   glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
774:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
775:   glBufferData(GL_ARRAY_BUFFER, sizeof(linevertices), linevertices, GL_STATIC_DRAW);
776:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
777:   glEnableVertexAttribArray(0);
778:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
779:   glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
780:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);

782:   glGenBuffers(1, &colorBufferObject);
783:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
784:   glBindBuffer(GL_ARRAY_BUFFER, colorBufferObject);
785:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
786:   glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
787:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
788:   glEnableVertexAttribArray(1);
789:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
790:   glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
791:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);

793:   glDrawArrays(GL_LINES, 0, 2);
794:   glDisableVertexAttribArray(0);
795:   glDisableVertexAttribArray(1);
796:   glDeleteBuffers(1, &positionBufferObject);
797:   glDeleteBuffers(1, &colorBufferObject);
798:   return(0);
799: }

801: 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)
802: {
803:   PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
804:   PetscErrorCode   ierr;
805:   GLfloat          vertices[6],colors[9];
806:   GLenum           err;
807:   GLuint           positionBufferObject;
808:   GLuint           colorBufferObject;

811:   vertices[0] = XTRANS(draw,X1);
812:   vertices[1] = YTRANS(draw,Y_1);
813:   vertices[2] = XTRANS(draw,X2);
814:   vertices[3] = YTRANS(draw,Y2);
815:   vertices[4] = XTRANS(draw,X3);
816:   vertices[5] = YTRANS(draw,Y3);
817:   colors[0]   = rcolor[c1]/255.0;  colors[1] = gcolor[c1]/255.0; colors[2] = bcolor[c1]/255.0;
818:   colors[3]   = rcolor[c2]/255.0;  colors[4] = gcolor[c2]/255.0; colors[5] = bcolor[c2]/255.0;
819:   colors[6]   = rcolor[c3]/255.0;  colors[7] = gcolor[c3]/255.0; colors[8] = bcolor[c3]/255.0;

821:   OpenGLWindow(win);
822:   glGenBuffers(1, &positionBufferObject);
823:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
824:   glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
825:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
826:   glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
827:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
828:   glEnableVertexAttribArray(0);
829:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
830:   glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
831:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);

833:   glGenBuffers(1, &colorBufferObject);
834:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
835:   glBindBuffer(GL_ARRAY_BUFFER, colorBufferObject);
836:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
837:   glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
838:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
839:   glEnableVertexAttribArray(1);
840:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
841:   glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
842:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);

844:   glDrawArrays(GL_TRIANGLES, 0, 3);
845:   glDisableVertexAttribArray(0);
846:   glDisableVertexAttribArray(1);
847:   glDeleteBuffers(1, &positionBufferObject);
848:   glDeleteBuffers(1, &colorBufferObject);
849:   return(0);
850: }

852: static PetscErrorCode PetscDrawRectangle_OpenGL(PetscDraw draw,PetscReal Xl,PetscReal Yl,PetscReal Xr,PetscReal Yr,int c1,int c2,int c3,int c4)
853: {
854:   PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
855:   PetscErrorCode   ierr;
856:   GLfloat          vertices[12],colors[18];
857:   float            x1,y_1,x2,y2;
858:   GLuint           positionBufferObject;
859:   GLuint           colorBufferObject;
860:   GLenum           err;

863:   x1  = XTRANS(draw,Xl);
864:   y_1 = YTRANS(draw,Yl);
865:   x2  = XTRANS(draw,Xr);
866:   y2  = YTRANS(draw,Yr);

868:   OpenGLWindow(win);

870:   vertices[0] = x1; colors[0] = rcolor[c1]/255.0;  colors[1] = gcolor[c1]/255.0; colors[2] = bcolor[c1]/255.0;
871:   vertices[1] = y_1;
872:   vertices[2] = x2;colors[3] = rcolor[c2]/255.0;  colors[4] = gcolor[c2]/255.0; colors[5] = bcolor[c2]/255.0;
873:   vertices[3] = y_1;
874:   vertices[4] = x1;colors[6] = rcolor[c4]/255.0;  colors[7] = gcolor[c4]/255.0; colors[8] = bcolor[c4]/255.0;
875:   vertices[5] = y2;

877:   vertices[6]  = x1;colors[9] = rcolor[c4]/255.0;  colors[10] = gcolor[c4]/255.0; colors[11] = bcolor[c4]/255.0;
878:   vertices[7]  = y2;
879:   vertices[8]  = x2;colors[12] = rcolor[c3]/255.0;  colors[13] = gcolor[c3]/255.0; colors[14] = bcolor[c3]/255.0;
880:   vertices[9]  = y2;
881:   vertices[10] = x2;colors[15] = rcolor[c2]/255.0;  colors[16] = gcolor[c2]/255.0; colors[17] = bcolor[c2]/255.0;
882:   vertices[11] = y_1;

884:   glGenBuffers(1, &positionBufferObject);
885:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
886:   glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
887:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
888:   glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
889:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
890:   glEnableVertexAttribArray(0);
891:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
892:   glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
893:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);

895:   glGenBuffers(1, &colorBufferObject);
896:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
897:   glBindBuffer(GL_ARRAY_BUFFER, colorBufferObject);
898:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
899:   glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
900:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
901:   glEnableVertexAttribArray(1);
902:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
903:   glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
904:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);

906:   glDrawArrays(GL_TRIANGLES, 0, 6);
907:   glDisableVertexAttribArray(0);
908:   glDisableVertexAttribArray(1);
909:   glDeleteBuffers(1, &positionBufferObject);
910:   glDeleteBuffers(1, &colorBufferObject);
911:   return(0);
912: }


915: static PetscErrorCode PetscDrawPause_OpenGL(PetscDraw draw)
916: {

920:   if (draw->pause > 0) PetscSleep(draw->pause);
921:   else if (draw->pause == -1) {
922:     PetscDrawButton button = PETSC_BUTTON_NONE;
923:     PetscDrawGetMouseButton(draw,&button,0,0,0,0);
924:     if (button == PETSC_BUTTON_CENTER) draw->pause = 0;
925:   }
926:   return(0);
927: }


930: static struct _PetscDrawOps DvOps = { 0,
931:                                       PetscDrawFlush_OpenGL,
932:                                       PetscDrawLine_OpenGL,
933:                                       0,
934:                                       0,
935:                                       PetscDrawPoint_OpenGL,
936:                                       0,
937:                                       PetscDrawString_OpenGL,
938:                                       PetscDrawStringVertical_OpenGL,
939:                                       0, /* PetscDrawStringSetSize_OpenGL,*/
940:                                       PetscDrawStringGetSize_OpenGL,
941:                                       0, /* PetscDrawSetViewport_OpenGL,*/
942:                                       PetscDrawClear_OpenGL,
943:                                       PetscDrawRectangle_OpenGL,
944:                                       PetscDrawTriangle_OpenGL,
945:                                       0, /* PetscDrawEllipse_OpenGL,*/
946:                                       PetscDrawGetMouseButton_OpenGL,
947:                                       PetscDrawPause_OpenGL,
948:                                       0,
949:                                       0,
950:                                       PetscDrawGetPopup_OpenGL,
951:                                       PetscDrawSetTitle_OpenGL,
952:                                       PetscDrawCheckResizedWindow_OpenGL,
953:                                       PetscDrawResizeWindow_OpenGL,
954:                                       PetscDrawDestroy_OpenGL,
955:                                       0,
956:                                       0, /* PetscDrawGetSingleton_OpenGL,*/
957:                                       0, /* PetscDrawRestoreSingleton_OpenGL,*/
958:                                       0,
959:                                       0,
960:                                       0,
961:                                       PetscDrawLine_OpenGL};

963: #if defined(PETSC_HAVE_GLUT)
964: /* callbacks required by GLUT */
965: static void display(void) {;}
966: static void reshape(int width, int height)
967: {
968:   glViewport(0, 0, width, height);
969:   resized = PETSC_TRUE;
970: }
971: static void mouse(int button, int state,int x, int y)
972: {
973:   if (state == GLUT_UP) {
974:     Mouse.button = button;
975:     Mouse.x      = x;
976:     Mouse.y      = y;
977:   }
978: }

980: PETSC_EXTERN PetscErrorCode PetscDrawCreate_GLUT(PetscDraw draw)
981: {
982:   PetscDraw_OpenGL *win;
983:   PetscErrorCode   ierr;
984:   PetscInt         xywh[4],osize = 4;
985:   int              x = draw->x,y = draw->y,w = draw->w,h = draw->h;
986:   static int       xavailable = 0,yavailable = 0,xmax = 0,ymax = 0,ybottom = 0;
987:   static PetscBool initialized = PETSC_FALSE;
988:   int              argc;
989:   char             **argv;

992:   if (!initialized) {
993:     PetscGetArgs(&argc,&argv);
994:     glutInit(&argc, argv);
995:     glutInitDisplayMode(GLUT_RGBA /* | GLUT_DOUBLE */| GLUT_DEPTH);
996:     InitializeColors();
997:   }

999:   /*
1000:       Initialize the display size
1001:   */
1002:   if (!xmax) {
1003:     xmax = glutGet(GLUT_SCREEN_WIDTH);
1004:     ymax = glutGet(GLUT_SCREEN_HEIGHT);
1005:   }

1007:   if (w == PETSC_DECIDE) w = draw->w = 300;
1008:   if (h == PETSC_DECIDE) h = draw->h = 300;
1009:   switch (w) {
1010:   case PETSC_DRAW_FULL_SIZE: w = draw->w = xmax - 10; break;
1011:   case PETSC_DRAW_HALF_SIZE: w = draw->w = (xmax - 20)/2; break;
1012:   case PETSC_DRAW_THIRD_SIZE: w = draw->w = (xmax - 30)/3; break;
1013:   case PETSC_DRAW_QUARTER_SIZE: w = draw->w = (xmax - 40)/4; break;
1014:   }
1015:   switch (h) {
1016:   case PETSC_DRAW_FULL_SIZE: h = draw->h = ymax - 10; break;
1017:   case PETSC_DRAW_HALF_SIZE: h = draw->h = (ymax - 20)/2; break;
1018:   case PETSC_DRAW_THIRD_SIZE: h = draw->h = (ymax - 30)/3; break;
1019:   case PETSC_DRAW_QUARTER_SIZE: h = draw->h = (ymax - 40)/4; break;
1020:   }

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


1028:   if (draw->x == PETSC_DECIDE || draw->y == PETSC_DECIDE) {
1029:     /*
1030:        PETSc tries to place windows starting in the upper left corner and
1031:        moving across to the right.

1033:               --------------------------------------------
1034:               |  Region used so far +xavailable,yavailable |
1035:               |                     +                      |
1036:               |                     +                      |
1037:               |++++++++++++++++++++++ybottom               |
1038:               |                                            |
1039:               |                                            |
1040:               |--------------------------------------------|
1041:     */
1042:     /*  First: can we add it to the right? */
1043:     if (xavailable+w+10 <= xmax) {
1044:       x       = xavailable;
1045:       y       = yavailable;
1046:       ybottom = PetscMax(ybottom,y + h + 30);
1047:     } else {
1048:       /* No, so add it below on the left */
1049:       xavailable = 0;
1050:       x          = 0;
1051:       yavailable = ybottom;
1052:       y          = ybottom;
1053:       ybottom    = ybottom + h + 30;
1054:     }
1055:   }
1056:   /* update available region */
1057:   xavailable = PetscMax(xavailable,x + w + 10);
1058:   if (xavailable >= xmax) {
1059:     xavailable = 0;
1060:     yavailable = yavailable + h + 30;
1061:     ybottom    = yavailable;
1062:   }
1063:   if (yavailable >= ymax) {
1064:     y          = 0;
1065:     yavailable = 0;
1066:     ybottom    = 0;
1067:   }

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

1071:   /* actually create and open the window */
1072:   PetscNew(&win);
1073:   PetscLogObjectMemory((PetscObject)draw,sizeof(PetscDraw_OpenGL));

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

1078:   win->x = x;
1079:   win->y = y;
1080:   win->w = w;
1081:   win->h = h;

1083:   glutInitWindowSize(w, h);
1084:   glutInitWindowPosition(x,y);
1085:   win->win = glutCreateWindow(draw->title);
1086:   glutDisplayFunc(display);
1087:   glutReshapeFunc(reshape);
1088:   Mouse.button = -1;
1089:   Mouse.x      = -1;
1090:   Mouse.y      = -1;
1091:   glutMouseFunc(mouse);

1093:   glClearColor(1.0,1.0,1.0,1.0);

1095:   draw->data = win;
1096:   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1097:   InitializeShader();

1099:   PetscDrawClear(draw);
1100:   resized = PETSC_FALSE; /* opening the window triggers OpenGL call to reshape so need to cancel that resized flag */
1101:   glutCheckLoop();
1102:   return(0);
1103: }

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

1108:    Collective on MPI_Comm

1110:    Input Parameters:
1111: +  comm - the communicator that will share X-window
1112: .  display - the X display on which to open,or null for the local machine
1113: .  title - the title to put in the title bar,or null for no title
1114: .  x,y - the screen coordinates of the upper left corner of window
1115:           may use PETSC_DECIDE for these two arguments, then PETSc places the
1116:           window
1117: -  w, h - the screen width and height in pixels,  or PETSC_DRAW_HALF_SIZE, PETSC_DRAW_FULL_SIZE,
1118:           or PETSC_DRAW_THIRD_SIZE or PETSC_DRAW_QUARTER_SIZE

1120:    Output Parameters:
1121: .  draw - the drawing context.

1123:    Options Database Keys:
1124: +  -nox - Disables all x-windows output
1125: .  -draw_pause <pause> - Sets time (in seconds) that the
1126:        program pauses after PetscDrawPause() has been called
1127:        (0 is default, -1 implies until user input).
1128: .  -draw_cmap <name> - Sets the colormap to use.
1129: .  -draw_cmap_reverse - Reverses the colormap.
1130: -  -draw_cmap_brighten - Brighten (0 < beta < 1) or darken (-1 < beta < 0) the colormap.

1132:    Level: beginner

1134:    Note:
1135:    When finished with the drawing context, it should be destroyed
1136:    with PetscDrawDestroy().

1138:    Note for Fortran Programmers:
1139:    Whenever indicating null character data in a Fortran code,
1140:    NULL_CHARACTER must be employed; using NULL is not
1141:    correct for character data!  Thus, NULL_CHARACTER can be
1142:    used for the display and title input parameters.

1144:    Concepts: OpenGL^drawing to

1146: .seealso: PetscDrawFlush(), PetscDrawDestroy(), PetscDrawOpenX(), PetscDrawCreate()
1147: @*/
1148: PetscErrorCode  PetscDrawOpenGLUT(MPI_Comm comm,const char display[],const char title[],int x,int y,int w,int h,PetscDraw *draw)
1149: {

1153:   PetscDrawCreate(comm,display,title,x,y,w,h,draw);
1154:   PetscDrawSetType(*draw,PETSC_DRAW_GLUT);
1155:   return(0);
1156: }

1158: #elif defined(PETSC_HAVE_OPENGLES)

1160: PetscErrorCode  PetscDrawOpenGLESRegisterGLKView(GLKView *view)
1161: {
1162:   PetscInt i;

1165:   for (i=0; i<10; i++) {
1166:     if (view == globalGLKView[i]) return(0);  /* already registered */
1167:     if (!globalGLKView[i]) {
1168:       globalGLKView[i] = view;
1169:       return(0);
1170:     }
1171:   }
1172:   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Out of GLKView slots");
1173:   return(0);
1174: }

1176: PETSC_EXTERN PetscErrorCode PetscDrawCreate_OpenGLES(PetscDraw draw)
1177: {
1178:   PetscDraw_OpenGL *win;
1179:   PetscErrorCode   ierr;
1180:   static PetscBool initialized = PETSC_FALSE;
1181:   PetscInt         i;

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

1186:   PetscMemcpy(draw->ops,&DvOps,sizeof(DvOps));
1187:   PetscNew(&win);
1188:   PetscLogObjectMemory((PetscObject)draw,sizeof(PetscDraw_OpenGL));

1190:   draw->data = win;
1191:   win->view  = -1;
1192:   for (i=0; i<10; i++) {
1193:     if (!globalGLKViewUsed[i]) {
1194:       win->view = i;
1195:       win->w    = globalGLKView[win->view].frame.size.width;
1196:       win->h    = globalGLKView[win->view].frame.size.height;
1197:       [globalGLKView[win->view] bindDrawable];
1198:       globalGLKViewUsed[i] = 1;
1199:       break;
1200:     }
1201:   }
1202:   if (win->view == -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Requested more OpenGL ES windows then provided with PetscDrawOpenGLRegisterGLKView()");

1204:   if (!initialized) {
1205:     initialized = PETSC_TRUE;
1206:     InitializeColors();
1207:   }
1208:   InitializeShader();

1210:   PetscDrawClear(draw);
1211:   NSLog(@"Ending PetscDrawCreate_OpenGLES()");
1212:   return(0);
1213: }

1215: #endif