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
checkEglError(const char * op,EGLBoolean returnVal=EGL_TRUE)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
printEGLConfiguration(EGLDisplay dpy,EGLConfig config)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
DumpDebug(RsdHal * dc)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
rsdGLShutdown(const Context * rsc)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
getConfigData(const Context * rsc,EGLint * configAttribs,size_t configAttribsLen,uint32_t numSamples)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
rsdGLInit(const Context * rsc)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
rsdGLSetInternalSurface(const Context * rsc,RsNativeWindow sur)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
rsdGLSetSurface(const Context * rsc,uint32_t w,uint32_t h,RsNativeWindow sur)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
rsdGLSwap(const android::renderscript::Context * rsc)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
rsdGLSetPriority(const Context * rsc,int32_t priority)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
rsdGLCheckError(const android::renderscript::Context * rsc,const char * msg,bool isFatal)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
rsdGLClearColor(const android::renderscript::Context * rsc,float r,float g,float b,float a)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
rsdGLClearDepth(const android::renderscript::Context * rsc,float v)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
rsdGLFinish(const android::renderscript::Context * rsc)530 void rsdGLFinish(const android::renderscript::Context *rsc) {
531 RSD_CALL_GL(glFinish);
532 }
533
rsdGLDrawQuadTexCoords(const android::renderscript::Context * rsc,float x1,float y1,float z1,float u1,float v1,float x2,float y2,float z2,float u2,float v2,float x3,float y3,float z3,float u3,float v3,float x4,float y4,float z4,float u4,float v4)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