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