1 /*
   2  * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #include <jni.h>
  27 #include <stdlib.h>
  28 #include <assert.h>
  29 #include <stdio.h>
  30 #include <string.h>
  31 #include <math.h>
  32 
  33 #include "PrismES2Defs.h"
  34 
  35 extern char *strJavaToC(JNIEnv *env, jstring str);
  36 
  37 void printGLError(GLenum errCode) {
  38     char const glCString[] = "*** GLError Code = ";
  39     switch (errCode) {
  40         case GL_NO_ERROR:
  41             //fprintf(stderr, "%sGL_NO_ERROR\n", glCString);
  42             break;
  43         case GL_INVALID_ENUM:
  44             fprintf(stderr, "%sGL_INVALID_ENUM\n", glCString);
  45             break;
  46         case GL_INVALID_VALUE:
  47             fprintf(stderr, "%sGL_INVALID_VALUE\n", glCString);
  48             break;
  49         case GL_INVALID_OPERATION:
  50             fprintf(stderr, "%sGL_INVALID_OPERATION\n", glCString);
  51             break;
  52         case GL_STACK_OVERFLOW:
  53             fprintf(stderr, "%sGL_STACK_OVERFLOW\n", glCString);
  54             break;
  55         case GL_STACK_UNDERFLOW:
  56             fprintf(stderr, "%sGL_STACK_UNDERFLOW\n", glCString);
  57             break;
  58         case GL_OUT_OF_MEMORY:
  59             fprintf(stderr, "%sGL_OUT_OF_MEMORY\n", glCString);
  60             break;
  61         default:
  62             fprintf(stderr, "%s*** UNKNOWN ERROR CODE ***\n", glCString);
  63     }
  64 }
  65 
  66 void initializeCtxInfo(ContextInfo *ctxInfo) {
  67     if (ctxInfo == NULL) {
  68         return;
  69     }
  70     // Initialize structure to all zeros
  71     memset(ctxInfo, 0, sizeof (ContextInfo));
  72 }
  73 
  74 void deleteCtxInfo(ContextInfo *ctxInfo) {
  75     if (ctxInfo == NULL) {
  76         return;
  77     }
  78 
  79     if (ctxInfo->versionStr != NULL) {
  80         free(ctxInfo->versionStr);
  81     }
  82     if (ctxInfo->vendorStr != NULL) {
  83         free(ctxInfo->vendorStr);
  84     }
  85     if (ctxInfo->rendererStr != NULL) {
  86         free(ctxInfo->rendererStr);
  87     }
  88     if (ctxInfo->glExtensionStr != NULL) {
  89         free(ctxInfo->glExtensionStr);
  90     }
  91 
  92 #ifdef WIN32 /* WIN32 */
  93     if (ctxInfo->wglExtensionStr != NULL) {
  94         free(ctxInfo->wglExtensionStr);
  95     }
  96     if (ctxInfo->hglrc != NULL) {
  97         wglDeleteContext(ctxInfo->hglrc);
  98         ctxInfo->hglrc = NULL;
  99     }
 100 #endif
 101 
 102 #ifdef UNIX
 103     if (ctxInfo->glxExtensionStr != NULL) {
 104         free(ctxInfo->glxExtensionStr);
 105     }
 106     if (ctxInfo->context != NULL) {
 107 #if defined(IS_GLX)
 108         glXDestroyContext(ctxInfo->display, ctxInfo->context);
 109 #endif
 110 #ifdef IS_EGL
 111         eglDestroyContext(ctxInfo->display, ctxInfo->context);
 112 #endif
 113     }
 114 #endif
 115     // Initialize structure to all zeros
 116     memset(ctxInfo, 0, sizeof (ContextInfo));
 117 }
 118 
 119 void initState(ContextInfo *ctxInfo) {
 120     if (ctxInfo == NULL) {
 121         return;
 122     }
 123 
 124     glEnable(GL_BLEND);
 125     glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
 126 
 127     // initialize states and properties to
 128     // match cached states and properties
 129 
 130     // depthtest is set to false
 131     // Note: This state is cached in GLContext.java
 132     ctxInfo->state.depthWritesEnabled = JNI_FALSE;
 133     glDepthMask(ctxInfo->state.depthWritesEnabled);
 134     glDisable(GL_DEPTH_TEST);
 135 #ifndef IS_EGL
 136     glDisable(GL_ALPHA_TEST);
 137 #endif
 138 
 139     if (ctxInfo->state.scissorEnabled) {
 140         ctxInfo->state.scissorEnabled = JNI_FALSE;
 141         glDisable(GL_SCISSOR_TEST);
 142     }
 143 
 144     ctxInfo->state.clearColor[0] = 0.0;
 145     ctxInfo->state.clearColor[1] = 0.0;
 146     ctxInfo->state.clearColor[2] = 0.0;
 147     ctxInfo->state.clearColor[3] = 0.0;
 148     glClearColor(ctxInfo->state.clearColor[0], ctxInfo->state.clearColor[1],
 149             ctxInfo->state.clearColor[2], ctxInfo->state.clearColor[3]);
 150 
 151     ctxInfo->vbFloatData = NULL;
 152     ctxInfo->vbByteData = NULL;
 153     ctxInfo->state.fillMode = GL_FILL;
 154     ctxInfo->state.cullEnable = JNI_FALSE;
 155     ctxInfo->state.cullMode = GL_BACK;
 156     ctxInfo->state.fbo = 0;    
 157 }
 158 
 159 void clearBuffers(ContextInfo *ctxInfo,
 160         GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha,
 161         jboolean clearColor, jboolean clearDepth, jboolean ignoreScissor) {
 162     GLbitfield clearBIT = 0;
 163 
 164     if (ctxInfo == NULL) {
 165         return;
 166     }
 167 
 168     if (ignoreScissor && ctxInfo->state.scissorEnabled) {
 169         // glClear() honors the current scissor, so disable it
 170         // temporarily if ignoreScissor is true
 171         glDisable(GL_SCISSOR_TEST);
 172     }
 173 
 174     if (clearColor) {
 175         clearBIT = GL_COLOR_BUFFER_BIT;
 176         if ((ctxInfo->state.clearColor[0] != red)
 177                 || (ctxInfo->state.clearColor[1] != green)
 178                 || (ctxInfo->state.clearColor[2] != blue)
 179                 || (ctxInfo->state.clearColor[3] != alpha)) {
 180             glClearColor(red, green, blue, alpha);
 181             ctxInfo->state.clearColor[0] = red;
 182             ctxInfo->state.clearColor[1] = green;
 183             ctxInfo->state.clearColor[2] = blue;
 184             ctxInfo->state.clearColor[3] = alpha;
 185         }
 186     }
 187 
 188     if (clearDepth) {
 189         clearBIT |= GL_DEPTH_BUFFER_BIT;
 190         // also make sure depth writes are enabled for the clear operation
 191         if (!ctxInfo->state.depthWritesEnabled) {
 192             glDepthMask(GL_TRUE);
 193         }
 194         glClear(clearBIT);
 195         if (!ctxInfo->state.depthWritesEnabled) {
 196             glDepthMask(GL_FALSE);
 197         }
 198     } else {
 199         glClear(clearBIT);
 200     }
 201 
 202     // restore previous state
 203     if (ignoreScissor && ctxInfo->state.scissorEnabled) {
 204         glEnable(GL_SCISSOR_TEST);
 205     }
 206 }
 207 
 208 void bindFBO(ContextInfo *ctxInfo, GLuint fboId) {
 209     if ((ctxInfo == NULL) || (ctxInfo->glBindFramebuffer == NULL)) {
 210         return;
 211     }
 212     ctxInfo->glBindFramebuffer(GL_FRAMEBUFFER, fboId);
 213     ctxInfo->state.fbo = fboId;
 214 }
 215 
 216 /*
 217  * Class:     com_sun_prism_es2_GLContext
 218  * Method:    nActiveTexture
 219  * Signature: (JI)V
 220  */
 221 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nActiveTexture
 222 (JNIEnv *env, jclass class, jlong nativeCtxInfo, jint texUnit) {
 223     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
 224     if ((ctxInfo == NULL) || (ctxInfo->glActiveTexture == NULL)) {
 225         return;
 226     }
 227     ctxInfo->glActiveTexture(GL_TEXTURE0 + texUnit);
 228 }
 229 
 230 /*
 231  * Class:     com_sun_prism_es2_GLContext
 232  * Method:    nBindFBO
 233  * Signature: (JI)V
 234  */
 235 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nBindFBO
 236 (JNIEnv *env, jclass class, jlong nativeCtxInfo, jint fboId) {
 237     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
 238     bindFBO(ctxInfo, (GLuint)fboId);
 239 }
 240 
 241 /*
 242  * Class:     com_sun_prism_es2_GLContext
 243  * Method:    nBindTexture
 244  * Signature: (JI)V
 245  */
 246 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nBindTexture
 247 (JNIEnv *env, jclass class, jlong nativeCtxInfo, jint texID) {
 248     glBindTexture(GL_TEXTURE_2D, texID);
 249 }
 250 
 251 GLenum translateScaleFactor(jint scaleFactor) {
 252     switch (scaleFactor) {
 253         case com_sun_prism_es2_GLContext_GL_ZERO:
 254             return GL_ZERO;
 255         case com_sun_prism_es2_GLContext_GL_ONE:
 256             return GL_ONE;
 257         case com_sun_prism_es2_GLContext_GL_SRC_COLOR:
 258             return GL_SRC_COLOR;
 259         case com_sun_prism_es2_GLContext_GL_ONE_MINUS_SRC_COLOR:
 260             return GL_ONE_MINUS_SRC_COLOR;
 261         case com_sun_prism_es2_GLContext_GL_DST_COLOR:
 262             return GL_DST_COLOR;
 263         case com_sun_prism_es2_GLContext_GL_ONE_MINUS_DST_COLOR:
 264             return GL_ONE_MINUS_DST_COLOR;
 265         case com_sun_prism_es2_GLContext_GL_SRC_ALPHA:
 266             return GL_SRC_ALPHA;
 267         case com_sun_prism_es2_GLContext_GL_ONE_MINUS_SRC_ALPHA:
 268             return GL_ONE_MINUS_SRC_ALPHA;
 269         case com_sun_prism_es2_GLContext_GL_DST_ALPHA:
 270             return GL_DST_ALPHA;
 271         case com_sun_prism_es2_GLContext_GL_ONE_MINUS_DST_ALPHA:
 272             return GL_ONE_MINUS_DST_ALPHA;
 273         case com_sun_prism_es2_GLContext_GL_CONSTANT_COLOR:
 274             return GL_CONSTANT_COLOR;
 275         case com_sun_prism_es2_GLContext_GL_ONE_MINUS_CONSTANT_COLOR:
 276             return GL_ONE_MINUS_CONSTANT_COLOR;
 277         case com_sun_prism_es2_GLContext_GL_CONSTANT_ALPHA:
 278             return GL_CONSTANT_ALPHA;
 279         case com_sun_prism_es2_GLContext_GL_ONE_MINUS_CONSTANT_ALPHA:
 280             return GL_ONE_MINUS_CONSTANT_ALPHA;
 281         case com_sun_prism_es2_GLContext_GL_SRC_ALPHA_SATURATE:
 282             return GL_SRC_ALPHA_SATURATE;
 283         default:
 284             fprintf(stderr, "Error: Unknown scale factor. Returning GL_ZERO (default)");
 285     }
 286     return GL_ZERO;
 287 }
 288 
 289 /*
 290  * Class:     com_sun_prism_es2_GLContext
 291  * Method:    nBlendFunc
 292  * Signature: (II)V
 293  */
 294 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nBlendFunc
 295 (JNIEnv *env, jclass class, jint sFactor, jint dFactor) {
 296     glBlendFunc(translateScaleFactor(sFactor), translateScaleFactor(dFactor));
 297 }
 298 
 299 /*
 300  * Class:     com_sun_prism_es2_GLContext
 301  * Method:    nClearBuffers
 302  * Signature: (JFFFFZZZ)V
 303  */
 304 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nClearBuffers
 305 (JNIEnv *env, jclass class, jlong nativeCtxInfo,
 306         jfloat red, jfloat green, jfloat blue, jfloat alpha,
 307         jboolean clearColor, jboolean clearDepth, jboolean ignoreScissor) {
 308     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
 309     if (ctxInfo == NULL) {
 310         return;
 311     }
 312 
 313     clearBuffers(ctxInfo,
 314             (GLclampf) red, (GLclampf) green, (GLclampf) blue, (GLclampf) alpha,
 315             clearColor, clearDepth, ignoreScissor);
 316 }
 317 
 318 int checkFramebufferStatus(ContextInfo *ctxInfo) {
 319     GLenum status;
 320     status = ctxInfo->glCheckFramebufferStatus(GL_FRAMEBUFFER);
 321     if (status != GL_FRAMEBUFFER_COMPLETE) {
 322         switch(status) {
 323             case GL_FRAMEBUFFER_COMPLETE:
 324                 return GL_FALSE;
 325                 break;
 326             case GL_FRAMEBUFFER_UNSUPPORTED:
 327             //Choose different formats
 328                 fprintf(stderr, "Framebuffer object format is unsupported by the video hardware. (GL_FRAMEBUFFER_UNSUPPORTED)(FBO - 820)\n");
 329                 break;
 330             case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
 331                 fprintf(stderr, "Incomplete attachment. (GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)(FBO - 820)\n");
 332                 break;
 333             case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
 334                 fprintf(stderr, "Incomplete missing attachment. (GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)(FBO - 820)\n");
 335                 break;
 336             case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
 337                 fprintf(stderr, "Incomplete dimensions. (GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT)(FBO - 820)\n");
 338                 break;
 339             case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
 340                 fprintf(stderr, "Incomplete formats. (GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT)(FBO - 820)\n");
 341                 break;
 342             case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
 343                 fprintf(stderr, "Incomplete draw buffer. (GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER)(FBO - 820)\n");
 344                 break; 
 345             case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
 346                 fprintf(stderr, "Incomplete read buffer. (GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER)(FBO - 820)\n");
 347                 break;
 348             case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
 349                 fprintf(stderr, "Incomplete multisample buffer. (GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE)(FBO - 820)\n");
 350                 break;
 351             default:
 352                 //Programming error; will fail on all hardware
 353                 fprintf(stderr, "Some video driver error or programming error occurred. Framebuffer object status is invalid. (FBO - 823)\n");
 354                 break;
 355         }
 356         return GL_TRUE;
 357     }
 358     return GL_FALSE;
 359 }
 360 
 361 /*
 362  * Class:     com_sun_prism_es2_GLContext
 363  * Method:    nBlit
 364  * Signature: (JIIIIIIIIII)V
 365  */
 366 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nBlit
 367 (JNIEnv *env, jclass class, jlong nativeCtxInfo, jint srcFBO, jint dstFBO,
 368             jint jsrcX0, jint jsrcY0, jint srcX1, jint srcY1,
 369             jint jdstX0, jint jdstY0, jint dstX1, jint dstY1) {
 370     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
 371     if ((ctxInfo == NULL) || (ctxInfo->glGenFramebuffers == NULL)
 372             || (ctxInfo->glBindFramebuffer == NULL)
 373             || (ctxInfo->glBlitFramebuffer == NULL)) {
 374         return;
 375     }
 376 
 377     if (dstFBO == 0) {
 378         dstFBO = ctxInfo->state.fbo;
 379     }
 380     //Bind the FBOs
 381     ctxInfo->glBindFramebuffer(GL_READ_FRAMEBUFFER, (GLuint)srcFBO);
 382     ctxInfo->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint)dstFBO);
 383     ctxInfo->glBlitFramebuffer(jsrcX0, jsrcY0, srcX1, srcY1,
 384                                jdstX0, jdstY0, dstX1, dstY1,
 385                                GL_COLOR_BUFFER_BIT, GL_NEAREST);
 386     /* TODO: iOS MSAA support:
 387      * We are using glBlitFramebuffer to "resolve" the mutlisample buffer,
 388      * to a color destination. iOS does things differently, it uses
 389      * glResolveMultisampleFramebufferAPPLE() in place of glBlit...
 390      * Problem is glResolve.. does not take arguments so we can't flip
 391      * coordinate system.
 392      */
 393 
 394     // Restore previous FBO
 395     ctxInfo->glBindFramebuffer(GL_FRAMEBUFFER, ctxInfo->state.fbo);
 396 }
 397 
 398 GLuint attachRenderbuffer(ContextInfo *ctxInfo, GLuint rbID, GLenum attachment) {
 399     //GLenum status;
 400     ctxInfo->glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment,
 401             GL_RENDERBUFFER, rbID);
 402     ctxInfo->glBindRenderbuffer(GL_RENDERBUFFER, 0);
 403     //status = ctxInfo->glCheckFramebufferStatus(GL_FRAMEBUFFER);
 404     if (checkFramebufferStatus(ctxInfo)) {
 405         ctxInfo->glDeleteRenderbuffers(1, &rbID);
 406         rbID = 0;
 407         fprintf(stderr, "Error creating render buffer object %d\n", rbID);
 408     } else {
 409         // explicitly clear the render buffers, since it may contain
 410         // garbage after initialization
 411         clearBuffers(ctxInfo, 0, 0, 0, 0, JNI_FALSE, JNI_TRUE, JNI_TRUE);
 412     }
 413     return rbID;
 414 }
 415 
 416 GLuint createAndAttachRenderBuffer(ContextInfo *ctxInfo, GLsizei width, GLsizei height, GLsizei msaa, GLenum attachment) {
 417     GLuint rbID;
 418     GLenum internalFormat;
 419 
 420     if ((ctxInfo == NULL) || (ctxInfo->glGenRenderbuffers == NULL)
 421             || (ctxInfo->glBindRenderbuffer == NULL)
 422             || (ctxInfo->glRenderbufferStorage == NULL)
 423             || (ctxInfo->glFramebufferRenderbuffer == NULL)
 424 #ifndef IS_EGL
 425             || (ctxInfo->glRenderbufferStorageMultisample == NULL)
 426 #endif
 427             || (ctxInfo->glCheckFramebufferStatus == NULL)
 428             || (ctxInfo->glDeleteRenderbuffers == NULL)) {
 429         return 0;
 430     }
 431 
 432     if (attachment == GL_DEPTH_ATTACHMENT) {
 433 #ifdef IS_EGL
 434         internalFormat = GL_DEPTH_COMPONENT16;
 435 #else
 436         internalFormat = GL_DEPTH_COMPONENT;
 437 #endif
 438     } else {
 439         internalFormat = GL_RGBA8; //TODO verify format on RGBA or RGBA8
 440     }
 441     // create a depth buffer
 442     ctxInfo->glGenRenderbuffers(1, &rbID);
 443     ctxInfo->glBindRenderbuffer(GL_RENDERBUFFER, rbID);
 444 #ifdef IS_EGL
 445     ctxInfo->glRenderbufferStorage(GL_RENDERBUFFER, internalFormat, width, height);
 446 #else
 447     if (msaa) {
 448         ctxInfo->glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, internalFormat, width, height);
 449     } else {
 450         ctxInfo->glRenderbufferStorage(GL_RENDERBUFFER, internalFormat, width, height);
 451     }
 452 #endif
 453     return attachRenderbuffer(ctxInfo, rbID, attachment);
 454 }
 455 
 456 /*
 457  * Class:     com_sun_prism_es2_GLContext
 458  * Method:    nCreateDepthBuffer
 459  * Signature: (JIII)I
 460  */
 461 JNIEXPORT jint JNICALL Java_com_sun_prism_es2_GLContext_nCreateDepthBuffer
 462 (JNIEnv *env, jclass class, jlong nativeCtxInfo, jint width, jint height, jint msaa) {
 463     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
 464     return createAndAttachRenderBuffer(ctxInfo, width, height, msaa, GL_DEPTH_ATTACHMENT);
 465 }
 466 
 467 /*
 468  * Class:     com_sun_prism_es2_GLContext
 469  * Method:    nCreateRenderBuffer
 470  * Signature: (JIII)I
 471  */
 472 JNIEXPORT jint JNICALL Java_com_sun_prism_es2_GLContext_nCreateRenderBuffer
 473 (JNIEnv *env, jclass class, jlong nativeCtxInfo, jint width, jint height, jint msaa) {
 474     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
 475     return createAndAttachRenderBuffer(ctxInfo, width, height, msaa, GL_COLOR_ATTACHMENT0);
 476 }
 477 
 478 /*
 479  * Class:     com_sun_prism_es2_GLContext
 480  * Method:    nCreateFBO
 481  * Signature: (JI)I
 482  */
 483 JNIEXPORT jint JNICALL Java_com_sun_prism_es2_GLContext_nCreateFBO
 484 (JNIEnv *env, jclass class, jlong nativeCtxInfo, jint texID) {
 485     GLuint fboID;
 486 
 487     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
 488     if ((ctxInfo == NULL) || (ctxInfo->glGenFramebuffers == NULL)
 489             || (ctxInfo->glFramebufferTexture2D == NULL)
 490             || (ctxInfo->glCheckFramebufferStatus == NULL)
 491             || (ctxInfo->glDeleteFramebuffers == NULL)) {
 492         return 0;
 493     }
 494 
 495     // initialize framebuffer object
 496     ctxInfo->glGenFramebuffers(1, &fboID);
 497     bindFBO(ctxInfo, fboID);
 498 
 499     if (texID) {
 500         // Attach color texture to framebuffer object
 501         ctxInfo->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
 502                                         GL_TEXTURE_2D, (GLuint)texID, 0);
 503         // Can't check status of FBO until after a buffer is attached to it
 504         if (checkFramebufferStatus(ctxInfo)) {
 505             ctxInfo->glDeleteFramebuffers(1, &fboID);
 506             fprintf(stderr,
 507                     "Error creating framebuffer object with TexID %d)\n", (int) texID);
 508             return 0;
 509         }
 510         // explicitly clear the color buffer, since it may contain garbage
 511         // after initialization
 512         clearBuffers(ctxInfo, 0, 0, 0, 0, JNI_TRUE, JNI_FALSE, JNI_TRUE);
 513     }
 514 
 515     return (jint)fboID;
 516 }
 517 
 518 /*
 519  * Class:     com_sun_prism_es2_GLContext
 520  * Method:    nCreateProgram
 521  * Signature: (JI[II[Ljava/lang/String;[I)I
 522  */
 523 JNIEXPORT jint JNICALL Java_com_sun_prism_es2_GLContext_nCreateProgram
 524 (JNIEnv *env, jclass class, jlong nativeCtxInfo, jint vertID, jintArray fragIDArr,
 525         jint numAttrs, jobjectArray attrs, jintArray indexs) {
 526     GLuint shaderProgram;
 527     int success, status, i;
 528     jstring attrName;
 529     jint *indexsPtr;
 530     char *attrNameString;
 531     jboolean valid;
 532     jint *fragIDs;
 533     jsize length;
 534     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
 535     if ((ctxInfo == NULL) || (attrs == NULL) || (indexs == NULL)
 536             || (ctxInfo->glCreateProgram == NULL)
 537             || (ctxInfo->glAttachShader == NULL)
 538             || (ctxInfo->glBindAttribLocation == NULL)
 539             || (ctxInfo->glLinkProgram == NULL)
 540             || (ctxInfo->glGetProgramiv == NULL)
 541             || (ctxInfo->glValidateProgram == NULL)
 542             || (ctxInfo->glDetachShader == NULL)
 543             || (ctxInfo->glDeleteShader == NULL)
 544             || (ctxInfo->glDeleteProgram == NULL)) {
 545         return 0;
 546     }
 547 
 548     if (fragIDArr != NULL) {
 549         length = (*env)->GetArrayLength(env, fragIDArr);
 550         fragIDs = (*env)->GetIntArrayElements(env, fragIDArr, NULL);
 551     } else {
 552         return 0;
 553     }
 554     // create the program object and attach it to the shader
 555     shaderProgram = ctxInfo->glCreateProgram();
 556     ctxInfo->glAttachShader(shaderProgram, vertID);
 557     for (i = 0; i < length; i++) {
 558         ctxInfo->glAttachShader(shaderProgram, fragIDs[i]);
 559     }
 560 
 561     // bind any user-defined index values to their corresponding names
 562     indexsPtr = (*env)->GetIntArrayElements(env, indexs, NULL);
 563     for (i = 0; i < numAttrs; i++) {
 564         attrName = (*env)->GetObjectArrayElement(env, attrs, i);
 565         attrNameString = strJavaToC(env, attrName);
 566         ctxInfo->glBindAttribLocation(shaderProgram, indexsPtr[i], attrNameString);
 567         free(attrNameString);
 568     }
 569 
 570     // link the program
 571     ctxInfo->glLinkProgram(shaderProgram);
 572     ctxInfo->glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
 573 
 574     if (success == GL_FALSE) {
 575         GLint  length;
 576 
 577         valid = JNI_FALSE;
 578         ctxInfo->glGetProgramiv(shaderProgram, GL_INFO_LOG_LENGTH , &length );
 579         if (length) {
 580             char* msg  =  (char *) malloc((length * sizeof(char)));
 581             ctxInfo->glGetProgramInfoLog ( shaderProgram , length , NULL , msg );
 582             printf("Program link log: %s\n",msg);
 583             free(msg);
 584         }
 585     } else {
 586         ctxInfo->glValidateProgram(shaderProgram);
 587         ctxInfo->glGetProgramiv(shaderProgram, GL_VALIDATE_STATUS, &status);
 588         if (status == GL_FALSE) {
 589             GLint  length;
 590             valid = JNI_FALSE;
 591             fprintf(stderr, "Program validation failed\n");
 592             ctxInfo->glGetProgramiv(shaderProgram, GL_INFO_LOG_LENGTH , &length );
 593             if (length) {
 594                 char* msg  =  (char *) malloc((length * sizeof(char)));
 595                 ctxInfo->glGetProgramInfoLog ( shaderProgram , length , NULL , msg );
 596                 fprintf(stderr, "Program validation log: %s\n", msg);
 597                 fflush(stderr);
 598                 free(msg);
 599             }
 600         } else {
 601             valid = JNI_TRUE;
 602         }
 603     }
 604 #ifdef ANDROID_NDK
 605     valid = JNI_TRUE;
 606 #endif
 607     if (!valid) {
 608         ctxInfo->glDetachShader(shaderProgram, vertID);
 609         ctxInfo->glDeleteShader(vertID);
 610         for(i = 0; i < length; i++) {
 611             ctxInfo->glDetachShader(shaderProgram, fragIDs[i]);
 612             ctxInfo->glDeleteShader(fragIDs[i]);
 613         }
 614         ctxInfo->glDeleteProgram(shaderProgram);
 615         return 0;
 616     }
 617 
 618     (*env)->ReleaseIntArrayElements(env, fragIDArr, fragIDs, JNI_ABORT);
 619 
 620     return shaderProgram;
 621 }
 622 
 623 /*
 624  * Class:     com_sun_prism_es2_GLContext
 625  * Method:    nCompileShader
 626  * Signature: (JLjava/lang/String;Z)I
 627  */
 628 JNIEXPORT jint JNICALL Java_com_sun_prism_es2_GLContext_nCompileShader
 629 (JNIEnv *env, jclass class, jlong nativeCtxInfo, jstring src, jboolean vertex) {
 630     GLenum shaderType;
 631     GLuint shaderID;
 632     GLint success;
 633 
 634     /* Null-terminated "C" strings */
 635     GLchar *shaderString = NULL;
 636     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
 637     if ((ctxInfo == NULL) || (src == NULL)
 638             || (ctxInfo->glCreateShader == NULL)
 639             || (ctxInfo->glShaderSource == NULL)
 640             || (ctxInfo->glCompileShader == NULL)
 641             || (ctxInfo->glGetShaderiv == NULL)
 642             || (ctxInfo->glDeleteShader == NULL)) {
 643         return 0;
 644     }
 645 
 646     // create the shader object and compile the shader source code
 647     shaderType = vertex ? GL_VERTEX_SHADER : GL_FRAGMENT_SHADER;
 648     shaderID = ctxInfo->glCreateShader(shaderType);
 649     shaderString = (GLchar *) strJavaToC(env, src);
 650     if (shaderString == NULL) {
 651         /* Just return, since strJavaToC will throw OOM if it returns NULL */
 652         return 0;
 653     }
 654     ctxInfo->glShaderSource(shaderID, 1, (const GLchar **) &shaderString, (GLint *) NULL);
 655     ctxInfo->glCompileShader(shaderID);
 656     ctxInfo->glGetShaderiv(shaderID, GL_COMPILE_STATUS, &success);
 657 
 658     free(shaderString);
 659 
 660     if (success == GL_FALSE) {
 661         GLint  length;
 662         ctxInfo->glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH , &length );
 663         if (length) {
 664             char* msg  =  (char *) malloc((length * sizeof(char)) + 1);
 665             ctxInfo->glGetShaderInfoLog ( shaderID , length , NULL , msg );
 666             printf("Shader compile log: %s\n",msg);
 667             free(msg);
 668         }
 669     }
 670 
 671     if (success == GL_FALSE) {
 672         ctxInfo->glDeleteShader(shaderID);
 673         return 0;
 674     }
 675 
 676     return shaderID;
 677 }
 678 
 679 /*
 680  * Class:     com_sun_prism_es2_GLContext
 681  * Method:    nCreateTexture
 682  * Signature: (JII)I
 683  */
 684 JNIEXPORT jint JNICALL Java_com_sun_prism_es2_GLContext_nCreateTexture
 685 (JNIEnv *env, jclass class, jlong nativeCtxInfo, jint width, jint height) {
 686     GLuint texID = 0;
 687     GLenum err;
 688 
 689     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
 690     if ((ctxInfo == NULL) || (ctxInfo->glActiveTexture == NULL)) {
 691         return 0;
 692     }
 693 
 694     glGenTextures(1, &texID);
 695     if (texID == 0) {
 696         // fprintf(stderr, "nCreateTexture: Failed to generate texture.\n");
 697         return (jint) texID;
 698     }
 699 
 700     glBindTexture(GL_TEXTURE_2D, texID);
 701 
 702     // Reset Error
 703     glGetError();
 704     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height,
 705             0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
 706 
 707     err  = glGetError();
 708     // printGLError(err);
 709 
 710     if (err != GL_NO_ERROR) {
 711         glDeleteTextures(1, &texID);
 712         texID = 0;
 713     } else {
 714         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 715         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 716     }
 717     return (jint) texID;
 718 }
 719 
 720 /*
 721  * Class:     com_sun_prism_es2_GLContext
 722  * Method:    nDisposeShaders
 723  * Signature: (JII[I)V
 724  */
 725 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nDisposeShaders
 726 (JNIEnv *env, jclass class, jlong nativeCtxInfo, jint shaderProgram,
 727         jint vertID, jintArray fragIDArr) {
 728     jsize length;
 729     jint* fragIDs;
 730     int i;
 731     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
 732     if ((ctxInfo == NULL) || (ctxInfo->glDetachShader == NULL)
 733             || (ctxInfo->glDeleteShader == NULL)
 734             || (ctxInfo->glDeleteProgram == NULL)) {
 735         return;
 736     }
 737 
 738     if (vertID != 0) {
 739         ctxInfo->glDetachShader(shaderProgram, vertID);
 740         ctxInfo->glDeleteShader(vertID);
 741     }
 742 
 743     if (fragIDArr == NULL) {
 744         return;
 745     }
 746 
 747     length = (*env)->GetArrayLength(env, fragIDArr);
 748     fragIDs = (*env)->GetIntArrayElements(env, fragIDArr, NULL);
 749 
 750     for (i = 0; i < length; i++) {
 751         if (fragIDs[i] != 0) {
 752             ctxInfo->glDetachShader(shaderProgram, fragIDs[i]);
 753             ctxInfo->glDeleteShader(fragIDs[i]);
 754         }
 755     }
 756 
 757     (*env)->ReleaseIntArrayElements(env, fragIDArr, fragIDs, JNI_ABORT);
 758 
 759     ctxInfo->glDeleteProgram(shaderProgram);
 760 }
 761 
 762 /*
 763  * Class:     com_sun_prism_es2_GLContext
 764  * Method:    nDeleteFBO
 765  * Signature: (JI)V
 766  */
 767 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nDeleteFBO
 768 (JNIEnv *env, jclass class, jlong nativeCtxInfo, jint fboID) {
 769     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
 770     if ((ctxInfo == NULL) || (ctxInfo->glDeleteFramebuffers == NULL)) {
 771         return;
 772     }
 773     if (fboID != 0) {
 774         ctxInfo->glDeleteFramebuffers(1, (GLuint *) &fboID);
 775     }
 776 }
 777 
 778 /*
 779  * Class:     com_sun_prism_es2_GLContext
 780  * Method:    nDeleteRenderBuffer
 781  * Signature: (JI)V
 782  */
 783 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nDeleteRenderBuffer
 784 (JNIEnv *env, jclass class, jlong nativeCtxInfo, jint rbID) {
 785     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
 786     if ((ctxInfo == NULL) || (ctxInfo->glDeleteRenderbuffers == NULL)) {
 787         return;
 788     }
 789     if (rbID != 0) {
 790         ctxInfo->glDeleteRenderbuffers(1, (GLuint *) &rbID);
 791     }
 792 }
 793 
 794 /*
 795  * Class:     com_sun_prism_es2_GLContext
 796  * Method:    nDeleteShader
 797  * Signature: (JI)V
 798  */
 799 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nDeleteShader
 800 (JNIEnv *env, jclass class, jlong nativeCtxInfo, jint shaderID) {
 801     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
 802     if ((ctxInfo == NULL) || (ctxInfo->glDeleteShader == NULL)) {
 803         return;
 804     }
 805     if (shaderID != 0) {
 806         ctxInfo->glDeleteShader(shaderID);
 807     }
 808 }
 809 
 810 /*
 811  * Class:     com_sun_prism_es2_GLContext
 812  * Method:    nDeleteTexture
 813  * Signature: (JI)V
 814  */
 815 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nDeleteTexture
 816 (JNIEnv *env, jclass class, jlong nativeCtxInfo, jint texID) {
 817     GLuint tID = (GLuint) texID;
 818     if (tID != 0) {
 819         glDeleteTextures(1, &tID);
 820     }
 821 }
 822 
 823 /*
 824  * Class:     com_sun_prism_es2_GLContext
 825  * Method:    nFinish
 826  * Signature: ()V
 827  */
 828 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nFinish
 829 (JNIEnv *env, jclass class) {
 830     glFinish();
 831 }
 832 
 833 /*
 834  * Class:     com_sun_prism_es2_GLContext
 835  * Method:    nGenAndBindTexture
 836  * Signature: ()I
 837  */
 838 JNIEXPORT jint JNICALL Java_com_sun_prism_es2_GLContext_nGenAndBindTexture
 839 (JNIEnv *env, jclass class) {
 840     GLuint texID;
 841     glGenTextures(1, &texID);
 842     glBindTexture(GL_TEXTURE_2D, texID);
 843     return texID;
 844 }
 845 
 846 /*
 847  * Class:     com_sun_prism_es2_GLContext
 848  * Method:    nGetFBO
 849  * Signature: ()I
 850  */
 851 JNIEXPORT jint JNICALL Java_com_sun_prism_es2_GLContext_nGetFBO
 852 (JNIEnv *env, jclass class) {
 853     GLint param;
 854     /* The caching logic has been done on Java side if 
 855      * platform isn't MAC or IOS. On these platforms Glass
 856      * can change the FBO under us. We should be able to simplify the
 857      * logic in Java and remove this method once once Glass stop doing it.
 858      */
 859     glGetIntegerv(GL_FRAMEBUFFER_BINDING, &param);
 860     return (jint) param;
 861 }
 862 
 863 /*
 864  * Class:     com_sun_prism_es2_GLContext
 865  * Method:    nGetMaxSampleSize
 866  * Signature: ()I
 867  */
 868 JNIEXPORT jint JNICALL Java_com_sun_prism_es2_GLContext_nGetMaxSampleSize
 869 (JNIEnv *env, jclass class) {
 870     GLint samples;
 871     glGetIntegerv(GL_MAX_SAMPLES, &samples);
 872     return (jint)samples;
 873 }
 874 
 875 /*
 876  * Class:     com_sun_prism_es2_GLContext
 877  * Method:    nGetMaxTextureSize
 878  * Signature: ()I
 879  */
 880 JNIEXPORT jint JNICALL Java_com_sun_prism_es2_GLContext_nGetMaxTextureSize
 881 (JNIEnv *env, jclass class) {
 882     GLint param;
 883     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &param);
 884     return (jint) param;
 885 }
 886 
 887 /*
 888  * Class:     com_sun_prism_es2_GLContext
 889  * Method:    nGetUniformLocation
 890  * Signature: (JILjava/lang/String;)I
 891  */
 892 JNIEXPORT jint JNICALL Java_com_sun_prism_es2_GLContext_nGetUniformLocation
 893 (JNIEnv *env, jclass class, jlong nativeCtxInfo, jint programID, jstring name) {
 894     GLint result;
 895     char *nameString;
 896     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
 897 
 898     if ((ctxInfo == NULL) || (name == NULL)
 899             || (ctxInfo->glGetUniformLocation == NULL)) {
 900         return 0;
 901     }
 902 
 903     nameString = strJavaToC(env, name);
 904     result = ctxInfo->glGetUniformLocation(programID, nameString);
 905     free(nameString);
 906     return result;
 907 }
 908 
 909 int translatePrismToGL(int value) {
 910     switch (value) {
 911         case com_sun_prism_es2_GLContext_GL_FLOAT:
 912             return GL_FLOAT;
 913         case com_sun_prism_es2_GLContext_GL_UNSIGNED_BYTE:
 914             return GL_UNSIGNED_BYTE;
 915         case com_sun_prism_es2_GLContext_GL_UNSIGNED_INT_8_8_8_8_REV:
 916             return GL_UNSIGNED_INT_8_8_8_8_REV;
 917         case com_sun_prism_es2_GLContext_GL_UNSIGNED_INT_8_8_8_8:
 918             return GL_UNSIGNED_INT_8_8_8_8;
 919         case com_sun_prism_es2_GLContext_GL_UNSIGNED_SHORT_8_8_APPLE:
 920             /* not using symbolic name may not be available on all platform - DrD*/
 921             return 0x85BA;
 922 
 923         case com_sun_prism_es2_GLContext_GL_RGBA:
 924             return GL_RGBA;
 925         case com_sun_prism_es2_GLContext_GL_BGRA:
 926             return GL_BGRA;
 927         case com_sun_prism_es2_GLContext_GL_RGB:
 928             return GL_RGB;
 929         case com_sun_prism_es2_GLContext_GL_LUMINANCE:
 930             return GL_LUMINANCE;
 931         case com_sun_prism_es2_GLContext_GL_ALPHA:
 932             return GL_ALPHA;
 933         case com_sun_prism_es2_GLContext_GL_RGBA32F:
 934             return GL_RGBA32F;
 935         case com_sun_prism_es2_GLContext_GL_YCBCR_422_APPLE:
 936             /* not using symbolic name may not be available on all platform - DrD*/
 937             return 0x85B9;
 938 
 939         case com_sun_prism_es2_GLContext_GL_TEXTURE_2D:
 940             return GL_TEXTURE_2D;
 941         case com_sun_prism_es2_GLContext_GL_TEXTURE_BINDING_2D:
 942             return GL_TEXTURE_BINDING_2D;
 943         case com_sun_prism_es2_GLContext_GL_LINEAR:
 944             return GL_LINEAR;
 945 
 946         case com_sun_prism_es2_GLContext_WRAPMODE_REPEAT:
 947             return GL_REPEAT;
 948         case com_sun_prism_es2_GLContext_WRAPMODE_CLAMP_TO_EDGE:
 949             return GL_CLAMP_TO_EDGE;
 950         case com_sun_prism_es2_GLContext_WRAPMODE_CLAMP_TO_BORDER:
 951             return GL_CLAMP_TO_BORDER;
 952         default:
 953             fprintf(stderr, "warning: Unknown value. Returning value = %d\n", value);
 954     }
 955     return value;
 956 }
 957 
 958 GLint translatePixelStore(int pname) {
 959     switch (pname) {
 960             // Use by glPixelStorei
 961         case com_sun_prism_es2_GLContext_GL_UNPACK_ALIGNMENT:
 962             return GL_UNPACK_ALIGNMENT;
 963         case com_sun_prism_es2_GLContext_GL_UNPACK_ROW_LENGTH:
 964             return GL_UNPACK_ROW_LENGTH;
 965         case com_sun_prism_es2_GLContext_GL_UNPACK_SKIP_PIXELS:
 966             return GL_UNPACK_SKIP_PIXELS;
 967         case com_sun_prism_es2_GLContext_GL_UNPACK_SKIP_ROWS:
 968             return GL_UNPACK_SKIP_ROWS;
 969 
 970         default:
 971             fprintf(stderr, "warning: Unknown pname. Returning pname = %d\n", pname);
 972     }
 973     return (GLint) pname;
 974 }
 975 
 976 /*
 977  * Class:     com_sun_prism_es2_GLContext
 978  * Method:    nPixelStorei
 979  * Signature: (II)V
 980  */
 981 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nPixelStorei
 982 (JNIEnv *env, jclass class, jint pname, jint value) {
 983     glPixelStorei((GLenum) translatePixelStore(pname), (GLint) value);
 984 }
 985 
 986 jboolean doReadPixels(JNIEnv *env, jlong nativeCtxInfo, jint length, jobject buffer,
 987         jarray pixelArr, jint x, jint y, jint width, jint height) {
 988     GLvoid *ptr = NULL;
 989 
 990     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
 991     if (ctxInfo == NULL) {
 992         fprintf(stderr, "doReadPixels: ctxInfo is NULL\n");
 993         return JNI_FALSE;
 994     }
 995 
 996     // sanity check, do we have enough memory
 997     // length, width and height are non-negative
 998     if ((length / 4 / width) < height) {
 999         fprintf(stderr, "doReadPixels: pixel buffer too small - length = %d\n",
1000                 (int) length);
1001         return JNI_FALSE;
1002     }
1003 
1004     ptr = (GLvoid *) (pixelArr ?
1005             ((char *) (*env)->GetPrimitiveArrayCritical(env, pixelArr, NULL)) :
1006             ((char *) (*env)->GetDirectBufferAddress(env, buffer)));
1007 
1008     if (ptr == NULL) {
1009         fprintf(stderr, "doReadPixels: pixel buffer is NULL\n");
1010         return JNI_FALSE;
1011     }
1012 
1013     if (ctxInfo->gl2) {
1014         glReadPixels((GLint) x, (GLint) y, (GLsizei) width, (GLsizei) height,
1015                     GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, ptr);
1016     } else {
1017         jint i;
1018         GLubyte* c = (GLubyte*) ptr;
1019         GLubyte temp;
1020         glReadPixels((GLint) x, (GLint) y, (GLsizei) width, (GLsizei) height,
1021                 GL_RGBA, GL_UNSIGNED_BYTE, ptr);
1022 
1023         for (i = 0; i < width * height; i++) {
1024             temp = c[0];
1025             c[0] = c[2];
1026             c[2] = temp;
1027             c += 4;
1028         }
1029     }
1030 
1031     if (pixelArr != NULL) {
1032         (*env)->ReleasePrimitiveArrayCritical(env, pixelArr, ptr, 0);
1033     }
1034     return JNI_TRUE;
1035 }
1036 
1037 /*
1038  * Class:     com_sun_prism_es2_GLContext
1039  * Method:    nReadPixelsByte
1040  * Signature: (JILjava/nio/Buffer;[BIIII)Z
1041  */
1042 JNIEXPORT jboolean JNICALL Java_com_sun_prism_es2_GLContext_nReadPixelsByte
1043 (JNIEnv *env, jclass class, jlong nativeCtxInfo, jint length, jobject buffer,
1044         jbyteArray pixelArr, jint x, jint y, jint w, jint h) {
1045     return doReadPixels(env, nativeCtxInfo, length, buffer, pixelArr, x, y, w, h);
1046 }
1047 
1048 /*
1049  * Class:     com_sun_prism_es2_GLContext
1050  * Method:    nReadPixelsInt
1051  * Signature: (JILjava/nio/Buffer;[IIIII)Z
1052  */
1053 JNIEXPORT jboolean JNICALL Java_com_sun_prism_es2_GLContext_nReadPixelsInt
1054 (JNIEnv *env, jclass class, jlong nativeCtxInfo, jint length, jobject buffer,
1055         jintArray pixelArr, jint x, jint y, jint w, jint h) {
1056     return doReadPixels(env, nativeCtxInfo, length, buffer, pixelArr, x, y, w, h);
1057 }
1058 
1059 /*
1060  * Class:     com_sun_prism_es2_GLContext
1061  * Method:    nScissorTest
1062  * Signature: (JZIIII)V
1063  */
1064 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nScissorTest
1065 (JNIEnv *env, jclass class, jlong nativeCtxInfo, jboolean enable,
1066         jint x, jint y, jint w, jint h) {
1067     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
1068     if (ctxInfo == NULL) {
1069         return;
1070     }
1071 
1072     if (enable) {
1073         if (!ctxInfo->state.scissorEnabled) {
1074             glEnable(GL_SCISSOR_TEST);
1075             ctxInfo->state.scissorEnabled = JNI_TRUE;
1076         }
1077         glScissor(x, y, w, h);
1078     } else if (ctxInfo->state.scissorEnabled) {
1079         glDisable(GL_SCISSOR_TEST);
1080         ctxInfo->state.scissorEnabled = JNI_FALSE;
1081     }
1082 }
1083 
1084 /*
1085  * Class:     com_sun_prism_es2_GLContext
1086  * Method:    nTexParamsMinMax
1087  * Signature: (I)V
1088  */
1089 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nTexParamsMinMax
1090 (JNIEnv *env, jclass class, jint pname) {
1091     GLenum param = translatePrismToGL(pname);
1092     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, param);
1093     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, param);
1094 }
1095 
1096 /*
1097  * Class:     com_sun_prism_es2_GLContext
1098  * Method:    nTexImage2D0
1099  * Signature: (IIIIIIIILjava/lang/Object;I)Z
1100  */
1101 JNIEXPORT jboolean JNICALL Java_com_sun_prism_es2_GLContext_nTexImage2D0
1102 (JNIEnv *env, jclass class, jint target, jint level, jint internalFormat,
1103         jint width, jint height, jint border, jint format, jint type,
1104         jobject pixels, jint pixelsByteOffset) {
1105     GLvoid *ptr = NULL;
1106     GLenum err;
1107 
1108     if (pixels != NULL) {
1109         ptr = (GLvoid *) (((char *) (*env)->GetDirectBufferAddress(env, pixels))
1110                 + pixelsByteOffset);
1111     }
1112 
1113     glGetError();
1114     glTexImage2D((GLenum) translatePrismToGL(target), (GLint) level,
1115             (GLint) translatePrismToGL(internalFormat),
1116             (GLsizei) width, (GLsizei) height, (GLint) border,
1117             (GLenum) translatePrismToGL(format),
1118             (GLenum) translatePrismToGL(type), (GLvoid *) ptr);
1119     err  = glGetError();
1120 
1121     // printGLError(err);
1122     return err == GL_NO_ERROR ? JNI_TRUE : JNI_FALSE;
1123 }
1124 
1125 /*
1126  * Class:     com_sun_prism_es2_GLContext
1127  * Method:    nTexImage2D1
1128  * Signature: (IIIIIIIILjava/lang/Object;I)Z
1129  */
1130 JNIEXPORT jboolean JNICALL Java_com_sun_prism_es2_GLContext_nTexImage2D1
1131 (JNIEnv *env, jclass class, jint target, jint level, jint internalFormat,
1132         jint width, jint height, jint border, jint format, jint type,
1133         jobject pixels, jint pixelsByteOffset) {
1134     GLvoid *ptr = NULL;
1135     GLenum err;
1136 
1137     if (pixels != NULL) {
1138         ptr = (GLvoid *) (((char *) (*env)->GetPrimitiveArrayCritical(env, pixels, NULL))
1139                 + pixelsByteOffset);
1140     }
1141 
1142     glGetError();
1143     glTexImage2D((GLenum) translatePrismToGL(target), (GLint) level,
1144             (GLint) translatePrismToGL(internalFormat),
1145             (GLsizei) width, (GLsizei) height, (GLint) border,
1146             (GLenum) translatePrismToGL(format),
1147             (GLenum) translatePrismToGL(type), (GLvoid *) ptr);
1148 
1149     err  = glGetError();
1150 
1151     if (pixels != NULL) {
1152         (*env)->ReleasePrimitiveArrayCritical(env, pixels, ptr, 0);
1153     }
1154 
1155     // printGLError(err);
1156     return err == GL_NO_ERROR ? JNI_TRUE : JNI_FALSE;
1157 }
1158 
1159 /*
1160  * Class:     com_sun_prism_es2_GLContext
1161  * Method:    nTexSubImage2D0
1162  * Signature: (IIIIIIIILjava/lang/Object;I)V
1163  */
1164 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nTexSubImage2D0
1165 (JNIEnv *env, jclass class, jint target, jint level,
1166         jint xoffset, jint yoffset, jint width, jint height, jint format,
1167         jint type, jobject pixels, jint pixelsByteOffset) {
1168     GLvoid *ptr = NULL;
1169     if (pixels != NULL) {
1170         ptr = (GLvoid *) (((char *) (*env)->GetDirectBufferAddress(env, pixels))
1171                 + pixelsByteOffset);
1172     }
1173     glTexSubImage2D((GLenum) translatePrismToGL(target), (GLint) level,
1174             (GLint) xoffset, (GLint) yoffset,
1175             (GLsizei) width, (GLsizei) height, (GLenum) translatePrismToGL(format),
1176             (GLenum) translatePrismToGL(type), (GLvoid *) ptr);
1177 }
1178 
1179 /*
1180  * Class:     com_sun_prism_es2_GLContext
1181  * Method:    nTexSubImage2D1
1182  * Signature: (IIIIIIIILjava/lang/Object;I)V
1183  */
1184 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nTexSubImage2D1
1185 (JNIEnv *env, jclass class, jint target, jint level,
1186         jint xoffset, jint yoffset, jint width, jint height, jint format,
1187         jint type, jobject pixels, jint pixelsByteOffset) {
1188     GLvoid *ptr = NULL;
1189     if (pixels != NULL) {
1190         ptr = (GLvoid *) (((char *) (*env)->GetPrimitiveArrayCritical(env, pixels, NULL))
1191                 + pixelsByteOffset);
1192     }
1193     glTexSubImage2D((GLenum) translatePrismToGL(target), (GLint) level,
1194             (GLint) xoffset, (GLint) yoffset,
1195             (GLsizei) width, (GLsizei) height, (GLenum) translatePrismToGL(format),
1196             (GLenum) translatePrismToGL(type), (GLvoid *) ptr);
1197     if (pixels != NULL) {
1198         (*env)->ReleasePrimitiveArrayCritical(env, pixels, ptr, 0);
1199     }
1200 }
1201 
1202 /*
1203  * Class:     com_sun_prism_es2_GLContext
1204  * Method:    nUpdateViewport
1205  * Signature: (JIIII)V
1206  */
1207 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nUpdateViewport
1208 (JNIEnv *env, jclass class, jlong nativeCtxInfo, jint x, jint y,
1209         jint w, jint h) {
1210     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
1211     if (ctxInfo == NULL) {
1212         return;
1213     }
1214 
1215     glViewport((GLint) x, (GLint) y, (GLsizei) w, (GLsizei) h);
1216 }
1217 
1218 /*
1219  * Class:     com_sun_prism_es2_GLContext
1220  * Method:    nSetMSAA
1221  * Signature: (JZ)V
1222  */
1223 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nSetMSAA
1224 (JNIEnv *env, jclass class, jlong nativeCtxInfo, jboolean msaa) {
1225 #ifndef IS_EGL
1226     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
1227     if (ctxInfo == NULL) {
1228         return;
1229     }
1230 
1231     if (msaa) {
1232         glEnable(GL_MULTISAMPLE);
1233     } else {
1234         glDisable(GL_MULTISAMPLE);
1235     }
1236 #endif
1237 }
1238 
1239 /*
1240  * Class:     com_sun_prism_es2_GLContext
1241  * Method:    nSetDepthTest
1242  * Signature: (JZ)V
1243  */
1244 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nSetDepthTest
1245 (JNIEnv *env, jclass class, jlong nativeCtxInfo, jboolean depthTest) {
1246     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
1247     if (ctxInfo == NULL) {
1248         return;
1249     }
1250 
1251     if (depthTest) {
1252         glEnable(GL_DEPTH_TEST);
1253         glDepthFunc(GL_LEQUAL);
1254         glDepthMask(GL_TRUE);
1255         ctxInfo->state.depthWritesEnabled = JNI_TRUE;
1256 #ifndef IS_EGL /* RT-25058 */
1257         glEnable(GL_ALPHA_TEST);
1258 #ifndef ANDROID_NDK
1259         glAlphaFunc(GL_NOTEQUAL, 0.0);
1260 #endif
1261 #endif
1262     } else {
1263         glDisable(GL_DEPTH_TEST);
1264         glDepthMask(GL_FALSE);
1265         ctxInfo->state.depthWritesEnabled = JNI_FALSE;
1266 #ifndef IS_EGL
1267         glDisable(GL_ALPHA_TEST);
1268 #endif
1269     }
1270 }
1271 
1272 /*
1273  * Class:     com_sun_prism_es2_GLContext
1274  * Method:    nUniform1f
1275  * Signature: (JIF)V
1276  */
1277 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nUniform1f
1278 (JNIEnv *env, jclass class, jlong nativeCtxInfo, jint location, jfloat v0) {
1279     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
1280     if (ctxInfo == NULL) {
1281         return;
1282     }
1283     ctxInfo->glUniform1f(location, v0);
1284 }
1285 
1286 /*
1287  * Class:     com_sun_prism_es2_GLContext
1288  * Method:    nUniform2f
1289  * Signature: (JIFF)V
1290  */
1291 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nUniform2f
1292 (JNIEnv *env, jclass class, jlong nativeCtxInfo, jint location,
1293         jfloat v0, jfloat v1) {
1294     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
1295     if (ctxInfo == NULL) {
1296         return;
1297     }
1298     ctxInfo->glUniform2f(location, v0, v1);
1299 }
1300 
1301 /*
1302  * Class:     com_sun_prism_es2_GLContext
1303  * Method:    nUniform3f
1304  * Signature: (JIFFF)V
1305  */
1306 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nUniform3f
1307 (JNIEnv *env, jclass class, jlong nativeCtxInfo, jint location,
1308         jfloat v0, jfloat v1, jfloat v2) {
1309     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
1310     if (ctxInfo == NULL) {
1311         return;
1312     }
1313     ctxInfo->glUniform3f(location, v0, v1, v2);
1314 }
1315 
1316 /*
1317  * Class:     com_sun_prism_es2_GLContext
1318  * Method:    nUniform4f
1319  * Signature: (JIFFFF)V
1320  */
1321 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nUniform4f
1322 (JNIEnv *env, jclass class, jlong nativeCtxInfo, jint location,
1323         jfloat v0, jfloat v1, jfloat v2, jfloat v3) {
1324     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
1325     if (ctxInfo == NULL) {
1326         return;
1327     }
1328     ctxInfo->glUniform4f(location, v0, v1, v2, v3);
1329 }
1330 
1331 /*
1332  * Class:     com_sun_prism_es2_GLContext
1333  * Method:    nUniform4fv0
1334  * Signature: (JIILjava/lang/Object;I)V
1335  */
1336 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nUniform4fv0
1337 (JNIEnv *env, jclass class, jlong nativeCtxInfo, jint location, jint count,
1338         jobject value, jint valueByteOffset) {
1339     GLfloat *_ptr2 = NULL;
1340     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
1341     if ((env == NULL) || (ctxInfo == NULL)) {
1342         return;
1343     }
1344     if (value != NULL) {
1345         _ptr2 = (GLfloat *) (((char *) (*env)->GetDirectBufferAddress(env, value))
1346                 + valueByteOffset);
1347     }
1348     ctxInfo->glUniform4fv((GLint) location, (GLsizei) count, (GLfloat *) _ptr2);
1349 }
1350 
1351 /*
1352  * Class:     com_sun_prism_es2_GLContext
1353  * Method:    nUniform4fv1
1354  * Signature: (JIILjava/lang/Object;I)V
1355  */
1356 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nUniform4fv1
1357 (JNIEnv *env, jclass class, jlong nativeCtxInfo, jint location, jint count,
1358         jobject value, jint valueByteOffset) {
1359     GLfloat *_ptr2 = NULL;
1360     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
1361     if ((env == NULL) || (ctxInfo == NULL)) {
1362         return;
1363     }
1364     if (value != NULL) {
1365         _ptr2 = (GLfloat *) (((char *) (*env)->GetPrimitiveArrayCritical(env, value, NULL))
1366                 + valueByteOffset);
1367     }
1368     ctxInfo->glUniform4fv((GLint) location, (GLsizei) count, (GLfloat *) _ptr2);
1369     if (value != NULL) {
1370         (*env)->ReleasePrimitiveArrayCritical(env, value, _ptr2, 0);
1371     }
1372 }
1373 
1374 /*
1375  * Class:     com_sun_prism_es2_GLContext
1376  * Method:    nUniform1i
1377  * Signature: (JII)V
1378  */
1379 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nUniform1i
1380 (JNIEnv *env, jclass class, jlong nativeCtxInfo, jint location, jint v0) {
1381     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
1382     if ((ctxInfo == NULL) || (ctxInfo->glUniform1i == NULL)) {
1383         return;
1384     }
1385     ctxInfo->glUniform1i(location, v0);
1386 }
1387 
1388 /*
1389  * Class:     com_sun_prism_es2_GLContext
1390  * Method:    nUniform2i
1391  * Signature: (JIII)V
1392  */
1393 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nUniform2i
1394 (JNIEnv *env, jclass class, jlong nativeCtxInfo, jint location, jint v0, jint v1) {
1395     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
1396     if ((ctxInfo == NULL) || (ctxInfo->glUniform2i == NULL)) {
1397         return;
1398     }
1399     ctxInfo->glUniform2i(location, v0, v1);
1400 }
1401 
1402 /*
1403  * Class:     com_sun_prism_es2_GLContext
1404  * Method:    nUniform3i
1405  * Signature: (JIIII)V
1406  */
1407 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nUniform3i
1408 (JNIEnv *env, jclass class, jlong nativeCtxInfo, jint location,
1409         jint v0, jint v1, jint v2) {
1410     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
1411     if ((ctxInfo == NULL) || (ctxInfo->glUniform3i == NULL)) {
1412         return;
1413     }
1414     ctxInfo->glUniform3i(location, v0, v1, v2);
1415 }
1416 
1417 /*
1418  * Class:     com_sun_prism_es2_GLContext
1419  * Method:    nUniform4i
1420  * Signature: (JIIIII)V
1421  */
1422 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nUniform4i
1423 (JNIEnv *env, jclass class, jlong nativeCtxInfo, jint location,
1424         jint v0, jint v1, jint v2, jint v3) {
1425     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
1426     if ((ctxInfo == NULL) || (ctxInfo->glUniform4i == NULL)) {
1427         return;
1428     }
1429     ctxInfo->glUniform4i(location, v0, v1, v2, v3);
1430 }
1431 
1432 /*
1433  * Class:     com_sun_prism_es2_GLContext
1434  * Method:    nUniform4iv0
1435  * Signature: (JIILjava/lang/Object;I)V
1436  */
1437 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nUniform4iv0
1438 (JNIEnv *env, jclass class, jlong nativeCtxInfo, jint location, jint count,
1439         jobject value, jint valueByteOffset) {
1440     GLint *_ptr2 = NULL;
1441     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
1442     if ((ctxInfo == NULL) || (ctxInfo->glUniform4iv == NULL)) {
1443         return;
1444     }
1445 
1446     if (value != NULL) {
1447         _ptr2 = (GLint *) (((char *) (*env)->GetDirectBufferAddress(env, value))
1448                 + valueByteOffset);
1449     }
1450     ctxInfo->glUniform4iv((GLint) location, (GLsizei) count, (GLint *) _ptr2);
1451 }
1452 
1453 /*
1454  * Class:     com_sun_prism_es2_GLContext
1455  * Method:    nUniform4iv1
1456  * Signature: (JIILjava/lang/Object;I)V
1457  */
1458 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nUniform4iv1
1459 (JNIEnv *env, jclass class, jlong nativeCtxInfo, jint location, jint count,
1460         jobject value, jint valueByteOffset) {
1461     GLint *_ptr2 = NULL;
1462     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
1463     if ((ctxInfo == NULL) || (ctxInfo->glUniform4iv == NULL)) {
1464         return;
1465     }
1466 
1467     if (value != NULL) {
1468         _ptr2 = (GLint *) (((char *) (*env)->GetPrimitiveArrayCritical(env, value, NULL))
1469                 + valueByteOffset);
1470     }
1471     ctxInfo->glUniform4iv((GLint) location, (GLsizei) count, (GLint *) _ptr2);
1472     if (value != NULL) {
1473         (*env)->ReleasePrimitiveArrayCritical(env, value, _ptr2, 0);
1474     }
1475 }
1476 
1477 /*
1478  * Class:     com_sun_prism_es2_GLContext
1479  * Method:    nUniformMatrix4fv0
1480  * Signature: (JIIZLjava/lang/Object;I)V
1481  */
1482 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nUniformMatrix4fv
1483 (JNIEnv *env, jclass class, jlong nativeCtxInfo, jint location,
1484         jboolean transpose, jfloatArray values) {
1485     GLfloat *_ptr = NULL;
1486     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
1487     if ((ctxInfo == NULL) || (ctxInfo->glUniformMatrix4fv == NULL)) {
1488         return;
1489     }
1490 
1491     if (values != NULL) {
1492         _ptr = (float *)(*env)->GetPrimitiveArrayCritical(env, values, NULL);
1493     }
1494     ctxInfo->glUniformMatrix4fv((GLint) location, 1, (GLboolean) transpose, _ptr);
1495 
1496     if (_ptr) (*env)->ReleasePrimitiveArrayCritical(env, values, _ptr, JNI_ABORT);
1497 }
1498 
1499 /*
1500  * Class:     com_sun_prism_es2_GLContext
1501  * Method:    nUpdateFilterState
1502  * Signature: (JIZ)V
1503  */
1504 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nUpdateFilterState
1505 (JNIEnv *env, jclass class, jlong nativeCtxInfo, jint texID, jboolean linearFiler) {
1506     int glFilter;
1507 
1508     glFilter = linearFiler ? GL_LINEAR : GL_NEAREST;
1509     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glFilter);
1510     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, glFilter);
1511 }
1512 
1513 /*
1514  * Class:     com_sun_prism_es2_GLContext
1515  * Method:    nUpdateWrapState
1516  * Signature: (JII)V
1517  */
1518 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nUpdateWrapState
1519 (JNIEnv *env, jclass class, jlong nativeCtxInfo, jint texID, jint wrapMode) {
1520     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
1521             (GLenum) translatePrismToGL(wrapMode));
1522     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
1523             (GLenum) translatePrismToGL(wrapMode));
1524 }
1525 
1526 /*
1527  * Class:     com_sun_prism_es2_GLContext
1528  * Method:    nUseProgram
1529  * Signature: (JI)V
1530  */
1531 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nUseProgram
1532 (JNIEnv *env, jclass class, jlong nativeCtxInfo, jint pID) {
1533     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
1534     if ((ctxInfo == NULL) || (ctxInfo->glUseProgram == NULL)) {
1535         return;
1536     }
1537     ctxInfo->glUseProgram(pID);
1538 }
1539 
1540 /*
1541  * Class:     com_sun_prism_es2_GLContext
1542  * Method:    nDisableVertexAttributes
1543  * Signature: (J)V
1544  */
1545 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nDisableVertexAttributes
1546 (JNIEnv *env, jclass class, jlong nativeCtxInfo) {
1547     int i;
1548     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
1549     if ((ctxInfo == NULL) || (ctxInfo->glDisableVertexAttribArray == NULL)) {
1550         return;
1551     }
1552 
1553     for (i = 0; i != 4; ++i) {
1554         ctxInfo->glDisableVertexAttribArray(i);
1555     }
1556 }
1557 
1558 /*
1559  * Class:     com_sun_prism_es2_GLContext
1560  * Method:    nEnableVertexAttributes
1561  * Signature: (J)V
1562  */
1563 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nEnableVertexAttributes
1564 (JNIEnv *env, jclass class, jlong nativeCtxInfo) {
1565     int i;
1566     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
1567     if ((ctxInfo == NULL) || (ctxInfo->glEnableVertexAttribArray == NULL)) {
1568         return;
1569     }
1570 
1571     for (i = 0; i != 4; ++i) {
1572         ctxInfo->glEnableVertexAttribArray(i);
1573     }
1574 }
1575 
1576 #define FLOATS_PER_TC 2
1577 #define FLOATS_PER_VC 3
1578 #define FLOATS_PER_VERT (FLOATS_PER_TC * 2 + FLOATS_PER_VC)
1579 
1580 #define coordStride (sizeof(float) * FLOATS_PER_VERT)
1581 #define colorStride 4
1582 
1583 /* NOTE: the ctx->vbFloatData and ctx->vbByteData pointers must be updated
1584  * whenever calling glVertexAttribPointer. Failing to do this could leave
1585  * the pointers in an inconsistent state.
1586  */
1587 
1588 static void setVertexAttributePointers(ContextInfo *ctx, float *pFloat, char *pByte) {
1589     if (pFloat != ctx->vbFloatData) {
1590         ctx->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, coordStride, pFloat);
1591         ctx->glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, coordStride,
1592             pFloat + FLOATS_PER_VC);
1593         ctx->glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, coordStride,
1594             pFloat + FLOATS_PER_VC + FLOATS_PER_TC);
1595         ctx->vbFloatData = pFloat;
1596     }
1597 
1598     if (pByte != ctx->vbByteData) {
1599         ctx->glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_TRUE, colorStride, pByte);
1600         ctx->vbByteData = pByte;
1601     }
1602 }
1603 /*
1604  * Class:     com_sun_prism_es2_GLContext
1605  * Method:    nDrawIndexedQuads
1606  * Signature: (JI[F[B)V
1607  */
1608 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nDrawIndexedQuads
1609   (JNIEnv *env, jclass class, jlong nativeCtxInfo, jint numVertices,
1610    jfloatArray dataf, jbyteArray datab)
1611 {
1612     float *pFloat;
1613     char *pByte;
1614     int numQuads = numVertices / 4;
1615 
1616     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
1617     if ((ctxInfo == NULL) || (ctxInfo->glVertexAttribPointer == NULL)) {
1618         return;
1619     }
1620 
1621     pFloat = (float *)(*env)->GetPrimitiveArrayCritical(env, dataf, NULL);
1622     pByte = (char *)(*env)->GetPrimitiveArrayCritical(env, datab, NULL);
1623 
1624     if (pFloat && pByte) {
1625         setVertexAttributePointers(ctxInfo, pFloat, pByte);
1626         glDrawElements(GL_TRIANGLES, numQuads * 2 * 3, GL_UNSIGNED_SHORT, 0);
1627     }
1628 
1629     if (pByte)  (*env)->ReleasePrimitiveArrayCritical(env, datab, pByte, JNI_ABORT);
1630     if (pFloat) (*env)->ReleasePrimitiveArrayCritical(env, dataf, pFloat, JNI_ABORT);
1631 }
1632 
1633 /*
1634  * Class:     com_sun_prism_es2_GLContext
1635  * Method:    nDrawTriangleList
1636  * Signature: (JI[F[B)V
1637  */
1638 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nDrawTriangleList
1639   (JNIEnv *env, jclass class, jlong nativeCtxInfo, jint numTriangles,
1640    jfloatArray dataf, jbyteArray datab)
1641 {
1642     float *pFloat;
1643     char *pByte;
1644 
1645     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
1646     if ((ctxInfo == NULL) || (ctxInfo->glVertexAttribPointer == NULL)) {
1647         return;
1648     }
1649 
1650     pFloat = (float *)(*env)->GetPrimitiveArrayCritical(env, dataf, NULL);
1651     pByte = (char *)(*env)->GetPrimitiveArrayCritical(env, datab, NULL);
1652 
1653     if (pFloat && pByte) {
1654         setVertexAttributePointers(ctxInfo, pFloat, pByte);
1655         glDrawArrays(GL_TRIANGLES, 0, numTriangles * 3);
1656     }
1657 
1658     if (pByte)  (*env)->ReleasePrimitiveArrayCritical(env, datab, pByte, JNI_ABORT);
1659     if (pFloat) (*env)->ReleasePrimitiveArrayCritical(env, dataf, pFloat, JNI_ABORT);
1660 }
1661 
1662 /*
1663  * Class:     com_sun_prism_es2_GLContext
1664  * Method:    nCreateIndexBuffer16
1665  * Signature: (J[SI)I
1666  */
1667 JNIEXPORT jint JNICALL Java_com_sun_prism_es2_GLContext_nCreateIndexBuffer16
1668   (JNIEnv *env, jclass class, jlong nativeCtxInfo, jshortArray array, jint n)
1669 {
1670     GLuint id = 0;
1671     void *pData;
1672 
1673     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
1674     if ((ctxInfo == NULL) || (ctxInfo->glBindBuffer == NULL) ||
1675             (ctxInfo->glBufferData == NULL) || (ctxInfo->glGenBuffers == NULL)) {
1676         return 0;
1677     }
1678 
1679     pData = (*env)->GetPrimitiveArrayCritical(env, array, NULL);
1680     if (pData) {
1681         ctxInfo->glGenBuffers(1, &id);
1682         if (id) {
1683             ctxInfo->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, id);
1684             ctxInfo->glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(short) * n, pData, GL_STATIC_DRAW);
1685         }
1686     }
1687     if (pData) (*env)->ReleasePrimitiveArrayCritical(env, array, pData, JNI_ABORT);
1688     return id;
1689 }
1690 
1691 /*
1692  * Class:     com_sun_prism_es2_GLContext
1693  * Method:    nSetIndexBuffer
1694  * Signature: (JI)V
1695  */
1696 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nSetIndexBuffer
1697   (JNIEnv *env, jclass class, jlong nativeCtxInfo, jint buffer)
1698 {
1699     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
1700     if ((ctxInfo == NULL) || (ctxInfo->glBindBuffer == NULL)) {
1701         return;
1702     }
1703     ctxInfo->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
1704 }
1705 
1706 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nSetDeviceParametersFor2D
1707   (JNIEnv *env, jclass class, jlong nativeCtxInfo)
1708 {
1709     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
1710     if ((ctxInfo == NULL) || (ctxInfo->glBindBuffer == NULL) ||
1711             (ctxInfo->glBufferData == NULL) ||
1712             (ctxInfo->glDisableVertexAttribArray == NULL)) {
1713         return;
1714     }
1715 
1716     // Disable 3D states
1717     ctxInfo->glBindBuffer(GL_ARRAY_BUFFER, 0);
1718     ctxInfo->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1719     ctxInfo->glDisableVertexAttribArray(VC_3D_INDEX);
1720     ctxInfo->glDisableVertexAttribArray(NC_3D_INDEX);
1721     ctxInfo->glDisableVertexAttribArray(TC_3D_INDEX);
1722 
1723     ctxInfo->vbFloatData = NULL;
1724     ctxInfo->vbByteData = NULL;
1725 
1726     glEnable(GL_BLEND);
1727     glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1728 
1729     if (ctxInfo->state.scissorEnabled) {
1730         ctxInfo->state.scissorEnabled = JNI_FALSE;
1731         glDisable(GL_SCISSOR_TEST);
1732     }
1733 
1734     glCullFace(GL_BACK);
1735     ctxInfo->state.cullMode = GL_BACK;
1736     glDisable(GL_CULL_FACE);
1737     ctxInfo->state.cullEnable = JNI_FALSE;
1738 #ifndef IS_EGL
1739     glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1740 #endif
1741     ctxInfo->state.fillMode = GL_FILL;
1742 }
1743 
1744 /*
1745  * Class:     com_sun_prism_es2_GLContext
1746  * Method:    nSetDeviceParametersFor3D
1747  * Signature: (J)V
1748  */
1749 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nSetDeviceParametersFor3D
1750   (JNIEnv *env, jclass class, jlong nativeCtxInfo)
1751 {
1752     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
1753     if (ctxInfo == NULL) {
1754         return;
1755     }
1756     // Note: projViewTx and camPos are handled above in the Java layer
1757 
1758     glDisable(GL_BLEND);
1759     glBlendFunc(GL_ONE, GL_ZERO);
1760 
1761     if (ctxInfo->state.scissorEnabled) {
1762         ctxInfo->state.scissorEnabled = JNI_FALSE;
1763         glDisable(GL_SCISSOR_TEST);
1764     }
1765 
1766     glEnable(GL_CULL_FACE);
1767     ctxInfo->state.cullEnable = GL_TRUE;
1768     glCullFace(GL_BACK);
1769     ctxInfo->state.cullMode = GL_BACK;
1770     glFrontFace(GL_CW); // set clockwise order as front-facing
1771 #ifndef IS_EGL
1772     glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1773 #endif
1774     ctxInfo->state.fillMode = GL_FILL;
1775 
1776 }
1777 
1778 /*
1779  * Class:     com_sun_prism_es2_GLContext
1780  * Method:    nCreateES2Mesh
1781  * Signature: (J)J
1782  */
1783 JNIEXPORT jlong JNICALL Java_com_sun_prism_es2_GLContext_nCreateES2Mesh
1784   (JNIEnv *env, jclass class, jlong nativeCtxInfo)
1785 {
1786     MeshInfo *meshInfo = NULL;
1787     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
1788     if ((ctxInfo == NULL) || (ctxInfo->glGenBuffers == NULL)) {
1789         return 0;
1790     }
1791 
1792     /* allocate the structure */
1793     meshInfo = (MeshInfo *) malloc(sizeof (MeshInfo));
1794     if (meshInfo == NULL) {
1795         fprintf(stderr, "nCreateES2Mesh: Failed in malloc\n");
1796         return 0;
1797     }
1798 
1799     /* initialize the structure */    
1800     meshInfo->vboIDArray[MESH_VERTEXBUFFER] = 0;
1801     meshInfo->vboIDArray[MESH_INDEXBUFFER] = 0;
1802     meshInfo->indexBufferSize = 0;
1803     meshInfo->indexBufferType = 0;
1804 
1805     /* create vbo ids */
1806     ctxInfo->glGenBuffers(MESH_MAX_BUFFERS, (meshInfo->vboIDArray));
1807 
1808     return ptr_to_jlong(meshInfo);
1809 }
1810 
1811 /*
1812  * Class:     com_sun_prism_es2_GLContext
1813  * Method:    nReleaseES2Mesh
1814  * Signature: (JJ)V
1815  */
1816 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nReleaseES2Mesh
1817   (JNIEnv *env, jclass class, jlong nativeCtxInfo, jlong nativeMeshInfo)
1818 {
1819     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
1820     MeshInfo *meshInfo = (MeshInfo *) jlong_to_ptr(nativeMeshInfo);
1821     if ((ctxInfo == NULL) || (meshInfo == NULL) ||
1822             (ctxInfo->glDeleteBuffers == NULL)) {
1823         return;
1824     }
1825 
1826     // TODO: 3D - Native clean up. Need to determine do we have to free what
1827     //            is held by ES2MeshInfo.
1828     ctxInfo->glDeleteBuffers(MESH_MAX_BUFFERS, (GLuint *) (meshInfo->vboIDArray));
1829     free(meshInfo);
1830 }
1831 
1832 /*
1833  * Class:     com_sun_prism_es2_GLContext
1834  * Method:    nBuildNativeGeometryShort
1835  * Signature: (JJ[FI[SI)Z
1836  */
1837 JNIEXPORT jboolean JNICALL Java_com_sun_prism_es2_GLContext_nBuildNativeGeometryShort
1838   (JNIEnv *env, jclass class, jlong nativeCtxInfo, jlong nativeMeshInfo,
1839         jfloatArray vbArray, jint vbSize, jshortArray ibArray, jint ibSize)
1840 {
1841     GLuint vertexBufferSize;
1842     GLuint indexBufferSize;
1843     GLushort *indexBuffer;
1844     GLfloat *vertexBuffer;
1845     jboolean status = JNI_TRUE;
1846     GLuint uvbSize;
1847     GLuint uibSize;
1848 
1849     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
1850     MeshInfo *meshInfo = (MeshInfo *) jlong_to_ptr(nativeMeshInfo);
1851     if ((ctxInfo == NULL) || (meshInfo == NULL) ||
1852             (vbArray == NULL) || (ibArray == NULL) ||
1853             (ctxInfo->glBindBuffer == NULL) ||
1854             (ctxInfo->glBufferData == NULL) ||
1855             (meshInfo->vboIDArray[MESH_VERTEXBUFFER] == 0)||
1856             (meshInfo->vboIDArray[MESH_INDEXBUFFER] == 0) ||
1857             vbSize < 0 || ibSize < 0) {
1858         return JNI_FALSE;
1859     }
1860 
1861     vertexBufferSize = (*env)->GetArrayLength(env, vbArray);
1862     vertexBuffer = (GLfloat *) ((*env)->GetPrimitiveArrayCritical(env, vbArray, NULL));
1863 
1864     indexBufferSize = (*env)->GetArrayLength(env, ibArray);
1865     indexBuffer = (GLushort *) ((*env)->GetPrimitiveArrayCritical(env, ibArray, NULL));
1866 
1867     uvbSize = (GLuint) vbSize;
1868     uibSize = (GLuint) ibSize;
1869     if (vertexBuffer == NULL || indexBuffer == NULL
1870             || uvbSize > vertexBufferSize || uibSize > indexBufferSize) {
1871         status = JNI_FALSE;
1872     }
1873 
1874     if (status) {
1875         // Initialize vertex buffer
1876         ctxInfo->glBindBuffer(GL_ARRAY_BUFFER, meshInfo->vboIDArray[MESH_VERTEXBUFFER]);
1877         ctxInfo->glBufferData(GL_ARRAY_BUFFER, uvbSize * sizeof (GLfloat),
1878                 vertexBuffer, GL_STATIC_DRAW);
1879 
1880         // Initialize index buffer
1881         ctxInfo->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, meshInfo->vboIDArray[MESH_INDEXBUFFER]);
1882         ctxInfo->glBufferData(GL_ELEMENT_ARRAY_BUFFER, uibSize * sizeof (GLushort),
1883                 indexBuffer, GL_STATIC_DRAW);
1884         meshInfo->indexBufferSize = uibSize;
1885         meshInfo->indexBufferType = GL_UNSIGNED_SHORT;
1886 
1887         // Unbind VBOs
1888         ctxInfo->glBindBuffer(GL_ARRAY_BUFFER, 0);
1889         ctxInfo->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1890     }
1891 
1892     if (indexBuffer) {
1893         (*env)->ReleasePrimitiveArrayCritical(env, ibArray, indexBuffer, JNI_ABORT);
1894     }
1895     if (vertexBuffer) {
1896         (*env)->ReleasePrimitiveArrayCritical(env, vbArray, vertexBuffer, JNI_ABORT);
1897     }
1898 
1899     return status;
1900 }
1901 
1902 /*
1903  * Class:     com_sun_prism_es2_GLContext
1904  * Method:    nBuildNativeGeometryInt
1905  * Signature: (JJ[FI[II)Z
1906  */
1907 JNIEXPORT jboolean JNICALL Java_com_sun_prism_es2_GLContext_nBuildNativeGeometryInt
1908 (JNIEnv *env, jclass class, jlong nativeCtxInfo, jlong nativeMeshInfo,
1909         jfloatArray vbArray, jint vbSize, jintArray ibArray, jint ibSize)
1910 {
1911     GLuint vertexBufferSize;
1912     GLuint indexBufferSize;
1913     GLuint *indexBuffer;
1914     GLfloat *vertexBuffer;
1915     jboolean status = JNI_TRUE;
1916     GLuint uvbSize;
1917     GLuint uibSize;
1918 
1919     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
1920     MeshInfo *meshInfo = (MeshInfo *) jlong_to_ptr(nativeMeshInfo);
1921     if ((ctxInfo == NULL) || (meshInfo == NULL) ||
1922             (vbArray == NULL) || (ibArray == NULL) ||
1923             (ctxInfo->glBindBuffer == NULL) ||
1924             (ctxInfo->glBufferData == NULL) ||
1925             (meshInfo->vboIDArray[MESH_VERTEXBUFFER] == 0)||
1926             (meshInfo->vboIDArray[MESH_INDEXBUFFER] == 0) ||
1927             vbSize < 0 || ibSize < 0) {
1928         return JNI_FALSE;
1929     }
1930 
1931     vertexBufferSize = (*env)->GetArrayLength(env, vbArray);
1932     vertexBuffer = (GLfloat *) ((*env)->GetPrimitiveArrayCritical(env, vbArray, NULL));
1933 
1934     indexBufferSize = (*env)->GetArrayLength(env, ibArray);
1935     indexBuffer = (GLuint *) ((*env)->GetPrimitiveArrayCritical(env, ibArray, NULL));
1936 
1937     uvbSize = (GLuint) vbSize;
1938     uibSize = (GLuint) ibSize;
1939     if (vertexBuffer == NULL || indexBuffer == NULL
1940             || uvbSize > vertexBufferSize || uibSize > indexBufferSize) {
1941         status = JNI_FALSE;
1942     }
1943 
1944     if (status) {
1945         // Initialize vertex buffer
1946         ctxInfo->glBindBuffer(GL_ARRAY_BUFFER, meshInfo->vboIDArray[MESH_VERTEXBUFFER]);
1947         ctxInfo->glBufferData(GL_ARRAY_BUFFER, uvbSize * sizeof (GLfloat),
1948                 vertexBuffer, GL_STATIC_DRAW);
1949 
1950         // Initialize index buffer
1951         ctxInfo->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, meshInfo->vboIDArray[MESH_INDEXBUFFER]);
1952         ctxInfo->glBufferData(GL_ELEMENT_ARRAY_BUFFER, uibSize * sizeof (GLuint),
1953                 indexBuffer, GL_STATIC_DRAW);
1954         meshInfo->indexBufferSize = uibSize;
1955         meshInfo->indexBufferType = GL_UNSIGNED_INT;
1956 
1957         // Unbind VBOs
1958         ctxInfo->glBindBuffer(GL_ARRAY_BUFFER, 0);
1959         ctxInfo->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1960     }
1961 
1962     if (indexBuffer) {
1963         (*env)->ReleasePrimitiveArrayCritical(env, ibArray, indexBuffer, JNI_ABORT);
1964     }
1965     if (vertexBuffer) {
1966         (*env)->ReleasePrimitiveArrayCritical(env, vbArray, vertexBuffer, JNI_ABORT);
1967     }
1968 
1969     return status;
1970 }
1971 
1972 /*
1973  * Class:     com_sun_prism_es2_GLContext
1974  * Method:    nCreateES2PhongMaterial
1975  * Signature: (J)J
1976  */
1977 JNIEXPORT jlong JNICALL Java_com_sun_prism_es2_GLContext_nCreateES2PhongMaterial
1978   (JNIEnv *env, jclass class, jlong nativeCtxInfo)
1979 {
1980     PhongMaterialInfo *pmInfo = NULL;
1981     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
1982     if (ctxInfo == NULL) {
1983         return 0;
1984     }
1985 
1986     /* allocate the structure */
1987     pmInfo = (PhongMaterialInfo *) malloc(sizeof (PhongMaterialInfo));
1988     if (pmInfo == NULL) {
1989         fprintf(stderr, "nCreateES2PhongMaterial: Failed in malloc\n");
1990         return 0;
1991     }
1992 
1993     /* initialize the structure */
1994     pmInfo->diffuseColor[0] = 0.0f;
1995     pmInfo->diffuseColor[1] = 0.0f;
1996     pmInfo->diffuseColor[2] = 0.0f;
1997     pmInfo->diffuseColor[3] = 0.0f;
1998     pmInfo->maps[0] = 0;
1999     pmInfo->maps[1] = 0;
2000     pmInfo->maps[2] = 0;
2001     pmInfo->maps[3] = 0;
2002     return ptr_to_jlong(pmInfo);
2003 }
2004 
2005 /*
2006  * Class:     com_sun_prism_es2_GLContext
2007  * Method:    nReleaseES2PhongMaterial
2008  * Signature: (JJ)V
2009  */
2010 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nReleaseES2PhongMaterial
2011   (JNIEnv *env, jclass class, jlong nativeCtxInfo, jlong nativePhongMaterialInfo)
2012 {
2013     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
2014     PhongMaterialInfo *pmInfo = (PhongMaterialInfo *) jlong_to_ptr(nativePhongMaterialInfo);
2015     if ((ctxInfo == NULL) || (pmInfo == NULL)) {
2016         return;
2017     }
2018 
2019     // We shouldn't free maps (texture) here. This freeing should be handled higher
2020     // in the Java layer in dealing with Texture object.
2021 
2022     free(pmInfo);
2023 }
2024 
2025 /*
2026  * Class:     com_sun_prism_es2_GLContext
2027  * Method:    nSetSolidColor
2028  * Signature: (JJFFFF)V
2029  */
2030 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nSetSolidColor
2031   (JNIEnv *env, jclass class, jlong nativeCtxInfo, jlong nativePhongMaterialInfo,
2032         jfloat r, jfloat g, jfloat b, jfloat a)
2033 {
2034     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
2035     PhongMaterialInfo *pmInfo = (PhongMaterialInfo *) jlong_to_ptr(nativePhongMaterialInfo);
2036     if ((ctxInfo == NULL) || (pmInfo == NULL)) {
2037         return;
2038     }
2039 
2040     pmInfo->diffuseColor[0] = r;
2041     pmInfo->diffuseColor[1] = g;
2042     pmInfo->diffuseColor[2] = b;
2043     pmInfo->diffuseColor[3] = a;
2044 }
2045 
2046 /*
2047  * Class:     com_sun_prism_es2_GLContext
2048  * Method:    nSetMap
2049  * Signature: (JJII)V
2050  */
2051 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nSetMap
2052   (JNIEnv *env, jclass class, jlong nativeCtxInfo, jlong nativePhongMaterialInfo,
2053         jint mapType, jint texID)
2054 {
2055     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
2056     PhongMaterialInfo *pmInfo = (PhongMaterialInfo *) jlong_to_ptr(nativePhongMaterialInfo);
2057     if ((ctxInfo == NULL) || (pmInfo == NULL)) {
2058         return;
2059     }
2060     
2061     // Must within the range of DIFFUSE, SPECULAR, BUMP, SELFILLUMINATION
2062     if ((mapType < 0) || (mapType > 3)) {
2063         fprintf(stderr, "nSetMap: mapType is out of bounds\n");
2064         return;
2065     }
2066     
2067     pmInfo->maps[mapType] = texID;
2068 }
2069 
2070 /*
2071  * Class:     com_sun_prism_es2_GLContext
2072  * Method:    nCreateES2MeshView
2073  * Signature: (JJ)J
2074  */
2075 JNIEXPORT jlong JNICALL Java_com_sun_prism_es2_GLContext_nCreateES2MeshView
2076   (JNIEnv *env, jclass class, jlong nativeCtxInfo, jlong nativeMeshInfo)
2077 {
2078     MeshViewInfo *meshViewInfo;
2079     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
2080     MeshInfo *meshInfo = (MeshInfo *) jlong_to_ptr(nativeMeshInfo);
2081     if ((ctxInfo == NULL) || (meshInfo == NULL)) {
2082         return 0;
2083     }
2084 
2085     /* allocate the structure */
2086     meshViewInfo = (MeshViewInfo *) malloc(sizeof (MeshViewInfo));
2087     if (meshViewInfo == NULL) {
2088         fprintf(stderr, "nCreateES2MeshView: Failed in malloc\n");
2089         return 0;
2090     }
2091 
2092     /* initialize the structure */
2093     meshViewInfo->meshInfo = meshInfo;
2094     meshViewInfo->phongMaterialInfo = NULL;
2095     meshViewInfo->cullEnable = GL_TRUE;
2096     meshViewInfo->cullMode = GL_BACK;
2097     meshViewInfo->fillMode = GL_FILL;
2098     meshViewInfo->ambientLightColor[0] = 0;
2099     meshViewInfo->ambientLightColor[1] = 0;
2100     meshViewInfo->ambientLightColor[2] = 0;
2101     meshViewInfo->pointLightIndex = 0;
2102     meshViewInfo->pointLightColor[0] = 0;
2103     meshViewInfo->pointLightColor[1] = 0;
2104     meshViewInfo->pointLightColor[2] = 0;
2105     meshViewInfo->pointLightPosition[0] = 0;
2106     meshViewInfo->pointLightPosition[1] = 0;
2107     meshViewInfo->pointLightPosition[2] = 0;
2108     meshViewInfo->pointLightWeight = 0;
2109 
2110     return ptr_to_jlong(meshViewInfo);
2111 }
2112 
2113 /*
2114  * Class:     com_sun_prism_es2_GLContext
2115  * Method:    nReleaseES2MeshView
2116  * Signature: (JJ)V
2117  */
2118 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nReleaseES2MeshView
2119   (JNIEnv *env, jclass class, jlong nativeCtxInfo, jlong nativeMeshInfo)
2120 {
2121     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
2122     MeshViewInfo *mvInfo = (MeshViewInfo *) jlong_to_ptr(nativeMeshInfo);
2123     if ((ctxInfo == NULL) || (mvInfo == NULL)) {
2124         return;
2125     }
2126 
2127     // TODO: 3D - Native clean up. Need to determine do we have to free what
2128     //            is held by ES2MeshViewInfo.
2129     free(mvInfo);
2130 }
2131 
2132 void setCullMode(ContextInfo *ctxInfo, MeshViewInfo *mvInfo) {
2133     if (mvInfo->cullEnable != ctxInfo->state.cullEnable) {
2134         if (mvInfo->cullEnable) {
2135             glEnable(GL_CULL_FACE);
2136         } else {
2137             glDisable(GL_CULL_FACE);
2138         }
2139         ctxInfo->state.cullEnable = mvInfo->cullEnable;
2140     }
2141 
2142     if (mvInfo->cullMode != ctxInfo->state.cullMode) {
2143         glCullFace(mvInfo->cullMode);
2144         ctxInfo->state.cullMode = mvInfo->cullMode;
2145     }
2146 }
2147 
2148 /*
2149  * Class:     com_sun_prism_es2_GLContext
2150  * Method:    nSetCullingMode
2151  * Signature: (JJI)V
2152  */
2153 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nSetCullingMode
2154   (JNIEnv *env, jclass class, jlong nativeCtxInfo, jlong nativeMeshViewInfo,
2155         jint cullMode)
2156 {
2157     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
2158     MeshViewInfo *meshViewInfo = (MeshViewInfo *) jlong_to_ptr(nativeMeshViewInfo);
2159     if ((ctxInfo == NULL) || (meshViewInfo == NULL)) {
2160         return;
2161     }
2162     switch (cullMode) {
2163         case com_sun_prism_es2_GLContext_GL_BACK:
2164             meshViewInfo->cullEnable = GL_TRUE;
2165             meshViewInfo->cullMode = GL_BACK;
2166             break;
2167         case com_sun_prism_es2_GLContext_GL_FRONT:
2168             meshViewInfo->cullEnable = GL_TRUE;
2169             meshViewInfo->cullMode = GL_FRONT;
2170             break;
2171         case com_sun_prism_es2_GLContext_GL_NONE:
2172             meshViewInfo->cullEnable = GL_FALSE;
2173             meshViewInfo->cullMode = GL_BACK;
2174             break;
2175     }
2176 }
2177 
2178 /*
2179  * Class:     com_sun_prism_es2_GLContext
2180  * Method:    nSetMaterial
2181  * Signature: (JJJ)V
2182  */
2183 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nSetMaterial
2184   (JNIEnv *env, jclass class, jlong nativeCtxInfo, jlong nativeMeshViewInfo,
2185         jlong nativePhongMaterialInfo)
2186 {
2187     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
2188     MeshViewInfo *mvInfo = (MeshViewInfo *) jlong_to_ptr(nativeMeshViewInfo);
2189     PhongMaterialInfo *pmInfo = (PhongMaterialInfo *) jlong_to_ptr(nativePhongMaterialInfo);
2190     if ((ctxInfo == NULL) || (mvInfo == NULL) || (pmInfo == NULL)) {
2191         return;
2192     }
2193     mvInfo->phongMaterialInfo = pmInfo;
2194 }
2195 
2196 void setPolyonMode(ContextInfo *ctxInfo, MeshViewInfo *mvInfo) {
2197 #ifndef IS_EGL
2198     if (mvInfo->fillMode != ctxInfo->state.fillMode) {
2199         glPolygonMode(GL_FRONT_AND_BACK, mvInfo->fillMode);
2200         ctxInfo->state.fillMode = mvInfo->fillMode;
2201     }
2202 #endif
2203 }
2204 
2205 /*
2206  * Class:     com_sun_prism_es2_GLContext
2207  * Method:    nSetWireframe
2208  * Signature: (JJZ)V
2209  */
2210 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nSetWireframe
2211   (JNIEnv *env, jclass class, jlong nativeCtxInfo, jlong nativeMeshViewInfo,
2212         jboolean wireframe)
2213 {
2214     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
2215     MeshViewInfo *meshViewInfo = (MeshViewInfo *) jlong_to_ptr(nativeMeshViewInfo);
2216     if ((ctxInfo == NULL) || (meshViewInfo == NULL)) {
2217         return;
2218     }
2219     if (wireframe) {
2220         meshViewInfo->fillMode = GL_LINE;
2221     } else {
2222         meshViewInfo->fillMode = GL_FILL;
2223     }
2224 }
2225 
2226 /*
2227  * Class:     com_sun_prism_es2_GLContext
2228  * Method:    nSetAmbientLight
2229  * Signature: (JJFFF)V
2230  */
2231 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nSetAmbientLight
2232   (JNIEnv *env, jclass class, jlong nativeCtxInfo, jlong nativeMeshViewInfo,
2233         jfloat r, jfloat g, jfloat b)
2234 {
2235     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
2236     MeshViewInfo *meshViewInfo = (MeshViewInfo *) jlong_to_ptr(nativeMeshViewInfo);
2237     if ((ctxInfo == NULL) || (meshViewInfo == NULL)) {
2238         return;
2239     }
2240     meshViewInfo->ambientLightColor[0] = r;
2241     meshViewInfo->ambientLightColor[1] = g;
2242     meshViewInfo->ambientLightColor[2] = b;
2243 }
2244 
2245 /*
2246  * Class:     com_sun_prism_es2_GLContext
2247  * Method:    nSetPointLight
2248  * Signature: (JJIFFFFFFF)V
2249  */
2250 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nSetPointLight
2251   (JNIEnv *env, jclass class, jlong nativeCtxInfo, jlong nativeMeshViewInfo,
2252         jint index, jfloat x, jfloat y, jfloat z, jfloat r, jfloat g, jfloat b, jfloat w)
2253 {
2254     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
2255     MeshViewInfo *meshViewInfo = (MeshViewInfo *) jlong_to_ptr(nativeMeshViewInfo);
2256     // NOTE: We only support up to 3 point lights at the present
2257     if ((ctxInfo == NULL) || (meshViewInfo == NULL) || (index < 0) || (index > 2)) {
2258         return;
2259     }
2260     meshViewInfo->pointLightIndex = index;
2261     meshViewInfo->pointLightPosition[0] = x;
2262     meshViewInfo->pointLightPosition[1] = y;
2263     meshViewInfo->pointLightPosition[2] = z;
2264     meshViewInfo->pointLightColor[0] = r;
2265     meshViewInfo->pointLightColor[1] = g;
2266     meshViewInfo->pointLightColor[2] = b;
2267     meshViewInfo->pointLightWeight = w;
2268 }
2269 
2270 /*
2271  * Class:     com_sun_prism_es2_GLContext
2272  * Method:    nRenderMeshView
2273  * Signature: (JJ)V
2274  */
2275 JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nRenderMeshView
2276   (JNIEnv *env, jclass class, jlong nativeCtxInfo, jlong nativeMeshViewInfo)
2277 {
2278     GLuint offset = 0;
2279     MeshInfo *mInfo;
2280     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
2281     MeshViewInfo *mvInfo = (MeshViewInfo *) jlong_to_ptr(nativeMeshViewInfo);
2282     if ((ctxInfo == NULL) || (mvInfo == NULL) ||
2283             (ctxInfo->glBindBuffer == NULL) ||
2284             (ctxInfo->glBufferData == NULL) ||
2285             (ctxInfo->glDisableVertexAttribArray == NULL) ||
2286             (ctxInfo->glEnableVertexAttribArray == NULL) ||
2287             (ctxInfo->glVertexAttribPointer == NULL)) {
2288         return;
2289     }
2290 
2291     if ((mvInfo->phongMaterialInfo == NULL) || (mvInfo->meshInfo == NULL)) {
2292         return;
2293     }
2294 
2295     setCullMode(ctxInfo, mvInfo);
2296     setPolyonMode(ctxInfo, mvInfo);
2297 
2298     // Draw triangles ...
2299     mInfo = mvInfo->meshInfo;
2300     ctxInfo->glBindBuffer(GL_ARRAY_BUFFER, mInfo->vboIDArray[MESH_VERTEXBUFFER]);
2301     ctxInfo->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mInfo->vboIDArray[MESH_INDEXBUFFER]);
2302 
2303     ctxInfo->glEnableVertexAttribArray(VC_3D_INDEX);
2304     ctxInfo->glEnableVertexAttribArray(TC_3D_INDEX);
2305     ctxInfo->glEnableVertexAttribArray(NC_3D_INDEX);
2306 
2307     ctxInfo->glVertexAttribPointer(VC_3D_INDEX, VC_3D_SIZE, GL_FLOAT, GL_FALSE,
2308             VERT_3D_STRIDE, (const void*) offset);
2309     offset += VC_3D_SIZE * sizeof(GLfloat);
2310     ctxInfo->glVertexAttribPointer(TC_3D_INDEX, TC_3D_SIZE, GL_FLOAT, GL_FALSE,
2311             VERT_3D_STRIDE, (const void*) offset);
2312     offset += TC_3D_SIZE * sizeof(GLfloat);
2313     ctxInfo->glVertexAttribPointer(NC_3D_INDEX, NC_3D_SIZE, GL_FLOAT, GL_FALSE,
2314             VERT_3D_STRIDE, (const void*) offset);
2315 
2316     glDrawElements(GL_TRIANGLES, mvInfo->meshInfo->indexBufferSize,
2317             mvInfo->meshInfo->indexBufferType, 0);
2318 
2319     // Reset states
2320     ctxInfo->glDisableVertexAttribArray(VC_3D_INDEX);
2321     ctxInfo->glDisableVertexAttribArray(NC_3D_INDEX);
2322     ctxInfo->glDisableVertexAttribArray(TC_3D_INDEX);
2323     ctxInfo->glBindBuffer(GL_ARRAY_BUFFER, 0);
2324     ctxInfo->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
2325 }
2326