Date: 2013-07-02T14:38:25+00:00

Actual source code: openglops.c
petsc-3.4.2 2013-07-02

      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:     PetscMalloc(maxLength*sizeof(char),&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:     PetscMalloc(maxLength*sizeof(char),&fragmentInfoLog);
    226:     glGetShaderInfoLog(fragmentshader, maxLength, &maxLength, fragmentInfoLog);
    227:     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Failed to compile fragment shader %s",fragmentInfoLog);
    228:   }

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

    236:   /* Attach our shaders to our program */
    237:   glAttachShader(shaderprogram, vertexshader);
    238:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
    239:   glAttachShader(shaderprogram, fragmentshader);
    240:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);

    242:   glBindAttribLocation(shaderprogram,0,"position");
    243:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
    244:   glBindAttribLocation(shaderprogram,1,"color");
    245:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);

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

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

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

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

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

    299: extern PetscErrorCode PetscDrawClear_OpenGL_Base(PetscDraw);

    301: #if defined(PETSC_HAVE_GLUT)
    302: #include <GLUT/glut.h>
    303: typedef struct {
    304:   int win;           /* OpenGL GLUT window identifier */
    305:   int x,y,w,h;       /* Size and location of window */
    306: } PetscDraw_OpenGL;

    308: static int currentwindow = -1;
    309: PETSC_STATIC_INLINE PetscErrorCode OpenGLWindow(PetscDraw_OpenGL *win)
    310: {
    311:   if (win->win == currentwindow) return 0;
    312:   currentwindow = win->win;
    313:   glutSetWindow(win->win);
    314:   return 0;
    315: }

    317: PETSC_STATIC_INLINE PetscErrorCode OpenGLString(float x,float y, const char *str,size_t len,int icolor)
    318: {
    319:   PetscInt i;

    321:   glColor3ub(rcolor[icolor],gcolor[icolor],bcolor[icolor]);
    322:   glRasterPos2f(x, y);
    323:   for (i = 0; i < len; i++) glutBitmapCharacter(GLUT_BITMAP_8_BY_13, str[i]);
    324:   return 0;
    325: }

    329: PetscErrorCode PetscDrawClear_OpenGL(PetscDraw draw)
    330: {

    334:   PetscDrawClear_OpenGL_Base(draw);
    335:   return(0);
    336: }

    340: static PetscErrorCode PetscDrawGetPopup_OpenGL(PetscDraw draw,PetscDraw *popup)
    341: {

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

    348:   draw->popup = *popup;
    349:   return(0);
    350: }

    354: static PetscErrorCode PetscDrawStringVertical_OpenGL(PetscDraw draw,PetscReal x,PetscReal y,int c,const char chrs[])
    355: {
    356:   PetscErrorCode   ierr;
    357:   float            xx,yy;
    358:   PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
    359:   PetscReal        tw,th;
    360:   size_t           i,n;

    363:   OpenGLWindow(win);
    364:   PetscStrlen(chrs,&n);
    365:   PetscDrawStringGetSize(draw,&tw,&th);
    366:   xx   = XTRANS(draw,x);
    367:   for (i=0; i<n; i++) {
    368:     yy   = YTRANS(draw,y-th*i);
    369:     OpenGLString(xx,yy,chrs+i,1,c);
    370:   }
    371:   return(0);
    372: }

    376: static PetscErrorCode PetscDrawString_OpenGL(PetscDraw draw,PetscReal x,PetscReal y,int c,const char chrs[])
    377: {
    378:   PetscErrorCode   ierr;
    379:   float            xx,yy;
    380:   size_t           len;
    381:   PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
    382:   char             *substr;
    383:   PetscToken       token;

    386:   xx   = XTRANS(draw,x);
    387:   yy   = YTRANS(draw,y);
    388:   OpenGLWindow(win);

    390:   PetscTokenCreate(chrs,'\n',&token);
    391:   PetscTokenFind(token,&substr);
    392:   PetscStrlen(substr,&len);
    393:   OpenGLString(xx,yy,substr,len,c);
    394:   PetscTokenFind(token,&substr);
    395:   while (substr) {
    396:     yy  += 16;
    397:     PetscStrlen(substr,&len);
    398:     OpenGLString(xx,yy,substr,len,c);
    399:     PetscTokenFind(token,&substr);
    400:   }
    401:   PetscTokenDestroy(&token);
    402:   return(0);
    403: }

    407: static PetscErrorCode PetscDrawSetTitle_OpenGL(PetscDraw draw,const char title[])
    408: {
    409:   PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
    410:   PetscErrorCode   ierr;

    413:   OpenGLWindow(win);
    414:   glutSetWindowTitle(title);
    415:   return(0);
    416: }

    420: static PetscErrorCode PetscDrawDestroy_OpenGL(PetscDraw draw)
    421: {
    422:   PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
    423:   PetscErrorCode   ierr;

    426:   PetscDrawSynchronizedClear(draw);
    427:   PetscDrawDestroy(&draw->popup);
    428:   glutDestroyWindow(win->win);
    429:   PetscFree(win);
    430:   return(0);
    431: }

    435: static PetscErrorCode PetscDrawFlush_OpenGL(PetscDraw draw)
    436: {
    437:   PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
    438:   PetscErrorCode   ierr;

    441:   OpenGLWindow(win);
    442:   glutCheckLoop();
    443:   glFinish();
    444:   return(0);
    445: }

    449: static PetscErrorCode PetscDrawStringGetSize_OpenGL(PetscDraw draw,PetscReal *x,PetscReal  *y)
    450: {
    451:   PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
    452:   PetscInt         w;
    453:   PetscErrorCode   ierr;

    456:   OpenGLWindow(win);
    457:   w    = glutBitmapWidth(GLUT_BITMAP_8_BY_13,'W');
    458:   *x   = w*(draw->coor_xr - draw->coor_xl)/((win->w)*(draw->port_xr - draw->port_xl));
    459:   *y   = (13./8.0)*w*(draw->coor_yr - draw->coor_yl)/((win->h)*(draw->port_yr - draw->port_yl));
    460:   return(0);
    461: }

    465: static PetscErrorCode PetscDrawResizeWindow_OpenGL(PetscDraw draw,int w,int h)
    466: {
    467:   PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
    468:   PetscErrorCode   ierr;

    471:   OpenGLWindow(win);
    472:   glutReshapeWindow(w,h);
    473:   PetscDrawFlush(draw);
    474:   PetscDrawCheckResizedWindow(draw);
    475:   return(0);
    476: }

    478: static PetscBool resized = PETSC_FALSE;

    482: static PetscErrorCode PetscDrawCheckResizedWindow_OpenGL(PetscDraw draw)
    483: {

    487:   if (!resized) return(0);
    488:   resized = PETSC_FALSE;
    489:   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    490:   PetscDrawClear(draw);
    491:   return(0);
    492: }

    494: typedef struct {
    495:   int button,x,y;
    496: } OpenGLButton;
    497: static OpenGLButton Mouse;

    501: static PetscErrorCode PetscDrawGetMouseButton_OpenGL(PetscDraw draw,PetscDrawButton *button,PetscReal *x_user,PetscReal *y_user,PetscReal *x_phys,PetscReal *y_phys)
    502: {
    503:   PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
    504:   int              px,py;

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

    509:   *button      = (PetscDrawButton)(Mouse.button + 1);
    510:   px           = Mouse.x;
    511:   py           = Mouse.y;
    512:   Mouse.button = -1;

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

    517:   if (x_user) *x_user = draw->coor_xl + ((((double)px)/((double)win->w)-draw->port_xl))*(draw->coor_xr - draw->coor_xl)/(draw->port_xr - draw->port_xl);
    518:   if (y_user) *y_user = draw->coor_yl + ((1.0 - ((double)py)/((double)win->h)-draw->port_yl))*(draw->coor_yr - draw->coor_yl)/(draw->port_yr - draw->port_yl);
    519:   return(0);
    520: }
    521: #elif defined(PETSC_HAVE_OPENGLES)
    522: typedef struct {
    523:   GLint   win;    /* not currently used */
    524:   int     w,h;    /* width and height in pixels */
    525:   GLKView *view;
    526: } PetscDraw_OpenGL;

    528: static GLKView *globalGLKView[10] = {0,0,0,0,0,0,0,0,0,0};

    530: PETSC_STATIC_INLINE PetscErrorCode OpenGLWindow(PetscDraw_OpenGL *win)
    531: {
    532:   return 0;
    533: }

    537: static PetscErrorCode PetscDrawClear_OpenGL(PetscDraw draw)
    538: {
    539:   PetscErrorCode   ierr;
    540:   PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;

    543:   /* remove all UIText added to window */
    544:   for (UIView *view in [win->view subviews]) {[view removeFromSuperview];}
    545:   PetscDrawClear_OpenGL_Base(draw);
    546:   return(0);
    547: }

    551: static PetscErrorCode PetscDrawGetPopup_OpenGL(PetscDraw draw,PetscDraw *popup)
    552: {

    556:   *popup = NULL;
    557:   return(0);
    558: }

    562: static PetscErrorCode PetscDrawString_OpenGL(PetscDraw draw,PetscReal x,PetscReal y,int c,const char chrs[])
    563: {
    564:   PetscErrorCode   ierr;
    565:   float            xx,yy;
    566:   PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
    567:   UILabel          *yourLabel;

    570:   OpenGLWindow(win);
    571:   xx   = XPTRANS(draw,win,x);
    572:   yy   = YPTRANS(draw,win,y);
    573:   NSLog(@"Draw string start");
    574:   yourLabel = [[UILabel alloc] initWithFrame:CGRectMake(xx, yy, 300, 20)];
    575:   [yourLabel setTextColor:[UIColor colorWithRed:rcolor[c]/255.0 green:gcolor[c]/255.0 blue:rcolor[c]/255.0 alpha:1.0]];
    576:   [yourLabel setText: [[NSString alloc] initWithCString:chrs encoding:NSMacOSRomanStringEncoding]];
    577:   [yourLabel setBackgroundColor:[UIColor clearColor]];
    578:   /* [yourLabel setFont:[UIFont fontWithName: @"Trebuchet MS" size: 14.0f]]; */
    579:   [win->view addSubview:yourLabel];
    580:   NSLog(@"Draw string end");
    581:   return(0);
    582: }

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

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

    589:    This makes src/sys/draw/examples/tests/ex3.c look good but may be terrible for other locations
    590: */
    593: static PetscErrorCode PetscDrawStringVertical_OpenGL(PetscDraw draw,PetscReal x,PetscReal y,int c,const char chrs[])
    594: {
    595:   PetscErrorCode   ierr;
    596:   float            xx,yy, w = 100,h = 20;
    597:   PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
    598:   UILabel          *yourLabel;

    601:   OpenGLWindow(win);
    602:   xx   = XPTRANS(draw,win,x);
    603:   yy   = YPTRANS(draw,win,y);
    604:   NSLog(@"Draw string vertical start");
    605:   yourLabel = [[UILabel alloc] initWithFrame:CGRectMake(0,0, w, h)];
    606:   [yourLabel setTextColor:[UIColor colorWithRed:rcolor[c]/255.0 green:gcolor[c]/255.0 blue:rcolor[c]/255.0 alpha:1.0]];
    607:   [yourLabel setText: [[NSString alloc] initWithCString:chrs encoding:NSMacOSRomanStringEncoding]];
    608:   [yourLabel setBackgroundColor:[UIColor clearColor]];
    609:   [yourLabel setTransform:CGAffineTransformTranslate(CGAffineTransformMakeRotation(-M_PI / 2),-w/2.0-yy,-h+xx)];
    610:   /* [yourLabel setFont:[UIFont fontWithName: @"Trebuchet MS" size: 14.0f]]; */
    611:   [win->view addSubview:yourLabel];
    612:   NSLog(@"Draw string vertical end");
    613:   return(0);
    614: }

    618: static PetscErrorCode PetscDrawSetTitle_OpenGL(PetscDraw draw,const char title[])
    619: {
    620:   return 0;
    621: }
    624: static PetscErrorCode PetscDrawDestroy_OpenGL(PetscDraw draw)
    625: {
    626:   PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
    627:   PetscErrorCode   ierr;
    628:   PetscInt         i;

    631:   for (i=0; i<10; i++) {
    632:     if (!globalGLKView[i]) {
    633:       globalGLKView[i] = win->view;

    635:       PetscFree(win);
    636:       return(0);
    637:     }
    638:   }
    639:   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Could not locate available GLKView slot");
    640:   return(0);
    641: }
    644: static PetscErrorCode PetscDrawFlush_OpenGL(PetscDraw draw)
    645: {
    646:   PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;

    648:   GLenum err;
    649:   glFlush();
    650:   err = glGetError();
    651:   if (err != GL_NO_ERROR) {
    652:     NSLog(@"GL error detected glFlush()");
    653:     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unable to flush OpenGL Error Code %d",err);
    654:   }
    655:   [win->view display];
    656:   NSLog(@"Completed display in PetscDrawFlush()");
    657:   return 0;
    658: }
    661: static PetscErrorCode PetscDrawStringGetSize_OpenGL(PetscDraw draw,PetscReal *x,PetscReal  *y)
    662: {
    663:   float w = .02;
    664:   *x = w*(draw->coor_xr - draw->coor_xl)/(draw->port_xr - draw->port_xl);
    665:   *y = (13./8.0)*w*(draw->coor_yr - draw->coor_yl)/(draw->port_yr - draw->port_yl);
    666:   return 0;
    667: }
    670: static PetscErrorCode PetscDrawResizeWindow_OpenGL(PetscDraw draw,int w,int h)
    671: {
    672:   return 0;
    673: }
    676: static PetscErrorCode PetscDrawCheckResizedWindow_OpenGL(PetscDraw draw)
    677: {
    678:   return 0;
    679: }
    682: static PetscErrorCode PetscDrawGetMouseButton_OpenGL(PetscDraw draw,PetscDrawButton *button,PetscReal *x_user,PetscReal *y_user,PetscReal *x_phys,PetscReal *y_phys)
    683: {
    684:   return 0;
    685: }
    686: #endif

    688: /* -----------------------------------------------------------------------*/
    691: static PetscErrorCode PetscDrawSynchronizedFlush_OpenGL(PetscDraw draw)
    692: {

    696:   /* currently on sequential support */
    697:   PetscDrawFlush(draw);
    698:   return(0);
    699: }

    703: PetscErrorCode PetscDrawClear_OpenGL_Base(PetscDraw draw)
    704: {
    705:   PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
    706:   PetscErrorCode   ierr;
    707:   float            xl,yl,xr,yr;
    708:   GLfloat          vertices[12];
    709:   GLfloat          colors[18];
    710:   GLuint           positionBufferObject;
    711:   GLuint           colorBufferObject;
    712:   GLenum           err;

    715:   OpenGLWindow(win);
    716:   xl   = -1.0 + 2.0*((draw)->port_xl);
    717:   xr   = -1.0 + 2.0*((draw)->port_xr);
    718:   yl   = -1.0 + 2.0*((draw)->port_yl);
    719:   yr   = -1.0 + 2.0*((draw)->port_yr);

    721:   vertices[0] = xl;
    722:   vertices[1] = yl;
    723:   vertices[2] = xr;
    724:   vertices[3] = yl;
    725:   vertices[4] = xl;
    726:   vertices[5] = yr;

    728:   vertices[6]  = xl;
    729:   vertices[7]  = yr;
    730:   vertices[8]  = xr;
    731:   vertices[9]  = yr;
    732:   vertices[10] = xr;
    733:   vertices[11] = yl;

    735:   colors[0] = 1.0;  colors[1] = 1.0; colors[2] = 1.0;
    736:   colors[3] = 1.0;  colors[4] = 1.0; colors[5] = 1.0;
    737:   colors[6] = 1.0;  colors[7] = 1.0; colors[8] = 1.0;

    739:   colors[9]  = 1.0;  colors[10] = 1.0; colors[11] = 1.0;
    740:   colors[12] = 1.0;  colors[13] = 1.0; colors[14] = 1.0;
    741:   colors[15] = 1.0;  colors[16] = 1.0; colors[17] = 1.0;

    743:   glGenBuffers(1, &positionBufferObject);
    744:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
    745:   glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
    746:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
    747:   glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    748:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
    749:   glEnableVertexAttribArray(0);
    750:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
    751:   glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
    752:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);

    754:   glGenBuffers(1, &colorBufferObject);
    755:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
    756:   glBindBuffer(GL_ARRAY_BUFFER, colorBufferObject);
    757:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
    758:   glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
    759:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
    760:   glEnableVertexAttribArray(1);
    761:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
    762:   glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
    763:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);

    765:   glDrawArrays(GL_TRIANGLES, 0, 6);
    766:   glDisableVertexAttribArray(0);
    767:   glDisableVertexAttribArray(1);
    768:   glDeleteBuffers(1, &positionBufferObject);
    769:   glDeleteBuffers(1, &colorBufferObject);
    770:   PetscDrawFlush(draw);
    771:   return(0);
    772: }

    776: static PetscErrorCode PetscDrawSynchronizedClear_OpenGL(PetscDraw draw)
    777: {

    781:   /* currently only sequential support */
    782:   PetscDrawClear(draw);
    783:   return(0);
    784: }

    788: static PetscErrorCode PetscDrawPoint_OpenGL(PetscDraw draw,PetscReal xl,PetscReal yl,int cl)
    789: {
    790:   PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
    791:   GLfloat          vertices[2],colors[3];
    792:   PetscErrorCode   ierr;
    793:   GLuint           positionBufferObject;
    794:   GLuint           colorBufferObject;
    795:   GLenum           err;

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

    802:   OpenGLWindow(win);
    803:   glGenBuffers(1, &positionBufferObject);
    804:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
    805:   glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
    806:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
    807:   glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    808:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
    809:   glEnableVertexAttribArray(0);
    810:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
    811:   glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
    812:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);

    814:   glGenBuffers(1, &colorBufferObject);
    815:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
    816:   glBindBuffer(GL_ARRAY_BUFFER, colorBufferObject);
    817:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
    818:   glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
    819:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
    820:   glEnableVertexAttribArray(1);
    821:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
    822:   glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
    823:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);

    825:   glDrawArrays(GL_POINTS, 0, 2);
    826:   glDisableVertexAttribArray(0);
    827:   glDisableVertexAttribArray(1);
    828:   glDeleteBuffers(1, &positionBufferObject);
    829:   glDeleteBuffers(1, &colorBufferObject);
    830:   return(0);
    831: }

    835: static PetscErrorCode PetscDrawLine_OpenGL(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int cl)
    836: {
    837:   PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
    838:   GLfloat          linevertices[4],colors[6];
    839:   PetscErrorCode   ierr;
    840:   GLenum           err;
    841:   GLuint           positionBufferObject;
    842:   GLuint           colorBufferObject;

    846:   linevertices[0] = XTRANS(draw,xl);
    847:   linevertices[2] = XTRANS(draw,xr);
    848:   linevertices[1] = YTRANS(draw,yl);
    849:   linevertices[3] = YTRANS(draw,yr);
    850:   if (linevertices[0] == linevertices[2] && linevertices[1] == linevertices[3]) return(0);
    851:   colors[0] = rcolor[cl]/255.0;  colors[1] = gcolor[cl]/255.0; colors[2] = bcolor[cl]/255.0;
    852:   colors[3] = rcolor[cl]/255.0;  colors[4] = gcolor[cl]/255.0; colors[5] = bcolor[cl]/255.0;

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

    867:   glGenBuffers(1, &colorBufferObject);
    868:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
    869:   glBindBuffer(GL_ARRAY_BUFFER, colorBufferObject);
    870:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
    871:   glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
    872:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
    873:   glEnableVertexAttribArray(1);
    874:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
    875:   glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
    876:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);

    878:   glDrawArrays(GL_LINES, 0, 2);
    879:   glDisableVertexAttribArray(0);
    880:   glDisableVertexAttribArray(1);
    881:   glDeleteBuffers(1, &positionBufferObject);
    882:   glDeleteBuffers(1, &colorBufferObject);
    883:   return(0);
    884: }

    888: static PetscErrorCode PetscDrawTriangle_OpenGL(PetscDraw draw,PetscReal X1,PetscReal Y_1,PetscReal X2,PetscReal Y2,PetscReal X3,PetscReal Y3,int c1,int c2,int c3)
    889: {
    890:   PetscDraw_OpenGL *win = (PetscDraw_OpenGL*)draw->data;
    891:   PetscErrorCode   ierr;
    892:   GLfloat          vertices[6],colors[9];
    893:   GLenum           err;
    894:   GLuint           positionBufferObject;
    895:   GLuint           colorBufferObject;

    898:   vertices[0] = XTRANS(draw,X1);
    899:   vertices[1] = YTRANS(draw,Y_1);
    900:   vertices[2] = XTRANS(draw,X2);
    901:   vertices[3] = YTRANS(draw,Y2);
    902:   vertices[4] = XTRANS(draw,X3);
    903:   vertices[5] = YTRANS(draw,Y3);
    904:   colors[0]   = rcolor[c1]/255.0;  colors[1] = gcolor[c1]/255.0; colors[2] = bcolor[c1]/255.0;
    905:   colors[3]   = rcolor[c2]/255.0;  colors[4] = gcolor[c2]/255.0; colors[5] = bcolor[c2]/255.0;
    906:   colors[6]   = rcolor[c3]/255.0;  colors[7] = gcolor[c3]/255.0; colors[8] = bcolor[c3]/255.0;

    908:   OpenGLWindow(win);
    909:   glGenBuffers(1, &positionBufferObject);
    910:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
    911:   glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
    912:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
    913:   glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    914:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
    915:   glEnableVertexAttribArray(0);
    916:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
    917:   glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
    918:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);

    920:   glGenBuffers(1, &colorBufferObject);
    921:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
    922:   glBindBuffer(GL_ARRAY_BUFFER, colorBufferObject);
    923:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
    924:   glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
    925:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
    926:   glEnableVertexAttribArray(1);
    927:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
    928:   glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
    929:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);

    931:   glDrawArrays(GL_TRIANGLES, 0, 3);
    932:   glDisableVertexAttribArray(0);
    933:   glDisableVertexAttribArray(1);
    934:   glDeleteBuffers(1, &positionBufferObject);
    935:   glDeleteBuffers(1, &colorBufferObject);
    936:   return(0);
    937: }

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

    952:   x1  = XTRANS(draw,Xl);
    953:   y_1 = YTRANS(draw,Yl);
    954:   x2  = XTRANS(draw,Xr);
    955:   y2  = YTRANS(draw,Yr);

    957:   OpenGLWindow(win);

    959:   vertices[0] = x1; colors[0] = rcolor[c1]/255.0;  colors[1] = gcolor[c1]/255.0; colors[2] = bcolor[c1]/255.0;
    960:   vertices[1] = y_1;
    961:   vertices[2] = x2;colors[3] = rcolor[c2]/255.0;  colors[4] = gcolor[c2]/255.0; colors[5] = bcolor[c2]/255.0;
    962:   vertices[3] = y_1;
    963:   vertices[4] = x1;colors[6] = rcolor[c4]/255.0;  colors[7] = gcolor[c4]/255.0; colors[8] = bcolor[c4]/255.0;
    964:   vertices[5] = y2;

    966:   vertices[6]  = x1;colors[9] = rcolor[c4]/255.0;  colors[10] = gcolor[c4]/255.0; colors[11] = bcolor[c4]/255.0;
    967:   vertices[7]  = y2;
    968:   vertices[8]  = x2;colors[12] = rcolor[c3]/255.0;  colors[13] = gcolor[c3]/255.0; colors[14] = bcolor[c3]/255.0;
    969:   vertices[9]  = y2;
    970:   vertices[10] = x2;colors[15] = rcolor[c2]/255.0;  colors[16] = gcolor[c2]/255.0; colors[17] = bcolor[c2]/255.0;
    971:   vertices[11] = y_1;

    973:   glGenBuffers(1, &positionBufferObject);
    974:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
    975:   glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
    976:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
    977:   glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    978:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
    979:   glEnableVertexAttribArray(0);
    980:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
    981:   glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
    982:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);

    984:   glGenBuffers(1, &colorBufferObject);
    985:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
    986:   glBindBuffer(GL_ARRAY_BUFFER, colorBufferObject);
    987:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
    988:   glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
    989:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
    990:   glEnableVertexAttribArray(1);
    991:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);
    992:   glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
    993:   err = glGetError(); if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"OpenGL error %d\n",err);

    995:   glDrawArrays(GL_TRIANGLES, 0, 6);
    996:   glDisableVertexAttribArray(0);
    997:   glDisableVertexAttribArray(1);
    998:   glDeleteBuffers(1, &positionBufferObject);
    999:   glDeleteBuffers(1, &colorBufferObject);
    1000:   return(0);
    1001: }

    1006: static PetscErrorCode PetscDrawPause_OpenGL(PetscDraw draw)
    1007: {

    1011:   if (draw->pause > 0) PetscSleep(draw->pause);
    1012:   else if (draw->pause == -1) {
    1013:     PetscDrawButton button;
    1014:     PetscMPIInt     rank;
    1015:     MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);
    1016:     if (!rank) {
    1017:       PetscDrawGetMouseButton(draw,&button,0,0,0,0);
    1018:       if (button == PETSC_BUTTON_CENTER) draw->pause = 0;
    1019:     }
    1020:     MPI_Bcast(&draw->pause,1,MPI_INT,0,PetscObjectComm((PetscObject)draw));
    1021:   }
    1022:   return(0);
    1023: }

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

    1061: #if defined(PETSC_HAVE_GLUT)
    1062: /* callbacks required by GLUT */
    1063: static void display(void) {;}
    1064: static void reshape(int width, int height)
    1065: {
    1066:   glViewport(0, 0, width, height);
    1067:   resized = PETSC_TRUE;
    1068: }
    1069: static void mouse(int button, int state,int x, int y)
    1070: {
    1071:   if (state == GLUT_UP) {
    1072:     Mouse.button = button;
    1073:     Mouse.x      = x;
    1074:     Mouse.y      = y;
    1075:   }
    1076: }

    1080: PETSC_EXTERN PetscErrorCode PetscDrawCreate_GLUT(PetscDraw draw)
    1081: {
    1082:   PetscDraw_OpenGL *win;
    1083:   PetscErrorCode   ierr;
    1084:   PetscInt         xywh[4],osize = 4;
    1085:   int              x = draw->x,y = draw->y,w = draw->w,h = draw->h;
    1086:   static int       xavailable = 0,yavailable = 0,xmax = 0,ymax = 0,ybottom = 0;
    1087:   static PetscBool initialized = PETSC_FALSE;
    1088:   int              argc;
    1089:   char             **argv;

    1092:   if (!initialized) {
    1093:     PetscGetArgs(&argc,&argv);
    1094:     glutInit(&argc, argv);
    1095:     glutInitDisplayMode(GLUT_RGBA /* | GLUT_DOUBLE */| GLUT_DEPTH);
    1096:     InitializeColors();
    1097:   }

    1099:   /*
    1100:       Initialize the display size
    1101:   */
    1102:   if (!xmax) {
    1103:     xmax = glutGet(GLUT_SCREEN_WIDTH);
    1104:     ymax = glutGet(GLUT_SCREEN_HEIGHT);
    1105:   }

    1107:   if (w == PETSC_DECIDE) w = draw->w = 300;
    1108:   if (h == PETSC_DECIDE) h = draw->h = 300;
    1109:   switch (w) {
    1110:   case PETSC_DRAW_FULL_SIZE: w = draw->w = xmax - 10; break;
    1111:   case PETSC_DRAW_HALF_SIZE: w = draw->w = (xmax - 20)/2; break;
    1112:   case PETSC_DRAW_THIRD_SIZE: w = draw->w = (xmax - 30)/3; break;
    1113:   case PETSC_DRAW_QUARTER_SIZE: w = draw->w = (xmax - 40)/4; break;
    1114:   }
    1115:   switch (h) {
    1116:   case PETSC_DRAW_FULL_SIZE: h = draw->h = ymax - 10; break;
    1117:   case PETSC_DRAW_HALF_SIZE: h = draw->h = (ymax - 20)/2; break;
    1118:   case PETSC_DRAW_THIRD_SIZE: h = draw->h = (ymax - 30)/3; break;
    1119:   case PETSC_DRAW_QUARTER_SIZE: h = draw->h = (ymax - 40)/4; break;
    1120:   }

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

    1128:   if (draw->x == PETSC_DECIDE || draw->y == PETSC_DECIDE) {
    1129:     /*
    1130:        PETSc tries to place windows starting in the upper left corner and
    1131:        moving across to the right.

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

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

    1171:   /* actually create and open the window */
    1172:   PetscNew(PetscDraw_OpenGL,&win);
    1173:   PetscLogObjectMemory(draw,sizeof(PetscDraw_OpenGL));

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

    1178:   win->x = x;
    1179:   win->y = y;
    1180:   win->w = w;
    1181:   win->h = h;

    1183:   glutInitWindowSize(w, h);
    1184:   glutInitWindowPosition(x,y);
    1185:   win->win = glutCreateWindow(draw->title);
    1186:   glutDisplayFunc(display);
    1187:   glutReshapeFunc(reshape);
    1188:   Mouse.button = -1;
    1189:   Mouse.x      = -1;
    1190:   Mouse.y      = -1;
    1191:   glutMouseFunc(mouse);

    1193:   glClearColor(1.0,1.0,1.0,1.0);

    1195:   draw->data = win;
    1196:   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    1197:   InitializeShader();

    1199:   PetscDrawClear(draw);
    1200:   resized = PETSC_FALSE; /* opening the window triggers OpenGL call to reshape so need to cancel that resized flag */
    1201:   glutCheckLoop();
    1202:   return(0);
    1203: }

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

    1210:    Collective on MPI_Comm

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

    1222:    Output Parameters:
    1223: .  draw - the drawing context.

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

    1231:    Level: beginner

    1233:    Note:
    1234:    When finished with the drawing context, it should be destroyed
    1235:    with PetscDrawDestroy().

    1237:    Note for Fortran Programmers:
    1238:    Whenever indicating null character data in a Fortran code,
    1239:    NULL_CHARACTER must be employed; using NULL is not
    1240:    correct for character data!  Thus, NULL_CHARACTER can be
    1241:    used for the display and title input parameters.

    1243:    Concepts: OpenGL^drawing to

    1245: .seealso: PetscDrawSynchronizedFlush(), PetscDrawDestroy(), PetscDrawOpenX(), PetscDrawCreate()
    1246: @*/
    1247: PetscErrorCode  PetscDrawOpenGLUT(MPI_Comm comm,const char display[],const char title[],int x,int y,int w,int h,PetscDraw *draw)
    1248: {

    1252:   PetscDrawCreate(comm,display,title,x,y,w,h,draw);
    1253:   PetscDrawSetType(*draw,PETSC_DRAW_GLUT);
    1254:   return(0);
    1255: }

    1257: #elif defined(PETSC_HAVE_OPENGLES)

    1261: PetscErrorCode  PetscDrawOpenGLESRegisterGLKView(GLKView *view)
    1262: {
    1263:   PetscInt i;

    1266:   for (i=0; i<10; i++) {
    1267:     if (view == globalGLKView[i]) return(0);  /* already registered */
    1268:     if (!globalGLKView[i]) {
    1269:       globalGLKView[i] = view;
    1270:       return(0);
    1271:     }
    1272:   }
    1273:   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Out of GLKView slots");
    1274:   return(0);
    1275: }

    1279: PETSC_EXTERN PetscErrorCode PetscDrawCreate_OpenGLES(PetscDraw draw)
    1280: {
    1281:   PetscDraw_OpenGL *win;
    1282:   PetscErrorCode   ierr;
    1283:   static PetscBool initialized = PETSC_FALSE;
    1284:   PetscInt         i;

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

    1289:   PetscMemcpy(draw->ops,&DvOps,sizeof(DvOps));
    1290:   PetscNew(PetscDraw_OpenGL,&win);
    1291:   PetscLogObjectMemory(draw,sizeof(PetscDraw_OpenGL));

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

    1306:   if (!initialized) {
    1307:     initialized = PETSC_TRUE;
    1308:     InitializeColors();
    1309:   }
    1310:   InitializeShader();

    1312:   PetscDrawClear(draw);
    1313:   NSLog(@"Ending PetscDrawCreate_OpenGLES()");
    1314:   return(0);
    1315: }

    1317: #endif