这个问题,实际上北京老猫在它的 FireMonkey 移动开发中已经给出了一个解决方案,要求修改 FMX.Canvas.GPU,因为实际遇到了这个情况,所以我就特意跟踪了下,我觉得真正的问题应该是出在 Vivo,或者是高通提供的驱动上的问题。FMX.Canvas.GPU 实际上低层调用的是 FMX.Context.GLES 中的 MaxTextureSize 方法来获取图片的最大允许大小, Delphi 的实现代码为:
class function TCustomContextOpenGL.MaxTextureSize: Integer; begin CreateSharedContext; glGetIntegerv(GL_MAX_TEXTURE_SIZE, @Result); end;
单步执行的结果,发现 Result 的值返回的是 0。那么尝试看 GL_MAX_TEXTURE_SIZE 啥时候会返回 0 呢?
我们在这块以微软的文档来看看 glGetIntergerv 到底怎么说的:
GL_MAX_TEXTURE_SIZE
The params parameter returns one value: the maximum width or height of any texture image (without borders). See glTexImage1D and glTexImage2D.
好吧,让我们看 glTextImage1D 和 glTextImage2D,找到下面一段话:
GL_INVALID_VALUE
width or height was less than zero or greater than 2 + GL_MAX_TEXTURE_SIZE, or it could not be represented as 2ⁿ + 2(border) for some integer value of n.
好吧,我是没看它官方说啥时候应该返回0。不过在 Stackflow 的一篇问答里,它说了一句话:
maxTextureSize stores the size limit for decoded image such as 4096×4096, 8192×8192 . Remember to run this piece of code in the MainThread or you will get Zero.
简单说来,就是说这段代码如果不是运行在主线程,将会返回 0。因为着急,我直接处理了 MaxTextureSize 函数,直接返回了一个固定值 8192(一般是8192/16384的居多:数据来源)。但这个问题的原因到底是什么,我现在因为没有测试环境,无法确定问题的真正原因,如果那位朋友有这款手机,欢迎联系我大家一起测试下问题到底出在那里,会不会是某些特定情况下,OpenGL 的上下文真的创建在了后台线程造成的。
另外,这个问题仅存在于 Android 中,iOS 中暂时至少我是没有遇到。
附:Android 调试日志,可以看到 eglCreateWindowSurface 调用失败造成后面 GL_MAX_TEXTURE_SIZE 为 0 造成此问题。
08-11 13:02:40.284: I/Adreno-EGL(22385): Reconstruct Branch: NOTHING 08-11 13:02:40.294: D/StatusBarColorManager(3760): SystemUI|notifyStatusBarColorInfo: iconColor = -1, bgColor = ffededed, bgVisible = true 08-11 13:02:40.324: E/BufferQueueProducer(249): [com.jlgoldenbay.ddb/com.embarcadero.firemonkey.FMXNativeActivity] connect(P): BufferQueue has been abandoned 08-11 13:02:40.324: E/libEGL(22385): eglCreateWindowSurface: native_window_api_connect (win=0xb96fa290) failed (0xffffffed) (already connected to another API?) 08-11 13:02:40.324: E/libEGL(22385): eglCreateWindowSurface:417 error 3003 (EGL_BAD_ALLOC) 08-11 13:02:40.324: W/Adreno-EGL(22385): <qeglDrvAPI_eglMakeCurrent:2963>: EGL_BAD_MATCH 08-11 13:02:40.324: E/libEGL(22385): eglMakeCurrent:792 error 3009 (EGL_BAD_MATCH) 08-11 13:02:40.324: E/libEGL(22385): eglDestroySurface:587 error 300d (EGL_BAD_SURFACE) 08-11 13:02:40.324: I/info(22385): FMX: 顶顶棒: [Context Exception]: Cannot create OpenGL context for 'eglMakeCurrent'. 08-11 13:02:40.444: E/libEGL(22385): call to OpenGL ES API with no current context (logged once per thread) 08-11 13:02:40.444: E/libEGL(22385): validate_display:255 error 3008 (EGL_BAD_DISPLAY) 08-11 13:02:40.444: E/libEGL(22385): validate_display:255 error 3008 (EGL_BAD_DISPLAY) 08-11 13:02:40.444: E/BufferQueueProducer(249): [com.jlgoldenbay.ddb/com.embarcadero.firemonkey.FMXNativeActivity] connect(P): BufferQueue has been abandoned 08-11 13:02:40.444: E/libEGL(22385): eglCreateWindowSurface: native_window_api_connect (win=0xb96fa290) failed (0xffffffed) (already connected to another API?) 08-11 13:02:40.444: E/libEGL(22385): eglCreateWindowSurface:417 error 3003 (EGL_BAD_ALLOC) 08-11 13:02:40.444: W/Adreno-EGL(22385): <qeglDrvAPI_eglMakeCurrent:2963>: EGL_BAD_MATCH 08-11 13:02:40.444: E/libEGL(22385): eglMakeCurrent:792 error 3009 (EGL_BAD_MATCH) 08-11 13:02:40.444: I/info(22385): FMX: 顶顶棒: [Context Exception]: Cannot create OpenGL context for 'CreateDummyContext'. 08-11 13:02:40.444: E/libEGL(22385): eglDestroySurface:587 error 300d (EGL_BAD_SURFACE) 08-11 13:02:40.444: E/BufferQueueProducer(249): [com.jlgoldenbay.ddb/com.embarcadero.firemonkey.FMXNativeActivity] connect(P): BufferQueue has been abandoned 08-11 13:02:40.444: E/libEGL(22385): eglCreateWindowSurface: native_window_api_connect (win=0xb96fa290) failed (0xffffffed) (already connected to another API?) 08-11 13:02:40.444: E/libEGL(22385): eglCreateWindowSurface:417 error 3003 (EGL_BAD_ALLOC) 08-11 13:02:40.454: W/Adreno-EGL(22385): <qeglDrvAPI_eglMakeCurrent:2963>: EGL_BAD_MATCH 08-11 13:02:40.454: E/libEGL(22385): eglMakeCurrent:792 error 3009 (EGL_BAD_MATCH) 08-11 13:02:40.454: E/libEGL(22385): eglDestroySurface:587 error 300d (EGL_BAD_SURFACE) 08-11 13:02:40.454: I/info(22385): FMX: 顶顶棒: [Context Exception]: Cannot create OpenGL context for 'eglMakeCurrent'. 08-11 13:02:40.484: E/libEGL(22385): validate_display:255 error 3008 (EGL_BAD_DISPLAY) 08-11 13:02:40.494: E/libEGL(22385): validate_display:255 error 3008 (EGL_BAD_DISPLAY) 08-11 13:02:40.494: E/libEGL(22385): validate_display:255 error 3008 (EGL_BAD_DISPLAY) 08-11 13:02:40.504: D/debug(22385): OpenGLES.GL_MAX_TEXTURE_SIZE:0 08-11 13:02:40.504: D/debug(22385): OpenGLES.GL_MAX_TEXTURE_SIZE:0