1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <ui/FramebufferNativeWindow.h> 18 #include <ui/PixelFormat.h> 19 20 #include <system/window.h> 21 22 #include <sys/types.h> 23 #include <sys/resource.h> 24 #include <sched.h> 25 26 #include <cutils/properties.h> 27 28 #include <GLES/gl.h> 29 #include <GLES/glext.h> 30 #include <GLES2/gl2.h> 31 #include <GLES2/gl2ext.h> 32 33 #include <string.h> 34 35 #include "rsdCore.h" 36 #include "rsdGL.h" 37 38 #include <malloc.h> 39 #include "rsContext.h" 40 #include "rsDevice.h" 41 #include "rsdShaderCache.h" 42 #include "rsdVertexArray.h" 43 #include "rsdFrameBufferObj.h" 44 45 #include <gui/Surface.h> 46 47 using namespace android; 48 using namespace android::renderscript; 49 50 static int32_t gGLContextCount = 0; 51 52 static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) { 53 struct EGLUtils { 54 static const char *strerror(EGLint err) { 55 switch (err){ 56 case EGL_SUCCESS: return "EGL_SUCCESS"; 57 case EGL_NOT_INITIALIZED: return "EGL_NOT_INITIALIZED"; 58 case EGL_BAD_ACCESS: return "EGL_BAD_ACCESS"; 59 case EGL_BAD_ALLOC: return "EGL_BAD_ALLOC"; 60 case EGL_BAD_ATTRIBUTE: return "EGL_BAD_ATTRIBUTE"; 61 case EGL_BAD_CONFIG: return "EGL_BAD_CONFIG"; 62 case EGL_BAD_CONTEXT: return "EGL_BAD_CONTEXT"; 63 case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE"; 64 case EGL_BAD_DISPLAY: return "EGL_BAD_DISPLAY"; 65 case EGL_BAD_MATCH: return "EGL_BAD_MATCH"; 66 case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP"; 67 case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW"; 68 case EGL_BAD_PARAMETER: return "EGL_BAD_PARAMETER"; 69 case EGL_BAD_SURFACE: return "EGL_BAD_SURFACE"; 70 case EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST"; 71 default: return "UNKNOWN"; 72 } 73 } 74 }; 75 76 if (returnVal != EGL_TRUE) { 77 fprintf(stderr, "%s() returned %d\n", op, returnVal); 78 } 79 80 for (EGLint error = eglGetError(); error != EGL_SUCCESS; error 81 = eglGetError()) { 82 fprintf(stderr, "after %s() eglError %s (0x%x)\n", op, EGLUtils::strerror(error), 83 error); 84 } 85 } 86 87 static void printEGLConfiguration(EGLDisplay dpy, EGLConfig config) { 88 89 #define X(VAL) {VAL, #VAL} 90 struct {EGLint attribute; const char* name;} names[] = { 91 X(EGL_BUFFER_SIZE), 92 X(EGL_ALPHA_SIZE), 93 X(EGL_BLUE_SIZE), 94 X(EGL_GREEN_SIZE), 95 X(EGL_RED_SIZE), 96 X(EGL_DEPTH_SIZE), 97 X(EGL_STENCIL_SIZE), 98 X(EGL_CONFIG_CAVEAT), 99 X(EGL_CONFIG_ID), 100 X(EGL_LEVEL), 101 X(EGL_MAX_PBUFFER_HEIGHT), 102 X(EGL_MAX_PBUFFER_PIXELS), 103 X(EGL_MAX_PBUFFER_WIDTH), 104 X(EGL_NATIVE_RENDERABLE), 105 X(EGL_NATIVE_VISUAL_ID), 106 X(EGL_NATIVE_VISUAL_TYPE), 107 X(EGL_SAMPLES), 108 X(EGL_SAMPLE_BUFFERS), 109 X(EGL_SURFACE_TYPE), 110 X(EGL_TRANSPARENT_TYPE), 111 X(EGL_TRANSPARENT_RED_VALUE), 112 X(EGL_TRANSPARENT_GREEN_VALUE), 113 X(EGL_TRANSPARENT_BLUE_VALUE), 114 X(EGL_BIND_TO_TEXTURE_RGB), 115 X(EGL_BIND_TO_TEXTURE_RGBA), 116 X(EGL_MIN_SWAP_INTERVAL), 117 X(EGL_MAX_SWAP_INTERVAL), 118 X(EGL_LUMINANCE_SIZE), 119 X(EGL_ALPHA_MASK_SIZE), 120 X(EGL_COLOR_BUFFER_TYPE), 121 X(EGL_RENDERABLE_TYPE), 122 X(EGL_CONFORMANT), 123 }; 124 #undef X 125 126 for (size_t j = 0; j < sizeof(names) / sizeof(names[0]); j++) { 127 EGLint value = -1; 128 EGLBoolean returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute, &value); 129 if (returnVal) { 130 ALOGV(" %s: %d (0x%x)", names[j].name, value, value); 131 } 132 } 133 } 134 135 static void DumpDebug(RsdHal *dc) { 136 ALOGE(" EGL ver %i %i", dc->gl.egl.majorVersion, dc->gl.egl.minorVersion); 137 ALOGE(" EGL context %p surface %p, Display=%p", dc->gl.egl.context, dc->gl.egl.surface, 138 dc->gl.egl.display); 139 ALOGE(" GL vendor: %s", dc->gl.gl.vendor); 140 ALOGE(" GL renderer: %s", dc->gl.gl.renderer); 141 ALOGE(" GL Version: %s", dc->gl.gl.version); 142 ALOGE(" GL Extensions: %s", dc->gl.gl.extensions); 143 ALOGE(" GL int Versions %i %i", dc->gl.gl.majorVersion, dc->gl.gl.minorVersion); 144 145 ALOGV("MAX Textures %i, %i %i", dc->gl.gl.maxVertexTextureUnits, 146 dc->gl.gl.maxFragmentTextureImageUnits, dc->gl.gl.maxTextureImageUnits); 147 ALOGV("MAX Attribs %i", dc->gl.gl.maxVertexAttribs); 148 ALOGV("MAX Uniforms %i, %i", dc->gl.gl.maxVertexUniformVectors, 149 dc->gl.gl.maxFragmentUniformVectors); 150 ALOGV("MAX Varyings %i", dc->gl.gl.maxVaryingVectors); 151 } 152 153 void rsdGLShutdown(const Context *rsc) { 154 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 155 156 rsdGLSetSurface(rsc, 0, 0, NULL); 157 dc->gl.shaderCache->cleanupAll(); 158 delete dc->gl.shaderCache; 159 delete dc->gl.vertexArrayState; 160 161 if (dc->gl.egl.context != EGL_NO_CONTEXT) { 162 RSD_CALL_GL(eglMakeCurrent, dc->gl.egl.display, 163 EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 164 RSD_CALL_GL(eglDestroySurface, dc->gl.egl.display, dc->gl.egl.surfaceDefault); 165 if (dc->gl.egl.surface != EGL_NO_SURFACE) { 166 RSD_CALL_GL(eglDestroySurface, dc->gl.egl.display, dc->gl.egl.surface); 167 } 168 RSD_CALL_GL(eglDestroyContext, dc->gl.egl.display, dc->gl.egl.context); 169 checkEglError("eglDestroyContext"); 170 } 171 172 gGLContextCount--; 173 if (!gGLContextCount) { 174 RSD_CALL_GL(eglTerminate, dc->gl.egl.display); 175 } 176 } 177 178 void getConfigData(const Context *rsc, 179 EGLint *configAttribs, size_t configAttribsLen, 180 uint32_t numSamples) { 181 memset(configAttribs, 0, configAttribsLen*sizeof(*configAttribs)); 182 183 EGLint *configAttribsPtr = configAttribs; 184 185 configAttribsPtr[0] = EGL_SURFACE_TYPE; 186 configAttribsPtr[1] = EGL_WINDOW_BIT; 187 configAttribsPtr += 2; 188 189 configAttribsPtr[0] = EGL_RENDERABLE_TYPE; 190 configAttribsPtr[1] = EGL_OPENGL_ES2_BIT; 191 configAttribsPtr += 2; 192 193 configAttribsPtr[0] = EGL_RED_SIZE; 194 configAttribsPtr[1] = 8; 195 configAttribsPtr += 2; 196 197 configAttribsPtr[0] = EGL_GREEN_SIZE; 198 configAttribsPtr[1] = 8; 199 configAttribsPtr += 2; 200 201 configAttribsPtr[0] = EGL_BLUE_SIZE; 202 configAttribsPtr[1] = 8; 203 configAttribsPtr += 2; 204 205 if (rsc->mUserSurfaceConfig.alphaMin > 0) { 206 configAttribsPtr[0] = EGL_ALPHA_SIZE; 207 configAttribsPtr[1] = rsc->mUserSurfaceConfig.alphaMin; 208 configAttribsPtr += 2; 209 } 210 211 if (rsc->mUserSurfaceConfig.depthMin > 0) { 212 configAttribsPtr[0] = EGL_DEPTH_SIZE; 213 configAttribsPtr[1] = rsc->mUserSurfaceConfig.depthMin; 214 configAttribsPtr += 2; 215 } 216 217 if (rsc->mDev->mForceSW) { 218 configAttribsPtr[0] = EGL_CONFIG_CAVEAT; 219 configAttribsPtr[1] = EGL_SLOW_CONFIG; 220 configAttribsPtr += 2; 221 } 222 223 if (numSamples > 1) { 224 configAttribsPtr[0] = EGL_SAMPLE_BUFFERS; 225 configAttribsPtr[1] = 1; 226 configAttribsPtr[2] = EGL_SAMPLES; 227 configAttribsPtr[3] = numSamples; 228 configAttribsPtr += 4; 229 } 230 231 configAttribsPtr[0] = EGL_NONE; 232 rsAssert(configAttribsPtr < (configAttribs + configAttribsLen)); 233 } 234 235 bool rsdGLInit(const Context *rsc) { 236 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 237 238 dc->gl.egl.numConfigs = -1; 239 240 EGLint configAttribs[128]; 241 EGLint context_attribs2[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; 242 243 ALOGV("%p initEGL start", rsc); 244 rsc->setWatchdogGL("eglGetDisplay", __LINE__, __FILE__); 245 dc->gl.egl.display = eglGetDisplay(EGL_DEFAULT_DISPLAY); 246 checkEglError("eglGetDisplay"); 247 248 RSD_CALL_GL(eglInitialize, dc->gl.egl.display, 249 &dc->gl.egl.majorVersion, &dc->gl.egl.minorVersion); 250 checkEglError("eglInitialize"); 251 252 EGLBoolean ret; 253 254 EGLint numConfigs = -1, n = 0; 255 rsc->setWatchdogGL("eglChooseConfig", __LINE__, __FILE__); 256 257 // Try minding a multisample config that matches the user request 258 uint32_t minSample = rsc->mUserSurfaceConfig.samplesMin; 259 uint32_t prefSample = rsc->mUserSurfaceConfig.samplesPref; 260 for (uint32_t sampleCount = prefSample; sampleCount >= minSample; sampleCount--) { 261 getConfigData(rsc, configAttribs, (sizeof(configAttribs) / sizeof(EGLint)), sampleCount); 262 ret = eglChooseConfig(dc->gl.egl.display, configAttribs, 0, 0, &numConfigs); 263 checkEglError("eglGetConfigs", ret); 264 if (numConfigs > 0) { 265 break; 266 } 267 } 268 269 if (numConfigs) { 270 EGLConfig* const configs = new EGLConfig[numConfigs]; 271 272 rsc->setWatchdogGL("eglChooseConfig", __LINE__, __FILE__); 273 ret = eglChooseConfig(dc->gl.egl.display, 274 configAttribs, configs, numConfigs, &n); 275 if (!ret || !n) { 276 checkEglError("eglChooseConfig", ret); 277 ALOGE("%p, couldn't find an EGLConfig matching the screen format\n", rsc); 278 } 279 280 // The first config is guaranteed to over-satisfy the constraints 281 dc->gl.egl.config = configs[0]; 282 283 // go through the list and skip configs that over-satisfy our needs 284 for (int i=0 ; i<n ; i++) { 285 if (rsc->mUserSurfaceConfig.alphaMin <= 0) { 286 EGLint alphaSize; 287 eglGetConfigAttrib(dc->gl.egl.display, 288 configs[i], EGL_ALPHA_SIZE, &alphaSize); 289 if (alphaSize > 0) { 290 continue; 291 } 292 } 293 294 if (rsc->mUserSurfaceConfig.depthMin <= 0) { 295 EGLint depthSize; 296 eglGetConfigAttrib(dc->gl.egl.display, 297 configs[i], EGL_DEPTH_SIZE, &depthSize); 298 if (depthSize > 0) { 299 continue; 300 } 301 } 302 303 // Found one! 304 dc->gl.egl.config = configs[i]; 305 break; 306 } 307 308 delete [] configs; 309 } 310 311 //if (props.mLogVisual) { 312 if (0) { 313 printEGLConfiguration(dc->gl.egl.display, dc->gl.egl.config); 314 } 315 //} 316 317 rsc->setWatchdogGL("eglCreateContext", __LINE__, __FILE__); 318 dc->gl.egl.context = eglCreateContext(dc->gl.egl.display, dc->gl.egl.config, 319 EGL_NO_CONTEXT, context_attribs2); 320 checkEglError("eglCreateContext"); 321 if (dc->gl.egl.context == EGL_NO_CONTEXT) { 322 ALOGE("%p, eglCreateContext returned EGL_NO_CONTEXT", rsc); 323 rsc->setWatchdogGL(NULL, 0, NULL); 324 return false; 325 } 326 gGLContextCount++; 327 328 EGLint pbuffer_attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE }; 329 rsc->setWatchdogGL("eglCreatePbufferSurface", __LINE__, __FILE__); 330 dc->gl.egl.surfaceDefault = eglCreatePbufferSurface(dc->gl.egl.display, dc->gl.egl.config, 331 pbuffer_attribs); 332 checkEglError("eglCreatePbufferSurface"); 333 if (dc->gl.egl.surfaceDefault == EGL_NO_SURFACE) { 334 ALOGE("eglCreatePbufferSurface returned EGL_NO_SURFACE"); 335 rsdGLShutdown(rsc); 336 rsc->setWatchdogGL(NULL, 0, NULL); 337 return false; 338 } 339 340 rsc->setWatchdogGL("eglMakeCurrent", __LINE__, __FILE__); 341 ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surfaceDefault, 342 dc->gl.egl.surfaceDefault, dc->gl.egl.context); 343 if (ret == EGL_FALSE) { 344 ALOGE("eglMakeCurrent returned EGL_FALSE"); 345 checkEglError("eglMakeCurrent", ret); 346 rsdGLShutdown(rsc); 347 rsc->setWatchdogGL(NULL, 0, NULL); 348 return false; 349 } 350 351 dc->gl.gl.version = glGetString(GL_VERSION); 352 dc->gl.gl.vendor = glGetString(GL_VENDOR); 353 dc->gl.gl.renderer = glGetString(GL_RENDERER); 354 dc->gl.gl.extensions = glGetString(GL_EXTENSIONS); 355 356 //ALOGV("EGL Version %i %i", mEGL.mMajorVersion, mEGL.mMinorVersion); 357 //ALOGV("GL Version %s", mGL.mVersion); 358 //ALOGV("GL Vendor %s", mGL.mVendor); 359 //ALOGV("GL Renderer %s", mGL.mRenderer); 360 //ALOGV("GL Extensions %s", mGL.mExtensions); 361 362 const char *verptr = NULL; 363 if (strlen((const char *)dc->gl.gl.version) > 9) { 364 if (!memcmp(dc->gl.gl.version, "OpenGL ES-CM", 12)) { 365 verptr = (const char *)dc->gl.gl.version + 12; 366 } 367 if (!memcmp(dc->gl.gl.version, "OpenGL ES ", 10)) { 368 verptr = (const char *)dc->gl.gl.version + 9; 369 } 370 } 371 372 if (!verptr) { 373 ALOGE("Error, OpenGL ES Lite not supported"); 374 rsdGLShutdown(rsc); 375 rsc->setWatchdogGL(NULL, 0, NULL); 376 return false; 377 } else { 378 sscanf(verptr, " %i.%i", &dc->gl.gl.majorVersion, &dc->gl.gl.minorVersion); 379 } 380 381 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &dc->gl.gl.maxVertexAttribs); 382 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &dc->gl.gl.maxVertexUniformVectors); 383 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &dc->gl.gl.maxVertexTextureUnits); 384 385 glGetIntegerv(GL_MAX_VARYING_VECTORS, &dc->gl.gl.maxVaryingVectors); 386 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &dc->gl.gl.maxTextureImageUnits); 387 388 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &dc->gl.gl.maxFragmentTextureImageUnits); 389 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &dc->gl.gl.maxFragmentUniformVectors); 390 391 dc->gl.gl.OES_texture_npot = NULL != strstr((const char *)dc->gl.gl.extensions, 392 "GL_OES_texture_npot"); 393 dc->gl.gl.IMG_texture_npot = NULL != strstr((const char *)dc->gl.gl.extensions, 394 "GL_IMG_texture_npot"); 395 dc->gl.gl.NV_texture_npot_2D_mipmap = NULL != strstr((const char *)dc->gl.gl.extensions, 396 "GL_NV_texture_npot_2D_mipmap"); 397 dc->gl.gl.EXT_texture_max_aniso = 1.0f; 398 bool hasAniso = NULL != strstr((const char *)dc->gl.gl.extensions, 399 "GL_EXT_texture_filter_anisotropic"); 400 if (hasAniso) { 401 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &dc->gl.gl.EXT_texture_max_aniso); 402 } 403 404 if (0) { 405 DumpDebug(dc); 406 } 407 408 dc->gl.shaderCache = new RsdShaderCache(); 409 dc->gl.vertexArrayState = new RsdVertexArrayState(); 410 dc->gl.vertexArrayState->init(dc->gl.gl.maxVertexAttribs); 411 dc->gl.currentFrameBuffer = NULL; 412 dc->mHasGraphics = true; 413 414 ALOGV("%p initGLThread end", rsc); 415 rsc->setWatchdogGL(NULL, 0, NULL); 416 return true; 417 } 418 419 420 bool rsdGLSetInternalSurface(const Context *rsc, RsNativeWindow sur) { 421 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 422 423 EGLBoolean ret; 424 if (dc->gl.egl.surface != NULL) { 425 rsc->setWatchdogGL("eglMakeCurrent", __LINE__, __FILE__); 426 ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surfaceDefault, 427 dc->gl.egl.surfaceDefault, dc->gl.egl.context); 428 checkEglError("eglMakeCurrent", ret); 429 430 rsc->setWatchdogGL("eglDestroySurface", __LINE__, __FILE__); 431 ret = eglDestroySurface(dc->gl.egl.display, dc->gl.egl.surface); 432 checkEglError("eglDestroySurface", ret); 433 434 dc->gl.egl.surface = NULL; 435 } 436 437 if (dc->gl.currentWndSurface != NULL) { 438 dc->gl.currentWndSurface->decStrong(NULL); 439 } 440 441 dc->gl.currentWndSurface = (ANativeWindow *)sur; 442 if (dc->gl.currentWndSurface != NULL) { 443 dc->gl.currentWndSurface->incStrong(NULL); 444 445 rsc->setWatchdogGL("eglCreateWindowSurface", __LINE__, __FILE__); 446 dc->gl.egl.surface = eglCreateWindowSurface(dc->gl.egl.display, dc->gl.egl.config, 447 dc->gl.currentWndSurface, NULL); 448 checkEglError("eglCreateWindowSurface"); 449 if (dc->gl.egl.surface == EGL_NO_SURFACE) { 450 ALOGE("eglCreateWindowSurface returned EGL_NO_SURFACE"); 451 } 452 453 rsc->setWatchdogGL("eglMakeCurrent", __LINE__, __FILE__); 454 ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surface, 455 dc->gl.egl.surface, dc->gl.egl.context); 456 checkEglError("eglMakeCurrent", ret); 457 } 458 rsc->setWatchdogGL(NULL, 0, NULL); 459 return true; 460 } 461 462 bool rsdGLSetSurface(const Context *rsc, uint32_t w, uint32_t h, RsNativeWindow sur) { 463 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 464 465 if (dc->gl.wndSurface != NULL) { 466 dc->gl.wndSurface->decStrong(NULL); 467 dc->gl.wndSurface = NULL; 468 } 469 if(w && h) { 470 // WAR: Some drivers fail to handle 0 size surfaces correctly. Use the 471 // pbuffer to avoid this pitfall. 472 dc->gl.wndSurface = (ANativeWindow *)sur; 473 if (dc->gl.wndSurface != NULL) { 474 dc->gl.wndSurface->incStrong(NULL); 475 } 476 } 477 478 return rsdGLSetInternalSurface(rsc, sur); 479 } 480 481 void rsdGLSwap(const android::renderscript::Context *rsc) { 482 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 483 RSD_CALL_GL(eglSwapBuffers, dc->gl.egl.display, dc->gl.egl.surface); 484 } 485 486 void rsdGLSetPriority(const Context *rsc, int32_t priority) { 487 if (priority > 0) { 488 // Mark context as low priority. 489 ALOGV("low pri"); 490 } else { 491 ALOGV("normal pri"); 492 } 493 } 494 495 void rsdGLCheckError(const android::renderscript::Context *rsc, 496 const char *msg, bool isFatal) { 497 GLenum err = glGetError(); 498 if (err != GL_NO_ERROR) { 499 char buf[1024]; 500 snprintf(buf, sizeof(buf), "GL Error = 0x%08x, from: %s", err, msg); 501 502 if (isFatal) { 503 rsc->setError(RS_ERROR_FATAL_DRIVER, buf); 504 } else { 505 switch (err) { 506 case GL_OUT_OF_MEMORY: 507 rsc->setError(RS_ERROR_OUT_OF_MEMORY, buf); 508 break; 509 default: 510 rsc->setError(RS_ERROR_DRIVER, buf); 511 break; 512 } 513 } 514 515 ALOGE("%p, %s", rsc, buf); 516 } 517 518 } 519 520 void rsdGLClearColor(const android::renderscript::Context *rsc, 521 float r, float g, float b, float a) { 522 RSD_CALL_GL(glClearColor, r, g, b, a); 523 RSD_CALL_GL(glClear, GL_COLOR_BUFFER_BIT); 524 } 525 526 void rsdGLClearDepth(const android::renderscript::Context *rsc, float v) { 527 RSD_CALL_GL(glClearDepthf, v); 528 RSD_CALL_GL(glClear, GL_DEPTH_BUFFER_BIT); 529 } 530 531 void rsdGLFinish(const android::renderscript::Context *rsc) { 532 RSD_CALL_GL(glFinish); 533 } 534 535 void rsdGLDrawQuadTexCoords(const android::renderscript::Context *rsc, 536 float x1, float y1, float z1, float u1, float v1, 537 float x2, float y2, float z2, float u2, float v2, 538 float x3, float y3, float z3, float u3, float v3, 539 float x4, float y4, float z4, float u4, float v4) { 540 541 float vtx[] = {x1,y1,z1, x2,y2,z2, x3,y3,z3, x4,y4,z4}; 542 const float tex[] = {u1,v1, u2,v2, u3,v3, u4,v4}; 543 544 RsdVertexArray::Attrib attribs[2]; 545 attribs[0].set(GL_FLOAT, 3, 12, false, (uint32_t)vtx, "ATTRIB_position"); 546 attribs[1].set(GL_FLOAT, 2, 8, false, (uint32_t)tex, "ATTRIB_texture0"); 547 548 RsdVertexArray va(attribs, 2); 549 va.setup(rsc); 550 551 RSD_CALL_GL(glDrawArrays, GL_TRIANGLE_FAN, 0, 4); 552 } 553