rsdGL.cpp revision b322033c13487a174bb9c26466e9684d1ff4de8d
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/SurfaceTextureClient.h> 46#include <gui/DummyConsumer.h> 47 48using namespace android; 49using namespace android::renderscript; 50 51static int32_t gGLContextCount = 0; 52 53static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) { 54 struct EGLUtils { 55 static const char *strerror(EGLint err) { 56 switch (err){ 57 case EGL_SUCCESS: return "EGL_SUCCESS"; 58 case EGL_NOT_INITIALIZED: return "EGL_NOT_INITIALIZED"; 59 case EGL_BAD_ACCESS: return "EGL_BAD_ACCESS"; 60 case EGL_BAD_ALLOC: return "EGL_BAD_ALLOC"; 61 case EGL_BAD_ATTRIBUTE: return "EGL_BAD_ATTRIBUTE"; 62 case EGL_BAD_CONFIG: return "EGL_BAD_CONFIG"; 63 case EGL_BAD_CONTEXT: return "EGL_BAD_CONTEXT"; 64 case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE"; 65 case EGL_BAD_DISPLAY: return "EGL_BAD_DISPLAY"; 66 case EGL_BAD_MATCH: return "EGL_BAD_MATCH"; 67 case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP"; 68 case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW"; 69 case EGL_BAD_PARAMETER: return "EGL_BAD_PARAMETER"; 70 case EGL_BAD_SURFACE: return "EGL_BAD_SURFACE"; 71 case EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST"; 72 default: return "UNKNOWN"; 73 } 74 } 75 }; 76 77 if (returnVal != EGL_TRUE) { 78 fprintf(stderr, "%s() returned %d\n", op, returnVal); 79 } 80 81 for (EGLint error = eglGetError(); error != EGL_SUCCESS; error 82 = eglGetError()) { 83 fprintf(stderr, "after %s() eglError %s (0x%x)\n", op, EGLUtils::strerror(error), 84 error); 85 } 86} 87 88static void printEGLConfiguration(EGLDisplay dpy, EGLConfig config) { 89 90#define X(VAL) {VAL, #VAL} 91 struct {EGLint attribute; const char* name;} names[] = { 92 X(EGL_BUFFER_SIZE), 93 X(EGL_ALPHA_SIZE), 94 X(EGL_BLUE_SIZE), 95 X(EGL_GREEN_SIZE), 96 X(EGL_RED_SIZE), 97 X(EGL_DEPTH_SIZE), 98 X(EGL_STENCIL_SIZE), 99 X(EGL_CONFIG_CAVEAT), 100 X(EGL_CONFIG_ID), 101 X(EGL_LEVEL), 102 X(EGL_MAX_PBUFFER_HEIGHT), 103 X(EGL_MAX_PBUFFER_PIXELS), 104 X(EGL_MAX_PBUFFER_WIDTH), 105 X(EGL_NATIVE_RENDERABLE), 106 X(EGL_NATIVE_VISUAL_ID), 107 X(EGL_NATIVE_VISUAL_TYPE), 108 X(EGL_SAMPLES), 109 X(EGL_SAMPLE_BUFFERS), 110 X(EGL_SURFACE_TYPE), 111 X(EGL_TRANSPARENT_TYPE), 112 X(EGL_TRANSPARENT_RED_VALUE), 113 X(EGL_TRANSPARENT_GREEN_VALUE), 114 X(EGL_TRANSPARENT_BLUE_VALUE), 115 X(EGL_BIND_TO_TEXTURE_RGB), 116 X(EGL_BIND_TO_TEXTURE_RGBA), 117 X(EGL_MIN_SWAP_INTERVAL), 118 X(EGL_MAX_SWAP_INTERVAL), 119 X(EGL_LUMINANCE_SIZE), 120 X(EGL_ALPHA_MASK_SIZE), 121 X(EGL_COLOR_BUFFER_TYPE), 122 X(EGL_RENDERABLE_TYPE), 123 X(EGL_CONFORMANT), 124 }; 125#undef X 126 127 for (size_t j = 0; j < sizeof(names) / sizeof(names[0]); j++) { 128 EGLint value = -1; 129 EGLBoolean returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute, &value); 130 if (returnVal) { 131 ALOGV(" %s: %d (0x%x)", names[j].name, value, value); 132 } 133 } 134} 135 136static void DumpDebug(RsdHal *dc) { 137 ALOGE(" EGL ver %i %i", dc->gl.egl.majorVersion, dc->gl.egl.minorVersion); 138 ALOGE(" EGL context %p surface %p, Display=%p", dc->gl.egl.context, dc->gl.egl.surface, 139 dc->gl.egl.display); 140 ALOGE(" GL vendor: %s", dc->gl.gl.vendor); 141 ALOGE(" GL renderer: %s", dc->gl.gl.renderer); 142 ALOGE(" GL Version: %s", dc->gl.gl.version); 143 ALOGE(" GL Extensions: %s", dc->gl.gl.extensions); 144 ALOGE(" GL int Versions %i %i", dc->gl.gl.majorVersion, dc->gl.gl.minorVersion); 145 146 ALOGV("MAX Textures %i, %i %i", dc->gl.gl.maxVertexTextureUnits, 147 dc->gl.gl.maxFragmentTextureImageUnits, dc->gl.gl.maxTextureImageUnits); 148 ALOGV("MAX Attribs %i", dc->gl.gl.maxVertexAttribs); 149 ALOGV("MAX Uniforms %i, %i", dc->gl.gl.maxVertexUniformVectors, 150 dc->gl.gl.maxFragmentUniformVectors); 151 ALOGV("MAX Varyings %i", dc->gl.gl.maxVaryingVectors); 152} 153 154void rsdGLShutdown(const Context *rsc) { 155 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 156 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 178void 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 235bool 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 eglSwapInterval(dc->gl.egl.display, 0); 270 271 if (numConfigs) { 272 EGLConfig* const configs = new EGLConfig[numConfigs]; 273 274 rsc->setWatchdogGL("eglChooseConfig", __LINE__, __FILE__); 275 ret = eglChooseConfig(dc->gl.egl.display, 276 configAttribs, configs, numConfigs, &n); 277 if (!ret || !n) { 278 checkEglError("eglChooseConfig", ret); 279 ALOGE("%p, couldn't find an EGLConfig matching the screen format\n", rsc); 280 } 281 282 // The first config is guaranteed to over-satisfy the constraints 283 dc->gl.egl.config = configs[0]; 284 285 // go through the list and skip configs that over-satisfy our needs 286 for (int i=0 ; i<n ; i++) { 287 if (rsc->mUserSurfaceConfig.alphaMin <= 0) { 288 EGLint alphaSize; 289 eglGetConfigAttrib(dc->gl.egl.display, 290 configs[i], EGL_ALPHA_SIZE, &alphaSize); 291 if (alphaSize > 0) { 292 continue; 293 } 294 } 295 296 if (rsc->mUserSurfaceConfig.depthMin <= 0) { 297 EGLint depthSize; 298 eglGetConfigAttrib(dc->gl.egl.display, 299 configs[i], EGL_DEPTH_SIZE, &depthSize); 300 if (depthSize > 0) { 301 continue; 302 } 303 } 304 305 // Found one! 306 dc->gl.egl.config = configs[i]; 307 break; 308 } 309 310 delete [] configs; 311 } 312 313 //if (props.mLogVisual) { 314 if (0) { 315 printEGLConfiguration(dc->gl.egl.display, dc->gl.egl.config); 316 } 317 //} 318 319 rsc->setWatchdogGL("eglCreateContext", __LINE__, __FILE__); 320 dc->gl.egl.context = eglCreateContext(dc->gl.egl.display, dc->gl.egl.config, 321 EGL_NO_CONTEXT, context_attribs2); 322 checkEglError("eglCreateContext"); 323 if (dc->gl.egl.context == EGL_NO_CONTEXT) { 324 ALOGE("%p, eglCreateContext returned EGL_NO_CONTEXT", rsc); 325 rsc->setWatchdogGL(NULL, 0, NULL); 326 return false; 327 } 328 gGLContextCount++; 329 330 // Create a BufferQueue with a fake consumer 331 sp<BufferQueue> bq = new BufferQueue(); 332 bq->consumerConnect(new DummyConsumer()); 333 sp<SurfaceTextureClient> stc(new SurfaceTextureClient(static_cast<sp<ISurfaceTexture> >(bq))); 334 335 dc->gl.egl.surfaceDefault = eglCreateWindowSurface(dc->gl.egl.display, dc->gl.egl.config, 336 static_cast<ANativeWindow*>(stc.get()), 337 NULL); 338 339 checkEglError("eglCreateWindowSurface"); 340 if (dc->gl.egl.surfaceDefault == EGL_NO_SURFACE) { 341 ALOGE("eglCreateWindowSurface returned EGL_NO_SURFACE"); 342 rsdGLShutdown(rsc); 343 rsc->setWatchdogGL(NULL, 0, NULL); 344 return false; 345 } 346 347 rsc->setWatchdogGL("eglMakeCurrent", __LINE__, __FILE__); 348 ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surfaceDefault, 349 dc->gl.egl.surfaceDefault, dc->gl.egl.context); 350 if (ret == EGL_FALSE) { 351 ALOGE("eglMakeCurrent returned EGL_FALSE"); 352 checkEglError("eglMakeCurrent", ret); 353 rsdGLShutdown(rsc); 354 rsc->setWatchdogGL(NULL, 0, NULL); 355 return false; 356 } 357 358 dc->gl.gl.version = glGetString(GL_VERSION); 359 dc->gl.gl.vendor = glGetString(GL_VENDOR); 360 dc->gl.gl.renderer = glGetString(GL_RENDERER); 361 dc->gl.gl.extensions = glGetString(GL_EXTENSIONS); 362 363 //ALOGV("EGL Version %i %i", mEGL.mMajorVersion, mEGL.mMinorVersion); 364 //ALOGV("GL Version %s", mGL.mVersion); 365 //ALOGV("GL Vendor %s", mGL.mVendor); 366 //ALOGV("GL Renderer %s", mGL.mRenderer); 367 //ALOGV("GL Extensions %s", mGL.mExtensions); 368 369 const char *verptr = NULL; 370 if (strlen((const char *)dc->gl.gl.version) > 9) { 371 if (!memcmp(dc->gl.gl.version, "OpenGL ES-CM", 12)) { 372 verptr = (const char *)dc->gl.gl.version + 12; 373 } 374 if (!memcmp(dc->gl.gl.version, "OpenGL ES ", 10)) { 375 verptr = (const char *)dc->gl.gl.version + 9; 376 } 377 } 378 379 if (!verptr) { 380 ALOGE("Error, OpenGL ES Lite not supported"); 381 rsdGLShutdown(rsc); 382 rsc->setWatchdogGL(NULL, 0, NULL); 383 return false; 384 } else { 385 sscanf(verptr, " %i.%i", &dc->gl.gl.majorVersion, &dc->gl.gl.minorVersion); 386 } 387 388 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &dc->gl.gl.maxVertexAttribs); 389 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &dc->gl.gl.maxVertexUniformVectors); 390 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &dc->gl.gl.maxVertexTextureUnits); 391 392 glGetIntegerv(GL_MAX_VARYING_VECTORS, &dc->gl.gl.maxVaryingVectors); 393 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &dc->gl.gl.maxTextureImageUnits); 394 395 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &dc->gl.gl.maxFragmentTextureImageUnits); 396 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &dc->gl.gl.maxFragmentUniformVectors); 397 398 dc->gl.gl.OES_texture_npot = NULL != strstr((const char *)dc->gl.gl.extensions, 399 "GL_OES_texture_npot"); 400 dc->gl.gl.IMG_texture_npot = NULL != strstr((const char *)dc->gl.gl.extensions, 401 "GL_IMG_texture_npot"); 402 dc->gl.gl.NV_texture_npot_2D_mipmap = NULL != strstr((const char *)dc->gl.gl.extensions, 403 "GL_NV_texture_npot_2D_mipmap"); 404 dc->gl.gl.EXT_texture_max_aniso = 1.0f; 405 bool hasAniso = NULL != strstr((const char *)dc->gl.gl.extensions, 406 "GL_EXT_texture_filter_anisotropic"); 407 if (hasAniso) { 408 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &dc->gl.gl.EXT_texture_max_aniso); 409 } 410 411 if (0) { 412 DumpDebug(dc); 413 } 414 415 dc->gl.shaderCache = new RsdShaderCache(); 416 dc->gl.vertexArrayState = new RsdVertexArrayState(); 417 dc->gl.vertexArrayState->init(dc->gl.gl.maxVertexAttribs); 418 dc->gl.currentFrameBuffer = NULL; 419 dc->mHasGraphics = true; 420 421 ALOGV("%p initGLThread end", rsc); 422 rsc->setWatchdogGL(NULL, 0, NULL); 423 return true; 424} 425 426 427bool rsdGLSetInternalSurface(const Context *rsc, RsNativeWindow sur) { 428 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 429 430 EGLBoolean ret; 431 if (dc->gl.egl.surface != NULL) { 432 rsc->setWatchdogGL("eglMakeCurrent", __LINE__, __FILE__); 433 ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surfaceDefault, 434 dc->gl.egl.surfaceDefault, dc->gl.egl.context); 435 checkEglError("eglMakeCurrent", ret); 436 437 rsc->setWatchdogGL("eglDestroySurface", __LINE__, __FILE__); 438 ret = eglDestroySurface(dc->gl.egl.display, dc->gl.egl.surface); 439 checkEglError("eglDestroySurface", ret); 440 441 dc->gl.egl.surface = NULL; 442 } 443 444 if (dc->gl.currentWndSurface != NULL) { 445 dc->gl.currentWndSurface->decStrong(NULL); 446 } 447 448 dc->gl.currentWndSurface = (ANativeWindow *)sur; 449 if (dc->gl.currentWndSurface != NULL) { 450 dc->gl.currentWndSurface->incStrong(NULL); 451 452 rsc->setWatchdogGL("eglCreateWindowSurface", __LINE__, __FILE__); 453 dc->gl.egl.surface = eglCreateWindowSurface(dc->gl.egl.display, dc->gl.egl.config, 454 dc->gl.currentWndSurface, NULL); 455 checkEglError("eglCreateWindowSurface"); 456 if (dc->gl.egl.surface == EGL_NO_SURFACE) { 457 ALOGE("eglCreateWindowSurface returned EGL_NO_SURFACE"); 458 } 459 460 rsc->setWatchdogGL("eglMakeCurrent", __LINE__, __FILE__); 461 ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surface, 462 dc->gl.egl.surface, dc->gl.egl.context); 463 checkEglError("eglMakeCurrent", ret); 464 } 465 rsc->setWatchdogGL(NULL, 0, NULL); 466 return true; 467} 468 469bool rsdGLSetSurface(const Context *rsc, uint32_t w, uint32_t h, RsNativeWindow sur) { 470 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 471 472 if (dc->gl.wndSurface != NULL) { 473 dc->gl.wndSurface->decStrong(NULL); 474 dc->gl.wndSurface = NULL; 475 } 476 if(w && h) { 477 // WAR: Some drivers fail to handle 0 size surfaces correctly. Use the 478 // pbuffer to avoid this pitfall. 479 dc->gl.wndSurface = (ANativeWindow *)sur; 480 if (dc->gl.wndSurface != NULL) { 481 dc->gl.wndSurface->incStrong(NULL); 482 } 483 } 484 485 return rsdGLSetInternalSurface(rsc, sur); 486} 487 488void rsdGLSwap(const android::renderscript::Context *rsc) { 489 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 490 RSD_CALL_GL(eglSwapBuffers, dc->gl.egl.display, dc->gl.egl.surface); 491} 492 493void rsdGLSetPriority(const Context *rsc, int32_t priority) { 494 if (priority > 0) { 495 // Mark context as low priority. 496 ALOGV("low pri"); 497 } else { 498 ALOGV("normal pri"); 499 } 500} 501 502void rsdGLCheckError(const android::renderscript::Context *rsc, 503 const char *msg, bool isFatal) { 504 GLenum err = glGetError(); 505 if (err != GL_NO_ERROR) { 506 char buf[1024]; 507 snprintf(buf, sizeof(buf), "GL Error = 0x%08x, from: %s", err, msg); 508 509 if (isFatal) { 510 rsc->setError(RS_ERROR_FATAL_DRIVER, buf); 511 } else { 512 switch (err) { 513 case GL_OUT_OF_MEMORY: 514 rsc->setError(RS_ERROR_OUT_OF_MEMORY, buf); 515 break; 516 default: 517 rsc->setError(RS_ERROR_DRIVER, buf); 518 break; 519 } 520 } 521 522 ALOGE("%p, %s", rsc, buf); 523 } 524 525} 526 527void rsdGLClearColor(const android::renderscript::Context *rsc, 528 float r, float g, float b, float a) { 529 RSD_CALL_GL(glClearColor, r, g, b, a); 530 RSD_CALL_GL(glClear, GL_COLOR_BUFFER_BIT); 531} 532 533void rsdGLClearDepth(const android::renderscript::Context *rsc, float v) { 534 RSD_CALL_GL(glClearDepthf, v); 535 RSD_CALL_GL(glClear, GL_DEPTH_BUFFER_BIT); 536} 537 538void rsdGLFinish(const android::renderscript::Context *rsc) { 539 RSD_CALL_GL(glFinish); 540} 541 542void rsdGLDrawQuadTexCoords(const android::renderscript::Context *rsc, 543 float x1, float y1, float z1, float u1, float v1, 544 float x2, float y2, float z2, float u2, float v2, 545 float x3, float y3, float z3, float u3, float v3, 546 float x4, float y4, float z4, float u4, float v4) { 547 548 float vtx[] = {x1,y1,z1, x2,y2,z2, x3,y3,z3, x4,y4,z4}; 549 const float tex[] = {u1,v1, u2,v2, u3,v3, u4,v4}; 550 551 RsdVertexArray::Attrib attribs[2]; 552 attribs[0].set(GL_FLOAT, 3, 12, false, (uint32_t)vtx, "ATTRIB_position"); 553 attribs[1].set(GL_FLOAT, 2, 8, false, (uint32_t)tex, "ATTRIB_texture0"); 554 555 RsdVertexArray va(attribs, 2); 556 va.setup(rsc); 557 558 RSD_CALL_GL(glDrawArrays, GL_TRIANGLE_FAN, 0, 4); 559} 560