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
48 using namespace android;
49 using namespace android::renderscript;
50
51 static int32_t gGLContextCount = 0;
52
checkEglError(const char * op,EGLBoolean returnVal=EGL_TRUE)53 static 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
printEGLConfiguration(EGLDisplay dpy,EGLConfig config)88 static 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
DumpDebug(RsdHal * dc)136 static 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
rsdGLShutdown(const Context * rsc)154 void rsdGLShutdown(const Context *rsc) {
155 RsdHal *dc = (RsdHal *)rsc->mHal.drv;
156
157 rsdGLSetSurface(rsc, 0, 0, NULL);
158 dc->gl.shaderCache->cleanupAll();
159 delete dc->gl.shaderCache;
160 delete dc->gl.vertexArrayState;
161
162 if (dc->gl.egl.context != EGL_NO_CONTEXT) {
163 RSD_CALL_GL(eglMakeCurrent, dc->gl.egl.display,
164 EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
165 RSD_CALL_GL(eglDestroySurface, dc->gl.egl.display, dc->gl.egl.surfaceDefault);
166 if (dc->gl.egl.surface != EGL_NO_SURFACE) {
167 RSD_CALL_GL(eglDestroySurface, dc->gl.egl.display, dc->gl.egl.surface);
168 }
169 RSD_CALL_GL(eglDestroyContext, dc->gl.egl.display, dc->gl.egl.context);
170 checkEglError("eglDestroyContext");
171 }
172
173 gGLContextCount--;
174 if (!gGLContextCount) {
175 RSD_CALL_GL(eglTerminate, dc->gl.egl.display);
176 }
177 }
178
getConfigData(const Context * rsc,EGLint * configAttribs,size_t configAttribsLen,uint32_t numSamples)179 void getConfigData(const Context *rsc,
180 EGLint *configAttribs, size_t configAttribsLen,
181 uint32_t numSamples) {
182 memset(configAttribs, 0, configAttribsLen*sizeof(*configAttribs));
183
184 EGLint *configAttribsPtr = configAttribs;
185
186 configAttribsPtr[0] = EGL_SURFACE_TYPE;
187 configAttribsPtr[1] = EGL_WINDOW_BIT;
188 configAttribsPtr += 2;
189
190 configAttribsPtr[0] = EGL_RENDERABLE_TYPE;
191 configAttribsPtr[1] = EGL_OPENGL_ES2_BIT;
192 configAttribsPtr += 2;
193
194 configAttribsPtr[0] = EGL_RED_SIZE;
195 configAttribsPtr[1] = 8;
196 configAttribsPtr += 2;
197
198 configAttribsPtr[0] = EGL_GREEN_SIZE;
199 configAttribsPtr[1] = 8;
200 configAttribsPtr += 2;
201
202 configAttribsPtr[0] = EGL_BLUE_SIZE;
203 configAttribsPtr[1] = 8;
204 configAttribsPtr += 2;
205
206 if (rsc->mUserSurfaceConfig.alphaMin > 0) {
207 configAttribsPtr[0] = EGL_ALPHA_SIZE;
208 configAttribsPtr[1] = rsc->mUserSurfaceConfig.alphaMin;
209 configAttribsPtr += 2;
210 }
211
212 if (rsc->mUserSurfaceConfig.depthMin > 0) {
213 configAttribsPtr[0] = EGL_DEPTH_SIZE;
214 configAttribsPtr[1] = rsc->mUserSurfaceConfig.depthMin;
215 configAttribsPtr += 2;
216 }
217
218 if (rsc->mDev->mForceSW) {
219 configAttribsPtr[0] = EGL_CONFIG_CAVEAT;
220 configAttribsPtr[1] = EGL_SLOW_CONFIG;
221 configAttribsPtr += 2;
222 }
223
224 if (numSamples > 1) {
225 configAttribsPtr[0] = EGL_SAMPLE_BUFFERS;
226 configAttribsPtr[1] = 1;
227 configAttribsPtr[2] = EGL_SAMPLES;
228 configAttribsPtr[3] = numSamples;
229 configAttribsPtr += 4;
230 }
231
232 configAttribsPtr[0] = EGL_NONE;
233 rsAssert(configAttribsPtr < (configAttribs + configAttribsLen));
234 }
235
rsdGLInit(const Context * rsc)236 bool rsdGLInit(const Context *rsc) {
237 RsdHal *dc = (RsdHal *)rsc->mHal.drv;
238
239 dc->gl.egl.numConfigs = -1;
240
241 EGLint configAttribs[128];
242 EGLint context_attribs2[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
243
244 ALOGV("%p initEGL start", rsc);
245 rsc->setWatchdogGL("eglGetDisplay", __LINE__, __FILE__);
246 dc->gl.egl.display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
247 checkEglError("eglGetDisplay");
248
249 RSD_CALL_GL(eglInitialize, dc->gl.egl.display,
250 &dc->gl.egl.majorVersion, &dc->gl.egl.minorVersion);
251 checkEglError("eglInitialize");
252
253 EGLBoolean ret;
254
255 EGLint numConfigs = -1, n = 0;
256 rsc->setWatchdogGL("eglChooseConfig", __LINE__, __FILE__);
257
258 // Try minding a multisample config that matches the user request
259 uint32_t minSample = rsc->mUserSurfaceConfig.samplesMin;
260 uint32_t prefSample = rsc->mUserSurfaceConfig.samplesPref;
261 for (uint32_t sampleCount = prefSample; sampleCount >= minSample; sampleCount--) {
262 getConfigData(rsc, configAttribs, (sizeof(configAttribs) / sizeof(EGLint)), sampleCount);
263 ret = eglChooseConfig(dc->gl.egl.display, configAttribs, 0, 0, &numConfigs);
264 checkEglError("eglGetConfigs", ret);
265 if (numConfigs > 0) {
266 break;
267 }
268 }
269
270 eglSwapInterval(dc->gl.egl.display, 0);
271
272 if (numConfigs) {
273 EGLConfig* const configs = new EGLConfig[numConfigs];
274
275 rsc->setWatchdogGL("eglChooseConfig", __LINE__, __FILE__);
276 ret = eglChooseConfig(dc->gl.egl.display,
277 configAttribs, configs, numConfigs, &n);
278 if (!ret || !n) {
279 checkEglError("eglChooseConfig", ret);
280 ALOGE("%p, couldn't find an EGLConfig matching the screen format\n", rsc);
281 }
282
283 // The first config is guaranteed to over-satisfy the constraints
284 dc->gl.egl.config = configs[0];
285
286 // go through the list and skip configs that over-satisfy our needs
287 for (int i=0 ; i<n ; i++) {
288 if (rsc->mUserSurfaceConfig.alphaMin <= 0) {
289 EGLint alphaSize;
290 eglGetConfigAttrib(dc->gl.egl.display,
291 configs[i], EGL_ALPHA_SIZE, &alphaSize);
292 if (alphaSize > 0) {
293 continue;
294 }
295 }
296
297 if (rsc->mUserSurfaceConfig.depthMin <= 0) {
298 EGLint depthSize;
299 eglGetConfigAttrib(dc->gl.egl.display,
300 configs[i], EGL_DEPTH_SIZE, &depthSize);
301 if (depthSize > 0) {
302 continue;
303 }
304 }
305
306 // Found one!
307 dc->gl.egl.config = configs[i];
308 break;
309 }
310
311 delete [] configs;
312 }
313
314 //if (props.mLogVisual) {
315 if (0) {
316 printEGLConfiguration(dc->gl.egl.display, dc->gl.egl.config);
317 }
318 //}
319
320 rsc->setWatchdogGL("eglCreateContext", __LINE__, __FILE__);
321 dc->gl.egl.context = eglCreateContext(dc->gl.egl.display, dc->gl.egl.config,
322 EGL_NO_CONTEXT, context_attribs2);
323 checkEglError("eglCreateContext");
324 if (dc->gl.egl.context == EGL_NO_CONTEXT) {
325 ALOGE("%p, eglCreateContext returned EGL_NO_CONTEXT", rsc);
326 rsc->setWatchdogGL(NULL, 0, NULL);
327 return false;
328 }
329 gGLContextCount++;
330
331 // Create a BufferQueue with a fake consumer
332 sp<BufferQueue> bq = new BufferQueue();
333 bq->consumerConnect(new DummyConsumer());
334 sp<SurfaceTextureClient> stc(new SurfaceTextureClient(static_cast<sp<ISurfaceTexture> >(bq)));
335
336 dc->gl.egl.surfaceDefault = eglCreateWindowSurface(dc->gl.egl.display, dc->gl.egl.config,
337 static_cast<ANativeWindow*>(stc.get()),
338 NULL);
339
340 checkEglError("eglCreateWindowSurface");
341 if (dc->gl.egl.surfaceDefault == EGL_NO_SURFACE) {
342 ALOGE("eglCreateWindowSurface returned EGL_NO_SURFACE");
343 rsdGLShutdown(rsc);
344 rsc->setWatchdogGL(NULL, 0, NULL);
345 return false;
346 }
347
348 rsc->setWatchdogGL("eglMakeCurrent", __LINE__, __FILE__);
349 ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surfaceDefault,
350 dc->gl.egl.surfaceDefault, dc->gl.egl.context);
351 if (ret == EGL_FALSE) {
352 ALOGE("eglMakeCurrent returned EGL_FALSE");
353 checkEglError("eglMakeCurrent", ret);
354 rsdGLShutdown(rsc);
355 rsc->setWatchdogGL(NULL, 0, NULL);
356 return false;
357 }
358
359 dc->gl.gl.version = glGetString(GL_VERSION);
360 dc->gl.gl.vendor = glGetString(GL_VENDOR);
361 dc->gl.gl.renderer = glGetString(GL_RENDERER);
362 dc->gl.gl.extensions = glGetString(GL_EXTENSIONS);
363
364 //ALOGV("EGL Version %i %i", mEGL.mMajorVersion, mEGL.mMinorVersion);
365 //ALOGV("GL Version %s", mGL.mVersion);
366 //ALOGV("GL Vendor %s", mGL.mVendor);
367 //ALOGV("GL Renderer %s", mGL.mRenderer);
368 //ALOGV("GL Extensions %s", mGL.mExtensions);
369
370 const char *verptr = NULL;
371 if (strlen((const char *)dc->gl.gl.version) > 9) {
372 if (!memcmp(dc->gl.gl.version, "OpenGL ES-CM", 12)) {
373 verptr = (const char *)dc->gl.gl.version + 12;
374 }
375 if (!memcmp(dc->gl.gl.version, "OpenGL ES ", 10)) {
376 verptr = (const char *)dc->gl.gl.version + 9;
377 }
378 }
379
380 if (!verptr) {
381 ALOGE("Error, OpenGL ES Lite not supported");
382 rsdGLShutdown(rsc);
383 rsc->setWatchdogGL(NULL, 0, NULL);
384 return false;
385 } else {
386 sscanf(verptr, " %i.%i", &dc->gl.gl.majorVersion, &dc->gl.gl.minorVersion);
387 }
388
389 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &dc->gl.gl.maxVertexAttribs);
390 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &dc->gl.gl.maxVertexUniformVectors);
391 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &dc->gl.gl.maxVertexTextureUnits);
392
393 glGetIntegerv(GL_MAX_VARYING_VECTORS, &dc->gl.gl.maxVaryingVectors);
394 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &dc->gl.gl.maxTextureImageUnits);
395
396 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &dc->gl.gl.maxFragmentTextureImageUnits);
397 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &dc->gl.gl.maxFragmentUniformVectors);
398
399 dc->gl.gl.OES_texture_npot = NULL != strstr((const char *)dc->gl.gl.extensions,
400 "GL_OES_texture_npot");
401 dc->gl.gl.IMG_texture_npot = NULL != strstr((const char *)dc->gl.gl.extensions,
402 "GL_IMG_texture_npot");
403 dc->gl.gl.NV_texture_npot_2D_mipmap = NULL != strstr((const char *)dc->gl.gl.extensions,
404 "GL_NV_texture_npot_2D_mipmap");
405 dc->gl.gl.EXT_texture_max_aniso = 1.0f;
406 bool hasAniso = NULL != strstr((const char *)dc->gl.gl.extensions,
407 "GL_EXT_texture_filter_anisotropic");
408 if (hasAniso) {
409 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &dc->gl.gl.EXT_texture_max_aniso);
410 }
411
412 if (0) {
413 DumpDebug(dc);
414 }
415
416 dc->gl.shaderCache = new RsdShaderCache();
417 dc->gl.vertexArrayState = new RsdVertexArrayState();
418 dc->gl.vertexArrayState->init(dc->gl.gl.maxVertexAttribs);
419 dc->gl.currentFrameBuffer = NULL;
420 dc->mHasGraphics = true;
421
422 ALOGV("%p initGLThread end", rsc);
423 rsc->setWatchdogGL(NULL, 0, NULL);
424 return true;
425 }
426
427
rsdGLSetInternalSurface(const Context * rsc,RsNativeWindow sur)428 bool rsdGLSetInternalSurface(const Context *rsc, RsNativeWindow sur) {
429 RsdHal *dc = (RsdHal *)rsc->mHal.drv;
430
431 EGLBoolean ret;
432 if (dc->gl.egl.surface != NULL) {
433 rsc->setWatchdogGL("eglMakeCurrent", __LINE__, __FILE__);
434 ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surfaceDefault,
435 dc->gl.egl.surfaceDefault, dc->gl.egl.context);
436 checkEglError("eglMakeCurrent", ret);
437
438 rsc->setWatchdogGL("eglDestroySurface", __LINE__, __FILE__);
439 ret = eglDestroySurface(dc->gl.egl.display, dc->gl.egl.surface);
440 checkEglError("eglDestroySurface", ret);
441
442 dc->gl.egl.surface = NULL;
443 }
444
445 if (dc->gl.currentWndSurface != NULL) {
446 dc->gl.currentWndSurface->decStrong(NULL);
447 }
448
449 dc->gl.currentWndSurface = (ANativeWindow *)sur;
450 if (dc->gl.currentWndSurface != NULL) {
451 dc->gl.currentWndSurface->incStrong(NULL);
452
453 rsc->setWatchdogGL("eglCreateWindowSurface", __LINE__, __FILE__);
454 dc->gl.egl.surface = eglCreateWindowSurface(dc->gl.egl.display, dc->gl.egl.config,
455 dc->gl.currentWndSurface, NULL);
456 checkEglError("eglCreateWindowSurface");
457 if (dc->gl.egl.surface == EGL_NO_SURFACE) {
458 ALOGE("eglCreateWindowSurface returned EGL_NO_SURFACE");
459 }
460
461 rsc->setWatchdogGL("eglMakeCurrent", __LINE__, __FILE__);
462 ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surface,
463 dc->gl.egl.surface, dc->gl.egl.context);
464 checkEglError("eglMakeCurrent", ret);
465 }
466 rsc->setWatchdogGL(NULL, 0, NULL);
467 return true;
468 }
469
rsdGLSetSurface(const Context * rsc,uint32_t w,uint32_t h,RsNativeWindow sur)470 bool rsdGLSetSurface(const Context *rsc, uint32_t w, uint32_t h, RsNativeWindow sur) {
471 RsdHal *dc = (RsdHal *)rsc->mHal.drv;
472
473 if (dc->gl.wndSurface != NULL) {
474 dc->gl.wndSurface->decStrong(NULL);
475 dc->gl.wndSurface = NULL;
476 }
477 if(w && h) {
478 // WAR: Some drivers fail to handle 0 size surfaces correctly. Use the
479 // pbuffer to avoid this pitfall.
480 dc->gl.wndSurface = (ANativeWindow *)sur;
481 if (dc->gl.wndSurface != NULL) {
482 dc->gl.wndSurface->incStrong(NULL);
483 }
484 }
485
486 return rsdGLSetInternalSurface(rsc, sur);
487 }
488
rsdGLSwap(const android::renderscript::Context * rsc)489 void rsdGLSwap(const android::renderscript::Context *rsc) {
490 RsdHal *dc = (RsdHal *)rsc->mHal.drv;
491 RSD_CALL_GL(eglSwapBuffers, dc->gl.egl.display, dc->gl.egl.surface);
492 }
493
rsdGLSetPriority(const Context * rsc,int32_t priority)494 void rsdGLSetPriority(const Context *rsc, int32_t priority) {
495 if (priority > 0) {
496 // Mark context as low priority.
497 ALOGV("low pri");
498 } else {
499 ALOGV("normal pri");
500 }
501 }
502
rsdGLCheckError(const android::renderscript::Context * rsc,const char * msg,bool isFatal)503 void rsdGLCheckError(const android::renderscript::Context *rsc,
504 const char *msg, bool isFatal) {
505 GLenum err = glGetError();
506 if (err != GL_NO_ERROR) {
507 char buf[1024];
508 snprintf(buf, sizeof(buf), "GL Error = 0x%08x, from: %s", err, msg);
509
510 if (isFatal) {
511 rsc->setError(RS_ERROR_FATAL_DRIVER, buf);
512 } else {
513 switch (err) {
514 case GL_OUT_OF_MEMORY:
515 rsc->setError(RS_ERROR_OUT_OF_MEMORY, buf);
516 break;
517 default:
518 rsc->setError(RS_ERROR_DRIVER, buf);
519 break;
520 }
521 }
522
523 ALOGE("%p, %s", rsc, buf);
524 }
525
526 }
527
rsdGLClearColor(const android::renderscript::Context * rsc,float r,float g,float b,float a)528 void rsdGLClearColor(const android::renderscript::Context *rsc,
529 float r, float g, float b, float a) {
530 RSD_CALL_GL(glClearColor, r, g, b, a);
531 RSD_CALL_GL(glClear, GL_COLOR_BUFFER_BIT);
532 }
533
rsdGLClearDepth(const android::renderscript::Context * rsc,float v)534 void rsdGLClearDepth(const android::renderscript::Context *rsc, float v) {
535 RSD_CALL_GL(glClearDepthf, v);
536 RSD_CALL_GL(glClear, GL_DEPTH_BUFFER_BIT);
537 }
538
rsdGLFinish(const android::renderscript::Context * rsc)539 void rsdGLFinish(const android::renderscript::Context *rsc) {
540 RSD_CALL_GL(glFinish);
541 }
542
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)543 void rsdGLDrawQuadTexCoords(const android::renderscript::Context *rsc,
544 float x1, float y1, float z1, float u1, float v1,
545 float x2, float y2, float z2, float u2, float v2,
546 float x3, float y3, float z3, float u3, float v3,
547 float x4, float y4, float z4, float u4, float v4) {
548
549 float vtx[] = {x1,y1,z1, x2,y2,z2, x3,y3,z3, x4,y4,z4};
550 const float tex[] = {u1,v1, u2,v2, u3,v3, u4,v4};
551
552 RsdVertexArray::Attrib attribs[2];
553 attribs[0].set(GL_FLOAT, 3, 12, false, (uint32_t)vtx, "ATTRIB_position");
554 attribs[1].set(GL_FLOAT, 2, 8, false, (uint32_t)tex, "ATTRIB_texture0");
555
556 RsdVertexArray va(attribs, 2);
557 va.setup(rsc);
558
559 RSD_CALL_GL(glDrawArrays, GL_TRIANGLE_FAN, 0, 4);
560 }
561