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