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/Surface.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 if (numConfigs) {
271 EGLConfig* const configs = new EGLConfig[numConfigs];
272
273 rsc->setWatchdogGL("eglChooseConfig", __LINE__, __FILE__);
274 ret = eglChooseConfig(dc->gl.egl.display,
275 configAttribs, configs, numConfigs, &n);
276 if (!ret || !n) {
277 checkEglError("eglChooseConfig", ret);
278 ALOGE("%p, couldn't find an EGLConfig matching the screen format\n", rsc);
279 }
280
281 // The first config is guaranteed to over-satisfy the constraints
282 dc->gl.egl.config = configs[0];
283
284 // go through the list and skip configs that over-satisfy our needs
285 for (int i=0 ; i<n ; i++) {
286 if (rsc->mUserSurfaceConfig.alphaMin <= 0) {
287 EGLint alphaSize;
288 eglGetConfigAttrib(dc->gl.egl.display,
289 configs[i], EGL_ALPHA_SIZE, &alphaSize);
290 if (alphaSize > 0) {
291 continue;
292 }
293 }
294
295 if (rsc->mUserSurfaceConfig.depthMin <= 0) {
296 EGLint depthSize;
297 eglGetConfigAttrib(dc->gl.egl.display,
298 configs[i], EGL_DEPTH_SIZE, &depthSize);
299 if (depthSize > 0) {
300 continue;
301 }
302 }
303
304 // Found one!
305 dc->gl.egl.config = configs[i];
306 break;
307 }
308
309 delete [] configs;
310 }
311
312 //if (props.mLogVisual) {
313 if (0) {
314 printEGLConfiguration(dc->gl.egl.display, dc->gl.egl.config);
315 }
316 //}
317
318 rsc->setWatchdogGL("eglCreateContext", __LINE__, __FILE__);
319 dc->gl.egl.context = eglCreateContext(dc->gl.egl.display, dc->gl.egl.config,
320 EGL_NO_CONTEXT, context_attribs2);
321 checkEglError("eglCreateContext");
322 if (dc->gl.egl.context == EGL_NO_CONTEXT) {
323 ALOGE("%p, eglCreateContext returned EGL_NO_CONTEXT", rsc);
324 rsc->setWatchdogGL(NULL, 0, NULL);
325 return false;
326 }
327 gGLContextCount++;
328
329 // Create a BufferQueue with a fake consumer
330 sp<BufferQueue> bq = new BufferQueue();
331 bq->consumerConnect(new DummyConsumer());
332 sp<Surface> stc(new Surface(static_cast<sp<IGraphicBufferProducer> >(bq)));
333
334 dc->gl.egl.surfaceDefault = eglCreateWindowSurface(dc->gl.egl.display, dc->gl.egl.config,
335 static_cast<ANativeWindow*>(stc.get()),
336 NULL);
337
338 checkEglError("eglCreateWindowSurface");
339 if (dc->gl.egl.surfaceDefault == EGL_NO_SURFACE) {
340 ALOGE("eglCreateWindowSurface returned EGL_NO_SURFACE");
341 rsdGLShutdown(rsc);
342 rsc->setWatchdogGL(NULL, 0, NULL);
343 return false;
344 }
345
346 rsc->setWatchdogGL("eglMakeCurrent", __LINE__, __FILE__);
347 ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surfaceDefault,
348 dc->gl.egl.surfaceDefault, dc->gl.egl.context);
349 if (ret == EGL_FALSE) {
350 ALOGE("eglMakeCurrent returned EGL_FALSE");
351 checkEglError("eglMakeCurrent", ret);
352 rsdGLShutdown(rsc);
353 rsc->setWatchdogGL(NULL, 0, NULL);
354 return false;
355 }
356
357 dc->gl.gl.version = glGetString(GL_VERSION);
358 dc->gl.gl.vendor = glGetString(GL_VENDOR);
359 dc->gl.gl.renderer = glGetString(GL_RENDERER);
360 dc->gl.gl.extensions = glGetString(GL_EXTENSIONS);
361
362 //ALOGV("EGL Version %i %i", mEGL.mMajorVersion, mEGL.mMinorVersion);
363 //ALOGV("GL Version %s", mGL.mVersion);
364 //ALOGV("GL Vendor %s", mGL.mVendor);
365 //ALOGV("GL Renderer %s", mGL.mRenderer);
366 //ALOGV("GL Extensions %s", mGL.mExtensions);
367
368 const char *verptr = NULL;
369 if (strlen((const char *)dc->gl.gl.version) > 9) {
370 if (!memcmp(dc->gl.gl.version, "OpenGL ES-CM", 12)) {
371 verptr = (const char *)dc->gl.gl.version + 12;
372 }
373 if (!memcmp(dc->gl.gl.version, "OpenGL ES ", 10)) {
374 verptr = (const char *)dc->gl.gl.version + 9;
375 }
376 }
377
378 if (!verptr) {
379 ALOGE("Error, OpenGL ES Lite not supported");
380 rsdGLShutdown(rsc);
381 rsc->setWatchdogGL(NULL, 0, NULL);
382 return false;
383 } else {
384 sscanf(verptr, " %i.%i", &dc->gl.gl.majorVersion, &dc->gl.gl.minorVersion);
385 }
386
387 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &dc->gl.gl.maxVertexAttribs);
388 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &dc->gl.gl.maxVertexUniformVectors);
389 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &dc->gl.gl.maxVertexTextureUnits);
390
391 glGetIntegerv(GL_MAX_VARYING_VECTORS, &dc->gl.gl.maxVaryingVectors);
392 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &dc->gl.gl.maxTextureImageUnits);
393
394 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &dc->gl.gl.maxFragmentTextureImageUnits);
395 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &dc->gl.gl.maxFragmentUniformVectors);
396
397 dc->gl.gl.OES_texture_npot = NULL != strstr((const char *)dc->gl.gl.extensions,
398 "GL_OES_texture_npot");
399 dc->gl.gl.IMG_texture_npot = NULL != strstr((const char *)dc->gl.gl.extensions,
400 "GL_IMG_texture_npot");
401 dc->gl.gl.NV_texture_npot_2D_mipmap = NULL != strstr((const char *)dc->gl.gl.extensions,
402 "GL_NV_texture_npot_2D_mipmap");
403 dc->gl.gl.EXT_texture_max_aniso = 1.0f;
404 bool hasAniso = NULL != strstr((const char *)dc->gl.gl.extensions,
405 "GL_EXT_texture_filter_anisotropic");
406 if (hasAniso) {
407 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &dc->gl.gl.EXT_texture_max_aniso);
408 }
409
410 if (0) {
411 DumpDebug(dc);
412 }
413
414 dc->gl.shaderCache = new RsdShaderCache();
415 dc->gl.vertexArrayState = new RsdVertexArrayState();
416 dc->gl.vertexArrayState->init(dc->gl.gl.maxVertexAttribs);
417 dc->gl.currentFrameBuffer = NULL;
418 dc->mHasGraphics = true;
419
420 ALOGV("%p initGLThread end", rsc);
421 rsc->setWatchdogGL(NULL, 0, NULL);
422 return true;
423 }
424
425
rsdGLSetInternalSurface(const Context * rsc,RsNativeWindow sur)426 bool rsdGLSetInternalSurface(const Context *rsc, RsNativeWindow sur) {
427 RsdHal *dc = (RsdHal *)rsc->mHal.drv;
428
429 EGLBoolean ret;
430 if (dc->gl.egl.surface != NULL) {
431 rsc->setWatchdogGL("eglMakeCurrent", __LINE__, __FILE__);
432 ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surfaceDefault,
433 dc->gl.egl.surfaceDefault, dc->gl.egl.context);
434 checkEglError("eglMakeCurrent", ret);
435
436 rsc->setWatchdogGL("eglDestroySurface", __LINE__, __FILE__);
437 ret = eglDestroySurface(dc->gl.egl.display, dc->gl.egl.surface);
438 checkEglError("eglDestroySurface", ret);
439
440 dc->gl.egl.surface = NULL;
441 }
442
443 if (dc->gl.currentWndSurface != NULL) {
444 dc->gl.currentWndSurface->decStrong(NULL);
445 }
446
447 dc->gl.currentWndSurface = (ANativeWindow *)sur;
448 if (dc->gl.currentWndSurface != NULL) {
449 dc->gl.currentWndSurface->incStrong(NULL);
450
451 rsc->setWatchdogGL("eglCreateWindowSurface", __LINE__, __FILE__);
452 dc->gl.egl.surface = eglCreateWindowSurface(dc->gl.egl.display, dc->gl.egl.config,
453 dc->gl.currentWndSurface, NULL);
454 checkEglError("eglCreateWindowSurface");
455 if (dc->gl.egl.surface == EGL_NO_SURFACE) {
456 ALOGE("eglCreateWindowSurface returned EGL_NO_SURFACE");
457 }
458
459 rsc->setWatchdogGL("eglMakeCurrent", __LINE__, __FILE__);
460 ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surface,
461 dc->gl.egl.surface, dc->gl.egl.context);
462 checkEglError("eglMakeCurrent", ret);
463 }
464 rsc->setWatchdogGL(NULL, 0, NULL);
465 return true;
466 }
467
rsdGLSetSurface(const Context * rsc,uint32_t w,uint32_t h,RsNativeWindow sur)468 bool rsdGLSetSurface(const Context *rsc, uint32_t w, uint32_t h, RsNativeWindow sur) {
469 RsdHal *dc = (RsdHal *)rsc->mHal.drv;
470
471 if (dc->gl.wndSurface != NULL) {
472 dc->gl.wndSurface->decStrong(NULL);
473 dc->gl.wndSurface = NULL;
474 }
475 if(w && h) {
476 // WAR: Some drivers fail to handle 0 size surfaces correctly. Use the
477 // pbuffer to avoid this pitfall.
478 dc->gl.wndSurface = (ANativeWindow *)sur;
479 if (dc->gl.wndSurface != NULL) {
480 dc->gl.wndSurface->incStrong(NULL);
481 }
482 }
483
484 return rsdGLSetInternalSurface(rsc, sur);
485 }
486
rsdGLSwap(const android::renderscript::Context * rsc)487 void rsdGLSwap(const android::renderscript::Context *rsc) {
488 RsdHal *dc = (RsdHal *)rsc->mHal.drv;
489 RSD_CALL_GL(eglSwapBuffers, dc->gl.egl.display, dc->gl.egl.surface);
490 }
491
rsdGLSetPriority(const Context * rsc,int32_t priority)492 void rsdGLSetPriority(const Context *rsc, int32_t priority) {
493 if (priority > 0) {
494 // Mark context as low priority.
495 ALOGV("low pri");
496 } else {
497 ALOGV("normal pri");
498 }
499 }
500
rsdGLCheckError(const android::renderscript::Context * rsc,const char * msg,bool isFatal)501 void rsdGLCheckError(const android::renderscript::Context *rsc,
502 const char *msg, bool isFatal) {
503 GLenum err = glGetError();
504 if (err != GL_NO_ERROR) {
505 char buf[1024];
506 snprintf(buf, sizeof(buf), "GL Error = 0x%08x, from: %s", err, msg);
507
508 if (isFatal) {
509 rsc->setError(RS_ERROR_FATAL_DRIVER, buf);
510 } else {
511 switch (err) {
512 case GL_OUT_OF_MEMORY:
513 rsc->setError(RS_ERROR_OUT_OF_MEMORY, buf);
514 break;
515 default:
516 rsc->setError(RS_ERROR_DRIVER, buf);
517 break;
518 }
519 }
520
521 ALOGE("%p, %s", rsc, buf);
522 }
523
524 }
525
rsdGLClearColor(const android::renderscript::Context * rsc,float r,float g,float b,float a)526 void rsdGLClearColor(const android::renderscript::Context *rsc,
527 float r, float g, float b, float a) {
528 RSD_CALL_GL(glClearColor, r, g, b, a);
529 RSD_CALL_GL(glClear, GL_COLOR_BUFFER_BIT);
530 }
531
rsdGLClearDepth(const android::renderscript::Context * rsc,float v)532 void rsdGLClearDepth(const android::renderscript::Context *rsc, float v) {
533 RSD_CALL_GL(glClearDepthf, v);
534 RSD_CALL_GL(glClear, GL_DEPTH_BUFFER_BIT);
535 }
536
rsdGLFinish(const android::renderscript::Context * rsc)537 void rsdGLFinish(const android::renderscript::Context *rsc) {
538 RSD_CALL_GL(glFinish);
539 }
540
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)541 void rsdGLDrawQuadTexCoords(const android::renderscript::Context *rsc,
542 float x1, float y1, float z1, float u1, float v1,
543 float x2, float y2, float z2, float u2, float v2,
544 float x3, float y3, float z3, float u3, float v3,
545 float x4, float y4, float z4, float u4, float v4) {
546
547 float vtx[] = {x1,y1,z1, x2,y2,z2, x3,y3,z3, x4,y4,z4};
548 const float tex[] = {u1,v1, u2,v2, u3,v3, u4,v4};
549
550 RsdVertexArray::Attrib attribs[2];
551 attribs[0].set(GL_FLOAT, 3, 12, false, (uint32_t)vtx, "ATTRIB_position");
552 attribs[1].set(GL_FLOAT, 2, 8, false, (uint32_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